/prefixed-elements.d.ts Secret
Created
March 27, 2023 19:25
Using prefixed elements in ".d.ts" files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is a list of all harmony components as we use them so they can be registered to global namespace. | |
import * as preact from 'preact' | |
import HarmonyElement from '@harmony/enablers/components'; | |
import type button from "@harmony/enablers/components/button/button"; | |
import type checkbox from "@harmony/enablers/components/checkbox/checkbox"; | |
import type details from "@harmony/enablers/components/details/details"; | |
import type icon from "@harmony/enablers/components/icon/icon"; | |
import type layout from "@harmony/enablers/components/layout/layout"; | |
import type navHeader from "@harmony/enablers/components/nav-header/nav-header"; | |
import type option from "@harmony/enablers/components/option/option"; | |
import type progressRing from "@harmony/enablers/components/progress-ring/progress-ring"; | |
import type select from "@harmony/enablers/components/select/select"; | |
import type radio from "@harmony/enablers/components/radio/radio"; | |
import type radioGroup from "@harmony/enablers/components/radio-group/radio-group"; | |
import type tab from "@harmony/enablers/components/tab/tab"; | |
import type tabs from "@harmony/enablers/components/tabs/tabs"; | |
import type tabPanel from "@harmony/enablers/components/tab-panel/tab-panel"; | |
import type textField from "@harmony/enablers/components/text-field/text-field.js"; | |
import type textArea from "@harmony/enablers/components/text-area/text-area.js"; | |
import type tooltip from "@harmony/enablers/components/tooltip/tooltip.js"; | |
interface HarmonyElements { | |
'he-button': CustomElement<typeof button>; | |
'he-checkbox': CustomElement<typeof checkbox>; | |
'he-details': CustomElement<typeof details>; | |
'he-layout': CustomElement<typeof layout>; | |
'he-icon': CustomElement<typeof icon>; | |
'he-nav-header': CustomElement<typeof navHeader>; | |
'he-option': CustomElement<typeof option>; | |
'he-progress-ring': CustomElement<typeof progressRing>; | |
'he-radio-group': CustomElement<typeof radioGroup> | |
'he-radio': CustomElement<typeof radio> | |
'he-select': CustomElement<typeof select>; | |
'he-tab': CustomElement<typeof tab>; | |
'he-tab-panel': CustomElement<typeof tabPanel>; | |
'he-tabs': CustomElement<typeof tabs>; | |
'he-text-area': CustomElement<typeof textArea>; | |
'he-text-field': CustomElement<typeof textField>; | |
'he-tooltip': CustomElement<typeof tooltip>; | |
} | |
// Hacky way to get `onHeChange` to turn into `onhe-change` | |
type ToEvent<T extends string> = T extends `on-${infer Suffix}` ? `on${Suffix}` : T; | |
type CamelToKebabCase<S extends string> = | |
S extends `${infer Start}${infer Rest}` | |
? Start extends Uppercase<Start> | |
? `-${Lowercase<Start>}${CamelToKebabCase<Rest>}` | |
: `${Start}${CamelToKebabCase<Rest>}` | |
: S | |
type ReactEvents<TEvents extends Record<string, Event>> = { | |
[P in keyof TEvents as P extends string | |
? ToEvent<CamelToKebabCase<P>> | |
: never | |
]?: (e: TEvents[P]) => void; | |
}; | |
type CustomElement<T extends typeof HarmonyElement> = | |
Partial< | |
| InstanceType<T> | |
| { children: any } | |
| ReactEvents<T["reactEvents"]> | |
| preact.createElement.JSX.HTMLAttributes | |
>; | |
// https://www.typescriptlang.org/play?jsx=0#code/C4TwDgpgBAhgJnACgJwgMwJYA8A8AVAaQhABoo8V1soItgIA7OAZymeGQwYHMA+KALzkiIGnUYs2HLtygB+KAAMAJAG8KqTFgC+awsW2KoALigMIANwjIA3AFgAUI9pgA9smBQu9ZGhgBjaABRABsIAFtGYFZVRygoAHIACwgAWgAjAFdgYFcGBNNQSFc0KFCIqPsHbUdHIuhKLQg4csiGaJxG6lp6JlZ2Th5BKAAiEf4hWId4+IBtES8GKABrYhKysLbo2FZ4JE1sHBEyFVUunQB9RV4AXVNWqOZ54hvHbSq68GgAQTAwB-arCE52aAI6Ixgf3GQA | |
type addPrefix<TKey, TPrefix extends string> = TKey extends string ? `${TPrefix}${TKey}` : never; | |
/** | |
* If scopes accept additional prefixes, we can add these to the extends below. | |
* @example | |
* interface IntrinsicElements extends HarmonyElements, PrefixedElements<"app"> | |
*/ | |
type PrefixedElements<Prefix extends string = ""> = { | |
[Key in keyof HarmonyElements as addPrefix<Key, `${Prefix}_`>]: HarmonyElements[Key] | |
}; | |
declare global { | |
namespace preact.createElement.JSX { | |
interface IntrinsicElements extends HarmonyElements, PrefixedElements<"app"> {} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment