@nuxt/ui 3.0.2 → 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 (220) 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 +23 -2
  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 +102 -83
  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 +43 -22
  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.json +5 -5
  56. package/dist/module.mjs +11 -7
  57. package/dist/runtime/components/Accordion.vue +36 -93
  58. package/dist/runtime/components/Accordion.vue.d.ts +91 -0
  59. package/dist/runtime/components/Alert.vue +37 -100
  60. package/dist/runtime/components/Alert.vue.d.ts +96 -0
  61. package/dist/runtime/components/App.vue +28 -34
  62. package/dist/runtime/components/App.vue.d.ts +24 -0
  63. package/dist/runtime/components/Avatar.vue +42 -75
  64. package/dist/runtime/components/Avatar.vue.d.ts +60 -0
  65. package/dist/runtime/components/AvatarGroup.vue +40 -77
  66. package/dist/runtime/components/AvatarGroup.vue.d.ts +40 -0
  67. package/dist/runtime/components/Badge.vue +33 -62
  68. package/dist/runtime/components/Badge.vue.d.ts +62 -0
  69. package/dist/runtime/components/Breadcrumb.vue +37 -90
  70. package/dist/runtime/components/Breadcrumb.vue.d.ts +82 -0
  71. package/dist/runtime/components/Button.vue +95 -104
  72. package/dist/runtime/components/Button.vue.d.ts +73 -0
  73. package/dist/runtime/components/ButtonGroup.vue +20 -46
  74. package/dist/runtime/components/ButtonGroup.vue.d.ts +55 -0
  75. package/dist/runtime/components/Calendar.vue +67 -150
  76. package/dist/runtime/components/Calendar.vue.d.ts +107 -0
  77. package/dist/runtime/components/Card.vue +18 -40
  78. package/dist/runtime/components/Card.vue.d.ts +38 -0
  79. package/dist/runtime/components/Carousel.vue +112 -234
  80. package/dist/runtime/components/Carousel.vue.d.ts +120 -0
  81. package/dist/runtime/components/Checkbox.vue +52 -93
  82. package/dist/runtime/components/Checkbox.vue.d.ts +76 -0
  83. package/dist/runtime/components/CheckboxGroup.vue +121 -0
  84. package/dist/runtime/components/CheckboxGroup.vue.d.ts +75 -0
  85. package/dist/runtime/components/Chip.vue +26 -69
  86. package/dist/runtime/components/Chip.vue.d.ts +71 -0
  87. package/dist/runtime/components/Collapsible.vue +22 -41
  88. package/dist/runtime/components/Collapsible.vue.d.ts +50 -0
  89. package/dist/runtime/components/ColorPicker.vue +111 -197
  90. package/dist/runtime/components/ColorPicker.vue.d.ts +63 -0
  91. package/dist/runtime/components/CommandPalette.vue +96 -237
  92. package/dist/runtime/components/CommandPalette.vue.d.ts +173 -0
  93. package/dist/runtime/components/Container.vue +15 -28
  94. package/dist/runtime/components/Container.vue.d.ts +27 -0
  95. package/dist/runtime/components/ContextMenu.vue +34 -133
  96. package/dist/runtime/components/ContextMenu.vue.d.ts +127 -0
  97. package/dist/runtime/components/ContextMenuContent.vue +73 -81
  98. package/dist/runtime/components/ContextMenuContent.vue.d.ts +105 -0
  99. package/dist/runtime/components/Drawer.vue +49 -83
  100. package/dist/runtime/components/Drawer.vue.d.ts +88 -0
  101. package/dist/runtime/components/DropdownMenu.vue +39 -142
  102. package/dist/runtime/components/DropdownMenu.vue.d.ts +141 -0
  103. package/dist/runtime/components/DropdownMenuContent.vue +78 -88
  104. package/dist/runtime/components/DropdownMenuContent.vue.d.ts +55 -0
  105. package/dist/runtime/components/Form.vue +135 -220
  106. package/dist/runtime/components/Form.vue.d.ts +66 -0
  107. package/dist/runtime/components/FormField.vue +35 -77
  108. package/dist/runtime/components/FormField.vue.d.ts +70 -0
  109. package/dist/runtime/components/Icon.vue +12 -19
  110. package/dist/runtime/components/Icon.vue.d.ts +17 -0
  111. package/dist/runtime/components/Input.vue +82 -140
  112. package/dist/runtime/components/Input.vue.d.ts +91 -0
  113. package/dist/runtime/components/InputMenu.vue +185 -332
  114. package/dist/runtime/components/InputMenu.vue.d.ts +312 -0
  115. package/dist/runtime/components/InputNumber.vue +71 -133
  116. package/dist/runtime/components/InputNumber.vue.d.ts +193 -0
  117. package/dist/runtime/components/Kbd.vue +20 -46
  118. package/dist/runtime/components/Kbd.vue.d.ts +55 -0
  119. package/dist/runtime/components/Link.vue +98 -176
  120. package/dist/runtime/components/Link.vue.d.ts +124 -0
  121. package/dist/runtime/components/LinkBase.vue +33 -42
  122. package/dist/runtime/components/LinkBase.vue.d.ts +48 -0
  123. package/dist/runtime/components/Modal.vue +53 -116
  124. package/dist/runtime/components/Modal.vue.d.ts +109 -0
  125. package/dist/runtime/components/NavigationMenu.vue +77 -209
  126. package/dist/runtime/components/NavigationMenu.vue.d.ts +159 -0
  127. package/dist/runtime/components/OverlayProvider.vue +14 -18
  128. package/dist/runtime/components/OverlayProvider.vue.d.ts +2 -0
  129. package/dist/runtime/components/Pagination.vue +46 -140
  130. package/dist/runtime/components/Pagination.vue.d.ts +143 -0
  131. package/dist/runtime/components/PinInput.vue +61 -78
  132. package/dist/runtime/components/PinInput.vue.d.ts +68 -0
  133. package/dist/runtime/components/Popover.vue +47 -84
  134. package/dist/runtime/components/Popover.vue.d.ts +80 -0
  135. package/dist/runtime/components/Progress.vue +70 -131
  136. package/dist/runtime/components/Progress.vue.d.ts +97 -0
  137. package/dist/runtime/components/RadioGroup.vue +70 -132
  138. package/dist/runtime/components/RadioGroup.vue.d.ts +88 -0
  139. package/dist/runtime/components/Select.vue +110 -224
  140. package/dist/runtime/components/Select.vue.d.ts +139 -0
  141. package/dist/runtime/components/SelectMenu.vue +161 -310
  142. package/dist/runtime/components/SelectMenu.vue.d.ts +184 -0
  143. package/dist/runtime/components/Separator.vue +29 -71
  144. package/dist/runtime/components/Separator.vue.d.ts +75 -0
  145. package/dist/runtime/components/Skeleton.vue +21 -23
  146. package/dist/runtime/components/Skeleton.vue.d.ts +26 -0
  147. package/dist/runtime/components/Slideover.vue +53 -120
  148. package/dist/runtime/components/Slideover.vue.d.ts +111 -0
  149. package/dist/runtime/components/Slider.vue +46 -84
  150. package/dist/runtime/components/Slider.vue.d.ts +71 -0
  151. package/dist/runtime/components/Stepper.vue +45 -115
  152. package/dist/runtime/components/Stepper.vue.d.ts +89 -0
  153. package/dist/runtime/components/Switch.vue +45 -93
  154. package/dist/runtime/components/Switch.vue.d.ts +73 -0
  155. package/dist/runtime/components/Table.vue +163 -267
  156. package/dist/runtime/components/Table.vue.d.ts +183 -0
  157. package/dist/runtime/components/Tabs.vue +41 -107
  158. package/dist/runtime/components/Tabs.vue.d.ts +104 -0
  159. package/dist/runtime/components/Textarea.vue +113 -158
  160. package/dist/runtime/components/Textarea.vue.d.ts +95 -0
  161. package/dist/runtime/components/Toast.vue +49 -110
  162. package/dist/runtime/components/Toast.vue.d.ts +95 -0
  163. package/dist/runtime/components/Toaster.vue +70 -107
  164. package/dist/runtime/components/Toaster.vue.d.ts +63 -0
  165. package/dist/runtime/components/Tooltip.vue +38 -65
  166. package/dist/runtime/components/Tooltip.vue.d.ts +65 -0
  167. package/dist/runtime/components/Tree.vue +59 -166
  168. package/dist/runtime/components/Tree.vue.d.ts +128 -0
  169. package/dist/runtime/composables/defineShortcuts.d.ts +1 -1
  170. package/dist/runtime/composables/useAvatarGroup.d.ts +1 -1
  171. package/dist/runtime/composables/useButtonGroup.d.ts +2 -2
  172. package/dist/runtime/composables/useFormField.d.ts +2 -2
  173. package/dist/runtime/composables/useOverlay.d.ts +14 -7
  174. package/dist/runtime/composables/useOverlay.js +14 -6
  175. package/dist/runtime/composables/usePortal.d.ts +6 -0
  176. package/dist/runtime/composables/usePortal.js +17 -0
  177. package/dist/runtime/index.css +1 -1
  178. package/dist/runtime/inertia/components/Link.vue +146 -0
  179. package/dist/runtime/inertia/components/Link.vue.d.ts +92 -0
  180. package/dist/runtime/inertia/stubs.d.ts +43 -0
  181. package/dist/runtime/inertia/stubs.js +82 -0
  182. package/dist/runtime/locale/bg.d.ts +3 -0
  183. package/dist/runtime/locale/bg.js +54 -0
  184. package/dist/runtime/locale/index.d.ts +5 -1
  185. package/dist/runtime/locale/index.js +5 -1
  186. package/dist/runtime/locale/kk.d.ts +3 -0
  187. package/dist/runtime/locale/kk.js +54 -0
  188. package/dist/runtime/locale/tj.d.ts +3 -0
  189. package/dist/runtime/locale/tj.js +54 -0
  190. package/dist/runtime/locale/ug_cn.d.ts +3 -0
  191. package/dist/runtime/locale/ug_cn.js +55 -0
  192. package/dist/runtime/types/form.d.ts +4 -1
  193. package/dist/runtime/types/index.d.ts +1 -0
  194. package/dist/runtime/types/index.js +1 -0
  195. package/dist/runtime/types/utils.d.ts +47 -7
  196. package/dist/runtime/utils/link.d.ts +3 -3
  197. package/dist/runtime/utils/link.js +1 -0
  198. package/dist/runtime/utils/tv.js +2 -2
  199. package/dist/runtime/vue/components/Icon.vue +7 -8
  200. package/dist/runtime/vue/components/Icon.vue.d.ts +14 -0
  201. package/dist/runtime/vue/components/Link.vue +118 -202
  202. package/dist/runtime/vue/components/Link.vue.d.ts +124 -0
  203. package/dist/runtime/vue/stubs.d.ts +2 -2
  204. package/dist/shared/{ui.BkNUP964.mjs → ui.D7lOOabO.mjs} +621 -362
  205. package/dist/types.d.mts +3 -5
  206. package/dist/unplugin.d.mts +4 -0
  207. package/dist/unplugin.mjs +25 -4
  208. package/dist/vite.mjs +1 -1
  209. package/package.json +94 -53
  210. package/dist/module.cjs +0 -62
  211. package/dist/module.d.cts +0 -45
  212. package/dist/module.d.ts +0 -45
  213. package/dist/shared/ui.BL-XB3u1.cjs +0 -3555
  214. package/dist/types.d.ts +0 -7
  215. package/dist/unplugin.cjs +0 -232
  216. package/dist/unplugin.d.cts +0 -62
  217. package/dist/unplugin.d.ts +0 -62
  218. package/dist/vite.cjs +0 -23
  219. package/dist/vite.d.cts +0 -15
  220. package/dist/vite.d.ts +0 -15
