@nuxt/ui 3.1.2 → 3.2.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/.nuxt/ui/avatar.ts +1 -1
- package/.nuxt/ui/card.ts +1 -1
- package/.nuxt/ui/carousel.ts +1 -1
- package/.nuxt/ui/checkbox-group.ts +1 -1
- package/.nuxt/ui/command-palette.ts +1 -0
- package/.nuxt/ui/context-menu.ts +2 -1
- package/.nuxt/ui/drawer.ts +1 -1
- package/.nuxt/ui/dropdown-menu.ts +2 -1
- package/.nuxt/ui/index.ts +2 -0
- package/.nuxt/ui/input-menu.ts +26 -12
- package/.nuxt/ui/input-tags.ts +310 -0
- package/.nuxt/ui/modal.ts +1 -1
- package/.nuxt/ui/navigation-menu.ts +43 -34
- package/.nuxt/ui/radio-group.ts +1 -1
- package/.nuxt/ui/select-menu.ts +13 -8
- package/.nuxt/ui/select.ts +13 -8
- package/.nuxt/ui/table.ts +3 -2
- package/.nuxt/ui/timeline.ts +321 -0
- package/.nuxt/ui/toaster.ts +1 -1
- package/.nuxt/ui/tooltip.ts +1 -1
- package/.nuxt/ui.css +4 -1
- package/cli/templates.mjs +7 -4
- package/dist/module.json +1 -1
- package/dist/module.mjs +2 -2
- package/dist/runtime/components/Alert.vue +0 -1
- package/dist/runtime/components/Avatar.vue +10 -2
- package/dist/runtime/components/Avatar.vue.d.ts +2 -0
- package/dist/runtime/components/Calendar.vue +4 -1
- package/dist/runtime/components/Carousel.vue +1 -2
- package/dist/runtime/components/Checkbox.vue +1 -1
- package/dist/runtime/components/CommandPalette.vue +80 -16
- package/dist/runtime/components/CommandPalette.vue.d.ts +32 -8
- package/dist/runtime/components/ContextMenuContent.vue +58 -56
- package/dist/runtime/components/ContextMenuContent.vue.d.ts +4 -20
- package/dist/runtime/components/Drawer.vue +15 -1
- package/dist/runtime/components/DropdownMenuContent.vue +60 -58
- package/dist/runtime/components/DropdownMenuContent.vue.d.ts +4 -20
- package/dist/runtime/components/Form.vue +6 -6
- package/dist/runtime/components/Form.vue.d.ts +12 -11
- package/dist/runtime/components/Input.vue +1 -0
- package/dist/runtime/components/Input.vue.d.ts +7 -0
- package/dist/runtime/components/InputMenu.vue +3 -3
- package/dist/runtime/components/InputMenu.vue.d.ts +4 -4
- package/dist/runtime/components/InputNumber.vue +3 -2
- package/dist/runtime/components/InputNumber.vue.d.ts +1 -1
- package/dist/runtime/components/InputTags.vue +159 -0
- package/dist/runtime/components/InputTags.vue.d.ts +183 -0
- package/dist/runtime/components/Modal.vue +16 -15
- package/dist/runtime/components/Modal.vue.d.ts +17 -4
- package/dist/runtime/components/NavigationMenu.vue +85 -26
- package/dist/runtime/components/NavigationMenu.vue.d.ts +30 -17
- package/dist/runtime/components/OverlayProvider.vue +2 -2
- package/dist/runtime/components/Pagination.vue +1 -1
- package/dist/runtime/components/Pagination.vue.d.ts +0 -1
- package/dist/runtime/components/PinInput.vue +4 -3
- package/dist/runtime/components/PinInput.vue.d.ts +22 -19
- package/dist/runtime/components/Popover.vue +4 -0
- package/dist/runtime/components/Popover.vue.d.ts +1 -0
- package/dist/runtime/components/Progress.vue +2 -1
- package/dist/runtime/components/Progress.vue.d.ts +1 -1
- package/dist/runtime/components/RadioGroup.vue +2 -2
- package/dist/runtime/components/Select.vue +26 -7
- package/dist/runtime/components/Select.vue.d.ts +107 -1
- package/dist/runtime/components/SelectMenu.vue +27 -8
- package/dist/runtime/components/SelectMenu.vue.d.ts +105 -1
- package/dist/runtime/components/Slideover.vue +23 -15
- package/dist/runtime/components/Slideover.vue.d.ts +17 -4
- package/dist/runtime/components/Table.vue +7 -1
- package/dist/runtime/components/Table.vue.d.ts +10 -8
- package/dist/runtime/components/Tabs.vue +13 -2
- package/dist/runtime/components/Tabs.vue.d.ts +4 -1
- package/dist/runtime/components/Textarea.vue +4 -1
- package/dist/runtime/components/Textarea.vue.d.ts +11 -4
- package/dist/runtime/components/Timeline.vue +92 -0
- package/dist/runtime/components/Timeline.vue.d.ts +70 -0
- package/dist/runtime/components/Toast.vue +4 -5
- package/dist/runtime/components/Tree.vue +3 -2
- package/dist/runtime/components/Tree.vue.d.ts +1 -1
- package/dist/runtime/composables/defineLocale.d.ts +2 -0
- package/dist/runtime/composables/defineLocale.js +4 -0
- package/dist/runtime/composables/defineShortcuts.js +2 -2
- package/dist/runtime/composables/useOverlay.d.ts +2 -1
- package/dist/runtime/composables/useOverlay.js +7 -6
- package/dist/runtime/locale/ar.js +2 -1
- package/dist/runtime/locale/az.js +2 -1
- package/dist/runtime/locale/bg.js +2 -1
- package/dist/runtime/locale/bn.js +2 -1
- package/dist/runtime/locale/ca.js +2 -1
- package/dist/runtime/locale/ckb.js +2 -1
- package/dist/runtime/locale/cs.js +2 -1
- package/dist/runtime/locale/da.js +2 -1
- package/dist/runtime/locale/de.js +2 -1
- package/dist/runtime/locale/el.js +2 -1
- package/dist/runtime/locale/en.js +2 -1
- package/dist/runtime/locale/es.js +2 -1
- package/dist/runtime/locale/et.js +2 -1
- package/dist/runtime/locale/fa_ir.js +2 -1
- package/dist/runtime/locale/fi.js +2 -1
- package/dist/runtime/locale/fr.js +2 -1
- package/dist/runtime/locale/he.js +2 -1
- package/dist/runtime/locale/hi.js +2 -1
- package/dist/runtime/locale/hu.js +2 -1
- package/dist/runtime/locale/hy.js +2 -1
- package/dist/runtime/locale/id.js +2 -1
- package/dist/runtime/locale/index.d.ts +7 -2
- package/dist/runtime/locale/index.js +7 -2
- package/dist/runtime/locale/it.js +2 -1
- package/dist/runtime/locale/ja.js +2 -1
- package/dist/runtime/locale/kk.js +2 -1
- package/dist/runtime/locale/km.js +2 -1
- package/dist/runtime/locale/ko.js +2 -1
- package/dist/runtime/locale/ky.d.ts +3 -0
- package/dist/runtime/locale/ky.js +55 -0
- package/dist/runtime/locale/lb.d.ts +3 -0
- package/dist/runtime/locale/lb.js +55 -0
- package/dist/runtime/locale/lt.d.ts +3 -0
- package/dist/runtime/locale/lt.js +55 -0
- package/dist/runtime/locale/mn.d.ts +3 -0
- package/dist/runtime/locale/mn.js +55 -0
- package/dist/runtime/locale/ms.d.ts +3 -0
- package/dist/runtime/locale/ms.js +55 -0
- package/dist/runtime/locale/nb_no.js +2 -1
- package/dist/runtime/locale/nl.js +2 -1
- package/dist/runtime/locale/pl.js +2 -1
- package/dist/runtime/locale/pt.js +2 -1
- package/dist/runtime/locale/pt_br.js +2 -1
- package/dist/runtime/locale/ro.js +2 -1
- package/dist/runtime/locale/ru.js +2 -1
- package/dist/runtime/locale/sk.js +2 -1
- package/dist/runtime/locale/sl.js +2 -1
- package/dist/runtime/locale/sv.js +2 -1
- package/dist/runtime/locale/th.js +2 -1
- package/dist/runtime/locale/tj.js +2 -1
- package/dist/runtime/locale/tr.js +2 -1
- package/dist/runtime/locale/ug_cn.js +2 -1
- package/dist/runtime/locale/uk.js +2 -1
- package/dist/runtime/locale/ur.js +2 -1
- package/dist/runtime/locale/uz.js +2 -1
- package/dist/runtime/locale/vi.js +2 -1
- package/dist/runtime/locale/zh_cn.js +2 -1
- package/dist/runtime/locale/zh_tw.js +2 -1
- package/dist/runtime/types/form.d.ts +11 -10
- package/dist/runtime/types/index.d.ts +2 -0
- package/dist/runtime/types/index.js +2 -0
- package/dist/runtime/types/locale.d.ts +1 -0
- package/dist/runtime/types/utils.d.ts +3 -0
- package/dist/shared/{ui.BvUP-pSb.mjs → ui.BPVxSPGY.mjs} +332 -62
- package/dist/unplugin.mjs +1 -1
- package/dist/vite.mjs +1 -1
- package/package.json +35 -36
package/.nuxt/ui.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
@source "./ui";
|
|
2
2
|
|
|
3
|
-
@theme
|
|
3
|
+
@theme static {
|
|
4
4
|
--color-old-neutral-50: oklch(98.5% 0 0);
|
|
5
5
|
--color-old-neutral-100: oklch(97% 0 0);
|
|
6
6
|
--color-old-neutral-200: oklch(92.2% 0 0);
|
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
--color-old-neutral-800: oklch(26.9% 0 0);
|
|
13
13
|
--color-old-neutral-900: oklch(20.5% 0 0);
|
|
14
14
|
--color-old-neutral-950: oklch(14.5% 0 0);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@theme default inline {
|
|
15
18
|
--color-primary-50: var(--ui-color-primary-50);
|
|
16
19
|
--color-primary-100: var(--ui-color-primary-100);
|
|
17
20
|
--color-primary-200: var(--ui-color-primary-200);
|
package/cli/templates.mjs
CHANGED
|
@@ -31,8 +31,9 @@ const component = ({ name, primitive, pro, prose, content }) => {
|
|
|
31
31
|
? `
|
|
32
32
|
<script lang="ts">
|
|
33
33
|
import type { AppConfig } from '@nuxt/schema'
|
|
34
|
+
${pro ? `import type { ComponentConfig } from '@nuxt/ui'` : ''}
|
|
34
35
|
import theme from '#build/${path}/${prose ? 'prose/' : ''}${content ? 'content/' : ''}${kebabName}'
|
|
35
|
-
import type { ComponentConfig } from '../types/utils'
|
|
36
|
+
${!pro ? `import type { ComponentConfig } from '../types/utils'` : ''}
|
|
36
37
|
|
|
37
38
|
type ${upperName} = ComponentConfig<typeof theme, AppConfig, ${upperName}${pro ? `, '${key}'` : ''}>
|
|
38
39
|
|
|
@@ -62,7 +63,7 @@ defineSlots<${upperName}Slots>()
|
|
|
62
63
|
|
|
63
64
|
const appConfig = useAppConfig() as ${upperName}['AppConfig']
|
|
64
65
|
|
|
65
|
-
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig
|
|
66
|
+
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.${pro ? 'uiPro' : 'ui'}?.${camelName} || {}) })())
|
|
66
67
|
</script>
|
|
67
68
|
|
|
68
69
|
<template>
|
|
@@ -75,8 +76,9 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.${camelName}
|
|
|
75
76
|
<script lang="ts">
|
|
76
77
|
import type { ${upperName}RootProps, ${upperName}RootEmits } from 'reka-ui'
|
|
77
78
|
import type { AppConfig } from '@nuxt/schema'
|
|
79
|
+
${pro ? `import type { ComponentConfig } from '@nuxt/ui'` : ''}
|
|
78
80
|
import theme from '#build/${path}/${prose ? 'prose/' : ''}${content ? 'content/' : ''}${kebabName}'
|
|
79
|
-
import type { ComponentConfig } from '../types/utils'
|
|
81
|
+
${!pro ? `import type { ComponentConfig } from '../types/utils'` : ''}
|
|
80
82
|
|
|
81
83
|
type ${upperName} = ComponentConfig<typeof theme, AppConfig, ${upperName}${pro ? `, '${key}'` : ''}>
|
|
82
84
|
|
|
@@ -105,7 +107,7 @@ const appConfig = useAppConfig() as ${upperName}['AppConfig']
|
|
|
105
107
|
|
|
106
108
|
const rootProps = useForwardPropsEmits(reactivePick(props), emits)
|
|
107
109
|
|
|
108
|
-
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig
|
|
110
|
+
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.${pro ? 'uiPro' : 'ui'}?.${camelName} || {}) })())
|
|
109
111
|
</script>
|
|
110
112
|
|
|
111
113
|
<template>
|
|
@@ -186,6 +188,7 @@ links:${primitive
|
|
|
186
188
|
- label: GitHub
|
|
187
189
|
icon: i-simple-icons-github
|
|
188
190
|
to: https://github.com/nuxt/${pro ? 'ui-pro' : 'ui'}/tree/v3/src/runtime/components/${upperName}.vue
|
|
191
|
+
navigation.badge: Soon
|
|
189
192
|
---
|
|
190
193
|
|
|
191
194
|
## Usage
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defu } from 'defu';
|
|
2
2
|
import { defineNuxtModule, createResolver, addVitePlugin, addPlugin, addComponentsDir, addImportsDir, hasNuxtModule, installModule } from '@nuxt/kit';
|
|
3
|
-
import { d as defaultOptions, r as resolveColors, a as getDefaultUiConfig, b as addTemplates } from './shared/ui.
|
|
3
|
+
import { d as defaultOptions, r as resolveColors, a as getDefaultUiConfig, b as addTemplates } from './shared/ui.BPVxSPGY.mjs';
|
|
4
4
|
import '../dist/runtime/utils/index.js';
|
|
5
5
|
import 'node:url';
|
|
6
6
|
import 'scule';
|
|
@@ -8,7 +8,7 @@ import 'tailwindcss/colors';
|
|
|
8
8
|
import 'knitwork';
|
|
9
9
|
|
|
10
10
|
const name = "@nuxt/ui";
|
|
11
|
-
const version = "3.
|
|
11
|
+
const version = "3.2.0";
|
|
12
12
|
|
|
13
13
|
const module = defineNuxtModule({
|
|
14
14
|
meta: {
|
|
@@ -10,6 +10,7 @@ import ImageComponent from "#build/ui-image-component";
|
|
|
10
10
|
import { useAvatarGroup } from "../composables/useAvatarGroup";
|
|
11
11
|
import { tv } from "../utils/tv";
|
|
12
12
|
import UIcon from "./Icon.vue";
|
|
13
|
+
import UChip from "./Chip.vue";
|
|
13
14
|
defineOptions({ inheritAttrs: false });
|
|
14
15
|
const props = defineProps({
|
|
15
16
|
as: { type: null, required: false, default: "span" },
|
|
@@ -18,6 +19,7 @@ const props = defineProps({
|
|
|
18
19
|
icon: { type: String, required: false },
|
|
19
20
|
text: { type: String, required: false },
|
|
20
21
|
size: { type: null, required: false },
|
|
22
|
+
chip: { type: [Boolean, Object], required: false },
|
|
21
23
|
class: { type: null, required: false },
|
|
22
24
|
style: { type: null, required: false },
|
|
23
25
|
ui: { type: null, required: false }
|
|
@@ -51,7 +53,13 @@ function onError() {
|
|
|
51
53
|
</script>
|
|
52
54
|
|
|
53
55
|
<template>
|
|
54
|
-
<
|
|
56
|
+
<component
|
|
57
|
+
:is="props.chip ? UChip : Primitive"
|
|
58
|
+
:as="as"
|
|
59
|
+
v-bind="props.chip ? typeof props.chip === 'object' ? { inset: true, ...props.chip } : { inset: true } : {}"
|
|
60
|
+
:class="ui.root({ class: [props.ui?.root, props.class] })"
|
|
61
|
+
:style="props.style"
|
|
62
|
+
>
|
|
55
63
|
<component
|
|
56
64
|
:is="ImageComponent"
|
|
57
65
|
v-if="src && !error"
|
|
@@ -71,5 +79,5 @@ function onError() {
|
|
|
71
79
|
<span v-else :class="ui.fallback({ class: props.ui?.fallback })">{{ fallback || "\xA0" }}</span>
|
|
72
80
|
</slot>
|
|
73
81
|
</Slot>
|
|
74
|
-
</
|
|
82
|
+
</component>
|
|
75
83
|
</template>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AppConfig } from '@nuxt/schema';
|
|
2
2
|
import theme from '#build/ui/avatar';
|
|
3
|
+
import type { ChipProps } from '../types';
|
|
3
4
|
import type { ComponentConfig } from '../types/utils';
|
|
4
5
|
type Avatar = ComponentConfig<typeof theme, AppConfig, 'avatar'>;
|
|
5
6
|
export interface AvatarProps {
|
|
@@ -19,6 +20,7 @@ export interface AvatarProps {
|
|
|
19
20
|
* @defaultValue 'md'
|
|
20
21
|
*/
|
|
21
22
|
size?: Avatar['variants']['size'];
|
|
23
|
+
chip?: boolean | ChipProps;
|
|
22
24
|
class?: any;
|
|
23
25
|
style?: any;
|
|
24
26
|
ui?: Avatar['slots'];
|
|
@@ -36,6 +36,7 @@ const props = defineProps({
|
|
|
36
36
|
allowNonContiguousRanges: { type: Boolean, required: false },
|
|
37
37
|
pagedNavigation: { type: Boolean, required: false },
|
|
38
38
|
preventDeselect: { type: Boolean, required: false },
|
|
39
|
+
maximumDays: { type: Number, required: false },
|
|
39
40
|
weekStartsOn: { type: Number, required: false },
|
|
40
41
|
weekdayFormat: { type: String, required: false },
|
|
41
42
|
fixedWeeks: { type: Boolean, required: false, default: true },
|
|
@@ -49,7 +50,9 @@ const props = defineProps({
|
|
|
49
50
|
isDateUnavailable: { type: Function, required: false },
|
|
50
51
|
isDateHighlightable: { type: Function, required: false },
|
|
51
52
|
nextPage: { type: Function, required: false },
|
|
52
|
-
prevPage: { type: Function, required: false }
|
|
53
|
+
prevPage: { type: Function, required: false },
|
|
54
|
+
disableDaysOutsideCurrentView: { type: Boolean, required: false },
|
|
55
|
+
fixedDate: { type: String, required: false }
|
|
53
56
|
});
|
|
54
57
|
const emits = defineEmits(["update:modelValue", "update:placeholder", "update:startValue"]);
|
|
55
58
|
defineSlots();
|
|
@@ -176,7 +176,6 @@ defineExpose({
|
|
|
176
176
|
<UButton
|
|
177
177
|
:disabled="!canScrollPrev"
|
|
178
178
|
:icon="prevIcon"
|
|
179
|
-
size="md"
|
|
180
179
|
color="neutral"
|
|
181
180
|
variant="outline"
|
|
182
181
|
:aria-label="t('carousel.prev')"
|
|
@@ -187,7 +186,6 @@ defineExpose({
|
|
|
187
186
|
<UButton
|
|
188
187
|
:disabled="!canScrollNext"
|
|
189
188
|
:icon="nextIcon"
|
|
190
|
-
size="md"
|
|
191
189
|
color="neutral"
|
|
192
190
|
variant="outline"
|
|
193
191
|
:aria-label="t('carousel.next')"
|
|
@@ -202,6 +200,7 @@ defineExpose({
|
|
|
202
200
|
<button
|
|
203
201
|
:aria-label="t('carousel.goto', { slide: index + 1 })"
|
|
204
202
|
:class="ui.dot({ class: props.ui?.dot, active: selectedIndex === index })"
|
|
203
|
+
:data-state="selectedIndex === index ? 'active' : void 0"
|
|
205
204
|
@click="scrollTo(index)"
|
|
206
205
|
/>
|
|
207
206
|
</template>
|
|
@@ -26,7 +26,7 @@ const props = defineProps({
|
|
|
26
26
|
disabled: { type: Boolean, required: false },
|
|
27
27
|
required: { type: Boolean, required: false },
|
|
28
28
|
name: { type: String, required: false },
|
|
29
|
-
value: { type:
|
|
29
|
+
value: { type: null, required: false },
|
|
30
30
|
id: { type: String, required: false },
|
|
31
31
|
defaultValue: { type: [Boolean, String], required: false }
|
|
32
32
|
});
|
|
@@ -3,7 +3,7 @@ import theme from "#build/ui/command-palette";
|
|
|
3
3
|
</script>
|
|
4
4
|
|
|
5
5
|
<script setup>
|
|
6
|
-
import { computed } from "vue";
|
|
6
|
+
import { computed, ref, useTemplateRef } from "vue";
|
|
7
7
|
import { ListboxRoot, ListboxFilter, ListboxContent, ListboxGroup, ListboxGroupLabel, ListboxItem, ListboxItemIndicator, useForwardProps, useForwardPropsEmits } from "reka-ui";
|
|
8
8
|
import { defu } from "defu";
|
|
9
9
|
import { reactivePick } from "@vueuse/core";
|
|
@@ -26,10 +26,13 @@ const props = defineProps({
|
|
|
26
26
|
as: { type: null, required: false },
|
|
27
27
|
icon: { type: String, required: false },
|
|
28
28
|
selectedIcon: { type: String, required: false },
|
|
29
|
+
trailingIcon: { type: String, required: false },
|
|
29
30
|
placeholder: { type: String, required: false },
|
|
30
31
|
autofocus: { type: Boolean, required: false, default: true },
|
|
31
32
|
close: { type: [Boolean, Object], required: false },
|
|
32
33
|
closeIcon: { type: String, required: false },
|
|
34
|
+
back: { type: [Boolean, Object], required: false, default: true },
|
|
35
|
+
backIcon: { type: String, required: false },
|
|
33
36
|
groups: { type: Array, required: false },
|
|
34
37
|
fuse: { type: Object, required: false },
|
|
35
38
|
labelKey: { type: String, required: false, default: "label" },
|
|
@@ -40,6 +43,7 @@ const props = defineProps({
|
|
|
40
43
|
modelValue: { type: null, required: false, default: "" },
|
|
41
44
|
defaultValue: { type: null, required: false },
|
|
42
45
|
highlightOnHover: { type: Boolean, required: false },
|
|
46
|
+
selectionBehavior: { type: String, required: false },
|
|
43
47
|
loading: { type: Boolean, required: false },
|
|
44
48
|
loadingIcon: { type: String, required: false }
|
|
45
49
|
});
|
|
@@ -48,7 +52,7 @@ const slots = defineSlots();
|
|
|
48
52
|
const searchTerm = defineModel("searchTerm", { type: String, ...{ default: "" } });
|
|
49
53
|
const { t } = useLocale();
|
|
50
54
|
const appConfig = useAppConfig();
|
|
51
|
-
const rootProps = useForwardPropsEmits(reactivePick(props, "as", "disabled", "multiple", "modelValue", "defaultValue", "highlightOnHover"), emits);
|
|
55
|
+
const rootProps = useForwardPropsEmits(reactivePick(props, "as", "disabled", "multiple", "modelValue", "defaultValue", "highlightOnHover", "selectionBehavior"), emits);
|
|
52
56
|
const inputProps = useForwardProps(reactivePick(props, "loading", "loadingIcon"));
|
|
53
57
|
const ui = computed(() => tv({ extend: tv(theme), ...appConfig.ui?.commandPalette || {} })());
|
|
54
58
|
const fuse = computed(() => defu({}, props.fuse, {
|
|
@@ -60,7 +64,10 @@ const fuse = computed(() => defu({}, props.fuse, {
|
|
|
60
64
|
resultLimit: 12,
|
|
61
65
|
matchAllWhenSearchEmpty: true
|
|
62
66
|
}));
|
|
63
|
-
const
|
|
67
|
+
const history = ref([]);
|
|
68
|
+
const placeholder = computed(() => history.value[history.value.length - 1]?.placeholder || props.placeholder || t("commandPalette.placeholder"));
|
|
69
|
+
const groups = computed(() => history.value?.length ? [history.value[history.value.length - 1]] : props.groups);
|
|
70
|
+
const items = computed(() => groups.value?.filter((group) => {
|
|
64
71
|
if (!group.id) {
|
|
65
72
|
console.warn(`[@nuxt/ui] CommandPalette group is missing an \`id\` property`);
|
|
66
73
|
return false;
|
|
@@ -69,7 +76,7 @@ const items = computed(() => props.groups?.filter((group) => {
|
|
|
69
76
|
return false;
|
|
70
77
|
}
|
|
71
78
|
return true;
|
|
72
|
-
})
|
|
79
|
+
})?.flatMap((group) => group.items?.map((item) => ({ ...item, group: group.id })) || []) || []);
|
|
73
80
|
const { results: fuseResults } = useFuse(searchTerm, items, fuse);
|
|
74
81
|
function getGroupWithItems(group, items2) {
|
|
75
82
|
if (group?.postFilter && typeof group.postFilter === "function") {
|
|
@@ -86,7 +93,7 @@ function getGroupWithItems(group, items2) {
|
|
|
86
93
|
})
|
|
87
94
|
};
|
|
88
95
|
}
|
|
89
|
-
const
|
|
96
|
+
const filteredGroups = computed(() => {
|
|
90
97
|
const groupsById = fuseResults.value.reduce((acc, result) => {
|
|
91
98
|
const { item, matches } = result;
|
|
92
99
|
if (!item.group) {
|
|
@@ -97,37 +104,87 @@ const groups = computed(() => {
|
|
|
97
104
|
return acc;
|
|
98
105
|
}, {});
|
|
99
106
|
const fuseGroups = Object.entries(groupsById).map(([id, items2]) => {
|
|
100
|
-
const group =
|
|
107
|
+
const group = groups.value?.find((group2) => group2.id === id);
|
|
101
108
|
if (!group) {
|
|
102
109
|
return;
|
|
103
110
|
}
|
|
104
111
|
return getGroupWithItems(group, items2);
|
|
105
112
|
}).filter((group) => !!group);
|
|
106
|
-
const nonFuseGroups =
|
|
113
|
+
const nonFuseGroups = groups.value?.map((group, index) => ({ ...group, index }))?.filter((group) => group.ignoreFilter && group.items?.length)?.map((group) => ({ ...getGroupWithItems(group, group.items || []), index: group.index })) || [];
|
|
107
114
|
return nonFuseGroups.reduce((acc, group) => {
|
|
108
115
|
acc.splice(group.index, 0, group);
|
|
109
116
|
return acc;
|
|
110
117
|
}, [...fuseGroups]);
|
|
111
118
|
});
|
|
119
|
+
const listboxRootRef = useTemplateRef("listboxRootRef");
|
|
120
|
+
function navigate(item) {
|
|
121
|
+
if (!item.children?.length) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
history.value.push({
|
|
125
|
+
id: `history-${history.value.length}`,
|
|
126
|
+
label: item.label,
|
|
127
|
+
slot: item.slot,
|
|
128
|
+
placeholder: item.placeholder,
|
|
129
|
+
items: item.children
|
|
130
|
+
});
|
|
131
|
+
searchTerm.value = "";
|
|
132
|
+
listboxRootRef.value?.highlightFirstItem();
|
|
133
|
+
}
|
|
134
|
+
function navigateBack() {
|
|
135
|
+
if (!history.value.length) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
history.value.pop();
|
|
139
|
+
searchTerm.value = "";
|
|
140
|
+
listboxRootRef.value?.highlightFirstItem();
|
|
141
|
+
}
|
|
142
|
+
function onBackspace() {
|
|
143
|
+
if (!searchTerm.value) {
|
|
144
|
+
navigateBack();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function onSelect(e, item) {
|
|
148
|
+
if (item.children?.length) {
|
|
149
|
+
e.preventDefault();
|
|
150
|
+
navigate(item);
|
|
151
|
+
} else {
|
|
152
|
+
item.onSelect?.(e);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
112
155
|
</script>
|
|
113
156
|
|
|
114
157
|
<template>
|
|
115
|
-
<ListboxRoot v-bind="rootProps" :class="ui.root({ class: [props.ui?.root, props.class] })">
|
|
158
|
+
<ListboxRoot v-bind="rootProps" ref="listboxRootRef" :class="ui.root({ class: [props.ui?.root, props.class] })">
|
|
116
159
|
<ListboxFilter v-model="searchTerm" as-child>
|
|
117
160
|
<UInput
|
|
118
|
-
:placeholder="placeholder
|
|
161
|
+
:placeholder="placeholder"
|
|
119
162
|
variant="none"
|
|
120
163
|
:autofocus="autofocus"
|
|
121
164
|
v-bind="inputProps"
|
|
122
165
|
:icon="icon || appConfig.ui.icons.search"
|
|
123
166
|
:class="ui.input({ class: props.ui?.input })"
|
|
167
|
+
@keydown.backspace="onBackspace"
|
|
124
168
|
>
|
|
169
|
+
<template v-if="history?.length && (back || !!slots.back)" #leading>
|
|
170
|
+
<slot name="back" :ui="ui">
|
|
171
|
+
<UButton
|
|
172
|
+
:icon="backIcon || appConfig.ui.icons.arrowLeft"
|
|
173
|
+
color="neutral"
|
|
174
|
+
variant="link"
|
|
175
|
+
:aria-label="t('commandPalette.back')"
|
|
176
|
+
v-bind="typeof back === 'object' ? back : {}"
|
|
177
|
+
:class="ui.back({ class: props.ui?.back })"
|
|
178
|
+
@click="navigateBack"
|
|
179
|
+
/>
|
|
180
|
+
</slot>
|
|
181
|
+
</template>
|
|
182
|
+
|
|
125
183
|
<template v-if="close || !!slots.close" #trailing>
|
|
126
184
|
<slot name="close" :ui="ui">
|
|
127
185
|
<UButton
|
|
128
186
|
v-if="close"
|
|
129
187
|
:icon="closeIcon || appConfig.ui.icons.close"
|
|
130
|
-
size="md"
|
|
131
188
|
color="neutral"
|
|
132
189
|
variant="ghost"
|
|
133
190
|
:aria-label="t('commandPalette.close')"
|
|
@@ -141,8 +198,8 @@ const groups = computed(() => {
|
|
|
141
198
|
</ListboxFilter>
|
|
142
199
|
|
|
143
200
|
<ListboxContent :class="ui.content({ class: props.ui?.content })">
|
|
144
|
-
<div v-if="
|
|
145
|
-
<ListboxGroup v-for="group in
|
|
201
|
+
<div v-if="filteredGroups?.length" role="presentation" :class="ui.viewport({ class: props.ui?.viewport })">
|
|
202
|
+
<ListboxGroup v-for="group in filteredGroups" :key="`group-${group.id}`" :class="ui.group({ class: props.ui?.group })">
|
|
146
203
|
<ListboxGroupLabel v-if="get(group, props.labelKey)" :class="ui.label({ class: props.ui?.label })">
|
|
147
204
|
{{ get(group, props.labelKey) }}
|
|
148
205
|
</ListboxGroupLabel>
|
|
@@ -150,10 +207,10 @@ const groups = computed(() => {
|
|
|
150
207
|
<ListboxItem
|
|
151
208
|
v-for="(item, index) in group.items"
|
|
152
209
|
:key="`group-${group.id}-${index}`"
|
|
153
|
-
:value="omit(item, ['matches', 'group', 'onSelect', 'labelHtml', 'suffixHtml'])"
|
|
210
|
+
:value="omit(item, ['matches', 'group', 'onSelect', 'labelHtml', 'suffixHtml', 'children'])"
|
|
154
211
|
:disabled="item.disabled"
|
|
155
212
|
as-child
|
|
156
|
-
@select="item
|
|
213
|
+
@select="onSelect($event, item)"
|
|
157
214
|
>
|
|
158
215
|
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
|
|
159
216
|
<ULinkBase v-bind="slotProps" :class="ui.item({ class: [props.ui?.item, item.ui?.item, item.class], active: active || item.active })">
|
|
@@ -184,13 +241,20 @@ const groups = computed(() => {
|
|
|
184
241
|
|
|
185
242
|
<span :class="ui.itemTrailing({ class: [props.ui?.itemTrailing, item.ui?.itemTrailing] })">
|
|
186
243
|
<slot :name="item.slot ? `${item.slot}-trailing` : group.slot ? `${group.slot}-trailing` : `item-trailing`" :item="item" :index="index">
|
|
187
|
-
<
|
|
244
|
+
<UIcon
|
|
245
|
+
v-if="item.children && item.children.length > 0"
|
|
246
|
+
:name="trailingIcon || appConfig.ui.icons.chevronRight"
|
|
247
|
+
:class="ui.itemTrailingIcon({ class: [props.ui?.itemTrailingIcon, item.ui?.itemTrailingIcon] })"
|
|
248
|
+
/>
|
|
249
|
+
|
|
250
|
+
<span v-else-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: [props.ui?.itemTrailingKbds, item.ui?.itemTrailingKbds] })">
|
|
188
251
|
<UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="item.ui?.itemTrailingKbdsSize || props.ui?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
|
|
189
252
|
</span>
|
|
253
|
+
|
|
190
254
|
<UIcon v-else-if="group.highlightedIcon" :name="group.highlightedIcon" :class="ui.itemTrailingHighlightedIcon({ class: [props.ui?.itemTrailingHighlightedIcon, item.ui?.itemTrailingHighlightedIcon] })" />
|
|
191
255
|
</slot>
|
|
192
256
|
|
|
193
|
-
<ListboxItemIndicator as-child>
|
|
257
|
+
<ListboxItemIndicator v-if="!item.children?.length" as-child>
|
|
194
258
|
<UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: [props.ui?.itemTrailingIcon, item.ui?.itemTrailingIcon] })" />
|
|
195
259
|
</ListboxItemIndicator>
|
|
196
260
|
</span>
|
|
@@ -21,12 +21,17 @@ export interface CommandPaletteItem extends Omit<LinkProps, 'type' | 'raw' | 'cu
|
|
|
21
21
|
loading?: boolean;
|
|
22
22
|
disabled?: boolean;
|
|
23
23
|
slot?: string;
|
|
24
|
+
/**
|
|
25
|
+
* The placeholder to display when the item has children.
|
|
26
|
+
*/
|
|
27
|
+
placeholder?: string;
|
|
28
|
+
children?: CommandPaletteItem[];
|
|
24
29
|
onSelect?(e?: Event): void;
|
|
25
30
|
class?: any;
|
|
26
31
|
ui?: Pick<CommandPalette['slots'], 'item' | 'itemLeadingIcon' | 'itemLeadingAvatarSize' | 'itemLeadingAvatar' | 'itemLeadingChipSize' | 'itemLeadingChip' | 'itemLabel' | 'itemLabelPrefix' | 'itemLabelBase' | 'itemLabelSuffix' | 'itemTrailing' | 'itemTrailingKbds' | 'itemTrailingKbdsSize' | 'itemTrailingHighlightedIcon' | 'itemTrailingIcon'>;
|
|
27
32
|
[key: string]: any;
|
|
28
33
|
}
|
|
29
|
-
export interface CommandPaletteGroup<T> {
|
|
34
|
+
export interface CommandPaletteGroup<T extends CommandPaletteItem = CommandPaletteItem> {
|
|
30
35
|
id: string;
|
|
31
36
|
label?: string;
|
|
32
37
|
slot?: string;
|
|
@@ -45,7 +50,7 @@ export interface CommandPaletteGroup<T> {
|
|
|
45
50
|
*/
|
|
46
51
|
highlightedIcon?: string;
|
|
47
52
|
}
|
|
48
|
-
export interface CommandPaletteProps<G
|
|
53
|
+
export interface CommandPaletteProps<G extends CommandPaletteGroup<T> = CommandPaletteGroup<any>, T extends CommandPaletteItem = CommandPaletteItem> extends Pick<ListboxRootProps, 'multiple' | 'disabled' | 'modelValue' | 'defaultValue' | 'highlightOnHover' | 'selectionBehavior'>, Pick<UseComponentIconsProps, 'loading' | 'loadingIcon'> {
|
|
49
54
|
/**
|
|
50
55
|
* The element or component this component should render as.
|
|
51
56
|
* @defaultValue 'div'
|
|
@@ -63,6 +68,12 @@ export interface CommandPaletteProps<G, T> extends Pick<ListboxRootProps, 'multi
|
|
|
63
68
|
* @IconifyIcon
|
|
64
69
|
*/
|
|
65
70
|
selectedIcon?: string;
|
|
71
|
+
/**
|
|
72
|
+
* The icon displayed when an item has children.
|
|
73
|
+
* @defaultValue appConfig.ui.icons.chevronRight
|
|
74
|
+
* @IconifyIcon
|
|
75
|
+
*/
|
|
76
|
+
trailingIcon?: string;
|
|
66
77
|
/**
|
|
67
78
|
* The placeholder text for the input.
|
|
68
79
|
* @defaultValue t('commandPalette.placeholder')
|
|
@@ -86,6 +97,18 @@ export interface CommandPaletteProps<G, T> extends Pick<ListboxRootProps, 'multi
|
|
|
86
97
|
* @IconifyIcon
|
|
87
98
|
*/
|
|
88
99
|
closeIcon?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Display a button to navigate back in history.
|
|
102
|
+
* `{ size: 'md', color: 'neutral', variant: 'link' }`{lang="ts-type"}
|
|
103
|
+
* @defaultValue true
|
|
104
|
+
*/
|
|
105
|
+
back?: boolean | ButtonProps;
|
|
106
|
+
/**
|
|
107
|
+
* The icon displayed in the back button.
|
|
108
|
+
* @defaultValue appConfig.ui.icons.arrowLeft
|
|
109
|
+
* @IconifyIcon
|
|
110
|
+
*/
|
|
111
|
+
backIcon?: string;
|
|
89
112
|
groups?: G[];
|
|
90
113
|
/**
|
|
91
114
|
* Options for [useFuse](https://vueuse.org/integrations/useFuse).
|
|
@@ -108,21 +131,22 @@ export interface CommandPaletteProps<G, T> extends Pick<ListboxRootProps, 'multi
|
|
|
108
131
|
class?: any;
|
|
109
132
|
ui?: CommandPalette['slots'];
|
|
110
133
|
}
|
|
111
|
-
export type CommandPaletteEmits<T> = ListboxRootEmits<T> & {
|
|
134
|
+
export type CommandPaletteEmits<T extends CommandPaletteItem = CommandPaletteItem> = ListboxRootEmits<T> & {
|
|
112
135
|
'update:open': [value: boolean];
|
|
113
136
|
};
|
|
114
137
|
type SlotProps<T> = (props: {
|
|
115
138
|
item: T;
|
|
116
139
|
index: number;
|
|
117
140
|
}) => any;
|
|
118
|
-
export type CommandPaletteSlots<G extends {
|
|
119
|
-
slot?: string;
|
|
120
|
-
}, T extends {
|
|
121
|
-
slot?: string;
|
|
122
|
-
}> = {
|
|
141
|
+
export type CommandPaletteSlots<G extends CommandPaletteGroup<T> = CommandPaletteGroup<any>, T extends CommandPaletteItem = CommandPaletteItem> = {
|
|
123
142
|
'empty'(props: {
|
|
124
143
|
searchTerm?: string;
|
|
125
144
|
}): any;
|
|
145
|
+
'back'(props: {
|
|
146
|
+
ui: {
|
|
147
|
+
[K in keyof Required<CommandPalette['slots']>]: (props?: Record<string, any>) => string;
|
|
148
|
+
};
|
|
149
|
+
}): any;
|
|
126
150
|
'close'(props: {
|
|
127
151
|
ui: {
|
|
128
152
|
[K in keyof Required<CommandPalette['slots']>]: (props?: Record<string, any>) => string;
|
|
@@ -91,68 +91,70 @@ const groups = computed(
|
|
|
91
91
|
<component :is="sub ? ContextMenu.SubContent : ContextMenu.Content" :class="props.class" v-bind="contentProps">
|
|
92
92
|
<slot name="content-top" />
|
|
93
93
|
|
|
94
|
-
<
|
|
95
|
-
<
|
|
96
|
-
<
|
|
97
|
-
<
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
<ContextMenu.
|
|
102
|
-
|
|
103
|
-
|
|
94
|
+
<div role="presentation" :class="ui.viewport({ class: props.ui?.viewport })">
|
|
95
|
+
<ContextMenu.Group v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: uiOverride?.group })">
|
|
96
|
+
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
|
97
|
+
<ContextMenu.Label v-if="item.type === 'label'" :class="ui.label({ class: [uiOverride?.label, item.ui?.label, item.class] })">
|
|
98
|
+
<ReuseItemTemplate :item="item" :index="index" />
|
|
99
|
+
</ContextMenu.Label>
|
|
100
|
+
<ContextMenu.Separator v-else-if="item.type === 'separator'" :class="ui.separator({ class: [uiOverride?.separator, item.ui?.separator, item.class] })" />
|
|
101
|
+
<ContextMenu.Sub v-else-if="item?.children?.length" :open="item.open" :default-open="item.defaultOpen">
|
|
102
|
+
<ContextMenu.SubTrigger
|
|
103
|
+
as="button"
|
|
104
|
+
type="button"
|
|
105
|
+
:disabled="item.disabled"
|
|
106
|
+
:text-value="get(item, props.labelKey)"
|
|
107
|
+
:class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], color: item?.color })"
|
|
108
|
+
>
|
|
109
|
+
<ReuseItemTemplate :item="item" :index="index" />
|
|
110
|
+
</ContextMenu.SubTrigger>
|
|
111
|
+
|
|
112
|
+
<UContextMenuContent
|
|
113
|
+
sub
|
|
114
|
+
:class="props.class"
|
|
115
|
+
:ui="ui"
|
|
116
|
+
:ui-override="uiOverride"
|
|
117
|
+
:portal="portal"
|
|
118
|
+
:items="item.children"
|
|
119
|
+
:align-offset="-4"
|
|
120
|
+
:label-key="labelKey"
|
|
121
|
+
:checked-icon="checkedIcon"
|
|
122
|
+
:loading-icon="loadingIcon"
|
|
123
|
+
:external-icon="externalIcon"
|
|
124
|
+
v-bind="item.content"
|
|
125
|
+
>
|
|
126
|
+
<template v-for="(_, name) in proxySlots" #[name]="slotData">
|
|
127
|
+
<slot :name="name" v-bind="slotData" />
|
|
128
|
+
</template>
|
|
129
|
+
</UContextMenuContent>
|
|
130
|
+
</ContextMenu.Sub>
|
|
131
|
+
<ContextMenu.CheckboxItem
|
|
132
|
+
v-else-if="item.type === 'checkbox'"
|
|
133
|
+
:model-value="item.checked"
|
|
104
134
|
:disabled="item.disabled"
|
|
105
135
|
:text-value="get(item, props.labelKey)"
|
|
106
136
|
:class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], color: item?.color })"
|
|
137
|
+
@update:model-value="item.onUpdateChecked"
|
|
138
|
+
@select="item.onSelect"
|
|
107
139
|
>
|
|
108
140
|
<ReuseItemTemplate :item="item" :index="index" />
|
|
109
|
-
</ContextMenu.
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
:
|
|
114
|
-
:
|
|
115
|
-
|
|
116
|
-
:portal="portal"
|
|
117
|
-
:items="item.children"
|
|
118
|
-
:align-offset="-4"
|
|
119
|
-
:label-key="labelKey"
|
|
120
|
-
:checked-icon="checkedIcon"
|
|
121
|
-
:loading-icon="loadingIcon"
|
|
122
|
-
:external-icon="externalIcon"
|
|
123
|
-
v-bind="item.content"
|
|
141
|
+
</ContextMenu.CheckboxItem>
|
|
142
|
+
<ContextMenu.Item
|
|
143
|
+
v-else
|
|
144
|
+
as-child
|
|
145
|
+
:disabled="item.disabled"
|
|
146
|
+
:text-value="get(item, props.labelKey)"
|
|
147
|
+
@select="item.onSelect"
|
|
124
148
|
>
|
|
125
|
-
<
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
:text-value="get(item, props.labelKey)"
|
|
135
|
-
:class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], color: item?.color })"
|
|
136
|
-
@update:model-value="item.onUpdateChecked"
|
|
137
|
-
@select="item.onSelect"
|
|
138
|
-
>
|
|
139
|
-
<ReuseItemTemplate :item="item" :index="index" />
|
|
140
|
-
</ContextMenu.CheckboxItem>
|
|
141
|
-
<ContextMenu.Item
|
|
142
|
-
v-else
|
|
143
|
-
as-child
|
|
144
|
-
:disabled="item.disabled"
|
|
145
|
-
:text-value="get(item, props.labelKey)"
|
|
146
|
-
@select="item.onSelect"
|
|
147
|
-
>
|
|
148
|
-
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
|
|
149
|
-
<ULinkBase v-bind="slotProps" :class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], active, color: item?.color })">
|
|
150
|
-
<ReuseItemTemplate :item="item" :active="active" :index="index" />
|
|
151
|
-
</ULinkBase>
|
|
152
|
-
</ULink>
|
|
153
|
-
</ContextMenu.Item>
|
|
154
|
-
</template>
|
|
155
|
-
</ContextMenu.Group>
|
|
149
|
+
<ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
|
|
150
|
+
<ULinkBase v-bind="slotProps" :class="ui.item({ class: [uiOverride?.item, item.ui?.item, item.class], active, color: item?.color })">
|
|
151
|
+
<ReuseItemTemplate :item="item" :active="active" :index="index" />
|
|
152
|
+
</ULinkBase>
|
|
153
|
+
</ULink>
|
|
154
|
+
</ContextMenu.Item>
|
|
155
|
+
</template>
|
|
156
|
+
</ContextMenu.Group>
|
|
157
|
+
</div>
|
|
156
158
|
|
|
157
159
|
<slot />
|
|
158
160
|
|