@adia-ai/web-modules 0.8.36 → 0.8.37

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 (89) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +3 -3
  3. package/agent-admin/admin-roster/admin-roster.js +1 -1
  4. package/agent-admin/admin-settings/admin-settings.js +1 -1
  5. package/agent-admin/agent-admin/agent-admin.js +1 -1
  6. package/billing/billing-overview/billing-overview.a2ui.json +281 -0
  7. package/billing/billing-overview/billing-overview.class.js +838 -0
  8. package/billing/billing-overview/billing-overview.css +223 -0
  9. package/billing/billing-overview/billing-overview.js +16 -0
  10. package/billing/billing-overview/billing-overview.yaml +441 -0
  11. package/billing/index.js +21 -0
  12. package/billing/invoice-detail/invoice-detail.a2ui.json +276 -0
  13. package/billing/invoice-detail/invoice-detail.class.js +711 -0
  14. package/billing/invoice-detail/invoice-detail.css +305 -0
  15. package/billing/invoice-detail/invoice-detail.js +16 -0
  16. package/billing/invoice-detail/invoice-detail.yaml +411 -0
  17. package/billing/invoice-history/invoice-history.a2ui.json +315 -0
  18. package/billing/invoice-history/invoice-history.class.js +672 -0
  19. package/billing/invoice-history/invoice-history.css +130 -0
  20. package/billing/invoice-history/invoice-history.js +16 -0
  21. package/billing/invoice-history/invoice-history.yaml +398 -0
  22. package/billing/payment-method-form/payment-method-form.a2ui.json +310 -0
  23. package/billing/payment-method-form/payment-method-form.class.js +886 -0
  24. package/billing/payment-method-form/payment-method-form.css +149 -0
  25. package/billing/payment-method-form/payment-method-form.js +16 -0
  26. package/billing/payment-method-form/payment-method-form.yaml +430 -0
  27. package/billing/payment-method-list/payment-method-list.a2ui.json +283 -0
  28. package/billing/payment-method-list/payment-method-list.class.js +705 -0
  29. package/billing/payment-method-list/payment-method-list.css +128 -0
  30. package/billing/payment-method-list/payment-method-list.js +16 -0
  31. package/billing/payment-method-list/payment-method-list.yaml +355 -0
  32. package/billing/plan-picker/plan-picker.a2ui.json +349 -0
  33. package/billing/plan-picker/plan-picker.class.js +635 -0
  34. package/billing/plan-picker/plan-picker.css +227 -0
  35. package/billing/plan-picker/plan-picker.js +16 -0
  36. package/billing/plan-picker/plan-picker.yaml +453 -0
  37. package/chat/README.md +1 -1
  38. package/chat/chat-composer/chat-composer.js +2 -2
  39. package/chat/chat-empty/chat-empty.js +2 -2
  40. package/chat/chat-shell/chat-shell.js +4 -4
  41. package/chat/chat-sidebar/chat-sidebar.js +2 -2
  42. package/chat/chat-surfaces/chat-surfaces.js +2 -2
  43. package/chat/chat-thread/chat-thread.js +2 -2
  44. package/dashboard/dashboard-layout/dashboard-layout.a2ui.json +254 -0
  45. package/dashboard/dashboard-layout/dashboard-layout.css +190 -0
  46. package/dashboard/dashboard-layout/dashboard-layout.js +289 -0
  47. package/dashboard/dashboard-layout/dashboard-layout.yaml +374 -0
  48. package/dashboard/date-range-selector/date-range-selector.a2ui.json +236 -0
  49. package/dashboard/date-range-selector/date-range-selector.css +84 -0
  50. package/dashboard/date-range-selector/date-range-selector.js +686 -0
  51. package/dashboard/date-range-selector/date-range-selector.yaml +358 -0
  52. package/dashboard/index.js +14 -0
  53. package/dist/everything.min.js +1 -1
  54. package/editor/editor-canvas/editor-canvas.js +2 -2
  55. package/editor/editor-shell/editor-shell.js +2 -2
  56. package/editor/editor-sidebar/editor-sidebar.js +2 -2
  57. package/editor/editor-toolbar/editor-toolbar.js +2 -2
  58. package/feedback/confirm-dialog/confirm-dialog.a2ui.json +206 -0
  59. package/feedback/confirm-dialog/confirm-dialog.css +157 -0
  60. package/feedback/confirm-dialog/confirm-dialog.js +383 -0
  61. package/feedback/confirm-dialog/confirm-dialog.yaml +297 -0
  62. package/feedback/index.js +10 -0
  63. package/form/form-popover/form-popover.js +1 -1
  64. package/generative/index.d.ts +1 -1
  65. package/generative/index.js +2 -2
  66. package/onboarding/index.js +1 -0
  67. package/onboarding/onboarding-checklist/onboarding-checklist.a2ui.json +263 -0
  68. package/onboarding/onboarding-checklist/onboarding-checklist.css +157 -0
  69. package/onboarding/onboarding-checklist/onboarding-checklist.js +428 -0
  70. package/onboarding/onboarding-checklist/onboarding-checklist.yaml +236 -0
  71. package/package.json +99 -6
  72. package/runtime/a2ui-root/a2ui-root.js +3 -3
  73. package/runtime/gen-root/gen-root.js +5 -5
  74. package/settings/index.js +12 -0
  75. package/settings/integrations-page/integrations-page.a2ui.json +274 -0
  76. package/settings/integrations-page/integrations-page.css +177 -0
  77. package/settings/integrations-page/integrations-page.d.ts +77 -0
  78. package/settings/integrations-page/integrations-page.js +413 -0
  79. package/settings/integrations-page/integrations-page.yaml +317 -0
  80. package/settings/notification-preferences/notification-preferences.a2ui.json +245 -0
  81. package/settings/notification-preferences/notification-preferences.css +204 -0
  82. package/settings/notification-preferences/notification-preferences.js +622 -0
  83. package/settings/notification-preferences/notification-preferences.yaml +358 -0
  84. package/shell/admin-command/admin-command.js +2 -2
  85. package/shell/admin-shell/admin-shell.js +2 -2
  86. package/shell/admin-sidebar/admin-sidebar.js +2 -2
  87. package/shell/embed-shell/embed-shell.js +3 -3
  88. package/simple/simple-shell/simple-shell.js +1 -1
  89. package/theme/theme-panel/theme-panel.js +2 -2
