quasar-ui-danx 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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>
@@ -0,0 +1,95 @@
1
+ <template>
2
+ <QDialog
3
+ class="dx-dialog"
4
+ :full-height="fullHeight"
5
+ :full-width="fullWidth"
6
+ :model-value="!!modelValue"
7
+ :no-backdrop-dismiss="!backdropDismiss"
8
+ :maximized="maximized"
9
+ @update:model-value="onClose"
10
+ >
11
+ <QCard class="dx-dialog-card flex flex-col flex-nowrap">
12
+ <QCardSection
13
+ class="dx-dialog-header flex items-center"
14
+ >
15
+ <div class="flex-grow">
16
+ <h3
17
+ v-if="title || $slots.title"
18
+ class="dx-dialog-title flex items-center"
19
+ :class="titleClass"
20
+ >
21
+ <slot name="title">
22
+ {{ title }}
23
+ </slot>
24
+ </h3>
25
+ <div
26
+ v-if="subtitle || $slots.subtitle"
27
+ class="dx-dialog-subtitle"
28
+ >
29
+ <slot name="subtitle">
30
+ {{ subtitle }}
31
+ </slot>
32
+ </div>
33
+ </div>
34
+ <div>
35
+ <div
36
+ class="dx-close-button cursor-pointer"
37
+ @click="onClose"
38
+ >
39
+ <CloseIcon class="w-5" />
40
+ </div>
41
+ </div>
42
+ </QCardSection>
43
+ <QCardSection v-if="$slots.toolbar">
44
+ <slot name="toolbar" />
45
+ </QCardSection>
46
+ <QCardSection
47
+ v-if="content || $slots.default"
48
+ class="dx-dialog-content flex-grow max-h-full overflow-y-auto"
49
+ :class="contentClass"
50
+ >
51
+ <slot>{{ content }}</slot>
52
+ </QCardSection>
53
+ <div class="flex dx-dialog-actions">
54
+ <slot name="actions" />
55
+ </div>
56
+ </QCard>
57
+ </QDialog>
58
+ </template>
59
+
60
+ <script setup>
61
+ import { XIcon as CloseIcon } from "@heroicons/vue/outline";
62
+
63
+ const emit = defineEmits(["close"]);
64
+ defineProps({
65
+ modelValue: { type: [String, Boolean, Object], default: true },
66
+ title: {
67
+ type: String,
68
+ default: ""
69
+ },
70
+ titleClass: {
71
+ type: String,
72
+ default: ""
73
+ },
74
+ subtitle: {
75
+ type: String,
76
+ default: ""
77
+ },
78
+ content: {
79
+ type: String,
80
+ default: ""
81
+ },
82
+ backdropDismiss: Boolean,
83
+ maximized: Boolean,
84
+ fullWidth: Boolean,
85
+ fullHeight: Boolean,
86
+ contentClass: {
87
+ type: String,
88
+ default: ""
89
+ }
90
+ });
91
+
92
+ function onClose() {
93
+ emit("close");
94
+ }
95
+ </script>
@@ -1,95 +1,55 @@
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-info-dialog"
4
+ v-bind="$props"
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"
7
+ <template
8
+ v-if="$slots.title"
9
+ #title
10
+ >
11
+ <slot name="title" />
12
+ </template>
13
+ <template
14
+ v-if="$slots.subtitle"
15
+ #subtitle
16
+ >
17
+ <slot name="subtitle" />
18
+ </template>
19
+ <template #actions>
20
+ <div class="flex-grow">
21
+ <QBtn
22
+ :label="doneText"
23
+ class="dx-dialog-button dx-dialog-button-done"
24
+ :class="doneClass"
25
+ @click="onClose"
18
26
  >
19
- <slot name="title">
20
- {{ title }}
21
- </slot>
22
- </h3>
23
- <div
24
- v-if="subtitle"
25
- class="mt-1 text-sm"
26
- >
27
- {{ subtitle }}
28
- </div>
29
- </QCardSection>
30
- <QCardSection
31
- v-if="content || $slots.default"
32
- class="px-6 bg-gray-100 flex-grow max-h-full overflow-y-auto"
33
- >
34
- <slot>{{ content }}</slot>
35
- </QCardSection>
36
- <div
37
- class="flex items-center justify-center px-6 py-4 border-t border-gray-300"
38
- >
39
- <div class="flex-grow text-right">
40
- <QBtn
41
- :label="doneText"
42
- class="action-btn btn-white-gray"
43
- @click="onClose"
44
- >
45
- <slot name="done-text" />
46
- </QBtn>
47
- </div>
27
+ <slot name="done-text" />
28
+ </QBtn>
48
29
  </div>
