@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.
Files changed (275) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/BottomSheet/BottomSheet.d.ts +11 -2
  3. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  4. package/dist/BottomSheet/BottomSheet.js +4 -0
  5. package/dist/BottomSheet/BottomSheetPanel.d.ts +5 -2
  6. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  7. package/dist/BottomSheet/BottomSheetPanel.js +65 -15
  8. package/dist/BottomSheet/index.d.ts +1 -1
  9. package/dist/BottomSheet/index.d.ts.map +1 -1
  10. package/dist/BottomSheet/snapOffsets.d.ts +57 -20
  11. package/dist/BottomSheet/snapOffsets.d.ts.map +1 -1
  12. package/dist/BottomSheet/snapOffsets.js +106 -30
  13. package/dist/BottomSheet/useSheetGestures.d.ts +13 -8
  14. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  15. package/dist/BottomSheet/useSheetGestures.js +160 -64
  16. package/dist/Calendar/Calendar.d.ts +17 -0
  17. package/dist/Calendar/Calendar.d.ts.map +1 -1
  18. package/dist/Calendar/Calendar.js +34 -3
  19. package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts +14 -0
  20. package/dist/Calendar/getStandaloneShortWeekdayNames.d.ts.map +1 -0
  21. package/dist/Calendar/getStandaloneShortWeekdayNames.js +26 -0
  22. package/dist/Calendar/hooks/useCalendarConstraints.d.ts +22 -1
  23. package/dist/Calendar/hooks/useCalendarConstraints.d.ts.map +1 -1
  24. package/dist/Calendar/hooks/useCalendarConstraints.js +26 -4
  25. package/dist/Calendar/hooks/useCalendarDays.d.ts.map +1 -1
  26. package/dist/Calendar/hooks/useCalendarDays.js +14 -10
  27. package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts +47 -0
  28. package/dist/Calendar/standaloneShortWeekdayNames.generated.d.ts.map +1 -0
  29. package/dist/Calendar/standaloneShortWeekdayNames.generated.js +40 -0
  30. package/dist/Center/Center.d.ts +23 -1
  31. package/dist/Center/Center.d.ts.map +1 -1
  32. package/dist/Center/Center.js +12 -6
  33. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  34. package/dist/CheckboxInput/CheckboxInput.js +9 -0
  35. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  36. package/dist/ComplexSelector/ComplexSelector.js +6 -1
  37. package/dist/DateInput/DateInput.d.ts.map +1 -1
  38. package/dist/DateInput/DateInput.js +6 -1
  39. package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
  40. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  41. package/dist/DateRangeInput/DateRangeInput.js +38 -3
  42. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  43. package/dist/DateTimeInput/DateTimeInput.js +7 -2
  44. package/dist/Dialog/Dialog.d.ts.map +1 -1
  45. package/dist/Dialog/Dialog.js +3 -3
  46. package/dist/Field/FieldLabel.d.ts +2 -1
  47. package/dist/Field/FieldLabel.d.ts.map +1 -1
  48. package/dist/Field/FieldLabel.js +21 -3
  49. package/dist/Field/InputClearButton.d.ts +2 -1
  50. package/dist/Field/InputClearButton.d.ts.map +1 -1
  51. package/dist/Field/InputClearButton.js +6 -1
  52. package/dist/FormLayout/FormLayout.d.ts +24 -2
  53. package/dist/FormLayout/FormLayout.d.ts.map +1 -1
  54. package/dist/FormLayout/FormLayout.js +7 -2
  55. package/dist/FormLayout/FormLayoutContext.d.ts +15 -2
  56. package/dist/FormLayout/FormLayoutContext.d.ts.map +1 -1
  57. package/dist/FormLayout/FormLayoutContext.js +19 -4
  58. package/dist/FormLayout/index.d.ts +1 -1
  59. package/dist/FormLayout/index.d.ts.map +1 -1
  60. package/dist/Item/Item.d.ts +9 -1
  61. package/dist/Item/Item.d.ts.map +1 -1
  62. package/dist/Item/Item.js +45 -7
  63. package/dist/Layer/useLayer.d.ts.map +1 -1
  64. package/dist/Layer/useLayer.js +3 -2
  65. package/dist/Layout/container.stylex.d.ts +4 -2
  66. package/dist/Layout/container.stylex.d.ts.map +1 -1
  67. package/dist/Layout/container.stylex.js +19 -11
  68. package/dist/Layout/index.d.ts +1 -0
  69. package/dist/Layout/index.d.ts.map +1 -1
  70. package/dist/Layout/index.js +4 -0
  71. package/dist/Layout/padding.stylex.d.ts +315 -12
  72. package/dist/Layout/padding.stylex.d.ts.map +1 -1
  73. package/dist/Layout/padding.stylex.js +389 -12
  74. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  75. package/dist/Lightbox/Lightbox.js +2 -1
  76. package/dist/Markdown/Markdown.d.ts +8 -0
  77. package/dist/Markdown/Markdown.d.ts.map +1 -1
  78. package/dist/Markdown/Markdown.js +31 -3
  79. package/dist/Markdown/parser.d.ts +14 -2
  80. package/dist/Markdown/parser.d.ts.map +1 -1
  81. package/dist/Markdown/parser.js +50 -2
  82. package/dist/MobileNav/MobileNav.d.ts +1 -0
  83. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  84. package/dist/MobileNav/MobileNav.js +24 -6
  85. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  86. package/dist/MultiSelector/MultiSelector.js +6 -1
  87. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  88. package/dist/NumberInput/NumberInput.js +36 -3
  89. package/dist/Outline/parseOutlineFromMarkdown.d.ts +2 -0
  90. package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
  91. package/dist/Outline/parseOutlineFromMarkdown.js +5 -31
  92. package/dist/RadioList/RadioList.d.ts.map +1 -1
  93. package/dist/RadioList/RadioList.js +12 -1
  94. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  95. package/dist/Resizable/ResizeHandle.js +3 -3
  96. package/dist/Section/Section.d.ts +36 -1
  97. package/dist/Section/Section.d.ts.map +1 -1
  98. package/dist/Section/Section.js +12 -2
  99. package/dist/Selector/Selector.d.ts +26 -1
  100. package/dist/Selector/Selector.d.ts.map +1 -1
  101. package/dist/Selector/Selector.js +93 -15
  102. package/dist/Selector/SelectorOption.d.ts +14 -1
  103. package/dist/Selector/SelectorOption.d.ts.map +1 -1
  104. package/dist/Selector/SelectorOption.js +6 -0
  105. package/dist/Selector/SelectorRowLayoutContext.d.ts +8 -0
  106. package/dist/Selector/SelectorRowLayoutContext.d.ts.map +1 -0
  107. package/dist/Selector/SelectorRowLayoutContext.js +27 -0
  108. package/dist/Selector/types.d.ts +1 -0
  109. package/dist/Selector/types.d.ts.map +1 -1
  110. package/dist/Slider/Slider.d.ts.map +1 -1
  111. package/dist/Slider/Slider.js +2 -2
  112. package/dist/Stack/Stack.d.ts +23 -1
  113. package/dist/Stack/Stack.d.ts.map +1 -1
  114. package/dist/Stack/Stack.js +12 -6
  115. package/dist/StatusDot/StatusDot.d.ts +43 -3
  116. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  117. package/dist/StatusDot/StatusDot.js +42 -5
  118. package/dist/Switch/Switch.d.ts.map +1 -1
  119. package/dist/Switch/Switch.js +9 -0
  120. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  121. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
  122. package/dist/TextArea/TextArea.d.ts.map +1 -1
  123. package/dist/TextArea/TextArea.js +6 -1
  124. package/dist/TextInput/TextInput.d.ts.map +1 -1
  125. package/dist/TextInput/TextInput.js +6 -1
  126. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  127. package/dist/TimeInput/TimeInput.js +6 -1
  128. package/dist/astryx.css +40 -21
  129. package/dist/hooks/scrollbarGutter.d.ts +28 -0
  130. package/dist/hooks/scrollbarGutter.d.ts.map +1 -0
  131. package/dist/hooks/scrollbarGutter.js +103 -0
  132. package/dist/hooks/useResolvedRequired.d.ts +19 -0
  133. package/dist/hooks/useResolvedRequired.d.ts.map +1 -0
  134. package/dist/hooks/useResolvedRequired.js +40 -0
  135. package/dist/hooks/useScrollLock.d.ts +4 -0
  136. package/dist/hooks/useScrollLock.d.ts.map +1 -1
  137. package/dist/hooks/useScrollLock.js +13 -1
  138. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  139. package/dist/theme/derivedVarRegistry.js +7 -0
  140. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  141. package/dist/theme/generateThemeRules.js +37 -4
  142. package/dist/utils/plainDate.d.ts +6 -0
  143. package/dist/utils/plainDate.d.ts.map +1 -1
  144. package/dist/utils/plainDate.js +12 -0
  145. package/locales/af-ZA.json +958 -0
  146. package/locales/ar-SA.json +998 -0
  147. package/locales/ca-ES.json +974 -0
  148. package/locales/cs-CZ.json +990 -0
  149. package/locales/da-DK.json +966 -0
  150. package/locales/de-DE.json +966 -0
  151. package/locales/el-GR.json +990 -0
  152. package/locales/en.json +8 -0
  153. package/locales/es-ES.json +978 -0
  154. package/locales/fi-FI.json +990 -0
  155. package/locales/fr-FR.json +928 -0
  156. package/locales/he-IL.json +990 -0
  157. package/locales/hu-HU.json +990 -0
  158. package/locales/it-IT.json +978 -0
  159. package/locales/ja-JP.json +998 -0
  160. package/locales/ko-KR.json +990 -0
  161. package/locales/nl-NL.json +954 -0
  162. package/locales/no-NO.json +978 -0
  163. package/locales/pl-PL.json +982 -0
  164. package/locales/pseudo.json +6 -0
  165. package/locales/pt-BR.json +982 -0
  166. package/locales/pt-PT.json +982 -0
  167. package/locales/ro-RO.json +982 -0
  168. package/locales/ru-RU.json +990 -0
  169. package/locales/sr-SP.json +990 -0
  170. package/locales/sv-SE.json +986 -0
  171. package/locales/tr-TR.json +990 -0
  172. package/locales/uk-UA.json +990 -0
  173. package/locales/vi-VN.json +986 -0
  174. package/locales/zh-CN.json +998 -0
  175. package/locales/zh-TW.json +998 -0
  176. package/package.json +3 -3
  177. package/src/BottomSheet/BottomSheet.doc.mjs +36 -3
  178. package/src/BottomSheet/BottomSheet.test.tsx +177 -2
  179. package/src/BottomSheet/BottomSheet.tsx +16 -2
  180. package/src/BottomSheet/BottomSheetPanel.test.tsx +41 -0
  181. package/src/BottomSheet/BottomSheetPanel.tsx +95 -15
  182. package/src/BottomSheet/index.ts +5 -1
  183. package/src/BottomSheet/snapOffsets.test.ts +114 -47
  184. package/src/BottomSheet/snapOffsets.ts +119 -33
  185. package/src/BottomSheet/useSheetGestures.test.ts +113 -15
  186. package/src/BottomSheet/useSheetGestures.ts +196 -100
  187. package/src/Calendar/Calendar.doc.mjs +16 -0
  188. package/src/Calendar/Calendar.test.tsx +137 -0
  189. package/src/Calendar/Calendar.tsx +65 -2
  190. package/src/Calendar/getStandaloneShortWeekdayNames.test.ts +54 -0
  191. package/src/Calendar/getStandaloneShortWeekdayNames.ts +38 -0
  192. package/src/Calendar/hooks/useCalendarConstraints.ts +54 -3
  193. package/src/Calendar/hooks/useCalendarDays.ts +13 -10
  194. package/src/Calendar/standaloneShortWeekdayNames.generated.ts +50 -0
  195. package/src/Center/Center.doc.mjs +48 -0
  196. package/src/Center/Center.test.tsx +158 -0
  197. package/src/Center/Center.tsx +50 -9
  198. package/src/CheckboxInput/CheckboxInput.tsx +6 -0
  199. package/src/ComplexSelector/ComplexSelector.tsx +3 -1
  200. package/src/DateInput/DateInput.tsx +3 -1
  201. package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
  202. package/src/DateRangeInput/DateRangeInput.test.tsx +81 -1
  203. package/src/DateRangeInput/DateRangeInput.tsx +72 -1
  204. package/src/DateTimeInput/DateTimeInput.tsx +4 -2
  205. package/src/Dialog/Dialog.test.tsx +24 -0
  206. package/src/Dialog/Dialog.tsx +3 -0
  207. package/src/Field/Field.doc.mjs +1 -0
  208. package/src/Field/FieldLabel.tsx +20 -4
  209. package/src/Field/InputClearButton.test.tsx +25 -0
  210. package/src/Field/InputClearButton.tsx +4 -1
  211. package/src/FormLayout/FormLayout.doc.mjs +13 -0
  212. package/src/FormLayout/FormLayout.test.tsx +181 -4
  213. package/src/FormLayout/FormLayout.tsx +33 -2
  214. package/src/FormLayout/FormLayoutContext.ts +22 -7
  215. package/src/FormLayout/index.ts +1 -1
  216. package/src/Item/Item.doc.mjs +1 -0
  217. package/src/Item/Item.test.tsx +50 -0
  218. package/src/Item/Item.tsx +40 -1
  219. package/src/Layer/useLayer.tsx +13 -2
  220. package/src/Layout/Layout.doc.mjs +18 -0
  221. package/src/Layout/container.stylex.ts +11 -3
  222. package/src/Layout/index.ts +4 -0
  223. package/src/Layout/overlayPaddingReset.test.tsx +222 -0
  224. package/src/Layout/padding.stylex.ts +192 -12
  225. package/src/Lightbox/Lightbox.tsx +2 -1
  226. package/src/Markdown/Markdown.doc.mjs +3 -0
  227. package/src/Markdown/Markdown.test.tsx +78 -0
  228. package/src/Markdown/Markdown.tsx +41 -1
  229. package/src/Markdown/parser.ts +60 -2
  230. package/src/MobileNav/MobileNav.tsx +61 -5
  231. package/src/MobileNav/MobileNavEntryAnimation.test.tsx +212 -0
  232. package/src/MobileNav/MobileNavScrollbarGutter.test.tsx +109 -0
  233. package/src/MultiSelector/MultiSelector.tsx +3 -1
  234. package/src/NumberInput/NumberInput.doc.mjs +24 -0
  235. package/src/NumberInput/NumberInput.test.tsx +138 -0
  236. package/src/NumberInput/NumberInput.tsx +43 -5
  237. package/src/Outline/Outline.doc.mjs +2 -0
  238. package/src/Outline/parseOutlineFromMarkdown.ts +10 -40
  239. package/src/RadioList/RadioList.tsx +9 -1
  240. package/src/Resizable/ResizeHandle.test.tsx +22 -0
  241. package/src/Resizable/ResizeHandle.tsx +9 -3
  242. package/src/Section/Section.doc.mjs +55 -0
  243. package/src/Section/Section.test.tsx +201 -4
  244. package/src/Section/Section.tsx +69 -0
  245. package/src/Selector/Selector.doc.mjs +16 -2
  246. package/src/Selector/Selector.test.tsx +524 -0
  247. package/src/Selector/Selector.tsx +161 -17
  248. package/src/Selector/SelectorOption.doc.mjs +7 -0
  249. package/src/Selector/SelectorOption.tsx +21 -0
  250. package/src/Selector/SelectorRowLayoutContext.ts +32 -0
  251. package/src/Selector/types.ts +4 -4
  252. package/src/Slider/Slider.tsx +10 -0
  253. package/src/Stack/Stack.doc.mjs +72 -0
  254. package/src/Stack/Stack.test.tsx +156 -0
  255. package/src/Stack/Stack.tsx +50 -8
  256. package/src/StatusDot/StatusDot.doc.mjs +13 -0
  257. package/src/StatusDot/StatusDot.test.tsx +115 -8
  258. package/src/StatusDot/StatusDot.tsx +74 -9
  259. package/src/Switch/Switch.tsx +6 -0
  260. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +20 -2
  261. package/src/TextArea/TextArea.tsx +3 -1
  262. package/src/TextInput/TextInput.tsx +3 -1
  263. package/src/TimeInput/TimeInput.tsx +3 -1
  264. package/src/hooks/scrollbarGutter.test.ts +167 -0
  265. package/src/hooks/scrollbarGutter.ts +121 -0
  266. package/src/hooks/useResolvedRequired.ts +42 -0
  267. package/src/hooks/useScrollLock.doc.mjs +4 -4
  268. package/src/hooks/useScrollLock.test.ts +73 -0
  269. package/src/hooks/useScrollLock.ts +14 -0
  270. package/src/theme/derivedVarRegistry.test.ts +14 -3
  271. package/src/theme/derivedVarRegistry.ts +4 -0
  272. package/src/theme/generateThemeRules.test.ts +79 -0
  273. package/src/theme/generateThemeRules.ts +49 -4
  274. package/src/utils/plainDate.test.ts +50 -0
  275. package/src/utils/plainDate.ts +12 -0
