@ccheever/exact-facet-core 0.1.0
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/facet-registry.json +548 -0
- package/package.json +22 -0
- package/src/__tests__/facet-overrides.test.ts +91 -0
- package/src/__tests__/theme-definition-resolution.test.ts +235 -0
- package/src/__tests__/theme-store-parity.test.ts +283 -0
- package/src/facet-catalog.ts +75 -0
- package/src/facet-overrides.ts +322 -0
- package/src/facet-params.generated.ts +65 -0
- package/src/facet-scorecard.ts +60 -0
- package/src/index.ts +16 -0
- package/src/internals.ts +1313 -0
- package/src/provenance-trace.ts +153 -0
- package/src/store-machinery.ts +128 -0
- package/src/theme-definition.ts +566 -0
- package/src/theme-store.ts +456 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"name": "Button",
|
|
4
|
+
"aliases": [
|
|
5
|
+
"button"
|
|
6
|
+
],
|
|
7
|
+
"category": "forms",
|
|
8
|
+
"description": "Intentful action control",
|
|
9
|
+
"tier": "core",
|
|
10
|
+
"status": "stable",
|
|
11
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
12
|
+
"sources": {
|
|
13
|
+
"react": "packages/exact-facet/src/index.tsx",
|
|
14
|
+
"contract": "packages/exact-facet-contract/src/components/button.contract"
|
|
15
|
+
},
|
|
16
|
+
"variants": [
|
|
17
|
+
{
|
|
18
|
+
"name": "variant",
|
|
19
|
+
"values": [
|
|
20
|
+
"primary",
|
|
21
|
+
"secondary",
|
|
22
|
+
"ghost"
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"annotations": {
|
|
27
|
+
"targeting": "testId (developer-supplied) or accessibilityRole=\"button\"",
|
|
28
|
+
"verify": "After press, verify the callback fired or state changed.",
|
|
29
|
+
"wait": "none"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "Input",
|
|
34
|
+
"aliases": [
|
|
35
|
+
"input"
|
|
36
|
+
],
|
|
37
|
+
"category": "forms",
|
|
38
|
+
"description": "Text input with Facet chrome",
|
|
39
|
+
"tier": "core",
|
|
40
|
+
"status": "stable",
|
|
41
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
42
|
+
"sources": {
|
|
43
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "Textarea",
|
|
48
|
+
"aliases": [
|
|
49
|
+
"textarea"
|
|
50
|
+
],
|
|
51
|
+
"category": "forms",
|
|
52
|
+
"description": "Multi-line text input with shared Facet chrome",
|
|
53
|
+
"tier": "core",
|
|
54
|
+
"status": "stable",
|
|
55
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
56
|
+
"sources": {
|
|
57
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
58
|
+
},
|
|
59
|
+
"dependencies": [
|
|
60
|
+
"Input"
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "FormField",
|
|
65
|
+
"aliases": [
|
|
66
|
+
"formfield",
|
|
67
|
+
"form-field"
|
|
68
|
+
],
|
|
69
|
+
"category": "forms",
|
|
70
|
+
"description": "Label, description, and validation wrapper for form controls",
|
|
71
|
+
"tier": "core",
|
|
72
|
+
"status": "stable",
|
|
73
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
74
|
+
"sources": {
|
|
75
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
76
|
+
},
|
|
77
|
+
"dependencies": [
|
|
78
|
+
"Input",
|
|
79
|
+
"Label"
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"name": "Card",
|
|
84
|
+
"aliases": [
|
|
85
|
+
"card"
|
|
86
|
+
],
|
|
87
|
+
"category": "layout",
|
|
88
|
+
"description": "Surface container with theme shadow",
|
|
89
|
+
"tier": "core",
|
|
90
|
+
"status": "stable",
|
|
91
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
92
|
+
"sources": {
|
|
93
|
+
"react": "packages/exact-facet/src/index.tsx",
|
|
94
|
+
"contract": "packages/exact-facet-contract/src/components/card.contract"
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"name": "Badge",
|
|
99
|
+
"aliases": [
|
|
100
|
+
"badge"
|
|
101
|
+
],
|
|
102
|
+
"category": "feedback",
|
|
103
|
+
"description": "Compact status chip",
|
|
104
|
+
"tier": "core",
|
|
105
|
+
"status": "stable",
|
|
106
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
107
|
+
"sources": {
|
|
108
|
+
"react": "packages/exact-facet/src/index.tsx",
|
|
109
|
+
"contract": "packages/exact-facet-contract/src/components/badge.contract"
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"name": "Label",
|
|
114
|
+
"aliases": [
|
|
115
|
+
"label"
|
|
116
|
+
],
|
|
117
|
+
"category": "forms",
|
|
118
|
+
"description": "Form label with optional required indicator",
|
|
119
|
+
"tier": "core",
|
|
120
|
+
"status": "stable",
|
|
121
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
122
|
+
"sources": {
|
|
123
|
+
"react": "packages/exact-facet/src/index.tsx",
|
|
124
|
+
"contract": "packages/exact-facet-contract/src/components/label.contract"
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"name": "Separator",
|
|
129
|
+
"aliases": [
|
|
130
|
+
"separator"
|
|
131
|
+
],
|
|
132
|
+
"category": "layout",
|
|
133
|
+
"description": "Low-contrast divider line",
|
|
134
|
+
"tier": "core",
|
|
135
|
+
"status": "stable",
|
|
136
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
137
|
+
"sources": {
|
|
138
|
+
"react": "packages/exact-facet/src/index.tsx",
|
|
139
|
+
"contract": "packages/exact-facet-contract/src/components/separator.contract"
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"name": "Avatar",
|
|
144
|
+
"aliases": [
|
|
145
|
+
"avatar"
|
|
146
|
+
],
|
|
147
|
+
"category": "feedback",
|
|
148
|
+
"description": "Image-backed identity chip with fallback initials",
|
|
149
|
+
"tier": "core",
|
|
150
|
+
"status": "stable",
|
|
151
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
152
|
+
"sources": {
|
|
153
|
+
"react": "packages/exact-facet/src/index.tsx",
|
|
154
|
+
"contract": "packages/exact-facet-contract/src/components/avatar.contract"
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"name": "Skeleton",
|
|
159
|
+
"aliases": [
|
|
160
|
+
"skeleton"
|
|
161
|
+
],
|
|
162
|
+
"category": "feedback",
|
|
163
|
+
"description": "Loading placeholder block",
|
|
164
|
+
"tier": "core",
|
|
165
|
+
"status": "stable",
|
|
166
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
167
|
+
"sources": {
|
|
168
|
+
"react": "packages/exact-facet/src/index.tsx",
|
|
169
|
+
"contract": "packages/exact-facet-contract/src/components/skeleton.contract"
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"name": "Progress",
|
|
174
|
+
"aliases": [
|
|
175
|
+
"progress"
|
|
176
|
+
],
|
|
177
|
+
"category": "feedback",
|
|
178
|
+
"description": "Determinate progress indicator",
|
|
179
|
+
"tier": "core",
|
|
180
|
+
"status": "stable",
|
|
181
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
182
|
+
"sources": {
|
|
183
|
+
"react": "packages/exact-facet/src/index.tsx",
|
|
184
|
+
"contract": "packages/exact-facet-contract/src/components/progress.contract"
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"name": "Spinner",
|
|
189
|
+
"aliases": [
|
|
190
|
+
"spinner"
|
|
191
|
+
],
|
|
192
|
+
"category": "feedback",
|
|
193
|
+
"description": "Indeterminate activity indicator",
|
|
194
|
+
"tier": "core",
|
|
195
|
+
"status": "stable",
|
|
196
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
197
|
+
"sources": {
|
|
198
|
+
"react": "packages/exact-facet/src/index.tsx",
|
|
199
|
+
"contract": "packages/exact-facet-contract/src/components/spinner.contract"
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"name": "Alert",
|
|
204
|
+
"aliases": [
|
|
205
|
+
"alert"
|
|
206
|
+
],
|
|
207
|
+
"category": "feedback",
|
|
208
|
+
"description": "Inline alert surface with live-region semantics",
|
|
209
|
+
"tier": "core",
|
|
210
|
+
"status": "stable",
|
|
211
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
212
|
+
"sources": {
|
|
213
|
+
"react": "packages/exact-facet/src/index.tsx",
|
|
214
|
+
"contract": "packages/exact-facet-contract/src/components/alert.contract"
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"name": "Toggle",
|
|
219
|
+
"aliases": [
|
|
220
|
+
"toggle",
|
|
221
|
+
"switch"
|
|
222
|
+
],
|
|
223
|
+
"category": "forms",
|
|
224
|
+
"description": "Boolean switch control",
|
|
225
|
+
"tier": "core",
|
|
226
|
+
"status": "stable",
|
|
227
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
228
|
+
"sources": {
|
|
229
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"name": "Checkbox",
|
|
234
|
+
"aliases": [
|
|
235
|
+
"checkbox"
|
|
236
|
+
],
|
|
237
|
+
"category": "forms",
|
|
238
|
+
"description": "Boolean checkbox control",
|
|
239
|
+
"tier": "core",
|
|
240
|
+
"status": "stable",
|
|
241
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
242
|
+
"sources": {
|
|
243
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"name": "Slider",
|
|
248
|
+
"aliases": [
|
|
249
|
+
"slider"
|
|
250
|
+
],
|
|
251
|
+
"category": "forms",
|
|
252
|
+
"description": "Continuous numeric input control",
|
|
253
|
+
"tier": "core",
|
|
254
|
+
"status": "stable",
|
|
255
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
256
|
+
"sources": {
|
|
257
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"name": "RadioGroup",
|
|
262
|
+
"aliases": [
|
|
263
|
+
"radiogroup",
|
|
264
|
+
"radio-group"
|
|
265
|
+
],
|
|
266
|
+
"category": "forms",
|
|
267
|
+
"description": "Single-select radio group with roving focus",
|
|
268
|
+
"tier": "core",
|
|
269
|
+
"status": "stable",
|
|
270
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
271
|
+
"sources": {
|
|
272
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"name": "Dialog",
|
|
277
|
+
"aliases": [
|
|
278
|
+
"dialog"
|
|
279
|
+
],
|
|
280
|
+
"category": "overlay",
|
|
281
|
+
"description": "Modal surface with focus layer",
|
|
282
|
+
"tier": "core",
|
|
283
|
+
"status": "stable",
|
|
284
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
285
|
+
"sources": {
|
|
286
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
287
|
+
},
|
|
288
|
+
"dependencies": [
|
|
289
|
+
"Button"
|
|
290
|
+
],
|
|
291
|
+
"annotations": {
|
|
292
|
+
"targeting": "testId=\"facet-dialog-content\" or accessibilityRole=\"dialog\"",
|
|
293
|
+
"verify": "Focus is trapped, the dialog is modal, and outside press dismisses.",
|
|
294
|
+
"wait": "presencePhase=\"entered\""
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"name": "AlertDialog",
|
|
299
|
+
"aliases": [
|
|
300
|
+
"alertdialog",
|
|
301
|
+
"alert-dialog"
|
|
302
|
+
],
|
|
303
|
+
"category": "overlay",
|
|
304
|
+
"description": "High-priority dialog that resists outside dismissal",
|
|
305
|
+
"tier": "core",
|
|
306
|
+
"status": "stable",
|
|
307
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
308
|
+
"sources": {
|
|
309
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
310
|
+
},
|
|
311
|
+
"dependencies": [
|
|
312
|
+
"Dialog",
|
|
313
|
+
"Button"
|
|
314
|
+
]
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
"name": "Sheet",
|
|
318
|
+
"aliases": [
|
|
319
|
+
"sheet"
|
|
320
|
+
],
|
|
321
|
+
"category": "overlay",
|
|
322
|
+
"description": "Edge-anchored panel surface",
|
|
323
|
+
"tier": "core",
|
|
324
|
+
"status": "stable",
|
|
325
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
326
|
+
"sources": {
|
|
327
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
328
|
+
},
|
|
329
|
+
"dependencies": [
|
|
330
|
+
"Dialog"
|
|
331
|
+
]
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
"name": "Accordion",
|
|
335
|
+
"aliases": [
|
|
336
|
+
"accordion"
|
|
337
|
+
],
|
|
338
|
+
"category": "navigation",
|
|
339
|
+
"description": "Expandable disclosure surface with presence-backed content",
|
|
340
|
+
"tier": "core",
|
|
341
|
+
"status": "stable",
|
|
342
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
343
|
+
"sources": {
|
|
344
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
"name": "Collapsible",
|
|
349
|
+
"aliases": [
|
|
350
|
+
"collapsible"
|
|
351
|
+
],
|
|
352
|
+
"category": "navigation",
|
|
353
|
+
"description": "Standalone disclosure primitive with presence-backed content",
|
|
354
|
+
"tier": "core",
|
|
355
|
+
"status": "stable",
|
|
356
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
357
|
+
"sources": {
|
|
358
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
359
|
+
},
|
|
360
|
+
"dependencies": [
|
|
361
|
+
"Accordion"
|
|
362
|
+
]
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
"name": "Tabs",
|
|
366
|
+
"aliases": [
|
|
367
|
+
"tabs"
|
|
368
|
+
],
|
|
369
|
+
"category": "navigation",
|
|
370
|
+
"description": "Segmented tab switcher",
|
|
371
|
+
"tier": "core",
|
|
372
|
+
"status": "stable",
|
|
373
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
374
|
+
"sources": {
|
|
375
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
"name": "Toast",
|
|
380
|
+
"aliases": [
|
|
381
|
+
"toast"
|
|
382
|
+
],
|
|
383
|
+
"category": "feedback",
|
|
384
|
+
"description": "Transient notification surface",
|
|
385
|
+
"tier": "core",
|
|
386
|
+
"status": "stable",
|
|
387
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
388
|
+
"sources": {
|
|
389
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
"name": "Popover",
|
|
394
|
+
"aliases": [
|
|
395
|
+
"popover"
|
|
396
|
+
],
|
|
397
|
+
"category": "overlay",
|
|
398
|
+
"description": "Anchored floating surface",
|
|
399
|
+
"tier": "floating",
|
|
400
|
+
"status": "preview",
|
|
401
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
402
|
+
"sources": {
|
|
403
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
404
|
+
},
|
|
405
|
+
"annotations": {
|
|
406
|
+
"targeting": "testId or accessibilityRole=\"dialog\"",
|
|
407
|
+
"verify": "Floating placement is positioned and dismissable.",
|
|
408
|
+
"wait": "floatingPositioned"
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
"name": "Tooltip",
|
|
413
|
+
"aliases": [
|
|
414
|
+
"tooltip"
|
|
415
|
+
],
|
|
416
|
+
"category": "overlay",
|
|
417
|
+
"description": "Hover/focus hint surface",
|
|
418
|
+
"tier": "floating",
|
|
419
|
+
"status": "preview",
|
|
420
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
421
|
+
"sources": {
|
|
422
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
"name": "DropdownMenu",
|
|
427
|
+
"aliases": [
|
|
428
|
+
"dropdownmenu",
|
|
429
|
+
"dropdown-menu"
|
|
430
|
+
],
|
|
431
|
+
"category": "overlay",
|
|
432
|
+
"description": "Action menu anchored to a trigger",
|
|
433
|
+
"tier": "floating",
|
|
434
|
+
"status": "preview",
|
|
435
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
436
|
+
"sources": {
|
|
437
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
438
|
+
},
|
|
439
|
+
"dependencies": [
|
|
440
|
+
"Popover"
|
|
441
|
+
]
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
"name": "Select",
|
|
445
|
+
"aliases": [
|
|
446
|
+
"select"
|
|
447
|
+
],
|
|
448
|
+
"category": "forms",
|
|
449
|
+
"description": "Single-select floating listbox",
|
|
450
|
+
"tier": "floating",
|
|
451
|
+
"status": "preview",
|
|
452
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
453
|
+
"sources": {
|
|
454
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
455
|
+
},
|
|
456
|
+
"dependencies": [
|
|
457
|
+
"DropdownMenu"
|
|
458
|
+
],
|
|
459
|
+
"annotations": {
|
|
460
|
+
"targeting": "testId or accessibilityRole=\"combobox\"",
|
|
461
|
+
"verify": "Expanded state is true after opening and a new value is selected.",
|
|
462
|
+
"wait": "floatingPositioned"
|
|
463
|
+
}
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
"name": "Combobox",
|
|
467
|
+
"aliases": [
|
|
468
|
+
"combobox"
|
|
469
|
+
],
|
|
470
|
+
"category": "forms",
|
|
471
|
+
"description": "Searchable single-select field with filtering",
|
|
472
|
+
"tier": "floating",
|
|
473
|
+
"status": "stable",
|
|
474
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
475
|
+
"sources": {
|
|
476
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
477
|
+
},
|
|
478
|
+
"dependencies": [
|
|
479
|
+
"Select",
|
|
480
|
+
"Input",
|
|
481
|
+
"Popover"
|
|
482
|
+
],
|
|
483
|
+
"annotations": {
|
|
484
|
+
"targeting": "testId or accessibilityRole=\"combobox\"",
|
|
485
|
+
"verify": "Typing filters the listbox and Enter or tap selects the highlighted option.",
|
|
486
|
+
"wait": "floatingPositioned"
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
"name": "Command",
|
|
491
|
+
"aliases": [
|
|
492
|
+
"command",
|
|
493
|
+
"command-palette"
|
|
494
|
+
],
|
|
495
|
+
"category": "overlay",
|
|
496
|
+
"description": "Searchable command palette with grouped actions",
|
|
497
|
+
"tier": "core",
|
|
498
|
+
"status": "stable",
|
|
499
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
500
|
+
"sources": {
|
|
501
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
502
|
+
},
|
|
503
|
+
"dependencies": [
|
|
504
|
+
"Dialog",
|
|
505
|
+
"Input"
|
|
506
|
+
],
|
|
507
|
+
"annotations": {
|
|
508
|
+
"targeting": "testId=\"facet-command\" or accessibilityRole=\"dialog\"",
|
|
509
|
+
"verify": "Typing filters the action list and Enter triggers the active command.",
|
|
510
|
+
"wait": "presencePhase=\"entered\""
|
|
511
|
+
}
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
"name": "Table",
|
|
515
|
+
"aliases": [
|
|
516
|
+
"table"
|
|
517
|
+
],
|
|
518
|
+
"category": "data",
|
|
519
|
+
"description": "Semantic data table with sortable headers",
|
|
520
|
+
"tier": "core",
|
|
521
|
+
"status": "stable",
|
|
522
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
523
|
+
"sources": {
|
|
524
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
525
|
+
},
|
|
526
|
+
"dependencies": [
|
|
527
|
+
"Card"
|
|
528
|
+
]
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
"name": "ContextMenu",
|
|
532
|
+
"aliases": [
|
|
533
|
+
"contextmenu",
|
|
534
|
+
"context-menu"
|
|
535
|
+
],
|
|
536
|
+
"category": "overlay",
|
|
537
|
+
"description": "Secondary-action menu",
|
|
538
|
+
"tier": "floating",
|
|
539
|
+
"status": "preview",
|
|
540
|
+
"sourceFilePath": "packages/exact-facet/src/index.tsx",
|
|
541
|
+
"sources": {
|
|
542
|
+
"react": "packages/exact-facet/src/index.tsx"
|
|
543
|
+
},
|
|
544
|
+
"dependencies": [
|
|
545
|
+
"DropdownMenu"
|
|
546
|
+
]
|
|
547
|
+
}
|
|
548
|
+
]
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ccheever/exact-facet-core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Framework-neutral heart of the Facet design system: tokens, themes, recipes, motion, color math, catalog metadata, and the consolidated theme store (LLP 0157 F0)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.ts",
|
|
7
|
+
"types": "src/index.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./src/index.ts",
|
|
11
|
+
"types": "./src/index.ts"
|
|
12
|
+
},
|
|
13
|
+
"./store-machinery": {
|
|
14
|
+
"import": "./src/store-machinery.ts",
|
|
15
|
+
"types": "./src/store-machinery.ts"
|
|
16
|
+
},
|
|
17
|
+
"./facet-registry.json": "./facet-registry.json"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@exact/core": "npm:@ccheever/exact-core@0.1.0"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/// <reference path="../../../../js/src/types/bun-test.d.ts" />
|
|
2
|
+
// Design Mode D1 (LLP 0158 §6.2): override-layer fixtures — resolver
|
|
3
|
+
// precedence (variant → base → default), token rebinds through the live
|
|
4
|
+
// theme, app-theme layering below scope/agent overrides, and sentinel
|
|
5
|
+
// tracing staying exact under rebinding.
|
|
6
|
+
|
|
7
|
+
import { afterEach, describe, expect, it } from 'bun:test';
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
_resetFacetOverridesForTests,
|
|
11
|
+
createTracingTheme,
|
|
12
|
+
darkTheme,
|
|
13
|
+
resolveRecipeParam,
|
|
14
|
+
resolveThemeForConfig,
|
|
15
|
+
setAppThemeOverrides,
|
|
16
|
+
setFacetParamOverrides,
|
|
17
|
+
traceStyleOrigins,
|
|
18
|
+
type FacetTheme,
|
|
19
|
+
} from '../index.js';
|
|
20
|
+
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
_resetFacetOverridesForTests();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('facet overrides layer (LLP 0158 D1 fixtures)', () => {
|
|
26
|
+
it('resolves override(variant) → override(base) → recipe default', () => {
|
|
27
|
+
setFacetParamOverrides({
|
|
28
|
+
FacetButton: {
|
|
29
|
+
base: { paddingX: 10 },
|
|
30
|
+
variants: { primary: { paddingX: 24 } },
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
expect(resolveRecipeParam(darkTheme, 'FacetButton', 'primary', 'paddingX', darkTheme.space.md)).toBe(24);
|
|
34
|
+
expect(resolveRecipeParam(darkTheme, 'FacetButton', 'secondary', 'paddingX', darkTheme.space.md)).toBe(10);
|
|
35
|
+
expect(resolveRecipeParam(darkTheme, 'FacetButton', 'primary', 'paddingY', darkTheme.space.xs)).toBe(
|
|
36
|
+
darkTheme.space.xs,
|
|
37
|
+
);
|
|
38
|
+
expect(resolveRecipeParam(darkTheme, 'FacetCard', null, 'padding', darkTheme.space.lg)).toBe(
|
|
39
|
+
darkTheme.space.lg,
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('token rebinds resolve through the live theme', () => {
|
|
44
|
+
setFacetParamOverrides({
|
|
45
|
+
FacetButton: { base: { radius: { token: 'radius.page' } } },
|
|
46
|
+
});
|
|
47
|
+
expect(resolveRecipeParam(darkTheme, 'FacetButton', 'primary', 'radius', darkTheme.radius.element)).toBe(
|
|
48
|
+
darkTheme.radius.page,
|
|
49
|
+
);
|
|
50
|
+
// Unresolvable rebind falls back to the default, never undefined.
|
|
51
|
+
setFacetParamOverrides({
|
|
52
|
+
FacetButton: { base: { radius: { token: 'radius.doesNotExist' } } },
|
|
53
|
+
});
|
|
54
|
+
expect(resolveRecipeParam(darkTheme, 'FacetButton', 'primary', 'radius', darkTheme.radius.element)).toBe(
|
|
55
|
+
darkTheme.radius.element,
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('app theme overrides merge above base, below scope overrides', () => {
|
|
60
|
+
setAppThemeOverrides({ color: { accent: { fill: '#0000aa' } }, space: { md: 99 } });
|
|
61
|
+
const resolved = resolveThemeForConfig({ scheme: 'dark' });
|
|
62
|
+
expect(resolved.color.accent.fill).toBe('#0000aa');
|
|
63
|
+
expect(resolved.space.md).toBe(99);
|
|
64
|
+
// Scope overrides beat the app file (a provider's explicit choice wins).
|
|
65
|
+
const scoped = resolveThemeForConfig({ scheme: 'dark', overrides: { color: { accent: { fill: '#cc0000' } } } });
|
|
66
|
+
expect(scoped.color.accent.fill).toBe('#cc0000');
|
|
67
|
+
expect(scoped.space.md).toBe(99);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('sentinel tracing stays exact under a token rebind', () => {
|
|
71
|
+
setFacetParamOverrides({
|
|
72
|
+
FacetButton: { variants: { primary: { radius: { token: 'radius.page' } } } },
|
|
73
|
+
});
|
|
74
|
+
const recipe = (theme: FacetTheme, variant: string) => ({
|
|
75
|
+
borderRadius: resolveRecipeParam(theme, 'FacetButton', variant, 'radius', theme.radius.element),
|
|
76
|
+
});
|
|
77
|
+
const origins = traceStyleOrigins(recipe, [darkTheme, 'primary']);
|
|
78
|
+
// The traced origin is the REBOUND token, not the default.
|
|
79
|
+
expect(origins!.borderRadius).toEqual({ kind: 'token', tokenPath: 'radius.page' });
|
|
80
|
+
// A literal override reports computed, never a wrong token.
|
|
81
|
+
setFacetParamOverrides({ FacetButton: { variants: { primary: { radius: 14 } } } });
|
|
82
|
+
const literalOrigins = traceStyleOrigins(recipe, [darkTheme, 'primary']);
|
|
83
|
+
expect(literalOrigins!.borderRadius).toEqual({ kind: 'computed' });
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('createTracingTheme twin round-trips through the resolver fallback path', () => {
|
|
87
|
+
const handle = createTracingTheme(darkTheme);
|
|
88
|
+
const value = resolveRecipeParam(handle.theme, 'FacetButton', 'primary', 'paddingX', handle.theme.space.md);
|
|
89
|
+
expect(handle.resolve(value)).toBe('space.md');
|
|
90
|
+
});
|
|
91
|
+
});
|