@omnitend/dashboard-for-laravel 0.25.0 → 0.27.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.
@@ -1,8 +1,8 @@
1
1
  {
2
- "generated": "2026-07-11T11:02:20.726Z",
2
+ "generated": "2026-07-18T05:05:36.998Z",
3
3
  "package": {
4
4
  "name": "@omnitend/dashboard-for-laravel",
5
- "version": "0.25.0"
5
+ "version": "0.26.0"
6
6
  },
7
7
  "components": {
8
8
  "base": [
@@ -1121,27 +1121,6 @@
1121
1121
  "slots": [],
1122
1122
  "methods": []
1123
1123
  },
1124
- {
1125
- "name": "DTab",
1126
- "category": "base",
1127
- "filePath": "resources/js/components/base/DTab.vue",
1128
- "description": "",
1129
- "props": [],
1130
- "events": [],
1131
- "slots": [
1132
- {
1133
- "name": "name",
1134
- "description": "",
1135
- "bindings": [
1136
- {
1137
- "name": "name",
1138
- "title": "binding"
1139
- }
1140
- ]
1141
- }
1142
- ],
1143
- "methods": []
1144
- },
1145
1124
  {
1146
1125
  "name": "DTable",
1147
1126
  "category": "base",
@@ -2928,6 +2907,18 @@
2928
2907
  "required": false,
2929
2908
  "description": "Rows currently expanded, as a `v-model`. Pair with the `row-expansion`\nslot to render detail content under a row (#112) instead of forcing every\nper-row detail into a modal."
2930
2909
  },
2910
+ {
2911
+ "name": "rowClass",
2912
+ "type": "union",
2913
+ "required": false,
2914
+ "description": "Class(es) applied to each row's `<tr>` — a string, or a function of the\nrow. Use for conditional row styling (a variant, a muted/disabled look)\nwithout reaching into the table's internal DOM from global CSS."
2915
+ },
2916
+ {
2917
+ "name": "rowClickable",
2918
+ "type": "TSFunctionType",
2919
+ "required": false,
2920
+ "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."
2921
+ },
2931
2922
  {
2932
2923
  "name": "clientSide",
2933
2924
  "type": "boolean",
@@ -3023,6 +3014,28 @@
3023
3014
  "description": "Card header content; overrides the default title heading and the \"New {item}\" button.",
3024
3015
  "bindings": []
3025
3016
  },
3017
+ {
3018
+ "name": "thead-top",
3019
+ "description": "A row rendered ABOVE the column headers — a grouped-column banner (a `<th colspan>` spanning several columns), or a pinned totals row. Renders above DXTable's own filter row. Give it `<tr>`s.",
3020
+ "bindings": [
3021
+ {
3022
+ "title": "binding",
3023
+ "type": {
3024
+ "name": "object"
3025
+ },
3026
+ "name": "columns",
3027
+ "description": "The number of columns in the table."
3028
+ },
3029
+ {
3030
+ "title": "binding",
3031
+ "type": {
3032
+ "name": "object"
3033
+ },
3034
+ "name": "fields",
3035
+ "description": "The table's fields."
3036
+ }
3037
+ ]
3038
+ },
3026
3039
  {
3027
3040
  "name": "name",
3028
3041
  "description": "Any slot the underlying table supports, forwarded with its scope: `cell(<fieldKey>)` for a cell, `foot(<fieldKey>)` for a footer cell (needs `footClone`), `empty` for the no-rows message, `row-expansion` for expandable row detail, plus `custom-foot`, `top-row`, `bottom-row`, `thead-sub` and the `table-*` slots.",
@@ -3282,8 +3295,8 @@
3282
3295
  ]
3283
3296
  },
3284
3297
  "stats": {
3285
- "totalComponents": 74,
3286
- "baseComponents": 57,
3298
+ "totalComponents": 73,
3299
+ "baseComponents": 56,
3287
3300
  "extendedComponents": 17
3288
3301
  }
3289
3302
  }
