@nuxt/ui 2.11.1 → 2.12.1

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 (74) hide show
  1. package/dist/module.d.mts +100 -28
  2. package/dist/module.d.ts +100 -28
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +2 -2
  5. package/dist/runtime/components/data/Table.vue +26 -18
  6. package/dist/runtime/components/data/Table.vue.d.ts +21 -12
  7. package/dist/runtime/components/elements/Accordion.vue +8 -4
  8. package/dist/runtime/components/elements/Accordion.vue.d.ts +4 -4
  9. package/dist/runtime/components/elements/Alert.vue +8 -2
  10. package/dist/runtime/components/elements/Alert.vue.d.ts +5 -10
  11. package/dist/runtime/components/elements/Button.vue +6 -3
  12. package/dist/runtime/components/elements/Button.vue.d.ts +119 -1
  13. package/dist/runtime/components/elements/Chip.vue.d.ts +2 -2
  14. package/dist/runtime/components/elements/Dropdown.vue +66 -17
  15. package/dist/runtime/components/elements/Dropdown.vue.d.ts +31 -4
  16. package/dist/runtime/components/elements/Link.vue +9 -4
  17. package/dist/runtime/components/elements/Link.vue.d.ts +194 -4
  18. package/dist/runtime/components/forms/Form.vue +16 -7
  19. package/dist/runtime/components/forms/Form.vue.d.ts +1 -1
  20. package/dist/runtime/components/forms/Input.vue +1 -1
  21. package/dist/runtime/components/forms/Input.vue.d.ts +1 -1
  22. package/dist/runtime/components/forms/InputMenu.vue +419 -0
  23. package/dist/runtime/components/forms/InputMenu.vue.d.ts +332 -0
  24. package/dist/runtime/components/forms/RadioGroup.vue +1 -1
  25. package/dist/runtime/components/forms/Select.vue +1 -1
  26. package/dist/runtime/components/forms/Select.vue.d.ts +1 -1
  27. package/dist/runtime/components/forms/SelectMenu.vue +70 -21
  28. package/dist/runtime/components/forms/SelectMenu.vue.d.ts +31 -10
  29. package/dist/runtime/components/forms/Toggle.vue +1 -1
  30. package/dist/runtime/components/forms/Toggle.vue.d.ts +2 -1
  31. package/dist/runtime/components/layout/Divider.vue +4 -5
  32. package/dist/runtime/components/navigation/Breadcrumb.vue +8 -5
  33. package/dist/runtime/components/navigation/Breadcrumb.vue.d.ts +4 -2
  34. package/dist/runtime/components/navigation/CommandPalette.vue.d.ts +3 -3
  35. package/dist/runtime/components/navigation/Pagination.vue +9 -4
  36. package/dist/runtime/components/navigation/Pagination.vue.d.ts +9 -0
  37. package/dist/runtime/components/navigation/VerticalNavigation.vue +53 -38
  38. package/dist/runtime/components/navigation/VerticalNavigation.vue.d.ts +8 -5
  39. package/dist/runtime/components/overlays/Modal.vue.d.ts +1 -1
  40. package/dist/runtime/components/overlays/Popover.vue +49 -13
  41. package/dist/runtime/components/overlays/Popover.vue.d.ts +14 -4
  42. package/dist/runtime/components/overlays/Slideover.vue.d.ts +1 -1
  43. package/dist/runtime/components/overlays/Tooltip.vue +1 -1
  44. package/dist/runtime/composables/useShortcuts.mjs +3 -1
  45. package/dist/runtime/types/alert.d.ts +5 -0
  46. package/dist/runtime/types/breadcrumb.d.ts +1 -0
  47. package/dist/runtime/types/chip.d.ts +4 -0
  48. package/dist/runtime/types/dropdown.d.ts +2 -0
  49. package/dist/runtime/types/form.d.ts +1 -0
  50. package/dist/runtime/types/index.d.ts +1 -0
  51. package/dist/runtime/types/link.d.ts +3 -0
  52. package/dist/runtime/types/tooltip.d.ts +7 -0
  53. package/dist/runtime/types/vertical-navigation.d.ts +1 -0
  54. package/dist/runtime/ui.config/forms/input.mjs +12 -12
  55. package/dist/runtime/ui.config/forms/inputMenu.d.ts +64 -0
  56. package/dist/runtime/ui.config/forms/inputMenu.mjs +62 -0
  57. package/dist/runtime/ui.config/forms/selectMenu.d.ts +14 -12
  58. package/dist/runtime/ui.config/forms/selectMenu.mjs +7 -41
  59. package/dist/runtime/ui.config/index.d.ts +1 -0
  60. package/dist/runtime/ui.config/index.mjs +1 -0
  61. package/dist/runtime/ui.config/layout/card.mjs +1 -1
  62. package/dist/runtime/ui.config/navigation/breadcrumb.d.ts +1 -0
  63. package/dist/runtime/ui.config/navigation/breadcrumb.mjs +1 -0
  64. package/dist/runtime/ui.config/navigation/verticalNavigation.d.ts +5 -0
  65. package/dist/runtime/ui.config/navigation/verticalNavigation.mjs +5 -0
  66. package/dist/runtime/ui.config/popper.mjs +2 -1
  67. package/dist/runtime/utils/index.d.ts +1 -0
  68. package/dist/runtime/utils/index.mjs +12 -3
  69. package/dist/runtime/utils/link.d.ts +58 -0
  70. package/dist/runtime/utils/link.mjs +111 -0
  71. package/dist/runtime/utils/uid.mjs +2 -1
  72. package/dist/types.d.mts +2 -2
  73. package/dist/types.d.ts +1 -1
  74. package/package.json +31 -28
