@omnitend/dashboard-for-laravel 0.40.0 → 0.41.1
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/dist/charts.d.ts +19 -0
- package/dist/components/base/DAccordion.vue.d.ts +12 -0
- package/dist/components/base/DAccordionItem.vue.d.ts +12 -0
- package/dist/components/base/DAlert.vue.d.ts +17 -0
- package/dist/components/base/DAspect.vue.d.ts +12 -0
- package/dist/components/base/DAutocomplete.vue.d.ts +32 -0
- package/dist/components/base/DAvatar.vue.d.ts +12 -0
- package/dist/components/base/DBadge.vue.d.ts +12 -0
- package/dist/components/base/DBreadcrumb.vue.d.ts +12 -0
- package/dist/components/base/DButton.vue.d.ts +97 -0
- package/dist/components/base/DButtonGroup.vue.d.ts +12 -0
- package/dist/components/base/DButtonToolbar.vue.d.ts +12 -0
- package/dist/components/base/DCard.vue.d.ts +12 -0
- package/dist/components/base/DCol.vue.d.ts +12 -0
- package/dist/components/base/DCollapse.vue.d.ts +12 -0
- package/dist/components/base/DContainer.vue.d.ts +12 -0
- package/dist/components/base/DDropdown.vue.d.ts +12 -0
- package/dist/components/base/DDropdownDivider.vue.d.ts +2 -0
- package/dist/components/base/DDropdownItem.vue.d.ts +12 -0
- package/dist/components/base/DForm.vue.d.ts +12 -0
- package/dist/components/base/DFormCheckbox.vue.d.ts +12 -0
- package/dist/components/base/DFormCheckboxGroup.vue.d.ts +12 -0
- package/dist/components/base/DFormGroup.vue.d.ts +12 -0
- package/dist/components/base/DFormInput.vue.d.ts +2 -0
- package/dist/components/base/DFormInvalidFeedback.vue.d.ts +12 -0
- package/dist/components/base/DFormOtp.vue.d.ts +12 -0
- package/dist/components/base/DFormRadio.vue.d.ts +12 -0
- package/dist/components/base/DFormRadioGroup.vue.d.ts +12 -0
- package/dist/components/base/DFormSelect.vue.d.ts +27 -0
- package/dist/components/base/DFormSpinbutton.vue.d.ts +12 -0
- package/dist/components/base/DFormTags.vue.d.ts +12 -0
- package/dist/components/base/DFormText.vue.d.ts +12 -0
- package/dist/components/base/DFormTextarea.vue.d.ts +2 -0
- package/dist/components/base/DImage.vue.d.ts +12 -0
- package/dist/components/base/DInputGroup.vue.d.ts +12 -0
- package/dist/components/base/DLink.vue.d.ts +12 -0
- package/dist/components/base/DListGroup.vue.d.ts +12 -0
- package/dist/components/base/DListGroupItem.vue.d.ts +12 -0
- package/dist/components/base/DModal.vue.d.ts +12 -0
- package/dist/components/base/DNav.vue.d.ts +12 -0
- package/dist/components/base/DNavItem.vue.d.ts +12 -0
- package/dist/components/base/DNavbar.vue.d.ts +12 -0
- package/dist/components/base/DNavbarBrand.vue.d.ts +12 -0
- package/dist/components/base/DNavbarNav.vue.d.ts +12 -0
- package/dist/components/base/DNavbarToggle.vue.d.ts +12 -0
- package/dist/components/base/DOffcanvas.vue.d.ts +12 -0
- package/dist/components/base/DOverlay.vue.d.ts +12 -0
- package/dist/components/base/DPagination.vue.d.ts +2 -0
- package/dist/components/base/DPlaceholder.vue.d.ts +12 -0
- package/dist/components/base/DPopover.vue.d.ts +12 -0
- package/dist/components/base/DProgress.vue.d.ts +12 -0
- package/dist/components/base/DRow.vue.d.ts +12 -0
- package/dist/components/base/DSpinner.vue.d.ts +2 -0
- package/dist/components/base/DTable.vue.d.ts +34 -0
- package/dist/components/base/DTabs.vue.d.ts +12 -0
- package/dist/components/base/DToast.vue.d.ts +12 -0
- package/dist/components/base/DToaster.vue.d.ts +12 -0
- package/dist/components/base/DTooltip.vue.d.ts +12 -0
- package/dist/components/charts/DXBarChart.vue.d.ts +7 -0
- package/dist/components/charts/DXDoughnutChart.vue.d.ts +24 -0
- package/dist/components/charts/DXLineChart.vue.d.ts +7 -0
- package/dist/components/charts/chartTheme.d.ts +59 -0
- package/dist/components/charts/useThemedChart.d.ts +40 -0
- package/dist/components/extended/DXBasicForm.vue.d.ts +10 -0
- package/dist/components/extended/DXChoiceField.vue.d.ts +26 -0
- package/dist/components/extended/DXCurrencyInput.vue.d.ts +42 -0
- package/dist/components/extended/DXDashboard.vue.d.ts +105 -0
- package/dist/components/extended/DXDashboardNavbar.vue.d.ts +86 -0
- package/dist/components/extended/DXDashboardSidebar.vue.d.ts +61 -0
- package/dist/components/extended/DXField.vue.d.ts +86 -0
- package/dist/components/extended/DXFieldLabel.vue.d.ts +18 -0
- package/dist/components/extended/DXFieldShell.vue.d.ts +73 -0
- package/dist/components/extended/DXForm.vue.d.ts +112 -0
- package/dist/components/extended/DXFormField.vue.d.ts +41 -0
- package/dist/components/extended/DXNumericField.vue.d.ts +23 -0
- package/dist/components/extended/DXRepeater.vue.d.ts +46 -0
- package/dist/components/extended/DXRepeaterCards.vue.d.ts +45 -0
- package/dist/components/extended/DXStatCard.vue.d.ts +56 -0
- package/dist/components/extended/DXSwitch.vue.d.ts +47 -0
- package/dist/components/extended/DXTable.vue.d.ts +495 -0
- package/dist/components/extended/DXTableEditorModal.vue.d.ts +100 -0
- package/dist/components/extended/DXTablePagination.vue.d.ts +50 -0
- package/dist/components/extended/DXTableShell.vue.d.ts +24 -0
- package/dist/components/extended/DXUserAvatar.vue.d.ts +40 -0
- package/dist/components/extended/dxFieldContext.d.ts +11 -0
- package/dist/composables/defineForm.d.ts +41 -0
- package/dist/composables/useAsyncOptions.d.ts +20 -0
- package/dist/composables/useContainerWidth.d.ts +96 -0
- package/dist/composables/useForm.d.ts +46 -0
- package/dist/composables/useResourceEditor.d.ts +77 -0
- package/dist/composables/useToast.d.ts +2 -0
- package/dist/dashboard-for-laravel.js +4166 -4156
- package/dist/dashboard-for-laravel.js.map +1 -1
- package/dist/dashboard-for-laravel.umd.cjs +5 -5
- package/dist/dashboard-for-laravel.umd.cjs.map +1 -1
- package/dist/index.d.ts +93 -0
- package/dist/style.css +2 -2
- package/dist/types/index.d.ts +477 -0
- package/dist/types/navigation.d.ts +43 -0
- package/dist/utils/api.d.ts +30 -0
- package/dist/utils/formSchema.d.ts +59 -0
- package/dist/utils/objectPath.d.ts +18 -0
- package/docs/public/api-reference.json +26 -5
- package/docs/public/docs-map.md +1 -1
- package/package.json +1 -1
- package/resources/css/theme.scss +33 -26
- package/resources/js/components/base/DAutocomplete.vue +3 -3
- package/resources/js/components/base/DButton.vue +39 -5
- package/resources/js/components/extended/DXDashboardSidebar.vue +9 -5
- package/resources/js/components/extended/DXSwitch.vue +10 -7
- package/resources/js/components/extended/DXTable.vue +86 -88
- package/resources/js/composables/useResourceEditor.ts +41 -1
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import type { Component } from "vue";
|
|
2
|
+
/**
|
|
3
|
+
* Field types supported by DXForm (and DXField, its per-field renderer).
|
|
4
|
+
*
|
|
5
|
+
* Text-like types render an `<input>`; the remainder render purpose-built
|
|
6
|
+
* controls:
|
|
7
|
+
* - `currency` / `percentage` — numeric input wrapped in an input-group
|
|
8
|
+
* with a symbol affix.
|
|
9
|
+
* - `datetime` — alias for the native `datetime-local` control.
|
|
10
|
+
* - `image` / `file` — file input (`image` additionally shows a preview).
|
|
11
|
+
* - `component` — escape hatch that renders `field.component`.
|
|
12
|
+
* - `repeater` — nested, repeatable sub-form driven by `field.fields`.
|
|
13
|
+
* - `switch` — a toggle checkbox with contextual on/off text and an
|
|
14
|
+
* on-state (filled) style; see `textWhenTrue` / `textWhenFalse`.
|
|
15
|
+
*/
|
|
16
|
+
export type FieldType = "text" | "email" | "password" | "number" | "url" | "tel" | "date" | "datetime-local" | "datetime" | "time" | "currency" | "percentage" | "textarea" | "select" | "autocomplete" | "checkbox" | "checkbox-group" | "switch" | "switch-list" | "radio" | "image" | "file" | "component" | "repeater";
|
|
17
|
+
/**
|
|
18
|
+
* A value that may be supplied directly or computed from the live form
|
|
19
|
+
* model. Predicates receive the current model so fields can react to
|
|
20
|
+
* other fields (cross-field reactivity).
|
|
21
|
+
*/
|
|
22
|
+
export type MaybeFn<TValue> = TValue | ((model: any) => TValue);
|
|
23
|
+
/**
|
|
24
|
+
* Option for select or radio fields
|
|
25
|
+
*/
|
|
26
|
+
export interface FieldOption extends Record<string, unknown> {
|
|
27
|
+
value: any;
|
|
28
|
+
text: string;
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Asynchronously resolves the options for a select/radio field from the
|
|
33
|
+
* current model (e.g. fetch a dependent list). Resolved on mount, and
|
|
34
|
+
* again on model change when `reloadOptionsOnChange` is set.
|
|
35
|
+
*/
|
|
36
|
+
export type OptionsLoader = (model: any) => Promise<FieldOption[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Label column width for horizontal layout, mirroring Bootstrap Vue Next's
|
|
39
|
+
* `BFormGroup` `labelCols`/`labelCols*` props: either a single width applied
|
|
40
|
+
* at all breakpoints, or a per-breakpoint object (omitted breakpoints fall
|
|
41
|
+
* back to BFormGroup's own defaults, which is how "collapse to vertical
|
|
42
|
+
* below a breakpoint" comes for free — e.g. `{ md: 3 }` stacks below `md`).
|
|
43
|
+
*
|
|
44
|
+
* Deliberately excludes `boolean` (which BFormGroup's own `labelCols` prop
|
|
45
|
+
* accepts): Vue's type-based `defineProps` auto-defaults an omitted prop to
|
|
46
|
+
* `false` (not `undefined`) whenever its declared type includes `boolean`,
|
|
47
|
+
* which would silently break the `field.labelCols ?? formLabelCols ?? 3`
|
|
48
|
+
* fallback chain used to resolve this value.
|
|
49
|
+
*/
|
|
50
|
+
export type LabelCols = number | {
|
|
51
|
+
sm?: number;
|
|
52
|
+
md?: number;
|
|
53
|
+
lg?: number;
|
|
54
|
+
xl?: number;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Field definition shared by every form renderer.
|
|
58
|
+
*
|
|
59
|
+
* DXForm and DXTable's edit modal honour `hint`, `span`, `when`,
|
|
60
|
+
* `readonly`, `disabledWhen`, function-valued `label`/`hint`, async
|
|
61
|
+
* options, the `component` escape hatch and nested `repeater` fields.
|
|
62
|
+
*/
|
|
63
|
+
export interface FieldDefinition {
|
|
64
|
+
/** Field key (must match form data key) */
|
|
65
|
+
key: string;
|
|
66
|
+
/** Field type */
|
|
67
|
+
type: FieldType;
|
|
68
|
+
/** Field label — string or a function of the form model */
|
|
69
|
+
label?: MaybeFn<string>;
|
|
70
|
+
/** Placeholder text (optional) */
|
|
71
|
+
placeholder?: string;
|
|
72
|
+
/** Whether field is required (optional) */
|
|
73
|
+
required?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Options for `select`, `radio`, `checkbox-group`, `switch-list` and
|
|
76
|
+
* `autocomplete` fields. For `autocomplete` these are the datalist
|
|
77
|
+
* suggestions; the field still accepts free text not present in the list.
|
|
78
|
+
* For `switch-list` each option renders a labelled toggle row
|
|
79
|
+
* (`description` becomes the row label's tooltip).
|
|
80
|
+
*/
|
|
81
|
+
options?: FieldOption[];
|
|
82
|
+
/**
|
|
83
|
+
* Asynchronously load options for `select`, `radio` and `autocomplete`
|
|
84
|
+
* fields (e.g. fetch a suggestion list). Takes precedence over `options`
|
|
85
|
+
* once resolved.
|
|
86
|
+
*/
|
|
87
|
+
optionsLoader?: OptionsLoader;
|
|
88
|
+
/** Re-run `optionsLoader` whenever the form model changes. */
|
|
89
|
+
reloadOptionsOnChange?: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* For `select` fields: render a **searchable** select — type to filter a
|
|
92
|
+
* long option list, while the model still holds `option.value` (an id).
|
|
93
|
+
*
|
|
94
|
+
* A plain `select` is fine for ten options and unusable for hundreds; the
|
|
95
|
+
* `autocomplete` type filters but models the *typed text*, so it can't back
|
|
96
|
+
* a foreign key (picking "Tesco" gives you `"Tesco"`, not `37`). This is the
|
|
97
|
+
* combination high-frequency data entry against a long list needs.
|
|
98
|
+
*/
|
|
99
|
+
searchable?: boolean;
|
|
100
|
+
/** Number of rows for textarea (default: 3) */
|
|
101
|
+
rows?: number;
|
|
102
|
+
/** Step for numeric/currency/percentage inputs */
|
|
103
|
+
step?: number | string;
|
|
104
|
+
/** Min/max for numeric inputs */
|
|
105
|
+
min?: number | string;
|
|
106
|
+
max?: number | string;
|
|
107
|
+
/** Symbol shown for `currency` fields (default: the locale's, "£"). */
|
|
108
|
+
currencySymbol?: string;
|
|
109
|
+
/**
|
|
110
|
+
* For `currency` fields: minor-unit decimal places the *display* value is
|
|
111
|
+
* formatted to on blur and on initial seed (default: 2, e.g. GBP/EUR/USD —
|
|
112
|
+
* pass 0 for a currency with no minor unit, e.g. JPY). The model stays a
|
|
113
|
+
* plain number throughout; only the input's shown text is padded (`3.8` →
|
|
114
|
+
* `3.80`). Typing is never reformatted mid-edit.
|
|
115
|
+
*/
|
|
116
|
+
decimals?: number;
|
|
117
|
+
/**
|
|
118
|
+
* For `currency` fields: the model stores integer MINOR units (pence) but
|
|
119
|
+
* the input shows/edits MAJOR units (pounds) — display = value / 10^decimals,
|
|
120
|
+
* submit = round(input × 10^decimals). `min`/`max`/`step` stay in major
|
|
121
|
+
* units. Off by default (the model is the major-unit amount). Use for
|
|
122
|
+
* legacy pence-integer columns (#116).
|
|
123
|
+
*/
|
|
124
|
+
minorUnits?: boolean;
|
|
125
|
+
/**
|
|
126
|
+
* For `percentage` fields: treat the underlying model value as a 0–1
|
|
127
|
+
* fraction while showing/editing it as a 0–100 percentage. The model keeps
|
|
128
|
+
* the fraction (e.g. `0.2`), the input shows `20`. Off by default (the value
|
|
129
|
+
* is taken as a whole percentage). Use for fields stored as ratios (VAT
|
|
130
|
+
* rates, discounts, …).
|
|
131
|
+
*/
|
|
132
|
+
asFraction?: boolean;
|
|
133
|
+
/** `accept` attribute for `image`/`file` inputs (e.g. "image/*"). */
|
|
134
|
+
accept?: string;
|
|
135
|
+
/** Help text displayed below the field (always visible). */
|
|
136
|
+
help?: string;
|
|
137
|
+
/**
|
|
138
|
+
* Hint text displayed below the field. Unlike `help`, may be a
|
|
139
|
+
* function of the model for dynamic hints.
|
|
140
|
+
*/
|
|
141
|
+
hint?: MaybeFn<string>;
|
|
142
|
+
/**
|
|
143
|
+
* Longer help text revealed in a popover from a small info affordance
|
|
144
|
+
* on the field's label (on hover/focus). Complements `hint` (which is
|
|
145
|
+
* always-visible muted text below the control). May be a function of
|
|
146
|
+
* the model. Plain text only — for a rich popover body (lists, bold,
|
|
147
|
+
* paragraphs) use the `#info-popover(<key>)` slot. Note the separate
|
|
148
|
+
* `#info(<key>)` slot renders an always-visible block below the control,
|
|
149
|
+
* not popover content.
|
|
150
|
+
*/
|
|
151
|
+
info?: MaybeFn<string>;
|
|
152
|
+
/**
|
|
153
|
+
* For `switch` fields: contextual label shown when the toggle is on.
|
|
154
|
+
* Falls back to `label` when omitted. May be a function of the model.
|
|
155
|
+
*/
|
|
156
|
+
textWhenTrue?: MaybeFn<string>;
|
|
157
|
+
/**
|
|
158
|
+
* For `switch` fields: contextual label shown when the toggle is off.
|
|
159
|
+
* Falls back to `label` when omitted. May be a function of the model.
|
|
160
|
+
*/
|
|
161
|
+
textWhenFalse?: MaybeFn<string>;
|
|
162
|
+
/**
|
|
163
|
+
* For `switch` and `switch-list` fields: the on-state colour. `"success"`
|
|
164
|
+
* (default) is the house green-on / red-off style for an
|
|
165
|
+
* active/enabled/good switch; `"neutral"` (brand primary on / grey off) is
|
|
166
|
+
* for semantically-mixed switches that shouldn't imply good/bad ("contains
|
|
167
|
+
* alcohol", an allergen toggle, "hidden on web shop"). A `switch-list`
|
|
168
|
+
* usually wants `"neutral"` — a wall of red-off toggles over-signals when
|
|
169
|
+
* off simply means "not present". See DXSwitch `onVariant` (#158).
|
|
170
|
+
*/
|
|
171
|
+
switchVariant?: "success" | "neutral";
|
|
172
|
+
/** CSS class for the form group */
|
|
173
|
+
class?: string;
|
|
174
|
+
/** Additional props to pass to the input component */
|
|
175
|
+
inputProps?: Record<string, any>;
|
|
176
|
+
/**
|
|
177
|
+
* Render the field full-width with no label wrapper, delegating its
|
|
178
|
+
* content to the `#span(<key>)` slot. Useful for custom blocks. Also
|
|
179
|
+
* doubles as the "fill both columns" escape hatch in horizontal layout —
|
|
180
|
+
* a span field always bypasses the label/content column split.
|
|
181
|
+
*/
|
|
182
|
+
span?: boolean;
|
|
183
|
+
/**
|
|
184
|
+
* Per-field override of DXForm's `layout` prop ("vertical" | "horizontal").
|
|
185
|
+
* Falls back to the form-level `layout` when omitted.
|
|
186
|
+
*/
|
|
187
|
+
layout?: "vertical" | "horizontal";
|
|
188
|
+
/**
|
|
189
|
+
* Per-field override of DXForm's `labelCols` prop, for horizontal
|
|
190
|
+
* layout. Falls back to the form-level `labelCols` when omitted.
|
|
191
|
+
*/
|
|
192
|
+
labelCols?: LabelCols;
|
|
193
|
+
/**
|
|
194
|
+
* Skip rendering the field's own label. In horizontal layout no label
|
|
195
|
+
* column is reserved either, so the control spans the full width. Useful
|
|
196
|
+
* for `switch` (and `checkbox`) fields, which render their own label
|
|
197
|
+
* inside the control — the outer row label would otherwise duplicate it,
|
|
198
|
+
* and the self-label then lines up with sibling row labels. Also used
|
|
199
|
+
* internally by `DXRepeater`'s `table` layout, where a column header
|
|
200
|
+
* already names the field.
|
|
201
|
+
*/
|
|
202
|
+
hideLabel?: boolean;
|
|
203
|
+
/**
|
|
204
|
+
* Component rendered for `type: "component"` fields. Receives
|
|
205
|
+
* `modelValue`, `field`, `model` props and emits `update:modelValue`.
|
|
206
|
+
*/
|
|
207
|
+
component?: Component;
|
|
208
|
+
/** Sub-field definitions for `type: "repeater"` fields. */
|
|
209
|
+
fields?: FieldDefinition[];
|
|
210
|
+
/**
|
|
211
|
+
* Default/initial value. Used by `defineForm` to seed form data and by
|
|
212
|
+
* repeaters to seed a freshly-added row's sub-fields. (`defineForm`'s
|
|
213
|
+
* `FormFieldDefinition` re-declares this as required for inference.)
|
|
214
|
+
*/
|
|
215
|
+
default?: any;
|
|
216
|
+
/** Label for a repeater's "add row" button (default: "Add"). */
|
|
217
|
+
addLabel?: string;
|
|
218
|
+
/** Minimum / maximum number of repeater rows. */
|
|
219
|
+
minItems?: number;
|
|
220
|
+
maxItems?: number;
|
|
221
|
+
/**
|
|
222
|
+
* For `repeater` fields: `"cards"` (default) stacks each row as its own
|
|
223
|
+
* card with sub-fields listed vertically — best for rows with several
|
|
224
|
+
* or complex sub-fields. `"table"` renders one row per item with
|
|
225
|
+
* sub-fields as columns — far more compact for simple child-row lists
|
|
226
|
+
* (e.g. 2-3 short sub-fields). Named `repeaterLayout` (not `layout`) to
|
|
227
|
+
* avoid colliding with the unrelated form-level `layout` prop
|
|
228
|
+
* ("vertical" | "horizontal") every field type accepts.
|
|
229
|
+
*/
|
|
230
|
+
repeaterLayout?: "cards" | "table";
|
|
231
|
+
/**
|
|
232
|
+
* For `repeater` fields in `cards` layout: show each row's 1-based
|
|
233
|
+
* position (e.g. "1", "2") next to its Remove button. Off by default —
|
|
234
|
+
* only meaningful once a consumer explicitly wants it (e.g. rows the
|
|
235
|
+
* user thinks of as numbered/ordered); most repeaters don't need it.
|
|
236
|
+
* Not applicable to `table` layout, which has no equivalent column.
|
|
237
|
+
*/
|
|
238
|
+
showRowIndex?: boolean;
|
|
239
|
+
/**
|
|
240
|
+
* For `repeater` fields backed by an upsert-children API contract (rows
|
|
241
|
+
* carrying a persisted `id` are only deleted server-side when submitted
|
|
242
|
+
* flagged, e.g. Laravel's `{ id, to_delete: true }` pattern): the
|
|
243
|
+
* sub-field key to set `true` when a row is removed, instead of splicing
|
|
244
|
+
* it out of the array. Only applies to rows that already have an `id`
|
|
245
|
+
* (freshly added, never-persisted rows are still spliced normally since
|
|
246
|
+
* the server has never seen them). Flagged rows remain in `form.data`
|
|
247
|
+
* (so they're submitted) but are hidden from the UI and excluded from
|
|
248
|
+
* `minItems`/`maxItems` counts.
|
|
249
|
+
*/
|
|
250
|
+
softDeleteKey?: string;
|
|
251
|
+
/** Disable the field (static or computed from the model). */
|
|
252
|
+
disabled?: MaybeFn<boolean>;
|
|
253
|
+
/**
|
|
254
|
+
* Disable the field based on the model. Retained for backwards
|
|
255
|
+
* compatibility with DXTable; prefer `disabled` with a function.
|
|
256
|
+
*/
|
|
257
|
+
disabledWhen?: (model: any) => boolean;
|
|
258
|
+
/**
|
|
259
|
+
* Render the field read-only (static or computed). For controls
|
|
260
|
+
* without a native readonly state (select/checkbox/radio) this is
|
|
261
|
+
* applied as `disabled`.
|
|
262
|
+
*/
|
|
263
|
+
readonly?: MaybeFn<boolean>;
|
|
264
|
+
/**
|
|
265
|
+
* Display the value as static text instead of a control — no border, no
|
|
266
|
+
* input box (Bootstrap's `.form-control-plaintext`). For values a
|
|
267
|
+
* profile/settings page shows but never lets you edit, where a `readonly`
|
|
268
|
+
* input still reads as "you could edit this, but can't".
|
|
269
|
+
*
|
|
270
|
+
* Implies read-only, for every field type. Anything backed by a real input
|
|
271
|
+
* — the text family, textarea, currency, percentage, autocomplete — renders
|
|
272
|
+
* as static text; control types with no native readonly state
|
|
273
|
+
* (select/radio/checkbox/switch/file) are disabled instead, exactly as they
|
|
274
|
+
* are for `readonly`.
|
|
275
|
+
*
|
|
276
|
+
* Enforced over `inputProps`: unlike the field's other bindings, which
|
|
277
|
+
* `inputProps` may override, a plaintext field cannot be made editable
|
|
278
|
+
* again through it.
|
|
279
|
+
*/
|
|
280
|
+
plaintext?: MaybeFn<boolean>;
|
|
281
|
+
/**
|
|
282
|
+
* Only for `type: "password"`. Show the reveal (eye) toggle that switches
|
|
283
|
+
* the input between masked and plain text. Defaults to `true` — set
|
|
284
|
+
* `false` to render a bare password input.
|
|
285
|
+
*/
|
|
286
|
+
revealable?: boolean;
|
|
287
|
+
/**
|
|
288
|
+
* Include this field's value in the submitted payload. Default `true`.
|
|
289
|
+
*
|
|
290
|
+
* Set `false` for a **presentational** field — a header, an alert, an
|
|
291
|
+
* explanatory block rendered via `span` — that exists to lay out the form,
|
|
292
|
+
* not to hold data. Without it, `DXTable`'s edit modal seeds its form from
|
|
293
|
+
* every `editFields` key, so those decorative fields are POSTed alongside
|
|
294
|
+
* the real ones (an empty string, an empty array) purely because they were
|
|
295
|
+
* declared.
|
|
296
|
+
*/
|
|
297
|
+
submit?: boolean;
|
|
298
|
+
/**
|
|
299
|
+
* Conditionally show or hide this field. When omitted the field is
|
|
300
|
+
* always visible. Boolean or a function of the form model; evaluated
|
|
301
|
+
* reactively for cross-field conditional fields.
|
|
302
|
+
*/
|
|
303
|
+
when?: MaybeFn<boolean>;
|
|
304
|
+
/**
|
|
305
|
+
* Legacy no-argument visibility predicate. Retained for backwards
|
|
306
|
+
* compatibility; prefer `when`. When both are present, a field is
|
|
307
|
+
* visible only if both pass.
|
|
308
|
+
*/
|
|
309
|
+
show?: () => boolean;
|
|
310
|
+
}
|
|
311
|
+
/** Options common to every field variant (the non-`type`-specific props). */
|
|
312
|
+
export interface BaseFieldDef {
|
|
313
|
+
key: string;
|
|
314
|
+
label?: MaybeFn<string>;
|
|
315
|
+
required?: boolean;
|
|
316
|
+
help?: string;
|
|
317
|
+
hint?: MaybeFn<string>;
|
|
318
|
+
info?: MaybeFn<string>;
|
|
319
|
+
class?: string;
|
|
320
|
+
inputProps?: Record<string, any>;
|
|
321
|
+
span?: boolean;
|
|
322
|
+
layout?: "vertical" | "horizontal";
|
|
323
|
+
labelCols?: LabelCols;
|
|
324
|
+
hideLabel?: boolean;
|
|
325
|
+
default?: any;
|
|
326
|
+
disabled?: MaybeFn<boolean>;
|
|
327
|
+
disabledWhen?: (model: any) => boolean;
|
|
328
|
+
readonly?: MaybeFn<boolean>;
|
|
329
|
+
plaintext?: MaybeFn<boolean>;
|
|
330
|
+
submit?: boolean;
|
|
331
|
+
when?: MaybeFn<boolean>;
|
|
332
|
+
show?: () => boolean;
|
|
333
|
+
}
|
|
334
|
+
/** Mixins shared by several variants (not exported — internal composition). */
|
|
335
|
+
interface WithPlaceholder {
|
|
336
|
+
placeholder?: string;
|
|
337
|
+
}
|
|
338
|
+
interface WithNumericBounds {
|
|
339
|
+
step?: number | string;
|
|
340
|
+
min?: number | string;
|
|
341
|
+
max?: number | string;
|
|
342
|
+
}
|
|
343
|
+
interface WithSelectableOptions {
|
|
344
|
+
options?: FieldOption[];
|
|
345
|
+
optionsLoader?: OptionsLoader;
|
|
346
|
+
reloadOptionsOnChange?: boolean;
|
|
347
|
+
}
|
|
348
|
+
/** `text` / `email` / `url` / `tel` — a plain text-like `<input>`. */
|
|
349
|
+
export interface TextFieldDef extends BaseFieldDef, WithPlaceholder {
|
|
350
|
+
type: "text" | "email" | "url" | "tel";
|
|
351
|
+
}
|
|
352
|
+
/** `password` — text input with an optional reveal (eye) toggle. */
|
|
353
|
+
export interface PasswordFieldDef extends BaseFieldDef, WithPlaceholder {
|
|
354
|
+
type: "password";
|
|
355
|
+
revealable?: boolean;
|
|
356
|
+
}
|
|
357
|
+
/** `number` — numeric input with optional bounds. */
|
|
358
|
+
export interface NumberFieldDef extends BaseFieldDef, WithPlaceholder, WithNumericBounds {
|
|
359
|
+
type: "number";
|
|
360
|
+
}
|
|
361
|
+
/** `date` / `datetime` / `datetime-local` / `time` — native date/time controls.
|
|
362
|
+
* `min`/`max`/`step` are valid on these inputs (e.g. `min="2024-01-01"`) and
|
|
363
|
+
* DXField forwards them, so the variant permits them. */
|
|
364
|
+
export interface DateFieldDef extends BaseFieldDef, WithNumericBounds {
|
|
365
|
+
type: "date" | "datetime" | "datetime-local" | "time";
|
|
366
|
+
}
|
|
367
|
+
/** `currency` — numeric input with a symbol affix and minor-unit handling. */
|
|
368
|
+
export interface CurrencyFieldDef extends BaseFieldDef, WithPlaceholder, WithNumericBounds {
|
|
369
|
+
type: "currency";
|
|
370
|
+
currencySymbol?: string;
|
|
371
|
+
decimals?: number;
|
|
372
|
+
minorUnits?: boolean;
|
|
373
|
+
}
|
|
374
|
+
/** `percentage` — numeric input shown as a 0–100 percentage. */
|
|
375
|
+
export interface PercentageFieldDef extends BaseFieldDef, WithPlaceholder, WithNumericBounds {
|
|
376
|
+
type: "percentage";
|
|
377
|
+
asFraction?: boolean;
|
|
378
|
+
}
|
|
379
|
+
/** `textarea` — multi-line text input. */
|
|
380
|
+
export interface TextareaFieldDef extends BaseFieldDef, WithPlaceholder {
|
|
381
|
+
type: "textarea";
|
|
382
|
+
rows?: number;
|
|
383
|
+
}
|
|
384
|
+
/** `select` — dropdown; `searchable` upgrades it to a filterable select. */
|
|
385
|
+
export interface SelectFieldDef extends BaseFieldDef, WithPlaceholder, WithSelectableOptions {
|
|
386
|
+
type: "select";
|
|
387
|
+
searchable?: boolean;
|
|
388
|
+
}
|
|
389
|
+
/** `autocomplete` — free-text input with datalist suggestions. */
|
|
390
|
+
export interface AutocompleteFieldDef extends BaseFieldDef, WithPlaceholder, WithSelectableOptions {
|
|
391
|
+
type: "autocomplete";
|
|
392
|
+
}
|
|
393
|
+
/** `checkbox` — a single boolean checkbox. */
|
|
394
|
+
export interface CheckboxFieldDef extends BaseFieldDef {
|
|
395
|
+
type: "checkbox";
|
|
396
|
+
}
|
|
397
|
+
/** `checkbox-group` — multiple checkboxes; model is an array of values. */
|
|
398
|
+
export interface CheckboxGroupFieldDef extends BaseFieldDef, WithSelectableOptions {
|
|
399
|
+
type: "checkbox-group";
|
|
400
|
+
}
|
|
401
|
+
/** `switch` — a toggle with contextual on/off text and on-state colour. */
|
|
402
|
+
export interface SwitchFieldDef extends BaseFieldDef {
|
|
403
|
+
type: "switch";
|
|
404
|
+
textWhenTrue?: MaybeFn<string>;
|
|
405
|
+
textWhenFalse?: MaybeFn<string>;
|
|
406
|
+
switchVariant?: "success" | "neutral";
|
|
407
|
+
}
|
|
408
|
+
/** `switch-list` — a labelled toggle row per option; model is an array. */
|
|
409
|
+
export interface SwitchListFieldDef extends BaseFieldDef, WithSelectableOptions {
|
|
410
|
+
type: "switch-list";
|
|
411
|
+
switchVariant?: "success" | "neutral";
|
|
412
|
+
}
|
|
413
|
+
/** `radio` — a radio group. */
|
|
414
|
+
export interface RadioFieldDef extends BaseFieldDef, WithSelectableOptions {
|
|
415
|
+
type: "radio";
|
|
416
|
+
}
|
|
417
|
+
/** `image` / `file` — file input (`image` also shows a preview). */
|
|
418
|
+
export interface FileFieldDef extends BaseFieldDef {
|
|
419
|
+
type: "image" | "file";
|
|
420
|
+
accept?: string;
|
|
421
|
+
}
|
|
422
|
+
/** `component` — escape hatch rendering `field.component`. */
|
|
423
|
+
export interface ComponentFieldDef extends BaseFieldDef {
|
|
424
|
+
type: "component";
|
|
425
|
+
/** Required on the strict variant: a `component` field with no component
|
|
426
|
+
* falls through to the generic input branch, so the union enforces it. */
|
|
427
|
+
component: Component;
|
|
428
|
+
}
|
|
429
|
+
/** `repeater` — a nested, repeatable sub-form driven by `fields`. */
|
|
430
|
+
export interface RepeaterFieldDef extends BaseFieldDef {
|
|
431
|
+
type: "repeater";
|
|
432
|
+
fields?: FieldDef[];
|
|
433
|
+
addLabel?: string;
|
|
434
|
+
minItems?: number;
|
|
435
|
+
maxItems?: number;
|
|
436
|
+
repeaterLayout?: "cards" | "table";
|
|
437
|
+
showRowIndex?: boolean;
|
|
438
|
+
softDeleteKey?: string;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Strict, discriminated replacement for `FieldDefinition`. Keyed on `type`,
|
|
442
|
+
* so each field only permits its own options. Opt-in today; canonical in a
|
|
443
|
+
* future major (#131). See the banner above.
|
|
444
|
+
*/
|
|
445
|
+
export type FieldDef = TextFieldDef | PasswordFieldDef | NumberFieldDef | DateFieldDef | CurrencyFieldDef | PercentageFieldDef | TextareaFieldDef | SelectFieldDef | AutocompleteFieldDef | CheckboxFieldDef | CheckboxGroupFieldDef | SwitchFieldDef | SwitchListFieldDef | RadioFieldDef | FileFieldDef | ComponentFieldDef | RepeaterFieldDef;
|
|
446
|
+
/**
|
|
447
|
+
* Compile-time drift guard (#131): every strict variant must remain assignable
|
|
448
|
+
* to the permissive `FieldDefinition`. If a `FieldDef` variant grows a prop that
|
|
449
|
+
* `FieldDefinition` doesn't have (or types incompatibly), this fails to satisfy
|
|
450
|
+
* its `true` constraint and the build goes red. Purely type-level — no runtime.
|
|
451
|
+
* (The reverse direction — a prop added to `FieldDefinition` but forgotten on a
|
|
452
|
+
* variant — can't be asserted this way; the banner above is the reminder.)
|
|
453
|
+
*/
|
|
454
|
+
type _AssertTrue<T extends true> = T;
|
|
455
|
+
export type _FieldDefStaysASubset = _AssertTrue<FieldDef extends FieldDefinition ? true : false>;
|
|
456
|
+
/**
|
|
457
|
+
* A tab in a tabbed form. Groups a subset of fields and can be shown
|
|
458
|
+
* conditionally or lazily mounted.
|
|
459
|
+
*/
|
|
460
|
+
export interface FormTab {
|
|
461
|
+
/** Unique key for this tab */
|
|
462
|
+
key: string;
|
|
463
|
+
/**
|
|
464
|
+
* Display label (optional, defaults to the key). May be a function of the
|
|
465
|
+
* form model — the live form data merged with any `context` (e.g. the row
|
|
466
|
+
* DXTable is editing) — so a tab title can reflect the record, such as
|
|
467
|
+
* `label: (model) => \`Products (${model.products_count ?? 0})\``.
|
|
468
|
+
*/
|
|
469
|
+
label?: MaybeFn<string>;
|
|
470
|
+
/** Field keys (from the form's fields) to render in this tab */
|
|
471
|
+
fieldKeys: string[];
|
|
472
|
+
/** Conditional display — boolean or a function of the form model */
|
|
473
|
+
when?: MaybeFn<boolean>;
|
|
474
|
+
/** Lazily mount tab content until first activated */
|
|
475
|
+
lazy?: boolean;
|
|
476
|
+
}
|
|
477
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface NavigationItem {
|
|
2
|
+
label: string;
|
|
3
|
+
url: string;
|
|
4
|
+
icon?: string;
|
|
5
|
+
badge?: string | number;
|
|
6
|
+
badgeColor?: string;
|
|
7
|
+
active?: boolean;
|
|
8
|
+
visible?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface NavigationGroup {
|
|
11
|
+
label?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Stable identifier for the group's collapsible open/closed state. Defaults
|
|
14
|
+
* to `label` (then the array index). Set this when a menu can be reordered at
|
|
15
|
+
* runtime, or two groups share a label, so a manually-opened group keeps its
|
|
16
|
+
* state attached to the right group.
|
|
17
|
+
*/
|
|
18
|
+
key?: string;
|
|
19
|
+
items: NavigationItem[];
|
|
20
|
+
/**
|
|
21
|
+
* Per-group override for the sidebar's `collapsibleGroups` behaviour.
|
|
22
|
+
* Set to `false` to keep a group permanently expanded (no toggle header)
|
|
23
|
+
* even when the sidebar has collapsible groups enabled. Defaults to `true`.
|
|
24
|
+
*/
|
|
25
|
+
collapsible?: boolean;
|
|
26
|
+
/** Reserved for a future explicit initial-open hint; not currently wired. */
|
|
27
|
+
collapsed?: boolean;
|
|
28
|
+
visible?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export type Navigation = NavigationGroup[];
|
|
31
|
+
/**
|
|
32
|
+
* Horizontal alignment of the navbar search slot content within its region:
|
|
33
|
+
* `"start"` = flush left (after the title from `md` up), `"center"` = centred.
|
|
34
|
+
* Shared by DXDashboard (which forwards it) and DXDashboardNavbar.
|
|
35
|
+
*/
|
|
36
|
+
export type NavbarSearchAlign = "start" | "center";
|
|
37
|
+
/**
|
|
38
|
+
* What the navbar actions slot does below the `md` breakpoint: `"wrap"` moves
|
|
39
|
+
* it to its own full-width row (the bar grows), `"hide"` removes it entirely
|
|
40
|
+
* (for apps that relocate page actions into the page on phones).
|
|
41
|
+
* Shared by DXDashboard (which forwards it) and DXDashboardNavbar.
|
|
42
|
+
*/
|
|
43
|
+
export type NavbarActionsOnMobile = "wrap" | "hide";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface ApiError {
|
|
2
|
+
message: string;
|
|
3
|
+
errors: Record<string, string[]>;
|
|
4
|
+
status: number;
|
|
5
|
+
}
|
|
6
|
+
export interface ApiResponse<T = unknown> {
|
|
7
|
+
data: T;
|
|
8
|
+
response: Response;
|
|
9
|
+
}
|
|
10
|
+
interface RequestOptions extends Omit<RequestInit, "body"> {
|
|
11
|
+
headers?: Record<string, string>;
|
|
12
|
+
body?: BodyInit | null;
|
|
13
|
+
}
|
|
14
|
+
declare class ApiClient {
|
|
15
|
+
private baseURL;
|
|
16
|
+
private defaultHeaders;
|
|
17
|
+
setBaseURL(url: string): void;
|
|
18
|
+
setDefaultHeader(key: string, value: string): void;
|
|
19
|
+
private getCsrfToken;
|
|
20
|
+
private toQuery;
|
|
21
|
+
private handleError;
|
|
22
|
+
request<T = unknown>(url: string, options?: RequestOptions): Promise<ApiResponse<T>>;
|
|
23
|
+
get<T = unknown>(url: string, params?: Record<string, unknown>, options?: Omit<RequestOptions, "method">): Promise<ApiResponse<T>>;
|
|
24
|
+
post<T = unknown>(url: string, data?: any, options?: Omit<RequestOptions, "method" | "body">): Promise<ApiResponse<T>>;
|
|
25
|
+
put<T = unknown>(url: string, data?: any, options?: Omit<RequestOptions, "method" | "body">): Promise<ApiResponse<T>>;
|
|
26
|
+
patch<T = unknown>(url: string, data?: any, options?: Omit<RequestOptions, "method" | "body">): Promise<ApiResponse<T>>;
|
|
27
|
+
delete<T = unknown>(url: string, data?: any, options?: Omit<RequestOptions, "method" | "body">): Promise<ApiResponse<T>>;
|
|
28
|
+
}
|
|
29
|
+
export declare const api: ApiClient;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { FieldType, MaybeFn } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* The canonical starting value for a field TYPE, used when a field declares no
|
|
4
|
+
* explicit `default`. Superset of the previous copies:
|
|
5
|
+
* - `checkbox` / `switch` → `false`
|
|
6
|
+
* - `number` / `currency` / `percentage` → `0`
|
|
7
|
+
* - `repeater` / `checkbox-group` / `switch-list` → `[]` (array-valued models)
|
|
8
|
+
* - `image` / `file` → `null`
|
|
9
|
+
* - everything else (text family, `select`, `radio`, `autocomplete`, …) → `""`
|
|
10
|
+
*/
|
|
11
|
+
export declare function defaultValueForType(type: FieldType): any;
|
|
12
|
+
/**
|
|
13
|
+
* Deep-clone a default so object/array defaults aren't shared BY REFERENCE
|
|
14
|
+
* across form instances or repeater rows (mutating one row would otherwise
|
|
15
|
+
* mutate the field's declared default and every sibling row).
|
|
16
|
+
*
|
|
17
|
+
* Mirrors `useForm`'s `deepClone`: `toRaw` unwraps a Vue reactive proxy, then
|
|
18
|
+
* `structuredClone` (which preserves Date/File/Map — a plain JSON round-trip
|
|
19
|
+
* would flatten a `Date` default to a string) with a JSON fallback for a
|
|
20
|
+
* residual nested proxy or otherwise-uncloneable value. This matters because
|
|
21
|
+
* `defineForm`/`useResourceEditor` now clone here BEFORE the value reaches
|
|
22
|
+
* `useForm`, so a lossy clone would corrupt a rich default the raw path used
|
|
23
|
+
* to preserve (#134 review).
|
|
24
|
+
*/
|
|
25
|
+
export declare function cloneDefault<TValue>(value: TValue): TValue;
|
|
26
|
+
/**
|
|
27
|
+
* A field's starting value: its explicit `default` (deep-cloned) when one is
|
|
28
|
+
* DEFINED, else the type default. Definedness — not nullishness — decides, so a
|
|
29
|
+
* legitimate `null` default (e.g. a "none" select option whose value is `null`)
|
|
30
|
+
* survives instead of being replaced by the type default (#122/#125). An absent
|
|
31
|
+
* or explicitly-`undefined` default falls back to the type default rather than
|
|
32
|
+
* seeding `undefined`, which would drop the key from the JSON payload.
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveFieldDefault(field: {
|
|
35
|
+
type: FieldType;
|
|
36
|
+
default?: any;
|
|
37
|
+
}): any;
|
|
38
|
+
/**
|
|
39
|
+
* Resolve a `MaybeFn<boolean>` predicate (`when` on a field or tab) against the
|
|
40
|
+
* live model. `undefined` yields `fallback` (the field/tab is unconditioned).
|
|
41
|
+
*/
|
|
42
|
+
export declare function resolvePredicate(when: MaybeFn<boolean> | undefined, model: any, fallback: boolean): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Whether a field is VISIBLE against a model, by the one rule every renderer
|
|
45
|
+
* shares: the `when` predicate (default visible) AND the legacy no-arg `show`
|
|
46
|
+
* predicate. A field is visible only if both pass.
|
|
47
|
+
*/
|
|
48
|
+
export declare function isFieldVisible(field: {
|
|
49
|
+
when?: MaybeFn<boolean>;
|
|
50
|
+
show?: () => boolean;
|
|
51
|
+
}, model: any): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Whether a field's value belongs in the submitted payload. A presentational
|
|
54
|
+
* field (`submit: false`) — a header, an alert, an explanatory `span` block —
|
|
55
|
+
* renders but holds no data and must not be POSTed just because it was declared.
|
|
56
|
+
*/
|
|
57
|
+
export declare function isSubmittableField(field: {
|
|
58
|
+
submit?: boolean;
|
|
59
|
+
}): boolean;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal dot-path get/set helpers used for nested form binding
|
|
3
|
+
* (e.g. repeater rows where a field value lives at `lines.0.price`).
|
|
4
|
+
*
|
|
5
|
+
* Paths are dot-separated; numeric segments index into arrays. Setting
|
|
6
|
+
* creates intermediate objects/arrays as needed so a fresh repeater row
|
|
7
|
+
* can be populated without pre-seeding the whole shape.
|
|
8
|
+
*/
|
|
9
|
+
type AnyRecord = Record<string, any>;
|
|
10
|
+
/** Read the value at `path` within `target`, or `undefined` if absent. */
|
|
11
|
+
export declare function getByPath(target: AnyRecord, path: string): any;
|
|
12
|
+
/**
|
|
13
|
+
* Write `value` at `path` within `target`, creating intermediate
|
|
14
|
+
* containers. A numeric next-segment creates an array; otherwise an
|
|
15
|
+
* object. Mutates `target` in place (form.data is reactive).
|
|
16
|
+
*/
|
|
17
|
+
export declare function setByPath(target: AnyRecord, path: string, value: any): void;
|
|
18
|
+
export {};
|