@@ -0,0 +1,227 @@
1
+ /* ═══════════════════════════════════════════════════════════════
2
+ <plan-picker-ui> — Form-participating chooser of one of N plans.
3
+
4
+ Composite over <option-card-ui> + <segmented-ui> + <segment-ui> +
5
+ <tag-ui> + <button-ui> + <icon-ui> + <empty-state-ui>. The host is
6
+ a column that lays out the toggle row · plans grid · skeleton ·
7
+ empty-state regions in DOM order. Each plan card is an
8
+ <option-card-ui> decorated with a price block, feature list, and
9
+ CTA via per-region L3 tokens.
10
+
11
+ SPEC: docs/specs/implementation-ready/SPEC-011-plan-picker-in-app-upgrade.md
12
+ Two-block @scope pattern per docs/specs/component-token-contract.md.
13
+ Zero raw color values (repo hard rule); zero raw px ≥ 3 (rem only).
14
+ ═══════════════════════════════════════════════════════════════ */
15
+
16
+ /* ── Block 1: TOKEN DECLARATIONS ───────────────────────────────── */
17
+
18
+ plan-picker-ui {
19
+ --plan-picker-bg: transparent;
20
+ --plan-picker-grid-gap: var(--a-space-4);
21
+ --plan-picker-grid-min: 16rem;
22
+
23
+ --plan-picker-card-bg: var(--md-sys-color-neutral-background);
24
+ --plan-picker-card-bg-recommended: var(--md-sys-color-primary-container);
25
+ --plan-picker-card-bg-current: var(--a-bg-muted);
26
+ --plan-picker-card-border: 1px solid var(--md-sys-color-neutral-outline);
27
+ --plan-picker-card-border-recommended: 2px solid var(--md-sys-color-primary);
28
+ --plan-picker-card-radius: var(--a-radius-lg);
29
+ --plan-picker-card-py: var(--a-space-5);
30
+ --plan-picker-card-px: var(--a-space-5);
31
+ --plan-picker-card-shadow-recommended: var(--a-shadow-md);
32
+
33
+ --plan-picker-price-size: var(--a-text-3xl, 1.875rem);
34
+ --plan-picker-price-fg: var(--a-fg-strong, var(--md-sys-color-neutral-on-surface));
35
+ --plan-picker-cycle-fg: var(--a-fg-muted);
36
+
37
+ --plan-picker-features-gap: var(--a-space-2);
38
+ --plan-picker-feature-icon-fg: var(--md-sys-color-primary);
39
+
40
+ --plan-picker-toggle-justify: center;
41
+
42
+ --plan-picker-disabled-opacity: var(--a-opacity-disabled, 0.5);
43
+ }
44
+
45
+ /* ── Block 2: SCOPED LAYOUT ────────────────────────────────────── */
46
+
47
+ @scope (plan-picker-ui) {
48
+
49
+ :scope {
50
+ display: flex;
51
+ flex-direction: column;
52
+ gap: var(--a-space-4);
53
+ background: var(--plan-picker-bg);
54
+ }
55
+
56
+ /* ── Toggle row ── */
57
+ :scope > [data-toggle] {
58
+ display: flex;
59
+ justify-content: var(--plan-picker-toggle-justify);
60
+ }
61
+ :scope > [data-toggle][hidden] {
62
+ display: none;
63
+ }
64
+
65
+ /* ── Plans grid ── */
66
+ :scope > [data-plans] {
67
+ display: grid;
68
+ grid-template-columns: repeat(
69
+ auto-fit,
70
+ minmax(var(--plan-picker-grid-min), 1fr)
71
+ );
72
+ gap: var(--plan-picker-grid-gap);
73
+ align-items: stretch;
74
+ }
75
+
76
+ /* List layout — single-column rows for in-app settings. */
77
+ :scope[layout="list"] > [data-plans] {
78
+ grid-template-columns: 1fr;
79
+ }
80
+
81
+ /* ── Per-card cascades into option-card-ui L3 tokens ── */
82
+ :scope > [data-plans] > option-card-ui {
83
+ --option-card-bg: var(--plan-picker-card-bg);
84
+ --option-card-border: var(--plan-picker-card-border);
85
+ --option-card-radius: var(--plan-picker-card-radius);
86
+ --option-card-padding-block: var(--plan-picker-card-py);
87
+ --option-card-padding-inline: var(--plan-picker-card-px);
88
+ box-sizing: border-box;
89
+ /* Equal-height cards across the auto-fit row (the grid sets
90
+ align-items:stretch); option-card[layout="tile"] supplies the flex
91
+ column, so we must NOT override its display here — doing so strands
92
+ the radio indicator in a collapsed 8px grid gutter. */
93
+ height: 100%;
94
+ }
95
+
96
+ :scope > [data-plans] > option-card-ui[data-recommended] {
97
+ --option-card-bg: var(--plan-picker-card-bg-recommended);
98
+ --option-card-border: var(--plan-picker-card-border-recommended);
99
+ box-shadow: var(--plan-picker-card-shadow-recommended);
100
+ }
101
+
102
+ :scope > [data-plans] > option-card-ui[data-current] {
103
+ --option-card-bg: var(--plan-picker-card-bg-current);
104
+ }
105
+
106
+ /* ── Plan body — price + features + CTA, REVEALED ALWAYS.
107
+ option-card-ui hides default-slot children unless [checked],
108
+ but plan cards must show their content regardless. We override
109
+ with the same `:not([slot])` selector option-card uses
110
+ internally, scoped to our [data-plan-body] children. flex:1 lets
111
+ the body absorb the card's free height so the CTA (margin-top:auto
112
+ below) anchors to the bottom edge — CTAs align across a row of
113
+ cards with uneven feature lists. ── */
114
+ :scope > [data-plans] > option-card-ui > [data-plan-body] {
115
+ flex: 1;
116
+ display: flex !important;
117
+ flex-direction: column;
118
+ gap: var(--a-space-3);
119
+ }
120
+
121
+ /* Recommended / current pill — a standalone tag at the card's top-left
122
+ (the tile radio sits top-right). order:0 default keeps it ahead of the
123
+ order:2 heading regardless of DOM position. */
124
+ :scope > [data-plans] > option-card-ui > [data-plan-tags] {
125
+ display: flex;
126
+ align-self: start;
127
+ align-items: center;
128
+ gap: var(--a-space-1);
129
+ }
130
+ :scope > [data-plans] > option-card-ui > [data-plan-tags]:empty {
131
+ display: none;
132
+ }
133
+
134
+ /* ── Price row ── */
135
+ :scope [data-price-row] {
136
+ display: flex;
137
+ align-items: baseline;
138
+ gap: var(--a-space-1);
139
+ }
140
+ :scope [data-price] {
141
+ font-size: var(--plan-picker-price-size);
142
+ color: var(--plan-picker-price-fg);
143
+ font-weight: var(--a-weight-bold, 700);
144
+ line-height: 1;
145
+ }
146
+ :scope [data-cycle] {
147
+ font-size: var(--a-text-sm, 0.875rem);
148
+ color: var(--plan-picker-cycle-fg);
149
+ }
150
+ :scope [data-price-note] {
151
+ font-size: var(--a-text-xs, 0.75rem);
152
+ color: var(--plan-picker-cycle-fg);
153
+ }
154
+
155
+ /* ── Features list ── */
156
+ :scope ul[data-features] {
157
+ list-style: none;
158
+ margin: 0;
159
+ padding: 0;
160
+ display: flex;
161
+ flex-direction: column;
162
+ gap: var(--plan-picker-features-gap);
163
+ }
164
+ :scope ul[data-features] > li {
165
+ display: flex;
166
+ align-items: flex-start;
167
+ gap: var(--a-space-2);
168
+ /* Override the docs feature-list indent (site.css adds
169
+ `padding-left: 24px` + a ::before checkmark to ul[data-features] li);
170
+ the slotted <icon-ui> IS our bullet, so the row aligns flush-left. */
171
+ padding-inline-start: 0;
172
+ color: var(--md-sys-color-neutral-on-surface);
173
+ font-size: var(--a-text-sm, 0.875rem);
174
+ line-height: 1.4;
175
+ }
176
+ :scope ul[data-features] > li > icon-ui {
177
+ flex-shrink: 0;
178
+ color: var(--plan-picker-feature-icon-fg);
179
+ --a-icon-size: 1rem;
180
+ margin-block-start: 0.125rem;
181
+ }
182
+ /* The feature check is the slotted <icon-ui>. Suppress any inherited
183
+ ::before checkmark (the docs admin-page feature-list style adds a green
184
+ "✓" to every ul[data-features] li) so the bullet doesn't double up. */
185
+ :scope ul[data-features] > li::before {
186
+ content: none;
187
+ }
188
+
189
+ /* ── CTA button — full-width, anchored to the body's bottom edge so a
190
+ row of cards keeps their CTAs aligned regardless of feature count. ── */
191
+ :scope button-ui[data-cta] {
192
+ width: 100%;
193
+ margin-block-start: auto;
194
+ }
195
+
196
+ /* ── Empty state ── gated by [empty] attribute.
197
+ Hide [data-empty] when host is NOT empty; do NOT set a display
198
+ value when shown (would clobber empty-state-ui's flex layout). */
199
+ :scope:not([empty]) > [data-empty] {
200
+ display: none;
201
+ }
202
+ :scope[empty] > [data-plans] {
203
+ display: none;
204
+ }
205
+
206
+ /* ── Loading skeleton ── */
207
+ :scope > [data-skeleton] {
208
+ display: none;
209
+ }
210
+ :scope[loading] > [data-skeleton] {
211
+ display: grid;
212
+ grid-template-columns: repeat(
213
+ auto-fit,
214
+ minmax(var(--plan-picker-grid-min), 1fr)
215
+ );
216
+ gap: var(--plan-picker-grid-gap);
217
+ }
218
+ :scope[loading] > [data-plans] {
219
+ visibility: hidden;
220
+ }
221
+
222
+ /* ── Disabled state ── */
223
+ :scope[disabled] {
224
+ opacity: var(--plan-picker-disabled-opacity);
225
+ pointer-events: none;
226
+ }
227
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `<plan-picker-ui>` — auto-registers the tag on import.
3
+ *
4
+ * For a non-side-effect class import (test isolation, tag override),
5
+ * use the class export from `./plan-picker.class.js`:
6
+ *
7
+ * import { PlanPicker } from '@adia-ai/web-modules/billing/plan-picker/class';
8
+ */
9
+
10
+ import { PlanPicker } from './plan-picker.class.js';
11
+
12
+ if (!customElements.get('plan-picker-ui')) {
13
+ customElements.define('plan-picker-ui', PlanPicker);
14
+ }
15
+
16
+ export { PlanPicker };
@@ -0,0 +1,453 @@
1
+ # Edit this file; run `npm run build:components` to regenerate a2ui.json.
2
+ $schema: ../../../../scripts/schemas/component.yaml.schema.json
3
+ name: PlanPicker
4
+ tag: plan-picker-ui
5
+ status: experimental
6
+ component: PlanPicker
7
+ category: input
8
+ version: 1
9
+ description: |
10
+ A form-participating chooser of one of N billing plans. The canonical
11
+ plan-card grid used by both in-app upgrade modals and marketing
12
+ pricing pages (SPEC-012 composes this primitive as its core), so
13
+ benefit copy, pricing strings, recommendation highlighting, and the
14
+ billing-cycle toggle never drift between surfaces.
15
+
16
+ Each plan record carries a stable id, name, optional tagline + icon,
17
+ a per-cycle price object, a feature list, and optional flags
18
+ (recommended, rank, disabled). One plan may carry recommended:true
19
+ (accent border + tinted bg + shadow); a host-level `current` id
20
+ marks the user's current plan (muted bg, "Current plan" tag, no
21
+ Choose CTA, contextual "Upgrade"/"Downgrade" labels on siblings).
22
+
23
+ Layout is grid by default (marketing surfaces) and `layout="list"`
24
+ for in-app settings panels. The optional `cycle-toggle` boolean
25
+ renders an internal <segmented-ui> that swaps prices between
26
+ monthly and annual cycles in place across every card.
27
+
28
+ Spec: .claude/docs/specs/implementation-ready/SPEC-011-plan-picker-in-app-upgrade.md.
29
+
30
+ # Per ADR-0027 — composites do NOT auto-import the primitives they
31
+ # stamp in connected()/render(). The consumer (or this primitive's
32
+ # .html demo shell) must explicitly side-effect-import each one.
33
+ composes:
34
+ - option-card-ui
35
+ - segmented-ui
36
+ - segment-ui
37
+ - button-ui
38
+ - icon-ui
39
+ - text-ui
40
+ - tag-ui
41
+ - empty-state-ui
42
+
43
+ props:
44
+ plans:
45
+ description: |
46
+ Array of plan records. Source of truth for the rendered cards.
47
+ Shape per record: {id, name, tagline?, prices: {monthly: {amount,
48
+ currency?, unit?, note?}, annual?: {...}}, features?: string[],
49
+ cta?: string, recommended?: boolean, rank?: number, icon?: string,
50
+ disabled?: boolean}. Empty array renders the empty-state.
51
+ type: array
52
+ default: []
53
+ dynamic: true
54
+ required: true
55
+
56
+ value:
57
+ description: |
58
+ Currently selected plan id (form value). Read-write — both the
59
+ form submission key and the [checked] gate on the matching
60
+ <option-card-ui>.
61
+ type: string
62
+ default: ""
63
+ reflect: true
64
+ dynamic: true
65
+
66
+ current:
67
+ description: |
68
+ Id of the user's CURRENT plan. When set, that card renders with
69
+ a muted background, a "Current plan" <tag-ui>, and either no CTA
70
+ or a "Manage" CTA. Other plans receive contextual upgrade /
71
+ downgrade CTA labels derived from rank. Unknown ids fail
72
+ silently (no anchor row).
73
+ type: string
74
+ default: ""
75
+ reflect: true
76
+ dynamic: true
77
+
78
+ name:
79
+ description: |
80
+ Form field name for the selected plan id. Mirrors UIFormElement
81
+ conventions; serialized via ElementInternals.
82
+ type: string
83
+ default: ""
84
+ reflect: true
85
+
86
+ cycle:
87
+ description: |
88
+ Active billing cycle. Drives which `plans[].prices[cycle]` value
89
+ renders across every card simultaneously. Toggle via the in-host
90
+ `cycle-toggle` (when set) or programmatically via setCycle().
91
+ type: string
92
+ default: "monthly"
93
+ enum:
94
+ - monthly
95
+ - annual
96
+ reflect: true
97
+ dynamic: true
98
+
99
+ cycle-toggle:
100
+ description: |
101
+ When set, the primitive renders an internal <segmented-ui> with
102
+ Monthly / Annual options above the plan grid. When unset, the
103
+ consumer drives [cycle] externally (e.g. from a parent toolbar).
104
+ type: boolean
105
+ default: false
106
+ reflect: true
107
+ attribute: cycle-toggle
108
+
109
+ currency:
110
+ description: |
111
+ Default ISO 4217 currency code for price rendering. Overridable
112
+ per-price via plans[].prices[cycle].currency.
113
+ type: string
114
+ default: "USD"
115
+
116
+ locale:
117
+ description: |
118
+ Locale for Intl.NumberFormat (price) and cycle labels. Defaults
119
+ to document.documentElement.lang (or "en-US" when absent).
120
+ type: string
121
+ default: ""
122
+
123
+ layout:
124
+ description: |
125
+ Card layout. `grid` (auto-fit columns, minimum 16rem) for
126
+ marketing surfaces. `list` (single column rows) for in-app
127
+ settings panels.
128
+ type: string
129
+ default: "grid"
130
+ enum:
131
+ - grid
132
+ - list
133
+ reflect: true
134
+
135
+ disabled:
136
+ description: Block all interaction across the picker.
137
+ type: boolean
138
+ default: false
139
+ reflect: true
140
+
141
+ data-stream-src:
142
+ description: |
143
+ Optional endpoint returning the `plans` array (universal
144
+ data-stream-* trait). On successful load, `plans` is replaced
145
+ and a `load` event fires; on failure an `error` event fires.
146
+ type: string
147
+ default: ""
148
+ attribute: data-stream-src
149
+
150
+ events:
151
+ change:
152
+ description: |
153
+ Fired when the selected plan id changes — either via user click
154
+ or programmatic value set. Bubbles.
155
+ detail:
156
+ value:
157
+ type: string
158
+ description: New plan id.
159
+ previous:
160
+ type: string
161
+ description: Previous plan id (empty string when none).
162
+ cycle:
163
+ type: string
164
+ description: Active billing cycle.
165
+
166
+ cycle-change:
167
+ description: |
168
+ Fired when the active billing cycle changes (cycle-toggle
169
+ click or programmatic setCycle). Bubbles.
170
+ detail:
171
+ cycle:
172
+ type: string
173
+ description: New cycle.
174
+ enum:
175
+ - monthly
176
+ - annual
177
+ previous:
178
+ type: string
179
+ description: Previous cycle.
180
+
181
+ select:
182
+ description: |
183
+ Fired when the user activates a plan's CTA button — the
184
+ committing action that consumers wire to a checkout / upgrade
185
+ flow. Distinct from `change` (selection without commit). Bubbles.
186
+ detail:
187
+ value:
188
+ type: string
189
+ description: Plan id being committed.
190
+ cycle:
191
+ type: string
192
+ description: Active billing cycle at commit.
193
+
194
+ load:
195
+ description: |
196
+ Fired when `data-stream-src` finishes a successful fetch and
197
+ `plans` is populated. Bubbles.
198
+ detail:
199
+ count:
200
+ type: integer
201
+ description: Number of plans loaded.
202
+
203
+ error:
204
+ description: |
205
+ Fired when a `data-stream-src` fetch fails OR when a user tries
206
+ to select a `disabled: true` plan. Bubbles.
207
+ detail:
208
+ reason:
209
+ type: string
210
+ description: One of `fetch-failed`, `plan-disabled`.
211
+
212
+ slots:
213
+ header:
214
+ description: |
215
+ Optional content above the plan grid (e.g. a <header> with a
216
+ title and a custom cycle toggle). When absent and
217
+ `cycle-toggle` is set, the primitive stamps its own toggle.
218
+
219
+ footer:
220
+ description: |
221
+ Optional content below the plan grid (compare-plans link, FAQ,
222
+ fine print).
223
+
224
+ empty:
225
+ description: |
226
+ Custom empty-state shown when `plans` is empty. Falls back to a
227
+ default <empty-state-ui> when not provided.
228
+
229
+ states:
230
+ - name: idle
231
+ description: Default — plans rendered, ready for interaction.
232
+ - name: loading
233
+ description: A `data-stream-src` fetch is in flight.
234
+ attribute: loading
235
+ - name: empty
236
+ description: No plans to render.
237
+ attribute: empty
238
+ - name: error
239
+ description: Last `data-stream-src` fetch failed.
240
+ attribute: error
241
+ - name: disabled
242
+ description: All cards non-interactive.
243
+ attribute: disabled
244
+
245
+ traits:
246
+ - focusable
247
+
248
+ tokens:
249
+ --plan-picker-bg:
250
+ description: Host background. Defaults to transparent.
251
+ default: transparent
252
+ --plan-picker-grid-gap:
253
+ description: Gap between plan cards in grid layout.
254
+ default: var(--a-space-4)
255
+ --plan-picker-grid-min:
256
+ description: Minimum column width in auto-fit grid.
257
+ default: 16rem
258
+ --plan-picker-card-bg:
259
+ description: Card background (cascades to option-card --option-card-bg).
260
+ default: var(--a-bg)
261
+ --plan-picker-card-bg-recommended:
262
+ description: Recommended-card background.
263
+ default: var(--md-sys-color-primary-container)
264
+ --plan-picker-card-bg-current:
265
+ description: Current-plan card background.
266
+ default: var(--a-bg-muted)
267
+ --plan-picker-card-border:
268
+ description: Default card border.
269
+ default: 1px solid var(--a-border)
270
+ --plan-picker-card-border-recommended:
271
+ description: Recommended-card accent border.
272
+ default: 2px solid var(--md-sys-color-primary)
273
+ --plan-picker-card-radius:
274
+ description: Card corner radius.
275
+ default: var(--a-radius-lg)
276
+ --plan-picker-card-py:
277
+ description: Card vertical padding.
278
+ default: var(--a-space-5)
279
+ --plan-picker-card-px:
280
+ description: Card horizontal padding.
281
+ default: var(--a-space-5)
282
+ --plan-picker-card-shadow-recommended:
283
+ description: Shadow elevation on the recommended card.
284
+ default: var(--a-shadow-md)
285
+ --plan-picker-price-size:
286
+ description: Price font size.
287
+ default: var(--a-text-3xl, 1.875rem)
288
+ --plan-picker-price-fg:
289
+ description: Price color.
290
+ default: var(--a-fg-strong, var(--a-fg))
291
+ --plan-picker-cycle-fg:
292
+ description: "Per-unit / cycle suffix color (e.g. \"/month\")."
293
+ default: var(--a-fg-muted)
294
+ --plan-picker-features-gap:
295
+ description: Gap between feature list rows.
296
+ default: var(--a-space-2)
297
+ --plan-picker-feature-icon-fg:
298
+ description: Feature-row check icon color.
299
+ default: var(--md-sys-color-primary)
300
+ --plan-picker-toggle-justify:
301
+ description: |
302
+ Justification of the internal cycle toggle row. `center` for
303
+ marketing layouts; `start` for in-app settings panels.
304
+ default: center
305
+
306
+ requiredIcons:
307
+ - check
308
+ - package
309
+
310
+ a2ui:
311
+ rules:
312
+ - >-
313
+ PlanPicker.plans MUST be a non-empty array on commit. Empty
314
+ arrays render the empty-state but cannot be the submission
315
+ state.
316
+ - >-
317
+ At most ONE plans[] record may carry `recommended: true`. Two
318
+ recommended plans are visually ambiguous and defeat the
319
+ treatment's purpose.
320
+ - >-
321
+ `current` MUST match a plans[].id or be empty. Unknown ids
322
+ fail silently — no anchor row renders, no current-state
323
+ contextualization on siblings.
324
+ - >-
325
+ plans[].prices.monthly is REQUIRED on every record. annual is
326
+ optional; if absent and cycle="annual" the card renders the
327
+ monthly price with the annual cycle suffix and no `note`.
328
+ - >-
329
+ `cycle` MUST be `monthly` or `annual`. Other values are
330
+ coerced to `monthly` and a one-shot console.warn fires.
331
+ - >-
332
+ Use `layout="list"` for in-app settings panels where the picker
333
+ sits inside a <card-ui> and width is constrained. Use the
334
+ default `layout="grid"` for marketing pricing pages.
335
+ - >-
336
+ Wire `select` (not `change`) to the actual commit handler —
337
+ change fires on selection without commit (keyboard focus
338
+ traversal, programmatic value-set); select fires when the user
339
+ clicks the CTA inside a card.
340
+
341
+ anti_patterns:
342
+ - wrong: |
343
+ <plan-picker-ui plans='[
344
+ {"id":"p1","name":"Free","price":0},
345
+ {"id":"p2","name":"Pro","price":20}
346
+ ]'></plan-picker-ui>
347
+ why: |
348
+ `price` is a top-level shortcut not in the schema. Prices are
349
+ keyed by cycle (monthly / annual). Without a cycle key, the
350
+ cycle toggle has nothing to switch and annual pricing is
351
+ invisible to consumers.
352
+ fix: |
353
+ <plan-picker-ui plans='[
354
+ {"id":"p1","name":"Free","prices":{"monthly":{"amount":0}}},
355
+ {"id":"p2","name":"Pro","prices":{"monthly":{"amount":20}}}
356
+ ]'></plan-picker-ui>
357
+ - wrong: |
358
+ <plan-picker-ui plans='[
359
+ {"id":"t","name":"Team","recommended":true,"prices":{"monthly":{"amount":10}}},
360
+ {"id":"p","name":"Pro","recommended":true,"prices":{"monthly":{"amount":20}}}
361
+ ]'></plan-picker-ui>
362
+ why: |
363
+ Two recommended plans cancel each other visually — there is no
364
+ "the" recommendation. Pick one.
365
+ fix: |
366
+ <plan-picker-ui plans='[
367
+ {"id":"t","name":"Team","prices":{"monthly":{"amount":10}}},
368
+ {"id":"p","name":"Pro","recommended":true,"prices":{"monthly":{"amount":20}}}
369
+ ]'></plan-picker-ui>
370
+ - wrong: |
371
+ A <col-ui> of bespoke <card-ui> plan cards with manual radio
372
+ markup and a per-plan cycle pill.
373
+ why: |
374
+ Reinvents the radiogroup keyboard model and the cycle-toggle
375
+ semantics; pricing strings drift between this surface and the
376
+ marketing pricing page that uses the canonical primitive.
377
+ fix: |
378
+ <plan-picker-ui plans="..." cycle-toggle></plan-picker-ui>
379
+
380
+ examples:
381
+ - name: in-app-upgrade
382
+ description: In-app upgrade modal with three plans + annual default + cycle toggle.
383
+ a2ui: |
384
+ [
385
+ {
386
+ "id": "pp-upgrade",
387
+ "component": "PlanPicker",
388
+ "name": "plan",
389
+ "current": "plan_team",
390
+ "cycle": "annual",
391
+ "cycleToggle": true,
392
+ "plans": [
393
+ {"id":"plan_free","name":"Free","prices":{"monthly":{"amount":0}},"features":["3 projects","Community support"],"rank":1},
394
+ {"id":"plan_team","name":"Team","prices":{"monthly":{"amount":10,"unit":"seat"},"annual":{"amount":8,"unit":"seat","note":"billed annually"}},"features":["Unlimited projects","Email support"],"rank":2},
395
+ {"id":"plan_pro","name":"Pro","prices":{"monthly":{"amount":25,"unit":"seat"},"annual":{"amount":20,"unit":"seat","note":"billed annually"}},"features":["Everything in Team","Priority support"],"recommended":true,"rank":3}
396
+ ]
397
+ }
398
+ ]
399
+ - name: settings-list
400
+ description: Settings-page plan picker — single-column list inside a card.
401
+ a2ui: |
402
+ [
403
+ {
404
+ "id": "pp-settings",
405
+ "component": "PlanPicker",
406
+ "name": "plan",
407
+ "current": "plan_team",
408
+ "layout": "list",
409
+ "plans": [
410
+ {"id":"plan_team","name":"Team","prices":{"monthly":{"amount":10,"unit":"seat"}},"features":["Unlimited projects"],"rank":2},
411
+ {"id":"plan_pro","name":"Pro","prices":{"monthly":{"amount":25,"unit":"seat"}},"features":["Everything in Team","Priority support"],"recommended":true,"rank":3}
412
+ ]
413
+ }
414
+ ]
415
+
416
+ keywords:
417
+ - plan-picker
418
+ - plans
419
+ - pricing
420
+ - upgrade
421
+ - billing
422
+ - tier
423
+ - tiers
424
+ - subscription
425
+ - subscribe
426
+ - paywall
427
+ - choose-plan
428
+ - select-plan
429
+ - plan-selection
430
+
431
+ synonyms:
432
+ plan:
433
+ - tier
434
+ - subscription
435
+ - package
436
+ pricing:
437
+ - plan
438
+ - price
439
+ - tier
440
+ upgrade:
441
+ - plan-change
442
+ - subscribe
443
+ - choose-plan
444
+
445
+ related:
446
+ - OptionCard
447
+ - Segmented
448
+ - Segment
449
+ - Tag
450
+ - Button
451
+ - Card
452
+ - EmptyState
453
+ - Skeleton
package/chat/README.md CHANGED
@@ -34,7 +34,7 @@ job, the same event object just also flows through this function to paint.
34
34
  | `done` | `reasoning.finish()` (or `.fail('Blocked by guardrail')` when `stopReason === 'guardrail_denied'`) + `stopStreaming()`. |
35
35
 
36
36
  **Why `<agent-reasoning-ui>`, not a new primitive:** the primitive audit
37
- (adia-author §0) found `agent-reasoning-ui` already built for exactly this
37
+ (primitive-authoring §0) found `agent-reasoning-ui` already built for exactly this
38
38
  shape — "Agent inner monologue + pipeline viewer with steps, thoughts,
39
39
  plans, and iterations," composing `<timeline-ui>` for step rows with a
40
40
  collapsible per-step `outcomes` list (the "collapsible tool-result body"