@coherent.js/web-components 1.0.0-beta.5 → 1.0.0-beta.7

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/dist/index.js ADDED
@@ -0,0 +1,110 @@
1
+ // src/index.js
2
+ import { render } from "@coherent.js/core";
3
+ function defineComponent(name, component, options = {}) {
4
+ if (typeof window === "undefined") {
5
+ return { name, component, options };
6
+ }
7
+ if (!window.customElements) {
8
+ throw new Error("Custom Elements API not supported");
9
+ }
10
+ const observedAttrs = options.observedAttributes || [];
11
+ const defaults = options.defaults || {};
12
+ class CoherentElement extends HTMLElement {
13
+ static get observedAttributes() {
14
+ return observedAttrs;
15
+ }
16
+ constructor() {
17
+ super();
18
+ this._props = { ...defaults };
19
+ this._connected = false;
20
+ this.component = component;
21
+ this.options = options;
22
+ }
23
+ connectedCallback() {
24
+ this._connected = true;
25
+ for (const attr of observedAttrs) {
26
+ if (this.hasAttribute(attr)) {
27
+ this._props[attr] = this.getAttribute(attr);
28
+ }
29
+ }
30
+ this._render();
31
+ }
32
+ disconnectedCallback() {
33
+ this._connected = false;
34
+ if (options.shadow && this.shadowRoot) {
35
+ this.shadowRoot.innerHTML = "";
36
+ } else {
37
+ this.innerHTML = "";
38
+ }
39
+ }
40
+ attributeChangedCallback(attrName, oldValue, newValue) {
41
+ if (oldValue === newValue) return;
42
+ this._props[attrName] = newValue;
43
+ if (this._connected) {
44
+ this._render();
45
+ }
46
+ }
47
+ /**
48
+ * Set a property and re-render
49
+ */
50
+ setProperty(key, value) {
51
+ this._props[key] = value;
52
+ if (this._connected) {
53
+ this._render();
54
+ }
55
+ }
56
+ /**
57
+ * Get current props
58
+ */
59
+ getProperties() {
60
+ return { ...this._props };
61
+ }
62
+ _render() {
63
+ const componentDef = typeof this.component === "function" ? this.component(this._props) : this.component;
64
+ const html = render(componentDef);
65
+ if (this.options.shadow) {
66
+ if (!this.shadowRoot) {
67
+ this.attachShadow({ mode: "open" });
68
+ }
69
+ this.shadowRoot.innerHTML = html;
70
+ this._delegateEvents(this.shadowRoot);
71
+ } else {
72
+ this.innerHTML = html;
73
+ this._delegateEvents(this);
74
+ }
75
+ }
76
+ /**
77
+ * Delegate data-action events to component handlers
78
+ */
79
+ _delegateEvents(root) {
80
+ const actionElements = root.querySelectorAll("[data-action]");
81
+ for (const el of actionElements) {
82
+ const action = el.dataset.action;
83
+ const [eventType, handlerName] = action.includes(":") ? action.split(":") : ["click", action];
84
+ el.addEventListener(eventType, (event) => {
85
+ this.dispatchEvent(new CustomEvent("coherent-action", {
86
+ bubbles: true,
87
+ detail: { action: handlerName, event, element: el }
88
+ }));
89
+ });
90
+ }
91
+ }
92
+ }
93
+ window.customElements.define(name, CoherentElement);
94
+ return CoherentElement;
95
+ }
96
+ function integrateWithWebComponents(_runtime) {
97
+ return {
98
+ defineComponent: (name, component, options) => defineComponent(name, component, options)
99
+ };
100
+ }
101
+ function defineCoherentElement(name, component, options = {}) {
102
+ return defineComponent(name, component, options);
103
+ }
104
+ export {
105
+ defineComponent as default,
106
+ defineCoherentElement,
107
+ defineComponent,
108
+ integrateWithWebComponents
109
+ };
110
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.js"],
4
+ "sourcesContent": ["/**\n * Coherent.js Web Components Integration\n * Provides custom element and web component utilities\n */\n\nimport { render } from '@coherent.js/core';\n\n/**\n * Define a Coherent.js component as a custom element\n *\n * @param {string} name - Custom element tag name (must contain a hyphen)\n * @param {Function|Object} component - Coherent.js component (function or object)\n * @param {Object} [options] - Configuration options\n * @param {boolean} [options.shadow] - Use Shadow DOM for style encapsulation\n * @param {string[]} [options.observedAttributes] - Attributes to watch for changes\n * @param {Object} [options.defaults] - Default property values\n * @returns {Function|Object} The custom element class, or a server-side placeholder\n */\nexport function defineComponent(name, component, options = {}) {\n if (typeof window === 'undefined') {\n // Server-side: return a placeholder for SSR\n return { name, component, options };\n }\n\n if (!window.customElements) {\n throw new Error('Custom Elements API not supported');\n }\n\n const observedAttrs = options.observedAttributes || [];\n const defaults = options.defaults || {};\n\n class CoherentElement extends HTMLElement {\n static get observedAttributes() {\n return observedAttrs;\n }\n\n constructor() {\n super();\n this._props = { ...defaults };\n this._connected = false;\n this.component = component;\n this.options = options;\n }\n\n connectedCallback() {\n this._connected = true;\n // Copy initial attributes to props\n for (const attr of observedAttrs) {\n if (this.hasAttribute(attr)) {\n this._props[attr] = this.getAttribute(attr);\n }\n }\n this._render();\n }\n\n disconnectedCallback() {\n this._connected = false;\n // Cleanup: remove event listeners and clear content\n if (options.shadow && this.shadowRoot) {\n this.shadowRoot.innerHTML = '';\n } else {\n this.innerHTML = '';\n }\n }\n\n attributeChangedCallback(attrName, oldValue, newValue) {\n if (oldValue === newValue) return;\n this._props[attrName] = newValue;\n if (this._connected) {\n this._render();\n }\n }\n\n /**\n * Set a property and re-render\n */\n setProperty(key, value) {\n this._props[key] = value;\n if (this._connected) {\n this._render();\n }\n }\n\n /**\n * Get current props\n */\n getProperties() {\n return { ...this._props };\n }\n\n _render() {\n const componentDef = typeof this.component === 'function'\n ? this.component(this._props)\n : this.component;\n\n const html = render(componentDef);\n\n if (this.options.shadow) {\n if (!this.shadowRoot) {\n this.attachShadow({ mode: 'open' });\n }\n this.shadowRoot.innerHTML = html;\n this._delegateEvents(this.shadowRoot);\n } else {\n this.innerHTML = html;\n this._delegateEvents(this);\n }\n }\n\n /**\n * Delegate data-action events to component handlers\n */\n _delegateEvents(root) {\n const actionElements = root.querySelectorAll('[data-action]');\n for (const el of actionElements) {\n const action = el.dataset.action;\n const [eventType, handlerName] = action.includes(':')\n ? action.split(':')\n : ['click', action];\n\n el.addEventListener(eventType, (event) => {\n this.dispatchEvent(new CustomEvent('coherent-action', {\n bubbles: true,\n detail: { action: handlerName, event, element: el }\n }));\n });\n }\n }\n }\n\n window.customElements.define(name, CoherentElement);\n return CoherentElement;\n}\n\n/**\n * Integration utilities for runtime environments\n */\nexport function integrateWithWebComponents(_runtime) {\n return {\n defineComponent: (name, component, options) => defineComponent(name, component, options)\n };\n}\n\n/**\n * Alias for defineComponent\n */\nexport function defineCoherentElement(name, component, options = {}) {\n return defineComponent(name, component, options);\n}\n\nexport { defineComponent as default };\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coherent.js/web-components",
3
- "version": "1.0.0-beta.5",
3
+ "version": "1.0.0-beta.7",
4
4
  "description": "Web Components integration for Coherent.js",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -15,8 +15,8 @@
15
15
  ],
