@cplieger/ui 0.0.0 → 1.0.0-dev.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 (66) hide show
  1. package/NOTICE +3 -0
  2. package/README.md +145 -2
  3. package/THIRD_PARTY_NOTICES.md +8 -0
  4. package/css/ui-primitives.css +344 -0
  5. package/jsr.json +36 -4
  6. package/package.json +86 -4
  7. package/src/actions/api.ts +268 -0
  8. package/src/actions/async-feedback.ts +217 -0
  9. package/src/actions/cleanup.ts +66 -0
  10. package/src/actions/debounce.ts +150 -0
  11. package/src/actions/define-helpers.ts +87 -0
  12. package/src/actions/define.ts +851 -0
  13. package/src/actions/error.ts +161 -0
  14. package/src/actions/index.ts +60 -0
  15. package/src/actions/loading.ts +131 -0
  16. package/src/actions/notifier.ts +61 -0
  17. package/src/actions/poll-until.ts +133 -0
  18. package/src/actions/poll.ts +156 -0
  19. package/src/actions/registry.ts +259 -0
  20. package/src/actions/retry.ts +79 -0
  21. package/src/actions/testing.ts +29 -0
  22. package/src/actions/transport.ts +104 -0
  23. package/src/actions/types.ts +249 -0
  24. package/src/dom/bind-list.ts +103 -0
  25. package/src/dom/el.ts +67 -0
  26. package/src/dom/index.ts +9 -0
  27. package/src/dom/reconcile-tree.ts +268 -0
  28. package/src/dom/reconcile.ts +76 -0
  29. package/src/fetch/index.ts +18 -0
  30. package/src/fetch/instance.ts +37 -0
  31. package/src/fetch/request.ts +437 -0
  32. package/src/fetch/timeout.ts +67 -0
  33. package/src/fetch/types.ts +206 -0
  34. package/src/fetch/verbs.ts +103 -0
  35. package/src/index.ts +4 -8
  36. package/src/primitives/announce.ts +134 -0
  37. package/src/primitives/ask.ts +406 -0
  38. package/src/primitives/dialog-engine.ts +500 -0
  39. package/src/primitives/dialog.ts +263 -0
  40. package/src/primitives/disclosure.ts +287 -0
  41. package/src/primitives/focus-trap.ts +157 -0
  42. package/src/primitives/fx.ts +204 -0
  43. package/src/primitives/live-regions.ts +83 -0
  44. package/src/primitives/modal-host.ts +214 -0
  45. package/src/primitives/modal.ts +247 -0
  46. package/src/primitives/owner.ts +322 -0
  47. package/src/primitives/popover.ts +500 -0
  48. package/src/primitives/popup-core.ts +603 -0
  49. package/src/primitives/popup.ts +23 -0
  50. package/src/primitives/roving-focus.ts +198 -0
  51. package/src/primitives/scroll-lock.ts +119 -0
  52. package/src/primitives/skeleton.ts +142 -0
  53. package/src/primitives/theme.ts +202 -0
  54. package/src/primitives/toast/engine.ts +327 -0
  55. package/src/primitives/toast/index.ts +139 -0
  56. package/src/primitives/toast/view.ts +244 -0
  57. package/src/primitives/tooltip.ts +377 -0
  58. package/src/primitives/transition.ts +119 -0
  59. package/src/primitives/view-transition.ts +57 -0
  60. package/src/signal/bus.ts +126 -0
  61. package/src/signal/collection.ts +182 -0
  62. package/src/signal/index.ts +34 -0
  63. package/src/signal/resource.ts +102 -0
  64. package/src/signal/signal-map.ts +46 -0
  65. package/src/signal/signal.ts +1002 -0
  66. package/src/signal/store.ts +84 -0
