coralite 0.36.2 → 0.37.0

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.
Files changed (96) hide show
  1. package/README.md +4 -4
  2. package/bin/coralite.js +3 -3
  3. package/dist/lib/collection-handlers.d.ts +29 -0
  4. package/dist/lib/collection-handlers.d.ts.map +1 -0
  5. package/dist/lib/collection.d.ts +3 -3
  6. package/dist/lib/collection.d.ts.map +1 -1
  7. package/dist/lib/compiler.d.ts +103 -0
  8. package/dist/lib/compiler.d.ts.map +1 -0
  9. package/dist/lib/component-setup.d.ts +37 -0
  10. package/dist/lib/component-setup.d.ts.map +1 -0
  11. package/dist/lib/config.d.ts +0 -3
  12. package/dist/lib/config.d.ts.map +1 -1
  13. package/dist/lib/coralite-element.d.ts +6 -5
  14. package/dist/lib/coralite-element.d.ts.map +1 -1
  15. package/dist/lib/coralite-element.js +63 -486
  16. package/dist/lib/coralite-element.js.map +4 -4
  17. package/dist/lib/coralite.d.ts +10 -709
  18. package/dist/lib/coralite.d.ts.map +1 -1
  19. package/dist/lib/hooks.d.ts +59 -0
  20. package/dist/lib/hooks.d.ts.map +1 -0
  21. package/dist/lib/index.d.ts +7 -9
  22. package/dist/lib/index.d.ts.map +1 -1
  23. package/dist/lib/index.js +4951 -4264
  24. package/dist/lib/index.js.map +4 -4
  25. package/dist/lib/parser.d.ts +46 -0
  26. package/dist/lib/parser.d.ts.map +1 -0
  27. package/dist/lib/plugin-setup.d.ts +26 -0
  28. package/dist/lib/plugin-setup.d.ts.map +1 -0
  29. package/dist/lib/plugin.d.ts.map +1 -1
  30. package/dist/lib/renderer.d.ts +46 -0
  31. package/dist/lib/renderer.d.ts.map +1 -0
  32. package/dist/lib/script-manager.d.ts +25 -18
  33. package/dist/lib/script-manager.d.ts.map +1 -1
  34. package/dist/lib/{client-runtime.d.ts → utils/client/runtime.d.ts} +2 -2
  35. package/dist/lib/utils/client/runtime.d.ts.map +1 -0
  36. package/dist/lib/{utils.d.ts → utils/core.d.ts} +9 -60
  37. package/dist/lib/utils/core.d.ts.map +1 -0
  38. package/dist/lib/utils/errors.d.ts +56 -0
  39. package/dist/lib/utils/errors.d.ts.map +1 -0
  40. package/dist/lib/utils/index.d.ts +5 -0
  41. package/dist/lib/utils/index.d.ts.map +1 -0
  42. package/dist/lib/{dom.d.ts → utils/server/dom.d.ts} +21 -10
  43. package/dist/lib/utils/server/dom.d.ts.map +1 -0
  44. package/dist/lib/utils/server/errors.d.ts +15 -0
  45. package/dist/lib/utils/server/errors.d.ts.map +1 -0
  46. package/dist/lib/{html.d.ts → utils/server/html.d.ts} +12 -10
  47. package/dist/lib/utils/server/html.d.ts.map +1 -0
  48. package/dist/lib/utils/server/index.d.ts +9 -0
  49. package/dist/lib/utils/server/index.d.ts.map +1 -0
  50. package/dist/lib/utils/server/manifest.d.ts +32 -0
  51. package/dist/lib/utils/server/manifest.d.ts.map +1 -0
  52. package/dist/lib/{parse.d.ts → utils/server/parse.d.ts} +9 -9
  53. package/dist/lib/utils/server/parse.d.ts.map +1 -0
  54. package/dist/lib/{render-helpers.d.ts → utils/server/render.d.ts} +7 -7
  55. package/dist/lib/utils/server/render.d.ts.map +1 -0
  56. package/dist/lib/utils/server/server.d.ts +56 -0
  57. package/dist/lib/utils/server/server.d.ts.map +1 -0
  58. package/dist/lib/{style-transform.d.ts → utils/server/style.d.ts} +7 -3
  59. package/dist/lib/utils/server/style.d.ts.map +1 -0
  60. package/dist/lib/utils/tags.d.ts.map +1 -0
  61. package/dist/lib/{type-helper.d.ts → utils/types.d.ts} +10 -10
  62. package/dist/lib/utils/types.d.ts.map +1 -0
  63. package/dist/plugins/index.d.ts +0 -1
  64. package/dist/plugins/metadata.d.ts.map +1 -1
  65. package/dist/plugins/static-assets.d.ts +2 -1
  66. package/dist/plugins/static-assets.d.ts.map +1 -1
  67. package/dist/types/collection.d.ts +42 -0
  68. package/dist/types/collection.d.ts.map +1 -1
  69. package/dist/types/core.d.ts +226 -4
  70. package/dist/types/core.d.ts.map +1 -1
  71. package/dist/types/dom.d.ts +92 -14
  72. package/dist/types/dom.d.ts.map +1 -1
  73. package/dist/types/index.d.ts +7 -68
  74. package/dist/types/index.d.ts.map +1 -1
  75. package/dist/types/module.d.ts +4 -0
  76. package/dist/types/module.d.ts.map +1 -1
  77. package/dist/types/plugin.d.ts +314 -53
  78. package/dist/types/plugin.d.ts.map +1 -1
  79. package/dist/types/script.d.ts +12 -11
  80. package/dist/types/script.d.ts.map +1 -1
  81. package/llms.txt +234 -25
  82. package/package.json +20 -3
  83. package/dist/lib/client-runtime.d.ts.map +0 -1
  84. package/dist/lib/dom.d.ts.map +0 -1
  85. package/dist/lib/errors.d.ts +0 -16
  86. package/dist/lib/errors.d.ts.map +0 -1
  87. package/dist/lib/html.d.ts.map +0 -1
  88. package/dist/lib/parse.d.ts.map +0 -1
  89. package/dist/lib/render-helpers.d.ts.map +0 -1
  90. package/dist/lib/style-transform.d.ts.map +0 -1
  91. package/dist/lib/tags.d.ts.map +0 -1
  92. package/dist/lib/type-helper.d.ts.map +0 -1
  93. package/dist/lib/utils.d.ts.map +0 -1
  94. package/dist/plugins/refs.d.ts +0 -5
  95. package/dist/plugins/refs.d.ts.map +0 -1
  96. /package/dist/lib/{tags.d.ts → utils/tags.d.ts} +0 -0
