@omnitend/dashboard-for-laravel 0.4.14 → 0.6.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 (35) hide show
  1. package/dist/components/base/DButton.vue.d.ts +2 -3
  2. package/dist/components/base/DTable.vue.d.ts +11 -3
  3. package/dist/components/extended/DXBasicForm.vue.d.ts +4 -33
  4. package/dist/components/extended/DXField.vue.d.ts +88 -0
  5. package/dist/components/extended/DXForm.vue.d.ts +34 -8
  6. package/dist/components/extended/DXRepeater.vue.d.ts +30 -0
  7. package/dist/components/extended/DXTable.vue.d.ts +10 -17
  8. package/dist/dashboard-for-laravel.js +31131 -16052
  9. package/dist/dashboard-for-laravel.js.map +1 -1
  10. package/dist/dashboard-for-laravel.umd.cjs +10 -7
  11. package/dist/dashboard-for-laravel.umd.cjs.map +1 -1
  12. package/dist/index.d.ts +12 -4
  13. package/dist/style.css +1 -1
  14. package/dist/types/index.d.ts +114 -9
  15. package/dist/utils/objectPath.d.ts +18 -0
  16. package/docs/public/api-reference.json +354 -130
  17. package/docs/public/docs-map.md +5 -4
  18. package/docs/public/llms.txt +8 -7
  19. package/package.json +3 -3
  20. package/resources/js/components/base/DButton.vue +2 -3
  21. package/resources/js/components/base/{DCarousel.vue → DFormRadioGroup.vue} +5 -5
  22. package/resources/js/components/base/DTable.vue +39 -3
  23. package/resources/js/components/base/DToaster.vue +5 -3
  24. package/resources/js/components/extended/DXBasicForm.vue +35 -184
  25. package/resources/js/components/extended/DXField.vue +402 -0
  26. package/resources/js/components/extended/DXForm.vue +282 -17
  27. package/resources/js/components/extended/DXRepeater.vue +216 -0
  28. package/resources/js/components/extended/DXTable.vue +96 -210
  29. package/resources/js/composables/defineForm.ts +7 -0
  30. package/resources/js/index.ts +18 -3
  31. package/resources/js/types/index.ts +146 -9
  32. package/resources/js/utils/objectPath.ts +59 -0
  33. package/dist/components/base/DCarouselSlide.vue.d.ts +0 -12
  34. package/resources/js/components/base/DCarouselSlide.vue +0 -14
  35. /package/dist/components/base/{DCarousel.vue.d.ts → DFormRadioGroup.vue.d.ts} +0 -0
@@ -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 61 Vue 3 components for building Laravel dashboards with Bootstrap Vue Next.
5
+ > A dual-package library (NPM + Composer) providing 62 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 (55 components)
22
+ ## Base Components (54 components)
23
23
 
24
24
  Lightweight type-safe wrappers around Bootstrap Vue Next components providing API stability and consistent theming.
25
25
 
@@ -33,8 +33,6 @@ Lightweight type-safe wrappers around Bootstrap Vue Next components providing AP
33
33
  - [DButtonGroup](/components/base/dbuttongroup): Bootstrap Vue Next ButtonGroup wrapper
34
34
  - [DButtonToolbar](/components/base/dbuttontoolbar): Bootstrap Vue Next ButtonToolbar wrapper
35
35
  - [DCard](/components/base/dcard): Bootstrap Vue Next Card wrapper
36
- - [DCarousel](/components/base/dcarousel): Bootstrap Vue Next Carousel wrapper
37
- - [DCarouselSlide](/components/base/dcarouselslide): Bootstrap Vue Next CarouselSlide wrapper
38
36
  - [DCol](/components/base/dcol): Bootstrap Vue Next Col wrapper
39
37
  - [DCollapse](/components/base/dcollapse): Bootstrap Vue Next Collapse wrapper
40
38
  - [DContainer](/components/base/dcontainer): Bootstrap Vue Next Container wrapper
@@ -47,6 +45,7 @@ Lightweight type-safe wrappers around Bootstrap Vue Next components providing AP
47
45
  - [DFormInput](/components/base/dforminput): Bootstrap Vue Next FormInput wrapper
48
46
  - [DFormInvalidFeedback](/components/base/dforminvalidfeedback): Bootstrap Vue Next FormInvalidFeedback wrapper
