@omnitend/dashboard-for-laravel 0.42.2 → 0.44.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/dist/components/base/DFormSelect.vue.d.ts +1 -1
- package/dist/components/extended/DXChoiceField.vue.d.ts +3 -3
- package/dist/components/extended/DXCurrencyInput.vue.d.ts +2 -2
- package/dist/components/extended/DXDashboard.vue.d.ts +14 -6
- package/dist/components/extended/DXDashboardNavbar.vue.d.ts +12 -3
- package/dist/components/extended/DXDashboardSidebar.vue.d.ts +21 -1
- package/dist/components/extended/DXForm.vue.d.ts +66 -1
- package/dist/components/extended/DXFormErrorSummary.vue.d.ts +70 -0
- package/dist/components/extended/DXFormField.vue.d.ts +3 -0
- package/dist/components/extended/DXStackingTable.vue.d.ts +25 -0
- package/dist/components/extended/DXTable.vue.d.ts +20 -0
- package/dist/components/extended/DXTableEditorModal.vue.d.ts +14 -10
- package/dist/composables/useAsyncOptions.d.ts +14 -1
- package/dist/composables/useForm.d.ts +26 -0
- package/dist/dashboard-for-laravel.js +12002 -11223
- package/dist/dashboard-for-laravel.js.map +1 -1
- package/dist/dashboard-for-laravel.umd.cjs +8 -8
- package/dist/dashboard-for-laravel.umd.cjs.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/style.css +1 -1
- package/dist/types/index.d.ts +12 -0
- package/dist/types/navigation.d.ts +8 -0
- package/dist/utils/formErrorTargets.d.ts +86 -0
- package/dist/utils/pageScrollLock.d.ts +9 -0
- package/docs/public/api-reference.json +223 -9
- package/docs/public/docs-map.md +4 -2
- package/docs/public/llms.txt +4 -2
- package/package.json +9 -8
- package/resources/css/theme.scss +508 -36
- package/resources/js/components/base/DFormSelect.vue +5 -2
- package/resources/js/components/base/DModal.vue +20 -2
- package/resources/js/components/extended/DXChoiceField.vue +42 -26
- package/resources/js/components/extended/DXCurrencyInput.vue +3 -1
- package/resources/js/components/extended/DXDashboard.vue +236 -43
- package/resources/js/components/extended/DXDashboardNavbar.vue +23 -13
- package/resources/js/components/extended/DXDashboardSidebar.vue +103 -29
- package/resources/js/components/extended/DXField.vue +15 -9
- package/resources/js/components/extended/DXForm.vue +676 -28
- package/resources/js/components/extended/DXFormErrorSummary.vue +232 -0
- package/resources/js/components/extended/DXFormField.vue +11 -2
- package/resources/js/components/extended/DXRepeater.vue +30 -4
- package/resources/js/components/extended/DXStackingTable.vue +264 -0
- package/resources/js/components/extended/DXTable.vue +36 -4
- package/resources/js/components/extended/DXTableEditorModal.vue +29 -1
- package/resources/js/composables/useAsyncOptions.ts +30 -5
- package/resources/js/composables/useContainerWidth.ts +12 -3
- package/resources/js/composables/useForm.ts +196 -18
- package/resources/js/composables/useResourceEditor.ts +140 -107
- package/resources/js/index.ts +17 -0
- package/resources/js/types/index.ts +13 -0
- package/resources/js/types/navigation.ts +9 -0
- package/resources/js/utils/formErrorTargets.ts +317 -0
- package/resources/js/utils/pageScrollLock.ts +27 -0
- package/scripts/mcp-server.mjs +58 -6
package/dist/types/index.d.ts
CHANGED
|
@@ -297,6 +297,17 @@ export interface FieldDefinition {
|
|
|
297
297
|
* declared.
|
|
298
298
|
*/
|
|
299
299
|
submit?: boolean;
|
|
300
|
+
/**
|
|
301
|
+
* Extra validation-error keys this field owns (#194), for a field whose
|
|
302
|
+
* server-side errors arrive under keys other than its own: a span or
|
|
303
|
+
* component field that edits nested data, say. Patterns, where `*`
|
|
304
|
+
* matches exactly one dot segment: `["lines.*", "lines.*.*"]` claims
|
|
305
|
+
* `lines.0` and `lines.0.price` but not `lines` or `lines.0.a.b`.
|
|
306
|
+
* Checked before the usual matching (the field's own key, then any key
|
|
307
|
+
* nested under it), so it decides which field an error belongs to: the
|
|
308
|
+
* label it is listed under in the error summary and the tab it selects.
|
|
309
|
+
*/
|
|
310
|
+
errorKeys?: string[];
|
|
300
311
|
/**
|
|
301
312
|
* Conditionally show or hide this field. When omitted the field is
|
|
302
313
|
* always visible. Boolean or a function of the form model; evaluated
|
|
@@ -330,6 +341,7 @@ export interface BaseFieldDef {
|
|
|
330
341
|
readonly?: MaybeFn<boolean>;
|
|
331
342
|
plaintext?: MaybeFn<boolean>;
|
|
332
343
|
submit?: boolean;
|
|
344
|
+
errorKeys?: string[];
|
|
333
345
|
when?: MaybeFn<boolean>;
|
|
334
346
|
show?: () => boolean;
|
|
335
347
|
}
|
|
@@ -34,6 +34,14 @@ export type Navigation = NavigationGroup[];
|
|
|
34
34
|
* Shared by DXDashboard (which forwards it) and DXDashboardNavbar.
|
|
35
35
|
*/
|
|
36
36
|
export type NavbarSearchAlign = "start" | "center";
|
|
37
|
+
/**
|
|
38
|
+
* Colour scheme of the dashboard sidebar: `"light"` (the default: a white pane,
|
|
39
|
+
* tinted group headers, a green active item, Poppins) or `"dark"` (the navy
|
|
40
|
+
* rail dfl shipped before). Every colour comes from a `--dx-sidebar-*` custom
|
|
41
|
+
* property, so either can be rebranded in CSS. Shared by DXDashboard (which
|
|
42
|
+
* forwards it as `sidebarVariant`) and DXDashboardSidebar (`variant`).
|
|
43
|
+
*/
|
|
44
|
+
export type SidebarVariant = "light" | "dark";
|
|
37
45
|
/**
|
|
38
46
|
* What the navbar actions slot does below the `md` breakpoint: `"wrap"` moves
|
|
39
47
|
* it to its own full-width row (the bar grows), `"hide"` removes it entirely
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which field a validation-error key belongs to (#194).
|
|
3
|
+
*
|
|
4
|
+
* One pure function decides, so the error summary's rows, the tab a failed
|
|
5
|
+
* submit selects and the field it scrolls to can never disagree. No Vue: the
|
|
6
|
+
* caller injects visibility and label resolution, so DXForm can pass its own
|
|
7
|
+
* `when`/`context`-aware predicates and a standalone summary can use the
|
|
8
|
+
* defaults below.
|
|
9
|
+
*/
|
|
10
|
+
import type { FieldDefinition, FormTab } from "../types";
|
|
11
|
+
import type { ValidationErrors } from "../composables/useForm";
|
|
12
|
+
/** One error key and where it belongs. */
|
|
13
|
+
export interface ErrorTarget {
|
|
14
|
+
/** The key as the server sent it (`lines.0.price`). */
|
|
15
|
+
errorKey: string;
|
|
16
|
+
/** The server's messages for that key, as sent. */
|
|
17
|
+
messages: string[];
|
|
18
|
+
/**
|
|
19
|
+
* One display line per message: the message itself, or `"Label: message"`
|
|
20
|
+
* when the message does not already say which field it is about (see
|
|
21
|
+
* `resolveErrorTargets`).
|
|
22
|
+
*/
|
|
23
|
+
lines: string[];
|
|
24
|
+
/** The owning field's key, or `null` when no visible field owns it. */
|
|
25
|
+
fieldKey: string | null;
|
|
26
|
+
/** The tab holding the owning field, or `null` (flat form, or unowned). */
|
|
27
|
+
tabKey: string | null;
|
|
28
|
+
/** A readable name for the key: "Price (line 1)", "Delivery date". */
|
|
29
|
+
label: string;
|
|
30
|
+
}
|
|
31
|
+
export interface ResolveErrorTargetsOptions {
|
|
32
|
+
/** The form's field definitions. */
|
|
33
|
+
fields?: FieldDefinition[];
|
|
34
|
+
/**
|
|
35
|
+
* The form's tabs. When given (non-empty), only fields listed in a
|
|
36
|
+
* visible tab can own an error, as only those render. A tab key with no
|
|
37
|
+
* field definition (consumer-rendered content) can still own its own key
|
|
38
|
+
* and keys nested under it.
|
|
39
|
+
*/
|
|
40
|
+
tabs?: FormTab[];
|
|
41
|
+
/** Model for the default predicates and labels (form data + context). */
|
|
42
|
+
model?: Record<string, any>;
|
|
43
|
+
/** Field visibility. Default: `when` and `show` against `model`. */
|
|
44
|
+
isFieldVisible?: (field: FieldDefinition) => boolean;
|
|
45
|
+
/** Tab visibility. Default: the tab's `when` against `model`. */
|
|
46
|
+
isTabVisible?: (tab: FormTab) => boolean;
|
|
47
|
+
/**
|
|
48
|
+
* A field's label. Default: its `label`, called with `labelModel` when it
|
|
49
|
+
* is a function. `labelModel` is `model` for a form field and the ROW
|
|
50
|
+
* (`model.lines[0]`) for a repeater sub-field, as DXRepeater renders it.
|
|
51
|
+
* An empty result, or a label function that throws, falls back to the
|
|
52
|
+
* humanised key, so a broken label can never hide an error.
|
|
53
|
+
*/
|
|
54
|
+
resolveLabel?: (field: FieldDefinition, labelModel: Record<string, any>) => string | null | undefined;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* `delivery_date` → "Delivery date"; `lines.0.price` → "Lines price (line 1)".
|
|
58
|
+
* A trailing `id` word names the record, not the thing, so it is dropped
|
|
59
|
+
* (`supplier_id`, `supplierId` → "Supplier"); an `id` word that is the whole
|
|
60
|
+
* segment, or not at its end, reads "ID" (`id` → "ID"). Words that merely end
|
|
61
|
+
* in "id" (`paid`, `valid`) are untouched.
|
|
62
|
+
*/
|
|
63
|
+
export declare function humaniseErrorKey(key: string): string;
|
|
64
|
+
/**
|
|
65
|
+
* Resolve every key in `errors` to its owning field, tab and label, with the
|
|
66
|
+
* display line for each message. Rows come in tab order, then field order
|
|
67
|
+
* (the order of `tab.fieldKeys`, or of `fields` in a flat form), then the
|
|
68
|
+
* order the server sent the keys; keys no visible field owns come last.
|
|
69
|
+
*
|
|
70
|
+
* Ownership, first match wins: a field whose `errorKeys` pattern matches; a
|
|
71
|
+
* field whose key equals the error key; the field with the longest key that
|
|
72
|
+
* is a dot prefix of it (repeater rows, media maps). Hidden fields, and
|
|
73
|
+
* fields on hidden tabs or on no tab of a tabbed form, never own a key; it
|
|
74
|
+
* falls through to the next rule, or is unowned.
|
|
75
|
+
*
|
|
76
|
+
* Labels: the owning field's label; for `field.N.sub` the sub-field's label
|
|
77
|
+
* (when the field defines `fields` and one has that key) or the field's own,
|
|
78
|
+
* plus "(line N+1)"; for any other nested key (a media map's
|
|
79
|
+
* `image_media.<uuid>`) the field's label. An unowned key is humanised.
|
|
80
|
+
*
|
|
81
|
+
* Display lines: "Label: message", except that the label is left off when
|
|
82
|
+
* the message already contains it (case-insensitive) — unless the message
|
|
83
|
+
* contains a raw key (`_`, or a dot inside a word) or another row has the
|
|
84
|
+
* same message text, when the label is what tells the rows apart.
|
|
85
|
+
*/
|
|
86
|
+
export declare function resolveErrorTargets(errors: ValidationErrors | null | undefined, options?: ResolveErrorTargetsOptions): ErrorTarget[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The class on <html> that stops the page scrolling behind DXDashboard's open
|
|
3
|
+
* phone menu (styled in theme.scss, below `sm` only).
|
|
4
|
+
*/
|
|
5
|
+
export declare const PAGE_SCROLL_LOCK_CLASS = "dx-dashboard-menu-open";
|
|
6
|
+
/** Hold the page scroll lock for `owner`. Idempotent. */
|
|
7
|
+
export declare const acquirePageScrollLock: (owner: object) => void;
|
|
8
|
+
/** Release `owner`'s hold; the page unlocks once no owner holds it. Idempotent. */
|
|
9
|
+
export declare const releasePageScrollLock: (owner: object) => void;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generated": "2026-10-
|
|
2
|
+
"generated": "2026-10-09T16:42:41.495Z",
|
|
3
3
|
"package": {
|
|
4
4
|
"name": "@omnitend/dashboard-for-laravel",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.44.0"
|
|
6
6
|
},
|
|
7
7
|
"components": {
|
|
8
8
|
"base": [
|
|
@@ -907,7 +907,7 @@
|
|
|
907
907
|
"name": "DModal",
|
|
908
908
|
"category": "base",
|
|
909
909
|
"filePath": "resources/js/components/base/DModal.vue",
|
|
910
|
-
"description": "",
|
|
910
|
+
"description": "Wrapper around bootstrap-vue-next's BModal. Two defaults differ from bvn's: `size=\"lg\"` (room for horizontal form labels on desktop) and `fullscreen=\"sm\"`: below 576px the modal covers the whole screen, with the header and footer pinned and the body scrolling between them (Bootstrap's `.modal-fullscreen-sm-down`). A `size=\"sm\"` modal (a short confirmation) keeps the centred small dialog on phones too. Pass `fullscreen` explicitly to override either way, e.g. `:fullscreen=\"false\"` to opt out.",
|
|
911
911
|
"props": [],
|
|
912
912
|
"events": [],
|
|
913
913
|
"slots": [
|
|
@@ -1475,10 +1475,10 @@
|
|
|
1475
1475
|
"description": "Escape-hatch control props, already guard-merged by DXField."
|
|
1476
1476
|
},
|
|
1477
1477
|
{
|
|
1478
|
-
"name": "
|
|
1478
|
+
"name": "optionsPending",
|
|
1479
1479
|
"type": "boolean",
|
|
1480
1480
|
"required": false,
|
|
1481
|
-
"description": "
|
|
1481
|
+
"description": "The field's first async options load is still in flight. A searchable\nselect then shows \"Loading…\" instead of its value's raw id."
|
|
1482
1482
|
}
|
|
1483
1483
|
],
|
|
1484
1484
|
"events": [
|
|
@@ -1649,6 +1649,13 @@
|
|
|
1649
1649
|
"default": "true",
|
|
1650
1650
|
"description": "Only relevant when `collapsibleGroups` is on. `true` (default): only the\nactive-route group starts open and opening one closes the others\n(single-open accordion). `false`: all groups start open, toggled independently."
|
|
1651
1651
|
},
|
|
1652
|
+
{
|
|
1653
|
+
"name": "sidebarVariant",
|
|
1654
|
+
"type": "SidebarVariant",
|
|
1655
|
+
"required": false,
|
|
1656
|
+
"default": "'light'",
|
|
1657
|
+
"description": "Sidebar colour scheme, forwarded to DXDashboardSidebar as `variant`:\n`'light'` (default: white pane, tinted group headers, green active item,\nPoppins) or `'dark'` (the navy rail). Colours come from the\n`--dx-sidebar-*` custom properties, so either can be rebranded in CSS."
|
|
1658
|
+
},
|
|
1652
1659
|
{
|
|
1653
1660
|
"name": "storageKey",
|
|
1654
1661
|
"type": "string",
|
|
@@ -1725,7 +1732,7 @@
|
|
|
1725
1732
|
"type": "NavbarSearchAlign",
|
|
1726
1733
|
"required": false,
|
|
1727
1734
|
"default": "\"start\"",
|
|
1728
|
-
"description": "Horizontal alignment of the search slot content within its region\n(`\"start\"` = flush left, `\"center\"` = centred).
|
|
1735
|
+
"description": "Horizontal alignment of the search slot content within its region\n(`\"start\"` = flush left, `\"center\"` = centred). The region sits inline\nbetween the toggle/title and the user menu at every width."
|
|
1729
1736
|
},
|
|
1730
1737
|
{
|
|
1731
1738
|
"name": "actionsOnMobile",
|
|
@@ -1740,6 +1747,20 @@
|
|
|
1740
1747
|
"required": false,
|
|
1741
1748
|
"default": "\"User menu\"",
|
|
1742
1749
|
"description": "Accessible name for the user-menu trigger. Without one, a screen reader\nannounces the trigger as the avatar's initial (\"J\") rather than as a menu."
|
|
1750
|
+
},
|
|
1751
|
+
{
|
|
1752
|
+
"name": "sidebarExpanded",
|
|
1753
|
+
"type": "boolean",
|
|
1754
|
+
"required": false,
|
|
1755
|
+
"default": "undefined",
|
|
1756
|
+
"description": "Whether the sidebar the toggle controls is showing, exposed as the\ntoggle's `aria-expanded`. Left unset, the toggle carries none.\nDXDashboard sets it."
|
|
1757
|
+
},
|
|
1758
|
+
{
|
|
1759
|
+
"name": "sidebarId",
|
|
1760
|
+
"type": "string",
|
|
1761
|
+
"required": false,
|
|
1762
|
+
"default": "\"\"",
|
|
1763
|
+
"description": "`id` of the sidebar the toggle controls (its `aria-controls`)."
|
|
1743
1764
|
}
|
|
1744
1765
|
],
|
|
1745
1766
|
"events": [
|
|
@@ -1757,7 +1778,7 @@
|
|
|
1757
1778
|
},
|
|
1758
1779
|
{
|
|
1759
1780
|
"name": "search",
|
|
1760
|
-
"description": "Search input or component.
|
|
1781
|
+
"description": "Search input or component. Fills the middle of the bar at every width, aligned per `searchAlign`. The region is a size container named `dx-navbar-search`; a `<kbd>` hint inside it is hidden when it is narrower than 16rem.",
|
|
1761
1782
|
"bindings": []
|
|
1762
1783
|
},
|
|
1763
1784
|
{
|
|
@@ -1879,13 +1900,37 @@
|
|
|
1879
1900
|
"required": false,
|
|
1880
1901
|
"default": "true",
|
|
1881
1902
|
"description": "Only relevant when `collapsibleGroups` is on.\n`true` (default): only the active-route group starts open, and opening one\ngroup closes the others (single-open accordion).\n`false`: all groups start open and toggle independently."
|
|
1903
|
+
},
|
|
1904
|
+
{
|
|
1905
|
+
"name": "variant",
|
|
1906
|
+
"type": "SidebarVariant",
|
|
1907
|
+
"required": false,
|
|
1908
|
+
"default": "'light'",
|
|
1909
|
+
"description": "Colour scheme: `'light'` (default) or `'dark'`. Colours come from the\n`--dx-sidebar-*` custom properties (see the theming guide), so either\nscheme can be rebranded in CSS."
|
|
1910
|
+
},
|
|
1911
|
+
{
|
|
1912
|
+
"name": "phoneMenu",
|
|
1913
|
+
"type": "boolean",
|
|
1914
|
+
"required": false,
|
|
1915
|
+
"default": "false",
|
|
1916
|
+
"description": "Below `sm`, show the open sidebar as a full-screen menu over the page,\nwith a close button (which emits `close`), instead of a rail beside it;\nhidden there until opened. The owner must answer `close`, Escape and\n`navigate`: DXDashboard sets this and does. Off by default, so a\nstandalone sidebar keeps its rail on phones."
|
|
1882
1917
|
}
|
|
1883
1918
|
],
|
|
1884
1919
|
"events": [
|
|
1920
|
+
{
|
|
1921
|
+
"name": "close",
|
|
1922
|
+
"description": "Emitted by the close button shown below `sm`, where the open sidebar covers the screen.",
|
|
1923
|
+
"properties": []
|
|
1924
|
+
},
|
|
1885
1925
|
{
|
|
1886
1926
|
"name": "toggle",
|
|
1887
1927
|
"description": "Emitted to request toggling the sidebar's collapsed/expanded state.",
|
|
1888
1928
|
"properties": []
|
|
1929
|
+
},
|
|
1930
|
+
{
|
|
1931
|
+
"name": "navigate",
|
|
1932
|
+
"description": "Emitted when a link anywhere in the sidebar is followed (a plain click,\nnot one that opens a new tab): the navigation, including links rendered\nthrough the `link` slot, and the `brand` and `footer` slots. DXDashboard\nuses it to close the full-screen menu on a phone.",
|
|
1933
|
+
"properties": []
|
|
1889
1934
|
}
|
|
1890
1935
|
],
|
|
1891
1936
|
"slots": [
|
|
@@ -2485,6 +2530,32 @@
|
|
|
2485
2530
|
"type": "LabelCols",
|
|
2486
2531
|
"required": false,
|
|
2487
2532
|
"description": "Label column width for horizontal layout (mirrors BFormGroup's\n`labelCols`/`labelCols*` props). Overridable per-field via\n`field.labelCols`. Ignored when `layout` is \"vertical\". Omitted (here\nand on the field): the label takes `--dx-form-label-width` (45%) from\n`sm` up and stacks above the input below `sm`."
|
|
2533
|
+
},
|
|
2534
|
+
{
|
|
2535
|
+
"name": "errorSummary",
|
|
2536
|
+
"type": "union",
|
|
2537
|
+
"required": false,
|
|
2538
|
+
"default": "\"footer\"",
|
|
2539
|
+
"description": "Where to list what the last failed submit returned (`form.submitFailure`:\nthe server's message and every validation message, with readable\nlabels):\n\n- `\"footer\"` (default) — directly above the submit button, below any\n tabs, next to the control the user just pressed.\n- `\"top\"` — above the fields, where the form-level alert sits.\n- `\"external\"` — the host renders a `DXFormErrorSummary` of its own\n elsewhere (beside a submit button outside the form, as DXTable's\n modal does). DXForm renders neither a summary nor, while a failure\n is listed, the form-level alert.\n- `false` — no summary; the form-level alert behaves as before.\n\nWhile a summary shows a failure the form-level alert does not render,\nso a failure shows exactly one alert. Each row naming a visible field is\na button that selects the field's tab and focuses it."
|
|
2540
|
+
},
|
|
2541
|
+
{
|
|
2542
|
+
"name": "errorSummaryTitle",
|
|
2543
|
+
"type": "string",
|
|
2544
|
+
"required": false,
|
|
2545
|
+
"description": "The summary's heading when the failure has field errors (default\n\"Couldn't save. Please check:\"). A failure with none (a message-only\n422, a 500) is headed by the server's message instead."
|
|
2546
|
+
},
|
|
2547
|
+
{
|
|
2548
|
+
"name": "errorSummaryOtherTitle",
|
|
2549
|
+
"type": "string",
|
|
2550
|
+
"required": false,
|
|
2551
|
+
"description": "The summary's sub-heading over the rows no visible field owns (default\n\"Other problems\"), shown only when some rows ARE owned."
|
|
2552
|
+
},
|
|
2553
|
+
{
|
|
2554
|
+
"name": "scrollToError",
|
|
2555
|
+
"type": "boolean",
|
|
2556
|
+
"required": false,
|
|
2557
|
+
"default": "true",
|
|
2558
|
+
"description": "After a failed submit, scroll the first field with an error into view\n(once its tab is selected and rendered). Never moves focus. On by\ndefault."
|
|
2488
2559
|
}
|
|
2489
2560
|
],
|
|
2490
2561
|
"events": [
|
|
@@ -2600,6 +2671,85 @@
|
|
|
2600
2671
|
],
|
|
2601
2672
|
"methods": []
|
|
2602
2673
|
},
|
|
2674
|
+
{
|
|
2675
|
+
"name": "DXFormErrorSummary",
|
|
2676
|
+
"category": "extended",
|
|
2677
|
+
"filePath": "resources/js/components/extended/DXFormErrorSummary.vue",
|
|
2678
|
+
"description": "Lists everything the last failed submit of a `useForm` returned: a heading, then one row per validation message with a readable label (\"Price (line 1): Must be positive.\"). The heading is `title` (\"Couldn't save. Please check:\") when the failure has field errors, and the server's message when it has none (a message-only 422, a 500, a network failure), since then the message is all there is. Built from `form.submitFailure`, so it survives field edits and `clearError`, and disappears when the next submit starts or one succeeds. Renders nothing before a failure. A row whose key belongs to a visible field is a button that emits `select-target`, for the host to select the field's tab and focus it; a key no visible field owns is listed as plain text, after the owned rows, under `otherTitle` (\"Other problems\") when both kinds are present. Place it next to the submit control.",
|
|
2679
|
+
"props": [
|
|
2680
|
+
{
|
|
2681
|
+
"name": "form",
|
|
2682
|
+
"type": "union",
|
|
2683
|
+
"required": true,
|
|
2684
|
+
"description": "The form: a `useForm` return or a `defineForm` return."
|
|
2685
|
+
},
|
|
2686
|
+
{
|
|
2687
|
+
"name": "fields",
|
|
2688
|
+
"type": "Array",
|
|
2689
|
+
"required": false,
|
|
2690
|
+
"description": "Field definitions (optional when `form` is a defineForm return)."
|
|
2691
|
+
},
|
|
2692
|
+
{
|
|
2693
|
+
"name": "tabs",
|
|
2694
|
+
"type": "Array",
|
|
2695
|
+
"required": false,
|
|
2696
|
+
"description": "The form's tabs, so rows follow tab order and know their tab."
|
|
2697
|
+
},
|
|
2698
|
+
{
|
|
2699
|
+
"name": "context",
|
|
2700
|
+
"type": "Record",
|
|
2701
|
+
"required": false,
|
|
2702
|
+
"description": "Extra context merged under the form data when evaluating `when` and\nfunction labels, as on DXForm."
|
|
2703
|
+
},
|
|
2704
|
+
{
|
|
2705
|
+
"name": "isFieldVisible",
|
|
2706
|
+
"type": "TSFunctionType",
|
|
2707
|
+
"required": false,
|
|
2708
|
+
"description": "Field visibility, replacing the default (`when`/`show` against form\ndata + `context`). A host form passes its own predicate so the summary\nagrees with what it renders."
|
|
2709
|
+
},
|
|
2710
|
+
{
|
|
2711
|
+
"name": "isTabVisible",
|
|
2712
|
+
"type": "TSFunctionType",
|
|
2713
|
+
"required": false,
|
|
2714
|
+
"description": "Tab visibility, replacing the default (the tab's `when`)."
|
|
2715
|
+
},
|
|
2716
|
+
{
|
|
2717
|
+
"name": "resolveLabel",
|
|
2718
|
+
"type": "TSFunctionType",
|
|
2719
|
+
"required": false,
|
|
2720
|
+
"description": "A field's label, replacing the default (its `label`, resolved against\n`labelModel`: the form model, or the row for a repeater sub-field)."
|
|
2721
|
+
},
|
|
2722
|
+
{
|
|
2723
|
+
"name": "targets",
|
|
2724
|
+
"type": "union",
|
|
2725
|
+
"required": false,
|
|
2726
|
+
"description": "Rows already resolved by the host (from `resolveErrorTargets` over\n`form.submitFailure.errors`). When given, the summary lists these and\nresolves nothing itself; the message still comes from\n`form.submitFailure`, and nothing renders while that is null."
|
|
2727
|
+
},
|
|
2728
|
+
{
|
|
2729
|
+
"name": "title",
|
|
2730
|
+
"type": "string",
|
|
2731
|
+
"required": false,
|
|
2732
|
+
"default": "\"Couldn't save. Please check:\"",
|
|
2733
|
+
"description": "The heading when the failure has at least one field error. The\nserver's own message is not used then: Laravel's default 422 message\nis the first error plus \"(and N more errors)\", which repeats the first\nrow. A failure with no field errors (a message-only 422, a 500, a\nnetwork failure) keeps the server's message as the heading, as it is\nthe only information."
|
|
2734
|
+
},
|
|
2735
|
+
{
|
|
2736
|
+
"name": "otherTitle",
|
|
2737
|
+
"type": "string",
|
|
2738
|
+
"required": false,
|
|
2739
|
+
"default": "\"Other problems\"",
|
|
2740
|
+
"description": "The sub-heading over the rows no visible field owns, listed after the\nowned rows. Shown only when there are both kinds; when no row is owned\nthey are listed under the heading alone."
|
|
2741
|
+
}
|
|
2742
|
+
],
|
|
2743
|
+
"events": [
|
|
2744
|
+
{
|
|
2745
|
+
"name": "select-target",
|
|
2746
|
+
"description": "A row was clicked: select `tabKey` (if any) and focus `fieldKey`.",
|
|
2747
|
+
"properties": []
|
|
2748
|
+
}
|
|
2749
|
+
],
|
|
2750
|
+
"slots": [],
|
|
2751
|
+
"methods": []
|
|
2752
|
+
},
|
|
2603
2753
|
{
|
|
2604
2754
|
"name": "DXFormField",
|
|
2605
2755
|
"category": "extended",
|
|
@@ -2654,6 +2804,10 @@
|
|
|
2654
2804
|
{
|
|
2655
2805
|
"name": "model",
|
|
2656
2806
|
"title": "binding"
|
|
2807
|
+
},
|
|
2808
|
+
{
|
|
2809
|
+
"name": "targetAttrs",
|
|
2810
|
+
"title": "binding"
|
|
2657
2811
|
}
|
|
2658
2812
|
]
|
|
2659
2813
|
},
|
|
@@ -3157,6 +3311,35 @@
|
|
|
3157
3311
|
],
|
|
3158
3312
|
"methods": []
|
|
3159
3313
|
},
|
|
3314
|
+
{
|
|
3315
|
+
"name": "DXStackingTable",
|
|
3316
|
+
"category": "extended",
|
|
3317
|
+
"filePath": "resources/js/components/extended/DXStackingTable.vue",
|
|
3318
|
+
"description": "",
|
|
3319
|
+
"props": [
|
|
3320
|
+
{
|
|
3321
|
+
"name": "stackBelow",
|
|
3322
|
+
"type": "number",
|
|
3323
|
+
"required": false,
|
|
3324
|
+
"default": "576",
|
|
3325
|
+
"description": "Stack when the wrapper's content width is below this many px. 576 is\nBootstrap's `sm` breakpoint, but measured on the container."
|
|
3326
|
+
}
|
|
3327
|
+
],
|
|
3328
|
+
"events": [],
|
|
3329
|
+
"slots": [
|
|
3330
|
+
{
|
|
3331
|
+
"name": "default",
|
|
3332
|
+
"description": "The consumer's own `<table>`, as the wrapper's direct child.",
|
|
3333
|
+
"bindings": [
|
|
3334
|
+
{
|
|
3335
|
+
"name": "stacked",
|
|
3336
|
+
"title": "binding"
|
|
3337
|
+
}
|
|
3338
|
+
]
|
|
3339
|
+
}
|
|
3340
|
+
],
|
|
3341
|
+
"methods": []
|
|
3342
|
+
},
|
|
3160
3343
|
{
|
|
3161
3344
|
"name": "DXStatCard",
|
|
3162
3345
|
"category": "extended",
|
|
@@ -3614,6 +3797,18 @@
|
|
|
3614
3797
|
"required": false,
|
|
3615
3798
|
"description": "Override the modal's Delete button label (default: \"Delete {item}\")."
|
|
3616
3799
|
},
|
|
3800
|
+
{
|
|
3801
|
+
"name": "errorSummaryTitle",
|
|
3802
|
+
"type": "string",
|
|
3803
|
+
"required": false,
|
|
3804
|
+
"description": "Heading of the modal's failed-save summary when the failure has field\nerrors (default \"Couldn't save. Please check:\"). A failure with none\nis headed by the server's message instead."
|
|
3805
|
+
},
|
|
3806
|
+
{
|
|
3807
|
+
"name": "errorSummaryOtherTitle",
|
|
3808
|
+
"type": "string",
|
|
3809
|
+
"required": false,
|
|
3810
|
+
"description": "Sub-heading over the summary rows no edit field owns (default \"Other\nproblems\"), shown only when some rows ARE owned."
|
|
3811
|
+
},
|
|
3617
3812
|
{
|
|
3618
3813
|
"name": "editUrl",
|
|
3619
3814
|
"type": "string",
|
|
@@ -3695,6 +3890,13 @@
|
|
|
3695
3890
|
"required": false,
|
|
3696
3891
|
"description": "Whether a given row is actionable. Only relevant when rows are clickable\n(an `editFields` modal or a `row-clicked` listener). A row this returns\n`false` for gets no pointer cursor, no hover highlight, and does not fire\n`row-clicked` or open the edit modal — so a row that isn't clickable\ndoesn't *look* clickable, and a click on it can't quietly do something."
|
|
3697
3892
|
},
|
|
3893
|
+
{
|
|
3894
|
+
"name": "editOnRowClick",
|
|
3895
|
+
"type": "boolean",
|
|
3896
|
+
"required": false,
|
|
3897
|
+
"default": "true",
|
|
3898
|
+
"description": "Whether clicking a row opens the edit modal (when `editFields` are set).\nDefaults to `true`. Set `false` when `editFields` exist only for the\ncreate modal (`openCreate()` / the create button) and a row click does\nsomething else, such as opening the record's own page from `row-clicked`:\nthe row then emits `row-clicked` without also opening the edit modal, and\nonly a `row-clicked` listener makes rows look clickable (#200)."
|
|
3899
|
+
},
|
|
3698
3900
|
{
|
|
3699
3901
|
"name": "clientSide",
|
|
3700
3902
|
"type": "boolean",
|
|
@@ -4003,6 +4205,18 @@
|
|
|
4003
4205
|
"type": "string",
|
|
4004
4206
|
"required": false,
|
|
4005
4207
|
"description": "Override the Delete button label."
|
|
4208
|
+
},
|
|
4209
|
+
{
|
|
4210
|
+
"name": "errorSummaryTitle",
|
|
4211
|
+
"type": "string",
|
|
4212
|
+
"required": false,
|
|
4213
|
+
"description": "The footer summary's heading for a failure with field errors."
|
|
4214
|
+
},
|
|
4215
|
+
{
|
|
4216
|
+
"name": "errorSummaryOtherTitle",
|
|
4217
|
+
"type": "string",
|
|
4218
|
+
"required": false,
|
|
4219
|
+
"description": "The footer summary's sub-heading over rows no field owns."
|
|
4006
4220
|
}
|
|
4007
4221
|
],
|
|
4008
4222
|
"events": [
|
|
@@ -4365,8 +4579,8 @@
|
|
|
4365
4579
|
]
|
|
4366
4580
|
},
|
|
4367
4581
|
"stats": {
|
|
4368
|
-
"totalComponents":
|
|
4582
|
+
"totalComponents": 90,
|
|
4369
4583
|
"baseComponents": 60,
|
|
4370
|
-
"extendedComponents":
|
|
4584
|
+
"extendedComponents": 30
|
|
4371
4585
|
}
|
|
4372
4586
|
}
|
package/docs/public/docs-map.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Documentation Map
|
|
2
2
|
|
|
3
3
|
> Auto-generated hierarchical overview of all documentation
|
|
4
|
-
> Last updated: 2026-10-
|
|
4
|
+
> Last updated: 2026-10-09T16:42:41.546Z
|
|
5
5
|
|
|
6
6
|
This file provides a complete map of all available documentation for AI agents and developers.
|
|
7
7
|
|
|
@@ -79,9 +79,11 @@ This file provides a complete map of all available documentation for AI agents a
|
|
|
79
79
|
- [DXDashboardSidebar](/components/extended/DXDashboardSidebar): A collapsible sidebar navigation component for Laravel dashboards with support for navigation groups
|
|
80
80
|
- [DXField](/components/extended/DXField): The single-field renderer that powers `DXForm` and
|
|
81
81
|
- [DXForm](/components/extended/DXForm): The canonical form renderer. Drive it with field definitions; add `tabs` when
|
|
82
|
+
- [DXFormErrorSummary](/components/extended/DXFormErrorSummary): Lists everything the last failed submit of a `useForm` returned: a heading,
|
|
82
83
|
- [DXNumberStepper](/components/extended/DXNumberStepper): A number input between a decrease and an increase button, `[ − ][ 12 ][ + ]`,
|
|
83
84
|
- [DXRepeater](/components/extended/DXRepeater): A repeatable sub-form (field array) primitive for nested, dynamic collections —
|
|
84
85
|
- [DXSaveButton](/components/extended/DXSaveButton): A save button that confirms the save in place. While saving it shows
|
|
86
|
+
- [DXStackingTable](/components/extended/DXStackingTable): A wrapper for a table you write yourself (an order's lines with price and
|
|
85
87
|
- [DXStatCard](/components/extended/DXStatCard): A KPI / stat tile: a big formatted value with a title, optional subtitle, an
|
|
86
88
|
- [DXSwitch](/components/extended/DXSwitch): A "filled box" toggle switch built on `DFormCheckbox`: a bordered box sized like
|
|
87
89
|
- [DXTable](/components/extended/DXTable): A comprehensive data table component with built-in pagination, sorting, filtering, and CRUD operatio
|
|
@@ -104,4 +106,4 @@ This file provides a complete map of all available documentation for AI agents a
|
|
|
104
106
|
|
|
105
107
|
---
|
|
106
108
|
|
|
107
|
-
**Total Pages**:
|
|
109
|
+
**Total Pages**: 82
|
package/docs/public/llms.txt
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Vue 3 dashboard components for Laravel with Bootstrap Vue Next
|
|
4
4
|
>
|
|
5
|
-
> A dual-package library (NPM + Composer) providing
|
|
5
|
+
> A dual-package library (NPM + Composer) providing 80 Vue 3 components for building Laravel dashboards with Bootstrap Vue Next.
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
@@ -84,7 +84,7 @@ Lightweight type-safe wrappers around Bootstrap Vue Next components providing AP
|
|
|
84
84
|
- [DToaster](/components/base/dtoaster): Bootstrap Vue Next Toaster wrapper
|
|
85
85
|
- [DTooltip](/components/base/dtooltip): Bootstrap Vue Next Tooltip wrapper
|
|
86
86
|
|
|
87
|
-
## Extended Components (
|
|
87
|
+
## Extended Components (20 components)
|
|
88
88
|
|
|
89
89
|
Custom dashboard components with advanced functionality beyond Bootstrap Vue Next.
|
|
90
90
|
|
|
@@ -96,11 +96,13 @@ Custom dashboard components with advanced functionality beyond Bootstrap Vue Nex
|
|
|
96
96
|
- [DXField](/components/extended/dxfield): Single-field renderer for any field type with value/span/info/hint slots
|
|
97
97
|
- [DXFieldLabel](/components/extended/dxfieldlabel): Extended dashboard component
|
|
98
98
|
- [DXForm](/components/extended/dxform): Form renderer driven by field definitions, with optional tabs, conditional fields, per-field slots, async options, nested repeaters, and auto error-tab switching
|
|
99
|
+
- [DXFormErrorSummary](/components/extended/dxformerrorsummary): One alert listing every message of the last failed submit, with readable labels, placed next to the submit control
|
|
99
100
|
- [DXLoading](/components/extended/dxloading): Extended dashboard component
|
|
100
101
|
- [DXModalActions](/components/extended/dxmodalactions): Extended dashboard component
|
|
101
102
|
- [DXNumberStepper](/components/extended/dxnumberstepper): Extended dashboard component
|
|
102
103
|
- [DXRepeater](/components/extended/dxrepeater): Repeatable nested sub-form (field array) primitive
|
|
103
104
|
- [DXSaveButton](/components/extended/dxsavebutton): Extended dashboard component
|
|
105
|
+
- [DXStackingTable](/components/extended/dxstackingtable): Extended dashboard component
|
|
104
106
|
- [DXStatCard](/components/extended/dxstatcard): Extended dashboard component
|
|
105
107
|
- [DXSwitch](/components/extended/dxswitch): Extended dashboard component
|
|
106
108
|
- [DXTable](/components/extended/dxtable): Data table with pagination, filtering, and sorting
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omnitend/dashboard-for-laravel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.44.0",
|
|
4
4
|
"description": "Vue 3 dashboard components for Laravel with Bootstrap Vue Next",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/dashboard-for-laravel.umd.cjs",
|
|
@@ -55,12 +55,13 @@
|
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"@inertiajs/vue3": "^2.0.0",
|
|
58
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
58
59
|
"chart.js": "^4.4.0",
|
|
59
60
|
"vue": "^3.5.13",
|
|
60
61
|
"vue-chartjs": "^5.3.0"
|
|
61
62
|
},
|
|
62
63
|
"peerDependenciesMeta": {
|
|
63
|
-
"
|
|
64
|
+
"@modelcontextprotocol/sdk": {
|
|
64
65
|
"optional": true
|
|
65
66
|
},
|
|
66
67
|
"chart.js": {
|
|
@@ -71,13 +72,8 @@
|
|
|
71
72
|
}
|
|
72
73
|
},
|
|
73
74
|
"dependencies": {
|
|
74
|
-
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
75
75
|
"bootstrap-vue-next": "^0.45.6",
|
|
76
|
-
"
|
|
77
|
-
"pluralize": "^8.0.0",
|
|
78
|
-
"rehype-autolink-headings": "^7.1.0",
|
|
79
|
-
"rehype-slug": "^6.0.0",
|
|
80
|
-
"vue-docgen-api": "^4.79.2"
|
|
76
|
+
"pluralize": "^8.0.0"
|
|
81
77
|
},
|
|
82
78
|
"devDependencies": {
|
|
83
79
|
"@astrojs/markdown-remark": "^7.2.0",
|
|
@@ -87,6 +83,7 @@
|
|
|
87
83
|
"@iconify-json/lucide": "^1.2.71",
|
|
88
84
|
"@iconify/json": "^2.2.397",
|
|
89
85
|
"@inertiajs/vue3": "^2.2.15",
|
|
86
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
90
87
|
"@types/pluralize": "^0.0.33",
|
|
91
88
|
"@vitejs/plugin-vue": "^5.2.4",
|
|
92
89
|
"@vitest/browser": "^4.1.8",
|
|
@@ -97,8 +94,11 @@
|
|
|
97
94
|
"bootstrap-icons": "^1.13.1",
|
|
98
95
|
"chart.js": "^4.5.1",
|
|
99
96
|
"happy-dom": "^20.0.8",
|
|
97
|
+
"highlight.js": "^11.11.1",
|
|
100
98
|
"pagefind": "^1.4.0",
|
|
101
99
|
"playwright": "^1.56.1",
|
|
100
|
+
"rehype-autolink-headings": "^7.1.0",
|
|
101
|
+
"rehype-slug": "^6.0.0",
|
|
102
102
|
"sass-embedded": "^1.93.2",
|
|
103
103
|
"typescript": "^5.9.3",
|
|
104
104
|
"unplugin-icons": "^22.5.0",
|
|
@@ -107,6 +107,7 @@
|
|
|
107
107
|
"vitest": "^4.1.8",
|
|
108
108
|
"vitest-browser-vue": "^2.0.0",
|
|
109
109
|
"vue-chartjs": "^5.3.3",
|
|
110
|
+
"vue-docgen-api": "^4.79.2",
|
|
110
111
|
"vue-tsc": "^2.2.12"
|
|
111
112
|
},
|
|
112
113
|
"keywords": [
|