native-document 1.0.166 → 1.0.169

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 (139) hide show
  1. package/.vitepress/config.js +166 -0
  2. package/CHANGELOG.md +187 -0
  3. package/components.js +4 -1
  4. package/dist/native-document.components.min.js +593 -300
  5. package/dist/native-document.dev.js +99 -75
  6. package/dist/native-document.dev.js.map +1 -1
  7. package/dist/native-document.min.js +1 -1
  8. package/docs/advanced-components.md +213 -608
  9. package/docs/anchor.md +173 -312
  10. package/docs/cache.md +95 -803
  11. package/docs/cli.md +179 -0
  12. package/docs/components/accordion.md +172 -0
  13. package/docs/components/alert.md +99 -0
  14. package/docs/components/avatar.md +160 -0
  15. package/docs/components/badge.md +102 -0
  16. package/docs/components/breadcrumb.md +89 -0
  17. package/docs/components/button.md +183 -0
  18. package/docs/components/card.md +69 -0
  19. package/docs/components/context-menu.md +118 -0
  20. package/docs/components/data-table.md +345 -0
  21. package/docs/components/dropdown.md +214 -0
  22. package/docs/components/form/autocomplete-field.md +81 -0
  23. package/docs/components/form/checkbox-field.md +41 -0
  24. package/docs/components/form/checkbox-group-field.md +54 -0
  25. package/docs/components/form/color-field.md +64 -0
  26. package/docs/components/form/date-field.md +92 -0
  27. package/docs/components/form/field-collection.md +63 -0
  28. package/docs/components/form/file-field.md +203 -0
  29. package/docs/components/form/form-control.md +87 -0
  30. package/docs/components/form/image-field.md +90 -0
  31. package/docs/components/form/index.md +115 -0
  32. package/docs/components/form/number-field.md +65 -0
  33. package/docs/components/form/radio-field.md +51 -0
  34. package/docs/components/form/select-field.md +123 -0
  35. package/docs/components/form/slider.md +136 -0
  36. package/docs/components/form/string-field.md +134 -0
  37. package/docs/components/form/textarea-field.md +65 -0
  38. package/docs/components/form-fields.md +372 -0
  39. package/docs/components/getting-started.md +264 -0
  40. package/docs/components/icons.md +321 -0
  41. package/docs/components/index.md +337 -0
  42. package/docs/components/layout.md +279 -0
  43. package/docs/components/list.md +73 -0
  44. package/docs/components/menu.md +215 -0
  45. package/docs/components/modal.md +156 -0
  46. package/docs/components/pagination.md +95 -0
  47. package/docs/components/popover.md +131 -0
  48. package/docs/components/progress.md +111 -0
  49. package/docs/components/shortcut-manager.md +221 -0
  50. package/docs/components/simple-table.md +107 -0
  51. package/docs/components/skeleton.md +155 -0
  52. package/docs/components/spinner.md +100 -0
  53. package/docs/components/splitter.md +133 -0
  54. package/docs/components/stepper.md +163 -0
  55. package/docs/components/switch.md +113 -0
  56. package/docs/components/tabs.md +153 -0
  57. package/docs/components/toast.md +119 -0
  58. package/docs/components/tooltip.md +151 -0
  59. package/docs/components/traits.md +261 -0
  60. package/docs/conditional-rendering.md +170 -588
  61. package/docs/contributing.md +300 -25
  62. package/docs/core-concepts.md +205 -374
  63. package/docs/elements.md +251 -367
  64. package/docs/extending-native-document-element.md +192 -207
  65. package/docs/filters.md +153 -1122
  66. package/docs/getting-started.md +193 -267
  67. package/docs/i18n.md +241 -0
  68. package/docs/index.md +76 -0
  69. package/docs/lifecycle-events.md +143 -75
  70. package/docs/list-rendering.md +227 -852
  71. package/docs/memory-management.md +134 -47
  72. package/docs/native-document-element.md +337 -186
  73. package/docs/native-fetch.md +99 -630
  74. package/docs/observable-resource.md +364 -0
  75. package/docs/observables.md +592 -526
  76. package/docs/routing.md +244 -653
  77. package/docs/state-management.md +134 -241
  78. package/docs/svg-elements.md +231 -0
  79. package/docs/theming.md +409 -0
  80. package/docs/tutorials/.gitkeep +0 -0
  81. package/docs/validation.md +95 -97
  82. package/docs/vitepress-conventions.md +219 -0
  83. package/package.json +34 -13
  84. package/readme.md +269 -89
  85. package/src/components/card/Card.js +93 -39
  86. package/src/components/card/index.js +1 -1
  87. package/src/components/form/field/types/FileField.js +3 -3
  88. package/src/components/icon/Icon.js +107 -0
  89. package/src/components/icon/icon-getters.js +142 -0
  90. package/src/components/icon/icons.js +171 -0
  91. package/src/components/icon/index.js +17 -0
  92. package/src/components/icon/types/Icon.d.ts +191 -0
  93. package/src/components/index.d.ts +6 -1
  94. package/src/components/list/HasListItem.js +171 -0
  95. package/src/components/list/List.js +41 -107
  96. package/src/components/list/ListDivider.js +39 -0
  97. package/src/components/list/ListGroup.js +76 -59
  98. package/src/components/list/ListItem.js +117 -69
  99. package/src/components/list/index.js +3 -1
  100. package/src/components/list/types/List.d.ts +45 -32
  101. package/src/components/list/types/ListDivider.ts +16 -0
  102. package/src/components/list/types/ListGroup.d.ts +51 -29
  103. package/src/components/list/types/ListItem.d.ts +40 -30
  104. package/src/components/spacer/Spacer.js +1 -1
  105. package/src/core/data/ObservableResource.js +5 -0
  106. package/src/core/data/observable-helpers/observable.prototypes.js +2 -0
  107. package/src/core/elements/content-formatter.js +16 -2
  108. package/src/core/elements/form.js +1 -1
  109. package/src/core/elements/img.js +1 -1
  110. package/src/core/elements/medias.js +2 -2
  111. package/src/core/elements/meta-data.js +1 -1
  112. package/src/core/wrappers/AttributesWrapper.js +37 -22
  113. package/src/core/wrappers/ElementCreator.js +9 -16
  114. package/src/core/wrappers/HtmlElementWrapper.js +26 -7
  115. package/src/core/wrappers/NDElement.js +12 -1
  116. package/src/core/wrappers/prototypes/attributes-extensions.js +24 -24
  117. package/src/core/wrappers/prototypes/nd-element-extensions.js +1 -8
  118. package/src/ui/components/card/CardRender.js +133 -0
  119. package/src/ui/components/card/card.css +169 -0
  120. package/src/ui/components/contextmenu/ContextmenuRender.js +1 -1
  121. package/src/ui/components/icon/material/MaterialIconRender.js +71 -0
  122. package/src/ui/components/icon/material/material.css +15 -0
  123. package/src/ui/components/icon/material/material.map.js +170 -0
  124. package/src/ui/components/icon/phosphor/PhosphorIconRender.js +71 -0
  125. package/src/ui/components/icon/phosphor/phosphor.css +17 -0
  126. package/src/ui/components/icon/phosphor/phosphor.map.js +165 -0
  127. package/src/ui/components/icon/tabler/TablerIconRender.js +59 -0
  128. package/src/ui/components/icon/tabler/tabler.css +14 -0
  129. package/src/ui/components/icon/tabler/tabler.map.js +165 -0
  130. package/src/ui/components/list/ListRender.js +18 -0
  131. package/src/ui/components/list/divider/ListDividerRender.js +10 -0
  132. package/src/ui/components/list/divider/list-divider.css +12 -0
  133. package/src/ui/components/list/group/ListGroupRender.js +61 -0
  134. package/src/ui/components/list/group/list-group.css +62 -0
  135. package/src/ui/components/list/item/ListItemRender.js +238 -0
  136. package/src/ui/components/list/item/list-item.css +191 -0
  137. package/src/ui/components/list/list.css +24 -0
  138. package/src/ui/components/spacer/SpacerRender.js +10 -0
  139. package/src/ui/index.js +13 -0
