quasar-ui-danx 0.3.22 → 0.4.2

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 (53) hide show
  1. package/.eslintrc.cjs +32 -30
  2. package/danx-local.sh +1 -1
  3. package/dist/danx.es.js +7413 -7461
  4. package/dist/danx.es.js.map +1 -1
  5. package/dist/danx.umd.js +5 -5
  6. package/dist/danx.umd.js.map +1 -1
  7. package/dist/style.css +1 -1
  8. package/package.json +1 -1
  9. package/src/components/ActionTable/ActionMenu.vue +1 -1
  10. package/src/components/ActionTable/ActionTable.vue +67 -47
  11. package/src/components/ActionTable/{ActionTableColumn.vue → Columns/ActionTableColumn.vue} +4 -3
  12. package/src/components/ActionTable/{ActionTableHeaderColumn.vue → Columns/ActionTableHeaderColumn.vue} +2 -2
  13. package/src/components/ActionTable/Columns/index.ts +2 -0
  14. package/src/components/ActionTable/Filters/CollapsableFiltersSidebar.vue +23 -21
  15. package/src/components/ActionTable/Form/Fields/DateRangeField.vue +3 -5
  16. package/src/components/ActionTable/Form/Fields/NumberField.vue +60 -59
  17. package/src/components/ActionTable/Form/Fields/SelectField.vue +135 -135
  18. package/src/components/ActionTable/Form/Fields/TextField.vue +36 -36
  19. package/src/components/ActionTable/Form/RenderedForm.vue +133 -112
  20. package/src/components/ActionTable/Form/form.d.ts +31 -0
  21. package/src/components/ActionTable/Layouts/ActionTableLayout.vue +93 -4
  22. package/src/components/ActionTable/TableSummaryRow.vue +4 -4
  23. package/src/components/ActionTable/Toolbars/ActionToolbar.vue +46 -0
  24. package/src/components/ActionTable/Toolbars/index.ts +1 -0
  25. package/src/components/ActionTable/index.ts +1 -2
  26. package/src/components/ActionTable/listControls.ts +512 -385
  27. package/src/components/ActionTable/listHelpers.ts +46 -44
  28. package/src/components/ActionTable/tableColumns.ts +66 -66
  29. package/src/components/PanelsDrawer/PanelsDrawer.vue +37 -26
  30. package/src/components/PanelsDrawer/PanelsDrawerPanels.vue +1 -1
  31. package/src/components/PanelsDrawer/PanelsDrawerTabs.vue +1 -6
  32. package/src/components/Utility/Buttons/ExportButton.vue +1 -1
  33. package/src/components/Utility/Buttons/RefreshButton.vue +5 -5
  34. package/src/components/Utility/Controls/PreviousNextControls.vue +4 -4
  35. package/src/components/Utility/Dialogs/ConfirmDialog.vue +69 -115
  36. package/src/components/Utility/Dialogs/DialogLayout.vue +95 -0
  37. package/src/components/Utility/Dialogs/InfoDialog.vue +40 -80
  38. package/src/components/Utility/Layouts/CollapsableSidebar.vue +2 -8
  39. package/src/components/Utility/Popovers/PopoverMenu.vue +3 -3
  40. package/src/components/Utility/Tools/RenderVnode.vue +21 -12
  41. package/src/helpers/actions.ts +198 -188
  42. package/src/styles/general.scss +12 -11
  43. package/src/styles/quasar-reset.scss +81 -22
  44. package/src/styles/themes/danx/action-table.scss +19 -0
  45. package/src/styles/themes/danx/buttons.scss +13 -0
  46. package/src/styles/themes/danx/dialogs.scss +43 -0
  47. package/src/styles/themes/danx/forms.scss +23 -0
  48. package/src/styles/themes/danx/index.scss +7 -0
  49. package/src/styles/themes/danx/panels.scss +19 -0
  50. package/src/styles/themes/danx/sidebar.scss +3 -0
  51. package/src/styles/themes/danx/toolbar.scss +3 -0
  52. package/types/index.d.ts +1 -0
  53. package/src/styles/actions.scss +0 -10