@@ -0,0 +1,27 @@
1
+ export interface ContainerProps {
2
+ /**
3
+ * The element or component this component should render as.
4
+ * @defaultValue 'div'
5
+ */
6
+ as?: any;
7
+ class?: any;
8
+ }
9
+ export interface ContainerSlots {
10
+ default(props?: {}): any;
11
+ }
12
+ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<ContainerProps>>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<ContainerProps>>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>, Readonly<ContainerSlots> & ContainerSlots>;
13
+ export default _default;
14
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
15
+ type __VLS_TypePropsToOption<T> = {
16
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
17
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
18
+ } : {
19
+ type: import('vue').PropType<T[K]>;
20
+ required: true;
21
+ };
22
+ };
23
+ type __VLS_WithTemplateSlots<T, S> = T & {
24
+ new (): {
25
+ $slots: S;
26
+ };
27
+ };
@@ -1,137 +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 {
11
- ArrayOrNested,
12
- DynamicSlots,
13
- MergeTypes,
14
- NestedItem,
15
- PartialString,
16
- EmitsToProps
17
- } from '../types/utils'
18
-
19
- const appConfigContextMenu = _appConfig as AppConfig & { ui: { contextMenu: Partial<typeof theme> } }
20
-
21
- const contextMenu = tv({ extend: tv(theme), ...(appConfigContextMenu.ui?.contextMenu || {}) })
22
-
23
- type ContextMenuVariants = VariantProps<typeof contextMenu>
24
-
25
- export interface ContextMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'custom'> {
26
- label?: string
27
- /**
28
- * @IconifyIcon
29
- */
30
- icon?: string
31
- color?: ContextMenuVariants['color']
32
- avatar?: AvatarProps
33
- content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<ContextMenuContentEmits>>
34
- kbds?: KbdProps['value'][] | KbdProps[]
35
- /**
36
- * The item type.
37
- * @defaultValue 'link'
38
- */
39
- type?: 'label' | 'separator' | 'link' | 'checkbox'
40
- slot?: string
41
- loading?: boolean
42
- disabled?: boolean
43
- checked?: boolean
44
- open?: boolean
45
- defaultOpen?: boolean
46
- children?: ArrayOrNested<ContextMenuItem>
47
- onSelect?(e: Event): void
48
- onUpdateChecked?(checked: boolean): void
49
- [key: string]: any
50
- }
51
-
52
- export interface ContextMenuProps<T extends ArrayOrNested<ContextMenuItem> = ArrayOrNested<ContextMenuItem>> extends Omit<ContextMenuRootProps, 'dir'> {
53
- /**
54
- * @defaultValue 'md'
55
- */
56
- size?: ContextMenuVariants['size']
57
- items?: T
58
- /**
59
- * The icon displayed when an item is checked.
60
- * @defaultValue appConfig.ui.icons.check
61
- * @IconifyIcon
62
- */
63
- checkedIcon?: string
64
- /**
65
- * The icon displayed when an item is loading.
66
- * @defaultValue appConfig.ui.icons.loading
67
- * @IconifyIcon
68
- */
69
- loadingIcon?: string
70
- /**
71
- * The icon displayed when the item is an external link.
72
- * Set to `false` to hide the external icon.
73
- * @defaultValue appConfig.ui.icons.external
74
- * @IconifyIcon
75
- */
76
- externalIcon?: boolean | string
77
- /** The content of the menu. */
78
- content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<ContextMenuContentEmits>>
79
- /**
80
- * Render the menu in a portal.
81
- * @defaultValue true
82
- */
83
- portal?: boolean
84
- /**
85
- * The key used to get the label from the item.
86
- * @defaultValue 'label'
87
- */
88
- labelKey?: keyof NestedItem<T>
89
- disabled?: boolean
90
- class?: any
91
- ui?: PartialString<typeof contextMenu.slots>
92
- }
93
-
94
- export interface ContextMenuEmits extends ContextMenuRootEmits {}
95
-
96
- type SlotProps<T extends ContextMenuItem> = (props: { item: T, active?: boolean, index: number }) => any
97
-
98
- export type ContextMenuSlots<
99
- A extends ArrayOrNested<ContextMenuItem> = ArrayOrNested<ContextMenuItem>,
100
- T extends NestedItem<A> = NestedItem<A>
101
- > = {
102
- 'default'(props?: {}): any
103
- 'item': SlotProps<T>
104
- 'item-leading': SlotProps<T>
105
- 'item-label': SlotProps<T>
106
- 'item-trailing': SlotProps<T>
107
- } & DynamicSlots<MergeTypes<T>, 'leading' | 'label' | 'trailing', { active?: boolean, index: number }>
108
-
1
+ <script>
2
+ import theme from "#build/ui/context-menu";
109
3
  </script>
