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,89 @@
1
+ ---
2
+ title: Breadcrumb
3
+ description: Breadcrumb navigation component with custom separators and click handlers
4
+ ---
5
+
6
+ # Breadcrumb
7
+
8
+ ```javascript
9
+ import { Breadcrumb } from 'native-document/components';
10
+
11
+ Breadcrumb(props?)
12
+ ```
13
+
14
+ ## Default Renderer
15
+
16
+ ```javascript
17
+ import { BreadcrumbRender } from 'native-document/ui';
18
+
19
+ Breadcrumb.use(BreadcrumbRender);
20
+ ```
21
+
22
+ ## Methods
23
+
24
+ ```javascript
25
+ // Add items
26
+ .item(label, href?, value?)
27
+ .items([{ label, href, value }, ...])
28
+ .removeItem(index)
29
+
30
+ // Bind to an observable array
31
+ .bind(Observable.array([...]))
32
+
33
+ // Separator
34
+ .separator('/')
35
+ .separator(ChevronIcon)
36
+ .renderSeparator(($description) => Span(' > '))
37
+
38
+ // Events
39
+ .onItemClick((item, index) => Router.push(item.href))
40
+
41
+ // Custom renderers
42
+ .renderItem(($item) => Link({ href: $item.href }, $item.label))
43
+ ```
44
+
45
+ ## Example
46
+
47
+ ```javascript
48
+ Breadcrumb()
49
+ .item('Home', '/')
50
+ .item('Products', '/products')
51
+ .item('Laptops', '/products/laptops')
52
+ .item('MacBook Pro') // current - no href
53
+ .separator('/')
54
+ .onItemClick((item) => {
55
+ if (item.href) {
56
+ Router.push(item.href);
57
+ }
58
+ })
59
+ ```
60
+
61
+ ## Reactive Binding
62
+
63
+ ```javascript
64
+ const crumbs = Observable.array([
65
+ { label: 'Home', href: '/' },
66
+ { label: 'Products', href: '/products' }
67
+ ]);
68
+
69
+ Breadcrumb().bind(crumbs).separator(ChevronRight)
70
+
71
+ // Update dynamically
72
+ crumbs.push({ label: 'Laptops', href: '/products/laptops' });
73
+ ```
74
+
75
+ ---
76
+
77
+ ## Theming
78
+
79
+ ```css
80
+ :root {
81
+ --breadcrumb-font-size: var(--description-size);
82
+ --breadcrumb-color: var(--gray);
83
+ --breadcrumb-color-active: var(--text-color);
84
+ --breadcrumb-color-hover: var(--color-primary);
85
+ --breadcrumb-separator-color: var(--gray-lite-2);
86
+ --breadcrumb-separator: '/';
87
+ --breadcrumb-gap: var(--space-cozy);
88
+ }
89
+ ```
@@ -0,0 +1,183 @@
1
+ ---
2
+ title: Button
3
+ description: Headless Button component with variants, sizes, loading state, icons, and presets
4
+ ---
5
+
6
+ # Button
7
+
8
+ ```javascript
9
+ import { Button } from 'native-document/components';
10
+
11
+ Button(label, props?)
12
+ ```
13
+
14
+ ## Default Renderer
15
+
16
+ ```javascript
17
+ import { ButtonRender } from 'native-document/ui';
18
+ import { SpinnerRender } from 'native-document/ui';
19
+
20
+ Button.use(ButtonRender);
21
+ Spinner.use(SpinnerRender); // required - loading state is rendered as a spinner
22
+ ```
23
+
24
+ ## `$description`
25
+
26
+ ```javascript
27
+ {
28
+ label: 'Submit',
29
+ type: null, // 'button' | 'submit' | 'reset'
30
+ variant: null,
31
+ size: null, // 'small' | 'medium' | 'large'
32
+ icon: null, // DOM element
33
+ iconPosition: 'leading', // 'leading' | 'trailing' | 'top' | 'bottom'
34
+ iconOnly: false,
35
+ loading: null, // Observable<boolean>
36
+ disabled: null, // Observable<boolean>
37
+ outline: false,
38
+ block: false,
39
+ borderRadiusType: null, // 'rounded' | 'pill' | 'circle' | 'smooth'
40
+ props: {} // HTML attributes for the root element
41
+ }
42
+ ```
43
+
44
+ ## Methods
45
+
46
+ ### Variants
47
+
48
+ ```javascript
49
+ .primary()
50
+ .secondary()
51
+ .danger()
52
+ .success()
53
+ .warning()
54
+ .ghost()
55
+ .link()
56
+ .outline()
57
+ ```
58
+
59
+ ### Size
60
+
61
+ ```javascript
62
+ .small()
63
+ .medium()
64
+ .large()
65
+ ```
66
+
67
+ ### Shape
68
+
69
+ ```javascript
70
+ .rounded()
71
+ .pill()
72
+ .circle()
73
+ .smooth()
74
+ ```
75
+
76
+ ### Icon
77
+
78
+ ```javascript
79
+ .icon(element, position?)
80
+ .iconAtLeading()
81
+ .iconAtTrailing()
82
+ .iconAtTop()
83
+ .iconAtBottom()
84
+ .iconOnly()
85
+ ```
86
+
87
+ ### State
88
+
89
+ ```javascript
90
+ .loading(observable | true)
91
+ .disabled(observable | true)
92
+ .block()
93
+ .type('submit')
94
+ ```
95
+
96
+ ## Example
97
+
98
+ ```javascript
99
+ const isLoading = Observable(false);
100
+
101
+ Button('Save Changes')
102
+ .primary()
103
+ .large()
104
+ .rounded()
105
+ .loading(isLoading)
106
+ .icon(SaveIcon)
107
+ .nd
108
+ .onClick(async () => {
109
+ isLoading.set(true);
110
+ await save();
111
+ isLoading.set(false);
112
+ })
113
+ ```
114
+
115
+ ## Presets
116
+
117
+ ```javascript
118
+ Button.preset('save', (label, props) => {
119
+ return Button(label || 'Save', props).primary();
120
+ });
121
+ Button.preset('cancel', (label, props) => {
122
+ return Button(label || 'Cancel', props).ghost();
123
+ });
124
+
125
+ Button.save()
126
+ Button.cancel('Go back')
127
+ ```
128
+
129
+ ## Custom Renderer Example
130
+
131
+ ```javascript
132
+ Button.use(($description) => {
133
+ return NativeButton({
134
+ type: $description.type || 'button',
135
+ class: buildClasses($description),
136
+ disabled: $description.disabled,
137
+ ...$description.props
138
+ }, [
139
+ ShowIf($description.loading, () => Spinner()),
140
+ ShowIf($description.icon && $description.iconPosition === 'leading', () => $description.icon),
141
+ ShowIf(!$description.iconOnly, $description.label),
142
+ ShowIf($description.icon && $description.iconPosition === 'trailing', () => $description.icon),
143
+ ]);
144
+ });
145
+ ```
146
+
147
+ ---
148
+
149
+ ## Theming
150
+
151
+ ```css
152
+ :root {
153
+ --btn-height-small: 28px;
154
+ --btn-height-medium: 36px;
155
+ --btn-height-large: 44px;
156
+ --btn-padding-small: 0 var(--space-cozy-comfortable);
157
+ --btn-padding-medium: 0 var(--space-comfortable);
158
+ --btn-padding-large: 0 var(--space-relaxed);
159
+ --btn-font-size-small: var(--note-size);
160
+ --btn-font-size-medium: var(--description-size);
161
+ --btn-font-size-large: var(--text-size);
162
+ --btn-icon-size-small: 14px;
163
+ --btn-icon-size-medium: 16px;
164
+ --btn-icon-size-large: 18px;
165
+ --btn-loader-size: 14px;
166
+ --btn-gap: var(--space-cozy);
167
+ --btn-font-weight: 500;
168
+ --btn-transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
169
+ --btn-disabled-opacity: 0.45;
170
+ --btn-color-primary: var(--color-primary);
171
+ --btn-color-primary-hover: var(--color-primary-hover);
172
+ --btn-color-secondary: var(--color-secondary);
173
+ --btn-color-secondary-hover: var(--color-secondary-hover);
174
+ --btn-color-danger: var(--color-danger);
175
+ --btn-color-danger-hover: var(--color-danger-hover);
176
+ --btn-color-success: var(--color-success);
177
+ --btn-color-success-hover: var(--color-success-hover);
178
+ --btn-color-warning: var(--color-warning);
179
+ --btn-color-warning-hover: var(--color-warning-hover);
180
+ --btn-color-info: var(--color-info);
181
+ --btn-color-info-hover: var(--color-info-hover);
182
+ }
183
+ ```
@@ -0,0 +1,69 @@
1
+ ---
2
+ title: Card
3
+ description: Versatile content container with optional image, header, footer, and actions
4
+ ---
5
+
6
+ # Card
7
+
8
+ > **Status: coming soon.** The `Card` API is fully defined but the default renderer is not yet implemented. You can use `Card` today by providing your own renderer via `Card.use()`.
9
+
10
+ ```javascript
11
+ import { Card } from 'native-document/components';
12
+
13
+ Card(props?)
14
+ ```
15
+
16
+ ## Custom Renderer
17
+
18
+ Until the default renderer ships, register your own:
19
+
20
+ ```javascript
21
+ import { Div, Img, H3, P, Button, HStack } from 'native-document/elements';
22
+
23
+ Card.use(($d, instance) => {
24
+ return Div({ class: `card ${$d.variant ?? ''}` }, [
25
+ $d.image ? Img({ src: $d.image.src, class: `card-image card-image-${$d.image.position}` }) : null,
26
+ Div({ class: 'card-body' }, [
27
+ $d.title ? H3({ class: 'card-title' }, $d.title) : null,
28
+ $d.subtitle ? P({ class: 'card-subtitle' }, $d.subtitle) : null,
29
+ $d.content ? Div({ class: 'card-content' }, $d.content) : null,
30
+ ]),
31
+ $d.actions?.length ? HStack({ class: 'card-footer' },
32
+ $d.actions.map(a => Button(a.label).nd.onClick(a.callback))
33
+ ) : null,
34
+ ]);
35
+ });
36
+ ```
37
+
38
+ ## Methods
39
+
40
+ | Method | Parameters | Description |
41
+ |---|---|---|
42
+ | `.title(element)` | `element: NdChild` | Card title |
43
+ | `.subtitle(element)` | `element: NdChild` | Card subtitle |
44
+ | `.image(src, position?)` | `src: string`, `position?: 'top' \| 'bottom' \| 'left' \| 'right'` | Card image. Default position: `'top'` |
45
+ | `.content(element)` | `element: NdChild` | Card body content |
46
+ | `.action(label, callback)` | `label: NdChild`, `callback: () => void` | Add a footer action button |
47
+ | `.clearActions()` | - | Remove all action buttons |
48
+ | `.variant(name)` | `name: string` | CSS variant class |
49
+ | `.elevated()` | - | Shorthand for `.variant('elevated')` |
50
+ | `.outlined()` | - | Shorthand for `.variant('outlined')` |
51
+ | `.flat()` | - | Shorthand for `.variant('flat')` |
52
+ | `.horizontal()` | - | Horizontal layout (image on the left) |
53
+ | `.clickable(handler)` | `handler: (event) => void` | Make the entire card clickable |
54
+ | `.hoverable()` | - | Add hover effect |
55
+ | `.loading(val?)` | `val?: boolean \| Observable<boolean>` | Show loading state |
56
+ | `.onClick(handler)` | `handler: (event) => void` | Click event |
57
+ | `.onHover(handler)` | `handler: (event) => void` | Hover event |
58
+ | `.renderImage(fn)` | `fn: ($d, instance) => NdChild` | Custom image renderer |
59
+ | `.renderHeader(fn)` | `fn: ($d, instance) => NdChild` | Custom header renderer |
60
+ | `.renderContent(fn)` | `fn: ($d, instance) => NdChild` | Custom content renderer |
61
+ | `.renderFooter(fn)` | `fn: ($d, instance) => NdChild` | Custom footer renderer |
62
+ | `.layout(fn)` | `fn: ($d, instance) => NdChild` | Fully custom layout |
63
+
64
+ ---
65
+
66
+ ## Next Steps
67
+
68
+ - **[Components Overview](./index.md)** - BaseComponent and renderer pattern
69
+ - **[Getting Started](./getting-started.md)** - Register default renderers
@@ -0,0 +1,118 @@
1
+ ---
2
+ title: Context Menu
3
+ description: Right-click context menu with trigger binding, items, groups, and dividers
4
+ ---
5
+
6
+ # Context Menu
7
+
8
+ ```javascript
9
+ import { ContextMenu, ContextMenuGroup, ContextMenuItem } from 'native-document/components';
10
+ import { Menu, MenuGroup, MenuItem, MenuDivider, MenuLink } from 'native-document/components';
11
+ ```
12
+
13
+ `ContextMenu.use()` takes two arguments - a renderer and a handler. The handler wires the right-click behavior to any element, making `.nd.contextMenu()` available on all elements.
14
+
15
+ ## Default Renderer
16
+
17
+ ```javascript
18
+ import {
19
+ ContextMenuRender, contextMenuHandler,
20
+ MenuRender, MenuGroupRender, MenuItemRender,
21
+ MenuDividerRender, MenuLinkRender
22
+ } from 'native-document/ui';
23
+
24
+ Menu.use(MenuRender);
25
+ MenuGroup.use(MenuGroupRender);
26
+ MenuItem.use(MenuItemRender);
27
+ MenuDivider.use(MenuDividerRender);
28
+ MenuLink.use(MenuLinkRender);
29
+ ContextMenu.use(ContextMenuRender, contextMenuHandler);
30
+ ```
31
+
32
+ ## Building a Context Menu
33
+
34
+ ```javascript
35
+ const tableContextMenu = ContextMenu()
36
+ .menu((menu) => {
37
+ menu
38
+ .item('Edit', { action: (data) => openEdit(data) })
39
+ .item('Duplicate', { action: (data) => duplicate(data) })
40
+ .divider()
41
+ // pass a function to get the MenuItem instance for fluent configuration
42
+ .item('Delete', (item) => {
43
+ item
44
+ .action((data) => deleteRow(data))
45
+ .icon(TrashIcon)
46
+ .shortcut('+Delete')
47
+ .danger()
48
+ })
49
+ });
50
+
51
+ // Attach to any element, pass contextual data
52
+ TableRow(item)
53
+ .nd.contextMenu(tableContextMenu, item)
54
+ ```
55
+
56
+ ## Methods
57
+
58
+ ```javascript
59
+ .menu((menu) => { menu.item(...) })
60
+ .position(x, y)
61
+ .show()
62
+ .hide()
63
+ .trigger(element)
64
+ ```
65
+
66
+ ## `ContextMenuItem`
67
+
68
+ ```javascript
69
+ ContextMenuItem()
70
+ .label('Edit')
71
+ .icon(EditIcon)
72
+ .action((data) => openEditor(data))
73
+ .shortcut('+E') // short convention: + = meta/ctrl, ++ = meta+alt
74
+ .disabled(false)
75
+ .danger()
76
+ ```
77
+
78
+ ### Shortcut convention
79
+
80
+ | Syntax | Meaning |
81
+ |---|---|
82
+ | `'+S'` | Ctrl/Cmd + S |
83
+ | `'++S'` | Ctrl/Cmd + Alt + S |
84
+ | `'+Shift+S'` | Ctrl/Cmd + Shift + S |
85
+ | `'Ctrl+S'` | Standard form |
86
+ | `'Cmd+Shift+S'` | Standard form |
87
+
88
+ Shortcuts are displayed automatically per OS - Mac uses symbols (`⌘ S`), Windows uses labels (`Ctrl+S`).
89
+
90
+ See **[ShortcutManager](./shortcut-manager.md)** for the full reference.
91
+
92
+ ## `ContextMenuGroup`
93
+
94
+ Groups items under a label:
95
+
96
+ ```javascript
97
+ ContextMenuGroup('File actions')
98
+ .item('New', handler)
99
+ .item('Open', handler)
100
+ .divider()
101
+ .item('Save', handler)
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Theming
107
+
108
+ ```css
109
+ :root {
110
+ --context-menu-bg: var(--background);
111
+ --context-menu-border: var(--gray-lite-3);
112
+ --context-menu-radius: var(--radius-card);
113
+ --context-menu-shadow: var(--shadow-lg);
114
+ --context-menu-z-index: 99999;
115
+ --context-menu-min-width: 180px;
116
+ --context-menu-animation-duration: 0.12s;
117
+ }
118
+ ```