@nuxt/ui 3.0.1 → 3.1.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.
Files changed (228) hide show
  1. package/.nuxt/ui/accordion.ts +25 -4
  2. package/.nuxt/ui/alert.ts +52 -31
  3. package/.nuxt/ui/avatar-group.ts +24 -3
  4. package/.nuxt/ui/avatar.ts +26 -5
  5. package/.nuxt/ui/badge.ts +56 -35
  6. package/.nuxt/ui/breadcrumb.ts +28 -7
  7. package/.nuxt/ui/button-group.ts +23 -2
  8. package/.nuxt/ui/button.ts +66 -45
  9. package/.nuxt/ui/calendar.ts +39 -18
  10. package/.nuxt/ui/card.ts +28 -7
  11. package/.nuxt/ui/carousel.ts +29 -8
  12. package/.nuxt/ui/checkbox-group.ts +82 -0
  13. package/.nuxt/ui/checkbox.ts +163 -29
  14. package/.nuxt/ui/chip.ts +31 -10
  15. package/.nuxt/ui/collapsible.ts +23 -2
  16. package/.nuxt/ui/color-picker.ts +26 -5
  17. package/.nuxt/ui/command-palette.ts +37 -16
  18. package/.nuxt/ui/container.ts +24 -3
  19. package/.nuxt/ui/context-menu.ts +56 -35
  20. package/.nuxt/ui/drawer.ts +33 -12
  21. package/.nuxt/ui/dropdown-menu.ts +57 -36
  22. package/.nuxt/ui/form-field.ts +29 -8
  23. package/.nuxt/ui/form.ts +23 -2
  24. package/.nuxt/ui/index.ts +1 -0
  25. package/.nuxt/ui/input-menu.ts +65 -44
  26. package/.nuxt/ui/input-number.ts +43 -22
  27. package/.nuxt/ui/input.ts +46 -25
  28. package/.nuxt/ui/kbd.ts +27 -6
  29. package/.nuxt/ui/link.ts +26 -5
  30. package/.nuxt/ui/modal.ts +28 -7
  31. package/.nuxt/ui/navigation-menu.ts +103 -84
  32. package/.nuxt/ui/pagination.ts +23 -2
  33. package/.nuxt/ui/pin-input.ts +43 -22
  34. package/.nuxt/ui/popover.ts +25 -4
  35. package/.nuxt/ui/progress.ts +40 -19
  36. package/.nuxt/ui/radio-group.ts +273 -37
  37. package/.nuxt/ui/select-menu.ts +59 -35
  38. package/.nuxt/ui/select.ts +55 -34
  39. package/.nuxt/ui/separator.ts +31 -10
  40. package/.nuxt/ui/skeleton.ts +24 -3
  41. package/.nuxt/ui/slideover.ts +27 -6
  42. package/.nuxt/ui/slider.ts +39 -18
  43. package/.nuxt/ui/stepper.ts +41 -20
  44. package/.nuxt/ui/switch.ts +44 -23
  45. package/.nuxt/ui/table.ts +38 -17
  46. package/.nuxt/ui/tabs.ts +55 -34
  47. package/.nuxt/ui/textarea.ts +63 -37
  48. package/.nuxt/ui/toast.ts +47 -26
  49. package/.nuxt/ui/toaster.ts +23 -2
  50. package/.nuxt/ui/tooltip.ts +25 -4
  51. package/.nuxt/ui/tree.ts +41 -20
  52. package/.nuxt/ui.css +56 -12
  53. package/README.md +11 -0
  54. package/cli/templates.mjs +18 -17
  55. package/dist/module.d.mts +2 -1
  56. package/dist/module.json +5 -5
  57. package/dist/module.mjs +11 -7
  58. package/dist/runtime/components/Accordion.vue +36 -92
  59. package/dist/runtime/components/Accordion.vue.d.ts +91 -0
  60. package/dist/runtime/components/Alert.vue +37 -100
  61. package/dist/runtime/components/Alert.vue.d.ts +96 -0
  62. package/dist/runtime/components/App.vue +28 -34
  63. package/dist/runtime/components/App.vue.d.ts +24 -0
  64. package/dist/runtime/components/Avatar.vue +47 -78
  65. package/dist/runtime/components/Avatar.vue.d.ts +60 -0
  66. package/dist/runtime/components/AvatarGroup.vue +40 -77
  67. package/dist/runtime/components/AvatarGroup.vue.d.ts +40 -0
  68. package/dist/runtime/components/Badge.vue +33 -62
  69. package/dist/runtime/components/Badge.vue.d.ts +62 -0
  70. package/dist/runtime/components/Breadcrumb.vue +36 -88
  71. package/dist/runtime/components/Breadcrumb.vue.d.ts +82 -0
  72. package/dist/runtime/components/Button.vue +96 -105
  73. package/dist/runtime/components/Button.vue.d.ts +73 -0
  74. package/dist/runtime/components/ButtonGroup.vue +20 -46
  75. package/dist/runtime/components/ButtonGroup.vue.d.ts +55 -0
  76. package/dist/runtime/components/Calendar.vue +73 -127
  77. package/dist/runtime/components/Calendar.vue.d.ts +107 -0
  78. package/dist/runtime/components/Card.vue +18 -40
  79. package/dist/runtime/components/Card.vue.d.ts +38 -0
  80. package/dist/runtime/components/Carousel.vue +112 -230
  81. package/dist/runtime/components/Carousel.vue.d.ts +120 -0
  82. package/dist/runtime/components/Checkbox.vue +52 -93
  83. package/dist/runtime/components/Checkbox.vue.d.ts +76 -0
  84. package/dist/runtime/components/CheckboxGroup.vue +121 -0
  85. package/dist/runtime/components/CheckboxGroup.vue.d.ts +75 -0
  86. package/dist/runtime/components/Chip.vue +26 -69
  87. package/dist/runtime/components/Chip.vue.d.ts +71 -0
  88. package/dist/runtime/components/Collapsible.vue +22 -41
  89. package/dist/runtime/components/Collapsible.vue.d.ts +50 -0
  90. package/dist/runtime/components/ColorPicker.vue +111 -197
  91. package/dist/runtime/components/ColorPicker.vue.d.ts +63 -0
  92. package/dist/runtime/components/CommandPalette.vue +94 -234
  93. package/dist/runtime/components/CommandPalette.vue.d.ts +173 -0
  94. package/dist/runtime/components/Container.vue +15 -28
  95. package/dist/runtime/components/Container.vue.d.ts +27 -0
  96. package/dist/runtime/components/ContextMenu.vue +32 -119
  97. package/dist/runtime/components/ContextMenu.vue.d.ts +127 -0
  98. package/dist/runtime/components/ContextMenuContent.vue +71 -72
  99. package/dist/runtime/components/ContextMenuContent.vue.d.ts +105 -0
  100. package/dist/runtime/components/Drawer.vue +49 -87
  101. package/dist/runtime/components/Drawer.vue.d.ts +88 -0
  102. package/dist/runtime/components/DropdownMenu.vue +37 -129
  103. package/dist/runtime/components/DropdownMenu.vue.d.ts +141 -0
  104. package/dist/runtime/components/DropdownMenuContent.vue +76 -79
  105. package/dist/runtime/components/DropdownMenuContent.vue.d.ts +55 -0
  106. package/dist/runtime/components/Form.vue +135 -219
  107. package/dist/runtime/components/Form.vue.d.ts +66 -0
  108. package/dist/runtime/components/FormField.vue +36 -77
  109. package/dist/runtime/components/FormField.vue.d.ts +70 -0
  110. package/dist/runtime/components/Icon.vue +12 -19
  111. package/dist/runtime/components/Icon.vue.d.ts +17 -0
  112. package/dist/runtime/components/Input.vue +82 -140
  113. package/dist/runtime/components/Input.vue.d.ts +91 -0
  114. package/dist/runtime/components/InputMenu.vue +193 -302
  115. package/dist/runtime/components/InputMenu.vue.d.ts +312 -0
  116. package/dist/runtime/components/InputNumber.vue +71 -133
  117. package/dist/runtime/components/InputNumber.vue.d.ts +193 -0
  118. package/dist/runtime/components/Kbd.vue +20 -46
  119. package/dist/runtime/components/Kbd.vue.d.ts +55 -0
  120. package/dist/runtime/components/Link.vue +98 -173
  121. package/dist/runtime/components/Link.vue.d.ts +124 -0
  122. package/dist/runtime/components/LinkBase.vue +33 -41
  123. package/dist/runtime/components/LinkBase.vue.d.ts +48 -0
  124. package/dist/runtime/components/Modal.vue +53 -116
  125. package/dist/runtime/components/Modal.vue.d.ts +109 -0
  126. package/dist/runtime/components/NavigationMenu.vue +78 -186
  127. package/dist/runtime/components/NavigationMenu.vue.d.ts +159 -0
  128. package/dist/runtime/components/OverlayProvider.vue +14 -18
  129. package/dist/runtime/components/OverlayProvider.vue.d.ts +2 -0
  130. package/dist/runtime/components/Pagination.vue +46 -140
  131. package/dist/runtime/components/Pagination.vue.d.ts +143 -0
  132. package/dist/runtime/components/PinInput.vue +61 -78
  133. package/dist/runtime/components/PinInput.vue.d.ts +68 -0
  134. package/dist/runtime/components/Popover.vue +47 -84
  135. package/dist/runtime/components/Popover.vue.d.ts +80 -0
  136. package/dist/runtime/components/Progress.vue +70 -131
  137. package/dist/runtime/components/Progress.vue.d.ts +97 -0
  138. package/dist/runtime/components/RadioGroup.vue +75 -126
  139. package/dist/runtime/components/RadioGroup.vue.d.ts +88 -0
  140. package/dist/runtime/components/Select.vue +115 -202
  141. package/dist/runtime/components/Select.vue.d.ts +139 -0
  142. package/dist/runtime/components/SelectMenu.vue +167 -281
  143. package/dist/runtime/components/SelectMenu.vue.d.ts +184 -0
  144. package/dist/runtime/components/Separator.vue +29 -71
  145. package/dist/runtime/components/Separator.vue.d.ts +75 -0
  146. package/dist/runtime/components/Skeleton.vue +21 -23
  147. package/dist/runtime/components/Skeleton.vue.d.ts +26 -0
  148. package/dist/runtime/components/Slideover.vue +53 -120
  149. package/dist/runtime/components/Slideover.vue.d.ts +111 -0
  150. package/dist/runtime/components/Slider.vue +46 -84
  151. package/dist/runtime/components/Slider.vue.d.ts +71 -0
  152. package/dist/runtime/components/Stepper.vue +44 -113
  153. package/dist/runtime/components/Stepper.vue.d.ts +89 -0
  154. package/dist/runtime/components/Switch.vue +45 -93
  155. package/dist/runtime/components/Switch.vue.d.ts +73 -0
  156. package/dist/runtime/components/Table.vue +165 -264
  157. package/dist/runtime/components/Table.vue.d.ts +183 -0
  158. package/dist/runtime/components/Tabs.vue +40 -105
  159. package/dist/runtime/components/Tabs.vue.d.ts +104 -0
  160. package/dist/runtime/components/Textarea.vue +113 -158
  161. package/dist/runtime/components/Textarea.vue.d.ts +95 -0
  162. package/dist/runtime/components/Toast.vue +49 -110
  163. package/dist/runtime/components/Toast.vue.d.ts +95 -0
  164. package/dist/runtime/components/Toaster.vue +70 -107
  165. package/dist/runtime/components/Toaster.vue.d.ts +63 -0
  166. package/dist/runtime/components/Tooltip.vue +38 -65
  167. package/dist/runtime/components/Tooltip.vue.d.ts +65 -0
  168. package/dist/runtime/components/Tree.vue +57 -150
  169. package/dist/runtime/components/Tree.vue.d.ts +128 -0
  170. package/dist/runtime/composables/defineShortcuts.d.ts +1 -1
  171. package/dist/runtime/composables/defineShortcuts.js +0 -1
  172. package/dist/runtime/composables/useAvatarGroup.d.ts +1 -1
  173. package/dist/runtime/composables/useButtonGroup.d.ts +2 -2
  174. package/dist/runtime/composables/useFormField.d.ts +2 -2
  175. package/dist/runtime/composables/useFormField.js +1 -1
  176. package/dist/runtime/composables/useOverlay.d.ts +16 -8
  177. package/dist/runtime/composables/useOverlay.js +14 -6
  178. package/dist/runtime/composables/usePortal.d.ts +6 -0
  179. package/dist/runtime/composables/usePortal.js +17 -0
  180. package/dist/runtime/index.css +1 -1
  181. package/dist/runtime/inertia/components/Link.vue +146 -0
  182. package/dist/runtime/inertia/components/Link.vue.d.ts +92 -0
  183. package/dist/runtime/inertia/stubs.d.ts +43 -0
  184. package/dist/runtime/inertia/stubs.js +82 -0
  185. package/dist/runtime/locale/bg.d.ts +3 -0
  186. package/dist/runtime/locale/bg.js +54 -0
  187. package/dist/runtime/locale/hy.d.ts +3 -0
  188. package/dist/runtime/locale/hy.js +54 -0
  189. package/dist/runtime/locale/index.d.ts +6 -1
  190. package/dist/runtime/locale/index.js +6 -1
  191. package/dist/runtime/locale/kk.d.ts +3 -0
  192. package/dist/runtime/locale/kk.js +54 -0
  193. package/dist/runtime/locale/tj.d.ts +3 -0
  194. package/dist/runtime/locale/tj.js +54 -0
  195. package/dist/runtime/locale/ug_cn.d.ts +3 -0
  196. package/dist/runtime/locale/ug_cn.js +55 -0
  197. package/dist/runtime/types/form.d.ts +5 -1
  198. package/dist/runtime/types/index.d.ts +2 -0
  199. package/dist/runtime/types/index.js +2 -0
  200. package/dist/runtime/types/utils.d.ts +70 -10
  201. package/dist/runtime/utils/index.d.ts +1 -0
  202. package/dist/runtime/utils/index.js +3 -0
  203. package/dist/runtime/utils/link.d.ts +4 -27
  204. package/dist/runtime/utils/link.js +32 -1
  205. package/dist/runtime/utils/tv.js +2 -2
  206. package/dist/runtime/vue/components/Icon.vue +7 -8
  207. package/dist/runtime/vue/components/Icon.vue.d.ts +14 -0
  208. package/dist/runtime/vue/components/Link.vue +118 -199
  209. package/dist/runtime/vue/components/Link.vue.d.ts +124 -0
  210. package/dist/runtime/vue/stubs.d.ts +5 -0
  211. package/dist/runtime/vue/stubs.js +11 -2
  212. package/dist/shared/{ui.BCaWD5Ek.mjs → ui.D7lOOabO.mjs} +623 -364
  213. package/dist/types.d.mts +5 -1
  214. package/dist/unplugin.d.mts +6 -1
  215. package/dist/unplugin.mjs +25 -4
  216. package/dist/vite.mjs +1 -1
  217. package/package.json +122 -64
  218. package/dist/module.cjs +0 -62
  219. package/dist/module.d.cts +0 -44
  220. package/dist/module.d.ts +0 -44
  221. package/dist/shared/ui.C6uTSFTI.cjs +0 -3555
  222. package/dist/types.d.ts +0 -1
  223. package/dist/unplugin.cjs +0 -232
  224. package/dist/unplugin.d.cts +0 -61
  225. package/dist/unplugin.d.ts +0 -61
  226. package/dist/vite.cjs +0 -23
  227. package/dist/vite.d.cts +0 -15
  228. package/dist/vite.d.ts +0 -15