@@ -0,0 +1,155 @@
1
+ ---
2
+ title: Skeleton
3
+ description: Placeholder that mimics content shape while loading
4
+ ---
5
+
6
+ # Skeleton
7
+
8
+ ```javascript
9
+ import { Skeleton } from 'native-document/components';
10
+
11
+ Skeleton(props?)
12
+ ```
13
+
14
+ A placeholder that mimics the shape of content while it loads.
15
+
16
+ ## Default Renderer
17
+
18
+ ```javascript
19
+ import { SkeletonRender } from 'native-document/ui';
20
+
21
+ Skeleton.use(SkeletonRender);
22
+ ```
23
+
24
+ ## `$description`
25
+
26
+ ```javascript
27
+ {
28
+ type: 'rect', // 'rect' | 'circle' | 'text' | 'avatar' | 'image'
29
+ variant: 'pulse', // 'pulse' | 'wave'
30
+ borderRadiusType: 'rounded',
31
+ lines: null, // number - for text type
32
+ width: null,
33
+ height: null,
34
+ loading: null, // Observable<boolean>
35
+ repeat: null, // number - repeat N times
36
+ props: {} // HTML attributes for the root element
37
+ }
38
+ ```
39
+
40
+ ## Methods
41
+
42
+ ```javascript
43
+ // Type
44
+ .rect()
45
+ .circle()
46
+ .text(lines?)
47
+ .avatar()
48
+ .image()
49
+
50
+ // Animation
51
+ .pulse()
52
+ .wave()
53
+
54
+ // Size
55
+ .width(200)
56
+ .height(100)
57
+ .size(width, height)
58
+
59
+ // Shape
60
+ .rounded()
61
+ .pill()
62
+ .smooth()
63
+
64
+ // Options
65
+ .lines(3)
66
+ .repeat(4)
67
+ .loading(isLoading)
68
+ ```
69
+
70
+ ## Built-in Presets
71
+
72
+ Skeleton ships with four ready-to-use presets:
73
+
74
+ ### `Skeleton.card(type?)`
75
+
76
+ A card with an image area and text lines below:
77
+
78
+ ```javascript
79
+ Skeleton.card()
80
+ Skeleton.card('featured') // adds type as extra CSS class
81
+ ```
82
+
83
+ ### `Skeleton.list(items?)`
84
+
85
+ A list of rows with avatar and text lines. Default: 3 items:
86
+
87
+ ```javascript
88
+ Skeleton.list()
89
+ Skeleton.list(5)
90
+ ```
91
+
92
+ ### `Skeleton.table(rows?, cols?)`
93
+
94
+ A table with a header row and data rows. Default: 5 rows, 4 cols:
95
+
96
+ ```javascript
97
+ Skeleton.table()
98
+ Skeleton.table(10, 6)
99
+ ```
100
+
101
+ ### `Skeleton.paragraph(lines?)`
102
+
103
+ A block of text lines. Default: 3 lines:
104
+
105
+ ```javascript
106
+ Skeleton.paragraph()
107
+ Skeleton.paragraph(5)
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Custom Presets
113
+
114
+ Register your own reusable shapes with `Skeleton.preset()` or `Skeleton.presets()`:
115
+
116
+ ```javascript
117
+ Skeleton.preset('userRow', (skeleton) => {
118
+ return skeleton.avatar().circle().size(40, 40);
119
+ });
120
+
121
+ // Register multiple at once
122
+ Skeleton.presets({
123
+ title: (s) => s.rect().width(200).height(24).rounded(),
124
+ avatar: (s) => s.circle().size(48, 48),
125
+ });
126
+
127
+ // Usage
128
+ Skeleton.userRow()
129
+ Skeleton.title()
130
+ ```
131
+
132
+ ## Example
133
+
134
+ ```javascript
135
+ ShowIf(isLoading, () =>
136
+ VStack([
137
+ Skeleton().avatar().circle().size(48, 48),
138
+ Skeleton().text(3)
139
+ ]).spacing(8)
140
+ )
141
+ ```
142
+
143
+ ---
144
+
145
+ ## Theming
146
+
147
+ ```css
148
+ :root {
149
+ --skeleton-color: var(--gray-lite-4);
150
+ --skeleton-highlight: var(--gray-lite-5);
151
+ --skeleton-radius: var(--radius-button);
152
+ --skeleton-wave-duration: 1.6s;
153
+ --skeleton-pulse-duration: 1.2s;
154
+ }
155
+ ```
@@ -0,0 +1,100 @@
1
+ ---
2
+ title: Spinner
3
+ description: Loading indicator with multiple types, sizes, and overlay support
4
+ ---
5
+
6
+ # Spinner
7
+
8
+ ```javascript
9
+ import { Spinner } from 'native-document/components';
10
+
11
+ Spinner(props?)
12
+ ```
13
+
14
+ A loading indicator.
15
+
16
+ ## Default Renderer
17
+
18
+ ```javascript
19
+ import { SpinnerRender } from 'native-document/ui';
20
+
21
+ Spinner.use(SpinnerRender);
22
+ ```
23
+
24
+ ## `$description`
25
+
26
+ ```javascript
27
+ {
28
+ type: 'circle', // 'circle' | 'dots' | 'bars' | 'pulse' | 'ring'
29
+ variant: 'primary',
30
+ color: null,
31
+ size: 'small', // 'xs' | 'small' | 'medium' | 'large'
32
+ label: null,
33
+ labelPosition: null, // 'top' | 'bottom' | 'left' | 'right'
34
+ overlay: null,
35
+ backdrop: null,
36
+ fullScreenOverlay: null,
37
+ speed: 'normal', // 'slow' | 'normal' | 'fast'
38
+ props: {} // HTML attributes for the root element
39
+ }
40
+ ```
41
+
42
+ ## Methods
43
+
44
+ ```javascript
45
+ // Type
46
+ .circle()
47
+ .dots()
48
+ .bars()
49
+ .pulse()
50
+ .ring()
51
+
52
+ // Size
53
+ .extraSmall()
54
+ .small()
55
+ .medium()
56
+ .large()
57
+
58
+ // Style
59
+ .primary()
60
+ .color('#3b82f6')
61
+ .speed('fast')
62
+
63
+ // Label
64
+ .label('Loading...')
65
+ .labelPosition('bottom')
66
+
67
+ // Overlay
68
+ .overlay()
69
+ .fullScreenOverlay()
70
+ ```
71
+
72
+ ## Example
73
+
74
+ ```javascript
75
+ ShowIf(isLoading, () => Spinner().large().label('Loading...'))
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Theming
81
+
82
+ ```css
83
+ :root {
84
+ --spinner-size-extra-small: 16px;
85
+ --spinner-size-small: 24px;
86
+ --spinner-size-medium: 36px;
87
+ --spinner-size-large: 48px;
88
+ --spinner-size-extra-large: 64px;
89
+ --spinner-speed-slow: 1.2s;
90
+ --spinner-speed-normal: 0.8s;
91
+ --spinner-speed-fast: 0.4s;
92
+ --spinner-thickness: 3px;
93
+ --spinner-color: var(--color-primary);
94
+ --spinner-color-primary: var(--color-primary);
95
+ --spinner-color-secondary: var(--color-secondary-text);
96
+ --spinner-color-success: var(--color-success);
97
+ --spinner-color-danger: var(--color-danger);
98
+ --spinner-color-warning: var(--color-warning);
99
+ }
100
+ ```
@@ -0,0 +1,133 @@
1
+ ---
2
+ title: Splitter
3
+ description: Resizable split panel layout with horizontal and vertical orientations
4
+ ---
5
+
6
+ # Splitter
7
+
8
+ ```javascript
9
+ import { Splitter, SplitterPanel, SplitterGutter } from 'native-document/components';
10
+ ```
11
+
12
+ ## Default Renderer
13
+
14
+ ```javascript
15
+ import { SplitterRender, SplitterPanelRender, SplitterGutterRender } from 'native-document/ui';
16
+
17
+ Splitter.use(SplitterRender);
18
+ SplitterPanel.use(SplitterPanelRender);
19
+ SplitterGutter.use(SplitterGutterRender);
20
+ ```
21
+
22
+ ---
23
+
24
+ ## `Splitter`
25
+
26
+ ### Methods
27
+
28
+ | Method | Parameters | Description |
29
+ |---|---|---|
30
+ | `.horizontal()` | - | Side-by-side layout (default) |
31
+ | `.vertical()` | - | Stacked layout |
32
+ | `.gutterSize(px)` | `px: number` | Width of the drag handle in px |
33
+ | `.panel(content, options?, props?)` | `content: NdChild`, `options?: object` | Add a panel inline |
34
+ | `.panels(panels)` | `panels: SplitterPanel[]` | Add multiple panels at once |
35
+ | `.dynamic()` | - | Enable dynamic panel management (add/remove at runtime) |
36
+ | `.removePanel(panel)` | `panel: SplitterPanel` | Remove a panel dynamically |
37
+ | `.onResize(handler)` | `handler: (sizes) => void` | Fires on every resize |
38
+ | `.onPanelAdd(handler)` | `handler: (panel) => void` | Fires when a panel is added dynamically |
39
+ | `.onPanelRemove(handler)` | `handler: (panel) => void` | Fires when a panel is removed dynamically |
40
+
41
+ The inline `options` object for `.panel(content, options)` accepts the same properties as `SplitterPanel` methods: `size`, `minSize`, `maxSize`, `collapsible`.
42
+
43
+ ---
44
+
45
+ ## `SplitterPanel`
46
+
47
+ | Method | Parameters | Description |
48
+ |---|---|---|
49
+ | `.content(element)` | `element: NdChild` | Panel content |
50
+ | `.size(value)` | `value: string \| number` | Initial size (`'30%'`, `300`) |
51
+ | `.minSize(px)` | `px: number` | Minimum size in px |
52
+ | `.maxSize(px)` | `px: number` | Maximum size in px |
53
+ | `.collapsible(enabled?)` | `enabled?: boolean` | Allow collapsing to 0 |
54
+ | `.collapsed(val?)` | `val?: boolean` | Start collapsed |
55
+ | `.resizable(enabled?)` | `enabled?: boolean` | Enable/disable resize for this panel |
56
+ | `.fixed()` | - | Panel is not resizable and keeps its size |
57
+ | `.data(data)` | `data: *` | Attach metadata to the panel |
58
+
59
+ ---
60
+
61
+ ## `SplitterGutter`
62
+
63
+ The drag handle between panels. No extra methods - its appearance is controlled entirely by the renderer.
64
+
65
+ ---
66
+
67
+ ## Dynamic panels
68
+
69
+ Use `.dynamic()` to add or remove panels at runtime. Track a panel reference to remove it later:
70
+
71
+ ```javascript
72
+ const sidebar = SplitterPanel(SidebarContent)
73
+ .size('25%')
74
+ .minSize(150)
75
+ .collapsible();
76
+
77
+ const splitter = Splitter()
78
+ .dynamic()
79
+ .panel(sidebar)
80
+ .panel(SplitterPanel(MainContent).size('75%'))
81
+ .onPanelAdd((panel) => console.log('Panel added'))
82
+ .onPanelRemove((panel) => console.log('Panel removed'));
83
+
84
+ // Remove the sidebar later
85
+ Button('Hide sidebar').nd.onClick(() => splitter.removePanel(sidebar))
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Example
91
+
92
+ ```javascript
93
+ Splitter()
94
+ .horizontal()
95
+ .gutterSize(4)
96
+ .panel(
97
+ SplitterPanel(FileExplorer)
98
+ .size('20%')
99
+ .minSize(150)
100
+ .collapsible()
101
+ )
102
+ .panel(
103
+ SplitterPanel(
104
+ Splitter()
105
+ .vertical()
106
+ .panel(CodeEditor, { size: '70%' })
107
+ .panel(Terminal, { size: '30%', minSize: 100 })
108
+ ).size('80%')
109
+ )
110
+ .onResize((sizes) => savePanelSizes(sizes))
111
+ ```
112
+
113
+
114
+ ---
115
+
116
+ ## Theming
117
+
118
+ ```css
119
+ :root {
120
+ --splitter-gutter-size: 1px;
121
+ --splitter-gutter-hit-area: 8px;
122
+ --splitter-gutter-color: var(--gray-lite-3);
123
+ --splitter-gutter-handle-size: 32px;
124
+ --splitter-gutter-handle-color: var(--gray-lite-2);
125
+ --splitter-gutter-handle-color-hover: var(--color-primary);
126
+ }
127
+ ```
128
+
129
+ ---
130
+
131
+ ## Next Steps
132
+
133
+ - **[Layout](./layout.md)** - Stack-based layout components
@@ -0,0 +1,163 @@
1
+ ---
2
+ title: Stepper
3
+ description: Multi-step wizard component with validation, navigation, and custom renderers
4
+ ---
5
+
6
+ # Stepper
7
+
8
+ ```javascript
9
+ import { Stepper, StepperStep } from 'native-document/components';
10
+ ```
11
+
12
+ ## Default Renderer
13
+
14
+ ```javascript
15
+ import { StepperRender, StepperStepRender } from 'native-document/ui';
16
+
17
+ Stepper.use(StepperRender);
18
+ StepperStep.use(StepperStepRender);
19
+ ```
20
+
21
+ ---
22
+
23
+ ## `Stepper`
24
+
25
+ ### Configuration
26
+
27
+ | Method | Parameters | Description |
28
+ |---|---|---|
29
+ | `.step(step)` | `step: StepperStep` | Add a step |
30
+ | `.data(data)` | `data: *` | Initial data passed to all steps |
31
+ | `.currentStep(obs)` | `obs: Observable<number>` | Bind the current step index to an observable |
32
+ | `.linear(enabled?)` | `enabled?: boolean` | Steps must complete in order (default) |
33
+ | `.nonLinear()` | - | Can jump to any step freely |
34
+ | `.editable(enabled?)` | `enabled?: boolean` | Allow returning to completed steps |
35
+ | `.horizontal()` | - | Horizontal layout (default) |
36
+ | `.vertical()` | - | Vertical layout |
37
+ | `.alternativeLabel(enabled?)` | `enabled?: boolean` | Labels below the indicators |
38
+ | `.showNumbers(enabled?)` | `enabled?: boolean` | Show step numbers in indicators |
39
+ | `.showConnector(enabled?)` | `enabled?: boolean` | Show connector line between steps |
40
+
41
+ ### Navigation position
42
+
43
+ | Method | Description |
44
+ |---|---|
45
+ | `.navigationAtBottom()` | Navigation buttons at the bottom, horizontal layout |
46
+ | `.navigationAtTop()` | Navigation buttons at the top, horizontal layout |
47
+ | `.navigationAtLeading()` | Navigation buttons on the leading side, vertical layout |
48
+
49
+ ### Navigation methods
50
+
51
+ | Method | Parameters | Description |
52
+ |---|---|---|
53
+ | `await stepper.next()` | - | Validates current step, then advances |
54
+ | `stepper.previous()` | - | Go to previous step |
55
+ | `await stepper.goToStep(index)` | `index: number` | Jump to a step (0-indexed) |
56
+ | `stepper.reset()` | - | Reset to step 0 |
57
+
58
+ ### Events
59
+
60
+ | Method | Parameters | Description |
61
+ |---|---|---|
62
+ | `.onStepChange(handler)` | `handler: (current, previous) => void` | Fires on every step change |
63
+ | `.onNext(handler)` | `handler: (step, index) => void` | Fires when advancing |
64
+ | `.onPrevious(handler)` | `handler: (step, index) => void` | Fires when going back |
65
+ | `.onComplete(handler)` | `handler: (data) => void` | Fires when last step is completed |
66
+ | `.onReset(handler)` | `handler: () => void` | Fires on reset |
67
+
68
+ ### Custom renderers
69
+
70
+ | Method | Parameters | Description |
71
+ |---|---|---|
72
+ | `.renderStepIndicator(fn)` | `fn: ($step) => NdChild` | Custom step indicator (circle/icon) |
73
+ | `.renderStepIndicatorConnector(fn)` | `fn: ($step) => NdChild` | Custom connector between indicators |
74
+ | `.renderContent(fn)` | `fn: ($step) => NdChild` | Custom step content wrapper |
75
+
76
+ ---
77
+
78
+ ## `StepperStep`
79
+
80
+ ```javascript
81
+ StepperStep(title)
82
+ ```
83
+
84
+ | Method | Parameters | Description |
85
+ |---|---|---|
86
+ | `.description(text)` | `text: string` | Subtitle below the step title |
87
+ | `.icon(element)` | `element: NdChild` | Icon displayed in the indicator |
88
+ | `.content(element)` | `element: NdChild` | Step body content |
89
+ | `.key(key)` | `key: string` | Unique identifier for this step |
90
+ | `.optional()` | - | Mark step as optional (can be skipped) |
91
+ | `.disabled(val)` | `val: boolean \| Observable<boolean>` | Disable the step |
92
+ | `.visibility(val)` | `val: boolean \| Observable<boolean>` | Show or hide the step reactively |
93
+ | `.validator(fn)` | `fn: () => boolean \| Promise<boolean>` | Validation function - must return `true` to advance |
94
+
95
+ ---
96
+
97
+ ## Example
98
+
99
+ ```javascript
100
+ const refs = {};
101
+
102
+ const wizard = Stepper()
103
+ .linear()
104
+ .step(
105
+ StepperStep('Account')
106
+ .content(AccountForm().nd.refSelf(refs, 'accountForm'))
107
+ .validator(async () => refs.accountForm.validate())
108
+ )
109
+ .step(
110
+ StepperStep('Profile')
111
+ .description('Tell us about yourself')
112
+ .content(ProfileForm)
113
+ .optional()
114
+ )
115
+ .step(
116
+ StepperStep('Done')
117
+ .icon(CheckIcon)
118
+ .content(SuccessPanel)
119
+ )
120
+ .navigationAtBottom()
121
+ .onComplete(async (data) => {
122
+ await registerUser(data);
123
+ })
124
+
125
+ document.body.appendChild(wizard);
126
+ ```
127
+
128
+
129
+ ---
130
+
131
+ ## Theming
132
+
133
+ ```css
134
+ :root {
135
+ --stepper-connector-color: var(--gray-lite-3);
136
+ --stepper-connector-color-active: var(--color-primary);
137
+ --stepper-connector-color-completed: var(--color-success);
138
+ --stepper-connector-thickness: 2px;
139
+ --step-indicator-size: 32px;
140
+ --step-indicator-bg: var(--gray-lite-4);
141
+ --step-indicator-bg-active: var(--color-primary);
142
+ --step-indicator-bg-completed: var(--color-success);
143
+ --step-indicator-bg-error: var(--color-danger);
144
+ --step-indicator-color: var(--gray);
145
+ --step-indicator-color-active: var(--white);
146
+ --step-indicator-font-size: var(--hint-size);
147
+ --step-indicator-font-weight: 600;
148
+ --step-label-size: var(--hint-size);
149
+ --step-label-color: var(--gray);
150
+ --step-label-color-active: var(--text-color);
151
+ --step-label-weight: 500;
152
+ --step-description-size: var(--note-size);
153
+ --step-description-color: var(--gray);
154
+ --stepper-content-padding: var(--space-comfortable) 0;
155
+ }
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Next Steps
161
+
162
+ - **[Components Overview](./index.md)** - BaseComponent philosophy
163
+ - **[FormControl](./form/form-control.md)** - Form validation with steps
@@ -0,0 +1,113 @@
1
+ ---
2
+ title: Switch
3
+ description: Toggle switch component with two-way binding, variants, icons, and inner labels
4
+ ---
5
+
6
+ # Switch
7
+
8
+ ```javascript
9
+ import { Switch } from 'native-document/components';
10
+
11
+ Switch(props?)
12
+ ```
13
+
14
+ ## Default Renderer
15
+
16
+ ```javascript
17
+ import { SwitchRender } from 'native-document/ui';
18
+
19
+ Switch.use(SwitchRender);
20
+ ```
21
+
22
+ ## `$description`
23
+
24
+ ```javascript
25
+ {
26
+ value: Observable(false),
27
+ label: null,
28
+ labelPosition: Observable('right'), // 'left' | 'right' | 'top' | 'bottom'
29
+ variant: Observable('primary'),
30
+ outline: false,
31
+ disabled: false,
32
+ loading: false,
33
+ readonly: false,
34
+ onIcon: null,
35
+ offIcon: null,
36
+ innerOnLabel: null,
37
+ innerOffLabel: null,
38
+ props: {} // HTML attributes for the root element
39
+ }
40
+ ```
41
+
42
+ ## Methods
43
+
44
+ ```javascript
45
+ // Binding
46
+ .model(Observable(false))
47
+
48
+ // Label
49
+ .label('Enable notifications')
50
+ .labelPosition('left') // 'left' | 'right' | 'top' | 'bottom'
51
+
52
+ // Inner labels (inside the toggle)
53
+ .innerLabel('Yes', 'No')
54
+
55
+ // Icons
56
+ .icon(SunIcon, MoonIcon) // onIcon, offIcon
57
+
58
+ // Variants
59
+ .primary()
60
+ .success()
61
+ .danger()
62
+ .warning()
63
+ .ghost()
64
+ .outline()
65
+
66
+ // State
67
+ .disabled(Observable(false))
68
+ .loading(Observable(false))
69
+ .readonly(true)
70
+
71
+ // Programmatic
72
+ .toggle()
73
+ .on()
74
+ .off()
75
+
76
+ // Events
77
+ .onChange((value) => console.log('Changed:', value))
78
+ .onOn(() => console.log('Switched on'))
79
+ .onOff(() => console.log('Switched off'))
80
+ ```
81
+
82
+ ## Example
83
+
84
+ ```javascript
85
+ const darkMode = Observable(false);
86
+
87
+ Switch()
88
+ .model(darkMode)
89
+ .label('Dark mode')
90
+ .icon(SunIcon, MoonIcon)
91
+ .innerLabel('On', 'Off')
92
+ .onChange((value) => applyTheme(value ? 'dark' : 'light'))
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Theming
98
+
99
+ ```css
100
+ :root {
101
+ --switch-width: 44px;
102
+ --switch-height: 24px;
103
+ --switch-thumb-size: 18px;
104
+ --switch-thumb-offset: 3px;
105
+ --switch-border-width: 0px;
106
+ --switch-track-bg: var(--gray-lite-3);
107
+ --switch-track-bg-active: var(--color-primary);
108
+ --switch-thumb-bg: var(--background);
109
+ --switch-thumb-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
110
+ --switch-transition: 0.2s ease;
111
+ --switch-label-gap: var(--space-cozy);
112
+ }
113
+ ```