@seahax/elemental 0.4.2 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -14
- package/dist/{store.js → createStore.js} +3 -3
- package/dist/createStore.js.map +1 -0
- package/dist/{component.d.ts → defineComponent.d.ts} +11 -7
- package/dist/defineComponent.js +57 -0
- package/dist/defineComponent.js.map +1 -0
- package/dist/{router.d.ts → getRouter.d.ts} +3 -2
- package/dist/getRouter.js +33 -0
- package/dist/getRouter.js.map +1 -0
- package/dist/hooks/useAsync.d.ts +11 -0
- package/dist/hooks/{loading.js → useAsync.js} +5 -5
- package/dist/hooks/useAsync.js.map +1 -0
- package/dist/hooks/{attributes.d.ts → useAttributes.d.ts} +1 -1
- package/dist/hooks/useAttributes.js +37 -0
- package/dist/hooks/useAttributes.js.map +1 -0
- package/dist/hooks/useChildEffect.js +24 -0
- package/dist/hooks/useChildEffect.js.map +1 -0
- package/dist/hooks/useDisconnect.d.ts +2 -0
- package/dist/hooks/useDisconnect.js +9 -0
- package/dist/hooks/useDisconnect.js.map +1 -0
- package/dist/hooks/useDocument.d.ts +3 -0
- package/dist/hooks/useDocument.js +9 -0
- package/dist/hooks/useDocument.js.map +1 -0
- package/dist/hooks/useEffect.d.ts +3 -0
- package/dist/hooks/useEffect.js +17 -0
- package/dist/hooks/useEffect.js.map +1 -0
- package/dist/hooks/useElementInternals.d.ts +2 -0
- package/dist/hooks/useElementInternals.js +9 -0
- package/dist/hooks/useElementInternals.js.map +1 -0
- package/dist/hooks/useForm.d.ts +9 -0
- package/dist/hooks/useForm.js +23 -0
- package/dist/hooks/useForm.js.map +1 -0
- package/dist/hooks/{host.d.ts → useHost.d.ts} +1 -1
- package/dist/hooks/useHost.js +9 -0
- package/dist/hooks/useHost.js.map +1 -0
- package/dist/hooks/useInternalController.d.ts +3 -0
- package/dist/hooks/useInternalController.js +11 -0
- package/dist/hooks/useInternalController.js.map +1 -0
- package/dist/hooks/useParent.d.ts +3 -0
- package/dist/hooks/useParent.js +9 -0
- package/dist/hooks/useParent.js.map +1 -0
- package/dist/hooks/{ref.d.ts → useRef.d.ts} +1 -2
- package/dist/hooks/useRef.js +9 -0
- package/dist/hooks/useRef.js.map +1 -0
- package/dist/hooks/{route.d.ts → useRoute.d.ts} +3 -3
- package/dist/hooks/{route.js → useRoute.js} +6 -6
- package/dist/hooks/useRoute.js.map +1 -0
- package/dist/hooks/{store.d.ts → useStore.d.ts} +2 -2
- package/dist/hooks/{store.js → useStore.js} +4 -4
- package/dist/hooks/useStore.js.map +1 -0
- package/dist/html.d.ts +1 -1
- package/dist/html.js.map +1 -1
- package/dist/index.d.ts +15 -11
- package/dist/index.js +17 -13
- package/dist/internal/constants.d.ts +1 -0
- package/dist/internal/constants.js +6 -0
- package/dist/internal/constants.js.map +1 -0
- package/dist/internal/controllers.d.ts +2 -0
- package/dist/internal/controllers.js +6 -0
- package/dist/internal/controllers.js.map +1 -0
- package/dist/internal/{callbacks.js → createCallbacks.js} +2 -2
- package/dist/internal/createCallbacks.js.map +1 -0
- package/dist/internal/createController.d.ts +33 -0
- package/dist/internal/createController.js +73 -0
- package/dist/internal/createController.js.map +1 -0
- package/dist/internal/getOrInsert.d.ts +4 -0
- package/dist/internal/getOrInsert.js +10 -0
- package/dist/internal/getOrInsert.js.map +1 -0
- package/package.json +7 -3
- package/dist/component.js +0 -34
- package/dist/component.js.map +0 -1
- package/dist/hooks/attributes.js +0 -25
- package/dist/hooks/attributes.js.map +0 -1
- package/dist/hooks/child-effect.js +0 -14
- package/dist/hooks/child-effect.js.map +0 -1
- package/dist/hooks/context.d.ts +0 -3
- package/dist/hooks/context.js +0 -11
- package/dist/hooks/context.js.map +0 -1
- package/dist/hooks/effect.d.ts +0 -9
- package/dist/hooks/effect.js +0 -20
- package/dist/hooks/effect.js.map +0 -1
- package/dist/hooks/host.js +0 -9
- package/dist/hooks/host.js.map +0 -1
- package/dist/hooks/loading.d.ts +0 -11
- package/dist/hooks/loading.js.map +0 -1
- package/dist/hooks/ref.js +0 -19
- package/dist/hooks/ref.js.map +0 -1
- package/dist/hooks/route.js.map +0 -1
- package/dist/hooks/store.js.map +0 -1
- package/dist/internal/callbacks.js.map +0 -1
- package/dist/internal/context.d.ts +0 -13
- package/dist/internal/context.js +0 -32
- package/dist/internal/context.js.map +0 -1
- package/dist/router.js +0 -35
- package/dist/router.js.map +0 -1
- package/dist/store.js.map +0 -1
- /package/dist/{store.d.ts → createStore.d.ts} +0 -0
- /package/dist/hooks/{child-effect.d.ts → useChildEffect.d.ts} +0 -0
- /package/dist/internal/{callbacks.d.ts → createCallbacks.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useParent.js","names":[],"sources":["../../src/hooks/useParent.ts"],"sourcesContent":["import { useInternalController } from './useInternalController.ts';\nimport type { ReadonlyRef } from './useRef.ts';\n\n/** Use a reference (reactive state) bound to the parent node. */\nexport function useParent(): ReadonlyRef<ParentNode | null> {\n return useInternalController().refParent;\n}\n"],"mappings":";;AAIA,SAAgB,IAA4C;AAC1D,QAAO,GAAuB,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { $$ref } from '../internal/constants.ts';
|
|
1
2
|
export interface Ref<T> extends ReadonlyRef<T> {
|
|
2
3
|
value: T;
|
|
3
4
|
}
|
|
@@ -9,7 +10,5 @@ export interface ReadonlyRef<T> {
|
|
|
9
10
|
export type RefValues<T> = T extends readonly any[] ? {
|
|
10
11
|
[K in keyof T]: T[K] extends ReadonlyRef<infer V> ? V : never;
|
|
11
12
|
} : never;
|
|
12
|
-
declare const $$ref: unique symbol;
|
|
13
13
|
/** Use a reference (reactive state) value. */
|
|
14
14
|
export declare function useRef<T>(initialValue: T, onChange?: (value: T) => void): Ref<T>;
|
|
15
|
-
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRef.js","names":[],"sources":["../../src/hooks/useRef.ts"],"sourcesContent":["import type { $$ref } from '../internal/constants.ts';\nimport { useInternalController } from './useInternalController.ts';\n\nexport interface Ref<T> extends ReadonlyRef<T> {\n value: T;\n}\n\nexport interface ReadonlyRef<T> {\n /** @hidden */\n [$$ref]: unknown;\n readonly value: T;\n}\n\nexport type RefValues<T> = T extends readonly any[]\n ? { [K in keyof T]: T[K] extends ReadonlyRef<infer V> ? V : never }\n : never;\n\n/** Use a reference (reactive state) value. */\nexport function useRef<T>(initialValue: T, onChange?: (value: T) => void): Ref<T> {\n return useInternalController().createRef(initialValue, onChange);\n}\n"],"mappings":";;AAkBA,SAAgB,EAAU,GAAiB,GAAuC;AAChF,QAAO,GAAuB,CAAC,UAAU,GAAc,EAAS"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { type Ref } from './
|
|
1
|
+
import { type Ref } from './useRef.ts';
|
|
2
2
|
export interface RouteOptions {
|
|
3
3
|
readonly match?: 'prefix' | 'exact' | RegExp;
|
|
4
4
|
readonly source?: 'pathname' | 'hash';
|
|
5
5
|
}
|
|
6
|
-
export type
|
|
6
|
+
export type RouteMatch = readonly [string, ...string[]] & {
|
|
7
7
|
readonly groups: Record<string, string>;
|
|
8
8
|
};
|
|
9
9
|
/** Use a reference (reactive state) bound to route matching. */
|
|
10
|
-
export declare function useRoute(path: string | readonly string[], { match, source }?: RouteOptions): Ref<
|
|
10
|
+
export declare function useRoute(path: string | readonly string[], { match, source }?: RouteOptions): Ref<RouteMatch | null>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { useRef as e } from "./
|
|
2
|
-
import { useEffect as t } from "./
|
|
3
|
-
import { getRouter as n } from "../
|
|
4
|
-
import { useStore as r } from "./
|
|
5
|
-
//#region src/hooks/
|
|
1
|
+
import { useRef as e } from "./useRef.js";
|
|
2
|
+
import { useEffect as t } from "./useEffect.js";
|
|
3
|
+
import { getRouter as n } from "../getRouter.js";
|
|
4
|
+
import { useStore as r } from "./useStore.js";
|
|
5
|
+
//#region src/hooks/useRoute.ts
|
|
6
6
|
function i(i, { match: a = "prefix", source: o = "pathname" } = {}) {
|
|
7
7
|
let s = a === "exact" ? /^$/u : a === "prefix" ? /^.*$/u : a, c = Array.isArray(i) ? i : [i], l = r(n(), (e) => e[o]), u = e(d(l.value));
|
|
8
8
|
return t([l], (e) => {
|
|
@@ -16,4 +16,4 @@ function i(i, { match: a = "prefix", source: o = "pathname" } = {}) {
|
|
|
16
16
|
//#endregion
|
|
17
17
|
export { i as useRoute };
|
|
18
18
|
|
|
19
|
-
//# sourceMappingURL=
|
|
19
|
+
//# sourceMappingURL=useRoute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRoute.js","names":[],"sources":["../../src/hooks/useRoute.ts"],"sourcesContent":["import { getRouter } from '../getRouter.ts';\nimport { useEffect } from './useEffect.ts';\nimport { type Ref, useRef } from './useRef.ts';\nimport { useStore } from './useStore.ts';\n\nexport interface RouteOptions {\n readonly match?: 'prefix' | 'exact' | RegExp;\n readonly source?: 'pathname' | 'hash';\n}\n\nexport type RouteMatch = readonly [string, ...string[]] & { readonly groups: Record<string, string> };\n\n/** Use a reference (reactive state) bound to route matching. */\nexport function useRoute(\n path: string | readonly string[],\n { match = 'prefix', source = 'pathname' }: RouteOptions = {},\n): Ref<RouteMatch | null> {\n const matchRx = match === 'exact' ? /^$/u : match === 'prefix' ? /^.*$/u : match;\n const paths = Array.isArray(path) ? (path as readonly string[]) : [path as string];\n const refRoute = useStore(getRouter(), (state) => state[source]);\n const refMatch = useRef<RouteMatch | null>(getMatch(refRoute.value));\n\n useEffect([refRoute], (route) => {\n refMatch.value = getMatch(route);\n });\n\n return refMatch;\n\n function getMatch(route: string): RouteMatch | null {\n const prefix = paths.find((path) => route.endsWith(path)) ?? null;\n if (prefix == null) return null;\n route = route.slice(prefix.length);\n return route.match(matchRx) as RouteMatch | null;\n }\n}\n"],"mappings":";;;;;AAaA,SAAgB,EACd,GACA,EAAE,WAAQ,UAAU,YAAS,eAA6B,EAAE,EACpC;CACxB,IAAM,IAAU,MAAU,UAAU,QAAQ,MAAU,WAAW,UAAU,GACrE,IAAQ,MAAM,QAAQ,EAAK,GAAI,IAA6B,CAAC,EAAe,EAC5E,IAAW,EAAS,GAAW,GAAG,MAAU,EAAM,GAAQ,EAC1D,IAAW,EAA0B,EAAS,EAAS,MAAM,CAAC;AAMpE,QAJA,EAAU,CAAC,EAAS,GAAG,MAAU;AAC/B,IAAS,QAAQ,EAAS,EAAM;GAChC,EAEK;CAEP,SAAS,EAAS,GAAkC;EAClD,IAAM,IAAS,EAAM,MAAM,MAAS,EAAM,SAAS,EAAK,CAAC,IAAI;AAG7D,SAFI,KAAU,OAAa,QAC3B,IAAQ,EAAM,MAAM,EAAO,OAAO,EAC3B,EAAM,MAAM,EAAQ"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Store } from '../
|
|
2
|
-
import { type ReadonlyRef, type Ref } from './
|
|
1
|
+
import type { Store } from '../createStore.ts';
|
|
2
|
+
import { type ReadonlyRef, type Ref } from './useRef.ts';
|
|
3
3
|
/** Use a reference (reactive state) bound to a (shared) store. */
|
|
4
4
|
export declare function useStore<TState, TValue = TState>(store: Store<TState>, select: (state: TState) => TValue, mutate: (store: Store<TState>, value: TValue) => void): Ref<TValue>;
|
|
5
5
|
export declare function useStore<TState, TValue = TState>(store: Store<TState>, select?: (state: TState) => TValue): ReadonlyRef<TValue>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useRef as e } from "./
|
|
2
|
-
import { useEffect as t } from "./
|
|
3
|
-
//#region src/hooks/
|
|
1
|
+
import { useRef as e } from "./useRef.js";
|
|
2
|
+
import { useEffect as t } from "./useEffect.js";
|
|
3
|
+
//#region src/hooks/useStore.ts
|
|
4
4
|
function n(n, r = (e) => e, i) {
|
|
5
5
|
let a = e(r(n.state), i && ((e) => i(n, e)));
|
|
6
6
|
return t([], () => n.subscribe((e) => a.value = r(e))), a;
|
|
@@ -8,4 +8,4 @@ function n(n, r = (e) => e, i) {
|
|
|
8
8
|
//#endregion
|
|
9
9
|
export { n as useStore };
|
|
10
10
|
|
|
11
|
-
//# sourceMappingURL=
|
|
11
|
+
//# sourceMappingURL=useStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStore.js","names":[],"sources":["../../src/hooks/useStore.ts"],"sourcesContent":["import type { Store } from '../createStore.ts';\nimport { useEffect } from './useEffect.ts';\nimport { type ReadonlyRef, type Ref, useRef } from './useRef.ts';\n\n/** Use a reference (reactive state) bound to a (shared) store. */\nexport function useStore<TState, TValue = TState>(\n store: Store<TState>,\n select: (state: TState) => TValue,\n mutate: (store: Store<TState>, value: TValue) => void,\n): Ref<TValue>;\nexport function useStore<TState, TValue = TState>(\n store: Store<TState>,\n select?: (state: TState) => TValue,\n): ReadonlyRef<TValue>;\nexport function useStore<TState, TValue = TState>(\n store: Store<TState>,\n select: (state: TState) => TValue = (state) => state as unknown as TValue,\n mutate?: (store: Store<TState>, value: TValue) => void,\n): Ref<TValue> {\n const ref = useRef(select(store.state), mutate && ((value) => mutate(store, value)));\n useEffect([], () => store.subscribe((state) => (ref.value = select(state))));\n return ref;\n}\n"],"mappings":";;;AAcA,SAAgB,EACd,GACA,KAAqC,MAAU,GAC/C,GACa;CACb,IAAM,IAAM,EAAO,EAAO,EAAM,MAAM,EAAE,OAAY,MAAU,EAAO,GAAO,EAAM,EAAE;AAEpF,QADA,EAAU,EAAE,QAAQ,EAAM,WAAW,MAAW,EAAI,QAAQ,EAAO,EAAM,CAAE,CAAC,EACrE"}
|
package/dist/html.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ type ElementType<TElement> = TElement extends string ? TElement extends keyof Ta
|
|
|
7
7
|
type ElementProps<TElement> = {
|
|
8
8
|
readonly [P in keyof TElement & string as TElement[P] extends ((...args: any[]) => any) | null | undefined ? never : IfEquals<Record<P, TElement[P]>, Pick<TElement, P>, `:${P}`, never>]?: TElement[P];
|
|
9
9
|
};
|
|
10
|
-
type ElementAttrs<TElement> = TElement extends string | CustomElementConstructor | Element ?
|
|
10
|
+
type ElementAttrs<TElement> = TElement extends string | CustomElementConstructor | Element ? Readonly<Record<`${Alpha}${string}`, AttrValue>> : {};
|
|
11
11
|
export type HtmlConfig<TElement> = ElementAttrs<TElement> & ElementProps<ElementType<TElement>>;
|
|
12
12
|
export type HtmlConfigWithKey<TElement> = {
|
|
13
13
|
readonly [DATA_KEY]: string;
|
package/dist/html.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html.js","names":[],"sources":["../src/html.ts"],"sourcesContent":["// prettier-ignore\ntype Alpha = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z';\ntype ChildValue = Node | HtmlDeferredElement | string | number | bigint | false | null | undefined;\ntype AttrValue = string | number | bigint | boolean | null | undefined;\ntype TagMap = HTMLElementTagNameMap & HTMLElementDeprecatedTagNameMap;\n\ntype IfEquals<T, U, Y = unknown, N = never> =\n (<G>() => G extends T ? 1 : 2) extends <G>() => G extends U ? 1 : 2 ? Y : N;\n\ntype ElementType<TElement> = TElement extends string\n ? TElement extends keyof TagMap\n ? TagMap[TElement]\n : HTMLElement\n : TElement extends CustomElementConstructor\n ? InstanceType<TElement>\n : TElement extends Element | Document | ShadowRoot\n ? TElement\n : never;\n\ntype ElementProps<TElement> = {\n readonly [P in keyof TElement & string as TElement[P] extends ((...args: any[]) => any) | null | undefined\n ? never\n : IfEquals<Record<P, TElement[P]>, Pick<TElement, P>, `:${P}`, never>]?: TElement[P];\n};\n\ntype ElementAttrs<TElement> = TElement extends string | CustomElementConstructor | Element\n ?
|
|
1
|
+
{"version":3,"file":"html.js","names":[],"sources":["../src/html.ts"],"sourcesContent":["// prettier-ignore\ntype Alpha = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z';\ntype ChildValue = Node | HtmlDeferredElement | string | number | bigint | false | null | undefined;\ntype AttrValue = string | number | bigint | boolean | null | undefined;\ntype TagMap = HTMLElementTagNameMap & HTMLElementDeprecatedTagNameMap;\n\ntype IfEquals<T, U, Y = unknown, N = never> =\n (<G>() => G extends T ? 1 : 2) extends <G>() => G extends U ? 1 : 2 ? Y : N;\n\ntype ElementType<TElement> = TElement extends string\n ? TElement extends keyof TagMap\n ? TagMap[TElement]\n : HTMLElement\n : TElement extends CustomElementConstructor\n ? InstanceType<TElement>\n : TElement extends Element | Document | ShadowRoot\n ? TElement\n : never;\n\ntype ElementProps<TElement> = {\n readonly [P in keyof TElement & string as TElement[P] extends ((...args: any[]) => any) | null | undefined\n ? never\n : IfEquals<Record<P, TElement[P]>, Pick<TElement, P>, `:${P}`, never>]?: TElement[P];\n};\n\ntype ElementAttrs<TElement> = TElement extends string | CustomElementConstructor | Element\n ? Readonly<Record<`${Alpha}${string}`, AttrValue>>\n : {};\n\nexport type HtmlConfig<TElement> = ElementAttrs<TElement> & ElementProps<ElementType<TElement>>;\nexport type HtmlConfigWithKey<TElement> = { readonly [DATA_KEY]: string } & HtmlConfig<TElement>;\n\nexport interface HtmlDeferredElement<TElement extends HTMLElement = HTMLElement> {\n readonly tag: string;\n readonly config: { readonly [DATA_KEY]: string } & HtmlConfig<TElement>;\n readonly children: readonly ChildValue[] | undefined;\n toElement: () => TElement;\n}\n\nconst DATA_KEY = 'data-key';\n\n/**\n * Create a deferred HTML element with a key.\n *\n * Final element creation is deferred until the element is used as a child,\n * when it can be determined if a new element should be created, or an existing\n * element with the same key and tag-name should be updated.\n */\nexport function html<const TElement extends keyof TagMap | (string & {}) | CustomElementConstructor>(\n el: TElement,\n config: HtmlConfigWithKey<TElement>,\n children?: readonly ChildValue[],\n): HtmlDeferredElement<ElementType<TElement>>;\n\n/**\n * Create or update an HTML element.\n */\nexport function html<\n TElement extends keyof TagMap | (string & {}) | CustomElementConstructor | Element | Document | ShadowRoot,\n>(el: TElement, attrs?: HtmlConfig<TElement>, children?: readonly ChildValue[]): ElementType<NoInfer<TElement>>;\nexport function html<\n TElement extends keyof TagMap | (string & {}) | CustomElementConstructor | Element | Document | ShadowRoot,\n>(el: TElement, children?: readonly ChildValue[]): ElementType<TElement>;\n\nexport function html(\n el: string | CustomElementConstructor | Element | Document | ShadowRoot,\n attrsOrChildren: readonly ChildValue[] | Readonly<Record<string, any>> = {},\n children: readonly ChildValue[] = [],\n): Node | HtmlDeferredElement {\n if (typeof el === 'function') {\n let name = customElements.getName(el);\n\n if (name == null) {\n name = `ce-${crypto.randomUUID()}`;\n customElements.define(name, el);\n }\n\n el = name;\n }\n\n let attrs: Readonly<Record<string, any>>;\n [attrs, children] = Array.isArray(attrsOrChildren)\n ? [{}, attrsOrChildren as readonly ChildValue[]]\n : [attrsOrChildren as Readonly<Record<string, any>>, children];\n\n if (typeof el === 'string') {\n return DATA_KEY in attrs\n ? {\n tag: el,\n config: attrs as HtmlDeferredElement['config'],\n children,\n toElement: () => html(document.createElement(el), attrs, children),\n }\n : html(document.createElement(el), attrs, children);\n }\n\n if ('setAttribute' in el) {\n for (const [name, rawValue] of Object.entries(attrs)) {\n if (rawValue === undefined || name.startsWith(':')) continue;\n\n if (rawValue === null || rawValue === false) {\n if (el.hasAttribute(name)) el.removeAttribute(name);\n } else {\n const value = rawValue == true ? '' : String(rawValue);\n if (el.getAttribute(name) !== value) el.setAttribute(name, value);\n }\n }\n }\n\n for (const [rawName, value] of Object.entries(attrs)) {\n if (value === undefined || !rawName.startsWith(':')) continue;\n const name = rawName.slice(1);\n if (Reflect.get(el, name) !== value) Reflect.set(el, name, value);\n }\n\n let keyElements: Map<string, Element> | undefined;\n\n el.replaceChildren(\n ...children\n .filter((child) => child != null && child !== false)\n .map((child) => {\n if (typeof child !== 'object') return document.createTextNode(String(child));\n if (child instanceof Node) return child;\n\n keyElements ??= new Map(\n [...el.children].flatMap((child) => {\n const key = child.getAttribute(DATA_KEY);\n return key == null ? [] : [[key, child] as const];\n }),\n );\n\n const key = child.config[DATA_KEY];\n const reused = keyElements.get(key);\n\n if (reused && reused.tagName.toLowerCase() === child.tag) {\n keyElements.delete(key);\n return html(reused, child.config, child.children);\n }\n\n return child.toElement();\n }),\n );\n\n return el;\n}\n"],"mappings":";AAuCA,IAAM,IAAW;AAyBjB,SAAgB,EACd,GACA,IAAyE,EAAE,EAC3E,IAAkC,EAAE,EACR;AAC5B,KAAI,OAAO,KAAO,YAAY;EAC5B,IAAI,IAAO,eAAe,QAAQ,EAAG;AAOrC,EALI,MACF,IAAO,MAAM,OAAO,YAAY,IAChC,eAAe,OAAO,GAAM,EAAG,GAGjC,IAAK;;CAGP,IAAI;AAKJ,KAJA,CAAC,GAAO,KAAY,MAAM,QAAQ,EAAgB,GAC9C,CAAC,EAAE,EAAE,EAAyC,GAC9C,CAAC,GAAkD,EAAS,EAE5D,OAAO,KAAO,SAChB,QAAO,KAAY,IACf;EACE,KAAK;EACL,QAAQ;EACR;EACA,iBAAiB,EAAK,SAAS,cAAc,EAAG,EAAE,GAAO,EAAS;EACnE,GACD,EAAK,SAAS,cAAc,EAAG,EAAE,GAAO,EAAS;AAGvD,KAAI,kBAAkB,GACpB;OAAK,IAAM,CAAC,GAAM,MAAa,OAAO,QAAQ,EAAM,CAC9C,aAAa,KAAA,KAAa,EAAK,WAAW,IAAI,EAElD,KAAI,MAAa,QAAQ,MAAa,IAChC,EAAG,aAAa,EAAK,IAAE,EAAG,gBAAgB,EAAK;OAC9C;GACL,IAAM,IAAQ,KAAY,IAAO,KAAK,OAAO,EAAS;AACtD,GAAI,EAAG,aAAa,EAAK,KAAK,KAAO,EAAG,aAAa,GAAM,EAAM;;;AAKvE,MAAK,IAAM,CAAC,GAAS,MAAU,OAAO,QAAQ,EAAM,EAAE;AACpD,MAAI,MAAU,KAAA,KAAa,CAAC,EAAQ,WAAW,IAAI,CAAE;EACrD,IAAM,IAAO,EAAQ,MAAM,EAAE;AAC7B,EAAI,QAAQ,IAAI,GAAI,EAAK,KAAK,KAAO,QAAQ,IAAI,GAAI,GAAM,EAAM;;CAGnE,IAAI;AA4BJ,QA1BA,EAAG,gBACD,GAAG,EACA,QAAQ,MAAU,KAAS,QAAQ,MAAU,GAAM,CACnD,KAAK,MAAU;AACd,MAAI,OAAO,KAAU,SAAU,QAAO,SAAS,eAAe,OAAO,EAAM,CAAC;AAC5E,MAAI,aAAiB,KAAM,QAAO;AAElC,QAAgB,IAAI,IAClB,CAAC,GAAG,EAAG,SAAS,CAAC,SAAS,MAAU;GAClC,IAAM,IAAM,EAAM,aAAa,EAAS;AACxC,UAAO,KAAO,OAAO,EAAE,GAAG,CAAC,CAAC,GAAK,EAAM,CAAU;IACjD,CACH;EAED,IAAM,IAAM,EAAM,OAAO,IACnB,IAAS,EAAY,IAAI,EAAI;AAOnC,SALI,KAAU,EAAO,QAAQ,aAAa,KAAK,EAAM,OACnD,EAAY,OAAO,EAAI,EAChB,EAAK,GAAQ,EAAM,QAAQ,EAAM,SAAS,IAG5C,EAAM,WAAW;GACxB,CACL,EAEM"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './hooks/
|
|
4
|
-
export * from './hooks/
|
|
5
|
-
export * from './hooks/
|
|
6
|
-
export * from './hooks/
|
|
7
|
-
export * from './hooks/
|
|
8
|
-
export * from './hooks/
|
|
9
|
-
export * from './hooks/
|
|
1
|
+
export * from './createStore.ts';
|
|
2
|
+
export * from './defineComponent.ts';
|
|
3
|
+
export * from './hooks/useAsync.ts';
|
|
4
|
+
export * from './hooks/useAttributes.ts';
|
|
5
|
+
export * from './hooks/useChildEffect.ts';
|
|
6
|
+
export * from './hooks/useDisconnect.ts';
|
|
7
|
+
export * from './hooks/useDocument.ts';
|
|
8
|
+
export * from './hooks/useEffect.ts';
|
|
9
|
+
export * from './hooks/useElementInternals.ts';
|
|
10
|
+
export * from './hooks/useForm.ts';
|
|
11
|
+
export * from './hooks/useHost.ts';
|
|
12
|
+
export * from './hooks/useParent.ts';
|
|
13
|
+
export * from './hooks/useRef.ts';
|
|
14
|
+
export * from './hooks/useRoute.ts';
|
|
15
|
+
export * from './hooks/useStore.ts';
|
|
10
16
|
export * from './html.ts';
|
|
11
17
|
export { html as h } from './html.ts';
|
|
12
|
-
export * from './router.ts';
|
|
13
|
-
export * from './store.ts';
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
|
|
1
|
+
import { createStore as e } from "./createStore.js";
|
|
2
|
+
import { useRef as t } from "./hooks/useRef.js";
|
|
3
|
+
import { defineComponent as n } from "./defineComponent.js";
|
|
4
|
+
import { useDisconnectCallback as r } from "./hooks/useDisconnect.js";
|
|
5
|
+
import { useEffect as i } from "./hooks/useEffect.js";
|
|
6
|
+
import { useAsync as a } from "./hooks/useAsync.js";
|
|
7
|
+
import { useHost as o } from "./hooks/useHost.js";
|
|
8
|
+
import { useAttributes as s } from "./hooks/useAttributes.js";
|
|
9
|
+
import { useChildEffect as c } from "./hooks/useChildEffect.js";
|
|
10
|
+
import { useDocument as l } from "./hooks/useDocument.js";
|
|
11
|
+
import { useElementInternals as u } from "./hooks/useElementInternals.js";
|
|
12
|
+
import { useForm as d, useFormDisabled as f, useFormResetCallback as p, useFormRestoreCallback as m } from "./hooks/useForm.js";
|
|
13
|
+
import { useParent as h } from "./hooks/useParent.js";
|
|
14
|
+
import { useStore as g } from "./hooks/useStore.js";
|
|
15
|
+
import { useRoute as _ } from "./hooks/useRoute.js";
|
|
16
|
+
import { html as v } from "./html.js";
|
|
17
|
+
export { e as createStore, n as defineComponent, v as h, v as html, a as useAsync, s as useAttributes, c as useChildEffect, r as useDisconnectCallback, l as useDocument, i as useEffect, u as useElementInternals, d as useForm, f as useFormDisabled, p as useFormResetCallback, m as useFormRestoreCallback, o as useHost, h as useParent, t as useRef, _ as useRoute, g as useStore };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const $$ref: unique symbol;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","names":[],"sources":["../../src/internal/constants.ts"],"sourcesContent":["export const $$ref = Symbol();\n"],"mappings":";AAAA,IAAa,IAAQ,QAAQ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controllers.js","names":[],"sources":["../../src/internal/controllers.ts"],"sourcesContent":["import type { Controller } from './createController.ts';\n\nexport const controllers: Controller[] = [];\n"],"mappings":";AAEA,IAAa,IAA4B,EAAE"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region src/internal/
|
|
1
|
+
//#region src/internal/createCallbacks.ts
|
|
2
2
|
function e() {
|
|
3
3
|
let e = /* @__PURE__ */ new Set(), t = {
|
|
4
4
|
push: (t) => (e.add(t), () => e.delete(t)),
|
|
@@ -27,4 +27,4 @@ function e() {
|
|
|
27
27
|
//#endregion
|
|
28
28
|
export { e as createCallbacks };
|
|
29
29
|
|
|
30
|
-
//# sourceMappingURL=
|
|
30
|
+
//# sourceMappingURL=createCallbacks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createCallbacks.js","names":[],"sources":["../../src/internal/createCallbacks.ts"],"sourcesContent":["export interface Callbacks<TArgs extends unknown[] = []> {\n readonly push: (callback: (...args: TArgs) => void) => () => void;\n readonly run: (...args: TArgs) => void;\n readonly runAndClear: (...args: TArgs) => void;\n readonly clear: () => void;\n}\n\nexport function createCallbacks<TArgs extends unknown[] = []>(): Callbacks<TArgs> {\n const callbacks = new Set<(...args: TArgs) => void>();\n\n const self: Callbacks<TArgs> = {\n push: (callback) => {\n callbacks.add(callback);\n return () => callbacks.delete(callback);\n },\n run: (...args) => {\n const errors: unknown[] = [];\n const callbacksCopy = [...callbacks];\n\n for (const callback of callbacksCopy) {\n try {\n callback(...args);\n } catch (error: unknown) {\n errors.push(error);\n }\n }\n\n if (errors.length > 0) throw new AggregateError(errors);\n },\n runAndClear: (...args: TArgs) => {\n try {\n self.run(...args);\n } finally {\n self.clear();\n }\n },\n clear: () => {\n callbacks.clear();\n },\n };\n\n return self;\n}\n"],"mappings":";AAOA,SAAgB,IAAkE;CAChF,IAAM,oBAAY,IAAI,KAA+B,EAE/C,IAAyB;EAC7B,OAAO,OACL,EAAU,IAAI,EAAS,QACV,EAAU,OAAO,EAAS;EAEzC,MAAM,GAAG,MAAS;GAChB,IAAM,IAAoB,EAAE,EACtB,IAAgB,CAAC,GAAG,EAAU;AAEpC,QAAK,IAAM,KAAY,EACrB,KAAI;AACF,MAAS,GAAG,EAAK;YACV,GAAgB;AACvB,MAAO,KAAK,EAAM;;AAItB,OAAI,EAAO,SAAS,EAAG,OAAU,eAAe,EAAO;;EAEzD,cAAc,GAAG,MAAgB;AAC/B,OAAI;AACF,MAAK,IAAI,GAAG,EAAK;aACT;AACR,MAAK,OAAO;;;EAGhB,aAAa;AACX,KAAU,OAAO;;EAEpB;AAED,QAAO"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type ReadonlyRef, type Ref } from '../hooks/useRef.ts';
|
|
2
|
+
import { type Callbacks } from './createCallbacks.ts';
|
|
3
|
+
export interface Controller {
|
|
4
|
+
readonly host: HTMLElement;
|
|
5
|
+
readonly onNotify: Callbacks;
|
|
6
|
+
readonly onAfterRender: Callbacks;
|
|
7
|
+
readonly onDisconnect: Callbacks;
|
|
8
|
+
readonly refDocument: ReadonlyRef<Document>;
|
|
9
|
+
readonly refParent: ReadonlyRef<ParentNode | null>;
|
|
10
|
+
readonly formAssociated: {
|
|
11
|
+
readonly refForm: ReadonlyRef<HTMLFormElement | null>;
|
|
12
|
+
readonly refDisabled: ReadonlyRef<boolean>;
|
|
13
|
+
readonly onReset: Callbacks;
|
|
14
|
+
readonly onRestore: Callbacks<[state: string | File | FormData, reason: 'restore' | 'autocomplete']>;
|
|
15
|
+
} | undefined;
|
|
16
|
+
readonly createRef: <T>(value: T, onChange?: (value: T) => void) => Ref<T>;
|
|
17
|
+
readonly attachInternals: () => ElementInternals;
|
|
18
|
+
readonly connectedCallback: () => void;
|
|
19
|
+
readonly connectedMoveCallback: () => void;
|
|
20
|
+
readonly disconnectedCallback: () => void;
|
|
21
|
+
readonly adoptedCallback: () => void;
|
|
22
|
+
readonly formDisabledCallback: (disabled: boolean) => void;
|
|
23
|
+
readonly formResetCallback: () => void;
|
|
24
|
+
readonly formStateRestoreCallback: (state: string | File | FormData, reason: 'restore' | 'autocomplete') => void;
|
|
25
|
+
}
|
|
26
|
+
interface ControllerConfig {
|
|
27
|
+
readonly host: HTMLElement;
|
|
28
|
+
readonly formAssociated: boolean;
|
|
29
|
+
readonly render: (controller: Controller) => void;
|
|
30
|
+
readonly attachInternals: () => ElementInternals;
|
|
31
|
+
}
|
|
32
|
+
export declare function createController({ host, formAssociated, render, attachInternals }: ControllerConfig): Controller;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { createCallbacks as e } from "./createCallbacks.js";
|
|
2
|
+
import { controllers as t } from "./controllers.js";
|
|
3
|
+
import { $$ref as n } from "./constants.js";
|
|
4
|
+
//#region src/internal/createController.ts
|
|
5
|
+
function r({ host: r, formAssociated: i, render: a, attachInternals: o }) {
|
|
6
|
+
let s = !1, c = !1, l, u, d = e(), f = (e, t) => {
|
|
7
|
+
let r = e;
|
|
8
|
+
return {
|
|
9
|
+
[n]: !0,
|
|
10
|
+
get value() {
|
|
11
|
+
return r;
|
|
12
|
+
},
|
|
13
|
+
set value(e) {
|
|
14
|
+
e !== r && (r = e, t?.(r), !(!c || s) && (s = !0, queueMicrotask(() => {
|
|
15
|
+
s = !1, d.run();
|
|
16
|
+
})));
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}, p = {
|
|
20
|
+
host: r,
|
|
21
|
+
onNotify: d,
|
|
22
|
+
onAfterRender: e(),
|
|
23
|
+
onDisconnect: e(),
|
|
24
|
+
refDocument: f(r.ownerDocument),
|
|
25
|
+
refParent: f(r.parentNode),
|
|
26
|
+
formAssociated: i ? {
|
|
27
|
+
refForm: f(null),
|
|
28
|
+
refDisabled: f(!1),
|
|
29
|
+
onReset: e(),
|
|
30
|
+
onRestore: e()
|
|
31
|
+
} : void 0,
|
|
32
|
+
createRef: f,
|
|
33
|
+
attachInternals: () => l ??= o(),
|
|
34
|
+
connectedCallback: () => {
|
|
35
|
+
if (!c) {
|
|
36
|
+
c = !0, p.refParent.value = r.parentNode;
|
|
37
|
+
try {
|
|
38
|
+
t.push(p), a(p);
|
|
39
|
+
} finally {
|
|
40
|
+
t.pop();
|
|
41
|
+
}
|
|
42
|
+
p.onAfterRender.runAndClear(), u?.type === "reset" ? p.formAssociated?.onReset.run() : u?.type === "restore" && p.formAssociated?.onRestore.run(u.state, u.reason), p.onNotify.run();
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
connectedMoveCallback: () => {
|
|
46
|
+
c && (p.refParent.value = r.parentNode, p.onNotify.run());
|
|
47
|
+
},
|
|
48
|
+
disconnectedCallback: () => {
|
|
49
|
+
c && (p.onNotify.clear(), p.formAssociated?.onReset.clear(), p.formAssociated?.onRestore.clear(), p.onDisconnect.runAndClear());
|
|
50
|
+
},
|
|
51
|
+
adoptedCallback: () => {
|
|
52
|
+
p.refDocument.value = r.ownerDocument, p.onNotify.run();
|
|
53
|
+
},
|
|
54
|
+
formDisabledCallback: (e) => {
|
|
55
|
+
p.formAssociated && (p.formAssociated.refDisabled.value = e, p.onNotify.run());
|
|
56
|
+
},
|
|
57
|
+
formResetCallback: () => {
|
|
58
|
+
p.formAssociated && (c ? p.formAssociated.onReset.run() : u = { type: "reset" });
|
|
59
|
+
},
|
|
60
|
+
formStateRestoreCallback: (e, t) => {
|
|
61
|
+
p.formAssociated && (c ? p.formAssociated.onRestore.run(e, t) : u = {
|
|
62
|
+
type: "restore",
|
|
63
|
+
state: e,
|
|
64
|
+
reason: t
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
return p;
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
export { r as createController };
|
|
72
|
+
|
|
73
|
+
//# sourceMappingURL=createController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createController.js","names":[],"sources":["../../src/internal/createController.ts"],"sourcesContent":["import { type ReadonlyRef, type Ref } from '../hooks/useRef.ts';\nimport { $$ref } from './constants.ts';\nimport { controllers } from './controllers.ts';\nimport { type Callbacks, createCallbacks } from './createCallbacks.ts';\n\nexport interface Controller {\n readonly host: HTMLElement;\n readonly onNotify: Callbacks;\n readonly onAfterRender: Callbacks;\n readonly onDisconnect: Callbacks;\n readonly refDocument: ReadonlyRef<Document>;\n readonly refParent: ReadonlyRef<ParentNode | null>;\n readonly formAssociated:\n | {\n readonly refForm: ReadonlyRef<HTMLFormElement | null>;\n readonly refDisabled: ReadonlyRef<boolean>;\n readonly onReset: Callbacks;\n readonly onRestore: Callbacks<[state: string | File | FormData, reason: 'restore' | 'autocomplete']>;\n }\n | undefined;\n readonly createRef: <T>(value: T, onChange?: (value: T) => void) => Ref<T>;\n readonly attachInternals: () => ElementInternals;\n readonly connectedCallback: () => void;\n readonly connectedMoveCallback: () => void;\n readonly disconnectedCallback: () => void;\n readonly adoptedCallback: () => void;\n readonly formDisabledCallback: (disabled: boolean) => void;\n readonly formResetCallback: () => void;\n readonly formStateRestoreCallback: (state: string | File | FormData, reason: 'restore' | 'autocomplete') => void;\n}\n\ninterface ControllerConfig {\n readonly host: HTMLElement;\n readonly formAssociated: boolean;\n readonly render: (controller: Controller) => void;\n readonly attachInternals: () => ElementInternals;\n}\n\nexport function createController({ host, formAssociated, render, attachInternals }: ControllerConfig): Controller {\n let notifying = false;\n let connected = false;\n let internals: ElementInternals | undefined;\n\n let deferredFormUpdate:\n | { readonly type: 'reset' }\n | { readonly type: 'restore'; state: string | File | FormData; reason: 'restore' | 'autocomplete' }\n | undefined;\n\n const onNotify = createCallbacks();\n\n const createRef = <T>(initialValue: T, onChange?: (value: T) => void): Ref<T> => {\n let value = initialValue;\n\n return {\n [$$ref]: true,\n get value() {\n return value;\n },\n set value(newValue) {\n if (newValue === value) return;\n value = newValue;\n onChange?.(value);\n if (!connected || notifying) return;\n notifying = true;\n\n queueMicrotask(() => {\n notifying = false;\n onNotify.run();\n });\n },\n };\n };\n\n const controller = {\n host,\n onNotify,\n onAfterRender: createCallbacks(),\n onDisconnect: createCallbacks(),\n refDocument: createRef(host.ownerDocument),\n refParent: createRef(host.parentNode),\n formAssociated: formAssociated\n ? {\n refForm: createRef<HTMLFormElement | null>(null),\n refDisabled: createRef(false),\n onReset: createCallbacks(),\n onRestore: createCallbacks(),\n }\n : undefined,\n createRef,\n attachInternals: () => {\n return (internals ??= attachInternals());\n },\n connectedCallback: () => {\n if (connected) return;\n connected = true;\n controller.refParent.value = host.parentNode;\n\n try {\n controllers.push(controller);\n render(controller);\n } finally {\n controllers.pop();\n }\n\n controller.onAfterRender.runAndClear();\n\n if (deferredFormUpdate?.type === 'reset') {\n controller.formAssociated?.onReset.run();\n } else if (deferredFormUpdate?.type === 'restore') {\n controller.formAssociated?.onRestore.run(deferredFormUpdate.state, deferredFormUpdate.reason);\n }\n\n controller.onNotify.run();\n },\n connectedMoveCallback: () => {\n if (!connected) return;\n controller.refParent.value = host.parentNode;\n controller.onNotify.run();\n },\n disconnectedCallback: () => {\n if (!connected) return;\n controller.onNotify.clear();\n controller.formAssociated?.onReset.clear();\n controller.formAssociated?.onRestore.clear();\n controller.onDisconnect.runAndClear();\n },\n adoptedCallback: () => {\n controller.refDocument.value = host.ownerDocument;\n controller.onNotify.run();\n },\n formDisabledCallback: (disabled: boolean) => {\n if (!controller.formAssociated) return;\n controller.formAssociated.refDisabled.value = disabled;\n controller.onNotify.run();\n },\n formResetCallback: () => {\n if (!controller.formAssociated) return;\n if (connected) controller.formAssociated.onReset.run();\n else deferredFormUpdate = { type: 'reset' };\n },\n formStateRestoreCallback: (state, reason) => {\n if (!controller.formAssociated) return;\n if (connected) controller.formAssociated.onRestore.run(state, reason);\n else deferredFormUpdate = { type: 'restore', state, reason };\n },\n } satisfies Controller;\n\n return controller;\n}\n"],"mappings":";;;;AAsCA,SAAgB,EAAiB,EAAE,SAAM,mBAAgB,WAAQ,sBAAiD;CAChH,IAAI,IAAY,IACZ,IAAY,IACZ,GAEA,GAKE,IAAW,GAAiB,EAE5B,KAAgB,GAAiB,MAA0C;EAC/E,IAAI,IAAQ;AAEZ,SAAO;IACJ,IAAQ;GACT,IAAI,QAAQ;AACV,WAAO;;GAET,IAAI,MAAM,GAAU;AACd,UAAa,MACjB,IAAQ,GACR,IAAW,EAAM,EACb,GAAC,KAAa,OAClB,IAAY,IAEZ,qBAAqB;AAEnB,KADA,IAAY,IACZ,EAAS,KAAK;MACd;;GAEL;IAGG,IAAa;EACjB;EACA;EACA,eAAe,GAAiB;EAChC,cAAc,GAAiB;EAC/B,aAAa,EAAU,EAAK,cAAc;EAC1C,WAAW,EAAU,EAAK,WAAW;EACrC,gBAAgB,IACZ;GACE,SAAS,EAAkC,KAAK;GAChD,aAAa,EAAU,GAAM;GAC7B,SAAS,GAAiB;GAC1B,WAAW,GAAiB;GAC7B,GACD,KAAA;EACJ;EACA,uBACU,MAAc,GAAiB;EAEzC,yBAAyB;AACnB,WAEJ;IADA,IAAY,IACZ,EAAW,UAAU,QAAQ,EAAK;AAElC,QAAI;AAEF,KADA,EAAY,KAAK,EAAW,EAC5B,EAAO,EAAW;cACV;AACR,OAAY,KAAK;;AAWnB,IARA,EAAW,cAAc,aAAa,EAElC,GAAoB,SAAS,UAC/B,EAAW,gBAAgB,QAAQ,KAAK,GAC/B,GAAoB,SAAS,aACtC,EAAW,gBAAgB,UAAU,IAAI,EAAmB,OAAO,EAAmB,OAAO,EAG/F,EAAW,SAAS,KAAK;;;EAE3B,6BAA6B;AACtB,SACL,EAAW,UAAU,QAAQ,EAAK,YAClC,EAAW,SAAS,KAAK;;EAE3B,4BAA4B;AACrB,SACL,EAAW,SAAS,OAAO,EAC3B,EAAW,gBAAgB,QAAQ,OAAO,EAC1C,EAAW,gBAAgB,UAAU,OAAO,EAC5C,EAAW,aAAa,aAAa;;EAEvC,uBAAuB;AAErB,GADA,EAAW,YAAY,QAAQ,EAAK,eACpC,EAAW,SAAS,KAAK;;EAE3B,uBAAuB,MAAsB;AACtC,KAAW,mBAChB,EAAW,eAAe,YAAY,QAAQ,GAC9C,EAAW,SAAS,KAAK;;EAE3B,yBAAyB;AAClB,KAAW,mBACZ,IAAW,EAAW,eAAe,QAAQ,KAAK,GACjD,IAAqB,EAAE,MAAM,SAAS;;EAE7C,2BAA2B,GAAO,MAAW;AACtC,KAAW,mBACZ,IAAW,EAAW,eAAe,UAAU,IAAI,GAAO,EAAO,GAChE,IAAqB;IAAE,MAAM;IAAW;IAAO;IAAQ;;EAE/D;AAED,QAAO"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
type MapKey<T> = T extends Map<infer TKey, any> ? TKey : T extends WeakMap<infer TKey, any> ? TKey : never;
|
|
2
|
+
type MapValue<T> = T extends Map<any, infer TValue> ? TValue : T extends WeakMap<any, infer TValue> ? TValue : never;
|
|
3
|
+
export declare function getOrInsert<TMap extends Map<any, any> | WeakMap<any, any>>(map: TMap, key: MapKey<TMap>, createValue: (key: MapKey<TMap>) => MapValue<TMap>): MapValue<TMap>;
|
|
4
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getOrInsert.js","names":[],"sources":["../../src/internal/getOrInsert.ts"],"sourcesContent":["type MapKey<T> = T extends Map<infer TKey, any> ? TKey : T extends WeakMap<infer TKey, any> ? TKey : never;\ntype MapValue<T> = T extends Map<any, infer TValue> ? TValue : T extends WeakMap<any, infer TValue> ? TValue : never;\n\nexport function getOrInsert<TMap extends Map<any, any> | WeakMap<any, any>>(\n map: TMap,\n key: MapKey<TMap>,\n createValue: (key: MapKey<TMap>) => MapValue<TMap>,\n): MapValue<TMap> {\n if (map.has(key)) return map.get(key)!;\n const value = createValue(key);\n map.set(key, value);\n return value;\n}\n"],"mappings":";AAGA,SAAgB,EACd,GACA,GACA,GACgB;AAChB,KAAI,EAAI,IAAI,EAAI,CAAE,QAAO,EAAI,IAAI,EAAI;CACrC,IAAM,IAAQ,EAAY,EAAI;AAE9B,QADA,EAAI,IAAI,GAAK,EAAM,EACZ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seahax/elemental",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Functional, reactive, web component base library.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,22 +20,26 @@
|
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
22
|
"build": "vite build && tsc -b -f tsconfig.lib.json",
|
|
23
|
+
"postinstall": "playwright install",
|
|
23
24
|
"prepublishOnly": "npm run build && npm test",
|
|
24
|
-
"test": "eslint src"
|
|
25
|
+
"test": "eslint src && vitest run"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"@eslint/js": "^10.0.1",
|
|
28
29
|
"@seahax/eslint-progress": "^0.1.17",
|
|
29
30
|
"@types/node": "^25.6.0",
|
|
31
|
+
"@vitest/browser-playwright": "^4.1.6",
|
|
30
32
|
"eslint": "^10.3.0",
|
|
31
33
|
"eslint-config-prettier": "^10.1.8",
|
|
32
34
|
"eslint-plugin-prettier": "^5.5.5",
|
|
33
35
|
"eslint-plugin-regexp": "^3.1.0",
|
|
34
36
|
"eslint-plugin-simple-import-sort": "^13.0.0",
|
|
35
37
|
"jiti": "^2.6.1",
|
|
38
|
+
"playwright": "^1.60.0",
|
|
36
39
|
"typescript-eslint": "^8.59.1",
|
|
37
40
|
"vite": "^8.0.10",
|
|
38
|
-
"vite-bundle-analyzer": "^1.3.8"
|
|
41
|
+
"vite-bundle-analyzer": "^1.3.8",
|
|
42
|
+
"vitest": "^4.1.6"
|
|
39
43
|
},
|
|
40
44
|
"publishConfig": {
|
|
41
45
|
"access": "public"
|
package/dist/component.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { createContextController as e } from "./internal/context.js";
|
|
2
|
-
import { useRef as t } from "./hooks/ref.js";
|
|
3
|
-
//#region src/component.ts
|
|
4
|
-
function n(n, { props: r, shadow: i } = {}) {
|
|
5
|
-
return class extends HTMLElement {
|
|
6
|
-
#e = {};
|
|
7
|
-
#t = e(this);
|
|
8
|
-
constructor() {
|
|
9
|
-
if (super(), r) {
|
|
10
|
-
let e = this.#e;
|
|
11
|
-
for (let [n, i] of Object.entries(r)) {
|
|
12
|
-
if (n in this) continue;
|
|
13
|
-
let r = i(e[n] = t(void 0), this);
|
|
14
|
-
Object.defineProperty(this, n, r);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
connectedCallback() {
|
|
19
|
-
this.#t.connect(() => {
|
|
20
|
-
n(this.attachShadow({
|
|
21
|
-
...i,
|
|
22
|
-
mode: i?.mode ?? "open"
|
|
23
|
-
}), this.#e);
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
disconnectedCallback() {
|
|
27
|
-
this.#t.disconnect();
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
//#endregion
|
|
32
|
-
export { n as defineComponent };
|
|
33
|
-
|
|
34
|
-
//# sourceMappingURL=component.js.map
|
package/dist/component.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"component.js","names":["#propRefs","#contextController"],"sources":["../src/component.ts"],"sourcesContent":["import { type Ref, useRef } from './hooks/ref.ts';\nimport { createContextController } from './internal/context.ts';\n\ntype SafeProps<TProps> = any extends any\n ? { [P in keyof TProps as P extends keyof HTMLElement ? never : P]: TProps[P] }\n : never;\n\nexport interface ComponentConstructor<TProps extends object> {\n new (): ComponentWithProps<TProps>;\n}\n\nexport interface ComponentOptions<TProps extends object> {\n readonly shadow?: Partial<ShadowRootInit>;\n readonly props?: ComponentPropDescriptors<TProps>;\n}\n\nexport type ComponentPropDescriptors<TProps extends object> = {\n readonly [P in keyof SafeProps<TProps>]: ComponentPropDescriptorFactory<TProps[P]>;\n};\n\nexport type ComponentPropDescriptorFactory<TType> = (\n ref: Ref<TType | undefined>,\n host: HTMLElement,\n) => ComponentPropDescriptor<TType>;\n\nexport interface ComponentPropDescriptor<T> extends Omit<PropertyDescriptor, 'value' | 'get' | 'set'> {\n get(): T;\n set?(value: T): void;\n}\n\nexport type ComponentWithProps<TProps extends object> = HTMLElement & {\n -readonly [P in keyof SafeProps<TProps>]: TProps[P];\n};\n\nexport type ComponentShadowRoot<TProps extends object> = Omit<ShadowRoot, 'host'> & {\n readonly host: ComponentWithProps<TProps>;\n};\n\nexport type ComponentPropRefs<TProps extends object> = {\n readonly [P in keyof SafeProps<TProps>]: Ref<TProps[P] | undefined>;\n};\n\n/** Define a custom `HTMLElement` that is functional and reactive. */\nexport function defineComponent<TProps extends object = {}>(\n render: (shadowRoot: ComponentShadowRoot<TProps>, props: ComponentPropRefs<TProps>) => void,\n options?: ComponentOptions<TProps>,\n): ComponentConstructor<TProps>;\nexport function defineComponent(\n render: (\n shadowRoot: ComponentShadowRoot<Record<string, unknown>>,\n props: ComponentPropRefs<Record<string, unknown>>,\n ) => void,\n { props, shadow }: ComponentOptions<Record<string, unknown>> = {},\n): ComponentConstructor<{}> {\n return class extends HTMLElement {\n readonly #propRefs: ComponentPropRefs<Record<string, unknown>> = {};\n readonly #contextController = createContextController(this);\n\n constructor() {\n super();\n\n if (props) {\n const propRefs: Record<string, Ref<unknown>> = this.#propRefs;\n\n for (const [key, getDescriptor] of Object.entries(props)) {\n if (key in this) continue;\n const ref = (propRefs[key] = useRef<any>(undefined));\n const descriptor = getDescriptor(ref, this);\n Object.defineProperty(this, key, descriptor);\n }\n }\n }\n\n protected connectedCallback(): void {\n this.#contextController.connect(() => {\n const shadowRoot = this.attachShadow({ ...shadow, mode: shadow?.mode ?? 'open' });\n render(shadowRoot as ComponentShadowRoot<Record<string, unknown>>, this.#propRefs);\n });\n }\n\n protected disconnectedCallback(): void {\n this.#contextController.disconnect();\n }\n };\n}\n"],"mappings":";;;AA+CA,SAAgB,EACd,GAIA,EAAE,UAAO,cAAsD,EAAE,EACvC;AAC1B,QAAO,cAAc,YAAY;EAC/B,KAAiE,EAAE;EACnE,KAA8B,EAAwB,KAAK;EAE3D,cAAc;AAGZ,OAFA,OAAO,EAEH,GAAO;IACT,IAAM,IAAyC,MAAA;AAE/C,SAAK,IAAM,CAAC,GAAK,MAAkB,OAAO,QAAQ,EAAM,EAAE;AACxD,SAAI,KAAO,KAAM;KAEjB,IAAM,IAAa,EAAc,EADX,KAAO,EAAY,KAAA,EAAU,EACb,KAAK;AAC3C,YAAO,eAAe,MAAM,GAAK,EAAW;;;;EAKlD,oBAAoC;AAClC,SAAA,EAAwB,cAAc;AAEpC,MADmB,KAAK,aAAa;KAAE,GAAG;KAAQ,MAAM,GAAQ,QAAQ;KAAQ,CACzE,EAA4D,MAAA,EAAe;KAClF;;EAGJ,uBAAuC;AACrC,SAAA,EAAwB,YAAY"}
|
package/dist/hooks/attributes.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { useRef as e } from "./ref.js";
|
|
2
|
-
import { useEffect as t } from "./effect.js";
|
|
3
|
-
import { useHost as n } from "./host.js";
|
|
4
|
-
//#region src/hooks/attributes.ts
|
|
5
|
-
function r(...r) {
|
|
6
|
-
if (r.length === 0) return {};
|
|
7
|
-
let i = n(), a = [], o = /* @__PURE__ */ new Map();
|
|
8
|
-
for (let t of r) {
|
|
9
|
-
let n = e(i.getAttribute(t), (e) => {
|
|
10
|
-
e == null ? i.removeAttribute(t) : i.setAttribute(t, e);
|
|
11
|
-
});
|
|
12
|
-
a.push(n), o.set(t, n);
|
|
13
|
-
}
|
|
14
|
-
let s = new MutationObserver((e) => {
|
|
15
|
-
for (let { attributeName: t } of e) t != null && Object.hasOwn(a, t) && (o.get(t).value = i.getAttribute(t));
|
|
16
|
-
});
|
|
17
|
-
return t([], () => (s.observe(i, {
|
|
18
|
-
attributeFilter: r,
|
|
19
|
-
attributes: !0
|
|
20
|
-
}), () => s.disconnect())), a;
|
|
21
|
-
}
|
|
22
|
-
//#endregion
|
|
23
|
-
export { r as useAttributes };
|
|
24
|
-
|
|
25
|
-
//# sourceMappingURL=attributes.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"attributes.js","names":[],"sources":["../../src/hooks/attributes.ts"],"sourcesContent":["import { useEffect } from './effect.ts';\nimport { useHost } from './host.ts';\nimport { type Ref, useRef } from './ref.ts';\n\n/** Use references (reactive state) bound to attributes. */\nexport function useAttributes<const TNames extends string[]>(\n ...names: TNames\n): { -readonly [P in keyof TNames]: Ref<string | null> } {\n if (names.length === 0) return {} as any;\n const host = useHost();\n const refs: Ref<string | null>[] = [];\n const refMap = new Map<string, Ref<string | null>>();\n\n for (const name of names) {\n const ref = useRef(host.getAttribute(name), (value) => {\n if (value == null) host.removeAttribute(name);\n else host.setAttribute(name, value);\n });\n\n refs.push(ref);\n refMap.set(name, ref);\n }\n\n const observer = new MutationObserver((mutation) => {\n for (const { attributeName } of mutation) {\n if (attributeName != null && Object.hasOwn(refs, attributeName)) {\n refMap.get(attributeName)!.value = host.getAttribute(attributeName);\n }\n }\n });\n\n useEffect([], () => {\n observer.observe(host, { attributeFilter: names, attributes: true });\n return () => observer.disconnect();\n });\n\n return refs as any;\n}\n"],"mappings":";;;;AAKA,SAAgB,EACd,GAAG,GACoD;AACvD,KAAI,EAAM,WAAW,EAAG,QAAO,EAAE;CACjC,IAAM,IAAO,GAAS,EAChB,IAA6B,EAAE,EAC/B,oBAAS,IAAI,KAAiC;AAEpD,MAAK,IAAM,KAAQ,GAAO;EACxB,IAAM,IAAM,EAAO,EAAK,aAAa,EAAK,GAAG,MAAU;AACrD,GAAI,KAAS,OAAM,EAAK,gBAAgB,EAAK,GACxC,EAAK,aAAa,GAAM,EAAM;IACnC;AAGF,EADA,EAAK,KAAK,EAAI,EACd,EAAO,IAAI,GAAM,EAAI;;CAGvB,IAAM,IAAW,IAAI,kBAAkB,MAAa;AAClD,OAAK,IAAM,EAAE,sBAAmB,EAC9B,CAAI,KAAiB,QAAQ,OAAO,OAAO,GAAM,EAAc,KAC7D,EAAO,IAAI,EAAc,CAAE,QAAQ,EAAK,aAAa,EAAc;GAGvE;AAOF,QALA,EAAU,EAAE,SACV,EAAS,QAAQ,GAAM;EAAE,iBAAiB;EAAO,YAAY;EAAM,CAAC,QACvD,EAAS,YAAY,EAClC,EAEK"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { useRef as e } from "./ref.js";
|
|
2
|
-
import { useEffect as t } from "./effect.js";
|
|
3
|
-
import { useHost as n } from "./host.js";
|
|
4
|
-
//#region src/hooks/child-effect.ts
|
|
5
|
-
function r(r) {
|
|
6
|
-
let i = n(), a = e(0), o = new MutationObserver((e) => {
|
|
7
|
-
e.some((e) => e.type === "childList") && (a.value = (a.value + 1) % (2 ** 53 - 1));
|
|
8
|
-
});
|
|
9
|
-
t([], () => (o.observe(i, { childList: !0 }), () => o.disconnect())), t([a], () => r());
|
|
10
|
-
}
|
|
11
|
-
//#endregion
|
|
12
|
-
export { r as useChildEffect };
|
|
13
|
-
|
|
14
|
-
//# sourceMappingURL=child-effect.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"child-effect.js","names":[],"sources":["../../src/hooks/child-effect.ts"],"sourcesContent":["import { useEffect } from './effect.ts';\nimport { useHost } from './host.ts';\nimport { useRef } from './ref.ts';\n\n/** React to child list changes (non-recursive). */\nexport function useChildEffect(callback: () => (() => void) | void): void {\n const host = useHost();\n const ref = useRef(0);\n\n const observer = new MutationObserver((mutation) => {\n if (mutation.some((m) => m.type === 'childList')) {\n ref.value = (ref.value + 1) % Number.MAX_SAFE_INTEGER;\n }\n });\n\n useEffect([], () => {\n observer.observe(host, { childList: true });\n return () => observer.disconnect();\n });\n\n useEffect([ref], () => {\n return callback();\n });\n}\n"],"mappings":";;;;AAKA,SAAgB,EAAe,GAA2C;CACxE,IAAM,IAAO,GAAS,EAChB,IAAM,EAAO,EAAE,EAEf,IAAW,IAAI,kBAAkB,MAAa;AAClD,EAAI,EAAS,MAAM,MAAM,EAAE,SAAS,YAAY,KAC9C,EAAI,SAAS,EAAI,QAAQ;GAE3B;AAOF,CALA,EAAU,EAAE,SACV,EAAS,QAAQ,GAAM,EAAE,WAAW,IAAM,CAAC,QAC9B,EAAS,YAAY,EAClC,EAEF,EAAU,CAAC,EAAI,QACN,GAAU,CACjB"}
|
package/dist/hooks/context.d.ts
DELETED
package/dist/hooks/context.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { contextStack as e } from "../internal/context.js";
|
|
2
|
-
//#region src/hooks/context.ts
|
|
3
|
-
function t() {
|
|
4
|
-
let t = e.at(-1);
|
|
5
|
-
if (!t) throw Error("hooks must be called inside a render function");
|
|
6
|
-
return t;
|
|
7
|
-
}
|
|
8
|
-
//#endregion
|
|
9
|
-
export { t as useContext };
|
|
10
|
-
|
|
11
|
-
//# sourceMappingURL=context.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","names":[],"sources":["../../src/hooks/context.ts"],"sourcesContent":["import { type Context, contextStack } from '../internal/context.ts';\n\n/** @internal Get the context of the currently rendering component. */\nexport function useContext(): Context {\n const context = contextStack.at(-1);\n if (!context) throw new Error('hooks must be called inside a render function');\n return context;\n}\n"],"mappings":";;AAGA,SAAgB,IAAsB;CACpC,IAAM,IAAU,EAAa,GAAG,GAAG;AACnC,KAAI,CAAC,EAAS,OAAU,MAAM,gDAAgD;AAC9E,QAAO"}
|
package/dist/hooks/effect.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ReadonlyRef, RefValues } from './ref.ts';
|
|
2
|
-
/** React to observable (reference) changes. */
|
|
3
|
-
export declare function useEffect<const TDeps extends readonly ReadonlyRef<any>[]>(deps: TDeps, callback: (...values: RefValues<TDeps>) => (() => void) | void): void;
|
|
4
|
-
/**
|
|
5
|
-
* React to document disconnection.
|
|
6
|
-
*
|
|
7
|
-
* Alias for: `useEffect([], () => callback)`
|
|
8
|
-
*/
|
|
9
|
-
export declare function useDisconnectEffect(callback: () => void): void;
|