@omnitend/dashboard-for-laravel 0.15.0 → 0.16.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.
@@ -13,7 +13,7 @@ import type { Component } from "vue";
13
13
  * - `switch` — a toggle checkbox with contextual on/off text and an
14
14
  * on-state (filled) style; see `textWhenTrue` / `textWhenFalse`.
15
15
  */
16
- export type FieldType = "text" | "email" | "password" | "number" | "url" | "tel" | "date" | "datetime-local" | "datetime" | "time" | "currency" | "percentage" | "textarea" | "select" | "checkbox" | "switch" | "radio" | "image" | "file" | "component" | "repeater";
16
+ export type FieldType = "text" | "email" | "password" | "number" | "url" | "tel" | "date" | "datetime-local" | "datetime" | "time" | "currency" | "percentage" | "textarea" | "select" | "autocomplete" | "checkbox" | "switch" | "radio" | "image" | "file" | "component" | "repeater";
17
17
  /**
18
18
  * A value that may be supplied directly or computed from the live form
19
19
  * model. Predicates receive the current model so fields can react to
@@ -52,11 +52,16 @@ export interface FieldDefinition {
52
52
  placeholder?: string;
53
53
  /** Whether field is required (optional) */
54
54
  required?: boolean;
55
- /** Options for select or radio fields */
55
+ /**
56
+ * Options for `select`, `radio` and `autocomplete` fields. For
57
+ * `autocomplete` these are the datalist suggestions; the field still
58
+ * accepts free text not present in the list.
59
+ */
56
60
  options?: FieldOption[];
57
61
  /**
58
- * Asynchronously load options for select/radio fields. Takes
59
- * precedence over `options` once resolved.
62
+ * Asynchronously load options for `select`, `radio` and `autocomplete`
63
+ * fields (e.g. fetch a suggestion list). Takes precedence over `options`
64
+ * once resolved.
60
65
  */
61
66
  optionsLoader?: OptionsLoader;
62
67
  /** Re-run `optionsLoader` whenever the form model changes. */
