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.
- package/.vitepress/config.js +166 -0
- package/CHANGELOG.md +153 -0
- package/components.js +2 -1
- package/dist/native-document.components.min.js +495 -228
- package/dist/native-document.dev.js +7 -0
- package/dist/native-document.dev.js.map +1 -1
- package/dist/native-document.min.js +1 -1
- package/docs/advanced-components.md +213 -608
- package/docs/anchor.md +173 -312
- package/docs/cache.md +95 -803
- package/docs/cli.md +179 -0
- package/docs/components/accordion.md +172 -0
- package/docs/components/alert.md +99 -0
- package/docs/components/avatar.md +160 -0
- package/docs/components/badge.md +102 -0
- package/docs/components/breadcrumb.md +89 -0
- package/docs/components/button.md +183 -0
- package/docs/components/card.md +69 -0
- package/docs/components/context-menu.md +118 -0
- package/docs/components/data-table.md +345 -0
- package/docs/components/dropdown.md +214 -0
- package/docs/components/form/autocomplete-field.md +81 -0
- package/docs/components/form/checkbox-field.md +41 -0
- package/docs/components/form/checkbox-group-field.md +54 -0
- package/docs/components/form/color-field.md +64 -0
- package/docs/components/form/date-field.md +92 -0
- package/docs/components/form/field-collection.md +63 -0
- package/docs/components/form/file-field.md +203 -0
- package/docs/components/form/form-control.md +87 -0
- package/docs/components/form/image-field.md +90 -0
- package/docs/components/form/index.md +115 -0
- package/docs/components/form/number-field.md +65 -0
- package/docs/components/form/radio-field.md +51 -0
- package/docs/components/form/select-field.md +123 -0
- package/docs/components/form/slider.md +136 -0
- package/docs/components/form/string-field.md +134 -0
- package/docs/components/form/textarea-field.md +65 -0
- package/docs/components/form-fields.md +372 -0
- package/docs/components/getting-started.md +264 -0
- package/docs/components/index.md +337 -0
- package/docs/components/layout.md +279 -0
- package/docs/components/list.md +73 -0
- package/docs/components/menu.md +215 -0
- package/docs/components/modal.md +156 -0
- package/docs/components/pagination.md +95 -0
- package/docs/components/popover.md +131 -0
- package/docs/components/progress.md +111 -0
- package/docs/components/shortcut-manager.md +221 -0
- package/docs/components/simple-table.md +107 -0
- package/docs/components/skeleton.md +155 -0
- package/docs/components/spinner.md +100 -0
- package/docs/components/splitter.md +133 -0
- package/docs/components/stepper.md +163 -0
- package/docs/components/switch.md +113 -0
- package/docs/components/tabs.md +153 -0
- package/docs/components/toast.md +119 -0
- package/docs/components/tooltip.md +151 -0
- package/docs/components/traits.md +261 -0
- package/docs/conditional-rendering.md +170 -588
- package/docs/contributing.md +300 -25
- package/docs/core-concepts.md +205 -374
- package/docs/elements.md +251 -367
- package/docs/extending-native-document-element.md +192 -207
- package/docs/filters.md +153 -1122
- package/docs/getting-started.md +193 -267
- package/docs/i18n.md +241 -0
- package/docs/index.md +76 -0
- package/docs/lifecycle-events.md +143 -75
- package/docs/list-rendering.md +227 -852
- package/docs/memory-management.md +134 -47
- package/docs/native-document-element.md +337 -186
- package/docs/native-fetch.md +99 -630
- package/docs/observable-resource.md +364 -0
- package/docs/observables.md +592 -526
- package/docs/routing.md +244 -653
- package/docs/state-management.md +134 -241
- package/docs/svg-elements.md +231 -0
- package/docs/theming.md +409 -0
- package/docs/tutorials/.gitkeep +0 -0
- package/docs/validation.md +95 -97
- package/docs/vitepress-conventions.md +219 -0
- package/package.json +34 -13
- package/readme.md +269 -89
- package/src/components/card/Card.js +93 -39
- package/src/components/card/index.js +1 -1
- package/src/components/list/HasListItem.js +171 -0
- package/src/components/list/List.js +41 -107
- package/src/components/list/ListDivider.js +39 -0
- package/src/components/list/ListGroup.js +76 -59
- package/src/components/list/ListItem.js +117 -69
- package/src/components/list/index.js +3 -1
- package/src/components/list/types/ListItem.d.ts +45 -34
- package/src/components/spacer/Spacer.js +1 -1
- package/src/core/data/ObservableResource.js +5 -0
- package/src/core/data/observable-helpers/observable.prototypes.js +2 -0
- package/src/ui/components/card/CardRender.js +133 -0
- package/src/ui/components/card/card.css +169 -0
- package/src/ui/components/contextmenu/ContextmenuRender.js +1 -1
- package/src/ui/components/list/ListRender.js +18 -0
- package/src/ui/components/list/divider/ListDividerRender.js +10 -0
- package/src/ui/components/list/divider/list-divider.css +12 -0
- package/src/ui/components/list/group/ListGroupRender.js +61 -0
- package/src/ui/components/list/group/list-group.css +62 -0
- package/src/ui/components/list/item/ListItemRender.js +238 -0
- package/src/ui/components/list/item/list-item.css +191 -0
- package/src/ui/components/list/list.css +24 -0
- package/src/ui/components/spacer/SpacerRender.js +10 -0
- 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
|
+
```
|