From cfea170bab7722078352242abb125b31dc823d45 Mon Sep 17 00:00:00 2001 From: NullVoxPopuli Date: Sun, 3 Jul 2022 12:21:41 -0400 Subject: [PATCH] feat: automatic glint registration via importing /glint --- README.md | 28 ++++++++----------- ember-statechart-component/src/glint.ts | 37 +++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index be6a1f81..6e5e31f4 100644 --- a/README.md +++ b/README.md @@ -159,26 +159,22 @@ Usage: ### Glint -Having type checking with these state machines requires a wrapper function. +Having type checking with these state machines can be done automatically +after importing the `/glint` file in your `types//glint-registry.d.ts`. ```ts -// app/components/my-component.ts -import { createMachine } from 'xstate'; -import { asComponent } from 'ember-statechart-component/glint'; - -export const machine = createMachine(/* ... */); - -export default asComponent(machine); -``` -or, if you want 0 runtime cost there is a more verbose, type-only option: -```ts -// app/components/my-component.ts -import { createMachine } from 'xstate'; -import type { MachineComponent } from 'ember-statechart-component/glint'; +import "@glint/environment-ember-loose"; +import "@glint/environment-ember-loose/native-integration"; +import "ember-page-title/glint"; -export const machine = createMachine(/* ... */); +// This import extends the type of `StateMachine` to be glint-compatible +import 'ember-statechart-component/glint'; -export default machine as unknown as MachineComponent; +declare module "@glint/environment-ember-loose/registry" { + export default interface Registry { + // How to define globals from external addons + } +} ``` ### API diff --git a/ember-statechart-component/src/glint.ts b/ember-statechart-component/src/glint.ts index 3e9cb5fe..56ed5adb 100644 --- a/ember-statechart-component/src/glint.ts +++ b/ember-statechart-component/src/glint.ts @@ -2,13 +2,20 @@ import type { ComponentLike } from '@glint/template'; import type { AnyStateMachine, + BaseActionObject, ContextFrom, EventFrom, + EventObject, Interpreter, MachineConfig, + NoInfer, + ResolveTypegenMeta, + ServiceMap, StateFrom, StateMachine, StateSchema, + TypegenDisabled, + Typestate, } from 'xstate'; type StateSchemaFrom = T extends StateMachine ? U : StateSchema; @@ -28,6 +35,36 @@ export type MachineComponent = ComponentLike<{ }; }>; +declare module 'xstate' { + // We need to + // eslint-disable-next-line @typescript-eslint/no-empty-interface + export interface StateMachine< + TContext, + TStateSchema extends StateSchema, + TEvent extends EventObject, + TTypestate extends Typestate = { value: any; context: TContext }, + TAction extends BaseActionObject = BaseActionObject, + TServiceMap extends ServiceMap = ServiceMap, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + TResolvedTypesMeta = ResolveTypegenMeta, TAction, TServiceMap> + > extends ComponentLike<{ + Args: { + config?: MachineConfig; + context?: TContext; + state?: Interpreter['state']; + }; + Blocks: { + default: [ + Interpreter['state'], + Interpreter['send'], + Interpreter['onTransition'] + ]; + }; + }> { + // Intentionally empty as we're changing StateMachine to extend from ComponentLike + } +} + export function asComponent(machine: T): MachineComponent { return machine as unknown as MachineComponent; }