quasar-ui-danx 0.4.10 → 0.4.13

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 (55) hide show
  1. package/dist/danx.es.js +12389 -7677
  2. package/dist/danx.es.js.map +1 -1
  3. package/dist/danx.umd.js +137 -7
  4. package/dist/danx.umd.js.map +1 -1
  5. package/dist/style.css +1 -1
  6. package/index.d.ts +7 -0
  7. package/index.ts +1 -0
  8. package/package.json +10 -4
  9. package/src/components/ActionTable/ActionMenu.vue +26 -31
  10. package/src/components/ActionTable/ActionTable.vue +4 -1
  11. package/src/components/ActionTable/Columns/ActionTableColumn.vue +14 -6
  12. package/src/components/ActionTable/Columns/ActionTableHeaderColumn.vue +63 -42
  13. package/src/components/ActionTable/Form/ActionForm.vue +55 -0
  14. package/src/components/ActionTable/Form/Fields/EditOnClickTextField.vue +11 -5
  15. package/src/components/ActionTable/Form/Fields/FileUploadButton.vue +1 -0
  16. package/src/components/ActionTable/Form/Fields/MultiFileField.vue +1 -1
  17. package/src/components/ActionTable/Form/Fields/NumberField.vue +0 -1
  18. package/src/components/ActionTable/Form/RenderedForm.vue +57 -50
  19. package/src/components/ActionTable/Form/index.ts +1 -0
  20. package/src/components/ActionTable/Layouts/ActionTableLayout.vue +3 -3
  21. package/src/components/ActionTable/TableSummaryRow.vue +48 -37
  22. package/src/components/ActionTable/Toolbars/ActionToolbar.vue +2 -2
  23. package/src/components/ActionTable/listControls.ts +3 -2
  24. package/src/components/PanelsDrawer/PanelsDrawer.vue +15 -5
  25. package/src/components/PanelsDrawer/PanelsDrawerPanels.vue +3 -1
  26. package/src/components/PanelsDrawer/PanelsDrawerTabs.vue +17 -4
  27. package/src/components/Utility/Dialogs/FullscreenCarouselDialog.vue +30 -5
  28. package/src/components/Utility/Files/FilePreview.vue +72 -12
  29. package/src/components/Utility/Popovers/PopoverMenu.vue +34 -29
  30. package/src/components/Utility/Tools/RenderVnode.vue +5 -1
  31. package/src/config/index.ts +2 -1
  32. package/src/helpers/FileUpload.ts +59 -8
  33. package/src/helpers/actions.ts +27 -27
  34. package/src/helpers/date.ts +2 -2
  35. package/src/helpers/download.ts +8 -2
  36. package/src/helpers/formats.ts +52 -5
  37. package/src/helpers/multiFileUpload.ts +6 -4
  38. package/src/helpers/objectStore.ts +14 -17
  39. package/src/helpers/request.ts +12 -0
  40. package/src/helpers/singleFileUpload.ts +63 -55
  41. package/src/helpers/utils.ts +12 -3
  42. package/src/index.ts +1 -0
  43. package/src/styles/danx.scss +5 -0
  44. package/src/styles/index.scss +1 -0
  45. package/src/styles/themes/danx/action-table.scss +24 -13
  46. package/src/types/actions.d.ts +16 -7
  47. package/src/types/controls.d.ts +4 -4
  48. package/src/types/files.d.ts +10 -5
  49. package/src/types/forms.d.ts +19 -1
  50. package/src/types/index.d.ts +0 -1
  51. package/src/types/requests.d.ts +2 -0
  52. package/src/types/tables.d.ts +28 -22
  53. package/src/{vue-plugin.js → vue-plugin.ts} +5 -4
  54. package/tsconfig.json +1 -0
  55. package/types/index.d.ts +2 -0
package/index.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ declare module "quasar-ui-danx";
2
+
3
+ export * from "./src/components";
4
+ export * from "./src/config";
5
+ export * from "./src/helpers";
6
+ export * from "./src/svg";
7
+ export * from "./src/types";
package/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./src";
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "quasar-ui-danx",
3
- "version": "0.4.10",
3
+ "version": "0.4.13",
4
4
  "author": "Dan <dan@flytedesk.com>",
5
5
  "description": "DanX Vue / Quasar component library",
