@astryxdesign/core 0.6.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/DateRangeInput/DateRangeInput.d.ts +3 -0
  3. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  4. package/dist/DateRangeInput/DateRangeInput.js +16 -9
  5. package/dist/Dialog/DialogHeader.d.ts +1 -1
  6. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  7. package/dist/Dialog/DialogHeader.js +10 -7
  8. package/dist/FileInput/FileInput.d.ts.map +1 -1
  9. package/dist/FileInput/FileInput.js +9 -3
  10. package/dist/Markdown/Markdown.d.ts +10 -2
  11. package/dist/Markdown/Markdown.d.ts.map +1 -1
  12. package/dist/Markdown/Markdown.js +58 -14
  13. package/dist/Markdown/index.d.ts +1 -1
  14. package/dist/Markdown/index.d.ts.map +1 -1
  15. package/dist/Markdown/parser.d.ts +126 -12
  16. package/dist/Markdown/parser.d.ts.map +1 -1
  17. package/dist/Markdown/parser.js +369 -34
  18. package/dist/Markdown/utils.d.ts +1 -1
  19. package/dist/Markdown/utils.d.ts.map +1 -1
  20. package/dist/Slider/Slider.d.ts.map +1 -1
  21. package/dist/Slider/Slider.js +5 -2
  22. package/dist/Spinner/Spinner.d.ts +1 -1
  23. package/dist/Spinner/Spinner.d.ts.map +1 -1
  24. package/dist/Spinner/Spinner.js +23 -15
  25. package/dist/astryx.css +2 -1
  26. package/locales/en.json +16 -0
  27. package/locales/pseudo.json +12 -0
  28. package/package.json +6 -4
  29. package/scripts/agent-doc-state.mjs +1 -1
  30. package/src/DateRangeInput/DateRangeInput.doc.mjs +35 -7
  31. package/src/DateRangeInput/DateRangeInput.spec.md +203 -0
  32. package/src/DateRangeInput/DateRangeInput.test.tsx +100 -4
  33. package/src/DateRangeInput/DateRangeInput.tsx +29 -20
  34. package/src/Dialog/Dialog.doc.mjs +3 -0
  35. package/src/Dialog/Dialog.spec.md +1 -1
  36. package/src/Dialog/DialogHeader.doc.mjs +38 -0
  37. package/src/Dialog/DialogHeader.test.tsx +49 -0
  38. package/src/Dialog/DialogHeader.tsx +23 -4
  39. package/src/Dialog/modules/DialogHeader.spec.md +152 -0
  40. package/src/FileInput/FileInput.doc.mjs +2 -0
  41. package/src/FileInput/FileInput.spec.md +199 -0
  42. package/src/FileInput/FileInput.test.tsx +14 -0
  43. package/src/FileInput/FileInput.tsx +13 -3
  44. package/src/Markdown/Markdown.doc.mjs +167 -42
  45. package/src/Markdown/Markdown.public.test.ts +157 -0
  46. package/src/Markdown/Markdown.spec.md +149 -70
  47. package/src/Markdown/Markdown.test.tsx +107 -3
  48. package/src/Markdown/Markdown.tsx +116 -35
  49. package/src/Markdown/incremental.test.ts +175 -7
  50. package/src/Markdown/index.ts +6 -0
  51. package/src/Markdown/parser.perf.test.ts +3 -1
  52. package/src/Markdown/parser.test.ts +122 -0
  53. package/src/Markdown/parser.ts +609 -81
  54. package/src/Markdown/utils.ts +6 -0
  55. package/src/Slider/Slider.doc.mjs +16 -0
  56. package/src/Slider/Slider.spec.md +61 -47
  57. package/src/Slider/Slider.test.tsx +18 -0
  58. package/src/Slider/Slider.tsx +12 -6
  59. package/src/Spinner/Spinner.doc.mjs +6 -3
  60. package/src/Spinner/Spinner.test.tsx +37 -0
  61. package/src/Spinner/Spinner.tsx +31 -14
  62. package/src/theme/derivedVarRegistry.test.ts +6 -4
@@ -54,6 +54,7 @@ import {
54
54
  type DayOfWeek,
55
55
  type DayOfWeekName,
56
56
  } from '../Calendar';
57
+ import {useCalendarConstraints} from '../Calendar/hooks';
57
58
  import {usePopover} from '../Popover';