@@ -1,125 +1,38 @@
1
- <!-- eslint-disable vue/block-tag-newline -->
2
- <script lang="ts">
3
- import type { VariantProps } from 'tailwind-variants'
4
- import type { ContextMenuRootProps, ContextMenuRootEmits, ContextMenuContentProps, ContextMenuContentEmits } from 'reka-ui'
5
- import type { AppConfig } from '@nuxt/schema'
6
- import _appConfig from '#build/app.config'
7
- import theme from '#build/ui/context-menu'
8
- import { tv } from '../utils/tv'
9
- import type { AvatarProps, KbdProps, LinkProps } from '../types'
10
- import type { DynamicSlots, PartialString, EmitsToProps } from '../types/utils'
11
-
12
- const appConfigContextMenu = _appConfig as AppConfig & { ui: { contextMenu: Partial<typeof theme> } }
13
-
14
- const contextMenu = tv({ extend: tv(theme), ...(appConfigContextMenu.ui?.contextMenu || {}) })
15
-
16
- type ContextMenuVariants = VariantProps<typeof contextMenu>
17
-
18
- export interface ContextMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'custom'> {
19
- label?: string
20
- /**
21
- * @IconifyIcon
22
- */
23
- icon?: string
24
- color?: ContextMenuVariants['color']
25
- avatar?: AvatarProps
26
- content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<ContextMenuContentEmits>>
27
- kbds?: KbdProps['value'][] | KbdProps[]
28
- /**
29
- * The item type.
30
- * @defaultValue 'link'
31
- */
32
- type?: 'label' | 'separator' | 'link' | 'checkbox'
33
- slot?: string
34
- loading?: boolean
35
- disabled?: boolean
36
- checked?: boolean
37
- open?: boolean
38
- defaultOpen?: boolean
39
- children?: ContextMenuItem[] | ContextMenuItem[][]
40
- onSelect?(e: Event): void
41
- onUpdateChecked?(checked: boolean): void
42
- }
43
-
44
- export interface ContextMenuProps<T> extends Omit<ContextMenuRootProps, 'dir'> {
45
- /**
46
- * @defaultValue 'md'
47
- */
48
- size?: ContextMenuVariants['size']
49
- items?: T[] | T[][]
50
- /**
51
- * The icon displayed when an item is checked.
52
- * @defaultValue appConfig.ui.icons.check
53
- * @IconifyIcon
54
- */
55
- checkedIcon?: string
56
- /**
57
- * The icon displayed when an item is loading.
58
- * @defaultValue appConfig.ui.icons.loading
59
- * @IconifyIcon
60
- */
61
- loadingIcon?: string
62
- /**
63
- * The icon displayed when the item is an external link.
64
- * Set to `false` to hide the external icon.
65
- * @defaultValue appConfig.ui.icons.external
66
- * @IconifyIcon
67
- */
68
- externalIcon?: boolean | string
69
- /** The content of the menu. */
70
- content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<ContextMenuContentEmits>>
71
- /**
72
- * Render the menu in a portal.
73
- * @defaultValue true
74
- */
75
- portal?: boolean
76
- /**
77
- * The key used to get the label from the item.
78
- * @defaultValue 'label'
79
- */
80
- labelKey?: string
81
- disabled?: boolean
82
- class?: any
83
- ui?: PartialString<typeof contextMenu.slots>
84
- }
85
-
86
- export interface ContextMenuEmits extends ContextMenuRootEmits {}
87
-
88
- type SlotProps<T> = (props: { item: T, active?: boolean, index: number }) => any
89
-
90
- export type ContextMenuSlots<T extends { slot?: string }> = {
91
- 'default'(props?: {}): any
92
- 'item': SlotProps<T>
93
- 'item-leading': SlotProps<T>
94
- 'item-label': SlotProps<T>
95
- 'item-trailing': SlotProps<T>
96
- } & DynamicSlots<T, SlotProps<T>>
97
-
1
+ <script>
2
+ import theme from "#build/ui/context-menu";
98
3
  </script>
