@nexxtmove/ui 1.1.6 → 1.1.8
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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexxtmove/ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.8",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"@eslint/js": "^10.0.1",
|
|
35
35
|
"@nuxt/kit": "^4.4.8",
|
|
36
36
|
"@nuxt/schema": "^4.4.4",
|
|
37
|
-
"@storybook/addon-a11y": "^10.5.
|
|
37
|
+
"@storybook/addon-a11y": "^10.5.4",
|
|
38
38
|
"@storybook/addon-designs": "^11.1.4",
|
|
39
|
-
"@storybook/addon-docs": "^10.5.
|
|
40
|
-
"@storybook/addon-vitest": "^10.5.
|
|
41
|
-
"@storybook/builder-vite": "^10.5.
|
|
42
|
-
"@storybook/vue3-vite": "^10.5.
|
|
39
|
+
"@storybook/addon-docs": "^10.5.4",
|
|
40
|
+
"@storybook/addon-vitest": "^10.5.4",
|
|
41
|
+
"@storybook/builder-vite": "^10.5.4",
|
|
42
|
+
"@storybook/vue3-vite": "^10.5.4",
|
|
43
43
|
"@tailwindcss/vite": "^4.3.1",
|
|
44
44
|
"@types/node": "^26.0.1",
|
|
45
45
|
"@types/react": "^19.2.17",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"eslint": "^10.6.0",
|
|
54
54
|
"eslint-config-prettier": "^10.1.8",
|
|
55
55
|
"eslint-plugin-prettier": "^5.5.6",
|
|
56
|
-
"eslint-plugin-storybook": "10.5.
|
|
56
|
+
"eslint-plugin-storybook": "10.5.4",
|
|
57
57
|
"eslint-plugin-vue": "^10.9.2",
|
|
58
58
|
"flag-icons": "^7.5.0",
|
|
59
59
|
"globals": "^17.7.0",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"react": "^19.2.7",
|
|
64
64
|
"react-dom": "^19.2.7",
|
|
65
65
|
"remark-frontmatter": "^5.0.0",
|
|
66
|
-
"storybook": "^10.5.
|
|
66
|
+
"storybook": "^10.5.4",
|
|
67
67
|
"typescript-eslint": "^8.62.0",
|
|
68
68
|
"vite": "^8.1.0",
|
|
69
69
|
"vite-plugin-dts": "^5.0.3",
|
|
@@ -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"
|
|
@@ -3,10 +3,12 @@ import type { IconName } from '@awesome.me/kit-37b149f3ef/icons'
|
|
|
3
3
|
import Icon from '../Icon/Icon.vue'
|
|
4
4
|
|
|
5
5
|
type SwitchColor = 'blue' | 'green'
|
|
6
|
+
type SwitchSize = 'sm' | 'md' | 'lg'
|
|
6
7
|
|
|
7
8
|
interface NexxtSwitchProps {
|
|
8
9
|
labelPosition?: 'before' | 'after'
|
|
9
10
|
color?: SwitchColor
|
|
11
|
+
size?: SwitchSize
|
|
10
12
|
iconOn?: IconName
|
|
11
13
|
iconOff?: IconName
|
|
12
14
|
}
|
|
@@ -16,7 +18,13 @@ defineOptions({
|
|
|
16
18
|
inheritAttrs: false,
|
|
17
19
|
})
|
|
18
20
|
|
|
19
|
-
const {
|
|
21
|
+
const {
|
|
22
|
+
labelPosition = 'after',
|
|
23
|
+
color = 'blue',
|
|
24
|
+
size = 'lg',
|
|
25
|
+
iconOn,
|
|
26
|
+
iconOff,
|
|
27
|
+
} = defineProps<NexxtSwitchProps>()
|
|
20
28
|
|
|
21
29
|
const model = defineModel<boolean>()
|
|
22
30
|
|
|
@@ -24,12 +32,36 @@ const checkedColorClasses: Record<SwitchColor, string> = {
|
|
|
24
32
|
blue: 'border-cornflower-blue-500 bg-cornflower-blue-500',
|
|
25
33
|
green: 'border-green-400 bg-green-400',
|
|
26
34
|
}
|
|
35
|
+
|
|
36
|
+
const trackClasses: Record<SwitchSize, string> = {
|
|
37
|
+
sm: 'h-5 w-9',
|
|
38
|
+
md: 'h-6 w-11',
|
|
39
|
+
lg: 'h-8 w-15',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const knobClasses: Record<SwitchSize, string> = {
|
|
43
|
+
sm: 'top-0.5 left-0.5 h-3.5 w-3.5',
|
|
44
|
+
md: 'top-0.5 left-0.5 h-4.5 w-4.5',
|
|
45
|
+
lg: 'top-0.75 left-0.75 h-6 w-6',
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const knobTranslateClasses: Record<SwitchSize, string> = {
|
|
49
|
+
sm: 'translate-x-4',
|
|
50
|
+
md: 'translate-x-5',
|
|
51
|
+
lg: 'translate-x-7',
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const iconSizeClasses: Record<SwitchSize, string> = {
|
|
55
|
+
sm: 'text-[8px]',
|
|
56
|
+
md: 'text-[10px]',
|
|
57
|
+
lg: 'text-xs',
|
|
58
|
+
}
|
|
27
59
|
</script>
|
|
28
60
|
|
|
29
61
|
<template>
|
|
30
62
|
<label class="inline-flex cursor-pointer items-center gap-2">
|
|
31
63
|
<slot v-if="labelPosition === 'before'" />
|
|
32
|
-
<span class="relative inline-block
|
|
64
|
+
<span :class="['relative inline-block', trackClasses[size]]">
|
|
33
65
|
<input v-bind="$attrs" type="checkbox" class="peer sr-only" v-model="model" />
|
|
34
66
|
<span
|
|
35
67
|
:class="[
|
|
@@ -39,18 +71,29 @@ const checkedColorClasses: Record<SwitchColor, string> = {
|
|
|
39
71
|
>
|
|
40
72
|
<span
|
|
41
73
|
:class="[
|
|
42
|
-
'absolute
|
|
43
|
-
|
|
74
|
+
'absolute rounded-full bg-white transition-transform duration-400',
|
|
75
|
+
knobClasses[size],
|
|
76
|
+
model && knobTranslateClasses[size],
|
|
44
77
|
]"
|
|
45
78
|
/>
|
|
46
79
|
<span
|
|
47
80
|
:class="[
|
|
48
|
-
'absolute
|
|
49
|
-
|
|
81
|
+
'absolute flex items-center justify-center rounded-full bg-white transition-transform duration-300',
|
|
82
|
+
knobClasses[size],
|
|
83
|
+
model && knobTranslateClasses[size],
|
|
50
84
|
]"
|
|
51
85
|
>
|
|
52
|
-
<Icon
|
|
53
|
-
|
|
86
|
+
<Icon
|
|
87
|
+
v-if="model && iconOn"
|
|
88
|
+
:name="iconOn"
|
|
89
|
+
type="solid"
|
|
90
|
+
:class="['text-gray-600', iconSizeClasses[size]]"
|
|
91
|
+
/>
|
|
92
|
+
<Icon
|
|
93
|
+
v-else-if="!model && iconOff"
|
|
94
|
+
:name="iconOff"
|
|
95
|
+
:class="['text-gray-600', iconSizeClasses[size]]"
|
|
96
|
+
/>
|
|
54
97
|
</span>
|
|
55
98
|
</span>
|
|
56
99
|
</span>
|