elit 3.6.5 → 3.6.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.
Files changed (154) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/README.md +6 -0
  4. package/dist/build.cjs +421 -331
  5. package/dist/build.d.ts +1 -16
  6. package/dist/build.js +420 -330
  7. package/dist/build.mjs +420 -330
  8. package/dist/chokidar.cjs +219 -182
  9. package/dist/chokidar.d.ts +25 -10
  10. package/dist/chokidar.js +217 -182
  11. package/dist/chokidar.mjs +218 -183
  12. package/dist/cli.cjs +21608 -20241
  13. package/dist/cli.d.ts +19 -37
  14. package/dist/cli.mjs +21262 -19910
  15. package/dist/config.cjs +357 -350
  16. package/dist/config.d.ts +19 -240
  17. package/dist/config.js +520 -515
  18. package/dist/config.mjs +346 -341
  19. package/dist/contracts-BeW9k0yZ.d.ts +54 -0
  20. package/dist/contracts-D7KIS-TK.d.ts +36 -0
  21. package/dist/coverage.cjs +448 -485
  22. package/dist/coverage.d.ts +13 -59
  23. package/dist/coverage.js +447 -484
  24. package/dist/coverage.mjs +447 -484
  25. package/dist/database.cjs +819 -828
  26. package/dist/database.d.ts +8 -24
  27. package/dist/database.js +818 -829
  28. package/dist/database.mjs +818 -829
  29. package/dist/desktop-auto-render.cjs +1700 -1522
  30. package/dist/desktop-auto-render.d.ts +4 -9
  31. package/dist/desktop-auto-render.js +1695 -1517
  32. package/dist/desktop-auto-render.mjs +1696 -1518
  33. package/dist/desktop.cjs +3 -1
  34. package/dist/desktop.d.ts +4 -1
  35. package/dist/desktop.js +1 -1
  36. package/dist/desktop.mjs +1 -1
  37. package/dist/dev-build.cjs +830 -0
  38. package/dist/dev-build.d.ts +53 -0
  39. package/dist/dev-build.js +3318 -0
  40. package/dist/dev-build.mjs +797 -0
  41. package/dist/dom.cjs +717 -590
  42. package/dist/dom.d.ts +2 -15
  43. package/dist/dom.js +714 -587
  44. package/dist/dom.mjs +716 -589
  45. package/dist/el.cjs +62 -52
  46. package/dist/el.d.ts +5 -10
  47. package/dist/el.js +60 -52
  48. package/dist/el.mjs +60 -52
  49. package/dist/fs.cjs +72 -63
  50. package/dist/fs.d.ts +22 -19
  51. package/dist/fs.js +71 -62
  52. package/dist/fs.mjs +71 -62
  53. package/dist/hmr.cjs +40 -14
  54. package/dist/hmr.d.ts +11 -23
  55. package/dist/hmr.js +38 -14
  56. package/dist/hmr.mjs +38 -14
  57. package/dist/http.cjs +251 -99
  58. package/dist/http.d.ts +38 -104
  59. package/dist/http.js +249 -99
  60. package/dist/http.mjs +249 -99
  61. package/dist/https.cjs +524 -228
  62. package/dist/https.d.ts +44 -36
  63. package/dist/https.js +520 -226
  64. package/dist/https.mjs +522 -228
  65. package/dist/index.cjs +7502 -7690
  66. package/dist/index.d.ts +8 -3
  67. package/dist/index.js +7486 -7676
  68. package/dist/index.mjs +7497 -7686
  69. package/dist/mime-types.cjs +10 -4
  70. package/dist/mime-types.d.ts +8 -11
  71. package/dist/mime-types.js +9 -3
  72. package/dist/mime-types.mjs +9 -3
  73. package/dist/native.cjs +8616 -8869
  74. package/dist/native.d.ts +7 -8
  75. package/dist/native.js +8682 -8935
  76. package/dist/native.mjs +8615 -8868
  77. package/dist/path.cjs +83 -77
  78. package/dist/path.d.ts +29 -29
  79. package/dist/path.js +82 -76
  80. package/dist/path.mjs +82 -76
  81. package/dist/pm.cjs +3300 -0
  82. package/dist/pm.d.ts +256 -0
  83. package/dist/pm.js +5638 -0
  84. package/dist/pm.mjs +3196 -0
  85. package/dist/preview-build.cjs +712 -0
  86. package/dist/preview-build.d.ts +59 -0
  87. package/dist/preview-build.js +3194 -0
  88. package/dist/preview-build.mjs +676 -0
  89. package/dist/render-context.cjs +13 -2
  90. package/dist/render-context.d.ts +9 -31
  91. package/dist/render-context.js +11 -2
  92. package/dist/render-context.mjs +11 -2
  93. package/dist/router.cjs +787 -645
  94. package/dist/router.d.ts +8 -12
  95. package/dist/router.js +786 -644
  96. package/dist/router.mjs +786 -644
  97. package/dist/runtime.cjs +1 -1
  98. package/dist/runtime.js +1 -1
  99. package/dist/runtime.mjs +1 -1
  100. package/dist/server.cjs +3315 -2603
  101. package/dist/server.d.ts +49 -4
  102. package/dist/server.js +7611 -2834
  103. package/dist/server.mjs +3317 -2607
  104. package/dist/smtp-server.cjs +128 -0
  105. package/dist/smtp-server.d.ts +27 -0
  106. package/dist/smtp-server.js +4199 -0
  107. package/dist/smtp-server.mjs +100 -0
  108. package/dist/state-DvEkDehk.d.ts +195 -0
  109. package/dist/state.cjs +768 -658
  110. package/dist/state.d.ts +11 -69
  111. package/dist/state.js +760 -650
  112. package/dist/state.mjs +767 -657
  113. package/dist/style.cjs +1011 -968
  114. package/dist/style.d.ts +13 -127
  115. package/dist/style.js +1009 -970
  116. package/dist/style.mjs +1011 -971
  117. package/dist/test-reporter.cjs +332 -316
  118. package/dist/test-reporter.d.ts +28 -33
  119. package/dist/test-reporter.js +328 -312
  120. package/dist/test-reporter.mjs +328 -312
  121. package/dist/test-runtime.cjs +927 -968
  122. package/dist/test-runtime.d.ts +24 -99
  123. package/dist/test-runtime.js +922 -965
  124. package/dist/test-runtime.mjs +922 -965
  125. package/dist/test.cjs +4428 -4273
  126. package/dist/test.d.ts +2 -8
  127. package/dist/test.js +4307 -4154
  128. package/dist/test.mjs +4419 -4267
  129. package/dist/types-BONVzPtp.d.ts +59 -0
  130. package/dist/types-BR4wMiVx.d.ts +32 -0
  131. package/dist/types-C4gKykuG.d.ts +23 -0
  132. package/dist/types-CIhpN1-K.d.ts +64 -0
  133. package/dist/types-Ckj8md_j.d.ts +84 -0
  134. package/dist/types-CpjQTAkX.d.ts +24 -0
  135. package/dist/types-D0LjrYjS.d.ts +14 -0
  136. package/dist/types-DAisuVr5.d.ts +75 -0
  137. package/dist/types-tJn88E1N.d.ts +242 -0
  138. package/dist/types.d.ts +71 -226
  139. package/dist/universal.cjs +1 -1
  140. package/dist/universal.d.ts +1 -5
  141. package/dist/universal.js +1 -1
  142. package/dist/universal.mjs +1 -1
  143. package/dist/websocket-XfyK23zD.d.ts +119 -0
  144. package/dist/ws.cjs +129 -108
  145. package/dist/ws.d.ts +21 -131
  146. package/dist/ws.js +128 -109
  147. package/dist/ws.mjs +128 -109
  148. package/dist/wss.cjs +757 -479
  149. package/dist/wss.d.ts +31 -28
  150. package/dist/wss.js +755 -479
  151. package/dist/wss.mjs +758 -482
  152. package/package.json +16 -1
  153. package/vendor/epaint-0.31.1/src/image.rs +418 -0
  154. package/dist/server-CcBFc2F5.d.ts +0 -449
@@ -1,13 +1,17 @@
1
1
  import {createRequire as __createRequire} from 'module';const require = __createRequire(import.meta.url);
2
2
 
3
- // src/render-context.ts
3
+ // src/desktop/render-context/constants.ts
4
4
  var RUNTIME_TARGET_KEY = "__ELIT_RUNTIME_TARGET__";
5
5
  var CAPTURED_RENDER_KEY = "__ELIT_CAPTURED_RENDER__";
6
6
  var DESKTOP_RENDER_OPTIONS_KEY = "__ELIT_DESKTOP_RENDER_OPTIONS__";
7
7
  var RUNTIME_TARGET_ENV = "ELIT_RUNTIME_TARGET";
8
+
9
+ // src/desktop/render-context/globals.ts
8
10
  function getGlobalRenderScope() {
9
11
  return globalThis;
10
12
  }
13
+
14
+ // src/desktop/render-context/runtime-target.ts
11
15
  function isRenderRuntimeTarget(value) {
12
16
  return value === "web" || value === "desktop" || value === "mobile" || value === "unknown";
13
17
  }
@@ -23,7 +27,8 @@ function detectRenderRuntimeTarget() {
23
27
  if (typeof globalScope.createWindow === "function") {
24
28
  return "desktop";
25
29
  }
26
- const argv = Array.isArray(globalScope.process?.argv) ? globalScope.process.argv.join(" ") : "";
30
+ const argvValues = globalScope.process?.argv;
31
+ const argv = Array.isArray(argvValues) ? argvValues.join(" ") : "";
27
32
  if (/\bdesktop\b/i.test(argv)) {
28
33
  return "desktop";
29
34
  }
@@ -32,6 +37,8 @@ function detectRenderRuntimeTarget() {
32
37
  }
33
38
  return "unknown";
34
39
  }