110
4
 
111
- <script setup lang="ts" generic="T extends ArrayOrNested<ContextMenuItem>">
112
- import { computed, toRef } from 'vue'
113
- import { ContextMenuRoot, ContextMenuTrigger, useForwardPropsEmits } from 'reka-ui'
114
- import { reactivePick } from '@vueuse/core'
115
- import { omit } from '../utils'
116
- import UContextMenuContent from './ContextMenuContent.vue'
117
-
118
- const props = withDefaults(defineProps<ContextMenuProps<T>>(), {
119
- portal: true,
120
- modal: true,
121
- externalIcon: true,
122
- labelKey: 'label'
123
- })
124
- const emits = defineEmits<ContextMenuEmits>()
125
- const slots = defineSlots<ContextMenuSlots<T>>()
126
-
127
- const rootProps = useForwardPropsEmits(reactivePick(props, 'modal'), emits)
128
-
129
- const contentProps = toRef(() => props.content)
130
- const proxySlots = omit(slots, ['default'])
131
-
132
- 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 || {} })({
133
34
  size: props.size
134
- }))
35
+ }));
135
36
  </script>
136
37
 
137
38
  <template>
@@ -147,13 +48,13 @@ const ui = computed(() => contextMenu({
147
48
  v-bind="contentProps"
148
49
  :items="items"
149
50
  :portal="portal"
150
- :label-key="(labelKey as keyof NestedItem<T>)"
51
+ :label-key="labelKey"
151
52
  :checked-icon="checkedIcon"
152
53
  :loading-icon="loadingIcon"
153
54
  :external-icon="externalIcon"
154
55
  >
155
56
  <template v-for="(_, name) in proxySlots" #[name]="slotData">
156
- <slot :name="(name as keyof ContextMenuSlots<T>)" v-bind="slotData" />
57
+ <slot :name="name" v-bind="slotData" />
157
58
  </template>
158
59
  </UContextMenuContent>
159
60
  </ContextMenuRoot>
@@ -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,94 +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 { AvatarProps, ContextMenuItem, ContextMenuSlots, KbdProps } from '../types'
6
- import type { ArrayOrNested, NestedItem } from '../types/utils'
1
+ <script>
7
2
 
8
- const _contextMenu = tv(theme)()
9
-
10
- interface ContextMenuContentProps<T extends ArrayOrNested<ContextMenuItem>> extends Omit<RekaContextMenuContentProps, 'as' | 'asChild' | 'forceMount'> {
11
- items?: T
12
- portal?: boolean
13
- sub?: boolean
14
- labelKey: keyof NestedItem<T>
15
- /**
16
- * @IconifyIcon
17
- */
18
- checkedIcon?: string
19
- /**
20
- * @IconifyIcon
21
- */
22
- loadingIcon?: string
23
- /**
24
- * @IconifyIcon
25
- */
26
- externalIcon?: boolean | string
27
- class?: any
28
- ui: typeof _contextMenu
29
- uiOverride?: any
30
- }
31
-
32
- interface ContextMenuContentEmits extends RekaContextMenuContentEmits {}
33
3
  </script>
34
4
 
35
- <script setup lang="ts" generic="T extends ArrayOrNested<ContextMenuItem>">
36
- import { computed } from 'vue'
37
- import { ContextMenu } from 'reka-ui/namespaced'
38
- import { useForwardPropsEmits } from 'reka-ui'
39
- import { reactiveOmit, createReusableTemplate } from '@vueuse/core'
40
- import { useAppConfig } from '#imports'
41
- import { omit, get, isArrayOfArray } from '../utils'
42
- import { pickLinkProps } from '../utils/link'
43
- import ULinkBase from './LinkBase.vue'
44
- import ULink from './Link.vue'
45
- import UAvatar from './Avatar.vue'
46
- import UIcon from './Icon.vue'
47
- import UKbd from './Kbd.vue'
48
- // eslint-disable-next-line import/no-self-import
49
- import UContextMenuContent from './ContextMenuContent.vue'
50
-
51
- const props = defineProps<ContextMenuContentProps<T>>()
52
- const emits = defineEmits<ContextMenuContentEmits>()
53
- const slots = defineSlots<ContextMenuSlots<T>>()
54
-
55
- const appConfig = useAppConfig()
56
- const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'labelKey', 'checkedIcon', 'loadingIcon', 'externalIcon', 'class', 'ui', 'uiOverride'), emits)
57
- const proxySlots = omit(slots, ['default'])
58
-
59
- const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: ContextMenuItem, active?: boolean, index: number }>()
60
-
61
- const groups = computed<ContextMenuItem[][]>(() =>
62
- props.items?.length
63
- ? isArrayOfArray(props.items)
64
- ? props.items
65
- : [props.items]
66
- : []
67
- )
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
+ );
68
56
  </script>
