@inriver/inri 1.13.0 → 1.15.0
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/.changeset/README.md +8 -0
- package/.changeset/config.json +11 -0
- package/.eslintrc.js +5 -5
- package/azure/pipelines/single-build-release.yml +6 -0
- package/azure/pipelines/templates/deployFramework.yml +50 -0
- package/componentProperties.d.ts +8 -8
- package/configs/base-eslint-config.js +36 -36
- package/configs/base-tailwind-config.js +149 -149
- package/i18n.ts +11 -11
- package/index.ts +29 -29
- package/package.json +7 -2
- package/src/components/CAutoBreadcrumbs.vue +72 -72
- package/src/components/CBtn.vue +98 -98
- package/src/components/CColorPicker.vue +55 -55
- package/src/components/CContextMenu.vue +29 -29
- package/src/components/CDatePicker.vue +51 -51
- package/src/components/CDeleteTileBtn.vue +52 -52
- package/src/components/CDialog.vue +253 -253
- package/src/components/CDialogCloseBtn.vue +9 -9
- package/src/components/CDirtyCheck.vue +68 -68
- package/src/components/CDrawer.vue +44 -44
- package/src/components/CDrawerButton.vue +91 -91
- package/src/components/CExpansionItem.vue +57 -57
- package/src/components/CExpansionItemWithCheckbox.vue +41 -41
- package/src/components/CFileDropzone.vue +114 -114
- package/src/components/CGrid.vue +101 -101
- package/src/components/CHeader.vue +10 -10
- package/src/components/CHeaderLinks.vue +61 -61
- package/src/components/CHeaderMenuLink.vue +51 -51
- package/src/components/CHeaderSearch.vue +142 -142
- package/src/components/CIconBtn.vue +70 -70
- package/src/components/CMenuItem.vue +66 -66
- package/src/components/CPageContainer.vue +11 -11
- package/src/components/CPageError.vue +24 -24
- package/src/components/CPageSpinner.vue +18 -18
- package/src/components/CSearch.vue +45 -45
- package/src/components/CSection.vue +29 -29
- package/src/components/CSectionTitle.vue +8 -8
- package/src/components/CSelect.vue +208 -208
- package/src/components/CSlideEffect.vue +62 -62
- package/src/components/CSpinner.vue +107 -107
- package/src/components/CTableActions.vue +16 -16
- package/src/components/CTileBtn.vue +178 -178
- package/src/components/CTimePicker.vue +42 -42
- package/src/components/CToggleGridView.vue +26 -26
- package/src/components/CToggleSidebarBtn.vue +19 -19
- package/src/components/CTooltip.vue +44 -44
- package/src/components/CTreeNode.vue +39 -39
- package/src/components/cards/CBannerCard.vue +103 -103
- package/src/components/cards/CSmallCard.vue +149 -149
- package/src/components/internal-components/ConfirmDialog.vue +78 -78
- package/src/composables/useDialog.ts +46 -46
- package/src/composables/useDirtyCheck.ts +25 -25
- package/src/composables/useDoubleClickListener.ts +28 -28
- package/src/composables/useSelectable.ts +62 -62
- package/src/composables/useTruncateChips.ts +46 -46
- package/src/i18n/de/index.ts +17 -17
- package/src/i18n/en/index.ts +84 -84
- package/src/i18n/es/index.ts +7 -7
- package/src/i18n/fr/index.ts +7 -7
- package/src/init/initInriFramework.ts +37 -37
- package/src/init/useInriApp.ts +55 -55
- package/src/layouts/CLayoutBlank.vue +7 -7
- package/src/layouts/CLayoutWithBackButton.vue +50 -50
- package/src/layouts/CLayoutWithSidebars.vue +46 -46
- package/src/layouts/layout-fragments/CPageAutoBreadcrumbs.vue +6 -6
- package/src/layouts/layout-fragments/CPageBackButton.vue +18 -18
- package/src/layouts/layout-fragments/CPageBlank.vue +20 -20
- package/src/layouts/layout-fragments/CPageFlexCol.vue +5 -5
- package/src/layouts/layout-fragments/CPageLeftSidebar.vue +5 -5
- package/src/layouts/layout-fragments/CPageMainContent.vue +5 -5
- package/src/layouts/layout-fragments/CPageOuterWrapper.vue +5 -5
- package/src/layouts/layout-fragments/CPageRightSidebar.vue +5 -5
- package/src/layouts/layout-fragments/CPageTitle.vue +34 -34
- package/src/plugins/dialog.ts +45 -45
- package/src/plugins/errors/ErrorFactories.ts +59 -59
- package/src/plugins/errors/Errors.ts +156 -156
- package/src/plugins/errors/Exception.ts +6 -6
- package/src/plugins/errors/globalErrorHandler.ts +21 -21
- package/src/plugins/errors/handleError.ts +34 -34
- package/src/plugins/errors/logger.ts +16 -16
- package/src/plugins/errors/vueErrorHandler.ts +26 -26
- package/src/plugins/globalAppConfig.ts +25 -25
- package/src/plugins/i18n.ts +46 -46
- package/src/plugins/inriIcons.ts +58 -58
- package/src/plugins/inriverQuasarComponentConfigurations.ts +67 -67
- package/src/plugins/library.ts +119 -119
- package/src/plugins/notify.ts +153 -153
- package/src/plugins/quasar-user-options.ts +19 -19
- package/src/plugins/validationRules.ts +292 -292
- package/src/shims-vue.d.ts +6 -6
- package/src/stores/inriStore.ts +54 -54
- package/src/stores/interfaceLanguageStore.ts +27 -27
- package/src/styles/_css-variables.scss +101 -101
- package/src/styles/_reset.scss +67 -67
- package/src/styles/_transitions.scss +9 -9
- package/src/styles/_utils.scss +15 -15
- package/src/styles/components/_breadcrumbs.scss +3 -3
- package/src/styles/components/_checkboxes.scss +17 -17
- package/src/styles/components/_chips.scss +17 -17
- package/src/styles/components/_forms.scss +203 -203
- package/src/styles/components/_menu.scss +12 -12
- package/src/styles/components/_notifications.scss +24 -24
- package/src/styles/components/_q-editor.scss +14 -14
- package/src/styles/components/_radio-buttons.scss +17 -17
- package/src/styles/components/_tables.scss +92 -92
- package/src/styles/components/_tooltips.scss +5 -5
- package/src/styles/components/_tree.scss +86 -86
- package/src/styles/components/_truncated-chips.scss +39 -39
- package/src/styles/main.scss +45 -45
- package/src/styles/quasar.variables.scss +50 -50
- package/src/styles/tailwind/index.css +2 -2
- package/src/typings.d.ts +70 -70
- package/src/utils/colorUtils.ts +73 -73
- package/src/utils/errorUtils.ts +37 -37
- package/src/utils/fileUtils.ts +57 -57
- package/src/utils/helpers.ts +6 -6
- package/src/utils/routeUtils.ts +23 -23
- package/tsconfig.json +34 -34
|
@@ -1,114 +1,114 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div
|
|
3
|
-
v-show="isDragging"
|
|
4
|
-
:style="`height: ${height}; width: ${width}`"
|
|
5
|
-
:class="[
|
|
6
|
-
'absolute',
|
|
7
|
-
'inset-x-0',
|
|
8
|
-
'z-10',
|
|
9
|
-
isDragging && 'border-2 border-solid border-green bg-green-light-30',
|
|
10
|
-
]"
|
|
11
|
-
@drop.prevent="handleDrop"
|
|
12
|
-
>
|
|
13
|
-
<div class="relative w-full h-full flex justify-center items-end p-8">
|
|
14
|
-
<div class="absolute flex items-center rounded bg-grey-darkest text-white px-5 py-4">
|
|
15
|
-
<q-icon
|
|
16
|
-
name="mdi-download-outline"
|
|
17
|
-
class="mr-5 rotate-180"
|
|
18
|
-
size="24px"
|
|
19
|
-
/>
|
|
20
|
-
<i18n-t
|
|
21
|
-
v-if="hintLabel"
|
|
22
|
-
keypath="inri.dropzone.hint"
|
|
23
|
-
tag="span"
|
|
24
|
-
scope="global"
|
|
25
|
-
>
|
|
26
|
-
<b>{{ hintLabel }}</b>
|
|
27
|
-
</i18n-t>
|
|
28
|
-
<span v-else>{{ $t('inri.dropzone.hint_general') }}</span>
|
|
29
|
-
</div>
|
|
30
|
-
</div>
|
|
31
|
-
</div>
|
|
32
|
-
</template>
|
|
33
|
-
|
|
34
|
-
<script setup lang="ts">
|
|
35
|
-
import { ref, onMounted, onUnmounted } from 'vue'
|
|
36
|
-
import { useI18n } from 'vue-i18n'
|
|
37
|
-
import notify from '../plugins/notify'
|
|
38
|
-
|
|
39
|
-
const { t } = useI18n()
|
|
40
|
-
|
|
41
|
-
defineProps({
|
|
42
|
-
hintLabel: {
|
|
43
|
-
type: String,
|
|
44
|
-
default: '',
|
|
45
|
-
},
|
|
46
|
-
height: {
|
|
47
|
-
type: String,
|
|
48
|
-
default: '100%',
|
|
49
|
-
},
|
|
50
|
-
width: {
|
|
51
|
-
type: String,
|
|
52
|
-
default: '100%',
|
|
53
|
-
},
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
const emit = defineEmits(['files-dropped'])
|
|
57
|
-
|
|
58
|
-
const isDragging = ref(false)
|
|
59
|
-
let isDraggingTimeout: ReturnType<typeof setTimeout>
|
|
60
|
-
|
|
61
|
-
function setDraggingTimeout () {
|
|
62
|
-
isDraggingTimeout = setTimeout(() => {
|
|
63
|
-
isDragging.value = false
|
|
64
|
-
}, 50)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function isFileDrag (e: DragEvent) {
|
|
68
|
-
return e.dataTransfer?.items.length && e.dataTransfer?.items[0].kind === 'file'
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function handleDragEnter (e) {
|
|
72
|
-
if (isFileDrag(e)) {
|
|
73
|
-
isDragging.value = true
|
|
74
|
-
clearTimeout(isDraggingTimeout)
|
|
75
|
-
e.preventDefault()
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function handleDragOver (e) {
|
|
80
|
-
if (isFileDrag(e)) {
|
|
81
|
-
isDragging.value = true
|
|
82
|
-
clearTimeout(isDraggingTimeout)
|
|
83
|
-
e.preventDefault()
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function handleDragLeave (e) {
|
|
88
|
-
setDraggingTimeout()
|
|
89
|
-
e.preventDefault()
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
onMounted(() => {
|
|
93
|
-
document.body.addEventListener('dragenter', handleDragEnter, false)
|
|
94
|
-
document.body.addEventListener('dragover', handleDragOver, false)
|
|
95
|
-
document.body.addEventListener('dragleave', handleDragLeave, false)
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
onUnmounted(() => {
|
|
99
|
-
document.body.removeEventListener('dragenter', handleDragEnter, false)
|
|
100
|
-
document.body.removeEventListener('dragover', handleDragOver, false)
|
|
101
|
-
document.body.removeEventListener('dragleave', handleDragLeave, false)
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
function handleDrop (e) {
|
|
105
|
-
setDraggingTimeout()
|
|
106
|
-
|
|
107
|
-
if (!e.dataTransfer.files) {
|
|
108
|
-
notify.error(t('dropzone.invalid_drop_items'))
|
|
109
|
-
return
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
emit('files-dropped', [...e.dataTransfer.files])
|
|
113
|
-
}
|
|
114
|
-
</script>
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
v-show="isDragging"
|
|
4
|
+
:style="`height: ${height}; width: ${width}`"
|
|
5
|
+
:class="[
|
|
6
|
+
'absolute',
|
|
7
|
+
'inset-x-0',
|
|
8
|
+
'z-10',
|
|
9
|
+
isDragging && 'border-2 border-solid border-green bg-green-light-30',
|
|
10
|
+
]"
|
|
11
|
+
@drop.prevent="handleDrop"
|
|
12
|
+
>
|
|
13
|
+
<div class="relative w-full h-full flex justify-center items-end p-8">
|
|
14
|
+
<div class="absolute flex items-center rounded bg-grey-darkest text-white px-5 py-4">
|
|
15
|
+
<q-icon
|
|
16
|
+
name="mdi-download-outline"
|
|
17
|
+
class="mr-5 rotate-180"
|
|
18
|
+
size="24px"
|
|
19
|
+
/>
|
|
20
|
+
<i18n-t
|
|
21
|
+
v-if="hintLabel"
|
|
22
|
+
keypath="inri.dropzone.hint"
|
|
23
|
+
tag="span"
|
|
24
|
+
scope="global"
|
|
25
|
+
>
|
|
26
|
+
<b>{{ hintLabel }}</b>
|
|
27
|
+
</i18n-t>
|
|
28
|
+
<span v-else>{{ $t('inri.dropzone.hint_general') }}</span>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</template>
|
|
33
|
+
|
|
34
|
+
<script setup lang="ts">
|
|
35
|
+
import { ref, onMounted, onUnmounted } from 'vue'
|
|
36
|
+
import { useI18n } from 'vue-i18n'
|
|
37
|
+
import notify from '../plugins/notify'
|
|
38
|
+
|
|
39
|
+
const { t } = useI18n()
|
|
40
|
+
|
|
41
|
+
defineProps({
|
|
42
|
+
hintLabel: {
|
|
43
|
+
type: String,
|
|
44
|
+
default: '',
|
|
45
|
+
},
|
|
46
|
+
height: {
|
|
47
|
+
type: String,
|
|
48
|
+
default: '100%',
|
|
49
|
+
},
|
|
50
|
+
width: {
|
|
51
|
+
type: String,
|
|
52
|
+
default: '100%',
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const emit = defineEmits(['files-dropped'])
|
|
57
|
+
|
|
58
|
+
const isDragging = ref(false)
|
|
59
|
+
let isDraggingTimeout: ReturnType<typeof setTimeout>
|
|
60
|
+
|
|
61
|
+
function setDraggingTimeout () {
|
|
62
|
+
isDraggingTimeout = setTimeout(() => {
|
|
63
|
+
isDragging.value = false
|
|
64
|
+
}, 50)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function isFileDrag (e: DragEvent) {
|
|
68
|
+
return e.dataTransfer?.items.length && e.dataTransfer?.items[0].kind === 'file'
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function handleDragEnter (e) {
|
|
72
|
+
if (isFileDrag(e)) {
|
|
73
|
+
isDragging.value = true
|
|
74
|
+
clearTimeout(isDraggingTimeout)
|
|
75
|
+
e.preventDefault()
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function handleDragOver (e) {
|
|
80
|
+
if (isFileDrag(e)) {
|
|
81
|
+
isDragging.value = true
|
|
82
|
+
clearTimeout(isDraggingTimeout)
|
|
83
|
+
e.preventDefault()
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function handleDragLeave (e) {
|
|
88
|
+
setDraggingTimeout()
|
|
89
|
+
e.preventDefault()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
onMounted(() => {
|
|
93
|
+
document.body.addEventListener('dragenter', handleDragEnter, false)
|
|
94
|
+
document.body.addEventListener('dragover', handleDragOver, false)
|
|
95
|
+
document.body.addEventListener('dragleave', handleDragLeave, false)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
onUnmounted(() => {
|
|
99
|
+
document.body.removeEventListener('dragenter', handleDragEnter, false)
|
|
100
|
+
document.body.removeEventListener('dragover', handleDragOver, false)
|
|
101
|
+
document.body.removeEventListener('dragleave', handleDragLeave, false)
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
function handleDrop (e) {
|
|
105
|
+
setDraggingTimeout()
|
|
106
|
+
|
|
107
|
+
if (!e.dataTransfer.files) {
|
|
108
|
+
notify.error(t('dropzone.invalid_drop_items'))
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
emit('files-dropped', [...e.dataTransfer.files])
|
|
113
|
+
}
|
|
114
|
+
</script>
|
package/src/components/CGrid.vue
CHANGED
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div
|
|
3
|
-
class="grid"
|
|
4
|
-
:style="{
|
|
5
|
-
columnGap: `${colGap}px`,
|
|
6
|
-
rowGap: `${rowGap}px`,
|
|
7
|
-
gridTemplateColumns: computedColumns,
|
|
8
|
-
gridTemplateRows: computedRows,
|
|
9
|
-
}"
|
|
10
|
-
>
|
|
11
|
-
<slot />
|
|
12
|
-
</div>
|
|
13
|
-
</template>
|
|
14
|
-
|
|
15
|
-
<script setup lang="ts">
|
|
16
|
-
import { computed } from 'vue'
|
|
17
|
-
import { useQuasar } from 'quasar'
|
|
18
|
-
|
|
19
|
-
const $q = useQuasar()
|
|
20
|
-
|
|
21
|
-
const props = defineProps({
|
|
22
|
-
cols: {
|
|
23
|
-
type: [String, Number, Object],
|
|
24
|
-
default: undefined,
|
|
25
|
-
},
|
|
26
|
-
rows: {
|
|
27
|
-
type: [String, Number, Object],
|
|
28
|
-
default: undefined,
|
|
29
|
-
},
|
|
30
|
-
colGap: {
|
|
31
|
-
type: [Number, String],
|
|
32
|
-
default: 24,
|
|
33
|
-
},
|
|
34
|
-
rowGap: {
|
|
35
|
-
type: [Number, String],
|
|
36
|
-
default: 24,
|
|
37
|
-
},
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
// Computed
|
|
41
|
-
const computedColumns = computed(() => {
|
|
42
|
-
if (typeof props.cols === 'object') {
|
|
43
|
-
if ($q.screen.xl && props.cols.xl) {
|
|
44
|
-
return generateColumnsTemplate(props.cols.xl)
|
|
45
|
-
} if ($q.screen.gt.md && props.cols.lg) {
|
|
46
|
-
return generateColumnsTemplate(props.cols.lg)
|
|
47
|
-
} else if ($q.screen.gt.sm && props.cols.md) {
|
|
48
|
-
return generateColumnsTemplate(props.cols.md)
|
|
49
|
-
} else if ($q.screen.gt.xs && props.cols.sm) {
|
|
50
|
-
return generateColumnsTemplate(props.cols.sm)
|
|
51
|
-
} else if (props.cols.xs) {
|
|
52
|
-
return generateColumnsTemplate(props.cols.xs)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return null
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return generateColumnsTemplate(props.cols)
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
const computedRows = computed(() => {
|
|
62
|
-
if (typeof props.rows === 'object') {
|
|
63
|
-
if ($q.screen.xl && props.rows.xl) {
|
|
64
|
-
return generateRowsTemplate(props.rows.xl)
|
|
65
|
-
} if ($q.screen.gt.md && props.rows.lg) {
|
|
66
|
-
return generateRowsTemplate(props.rows.lg)
|
|
67
|
-
} else if ($q.screen.gt.sm && props.rows.md) {
|
|
68
|
-
return generateRowsTemplate(props.rows.md)
|
|
69
|
-
} else if ($q.screen.gt.xs && props.rows.sm) {
|
|
70
|
-
return generateRowsTemplate(props.rows.sm)
|
|
71
|
-
} else if (props.rows.xs) {
|
|
72
|
-
return generateRowsTemplate(props.rows.xs)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return null
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return generateRowsTemplate(props.rows)
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
// Methods
|
|
82
|
-
function isNumeric (num) {
|
|
83
|
-
return !isNaN(num)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function generateColumnsTemplate (template) {
|
|
87
|
-
if (isNumeric(template)) {
|
|
88
|
-
return `repeat(${template}, minmax(0, 1fr))`
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return template
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function generateRowsTemplate (template) {
|
|
95
|
-
if (isNumeric(template)) {
|
|
96
|
-
return `repeat(${template}, minmax(0, 1fr))`
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return template
|
|
100
|
-
}
|
|
101
|
-
</script>
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="grid"
|
|
4
|
+
:style="{
|
|
5
|
+
columnGap: `${colGap}px`,
|
|
6
|
+
rowGap: `${rowGap}px`,
|
|
7
|
+
gridTemplateColumns: computedColumns,
|
|
8
|
+
gridTemplateRows: computedRows,
|
|
9
|
+
}"
|
|
10
|
+
>
|
|
11
|
+
<slot />
|
|
12
|
+
</div>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script setup lang="ts">
|
|
16
|
+
import { computed } from 'vue'
|
|
17
|
+
import { useQuasar } from 'quasar'
|
|
18
|
+
|
|
19
|
+
const $q = useQuasar()
|
|
20
|
+
|
|
21
|
+
const props = defineProps({
|
|
22
|
+
cols: {
|
|
23
|
+
type: [String, Number, Object],
|
|
24
|
+
default: undefined,
|
|
25
|
+
},
|
|
26
|
+
rows: {
|
|
27
|
+
type: [String, Number, Object],
|
|
28
|
+
default: undefined,
|
|
29
|
+
},
|
|
30
|
+
colGap: {
|
|
31
|
+
type: [Number, String],
|
|
32
|
+
default: 24,
|
|
33
|
+
},
|
|
34
|
+
rowGap: {
|
|
35
|
+
type: [Number, String],
|
|
36
|
+
default: 24,
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
// Computed
|
|
41
|
+
const computedColumns = computed(() => {
|
|
42
|
+
if (typeof props.cols === 'object') {
|
|
43
|
+
if ($q.screen.xl && props.cols.xl) {
|
|
44
|
+
return generateColumnsTemplate(props.cols.xl)
|
|
45
|
+
} if ($q.screen.gt.md && props.cols.lg) {
|
|
46
|
+
return generateColumnsTemplate(props.cols.lg)
|
|
47
|
+
} else if ($q.screen.gt.sm && props.cols.md) {
|
|
48
|
+
return generateColumnsTemplate(props.cols.md)
|
|
49
|
+
} else if ($q.screen.gt.xs && props.cols.sm) {
|
|
50
|
+
return generateColumnsTemplate(props.cols.sm)
|
|
51
|
+
} else if (props.cols.xs) {
|
|
52
|
+
return generateColumnsTemplate(props.cols.xs)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return null
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return generateColumnsTemplate(props.cols)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
const computedRows = computed(() => {
|
|
62
|
+
if (typeof props.rows === 'object') {
|
|
63
|
+
if ($q.screen.xl && props.rows.xl) {
|
|
64
|
+
return generateRowsTemplate(props.rows.xl)
|
|
65
|
+
} if ($q.screen.gt.md && props.rows.lg) {
|
|
66
|
+
return generateRowsTemplate(props.rows.lg)
|
|
67
|
+
} else if ($q.screen.gt.sm && props.rows.md) {
|
|
68
|
+
return generateRowsTemplate(props.rows.md)
|
|
69
|
+
} else if ($q.screen.gt.xs && props.rows.sm) {
|
|
70
|
+
return generateRowsTemplate(props.rows.sm)
|
|
71
|
+
} else if (props.rows.xs) {
|
|
72
|
+
return generateRowsTemplate(props.rows.xs)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return null
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return generateRowsTemplate(props.rows)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
// Methods
|
|
82
|
+
function isNumeric (num) {
|
|
83
|
+
return !isNaN(num)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function generateColumnsTemplate (template) {
|
|
87
|
+
if (isNumeric(template)) {
|
|
88
|
+
return `repeat(${template}, minmax(0, 1fr))`
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return template
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function generateRowsTemplate (template) {
|
|
95
|
+
if (isNumeric(template)) {
|
|
96
|
+
return `repeat(${template}, minmax(0, 1fr))`
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return template
|
|
100
|
+
}
|
|
101
|
+
</script>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<q-header
|
|
3
|
-
class="bg-surface"
|
|
4
|
-
data-id="site-header"
|
|
5
|
-
>
|
|
6
|
-
<q-toolbar class="p-0 h-15">
|
|
7
|
-
<slot />
|
|
8
|
-
</q-toolbar>
|
|
9
|
-
</q-header>
|
|
10
|
-
</template>
|
|
1
|
+
<template>
|
|
2
|
+
<q-header
|
|
3
|
+
class="bg-surface"
|
|
4
|
+
data-id="site-header"
|
|
5
|
+
>
|
|
6
|
+
<q-toolbar class="p-0 h-15">
|
|
7
|
+
<slot />
|
|
8
|
+
</q-toolbar>
|
|
9
|
+
</q-header>
|
|
10
|
+
</template>
|
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div
|
|
3
|
-
v-if="showExtendedMenu"
|
|
4
|
-
class="header-links gt-sm"
|
|
5
|
-
>
|
|
6
|
-
<c-header-menu-link
|
|
7
|
-
v-for="link in links"
|
|
8
|
-
:key="link.href"
|
|
9
|
-
:text="link.text"
|
|
10
|
-
:href="link.href"
|
|
11
|
-
:is-active="link.isActive"
|
|
12
|
-
/>
|
|
13
|
-
</div>
|
|
14
|
-
|
|
15
|
-
<!-- Toggle menu items with button on small devices-->
|
|
16
|
-
<c-tile-btn
|
|
17
|
-
icon="mdi-menu"
|
|
18
|
-
:class="showExtendedMenu ? 'lt-md' : ''"
|
|
19
|
-
>
|
|
20
|
-
<q-menu>
|
|
21
|
-
<q-list>
|
|
22
|
-
<c-menu-item
|
|
23
|
-
v-for="link in links"
|
|
24
|
-
:key="link.href"
|
|
25
|
-
:text="link.text"
|
|
26
|
-
:href="link.href"
|
|
27
|
-
/>
|
|
28
|
-
</q-list>
|
|
29
|
-
</q-menu>
|
|
30
|
-
</c-tile-btn>
|
|
31
|
-
</template>
|
|
32
|
-
|
|
33
|
-
<script setup lang="ts">
|
|
34
|
-
import { computed, withDefaults } from 'vue'
|
|
35
|
-
|
|
36
|
-
interface Link {
|
|
37
|
-
text: string,
|
|
38
|
-
href: string,
|
|
39
|
-
isActive?: boolean,
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
interface Props {
|
|
43
|
-
maxVisible?: number,
|
|
44
|
-
links: Link[]
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const props = withDefaults(defineProps<Props>(), {
|
|
48
|
-
maxVisible: 12,
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
const showExtendedMenu = computed(() => props.maxVisible >= props.links.length)
|
|
52
|
-
</script>
|
|
53
|
-
|
|
54
|
-
<style scoped>
|
|
55
|
-
.header-links {
|
|
56
|
-
margin-right: 32px;
|
|
57
|
-
height: 100%;
|
|
58
|
-
display: flex;
|
|
59
|
-
overflow: hidden;
|
|
60
|
-
}
|
|
61
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
v-if="showExtendedMenu"
|
|
4
|
+
class="header-links gt-sm"
|
|
5
|
+
>
|
|
6
|
+
<c-header-menu-link
|
|
7
|
+
v-for="link in links"
|
|
8
|
+
:key="link.href"
|
|
9
|
+
:text="link.text"
|
|
10
|
+
:href="link.href"
|
|
11
|
+
:is-active="link.isActive"
|
|
12
|
+
/>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<!-- Toggle menu items with button on small devices-->
|
|
16
|
+
<c-tile-btn
|
|
17
|
+
icon="mdi-menu"
|
|
18
|
+
:class="showExtendedMenu ? 'lt-md' : ''"
|
|
19
|
+
>
|
|
20
|
+
<q-menu>
|
|
21
|
+
<q-list>
|
|
22
|
+
<c-menu-item
|
|
23
|
+
v-for="link in links"
|
|
24
|
+
:key="link.href"
|
|
25
|
+
:text="link.text"
|
|
26
|
+
:href="link.href"
|
|
27
|
+
/>
|
|
28
|
+
</q-list>
|
|
29
|
+
</q-menu>
|
|
30
|
+
</c-tile-btn>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script setup lang="ts">
|
|
34
|
+
import { computed, withDefaults } from 'vue'
|
|
35
|
+
|
|
36
|
+
interface Link {
|
|
37
|
+
text: string,
|
|
38
|
+
href: string,
|
|
39
|
+
isActive?: boolean,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface Props {
|
|
43
|
+
maxVisible?: number,
|
|
44
|
+
links: Link[]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
48
|
+
maxVisible: 12,
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const showExtendedMenu = computed(() => props.maxVisible >= props.links.length)
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<style scoped>
|
|
55
|
+
.header-links {
|
|
56
|
+
margin-right: 32px;
|
|
57
|
+
height: 100%;
|
|
58
|
+
display: flex;
|
|
59
|
+
overflow: hidden;
|
|
60
|
+
}
|
|
61
|
+
</style>
|
|
@@ -1,51 +1,51 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<a
|
|
3
|
-
class="link"
|
|
4
|
-
:class="{ 'is-active': isActive }"
|
|
5
|
-
:href="href"
|
|
6
|
-
>
|
|
7
|
-
<span class="truncate">
|
|
8
|
-
{{ text }}
|
|
9
|
-
</span>
|
|
10
|
-
</a>
|
|
11
|
-
</template>
|
|
12
|
-
|
|
13
|
-
<script setup lang="ts">
|
|
14
|
-
interface Props {
|
|
15
|
-
text: string,
|
|
16
|
-
href: string,
|
|
17
|
-
isActive?: boolean
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
defineProps<Props>()
|
|
21
|
-
</script>
|
|
22
|
-
|
|
23
|
-
<style scoped>
|
|
24
|
-
.link {
|
|
25
|
-
display: flex;
|
|
26
|
-
align-items: center;
|
|
27
|
-
font-size: 16px;
|
|
28
|
-
font-weight: 500;
|
|
29
|
-
padding: 0 20px 4px;
|
|
30
|
-
position: relative;
|
|
31
|
-
min-width: 0;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.link:hover {
|
|
35
|
-
text-decoration: underline;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.is-active {
|
|
39
|
-
font-weight: 600;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.is-active::before {
|
|
43
|
-
content: '';
|
|
44
|
-
width: 8px;
|
|
45
|
-
height: 8px;
|
|
46
|
-
background: var(--q-accent);
|
|
47
|
-
position: absolute;
|
|
48
|
-
top: calc(50% - 4px);
|
|
49
|
-
left: 8px;
|
|
50
|
-
}
|
|
51
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<a
|
|
3
|
+
class="link"
|
|
4
|
+
:class="{ 'is-active': isActive }"
|
|
5
|
+
:href="href"
|
|
6
|
+
>
|
|
7
|
+
<span class="truncate">
|
|
8
|
+
{{ text }}
|
|
9
|
+
</span>
|
|
10
|
+
</a>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
interface Props {
|
|
15
|
+
text: string,
|
|
16
|
+
href: string,
|
|
17
|
+
isActive?: boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
defineProps<Props>()
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<style scoped>
|
|
24
|
+
.link {
|
|
25
|
+
display: flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
font-size: 16px;
|
|
28
|
+
font-weight: 500;
|
|
29
|
+
padding: 0 20px 4px;
|
|
30
|
+
position: relative;
|
|
31
|
+
min-width: 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.link:hover {
|
|
35
|
+
text-decoration: underline;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.is-active {
|
|
39
|
+
font-weight: 600;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.is-active::before {
|
|
43
|
+
content: '';
|
|
44
|
+
width: 8px;
|
|
45
|
+
height: 8px;
|
|
46
|
+
background: var(--q-accent);
|
|
47
|
+
position: absolute;
|
|
48
|
+
top: calc(50% - 4px);
|
|
49
|
+
left: 8px;
|
|
50
|
+
}
|
|
51
|
+
</style>
|