quasar-ui-danx 0.0.11 → 0.0.12
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.
- package/package.json +6 -1
- package/src/components/ActionTable/ActionTable.vue +49 -41
- package/src/components/ActionTable/BatchActionMenu.vue +20 -20
- package/src/components/ActionTable/EmptyTableState.vue +5 -5
- package/src/components/ActionTable/Filters/CollapsableFiltersSidebar.vue +11 -11
- package/src/components/ActionTable/Filters/FilterGroupItem.vue +7 -7
- package/src/components/ActionTable/Filters/FilterGroupList.vue +29 -29
- package/src/components/ActionTable/Filters/FilterListToggle.vue +15 -15
- package/src/components/ActionTable/Filters/FilterableField.vue +82 -80
- package/src/components/ActionTable/Filters/index.ts +5 -0
- package/src/components/ActionTable/Form/Fields/BooleanField.vue +13 -13
- package/src/components/ActionTable/Form/Fields/ConfirmPasswordField.vue +11 -11
- package/src/components/ActionTable/Form/Fields/DateField.vue +13 -13
- package/src/components/ActionTable/Form/Fields/DateRangeField.vue +25 -25
- package/src/components/ActionTable/Form/Fields/DateTimeField.vue +21 -21
- package/src/components/ActionTable/Form/Fields/DateTimePicker.vue +23 -23
- package/src/components/ActionTable/Form/Fields/FileUploadButton.vue +31 -31
- package/src/components/ActionTable/Form/Fields/InlineDateTimeField.vue +19 -19
- package/src/components/ActionTable/Form/Fields/IntegerField.vue +7 -7
- package/src/components/ActionTable/Form/Fields/LabelValueBlock.vue +22 -0
- package/src/components/ActionTable/Form/Fields/LabeledInput.vue +19 -19
- package/src/components/ActionTable/Form/Fields/MultiFileField.vue +40 -40
- package/src/components/ActionTable/Form/Fields/MultiKeywordField.vue +23 -23
- package/src/components/ActionTable/Form/Fields/NewPasswordField.vue +10 -10
- package/src/components/ActionTable/Form/Fields/NumberField.vue +29 -29
- package/src/components/ActionTable/Form/Fields/NumberRangeField.vue +33 -33
- package/src/components/ActionTable/Form/Fields/SelectDrawer.vue +36 -36
- package/src/components/ActionTable/Form/Fields/SelectField.vue +66 -66
- package/src/components/ActionTable/Form/Fields/SelectWithChildrenField.vue +23 -23
- package/src/components/ActionTable/Form/Fields/SingleFileField.vue +32 -32
- package/src/components/ActionTable/Form/Fields/TextField.vue +36 -36
- package/src/components/ActionTable/Form/Fields/WysiwygField.vue +16 -16
- package/src/components/ActionTable/Form/Fields/index.ts +23 -23
- package/src/components/ActionTable/Form/RenderedForm.vue +27 -25
- package/src/components/ActionTable/Form/index.ts +2 -0
- package/src/components/ActionTable/TableSummaryRow.vue +33 -33
- package/src/components/ActionTable/index.ts +8 -13
- package/src/components/ActionTable/listActions.ts +340 -339
- package/src/components/ActionTable/listHelpers.ts +74 -0
- package/src/components/ActionTable/tableColumns.ts +56 -56
- package/src/components/DragAndDrop/HandleDraggable.vue +29 -29
- package/src/components/DragAndDrop/ListItemDraggable.vue +10 -10
- package/src/components/DragAndDrop/index.ts +0 -1
- package/src/components/DragAndDrop/listDragAndDrop.ts +1 -1
- package/src/components/Utility/CollapsableSidebar.vue +35 -35
- package/src/components/Utility/ContentDrawer.vue +20 -20
- package/src/components/Utility/Dialogs/ConfirmDialog.vue +55 -55
- package/src/components/Utility/Dialogs/FullScreenDialog.vue +18 -18
- package/src/components/Utility/Dialogs/FullscreenCarouselDialog.vue +105 -0
- package/src/components/Utility/Dialogs/InfoDialog.vue +10 -10
- package/src/components/Utility/Dialogs/InputDialog.vue +13 -13
- package/src/components/Utility/ImagePreview.vue +192 -0
- package/src/components/Utility/Popover/PopoverMenu.vue +64 -0
- package/src/components/Utility/Transitions/StaggeredListTransition.vue +15 -15
- package/src/components/Utility/index.ts +11 -9
- package/src/components/index.ts +1 -1
- package/src/helpers/FileUpload.ts +274 -273
- package/src/helpers/compatibility.ts +45 -45
- package/src/helpers/date.ts +2 -2
- package/src/helpers/download.ts +166 -158
- package/src/helpers/downloadPdf.ts +48 -48
- package/src/helpers/files.ts +42 -42
- package/src/helpers/index.ts +2 -0
- package/src/helpers/multiFileUpload.ts +56 -56
- package/src/helpers/singleFileUpload.ts +49 -49
- package/src/index.esm.js +3 -4
- package/src/svg/FilterIcon.svg +7 -0
- package/src/svg/ImageIcon.svg +30 -0
- package/src/svg/PdfIcon.svg +21 -0
- package/src/svg/PercentIcon.svg +13 -0
- package/src/svg/TrashIcon.svg +15 -0
- package/src/svg/XIcon.svg +18 -0
- package/src/svg/index.ts +8 -0
- package/src/vendor/tinymce-config.ts +1 -0
- package/src/vue-plugin.js +7 -4
- package/tsconfig.json +14 -13
- package/src/components/ActionTable/tableHelpers.ts +0 -83
- package/src/components/DragAndDrop/Icons/index.ts +0 -2
- /package/src/{components/DragAndDrop/Icons → svg}/DragHandleDotsIcon.svg +0 -0
- /package/src/{components/DragAndDrop/Icons → svg}/DragHandleIcon.svg +0 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
import { getUrlParam } from "@ui/helpers";
|
2
|
+
import { onMounted, watch } from "vue";
|
3
|
+
|
4
|
+
export function registerStickyScrolling(tableRef) {
|
5
|
+
onMounted(() => {
|
6
|
+
const scrollEl = tableRef.value.$el.getElementsByClassName("q-table__middle")[0];
|
7
|
+
scrollEl.addEventListener("scroll", onScroll);
|
8
|
+
|
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
|
+
}
|
16
|
+
|
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
|
+
});
|
25
|
+
}
|
26
|
+
|
27
|
+
export function mapSortBy(pagination, columns) {
|
28
|
+
if (!pagination.sortBy) return null;
|
29
|
+
|
30
|
+
const column = columns.find(c => c.name === pagination.sortBy);
|
31
|
+
return [
|
32
|
+
{
|
33
|
+
column: column.sortBy || column.name,
|
34
|
+
expression: column.sortByExpression || undefined,
|
35
|
+
order: pagination.descending ? "desc" : "asc"
|
36
|
+
}
|
37
|
+
];
|
38
|
+
}
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Wait for a ref to have a value and then resolve the promise
|
42
|
+
*
|
43
|
+
* @param ref
|
44
|
+
* @param value
|
45
|
+
* @returns {Promise<void>}
|
46
|
+
*/
|
47
|
+
export function waitForRef(ref, value) {
|
48
|
+
return new Promise<void>((resolve) => {
|
49
|
+
watch(ref, (newValue) => {
|
50
|
+
if (newValue === value) {
|
51
|
+
resolve();
|
52
|
+
}
|
53
|
+
});
|
54
|
+
});
|
55
|
+
}
|
56
|
+
|
57
|
+
/**
|
58
|
+
* Returns the filter from the URL if it is set
|
59
|
+
* @param url
|
60
|
+
* @param allowedKeys
|
61
|
+
*/
|
62
|
+
export function getFilterFromUrl(url, allowedKeys = null) {
|
63
|
+
const filter = {};
|
64
|
+
const urlFilter = getUrlParam("filter", url);
|
65
|
+
if (urlFilter) {
|
66
|
+
const fields = JSON.parse(urlFilter);
|
67
|
+
Object.keys(fields).forEach((key) => {
|
68
|
+
if (!allowedKeys || allowedKeys.includes(key)) {
|
69
|
+
filter[key] = fields[key];
|
70
|
+
}
|
71
|
+
});
|
72
|
+
}
|
73
|
+
return filter;
|
74
|
+
}
|
@@ -1,72 +1,72 @@
|
|
1
|
-
import { getItem, setItem } from "
|
1
|
+
import { getItem, setItem } from "@ui/helpers";
|
2
2
|
import { computed, ref, watch } from "vue";
|
3
3
|
|
4
4
|
export function useTableColumns(name, columns, options = { titleMinWidth: 120, titleMaxWidth: 200 }) {
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
const COLUMN_ORDER_KEY = `${name}-column-order`;
|
6
|
+
const VISIBLE_COLUMNS_KEY = `${name}-visible-columns`;
|
7
|
+
const TITLE_COLUMNS_KEY = `${name}-title-columns`;
|
8
|
+
const TITLE_WIDTH_KEY = `${name}-title-width`;
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
// The list that defines the order the columns should appear in
|
11
|
+
const columnOrder = ref(getItem(COLUMN_ORDER_KEY) || []);
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
// Manages visible columns on the table
|
14
|
+
const hiddenColumnNames = ref(getItem(VISIBLE_COLUMNS_KEY, columns.filter(c => c.category !== "General" || c.name === "status").map(c => c.name)));
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
// Title columns will have their name appear on the first column of the table as part of the records' title
|
17
|
+
const titleColumnNames = ref(getItem(TITLE_COLUMNS_KEY, []));
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
// The width of the title column
|
20
|
+
const titleWidth = ref(getItem(TITLE_WIDTH_KEY, options.titleMinWidth));
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
/**
|
23
|
+
* When the title column is resized, update the titleWidth
|
24
|
+
* @param val
|
25
|
+
*/
|
26
|
+
function onResizeTitleColumn(val) {
|
27
|
+
titleWidth.value = Math.max(Math.min(val.distance + val.startDropZoneSize, options.titleMaxWidth), options.titleMinWidth);
|
28
|
+
}
|
29
29
|
|
30
|
-
|
31
|
-
|
30
|
+
// Columns that should be locked to the left side of the table
|
31
|
+
const lockedColumns = computed(() => orderedColumns.value.slice(0, 1));
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
33
|
+
// The resolved list of columns in the order they should appear in
|
34
|
+
const orderedColumns = computed(() => [...columns].sort((a, b) => {
|
35
|
+
const aIndex = columnOrder.value.indexOf(a.name);
|
36
|
+
const bIndex = columnOrder.value.indexOf(b.name);
|
37
|
+
return aIndex === -1 ? 1 : bIndex === -1 ? -1 : aIndex - bIndex;
|
38
|
+
}));
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
40
|
+
// The ordered list of columns. The ordering of this list is editable and will be stored in localStorage
|
41
|
+
const sortableColumns = computed({
|
42
|
+
get() {
|
43
|
+
return orderedColumns.value.slice(1);
|
44
|
+
},
|
45
|
+
set(newColumns) {
|
46
|
+
columnOrder.value = [...lockedColumns.value.map(c => c.name), ...newColumns.map(c => c.name)];
|
47
|
+
setItem(COLUMN_ORDER_KEY, columnOrder.value);
|
48
|
+
}
|
49
|
+
});
|
50
50
|
|
51
|
-
|
52
|
-
|
51
|
+
// The list of columns that are visible. To edit the visible columns, edit the hiddenColumnNames list
|
52
|
+
const visibleColumns = computed(() => orderedColumns.value.filter(c => !hiddenColumnNames.value.includes(c.name)));
|
53
53
|
|
54
|
-
|
55
|
-
|
54
|
+
// The list of columns that should be included in the title of a row
|
55
|
+
const orderedTitleColumns = computed(() => orderedColumns.value.filter(c => titleColumnNames.value.includes(c.name)));
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
57
|
+
// Save changes to the list of hidden columns in localStorage
|
58
|
+
watch(() => hiddenColumnNames.value, () => setItem(VISIBLE_COLUMNS_KEY, hiddenColumnNames.value));
|
59
|
+
watch(() => titleColumnNames.value, () => setItem(TITLE_COLUMNS_KEY, titleColumnNames.value));
|
60
|
+
watch(() => titleWidth.value, () => setItem(TITLE_WIDTH_KEY, titleWidth.value));
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
62
|
+
return {
|
63
|
+
sortableColumns,
|
64
|
+
lockedColumns,
|
65
|
+
visibleColumns,
|
66
|
+
hiddenColumnNames,
|
67
|
+
titleColumnNames,
|
68
|
+
titleWidth,
|
69
|
+
orderedTitleColumns,
|
70
|
+
onResizeTitleColumn
|
71
|
+
};
|
72
72
|
}
|
@@ -1,53 +1,53 @@
|
|
1
1
|
<template>
|
2
2
|
<div
|
3
|
-
|
3
|
+
:class="{
|
4
4
|
'cursor-ew-resize': direction === 'horizontal',
|
5
5
|
'cursor-ns-resize': direction === 'vertical',
|
6
6
|
}"
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
class="flex justify-center items-center w-full h-full"
|
8
|
+
draggable="true"
|
9
|
+
@dragstart="dragAndDrop.dragStart"
|
10
|
+
@dragend="dragAndDrop.dragEnd"
|
11
11
|
>
|
12
12
|
<slot />
|
13
13
|
</div>
|
14
14
|
</template>
|
15
15
|
<script setup>
|
16
|
-
import {
|
17
|
-
import {
|
16
|
+
import { DragAndDrop } from '@ui/components';
|
17
|
+
import { useDebounceFn } from '@vueuse/core';
|
18
18
|
|
19
|
-
const emit = defineEmits([
|
19
|
+
const emit = defineEmits(['start', 'end', 'resize']);
|
20
20
|
const props = defineProps({
|
21
21
|
initialValue: {
|
22
22
|
type: Number,
|
23
|
-
default: null
|
23
|
+
default: null
|
24
24
|
},
|
25
25
|
dropZone: {
|
26
26
|
type: [Function, String],
|
27
|
-
required: true
|
27
|
+
required: true
|
28
28
|
},
|
29
29
|
direction: {
|
30
30
|
type: String,
|
31
|
-
default:
|
32
|
-
validator: (value) => [
|
33
|
-
}
|
31
|
+
default: 'horizontal',
|
32
|
+
validator: (value) => ['vertical', 'horizontal'].includes(value)
|
33
|
+
}
|
34
34
|
});
|
35
35
|
|
36
36
|
const dragAndDrop = new DragAndDrop()
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
37
|
+
.setDropZone(props.dropZone)
|
38
|
+
.setOptions({
|
39
|
+
showPlaceholder: true,
|
40
|
+
direction: props.direction,
|
41
|
+
hideDragImage: true
|
42
|
+
})
|
43
|
+
.onDragging(useDebounceFn(() => {
|
44
|
+
emit('resize', {
|
45
|
+
distance: dragAndDrop.getDistance(),
|
46
|
+
percent: dragAndDrop.getPercentChange(),
|
47
|
+
startDropZoneSize: dragAndDrop.startSize,
|
48
|
+
dropZoneSize: dragAndDrop.getDropZoneSize()
|
49
|
+
});
|
50
|
+
}, 20, { maxWait: 30 }))
|
51
|
+
.onStart(() => emit('start'))
|
52
|
+
.onEnd(() => emit('end'));
|
53
53
|
</script>
|
@@ -16,25 +16,25 @@
|
|
16
16
|
</div>
|
17
17
|
</template>
|
18
18
|
<script setup>
|
19
|
-
import
|
20
|
-
import {
|
21
|
-
import
|
19
|
+
import { ListDragAndDrop } from '@ui/components';
|
20
|
+
import { DragHandleDotsIcon as DragHandleIcon } from '@ui/svg';
|
21
|
+
import SvgImg from '../Utility/SvgImg';
|
22
22
|
|
23
|
-
const emit = defineEmits([
|
23
|
+
const emit = defineEmits(['position', 'update:list-items']);
|
24
24
|
const props = defineProps({
|
25
25
|
dropZone: {
|
26
26
|
type: [Function, String],
|
27
|
-
required: true
|
27
|
+
required: true
|
28
28
|
},
|
29
29
|
direction: {
|
30
30
|
type: String,
|
31
|
-
default:
|
32
|
-
validator: (value) => [
|
31
|
+
default: 'vertical',
|
32
|
+
validator: (value) => ['vertical', 'horizontal'].includes(value)
|
33
33
|
},
|
34
34
|
showHandle: Boolean,
|
35
35
|
listItems: {
|
36
36
|
type: Array,
|
37
|
-
default: null
|
37
|
+
default: null
|
38
38
|
}
|
39
39
|
});
|
40
40
|
|
@@ -42,12 +42,12 @@ const dragAndDrop = new ListDragAndDrop()
|
|
42
42
|
.setDropZone(props.dropZone)
|
43
43
|
.setOptions({ showPlaceholder: true, direction: props.direction })
|
44
44
|
.onPositionChange((newPosition, oldPosition) => {
|
45
|
-
emit(
|
45
|
+
emit('position', newPosition);
|
46
46
|
|
47
47
|
if (props.listItems) {
|
48
48
|
const items = [...props.listItems];
|
49
49
|
items.splice(newPosition, 0, items.splice(oldPosition, 1)[0]);
|
50
|
-
emit(
|
50
|
+
emit('update:list-items', items);
|
51
51
|
}
|
52
52
|
});
|
53
53
|
</script>
|
@@ -1,102 +1,102 @@
|
|
1
1
|
<template>
|
2
2
|
<div
|
3
|
-
|
4
|
-
|
3
|
+
class="collapsable-sidebar overflow-x-hidden overflow-y-scroll relative"
|
4
|
+
:class="{
|
5
5
|
'is-collapsed': isCollapsed,
|
6
6
|
'is-right-side': rightSide,
|
7
7
|
[displayClass]: true,
|
8
8
|
}"
|
9
|
-
|
9
|
+
:style="style"
|
10
10
|
>
|
11
11
|
<div class="flex-grow max-w-full">
|
12
12
|
<slot :is-collapsed="isCollapsed" />
|
13
13
|
</div>
|
14
14
|
<template v-if="!disabled && (!hideToggleOnCollapse || !isCollapsed)">
|
15
15
|
<div
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
v-if="!toggleAtTop"
|
17
|
+
class="flex w-full p-4"
|
18
|
+
:class="rightSide ? 'justify-start' : 'justify-end'"
|
19
19
|
>
|
20
20
|
<slot name="toggle">
|
21
|
-
<
|
22
|
-
|
23
|
-
|
21
|
+
<q-btn
|
22
|
+
class="btn-secondary"
|
23
|
+
@click="toggleCollapse"
|
24
24
|
>
|
25
25
|
<ToggleIcon
|
26
|
-
|
27
|
-
|
26
|
+
class="w-5 transition-all"
|
27
|
+
:class="{ 'rotate-180': rightSide ? !isCollapsed : isCollapsed }"
|
28
28
|
/>
|
29
|
-
</
|
29
|
+
</q-btn>
|
30
30
|
</slot>
|
31
31
|
</div>
|
32
32
|
<div
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
v-else
|
34
|
+
class="absolute top-0 right-0 cursor-pointer p-2"
|
35
|
+
:class="toggleClass"
|
36
|
+
@click="toggleCollapse"
|
37
37
|
>
|
38
38
|
<ToggleIcon
|
39
|
-
|
40
|
-
|
39
|
+
class="w-5 transition-all"
|
40
|
+
:class="{ 'rotate-180': rightSide ? !isCollapsed : isCollapsed }"
|
41
41
|
/>
|
42
42
|
</div>
|
43
43
|
</template>
|
44
44
|
</div>
|
45
45
|
</template>
|
46
46
|
<script setup>
|
47
|
-
import { ChevronLeftIcon as ToggleIcon } from
|
48
|
-
import { computed, onMounted, ref, watch } from
|
47
|
+
import { ChevronLeftIcon as ToggleIcon } from '@heroicons/vue/outline';
|
48
|
+
import { computed, onMounted, ref, watch } from 'vue';
|
49
49
|
|
50
|
-
const emit = defineEmits([
|
50
|
+
const emit = defineEmits(['collapse', 'update:collapse']);
|
51
51
|
const props = defineProps({
|
52
52
|
rightSide: Boolean,
|
53
53
|
displayClass: {
|
54
54
|
type: String,
|
55
|
-
default:
|
55
|
+
default: 'flex flex-col'
|
56
56
|
},
|
57
57
|
maxWidth: {
|
58
58
|
type: String,
|
59
|
-
default:
|
59
|
+
default: '13.5rem'
|
60
60
|
},
|
61
61
|
minWidth: {
|
62
62
|
type: String,
|
63
|
-
default:
|
63
|
+
default: '5.5rem'
|
64
64
|
},
|
65
65
|
disabled: Boolean,
|
66
66
|
collapse: Boolean,
|
67
67
|
name: {
|
68
68
|
type: String,
|
69
|
-
default:
|
69
|
+
default: 'sidebar'
|
70
70
|
},
|
71
71
|
toggleAtTop: Boolean,
|
72
72
|
toggleClass: {
|
73
73
|
type: String,
|
74
|
-
default:
|
74
|
+
default: ''
|
75
75
|
},
|
76
76
|
hideToggleOnCollapse: Boolean
|
77
77
|
});
|
78
78
|
|
79
79
|
const isCollapsed = ref(props.collapse);
|
80
80
|
|
81
|
-
const stored = localStorage.getItem(props.name +
|
81
|
+
const stored = localStorage.getItem(props.name + '-is-collapsed');
|
82
82
|
|
83
83
|
if (stored !== null) {
|
84
|
-
isCollapsed.value = stored ===
|
84
|
+
isCollapsed.value = stored === '1';
|
85
85
|
}
|
86
86
|
function toggleCollapse() {
|
87
87
|
setCollapse(!isCollapsed.value);
|
88
|
-
emit(
|
89
|
-
emit(
|
88
|
+
emit('collapse', isCollapsed.value);
|
89
|
+
emit('update:collapse', isCollapsed.value);
|
90
90
|
}
|
91
91
|
|
92
92
|
function setCollapse(state) {
|
93
93
|
isCollapsed.value = state;
|
94
|
-
localStorage.setItem(props.name +
|
94
|
+
localStorage.setItem(props.name + '-is-collapsed', isCollapsed.value ? '1' : '');
|
95
95
|
}
|
96
96
|
|
97
97
|
onMounted(() => {
|
98
|
-
emit(
|
99
|
-
emit(
|
98
|
+
emit('collapse', isCollapsed.value);
|
99
|
+
emit('update:collapse', isCollapsed.value);
|
100
100
|
});
|
101
101
|
const style = computed(() => {
|
102
102
|
return {
|
@@ -110,8 +110,8 @@ watch(() => props.collapse, () => {
|
|
110
110
|
</script>
|
111
111
|
|
112
112
|
<style
|
113
|
-
|
114
|
-
|
113
|
+
scoped
|
114
|
+
lang="scss"
|
115
115
|
>
|
116
116
|
.collapsable-sidebar {
|
117
117
|
@apply overflow-y-auto scroll-smooth flex-shrink-0 border-r border-neutral-plus-5 transition-all;
|
@@ -1,33 +1,33 @@
|
|
1
1
|
<template>
|
2
|
-
<
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
<q-dialog
|
3
|
+
v-model="isShowing"
|
4
|
+
maximized
|
5
|
+
:position="position"
|
6
|
+
:seamless="seamless"
|
7
|
+
:class="{'hide-backdrop': !overlay}"
|
8
8
|
>
|
9
9
|
<div>
|
10
10
|
<div
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
v-if="title"
|
12
|
+
class="dialog-title"
|
13
|
+
@click.stop.prevent
|
14
14
|
>
|
15
15
|
{{ title }}
|
16
16
|
</div>
|
17
17
|
<div
|
18
|
-
|
19
|
-
|
18
|
+
class="dialog-content bg-white"
|
19
|
+
:class="{ [contentClass]: true }"
|
20
20
|
>
|
21
21
|
<slot />
|
22
22
|
</div>
|
23
23
|
</div>
|
24
|
-
|
24
|
+
</q-dialog>
|
25
25
|
</template>
|
26
26
|
|
27
27
|
<script setup>
|
28
|
-
import { computed } from
|
28
|
+
import { computed } from 'vue';
|
29
29
|
|
30
|
-
const emit = defineEmits([
|
30
|
+
const emit = defineEmits(['update:show']);
|
31
31
|
|
32
32
|
const props = defineProps({
|
33
33
|
show: Boolean,
|
@@ -35,27 +35,27 @@ const props = defineProps({
|
|
35
35
|
overlay: Boolean,
|
36
36
|
position: {
|
37
37
|
type: String,
|
38
|
-
default:
|
38
|
+
default: 'bottom'
|
39
39
|
},
|
40
40
|
contentClass: {
|
41
41
|
type: String,
|
42
|
-
default:
|
42
|
+
default: 'py-8 px-12'
|
43
43
|
},
|
44
44
|
title: {
|
45
45
|
type: String,
|
46
|
-
default:
|
46
|
+
default: 'Edit'
|
47
47
|
}
|
48
48
|
});
|
49
49
|
|
50
50
|
const isShowing = computed({
|
51
51
|
get: () => props.show,
|
52
|
-
set: (value) => emit(
|
52
|
+
set: (value) => emit('update:show', value)
|
53
53
|
});
|
54
54
|
</script>
|
55
55
|
|
56
56
|
<style
|
57
|
-
|
58
|
-
|
57
|
+
lang="scss"
|
58
|
+
scoped
|
59
59
|
>
|
60
60
|
.dialog-title {
|
61
61
|
@apply bg-gray-very-light text-gray-default font-medium uppercase text-xs px-6 py-3 border-b border-neutral-plus-5 rounded-t-md;
|