40
+
41
+ // src/desktop/render-context/captured-render.ts
35
42
  function captureRenderedVNode(rootElement, vNode, target = detectRenderRuntimeTarget()) {
36
43
  const globalScope = getGlobalRenderScope();
37
44
  globalScope[RUNTIME_TARGET_KEY] = target;
@@ -47,11 +54,13 @@ function getCapturedRenderedVNode() {
47
54
  function clearCapturedRenderedVNode() {
48
55
  delete getGlobalRenderScope()[CAPTURED_RENDER_KEY];
49
56
  }
57
+
58
+ // src/desktop/render-context/desktop-options.ts
50
59
  function getDesktopRenderOptions() {
51
60
  return getGlobalRenderScope()[DESKTOP_RENDER_OPTIONS_KEY];
52
61
  }
53
62
 
54
- // src/dom.ts
63
+ // src/client/dom/helpers.ts
55
64
  function resolveElement(rootElement) {
56
65
  return typeof rootElement === "string" ? document.getElementById(rootElement.replace("#", "")) : rootElement;
57
66
  }
@@ -79,1029 +88,1248 @@ function resolveTextareaValue(tagName, props) {
79
88
  function hasDocumentApi() {
80
89
  return typeof document !== "undefined";
81
90
  }
82
- var DomNode = class {
83
- constructor() {
84
- this.elementCache = /* @__PURE__ */ new WeakMap();
85
- this.reactiveNodes = /* @__PURE__ */ new Map();
86
- }
87
- createElement(tagName, props = {}, children = []) {
88
- return { tagName, props, children };
89
- }
90
- renderToDOM(vNode, parent) {
91
- if (vNode == null || vNode === false) return;
92
- if (typeof vNode !== "object") {
93
- parent.appendChild(document.createTextNode(String(vNode)));
94
- return;
95
- }
96
- if (this.isState(vNode)) {
97
- const textNode = document.createTextNode(String(vNode.value ?? ""));
98
- parent.appendChild(textNode);
99
- vNode.subscribe((newValue) => {
100
- textNode.textContent = String(newValue ?? "");
101
- });
102
- return;
103
- }
104
- if (Array.isArray(vNode)) {
105
- for (const child of vNode) {
106
- this.renderToDOM(child, parent);
107
- }
108
- return;
109
- }
110
- const { tagName, props, children } = vNode;
111
- const textareaValue = resolveTextareaValue(tagName, props);
112
- if (!tagName) {
113
- for (const child of children) {
114
- if (shouldSkipChild(child)) continue;
115
- if (Array.isArray(child)) {
116
- for (const c of child) {
117
- !shouldSkipChild(c) && this.renderToDOM(c, parent);
118
- }
119
- } else {
120
- this.renderToDOM(child, parent);
121
- }
122
- }
123
- return;
124
- }
125
- const isSVG = tagName === "svg" || tagName[0] === "s" && tagName[1] === "v" && tagName[2] === "g" || parent.namespaceURI === "http://www.w3.org/2000/svg";
126
- const el = isSVG ? document.createElementNS("http://www.w3.org/2000/svg", tagName.replace("svg", "").toLowerCase() || tagName) : document.createElement(tagName);
127
- for (const key in props) {
128
- const value = props[key];
129
- if (value == null || value === false) continue;
130
- const c = key.charCodeAt(0);
131
- if (c === 99 && (key.length < 6 || key[5] === "N")) {
132
- const classValue = Array.isArray(value) ? value.join(" ") : value;
133
- isSVG ? el.setAttribute("class", classValue) : el.className = classValue;
134
- } else if (c === 115 && key.length === 5) {
135
- if (typeof value === "string") {
136
- el.style.cssText = value;
137
- } else {
138
- const s = el.style;
139
- for (const k in value) s[k] = value[k];
140
- }
141
- } else if (c === 111 && key.charCodeAt(1) === 110) {
142
- el[key.toLowerCase()] = value;
143
- } else if (c === 100 && key.length > 20) {
144
- el.innerHTML = value.__html;
145
- } else if (c === 114 && key === "ref") {
146
- setTimeout(() => {
147
- typeof value === "function" ? value(el) : value.current = el;
148
- }, 0);
149
- } else if (textareaValue !== void 0 && key === "value") {
150
- continue;
91
+ function isState(value) {
92
+ return value && typeof value === "object" && "value" in value && "subscribe" in value && typeof value.subscribe === "function";
93
+ }
94
+
95
+ // src/client/dom/dom-render.ts
96
+ function isSvgElement(tagName, parent) {
97
+ return tagName === "svg" || tagName[0] === "s" && tagName[1] === "v" && tagName[2] === "g" || parent.namespaceURI === "http://www.w3.org/2000/svg";
98
+ }
99
+ function applyProps(el, props, textareaValue) {
100
+ for (const key in props) {
101
+ const value = props[key];
102
+ if (value == null || value === false) continue;
103
+ const c = key.charCodeAt(0);
104
+ if (c === 99 && (key.length < 6 || key[5] === "N")) {
105
+ const classValue = Array.isArray(value) ? value.join(" ") : String(value);
106
+ if (el instanceof SVGElement) {
107
+ el.setAttribute("class", classValue);
151
108
  } else {
152
- el.setAttribute(key, value === true ? "" : String(value));
109
+ el.className = classValue;
153
110
  }
154
- }
155
- const renderableChildren = textareaValue === void 0 ? children : [];
156
- const len = renderableChildren.length;
157
- if (!len) {
158
- if (textareaValue !== void 0) {
159
- el.value = textareaValue;
111
+ } else if (c === 115 && key.length === 5) {
112
+ if (typeof value === "string") {
113
+ el.style.cssText = value;
114
+ } else {
115
+ const style = el.style;
116
+ for (const styleKey in value) {
117
+ style[styleKey] = value[styleKey];
118
+ }
160
119
  }
161
- parent.appendChild(el);
162
- return;
163
- }
164
- const renderChildren = (target) => {
165
- for (let i = 0; i < len; i++) {
166
- const child = renderableChildren[i];
167
- if (shouldSkipChild(child)) continue;
168
- if (Array.isArray(child)) {
169
- for (let j = 0, cLen = child.length; j < cLen; j++) {
170
- const c = child[j];
171
- !shouldSkipChild(c) && this.renderToDOM(c, target);
172
- }
120
+ } else if (c === 111 && key.charCodeAt(1) === 110) {
121
+ el[key.toLowerCase()] = value;
122
+ } else if (c === 100 && key.length > 20) {
123
+ el.innerHTML = value.__html;
124
+ } else if (c === 114 && key === "ref") {
125
+ setTimeout(() => {
126
+ if (typeof value === "function") {
127
+ value(el);
173
128
  } else {
174
- this.renderToDOM(child, target);
129
+ value.current = el;
175
130
  }
176
- }
177
- };
178
- if (len > 30) {
179
- const fragment = document.createDocumentFragment();
180
- renderChildren(fragment);
181
- el.appendChild(fragment);
131
+ }, 0);
132
+ } else if (textareaValue !== void 0 && key === "value") {
133
+ continue;
182
134
  } else {
183
- renderChildren(el);
135
+ el.setAttribute(key, value === true ? "" : String(value));
184
136
  }
185
- parent.appendChild(el);
186
137
  }
187
- render(rootElement, vNode) {
188
- if (!hasDocumentApi()) {
189
- const runtimeTarget = detectRenderRuntimeTarget();
190
- if (runtimeTarget === "desktop" || runtimeTarget === "mobile") {
191
- captureRenderedVNode(rootElement, vNode, runtimeTarget);
192
- return {};
138
+ }
139
+ function renderChildren(children, target) {
140
+ const len = children.length;
141
+ for (let i = 0; i < len; i++) {
142
+ const child = children[i];
143
+ if (shouldSkipChild(child)) continue;
144
+ if (Array.isArray(child)) {
145
+ for (let j = 0, childLen = child.length; j < childLen; j++) {
146
+ const nestedChild = child[j];
147
+ if (!shouldSkipChild(nestedChild)) {
148
+ renderToDOM(nestedChild, target);
149
+ }
193
150
  }
194
- throw new Error("render() requires a DOM or an Elit desktop/mobile runtime target.");
195
- }
196
- const el = ensureElement(resolveElement(rootElement), rootElement);
197
- el.innerHTML = "";
198
- if (vNode.children && vNode.children.length > 500) {
199
- const fragment = document.createDocumentFragment();
200
- this.renderToDOM(vNode, fragment);
201
- el.appendChild(fragment);
202
151
  } else {
203
- this.renderToDOM(vNode, el);
152
+ renderToDOM(child, target);
204
153
  }
205
- return el;
206
154
  }
207
- batchRender(rootElement, vNodes) {
208
- const el = ensureElement(resolveElement(rootElement), rootElement);
209
- const len = vNodes.length;
210
- if (len > 3e3) {
211
- const fragment = document.createDocumentFragment();
212
- let processed = 0;
213
- const chunkSize = 1500;
214
- const processChunk = () => {
215
- const end = Math.min(processed + chunkSize, len);
216
- for (let i = processed; i < end; i++) {
217
- this.renderToDOM(vNodes[i], fragment);
218
- }
219
- processed = end;
220
- if (processed >= len) {
221
- el.appendChild(fragment);
222
- } else {
223
- requestAnimationFrame(processChunk);
224
- }
225
- };
226
- processChunk();
227
- } else {
228
- const fragment = document.createDocumentFragment();
229
- for (let i = 0; i < len; i++) {
230
- this.renderToDOM(vNodes[i], fragment);
231
- }
232
- el.appendChild(fragment);
233
- }
234
- return el;
155
+ }
156
+ function renderToDOM(vNode, parent) {
157
+ if (vNode == null || vNode === false) return;
158
+ if (typeof vNode !== "object") {
159
+ parent.appendChild(document.createTextNode(String(vNode)));
160
+ return;
235
161
  }
236
- renderChunked(rootElement, vNodes, chunkSize = 5e3, onProgress) {
237
- const el = ensureElement(resolveElement(rootElement), rootElement);
238
- const len = vNodes.length;
239
- let index = 0;
240
- const renderChunk = () => {
241
- const end = Math.min(index + chunkSize, len);
242
- const fragment = document.createDocumentFragment();
243
- for (let i = index; i < end; i++) {
244
- this.renderToDOM(vNodes[i], fragment);
245
- }
246
- el.appendChild(fragment);
247
- index = end;
248
- if (onProgress) onProgress(index, len);
249
- if (index < len) {
250
- requestAnimationFrame(renderChunk);
251
- }
252
- };
253
- requestAnimationFrame(renderChunk);
254
- return el;
162
+ if (isState(vNode)) {
163
+ const textNode = document.createTextNode(String(vNode.value ?? ""));
164
+ parent.appendChild(textNode);
165
+ vNode.subscribe((newValue) => {
166
+ textNode.textContent = String(newValue ?? "");
167
+ });
168
+ return;
255
169
  }
256
- renderToHead(...vNodes) {
257
- const head = document.head;
258
- if (head) {
259
- for (const vNode of vNodes.flat()) {
260
- vNode && this.renderToDOM(vNode, head);
261
- }
170
+ if (Array.isArray(vNode)) {
171
+ for (const child of vNode) {
172
+ renderToDOM(child, parent);
262
173
  }
263
- return head;
174
+ return;
264
175
  }
265
- addStyle(cssText) {
266
- const el = document.createElement("style");
267
- el.textContent = cssText;
268
- return document.head.appendChild(el);
176
+ const { tagName, props, children } = vNode;
177
+ const textareaValue = resolveTextareaValue(tagName, props);
178
+ if (!tagName) {
179
+ renderChildren(children, parent);
180
+ return;
269
181
  }
270
- addMeta(attrs) {
271
- const el = document.createElement("meta");
272
- for (const k in attrs) el.setAttribute(k, attrs[k]);
273
- return document.head.appendChild(el);
182
+ const el = isSvgElement(tagName, parent) ? document.createElementNS("http://www.w3.org/2000/svg", tagName.replace("svg", "").toLowerCase() || tagName) : document.createElement(tagName);
183
+ applyProps(el, props, textareaValue);
184
+ const renderableChildren = textareaValue === void 0 ? children : [];
185
+ if (!renderableChildren.length) {
186
+ if (textareaValue !== void 0) {
187
+ el.value = textareaValue;
188
+ }
189
+ parent.appendChild(el);
190
+ return;
274
191
  }
275
- addLink(attrs) {
276
- const el = document.createElement("link");
277
- for (const k in attrs) el.setAttribute(k, attrs[k]);
278
- return document.head.appendChild(el);
192
+ if (renderableChildren.length > 30) {
193
+ const fragment = document.createDocumentFragment();
194
+ renderChildren(renderableChildren, fragment);
195
+ el.appendChild(fragment);
196
+ } else {
197
+ renderChildren(renderableChildren, el);
279
198
  }
280
- setTitle(text) {
281
- return document.title = text;
199
+ parent.appendChild(el);
200
+ }
201
+ function render(rootElement, vNode) {
202
+ if (!hasDocumentApi()) {
203
+ const runtimeTarget = detectRenderRuntimeTarget();
204
+ if (runtimeTarget === "desktop" || runtimeTarget === "mobile") {
205
+ captureRenderedVNode(rootElement, vNode, runtimeTarget);
206
+ return {};
207
+ }
208
+ throw new Error("render() requires a DOM or an Elit desktop/mobile runtime target.");
209
+ }
210
+ const el = ensureElement(resolveElement(rootElement), rootElement);
211
+ el.innerHTML = "";
212
+ if (vNode.children && vNode.children.length > 500) {
213
+ const fragment = document.createDocumentFragment();
214
+ renderToDOM(vNode, fragment);
215
+ el.appendChild(fragment);
216
+ } else {
217
+ renderToDOM(vNode, el);
282
218
  }
283
- // Reactive State Management
284
- createState(initialValue, options = {}) {
285
- let value = initialValue;
286
- const listeners = /* @__PURE__ */ new Set();
287
- let updateTimer = null;
288
- const { throttle = 0, deep = false } = options;
289
- const notify = () => listeners.forEach((fn) => fn(value));
290
- const scheduleUpdate = () => {
291
- if (throttle > 0) {
292
- if (!updateTimer) {
293
- updateTimer = setTimeout(() => {
294
- updateTimer = null;
295
- notify();
296
- }, throttle);
297
- }
219
+ return el;
220
+ }
221
+ function batchRender(rootElement, vNodes) {
222
+ const el = ensureElement(resolveElement(rootElement), rootElement);
223
+ const len = vNodes.length;
224
+ if (len > 3e3) {
225
+ const fragment = document.createDocumentFragment();
226
+ let processed = 0;
227
+ const chunkSize = 1500;
228
+ const processChunk = () => {
229
+ const end = Math.min(processed + chunkSize, len);
230
+ for (let i = processed; i < end; i++) {
231
+ renderToDOM(vNodes[i], fragment);
232
+ }
233
+ processed = end;
234
+ if (processed >= len) {
235
+ el.appendChild(fragment);
298
236
  } else {
299
- notify();
237
+ requestAnimationFrame(processChunk);
300
238
  }
301
239
  };
302
- return {
303
- get value() {
304
- return value;
305
- },
306
- set value(newValue) {
307
- const changed = deep ? JSON.stringify(value) !== JSON.stringify(newValue) : value !== newValue;
308
- if (changed) {
309
- value = newValue;
310
- scheduleUpdate();
311
- }
312
- },
313
- subscribe(fn) {
314
- listeners.add(fn);
315
- return () => listeners.delete(fn);
316
- },
317
- destroy() {
318
- listeners.clear();
319
- updateTimer && clearTimeout(updateTimer);
240
+ processChunk();
241
+ } else {
242
+ const fragment = document.createDocumentFragment();
243
+ for (let i = 0; i < len; i++) {
244
+ renderToDOM(vNodes[i], fragment);
245
+ }
246
+ el.appendChild(fragment);
247
+ }
248
+ return el;
249
+ }
250
+ function renderChunked(rootElement, vNodes, chunkSize = 5e3, onProgress) {
251
+ const el = ensureElement(resolveElement(rootElement), rootElement);
252
+ const len = vNodes.length;
253
+ let index = 0;
254
+ const renderChunkFrame = () => {
255
+ const end = Math.min(index + chunkSize, len);
256
+ const fragment = document.createDocumentFragment();
257
+ for (let i = index; i < end; i++) {
258
+ renderToDOM(vNodes[i], fragment);
259
+ }
260
+ el.appendChild(fragment);
261
+ index = end;
262
+ if (onProgress) {
263
+ onProgress(index, len);
264
+ }
265
+ if (index < len) {
266
+ requestAnimationFrame(renderChunkFrame);
267
+ }
268
+ };
269
+ requestAnimationFrame(renderChunkFrame);
270
+ return el;
271
+ }
272
+ function renderToHead(...vNodes) {
273
+ const head = document.head;
274
+ if (head) {
275
+ for (const vNode of vNodes.flat()) {
276
+ if (vNode) {
277
+ renderToDOM(vNode, head);
320
278
  }
321
- };
279
+ }
322
280
  }
323
- computed(states, computeFn) {
324
- const values = states.map((s) => s.value);
325
- const result = this.createState(computeFn(...values));
326
- states.forEach((state, index) => {
327
- state.subscribe((newValue) => {
328
- values[index] = newValue;
329
- result.value = computeFn(...values);
330
- });
331
- });
332
- return result;
281
+ return head;
282
+ }
283
+ function addStyle(cssText) {
284
+ const el = document.createElement("style");
285
+ el.textContent = cssText;
286
+ return document.head.appendChild(el);
287
+ }
288
+ function addMeta(attrs) {
289
+ const el = document.createElement("meta");
290
+ for (const key in attrs) {
291
+ el.setAttribute(key, attrs[key]);
333
292
  }
334
- effect(stateFn) {
335
- stateFn();
293
+ return document.head.appendChild(el);
294
+ }
295
+ function addLink(attrs) {
296
+ const el = document.createElement("link");
297
+ for (const key in attrs) {
298
+ el.setAttribute(key, attrs[key]);
336
299
  }
337
- // Virtual scrolling helper for large lists
338
- createVirtualList(container2, items, renderItem, itemHeight = 50, bufferSize = 5) {
339
- const viewportHeight = container2.clientHeight;
340
- const totalHeight = items.length * itemHeight;
341
- let scrollTop = 0;
342
- const getVisibleRange = () => {
343
- const start = Math.max(0, Math.floor(scrollTop / itemHeight) - bufferSize);
344
- const end = Math.min(items.length, Math.ceil((scrollTop + viewportHeight) / itemHeight) + bufferSize);
345
- return { start, end };
346
- };
347
- const render2 = () => {
348
- const { start, end } = getVisibleRange();
349
- const wrapper = document.createElement("div");
350
- wrapper.style.cssText = `height:${totalHeight}px;position:relative`;
351
- for (let i = start; i < end; i++) {
352
- const itemEl = document.createElement("div");
353
- itemEl.style.cssText = `position:absolute;top:${i * itemHeight}px;height:${itemHeight}px;width:100%`;
354
- this.renderToDOM(renderItem(items[i], i), itemEl);
355
- wrapper.appendChild(itemEl);
356
- }
357
- container2.innerHTML = "";
358
- container2.appendChild(wrapper);
359
- };
360
- const scrollHandler = () => {
361
- scrollTop = container2.scrollTop;
362
- requestAnimationFrame(render2);
363
- };
364
- container2.addEventListener("scroll", scrollHandler);
365
- render2();
366
- return {
367
- render: render2,
368
- destroy: () => {
369
- container2.removeEventListener("scroll", scrollHandler);
370
- container2.innerHTML = "";
371
- }
372
- };
300
+ return document.head.appendChild(el);
301
+ }
302
+ function setTitle(text) {
303
+ return document.title = text;
304
+ }
305
+ function cleanupUnusedElements(root, elementCache) {
306
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
307
+ const toRemove = [];
308
+ while (walker.nextNode()) {
309
+ const node = walker.currentNode;
310
+ if (node.id && node.id.startsWith("r") && !elementCache.has(node)) {
311
+ toRemove.push(node);
312
+ }
373
313
  }
374
- // Lazy load components
375
- lazy(loadFn) {
376
- let component = null;
377
- let loading = false;
378
- return async (...args) => {
379
- if (!component && !loading) {
380
- loading = true;
381
- component = await loadFn();
382
- loading = false;
314
+ toRemove.forEach((el) => el.remove());
315
+ return toRemove.length;
316
+ }
317
+
318
+ // src/client/dom/reactive.ts
319
+ function createReactiveChild(state, reactiveNodes, renderFn) {
320
+ const currentValue = renderFn(state.value);
321
+ if (typeof window !== "undefined" && typeof document !== "undefined") {
322
+ const entry = { node: null, renderFn };
323
+ reactiveNodes.set(state, entry);
324
+ state.subscribe(() => {
325
+ if (entry.node && entry.node.parentNode) {
326
+ const newValue = renderFn(state.value);
327
+ entry.node.textContent = String(newValue ?? "");
383
328
  }
384
- return component ? component(...args) : { tagName: "div", props: { class: "loading" }, children: ["Loading..."] };
385
- };
329
+ });
386
330
  }
387
- // Memory management - cleanup unused elements
388
- cleanupUnusedElements(root) {
389
- const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
390
- const toRemove = [];
391
- while (walker.nextNode()) {
392
- const node = walker.currentNode;
393
- if (node.id && node.id.startsWith("r") && !this.elementCache.has(node)) {
394
- toRemove.push(node);
331
+ return currentValue;
332
+ }
333
+
334
+ // src/client/dom/string-render.ts
335
+ var SELF_CLOSING_TAGS = /* @__PURE__ */ new Set([
336
+ "area",
337
+ "base",
338
+ "br",
339
+ "col",
340
+ "embed",
341
+ "hr",
342
+ "img",
343
+ "input",
344
+ "link",
345
+ "meta",
346
+ "param",
347
+ "source",
348
+ "track",
349
+ "wbr"
350
+ ]);
351
+ function resolveStateValue(value) {
352
+ return isState(value) ? value.value : value;
353
+ }
354
+ function isReactiveWrapper(vNode) {
355
+ if (!vNode || typeof vNode !== "object" || !vNode.tagName) {
356
+ return false;
357
+ }
358
+ return vNode.tagName === "span" && vNode.props?.id && typeof vNode.props.id === "string" && /^r[a-z0-9]{9}$/.test(vNode.props.id);
359
+ }
360
+ function unwrapReactive(vNode) {
361
+ if (!isReactiveWrapper(vNode)) {
362
+ return vNode;
363
+ }
364
+ const children = vNode.children;
365
+ if (!children || children.length === 0) {
366
+ return "";
367
+ }
368
+ if (children.length === 1) {
369
+ const child = children[0];
370
+ if (child && typeof child === "object" && child.tagName === "span") {
371
+ const props = child.props;
372
+ const hasNoProps = !props || Object.keys(props).length === 0;
373
+ const hasSingleStringChild = child.children && child.children.length === 1 && typeof child.children[0] === "string";
374
+ if (hasNoProps && hasSingleStringChild) {
375
+ return child.children[0];
395
376
  }
396
377
  }
397
- toRemove.forEach((el) => el.remove());
398
- return toRemove.length;
378
+ return unwrapReactive(child);
399
379
  }
400
- // Server-Side Rendering - convert VNode to HTML string
401
- renderToString(vNode, options = {}) {
402
- const { pretty = false, indent = 0 } = options;
403
- const indentStr = pretty ? " ".repeat(indent) : "";
404
- const newLine = pretty ? "\n" : "";
405
- let resolvedVNode = this.resolveStateValue(vNode);
406
- resolvedVNode = this.unwrapReactive(resolvedVNode);
407
- if (Array.isArray(resolvedVNode)) {
408
- return resolvedVNode.map((child) => this.renderToString(child, options)).join("");
409
- }
410
- if (typeof resolvedVNode !== "object" || resolvedVNode === null) {
411
- if (resolvedVNode === null || resolvedVNode === void 0 || resolvedVNode === false) {
412
- return "";
380
+ return children.map((child) => unwrapReactive(child));
381
+ }
382
+ function escapeHtml(text) {
383
+ const htmlEscapes = {
384
+ "&": "&amp;",
385
+ "<": "&lt;",
386
+ ">": "&gt;",
387
+ '"': "&quot;",
388
+ "'": "&#x27;"
389
+ };
390
+ return text.replace(/[&<>"']/g, (char) => htmlEscapes[char]);
391
+ }
392
+ function isSelfClosingTag(tagName) {
393
+ return SELF_CLOSING_TAGS.has(tagName.toLowerCase());
394
+ }
395
+ function styleToString(style) {
396
+ if (typeof style === "string") {
397
+ return style;
398
+ }
399
+ if (typeof style === "object" && style !== null) {
400
+ const styles2 = [];
401
+ for (const key in style) {
402
+ const cssKey = key.replace(/([A-Z])/g, "-$1").toLowerCase();
403
+ styles2.push(`${cssKey}:${style[key]}`);
404
+ }
405
+ return styles2.join(";");
406
+ }
407
+ return "";
408
+ }
409
+ function propsToAttributes(props, tagName) {
410
+ const attrs = [];
411
+ for (const key in props) {
412
+ if (key === "children" || key === "dangerouslySetInnerHTML" || key === "ref" || tagName === "textarea" && key === "value") {
413
+ continue;
414
+ }
415
+ let value = props[key];
416
+ value = resolveStateValue(value);
417
+ if (value == null || value === false) continue;
418
+ if (key.startsWith("on") && typeof value === "function") {
419
+ continue;
420
+ }
421
+ if (key === "className" || key === "class") {
422
+ const className = Array.isArray(value) ? value.join(" ") : value;
423
+ if (className) {
424
+ attrs.push(`class="${escapeHtml(String(className))}"`);
413
425
  }
414
- return this.escapeHtml(String(resolvedVNode));
426
+ continue;
415
427
  }
416
- const { tagName, props, children } = resolvedVNode;
417
- const textareaValue = resolveTextareaValue(tagName, props);
418
- const isSelfClosing = this.isSelfClosingTag(tagName);
419
- let html = `${indentStr}<${tagName}`;
420
- const attrs = this.propsToAttributes(props, tagName);
421
- if (attrs) {
422
- html += ` ${attrs}`;
428
+ if (key === "style") {
429
+ const styleStr = styleToString(value);
430
+ if (styleStr) {
431
+ attrs.push(`style="${escapeHtml(styleStr)}"`);
432
+ }
433
+ continue;
423
434
  }
424
- if (isSelfClosing) {
425
- html += ` />${newLine}`;
426
- return html;
435
+ if (value === true) {
436
+ attrs.push(key);
437
+ continue;
427
438
  }
428
- html += ">";
429
- if (textareaValue !== void 0) {
430
- html += this.escapeHtml(textareaValue);
431
- html += `</${tagName}>${newLine}`;
432
- return html;
433
- }
434
- if (props.dangerouslySetInnerHTML) {
435
- html += props.dangerouslySetInnerHTML.__html;
436
- html += `</${tagName}>${newLine}`;
437
- return html;
438
- }
439
- if (children && children.length > 0) {
440
- const resolvedChildren = children.map((c) => {
441
- const resolved = this.resolveStateValue(c);
442
- return this.unwrapReactive(resolved);
443
- });
444
- const hasComplexChildren = resolvedChildren.some(
445
- (c) => typeof c === "object" && c !== null && !Array.isArray(c) && "tagName" in c
446
- );
447
- if (pretty && hasComplexChildren) {
448
- html += newLine;
449
- for (const child of resolvedChildren) {
450
- if (shouldSkipChild(child)) continue;
451
- if (Array.isArray(child)) {
452
- for (const c of child) {
453
- if (!shouldSkipChild(c)) {
454
- html += this.renderToString(c, { pretty, indent: indent + 1 });
455
- }
439
+ attrs.push(`${key}="${escapeHtml(String(value))}"`);
440
+ }
441
+ return attrs.join(" ");
442
+ }
443
+ function renderToString(vNode, options = {}) {
444
+ const { pretty = false, indent = 0 } = options;
445
+ const indentStr = pretty ? " ".repeat(indent) : "";
446
+ const newLine = pretty ? "\n" : "";
447
+ let resolvedVNode = resolveStateValue(vNode);
448
+ resolvedVNode = unwrapReactive(resolvedVNode);
449
+ if (Array.isArray(resolvedVNode)) {
450
+ return resolvedVNode.map((child) => renderToString(child, options)).join("");
451
+ }
452
+ if (typeof resolvedVNode !== "object" || resolvedVNode === null) {
453
+ if (resolvedVNode === null || resolvedVNode === void 0 || resolvedVNode === false) {
454
+ return "";
455
+ }
456
+ return escapeHtml(String(resolvedVNode));
457
+ }
458
+ const { tagName, props, children } = resolvedVNode;
459
+ const textareaValue = resolveTextareaValue(tagName, props);
460
+ const selfClosing = isSelfClosingTag(tagName);
461
+ let html = `${indentStr}<${tagName}`;
462
+ const attrs = propsToAttributes(props, tagName);
463
+ if (attrs) {
464
+ html += ` ${attrs}`;
465
+ }
466
+ if (selfClosing) {
467
+ html += ` />${newLine}`;
468
+ return html;
469
+ }
470
+ html += ">";
471
+ if (textareaValue !== void 0) {
472
+ html += escapeHtml(textareaValue);
473
+ html += `</${tagName}>${newLine}`;
474
+ return html;
475
+ }
476
+ if (props.dangerouslySetInnerHTML) {
477
+ html += props.dangerouslySetInnerHTML.__html;
478
+ html += `</${tagName}>${newLine}`;
479
+ return html;
480
+ }
481
+ const isRawText = tagName === "script" || tagName === "style";
482
+ if (children && children.length > 0) {
483
+ const resolvedChildren = children.map((child) => unwrapReactive(resolveStateValue(child)));
484
+ const hasComplexChildren = resolvedChildren.some(
485
+ (child) => typeof child === "object" && child !== null && !Array.isArray(child) && "tagName" in child
486
+ );
487
+ if (pretty && hasComplexChildren) {
488
+ html += newLine;
489
+ for (const child of resolvedChildren) {
490
+ if (shouldSkipChild(child)) continue;
491
+ if (Array.isArray(child)) {
492
+ for (const nestedChild of child) {
493
+ if (!shouldSkipChild(nestedChild)) {
494
+ html += isRawText && typeof nestedChild === "string" ? nestedChild : renderToString(nestedChild, { pretty, indent: indent + 1 });
456
495
  }
457
- } else {
458
- html += this.renderToString(child, { pretty, indent: indent + 1 });
459
496
  }
497
+ } else {
498
+ html += isRawText && typeof child === "string" ? child : renderToString(child, { pretty, indent: indent + 1 });
460
499
  }
461
- html += indentStr;
462
- } else {
463
- for (const child of resolvedChildren) {
464
- if (shouldSkipChild(child)) continue;
465
- if (Array.isArray(child)) {
466
- for (const c of child) {
467
- if (!shouldSkipChild(c)) {
468
- html += this.renderToString(c, { pretty: false, indent: 0 });
469
- }
500
+ }
501
+ html += indentStr;
502
+ } else {
503
+ for (const child of resolvedChildren) {
504
+ if (shouldSkipChild(child)) continue;
505
+ if (Array.isArray(child)) {
506
+ for (const nestedChild of child) {
507
+ if (!shouldSkipChild(nestedChild)) {
508
+ html += isRawText && typeof nestedChild === "string" ? nestedChild : renderToString(nestedChild, { pretty: false, indent: 0 });
470
509
  }
471
- } else {
472
- html += this.renderToString(child, { pretty: false, indent: 0 });
473
510
  }
511
+ } else {
512
+ html += isRawText && typeof child === "string" ? child : renderToString(child, { pretty: false, indent: 0 });
474
513
  }
475
514
  }
476
515
  }
477
- html += `</${tagName}>${newLine}`;
478
- return html;
479
516
  }
480
- resolveStateValue(value) {
481
- if (value && typeof value === "object" && "value" in value && "subscribe" in value) {
482
- return value.value;
517
+ html += `</${tagName}>${newLine}`;
518
+ return html;
519
+ }
520
+ function renderToHTMLDocument(vNode, options = {}) {
521
+ const {
522
+ title = "",
523
+ meta = [],
524
+ links = [],
525
+ scripts = [],
526
+ styles: styles2 = [],
527
+ lang = "en",
528
+ head = "",
529
+ bodyAttrs = {},
530
+ pretty = false
531
+ } = options;
532
+ const nl = pretty ? "\n" : "";
533
+ const indent = pretty ? " " : "";
534
+ const indent2 = pretty ? " " : "";
535
+ let html = `<!DOCTYPE html>${nl}<html lang="${lang}">${nl}${indent}<head>${nl}${indent2}<meta charset="UTF-8">${nl}${indent2}<meta name="viewport" content="width=device-width, initial-scale=1.0">${nl}`;
536
+ if (title) {
537
+ html += `${indent2}<title>${escapeHtml(title)}</title>${nl}`;
538
+ }
539
+ for (const metaAttrs of meta) {
540
+ html += `${indent2}<meta`;
541
+ for (const key in metaAttrs) {
542
+ html += ` ${key}="${escapeHtml(metaAttrs[key])}"`;
483
543
  }
484
- return value;
544
+ html += `>${nl}`;
485
545
  }
486
- isReactiveWrapper(vNode) {
487
- if (!vNode || typeof vNode !== "object" || !vNode.tagName) {
488
- return false;
546
+ for (const linkAttrs of links) {
547
+ html += `${indent2}<link`;
548
+ for (const key in linkAttrs) {
549
+ html += ` ${key}="${escapeHtml(linkAttrs[key])}"`;
489
550
  }
490
- return vNode.tagName === "span" && vNode.props?.id && typeof vNode.props.id === "string" && vNode.props.id.match(/^r[a-z0-9]{9}$/);
551
+ html += `>${nl}`;
491
552
  }
492
- unwrapReactive(vNode) {
493
- if (!this.isReactiveWrapper(vNode)) {
494
- return vNode;
495
- }
496
- const children = vNode.children;
497
- if (!children || children.length === 0) {
498
- return "";
553
+ for (const style of styles2) {
554
+ if (style.href) {
555
+ html += `${indent2}<link rel="stylesheet" href="${escapeHtml(style.href)}">${nl}`;
556
+ } else if (style.content) {
557
+ html += `${indent2}<style>${style.content}</style>${nl}`;
499
558
  }
500
- if (children.length === 1) {
501
- const child = children[0];
502
- if (child && typeof child === "object" && child.tagName === "span") {
503
- const props = child.props;
504
- const hasNoProps = !props || Object.keys(props).length === 0;
505
- const hasSingleStringChild = child.children && child.children.length === 1 && typeof child.children[0] === "string";
506
- if (hasNoProps && hasSingleStringChild) {
507
- return child.children[0];
508
- }
509
- }
510
- return this.unwrapReactive(child);
511
- }
512
- return children.map((c) => this.unwrapReactive(c));
513
559
  }
514
- escapeHtml(text) {
515
- const htmlEscapes = {
516
- "&": "&amp;",
517
- "<": "&lt;",
518
- ">": "&gt;",
519
- '"': "&quot;",
520
- "'": "&#x27;"
521
- };
522
- return text.replace(/[&<>"']/g, (char) => htmlEscapes[char]);
523
- }
524
- isSelfClosingTag(tagName) {
525
- const selfClosingTags = /* @__PURE__ */ new Set([
526
- "area",
527
- "base",
528
- "br",
529
- "col",
530
- "embed",
531
- "hr",
532
- "img",
533
- "input",
534
- "link",
535
- "meta",
536
- "param",
537
- "source",
538
- "track",
539
- "wbr"
540
- ]);
541
- return selfClosingTags.has(tagName.toLowerCase());
542
- }
543
- propsToAttributes(props, tagName) {
544
- const attrs = [];
545
- for (const key in props) {
546
- if (key === "children" || key === "dangerouslySetInnerHTML" || key === "ref" || tagName === "textarea" && key === "value") {
547
- continue;
548
- }
549
- let value = props[key];
550
- value = this.resolveStateValue(value);
551
- if (value == null || value === false) continue;
552
- if (key.startsWith("on") && typeof value === "function") {
553
- continue;
554
- }
555
- if (key === "className" || key === "class") {
556
- const className = Array.isArray(value) ? value.join(" ") : value;
557
- if (className) {
558
- attrs.push(`class="${this.escapeHtml(String(className))}"`);
559
- }
560
- continue;
561
- }
562
- if (key === "style") {
563
- const styleStr = this.styleToString(value);
564
- if (styleStr) {
565
- attrs.push(`style="${this.escapeHtml(styleStr)}"`);
566
- }
567
- continue;
568
- }
569
- if (value === true) {
570
- attrs.push(key);
571
- continue;
572
- }
573
- attrs.push(`${key}="${this.escapeHtml(String(value))}"`);
574
- }
575
- return attrs.join(" ");
560
+ if (head) {
561
+ html += head + nl;
562
+ }
563
+ html += `${indent}</head>${nl}${indent}<body`;
564
+ for (const key in bodyAttrs) {
565
+ html += ` ${key}="${escapeHtml(bodyAttrs[key])}"`;
576
566
  }
577
- styleToString(style) {
578
- if (typeof style === "string") {
579
- return style;
567
+ html += `>${nl}`;
568
+ html += renderToString(vNode, { pretty, indent: 2 });
569
+ for (const script of scripts) {
570
+ html += `${indent2}<script`;
571
+ if (script.type) {
572
+ html += ` type="${escapeHtml(script.type)}"`;
580
573
  }
581
- if (typeof style === "object" && style !== null) {
582
- const styles2 = [];
583
- for (const key in style) {
584
- const cssKey = key.replace(/([A-Z])/g, "-$1").toLowerCase();
585
- styles2.push(`${cssKey}:${style[key]}`);
586
- }
587
- return styles2.join(";");
574
+ if (script.async) {
575
+ html += " async";
588
576
  }
589
- return "";
590
- }
591
- isState(value) {
592
- return value && typeof value === "object" && "value" in value && "subscribe" in value && typeof value.subscribe === "function";
593
- }
594
- createReactiveChild(state, renderFn) {
595
- const currentValue = renderFn(state.value);
596
- if (typeof window !== "undefined" && typeof document !== "undefined") {
597
- const entry = { node: null, renderFn };
598
- this.reactiveNodes.set(state, entry);
599
- state.subscribe(() => {
600
- if (entry.node && entry.node.parentNode) {
601
- const newValue = renderFn(state.value);
602
- entry.node.textContent = String(newValue ?? "");
603
- }
604
- });
577
+ if (script.defer) {
578
+ html += " defer";
579
+ }
580
+ if (script.src) {
581
+ html += ` src="${escapeHtml(script.src)}"></script>${nl}`;
582
+ } else if (script.content) {
583
+ html += `>${script.content}</script>${nl}`;
584
+ } else {
585
+ html += `></script>${nl}`;
605
586
  }
606
- return currentValue;
607
587
  }
608
- jsonToVNode(json) {
609
- if (this.isState(json)) {
610
- return this.createReactiveChild(json, (v) => v);
611
- }
612
- if (isPrimitiveJson(json)) {
613
- return json;
614
- }
615
- const { tag, attributes = {}, children } = json;
616
- const props = {};
617
- for (const key in attributes) {
618
- const value = attributes[key];
619
- if (key === "class") {
620
- props.className = this.isState(value) ? value.value : value;
621
- } else {
622
- props[key] = this.isState(value) ? value.value : value;
623
- }
588
+ html += `${indent}</body>${nl}</html>`;
589
+ return html;
590
+ }
591
+
592
+ // src/client/dom/json.ts
593
+ function jsonToVNode(json, reactiveNodes) {
594
+ if (isState(json)) {
595
+ return createReactiveChild(json, reactiveNodes, (value) => value);
596
+ }
597
+ if (isPrimitiveJson(json)) {
598
+ return json;
599
+ }
600
+ const { tag, attributes = {}, children } = json;
601
+ const props = {};
602
+ for (const key in attributes) {
603
+ const value = attributes[key];
604
+ if (key === "class") {
605
+ props.className = isState(value) ? value.value : value;
606
+ } else {
607
+ props[key] = isState(value) ? value.value : value;
624
608
  }
625
- const childrenArray = [];
626
- if (children != null) {
627
- if (Array.isArray(children)) {
628
- for (const child of children) {
629
- if (this.isState(child)) {
630
- childrenArray.push(this.createReactiveChild(child, (v) => v));
631
- } else {
632
- const converted = this.jsonToVNode(child);
633
- if (converted != null && converted !== false) {
634
- childrenArray.push(converted);
635
- }
609
+ }
610
+ const childrenArray = [];
611
+ if (children != null) {
612
+ if (Array.isArray(children)) {
613
+ for (const child of children) {
614
+ if (isState(child)) {
615
+ childrenArray.push(createReactiveChild(child, reactiveNodes, (value) => value));
616
+ } else {
617
+ const converted = jsonToVNode(child, reactiveNodes);
618
+ if (converted != null && converted !== false) {
619
+ childrenArray.push(converted);
636
620
  }
637
621
  }
638
- } else if (this.isState(children)) {
639
- childrenArray.push(this.createReactiveChild(children, (v) => v));
640
- } else if (typeof children === "object" && "tag" in children) {
641
- const converted = this.jsonToVNode(children);
642
- if (converted != null && converted !== false) {
643
- childrenArray.push(converted);
644
- }
645
- } else {
646
- childrenArray.push(children);
647
622
  }
648
- }
649
- return { tagName: tag, props, children: childrenArray };
650
- }
651
- vNodeJsonToVNode(json) {
652
- if (this.isState(json)) {
653
- return this.createReactiveChild(json, (v) => v);
654
- }
655
- if (isPrimitiveJson(json)) {
656
- return json;
657
- }
658
- const { tagName, props = {}, children = [] } = json;
659
- const resolvedProps = {};
660
- for (const key in props) {
661
- const value = props[key];
662
- resolvedProps[key] = this.isState(value) ? value.value : value;
663
- }
664
- const childrenArray = [];
665
- for (const child of children) {
666
- if (this.isState(child)) {
667
- childrenArray.push(this.createReactiveChild(child, (v) => v));
668
- } else {
669
- const converted = this.vNodeJsonToVNode(child);
670
- if (converted != null && converted !== false) {
671
- childrenArray.push(converted);
672
- }
623
+ } else if (isState(children)) {
624
+ childrenArray.push(createReactiveChild(children, reactiveNodes, (value) => value));
625
+ } else if (typeof children === "object" && children !== null && "tag" in children) {
626
+ const converted = jsonToVNode(children, reactiveNodes);
627
+ if (converted != null && converted !== false) {
628
+ childrenArray.push(converted);
673
629
  }
630
+ } else {
631
+ childrenArray.push(children);
674
632
  }
675
- return { tagName, props: resolvedProps, children: childrenArray };
676
- }
677
- renderJson(rootElement, json) {
678
- const vNode = this.jsonToVNode(json);
679
- if (!vNode || typeof vNode !== "object" || !("tagName" in vNode)) {
680
- throw new Error("Invalid JSON structure");
681
- }
682
- return this.render(rootElement, vNode);
683
633
  }
684
- renderVNode(rootElement, json) {
685
- const vNode = this.vNodeJsonToVNode(json);
686
- if (!vNode || typeof vNode !== "object" || !("tagName" in vNode)) {
687
- throw new Error("Invalid VNode JSON structure");
634
+ return { tagName: tag, props, children: childrenArray };
635
+ }
636
+ function vNodeJsonToVNode(json, reactiveNodes) {
637
+ if (isState(json)) {
638
+ return createReactiveChild(json, reactiveNodes, (value) => value);
639
+ }
640
+ if (isPrimitiveJson(json)) {
641
+ return json;
642
+ }
643
+ const { tagName, props = {}, children = [] } = json;
644
+ const resolvedProps = {};
645
+ for (const key in props) {
646
+ const value = props[key];
647
+ resolvedProps[key] = isState(value) ? value.value : value;
648
+ }
649
+ const childrenArray = [];
650
+ for (const child of children) {
651
+ if (isState(child)) {
652
+ childrenArray.push(createReactiveChild(child, reactiveNodes, (value) => value));
653
+ } else {
654
+ const converted = vNodeJsonToVNode(child, reactiveNodes);
655
+ if (converted != null && converted !== false) {
656
+ childrenArray.push(converted);
657
+ }
688
658
  }
689
- return this.render(rootElement, vNode);
690
659
  }
691
- renderJsonToString(json, options = {}) {
692
- const vNode = this.jsonToVNode(json);
693
- return this.renderToString(vNode, options);
660
+ return { tagName, props: resolvedProps, children: childrenArray };
661
+ }
662
+ function renderJson(rootElement, json, reactiveNodes) {
663
+ const vNode = jsonToVNode(json, reactiveNodes);
664
+ if (!vNode || typeof vNode !== "object" || !("tagName" in vNode)) {
665
+ throw new Error("Invalid JSON structure");
694
666
  }
695
- renderVNodeToString(json, options = {}) {
696
- const vNode = this.vNodeJsonToVNode(json);
697
- return this.renderToString(vNode, options);
667
+ return render(rootElement, vNode);
668
+ }
669
+ function renderVNode(rootElement, json, reactiveNodes) {
670
+ const vNode = vNodeJsonToVNode(json, reactiveNodes);
671
+ if (!vNode || typeof vNode !== "object" || !("tagName" in vNode)) {
672
+ throw new Error("Invalid VNode JSON structure");
698
673
  }
699
- // Generate complete HTML document as string (for SSR)
700
- renderToHTMLDocument(vNode, options = {}) {
701
- const { title = "", meta = [], links = [], scripts = [], styles: styles2 = [], lang = "en", head = "", bodyAttrs = {}, pretty = false } = options;
702
- const nl = pretty ? "\n" : "";
703
- const indent = pretty ? " " : "";
704
- const indent2 = pretty ? " " : "";
705
- let html = `<!DOCTYPE html>${nl}<html lang="${lang}">${nl}${indent}<head>${nl}${indent2}<meta charset="UTF-8">${nl}${indent2}<meta name="viewport" content="width=device-width, initial-scale=1.0">${nl}`;
706
- if (title) html += `${indent2}<title>${this.escapeHtml(title)}</title>${nl}`;
707
- for (const m of meta) {
708
- html += `${indent2}<meta`;
709
- for (const k in m) html += ` ${k}="${this.escapeHtml(m[k])}"`;
710
- html += `>${nl}`;
711
- }
712
- for (const l of links) {
713
- html += `${indent2}<link`;
714
- for (const k in l) html += ` ${k}="${this.escapeHtml(l[k])}"`;
715
- html += `>${nl}`;
716
- }
717
- for (const s of styles2) {
718
- if (s.href) {
719
- html += `${indent2}<link rel="stylesheet" href="${this.escapeHtml(s.href)}">${nl}`;
720
- } else if (s.content) {
721
- html += `${indent2}<style>${s.content}</style>${nl}`;
674
+ return render(rootElement, vNode);
675
+ }
676
+ function renderJsonToString(json, reactiveNodes, options = {}) {
677
+ const vNode = jsonToVNode(json, reactiveNodes);
678
+ return renderToString(vNode, options);
679
+ }
680
+ function renderVNodeToString(json, reactiveNodes, options = {}) {
681
+ const vNode = vNodeJsonToVNode(json, reactiveNodes);
682
+ return renderToString(vNode, options);
683
+ }
684
+
685
+ // src/client/dom/state-utils.ts
686
+ function createState(initialValue, options = {}) {
687
+ let value = initialValue;
688
+ const listeners = /* @__PURE__ */ new Set();
689
+ let updateTimer = null;
690
+ const { throttle = 0, deep = false } = options;
691
+ const notify = () => listeners.forEach((listener) => listener(value));
692
+ const scheduleUpdate = () => {
693
+ if (throttle > 0) {
694
+ if (!updateTimer) {
695
+ updateTimer = setTimeout(() => {
696
+ updateTimer = null;
697
+ notify();
698
+ }, throttle);
722
699
  }
700
+ } else {
701
+ notify();
723
702
  }
724
- if (head) html += head + nl;
725
- html += `${indent}</head>${nl}${indent}<body`;
726
- for (const k in bodyAttrs) html += ` ${k}="${this.escapeHtml(bodyAttrs[k])}"`;
727
- html += `>${nl}`;
728
- html += this.renderToString(vNode, { pretty, indent: 2 });
729
- for (const script of scripts) {
730
- html += `${indent2}<script`;
731
- if (script.type) html += ` type="${this.escapeHtml(script.type)}"`;
732
- if (script.async) html += ` async`;
733
- if (script.defer) html += ` defer`;
734
- if (script.src) {
735
- html += ` src="${this.escapeHtml(script.src)}"></script>${nl}`;
736
- } else if (script.content) {
737
- html += `>${script.content}</script>${nl}`;
738
- } else {
739
- html += `></script>${nl}`;
703
+ };
704
+ return {
705
+ get value() {
706
+ return value;
707
+ },
708
+ set value(newValue) {
709
+ const changed = deep ? JSON.stringify(value) !== JSON.stringify(newValue) : value !== newValue;
710
+ if (changed) {
711
+ value = newValue;
712
+ scheduleUpdate();
713
+ }
714
+ },
715
+ subscribe(fn) {
716
+ listeners.add(fn);
717
+ return () => listeners.delete(fn);
718
+ },
719
+ destroy() {
720
+ listeners.clear();
721
+ if (updateTimer) {
722
+ clearTimeout(updateTimer);
740
723
  }
741
724
  }
742
- html += `${indent}</body>${nl}</html>`;
743
- return html;
744
- }
745
- // Expose elementCache for reactive updates
746
- getElementCache() {
747
- return this.elementCache;
748
- }
749
- };
750
- var dom = new DomNode();
751
- var render = dom.render.bind(dom);
752
- var renderToString = dom.renderToString.bind(dom);
753
-
754
- // src/style.ts
755
- var ELIT_SHARED_STYLE_STORE_KEY = "__elitSharedStyleStore__";
756
- function createStyleStore() {
757
- return {
758
- variables: [],
759
- rules: [],
760
- mediaRules: [],
761
- keyframes: [],
762
- fontFaces: [],
763
- imports: [],
764
- containerRules: [],
765
- supportsRules: [],
766
- layerRules: [],
767
- layerOrder: []
768
725
  };
769
726
  }
770
- function getSharedStyleStore() {
771
- const globalScope = globalThis;
772
- if (!globalScope[ELIT_SHARED_STYLE_STORE_KEY]) {
773
- globalScope[ELIT_SHARED_STYLE_STORE_KEY] = createStyleStore();
774
- }
775
- return globalScope[ELIT_SHARED_STYLE_STORE_KEY];
727
+ function computed(states, computeFn) {
728
+ const values = states.map((state) => state.value);
729
+ const result = createState(computeFn(...values));
730
+ states.forEach((state, index) => {
731
+ state.subscribe((newValue) => {
732
+ values[index] = newValue;
733
+ result.value = computeFn(...values);
734
+ });
735
+ });
736
+ return result;
776
737
  }
777
- var CreateStyle = class {
778
- constructor(store) {
779
- this.variables = [];
780
- this.rules = [];
781
- this.mediaRules = [];
782
- this.keyframes = [];
783
- this.fontFaces = [];
784
- this.imports = [];
785
- this.containerRules = [];
786
- this.supportsRules = [];
787
- this.layerRules = [];
788
- this._layerOrder = [];
789
- this.parsedSelectorChainCache = /* @__PURE__ */ new Map();
790
- if (!store) {
791
- return;
738
+ function effect(stateFn) {
739
+ stateFn();
740
+ }
741
+ function createVirtualList(container2, items, renderItem, itemHeight = 50, bufferSize = 5) {
742
+ const viewportHeight = container2.clientHeight;
743
+ const totalHeight = items.length * itemHeight;
744
+ let scrollTop = 0;
745
+ const getVisibleRange = () => {
746
+ const start = Math.max(0, Math.floor(scrollTop / itemHeight) - bufferSize);
747
+ const end = Math.min(items.length, Math.ceil((scrollTop + viewportHeight) / itemHeight) + bufferSize);
748
+ return { start, end };
749
+ };
750
+ const render3 = () => {
751
+ const { start, end } = getVisibleRange();
752
+ const wrapper = document.createElement("div");
753
+ wrapper.style.cssText = `height:${totalHeight}px;position:relative`;
754
+ for (let i = start; i < end; i++) {
755
+ const itemEl = document.createElement("div");
756
+ itemEl.style.cssText = `position:absolute;top:${i * itemHeight}px;height:${itemHeight}px;width:100%`;
757
+ renderToDOM(renderItem(items[i], i), itemEl);
758
+ wrapper.appendChild(itemEl);
759
+ }
760
+ container2.innerHTML = "";
761
+ container2.appendChild(wrapper);
762
+ };
763
+ const scrollHandler = () => {
764
+ scrollTop = container2.scrollTop;
765
+ requestAnimationFrame(render3);
766
+ };
767
+ container2.addEventListener("scroll", scrollHandler);
768
+ render3();
769
+ return {
770
+ render: render3,
771
+ destroy: () => {
772
+ container2.removeEventListener("scroll", scrollHandler);
773
+ container2.innerHTML = "";
792
774
  }
793
- this.variables = store.variables;
794
- this.rules = store.rules;
795
- this.mediaRules = store.mediaRules;
796
- this.keyframes = store.keyframes;
797
- this.fontFaces = store.fontFaces;
798
- this.imports = store.imports;
799
- this.containerRules = store.containerRules;
800
- this.supportsRules = store.supportsRules;
801
- this.layerRules = store.layerRules;
802
- this._layerOrder = store.layerOrder;
775
+ };
776
+ }
777
+ function lazy(loadFn) {
778
+ let component = null;
779
+ let loading = false;
780
+ return async (...args) => {
781
+ if (!component && !loading) {
782
+ loading = true;
783
+ component = await loadFn();
784
+ loading = false;
785
+ }
786
+ return component ? component(...args) : { tagName: "div", props: { class: "loading" }, children: ["Loading..."] };
787
+ };
788
+ }
789
+
790
+ // src/client/dom/index.ts
791
+ var DomNode = class {
792
+ constructor() {
793
+ this.elementCache = /* @__PURE__ */ new WeakMap();
794
+ this.reactiveNodes = /* @__PURE__ */ new Map();
803
795
  }
804
- // CSS Variables
805
- addVar(name, value) {
806
- const cssVar = {
807
- name: name.startsWith("--") ? name : `--${name}`,
808
- value,
809
- toString() {
810
- return `var(${this.name})`;
811
- }
812
- };
813
- this.variables.push(cssVar);
814
- return cssVar;
796
+ createElement(tagName, props = {}, children = []) {
797
+ return { tagName, props, children };
815
798
  }
816
- var(variable, fallback) {
817
- const varName = typeof variable === "string" ? variable.startsWith("--") ? variable : `--${variable}` : variable.name;
818
- return fallback ? `var(${varName}, ${fallback})` : `var(${varName})`;
799
+ renderToDOM(vNode, parent) {
800
+ return renderToDOM(vNode, parent);
819
801
  }
820
- // Basic Selectors
821
- addTag(tag, styles2) {
822
- const rule = { selector: tag, styles: styles2, type: "tag" };
823
- this.rules.push(rule);
824
- return rule;
802
+ render(rootElement, vNode) {
803
+ return render(rootElement, vNode);
825
804
  }
826
- addClass(name, styles2) {
827
- const selector = name.startsWith(".") ? name : `.${name}`;
828
- const rule = { selector, styles: styles2, type: "class" };
829
- this.rules.push(rule);
830
- return rule;
805
+ batchRender(rootElement, vNodes) {
806
+ return batchRender(rootElement, vNodes);
831
807
  }
832
- addId(name, styles2) {
833
- const selector = name.startsWith("#") ? name : `#${name}`;
834
- const rule = { selector, styles: styles2, type: "id" };
835
- this.rules.push(rule);
836
- return rule;
808
+ renderChunked(rootElement, vNodes, chunkSize = 5e3, onProgress) {
809
+ return renderChunked(rootElement, vNodes, chunkSize, onProgress);
837
810
  }
838
- // Pseudo Selectors
839
- addPseudoClass(pseudo, styles2, baseSelector) {
840
- const pseudoClass = pseudo.startsWith(":") ? pseudo : `:${pseudo}`;
841
- const selector = baseSelector ? `${baseSelector}${pseudoClass}` : pseudoClass;
842
- const rule = { selector, styles: styles2, type: "pseudo-class" };
843
- this.rules.push(rule);
844
- return rule;
811
+ renderToHead(...vNodes) {
812
+ return renderToHead(...vNodes);
845
813
  }
846
- addPseudoElement(pseudo, styles2, baseSelector) {
847
- const pseudoElement = pseudo.startsWith("::") ? pseudo : `::${pseudo}`;
848
- const selector = baseSelector ? `${baseSelector}${pseudoElement}` : pseudoElement;
849
- const rule = { selector, styles: styles2, type: "pseudo-element" };
850
- this.rules.push(rule);
851
- return rule;
814
+ addStyle(cssText) {
815
+ return addStyle(cssText);
852
816
  }
853
- // Attribute Selectors
854
- addAttribute(attr, styles2, baseSelector) {
855
- const attrSelector = attr.startsWith("[") ? attr : `[${attr}]`;
856
- const selector = baseSelector ? `${baseSelector}${attrSelector}` : attrSelector;
857
- const rule = { selector, styles: styles2, type: "attribute" };
858
- this.rules.push(rule);
859
- return rule;
817
+ addMeta(attrs) {
818
+ return addMeta(attrs);
860
819
  }
861
- attrEquals(attr, value, styles2, baseSelector) {
862
- return this.addAttribute(`${attr}="${value}"`, styles2, baseSelector);
820
+ addLink(attrs) {
821
+ return addLink(attrs);
863
822
  }
864
- attrContainsWord(attr, value, styles2, baseSelector) {
865
- return this.addAttribute(`${attr}~="${value}"`, styles2, baseSelector);
823
+ setTitle(text) {
824
+ return setTitle(text);
866
825
  }
867
- attrStartsWith(attr, value, styles2, baseSelector) {
868
- return this.addAttribute(`${attr}^="${value}"`, styles2, baseSelector);
826
+ // Reactive State Management
827
+ createState(initialValue, options = {}) {
828
+ return createState(initialValue, options);
869
829
  }
870
- attrEndsWith(attr, value, styles2, baseSelector) {
871
- return this.addAttribute(`${attr}$="${value}"`, styles2, baseSelector);
830
+ computed(states, computeFn) {
831
+ return computed(states, computeFn);
872
832
  }
873
- attrContains(attr, value, styles2, baseSelector) {
874
- return this.addAttribute(`${attr}*="${value}"`, styles2, baseSelector);
833
+ effect(stateFn) {
834
+ effect(stateFn);
875
835
  }
876
- // Combinator Selectors
877
- descendant(ancestor, descendant2, styles2) {
878
- return this.createAndAddRule(`${ancestor} ${descendant2}`, styles2);
836
+ // Virtual scrolling helper for large lists
837
+ createVirtualList(container2, items, renderItem, itemHeight = 50, bufferSize = 5) {
838
+ return createVirtualList(container2, items, renderItem, itemHeight, bufferSize);
879
839
  }
880
- child(parent, childSel, styles2) {
881
- return this.createAndAddRule(`${parent} > ${childSel}`, styles2);
840
+ // Lazy load components
841
+ lazy(loadFn) {
842
+ return lazy(loadFn);
882
843
  }
883
- adjacentSibling(element, sibling, styles2) {
884
- return this.createAndAddRule(`${element} + ${sibling}`, styles2);
844
+ // Memory management - cleanup unused elements
845
+ cleanupUnusedElements(root) {
846
+ return cleanupUnusedElements(root, this.elementCache);
885
847
  }
886
- generalSibling(element, sibling, styles2) {
887
- return this.createAndAddRule(`${element} ~ ${sibling}`, styles2);
848
+ // Server-Side Rendering - convert VNode to HTML string
849
+ renderToString(vNode, options = {}) {
850
+ return renderToString(vNode, options);
888
851
  }
889
- multiple(selectors, styles2) {
890
- return this.createAndAddRule(selectors.join(", "), styles2);
852
+ jsonToVNode(json) {
853
+ return jsonToVNode(json, this.reactiveNodes);
891
854
  }
892
- // Nesting (BEM-style)
893
- addName(name, styles2) {
894
- const selector = name.startsWith("--") ? `&${name}` : `&--${name}`;
895
- const rule = { selector, styles: styles2, type: "name" };
896
- return rule;
855
+ vNodeJsonToVNode(json) {
856
+ return vNodeJsonToVNode(json, this.reactiveNodes);
897
857
  }
898
- nesting(parentRule, ...childRules) {
899
- parentRule.nested = childRules;
900
- return parentRule;
858
+ renderJson(rootElement, json) {
859
+ return renderJson(rootElement, json, this.reactiveNodes);
901
860
  }
902
- // @keyframes - Animations
903
- keyframe(name, steps) {
904
- const keyframeSteps = Object.entries(steps).map(([step, styles2]) => ({
905
- step: step === "from" ? "from" : step === "to" ? "to" : `${step}%`,
906
- styles: styles2
907
- }));
908
- const kf = { name, steps: keyframeSteps };
909
- this.keyframes.push(kf);
910
- return kf;
861
+ renderVNode(rootElement, json) {
862
+ return renderVNode(rootElement, json, this.reactiveNodes);
911
863
  }
912
- keyframeFromTo(name, from, to) {
913
- return this.keyframe(name, { from, to });
864
+ renderJsonToString(json, options = {}) {
865
+ return renderJsonToString(json, this.reactiveNodes, options);
914
866
  }
915
- // @font-face - Custom Fonts
916
- fontFace(options) {
917
- this.fontFaces.push(options);
918
- return options;
867
+ renderVNodeToString(json, options = {}) {
868
+ return renderVNodeToString(json, this.reactiveNodes, options);
919
869
  }
920
- // @import - Import Stylesheets
921
- import(url, mediaQuery) {
922
- const importRule = mediaQuery ? `@import url("${url}") ${mediaQuery};` : `@import url("${url}");`;
923
- this.imports.push(importRule);
924
- return importRule;
870
+ // Generate complete HTML document as string (for SSR)
871
+ renderToHTMLDocument(vNode, options = {}) {
872
+ return renderToHTMLDocument(vNode, options);
925
873
  }
926
- // @media - Media Queries
927
- media(type, condition, rules) {
928
- const mediaRule = { type, condition, rules: this.rulesToCSSRules(rules) };
929
- this.mediaRules.push(mediaRule);
930
- return mediaRule;
874
+ // Expose elementCache for reactive updates
875
+ getElementCache() {
876
+ return this.elementCache;
931
877
  }
932
- mediaScreen(condition, rules) {
933
- return this.media("screen", condition, rules);
878
+ };
879
+ var dom = new DomNode();
880
+ var render2 = dom.render.bind(dom);
881
+ var renderToString2 = dom.renderToString.bind(dom);
882
+
883
+ // src/client/style/condition-utils.ts
884
+ function splitConditionalClauses(value, operator) {
885
+ const clauses = [];
886
+ let token = "";
887
+ let depth = 0;
888
+ for (let index = 0; index < value.length; index++) {
889
+ const char = value[index];
890
+ if (char === "(") {
891
+ depth += 1;
892
+ } else if (char === ")" && depth > 0) {
893
+ depth -= 1;
894
+ }
895
+ const operatorToken = ` ${operator} `;
896
+ if (depth === 0 && value.slice(index, index + operatorToken.length).toLowerCase() === operatorToken) {
897
+ const trimmed = token.trim();
898
+ if (trimmed) {
899
+ clauses.push(trimmed);
900
+ }
901
+ token = "";
902
+ index += operatorToken.length - 1;
903
+ continue;
904
+ }
905
+ token += char;
906
+ }
907
+ const trailing = token.trim();
908
+ if (trailing) {
909
+ clauses.push(trailing);
910
+ }
911
+ return clauses;
912
+ }
913
+ function matchesSupportsDeclaration(property, value) {
914
+ const normalizedProperty = property.trim().toLowerCase();
915
+ const normalizedValue = value.trim().toLowerCase();
916
+ const supportedProperties = /* @__PURE__ */ new Set([
917
+ "align-items",
918
+ "background",
919
+ "background-color",
920
+ "backdrop-filter",
921
+ "border",
922
+ "border-radius",
923
+ "box-shadow",
924
+ "color",
925
+ "column-gap",
926
+ "container-name",
927
+ "container-type",
928
+ "display",
929
+ "flex",
930
+ "flex-direction",
931
+ "flex-grow",
932
+ "flex-wrap",
933
+ "font-family",
934
+ "font-size",
935
+ "font-weight",
936
+ "gap",
937
+ "grid-template-columns",
938
+ "height",
939
+ "justify-content",
940
+ "letter-spacing",
941
+ "line-height",
942
+ "margin",
943
+ "margin-bottom",
944
+ "margin-left",
945
+ "margin-right",
946
+ "margin-top",
947
+ "max-height",
948
+ "max-width",
949
+ "min-height",
950
+ "min-width",
951
+ "padding",
952
+ "padding-bottom",
953
+ "padding-end",
954
+ "padding-horizontal",
955
+ "padding-left",
956
+ "padding-right",
957
+ "padding-start",
958
+ "padding-top",
959
+ "padding-vertical",
960
+ "row-gap",
961
+ "text-align",
962
+ "text-decoration",
963
+ "text-transform",
964
+ "width"
965
+ ]);
966
+ if (!supportedProperties.has(normalizedProperty)) {
967
+ return false;
934
968
  }
935
- mediaPrint(rules) {
936
- return this.media("print", "", rules);
969
+ if (normalizedProperty === "display") {
970
+ return (/* @__PURE__ */ new Set(["block", "flex", "grid", "inline", "inline-block", "inline-flex", "inline-grid"])).has(normalizedValue);
937
971
  }
938
- mediaMinWidth(minWidth, rules) {
939
- return this.media("screen", `min-width: ${minWidth}`, rules);
972
+ if (normalizedProperty === "backdrop-filter") {
973
+ return /blur\(/.test(normalizedValue);
940
974
  }
941
- mediaMaxWidth(maxWidth, rules) {
942
- return this.media("screen", `max-width: ${maxWidth}`, rules);
975
+ if (normalizedProperty === "container-type") {
976
+ return (/* @__PURE__ */ new Set(["inline-size", "size"])).has(normalizedValue);
943
977
  }
944
- mediaDark(rules) {
945
- const mediaRule = { type: "", condition: "prefers-color-scheme: dark", rules: this.rulesToCSSRules(rules) };
946
- this.mediaRules.push(mediaRule);
947
- return mediaRule;
978
+ return true;
979
+ }
980
+ function matchesSupportsCondition(condition) {
981
+ const normalized = condition.trim().replace(/^\(+|\)+$/g, "").trim();
982
+ if (!normalized) {
983
+ return true;
948
984
  }
949
- mediaLight(rules) {
950
- const mediaRule = { type: "", condition: "prefers-color-scheme: light", rules: this.rulesToCSSRules(rules) };
951
- this.mediaRules.push(mediaRule);
952
- return mediaRule;
985
+ if (normalized.toLowerCase().startsWith("not ")) {
986
+ return !matchesSupportsCondition(normalized.slice(4));
953
987
  }
954
- mediaReducedMotion(rules) {
955
- const mediaRule = { type: "", condition: "prefers-reduced-motion: reduce", rules: this.rulesToCSSRules(rules) };
956
- this.mediaRules.push(mediaRule);
957
- return mediaRule;
988
+ const orClauses = splitConditionalClauses(normalized, "or");
989
+ if (orClauses.length > 1) {
990
+ return orClauses.some((clause) => matchesSupportsCondition(clause));
958
991
  }
959
- // @container - Container Queries
960
- container(condition, rules, name) {
961
- const containerRule = { name, condition, rules: this.rulesToCSSRules(rules) };
962
- this.containerRules.push(containerRule);
963
- return containerRule;
992
+ const andClauses = splitConditionalClauses(normalized, "and");
993
+ if (andClauses.length > 1) {
994
+ return andClauses.every((clause) => matchesSupportsCondition(clause));
964
995
  }
965
- addContainer(name, styles2) {
966
- const containerStyles = { ...styles2, containerName: name };
967
- return this.addClass(name, containerStyles);
996
+ const declarationMatch = normalized.match(/^([a-z-]+)\s*:\s*(.+)$/i);
997
+ if (!declarationMatch) {
998
+ return false;
968
999
  }
969
- // @supports - Feature Queries
970
- supports(condition, rules) {
971
- const supportsRule = { condition, rules: this.rulesToCSSRules(rules) };
972
- this.supportsRules.push(supportsRule);
973
- return supportsRule;
1000
+ return matchesSupportsDeclaration(declarationMatch[1], declarationMatch[2]);
1001
+ }
1002
+ function findMatchingContainerTarget(ancestors, name) {
1003
+ const normalizedName = typeof name === "string" && name.trim() ? name.trim().toLowerCase() : void 0;
1004
+ for (let index = ancestors.length - 1; index >= 0; index--) {
1005
+ const ancestor = ancestors[index];
1006
+ if (!ancestor?.isContainer || ancestor.containerWidth === void 0) {
1007
+ continue;
1008
+ }
1009
+ if (!normalizedName) {
1010
+ return ancestor;
1011
+ }
1012
+ if ((ancestor.containerNames ?? []).includes(normalizedName)) {
1013
+ return ancestor;
1014
+ }
974
1015
  }
975
- // @layer - Cascade Layers
976
- layerOrder(...layers) {
977
- this._layerOrder = layers;
1016
+ return void 0;
1017
+ }
1018
+ function matchesContainerCondition(condition, containerWidth) {
1019
+ const normalized = condition.trim().replace(/^\(+|\)+$/g, "").trim().toLowerCase();
1020
+ if (!normalized) {
1021
+ return true;
978
1022
  }
979
- layer(name, rules) {
980
- const layerRule = { name, rules: this.rulesToCSSRules(rules) };
981
- this.layerRules.push(layerRule);
982
- return layerRule;
1023
+ if (normalized.startsWith("not ")) {
1024
+ return !matchesContainerCondition(normalized.slice(4), containerWidth);
983
1025
  }
984
- // Custom Rules
985
- add(rules) {
986
- const cssRules = Object.entries(rules).map(([selector, styles2]) => {
987
- const rule = { selector, styles: styles2, type: "custom" };
988
- this.rules.push(rule);
989
- return rule;
990
- });
991
- return cssRules;
1026
+ const orClauses = splitConditionalClauses(normalized, "or");
1027
+ if (orClauses.length > 1) {
1028
+ return orClauses.some((clause) => matchesContainerCondition(clause, containerWidth));
992
1029
  }
993
- important(value) {
994
- return `${value} !important`;
1030
+ const andClauses = splitConditionalClauses(normalized, "and");
1031
+ if (andClauses.length > 1) {
1032
+ return andClauses.every((clause) => matchesContainerCondition(clause, containerWidth));
995
1033
  }
996
- getVariables() {
997
- return Object.fromEntries(this.variables.map((variable) => [variable.name, variable.value]));
1034
+ if (normalized.startsWith("min-width:")) {
1035
+ const minWidth = parseMediaLength(normalized.slice("min-width:".length));
1036
+ return minWidth !== void 0 && containerWidth >= minWidth;
998
1037
  }
999
- resolveVariableReferences(value, variables) {
1000
- let resolved = value;
1001
- for (let index = 0; index < 8; index++) {
1002
- let replaced = false;
1003
- resolved = resolved.replace(/var\(\s*(--[\w-]+)\s*(?:,\s*([^\)]+))?\)/g, (match, name, fallback) => {
1004
- const variableValue = variables[name];
1005
- if (variableValue !== void 0) {
1006
- replaced = true;
1007
- return variableValue;
1008
- }
1009
- if (fallback !== void 0) {
1010
- replaced = true;
1011
- return fallback.trim();
1012
- }
1013
- return match;
1014
- });
1015
- if (!replaced) {
1016
- break;
1017
- }
1038
+ if (normalized.startsWith("max-width:")) {
1039
+ const maxWidth = parseMediaLength(normalized.slice("max-width:".length));
1040
+ return maxWidth !== void 0 && containerWidth <= maxWidth;
1041
+ }
1042
+ return false;
1043
+ }
1044
+ function parseMediaLength(value) {
1045
+ const match = value.trim().match(/^(-?\d+(?:\.\d+)?)(px|rem|em)?$/i);
1046
+ if (!match) {
1047
+ return void 0;
1048
+ }
1049
+ const numericValue = Number(match[1]);
1050
+ const unit = (match[2] ?? "px").toLowerCase();
1051
+ if (unit === "rem" || unit === "em") {
1052
+ return numericValue * 16;
1053
+ }
1054
+ return numericValue;
1055
+ }
1056
+ function matchesMediaCondition(condition, options) {
1057
+ const normalized = condition.trim().replace(/^\(+|\)+$/g, "").trim().toLowerCase();
1058
+ if (!normalized) {
1059
+ return true;
1060
+ }
1061
+ if (normalized.startsWith("min-width:")) {
1062
+ const minWidth = parseMediaLength(normalized.slice("min-width:".length));
1063
+ return minWidth !== void 0 && options.viewportWidth !== void 0 && options.viewportWidth >= minWidth;
1064
+ }
1065
+ if (normalized.startsWith("max-width:")) {
1066
+ const maxWidth = parseMediaLength(normalized.slice("max-width:".length));
1067
+ return maxWidth !== void 0 && options.viewportWidth !== void 0 && options.viewportWidth <= maxWidth;
1068
+ }
1069
+ if (normalized === "prefers-color-scheme: dark") {
1070
+ return options.colorScheme === "dark";
1071
+ }
1072
+ if (normalized === "prefers-color-scheme: light") {
1073
+ return (options.colorScheme ?? "light") === "light";
1074
+ }
1075
+ if (normalized === "prefers-reduced-motion: reduce") {
1076
+ return options.reducedMotion === true;
1077
+ }
1078
+ return false;
1079
+ }
1080
+ function matchesMediaRule(rule, options) {
1081
+ const mediaType = options.mediaType ?? "screen";
1082
+ if (rule.type && rule.type !== mediaType && rule.type !== "all") {
1083
+ return false;
1084
+ }
1085
+ if (!rule.condition.trim()) {
1086
+ return true;
1087
+ }
1088
+ return rule.condition.split(/\band\b/i).map((part) => part.trim()).filter(Boolean).every((part) => matchesMediaCondition(part, options));
1089
+ }
1090
+ function getOrderedLayerNames(layerOrder2, layerRules) {
1091
+ const orderedLayerNames = [];
1092
+ for (const layerName of layerOrder2) {
1093
+ const normalizedName = layerName.trim();
1094
+ if (normalizedName && !orderedLayerNames.includes(normalizedName)) {
1095
+ orderedLayerNames.push(normalizedName);
1018
1096
  }
1019
- return resolved.replace(/\s*!important\s*$/i, "").trim();
1020
1097
  }
1021
- normalizeTargetIdentity(target) {
1022
- return {
1023
- tagName: typeof target.tagName === "string" && target.tagName.trim() ? target.tagName.trim().toLowerCase() : void 0,
1024
- classNames: Array.isArray(target.classNames) ? target.classNames.map((className) => className.trim()).filter(Boolean) : [],
1025
- attributes: target.attributes ? Object.fromEntries(
1026
- Object.entries(target.attributes).filter(([, value]) => value !== void 0 && value !== null && value !== false).map(([name, value]) => [name.toLowerCase(), String(value)])
1027
- ) : {},
1028
- pseudoStates: Array.isArray(target.pseudoStates) ? [...new Set(target.pseudoStates.map((pseudoState) => pseudoState.trim().toLowerCase()).filter(Boolean))] : [],
1029
- childIndex: typeof target.childIndex === "number" && Number.isFinite(target.childIndex) ? target.childIndex : void 0,
1030
- siblingCount: typeof target.siblingCount === "number" && Number.isFinite(target.siblingCount) ? target.siblingCount : void 0,
1031
- sameTypeIndex: typeof target.sameTypeIndex === "number" && Number.isFinite(target.sameTypeIndex) ? target.sameTypeIndex : void 0,
1032
- sameTypeCount: typeof target.sameTypeCount === "number" && Number.isFinite(target.sameTypeCount) ? target.sameTypeCount : void 0,
1033
- containerNames: Array.isArray(target.containerNames) ? [...new Set(target.containerNames.map((containerName) => containerName.trim().toLowerCase()).filter(Boolean))] : [],
1034
- containerWidth: typeof target.containerWidth === "number" && Number.isFinite(target.containerWidth) ? target.containerWidth : void 0,
1035
- isContainer: target.isContainer === true,
1036
- isScopeReference: target.isScopeReference === true
1037
- };
1098
+ for (const layerRule of layerRules) {
1099
+ const normalizedName = layerRule.name.trim();
1100
+ if (normalizedName && !orderedLayerNames.includes(normalizedName)) {
1101
+ orderedLayerNames.push(normalizedName);
1102
+ }
1038
1103
  }
1039
- normalizeTarget(target) {
1040
- const cached = this.nativeTargetNormalizationCache?.get(target);
1041
- if (cached) {
1042
- return cached;
1104
+ return orderedLayerNames;
1105
+ }
1106
+
1107
+ // src/client/style/selector-parser.ts
1108
+ function splitSelectorList(value) {
1109
+ const selectors = [];
1110
+ let token = "";
1111
+ let attributeDepth = 0;
1112
+ let parenthesisDepth = 0;
1113
+ let quoted;
1114
+ for (let index = 0; index < value.length; index++) {
1115
+ const char = value[index];
1116
+ if (quoted) {
1117
+ token += char;
1118
+ if (char === quoted && value[index - 1] !== "\\") {
1119
+ quoted = void 0;
1120
+ }
1121
+ continue;
1043
1122
  }
1044
- const normalized = {
1045
- ...this.normalizeTargetIdentity(target),
1046
- previousSiblings: [],
1047
- nextSiblings: [],
1048
- children: []
1049
- };
1050
- this.nativeTargetNormalizationCache?.set(target, normalized);
1051
- normalized.previousSiblings = Array.isArray(target.previousSiblings) ? target.previousSiblings.map((sibling) => this.normalizeTarget(sibling)) : [];
1052
- normalized.nextSiblings = Array.isArray(target.nextSiblings) ? target.nextSiblings.map((sibling) => this.normalizeTarget(sibling)) : [];
1053
- normalized.children = Array.isArray(target.children) ? target.children.map((child) => this.normalizeTarget(child)) : [];
1054
- return normalized;
1123
+ if (char === '"' || char === "'") {
1124
+ quoted = char;
1125
+ token += char;
1126
+ continue;
1127
+ }
1128
+ if (char === "[") {
1129
+ attributeDepth += 1;
1130
+ token += char;
1131
+ continue;
1132
+ }
1133
+ if (char === "]" && attributeDepth > 0) {
1134
+ attributeDepth -= 1;
1135
+ token += char;
1136
+ continue;
1137
+ }
1138
+ if (attributeDepth === 0 && char === "(") {
1139
+ parenthesisDepth += 1;
1140
+ token += char;
1141
+ continue;
1142
+ }
1143
+ if (attributeDepth === 0 && char === ")" && parenthesisDepth > 0) {
1144
+ parenthesisDepth -= 1;
1145
+ token += char;
1146
+ continue;
1147
+ }
1148
+ if (attributeDepth === 0 && parenthesisDepth === 0 && char === ",") {
1149
+ const trimmed = token.trim();
1150
+ if (trimmed) {
1151
+ selectors.push(trimmed);
1152
+ }
1153
+ token = "";
1154
+ continue;
1155
+ }
1156
+ token += char;
1055
1157
  }
1056
- withNativeTargetNormalizationCache(callback) {
1057
- const previousCache = this.nativeTargetNormalizationCache;
1058
- this.nativeTargetNormalizationCache = /* @__PURE__ */ new WeakMap();
1059
- try {
1060
- return callback();
1061
- } finally {
1062
- this.nativeTargetNormalizationCache = previousCache;
1158
+ const trailing = token.trim();
1159
+ if (trailing) {
1160
+ selectors.push(trailing);
1161
+ }
1162
+ return selectors;
1163
+ }
1164
+ function parsePseudoSelectorToken(token, startIndex) {
1165
+ if (token[startIndex] !== ":" || token[startIndex + 1] === ":") {
1166
+ return void 0;
1167
+ }
1168
+ let cursor = startIndex + 1;
1169
+ const nameMatch = token.slice(cursor).match(/^([_a-zA-Z][-_a-zA-Z0-9]*)/);
1170
+ if (!nameMatch) {
1171
+ return void 0;
1172
+ }
1173
+ const pseudoName = nameMatch[1].toLowerCase();
1174
+ cursor += nameMatch[0].length;
1175
+ if (token[cursor] !== "(") {
1176
+ return { value: pseudoName, nextIndex: cursor };
1177
+ }
1178
+ const argumentStart = cursor + 1;
1179
+ let attributeDepth = 0;
1180
+ let parenthesisDepth = 1;
1181
+ let quoted;
1182
+ cursor += 1;
1183
+ while (cursor < token.length) {
1184
+ const char = token[cursor];
1185
+ if (quoted) {
1186
+ if (char === quoted && token[cursor - 1] !== "\\") {
1187
+ quoted = void 0;
1188
+ }
1189
+ cursor += 1;
1190
+ continue;
1191
+ }
1192
+ if (char === '"' || char === "'") {
1193
+ quoted = char;
1194
+ cursor += 1;
1195
+ continue;
1196
+ }
1197
+ if (char === "[") {
1198
+ attributeDepth += 1;
1199
+ cursor += 1;
1200
+ continue;
1201
+ }
1202
+ if (char === "]" && attributeDepth > 0) {
1203
+ attributeDepth -= 1;
1204
+ cursor += 1;
1205
+ continue;
1206
+ }
1207
+ if (attributeDepth === 0 && char === "(") {
1208
+ parenthesisDepth += 1;
1209
+ cursor += 1;
1210
+ continue;
1211
+ }
1212
+ if (attributeDepth === 0 && char === ")") {
1213
+ parenthesisDepth -= 1;
1214
+ if (parenthesisDepth === 0) {
1215
+ const pseudoArgument = token.slice(argumentStart, cursor).trim();
1216
+ return {
1217
+ value: pseudoArgument.length > 0 ? `${pseudoName}(${pseudoArgument})` : `${pseudoName}()`,
1218
+ nextIndex: cursor + 1
1219
+ };
1220
+ }
1221
+ cursor += 1;
1222
+ continue;
1063
1223
  }
1224
+ cursor += 1;
1064
1225
  }
1065
- splitConditionalClauses(value, operator) {
1066
- const clauses = [];
1067
- let token = "";
1068
- let depth = 0;
1069
- for (let index = 0; index < value.length; index++) {
1070
- const char = value[index];
1071
- if (char === "(") {
1072
- depth += 1;
1073
- } else if (char === ")" && depth > 0) {
1074
- depth -= 1;
1226
+ return void 0;
1227
+ }
1228
+ function parseSimpleSelectorToken(token) {
1229
+ const trimmed = token.trim();
1230
+ if (!trimmed || /[*&]/.test(trimmed)) {
1231
+ return void 0;
1232
+ }
1233
+ let cursor = 0;
1234
+ let tagName;
1235
+ let idName;
1236
+ const classNames = [];
1237
+ const attributes = [];
1238
+ const pseudoClasses = [];
1239
+ const tagMatch = trimmed.slice(cursor).match(/^([_a-zA-Z][-_a-zA-Z0-9]*)/);
1240
+ if (tagMatch) {
1241
+ tagName = tagMatch[1].toLowerCase();
1242
+ cursor += tagMatch[0].length;
1243
+ }
1244
+ while (cursor < trimmed.length) {
1245
+ const char = trimmed[cursor];
1246
+ if (char === ".") {
1247
+ const classMatch = trimmed.slice(cursor).match(/^\.([_a-zA-Z][-_a-zA-Z0-9]*)/);
1248
+ if (!classMatch) {
1249
+ return void 0;
1075
1250
  }
1076
- const operatorToken = ` ${operator} `;
1077
- if (depth === 0 && value.slice(index, index + operatorToken.length).toLowerCase() === operatorToken) {
1078
- const trimmed = token.trim();
1079
- if (trimmed) {
1080
- clauses.push(trimmed);
1081
- }
1082
- token = "";
1083
- index += operatorToken.length - 1;
1084
- continue;
1251
+ classNames.push(classMatch[1]);
1252
+ cursor += classMatch[0].length;
1253
+ continue;
1254
+ }
1255
+ if (char === "#") {
1256
+ const idMatch = trimmed.slice(cursor).match(/^#([_a-zA-Z][-_a-zA-Z0-9]*)/);
1257
+ if (!idMatch || idName) {
1258
+ return void 0;
1085
1259
  }
1086
- token += char;
1260
+ idName = idMatch[1];
1261
+ cursor += idMatch[0].length;
1262
+ continue;
1087
1263
  }
1088
- const trailing = token.trim();
1089
- if (trailing) {
1090
- clauses.push(trailing);
1264
+ if (char === "[") {
1265
+ const endIndex = trimmed.indexOf("]", cursor + 1);
1266
+ if (endIndex === -1) {
1267
+ return void 0;
1268
+ }
1269
+ const rawAttribute = trimmed.slice(cursor + 1, endIndex).trim();
1270
+ const attrMatch = rawAttribute.match(/^([_a-zA-Z][-_a-zA-Z0-9]*)(?:\s*(=|~=|\^=|\$=|\*=)\s*(?:"([^"]*)"|'([^']*)'|([^\s"']+)))?$/);
1271
+ if (!attrMatch) {
1272
+ return void 0;
1273
+ }
1274
+ attributes.push({
1275
+ name: attrMatch[1].toLowerCase(),
1276
+ operator: attrMatch[2],
1277
+ value: attrMatch[3] ?? attrMatch[4] ?? attrMatch[5]
1278
+ });
1279
+ cursor = endIndex + 1;
1280
+ continue;
1281
+ }
1282
+ if (char === ":") {
1283
+ const pseudoToken = parsePseudoSelectorToken(trimmed, cursor);
1284
+ if (!pseudoToken) {
1285
+ return void 0;
1286
+ }
1287
+ pseudoClasses.push(pseudoToken.value);
1288
+ cursor = pseudoToken.nextIndex;
1289
+ continue;
1091
1290
  }
1092
- return clauses;
1291
+ return void 0;
1292
+ }
1293
+ if (!tagName && !idName && classNames.length === 0 && attributes.length === 0 && pseudoClasses.length === 0) {
1294
+ return void 0;
1093
1295
  }
1094
- splitSelectorList(value) {
1095
- const selectors = [];
1296
+ return { tagName, idName, classNames, attributes, pseudoClasses };
1297
+ }
1298
+ function extractSupportedSelectorChains(selector, parsedSelectorChainCache) {
1299
+ const cached = parsedSelectorChainCache.get(selector);
1300
+ if (cached) {
1301
+ return cached;
1302
+ }
1303
+ const parsedChains = splitSelectorList(selector).map((segment) => segment.trim()).map((segment) => {
1304
+ const chain = [];
1096
1305
  let token = "";
1306
+ let combinator = "descendant";
1307
+ let invalid = false;
1097
1308
  let attributeDepth = 0;
1098
1309
  let parenthesisDepth = 0;
1099
1310
  let quoted;
1100
- for (let index = 0; index < value.length; index++) {
1101
- const char = value[index];
1311
+ const flushToken = () => {
1312
+ const trimmedToken = token.trim();
1313
+ token = "";
1314
+ if (!trimmedToken || invalid) {
1315
+ return;
1316
+ }
1317
+ const parsed = parseSimpleSelectorToken(trimmedToken);
1318
+ if (!parsed) {
1319
+ invalid = true;
1320
+ return;
1321
+ }
1322
+ if (chain.length > 0) {
1323
+ parsed.combinator = combinator;
1324
+ }
1325
+ chain.push(parsed);
1326
+ combinator = "descendant";
1327
+ };
1328
+ for (let index = 0; index < segment.length; index++) {
1329
+ const char = segment[index];
1102
1330
  if (quoted) {
1103
1331
  token += char;
1104
- if (char === quoted && value[index - 1] !== "\\") {
1332
+ if (char === quoted && segment[index - 1] !== "\\") {
1105
1333
  quoted = void 0;
1106
1334
  }
1107
1335
  continue;
@@ -1116,8 +1344,10 @@ var CreateStyle = class {
1116
1344
  token += char;
1117
1345
  continue;
1118
1346
  }
1119
- if (char === "]" && attributeDepth > 0) {
1120
- attributeDepth -= 1;
1347
+ if (char === "]") {
1348
+ if (attributeDepth > 0) {
1349
+ attributeDepth -= 1;
1350
+ }
1121
1351
  token += char;
1122
1352
  continue;
1123
1353
  }
@@ -1131,374 +1361,159 @@ var CreateStyle = class {
1131
1361
  token += char;
1132
1362
  continue;
1133
1363
  }
1134
- if (attributeDepth === 0 && parenthesisDepth === 0 && char === ",") {
1135
- const trimmed = token.trim();
1136
- if (trimmed) {
1137
- selectors.push(trimmed);
1364
+ if (attributeDepth === 0 && parenthesisDepth === 0 && (char === ">" || char === "+" || char === "~")) {
1365
+ flushToken();
1366
+ if (invalid) {
1367
+ break;
1138
1368
  }
1139
- token = "";
1369
+ combinator = char === ">" ? "child" : char === "+" ? "adjacent-sibling" : "general-sibling";
1140
1370
  continue;
1141
1371
  }
1142
- token += char;
1143
- }
1144
- const trailing = token.trim();
1145
- if (trailing) {
1146
- selectors.push(trailing);
1147
- }
1148
- return selectors;
1149
- }
1150
- parsePseudoSelectorToken(token, startIndex) {
1151
- if (token[startIndex] !== ":" || token[startIndex + 1] === ":") {
1152
- return void 0;
1153
- }
1154
- let cursor = startIndex + 1;
1155
- const nameMatch = token.slice(cursor).match(/^([_a-zA-Z][-_a-zA-Z0-9]*)/);
1156
- if (!nameMatch) {
1157
- return void 0;
1158
- }
1159
- const pseudoName = nameMatch[1].toLowerCase();
1160
- cursor += nameMatch[0].length;
1161
- if (token[cursor] !== "(") {
1162
- return { value: pseudoName, nextIndex: cursor };
1163
- }
1164
- const argumentStart = cursor + 1;
1165
- let attributeDepth = 0;
1166
- let parenthesisDepth = 1;
1167
- let quoted;
1168
- cursor += 1;
1169
- while (cursor < token.length) {
1170
- const char = token[cursor];
1171
- if (quoted) {
1172
- if (char === quoted && token[cursor - 1] !== "\\") {
1173
- quoted = void 0;
1174
- }
1175
- cursor += 1;
1176
- continue;
1177
- }
1178
- if (char === '"' || char === "'") {
1179
- quoted = char;
1180
- cursor += 1;
1181
- continue;
1182
- }
1183
- if (char === "[") {
1184
- attributeDepth += 1;
1185
- cursor += 1;
1186
- continue;
1187
- }
1188
- if (char === "]" && attributeDepth > 0) {
1189
- attributeDepth -= 1;
1190
- cursor += 1;
1191
- continue;
1192
- }
1193
- if (attributeDepth === 0 && char === "(") {
1194
- parenthesisDepth += 1;
1195
- cursor += 1;
1196
- continue;
1197
- }
1198
- if (attributeDepth === 0 && char === ")") {
1199
- parenthesisDepth -= 1;
1200
- if (parenthesisDepth === 0) {
1201
- const pseudoArgument = token.slice(argumentStart, cursor).trim();
1202
- return {
1203
- value: pseudoArgument.length > 0 ? `${pseudoName}(${pseudoArgument})` : `${pseudoName}()`,
1204
- nextIndex: cursor + 1
1205
- };
1372
+ if (attributeDepth === 0 && parenthesisDepth === 0 && /\s/.test(char)) {
1373
+ flushToken();
1374
+ if (invalid) {
1375
+ break;
1206
1376
  }
1207
- cursor += 1;
1208
1377
  continue;
1209
1378
  }
1210
- cursor += 1;
1211
- }
1212
- return void 0;
1213
- }
1214
- matchesSupportsDeclaration(property, value) {
1215
- const normalizedProperty = property.trim().toLowerCase();
1216
- const normalizedValue = value.trim().toLowerCase();
1217
- const supportedProperties = /* @__PURE__ */ new Set([
1218
- "align-items",
1219
- "background",
1220
- "background-color",
1221
- "backdrop-filter",
1222
- "border",
1223
- "border-radius",
1224
- "box-shadow",
1225
- "color",
1226
- "column-gap",
1227
- "container-name",
1228
- "container-type",
1229
- "display",
1230
- "flex",
1231
- "flex-direction",
1232
- "flex-grow",
1233
- "flex-wrap",
1234
- "font-family",
1235
- "font-size",
1236
- "font-weight",
1237
- "gap",
1238
- "grid-template-columns",
1239
- "height",
1240
- "justify-content",
1241
- "letter-spacing",
1242
- "line-height",
1243
- "margin",
1244
- "margin-bottom",
1245
- "margin-left",
1246
- "margin-right",
1247
- "margin-top",
1248
- "max-height",
1249
- "max-width",
1250
- "min-height",
1251
- "min-width",
1252
- "padding",
1253
- "padding-bottom",
1254
- "padding-end",
1255
- "padding-horizontal",
1256
- "padding-left",
1257
- "padding-right",
1258
- "padding-start",
1259
- "padding-top",
1260
- "padding-vertical",
1261
- "row-gap",
1262
- "text-align",
1263
- "text-decoration",
1264
- "text-transform",
1265
- "width"
1266
- ]);
1267
- if (!supportedProperties.has(normalizedProperty)) {
1268
- return false;
1269
- }
1270
- if (normalizedProperty === "display") {
1271
- return (/* @__PURE__ */ new Set(["block", "flex", "grid", "inline", "inline-block", "inline-flex", "inline-grid"])).has(normalizedValue);
1272
- }
1273
- if (normalizedProperty === "backdrop-filter") {
1274
- return /blur\(/.test(normalizedValue);
1275
- }
1276
- if (normalizedProperty === "container-type") {
1277
- return (/* @__PURE__ */ new Set(["inline-size", "size"])).has(normalizedValue);
1278
- }
1279
- return true;
1280
- }
1281
- matchesSupportsCondition(condition) {
1282
- const normalized = condition.trim().replace(/^\(+|\)+$/g, "").trim();
1283
- if (!normalized) {
1284
- return true;
1285
- }
1286
- if (normalized.toLowerCase().startsWith("not ")) {
1287
- return !this.matchesSupportsCondition(normalized.slice(4));
1288
- }
1289
- const orClauses = this.splitConditionalClauses(normalized, "or");
1290
- if (orClauses.length > 1) {
1291
- return orClauses.some((clause) => this.matchesSupportsCondition(clause));
1292
- }
1293
- const andClauses = this.splitConditionalClauses(normalized, "and");
1294
- if (andClauses.length > 1) {
1295
- return andClauses.every((clause) => this.matchesSupportsCondition(clause));
1379
+ token += char;
1296
1380
  }
1297
- const declarationMatch = normalized.match(/^([a-z-]+)\s*:\s*(.+)$/i);
1298
- if (!declarationMatch) {
1299
- return false;
1381
+ flushToken();
1382
+ if (invalid || chain.length === 0) {
1383
+ return void 0;
1300
1384
  }
1301
- return this.matchesSupportsDeclaration(declarationMatch[1], declarationMatch[2]);
1385
+ return chain.some((part) => Boolean(part.tagName) || Boolean(part.idName) || part.classNames.length > 0 || part.attributes.length > 0 || part.pseudoClasses.length > 0) ? chain : void 0;
1386
+ }).filter((segment) => Array.isArray(segment) && segment.length > 0);
1387
+ parsedSelectorChainCache.set(selector, parsedChains);
1388
+ return parsedChains;
1389
+ }
1390
+
1391
+ // src/client/style/native-resolver.ts
1392
+ var NativeStyleResolver = class {
1393
+ constructor() {
1394
+ this.parsedSelectorChainCache = /* @__PURE__ */ new Map();
1302
1395
  }
1303
- findMatchingContainerTarget(ancestors, name) {
1304
- const normalizedName = typeof name === "string" && name.trim() ? name.trim().toLowerCase() : void 0;
1305
- for (let index = ancestors.length - 1; index >= 0; index--) {
1306
- const ancestor = ancestors[index];
1307
- if (!ancestor?.isContainer || ancestor.containerWidth === void 0) {
1308
- continue;
1309
- }
1310
- if (!normalizedName) {
1311
- return ancestor;
1312
- }
1313
- if ((ancestor.containerNames ?? []).includes(normalizedName)) {
1314
- return ancestor;
1396
+ resolveNativeStyles(target, ancestors = [], options = {}, context) {
1397
+ return this.withNativeTargetNormalizationCache(() => {
1398
+ const normalizedTarget = this.normalizeTarget(target);
1399
+ if (!normalizedTarget.tagName && (!normalizedTarget.classNames || normalizedTarget.classNames.length === 0)) {
1400
+ return {};
1315
1401
  }
1316
- }
1317
- return void 0;
1318
- }
1319
- matchesContainerCondition(condition, containerWidth) {
1320
- const normalized = condition.trim().replace(/^\(+|\)+$/g, "").trim().toLowerCase();
1321
- if (!normalized) {
1322
- return true;
1323
- }
1324
- if (normalized.startsWith("not ")) {
1325
- return !this.matchesContainerCondition(normalized.slice(4), containerWidth);
1326
- }
1327
- const orClauses = this.splitConditionalClauses(normalized, "or");
1328
- if (orClauses.length > 1) {
1329
- return orClauses.some((clause) => this.matchesContainerCondition(clause, containerWidth));
1330
- }
1331
- const andClauses = this.splitConditionalClauses(normalized, "and");
1332
- if (andClauses.length > 1) {
1333
- return andClauses.every((clause) => this.matchesContainerCondition(clause, containerWidth));
1334
- }
1335
- if (normalized.startsWith("min-width:")) {
1336
- const minWidth = this.parseMediaLength(normalized.slice("min-width:".length));
1337
- return minWidth !== void 0 && containerWidth >= minWidth;
1338
- }
1339
- if (normalized.startsWith("max-width:")) {
1340
- const maxWidth = this.parseMediaLength(normalized.slice("max-width:".length));
1341
- return maxWidth !== void 0 && containerWidth <= maxWidth;
1342
- }
1343
- return false;
1344
- }
1345
- parseSimpleSelectorToken(token) {
1346
- const trimmed = token.trim();
1347
- if (!trimmed || /[*&]/.test(trimmed)) {
1348
- return void 0;
1349
- }
1350
- let cursor = 0;
1351
- let tagName;
1352
- let idName;
1353
- const classNames = [];
1354
- const attributes = [];
1355
- const pseudoClasses = [];
1356
- const tagMatch = trimmed.slice(cursor).match(/^([_a-zA-Z][-_a-zA-Z0-9]*)/);
1357
- if (tagMatch) {
1358
- tagName = tagMatch[1].toLowerCase();
1359
- cursor += tagMatch[0].length;
1360
- }
1361
- while (cursor < trimmed.length) {
1362
- const char = trimmed[cursor];
1363
- if (char === ".") {
1364
- const classMatch = trimmed.slice(cursor).match(/^\.([_a-zA-Z][-_a-zA-Z0-9]*)/);
1365
- if (!classMatch) {
1366
- return void 0;
1402
+ const normalizedAncestors = ancestors.map((ancestor) => this.normalizeTarget(ancestor));
1403
+ const resolved = {};
1404
+ const applyRules = (rules) => {
1405
+ for (const rule of rules) {
1406
+ const selectorChains = extractSupportedSelectorChains(rule.selector, this.parsedSelectorChainCache);
1407
+ if (selectorChains.length === 0) {
1408
+ continue;
1409
+ }
1410
+ const matches = selectorChains.some((selectorChain) => this.matchesSelectorChain(normalizedTarget, normalizedAncestors, selectorChain));
1411
+ if (!matches) {
1412
+ continue;
1413
+ }
1414
+ for (const [property, value] of Object.entries(rule.styles)) {
1415
+ resolved[property] = typeof value === "string" ? this.resolveVariableReferences(value, context.variables) : value;
1416
+ }
1417
+ }
1418
+ };
1419
+ for (const layerName of getOrderedLayerNames(context.layerOrder, context.layerRules)) {
1420
+ for (const layerRule of context.layerRules) {
1421
+ if (layerRule.name.trim() === layerName) {
1422
+ applyRules(layerRule.rules);
1423
+ }
1367
1424
  }
1368
- classNames.push(classMatch[1]);
1369
- cursor += classMatch[0].length;
1370
- continue;
1371
1425
  }
1372
- if (char === "#") {
1373
- const idMatch = trimmed.slice(cursor).match(/^#([_a-zA-Z][-_a-zA-Z0-9]*)/);
1374
- if (!idMatch || idName) {
1375
- return void 0;
1426
+ applyRules(context.rules);
1427
+ for (const supportsRule of context.supportsRules) {
1428
+ if (matchesSupportsCondition(supportsRule.condition)) {
1429
+ applyRules(supportsRule.rules);
1376
1430
  }
1377
- idName = idMatch[1];
1378
- cursor += idMatch[0].length;
1379
- continue;
1380
1431
  }
1381
- if (char === "[") {
1382
- const endIndex = trimmed.indexOf("]", cursor + 1);
1383
- if (endIndex === -1) {
1384
- return void 0;
1432
+ for (const containerRule of context.containerRules) {
1433
+ const matchingContainer = findMatchingContainerTarget(normalizedAncestors, containerRule.name);
1434
+ if (matchingContainer && this.hasContainerWidth(matchingContainer) && matchesContainerCondition(containerRule.condition, matchingContainer.containerWidth)) {
1435
+ applyRules(containerRule.rules);
1385
1436
  }
1386
- const rawAttribute = trimmed.slice(cursor + 1, endIndex).trim();
1387
- const attrMatch = rawAttribute.match(/^([_a-zA-Z][-_a-zA-Z0-9]*)(?:\s*(=|~=|\^=|\$=|\*=)\s*(?:"([^"]*)"|'([^']*)'|([^\s"']+)))?$/);
1388
- if (!attrMatch) {
1389
- return void 0;
1437
+ }
1438
+ for (const mediaRule of context.mediaRules) {
1439
+ if (matchesMediaRule(mediaRule, options)) {
1440
+ applyRules(mediaRule.rules);
1390
1441
  }
1391
- attributes.push({
1392
- name: attrMatch[1].toLowerCase(),
1393
- operator: attrMatch[2],
1394
- value: attrMatch[3] ?? attrMatch[4] ?? attrMatch[5]
1395
- });
1396
- cursor = endIndex + 1;
1397
- continue;
1398
1442
  }
1399
- if (char === ":") {
1400
- const pseudoToken = this.parsePseudoSelectorToken(trimmed, cursor);
1401
- if (!pseudoToken) {
1402
- return void 0;
1443
+ return resolved;
1444
+ });
1445
+ }
1446
+ resolveClassStyles(classNames, context) {
1447
+ return this.resolveNativeStyles({ classNames }, [], {}, context);
1448
+ }
1449
+ hasContainerWidth(target) {
1450
+ return typeof target.containerWidth === "number" && Number.isFinite(target.containerWidth);
1451
+ }
1452
+ resolveVariableReferences(value, variables) {
1453
+ let resolved = value;
1454
+ for (let index = 0; index < 8; index++) {
1455
+ let replaced = false;
1456
+ resolved = resolved.replace(/var\(\s*(--[\w-]+)\s*(?:,\s*([^\)]+))?\)/g, (match, name, fallback) => {
1457
+ const variableValue = variables[name];
1458
+ if (variableValue !== void 0) {
1459
+ replaced = true;
1460
+ return variableValue;
1403
1461
  }
1404
- pseudoClasses.push(pseudoToken.value);
1405
- cursor = pseudoToken.nextIndex;
1406
- continue;
1462
+ if (fallback !== void 0) {
1463
+ replaced = true;
1464
+ return fallback.trim();
1465
+ }
1466
+ return match;
1467
+ });
1468
+ if (!replaced) {
1469
+ break;
1407
1470
  }
1408
- return void 0;
1409
- }
1410
- if (!tagName && !idName && classNames.length === 0 && attributes.length === 0 && pseudoClasses.length === 0) {
1411
- return void 0;
1412
1471
  }
1413
- return { tagName, idName, classNames, attributes, pseudoClasses };
1472
+ return resolved.replace(/\s*!important\s*$/i, "").trim();
1473
+ }
1474
+ normalizeTargetIdentity(target) {
1475
+ return {
1476
+ tagName: typeof target.tagName === "string" && target.tagName.trim() ? target.tagName.trim().toLowerCase() : void 0,
1477
+ classNames: Array.isArray(target.classNames) ? target.classNames.map((className) => className.trim()).filter(Boolean) : [],
1478
+ attributes: target.attributes ? Object.fromEntries(
1479
+ Object.entries(target.attributes).filter(([, value]) => value !== void 0 && value !== null && value !== false).map(([name, value]) => [name.toLowerCase(), String(value)])
1480
+ ) : {},
1481
+ pseudoStates: Array.isArray(target.pseudoStates) ? [...new Set(target.pseudoStates.map((pseudoState) => pseudoState.trim().toLowerCase()).filter(Boolean))] : [],
1482
+ childIndex: typeof target.childIndex === "number" && Number.isFinite(target.childIndex) ? target.childIndex : void 0,
1483
+ siblingCount: typeof target.siblingCount === "number" && Number.isFinite(target.siblingCount) ? target.siblingCount : void 0,
1484
+ sameTypeIndex: typeof target.sameTypeIndex === "number" && Number.isFinite(target.sameTypeIndex) ? target.sameTypeIndex : void 0,
1485
+ sameTypeCount: typeof target.sameTypeCount === "number" && Number.isFinite(target.sameTypeCount) ? target.sameTypeCount : void 0,
1486
+ containerNames: Array.isArray(target.containerNames) ? [...new Set(target.containerNames.map((containerName) => containerName.trim().toLowerCase()).filter(Boolean))] : [],
1487
+ containerWidth: typeof target.containerWidth === "number" && Number.isFinite(target.containerWidth) ? target.containerWidth : void 0,
1488
+ isContainer: target.isContainer === true,
1489
+ isScopeReference: target.isScopeReference === true
1490
+ };
1414
1491
  }
1415
- extractSupportedSelectorChains(selector) {
1416
- const cached = this.parsedSelectorChainCache.get(selector);
1492
+ normalizeTarget(target) {
1493
+ const cached = this.nativeTargetNormalizationCache?.get(target);
1417
1494
  if (cached) {
1418
1495
  return cached;
1419
1496
  }
1420
- const parsedChains = this.splitSelectorList(selector).map((segment) => segment.trim()).map((segment) => {
1421
- const chain = [];
1422
- let token = "";
1423
- let combinator = "descendant";
1424
- let invalid = false;
1425
- let attributeDepth = 0;
1426
- let parenthesisDepth = 0;
1427
- let quoted;
1428
- const flushToken = () => {
1429
- const trimmedToken = token.trim();
1430
- token = "";
1431
- if (!trimmedToken || invalid) {
1432
- return;
1433
- }
1434
- const parsed = this.parseSimpleSelectorToken(trimmedToken);
1435
- if (!parsed) {
1436
- invalid = true;
1437
- return;
1438
- }
1439
- if (chain.length > 0) {
1440
- parsed.combinator = combinator;
1441
- }
1442
- chain.push(parsed);
1443
- combinator = "descendant";
1444
- };
1445
- for (let index = 0; index < segment.length; index++) {
1446
- const char = segment[index];
1447
- if (quoted) {
1448
- token += char;
1449
- if (char === quoted && segment[index - 1] !== "\\") {
1450
- quoted = void 0;
1451
- }
1452
- continue;
1453
- }
1454
- if (char === '"' || char === "'") {
1455
- quoted = char;
1456
- token += char;
1457
- continue;
1458
- }
1459
- if (char === "[") {
1460
- attributeDepth += 1;
1461
- token += char;
1462
- continue;
1463
- }
1464
- if (char === "]") {
1465
- if (attributeDepth > 0) {
1466
- attributeDepth -= 1;
1467
- }
1468
- token += char;
1469
- continue;
1470
- }
1471
- if (attributeDepth === 0 && char === "(") {
1472
- parenthesisDepth += 1;
1473
- token += char;
1474
- continue;
1475
- }
1476
- if (attributeDepth === 0 && char === ")" && parenthesisDepth > 0) {
1477
- parenthesisDepth -= 1;
1478
- token += char;
1479
- continue;
1480
- }
1481
- if (attributeDepth === 0 && parenthesisDepth === 0 && (char === ">" || char === "+" || char === "~")) {
1482
- flushToken();
1483
- if (invalid) break;
1484
- combinator = char === ">" ? "child" : char === "+" ? "adjacent-sibling" : "general-sibling";
1485
- continue;
1486
- }
1487
- if (attributeDepth === 0 && parenthesisDepth === 0 && /\s/.test(char)) {
1488
- flushToken();
1489
- if (invalid) break;
1490
- continue;
1491
- }
1492
- token += char;
1493
- }
1494
- flushToken();
1495
- if (invalid || chain.length === 0) {
1496
- return void 0;
1497
- }
1498
- return chain.some((part) => Boolean(part.tagName) || Boolean(part.idName) || part.classNames.length > 0 || part.attributes.length > 0 || part.pseudoClasses.length > 0) ? chain : void 0;
1499
- }).filter((segment) => Array.isArray(segment) && segment.length > 0);
1500
- this.parsedSelectorChainCache.set(selector, parsedChains);
1501
- return parsedChains;
1497
+ const normalized = {
1498
+ ...this.normalizeTargetIdentity(target),
1499
+ previousSiblings: [],
1500
+ nextSiblings: [],
1501
+ children: []
1502
+ };
1503
+ this.nativeTargetNormalizationCache?.set(target, normalized);
1504
+ normalized.previousSiblings = Array.isArray(target.previousSiblings) ? target.previousSiblings.map((sibling) => this.normalizeTarget(sibling)) : [];
1505
+ normalized.nextSiblings = Array.isArray(target.nextSiblings) ? target.nextSiblings.map((sibling) => this.normalizeTarget(sibling)) : [];
1506
+ normalized.children = Array.isArray(target.children) ? target.children.map((child) => this.normalizeTarget(child)) : [];
1507
+ return normalized;
1508
+ }
1509
+ withNativeTargetNormalizationCache(callback) {
1510
+ const previousCache = this.nativeTargetNormalizationCache;
1511
+ this.nativeTargetNormalizationCache = /* @__PURE__ */ new WeakMap();
1512
+ try {
1513
+ return callback();
1514
+ } finally {
1515
+ this.nativeTargetNormalizationCache = previousCache;
1516
+ }
1502
1517
  }
1503
1518
  matchesAttributeSelector(targetValue, selector) {
1504
1519
  if (selector.operator === void 0) {
@@ -1585,13 +1600,13 @@ var CreateStyle = class {
1585
1600
  if (!pseudoArgument) {
1586
1601
  return false;
1587
1602
  }
1588
- const selectorArguments = this.splitSelectorList(pseudoArgument);
1603
+ const selectorArguments = splitSelectorList(pseudoArgument);
1589
1604
  if (selectorArguments.length === 0) {
1590
1605
  return false;
1591
1606
  }
1592
1607
  const parsedSelectors = [];
1593
1608
  for (const selectorArgument of selectorArguments) {
1594
- const parsedSelector = this.parseSimpleSelectorToken(selectorArgument);
1609
+ const parsedSelector = parseSimpleSelectorToken(selectorArgument);
1595
1610
  if (!parsedSelector) {
1596
1611
  return false;
1597
1612
  }
@@ -1640,7 +1655,7 @@ var CreateStyle = class {
1640
1655
  return Number.isInteger(n) && n >= 0;
1641
1656
  }
1642
1657
  matchesHasPseudoClass(target, pseudoArgument) {
1643
- const selectorArguments = this.splitSelectorList(pseudoArgument);
1658
+ const selectorArguments = splitSelectorList(pseudoArgument);
1644
1659
  if (selectorArguments.length === 0) {
1645
1660
  return false;
1646
1661
  }
@@ -1655,7 +1670,7 @@ var CreateStyle = class {
1655
1670
  if (!scopeRelativeSelector) {
1656
1671
  return false;
1657
1672
  }
1658
- const selectorChains = this.extractSupportedSelectorChains(scopeRelativeSelector);
1673
+ const selectorChains = extractSupportedSelectorChains(scopeRelativeSelector, this.parsedSelectorChainCache);
1659
1674
  if (selectorChains.length === 0) {
1660
1675
  return false;
1661
1676
  }
@@ -1762,289 +1777,404 @@ var CreateStyle = class {
1762
1777
  }
1763
1778
  }
1764
1779
  }
1765
- parseMediaLength(value) {
1766
- const match = value.trim().match(/^(-?\d+(?:\.\d+)?)(px|rem|em)?$/i);
1767
- if (!match) {
1768
- return void 0;
1769
- }
1770
- const numericValue = Number(match[1]);
1771
- const unit = (match[2] ?? "px").toLowerCase();
1772
- if (unit === "rem" || unit === "em") {
1773
- return numericValue * 16;
1774
- }
1775
- return numericValue;
1780
+ };
1781
+
1782
+ // src/client/style/renderer.ts
1783
+ function toKebabCase(str) {
1784
+ return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
1785
+ }
1786
+ function stylesToString(styles2, indent = " ") {
1787
+ return Object.entries(styles2).map(([prop, value]) => {
1788
+ const cssValue = typeof value === "object" && value !== null && "name" in value ? `var(${value.name})` : value;
1789
+ return `${indent}${toKebabCase(prop)}: ${cssValue};`;
1790
+ }).join("\n");
1791
+ }
1792
+ function renderRule(rule, indent = "") {
1793
+ let css = `${indent}${rule.selector} {
1794
+ ${stylesToString(rule.styles, indent + " ")}
1795
+ `;
1796
+ if (rule.nested && rule.nested.length > 0) {
1797
+ for (const nestedRule of rule.nested) {
1798
+ const nestedSelector = nestedRule.selector.startsWith("&") ? nestedRule.selector.replace(/&/g, rule.selector) : `${rule.selector} ${nestedRule.selector}`;
1799
+ css += `
1800
+ ${indent}${nestedSelector} {
1801
+ ${stylesToString(nestedRule.styles, indent + " ")}
1802
+ ${indent}}
1803
+ `;
1804
+ }
1805
+ }
1806
+ css += `${indent}}`;
1807
+ return css;
1808
+ }
1809
+ function renderRulesWithIndent(rules, indent = " ") {
1810
+ return rules.map((rule) => renderRule(rule, indent)).join("\n");
1811
+ }
1812
+ function renderMediaRule(media) {
1813
+ const condition = media.type && media.condition ? `${media.type} and (${media.condition})` : media.type ? media.type : `(${media.condition})`;
1814
+ return `@media ${condition} {
1815
+ ${renderRulesWithIndent(media.rules)}
1816
+ }`;
1817
+ }
1818
+ function renderKeyframes(kf) {
1819
+ let css = `@keyframes ${kf.name} {
1820
+ `;
1821
+ for (const step of kf.steps) {
1822
+ css += ` ${step.step} {
1823
+ ${stylesToString(step.styles, " ")}
1824
+ }
1825
+ `;
1826
+ }
1827
+ css += "}";
1828
+ return css;
1829
+ }
1830
+ function renderFontFace(ff) {
1831
+ let css = "@font-face {\n";
1832
+ css += ` font-family: "${ff.fontFamily}";
1833
+ `;
1834
+ css += ` src: ${ff.src};
1835
+ `;
1836
+ if (ff.fontWeight) css += ` font-weight: ${ff.fontWeight};
1837
+ `;
1838
+ if (ff.fontStyle) css += ` font-style: ${ff.fontStyle};
1839
+ `;
1840
+ if (ff.fontDisplay) css += ` font-display: ${ff.fontDisplay};
1841
+ `;
1842
+ if (ff.unicodeRange) css += ` unicode-range: ${ff.unicodeRange};
1843
+ `;
1844
+ css += "}";
1845
+ return css;
1846
+ }
1847
+ function renderContainerRule(container2) {
1848
+ const nameStr = container2.name ? `${container2.name} ` : "";
1849
+ return `@container ${nameStr}(${container2.condition}) {
1850
+ ${renderRulesWithIndent(container2.rules)}
1851
+ }`;
1852
+ }
1853
+ function renderSupportsRule(supports) {
1854
+ return `@supports (${supports.condition}) {
1855
+ ${renderRulesWithIndent(supports.rules)}
1856
+ }`;
1857
+ }
1858
+ function renderLayerRule(layer2) {
1859
+ return `@layer ${layer2.name} {
1860
+ ${renderRulesWithIndent(layer2.rules)}
1861
+ }`;
1862
+ }
1863
+ function renderStyleSheet(context, ...additionalRules) {
1864
+ const parts = [];
1865
+ if (context.imports.length > 0) {
1866
+ parts.push(context.imports.join("\n"));
1867
+ }
1868
+ if (context.layerOrder.length > 0) {
1869
+ parts.push(`@layer ${context.layerOrder.join(", ")};`);
1870
+ }
1871
+ if (context.variables.length > 0) {
1872
+ const varDeclarations = context.variables.map((variable) => ` ${variable.name}: ${variable.value};`).join("\n");
1873
+ parts.push(`:root {
1874
+ ${varDeclarations}
1875
+ }`);
1876
+ }
1877
+ for (const ff of context.fontFaces) {
1878
+ parts.push(renderFontFace(ff));
1879
+ }
1880
+ for (const kf of context.keyframes) {
1881
+ parts.push(renderKeyframes(kf));
1882
+ }
1883
+ const allRules = [...context.rules];
1884
+ const allMediaRules = [...context.mediaRules];
1885
+ const allKeyframes = [];
1886
+ const allContainerRules = [...context.containerRules];
1887
+ const allSupportsRules = [...context.supportsRules];
1888
+ const allLayerRules = [...context.layerRules];
1889
+ for (const item of additionalRules) {
1890
+ if (!item) {
1891
+ continue;
1892
+ }
1893
+ if (Array.isArray(item)) {
1894
+ allRules.push(...item);
1895
+ } else if ("condition" in item && "rules" in item && !("name" in item && "steps" in item)) {
1896
+ if ("type" in item) {
1897
+ allMediaRules.push(item);
1898
+ } else if ("name" in item && typeof item.name === "string") {
1899
+ allContainerRules.push(item);
1900
+ } else {
1901
+ allSupportsRules.push(item);
1902
+ }
1903
+ } else if ("name" in item && "steps" in item) {
1904
+ allKeyframes.push(item);
1905
+ } else if ("name" in item && "rules" in item) {
1906
+ allLayerRules.push(item);
1907
+ } else {
1908
+ allRules.push(item);
1909
+ }
1910
+ }
1911
+ for (const kf of allKeyframes) {
1912
+ parts.push(renderKeyframes(kf));
1913
+ }
1914
+ for (const layer2 of allLayerRules) {
1915
+ parts.push(renderLayerRule(layer2));
1916
+ }
1917
+ for (const rule of allRules) {
1918
+ parts.push(renderRule(rule));
1919
+ }
1920
+ for (const supports of allSupportsRules) {
1921
+ parts.push(renderSupportsRule(supports));
1922
+ }
1923
+ for (const container2 of allContainerRules) {
1924
+ parts.push(renderContainerRule(container2));
1925
+ }
1926
+ for (const media of allMediaRules) {
1927
+ parts.push(renderMediaRule(media));
1928
+ }
1929
+ return parts.join("\n\n");
1930
+ }
1931
+
1932
+ // src/client/style/store.ts
1933
+ var ELIT_SHARED_STYLE_STORE_KEY = "__elitSharedStyleStore__";
1934
+ function createStyleStore() {
1935
+ return {
1936
+ variables: [],
1937
+ rules: [],
1938
+ mediaRules: [],
1939
+ keyframes: [],
1940
+ fontFaces: [],
1941
+ imports: [],
1942
+ containerRules: [],
1943
+ supportsRules: [],
1944
+ layerRules: [],
1945
+ layerOrder: []
1946
+ };
1947
+ }
1948
+ function getSharedStyleStore() {
1949
+ const globalScope = globalThis;
1950
+ if (!globalScope[ELIT_SHARED_STYLE_STORE_KEY]) {
1951
+ globalScope[ELIT_SHARED_STYLE_STORE_KEY] = createStyleStore();
1952
+ }
1953
+ return globalScope[ELIT_SHARED_STYLE_STORE_KEY];
1954
+ }
1955
+
1956
+ // src/client/style/index.ts
1957
+ var CreateStyle = class {
1958
+ constructor(store) {
1959
+ this.variables = [];
1960
+ this.rules = [];
1961
+ this.mediaRules = [];
1962
+ this.keyframes = [];
1963
+ this.fontFaces = [];
1964
+ this.imports = [];
1965
+ this.containerRules = [];
1966
+ this.supportsRules = [];
1967
+ this.layerRules = [];
1968
+ this._layerOrder = [];
1969
+ this.nativeStyleResolver = new NativeStyleResolver();
1970
+ if (!store) {
1971
+ return;
1972
+ }
1973
+ this.variables = store.variables;
1974
+ this.rules = store.rules;
1975
+ this.mediaRules = store.mediaRules;
1976
+ this.keyframes = store.keyframes;
1977
+ this.fontFaces = store.fontFaces;
1978
+ this.imports = store.imports;
1979
+ this.containerRules = store.containerRules;
1980
+ this.supportsRules = store.supportsRules;
1981
+ this.layerRules = store.layerRules;
1982
+ this._layerOrder = store.layerOrder;
1983
+ }
1984
+ addVar(name, value) {
1985
+ const cssVar = {
1986
+ name: name.startsWith("--") ? name : `--${name}`,
1987
+ value,
1988
+ toString() {
1989
+ return `var(${this.name})`;
1990
+ }
1991
+ };
1992
+ this.variables.push(cssVar);
1993
+ return cssVar;
1994
+ }
1995
+ var(variable, fallback) {
1996
+ const varName = typeof variable === "string" ? variable.startsWith("--") ? variable : `--${variable}` : variable.name;
1997
+ return fallback ? `var(${varName}, ${fallback})` : `var(${varName})`;
1998
+ }
1999
+ addTag(tag, styles2) {
2000
+ const rule = { selector: tag, styles: styles2, type: "tag" };
2001
+ this.rules.push(rule);
2002
+ return rule;
2003
+ }
2004
+ addClass(name, styles2) {
2005
+ const selector = name.startsWith(".") ? name : `.${name}`;
2006
+ const rule = { selector, styles: styles2, type: "class" };
2007
+ this.rules.push(rule);
2008
+ return rule;
2009
+ }
2010
+ addId(name, styles2) {
2011
+ const selector = name.startsWith("#") ? name : `#${name}`;
2012
+ const rule = { selector, styles: styles2, type: "id" };
2013
+ this.rules.push(rule);
2014
+ return rule;
2015
+ }
2016
+ addPseudoClass(pseudo, styles2, baseSelector) {
2017
+ const pseudoClass = pseudo.startsWith(":") ? pseudo : `:${pseudo}`;
2018
+ const selector = baseSelector ? `${baseSelector}${pseudoClass}` : pseudoClass;
2019
+ const rule = { selector, styles: styles2, type: "pseudo-class" };
2020
+ this.rules.push(rule);
2021
+ return rule;
2022
+ }
2023
+ addPseudoElement(pseudo, styles2, baseSelector) {
2024
+ const pseudoElement = pseudo.startsWith("::") ? pseudo : `::${pseudo}`;
2025
+ const selector = baseSelector ? `${baseSelector}${pseudoElement}` : pseudoElement;
2026
+ const rule = { selector, styles: styles2, type: "pseudo-element" };
2027
+ this.rules.push(rule);
2028
+ return rule;
2029
+ }
2030
+ addAttribute(attr, styles2, baseSelector) {
2031
+ const attrSelector = attr.startsWith("[") ? attr : `[${attr}]`;
2032
+ const selector = baseSelector ? `${baseSelector}${attrSelector}` : attrSelector;
2033
+ const rule = { selector, styles: styles2, type: "attribute" };
2034
+ this.rules.push(rule);
2035
+ return rule;
2036
+ }
2037
+ attrEquals(attr, value, styles2, baseSelector) {
2038
+ return this.addAttribute(`${attr}="${value}"`, styles2, baseSelector);
2039
+ }
2040
+ attrContainsWord(attr, value, styles2, baseSelector) {
2041
+ return this.addAttribute(`${attr}~="${value}"`, styles2, baseSelector);
2042
+ }
2043
+ attrStartsWith(attr, value, styles2, baseSelector) {
2044
+ return this.addAttribute(`${attr}^="${value}"`, styles2, baseSelector);
2045
+ }
2046
+ attrEndsWith(attr, value, styles2, baseSelector) {
2047
+ return this.addAttribute(`${attr}$="${value}"`, styles2, baseSelector);
1776
2048
  }
1777
- matchesMediaCondition(condition, options) {
1778
- const normalized = condition.trim().replace(/^\(+|\)+$/g, "").trim().toLowerCase();
1779
- if (!normalized) {
1780
- return true;
1781
- }
1782
- if (normalized.startsWith("min-width:")) {
1783
- const minWidth = this.parseMediaLength(normalized.slice("min-width:".length));
1784
- return minWidth !== void 0 && options.viewportWidth !== void 0 && options.viewportWidth >= minWidth;
1785
- }
1786
- if (normalized.startsWith("max-width:")) {
1787
- const maxWidth = this.parseMediaLength(normalized.slice("max-width:".length));
1788
- return maxWidth !== void 0 && options.viewportWidth !== void 0 && options.viewportWidth <= maxWidth;
1789
- }
1790
- if (normalized === "prefers-color-scheme: dark") {
1791
- return options.colorScheme === "dark";
1792
- }
1793
- if (normalized === "prefers-color-scheme: light") {
1794
- return (options.colorScheme ?? "light") === "light";
1795
- }
1796
- if (normalized === "prefers-reduced-motion: reduce") {
1797
- return options.reducedMotion === true;
1798
- }
1799
- return false;
2049
+ attrContains(attr, value, styles2, baseSelector) {
2050
+ return this.addAttribute(`${attr}*="${value}"`, styles2, baseSelector);
1800
2051
  }
1801
- matchesMediaRule(rule, options) {
1802
- const mediaType = options.mediaType ?? "screen";
1803
- if (rule.type && rule.type !== mediaType && rule.type !== "all") {
1804
- return false;
1805
- }
1806
- if (!rule.condition.trim()) {
1807
- return true;
1808
- }
1809
- return rule.condition.split(/\band\b/i).map((part) => part.trim()).filter(Boolean).every((part) => this.matchesMediaCondition(part, options));
2052
+ descendant(ancestor, descendant2, styles2) {
2053
+ return this.createAndAddRule(`${ancestor} ${descendant2}`, styles2);
1810
2054
  }
1811
- getOrderedLayerNames() {
1812
- const orderedLayerNames = [];
1813
- for (const layerName of this._layerOrder) {
1814
- const normalizedName = layerName.trim();
1815
- if (normalizedName && !orderedLayerNames.includes(normalizedName)) {
1816
- orderedLayerNames.push(normalizedName);
1817
- }
1818
- }
1819
- for (const layerRule of this.layerRules) {
1820
- const normalizedName = layerRule.name.trim();
1821
- if (normalizedName && !orderedLayerNames.includes(normalizedName)) {
1822
- orderedLayerNames.push(normalizedName);
1823
- }
1824
- }
1825
- return orderedLayerNames;
2055
+ child(parent, childSel, styles2) {
2056
+ return this.createAndAddRule(`${parent} > ${childSel}`, styles2);
1826
2057
  }
1827
- resolveNativeStyles(target, ancestors = [], options = {}) {
1828
- return this.withNativeTargetNormalizationCache(() => {
1829
- const normalizedTarget = this.normalizeTarget(target);
1830
- if (!normalizedTarget.tagName && (!normalizedTarget.classNames || normalizedTarget.classNames.length === 0)) {
1831
- return {};
1832
- }
1833
- const normalizedAncestors = ancestors.map((ancestor) => this.normalizeTarget(ancestor));
1834
- const variables = this.getVariables();
1835
- const resolved = {};
1836
- const applyRules = (rules) => {
1837
- for (const rule of rules) {
1838
- const selectorChains = this.extractSupportedSelectorChains(rule.selector);
1839
- if (selectorChains.length === 0) {
1840
- continue;
1841
- }
1842
- const matches = selectorChains.some((selectorChain) => this.matchesSelectorChain(normalizedTarget, normalizedAncestors, selectorChain));
1843
- if (!matches) {
1844
- continue;
1845
- }
1846
- for (const [property, value] of Object.entries(rule.styles)) {
1847
- resolved[property] = typeof value === "string" ? this.resolveVariableReferences(value, variables) : value;
1848
- }
1849
- }
1850
- };
1851
- for (const layerName of this.getOrderedLayerNames()) {
1852
- for (const layerRule of this.layerRules) {
1853
- if (layerRule.name.trim() === layerName) {
1854
- applyRules(layerRule.rules);
1855
- }
1856
- }
1857
- }
1858
- applyRules(this.rules);
1859
- for (const supportsRule of this.supportsRules) {
1860
- if (this.matchesSupportsCondition(supportsRule.condition)) {
1861
- applyRules(supportsRule.rules);
1862
- }
1863
- }
1864
- for (const containerRule of this.containerRules) {
1865
- const matchingContainer = this.findMatchingContainerTarget(normalizedAncestors, containerRule.name);
1866
- if (matchingContainer && this.matchesContainerCondition(containerRule.condition, matchingContainer.containerWidth)) {
1867
- applyRules(containerRule.rules);
1868
- }
1869
- }
1870
- for (const mediaRule of this.mediaRules) {
1871
- if (this.matchesMediaRule(mediaRule, options)) {
1872
- applyRules(mediaRule.rules);
1873
- }
1874
- }
1875
- return resolved;
1876
- });
2058
+ adjacentSibling(element, sibling, styles2) {
2059
+ return this.createAndAddRule(`${element} + ${sibling}`, styles2);
1877
2060
  }
1878
- resolveClassStyles(classNames) {
1879
- return this.resolveNativeStyles({ classNames });
2061
+ generalSibling(element, sibling, styles2) {
2062
+ return this.createAndAddRule(`${element} ~ ${sibling}`, styles2);
1880
2063
  }
1881
- // Utility Methods
1882
- toKebabCase(str) {
1883
- return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
2064
+ multiple(selectors, styles2) {
2065
+ return this.createAndAddRule(selectors.join(", "), styles2);
1884
2066
  }
1885
- // Helper: Create and add rule (eliminates duplication in combinator selectors)
1886
- createAndAddRule(selector, styles2, type = "custom") {
1887
- const rule = { selector, styles: styles2, type };
1888
- this.rules.push(rule);
1889
- return rule;
2067
+ addName(name, styles2) {
2068
+ const selector = name.startsWith("--") ? `&${name}` : `&--${name}`;
2069
+ return { selector, styles: styles2, type: "name" };
1890
2070
  }
1891
- // Helper: Convert rules object to CSSRule array (eliminates duplication in media/container/supports/layer)
1892
- rulesToCSSRules(rules) {
1893
- return Object.entries(rules).map(([selector, styles2]) => ({
1894
- selector,
1895
- styles: styles2,
1896
- type: "custom"
2071
+ nesting(parentRule, ...childRules) {
2072
+ parentRule.nested = childRules;
2073
+ return parentRule;
2074
+ }
2075
+ keyframe(name, steps) {
2076
+ const keyframeSteps = Object.entries(steps).map(([step, styles2]) => ({
2077
+ step: step === "from" ? "from" : step === "to" ? "to" : `${step}%`,
2078
+ styles: styles2
1897
2079
  }));
2080
+ const kf = { name, steps: keyframeSteps };
2081
+ this.keyframes.push(kf);
2082
+ return kf;
1898
2083
  }
1899
- // Helper: Render rules with indentation (eliminates duplication in render methods)
1900
- renderRulesWithIndent(rules, indent = " ") {
1901
- return rules.map((rule) => this.renderRule(rule, indent)).join("\n");
2084
+ keyframeFromTo(name, from, to) {
2085
+ return this.keyframe(name, { from, to });
1902
2086
  }
1903
- stylesToString(styles2, indent = " ") {
1904
- return Object.entries(styles2).map(([prop, value]) => {
1905
- const cssValue = typeof value === "object" && value !== null && "name" in value ? `var(${value.name})` : value;
1906
- return `${indent}${this.toKebabCase(prop)}: ${cssValue};`;
1907
- }).join("\n");
2087
+ fontFace(options) {
2088
+ this.fontFaces.push(options);
2089
+ return options;
1908
2090
  }
1909
- renderRule(rule, indent = "") {
1910
- let css = `${indent}${rule.selector} {
1911
- ${this.stylesToString(rule.styles, indent + " ")}
1912
- `;
1913
- if (rule.nested && rule.nested.length > 0) {
1914
- for (const nestedRule of rule.nested) {
1915
- const nestedSelector = nestedRule.selector.startsWith("&") ? nestedRule.selector.replace(/&/g, rule.selector) : `${rule.selector} ${nestedRule.selector}`;
1916
- css += `
1917
- ${indent}${nestedSelector} {
1918
- ${this.stylesToString(nestedRule.styles, indent + " ")}
1919
- ${indent}}
1920
- `;
1921
- }
1922
- }
1923
- css += `${indent}}`;
1924
- return css;
2091
+ import(url, mediaQuery) {
2092
+ const importRule = mediaQuery ? `@import url("${url}") ${mediaQuery};` : `@import url("${url}");`;
2093
+ this.imports.push(importRule);
2094
+ return importRule;
1925
2095
  }
1926
- renderMediaRule(media) {
1927
- const condition = media.type && media.condition ? `${media.type} and (${media.condition})` : media.type ? media.type : `(${media.condition})`;
1928
- return `@media ${condition} {
1929
- ${this.renderRulesWithIndent(media.rules)}
1930
- }`;
2096
+ media(type, condition, rules) {
2097
+ const mediaRule = { type, condition, rules: this.rulesToCSSRules(rules) };
2098
+ this.mediaRules.push(mediaRule);
2099
+ return mediaRule;
1931
2100
  }
1932
- renderKeyframes(kf) {
1933
- let css = `@keyframes ${kf.name} {
1934
- `;
1935
- for (const step of kf.steps) {
1936
- css += ` ${step.step} {
1937
- ${this.stylesToString(step.styles, " ")}
1938
- }
1939
- `;
1940
- }
1941
- css += "}";
1942
- return css;
2101
+ mediaScreen(condition, rules) {
2102
+ return this.media("screen", condition, rules);
1943
2103
  }
1944
- renderFontFace(ff) {
1945
- let css = "@font-face {\n";
1946
- css += ` font-family: "${ff.fontFamily}";
1947
- `;
1948
- css += ` src: ${ff.src};
1949
- `;
1950
- if (ff.fontWeight) css += ` font-weight: ${ff.fontWeight};
1951
- `;
1952
- if (ff.fontStyle) css += ` font-style: ${ff.fontStyle};
1953
- `;
1954
- if (ff.fontDisplay) css += ` font-display: ${ff.fontDisplay};
1955
- `;
1956
- if (ff.unicodeRange) css += ` unicode-range: ${ff.unicodeRange};
1957
- `;
1958
- css += "}";
1959
- return css;
2104
+ mediaPrint(rules) {
2105
+ return this.media("print", "", rules);
1960
2106
  }
1961
- renderContainerRule(container2) {
1962
- const nameStr = container2.name ? `${container2.name} ` : "";
1963
- return `@container ${nameStr}(${container2.condition}) {
1964
- ${this.renderRulesWithIndent(container2.rules)}
1965
- }`;
2107
+ mediaMinWidth(minWidth, rules) {
2108
+ return this.media("screen", `min-width: ${minWidth}`, rules);
1966
2109
  }
1967
- renderSupportsRule(supports) {
1968
- return `@supports (${supports.condition}) {
1969
- ${this.renderRulesWithIndent(supports.rules)}
1970
- }`;
2110
+ mediaMaxWidth(maxWidth, rules) {
2111
+ return this.media("screen", `max-width: ${maxWidth}`, rules);
1971
2112
  }
1972
- renderLayerRule(layer2) {
1973
- return `@layer ${layer2.name} {
1974
- ${this.renderRulesWithIndent(layer2.rules)}
1975
- }`;
2113
+ mediaDark(rules) {
2114
+ const mediaRule = { type: "", condition: "prefers-color-scheme: dark", rules: this.rulesToCSSRules(rules) };
2115
+ this.mediaRules.push(mediaRule);
2116
+ return mediaRule;
2117
+ }
2118
+ mediaLight(rules) {
2119
+ const mediaRule = { type: "", condition: "prefers-color-scheme: light", rules: this.rulesToCSSRules(rules) };
2120
+ this.mediaRules.push(mediaRule);
2121
+ return mediaRule;
2122
+ }
2123
+ mediaReducedMotion(rules) {
2124
+ const mediaRule = { type: "", condition: "prefers-reduced-motion: reduce", rules: this.rulesToCSSRules(rules) };
2125
+ this.mediaRules.push(mediaRule);
2126
+ return mediaRule;
2127
+ }
2128
+ container(condition, rules, name) {
2129
+ const containerRule = { name, condition, rules: this.rulesToCSSRules(rules) };
2130
+ this.containerRules.push(containerRule);
2131
+ return containerRule;
2132
+ }
2133
+ addContainer(name, styles2) {
2134
+ const containerStyles = { ...styles2, containerName: name };
2135
+ return this.addClass(name, containerStyles);
2136
+ }
2137
+ supports(condition, rules) {
2138
+ const supportsRule = { condition, rules: this.rulesToCSSRules(rules) };
2139
+ this.supportsRules.push(supportsRule);
2140
+ return supportsRule;
2141
+ }
2142
+ layerOrder(...layers) {
2143
+ this._layerOrder = layers;
2144
+ }
2145
+ layer(name, rules) {
2146
+ const layerRule = { name, rules: this.rulesToCSSRules(rules) };
2147
+ this.layerRules.push(layerRule);
2148
+ return layerRule;
2149
+ }
2150
+ add(rules) {
2151
+ return Object.entries(rules).map(([selector, styles2]) => {
2152
+ const rule = { selector, styles: styles2, type: "custom" };
2153
+ this.rules.push(rule);
2154
+ return rule;
2155
+ });
2156
+ }
2157
+ important(value) {
2158
+ return `${value} !important`;
2159
+ }
2160
+ getVariables() {
2161
+ return Object.fromEntries(this.variables.map((variable) => [variable.name, variable.value]));
2162
+ }
2163
+ resolveNativeStyles(target, ancestors = [], options = {}) {
2164
+ return this.nativeStyleResolver.resolveNativeStyles(target, ancestors, options, this.getResolverContext());
2165
+ }
2166
+ resolveClassStyles(classNames) {
2167
+ return this.nativeStyleResolver.resolveClassStyles(classNames, this.getResolverContext());
1976
2168
  }
1977
- // Render Output
1978
2169
  render(...additionalRules) {
1979
- const parts = [];
1980
- if (this.imports.length > 0) {
1981
- parts.push(this.imports.join("\n"));
1982
- }
1983
- if (this._layerOrder.length > 0) {
1984
- parts.push(`@layer ${this._layerOrder.join(", ")};`);
1985
- }
1986
- if (this.variables.length > 0) {
1987
- const varDeclarations = this.variables.map((v) => ` ${v.name}: ${v.value};`).join("\n");
1988
- parts.push(`:root {
1989
- ${varDeclarations}
1990
- }`);
1991
- }
1992
- for (const ff of this.fontFaces) {
1993
- parts.push(this.renderFontFace(ff));
1994
- }
1995
- for (const kf of this.keyframes) {
1996
- parts.push(this.renderKeyframes(kf));
1997
- }
1998
- const allRules = [...this.rules];
1999
- const allMediaRules = [...this.mediaRules];
2000
- const allKeyframes = [];
2001
- const allContainerRules = [...this.containerRules];
2002
- const allSupportsRules = [...this.supportsRules];
2003
- const allLayerRules = [...this.layerRules];
2004
- for (const item of additionalRules) {
2005
- if (!item) continue;
2006
- if (Array.isArray(item)) {
2007
- allRules.push(...item);
2008
- } else if ("condition" in item && "rules" in item && !("name" in item && "steps" in item)) {
2009
- if ("type" in item) {
2010
- allMediaRules.push(item);
2011
- } else if ("name" in item && typeof item.name === "string") {
2012
- allContainerRules.push(item);
2013
- } else {
2014
- allSupportsRules.push(item);
2015
- }
2016
- } else if ("name" in item && "steps" in item) {
2017
- allKeyframes.push(item);
2018
- } else if ("name" in item && "rules" in item) {
2019
- allLayerRules.push(item);
2020
- } else {
2021
- allRules.push(item);
2022
- }
2023
- }
2024
- for (const kf of allKeyframes) {
2025
- parts.push(this.renderKeyframes(kf));
2026
- }
2027
- for (const layer2 of allLayerRules) {
2028
- parts.push(this.renderLayerRule(layer2));
2029
- }
2030
- for (const rule of allRules) {
2031
- parts.push(this.renderRule(rule));
2032
- }
2033
- for (const supports of allSupportsRules) {
2034
- parts.push(this.renderSupportsRule(supports));
2035
- }
2036
- for (const container2 of allContainerRules) {
2037
- parts.push(this.renderContainerRule(container2));
2038
- }
2039
- for (const media of allMediaRules) {
2040
- parts.push(this.renderMediaRule(media));
2041
- }
2042
- return parts.join("\n\n");
2170
+ return renderStyleSheet(this.getRenderContext(), ...additionalRules);
2043
2171
  }
2044
2172
  inject(styleId) {
2045
2173
  const css = this.render();
2046
2174
  const style = document.createElement("style");
2047
- if (styleId) style.id = styleId;
2175
+ if (styleId) {
2176
+ style.id = styleId;
2177
+ }
2048
2178
  style.textContent = css;
2049
2179
  document.head.appendChild(style);
2050
2180
  return style;
@@ -2061,6 +2191,43 @@ ${varDeclarations}
2061
2191
  this.layerRules.length = 0;
2062
2192
  this._layerOrder.length = 0;
2063
2193
  }
2194
+ getResolverContext() {
2195
+ return {
2196
+ variables: this.getVariables(),
2197
+ rules: this.rules,
2198
+ mediaRules: this.mediaRules,
2199
+ containerRules: this.containerRules,
2200
+ supportsRules: this.supportsRules,
2201
+ layerRules: this.layerRules,
2202
+ layerOrder: this._layerOrder
2203
+ };
2204
+ }
2205
+ getRenderContext() {
2206
+ return {
2207
+ imports: this.imports,
2208
+ layerOrder: this._layerOrder,
2209
+ variables: this.variables,
2210
+ fontFaces: this.fontFaces,
2211
+ keyframes: this.keyframes,
2212
+ rules: this.rules,
2213
+ mediaRules: this.mediaRules,
2214
+ containerRules: this.containerRules,
2215
+ supportsRules: this.supportsRules,
2216
+ layerRules: this.layerRules
2217
+ };
2218
+ }
2219
+ createAndAddRule(selector, styles2, type = "custom") {
2220
+ const rule = { selector, styles: styles2, type };
2221
+ this.rules.push(rule);
2222
+ return rule;
2223
+ }
2224
+ rulesToCSSRules(rules) {
2225
+ return Object.entries(rules).map(([selector, styles2]) => ({
2226
+ selector,
2227
+ styles: styles2,
2228
+ type: "custom"
2229
+ }));
2230
+ }
2064
2231
  };
2065
2232
  var styles = new CreateStyle(getSharedStyleStore());
2066
2233
  var {
@@ -2101,23 +2268,28 @@ var {
2101
2268
  supports: supportsStyle,
2102
2269
  layerOrder,
2103
2270
  layer,
2104
- add: addStyle,
2271
+ add: addStyle2,
2105
2272
  important,
2106
2273
  getVariables: getStyleVariables,
2274
+ resolveNativeStyles,
2107
2275
  resolveClassStyles,
2108
2276
  render: renderStyle,
2109
2277
  inject: injectStyle,
2110
2278
  clear: clearStyle
2111
2279
  } = styles;
2112
2280
 
2113
- // src/desktop-auto-render.ts
2281
+ // src/desktop/auto-render/constants.ts
2114
2282
  var DESKTOP_RENDER_TRACKED_KEY = "__ELIT_DESKTOP_RENDER_TRACKED__";
2115
2283
  var DESKTOP_WINDOW_CREATED_KEY = "__ELIT_DESKTOP_WINDOW_CREATED__";
2116
2284
  var DESKTOP_MESSAGE_HANDLER_KEY = "__ELIT_DESKTOP_MESSAGE_HANDLER__";
2285
+
2286
+ // src/desktop/auto-render/globals.ts
2117
2287
  function getDesktopAutoRenderGlobals() {
2118
2288
  return globalThis;
2119
2289
  }
2120
- function escapeHtml(text) {
2290
+
2291
+ // src/desktop/auto-render/html.ts
2292
+ function escapeHtml2(text) {
2121
2293
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#x27;");
2122
2294
  }
2123
2295
  function escapeStyleText(css) {
@@ -2130,7 +2302,7 @@ function buildDesktopAutoHtml(options) {
2130
2302
  <head>
2131
2303
  <meta charset="utf-8" />
2132
2304
  <meta name="viewport" content="width=device-width, initial-scale=1" />
2133
- <title>${escapeHtml(options.title)}</title>
2305
+ <title>${escapeHtml2(options.title)}</title>
2134
2306
  ${styleTag}
2135
2307
  </head>
2136
2308
  <body>
@@ -2165,6 +2337,8 @@ ${styleTag}
2165
2337
  </body>
2166
2338
  </html>`;
2167
2339
  }
2340
+
2341
+ // src/desktop/auto-render/message-handler.ts
2168
2342
  function resolveDesktopBridgePayloadRoute(payload) {
2169
2343
  if (!payload) {
2170
2344
  return void 0;
@@ -2181,19 +2355,6 @@ function resolveDesktopBridgePayloadRoute(payload) {
2181
2355
  }
2182
2356
  return void 0;
2183
2357
  }
2184
- function installDesktopRenderTracking() {
2185
- const globalScope = getDesktopAutoRenderGlobals();
2186
- globalScope[DESKTOP_WINDOW_CREATED_KEY] = false;
2187
- if (globalScope[DESKTOP_RENDER_TRACKED_KEY] || typeof globalScope.createWindow !== "function") {
2188
- return;
2189
- }
2190
- const originalCreateWindow = globalScope.createWindow.bind(globalScope);
2191
- globalScope.createWindow = (options) => {
2192
- globalScope[DESKTOP_WINDOW_CREATED_KEY] = true;
2193
- return originalCreateWindow(options);
2194
- };
2195
- globalScope[DESKTOP_RENDER_TRACKED_KEY] = true;
2196
- }
2197
2358
  function installDesktopMessageHandler(options) {
2198
2359
  const globalScope = getDesktopAutoRenderGlobals();
2199
2360
  let routeHistory = [];
@@ -2301,6 +2462,23 @@ function installDesktopMessageHandler(options) {
2301
2462
  });
2302
2463
  globalScope[DESKTOP_MESSAGE_HANDLER_KEY] = true;
2303
2464
  }
2465
+
2466
+ // src/desktop/auto-render/tracking.ts
2467
+ function installDesktopRenderTracking() {
2468
+ const globalScope = getDesktopAutoRenderGlobals();
2469
+ globalScope[DESKTOP_WINDOW_CREATED_KEY] = false;
2470
+ if (globalScope[DESKTOP_RENDER_TRACKED_KEY] || typeof globalScope.createWindow !== "function") {
2471
+ return;
2472
+ }
2473
+ const originalCreateWindow = globalScope.createWindow.bind(globalScope);
2474
+ globalScope.createWindow = (options) => {
2475
+ globalScope[DESKTOP_WINDOW_CREATED_KEY] = true;
2476
+ return originalCreateWindow(options);
2477
+ };
2478
+ globalScope[DESKTOP_RENDER_TRACKED_KEY] = true;
2479
+ }
2480
+
2481
+ // src/desktop/auto-render/complete.ts
2304
2482
  function completeDesktopAutoRender(options = {}) {
2305
2483
  installDesktopRenderTracking();
2306
2484
  const globalScope = getDesktopAutoRenderGlobals();
@@ -2332,7 +2510,7 @@ function completeDesktopAutoRender(options = {}) {
2332
2510
  icon: resolvedOptions.icon,
2333
2511
  html: buildDesktopAutoHtml({
2334
2512
  css: styles.render(),
2335
- markup: renderToString(capturedRender.vNode),
2513
+ markup: renderToString2(capturedRender.vNode),
2336
2514
  title: resolvedOptions.title
2337
2515
  })
2338
2516
  });