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,115 @@
1
+ ---
2
+ title: Form Fields
3
+ description: Overview of all form field components and the shared Field API
4
+ ---
5
+
6
+ # Form Fields
7
+
8
+ NativeDocument provides a complete set of form field components. All fields extend `Field` which provides a consistent API for binding, validation, labels, and rendering.
9
+
10
+ ```javascript
11
+ import { Field } from 'native-document/components';
12
+ import { FieldRender } from 'native-document/ui';
13
+
14
+ Field.use(FieldRender);
15
+ ```
16
+
17
+ ---
18
+
19
+ ## Shared Field API
20
+
21
+ All form fields share the following methods:
22
+
23
+ ### Binding
24
+
25
+ ```javascript
26
+ .model(observable)
27
+ .bind(observable) // alias
28
+ .default('value')
29
+ ```
30
+
31
+ ### Labels & hints
32
+
33
+ ```javascript
34
+ .label('Email address')
35
+ .placeholder('you@example.com')
36
+ .help('We will never share your email.')
37
+ .hint('Required')
38
+ ```
39
+
40
+ ### State
41
+
42
+ ```javascript
43
+ .disabled(Observable(false))
44
+ .readonly(true)
45
+ .clearable()
46
+ ```
47
+
48
+ ### Slots
49
+
50
+ ```javascript
51
+ .leading(Icon) // prefix
52
+ .trailing(Icon) // suffix
53
+ .bottom(Div('hint')) // below the input
54
+ ```
55
+
56
+ ### HTML attributes
57
+
58
+ ```javascript
59
+ .wrapperProps({ class: 'form-group' })
60
+ .inputProps({ autocomplete: 'off' })
61
+ .labelProps({ class: 'form-label' })
62
+ .errorProps({ class: 'invalid-feedback' })
63
+ .hintProps({ class: 'form-text' })
64
+ ```
65
+
66
+ ### Validation
67
+
68
+ ```javascript
69
+ .required('This field is required')
70
+ .requiredIf(condition, 'Required when condition is true')
71
+ .custom((value, allValues) => {
72
+ if (value.startsWith('bad')) {
73
+ return 'Value cannot start with "bad"';
74
+ }
75
+ return true; // pass
76
+ })
77
+ .validateOn('blur') // 'blur' | 'input' | 'change'
78
+ .clearErrorOn('focus') // 'focus' | 'input'
79
+ .setError('Server-side error')
80
+ .showErrors()
81
+ .hideErrors()
82
+ .validate(allValues) // returns true | false
83
+ ```
84
+
85
+ ### Observables on `$description`
86
+
87
+ ```javascript
88
+ field.$description.hasErrors // Observable<boolean>
89
+ field.$description.errors // ObservableArray
90
+ field.$description.isDirty // Observable<boolean>
91
+ field.$description.isTouched // Observable<boolean>
92
+ field.$description.focus // Observable<boolean>
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Available Fields
98
+
99
+ | File | Components |
100
+ |---|---|
101
+ | [String Field](./string-field.md) | `StringField`, `EmailField`, `PasswordField`, `TelField`, `UrlField`, `HiddenField` |
102
+ | [Number Field](./number-field.md) | `NumberField`, `RangeField` |
103
+ | [Textarea Field](./textarea-field.md) | `TextAreaField` |
104
+ | [Date Field](./date-field.md) | `DateField`, `TimeField` |
105
+ | [Select Field](./select-field.md) | `SelectField` |
106
+ | [Autocomplete Field](./autocomplete-field.md) | `AutocompleteField` |
107
+ | [Checkbox Field](./checkbox-field.md) | `CheckboxField` |
108
+ | [Checkbox Group Field](./checkbox-group-field.md) | `CheckboxGroupField` |
109
+ | [Radio Field](./radio-field.md) | `RadioField` |
110
+ | [Color Field](./color-field.md) | `ColorField` |
111
+ | [File Field](./file-field.md) | `FileField` + all modes |
112
+ | [Image Field](./image-field.md) | `ImageField` |
113
+ | [Slider](./slider.md) | `Slider` |
114
+ | [Field Collection](./field-collection.md) | `FieldCollection` |
115
+ | [Form Control](./form-control.md) | `FormControl` |
@@ -0,0 +1,65 @@
1
+ ---
2
+ title: Number Fields
3
+ description: NumberField and RangeField for numeric input
4
+ ---
5
+
6
+ # Number Fields
7
+
8
+ ```javascript
9
+ import { NumberField, RangeField } from 'native-document/components';
10
+ ```
11
+
12
+ ## Default Renderers
13
+
14
+ ```javascript
15
+ import { NumberFieldRender, RangeFieldRender } from 'native-document/ui';
16
+
17
+ NumberField.use(NumberFieldRender);
18
+ RangeField.use(RangeFieldRender);
19
+ ```
20
+
21
+ ---
22
+
23
+ ## `NumberField`
24
+
25
+ ```javascript
26
+ NumberField('quantity')
27
+ .label('Quantity')
28
+ .model(quantity)
29
+ .min(1, 'Minimum 1')
30
+ .max(100, 'Maximum 100')
31
+ .step(1)
32
+ .required()
33
+ ```
34
+
35
+ ### Additional methods
36
+
37
+ ```javascript
38
+ .min(value, message?)
39
+ .max(value, message?)
40
+ .between(min, max, message?)
41
+ .integer(message?)
42
+ .positive(message?)
43
+ .unsigned(message?) // alias for positive
44
+ .negative(message?)
45
+ .multipleOf(n, message?)
46
+ .step(value)
47
+ .decimals(count?)
48
+ .prefix(text)
49
+ .suffix(text)
50
+ ```
51
+
52
+ ---
53
+
54
+ ## `RangeField`
55
+
56
+ A range slider bound to a field model.
57
+
58
+ ```javascript
59
+ RangeField('volume')
60
+ .label('Volume')
61
+ .model(volume)
62
+ .min(0)
63
+ .max(100)
64
+ .step(5)
65
+ ```
@@ -0,0 +1,51 @@
1
+ ---
2
+ title: RadioField
3
+ description: Group of radio buttons where only one can be selected
4
+ ---
5
+
6
+ # RadioField
7
+
8
+ ```javascript
9
+ import { RadioField } from 'native-document/components';
10
+
11
+ RadioField(name, props?)
12
+ ```
13
+
14
+ ## Default Renderer
15
+
16
+ ```javascript
17
+ import { RadioFieldRender } from 'native-document/ui';
18
+
19
+ RadioField.use(RadioFieldRender);
20
+ ```
21
+
22
+ ## Methods
23
+
24
+ | Method | Parameters | Description |
25
+ |---|---|---|
26
+ | `.model(observable)` | `observable: Observable` | Two-way binding - value of the selected option |
27
+ | `.label(text)` | `text: NdChild` | Label for the field group |
28
+ | `.disabled(val)` | `val: boolean \| Observable<boolean>` | Disable the field |
29
+ | `.option(value, label, props?)` | `value: *`, `label: NdChild`, `props?: object` | Add a radio option |
30
+ | `.options(items)` | `items: { value, label }[]` | Add multiple options at once |
31
+ | `.layout(type)` | `'vertical' \| 'horizontal' \| 'grid'` | Layout of the radio buttons. Default `'vertical'` |
32
+ | `.vertical()` | - | Shorthand for `.layout('vertical')` |
33
+ | `.horizontal()` | - | Shorthand for `.layout('horizontal')` |
34
+ | `.grid()` | - | Shorthand for `.layout('grid')` |
35
+ | `.required(message?)` | `message?: string` | Validation - field required |
36
+ | `.checked()` | - | Returns the current checked value (getter) |
37
+
38
+ ## Example
39
+
40
+ ```javascript
41
+ const plan = Observable('monthly');
42
+
43
+ RadioField('plan')
44
+ .label('Choose a plan')
45
+ .model(plan)
46
+ .option('monthly', 'Monthly - $9/mo')
47
+ .option('yearly', 'Yearly - $99/yr')
48
+ .option('lifetime', 'Lifetime - $299')
49
+ .horizontal()
50
+ .required('Please select a plan')
51
+ ```
@@ -0,0 +1,123 @@
1
+ ---
2
+ title: SelectField
3
+ description: Select dropdown with search, multiple selection, groups, and custom item rendering
4
+ ---
5
+
6
+ # SelectField
7
+
8
+ ```javascript
9
+ import { SelectField } from 'native-document/components';
10
+
11
+ SelectField(name, props?)
12
+ ```
13
+
14
+ ## Default Renderer
15
+
16
+ ```javascript
17
+ import { SelectFieldRender } from 'native-document/ui';
18
+
19
+ SelectField.use(SelectFieldRender);
20
+ ```
21
+
22
+ ## Methods
23
+
24
+ ### Options
25
+
26
+ ```javascript
27
+ .option(value, label, props?)
28
+ .option('fr', 'France')
29
+ .option('de', 'Germany', { disabled: true })
30
+ .options([
31
+ { value: 'fr', label: 'France' },
32
+ { value: 'de', label: 'Germany' }
33
+ ])
34
+ .options(Observable.array([...])) // reactive
35
+ ```
36
+
37
+ ### Groups
38
+
39
+ ```javascript
40
+ .groups([
41
+ {
42
+ label: 'Europe',
43
+ options: [
44
+ { value: 'fr', label: 'France' },
45
+ { value: 'de', label: 'Germany' }
46
+ ]
47
+ },
48
+ {
49
+ label: 'Africa',
50
+ options: [
51
+ { value: 'sn', label: 'Senegal' }
52
+ ]
53
+ }
54
+ ])
55
+ ```
56
+
57
+ ### Multiple selection
58
+
59
+ ```javascript
60
+ .multiple()
61
+ .multipleDisplayAsText() // "France, Germany"
62
+ .multipleDisplayAsTags() // tag chips
63
+ .multipleDisplayAsCount() // "3 selected"
64
+ .multipleDisplayAsTruncate(2) // "France, Germany +1"
65
+ .removeSelected() // hide selected options from the list
66
+ ```
67
+
68
+ ### Binding & behavior
69
+
70
+ ```javascript
71
+ .model(Observable(null)) // single selection
72
+ .model(Observable([])) // multiple selection
73
+ .searchable()
74
+ .searchable(true, 'Search...')
75
+ .clearable()
76
+ .disabled(Observable(false))
77
+ .onChange((value) => console.log(value))
78
+ ```
79
+
80
+ ### Custom rendering
81
+
82
+ ```javascript
83
+ .renderItem(($option) =>
84
+ HStack([
85
+ Img({ src: `/flags/${$option.value}.svg`, width: 20 }),
86
+ Span($option.label)
87
+ ]).spacing(8)
88
+ )
89
+ .selectedLabelRender(($option) => `${$option.label} (${$option.value})`)
90
+ .countRender((count) => `${count} countries selected`)
91
+ .truncateRender((visible, hidden) => `${visible} +${hidden} more`)
92
+ ```
93
+
94
+ ## Example
95
+
96
+ ```javascript
97
+ SelectField('country')
98
+ .label('Country')
99
+ .model(country)
100
+ .searchable()
101
+ .clearable()
102
+ .options(countriesList)
103
+ .required('Please select a country')
104
+ .onChange((value) => loadRegions(value))
105
+ ```
106
+
107
+ ## Multiple selection example
108
+
109
+ ```javascript
110
+ const selected = Observable([]);
111
+
112
+ SelectField('tags')
113
+ .label('Tags')
114
+ .model(selected)
115
+ .multiple()
116
+ .multipleDisplayAsTags()
117
+ .removeSelected()
118
+ .options([
119
+ { value: 'js', label: 'JavaScript' },
120
+ { value: 'ts', label: 'TypeScript' },
121
+ { value: 'py', label: 'Python' },
122
+ ])
123
+ ```
@@ -0,0 +1,136 @@
1
+ ---
2
+ title: Slider
3
+ description: Range input component with single value, range mode, marks, and tooltips
4
+ ---
5
+
6
+ # Slider
7
+
8
+ ```javascript
9
+ import { Slider } from 'native-document/components';
10
+
11
+ Slider(name, props?)
12
+ ```
13
+
14
+ ## Default Renderer
15
+
16
+ ```javascript
17
+ import { SliderFieldRender } from 'native-document/ui';
18
+
19
+ Slider.use(SliderFieldRender);
20
+ ```
21
+
22
+ ## Methods
23
+
24
+ ### Value
25
+
26
+ | Method | Parameters | Description |
27
+ |---|---|---|
28
+ | `.model(observable)` | `observable: Observable<number>` | Two-way binding for single value |
29
+ | `.modelStart(observable)` | `observable: Observable<number>` | Two-way binding for range start |
30
+ | `.modelEnd(observable)` | `observable: Observable<number>` | Two-way binding for range end |
31
+ | `.defaultValue(value)` | `value: number` | Initial value |
32
+ | `.range(enabled?)` | `enabled?: boolean` | Enable range mode (two handles) |
33
+ | `.min(value)` | `value: number` | Minimum value |
34
+ | `.max(value)` | `value: number` | Maximum value |
35
+ | `.step(value)` | `value: number` | Step increment |
36
+
37
+ ### Display
38
+
39
+ | Method | Parameters | Description |
40
+ |---|---|---|
41
+ | `.showValue(enabled?)` | `enabled?: boolean` | Display the current value |
42
+ | `.showTooltip(enabled?)` | `enabled?: boolean` | Show tooltip on the handle |
43
+ | `.tooltipFormat(fn)` | `fn: (value) => string` | Format the tooltip value |
44
+ | `.renderTooltip(fn)` | `fn: ($description) => NdChild` | Custom tooltip renderer |
45
+ | `.renderThumb(fn)` | `fn: ($description) => NdChild` | Custom thumb renderer |
46
+ | `.renderCursor(fn)` | `fn: ($description) => NdChild` | Custom cursor renderer |
47
+
48
+ ### Marks
49
+
50
+ | Method | Parameters | Description |
51
+ |---|---|---|
52
+ | `.marks(marks)` | `marks: { value, label }[]` | Define tick marks |
53
+ | `.showMarks(enabled?)` | `enabled?: boolean` | Show tick marks |
54
+ | `.snapToMarks(enabled?)` | `enabled?: boolean` | Snap handle to nearest mark |
55
+
56
+ ### Style
57
+
58
+ | Method | Parameters | Description |
59
+ |---|---|---|
60
+ | `.primary()` | - | Primary color variant |
61
+ | `.secondary()` | - | Secondary color variant |
62
+ | `.success()` | - | Success color variant |
63
+ | `.warning()` | - | Warning color variant |
64
+ | `.danger()` | - | Danger color variant |
65
+ | `.info()` | - | Info color variant |
66
+ | `.color(hex)` | `hex: string` | Custom handle color |
67
+ | `.trackColor(hex)` | `hex: string` | Custom track color |
68
+ | `.fillColor(hex)` | `hex: string` | Custom fill color |
69
+ | `.fullColor(hex)` | `hex: string` | Color for the full track |
70
+
71
+ ### Layout
72
+
73
+ | Method | Parameters | Description |
74
+ |---|---|---|
75
+ | `.vertical(enabled?)` | `enabled?: boolean` | Vertical orientation |
76
+ | `.height(px)` | `px: number` | Height in px (vertical mode) |
77
+ | `.reverse(enabled?)` | `enabled?: boolean` | Reverse the track direction |
78
+
79
+ ### State
80
+
81
+ | Method | Parameters | Description |
82
+ |---|---|---|
83
+ | `.disabled(condition?)` | `condition?: boolean \| Observable<boolean>` | Disable the slider |
84
+ | `.readonly(condition?)` | `condition?: boolean` | Read-only mode |
85
+
86
+ ### Events
87
+
88
+ | Method | Parameters | Description |
89
+ |---|---|---|
90
+ | `.onChange(handler)` | `handler: (value) => void` | Fires on every value change |
91
+ | `.onComplete(handler)` | `handler: (value) => void` | Fires when the user releases the handle |
92
+
93
+ ## Example
94
+
95
+ ```javascript
96
+ // Single value
97
+ const volume = Observable(70);
98
+
99
+ Slider('volume')
100
+ .model(volume)
101
+ .min(0)
102
+ .max(100)
103
+ .step(5)
104
+ .showTooltip()
105
+ .tooltipFormat((v) => `${v}%`)
106
+ .primary()
107
+
108
+ // Range
109
+ const priceMin = Observable(100);
110
+ const priceMax = Observable(500);
111
+
112
+ Slider('price')
113
+ .range()
114
+ .modelStart(priceMin)
115
+ .modelEnd(priceMax)
116
+ .min(0)
117
+ .max(1000)
118
+ .step(50)
119
+ .showValue()
120
+
121
+ // Vertical with marks
122
+ Slider('temperature')
123
+ .model(Observable(20))
124
+ .min(-10)
125
+ .max(40)
126
+ .vertical()
127
+ .height(200)
128
+ .marks([
129
+ { value: -10, label: '-10' },
130
+ { value: 0, label: '0' },
131
+ { value: 20, label: '20' },
132
+ { value: 40, label: '40' }
133
+ ])
134
+ .showMarks()
135
+ .snapToMarks()
136
+ ```
@@ -0,0 +1,134 @@
1
+ ---
2
+ title: String Fields
3
+ description: StringField, EmailField, PasswordField, TelField, UrlField, HiddenField
4
+ ---
5
+
6
+ # String Fields
7
+
8
+ ```javascript
9
+ import {
10
+ StringField, EmailField, PasswordField,
11
+ TelField, UrlField, HiddenField
12
+ } from 'native-document/components';
13
+ ```
14
+
15
+ ## Default Renderers
16
+
17
+ ```javascript
18
+ import {
19
+ StringFieldRender, EmailFieldRender, PasswordFieldRender,
20
+ TelFieldRender, UrlFieldRender, HiddenFieldRender
21
+ } from 'native-document/ui';
22
+
23
+ StringField.use(StringFieldRender);
24
+ EmailField.use(EmailFieldRender);
25
+ PasswordField.use(PasswordFieldRender);
26
+ TelField.use(TelFieldRender);
27
+ UrlField.use(UrlFieldRender);
28
+ HiddenField.use(HiddenFieldRender);
29
+ ```
30
+
31
+ ---
32
+
33
+ ## `StringField`
34
+
35
+ ```javascript
36
+ StringField('username')
37
+ .label('Username')
38
+ .placeholder('Choose a username')
39
+ .model(username)
40
+ .required()
41
+ .minLength(3, 'At least 3 characters')
42
+ .maxLength(20)
43
+ .pattern(/^[a-z0-9_]+$/, 'Lowercase, numbers, underscores only')
44
+ ```
45
+
46
+ ### Additional methods
47
+
48
+ ```javascript
49
+ .minLength(min, message?)
50
+ .maxLength(max, message?)
51
+ .length(exact, message?)
52
+ .pattern(regex, message?)
53
+ .alphaOnly(message?)
54
+ .numericOnly(message?)
55
+ .alphaNumeric(message?)
56
+ .noSpaces(message?)
57
+ .lowercase(message?)
58
+ .uppercase(message?)
59
+ ```
60
+
61
+ ---
62
+
63
+ ## `EmailField`
64
+
65
+ ```javascript
66
+ EmailField('email')
67
+ .label('Email')
68
+ .model(email)
69
+ .required()
70
+ .allowedDomain(['company.com'], 'Only company emails allowed')
71
+ ```
72
+
73
+ ### Additional methods
74
+
75
+ ```javascript
76
+ .email(message?)
77
+ .allowedDomain(domains, message?)
78
+ .notAllowedDomain(domains, message?)
79
+ ```
80
+
81
+ ---
82
+
83
+ ## `PasswordField`
84
+
85
+ ```javascript
86
+ PasswordField('password')
87
+ .label('Password')
88
+ .model(password)
89
+ .required()
90
+ .minLength(8)
91
+ .strong('Password is too weak')
92
+ .visibilityToggle()
93
+ .showStrengthMeter()
94
+ ```
95
+
96
+ ### Additional methods
97
+
98
+ ```javascript
99
+ .strong(message?)
100
+ .containsNumber(message?)
101
+ .containsUppercase(message?)
102
+ .containsLowercase(message?)
103
+ .containsSpecialChar(message?)
104
+ .visibilityToggle(enabled?, icons?)
105
+ .visibilityIcons(showIcon, hideIcon)
106
+ .showStrengthMeter()
107
+ .strengthLabels({ weak, fair, good, strong })
108
+ .same(fieldName, message?) // must match another field
109
+ .different(fieldName, message?) // must differ from another field
110
+ ```
111
+
112
+ ---
113
+
114
+ ## `TelField`
115
+
116
+ ```javascript
117
+ TelField('phone').label('Phone').model(phone)
118
+ ```
119
+
120
+ ---
121
+
122
+ ## `UrlField`
123
+
124
+ ```javascript
125
+ UrlField('website').label('Website').model(url)
126
+ ```
127
+
128
+ ---
129
+
130
+ ## `HiddenField`
131
+
132
+ ```javascript
133
+ HiddenField('csrf').model(csrfToken)
134
+ ```
@@ -0,0 +1,65 @@
1
+ ---
2
+ title: TextAreaField
3
+ description: Multi-line text input with auto-grow and character counter
4
+ ---
5
+
6
+ # TextAreaField
7
+
8
+ ```javascript
9
+ import { TextAreaField } from 'native-document/components';
10
+
11
+ TextAreaField(name, props?)
12
+ ```
13
+
14
+ ## Default Renderer
15
+
16
+ ```javascript
17
+ import { TextAreaFieldRender } from 'native-document/ui';
18
+
19
+ TextAreaField.use(TextAreaFieldRender);
20
+ ```
21
+
22
+ ## Methods
23
+
24
+ All shared Field methods apply (`model`, `label`, `placeholder`, `required`, `disabled`, `readonly`, `minLength`, `maxLength`…), plus:
25
+
26
+ | Method | Parameters | Description |
27
+ |---|---|---|
28
+ | `.rows(n)` | `n: number` | Number of visible rows |
29
+ | `.cols(n)` | `n: number` | Number of visible columns |
30
+ | `.resize(type)` | `'none' \| 'vertical' \| 'horizontal' \| 'both'` | CSS resize behavior |
31
+ | `.autoGrow(enabled?)` | `enabled?: boolean` | Grow height automatically as content increases |
32
+ | `.characterCounter(enabled?)` | `enabled?: boolean` | Show current / max character count |
33
+ | `.wordCount(min?, max?, message?)` | `min?: number`, `max?: number`, `message?: string` | Validate word count |
34
+
35
+ ## Example
36
+
37
+ ```javascript
38
+ TextAreaField('message')
39
+ .label('Message')
40
+ .placeholder('Write your message...')
41
+ .model(message)
42
+ .required()
43
+ .rows(5)
44
+ .autoGrow()
45
+ .characterCounter()
46
+ .maxLength(500)
47
+ ```
48
+
49
+ ## Validation example
50
+
51
+ ```javascript
52
+ const bio = Observable('');
53
+
54
+ TextAreaField('bio')
55
+ .label('About you')
56
+ .placeholder('Tell us about yourself...')
57
+ .model(bio)
58
+ .required('Bio is required')
59
+ .minLength(20, 'At least 20 characters')
60
+ .maxLength(500)
61
+ .rows(4)
62
+ .autoGrow()
63
+ .characterCounter()
64
+ .resize('none')
65
+ ```