@nexxtmove/ui 1.1.5 → 1.1.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/ProgressBar/ProgressBar.vue.d.ts +1 -0
- package/dist/components/ReferenceCard/ReferenceCard.vue.d.ts +4 -3
- package/dist/index.js +273 -240
- package/package.json +1 -1
- package/src/components/ProgressBar/ProgressBar.vue +29 -6
- package/src/components/ReferenceCard/ReferenceCard.vue +52 -19
package/package.json
CHANGED
|
@@ -8,6 +8,7 @@ interface NexxtProgressBarProps {
|
|
|
8
8
|
currentStep: number
|
|
9
9
|
progressLabel?: string
|
|
10
10
|
stepTitles?: string[]
|
|
11
|
+
maxInlineSteps?: number
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
defineOptions({
|
|
@@ -22,6 +23,7 @@ const {
|
|
|
22
23
|
stepTitles,
|
|
23
24
|
steps,
|
|
24
25
|
currentStep,
|
|
26
|
+
maxInlineSteps = 7,
|
|
25
27
|
} = defineProps<NexxtProgressBarProps>()
|
|
26
28
|
|
|
27
29
|
const isPercentage = computed(() => variant === 'percentage')
|
|
@@ -45,6 +47,14 @@ const percentage = computed(() => {
|
|
|
45
47
|
|
|
46
48
|
const hasTitles = computed(() => !isPercentage.value && Boolean(stepTitles?.length))
|
|
47
49
|
|
|
50
|
+
// Reserve the current-step number at the width of the total, so a 9 -> 10
|
|
51
|
+
// transition doesn't shift the "/x" that follows it.
|
|
52
|
+
const stepDigits = computed(() => String(Math.max(steps, 0)).length)
|
|
53
|
+
|
|
54
|
+
// When there are more titles than can comfortably fit side by side, fall back to
|
|
55
|
+
// the compact treatment (current title + "x/y" counter) at every breakpoint.
|
|
56
|
+
const isCompact = computed(() => hasTitles.value && (stepTitles?.length ?? 0) > maxInlineSteps)
|
|
57
|
+
|
|
48
58
|
watchEffect(() => {
|
|
49
59
|
if (stepTitles && stepTitles.length !== steps) {
|
|
50
60
|
console.warn(
|
|
@@ -89,24 +99,37 @@ watchEffect(() => {
|
|
|
89
99
|
</div>
|
|
90
100
|
<div
|
|
91
101
|
v-if="hasTitles"
|
|
92
|
-
class="flex items-center small-normal tabular-nums
|
|
102
|
+
class="flex items-center gap-0.5 small-normal tabular-nums"
|
|
103
|
+
:class="isCompact ? '' : '@md:hidden'"
|
|
93
104
|
aria-hidden="true"
|
|
94
105
|
>
|
|
95
|
-
<
|
|
96
|
-
|
|
106
|
+
<span class="flex justify-end" :style="{ minWidth: `${stepDigits}ch` }">
|
|
107
|
+
<AnimatedNumber :value="displayStep" />
|
|
108
|
+
</span>
|
|
109
|
+
<span>/</span>
|
|
110
|
+
<span>{{ steps }}</span>
|
|
97
111
|
</div>
|
|
98
112
|
</div>
|
|
99
113
|
<ol
|
|
100
114
|
v-if="hasTitles"
|
|
101
|
-
class="flex
|
|
115
|
+
class="flex @max-md:order-first"
|
|
116
|
+
:class="isCompact ? 'order-first justify-center' : 'justify-between @max-md:justify-center'"
|
|
102
117
|
aria-label="Progress steps"
|
|
103
118
|
>
|
|
104
119
|
<li
|
|
105
120
|
v-for="(title, index) in stepTitles"
|
|
106
121
|
:key="title"
|
|
107
|
-
class="rounded-xs transition-colors duration-500 focus-visible:outline-3
|
|
122
|
+
class="rounded-xs transition-colors duration-500 focus-visible:outline-3"
|
|
108
123
|
:class="[
|
|
109
|
-
|
|
124
|
+
isCompact
|
|
125
|
+
? index === clampedStep
|
|
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' : '',
|
|
110
133
|
index < clampedStep ? 'cursor-pointer duration-200! hover:text-sapphire-400' : '',
|
|
111
134
|
]"
|
|
112
135
|
:aria-current="index === clampedStep ? 'step' : undefined"
|
|
@@ -31,22 +31,36 @@ export interface ProposalReference {
|
|
|
31
31
|
pricePerSquareMeter: string | null
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
export type NexxtReferenceCardMessage = 'selected' | 'unselected' | 'details' | 'energyLabel'
|
|
35
|
+
|
|
34
36
|
export interface NexxtReferenceCardProps {
|
|
35
37
|
reference: ProposalReference
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
messages?: Partial<Record<NexxtReferenceCardMessage, string>>
|
|
39
|
+
locale?: string
|
|
40
|
+
currency?: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const DEFAULT_MESSAGES: Record<NexxtReferenceCardMessage, string> = {
|
|
44
|
+
selected: 'Meegenomen in advies',
|
|
45
|
+
unselected: 'Selecteer deze woning',
|
|
46
|
+
details: 'Meer details',
|
|
47
|
+
energyLabel: 'Energielabel',
|
|
39
48
|
}
|
|
40
49
|
|
|
41
50
|
defineOptions({ name: 'NexxtReferenceCard' })
|
|
42
51
|
|
|
43
52
|
const {
|
|
44
53
|
reference,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
54
|
+
messages = {},
|
|
55
|
+
locale = 'nl-NL',
|
|
56
|
+
currency = 'EUR',
|
|
48
57
|
} = defineProps<NexxtReferenceCardProps>()
|
|
49
58
|
|
|
59
|
+
const label = computed<Record<NexxtReferenceCardMessage, string>>(() => ({
|
|
60
|
+
...DEFAULT_MESSAGES,
|
|
61
|
+
...messages,
|
|
62
|
+
}))
|
|
63
|
+
|
|
50
64
|
const selected = defineModel<boolean>({ default: false })
|
|
51
65
|
|
|
52
66
|
defineEmits<{ details: [reference: ProposalReference] }>()
|
|
@@ -57,6 +71,19 @@ const location = computed(() => `${reference.postalCode} ${reference.city}`)
|
|
|
57
71
|
|
|
58
72
|
const energyLabel = computed(() => (reference.energyLabel ?? null) as EnergyLabelLetter | null)
|
|
59
73
|
|
|
74
|
+
const salePrice = computed(() => {
|
|
75
|
+
if (!reference.salePrice) return null
|
|
76
|
+
|
|
77
|
+
const amount = Number(reference.salePrice)
|
|
78
|
+
if (Number.isNaN(amount)) return reference.salePrice
|
|
79
|
+
|
|
80
|
+
return new Intl.NumberFormat(locale, {
|
|
81
|
+
style: 'currency',
|
|
82
|
+
currency,
|
|
83
|
+
maximumFractionDigits: 0,
|
|
84
|
+
}).format(amount)
|
|
85
|
+
})
|
|
86
|
+
|
|
60
87
|
const saleDate = computed(() => {
|
|
61
88
|
if (!reference.saleDate) return null
|
|
62
89
|
|
|
@@ -80,7 +107,9 @@ const saleDate = computed(() => {
|
|
|
80
107
|
:class="[
|
|
81
108
|
'@container flex w-full cursor-pointer flex-col overflow-hidden rounded-lg border transition-colors duration-200',
|
|
82
109
|
'focus-visible:ring-2 focus-visible:ring-cornflower-blue-400 focus-visible:ring-offset-2 focus-visible:outline-none',
|
|
83
|
-
selected
|
|
110
|
+
selected
|
|
111
|
+
? 'border-cornflower-blue-500 hover:border-cornflower-blue-600'
|
|
112
|
+
: 'border-gray-200 hover:border-cornflower-blue-300',
|
|
84
113
|
]"
|
|
85
114
|
@click="selected = !selected"
|
|
86
115
|
@keydown.space.prevent="selected = !selected"
|
|
@@ -88,16 +117,16 @@ const saleDate = computed(() => {
|
|
|
88
117
|
>
|
|
89
118
|
<div class="flex flex-col items-stretch bg-white @lg:flex-row">
|
|
90
119
|
<div
|
|
91
|
-
class="relative h-40 w-full self-stretch overflow-hidden bg-gray-100 @lg:h-auto @lg:w-48 @lg:shrink-0"
|
|
120
|
+
class="relative h-40 w-full self-stretch overflow-hidden bg-gray-100 @lg:h-auto @lg:min-h-32 @lg:w-48 @lg:shrink-0"
|
|
92
121
|
>
|
|
93
122
|
<img
|
|
94
123
|
v-if="reference.mainImageUrl"
|
|
95
124
|
:src="reference.mainImageUrl"
|
|
96
125
|
:alt="address"
|
|
97
126
|
loading="lazy"
|
|
98
|
-
class="
|
|
127
|
+
class="absolute inset-0 size-full object-cover"
|
|
99
128
|
/>
|
|
100
|
-
<div v-else class="
|
|
129
|
+
<div v-else class="absolute inset-0 flex items-center justify-center">
|
|
101
130
|
<NexxtIcon name="house" class="text-4xl text-gray-500" />
|
|
102
131
|
</div>
|
|
103
132
|
</div>
|
|
@@ -107,25 +136,25 @@ const saleDate = computed(() => {
|
|
|
107
136
|
>
|
|
108
137
|
<p class="truncate heading-4">{{ address }}</p>
|
|
109
138
|
<p class="truncate body-normal text-gray-800">{{ location }}</p>
|
|
110
|
-
<div v-if="energyLabel" class="flex items-center justify-between gap-2">
|
|
111
|
-
<span class="
|
|
139
|
+
<div v-if="energyLabel" class="mt-2 flex items-center justify-between gap-2">
|
|
140
|
+
<span class="small-normal text-gray-700">{{ label.energyLabel }}</span>
|
|
112
141
|
<NexxtEnergyLabel :label="energyLabel" />
|
|
113
142
|
</div>
|
|
114
143
|
</div>
|
|
115
144
|
|
|
116
145
|
<div
|
|
146
|
+
v-if="salePrice"
|
|
117
147
|
class="flex flex-col justify-center gap-1 border-t border-gray-200 p-4 text-left @lg:min-w-56 @lg:shrink-0 @lg:border-t-0 @lg:border-l"
|
|
118
148
|
>
|
|
119
|
-
<p
|
|
120
|
-
{{ reference.salePrice }}
|
|
121
|
-
</p>
|
|
149
|
+
<p class="heading-4 whitespace-nowrap">{{ salePrice }}</p>
|
|
122
150
|
<p v-if="saleDate" class="body-normal text-gray-800">{{ saleDate }}</p>
|
|
123
151
|
</div>
|
|
124
152
|
</div>
|
|
125
153
|
|
|
126
154
|
<div
|
|
127
155
|
:class="[
|
|
128
|
-
'flex flex-
|
|
156
|
+
'flex flex-col-reverse gap-3 border-t px-4 py-3',
|
|
157
|
+
'@lg:flex-row @lg:flex-wrap @lg:items-center @lg:justify-between @lg:gap-x-4 @lg:gap-y-2 @lg:py-2',
|
|
129
158
|
selected
|
|
130
159
|
? 'border-cornflower-blue-500 bg-cornflower-blue-50'
|
|
131
160
|
: 'border-gray-200 bg-gray-50',
|
|
@@ -134,12 +163,16 @@ const saleDate = computed(() => {
|
|
|
134
163
|
<div aria-hidden="true" class="pointer-events-none flex min-w-0 items-center gap-3">
|
|
135
164
|
<NexxtCheckbox :model-value="selected" tabindex="-1" />
|
|
136
165
|
<span class="truncate body-normal">
|
|
137
|
-
{{ selected ?
|
|
166
|
+
{{ selected ? label.selected : label.unselected }}
|
|
138
167
|
</span>
|
|
139
168
|
</div>
|
|
140
169
|
|
|
141
|
-
<NexxtButton
|
|
142
|
-
|
|
170
|
+
<NexxtButton
|
|
171
|
+
variant="secondary"
|
|
172
|
+
class="w-full @lg:w-auto"
|
|
173
|
+
@click.stop="$emit('details', reference)"
|
|
174
|
+
>
|
|
175
|
+
{{ label.details }}
|
|
143
176
|
</NexxtButton>
|
|
144
177
|
</div>
|
|
145
178
|
</div>
|