@vertz/ui 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +339 -857
  2. package/dist/css/public.d.ts +24 -27
  3. package/dist/css/public.js +5 -1
  4. package/dist/form/public.d.ts +94 -38
  5. package/dist/form/public.js +5 -3
  6. package/dist/index.d.ts +696 -167
  7. package/dist/index.js +461 -84
  8. package/dist/internals.d.ts +192 -23
  9. package/dist/internals.js +151 -102
  10. package/dist/jsx-runtime/index.d.ts +44 -17
  11. package/dist/jsx-runtime/index.js +26 -7
  12. package/dist/query/public.d.ts +62 -7
  13. package/dist/query/public.js +12 -4
  14. package/dist/router/public.d.ts +186 -26
  15. package/dist/router/public.js +22 -7
  16. package/dist/shared/{chunk-f1ynwam4.js → chunk-0p5f7gmg.js} +155 -32
  17. package/dist/shared/{chunk-j8vzvne3.js → chunk-9e92w0wt.js} +4 -1
  18. package/dist/shared/{chunk-xd9d7q5p.js → chunk-cq7xg4xe.js} +59 -10
  19. package/dist/shared/chunk-g4rch80a.js +33 -0
  20. package/dist/shared/{chunk-pgymxpn1.js → chunk-hrd0mft1.js} +136 -34
  21. package/dist/shared/chunk-nmjyj8p9.js +290 -0
  22. package/dist/shared/chunk-pp3a6xbn.js +483 -0
  23. package/dist/shared/chunk-prj7nm08.js +67 -0
  24. package/dist/shared/chunk-q6cpe5k7.js +230 -0
  25. package/dist/shared/chunk-ryb49346.js +374 -0
  26. package/dist/shared/chunk-v3yyf79g.js +48 -0
  27. package/dist/shared/chunk-vx0kzack.js +103 -0
  28. package/dist/shared/chunk-wv6kkj1w.js +464 -0
  29. package/dist/test/index.d.ts +67 -6
  30. package/dist/test/index.js +4 -3
  31. package/package.json +13 -8
  32. package/dist/shared/chunk-bp3v6s9j.js +0 -62
  33. package/dist/shared/chunk-d8h2eh8d.js +0 -141
  34. package/dist/shared/chunk-tsdpgmks.js +0 -98
  35. package/dist/shared/chunk-zbbvx05f.js +0 -202
