quasar-ui-danx 0.4.2 → 0.4.4

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 (75) hide show
  1. package/dist/danx.es.js +7127 -6615
  2. package/dist/danx.es.js.map +1 -1
  3. package/dist/danx.umd.js +11 -5
  4. package/dist/danx.umd.js.map +1 -1
  5. package/dist/style.css +1 -1
  6. package/package.json +3 -1
  7. package/src/components/ActionTable/ActionTable.vue +28 -41
  8. package/src/components/ActionTable/Columns/ActionTableColumn.vue +19 -18
  9. package/src/components/ActionTable/Filters/CollapsableFiltersSidebar.vue +6 -6
  10. package/src/components/ActionTable/Filters/{FilterFieldList.vue → FilterList.vue} +26 -26
  11. package/src/components/ActionTable/Filters/FilterableField.vue +28 -31
  12. package/src/components/ActionTable/Filters/index.ts +2 -2
  13. package/src/components/ActionTable/Form/Fields/EditOnClickTextField.vue +71 -0
  14. package/src/components/ActionTable/Form/Fields/FieldLabel.vue +8 -13
  15. package/src/components/ActionTable/Form/Fields/MultiFileField.vue +48 -44
  16. package/src/components/ActionTable/Form/Fields/SelectField.vue +24 -38
  17. package/src/components/ActionTable/Form/Fields/SelectWithChildrenField.vue +28 -33
  18. package/src/components/ActionTable/Form/Fields/SingleFileField.vue +15 -15
  19. package/src/components/ActionTable/Form/Fields/SliderNumberField.vue +45 -0
  20. package/src/components/ActionTable/Form/Fields/TextField.vue +47 -66
  21. package/src/components/ActionTable/Form/Fields/index.ts +2 -0
  22. package/src/components/ActionTable/Form/RenderedForm.vue +50 -9
  23. package/src/components/ActionTable/Form/Utilities/MaxLengthCounter.vue +17 -0
  24. package/src/components/ActionTable/Form/Utilities/index.ts +1 -0
  25. package/src/components/ActionTable/Form/index.ts +1 -0
  26. package/src/components/ActionTable/Layouts/ActionTableLayout.vue +16 -15
  27. package/src/components/ActionTable/Toolbars/ActionToolbar.vue +6 -6
  28. package/src/components/ActionTable/listControls.ts +106 -166
  29. package/src/components/ActionTable/listHelpers.ts +2 -3
  30. package/src/components/ActionTable/tableColumns.ts +3 -27
  31. package/src/components/AuditHistory/AuditHistoryItemValue.vue +26 -26
  32. package/src/components/PanelsDrawer/PanelsDrawer.vue +17 -4
  33. package/src/components/PanelsDrawer/PanelsDrawerPanels.vue +6 -11
  34. package/src/components/PanelsDrawer/PanelsDrawerTabs.vue +20 -20
  35. package/src/components/Utility/Dialogs/ConfirmActionDialog.vue +39 -0
  36. package/src/components/Utility/Dialogs/ConfirmDialog.vue +10 -24
  37. package/src/components/Utility/Dialogs/DialogLayout.vue +10 -28
  38. package/src/components/Utility/Dialogs/FullscreenCarouselDialog.vue +42 -36
  39. package/src/components/Utility/Dialogs/index.ts +1 -0
  40. package/src/components/Utility/Files/FilePreview.vue +76 -73
  41. package/src/components/Utility/Layouts/ContentDrawer.vue +24 -31
  42. package/src/components/Utility/Tools/ActionVnode.vue +3 -3
  43. package/src/components/Utility/Tools/RenderVnode.vue +1 -1
  44. package/src/components/Utility/Transitions/MaxHeightTransition.vue +26 -0
  45. package/src/components/Utility/Transitions/index.ts +1 -0
  46. package/src/config/index.ts +36 -31
  47. package/src/helpers/FileUpload.ts +295 -297
  48. package/src/helpers/FlashMessages.ts +80 -71
  49. package/src/helpers/actions.ts +102 -82
  50. package/src/helpers/download.ts +189 -189
  51. package/src/helpers/downloadPdf.ts +55 -52
  52. package/src/helpers/formats.ts +151 -109
  53. package/src/helpers/index.ts +2 -0
  54. package/src/helpers/multiFileUpload.ts +72 -58
  55. package/src/helpers/objectStore.ts +52 -0
  56. package/src/helpers/request.ts +70 -51
  57. package/src/helpers/routes.ts +29 -0
  58. package/src/helpers/storage.ts +7 -3
  59. package/src/helpers/utils.ts +47 -29
  60. package/src/styles/quasar-reset.scss +16 -1
  61. package/src/styles/themes/danx/dialogs.scss +4 -0
  62. package/src/types/actions.d.ts +43 -0
  63. package/src/types/config.d.ts +15 -0
  64. package/src/types/controls.d.ts +99 -0
  65. package/src/types/dialogs.d.ts +32 -0
  66. package/src/types/fields.d.ts +20 -0
  67. package/src/types/files.d.ts +54 -0
  68. package/src/types/formats.d.ts +4 -0
  69. package/src/{components/ActionTable/Form/form.d.ts → types/forms.d.ts} +6 -0
  70. package/src/types/index.d.ts +12 -0
  71. package/src/types/requests.d.ts +13 -0
  72. package/src/types/shared.d.ts +15 -0
  73. package/src/types/tables.d.ts +27 -0
  74. package/types/index.d.ts +1 -1
  75. /package/src/components/ActionTable/Filters/{FilterFieldItem.vue → FilterItem.vue} +0 -0