69
57
 
70
58
  <template>
71
59
  <DefineItemTemplate v-slot="{ item, active, index }">
72
- <slot :name="((item.slot || 'item') as keyof ContextMenuSlots<T>)" :item="item" :index="index">
73
- <slot :name="((item.slot ? `${item.slot}-leading`: 'item-leading') as keyof ContextMenuSlots<T>)" :item="item" :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">
74
62
  <UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: uiOverride?.itemLeadingIcon, color: item?.color, loading: true })" />
75
63
  <UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: uiOverride?.itemLeadingIcon, color: item?.color, active })" />
76
- <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 })" />
77
65
  </slot>
78
66
 
79
- <span v-if="get(item, props.labelKey as string) || !!slots[(item.slot ? `${item.slot}-label`: 'item-label') as keyof ContextMenuSlots<T>]" :class="ui.itemLabel({ class: uiOverride?.itemLabel, active })">
80
- <slot :name="((item.slot ? `${item.slot}-label`: 'item-label') as keyof ContextMenuSlots<T>)" :item="item" :active="active" :index="index">
81
- {{ 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) }}
82
70
  </slot>
83
71
 
84
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 })" />
85
73
  </span>
86
74
 
87
75
  <span :class="ui.itemTrailing({ class: uiOverride?.itemTrailing })">
