@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
@@ -4,6 +4,22 @@ import {describe, it, expect} from 'vitest';
4
4
  import {render, screen} from '@testing-library/react';
5
5
  import {Section} from './Section';
6
6
 
7
+ /**
8
+ * The functional class output, as an order-insensitive set. StyleX's dev
9
+ * runtime also emits readable debug classes naming the style object a
10
+ * declaration came from ("padding__paddingBlockStyles.2"); those record
11
+ * provenance rather than applied CSS and survive even when the declaration
12
+ * they name loses a merge, so they are dropped here.
13
+ */
14
+ function classSet(el: HTMLElement): Set<string> {
15
+ return new Set(
16
+ el.className
17
+ .split(' ')
18
+ .filter(Boolean)
19
+ .filter(c => !c.includes('__') && !c.includes('.')),
20
+ );
21
+ }
22
+
7
23
  describe('Section', () => {
8
24
  it('renders with default props', () => {
9
25
  const {container} = render(<Section>Default section</Section>);
@@ -151,15 +167,27 @@ describe('Section', () => {
151
167
  expect(screen.getByTestId('custom-section')).toBeInTheDocument();
152
168
  });
153
169
 
154
- it('propagates explicit padding to nested sections via --astryx-section-padding', () => {
170
+ it('propagates explicit padding to nested sections via --_section-padding-propagated', () => {
155
171
  const {container} = render(
156
172
  <Section padding={6}>
157
173
  <Section data-testid="inner">Inner</Section>
158
174
  </Section>,
159
175
  );
160
- // Outer section's inner div should set --astryx-section-padding
161
- const outerInner = container.firstElementChild!.firstElementChild!;
162
- expect(outerInner.className).toBeDefined();
176
+ // The outer section's inner div announces its padding on the PRIVATE
177
+ // propagation var, not the public `--astryx-section-padding` theme token —
178
+ // the split is what lets an overlay drop an inherited value at its
179
+ // boundary while keeping the theme's (see overlayPaddingReset).
180
+ const outerInner = container.firstElementChild!
181
+ .firstElementChild! as HTMLElement;
182
+ expect(
183
+ getComputedStyle(outerInner).getPropertyValue(
184
+ '--_section-padding-propagated',
185
+ ),
186
+ // jsdom does not resolve the token reference to its 24px value.
187
+ ).toBe('var(--spacing-6)');
188
+ expect(
189
+ getComputedStyle(outerInner).getPropertyValue('--astryx-section-padding'),
190
+ ).toBe('');
163
191
  // Inner section should render without error
164
192
  expect(screen.getByTestId('inner')).toBeInTheDocument();
165
193
  expect(screen.getByText('Inner')).toBeInTheDocument();
@@ -176,4 +204,173 @@ describe('Section', () => {
176
204
  expect(screen.getByTestId('inner')).toBeInTheDocument();
177
205
  expect(screen.getByText('Inner')).toBeInTheDocument();
178
206
  });
207
+
208
+ it('applies a class when paddingBlockStart is set on its own', () => {
209
+ const {container, rerender} = render(<Section>Content</Section>);
210
+ const baseline = (
211
+ container.firstElementChild!.firstElementChild as HTMLElement
212
+ ).className;
213
+ rerender(<Section paddingBlockStart={2}>Content</Section>);
214
+ const withEdge = (
215
+ container.firstElementChild!.firstElementChild as HTMLElement
216
+ ).className;
217
+ expect(withEdge).not.toBe(baseline);
218
+ });
219
+
220
+ it('treats paddingBlock as the two edge props set to the same step', () => {
221
+ const {container, rerender} = render(
222
+ <Section paddingBlock={2}>Content</Section>,
223
+ );
224
+ const axis = classSet(
225
+ container.firstElementChild!.firstElementChild as HTMLElement,
226
+ );
227
+ rerender(
228
+ <Section paddingBlockStart={2} paddingBlockEnd={2}>
229
+ Content
230
+ </Section>,
231
+ );
232
+ expect(axis).toEqual(
233
+ classSet(container.firstElementChild!.firstElementChild as HTMLElement),
234
+ );
235
+ });
236
+
237
+ it('gives paddingBlockEnd precedence over paddingBlock', () => {
238
+ const {container, rerender} = render(
239
+ <Section paddingBlock={2} paddingBlockEnd={8}>
240
+ Content
241
+ </Section>,
242
+ );
243
+ const overridden = classSet(
244
+ container.firstElementChild!.firstElementChild as HTMLElement,
245
+ );
246
+ rerender(
247
+ <Section paddingBlockStart={2} paddingBlockEnd={8}>
248
+ Content
249
+ </Section>,
250
+ );
251
+ expect(overridden).toEqual(
252
+ classSet(container.firstElementChild!.firstElementChild as HTMLElement),
253
+ );
254
+ });
255
+
256
+ it('keeps inline padding when only a block edge is overridden', () => {
257
+ // padding={6} sets all four edges; paddingBlockStart={0} may only move the
258
+ // top edge, so the inline classes must survive unchanged.
259
+ const {container, rerender} = render(
260
+ <Section padding={6}>Content</Section>,
261
+ );
262
+ const uniform = classSet(
263
+ container.firstElementChild!.firstElementChild as HTMLElement,
264
+ );
265
+ rerender(
266
+ <Section padding={6} paddingBlockStart={0}>
267
+ Content
268
+ </Section>,
269
+ );
270
+ const overridden = classSet(
271
+ container.firstElementChild!.firstElementChild as HTMLElement,
272
+ );
273
+ // Everything the uniform render dropped is block-start related.
274
+ const removed = [...uniform].filter(c => !overridden.has(c));
275
+ const added = [...overridden].filter(c => !uniform.has(c));
276
+ expect(removed.length).toBeGreaterThan(0);
277
+ expect(added.length).toBeGreaterThan(0);
278
+ // The inline-axis classes are shared by both renders.
279
+ expect(uniform.size - removed.length).toBeGreaterThan(0);
280
+ });
281
+
282
+ it('applies a class when paddingInlineStart is set on its own', () => {
283
+ const {container, rerender} = render(<Section>Content</Section>);
284
+ const baseline = (
285
+ container.firstElementChild!.firstElementChild as HTMLElement
286
+ ).className;
287
+ rerender(<Section paddingInlineStart={2}>Content</Section>);
288
+ expect(
289
+ (container.firstElementChild!.firstElementChild as HTMLElement).className,
290
+ ).not.toBe(baseline);
291
+ });
292
+
293
+ it('treats paddingInline as the two inline edge props set to the same step', () => {
294
+ const {container, rerender} = render(
295
+ <Section paddingInline={2}>Content</Section>,
296
+ );
297
+ const axis = classSet(
298
+ container.firstElementChild!.firstElementChild as HTMLElement,
299
+ );
300
+ rerender(
301
+ <Section paddingInlineStart={2} paddingInlineEnd={2}>
302
+ Content
303
+ </Section>,
304
+ );
305
+ expect(axis).toEqual(
306
+ classSet(container.firstElementChild!.firstElementChild as HTMLElement),
307
+ );
308
+ });
309
+
310
+ it('gives paddingInlineEnd precedence over paddingInline', () => {
311
+ const {container, rerender} = render(
312
+ <Section paddingInline={2} paddingInlineEnd={8}>
313
+ Content
314
+ </Section>,
315
+ );
316
+ const overridden = classSet(
317
+ container.firstElementChild!.firstElementChild as HTMLElement,
318
+ );
319
+ rerender(
320
+ <Section paddingInlineStart={2} paddingInlineEnd={8}>
321
+ Content
322
+ </Section>,
323
+ );
324
+ expect(overridden).toEqual(
325
+ classSet(container.firstElementChild!.firstElementChild as HTMLElement),
326
+ );
327
+ });
328
+
329
+ it('keeps block padding when only an inline edge is overridden', () => {
330
+ const {container, rerender} = render(
331
+ <Section padding={6}>Content</Section>,
332
+ );
333
+ const uniform = classSet(
334
+ container.firstElementChild!.firstElementChild as HTMLElement,
335
+ );
336
+ rerender(
337
+ <Section padding={6} paddingInlineStart={0}>
338
+ Content
339
+ </Section>,
340
+ );
341
+ const overridden = classSet(
342
+ container.firstElementChild!.firstElementChild as HTMLElement,
343
+ );
344
+ const removed = [...uniform].filter(c => !overridden.has(c));
345
+ const added = [...overridden].filter(c => !uniform.has(c));
346
+ expect(removed.length).toBeGreaterThan(0);
347
+ expect(added.length).toBeGreaterThan(0);
348
+ // The block-axis classes survive the inline-edge override.
349
+ expect(uniform.size - removed.length).toBeGreaterThan(0);
350
+ });
351
+
352
+ it('moves the inline container vars with a per-edge override', () => {
353
+ // Section drives --container-padding-inline-start/end for bleed children.
354
+ // A per-edge override must move only the matching var, so a nested Section
355
+ // or a bleeding Divider compensates against the real padding.
356
+ const {container, rerender} = render(
357
+ <Section padding={6} paddingInlineStart={2}>
358
+ Content
359
+ </Section>,
360
+ );
361
+ const startOverride = classSet(
362
+ container.firstElementChild!.firstElementChild as HTMLElement,
363
+ );
364
+ rerender(
365
+ <Section padding={6} paddingInlineEnd={2}>
366
+ Content
367
+ </Section>,
368
+ );
369
+ const endOverride = classSet(
370
+ container.firstElementChild!.firstElementChild as HTMLElement,
371
+ );
372
+ // Overriding opposite edges by the same step must not produce identical
373
+ // output — each edge carries its own padding class and its own var class.
374
+ expect(startOverride).not.toEqual(endOverride);
375
+ });
179
376
  });
@@ -21,8 +21,15 @@ import {container} from '../Layout/container.stylex';
21
21
  import type {SpacingToken} from '../Layout/container.stylex';
22
22
  import {
23
23
  paddingStyles,
24
+ paddingInlineStyles,
25
+ paddingInlineStartStyles,
26
+ paddingInlineEndStyles,
24
27
  paddingBlockStyles,
28
+ paddingBlockStartStyles,
29
+ paddingBlockEndStyles,
25
30
  containerPaddingInlineVarStyles,
31
+ containerPaddingInlineStartVarStyles,
32
+ containerPaddingInlineEndVarStyles,
26
33
  containerPaddingBlockStartVarStyles,
27
34
  containerPaddingBlockEndVarStyles,
28
35
  sectionPaddingPropagationStyles,
@@ -175,6 +182,27 @@ export interface SectionProps extends BaseProps<HTMLElement> {
175
182
  * @default 4 (16px)
176
183
  */
177
184
  padding?: SpacingStep;
185
+ /**
186
+ * Inline (horizontal) padding override. When set, overrides only the inline
187
+ * axis padding while preserving block padding from `padding` or the
188
+ * container theme default.
189
+ * Accepts numeric spacing steps: 0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10.
190
+ */
191
+ paddingInline?: SpacingStep;
192
+ /**
193
+ * Inline-start padding override. Logical: the left edge in LTR, the right
194
+ * edge in RTL. Takes precedence over `paddingInline` and `padding` on that
195
+ * edge only; every other edge is left alone.
196
+ * Accepts numeric spacing steps: 0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10.
197
+ */
198
+ paddingInlineStart?: SpacingStep;
199
+ /**
200
+ * Inline-end padding override. Logical: the right edge in LTR, the left
201
+ * edge in RTL. Takes precedence over `paddingInline` and `padding` on that
202
+ * edge only; every other edge is left alone.
203
+ * Accepts numeric spacing steps: 0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10.
204
+ */
205
+ paddingInlineEnd?: SpacingStep;
178
206
  /**
179
207
  * Block (vertical) padding override. When set, overrides only the block
180
208
  * axis padding while preserving inline padding from `padding` or the
@@ -182,6 +210,20 @@ export interface SectionProps extends BaseProps<HTMLElement> {
182
210
  * Accepts numeric spacing steps: 0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10.
183
211
  */
184
212
  paddingBlock?: SpacingStep;
213
+ /**
214
+ * Block-start (top) padding override. Takes precedence over `paddingBlock`
215
+ * and `padding` on that edge only; the block-end edge and both inline edges
216
+ * are left alone.
217
+ * Accepts numeric spacing steps: 0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10.
218
+ */
219
+ paddingBlockStart?: SpacingStep;
220
+ /**
221
+ * Block-end (bottom) padding override. Takes precedence over `paddingBlock`
222
+ * and `padding` on that edge only; the block-start edge and both inline
223
+ * edges are left alone.
224
+ * Accepts numeric spacing steps: 0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10.
225
+ */
226
+ paddingBlockEnd?: SpacingStep;
185
227
  }
186
228
 
187
229
  /**
@@ -211,7 +253,12 @@ export function Section({
211
253
  children,
212
254
  dividers,
213
255
  padding,
256
+ paddingInline,
257
+ paddingInlineStart,
258
+ paddingInlineEnd,
214
259
  paddingBlock,
260
+ paddingBlockStart,
261
+ paddingBlockEnd,
215
262
  xstyle,
216
263
  className,
217
264
  style,
@@ -275,11 +322,33 @@ export function Section({
275
322
  containerPaddingBlockEndVarStyles[effectivePadding],
276
323
  !useThemeDefault &&
277
324
  sectionPaddingPropagationStyles[effectivePadding],
325
+ paddingInline != null && paddingInlineStyles[paddingInline],
326
+ paddingInline != null &&
327
+ containerPaddingInlineVarStyles[paddingInline],
278
328
  paddingBlock != null && paddingBlockStyles[paddingBlock],
279
329
  paddingBlock != null &&
280
330
  containerPaddingBlockStartVarStyles[paddingBlock],
281
331
  paddingBlock != null &&
282
332
  containerPaddingBlockEndVarStyles[paddingBlock],
333
+ // Per-edge overrides come last so they win over `paddingBlock`
334
+ // and `padding` on their own edge. The matching container var is
335
+ // updated alongside so bleed children (Table, Divider, nested
336
+ // Section) compensate against the padding actually applied.
337
+ paddingBlockStart != null &&
338
+ paddingBlockStartStyles[paddingBlockStart],
339
+ paddingBlockStart != null &&
340
+ containerPaddingBlockStartVarStyles[paddingBlockStart],
341
+ paddingBlockEnd != null && paddingBlockEndStyles[paddingBlockEnd],
342
+ paddingBlockEnd != null &&
343
+ containerPaddingBlockEndVarStyles[paddingBlockEnd],
344
+ paddingInlineStart != null &&
345
+ paddingInlineStartStyles[paddingInlineStart],
346
+ paddingInlineStart != null &&
347
+ containerPaddingInlineStartVarStyles[paddingInlineStart],
348
+ paddingInlineEnd != null &&
349
+ paddingInlineEndStyles[paddingInlineEnd],
350
+ paddingInlineEnd != null &&
351
+ containerPaddingInlineEndVarStyles[paddingInlineEnd],
283
352
  variantStyles[variant],
284
353
  dividers?.includes('top') && dividerStyles.top,
285
354
  dividers?.includes('bottom') && dividerStyles.bottom,
@@ -27,10 +27,18 @@ export const docs = {
27
27
  states: ['disabled'],
28
28
  },
29
29
  {className: 'astryx-selector-option'},
30
+ {
31
+ className: 'astryx-selector-option-row',
32
+ visualProps: ['size'],
33
+ states: ['selected', 'disabled'],
34
+ },
30
35
  {className: 'astryx-selector-search'},
31
36
  {className: 'astryx-selector-section-heading'},
32
37
  {className: 'astryx-selector-empty-state'},
33
- {className: 'astryx-selector-clear-icon', deprecatedFor: 'input-clear-icon'},
38
+ {
39
+ className: 'astryx-selector-clear-icon',
40
+ deprecatedFor: 'input-clear-icon',
41
+ },
34
42
  {className: 'astryx-selector-indicator-icon', states: ['state']},
35
43
  {className: 'astryx-selector-check'},
36
44
  {className: 'astryx-selector-popup'},
@@ -48,7 +56,7 @@ export const docs = {
48
56
  name: 'options',
49
57
  type: 'SelectorOption[]',
50
58
  description:
51
- 'Array of items: strings, objects with value/label/icon/disabled, dividers ({type: "divider"}), or sections ({type: "section", title, items}).',
59
+ 'Array of items: strings, objects with value/label/description/icon/disabled, dividers ({type: "divider"}), or sections ({type: "section", title, items}).',
52
60
  required: true,
53
61
  },
54
62
  {
@@ -159,6 +167,12 @@ export const docs = {
159
167
  description:
160
168
  'Custom render function for each selectable option in the dropdown. Use this instead of JSX children; dividers and sections are rendered by the selector.',
161
169
  },
170
+ {
171
+ name: 'renderValue',
172
+ type: '(option: SelectorOptionData) => ReactNode',
173
+ description:
174
+ 'Custom render function for the selected option inside the closed trigger. The trigger is sized by padding, so it is the size token for a one-line value (28/32/36) and exactly one text line taller for a two-line one (48/52/56) — always on the 4px rhythm, always aligned with the buttons and inputs beside it. Inside an InputGroup the group owns the row height: a SelectorOption folds onto one line and ellipsizes, and any taller node is cut off at the row.',
175
+ },
162
176
  {
163
177
  name: 'indicatorPosition',
164
178
  type: "'start' | 'end'",