native-document 1.0.166 → 1.0.168

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 (108) hide show
  1. package/.vitepress/config.js +166 -0
  2. package/CHANGELOG.md +153 -0
  3. package/components.js +2 -1
  4. package/dist/native-document.components.min.js +495 -228
  5. package/dist/native-document.dev.js +7 -0
  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/index.md +337 -0
  41. package/docs/components/layout.md +279 -0
  42. package/docs/components/list.md +73 -0
  43. package/docs/components/menu.md +215 -0
  44. package/docs/components/modal.md +156 -0
  45. package/docs/components/pagination.md +95 -0
  46. package/docs/components/popover.md +131 -0
  47. package/docs/components/progress.md +111 -0
  48. package/docs/components/shortcut-manager.md +221 -0
  49. package/docs/components/simple-table.md +107 -0
  50. package/docs/components/skeleton.md +155 -0
  51. package/docs/components/spinner.md +100 -0
  52. package/docs/components/splitter.md +133 -0
  53. package/docs/components/stepper.md +163 -0
  54. package/docs/components/switch.md +113 -0
  55. package/docs/components/tabs.md +153 -0
  56. package/docs/components/toast.md +119 -0
  57. package/docs/components/tooltip.md +151 -0
  58. package/docs/components/traits.md +261 -0
  59. package/docs/conditional-rendering.md +170 -588
  60. package/docs/contributing.md +300 -25
  61. package/docs/core-concepts.md +205 -374
  62. package/docs/elements.md +251 -367
  63. package/docs/extending-native-document-element.md +192 -207
  64. package/docs/filters.md +153 -1122
  65. package/docs/getting-started.md +193 -267
  66. package/docs/i18n.md +241 -0
  67. package/docs/index.md +76 -0
  68. package/docs/lifecycle-events.md +143 -75
  69. package/docs/list-rendering.md +227 -852
  70. package/docs/memory-management.md +134 -47
  71. package/docs/native-document-element.md +337 -186
  72. package/docs/native-fetch.md +99 -630
  73. package/docs/observable-resource.md +364 -0
  74. package/docs/observables.md +592 -526
  75. package/docs/routing.md +244 -653
  76. package/docs/state-management.md +134 -241
  77. package/docs/svg-elements.md +231 -0
  78. package/docs/theming.md +409 -0
  79. package/docs/tutorials/.gitkeep +0 -0
  80. package/docs/validation.md +95 -97
  81. package/docs/vitepress-conventions.md +219 -0
  82. package/package.json +34 -13
  83. package/readme.md +269 -89
  84. package/src/components/card/Card.js +93 -39
  85. package/src/components/card/index.js +1 -1
  86. package/src/components/list/HasListItem.js +171 -0
  87. package/src/components/list/List.js +41 -107
  88. package/src/components/list/ListDivider.js +39 -0
  89. package/src/components/list/ListGroup.js +76 -59
  90. package/src/components/list/ListItem.js +117 -69
  91. package/src/components/list/index.js +3 -1
  92. package/src/components/list/types/ListItem.d.ts +45 -34
  93. package/src/components/spacer/Spacer.js +1 -1
  94. package/src/core/data/ObservableResource.js +5 -0
  95. package/src/core/data/observable-helpers/observable.prototypes.js +2 -0
  96. package/src/ui/components/card/CardRender.js +133 -0
  97. package/src/ui/components/card/card.css +169 -0
  98. package/src/ui/components/contextmenu/ContextmenuRender.js +1 -1
  99. package/src/ui/components/list/ListRender.js +18 -0
  100. package/src/ui/components/list/divider/ListDividerRender.js +10 -0
  101. package/src/ui/components/list/divider/list-divider.css +12 -0
  102. package/src/ui/components/list/group/ListGroupRender.js +61 -0
  103. package/src/ui/components/list/group/list-group.css +62 -0
  104. package/src/ui/components/list/item/ListItemRender.js +238 -0
  105. package/src/ui/components/list/item/list-item.css +191 -0
  106. package/src/ui/components/list/list.css +24 -0
  107. package/src/ui/components/spacer/SpacerRender.js +10 -0
  108. package/src/ui/index.js +8 -0