49
47
  - [DFormRadio](/components/base/dformradio): Bootstrap Vue Next FormRadio wrapper
48
+ - [DFormRadioGroup](/components/base/dformradiogroup): Bootstrap Vue Next FormRadioGroup wrapper
50
49
  - [DFormSelect](/components/base/dformselect): Bootstrap Vue Next FormSelect wrapper
51
50
  - [DFormSpinbutton](/components/base/dformspinbutton): Bootstrap Vue Next FormSpinbutton wrapper
52
51
  - [DFormTags](/components/base/dformtags): Bootstrap Vue Next FormTags wrapper
@@ -79,15 +78,17 @@ Lightweight type-safe wrappers around Bootstrap Vue Next components providing AP
79
78
  - [DToaster](/components/base/dtoaster): Bootstrap Vue Next Toaster wrapper
80
79
  - [DTooltip](/components/base/dtooltip): Bootstrap Vue Next Tooltip wrapper
81
80
 
82
- ## Extended Components (6 components)
81
+ ## Extended Components (8 components)
83
82
 
84
83
  Custom dashboard components with advanced functionality beyond Bootstrap Vue Next.
85
84
 
86
- - [DXBasicForm](/components/extended/dxbasicform): Auto-generated forms from field definitions
85
+ - [DXBasicForm](/components/extended/dxbasicform): Extended dashboard component
87
86
  - [DXDashboard](/components/extended/dxdashboard): Complete dashboard layout with sidebar and navbar
88
87
  - [DXDashboardNavbar](/components/extended/dxdashboardnavbar): Top navbar with user dropdown
89
88
  - [DXDashboardSidebar](/components/extended/dxdashboardsidebar): Collapsible sidebar with navigation