99
4
 
100
- <script setup lang="ts" generic="T extends ContextMenuItem">
101
- import { computed, toRef } from 'vue'
102
- import { ContextMenuRoot, ContextMenuTrigger, useForwardPropsEmits } from 'reka-ui'
103
- import { reactivePick } from '@vueuse/core'
104
- import { omit } from '../utils'
105
- import UContextMenuContent from './ContextMenuContent.vue'
106
-
107
- const props = withDefaults(defineProps<ContextMenuProps<T>>(), {
108
- portal: true,
109
- modal: true,
110
- externalIcon: true,
111
- labelKey: 'label'
112
- })
113
- const emits = defineEmits<ContextMenuEmits>()
114
- const slots = defineSlots<ContextMenuSlots<T>>()
115
-
116
- const rootProps = useForwardPropsEmits(reactivePick(props, 'modal'), emits)
117
- const contentProps = toRef(() => props.content)
118
- const proxySlots = omit(slots, ['default']) as Record<string, ContextMenuSlots<T>[string]>
119
-
120
- const ui = computed(() => contextMenu({
5
+ <script setup>
6
+ import { computed, toRef } from "vue";
7
+ import { ContextMenuRoot, ContextMenuTrigger, useForwardPropsEmits } from "reka-ui";
8
+ import { reactivePick } from "@vueuse/core";
9
+ import { useAppConfig } from "#imports";
10
+ import { omit } from "../utils";
11
+ import { tv } from "../utils/tv";
12
+ import UContextMenuContent from "./ContextMenuContent.vue";
13
+ const props = defineProps({
14
+ size: { type: null, required: false },
15
+ items: { type: null, required: false },
16
+ checkedIcon: { type: String, required: false },
17
+ loadingIcon: { type: String, required: false },
18
+ externalIcon: { type: [Boolean, String], required: false, default: true },
19
+ content: { type: Object, required: false },
20
+ portal: { type: [Boolean, String], required: false, skipCheck: true, default: true },
21
+ labelKey: { type: null, required: false, default: "label" },
22
+ disabled: { type: Boolean, required: false },
23
+ class: { type: null, required: false },
24
+ ui: { type: null, required: false },
25
+ modal: { type: Boolean, required: false, default: true }
26
+ });
27
+ const emits = defineEmits(["update:open"]);
28
+ const slots = defineSlots();
29
+ const appConfig = useAppConfig();
30
+ const rootProps = useForwardPropsEmits(reactivePick(props, "modal"), emits);
31
+ const contentProps = toRef(() => props.content);
32
+ const proxySlots = omit(slots, ["default"]);
33
+ const ui = computed(() => tv({ extend: tv(theme), ...appConfig.ui?.contextMenu || {} })({
121
34
  size: props.size
122
- }))
35
+ }));
123
36
  </script>