package/dist/index.js CHANGED
@@ -1,83 +1,100 @@
1
1
  import {
2
- eagerStrategy,
2
+ ANIMATION_DURATION,
3
+ ANIMATION_EASING,
4
+ accordionDown,
5
+ accordionUp,
6
+ fadeIn,
7
+ fadeOut,
3
8
  hydrate,
4
- idleStrategy,
5
- interactionStrategy,
6
- lazyStrategy,
7
- mediaStrategy,
8
- visibleStrategy
9
- } from "./shared/chunk-d8h2eh8d.js";
9
+ isQueryDescriptor,
10
+ keyframes,
11
+ onAnimationsComplete,
12
+ palettes,
13
+ slideInFromBottom,
14
+ slideInFromLeft,
15
+ slideInFromRight,
16
+ slideInFromTop,
17
+ slideOutToBottom,
18
+ slideOutToLeft,
19
+ slideOutToRight,
20
+ slideOutToTop,
21
+ zoomIn,
22
+ zoomOut
23
+ } from "./shared/chunk-pp3a6xbn.js";
10
24
  import {
25
+ Outlet,
26
+ OutletContext,
27
+ RouterContext,
28
+ RouterView,
11
29
  createLink,
12
- createOutlet,
13
30
  parseSearchParams,
31
+ useParams,
32
+ useRouter,
14
33
  useSearchParams
15
- } from "./shared/chunk-bp3v6s9j.js";
34
+ } from "./shared/chunk-nmjyj8p9.js";
35
+ import"./shared/chunk-v3yyf79g.js";
16
36
  import {
17
37
  createRouter
18
- } from "./shared/chunk-xd9d7q5p.js";
38
+ } from "./shared/chunk-cq7xg4xe.js";
19
39
  import {
20
40
  defineRoutes
21
- } from "./shared/chunk-j8vzvne3.js";
41
+ } from "./shared/chunk-9e92w0wt.js";
22
42
  import {
43
+ createFieldState,
23
44
  form,
24
45
  formDataToObject,
25
46
  validate
26
- } from "./shared/chunk-tsdpgmks.js";
47
+ } from "./shared/chunk-q6cpe5k7.js";
27
48
  import {
28
- query
29
- } from "./shared/chunk-zbbvx05f.js";
49
+ query,
50
+ queryMatch
51
+ } from "./shared/chunk-wv6kkj1w.js";
52
+ import"./shared/chunk-vx0kzack.js";
53
+ import {
54
+ ThemeProvider,
55
+ children,
56
+ compileTheme,
57
+ css,
58
+ defineTheme,
59
+ getInjectedCSS,
60
+ globalCss,
61
+ injectCSS,
62
+ resetInjectedStyles,
63
+ resolveChildren,
64
+ s,
65
+ variants
66
+ } from "./shared/chunk-0p5f7gmg.js";
67
+ import {
68
+ __append,
69
+ __element,
70
+ __enterChildren,
71
+ __exitChildren,
72
+ __staticText,
73
+ endHydration,
74
+ startHydration
75
+ } from "./shared/chunk-ryb49346.js";
76
+ import {
77
+ RENDER_NODE_BRAND,
78
+ createDOMAdapter,
79
+ getAdapter,
80
+ isRenderNode,
81
+ setAdapter
82
+ } from "./shared/chunk-g4rch80a.js";
30
83
  import {
31
84
  DisposalScopeError,
32
85
  _tryOnCleanup,
33
86
  batch,
34
87
  computed,
35
88
  createContext,
36
- effect,
37
- onCleanup,
89
+ domEffect,
38
90
  popScope,
39
91
  pushScope,
40
92
  runCleanups,
41
93
  signal,
42
94
  untrack,
43
95
  useContext
44
- } from "./shared/chunk-pgymxpn1.js";
45
- import {
46
- ThemeProvider,
47
- compileTheme,
48
- css,
49
- defineTheme,
50
- globalCss,
51
- s,
52
- variants
53
- } from "./shared/chunk-f1ynwam4.js";
54
-
55
- // src/component/children.ts
56
- function resolveChildren(value) {
57
- if (value == null) {
58
- return [];
59
- }
60
- if (typeof value === "string") {
61
- return [document.createTextNode(value)];
62
- }
63
- if (typeof value === "number") {
64
- return [document.createTextNode(String(value))];
65
- }
66
- if (Array.isArray(value)) {
67
- const result = [];
68
- for (const child of value) {
69
- const resolved = resolveChildren(child);
70
- for (const node of resolved) {
71
- result.push(node);
72
- }
73
- }
74
- return result;
75
- }
76
- return [value];
77
- }
78
- function children(accessor) {
79
- return () => resolveChildren(accessor());
80
- }
96
+ } from "./shared/chunk-hrd0mft1.js";
97
+ import"./shared/chunk-prj7nm08.js";
81
98
  // src/component/error-boundary-context.ts
82
99
  var handlerStack = [];