@@ -13,7 +13,6 @@ declare const _default: import("vue").DefineComponent<{
13
13
  rows: {
14
14
  type: PropType<{
15
15
  [key: string]: any;
16
- click?: Function | undefined;
17
16
  }[]>;
18
17
  default: () => never[];
19
18
  };
@@ -22,6 +21,7 @@ declare const _default: import("vue").DefineComponent<{
22
21
  [key: string]: any;
23
22
  key: string;
24
23
  sortable?: boolean | undefined;
24
+ sort?: ((a: any, b: any, direction: 'asc' | 'desc') => number) | undefined;
25
25
  direction?: "asc" | "desc" | undefined;
26
26
  class?: string | undefined;
27
27
  }[]>;
@@ -38,6 +38,10 @@ declare const _default: import("vue").DefineComponent<{
38
38
  }>;
39
39
  default: () => {};
40
40
  };
41
+ sortMode: {
42
+ type: PropType<"auto" | "manual">;
43
+ default: string;
44
+ };
41
45
  sortButton: {
42
46
  type: PropType<Button>;
43
47
  default: () => Button;
@@ -81,20 +85,20 @@ declare const _default: import("vue").DefineComponent<{
81
85
  attrs: import("vue").ComputedRef<Pick<{
82
86
  [x: string]: unknown;
83
87
  }, string>>;
84
- sort: import("vue").Ref<{
85
- direction: string;
88
+ sort: import("vue").WritableComputedRef<{
86
89
  column: string;
90
+ direction: 'asc' | 'desc';
87
91
  }>;
88
92
  columns: import("vue").ComputedRef<{
89
93
  [key: string]: any;
90
94
  key: string;
91
95
  sortable?: boolean | undefined;
96
+ sort?: ((a: any, b: any, direction: 'asc' | 'desc') => number) | undefined;
92
97
  direction?: "asc" | "desc" | undefined;
93
98
  class?: string | undefined;
94
99
  }[]>;
95
100
  rows: import("vue").ComputedRef<{
96
101
  [key: string]: any;
97
- click?: Function | undefined;
98
102
  }[]>;
99
103
  selected: import("vue").WritableComputedRef<unknown[]>;
100
104
  indeterminate: import("vue").ComputedRef<boolean>;
@@ -120,7 +124,6 @@ declare const _default: import("vue").DefineComponent<{
120
124
  rows: {
121
125
  type: PropType<{
122
126
  [key: string]: any;
123
- click?: Function | undefined;
124
127
  }[]>;
125
128
  default: () => never[];
126
129
  };
@@ -129,6 +132,7 @@ declare const _default: import("vue").DefineComponent<{
129
132
  [key: string]: any;
130
133
  key: string;
131
134
  sortable?: boolean | undefined;
135
+ sort?: ((a: any, b: any, direction: 'asc' | 'desc') => number) | undefined;
132
136
  direction?: "asc" | "desc" | undefined;
133
137
  class?: string | undefined;
134
138
  }[]>;
@@ -145,6 +149,10 @@ declare const _default: import("vue").DefineComponent<{
145
149
  }>;
146
150
  default: () => {};
147
151
  };
152
+ sortMode: {
153
+ type: PropType<"auto" | "manual">;
154
+ default: string;
155
+ };
148
156
  sortButton: {
149
157
  type: PropType<Button>;
150
158
  default: () => Button;
@@ -192,21 +200,22 @@ declare const _default: import("vue").DefineComponent<{
192
200
  direction: 'asc' | 'desc';
193
201
  };
194
202
  ui: any;
195
- class: any;
196
- modelValue: unknown[];
197
- by: string | Function;
198
- rows: {
199
- [key: string]: any;
200
- click?: Function | undefined;
201
- }[];
202
203
  columns: {
203
204
  [key: string]: any;
204
205
  key: string;
205
206
  sortable?: boolean | undefined;
207
+ sort?: ((a: any, b: any, direction: 'asc' | 'desc') => number) | undefined;
206
208
  direction?: "asc" | "desc" | undefined;
207
209
  class?: string | undefined;
208
210
  }[];
211
+ class: any;
212
+ modelValue: unknown[];
213
+ by: string | Function;
214
+ rows: {
215
+ [key: string]: any;
216
+ }[];
209
217
  columnAttribute: string;
218
+ sortMode: "auto" | "manual";
210
219
  sortButton: Button;
211
220
  sortAscIcon: string;
212
221
  sortDescIcon: string;
@@ -108,20 +108,24 @@ export default defineComponent({
108
108
  }
109
109
  });
110
110
  }
111
- function onEnter(el, done) {
111
+ function onEnter(_el, done) {
112
+ const el = _el;
112
113
  el.style.height = "0";
113
114
  el.offsetHeight;
114
115
  el.style.height = el.scrollHeight + "px";
115
116
  el.addEventListener("transitionend", done, { once: true });
116
117
  }
117
- function onBeforeLeave(el) {
118
+ function onBeforeLeave(_el) {
119
+ const el = _el;
118
120
  el.style.height = el.scrollHeight + "px";
119
121
  el.offsetHeight;
120
122
  }
121
- function onAfterEnter(el) {
123
+ function onAfterEnter(_el) {
124
+ const el = _el;
122
125
  el.style.height = "auto";
123
126
  }
124
- function onLeave(el, done) {
127
+ function onLeave(_el, done) {
128
+ const el = _el;
125
129
  el.style.height = "0";
126
130
  el.addEventListener("transitionend", done, { once: true });
127
131
  }
@@ -42,10 +42,10 @@ declare const _default: import("vue").DefineComponent<{
42
42
  }[]>;
43
43
  closeOthers: (currentIndex: number, e: Event) => void;
44
44
  omit: typeof omit;
45
- onEnter: (el: HTMLElement, done: any) => void;
46
- onBeforeLeave: (el: HTMLElement) => void;
47
- onAfterEnter: (el: HTMLElement) => void;
48
- onLeave: (el: HTMLElement, done: any) => void;
45
+ onEnter: (_el: Element, done: () => void) => void;
46
+ onBeforeLeave: (_el: Element) => void;
47
+ onAfterEnter: (_el: Element) => void;
48
+ onLeave: (_el: Element, done: () => void) => void;
49
49
  }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
50
50
  items: {
51
51
  type: PropType<AccordionItem[]>;
@@ -17,12 +17,12 @@
17
17
  </p>
18
18
 
19
19
  <div v-if="(description || $slots.description) && actions.length" :class="ui.actions">
20
- <UButton v-for="(action, index) of actions" :key="index" v-bind="{ ...(ui.default.actionButton || {}), ...action }" @click.stop="action.click" />
20
+ <UButton v-for="(action, index) of actions" :key="index" v-bind="{ ...(ui.default.actionButton || {}), ...action }" @click.stop="onAction(action)" />
21
21
  </div>
22
22
  </div>
23
23
  <div v-if="closeButton || (!description && !$slots.description && actions.length)" :class="twMerge(ui.actions, 'mt-0')">
24
24
  <template v-if="!description && !$slots.description && actions.length">
25
- <UButton v-for="(action, index) of actions" :key="index" v-bind="{ ...(ui.default.actionButton || {}), ...action }" @click.stop="action.click" />
25
+ <UButton v-for="(action, index) of actions" :key="index" v-bind="{ ...(ui.default.actionButton || {}), ...action }" @click.stop="onAction(action)" />
26
26
  </template>
27
27
 
28
28
  <UButton v-if="closeButton" aria-label="Close" v-bind="{ ...(ui.default.closeButton || {}), ...closeButton }" @click.stop="$emit('close')" />
@@ -113,11 +113,17 @@ export default defineComponent({
113
113
  variant?.replaceAll("{color}", props.color)
114
114
  ), props.class);
115
115
  });
116
+ function onAction(action) {
117
+ if (action.click) {
118
+ action.click();
119
+ }
120
+ }
116
121
  return {
117
122
  // eslint-disable-next-line vue/no-dupe-keys
118
123
  ui,
119
124
  attrs,
120
125
  alertClass,
126
+ onAction,
121
127
  twMerge
122
128
  };
123
129
  }
@@ -1,5 +1,5 @@
1
1
  import type { PropType } from 'vue';
2
- import type { Avatar, Button, AlertVariant } from '../../types';
2
+ import type { Avatar, Button, AlertVariant, AlertAction } from '../../types';
3
3
  declare const _default: import("vue").DefineComponent<{
4
4
  title: {
5
5
  type: StringConstructor;
@@ -22,9 +22,7 @@ declare const _default: import("vue").DefineComponent<{
22
22
  default: () => Button;
23
23
  };
24
24
  actions: {
25
- type: PropType<(Button & {
26
- click?: Function | undefined;
27
- })[]>;
25
+ type: PropType<AlertAction[]>;
28
26
  default: () => never[];
29
27
  };
30
28
  color: {
@@ -51,6 +49,7 @@ declare const _default: import("vue").DefineComponent<{
51
49
  [x: string]: unknown;
52
50
  }, string>>;
53
51
  alertClass: import("vue").ComputedRef<string>;
52
+ onAction: (action: AlertAction) => void;
54
53
  twMerge: (...classLists: import("tailwind-merge").ClassNameValue[]) => string;
55
54
  }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "close"[], "close", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
56
55
  title: {
@@ -74,9 +73,7 @@ declare const _default: import("vue").DefineComponent<{
74
73
  default: () => Button;
75
74
  };
76
75
  actions: {
77
- type: PropType<(Button & {
78
- click?: Function | undefined;
79
- })[]>;
76
+ type: PropType<AlertAction[]>;
80
77
  default: () => never[];
81
78
  };
82
79
  color: {
@@ -105,9 +102,7 @@ declare const _default: import("vue").DefineComponent<{
105
102
  icon: string;
106
103
  avatar: Avatar;
107
104
  closeButton: Button;
108
- actions: (Button & {
109
- click?: Function | undefined;
110
- })[];
105
+ actions: AlertAction[];
111
106
  color: any;
112
107
  class: any;
113
108
  variant: AlertVariant;
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <ULink :type="type" :disabled="disabled || loading" :class="buttonClass" v-bind="attrs">
2
+ <ULink :type="type" :disabled="disabled || loading" :class="buttonClass" v-bind="{ ...linkProps, ...attrs }">
3
3
  <slot name="leading" :disabled="disabled" :loading="loading">
4
4
  <UIcon v-if="isLeading && leadingIconName" :name="leadingIconName" :class="leadingIconClass" aria-hidden="true" />
5
5
  </slot>
@@ -22,7 +22,7 @@ import { twMerge, twJoin } from "tailwind-merge";
22
22
  import UIcon from "../elements/Icon.vue";
23
23
  import ULink from "../elements/Link.vue";
24
24
  import { useUI } from "../../composables/useUI";
25
- import { mergeConfig } from "../../utils";
25
+ import { mergeConfig, nuxtLinkProps, getNuxtLinkProps } from "../../utils";
26
26
  import { useInjectButtonGroup } from "../../composables/useButtonGroup";
27
27
  import appConfig from "#build/app.config";
28
28
  import { button } from "#ui/ui.config";
@@ -34,6 +34,7 @@ export default defineComponent({
34
34
  },
35
35
  inheritAttrs: false,
36
36
  props: {
37
+ ...nuxtLinkProps,
37
38
  type: {
38
39
  type: String,
39
40
  default: "button"
@@ -172,6 +173,7 @@ export default defineComponent({
172
173
  props.loading && !isLeading.value && ui.value.icon.loading
173
174
  );
174
175
  });
176
+ const linkProps = computed(() => getNuxtLinkProps(props));
175
177
  return {
176
178
  // eslint-disable-next-line vue/no-dupe-keys
177
179
  ui,
@@ -183,7 +185,8 @@ export default defineComponent({
183
185
  leadingIconName,
184
186
  trailingIconName,
185
187
  leadingIconClass,
186
- trailingIconClass
188
+ trailingIconClass,
189
+ linkProps
187
190
  };
188
191
  }
189
192
  });
@@ -80,6 +80,58 @@ declare const _default: import("vue").DefineComponent<{
80
80
  type: PropType<any>;
81
81
  default: () => {};
82
82
  };
83
+ to: {
84
+ readonly type: PropType<import("vue-router").RouteLocationRaw>;
85
+ readonly default: undefined;
86
+ };
87
+ href: {
88
+ readonly type: PropType<import("vue-router").RouteLocationRaw>;
89
+ readonly default: undefined;
90
+ };
91
+ target: {
92
+ readonly type: PropType<(string & {}) | "_blank" | "_parent" | "_self" | "_top" | null>;
93
+ readonly default: undefined;
94
+ };
95
+ rel: {
96
+ readonly type: StringConstructor;
97
+ readonly default: undefined;
98
+ };
99
+ noRel: {
100
+ readonly type: BooleanConstructor;
101
+ readonly default: undefined;
102
+ };
103
+ prefetch: {
104
+ readonly type: BooleanConstructor;
105
+ readonly default: undefined;
106
+ };
107
+ noPrefetch: {
108
+ readonly type: BooleanConstructor;
109
+ readonly default: undefined;
110
+ };
111
+ activeClass: {
112
+ readonly type: StringConstructor;
113
+ readonly default: undefined;
114
+ };
115
+ exactActiveClass: {
116
+ readonly type: StringConstructor;
117
+ readonly default: undefined;
118
+ };
119
+ prefetchedClass: {
120
+ readonly type: StringConstructor;
121
+ readonly default: undefined;
122
+ };
123
+ replace: {
124
+ readonly type: BooleanConstructor;
125
+ readonly default: undefined;
126
+ };
127
+ ariaCurrentValue: {
128
+ readonly type: StringConstructor;
129
+ readonly default: undefined;
130
+ };
131
+ external: {
132
+ readonly type: BooleanConstructor;
133
+ readonly default: undefined;
134
+ };
83
135
  }, {
84
136
  ui: import("vue").ComputedRef<any>;
85
137
  attrs: import("vue").ComputedRef<Pick<{
@@ -93,6 +145,7 @@ declare const _default: import("vue").DefineComponent<{
93
145
  trailingIconName: import("vue").ComputedRef<string | undefined>;
94
146
  leadingIconClass: import("vue").ComputedRef<string>;
95
147
  trailingIconClass: import("vue").ComputedRef<string>;
148
+ linkProps: import("vue").ComputedRef<{}>;
96
149
  }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
97
150
  type: {
98
151
  type: StringConstructor;
@@ -173,6 +226,58 @@ declare const _default: import("vue").DefineComponent<{
173
226
  type: PropType<any>;
174
227
  default: () => {};
175
228
  };
229
+ to: {
230
+ readonly type: PropType<import("vue-router").RouteLocationRaw>;
231
+ readonly default: undefined;
232
+ };
233
+ href: {
234
+ readonly type: PropType<import("vue-router").RouteLocationRaw>;
235
+ readonly default: undefined;
236
+ };
237
+ target: {
238
+ readonly type: PropType<(string & {}) | "_blank" | "_parent" | "_self" | "_top" | null>;
239
+ readonly default: undefined;
240
+ };
241
+ rel: {
242
+ readonly type: StringConstructor;
243
+ readonly default: undefined;
244
+ };
245
+ noRel: {
246
+ readonly type: BooleanConstructor;
247
+ readonly default: undefined;
248
+ };
249
+ prefetch: {
250
+ readonly type: BooleanConstructor;
251
+ readonly default: undefined;
252
+ };
253
+ noPrefetch: {
254
+ readonly type: BooleanConstructor;
255
+ readonly default: undefined;
256
+ };
257
+ activeClass: {
258
+ readonly type: StringConstructor;
259
+ readonly default: undefined;
260
+ };
261
+ exactActiveClass: {
262
+ readonly type: StringConstructor;
263
+ readonly default: undefined;
264
+ };
265
+ prefetchedClass: {
266
+ readonly type: StringConstructor;
267
+ readonly default: undefined;
268
+ };
269
+ replace: {
270
+ readonly type: BooleanConstructor;
271
+ readonly default: undefined;
272
+ };
273
+ ariaCurrentValue: {
274
+ readonly type: StringConstructor;
275
+ readonly default: undefined;
276
+ };
277
+ external: {
278
+ readonly type: BooleanConstructor;
279
+ readonly default: undefined;
280
+ };
176
281
  }>>, {
177
282
  size: ButtonSize;
178
283
  ui: any;
@@ -180,6 +285,8 @@ declare const _default: import("vue").DefineComponent<{
180
285
  icon: string;
181
286
  color: any;
182
287
  type: string;
288
+ leading: boolean;
289
+ replace: boolean;
183
290
  class: any;
184
291
  label: string;
185
292
  loading: boolean;
@@ -191,7 +298,18 @@ declare const _default: import("vue").DefineComponent<{
191
298
  leadingIcon: string;
192
299
  trailingIcon: string;
193
300
  trailing: boolean;
194
- leading: boolean;
195
301
  square: boolean;
302
+ to: import("vue-router").RouteLocationRaw;
303
+ href: import("vue-router").RouteLocationRaw;
304
+ target: (string & {}) | "_blank" | "_parent" | "_self" | "_top" | null;
305
+ rel: string;
306
+ noRel: boolean;
307
+ prefetch: boolean;
308
+ noPrefetch: boolean;
309
+ activeClass: string;
310
+ exactActiveClass: string;
311
+ prefetchedClass: string;
312
+ ariaCurrentValue: string;
313
+ external: boolean;
196
314
  }, {}>;
197
315
  export default _default;
@@ -81,10 +81,10 @@ declare const _default: import("vue").DefineComponent<{
81
81
  size: "sm" | "3xs" | "md" | "xs" | "2xs" | "lg" | "xl" | "2xl" | "3xl";
82
82
  ui: any;
83
83
  color: any;
84
+ inset: boolean;
85
+ position: "top-right" | "bottom-right" | "top-left" | "bottom-left";
84
86
  class: any;
85
87
  text: string | number;
86
- position: "top-right" | "bottom-right" | "top-left" | "bottom-left";
87
- inset: boolean;
88
88
  show: boolean;
89
89
  }, {}>;
90
90
  export default _default;
@@ -1,4 +1,5 @@
1
1
  <template>
2
+ <!-- eslint-disable-next-line vue/no-template-shadow -->
2
3
  <HMenu v-slot="{ open }" as="div" :class="ui.wrapper" v-bind="attrs" @mouseleave="onMouseLeave">
3
4
  <HMenuButton
4
5
  ref="trigger"
@@ -19,23 +20,24 @@
19
20
  <Transition appear v-bind="ui.transition">
20
21
  <div>
21
22
  <div v-if="popper.arrow" data-popper-arrow :class="Object.values(ui.arrow)" />
23
+
22
24
  <HMenuItems :class="[ui.base, ui.divide, ui.ring, ui.rounded, ui.shadow, ui.background, ui.height]" static>
23
25
  <div v-for="(subItems, index) of items" :key="index" :class="ui.padding">
24
- <NuxtLink v-for="(item, subIndex) of subItems" :key="subIndex" v-slot="{ href, target, rel, navigate, isExternal }" v-bind="omit(item, ['label', 'slot', 'icon', 'iconClass', 'avatar', 'shortcuts', 'disabled', 'click'])" custom>
26
+ <NuxtLink v-for="(item, subIndex) of subItems" :key="subIndex" v-slot="{ href, target, rel, navigate, isExternal }" v-bind="getNuxtLinkProps(item)" custom>
25
27
  <HMenuItem v-slot="{ active, disabled: itemDisabled, close }" :disabled="item.disabled">
26
28
  <component
27
29
  :is="!!href ? 'a' : 'button'"
28
30
  :href="!itemDisabled ? href : undefined"
29
31
  :rel="rel"
30
32
  :target="target"
31
- :class="[ui.item.base, ui.item.padding, ui.item.size, ui.item.rounded, active ? ui.item.active : ui.item.inactive, itemDisabled && ui.item.disabled]"
33
+ :class="twMerge(twJoin(ui.item.base, ui.item.padding, ui.item.size, ui.item.rounded, active ? ui.item.active : ui.item.inactive, itemDisabled && ui.item.disabled), item.class)"
32
34
  @click="onClick($event, item, { href, navigate, close, isExternal })"
33
35
  >
34
36
  <slot :name="item.slot || 'item'" :item="item">
35
- <UIcon v-if="item.icon" :name="item.icon" :class="[ui.item.icon.base, active ? ui.item.icon.active : ui.item.icon.inactive, item.iconClass]" />
37
+ <UIcon v-if="item.icon" :name="item.icon" :class="twMerge(twJoin(ui.item.icon.base, active ? ui.item.icon.active : ui.item.icon.inactive), item.iconClass)" />
36
38
  <UAvatar v-else-if="item.avatar" v-bind="{ size: ui.item.avatar.size, ...item.avatar }" :class="ui.item.avatar.base" />
37
39
 
38
- <span :class="ui.item.label">{{ item.label }}</span>
40
+ <span :class="twMerge(ui.item.label, item.labelClass)">{{ item.label }}</span>
39
41
 
40
42
  <span v-if="item.shortcuts?.length" :class="ui.item.shortcuts">
41
43
  <UKbd v-for="shortcut of item.shortcuts" :key="shortcut">{{ shortcut }}</UKbd>
@@ -53,15 +55,16 @@
53
55
  </template>
54
56
 
55
57
  <script>
56
- import { defineComponent, ref, computed, toRef, onMounted, resolveComponent } from "vue";
58
+ import { defineComponent, ref, computed, watch, toRef, onMounted, resolveComponent } from "vue";
57
59
  import { Menu as HMenu, MenuButton as HMenuButton, MenuItems as HMenuItems, MenuItem as HMenuItem } from "@headlessui/vue";
58
60
  import { defu } from "defu";
61
+ import { twMerge, twJoin } from "tailwind-merge";
59
62
  import UIcon from "../elements/Icon.vue";
60
63
  import UAvatar from "../elements/Avatar.vue";
61
64
  import UKbd from "../elements/Kbd.vue";
62
65
  import { useUI } from "../../composables/useUI";
63
66
  import { usePopper } from "../../composables/usePopper";
64
- import { mergeConfig, omit } from "../../utils";
67
+ import { mergeConfig, getNuxtLinkProps } from "../../utils";
65
68
  import appConfig from "#build/app.config";
66
69
  import { dropdown } from "#ui/ui.config";
67
70
  const config = mergeConfig(appConfig.ui.strategy, appConfig.ui.dropdown, dropdown);
@@ -86,6 +89,10 @@ export default defineComponent({
86
89
  default: "click",
87
90
  validator: (value) => ["click", "hover"].includes(value)
88
91
  },
92
+ open: {
93
+ type: Boolean,
94
+ default: void 0
95
+ },
89
96
  disabled: {
90
97
  type: Boolean,
91
98
  default: false
@@ -111,7 +118,8 @@ export default defineComponent({
111
118
  default: () => ({})
112
119
  }
113
120
  },
114
- setup(props) {
121
+ emits: ["update:open"],
122
+ setup(props, { emit }) {
115
123
  const { ui, attrs } = useUI("dropdown", toRef(props, "ui"), config, toRef(props, "class"));
116
124
  const popper = computed(() => defu(props.mode === "hover" ? { offsetDistance: 0 } : {}, props.popper, ui.value.popper));
117
125
  const [trigger, container] = usePopper(popper.value);
@@ -119,18 +127,41 @@ export default defineComponent({
119
127
  let openTimeout = null;
120
128
  let closeTimeout = null;
121
129
  onMounted(() => {
122
- setTimeout(() => {
123
- const menuProvides = trigger.value?.$.provides;
124
- if (!menuProvides) {
125
- return;
126
- }
127
- const menuProvidesSymbols = Object.getOwnPropertySymbols(menuProvides);
128
- menuApi.value = menuProvidesSymbols.length && menuProvides[menuProvidesSymbols[0]];
129
- }, 200);
130
+ const menuProvides = trigger.value?.$.provides;
131
+ if (!menuProvides) {
132
+ return;
133
+ }
134
+ const menuProvidesSymbols = Object.getOwnPropertySymbols(menuProvides);
135
+ menuApi.value = menuProvidesSymbols.length && menuProvides[menuProvidesSymbols[0]];
136
+ if (props.open) {
137
+ menuApi.value?.openMenu();
138
+ }
130
139
  });
131
140
  const containerStyle = computed(() => {
141
+ if (props.mode !== "hover") {
142
+ return {};
143
+ }
132
144
  const offsetDistance = props.popper?.offsetDistance || ui.value.popper?.offsetDistance || 8;
133
- return props.mode === "hover" ? { paddingTop: `${offsetDistance}px`, paddingBottom: `${offsetDistance}px` } : {};
145
+ const placement = popper.value.placement?.split("-")[0];
146
+ const padding = `${offsetDistance}px`;
147
+ if (placement === "top" || placement === "bottom") {
148
+ return {
149
+ paddingTop: padding,
150
+ paddingBottom: padding
151
+ };
152
+ } else if (placement === "left" || placement === "right") {
153
+ return {
154
+ paddingLeft: padding,
155
+ paddingRight: padding
156
+ };
157
+ } else {
158
+ return {
159
+ paddingTop: padding,
160
+ paddingBottom: padding,
161
+ paddingLeft: padding,
162
+ paddingRight: padding
163
+ };
164
+ }
134
165
  });
135
166
  function onMouseOver() {
136
167
  if (props.mode !== "hover" || !menuApi.value) {
@@ -173,6 +204,22 @@ export default defineComponent({
173
204
  close();
174
205
  }
175
206
  }
207
+ watch(() => props.open, (newValue, oldValue) => {
208
+ if (!menuApi.value)
209
+ return;
210
+ if (oldValue === void 0 || newValue === oldValue)
211
+ return;
212
+ if (newValue) {
213
+ menuApi.value.openMenu();
214
+ } else {
215
+ menuApi.value.closeMenu();
216
+ }
217
+ });
218
+ watch(() => menuApi.value?.menuState, (newValue, oldValue) => {
219
+ if (oldValue === void 0 || newValue === oldValue)
220
+ return;
221
+ emit("update:open", newValue === 0);
222
+ });
176
223
  const NuxtLink = resolveComponent("NuxtLink");
177
224
  return {
178
225
  // eslint-disable-next-line vue/no-dupe-keys
@@ -186,7 +233,9 @@ export default defineComponent({
186
233
  onMouseOver,
187
234
  onMouseLeave,
188
235
  onClick,
189
- omit,
236
+ getNuxtLinkProps,
237
+ twMerge,
238
+ twJoin,
190
239
  NuxtLink
191
240
  };
192
241
  }