124
37
 
125
38
  <template>
@@ -0,0 +1,127 @@
1
+ import type { ContextMenuRootProps, ContextMenuRootEmits, ContextMenuContentProps, ContextMenuContentEmits } from 'reka-ui';
2
+ import type { AppConfig } from '@nuxt/schema';
3
+ import theme from '#build/ui/context-menu';
4
+ import type { AvatarProps, KbdProps, LinkProps } from '../types';
5
+ import type { ArrayOrNested, DynamicSlots, MergeTypes, NestedItem, EmitsToProps, ComponentConfig } from '../types/utils';
6
+ type ContextMenu = ComponentConfig<typeof theme, AppConfig, 'contextMenu'>;
7
+ export interface ContextMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'custom'> {
8
+ label?: string;
9
+ /**
10
+ * @IconifyIcon
11
+ */
12
+ icon?: string;
13
+ color?: ContextMenu['variants']['color'];
14
+ avatar?: AvatarProps;
15
+ content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<ContextMenuContentEmits>>;
16
+ kbds?: KbdProps['value'][] | KbdProps[];
17
+ /**
18
+ * The item type.
19
+ * @defaultValue 'link'
20
+ */
21
+ type?: 'label' | 'separator' | 'link' | 'checkbox';
22
+ slot?: string;
23
+ loading?: boolean;
24
+ disabled?: boolean;
25
+ checked?: boolean;
26
+ open?: boolean;
27
+ defaultOpen?: boolean;
28
+ children?: ArrayOrNested<ContextMenuItem>;
29
+ onSelect?(e: Event): void;
30
+ onUpdateChecked?(checked: boolean): void;
31
+ [key: string]: any;
32
+ }
33
+ export interface ContextMenuProps<T extends ArrayOrNested<ContextMenuItem> = ArrayOrNested<ContextMenuItem>> extends Omit<ContextMenuRootProps, 'dir'> {
34
+ /**
35
+ * @defaultValue 'md'
36
+ */
37
+ size?: ContextMenu['variants']['size'];
38
+ items?: T;
39
+ /**
40
+ * The icon displayed when an item is checked.
41
+ * @defaultValue appConfig.ui.icons.check
42
+ * @IconifyIcon
43
+ */
44
+ checkedIcon?: string;
45
+ /**
46
+ * The icon displayed when an item is loading.
47
+ * @defaultValue appConfig.ui.icons.loading
48
+ * @IconifyIcon
49
+ */
50
+ loadingIcon?: string;
51
+ /**
52
+ * The icon displayed when the item is an external link.
53
+ * Set to `false` to hide the external icon.
54
+ * @defaultValue appConfig.ui.icons.external
55
+ * @IconifyIcon
56
+ */
57
+ externalIcon?: boolean | string;
58
+ /** The content of the menu. */
59
+ content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<ContextMenuContentEmits>>;
60
+ /**
61
+ * Render the menu in a portal.
62
+ * @defaultValue true
63
+ */
64
+ portal?: boolean | string | HTMLElement;
65
+ /**
66
+ * The key used to get the label from the item.
67
+ * @defaultValue 'label'
68
+ */
69
+ labelKey?: keyof NestedItem<T>;
70
+ disabled?: boolean;
71
+ class?: any;
72
+ ui?: ContextMenu['slots'];
73
+ }
74
+ export interface ContextMenuEmits extends ContextMenuRootEmits {
75
+ }
76
+ type SlotProps<T extends ContextMenuItem> = (props: {
77
+ item: T;
78
+ active?: boolean;
79
+ index: number;
80
+ }) => any;
81
+ export type ContextMenuSlots<A extends ArrayOrNested<ContextMenuItem> = ArrayOrNested<ContextMenuItem>, T extends NestedItem<A> = NestedItem<A>> = {
82
+ 'default'(props?: {}): any;
83
+ 'item': SlotProps<T>;
84
+ 'item-leading': SlotProps<T>;
85
+ 'item-label': SlotProps<T>;
86
+ 'item-trailing': SlotProps<T>;
87
+ 'content-top': (props?: {}) => any;
88
+ 'content-bottom': (props?: {}) => any;
89
+ } & DynamicSlots<MergeTypes<T>, 'leading' | 'label' | 'trailing', {
90
+ active?: boolean;
91
+ index: number;
92
+ }>;
93
+ declare const _default: <T extends ArrayOrNested<ContextMenuItem>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
94
+ props: __VLS_PrettifyLocal<any & ContextMenuProps<T> & Partial<{}>> & (import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps);
95
+ expose(exposed: import("vue").ShallowUnwrapRef<{}>): void;
96
+ attrs: any;
97
+ slots: Readonly<{
98
+ default(props?: {}): any;
99
+ item: SlotProps<NestedItem<T>>;
100
+ 'item-leading': SlotProps<NestedItem<T>>;
101
+ 'item-label': SlotProps<NestedItem<T>>;
102
+ 'item-trailing': SlotProps<NestedItem<T>>;
103
+ 'content-top': (props?: {}) => any;
104
+ 'content-bottom': (props?: {}) => any;
105
+ } & DynamicSlots<MergeTypes<NestedItem<T>>, "trailing" | "leading" | "label", {
106
+ active?: boolean;
107
+ index: number;
108
+ }>> & {
109
+ default(props?: {}): any;
110
+ item: SlotProps<NestedItem<T>>;
111
+ 'item-leading': SlotProps<NestedItem<T>>;
112
+ 'item-label': SlotProps<NestedItem<T>>;
113
+ 'item-trailing': SlotProps<NestedItem<T>>;
114
+ 'content-top': (props?: {}) => any;
115
+ 'content-bottom': (props?: {}) => any;
116
+ } & DynamicSlots<MergeTypes<NestedItem<T>>, "trailing" | "leading" | "label", {
117
+ active?: boolean;
118
+ index: number;
119
+ }>;
120
+ emit: (evt: "update:open", payload: boolean) => void;
121
+ }>) => import("vue").VNode & {
122
+ __ctx?: Awaited<typeof __VLS_setup>;
123
+ };
124
+ export default _default;
125
+ type __VLS_PrettifyLocal<T> = {
126
+ [K in keyof T]: T[K];
127
+ } & {};
@@ -1,87 +1,82 @@
1
- <script lang="ts">
2
- import type { ContextMenuContentProps as RekaContextMenuContentProps, ContextMenuContentEmits as RekaContextMenuContentEmits } from 'reka-ui'
3
- import theme from '#build/ui/context-menu'
4
- import { tv } from '../utils/tv'
5
- import type { KbdProps, AvatarProps, ContextMenuItem, ContextMenuSlots } from '../types'
1
+ <script>
6
2
 