49
- <a
50
- class="absolute top-0 right-0 p-4 text-black"
51
- @click="onClose"
52
- >
53
- <CloseIcon class="w-5" />
54
- </a>
55
- </QCard>
56
- </QDialog>
30
+ <slot name="actions" />
31
+ </template>
32
+ </DialogLayout>
57
33
  </template>
58
34
 
59
35
  <script setup>
60
- import { XIcon as CloseIcon } from "@heroicons/vue/outline";
36
+ import DialogLayout from "./DialogLayout";
61
37
 
62
38
  const emit = defineEmits(["update:model-value", "close"]);
63
39
  defineProps({
64
- modelValue: { type: [Boolean, Object], default: true },
65
- title: {
66
- type: String,
67
- default: ""
68
- },
69
- titleClass: {
70
- type: String,
71
- default: ""
72
- },
73
- subtitle: {
74
- type: String,
75
- default: ""
76
- },
77
- content: {
78
- type: String,
79
- default: ""
80
- },
81
- backdropDismiss: Boolean,
82
- maximized: Boolean,
83
- fullWidth: Boolean,
84
- fullHeight: Boolean,
85
- doneText: {
86
- type: String,
87
- default: "Done"
88
- }
40
+ ...DialogLayout.props,
41
+ doneClass: {
42
+ type: [String, Object],
43
+ default: ""
44
+ },
45
+ doneText: {
46
+ type: String,
47
+ default: "Done"
48
+ }
89
49
  });
90
50
 
91
51
  function onClose() {
92
- emit("update:model-value", false);
93
- emit("close");
52
+ emit("update:model-value", false);
53
+ emit("close");
94
54
  }
95
55
  </script>
@@ -2,20 +2,29 @@
2
2
  import { isRef, isVNode } from "vue";
3
3
 
4
4
  const RenderVnode = (props) => {
5
- if (isVNode(props.vnode)) {
6
- return props.vnode;
7
- }
5
+ if (isVNode(props.vnode)) {
6
+ return props.vnode;
7
+ }
8
+
9
+ if (isRef(props.vnode)) {
10
+ return props.vnode.value;
11
+ }
8
12
 
9
- if (isRef(props.vnode)) {
10
- return props.vnode.value;
11
- }
13
+ if (typeof props.vnode === "function") {
14
+ return props.vnode(props.props);
15
+ }
12
16
 
13
- if (typeof props.vnode === "function") {
14
- return props.vnode();
15
- }
16
-
17
- return null;
17
+ return null;
18
+ };
19
+ RenderVnode.props = {
20
+ vnode: {
21
+ type: [Function, Object],
22
+ required: true
23
+ },
24
+ props: {
25
+ type: Object,
26
+ default: () => ({})
27
+ }
18
28
  };
19
- RenderVnode.props = { vnode: { type: [Function, Object], required: true } };
20
29
  export default RenderVnode;
21
30
  </script>
@@ -9,7 +9,7 @@ export type ActionTargetItem = {
9
9
  isSaving: Ref<boolean>;
10
10
  [key: string]: any;
11
11
  };
12
- export type ActionTarget = ActionTargetItem[] | ActionTargetItem;
12
+ export type ActionTarget = ActionTargetItem[] | ActionTargetItem | null;
13
13
 