@@ -1,42 +1,44 @@
1
- import { onMounted } from "vue";
2
- import { getUrlParam } from "../../helpers";
1
+ import { ListControlsPagination } from "src/components/ActionTable/listControls";
2
+ import { TableColumn } from "src/components/ActionTable/tableColumns";
3
+ import { onMounted, Ref } from "vue";
4
+ import { AnyObject, getUrlParam } from "../../helpers";
3
5
 
4
- export function registerStickyScrolling(tableRef) {
5
- onMounted(() => {
6
- const scrollEl = tableRef.value.$el.getElementsByClassName("q-table__middle")[0];
7
- scrollEl.addEventListener("scroll", onScroll);
6
+ export function registerStickyScrolling(tableRef: Ref) {
7
+ onMounted(() => {
8
+ const scrollEl = tableRef.value.$el.getElementsByClassName("q-table__middle")[0];
9
+ scrollEl.addEventListener("scroll", onScroll);
8
10
 
9
- function onScroll({ target }) {
10
- // Add / remove scroll y class based on whether we're scrolling vertically
11
- if (target.scrollTop > 0) {
12
- scrollEl.classList.add("is-scrolling-y");
13
- } else {
14
- scrollEl.classList.remove("is-scrolling-y");
15
- }
11
+ function onScroll({ target }: { target: HTMLElement }) {
12
+ // Add / remove scroll y class based on whether we're scrolling vertically
13
+ if (target.scrollTop > 0) {
14
+ scrollEl.classList.add("is-scrolling-y");
15
+ } else {
16
+ scrollEl.classList.remove("is-scrolling-y");
17
+ }
16
18
 
17
- // Add / remove scroll x class based on whether we're scrolling horizontally
18
- if (target.scrollLeft > 0) {
19
- scrollEl.classList.add("is-scrolling-x");
20
- } else {
21
- scrollEl.classList.remove("is-scrolling-x");
22
- }
23
- }
24
- });
19
+ // Add / remove scroll x class based on whether we're scrolling horizontally
20
+ if (target.scrollLeft > 0) {
21
+ scrollEl.classList.add("is-scrolling-x");
22
+ } else {
23
+ scrollEl.classList.remove("is-scrolling-x");
24
+ }
25
+ }
26
+ });
25
27
  }
26
28
 
27
- export function mapSortBy(pagination, columns) {
28
- if (!pagination.sortBy) return null;
29
+ export function mapSortBy(pagination: ListControlsPagination, columns: TableColumn[]) {
30
+ if (!pagination.sortBy) return null;
29
31
 
30
- const column = columns.find(c => c.name === pagination.sortBy);
31
- if (!column) return null;
32
+ const column = columns.find(c => c.name === pagination.sortBy);
33
+ if (!column) return null;
32
34
 
33
- return [
34
- {
35
- column: column.sortBy || column.name,
36
- expression: column.sortByExpression || undefined,
37
- order: pagination.descending ? "desc" : "asc"
38
- }
39
- ];
35
+ return [
36
+ {
37
+ column: column.sortBy || column.name,
38
+ expression: column.sortByExpression || undefined,
39
+ order: pagination.descending ? "desc" : "asc"
40
+ }
41
+ ];
40
42
  }
41
43
 
42
44
  /**
@@ -44,16 +46,16 @@ export function mapSortBy(pagination, columns) {
44
46
  * @param url
45
47
  * @param allowedKeys
46
48
  */
47
- export function getFilterFromUrl(url: string, allowedKeys = null) {
48
- const filter = {};
49
- const urlFilter = getUrlParam("filter", url);
50
- if (urlFilter) {
51
- const fields = JSON.parse(urlFilter);
52
- Object.keys(fields).forEach((key) => {
53
- if (!allowedKeys || allowedKeys.includes(key)) {
54
- filter[key] = fields[key];
55
- }
56
- });
57
- }
58
- return filter;
49
+ export function getFilterFromUrl(url: string, allowedKeys: string[] | null = null) {
50
+ const filter: AnyObject = {};
51
+ const urlFilter = getUrlParam("filter", url);
52
+ if (urlFilter) {
53
+ const fields = JSON.parse(urlFilter);
54
+ Object.keys(fields).forEach((key) => {
55
+ if (!allowedKeys || allowedKeys.includes(key)) {
56
+ filter[key] = fields[key];
57
+ }
58
+ });
59
+ }
60
+ return filter;
59
61
  }
@@ -1,82 +1,82 @@
1
- import { computed, ref, watch } from "vue";
2
- import { getItem, setItem } from "../../helpers";
1
+ import { computed, ref, VNode, watch } from "vue";
2
+ import { ActionOptions, getItem, setItem } from "../../helpers";
3
3
 
4
4
  export interface TableColumn {
5
- actionMenu?: object,
6
- align?: string,
7
- category?: string,
8
- class?: string | object,
9
- field: string,
10
- format?: Function,
11
- innerClass?: string | object,
12
- style?: string | object,
13
- headerStyle?: string | object,
14
- isSavingRow?: boolean | Function,
15
- label: string,
16
- maxWidth?: number,
17
- minWidth?: number,
18
- name: string,
19
- onClick?: Function,
20
- required?: boolean,
21
- resizeable?: boolean,
22
- sortable?: boolean,
23
- sortBy?: string,
24
- sortByExpression?: string,
25
- titleColumns?: Function,
26
- vnode?: Function,
5
+ actionMenu?: ActionOptions[],
6
+ align?: string,
7
+ category?: string,
8
+ class?: string | object,
9
+ field: string,
10
+ format?: (value: any, options: any) => any,
11
+ innerClass?: string | object,
12
+ style?: string | object,
13
+ headerStyle?: string | object,
14
+ isSavingRow?: boolean | (() => boolean),
15
+ label: string,
16
+ maxWidth?: number,
17
+ minWidth?: number,
18
+ name: string,
19
+ onClick?: (target: any) => void,
20
+ required?: boolean,
21
+ resizeable?: boolean,
22
+ sortable?: boolean,
23
+ sortBy?: string,
24
+ sortByExpression?: string,
25
+ titleColumns?: () => string[],
26
+ vnode?: () => VNode,
27
27
  }
28
28
 
29
29
  export function useTableColumns(name: string, columns: TableColumn[]) {
30
- const COLUMN_ORDER_KEY = `${name}-column-order`;
31
- const VISIBLE_COLUMNS_KEY = `${name}-visible-columns`;
32
- const TITLE_COLUMNS_KEY = `${name}-title-columns`;
30
+ const COLUMN_ORDER_KEY = `${name}-column-order`;
31
+ const VISIBLE_COLUMNS_KEY = `${name}-visible-columns`;
32
+ const TITLE_COLUMNS_KEY = `${name}-title-columns`;
33
33
 
34
- // The list that defines the order the columns should appear in
35
- const columnOrder = ref(getItem(COLUMN_ORDER_KEY) || []);
34
+ // The list that defines the order the columns should appear in
35
+ const columnOrder = ref(getItem(COLUMN_ORDER_KEY) || []);
36
36
 
37
- // Manages visible columns on the table
38
- const hiddenColumnNames = ref(getItem(VISIBLE_COLUMNS_KEY, []));
37
+ // Manages visible columns on the table
38
+ const hiddenColumnNames = ref(getItem(VISIBLE_COLUMNS_KEY, []));
39
39
 
40
- // Title columns will have their name appear on the first column of the table as part of the records' title
41
- const titleColumnNames = ref(getItem(TITLE_COLUMNS_KEY, []));
40
+ // Title columns will have their name appear on the first column of the table as part of the records' title
41
+ const titleColumnNames = ref(getItem(TITLE_COLUMNS_KEY, []));
42
42
 
43
- // Columns that should be locked to the left side of the table
44
- const lockedColumns = computed(() => orderedColumns.value.slice(0, 1));
43
+ // Columns that should be locked to the left side of the table
44
+ const lockedColumns = computed(() => orderedColumns.value.slice(0, 1));
45
45
 
46
- // The resolved list of columns in the order they should appear in
47
- const orderedColumns = computed(() => [...columns].sort((a, b) => {
48
- const aIndex = columnOrder.value.indexOf(a.name);
49
- const bIndex = columnOrder.value.indexOf(b.name);
50
- return aIndex === -1 ? 1 : bIndex === -1 ? -1 : aIndex - bIndex;
51
- }));
46
+ // The resolved list of columns in the order they should appear in
47
+ const orderedColumns = computed(() => [...columns].sort((a, b) => {
48
+ const aIndex = columnOrder.value.indexOf(a.name);
49
+ const bIndex = columnOrder.value.indexOf(b.name);
50
+ return aIndex === -1 ? 1 : bIndex === -1 ? -1 : aIndex - bIndex;
51
+ }));
52
52
 
53
- // The ordered list of columns. The ordering of this list is editable and will be stored in localStorage
54
- const sortableColumns = computed({
55
- get() {
56
- return orderedColumns.value.slice(1);
57
- },
58
- set(newColumns) {
59
- columnOrder.value = [...lockedColumns.value.map(c => c.name), ...newColumns.map(c => c.name)];
60
- setItem(COLUMN_ORDER_KEY, columnOrder.value);
61
- }
62
- });
53
+ // The ordered list of columns. The ordering of this list is editable and will be stored in localStorage
54
+ const sortableColumns = computed({
55
+ get() {
56
+ return orderedColumns.value.slice(1);
57
+ },
58
+ set(newColumns) {
59
+ columnOrder.value = [...lockedColumns.value.map(c => c.name), ...newColumns.map(c => c.name)];
60
+ setItem(COLUMN_ORDER_KEY, columnOrder.value);
61
+ }
62
+ });
63
63
 
64
- // The list of columns that are visible. To edit the visible columns, edit the hiddenColumnNames list
65
- const visibleColumns = computed(() => orderedColumns.value.filter(c => !hiddenColumnNames.value.includes(c.name)));
64
+ // The list of columns that are visible. To edit the visible columns, edit the hiddenColumnNames list
65
+ const visibleColumns = computed(() => orderedColumns.value.filter(c => !hiddenColumnNames.value.includes(c.name)));
66
66
 
67
- // The list of columns that should be included in the title of a row
68
- const orderedTitleColumns = computed(() => orderedColumns.value.filter(c => titleColumnNames.value.includes(c.name)));
67
+ // The list of columns that should be included in the title of a row
68
+ const orderedTitleColumns = computed(() => orderedColumns.value.filter(c => titleColumnNames.value.includes(c.name)));
69
69
 
70
- // Save changes to the list of hidden columns in localStorage
71
- watch(() => hiddenColumnNames.value, () => setItem(VISIBLE_COLUMNS_KEY, hiddenColumnNames.value));
72
- watch(() => titleColumnNames.value, () => setItem(TITLE_COLUMNS_KEY, titleColumnNames.value));
70
+ // Save changes to the list of hidden columns in localStorage
71
+ watch(() => hiddenColumnNames.value, () => setItem(VISIBLE_COLUMNS_KEY, hiddenColumnNames.value));
72
+ watch(() => titleColumnNames.value, () => setItem(TITLE_COLUMNS_KEY, titleColumnNames.value));
73
73
 
74
- return {
75
- sortableColumns,
76
- lockedColumns,
77
- visibleColumns,
78
- hiddenColumnNames,
79
- titleColumnNames,
80
- orderedTitleColumns
81
- };
74
+ return {
75
+ sortableColumns,
76
+ lockedColumns,
77
+ visibleColumns,
78
+ hiddenColumnNames,
79
+ titleColumnNames,
80
+ orderedTitleColumns
81
+ };
82
82
  }
@@ -4,30 +4,40 @@
4
4
  :show="true"
5
5
  overlay
6
6
  content-class="h-full"
7
+ class="dx-panels-drawer"
7
8
  title=""
8
9
  @update:show="$emit('close')"
9
10
  >
10
11
  <div class="flex flex-col flex-nowrap h-full">
11
- <div class="flex items-center px-6 py-4 border-b">
12
+ <div class="dx-panels-drawer-header flex items-center px-6 py-4">
12
13
  <div class="flex-grow">
13
- <slot name="header" />
14
+ <slot name="header">
15
+ <h2>{{ title }}</h2>
16
+ </slot>
17
+ </div>
18
+ <div
19
+ v-if="$slots.controls"
20
+ class="mr-4"
21
+ >
22
+ <slot name="controls" />
14
23
  </div>
15
-
16
24
  <div>
17
- <QBtn @click="$emit('close')">
25
+ <QBtn
26
+ class="dx-close-button"
27
+ @click="$emit('close')"
28
+ >
18
29
  <CloseIcon class="w-4" />
19
30
  </QBtn>
20
31
  </div>
21
32
  </div>
22
- <div class="flex-grow overflow-hidden h-full">
33
+ <div class="dx-panels-drawer-body flex-grow overflow-hidden h-full">
23
34
  <div class="flex items-stretch flex-nowrap h-full">
24
- <div class="border-r w-[13.5rem] overflow-y-auto">
25
- <PanelsDrawerTabs
26
- v-model="activePanel"
27
- :panels="panels"
28
- @update:model-value="$emit('update:model-value', $event)"
29
- />
30
- </div>
35
+ <PanelsDrawerTabs
36
+ v-model="activePanel"
37
+ :class="tabsClass"
38
+ :panels="panels"
39
+ @update:model-value="$emit('update:model-value', $event)"
40
+ />
31
41
  <PanelsDrawerPanels
32
42
  :panels="panels"
33
43
  :active-panel="activePanel"
@@ -44,27 +54,28 @@
44
54
  </div>
45
55
  </ContentDrawer>
46
56
  </template>
47
- <script setup>
57
+ <script setup lang="ts">
48
58
  import { ref, watch } from "vue";
49
59
  import { XIcon as CloseIcon } from "../../svg";
60
+ import { ActionPanel } from "../ActionTable";
50
61
  import { ContentDrawer } from "../Utility";
51
62
  import PanelsDrawerPanels from "./PanelsDrawerPanels";
52
63
  import PanelsDrawerTabs from "./PanelsDrawerTabs";
53
64
 
65
+ export interface Props {
66
+ title?: string,
67
+ modelValue?: string,
68
+ tabsClass?: string | object,
69
+ panelsClass?: string | object,
70
+ panels: ActionPanel[]
71
+ }
72
+
54
73
  defineEmits(["update:model-value", "close"]);
55
- const props = defineProps({
56
- modelValue: {
57
- type: String,
58
- default: null
59
- },
60
- panelsClass: {
61
- type: [Object, String],
62
- default: "w-[35.5rem]"
63
- },
64
- panels: {
65
- type: Array,
66
- required: true
67
- }
74
+ const props = withDefaults(defineProps<Props>(), {
75
+ title: "",
76
+ modelValue: null,
77
+ tabsClass: "w-[13.5rem]",
78
+ panelsClass: "w-[35.5rem]"
68
79
  });
69
80
 
70
81
  const activePanel = ref(props.modelValue);
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <QTabPanels
3
3
  :model-value="activePanel"
4
- class="overflow-y-auto bg-gray-100 h-full transition-all"
4
+ class="dx-panels-drawer-panels overflow-y-auto h-full transition-all"
5
5
  >
6
6
  <QTabPanel
7
7
  v-for="panel in panels"
@@ -1,5 +1,6 @@
1
1
  <template>
2
2
  <QTabs
3
+ class="dx-panels-drawer-tabs overflow-y-auto"
3
4
  :model-value="modelValue"
4
5
  vertical
5
6
  align="left"
@@ -50,8 +51,6 @@ defineProps({
50
51
 
51
52
  :global(.q-tab) {
52
53
  justify-content: start !important;
53
- padding: 0;
54
- @apply text-left py-2.5 px-2 rounded-lg hover:bg-slate-200;
55
54
 
56
55
  :global(.q-focus-helper), :global(.q-tab__indicator) {
57
56
  display: none;
@@ -61,9 +60,5 @@ defineProps({
61
60
  @apply p-0;
62
61
  }
63
62
  }
64
-
65
- :global(.q-tab.q-tab--active) {
66
- @apply text-white bg-blue-600;
67
- }
68
63
  }
69
64
  </style>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <QBtn
3
- class="bg-slate-200"
3
+ class="dx-export-button dx-action-button"
4
4
  :loading="isExporting"
5
5
  @click="onExport"
6
6
  >
@@ -1,16 +1,16 @@
1
1
  <template>
2
2
  <QBtn
3
- class="bg-slate-200"
3
+ class="dx-refresh-button dx-action-button"
4
4
  :loading="loading"
5
5
  >
6
6
  <RefreshIcon class="w-5" />
7
7
  </QBtn>
8
8
  </template>
9
- <script setup>
9
+ <script setup lang="ts">
10
10
  import { RefreshIcon } from "@heroicons/vue/solid";
11
11
 
12
12
  defineEmits(["refresh"]);
13
- defineProps({
14
- loading: Boolean
15
- });
13
+ defineProps<{
14
+ loading?: boolean
15
+ }>();
16
16
  </script>
@@ -1,7 +1,7 @@
1
1
  <template>
2
- <div class="previous-next-controls">
2
+ <div class="dx-previous-next-controls">
3
3
  <QBtn
4
- class="bg-slate-200 border-gray-300 border border-solid !rounded-r-none !p-2 !min-w-0"
4
+ class="dx-control dx-control-previous border border-solid !rounded-r-none !p-2 !min-w-0"
5
5
  :disable="isLoading"
6
6
  :loading="isLoading"
7
7
  @click="$emit('next', -1)"
@@ -9,7 +9,7 @@
9
9
  <SkipPreviousIcon class="w-6" />
10
10
  </QBtn>
11
11
  <QBtn
12
- class="bg-slate-200 border-gray-300 border border-solid border-l-0 !rounded-l-none !p-2 !min-w-0"
12
+ class="dx-control dx-control-next border border-solid border-l-0 !rounded-l-none !p-2 !min-w-0"
13
13
  :disable="isLoading"
14
14
  :loading="isLoading"
15
15
  @click="$emit('next', 1)"
@@ -23,6 +23,6 @@ import { SkipNextIcon, SkipPreviousIcon } from "../../../svg";
23
23
 
24
24
  defineEmits(["next"]);
25
25
  defineProps({
26
- isLoading: Boolean
26
+ isLoading: Boolean
27
27
  });
28
28
  </script>
@@ -1,135 +1,89 @@
1
1
  <template>
2
- <QDialog
3
- :full-height="fullHeight"
4
- :full-width="fullWidth"
5
- :model-value="!!modelValue"
6
- :no-backdrop-dismiss="!backdropDismiss"
7
- :maximized="maximized"
8
- @update:model-value="onClose"
2
+ <DialogLayout
3
+ class="dx-confirm-dialog"
4
+ v-bind="layoutProps"
5
+ @close="onClose"
9
6
  >
10
- <QCard class="flex flex-col flex-nowrap">
11
- <QCardSection
12
- v-if="title || $slots.title"
13
- class="pl-6 pr-10 border-b border-gray-300"
14
- >
15
- <h3
16
- class="font-normal flex items-center"
17
- :class="titleClass"
18
- >
19
- <slot name="title">
20
- {{ title }}
21
- </slot>
22
- </h3>
23
- <div
24
- v-if="subtitle"
25
- class="mt-1 text-sm"
7
+ <template
8
+ v-for="slotName in childSlots"
9
+ #[slotName]
10
+ >
11
+ <slot :name="slotName" />
12
+ </template>
13
+
14
+ <template #actions>
15
+ <div class="dx-dialog-button-cancel">
16
+ <QBtn
17
+ :label="cancelText"
18
+ class="dx-dialog-button"
19
+ @click="onClose"
26
20
  >
27
- {{ subtitle }}
28
- </div>
29
- </QCardSection>
30
- <QCardSection v-if="$slots.toolbar">
31
- <slot name="toolbar" />
32
- </QCardSection>
33
- <QCardSection
34
- v-if="content || $slots.default"
35
- class="px-6 bg-gray-100 flex-grow max-h-full overflow-y-auto"
36
- :class="contentClass"
37
- >
38
- <slot>{{ content }}</slot>
39
- </QCardSection>
40
- <div class="flex px-6 py-4 border-t border-gray-300">
41
- <div class="flex-grow">
42
- <QBtn
43
- :label="cancelText"
44
- class="action-btn btn-white-gray"
45
- @click="onClose"
46
- >
47
- <slot name="cancel-text" />
48
- </QBtn>
49
- </div>
50
- <slot name="actions" />
51
- <div v-if="!hideConfirm">
52
- <QBtn
53
- :label="$slots['confirm-text'] ? '' : confirmText"
54
- class="action-btn ml-4"
55
- :class="confirmClass"
56
- :loading="isSaving"
57
- :disable="disabled"
58
- data-testid="confirm-button"
59
- @click="onConfirm"
60
- >
61
- <slot name="confirm-text" />
62
- </QBtn>
63
- </div>
21
+ <slot name="cancel-text" />
22
+ </QBtn>
64
23
  </div>
65
- <a
66
- class="absolute top-0 right-0 p-4 text-black"
67
- @click="onClose"
24
+ <slot name="actions" />
25
+ <div
26
+ v-if="!hideConfirm"
27
+ class="dx-dialog-button-confirm"
68
28
  >
69
- <CloseIcon class="w-5" />
70
- </a>
71
- </QCard>
72
- </QDialog>
29
+ <QBtn
30
+ :label="$slots['confirm-text'] ? '' : confirmText"
31
+ class="dx-dialog-button"
32
+ :class="confirmClass"
33
+ :loading="isSaving"
34
+ :disable="disabled"
35
+ data-testid="confirm-button"
36
+ @click="onConfirm"
37
+ >
38
+ <slot name="confirm-text" />
39
+ </QBtn>
40
+ </div>
41
+ </template>
42
+ </DialogLayout>
73
43
  </template>
74
44
 
75
45
  <script setup>
76
- import { XIcon as CloseIcon } from "@heroicons/vue/outline";
46
+ import { computed } from "vue";
47
+ import DialogLayout from "./DialogLayout";
77
48
 
78
49
  const emit = defineEmits(["update:model-value", "confirm", "close"]);
79
50
  const props = defineProps({
80
- modelValue: { type: [String, Boolean, Object], default: true },
81
- title: {
82
- type: String,
83
- default: ""
84
- },
85
- titleClass: {
86
- type: String,
87
- default: ""
88
- },
89
- subtitle: {
90
- type: String,
91
- default: ""
92
- },
93
- content: {
94
- type: String,
95
- default: ""
96
- },
97
- backdropDismiss: Boolean,
98
- maximized: Boolean,
99
- fullWidth: Boolean,
100
- fullHeight: Boolean,
101
- disabled: Boolean,
102
- isSaving: Boolean,
103
- closeOnConfirm: Boolean,
104
- hideConfirm: Boolean,
105
- confirmText: {
106
- type: String,
107
- default: "Confirm"
108
- },
109
- cancelText: {
110
- type: String,
111
- default: "Cancel"
112
- },
113
- confirmClass: {
114
- type: String,
115
- default: "bg-blue-600 text-white"
116
- },
117
- contentClass: {
118
- type: String,
119
- default: ""
120
- }
51
+ ...DialogLayout.props,
52
+ disabled: Boolean,
53
+ isSaving: Boolean,
54
+ closeOnConfirm: Boolean,
55
+ hideConfirm: Boolean,
56
+ confirmText: {
57
+ type: String,
58
+ default: "Confirm"
59
+ },
60
+ cancelText: {
61
+ type: String,
62
+ default: "Cancel"
63
+ },
64
+ confirmClass: {
65
+ type: String,
66
+ default: ""
67
+ },
68
+ contentClass: {
69
+ type: String,
70
+ default: ""
71
+ }
121
72
  });
122
73
 
74
+ const layoutProps = computed(() => ({ ...props, disabled: undefined }));
75
+ const childSlots = computed(() => ["title", "subtitle", "default", "toolbar"]);
76
+
123
77
  function onConfirm() {
124
- emit("confirm");
78
+ emit("confirm");
125
79
 
126
- if (props.closeOnConfirm) {
127
- emit("close");
128
- }
80
+ if (props.closeOnConfirm) {
81
+ emit("close");
82
+ }
129
83
  }
130
84
 
131
85
  function onClose() {
132
- emit("update:model-value", false);
133
- emit("close");
86
+ emit("update:model-value", false);
87
+ emit("close");
134
88
  }
135
89
  </script>