@@ -0,0 +1,215 @@
1
+ ---
2
+ title: Menu
3
+ description: Menu component with items, links, groups, dividers, keyboard navigation, and active state
4
+ ---
5
+
6
+ # Menu
7
+
8
+ ```javascript
9
+ import { Menu, MenuItem, MenuGroup, MenuLink, MenuDivider } from 'native-document/components';
10
+ ```
11
+
12
+ ## Default Renderer
13
+
14
+ ```javascript
15
+ import {
16
+ MenuRender, MenuItemRender,
17
+ MenuGroupRender, MenuLinkRender, MenuDividerRender
18
+ } from 'native-document/ui';
19
+
20
+ Menu.use(MenuRender);
21
+ MenuItem.use(MenuItemRender);
22
+ MenuGroup.use(MenuGroupRender);
23
+ MenuLink.use(MenuLinkRender);
24
+ MenuDivider.use(MenuDividerRender);
25
+ ```
26
+
27
+ ## Methods
28
+
29
+ ### Orientation
30
+
31
+ ```javascript
32
+ .horizontal()
33
+ .vertical()
34
+ .inline()
35
+ ```
36
+
37
+ ### Building items
38
+
39
+ ```javascript
40
+ .item(label, options?)
41
+ .item('Dashboard', { action: () => navigate('/'), icon: DashboardIcon, key: 'home' })
42
+
43
+ // Function form - receives MenuItem instance
44
+ .item('Settings', (item) => {
45
+ item.action(() => navigate('/settings'))
46
+ .icon(SettingsIcon)
47
+ .key('settings')
48
+ .shortcut('+,')
49
+ })
50
+
51
+ // Link item
52
+ .link(label, options?)
53
+ .link('Documentation', { href: 'https://docs.example.com', target: '_blank' })
54
+
55
+ // Router link
56
+ .linkTo(label, options?)
57
+ .linkTo('Home', { href: 'home' })
58
+ .linkTo('Profile', { href: { name: 'user', params: { id: 1 } } })
59
+
60
+ // Separator
61
+ .separator()
62
+ .divider() // alias
63
+
64
+ // Group
65
+ .group(label, (group) => {
66
+ group.item('Profile', { action: () => navigate('/profile') })
67
+ group.item('Security', { action: () => navigate('/security') })
68
+ group.separator()
69
+ group.item('Logout', { action: () => logout(), icon: LogoutIcon })
70
+ })
71
+ ```
72
+
73
+ ### Active state
74
+
75
+ ```javascript
76
+ .active(() => router.currentState().route?.name) // callback
77
+ .active(currentRoute.select(r => r.name)) // observable
78
+ ```
79
+
80
+ ### Behavior
81
+
82
+ ```javascript
83
+ .closeOnSelect(false)
84
+ .keyboardLoop(false)
85
+ .clickFirst()
86
+ .compactThreshold(80)
87
+ ```
88
+
89
+ ### Dynamic items
90
+
91
+ ```javascript
92
+ .bind(observableArray)
93
+ ```
94
+
95
+ ### Events
96
+
97
+ ```javascript
98
+ .onItemClick((item) => console.log('Clicked:', item.label))
99
+ .onItemSelect((item) => console.log('Selected:', item.key))
100
+ ```
101
+
102
+ ## Example - Sidebar Navigation
103
+
104
+ ```javascript
105
+ Menu()
106
+ .vertical()
107
+ .active(router.currentState().select(s => s.route?.name))
108
+ .item('Dashboard', { action: () => Router.push('/'), icon: HomeIcon, key: 'home' })
109
+ .item('Users', { action: () => Router.push('/users'), icon: UsersIcon, key: 'users' })
110
+ .separator()
111
+ .group('Settings', (group) => {
112
+ group.item('General', { action: () => Router.push('/settings'), key: 'settings' })
113
+ group.item('Security', { action: () => Router.push('/settings/security'), key: 'security' })
114
+ })
115
+ .separator()
116
+ .item('Logout', { action: () => logout(), icon: LogoutIcon, key: 'logout' })
117
+ ```
118
+
119
+ ## Example - Top Navigation
120
+
121
+ ```javascript
122
+ Menu()
123
+ .horizontal()
124
+ .linkTo('Home', { href: 'home' })
125
+ .linkTo('Products', { href: 'products' })
126
+ .linkTo('Pricing', { href: 'pricing' })
127
+ .link('Docs', { href: 'https://docs.example.com', target: '_blank' })
128
+ ```
129
+
130
+ ---
131
+
132
+ ## `MenuItem`
133
+
134
+ ```javascript
135
+ MenuItem()
136
+ .label('Dashboard')
137
+ .icon(DashboardIcon)
138
+ .key('dashboard')
139
+ .action(() => navigate('/dashboard'))
140
+ .shortcut('+D')
141
+ .disabled(Observable(false))
142
+ .selected(Observable(false))
143
+ .trailing(Badge('New').success())
144
+ ```
145
+
146
+ See **[ShortcutManager](./shortcut-manager.md)** for the shortcut convention.
147
+
148
+ ---
149
+
150
+ ## `MenuGroup`
151
+
152
+ ```javascript
153
+ MenuGroup('Settings')
154
+ .icon(SettingsIcon)
155
+ .collapsable()
156
+ .collapsed(true)
157
+ .item('Profile', { action: () => navigate('/profile') })
158
+ .item('Security', { action: () => navigate('/security') })
159
+ .divider()
160
+ .item('Logout', { action: logout })
161
+ ```
162
+
163
+ ---
164
+
165
+ ## `MenuLink`
166
+
167
+ Extends `MenuItem` with a `.target()` method:
168
+
169
+ ```javascript
170
+ MenuLink()
171
+ .label('Documentation')
172
+ .icon(BookIcon)
173
+ .action('https://docs.example.com')
174
+ .target('_blank')
175
+ ```
176
+
177
+ ---
178
+
179
+ ## `MenuDivider`
180
+
181
+ ```javascript
182
+ MenuDivider()
183
+ // or via shorthand:
184
+ menu.separator()
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Theming
190
+
191
+ ```css
192
+ :root {
193
+ --menu-bg: var(--background);
194
+ --menu-border: var(--gray-lite-3);
195
+ --menu-radius: var(--radius-card);
196
+ --menu-shadow: var(--shadow-md);
197
+ --menu-font-size: var(--description-size);
198
+ --menu-gap: var(--space-tiny);
199
+ --menu-padding: var(--space-cozy) 0;
200
+ --menu-item-padding: var(--space-cozy) var(--space-comfortable);
201
+ --menu-item-radius: var(--radius-button);
202
+ --menu-item-gap: var(--space-cozy);
203
+ --menu-item-color: var(--text-color);
204
+ --menu-item-color-hover: var(--text-color);
205
+ --menu-item-color-active: var(--color-primary);
206
+ --menu-item-color-disabled: var(--gray-lite-2);
207
+ --menu-item-bg-hover: var(--gray-lite-5);
208
+ --menu-group-label-size: var(--hint-size);
209
+ --menu-group-label-color: var(--gray);
210
+ --menu-shortcut-size: var(--note-size);
211
+ --menu-shortcut-color: var(--gray);
212
+ --menu-divider-color: var(--gray-lite-3);
213
+ --sub-menu-shadow: var(--shadow-lg);
214
+ }
215
+ ```
@@ -0,0 +1,156 @@
1
+ ---
2
+ title: Modal
3
+ description: Modal dialog with draggable and resizable support
4
+ ---
5
+
6
+ # Modal
7
+
8
+ ```javascript
9
+ import { Modal } from 'native-document/components';
10
+ ```
11
+
12
+ ## Default Renderers
13
+
14
+ ```javascript
15
+ import { ModalRender } from 'native-document/ui';
16
+
17
+ Modal.use(ModalRender);
18
+ ```
19
+
20
+ ---
21
+
22
+ ## `Modal`
23
+
24
+ ```javascript
25
+ Modal(content, props?)
26
+ ```
27
+
28
+ ### `$description`
29
+
30
+ ```javascript
31
+ {
32
+ content: null,
33
+ title: null,
34
+ footer: null,
35
+ size: null, // 'small' | 'medium' | 'large' | 'xl'
36
+ centered: true,
37
+ scrollable: false,
38
+ closeOnBackdrop: true,
39
+ closeOnEscape: true,
40
+ closable: true,
41
+ fullscreen: false,
42
+ draggable: false,
43
+ resizable: false,
44
+ focusTrap: true,
45
+ lockScroll: true,
46
+ isOpen: Observable(false),
47
+ props: {} // HTML attributes for the root element
48
+ }
49
+ ```
50
+
51
+ ### Methods
52
+
53
+ ```javascript
54
+ // Content
55
+ .title('Confirm deletion')
56
+ .content(Div('Are you sure?'))
57
+ .footer(
58
+ HStack([
59
+ Button('Cancel').ghost().nd.onClick(() => modal.close()),
60
+ Button('Delete').danger().nd.onClick(() => confirmDelete())
61
+ ]).justifyEnd().spacing(8)
62
+ )
63
+
64
+ // Size
65
+ .small()
66
+ .medium()
67
+ .large()
68
+ .extraLarge()
69
+ .fullscreen()
70
+
71
+ // Behavior
72
+ .centered()
73
+ .scrollable()
74
+ .closeOnBackdrop(false)
75
+ .closeOnEscape(false)
76
+ .closable(false)
77
+ .focusTrap(false)
78
+ .lockScroll(false)
79
+
80
+ // Draggable & Resizable
81
+ .draggable()
82
+ .resizable()
83
+ .resizable(true, { size: { minWidth: 300, minHeight: 200 } })
84
+
85
+ // Programmatic
86
+ .open()
87
+ .close()
88
+ .toggle()
89
+
90
+ // Events
91
+ .onOpen(() => console.log('Opened'))
92
+ .onClose(() => console.log('Closed'))
93
+ .onBeforeOpen(() => console.log('About to open'))
94
+ .onBeforeClose(() => console.log('About to close'))
95
+
96
+ // Custom renderers
97
+ .renderHeader(($description) => Div({ class: 'modal-header' }, $description.title))
98
+ .renderContent(($description) => Div({ class: 'modal-body' }, $description.content))
99
+ .renderFooter(($description) => Div({ class: 'modal-footer' }, $description.footer))
100
+ ```
101
+
102
+ ### Example
103
+
104
+ ```javascript
105
+ Modal(
106
+ Div([
107
+ P('This action cannot be undone.'),
108
+ P('All associated data will be permanently removed.')
109
+ ])
110
+ )
111
+ .title('Delete Account')
112
+ .footer(
113
+ HStack([
114
+ Button('Cancel').ghost().nd.onClick(() => deleteModal.close()),
115
+ Button('Yes, delete').danger().nd.onClick(async () => {
116
+ await deleteAccount();
117
+ deleteModal.close();
118
+ })
119
+ ]).justifyEnd().spacing(8)
120
+ )
121
+ .small()
122
+ .onOpen(() => trackEvent('delete_modal_open'))
123
+ .trigger(
124
+ Button('Delete account')
125
+ .danger()
126
+ )
127
+ ```
128
+
129
+ ---
130
+
131
+ ## Theming
132
+
133
+ ```css
134
+ :root {
135
+ --modal-bg: var(--white);
136
+ --modal-border: var(--gray-lite-5);
137
+ --modal-radius: var(--radius-card);
138
+ --modal-shadow: var(--shadow-lg);
139
+ --modal-z-index: 10001;
140
+ --modal-font-size: var(--description-size);
141
+ --modal-header-size: var(--text-size);
142
+ --modal-header-weight: 600;
143
+ --modal-padding: var(--space-comfortable);
144
+ --modal-header-padding: var(--space-tiny);
145
+ --modal-animation-duration: 0.2s;
146
+ --modal-width-small: 400px;
147
+ --modal-width-medium: 560px;
148
+ --modal-width-large: 720px;
149
+ --modal-width-extra-large: 960px;
150
+ --modal-backdrop-bg: rgba(0, 0, 0, 0.8);
151
+ --modal-close-width: 25px;
152
+ --modal-close-height: 25px;
153
+ --modal-close-hover-bg-color: var(--contrasted-red);
154
+ --modal-close-hover-color: var(--white);
155
+ }
156
+ ```
@@ -0,0 +1,95 @@
1
+ ---
2
+ title: Pagination
3
+ description: Standalone pagination component with first/last, ellipsis, and custom renderers
4
+ ---
5
+
6
+ # Pagination
7
+
8
+ ```javascript
9
+ import { Pagination } from 'native-document/components';
10
+
11
+ Pagination(props?)
12
+ ```
13
+
14
+ Standalone pagination. Also built into `DataTable`.
15
+
16
+ ## Default Renderer
17
+
18
+ ```javascript
19
+ import { PaginationRender } from 'native-document/ui';
20
+
21
+ Pagination.use(PaginationRender);
22
+ ```
23
+
24
+ ## Methods
25
+
26
+ ```javascript
27
+ // State
28
+ .currentPage(Observable(1))
29
+ .totalPages(Observable(10))
30
+ .totalItems(Observable(200))
31
+ .pageSize(20)
32
+ .disabled(Observable(false))
33
+
34
+ // Display
35
+ .siblingCount(1) // pages shown around current page
36
+ .boundaryCount(1) // pages shown at start and end
37
+ .showFirstLast()
38
+ .showPreviousNext()
39
+
40
+ // Navigation (programmatic)
41
+ .goToPage(3)
42
+ .next()
43
+ .previous()
44
+ .first()
45
+ .last()
46
+ .hasNext()
47
+ .hasPrevious()
48
+
49
+ // Events
50
+ .onPageChange((page) => fetchData(page))
51
+ .onChange((page) => fetchData(page)) // alias
52
+
53
+ // Custom renderers
54
+ .renderPage(($page) => Button($page.label))
55
+ .renderEllipsis(() => Span('...'))
56
+ .renderPrevious(() => Span('Prev'))
57
+ .renderNext(() => Span('Next'))
58
+ .renderFirst(() => Span('First'))
59
+ .renderLast(() => Span('Last'))
60
+ ```
61
+
62
+ ## Example
63
+
64
+ ```javascript
65
+ const page = Observable(1);
66
+ const total = Observable(50);
67
+
68
+ Pagination()
69
+ .currentPage(page)
70
+ .totalPages(total)
71
+ .siblingCount(2)
72
+ .showFirstLast()
73
+ .onPageChange((p) => {
74
+ page.set(p);
75
+ fetchUsers(p);
76
+ })
77
+ ```
78
+
79
+ ---
80
+
81
+ ## Theming
82
+
83
+ ```css
84
+ :root {
85
+ --pagination-gap: var(--space-cozy);
86
+ --pagination-font-size: var(--description-size);
87
+ --page-size: 36px;
88
+ --page-radius: var(--radius-button);
89
+ --page-color: var(--text-color);
90
+ --page-bg-hover: var(--gray-lite-5);
91
+ --page-bg-active: var(--color-primary);
92
+ --page-color-active: var(--white);
93
+ --page-color-disabled: var(--gray-lite-2);
94
+ }
95
+ ```
@@ -0,0 +1,131 @@
1
+ ---
2
+ title: Popover
3
+ description: Floating panel anchored to a trigger element with flexible positioning and interaction modes
4
+ ---
5
+
6
+ # Popover
7
+
8
+ ```javascript
9
+ import { Popover } from 'native-document/components';
10
+
11
+ Popover(content, props?)
12
+ ```
13
+
14
+ A floating panel anchored to a trigger element. Lighter than Modal - no overlay, positions relative to trigger.
15
+
16
+ ## Default Renderer
17
+
18
+ ```javascript
19
+ import { PopoverRender } from 'native-document/ui';
20
+
21
+ Popover.use(PopoverRender);
22
+ ```
23
+
24
+ ## `$description`
25
+
26
+ ```javascript
27
+ {
28
+ content: null,
29
+ header: null,
30
+ footer: null,
31
+ trigger: null,
32
+ interaction: 'click', // 'click' | 'hover' | 'focus'
33
+ position: 'bottom',
34
+ offset: [0, 8],
35
+ arrow: false,
36
+ shift: false,
37
+ closeOnEscape: true,
38
+ closeOnClickOutside: true,
39
+ focusTrap: false,
40
+ returnFocus: true,
41
+ matchTriggerWidth: null,
42
+ updatePositionOn: null,
43
+ isOpen: Observable(false),
44
+ props: {}
45
+ }
46
+ ```
47
+
48
+ ## Methods
49
+
50
+ | Method | Parameters | Description |
51
+ |---|---|---|
52
+ | `.content(element)` | `element: NdChild` | Popover body |
53
+ | `.header(element)` | `element: NdChild` | Popover header |
54
+ | `.footer(element)` | `element: NdChild` | Popover footer |
55
+ | `.trigger(element)` | `element: HTMLElement` | Element that opens the popover |
56
+ | `.onClicked()` | - | Open on click (default) |
57
+ | `.onHovered()` | - | Open on hover |
58
+ | `.onFocused()` | - | Open on focus |
59
+ | `.position(pos)` | `pos: string` | Position relative to trigger: `top`, `bottom`, `left`, `right`, `top-start`, `bottom-end`, etc. |
60
+ | `.offset([x, y])` | `[x: number, y: number]` | Offset from trigger in px |
61
+ | `.arrow()` | - | Show arrow pointing to trigger |
62
+ | `.shift()` | - | Keep popover in viewport when near edges |
63
+ | `.closeOnEscape(enabled)` | `enabled: boolean` | Default `true` |
64
+ | `.closeOnClickOutside(enabled)` | `enabled: boolean` | Default `true` |
65
+ | `.focusTrap()` | - | Trap focus inside the popover |
66
+ | `.returnFocus(enabled)` | `enabled: boolean` | Return focus to trigger on close. Default `true` |
67
+ | `.matchTriggerWidth()` | - | Set popover width to match the trigger width |
68
+ | `.updatePositionOn(observable)` | `observable: Observable` | Recalculate position when the observable changes |
69
+ | `.open()` | - | Open programmatically |
70
+ | `.close()` | - | Close programmatically |
71
+ | `.toggle()` | - | Toggle open/close |
72
+
73
+ ## Example
74
+
75
+ ```javascript
76
+ Popover(
77
+ VStack([
78
+ Avatar(user.avatar).medium(),
79
+ Div(user.name),
80
+ Div(user.email),
81
+ Divider(),
82
+ Button('View profile')
83
+ .ghost()
84
+ .block()
85
+ .nd.onClick(() => {
86
+ userPopover.close();
87
+ Router.push({ name: 'profile' });
88
+ })
89
+ ]).spacing(8)
90
+ )
91
+ .position('bottom-end')
92
+ .arrow()
93
+ .trigger(Button('Show Profile').warning())
94
+ ```
95
+
96
+ ---
97
+
98
+ ## Tooltip vs Popover
99
+
100
+ | | Tooltip | Popover |
101
+ |---|---|---|
102
+ | **Purpose** | Short contextual hint | Rich floating panel |
103
+ | **Content** | Text or simple element | Header, body, footer |
104
+ | **Triggered by** | Hover (default) | Click (default) |
105
+ | **Focus trap** | No | Optional |
106
+ | **Use when** | Labeling an icon, short help text | User profile card, settings panel |
107
+
108
+ See **[Tooltip](./tooltip.md)** for the lightweight alternative.
109
+
110
+
111
+ ---
112
+
113
+ ## Theming
114
+
115
+ ```css
116
+ :root {
117
+ --popover-bg: var(--background);
118
+ --popover-border: var(--gray-lite-3);
119
+ --popover-radius: var(--radius-card);
120
+ --popover-shadow: var(--shadow-lg);
121
+ --popover-padding: 0;
122
+ --popover-min-width: 200px;
123
+ --popover-max-width: 320px;
124
+ --popover-z-index: 100001;
125
+ --popover-font-size: var(--description-size);
126
+ --popover-header-size: var(--text-size);
127
+ --popover-header-weight: 600;
128
+ --popover-arrow-size: 8px;
129
+ --popover-animation-duration: 0.15s;
130
+ }
131
+ ```
@@ -0,0 +1,111 @@
1
+ ---
2
+ title: Progress
3
+ description: Progress bar and circular progress indicator
4
+ ---
5
+
6
+ # Progress
7
+
8
+ ```javascript
9
+ import { Progress } from 'native-document/components';
10
+
11
+ Progress(props?)
12
+ ```
13
+
14
+ ## Default Renderer
15
+
16
+ ```javascript
17
+ import { ProgressRender } from 'native-document/ui';
18
+
19
+ Progress.use(ProgressRender);
20
+ ```
21
+
22
+ ## `$description`
23
+
24
+ ```javascript
25
+ {
26
+ value: null, // number | Observable<number>
27
+ type: null, // 'linear' | 'circular'
28
+ variant: null,
29
+ max: 100,
30
+ size: null,
31
+ stroke: null, // circular stroke width
32
+ height: null, // linear height
33
+ showValue: null,
34
+ showPercentage: null,
35
+ label: null,
36
+ format: null, // (value, max) => string
37
+ indeterminate: null,
38
+ striped: null,
39
+ animated: null,
40
+ borderRadiusType: null,
41
+ props: {}
42
+ }
43
+ ```
44
+
45
+ ## Methods
46
+
47
+ | Method | Parameters | Description |
48
+ |---|---|---|
49
+ | `.value(val)` | `val: number \| Observable<number>` | Current value |
50
+ | `.max(val)` | `val: number` | Maximum value. Default `100` |
51
+ | `.type(type)` | `'linear' \| 'circular'` | Progress type |
52
+ | `.primary()` | - | Primary color variant |
53
+ | `.success()` | - | Success color variant |
54
+ | `.danger()` | - | Danger color variant |
55
+ | `.warning()` | - | Warning color variant |
56
+ | `.size(size)` | `'small' \| 'large'` | Size preset |
57
+ | `.height(px)` | `px: number` | Height in px (linear) |
58
+ | `.stroke(px)` | `px: number` | Stroke width in px (circular) |
59
+ | `.showValue()` | - | Display the numeric value |
60
+ | `.showPercentage()` | - | Display the percentage |
61
+ | `.label(text)` | `text: string` | Label beside the bar |
62
+ | `.format(fn)` | `fn: (value, max) => string` | Custom value formatter |
63
+ | `.indeterminate()` | - | Indeterminate animation (no known value) |
64
+ | `.striped()` | - | Striped style |
65
+ | `.animated()` | - | Animate the stripes |
66
+ | `.rounded()` | - | Rounded border radius |
67
+ | `.pill()` | - | Pill border radius |
68
+ | `.onComplete(handler)` | `handler: () => void` | Fires once when value reaches max |
69
+
70
+ ## Example
71
+
72
+ ```javascript
73
+ const progress = Observable(0);
74
+
75
+ Progress()
76
+ .value(progress)
77
+ .primary()
78
+ .showPercentage()
79
+ .striped()
80
+ .animated()
81
+ .onComplete(() => {
82
+ Toast('Upload complete!').success().show();
83
+ })
84
+ ```
85
+
86
+
87
+ ---
88
+
89
+ ## Theming
90
+
91
+ ```css
92
+ :root {
93
+ --progress-height-small: 4px;
94
+ --progress-height-medium: 8px;
95
+ --progress-height-large: 14px;
96
+ --progress-color: var(--gray-lite-4);
97
+ --progress-color-primary: var(--color-primary);
98
+ --progress-color-secondary: var(--color-secondary);
99
+ --progress-color-success: var(--color-success);
100
+ --progress-color-danger: var(--color-danger);
101
+ --progress-color-warning: var(--color-warning);
102
+ --progress-color-info: var(--color-info);
103
+ --progress-circle-size: 80px;
104
+ --progress-circle-thickness: 6px;
105
+ --progress-label-size: var(--note-size);
106
+ --progress-label-color: var(--gray);
107
+ --progress-stripe-size: 20px;
108
+ --progress-animation-duration: 1s;
109
+ --progress-indeterminate-duration: 1.5s;
110
+ }
111
+ ```