@astryxdesign/core 0.7.1 → 0.7.2-canary.151434a
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/dist/AspectRatio/AspectRatio.d.ts +6 -8
- package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
- package/dist/AspectRatio/AspectRatio.js +44 -3
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +38 -14
- package/dist/CheckboxInput/CheckboxInput.d.ts +1 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +3 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts +9 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +4 -2
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +20 -8
- package/dist/Drawer/Drawer.d.ts +191 -0
- package/dist/Drawer/Drawer.d.ts.map +1 -0
- package/dist/Drawer/Drawer.js +382 -0
- package/dist/Drawer/DrawerHeader.d.ts +85 -0
- package/dist/Drawer/DrawerHeader.d.ts.map +1 -0
- package/dist/Drawer/DrawerHeader.js +134 -0
- package/dist/Drawer/index.d.ts +11 -0
- package/dist/Drawer/index.d.ts.map +1 -0
- package/dist/Drawer/index.js +11 -0
- package/dist/Drawer/useDrawerDialogPresence.d.ts +42 -0
- package/dist/Drawer/useDrawerDialogPresence.d.ts.map +1 -0
- package/dist/Drawer/useDrawerDialogPresence.js +236 -0
- package/dist/DropdownMenu/DropdownMenu.js +1 -1
- package/dist/DropdownMenu/DropdownMenuDivider.d.ts +5 -3
- package/dist/DropdownMenu/DropdownMenuDivider.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuDivider.js +7 -3
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +4 -4
- package/dist/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/EmptyState/EmptyState.js +4 -10
- package/dist/Field/Field.d.ts +1 -1
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +8 -4
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +10 -2
- package/dist/Item/Item.d.ts +6 -2
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +19 -4
- package/dist/Layer/layerViewportInset.stylex.d.ts +6 -2
- package/dist/Layer/layerViewportInset.stylex.d.ts.map +1 -1
- package/dist/Layer/layerViewportInset.stylex.js +6 -2
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +13 -7
- package/dist/Layer/useLayerDismissal.d.ts +1 -1
- package/dist/Layer/useLayerDismissal.js +1 -1
- package/dist/Layout/container.stylex.d.ts +5 -5
- package/dist/Layout/container.stylex.js +4 -4
- package/dist/List/List.d.ts +46 -19
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +28 -10
- package/dist/List/ListContext.d.ts +8 -3
- package/dist/List/ListContext.d.ts.map +1 -1
- package/dist/List/ListContext.js +7 -2
- package/dist/List/ListItem.d.ts +13 -5
- package/dist/List/ListItem.d.ts.map +1 -1
- package/dist/List/ListItem.js +21 -8
- package/dist/List/index.d.ts +1 -1
- package/dist/List/index.d.ts.map +1 -1
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +8 -1
- package/dist/Markdown/plugins/frontmatter.d.ts.map +1 -1
- package/dist/Markdown/plugins/frontmatter.js +7 -3
- package/dist/MetadataList/MetadataList.d.ts.map +1 -1
- package/dist/MetadataList/MetadataList.js +5 -1
- package/dist/MetadataList/MetadataListContext.d.ts +1 -1
- package/dist/MetadataList/MetadataListContext.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +22 -8
- package/dist/MultiSelector/OptionActions.a11y.chromium.spec.js +100 -2
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +3 -1
- package/dist/Pagination/Pagination.d.ts +8 -5
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +21 -8
- package/dist/Popover/Popover.js +2 -2
- package/dist/PowerSearch/PowerSearch.js +1 -1
- package/dist/RadioList/RadioListItem.d.ts +9 -1
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +2 -0
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +6 -2
- package/dist/Switch/Switch.d.ts +1 -1
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +13 -1
- package/dist/TabList/TabMenu.d.ts +2 -2
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +6 -3
- package/dist/Text/useTruncation.d.ts +7 -5
- package/dist/Text/useTruncation.d.ts.map +1 -1
- package/dist/Text/useTruncation.js +16 -5
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +11 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +26 -0
- package/dist/astryx.css +35 -12
- package/dist/hooks/useEntryAnimation.d.ts +2 -1
- package/dist/hooks/useEntryAnimation.d.ts.map +1 -1
- package/dist/hooks/useEntryAnimation.js +14 -12
- package/dist/hooks/useIsHydrating.d.ts +6 -0
- package/dist/hooks/useIsHydrating.d.ts.map +1 -0
- package/dist/hooks/useIsHydrating.js +30 -0
- package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/en.generated.js +112 -1
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +112 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +0 -3
- package/dist/utils/focusOutline.stylex.d.ts +4 -0
- package/dist/utils/focusOutline.stylex.d.ts.map +1 -1
- package/dist/utils/focusOutline.stylex.js +4 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +15 -9
- package/dist/utils/sharedMutationObserver.d.ts +21 -0
- package/dist/utils/sharedMutationObserver.d.ts.map +1 -0
- package/dist/utils/sharedMutationObserver.js +69 -0
- package/locales/en.json +444 -0
- package/locales/pseudo.json +333 -0
- package/package.json +9 -4
- package/src/AspectRatio/AspectRatio.test.tsx +44 -43
- package/src/AspectRatio/AspectRatio.tsx +38 -18
- package/src/AspectRatio/__tests__/AspectRatioFitLayers.a11y.browser.spec.ts +157 -0
- package/src/Button/Button.doc.mjs +2 -2
- package/src/Button/Button.test.tsx +155 -9
- package/src/Button/Button.tsx +39 -16
- package/src/Button/__tests__/Button.a11y.known-failures.ts +1 -62
- package/src/Button/__tests__/Button.a11y.states.ts +0 -10
- package/src/CheckboxInput/CheckboxInput.test.tsx +34 -0
- package/src/CheckboxInput/CheckboxInput.tsx +3 -1
- package/src/CheckboxList/CheckboxList.test.tsx +22 -0
- package/src/CheckboxList/CheckboxListItem.doc.mjs +16 -0
- package/src/CheckboxList/CheckboxListItem.tsx +10 -0
- package/src/Dialog/Dialog.test.tsx +46 -0
- package/src/Dialog/Dialog.tsx +20 -7
- package/src/Dialog/__tests__/Dialog.a11y.known-failures.ts +0 -14
- package/src/Drawer/Drawer.doc.mjs +472 -0
- package/src/Drawer/Drawer.spec.md +357 -0
- package/src/Drawer/Drawer.test.tsx +1300 -0
- package/src/Drawer/Drawer.tsx +613 -0
- package/src/Drawer/DrawerDirection.test.tsx +127 -0
- package/src/Drawer/DrawerHeader.doc.mjs +293 -0
- package/src/Drawer/DrawerHeader.test.tsx +102 -0
- package/src/Drawer/DrawerHeader.tsx +235 -0
- package/src/Drawer/__tests__/DrawerAudit.a11y.chromium.spec.ts +401 -0
- package/src/Drawer/__tests__/DrawerHeaderAudit.a11y.chromium.spec.ts +297 -0
- package/src/Drawer/index.ts +13 -0
- package/src/Drawer/useDrawerDialogPresence.ts +284 -0
- package/src/DropdownMenu/DropdownMenu.test.tsx +21 -12
- package/src/DropdownMenu/DropdownMenu.tsx +2 -2
- package/src/DropdownMenu/DropdownMenuDivider.doc.mjs +2 -2
- package/src/DropdownMenu/DropdownMenuDivider.tsx +9 -5
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +2 -2
- package/src/DropdownMenu/__tests__/Menu.a11y.chromium.spec.ts +145 -0
- package/src/DropdownMenu/__tests__/Menu.a11y.known-failures.ts +26 -0
- package/src/DropdownMenu/__tests__/Menu.a11y.renders.tsx +65 -0
- package/src/DropdownMenu/__tests__/Menu.a11y.states.ts +138 -0
- package/src/DropdownMenu/__tests__/Menu.a11y.test.tsx +136 -0
- package/src/EmptyState/EmptyState.doc.mjs +3 -2
- package/src/EmptyState/EmptyState.spec.md +189 -0
- package/src/EmptyState/EmptyState.test.tsx +74 -3
- package/src/EmptyState/EmptyState.tsx +4 -8
- package/src/Field/Field.doc.mjs +14 -8
- package/src/Field/Field.spec.md +217 -0
- package/src/Field/Field.test.tsx +60 -2
- package/src/Field/Field.tsx +17 -8
- package/src/HoverCard/HoverCard.test.tsx +58 -0
- package/src/HoverCard/useHoverCard.tsx +10 -2
- package/src/IconButton/IconButton.doc.mjs +2 -2
- package/src/IconButton/IconButton.test.tsx +3 -1
- package/src/Item/Item.doc.mjs +12 -8
- package/src/Item/Item.spec.md +226 -0
- package/src/Item/Item.test.tsx +61 -0
- package/src/Item/Item.tsx +40 -4
- package/src/Layer/layerViewportInset.source-build.test.mjs +90 -0
- package/src/Layer/layerViewportInset.stylex.ts +6 -2
- package/src/Layer/layerViewportInset.test.ts +1 -0
- package/src/Layer/useLayer.tsx +24 -13
- package/src/Layer/useLayerDismissal.ts +1 -1
- package/src/Layout/container.stylex.ts +6 -6
- package/src/List/List.doc.mjs +14 -1
- package/src/List/List.spec.md +129 -77
- package/src/List/List.test.tsx +163 -94
- package/src/List/List.tsx +74 -18
- package/src/List/ListContext.tsx +9 -3
- package/src/List/ListItem.doc.mjs +24 -5
- package/src/List/ListItem.tsx +56 -27
- package/src/List/index.ts +1 -1
- package/src/Markdown/Markdown.tsx +14 -1
- package/src/Markdown/plugins/frontmatter.test.tsx +25 -0
- package/src/Markdown/plugins/frontmatter.ts +7 -3
- package/src/MetadataList/MetadataList.doc.mjs +2 -2
- package/src/MetadataList/MetadataList.test.tsx +38 -0
- package/src/MetadataList/MetadataList.tsx +8 -1
- package/src/MetadataList/MetadataListContext.tsx +1 -1
- package/src/MultiSelector/MultiSelector.test.tsx +159 -0
- package/src/MultiSelector/MultiSelector.tsx +40 -7
- package/src/MultiSelector/OptionActions.a11y.chromium.spec.ts +112 -2
- package/src/MultiSelector/hooks.ts +3 -1
- package/src/MultiSelector/useMultiCombobox.doc.mjs +267 -0
- package/src/Pagination/Pagination.doc.mjs +7 -7
- package/src/Pagination/Pagination.spec.md +9 -9
- package/src/Pagination/Pagination.test.tsx +242 -0
- package/src/Pagination/Pagination.tsx +27 -11
- package/src/Popover/Popover.test.tsx +2 -2
- package/src/Popover/Popover.tsx +4 -4
- package/src/PowerSearch/PowerSearch.test.tsx +85 -0
- package/src/PowerSearch/PowerSearch.tsx +2 -2
- package/src/RadioList/RadioList.test.tsx +22 -0
- package/src/RadioList/RadioListItem.doc.mjs +16 -0
- package/src/RadioList/RadioListItem.tsx +10 -1
- package/src/Selector/hooks.ts +6 -2
- package/src/Selector/useCombobox.doc.mjs +237 -0
- package/src/Switch/Switch.test.tsx +49 -0
- package/src/Switch/Switch.tsx +11 -0
- package/src/TabList/TabList.spec.md +57 -44
- package/src/TabList/TabList.test.tsx +67 -0
- package/src/TabList/TabMenu.doc.mjs +4 -3
- package/src/TabList/TabMenu.tsx +7 -4
- package/src/Text/useTruncation.test.tsx +69 -0
- package/src/Text/useTruncation.ts +16 -5
- package/src/Tokenizer/Tokenizer.test.tsx +54 -1
- package/src/Tooltip/Tooltip.test.tsx +31 -0
- package/src/Tooltip/useTooltip.test.tsx +13 -0
- package/src/Tooltip/useTooltip.tsx +11 -0
- package/src/TreeList/TreeList.spec.md +29 -17
- package/src/Typeahead/BaseTypeahead.tsx +26 -0
- package/src/Typeahead/Typeahead.test.tsx +260 -2
- package/src/hooks/useEntryAnimation.doc.mjs +4 -4
- package/src/hooks/useEntryAnimation.ssr.test.tsx +143 -0
- package/src/hooks/useEntryAnimation.ts +15 -16
- package/src/hooks/useIsHydrating.test.tsx +70 -0
- package/src/hooks/useIsHydrating.ts +31 -0
- package/src/i18n/InternationalizationProvider.doc.mjs +8 -0
- package/src/i18n/InternationalizationProvider.spec.md +252 -0
- package/src/i18n/__tests__/InternationalizationProvider.test.tsx +128 -0
- package/src/i18n/generated-locales/en.generated.ts +121 -0
- package/src/i18n/generated-locales/pseudo.generated.ts +121 -0
- package/src/i18n/useTranslator.test.tsx +37 -0
- package/src/index.ts +1 -0
- package/src/reset.css +0 -29
- package/src/theme/derivedVarRegistry.test.ts +3 -3
- package/src/theme/derivedVarRegistry.ts +0 -3
- package/src/utils/focusOutline.stylex.ts +4 -0
- package/src/utils/plainDate.test.ts +37 -1
- package/src/utils/plainDate.ts +15 -5
- package/src/utils/sharedMutationObserver.test.ts +53 -0
- package/src/utils/sharedMutationObserver.ts +78 -0
package/src/Item/Item.tsx
CHANGED
|
@@ -67,7 +67,7 @@ const LazyItemSwipeLayer = lazy(async () => import('./ItemSwipeLayer'));
|
|
|
67
67
|
// Types
|
|
68
68
|
// =============================================================================
|
|
69
69
|
|
|
70
|
-
export type ItemAlign = 'center' | 'start';
|
|
70
|
+
export type ItemAlign = 'center' | 'start' | 'first-line';
|
|
71
71
|
export type ItemDensity = 'compact' | 'balanced' | 'spacious';
|
|
72
72
|
|
|
73
73
|
/**
|
|
@@ -168,7 +168,11 @@ export interface ItemProps extends BaseProps<HTMLElement> {
|
|
|
168
168
|
endContent?: ReactNode;
|
|
169
169
|
|
|
170
170
|
/**
|
|
171
|
-
* Vertical alignment of the start/end content slots.
|
|
171
|
+
* Vertical alignment of the start/end content slots. `center` centers each
|
|
172
|
+
* slot on the whole text block; `start` lines up slot tops with the text's
|
|
173
|
+
* top; `first-line` centers each slot on the label's first line, so a small
|
|
174
|
+
* mark (a status dot, a radio, a timestamp) stays level with the first line
|
|
175
|
+
* of a wrapped label. A slot taller than that line moves the text down.
|
|
172
176
|
* @default 'center'
|
|
173
177
|
*/
|
|
174
178
|
align?: ItemAlign;
|
|
@@ -338,7 +342,7 @@ const styles = stylex.create({
|
|
|
338
342
|
gap: spacingVars['--spacing-2'],
|
|
339
343
|
// The inline inset is published as --_item-inset-inline and the padding
|
|
340
344
|
// derives from it, so consumers that need to compensate for the inset
|
|
341
|
-
// (List's
|
|
345
|
+
// (List's edge treatments) read the var instead of mirroring the values.
|
|
342
346
|
// Themes that set paddingInline on `item` also feed this var via the
|
|
343
347
|
// derived var registry, keeping padding and compensation in sync.
|
|
344
348
|
'--_item-inset-inline': spacingVars['--spacing-2'],
|
|
@@ -351,6 +355,30 @@ const styles = stylex.create({
|
|
|
351
355
|
alignStart: {
|
|
352
356
|
alignItems: 'flex-start',
|
|
353
357
|
},
|
|
358
|
+
// `first-line`: the row aligns its children on their first baselines. The
|
|
359
|
+
// label's first baseline is its first line's; each slot gets the same
|
|
360
|
+
// baseline from its strut (below), which the slot centers against its
|
|
361
|
+
// content. So each slot's center lands on the first line's center for any
|
|
362
|
+
// slot height, and a taller slot pushes the text down instead of leaving
|
|
363
|
+
// the row. Pure CSS: no measurement.
|
|
364
|
+
alignFirstLine: {
|
|
365
|
+
alignItems: 'baseline',
|
|
366
|
+
},
|
|
367
|
+
// A zero-width line of label text inside the slot: same size and leading as
|
|
368
|
+
// the label, so its line box is the label's first line box. The slot centers
|
|
369
|
+
// it against the slot's content, and the row's baseline alignment puts it on
|
|
370
|
+
// the label's first line. Its content carries empty alternative text so
|
|
371
|
+
// assistive technology reads nothing from it.
|
|
372
|
+
firstLineSlot: {
|
|
373
|
+
alignItems: 'center',
|
|
374
|
+
'::before': {
|
|
375
|
+
content: stylex.firstThatWorks('"\\200B" / ""', '"\\200B"'),
|
|
376
|
+
inlineSize: 0,
|
|
377
|
+
overflow: 'hidden',
|
|
378
|
+
fontSize: typeScaleVars['--text-body-size'],
|
|
379
|
+
lineHeight: typeScaleVars['--text-body-leading'],
|
|
380
|
+
},
|
|
381
|
+
},
|
|
354
382
|
interactive: {
|
|
355
383
|
cursor: {
|
|
356
384
|
default: 'pointer',
|
|
@@ -712,7 +740,13 @@ export function Item({
|
|
|
712
740
|
<>
|
|
713
741
|
{marker}
|
|
714
742
|
{startContent != null && (
|
|
715
|
-
<span
|
|
743
|
+
<span
|
|
744
|
+
{...stylex.props(
|
|
745
|
+
styles.startContent,
|
|
746
|
+
align === 'first-line' && styles.firstLineSlot,
|
|
747
|
+
)}>
|
|
748
|
+
{startContent}
|
|
749
|
+
</span>
|
|
716
750
|
)}
|
|
717
751
|
|
|
718
752
|
{hasParentRole || isDelegate ? (
|
|
@@ -768,6 +802,7 @@ export function Item({
|
|
|
768
802
|
<span
|
|
769
803
|
{...stylex.props(
|
|
770
804
|
styles.endContent,
|
|
805
|
+
align === 'first-line' && styles.firstLineSlot,
|
|
771
806
|
isDisabled && styles.disabledContent,
|
|
772
807
|
)}>
|
|
773
808
|
{endContent}
|
|
@@ -846,6 +881,7 @@ export function Item({
|
|
|
846
881
|
styles.root,
|
|
847
882
|
densityStyles[density],
|
|
848
883
|
align === 'start' && styles.alignStart,
|
|
884
|
+
align === 'first-line' && styles.alignFirstLine,
|
|
849
885
|
isInteractive && styles.interactive,
|
|
850
886
|
isInteractive && interactionOverlayStyles.backgroundColor,
|
|
851
887
|
isLinkRoot && styles.linkRoot,
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file layerViewportInset.source-build.test.mjs
|
|
5
|
+
* @input Uses Babel, the core StyleX build config, the StyleX rule processor,
|
|
6
|
+
* and the sources that cap or inset anchored layers
|
|
7
|
+
* @output Verifies the shipped stylesheet carries the dynamic-viewport,
|
|
8
|
+
* safe-area gutter and caps (spec:AST-059 FR1–FR3), not only the fallbacks
|
|
9
|
+
* @position Regression test for the compiled layer viewport inset
|
|
10
|
+
*
|
|
11
|
+
* `stylex.firstThatWorks(a, b)` turns two `var()` arguments into one nested
|
|
12
|
+
* `var(a, b)`. A `defineConsts` reference compiles to such a `var()`, and the
|
|
13
|
+
* rule processor inlines a constant only where its `var()` stands alone, so a
|
|
14
|
+
* pair of bare constant references shipped as `var(--<hash>, <fallback>)`
|
|
15
|
+
* with `--<hash>` defined nowhere: every engine took the fallback.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import fs from 'node:fs/promises';
|
|
19
|
+
import path from 'node:path';
|
|
20
|
+
import {fileURLToPath} from 'node:url';
|
|
21
|
+
import {transformAsync} from '@babel/core';
|
|
22
|
+
import stylexBabelPlugin from '@stylexjs/babel-plugin';
|
|
23
|
+
import {describe, expect, it} from 'vitest';
|
|
24
|
+
|
|
25
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
const SRC = path.resolve(__dirname, '..');
|
|
27
|
+
const CORE_ROOT = path.resolve(SRC, '..');
|
|
28
|
+
|
|
29
|
+
const SOURCES = [
|
|
30
|
+
'Layer/layerViewportInset.stylex.ts',
|
|
31
|
+
'Layer/useLayer.tsx',
|
|
32
|
+
'Popover/Popover.tsx',
|
|
33
|
+
'DropdownMenu/DropdownMenu.tsx',
|
|
34
|
+
'DropdownMenu/DropdownMenuSubMenu.tsx',
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
async function compileStylesheet() {
|
|
38
|
+
const rules = [];
|
|
39
|
+
for (const relative of SOURCES) {
|
|
40
|
+
const filename = path.join(SRC, relative);
|
|
41
|
+
const result = await transformAsync(await fs.readFile(filename, 'utf8'), {
|
|
42
|
+
babelrc: false,
|
|
43
|
+
configFile: path.join(CORE_ROOT, 'babel.config.json'),
|
|
44
|
+
filename,
|
|
45
|
+
});
|
|
46
|
+
rules.push(...(result?.metadata?.stylex ?? []));
|
|
47
|
+
}
|
|
48
|
+
return stylexBabelPlugin.processStylexRules(rules, false);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Every declaration of `property` in the compiled sheet. */
|
|
52
|
+
function declarations(css, property) {
|
|
53
|
+
return [...css.matchAll(new RegExp(`[{;]${property}:([^;}]+)`, 'g'))].map(
|
|
54
|
+
match => match[1],
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
describe('layer viewport inset stylesheet (spec:AST-059)', () => {
|
|
59
|
+
it('leaves no constant reference unresolved behind a fallback', async () => {
|
|
60
|
+
const css = await compileStylesheet();
|
|
61
|
+
const defined = new Set(
|
|
62
|
+
[...css.matchAll(/(--[\w-]+)\s*:/g)].map(match => match[1]),
|
|
63
|
+
);
|
|
64
|
+
const undefinedReferences = [
|
|
65
|
+
...css.matchAll(/var\((--x[a-z0-9]+),/g),
|
|
66
|
+
].flatMap(match => (defined.has(match[1]) ? [] : [match[0]]));
|
|
67
|
+
// Covers the caps and the four alignment-axis gutter margins.
|
|
68
|
+
expect(undefinedReferences).toEqual([]);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('caps both axes against the dynamic viewport and the safe-area gutters', async () => {
|
|
72
|
+
const css = await compileStylesheet();
|
|
73
|
+
const blockCaps = declarations(css, 'max-height');
|
|
74
|
+
const inlineCaps = declarations(css, 'max-width');
|
|
75
|
+
|
|
76
|
+
expect(blockCaps).toContainEqual(
|
|
77
|
+
expect.stringMatching(/^calc\(calc\(100dvb - .*safe-area-inset-top/),
|
|
78
|
+
);
|
|
79
|
+
expect(inlineCaps).toContainEqual(
|
|
80
|
+
expect.stringMatching(/^calc\(calc\(100vi - .*safe-area-inset-left/),
|
|
81
|
+
);
|
|
82
|
+
// The older-engine fallbacks still ship, ahead of the preferred value.
|
|
83
|
+
expect(blockCaps).toContainEqual(
|
|
84
|
+
expect.stringMatching(/^calc\(calc\(100vh - /),
|
|
85
|
+
);
|
|
86
|
+
expect(inlineCaps).toContainEqual(
|
|
87
|
+
expect.stringMatching(/^calc\(calc\(100vw - /),
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -56,8 +56,12 @@ const GUTTER_BLOCK = `calc(max(${SPACING}, env(safe-area-inset-top, 0px), env(sa
|
|
|
56
56
|
|
|
57
57
|
/**
|
|
58
58
|
* The viewport gutter and the caps derived from it. Every value has an
|
|
59
|
-
* `env()`-less fallback for engines without safe-area support; pair them
|
|
60
|
-
* `stylex.firstThatWorks(cap
|
|
59
|
+
* `env()`-less fallback for engines without safe-area support; pair them as
|
|
60
|
+
* `stylex.firstThatWorks(`calc(${cap})`, `calc(${capFallback})`)`. Pass
|
|
61
|
+
* each inside a `calc()` (or another function), never as a bare reference: a
|
|
62
|
+
* constant reference compiles to a `var()`, and `firstThatWorks` folds two
|
|
63
|
+
* `var()` arguments into one `var(cap, capFallback)` whose constant is never
|
|
64
|
+
* inlined, so every engine would take the fallback.
|
|
61
65
|
*/
|
|
62
66
|
export const layerViewportInset = stylex.defineConsts({
|
|
63
67
|
/** Gutter from the block-start viewport edge. */
|
package/src/Layer/useLayer.tsx
CHANGED
|
@@ -102,15 +102,17 @@ const styles = stylex.create({
|
|
|
102
102
|
// The cap is on the layer box itself: content wider than the viewport
|
|
103
103
|
// overflows inside the layer, where the composing component decides
|
|
104
104
|
// whether it scrolls or clips; the box never leaves the viewport.
|
|
105
|
+
// Each constant is wrapped in `calc()` so both declarations ship (see
|
|
106
|
+
// layerViewportInset).
|
|
105
107
|
viewportFit: {
|
|
106
108
|
boxSizing: 'border-box',
|
|
107
109
|
maxInlineSize: stylex.firstThatWorks(
|
|
108
|
-
layerViewportInset.maxInlineSize
|
|
109
|
-
layerViewportInset.maxInlineSizeFallback
|
|
110
|
+
`calc(${layerViewportInset.maxInlineSize})`,
|
|
111
|
+
`calc(${layerViewportInset.maxInlineSizeFallback})`,
|
|
110
112
|
),
|
|
111
113
|
maxBlockSize: stylex.firstThatWorks(
|
|
112
|
-
layerViewportInset.maxBlockSize
|
|
113
|
-
layerViewportInset.maxBlockSizeFallback
|
|
114
|
+
`calc(${layerViewportInset.maxBlockSize})`,
|
|
115
|
+
`calc(${layerViewportInset.maxBlockSizeFallback})`,
|
|
114
116
|
),
|
|
115
117
|
},
|
|
116
118
|
// Alignment-axis gutter (spec:AST-059 FR1): a margin on the far viewport
|
|
@@ -120,26 +122,26 @@ const styles = stylex.create({
|
|
|
120
122
|
// (see layerSlideRules.ts).
|
|
121
123
|
gutterInlineEnd: {
|
|
122
124
|
marginInlineEnd: stylex.firstThatWorks(
|
|
123
|
-
layerViewportInset.gutterInline
|
|
124
|
-
layerViewportInset.gutterInlineFallback
|
|
125
|
+
`calc(${layerViewportInset.gutterInline})`,
|
|
126
|
+
`calc(${layerViewportInset.gutterInlineFallback})`,
|
|
125
127
|
),
|
|
126
128
|
},
|
|
127
129
|
gutterInlineStart: {
|
|
128
130
|
marginInlineStart: stylex.firstThatWorks(
|
|
129
|
-
layerViewportInset.gutterInline
|
|
130
|
-
layerViewportInset.gutterInlineFallback
|
|
131
|
+
`calc(${layerViewportInset.gutterInline})`,
|
|
132
|
+
`calc(${layerViewportInset.gutterInlineFallback})`,
|
|
131
133
|
),
|
|
132
134
|
},
|
|
133
135
|
gutterBlockEnd: {
|
|
134
136
|
marginBlockEnd: stylex.firstThatWorks(
|
|
135
|
-
layerViewportInset.gutterBlock
|
|
136
|
-
layerViewportInset.gutterBlockFallback
|
|
137
|
+
`calc(${layerViewportInset.gutterBlock})`,
|
|
138
|
+
`calc(${layerViewportInset.gutterBlockFallback})`,
|
|
137
139
|
),
|
|
138
140
|
},
|
|
139
141
|
gutterBlockStart: {
|
|
140
142
|
marginBlockStart: stylex.firstThatWorks(
|
|
141
|
-
layerViewportInset.gutterBlock
|
|
142
|
-
layerViewportInset.gutterBlockFallback
|
|
143
|
+
`calc(${layerViewportInset.gutterBlock})`,
|
|
144
|
+
`calc(${layerViewportInset.gutterBlockFallback})`,
|
|
143
145
|
),
|
|
144
146
|
},
|
|
145
147
|
});
|
|
@@ -760,7 +762,16 @@ function useLayerImplementation(
|
|
|
760
762
|
// hosted away from its trigger then still takes its sequential focus
|
|
761
763
|
// order (and its popover nesting) from the trigger rather than from
|
|
762
764
|
// its own DOM position. Browsers without the option ignore it.
|
|
763
|
-
|
|
765
|
+
// `source` is declared as an `HTMLElement`. A caller-rendered icon
|
|
766
|
+
// trigger is an `SVGElement`, whose dictionary conversion throws
|
|
767
|
+
// before the popover opens. Omitting the option for it still anchors
|
|
768
|
+
// the layer, because positioning reads the anchor-name pair, and only
|
|
769
|
+
// gives up the invoker's focus order.
|
|
770
|
+
const trigger =
|
|
771
|
+
triggerRef.current instanceof HTMLElement
|
|
772
|
+
? triggerRef.current
|
|
773
|
+
: undefined;
|
|
774
|
+
popover.showPopover({source: trigger});
|
|
764
775
|
});
|
|
765
776
|
} else {
|
|
766
777
|
popover.style.display = 'block';
|
|
@@ -98,7 +98,7 @@ export interface UseLayerDismissalReturn {
|
|
|
98
98
|
* routes each Escape press to the top-most REGISTERED layer, so one press
|
|
99
99
|
* dismisses exactly one of them. Dialog (and what is built on it, including
|
|
100
100
|
* CommandPalette), Popover and the menus built on it, ContextMenu, Tooltip,
|
|
101
|
-
* HoverCard, Lightbox, MobileNav, BottomSheet, BottomSheetSwitcher and
|
|
101
|
+
* HoverCard, Lightbox, MobileNav, BottomSheet, BottomSheetSwitcher and
|
|
102
102
|
* `Drawer` register today.
|
|
103
103
|
*
|
|
104
104
|
* `DropdownMenuSubMenu` and `PowerSearchEditPopover` still run their own Escape
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* @file container.stylex.ts
|
|
5
5
|
* @input Uses @stylexjs/stylex, spacing from theme
|
|
6
6
|
* @output StyleX utility for layout container styling
|
|
7
|
-
* @position Layout utility; used by Card, Section, Dialog, BottomSheet, and
|
|
8
|
-
*
|
|
7
|
+
* @position Layout utility; used by Card, Section, Dialog, BottomSheet, and
|
|
8
|
+
* Drawer
|
|
9
9
|
*
|
|
10
10
|
* ## Public API for themes
|
|
11
11
|
*
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* --astryx-card-padding-block-end
|
|
20
20
|
*
|
|
21
21
|
* Read order per level: `var(--astryx-…, <next level>)`, terminating at
|
|
22
|
-
* `--spacing-4`. Same pattern for section, dialog, bottom-sheet, and
|
|
22
|
+
* `--spacing-4`. Same pattern for section, dialog, bottom-sheet, and
|
|
23
23
|
* drawer.
|
|
24
24
|
*
|
|
25
25
|
* ```ts
|
|
@@ -150,7 +150,7 @@ const bottomSheetInlineEnd = `var(--astryx-bottom-sheet-padding-inline-end, ${bo
|
|
|
150
150
|
const bottomSheetBlockStart = `var(--astryx-bottom-sheet-padding-block-start, ${bottomSheetShorthand})`;
|
|
151
151
|
const bottomSheetBlockEnd = `var(--astryx-bottom-sheet-padding-block-end, ${bottomSheetShorthand})`;
|
|
152
152
|
|
|
153
|
-
// Drawer
|
|
153
|
+
// Drawer padding chains: --astryx-* then the next specificity level,
|
|
154
154
|
// terminating at --spacing-4 like Dialog. Built as chained const strings (no
|
|
155
155
|
// function calls) so StyleX can statically analyze them; see naming.ts for the
|
|
156
156
|
// prefix policy.
|
|
@@ -522,8 +522,8 @@ export interface ContainerOptions {
|
|
|
522
522
|
* This allows themes to override container padding via component-specific
|
|
523
523
|
* public CSS custom properties without touching internal vars.
|
|
524
524
|
*
|
|
525
|
-
* Used by Card, Section, Dialog, BottomSheet, and
|
|
526
|
-
*
|
|
525
|
+
* Used by Card, Section, Dialog, BottomSheet, and Drawer when no explicit
|
|
526
|
+
* padding prop is provided.
|
|
527
527
|
* @default undefined (uses explicit spacing token values)
|
|
528
528
|
*/
|
|
529
529
|
useThemeDefault?: ContainerComponent;
|
package/src/List/List.doc.mjs
CHANGED
|
@@ -41,11 +41,18 @@ export const docs = {
|
|
|
41
41
|
description: 'Show dividers between items.',
|
|
42
42
|
default: 'false',
|
|
43
43
|
},
|
|
44
|
+
{
|
|
45
|
+
name: 'edge',
|
|
46
|
+
type: "'padded' | 'flush' | 'outset' | 'bleed'",
|
|
47
|
+
description:
|
|
48
|
+
"Where each row's text, dividers, and hover and selection backgrounds sit, relative to the list's edges and the container around it. 'padded' keeps text inside each row's padding, so it starts a little in from a heading above the list and backgrounds have room around it. 'flush' drops the rows' side padding: text starts on the heading's line, and dividers and backgrounds stop at the row's content, with no room beyond it on either side. It works anywhere and suits static rows. 'outset' puts text on the heading's line and reaches dividers and backgrounds a little past it into the container's padding; it suits interactive rows in a container. 'bleed' puts text on the heading's line and reaches dividers and backgrounds to the container's edges with square corners, like Table rows in a Card. A row's first content is what lines up with the heading: its marker, icon, or avatar when it has one, otherwise its label. 'outset' and 'bleed' reach into the padding of the nearest container that shares its padding: a Card, Section, Dialog, or BottomSheet, or a transparent container such as a Layout region with explicit padding or a padded ScrollableArea. Place the List directly in that container's padding: padding that Stack, Center, or your own styles add in between is not counted. Drawers and the automatic padding of LayoutContent and LayoutPanel aren't supported yet. With no such container, including in a Popover, they look like 'padded'. In a container with less padding than the rows' own, text starts a little after the heading's line. A theme's inline padding on `item` replaces the row padding of every value, including the zero padding of flush.",
|
|
49
|
+
default: "'padded'",
|
|
50
|
+
},
|
|
44
51
|
{
|
|
45
52
|
name: 'edgeCompensation',
|
|
46
53
|
type: "'inline'",
|
|
47
54
|
description:
|
|
48
|
-
"
|
|
55
|
+
"Deprecated: use edge=\"outset\", which this sets. Still works; edge wins when both are set. `astryx upgrade` rewrites existing usage.",
|
|
49
56
|
},
|
|
50
57
|
{
|
|
51
58
|
name: 'header',
|
|
@@ -89,6 +96,8 @@ export const docs = {
|
|
|
89
96
|
bestPractices: [
|
|
90
97
|
{ guidance: true, description: 'Provide a header to label the list and give context to screen readers.' },
|
|
91
98
|
{ guidance: true, description: 'Use start and end content slots to add icons, avatars, or badges to each item.' },
|
|
99
|
+
{ guidance: true, description: 'Set edge to line row text up with a heading above the list: flush for static rows, outset or bleed for rows in a Card, Section, or Dialog.' },
|
|
100
|
+
{ guidance: true, description: 'To line text up with a heading and keep room around the highlight where there is no Card, such as a sidebar, put the heading and the list in a Section with variant="transparent" and set edge="outset".' },
|
|
92
101
|
{ guidance: false, description: 'Place interactive elements inside an interactive list item; it creates nested click targets and confusing focus behavior.' },
|
|
93
102
|
{ guidance: false, description: 'Use a list for a single item or for laying out unrelated content; lists imply a meaningful collection.' },
|
|
94
103
|
{ guidance: false, description: 'Mix clickable and non-clickable items in the same list without clear visual distinction.' },
|
|
@@ -109,6 +118,8 @@ export const docsZh = {
|
|
|
109
118
|
bestPractices: [
|
|
110
119
|
{ guidance: true, description: 'Provide a header to label the list and give context to screen readers.' },
|
|
111
120
|
{ guidance: true, description: 'Use start and end content slots to add icons, avatars, or badges to each item.' },
|
|
121
|
+
{ guidance: true, description: 'Set edge to line row text up with a heading above the list: flush for static rows, outset or bleed for rows in a Card, Section, or Dialog.' },
|
|
122
|
+
{ guidance: true, description: 'To line text up with a heading and keep room around the highlight where there is no Card, such as a sidebar, put the heading and the list in a Section with variant="transparent" and set edge="outset".' },
|
|
112
123
|
{ guidance: false, description: 'Place interactive elements inside an interactive list item; it creates nested click targets and confusing focus behavior.' },
|
|
113
124
|
{ guidance: false, description: 'Use a list for a single item or for laying out unrelated content; lists imply a meaningful collection.' },
|
|
114
125
|
{ guidance: false, description: 'Mix clickable and non-clickable items in the same list without clear visual distinction.' },
|
|
@@ -132,6 +143,8 @@ export const docsDense = {
|
|
|
132
143
|
bestPractices: [
|
|
133
144
|
{ guidance: true, description: 'Provide a header to label the list and give context to screen readers.' },
|
|
134
145
|
{ guidance: true, description: 'Use start and end content slots to add icons, avatars, or badges to each item.' },
|
|
146
|
+
{ guidance: true, description: 'Set edge to line row text up with a heading above the list: flush for static rows, outset or bleed for rows in a Card, Section, or Dialog.' },
|
|
147
|
+
{ guidance: true, description: 'To line text up with a heading and keep room around the highlight where there is no Card, such as a sidebar, put the heading and the list in a Section with variant="transparent" and set edge="outset".' },
|
|
135
148
|
{ guidance: false, description: 'Place interactive elements inside an interactive list item; it creates nested click targets and confusing focus behavior.' },
|
|
136
149
|
{ guidance: false, description: 'Use a list for a single item or for laying out unrelated content; lists imply a meaningful collection.' },
|
|
137
150
|
{ guidance: false, description: 'Mix clickable and non-clickable items in the same list without clear visual distinction.' },
|