@brytdesigns/web-component-core 1.1.0 → 1.1.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.
@@ -0,0 +1,160 @@
1
+ import { compose, register, noShadowDOM } from 'component-register';
2
+ import { createEffect, on, createRoot, onCleanup, createSignal } from 'solid-js';
3
+ import { insert } from 'solid-js/web';
4
+
5
+ // src/utils/toHyphenated.ts
6
+ function toHyphenated(str) {
7
+ return str.replace(/([A-Z])/g, "-$1").toLowerCase();
8
+ }
9
+ function createProps(raw) {
10
+ const keys = Object.keys(raw);
11
+ const props = {};
12
+ for (let i = 0; i < keys.length; i++) {
13
+ const key = keys[i];
14
+ if (typeof key === "undefined") continue;
15
+ const [get, set] = createSignal(Reflect.get(raw, key));
16
+ Object.defineProperty(props, key, {
17
+ get,
18
+ set(v) {
19
+ set(() => v);
20
+ }
21
+ });
22
+ }
23
+ return props;
24
+ }
25
+ function lookupContext(el) {
26
+ if (el.assignedSlot && el.assignedSlot._$owner)
27
+ return el.assignedSlot._$owner;
28
+ let next = el.parentNode;
29
+ while (next && !next._$owner && !(next.assignedSlot && next.assignedSlot._$owner))
30
+ next = next.parentNode;
31
+ return next && next.assignedSlot ? next.assignedSlot._$owner : el._$owner;
32
+ }
33
+ function withSolid(ComponentType) {
34
+ return (rawProps, options) => {
35
+ const { element } = options;
36
+ return createRoot((dispose) => {
37
+ const props = createProps(rawProps);
38
+ element.addPropertyChangedCallback(
39
+ (key, val) => props[key] = val
40
+ );
41
+ element.addReleaseCallback(() => {
42
+ element.renderRoot.textContent = "";
43
+ dispose();
44
+ });
45
+ const comp = ComponentType(props, options);
46
+ return insert(element.renderRoot, comp);
47
+ }, lookupContext(element));
48
+ };
49
+ }
50
+ function withNoShadowDOM(Component = () => {
51
+ }) {
52
+ return (props, options) => {
53
+ noShadowDOM();
54
+ const comp = Component(props, options);
55
+ return comp;
56
+ };
57
+ }
58
+ function customElement(tagName, props, Component = () => {
59
+ }, ...rest) {
60
+ return compose(register(tagName, props), withSolid, ...rest)(Component);
61
+ }
62
+ function customShadowlessElement(tagName, props, Component = () => {
63
+ }, ...rest) {
64
+ return compose(
65
+ register(tagName, props),
66
+ withNoShadowDOM,
67
+ withSolid,
68
+ ...rest
69
+ )(Component);
70
+ }
71
+ var correctElementType = (component) => {
72
+ return (props, options) => {
73
+ return component(props, options);
74
+ };
75
+ };
76
+
77
+ // src/utils/isCustomElement.ts
78
+ function isCustomElement(element) {
79
+ return Reflect.has(element, "__initialized");
80
+ }
81
+
82
+ // src/utils/getContextFromProvider.ts
83
+ function getContextFromProvider(context, element) {
84
+ const ctxSymbol = Object.getOwnPropertySymbols(element).find(
85
+ (s) => s.description === "element-context"
86
+ );
87
+ if (!ctxSymbol) {
88
+ throw new Error("No context provider found for the provided element");
89
+ }
90
+ const contexts = element[ctxSymbol];
91
+ return contexts[context.id];
92
+ }
93
+
94
+ // src/utils/checkLoaded.ts
95
+ function checkLoaded() {
96
+ return document.readyState === "complete" || //@ts-ignore
97
+ document.readyState === "loaded" || document.readyState === "interactive";
98
+ }
99
+
100
+ // src/utils/invokeOnLoaded.ts
101
+ function invokeOnLoaded(fn, { signal }) {
102
+ if (checkLoaded()) {
103
+ const id = setTimeout(() => fn());
104
+ signal?.addEventListener("abort", () => clearTimeout(id), {
105
+ once: true
106
+ });
107
+ return;
108
+ }
109
+ window.addEventListener("DOMContentLoaded", fn, { signal, once: true });
110
+ return;
111
+ }
112
+ function createWithElementContext(context) {
113
+ return function(selector, dependencies = () => null, cb) {
114
+ createEffect(
115
+ on(
116
+ () => {
117
+ const s = typeof selector === "string" ? selector : selector();
118
+ return {
119
+ selector: s,
120
+ dependencies: dependencies()
121
+ };
122
+ },
123
+ ({ selector: selector2, dependencies: dependencies2 }) => {
124
+ const controller = new AbortController();
125
+ invokeOnLoaded(
126
+ () => {
127
+ let target = null;
128
+ try {
129
+ target = document.querySelector(selector2);
130
+ } catch (e) {
131
+ }
132
+ if (!target)
133
+ return console.warn(`Target element not found!`, {
134
+ target: selector2
135
+ });
136
+ createRoot((dispose) => {
137
+ const c = getContextFromProvider(context, target);
138
+ const unsub = cb(c, dependencies2);
139
+ onCleanup(() => {
140
+ if (typeof unsub === "function") unsub();
141
+ });
142
+ controller.signal.addEventListener("abort", dispose, {
143
+ once: true
144
+ });
145
+ });
146
+ },
147
+ { signal: controller.signal }
148
+ );
149
+ onCleanup(() => {
150
+ controller.abort();
151
+ });
152
+ }
153
+ )
154
+ );
155
+ };
156
+ }
157
+
158
+ export { checkLoaded, correctElementType, createWithElementContext, customElement, customShadowlessElement, getContextFromProvider, invokeOnLoaded, isCustomElement, toHyphenated };
159
+ //# sourceMappingURL=index.js.map
160
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/toHyphenated.ts","../../../src/utils/solid-element.ts","../../../src/utils/isCustomElement.ts","../../../src/utils/getContextFromProvider.ts","../../../src/utils/checkLoaded.ts","../../../src/utils/invokeOnLoaded.ts","../../../src/utils/createWithElementContext.ts"],"names":["selector","dependencies","createRoot"],"mappings":"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","file":"index.js","sourcesContent":["export function toHyphenated(str: string): string {\n return str\n .replace(/([A-Z])/g, \"-$1\") // Insert hyphen before uppercase letters\n .toLowerCase(); // Convert the entire string to lowercase\n}\n","import {\n register,\n type ComponentType as mComponentType,\n type ICustomElement,\n type FunctionComponent,\n type ComponentOptions,\n noShadowDOM,\n compose,\n} from \"component-register\";\nimport { createRoot, createSignal } from \"solid-js\";\nimport { insert } from \"solid-js/web\";\n\nexport type ComponentType<T> = mComponentType<T>;\n\ntype CorrectComponentOptions = { element: HTMLElement & ICustomElement };\n\nexport type CorrectComponentType<T> = (\n props: T,\n options: CorrectComponentOptions,\n) => unknown;\n\nfunction createProps<T extends object>(raw: T) {\n const keys = Object.keys(raw) as (keyof T)[];\n const props = {};\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n if (typeof key === \"undefined\") continue;\n const [get, set] = createSignal(Reflect.get(raw, key));\n Object.defineProperty(props, key, {\n get,\n set(v) {\n set(() => v);\n },\n });\n }\n return props as T;\n}\n\nfunction lookupContext(el: ICustomElement & { _$owner?: any }) {\n if (el.assignedSlot && el.assignedSlot._$owner)\n return el.assignedSlot._$owner;\n let next: Element & { _$owner?: any } = el.parentNode;\n while (\n next &&\n !next._$owner &&\n !(\n next.assignedSlot &&\n (next.assignedSlot as Element & { _$owner?: any })._$owner\n )\n )\n next = next.parentNode as Element;\n return next && next.assignedSlot\n ? (next.assignedSlot as Element & { _$owner?: any })._$owner\n : el._$owner;\n}\n\nfunction withSolid<T extends object>(\n ComponentType: ComponentType<T>,\n): ComponentType<T> {\n return (rawProps: T, options: ComponentOptions) => {\n const { element } = options as {\n element: ICustomElement & { _$owner?: any };\n };\n return createRoot((dispose: Function) => {\n const props = createProps<T>(rawProps);\n\n element.addPropertyChangedCallback(\n (key: string, val: any) => (props[key as keyof T] = val),\n );\n element.addReleaseCallback(() => {\n element.renderRoot.textContent = \"\";\n dispose();\n });\n\n const comp = (ComponentType as FunctionComponent<T>)(props as T, options);\n return insert(element.renderRoot, comp);\n }, lookupContext(element));\n };\n}\n\nfunction withNoShadowDOM<T extends object>(\n Component: ComponentType<T> = () => {},\n) {\n return (props: T, options: ComponentOptions) => {\n noShadowDOM();\n const comp = (Component as FunctionComponent<T>)(props, options);\n return comp;\n };\n}\n\nexport function customElement<T extends object>(\n tagName: string,\n props: T,\n Component: ComponentType<T> = () => {},\n ...rest: ((C: ComponentType<T>) => ComponentType<T>)[]\n) {\n return compose(register(tagName, props), withSolid, ...rest)(Component);\n}\n\nexport function customShadowlessElement<T extends object>(\n tagName: string,\n props: T,\n Component: ComponentType<T> = () => {},\n ...rest: ((C: ComponentType<T>) => ComponentType<T>)[]\n) {\n return compose(\n register(tagName, props),\n withNoShadowDOM,\n withSolid,\n ...rest,\n )(Component);\n}\n\nexport const correctElementType = <T>(\n component: CorrectComponentType<T>,\n): ComponentType<T> => {\n return (props: T, options) => {\n return component(props, options as CorrectComponentOptions);\n };\n};\n","import type { ICustomElement } from \"component-register\";\nexport function isCustomElement(\n element: any,\n): element is ICustomElement & HTMLElement {\n return Reflect.has(element, \"__initialized\");\n}\n","import type { createContext } from \"component-register\";\n\nexport function getContextFromProvider<T>(\n context: ReturnType<typeof createContext>,\n element: Element,\n) {\n const ctxSymbol = Object.getOwnPropertySymbols(element).find(\n (s) => s.description === \"element-context\",\n );\n if (!ctxSymbol) {\n throw new Error(\"No context provider found for the provided element\");\n }\n // @ts-ignore\n const contexts = element[ctxSymbol];\n return contexts[context.id] as T;\n}\n","export function checkLoaded() {\n return (\n document.readyState === \"complete\" ||\n //@ts-ignore\n document.readyState === \"loaded\" ||\n document.readyState === \"interactive\"\n );\n}\n","import { checkLoaded } from \"./checkLoaded.js\";\n\nexport function invokeOnLoaded(\n fn: () => void,\n { signal }: { signal?: AbortSignal },\n) {\n if (checkLoaded()) {\n const id = setTimeout(() => fn());\n signal?.addEventListener(\"abort\", () => clearTimeout(id), {\n once: true,\n });\n return;\n }\n window.addEventListener(\"DOMContentLoaded\", fn, { signal, once: true });\n return;\n}\n","import type { createContext } from \"component-register\";\nimport { getContextFromProvider } from \"./getContextFromProvider.js\";\nimport { invokeOnLoaded } from \"./invokeOnLoaded.js\";\nimport {\n type Accessor,\n createEffect,\n createRoot,\n on,\n onCleanup,\n} from \"solid-js\";\n\n/**\n * Creates a HOF to ensure that a given callback is invoked only after the context for the element is ready.\n * */\n\nexport function createWithElementContext<\n Context extends ReturnType<typeof createContext>,\n ContextState = null,\n>(context: Context) {\n return function <D extends any>(\n selector: string | Accessor<string>,\n dependencies: Accessor<D> = () => null as D,\n cb: (context: ContextState, dependencies: D) => void | (() => void),\n ) {\n createEffect(\n on(\n () => {\n const s: string =\n typeof selector === \"string\" ? selector : selector();\n return {\n selector: s,\n dependencies: dependencies(),\n };\n },\n ({ selector, dependencies }) => {\n const controller = new AbortController();\n invokeOnLoaded(\n () => {\n let target: Element | null = null;\n try {\n target = document.querySelector(selector);\n } catch (e) {\n e;\n }\n if (!target)\n return console.warn(`Target element not found!`, {\n target: selector,\n });\n\n createRoot((dispose) => {\n const c = getContextFromProvider(context, target);\n\n const unsub = cb(c as ContextState, dependencies);\n\n onCleanup(() => {\n if (typeof unsub === \"function\") unsub();\n });\n\n controller.signal.addEventListener(\"abort\", dispose, {\n once: true,\n });\n });\n },\n { signal: controller.signal },\n );\n\n // abort controller when dependencies change\n onCleanup(() => {\n controller.abort();\n });\n },\n ),\n );\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brytdesigns/web-component-core",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Web component core utilities for building solid based web components",
5
5
  "main": "./dist/main/index.js",
6
6
  "module": "./dist/main/index.js",