quasar-ui-danx 0.3.22 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quasar-ui-danx",
3
- "version": "0.3.22",
3
+ "version": "0.4.2",
4
4
  "author": "Dan <dan@flytedesk.com>",
5
5
  "description": "DanX Vue / Quasar component library",
6
6
  "license": "MIT",
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <PopoverMenu
3
- class="px-2 flex action-button"
3
+ class="px-2 flex dx-action-button"
4
4
  :items="activeActions"
5
5
  :disabled="!hasTarget"
6
6
  :tooltip="!hasTarget ? tooltip : null"
@@ -1,21 +1,24 @@
1
1
  <template>
2
- <div class="overflow-hidden w-full">
2
+ <div
3
+ class="dx-action-table overflow-hidden"
4
+ :class="{'dx-no-data': !hasData}"
5
+ >
3
6
  <ActionVnode />
4
7
  <QTable
5
8
  ref="actionTable"
6
9
  :selected="selectedRows"
7
- :pagination="quasarPagination"
8
- :columns="columns"
9
- :loading="isLoadingList"
10
+ :pagination="pagination"
11
+ :columns="tableColumns"
12
+ :loading="loadingList"
10
13
  :rows="pagedItems?.data || []"
11
14
  :binary-state-sort="false"
12
15
  selection="multiple"
13
16
  :rows-per-page-options="rowsPerPageOptions"
14
17
  class="sticky-column sticky-header w-full h-full !border-0"
15
- color="blue-600"
18
+ :color="color"
16
19
  @update:selected="$emit('update:selected-rows', $event)"
17
20
  @update:pagination="() => {}"
18
- @request="$emit('update:quasar-pagination', {...$event.pagination, __sort: mapSortBy($event.pagination, columns)})"
21
+ @request="(e) => $emit('update:pagination', {...e.pagination, __sort: mapSortBy(e.pagination, tableColumns)})"
19
22
  >
20
23
  <template #no-data>
21
24
  <slot name="empty">
@@ -24,12 +27,13 @@
24
27
  </template>
25
28
  <template #top-row>
26
29
  <TableSummaryRow
30
+ v-if="hasData"
27
31
  :label="label"
28
32
  :item-count="summary?.count || 0"
29
33
  :selected-count="selectedRows.length"
30
- :loading="isLoadingSummary"
34
+ :loading="loadingSummary"
31
35
  :summary="summary"
32
- :columns="columns"
36
+ :columns="tableColumns"
33
37
  @clear="$emit('update:selected-rows', [])"
34
38
  />
35
39
  </template>
@@ -60,58 +64,74 @@
60
64
 
61
65
  <script setup>
62
66
  import { QTable } from "quasar";
63
- import { ref } from "vue";
67
+ import { computed, ref } from "vue";
64
68
  import { getItem, setItem } from "../../helpers";
65
69
  import { ActionVnode } from "../Utility";
66
- import ActionTableColumn from "./ActionTableColumn.vue";
67
- import ActionTableHeaderColumn from "./ActionTableHeaderColumn";
70
+ import { ActionTableColumn, ActionTableHeaderColumn } from "./Columns";
68
71
  import EmptyTableState from "./EmptyTableState.vue";
69
72
  import { mapSortBy, registerStickyScrolling } from "./listHelpers";
70
73
  import TableSummaryRow from "./TableSummaryRow.vue";
71
74
 
