@nexxtmove/ui 1.2.5 → 1.2.7
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/components/ReferenceCard/ReferenceCard.vue.d.ts +1 -0
- package/dist/index.js +304 -257
- package/package.json +9 -9
- package/src/components/Calendar/_CalendarYearView.vue +1 -2
- package/src/components/ComboboxPanel/ComboboxPanel.vue +2 -6
- package/src/components/CountrySelect/CountrySelect.vue +1 -4
- package/src/components/ProgressBar/ProgressBar.vue +67 -13
- package/src/components/ReferenceCard/ReferenceCard.vue +18 -2
- package/tailwind/nexxtmove.tailwind.custom.css +39 -0
- package/tailwind/theme.css +10 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexxtmove/ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.7",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"./nuxt": "./dist/nuxt.js",
|
|
11
11
|
"./ui.css": "./dist/ui.css",
|
|
12
12
|
"./dist/ui.css": "./dist/ui.css",
|
|
13
|
-
"./theme": "./tailwind/
|
|
13
|
+
"./theme": "./tailwind/theme.css",
|
|
14
14
|
"./components.json": "./src/components.json",
|
|
15
15
|
"./components/*": "./src/components/*"
|
|
16
16
|
},
|
|
@@ -36,12 +36,12 @@
|
|
|
36
36
|
"@eslint/js": "^10.0.1",
|
|
37
37
|
"@nuxt/kit": "^4.5.2",
|
|
38
38
|
"@nuxt/schema": "^4.5.2",
|
|
39
|
-
"@storybook/addon-a11y": "^10.5.
|
|
39
|
+
"@storybook/addon-a11y": "^10.5.10",
|
|
40
40
|
"@storybook/addon-designs": "^11.1.4",
|
|
41
|
-
"@storybook/addon-docs": "^10.5.
|
|
42
|
-
"@storybook/addon-vitest": "^10.5.
|
|
43
|
-
"@storybook/builder-vite": "^10.5.
|
|
44
|
-
"@storybook/vue3-vite": "^10.5.
|
|
41
|
+
"@storybook/addon-docs": "^10.5.10",
|
|
42
|
+
"@storybook/addon-vitest": "^10.5.10",
|
|
43
|
+
"@storybook/builder-vite": "^10.5.10",
|
|
44
|
+
"@storybook/vue3-vite": "^10.5.10",
|
|
45
45
|
"@tailwindcss/vite": "^4.3.3",
|
|
46
46
|
"@types/node": "^26.2.0",
|
|
47
47
|
"@types/react": "^19.2.18",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"eslint": "^10.8.1",
|
|
56
56
|
"eslint-config-prettier": "^10.1.8",
|
|
57
57
|
"eslint-plugin-prettier": "^5.5.6",
|
|
58
|
-
"eslint-plugin-storybook": "10.5.
|
|
58
|
+
"eslint-plugin-storybook": "10.5.10",
|
|
59
59
|
"eslint-plugin-vue": "^10.10.0",
|
|
60
60
|
"flag-icons": "^7.5.0",
|
|
61
61
|
"globals": "^17.11.0",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"react": "^19.2.8",
|
|
66
66
|
"react-dom": "^19.2.8",
|
|
67
67
|
"remark-frontmatter": "^5.0.0",
|
|
68
|
-
"storybook": "^10.5.
|
|
68
|
+
"storybook": "^10.5.10",
|
|
69
69
|
"typescript-eslint": "^8.67.0",
|
|
70
70
|
"vite": "^8.2.1",
|
|
71
71
|
"vite-plugin-dts": "^5.0.3",
|
|
@@ -58,8 +58,7 @@ onMounted(async () => {
|
|
|
58
58
|
<!-- Scrollable drum -->
|
|
59
59
|
<div
|
|
60
60
|
ref="yearScrollerRef"
|
|
61
|
-
class="relative h-full snap-y snap-mandatory overflow-y-scroll
|
|
62
|
-
style="scrollbar-width: none"
|
|
61
|
+
class="relative scrollbar-none h-full snap-y snap-mandatory overflow-y-scroll"
|
|
63
62
|
>
|
|
64
63
|
<div class="h-18" />
|
|
65
64
|
<button
|
|
@@ -208,7 +208,7 @@ defineExpose({ focus })
|
|
|
208
208
|
role="listbox"
|
|
209
209
|
aria-multiselectable="true"
|
|
210
210
|
tabindex="0"
|
|
211
|
-
class="max-h-56 overflow-y-auto
|
|
211
|
+
class="scrollbar-thin max-h-56 overflow-y-auto"
|
|
212
212
|
>
|
|
213
213
|
<li
|
|
214
214
|
v-for="option in filteredOptions"
|
|
@@ -298,11 +298,7 @@ defineExpose({ focus })
|
|
|
298
298
|
</button>
|
|
299
299
|
</TransitionGroup>
|
|
300
300
|
</Transition>
|
|
301
|
-
<ul
|
|
302
|
-
role="listbox"
|
|
303
|
-
aria-multiselectable="true"
|
|
304
|
-
class="max-h-56 overflow-y-auto [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-cornflower-blue-200 [&::-webkit-scrollbar-thumb:hover]:bg-gray-300 [&::-webkit-scrollbar-track]:bg-transparent"
|
|
305
|
-
>
|
|
301
|
+
<ul role="listbox" aria-multiselectable="true" class="scrollbar-thin max-h-56 overflow-y-auto">
|
|
306
302
|
<li
|
|
307
303
|
v-for="option in filteredOptions"
|
|
308
304
|
:key="getValue(option)"
|
|
@@ -125,10 +125,7 @@ const onOpen = async () => {
|
|
|
125
125
|
placeholder="Zoeken..."
|
|
126
126
|
/>
|
|
127
127
|
</div>
|
|
128
|
-
<ul
|
|
129
|
-
role="listbox"
|
|
130
|
-
class="max-h-60 overflow-y-auto [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-cornflower-blue-200 [&::-webkit-scrollbar-thumb:hover]:bg-gray-300 [&::-webkit-scrollbar-track]:bg-transparent"
|
|
131
|
-
>
|
|
128
|
+
<ul role="listbox" class="scrollbar-thin max-h-60 overflow-y-auto">
|
|
132
129
|
<li
|
|
133
130
|
v-for="country in filteredCountries"
|
|
134
131
|
:key="country.code"
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, watchEffect } from 'vue'
|
|
3
3
|
import AnimatedNumber from '../AnimatedNumber/AnimatedNumber.vue'
|
|
4
|
+
import Icon from '../Icon/Icon.vue'
|
|
5
|
+
import FloatingPanel from '../FloatingPanel/FloatingPanel.vue'
|
|
4
6
|
|
|
5
7
|
interface NexxtProgressBarProps {
|
|
6
8
|
variant?: 'stepper' | 'percentage'
|
|
@@ -15,7 +17,7 @@ defineOptions({
|
|
|
15
17
|
name: 'NexxtProgressBar',
|
|
16
18
|
})
|
|
17
19
|
|
|
18
|
-
defineEmits(['update:currentStep'])
|
|
20
|
+
const emit = defineEmits(['update:currentStep'])
|
|
19
21
|
|
|
20
22
|
const {
|
|
21
23
|
variant = 'stepper',
|
|
@@ -55,6 +57,11 @@ const stepDigits = computed(() => String(Math.max(steps, 0)).length)
|
|
|
55
57
|
// the compact treatment (current title + "x/y" counter) at every breakpoint.
|
|
56
58
|
const isCompact = computed(() => hasTitles.value && (stepTitles?.length ?? 0) > maxInlineSteps)
|
|
57
59
|
|
|
60
|
+
const selectStep = (index: number, close: () => void) => {
|
|
61
|
+
close()
|
|
62
|
+
if (index < clampedStep.value) emit('update:currentStep', index)
|
|
63
|
+
}
|
|
64
|
+
|
|
58
65
|
watchEffect(() => {
|
|
59
66
|
if (stepTitles && stepTitles.length !== steps) {
|
|
60
67
|
console.warn(
|
|
@@ -110,10 +117,64 @@ watchEffect(() => {
|
|
|
110
117
|
<span>{{ steps }}</span>
|
|
111
118
|
</div>
|
|
112
119
|
</div>
|
|
120
|
+
<div v-if="isCompact" class="order-first flex justify-center">
|
|
121
|
+
<FloatingPanel placement="bottom">
|
|
122
|
+
<template #trigger="{ isOpen, toggle }">
|
|
123
|
+
<button
|
|
124
|
+
type="button"
|
|
125
|
+
class="flex cursor-pointer items-center gap-1.5 rounded-xs body-normal text-sapphire-500 transition-colors duration-200 hover:text-sapphire-400 focus-visible:outline-3"
|
|
126
|
+
aria-haspopup="menu"
|
|
127
|
+
:aria-expanded="isOpen"
|
|
128
|
+
:aria-label="`Stap ${displayStep} van ${steps}: ${stepTitles?.[clampedStep]}. Kies een stap`"
|
|
129
|
+
@click="toggle"
|
|
130
|
+
>
|
|
131
|
+
{{ stepTitles?.[clampedStep] }}
|
|
132
|
+
<Icon
|
|
133
|
+
name="chevron-down"
|
|
134
|
+
class="text-xs transition-transform duration-200"
|
|
135
|
+
:class="{ 'rotate-180': isOpen }"
|
|
136
|
+
aria-hidden="true"
|
|
137
|
+
/>
|
|
138
|
+
</button>
|
|
139
|
+
</template>
|
|
140
|
+
|
|
141
|
+
<template #content="{ close }">
|
|
142
|
+
<ol
|
|
143
|
+
role="menu"
|
|
144
|
+
class="scrollbar-thin max-h-72 min-w-52 overflow-y-auto rounded-lg border border-gray-200 bg-white py-1"
|
|
145
|
+
aria-label="Progress steps"
|
|
146
|
+
>
|
|
147
|
+
<li v-for="(title, index) in stepTitles" :key="title">
|
|
148
|
+
<button
|
|
149
|
+
type="button"
|
|
150
|
+
role="menuitem"
|
|
151
|
+
class="flex w-full items-center gap-2 p-3 text-left small-normal whitespace-nowrap transition-colors duration-200 focus:outline-none"
|
|
152
|
+
:class="
|
|
153
|
+
index > clampedStep
|
|
154
|
+
? 'cursor-default text-gray-400'
|
|
155
|
+
: 'cursor-pointer text-gray-700 hover:bg-gray-100 hover:text-sapphire-400 focus-visible:bg-gray-100'
|
|
156
|
+
"
|
|
157
|
+
:disabled="index > clampedStep"
|
|
158
|
+
:aria-current="index === clampedStep ? 'step' : undefined"
|
|
159
|
+
@click="selectStep(index, close)"
|
|
160
|
+
>
|
|
161
|
+
<span
|
|
162
|
+
class="w-(--step-number-width) shrink-0 text-right tabular-nums"
|
|
163
|
+
:style="{ '--step-number-width': `${stepDigits}ch` }"
|
|
164
|
+
aria-hidden="true"
|
|
165
|
+
>
|
|
166
|
+
{{ index + 1 }}
|
|
167
|
+
</span>
|
|
168
|
+
<span :class="index === clampedStep ? 'text-sapphire-500' : ''">{{ title }}</span>
|
|
169
|
+
</button>
|
|
170
|
+
</li>
|
|
171
|
+
</ol>
|
|
172
|
+
</template>
|
|
173
|
+
</FloatingPanel>
|
|
174
|
+
</div>
|
|
113
175
|
<ol
|
|
114
|
-
v-if="hasTitles"
|
|
115
|
-
class="flex @max-md:order-first"
|
|
116
|
-
:class="isCompact ? 'order-first justify-center' : 'justify-between @max-md:justify-center'"
|
|
176
|
+
v-else-if="hasTitles"
|
|
177
|
+
class="flex justify-between @max-md:order-first @max-md:justify-center"
|
|
117
178
|
aria-label="Progress steps"
|
|
118
179
|
>
|
|
119
180
|
<li
|
|
@@ -121,15 +182,8 @@ watchEffect(() => {
|
|
|
121
182
|
:key="title"
|
|
122
183
|
class="rounded-xs transition-colors duration-500 focus-visible:outline-3"
|
|
123
184
|
:class="[
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
? 'body-normal'
|
|
127
|
-
: 'hidden'
|
|
128
|
-
: [
|
|
129
|
-
'@max-md:body-normal @min-md:small-normal',
|
|
130
|
-
index === clampedStep ? '@max-md:inline' : '@max-md:hidden',
|
|
131
|
-
],
|
|
132
|
-
index === clampedStep ? 'text-sapphire-500' : '',
|
|
185
|
+
'@max-md:body-normal @min-md:small-normal',
|
|
186
|
+
index === clampedStep ? 'text-sapphire-500 @max-md:inline' : '@max-md:hidden',
|
|
133
187
|
index < clampedStep ? 'cursor-pointer duration-200! hover:text-sapphire-400' : '',
|
|
134
188
|
]"
|
|
135
189
|
:aria-current="index === clampedStep ? 'step' : undefined"
|
|
@@ -10,6 +10,7 @@ export interface ProposalReference {
|
|
|
10
10
|
postalCode: string
|
|
11
11
|
streetName: string
|
|
12
12
|
houseNumber: number
|
|
13
|
+
houseNumberExt?: string | number | null
|
|
13
14
|
houseType: string
|
|
14
15
|
city: string
|
|
15
16
|
mainImageUrl: string | null
|
|
@@ -65,7 +66,16 @@ const selected = defineModel<boolean>({ default: false })
|
|
|
65
66
|
|
|
66
67
|
defineEmits<{ details: [reference: ProposalReference] }>()
|
|
67
68
|
|
|
68
|
-
const
|
|
69
|
+
const formattedHouseNumberExtension = (value: string | number | null | undefined) => {
|
|
70
|
+
const extension = String(value ?? '').trim()
|
|
71
|
+
|
|
72
|
+
return extension ? (extension.startsWith('-') ? extension : `-${extension}`) : ''
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const address = computed(
|
|
76
|
+
() =>
|
|
77
|
+
`${reference.streetName} ${reference.houseNumber}${formattedHouseNumberExtension(reference.houseNumberExt)}`,
|
|
78
|
+
)
|
|
69
79
|
|
|
70
80
|
const location = computed(() => `${reference.postalCode} ${reference.city}`)
|
|
71
81
|
|
|
@@ -74,7 +84,13 @@ const energyLabel = computed(() => (reference.energyLabel ?? null) as EnergyLabe
|
|
|
74
84
|
const salePrice = computed(() => {
|
|
75
85
|
if (!reference.salePrice) return null
|
|
76
86
|
|
|
77
|
-
const
|
|
87
|
+
const normalized = String(reference.salePrice)
|
|
88
|
+
.replace(/[^\d,-]/g, '')
|
|
89
|
+
.replace(/\./g, '')
|
|
90
|
+
.replace(',', '.')
|
|
91
|
+
if (!normalized) return reference.salePrice
|
|
92
|
+
|
|
93
|
+
const amount = Number(normalized)
|
|
78
94
|
if (Number.isNaN(amount)) return reference.salePrice
|
|
79
95
|
|
|
80
96
|
return new Intl.NumberFormat(locale, {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hand-written utilities.
|
|
3
|
+
*
|
|
4
|
+
* The other files in this folder are generated by the Figma design-tokens
|
|
5
|
+
* plugin and get overwritten on every token sync, so anything we author by
|
|
6
|
+
* hand lives here. It is pulled in through `tailwind/theme.css`, the entry
|
|
7
|
+
* behind the `@nexxtmove/ui/theme` export.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/* Slim, branded scrollbar for scrollable panels (dropdowns, lists, drawers). */
|
|
11
|
+
@utility scrollbar-thin {
|
|
12
|
+
scrollbar-width: thin;
|
|
13
|
+
scrollbar-color: var(--color-cornflower-blue-200) transparent;
|
|
14
|
+
|
|
15
|
+
&::-webkit-scrollbar {
|
|
16
|
+
@apply h-1.5 w-1.5;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
&::-webkit-scrollbar-track {
|
|
20
|
+
@apply bg-transparent;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&::-webkit-scrollbar-thumb {
|
|
24
|
+
@apply rounded-full bg-cornflower-blue-200 transition-colors duration-200;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&::-webkit-scrollbar-thumb:hover {
|
|
28
|
+
@apply bg-gray-300;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Scrollable, but without a visible scrollbar. */
|
|
33
|
+
@utility scrollbar-none {
|
|
34
|
+
scrollbar-width: none;
|
|
35
|
+
|
|
36
|
+
&::-webkit-scrollbar {
|
|
37
|
+
display: none;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entry point behind the `@nexxtmove/ui/theme` export.
|
|
3
|
+
*
|
|
4
|
+
* Keep this file free of anything generated: `nexxtmove.tailwind.theme.css`
|
|
5
|
+
* (and the utilities/components it imports) is overwritten by the Figma
|
|
6
|
+
* design-tokens sync, so hand-written CSS belongs in the custom file below.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
@import './nexxtmove.tailwind.theme.css';
|
|
10
|
+
@import './nexxtmove.tailwind.custom.css';
|