@@ -13,6 +13,22 @@ import {describe, it, expect, vi} from 'vitest';
13
13
  import {render, screen} from '@testing-library/react';
14
14
  import {Center} from './Center';
15
15
 
16
+ /**
17
+ * The functional class output, as an order-insensitive set. StyleX's dev
18
+ * runtime also emits readable debug classes naming the style object a
19
+ * declaration came from ("padding__paddingBlockStyles.2"); those record
20
+ * provenance rather than applied CSS and survive even when the declaration
21
+ * they name loses a merge, so they are dropped here.
22
+ */
23
+ function classSet(el: HTMLElement): Set<string> {
24
+ return new Set(
25
+ el.className
26
+ .split(' ')
27
+ .filter(Boolean)
28
+ .filter(c => !c.includes('__') && !c.includes('.')),
29
+ );
30
+ }
31
+
16
32
  describe('Center', () => {
17
33
  it('renders and centers children (both axes by default)', () => {
18
34
  render(
@@ -207,4 +223,146 @@ describe('Center', () => {
207
223
  const element = screen.getByTestId('center');
208
224
  expect(element.tagName).toBe('DIV');
209
225
  });
226
+
227
+ it('applies a class when paddingBlockStart is set on its own', () => {
228
+ const {rerender} = render(
229
+ <Center data-testid="center">
230
+ <div>Content</div>
231
+ </Center>,
232
+ );
233
+ const baseline = screen.getByTestId('center').className;
234
+ rerender(
235
+ <Center paddingBlockStart={2} data-testid="center">
236
+ <div>Content</div>
237
+ </Center>,
238
+ );
239
+ expect(screen.getByTestId('center').className).not.toBe(baseline);
240
+ });
241
+
242
+ it('lets paddingBlockStart/paddingBlockEnd override only their own edge', () => {
243
+ // padding={4} + paddingBlockStart={2} must equal spelling every edge out:
244
+ // both inline edges and the block-end edge stay at 4.
245
+ const {rerender} = render(
246
+ <Center padding={4} paddingBlockStart={2} data-testid="center">
247
+ <div>Content</div>
248
+ </Center>,
249
+ );
250
+ const perEdge = classSet(screen.getByTestId('center'));
251
+ rerender(
252
+ <Center
253
+ paddingInline={4}
254
+ paddingBlockStart={2}
255
+ paddingBlockEnd={4}
256
+ data-testid="center">
257
+ <div>Content</div>
258
+ </Center>,
259
+ );
260
+ expect(perEdge).toEqual(classSet(screen.getByTestId('center')));
261
+ });
262
+
263
+ it('gives paddingBlockEnd precedence over paddingBlock', () => {
264
+ const {rerender} = render(
265
+ <Center paddingBlock={6} paddingBlockEnd={0} data-testid="center">
266
+ <div>Content</div>
267
+ </Center>,
268
+ );
269
+ const overridden = classSet(screen.getByTestId('center'));
270
+ rerender(
271
+ <Center paddingBlockStart={6} paddingBlockEnd={0} data-testid="center">
272
+ <div>Content</div>
273
+ </Center>,
274
+ );
275
+ expect(overridden).toEqual(classSet(screen.getByTestId('center')));
276
+ });
277
+
278
+ it('leaves padding/paddingBlock output unchanged when no edge prop is set', () => {
279
+ const {rerender} = render(
280
+ <Center padding={3} data-testid="center">
281
+ <div>Content</div>
282
+ </Center>,
283
+ );
284
+ const uniform = classSet(screen.getByTestId('center'));
285
+ rerender(
286
+ <Center paddingInline={3} paddingBlock={3} data-testid="center">
287
+ <div>Content</div>
288
+ </Center>,
289
+ );
290
+ expect(uniform).toEqual(classSet(screen.getByTestId('center')));
291
+ });
292
+
293
+ it('applies a class when paddingInlineStart is set on its own', () => {
294
+ const {rerender} = render(
295
+ <Center data-testid="center">
296
+ <div>Content</div>
297
+ </Center>,
298
+ );
299
+ const baseline = screen.getByTestId('center').className;
300
+ rerender(
301
+ <Center paddingInlineStart={2} data-testid="center">
302
+ <div>Content</div>
303
+ </Center>,
304
+ );
305
+ expect(screen.getByTestId('center').className).not.toBe(baseline);
306
+ });
307
+
308
+ it('lets paddingInlineStart/paddingInlineEnd override only their own edge', () => {
309
+ const {rerender} = render(
310
+ <Center padding={4} paddingInlineStart={2} data-testid="center">
311
+ <div>Content</div>
312
+ </Center>,
313
+ );
314
+ const perEdge = classSet(screen.getByTestId('center'));
315
+ rerender(
316
+ <Center
317
+ paddingInlineStart={2}
318
+ paddingInlineEnd={4}
319
+ paddingBlock={4}
320
+ data-testid="center">
321
+ <div>Content</div>
322
+ </Center>,
323
+ );
324
+ expect(perEdge).toEqual(classSet(screen.getByTestId('center')));
325
+ });
326
+
327
+ it('gives paddingInlineEnd precedence over paddingInline', () => {
328
+ const {rerender} = render(
329
+ <Center paddingInline={6} paddingInlineEnd={0} data-testid="center">
330
+ <div>Content</div>
331
+ </Center>,
332
+ );
333
+ const overridden = classSet(screen.getByTestId('center'));
334
+ rerender(
335
+ <Center paddingInlineStart={6} paddingInlineEnd={0} data-testid="center">
336
+ <div>Content</div>
337
+ </Center>,
338
+ );
339
+ expect(overridden).toEqual(classSet(screen.getByTestId('center')));
340
+ });
341
+
342
+ it('resolves all four edges independently', () => {
343
+ // One prop per edge, each a different step: the four-edge spelling and the
344
+ // shorthand-plus-overrides spelling must agree.
345
+ const {rerender} = render(
346
+ <Center
347
+ paddingInlineStart={1}
348
+ paddingInlineEnd={2}
349
+ paddingBlockStart={3}
350
+ paddingBlockEnd={4}
351
+ data-testid="center">
352
+ <div>Content</div>
353
+ </Center>,
354
+ );
355
+ const explicit = classSet(screen.getByTestId('center'));
356
+ rerender(
357
+ <Center
358
+ padding={4}
359
+ paddingInlineStart={1}
360
+ paddingInlineEnd={2}
361
+ paddingBlockStart={3}
362
+ data-testid="center">
363
+ <div>Content</div>
364
+ </Center>,
365
+ );
366
+ expect(explicit).toEqual(classSet(screen.getByTestId('center')));
367
+ });
210
368
  });
@@ -18,8 +18,10 @@ import type {BaseProps} from '../BaseProps';
18
18
  import * as stylex from '@stylexjs/stylex';
19
19
  import type {SizeValue, SpacingStep} from '../utils/types';
20
20
  import {
21
- paddingInlineStyles,
22
- paddingBlockStyles,
21
+ paddingInlineStartStyles,
22
+ paddingInlineEndStyles,
23
+ paddingBlockStartStyles,
24
+ paddingBlockEndStyles,
23
25
  } from '../Layout/padding.stylex';
24
26
  import {mergeProps} from '../utils';
25
27
  import {themeProps} from '../utils/themeProps';
@@ -106,12 +108,38 @@ export interface CenterProps extends BaseProps<HTMLDivElement> {
106
108
  */
107
109
  paddingInline?: SpacingStep;
108
110
 
111
+ /**
112
+ * Inline-start padding, using the spacing scale. Logical: the left edge in
113
+ * LTR, the right edge in RTL.
114
+ * Overrides `paddingInline` and `padding` on that edge only.
115
+ */
116
+ paddingInlineStart?: SpacingStep;
117
+
118
+ /**
119
+ * Inline-end padding, using the spacing scale. Logical: the right edge in
120
+ * LTR, the left edge in RTL.
121
+ * Overrides `paddingInline` and `padding` on that edge only.
122
+ */
123
+ paddingInlineEnd?: SpacingStep;
124
+
109
125
  /**
110
126
  * Block (vertical) padding, using the spacing scale.
111
127
  * Overrides `padding` on the block axis when both are set.
112
128
  */
113
129
  paddingBlock?: SpacingStep;
114
130
 
131
+ /**
132
+ * Block-start (top) padding, using the spacing scale.
133
+ * Overrides `paddingBlock` and `padding` on that edge only.
134
+ */
135
+ paddingBlockStart?: SpacingStep;
136
+
137
+ /**
138
+ * Block-end (bottom) padding, using the spacing scale.
139
+ * Overrides `paddingBlock` and `padding` on that edge only.
140
+ */
141
+ paddingBlockEnd?: SpacingStep;
142
+
115
143
  /**
116
144
  * Whether to make the container inline-flex (useful for text/icons).
117
145
  * @default false
@@ -145,7 +173,11 @@ export function Center({
145
173
  minHeight,
146
174
  padding,
147
175
  paddingInline,
176
+ paddingInlineStart,
177
+ paddingInlineEnd,
148
178
  paddingBlock,
179
+ paddingBlockStart,
180
+ paddingBlockEnd,
149
181
  isInline = false,
150
182
  children,
151
183
  xstyle,
@@ -154,10 +186,14 @@ export function Center({
154
186
  ref,
155
187
  ...props
156
188
  }: CenterProps) {
157
- // Resolve padding to per-axis values: `padding` sets both axes; `paddingInline`
158
- // / `paddingBlock` take precedence on their own axis when provided.
159
- const resolvedPaddingInline = paddingInline ?? padding;
160
- const resolvedPaddingBlock = paddingBlock ?? padding;
189
+ // Resolve padding to per-edge values. Most specific wins, per edge:
190
+ // edge prop -> axis prop -> `padding`.
191
+ const resolvedPaddingInlineStart =
192
+ paddingInlineStart ?? paddingInline ?? padding;
193
+ const resolvedPaddingInlineEnd = paddingInlineEnd ?? paddingInline ?? padding;
194
+ const resolvedPaddingBlockStart =
195
+ paddingBlockStart ?? paddingBlock ?? padding;
196
+ const resolvedPaddingBlockEnd = paddingBlockEnd ?? paddingBlock ?? padding;
161
197
 
162
198
  const stylexProps = mergeProps(
163
199
  themeProps('center', {axis}),
@@ -171,9 +207,14 @@ export function Center({
171
207
  maxWidth ?? null,
172
208
  minHeight ?? null,
173
209
  ),
174
- resolvedPaddingInline != null &&
175
- paddingInlineStyles[resolvedPaddingInline],
176
- resolvedPaddingBlock != null && paddingBlockStyles[resolvedPaddingBlock],
210
+ resolvedPaddingInlineStart != null &&
211
+ paddingInlineStartStyles[resolvedPaddingInlineStart],
212
+ resolvedPaddingInlineEnd != null &&
213
+ paddingInlineEndStyles[resolvedPaddingInlineEnd],
214
+ resolvedPaddingBlockStart != null &&
215
+ paddingBlockStartStyles[resolvedPaddingBlockStart],
216
+ resolvedPaddingBlockEnd != null &&
217
+ paddingBlockEndStyles[resolvedPaddingBlockEnd],
177
218
  xstyle,
178
219
  ),
179
220
  className,
@@ -47,6 +47,7 @@ import {useTooltip} from '../Tooltip';
47
47
  import {mergeProps, mergeRefs} from '../utils';
48
48
  import {indicatorScope} from '../Indicator/indicator.markers.stylex';
49
49
  import {useIndicatorFocusRing} from '../hooks/useIndicatorFocusRing';
50
+ import {useResolvedRequired} from '../hooks/useResolvedRequired';
50
51
  import {useIndicator} from '../Indicator';
51
52
  import {themeProps} from '../utils/themeProps';
52
53
  import {CheckboxListContext} from '../CheckboxList/CheckboxListContext';
@@ -301,6 +302,10 @@ export function CheckboxInput({
301
302
  const id = useId();
302
303
  const descriptionID = useId();
303
304
  const statusMessageID = useId();
305
+ // Announce the effective required state (form default included) while the
306
+ // native `required` stays bound to the explicit `isRequired` so a layout
307
+ // default never switches on browser validation.
308
+ const isEffectivelyRequired = useResolvedRequired({isRequired, isOptional});
304
309
 
305
310
  const [, startTransition] = useTransition();
306
311
  const [optimisticValue, setOptimisticValue] = useOptimistic(value);
@@ -421,6 +426,7 @@ export function CheckboxInput({
421
426
  form={isFocusableDisabled ? '' : undefined}
422
427
  readOnly={isReadOnly}
423
428
  required={isRequired}
429
+ aria-required={isEffectivelyRequired ? 'true' : undefined}
424
430
  onChange={e => {
425
431
  if (isDisabled || isBusy || isReadOnly) {
426
432
  return;
@@ -35,6 +35,7 @@ import {useTranslator} from '../i18n';
35
35
  import {layerAnimations} from '../Layer/layerAnimations.stylex';
36
36
  import type {LayerAlignment, LayerPlacement} from '../Layer/useLayer';
37
37
  import {usePopover} from '../Popover/usePopover';
38
+ import {useResolvedRequired} from '../hooks/useResolvedRequired';
38
39
  import {
39
40
  colorVars,
40
41
  durationVars,
@@ -344,6 +345,7 @@ export function ComplexSelector<Value>({
344
345
  ...props
345
346
  }: ComplexSelectorProps<Value>) {
346
347
  const t = useTranslator();
348
+ const isEffectivelyRequired = useResolvedRequired({isRequired, isOptional});
347
349
  const placeholder = placeholderFromProps ?? t('@astryx.selector.placeholder');
348
350
  const effectiveStatusVariant =
349
351
  variant === 'ghost' && statusVariant === 'attached'
@@ -497,7 +499,7 @@ export function ComplexSelector<Value>({
497
499
  aria-controls={contentId}
498
500
  aria-describedby={ariaDescribedBy}
499
501
  aria-labelledby={labelId}
500
- aria-required={isRequired ? 'true' : undefined}
502
+ aria-required={isEffectivelyRequired ? 'true' : undefined}
501
503
  aria-invalid={status?.type === 'error' ? 'true' : undefined}
502
504
  aria-busy={isBusy || undefined}
503
505
  disabled={isDisabled}
@@ -58,6 +58,7 @@ import {
58
58
  } from '../Calendar';
59
59
  import {useCalendarConstraints} from '../Calendar/hooks';
60
60
  import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
61
+ import {useResolvedRequired} from '../hooks/useResolvedRequired';
61
62
  import {usePopover} from '../Popover';
62
63
  import {useTooltip} from '../Tooltip';
63
64
  import {getInputARIA, isImeKeyEvent, parseDateInput} from '../utils';
@@ -399,6 +400,7 @@ export function DateInput({
399
400
  ...rest
400
401
  }: DateInputProps) {
401
402
  const t = useTranslator();
403
+ const isEffectivelyRequired = useResolvedRequired({isRequired, isOptional});
402
404
  const placeholder =
403
405
  placeholderFromProps ?? t('@astryx.dateInput.placeholder');
404
406
  const size = useSize(sizeProp, 'md');
@@ -737,7 +739,7 @@ export function DateInput({
737
739
  readOnly={showsDisabledMessage || undefined}
738
740
  aria-labelledby={ariaLabelledBy}
739
741
  aria-describedby={ariaDescribedBy}
740
- aria-required={isRequired === true ? 'true' : undefined}
742
+ aria-required={isEffectivelyRequired ? 'true' : undefined}
741
743
  aria-invalid={
742
744
  status?.type === 'error' || !isInputValid ? 'true' : undefined
743
745
  }
@@ -98,6 +98,18 @@ export const docs = {
98
98
  type: 'Array<(date: Date) => boolean>',
99
99
  description: 'Custom constraint functions to disable specific dates.',
100
100
  },
101
+ {
102
+ name: 'maxRangeSpan',
103
+ type: 'number',
104
+ description:
105
+ 'Maximum days a selected range may span, counting both endpoints (`7` = a 7-day window, start + 6). Once a start is picked, days beyond this distance are disabled so the range cannot stretch past the cap. Rolling window relative to the start — for fixed calendar bounds use `min`/`max`. Constrains selection only; it never rewrites a `value` already wider than the cap (flag that with `status`).',
106
+ },
107
+ {
108
+ name: 'minRangeSpan',
109
+ type: 'number',
110
+ description:
111
+ 'Minimum days a selected range must span, counting both endpoints (`2` forbids a single-day range). Once a start is picked, days closer than this are disabled. Defaults to 1 (same-day start and end allowed).',
112
+ },
101
113
  {
102
114
  name: 'presets',
103
115
  type: 'Array<DateRangePreset>',
@@ -313,6 +325,10 @@ export const docsDense = {
313
325
  min: 'min selectable date: ISODateString template literal type (YYYY-MM-DD); use string literal or cast `as ISODateString`',
314
326
  max: 'max selectable date: ISODateString template literal type (YYYY-MM-DD); use string literal or cast `as ISODateString`',
315
327
  dateConstraints: 'custom constraint fns to disable dates',
328
+ maxRangeSpan:
329
+ 'max days a range may span, both endpoints counted (7 = a 7-day window); caps the window from the picked start. Selection-only; does not rewrite an over-wide value',
330
+ minRangeSpan:
331
+ 'min days a range must span, both endpoints counted (2 forbids a single-day range); default 1',
316
332
  presets: 'preset ranges as quick-select options',
317
333
  hasClear: 'clear button when range is set (default true)',
318
334
  placeholder: 'placeholder when empty',
@@ -9,7 +9,7 @@
9
9
  * SYNC: When DateRangeInput.tsx changes, update tests to match new behavior
10
10
  */
11
11
 
12
- import {describe, it, expect, vi, beforeEach} from 'vitest';
12
+ import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
13
13
  import {render, screen, fireEvent, waitFor} from '@testing-library/react';
14
14
  import userEvent from '@testing-library/user-event';
15
15
 
@@ -712,3 +712,83 @@ describe('DateRangeInput disabled theme state', () => {
712
712
  expect(root).not.toHaveAttribute('data-disabled');
713
713
  });
714
714
  });
715
+
716
+ describe('DateRangeInput range-span forwarding', () => {
717
+ // Pin "today" so the popover opens on a known month and the day buttons we
718
+ // query are guaranteed to render.
719
+ beforeEach(() => {
720
+ vi.useFakeTimers();
721
+ vi.setSystemTime(new Date('2026-01-05T12:00:00Z'));
722
+ });
723
+ afterEach(() => {
724
+ vi.useRealTimers();
725
+ });
726
+
727
+ // The calendar renders in the top layer; jsdom keeps day buttons in the DOM
728
+ // but role queries skip them, so reach them by their machine-readable
729
+ // data-date (ISO) attribute — the same approach Calendar's own tests use.
730
+ const dayButton = (iso: string): HTMLButtonElement | null =>
731
+ document.querySelector<HTMLButtonElement>(`button[data-date="${iso}"]`);
732
+
733
+ it('forwards maxRangeSpan so the window caps after a start is picked', () => {
734
+ render(
735
+ <DateRangeInput
736
+ label="Reporting period"
737
+ value={null}
738
+ onChange={() => {}}
739
+ maxRangeSpan={7}
740
+ />,
741
+ );
742
+
743
+ fireEvent.click(getButton('Open calendar'));
744
+
745
+ // Before a start is picked, a far-off day is selectable.
746
+ expect(dayButton('2026-01-20')).not.toBeDisabled();
747
+
748
+ fireEvent.click(dayButton('2026-01-10') as HTMLButtonElement);
749
+
750
+ // A 7-day window spans start ± 6 days: Jan 16 is the edge, Jan 17 is out.
751
+ expect(dayButton('2026-01-16')).not.toBeDisabled();
752
+ expect(dayButton('2026-01-17')).toBeDisabled();
753
+ });
754
+
755
+ it('disables a preset whose range violates the span cap', () => {
756
+ const presets = [
757
+ {
758
+ label: 'Last 3 days',
759
+ getRange: (): DateRange => ({
760
+ start: '2026-01-08',
761
+ end: '2026-01-10',
762
+ }),
763
+ },
764
+ {
765
+ label: 'Last 30 days',
766
+ getRange: (): DateRange => ({
767
+ start: '2025-12-12',
768
+ end: '2026-01-10',
769
+ }),
770
+ },
771
+ ];
772
+ const handleChange = vi.fn();
773
+ render(
774
+ <DateRangeInput
775
+ label="Reporting period"
776
+ value={null}
777
+ onChange={handleChange}
778
+ maxRangeSpan={7}
779
+ presets={presets}
780
+ />,
781
+ );
782
+
783
+ fireEvent.click(getButton('Open calendar'));
784
+
785
+ // The 3-day preset fits the 7-day cap; the 30-day preset can't be committed.
786
+ const withinCap = getButton('Last 3 days');
787
+ const overCap = getButton('Last 30 days');
788
+ expect(withinCap).not.toBeDisabled();
789
+ expect(overCap).toBeDisabled();
790
+
791
+ fireEvent.click(overCap);
792
+ expect(handleChange).not.toHaveBeenCalled();
793
+ });
794
+ });
@@ -22,6 +22,7 @@ import {
22
22
  plainDateFromISO,
23
23
  plainDateToday,
24
24
  plainDateFormat,
25
+ plainDateDiffDays,
25
26
  DATE_FORMAT_SHORT,
26
27
  DATE_FORMAT_SHORT_WITH_YEAR,
27
28
  } from '../utils/plainDate';
@@ -60,6 +61,7 @@ import type {BaseProps} from '../BaseProps';
60
61
  import type {SizeValue} from '../utils/types';
61
62
  import {useSize} from '../SizeContext/SizeContext';
62
63
  import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
64
+ import {useResolvedRequired} from '../hooks/useResolvedRequired';
63
65
  import {themeProps} from '../utils/themeProps';
64
66
  import {focusOutlineStyles} from '../utils/focusOutline.stylex';
65
67
  import {stableClassName} from '../naming';
@@ -161,6 +163,11 @@ const styles = stylex.create({
161
163
  backgroundColor: colorVars['--color-accent-muted'],
162
164
  color: colorVars['--color-accent'],
163
165
  },
166
+ presetButtonDisabled: {
167
+ color: colorVars['--color-text-disabled'],
168
+ cursor: 'not-allowed',
169
+ backgroundColor: 'transparent',
170
+ },
164
171
  });
165
172
 
166
173
  const sizeStyles = stylex.create({
@@ -201,6 +208,34 @@ function isRangeEqual(a: DateRange | null, b: DateRange | null): boolean {
201
208
  return a.start === b.start && a.end === b.end;
202
209
  }
203
210
 
211
+ // A preset that would land outside the span bounds is disabled rather than
212
+ // allowed to override them: the cap is authoritative, so an out-of-window
213
+ // preset stays visible (discoverable) but non-committable, mirroring how the
214
+ // calendar disables out-of-window days. Spans count both endpoints.
215
+ function isRangeWithinSpan(
216
+ range: DateRange,
217
+ maxRangeSpan: number | undefined,
218
+ minRangeSpan: number | undefined,
219
+ ): boolean {
220
+ if (maxRangeSpan == null && minRangeSpan == null) {
221
+ return true;
222
+ }
223
+ const span =
224
+ Math.abs(
225
+ plainDateDiffDays(
226
+ plainDateFromISO(range.start),
227
+ plainDateFromISO(range.end),
228
+ ),
229
+ ) + 1;
230
+ if (maxRangeSpan != null && span > maxRangeSpan) {
231
+ return false;
232
+ }
233
+ if (minRangeSpan != null && span < minRangeSpan) {
234
+ return false;
235
+ }
236
+ return true;
237
+ }
238
+
204
239
  export interface DateRangeInputProps extends Omit<
205
240
  BaseProps,
206
241
  'onChange' | 'defaultValue'
@@ -303,6 +338,30 @@ export interface DateRangeInputProps extends Omit<
303
338
  */
304
339
  dateConstraints?: ReadonlyArray<(date: Date) => boolean>;
305
340
 
341
+ /**
342
+ * Maximum number of days the selected range may span, counting both
343
+ * endpoints — `maxRangeSpan={7}` allows a 7-day window (start + 6 days).
344
+ * Once a start date is picked, days beyond this distance from it are
345
+ * disabled, so the user can't stretch the range past the cap. Use for
346
+ * rolling windows like "at most a week from the chosen day"; for fixed
347
+ * calendar bounds use `min`/`max`.
348
+ *
349
+ * This constrains selection only — it never rewrites a `value` that is
350
+ * already wider than the cap. Surface such a value with `status` if you
351
+ * need to flag it. A `preset` whose range violates the cap is disabled
352
+ * (shown but not committable) rather than allowed to override it.
353
+ */
354
+ maxRangeSpan?: number;
355
+
356
+ /**
357
+ * Minimum number of days the selected range must span, counting both
358
+ * endpoints — `minRangeSpan={2}` forbids a single-day range. Once a start
359
+ * date is picked, days closer than this to it are disabled — except the
360
+ * start itself, which stays selectable as the active anchor. Defaults to 1
361
+ * (a same-day start and end is allowed).
362
+ */
363
+ minRangeSpan?: number;
364
+
306
365
  /**
307
366
  * Preset date ranges shown as quick-select options beside the calendar.
308
367
  */
@@ -396,6 +455,8 @@ export function DateRangeInput({
396
455
  min,
397
456
  max,
398
457
  dateConstraints,
458
+ maxRangeSpan,
459
+ minRangeSpan,
399
460
  presets,
400
461
  hasClear = true,
401
462
  placeholder: placeholderFromProps,
@@ -413,6 +474,7 @@ export function DateRangeInput({
413
474
  ...rest
414
475
  }: DateRangeInputProps) {
415
476
  const t = useTranslator();
477
+ const isEffectivelyRequired = useResolvedRequired({isRequired, isOptional});
416
478
  const placeholder =
417
479
  placeholderFromProps ?? t('@astryx.dateRangeInput.placeholder');
418
480
  const size = useSize(sizeProp, 'md');
@@ -609,7 +671,7 @@ export function DateRangeInput({
609
671
  aria-disabled={showsDisabledMessage ? 'true' : undefined}
610
672
  aria-label={triggerAriaLabel}
611
673
  aria-describedby={ariaDescribedBy}
612
- aria-required={isRequired === true ? 'true' : undefined}
674
+ aria-required={isEffectivelyRequired ? 'true' : undefined}
613
675
  aria-invalid={status?.type === 'error' ? 'true' : undefined}
614
676
  aria-busy={isBusy || undefined}
615
677
  aria-expanded={popover.isOpen}
@@ -642,6 +704,11 @@ export function DateRangeInput({
642
704
  {presets.map(preset => {
643
705
  const presetRange = preset.getRange();
644
706
  const isActive = isRangeEqual(value, presetRange);
707
+ const isPresetDisabled = !isRangeWithinSpan(
708
+ presetRange,
709
+ maxRangeSpan,
710
+ minRangeSpan,
711
+ );
645
712
  return (
646
713
  <button
647
714
  key={preset.label}
@@ -652,11 +719,13 @@ export function DateRangeInput({
652
719
  // marked with aria-current (not aria-selected, a listbox
653
720
  // concept that contradicted the Tab interaction) (forms-5).
654
721
  aria-current={isActive ? 'true' : undefined}
722
+ disabled={isPresetDisabled}
655
723
  onClick={() => handlePresetClick(preset)}
656
724
  {...stylex.props(
657
725
  focusOutlineStyles.focusVisible,
658
726
  styles.presetButton,
659
727
  isActive && styles.presetButtonActive,
728
+ isPresetDisabled && styles.presetButtonDisabled,
660
729
  )}>
661
730
  {preset.label}
662
731
  </button>
@@ -671,6 +740,8 @@ export function DateRangeInput({
671
740
  min={min}
672
741
  max={max}
673
742
  dateConstraints={dateConstraints}
743
+ maxRangeSpan={maxRangeSpan}
744
+ minRangeSpan={minRangeSpan}
674
745
  numberOfMonths={numberOfMonths}
675
746
  weekStartsOn={weekStartsOn}
676
747
  />
@@ -84,6 +84,7 @@ import {
84
84
  import type {BaseProps} from '../BaseProps';
85
85
  import type {SizeValue} from '../utils/types';
86
86
  import {useAnnounce} from '../hooks/useAnnounce';
87
+ import {useResolvedRequired} from '../hooks/useResolvedRequired';
87
88
  import {useSize} from '../SizeContext/SizeContext';
88
89
  import {themeProps} from '../utils/themeProps';
89
90
  import {focusOutlineStyles} from '../utils/focusOutline.stylex';
@@ -448,6 +449,7 @@ export function DateTimeInput({
448
449
  ...rest
449
450
  }: DateTimeInputProps) {
450
451
  const t = useTranslator();
452
+ const isEffectivelyRequired = useResolvedRequired({isRequired, isOptional});
451
453
  // Speaks arrow-key stepping results through the persistent live regions:
452
454
  // stepping programmatically rewrites a plain textbox's value, which screen
453
455
  // readers do not announce on their own (WCAG 4.1.2).
@@ -1009,7 +1011,7 @@ export function DateTimeInput({
1009
1011
  aria-disabled={showsDisabledMessage ? 'true' : undefined}
1010
1012
  readOnly={showsDisabledMessage || undefined}
1011
1013
  aria-describedby={ariaDescribedBy}
1012
- aria-required={isRequired === true ? 'true' : undefined}
1014
+ aria-required={isEffectivelyRequired ? 'true' : undefined}
1013
1015
  aria-invalid={
1014
1016
  status?.type === 'error' || !isDateInputValid ? 'true' : undefined
1015
1017
  }
@@ -1098,7 +1100,7 @@ export function DateTimeInput({
1098
1100
  timeLabel ?? t('@astryx.dateTimeInput.timeSuffix', {label})
1099
1101
  }
1100
1102
  aria-describedby={ariaDescribedBy}
1101
- aria-required={isRequired === true ? 'true' : undefined}
1103
+ aria-required={isEffectivelyRequired ? 'true' : undefined}
1102
1104
  aria-invalid={
1103
1105
  status?.type === 'error' || !isTimeInputValid ? 'true' : undefined
1104
1106
  }
@@ -461,4 +461,28 @@ describe('Dialog', () => {
461
461
  before.remove();
462
462
  });
463
463
  });
464
+
465
+ describe('container padding isolation', () => {
466
+ it('resets container padding custom properties on the root dialog element', () => {
467
+ render(
468
+ <Dialog isOpen={true} onOpenChange={() => {}}>
469
+ Content
470
+ </Dialog>,
471
+ );
472
+ const dialog = screen.getByRole('dialog');
473
+ const computed = window.getComputedStyle(dialog);
474
+ expect(
475
+ computed.getPropertyValue('--container-padding-inline-start'),
476
+ ).toBe('0px');
477
+ expect(computed.getPropertyValue('--container-padding-inline-end')).toBe(
478
+ '0px',
479
+ );
480
+ expect(computed.getPropertyValue('--container-padding-block-start')).toBe(
481
+ '0px',
482
+ );
483
+ expect(computed.getPropertyValue('--container-padding-block-end')).toBe(
484
+ '0px',
485
+ );
486
+ });
487
+ });
464
488
  });