@nexxtmove/ui 0.1.38 → 0.1.39
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/dist/index.d.ts +71 -25
- package/dist/index.js +2303 -1771
- package/package.json +2 -1
- package/src/components/AnimatedNumber/AnimatedNumber.vue +4 -48
- package/src/components/CustomerJourneyTile/CustomerJourneyTile.vue +39 -14
- package/src/components/DropdownButton/DropdownButton.vue +31 -19
- package/src/components/Header/Header.vue +3 -1
- package/src/components/InputField/InputField.vue +6 -5
- package/src/components/Table/Table.vue +37 -7
- package/src/components/TimelineEvent/TimelineTypes.ts +2 -2
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexxtmove/ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.39",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"tailwind"
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
|
+
"@number-flow/vue": "^0.5.0",
|
|
23
24
|
"date-fns": "^4.1.0",
|
|
24
25
|
"date-fns-tz": "^3.2.0",
|
|
25
26
|
"reka-ui": "^2.9.2"
|
|
@@ -1,65 +1,21 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import
|
|
2
|
+
import NumberFlow from '@number-flow/vue'
|
|
3
3
|
|
|
4
4
|
defineOptions({
|
|
5
5
|
name: 'NexxtAnimatedNumber',
|
|
6
6
|
})
|
|
7
7
|
|
|
8
|
-
type EasingFunction = 'ease-linear' | 'ease-in' | 'ease-out' | 'ease-in-out'
|
|
9
|
-
|
|
10
8
|
const {
|
|
11
9
|
value,
|
|
12
10
|
duration = 500,
|
|
13
|
-
|
|
11
|
+
delay = 0,
|
|
14
12
|
} = defineProps<{
|
|
15
13
|
value: number
|
|
16
14
|
duration?: number
|
|
17
|
-
|
|
15
|
+
delay?: number
|
|
18
16
|
}>()
|
|
19
|
-
|
|
20
|
-
const direction = ref<'up' | 'down'>('up')
|
|
21
|
-
const digits = computed(() => String(value).split(''))
|
|
22
|
-
const transitionDuration = computed(() => `duration-${duration}`)
|
|
23
|
-
|
|
24
|
-
watch(
|
|
25
|
-
() => value,
|
|
26
|
-
(newVal, oldVal) => {
|
|
27
|
-
direction.value = newVal > oldVal ? 'up' : 'down'
|
|
28
|
-
},
|
|
29
|
-
)
|
|
30
17
|
</script>
|
|
31
18
|
|
|
32
19
|
<template>
|
|
33
|
-
<
|
|
34
|
-
tag="div"
|
|
35
|
-
class="relative flex shrink-0 items-center tabular-nums"
|
|
36
|
-
:aria-label="value"
|
|
37
|
-
:enter-active-class="`transition-all ${transitionDuration} ${easing}`"
|
|
38
|
-
:leave-active-class="`absolute transition-all ${transitionDuration} ${easing}`"
|
|
39
|
-
:enter-from-class="
|
|
40
|
-
direction === 'up' ? 'translate-y-full opacity-0' : '-translate-y-full opacity-0'
|
|
41
|
-
"
|
|
42
|
-
:leave-to-class="
|
|
43
|
-
direction === 'up' ? '-translate-y-full opacity-0' : 'translate-y-full opacity-0'
|
|
44
|
-
"
|
|
45
|
-
move-class="transition-all duration-500 ease-in-out"
|
|
46
|
-
>
|
|
47
|
-
<div
|
|
48
|
-
v-for="(digit, i) in digits"
|
|
49
|
-
:key="i"
|
|
50
|
-
class="relative inline-flex h-[1.5em] w-[1ch] items-center justify-center overflow-hidden"
|
|
51
|
-
aria-hidden="true"
|
|
52
|
-
>
|
|
53
|
-
<Transition
|
|
54
|
-
:enter-active-class="`transition-transform ${transitionDuration} ${easing}`"
|
|
55
|
-
:leave-active-class="`absolute inset-0 transition-transform ${transitionDuration} ${easing}`"
|
|
56
|
-
:enter-from-class="direction === 'up' ? 'translate-y-full' : '-translate-y-full'"
|
|
57
|
-
:leave-to-class="direction === 'up' ? '-translate-y-full' : 'translate-y-full'"
|
|
58
|
-
>
|
|
59
|
-
<span :key="digit" class="flex h-full w-full items-center justify-center">
|
|
60
|
-
{{ digit }}
|
|
61
|
-
</span>
|
|
62
|
-
</Transition>
|
|
63
|
-
</div>
|
|
64
|
-
</TransitionGroup>
|
|
20
|
+
<NumberFlow :value="value" :transform-timing="{ duration, delay }" />
|
|
65
21
|
</template>
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import NexxtIcon from '../Icon/Icon.vue'
|
|
3
|
-
import
|
|
3
|
+
import NexxtAnimatedNumber from '../AnimatedNumber/AnimatedNumber.vue'
|
|
4
|
+
import { computed, onMounted, ref } from 'vue'
|
|
5
|
+
import { PHASE_MAP } from '../TimelineEvent/TimelineTypes'
|
|
4
6
|
|
|
5
|
-
type Phase =
|
|
7
|
+
type Phase = (typeof PHASE_MAP)[keyof typeof PHASE_MAP]['label']
|
|
6
8
|
|
|
7
9
|
interface NexxtCustomerJourneyTileProps {
|
|
10
|
+
as?: keyof HTMLElementTagNameMap
|
|
8
11
|
title?: string
|
|
9
12
|
amount?: number
|
|
13
|
+
animated?: boolean
|
|
14
|
+
delay?: number
|
|
10
15
|
percentage?: number
|
|
11
16
|
percentageExplanaition?: string
|
|
12
17
|
}
|
|
13
18
|
|
|
14
|
-
const PHASE_ICON_MAP: Record<Phase, string
|
|
19
|
+
const PHASE_ICON_MAP: Partial<Record<Phase, string>> = {
|
|
15
20
|
Latent: 'eye-closed',
|
|
16
21
|
Oriëntatie: 'building-magnifying-glass',
|
|
17
22
|
'Actief zoeken': 'house-person-return',
|
|
@@ -24,8 +29,21 @@ defineOptions({
|
|
|
24
29
|
name: 'NexxtCustomerJourneyTile',
|
|
25
30
|
})
|
|
26
31
|
|
|
27
|
-
const {
|
|
28
|
-
|
|
32
|
+
const {
|
|
33
|
+
as = 'div',
|
|
34
|
+
title,
|
|
35
|
+
amount,
|
|
36
|
+
animated = false,
|
|
37
|
+
delay,
|
|
38
|
+
percentage,
|
|
39
|
+
percentageExplanaition,
|
|
40
|
+
} = defineProps<NexxtCustomerJourneyTileProps>()
|
|
41
|
+
|
|
42
|
+
const displayAmount = ref(animated ? 0 : (amount ?? 0))
|
|
43
|
+
|
|
44
|
+
onMounted(() => {
|
|
45
|
+
if (animated && amount !== undefined) displayAmount.value = amount
|
|
46
|
+
})
|
|
29
47
|
|
|
30
48
|
const icon = computed(() => {
|
|
31
49
|
if (!title) return null
|
|
@@ -46,10 +64,10 @@ const ariaLabel = computed(() => {
|
|
|
46
64
|
</script>
|
|
47
65
|
|
|
48
66
|
<template>
|
|
49
|
-
<
|
|
50
|
-
|
|
67
|
+
<component
|
|
68
|
+
:is="as"
|
|
51
69
|
:aria-label="ariaLabel"
|
|
52
|
-
class="flex
|
|
70
|
+
class="flex rounded-xl bg-white outline outline-gray-200 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-cornflower-blue-500"
|
|
53
71
|
:class="icon ? 'gap-6 p-1.5' : 'p-4'"
|
|
54
72
|
>
|
|
55
73
|
<div
|
|
@@ -63,19 +81,26 @@ const ariaLabel = computed(() => {
|
|
|
63
81
|
<span
|
|
64
82
|
class="heading-1"
|
|
65
83
|
:class="icon ? 'text-purple-500' : 'text-sapphire-900'"
|
|
66
|
-
v-if="amount"
|
|
67
|
-
>{{ amount }}</span
|
|
84
|
+
v-if="amount !== undefined"
|
|
68
85
|
>
|
|
69
|
-
|
|
86
|
+
<NexxtAnimatedNumber :value="displayAmount" :delay="delay" />
|
|
87
|
+
</span>
|
|
88
|
+
<div v-if="percentage !== undefined" class="flex gap-0.5">
|
|
70
89
|
<span
|
|
71
90
|
class="extra-small-semibold"
|
|
72
|
-
:class="
|
|
91
|
+
:class="
|
|
92
|
+
percentage > 0
|
|
93
|
+
? 'text-green-500'
|
|
94
|
+
: percentage === 0
|
|
95
|
+
? 'text-orange-500'
|
|
96
|
+
: 'text-brick-500'
|
|
97
|
+
"
|
|
73
98
|
><template v-if="percentage > 0">+</template>{{ percentage }}%</span
|
|
74
99
|
>
|
|
75
|
-
<span class="extra-small-normal" v-if="percentageExplanaition">{{
|
|
100
|
+
<span class="ml-0.5 text-left extra-small-normal" v-if="percentageExplanaition">{{
|
|
76
101
|
percentageExplanaition
|
|
77
102
|
}}</span>
|
|
78
103
|
</div>
|
|
79
104
|
</div>
|
|
80
|
-
</
|
|
105
|
+
</component>
|
|
81
106
|
</template>
|
|
@@ -6,14 +6,21 @@ interface NexxtDropdownButton {
|
|
|
6
6
|
label: string
|
|
7
7
|
action: string | (() => void)
|
|
8
8
|
icon?: InstanceType<typeof NexxtIcon>['name']
|
|
9
|
+
selected?: boolean
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
type NexxtDropdownButtonBase = {
|
|
12
13
|
variant?: 'primary' | 'secondary'
|
|
13
14
|
options: NexxtDropdownButton[]
|
|
14
15
|
placement?: 'left' | 'right'
|
|
16
|
+
triggerIcon?: InstanceType<typeof NexxtIcon>['name']
|
|
17
|
+
icon?: InstanceType<typeof NexxtIcon>['name']
|
|
15
18
|
}
|
|
16
19
|
|
|
20
|
+
export type NexxtDropdownButtonProps =
|
|
21
|
+
| (NexxtDropdownButtonBase & { iconOnly?: false; label: string; action: string | (() => void) })
|
|
22
|
+
| (NexxtDropdownButtonBase & { iconOnly: true; label?: string; action?: string | (() => void) })
|
|
23
|
+
|
|
17
24
|
const {
|
|
18
25
|
variant = 'primary',
|
|
19
26
|
options,
|
|
@@ -21,6 +28,8 @@ const {
|
|
|
21
28
|
action,
|
|
22
29
|
icon,
|
|
23
30
|
placement = 'right',
|
|
31
|
+
iconOnly = false,
|
|
32
|
+
triggerIcon = 'chevron-down',
|
|
24
33
|
} = defineProps<NexxtDropdownButtonProps>()
|
|
25
34
|
|
|
26
35
|
const emit = defineEmits<{
|
|
@@ -106,31 +115,33 @@ const transitionClasses = computed(() => {
|
|
|
106
115
|
:class="placement === 'right' ? 'items-end' : 'items-start'"
|
|
107
116
|
>
|
|
108
117
|
<div class="inline-flex items-center overflow-hidden rounded-md" :class="componentClasses">
|
|
118
|
+
<template v-if="!iconOnly">
|
|
119
|
+
<button
|
|
120
|
+
class="flex cursor-pointer items-center gap-2 px-4 py-2 transition-colors duration-200"
|
|
121
|
+
:class="buttonClasses"
|
|
122
|
+
@click="action && handleAction(action)"
|
|
123
|
+
>
|
|
124
|
+
<NexxtIcon v-if="icon" :name="icon" aria-hidden="true" />
|
|
125
|
+
{{ label }}
|
|
126
|
+
</button>
|
|
127
|
+
<span
|
|
128
|
+
class="h-7 w-px rounded-sm"
|
|
129
|
+
:class="variant === 'primary' ? 'bg-white' : 'bg-gray-200'"
|
|
130
|
+
aria-hidden="true"
|
|
131
|
+
></span>
|
|
132
|
+
</template>
|
|
109
133
|
<button
|
|
110
|
-
class="
|
|
111
|
-
:class="buttonClasses"
|
|
112
|
-
@click="
|
|
113
|
-
>
|
|
114
|
-
<NexxtIcon v-if="icon" :name="icon" aria-hidden="true" />
|
|
115
|
-
{{ label }}
|
|
116
|
-
</button>
|
|
117
|
-
<span
|
|
118
|
-
class="h-7 w-px rounded-sm"
|
|
119
|
-
:class="variant === 'primary' ? 'bg-white' : 'bg-gray-200'"
|
|
120
|
-
aria-hidden="true"
|
|
121
|
-
></span>
|
|
122
|
-
<button
|
|
123
|
-
class="cursor-pointer px-2 py-2 transition-colors duration-200"
|
|
124
|
-
:class="buttonClasses"
|
|
125
|
-
@click="toggleDropdown"
|
|
134
|
+
class="w-10 shrink-0 cursor-pointer transition-colors duration-200"
|
|
135
|
+
:class="[buttonClasses, iconOnly ? 'p-2' : 'px-2 py-2']"
|
|
136
|
+
@click="iconOnly ? toggleDropdown() : toggleDropdown()"
|
|
126
137
|
aria-haspopup="menu"
|
|
127
138
|
:aria-expanded="isOpen"
|
|
128
139
|
:aria-label="`Open ${label} menu`"
|
|
129
140
|
>
|
|
130
141
|
<NexxtIcon
|
|
131
|
-
name="
|
|
142
|
+
:name="triggerIcon"
|
|
132
143
|
class="transition-transform duration-200"
|
|
133
|
-
:class="{ 'rotate-180': isOpen }"
|
|
144
|
+
:class="{ 'rotate-180': isOpen && triggerIcon === 'chevron-down' }"
|
|
134
145
|
aria-hidden="true"
|
|
135
146
|
/>
|
|
136
147
|
</button>
|
|
@@ -148,6 +159,7 @@ const transitionClasses = computed(() => {
|
|
|
148
159
|
:key="option.label"
|
|
149
160
|
role="menuitem"
|
|
150
161
|
class="flex w-full min-w-42 cursor-pointer items-center gap-2 px-4 py-2 text-left text-sm whitespace-nowrap text-gray-700 transition-colors duration-200 hover:bg-gray-100 hover:text-purple-600 focus:bg-gray-100 focus:outline-none"
|
|
162
|
+
:class="option.selected ? 'bg-cornflower-blue-100' : ''"
|
|
151
163
|
@click="handleOptionClick(option.action)"
|
|
152
164
|
>
|
|
153
165
|
<NexxtIcon v-if="option.icon" :name="option.icon" aria-hidden="true" />
|
|
@@ -3,6 +3,7 @@ import Button from '../Button/Button.vue'
|
|
|
3
3
|
|
|
4
4
|
interface NexxtHeaderProps {
|
|
5
5
|
title: string
|
|
6
|
+
headingType?: 'heading-1' | 'heading-2' | 'heading-3' | 'heading-4'
|
|
6
7
|
backButtonText?: string
|
|
7
8
|
backButtonAction?: () => void
|
|
8
9
|
}
|
|
@@ -12,6 +13,7 @@ defineOptions({
|
|
|
12
13
|
})
|
|
13
14
|
|
|
14
15
|
const {
|
|
16
|
+
headingType = 'heading-4',
|
|
15
17
|
backButtonText,
|
|
16
18
|
backButtonAction = () => {
|
|
17
19
|
window.history.back()
|
|
@@ -29,7 +31,7 @@ const {
|
|
|
29
31
|
@click="backButtonAction"
|
|
30
32
|
>{{ backButtonText }}</Button
|
|
31
33
|
>
|
|
32
|
-
<span class="block truncate
|
|
34
|
+
<span class="block truncate text-sapphire-500" :class="headingType">
|
|
33
35
|
{{ title }}
|
|
34
36
|
</span>
|
|
35
37
|
</div>
|
|
@@ -33,7 +33,7 @@ const modelValue = defineModel<string>()
|
|
|
33
33
|
</label>
|
|
34
34
|
|
|
35
35
|
<div
|
|
36
|
-
class="flex items-center gap-2 rounded-
|
|
36
|
+
class="flex items-center gap-2 rounded-sm px-3 ring transition-colors ease-out focus-within:ring-cornflower-blue-500"
|
|
37
37
|
:class="error ? 'ring-brick-400' : 'ring-gray-200'"
|
|
38
38
|
>
|
|
39
39
|
<span v-if="leftIcon" class="flex items-center">
|
|
@@ -47,10 +47,11 @@ const modelValue = defineModel<string>()
|
|
|
47
47
|
v-bind="$attrs"
|
|
48
48
|
class="h-10 min-w-60 bg-transparent text-sm text-gray-900 placeholder-gray-400 focus:outline-none"
|
|
49
49
|
/>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
<slot name="right">
|
|
51
|
+
<span v-if="rightIcon" class="flex items-center">
|
|
52
|
+
<Icon :name="rightIcon" />
|
|
53
|
+
</span>
|
|
54
|
+
</slot>
|
|
54
55
|
</div>
|
|
55
56
|
|
|
56
57
|
<Transition
|
|
@@ -8,6 +8,7 @@ export interface TableColumn<K extends string = string> {
|
|
|
8
8
|
label: string
|
|
9
9
|
sortable?: boolean
|
|
10
10
|
width?: string
|
|
11
|
+
minCellWidth?: number
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export interface NexxtTableProps<
|
|
@@ -17,12 +18,19 @@ export interface NexxtTableProps<
|
|
|
17
18
|
columns: TableColumn<TKey>[]
|
|
18
19
|
rows: TRow[]
|
|
19
20
|
selectable?: boolean
|
|
21
|
+
loading?: boolean
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
const INTERACTIVE = ['a', 'button', 'input', 'select', 'textarea', 'label']
|
|
23
25
|
|
|
24
26
|
defineOptions({ name: 'NexxtTable' })
|
|
25
27
|
|
|
28
|
+
defineSlots<
|
|
29
|
+
{ [K in TKey as `cell-${K}`]?: (props: { row: TRow; value: TRow[K] }) => unknown } & {
|
|
30
|
+
[key: string]: ((props: Record<string, unknown>) => unknown) | undefined
|
|
31
|
+
}
|
|
32
|
+
>()
|
|
33
|
+
|
|
26
34
|
const props = defineProps<NexxtTableProps<TKey, TRow>>()
|
|
27
35
|
const emit = defineEmits<{
|
|
28
36
|
'row-click': [row: TRow]
|
|
@@ -54,7 +62,9 @@ const toggleRow = (row: TRow) => {
|
|
|
54
62
|
}
|
|
55
63
|
|
|
56
64
|
const columnTemplate = computed(() =>
|
|
57
|
-
props.columns
|
|
65
|
+
props.columns
|
|
66
|
+
.map((col) => `minmax(${col.minCellWidth ?? 150}px, ${col.width ?? '1fr'})`)
|
|
67
|
+
.join(' '),
|
|
58
68
|
)
|
|
59
69
|
|
|
60
70
|
const gridTemplate = computed(() =>
|
|
@@ -87,7 +97,8 @@ const getRowRoundedClass = (rowIndex: number) => {
|
|
|
87
97
|
return ''
|
|
88
98
|
}
|
|
89
99
|
|
|
90
|
-
const rowValue = (row: TRow, key: TKey) =>
|
|
100
|
+
const rowValue = (row: TRow, key: TKey): TRow[TKey] => row[key]
|
|
101
|
+
const cellSlotName = (key: TKey): string => `cell-${key}`
|
|
91
102
|
|
|
92
103
|
const handleRowKeydown = (event: KeyboardEvent, rowIndex: number) => {
|
|
93
104
|
if (event.key === 'ArrowDown') {
|
|
@@ -102,12 +113,12 @@ const handleRowKeydown = (event: KeyboardEvent, rowIndex: number) => {
|
|
|
102
113
|
|
|
103
114
|
<template>
|
|
104
115
|
<div class="flex flex-col gap-3">
|
|
105
|
-
<div class="overflow-auto">
|
|
116
|
+
<div class="overflow-x-auto">
|
|
106
117
|
<div
|
|
107
118
|
role="grid"
|
|
108
119
|
:aria-colcount="columns.length + (selectable ? 1 : 0)"
|
|
109
120
|
:aria-rowcount="rows.length + 1"
|
|
110
|
-
class="
|
|
121
|
+
class="min-w-full"
|
|
111
122
|
>
|
|
112
123
|
<div class="sticky top-0 z-10 mb-0.5">
|
|
113
124
|
<div v-if="$slots.toolbar">
|
|
@@ -156,7 +167,9 @@ const handleRowKeydown = (event: KeyboardEvent, rowIndex: number) => {
|
|
|
156
167
|
@keydown.enter.prevent="handleSort(column)"
|
|
157
168
|
@keydown.space.prevent="handleSort(column)"
|
|
158
169
|
>
|
|
159
|
-
|
|
170
|
+
<span :class="sortKey === column.key ? 'text-cornflower-blue-600' : ''">{{
|
|
171
|
+
column.label
|
|
172
|
+
}}</span>
|
|
160
173
|
<Icon
|
|
161
174
|
v-if="column.sortable"
|
|
162
175
|
:name="
|
|
@@ -173,7 +186,7 @@ const handleRowKeydown = (event: KeyboardEvent, rowIndex: number) => {
|
|
|
173
186
|
</div>
|
|
174
187
|
</div>
|
|
175
188
|
|
|
176
|
-
<div role="rowgroup">
|
|
189
|
+
<div role="rowgroup" class="relative">
|
|
177
190
|
<div
|
|
178
191
|
v-for="(row, rowIndex) in rows"
|
|
179
192
|
:key="rowIndex"
|
|
@@ -215,7 +228,7 @@ const handleRowKeydown = (event: KeyboardEvent, rowIndex: number) => {
|
|
|
215
228
|
role="gridcell"
|
|
216
229
|
:aria-colindex="colIndex + (selectable ? 2 : 1)"
|
|
217
230
|
>
|
|
218
|
-
<slot :name="
|
|
231
|
+
<slot :name="cellSlotName(column.key)" :row="row" :value="rowValue(row, column.key)">
|
|
219
232
|
{{ rowValue(row, column.key) }}
|
|
220
233
|
</slot>
|
|
221
234
|
</div>
|
|
@@ -224,6 +237,23 @@ const handleRowKeydown = (event: KeyboardEvent, rowIndex: number) => {
|
|
|
224
237
|
<div v-if="!rows.length" class="px-4 py-8 text-center text-sm text-slate-400" role="row">
|
|
225
238
|
<slot name="empty">Geen data beschikbaar</slot>
|
|
226
239
|
</div>
|
|
240
|
+
|
|
241
|
+
<Transition
|
|
242
|
+
enter-active-class="transition-opacity duration-200"
|
|
243
|
+
leave-active-class="transition-opacity duration-200"
|
|
244
|
+
enter-from-class="opacity-0"
|
|
245
|
+
leave-to-class="opacity-0"
|
|
246
|
+
>
|
|
247
|
+
<div
|
|
248
|
+
v-if="loading"
|
|
249
|
+
data-testid="loading-overlay"
|
|
250
|
+
class="absolute inset-0 flex items-center justify-center rounded-md bg-white/40 backdrop-blur-sm"
|
|
251
|
+
>
|
|
252
|
+
<slot name="loading"
|
|
253
|
+
><Icon name="spinner-third" class="fa-spin text-3xl text-purple-500"
|
|
254
|
+
/></slot>
|
|
255
|
+
</div>
|
|
256
|
+
</Transition>
|
|
227
257
|
</div>
|
|
228
258
|
</div>
|
|
229
259
|
</div>
|
|
@@ -186,7 +186,7 @@ export const PHASE_MAP: Record<number, PhaseConfig> = {
|
|
|
186
186
|
textColor: 'text-gray-700',
|
|
187
187
|
},
|
|
188
188
|
1: {
|
|
189
|
-
label: '
|
|
189
|
+
label: 'Latent',
|
|
190
190
|
color: 'border-amber-500',
|
|
191
191
|
bgColor: 'bg-amber-500',
|
|
192
192
|
fromColor: 'from-amber-500',
|
|
@@ -202,7 +202,7 @@ export const PHASE_MAP: Record<number, PhaseConfig> = {
|
|
|
202
202
|
textColor: 'text-white',
|
|
203
203
|
},
|
|
204
204
|
3: {
|
|
205
|
-
label: '
|
|
205
|
+
label: 'Actief zoeken',
|
|
206
206
|
color: 'border-yellow-500',
|
|
207
207
|
bgColor: 'bg-yellow-500',
|
|
208
208
|
fromColor: 'from-yellow-500',
|