58
59
  import {useTooltip} from '../Tooltip';
59
60
  import {mergeProps} from '../utils';
@@ -376,6 +377,9 @@ export interface DateRangeInputProps extends Omit<
376
377
 
377
378
  /**
378
379
  * Preset date ranges shown as quick-select options beside the calendar.
380
+ * A preset is disabled when either endpoint violates `min`, `max`, or
381
+ * `dateConstraints`, or when its span violates `minRangeSpan` or
382
+ * `maxRangeSpan`.
379
383
  */
380
384
  presets?: ReadonlyArray<DateRangePreset>;
381
385
 
@@ -542,6 +546,11 @@ export function DateRangeInput({
542
546
  dialogLabel: t('@astryx.dateRangeInput.dialogLabel'),
543
547
  closeButtonLabel: t('@astryx.dateInput.closeCalendar'),
544
548
  });
549
+ const {isDateDisabled} = useCalendarConstraints({
550
+ min,
551
+ max,
552
+ dateConstraints,
553
+ });
545
554
 
546
555
  const fireChange = useCallback(
547
556
  (newValue: DateRange | null) => {
@@ -577,14 +586,6 @@ export function DateRangeInput({
577
586
  [fireChange, popover],
578
587
  );
579
588
 
580
- const handlePresetClick = useCallback(
581
- (preset: DateRangePreset) => {
582
- fireChange(preset.getRange());
583
- popover.hide();
584
- },
585
- [fireChange, popover],
586
- );
587
-
588
589
  const handleClear = useCallback(
589
590
  (e: React.MouseEvent) => {
590
591
  e.stopPropagation();
@@ -713,15 +714,17 @@ export function DateRangeInput({
713
714
  <div
714
715
  role="group"
715
716
  aria-label={t('@astryx.dateRangeInput.presetDateRanges')}
716
- {...stylex.props(styles.presetSidebar)}>
717
+ {...mergeProps(
718
+ themeProps('date-range-input-presets'),
719
+ stylex.props(styles.presetSidebar),
720
+ )}>
717
721
  {presets.map(preset => {
718
722
  const presetRange = preset.getRange();
719
723
  const isActive = isRangeEqual(value, presetRange);
720
- const isPresetDisabled = !isRangeWithinSpan(
721
- presetRange,
722
- maxRangeSpan,
723
- minRangeSpan,
724
- );
724
+ const isPresetDisabled =
725
+ !isRangeWithinSpan(presetRange, maxRangeSpan, minRangeSpan) ||
726
+ isDateDisabled(plainDateFromISO(presetRange.start)) ||
727
+ isDateDisabled(plainDateFromISO(presetRange.end));
725
728
  return (
726
729
  <button
727
730
  key={preset.label}
@@ -733,12 +736,18 @@ export function DateRangeInput({
733
736
  // concept that contradicted the Tab interaction) (forms-5).
734
737
  aria-current={isActive ? 'true' : undefined}
735
738
  disabled={isPresetDisabled}
736
- onClick={() => handlePresetClick(preset)}
737
- {...stylex.props(
738
- focusOutlineStyles.focusVisible,
739
- styles.presetButton,
740
- isActive && styles.presetButtonActive,
741
- isPresetDisabled && styles.presetButtonDisabled,
739
+ onClick={() => handleRangeSelect(presetRange)}
740
+ {...mergeProps(
741
+ themeProps('date-range-input-preset', {
742
+ selected: isActive ? 'selected' : null,
743
+ disabled: isPresetDisabled ? 'disabled' : null,
744
+ }),
745
+ stylex.props(
746
+ focusOutlineStyles.focusVisible,
747
+ styles.presetButton,
748
+ isActive && styles.presetButtonActive,
749
+ isPresetDisabled && styles.presetButtonDisabled,
750
+ ),
742
751
  )}>
743
752
  {preset.label}
744
753
  </button>
@@ -30,6 +30,9 @@ export const docs = {
30
30
  container: true,
31
31
  targets: [
32
32
  {className: 'astryx-dialog', visualProps: ['variant']},
33
+ {className: 'astryx-dialog-header'},
34
+ {className: 'astryx-dialog-header-title-block'},
35
+ {className: 'astryx-dialog-header-close-icon'},
33
36
  ],
34
37
  vars: [
35
38
  {name: '--_dialog-radius', description: 'Border radius of the dialog', default: 'var(--radius-container)', private: true},
@@ -17,7 +17,7 @@ verified_by:
17
17
  packages/core/src/Dialog/__tests__/Dialog.a11y.test.tsx,
18
18
  packages/core/src/Dialog/__tests__/Dialog.a11y.chromium.spec.ts,
19
19
  ]
20
- modules: []
20
+ modules: [module:Dialog/DialogHeader]
21
21
  families: [family:overlay-dismissal]
22
22
  design_specs: []
23
23
  architecture:
@@ -8,6 +8,14 @@ export const docs = {
8
8
  displayName: 'Dialog Header',
9
9
  isHiddenFromOverview: true,
10
10
  description: 'Header for dialogs with a title, optional subtitle, close button, and start/end content slots.',
11
+ usage: {
12
+ description: 'Use DialogHeader to give a dialog a labelled title area and optional close control.',
13
+ anatomy: [
14
+ {name: 'Header row', required: true, description: 'Arranges the title block, optional start/end content, and close control.'},
15
+ {name: 'Title block', required: true, description: 'Groups the title and optional subtitle.'},
16
+ {name: 'Close icon', required: false, description: 'Visual close glyph inside the close button.'},
17
+ ],
18
+ },
11
19
  props: [
12
20
  {
13
21
  name: 'title',
@@ -72,6 +80,13 @@ export const docs = {
72
80
  hasDivider: true,
73
81
  },
74
82
  },
83
+ theming: {
84
+ targets: [
85
+ {className: 'astryx-dialog-header'},
86
+ {className: 'astryx-dialog-header-title-block'},
87
+ {className: 'astryx-dialog-header-close-icon'},
88
+ ],
89
+ },
75
90
  examples: [
76
91
  {
77
92
  label: 'Basic',
@@ -117,6 +132,14 @@ export const docsZh = {
117
132
  isHiddenFromOverview: true,
118
133
  displayName: 'Dialog Header',
119
134
  description: '对话框头部,包含标题、可选副标题、关闭按钮以及首尾内容插槽。',
135
+ usage: {
136
+ description: '使用 DialogHeader 为对话框提供带标签的标题区和可选的关闭控件。',
137
+ anatomy: [
138
+ {name: 'Header row', required: true, description: '排列标题区、可选的首尾内容和关闭控件。'},
139
+ {name: 'Title block', required: true, description: '组合标题和可选副标题。'},
140
+ {name: 'Close icon', required: false, description: '关闭按钮内的关闭图标。'},
141
+ ],
142
+ },
120
143
  props: [
121
144
  {
122
145
  name: 'title',
@@ -150,6 +173,13 @@ export const docsZh = {
150
173
  default: 'true',
151
174
  },
152
175
  ],
176
+ theming: {
177
+ targets: [
178
+ {className: 'astryx-dialog-header'},
179
+ {className: 'astryx-dialog-header-title-block'},
180
+ {className: 'astryx-dialog-header-close-icon'},
181
+ ],
182
+ },
153
183
  };
154
184
 
155
185
  export const docsDense = {
@@ -157,6 +187,14 @@ export const docsDense = {
157
187
  isHiddenFromOverview: true,
158
188
  displayName: 'Dialog Header',
159
189
  description: 'dialog header w/ title, optional subtitle, close button, start/end content slots',
190
+ usage: {
191
+ description: 'labelled dialog title area + optional close control',
192
+ anatomy: [
193
+ {name: 'Header row', required: true, description: 'arranges title block, optional start/end content, close control'},
194
+ {name: 'Title block', required: true, description: 'groups title + optional subtitle'},
195
+ {name: 'Close icon', required: false, description: 'close glyph inside close button'},
196
+ ],
197
+ },
160
198
  propDescriptions: {
161
199
  title: 'dialog title (focused on open; labels dialog via aria-labelledby)',
162
200
  subtitle: 'subtitle below title',
@@ -14,6 +14,13 @@ import {render, screen} from '@testing-library/react';
14
14
  import userEvent from '@testing-library/user-event';
15
15
  import {DialogHeader} from './DialogHeader';
16
16
  import {LayoutDividerContext} from '../Layout/LayoutDividerContext';
17
+ import {defineTheme} from '../theme/defineTheme';
18
+ import {generateThemeCSS} from '../theme/generateThemeRules';
19
+
20
+ function generateThemeTestCSS(theme: Parameters<typeof generateThemeCSS>[0]) {
21
+ const {prose, component} = generateThemeCSS(theme);
22
+ return [prose, component].filter(Boolean).join('\n\n');
23
+ }
17
24
 
18
25
  describe('DialogHeader', () => {
19
26
  it('renders the title', () => {
@@ -56,6 +63,48 @@ describe('DialogHeader', () => {
56
63
  expect(screen.getByRole('button', {name: /close/i})).toBeInTheDocument();
57
64
  });
58
65
 
66
+ it('exposes theme targets for the header row, title block, and close icon', () => {
67
+ const {container} = render(
68
+ <DialogHeader
69
+ title="Title"
70
+ subtitle="Subtitle"
71
+ onOpenChange={() => {}}
72
+ />,
73
+ );
74
+
75
+ expect(container.querySelector('.astryx-dialog-header')).not.toBeNull();
76
+ expect(screen.getByRole('heading', {level: 2}).parentElement).toHaveClass(
77
+ 'astryx-dialog-header-title-block',
78
+ );
79
+
80
+ const closeIcon = screen
81
+ .getByRole('button', {name: /close/i})
82
+ .querySelector('.astryx-dialog-header-close-icon');
83
+ expect(closeIcon).toHaveClass('astryx-icon');
84
+ });
85
+
86
+ it('lets themes set the two internal gaps and close-icon size', () => {
87
+ const theme = defineTheme({
88
+ name: 'dialog-header-targets-test',
89
+ components: {
90
+ 'dialog-header': {base: {gap: '8px'}},
91
+ 'dialog-header-title-block': {base: {gap: '4px'}},
92
+ 'dialog-header-close-icon': {
93
+ base: {width: '16px', height: '16px', fontSize: '16px'},
94
+ },
95
+ },
96
+ });
97
+ const css = generateThemeTestCSS(theme);
98
+
99
+ expect(css).toContain('.astryx-dialog-header {');
100
+ expect(css).toContain('gap: 8px');
101
+ expect(css).toContain('.astryx-dialog-header-title-block {');
102
+ expect(css).toContain('gap: 4px');
103
+ expect(css).toContain('.astryx-dialog-header-close-icon {');
104
+ expect(css).toContain('width: 16px');
105
+ expect(css).toContain('height: 16px');
106
+ });
107
+
59
108
  it('does not render close button when onOpenChange is not provided', () => {
60
109
  render(<DialogHeader title="Title" />);
61
110
  expect(
@@ -4,7 +4,7 @@
4
4
 
5
5
  /**
6
6
  * @file DialogHeader.tsx
7
- * @input Uses React, useEffect, useRef, LayoutHeader, Button, Icon, Heading, Text, DialogContext
7
+ * @input Uses React, StyleX, LayoutHeader, Button, Icon, Heading, Text, DialogContext, mergeProps, themeProps
8
8
  * @output Exports DialogHeader component and DialogHeaderProps
9
9
  * @position Dialog header component; used with Dialog and Layout
10
10
  *
@@ -25,6 +25,8 @@ import {Icon} from '../Icon';
25
25
  import {Heading} from '../Heading/Heading';
26
26
  import {Text} from '../Text/Text';
27
27
  import type {BaseProps} from '../BaseProps';
28
+ import {mergeProps} from '../utils';
29
+ import {themeProps} from '../utils/themeProps';
28
30
  import {useDialogContext} from './DialogContext';
29
31
  import {useTranslator} from '../i18n';
30
32
 
@@ -41,6 +43,9 @@ const styles = stylex.create({
41
43
  marginInlineEnd: `calc(-1 * ${spacingVars['--spacing-2']})`,
42
44
  },
43
45
  titleWrapper: {
46
+ display: 'flex',
47
+ flexDirection: 'column',
48
+ gap: spacingVars['--spacing-0'],
44
49
  flex: 1,
45
50
  minWidth: 0,
46
51
  // Visual centering: align title center with close button center
@@ -161,11 +166,19 @@ export function DialogHeader({
161
166
  className={className}
162
167
  style={style}
163
168
  {...rest}>
164
- <div {...stylex.props(styles.container)}>
169
+ <div
170
+ {...mergeProps(
171
+ themeProps('dialog-header'),
172
+ stylex.props(styles.container),
173
+ )}>
165
174
  {startContent && (
166
175
  <div {...stylex.props(styles.actions)}>{startContent}</div>
167
176
  )}
168
- <div {...stylex.props(styles.titleWrapper)}>
177
+ <div
178
+ {...mergeProps(
179
+ themeProps('dialog-header-title-block'),
180
+ stylex.props(styles.titleWrapper),
181
+ )}>
169
182
  <Heading
170
183
  ref={titleRef}
171
184
  id={titleId}
@@ -192,7 +205,13 @@ export function DialogHeader({
192
205
  variant="ghost"
193
206
  label={t('@astryx.dialog.close')}
194
207
  tooltip={t('@astryx.dialog.close')}
195
- icon={<Icon icon="close" color="inherit" />}
208
+ icon={
209
+ <Icon
210
+ icon="close"
211
+ color="inherit"
212
+ {...themeProps('dialog-header-close-icon')}
213
+ />
214
+ }
196
215
  onClick={() => {
197
216
  onOpenChange?.(false);
198
217
  }}
@@ -0,0 +1,152 @@
1
+ ---
2
+ schema_version: 3
3
+ template_version: 1
4
+ kind: module
5
+ id: module:Dialog/DialogHeader
6
+ authority: current
7
+ archive_reason: null
8
+ superseded_by: null
9
+ approved_by: cixzhang
10
+ approved_at: 2026-09-14
11
+ owners: [cixzhang, imdreamrunner]
12
+ review_triggers: [theming, layout]
13
+ verified_by:
14
+ [
15
+ packages/core/src/Dialog/DialogHeader.test.tsx,
16
+ packages/core/src/theme/themingTargets.test.ts,
17
+ scripts/check-knowledge.mjs,
18
+ ]
19
+ parent_component: component:Dialog
20
+ references: [architecture:component-theming-surface]
21
+ ---
22
+
23
+ # DialogHeader module contract
24
+
25
+ ## Intent
26
+
27
+ `DialogHeader` presents the title region of a Dialog and its optional close
28
+ control. This record owns the stable header-row, title-block, and close-icon
29
+ anatomy and their public theming targets.
30
+
31
+ ## Compatibility and migration
32
+
33
+ - Released default preserved: `yes`
34
+ - Compatibility class: additive theme targets only; default layout, paint,
35
+ interaction, accessibility, and public props remain unchanged
36
+ - Migration decision: none
37
+
38
+ Consumer migration instructions belong in consumer docs and release notes.
39
+
40
+ ## Ownership boundary
41
+
42
+ **Owns**
43
+
44
+ - The header row that arranges title content and trailing controls.
45
+ - The title block that groups the title and optional subtitle.
46
+ - The close icon rendered for the optional close action.
47
+ - The `dialog-header`, `dialog-header-title-block`, and
48
+ `dialog-header-close-icon` targets.
49
+
50
+ **Does not own / non-goals**
51
+
52
+ - Dialog modality, dismissal policy, or focus lifecycle — owned by
53
+ `component:Dialog` and its linked system records.
54
+ - Generic Button or Icon presentation outside this module — owned by those
55
+ components.
56
+ - New public props or default visual changes.
57
+
58
+ ## Public API and concepts
59
+
60
+ No component prop changes. This contract adds three public theming surfaces for
61
+ existing anatomy.
62
+
63
+ | Concept | Closed values or states | Meaning | Default | Owner | Stability |
64
+ | --- | --- | --- | --- | --- | --- |
65
+ | Header row target | present | Styles the row that arranges title content and controls | Existing row visuals | `module:Dialog/DialogHeader` | stable |
66
+ | Title block target | present | Styles the title/subtitle grouping element | Existing title stack visuals | `module:Dialog/DialogHeader` | stable |
67
+ | Close icon target | present when close action renders | Styles the close glyph itself | Existing medium Icon visuals | `module:Dialog/DialogHeader` | stable |
68
+
69
+ ## Behavioral contract
70
+
71
+ | ID | Invariant | Basis | Review state |
72
+ | --- | --- | --- | --- |
73
+ | FR1 | The header row MUST carry `dialog-header` on the element that applies its row layout and gap. | Current implementation and owner decision | settled |
74
+ | FR2 | The title block MUST carry `dialog-header-title-block` on the element that applies its title/subtitle layout and gap. | Current implementation and owner decision | settled |
75
+ | FR3 | The rendered close Icon MUST carry `dialog-header-close-icon` on the glyph element that applies icon presentation. | Current implementation and owner decision | settled |
76
+ | FR4 | Omitting `onOpenChange` MUST continue to omit the close action and its optional close-icon anatomy. | Released behavior | settled |
77
+
78
+ ### Transformation and precedence order
79
+
80
+ - The module applies each target to its owning element before normal theme CSS
81
+ resolves through the shared theming pipeline.
82
+
83
+ ### Performance and resources
84
+
85
+ - The additive class names and metadata introduce no listener, observer, timer,
86
+ measurement, or asynchronous resource.
87
+
88
+ ## Accessibility contract
89
+
90
+ - Theme targets MUST NOT change the title's role, focus behavior, dialog naming,
91
+ or the close button's accessible name and operation.
92
+
93
+ ## Design relationships
94
+
95
+ | Anatomy or state | Design requirement | Representation authority | Module contract |
96
+ | --- | --- | --- | --- |
97
+ | Header row | Owns arrangement and spacing among title content and controls. | This module | FR1 |
98
+ | Title block | Owns title/subtitle grouping and spacing. | This module | FR2 |
99
+ | Close icon | Owns the close glyph's visual box inside the Button-owned action. | This module with Icon rendering | FR3, FR4 |
100
+
101
+ ### Theming anatomy
102
+
103
+ <!-- anatomy-theming:v1 -->
104
+
105
+ ```json
106
+ {
107
+ "Header row": {"target": "dialog-header"},
108
+ "Title block": {"target": "dialog-header-title-block"},
109
+ "Close icon": {"target": "dialog-header-close-icon"}
110
+ }
111
+ ```
112
+
113
+ ## Parent and system relationships
114
+
115
+ - `component:Dialog` owns modal behavior and the aggregate Dialog contract.
116
+ - `component:Layout` owns the composed LayoutHeader region outside the three
117
+ module-owned inner parts.
118
+ - `component:Button` owns the close action's control behavior and outer button
119
+ presentation.
120
+ - `component:Icon` renders the glyph; this module guarantees a distinct target
121
+ for the close icon's DialogHeader-specific visual contract.
122
+ - `architecture:component-theming-surface` owns target qualification, anatomy
123
+ mapping, and the requirement that each target sits on its painter.
124
+
125
+ ## Verification map
126
+
127
+ | Contract | Verification | Representative states | Mutation or failure expectation |
128
+ | --- | --- | --- | --- |
129
+ | FR1–FR3 | `DialogHeader.test.tsx`, target inventory, generated probe theme, and source inspection | title only, title/subtitle, close action | A target is missing, undocumented, or moved away from its owning painter. |
130
+ | FR4 | Existing close-button presence tests | with and without `onOpenChange` | The optional target renders without the optional close action. |
131
+ | Theming anatomy map | `scripts/check-knowledge.mjs` | all three module anatomy entries and targets | Anatomy, docs, runtime targets, and the module map drift. |
132
+
133
+ ## Decision log
134
+
135
+ ### DEC-1 — Header targets follow stable anatomy and visual ownership
136
+
137
+ **Reference:** `module:Dialog/DialogHeader/DEC-1`
138
+ **Decider:** cixzhang, 2026-09-14
139
+
140
+ Each public target represents documented anatomy and is applied to the element
141
+ that owns the corresponding visuals. The header row, title block, and close icon
142
+ meet that admission rule and are approved as additive targets.
143
+
144
+ ## Open questions
145
+
146
+ None.
147
+
148
+ ## Content boundary
149
+
150
+ This record does not duplicate consumer signatures/examples, parent Dialog
151
+ behavior, implementation steps, or shared theming rules. It links to their
152
+ canonical owners.
@@ -142,6 +142,7 @@ export const docs = {
142
142
  theming: {
143
143
  targets: [
144
144
  {className: 'astryx-file-input', visualProps: ['mode', 'status']},
145
+ {className: 'astryx-file-input-icon', visualProps: ['mode']},
145
146
  ],
146
147
  },
147
148
  usage: {
@@ -270,6 +271,7 @@ export const docsZh = {
270
271
  theming: {
271
272
  targets: [
272
273
  {className: 'astryx-file-input', visualProps: ['mode', 'status']},
274
+ {className: 'astryx-file-input-icon', visualProps: ['mode']},
273
275
  ],
274
276
  },
275
277
  usage: {