@adia-ai/web-components 0.8.44 → 0.8.45

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 (43) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/components/context-menu/context-menu.a2ui.json +8 -3
  3. package/components/context-menu/context-menu.class.js +46 -5
  4. package/components/context-menu/context-menu.d.ts +6 -3
  5. package/components/context-menu/context-menu.examples.md +2 -2
  6. package/components/context-menu/context-menu.yaml +22 -5
  7. package/components/nav/nav.a2ui.json +2 -2
  8. package/components/nav/nav.css +1 -1
  9. package/components/nav/nav.d.ts +1 -1
  10. package/components/nav/nav.yaml +14 -3
  11. package/components/nav-group/nav-group.css +37 -3
  12. package/components/pagination/pagination.class.js +52 -22
  13. package/components/search/search.class.js +39 -5
  14. package/components/select/select.a2ui.json +5 -0
  15. package/components/select/select.class.js +20 -0
  16. package/components/select/select.css +25 -0
  17. package/components/select/select.d.ts +2 -0
  18. package/components/select/select.yaml +12 -0
  19. package/components/table/cell-types.js +9 -0
  20. package/components/table/table.class.js +247 -33
  21. package/components/table/table.css +7 -4
  22. package/components/table/table.yaml +6 -1
  23. package/components/table-toolbar/table-toolbar.a2ui.json +15 -0
  24. package/components/table-toolbar/table-toolbar.class.js +61 -17
  25. package/components/table-toolbar/table-toolbar.css +34 -0
  26. package/components/table-toolbar/table-toolbar.d.ts +10 -0
  27. package/components/table-toolbar/table-toolbar.yaml +41 -9
  28. package/core/data-stream.js +37 -2
  29. package/core/index.d.ts +1 -0
  30. package/core/index.js +1 -0
  31. package/core/provider.d.ts +9 -13
  32. package/core/provider.js +9 -113
  33. package/core/store.d.ts +46 -0
  34. package/core/store.js +89 -0
  35. package/custom-elements.json +54 -4
  36. package/dist/host.min.css +1 -1
  37. package/dist/host.sheet.js +1 -1
  38. package/dist/theme-provider.min.js +1 -1
  39. package/dist/web-components.min.css +1 -1
  40. package/dist/web-components.min.js +93 -93
  41. package/dist/web-components.sheet.js +1 -1
  42. package/package.json +1 -1
  43. package/styles/api/sizing.css +46 -0
