quasar-ui-danx 0.0.43 → 0.0.44

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quasar-ui-danx",
3
- "version": "0.0.43",
3
+ "version": "0.0.44",
4
4
  "author": "Dan <dan@flytedesk.com>",
5
5
  "description": "DanX Vue / Quasar component library",
6
6
  "license": "MIT",
@@ -48,46 +48,17 @@
48
48
  </q-th>
49
49
  </template>
50
50
  <template #body-cell="rowProps">
51
- <q-td :key="rowProps.key" :props="rowProps">
52
- <component
53
- :is="rowProps.col.onClick ? 'a' : 'div'"
54
- class="flex items-center flex-nowrap"
55
- :class="{'justify-end': rowProps.col.align === 'right', 'justify-center': rowProps.col.align === 'center', 'justify-start': rowProps.col.align === 'left'}"
56
- :style="getColumnStyle(rowProps.col)"
57
- @click="() => rowProps.col.onClick && rowProps.col.onClick(rowProps.row)"
58
- >
59
- <RenderVNode
60
- v-if="rowProps.col.vnode"
61
- :vnode="rowProps.col.vnode(rowProps.row)"
62
- />
63
- <RenderComponent
64
- v-else-if="rowProps.col.component"
65
- :params="[rowProps.row]"
66
- :component="rowProps.col.component"
67
- />
68
- <div v-else-if="rowProps.col.fieldList">
69
- <div v-for="field in rowProps.col.fieldList" :key="field">
70
- {{ rowProps.row[field] }}
71
- </div>
72
- </div>
73
- <div v-else>
74
- <slot v-bind="{name: rowProps.col.name, row: rowProps.row, value: rowProps.value}">
75
- {{ rowProps.value }}
76
- </slot>
77
- </div>
78
- <div v-if="rowProps.col.actions" class="flex-grow flex justify-end pl-2">
79
- <ActionMenu
80
- :actions="rowProps.col.actions"
81
- :target="rowProps.row"
82
- :loading="isSavingRow(rowProps.row)"
83
- @action="(action) => $emit('action', action, rowProps.row)"
84
- />
85
- </div>
86
- </component>
87
- </q-td>
51
+ <ActionTableColumn
52
+ :row-props="rowProps"
53
+ :settings="columnSettings[rowProps.col.name]"
54
+ :is-saving="isSavingRow(rowProps.row)"
55
+ @action="$emit('action', $event, rowProps.row)"
56
+ >
57
+ <slot />
58
+ </ActionTableColumn>
88
59
  </template>
89
60
  <template #bottom>
90
- <ActionInputComponent />
61
+ <ActionVnode />
91
62
  </template>
92
63
  </q-table>
93
64
  </template>
@@ -97,8 +68,8 @@ import { ref } from 'vue';
97
68
  import { getItem, setItem } from '../../helpers';
98
69
  import { DragHandleIcon as RowResizeIcon } from '../../svg';
99
70
  import { HandleDraggable } from '../DragAndDrop';
100
- import { ActionInputComponent, mapSortBy, RenderComponent, RenderVNode } from '../index';
101
- import { ActionMenu, EmptyTableState, registerStickyScrolling, TableSummaryRow } from './index';
71
+ import { ActionVnode, mapSortBy } from '../index';
72
+ import { ActionTableColumn, EmptyTableState, registerStickyScrolling, TableSummaryRow } from './index';
102
73
 
103
74
  defineEmits(['action', 'update:quasar-pagination', 'update:selected-rows']);
