@imaginario27/air-ui-ds 1.9.3 → 1.10.0
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/CHANGELOG.md +33 -0
- package/components/cards/CardTitle.vue +1 -1
- package/components/dropdowns/DropdownMenu.vue +18 -0
- package/components/dropdowns/DropdownMenuItem.vue +12 -0
- package/components/dropdowns/DropdownSelect.vue +8 -2
- package/components/layouts/headers/CompactHeader.vue +6 -0
- package/components/navigation/nav-menu/NavMenu.vue +5 -0
- package/components/navigation/nav-menu/NavMenuItem.vue +5 -1
- package/components/navigation/nav-sidebar/NavSidebar.vue +8 -0
- package/components/navigation/nav-sidebar/NavSidebarMenuItem.vue +12 -2
- package/components/tabs/Tab.vue +7 -1
- package/components/tabs/TabBar.vue +31 -2
- package/models/enums/prefetch.ts +4 -0
- package/models/types/dropdowns.ts +1 -0
- package/models/types/navigation.ts +1 -0
- package/models/types/prefetch.ts +6 -0
- package/models/types/tabs.ts +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,39 @@ All notable changes to this package are documented in this file.
|
|
|
5
5
|
Historical releases were reconstructed from git history (GitHub repository) and npm publish dates.
|
|
6
6
|
Future releases will include detailed entries generated with Changesets.
|
|
7
7
|
|
|
8
|
+
## 1.9.4 - 2026-04-06
|
|
9
|
+
|
|
10
|
+
Release type: patch.
|
|
11
|
+
Commits found in range: 1.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
1. fix CardTitle text color ([6a8807b](https://github.com/imaginario27/air-ui/commit/6a8807b9c4a3b22aa3f2b78eada1d8421ae9ed85))
|
|
16
|
+
|
|
17
|
+
- Package: @imaginario27/air-ui-ds.
|
|
18
|
+
|
|
19
|
+
## 1.9.3 - 2026-04-06
|
|
20
|
+
|
|
21
|
+
Release type: patch.
|
|
22
|
+
Commits found in range: 1.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
1. fix SelectField empty div with multiple option and badge stack ([041fd2d](https://github.com/imaginario27/air-ui/commit/041fd2df2eab1a17c83b51cc736d0d7ce591faf6))
|
|
27
|
+
|
|
28
|
+
- Package: @imaginario27/air-ui-ds.
|
|
29
|
+
|
|
30
|
+
## 1.9.2 - 2026-03-31
|
|
31
|
+
|
|
32
|
+
Release type: patch.
|
|
33
|
+
Commits found in range: 1.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
1. fix typecheck issues ([763c932](https://github.com/imaginario27/air-ui/commit/763c932692a380b5b172d1258dcbb38083a27fde))
|
|
38
|
+
|
|
39
|
+
- Package: @imaginario27/air-ui-ds.
|
|
40
|
+
|
|
8
41
|
## 1.9.1 - 2026-03-31
|
|
9
42
|
|
|
10
43
|
Release type: patch.
|
|
@@ -71,6 +71,8 @@
|
|
|
71
71
|
:to="item.to"
|
|
72
72
|
:isExternal="item.isExternal"
|
|
73
73
|
:hasSeparator="item.hasSeparator"
|
|
74
|
+
:disabled="disabled || item.disabled"
|
|
75
|
+
:prefetchOn
|
|
74
76
|
@click="handleClick(item.callback)"
|
|
75
77
|
/>
|
|
76
78
|
</template>
|
|
@@ -129,6 +131,8 @@
|
|
|
129
131
|
:to="item.to"
|
|
130
132
|
:isExternal="item.isExternal"
|
|
131
133
|
:hasSeparator="item.hasSeparator"
|
|
134
|
+
:disabled="disabled || item.disabled"
|
|
135
|
+
:prefetchOn
|
|
132
136
|
@click="handleClick(item.callback)"
|
|
133
137
|
/>
|
|
134
138
|
</template>
|
|
@@ -193,6 +197,14 @@ const props = defineProps({
|
|
|
193
197
|
default: Trigger.CLICK,
|
|
194
198
|
validator: (value: Trigger) => Object.values(Trigger).includes(value),
|
|
195
199
|
},
|
|
200
|
+
disabled: {
|
|
201
|
+
type: Boolean as PropType<boolean>,
|
|
202
|
+
default: false,
|
|
203
|
+
},
|
|
204
|
+
prefetchOn: {
|
|
205
|
+
type: [String, Object] as PropType<PrefetchOnStrategy>,
|
|
206
|
+
default: PrefetchOn.VISIBILITY,
|
|
207
|
+
},
|
|
196
208
|
})
|
|
197
209
|
|
|
198
210
|
// Refs
|
|
@@ -251,6 +263,8 @@ const getActivatorElement = () => {
|
|
|
251
263
|
}
|
|
252
264
|
|
|
253
265
|
const onActivatorClick = (event: MouseEvent) => {
|
|
266
|
+
if(props.disabled) return
|
|
267
|
+
|
|
254
268
|
if (props.trigger !== Trigger.CLICK) return
|
|
255
269
|
if (!activatorWrapper.value) return
|
|
256
270
|
|
|
@@ -260,6 +274,8 @@ const onActivatorClick = (event: MouseEvent) => {
|
|
|
260
274
|
}
|
|
261
275
|
|
|
262
276
|
const onActivatorMouseEnter = () => {
|
|
277
|
+
if(props.disabled) return
|
|
278
|
+
|
|
263
279
|
if (props.trigger !== Trigger.HOVER) return
|
|
264
280
|
|
|
265
281
|
clearCloseTimer()
|
|
@@ -267,6 +283,8 @@ const onActivatorMouseEnter = () => {
|
|
|
267
283
|
}
|
|
268
284
|
|
|
269
285
|
const onActivatorMouseLeave = () => {
|
|
286
|
+
if(props.disabled) return
|
|
287
|
+
|
|
270
288
|
if (props.trigger !== Trigger.HOVER) return
|
|
271
289
|
|
|
272
290
|
scheduleClose()
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
typeClass,
|
|
17
17
|
hasSeparator ? 'border-b border-border-default' : undefined,
|
|
18
18
|
helpText ? 'py-2' : undefined,
|
|
19
|
+
disabled && 'opacity-disabled cursor-not-allowed pointer-events-none',
|
|
19
20
|
]"
|
|
20
21
|
>
|
|
21
22
|
<div class="flex items-center gap-3 w-full">
|
|
@@ -120,6 +121,14 @@ const props = defineProps({
|
|
|
120
121
|
type: Boolean as PropType<boolean>,
|
|
121
122
|
default: false,
|
|
122
123
|
},
|
|
124
|
+
disabled: {
|
|
125
|
+
type: Boolean as PropType<boolean>,
|
|
126
|
+
default: false,
|
|
127
|
+
},
|
|
128
|
+
prefetchOn: {
|
|
129
|
+
type: [String, Object] as PropType<PrefetchOnStrategy>,
|
|
130
|
+
default: PrefetchOn.VISIBILITY,
|
|
131
|
+
},
|
|
123
132
|
})
|
|
124
133
|
|
|
125
134
|
// States
|
|
@@ -128,6 +137,8 @@ const isImageLoaded = ref(true)
|
|
|
128
137
|
// Emits
|
|
129
138
|
const emit = defineEmits(["click", "close"])
|
|
130
139
|
const emitClick = () => {
|
|
140
|
+
if (props.disabled) return
|
|
141
|
+
|
|
131
142
|
if (props.actionType === DropdownActionType.ACTION) {
|
|
132
143
|
emit("click")
|
|
133
144
|
emit("close")
|
|
@@ -196,6 +207,7 @@ const componentProps = computed(() => {
|
|
|
196
207
|
target: props.isExternal ? '_blank' : '_self',
|
|
197
208
|
rel: props.isExternal ? 'noopener noreferrer' : undefined,
|
|
198
209
|
external: props.isExternal,
|
|
210
|
+
prefetchOn: props.prefetchOn,
|
|
199
211
|
}
|
|
200
212
|
} else {
|
|
201
213
|
return {}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
:shouldTeleport="false"
|
|
7
7
|
:positionClass="`absolute ${dropdownPositionClass}`"
|
|
8
8
|
zIndex="10"
|
|
9
|
-
dropdownClass
|
|
9
|
+
:dropdownClass
|
|
10
10
|
:class="[
|
|
11
11
|
'max-h-[200px]',
|
|
12
12
|
'overflow-y-auto',
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
'p-2',
|
|
129
129
|
'sticky',
|
|
130
130
|
'top-0',
|
|
131
|
-
'bg-
|
|
131
|
+
'bg-background-container-surface',
|
|
132
132
|
'z-10'
|
|
133
133
|
]"
|
|
134
134
|
>
|
|
@@ -300,6 +300,12 @@ const dropdownPositionClass = computed(() => {
|
|
|
300
300
|
return positionVariant[props.dropdownPosition as Position] || 'top-full mt-1'
|
|
301
301
|
})
|
|
302
302
|
|
|
303
|
+
const dropdownClass = computed(() => {
|
|
304
|
+
const baseClass= 'max-w-full'
|
|
305
|
+
|
|
306
|
+
return props.filterable? `${baseClass} pt-0!` : baseClass
|
|
307
|
+
})
|
|
308
|
+
|
|
303
309
|
// States
|
|
304
310
|
const isImageLoaded = ref(true)
|
|
305
311
|
const selected = ref<SelectOption[] | SelectOption | null>(props.multiple ? [] : null)
|
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
:submenuYOffset
|
|
68
68
|
:submenuDropdownClass
|
|
69
69
|
:submenuTrigger
|
|
70
|
+
:prefetchOn
|
|
70
71
|
:class="navMenuClass"
|
|
71
72
|
/>
|
|
72
73
|
|
|
@@ -103,6 +104,7 @@
|
|
|
103
104
|
:to="item.to"
|
|
104
105
|
:isExternal="item.isExternal"
|
|
105
106
|
:actionType="item.actionType"
|
|
107
|
+
:prefetchOn
|
|
106
108
|
@click="item.callback"
|
|
107
109
|
/>
|
|
108
110
|
</template>
|
|
@@ -224,6 +226,10 @@ const props = defineProps({
|
|
|
224
226
|
type: Boolean,
|
|
225
227
|
default: true,
|
|
226
228
|
},
|
|
229
|
+
prefetchOn: {
|
|
230
|
+
type: [String, Object] as PropType<PrefetchOnStrategy>,
|
|
231
|
+
default: PrefetchOn.VISIBILITY,
|
|
232
|
+
},
|
|
227
233
|
navMenuClass: {
|
|
228
234
|
type: String as PropType<string>,
|
|
229
235
|
default: 'hidden lg:flex'
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
:text="item.text"
|
|
44
44
|
:to="item.to"
|
|
45
45
|
:detectActive="props.detectActive"
|
|
46
|
+
:prefetchOn
|
|
46
47
|
/>
|
|
47
48
|
</template>
|
|
48
49
|
</nav>
|
|
@@ -84,6 +85,10 @@ const props = defineProps({
|
|
|
84
85
|
default: Trigger.CLICK,
|
|
85
86
|
validator: (value: Trigger) => Object.values(Trigger).includes(value),
|
|
86
87
|
},
|
|
88
|
+
prefetchOn: {
|
|
89
|
+
type: [String, Object] as PropType<PrefetchOnStrategy>,
|
|
90
|
+
default: PrefetchOn.VISIBILITY,
|
|
91
|
+
},
|
|
87
92
|
})
|
|
88
93
|
|
|
89
94
|
// Composables
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<NuxtLink :to="
|
|
2
|
+
<NuxtLink :to :prefetch-on="prefetchOn">
|
|
3
3
|
<span
|
|
4
4
|
:class="[
|
|
5
5
|
'font-medium',
|
|
@@ -28,6 +28,10 @@ const props = defineProps({
|
|
|
28
28
|
type: Boolean,
|
|
29
29
|
default: true,
|
|
30
30
|
},
|
|
31
|
+
prefetchOn: {
|
|
32
|
+
type: [String, Object] as PropType<PrefetchOnStrategy>,
|
|
33
|
+
default: PrefetchOn.VISIBILITY,
|
|
34
|
+
},
|
|
31
35
|
})
|
|
32
36
|
|
|
33
37
|
// Composables
|
|
@@ -125,6 +125,8 @@
|
|
|
125
125
|
:text="item.text"
|
|
126
126
|
:icon="item.icon"
|
|
127
127
|
:to="item.to"
|
|
128
|
+
:disabled="item.disabled"
|
|
129
|
+
:prefetchOn
|
|
128
130
|
:styleType="itemsStyleType"
|
|
129
131
|
:textClass="itemsTextClass"
|
|
130
132
|
:iconClass="itemsIconClass"
|
|
@@ -143,6 +145,8 @@
|
|
|
143
145
|
:text="child.text"
|
|
144
146
|
:icon="child.icon"
|
|
145
147
|
:to="child.to"
|
|
148
|
+
:disabled="child.disabled"
|
|
149
|
+
:prefetchOn
|
|
146
150
|
:styleType="itemsStyleType"
|
|
147
151
|
:textClass="subItemsTextClass"
|
|
148
152
|
:iconClass="subItemsIconClass"
|
|
@@ -320,6 +324,10 @@ const props = defineProps({
|
|
|
320
324
|
subItemsCustomClass: String as PropType<string>,
|
|
321
325
|
subItemsTextClass: String as PropType<string>,
|
|
322
326
|
subItemsIconClass: String as PropType<string>,
|
|
327
|
+
prefetchOn: {
|
|
328
|
+
type: [String, Object] as PropType<PrefetchOnStrategy>,
|
|
329
|
+
default: PrefetchOn.VISIBILITY,
|
|
330
|
+
},
|
|
323
331
|
})
|
|
324
332
|
|
|
325
333
|
// States
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
'flex',
|
|
7
7
|
'items-center',
|
|
8
8
|
'text-sm',
|
|
9
|
+
'text-left',
|
|
9
10
|
'font-semibold',
|
|
10
11
|
'rounded-lg',
|
|
11
12
|
'hover:bg-background-neutral-hover',
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
spacingClass,
|
|
14
15
|
!isActive && 'text-text-default',
|
|
15
16
|
isActive && 'text-text-primary-brand-on-neutral-hover-bg bg-background-neutral-hover',
|
|
17
|
+
disabled && 'opacity-disabled cursor-not-allowed pointer-events-none',
|
|
16
18
|
]"
|
|
17
19
|
@click="$emit('click')"
|
|
18
20
|
>
|
|
@@ -32,7 +34,7 @@
|
|
|
32
34
|
|
|
33
35
|
<span
|
|
34
36
|
v-if="!isCollapsed"
|
|
35
|
-
:class="textClass"
|
|
37
|
+
:class="[disabled && 'select-none', textClass]"
|
|
36
38
|
>
|
|
37
39
|
{{ text }}
|
|
38
40
|
</span>
|
|
@@ -82,6 +84,14 @@ const props = defineProps({
|
|
|
82
84
|
},
|
|
83
85
|
textClass: String as PropType<string>,
|
|
84
86
|
iconClass: String as PropType<string>,
|
|
87
|
+
disabled: {
|
|
88
|
+
type: Boolean as PropType<boolean>,
|
|
89
|
+
default: false,
|
|
90
|
+
},
|
|
91
|
+
prefetchOn: {
|
|
92
|
+
type: [String, Object] as PropType<PrefetchOnStrategy>,
|
|
93
|
+
default: PrefetchOn.VISIBILITY,
|
|
94
|
+
},
|
|
85
95
|
})
|
|
86
96
|
|
|
87
97
|
// Emits
|
|
@@ -147,7 +157,7 @@ const componentTag = computed(() => {
|
|
|
147
157
|
|
|
148
158
|
const componentProps = computed(() => {
|
|
149
159
|
if (props.to) {
|
|
150
|
-
return { to: props.to }
|
|
160
|
+
return { to: props.to, prefetchOn: props.prefetchOn }
|
|
151
161
|
}
|
|
152
162
|
|
|
153
163
|
return { type: 'button' }
|
package/components/tabs/Tab.vue
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
'px-3',
|
|
8
8
|
'hover:cursor-pointer',
|
|
9
9
|
'group',
|
|
10
|
-
|
|
10
|
+
disabled && 'opacity-disabled cursor-not-allowed pointer-events-none',
|
|
11
|
+
styleClass,
|
|
11
12
|
]"
|
|
12
13
|
>
|
|
13
14
|
<Icon
|
|
@@ -36,6 +37,7 @@
|
|
|
36
37
|
:class="[
|
|
37
38
|
'text-sm',
|
|
38
39
|
'font-semibold',
|
|
40
|
+
disabled && 'select-none',
|
|
39
41
|
]"
|
|
40
42
|
>
|
|
41
43
|
{{ text }}
|
|
@@ -88,6 +90,10 @@ const props = defineProps({
|
|
|
88
90
|
default: false,
|
|
89
91
|
},
|
|
90
92
|
badgeValue: [String, Number] as PropType<string | number>,
|
|
93
|
+
disabled: {
|
|
94
|
+
type: Boolean as PropType<boolean>,
|
|
95
|
+
default: false,
|
|
96
|
+
},
|
|
91
97
|
})
|
|
92
98
|
|
|
93
99
|
// States
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
hasContainer && 'border border-border-default',
|
|
6
6
|
hasContainer && containerStyleClass,
|
|
7
7
|
hasContainer && isContainerFullWidth && 'w-full',
|
|
8
|
+
disabled && 'opacity-disabled cursor-not-allowed pointer-events-none',
|
|
8
9
|
]"
|
|
9
10
|
>
|
|
10
11
|
<Tab
|
|
@@ -15,10 +16,13 @@
|
|
|
15
16
|
:imgUrl="tab.imgUrl"
|
|
16
17
|
:badgeValue="tab.badgeValue"
|
|
17
18
|
:active="index === activeIndex"
|
|
19
|
+
:disabled="disabled || tab.disabled"
|
|
18
20
|
:tabStyle
|
|
19
21
|
:size="tabSize"
|
|
20
22
|
:decoration
|
|
21
23
|
@click="handleTabClick(index, tab.to)"
|
|
24
|
+
@pointerenter="handleTabPrefetch(tab.to)"
|
|
25
|
+
@focus="handleTabPrefetch(tab.to)"
|
|
22
26
|
/>
|
|
23
27
|
</div>
|
|
24
28
|
</template>
|
|
@@ -59,6 +63,14 @@ const props = defineProps({
|
|
|
59
63
|
type: Boolean as PropType<boolean>,
|
|
60
64
|
default: false,
|
|
61
65
|
},
|
|
66
|
+
disabled: {
|
|
67
|
+
type: Boolean as PropType<boolean>,
|
|
68
|
+
default: false,
|
|
69
|
+
},
|
|
70
|
+
prefetchOn: {
|
|
71
|
+
type: [String, Object] as PropType<PrefetchOnStrategy>,
|
|
72
|
+
default: PrefetchOn.VISIBILITY,
|
|
73
|
+
},
|
|
62
74
|
})
|
|
63
75
|
|
|
64
76
|
// Local
|
|
@@ -69,7 +81,7 @@ const emit = defineEmits(['update:modelValue'])
|
|
|
69
81
|
|
|
70
82
|
// Methods
|
|
71
83
|
const handleTabClick = (index: number, to?: string) => {
|
|
72
|
-
if(to) {
|
|
84
|
+
if(to) {
|
|
73
85
|
navigateTo(to)
|
|
74
86
|
return
|
|
75
87
|
}
|
|
@@ -78,6 +90,24 @@ const handleTabClick = (index: number, to?: string) => {
|
|
|
78
90
|
emit('update:modelValue', index)
|
|
79
91
|
}
|
|
80
92
|
|
|
93
|
+
const shouldPrefetchOn = (trigger: PrefetchOn): boolean => {
|
|
94
|
+
if (typeof props.prefetchOn === 'string') {
|
|
95
|
+
return props.prefetchOn === trigger
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return trigger === PrefetchOn.VISIBILITY
|
|
99
|
+
? !!props.prefetchOn?.visibility
|
|
100
|
+
: !!props.prefetchOn?.interaction
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const handleTabPrefetch = (to?: string) => {
|
|
104
|
+
if (!to) return
|
|
105
|
+
|
|
106
|
+
if (!shouldPrefetchOn(PrefetchOn.INTERACTION)) return
|
|
107
|
+
|
|
108
|
+
// fire and forget — do not await to avoid blocking
|
|
109
|
+
preloadRouteComponents(to)
|
|
110
|
+
}
|
|
81
111
|
// Watchers
|
|
82
112
|
watch(() => props.modelValue, (newVal) => {
|
|
83
113
|
activeIndex.value = newVal
|
|
@@ -93,5 +123,4 @@ const containerStyleClass = computed(() => {
|
|
|
93
123
|
|
|
94
124
|
return variant[props.tabSize as TabSize] || "p-4 rounded-md"
|
|
95
125
|
})
|
|
96
|
-
|
|
97
126
|
</script>
|
package/models/types/tabs.ts
CHANGED