16
16
  "author": "Coherent.js Team",
17
17
  "license": "MIT",
18
- "dependencies": {
19
- "@coherent.js/core": "1.0.0-beta.5"
18
+ "peerDependencies": {
19
+ "@coherent.js/core": "1.0.0-beta.7"
20
20
  },
21
21
  "devDependencies": {
22
22
  "vitest": "^3.2.4"
@@ -25,11 +25,20 @@
25
25
  "type": "git",
26
26
  "url": "git+https://github.com/Tomdrouv1/coherent.js.git"
27
27
  },
28
+ "homepage": "https://github.com/Tomdrouv1/coherent.js",
29
+ "bugs": {
30
+ "url": "https://github.com/Tomdrouv1/coherent.js/issues"
31
+ },
28
32
  "publishConfig": {
29
33
  "access": "public"
30
34
  },
35
+ "engines": {
36
+ "node": ">=20.0.0"
37
+ },
31
38
  "types": "./types/index.d.ts",
32
39
  "files": [
40
+ "dist/",
41
+ "src/",
33
42
  "LICENSE",
34
43
  "README.md",
35
44
  "types/"
package/src/index.js CHANGED
@@ -7,10 +7,18 @@ import { render } from '@coherent.js/core';
7
7
 
8
8
  /**
9
9
  * Define a Coherent.js component as a custom element
10
+ *
11
+ * @param {string} name - Custom element tag name (must contain a hyphen)
12
+ * @param {Function|Object} component - Coherent.js component (function or object)
13
+ * @param {Object} [options] - Configuration options
14
+ * @param {boolean} [options.shadow] - Use Shadow DOM for style encapsulation
15
+ * @param {string[]} [options.observedAttributes] - Attributes to watch for changes
16
+ * @param {Object} [options.defaults] - Default property values
17
+ * @returns {Function|Object} The custom element class, or a server-side placeholder
10
18
  */
11
19
  export function defineComponent(name, component, options = {}) {
12
20
  if (typeof window === 'undefined') {
13
- // Server-side: just return a placeholder
21
+ // Server-side: return a placeholder for SSR
14
22
  return { name, component, options };
15
23
  }
16
24
 
@@ -18,24 +26,104 @@ export function defineComponent(name, component, options = {}) {
18
26
  throw new Error('Custom Elements API not supported');
19
27
  }
20
28
 
29
+ const observedAttrs = options.observedAttributes || [];
30
+ const defaults = options.defaults || {};
31
+
21
32
  class CoherentElement extends HTMLElement {
33
+ static get observedAttributes() {
34
+ return observedAttrs;
35
+ }
36
+
22
37
  constructor() {
23
38
  super();
39
+ this._props = { ...defaults };
40
+ this._connected = false;
24
41
  this.component = component;
25
42
  this.options = options;
26
43
  }
27
44
 
28
45
  connectedCallback() {
29
- this.render();
46
+ this._connected = true;
47
+ // Copy initial attributes to props
48
+ for (const attr of observedAttrs) {
49
+ if (this.hasAttribute(attr)) {
50
+ this._props[attr] = this.getAttribute(attr);
51
+ }
52
+ }
53
+ this._render();
54
+ }
55
+
56
+ disconnectedCallback() {
57
+ this._connected = false;
58
+ // Cleanup: remove event listeners and clear content
59
+ if (options.shadow && this.shadowRoot) {
60
+ this.shadowRoot.innerHTML = '';
61
+ } else {
62
+ this.innerHTML = '';
63
+ }
64
+ }
65
+
66
+ attributeChangedCallback(attrName, oldValue, newValue) {
67
+ if (oldValue === newValue) return;
68
+ this._props[attrName] = newValue;
69
+ if (this._connected) {
70
+ this._render();
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Set a property and re-render
76
+ */
77
+ setProperty(key, value) {
78
+ this._props[key] = value;
79
+ if (this._connected) {
80
+ this._render();
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Get current props
86
+ */
87
+ getProperties() {
88
+ return { ...this._props };
30
89
  }
31
90
 
32
- render() {
33
- const html = render(this.component);
91
+ _render() {
92
+ const componentDef = typeof this.component === 'function'
93
+ ? this.component(this._props)
94
+ : this.component;
95
+
96
+ const html = render(componentDef);
97
+
34
98
  if (this.options.shadow) {
35
- const shadow = this.attachShadow({ mode: 'open' });
36
- shadow.innerHTML = html;
99
+ if (!this.shadowRoot) {
100
+ this.attachShadow({ mode: 'open' });
101
+ }
102
+ this.shadowRoot.innerHTML = html;
103
+ this._delegateEvents(this.shadowRoot);
37
104
  } else {
38
105
  this.innerHTML = html;
106
+ this._delegateEvents(this);
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Delegate data-action events to component handlers
112
+ */
113
+ _delegateEvents(root) {
114
+ const actionElements = root.querySelectorAll('[data-action]');
115
+ for (const el of actionElements) {
116
+ const action = el.dataset.action;
117
+ const [eventType, handlerName] = action.includes(':')
118
+ ? action.split(':')
119
+ : ['click', action];
120
+
121
+ el.addEventListener(eventType, (event) => {
122
+ this.dispatchEvent(new CustomEvent('coherent-action', {
123
+ bubbles: true,
124
+ detail: { action: handlerName, event, element: el }
125
+ }));
126
+ });
39
127
  }
40
128
  }
41
129
  }
@@ -45,7 +133,7 @@ export function defineComponent(name, component, options = {}) {
45
133
  }
46
134
 
47
135
  /**
48
- * Integration utilities
136
+ * Integration utilities for runtime environments
49
137
  */
50
138
  export function integrateWithWebComponents(_runtime) {
51
139
  return {
@@ -53,6 +141,9 @@ export function integrateWithWebComponents(_runtime) {
53
141
  };
54
142
  }
55
143
 
144
+ /**
145
+ * Alias for defineComponent
146
+ */
56
147
  export function defineCoherentElement(name, component, options = {}) {
57
148
  return defineComponent(name, component, options);
58
149
  }
package/types/index.d.ts CHANGED
@@ -3,19 +3,51 @@
3
3
  * @module @coherent.js/web-components
4
4
  */
5
5
 
6
- // ===== Web Component Integration Types =====
6
+ import type { CoherentNode, CoherentComponent, ComponentState, ComponentProps } from '@coherent.js/core';
7
7
 
8
+ // ============================================================================
9
+ // Web Component Configuration
10
+ // ============================================================================
11
+
12
+ /**
13
+ * Property type constructors
14
+ */
15
+ export type PropertyType =
16
+ | StringConstructor
17
+ | NumberConstructor
18
+ | BooleanConstructor
19
+ | ObjectConstructor
20
+ | ArrayConstructor;
21
+
22
+ /**
23
+ * Property definition for web components
24
+ */
25
+ export interface PropertyDefinition {
26
+ /** Property type */
27
+ type?: PropertyType;
28
+ /** Default value */
29
+ default?: unknown;
30
+ /** Whether property is required */
31
+ required?: boolean;
32
+ /** Custom validator */
33
+ validator?: (value: unknown) => boolean;
34
+ }
35
+
36
+ /**
37
+ * Component options for web component registration
38
+ */
8
39
  export interface ComponentOptions {
40
+ /** Use shadow DOM */
9
41
  shadow?: boolean;
42
+ /** Shadow root mode */
10
43
  mode?: 'open' | 'closed';
44
+ /** Delegates focus to shadow root */
11
45
  delegatesFocus?: boolean;
46
+ /** Attributes to observe */
12
47
  observedAttributes?: string[];
13
- props?: Record<string, {
14
- type?: StringConstructor | NumberConstructor | BooleanConstructor | ObjectConstructor | ArrayConstructor;
15
- default?: any;
16
- required?: boolean;
17
- validator?: (value: any) => boolean;
18
- }>;
48
+ /** Property definitions */
49
+ props?: Record<string, PropertyDefinition>;
50
+ /** Lifecycle hooks */
19
51
  lifecycle?: {
20
52
  connected?: () => void;
21
53
  disconnected?: () => void;
@@ -24,19 +56,85 @@ export interface ComponentOptions {
24
56
  };
25
57
  }
26
58
 
59
+ /**
60
+ * Web component configuration
61
+ */
62
+ export interface WebComponentConfig {
63
+ /** Custom element tag name (must contain hyphen) */
64
+ tagName: string;
65
+ /** Coherent.js component */
66
+ component: CoherentComponent;
67
+ /** Attributes to observe */
68
+ observedAttributes?: string[];
69
+ /** Use shadow DOM */
70
+ shadow?: boolean | ShadowRootInit;
71
+ /** Styles to apply */
72
+ styles?: string | string[];
73
+ /** Adopted style sheets */
74
+ adoptedStyleSheets?: CSSStyleSheet[];
75
+ }
76
+
77
+ // ============================================================================
78
+ // Coherent Web Component
79
+ // ============================================================================
80
+
81
+ /**
82
+ * Coherent element constructor
83
+ */
27
84
  export interface CoherentElementConstructor {
28
85
  new (): CoherentElement;
29
86
  prototype: CoherentElement;
30
87
  }
31
88
 
89
+ /**
90
+ * Coherent web component element interface
91
+ */
32
92
  export interface CoherentElement extends HTMLElement {
33
- component: any;
93
+ /** The wrapped component */
94
+ component: CoherentComponent;
95
+ /** Component options */
34
96
  options: ComponentOptions;
97
+
98
+ /** Render the component */
35
99
  render(): void;
36
- update(props?: Record<string, any>): void;
37
- hydrate(data?: any): void;
100
+
101
+ /** Update with new props */
102
+ update(props?: Record<string, unknown>): void;
103
+
104
+ /** Hydrate with server data */
105
+ hydrate(data?: unknown): void;
38
106
  }
39
107
 
108
+ /**
109
+ * Extended coherent web component interface
110
+ */
111
+ export interface CoherentWebComponent extends HTMLElement {
112
+ /** Component instance reference */
113
+ readonly componentInstance: unknown;
114
+ /** Current props */
115
+ props: Record<string, unknown>;
116
+ /** Current state */
117
+ state: ComponentState;
118
+
119
+ /** Called when element is added to DOM */
120
+ connectedCallback(): void;
121
+ /** Called when element is removed from DOM */
122
+ disconnectedCallback(): void;
123
+ /** Called when an observed attribute changes */
124
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
125
+ /** Called when element is moved to a new document */
126
+ adoptedCallback(): void;
127
+
128
+ /** Update component state */
129
+ setState(updates: Partial<ComponentState>): void;
130
+ /** Force a re-render */
131
+ forceUpdate(): void;
132
+ }
133
+
134
+ // ============================================================================
135
+ // Registration Functions
136
+ // ============================================================================
137
+
40
138
  /**
41
139
  * Define a Coherent.js component as a custom element
42
140
  *
@@ -53,14 +151,14 @@ export interface CoherentElement extends HTMLElement {
53
151
  */
54
152
  export function defineComponent(
55
153
  name: string,
56
- component: any | ((props: any) => any),
154
+ component: CoherentComponent | CoherentNode,
57
155
  options?: ComponentOptions
58
156
  ): CoherentElementConstructor;
59
157
 
60
158
  /**
61
- * Integration utilities for web components runtime
159
+ * Define a web component with full configuration
62
160
  */
63
- export function integrateWithWebComponents(runtime: any): void;
161
+ export function defineWebComponent(config: WebComponentConfig): typeof CoherentWebComponent;
64
162
 
65
163
  /**
66
164
  * Register multiple components at once
@@ -73,7 +171,30 @@ export function integrateWithWebComponents(runtime: any): void;
73
171
  * });
74
172
  * ```
75
173
  */
76
- export function registerComponents(components: Record<string, any>, options?: ComponentOptions): void;
174
+ export function registerComponents(
175
+ components: Record<string, CoherentComponent | CoherentNode>,
176
+ options?: ComponentOptions
177
+ ): void;
178
+
179
+ /**
180
+ * Register web components with full configuration
181
+ */
182
+ export function registerWebComponents(
183
+ components: Record<string, WebComponentConfig>
184
+ ): void;
185
+
186
+ /**
187
+ * Create a custom element class from a component
188
+ */
189
+ export function createCustomElement(
190
+ component: CoherentComponent,
191
+ options?: Partial<WebComponentConfig>
192
+ ): typeof CoherentWebComponent;
193
+
194
+ /**
195
+ * Integration utilities for web components runtime
196
+ */
197
+ export function integrateWithWebComponents(runtime: unknown): void;
77
198
 
78
199
  /**
79
200
  * Check if a custom element is defined
@@ -93,19 +214,31 @@ export function upgradeElement(element: Element): void;
93
214
  /**
94
215
  * Create a Coherent.js component from a custom element
95
216
  */
96
- export function fromCustomElement(element: HTMLElement): any;
217
+ export function fromCustomElement(element: HTMLElement): CoherentNode;
218
+
219
+ // ============================================================================
220
+ // Property Decorators
221
+ // ============================================================================
97
222
 
98
223
  /**
99
- * Helper for creating reactive properties on custom elements
224
+ * Property declaration for decorators
100
225
  */
101
226
  export interface PropertyDeclaration {
102
- type?: StringConstructor | NumberConstructor | BooleanConstructor | ObjectConstructor | ArrayConstructor;
227
+ /** Property type */
228
+ type?: PropertyType;
229
+ /** Sync with attribute */
103
230
  attribute?: boolean | string;
231
+ /** Reflect to attribute */
104
232
  reflect?: boolean;
105
- converter?: (value: string) => any;
106
- default?: any;
233
+ /** Custom converter from attribute string */
234
+ converter?: (value: string) => unknown;
235
+ /** Default value */
236
+ default?: unknown;
107
237
  }
108
238
 
239
+ /**
240
+ * Create a property definition
241
+ */
109
242
  export function createProperty(declaration: PropertyDeclaration): PropertyDecorator;
110
243
 
111
244
  /**
@@ -120,56 +253,141 @@ export function property(declaration?: PropertyDeclaration): PropertyDecorator;
120
253
  */
121
254
  export function customElement(tagName: string): ClassDecorator;
122
255
 
123
- // ===== Event System Types =====
256
+ // ============================================================================
257
+ // Event System
258
+ // ============================================================================
124
259
 
260
+ /**
261
+ * Custom event options
262
+ */
125
263
  export interface EventOptions {
264
+ /** Whether event bubbles */
126
265
  bubbles?: boolean;
266
+ /** Whether event is composed (crosses shadow boundary) */
127
267
  composed?: boolean;
268
+ /** Whether event is cancelable */
128
269
  cancelable?: boolean;
129
- detail?: any;
270
+ /** Event detail data */
271
+ detail?: unknown;
130
272
  }
131
273
 
274
+ /**
275
+ * Create a custom event
276
+ */
132
277
  export function createEvent(type: string, options?: EventOptions): CustomEvent;
133
- export function dispatchCustomEvent(element: Element, type: string, options?: EventOptions): boolean;
134
278
 
135
- // ===== Slot Utilities Types =====
279
+ /**
280
+ * Dispatch a custom event on an element
281
+ */
282
+ export function dispatchCustomEvent(
283
+ element: Element,
284
+ type: string,
285
+ options?: EventOptions
286
+ ): boolean;
136
287
 
288
+ // ============================================================================
289
+ // Slot Utilities
290
+ // ============================================================================
291
+
292
+ /**
293
+ * Slot change event interface
294
+ */
137
295
  export interface SlotChangeEvent extends Event {
138
296
  target: HTMLSlotElement;
139
297
  }
140
298
 
299
+ /**
300
+ * Get slotted content
301
+ */
141
302
  export function getSlotContent(element: Element, slotName?: string): Node[];
303
+
304
+ /**
305
+ * Check if slot has content
306
+ */
142
307
  export function hasSlotContent(element: Element, slotName?: string): boolean;
143
- export function onSlotChange(element: Element, callback: (event: SlotChangeEvent) => void, slotName?: string): () => void;
144
308
 
145
- // ===== Shadow DOM Utilities Types =====
309
+ /**
310
+ * Listen for slot changes
311
+ */
312
+ export function onSlotChange(
313
+ element: Element,
314
+ callback: (event: SlotChangeEvent) => void,
315
+ slotName?: string
316
+ ): () => void;
146
317
 
318
+ // ============================================================================
319
+ // Shadow DOM Utilities
320
+ // ============================================================================
321
+
322
+ /**
323
+ * Shadow root initialization options
324
+ */
147
325
  export interface ShadowRootInit {
326
+ /** Shadow mode */
148
327
  mode: 'open' | 'closed';
328
+ /** Delegates focus */
149
329
  delegatesFocus?: boolean;
330
+ /** Slot assignment mode */
150
331
  slotAssignment?: 'manual' | 'named';
151
332
  }
152
333
 
334
+ /**
335
+ * Create a shadow root
336
+ */
153
337
  export function createShadowRoot(element: Element, init: ShadowRootInit): ShadowRoot;
338
+
339
+ /**
340
+ * Adopt styles into a shadow root
341
+ */
154
342
  export function adoptStyles(shadowRoot: ShadowRoot, styles: string | CSSStyleSheet[]): void;
343
+
344
+ /**
345
+ * Get an element's shadow root
346
+ */
155
347
  export function getShadowRoot(element: Element): ShadowRoot | null;
156
348
 
157
- // ===== Template Utilities Types =====
349
+ // ============================================================================
350
+ // Template Utilities
351
+ // ============================================================================
158
352
 
353
+ /**
354
+ * Create a template element from HTML
355
+ */
159
356
  export function createTemplate(html: string): HTMLTemplateElement;
357
+
358
+ /**
359
+ * Clone a template's content
360
+ */
160
361
  export function cloneTemplate(template: HTMLTemplateElement): DocumentFragment;
161
- export function renderToTemplate(component: any): HTMLTemplateElement;
162
362
 
163
- // ===== Lifecycle Hooks =====
363
+ /**
364
+ * Render a component to a template
365
+ */
366
+ export function renderToTemplate(component: CoherentNode): HTMLTemplateElement;
367
+
368
+ // ============================================================================
369
+ // Lifecycle Hooks
370
+ // ============================================================================
164
371
 
372
+ /**
373
+ * Lifecycle hook definitions
374
+ */
165
375
  export interface LifecycleHooks {
376
+ /** Called when element is added to DOM */
166
377
  onConnected?: () => void;
378
+ /** Called when element is removed from DOM */
167
379
  onDisconnected?: () => void;
380
+ /** Called when element is moved to new document */
168
381
  onAdopted?: () => void;
382
+ /** Called when observed attribute changes */
169
383
  onAttributeChanged?: (name: string, oldValue: string | null, newValue: string | null) => void;
170
- onPropertyChanged?: (name: string, oldValue: any, newValue: any) => void;
384
+ /** Called when a property changes */
385
+ onPropertyChanged?: (name: string, oldValue: unknown, newValue: unknown) => void;
171
386
  }
172
387
 
388
+ /**
389
+ * Create a lifecycle manager
390
+ */
173
391
  export function createLifecycleManager(hooks: LifecycleHooks): {
174
392
  connected(): void;
175
393
  disconnected(): void;