14
14
  export interface ActionOptions {
15
15
  name?: string;
@@ -23,9 +23,9 @@ export interface ActionOptions {
23
23
  vnode?: ((target: ActionTarget) => VNode) | undefined;
24
24
  enabled?: (target: object) => boolean;
25
25
  batchEnabled?: (targets: object[]) => boolean;
26
- optimistic?: (action: ActionOptions, target: object, input: any) => void;
27
- onAction?: (action: string | null | undefined, target: object, input: any) => Promise<any>;
28
- onBatchAction?: (action: string | null | undefined, targets: object[], input: any) => Promise<any>;
26
+ optimistic?: (action: ActionOptions, target: ActionTargetItem | null, input: any) => void;
27
+ onAction?: (action: string | null | undefined, target: ActionTargetItem | null, input: any) => Promise<any>;
28
+ onBatchAction?: (action: string | null | undefined, targets: ActionTargetItem[], input: any) => Promise<any>;
29
29
  onStart?: (action: ActionOptions | null, targets: ActionTarget, input: any) => boolean;
30
30
  onSuccess?: (result: any, targets: ActionTarget, input: any) => any;
31
31
  onError?: (result: any, targets: ActionTarget, input: any) => any;
@@ -60,7 +60,7 @@ export function useActions(actions: ActionOptions[], globalOptions: ActionOption
60
60
  for (const t of target) {
61
61
  t.isSaving.value = saving;
62
62
  }
63
- } else {
63
+ } else if (target) {
64
64
  target.isSaving.value = saving;
65
65
  }
66
66
  }
@@ -73,7 +73,7 @@ export function useActions(actions: ActionOptions[], globalOptions: ActionOption
73
73
  * @param {any} input - The input data to pass to the action handler
74
74
  * @param isTriggered - Whether the action was triggered by a trigger function
75
75
  */
76
- async function performAction(name: string | object, target: ActionTarget, input: any = null, isTriggered = false) {
76
+ async function performAction(name: string | object, target: ActionTarget = null, input: any = null, isTriggered = false) {
77
77
  const action: ActionOptions | null | undefined = typeof name === "string" ? mappedActions.find(a => a.name === name) : name;
78
78
  if (!action) {
79
79
  throw new Error(`Unknown action: ${name}`);
@@ -1,80 +1,91 @@
1
1
  .danx-app {
2
- .q-tab {
3
- text-transform: capitalize
4
- }
5
-
6
- .q-table__card {
7
- background: inherit;
8
- color: inherit;
9
- }
10
-
11
- .q-checkbox__inner {
12
- color: inherit;
13
- }
14
-
15
- .q-toolbar {
16
- min-height: 0;
17
- padding: 0;
18
- }
19
-
20
- .q-notification__actions {
21
- color: inherit;
22
- }
23
-
24
- .q-date {
25
- min-width: 100px;
26
-
27
- .q-date__view {
28
- min-height: 0;
29
- }
30
- }
31
-
32
- .q-field {
33
- &.q-field--auto-height {
34
- .q-field__control {
35
- min-height: 0;
36
-
37
- .q-field__native {
38
- min-height: 0;
39
- color: inherit;
40
- }
41
- }
42
-
43
- }
44
-
45
- &.q-field--labeled {
46
- .q-field__control-container {
47
- padding-top: 1.1rem;
48
- }
49
- }
50
-
51
- .q-field__marginal, .q-field__input, .q-field__label {
52
- color: inherit;
53
- }
54
- }
2
+ .q-tab {
3
+ text-transform: capitalize
4
+ }
5
+
6
+ .q-table__card {
7
+ background: inherit;
8
+ color: inherit;
9
+ }
10
+
11
+ .q-checkbox__inner {
12
+ color: inherit;
13
+ }
14
+
15
+ .q-toolbar {
16
+ min-height: 0;
17
+ padding: 0;
18
+ }
19
+
20
+ .q-notification__actions {
21
+ color: inherit;
22
+ }
23
+
24
+ .q-date {
25
+ min-width: 100px;
26
+
27
+ .q-date__view {
28
+ min-height: 0;
29
+ }
30
+ }
31
+
32
+ .q-field {
33
+ &.q-field--auto-height {
34
+ .q-field__control {
35
+ min-height: 0;
36
+
37
+ .q-field__native {
38
+ min-height: 0;
39
+ color: inherit;
40
+ }
41
+ }
42
+
43
+ }
44
+
45
+ &.q-field--labeled {
46
+ .q-field__control-container {
47
+ padding-top: 1.1rem;
48
+ }
49
+ }
50
+
51
+ .q-field__marginal, .q-field__input, .q-field__label {
52
+ color: inherit;
53
+ }
54
+ }
55
+ }
56
+
57
+ .q-btn {
58
+ text-transform: inherit;
59
+ @apply bg-inherit text-inherit;
55
60
  }
56
61
 
57
62
  .q-item {
58
- min-height: 0;
63
+ min-height: 0;
59
64
  }
60
65
 
61
66
  .q-tab-panels {
62
- overflow: visible;
63
- background: inherit;
67
+ overflow: visible;
68
+ background: inherit;
64
69
 
65
- .q-panel {
66
- overflow: visible;
70
+ .q-panel {
71
+ overflow: visible;
67
72
 
68
- &.scroll {
69
- overflow: auto;
70
- }
73
+ &.scroll {
74
+ overflow: auto;
75
+ }
71
76
 
72
- .q-tab-panel {
73
- padding: 0;
74
- }
75
- }
77
+ .q-tab-panel {
78
+ padding: 0;
79
+ }
80
+ }
81
+
82
+ &.overflow-y-auto {
83
+ overflow-y: auto;
84
+ }
85
+ }
76
86
 
77
- &.overflow-y-auto {
78
- overflow-y: auto;
79
- }
87
+ .dx-dialog {
88
+ .q-card__section--vert {
89
+ @apply p-0;
90
+ }
80
91
  }