7
- const _contextMenu = tv(theme)()
8
-
9
- interface ContextMenuContentProps<T> extends Omit<RekaContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> {
10
- items?: T[] | T[][]
11
- portal?: boolean
12
- sub?: boolean
13
- labelKey: string
14
- /**
15
- * @IconifyIcon
16
- */
17
- checkedIcon?: string
18
- /**
19
- * @IconifyIcon
20
- */
21
- loadingIcon?: string
22
- /**
23
- * @IconifyIcon
24
- */
25
- externalIcon?: boolean | string
26
- class?: any
27
- ui: typeof _contextMenu
28
- uiOverride?: any
29
- }
30
-
31
- interface ContextMenuContentEmits extends RekaContextMenuContentEmits {}
32
3
  </script>
33
4
 
34
- <script setup lang="ts" generic="T extends ContextMenuItem">
35
- import { computed } from 'vue'
36
- import { ContextMenu } from 'reka-ui/namespaced'
37
- import { useForwardPropsEmits } from 'reka-ui'
38
- import { reactiveOmit, createReusableTemplate } from '@vueuse/core'
39
- import { useAppConfig } from '#imports'
40
- import { omit, get } from '../utils'
41
- import { pickLinkProps } from '../utils/link'
42
- import ULinkBase from './LinkBase.vue'
43
- import ULink from './Link.vue'
44
- import UAvatar from './Avatar.vue'
45
- import UIcon from './Icon.vue'
46
- import UKbd from './Kbd.vue'
47
- // eslint-disable-next-line import/no-self-import
48
- import UContextMenuContent from './ContextMenuContent.vue'
49
-
50
- const props = defineProps<ContextMenuContentProps<T>>()
51
- const emits = defineEmits<ContextMenuContentEmits>()
52
- const slots = defineSlots<ContextMenuSlots<T>>()
53
-
54
- const appConfig = useAppConfig()
55
- const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'labelKey', 'checkedIcon', 'loadingIcon', 'externalIcon', 'class', 'ui', 'uiOverride'), emits)
56
- const proxySlots = omit(slots, ['default']) as Record<string, ContextMenuSlots<T>[string]>
57
-
58
- const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: ContextMenuItem, active?: boolean, index: number }>()
59
-
60
- const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0]) ? props.items : [props.items]) as T[][] : [])
5
+ <script setup>
6
+ import { computed, toRef } from "vue";
7
+ import { ContextMenu } from "reka-ui/namespaced";
8
+ import { useForwardPropsEmits } from "reka-ui";
9
+ import { reactiveOmit, createReusableTemplate } from "@vueuse/core";
10
+ import { useAppConfig } from "#imports";
11
+ import { useLocale } from "../composables/useLocale";
12
+ import { usePortal } from "../composables/usePortal";
13
+ import { omit, get, isArrayOfArray } from "../utils";
14
+ import { pickLinkProps } from "../utils/link";
15
+ import ULinkBase from "./LinkBase.vue";
16
+ import ULink from "./Link.vue";
17
+ import UAvatar from "./Avatar.vue";
18
+ import UIcon from "./Icon.vue";
19
+ import UKbd from "./Kbd.vue";
20
+ import UContextMenuContent from "./ContextMenuContent.vue";
21
+ const props = defineProps({
22
+ items: { type: null, required: false },
23
+ portal: { type: [Boolean, String], required: false, skipCheck: true },
24
+ sub: { type: Boolean, required: false },
25
+ labelKey: { type: null, required: true },
26
+ checkedIcon: { type: String, required: false },
27
+ loadingIcon: { type: String, required: false },
28
+ externalIcon: { type: [Boolean, String], required: false },
29
+ class: { type: null, required: false },
30
+ ui: { type: null, required: true },
31
+ uiOverride: { type: null, required: false },
32
+ loop: { type: Boolean, required: false },
33
+ alignOffset: { type: Number, required: false },
34
+ avoidCollisions: { type: Boolean, required: false },
35
+ collisionBoundary: { type: null, required: false },
36
+ collisionPadding: { type: [Number, Object], required: false },
37
+ sticky: { type: String, required: false },
38
+ hideWhenDetached: { type: Boolean, required: false },
39
+ positionStrategy: { type: String, required: false },
40
+ disableUpdateOnLayoutShift: { type: Boolean, required: false },
41
+ prioritizePosition: { type: Boolean, required: false },
42
+ reference: { type: null, required: false }
43
+ });
44
+ const emits = defineEmits(["escapeKeyDown", "pointerDownOutside", "focusOutside", "interactOutside", "closeAutoFocus"]);
45
+ const slots = defineSlots();
46
+ const { dir } = useLocale();
47
+ const appConfig = useAppConfig();
48
+ const portalProps = usePortal(toRef(() => props.portal));
49
+ const contentProps = useForwardPropsEmits(reactiveOmit(props, "sub", "items", "portal", "labelKey", "checkedIcon", "loadingIcon", "externalIcon", "class", "ui", "uiOverride"), emits);
50
+ const proxySlots = omit(slots, ["default"]);
51
+ const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate();
52
+ const childrenIcon = computed(() => dir.value === "rtl" ? appConfig.ui.icons.chevronLeft : appConfig.ui.icons.chevronRight);
53
+ const groups = computed(
54
+ () => props.items?.length ? isArrayOfArray(props.items) ? props.items : [props.items] : []
55
+ );
61
56
  </script>