@@ -1,483 +1,35 @@
1
- // lib/utils.js
2
- import { parse as parseJS } from "acorn";
3
- import { simple as walkJS } from "acorn-walk";
4
- import render from "dom-serializer";
5
- import { sanitize } from "isomorphic-dompurify";
6
-
7
- // lib/parse.js
8
- import { Parser } from "htmlparser2";
9
-
10
- // lib/dom.js
11
- var ELEMENT_NODE = 1;
12
- var TEXT_NODE = 3;
13
- var COMMENT_NODE = 8;
14
- var DOCUMENT_NODE = 9;
15
- var DOCUMENT_TYPE_NODE = 10;
16
- var nodeTypes = {
17
- tag: ELEMENT_NODE,
18
- script: ELEMENT_NODE,
19
- style: ELEMENT_NODE,
20
- text: TEXT_NODE,
21
- comment: COMMENT_NODE,
22
- root: DOCUMENT_NODE,
23
- directive: DOCUMENT_TYPE_NODE
24
- };
25
- function CoraliteNodeConstructor(node) {
26
- for (const key in node) {
27
- if (["parent", "prev", "next", "slots"].includes(key)) {
28
- Object.defineProperty(this, key, {
29
- value: node[key],
30
- enumerable: false,
31
- writable: true,
32
- configurable: true
33
- });
34
- } else {
35
- this[key] = node[key];
36
- }
37
- }
38
- }
39
- function makeCircularPropertiesNonEnumerable(node) {
40
- for (const key of ["parent", "prev", "next", "slots"]) {
41
- if (Object.hasOwn(node, key)) {
42
- const value = node[key];
43
- delete node[key];
44
- Object.defineProperty(node, key, {
45
- value,
46
- enumerable: false,
47
- writable: true,
48
- configurable: true
49
- });
50
- }
51
- }
52
- }
53
- Object.defineProperties(CoraliteNodeConstructor.prototype, {
54
- nodeType: {
55
- /**
56
- * Returns an integer identifying the type of the node.
57
- * @returns {number}
58
- */
59
- get() {
60
- return nodeTypes[this.type] || ELEMENT_NODE;
61
- }
62
- },
63
- parentNode: {
64
- /**
65
- * Returns the parent of the specified node in the DOM tree.
66
- * @returns {CoraliteAnyNode | CoraliteComponentRoot}
67
- */
68
- get() {
69
- return this.parent;
70
- },
71
- /**
72
- * Sets the parent of the node.
73
- * @param {CoraliteAnyNode | CoraliteComponentRoot} value - The parent node to set
74
- */
75
- set(value) {
76
- this.parent = value;
77
- }
78
- },
79
- parentElement: {
80
- /**
81
- * Returns the DOM node's parent Element, or null if the node either has no parent, or its parent isn't a DOM Element.
82
- * @returns {CoraliteAnyNode | CoraliteComponentRoot}
83
- */
84
- get() {
85
- return this.parent;
86
- },
87
- /**
88
- * Sets the parent element of the node.
89
- * @param {CoraliteAnyNode | CoraliteComponentRoot} value - The parent element to set
90
- */
91
- set(value) {
92
- this.parent = value;
93
- }
94
- },
95
- previousSibling: {
96
- /**
97
- * Returns the node immediately preceding the specified one in its parent's childNodes list, or null if the specified node is the first in that list.
98
- * @returns {CoraliteAnyNode | null}
99
- */
100
- get() {
101
- if (!this.parent || !this.parent.children) {
102
- return null;
103
- }
104
- const index = this.parent.children.indexOf(this);
105
- return index > 0 ? this.parent.children[index - 1] : null;
106
- }
107
- },
108
- nextSibling: {
109
- /**
110
- * Returns the node immediately following the specified one in its parent's childNodes list, or null if the specified node is the last node in that list.
111
- * @returns {CoraliteAnyNode | null}
112
- */
113
- get() {
114
- if (!this.parent || !this.parent.children) {
115
- return null;
116
- }
117
- const index = this.parent.children.indexOf(this);
118
- return index > -1 && index < this.parent.children.length - 1 ? this.parent.children[index + 1] : null;
119
- }
120
- }
121
- });
122
- function CoraliteElementConstructor(node) {
123
- CoraliteNodeConstructor.call(this, node);
124
- }
125
- CoraliteElementConstructor.prototype = Object.create(CoraliteNodeConstructor.prototype);
126
- CoraliteElementConstructor.prototype.constructor = CoraliteElementConstructor;
127
- Object.defineProperties(CoraliteElementConstructor.prototype, {
128
- nodeName: {
129
- /**
130
- * Returns the name of the node (uppercase tag name for elements).
131
- * @returns {string}
132
- */
133
- get() {
134
- return this.name.toUpperCase();
135
- }
136
- },
137
- tagName: {
138
- /**
139
- * Returns the tag name of the element (uppercase).
140
- * @returns {string}
141
- */
142
- get() {
143
- return this.name.toUpperCase();
144
- },
145
- /**
146
- * Sets the tag name of the element (converted to lowercase).
147
- * @param {string} value - The tag name to set
148
- */
149
- set(value) {
150
- this.name = value.toLowerCase();
151
- }
152
- },
153
- nodeValue: {
154
- /**
155
- * Returns null for elements.
156
- * @returns {null}
157
- */
158
- get() {
159
- return null;
160
- },
161
- /**
162
- * Setting nodeValue on an element has no effect.
163
- */
164
- set(value) {
165
- }
166
- },
167
- attributes: {
168
- /**
169
- * Returns a collection of the element's attributes.
170
- * @returns {Object.<string, string>}
171
- */
172
- get() {
173
- return this.attribs;
174
- },
175
- /**
176
- * Sets the attributes of the element.
177
- * @param {Object.<string, string>} value - The attributes object to set
178
- */
179
- set(value) {
180
- this.attribs = value;
181
- }
182
- },
183
- childNodes: {
184
- /**
185
- * Returns a live collection of child nodes of the given element.
186
- * @returns {CoraliteAnyNode[]}
187
- */
188
- get() {
189
- return this.children || [];
190
- },
191
- /**
192
- * Sets the child nodes of the element.
193
- * @param {CoraliteAnyNode[]} value - The array of child nodes to set
194
- */
195
- set(value) {
196
- this.children = value;
197
- }
198
- },
199
- firstChild: {
200
- /**
201
- * Returns the node's first child in the tree, or null if the node has no children.
202
- * @returns {CoraliteAnyNode | null}
203
- */
204
- get() {
205
- return this.children && this.children.length > 0 ? this.children[0] : null;
206
- }
207
- },
208
- lastChild: {
209
- /**
210
- * Returns the last child of the node, or null if there are no child nodes.
211
- * @returns {CoraliteAnyNode | null}
212
- */
213
- get() {
214
- return this.children && this.children.length > 0 ? this.children[this.children.length - 1] : null;
215
- }
216
- },
217
- textContent: {
218
- /**
219
- * Returns the text content of the node and its descendants.
220
- * @returns {string}
221
- */
222
- get() {
223
- if (this.children) {
224
- return this.children.map((child) => child.textContent).join("");
225
- }
226
- return "";
227
- },
228
- /**
229
- * Sets the text content of the node. Replaces all children with a single text node.
230
- * @param {string} value - The text content to set
231
- */
232
- set(value) {
233
- const textNode = createCoraliteTextNode({
234
- type: "text",
235
- data: value,
236
- parent: this
237
- });
238
- this.children = [textNode];
239
- }
240
- },
241
- id: {
242
- /**
243
- * Returns the element's ID attribute.
244
- * @returns {string}
245
- */
246
- get() {
247
- return this.attribs ? this.attribs.id : "";
248
- },
249
- /**
250
- * Sets the element's ID attribute.
251
- * @param {string} value - The ID to set
252
- */
253
- set(value) {
254
- if (this.attribs) {
255
- this.attribs.id = value;
256
- }
257
- }
258
- },
259
- className: {
260
- /**
261
- * Returns the element's class attribute.
262
- * @returns {string}
263
- */
264
- get() {
265
- return this.attribs ? this.attribs.class : "";
266
- },
267
- /**
268
- * Sets the element's class attribute.
269
- * @param {string} value - The class names to set
270
- */
271
- set(value) {
272
- if (this.attribs) {
273
- this.attribs.class = value;
274
- }
275
- }
276
- }
277
- });
278
- function CoraliteTextNodeConstructor(node) {
279
- CoraliteNodeConstructor.call(this, node);
280
- }
281
- CoraliteTextNodeConstructor.prototype = Object.create(CoraliteNodeConstructor.prototype);
282
- CoraliteTextNodeConstructor.prototype.constructor = CoraliteTextNodeConstructor;
283
- Object.defineProperties(CoraliteTextNodeConstructor.prototype, {
284
- nodeName: {
285
- /**
286
- * Returns the name of the node (#text).
287
- * @returns {string}
288
- */
289
- get() {
290
- return "#text";
291
- }
292
- },
293
- nodeValue: {
294
- /**
295
- * Returns the text content of the node.
296
- * @returns {string}
297
- */
298
- get() {
299
- return this.data;
300
- },
301
- /**
302
- * Sets the text content of the node.
303
- * @param {string} value - The text content to set
304
- */
305
- set(value) {
306
- this.data = value;
307
- }
308
- },
309
- textContent: {
310
- /**
311
- * Returns the text content of the node.
312
- * @returns {string}
313
- */
314
- get() {
315
- return this.data;
316
- },
317
- /**
318
- * Sets the text content of the node.
319
- * @param {string} value - The text content to set
320
- */
321
- set(value) {
322
- this.data = value;
323
- }
324
- }
325
- });
326
- function createCoraliteTextNode(node) {
327
- makeCircularPropertiesNonEnumerable(node);
328
- Object.setPrototypeOf(node, CoraliteTextNodeConstructor.prototype);
329
- return node;
330
- }
331
- function CoraliteCommentConstructor(node) {
332
- CoraliteNodeConstructor.call(this, node);
333
- }
334
- CoraliteCommentConstructor.prototype = Object.create(CoraliteNodeConstructor.prototype);
335
- CoraliteCommentConstructor.prototype.constructor = CoraliteCommentConstructor;
336
- Object.defineProperties(CoraliteCommentConstructor.prototype, {
337
- nodeName: {
338
- /**
339
- * Returns the name of the node (#comment).
340
- * @returns {string}
341
- */
342
- get() {
343
- return "#comment";
344
- }
345
- },
346
- nodeValue: {
347
- /**
348
- * Returns the content of the comment.
349
- * @returns {string}
350
- */
351
- get() {
352
- return this.data;
353
- },
354
- /**
355
- * Sets the content of the comment.
356
- * @param {string} value - The content to set
357
- */
358
- set(value) {
359
- this.data = value;
360
- }
361
- },
362
- textContent: {
363
- /**
364
- * Returns the content of the comment.
365
- * @returns {string}
366
- */
367
- get() {
368
- return this.data;
369
- },
370
- /**
371
- * Sets the content of the comment.
372
- * @param {string} value - The content to set
373
- */
374
- set(value) {
375
- this.data = value;
376
- }
377
- }
378
- });
379
- function CoraliteDirectiveConstructor(node) {
380
- CoraliteNodeConstructor.call(this, node);
381
- }
382
- CoraliteDirectiveConstructor.prototype = Object.create(CoraliteNodeConstructor.prototype);
383
- CoraliteDirectiveConstructor.prototype.constructor = CoraliteDirectiveConstructor;
384
- Object.defineProperties(CoraliteDirectiveConstructor.prototype, {
385
- nodeName: {
386
- /**
387
- * Returns the name of the directive (e.g., !DOCTYPE).
388
- * @returns {string}
389
- */
390
- get() {
391
- return this.name;
392
- }
393
- },
394
- nodeValue: {
395
- /**
396
- * Returns the content of the directive.
397
- * @returns {string}
398
- */
399
- get() {
400
- return this.data;
401
- },
402
- /**
403
- * Sets the content of the directive.
404
- * @param {string} value - The content to set
405
- */
406
- set(value) {
407
- this.data = value;
408
- }
409
- }
410
- });
411
- function CoraliteComponentConstructor(node) {
412
- CoraliteNodeConstructor.call(this, node);
413
- }
414
- CoraliteComponentConstructor.prototype = Object.create(CoraliteNodeConstructor.prototype);
415
- CoraliteComponentConstructor.prototype.constructor = CoraliteComponentConstructor;
416
- Object.defineProperties(CoraliteComponentConstructor.prototype, {
417
- nodeName: {
418
- /**
419
- * Returns the name of the node (#document).
420
- * @returns {string}
421
- */
422
- get() {
423
- return "#document";
424
- }
425
- },
426
- nodeValue: {
427
- /**
428
- * Returns null for document nodes.
429
- * @returns {null}
430
- */
431
- get() {
432
- return null;
433
- }
434
- },
435
- childNodes: {
436
- /**
437
- * Returns a live collection of child nodes of the document.
438
- * @returns {CoraliteAnyNode[]}
439
- */
440
- get() {
441
- return this.children || [];
442
- },
443
- /**
444
- * Sets the child nodes of the document.
445
- * @param {CoraliteAnyNode[]} value - The array of child nodes to set
446
- */
447
- set(value) {
448
- this.children = value;
449
- }
450
- },
451
- firstChild: {
452
- /**
453
- * Returns the document's first child in the tree, or null if the document has no children.
454
- * @returns {CoraliteAnyNode | null}
455
- */
456
- get() {
457
- return this.children && this.children.length > 0 ? this.children[0] : null;
458
- }
459
- },
460
- lastChild: {
461
- /**
462
- * Returns the last child of the document, or null if there are no child nodes.
463
- * @returns {CoraliteAnyNode | null}
464
- */
465
- get() {
466
- return this.children && this.children.length > 0 ? this.children[this.children.length - 1] : null;
467
- }
468
- },
469
- textContent: {
470
- /**
471
- * Returns null for document nodes.
472
- * @returns {null}
473
- */
474
- get() {
475
- return null;
1
+ // lib/utils/errors.js
2
+ var CoraliteError = class extends Error {
3
+ /**
4
+ * @param {string} message - The error message.
5
+ * @param {Object} [options] - Additional options for the error.
6
+ * @param {string} [options.componentId] - The ID of the component where the error occurred.
7
+ * @param {string} [options.filePath] - The path to the file where the error occurred.
8
+ * @param {string} [options.instanceId] - The unique ID of the component instance.
9
+ * @param {string} [options.pagePath] - The path to the page being rendered.
10
+ * @param {number} [options.line] - The line number where the error occurred.
11
+ * @param {number} [options.column] - The column number where the error occurred.
12
+ * @param {string} [options.stackFile] - The file name from the stack trace.
13
+ * @param {Error} [options.cause] - The original error that caused this error.
14
+ */
15
+ constructor(message, options = {}) {
16
+ super(message, options);
17
+ this.name = "CoraliteError";
18
+ this.isCoraliteError = true;
19
+ this.componentId = options.componentId;
20
+ this.filePath = options.filePath;
21
+ this.instanceId = options.instanceId;
22
+ this.pagePath = options.pagePath;
23
+ this.line = options.line;
24
+ this.column = options.column;
25
+ this.stackFile = options.stackFile;
26
+ if (options.cause && !this.cause) {
27
+ this.cause = options.cause;
476
28
  }
477
29
  }
478
- });
30
+ };
479
31
 
480
- // lib/utils.js
32
+ // lib/utils/core.js
481
33
  function createReadOnlyProxy(target, proxies = /* @__PURE__ */ new WeakMap()) {
482
34
  if (proxies.has(target)) {
483
35
  return proxies.get(target);
@@ -491,10 +43,10 @@ function createReadOnlyProxy(target, proxies = /* @__PURE__ */ new WeakMap()) {
491
43
  return value;
492
44
  },
493
45
  set() {
494
- throw new Error("Coralite Error: Cannot mutate state inside a getter. State is read-only here.");
46
+ throw new CoraliteError("Cannot mutate state inside a getter. State is read-only here.");
495
47
  },
496
48
  deleteProperty() {
497
- throw new Error("Coralite Error: Cannot delete state inside a getter. State is read-only here.");
49
+ throw new CoraliteError("Cannot delete state inside a getter. State is read-only here.");
498
50
  }
499
51
  };
500
52
  const proxy = new Proxy(target, handler);
@@ -503,7 +55,7 @@ function createReadOnlyProxy(target, proxies = /* @__PURE__ */ new WeakMap()) {
503
55
  }
504
56
 
505
57
  // lib/coralite-element.js
506
- var BOOLEAN_ATTRIBUTES2 = /* @__PURE__ */ new Set([
58
+ var BOOLEAN_ATTRIBUTES = /* @__PURE__ */ new Set([
507
59
  "allowfullscreen",
508
60
  "async",
509
61
  "autofocus",
@@ -619,6 +171,7 @@ var CoraliteElement = class extends HTMLElement {
619
171
  * Invoked natively when the element is removed from the document.
620
172
  * Aborts pending requests and triggers `onDisconnected` plugin hooks
621
173
  * to ensure external libraries (e.g., Observers) do not cause memory leaks.
174
+ * @this {any}
622
175
  */
623
176
  disconnectedCallback() {
624
177
  if (this._abortController) {
@@ -658,6 +211,7 @@ var CoraliteElement = class extends HTMLElement {
658
211
  * Constructs the unified state object.
659
212
  * Merges `defaultValues`, JSON hydration payloads, and DOM attributes.
660
213
  * Defines getters (wrapping state in a Read-Only proxy) and applies the final Read/Write Proxy.
214
+ * @this {any}
661
215
  * @private
662
216
  */
663
217
  _setupState() {
@@ -665,11 +219,18 @@ var CoraliteElement = class extends HTMLElement {
665
219
  const target = { ...options.defaultValues };
666
220
  const refs = [];
667
221
  if (options.hydrationMap && options.hydrationMap.refs) {
668
- for (const item of options.hydrationMap.refs) {
669
- const node = this.getNodeByPath(item.path);
222
+ for (const ref of options.hydrationMap.refs) {
223
+ const uniqueRefValue = `${this._instanceId}__${ref.name}`;
224
+ if (!target[`ref_${ref.name}`]) {
225
+ target[`ref_${ref.name}`] = uniqueRefValue;
226
+ }
227
+ const node = this.getNodeByPath(ref.path);
670
228
  if (node) {
229
+ if (node.setAttribute) {
230
+ node.setAttribute("ref", uniqueRefValue);
231
+ }
671
232
  refs.push({
672
- name: item.name,
233
+ name: ref.name,
673
234
  element: node
674
235
  });
675
236
  }
@@ -692,7 +253,7 @@ var CoraliteElement = class extends HTMLElement {
692
253
  if (allData[this._instanceId]) {
693
254
  Object.assign(target, allData[this._instanceId]);
694
255
  }
695
- } catch (e) {
256
+ } catch {
696
257
  console.error("Coralite Element hydration failed:", this._instanceId);
697
258
  }
698
259
  }
@@ -814,6 +375,7 @@ var CoraliteElement = class extends HTMLElement {
814
375
  * **Async Safety:** Implements a Symbol-based locking mechanism (`renderVersion`)
815
376
  * to guarantee that if state mutates while an async getter is pending, the stale
816
377
  * Promise will be discarded, preventing DOM race conditions.
378
+ * @this {any}
817
379
  * @private
818
380
  */
819
381
  _updateDOM() {
@@ -857,7 +419,7 @@ var CoraliteElement = class extends HTMLElement {
857
419
  }
858
420
  } else if (binding.type === "attribute") {
859
421
  const element = binding.node;
860
- if (BOOLEAN_ATTRIBUTES2.has(binding.name)) {
422
+ if (BOOLEAN_ATTRIBUTES.has(binding.name)) {
861
423
  const isFalsy = hydratedValue === "" || hydratedValue === "false" || hydratedValue === "null" || hydratedValue === "0" || hydratedValue === "undefined";
862
424
  if (isFalsy) {
863
425
  element.removeAttribute(binding.name);
@@ -919,6 +481,13 @@ var CoraliteElement = class extends HTMLElement {
919
481
  slotEl._originalNodes = Array.from(slotEl.childNodes).map((n) => n.cloneNode(true));
920
482
  }
921
483
  const result = slotFn(slotEl._originalNodes, this._state);
484
+ if (result === void 0) {
485
+ return;
486
+ }
487
+ if (result === null || result === "" || Array.isArray(result) && result.length === 0) {
488
+ slotEl.innerHTML = "";
489
+ return;
490
+ }
922
491
  if (typeof result === "string") {
923
492
  slotEl.innerHTML = result;
924
493
  } else if (Array.isArray(result)) {
@@ -935,11 +504,19 @@ var CoraliteElement = class extends HTMLElement {
935
504
  * @private
936
505
  */
937
506
  async _init(isImperative = false) {
507
+ const self = this;
938
508
  const localContext = {
939
509
  instanceId: this._instanceId,
940
510
  state: this._state,
941
511
  root: this,
942
- signal: this._abortController.signal
512
+ signal: this._abortController.signal,
513
+ refs(id) {
514
+ const refId = self._state[`ref_${id}`];
515
+ if (!refId && typeof refId !== "string") {
516
+ return null;
517
+ }
518
+ return self.querySelector(`[ref="${refId}"]`);
519
+ }
943
520
  };
944
521
  if (typeof this._clientContextGetter === "function") {
945
522
  const pluginContext = await this._clientContextGetter(localContext);