@nexxtmove/ui 0.1.46 → 0.1.48
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 +3 -0
- package/dist/index.js +1457 -1295
- package/dist/nuxt.js +25 -24
- package/package.json +9 -9
- package/src/components/Combobox/Combobox.vue +182 -0
- package/src/components.json +1 -0
- package/src/index.ts +1 -0
- package/tailwind/nexxtmove.tailwind.components.css +5 -1
- package/tailwind/nexxtmove.tailwind.theme.css +5 -1
package/dist/nuxt.js
CHANGED
|
@@ -1,31 +1,32 @@
|
|
|
1
1
|
import { defineNuxtModule as c, addComponent as s, addTemplate as a } from "@nuxt/kit";
|
|
2
|
-
const i = "components/AnimatedNumber/AnimatedNumber.vue",
|
|
2
|
+
const i = "components/AnimatedNumber/AnimatedNumber.vue", x = "components/Avatar/Avatar.vue", m = "components/Button/Button.vue", u = "components/Calendar/Calendar.vue", p = "components/Checkbox/Checkbox.vue", l = "components/Chip/Chip.vue", r = "components/Combobox/Combobox.vue", d = "components/CustomerJourneyTile/CustomerJourneyTile.vue", v = "components/DatePicker/DatePicker.vue", N = "components/DropdownButton/DropdownButton.vue", T = "components/Header/Header.vue", C = "components/Icon/Icon.vue", b = "components/InfoBlock/InfoBlock.vue", S = "components/InputField/InputField.vue", f = "components/Modal/Modal.vue", h = "components/Pagination/Pagination.vue", M = "components/ProgressBar/ProgressBar.vue", P = "components/SocialIcons/SocialIcons.vue", k = "components/SocialMediaCustomTemplate/SocialMediaCustomTemplate.vue", B = "components/SocialMediaTemplate/SocialMediaTemplate.vue", I = "components/SocialMediaType/SocialMediaType.vue", g = "components/StepperHeader/StepperHeader.vue", y = "components/Table/Table.vue", A = "components/TimelineEvent/TimelineEvent.vue", D = "components/TimelinePhaseblock/TimelinePhaseblock.vue", H = "components/Tooltip/Tooltip.vue", w = {
|
|
3
3
|
NexxtAnimatedNumber: i,
|
|
4
|
-
NexxtAvatar:
|
|
5
|
-
NexxtButton:
|
|
4
|
+
NexxtAvatar: x,
|
|
5
|
+
NexxtButton: m,
|
|
6
6
|
NexxtCalendar: u,
|
|
7
7
|
NexxtCheckbox: p,
|
|
8
8
|
NexxtChip: l,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
NexxtCombobox: r,
|
|
10
|
+
NexxtCustomerJourneyTile: d,
|
|
11
|
+
NexxtDatePicker: v,
|
|
12
|
+
NexxtDropdownButton: N,
|
|
13
|
+
NexxtHeader: T,
|
|
14
|
+
NexxtIcon: C,
|
|
15
|
+
NexxtInfoBlock: b,
|
|
15
16
|
NexxtInputField: S,
|
|
16
|
-
NexxtModal:
|
|
17
|
-
NexxtPagination:
|
|
18
|
-
NexxtProgressBar:
|
|
19
|
-
NexxtSocialIcons:
|
|
20
|
-
NexxtSocialMediaCustomTemplate:
|
|
21
|
-
NexxtSocialMediaTemplate:
|
|
22
|
-
NexxtSocialMediaType:
|
|
23
|
-
NexxtStepperHeader:
|
|
24
|
-
NexxtTable:
|
|
25
|
-
NexxtTimelineEvent:
|
|
26
|
-
NexxtTimelinePhaseblock:
|
|
27
|
-
NexxtTooltip:
|
|
28
|
-
},
|
|
17
|
+
NexxtModal: f,
|
|
18
|
+
NexxtPagination: h,
|
|
19
|
+
NexxtProgressBar: M,
|
|
20
|
+
NexxtSocialIcons: P,
|
|
21
|
+
NexxtSocialMediaCustomTemplate: k,
|
|
22
|
+
NexxtSocialMediaTemplate: B,
|
|
23
|
+
NexxtSocialMediaType: I,
|
|
24
|
+
NexxtStepperHeader: g,
|
|
25
|
+
NexxtTable: y,
|
|
26
|
+
NexxtTimelineEvent: A,
|
|
27
|
+
NexxtTimelinePhaseblock: D,
|
|
28
|
+
NexxtTooltip: H
|
|
29
|
+
}, F = c({
|
|
29
30
|
meta: {
|
|
30
31
|
name: "@nexxtmove/ui",
|
|
31
32
|
configKey: "nexxtmoveUi",
|
|
@@ -37,7 +38,7 @@ const i = "components/AnimatedNumber/AnimatedNumber.vue", m = "components/Avatar
|
|
|
37
38
|
addCSS: !0
|
|
38
39
|
},
|
|
39
40
|
setup(e, o) {
|
|
40
|
-
for (const [t, n] of Object.entries(
|
|
41
|
+
for (const [t, n] of Object.entries(w))
|
|
41
42
|
s({
|
|
42
43
|
name: t,
|
|
43
44
|
export: "default",
|
|
@@ -56,5 +57,5 @@ const i = "components/AnimatedNumber/AnimatedNumber.vue", m = "components/Avatar
|
|
|
56
57
|
}
|
|
57
58
|
});
|
|
58
59
|
export {
|
|
59
|
-
|
|
60
|
+
F as default
|
|
60
61
|
};
|
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.48",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"@eslint/js": "^9.39.2",
|
|
35
35
|
"@nuxt/kit": "^4.3.1",
|
|
36
36
|
"@nuxt/schema": "^4.3.1",
|
|
37
|
-
"@storybook/addon-a11y": "^10.3.
|
|
38
|
-
"@storybook/addon-designs": "^11.1.
|
|
39
|
-
"@storybook/addon-docs": "^10.3.
|
|
40
|
-
"@storybook/addon-vitest": "^10.3.
|
|
41
|
-
"@storybook/builder-vite": "^10.3.
|
|
42
|
-
"@storybook/vue3-vite": "^10.3.
|
|
37
|
+
"@storybook/addon-a11y": "^10.3.5",
|
|
38
|
+
"@storybook/addon-designs": "^11.1.3",
|
|
39
|
+
"@storybook/addon-docs": "^10.3.5",
|
|
40
|
+
"@storybook/addon-vitest": "^10.3.5",
|
|
41
|
+
"@storybook/builder-vite": "^10.3.5",
|
|
42
|
+
"@storybook/vue3-vite": "^10.3.5",
|
|
43
43
|
"@tailwindcss/vite": "^4.1.18",
|
|
44
44
|
"@types/node": "^25.0.3",
|
|
45
45
|
"@types/react": "^19.2.8",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"eslint": "^9.39.2",
|
|
54
54
|
"eslint-config-prettier": "^10.1.8",
|
|
55
55
|
"eslint-plugin-prettier": "^5.5.5",
|
|
56
|
-
"eslint-plugin-storybook": "10.3.
|
|
56
|
+
"eslint-plugin-storybook": "10.3.5",
|
|
57
57
|
"eslint-plugin-vue": "^10.6.2",
|
|
58
58
|
"globals": "^17.0.0",
|
|
59
59
|
"jsdom": "^28.1.0",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"react": "^19.2.3",
|
|
63
63
|
"react-dom": "^19.2.3",
|
|
64
64
|
"remark-frontmatter": "^5.0.0",
|
|
65
|
-
"storybook": "^10.3.
|
|
65
|
+
"storybook": "^10.3.5",
|
|
66
66
|
"typescript-eslint": "^8.52.0",
|
|
67
67
|
"vite": "^7.3.1",
|
|
68
68
|
"vite-plugin-dts": "^4.5.4",
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'
|
|
3
|
+
import NexxtButton from '../Button/Button.vue'
|
|
4
|
+
import NexxtChip from '../Chip/Chip.vue'
|
|
5
|
+
import NexxtIcon from '../Icon/Icon.vue'
|
|
6
|
+
import NexxtInputField from '../InputField/InputField.vue'
|
|
7
|
+
|
|
8
|
+
interface NexxtComboboxProps {
|
|
9
|
+
variant?: InstanceType<typeof NexxtButton>['variant']
|
|
10
|
+
icon?: InstanceType<typeof NexxtIcon>['name']
|
|
11
|
+
placeholder?: string
|
|
12
|
+
placement?: 'left' | 'right'
|
|
13
|
+
options: (string | { label: string; value: string | number })[]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const props = defineProps<NexxtComboboxProps>()
|
|
17
|
+
|
|
18
|
+
const {
|
|
19
|
+
variant = 'secondary',
|
|
20
|
+
placement = 'right',
|
|
21
|
+
icon = 'tag',
|
|
22
|
+
placeholder = 'Zoeken...',
|
|
23
|
+
} = props
|
|
24
|
+
|
|
25
|
+
const selected = defineModel<(string | number)[]>({ default: [] })
|
|
26
|
+
|
|
27
|
+
const isOpen = ref(false)
|
|
28
|
+
const inputFieldRef = ref<InstanceType<typeof NexxtInputField> | null>(null)
|
|
29
|
+
const wrapperRef = ref<HTMLElement | null>(null)
|
|
30
|
+
const search = ref('')
|
|
31
|
+
|
|
32
|
+
const getLabel = (option: string | { label: string; value: string | number }) =>
|
|
33
|
+
typeof option === 'string' ? option : option.label
|
|
34
|
+
|
|
35
|
+
const getValue = (option: string | { label: string; value: string | number }) =>
|
|
36
|
+
typeof option === 'string' ? option : option.value
|
|
37
|
+
|
|
38
|
+
const selectedLabels = computed(() =>
|
|
39
|
+
selected.value.map((val) => {
|
|
40
|
+
const match = props.options.find((o) => getValue(o) === val)
|
|
41
|
+
return { value: val, label: match ? getLabel(match) : String(val) }
|
|
42
|
+
}),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
const filteredOptions = computed(() => {
|
|
46
|
+
const q = search.value.toLowerCase()
|
|
47
|
+
return props.options
|
|
48
|
+
.filter((o) => !selected.value.includes(getValue(o)))
|
|
49
|
+
.filter((o) => getLabel(o).toLowerCase().includes(q))
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const selectOption = (option: string | { label: string; value: string | number }) => {
|
|
53
|
+
selected.value = [...selected.value, getValue(option)]
|
|
54
|
+
search.value = ''
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const removeSelected = (val: string | number) => {
|
|
58
|
+
selected.value = selected.value.filter((v) => v !== val)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
watch(isOpen, async (open) => {
|
|
62
|
+
if (open) {
|
|
63
|
+
await nextTick()
|
|
64
|
+
inputFieldRef.value?.$el.querySelector('input')?.focus()
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
69
|
+
if (wrapperRef.value && !wrapperRef.value.contains(event.target as Node)) {
|
|
70
|
+
isOpen.value = false
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const handleKeydown = (event: KeyboardEvent) => {
|
|
75
|
+
if (event.key === 'Escape' && isOpen.value) {
|
|
76
|
+
isOpen.value = false
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
onMounted(() => {
|
|
81
|
+
document.addEventListener('mousedown', handleClickOutside)
|
|
82
|
+
document.addEventListener('keydown', handleKeydown)
|
|
83
|
+
})
|
|
84
|
+
onUnmounted(() => {
|
|
85
|
+
document.removeEventListener('mousedown', handleClickOutside)
|
|
86
|
+
document.removeEventListener('keydown', handleKeydown)
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
const transitionClasses = computed(() => {
|
|
90
|
+
const origin = placement === 'right' ? 'origin-top-right' : 'origin-top-left'
|
|
91
|
+
return {
|
|
92
|
+
enterActiveClass: `transition-all duration-200 ease-out ${origin}`,
|
|
93
|
+
leaveActiveClass: `transition-all duration-150 ease-in ${origin}`,
|
|
94
|
+
enterFromClass: 'opacity-0 scale-95 -translate-y-3',
|
|
95
|
+
leaveToClass: 'opacity-0 scale-95 -translate-y-3',
|
|
96
|
+
enterToClass: 'opacity-100 scale-100 translate-y-0',
|
|
97
|
+
leaveFromClass: 'opacity-100 scale-100 translate-y-0',
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
</script>
|
|
101
|
+
|
|
102
|
+
<template>
|
|
103
|
+
<div ref="wrapperRef" class="relative">
|
|
104
|
+
<NexxtButton
|
|
105
|
+
:variant
|
|
106
|
+
:icon
|
|
107
|
+
:aria-expanded="isOpen"
|
|
108
|
+
aria-haspopup="listbox"
|
|
109
|
+
@click="isOpen = !isOpen"
|
|
110
|
+
>
|
|
111
|
+
<span class="flex gap-2"><slot>Combobox</slot><NexxtIcon name="chevron-down" /> </span>
|
|
112
|
+
</NexxtButton>
|
|
113
|
+
<Transition v-bind="transitionClasses">
|
|
114
|
+
<div
|
|
115
|
+
v-if="isOpen"
|
|
116
|
+
class="absolute top-full z-10 mt-2.5 min-w-80 rounded-md border border-gray-200 bg-white whitespace-nowrap"
|
|
117
|
+
:class="placement === 'right' ? 'right-0' : 'left-0'"
|
|
118
|
+
>
|
|
119
|
+
<div class="p-2">
|
|
120
|
+
<NexxtInputField
|
|
121
|
+
ref="inputFieldRef"
|
|
122
|
+
v-model="search"
|
|
123
|
+
class="w-full"
|
|
124
|
+
:left-icon="icon"
|
|
125
|
+
:placeholder
|
|
126
|
+
/>
|
|
127
|
+
</div>
|
|
128
|
+
<Transition
|
|
129
|
+
enter-active-class="transition-all duration-200 ease-out overflow-hidden"
|
|
130
|
+
enter-from-class="max-h-0 opacity-0"
|
|
131
|
+
enter-to-class="max-h-40 opacity-100"
|
|
132
|
+
leave-active-class="transition-all duration-150 ease-in overflow-hidden"
|
|
133
|
+
leave-from-class="max-h-40 opacity-100"
|
|
134
|
+
leave-to-class="max-h-0 opacity-0"
|
|
135
|
+
>
|
|
136
|
+
<TransitionGroup
|
|
137
|
+
v-if="selectedLabels.length > 0"
|
|
138
|
+
tag="div"
|
|
139
|
+
class="flex flex-wrap gap-1 border-b border-gray-200 p-2 pt-0"
|
|
140
|
+
enter-active-class="transition-all duration-150 ease-out"
|
|
141
|
+
enter-from-class="opacity-0 scale-75"
|
|
142
|
+
enter-to-class="opacity-100 scale-100"
|
|
143
|
+
leave-active-class="transition-all duration-100 ease-in"
|
|
144
|
+
leave-from-class="opacity-100 scale-100"
|
|
145
|
+
leave-to-class="opacity-0 scale-75"
|
|
146
|
+
>
|
|
147
|
+
<button
|
|
148
|
+
v-for="item in selectedLabels"
|
|
149
|
+
:key="item.value"
|
|
150
|
+
class="origin-left cursor-pointer"
|
|
151
|
+
:aria-label="`Verwijder ${item.label}`"
|
|
152
|
+
@click="removeSelected(item.value)"
|
|
153
|
+
>
|
|
154
|
+
<NexxtChip variant="ghost">
|
|
155
|
+
{{ item.label }}
|
|
156
|
+
<span>
|
|
157
|
+
<NexxtIcon name="xmark" class="text-xs" aria-hidden="true" />
|
|
158
|
+
</span>
|
|
159
|
+
</NexxtChip>
|
|
160
|
+
</button>
|
|
161
|
+
</TransitionGroup>
|
|
162
|
+
</Transition>
|
|
163
|
+
<ul
|
|
164
|
+
role="listbox"
|
|
165
|
+
aria-multiselectable="true"
|
|
166
|
+
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"
|
|
167
|
+
>
|
|
168
|
+
<li
|
|
169
|
+
v-for="option in filteredOptions"
|
|
170
|
+
:key="getValue(option)"
|
|
171
|
+
role="option"
|
|
172
|
+
aria-selected="false"
|
|
173
|
+
class="flex w-full min-w-42 cursor-pointer items-center gap-2 px-6 py-3 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"
|
|
174
|
+
@click="selectOption(option)"
|
|
175
|
+
>
|
|
176
|
+
{{ getLabel(option) }}
|
|
177
|
+
</li>
|
|
178
|
+
</ul>
|
|
179
|
+
</div>
|
|
180
|
+
</Transition>
|
|
181
|
+
</div>
|
|
182
|
+
</template>
|
package/src/components.json
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
"NexxtCalendar": "components/Calendar/Calendar.vue",
|
|
6
6
|
"NexxtCheckbox": "components/Checkbox/Checkbox.vue",
|
|
7
7
|
"NexxtChip": "components/Chip/Chip.vue",
|
|
8
|
+
"NexxtCombobox": "components/Combobox/Combobox.vue",
|
|
8
9
|
"NexxtCustomerJourneyTile": "components/CustomerJourneyTile/CustomerJourneyTile.vue",
|
|
9
10
|
"NexxtDatePicker": "components/DatePicker/DatePicker.vue",
|
|
10
11
|
"NexxtDropdownButton": "components/DropdownButton/DropdownButton.vue",
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { default as NexxtButton } from './components/Button/Button.vue'
|
|
|
5
5
|
export { default as NexxtCalendar } from './components/Calendar/Calendar.vue'
|
|
6
6
|
export { default as NexxtCheckbox } from './components/Checkbox/Checkbox.vue'
|
|
7
7
|
export { default as NexxtChip } from './components/Chip/Chip.vue'
|
|
8
|
+
export { default as NexxtCombobox } from './components/Combobox/Combobox.vue'
|
|
8
9
|
export { default as NexxtCustomerJourneyTile } from './components/CustomerJourneyTile/CustomerJourneyTile.vue'
|
|
9
10
|
export { default as NexxtDatePicker } from './components/DatePicker/DatePicker.vue'
|
|
10
11
|
export { default as NexxtDropdownButton } from './components/DropdownButton/DropdownButton.vue'
|
|
@@ -117,8 +117,12 @@
|
|
|
117
117
|
@apply bg-social-media-template-info-bg;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
.card-content {
|
|
121
|
+
@apply border-card-content-border px-(--card-content-padding-x) py-(--card-content-padding-y) border border-solid;
|
|
122
|
+
}
|
|
123
|
+
|
|
120
124
|
.card {
|
|
121
|
-
@apply
|
|
125
|
+
@apply bg-card-bg;
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
.info-block {
|
|
@@ -159,7 +159,8 @@
|
|
|
159
159
|
--color-progress-bar-border: var(--color-gray-200);
|
|
160
160
|
--color-header-border-bottom: var(--color-gray-200);
|
|
161
161
|
--color-social-media-template-info-bg: var(--color-cornflower-blue-500);
|
|
162
|
-
--color-card-border: var(--color-gray-200);
|
|
162
|
+
--color-card-content-border: var(--color-gray-200);
|
|
163
|
+
--color-card-bg: var(--color-white);
|
|
163
164
|
--text-xs: 0.75rem;
|
|
164
165
|
--text-base: 1rem;
|
|
165
166
|
--text-lg: 1.125rem;
|
|
@@ -228,6 +229,9 @@
|
|
|
228
229
|
--header-gap: var(--spacing-6);
|
|
229
230
|
--info-block-padding: var(--spacing-1);
|
|
230
231
|
--card-border-radius: var(--radius-lg);
|
|
232
|
+
--card-content-padding-x: var(--spacing-5);
|
|
233
|
+
--card-content-padding-y: var(--spacing-4);
|
|
234
|
+
--card-content-border-radius: var(--radius-lg);
|
|
231
235
|
--font-sans: 'Poppins', ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
232
236
|
--font-serif: 'Playfair Display', ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
|
|
233
237
|
--font-mono: 'Space Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|