@astryxdesign/core 0.4.4 → 0.4.5-canary.1fdecb1
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 +40 -0
- package/dist/BottomSheet/BottomSheet.d.ts +11 -2
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +4 -0
- package/dist/BottomSheet/BottomSheetPanel.d.ts +5 -2
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +65 -15
- package/dist/BottomSheet/index.d.ts +1 -1
- package/dist/BottomSheet/index.d.ts.map +1 -1
- package/dist/BottomSheet/snapOffsets.d.ts +57 -20
- package/dist/BottomSheet/snapOffsets.d.ts.map +1 -1
- package/dist/BottomSheet/snapOffsets.js +106 -30
- package/dist/BottomSheet/useSheetGestures.d.ts +13 -8
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
- package/dist/BottomSheet/useSheetGestures.js +160 -64
- package/dist/Calendar/Calendar.d.ts +17 -0
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +34 -3
- package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts +14 -0
- package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts.map +1 -0
- package/dist/Calendar/getStandaloneShortWeekdayNames.js +26 -0
- package/dist/Calendar/hooks/useCalendarConstraints.d.ts +22 -1
- package/dist/Calendar/hooks/useCalendarConstraints.d.ts.map +1 -1
- package/dist/Calendar/hooks/useCalendarConstraints.js +26 -4
- package/dist/Calendar/hooks/useCalendarDays.d.ts.map +1 -1
- package/dist/Calendar/hooks/useCalendarDays.js +14 -10
- package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts +47 -0
- package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts.map +1 -0
- package/dist/Calendar/standaloneShortWeekdayNames.generated.js +40 -0
- package/dist/Center/Center.d.ts +23 -1
- package/dist/Center/Center.d.ts.map +1 -1
- package/dist/Center/Center.js +12 -6
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +9 -0
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +6 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +6 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +38 -3
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +7 -2
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +3 -3
- package/dist/Field/FieldLabel.d.ts +2 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +21 -3
- package/dist/Field/InputClearButton.d.ts +2 -1
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +6 -1
- package/dist/FormLayout/FormLayout.d.ts +24 -2
- package/dist/FormLayout/FormLayout.d.ts.map +1 -1
- package/dist/FormLayout/FormLayout.js +7 -2
- package/dist/FormLayout/FormLayoutContext.d.ts +15 -2
- package/dist/FormLayout/FormLayoutContext.d.ts.map +1 -1
- package/dist/FormLayout/FormLayoutContext.js +19 -4
- package/dist/FormLayout/index.d.ts +1 -1
- package/dist/FormLayout/index.d.ts.map +1 -1
- package/dist/Item/Item.d.ts +9 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +45 -7
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +3 -2
- package/dist/Layout/container.stylex.d.ts +4 -2
- package/dist/Layout/container.stylex.d.ts.map +1 -1
- package/dist/Layout/container.stylex.js +19 -11
- package/dist/Layout/index.d.ts +1 -0
- package/dist/Layout/index.d.ts.map +1 -1
- package/dist/Layout/index.js +4 -0
- package/dist/Layout/padding.stylex.d.ts +315 -12
- package/dist/Layout/padding.stylex.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.js +389 -12
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +2 -1
- package/dist/Markdown/Markdown.d.ts +8 -0
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +31 -3
- package/dist/Markdown/parser.d.ts +14 -2
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +50 -2
- package/dist/MobileNav/MobileNav.d.ts +1 -0
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +24 -6
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +6 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +36 -3
- package/dist/Outline/parseOutlineFromMarkdown.d.ts +2 -0
- package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
- package/dist/Outline/parseOutlineFromMarkdown.js +5 -31
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +12 -1
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +3 -3
- package/dist/Section/Section.d.ts +36 -1
- package/dist/Section/Section.d.ts.map +1 -1
- package/dist/Section/Section.js +12 -2
- package/dist/Selector/Selector.d.ts +26 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +93 -15
- package/dist/Selector/SelectorOption.d.ts +14 -1
- package/dist/Selector/SelectorOption.d.ts.map +1 -1
- package/dist/Selector/SelectorOption.js +6 -0
- package/dist/Selector/SelectorRowLayoutContext.d.ts +8 -0
- package/dist/Selector/SelectorRowLayoutContext.d.ts.map +1 -0
- package/dist/Selector/SelectorRowLayoutContext.js +27 -0
- package/dist/Selector/types.d.ts +1 -0
- package/dist/Selector/types.d.ts.map +1 -1
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +2 -2
- package/dist/Stack/Stack.d.ts +23 -1
- package/dist/Stack/Stack.d.ts.map +1 -1
- package/dist/Stack/Stack.js +12 -6
- package/dist/StatusDot/StatusDot.d.ts +43 -3
- package/dist/StatusDot/StatusDot.d.ts.map +1 -1
- package/dist/StatusDot/StatusDot.js +42 -5
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +9 -0
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +6 -1
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +6 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +6 -1
- package/dist/astryx.css +40 -21
- package/dist/hooks/scrollbarGutter.d.ts +28 -0
- package/dist/hooks/scrollbarGutter.d.ts.map +1 -0
- package/dist/hooks/scrollbarGutter.js +103 -0
- package/dist/hooks/useResolvedRequired.d.ts +19 -0
- package/dist/hooks/useResolvedRequired.d.ts.map +1 -0
- package/dist/hooks/useResolvedRequired.js +40 -0
- package/dist/hooks/useScrollLock.d.ts +4 -0
- package/dist/hooks/useScrollLock.d.ts.map +1 -1
- package/dist/hooks/useScrollLock.js +13 -1
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +7 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +37 -4
- package/dist/utils/plainDate.d.ts +6 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +12 -0
- package/locales/af-ZA.json +958 -0
- package/locales/ar-SA.json +998 -0
- package/locales/ca-ES.json +974 -0
- package/locales/cs-CZ.json +990 -0
- package/locales/da-DK.json +966 -0
- package/locales/de-DE.json +966 -0
- package/locales/el-GR.json +990 -0
- package/locales/en.json +8 -0
- package/locales/es-ES.json +978 -0
- package/locales/fi-FI.json +990 -0
- package/locales/fr-FR.json +928 -0
- package/locales/he-IL.json +990 -0
- package/locales/hu-HU.json +990 -0
- package/locales/it-IT.json +978 -0
- package/locales/ja-JP.json +998 -0
- package/locales/ko-KR.json +990 -0
- package/locales/nl-NL.json +954 -0
- package/locales/no-NO.json +978 -0
- package/locales/pl-PL.json +982 -0
- package/locales/pseudo.json +6 -0
- package/locales/pt-BR.json +982 -0
- package/locales/pt-PT.json +982 -0
- package/locales/ro-RO.json +982 -0
- package/locales/ru-RU.json +990 -0
- package/locales/sr-SP.json +990 -0
- package/locales/sv-SE.json +986 -0
- package/locales/tr-TR.json +990 -0
- package/locales/uk-UA.json +990 -0
- package/locales/vi-VN.json +986 -0
- package/locales/zh-CN.json +998 -0
- package/locales/zh-TW.json +998 -0
- package/package.json +3 -3
- package/src/BottomSheet/BottomSheet.doc.mjs +36 -3
- package/src/BottomSheet/BottomSheet.test.tsx +177 -2
- package/src/BottomSheet/BottomSheet.tsx +16 -2
- package/src/BottomSheet/BottomSheetPanel.test.tsx +41 -0
- package/src/BottomSheet/BottomSheetPanel.tsx +95 -15
- package/src/BottomSheet/index.ts +5 -1
- package/src/BottomSheet/snapOffsets.test.ts +114 -47
- package/src/BottomSheet/snapOffsets.ts +119 -33
- package/src/BottomSheet/useSheetGestures.test.ts +113 -15
- package/src/BottomSheet/useSheetGestures.ts +196 -100
- package/src/Calendar/Calendar.doc.mjs +16 -0
- package/src/Calendar/Calendar.test.tsx +137 -0
- package/src/Calendar/Calendar.tsx +65 -2
- package/src/Calendar/getStandaloneShortWeekdayNames.test.ts +54 -0
- package/src/Calendar/getStandaloneShortWeekdayNames.ts +38 -0
- package/src/Calendar/hooks/useCalendarConstraints.ts +54 -3
- package/src/Calendar/hooks/useCalendarDays.ts +13 -10
- package/src/Calendar/standaloneShortWeekdayNames.generated.ts +50 -0
- package/src/Center/Center.doc.mjs +48 -0
- package/src/Center/Center.test.tsx +158 -0
- package/src/Center/Center.tsx +50 -9
- package/src/CheckboxInput/CheckboxInput.tsx +6 -0
- package/src/ComplexSelector/ComplexSelector.tsx +3 -1
- package/src/DateInput/DateInput.tsx +3 -1
- package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +81 -1
- package/src/DateRangeInput/DateRangeInput.tsx +72 -1
- package/src/DateTimeInput/DateTimeInput.tsx +4 -2
- package/src/Dialog/Dialog.test.tsx +24 -0
- package/src/Dialog/Dialog.tsx +3 -0
- package/src/Field/Field.doc.mjs +1 -0
- package/src/Field/FieldLabel.tsx +20 -4
- package/src/Field/InputClearButton.test.tsx +25 -0
- package/src/Field/InputClearButton.tsx +4 -1
- package/src/FormLayout/FormLayout.doc.mjs +13 -0
- package/src/FormLayout/FormLayout.test.tsx +181 -4
- package/src/FormLayout/FormLayout.tsx +33 -2
- package/src/FormLayout/FormLayoutContext.ts +22 -7
- package/src/FormLayout/index.ts +1 -1
- package/src/Item/Item.doc.mjs +1 -0
- package/src/Item/Item.test.tsx +50 -0
- package/src/Item/Item.tsx +40 -1
- package/src/Layer/useLayer.tsx +13 -2
- package/src/Layout/Layout.doc.mjs +18 -0
- package/src/Layout/container.stylex.ts +11 -3
- package/src/Layout/index.ts +4 -0
- package/src/Layout/overlayPaddingReset.test.tsx +222 -0
- package/src/Layout/padding.stylex.ts +192 -12
- package/src/Lightbox/Lightbox.tsx +2 -1
- package/src/Markdown/Markdown.doc.mjs +3 -0
- package/src/Markdown/Markdown.test.tsx +78 -0
- package/src/Markdown/Markdown.tsx +41 -1
- package/src/Markdown/parser.ts +60 -2
- package/src/MobileNav/MobileNav.tsx +61 -5
- package/src/MobileNav/MobileNavEntryAnimation.test.tsx +212 -0
- package/src/MobileNav/MobileNavScrollbarGutter.test.tsx +109 -0
- package/src/MultiSelector/MultiSelector.tsx +3 -1
- package/src/NumberInput/NumberInput.doc.mjs +24 -0
- package/src/NumberInput/NumberInput.test.tsx +138 -0
- package/src/NumberInput/NumberInput.tsx +43 -5
- package/src/Outline/Outline.doc.mjs +2 -0
- package/src/Outline/parseOutlineFromMarkdown.ts +10 -40
- package/src/RadioList/RadioList.tsx +9 -1
- package/src/Resizable/ResizeHandle.test.tsx +22 -0
- package/src/Resizable/ResizeHandle.tsx +9 -3
- package/src/Section/Section.doc.mjs +55 -0
- package/src/Section/Section.test.tsx +201 -4
- package/src/Section/Section.tsx +69 -0
- package/src/Selector/Selector.doc.mjs +16 -2
- package/src/Selector/Selector.test.tsx +524 -0
- package/src/Selector/Selector.tsx +161 -17
- package/src/Selector/SelectorOption.doc.mjs +7 -0
- package/src/Selector/SelectorOption.tsx +21 -0
- package/src/Selector/SelectorRowLayoutContext.ts +32 -0
- package/src/Selector/types.ts +4 -4
- package/src/Slider/Slider.tsx +10 -0
- package/src/Stack/Stack.doc.mjs +72 -0
- package/src/Stack/Stack.test.tsx +156 -0
- package/src/Stack/Stack.tsx +50 -8
- package/src/StatusDot/StatusDot.doc.mjs +13 -0
- package/src/StatusDot/StatusDot.test.tsx +115 -8
- package/src/StatusDot/StatusDot.tsx +74 -9
- package/src/Switch/Switch.tsx +6 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +20 -2
- package/src/TextArea/TextArea.tsx +3 -1
- package/src/TextInput/TextInput.tsx +3 -1
- package/src/TimeInput/TimeInput.tsx +3 -1
- package/src/hooks/scrollbarGutter.test.ts +167 -0
- package/src/hooks/scrollbarGutter.ts +121 -0
- package/src/hooks/useResolvedRequired.ts +42 -0
- package/src/hooks/useScrollLock.doc.mjs +4 -4
- package/src/hooks/useScrollLock.test.ts +73 -0
- package/src/hooks/useScrollLock.ts +14 -0
- package/src/theme/derivedVarRegistry.test.ts +14 -3
- package/src/theme/derivedVarRegistry.ts +4 -0
- package/src/theme/generateThemeRules.test.ts +79 -0
- package/src/theme/generateThemeRules.ts +49 -4
- package/src/utils/plainDate.test.ts +50 -0
- package/src/utils/plainDate.ts +12 -0
|
@@ -67,6 +67,10 @@ export const derivedVarRegistry: Record<string, DerivedVarEntry[]> = {
|
|
|
67
67
|
],
|
|
68
68
|
field: [{property: 'borderRadius', vars: ['--_field-radius']}],
|
|
69
69
|
hovercard: [{property: 'borderRadius', vars: ['--_hovercard-radius']}],
|
|
70
|
+
'number-input': [
|
|
71
|
+
{property: 'padding', expand: 'container'},
|
|
72
|
+
{property: 'borderRadius', vars: ['--_field-radius']},
|
|
73
|
+
],
|
|
70
74
|
popover: [{property: 'borderRadius', vars: ['--_popover-radius']}],
|
|
71
75
|
'progressbar-mark': [
|
|
72
76
|
{property: 'width', vars: ['--_progressbar-mark-width'], replaces: true},
|
|
@@ -584,3 +584,82 @@ describe('brutalist-style derived expansion', () => {
|
|
|
584
584
|
expect(rule).toContain('--_dropdown-menu-padding: 4px');
|
|
585
585
|
});
|
|
586
586
|
});
|
|
587
|
+
|
|
588
|
+
describe('physical padding longhands', () => {
|
|
589
|
+
const ruleFor = (
|
|
590
|
+
component: string,
|
|
591
|
+
base: Record<string, string>,
|
|
592
|
+
name = 'test-physical-padding',
|
|
593
|
+
) =>
|
|
594
|
+
generateThemeRules(
|
|
595
|
+
defineTheme({name, components: {[component]: {base}}}),
|
|
596
|
+
).find(r => r.includes(`.astryx-${component}`));
|
|
597
|
+
|
|
598
|
+
// `padding-top`/`padding-bottom` ARE the block edges in every horizontal
|
|
599
|
+
// writing mode, so the expansion can normalize them with no direction
|
|
600
|
+
// assumption. Without that, the padding lands raw on the element and the
|
|
601
|
+
// component's internals — the NumberInput stepper column, container bleed —
|
|
602
|
+
// read the default instead of what the theme set.
|
|
603
|
+
it.each([
|
|
604
|
+
['paddingTop', {paddingTop: '14px'}, 'block-start'],
|
|
605
|
+
['paddingBottom', {paddingBottom: '14px'}, 'block-end'],
|
|
606
|
+
])('routes %s through the container expansion', (_label, base, edge) => {
|
|
607
|
+
const rule = ruleFor('card', base);
|
|
608
|
+
expect(rule).toContain(`--astryx-card-padding-${edge}: 14px`);
|
|
609
|
+
expect(rule).not.toMatch(/[{;]\s*padding-(top|bottom):/);
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
it('normalizes both block edges together, asymmetrically', () => {
|
|
613
|
+
const rule = ruleFor('number-input', {
|
|
614
|
+
paddingTop: '14px',
|
|
615
|
+
paddingBottom: '6px',
|
|
616
|
+
});
|
|
617
|
+
expect(rule).toContain('--astryx-number-input-padding-block-start: 14px');
|
|
618
|
+
expect(rule).toContain('--astryx-number-input-padding-block-end: 6px');
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
it.each(['card', 'dialog', 'section', 'number-input'])(
|
|
622
|
+
'reaches %s, which expands its padding',
|
|
623
|
+
component => {
|
|
624
|
+
expect(ruleFor(component, {paddingTop: '14px'})).toContain(
|
|
625
|
+
`--astryx-${component}-padding-block-start: 14px`,
|
|
626
|
+
);
|
|
627
|
+
},
|
|
628
|
+
);
|
|
629
|
+
|
|
630
|
+
// THE RTL GUARD. `paddingLeft` is inline-start in LTR and inline-end in RTL,
|
|
631
|
+
// and the tokens are consumed by logical properties, so mapping it would
|
|
632
|
+
// silently move the padding to the other edge in RTL. It stays physical —
|
|
633
|
+
// which is what the author wrote — and does not reach the tokens.
|
|
634
|
+
it('leaves the direction-relative inline pair physical', () => {
|
|
635
|
+
const rule = ruleFor('card', {paddingLeft: '20px', paddingRight: '8px'});
|
|
636
|
+
expect(rule).toContain('padding-left: 20px');
|
|
637
|
+
expect(rule).toContain('padding-right: 8px');
|
|
638
|
+
expect(rule).not.toContain('--astryx-card-padding-inline');
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
it('expands the block edges while leaving left physical', () => {
|
|
642
|
+
const rule = ruleFor('card', {paddingTop: '14px', paddingLeft: '20px'});
|
|
643
|
+
expect(rule).toContain('--astryx-card-padding-block-start: 14px');
|
|
644
|
+
expect(rule).toContain('padding-left: 20px');
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
// The shorthand-plus-override case was the worst one: the tokens carried
|
|
648
|
+
// 10px while the element painted 14px on top, so every internal compensated
|
|
649
|
+
// by the wrong amount.
|
|
650
|
+
it('lets a physical longhand override the shorthand per edge', () => {
|
|
651
|
+
const rule = ruleFor('card', {padding: '10px', paddingTop: '14px'});
|
|
652
|
+
expect(rule).toContain('--astryx-card-padding-block-start: 14px');
|
|
653
|
+
expect(rule).toContain('--astryx-card-padding-block-end: 10px');
|
|
654
|
+
expect(rule).toContain('--astryx-card-padding-inline: 10px');
|
|
655
|
+
expect(rule).not.toMatch(/[{;]\s*padding(-top)?:/);
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
// A `vars` entry carries one value for the whole box, so a single physical
|
|
659
|
+
// edge must not feed it — only the container expansion takes these.
|
|
660
|
+
it('does not feed a single edge to a whole-box derived var', () => {
|
|
661
|
+
const rule = ruleFor('dropdown-menu', {paddingTop: '14px'});
|
|
662
|
+
expect(rule).toContain('padding-top: 14px');
|
|
663
|
+
expect(rule).not.toContain('--_dropdown-menu-padding');
|
|
664
|
+
});
|
|
665
|
+
});
|
|
@@ -128,6 +128,34 @@ const PADDING_PROPS = new Set([
|
|
|
128
128
|
'paddingInlineEnd',
|
|
129
129
|
]);
|
|
130
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Physical block-axis longhands, and the logical longhand each one *is* in
|
|
133
|
+
* every horizontal writing mode. Normalizing them costs no direction
|
|
134
|
+
* assumption, which is why they can join the container expansion.
|
|
135
|
+
*
|
|
136
|
+
* `paddingLeft`/`paddingRight` are deliberately absent. They are
|
|
137
|
+
* direction-relative — left is inline-start in LTR and inline-end in RTL — and
|
|
138
|
+
* the expansion's tokens are consumed by logical properties, so mapping them
|
|
139
|
+
* would put the padding on the opposite edge in RTL. They keep their physical
|
|
140
|
+
* meaning and land on the element as `padding-left`/`padding-right`; the cost
|
|
141
|
+
* is that a component's internals cannot see them.
|
|
142
|
+
*/
|
|
143
|
+
const PHYSICAL_BLOCK_PADDING_PROPS: Record<string, string> = {
|
|
144
|
+
paddingTop: 'paddingBlockStart',
|
|
145
|
+
paddingBottom: 'paddingBlockEnd',
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Every padding spelling the container expansion consumes. Kept separate from
|
|
150
|
+
* PADDING_PROPS, which also routes longhands to `vars`-style derived entries —
|
|
151
|
+
* those carry one value for the whole box, so a single physical edge must not
|
|
152
|
+
* reach them.
|
|
153
|
+
*/
|
|
154
|
+
const CONTAINER_PADDING_PROPS = new Set([
|
|
155
|
+
...PADDING_PROPS,
|
|
156
|
+
...Object.keys(PHYSICAL_BLOCK_PADDING_PROPS),
|
|
157
|
+
]);
|
|
158
|
+
|
|
131
159
|
interface ParsedPadding {
|
|
132
160
|
blockStart?: string;
|
|
133
161
|
blockEnd?: string;
|
|
@@ -138,12 +166,14 @@ interface ParsedPadding {
|
|
|
138
166
|
|
|
139
167
|
/**
|
|
140
168
|
* Parse CSS padding shorthand/longhand into block/inline values.
|
|
141
|
-
* Supports 1-3 value shorthands and
|
|
169
|
+
* Supports 1-3 value shorthands, logical properties, and the physical block
|
|
170
|
+
* longhands normalized by PHYSICAL_BLOCK_PADDING_PROPS.
|
|
142
171
|
*/
|
|
143
172
|
function parsePadding(props: [string, string][]): ParsedPadding {
|
|
144
173
|
const result: ParsedPadding = {};
|
|
145
174
|
|
|
146
|
-
for (const [
|
|
175
|
+
for (const [rawProp, value] of props) {
|
|
176
|
+
const prop = PHYSICAL_BLOCK_PADDING_PROPS[rawProp] ?? rawProp;
|
|
147
177
|
switch (prop) {
|
|
148
178
|
case 'padding': {
|
|
149
179
|
const parts = value.trim().split(/\s+/);
|
|
@@ -377,13 +407,28 @@ function generateComponentRules(
|
|
|
377
407
|
}
|
|
378
408
|
}
|
|
379
409
|
}
|
|
410
|
+
// A physical block longhand reaches the container expansion only. It
|
|
411
|
+
// names one edge, so it must not feed a `vars` entry above, which
|
|
412
|
+
// carries the padding for the whole box.
|
|
413
|
+
if (
|
|
414
|
+
prop in PHYSICAL_BLOCK_PADDING_PROPS &&
|
|
415
|
+
getDerivedVars(component, 'padding').some(
|
|
416
|
+
e => e.expand === 'container',
|
|
417
|
+
)
|
|
418
|
+
) {
|
|
419
|
+
containerExpanded = true;
|
|
420
|
+
}
|
|
380
421
|
}
|
|
381
422
|
|
|
382
423
|
// Container padding expansion: replace padding props with
|
|
383
424
|
// component-scoped container tokens for layout integration.
|
|
384
425
|
if (containerExpanded) {
|
|
385
|
-
const paddingProps = props.filter(([p]) =>
|
|
386
|
-
|
|
426
|
+
const paddingProps = props.filter(([p]) =>
|
|
427
|
+
CONTAINER_PADDING_PROPS.has(p),
|
|
428
|
+
);
|
|
429
|
+
const nonPaddingProps = props.filter(
|
|
430
|
+
([p]) => !CONTAINER_PADDING_PROPS.has(p),
|
|
431
|
+
);
|
|
387
432
|
const parsed = parsePadding(paddingProps);
|
|
388
433
|
const containerTokens = expandContainerPadding(component, parsed);
|
|
389
434
|
finalProps = [...nonPaddingProps, ...containerTokens];
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
plainDateDayOfWeek,
|
|
14
14
|
plainDateAddMonths,
|
|
15
15
|
plainDateAddDays,
|
|
16
|
+
plainDateDiffDays,
|
|
16
17
|
plainDateToInstant,
|
|
17
18
|
plainDateFromInstant,
|
|
18
19
|
plainDateIsBefore,
|
|
@@ -312,6 +313,55 @@ describe('plainDateAddDays', () => {
|
|
|
312
313
|
});
|
|
313
314
|
});
|
|
314
315
|
|
|
316
|
+
describe('plainDateDiffDays', () => {
|
|
317
|
+
it('counts whole days forward', () => {
|
|
318
|
+
expect(
|
|
319
|
+
plainDateDiffDays(
|
|
320
|
+
{year: 2026, month: 1, day: 10},
|
|
321
|
+
{year: 2026, month: 1, day: 17},
|
|
322
|
+
),
|
|
323
|
+
).toBe(7);
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
it('is negative when the second date is earlier', () => {
|
|
327
|
+
expect(
|
|
328
|
+
plainDateDiffDays(
|
|
329
|
+
{year: 2026, month: 1, day: 10},
|
|
330
|
+
{year: 2026, month: 1, day: 3},
|
|
331
|
+
),
|
|
332
|
+
).toBe(-7);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it('is zero for the same day', () => {
|
|
336
|
+
expect(
|
|
337
|
+
plainDateDiffDays(
|
|
338
|
+
{year: 2026, month: 6, day: 15},
|
|
339
|
+
{year: 2026, month: 6, day: 15},
|
|
340
|
+
),
|
|
341
|
+
).toBe(0);
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
it('counts across month and year boundaries', () => {
|
|
345
|
+
expect(
|
|
346
|
+
plainDateDiffDays(
|
|
347
|
+
{year: 2025, month: 12, day: 30},
|
|
348
|
+
{year: 2026, month: 1, day: 2},
|
|
349
|
+
),
|
|
350
|
+
).toBe(3);
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
it('ignores DST — every calendar day counts once across a spring-forward', () => {
|
|
354
|
+
// US DST 2026 begins Mar 8. The gap Mar 7 → Mar 9 is two calendar days
|
|
355
|
+
// even though one of them is 23 hours long.
|
|
356
|
+
expect(
|
|
357
|
+
plainDateDiffDays(
|
|
358
|
+
{year: 2026, month: 3, day: 7},
|
|
359
|
+
{year: 2026, month: 3, day: 9},
|
|
360
|
+
),
|
|
361
|
+
).toBe(2);
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
|
|
315
365
|
describe('plainDateToInstant / plainDateFromInstant', () => {
|
|
316
366
|
it('converts a PlainDate to midnight in the requested timezone', () => {
|
|
317
367
|
expect(
|
package/src/utils/plainDate.ts
CHANGED
|
@@ -88,6 +88,18 @@ export function plainDateAddDays(pd: PlainDate, n: number): PlainDate {
|
|
|
88
88
|
return plainDateFromDate(d);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Whole calendar days from `a` to `b`, ignoring time of day. Positive when
|
|
93
|
+
* `b` is after `a`, negative when before. Uses UTC midnight so DST shifts
|
|
94
|
+
* never add or drop a day.
|
|
95
|
+
*/
|
|
96
|
+
export function plainDateDiffDays(a: PlainDate, b: PlainDate): number {
|
|
97
|
+
const msPerDay = 24 * 60 * 60 * 1000;
|
|
98
|
+
const aUTC = Date.UTC(a.year, a.month - 1, a.day);
|
|
99
|
+
const bUTC = Date.UTC(b.year, b.month - 1, b.day);
|
|
100
|
+
return Math.round((bUTC - aUTC) / msPerDay);
|
|
101
|
+
}
|
|
102
|
+
|
|
91
103
|
/**
|
|
92
104
|
* The wall-clock fields an instant reads as in a given zone.
|
|
93
105
|
*
|