@omnitend/dashboard-for-laravel 0.33.0 → 0.34.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 (50) hide show
  1. package/dist/charts.js +82 -90
  2. package/dist/charts.js.map +1 -1
  3. package/dist/charts.umd.cjs +1 -1
  4. package/dist/charts.umd.cjs.map +1 -1
  5. package/dist/components/base/DButton.vue.d.ts +1 -1
  6. package/dist/components/charts/DXBarChart.vue.d.ts +3 -18
  7. package/dist/components/charts/DXLineChart.vue.d.ts +3 -18
  8. package/dist/components/charts/useThemedChart.d.ts +35 -0
  9. package/dist/components/extended/DXChoiceField.vue.d.ts +26 -0
  10. package/dist/components/extended/DXDashboardSidebar.vue.d.ts +1 -1
  11. package/dist/components/extended/DXField.vue.d.ts +10 -113
  12. package/dist/components/extended/DXFieldShell.vue.d.ts +73 -0
  13. package/dist/components/extended/DXNumericField.vue.d.ts +23 -0
  14. package/dist/components/extended/DXRepeater.vue.d.ts +4 -4
  15. package/dist/components/extended/DXRepeaterCards.vue.d.ts +45 -0
  16. package/dist/components/extended/DXTable.vue.d.ts +91 -2
  17. package/dist/components/extended/DXTableEditorModal.vue.d.ts +17 -2
  18. package/dist/components/extended/DXUserAvatar.vue.d.ts +1 -1
  19. package/dist/composables/useAsyncOptions.d.ts +20 -0
  20. package/dist/composables/useResourceEditor.d.ts +2 -1
  21. package/dist/dashboard-for-laravel.js +9987 -10054
  22. package/dist/dashboard-for-laravel.js.map +1 -1
  23. package/dist/dashboard-for-laravel.umd.cjs +7 -7
  24. package/dist/dashboard-for-laravel.umd.cjs.map +1 -1
  25. package/dist/index.d.ts +3 -2
  26. package/dist/style.css +1 -1
  27. package/dist/types/index.d.ts +146 -0
  28. package/dist/utils/formSchema.d.ts +59 -0
  29. package/docs/public/api-reference.json +464 -30
  30. package/docs/public/docs-map.md +1 -1
  31. package/docs/public/llms.txt +5 -2
  32. package/package.json +1 -1
  33. package/resources/js/components/charts/DXBarChart.vue +4 -43
  34. package/resources/js/components/charts/DXLineChart.vue +4 -43
  35. package/resources/js/components/charts/useThemedChart.ts +69 -0
  36. package/resources/js/components/extended/DXChoiceField.vue +114 -0
  37. package/resources/js/components/extended/DXField.vue +328 -615
  38. package/resources/js/components/extended/DXFieldShell.vue +124 -0
  39. package/resources/js/components/extended/DXForm.vue +9 -5
  40. package/resources/js/components/extended/DXNumericField.vue +144 -0
  41. package/resources/js/components/extended/DXRepeater.vue +53 -175
  42. package/resources/js/components/extended/DXRepeaterCards.vue +133 -0
  43. package/resources/js/components/extended/DXTable.vue +250 -37
  44. package/resources/js/components/extended/DXTableEditorModal.vue +34 -2
  45. package/resources/js/composables/defineForm.ts +8 -44
  46. package/resources/js/composables/useAsyncOptions.ts +61 -0
  47. package/resources/js/composables/useResourceEditor.ts +24 -38
  48. package/resources/js/index.ts +33 -0
  49. package/resources/js/types/index.ts +231 -0
  50. package/resources/js/utils/formSchema.ts +126 -0
@@ -14,57 +14,18 @@
14
14
  </template>
15
15
 
16
16
  <script setup lang="ts">
17
- import { computed } from "vue";
18
17
  import { Bar } from "vue-chartjs";
19
- import {
20
- registerCharts,
21
- baseOptions,
22
- applyPalette,
23
- mergeOptions,
24
- type ChartValueFormat,
25
- } from "./chartTheme";
18
+ import { registerCharts } from "./chartTheme";
19
+ import { useThemedChart, type ThemedChartProps } from "./useThemedChart";
26
20
 