@@ -0,0 +1,84 @@
1
+ // Typed per-key store: a facade over the signal engine with one lazily-created
2
+ // signal per key, and no reactivity of its own.
3
+ //
4
+ // A Store member exists only where it does something the engine's namesake
5
+ // does not: `subscribe` skips the initial call and runs untracked, `computed`
6
+ // is an eager key-writing effect. `batch` and `effect` stay off the store,
7
+ // because `store.batch(…)` reads as store-scoped while it batches the whole
8
+ // graph, a scope the flush model does not have.
9
+
10
+ import { signal, effect, untracked, type Signal } from "./signal.js";
11
+
12
+ /** A typed per-key reactive store: lazily signal-backed keys, change-only
13
+ * subscriptions, and eager derived keys. Effects and batching are the engine's
14
+ * own `effect` / `batch`, imported from the package root. */
15
+ export interface Store<M> {
16
+ get<K extends keyof M & string>(key: K): M[K];
17
+ set<K extends keyof M & string>(key: K, value: M[K]): void;
18
+ subscribe<K extends keyof M & string>(key: K, cb: (value: M[K]) => void): () => void;
19
+ /** Derive `outputKey` from other keys. NOT a lazy engine `computed`: this is
20
+ * an EAGER effect that re-runs `fn` on dependency change and WRITES the
21
+ * result to `outputKey`. Consequences of that shape: `fn` runs whether or
22
+ * not anyone reads `outputKey`; a throwing `fn` is isolated by the effect
23
+ * error handler (not cached and rethrown at the read site like an engine
24
+ * computed); `set(outputKey, …)` still works between recomputes; and a
25
+ * self-reading `fn` behaves as documented on the implementation below.
26
+ * Returns the effect's dispose function. */
27
+ computed<K extends keyof M & string>(outputKey: K, fn: () => M[K]): () => void;
28
+ }
29
+
30
+ /** Create a typed reactive store. Keys are lazily backed by signals; reading a
31
+ * key inside an effect auto-tracks it, and writes notify through the engine. */
32
+ export function createStore<M>(): Store<M> {
33
+ const sigs = new Map<string, Signal<unknown>>();
34
+
35
+ function sigFor<K extends keyof M & string>(key: K): Signal<M[K]> {
36
+ let s = sigs.get(key);
37
+ if (s === undefined) {
38
+ // Unset keys read as `undefined` (matching a sparse record) until first set.
39
+ s = signal<unknown>(undefined);
40
+ sigs.set(key, s);
41
+ }
42
+ return s as Signal<M[K]>;
43
+ }
44
+
45
+ function get<K extends keyof M & string>(key: K): M[K] {
46
+ return sigFor(key).value;
47
+ }
48
+
49
+ function set<K extends keyof M & string>(key: K, value: M[K]): void {
50
+ sigFor(key).value = value;
51
+ }
52
+
53
+ // Notify on change only (not immediately on subscribe) — the engine's
54
+ // `subscribe` fires immediately, so skip the initial effect run.
55
+ function subscribe<K extends keyof M & string>(key: K, cb: (value: M[K]) => void): () => void {
56
+ const s = sigFor(key);
57
+ let primed = false;
58
+ return effect(() => {
59
+ const v = s.value;
60
+ if (!primed) {
61
+ primed = true;
62
+ return;
63
+ }
64
+ // Untracked, mirroring the engine's `subscribe`: a callback that reads
65
+ // other keys must not become a dependency of this subscription.
66
+ untracked(() => {
67
+ cb(v);
68
+ });
69
+ });
70
+ }
71
+
72
+ // A derived key: an effect that writes `outputKey` from `fn`. A `fn` that reads
73
+ // `outputKey` and yields a new value each run trips the engine's batch-iteration
74
+ // guard after ~100 re-runs, surfacing Error("Cycle detected") through the effect
75
+ // error handler (effects isolate errors, so it is NOT rethrown to the caller); a
76
+ // self-read that returns a stable value settles via Object.is dedup without looping.
77
+ function computed<K extends keyof M & string>(outputKey: K, fn: () => M[K]): () => void {
78
+ return effect(() => {
79
+ set(outputKey, fn());
80
+ });
81
+ }
82
+
83
+ return { get, set, subscribe, computed };
84
+ }