62
57
 
63
58
  <template>
64
59
  <DefineItemTemplate v-slot="{ item, active, index }">
65
- <slot :name="item.slot || 'item'" :item="(item as T)" :index="index">
66
- <slot :name="item.slot ? `${item.slot}-leading`: 'item-leading'" :item="(item as T)" :active="active" :index="index">
60
+ <slot :name="item.slot || 'item'" :item="item" :index="index">
61
+ <slot :name="item.slot ? `${item.slot}-leading` : 'item-leading'" :item="item" :active="active" :index="index">
67
62
  <UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: uiOverride?.itemLeadingIcon, color: item?.color, loading: true })" />
68
63
  <UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: uiOverride?.itemLeadingIcon, color: item?.color, active })" />
69
- <UAvatar v-else-if="item.avatar" :size="((props.uiOverride?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: uiOverride?.itemLeadingAvatar, active })" />
64
+ <UAvatar v-else-if="item.avatar" :size="props.uiOverride?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: uiOverride?.itemLeadingAvatar, active })" />
70
65
  </slot>
71
66
 
72
- <span v-if="get(item, props.labelKey as string) || !!slots[item.slot ? `${item.slot}-label`: 'item-label']" :class="ui.itemLabel({ class: uiOverride?.itemLabel, active })">
73
- <slot :name="item.slot ? `${item.slot}-label`: 'item-label'" :item="(item as T)" :active="active" :index="index">
74
- {{ get(item, props.labelKey as string) }}
67
+ <span v-if="get(item, props.labelKey) || !!slots[item.slot ? `${item.slot}-label` : 'item-label']" :class="ui.itemLabel({ class: uiOverride?.itemLabel, active })">
68
+ <slot :name="item.slot ? `${item.slot}-label` : 'item-label'" :item="item" :active="active" :index="index">
69
+ {{ get(item, props.labelKey) }}
75
70
  </slot>