@@ -64,47 +64,33 @@
64
64
  </QSelect>
65
65
  </div>
66
66
  </template>
67
- <script setup>
67
+ <script setup lang="ts">
68
68
  import { ChevronDownIcon as DropDownIcon } from "@heroicons/vue/outline";
69
- import { QSelect } from "quasar";
69
+ import { QSelect, QSelectProps } from "quasar";
70
70
  import { computed, isRef, nextTick, ref } from "vue";
71
71
 
72
+ export interface Props extends QSelectProps {
73
+ modelValue?: any;
74
+ placeholder?: string;
75
+ selectionLabel?: string | ((option) => string);
76
+ chipLimit?: number;
77
+ inputClass?: string;
78
+ selectionClass?: string;
79
+ options?: unknown[];
80
+ filterable?: boolean;
81
+ filterFn?: (val: string) => void;
82
+ }
83
+
72
84
  const emit = defineEmits(["update:model-value", "search", "update"]);
73
- const props = defineProps({
74
- ...QSelect.props,
75
- modelValue: {
76
- type: [Array, String, Number, Object],
77
- default: undefined
78
- },
79
- placeholder: {
80
- type: String,
81
- default: ""
82
- },
83
- selectionLabel: {
84
- type: String,
85
- default: null
86
- },
87
- chipLimit: {
88
- type: Number,
89
- default: 3
90
- },
91
- inputClass: {
92
- type: String,
93
- default: ""
94
- },
95
- selectionClass: {
96
- type: String,
97
- default: ""
98
- },
99
- options: {
100
- type: Array,
101
- default: () => []
102
- },
103
- filterable: Boolean,
104
- filterFn: {
105
- type: Function,
106
- default: null
107
- }
85
+ const props = withDefaults(defineProps<Props>(), {
86
+ modelValue: undefined,
87
+ placeholder: "",
88
+ selectionLabel: null,
89
+ chipLimit: 3,
90
+ inputClass: "",
91
+ selectionClass: "",
92
+ options: () => [],
93
+ filterFn: null
108
94
  });
109
95
 
110
96
  const selectField = ref(null);
@@ -136,7 +122,7 @@ const computedOptions = computed(() => {
136
122
 
137
123
  const filteredOptions = computed(() => {
138
124
  if (filter.value && !props.filterFn) {
139
- return computedOptions.value.filter(o => o.label.toLocaleLowerCase().indexOf(filter.value.toLowerCase()) > -1);
125
+ return computedOptions.value.filter(o => o.label.toLocaleLowerCase().indexOf(filter.value?.toLowerCase()) > -1);
140
126
  } else {
141
127
  return computedOptions.value;
142
128
  }
@@ -31,55 +31,50 @@
31
31
  </div>
32
32
  </div>
33
33
  </template>
34
- <script setup>
34
+ <script setup lang="ts">
35
35
  import { ref, watch } from "vue";
36
36
  import { remove } from "../../../../helpers";
37
37
  import SelectField from "./SelectField";
38
38
 
39
+ export interface SelectWithChildrenFieldProps {
40
+ modelValue?: string[];
41
+ label?: string;
42
+ placeholder?: string;
43
+ options?: any[];
44
+ loading?: boolean;
45
+ }
46
+
39
47
  const emit = defineEmits(["update:model-value"]);
40
- const props = defineProps({
41
- modelValue: {
42
- type: Array,
43
- default: () => ([])
44
- },
45
- label: {
46
- type: String,
47
- default: "Selection"
48
- },
49
- placeholder: {
50
- type: String,
51
- default: "Select an option"
52
- },
53
- options: {
54
- type: Array,
55
- default: () => []
56
- },
57
- loading: Boolean
48
+ const props = withDefaults(defineProps<SelectWithChildrenFieldProps>(), {
49
+ modelValue: () => [],
50
+ label: "Selection",
51
+ placeholder: "Select an option",
52
+ options: () => []
58
53
  });
59
54
 
60
55
  function resolveSelectedOption() {
61
- if (props.modelValue?.length > 0) {
62
- return props.options.find((option) => option.children.find(child => props.modelValue.includes(child.id)));
63
- }
56
+ if (props.modelValue?.length > 0) {
57
+ return props.options.find((option) => option.children.find(child => props.modelValue.includes(child.id)));
58
+ }
64
59
 
65
- return null;
60
+ return null;
66
61
  }
67
62
  const selectedOption = ref(resolveSelectedOption());
68
63
  const selectedChildren = ref(props.modelValue || []);
69
64
  function onSelectChild(child) {
70
- if (selectedChildren.value.includes(child.id)) {
71
- selectedChildren.value = remove(selectedChildren.value, child.id);
72
- } else {
73
- selectedChildren.value.push(child.id);
74
- }
75
- emit("update:model-value", selectedChildren.value.length > 0 ? selectedChildren.value : undefined);
65
+ if (selectedChildren.value.includes(child.id)) {
66
+ selectedChildren.value = remove(selectedChildren.value, child.id);
67
+ } else {
68
+ selectedChildren.value.push(child.id);
69
+ }
70
+ emit("update:model-value", selectedChildren.value.length > 0 ? selectedChildren.value : undefined);
76
71
  }
77
72
  function onSelectOption() {
78
- selectedChildren.value = [];
79
- emit("update:model-value", undefined);
73
+ selectedChildren.value = [];
74
+ emit("update:model-value", undefined);
80
75
  }
81
76
  watch(() => props.modelValue, (value) => {
82
- selectedOption.value = resolveSelectedOption();
83
- selectedChildren.value = value || [];
77
+ selectedOption.value = resolveSelectedOption();
78
+ selectedChildren.value = value || [];
84
79
  });
85
80
  </script>
@@ -35,7 +35,7 @@
35
35
  v-if="!readonly || uploadedFile"
36
36
  class="w-32 cursor-pointer mt-2"
37
37
  :class="{'border border-dashed border-blue-600': !uploadedFile, 'mx-auto': !readonly}"
38
- :image="uploadedFile"
38
+ :file="uploadedFile"
39
39
  downloadable
40
40
  @click="!disable && $refs.file.click()"
41
41
  />
@@ -56,24 +56,24 @@ import FieldLabel from "./FieldLabel";
56
56
 
57
57
  const emit = defineEmits(["update:model-value"]);
58
58
  const props = defineProps({
59
- modelValue: {
60
- type: [Object, String],
61
- default: null
62
- },
63
- field: {
64
- type: Object,
65
- required: true
66
- },
67
- showName: Boolean,
68
- disable: Boolean,
69
- readonly: Boolean
59
+ modelValue: {
60
+ type: [Object, String],
61
+ default: null
62
+ },
63
+ field: {
64
+ type: Object,
65
+ required: true
66
+ },
67
+ showName: Boolean,
68
+ disable: Boolean,
69
+ readonly: Boolean
70
70
  });
71
71
  const { onComplete, onDrop, onFileSelected, uploadedFile, clearUploadedFile } = useSingleFileUpload();
72
72
  onComplete(() => emit("update:model-value", uploadedFile.value));
73
73
 
74
74
  onMounted(() => {
75
- if (props.modelValue) {
76
- uploadedFile.value = props.modelValue;
77
- }
75
+ if (props.modelValue) {
76
+ uploadedFile.value = props.modelValue;
77
+ }
78
78
  });
79
79
  </script>
@@ -0,0 +1,45 @@
1
+ <template>
2
+ <div class="dx-slider-number-field">
3
+ <FieldLabel
4
+ :label="label"
5
+ :field="field"
6
+ />
7
+ <QSlider
8
+ v-bind="sliderProps"
9
+ :min="min"
10
+ :max="max"
11
+ label
12
+ label-always
13
+ switch-label-side
14
+ :price-label="priceLabel"
15
+ />
16
+ </div>
17
+ </template>
18
+
19
+ <script setup lang="ts">
20
+ import { QSliderProps } from "quasar";
21
+ import { computed } from "vue";
22
+ import { FormField } from "../../../../types";
23
+ import FieldLabel from "./FieldLabel";
24
+
25
+ export interface SliderFieldProps extends QSliderProps {
26
+ modelValue?: number | null;
27
+ field?: FormField;
28
+ label?: string;
29
+ currency?: boolean;
30
+ percent?: boolean;
31
+ }
32
+
33
+ defineEmits(["update:model-value"]);
34
+ const props = defineProps<SliderFieldProps>();
35
+ const sliderProps = computed(() => ({ ...props, field: undefined, label: !!props.label }));
36
+ const priceLabel = computed(() => {
37
+ if (props.currency) {
38
+ return "$" + props.modelValue;
39
+ } else if (props.percent) {
40
+ return props.modelValue + "%";
41
+ } else {
42
+ return props.modelValue;
43
+ }
44
+ });
45
+ </script>
@@ -1,82 +1,63 @@
1
1
  <template>
2
2
  <div>
3
- <QInput
4
- v-if="!readonly"
5
- :data-dusk="'text-field-' + field?.id"
6
- :data-testid="'text-field-' + field?.id"
7
- :placeholder="field?.placeholder"
8
- outlined
9
- dense
10
- :disable="disabled"
11
- :label-slot="!noLabel"
12
- :input-class="inputClass"
13
- :class="parentClass"
14
- stack-label
15
- :type="type"
16
- :model-value="modelValue"
17
- :debounce="debounce"
18
- @keydown.enter="$emit('submit')"
19
- @update:model-value="$emit('update:model-value', $event)"
20
- >
21
- <template #label>
22
- <FieldLabel
23
- :field="field"
24
- :label="label"
25
- :show-name="showName"
26
- :class="labelClass"
27
- />
28
- </template>
29
- </QInput>
30
3
  <div v-if="readonly">
31
4
  <LabelValueBlock
32
- :label="label || field.label"
5
+ :label="label || field?.label || 'Text'"
33
6
  :value="modelValue"
34
7
  />
35
8
  </div>
9
+ <template v-else>
10
+ <QInput
11
+ :placeholder="field?.placeholder"
12
+ outlined
13
+ dense
14
+ :readonly="readonly"
15
+ :autogrow="autogrow"
16
+ :disable="disabled"
17
+ :label-slot="!noLabel"
18
+ :input-class="inputClass"
19
+ :class="parentClass"
20
+ stack-label
21
+ :type="type"
22
+ :model-value="modelValue"
23
+ :maxlength="allowOverMax ? undefined : field?.maxLength"
24
+ :debounce="debounce"
25
+ @keydown.enter="$emit('submit')"
26
+ @update:model-value="$emit('update:model-value', $event)"
27
+ >
28
+ <template #label>
29
+ <FieldLabel
30
+ :field="field"
31
+ :label="label"
32
+ :show-name="showName"
33
+ :class="labelClass"
34
+ />
35
+ </template>
36
+ </QInput>
37
+ <MaxLengthCounter
38
+ :length="modelValue?.length || 0"
39
+ :max-length="field?.maxLength"
40
+ />
41
+ </template>
36
42
  </div>
37
43
  </template>
38
44
 
39
- <script setup>
45
+ <script setup lang="ts">
46
+ import { TextFieldProps } from "../../../../types";
47
+ import MaxLengthCounter from "../Utilities/MaxLengthCounter";
40
48
  import FieldLabel from "./FieldLabel";
41
49
  import LabelValueBlock from "./LabelValueBlock";
42
50
 
43
51
  defineEmits(["update:model-value", "submit"]);
44
- defineProps({
45
- modelValue: {
46
- type: [String, Number],
47
- default: ""
48
- },
49
- field: {
50
- type: Object,
51
- default: null
52
- },
53
- type: {
54
- type: String,
55
- default: "text"
56
- },
57
- label: {
58
- type: String,
59
- default: null
60
- },
61
- labelClass: {
62
- type: String,
63
- default: ""
64
- },
65
- parentClass: {
66
- type: String,
67
- default: ""
68
- },
69
- inputClass: {
70
- type: String,
71
- default: ""
72
- },
73
- noLabel: Boolean,
74
- showName: Boolean,
75
- disabled: Boolean,
76
- readonly: Boolean,
77
- debounce: {
78
- type: [String, Number],
79
- default: 0
80
- }
52
+ withDefaults(defineProps<TextFieldProps>(), {
53
+ modelValue: "",
54
+ field: null,
55
+ type: "text",
56
+ label: "",
57
+ labelClass: "",
58
+ parentClass: "",
59
+ inputClass: "",
60
+ maxLength: null,
61
+ debounce: 0
81
62
  });
82
63
  </script>
@@ -5,6 +5,7 @@ export { default as DateRangeField } from "./DateRangeField.vue";
5
5
  export { default as DateTimeField } from "./DateTimeField.vue";
6
6
  export { default as DateTimePicker } from "./DateTimePicker.vue";
7
7
  export { default as EditableDiv } from "./EditableDiv.vue";
8
+ export { default as EditOnClickTextField } from "./EditOnClickTextField.vue";
8
9
  export { default as FieldLabel } from "./FieldLabel.vue";
9
10
  export { default as FileUploadButton } from "./FileUploadButton.vue";
10
11
  export { default as InlineDateTimeField } from "./InlineDateTimeField.vue";
@@ -20,5 +21,6 @@ export { default as SelectDrawer } from "./SelectDrawer.vue";
20
21
  export { default as SelectField } from "./SelectField.vue";
21
22
  export { default as SelectWithChildrenField } from "./SelectWithChildrenField.vue";
22
23
  export { default as SingleFileField } from "./SingleFileField.vue";
24
+ export { default as SliderNumberField } from "./SliderNumberField.vue";
23
25
  export { default as TextField } from "./TextField.vue";
24
26
  export { default as WysiwygField } from "./WysiwygField.vue";
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="rendered-form">
2
+ <div class="dx-rendered-form">
3
3
  <div
4
4
  v-if="form.variations > 1"
5
5
  class="mb-4"
@@ -65,12 +65,13 @@
65
65
  <div
66
66
  v-for="(field, index) in mappedFields"
67
67
  :key="field.id"
68
- :class="{ 'mt-4': index > 0 }"
68
+ :class="{ 'mt-4': index > 0, [fieldClass]: true }"
69
69
  >
70
70
  <RenderVnode
71
71
  v-if="field.vnode"
72
72
  :vnode="field.vnode"
73
- :props="{field, modelValue: getFieldValue(field.name), readonly, disable, showName, noLabel}"
73
+ :field="field"
74
+ :props="getVnodeProps(field)"
74
75
  @update:model-value="onInput(field.name, $event)"
75
76
  />
76
77
  <Component
@@ -81,11 +82,31 @@
81
82
  :label="field.label || undefined"
82
83
  :no-label="noLabel"
83
84
  :show-name="showName"
85
+ :clearable="field.clearable || clearable"
84
86
  :disable="disable"
85
87
  :readonly="readonly"
86
88
  @update:model-value="onInput(field.name, $event)"
87
89
  />
88
90
  </div>
91
+ <div
92
+ v-if="savedAt"
93
+ :class="savingClass"
94
+ class="dx-saving-indicator flex items-center flex-nowrap"
95
+ >
96
+ <slot
97
+ v-if="saving"
98
+ name="saving"
99
+ >
100
+ Saving...
101
+ <QSpinnerPie class="ml-2" />
102
+ </slot>
103
+ <slot
104
+ v-else
105
+ name="saved"
106
+ >
107
+ Saved at {{ fDateTime(savedAt, { format: "M/d/yy h:mm:ssa" }) }}
108
+ </slot>
109
+ </div>
89
110
  <ConfirmDialog
90
111
  v-if="variationToEdit !== false"
91
112
  title="Change variation name"
@@ -113,8 +134,9 @@
113
134
  <script setup lang="ts">
114
135
  import { ExclamationCircleIcon as MissingIcon, PencilIcon as EditIcon } from "@heroicons/vue/solid";
115
136
  import { computed, ref } from "vue";
116
- import { FlashMessages, incrementName, replace } from "../../../helpers";
137
+ import { fDateTime, FlashMessages, incrementName, replace } from "../../../helpers";
117
138
  import { TrashIcon as RemoveIcon } from "../../../svg";
139
+ import { Form, FormFieldValue } from "../../../types";
118
140
  import { ConfirmDialog, RenderVnode } from "../../Utility";
119
141
  import {
120
142
  BooleanField,
@@ -127,9 +149,8 @@ import {
127
149
  TextField,
128
150
  WysiwygField
129
151
  } from "./Fields";
130
- import { Form, FormFieldValue } from "./form.d.ts";
131
152
 
132
- export interface Props {
153
+ export interface RenderedFormProps {
133
154
  values?: FormFieldValue[] | object;
134
155
  form: Form;
135
156
  noLabel?: boolean;
@@ -137,13 +158,20 @@ export interface Props {
137
158
  disable?: boolean;
138
159
  readonly?: boolean;
139
160
  saving?: boolean;
161
+ clearable?: boolean;
140
162
  emptyValue?: string | number | boolean;
141
163
  canModifyVariations?: boolean;
164
+ fieldClass?: string;
165
+ savingClass?: string;
166
+ savedAt?: string;
142
167
  }
143
168
 
144
- const props = withDefaults(defineProps<Props>(), {
169
+ const props = withDefaults(defineProps<RenderedFormProps>(), {
145
170
  values: null,
146
- emptyValue: undefined
171
+ emptyValue: undefined,
172
+ fieldClass: "",
173
+ savingClass: "text-sm text-slate-500 justify-end mt-4",
174
+ savedAt: null
147
175
  });
148
176
 
149
177
  const emit = defineEmits(["update:values"]);
@@ -172,6 +200,19 @@ const fieldResponses = computed(() => {
172
200
  if (Array.isArray(props.values)) return props.values;
173
201
  return Object.entries(props.values).map(([name, value]) => ({ name, value, variation: "" }));
174
202
  });
203
+
204
+ function getVnodeProps(field) {
205
+ return {
206
+ modelValue: getFieldValue(field.name),
207
+ label: field.label,
208
+ clearable: field.clearable || props.clearable,
209
+ readonly: props.readonly,
210
+ disable: props.disable,
211
+ showName: props.showName,
212
+ noLabel: props.noLabel
213
+ };
214
+ }
215
+
175
216
  const variationNames = computed(() => {
176
217
  const names = [...new Set(fieldResponses.value.map(v => v.variation))].sort();
177
218
  // Always guarantee that we show the default variation
@@ -183,7 +224,7 @@ const variationNames = computed(() => {
183
224
 
184
225
  const currentVariation = ref(variationNames.value[0] || "");
185
226
  const newVariationName = ref("");
186
- const variationToEdit = ref(false);
227
+ const variationToEdit = ref<boolean | string>(false);
187
228
  const variationToDelete = ref("");
188
229
  const canAddVariation = computed(() => props.canModifyVariations && !props.readonly && !props.disable && variationNames.value.length < props.form.variations);
189
230
 
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <div
3
+ v-if="maxLength"
4
+ class="danx-input-chars mt-1"
5
+ :class="{'danx-input-chars--error': length > maxLength}"
6
+ >
7
+ {{ fNumber(length) }} / {{ fNumber(maxLength) }} characters
8
+ </div>
9
+ </template>
10
+ <script setup lang="ts">
11
+ import { fNumber } from "../../../../helpers";
12
+
13
+ defineProps<{
14
+ length: number;
15
+ maxLength?: number;
16
+ }>();
17
+ </script>
@@ -0,0 +1 @@
1
+ export { default as MaxLengthCounter } from "./MaxLengthCounter.vue";
@@ -1,2 +1,3 @@
1
1
  export * from "./Fields";
2
+ export * from "./Utilities";
2
3
  export { default as RenderedForm } from "./RenderedForm.vue";
@@ -3,6 +3,7 @@
3
3
  <slot name="top" />
4
4
  <slot name="toolbar">
5
5
  <ActionToolbar
6
+ :title="title"
6
7
  :refresh-button="refreshButton"
7
8
  :actions="actions?.filter(a => a.batch)"
8
9
  :action-target="controller.selectedRows.value"
@@ -15,7 +16,7 @@
15
16
  </ActionToolbar>
16
17
  </slot>
17
18
  <div class="flex flex-nowrap flex-grow overflow-hidden w-full">
18
- <slot name="filter-fields">
19
+ <slot name="filters">
19
20
  <CollapsableFiltersSidebar
20
21
  v-if="activeFilter"
21
22
  :name="controller.name"
@@ -48,6 +49,7 @@
48
49
  v-if="activeItem && panels"
49
50
  :title="panelTitle"
50
51
  :model-value="activePanel"
52
+ :active-item="activeItem"
51
53
  :panels="panels"
52
54
  @update:model-value="panel => controller.activatePanel(activeItem, panel)"
53
55
  @close="controller.setActiveItem(null)"
@@ -65,26 +67,25 @@
65
67
  </template>
66
68
  <script setup lang="ts">
67
69
  import { computed } from "vue";
68
- import { ActionOptions } from "../../../helpers";
70
+ import { ActionController, ActionOptions, ActionPanel, FilterGroup, TableColumn } from "../../../types";
69
71
  import { PanelsDrawer } from "../../PanelsDrawer";
70
72
  import { PreviousNextControls } from "../../Utility";
71
73
  import ActionTable from "../ActionTable";
72
74
  import { CollapsableFiltersSidebar } from "../Filters";
73
- import { ActionController, ActionPanel, FilterGroup } from "../listControls";
74
- import { TableColumn } from "../tableColumns";
75
75
  import { ActionToolbar } from "../Toolbars";
76
76
 
77
77
  const props = defineProps<{
78
- refreshButton: boolean,
79
- showFilters: boolean,
80
- controller: ActionController,
81
- columns: TableColumn[],
82
- filters?: FilterGroup[],
83
- panels?: ActionPanel[],
84
- actions?: ActionOptions[],
85
- exporter?: () => Promise<void>,
86
- titleField?: string,
87
- tableClass?: string
78
+ title?: string;
79
+ refreshButton: boolean;
80
+ showFilters: boolean;
81
+ controller: ActionController;
82
+ columns: TableColumn[];
83
+ filters?: FilterGroup[];
84
+ panels?: ActionPanel[];
85
+ actions?: ActionOptions[];
86
+ exporter?: () => Promise<void>;
87
+ panelTitleField?: string;
88
+ tableClass?: string;
88
89
  }>();
89
90
 
90
91
  const activeFilter = computed(() => props.controller.activeFilter.value);
@@ -92,7 +93,7 @@ const activeItem = computed(() => props.controller.activeItem.value);
92
93
  const activePanel = computed(() => props.controller.activePanel.value || "");
93
94
  const panelTitle = computed(() => {
94
95
  if (activeItem.value) {
95
- return activeItem.value[props.titleField || "title"] || activeItem.value.label || activeItem.value.name;
96
+ return activeItem.value[props.panelTitleField || "title"] || activeItem.value.label || activeItem.value.name || (props.title + " " + activeItem.value.id);
96
97
  }
97
98
  return null;
98
99
  });
@@ -2,9 +2,9 @@
2
2
  <div class="dx-action-toolbar flex items-center">
3
3
  <div class="flex-grow px-6">
4
4
  <slot name="title">
5
- <h2 v-if="title">
5
+ <h4 v-if="title">
6
6
  {{ title }}
7
- </h2>
7
+ </h4>
8
8
  </slot>
9
9
  </div>
10
10
  <div class="py-3 px-6 flex items-center flex-nowrap">
@@ -20,7 +20,7 @@
20
20
  class="ml-4"
21
21
  />
22
22
  <ActionMenu
23
- v-if="actions.length > 0"
23
+ v-if="actions && actions.length > 0"
24
24
  class="ml-4 dx-batch-actions"
25
25
  :target="actionTarget"
26
26
  :actions="actions"
@@ -30,17 +30,17 @@
30
30
  </div>
31
31
  </template>
32
32
  <script setup lang="ts">
33
- import { ActionOptions, ActionTargetItem } from "../../../helpers";
33
+ import { ActionOptions, ActionTargetItem, AnyObject } from "../../../types";
34
34
  import { ExportButton, RefreshButton } from "../../Utility";
35
35
  import ActionMenu from "../ActionMenu";
36
36
 
37
37
  defineEmits(["refresh"]);
38
38
  defineProps<{
39
39
  title?: string,
40
- actions: ActionOptions[],
40
+ actions?: ActionOptions[],
41
41
  actionTarget?: ActionTargetItem[],
42
42
  refreshButton?: boolean,
43
43
  loading?: boolean,
44
- exporter?: () => void
44
+ exporter?: (filter?: AnyObject) => void | Promise<void>
45
45
  }>();
46
46
  </script>