@@ -1,7 +1,7 @@
1
1
  # Documentation Map
2
2
 
3
3
  > Auto-generated hierarchical overview of all documentation
4
- > Last updated: 2026-07-11T11:02:20.808Z
4
+ > Last updated: 2026-07-18T05:05:37.057Z
5
5
 
6
6
  This file provides a complete map of all available documentation for AI agents and developers.
7
7
 
@@ -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 69 Vue 3 components for building Laravel dashboards with Bootstrap Vue Next.
5
+ > A dual-package library (NPM + Composer) providing 68 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 (57 components)
22
+ ## Base Components (56 components)
23
23
 
24
24
  Lightweight type-safe wrappers around Bootstrap Vue Next components providing API stability and consistent theming.
25
25
 
@@ -74,7 +74,6 @@ Lightweight type-safe wrappers around Bootstrap Vue Next components providing AP
74
74
  - [DProgress](/components/base/dprogress): Bootstrap Vue Next Progress wrapper
75
75
  - [DRow](/components/base/drow): Bootstrap Vue Next Row wrapper
76
76
  - [DSpinner](/components/base/dspinner): Bootstrap Vue Next Spinner wrapper
77
- - [DTab](/components/base/dtab): Bootstrap Vue Next Tab wrapper
78
77
  - [DTable](/components/base/dtable): Bootstrap Vue Next Table wrapper
79
78
  - [DTabs](/components/base/dtabs): Bootstrap Vue Next Tabs wrapper
80
79
  - [DToast](/components/base/dtoast): Bootstrap Vue Next Toast wrapper
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnitend/dashboard-for-laravel",
3
- "version": "0.25.0",
3
+ "version": "0.27.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",
@@ -29,7 +29,7 @@
29
29
  ],