@@ -1,8 +1,8 @@
1
1
  {
2
- "generated": "2026-07-05T08:20:04.640Z",
2
+ "generated": "2026-07-05T08:43:52.804Z",
3
3
  "package": {
4
4
  "name": "@omnitend/dashboard-for-laravel",
5
- "version": "0.14.0"
5
+ "version": "0.15.0"
6
6
  },
7
7
  "components": {
8
8
  "base": [
@@ -1682,7 +1682,7 @@
1682
1682
  "name": "DXField",
1683
1683
  "category": "extended",
1684
1684
  "filePath": "resources/js/components/extended/DXField.vue",
1685
- "description": "Renders a single `FieldDefinition` of any type (text, select, checkbox, switch, repeater, currency, percentage, file/image, component, etc.) with its label, validation error, hint and help. Used by `DXForm` and `DXTable`'s edit modal; exposes `value`, `span`, `info`, `hint` and `repeater-row` slots for per-field customisation.",
1685
+ "description": "Renders a single `FieldDefinition` of any type (text, select, autocomplete, checkbox, switch, repeater, currency, percentage, file/image, component, etc.) with its label, validation error, hint and help. Used by `DXForm` and `DXTable`'s edit modal; exposes `value`, `span`, `info`, `hint` and `repeater-row` slots for per-field customisation.",
1686
1686
  "props": [
1687
1687
  {
1688
1688
  "name": "field",
@@ -1,7 +1,7 @@
1
1
  # Documentation Map
2
2
 
3
3
  > Auto-generated hierarchical overview of all documentation
4
- > Last updated: 2026-07-05T08:20:04.705Z
4
+ > Last updated: 2026-07-05T08:43:52.857Z
5
5
 
6
6
  This file provides a complete map of all available documentation for AI agents and developers.
7
7
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnitend/dashboard-for-laravel",
3
- "version": "0.15.0",
3
+ "version": "0.16.1",
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",
@@ -258,6 +258,24 @@ $dashboard-navbar-height: 64px;
258
258
  }
259
259
  }
260
260
 
261
+ // ----------------------------------------------------------------------------
262
+ // Autocomplete
263
+ // ----------------------------------------------------------------------------
264
+ // BAutocomplete's dropdown popup (`.b-autocomplete-content`) only sets a
265
+ // max-height, so it inherits the (often narrow) anchor/trigger width and clips
266
+ // long option labels — a real problem for a DXTable `select` filter in a narrow
267
+ // column. Let it grow to fit the longest option while staying at least the
268
+ // trigger width, capped so a pathological label can't make it enormous.
269
+ //
270
+ // This lives in the global theme (not DAutocomplete's scoped styles) on
271
+ // purpose: the popup can be teleported out of the component (BAutocomplete's
272
+ // `teleportTo` prop), which escapes scoped `:deep()` entirely — a global rule
273
+ // applies whether or not it's teleported.
274
+ .b-autocomplete-content {
275
+ min-width: max-content; // grow to the longest option (floors at the trigger width)
276
+ max-width: min(90vw, 32rem); // but don't run away
277
+ }
278
+
261
279
  // ----------------------------------------------------------------------------
262
280
  // Custom Utilities
263
281
  // ----------------------------------------------------------------------------
@@ -14,12 +14,22 @@ defineOptions({
14
14
  </script>
15
15
 
16
16
  <template>
17
- <BAutocomplete v-bind="$attrs">
18
- <!-- Dynamically pass through all named slots with their props -->
19
- <template v-for="(_, name) in $slots" :key="name" #[name]="slotProps">
20
- <slot :name="name" v-bind="slotProps" />
21
- </template>
22
- </BAutocomplete>
17
+ <!--
18
+ Wrap BAutocomplete in a real element so our scoped styles have a concrete
19
+ host to attach the scope-id to. Styling BAutocomplete's internal DOM via
20
+ `:deep()` on a wrapper whose ONLY root is the `<BAutocomplete>` *component*
21
+ doesn't work: the scope-id isn't reliably forwarded onto BVN's rendered
22
+ root, so `[data-v-x] .input-group` matches nothing in a consumer build
23
+ (#53). A plain element root makes it deterministic.
24
+ -->
25
+ <div class="d-autocomplete">
26
+ <BAutocomplete v-bind="$attrs">
27
+ <!-- Dynamically pass through all named slots with their props -->
28
+ <template v-for="(_, name) in $slots" :key="name" #[name]="slotProps">
29
+ <slot :name="name" v-bind="slotProps" />
30
+ </template>
31
+ </BAutocomplete>
32
+ </div>
23
33
  </template>
24
34
 
25
35
  <style scoped>
@@ -30,11 +40,11 @@ defineOptions({
30
40
  line below the input. Keep the group on a single row and let the input wrapper
31
41
  flex, so the trigger sits inline as an append. (#53)
32
42
  */
33
- :deep(.input-group) {
43
+ .d-autocomplete :deep(.input-group) {
34
44
  flex-wrap: nowrap;
35
45
  }
36
46
 
37
- :deep(.b-autocomplete-input-wrapper) {
47
+ .d-autocomplete :deep(.b-autocomplete-input-wrapper) {
38
48
  flex: 1 1 auto;
39
49
  min-width: 0;
40
50
  }
@@ -42,17 +52,20 @@ defineOptions({
42
52
  /*
43
53
  The trigger renders as a heavy `btn btn-secondary` (dark), which reads as a
44
54
  detached dark block. Soften it to a subtle bordered chevron that matches the
45
- input and reads as a combobox affordance. Uses theme variables (no hardcoded
46
- colours) and a more specific selector than `.btn-secondary` (no `!important`).
55
+ input and reads as a combobox affordance. Driving Bootstrap's own `--bs-btn-*`
56
+ variables (rather than raw properties) keeps hover/active/focus states
57
+ coherent and avoids fighting the `.btn-secondary` state selectors.
47
58
  */
48
- :deep(.b-autocomplete-trigger) {
49
- background-color: var(--bs-body-bg);
50
- border-color: var(--bs-border-color);
51
- color: var(--bs-secondary-color);
52
- }
53
-
54
- :deep(.b-autocomplete-trigger:hover) {
55
- background-color: var(--bs-tertiary-bg);
56
- color: var(--bs-body-color);
59
+ .d-autocomplete :deep(.b-autocomplete-trigger) {
60
+ --bs-btn-bg: var(--bs-body-bg);
61
+ --bs-btn-border-color: var(--bs-border-color);
62
+ --bs-btn-color: var(--bs-secondary-color);
63
+ --bs-btn-hover-bg: var(--bs-tertiary-bg);
64
+ --bs-btn-hover-border-color: var(--bs-border-color);
65
+ --bs-btn-hover-color: var(--bs-body-color);
66
+ --bs-btn-active-bg: var(--bs-secondary-bg);
67
+ --bs-btn-active-border-color: var(--bs-border-color);
68
+ --bs-btn-active-color: var(--bs-body-color);
69
+ flex: 0 0 auto;
57
70
  }
58
71
  </style>
@@ -1,6 +1,6 @@
1
1
  <!--
2
2
  @component
3
- Renders a single `FieldDefinition` of any type (text, select, checkbox, switch, repeater, currency, percentage, file/image, component, etc.) with its label, validation error, hint and help. Used by `DXForm` and `DXTable`'s edit modal; exposes `value`, `span`, `info`, `hint` and `repeater-row` slots for per-field customisation.
3
+ Renders a single `FieldDefinition` of any type (text, select, autocomplete, checkbox, switch, repeater, currency, percentage, file/image, component, etc.) with its label, validation error, hint and help. Used by `DXForm` and `DXTable`'s edit modal; exposes `value`, `span`, `info`, `hint` and `repeater-row` slots for per-field customisation.
4
4
  -->
5
5
  <template>
6
6
  <!-- Full-width span field: delegate entirely to the #span slot -->
@@ -265,6 +265,33 @@
265
265
  </template>
266
266
  </DInputGroup>
267
267
 
268
+ <!-- Autocomplete: a free-text input with a datalist of suggestions
269
+ (sync or async options). Unlike select, a value not in the list can
270
+ still be typed and submitted; the consumer validates. -->
271
+ <template v-else-if="field.type === 'autocomplete'">
272
+ <DFormInput
273
+ v-model="fieldValue"
274
+ type="text"
275
+ :list="datalistId"
276
+ :required="field.required"
277
+ :placeholder="field.placeholder"
278
+ :state="fieldState"
279
+ :disabled="isDisabled"
280
+ :readonly="isReadonly"
281
+ autocomplete="off"
282
+ v-bind="field.inputProps"
283
+ />
284
+ <datalist :id="datalistId">
285
+ <option
286
+ v-for="opt in resolvedOptions"
287
+ :key="String(opt.value)"
288
+ :value="String(opt.value)"
289
+ >
290
+ {{ opt.text }}
291
+ </option>
292
+ </datalist>
293
+ </template>
294
+
268
295
  <!-- Text-based inputs (text/email/password/number/url/tel/date/time/datetime) -->
269
296
  <DFormInput
270
297
  v-else
@@ -316,6 +343,7 @@ import {
316
343
  onBeforeUnmount,
317
344
  onMounted,
318
345
  ref,
346
+ useId,
319
347
  watch,
320
348
  } from "vue";
321
349
  import DFormGroup from "../base/DFormGroup.vue";
@@ -512,6 +540,10 @@ const inputType = computed<string>(() => {
512
540
  return type;
513
541
  });
514
542
 
543
+ // Unique, SSR-safe id linking an `autocomplete` field's input to its
544
+ // `<datalist>` of suggestions (via the input's `list` attribute).
545
+ const datalistId = useId();
546
+
515
547
  // ————————————————— async options
516
548
 
517
549
  const loadedOptions = ref<FieldOption[] | null>(null);
@@ -29,6 +29,7 @@ export type FieldType =
29
29
  | "percentage"
30
30
  | "textarea"
31
31
  | "select"
32
+ | "autocomplete"
32
33
  | "checkbox"
33
34
  | "switch"
34
35
  | "radio"
@@ -83,12 +84,17 @@ export interface FieldDefinition {
83
84
  /** Whether field is required (optional) */
84
85
  required?: boolean;
85
86
 
86
- /** Options for select or radio fields */
87
+ /**
88
+ * Options for `select`, `radio` and `autocomplete` fields. For
89
+ * `autocomplete` these are the datalist suggestions; the field still
90
+ * accepts free text not present in the list.
91
+ */
87
92
  options?: FieldOption[];
88
93
 
89
94
  /**
90
- * Asynchronously load options for select/radio fields. Takes
91
- * precedence over `options` once resolved.
95
+ * Asynchronously load options for `select`, `radio` and `autocomplete`
96
+ * fields (e.g. fetch a suggestion list). Takes precedence over `options`
97
+ * once resolved.
92
98
  */
93
99
  optionsLoader?: OptionsLoader;
94
100