72
- defineEmits(["update:quasar-pagination", "update:selected-rows"]);
75
+ defineEmits(["update:selected-rows", "update:pagination"]);
73
76
  const props = defineProps({
74
- name: {
75
- type: String,
76
- required: true
77
- },
78
- label: {
79
- type: String,
80
- required: true
81
- },
82
- selectedRows: {
83
- type: Array,
84
- required: true
85
- },
86
- quasarPagination: {
87
- type: Object,
88
- required: true
89
- },
90
- isLoadingList: Boolean,
91
- pagedItems: {
92
- type: Object,
93
- default: null
94
- },
95
- isLoadingSummary: Boolean,
96
- summary: {
97
- type: Object,
98
- default: null
99
- },
100
- columns: {
101
- type: Array,
102
- required: true
103
- },
104
- rowsPerPageOptions: {
105
- type: Array,
106
- default: () => [10, 25, 50, 100]
107
- }
77
+ name: {
78
+ type: String,
79
+ required: true
80
+ },
81
+ label: {
82
+ type: String,
83
+ required: true
84
+ },
85
+ color: {
86
+ type: String,
87
+ default: "blue-600"
88
+ },
89
+ selectedRows: {
90
+ type: Array,
91
+ required: true
92
+ },
93
+ pagination: {
94
+ type: Object,
95
+ required: true
96
+ },
97
+ loadingList: Boolean,
98
+ loadingSummary: Boolean,
99
+ pagedItems: {
100
+ type: Object,
101
+ default: null
102
+ },
103
+ summary: {
104
+ type: Object,
105
+ default: null
106
+ },
107
+ columns: {
108
+ type: Array,
109
+ required: true
110
+ },
111
+ rowsPerPageOptions: {
112
+ type: Array,
113
+ default: () => [10, 25, 50, 100]
114
+ }
108
115
  });
109
116
  const actionTable = ref(null);
110
117
  registerStickyScrolling(actionTable);
111
118
 
119
+ const tableColumns = computed(() => props.columns.map((column) => ({ ...column, field: column.field || column.name })));
120
+ const hasData = computed(() => props.pagedItems?.data?.length);
112
121
  const COLUMN_SETTINGS_KEY = `column-settings-${props.name}`;
113
122
  const columnSettings = ref(getItem(COLUMN_SETTINGS_KEY) || {});
114
123
  function onUpdateColumnSettings() {
115
- setItem(COLUMN_SETTINGS_KEY, columnSettings.value);
124
+ setItem(COLUMN_SETTINGS_KEY, columnSettings.value);
116
125
  }
117
126
  </script>
127
+
128
+ <style scoped lang="scss">
129
+ .dx-action-table {
130
+ &.dx-no-data {
131
+ :deep(.q-table__middle) {
132
+ flex-grow: 0;
133
+ flex-shrink: 1;
134
+ }
135
+ }
136
+ }
137
+ </style>
@@ -44,6 +44,7 @@
44
44
  class="flex flex-shrink-0 pl-2"
45
45
  >
46
46
  <ActionMenu
47
+ class="dx-column-action-menu"
47
48
  :actions="column.actionMenu"
48
49
  :target="row"
49
50
  :loading="isSaving"
@@ -56,9 +57,9 @@
56
57
  <script setup>
57
58
  import { QTd } from "quasar";
58
59
  import { computed } from "vue";
59
- import { RenderVnode } from "../Utility";
60
- import ActionMenu from "./ActionMenu";
61
- import { TitleColumnFormat } from "./Columns";
60
+ import { RenderVnode } from "../../Utility";
61
+ import ActionMenu from "../ActionMenu";
62
+ import { TitleColumnFormat } from "./";
62
63
 
