@vebui/deno 0.0.3 → 0.0.4

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 (3) hide show
  1. package/cli.js +1636 -0
  2. package/package.json +8 -4
  3. package/cli.ts +0 -300
package/cli.js ADDED
@@ -0,0 +1,1636 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ // cli.ts
8
+ import { resolve, dirname } from "node:path";
9
+ import { build as esbuild, stop as esbuildStop } from "esbuild";
10
+
11
+ // node_modules/@vebui/core/dist/index.js
12
+ var dist_exports = {};
13
+ __export(dist_exports, {
14
+ A: () => A,
15
+ Block: () => Block,
16
+ Body: () => Body,
17
+ Button: () => Button,
18
+ Charset: () => Charset,
19
+ Dialog: () => Dialog,
20
+ Document: () => Document,
21
+ Footer: () => Footer,
22
+ GlobalStyles: () => GlobalStyles,
23
+ HStack: () => HStack,
24
+ Head: () => Head,
25
+ Input: () => Input,
26
+ Link: () => Link,
27
+ Nav: () => Nav,
28
+ StyleSheet: () => StyleSheet,
29
+ Text: () => Text,
30
+ Title: () => Title,
31
+ VStack: () => VStack,
32
+ Viewport: () => Viewport,
33
+ classToDeclaration: () => classToDeclaration,
34
+ drainCSS: () => drainCSS
35
+ });
36
+ function baseStyleMap(s) {
37
+ return {
38
+ width: s.width,
39
+ height: s.height,
40
+ padding: s.padding,
41
+ paddingTop: s.paddingTop,
42
+ paddingBottom: s.paddingBottom,
43
+ paddingLeft: s.paddingLeft,
44
+ paddingRight: s.paddingRight,
45
+ margin: s.margin,
46
+ marginTop: s.marginTop,
47
+ marginBottom: s.marginBottom,
48
+ marginLeft: s.marginLeft,
49
+ marginRight: s.marginRight,
50
+ backgroundColor: s.backgroundColor,
51
+ borderRadius: s.borderRadius,
52
+ border: s.border,
53
+ color: s.color,
54
+ opacity: s.opacity
55
+ };
56
+ }
57
+ var _cssChunks = globalThis._vebuiCssChunks ??= [];
58
+ function pushCSS(css) {
59
+ if (css) {
60
+ _cssChunks.push(css);
61
+ }
62
+ }
63
+ function drainCSS() {
64
+ const out = _cssChunks.join(`
65
+ `);
66
+ _cssChunks.length = 0;
67
+ return out;
68
+ }
69
+ var UIElement = class {
70
+ styles;
71
+ classes;
72
+ constructor(styles = {}, classes = {}) {
73
+ this.styles = styles;
74
+ this.classes = classes;
75
+ }
76
+ };
77
+ function toKebab(s) {
78
+ return s.replace(/([A-Z])/g, (m) => `-${m.toLowerCase()}`);
79
+ }
80
+ function styleAttr(styles) {
81
+ const entries = Object.entries(styles).filter(([, v]) => v !== void 0).map(([k, v]) => `${toKebab(k)}: ${v}`).join("; ");
82
+ return entries ? ` style="${entries}"` : "";
83
+ }
84
+ function escapeHtml(s) {
85
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
86
+ }
87
+ function cls(modifier, value) {
88
+ return `${modifier}-${String(value).replace(/[^a-zA-Z0-9]/g, "_")}`;
89
+ }
90
+ function resolveSize(v) {
91
+ if (v === "full")
92
+ return "100%";
93
+ if (v === "auto")
94
+ return "auto";
95
+ return v;
96
+ }
97
+ function resolveColor(v) {
98
+ if (v === "white" || v === "black")
99
+ return `var(--${v})`;
100
+ return /^[a-z]+-\d+$/.test(v) ? `var(--${v})` : v;
101
+ }
102
+ function resolveTextSize(v) {
103
+ return `var(--text-${v})`;
104
+ }
105
+ function classToDeclaration(className) {
106
+ if (className === "flex")
107
+ return "display: flex";
108
+ if (className === "flex-col")
109
+ return "flex-direction: column";
110
+ if (className === "flex-row")
111
+ return "flex-direction: row";
112
+ if (className.startsWith("items-")) {
113
+ const val2 = className.slice(6);
114
+ return `align-items: ${val2}`;
115
+ }
116
+ if (className.startsWith("justify-")) {
117
+ const val2 = className.slice(8);
118
+ return `justify-content: ${val2}`;
119
+ }
120
+ const match = className.match(/^([a-z]+)-(.+)$/);
121
+ if (!match)
122
+ return "";
123
+ const [, mod, val] = match;
124
+ if (val === void 0)
125
+ return "";
126
+ const v = val.replace(/_/g, ".");
127
+ const isNumeric = !isNaN(Number(v));
128
+ const space = val === "auto" ? "auto" : isNumeric ? `calc(var(--spacing) * ${v})` : v;
129
+ switch (mod) {
130
+ case "p":
131
+ return `padding: ${space}`;
132
+ case "pt":
133
+ return `padding-top: ${space}`;
134
+ case "pb":
135
+ return `padding-bottom: ${space}`;
136
+ case "pl":
137
+ return `padding-left: ${space}`;
138
+ case "pr":
139
+ return `padding-right: ${space}`;
140
+ case "px":
141
+ return `padding-left: ${space}; padding-right: ${space}`;
142
+ case "py":
143
+ return `padding-top: ${space}; padding-bottom: ${space}`;
144
+ case "m":
145
+ return `margin: ${space}`;
146
+ case "mt":
147
+ return `margin-top: ${space}`;
148
+ case "mb":
149
+ return `margin-bottom: ${space}`;
150
+ case "ml":
151
+ return `margin-left: ${space}`;
152
+ case "mr":
153
+ return `margin-right: ${space}`;
154
+ case "mx":
155
+ return `margin-left: ${space}; margin-right: ${space}`;
156
+ case "my":
157
+ return `margin-top: ${space}; margin-bottom: ${space}`;
158
+ case "gap":
159
+ return `gap: ${space}`;
160
+ case "gapx":
161
+ return `column-gap: ${space}`;
162
+ case "gapy":
163
+ return `row-gap: ${space}`;
164
+ case "radius":
165
+ return `border-radius: var(--radius-${v})`;
166
+ case "text":
167
+ return `font-size: var(--text-${v})`;
168
+ case "w": {
169
+ if (v === "full")
170
+ return "width: 100%";
171
+ if (v === "auto")
172
+ return "width: auto";
173
+ if (v.endsWith("px"))
174
+ return `width: ${v}`;
175
+ if (v.endsWith("rem"))
176
+ return `width: ${v}`;
177
+ if (v.endsWith("vh"))
178
+ return `width: ${v}`;
179
+ if (v.endsWith("vw"))
180
+ return `width: ${v}`;
181
+ if (v.endsWith("pct"))
182
+ return `width: ${v.replace("pct", "%")}`;
183
+ return `width: ${v}`;
184
+ }
185
+ case "h": {
186
+ if (v === "full")
187
+ return "height: 100%";
188
+ if (v === "auto")
189
+ return "height: auto";
190
+ if (v.endsWith("px"))
191
+ return `height: ${v}`;
192
+ if (v.endsWith("rem"))
193
+ return `height: ${v}`;
194
+ if (v.endsWith("vh"))
195
+ return `height: ${v}`;
196
+ if (v.endsWith("vw"))
197
+ return `height: ${v}`;
198
+ if (v.endsWith("pct"))
199
+ return `height: ${v.replace("pct", "%")}`;
200
+ return `height: ${v}`;
201
+ }
202
+ case "bg": {
203
+ if (v.includes("-")) {
204
+ return `background-color: var(--${v})`;
205
+ }
206
+ return `background-color: var(--${v})`;
207
+ }
208
+ default:
209
+ return "";
210
+ }
211
+ }
212
+ function renderPseudoCSS(selector, pseudos) {
213
+ return Object.entries(pseudos).map(([scope, entry]) => {
214
+ if (!entry)
215
+ return "";
216
+ const { styles, classes } = entry;
217
+ const declarations = [
218
+ ...Object.entries(styles).map(([k, v]) => `${toKebab(k)}: ${v}`),
219
+ ...Object.values(classes).map((c) => classToDeclaration(c))
220
+ ].filter(Boolean).join("; ");
221
+ if (!declarations)
222
+ return "";
223
+ switch (scope) {
224
+ case "mobile":
225
+ return `@media (max-width: 640px) { ${selector} { ${declarations} } }`;
226
+ case "tablet":
227
+ return `@media (max-width: 1024px) { ${selector} { ${declarations} } }`;
228
+ case "desktop":
229
+ return `@media (min-width: 1024px) { ${selector} { ${declarations} } }`;
230
+ case "focusWithin":
231
+ return `${selector}:focus-within { ${declarations} }`;
232
+ case "before":
233
+ return `${selector}::before { ${declarations} }`;
234
+ case "after":
235
+ return `${selector}::after { ${declarations} }`;
236
+ default:
237
+ return `${selector}:${scope} { ${declarations} }`;
238
+ }
239
+ }).filter(Boolean).join(`
240
+ `);
241
+ }
242
+ function createPseudoStyleBuilder(styles = {}, classes = {}) {
243
+ const clsName = (mod2, val) => `${mod2}-${String(val).replace(/[^a-zA-Z0-9]/g, "_")}`;
244
+ const mod = (ps, pc = {}) => createPseudoStyleBuilder({ ...styles, ...ps }, { ...classes, ...pc });
245
+ return {
246
+ background: (v) => mod({ backgroundColor: resolveColor(v) }),
247
+ color: (v) => mod({ color: resolveColor(v) }),
248
+ padding: (v) => mod({}, { padding: clsName("p", v) }),
249
+ paddingT: (v) => mod({}, { paddingT: clsName("pt", v) }),
250
+ paddingB: (v) => mod({}, { paddingB: clsName("pb", v) }),
251
+ paddingL: (v) => mod({}, { paddingL: clsName("pl", v) }),
252
+ paddingR: (v) => mod({}, { paddingR: clsName("pr", v) }),
253
+ paddingX: (v) => mod({}, { paddingX: clsName("px", v) }),
254
+ paddingY: (v) => mod({}, { paddingY: clsName("py", v) }),
255
+ pt: (v) => mod({}, { paddingT: clsName("pt", v) }),
256
+ pb: (v) => mod({}, { paddingB: clsName("pb", v) }),
257
+ pl: (v) => mod({}, { paddingL: clsName("pl", v) }),
258
+ pr: (v) => mod({}, { paddingR: clsName("pr", v) }),
259
+ px: (v) => mod({}, { paddingX: clsName("px", v) }),
260
+ py: (v) => mod({}, { paddingY: clsName("py", v) }),
261
+ margin: (v) => mod({}, { margin: clsName("m", v) }),
262
+ marginT: (v) => mod({}, { marginT: clsName("mt", v) }),
263
+ marginB: (v) => mod({}, { marginB: clsName("mb", v) }),
264
+ marginL: (v) => mod({}, { marginL: clsName("ml", v) }),
265
+ marginR: (v) => mod({}, { marginR: clsName("mr", v) }),
266
+ marginX: (v) => mod({}, { marginX: clsName("mx", v) }),
267
+ marginY: (v) => mod({}, { marginY: clsName("my", v) }),
268
+ mt: (v) => mod({}, { marginT: clsName("mt", v) }),
269
+ mb: (v) => mod({}, { marginB: clsName("mb", v) }),
270
+ ml: (v) => mod({}, { marginL: clsName("ml", v) }),
271
+ mr: (v) => mod({}, { marginR: clsName("mr", v) }),
272
+ mx: (v) => mod({}, { marginX: clsName("mx", v) }),
273
+ my: (v) => mod({}, { marginY: clsName("my", v) }),
274
+ radius: (v) => mod({}, { radius: clsName("radius", v) }),
275
+ width: (v) => mod({ width: resolveSize(v) }),
276
+ height: (v) => mod({ height: resolveSize(v) }),
277
+ gap: (v) => mod({}, { gap: clsName("gap", v) }),
278
+ gapX: (v) => mod({}, { gapx: clsName("gapx", v) }),
279
+ gapY: (v) => mod({}, { gapy: clsName("gapy", v) }),
280
+ spaceX: (v) => mod({}, { gapx: clsName("gapx", v) }),
281
+ spaceY: (v) => mod({}, { gapy: clsName("gapy", v) }),
282
+ fontSize: (v) => mod({}, { size: clsName("text", v) }),
283
+ fontWeight: (v) => mod({ fontWeight: v }),
284
+ opacity: (v) => mod({ opacity: String(v) }),
285
+ border: (v) => mod({ border: v }),
286
+ __styles: styles,
287
+ __classes: classes
288
+ };
289
+ }
290
+ function createBreakpointContext(bp, pseudos, rebuild) {
291
+ const existing = pseudos[bp] ?? { styles: {}, classes: {} };
292
+ const addStyle = (styles) => rebuild({
293
+ ...pseudos,
294
+ [bp]: {
295
+ styles: { ...existing.styles, ...styles },
296
+ classes: existing.classes
297
+ }
298
+ });
299
+ const addClass = (key, value) => rebuild({
300
+ ...pseudos,
301
+ [bp]: {
302
+ styles: existing.styles,
303
+ classes: { ...existing.classes, [key]: cls(key, value) }
304
+ }
305
+ });
306
+ return {
307
+ gap: (v) => addClass("gap", v),
308
+ gapX: (v) => addClass("gapx", v),
309
+ gapY: (v) => addClass("gapy", v),
310
+ spaceX: (v) => addClass("gapx", v),
311
+ spaceY: (v) => addClass("gapy", v),
312
+ padding: (v) => addClass("p", v),
313
+ paddingT: (v) => addClass("pt", v),
314
+ paddingB: (v) => addClass("pb", v),
315
+ paddingL: (v) => addClass("pl", v),
316
+ paddingR: (v) => addClass("pr", v),
317
+ paddingX: (v) => addClass("px", v),
318
+ paddingY: (v) => addClass("py", v),
319
+ p: (v) => addClass("p", v),
320
+ pt: (v) => addClass("pt", v),
321
+ pb: (v) => addClass("pb", v),
322
+ pl: (v) => addClass("pl", v),
323
+ pr: (v) => addClass("pr", v),
324
+ px: (v) => addClass("px", v),
325
+ py: (v) => addClass("py", v),
326
+ margin: (v) => addClass("m", v),
327
+ marginT: (v) => addClass("mt", v),
328
+ marginB: (v) => addClass("mb", v),
329
+ marginL: (v) => addClass("ml", v),
330
+ marginR: (v) => addClass("mr", v),
331
+ marginX: (v) => addClass("mx", v),
332
+ marginY: (v) => addClass("my", v),
333
+ m: (v) => addClass("m", v),
334
+ mt: (v) => addClass("mt", v),
335
+ mb: (v) => addClass("mb", v),
336
+ ml: (v) => addClass("ml", v),
337
+ mr: (v) => addClass("mr", v),
338
+ mx: (v) => addClass("mx", v),
339
+ my: (v) => addClass("my", v),
340
+ width: (v) => addStyle({ width: resolveSize(v) }),
341
+ height: (v) => addStyle({ height: resolveSize(v) }),
342
+ background: (v) => addStyle({ backgroundColor: resolveColor(v) }),
343
+ color: (v) => addStyle({ color: resolveColor(v) }),
344
+ radius: (v) => addClass("radius", v),
345
+ border: (v) => addStyle({ border: v }),
346
+ opacity: (v) => addStyle({ opacity: String(v) }),
347
+ size: (v) => addClass("text", v),
348
+ fontWeight: (v) => addStyle({ fontWeight: v })
349
+ };
350
+ }
351
+ var _counter = 0;
352
+ var rpcRegistry = /* @__PURE__ */ new Map();
353
+ var DerivedSignal = class {
354
+ key;
355
+ initial;
356
+ constructor(key, initial) {
357
+ this.key = key;
358
+ this.initial = initial;
359
+ }
360
+ };
361
+ var RpcSignal = class {
362
+ key;
363
+ initial;
364
+ type = "rpc";
365
+ error;
366
+ status;
367
+ _handler;
368
+ constructor(initial, handler) {
369
+ this.key = `sig_${_counter++}`;
370
+ this.initial = initial;
371
+ this._handler = handler;
372
+ this.error = new DerivedSignal(`${this.key}_error`, "");
373
+ this.status = new DerivedSignal(`${this.key}_status`, "none");
374
+ rpcRegistry.set(this.key, this);
375
+ }
376
+ async handle(payload) {
377
+ return this._handler(payload);
378
+ }
379
+ };
380
+ function stableStringify(obj) {
381
+ if (obj === null || typeof obj !== "object")
382
+ return JSON.stringify(obj);
383
+ if (Array.isArray(obj))
384
+ return "[" + obj.map(stableStringify).join(",") + "]";
385
+ const keys = Object.keys(obj).sort();
386
+ return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
387
+ }
388
+ function hash(obj) {
389
+ const str = typeof obj === "string" ? obj : stableStringify(obj);
390
+ let h = 0;
391
+ for (let i = 0; i < str.length; i++) {
392
+ h = Math.imul(31, h) + str.charCodeAt(i) | 0;
393
+ }
394
+ return (h >>> 0).toString(36);
395
+ }
396
+ var SafeHTML = class {
397
+ html;
398
+ constructor(html) {
399
+ this.html = html;
400
+ }
401
+ render() {
402
+ return this.html;
403
+ }
404
+ };
405
+ function resolveChild(c) {
406
+ if (c instanceof RpcSignal || c instanceof DerivedSignal) {
407
+ return `<span data-signal="${c.key}">${escapeHtml(String(c.initial))}</span>`;
408
+ }
409
+ if (c instanceof SafeHTML) {
410
+ return c.html;
411
+ }
412
+ return typeof c === "string" ? escapeHtml(c) : c.render();
413
+ }
414
+ function renderWithPseudo(html, pseudos) {
415
+ const hasPseudos = Object.keys(pseudos).length > 0;
416
+ if (!hasPseudos)
417
+ return html(null);
418
+ const styleKey = JSON.stringify(pseudos);
419
+ const className = `w-${hash(styleKey)}`;
420
+ pushCSS(renderPseudoCSS(`.${className}`, pseudos));
421
+ return html(className);
422
+ }
423
+ function renderStack(direction, state, children) {
424
+ const { styles, classes, pseudos } = state;
425
+ const inlineStyles = {
426
+ ...baseStyleMap(styles),
427
+ gap: styles.gap,
428
+ alignItems: styles.alignItems,
429
+ justifyContent: styles.justifyContent,
430
+ minWidth: styles.minWidth,
431
+ maxWidth: styles.maxWidth,
432
+ minHeight: styles.minHeight,
433
+ maxHeight: styles.maxHeight
434
+ };
435
+ return renderWithPseudo((className) => {
436
+ const styleStr = `display: flex; flex-direction: ${direction}` + Object.entries(inlineStyles).filter(([, v]) => v).map(([k, v]) => `; ${toKebab(k)}: ${v}`).join("");
437
+ const classList = [className, ...Object.values(classes)].filter(Boolean);
438
+ const classAttrStr = classList.length ? ` class="${classList.join(" ")}"` : "";
439
+ return `<div${classAttrStr} style="${styleStr}">${children.map(resolveChild).join("")}</div>`;
440
+ }, pseudos);
441
+ }
442
+ function createBuilder(factory, state = { styles: {}, classes: {}, pseudos: {} }) {
443
+ const fn = (...children) => factory(state, children);
444
+ const mod = (ps, pc = {}, pp) => createBuilder(factory, {
445
+ styles: { ...state.styles, ...ps },
446
+ classes: { ...state.classes, ...pc },
447
+ pseudos: pp ?? state.pseudos
448
+ });
449
+ const rebuildWithPseudos = (pseudos) => createBuilder(factory, { ...state, pseudos });
450
+ Object.defineProperty(fn, "mobile", {
451
+ get: () => createBreakpointContext("mobile", state.pseudos, rebuildWithPseudos),
452
+ enumerable: true
453
+ });
454
+ Object.defineProperty(fn, "tablet", {
455
+ get: () => createBreakpointContext("tablet", state.pseudos, rebuildWithPseudos),
456
+ enumerable: true
457
+ });
458
+ Object.defineProperty(fn, "desktop", {
459
+ get: () => createBreakpointContext("desktop", state.pseudos, rebuildWithPseudos),
460
+ enumerable: true
461
+ });
462
+ fn.hover = (cb) => rebuildWithPseudos(addPseudoState(state.pseudos, "hover", cb));
463
+ fn.active = (cb) => rebuildWithPseudos(addPseudoState(state.pseudos, "active", cb));
464
+ fn.focus = (cb) => rebuildWithPseudos(addPseudoState(state.pseudos, "focus", cb));
465
+ fn.focusWithin = (cb) => rebuildWithPseudos(addPseudoState(state.pseudos, "focusWithin", cb));
466
+ fn.width = (v) => mod({ width: resolveSize(v) });
467
+ fn.w = (v) => mod({ width: resolveSize(v) });
468
+ fn.minw = (v) => mod({ minWidth: resolveSize(v) });
469
+ fn.maxw = (v) => mod({ maxWidth: resolveSize(v) });
470
+ fn.height = (v) => mod({ height: resolveSize(v) });
471
+ fn.h = (v) => mod({ height: resolveSize(v) });
472
+ fn.minh = (v) => mod({ minHeight: resolveSize(v) });
473
+ fn.maxh = (v) => mod({ maxHeight: resolveSize(v) });
474
+ fn.margin = (v) => mod({}, { m: cls("m", v) });
475
+ fn.marginT = (v) => mod({}, { mt: cls("mt", v) });
476
+ fn.marginB = (v) => mod({}, { mb: cls("mb", v) });
477
+ fn.marginL = (v) => mod({}, { ml: cls("ml", v) });
478
+ fn.marginR = (v) => mod({}, { mr: cls("mr", v) });
479
+ fn.marginX = (v) => mod({}, { mx: cls("mx", v) });
480
+ fn.marginY = (v) => mod({}, { my: cls("my", v) });
481
+ fn.m = (v) => mod({}, { m: cls("m", v) });
482
+ fn.mt = (v) => mod({}, { mt: cls("mt", v) });
483
+ fn.mb = (v) => mod({}, { mb: cls("mb", v) });
484
+ fn.ml = (v) => mod({}, { ml: cls("ml", v) });
485
+ fn.mr = (v) => mod({}, { mr: cls("mr", v) });
486
+ fn.mx = (v) => mod({}, { mx: cls("mx", v) });
487
+ fn.my = (v) => mod({}, { my: cls("my", v) });
488
+ fn.padding = (v) => mod({}, { p: cls("p", v) });
489
+ fn.paddingT = (v) => mod({}, { pt: cls("pt", v) });
490
+ fn.paddingB = (v) => mod({}, { pb: cls("pb", v) });
491
+ fn.paddingL = (v) => mod({}, { pl: cls("pl", v) });
492
+ fn.paddingR = (v) => mod({}, { pr: cls("pr", v) });
493
+ fn.paddingX = (v) => mod({}, { px: cls("px", v) });
494
+ fn.paddingY = (v) => mod({}, { py: cls("py", v) });
495
+ fn.p = (v) => mod({}, { p: cls("p", v) });
496
+ fn.pt = (v) => mod({}, { pt: cls("pt", v) });
497
+ fn.pb = (v) => mod({}, { pb: cls("pb", v) });
498
+ fn.pl = (v) => mod({}, { pl: cls("pl", v) });
499
+ fn.pr = (v) => mod({}, { pr: cls("pr", v) });
500
+ fn.px = (v) => mod({}, { px: cls("px", v) });
501
+ fn.py = (v) => mod({}, { py: cls("py", v) });
502
+ fn.gap = (v) => mod({}, { gap: cls("gap", v) });
503
+ fn.gapX = (v) => mod({}, { gapx: cls("gapx", v) });
504
+ fn.gapY = (v) => mod({}, { gapy: cls("gapy", v) });
505
+ fn.spaceX = (v) => mod({}, { gapx: cls("gapx", v) });
506
+ fn.spaceY = (v) => mod({}, { gapy: cls("gapy", v) });
507
+ fn.align = (v) => {
508
+ const map = {
509
+ start: "flex-start",
510
+ end: "flex-end",
511
+ "end-safe": "safe flex-end",
512
+ center: "center",
513
+ "center-safe": "safe center",
514
+ baseline: "baseline",
515
+ "baseline-last": "last baseline",
516
+ stretch: "stretch"
517
+ };
518
+ return mod({ alignItems: map[v] });
519
+ };
520
+ fn.justify = (v) => {
521
+ const map = {
522
+ start: "flex-start",
523
+ end: "flex-end",
524
+ "end-safe": "safe flex-end",
525
+ center: "center",
526
+ "center-safe": "safe center",
527
+ between: "space-between",
528
+ around: "space-around",
529
+ evenly: "space-evenly",
530
+ stretch: "stretch",
531
+ baseline: "baseline",
532
+ normal: "normal"
533
+ };
534
+ return mod({ justifyContent: map[v] });
535
+ };
536
+ fn.acjc = () => mod({ alignItems: "center", justifyContent: "center" });
537
+ fn.background = (v) => mod({ backgroundColor: resolveColor(v) });
538
+ fn.radius = (v) => mod({}, { radius: cls("radius", v) });
539
+ return fn;
540
+ }
541
+ function addPseudoState(pseudos, key, cb) {
542
+ const b = cb(createPseudoStyleBuilder());
543
+ return { ...pseudos, [key]: { styles: b.__styles, classes: b.__classes } };
544
+ }
545
+ var VStackElement = class extends UIElement {
546
+ state;
547
+ children;
548
+ constructor(state, children) {
549
+ super();
550
+ this.state = state;
551
+ this.children = children;
552
+ }
553
+ render() {
554
+ return renderStack("column", this.state, this.children);
555
+ }
556
+ };
557
+ var VStack = createBuilder((state, children) => new VStackElement(state, children));
558
+ var HStackElement = class extends UIElement {
559
+ state;
560
+ children;
561
+ constructor(state, children) {
562
+ super();
563
+ this.state = state;
564
+ this.children = children;
565
+ }
566
+ render() {
567
+ return renderStack("row", this.state, this.children);
568
+ }
569
+ };
570
+ var HStack = createBuilder((state, children) => new HStackElement(state, children));
571
+ var BlockElement = class extends UIElement {
572
+ state;
573
+ children;
574
+ constructor(state, children) {
575
+ super();
576
+ this.state = state;
577
+ this.children = children;
578
+ }
579
+ render() {
580
+ return renderWithPseudo((className) => {
581
+ const classList = [className, ...Object.values(this.state.classes)].filter(Boolean);
582
+ const classAttrStr = classList.length ? ` class="${classList.join(" ")}"` : "";
583
+ return `<div${classAttrStr}${styleAttr(baseStyleMap(this.state.styles))}>${this.children.map(resolveChild).join("")}</div>`;
584
+ }, this.state.pseudos);
585
+ }
586
+ };
587
+ var Block = createBuilder((state, children) => new BlockElement(state, children));
588
+ var NavElement = class extends UIElement {
589
+ state;
590
+ children;
591
+ constructor(state, children) {
592
+ super();
593
+ this.state = state;
594
+ this.children = children;
595
+ }
596
+ render() {
597
+ return renderWithPseudo((className) => {
598
+ const classList = [className, ...Object.values(this.state.classes)].filter(Boolean);
599
+ const classAttrStr = classList.length ? ` class="${classList.join(" ")}"` : "";
600
+ return `<nav${classAttrStr}${styleAttr(baseStyleMap(this.state.styles))}>${this.children.map(resolveChild).join("")}</nav>`;
601
+ }, this.state.pseudos);
602
+ }
603
+ };
604
+ var Nav = createBuilder((state, children) => new NavElement(state, children));
605
+ var FooterElement = class extends UIElement {
606
+ state;
607
+ children;
608
+ constructor(state, children) {
609
+ super();
610
+ this.state = state;
611
+ this.children = children;
612
+ }
613
+ render() {
614
+ return renderWithPseudo((className) => {
615
+ const classList = [className, ...Object.values(this.state.classes)].filter(Boolean);
616
+ const classAttrStr = classList.length ? ` class="${classList.join(" ")}"` : "";
617
+ return `<footer${classAttrStr}${styleAttr(baseStyleMap(this.state.styles))}>${this.children.map(resolveChild).join("")}</footer>`;
618
+ }, this.state.pseudos);
619
+ }
620
+ };
621
+ var Footer = createBuilder((state, children) => new FooterElement(state, children));
622
+ var FONT_WEIGHT_MAP = {
623
+ thin: "100",
624
+ light: "300",
625
+ normal: "400",
626
+ medium: "500",
627
+ semibold: "600",
628
+ bold: "700",
629
+ extrabold: "800",
630
+ black: "900"
631
+ };
632
+ function createTextBuilder(styles = {}, classes = {}, pseudos = {}) {
633
+ const fn = (content) => new TextElement(content, styles, classes, pseudos);
634
+ const mod = (ps, pc = {}, pp) => createTextBuilder({ ...styles, ...ps }, { ...classes, ...pc }, pp ?? pseudos);
635
+ const rebuildWithPseudos = (pp) => createTextBuilder(styles, classes, pp);
636
+ Object.defineProperty(fn, "mobile", { get: () => createBreakpointContext("mobile", pseudos, rebuildWithPseudos), enumerable: true });
637
+ Object.defineProperty(fn, "tablet", { get: () => createBreakpointContext("tablet", pseudos, rebuildWithPseudos), enumerable: true });
638
+ Object.defineProperty(fn, "desktop", { get: () => createBreakpointContext("desktop", pseudos, rebuildWithPseudos), enumerable: true });
639
+ fn.hover = (cb) => {
640
+ const b = cb(createPseudoStyleBuilder());
641
+ return rebuildWithPseudos({ ...pseudos, hover: { styles: b.__styles, classes: b.__classes } });
642
+ };
643
+ fn.active = (cb) => {
644
+ const b = cb(createPseudoStyleBuilder());
645
+ return rebuildWithPseudos({ ...pseudos, active: { styles: b.__styles, classes: b.__classes } });
646
+ };
647
+ fn.focus = (cb) => {
648
+ const b = cb(createPseudoStyleBuilder());
649
+ return rebuildWithPseudos({ ...pseudos, focus: { styles: b.__styles, classes: b.__classes } });
650
+ };
651
+ fn.size = (v) => mod({}, { size: cls("text", v) });
652
+ fn.weight = (v) => mod({ fontWeight: FONT_WEIGHT_MAP[v] });
653
+ fn.color = (v) => mod({ color: resolveColor(v) });
654
+ fn.padding = (v) => mod({}, { p: cls("p", v) });
655
+ fn.paddingT = (v) => mod({}, { pt: cls("pt", v) });
656
+ fn.paddingB = (v) => mod({}, { pb: cls("pb", v) });
657
+ fn.paddingL = (v) => mod({}, { pl: cls("pl", v) });
658
+ fn.paddingR = (v) => mod({}, { pr: cls("pr", v) });
659
+ fn.paddingX = (v) => mod({}, { px: cls("px", v) });
660
+ fn.paddingY = (v) => mod({}, { py: cls("py", v) });
661
+ fn.p = fn.padding;
662
+ fn.pt = fn.paddingT;
663
+ fn.pb = fn.paddingB;
664
+ fn.pl = fn.paddingL;
665
+ fn.pr = fn.paddingR;
666
+ fn.px = fn.paddingX;
667
+ fn.py = fn.paddingY;
668
+ fn.margin = (v) => mod({}, { m: cls("m", v) });
669
+ fn.marginT = (v) => mod({}, { mt: cls("mt", v) });
670
+ fn.marginB = (v) => mod({}, { mb: cls("mb", v) });
671
+ fn.marginL = (v) => mod({}, { ml: cls("ml", v) });
672
+ fn.marginR = (v) => mod({}, { mr: cls("mr", v) });
673
+ fn.marginX = (v) => mod({}, { mx: cls("mx", v) });
674
+ fn.marginY = (v) => mod({}, { my: cls("my", v) });
675
+ fn.m = fn.margin;
676
+ fn.mt = fn.marginT;
677
+ fn.mb = fn.marginB;
678
+ fn.ml = fn.marginL;
679
+ fn.mr = fn.marginR;
680
+ fn.mx = fn.marginX;
681
+ fn.my = fn.marginY;
682
+ return fn;
683
+ }
684
+ var TextElement = class extends UIElement {
685
+ content;
686
+ ts;
687
+ tc;
688
+ pseudos;
689
+ constructor(content, ts, tc, pseudos) {
690
+ super();
691
+ this.content = content;
692
+ this.ts = ts;
693
+ this.tc = tc;
694
+ this.pseudos = pseudos;
695
+ }
696
+ render() {
697
+ return renderWithPseudo((className) => {
698
+ const classList = [className, ...Object.values(this.tc)].filter(Boolean);
699
+ const classAttrStr = classList.length ? ` class="${classList.join(" ")}"` : "";
700
+ const sAttr = styleAttr(this.ts);
701
+ if (this.content instanceof RpcSignal || this.content instanceof DerivedSignal) {
702
+ return `<span${classAttrStr}${sAttr} data-signal="${this.content.key}">${escapeHtml(String(this.content.initial))}</span>`;
703
+ }
704
+ return `<span${classAttrStr}${sAttr}>${escapeHtml(this.content)}</span>`;
705
+ }, this.pseudos);
706
+ }
707
+ };
708
+ var Text = createTextBuilder();
709
+ function createButtonBuilder(styles = {}, classes = {}, action, pseudos = {}) {
710
+ const fn = (label) => new ButtonElement(label, styles, classes, action, pseudos);
711
+ const mod = (ps, pc = {}, a, pp) => createButtonBuilder({ ...styles, ...ps }, { ...classes, ...pc }, a ?? action, pp ?? pseudos);
712
+ const rebuildWithPseudos = (pp) => createButtonBuilder(styles, classes, action, pp);
713
+ Object.defineProperty(fn, "mobile", { get: () => createBreakpointContext("mobile", pseudos, rebuildWithPseudos), enumerable: true });
714
+ Object.defineProperty(fn, "tablet", { get: () => createBreakpointContext("tablet", pseudos, rebuildWithPseudos), enumerable: true });
715
+ Object.defineProperty(fn, "desktop", { get: () => createBreakpointContext("desktop", pseudos, rebuildWithPseudos), enumerable: true });
716
+ fn.hover = (cb) => {
717
+ const b = cb(createPseudoStyleBuilder());
718
+ return rebuildWithPseudos({ ...pseudos, hover: { styles: b.__styles, classes: b.__classes } });
719
+ };
720
+ fn.active = (cb) => {
721
+ const b = cb(createPseudoStyleBuilder());
722
+ return rebuildWithPseudos({ ...pseudos, active: { styles: b.__styles, classes: b.__classes } });
723
+ };
724
+ fn.focus = (cb) => {
725
+ const b = cb(createPseudoStyleBuilder());
726
+ return rebuildWithPseudos({ ...pseudos, focus: { styles: b.__styles, classes: b.__classes } });
727
+ };
728
+ fn.onClick = (signal, value) => mod({}, {}, { signal, value });
729
+ fn.padding = (v) => mod({}, { p: cls("p", v) });
730
+ fn.paddingT = (v) => mod({}, { pt: cls("pt", v) });
731
+ fn.paddingB = (v) => mod({}, { pb: cls("pb", v) });
732
+ fn.paddingL = (v) => mod({}, { pl: cls("pl", v) });
733
+ fn.paddingR = (v) => mod({}, { pr: cls("pr", v) });
734
+ fn.paddingX = (v) => mod({}, { px: cls("px", v) });
735
+ fn.paddingY = (v) => mod({}, { py: cls("py", v) });
736
+ fn.p = fn.padding;
737
+ fn.pt = fn.paddingT;
738
+ fn.pb = fn.paddingB;
739
+ fn.pl = fn.paddingL;
740
+ fn.pr = fn.paddingR;
741
+ fn.px = fn.paddingX;
742
+ fn.py = fn.paddingY;
743
+ fn.margin = (v) => mod({}, { m: cls("m", v) });
744
+ fn.marginT = (v) => mod({}, { mt: cls("mt", v) });
745
+ fn.marginB = (v) => mod({}, { mb: cls("mb", v) });
746
+ fn.marginL = (v) => mod({}, { ml: cls("ml", v) });
747
+ fn.marginR = (v) => mod({}, { mr: cls("mr", v) });
748
+ fn.marginX = (v) => mod({}, { mx: cls("mx", v) });
749
+ fn.marginY = (v) => mod({}, { my: cls("my", v) });
750
+ fn.m = fn.margin;
751
+ fn.mt = fn.marginT;
752
+ fn.mb = fn.marginB;
753
+ fn.ml = fn.marginL;
754
+ fn.mr = fn.marginR;
755
+ fn.mx = fn.marginX;
756
+ fn.my = fn.marginY;
757
+ fn.background = (v) => mod({ backgroundColor: resolveColor(v) });
758
+ fn.radius = (v) => mod({}, { radius: cls("radius", v) });
759
+ fn.color = (v) => mod({ color: resolveColor(v) });
760
+ fn.width = (v) => mod({ width: resolveSize(v) });
761
+ fn.fontSize = (v) => mod({ fontSize: resolveTextSize(v) });
762
+ fn.fontWeight = (v) => mod({ fontWeight: FONT_WEIGHT_MAP[v] });
763
+ return fn;
764
+ }
765
+ var ButtonElement = class extends UIElement {
766
+ label;
767
+ bs;
768
+ bc;
769
+ action;
770
+ pseudos;
771
+ constructor(label, bs, bc, action, pseudos = {}) {
772
+ super();
773
+ this.label = label;
774
+ this.bs = bs;
775
+ this.bc = bc;
776
+ this.action = action;
777
+ this.pseudos = pseudos;
778
+ }
779
+ render() {
780
+ return renderWithPseudo((className) => {
781
+ let actionAttrs = "";
782
+ if (this.action) {
783
+ const { signal, value } = this.action;
784
+ if (signal.type === "browser") {
785
+ actionAttrs = ` data-set-signal="${signal.key}" data-set-value='${JSON.stringify(value)}'`;
786
+ } else {
787
+ const payload = typeof value === "object" && value !== null && !Array.isArray(value) ? value : { value };
788
+ actionAttrs = ` data-rpc="${signal.key}" data-payload='${JSON.stringify(payload)}'`;
789
+ }
790
+ }
791
+ const classList = [className, ...Object.values(this.bc)].filter(Boolean);
792
+ const classAttrStr = classList.length ? ` class="${classList.join(" ")}"` : "";
793
+ return `<button${classAttrStr}${styleAttr({
794
+ ...baseStyleMap(this.bs),
795
+ color: this.bs.color,
796
+ fontSize: this.bs.fontSize,
797
+ fontWeight: this.bs.fontWeight,
798
+ cursor: "pointer",
799
+ border: "none",
800
+ display: "inline-block"
801
+ })}${actionAttrs}>${escapeHtml(this.label)}</button>`;
802
+ }, this.pseudos);
803
+ }
804
+ };
805
+ var Button = createButtonBuilder();
806
+ function createInputBuilder(styles = {}, classes = {}, config = {}, pseudos = {}) {
807
+ const fn = (type) => new InputElement(type, styles, classes, config, pseudos);
808
+ const mod = (ps, pc = {}) => createInputBuilder({ ...styles, ...ps }, { ...classes, ...pc }, config, pseudos);
809
+ const cfg = (patch) => createInputBuilder(styles, classes, { ...config, ...patch }, pseudos);
810
+ const rebuildWithPseudos = (pp) => createInputBuilder(styles, classes, config, pp);
811
+ Object.defineProperty(fn, "mobile", { get: () => createBreakpointContext("mobile", pseudos, rebuildWithPseudos), enumerable: true });
812
+ Object.defineProperty(fn, "tablet", { get: () => createBreakpointContext("tablet", pseudos, rebuildWithPseudos), enumerable: true });
813
+ Object.defineProperty(fn, "desktop", { get: () => createBreakpointContext("desktop", pseudos, rebuildWithPseudos), enumerable: true });
814
+ fn.hover = (cb) => {
815
+ const b = cb(createPseudoStyleBuilder());
816
+ return rebuildWithPseudos({ ...pseudos, hover: { styles: b.__styles, classes: b.__classes } });
817
+ };
818
+ fn.focus = (cb) => {
819
+ const b = cb(createPseudoStyleBuilder());
820
+ return rebuildWithPseudos({ ...pseudos, focus: { styles: b.__styles, classes: b.__classes } });
821
+ };
822
+ fn.bind = (sig) => cfg({ signal: sig });
823
+ fn.debounce = (ms) => cfg({ debounceMs: ms });
824
+ fn.placeholder = (t) => cfg({ placeholder: t });
825
+ fn.padding = (v) => mod({}, { p: cls("p", v) });
826
+ fn.paddingT = (v) => mod({}, { pt: cls("pt", v) });
827
+ fn.paddingB = (v) => mod({}, { pb: cls("pb", v) });
828
+ fn.paddingL = (v) => mod({}, { pl: cls("pl", v) });
829
+ fn.paddingR = (v) => mod({}, { pr: cls("pr", v) });
830
+ fn.paddingX = (v) => mod({}, { px: cls("px", v) });
831
+ fn.paddingY = (v) => mod({}, { py: cls("py", v) });
832
+ fn.p = fn.padding;
833
+ fn.pt = fn.paddingT;
834
+ fn.pb = fn.paddingB;
835
+ fn.pl = fn.paddingL;
836
+ fn.pr = fn.paddingR;
837
+ fn.px = fn.paddingX;
838
+ fn.py = fn.paddingY;
839
+ fn.margin = (v) => mod({}, { m: cls("m", v) });
840
+ fn.marginT = (v) => mod({}, { mt: cls("mt", v) });
841
+ fn.marginB = (v) => mod({}, { mb: cls("mb", v) });
842
+ fn.marginL = (v) => mod({}, { ml: cls("ml", v) });
843
+ fn.marginR = (v) => mod({}, { mr: cls("mr", v) });
844
+ fn.marginX = (v) => mod({}, { mx: cls("mx", v) });
845
+ fn.marginY = (v) => mod({}, { my: cls("my", v) });
846
+ fn.m = fn.margin;
847
+ fn.mt = fn.marginT;
848
+ fn.mb = fn.marginB;
849
+ fn.ml = fn.marginL;
850
+ fn.mr = fn.marginR;
851
+ fn.mx = fn.marginX;
852
+ fn.my = fn.marginY;
853
+ fn.background = (v) => mod({ backgroundColor: resolveColor(v) });
854
+ fn.radius = (v) => mod({}, { radius: cls("radius", v) });
855
+ fn.width = (v) => mod({ width: resolveSize(v) });
856
+ fn.color = (v) => mod({ color: resolveColor(v) });
857
+ fn.border = (v) => mod({ border: v });
858
+ fn.fontSize = (v) => mod({ fontSize: resolveTextSize(v) });
859
+ return fn;
860
+ }
861
+ var InputElement = class extends UIElement {
862
+ type;
863
+ is;
864
+ ic;
865
+ config;
866
+ pseudos;
867
+ constructor(type, is, ic, config, pseudos) {
868
+ super();
869
+ this.type = type;
870
+ this.is = is;
871
+ this.ic = ic;
872
+ this.config = config;
873
+ this.pseudos = pseudos;
874
+ }
875
+ render() {
876
+ return renderWithPseudo((className) => {
877
+ const { signal, debounceMs, placeholder } = this.config;
878
+ const classList = [className, ...Object.values(this.ic)].filter(Boolean);
879
+ const classAttrStr = classList.length ? ` class="${classList.join(" ")}"` : "";
880
+ return `<input${classAttrStr} type="${this.type}"${styleAttr({
881
+ ...baseStyleMap(this.is),
882
+ color: this.is.color,
883
+ fontSize: this.is.fontSize,
884
+ border: this.is.border ?? "1px solid var(--gray-300)",
885
+ outline: "none"
886
+ })}${signal ? ` data-bind="${signal.key}"` : ""}${debounceMs ? ` data-debounce="${debounceMs}"` : ""}${placeholder ? ` placeholder="${escapeHtml(placeholder)}"` : ""}${signal ? ` value="${escapeHtml(String(signal.initial))}"` : ""} />`;
887
+ }, this.pseudos);
888
+ }
889
+ };
890
+ var Input = createInputBuilder();
891
+ function createLinkBuilder(styles = {}, classes = {}, state = {}, pseudos = {}) {
892
+ const fn = (label) => new LinkElement(label, styles, classes, state, pseudos);
893
+ const mod = (ps, pc = {}, st, pp) => createLinkBuilder({ ...styles, ...ps }, { ...classes, ...pc }, { ...state, ...st }, pp ?? pseudos);
894
+ const rebuildWithPseudos = (pp) => createLinkBuilder(styles, classes, state, pp);
895
+ Object.defineProperty(fn, "mobile", { get: () => createBreakpointContext("mobile", pseudos, rebuildWithPseudos), enumerable: true });
896
+ Object.defineProperty(fn, "tablet", { get: () => createBreakpointContext("tablet", pseudos, rebuildWithPseudos), enumerable: true });
897
+ Object.defineProperty(fn, "desktop", { get: () => createBreakpointContext("desktop", pseudos, rebuildWithPseudos), enumerable: true });
898
+ fn.hover = (cb) => {
899
+ const b = cb(createPseudoStyleBuilder());
900
+ return rebuildWithPseudos({ ...pseudos, hover: { styles: b.__styles, classes: b.__classes } });
901
+ };
902
+ fn.active = (cb) => {
903
+ const b = cb(createPseudoStyleBuilder());
904
+ return rebuildWithPseudos({ ...pseudos, active: { styles: b.__styles, classes: b.__classes } });
905
+ };
906
+ fn.focus = (cb) => {
907
+ const b = cb(createPseudoStyleBuilder());
908
+ return rebuildWithPseudos({ ...pseudos, focus: { styles: b.__styles, classes: b.__classes } });
909
+ };
910
+ fn.href = (url) => mod({}, {}, { href: url });
911
+ fn.target = (target) => mod({}, {}, { target });
912
+ fn.rel = (rel) => mod({}, {}, { rel });
913
+ fn.external = () => mod({}, {}, { target: "_blank", rel: "noopener noreferrer" });
914
+ fn.padding = (v) => mod({}, { p: cls("p", v) });
915
+ fn.paddingT = (v) => mod({}, { pt: cls("pt", v) });
916
+ fn.paddingB = (v) => mod({}, { pb: cls("pb", v) });
917
+ fn.paddingL = (v) => mod({}, { pl: cls("pl", v) });
918
+ fn.paddingR = (v) => mod({}, { pr: cls("pr", v) });
919
+ fn.paddingX = (v) => mod({}, { px: cls("px", v) });
920
+ fn.paddingY = (v) => mod({}, { py: cls("py", v) });
921
+ fn.p = fn.padding;
922
+ fn.pt = fn.paddingT;
923
+ fn.pb = fn.paddingB;
924
+ fn.pl = fn.paddingL;
925
+ fn.pr = fn.paddingR;
926
+ fn.px = fn.paddingX;
927
+ fn.py = fn.paddingY;
928
+ fn.margin = (v) => mod({}, { m: cls("m", v) });
929
+ fn.marginT = (v) => mod({}, { mt: cls("mt", v) });
930
+ fn.marginB = (v) => mod({}, { mb: cls("mb", v) });
931
+ fn.marginL = (v) => mod({}, { ml: cls("ml", v) });
932
+ fn.marginR = (v) => mod({}, { mr: cls("mr", v) });
933
+ fn.marginX = (v) => mod({}, { mx: cls("mx", v) });
934
+ fn.marginY = (v) => mod({}, { my: cls("my", v) });
935
+ fn.m = fn.margin;
936
+ fn.mt = fn.marginT;
937
+ fn.mb = fn.marginB;
938
+ fn.ml = fn.marginL;
939
+ fn.mr = fn.marginR;
940
+ fn.mx = fn.marginX;
941
+ fn.my = fn.marginY;
942
+ fn.color = (v) => mod({ color: resolveColor(v) });
943
+ fn.size = (v) => mod({ fontSize: resolveTextSize(v) });
944
+ fn.weight = (v) => mod({ fontWeight: FONT_WEIGHT_MAP[v] });
945
+ fn.underline = (v) => mod({ textDecoration: v ? "underline" : "none" });
946
+ return fn;
947
+ }
948
+ var LinkElement = class extends UIElement {
949
+ label;
950
+ styles;
951
+ classes;
952
+ state;
953
+ pseudos;
954
+ constructor(label, styles, classes, state, pseudos) {
955
+ super();
956
+ this.label = label;
957
+ this.styles = styles;
958
+ this.classes = classes;
959
+ this.state = state;
960
+ this.pseudos = pseudos;
961
+ }
962
+ render() {
963
+ return renderWithPseudo((className) => {
964
+ const href = this.state.href || "#";
965
+ const attrs2 = [`href="${escapeHtml(href)}"`];
966
+ if (this.state.target)
967
+ attrs2.push(`target="${this.state.target}"`);
968
+ if (this.state.rel)
969
+ attrs2.push(`rel="${this.state.rel}"`);
970
+ const classList = [className, ...Object.values(this.classes)].filter(Boolean);
971
+ const classAttrStr = classList.length ? ` class="${classList.join(" ")}"` : "";
972
+ return `<a ${attrs2.join(" ")}${classAttrStr}${styleAttr({
973
+ ...baseStyleMap(this.styles),
974
+ color: this.styles.color,
975
+ fontSize: this.styles.fontSize,
976
+ fontWeight: this.styles.fontWeight,
977
+ textDecoration: this.styles.textDecoration
978
+ })}>${escapeHtml(this.label)}</a>`;
979
+ }, this.pseudos);
980
+ }
981
+ };
982
+ var A = createLinkBuilder();
983
+ var DialogElement = class extends UIElement {
984
+ state;
985
+ children;
986
+ constructor(state, children) {
987
+ super();
988
+ this.state = state;
989
+ this.children = children;
990
+ }
991
+ render() {
992
+ const {
993
+ isOpen,
994
+ maskColor,
995
+ maskOpacity,
996
+ closeOnClickOutside,
997
+ closeOnEscape,
998
+ trapFocus,
999
+ styles,
1000
+ classes,
1001
+ pseudos
1002
+ } = this.state;
1003
+ if (!isOpen) {
1004
+ throw new Error("Dialog requires .bind(signal) to be set");
1005
+ }
1006
+ const dialogId = `dialog-${isOpen.key}`;
1007
+ const backdropClass = `dialog-backdrop-${hash({ maskColor, maskOpacity })}`;
1008
+ const backdropCSS = `
1009
+ dialog#${dialogId}::backdrop {
1010
+ background-color: ${maskColor};
1011
+ opacity: ${maskOpacity};
1012
+ }
1013
+ `;
1014
+ pushCSS(backdropCSS);
1015
+ const contentHtml = renderWithPseudo((className) => {
1016
+ const classList = [className, ...Object.values(classes)].filter(Boolean);
1017
+ const classAttrStr = classList.length ? ` class="${classList.join(" ")}"` : "";
1018
+ const inlineStyles = {
1019
+ ...baseStyleMap(styles),
1020
+ backgroundColor: styles.backgroundColor || "white",
1021
+ borderRadius: styles.borderRadius,
1022
+ width: styles.width,
1023
+ height: styles.height,
1024
+ minWidth: styles.minWidth,
1025
+ maxWidth: styles.maxWidth,
1026
+ minHeight: styles.minHeight,
1027
+ maxHeight: styles.maxHeight,
1028
+ border: "none",
1029
+ padding: "0"
1030
+ };
1031
+ const childrenHtml = this.children.map(resolveChild).join("");
1032
+ return `<dialog
1033
+ id="${dialogId}"
1034
+ data-dialog="${dialogId}"
1035
+ data-signal="${isOpen.key}"
1036
+ data-close-outside="${closeOnClickOutside}"
1037
+ data-close-escape="${closeOnEscape}"
1038
+ data-trap-focus="${trapFocus}"
1039
+ ${classAttrStr}
1040
+ ${styleAttr(inlineStyles)}
1041
+ >${childrenHtml}</dialog>`;
1042
+ }, pseudos);
1043
+ return contentHtml;
1044
+ }
1045
+ };
1046
+ function createDialogBuilder(state) {
1047
+ const fn = (...children) => new DialogElement(state, children);
1048
+ const mod = (updates) => createDialogBuilder({ ...state, ...updates });
1049
+ fn.bind = (signal) => mod({ isOpen: signal });
1050
+ fn.maskColor = (color) => mod({ maskColor: resolveColor(color) });
1051
+ fn.maskOpacity = (opacity) => mod({ maskOpacity: opacity });
1052
+ fn.closeOnClickOutside = (enabled) => mod({ closeOnClickOutside: enabled });
1053
+ fn.closeOnEscape = (enabled) => mod({ closeOnEscape: enabled });
1054
+ fn.trapFocus = (enabled) => mod({ trapFocus: enabled });
1055
+ fn.width = (v) => mod({ styles: { ...state.styles, width: resolveSize(v) } });
1056
+ fn.w = (v) => mod({ styles: { ...state.styles, width: resolveSize(v) } });
1057
+ fn.height = (v) => mod({ styles: { ...state.styles, height: resolveSize(v) } });
1058
+ fn.h = (v) => mod({ styles: { ...state.styles, height: resolveSize(v) } });
1059
+ fn.minw = (v) => mod({ styles: { ...state.styles, minWidth: resolveSize(v) } });
1060
+ fn.maxw = (v) => mod({ styles: { ...state.styles, maxWidth: resolveSize(v) } });
1061
+ fn.minh = (v) => mod({ styles: { ...state.styles, minHeight: resolveSize(v) } });
1062
+ fn.maxh = (v) => mod({ styles: { ...state.styles, maxHeight: resolveSize(v) } });
1063
+ fn.padding = (v) => mod({ classes: { ...state.classes, p: cls("p", v) } });
1064
+ fn.p = (v) => mod({ classes: { ...state.classes, p: cls("p", v) } });
1065
+ fn.pt = (v) => mod({ classes: { ...state.classes, pt: cls("pt", v) } });
1066
+ fn.pb = (v) => mod({ classes: { ...state.classes, pb: cls("pb", v) } });
1067
+ fn.pl = (v) => mod({ classes: { ...state.classes, pl: cls("pl", v) } });
1068
+ fn.pr = (v) => mod({ classes: { ...state.classes, pr: cls("pr", v) } });
1069
+ fn.px = (v) => mod({ classes: { ...state.classes, px: cls("px", v) } });
1070
+ fn.py = (v) => mod({ classes: { ...state.classes, py: cls("py", v) } });
1071
+ fn.background = (v) => mod({ styles: { ...state.styles, backgroundColor: resolveColor(v) } });
1072
+ fn.radius = (v) => mod({ classes: { ...state.classes, radius: cls("radius", v) } });
1073
+ fn.hover = (cb) => {
1074
+ const b = cb(createPseudoStyleBuilder());
1075
+ return mod({ pseudos: { ...state.pseudos, hover: { styles: b.__styles, classes: b.__classes } } });
1076
+ };
1077
+ fn.focus = (cb) => {
1078
+ const b = cb(createPseudoStyleBuilder());
1079
+ return mod({ pseudos: { ...state.pseudos, focus: { styles: b.__styles, classes: b.__classes } } });
1080
+ };
1081
+ return fn;
1082
+ }
1083
+ var Dialog = createDialogBuilder({
1084
+ isOpen: null,
1085
+ maskColor: "rgba(0, 0, 0, 0.5)",
1086
+ maskOpacity: 1,
1087
+ closeOnClickOutside: true,
1088
+ closeOnEscape: true,
1089
+ trapFocus: true,
1090
+ styles: {},
1091
+ classes: {},
1092
+ pseudos: {}
1093
+ });
1094
+ var HeadElement = class extends UIElement {
1095
+ children;
1096
+ constructor(children) {
1097
+ super();
1098
+ this.children = children;
1099
+ }
1100
+ render() {
1101
+ const scopedCSS = drainCSS();
1102
+ const parts = [];
1103
+ for (const child of this.children) {
1104
+ parts.push(resolveChild(child));
1105
+ }
1106
+ if (scopedCSS) {
1107
+ parts.push(`<style>
1108
+ ${scopedCSS}
1109
+ </style>`);
1110
+ }
1111
+ return `<head>
1112
+ ${parts.join(`
1113
+ `)}
1114
+ </head>`;
1115
+ }
1116
+ };
1117
+ function createHeadBuilder(children = []) {
1118
+ const fn = () => new HeadElement(children);
1119
+ fn.charset = (charset = "UTF-8") => createHeadBuilder([...children, Charset(charset)]);
1120
+ fn.viewport = (content = "width=device-width, initial-scale=1.0") => createHeadBuilder([...children, Viewport(content)]);
1121
+ fn.title = (title) => createHeadBuilder([...children, Title(title)]);
1122
+ fn.css = (hrefs) => {
1123
+ const files = Array.isArray(hrefs) ? hrefs : [hrefs];
1124
+ return createHeadBuilder([...children, ...files.map(StyleSheet)]);
1125
+ };
1126
+ fn.globalStyles = (css) => createHeadBuilder([...children, GlobalStyles(css)]);
1127
+ return fn;
1128
+ }
1129
+ function Head(...children) {
1130
+ return createHeadBuilder(children);
1131
+ }
1132
+ function Charset(charset = "UTF-8") {
1133
+ return new SafeHTML(`<meta charset="${charset}" />`);
1134
+ }
1135
+ function Viewport(content = "width=device-width, initial-scale=1.0") {
1136
+ return new SafeHTML(`<meta name="viewport" content="${content}" />`);
1137
+ }
1138
+ function Title(title) {
1139
+ return new SafeHTML(`<title>${escapeHtml(title)}</title>`);
1140
+ }
1141
+ function GlobalStyles(css) {
1142
+ return new SafeHTML(`<style>${css}</style>`);
1143
+ }
1144
+ var LinkElement2 = class _LinkElement2 {
1145
+ state;
1146
+ constructor(state = {}) {
1147
+ this.state = state;
1148
+ }
1149
+ rel(rel) {
1150
+ return new _LinkElement2({ ...this.state, rel });
1151
+ }
1152
+ href(href) {
1153
+ return new _LinkElement2({ ...this.state, href });
1154
+ }
1155
+ type(type) {
1156
+ return new _LinkElement2({ ...this.state, type });
1157
+ }
1158
+ as(as) {
1159
+ return new _LinkElement2({ ...this.state, as });
1160
+ }
1161
+ crossorigin(value) {
1162
+ return new _LinkElement2({ ...this.state, crossorigin: value });
1163
+ }
1164
+ integrity(value) {
1165
+ return new _LinkElement2({ ...this.state, integrity: value });
1166
+ }
1167
+ toString() {
1168
+ const attrs2 = [];
1169
+ if (this.state.rel)
1170
+ attrs2.push(`rel="${this.state.rel}"`);
1171
+ if (this.state.href)
1172
+ attrs2.push(`href="${this.state.href}"`);
1173
+ if (this.state.type)
1174
+ attrs2.push(`type="${this.state.type}"`);
1175
+ if (this.state.as)
1176
+ attrs2.push(`as="${this.state.as}"`);
1177
+ if (this.state.crossorigin)
1178
+ attrs2.push(`crossorigin="${this.state.crossorigin}"`);
1179
+ if (this.state.integrity)
1180
+ attrs2.push(`integrity="${this.state.integrity}"`);
1181
+ return `<link ${attrs2.join(" ")} />`;
1182
+ }
1183
+ };
1184
+ function Link() {
1185
+ return new LinkElement2();
1186
+ }
1187
+ function StyleSheet(href) {
1188
+ return new SafeHTML(Link().rel("stylesheet").href(href).toString());
1189
+ }
1190
+ var BodyElement = class extends UIElement {
1191
+ state;
1192
+ children;
1193
+ constructor(state, children) {
1194
+ super();
1195
+ this.state = state;
1196
+ this.children = children;
1197
+ }
1198
+ render() {
1199
+ const { flexDirection, scripts, signalState, styles, classes, pseudos } = this.state;
1200
+ const classList = [...Object.values(classes)];
1201
+ if (flexDirection) {
1202
+ classList.push("flex");
1203
+ classList.push(flexDirection === "col" ? "flex-col" : "flex-row");
1204
+ }
1205
+ const inlineStyles = {
1206
+ ...baseStyleMap(styles)
1207
+ };
1208
+ return renderWithPseudo((className) => {
1209
+ const allClasses = [className, ...classList].filter(Boolean);
1210
+ const classAttrStr = allClasses.length ? ` class="${allClasses.join(" ")}"` : "";
1211
+ const styleStr = Object.entries(inlineStyles).filter(([, v]) => v).map(([k, v]) => `${toKebab(k)}: ${v}`).join("; ");
1212
+ const styleAttrStr = styleStr ? ` style="${styleStr}"` : "";
1213
+ const childrenHtml = this.children.map(resolveChild).join(`
1214
+ `);
1215
+ const signalScript = signalState ? `
1216
+ <script>window.__signals__ = ${JSON.stringify(signalState)};</script>` : "";
1217
+ const scriptTags = scripts.length ? `
1218
+ ` + scripts.map((s) => `<script src="${s}"></script>`).join(`
1219
+ `) : "";
1220
+ return `<body${classAttrStr}${styleAttrStr}>
1221
+ ${childrenHtml}${signalScript}${scriptTags}
1222
+ </body>`;
1223
+ }, pseudos);
1224
+ }
1225
+ };
1226
+ function createBodyBuilder(state = {
1227
+ styles: {},
1228
+ classes: {},
1229
+ pseudos: {},
1230
+ flexDirection: void 0,
1231
+ scripts: [],
1232
+ signalState: void 0
1233
+ }) {
1234
+ const fn = (...children) => new BodyElement(state, children);
1235
+ const mod = (updates) => createBodyBuilder({ ...state, ...updates });
1236
+ const rebuildWithPseudos = (pseudos) => createBodyBuilder({ ...state, pseudos });
1237
+ fn.flex = (direction) => mod({ flexDirection: direction });
1238
+ fn.scripts = (scripts) => mod({ scripts: Array.isArray(scripts) ? scripts : [scripts] });
1239
+ fn.hydrateSignals = (signalState) => mod({ signalState });
1240
+ fn.signalState = (signalState) => signalState ? mod({ signalState }) : createBodyBuilder(state);
1241
+ Object.defineProperty(fn, "mobile", {
1242
+ get: () => createBreakpointContext("mobile", state.pseudos, rebuildWithPseudos),
1243
+ enumerable: true
1244
+ });
1245
+ Object.defineProperty(fn, "tablet", {
1246
+ get: () => createBreakpointContext("tablet", state.pseudos, rebuildWithPseudos),
1247
+ enumerable: true
1248
+ });
1249
+ Object.defineProperty(fn, "desktop", {
1250
+ get: () => createBreakpointContext("desktop", state.pseudos, rebuildWithPseudos),
1251
+ enumerable: true
1252
+ });
1253
+ function addPseudoState2(key, cb) {
1254
+ const b = cb(createPseudoStyleBuilder());
1255
+ return rebuildWithPseudos({ ...state.pseudos, [key]: { styles: b.__styles, classes: b.__classes } });
1256
+ }
1257
+ fn.hover = (cb) => addPseudoState2("hover", cb);
1258
+ fn.active = (cb) => addPseudoState2("active", cb);
1259
+ fn.focus = (cb) => addPseudoState2("focus", cb);
1260
+ fn.focusWithin = (cb) => addPseudoState2("focusWithin", cb);
1261
+ fn.width = (v) => mod({ classes: { ...state.classes, w: cls("w", v) } });
1262
+ fn.height = (v) => mod({ classes: { ...state.classes, h: cls("h", v) } });
1263
+ fn.margin = (v) => mod({ classes: { ...state.classes, m: cls("m", v) } });
1264
+ fn.marginT = (v) => mod({ classes: { ...state.classes, mt: cls("mt", v) } });
1265
+ fn.marginB = (v) => mod({ classes: { ...state.classes, mb: cls("mb", v) } });
1266
+ fn.marginL = (v) => mod({ classes: { ...state.classes, ml: cls("ml", v) } });
1267
+ fn.marginR = (v) => mod({ classes: { ...state.classes, mr: cls("mr", v) } });
1268
+ fn.marginX = (v) => mod({ classes: { ...state.classes, mx: cls("mx", v) } });
1269
+ fn.marginY = (v) => mod({ classes: { ...state.classes, my: cls("my", v) } });
1270
+ fn.m = (v) => mod({ classes: { ...state.classes, m: cls("m", v) } });
1271
+ fn.mt = (v) => mod({ classes: { ...state.classes, mt: cls("mt", v) } });
1272
+ fn.mb = (v) => mod({ classes: { ...state.classes, mb: cls("mb", v) } });
1273
+ fn.ml = (v) => mod({ classes: { ...state.classes, ml: cls("ml", v) } });
1274
+ fn.mr = (v) => mod({ classes: { ...state.classes, mr: cls("mr", v) } });
1275
+ fn.mx = (v) => mod({ classes: { ...state.classes, mx: cls("mx", v) } });
1276
+ fn.my = (v) => mod({ classes: { ...state.classes, my: cls("my", v) } });
1277
+ fn.padding = (v) => mod({ classes: { ...state.classes, p: cls("p", v) } });
1278
+ fn.paddingT = (v) => mod({ classes: { ...state.classes, pt: cls("pt", v) } });
1279
+ fn.paddingB = (v) => mod({ classes: { ...state.classes, pb: cls("pb", v) } });
1280
+ fn.paddingL = (v) => mod({ classes: { ...state.classes, pl: cls("pl", v) } });
1281
+ fn.paddingR = (v) => mod({ classes: { ...state.classes, pr: cls("pr", v) } });
1282
+ fn.paddingX = (v) => mod({ classes: { ...state.classes, px: cls("px", v) } });
1283
+ fn.paddingY = (v) => mod({ classes: { ...state.classes, py: cls("py", v) } });
1284
+ fn.p = (v) => mod({ classes: { ...state.classes, p: cls("p", v) } });
1285
+ fn.pt = (v) => mod({ classes: { ...state.classes, pt: cls("pt", v) } });
1286
+ fn.pb = (v) => mod({ classes: { ...state.classes, pb: cls("pb", v) } });
1287
+ fn.pl = (v) => mod({ classes: { ...state.classes, pl: cls("pl", v) } });
1288
+ fn.pr = (v) => mod({ classes: { ...state.classes, pr: cls("pr", v) } });
1289
+ fn.px = (v) => mod({ classes: { ...state.classes, px: cls("px", v) } });
1290
+ fn.py = (v) => mod({ classes: { ...state.classes, py: cls("py", v) } });
1291
+ fn.gap = (v) => mod({ classes: { ...state.classes, gap: cls("gap", v) } });
1292
+ fn.gapX = (v) => mod({ classes: { ...state.classes, gapx: cls("gapx", v) } });
1293
+ fn.gapY = (v) => mod({ classes: { ...state.classes, gapy: cls("gapy", v) } });
1294
+ fn.spaceX = (v) => mod({ classes: { ...state.classes, gapx: cls("gapx", v) } });
1295
+ fn.spaceY = (v) => mod({ classes: { ...state.classes, gapy: cls("gapy", v) } });
1296
+ fn.align = (v) => {
1297
+ const classMap = {
1298
+ start: "items-start",
1299
+ end: "items-end",
1300
+ "end-safe": "items-end",
1301
+ center: "items-center",
1302
+ "center-safe": "items-center",
1303
+ baseline: "items-baseline",
1304
+ "baseline-last": "items-baseline",
1305
+ stretch: "items-stretch"
1306
+ };
1307
+ return mod({ classes: { ...state.classes, align: classMap[v] } });
1308
+ };
1309
+ fn.justify = (v) => {
1310
+ const classMap = {
1311
+ start: "justify-start",
1312
+ end: "justify-end",
1313
+ "end-safe": "justify-end",
1314
+ center: "justify-center",
1315
+ "center-safe": "justify-center",
1316
+ between: "justify-between",
1317
+ around: "justify-around",
1318
+ evenly: "justify-evenly",
1319
+ stretch: "justify-stretch",
1320
+ baseline: "justify-baseline",
1321
+ normal: "justify-normal"
1322
+ };
1323
+ return mod({ classes: { ...state.classes, justify: classMap[v] } });
1324
+ };
1325
+ fn.acjc = () => mod({
1326
+ classes: { ...state.classes, align: "items-center", justify: "justify-center" }
1327
+ });
1328
+ fn.background = (v) => mod({ classes: { ...state.classes, bg: cls("bg", v) } });
1329
+ fn.radius = (v) => mod({ classes: { ...state.classes, radius: cls("radius", v) } });
1330
+ return fn;
1331
+ }
1332
+ var Body = createBodyBuilder();
1333
+ var DocumentElement = class extends UIElement {
1334
+ head;
1335
+ body;
1336
+ lang;
1337
+ constructor(head, body, lang = "en") {
1338
+ super();
1339
+ this.head = head;
1340
+ this.body = body;
1341
+ this.lang = lang;
1342
+ }
1343
+ render() {
1344
+ return `<!DOCTYPE html>
1345
+ <html lang="${this.lang}">
1346
+ ${this.head.render()}
1347
+ ${this.body.render()}
1348
+ </html>`;
1349
+ }
1350
+ };
1351
+ function createDocumentBuilder(head, body, lang = "en") {
1352
+ const doc = new DocumentElement(head, body, lang);
1353
+ return {
1354
+ lang(newLang) {
1355
+ return createDocumentBuilder(head, body, newLang);
1356
+ },
1357
+ render() {
1358
+ return doc.render();
1359
+ }
1360
+ };
1361
+ }
1362
+ function Document(head, body) {
1363
+ const headElement = typeof head === "function" ? head() : head;
1364
+ return createDocumentBuilder(headElement, body);
1365
+ }
1366
+
1367
+ // cli.ts
1368
+ var [command, appFile] = Deno.args;
1369
+ if (command !== "dev" && command !== "build") {
1370
+ console.error("Usage: vebui <dev|build> <file.ts>");
1371
+ Deno.exit(1);
1372
+ }
1373
+ var VERBOSE = Deno.env.get("VEBUI_VERBOSE") === "true";
1374
+ function resolveCorePackage() {
1375
+ const workspacePath = new URL("../../core", import.meta.url).pathname;
1376
+ try {
1377
+ Deno.statSync(workspacePath + "/index.ts");
1378
+ if (VERBOSE) console.log(`[vebui] using workspace core: ${workspacePath}`);
1379
+ return workspacePath;
1380
+ } catch {
1381
+ }
1382
+ try {
1383
+ const corePath = new URL(import.meta.resolve("@vebui/core")).pathname;
1384
+ if (VERBOSE) console.log(`[vebui] resolved core via import.meta: ${corePath}`);
1385
+ if (corePath.includes("/dist/")) return dirname(dirname(corePath));
1386
+ return dirname(corePath);
1387
+ } catch {
1388
+ console.error("[vebui] Error: Cannot resolve @vebui/core package");
1389
+ Deno.exit(1);
1390
+ }
1391
+ }
1392
+ var corePackageRoot = resolveCorePackage();
1393
+ if (VERBOSE) console.log(`[vebui] core package root: ${corePackageRoot}`);
1394
+ var userPatterns = Deno.env.get("VEBUI_CONTENT")?.split(",").map((s) => s.trim()) ?? [];
1395
+ var patterns = [
1396
+ `${corePackageRoot}/**/*.ts`,
1397
+ ...userPatterns
1398
+ ];
1399
+ var OUT_CSS = Deno.env.get("VEBUI_CSS_OUT") ?? "./assets/vebui/vebui.css";
1400
+ var OUT_JS = Deno.env.get("VEBUI_JS_OUT") ?? "./assets/vebui/vebui.client.js";
1401
+ async function* walkDir(dir) {
1402
+ for await (const entry of Deno.readDir(dir)) {
1403
+ const fullPath = resolve(dir, entry.name);
1404
+ if (entry.isDirectory) yield* walkDir(fullPath);
1405
+ else if (entry.isFile) yield fullPath;
1406
+ }
1407
+ }
1408
+ function globBase(pattern) {
1409
+ const starIdx = pattern.indexOf("*");
1410
+ if (starIdx === -1) return pattern;
1411
+ return dirname(pattern.slice(0, starIdx + 1));
1412
+ }
1413
+ async function resolveFiles(globs) {
1414
+ const files = /* @__PURE__ */ new Set();
1415
+ for (const pattern of globs) {
1416
+ const base = globBase(pattern);
1417
+ try {
1418
+ for await (const file of walkDir(base)) {
1419
+ if (!file.endsWith(".ts") || file.includes("clis/") || file.endsWith(".css") || file.endsWith(".js") || file.includes("/client/")) continue;
1420
+ files.add(file);
1421
+ }
1422
+ } catch {
1423
+ }
1424
+ }
1425
+ if (VERBOSE) console.log(`[vebui] resolved ${files.size} files`);
1426
+ return [...files];
1427
+ }
1428
+ var CHAIN_RE = /\b(VStack|HStack|Block|Text|Button|Input|Body|Head)(?:(?:\s*\.\s*[a-zA-Z0-9]+\s*\((?:[^()]*|\((?:[^()]*|\([^()]*\))*\))*\))|(?:\s*\.\s*(?:mobile|tablet|desktop|hover|active|focus|focusWithin|before|after)))+/g;
1429
+ var IMPORT_CSS_RE = /import\s+["'](.+\.css)["']/g;
1430
+ async function extractCSSFromSource(source, allClasses, discoveredCSS, currentFile) {
1431
+ for (const match of source.matchAll(IMPORT_CSS_RE)) {
1432
+ const importPath = match[1];
1433
+ if (!importPath) continue;
1434
+ const resolvedPath = importPath.startsWith(".") ? resolve(dirname(currentFile), importPath) : importPath;
1435
+ discoveredCSS.add(resolvedPath);
1436
+ }
1437
+ const MODIFIER_RE = /\.([a-zA-Z0-9]+)\((?:"([^"]+)"|([\d.]+))\)/g;
1438
+ const MODIFIER_TO_CLS = {
1439
+ margin: "m",
1440
+ marginT: "mt",
1441
+ marginB: "mb",
1442
+ marginL: "ml",
1443
+ marginR: "mr",
1444
+ marginX: "mx",
1445
+ marginY: "my",
1446
+ m: "m",
1447
+ mt: "mt",
1448
+ mb: "mb",
1449
+ ml: "ml",
1450
+ mr: "mr",
1451
+ mx: "mx",
1452
+ my: "my",
1453
+ padding: "p",
1454
+ paddingT: "pt",
1455
+ paddingB: "pb",
1456
+ paddingL: "pl",
1457
+ paddingR: "pr",
1458
+ paddingX: "px",
1459
+ paddingY: "py",
1460
+ p: "p",
1461
+ pt: "pt",
1462
+ pb: "pb",
1463
+ pl: "pl",
1464
+ pr: "pr",
1465
+ px: "px",
1466
+ py: "py",
1467
+ gap: "gap",
1468
+ gapX: "gapx",
1469
+ gapY: "gapy",
1470
+ spaceX: "gapx",
1471
+ spaceY: "gapy",
1472
+ radius: "radius",
1473
+ size: "text",
1474
+ width: "w",
1475
+ height: "h",
1476
+ background: "bg"
1477
+ };
1478
+ const INLINE_MODIFIERS = /* @__PURE__ */ new Set(["color", "weight", "align", "justify", "border", "opacity", "fontWeight", "fontSize", "flex"]);
1479
+ for (const match of source.matchAll(MODIFIER_RE)) {
1480
+ const [, modifier, strVal, numVal] = match;
1481
+ const value = strVal ?? numVal;
1482
+ if (!modifier || value === void 0 || value === null) continue;
1483
+ if (INLINE_MODIFIERS.has(modifier)) continue;
1484
+ const prefix = MODIFIER_TO_CLS[modifier];
1485
+ if (prefix) allClasses.add(`${prefix}-${String(value).replace(/[^a-zA-Z0-9]/g, "_")}`);
1486
+ }
1487
+ const mockProxy = new Proxy(() => mockProxy, {
1488
+ get: (_, key) => {
1489
+ if (key === Symbol.toPrimitive) return (hint) => hint === "string" ? "MOCK" : 0;
1490
+ if (key === "key") return "mock-sig";
1491
+ return mockProxy;
1492
+ },
1493
+ apply: () => mockProxy
1494
+ });
1495
+ const context = { ...dist_exports };
1496
+ for (const match of source.matchAll(CHAIN_RE)) {
1497
+ const chain = match[0];
1498
+ try {
1499
+ const proxy = new Proxy(context, {
1500
+ get: (target, key) => {
1501
+ if (key === Symbol.unscopables) return void 0;
1502
+ if (key in target) return target[key];
1503
+ return mockProxy;
1504
+ },
1505
+ has: () => true
1506
+ });
1507
+ const result = new Function("with(this) { return " + chain + " }").call(proxy);
1508
+ if (typeof result === "function") {
1509
+ const element = result("DUMMY");
1510
+ if (element && typeof element.render === "function") {
1511
+ const html = element.render();
1512
+ for (const classMatch of html.matchAll(/class="([^"]+)"/g)) {
1513
+ classMatch[1].split(" ").forEach((cls2) => {
1514
+ if (cls2 && !cls2.startsWith("w-")) allClasses.add(cls2);
1515
+ });
1516
+ }
1517
+ }
1518
+ }
1519
+ } catch (e) {
1520
+ if (VERBOSE) console.error(`[vebui] eval failed for ${chain.slice(0, 50).trim()}:`, e);
1521
+ }
1522
+ }
1523
+ }
1524
+ async function bundleClient() {
1525
+ const clientEntry = resolve(corePackageRoot, "client/index.ts");
1526
+ Deno.mkdirSync(dirname(OUT_JS), { recursive: true });
1527
+ const result = await esbuild({
1528
+ entryPoints: [clientEntry],
1529
+ bundle: true,
1530
+ minify: true,
1531
+ format: "esm",
1532
+ platform: "browser",
1533
+ write: false
1534
+ });
1535
+ const out = result.outputFiles[0];
1536
+ if (out) {
1537
+ await Deno.writeTextFile(OUT_JS, out.text);
1538
+ console.log(`[vebui] bundled client \u2192 ${OUT_JS} (${out.text.length} bytes)`);
1539
+ }
1540
+ }
1541
+ async function generateCSS() {
1542
+ const files = await resolveFiles(patterns);
1543
+ const allClasses = /* @__PURE__ */ new Set();
1544
+ const discoveredCSS = /* @__PURE__ */ new Set();
1545
+ Deno.mkdirSync(dirname(OUT_CSS), { recursive: true });
1546
+ drainCSS();
1547
+ for (const file of files) {
1548
+ const source = await Deno.readTextFile(file);
1549
+ await extractCSSFromSource(source, allClasses, discoveredCSS, file);
1550
+ }
1551
+ const hashedCSS = drainCSS();
1552
+ const utilityRules = [];
1553
+ for (const cls2 of allClasses) {
1554
+ const decl = classToDeclaration(cls2);
1555
+ if (decl) utilityRules.push(`.${cls2} { ${decl} }`);
1556
+ }
1557
+ const parts = ["/* Generated by vebui \u2014 do not edit */"];
1558
+ try {
1559
+ const tokens = await Deno.readTextFile(resolve(corePackageRoot, "tokens.css"));
1560
+ parts.push("\n/* Design Tokens & Reset */");
1561
+ parts.push(tokens);
1562
+ } catch {
1563
+ console.warn("[vebui] Warning: Could not find core/tokens.css");
1564
+ }
1565
+ for (const cssFile of discoveredCSS) {
1566
+ try {
1567
+ const content = await Deno.readTextFile(cssFile);
1568
+ parts.push(`
1569
+ /* User CSS: ${cssFile} */`);
1570
+ parts.push(content);
1571
+ } catch {
1572
+ console.warn(`[vebui] Warning: Could not read CSS file: ${cssFile}`);
1573
+ }
1574
+ }
1575
+ parts.push("\n/* Utility Classes */");
1576
+ parts.push(...utilityRules);
1577
+ if (hashedCSS.trim()) {
1578
+ parts.push("\n/* Hashed Pseudo-classes */");
1579
+ parts.push(hashedCSS);
1580
+ }
1581
+ await Deno.writeTextFile(OUT_CSS, parts.join("\n"));
1582
+ console.log(`[vebui] generated css \u2192 ${OUT_CSS} (${files.length} files, ${utilityRules.length} utilities)`);
1583
+ }
1584
+ async function buildAll() {
1585
+ await Promise.all([generateCSS(), bundleClient()]);
1586
+ }
1587
+ await buildAll();
1588
+ if (command === "build") {
1589
+ esbuildStop();
1590
+ Deno.exit(0);
1591
+ }
1592
+ if (appFile) {
1593
+ new Deno.Command("deno", {
1594
+ args: ["run", "--allow-all", appFile],
1595
+ stdout: "inherit",
1596
+ stderr: "inherit"
1597
+ }).spawn();
1598
+ }
1599
+ var watchDirs = new Set(
1600
+ patterns.map((p) => {
1601
+ const full = p.startsWith("/") ? p : resolve(Deno.cwd(), p);
1602
+ return p.includes("*") ? full.replace(/\/\*.*$/, "") : dirname(full);
1603
+ })
1604
+ );
1605
+ if (VERBOSE) console.log(`[vebui] watching: ${[...watchDirs].join(", ")}`);
1606
+ var debounceTimer = null;
1607
+ function scheduleRebuild(path) {
1608
+ if (debounceTimer) clearTimeout(debounceTimer);
1609
+ debounceTimer = setTimeout(async () => {
1610
+ const isClient = path.includes("/client/");
1611
+ if (!isClient) await generateCSS();
1612
+ if (isClient || path.includes("signal-rpc.ts")) await bundleClient();
1613
+ }, 50);
1614
+ }
1615
+ var cleanup = () => {
1616
+ esbuildStop();
1617
+ Deno.exit(0);
1618
+ };
1619
+ Deno.addSignalListener("SIGINT", cleanup);
1620
+ Deno.addSignalListener("SIGTERM", cleanup);
1621
+ for (const dir of watchDirs) {
1622
+ ;
1623
+ (async () => {
1624
+ try {
1625
+ const watcher = Deno.watchFs(dir, { recursive: true });
1626
+ for await (const event of watcher) {
1627
+ if (event.kind !== "modify" && event.kind !== "create") continue;
1628
+ for (const path of event.paths) {
1629
+ if (!path.endsWith(".ts")) continue;
1630
+ scheduleRebuild(path);
1631
+ }
1632
+ }
1633
+ } catch {
1634
+ }
1635
+ })();
1636
+ }