Skip to content

Instantly share code, notes, and snippets.

@MSFTKonnor
Created March 27, 2023 19:25
Show Gist options
  • Save MSFTKonnor/a28d93cd88240a24cba884d5a77be9e8 to your computer and use it in GitHub Desktop.
Save MSFTKonnor/a28d93cd88240a24cba884d5a77be9e8 to your computer and use it in GitHub Desktop.
Using prefixed elements in ".d.ts" files
// 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