6
6
  "license": "MIT",
7
7
  "type": "module",
8
- "main": "dist/danx.es.js",
9
- "module": "dist/danx.es.js",
8
+ "main": "./dist/danx.umd.js",
9
+ "module": "./dist/danx.es.js",
10
+ "types": "types/index.d.ts",
10
11
  "scripts": {
11
12
  "dev": "cd dev && quasar dev && cd ..",
12
13
  "build": "vite build",
@@ -17,6 +18,10 @@
17
18
  "type": "git",
18
19
  "url": "https://github.com/flytedan/quasar-ui-danx"
19
20
  },
21
+ "peerDependencies": {
22
+ "quasar": "^2.0.0",
23
+ "vue": "^3.4.21"
24
+ },
20
25
  "devDependencies": {
21
26
  "@quasar/extras": "^1.16.4",
22
27
  "@types/luxon": "^3.4.2",
@@ -52,7 +57,8 @@
52
57
  "danx-icon": "^1.0.2",
53
58
  "exifreader": "^4.21.1",
54
59
  "gsap": "^3.12.5",
55
- "luxon": "^3.4.4"
60
+ "luxon": "^3.4.4",
61
+ "yaml": "^2.4.5"
56
62
  },
57
63
  "browserslist": [
58
64
  "last 4 Chrome versions",
@@ -3,53 +3,48 @@
3
3
  class="px-2 flex dx-action-button"
4
4
  :items="activeActions"
5
5
  :disabled="!hasTarget"
6
- :tooltip="!hasTarget ? tooltip : null"
7
- :loading="isSaving || loading"
6
+ :tooltip="!hasTarget ? tooltip : ''"
7
+ :loading="isSaving || !!loading"
8
8
  :loading-component="loadingComponent"
9
9
  @action-item="onAction"
10
10
  />
11
11
  </template>
12
- <script setup>
12
+ <script setup lang="ts">
13
13
  import { computed, ref } from "vue";
14
+ import { ActionTarget, ResourceAction } from "../../types";
14
15
  import { PopoverMenu } from "../Utility";
15
16
 
16
- const props = defineProps({
17
- actions: {
18
- type: Array,
19
- required: true
20
- },
21
- target: {
22
- type: [Array, Object],
23
- default: () => []
24
- },
25
- tooltip: {
26
- type: String,
27
- default: "First select records to perform a batch action"
28
- },
29
- loading: Boolean,
30
- loadingComponent: {
31
- type: [Function, Object],
32
- default: undefined
33
- }
17
+ const emit = defineEmits(["success"]);
18
+ const props = withDefaults(defineProps<{
19
+ actions: ResourceAction[],
20
+ target?: ActionTarget,
21
+ tooltip?: string,
22
+ loading?: boolean,
23
+ loadingComponent?: any
24
+ }>(), {
25
+ target: () => [],
26
+ tooltip: "First select records to perform a batch action",
27
+ loadingComponent: undefined
34
28
  });
35
29
 
36
30
  const hasTarget = computed(() => Array.isArray(props.target) ? props.target.length > 0 : !!props.target);
37
31
 
38
32
  const activeActions = computed(() => props.actions.filter(action => {
39
- if (Array.isArray(props.target)) {
40
- return action.batchEnabled ? action.batchEnabled(props.target) : true;
41
- }
33
+ if (Array.isArray(props.target)) {
34
+ return action.batchEnabled ? action.batchEnabled(props.target) : true;
35
+ }
42
36
 
43
- return action.enabled ? action.enabled(props.target) : true;
37
+ return action.enabled ? action.enabled(props.target) : true;
44
38
  }));
45
39
 
46
40
  const isSaving = ref(false);
47
41
  async function onAction(action) {
48
- if (!action.trigger) {
49
- throw new Error("Action must have a trigger function! Make sure you are using useActions() or implement your own trigger function.");
50
- }
51
- isSaving.value = true;
52
- await action.trigger(props.target);
53
- isSaving.value = false;
42
+ if (!action.trigger) {
43
+ throw new Error("Action must have a trigger function! Make sure you are using useActions() or implement your own trigger function.");
44
+ }
45
+ isSaving.value = true;
46
+ await action.trigger(props.target);
47
+ isSaving.value = false;
48
+ emit("success", action);
54
49
  }
55
50
  </script>
@@ -31,6 +31,7 @@
31
31
  :label="label"
32
32
  :item-count="summary?.count || 0"
33
33
  :selected-count="selectedRows.length"
34
+ :sticky-colspan="summaryColSpan"
34
35
  :loading="loadingSummary"
35
36
  :summary="summary"
36
37
  :columns="tableColumns"
@@ -87,6 +88,7 @@ export interface Props {
87
88
  summary: any;
88
89
  columns: TableColumn[];
89
90
  rowsPerPageOptions?: number[];
91
+ summaryColSpan?: number;
90
92
  }
91
93
 
92
94
  const props = withDefaults(defineProps<Props>(), {
@@ -94,7 +96,8 @@ const props = withDefaults(defineProps<Props>(), {
94
96
  pagedItems: null,
95
97
  summary: null,
96
98
  loadingSummary: false,
97
- rowsPerPageOptions: () => [10, 25, 50, 100]
99
+ rowsPerPageOptions: () => [10, 25, 50, 100],
100
+ summaryColSpan: null
98
101
  });
99
102
 
100
103
  const actionTable = ref(null);
@@ -3,13 +3,18 @@
3
3
  :key="rowProps.key"
4
4
  :props="rowProps"
5
5
  :style="columnStyle"
6
+ class="dx-column"
7
+ :class="column.columnClass"
6
8
  >
7
9
  <div :style="columnStyle">
8
10
  <div
9
11
  class="flex items-center flex-nowrap"
10
- :class="columnClass"
12
+ :class="wrapClass"
11
13
  >
12
- <div class="flex-grow overflow-hidden">
14
+ <div
15
+ v-if="!column.hideContent"
16
+ class="flex-grow overflow-hidden"
17
+ >
13
18
  <a
14
19
  v-if="column.onClick"
15
20
  :class="column.innerClass"
@@ -25,6 +30,7 @@
25
30
  <div
26
31
  v-else
27
32
  :class="column.innerClass"
33
+ class="dx-column-text"
28
34
  >
29
35
  <RenderVnode
30
36
  v-if="column.vnode"
@@ -42,7 +48,8 @@
42
48
  </div>
43
49
  <div
44
50
  v-if="column.actionMenu"
45
- class="flex flex-shrink-0 pl-2"
51
+ class="flex flex-shrink-0"
52
+ :class="{'ml-2': !column.hideContent}"
46
53
  >
47
54
  <ActionMenu
48
55
  class="dx-column-action-menu"
@@ -55,12 +62,13 @@
55
62
  </div>
56
63
  </QTd>
57
64
  </template>
58
- <script setup>
65
+ <script setup lang="ts">
59
66
  import { QTd } from "quasar";
60
67
  import { computed } from "vue";
61
68
  import { RenderVnode } from "../../Utility";
62
69
  import ActionMenu from "../ActionMenu";
63
70
  import { TitleColumnFormat } from "./";
71
+ import { TableColumn } from "./../../../types";
64
72
 
65
73
  const props = defineProps({
66
74
  rowProps: {
@@ -74,7 +82,7 @@ const props = defineProps({
74
82
  });
75
83
 
76
84
  const row = computed(() => props.rowProps.row);
77
- const column = computed(() => props.rowProps.col);
85
+ const column = computed<TableColumn>(() => props.rowProps.col);
78
86
  const value = computed(() => props.rowProps.value);
79
87
  const isSaving = computed(() => row.value.isSaving?.value);
80
88
 
@@ -86,7 +94,7 @@ const columnStyle = computed(() => {
86
94
  };
87
95
  });
88
96
 
89
- const columnClass = computed(() => ({
97
+ const wrapClass = computed(() => ({
90
98
  [column.value.class || ""]: true,
91
99
  "is-saving": isSaving.value,
92
100
  "justify-end": column.value.align === "right",
@@ -3,7 +3,7 @@
3
3
  :key="rowProps.key"
4
4
  :props="rowProps"
5
5
  :data-drop-zone="isResizeable && `resize-column-` + column.name"
6
- :class="isResizeable && cls['handle-drop-zone']"
6
+ :class="columnClass"
7
7
  :style="columnStyle"
8
8
  >
9
9
  {{ column.label }}
@@ -17,67 +17,88 @@
17
17
  </HandleDraggable>
18
18
  </QTh>
19
19
  </template>
20
- <script setup>
20
+ <script setup lang="ts">
21
21
  import { QTh } from "quasar";
22
- import { computed } from "vue";
22
+ import { computed, useCssModule } from "vue";
23
23
  import { DragHandleIcon as RowResizeIcon } from "../../../svg";
24
+ import { TableColumn } from "../../../types";
24
25
  import { HandleDraggable } from "../../DragAndDrop";
25
26
 
26
27
  const emit = defineEmits(["update:model-value"]);
27
28
  const props = defineProps({
28
- modelValue: {
29
- type: Object,
30
- required: true
31
- },
32
- name: {
33
- type: String,
34
- required: true
35
- },
36
- rowProps: {
37
- type: Object,
38
- required: true
39
- }
29
+ modelValue: {
30
+ type: Object,
31
+ required: true
32
+ },
33
+ name: {
34
+ type: String,
35
+ required: true
36
+ },
37
+ rowProps: {
38
+ type: Object,
39
+ required: true
40
+ }
40
41
  });
41
42
 
42
- const column = computed(() => props.rowProps.col);
43
+ const column = computed<TableColumn>(() => props.rowProps.col);
43
44
  const isResizeable = computed(() => column.value.resizeable);
44
45
 
45
46
  const columnStyle = computed(() => {
46
- const width = props.settings?.width || column.value.width;
47
- return {
48
- width: width ? `${width}px` : undefined,
49
- minWidth: column.value.minWidth ? `${column.value.minWidth}px` : undefined,
50
- ...(column.value.headerStyle || {})
51
- };
47
+ const width = props.settings?.width || column.value.width;
48
+ return {
49
+ width: width ? `${width}px` : undefined,
50
+ minWidth: column.value.minWidth ? `${column.value.minWidth}px` : undefined,
51
+ ...(column.value.headerStyle || {})
52
+ };
52
53
  });
53
54
 
55
+ const clsModule = useCssModule("cls");
56
+ const columnClass = computed(() => {
57
+ const colCls = {
58
+ [clsModule["handle-drop-zone"]]: isResizeable.value,
59
+ "dx-column-shrink": column.value.shrink
60
+ };
61
+
62
+ const headerClass = column.value.headerClass;
63
+ if (headerClass) {
64
+ if (typeof headerClass === "string") {
65
+ colCls[headerClass] = true;
66
+ } else {
67
+ Object.keys(headerClass).forEach((key) => {
68
+ colCls[key] = headerClass[key];
69
+ });
70
+ }
71
+ }
72
+
73
+ return colCls;
74
+ });
54
75
 
55
76
  function onResizeColumn(val) {
56
- const settings = {
57
- ...props.modelValue,
58
- [column.value.name]: {
59
- width: Math.max(Math.min(val.distance + val.startDropZoneSize, column.value.maxWidth || 500), column.value.minWidth || 80)
60
- }
61
- };
62
- emit("update:model-value", settings);
77
+ const settings = {
78
+ ...props.modelValue,
79
+ [column.value.name]: {
80
+ width: Math.max(Math.min(val.distance + val.startDropZoneSize, column.value.maxWidth || 500), column.value.minWidth || 80)
81
+ }
82
+ };
83
+ emit("update:model-value", settings);
63
84
  }
64
85
  </script>
65
86
 
66
87
  <style lang="scss" module="cls">
67
88
  .handle-drop-zone {
68
- .resize-handle {
69
- position: absolute;
70
- top: 0;
71
- right: -.45em;
72
- width: .9em;
73
- opacity: 0;
74
- transition: all .3s;
75
- }
89
+ .resize-handle {
90
+ position: absolute;
91
+ top: 0;
92
+ right: -.45em;
93
+ width: .9em;
94
+ opacity: 0;
95
+ transition: all .3s;
96
+ }
76
97
 
77
- &:hover {
78
- .resize-handle {
79
- opacity: 1;
80
- }
81
- }
98
+ &:hover {
99
+ .resize-handle {
100
+ opacity: 1;
101
+ }
102
+ }
82
103
  }
83
104
  </style>
@@ -0,0 +1,55 @@
1
+ <template>
2
+ <div>
3
+ <RenderedForm
4
+ v-bind="renderedFormProps"
5
+ v-model:values="input"
6
+ empty-value=""
7
+ :saving="action.isApplying"
8
+ @update:values="action.trigger(target, input)"
9
+ />
10
+ </div>
11
+ </template>
12
+ <script setup lang="ts">
13
+ import { ref, watch } from "vue";
14
+ import { ActionTargetItem, AnyObject, Form, ResourceAction } from "../../../types";
15
+ import RenderedForm from "./RenderedForm.vue";
16
+
17
+ interface ActionFormProps {
18
+ action: ResourceAction;
19
+ target: ActionTargetItem;
20
+ form: Form;
21
+ noLabel?: boolean;
22
+ showName?: boolean;
23
+ disable?: boolean;
24
+ readonly?: boolean;
25
+ clearable?: boolean;
26
+ fieldClass?: string;
27
+ savingClass?: string;
28
+ }
29
+
30
+ const props = defineProps<ActionFormProps>();
31
+ const renderedFormProps = {
32
+ form: props.form,
33
+ noLabel: props.noLabel,
34
+ showName: props.showName,
35
+ disable: props.disable,
36
+ readonly: props.readonly,
37
+ clearable: props.clearable,
38
+ fieldClass: props.fieldClass,
39
+ savingClass: props.savingClass
40
+ };
41
+
42
+ const input: AnyObject = ref({ ...props.target });
43
+ const fieldStatus: AnyObject = {};
44
+
45
+ // Only update field values from target changes when the field is not already being saved
46
+ watch(() => props.target, (target: ActionTargetItem) => {
47
+ if (!target) return;
48
+
49
+ for (let field of props.form.fields) {
50
+ if (!fieldStatus[field.name]?.isSaving) {
51
+ input.value[field.name] = target[field.name];
52
+ }
53
+ }
54
+ });
55
+ </script>
@@ -3,12 +3,13 @@
3
3
  class="danx-edit-on-click-text-field flex flex-nowrap items-center rounded overflow-ellipsis"
4
4
  :class="{[props.class]: true, 'is-readonly': readonly, 'cursor-pointer': !isEditing && !readonly}"
5
5
  @click="onEdit"
6
+ @focusout="isEditing = false"
6
7
  >
7
8
  <div
8
9
  ref="editableBox"
9
10
  :contenteditable="!readonly && isEditing"
10
11
  class="flex-grow p-2 rounded outline-none border-none"
11
- :class="{[editingClass]: isEditing}"
12
+ :class="{[editingClass]: isEditing, [inputClass]: true}"
12
13
  @input="text = $event.target.innerText"
13
14
  >
14
15
  {{ text }}
@@ -33,15 +34,20 @@
33
34
  import { FaSolidCheck as DoneIcon, FaSolidPencil as EditIcon } from "danx-icon";
34
35
  import { nextTick, ref } from "vue";
35
36
 
36
- export interface Props {
37
- class?: "hover:bg-slate-300",
38
- editingClass?: "bg-slate-500";
37
+ export interface EditOnClickTextFieldProps {
38
+ class?: string;
39
+ editingClass?: string;
40
+ inputClass?: string;
39
41
  readonly?: boolean;
40
42
  }
41
43
 
42
44
  const editableBox = ref<HTMLElement | null>(null);
43
45
  const text = defineModel({ type: String });
44
- const props = defineProps<Props>();
46
+ const props = withDefaults(defineProps<EditOnClickTextFieldProps>(), {
47
+ class: "hover:bg-slate-300",
48
+ editingClass: "bg-slate-500",
49
+ inputClass: "whitespace-normal"
50
+ });
45
51
  const isEditing = ref(false);
46
52
  function onEdit() {
47
53
  if (props.readonly) return;
@@ -62,6 +62,7 @@ function upload() {
62
62
  async function onAttachFiles({ target: { files } }) {
63
63
  emit("uploading", files);
64
64
  let fileUpload = new FileUpload(files)
65
+ .prepare()
65
66
  .onProgress(({ file, progress }) => {
66
67
  file.progress = progress;
67
68
  emit("file-progress", file);
@@ -20,7 +20,7 @@
20
20
  @change="onFilesSelected"
21
21
  >
22
22
 
23
- <div class="max-w-[50em] flex items-stretch justify-start">
23
+ <div class="flex items-stretch justify-start">
24
24
  <FilePreview
25
25
  v-for="file in uploadedFiles"
26
26
  :key="'file-upload-' + file.id"
@@ -82,7 +82,6 @@ function onInput(value) {
82
82
  number = Math.min(number, props.max);
83
83
  }
84
84
 
85
- console.log("formattinged", number, value);
86
85
  numberVal.value = format(number);
87
86
  }
88
87
 
@@ -62,32 +62,36 @@
62
62
  </QTab>
63
63
  </QTabs>
64
64
  </div>
65
- <div
65
+ <template
66
66
  v-for="(field, index) in mappedFields"
67
67
  :key="field.id"
68
- :class="{ 'mt-4': index > 0, [fieldClass]: true }"
69
68
  >
70
- <RenderVnode
71
- v-if="field.vnode"
72
- :vnode="field.vnode"
73
- :field="field"
74
- :props="getVnodeProps(field)"
75
- @update:model-value="onInput(field.name, $event)"
76
- />
77
- <Component
78
- :is="field.component"
79
- :key="field.name + '-' + currentVariation"
80
- :model-value="getFieldValue(field.name)"
81
- :field="field"
82
- :label="field.label || undefined"
83
- :no-label="noLabel"
84
- :show-name="showName"
85
- :clearable="field.clearable || clearable"
86
- :disable="disable"
87
- :readonly="readonly"
88
- @update:model-value="onInput(field.name, $event)"
89
- />
90
- </div>
69
+ <div
70
+ v-show="isFieldEnabled(field)"
71
+ :class="{ 'mt-4': index > 0, [fieldClass]: true }"
72
+ >
73
+ <RenderVnode
74
+ v-if="field.vnode"
75
+ :vnode="field.vnode"
76
+ :props="getVnodeProps(field)"
77
+ :params="fieldInputs"
78
+ @update:model-value="onInput(field.name, $event)"
79
+ />
80
+ <Component
81
+ :is="field.component"
82
+ :key="field.name + '-' + currentVariation"
83
+ :model-value="getFieldValue(field.name)"
84
+ :field="field"
85
+ :label="field.label || undefined"
86
+ :no-label="noLabel"
87
+ :show-name="showName"
88
+ :clearable="field.clearable || clearable"
89
+ :disable="disable"
90
+ :readonly="readonly"
91
+ @update:model-value="onInput(field.name, $event)"
92
+ />
93
+ </div>
94
+ </template>
91
95
  <div
92
96
  v-if="savedAt"
93
97
  :class="savingClass"
@@ -136,7 +140,7 @@ import { ExclamationCircleIcon as MissingIcon, PencilIcon as EditIcon } from "@h
136
140
  import { computed, ref } from "vue";
137
141
  import { fDateTime, FlashMessages, incrementName, replace } from "../../../helpers";
138
142
  import { TrashIcon as RemoveIcon } from "../../../svg";
139
- import { Form, FormFieldValue } from "../../../types";
143
+ import { AnyObject, FormFieldValue, RenderedFormProps } from "../../../types";
140
144
  import { ConfirmDialog, RenderVnode } from "../../Utility";
141
145
  import {
142
146
  BooleanField,
@@ -150,28 +154,12 @@ import {
150
154
  WysiwygField
151
155
  } from "./Fields";
152
156
 
153
- export interface RenderedFormProps {
154
- values?: FormFieldValue[] | object;
155
- form: Form;
156
- noLabel?: boolean;
157
- showName?: boolean;
158
- disable?: boolean;
159
- readonly?: boolean;
160
- saving?: boolean;
161
- clearable?: boolean;
162
- emptyValue?: string | number | boolean;
163
- canModifyVariations?: boolean;
164
- fieldClass?: string;
165
- savingClass?: string;
166
- savedAt?: string;
167
- }
168
-
169
157
  const props = withDefaults(defineProps<RenderedFormProps>(), {
170
158
  values: null,
171
159
  emptyValue: undefined,
172
160
  fieldClass: "",
173
161
  savingClass: "text-sm text-slate-500 justify-end mt-4",
174
- savedAt: null
162
+ savedAt: undefined
175
163
  });
176
164
 
177
165
  const emit = defineEmits(["update:values"]);
@@ -190,9 +178,9 @@ const FORM_FIELD_MAP = {
190
178
 
191
179
  const mappedFields = props.form.fields.map((field) => ({
192
180
  placeholder: `Enter ${field.label}`,
181
+ default: field.type === "BOOLEAN" ? false : "",
193
182
  ...field,
194
- component: field.component || FORM_FIELD_MAP[field.type],
195
- default: field.type === "BOOLEAN" ? false : ""
183
+ component: field.component || FORM_FIELD_MAP[field.type]
196
184
  }));
197
185
 
198
186
  const fieldResponses = computed(() => {
@@ -201,6 +189,24 @@ const fieldResponses = computed(() => {
201
189
  return Object.entries(props.values).map(([name, value]) => ({ name, value, variation: "" }));
202
190
  });
203
191
 
192
+ const fieldInputs = computed(() => {
193
+ const inputs: AnyObject = {};
194
+ for (const field of mappedFields) {
195
+ inputs[field.name] = getFieldValue(field.name);
196
+ }
197
+ return inputs;
198
+ });
199
+
200
+ function isFieldEnabled(field) {
201
+ if (field.enabled === undefined) return true;
202
+
203
+ if (typeof field.enabled === "function") {
204
+ return field.enabled(fieldInputs.value);
205
+ }
206
+
207
+ return field.enabled;
208
+ }
209
+
204
210
  function getVnodeProps(field) {
205
211
  return {
206
212
  modelValue: getFieldValue(field.name),
@@ -226,16 +232,16 @@ const currentVariation = ref(variationNames.value[0] || "");
226
232
  const newVariationName = ref("");
227
233
  const variationToEdit = ref<boolean | string>(false);
228
234
  const variationToDelete = ref("");
229
- const canAddVariation = computed(() => props.canModifyVariations && !props.readonly && !props.disable && variationNames.value.length < props.form.variations);
235
+ const canAddVariation = computed(() => props.canModifyVariations && !props.readonly && !props.disable && variationNames.value.length < (props.form.variations || 0));
230
236
 
231
- function getFieldResponse(name, variation: string = undefined) {
237
+ function getFieldResponse(name: string, variation?: string) {
232
238
  if (!fieldResponses.value) return undefined;
233
239
  return fieldResponses.value.find((fr: FormFieldValue) => fr.variation === (variation !== undefined ? variation : currentVariation.value) && fr.name === name);
234
240
  }
235
- function getFieldValue(name) {
241
+ function getFieldValue(name: string) {
236
242
  return getFieldResponse(name)?.value;
237
243
  }
238
- function onInput(name, value) {
244
+ function onInput(name: string, value: any) {
239
245
  const fieldResponse = getFieldResponse(name);
240
246
  const newFieldResponse = {
241
247
  name,
@@ -291,11 +297,12 @@ function updateValues(values: FormFieldValue[]) {
291
297
  let updatedValues: FormFieldValue[] | object = values;
292
298
 
293
299
  if (!Array.isArray(props.values)) {
294
- updatedValues = values.reduce((acc, v) => {
300
+ updatedValues = values.reduce((acc: AnyObject, v) => {
295
301
  acc[v.name] = v.value;
296
302
  return acc;
297
303
  }, {});
298
304
  }
305
+
299
306
  emit("update:values", updatedValues);
300
307
  }
301
308
 
@@ -311,8 +318,8 @@ function onRemoveVariation(name: string) {
311
318
  variationToDelete.value = "";
312
319
  }
313
320
 
314
- function isVariationFormComplete(variation) {
315
- const requiredGroups = {};
321
+ function isVariationFormComplete(variation: string) {
322
+ const requiredGroups: AnyObject = {};
316
323
  return props.form.fields.filter(r => r.required || r.required_group).every((field) => {
317
324
  const fieldResponse = getFieldResponse(field.name, variation);
318
325
  const hasValue = !!fieldResponse && fieldResponse.value !== null;
@@ -1,3 +1,4 @@
1
1
  export * from "./Fields";
2
2
  export * from "./Utilities";
3
+ export { default as ActionForm } from "./ActionForm.vue";
3
4
  export { default as RenderedForm } from "./RenderedForm.vue";