90
- - [DXForm](/components/extended/dxform): Advanced form wrapper with defineForm integration
89
+ - [DXField](/components/extended/dxfield): Single-field renderer for any field type with value/span/info/hint slots
90
+ - [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
91
+ - [DXRepeater](/components/extended/dxrepeater): Repeatable nested sub-form (field array) primitive
91
92
  - [DXTable](/components/extended/dxtable): Data table with pagination, filtering, and sorting
92
93
 
93
94
  ## Composables
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnitend/dashboard-for-laravel",
3
- "version": "0.4.14",
3
+ "version": "0.6.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",
@@ -47,7 +47,7 @@
47
47
  "peerDependencies": {
48
48
  "@inertiajs/vue3": "^2.0.0",
49
49
  "axios": "^1.6.0",
50
- "vue": "^3.4.0"
50
+ "vue": "^3.5.13"
51
51
  },
52
52
  "peerDependenciesMeta": {
53
53
  "axios": {
@@ -59,7 +59,7 @@
59
59
  },
60
60
  "dependencies": {
61
61
  "@modelcontextprotocol/sdk": "^1.22.0",
62
- "bootstrap-vue-next": "^0.40.8",
62
+ "bootstrap-vue-next": "^0.45.6",
63
63
  "highlight.js": "^11.11.1",
64
64
  "pluralize": "^8.0.0",
65
65
  "rehype-autolink-headings": "^7.1.0",
@@ -33,15 +33,14 @@ interface Props {
33
33
  variant?: ButtonVariant | LinkVariant | null;
34
34
 
35
35
  /**
36
- * The size of the button
37
- * @default 'md'
36
+ * The size of the button. Omit for the default (medium) size —
37
+ * bootstrap-vue-next 0.45 removed the no-op `'md'` value from `Size`.
38
38
  */
39
39
  size?: Size;
40
40
  }
41
41
 
42
42
  withDefaults(defineProps<Props>(), {
43
43
  variant: 'primary',
44
- size: 'md',
45
44
  });
46
45
  </script>
47
46
 
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * @component
3
- * Type-safe wrapper around Bootstrap Vue Next BCarousel component.
4
- * Slideshow component for cycling through images or content.
3
+ * Type-safe wrapper around Bootstrap Vue Next BFormRadioGroup component.
4
+ * Renders a group of radio inputs from an `options` array or slot content.
5
5
  */
6
6
  <script setup lang="ts">
7
- import { BCarousel } from "bootstrap-vue-next";
7
+ import { BFormRadioGroup } from "bootstrap-vue-next";
8
8
 
9
9
  defineOptions({
10
10
  inheritAttrs: false,
@@ -12,10 +12,10 @@ defineOptions({
12
12
  </script>
13
13
 
14
14
  <template>
15
- <BCarousel v-bind="$attrs">
15
+ <BFormRadioGroup v-bind="$attrs">
16
16
  <!-- Dynamically pass through all named slots with their props -->
17
17
  <template v-for="(_, name) in $slots" :key="name" #[name]="slotProps">
18
18
  <slot :name="name" v-bind="slotProps" />
19
19
  </template>
20
- </BCarousel>
20
+ </BFormRadioGroup>
21
21
  </template>
@@ -2,6 +2,7 @@
2
2
  <BTable
3
3
  ref="bTableRef"
4
4
  v-bind="$attrs"
5
+ :fields="shieldedFields"
5
6
  @update:sort-by="handleSortByUpdate"
6
7
  @update:current-page="handleCurrentPageUpdate"
7
8
  @update:busy="handleBusyUpdate"
@@ -15,19 +16,49 @@
15
16
  </template>
16
17
 
17
18
  <script setup lang="ts">
18
- import { ref } from 'vue';
19
+ import { ref, computed } from 'vue';
19
20
  import { BTable } from "bootstrap-vue-next";
20
21
 
21
22
  defineOptions({
22
23
  inheritAttrs: false,
23
24
  });
24
25
 
26
+ const props = defineProps<{
27
+ /**
28
+ * Column definitions. Declared as a prop (rather than passed through
29
+ * `$attrs`) so we can shield the field `formatter` signature across
30
+ * bootstrap-vue-next versions.
31
+ */
32
+ fields?: any[];
33
+ }>();
34
+
25
35
  // Define emits to forward BTable events
26
36
  const emit = defineEmits(['update:sortBy', 'update:currentPage', 'update:busy', 'sorted', 'rowClicked']);
27
37
 
28
38
  // Reference to BTable for exposing methods
29
39
  const bTableRef = ref<any>(null);
30
40
 
41
+ /**
42
+ * bootstrap-vue-next 0.43 changed the field `formatter` to receive a single
43
+ * object `{ value, key, item }`. This library has always documented the
44
+ * positional `(value, key, item)` signature, so wrap each formatter to keep
45
+ * existing consumer formatters working across the upgrade.
46
+ */
47
+ const shieldedFields = computed(() => {
48
+ if (!props.fields) return undefined;
49
+ return props.fields.map((field) => {
50
+ if (field && typeof field.formatter === 'function') {
51
+ const original = field.formatter;
52
+ return {
53
+ ...field,
54
+ formatter: (obj: { value: unknown; key: string; item: any }) =>
55
+ original(obj?.value, obj?.key, obj?.item),
56
+ };
57
+ }
58
+ return field;
59
+ });
60
+ });
61
+
31
62
  // Event handlers to forward BTable events
32
63
  const handleSortByUpdate = (val: any) => {
33
64
  emit('update:sortBy', val);
@@ -45,8 +76,13 @@ const handleSorted = (val: any) => {
45
76
  emit('sorted', val);
46
77
  };
47
78
 
48
- const handleRowClicked = (item: any, index: number, event: MouseEvent) => {
49
- emit('rowClicked', item, index, event);
79
+ /**
80
+ * bootstrap-vue-next 0.43 changed row events to a single object payload
81
+ * `{ item, index, event }`. Re-emit in the historic `(item, index, event)`
82
+ * shape so consumers (incl. DXTable) keep their handler signatures.
83
+ */
84
+ const handleRowClicked = (obj: any) => {
85
+ emit('rowClicked', obj?.item, obj?.index, obj?.event);
50
86
  };
51
87
 
52
88
  // Expose refresh method from BTable
@@ -1,5 +1,7 @@
1
1
  <script setup lang="ts">
2
- import { BToastOrchestrator } from "bootstrap-vue-next";
2
+ // bootstrap-vue-next 0.44 removed BToastOrchestrator; the toast/modal/popover
3
+ // renderer is now the unified BOrchestrator (also included inside BApp).
4
+ import { BOrchestrator } from "bootstrap-vue-next";
3
5
 
4
6
  defineOptions({
5
7
  inheritAttrs: false,
@@ -7,10 +9,10 @@ defineOptions({
7
9
  </script>
8
10
 
9
11
  <template>
10
- <BToastOrchestrator v-bind="$attrs">
12
+ <BOrchestrator v-bind="$attrs">
11
13
  <!-- Dynamically pass through all named slots with their props -->
12
14
  <template v-for="(_, name) in $slots" :key="name" #[name]="slotProps">
13
15
  <slot :name="name" v-bind="slotProps" />
14
16
  </template>
15
- </BToastOrchestrator>
17
+ </BOrchestrator>
16
18
  </template>
@@ -1,189 +1,40 @@
1
- <template>
2
- <BForm @submit.prevent="handleSubmit">
3
- <!-- Form-level error message -->
4
- <DAlert
5
- v-if="form.shouldShowMessage"
6
- :model-value="form.shouldShowMessage"
7
- variant="danger"
8
- class="mb-3"
9
- >
10
- {{ form.message }}
11
- </DAlert>
12
-
13
- <!-- Render each field -->
14
- <template v-for="field in visibleFields" :key="field.key">
15
- <!-- Custom slot for this field -->
16
- <slot :name="`field-${field.key}`" :field="field" :form="form">
17
- <!-- Default field rendering -->
18
- <DFormGroup
19
- :label="field.label"
20
- :label-for="field.key"
21
- :class="field.class || 'mb-3'"
22
- >
23
- <!-- Text-based inputs -->
24
- <DFormInput
25
- v-if="isTextInput(field.type)"
26
- :id="field.key"
27
- v-model="form.data[field.key]"
28
- :type="field.type"
29
- :required="field.required"
30
- :placeholder="field.placeholder"
31
- :state="form.getState(field.key)"
32
- v-bind="field.inputProps"
33
- @input="form.clearError(field.key)"
34
- />
35
-
36
- <!-- Textarea -->
37
- <DFormTextarea
38
- v-else-if="field.type === 'textarea'"
39
- :id="field.key"
40
- v-model="form.data[field.key]"
41
- :required="field.required"
42
- :placeholder="field.placeholder"
43
- :rows="field.rows || 3"
44
- :state="form.getState(field.key)"
45
- v-bind="field.inputProps"
46
- @input="form.clearError(field.key)"
47
- />
48
-
49
- <!-- Select -->
50
- <DFormSelect
51
- v-else-if="field.type === 'select'"
52
- :id="field.key"
53
- v-model="form.data[field.key]"
54
- :required="field.required"
55
- :options="field.options"
56
- :state="form.getState(field.key)"
57
- v-bind="field.inputProps"
58
- @change="form.clearError(field.key)"
59
- />
60
-
61
- <!-- Checkbox -->
62
- <DFormCheckbox
63
- v-else-if="field.type === 'checkbox'"
64
- :id="field.key"
65
- v-model="form.data[field.key]"
66
- v-bind="field.inputProps"
67
- >
68
- {{ field.label }}
69
- </DFormCheckbox>
70
-
71
- <!-- Radio group -->
72
- <BFormRadioGroup
73
- v-else-if="field.type === 'radio'"
74
- :id="field.key"
75
- v-model="form.data[field.key]"
76
- :options="field.options"
77
- :required="field.required"
78
- :state="form.getState(field.key)"
79
- v-bind="field.inputProps"
80
- @change="form.clearError(field.key)"
81
- />
82
-
83
- <!-- Validation error -->
84
- <DFormInvalidFeedback v-if="form.hasError(field.key)">
85
- {{ form.getError(field.key) }}
86
- </DFormInvalidFeedback>
87
-
88
- <!-- Help text -->
89
- <DFormText v-if="field.help">
90
- {{ field.help }}
91
- </DFormText>
92
- </DFormGroup>
93
- </slot>
94
- </template>
95
-
96
- <!-- Submit button -->
97
- <DButton
98
- v-if="showSubmit"
99
- type="submit"
100
- variant="primary"
101
- :disabled="form.processing"
102
- class="w-100"
103
- >
104
- <span v-if="form.processing">{{ submitLoadingText }}</span>
105
- <span v-else>{{ submitText }}</span>
106
- </DButton>
107
-
108
- <!-- Footer slot -->
109
- <slot name="footer"></slot>
110
- </BForm>
111
- </template>
1
+ <!--
2
+ DXBasicForm — deprecated alias of DXForm.
3
+
4
+ A flat form is just DXForm without a `tabs` prop. This wrapper forwards
5
+ everything to DXForm and logs a one-time deprecation warning so existing
6
+ callers keep working while they migrate. Remove in a future major.
7
+ -->
8
+ <script lang="ts">
9
+ // Module scope: warn at most once per session, not once per instance.
10
+ let hasWarned = false;
11
+ </script>
112
12
 
113
13
  <script setup lang="ts">
114
- import { computed } from "vue";
115
- import { BForm, BFormRadioGroup } from "bootstrap-vue-next";
116
- import DAlert from "../base/DAlert.vue";
117
- import DFormGroup from "../base/DFormGroup.vue";
118
- import DFormInput from "../base/DFormInput.vue";
119
- import DFormTextarea from "../base/DFormTextarea.vue";
120
- import DFormSelect from "../base/DFormSelect.vue";
121
- import DFormCheckbox from "../base/DFormCheckbox.vue";
122
- import DFormInvalidFeedback from "../base/DFormInvalidFeedback.vue";
123
- import DFormText from "../base/DFormText.vue";
124
- import DButton from "../base/DButton.vue";
125
- import type { UseFormReturn } from "../../composables/useForm";
126
- import type { FieldDefinition, FieldType } from "../../types";
127
-
128
- interface Props {
129
- /** Form instance from useForm composable */
130
- form: UseFormReturn<any>;
131
-
132
- /** Field definitions */
133
- fields: FieldDefinition[];
134
-
135
- /** Submit button text */
136
- submitText?: string;
137
-
138
- /** Submit button loading text */
139
- submitLoadingText?: string;
140
-
141
- /** Show submit button */
142
- showSubmit?: boolean;
143
- }
144
-
145
- const props = withDefaults(defineProps<Props>(), {
146
- submitText: "Submit",
147
- submitLoadingText: "Submitting...",
148
- showSubmit: true,
149
- });
150
-
151
- /**
152
- * Fields whose `show()` predicate evaluates to true (or omits the
153
- * predicate entirely). Computed so the form re-renders when reactive
154
- * sources used inside `show` change.
155
- */
156
- const visibleFields = computed(() => {
157
- return props.fields.filter((field) =>
158
- field.show ? field.show() : true,
14
+ import { onMounted } from "vue";
15
+ import DXForm from "./DXForm.vue";
16
+
17
+ defineOptions({ inheritAttrs: false });
18
+
19
+ onMounted(() => {
20
+ if (hasWarned) return;
21
+ hasWarned = true;
22
+ console.warn(
23
+ "[dashboard-for-laravel] DXBasicForm is deprecated and will be " +
24
+ "removed in a future major version. Use DXForm instead " +
25
+ "(a flat form is DXForm without a `tabs` prop).",
159
26
  );
160
27
  });
161
-
162
- const emit = defineEmits<{
163
- submit: [];
164
- }>();
165
-
166
- /**
167
- * Check if field type is a text-based input
168
- */
169
- const isTextInput = (type: FieldType): boolean => {
170
- return [
171
- "text",
172
- "email",
173
- "password",
174
- "number",
175
- "url",
176
- "tel",
177
- "date",
178
- "datetime-local",
179
- "time",
180
- ].includes(type);
181
- };
182
-
183
- /**
184
- * Handle form submission
185
- */
186
- const handleSubmit = () => {
187
- emit("submit");
188
- };
189
28
  </script>
29
+
30
+ <template>
31
+ <!-- `form`/`fields`/etc. arrive via $attrs (inheritAttrs: false) and are
32
+ forwarded to DXForm. Cast because the type-checker can't see the
33
+ required `form` prop inside the untyped attrs spread. -->
34
+ <DXForm v-bind="($attrs as any)">
35
+ <!-- Forward all slots (#value(<key>), #footer, etc.) to DXForm. -->
36
+ <template v-for="(_, name) in $slots" :key="name" #[name]="slotProps">
37
+ <slot :name="name" v-bind="slotProps" />
38
+ </template>
39
+ </DXForm>
40
+ </template>