package/core/store.js ADDED
@@ -0,0 +1,89 @@
1
+ /**
2
+ * AdiaUI shared app store — the blessed R2 primitive.
3
+ *
4
+ * A signal-backed replacement for the Set-of-listeners pub/sub pattern
5
+ * hand-rolled across the app layer: plan-store, data-client, patient-visit
6
+ * record, persona store, task-service, a2ui BaseController, a2ui Surface
7
+ * watchers (reactivity review, .claude/docs/reports/2026-08-20-reactivity-
8
+ * review/03-app-layer-stores.md §4). Doctrine's pattern menu row 1 says
9
+ * reactive state -> signals; `createStore` is `signal()` plus the one thing
10
+ * those seven stores actually needed on top of it: an imperative
11
+ * `subscribe(cb) -> unsubscribe` channel for consumers that are closures or
12
+ * classes rather than `effect()` bodies.
13
+ *
14
+ * `.value` reads/writes pass straight through to a real `signal()`, so a
15
+ * store composes with `computed()`/`effect()` exactly like any other signal
16
+ * (tracked reads, `Object.is` no-notify, microtask-batched effect re-runs).
17
+ * `subscribe()` is the separate, synchronous, imperative channel the seven
18
+ * hand-rolled stores already share — same shape, so migrating one onto this
19
+ * primitive is a mechanical swap (opportunistic, later, per store; this
20
+ * primitive lands with NO migration).
21
+ *
22
+ * Interops with `UIElement`'s `controller` setter (`core/element.js`)
23
+ * out of the box: `element.controller = store` wires `store.subscribe(fn)`
24
+ * into the element's own render-trigger machinery — the setter calls
25
+ * `c.connect?.(this)` / `c.subscribe?.(...)` / `c.disconnect?.(this)`, all
26
+ * optional-chained, and `subscribe()` alone satisfies that contract.
27
+ *
28
+ * Rejected alternative: promoting/absorbing `BaseController`
29
+ * (`core/controller.js`) into this role, per the reactivity review's F5.
30
+ * BaseController's `connect()` bakes in schema/`getState()` validation
31
+ * (dev-warns without a static `schema`, dev-errors without an overridden
32
+ * `getState()`) that exists to serve DOM-reflecting UI controllers
33
+ * (`RouteController`'s attributes/commands surface) — semantics a plain
34
+ * data store has no use for and would either have to satisfy with a dummy
35
+ * schema or suppress. The one thing BaseController actually offers this
36
+ * role — the `subscribe(fn) -> unsubscribe` shape the controller setter
37
+ * expects — costs nothing to reimplement directly on `signal()`, and doing
38
+ * so keeps the store from inheriting a validation path built for a
39
+ * different kind of thing. BaseController stays as-is; still one consumer
40
+ * (`RouteController` / `<router-ui>`), still F5's to resolve separately.
41
+ *
42
+ * @see ../USAGE.md
43
+ * @see ./element.js (the `controller` setter this interops with)
44
+ * @see ./controller.js (BaseController — the rejected alternative above)
45
+ */
46
+
47
+ import { signal } from './signals.js';
48
+
49
+ export function createStore(initial) {
50
+ const s = signal(initial);
51
+ const listeners = new Set();
52
+
53
+ return {
54
+ get value() {
55
+ return s.value;
56
+ },
57
+ set value(next) {
58
+ // Object.is no-notify guard — matches persona-store's proven
59
+ // behavior (packages/llm/persona/src/store.ts) and the underlying
60
+ // signal's own equality cutoff. Checked here, not inferred from
61
+ // signal()'s silent no-op, so an identical write never reaches
62
+ // `listeners` either.
63
+ const changed = !Object.is(s.peek(), next);
64
+ s.value = next;
65
+ if (changed) {
66
+ // Pass the captured `next`, never re-read `s.peek()` here — a
67
+ // listener that re-entrantly writes `store.value` during this
68
+ // loop would otherwise make every later listener observe THAT
69
+ // write's value instead of this one's, silently skipping the
70
+ // value this write actually delivered.
71
+ for (const cb of listeners) cb(next);
72
+ }
73
+ },
74
+ /** Read without subscribing the surrounding `effect()`. */
75
+ peek() {
76
+ return s.peek();
77
+ },
78
+ /**
79
+ * Set-of-listeners-compatible subscribe. `cb` receives the new value;
80
+ * callers that only care that *something* changed (the
81
+ * `UIElement.controller` setter among them) simply ignore the
82
+ * argument. Returns an unsubscribe function.
83
+ */
84
+ subscribe(cb) {
85
+ listeners.add(cb);
86
+ return () => listeners.delete(cb);
87
+ },
88
+ };
89
+ }
@@ -3271,7 +3271,7 @@
3271
3271
  "declarations": [
3272
3272
  {
3273
3273
  "kind": "class",
3274
- "description": "Right-click activated menu — the OS-native context-menu pattern as a web component. Distinct from `menu-ui` (which is button-triggered): same item shape (`menu-item-ui` children), different trigger surface (`contextmenu` event), and pointer-anchored positioning instead of element-anchored. Pattern: WAI-APG Menu. Two binding modes: **A. Wrap.** Default-slot child becomes the target: `<context-menu-ui><my-table>...</my-table>...items</context-menu-ui>`. **B. Selector.** Point at one or more existing elements via [for]: `<context-menu-ui for=\"#my-table\">...items</context-menu-ui>`. On `contextmenu` event on a target: `preventDefault()`, position the menu at the pointer coords, show via Popover API. Touch long-press (configurable via [long-press-ms]) does the same. Shift+F10 / Menu key opens at the focused target's center for keyboard users.",
3274
+ "description": "Right-click activated menu — the OS-native context-menu pattern as a web component. Distinct from `menu-ui` (which is button-triggered): same item shape (`menu-item-ui` children), different trigger surface (`contextmenu` event), and pointer-anchored positioning instead of element-anchored. Pattern: WAI-APG Menu. Two binding modes: **A. Wrap.** Default-slot child becomes the target: `<context-menu-ui><my-table>...</my-table>...items</context-menu-ui>`. **B. Selector.** Point at one or more existing elements via [target-selector]: `<context-menu-ui target-selector=\"#my-table\">...items</context-menu-ui>`. On `contextmenu` event on a target: `preventDefault()`, position the menu at the pointer coords, show via Popover API. Touch long-press (configurable via [long-press-ms]) does the same. Shift+F10 / Menu key opens at the focused target's center for keyboard users.",
3275
3275
  "name": "UIContextMenu",
3276
3276
  "tagName": "context-menu-ui",
3277
3277
  "superclass": {
@@ -3279,12 +3279,19 @@
3279
3279
  "module": "/core/element.js"
3280
3280
  },
3281
3281
  "attributes": [
3282
+ {
3283
+ "name": "target-selector",
3284
+ "type": {
3285
+ "text": "string"
3286
+ },
3287
+ "description": "CSS selector(s) for target element(s). Empty = use default-slot child. Ratified name (gh#1764/#1780, ADR-0079) for what [for] used to carry — [for] means an id-ref everywhere else in AdiaUI (table-toolbar-ui, chart-legend-ui, tooltip-ui); context-menu-ui's own selector meaning predates that convention and was a same-name/ different-contract collision (ADR-0053's no-shadowing doctrine)."
3288
+ },
3282
3289
  {
3283
3290
  "name": "for",
3284
3291
  "type": {
3285
3292
  "text": "string"
3286
3293
  },
3287
- "description": "CSS selector(s) for target element(s). Empty = use default-slot child."
3294
+ "description": "DEPRECATED alias for [target-selector] — still a CSS selector, NOT an id-ref. Honored when [target-selector] is unset, with a one-shot console.warn pointing consumers at the replacement. New authoring should use [target-selector]."
3288
3295
  },
3289
3296
  {
3290
3297
  "name": "open",
@@ -6519,7 +6526,7 @@
6519
6526
  "type": {
6520
6527
  "text": "string"
6521
6528
  },
6522
- "description": "Optional kicker label. Section variant renders it via ::before; primary uses it as aria-label only."
6529
+ "description": "Optional kicker label. Section variant renders it via ::before; primary uses it as aria-label only. For a VISIBLE kicker inside a primary-variant rail — or more than one kicker per <nav-ui> — hand-place <span data-nav-label> in the default slot instead; see slots below."
6523
6530
  },
6524
6531
  {
6525
6532
  "name": "multi-expand",
@@ -6533,7 +6540,7 @@
6533
6540
  "slots": [
6534
6541
  {
6535
6542
  "name": "default",
6536
- "description": "Primary slot — accepts <nav-group-ui> + <nav-item-ui> children, plus <hr data-nav-divider> for hand-placed dividers."
6543
+ "description": "Primary slot — accepts <nav-group-ui> + <nav-item-ui> children, plus <hr data-nav-divider> for hand-placed dividers and <span data-nav-label> for hand-placed group-label kickers (titled runs of items/groups that aren't wrapped in a <nav-group-ui>). <span data-nav-label> renders with the same uppercase/tracking/muted kicker treatment as the [heading] ::before kicker, and is hidden alongside dividers whenever the primary-variant rail collapses ([collapsed] or ≤96px container width)."
6537
6544
  }
6538
6545
  ],
6539
6546
  "events": [
@@ -8566,6 +8573,14 @@
8566
8573
  },
8567
8574
  "description": "Label text above the trigger"
8568
8575
  },
8576
+ {
8577
+ "name": "label-hidden",
8578
+ "type": {
8579
+ "text": "boolean"
8580
+ },
8581
+ "default": "false",
8582
+ "description": "When true, [label] still sets the accessible name (aria-label) but the visible `::before` text is suppressed via the canonical sr-only technique (gh#1748, mirrors check-ui's [label-hidden], gh#1010). Use when a sibling/ancestor composition already conveys the same name visually (e.g. a scope/view-switcher select in a table-toolbar-ui [slot=\"scope\"], where the toolbar's own title already names the view) and a second visible \"Scope\"-style label would paint it twice."
8583
+ },
8569
8584
  {
8570
8585
  "name": "hint",
8571
8586
  "type": {
@@ -10089,6 +10104,41 @@
10089
10104
  "text": "CustomEvent"
10090
10105
  },
10091
10106
  "description": "Page-size select changed. Detail: { pageSize }."
10107
+ },
10108
+ {
10109
+ "name": "toolbar-search",
10110
+ "type": {
10111
+ "text": "CustomEvent"
10112
+ },
10113
+ "description": "gh#1764/#1780, ADR-0079 (events-only interaction contract) — dispatched directly at the resolved [for] target (not bubbled from this element) in place of the pre-#1780 direct `.search =` write. table-ui listens for this on itself. Detail: { value }."
10114
+ },
10115
+ {
10116
+ "name": "toolbar-filter-set",
10117
+ "type": {
10118
+ "text": "CustomEvent"
10119
+ },
10120
+ "description": "gh#1764/#1780, ADR-0079 — dispatched directly at the resolved [for] target in place of the pre-#1780 direct `target.setFilter()` call. table-ui listens for this on itself. Detail: { key, value, op }; a null `value` clears that one column's filter."
10121
+ },
10122
+ {
10123
+ "name": "toolbar-filter-clear",
10124
+ "type": {
10125
+ "text": "CustomEvent"
10126
+ },
10127
+ "description": "gh#1764/#1780, ADR-0079 — dispatched directly at the resolved [for] target in place of the pre-#1780 direct `target.clearFilters()` call. table-ui listens for this on itself. No detail."
10128
+ },
10129
+ {
10130
+ "name": "toolbar-columns-set",
10131
+ "type": {
10132
+ "text": "CustomEvent"
10133
+ },
10134
+ "description": "gh#1764/#1780, ADR-0079 — dispatched directly at the resolved [for] target in place of the pre-#1780 direct `target.columns =` write. table-ui listens for this on itself. Detail: { columns }."
10135
+ },
10136
+ {
10137
+ "name": "toolbar-paginate",
10138
+ "type": {
10139
+ "text": "CustomEvent"
10140
+ },
10141
+ "description": "gh#1764/#1780, ADR-0079 — dispatched directly at the resolved [for] target in place of the pre-#1780 direct `target.paginate =` write. table-ui listens for this on itself. Detail: { pageSize }."
10092
10142
  }
10093
10143
  ]
10094
10144
  }