@xen-orchestra/web-core 0.31.1 → 0.33.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/lib/assets/css/_colors.pcss +8 -0
- package/lib/components/button-group/VtsButtonGroup.vue +5 -1
- package/lib/components/menu/MenuList.vue +1 -2
- package/lib/components/menu/MenuTrigger.vue +5 -11
- package/lib/components/modal/VtsModal.vue +82 -0
- package/lib/components/modal/VtsModalButton.vue +36 -0
- package/lib/components/modal/VtsModalCancelButton.vue +37 -0
- package/lib/components/modal/VtsModalConfirmButton.vue +21 -0
- package/lib/components/modal/VtsModalList.vue +34 -0
- package/lib/components/object-icon/VtsObjectIcon.vue +3 -8
- package/lib/components/status/VtsStatus.vue +66 -0
- package/lib/components/task/VtsQuickTaskList.vue +17 -5
- package/lib/components/tree/VtsTreeItem.vue +2 -2
- package/lib/components/ui/breadcrumb/UiBreadcrumb.vue +79 -0
- package/lib/components/ui/button/UiButton.vue +13 -67
- package/lib/components/ui/modal/UiModal.vue +164 -0
- package/lib/components/ui/quick-task-item/UiQuickTaskItem.vue +2 -2
- package/lib/composables/context.composable.ts +3 -5
- package/lib/composables/link-component.composable.ts +3 -2
- package/lib/composables/pagination.composable.ts +3 -2
- package/lib/composables/tree-filter.composable.ts +5 -3
- package/lib/icons/fa-icons.ts +13 -1
- package/lib/icons/index.ts +17 -0
- package/lib/locales/cs.json +60 -2
- package/lib/locales/de.json +40 -2
- package/lib/locales/en.json +27 -1
- package/lib/locales/es.json +51 -5
- package/lib/locales/fa.json +10 -10
- package/lib/locales/fr.json +28 -2
- package/lib/locales/it.json +4 -0
- package/lib/locales/nl.json +64 -14
- package/lib/locales/pt_BR.json +3 -3
- package/lib/locales/ru.json +41 -2
- package/lib/locales/sv.json +55 -1
- package/lib/locales/uk.json +4 -4
- package/lib/packages/collection/use-collection.ts +3 -2
- package/lib/packages/form-select/use-form-option-controller.ts +3 -2
- package/lib/packages/form-select/use-form-select.ts +8 -7
- package/lib/packages/menu/action.ts +4 -3
- package/lib/packages/menu/link.ts +5 -4
- package/lib/packages/menu/router-link.ts +3 -2
- package/lib/packages/menu/toggle-target.ts +3 -2
- package/lib/packages/modal/ModalProvider.vue +17 -0
- package/lib/packages/modal/README.md +253 -0
- package/lib/packages/modal/create-modal-opener.ts +103 -0
- package/lib/packages/modal/modal.store.ts +22 -0
- package/lib/packages/modal/types.ts +92 -0
- package/lib/packages/modal/use-modal.ts +53 -0
- package/lib/packages/progress/use-progress.ts +4 -3
- package/lib/packages/table/README.md +336 -0
- package/lib/packages/table/apply-extensions.ts +26 -0
- package/lib/packages/table/define-columns.ts +62 -0
- package/lib/packages/table/define-renderer/define-table-cell-renderer.ts +27 -0
- package/lib/packages/table/define-renderer/define-table-renderer.ts +47 -0
- package/lib/packages/table/define-renderer/define-table-row-renderer.ts +29 -0
- package/lib/packages/table/define-renderer/define-table-section-renderer.ts +29 -0
- package/lib/packages/table/define-table/define-multi-source-table.ts +39 -0
- package/lib/packages/table/define-table/define-table.ts +13 -0
- package/lib/packages/table/define-table/define-typed-table.ts +18 -0
- package/lib/packages/table/index.ts +11 -0
- package/lib/packages/table/transform-sources.ts +13 -0
- package/lib/packages/table/types/extensions.ts +16 -0
- package/lib/packages/table/types/index.ts +47 -0
- package/lib/packages/table/types/table-cell.ts +18 -0
- package/lib/packages/table/types/table-row.ts +20 -0
- package/lib/packages/table/types/table-section.ts +19 -0
- package/lib/packages/table/types/table.ts +28 -0
- package/lib/packages/threshold/use-threshold.ts +4 -3
- package/lib/types/vue-virtual-scroller.d.ts +101 -0
- package/lib/utils/injection-keys.util.ts +3 -0
- package/lib/utils/progress.util.ts +2 -1
- package/lib/utils/to-computed.util.ts +15 -0
- package/package.json +3 -2
- package/lib/components/backup-state/VtsBackupState.vue +0 -37
- package/lib/components/connection-status/VtsConnectionStatus.vue +0 -36
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
--color-neutral-border: #d0d0d5;
|
|
14
14
|
|
|
15
|
+
/* OPACITY */
|
|
16
|
+
|
|
17
|
+
--color-opacity-primary: #1a1b3833;
|
|
18
|
+
|
|
15
19
|
/* BRAND */
|
|
16
20
|
|
|
17
21
|
--color-brand-txt-base: #6b63bf;
|
|
@@ -107,6 +111,10 @@
|
|
|
107
111
|
|
|
108
112
|
--color-neutral-border: #363647;
|
|
109
113
|
|
|
114
|
+
/* OPACITY */
|
|
115
|
+
|
|
116
|
+
--color-opacity-primary: #1a1b3899;
|
|
117
|
+
|
|
110
118
|
/* BRAND */
|
|
111
119
|
|
|
112
120
|
--color-brand-txt-base: #9b92ff;
|
|
@@ -88,12 +88,11 @@ const open = (event: MouseEvent) => {
|
|
|
88
88
|
.menu-list {
|
|
89
89
|
display: inline-flex;
|
|
90
90
|
flex-direction: column;
|
|
91
|
-
padding: 0.4rem;
|
|
92
91
|
cursor: default;
|
|
93
92
|
color: var(--color-neutral-txt-primary);
|
|
94
93
|
border-radius: 0.4rem;
|
|
95
94
|
background-color: var(--color-neutral-background-primary);
|
|
96
|
-
|
|
95
|
+
z-index: 1010;
|
|
97
96
|
|
|
98
97
|
&.horizontal {
|
|
99
98
|
flex-direction: row;
|
|
@@ -20,17 +20,11 @@ defineProps<{
|
|
|
20
20
|
|
|
21
21
|
<style lang="postcss" scoped>
|
|
22
22
|
.menu-trigger {
|
|
23
|
-
font-size: 1.6rem;
|
|
24
|
-
font-weight: 400;
|
|
25
23
|
display: flex;
|
|
26
24
|
align-items: center;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
white-space: nowrap;
|
|
31
|
-
border-radius: 0.8rem;
|
|
32
|
-
gap: 1rem;
|
|
33
|
-
background-color: var(--color-neutral-background-primary);
|
|
25
|
+
padding-inline: 1.6rem;
|
|
26
|
+
gap: 0.8rem;
|
|
27
|
+
height: 4.5rem;
|
|
34
28
|
|
|
35
29
|
&.disabled {
|
|
36
30
|
color: var(--color-neutral-txt-secondary);
|
|
@@ -40,12 +34,12 @@ defineProps<{
|
|
|
40
34
|
cursor: pointer;
|
|
41
35
|
|
|
42
36
|
&:hover {
|
|
43
|
-
background-color: var(--color-brand-background-
|
|
37
|
+
background-color: var(--color-brand-background-hover);
|
|
44
38
|
}
|
|
45
39
|
|
|
46
40
|
&:active,
|
|
47
41
|
&.active {
|
|
48
|
-
background-color: var(--color-brand-background-
|
|
42
|
+
background-color: var(--color-brand-background-active);
|
|
49
43
|
}
|
|
50
44
|
}
|
|
51
45
|
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<UiModal :icon :accent v-on="{ dismiss: handleDismiss, submit: handleSubmit }">
|
|
3
|
+
<template v-if="slots.title" #title>
|
|
4
|
+
<slot name="title" />
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<template #content>
|
|
8
|
+
<slot name="content" />
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<template v-if="slots.buttons" #buttons>
|
|
12
|
+
<slot name="buttons" />
|
|
13
|
+
</template>
|
|
14
|
+
</UiModal>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<script lang="ts" setup>
|
|
18
|
+
import UiModal, { type ModalAccent } from '@core/components/ui/modal/UiModal.vue'
|
|
19
|
+
import type { IconName } from '@core/icons'
|
|
20
|
+
import { IK_MODAL } from '@core/packages/modal/types.ts'
|
|
21
|
+
import { IK_MODAL_ACCENT } from '@core/utils/injection-keys.util.ts'
|
|
22
|
+
import { useMagicKeys, whenever } from '@vueuse/core'
|
|
23
|
+
import { computed, inject, provide } from 'vue'
|
|
24
|
+
|
|
25
|
+
const { accent, dismissible, onConfirm, onDismiss, current } = defineProps<{
|
|
26
|
+
accent: ModalAccent
|
|
27
|
+
icon?: IconName
|
|
28
|
+
dismissible?: boolean
|
|
29
|
+
onConfirm?: () => void
|
|
30
|
+
onDismiss?: () => void
|
|
31
|
+
current?: boolean
|
|
32
|
+
}>()
|
|
33
|
+
|
|
34
|
+
const emit = defineEmits<{
|
|
35
|
+
confirm: []
|
|
36
|
+
dismiss: []
|
|
37
|
+
}>()
|
|
38
|
+
|
|
39
|
+
const slots = defineSlots<{
|
|
40
|
+
content(): any
|
|
41
|
+
buttons?(): any
|
|
42
|
+
title?(): any
|
|
43
|
+
}>()
|
|
44
|
+
|
|
45
|
+
const modal = inject(IK_MODAL)
|
|
46
|
+
|
|
47
|
+
provide(
|
|
48
|
+
IK_MODAL_ACCENT,
|
|
49
|
+
computed(() => accent)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
const handleDismiss = computed(() => {
|
|
53
|
+
if (!dismissible) {
|
|
54
|
+
return undefined
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (onDismiss) {
|
|
58
|
+
return () => emit('dismiss')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return () => modal?.value.onCancel()
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
function handleSubmit(event: SubmitEvent) {
|
|
65
|
+
event.preventDefault()
|
|
66
|
+
|
|
67
|
+
if (onConfirm) {
|
|
68
|
+
emit('confirm')
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
modal?.value.onConfirm()
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const { escape } = useMagicKeys()
|
|
76
|
+
|
|
77
|
+
whenever(escape, () => {
|
|
78
|
+
if (dismissible && current) {
|
|
79
|
+
handleDismiss.value?.()
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
</script>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<UiButton :accent="buttonAccent" :busy="modal?.isBusy.value" :variant size="medium">
|
|
3
|
+
<slot />
|
|
4
|
+
</UiButton>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script lang="ts" setup>
|
|
8
|
+
import UiButton, { type ButtonVariant } from '@core/components/ui/button/UiButton.vue'
|
|
9
|
+
import { useMapper } from '@core/packages/mapper'
|
|
10
|
+
import { IK_MODAL } from '@core/packages/modal/types.ts'
|
|
11
|
+
import { IK_MODAL_ACCENT } from '@core/utils/injection-keys.util.ts'
|
|
12
|
+
import { inject } from 'vue'
|
|
13
|
+
|
|
14
|
+
defineProps<{
|
|
15
|
+
variant: ButtonVariant
|
|
16
|
+
}>()
|
|
17
|
+
|
|
18
|
+
defineSlots<{
|
|
19
|
+
default(): any
|
|
20
|
+
}>()
|
|
21
|
+
|
|
22
|
+
const modal = inject(IK_MODAL)
|
|
23
|
+
|
|
24
|
+
const modalAccent = inject(IK_MODAL_ACCENT)
|
|
25
|
+
|
|
26
|
+
const buttonAccent = useMapper(
|
|
27
|
+
() => modalAccent?.value,
|
|
28
|
+
{
|
|
29
|
+
success: 'brand',
|
|
30
|
+
info: 'brand',
|
|
31
|
+
warning: 'warning',
|
|
32
|
+
danger: 'danger',
|
|
33
|
+
},
|
|
34
|
+
'info'
|
|
35
|
+
)
|
|
36
|
+
</script>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<VtsModalButton variant="secondary" @click="handleClick">
|
|
3
|
+
<slot>{{ t('cancel') }}</slot>
|
|
4
|
+
</VtsModalButton>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script lang="ts" setup>
|
|
8
|
+
import VtsModalButton from '@core/components/modal/VtsModalButton.vue'
|
|
9
|
+
import { IK_MODAL } from '@core/packages/modal/types.ts'
|
|
10
|
+
import { inject } from 'vue'
|
|
11
|
+
import { useI18n } from 'vue-i18n'
|
|
12
|
+
|
|
13
|
+
const { onClick } = defineProps<{
|
|
14
|
+
onClick?: () => void
|
|
15
|
+
}>()
|
|
16
|
+
|
|
17
|
+
const emit = defineEmits<{
|
|
18
|
+
click: []
|
|
19
|
+
}>()
|
|
20
|
+
|
|
21
|
+
defineSlots<{
|
|
22
|
+
default?(): any
|
|
23
|
+
}>()
|
|
24
|
+
|
|
25
|
+
const { t } = useI18n()
|
|
26
|
+
|
|
27
|
+
const modal = inject(IK_MODAL)
|
|
28
|
+
|
|
29
|
+
function handleClick() {
|
|
30
|
+
if (onClick) {
|
|
31
|
+
emit('click')
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
modal?.value.onCancel()
|
|
36
|
+
}
|
|
37
|
+
</script>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<VtsModalButton variant="primary" :type="onClick ? 'button' : 'submit'" @click="emit('click')">
|
|
3
|
+
<slot />
|
|
4
|
+
</VtsModalButton>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script lang="ts" setup>
|
|
8
|
+
import VtsModalButton from '@core/components/modal/VtsModalButton.vue'
|
|
9
|
+
|
|
10
|
+
const { onClick } = defineProps<{
|
|
11
|
+
onClick?: () => void
|
|
12
|
+
}>()
|
|
13
|
+
|
|
14
|
+
const emit = defineEmits<{
|
|
15
|
+
click: []
|
|
16
|
+
}>()
|
|
17
|
+
|
|
18
|
+
defineSlots<{
|
|
19
|
+
default(): any
|
|
20
|
+
}>()
|
|
21
|
+
</script>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="modalStore.modals.length > 0" class="vts-modal-list">
|
|
3
|
+
<ModalProvider v-for="(modal, index) of modalStore.modals" :key="modal.id" :modal>
|
|
4
|
+
<component
|
|
5
|
+
:is="modal.component"
|
|
6
|
+
class="modal-component"
|
|
7
|
+
v-bind="modal.props"
|
|
8
|
+
:current="index === modalStore.modals.length - 1"
|
|
9
|
+
@confirm="modal.onConfirm"
|
|
10
|
+
@cancel="modal.onCancel"
|
|
11
|
+
/>
|
|
12
|
+
</ModalProvider>
|
|
13
|
+
</div>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script lang="ts" setup>
|
|
17
|
+
import { useModalStore } from '@core/packages/modal/modal.store.ts'
|
|
18
|
+
import ModalProvider from '@core/packages/modal/ModalProvider.vue'
|
|
19
|
+
|
|
20
|
+
const modalStore = useModalStore()
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<style lang="postcss" scoped>
|
|
24
|
+
.vts-modal-list {
|
|
25
|
+
position: fixed;
|
|
26
|
+
inset: 0;
|
|
27
|
+
background-color: var(--color-opacity-primary);
|
|
28
|
+
z-index: 1010;
|
|
29
|
+
|
|
30
|
+
.modal-component:not(:last-child) {
|
|
31
|
+
filter: brightness(0.8);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
</style>
|
|
@@ -2,19 +2,14 @@
|
|
|
2
2
|
<VtsIcon :name="iconName" :size />
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
|
-
<script generic="TType extends
|
|
5
|
+
<script generic="TType extends ObjectType, TState extends ObjectState<TType>" lang="ts" setup>
|
|
6
6
|
import VtsIcon, { type IconSize } from '@core/components/icon/VtsIcon.vue'
|
|
7
|
-
import type { ObjectIconName } from '@core/icons'
|
|
7
|
+
import type { ObjectIconName, ObjectState, ObjectType } from '@core/icons'
|
|
8
8
|
import { computed } from 'vue'
|
|
9
9
|
|
|
10
|
-
export type ObjectIconType = ObjectIconName extends `object:${infer TType}:${string}` ? TType : never
|
|
11
|
-
|
|
12
|
-
export type ObjectIconState<TType extends ObjectIconType> =
|
|
13
|
-
Extract<ObjectIconName, `object:${TType}:${string}`> extends `object:${TType}:${infer TState}` ? TState : never
|
|
14
|
-
|
|
15
10
|
const { type, state } = defineProps<{
|
|
16
11
|
type: TType
|
|
17
|
-
state:
|
|
12
|
+
state: TState
|
|
18
13
|
size: IconSize
|
|
19
14
|
}>()
|
|
20
15
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<UiInfo v-tooltip="iconOnly ? currentStatus.text : false" class="vts-status" :accent="currentStatus.accent">
|
|
3
|
+
<template v-if="!iconOnly">{{ currentStatus.text }}</template>
|
|
4
|
+
</UiInfo>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts">
|
|
8
|
+
import UiInfo, { type InfoAccent } from '@core/components/ui/info/UiInfo.vue'
|
|
9
|
+
import { vTooltip } from '@core/directives/tooltip.directive'
|
|
10
|
+
import { useMapper } from '@core/packages/mapper'
|
|
11
|
+
import { useI18n } from 'vue-i18n'
|
|
12
|
+
|
|
13
|
+
export type Status =
|
|
14
|
+
| 'connecting'
|
|
15
|
+
| 'connected'
|
|
16
|
+
| 'disconnected'
|
|
17
|
+
| 'partially-connected'
|
|
18
|
+
| 'disconnected-from-physical-device'
|
|
19
|
+
| 'physically-disconnected'
|
|
20
|
+
| 'unable-to-connect-to-the-pool'
|
|
21
|
+
| 'success'
|
|
22
|
+
| 'skipped'
|
|
23
|
+
| 'interrupted'
|
|
24
|
+
| 'failure'
|
|
25
|
+
| 'pending'
|
|
26
|
+
| 'enabled'
|
|
27
|
+
| 'disabled'
|
|
28
|
+
| true
|
|
29
|
+
| false
|
|
30
|
+
|
|
31
|
+
const { status } = defineProps<{
|
|
32
|
+
status: Status
|
|
33
|
+
iconOnly?: boolean
|
|
34
|
+
}>()
|
|
35
|
+
|
|
36
|
+
const { t } = useI18n()
|
|
37
|
+
|
|
38
|
+
const currentStatus = useMapper<Status, { text: string; accent: InfoAccent }>(
|
|
39
|
+
() => status,
|
|
40
|
+
() => [
|
|
41
|
+
['connecting', { text: t('connecting'), accent: 'info' }],
|
|
42
|
+
['connected', { text: t('connected'), accent: 'success' }],
|
|
43
|
+
['disconnected', { text: t('disconnected'), accent: 'danger' }],
|
|
44
|
+
['partially-connected', { text: t('partially-connected'), accent: 'warning' }],
|
|
45
|
+
['disconnected-from-physical-device', { text: t('disconnected-from-physical-device'), accent: 'warning' }],
|
|
46
|
+
['physically-disconnected', { text: t('disconnected-from-physical-device'), accent: 'danger' }],
|
|
47
|
+
['unable-to-connect-to-the-pool', { text: t('unable-to-connect-to-the-pool'), accent: 'danger' }],
|
|
48
|
+
['success', { text: t('success'), accent: 'success' }],
|
|
49
|
+
['skipped', { text: t('skipped'), accent: 'warning' }],
|
|
50
|
+
['interrupted', { text: t('interrupted'), accent: 'danger' }],
|
|
51
|
+
['failure', { text: t('failure'), accent: 'danger' }],
|
|
52
|
+
['pending', { text: t('in-progress'), accent: 'info' }],
|
|
53
|
+
['enabled', { text: t('enabled'), accent: 'success' }],
|
|
54
|
+
['disabled', { text: t('disabled'), accent: 'muted' }],
|
|
55
|
+
[true, { text: t('enabled'), accent: 'success' }],
|
|
56
|
+
[false, { text: t('disabled'), accent: 'muted' }],
|
|
57
|
+
],
|
|
58
|
+
false
|
|
59
|
+
)
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
<style lang="postcss" scoped>
|
|
63
|
+
.vts-status {
|
|
64
|
+
align-items: center;
|
|
65
|
+
}
|
|
66
|
+
</style>
|
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<DynamicScroller
|
|
3
|
+
v-if="!loading && tasks.length > 0"
|
|
4
|
+
:items="tasks"
|
|
5
|
+
:min-item-size="83"
|
|
6
|
+
class="vts-quick-task-list"
|
|
7
|
+
list-tag="ul"
|
|
8
|
+
item-tag="li"
|
|
9
|
+
>
|
|
10
|
+
<template #default="{ item: task, active }">
|
|
11
|
+
<DynamicScrollerItem :item="task" :active :size-dependencies="[task.subtasks]">
|
|
12
|
+
<UiQuickTaskItem :task />
|
|
13
|
+
</DynamicScrollerItem>
|
|
14
|
+
</template>
|
|
15
|
+
</DynamicScroller>
|
|
16
|
+
<ul v-else class="vts-quick-task-list">
|
|
3
17
|
<li v-if="loading">
|
|
4
18
|
<div class="loading">
|
|
5
19
|
<UiLoader />
|
|
6
20
|
<div>{{ t('loading') }}</div>
|
|
7
21
|
</div>
|
|
8
22
|
</li>
|
|
9
|
-
<
|
|
10
|
-
<li v-if="tasks.length === 0" class="typo-body-bold">{{ t('tasks.no-tasks') }}</li>
|
|
11
|
-
<UiQuickTaskItem v-for="task of tasks" :key="task.id" :task />
|
|
12
|
-
</template>
|
|
23
|
+
<li v-else-if="tasks.length === 0" class="typo-body-bold">{{ t('tasks.no-tasks') }}</li>
|
|
13
24
|
</ul>
|
|
14
25
|
</template>
|
|
15
26
|
|
|
@@ -17,6 +28,7 @@
|
|
|
17
28
|
import UiLoader from '@core/components/ui/loader/UiLoader.vue'
|
|
18
29
|
import UiQuickTaskItem, { type Task } from '@core/components/ui/quick-task-item/UiQuickTaskItem.vue'
|
|
19
30
|
import { useI18n } from 'vue-i18n'
|
|
31
|
+
import { DynamicScroller, DynamicScrollerItem } from 'vue-virtual-scroller'
|
|
20
32
|
|
|
21
33
|
defineProps<{
|
|
22
34
|
tasks: Task[]
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<!-- v2 -->
|
|
2
|
+
<template>
|
|
3
|
+
<nav class="ui-breadcrumb" :class="className" :aria-label="t('aria.breadcrumb.label')">
|
|
4
|
+
<ol>
|
|
5
|
+
<li v-for="child in slots.default()" :key="child.ctx.uid">
|
|
6
|
+
<component :is="child" />
|
|
7
|
+
</li>
|
|
8
|
+
</ol>
|
|
9
|
+
</nav>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script lang="ts" setup>
|
|
13
|
+
import { useMapper } from '@core/packages/mapper'
|
|
14
|
+
import { toVariants } from '@core/utils/to-variants.util.ts'
|
|
15
|
+
import { computed } from 'vue'
|
|
16
|
+
import { useI18n } from 'vue-i18n'
|
|
17
|
+
|
|
18
|
+
const { size } = defineProps<{
|
|
19
|
+
size: 'small' | 'medium'
|
|
20
|
+
}>()
|
|
21
|
+
|
|
22
|
+
const slots = defineSlots<{
|
|
23
|
+
default(): any
|
|
24
|
+
}>()
|
|
25
|
+
|
|
26
|
+
const { t } = useI18n()
|
|
27
|
+
|
|
28
|
+
const fontWeight = useMapper(
|
|
29
|
+
() => size,
|
|
30
|
+
{
|
|
31
|
+
small: 'typo-body-bold-small',
|
|
32
|
+
medium: 'typo-body-bold',
|
|
33
|
+
},
|
|
34
|
+
'medium'
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
const className = computed(() => [toVariants({ size }), fontWeight.value])
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<style lang="postcss" scoped>
|
|
41
|
+
.ui-breadcrumb {
|
|
42
|
+
ol {
|
|
43
|
+
display: flex;
|
|
44
|
+
align-items: center;
|
|
45
|
+
gap: 0.8rem;
|
|
46
|
+
flex-wrap: wrap;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
li {
|
|
50
|
+
display: flex;
|
|
51
|
+
align-items: center;
|
|
52
|
+
color: var(--color-neutral-txt-primary);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
li:not(:last-child)::after {
|
|
56
|
+
content: '';
|
|
57
|
+
display: inline-block;
|
|
58
|
+
margin-inline: 0.8rem 0.4rem;
|
|
59
|
+
border-inline-end: 0.2rem solid var(--color-neutral-txt-secondary);
|
|
60
|
+
border-block-start: 0.2rem solid var(--color-neutral-txt-secondary);
|
|
61
|
+
transform: rotate(45deg);
|
|
62
|
+
vertical-align: middle;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
&.size--small {
|
|
66
|
+
li:not(:last-child)::after {
|
|
67
|
+
width: 0.7rem;
|
|
68
|
+
height: 0.7rem;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
&.size--medium {
|
|
73
|
+
li:not(:last-child)::after {
|
|
74
|
+
width: 0.9rem;
|
|
75
|
+
height: 0.9rem;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
</style>
|