88
- <slot :name="((item.slot ? `${item.slot}-trailing`: 'item-trailing') as keyof ContextMenuSlots<T>)" :item="item" :active="active" :index="index">
89
- <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 })" />
90
78
  <span v-else-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: uiOverride?.itemTrailingKbds })">
91
- <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" />
92
80
  </span>
93
81
  </slot>
94
82
 
@@ -99,8 +87,10 @@ const groups = computed<ContextMenuItem[][]>(() =>
99
87
  </slot>
100
88
  </DefineItemTemplate>
101
89
 
102
- <ContextMenu.Portal :disabled="!portal">
90
+ <ContextMenu.Portal v-bind="portalProps">
103
91
  <component :is="sub ? ContextMenu.SubContent : ContextMenu.Content" :class="props.class" v-bind="contentProps">
92
+ <slot name="content-top" />
93
+
104
94
  <ContextMenu.Group v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: uiOverride?.group })">
105
95
  <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
106
96
  <ContextMenu.Label v-if="item.type === 'label'" :class="ui.label({ class: uiOverride?.label })">
@@ -112,7 +102,7 @@ const groups = computed<ContextMenuItem[][]>(() =>
112
102
  as="button"
113
103
  type="button"
114
104
  :disabled="item.disabled"
115
- :text-value="get(item, props.labelKey as string)"
105
+ :text-value="get(item, props.labelKey)"
116
106
  :class="ui.item({ class: uiOverride?.item, color: item?.color })"
117
107
  >
118
108
  <ReuseItemTemplate :item="item" :index="index" />
@@ -124,7 +114,7 @@ const groups = computed<ContextMenuItem[][]>(() =>
124
114
  :ui="ui"
125
115
  :ui-override="uiOverride"
126
116
  :portal="portal"
127
- :items="(item.children as T)"
117
+ :items="item.children"
128
118
  :align-offset="-4"
129
119
  :label-key="labelKey"
130
120
  :checked-icon="checkedIcon"
@@ -132,8 +122,8 @@ const groups = computed<ContextMenuItem[][]>(() =>
132
122
  :external-icon="externalIcon"
133
123
  v-bind="item.content"
134
124
  >
135
- <template v-for="(_, name) in proxySlots" #[name]="slotData: any">
136
- <slot :name="(name as keyof ContextMenuSlots<T>)" v-bind="slotData" />
125
+ <template v-for="(_, name) in proxySlots" #[name]="slotData">
126
+ <slot :name="name" v-bind="slotData" />
137
127
  </template>
138
128
  </UContextMenuContent>
139
129
  </ContextMenu.Sub>
@@ -141,7 +131,7 @@ const groups = computed<ContextMenuItem[][]>(() =>
141
131
  v-else-if="item.type === 'checkbox'"
142
132
  :model-value="item.checked"
143
133
  :disabled="item.disabled"
144
- :text-value="get(item, props.labelKey as string)"
134
+ :text-value="get(item, props.labelKey)"
145
135
  :class="ui.item({ class: [uiOverride?.item, item.class], color: item?.color })"
146
136
  @update:model-value="item.onUpdateChecked"
147
137
  @select="item.onSelect"
@@ -152,10 +142,10 @@ const groups = computed<ContextMenuItem[][]>(() =>
152
142
  v-else
153
143
  as-child
154
144
  :disabled="item.disabled"
155
- :text-value="get(item, props.labelKey as string)"
145
+ :text-value="get(item, props.labelKey)"
156
146
  @select="item.onSelect"
157
147
  >
158
- <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>
159
149
  <ULinkBase v-bind="slotProps" :class="ui.item({ class: [uiOverride?.item, item.class], active, color: item?.color })">
160
150
  <ReuseItemTemplate :item="item" :active="active" :index="index" />
161
151
  </ULinkBase>
@@ -165,6 +155,8 @@ const groups = computed<ContextMenuItem[][]>(() =>
165
155
  </ContextMenu.Group>
166
156
 
167
157
  <slot />
158
+
159
+ <slot name="content-bottom" />
168
160
  </component>
169
161
  </ContextMenu.Portal>
170
162
  </template>