76
71
 
77
72
  <UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
78
73
  </span>
79
74
 
80
75
  <span :class="ui.itemTrailing({ class: uiOverride?.itemTrailing })">
81
- <slot :name="item.slot ? `${item.slot}-trailing`: 'item-trailing'" :item="(item as T)" :active="active" :index="index">
82
- <UIcon v-if="item.children?.length" :name="appConfig.ui.icons.chevronRight" :class="ui.itemTrailingIcon({ class: uiOverride?.itemTrailingIcon, color: item?.color, active })" />
76
+ <slot :name="item.slot ? `${item.slot}-trailing` : 'item-trailing'" :item="item" :active="active" :index="index">
77
+ <UIcon v-if="item.children?.length" :name="childrenIcon" :class="ui.itemTrailingIcon({ class: uiOverride?.itemTrailingIcon, color: item?.color, active })" />
83
78
  <span v-else-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: uiOverride?.itemTrailingKbds })">
84
- <UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((props.uiOverride?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
79
+ <UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="props.uiOverride?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
85
80
  </span>
86
81
  </slot>
87
82
 
@@ -92,8 +87,10 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
92
87
  </slot>
93
88
  </DefineItemTemplate>
94
89
 
95
- <ContextMenu.Portal :disabled="!portal">
90
+ <ContextMenu.Portal v-bind="portalProps">
96
91
  <component :is="sub ? ContextMenu.SubContent : ContextMenu.Content" :class="props.class" v-bind="contentProps">
92
+ <slot name="content-top" />
93
+
97
94
  <ContextMenu.Group v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: uiOverride?.group })">
98
95
  <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
99
96
  <ContextMenu.Label v-if="item.type === 'label'" :class="ui.label({ class: uiOverride?.label })">
@@ -105,7 +102,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
105
102
  as="button"
106
103
  type="button"
107
104
  :disabled="item.disabled"
108
- :text-value="get(item, props.labelKey as string)"
105
+ :text-value="get(item, props.labelKey)"
109
106
  :class="ui.item({ class: uiOverride?.item, color: item?.color })"
110
107
  >
111
108
  <ReuseItemTemplate :item="item" :index="index" />
@@ -125,7 +122,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
125
122
  :external-icon="externalIcon"
126
123
  v-bind="item.content"
127
124
  >
128
- <template v-for="(_, name) in proxySlots" #[name]="slotData: any">
125
+ <template v-for="(_, name) in proxySlots" #[name]="slotData">
129
126
  <slot :name="name" v-bind="slotData" />
130
127
  </template>
131
128
  </UContextMenuContent>
@@ -134,7 +131,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
134
131
  v-else-if="item.type === 'checkbox'"
135
132
  :model-value="item.checked"
136
133
  :disabled="item.disabled"
137
- :text-value="get(item, props.labelKey as string)"
134
+ :text-value="get(item, props.labelKey)"
138
135
  :class="ui.item({ class: [uiOverride?.item, item.class], color: item?.color })"
139
136
  @update:model-value="item.onUpdateChecked"