63
64
  const props = defineProps({
64
65
  rowProps: {
@@ -20,8 +20,8 @@
20
20
  <script setup>
21
21
  import { QTh } from "quasar";
22
22
  import { computed } from "vue";
23
- import { DragHandleIcon as RowResizeIcon } from "../../svg";
24
- import { HandleDraggable } from "../DragAndDrop";
23
+ import { DragHandleIcon as RowResizeIcon } from "../../../svg";
24
+ import { HandleDraggable } from "../../DragAndDrop";
25
25
 
26
26
  const emit = defineEmits(["update:model-value"]);
27
27
  const props = defineProps({
@@ -1,3 +1,5 @@
1
+ export { default as ActionTableColumn } from "./ActionTableColumn.vue";
2
+ export { default as ActionTableHeaderColumn } from "./ActionTableHeaderColumn.vue";
1
3
  export { default as ColumnListItem } from "./ColumnListItem.vue";
2
4
  export { default as ColumnSettingsDialog } from "./ColumnSettingsDialog.vue";
3
5
  export { default as TitleColumnFormat } from "./TitleColumnFormat.vue";
@@ -1,37 +1,39 @@
1
1
  <template>
2
2
  <CollapsableSidebar
3
+ class="dx-collapsable-filters-sidebar"
3
4
  :collapse="!showFilters"
4
5
  disabled
5
- min-width="0"
6
- max-width="18rem"
6
+ :min-width="minWidth"
7
+ :max-width="maxWidth"
7
8
  :name="name"
8
9
  @update:collapse="$emit('update:show-filters', !$event)"
9
10
  >
10
11
  <FilterFieldList
11
- :filter="filter"
12
- :filter-fields="filterFields"
13
- @update:filter="$emit('update:filter', $event)"
12
+ :filter="activeFilter"
13
+ :filter-fields="filters"
14
+ @update:filter="$emit('update:active-filter', $event)"
14
15
  />
15
16
  </CollapsableSidebar>
16
17
  </template>
17
- <script setup>
18
+ <script setup lang="ts">
19
+ import { FilterField, ListControlsFilter } from "src/components/ActionTable/listControls";
18
20
  import { FilterFieldList } from ".";
19
21
  import { CollapsableSidebar } from "../../Utility";
20
22
 
21
- defineEmits(["update:filter", "update:show-filters"]);
22
- defineProps({
23
- name: {
24
- type: String,
25
- required: true
26
- },
27
- showFilters: Boolean,
28
- filter: {
29
- type: Object,
30
- default: null
31
- },
32
- filterFields: {
33
- type: Array,
34
- default: () => []
35
- }
23
+ defineEmits(["update:active-filter", "update:show-filters"]);
24
+
25
+ export interface Props {
26
+ name: string,
27
+ showFilters?: boolean,
28
+ activeFilter: ListControlsFilter,
29
+ minWidth?: string,
30
+ maxWidth?: string,
31
+ filters?: FilterField[]
32
+ }
33
+
34
+ withDefaults(defineProps<Props>(), {
35
+ minWidth: "5rem",
36
+ maxWidth: "18rem",
37
+ filters: () => []
36
38
  });
37
39
  </script>
@@ -1,10 +1,7 @@
1
1
  <template>
2
2
  <div>
3
- <div
4
- v-if="label"
5
- class="font-bold text-xs mb-2"
6
- >
7
- {{ label }}
3
+ <div class="mb-2">
4
+ <FieldLabel :label="label" />
8
5
  </div>
9
6
  <template v-if="inline">
10
7
  <QDate
@@ -41,6 +38,7 @@
41
38
  import { CalendarIcon as DateIcon } from "@heroicons/vue/outline";
42
39
  import { computed, ref, watch } from "vue";
43
40
  import { fDate, parseQDate, parseQDateTime } from "../../../../helpers";
41
+ import FieldLabel from "./FieldLabel";
44
42
 
45
43
  const emit = defineEmits(["update:model-value"]);
46
44
  const props = defineProps({
@@ -1,13 +1,14 @@
1
1
  <template>
2
2
  <QInput
3
+ class="dx-number-field max-w-full"
4
+ :class="{'dx-no-prepend-label': hidePrependLabel, 'dx-prepend-label': !hidePrependLabel}"
3
5
  :model-value="numberVal"
4
6
  :data-testid="'number-field-' + fieldOptions.id"
5
7
  :placeholder="fieldOptions.placeholder"
6
8
  outlined
7
9
  dense
8
10
  inputmode="numeric"
9
- :input-class="{[inputClass]: true, 'text-right bg-white': !hidePrependLabel, 'text-right !text-xs text-black font-normal': hidePrependLabel}"
10
- :class="{'no-prepend-icon w-32 max-w-full': hidePrependLabel, 'prepend-label': !hidePrependLabel}"
11
+ :input-class="inputClass"
11
12
  @update:model-value="onInput"
12
13
  >
13
14
  <template #prepend>
@@ -27,33 +28,33 @@ import FieldLabel from "./FieldLabel";
27
28
 
28
29
  const emit = defineEmits(["update:model-value", "update"]);
29
30
  const props = defineProps({
30
- modelValue: {
31
- type: [String, Number],
32
- default: ""
33
- },
34
- precision: {
35
- type: Number,
36
- default: 2
37
- },
38
- label: {
39
- type: String,
40
- default: undefined
41
- },
42
- field: {
43
- type: Object,
44
- default: null
45
- },
46
- inputClass: {
47
- type: String,
48
- default: ""
49
- },
50
- delay: {
51
- type: Number,
52
- default: 1000
53
- },
54
- hidePrependLabel: Boolean,
55
- currency: Boolean,
56
- showName: Boolean
31
+ modelValue: {
32
+ type: [String, Number],
33
+ default: ""
34
+ },
35
+ precision: {
36
+ type: Number,
37
+ default: 2
38
+ },
39
+ label: {
40
+ type: String,
41
+ default: undefined
42
+ },
43
+ field: {
44
+ type: Object,
45
+ default: null
46
+ },
47
+ inputClass: {
48
+ type: [String, Object],
49
+ default: ""
50
+ },
51
+ delay: {
52
+ type: Number,
53
+ default: 1000
54
+ },
55
+ hidePrependLabel: Boolean,
56
+ currency: Boolean,
57
+ showName: Boolean
57
58
  });
58
59
 
59
60
  const numberVal = ref(format(props.modelValue));
@@ -62,46 +63,46 @@ watch(() => props.modelValue, () => numberVal.value = format(props.modelValue));
62
63
  const fieldOptions = computed(() => props.field || { label: props.label || "", placeholder: "", id: "" });
63
64
 
64
65
  function format(number) {
65
- if (!number && number !== 0 && number !== "0") return number;
66
+ if (!number && number !== 0 && number !== "0") return number;
66
67
 
67
- const minimumFractionDigits = Math.min(props.precision, ("" + number).split(".")[1]?.length || 0);
68
- let options = {
69
- minimumFractionDigits
70
- };
68
+ const minimumFractionDigits = Math.min(props.precision, ("" + number).split(".")[1]?.length || 0);
69
+ let options = {
70
+ minimumFractionDigits
71
+ };
71
72
 
72
- if (props.currency) {
73
- options = {
74
- style: "currency",
75
- currency: "USD",
76
- minimumFractionDigits
77
- };
78
- }
79
- return fNumber(number, options);
73
+ if (props.currency) {
74
+ options = {
75
+ style: "currency",
76
+ currency: "USD",
77
+ minimumFractionDigits
78
+ };
79
+ }
80
+ return fNumber(number, options);
80
81
  }
81
82
 
82
83
  const onUpdateDebounced = useDebounceFn((val) => emit("update", val), props.delay);
83
84
 
84
85
  function onInput(value) {
85
- let number = "";
86
+ let number = "";
86
87
 
87
- // Prevent invalid characters
88
- if (value.match(/[^\d.,$]/)) {
89
- const oldVal = numberVal.value;
90
- // XXX: To get QInput to show only the value we want
91
- numberVal.value += " ";
92
- return nextTick(() => numberVal.value = oldVal);
93
- }
88
+ // Prevent invalid characters
89
+ if (value.match(/[^\d.,$]/)) {
90
+ const oldVal = numberVal.value;
91
+ // XXX: To get QInput to show only the value we want
92
+ numberVal.value += " ";
93
+ return nextTick(() => numberVal.value = oldVal);
94
+ }
94
95
 
95
- if (value !== "") {
96
- value = value.replace(/[^\d.]/g, "");
97
- number = Number(value);
98
- numberVal.value = format(number);
99
- }
96
+ if (value !== "") {
97
+ value = value.replace(/[^\d.]/g, "");
98
+ number = Number(value);
99
+ numberVal.value = format(number);
100
+ }
100
101
 
101
- number = number === "" ? undefined : number;
102
- emit("update:model-value", number);
102
+ number = number === "" ? undefined : number;
103
+ emit("update:model-value", number);
103
104
 
104
- // Delay the change event, so we only see the value after the user has finished
105
- onUpdateDebounced(number);
105
+ // Delay the change event, so we only see the value after the user has finished
106
+ onUpdateDebounced(number);
106
107
  }
107
108
  </script>