@cplieger/ui 0.0.0-stage → 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 (67) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +3 -0
  3. package/README.md +157 -2
  4. package/THIRD_PARTY_NOTICES.md +8 -0
  5. package/css/ui-primitives.css +344 -0
  6. package/jsr.json +44 -0
  7. package/package.json +105 -4
  8. package/src/actions/api.ts +268 -0
  9. package/src/actions/async-feedback.ts +217 -0
  10. package/src/actions/cleanup.ts +66 -0
  11. package/src/actions/debounce.ts +150 -0
  12. package/src/actions/define-helpers.ts +87 -0
  13. package/src/actions/define.ts +851 -0
  14. package/src/actions/error.ts +161 -0
  15. package/src/actions/index.ts +60 -0
  16. package/src/actions/loading.ts +131 -0
  17. package/src/actions/notifier.ts +61 -0
  18. package/src/actions/poll-until.ts +133 -0
  19. package/src/actions/poll.ts +156 -0
  20. package/src/actions/registry.ts +259 -0
  21. package/src/actions/retry.ts +79 -0
  22. package/src/actions/testing.ts +29 -0
  23. package/src/actions/transport.ts +104 -0
  24. package/src/actions/types.ts +249 -0
  25. package/src/dom/bind-list.ts +103 -0
  26. package/src/dom/el.ts +67 -0
  27. package/src/dom/index.ts +9 -0
  28. package/src/dom/reconcile-tree.ts +268 -0
  29. package/src/dom/reconcile.ts +76 -0
  30. package/src/fetch/index.ts +18 -0
  31. package/src/fetch/instance.ts +37 -0
  32. package/src/fetch/request.ts +437 -0
  33. package/src/fetch/timeout.ts +67 -0
  34. package/src/fetch/types.ts +206 -0
  35. package/src/fetch/verbs.ts +103 -0
  36. package/src/index.ts +4 -0
  37. package/src/primitives/announce.ts +134 -0
  38. package/src/primitives/ask.ts +406 -0
  39. package/src/primitives/dialog-engine.ts +500 -0
  40. package/src/primitives/dialog.ts +263 -0
  41. package/src/primitives/disclosure.ts +287 -0
  42. package/src/primitives/focus-trap.ts +157 -0
  43. package/src/primitives/fx.ts +204 -0
  44. package/src/primitives/live-regions.ts +83 -0
  45. package/src/primitives/modal-host.ts +214 -0
  46. package/src/primitives/modal.ts +247 -0
  47. package/src/primitives/owner.ts +322 -0
  48. package/src/primitives/popover.ts +500 -0
  49. package/src/primitives/popup-core.ts +603 -0
  50. package/src/primitives/popup.ts +23 -0
  51. package/src/primitives/roving-focus.ts +198 -0
  52. package/src/primitives/scroll-lock.ts +119 -0
  53. package/src/primitives/skeleton.ts +142 -0
  54. package/src/primitives/theme.ts +202 -0
  55. package/src/primitives/toast/engine.ts +327 -0
  56. package/src/primitives/toast/index.ts +139 -0
  57. package/src/primitives/toast/view.ts +244 -0
  58. package/src/primitives/tooltip.ts +377 -0
  59. package/src/primitives/transition.ts +119 -0
  60. package/src/primitives/view-transition.ts +57 -0
  61. package/src/signal/bus.ts +126 -0
  62. package/src/signal/collection.ts +182 -0
  63. package/src/signal/index.ts +34 -0
  64. package/src/signal/resource.ts +102 -0
  65. package/src/signal/signal-map.ts +46 -0
  66. package/src/signal/signal.ts +1002 -0
  67. package/src/signal/store.ts +84 -0
@@ -0,0 +1,87 @@
1
+ import type { NotificationSpec } from "./types.js";
2
+
3
+ /** Errors are caught and logged; never disrupts the dispatch lifecycle. */
4
+ export function safeInvoke(actionName: string, hookName: string, fn: () => void): void {
5
+ try {
6
+ fn();
7
+ } catch (e) {
8
+ console.error(`[actions] ${hookName} callback for ${actionName} threw`, e);
9
+ }
10
+ }
11
+
12
+ // Symbols with the same description are distinct values but String(sym) is
13
+ // identical, so each unique symbol needs its own stable numeric id.
14
+ let _symbolCounter = 0;
15
+ const _symbolMap = new Map<symbol, number>();
16
+ export function symbolId(sym: symbol): number {
17
+ let id = _symbolMap.get(sym);
18
+ if (id === undefined) {
19
+ id = ++_symbolCounter;
20
+ _symbolMap.set(sym, id);
21
+ }
22
+ return id;
23
+ }
24
+
25
+ export function _resetSymbols(): void {
26
+ _symbolCounter = 0;
27
+ _symbolMap.clear();
28
+ }
29
+
30
+ /** Falls back to String(args) on cycles or non-serializable values. */
31
+ export function safeStringify(args: unknown): string {
32
+ if (args === undefined) {
33
+ return "undefined";
34
+ }
35
+ if (args === null || typeof args === "number" || typeof args === "boolean") {
36
+ return String(args);
37
+ }
38
+ if (typeof args === "string") {
39
+ return JSON.stringify(args);
40
+ }
41
+ if (typeof args === "bigint") {
42
+ return `${String(args)}n`;
43
+ }
44
+ if (typeof args === "symbol") {
45
+ return `@@sym${String(symbolId(args))}`;
46
+ }
47
+ try {
48
+ const out = JSON.stringify(args, (_key, value: unknown) =>
49
+ value === undefined ? "__undef__" : value,
50
+ );
51
+ // A bare function makes JSON.stringify return `undefined` rather than throw,
52
+ // so the catch never fires; coerce so distinct functions don't collide on
53
+ // one dedupe key.
54
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string -- intentional fallback for non-serializable values
55
+ return typeof out === "string" ? out : String(args);
56
+ } catch {
57
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string -- intentional fallback for cyclic objects
58
+ return String(args);
59
+ }
60
+ }
61
+
62
+ /** Returns null when spec is `false` (suppressed) or undefined with no fallback. */
63
+ export function resolveNotification<TArgs, TPayload>(
64
+ spec: NotificationSpec<TArgs, TPayload> | undefined,
65
+ args: TArgs,
66
+ payload: TPayload,
67
+ fallback?: string,
68
+ ): string | null {
69
+ if (spec === false) {
70
+ return null;
71
+ }
72
+ if (spec === undefined) {
73
+ return fallback ?? null;
74
+ }
75
+ if (typeof spec === "string") {
76
+ return spec;
77
+ }
78
+ return spec(args, payload);
79
+ }
80
+
81
+ /** "chat.delete" -> "Delete failed". */
82
+ export function defaultErrorPrefix(name: string): string {
83
+ const parts = name.split(".");
84
+ const tail = parts[parts.length - 1] ?? name;
85
+ const readable = tail.replace(/[_-]/g, " ");
86
+ return readable.charAt(0).toUpperCase() + readable.slice(1) + " failed";
87
+ }