104
75
  const props = defineProps({
@@ -147,19 +118,14 @@ registerStickyScrolling(actionTable);
147
118
  const COLUMN_SETTINGS_KEY = `column-settings-${props.name}`;
148
119
  const columnSettings = ref(getItem(COLUMN_SETTINGS_KEY) || {});
149
120
  function onResizeColumn(column, val) {
150
- columnSettings.value[column.name] = Math.max(Math.min(val.distance + val.startDropZoneSize, column.maxWidth || 500), column.minWidth || 80);
121
+ columnSettings.value = {
122
+ ...columnSettings.value,
123
+ [column.name]: {
124
+ width: Math.max(Math.min(val.distance + val.startDropZoneSize, column.maxWidth || 500), column.minWidth || 80)
125
+ }
126
+ };
151
127
  setItem(COLUMN_SETTINGS_KEY, columnSettings.value);
152
128
  }
153
- function getColumnStyle(column) {
154
- const width = columnSettings.value[column.name] || column.width;
155
-
156
- if (width) {
157
- return {
158
- width: `${width}px`
159
- };
160
- }
161
- return null;
162
- }
163
129
 
164
130
  function isSavingRow(row) {
165
131
  if (!props.isSavingTarget) return false;
@@ -0,0 +1,72 @@
1
+ <template>
2
+ <q-td :key="rowProps.key" :props="rowProps" :style="columnStyle">
3
+ <div
4
+ class="flex items-center flex-nowrap"
5
+ :class="columnClass"
6
+ >
7
+ <a
8
+ v-if="column.onClick"
9
+ class="flex-grow"
10
+ @click="column.onClick(row)"
11
+ >
12
+ <RenderVnode
13
+ v-if="column.vnode"
14
+ :vnode="column.vnode(row)"
15
+ />
16
+ <slot v-else v-bind="{name: column.name, row, value}">
17
+ {{ value }}
18
+ </slot>
19
+ </a>
20
+ <div v-else class="flex-grow">
21
+ <RenderVnode
22
+ v-if="column.vnode"
23
+ :vnode="column.vnode(row)"
24
+ />
25
+ <slot v-else v-bind="{name: column.name, row, value}">
26
+ {{ value }}
27
+ </slot>
28
+ </div>
29
+ <div v-if="column.actions" class="flex flex-shrink-0 pl-2">
30
+ <ActionMenu
31
+ :actions="column.actions"
32
+ :target="row"
33
+ :loading="isSaving"
34
+ @action="$emit('action', $event)"
35
+ />
36
+ </div>
37
+ </div>
38
+ </q-td>
39
+ </template>
40
+ <script setup>
41
+ import { computed } from 'vue';
42
+ import { RenderVnode } from '../Utility';
43
+ import { ActionMenu } from './index';
44
+
45
+ defineEmits(['action']);
46
+ const props = defineProps({
47
+ rowProps: {
48
+ type: Object,
49
+ required: true
50
+ },
51
+ settings: {
52
+ type: Object,
53
+ default: null
54
+ },
55
+ isSaving: Boolean
56
+ });
57
+
58
+ const row = computed(() => props.rowProps.row);
59
+ const column = computed(() => props.rowProps.col);
60
+ const value = computed(() => props.rowProps.value);
61
+
62
+ const columnStyle = computed(() => {
63
+ const width = props.settings?.width || column.value.width;
64
+ return width ? { width: `${width}px` } : null;
65
+ });
66
+
67
+ const columnClass = computed(() => ({
68
+ 'justify-end': column.value.align === 'right',
69
+ 'justify-center': column.value.align === 'center',
70
+ 'justify-start': column.value.align === 'left'
71
+ }));
72
+ </script>
@@ -6,5 +6,6 @@ export * from "./listHelpers";
6
6
  export * from "./tableColumns";
7
7
  export { default as ActionMenu } from "./ActionMenu.vue";
8
8
  export { default as ActionTable } from "./ActionTable.vue";
9
+ export { default as ActionTableColumn } from "./ActionTableColumn.vue";
9
10
  export { default as EmptyTableState } from "./EmptyTableState.vue";
10
11
  export { default as TableSummaryRow } from "./TableSummaryRow.vue";
@@ -2,7 +2,7 @@
2
2
  <div class="flex items-center">
3
3
  <component :is="icon" :class="iconClass" />
4
4
  <div :class="textClass">
5
- <slot />
5
+ <slot>{{ text }}</slot>
6
6
  </div>
7
7
  </div>
8
8
  </template>
@@ -14,11 +14,15 @@ defineProps({
14
14
  },
15
15
  iconClass: {
16
16
  type: String,
17
- default: "w-6"
17
+ default: 'w-6'
18
+ },
19
+ text: {
20
+ type: String,
21
+ default: null
18
22
  },
19
23
  textClass: {
20
24
  type: String,
21
- default: "ml-2"
25
+ default: 'ml-2'
22
26
  }
23
27
  });
24
28
  </script>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <div>
3
+ <RenderVnode
4
+ v-if="activeActionVnode"
5
+ :vnode="activeActionVnode.vnode"
6
+ :is-saving="isSaving"
7
+ @confirm="onConfirm"
8
+ @close="activeActionVnode.cancel"
9
+ />
10
+ </div>
11
+ </template>
12
+ <script setup>
13
+ import { ref } from 'vue';
14
+ import { activeActionVnode } from '../../../helpers';
15
+ import { RenderVnode } from './index';
16
+
17
+ const isSaving = ref(false);
18
+ async function onConfirm(input) {
19
+ isSaving.value = true;
20
+ await activeActionVnode.value.confirm(input);
21
+ isSaving.value = false;
22
+ }
23
+ </script>
@@ -0,0 +1,5 @@
1
+ <script>
2
+ const RenderVnode = (props) => props.vnode;
3
+ RenderVnode.props = { vnode: { type: Object, required: true } };
4
+ export default RenderVnode;
5
+ </script>
@@ -1,3 +1,3 @@
1
- export { default as ActionInputComponent } from "./ActionInputComponent.vue";
1
+ export { default as ActionVnode } from "./ActionVnode.vue";
2
2
  export { default as RenderComponent } from "./RenderComponent.vue";
3
- export { default as RenderVNode } from "./RenderVNode.vue";
3
+ export { default as RenderVnode } from "./RenderVnode.vue";
@@ -1,4 +1,4 @@
1
- import { shallowRef } from "vue";
1
+ import { shallowRef, VNode } from "vue";
2
2
  import { FlashMessages } from "./index";
3
3
 
4
4
  interface ActionOptions {
@@ -8,7 +8,7 @@ interface ActionOptions {
8
8
  batch?: boolean;
9
9
  category?: string;
10
10
  class?: string;
11
- inputComponent?: (target: object[] | object) => any;
11
+ vnode?: (target: object[] | object) => VNode;
12
12
  enabled?: (target: object) => boolean;
13
13
  batchEnabled?: (targets: object[]) => boolean;
14
14
  onAction?: (action: string | null, target: object, input: any) => Promise<any>;
@@ -18,7 +18,7 @@ interface ActionOptions {
18
18
  onFinish?: (action: string | null, targets: object, input: any) => any;
19
19
  }
20
20
 
21
- export const activeActionInput = shallowRef(null);
21
+ export const activeActionVnode = shallowRef(null);
22
22
 
23
23
  /**
24
24
  * Hook to perform an action on a set of targets
@@ -98,25 +98,25 @@ export function useActions(actions: ActionOptions[], globalOptions: ActionOption
98
98
  */
99
99
  async performAction(name: string | object, target: object[] | object, input: any = null) {
100
100
  const action = resolveAction(name);
101
- const component = action.inputComponent && action.inputComponent(target);
101
+ const vnode = action.vnode && action.vnode(target);
102
102
  let result = null;
103
103
 
104
104
  isSavingTarget.value = target;
105
105
 
106
- // If no component input is required, we can directly perform the action
107
- if (component) {
108
- // If the action requires an input, we set the activeActionInput to the input component.
109
- // This will tell the ActionInputComponent to render the input component, and confirm or cancel the
106
+ // If additional input is required, first render the vnode and wait for the confirm or cancel action
107
+ if (vnode) {
108
+ // If the action requires an input, we set the activeActionVnode to the input component.
109
+ // This will tell the ActionVnode to render the input component, and confirm or cancel the
110
110
  // action The confirm function has the input from the component passed and will resolve the promise
111
111
  // with the result of the action
112
112
  result = await new Promise((resolve, reject) => {
113
- activeActionInput.value = {
114
- component,
113
+ activeActionVnode.value = {
114
+ vnode,
115
115
  confirm: async input => {
116
116
  const result = await onConfirmAction(action, target, input);
117
117
 
118
118
  // Only resolve when we have a non-error response, so we can show the error message w/o
119
- // hiding the dialog / inputComponent
119
+ // hiding the dialog / vnode
120
120
  if (result === undefined || result === true || result?.success) {
121
121
  resolve(result);
122
122
  }
@@ -125,7 +125,7 @@ export function useActions(actions: ActionOptions[], globalOptions: ActionOption
125
125
  };
126
126
  });
127
127
 
128
- activeActionInput.value = null;
128
+ activeActionVnode.value = null;
129
129
  } else {
130
130
  result = await onConfirmAction(action, target, input);
131
131
  }
@@ -1,23 +0,0 @@
1
- <template>
2
- <div>
3
- <RenderComponent
4
- v-if="activeActionInput"
5
- :component="activeActionInput.component"
6
- :is-saving="isSaving"
7
- @confirm="onConfirm"
8
- @close="activeActionInput.cancel"
9
- />
10
- </div>
11
- </template>
12
- <script setup>
13
- import { ref } from 'vue';
14
- import { activeActionInput } from '../../../helpers';
15
- import RenderComponent from './RenderComponent';
16
-
17
- const isSaving = ref(false);
18
- async function onConfirm(input) {
19
- isSaving.value = true;
20
- await activeActionInput.value.confirm(input);
21
- isSaving.value = false;
22
- }
23
- </script>
@@ -1,6 +0,0 @@
1
- <script>
2
- const RenderVNode = (props) => props.vnode;
3
- RenderVNode.props = { vnode: { type: Object, required: true } };
4
- RenderVNode.emits = ['action'];
5
- export default RenderVNode;
6
- </script>