30
30
  "scripts": {
31
31
  "dev": "vite build --watch",
32
- "build": "vite build && vue-tsc --declaration --emitDeclarationOnly --outDir dist",
32
+ "build": "vite build && node scripts/extract-icon-font.mjs && vue-tsc --declaration --emitDeclarationOnly --outDir dist",
33
33
  "typecheck": "vue-tsc --noEmit",
34
34
  "pretest": "vite build",
35
35
  "test": "vitest",
@@ -7,19 +7,31 @@
7
7
  // The Sass module for `color.mix()` etc. `@use` must precede all other
8
8
  // statements (variable overrides, `@import`), so it stays at the very top.
9
9
  @use "sass:color";
10
+ @use "sass:map";
10
11
 
11
12
  // ----------------------------------------------------------------------------
12
13
  // Colors
13
14
  // ----------------------------------------------------------------------------
14
15
 
15
- $primary: #4f46e5; // Indigo-600 (8.6:1 with white)
16
- $secondary: #475569; // Slate-600 (7.0:1 with white) - darkened for better contrast
17
- $success: #10b981; // Emerald-500 (6.7:1 with white)
18
- $danger: #dc2626; // Red-600 (7.2:1 with white) - darkened for better contrast
19
- $warning: #f59e0b; // Amber-500 (7.7:1 with white)
20
- $info: #2563eb; // Blue-600 (7.3:1 with white)
16
+ // Base $theme-colors carry each hue's READABLE-ON-LIGHT identity (its "emphasis"
17
+ // shade) — this is what `.text-*`, `.link-*`, `.border-*` and outline buttons
18
+ // use, so every one must clear AA on white. Bold solid FILLS (primary/danger
19
+ // buttons) and SOFT tints (soft buttons, badges, alerts) are applied as explicit
20
+ // overrides after the Bootstrap import, from the $dx-variants map. See
21
+ // plans/2026-07-18-semantic-colour-system.md.
22
+ $primary: #151e2d; // Omni Tend brand navy (16.73:1 on white)
23
+ $secondary: #475569; // Slate-600 (7.58:1 on white)
24
+ $success: #4d7c0f; // Lime-700 emphasis (4.99:1 on white); soft/vivid tints in $dx-variants
25
+ $danger: #dc2626; // Red-600 (4.83:1 on white)
26
+ $warning: #b45309; // Amber-700 emphasis (5.02:1 on white)
27
+ $info: #2563eb; // Blue-600 (5.17:1 on white)
21
28
  $light: #f8fafc; // Slate-50 (uses dark text)
22
- $dark: #0f172a; // Slate-900 (uses white text)
29
+ $dark: #151e2d; // Brand navy — sidebar/high-contrast surfaces (was Slate-900 #0f172a)
30
+
31
+ // Links are the info-blue, independent of the near-black brand primary (a navy
32
+ // link would read as bold text, not a link).
33
+ $link-color: #2563eb;
34
+ $link-shade-percentage: 15%;
23
35
 
24
36
  // ----------------------------------------------------------------------------
25
37
  // Contrast Settings
@@ -154,6 +166,21 @@ $badge-padding-y: 0.25rem;
154
166
  $badge-padding-x: 0.625rem;
155
167
  $badge-font-weight: 500;
156
168
 
169
+ // The ONE source of truth for the semantic colour system. Each variant carries
170
+ // its SOLID fill + same-hue text (primary/danger buttons, solid fills), its SOFT
171
+ // tint pair (soft buttons, badges, alerts, status), its EMPHASIS shade (outline
172
+ // buttons, coloured links, .text-*), and whether its button is solid or soft.
173
+ // The overrides after the Bootstrap import loop over this map. All pairs are
174
+ // WCAG AA verified. See plans/2026-07-18-semantic-colour-system.md.
175
+ $dx-variants: (
176
+ "primary": (solid-bg: #151e2d, solid-text: #e9f0f8, soft-bg: #e9f0f8, soft-text: #151e2d, emphasis: #151e2d, button: "solid"),
177
+ "secondary": (solid-bg: #475569, solid-text: #e6ebf2, soft-bg: #e6ebf2, soft-text: #29374a, emphasis: #475569, button: "soft"),
178
+ "success": (solid-bg: #84cc16, solid-text: #203b0e, soft-bg: #cdf9b2, soft-text: #203b0e, emphasis: #4d7c0f, button: "soft"),
179
+ "danger": (solid-bg: #dc2626, solid-text: #ffffff, soft-bg: #f5dff1, soft-text: #59194a, emphasis: #dc2626, button: "solid"),
180
+ "warning": (solid-bg: #f59e0b, solid-text: #512d05, soft-bg: #fce5c4, soft-text: #512d05, emphasis: #b45309, button: "soft"),
181
+ "info": (solid-bg: #2563eb, solid-text: #eef4ff, soft-bg: #deebff, soft-text: #12376c, emphasis: #2563eb, button: "soft"),
182
+ );
183
+
157
184
  // ----------------------------------------------------------------------------
158
185
  // Dashboard
159
186
  // ----------------------------------------------------------------------------
@@ -210,12 +237,18 @@ $dashboard-navbar-content-height: calc(
210
237
  // bi-*">`) renders without the consumer wiring up their own icon set.
211
238
  //
212
239
  // Imported as SCSS (not the prebuilt CSS) so we can override the font `src` to
213
- // woff2 ONLY — dropping bootstrap-icons' legacy `woff` fallback. In the library
214
- // build Vite inlines CSS `url()` assets as data URIs, so shipping both formats
215
- // doubled the embedded font bytes in `dist/style.css` for no benefit (every
216
- // browser we target reads woff2). The override must come BEFORE the import so
240
+ // woff2 ONLY — dropping bootstrap-icons' legacy `woff` fallback, which no
241
+ // browser we target needs. The override must come BEFORE the import so
217
242
  // bootstrap-icons' own `!default` src doesn't re-add the woff. The bare
218
243
  // `bootstrap-icons/...` specifier resolves through Vite's module resolver.
244
+ //
245
+ // The font itself does NOT ship inside `dist/style.css`. Vite always inlines
246
+ // CSS-referenced assets as base64 data URIs in library mode, which is
247
+ // pathological for a woff2 (already Brotli-compressed; base64 inflates it a
248
+ // third; gzip recovers none of it) — inlined, the font alone was 137 KB of the
249
+ // stylesheet's 191 KB gzip. `scripts/extract-icon-font.mjs` writes it back out
250
+ // as a real file post-build, so the browser fetches it only when a `.bi-*`
251
+ // glyph actually renders. See #77.
219
252
  $bootstrap-icons-font-src: url("bootstrap-icons/font/fonts/bootstrap-icons.woff2")
220
253
  format("woff2");
221
254
  @import "bootstrap-icons/font/bootstrap-icons";
@@ -414,6 +447,112 @@ $bootstrap-icons-font-src: url("bootstrap-icons/font/fonts/bootstrap-icons.woff2
414
447
  }
415
448
  }
416
449
 
450
+ // ----------------------------------------------------------------------------
451
+ // Semantic colour system (soft-first)
452
+ // ----------------------------------------------------------------------------
453
+ // One loop over $dx-variants applies the whole system on top of Bootstrap:
454
+ //
455
+ // - Buttons: primary/danger are SOLID (fill from the base colour; we only
456
+ // override the label to the same-hue tint, letting Bootstrap shade hover/
457
+ // active). secondary/success/warning/info are SOFT (light tint bg + dark
458
+ // text, fully overridden incl. hover/active).
459
+ // - Outline buttons: the emphasis shade for border/label, the soft tint on hover.
460
+ // - Badges: `.badge.text-bg-*` re-tinted soft — needs `!important` because
461
+ // Bootstrap's `.text-bg-*` helper sets its colours `!important` by design.
462
+ // - Alerts: the soft tint.
463
+ // - Links/text: `.link-*` and `.text-*` take the emphasis shade so they read
464
+ // on white (the base colours already carry emphasis for most variants; this
465
+ // pins the two — success/warning — whose base differs).
466
+ @each $name, $v in $dx-variants {
467
+ $solid-bg: map.get($v, "solid-bg");
468
+ $solid-text: map.get($v, "solid-text");
469
+ $soft-bg: map.get($v, "soft-bg");
470
+ $soft-text: map.get($v, "soft-text");
471
+ $emphasis: map.get($v, "emphasis");
472
+ $is-solid: map.get($v, "button") == "solid";
473
+
474
+ @if $is-solid {
475
+ // Solid button: keep Bootstrap's fill + hover/active shading (from the base
476
+ // colour), override only the LABEL to the same-hue tint.
477
+ .btn-#{$name} {
478
+ --bs-btn-color: #{$solid-text};
479
+ --bs-btn-hover-color: #{$solid-text};
480
+ --bs-btn-active-color: #{$solid-text};
481
+ --bs-btn-disabled-color: #{$solid-text};
482
+ }
483
+ } @else {
484
+ // Soft button: light tint bg + dark same-hue label; darken the tint slightly
485
+ // on hover/active for feedback.
486
+ .btn-#{$name} {
487
+ --bs-btn-color: #{$soft-text};
488
+ --bs-btn-bg: #{$soft-bg};
489
+ --bs-btn-border-color: #{$soft-bg};
490
+ --bs-btn-hover-color: #{$soft-text};
491
+ --bs-btn-hover-bg: #{color.scale($soft-bg, $lightness: -6%)};
492
+ --bs-btn-hover-border-color: #{color.scale($soft-bg, $lightness: -6%)};
493
+ --bs-btn-active-color: #{$soft-text};
494
+ --bs-btn-active-bg: #{color.scale($soft-bg, $lightness: -10%)};
495
+ --bs-btn-active-border-color: #{color.scale($soft-bg, $lightness: -10%)};
496
+ --bs-btn-disabled-color: #{$soft-text};
497
+ --bs-btn-disabled-bg: #{$soft-bg};
498
+ --bs-btn-disabled-border-color: #{$soft-bg};
499
+ }
500
+ }
501
+
502
+ // Outline button: emphasis border/label, fills to the soft tint on hover so it
503
+ // stays calm (not a sudden saturated block).
504
+ .btn-outline-#{$name} {
505
+ --bs-btn-color: #{$emphasis};
506
+ --bs-btn-border-color: #{$emphasis};
507
+ --bs-btn-hover-color: #{$soft-text};
508
+ --bs-btn-hover-bg: #{$soft-bg};
509
+ --bs-btn-hover-border-color: #{$emphasis};
510
+ --bs-btn-active-color: #{$soft-text};
511
+ --bs-btn-active-bg: #{$soft-bg};
512
+ --bs-btn-active-border-color: #{$emphasis};
513
+ }
514
+
515
+ // Badge — soft tint. `!important` beats Bootstrap's `.text-bg-*` helper.
516
+ .badge.text-bg-#{$name} {
517
+ background-color: #{$soft-bg} !important;
518
+ color: #{$soft-text} !important;
519
+ }
520
+
521
+ // Alert — soft tint, with the emphasis shade as the accent border.
522
+ .alert-#{$name} {
523
+ --bs-alert-bg: #{$soft-bg};
524
+ --bs-alert-color: #{$soft-text};
525
+ --bs-alert-border-color: #{color.scale($soft-bg, $lightness: -8%)};
526
+ --bs-alert-link-color: #{$emphasis};
527
+ }
528
+
529
+ // `.text-#{$name}` and `.link-#{$name}` need no override: each variant's base
530
+ // colour IS its emphasis shade, so Bootstrap already renders them legible.
531
+ }
532
+
533
+ // primary is near-black navy, so Bootstrap's darken-on-hover is imperceptible —
534
+ // the main action button would have no visible hover feedback. Lighten instead.
535
+ // (danger's red darkens visibly, so the generic solid path is fine for it.)
536
+ .btn-primary {
537
+ --bs-btn-hover-bg: #{color.scale($primary, $lightness: 20%)};
538
+ --bs-btn-hover-border-color: #{color.scale($primary, $lightness: 20%)};
539
+ --bs-btn-active-bg: #{color.scale($primary, $lightness: 12%)};
540
+ --bs-btn-active-border-color: #{color.scale($primary, $lightness: 12%)};
541
+ }
542
+
543
+ // Tertiary "ghost" button: a `link`-variant button restyled to read as a quiet
544
+ // action, not a hyperlink — body colour, no underline, faint hover surface.
545
+ .btn-link {
546
+ --bs-btn-color: var(--bs-body-color);
547
+ --bs-btn-hover-color: var(--bs-body-color);
548
+ --bs-btn-active-color: var(--bs-body-color);
549
+ text-decoration: none;
550
+
551
+ &:hover {
552
+ background-color: var(--bs-light);
553
+ }
554
+ }
555
+
417
556
  // ----------------------------------------------------------------------------
418
557
  // Autocomplete
419
558
  // ----------------------------------------------------------------------------
@@ -172,7 +172,7 @@ import DAlert from "../base/DAlert.vue";
172
172
  import DButton from "../base/DButton.vue";
173
173
  import DCard from "../base/DCard.vue";
174
174
  import DTabs from "../base/DTabs.vue";
175
- import DTab from "../base/DTab.vue";
175
+ import { BTab as DTab } from "bootstrap-vue-next"; // raw BTab: BTabs scans slot vnodes for it (#119)
176
176
  import DXFormField from "./DXFormField.vue";
177
177
  import type { UseFormReturn } from "../../composables/useForm";
178
178
  import type { DefineFormReturn } from "../../composables/defineForm";