@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.
- package/NOTICE +3 -0
- package/README.md +145 -2
- package/THIRD_PARTY_NOTICES.md +8 -0
- package/css/ui-primitives.css +344 -0
- package/jsr.json +36 -4
- package/package.json +86 -4
- package/src/actions/api.ts +268 -0
- package/src/actions/async-feedback.ts +217 -0
- package/src/actions/cleanup.ts +66 -0
- package/src/actions/debounce.ts +150 -0
- package/src/actions/define-helpers.ts +87 -0
- package/src/actions/define.ts +851 -0
- package/src/actions/error.ts +161 -0
- package/src/actions/index.ts +60 -0
- package/src/actions/loading.ts +131 -0
- package/src/actions/notifier.ts +61 -0
- package/src/actions/poll-until.ts +133 -0
- package/src/actions/poll.ts +156 -0
- package/src/actions/registry.ts +259 -0
- package/src/actions/retry.ts +79 -0
- package/src/actions/testing.ts +29 -0
- package/src/actions/transport.ts +104 -0
- package/src/actions/types.ts +249 -0
- package/src/dom/bind-list.ts +103 -0
- package/src/dom/el.ts +67 -0
- package/src/dom/index.ts +9 -0
- package/src/dom/reconcile-tree.ts +268 -0
- package/src/dom/reconcile.ts +76 -0
- package/src/fetch/index.ts +18 -0
- package/src/fetch/instance.ts +37 -0
- package/src/fetch/request.ts +437 -0
- package/src/fetch/timeout.ts +67 -0
- package/src/fetch/types.ts +206 -0
- package/src/fetch/verbs.ts +103 -0
- package/src/index.ts +4 -8
- package/src/primitives/announce.ts +134 -0
- package/src/primitives/ask.ts +406 -0
- package/src/primitives/dialog-engine.ts +500 -0
- package/src/primitives/dialog.ts +263 -0
- package/src/primitives/disclosure.ts +287 -0
- package/src/primitives/focus-trap.ts +157 -0
- package/src/primitives/fx.ts +204 -0
- package/src/primitives/live-regions.ts +83 -0
- package/src/primitives/modal-host.ts +214 -0
- package/src/primitives/modal.ts +247 -0
- package/src/primitives/owner.ts +322 -0
- package/src/primitives/popover.ts +500 -0
- package/src/primitives/popup-core.ts +603 -0
- package/src/primitives/popup.ts +23 -0
- package/src/primitives/roving-focus.ts +198 -0
- package/src/primitives/scroll-lock.ts +119 -0
- package/src/primitives/skeleton.ts +142 -0
- package/src/primitives/theme.ts +202 -0
- package/src/primitives/toast/engine.ts +327 -0
- package/src/primitives/toast/index.ts +139 -0
- package/src/primitives/toast/view.ts +244 -0
- package/src/primitives/tooltip.ts +377 -0
- package/src/primitives/transition.ts +119 -0
- package/src/primitives/view-transition.ts +57 -0
- package/src/signal/bus.ts +126 -0
- package/src/signal/collection.ts +182 -0
- package/src/signal/index.ts +34 -0
- package/src/signal/resource.ts +102 -0
- package/src/signal/signal-map.ts +46 -0
- package/src/signal/signal.ts +1002 -0
- 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
|
+
}
|