@omnitend/dashboard-for-laravel 0.45.0 → 0.46.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.
Files changed (39) hide show
  1. package/dist/assets/IBMPlexSans-Bold-Latin1-914f1400.woff2 +0 -0
  2. package/dist/assets/IBMPlexSans-Medium-Latin1-b5610af0.woff2 +0 -0
  3. package/dist/assets/IBMPlexSans-Regular-Latin1-b5ad7bd3.woff2 +0 -0
  4. package/dist/assets/IBMPlexSans-SemiBold-Latin1-fff0ab3a.woff2 +0 -0
  5. package/dist/components/base/DFormFile.vue.d.ts +17 -0
  6. package/dist/components/base/DFormValidFeedback.vue.d.ts +12 -0
  7. package/dist/components/extended/DXDashboard.vue.d.ts +95 -111
  8. package/dist/components/extended/DXDashboardNavbar.vue.d.ts +2 -36
  9. package/dist/components/extended/DXDashboardSidebar.vue.d.ts +60 -79
  10. package/dist/components/extended/DXTable.vue.d.ts +10 -1
  11. package/dist/dashboard-for-laravel.js +8176 -7953
  12. package/dist/dashboard-for-laravel.js.map +1 -1
  13. package/dist/dashboard-for-laravel.umd.cjs +7 -7
  14. package/dist/dashboard-for-laravel.umd.cjs.map +1 -1
  15. package/dist/index.d.ts +3 -1
  16. package/dist/style.css +2 -2
  17. package/dist/types/navigation.d.ts +153 -3
  18. package/dist/utils/statCardFit.d.ts +19 -0
  19. package/docs/public/api-reference.json +48 -6
  20. package/docs/public/docs-map.md +4 -2
  21. package/docs/public/llms.txt +4 -2
  22. package/package.json +3 -2
  23. package/resources/css/theme.scss +264 -4
  24. package/resources/fonts/ibm-plex-sans/IBMPlexSans-Bold-Latin1.woff2 +0 -0
  25. package/resources/fonts/ibm-plex-sans/IBMPlexSans-Medium-Latin1.woff2 +0 -0
  26. package/resources/fonts/ibm-plex-sans/IBMPlexSans-Regular-Latin1.woff2 +0 -0
  27. package/resources/fonts/ibm-plex-sans/IBMPlexSans-SemiBold-Latin1.woff2 +0 -0
  28. package/resources/fonts/ibm-plex-sans/OFL.txt +93 -0
  29. package/resources/fonts/ibm-plex-sans/SOURCE.txt +18 -0
  30. package/resources/js/components/base/DFormFile.vue +103 -0
  31. package/resources/js/components/base/DFormValidFeedback.vue +16 -0
  32. package/resources/js/components/extended/DXDashboard.vue +41 -18
  33. package/resources/js/components/extended/DXDashboardNavbar.vue +9 -1
  34. package/resources/js/components/extended/DXDashboardSidebar.vue +25 -3
  35. package/resources/js/components/extended/DXStatCard.vue +154 -11
  36. package/resources/js/components/extended/DXTable.vue +58 -5
  37. package/resources/js/index.ts +9 -0
  38. package/resources/js/types/navigation.ts +175 -3
  39. package/resources/js/utils/statCardFit.ts +210 -0
@@ -7,7 +7,13 @@ export interface NavigationItem {
7
7
  active?: boolean;
8
8
  visible?: boolean;
9
9
  }