83
100
  function pushErrorHandler(handler) {
@@ -137,9 +154,17 @@ function ErrorBoundary(props) {
137
154
  }
138
155
  // src/component/lifecycle.ts
139
156
  function onMount(callback) {
157
+ if (typeof globalThis !== "undefined") {
158
+ const check = globalThis.__VERTZ_IS_SSR__;
159
+ if (typeof check === "function" && check())
160
+ return;
161
+ }
140
162
  const scope = pushScope();
141
163
  try {
142
- untrack(callback);
164
+ const cleanup = untrack(callback);
165
+ if (typeof cleanup === "function") {
166
+ _tryOnCleanup(cleanup);
167
+ }
143
168
  } finally {
144
169
  popScope();
145
170
  if (scope.length > 0) {
@@ -147,26 +172,74 @@ function onMount(callback) {
147
172
  }
148
173
  }
149
174
  }
150
- function watch(dep, callback) {
151
- let innerCleanups = null;
152
- const dispose = effect(() => {
153
- if (innerCleanups) {
154
- runCleanups(innerCleanups);
155
- }
156
- const value = dep();
157
- innerCleanups = pushScope();
158
- try {
159
- untrack(() => callback(value));
160
- } finally {
161
- popScope();
162
- }
163
- });
164
- _tryOnCleanup(() => {
165
- if (innerCleanups) {
166
- runCleanups(innerCleanups);
175
+ // src/component/presence.ts
176
+ function Presence(props) {
177
+ const anchor = document.createComment("presence");
178
+ let currentNode = null;
179
+ let exitingNode = null;
180
+ let branchCleanups = [];
181
+ let generation = 0;
182
+ const outerScope = pushScope();
183
+ try {
184
+ domEffect(() => {
185
+ const show = props.when;
186
+ if (show && !currentNode) {
187
+ generation++;
188
+ if (exitingNode?.parentNode) {
189
+ exitingNode.parentNode.removeChild(exitingNode);
190
+ exitingNode = null;
191
+ }
192
+ const scope = pushScope();
193
+ const child = props.children();
194
+ popScope();
195
+ if (!(child instanceof HTMLElement)) {
196
+ runCleanups(scope);
197
+ throw new Error("Presence requires a single HTMLElement child. Wrap multiple children in a container element.");
198
+ }
199
+ branchCleanups = scope;
200
+ currentNode = child;
201
+ child.setAttribute("data-presence", "enter");
202
+ anchor.parentNode?.insertBefore(currentNode, anchor.nextSibling);
203
+ onAnimationsComplete(child, () => {
204
+ if (currentNode === child) {
205
+ child.removeAttribute("data-presence");
206
+ }
207
+ });
208
+ } else if (!show && currentNode) {
209
+ const gen = ++generation;
210
+ const exitingEl = currentNode;
211
+ currentNode = null;
212
+ exitingNode = exitingEl;
213
+ runCleanups(branchCleanups);
214
+ branchCleanups = [];
215
+ exitingEl.setAttribute("data-presence", "exit");
216
+ exitingEl.offsetHeight;
217
+ onAnimationsComplete(exitingEl, () => {
218
+ if (generation === gen) {
219
+ exitingEl.parentNode?.removeChild(exitingEl);
220
+ exitingNode = null;
221
+ }
222
+ });
223
+ }
224
+ });
225
+ } finally {
226
+ popScope();
227
+ }
228
+ const dispose = () => {
229
+ runCleanups(branchCleanups);
230
+ runCleanups(outerScope);
231
+ if (currentNode?.parentNode) {
232
+ currentNode.parentNode.removeChild(currentNode);
233
+ currentNode = null;
167
234
  }
168
- dispose();
169
- });
235
+ };
236
+ _tryOnCleanup(dispose);
237
+ const fragment = document.createDocumentFragment();
238
+ fragment.appendChild(anchor);
239
+ if (currentNode) {
240
+ fragment.appendChild(currentNode);
241
+ }
242
+ return Object.assign(fragment, { dispose });
170
243
  }
171
244
  // src/component/refs.ts
172
245
  function ref() {
@@ -217,45 +290,349 @@ function Suspense(props) {
217
290
  return placeholder;
218
291
  }
219
292
  }
293
+ // src/mount.ts
294
+ function mount(app, selector, options) {
295
+ if (typeof selector !== "string" && !(selector instanceof HTMLElement)) {
296
+ throw new Error(`mount(): selector must be a string or HTMLElement, got ${typeof selector}`);
297
+ }
298
+ const root = typeof selector === "string" ? document.querySelector(selector) : selector;
299
+ if (!root) {
300
+ throw new Error(`mount(): root element "${selector}" not found`);
301
+ }
302
+ if (options?.theme) {
303
+ const { css: css2 } = compileTheme(options.theme);
304
+ injectCSS(css2);
305
+ }
306
+ if (options?.styles) {
307
+ for (const css2 of options.styles) {
308
+ injectCSS(css2);
309
+ }
310
+ }
311
+ if (root.firstChild) {
312
+ const scope2 = pushScope();
313
+ try {
314
+ startHydration(root);
315
+ app();
316
+ endHydration();
317
+ popScope();
318
+ options?.onMount?.(root);
319
+ return {
320
+ unmount: () => {
321
+ runCleanups(scope2);
322
+ root.textContent = "";
323
+ },
324
+ root
325
+ };
326
+ } catch (e) {
327
+ endHydration();
328
+ popScope();
329
+ runCleanups(scope2);
330
+ if (typeof process !== "undefined" && true) {
331
+ console.warn("[mount] Hydration failed — re-rendering from scratch (no data loss):", e);
332
+ }
333
+ }
334
+ }
335
+ const scope = pushScope();
336
+ root.textContent = "";
337
+ const appElement = app();
338
+ root.appendChild(appElement);
339
+ popScope();
340
+ options?.onMount?.(root);
341
+ return {
342
+ unmount: () => {
343
+ runCleanups(scope);
344
+ root.textContent = "";
345
+ },
346
+ root
347
+ };
348
+ }
349
+ // src/store/merge.ts
350
+ function shallowMerge(existing, incoming) {
351
+ const result = { ...existing };
352
+ for (const key of Object.keys(incoming)) {
353
+ const value = incoming[key];
354
+ if (value !== undefined) {
355
+ result[key] = value;
356
+ }
357
+ }
358
+ return result;
359
+ }
360
+ function shallowEqual(a, b) {
361
+ const keysA = Object.keys(a);
362
+ const keysB = Object.keys(b);
363
+ if (keysA.length !== keysB.length) {
364
+ return false;
365
+ }
366
+ for (const key of keysA) {
367
+ if (a[key] !== b[key]) {
368
+ return false;
369
+ }
370
+ }
371
+ return true;
372
+ }
373
+
374
+ // src/store/query-result-index.ts
375
+ class QueryResultIndex {
376
+ _indices = new Map;
377
+ set(queryKey, ids) {
378
+ this._indices.set(queryKey, ids);
379
+ }
380
+ get(queryKey) {
381
+ return this._indices.get(queryKey);
382
+ }
383
+ removeEntity(entityId) {
384
+ for (const [queryKey, ids] of this._indices.entries()) {
385
+ const filtered = ids.filter((id) => id !== entityId);
386
+ if (filtered.length !== ids.length) {
387
+ this._indices.set(queryKey, filtered);
388
+ }
389
+ }
390
+ }
391
+ clear(queryKey) {
392
+ this._indices.delete(queryKey);
393
+ }
394
+ keys() {
395
+ return Array.from(this._indices.keys());
396
+ }
397
+ }
398
+
399
+ // src/store/entity-store.ts
400
+ class EntityStore {
401
+ _entities = new Map;
402
+ _typeListeners = new Map;
403
+ _queryIndices = new QueryResultIndex;
404
+ constructor(options) {
405
+ if (options?.initialData) {
406
+ this.hydrate(options.initialData);
407
+ }
408
+ }
409
+ get(type, id) {
410
+ const typeMap = this._entities.get(type);
411
+ if (typeMap?.has(id)) {
412
+ return typeMap.get(id);
413
+ }
414
+ const sig = signal(undefined);
415
+ this._getOrCreateTypeMap(type).set(id, sig);
416
+ return sig;
417
+ }
418
+ getMany(type, ids) {
419
+ return computed(() => ids.map((id) => this.get(type, id).value));
420
+ }
421
+ merge(type, data) {
422
+ const items = Array.isArray(data) ? data : [data];
423
+ if (items.length === 0) {
424
+ return;
425
+ }
426
+ batch(() => {
427
+ for (const item of items) {
428
+ const typeMap = this._entities.get(type);
429
+ const existing = typeMap?.get(item.id);
430
+ if (existing) {
431
+ const current = existing.peek();
432
+ const merged = shallowMerge(current || {}, item);
433
+ if (!shallowEqual(current || {}, merged)) {
434
+ untrack(() => {
435
+ existing.value = merged;
436
+ });
437
+ }
438
+ } else {
439
+ const newSignal = signal(item);
440
+ this._getOrCreateTypeMap(type).set(item.id, newSignal);
441
+ this._notifyTypeChange(type);
442
+ }
443
+ }
444
+ });
445
+ }
446
+ remove(type, id) {
447
+ const typeMap = this._entities.get(type);
448
+ if (!typeMap?.has(id)) {
449
+ return;
450
+ }
451
+ const existing = typeMap.get(id);
452
+ if (existing) {
453
+ existing.value = undefined;
454
+ }
455
+ typeMap.delete(id);
456
+ this._queryIndices.removeEntity(id);
457
+ this._notifyTypeChange(type);
458
+ }
459
+ onTypeChange(type, callback) {
460
+ const listeners = this._getOrCreateListeners(type);
461
+ listeners.add(callback);
462
+ return () => {
463
+ listeners.delete(callback);
464
+ };
465
+ }
466
+ has(type, id) {
467
+ const typeMap = this._entities.get(type);
468
+ if (!typeMap?.has(id)) {
469
+ return false;
470
+ }
471
+ const signal2 = typeMap.get(id);
472
+ return signal2?.peek() !== undefined;
473
+ }
474
+ size(type) {
475
+ const typeMap = this._entities.get(type);
476
+ if (!typeMap) {
477
+ return 0;
478
+ }
479
+ let count = 0;
480
+ for (const signal2 of typeMap.values()) {
481
+ if (signal2.peek() !== undefined) {
482
+ count++;
483
+ }
484
+ }
485
+ return count;
486
+ }
487
+ dehydrate() {
488
+ const entities = {};
489
+ for (const [type, typeMap] of this._entities.entries()) {
490
+ const typeEntities = {};
491
+ for (const [id, signal2] of typeMap.entries()) {
492
+ const value = signal2.peek();
493
+ if (value !== undefined) {
494
+ typeEntities[id] = value;
495
+ }
496
+ }
497
+ if (Object.keys(typeEntities).length > 0) {
498
+ entities[type] = typeEntities;
499
+ }
500
+ }
501
+ const queries = {};
502
+ for (const queryKey of this._queryIndices.keys()) {
503
+ const ids = this._queryIndices.get(queryKey);
504
+ if (ids) {
505
+ queries[queryKey] = { ids };
506
+ }
507
+ }
508
+ return {
509
+ entities,
510
+ ...Object.keys(queries).length > 0 ? { queries } : {}
511
+ };
512
+ }
513
+ hydrate(data) {
514
+ for (const [type, typeEntities] of Object.entries(data.entities)) {
515
+ const entities = Object.values(typeEntities).map((entity) => ({
516
+ ...entity,
517
+ id: entity.id
518
+ }));
519
+ this.merge(type, entities);
520
+ }
521
+ if (data.queries) {
522
+ for (const [queryKey, queryData] of Object.entries(data.queries)) {
523
+ this._queryIndices.set(queryKey, queryData.ids);
524
+ }
525
+ }
526
+ }
527
+ _getOrCreateTypeMap(type) {
528
+ let typeMap = this._entities.get(type);
529
+ if (!typeMap) {
530
+ typeMap = new Map;
531
+ this._entities.set(type, typeMap);
532
+ }
533
+ return typeMap;
534
+ }
535
+ _getOrCreateListeners(type) {
536
+ let listeners = this._typeListeners.get(type);
537
+ if (!listeners) {
538
+ listeners = new Set;
539
+ this._typeListeners.set(type, listeners);
540
+ }
541
+ return listeners;
542
+ }
543
+ _notifyTypeChange(type) {
544
+ const listeners = this._typeListeners.get(type);
545
+ if (listeners) {
546
+ for (const callback of listeners) {
547
+ callback();
548
+ }
549
+ }
550
+ }
551
+ }
552
+ // src/store/test-utils.ts
553
+ function createTestStore(data) {
554
+ const store = new EntityStore;
555
+ for (const [type, entities] of Object.entries(data)) {
556
+ const entityArray = Object.values(entities);
557
+ if (entityArray.length > 0) {
558
+ store.merge(type, entityArray);
559
+ }
560
+ }
561
+ return store;
562
+ }
220
563
  export {
221
- watch,
222
- visibleStrategy,
564
+ zoomOut,
565
+ zoomIn,
223
566
  variants,
224
567
  validate,
225
568
  useSearchParams,
569
+ useRouter,
570
+ useParams,
226
571
  useContext,
227
572
  untrack,
573
+ slideOutToTop,
574
+ slideOutToRight,
575
+ slideOutToLeft,
576
+ slideOutToBottom,
577
+ slideInFromTop,
578
+ slideInFromRight,
579
+ slideInFromLeft,
580
+ slideInFromBottom,
228
581
  signal,
582
+ setAdapter,
229
583
  s,
230
584
  resolveChildren,
585
+ resetInjectedStyles,
231
586
  ref,
587
+ queryMatch,
232
588
  query,
233
589
  parseSearchParams,
590
+ palettes,
234
591
  onMount,
235
- onCleanup,
236
- mediaStrategy,
237
- lazyStrategy,
238
- interactionStrategy,
239
- idleStrategy,
592
+ mount,
593
+ keyframes,
594
+ isRenderNode,
595
+ isQueryDescriptor,
596
+ injectCSS,
240
597
  hydrate,
241
598
  globalCss,
599
+ getInjectedCSS,
600
+ getAdapter,
242
601
  formDataToObject,
243
602
  form,
244
- effect,
245
- eagerStrategy,
603
+ fadeOut,
604
+ fadeIn,
246
605
  defineTheme,
247
606
  defineRoutes,
248
607
  css,
608
+ createTestStore,
249
609
  createRouter,
250
- createOutlet,
251
610
  createLink,
611
+ createFieldState,
612
+ createDOMAdapter,
252
613
  createContext,
253
614
  computed,
254
615
  compileTheme,
255
616
  children,
256
617
  batch,
618
+ accordionUp,
619
+ accordionDown,
620
+ __staticText,
621
+ __exitChildren,
622
+ __enterChildren,
623
+ __element,
624
+ __append,
257
625
  ThemeProvider,
258
626
  Suspense,
627
+ RouterView,
628
+ RouterContext,
629
+ RENDER_NODE_BRAND,
630
+ Presence,
631
+ OutletContext,
632
+ Outlet,
259
633
  ErrorBoundary,
260
- DisposalScopeError
634
+ EntityStore,
635
+ DisposalScopeError,
636
+ ANIMATION_EASING,
637
+ ANIMATION_DURATION
261
638
  };