domma-js 0.55.0 → 0.57.0
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/assets/types/generated/public/assets/flags/africa.d.ts +6 -0
- package/assets/types/generated/public/assets/flags/americas.d.ts +6 -0
- package/assets/types/generated/public/assets/flags/asia.d.ts +6 -0
- package/assets/types/generated/public/assets/flags/europe.d.ts +9 -0
- package/assets/types/generated/public/assets/flags/index.d.ts +11 -0
- package/assets/types/generated/public/assets/flags/oceania.d.ts +2 -0
- package/assets/types/generated/public/assets/icons/buildings.d.ts +6 -0
- package/assets/types/generated/public/assets/icons/code.d.ts +2 -0
- package/assets/types/generated/public/assets/icons/commerce.d.ts +7 -0
- package/assets/types/generated/public/assets/icons/communication.d.ts +7 -0
- package/assets/types/generated/public/assets/icons/devices.d.ts +6 -0
- package/assets/types/generated/public/assets/icons/emojis.d.ts +6 -0
- package/assets/types/generated/public/assets/icons/files.d.ts +7 -0
- package/assets/types/generated/public/assets/icons/finance.d.ts +6 -0
- package/assets/types/generated/public/assets/icons/forms.d.ts +5 -0
- package/assets/types/generated/public/assets/icons/health.d.ts +6 -0
- package/assets/types/generated/public/assets/icons/index.d.ts +24 -0
- package/assets/types/generated/public/assets/icons/media.d.ts +7 -0
- package/assets/types/generated/public/assets/icons/navigation.d.ts +7 -0
- package/assets/types/generated/public/assets/icons/seasonal.d.ts +6 -0
- package/assets/types/generated/public/assets/icons/social.d.ts +7 -0
- package/assets/types/generated/public/assets/icons/sport.d.ts +6 -0
- package/assets/types/generated/public/assets/icons/status.d.ts +7 -0
- package/assets/types/generated/public/assets/icons/transport.d.ts +7 -0
- package/assets/types/generated/public/assets/icons/ui.d.ts +7 -0
- package/assets/types/generated/public/assets/icons/weather.d.ts +6 -0
- package/assets/types/generated/src/auth.d.ts +424 -0
- package/assets/types/generated/src/avatar.d.ts +270 -0
- package/assets/types/generated/src/binding-source.d.ts +58 -0
- package/assets/types/generated/src/butterfly-drawing.d.ts +2 -0
- package/assets/types/generated/src/component-factory.d.ts +150 -0
- package/assets/types/generated/src/component.d.ts +162 -0
- package/assets/types/generated/src/components/back-to-top.d.ts +150 -0
- package/assets/types/generated/src/components/badge.d.ts +208 -0
- package/assets/types/generated/src/components/card.d.ts +189 -0
- package/assets/types/generated/src/components/command-palette.d.ts +352 -0
- package/assets/types/generated/src/components/dropzone.d.ts +342 -0
- package/assets/types/generated/src/components/focus-trap.d.ts +238 -0
- package/assets/types/generated/src/components/loader.d.ts +133 -0
- package/assets/types/generated/src/components/modal.d.ts +341 -0
- package/assets/types/generated/src/components/range-slider.d.ts +267 -0
- package/assets/types/generated/src/components/shared.d.ts +91 -0
- package/assets/types/generated/src/components/split-pane.d.ts +239 -0
- package/assets/types/generated/src/components/toast.d.ts +284 -0
- package/assets/types/generated/src/components/tooltip.d.ts +200 -0
- package/assets/types/generated/src/components/virtual-list.d.ts +340 -0
- package/assets/types/generated/src/config.d.ts +193 -0
- package/assets/types/generated/src/context-cursor.d.ts +69 -0
- package/assets/types/generated/src/context-menu.d.ts +596 -0
- package/assets/types/generated/src/dates.d.ts +367 -0
- package/assets/types/generated/src/dom.d.ts +1221 -0
- package/assets/types/generated/src/effects.d.ts +1281 -0
- package/assets/types/generated/src/elements.d.ts +4996 -0
- package/assets/types/generated/src/escape.d.ts +5 -0
- package/assets/types/generated/src/flags-bundle.d.ts +4 -0
- package/assets/types/generated/src/flags.d.ts +338 -0
- package/assets/types/generated/src/forms.d.ts +1060 -0
- package/assets/types/generated/src/globals.d.ts +45 -0
- package/assets/types/generated/src/http.d.ts +131 -0
- package/assets/types/generated/src/i18n.d.ts +261 -0
- package/assets/types/generated/src/icons.d.ts +213 -0
- package/assets/types/generated/src/index.d.ts +249 -0
- package/assets/types/generated/src/input-group.d.ts +135 -0
- package/assets/types/generated/src/models.d.ts +968 -0
- package/assets/types/generated/src/popover.d.ts +412 -0
- package/assets/types/generated/src/router.d.ts +344 -0
- package/assets/types/generated/src/safe-url.d.ts +10 -0
- package/assets/types/generated/src/sanitize.d.ts +97 -0
- package/assets/types/generated/src/schema-builder.d.ts +420 -0
- package/assets/types/generated/src/skeleton.d.ts +135 -0
- package/assets/types/generated/src/smooth-caret.d.ts +61 -0
- package/assets/types/generated/src/sortable.d.ts +369 -0
- package/assets/types/generated/src/storage.d.ts +93 -0
- package/assets/types/generated/src/tables.d.ts +901 -0
- package/assets/types/generated/src/theme.d.ts +277 -0
- package/assets/types/generated/src/ticker-tape-drawing.d.ts +2 -0
- package/assets/types/generated/src/treeview.d.ts +504 -0
- package/assets/types/generated/src/utils.d.ts +1667 -0
- package/assets/types/generated/src/web-components/base/domma-element.d.ts +134 -0
- package/assets/types/generated/src/web-components/index.d.ts +14 -0
- package/assets/types/generated/vendor/domma-reactive.d.ts +587 -0
- package/assets/types/index.d.ts +104 -216
- package/package.json +5 -2
- package/public/dist/bundles/domma-complete.css +1084 -14
- package/public/dist/bundles/domma-data-focused.css +1084 -14
- package/public/dist/bundles/domma-essentials.css +1084 -14
- package/public/dist/bundles/domma-full.css +1084 -14
- package/public/dist/bundles/domma-minimal.css +8 -8
- package/public/dist/domma-flags.esm.js +3 -3
- package/public/dist/domma-flags.esm.js.map +1 -1
- package/public/dist/domma-flags.min.js +3 -3
- package/public/dist/domma-flags.min.js.map +1 -1
- package/public/dist/domma-syntax.min.js +3 -3
- package/public/dist/domma.css +3 -3
- package/public/dist/domma.esm.js +5 -5
- package/public/dist/domma.esm.js.map +1 -1
- package/public/dist/domma.min.js +5 -5
- package/public/dist/domma.min.js.map +1 -1
- package/public/dist/elements.css +1073 -3
- package/public/dist/grid.css +3 -3
- package/public/dist/syntax.css +3 -3
- package/public/dist/themes/domma-themes.css +3 -3
- package/templates/kickstart/frontend/types/domma.d.ts +2 -1
- package/assets/types/config.d.ts +0 -136
- package/assets/types/dates.d.ts +0 -209
- package/assets/types/dom.d.ts +0 -448
- package/assets/types/elements.d.ts +0 -682
- package/assets/types/flags.d.ts +0 -130
- package/assets/types/http.d.ts +0 -97
- package/assets/types/icons.d.ts +0 -147
- package/assets/types/models.d.ts +0 -260
- package/assets/types/smooth-caret.d.ts +0 -12
- package/assets/types/storage.d.ts +0 -93
- package/assets/types/tables.d.ts +0 -327
- package/assets/types/theme.d.ts +0 -137
- package/assets/types/utils.d.ts +0 -675
|
@@ -0,0 +1,1060 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field types a form can render. Anything not listed renders as a text input.
|
|
3
|
+
* `boolean`/`checkbox` are one checkbox; `select`/`radio`/`checkbox-group`/`multiselect`/`chooser` take `options`;
|
|
4
|
+
* `slider` is an E.rangeSlider (as is `range` with `formConfig.slider`); `dropzone` is an E.dropzone (value: File[]);
|
|
5
|
+
* `signature` is an E.signature pad (value: base64 PNG).
|
|
6
|
+
* @typedef {'string'|'email'|'password'|'number'|'integer'|'float'|'boolean'|'checkbox'|'date'|'datetime'|'time'|'url'|'tel'|'color'|'range'|'file'|'hidden'|'signature'|'select'|'multiselect'|'textarea'|'radio'|'checkbox-group'|'chooser'|'slider'|'dropzone'|(string & {})} FormFieldType
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* A choice for select / radio / checkbox-group / multiselect / chooser fields. A plain string is both the
|
|
10
|
+
* value and (capitalised) the label. Chooser options also read icon, description, badge, tooltip, etc.
|
|
11
|
+
* @typedef {string|{value: any, label: string, [key: string]: any}} FormOption
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* An input-group addon for `formConfig.prefix` / `formConfig.suffix`: `{icon}` draws a Domma icon,
|
|
15
|
+
* `{text}` escaped text, `{html}` raw HTML (the caller's responsibility); a string is shorthand for `{text}`.
|
|
16
|
+
* @typedef {string|{icon: string}|{text: string|number}|{html: string}} FormAddon
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* How a field is presented (`fieldDef.formConfig`). Slider fields pass range/ticks/tickLabels/labels/format/
|
|
20
|
+
* tooltip/marks/minDistance/orientation/rtl/names/ariaLabels/className to E.rangeSlider; dropzone fields pass
|
|
21
|
+
* accept/multiple/maxFiles/maxSize/minSize/previews/upload/autoUpload/retry/labels/list/className to E.dropzone.
|
|
22
|
+
* @typedef {object} FormFieldConfig
|
|
23
|
+
* @property {string} [placeholder]
|
|
24
|
+
* @property {string} [hint] - Small text beside the label; also the message when `pattern` fails
|
|
25
|
+
* @property {string} [helperText] - Text under the control (HTML)
|
|
26
|
+
* @property {string} [tooltip] - Tooltip on the label (a slider field also passes it to E.rangeSlider)
|
|
27
|
+
* @property {number} [span] - Columns the field spans in a grid layout
|
|
28
|
+
* @property {boolean} [disabled]
|
|
29
|
+
* @property {number} [rows] - textarea rows (default 3)
|
|
30
|
+
* @property {number|'any'} [step] - Used when the field definition has no `step`
|
|
31
|
+
* @property {string} [autocomplete]
|
|
32
|
+
* @property {FormAddon} [prefix]
|
|
33
|
+
* @property {FormAddon} [suffix]
|
|
34
|
+
* @property {boolean} [reveal] - password: show / hide toggle
|
|
35
|
+
* @property {boolean} [clear] - text-like inputs and textareas: a clear button
|
|
36
|
+
* @property {boolean} [stepper] - number / integer / float: - and + buttons
|
|
37
|
+
* @property {boolean|number} [counter] - text-like inputs and textareas: a character counter; true reads `maxLength`
|
|
38
|
+
* @property {Record<string, string>|((value: number, where: 'tick'|'mark'|'tooltip'|'aria') => string)} [labels] - Text for the input extras or the dropzone; a slider's value formatter
|
|
39
|
+
* @property {string|string[]} [accept] - file / dropzone
|
|
40
|
+
* @property {boolean} [multiple] - file / dropzone (a dropzone allows several unless false)
|
|
41
|
+
* @property {boolean} [slider] - Render a `range` field as E.rangeSlider
|
|
42
|
+
* @property {boolean} [range] - slider: two thumbs, value [low, high]
|
|
43
|
+
* @property {import('./components/range-slider.js').RangeSliderOptions['ticks']} [ticks]
|
|
44
|
+
* @property {boolean} [tickLabels]
|
|
45
|
+
* @property {import('./components/range-slider.js').RangeSliderOptions['format']} [format]
|
|
46
|
+
* @property {import('./components/range-slider.js').RangeSliderOptions['marks']} [marks]
|
|
47
|
+
* @property {number} [minDistance]
|
|
48
|
+
* @property {'horizontal'|'vertical'} [orientation]
|
|
49
|
+
* @property {boolean|null} [rtl]
|
|
50
|
+
* @property {[string, string]|null} [names]
|
|
51
|
+
* @property {[string, string]|null} [ariaLabels]
|
|
52
|
+
* @property {string} [className]
|
|
53
|
+
* @property {number|null} [maxFiles]
|
|
54
|
+
* @property {number|null} [maxSize] - Bytes
|
|
55
|
+
* @property {number|null} [minSize] - Bytes
|
|
56
|
+
* @property {boolean} [previews]
|
|
57
|
+
* @property {import('./components/dropzone.js').DropzoneOptions['upload']} [upload]
|
|
58
|
+
* @property {boolean} [autoUpload]
|
|
59
|
+
* @property {number} [retry]
|
|
60
|
+
* @property {boolean|string|HTMLElement} [list]
|
|
61
|
+
*/
|
|
62
|
+
/**
|
|
63
|
+
* One field of a form blueprint. The same object also feeds `M.create` (the form builds its model from the
|
|
64
|
+
* blueprint), so model keys such as `default`, `required` and `validate` apply to both.
|
|
65
|
+
* @typedef {object} FormFieldDefinition
|
|
66
|
+
* @property {FormFieldType} [type] - default 'string'
|
|
67
|
+
* @property {string} [label] - default: the capitalised field name
|
|
68
|
+
* @property {any} [default]
|
|
69
|
+
* @property {boolean} [required]
|
|
70
|
+
* @property {boolean} [readonly] - Renders the control disabled
|
|
71
|
+
* @property {number} [min]
|
|
72
|
+
* @property {number} [max]
|
|
73
|
+
* @property {number|'any'} [step]
|
|
74
|
+
* @property {number} [minLength]
|
|
75
|
+
* @property {number} [maxLength]
|
|
76
|
+
* @property {RegExp} [pattern]
|
|
77
|
+
* @property {(value: any, data: Record<string, any>) => boolean|string} [validate] - true passes; a string (or anything else) fails with that message
|
|
78
|
+
* @property {FormOption[]} [options] - Choices for select / radio / checkbox-group / multiselect / chooser
|
|
79
|
+
* @property {FormFieldConfig} [formConfig]
|
|
80
|
+
* @property {(value: any, row: Record<string, any>, index: number) => string} [tableRender] - `F.crud` table cell renderer
|
|
81
|
+
* @property {'card'|'chip'} [variant] - chooser (default 'card')
|
|
82
|
+
* @property {boolean} [multiple] - chooser: several choices (value is an array)
|
|
83
|
+
* @property {'comfortable'|'compact'} [density] - chooser
|
|
84
|
+
* @property {number} [columns] - chooser (default 3)
|
|
85
|
+
* @property {string} [accent] - chooser: semantic name or CSS colour (default 'primary')
|
|
86
|
+
* @property {'border'|'solid'|'glow'|'overlay'|'underline'} [accentStyle] - chooser
|
|
87
|
+
* @property {boolean} [glow] - chooser
|
|
88
|
+
* @property {string|null} [glowColour] - chooser
|
|
89
|
+
* @property {string} [shadow] - chooser (default 'none')
|
|
90
|
+
* @property {string|null} [shadowColour] - chooser
|
|
91
|
+
*/
|
|
92
|
+
/**
|
|
93
|
+
* A form blueprint: field name -> definition. Fields render in key order unless `options.sections` says otherwise.
|
|
94
|
+
* @typedef {{[field: string]: FormFieldDefinition}} FormBlueprint
|
|
95
|
+
*/
|
|
96
|
+
/**
|
|
97
|
+
* A group of fields (`options.sections`); with a title it is a fieldset with a legend.
|
|
98
|
+
* @typedef {object} FormSection
|
|
99
|
+
* @property {string} [title]
|
|
100
|
+
* @property {string[]} [fields] - Blueprint keys, in order
|
|
101
|
+
* @property {'grid'|'stacked'} [layout]
|
|
102
|
+
* @property {number} [columns] - grid columns (default 2)
|
|
103
|
+
*/
|
|
104
|
+
/**
|
|
105
|
+
* @typedef {object} FormOptions
|
|
106
|
+
* @property {'stacked'|'grid'|'inline'} [layout] - default 'stacked'
|
|
107
|
+
* @property {2|3|number} [columns] - grid layout columns (2 or 3, default 2)
|
|
108
|
+
* @property {'top'|'left'|'floating'} [labelPosition] - default 'top'
|
|
109
|
+
* @property {boolean} [showLabels] - default true
|
|
110
|
+
* @property {boolean} [showHelperText] - default true
|
|
111
|
+
* @property {boolean} [showHints] - default true
|
|
112
|
+
* @property {'blur'|'change'|'submit'} [validationMode] - default 'blur'
|
|
113
|
+
* @property {'domma'|'bootstrap'|'tailwind'} [cssFramework] - default 'domma'
|
|
114
|
+
* @property {string} [className] - default 'domma-form'
|
|
115
|
+
* @property {string} [fieldClassName] - default 'domma-form-field'
|
|
116
|
+
* @property {string} [labelClassName] - default 'form-label'
|
|
117
|
+
* @property {string} [inputClassName] - default 'form-input'
|
|
118
|
+
* @property {string} [errorClassName] - default 'form-error'
|
|
119
|
+
* @property {string} [helperClassName] - default 'form-helper-text'
|
|
120
|
+
* @property {string} [hintClassName] - default 'form-hint'
|
|
121
|
+
* @property {boolean} [cardWrapper] - Wrap the form in a card (default false)
|
|
122
|
+
* @property {FormSection[]} [sections]
|
|
123
|
+
* @property {boolean} [showSubmitButton] - default true
|
|
124
|
+
* @property {string} [submitText] - default 'Submit'
|
|
125
|
+
* @property {string} [resetText] - Adds a reset button with this text
|
|
126
|
+
* @property {'left'|'center'|'right'} [buttonAlignment] - default 'right'
|
|
127
|
+
* @property {(data: Record<string, any>, form: FormInstance) => void} [onSubmit] - A valid submit
|
|
128
|
+
* @property {(errors: Record<string, string>, form: FormInstance) => void} [onValidationError] - An invalid submit
|
|
129
|
+
* @property {string} [persist] - Passed to the model: a storage key to keep the values under
|
|
130
|
+
* @property {boolean} [autoSave] - Passed to the model
|
|
131
|
+
*/
|
|
132
|
+
/**
|
|
133
|
+
* What `handleSubmit()` returns.
|
|
134
|
+
* @typedef {object} FormSubmitResult
|
|
135
|
+
* @property {boolean} isValid
|
|
136
|
+
* @property {Record<string, any>} data
|
|
137
|
+
* @property {Record<string, string>} errors - field name -> message
|
|
138
|
+
*/
|
|
139
|
+
/**
|
|
140
|
+
* One step of `F.wizard`.
|
|
141
|
+
* @typedef {object} FormWizardStep
|
|
142
|
+
* @property {string} [title] - default 'Step <n>'
|
|
143
|
+
* @property {string} [description]
|
|
144
|
+
* @property {FormBlueprint} fields - The step's blueprint
|
|
145
|
+
* @property {'stacked'|'grid'|'inline'} [layout]
|
|
146
|
+
*/
|
|
147
|
+
/**
|
|
148
|
+
* `F.wizard` options; the rest are FormOptions applied to every step.
|
|
149
|
+
* @typedef {FormOptions & {
|
|
150
|
+
* schema: {steps: FormWizardStep[]},
|
|
151
|
+
* data?: Record<string, any>,
|
|
152
|
+
* prevText?: string,
|
|
153
|
+
* nextText?: string,
|
|
154
|
+
* finishText?: string,
|
|
155
|
+
* onStepChange?: (stepIndex: number, data: Record<string, any>) => void,
|
|
156
|
+
* onValidation?: (isValid: boolean, errors: Record<string, string>, stepIndex: number) => void,
|
|
157
|
+
* onSubmit?: (data: Record<string, any>, form: FormInstance) => void|Promise<void>,
|
|
158
|
+
* onError?: (error: any, data: Record<string, any>, form: FormInstance) => void
|
|
159
|
+
* }} FormWizardOptions
|
|
160
|
+
*/
|
|
161
|
+
/**
|
|
162
|
+
* The control object `F.wizard` returns.
|
|
163
|
+
* @typedef {object} FormWizard
|
|
164
|
+
* @property {() => void} nextStep
|
|
165
|
+
* @property {() => void} prevStep
|
|
166
|
+
* @property {(stepIndex: number) => void} goToStep
|
|
167
|
+
* @property {() => number} getCurrentStep - 0-based
|
|
168
|
+
* @property {() => Record<string, any>} getStepData - The values gathered so far (a copy)
|
|
169
|
+
* @property {(data: Record<string, any>) => void} setStepData - Merge values in and re-render the step
|
|
170
|
+
* @property {() => boolean} validate - Validate the current step
|
|
171
|
+
* @property {() => HTMLElement|null} getElement
|
|
172
|
+
* @property {() => void} destroy - Tear down the current step's controls and remove the wizard
|
|
173
|
+
*/
|
|
174
|
+
/**
|
|
175
|
+
* `F.modal` options; the rest are FormOptions (`onSubmit` and `showSubmitButton` are set by the modal).
|
|
176
|
+
* @typedef {FormOptions & {
|
|
177
|
+
* title?: string,
|
|
178
|
+
* saveText?: string,
|
|
179
|
+
* closeOnSave?: boolean,
|
|
180
|
+
* size?: string,
|
|
181
|
+
* onSave?: (data: Record<string, any>, form: FormInstance) => void|Promise<void>,
|
|
182
|
+
* onError?: (error: any, data: Record<string, any>, form: FormInstance) => void
|
|
183
|
+
* }} FormModalOptions
|
|
184
|
+
*/
|
|
185
|
+
/**
|
|
186
|
+
* The control object `F.modal` returns. `close()` removes the modal from the page.
|
|
187
|
+
* @typedef {object} FormModal
|
|
188
|
+
* @property {() => void} open
|
|
189
|
+
* @property {() => void} close
|
|
190
|
+
* @property {() => boolean} isOpen
|
|
191
|
+
*/
|
|
192
|
+
/**
|
|
193
|
+
* `F.crud` configuration.
|
|
194
|
+
* @typedef {object} FormCrudConfig
|
|
195
|
+
* @property {FormBlueprint} schema
|
|
196
|
+
* @property {string} endpoint - REST endpoint (GET list, POST create, PUT/DELETE `<endpoint>/<id>`); responses are `{success, data, message}`
|
|
197
|
+
* @property {string|HTMLElement} [tableSelector] - Where the table goes
|
|
198
|
+
* @property {string} [title] - default 'Manage Items'
|
|
199
|
+
* @property {string} [primaryKey] - default 'id'
|
|
200
|
+
* @property {string} [displayField] - default 'name'
|
|
201
|
+
* @property {Record<string, string>} [headers]
|
|
202
|
+
* @property {(error: any) => void} [onError]
|
|
203
|
+
* @property {(message: string) => void} [onSuccess]
|
|
204
|
+
*/
|
|
205
|
+
/**
|
|
206
|
+
* The object `F.crud` returns. Call `init()` to load the data and build the table.
|
|
207
|
+
* @typedef {object} FormCrud
|
|
208
|
+
* @property {() => Promise<void>} init
|
|
209
|
+
* @property {() => Promise<void>} loadData
|
|
210
|
+
* @property {() => void} createTable
|
|
211
|
+
* @property {() => void} initializeTableIcons
|
|
212
|
+
* @property {() => void} bindEvents
|
|
213
|
+
* @property {() => Promise<void>} create - Open the create modal
|
|
214
|
+
* @property {(id: string|number) => Promise<void>} edit - Open the edit modal for an item
|
|
215
|
+
* @property {(id: string|number) => Promise<void>} delete - Confirm, then delete an item
|
|
216
|
+
* @property {() => Promise<void>} refresh
|
|
217
|
+
* @property {() => Record<string, any>[]} getData
|
|
218
|
+
* @property {() => import('./tables.js').TableInstance|null} getTable
|
|
219
|
+
* @property {(item: Record<string, any>) => void} addItem
|
|
220
|
+
* @property {(id: string|number, updates: Record<string, any>) => void} updateItem
|
|
221
|
+
* @property {(id: string|number) => void} removeItem
|
|
222
|
+
*/
|
|
223
|
+
/** @typedef {Forma} FormInstance */
|
|
224
|
+
/**
|
|
225
|
+
* Forma Class - Generates forms from Model schemas
|
|
226
|
+
*/
|
|
227
|
+
export class Forma {
|
|
228
|
+
static defaults: {
|
|
229
|
+
layout: string;
|
|
230
|
+
columns: number;
|
|
231
|
+
labelPosition: string;
|
|
232
|
+
showLabels: boolean;
|
|
233
|
+
showHelperText: boolean;
|
|
234
|
+
showHints: boolean;
|
|
235
|
+
validationMode: string;
|
|
236
|
+
cssFramework: string;
|
|
237
|
+
className: string;
|
|
238
|
+
fieldClassName: string;
|
|
239
|
+
labelClassName: string;
|
|
240
|
+
inputClassName: string;
|
|
241
|
+
errorClassName: string;
|
|
242
|
+
helperClassName: string;
|
|
243
|
+
hintClassName: string;
|
|
244
|
+
cardWrapper: boolean;
|
|
245
|
+
};
|
|
246
|
+
static inputTypes: {
|
|
247
|
+
string: string;
|
|
248
|
+
email: string;
|
|
249
|
+
password: string;
|
|
250
|
+
number: string;
|
|
251
|
+
integer: string;
|
|
252
|
+
float: string;
|
|
253
|
+
boolean: string;
|
|
254
|
+
date: string;
|
|
255
|
+
datetime: string;
|
|
256
|
+
time: string;
|
|
257
|
+
url: string;
|
|
258
|
+
tel: string;
|
|
259
|
+
color: string;
|
|
260
|
+
range: string;
|
|
261
|
+
file: string;
|
|
262
|
+
hidden: string;
|
|
263
|
+
signature: string;
|
|
264
|
+
};
|
|
265
|
+
/**
|
|
266
|
+
* @param {FormBlueprint} schema
|
|
267
|
+
* @param {Record<string, any>} [data] - Initial values
|
|
268
|
+
* @param {FormOptions} [options]
|
|
269
|
+
*/
|
|
270
|
+
constructor(schema: FormBlueprint, data?: Record<string, any>, options?: FormOptions);
|
|
271
|
+
/** @type {FormBlueprint} */
|
|
272
|
+
schema: FormBlueprint;
|
|
273
|
+
/** @type {Record<string, any>} */
|
|
274
|
+
data: Record<string, any>;
|
|
275
|
+
/** @private */
|
|
276
|
+
private _startData;
|
|
277
|
+
/** @type {FormOptions} */
|
|
278
|
+
options: FormOptions;
|
|
279
|
+
/** @type {import('./models.js').Model|null} The model built from the blueprint */
|
|
280
|
+
model: import("./models.js").Model | null;
|
|
281
|
+
/** @type {Record<string, string>} field name -> error message */
|
|
282
|
+
errors: Record<string, string>;
|
|
283
|
+
/** @type {Set<string>} Fields that have lost focus at least once */
|
|
284
|
+
touched: Set<string>;
|
|
285
|
+
/** @type {typeof utils} */
|
|
286
|
+
utils: typeof utils;
|
|
287
|
+
/** @type {typeof models} */
|
|
288
|
+
models: typeof models;
|
|
289
|
+
/**
|
|
290
|
+
* Generate form HTML
|
|
291
|
+
* @returns {string}
|
|
292
|
+
*/
|
|
293
|
+
render(): string;
|
|
294
|
+
/**
|
|
295
|
+
* Render form into DOM element
|
|
296
|
+
* @param {string|HTMLElement} selector - Container (its content is replaced)
|
|
297
|
+
* @returns {HTMLElement} The container
|
|
298
|
+
*/
|
|
299
|
+
renderTo(selector: string | HTMLElement): HTMLElement;
|
|
300
|
+
/** @type {HTMLFormElement|null} The rendered <form> */
|
|
301
|
+
formElement: HTMLFormElement | null;
|
|
302
|
+
/**
|
|
303
|
+
* Build the complete form structure
|
|
304
|
+
* @private
|
|
305
|
+
*/
|
|
306
|
+
private _buildForm;
|
|
307
|
+
/**
|
|
308
|
+
* Build a form section
|
|
309
|
+
* @private
|
|
310
|
+
*/
|
|
311
|
+
private _buildSection;
|
|
312
|
+
/**
|
|
313
|
+
* Build individual field
|
|
314
|
+
* @private
|
|
315
|
+
*/
|
|
316
|
+
private _buildField;
|
|
317
|
+
/**
|
|
318
|
+
* Builds an HTML input element based on the provided field definition and options.
|
|
319
|
+
*
|
|
320
|
+
* @param {string} fieldName - The name of the field, used as the 'name' attribute for the input.
|
|
321
|
+
* @param {Object} fieldDef - The field definition containing configuration details such as min, max, pattern, etc.
|
|
322
|
+
* @param {Object} inputOptions - Options to customize the input element including type, value, required, disabled, placeholder, etc.
|
|
323
|
+
*
|
|
324
|
+
* @return {string} A string representing the HTML input element with appropriate attributes and content based on the specified type.
|
|
325
|
+
* @private
|
|
326
|
+
*/
|
|
327
|
+
private _buildInput;
|
|
328
|
+
/**
|
|
329
|
+
* The interactive extras a field asks for through formConfig, reduced to
|
|
330
|
+
* those its type can take, or null:
|
|
331
|
+
* reveal: true password - show / hide toggle
|
|
332
|
+
* clear: true single-line text-like inputs and textareas
|
|
333
|
+
* stepper: true number / integer / float - the - and + buttons
|
|
334
|
+
* counter: true | n text-like inputs and textareas; true reads the
|
|
335
|
+
* field's maxLength
|
|
336
|
+
*
|
|
337
|
+
* @param {string} type
|
|
338
|
+
* @param {Object} fieldDef
|
|
339
|
+
* @return {Object|null}
|
|
340
|
+
* @private
|
|
341
|
+
*/
|
|
342
|
+
private _inputExtras;
|
|
343
|
+
/**
|
|
344
|
+
* Joins formConfig.prefix / formConfig.suffix addons to a control's markup.
|
|
345
|
+
* Used for single-line inputs, selects and textareas; a control with neither
|
|
346
|
+
* is returned untouched.
|
|
347
|
+
*
|
|
348
|
+
* @param {string} controlHtml
|
|
349
|
+
* @param {Object} formConfig
|
|
350
|
+
* @return {string}
|
|
351
|
+
* @private
|
|
352
|
+
*/
|
|
353
|
+
private _wrapAddons;
|
|
354
|
+
/**
|
|
355
|
+
* Builds an input-group addon (prefix or suffix) for decoration inside a form input.
|
|
356
|
+
*
|
|
357
|
+
* Accepts a slot descriptor object from formConfig.prefix / formConfig.suffix:
|
|
358
|
+
* { icon: 'search' } → renders a Domma icon
|
|
359
|
+
* { text: '$' } → renders escaped plain text (currency, units, etc.)
|
|
360
|
+
* { html: '<kbd>K</kbd>' } → renders raw HTML (caller takes responsibility)
|
|
361
|
+
* '£' → shorthand for { text: '£' }
|
|
362
|
+
*
|
|
363
|
+
* @param {Object|undefined} slot The prefix/suffix descriptor, or falsy to skip.
|
|
364
|
+
* @param {'left'|'right'} side Which side the addon renders on.
|
|
365
|
+
* @return {string} The addon HTML, or '' if no addon should be rendered.
|
|
366
|
+
* @private
|
|
367
|
+
*/
|
|
368
|
+
private _buildAddon;
|
|
369
|
+
/**
|
|
370
|
+
* Constructs the HTML select element based on field definition and current value.
|
|
371
|
+
*
|
|
372
|
+
* @param fieldName
|
|
373
|
+
* @param {Object} fieldDef - The field definition containing options, required status, and other attributes.
|
|
374
|
+
* @param attrs
|
|
375
|
+
* @param currentValue
|
|
376
|
+
* @return {string} A string representing the generated HTML `<select>` element with appropriate options.
|
|
377
|
+
* @private
|
|
378
|
+
*/
|
|
379
|
+
private _buildSelect;
|
|
380
|
+
/**
|
|
381
|
+
* Constructs the HTML structure for a radio group based on provided field definitions and attributes.
|
|
382
|
+
*
|
|
383
|
+
* @return {string} A string containing the generated HTML markup for the radio group with proper styling classes.
|
|
384
|
+
* @param fieldName
|
|
385
|
+
* @param fieldDef
|
|
386
|
+
* @param attrs
|
|
387
|
+
* @param currentValue
|
|
388
|
+
* @private
|
|
389
|
+
*/
|
|
390
|
+
private _buildRadioGroup;
|
|
391
|
+
/**
|
|
392
|
+
* Build checkbox group
|
|
393
|
+
* @private
|
|
394
|
+
*/
|
|
395
|
+
private _buildCheckboxGroup;
|
|
396
|
+
/**
|
|
397
|
+
* Build a placeholder element for a chooser field. The element is
|
|
398
|
+
* hydrated post-render by `_initChooserFields`, which instantiates
|
|
399
|
+
* `Domma.elements.chooser()` inside it. The configuration is round-tripped
|
|
400
|
+
* via a dataset attribute (JSON, attribute-quoted) so the form pipeline
|
|
401
|
+
* stays string-based until hydration time.
|
|
402
|
+
*
|
|
403
|
+
* @param {string} fieldName blueprint key
|
|
404
|
+
* @param {Object} fieldDef blueprint definition
|
|
405
|
+
* @param {Object} attrs attribute object built by _buildField
|
|
406
|
+
* @param {*} currentValue current model value (string or array)
|
|
407
|
+
* @returns {string} HTML string
|
|
408
|
+
* @private
|
|
409
|
+
*/
|
|
410
|
+
private _buildChooser;
|
|
411
|
+
/**
|
|
412
|
+
* Bind events to form
|
|
413
|
+
* @param {HTMLElement} formElement
|
|
414
|
+
* @returns {void}
|
|
415
|
+
*/
|
|
416
|
+
_bindEvents(formElement: HTMLElement): void;
|
|
417
|
+
/**
|
|
418
|
+
* The current value of a field from the model, the data, or its default.
|
|
419
|
+
* @private
|
|
420
|
+
*/
|
|
421
|
+
private _initialValue;
|
|
422
|
+
/** Store a value a component reported, as the chooser fields do. @private */
|
|
423
|
+
private _storeFieldValue;
|
|
424
|
+
/**
|
|
425
|
+
* Turn every `[data-slider-field]` input into an E.rangeSlider. Slider options come from
|
|
426
|
+
* the field definition (min / max / step) and formConfig (range, ticks, tickLabels,
|
|
427
|
+
* labels, tooltip, marks, minDistance, orientation, rtl, names). With `range: true` the
|
|
428
|
+
* value is [low, high].
|
|
429
|
+
* @param {HTMLElement} formElement
|
|
430
|
+
* @private
|
|
431
|
+
*/
|
|
432
|
+
private _initSliderFields;
|
|
433
|
+
/**
|
|
434
|
+
* Turn every `[data-dropzone-field]` placeholder into an E.dropzone over its file input.
|
|
435
|
+
* formConfig passes accept, multiple, maxFiles, maxSize, minSize, previews, upload,
|
|
436
|
+
* autoUpload, retry and labels through. The value is the array of File objects.
|
|
437
|
+
* @param {HTMLElement} formElement
|
|
438
|
+
* @private
|
|
439
|
+
*/
|
|
440
|
+
private _initDropzoneFields;
|
|
441
|
+
/** @private */
|
|
442
|
+
private _destroyFieldControls;
|
|
443
|
+
/**
|
|
444
|
+
* Bind E.inputGroup to every control that carries `data-input-extras`,
|
|
445
|
+
* reusing the addon group _wrapAddons may already have written. Instances
|
|
446
|
+
* live on `this._inputGroups` keyed by field name; a re-render or
|
|
447
|
+
* destroy() tears the previous ones down.
|
|
448
|
+
*
|
|
449
|
+
* @param {HTMLElement} formElement
|
|
450
|
+
* @private
|
|
451
|
+
*/
|
|
452
|
+
private _initInputExtras;
|
|
453
|
+
/** @private */
|
|
454
|
+
private _destroyInputExtras;
|
|
455
|
+
_inputGroups: {};
|
|
456
|
+
/**
|
|
457
|
+
* Put every field back to the value the form started with (its data, else the schema
|
|
458
|
+
* default): the model, the native inputs, and the slider / dropzone / chooser controls.
|
|
459
|
+
* A `[data-action="reset"]` button inside the form calls it.
|
|
460
|
+
* @returns {this}
|
|
461
|
+
*/
|
|
462
|
+
reset(): this;
|
|
463
|
+
/**
|
|
464
|
+
* Remove the listeners and controls the form's input extras added.
|
|
465
|
+
* @returns {void}
|
|
466
|
+
*/
|
|
467
|
+
destroy(): void;
|
|
468
|
+
/**
|
|
469
|
+
* Locate every `[data-chooser-field]` placeholder in the rendered form
|
|
470
|
+
* and instantiate `Domma.elements.chooser()` inside it. Stores each
|
|
471
|
+
* control instance on `this._choosers` keyed by field name so
|
|
472
|
+
* `_getFieldValueByName` and `validateField` can read its current value.
|
|
473
|
+
*
|
|
474
|
+
* @param {HTMLElement} formElement
|
|
475
|
+
* @private
|
|
476
|
+
*/
|
|
477
|
+
private _initChooserFields;
|
|
478
|
+
_choosers: {};
|
|
479
|
+
/**
|
|
480
|
+
* Initialise any signature fields inside a rendered form.
|
|
481
|
+
* @param {HTMLElement} formElement
|
|
482
|
+
* @private
|
|
483
|
+
*/
|
|
484
|
+
private _initSignatureFields;
|
|
485
|
+
/**
|
|
486
|
+
* Initialize tooltips on form labels
|
|
487
|
+
* @private
|
|
488
|
+
*/
|
|
489
|
+
private _initTooltips;
|
|
490
|
+
/**
|
|
491
|
+
* Get form data
|
|
492
|
+
* @returns {Record<string, any>}
|
|
493
|
+
*/
|
|
494
|
+
getData(): Record<string, any>;
|
|
495
|
+
/**
|
|
496
|
+
* Set form data (merged into the current values)
|
|
497
|
+
* @param {Record<string, any>} data
|
|
498
|
+
* @returns {void}
|
|
499
|
+
*/
|
|
500
|
+
setData(data: Record<string, any>): void;
|
|
501
|
+
/**
|
|
502
|
+
* Validate entire form
|
|
503
|
+
* @returns {boolean}
|
|
504
|
+
*/
|
|
505
|
+
validate(): boolean;
|
|
506
|
+
/**
|
|
507
|
+
* Validate single field
|
|
508
|
+
* @param {string} fieldName
|
|
509
|
+
* @returns {boolean}
|
|
510
|
+
*/
|
|
511
|
+
validateField(fieldName: string): boolean;
|
|
512
|
+
/**
|
|
513
|
+
* Set field error
|
|
514
|
+
* @param {string} fieldName
|
|
515
|
+
* @param {string} message
|
|
516
|
+
* @returns {void}
|
|
517
|
+
*/
|
|
518
|
+
setFieldError(fieldName: string, message: string): void;
|
|
519
|
+
/**
|
|
520
|
+
* Clear field error
|
|
521
|
+
* @param {string} fieldName
|
|
522
|
+
* @returns {void}
|
|
523
|
+
*/
|
|
524
|
+
clearFieldError(fieldName: string): void;
|
|
525
|
+
/**
|
|
526
|
+
* Handle form submission: validate, then call `onSubmit` or `onValidationError`.
|
|
527
|
+
* @returns {FormSubmitResult}
|
|
528
|
+
*/
|
|
529
|
+
handleSubmit(): FormSubmitResult;
|
|
530
|
+
/**
|
|
531
|
+
* Get value from form field element
|
|
532
|
+
* @private
|
|
533
|
+
*/
|
|
534
|
+
private _getFieldValue;
|
|
535
|
+
/**
|
|
536
|
+
* Get field value by field name
|
|
537
|
+
* @param {string} fieldName
|
|
538
|
+
* @returns {any}
|
|
539
|
+
*/
|
|
540
|
+
_getFieldValueByName(fieldName: string): any;
|
|
541
|
+
/**
|
|
542
|
+
* Validate field value against schema definition
|
|
543
|
+
* @private
|
|
544
|
+
*/
|
|
545
|
+
private _validateFieldValue;
|
|
546
|
+
}
|
|
547
|
+
export namespace forms {
|
|
548
|
+
/**
|
|
549
|
+
* Create a new form builder instance (call `renderTo()` to put it on the page)
|
|
550
|
+
* @param {FormBlueprint} schema
|
|
551
|
+
* @param {Record<string, any>} [data] - Initial values
|
|
552
|
+
* @param {FormOptions} [options]
|
|
553
|
+
* @returns {FormInstance}
|
|
554
|
+
*/
|
|
555
|
+
function create(schema: FormBlueprint, data?: Record<string, any>, options?: FormOptions): FormInstance;
|
|
556
|
+
/**
|
|
557
|
+
* Render form into element
|
|
558
|
+
* @param {string|HTMLElement} selector - Container (its content is replaced)
|
|
559
|
+
* @param {FormBlueprint} schema
|
|
560
|
+
* @param {Record<string, any>} [data] - Initial values
|
|
561
|
+
* @param {FormOptions} [options]
|
|
562
|
+
* @returns {HTMLElement} The container
|
|
563
|
+
*/
|
|
564
|
+
function render(selector: string | HTMLElement, schema: FormBlueprint, data?: Record<string, any>, options?: FormOptions): HTMLElement;
|
|
565
|
+
/**
|
|
566
|
+
* Create wizard form (multi-step form)
|
|
567
|
+
* @param {string|HTMLElement} selector - Container
|
|
568
|
+
* @param {FormWizardOptions} options
|
|
569
|
+
* @returns {FormWizard}
|
|
570
|
+
*/
|
|
571
|
+
function wizard(selector: string | HTMLElement, options?: FormWizardOptions): FormWizard;
|
|
572
|
+
/**
|
|
573
|
+
* Create modal form (integration with existing modal system). The modal is added to the page
|
|
574
|
+
* at once, hidden; call `open()`.
|
|
575
|
+
* @param {FormBlueprint} schema
|
|
576
|
+
* @param {Record<string, any>} [data] - Initial values
|
|
577
|
+
* @param {FormModalOptions} [options]
|
|
578
|
+
* @returns {FormModal}
|
|
579
|
+
*/
|
|
580
|
+
function modal(schema: FormBlueprint, data?: Record<string, any>, options?: FormModalOptions): FormModal;
|
|
581
|
+
/**
|
|
582
|
+
* CRUD Helper - Complete Create, Read, Update, Delete functionality
|
|
583
|
+
* @param {FormCrudConfig} config
|
|
584
|
+
* @returns {FormCrud}
|
|
585
|
+
*/
|
|
586
|
+
function crud(config: FormCrudConfig): FormCrud;
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Field types a form can render. Anything not listed renders as a text input.
|
|
590
|
+
* `boolean`/`checkbox` are one checkbox; `select`/`radio`/`checkbox-group`/`multiselect`/`chooser` take `options`;
|
|
591
|
+
* `slider` is an E.rangeSlider (as is `range` with `formConfig.slider`); `dropzone` is an E.dropzone (value: File[]);
|
|
592
|
+
* `signature` is an E.signature pad (value: base64 PNG).
|
|
593
|
+
*/
|
|
594
|
+
export type FormFieldType = "string" | "email" | "password" | "number" | "integer" | "float" | "boolean" | "checkbox" | "date" | "datetime" | "time" | "url" | "tel" | "color" | "range" | "file" | "hidden" | "signature" | "select" | "multiselect" | "textarea" | "radio" | "checkbox-group" | "chooser" | "slider" | "dropzone" | (string & {});
|
|
595
|
+
/**
|
|
596
|
+
* A choice for select / radio / checkbox-group / multiselect / chooser fields. A plain string is both the
|
|
597
|
+
* value and (capitalised) the label. Chooser options also read icon, description, badge, tooltip, etc.
|
|
598
|
+
*/
|
|
599
|
+
export type FormOption = string | {
|
|
600
|
+
value: any;
|
|
601
|
+
label: string;
|
|
602
|
+
[key: string]: any;
|
|
603
|
+
};
|
|
604
|
+
/**
|
|
605
|
+
* An input-group addon for `formConfig.prefix` / `formConfig.suffix`: `{icon}` draws a Domma icon,
|
|
606
|
+
* `{text}` escaped text, `{html}` raw HTML (the caller's responsibility); a string is shorthand for `{text}`.
|
|
607
|
+
*/
|
|
608
|
+
export type FormAddon = string | {
|
|
609
|
+
icon: string;
|
|
610
|
+
} | {
|
|
611
|
+
text: string | number;
|
|
612
|
+
} | {
|
|
613
|
+
html: string;
|
|
614
|
+
};
|
|
615
|
+
/**
|
|
616
|
+
* How a field is presented (`fieldDef.formConfig`). Slider fields pass range/ticks/tickLabels/labels/format/
|
|
617
|
+
* tooltip/marks/minDistance/orientation/rtl/names/ariaLabels/className to E.rangeSlider; dropzone fields pass
|
|
618
|
+
* accept/multiple/maxFiles/maxSize/minSize/previews/upload/autoUpload/retry/labels/list/className to E.dropzone.
|
|
619
|
+
*/
|
|
620
|
+
export type FormFieldConfig = {
|
|
621
|
+
placeholder?: string;
|
|
622
|
+
/**
|
|
623
|
+
* - Small text beside the label; also the message when `pattern` fails
|
|
624
|
+
*/
|
|
625
|
+
hint?: string;
|
|
626
|
+
/**
|
|
627
|
+
* - Text under the control (HTML)
|
|
628
|
+
*/
|
|
629
|
+
helperText?: string;
|
|
630
|
+
/**
|
|
631
|
+
* - Tooltip on the label (a slider field also passes it to E.rangeSlider)
|
|
632
|
+
*/
|
|
633
|
+
tooltip?: string;
|
|
634
|
+
/**
|
|
635
|
+
* - Columns the field spans in a grid layout
|
|
636
|
+
*/
|
|
637
|
+
span?: number;
|
|
638
|
+
disabled?: boolean;
|
|
639
|
+
/**
|
|
640
|
+
* - textarea rows (default 3)
|
|
641
|
+
*/
|
|
642
|
+
rows?: number;
|
|
643
|
+
/**
|
|
644
|
+
* - Used when the field definition has no `step`
|
|
645
|
+
*/
|
|
646
|
+
step?: number | "any";
|
|
647
|
+
autocomplete?: string;
|
|
648
|
+
prefix?: FormAddon;
|
|
649
|
+
suffix?: FormAddon;
|
|
650
|
+
/**
|
|
651
|
+
* - password: show / hide toggle
|
|
652
|
+
*/
|
|
653
|
+
reveal?: boolean;
|
|
654
|
+
/**
|
|
655
|
+
* - text-like inputs and textareas: a clear button
|
|
656
|
+
*/
|
|
657
|
+
clear?: boolean;
|
|
658
|
+
/**
|
|
659
|
+
* - number / integer / float: - and + buttons
|
|
660
|
+
*/
|
|
661
|
+
stepper?: boolean;
|
|
662
|
+
/**
|
|
663
|
+
* - text-like inputs and textareas: a character counter; true reads `maxLength`
|
|
664
|
+
*/
|
|
665
|
+
counter?: boolean | number;
|
|
666
|
+
/**
|
|
667
|
+
* - Text for the input extras or the dropzone; a slider's value formatter
|
|
668
|
+
*/
|
|
669
|
+
labels?: Record<string, string> | ((value: number, where: "tick" | "mark" | "tooltip" | "aria") => string);
|
|
670
|
+
/**
|
|
671
|
+
* - file / dropzone
|
|
672
|
+
*/
|
|
673
|
+
accept?: string | string[];
|
|
674
|
+
/**
|
|
675
|
+
* - file / dropzone (a dropzone allows several unless false)
|
|
676
|
+
*/
|
|
677
|
+
multiple?: boolean;
|
|
678
|
+
/**
|
|
679
|
+
* - Render a `range` field as E.rangeSlider
|
|
680
|
+
*/
|
|
681
|
+
slider?: boolean;
|
|
682
|
+
/**
|
|
683
|
+
* - slider: two thumbs, value [low, high]
|
|
684
|
+
*/
|
|
685
|
+
range?: boolean;
|
|
686
|
+
ticks?: import("./components/range-slider.js").RangeSliderOptions["ticks"];
|
|
687
|
+
tickLabels?: boolean;
|
|
688
|
+
format?: import("./components/range-slider.js").RangeSliderOptions["format"];
|
|
689
|
+
marks?: import("./components/range-slider.js").RangeSliderOptions["marks"];
|
|
690
|
+
minDistance?: number;
|
|
691
|
+
orientation?: "horizontal" | "vertical";
|
|
692
|
+
rtl?: boolean | null;
|
|
693
|
+
names?: [string, string] | null;
|
|
694
|
+
ariaLabels?: [string, string] | null;
|
|
695
|
+
className?: string;
|
|
696
|
+
maxFiles?: number | null;
|
|
697
|
+
/**
|
|
698
|
+
* - Bytes
|
|
699
|
+
*/
|
|
700
|
+
maxSize?: number | null;
|
|
701
|
+
/**
|
|
702
|
+
* - Bytes
|
|
703
|
+
*/
|
|
704
|
+
minSize?: number | null;
|
|
705
|
+
previews?: boolean;
|
|
706
|
+
upload?: import("./components/dropzone.js").DropzoneOptions["upload"];
|
|
707
|
+
autoUpload?: boolean;
|
|
708
|
+
retry?: number;
|
|
709
|
+
list?: boolean | string | HTMLElement;
|
|
710
|
+
};
|
|
711
|
+
/**
|
|
712
|
+
* One field of a form blueprint. The same object also feeds `M.create` (the form builds its model from the
|
|
713
|
+
* blueprint), so model keys such as `default`, `required` and `validate` apply to both.
|
|
714
|
+
*/
|
|
715
|
+
export type FormFieldDefinition = {
|
|
716
|
+
/**
|
|
717
|
+
* - default 'string'
|
|
718
|
+
*/
|
|
719
|
+
type?: FormFieldType;
|
|
720
|
+
/**
|
|
721
|
+
* - default: the capitalised field name
|
|
722
|
+
*/
|
|
723
|
+
label?: string;
|
|
724
|
+
default?: any;
|
|
725
|
+
required?: boolean;
|
|
726
|
+
/**
|
|
727
|
+
* - Renders the control disabled
|
|
728
|
+
*/
|
|
729
|
+
readonly?: boolean;
|
|
730
|
+
min?: number;
|
|
731
|
+
max?: number;
|
|
732
|
+
step?: number | "any";
|
|
733
|
+
minLength?: number;
|
|
734
|
+
maxLength?: number;
|
|
735
|
+
pattern?: RegExp;
|
|
736
|
+
/**
|
|
737
|
+
* - true passes; a string (or anything else) fails with that message
|
|
738
|
+
*/
|
|
739
|
+
validate?: (value: any, data: Record<string, any>) => boolean | string;
|
|
740
|
+
/**
|
|
741
|
+
* - Choices for select / radio / checkbox-group / multiselect / chooser
|
|
742
|
+
*/
|
|
743
|
+
options?: FormOption[];
|
|
744
|
+
formConfig?: FormFieldConfig;
|
|
745
|
+
/**
|
|
746
|
+
* - `F.crud` table cell renderer
|
|
747
|
+
*/
|
|
748
|
+
tableRender?: (value: any, row: Record<string, any>, index: number) => string;
|
|
749
|
+
/**
|
|
750
|
+
* - chooser (default 'card')
|
|
751
|
+
*/
|
|
752
|
+
variant?: "card" | "chip";
|
|
753
|
+
/**
|
|
754
|
+
* - chooser: several choices (value is an array)
|
|
755
|
+
*/
|
|
756
|
+
multiple?: boolean;
|
|
757
|
+
/**
|
|
758
|
+
* - chooser
|
|
759
|
+
*/
|
|
760
|
+
density?: "comfortable" | "compact";
|
|
761
|
+
/**
|
|
762
|
+
* - chooser (default 3)
|
|
763
|
+
*/
|
|
764
|
+
columns?: number;
|
|
765
|
+
/**
|
|
766
|
+
* - chooser: semantic name or CSS colour (default 'primary')
|
|
767
|
+
*/
|
|
768
|
+
accent?: string;
|
|
769
|
+
/**
|
|
770
|
+
* - chooser
|
|
771
|
+
*/
|
|
772
|
+
accentStyle?: "border" | "solid" | "glow" | "overlay" | "underline";
|
|
773
|
+
/**
|
|
774
|
+
* - chooser
|
|
775
|
+
*/
|
|
776
|
+
glow?: boolean;
|
|
777
|
+
/**
|
|
778
|
+
* - chooser
|
|
779
|
+
*/
|
|
780
|
+
glowColour?: string | null;
|
|
781
|
+
/**
|
|
782
|
+
* - chooser (default 'none')
|
|
783
|
+
*/
|
|
784
|
+
shadow?: string;
|
|
785
|
+
/**
|
|
786
|
+
* - chooser
|
|
787
|
+
*/
|
|
788
|
+
shadowColour?: string | null;
|
|
789
|
+
};
|
|
790
|
+
/**
|
|
791
|
+
* A form blueprint: field name -> definition. Fields render in key order unless `options.sections` says otherwise.
|
|
792
|
+
*/
|
|
793
|
+
export type FormBlueprint = {
|
|
794
|
+
[field: string]: FormFieldDefinition;
|
|
795
|
+
};
|
|
796
|
+
/**
|
|
797
|
+
* A group of fields (`options.sections`); with a title it is a fieldset with a legend.
|
|
798
|
+
*/
|
|
799
|
+
export type FormSection = {
|
|
800
|
+
title?: string;
|
|
801
|
+
/**
|
|
802
|
+
* - Blueprint keys, in order
|
|
803
|
+
*/
|
|
804
|
+
fields?: string[];
|
|
805
|
+
layout?: "grid" | "stacked";
|
|
806
|
+
/**
|
|
807
|
+
* - grid columns (default 2)
|
|
808
|
+
*/
|
|
809
|
+
columns?: number;
|
|
810
|
+
};
|
|
811
|
+
export type FormOptions = {
|
|
812
|
+
/**
|
|
813
|
+
* - default 'stacked'
|
|
814
|
+
*/
|
|
815
|
+
layout?: "stacked" | "grid" | "inline";
|
|
816
|
+
/**
|
|
817
|
+
* - grid layout columns (2 or 3, default 2)
|
|
818
|
+
*/
|
|
819
|
+
columns?: 2 | 3 | number;
|
|
820
|
+
/**
|
|
821
|
+
* - default 'top'
|
|
822
|
+
*/
|
|
823
|
+
labelPosition?: "top" | "left" | "floating";
|
|
824
|
+
/**
|
|
825
|
+
* - default true
|
|
826
|
+
*/
|
|
827
|
+
showLabels?: boolean;
|
|
828
|
+
/**
|
|
829
|
+
* - default true
|
|
830
|
+
*/
|
|
831
|
+
showHelperText?: boolean;
|
|
832
|
+
/**
|
|
833
|
+
* - default true
|
|
834
|
+
*/
|
|
835
|
+
showHints?: boolean;
|
|
836
|
+
/**
|
|
837
|
+
* - default 'blur'
|
|
838
|
+
*/
|
|
839
|
+
validationMode?: "blur" | "change" | "submit";
|
|
840
|
+
/**
|
|
841
|
+
* - default 'domma'
|
|
842
|
+
*/
|
|
843
|
+
cssFramework?: "domma" | "bootstrap" | "tailwind";
|
|
844
|
+
/**
|
|
845
|
+
* - default 'domma-form'
|
|
846
|
+
*/
|
|
847
|
+
className?: string;
|
|
848
|
+
/**
|
|
849
|
+
* - default 'domma-form-field'
|
|
850
|
+
*/
|
|
851
|
+
fieldClassName?: string;
|
|
852
|
+
/**
|
|
853
|
+
* - default 'form-label'
|
|
854
|
+
*/
|
|
855
|
+
labelClassName?: string;
|
|
856
|
+
/**
|
|
857
|
+
* - default 'form-input'
|
|
858
|
+
*/
|
|
859
|
+
inputClassName?: string;
|
|
860
|
+
/**
|
|
861
|
+
* - default 'form-error'
|
|
862
|
+
*/
|
|
863
|
+
errorClassName?: string;
|
|
864
|
+
/**
|
|
865
|
+
* - default 'form-helper-text'
|
|
866
|
+
*/
|
|
867
|
+
helperClassName?: string;
|
|
868
|
+
/**
|
|
869
|
+
* - default 'form-hint'
|
|
870
|
+
*/
|
|
871
|
+
hintClassName?: string;
|
|
872
|
+
/**
|
|
873
|
+
* - Wrap the form in a card (default false)
|
|
874
|
+
*/
|
|
875
|
+
cardWrapper?: boolean;
|
|
876
|
+
sections?: FormSection[];
|
|
877
|
+
/**
|
|
878
|
+
* - default true
|
|
879
|
+
*/
|
|
880
|
+
showSubmitButton?: boolean;
|
|
881
|
+
/**
|
|
882
|
+
* - default 'Submit'
|
|
883
|
+
*/
|
|
884
|
+
submitText?: string;
|
|
885
|
+
/**
|
|
886
|
+
* - Adds a reset button with this text
|
|
887
|
+
*/
|
|
888
|
+
resetText?: string;
|
|
889
|
+
/**
|
|
890
|
+
* - default 'right'
|
|
891
|
+
*/
|
|
892
|
+
buttonAlignment?: "left" | "center" | "right";
|
|
893
|
+
/**
|
|
894
|
+
* - A valid submit
|
|
895
|
+
*/
|
|
896
|
+
onSubmit?: (data: Record<string, any>, form: FormInstance) => void;
|
|
897
|
+
/**
|
|
898
|
+
* - An invalid submit
|
|
899
|
+
*/
|
|
900
|
+
onValidationError?: (errors: Record<string, string>, form: FormInstance) => void;
|
|
901
|
+
/**
|
|
902
|
+
* - Passed to the model: a storage key to keep the values under
|
|
903
|
+
*/
|
|
904
|
+
persist?: string;
|
|
905
|
+
/**
|
|
906
|
+
* - Passed to the model
|
|
907
|
+
*/
|
|
908
|
+
autoSave?: boolean;
|
|
909
|
+
};
|
|
910
|
+
/**
|
|
911
|
+
* What `handleSubmit()` returns.
|
|
912
|
+
*/
|
|
913
|
+
export type FormSubmitResult = {
|
|
914
|
+
isValid: boolean;
|
|
915
|
+
data: Record<string, any>;
|
|
916
|
+
/**
|
|
917
|
+
* - field name -> message
|
|
918
|
+
*/
|
|
919
|
+
errors: Record<string, string>;
|
|
920
|
+
};
|
|
921
|
+
/**
|
|
922
|
+
* One step of `F.wizard`.
|
|
923
|
+
*/
|
|
924
|
+
export type FormWizardStep = {
|
|
925
|
+
/**
|
|
926
|
+
* - default 'Step <n>'
|
|
927
|
+
*/
|
|
928
|
+
title?: string;
|
|
929
|
+
description?: string;
|
|
930
|
+
/**
|
|
931
|
+
* - The step's blueprint
|
|
932
|
+
*/
|
|
933
|
+
fields: FormBlueprint;
|
|
934
|
+
layout?: "stacked" | "grid" | "inline";
|
|
935
|
+
};
|
|
936
|
+
/**
|
|
937
|
+
* `F.wizard` options; the rest are FormOptions applied to every step.
|
|
938
|
+
*/
|
|
939
|
+
export type FormWizardOptions = FormOptions & {
|
|
940
|
+
schema: {
|
|
941
|
+
steps: FormWizardStep[];
|
|
942
|
+
};
|
|
943
|
+
data?: Record<string, any>;
|
|
944
|
+
prevText?: string;
|
|
945
|
+
nextText?: string;
|
|
946
|
+
finishText?: string;
|
|
947
|
+
onStepChange?: (stepIndex: number, data: Record<string, any>) => void;
|
|
948
|
+
onValidation?: (isValid: boolean, errors: Record<string, string>, stepIndex: number) => void;
|
|
949
|
+
onSubmit?: (data: Record<string, any>, form: FormInstance) => void | Promise<void>;
|
|
950
|
+
onError?: (error: any, data: Record<string, any>, form: FormInstance) => void;
|
|
951
|
+
};
|
|
952
|
+
/**
|
|
953
|
+
* The control object `F.wizard` returns.
|
|
954
|
+
*/
|
|
955
|
+
export type FormWizard = {
|
|
956
|
+
nextStep: () => void;
|
|
957
|
+
prevStep: () => void;
|
|
958
|
+
goToStep: (stepIndex: number) => void;
|
|
959
|
+
/**
|
|
960
|
+
* - 0-based
|
|
961
|
+
*/
|
|
962
|
+
getCurrentStep: () => number;
|
|
963
|
+
/**
|
|
964
|
+
* - The values gathered so far (a copy)
|
|
965
|
+
*/
|
|
966
|
+
getStepData: () => Record<string, any>;
|
|
967
|
+
/**
|
|
968
|
+
* - Merge values in and re-render the step
|
|
969
|
+
*/
|
|
970
|
+
setStepData: (data: Record<string, any>) => void;
|
|
971
|
+
/**
|
|
972
|
+
* - Validate the current step
|
|
973
|
+
*/
|
|
974
|
+
validate: () => boolean;
|
|
975
|
+
getElement: () => HTMLElement | null;
|
|
976
|
+
/**
|
|
977
|
+
* - Tear down the current step's controls and remove the wizard
|
|
978
|
+
*/
|
|
979
|
+
destroy: () => void;
|
|
980
|
+
};
|
|
981
|
+
/**
|
|
982
|
+
* `F.modal` options; the rest are FormOptions (`onSubmit` and `showSubmitButton` are set by the modal).
|
|
983
|
+
*/
|
|
984
|
+
export type FormModalOptions = FormOptions & {
|
|
985
|
+
title?: string;
|
|
986
|
+
saveText?: string;
|
|
987
|
+
closeOnSave?: boolean;
|
|
988
|
+
size?: string;
|
|
989
|
+
onSave?: (data: Record<string, any>, form: FormInstance) => void | Promise<void>;
|
|
990
|
+
onError?: (error: any, data: Record<string, any>, form: FormInstance) => void;
|
|
991
|
+
};
|
|
992
|
+
/**
|
|
993
|
+
* The control object `F.modal` returns. `close()` removes the modal from the page.
|
|
994
|
+
*/
|
|
995
|
+
export type FormModal = {
|
|
996
|
+
open: () => void;
|
|
997
|
+
close: () => void;
|
|
998
|
+
isOpen: () => boolean;
|
|
999
|
+
};
|
|
1000
|
+
/**
|
|
1001
|
+
* `F.crud` configuration.
|
|
1002
|
+
*/
|
|
1003
|
+
export type FormCrudConfig = {
|
|
1004
|
+
schema: FormBlueprint;
|
|
1005
|
+
/**
|
|
1006
|
+
* - REST endpoint (GET list, POST create, PUT/DELETE `<endpoint>/<id>`); responses are `{success, data, message}`
|
|
1007
|
+
*/
|
|
1008
|
+
endpoint: string;
|
|
1009
|
+
/**
|
|
1010
|
+
* - Where the table goes
|
|
1011
|
+
*/
|
|
1012
|
+
tableSelector?: string | HTMLElement;
|
|
1013
|
+
/**
|
|
1014
|
+
* - default 'Manage Items'
|
|
1015
|
+
*/
|
|
1016
|
+
title?: string;
|
|
1017
|
+
/**
|
|
1018
|
+
* - default 'id'
|
|
1019
|
+
*/
|
|
1020
|
+
primaryKey?: string;
|
|
1021
|
+
/**
|
|
1022
|
+
* - default 'name'
|
|
1023
|
+
*/
|
|
1024
|
+
displayField?: string;
|
|
1025
|
+
headers?: Record<string, string>;
|
|
1026
|
+
onError?: (error: any) => void;
|
|
1027
|
+
onSuccess?: (message: string) => void;
|
|
1028
|
+
};
|
|
1029
|
+
/**
|
|
1030
|
+
* The object `F.crud` returns. Call `init()` to load the data and build the table.
|
|
1031
|
+
*/
|
|
1032
|
+
export type FormCrud = {
|
|
1033
|
+
init: () => Promise<void>;
|
|
1034
|
+
loadData: () => Promise<void>;
|
|
1035
|
+
createTable: () => void;
|
|
1036
|
+
initializeTableIcons: () => void;
|
|
1037
|
+
bindEvents: () => void;
|
|
1038
|
+
/**
|
|
1039
|
+
* - Open the create modal
|
|
1040
|
+
*/
|
|
1041
|
+
create: () => Promise<void>;
|
|
1042
|
+
/**
|
|
1043
|
+
* - Open the edit modal for an item
|
|
1044
|
+
*/
|
|
1045
|
+
edit: (id: string | number) => Promise<void>;
|
|
1046
|
+
/**
|
|
1047
|
+
* - Confirm, then delete an item
|
|
1048
|
+
*/
|
|
1049
|
+
delete: (id: string | number) => Promise<void>;
|
|
1050
|
+
refresh: () => Promise<void>;
|
|
1051
|
+
getData: () => Record<string, any>[];
|
|
1052
|
+
getTable: () => import("./tables.js").TableInstance | null;
|
|
1053
|
+
addItem: (item: Record<string, any>) => void;
|
|
1054
|
+
updateItem: (id: string | number, updates: Record<string, any>) => void;
|
|
1055
|
+
removeItem: (id: string | number) => void;
|
|
1056
|
+
};
|
|
1057
|
+
export type FormInstance = Forma;
|
|
1058
|
+
export type Forms = typeof forms;
|
|
1059
|
+
import { utils } from './utils.js';
|
|
1060
|
+
import { models } from './models.js';
|