10
- export interface NavigationGroup {
10
+ /**
11
+ * A group of sidebar links. `TItem` is the app's own item type, for menus whose
12
+ * items carry extra keys (a permission, a route name): DXDashboard and
13
+ * DXDashboardSidebar infer it from the `navigation` prop, so the `link` slot's
14
+ * `item` has those keys too. Defaults to `NavigationItem`.
15
+ */
16
+ export interface NavigationGroup<TItem extends NavigationItem = NavigationItem> {
11
17
  label?: string;
12
18
  /**
13
19
  * Stable identifier for the group's collapsible open/closed state. Defaults
@@ -16,7 +22,7 @@ export interface NavigationGroup {
16
22
  * state attached to the right group.
17
23
  */
18
24
  key?: string;
19
- items: NavigationItem[];
25
+ items: TItem[];
20
26
  /**
21
27
  * Per-group override for the sidebar's `collapsibleGroups` behaviour.
22
28
  * Set to `false` to keep a group permanently expanded (no toggle header)
@@ -27,7 +33,23 @@ export interface NavigationGroup {
27
33
  collapsed?: boolean;
28
34
  visible?: boolean;
29
35
  }
30
- export type Navigation = NavigationGroup[];
36
+ /** The sidebar's navigation: its groups, in order. See `NavigationGroup` for `TItem`. */
37
+ export type Navigation<TItem extends NavigationItem = NavigationItem> = NavigationGroup<TItem>[];
38
+ /**
39
+ * The item type of a navigation, as the `link` slot's `item` receives it:
40
+ * `NavigationItemOf<Navigation<AppItem>>` is `AppItem`. An `any` navigation
41
+ * (untyped page props) gives `any`, and an empty `[]` gives `NavigationItem`.
42
+ *
43
+ * DXDashboard and DXDashboardSidebar are generic over the whole navigation
44
+ * (`TNavigation`) and derive the item from it, rather than generic over the
45
+ * item: TypeScript infers `any` for a type parameter that IS the prop's type,
46
+ * but not for one nested inside it (`{ items: TItem[] }[]`), where an `any`
47
+ * navigation would have fallen back to `NavigationItem` and rejected the app's
48
+ * extra keys.
49
+ */
50
+ export type NavigationItemOf<TNavigation extends Navigation> = [
51
+ TNavigation[number]["items"][number]
52
+ ] extends [never] ? NavigationItem : TNavigation[number]["items"][number];
31
53
  /**
32
54
  * Horizontal alignment of the navbar search slot content within its region:
33
55
  * `"start"` = flush left (after the title from `md` up), `"center"` = centred.
@@ -49,3 +71,131 @@ export type SidebarVariant = "light" | "dark";
49
71
  * Shared by DXDashboard (which forwards it) and DXDashboardNavbar.
50
72
  */
51
73
  export type NavbarActionsOnMobile = "wrap" | "hide";
74
+ /**
75
+ * The signed-in user DXDashboardNavbar (and DXDashboard, which forwards it)
76
+ * shows in the avatar dropdown. Extra keys are allowed and reach the
77
+ * user-menu slots.
78
+ */
79
+ export interface DashboardUser {
80
+ name: string;
81
+ email: string;
82
+ [key: string]: any;
83
+ }
84
+ /** A slot that receives no props. */
85
+ type NoSlotProps = Record<never, never>;
86
+ /** Slots of DXDashboardNavbar, with their slot props. All are optional. */
87
+ export interface DashboardNavbarSlots {
88
+ /** Custom hamburger/menu icon. Defaults to a three-line SVG. */
89
+ "menu-icon"?(props: NoSlotProps): any;
90
+ /**
91
+ * Search input or component. Fills the middle of the bar at every width,
92
+ * aligned per `searchAlign`. The region is a size container named
93
+ * `dx-navbar-search`; a `<kbd>` hint inside it is hidden when it is
94
+ * narrower than 16rem.
95
+ */
96
+ "search"?(props: NoSlotProps): any;
97
+ /**
98
+ * Page-level primary actions (e.g. a Create button). Right-aligned next to
99
+ * the user menu from `md` up; below, wraps to its own full-width row or is
100
+ * hidden entirely per `actionsOnMobile`.
101
+ */
102
+ "actions"?(props: {
103
+ /** The current page title, for context. */
104
+ pageTitle: string;
105
+ }): any;
106
+ /** Replaces the entire user menu (the default avatar dropdown). */
107
+ "user-menu"?(props: {
108
+ /** The signed-in user; `null` for a guest. */
109
+ user: DashboardUser | null;
110
+ }): any;
111
+ /**
112
+ * Custom user avatar/icon in the dropdown trigger. To decorate the default
113
+ * avatar (e.g. add a notification dot) rather than replace it, render
114
+ * `DXUserAvatar`. Only rendered for a signed-in user.
115
+ */
116
+ "user-icon"?(props: {
117
+ /** The first letter of the user's name. */
118
+ initial: string;
119
+ /** The signed-in user. */
120
+ user: DashboardUser;
121
+ }): any;
122
+ /** Items for the default user dropdown menu. Only rendered for a signed-in user. */
123
+ "user-menu-items"?(props: {
124
+ /** The signed-in user. */
125
+ user: DashboardUser;
126
+ }): any;
127
+ }
128
+ /**
129
+ * Slots of DXDashboardSidebar, with their slot props. All are optional.
130
+ * `TItem` is the navigation's item type (see `NavigationGroup`).
131
+ */
132
+ export interface DashboardSidebarSlots<TItem extends NavigationItem = NavigationItem> {
133
+ /**
134
+ * Brand/logo area in the sidebar header. Defaults to the title's initial
135
+ * plus the full title (hidden when collapsed).
136
+ */
137
+ "brand"?(props: {
138
+ /** Whether the sidebar rail is collapsed to icons only. */
139
+ collapsed: boolean;
140
+ /** The sidebar title text. */
141
+ title: string;
142
+ }): any;
143
+ /**
144
+ * Renders a single navigation item link. Defaults to an anchor with
145
+ * optional icon, label, and badge.
146
+ */
147
+ "link"?(props: {
148
+ /**
149
+ * The navigation item (label, url, icon, badge, badgeColor), typed as the
150
+ * app's own item type when its items carry extra keys.
151
+ */
152
+ item: TItem;
153
+ /** Whether this item matches the current route. */
154
+ isActive: boolean;
155
+ /** Whether the sidebar rail is collapsed to icons only. */
156
+ collapsed: boolean;
157
+ /** Whether the item's group is currently expanded. */
158
+ isExpanded: boolean;
159
+ }): any;
160
+ /**
161
+ * Utility/secondary links pinned to the bottom of the sidebar (help,
162
+ * changelog, sign-out, …), below the nav groups.
163
+ */
164
+ "footer"?(props: {
165
+ /** Whether the sidebar rail is collapsed to icons only. */
166
+ collapsed: boolean;
167
+ }): any;
168
+ }
169
+ /**
170
+ * The two bindings DXDashboard adds to every forwarded `sidebar-*` and
171
+ * `navbar-*` slot. They are bound after the child's own slot props, so they
172
+ * win a name clash.
173
+ */
174
+ export interface DashboardSlotExtras {
175
+ /** Shows/hides the sidebar. */
176
+ toggleSidebar: () => void;
177
+ /** Whether the sidebar is currently hidden. */
178
+ sidebarHidden: boolean;
179
+ }
180
+ /** The props a (possibly optional) slot function receives. */
181
+ type SlotPropsOf<Slot> = NonNullable<Slot> extends (props: infer Props) => any ? Props : never;
182
+ /**
183
+ * A child component's slots renamed with `Prefix` and given the dashboard's
184
+ * extra bindings: `{ brand(props: P) }` becomes
185
+ * `{ "sidebar-brand"(props: P & DashboardSlotExtras) }`. Derived from the
186
+ * child's slot types, so a slot added to the child is typed here for free.
187
+ */
188
+ export type PrefixedDashboardSlots<Slots, Prefix extends string> = {
189
+ [Name in keyof Slots as `${Prefix}${Name & string}`]?: (props: Omit<SlotPropsOf<Slots[Name]>, keyof DashboardSlotExtras> & DashboardSlotExtras) => any;
190
+ };
191
+ /**
192
+ * Slots of DXDashboard: the page content (`default`), every
193
+ * DXDashboardSidebar slot as `sidebar-<name>` and every DXDashboardNavbar
194
+ * slot as `navbar-<name>`. An unprefixed name (`#search`) is not forwarded.
195
+ * `TItem` is the navigation's item type (see `NavigationGroup`).
196
+ */
197
+ export type DashboardSlots<TItem extends NavigationItem = NavigationItem> = {
198
+ /** The main page content. */
199
+ default?(props: NoSlotProps): any;
200
+ } & PrefixedDashboardSlots<DashboardSidebarSlots<TItem>, "sidebar-"> & PrefixedDashboardSlots<DashboardNavbarSlots, "navbar-">;
201
+ export {};
@@ -0,0 +1,19 @@
1
+ /** One card's fit: its elements, and the box width it was last fitted to. */
2
+ export interface FitTarget {
3
+ box: HTMLElement;
4
+ value: HTMLElement;
5
+ /** Only numeric values are fitted; text wraps instead. */
6
+ isNumeric: () => boolean;
7
+ /** -1 when the next resize entry must refit whatever its width. */
8
+ fittedBoxWidth: number;
9
+ }
10
+ /**
11
+ * Queue a fit. "microtask" runs before the next paint, for mounts, content
12
+ * changes, reactivation and font loads. "frame" is for ResizeObserver
13
+ * callbacks: a fit inside the observer's delivery (microtasks run there
14
+ * too) changes the box's HEIGHT, which the browser reports as a
15
+ * "ResizeObserver loop" error, so a resize refits in the next frame.
16
+ */
17
+ export declare function queueFit(target: FitTarget, timing: "microtask" | "frame"): void;
18
+ export declare function registerTarget(target: FitTarget): void;
19
+ export declare function unregisterTarget(target: FitTarget): void;
@@ -1,8 +1,8 @@
1
1
  {
2
- "generated": "2026-10-11T09:08:08.777Z",
2
+ "generated": "2026-10-15T11:16:01.160Z",
3
3
  "package": {
4
4
  "name": "@omnitend/dashboard-for-laravel",
5
- "version": "0.45.0"
5
+ "version": "0.46.0"
6
6
  },
7
7
  "components": {
8
8
  "base": [
@@ -556,6 +556,27 @@
556
556
  ],
557
557
  "methods": []
558
558
  },
559
+ {
560
+ "name": "DFormFile",
561
+ "category": "base",
562
+ "filePath": "resources/js/components/base/DFormFile.vue",
563
+ "description": "Type-safe wrapper around Bootstrap Vue Next BFormFile component. File picker with a browse button, file-name display and drag-and-drop zone. `v-model` is a `File` (single), `File[]` (`multiple`/`directory`) or `null`; setting it to `null` (or `[]`) also clears the native input. A disabled control (the prop, or a disabled fieldset) ignores dropped files. Slots: `label`, `placeholder`, `file-name` (`{ files, names }`) and `drop-placeholder`. Exposes BFormFile's `focus`, `blur` and `reset`.",
564
+ "props": [],
565
+ "events": [],
566
+ "slots": [
567
+ {
568
+ "name": "name",
569
+ "description": "",
570
+ "bindings": [
571
+ {
572
+ "name": "name",
573
+ "title": "binding"
574
+ }
575
+ ]
576
+ }
577
+ ],
578
+ "methods": []
579
+ },
559
580
  {
560
581
  "name": "DFormGroup",
561
582
  "category": "base",
@@ -798,6 +819,27 @@
798
819
  "slots": [],
799
820
  "methods": []
800
821
  },
822
+ {
823
+ "name": "DFormValidFeedback",
824
+ "category": "base",
825
+ "filePath": "resources/js/components/base/DFormValidFeedback.vue",
826
+ "description": "",
827
+ "props": [],
828
+ "events": [],
829
+ "slots": [
830
+ {
831
+ "name": "name",
832
+ "description": "",
833
+ "bindings": [
834
+ {
835
+ "name": "name",
836
+ "title": "binding"
837
+ }
838
+ ]
839
+ }
840
+ ],
841
+ "methods": []
842
+ },
801
843
  {
802
844
  "name": "DImage",
803
845
  "category": "base",
@@ -1564,7 +1606,7 @@
1564
1606
  "props": [
1565
1607
  {
1566
1608
  "name": "navigation",
1567
- "type": "Navigation",
1609
+ "type": "TNavigation",
1568
1610
  "required": true,
1569
1611
  "description": "Navigation structure for sidebar"
1570
1612
  },
@@ -1856,7 +1898,7 @@
1856
1898
  "props": [
1857
1899
  {
1858
1900
  "name": "navigation",
1859
- "type": "Navigation",
1901
+ "type": "TNavigation",
1860
1902
  "required": true,
1861
1903
  "description": "Grouped navigation to render: an array of groups, each with a label and items."
1862
1904
  },
@@ -4579,8 +4621,8 @@
4579
4621
  ]
4580
4622
  },
4581
4623
  "stats": {
4582
- "totalComponents": 90,
4583
- "baseComponents": 60,
4624
+ "totalComponents": 92,
4625
+ "baseComponents": 62,
4584
4626
  "extendedComponents": 30
4585
4627
  }
4586
4628
  }
@@ -1,7 +1,7 @@
1
1
  # Documentation Map
2
2
 
3
3
  > Auto-generated hierarchical overview of all documentation
4
- > Last updated: 2026-10-11T09:08:08.837Z
4
+ > Last updated: 2026-10-15T11:16:01.216Z
5
5
 
6
6
  This file provides a complete map of all available documentation for AI agents and developers.
7
7
 
@@ -33,6 +33,7 @@ This file provides a complete map of all available documentation for AI agents a
33
33
  - [DDropdownItem](/components/base/DDropdownItem): Type-safe wrapper around Bootstrap Vue Next's BDropdownItem component
34
34
  - [DForm](/components/base/DForm): Type-safe wrapper around Bootstrap Vue Next's BForm component
35
35
  - [DFormCheckbox](/components/base/DFormCheckbox): Type-safe wrapper around Bootstrap Vue Next's BFormCheckbox component
36
+ - [DFormFile](/components/base/DFormFile): Type-safe wrapper around Bootstrap Vue Next's BFormFile component
36
37
  - [DFormGroup](/components/base/DFormGroup): Type-safe wrapper around Bootstrap Vue Next's BFormGroup component
37
38
  - [DFormInput](/components/base/DFormInput): Type-safe wrapper around Bootstrap Vue Next's BFormInput component
38
39
  - [DFormInvalidFeedback](/components/base/DFormInvalidFeedback): Type-safe wrapper around Bootstrap Vue Next's BFormInvalidFeedback component
@@ -43,6 +44,7 @@ This file provides a complete map of all available documentation for AI agents a
43
44
  - [DFormTags](/components/base/DFormTags): Type-safe wrapper around Bootstrap Vue Next's BFormTags component
44
45
  - [DFormText](/components/base/DFormText): Type-safe wrapper around Bootstrap Vue Next's BFormText component
45
46
  - [DFormTextarea](/components/base/DFormTextarea): Type-safe wrapper around Bootstrap Vue Next's BFormTextarea component
47
+ - [DFormValidFeedback](/components/base/DFormValidFeedback): Type-safe wrapper around Bootstrap Vue Next's BFormValidFeedback component
46
48
  - [DImage](/components/base/DImage): Type-safe wrapper around Bootstrap Vue Next's BImage component
47
49
  - [DInputGroup](/components/base/DInputGroup): Type-safe wrapper around Bootstrap Vue Next's BInputGroup component
48
50
  - [DLink](/components/base/DLink): Type-safe wrapper around Bootstrap Vue Next's BLink component
@@ -106,4 +108,4 @@ This file provides a complete map of all available documentation for AI agents a
106
108
 
107
109
  ---
108
110
 
109
- **Total Pages**: 82
111
+ **Total Pages**: 84
@@ -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 80 Vue 3 components for building Laravel dashboards with Bootstrap Vue Next.
5
+ > A dual-package library (NPM + Composer) providing 82 Vue 3 components for building Laravel dashboards with Bootstrap Vue Next.
6
6
 
7
7
  ## Installation
8
8
 
@@ -19,7 +19,7 @@
19
19
  - [Theming](/guide/theming): Customize appearance with CSS variables
20
20
  - [TypeScript](/guide/typescript): TypeScript types and best practices
21
21
 
22
- ## Base Components (60 components)
22
+ ## Base Components (62 components)
23
23
 
24
24
  Lightweight type-safe wrappers around Bootstrap Vue Next components providing API stability and consistent theming.
25
25
 
@@ -46,6 +46,7 @@ Lightweight type-safe wrappers around Bootstrap Vue Next components providing AP
46
46
  - [DForm](/components/base/dform): Bootstrap Vue Next Form wrapper
47
47
  - [DFormCheckbox](/components/base/dformcheckbox): Bootstrap Vue Next FormCheckbox wrapper
48
48
  - [DFormCheckboxGroup](/components/base/dformcheckboxgroup): Bootstrap Vue Next FormCheckboxGroup wrapper
49
+ - [DFormFile](/components/base/dformfile): Bootstrap Vue Next FormFile wrapper
49
50
  - [DFormGroup](/components/base/dformgroup): Bootstrap Vue Next FormGroup wrapper
50
51
  - [DFormInput](/components/base/dforminput): Bootstrap Vue Next FormInput wrapper
51
52
  - [DFormInvalidFeedback](/components/base/dforminvalidfeedback): Bootstrap Vue Next FormInvalidFeedback wrapper
@@ -57,6 +58,7 @@ Lightweight type-safe wrappers around Bootstrap Vue Next components providing AP
57
58
  - [DFormTags](/components/base/dformtags): Bootstrap Vue Next FormTags wrapper
58
59
  - [DFormText](/components/base/dformtext): Bootstrap Vue Next FormText wrapper
59
60
  - [DFormTextarea](/components/base/dformtextarea): Bootstrap Vue Next FormTextarea wrapper
61
+ - [DFormValidFeedback](/components/base/dformvalidfeedback): Bootstrap Vue Next FormValidFeedback wrapper
60
62
  - [DImage](/components/base/dimage): Bootstrap Vue Next Image wrapper
61
63
  - [DInputGroup](/components/base/dinputgroup): Bootstrap Vue Next InputGroup wrapper
62
64
  - [DLink](/components/base/dlink): Bootstrap Vue Next Link wrapper
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnitend/dashboard-for-laravel",
3
- "version": "0.45.0",
3
+ "version": "0.46.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",
@@ -36,13 +36,14 @@
36
36
  "dev": "vite build --watch",
37
37
  "build:lib": "vite build && vite build --config vite.config.charts.ts && node scripts/extract-icon-font.mjs",
38
38
  "build": "npm run build:lib && vue-tsc --declaration --emitDeclarationOnly --outDir dist",
39
- "typecheck": "vue-tsc --noEmit",
39
+ "typecheck": "vue-tsc --noEmit && vue-tsc --noEmit -p tests/types/tsconfig.json",
40
40
  "pretest": "npm run build:lib",
41
41
  "test": "vitest",
42
42
  "pretest:ui": "npm run build:lib",
43
43
  "test:ui": "vitest --ui",
44
44
  "pretest:headless": "npm run build:lib",
45
45
  "test:headless": "vitest --run --browser.headless",
46
+ "test:linux": "bash scripts/test-linux.sh",
46
47
  "docs:dev": "astro dev",
47
48
  "docs:build": "npm run docs:generate:ai && astro build && node scripts/check-docs-base-links.mjs",
48
49
  "docs:preview": "astro preview",