140
137
  @select="item.onSelect"
@@ -145,10 +142,10 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
145
142
  v-else
146
143
  as-child
147
144
  :disabled="item.disabled"
148
- :text-value="get(item, props.labelKey as string)"
145
+ :text-value="get(item, props.labelKey)"
149
146
  @select="item.onSelect"
150
147
  >
151
- <ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item as Omit<ContextMenuItem, 'type'>)" custom>
148
+ <ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
152
149
  <ULinkBase v-bind="slotProps" :class="ui.item({ class: [uiOverride?.item, item.class], active, color: item?.color })">
153
150
  <ReuseItemTemplate :item="item" :active="active" :index="index" />
154
151
  </ULinkBase>
@@ -158,6 +155,8 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
158
155
  </ContextMenu.Group>
159
156
 
160
157
  <slot />
158
+
159
+ <slot name="content-bottom" />
161
160
  </component>
162
161
  </ContextMenu.Portal>
163
162
  </template>
@@ -0,0 +1,105 @@
1
+ import { ContextMenu } from 'reka-ui/namespaced';
2
+ import type { ContextMenuContentProps as RekaContextMenuContentProps } from 'reka-ui';
3
+ import type { AppConfig } from '@nuxt/schema';
4
+ import type theme from '#build/ui/context-menu';
5
+ import type { ContextMenuItem } from '../types';
6
+ import type { ArrayOrNested, NestedItem, ComponentConfig } from '../types/utils';
7
+ type ContextMenu = ComponentConfig<typeof theme, AppConfig, 'contextMenu'>;
8
+ interface ContextMenuContentProps<T extends ArrayOrNested<ContextMenuItem>> extends Omit<RekaContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> {
9
+ items?: T;
10
+ portal?: boolean | string | HTMLElement;
11
+ sub?: boolean;
12
+ labelKey: keyof NestedItem<T>;
13
+ /**
14
+ * @IconifyIcon
15
+ */
16
+ checkedIcon?: string;
17
+ /**
18
+ * @IconifyIcon
19
+ */
20
+ loadingIcon?: string;
21
+ /**
22
+ * @IconifyIcon
23
+ */
24
+ externalIcon?: boolean | string;
25
+ class?: any;
26
+ ui: {
27
+ [K in keyof Required<ContextMenu['slots']>]: (props?: Record<string, any>) => string;
28
+ };
29
+ uiOverride?: ContextMenu['slots'];
30
+ }
31
+ declare const _default: <T extends ArrayOrNested<ContextMenuItem>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
32
+ props: __VLS_PrettifyLocal<any & ContextMenuContentProps<T> & Partial<{}>> & (import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps);
33
+ expose(exposed: import("vue").ShallowUnwrapRef<{}>): void;
34
+ attrs: any;
35
+ slots: Readonly<{
36
+ default(props?: {}): any;
37
+ item: (props: {
38
+ item: NestedItem<T>;
39
+ active?: boolean;
40
+ index: number;
41
+ }) => any;
42
+ 'item-leading': (props: {
43
+ item: NestedItem<T>;
44
+ active?: boolean;
45
+ index: number;
46
+ }) => any;
47
+ 'item-label': (props: {
48
+ item: NestedItem<T>;
49
+ active?: boolean;
50
+ index: number;
51
+ }) => any;
52
+ 'item-trailing': (props: {
53
+ item: NestedItem<T>;
54
+ active?: boolean;
55
+ index: number;
56
+ }) => any;
57
+ 'content-top': (props?: {}) => any;
58
+ 'content-bottom': (props?: {}) => any;
59
+ } & import("../types").DynamicSlots<import("../types").MergeTypes<NestedItem<T>>, "trailing" | "leading" | "label", {
60
+ active?: boolean;
61
+ index: number;
62
+ }>> & {
63
+ default(props?: {}): any;
64
+ item: (props: {
65
+ item: NestedItem<T>;
66
+ active?: boolean;
67
+ index: number;
68
+ }) => any;
69
+ 'item-leading': (props: {
70
+ item: NestedItem<T>;
71
+ active?: boolean;
72
+ index: number;
73
+ }) => any;
74
+ 'item-label': (props: {
75
+ item: NestedItem<T>;
76
+ active?: boolean;
77
+ index: number;
78
+ }) => any;
79
+ 'item-trailing': (props: {
80
+ item: NestedItem<T>;
81
+ active?: boolean;
82
+ index: number;
83
+ }) => any;
84
+ 'content-top': (props?: {}) => any;
85
+ 'content-bottom': (props?: {}) => any;
86
+ } & import("../types").DynamicSlots<import("../types").MergeTypes<NestedItem<T>>, "trailing" | "leading" | "label", {
87
+ active?: boolean;
88
+ index: number;
89
+ }>;
90
+ emit: ((evt: "escapeKeyDown", event: KeyboardEvent) => void) & ((evt: "pointerDownOutside", event: CustomEvent<{
91
+ originalEvent: PointerEvent;
92
+ }>) => void) & ((evt: "focusOutside", event: CustomEvent<{
93
+ originalEvent: FocusEvent;
94
+ }>) => void) & ((evt: "interactOutside", event: CustomEvent<{
95
+ originalEvent: PointerEvent;
96
+ }> | CustomEvent<{
97
+ originalEvent: FocusEvent;
98
+ }>) => void) & ((evt: "closeAutoFocus", event: Event) => void);
99
+ }>) => import("vue").VNode & {
100
+ __ctx?: Awaited<typeof __VLS_setup>;
101
+ };
102
+ export default _default;
103
+ type __VLS_PrettifyLocal<T> = {
104
+ [K in keyof T]: T[K];
105
+ } & {};