27
21
  registerCharts();
28
22
 
29
- interface Props {
30
- /** X-axis category labels. */
31
- labels: string[];
32
- /** Chart.js datasets. Colours are themed when a dataset omits them. */
33
- datasets: any[];
34
- /** Chart.js options; deep-merged over the themed defaults. */
35
- options?: Record<string, any>;
36
- /** Format value-axis ticks and tooltips. */
37
- valueFormat?: ChartValueFormat;
38
- /** Currency symbol for valueFormat: "currency" (default "£"). */
39
- currencySymbol?: string;
40
- /** Locale for number formatting. */
41
- locale?: string;
42
- /** Show the legend (default: only when there is more than one dataset). */
43
- showLegend?: boolean;
44
- }
45
-
46
23
  // `showLegend` defaults to `undefined` (not Vue's Boolean-cast `false`) so the
47
24
  // `?? datasets.length > 1` default can actually fire when it isn't passed.
48
- const props = withDefaults(defineProps<Props>(), {
25
+ const props = withDefaults(defineProps<ThemedChartProps<"bar">>(), {
49
26
  currencySymbol: "£",
50
27
  showLegend: undefined,
51
28
  });
52
29
 
53
- const chartData = computed(() => ({
54
- labels: props.labels,
55
- datasets: applyPalette(props.datasets, "bar", props.labels.length),
56
- }));
57
-
58
- const mergedOptions = computed(() =>
59
- mergeOptions(
60
- baseOptions({
61
- valueFormat: props.valueFormat,
62
- currencySymbol: props.currencySymbol,
63
- locale: props.locale,
64
- showLegend: props.showLegend ?? props.datasets.length > 1,
65
- hasValueAxis: true,
66
- }),
67
- props.options ?? {},
68
- ),
69
- );
30
+ const { chartData, mergedOptions } = useThemedChart("bar", props);
70
31
  </script>
@@ -14,57 +14,18 @@
14
14
  </template>
15
15
 
16
16
  <script setup lang="ts">
17
- import { computed } from "vue";
18
17
  import { Line } from "vue-chartjs";
19
- import {
20
- registerCharts,
21
- baseOptions,
22
- applyPalette,
23
- mergeOptions,
24
- type ChartValueFormat,
25
- } from "./chartTheme";
18
+ import { registerCharts } from "./chartTheme";
19
+ import { useThemedChart, type ThemedChartProps } from "./useThemedChart";
26
20
 
27
21
  registerCharts();
28
22
 
29
- interface Props {
30
- /** X-axis category labels. */
31
- labels: string[];
32
- /** Chart.js datasets. Colours are themed when a dataset omits them. */
33
- datasets: any[];
34
- /** Chart.js options; deep-merged over the themed defaults. */
35
- options?: Record<string, any>;
36
- /** Format value-axis ticks and tooltips. */
37
- valueFormat?: ChartValueFormat;
38
- /** Currency symbol for valueFormat: "currency" (default "£"). */
39
- currencySymbol?: string;
40
- /** Locale for number formatting. */
41
- locale?: string;
42
- /** Show the legend (default: only when there is more than one dataset). */
43
- showLegend?: boolean;
44
- }
45
-
46
23
  // `showLegend` defaults to `undefined` (not Vue's Boolean-cast `false`) so the
47
24
  // `?? datasets.length > 1` default can actually fire when it isn't passed.
48
- const props = withDefaults(defineProps<Props>(), {
25
+ const props = withDefaults(defineProps<ThemedChartProps<"line">>(), {
49
26
  currencySymbol: "£",
50
27
  showLegend: undefined,
51
28
  });
52
29
 
53
- const chartData = computed(() => ({
54
- labels: props.labels,
55
- datasets: applyPalette(props.datasets, "line", props.labels.length),
56
- }));
57
-
58
- const mergedOptions = computed(() =>
59
- mergeOptions(
60
- baseOptions({
61
- valueFormat: props.valueFormat,
62
- currencySymbol: props.currencySymbol,
63
- locale: props.locale,
64
- showLegend: props.showLegend ?? props.datasets.length > 1,
65
- hasValueAxis: true,
66
- }),
67
- props.options ?? {},
68
- ),
69
- );
30
+ const { chartData, mergedOptions } = useThemedChart("line", props);
70
31
  </script>
@@ -0,0 +1,69 @@
1
+ import { computed, type ComputedRef } from "vue";
2
+ import type { ChartData, ChartDataset, ChartOptions } from "chart.js";
3
+ import {
4
+ baseOptions,
5
+ applyPalette,
6
+ mergeOptions,
7
+ type ChartValueFormat,
8
+ } from "./chartTheme";
9
+
10
+ /**
11
+ * Shared props for the value-axis chart wrappers (`DXBarChart`, `DXLineChart`).
12
+ * `DXBarChart` and `DXLineChart` differ ONLY in the chart.js component they
13
+ * render and the palette kind — everything else (theming, option-merge,
14
+ * legend-default) is identical, and lived duplicated in both SFCs (#135).
15
+ */
16
+ export interface ThemedChartProps<TType extends "bar" | "line"> {
17
+ /** X-axis category labels. */
18
+ labels: string[];
19
+ /** Chart.js datasets. Colours are themed when a dataset omits them. */
20
+ datasets: ChartDataset<TType>[];
21
+ /** Chart.js options; deep-merged over the themed defaults. */
22
+ options?: ChartOptions<TType>;
23
+ /** Format value-axis ticks and tooltips. */
24
+ valueFormat?: ChartValueFormat;
25
+ /** Currency symbol for valueFormat: "currency" (default "£"). */
26
+ currencySymbol?: string;
27
+ /** Locale for number formatting. */
28
+ locale?: string;
29
+ /** Show the legend (default: only when there is more than one dataset). */
30
+ showLegend?: boolean;
31
+ }
32
+
33
+ /**
34
+ * The themed-chart body shared by `DXBarChart` and `DXLineChart`: applies the
35
+ * data-viz palette to un-coloured datasets and deep-merges the consumer's
36
+ * `options` over the dashboard-friendly defaults. Pass the reactive `props`
37
+ * object (property access stays reactive inside the computeds).
38
+ */
39
+ export function useThemedChart<TType extends "bar" | "line">(
40
+ type: TType,
41
+ props: ThemedChartProps<TType>,
42
+ ): {
43
+ chartData: ComputedRef<ChartData<TType>>;
44
+ mergedOptions: ComputedRef<ChartOptions<TType>>;
45
+ } {
46
+ const chartData = computed(
47
+ () =>
48
+ ({
49
+ labels: props.labels,
50
+ datasets: applyPalette(props.datasets, type, props.labels.length),
51
+ }) as ChartData<TType>,
52
+ );
53
+
54
+ const mergedOptions = computed(
55
+ () =>
56
+ mergeOptions(
57
+ baseOptions({
58
+ valueFormat: props.valueFormat,
59
+ currencySymbol: props.currencySymbol,
60
+ locale: props.locale,
61
+ showLegend: props.showLegend ?? props.datasets.length > 1,
62
+ hasValueAxis: true,
63
+ }),
64
+ props.options ?? {},
65
+ ) as ChartOptions<TType>,
66
+ );
67
+
68
+ return { chartData, mergedOptions };
69
+ }
@@ -0,0 +1,114 @@
1
+ <!--
2
+ @component (internal — not exported)
3
+ The choice control family for DXField: `select` (plain or `searchable`),
4
+ `radio`, and `checkbox-group`. Extracted from DXField (#135) unchanged. These
5
+ share the "no native readonly" convention (read-only is expressed as
6
+ `disabled`, hence the pre-merged `disabled` + `controlProps`). The parent
7
+ DXField still owns the value/options/guards and the `setValue` coercion; this
8
+ component only renders the control and emits the edited value up.
9
+
10
+ Plain-text `autocomplete` (a text input + datalist) stays in DXField itself,
11
+ with the text-family controls, because it uses the native-readonly guard path
12
+ rather than this disabled-only convention.
13
+ -->
14
+ <template>
15
+ <!-- Searchable select: type to filter a long option list, while the model
16
+ keeps the option's VALUE (an id), not the typed text. -->
17
+ <template v-if="field.type === 'select' && field.searchable">
18
+ <DAutocomplete
19
+ v-if="optionsReady"
20
+ :model-value="modelValue"
21
+ :options="options"
22
+ :placeholder="field.placeholder"
23
+ :required="field.required"
24
+ :state="state"
25
+ :disabled="disabled"
26
+ open-on-focus
27
+ v-bind="controlProps"
28
+ @update:model-value="emit('update:modelValue', $event)"
29
+ />
30
+ <!-- BAutocomplete resolves the input's display text from the model AT
31
+ MOUNT and doesn't re-derive it when `options` arrive later, so an
32
+ async list would leave the raw id showing ("51" instead of
33
+ "Waitrose") — and a long list is exactly the case that loads async.
34
+ Hold the control until the options are in. -->
35
+ <DFormInput v-else placeholder="Loading…" disabled />
36
+ </template>
37
+
38
+ <!-- Select (sync or async options) -->
39
+ <DFormSelect
40
+ v-else-if="field.type === 'select'"
41
+ :model-value="modelValue"
42
+ :required="field.required"
43
+ :options="options"
44
+ :state="state"
45
+ :disabled="disabled"
46
+ v-bind="controlProps"
47
+ @update:model-value="emit('update:modelValue', $event)"
48
+ />
49
+
50
+ <!-- Radio group -->
51
+ <DFormRadioGroup
52
+ v-else-if="field.type === 'radio'"
53
+ :model-value="modelValue"
54
+ :options="options"
55
+ :required="field.required"
56
+ :state="state"
57
+ :disabled="disabled"
58
+ v-bind="controlProps"
59
+ @update:model-value="emit('update:modelValue', $event)"
60
+ />
61
+
62
+ <!-- Checkbox group: "pick any of N" — the model is an ARRAY of the checked
63
+ option values (default the field to []). -->
64
+ <DFormCheckboxGroup
65
+ v-else
66
+ :model-value="modelValue"
67
+ :options="options"
68
+ :state="state"
69
+ :disabled="disabled"
70
+ v-bind="controlProps"
71
+ @update:model-value="emit('update:modelValue', $event)"
72
+ />
73
+ </template>
74
+
75
+ <script setup lang="ts">
76
+ import DFormSelect from "../base/DFormSelect.vue";
77
+ import DFormRadioGroup from "../base/DFormRadioGroup.vue";
78
+ import DFormCheckboxGroup from "../base/DFormCheckboxGroup.vue";
79
+ import DFormInput from "../base/DFormInput.vue";
80
+ import DAutocomplete from "../base/DAutocomplete.vue";
81
+ import type { FieldDefinition, FieldOption } from "../../types";
82
+
83
+ interface Props {
84
+ /** Field definition (type select/radio/checkbox-group + `searchable`). */
85
+ field: FieldDefinition;
86
+
87
+ /** Current model value. */
88
+ modelValue: any;
89
+
90
+ /** Resolved options (async-loaded or static). */
91
+ options?: FieldOption[];
92
+
93
+ /** Validation state passed to the control. */
94
+ state?: boolean | null;
95
+
96
+ /** Pre-merged disabled state (`isDisabled || isReadonly || isPlaintext`). */
97
+ disabled?: boolean;
98
+
99
+ /** Escape-hatch control props, already guard-merged by DXField. */
100
+ controlProps?: Record<string, any>;
101
+
102
+ /**
103
+ * Whether async options have resolved (a searchable select must not render
104
+ * before its options load, or it shows the raw id instead of the label).
105
+ */
106
+ optionsReady?: boolean;
107
+ }
108
+
109
+ defineProps<Props>();
110
+
111
+ const emit = defineEmits<{
112
+ (event: "update:modelValue", value: any): void;
113
+ }>();
114
+ </script>