@adia-ai/web-modules 0.8.35 → 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.
- package/CHANGELOG.md +22 -0
- package/README.md +3 -3
- package/agent-admin/admin-roster/admin-roster.js +1 -1
- package/agent-admin/admin-settings/admin-settings.js +1 -1
- package/agent-admin/agent-admin/agent-admin.js +1 -1
- package/billing/billing-overview/billing-overview.a2ui.json +281 -0
- package/billing/billing-overview/billing-overview.class.js +838 -0
- package/billing/billing-overview/billing-overview.css +223 -0
- package/billing/billing-overview/billing-overview.js +16 -0
- package/billing/billing-overview/billing-overview.yaml +441 -0
- package/billing/index.js +21 -0
- package/billing/invoice-detail/invoice-detail.a2ui.json +276 -0
- package/billing/invoice-detail/invoice-detail.class.js +711 -0
- package/billing/invoice-detail/invoice-detail.css +305 -0
- package/billing/invoice-detail/invoice-detail.js +16 -0
- package/billing/invoice-detail/invoice-detail.yaml +411 -0
- package/billing/invoice-history/invoice-history.a2ui.json +315 -0
- package/billing/invoice-history/invoice-history.class.js +672 -0
- package/billing/invoice-history/invoice-history.css +130 -0
- package/billing/invoice-history/invoice-history.js +16 -0
- package/billing/invoice-history/invoice-history.yaml +398 -0
- package/billing/payment-method-form/payment-method-form.a2ui.json +310 -0
- package/billing/payment-method-form/payment-method-form.class.js +886 -0
- package/billing/payment-method-form/payment-method-form.css +149 -0
- package/billing/payment-method-form/payment-method-form.js +16 -0
- package/billing/payment-method-form/payment-method-form.yaml +430 -0
- package/billing/payment-method-list/payment-method-list.a2ui.json +283 -0
- package/billing/payment-method-list/payment-method-list.class.js +705 -0
- package/billing/payment-method-list/payment-method-list.css +128 -0
- package/billing/payment-method-list/payment-method-list.js +16 -0
- package/billing/payment-method-list/payment-method-list.yaml +355 -0
- package/billing/plan-picker/plan-picker.a2ui.json +349 -0
- package/billing/plan-picker/plan-picker.class.js +635 -0
- package/billing/plan-picker/plan-picker.css +227 -0
- package/billing/plan-picker/plan-picker.js +16 -0
- package/billing/plan-picker/plan-picker.yaml +453 -0
- package/chat/README.md +1 -1
- package/chat/chat-composer/chat-composer.js +2 -2
- package/chat/chat-empty/chat-empty.js +2 -2
- package/chat/chat-shell/chat-shell.js +4 -4
- package/chat/chat-sidebar/chat-sidebar.js +2 -2
- package/chat/chat-surfaces/chat-surfaces.js +2 -2
- package/chat/chat-thread/chat-thread.js +2 -2
- package/dashboard/dashboard-layout/dashboard-layout.a2ui.json +254 -0
- package/dashboard/dashboard-layout/dashboard-layout.css +190 -0
- package/dashboard/dashboard-layout/dashboard-layout.js +289 -0
- package/dashboard/dashboard-layout/dashboard-layout.yaml +374 -0
- package/dashboard/date-range-selector/date-range-selector.a2ui.json +236 -0
- package/dashboard/date-range-selector/date-range-selector.css +84 -0
- package/dashboard/date-range-selector/date-range-selector.js +686 -0
- package/dashboard/date-range-selector/date-range-selector.yaml +358 -0
- package/dashboard/index.js +14 -0
- package/dist/everything.min.js +1 -1
- package/editor/editor-canvas/editor-canvas.js +2 -2
- package/editor/editor-shell/editor-shell.js +2 -2
- package/editor/editor-sidebar/editor-sidebar.js +2 -2
- package/editor/editor-toolbar/editor-toolbar.js +2 -2
- package/feedback/confirm-dialog/confirm-dialog.a2ui.json +206 -0
- package/feedback/confirm-dialog/confirm-dialog.css +157 -0
- package/feedback/confirm-dialog/confirm-dialog.js +383 -0
- package/feedback/confirm-dialog/confirm-dialog.yaml +297 -0
- package/feedback/index.js +10 -0
- package/form/form-popover/form-popover.js +1 -1
- package/generative/index.d.ts +1 -1
- package/generative/index.js +2 -2
- package/onboarding/index.js +1 -0
- package/onboarding/onboarding-checklist/onboarding-checklist.a2ui.json +263 -0
- package/onboarding/onboarding-checklist/onboarding-checklist.css +157 -0
- package/onboarding/onboarding-checklist/onboarding-checklist.js +428 -0
- package/onboarding/onboarding-checklist/onboarding-checklist.yaml +236 -0
- package/package.json +99 -6
- package/runtime/a2ui-root/a2ui-root.js +3 -3
- package/runtime/gen-root/gen-root.js +5 -5
- package/settings/index.js +12 -0
- package/settings/integrations-page/integrations-page.a2ui.json +274 -0
- package/settings/integrations-page/integrations-page.css +177 -0
- package/settings/integrations-page/integrations-page.d.ts +77 -0
- package/settings/integrations-page/integrations-page.js +413 -0
- package/settings/integrations-page/integrations-page.yaml +317 -0
- package/settings/notification-preferences/notification-preferences.a2ui.json +245 -0
- package/settings/notification-preferences/notification-preferences.css +204 -0
- package/settings/notification-preferences/notification-preferences.js +622 -0
- package/settings/notification-preferences/notification-preferences.yaml +358 -0
- package/shell/admin-command/admin-command.js +2 -2
- package/shell/admin-shell/admin-shell.js +2 -2
- package/shell/admin-sidebar/admin-sidebar.js +2 -2
- package/shell/embed-shell/embed-shell.js +3 -3
- package/simple/simple-shell/simple-shell.js +1 -1
- package/theme/theme-panel/theme-panel.js +2 -2
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# Edit this file; run `npm run build:components` to regenerate a2ui.json.
|
|
2
|
+
$schema: ../../../../scripts/schemas/component.yaml.schema.json
|
|
3
|
+
name: UIIntegrationsPage
|
|
4
|
+
tag: integrations-page-ui
|
|
5
|
+
status: stable
|
|
6
|
+
component: IntegrationsPage
|
|
7
|
+
category: container
|
|
8
|
+
version: 1
|
|
9
|
+
description: |
|
|
10
|
+
Module-tier Settings page composite — a searchable, category-grouped
|
|
11
|
+
grid of <integration-card-ui> tiles (SPEC-062). Owns the
|
|
12
|
+
`integrations` array, the search-filter state, the category /
|
|
13
|
+
status grouping, the responsive grid breakpoints, and the empty-state
|
|
14
|
+
copy. Card-level events (`connect` / `configure` / `disconnect` /
|
|
15
|
+
`retry`) bubble up unchanged with `provider` in detail; the page also
|
|
16
|
+
emits `search` (debounced) and a top-bar `filter-change` when the
|
|
17
|
+
user picks a status chip.
|
|
18
|
+
|
|
19
|
+
Lives in `packages/web-modules/settings/integrations-page/` per the
|
|
20
|
+
three-tier architecture — composes multiple primitives, holds layout
|
|
21
|
+
responsibility, consumed by the settings shell. Replaces the
|
|
22
|
+
hand-rolled `settings/integrations` HTML template per consumer.
|
|
23
|
+
|
|
24
|
+
Spec: .claude/docs/specs/implementation-ready/SPEC-063-integrations-page.md
|
|
25
|
+
|
|
26
|
+
# Per ADR-0027 — composites that programmatically create primitives in
|
|
27
|
+
# their render() do NOT auto-import those primitives. Consumer (or demo
|
|
28
|
+
# shell) must explicitly import each composed primitive.
|
|
29
|
+
composes:
|
|
30
|
+
- integration-card-ui
|
|
31
|
+
- grid-ui
|
|
32
|
+
- search-ui
|
|
33
|
+
- segmented-ui
|
|
34
|
+
- segment-ui
|
|
35
|
+
- text-ui
|
|
36
|
+
|
|
37
|
+
props:
|
|
38
|
+
integrations:
|
|
39
|
+
description: |
|
|
40
|
+
Array of integration descriptors — each item conforms to the
|
|
41
|
+
SPEC-062 <integration-card-ui> prop shape:
|
|
42
|
+
`{ provider, name, logo?, description?, status, category?,
|
|
43
|
+
error-message? }`. Empty array renders the empty-state slot.
|
|
44
|
+
type: array
|
|
45
|
+
default: []
|
|
46
|
+
required: true
|
|
47
|
+
dynamic: true
|
|
48
|
+
loading:
|
|
49
|
+
description: |
|
|
50
|
+
Renders a skeleton grid (6 tiles) instead of cards. Driven by the
|
|
51
|
+
consumer while the integrations payload is in flight.
|
|
52
|
+
type: boolean
|
|
53
|
+
default: false
|
|
54
|
+
reflect: true
|
|
55
|
+
dynamic: true
|
|
56
|
+
search-placeholder:
|
|
57
|
+
description: |
|
|
58
|
+
Placeholder copy for the built-in search input. Defaults to
|
|
59
|
+
"Search integrations".
|
|
60
|
+
type: string
|
|
61
|
+
default: "Search integrations"
|
|
62
|
+
reflect: true
|
|
63
|
+
group-by:
|
|
64
|
+
description: |
|
|
65
|
+
How to bucket cards into sections. `category` groups by the per-item
|
|
66
|
+
`category` key; `status` groups by connection state; `none` renders
|
|
67
|
+
a single ungrouped grid.
|
|
68
|
+
type: string
|
|
69
|
+
default: category
|
|
70
|
+
enum:
|
|
71
|
+
- category
|
|
72
|
+
- status
|
|
73
|
+
- none
|
|
74
|
+
reflect: true
|
|
75
|
+
status-filter:
|
|
76
|
+
description: |
|
|
77
|
+
Optional status filter — restricts the visible cards to one status.
|
|
78
|
+
`all` (default) shows everything; the rest restrict to that status
|
|
79
|
+
bucket. Reflects so consumers can deep-link.
|
|
80
|
+
type: string
|
|
81
|
+
default: all
|
|
82
|
+
enum:
|
|
83
|
+
- all
|
|
84
|
+
- available
|
|
85
|
+
- connected
|
|
86
|
+
- error
|
|
87
|
+
- coming-soon
|
|
88
|
+
reflect: true
|
|
89
|
+
dynamic: true
|
|
90
|
+
|
|
91
|
+
events:
|
|
92
|
+
connect:
|
|
93
|
+
description: Bubbled from a child <integration-card-ui> when its primary button is pressed while `status="available"`.
|
|
94
|
+
detail:
|
|
95
|
+
provider:
|
|
96
|
+
type: string
|
|
97
|
+
description: The provider key of the card that fired.
|
|
98
|
+
configure:
|
|
99
|
+
description: Bubbled from a child <integration-card-ui> while `status="connected"`.
|
|
100
|
+
detail:
|
|
101
|
+
provider:
|
|
102
|
+
type: string
|
|
103
|
+
description: The provider key of the card that fired.
|
|
104
|
+
disconnect:
|
|
105
|
+
description: Bubbled from a child card's overflow menu disconnect item.
|
|
106
|
+
detail:
|
|
107
|
+
provider:
|
|
108
|
+
type: string
|
|
109
|
+
description: The provider key of the card that fired.
|
|
110
|
+
retry:
|
|
111
|
+
description: Bubbled from a child <integration-card-ui> while `status="error"`.
|
|
112
|
+
detail:
|
|
113
|
+
provider:
|
|
114
|
+
type: string
|
|
115
|
+
description: The provider key of the card that fired.
|
|
116
|
+
search:
|
|
117
|
+
description: Debounced search input change.
|
|
118
|
+
detail:
|
|
119
|
+
query:
|
|
120
|
+
type: string
|
|
121
|
+
description: The current search query (lower-cased, trimmed).
|
|
122
|
+
filter-change:
|
|
123
|
+
description: User clicked a status filter chip in the top bar.
|
|
124
|
+
detail:
|
|
125
|
+
status:
|
|
126
|
+
type: string
|
|
127
|
+
description: The newly-selected status filter (`all` resets).
|
|
128
|
+
|
|
129
|
+
slots:
|
|
130
|
+
header:
|
|
131
|
+
description: |
|
|
132
|
+
Optional page header (kicker / title / subtitle). Overrides the
|
|
133
|
+
default rendering — when supplied the composite stamps no
|
|
134
|
+
built-in heading.
|
|
135
|
+
empty:
|
|
136
|
+
description: |
|
|
137
|
+
Optional override for the empty-state copy. When supplied, replaces
|
|
138
|
+
the built-in "No integrations match" / "No integrations available"
|
|
139
|
+
messages.
|
|
140
|
+
|
|
141
|
+
states:
|
|
142
|
+
- name: idle
|
|
143
|
+
description: Default; renders all groups matching the current filter.
|
|
144
|
+
- name: loading
|
|
145
|
+
description: Skeleton grid; cards hidden.
|
|
146
|
+
attribute: loading
|
|
147
|
+
- name: empty-search
|
|
148
|
+
description: Search query yields zero cards.
|
|
149
|
+
attribute: data-empty-search
|
|
150
|
+
- name: empty-data
|
|
151
|
+
description: "`integrations` array is empty."
|
|
152
|
+
attribute: data-empty-data
|
|
153
|
+
|
|
154
|
+
traits: []
|
|
155
|
+
|
|
156
|
+
tokens:
|
|
157
|
+
--integrations-page-bg:
|
|
158
|
+
description: Page background. Defaults to `var(--a-bg)`.
|
|
159
|
+
default: var(--a-bg)
|
|
160
|
+
--integrations-page-fg:
|
|
161
|
+
description: Primary foreground. Defaults to `var(--a-fg)`.
|
|
162
|
+
default: var(--a-fg)
|
|
163
|
+
--integrations-page-fg-muted:
|
|
164
|
+
description: Secondary foreground for empty-state copy + section meta.
|
|
165
|
+
default: var(--a-fg-muted)
|
|
166
|
+
--integrations-page-px:
|
|
167
|
+
description: Horizontal padding around the page.
|
|
168
|
+
default: var(--a-space-5)
|
|
169
|
+
--integrations-page-py:
|
|
170
|
+
description: Vertical padding around the page.
|
|
171
|
+
default: var(--a-space-5)
|
|
172
|
+
--integrations-page-gap:
|
|
173
|
+
description: Vertical gap between toolbar / sections / empty-state.
|
|
174
|
+
default: var(--a-space-5)
|
|
175
|
+
--integrations-page-section-gap:
|
|
176
|
+
description: Vertical gap between sibling category sections.
|
|
177
|
+
default: var(--a-space-6)
|
|
178
|
+
--integrations-page-card-gap:
|
|
179
|
+
description: Gap inside the grid between cards.
|
|
180
|
+
default: var(--a-space-4)
|
|
181
|
+
--integrations-page-grid-min:
|
|
182
|
+
description: Minimum card width for the auto-fill grid track.
|
|
183
|
+
default: var(--a-space-12)
|
|
184
|
+
--integrations-page-section-heading-fg:
|
|
185
|
+
description: Section heading color.
|
|
186
|
+
default: var(--a-fg-strong)
|
|
187
|
+
--integrations-page-section-heading-size:
|
|
188
|
+
description: Section heading font size.
|
|
189
|
+
default: var(--a-ui-sm)
|
|
190
|
+
--integrations-page-section-heading-weight:
|
|
191
|
+
description: Section heading font weight.
|
|
192
|
+
default: var(--a-weight-medium)
|
|
193
|
+
|
|
194
|
+
a2ui:
|
|
195
|
+
rules:
|
|
196
|
+
- rule: |
|
|
197
|
+
Use <integrations-page-ui> for the canonical Settings >
|
|
198
|
+
Integrations grid. Supply the `integrations` array — the
|
|
199
|
+
composite owns the search + grouping + grid breakpoints +
|
|
200
|
+
empty state.
|
|
201
|
+
reason: One composite replaces the per-app hand-rolled grid.
|
|
202
|
+
- rule: |
|
|
203
|
+
`integrations` MUST be a non-empty array OR the page renders
|
|
204
|
+
the empty-state. Each item MUST satisfy the SPEC-062 card
|
|
205
|
+
prop contract (provider + name required).
|
|
206
|
+
reason: Cards generated from data; missing required keys break a11y wiring.
|
|
207
|
+
- rule: |
|
|
208
|
+
Do NOT slot <integration-card-ui> children directly — the page
|
|
209
|
+
generates cards from the `integrations` prop. Slotted children
|
|
210
|
+
are ignored.
|
|
211
|
+
reason: Single source of truth (prop), not mixed slot + data.
|
|
212
|
+
- rule: |
|
|
213
|
+
Do NOT nest <integrations-page-ui> inside another
|
|
214
|
+
<integrations-page-ui>.
|
|
215
|
+
reason: Composite carries page-level layout; nesting double-pads + double-toolbars.
|
|
216
|
+
- rule: |
|
|
217
|
+
For one-off integration tile groups (e.g., a single recommended
|
|
218
|
+
provider on a marketing page) use <integration-card-ui> directly
|
|
219
|
+
inside <grid-ui>; reach for the page composite only when search
|
|
220
|
+
+ grouping + empty-state semantics are needed.
|
|
221
|
+
reason: Capacity guidance — page is a Settings construct.
|
|
222
|
+
|
|
223
|
+
anti_patterns:
|
|
224
|
+
- wrong: |
|
|
225
|
+
{"component": "IntegrationsPage", "children": [
|
|
226
|
+
{"component": "IntegrationCard", "provider": "slack", "name": "Slack"}
|
|
227
|
+
]}
|
|
228
|
+
why: |
|
|
229
|
+
Slotted cards are ignored — the page generates cards from the
|
|
230
|
+
`integrations` prop. The page renders empty.
|
|
231
|
+
fix: |
|
|
232
|
+
{"component": "IntegrationsPage", "integrations": [
|
|
233
|
+
{"provider": "slack", "name": "Slack", "status": "available"}
|
|
234
|
+
]}
|
|
235
|
+
- wrong: |
|
|
236
|
+
{"component": "Page", "children": [
|
|
237
|
+
{"component": "Grid", "children": [
|
|
238
|
+
{"component": "IntegrationCard", "provider": "slack", "name": "Slack"}
|
|
239
|
+
]}
|
|
240
|
+
]}
|
|
241
|
+
why: |
|
|
242
|
+
Re-implements the page composite with primitives. Loses search,
|
|
243
|
+
grouping, and empty-state semantics.
|
|
244
|
+
fix: |
|
|
245
|
+
{"component": "IntegrationsPage", "integrations": [
|
|
246
|
+
{"provider": "slack", "name": "Slack", "status": "available"}
|
|
247
|
+
]}
|
|
248
|
+
|
|
249
|
+
examples:
|
|
250
|
+
- name: category-grouped
|
|
251
|
+
description: Full integrations page grouped by category (default).
|
|
252
|
+
a2ui: |
|
|
253
|
+
[
|
|
254
|
+
{
|
|
255
|
+
"id": "page",
|
|
256
|
+
"component": "IntegrationsPage",
|
|
257
|
+
"group-by": "category",
|
|
258
|
+
"integrations": [
|
|
259
|
+
{"provider": "slack", "name": "Slack", "logo": "/integrations/slack.svg",
|
|
260
|
+
"description": "Notifications and replies in channels.",
|
|
261
|
+
"status": "connected", "category": "Communication"},
|
|
262
|
+
{"provider": "github", "name": "GitHub", "logo": "/integrations/github.svg",
|
|
263
|
+
"description": "Sync issues and pull requests.",
|
|
264
|
+
"status": "available", "category": "Developer Tools"},
|
|
265
|
+
{"provider": "stripe", "name": "Stripe", "logo": "/integrations/stripe.svg",
|
|
266
|
+
"description": "Charge customers and reconcile invoices.",
|
|
267
|
+
"status": "error", "category": "Payments",
|
|
268
|
+
"error-message": "Token expired — re-authenticate."}
|
|
269
|
+
]
|
|
270
|
+
}
|
|
271
|
+
]
|
|
272
|
+
- name: loading-skeleton
|
|
273
|
+
description: Loading state — 6 skeleton tiles, no cards.
|
|
274
|
+
a2ui: |
|
|
275
|
+
[{"id": "page", "component": "IntegrationsPage", "loading": true}]
|
|
276
|
+
- name: empty-data
|
|
277
|
+
description: Empty state — no integrations available.
|
|
278
|
+
a2ui: |
|
|
279
|
+
[{"id": "page", "component": "IntegrationsPage", "integrations": []}]
|
|
280
|
+
|
|
281
|
+
keywords:
|
|
282
|
+
- integrations
|
|
283
|
+
- integration
|
|
284
|
+
- settings
|
|
285
|
+
- settings-page
|
|
286
|
+
- connections
|
|
287
|
+
- third-party
|
|
288
|
+
- oauth
|
|
289
|
+
- providers
|
|
290
|
+
- app-directory
|
|
291
|
+
- marketplace
|
|
292
|
+
|
|
293
|
+
synonyms:
|
|
294
|
+
integrations:
|
|
295
|
+
- integration
|
|
296
|
+
- connections
|
|
297
|
+
- apps
|
|
298
|
+
- providers
|
|
299
|
+
settings:
|
|
300
|
+
- settings
|
|
301
|
+
- account
|
|
302
|
+
- admin
|
|
303
|
+
marketplace:
|
|
304
|
+
- integrations
|
|
305
|
+
- app-directory
|
|
306
|
+
- apps
|
|
307
|
+
oauth:
|
|
308
|
+
- integration
|
|
309
|
+
- connection
|
|
310
|
+
- auth
|
|
311
|
+
|
|
312
|
+
related:
|
|
313
|
+
- IntegrationCard
|
|
314
|
+
- Grid
|
|
315
|
+
- Search
|
|
316
|
+
- Segmented
|
|
317
|
+
- Page
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/NotificationPreferences.json",
|
|
4
|
+
"title": "NotificationPreferences",
|
|
5
|
+
"description": "Page-level Settings composite: a matrix of notification types (rows)\n× delivery channels (columns: in-app, email, SMS) with a binary\n<check-ui> in each cell and an optional <switch-ui> column-header\nmaster toggle for bulk-flipping a channel across every row.\n\nForm-bearing — the composite extends UIFormElement and serializes its\ncurrent preferences shape as JSON on `value`. Per first-principle #2\n(\"save is the consumer's job\"), the composite does NOT mutate the\npassed-in `preferences` array; it emits a typed `change` event per\ncell toggle and a `bulk-toggle` event per column-header switch, and\nexposes the staged JSON via the form value so a host <form> submit\ncarries it through ElementInternals.\n\nChannels are columns; types are rows (the smaller-set / larger-set\ninvariant — channels are 3-5 in the wild, types are 10-50). Layout\nrenders as a semantic ARIA grid (`role=\"table\"`/`row`/`cell`/\n`rowheader`/`columnheader`) — NOT native `<table>` (per the HTML\nparser strip rule, table-content tags would foster-parent out of a\ncustom-element subtree).\n\nSpec: .claude/docs/specs/implementation-ready/SPEC-064-notification-preferences.md.\n",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"allOf": [
|
|
8
|
+
{
|
|
9
|
+
"$ref": "common_types.json#/$defs/ComponentCommon"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"$ref": "common_types.json#/$defs/CatalogComponentCommon"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"channelEnabled": {
|
|
17
|
+
"description": "Map of channel-key → master-toggle boolean for the column-header\n<switch-ui>. When omitted, master toggles default to `true` for\nevery channel. Independent of cell values — toggling the master\noff does NOT auto-update the cells; the host receives a\n`bulk-toggle` event and updates `preferences` itself.\n",
|
|
18
|
+
"type": "object",
|
|
19
|
+
"default": {}
|
|
20
|
+
},
|
|
21
|
+
"channels": {
|
|
22
|
+
"description": "Column definitions — one record per delivery channel. Each\ncarries a stable `key`, a `label` (the column header), and an\noptional `icon` name (Phosphor — defaults to no icon when\nabsent). Example: [{key:\"in-app\", label:\"In-app\", icon:\"chat-circle\"},\n{key:\"email\", label:\"Email\", icon:\"envelope\"}]. Empty array\nrenders nothing (the matrix needs at least one column).\n",
|
|
23
|
+
"$ref": "common_types.json#/$defs/DynamicStringList"
|
|
24
|
+
},
|
|
25
|
+
"component": {
|
|
26
|
+
"const": "NotificationPreferences"
|
|
27
|
+
},
|
|
28
|
+
"disabled": {
|
|
29
|
+
"description": "All cells + master toggles become non-interactive.",
|
|
30
|
+
"type": "boolean",
|
|
31
|
+
"default": false
|
|
32
|
+
},
|
|
33
|
+
"group-by": {
|
|
34
|
+
"description": "Row-grouping mode. `none` (default) renders all rows in one\nblock. `group` renders one section per unique `preferences[].group`\nvalue with a header row above each section.\n",
|
|
35
|
+
"type": "string",
|
|
36
|
+
"enum": [
|
|
37
|
+
"none",
|
|
38
|
+
"group"
|
|
39
|
+
],
|
|
40
|
+
"default": "none"
|
|
41
|
+
},
|
|
42
|
+
"loading": {
|
|
43
|
+
"description": "Renders a skeleton matrix overlay. Cells become non-interactive\nand dim while loading.\n",
|
|
44
|
+
"type": "boolean",
|
|
45
|
+
"default": false
|
|
46
|
+
},
|
|
47
|
+
"preferences": {
|
|
48
|
+
"description": "Matrix data — one row per notification type. Each record carries\na stable `key`, a `label`, optional `description` (rendered under\nthe label), optional `group` (when `group-by=\"group\"`), and a\n`channels` map keyed by channel key with boolean values.\nExample: {key:\"mentions\", label:\"Mentions\", channels:{\"in-app\":true,\nemail:false, sms:false}}. Empty array renders the empty state.\n",
|
|
49
|
+
"$ref": "common_types.json#/$defs/DynamicStringList"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"required": [
|
|
53
|
+
"component",
|
|
54
|
+
"preferences",
|
|
55
|
+
"channels"
|
|
56
|
+
],
|
|
57
|
+
"unevaluatedProperties": false,
|
|
58
|
+
"x-adiaui": {
|
|
59
|
+
"anti_patterns": [
|
|
60
|
+
{
|
|
61
|
+
"fix": "<notification-preferences-ui id=\"prefs\"></notification-preferences-ui>\n<script>\n document.querySelector('#prefs').channels = [\n {key:'email', label:'Email'}\n ];\n document.querySelector('#prefs').preferences = [\n {key:'mentions', label:'Mentions', channels:{email:true}},\n {key:'replies', label:'Replies', channels:{email:false}}\n ];\n</script>\n",
|
|
62
|
+
"why": "Cells are generated from the `preferences` matrix. Slotted\nswitches are ignored and the host renders empty.\n",
|
|
63
|
+
"wrong": "<notification-preferences-ui>\n <switch-ui label=\"Email mentions\"></switch-ui>\n <switch-ui label=\"Email replies\"></switch-ui>\n</notification-preferences-ui>\n"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"fix": "<notification-preferences-ui id=\"prefs\"></notification-preferences-ui>\n<script>/* set channels + preferences here */</script>\n",
|
|
67
|
+
"why": "Re-implements the matrix in raw HTML — loses the typed\n`change` / `bulk-toggle` event contract, the column-master\nswitch, the group-by support, and the consistent token-driven\nvisual treatment. Worse, table-content tags inside a custom\nelement subtree are foster-parented out of the DOM by the HTML\nparser — they silently vanish.\n",
|
|
68
|
+
"wrong": "<table>\n <thead><tr><th></th><th>Email</th></tr></thead>\n <tbody>\n <tr><th>Mentions</th><td><check-ui></check-ui></td></tr>\n </tbody>\n</table>\n"
|
|
69
|
+
}
|
|
70
|
+
],
|
|
71
|
+
"category": "container",
|
|
72
|
+
"composes": [
|
|
73
|
+
"check-ui",
|
|
74
|
+
"switch-ui",
|
|
75
|
+
"icon-ui",
|
|
76
|
+
"text-ui",
|
|
77
|
+
"empty-state-ui"
|
|
78
|
+
],
|
|
79
|
+
"events": {
|
|
80
|
+
"bulk-toggle": {
|
|
81
|
+
"description": "Fired when the user toggles a column-header <switch-ui>.\nBubbles. Mirrors `change` shape but for the column master —\nhost applies the bulk change to its own `preferences` data.\n",
|
|
82
|
+
"detail": {
|
|
83
|
+
"channel": {
|
|
84
|
+
"description": "The `key` of the channel column whose master flipped.",
|
|
85
|
+
"type": "string"
|
|
86
|
+
},
|
|
87
|
+
"enabled": {
|
|
88
|
+
"description": "The new desired master state.",
|
|
89
|
+
"type": "boolean"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"change": {
|
|
94
|
+
"description": "Fired when the user toggles a cell <check-ui>. Bubbles. The\ncomposite emits this with the previous state — the host must\napply the new state to its own data and re-pass `preferences`\nfor the cell to visually update.\n",
|
|
95
|
+
"detail": {
|
|
96
|
+
"channel": {
|
|
97
|
+
"description": "The `key` of the channel column whose cell flipped.",
|
|
98
|
+
"type": "string"
|
|
99
|
+
},
|
|
100
|
+
"enabled": {
|
|
101
|
+
"description": "The new desired state (true = opted in).",
|
|
102
|
+
"type": "boolean"
|
|
103
|
+
},
|
|
104
|
+
"row": {
|
|
105
|
+
"description": "The `key` of the notification type whose cell flipped.",
|
|
106
|
+
"type": "string"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"examples": [
|
|
112
|
+
{
|
|
113
|
+
"description": "Three channels (in-app / email / SMS) × four notification types.",
|
|
114
|
+
"a2ui": "[\n {\n \"id\": \"np-default\",\n \"component\": \"NotificationPreferences\",\n \"name\": \"notifications\",\n \"channels\": [\n {\"key\": \"in-app\", \"label\": \"In-app\", \"icon\": \"chat-circle\"},\n {\"key\": \"email\", \"label\": \"Email\", \"icon\": \"envelope\"},\n {\"key\": \"sms\", \"label\": \"SMS\", \"icon\": \"device-mobile\"}\n ],\n \"preferences\": [\n {\"key\": \"mentions\", \"label\": \"Mentions\",\n \"channels\": {\"in-app\": true, \"email\": true, \"sms\": false}},\n {\"key\": \"comments\", \"label\": \"Comments\",\n \"channels\": {\"in-app\": true, \"email\": false, \"sms\": false}},\n {\"key\": \"releases\", \"label\": \"Releases\",\n \"channels\": {\"in-app\": false,\"email\": true, \"sms\": false}},\n {\"key\": \"security\", \"label\": \"Security alerts\",\n \"channels\": {\"in-app\": true, \"email\": true, \"sms\": true}}\n ]\n }\n]\n",
|
|
115
|
+
"name": "default"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"description": "Same matrix grouped by category via group-by=\"group\".",
|
|
119
|
+
"a2ui": "[\n {\n \"id\": \"np-grouped\",\n \"component\": \"NotificationPreferences\",\n \"name\": \"notifications\",\n \"groupBy\": \"group\",\n \"channels\": [\n {\"key\": \"in-app\", \"label\": \"In-app\"},\n {\"key\": \"email\", \"label\": \"Email\"}\n ],\n \"preferences\": [\n {\"key\": \"mentions\", \"label\": \"Mentions\", \"group\": \"Activity\",\n \"channels\": {\"in-app\": true, \"email\": true}},\n {\"key\": \"comments\", \"label\": \"Comments\", \"group\": \"Activity\",\n \"channels\": {\"in-app\": true, \"email\": false}},\n {\"key\": \"digest\", \"label\": \"Weekly digest\", \"group\": \"Summaries\",\n \"channels\": {\"in-app\": false, \"email\": true}}\n ]\n }\n]\n",
|
|
120
|
+
"name": "grouped"
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
"keywords": [
|
|
124
|
+
"notification-preferences",
|
|
125
|
+
"notifications",
|
|
126
|
+
"preferences",
|
|
127
|
+
"opt-in",
|
|
128
|
+
"opt-out",
|
|
129
|
+
"alerts",
|
|
130
|
+
"channels",
|
|
131
|
+
"in-app",
|
|
132
|
+
"email",
|
|
133
|
+
"sms",
|
|
134
|
+
"subscriptions",
|
|
135
|
+
"notification-settings"
|
|
136
|
+
],
|
|
137
|
+
"name": "UINotificationPreferences",
|
|
138
|
+
"related": [
|
|
139
|
+
"Check",
|
|
140
|
+
"Switch",
|
|
141
|
+
"Table",
|
|
142
|
+
"EmptyState",
|
|
143
|
+
"Icon",
|
|
144
|
+
"Text"
|
|
145
|
+
],
|
|
146
|
+
"slots": {
|
|
147
|
+
"empty": {
|
|
148
|
+
"description": "Custom empty-state copy shown when `preferences` is empty. Falls\nback to a default <empty-state-ui> when not provided.\n"
|
|
149
|
+
},
|
|
150
|
+
"footer": {
|
|
151
|
+
"description": "Optional content below the matrix — e.g. a global Save Changes\nbutton row or fine-print disclaimer. Falls back to nothing.\n"
|
|
152
|
+
},
|
|
153
|
+
"header": {
|
|
154
|
+
"description": "Optional content above the matrix — e.g. a page title, intro\ncopy, or per-page save row. Falls back to nothing when empty.\n"
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
"states": [
|
|
158
|
+
{
|
|
159
|
+
"description": "Default — matrix rendered, ready for interaction.",
|
|
160
|
+
"name": "idle"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"description": "Skeleton overlay while data loads.",
|
|
164
|
+
"attribute": "loading",
|
|
165
|
+
"name": "loading"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"description": "All toggles non-interactive.",
|
|
169
|
+
"attribute": "disabled",
|
|
170
|
+
"name": "disabled"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"description": "No notification types configured.",
|
|
174
|
+
"attribute": "empty",
|
|
175
|
+
"name": "empty"
|
|
176
|
+
}
|
|
177
|
+
],
|
|
178
|
+
"status": "stable",
|
|
179
|
+
"synonyms": {
|
|
180
|
+
"channels": [
|
|
181
|
+
"delivery",
|
|
182
|
+
"destinations"
|
|
183
|
+
],
|
|
184
|
+
"notifications": [
|
|
185
|
+
"alerts",
|
|
186
|
+
"messages",
|
|
187
|
+
"updates"
|
|
188
|
+
],
|
|
189
|
+
"preferences": [
|
|
190
|
+
"settings",
|
|
191
|
+
"opt-ins",
|
|
192
|
+
"subscriptions"
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
"tag": "notification-preferences-ui",
|
|
196
|
+
"tokens": {
|
|
197
|
+
"--notification-preferences-bg": {
|
|
198
|
+
"description": "Host background.",
|
|
199
|
+
"default": "var(--a-bg)"
|
|
200
|
+
},
|
|
201
|
+
"--notification-preferences-border": {
|
|
202
|
+
"description": "Row separator color.",
|
|
203
|
+
"default": "var(--a-border-subtle)"
|
|
204
|
+
},
|
|
205
|
+
"--notification-preferences-channel-width": {
|
|
206
|
+
"description": "Minimum column width for each channel cell.",
|
|
207
|
+
"default": "var(--a-space-9)"
|
|
208
|
+
},
|
|
209
|
+
"--notification-preferences-group-fg": {
|
|
210
|
+
"description": "Group-heading label color.",
|
|
211
|
+
"default": "var(--a-fg-muted)"
|
|
212
|
+
},
|
|
213
|
+
"--notification-preferences-px": {
|
|
214
|
+
"description": "Host horizontal padding.",
|
|
215
|
+
"default": "var(--a-space-5)"
|
|
216
|
+
},
|
|
217
|
+
"--notification-preferences-py": {
|
|
218
|
+
"description": "Host vertical padding.",
|
|
219
|
+
"default": "var(--a-space-5)"
|
|
220
|
+
},
|
|
221
|
+
"--notification-preferences-radius": {
|
|
222
|
+
"description": "Outer matrix container radius.",
|
|
223
|
+
"default": "var(--a-radius-md)"
|
|
224
|
+
},
|
|
225
|
+
"--notification-preferences-row-bg": {
|
|
226
|
+
"description": "Even-row zebra background.",
|
|
227
|
+
"default": "var(--a-bg-muted)"
|
|
228
|
+
},
|
|
229
|
+
"--notification-preferences-row-label-min": {
|
|
230
|
+
"description": "Minimum row-label column width.",
|
|
231
|
+
"default": "12rem"
|
|
232
|
+
},
|
|
233
|
+
"--notification-preferences-row-px": {
|
|
234
|
+
"description": "Per-cell horizontal padding.",
|
|
235
|
+
"default": "var(--a-space-3)"
|
|
236
|
+
},
|
|
237
|
+
"--notification-preferences-row-py": {
|
|
238
|
+
"description": "Per-row vertical padding.",
|
|
239
|
+
"default": "var(--a-space-3)"
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
"traits": [],
|
|
243
|
+
"version": 1
|
|
244
|
+
}
|
|
245
|
+
}
|