@astryxdesign/core 0.7.2-canary.fdd384f → 0.7.2
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 +156 -2
- package/README.md +4 -4
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +8 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +4 -1
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +1 -0
- package/dist/CheckboxList/CheckboxList.d.ts +1 -1
- package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxList.js +6 -2
- package/dist/DropdownMenu/DropdownMenu.d.ts +1 -1
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +38 -110
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +1 -1
- package/dist/DropdownMenu/DropdownMenuGroup.d.ts +6 -4
- package/dist/DropdownMenu/DropdownMenuGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuGroup.js +4 -3
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +1 -1
- package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts +24 -0
- package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts.map +1 -0
- package/dist/DropdownMenu/lazyMenuBottomSheet.js +46 -0
- package/dist/DropdownMenu/menuRegionStops.d.ts +38 -0
- package/dist/DropdownMenu/menuRegionStops.d.ts.map +1 -0
- package/dist/DropdownMenu/menuRegionStops.js +131 -0
- package/dist/FormLayout/FormLayout.d.ts +5 -4
- package/dist/FormLayout/FormLayout.d.ts.map +1 -1
- package/dist/FormLayout/FormLayout.js +1 -1
- package/dist/FormLayout/FormLayoutContext.d.ts +3 -3
- package/dist/FormLayout/FormLayoutContext.js +3 -3
- package/dist/Grid/Grid.d.ts +8 -7
- package/dist/Grid/Grid.d.ts.map +1 -1
- package/dist/Grid/Grid.js +5 -4
- package/dist/Grid/GridSpan.d.ts +1 -1
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +8 -2
- package/dist/Markdown/plugins/headingLinks.d.ts.map +1 -1
- package/dist/Markdown/plugins/headingLinks.js +9 -1
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +5 -0
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +45 -11
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +6 -2
- package/dist/Token/Token.js +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +2 -0
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +2 -0
- package/dist/astryx.css +1 -1
- package/dist/reset.a11y.chromium.spec.js +50 -1
- package/docs.mjs +4 -4
- package/package.json +4 -4
- package/scripts/agent-doc-state.mjs +66 -6
- package/scripts/postinstall.mjs +44 -3
- package/src/Avatar/Avatar.tsx +11 -2
- package/src/AvatarGroup/AvatarGroupOverflow.test.tsx +24 -1
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +2 -0
- package/src/Chat/ChatLayoutScrollButton.test.tsx +13 -0
- package/src/Chat/ChatLayoutScrollButton.tsx +4 -2
- package/src/Chat/__tests__/ChatLayoutScrollButton.a11y.chromium.spec.ts +64 -19
- package/src/CheckboxList/CheckboxList.fr10.test.tsx +29 -2
- package/src/CheckboxList/CheckboxList.tsx +4 -1
- package/src/Code/Code.doc.mjs +1 -0
- package/src/CommandPalette/CommandPalette.doc.mjs +2 -0
- package/src/ContextMenu/ContextMenu.test.tsx +12 -2
- package/src/Drawer/Drawer.doc.mjs +1 -0
- package/src/DropdownMenu/DropdownMenu.ssr.test.tsx +57 -0
- package/src/DropdownMenu/DropdownMenu.test.tsx +17 -5
- package/src/DropdownMenu/DropdownMenu.tsx +43 -142
- package/src/DropdownMenu/DropdownMenuCheckboxItem.doc.mjs +1 -1
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +1 -1
- package/src/DropdownMenu/DropdownMenuGroup.doc.mjs +169 -10
- package/src/DropdownMenu/DropdownMenuGroup.tsx +6 -4
- package/src/DropdownMenu/DropdownMenuLazySheet.test.tsx +126 -0
- package/src/DropdownMenu/DropdownMenuRadioItem.doc.mjs +1 -1
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +1 -1
- package/src/DropdownMenu/__tests__/DropdownMenuGroupAudit.a11y.chromium.spec.ts +334 -0
- package/src/DropdownMenu/__tests__/warmMenuBottomSheet.tsx +43 -0
- package/src/DropdownMenu/lazyMenuBottomSheet.ts +71 -0
- package/src/DropdownMenu/menuRegionStops.ts +167 -0
- package/src/Field/FieldLabel.doc.mjs +133 -26
- package/src/Field/FieldLabel.spec.md +172 -0
- package/src/Field/__tests__/FieldLabelAudit.a11y.chromium.spec.ts +296 -0
- package/src/FormLayout/FormLayout.doc.mjs +6 -3
- package/src/FormLayout/FormLayout.spec.md +192 -0
- package/src/FormLayout/FormLayout.test.tsx +15 -0
- package/src/FormLayout/FormLayout.tsx +7 -6
- package/src/FormLayout/FormLayoutContext.ts +3 -3
- package/src/Grid/Grid.doc.mjs +7 -1
- package/src/Grid/Grid.spec.md +93 -113
- package/src/Grid/Grid.test.tsx +22 -0
- package/src/Grid/Grid.tsx +10 -9
- package/src/Grid/GridSpan.doc.mjs +3 -3
- package/src/Grid/GridSpan.tsx +1 -1
- package/src/Icon/Icon.doc.mjs +36 -0
- package/src/Indicator/Indicator.doc.mjs +3 -3
- package/src/Layout/LayoutHeader.doc.mjs +5 -0
- package/src/Markdown/parser.ts +8 -2
- package/src/Markdown/plugins/headingLinks.ts +9 -1
- package/src/MetadataList/MetadataList.doc.mjs +1 -1
- package/src/MoreMenu/MoreMenu.test.tsx +5 -1
- package/src/PowerSearch/PowerSearch.test.tsx +62 -0
- package/src/PowerSearch/PowerSearch.tsx +9 -0
- package/src/PowerSearch/PowerSearchValueEditor.test.tsx +71 -0
- package/src/PowerSearch/PowerSearchValueEditor.tsx +45 -0
- package/src/ProgressBar/ProgressBar.doc.mjs +1 -0
- package/src/Resizable/useResizable.doc.mjs +2 -0
- package/src/ScrollableArea/ScrollableArea.doc.mjs +1 -1
- package/src/SideNav/SideNav.spec.md +227 -0
- package/src/SideNav/SideNav.test.tsx +41 -0
- package/src/SideNav/SideNavItem.tsx +5 -2
- package/src/Spinner/Spinner.doc.mjs +1 -1
- package/src/Table/Table.spec.md +6 -1
- package/src/Table/plugins/activation/useTableActivation.spec.md +254 -0
- package/src/Timestamp/Timestamp.doc.mjs +1 -1
- package/src/ToggleButton/ToggleButtonGroup.doc.mjs +4 -0
- package/src/Token/Token.tsx +1 -1
- package/src/Token/__tests__/TokenRemoveTarget.a11y.chromium.spec.ts +86 -0
- package/src/Toolbar/Toolbar.test.tsx +0 -8
- package/src/Toolbar/__tests__/Toolbar.a11y.chromium.spec.ts +163 -0
- package/src/Toolbar/__tests__/Toolbar.a11y.renders.tsx +63 -0
- package/src/Toolbar/__tests__/Toolbar.a11y.states.ts +142 -0
- package/src/Toolbar/__tests__/Toolbar.a11y.test.tsx +126 -0
- package/src/TopNav/TopNavMegaMenu.test.tsx +25 -0
- package/src/TopNav/TopNavMegaMenu.tsx +2 -0
- package/src/TopNav/TopNavMenu.test.tsx +27 -1
- package/src/TopNav/TopNavMenu.tsx +2 -0
- package/src/postinstall.test.mjs +79 -0
- package/src/reset.a11y.chromium.spec.ts +52 -1
- package/src/reset.css +9 -0
- package/src/reset.test.ts +11 -0
- package/src/unicodePropertyEscapes.source-build.test.mjs +69 -0
|
@@ -59,7 +59,8 @@ function StringEditor({
|
|
|
59
59
|
filterValue,
|
|
60
60
|
onChange,
|
|
61
61
|
onEnter: _onEnter,
|
|
62
|
-
maxMenuItems
|
|
62
|
+
maxMenuItems,
|
|
63
|
+
isDisabled
|
|
63
64
|
}) {
|
|
64
65
|
const t = useTranslator();
|
|
65
66
|
const currentValue = filterValue?.type === 'string' ? filterValue.value : '';
|
|
@@ -74,6 +75,7 @@ function StringEditor({
|
|
|
74
75
|
return /*#__PURE__*/_jsx(Typeahead, {
|
|
75
76
|
label: t('@astryx.powersearch.valueEditor.value'),
|
|
76
77
|
isLabelHidden: true,
|
|
78
|
+
isDisabled: isDisabled,
|
|
77
79
|
searchSource: operatorValue.searchSource,
|
|
78
80
|
value: selectedItem,
|
|
79
81
|
onChange: item => {
|
|
@@ -97,6 +99,7 @@ function StringEditor({
|
|
|
97
99
|
return /*#__PURE__*/_jsx(TextInput, {
|
|
98
100
|
label: t('@astryx.powersearch.valueEditor.value'),
|
|
99
101
|
isLabelHidden: true,
|
|
102
|
+
isDisabled: isDisabled,
|
|
100
103
|
value: currentValue,
|
|
101
104
|
placeholder: t('@astryx.powersearch.valueEditor.enterValuePlaceholder'),
|
|
102
105
|
onChange: value => {
|
|
@@ -111,7 +114,8 @@ function StringListEditor({
|
|
|
111
114
|
operatorValue,
|
|
112
115
|
filterValue,
|
|
113
116
|
onChange,
|
|
114
|
-
maxMenuItems
|
|
117
|
+
maxMenuItems,
|
|
118
|
+
isDisabled
|
|
115
119
|
}) {
|
|
116
120
|
const t = useTranslator();
|
|
117
121
|
const currentValue = useMemo(() => {
|
|
@@ -140,6 +144,7 @@ function StringListEditor({
|
|
|
140
144
|
return /*#__PURE__*/_jsx(Tokenizer, {
|
|
141
145
|
label: t('@astryx.powersearch.valueEditor.values'),
|
|
142
146
|
isLabelHidden: true,
|
|
147
|
+
isDisabled: isDisabled,
|
|
143
148
|
searchSource: source,
|
|
144
149
|
value: currentValue,
|
|
145
150
|
onChange: items => {
|
|
@@ -212,7 +217,8 @@ function IntegerEditor({
|
|
|
212
217
|
operatorValue,
|
|
213
218
|
filterValue,
|
|
214
219
|
onChange,
|
|
215
|
-
onEnter
|
|
220
|
+
onEnter,
|
|
221
|
+
isDisabled
|
|
216
222
|
}) {
|
|
217
223
|
const t = useTranslator();
|
|
218
224
|
const currentValue = filterValue?.type === 'integer' ? filterValue.value : undefined;
|
|
@@ -227,6 +233,7 @@ function IntegerEditor({
|
|
|
227
233
|
return /*#__PURE__*/_jsx(NumberInput, {
|
|
228
234
|
label: t('@astryx.powersearch.valueEditor.value'),
|
|
229
235
|
isLabelHidden: true,
|
|
236
|
+
isDisabled: isDisabled,
|
|
230
237
|
value: currentValue ?? null,
|
|
231
238
|
onChange: handlers.handleChange,
|
|
232
239
|
onFocus: handlers.handleFocus,
|
|
@@ -244,7 +251,8 @@ function FloatEditor({
|
|
|
244
251
|
operatorValue,
|
|
245
252
|
filterValue,
|
|
246
253
|
onChange,
|
|
247
|
-
onEnter
|
|
254
|
+
onEnter,
|
|
255
|
+
isDisabled
|
|
248
256
|
}) {
|
|
249
257
|
const t = useTranslator();
|
|
250
258
|
const currentValue = filterValue?.type === 'float' ? filterValue.value : undefined;
|
|
@@ -259,6 +267,7 @@ function FloatEditor({
|
|
|
259
267
|
return /*#__PURE__*/_jsx(NumberInput, {
|
|
260
268
|
label: t('@astryx.powersearch.valueEditor.value'),
|
|
261
269
|
isLabelHidden: true,
|
|
270
|
+
isDisabled: isDisabled,
|
|
262
271
|
value: currentValue ?? null,
|
|
263
272
|
onChange: handlers.handleChange,
|
|
264
273
|
onFocus: handlers.handleFocus,
|
|
@@ -274,13 +283,15 @@ function FloatEditor({
|
|
|
274
283
|
function TimeEditor({
|
|
275
284
|
operatorValue,
|
|
276
285
|
filterValue,
|
|
277
|
-
onChange
|
|
286
|
+
onChange,
|
|
287
|
+
isDisabled
|
|
278
288
|
}) {
|
|
279
289
|
const t = useTranslator();
|
|
280
290
|
const currentValue = filterValue?.type === 'time' ? filterValue.value : undefined;
|
|
281
291
|
return /*#__PURE__*/_jsx(TimeInput, {
|
|
282
292
|
label: t('@astryx.powersearch.valueEditor.time'),
|
|
283
293
|
isLabelHidden: true,
|
|
294
|
+
isDisabled: isDisabled,
|
|
284
295
|
value: currentValue,
|
|
285
296
|
onChange: value => {
|
|
286
297
|
if (value != null) {
|
|
@@ -296,7 +307,8 @@ function TimeEditor({
|
|
|
296
307
|
}
|
|
297
308
|
function DateAbsoluteEditor({
|
|
298
309
|
filterValue,
|
|
299
|
-
onChange
|
|
310
|
+
onChange,
|
|
311
|
+
isDisabled
|
|
300
312
|
}) {
|
|
301
313
|
const t = useTranslator();
|
|
302
314
|
// Convert unixSeconds to ISO date string for the date input
|
|
@@ -310,6 +322,7 @@ function DateAbsoluteEditor({
|
|
|
310
322
|
return /*#__PURE__*/_jsx(DateInput, {
|
|
311
323
|
label: t('@astryx.powersearch.valueEditor.date'),
|
|
312
324
|
isLabelHidden: true,
|
|
325
|
+
isDisabled: isDisabled,
|
|
313
326
|
value: currentValue,
|
|
314
327
|
onChange: value => {
|
|
315
328
|
if (value != null) {
|
|
@@ -325,7 +338,8 @@ function DateAbsoluteEditor({
|
|
|
325
338
|
function DateRelativeEditor({
|
|
326
339
|
operatorValue,
|
|
327
340
|
filterValue,
|
|
328
|
-
onChange
|
|
341
|
+
onChange,
|
|
342
|
+
isDisabled
|
|
329
343
|
}) {
|
|
330
344
|
const t = useTranslator();
|
|
331
345
|
const currentValue = filterValue?.type === 'date_relative' ? filterValue.value : undefined;
|
|
@@ -366,6 +380,7 @@ function DateRelativeEditor({
|
|
|
366
380
|
return /*#__PURE__*/_jsx(Selector, {
|
|
367
381
|
label: t('@astryx.powersearch.valueEditor.relativeDate'),
|
|
368
382
|
isLabelHidden: true,
|
|
383
|
+
isDisabled: isDisabled,
|
|
369
384
|
options: options,
|
|
370
385
|
value: currentValue,
|
|
371
386
|
onChange: value => {
|
|
@@ -378,7 +393,8 @@ function DateRelativeEditor({
|
|
|
378
393
|
}
|
|
379
394
|
function DateRangeEditor({
|
|
380
395
|
filterValue,
|
|
381
|
-
onChange
|
|
396
|
+
onChange,
|
|
397
|
+
isDisabled
|
|
382
398
|
}) {
|
|
383
399
|
const t = useTranslator();
|
|
384
400
|
const currentValue = useMemo(() => {
|
|
@@ -425,6 +441,7 @@ function DateRangeEditor({
|
|
|
425
441
|
children: /*#__PURE__*/_jsx(DateRangeInput, {
|
|
426
442
|
label: t('@astryx.powersearch.valueEditor.dateRange'),
|
|
427
443
|
isLabelHidden: true,
|
|
444
|
+
isDisabled: isDisabled,
|
|
428
445
|
value: currentValue,
|
|
429
446
|
onChange: handleChange,
|
|
430
447
|
hasClear: false
|
|
@@ -434,7 +451,8 @@ function DateRangeEditor({
|
|
|
434
451
|
function EnumEditor({
|
|
435
452
|
operatorValue,
|
|
436
453
|
filterValue,
|
|
437
|
-
onChange
|
|
454
|
+
onChange,
|
|
455
|
+
isDisabled
|
|
438
456
|
}) {
|
|
439
457
|
const t = useTranslator();
|
|
440
458
|
const currentValue = filterValue?.type === 'enum' ? filterValue.value : undefined;
|
|
@@ -445,6 +463,7 @@ function EnumEditor({
|
|
|
445
463
|
return /*#__PURE__*/_jsx(Selector, {
|
|
446
464
|
label: t('@astryx.powersearch.valueEditor.value'),
|
|
447
465
|
isLabelHidden: true,
|
|
466
|
+
isDisabled: isDisabled,
|
|
448
467
|
options: options,
|
|
449
468
|
value: currentValue,
|
|
450
469
|
onChange: value => {
|
|
@@ -458,7 +477,8 @@ function EnumEditor({
|
|
|
458
477
|
function EnumListEditor({
|
|
459
478
|
operatorValue,
|
|
460
479
|
filterValue,
|
|
461
|
-
onChange
|
|
480
|
+
onChange,
|
|
481
|
+
isDisabled
|
|
462
482
|
}) {
|
|
463
483
|
const t = useTranslator();
|
|
464
484
|
const items = useMemo(() => enumItemsToSearchableItems(operatorValue.values), [operatorValue.values]);
|
|
@@ -478,6 +498,7 @@ function EnumListEditor({
|
|
|
478
498
|
return /*#__PURE__*/_jsx(Tokenizer, {
|
|
479
499
|
label: t('@astryx.powersearch.valueEditor.values'),
|
|
480
500
|
isLabelHidden: true,
|
|
501
|
+
isDisabled: isDisabled,
|
|
481
502
|
searchSource: source,
|
|
482
503
|
value: currentValue,
|
|
483
504
|
onChange: selectedItems => {
|
|
@@ -500,7 +521,8 @@ function EntityListEditor({
|
|
|
500
521
|
operatorValue,
|
|
501
522
|
filterValue,
|
|
502
523
|
onChange,
|
|
503
|
-
maxMenuItems
|
|
524
|
+
maxMenuItems,
|
|
525
|
+
isDisabled
|
|
504
526
|
}) {
|
|
505
527
|
const t = useTranslator();
|
|
506
528
|
const source = useMemo(() => {
|
|
@@ -529,6 +551,7 @@ function EntityListEditor({
|
|
|
529
551
|
return /*#__PURE__*/_jsx(Tokenizer, {
|
|
530
552
|
label: t('@astryx.powersearch.valueEditor.entities'),
|
|
531
553
|
isLabelHidden: true,
|
|
554
|
+
isDisabled: isDisabled,
|
|
532
555
|
searchSource: source,
|
|
533
556
|
value: currentValue,
|
|
534
557
|
onChange: items => {
|
|
@@ -594,6 +617,7 @@ export function PowerSearchValueEditor({
|
|
|
594
617
|
return null;
|
|
595
618
|
case 'string':
|
|
596
619
|
return /*#__PURE__*/_jsx(StringEditor, {
|
|
620
|
+
isDisabled: isDisabled,
|
|
597
621
|
operatorValue: operatorValue,
|
|
598
622
|
filterValue: filterValue,
|
|
599
623
|
onChange: onChange,
|
|
@@ -602,6 +626,7 @@ export function PowerSearchValueEditor({
|
|
|
602
626
|
});
|
|
603
627
|
case 'string_list':
|
|
604
628
|
return /*#__PURE__*/_jsx(StringListEditor, {
|
|
629
|
+
isDisabled: isDisabled,
|
|
605
630
|
operatorValue: operatorValue,
|
|
606
631
|
filterValue: filterValue,
|
|
607
632
|
onChange: onChange,
|
|
@@ -609,6 +634,7 @@ export function PowerSearchValueEditor({
|
|
|
609
634
|
});
|
|
610
635
|
case 'integer':
|
|
611
636
|
return /*#__PURE__*/_jsx(IntegerEditor, {
|
|
637
|
+
isDisabled: isDisabled,
|
|
612
638
|
operatorValue: operatorValue,
|
|
613
639
|
filterValue: filterValue,
|
|
614
640
|
onChange: onChange,
|
|
@@ -616,6 +642,7 @@ export function PowerSearchValueEditor({
|
|
|
616
642
|
});
|
|
617
643
|
case 'float':
|
|
618
644
|
return /*#__PURE__*/_jsx(FloatEditor, {
|
|
645
|
+
isDisabled: isDisabled,
|
|
619
646
|
operatorValue: operatorValue,
|
|
620
647
|
filterValue: filterValue,
|
|
621
648
|
onChange: onChange,
|
|
@@ -623,42 +650,49 @@ export function PowerSearchValueEditor({
|
|
|
623
650
|
});
|
|
624
651
|
case 'time':
|
|
625
652
|
return /*#__PURE__*/_jsx(TimeEditor, {
|
|
653
|
+
isDisabled: isDisabled,
|
|
626
654
|
operatorValue: operatorValue,
|
|
627
655
|
filterValue: filterValue,
|
|
628
656
|
onChange: onChange
|
|
629
657
|
});
|
|
630
658
|
case 'date_absolute':
|
|
631
659
|
return /*#__PURE__*/_jsx(DateAbsoluteEditor, {
|
|
660
|
+
isDisabled: isDisabled,
|
|
632
661
|
operatorValue: operatorValue,
|
|
633
662
|
filterValue: filterValue,
|
|
634
663
|
onChange: onChange
|
|
635
664
|
});
|
|
636
665
|
case 'date_relative':
|
|
637
666
|
return /*#__PURE__*/_jsx(DateRelativeEditor, {
|
|
667
|
+
isDisabled: isDisabled,
|
|
638
668
|
operatorValue: operatorValue,
|
|
639
669
|
filterValue: filterValue,
|
|
640
670
|
onChange: onChange
|
|
641
671
|
});
|
|
642
672
|
case 'date_range':
|
|
643
673
|
return /*#__PURE__*/_jsx(DateRangeEditor, {
|
|
674
|
+
isDisabled: isDisabled,
|
|
644
675
|
operatorValue: operatorValue,
|
|
645
676
|
filterValue: filterValue,
|
|
646
677
|
onChange: onChange
|
|
647
678
|
});
|
|
648
679
|
case 'enum':
|
|
649
680
|
return /*#__PURE__*/_jsx(EnumEditor, {
|
|
681
|
+
isDisabled: isDisabled,
|
|
650
682
|
operatorValue: operatorValue,
|
|
651
683
|
filterValue: filterValue,
|
|
652
684
|
onChange: onChange
|
|
653
685
|
});
|
|
654
686
|
case 'enum_list':
|
|
655
687
|
return /*#__PURE__*/_jsx(EnumListEditor, {
|
|
688
|
+
isDisabled: isDisabled,
|
|
656
689
|
operatorValue: operatorValue,
|
|
657
690
|
filterValue: filterValue,
|
|
658
691
|
onChange: onChange
|
|
659
692
|
});
|
|
660
693
|
case 'entity_list':
|
|
661
694
|
return /*#__PURE__*/_jsx(EntityListEditor, {
|
|
695
|
+
isDisabled: isDisabled,
|
|
662
696
|
operatorValue: operatorValue,
|
|
663
697
|
filterValue: filterValue,
|
|
664
698
|
onChange: onChange,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SideNavItem.d.ts","sourceRoot":"","sources":["../../src/SideNav/SideNavItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAYf,OAAO,EAAuB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAE5D,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAIrD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAgB,KAAK,WAAW,EAAC,MAAM,iCAAiC,CAAC;AA4ShF,MAAM,WAAW,gBAAiB,SAAQ,SAAS,CAAC,WAAW,CAAC;IAC9D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;;;OAIG;IACH,EAAE,CAAC,EAAE,iBAAiB,CAAC;IACvB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B;;OAEG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACpC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACxC;;;;OAIG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EACR,OAAO,GACP;QACE,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,KAAK,IAAI,CAAC;KACpD,CAAC;IACN;;;OAGG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,WAAW,CAAC,EAC1B,EAAE,EACF,KAAK,EACL,IAAI,EACJ,YAAY,EACZ,UAAkB,EAClB,UAAkB,EAClB,IAAI,EACJ,OAAO,EACP,UAAU,EACV,OAAO,EACP,QAAQ,EACR,WAAW,EAAE,eAAe,EAC5B,IAAW,EACX,aAAa,EAAE,MAAM,EACrB,GAAG,EACH,MAAM,EACN,GAAG,IAAI,EACR,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"SideNavItem.d.ts","sourceRoot":"","sources":["../../src/SideNav/SideNavItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAYf,OAAO,EAAuB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAE5D,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAIrD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAgB,KAAK,WAAW,EAAC,MAAM,iCAAiC,CAAC;AA4ShF,MAAM,WAAW,gBAAiB,SAAQ,SAAS,CAAC,WAAW,CAAC;IAC9D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;;;OAIG;IACH,EAAE,CAAC,EAAE,iBAAiB,CAAC;IACvB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B;;OAEG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACpC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACxC;;;;OAIG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EACR,OAAO,GACP;QACE,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,KAAK,IAAI,CAAC;KACpD,CAAC;IACN;;;OAGG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,WAAW,CAAC,EAC1B,EAAE,EACF,KAAK,EACL,IAAI,EACJ,YAAY,EACZ,UAAkB,EAClB,UAAkB,EAClB,IAAI,EACJ,OAAO,EACP,UAAU,EACV,OAAO,EACP,QAAQ,EACR,WAAW,EAAE,eAAe,EAC5B,IAAW,EACX,aAAa,EAAE,MAAM,EACrB,GAAG,EACH,MAAM,EACN,GAAG,IAAI,EACR,EAAE,gBAAgB,sCAqalB;yBAvbe,WAAW"}
|
|
@@ -405,7 +405,9 @@ export function SideNavItem({
|
|
|
405
405
|
size,
|
|
406
406
|
selected: isSelected ? 'selected' : null,
|
|
407
407
|
disabled: isDisabled ? 'disabled' : null
|
|
408
|
-
}), focusOutlineProps.focusVisible(navItemStyles.item, interactionOverlayStyles.backgroundColor, navItemStyles[size], styles.itemCollapsed, size === 'sm' && styles.itemCollapsedSm, size === 'lg' && styles.itemCollapsedLg, isSelected && navItemStyles.selected, isDisabled && navItemStyles.disabled)
|
|
408
|
+
}), focusOutlineProps.focusVisible(navItemStyles.item, interactionOverlayStyles.backgroundColor, navItemStyles[size], styles.itemCollapsed, size === 'sm' && styles.itemCollapsedSm, size === 'lg' && styles.itemCollapsedLg, isSelected && navItemStyles.selected, isDisabled && navItemStyles.disabled),
|
|
409
|
+
// Spread after `rest`, so keep the caller's class beside these.
|
|
410
|
+
rest.className),
|
|
409
411
|
...pressable
|
|
410
412
|
};
|
|
411
413
|
const collapsedAccessibleLabel = rest['aria-label'] != null && rest['aria-label'].trim() !== '' ? rest['aria-label'] : label;
|
|
@@ -512,8 +514,10 @@ export function SideNavItem({
|
|
|
512
514
|
|
|
513
515
|
// The indent is a runtime value, so it reaches the element as an inline
|
|
514
516
|
// style. These props are spread after `rest`, so fold the caller's `style`
|
|
515
|
-
// back in (caller wins) rather than letting the indent replace it
|
|
517
|
+
// back in (caller wins) rather than letting the indent replace it, and the
|
|
518
|
+
// caller's `className` beside the row's own classes.
|
|
516
519
|
const callerStyle = {
|
|
520
|
+
className: rest.className,
|
|
517
521
|
style: rest.style
|
|
518
522
|
};
|
|
519
523
|
|
package/dist/Token/Token.js
CHANGED
|
@@ -409,6 +409,8 @@ function DrawerMegaMenu({
|
|
|
409
409
|
})]
|
|
410
410
|
}), /*#__PURE__*/_jsx("div", {
|
|
411
411
|
id: `${menuId}-items`,
|
|
412
|
+
"aria-hidden": !isExpanded,
|
|
413
|
+
inert: !isExpanded ? true : undefined,
|
|
412
414
|
...{
|
|
413
415
|
0: {
|
|
414
416
|
className: "xrvj5dj xihq33y xb3r6kr x6kj92 xd00j3c x1eizr8u xlr8y92"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TopNavMenu.d.ts","sourceRoot":"","sources":["../../src/TopNav/TopNavMenu.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EAKZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AASf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAkN5C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAMD,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IACnE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAE5B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,wBAAgB,UAAU,CAAC,EACzB,GAAG,EACH,KAAK,EACL,KAAK,EACL,KAAW,EACX,SAAe,EACf,MAAM,EACN,SAAS,EACT,KAAK,EACL,OAAO,EAAE,WAAW,EACpB,YAAY,EAAE,gBAAgB,EAC9B,YAAY,EAAE,gBAAgB,EAC9B,GAAG,IAAI,EACR,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"TopNavMenu.d.ts","sourceRoot":"","sources":["../../src/TopNav/TopNavMenu.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EAKZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AASf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAkN5C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAMD,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IACnE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAE5B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,wBAAgB,UAAU,CAAC,EACzB,GAAG,EACH,KAAK,EACL,KAAK,EACL,KAAW,EACX,SAAe,EACf,MAAM,EACN,SAAS,EACT,KAAK,EACL,OAAO,EAAE,WAAW,EACpB,YAAY,EAAE,gBAAgB,EAC9B,YAAY,EAAE,gBAAgB,EAC9B,GAAG,IAAI,EACR,EAAE,eAAe,4BA8QjB;yBA3Re,UAAU"}
|
|
@@ -309,6 +309,8 @@ export function TopNavMenu({
|
|
|
309
309
|
})]
|
|
310
310
|
}), /*#__PURE__*/_jsx("div", {
|
|
311
311
|
id: `${menuId}-items`,
|
|
312
|
+
"aria-hidden": !drawerExpanded,
|
|
313
|
+
inert: !drawerExpanded ? true : undefined,
|
|
312
314
|
...{
|
|
313
315
|
0: {
|
|
314
316
|
className: "xrvj5dj xihq33y xb3r6kr x6kj92 xd00j3c x1eizr8u xlr8y92"
|
package/dist/astryx.css
CHANGED
|
@@ -2077,7 +2077,7 @@
|
|
|
2077
2077
|
.x1bev2v5[data-astryx-press="on"]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){background-image:none}
|
|
2078
2078
|
.x524tya[data-astryx-press="fading"]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){background-image:none}
|
|
2079
2079
|
@starting-style{.x1sopeo2.x1sopeo2:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){grid-template-rows:0fr}}
|
|
2080
|
-
.
|
|
2080
|
+
.xramuyw:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::after{inset:-4px}
|
|
2081
2081
|
.xarstr8:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::after{inset:0}
|
|
2082
2082
|
.xxx281p:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::before{inset:0}
|
|
2083
2083
|
.xht581f:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::after{inset:var(--_input-clear-hit-inset)}
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* @file reset.a11y.chromium.spec.ts
|
|
5
5
|
* @input packages/core/src/reset.css, alone on a blank Chromium page
|
|
6
6
|
* @output Browser evidence that the reset reaches ::before, ::after,
|
|
7
|
-
* ::placeholder
|
|
7
|
+
* ::placeholder, the search field's cancel button and the dropdown marker
|
|
8
|
+
* of a field with a list
|
|
8
9
|
* @position reset.css integration proof. A pseudo-element inside :where() is
|
|
9
10
|
* invalid, and the forgiving list drops it without an error, so only a
|
|
10
11
|
* shipping engine shows which of the reset's rules still match.
|
|
@@ -13,6 +14,8 @@
|
|
|
13
14
|
import * as fs from 'node:fs';
|
|
14
15
|
import { fileURLToPath } from 'node:url';
|
|
15
16
|
import { expect, test } from '@playwright/test';
|
|
17
|
+
// @ts-expect-error -- pngjs ships no declarations; runtime support is pinned.
|
|
18
|
+
import { PNG } from 'pngjs';
|
|
16
19
|
const RESET_CSS = fs.readFileSync(fileURLToPath(new URL('./reset.css', import.meta.url)), 'utf8');
|
|
17
20
|
|
|
18
21
|
// No Astryx CSS is loaded, so --color-text-secondary is undefined and a
|
|
@@ -149,6 +152,52 @@ test('a search field has no cancel button to clear it', async ({
|
|
|
149
152
|
await page.mouse.click(box.x + box.width - 8, box.y + box.height / 2);
|
|
150
153
|
await expect(query).toHaveValue('query');
|
|
151
154
|
});
|
|
155
|
+
test('the dropdown marker of a field with a list sits in its middle', async ({
|
|
156
|
+
page
|
|
157
|
+
}) => {
|
|
158
|
+
// Chromium shows the marker while the pointer is over the field and draws
|
|
159
|
+
// it as a glyph set on the field's line-height, the 1.5 the reset inherits.
|
|
160
|
+
await page.evaluate(() => {
|
|
161
|
+
const field = document.createElement('input');
|
|
162
|
+
field.id = 'fruit';
|
|
163
|
+
field.setAttribute('list', 'fruits');
|
|
164
|
+
const options = document.createElement('datalist');
|
|
165
|
+
options.id = 'fruits';
|
|
166
|
+
options.append(new Option('Apple'));
|
|
167
|
+
document.body.append(field, options);
|
|
168
|
+
});
|
|
169
|
+
await page.addStyleTag({
|
|
170
|
+
content: `
|
|
171
|
+
#fruit {
|
|
172
|
+
display: block;
|
|
173
|
+
width: 240px;
|
|
174
|
+
padding: 7px 11px;
|
|
175
|
+
border: 1px solid;
|
|
176
|
+
line-height: 1.5;
|
|
177
|
+
}
|
|
178
|
+
`
|
|
179
|
+
});
|
|
180
|
+
const field = page.locator('#fruit');
|
|
181
|
+
await field.hover();
|
|
182
|
+
const png = PNG.sync.read(await field.screenshot({
|
|
183
|
+
caret: 'hide'
|
|
184
|
+
}));
|
|
185
|
+
// The marker is the only ink in the field's last 32px, inside the border.
|
|
186
|
+
const inkRows = [];
|
|
187
|
+
for (let y = 2; y < png.height - 2; y++) {
|
|
188
|
+
for (let x = png.width - 32; x < png.width - 2; x++) {
|
|
189
|
+
const offset = (y * png.width + x) * 4;
|
|
190
|
+
const luminance = (png.data[offset] + png.data[offset + 1] + png.data[offset + 2]) / 3;
|
|
191
|
+
if (luminance < 160) {
|
|
192
|
+
inkRows.push(y);
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
expect(inkRows.length, 'the hovered field shows its marker').toBeGreaterThan(0);
|
|
198
|
+
const markerMiddle = (inkRows[0] + inkRows[inkRows.length - 1] + 1) / 2;
|
|
199
|
+
expect(Math.abs(markerMiddle - png.height / 2)).toBeLessThanOrEqual(1);
|
|
200
|
+
});
|
|
152
201
|
test('a later layer and an unlayered rule still override the reset', async ({
|
|
153
202
|
page
|
|
154
203
|
}) => {
|
package/docs.mjs
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* ==========================================================================
|
|
14
14
|
* AI AGENT: do NOT guess component APIs or hand-write CSS. Run:
|
|
15
15
|
* npx @astryxdesign/cli init
|
|
16
|
-
* Use the SCOPED name `@astryxdesign/cli` —
|
|
17
|
-
* unrelated package until the CLI is a dependency. Then, per component:
|
|
16
|
+
* Use the SCOPED name `@astryxdesign/cli` — the unscoped `astryx` resolves to
|
|
17
|
+
* an unrelated npm package until the CLI is a dependency. Then, per component:
|
|
18
18
|
* npx @astryxdesign/cli component <Name>
|
|
19
19
|
* npx @astryxdesign/cli component --list
|
|
20
20
|
* ==========================================================================
|
|
@@ -27,8 +27,8 @@ const BANNER = `
|
|
|
27
27
|
|
|
28
28
|
npx @astryxdesign/cli init
|
|
29
29
|
|
|
30
|
-
(Use the scoped name @astryxdesign/cli.
|
|
31
|
-
unrelated package until the CLI is installed as a dependency.)
|
|
30
|
+
(Use the scoped name @astryxdesign/cli. The unscoped name astryx resolves
|
|
31
|
+
to an unrelated npm package until the CLI is installed as a dependency.)
|
|
32
32
|
|
|
33
33
|
init writes the full component guide, page templates, design rules & tokens
|
|
34
34
|
into your AGENTS.md / CLAUDE.md. Then, for any component:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/core",
|
|
3
|
-
"version": "0.7.2
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"displayName": "Astryx Core",
|
|
5
5
|
"description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -792,8 +792,6 @@
|
|
|
792
792
|
"react-dom": ">=19.0.0"
|
|
793
793
|
},
|
|
794
794
|
"devDependencies": {
|
|
795
|
-
"@astryxdesign/a11y-spec": "0.7.2-canary.fdd384f",
|
|
796
|
-
"@astryxdesign/cli": "0.7.2-canary.fdd384f",
|
|
797
795
|
"@babel/cli": "^7.29.7",
|
|
798
796
|
"@babel/core": "^7.29.7",
|
|
799
797
|
"@babel/preset-react": "^7.29.7",
|
|
@@ -804,7 +802,9 @@
|
|
|
804
802
|
"@testing-library/jest-dom": "^6.6.0",
|
|
805
803
|
"@testing-library/react": "^16.3.2",
|
|
806
804
|
"@types/babel__core": "^7.20.5",
|
|
807
|
-
"tailwindcss": "^4.3.2"
|
|
805
|
+
"tailwindcss": "^4.3.2",
|
|
806
|
+
"@astryxdesign/a11y-spec": "0.0.0",
|
|
807
|
+
"@astryxdesign/cli": "0.7.2"
|
|
808
808
|
},
|
|
809
809
|
"dependencies": {
|
|
810
810
|
"intl-messageformat": "^11.2.9"
|
|
@@ -107,15 +107,75 @@ export function isAstryxInitialized(targetDir = process.cwd()) {
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
/**
|
|
110
|
-
*
|
|
111
|
-
* (core) and layer 2 (cli) can never word it differently.
|
|
110
|
+
* Does an agent working in `startDir` already have the Astryx prompt in reach?
|
|
112
111
|
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
112
|
+
* Coding agents read the agent docs between the repository root and the folder
|
|
113
|
+
* they work in. So inside a git repository, init's block in any folder from
|
|
114
|
+
* `startDir` up to the repository root counts: a workspace package of a
|
|
115
|
+
* monorepo initialized at its root is set up. Outside a repository only
|
|
116
|
+
* `startDir` itself is checked, as {@link isAstryxInitialized} does. Both the
|
|
117
|
+
* per-command nudge and the postinstall nudges ask this.
|
|
118
|
+
*
|
|
119
|
+
* @param {string} [startDir=process.cwd()]
|
|
120
|
+
* @returns {boolean}
|
|
121
|
+
*/
|
|
122
|
+
export function isAstryxPromptInReach(startDir = process.cwd()) {
|
|
123
|
+
const start = path.resolve(startDir);
|
|
124
|
+
const repositoryRoot = findRepositoryRoot(start);
|
|
125
|
+
if (!repositoryRoot) return isAstryxInitialized(start);
|
|
126
|
+
for (let dir = start; ; dir = path.dirname(dir)) {
|
|
127
|
+
if (isAstryxInitialized(dir)) return true;
|
|
128
|
+
if (dir === repositoryRoot) return false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* The nearest folder at or above `start` that holds `.git` (a folder, or the
|
|
134
|
+
* file a worktree uses), or null outside a repository.
|
|
135
|
+
* @param {string} start
|
|
136
|
+
* @returns {string | null}
|
|
137
|
+
*/
|
|
138
|
+
function findRepositoryRoot(start) {
|
|
139
|
+
for (let dir = start; ; ) {
|
|
140
|
+
if (fs.existsSync(path.join(dir, '.git'))) return dir;
|
|
141
|
+
const parent = path.dirname(dir);
|
|
142
|
+
if (parent === dir) return null;
|
|
143
|
+
dir = parent;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* The invocation the setup nudge falls back to when the CLI's picker
|
|
149
|
+
* (`getCliInvocation`) cannot be loaded. Scoped package form
|
|
150
|
+
* (`@astryxdesign/cli`) — always resolves to us, even before the CLI is
|
|
151
|
+
* installed. npx with the unscoped name would fetch an unrelated look-alike
|
|
115
152
|
* package (see PR #4151).
|
|
116
153
|
*/
|
|
117
|
-
export const
|
|
118
|
-
|
|
154
|
+
export const SETUP_INVOCATION = 'npx @astryxdesign/cli';
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* The one-line next-step every setup layer prints. Kept here so layer 1
|
|
158
|
+
* (core), layer 2 (cli postinstall) and layer 3 (each command) can never word
|
|
159
|
+
* it differently. Each layer passes the stem from the CLI's picker when it can
|
|
160
|
+
* load it.
|
|
161
|
+
*
|
|
162
|
+
* @param {string} [invocation] the CLI invocation stem, e.g. `pnpm exec astryx`
|
|
163
|
+
* @param {{before?: string | null}} [options] `before`: a command to run
|
|
164
|
+
* first, such as the one that adds the CLI to a project that has none
|
|
165
|
+
* @returns {string}
|
|
166
|
+
*/
|
|
167
|
+
export function setupNudge(
|
|
168
|
+
invocation = SETUP_INVOCATION,
|
|
169
|
+
{before = null} = {},
|
|
170
|
+
) {
|
|
171
|
+
const run = before
|
|
172
|
+
? `\`${before}\`, then \`${invocation} init\``
|
|
173
|
+
: `\`${invocation} init\``;
|
|
174
|
+
return `\nNext step: run ${run} to finish setup and install the Astryx agent prompt.\n\n`;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** The nudge with the fallback invocation. */
|
|
178
|
+
export const SETUP_NUDGE = setupNudge();
|
|
119
179
|
|
|
120
180
|
/**
|
|
121
181
|
* Pure decision: should a postinstall print the setup nudge? Shared by BOTH
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @file @astryxdesign/core postinstall — nudge to run `
|
|
4
|
+
* @file @astryxdesign/core postinstall — nudge to run `astryx init`, prefixed
|
|
5
|
+
* the way the project's installed CLI prints commands.
|
|
5
6
|
*
|
|
6
7
|
* Enforcement layer 1 of making `astryx init` foolproof: when the design system
|
|
7
8
|
* is installed and the project hasn't run init yet, print a one-line next-step
|
|
@@ -19,6 +20,8 @@
|
|
|
19
20
|
* during npx's fetch, and once set up.
|
|
20
21
|
*/
|
|
21
22
|
|
|
23
|
+
import * as fs from 'node:fs';
|
|
24
|
+
import * as path from 'node:path';
|
|
22
25
|
import {fileURLToPath, pathToFileURL} from 'node:url';
|
|
23
26
|
|
|
24
27
|
const HERE = fileURLToPath(import.meta.url);
|
|
@@ -37,6 +40,39 @@ async function loadContract() {
|
|
|
37
40
|
}
|
|
38
41
|
}
|
|
39
42
|
|
|
43
|
+
/**
|
|
44
|
+
* The stem the project's installed CLI would print, from its picker
|
|
45
|
+
* (`getCliInvocation`). Core cannot depend on the CLI, so this looks for an
|
|
46
|
+
* installed copy from the project upward and imports the picker by path; with
|
|
47
|
+
* no CLI there, or one too old to have the picker, it returns undefined and
|
|
48
|
+
* the contract's scoped fallback is printed. At install time no integration is
|
|
49
|
+
* loaded, so this is the package-manager guess.
|
|
50
|
+
* @param {string} root
|
|
51
|
+
* @returns {Promise<string | undefined>}
|
|
52
|
+
*/
|
|
53
|
+
export async function cliInvocation(root) {
|
|
54
|
+
try {
|
|
55
|
+
let dir = path.resolve(root);
|
|
56
|
+
for (;;) {
|
|
57
|
+
const picker = path.join(
|
|
58
|
+
dir,
|
|
59
|
+
'node_modules/@astryxdesign/cli/foundation/env/package-manager.mjs',
|
|
60
|
+
);
|
|
61
|
+
if (fs.existsSync(picker)) {
|
|
62
|
+
const {getCliInvocation} = await import(pathToFileURL(picker).href);
|
|
63
|
+
return typeof getCliInvocation === 'function'
|
|
64
|
+
? getCliInvocation(root)
|
|
65
|
+
: undefined;
|
|
66
|
+
}
|
|
67
|
+
const parent = path.dirname(dir);
|
|
68
|
+
if (parent === dir) return undefined;
|
|
69
|
+
dir = parent;
|
|
70
|
+
}
|
|
71
|
+
} catch {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
40
76
|
async function main() {
|
|
41
77
|
const contract = await loadContract();
|
|
42
78
|
if (!contract) return;
|
|
@@ -45,10 +81,15 @@ async function main() {
|
|
|
45
81
|
contract.shouldNudge({
|
|
46
82
|
scriptPath: HERE,
|
|
47
83
|
npmCommand: process.env.npm_command,
|
|
48
|
-
isSetUp: contract.
|
|
84
|
+
isSetUp: contract.isAstryxPromptInReach(root),
|
|
49
85
|
})
|
|
50
86
|
) {
|
|
51
|
-
|
|
87
|
+
const invocation = await cliInvocation(root);
|
|
88
|
+
process.stdout.write(
|
|
89
|
+
typeof contract.setupNudge === 'function'
|
|
90
|
+
? contract.setupNudge(invocation)
|
|
91
|
+
: contract.SETUP_NUDGE,
|
|
92
|
+
);
|
|
52
93
|
}
|
|
53
94
|
}
|
|
54
95
|
|
package/src/Avatar/Avatar.tsx
CHANGED
|
@@ -387,9 +387,18 @@ export interface AvatarProps extends BaseProps<HTMLDivElement> {
|
|
|
387
387
|
/**
|
|
388
388
|
* A character that can stand for a word in initials: a letter, a digit, or an
|
|
389
389
|
* emoji. Punctuation and other symbols, such as `(`, `"` or `-`, cannot.
|
|
390
|
+
*
|
|
391
|
+
* Built at runtime, not written as a literal: for targets without property
|
|
392
|
+
* escapes, or when no browserslist is set, Babel's
|
|
393
|
+
* transform-unicode-property-regex rewrites a `\p{…}` literal, and the copy
|
|
394
|
+
* bundled with Next.js lacks the Unicode data it needs, so a source build fails
|
|
395
|
+
* with "Unknown property". A literal is safe once Next's bundled Babel ships
|
|
396
|
+
* that data.
|
|
390
397
|
*/
|
|
391
|
-
const INITIAL_CHARACTER =
|
|
392
|
-
|
|
398
|
+
const INITIAL_CHARACTER = new RegExp(
|
|
399
|
+
'[\\p{L}\\p{N}\\p{Extended_Pictographic}\\p{Regional_Indicator}]',
|
|
400
|
+
'u',
|
|
401
|
+
);
|
|
393
402
|
|
|
394
403
|
/**
|
|
395
404
|
* The first character of a word that can stand for it in initials, skipping
|