@nuxt/ui 3.0.0-alpha.12 → 3.0.0-alpha.13

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 (123) hide show
  1. package/.nuxt/ui/accordion.ts +2 -2
  2. package/.nuxt/ui/alert.ts +46 -36
  3. package/.nuxt/ui/avatar-group.ts +1 -1
  4. package/.nuxt/ui/avatar.ts +3 -3
  5. package/.nuxt/ui/badge.ts +37 -28
  6. package/.nuxt/ui/breadcrumb.ts +5 -5
  7. package/.nuxt/ui/button.ts +42 -42
  8. package/.nuxt/ui/calendar.ts +15 -15
  9. package/.nuxt/ui/card.ts +27 -1
  10. package/.nuxt/ui/carousel.ts +2 -2
  11. package/.nuxt/ui/checkbox.ts +18 -18
  12. package/.nuxt/ui/chip.ts +8 -8
  13. package/.nuxt/ui/color-picker.ts +2 -2
  14. package/.nuxt/ui/command-palette.ts +12 -12
  15. package/.nuxt/ui/container.ts +1 -1
  16. package/.nuxt/ui/context-menu.ts +32 -32
  17. package/.nuxt/ui/drawer.ts +72 -11
  18. package/.nuxt/ui/dropdown-menu.ts +33 -33
  19. package/.nuxt/ui/form-field.ts +6 -6
  20. package/.nuxt/ui/input-menu.ts +41 -41
  21. package/.nuxt/ui/input-number.ts +20 -20
  22. package/.nuxt/ui/input.ts +23 -23
  23. package/.nuxt/ui/kbd.ts +4 -4
  24. package/.nuxt/ui/link.ts +3 -3
  25. package/.nuxt/ui/modal.ts +5 -5
  26. package/.nuxt/ui/navigation-menu.ts +77 -78
  27. package/.nuxt/ui/pin-input.ts +20 -20
  28. package/.nuxt/ui/popover.ts +2 -2
  29. package/.nuxt/ui/progress.ts +17 -17
  30. package/.nuxt/ui/radio-group.ts +20 -20
  31. package/.nuxt/ui/select-menu.ts +33 -32
  32. package/.nuxt/ui/select.ts +31 -31
  33. package/.nuxt/ui/separator.ts +8 -8
  34. package/.nuxt/ui/skeleton.ts +1 -1
  35. package/.nuxt/ui/slideover.ts +4 -4
  36. package/.nuxt/ui/slider.ts +16 -16
  37. package/.nuxt/ui/stepper.ts +18 -18
  38. package/.nuxt/ui/switch.ts +20 -20
  39. package/.nuxt/ui/table.ts +16 -16
  40. package/.nuxt/ui/tabs.ts +33 -33
  41. package/.nuxt/ui/textarea.ts +23 -23
  42. package/.nuxt/ui/toast.ts +42 -32
  43. package/.nuxt/ui/toaster.ts +4 -4
  44. package/.nuxt/ui/tooltip.ts +2 -2
  45. package/.nuxt/ui.css +90 -0
  46. package/README.md +2 -2
  47. package/cli/package.json +1 -1
  48. package/cli/templates.mjs +1 -1
  49. package/dist/client/devtools/200.html +1 -1
  50. package/dist/client/devtools/404.html +1 -1
  51. package/dist/client/devtools/_nuxt/CG6Dc4jp.js +1 -0
  52. package/dist/client/devtools/_nuxt/{DYuJNiSW.js → DrNJgD08.js} +1 -1
  53. package/dist/client/devtools/_nuxt/{DLmPhbaq.js → ElqrUh1r.js} +1 -1
  54. package/dist/client/devtools/_nuxt/builds/latest.json +1 -1
  55. package/dist/client/devtools/_nuxt/builds/meta/255c8d0b-7281-4d74-b4b6-ec96e6721aa0.json +1 -0
  56. package/dist/client/devtools/_nuxt/entry.Hn8drx4g.css +1 -0
  57. package/dist/client/devtools/_nuxt/error-404.Dew7w9Ee.css +1 -0
  58. package/dist/client/devtools/_nuxt/error-500.Dep59i31.css +1 -0
  59. package/dist/client/devtools/_nuxt/mC2e7kOs.js +57 -0
  60. package/dist/client/devtools/index.html +1 -1
  61. package/dist/devtools/runtime/examples/CardExample.vue +3 -3
  62. package/dist/devtools/runtime/examples/CollapsibleExample.vue +1 -1
  63. package/dist/devtools/runtime/examples/ContainerExample.vue +1 -1
  64. package/dist/devtools/runtime/examples/ContextMenuExample.vue +1 -1
  65. package/dist/devtools/runtime/examples/PopoverExample.vue +1 -1
  66. package/dist/devtools/runtime/examples/TooltipExample.vue +1 -1
  67. package/dist/module.cjs +2 -1
  68. package/dist/module.json +1 -1
  69. package/dist/module.mjs +2 -1
  70. package/dist/runtime/components/Alert.vue +13 -10
  71. package/dist/runtime/components/App.vue +3 -3
  72. package/dist/runtime/components/Avatar.vue +1 -1
  73. package/dist/runtime/components/Badge.vue +5 -1
  74. package/dist/runtime/components/Calendar.vue +2 -1
  75. package/dist/runtime/components/Card.vue +6 -2
  76. package/dist/runtime/components/CommandPalette.vue +46 -39
  77. package/dist/runtime/components/ContextMenu.vue +8 -0
  78. package/dist/runtime/components/ContextMenuContent.vue +4 -2
  79. package/dist/runtime/components/Drawer.vue +7 -1
  80. package/dist/runtime/components/DropdownMenu.vue +8 -0
  81. package/dist/runtime/components/DropdownMenuContent.vue +4 -2
  82. package/dist/runtime/components/InputNumber.vue +3 -2
  83. package/dist/runtime/components/Modal.vue +15 -1
  84. package/dist/runtime/components/NavigationMenu.vue +31 -11
  85. package/dist/runtime/components/SelectMenu.vue +62 -60
  86. package/dist/runtime/components/Slideover.vue +15 -1
  87. package/dist/runtime/components/Stepper.vue +1 -1
  88. package/dist/runtime/components/Table.vue +94 -16
  89. package/dist/runtime/components/Textarea.vue +2 -1
  90. package/dist/runtime/components/Toast.vue +26 -14
  91. package/dist/runtime/components/Toaster.vue +2 -2
  92. package/dist/runtime/composables/useToast.d.ts +5 -4
  93. package/dist/runtime/composables/useToast.js +2 -2
  94. package/dist/runtime/index.css +1 -1
  95. package/dist/runtime/locale/az.d.ts +2 -0
  96. package/dist/runtime/locale/az.js +54 -0
  97. package/dist/runtime/locale/bn.d.ts +2 -0
  98. package/dist/runtime/locale/bn.js +54 -0
  99. package/dist/runtime/locale/index.d.ts +3 -0
  100. package/dist/runtime/locale/index.js +3 -0
  101. package/dist/runtime/plugins/colors.js +1 -1
  102. package/dist/runtime/types/index.d.ts +1 -0
  103. package/dist/runtime/types/index.js +1 -0
  104. package/dist/runtime/types/utils.d.ts +5 -0
  105. package/dist/runtime/vue/components/Link.vue +75 -16
  106. package/dist/shared/{ui.ClMXjgLK.cjs → ui.C5FzRWM5.cjs} +471 -364
  107. package/dist/shared/{ui.CENZ17mM.mjs → ui.DCZM2pl8.mjs} +467 -364
  108. package/dist/unplugin.cjs +44 -20
  109. package/dist/unplugin.d.cts +10 -0
  110. package/dist/unplugin.d.mts +10 -0
  111. package/dist/unplugin.d.ts +10 -0
  112. package/dist/unplugin.mjs +43 -19
  113. package/dist/vite.cjs +3 -2
  114. package/dist/vite.d.cts +2 -0
  115. package/dist/vite.d.mts +2 -0
  116. package/dist/vite.d.ts +2 -0
  117. package/dist/vite.mjs +3 -2
  118. package/package.json +60 -33
  119. package/dist/client/devtools/_nuxt/CgoQwOTV.js +0 -57
  120. package/dist/client/devtools/_nuxt/builds/meta/3184ffe2-7577-4441-af98-fe6e81c30e3a.json +0 -1
  121. package/dist/client/devtools/_nuxt/entry.ChJczkiN.css +0 -1
  122. package/dist/client/devtools/_nuxt/error-404.DyY3rYaL.css +0 -1
  123. package/dist/client/devtools/_nuxt/error-500.D_1PCaJh.css +0 -1
@@ -53,6 +53,12 @@ export interface NavigationMenuProps<T> extends Pick<NavigationMenuRootProps, 'm
53
53
  * @defaultValue appConfig.ui.icons.chevronDown
54
54
  */
55
55
  trailingIcon?: string
56
+ /**
57
+ * The icon displayed when the item is an external link.
58
+ * Set to `false` to hide the external icon.
59
+ * @defaultValue appConfig.ui.icons.external
60
+ */
61
+ externalIcon?: boolean | string
56
62
  items?: T
57
63
  color?: NavigationMenuVariants['color']
58
64
  variant?: NavigationMenuVariants['variant']
@@ -161,6 +167,7 @@ import UCollapsible from './Collapsible.vue'
161
167
  const props = withDefaults(defineProps<NavigationMenuProps<I>>(), {
162
168
  orientation: 'horizontal',
163
169
  contentOrientation: 'horizontal',
170
+ externalIcon: true,
164
171
  delayDuration: 0,
165
172
  unmountOnHide: true,
166
173
  labelKey: 'label'
@@ -185,7 +192,13 @@ const contentProps = toRef(() => props.content)
185
192
 
186
193
  const appConfig = useAppConfig()
187
194
  const [DefineLinkTemplate, ReuseLinkTemplate] = createReusableTemplate<{ item: NavigationMenuItem, index: number, active?: boolean }>()
188
- const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: NavigationMenuItem, index: number }>()
195
+ const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: NavigationMenuItem, index: number, level?: number }>({
196
+ props: {
197
+ item: Object,
198
+ index: Number,
199
+ level: Number
200
+ }
201
+ })
189
202
 
190
203
  const ui = computed(() => navigationMenu({
191
204
  orientation: props.orientation,
@@ -216,7 +229,7 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
216
229
  {{ get(item, props.labelKey as string) }}
217
230
  </slot>
218
231
 
219
- <UIcon v-if="item.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.linkLabelExternalIcon({ class: props.ui?.linkLabelExternalIcon, active })" />
232
+ <UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.linkLabelExternalIcon({ class: props.ui?.linkLabelExternalIcon, active })" />
220
233
  </span>
221
234
 
222
235
  <span v-if="(!collapsed || orientation !== 'vertical') && (item.badge || (orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) || (orientation === 'vertical' && item.children?.length) || item.trailingIcon || !!slots[item.slot ? `${item.slot}-trailing` : 'item-trailing'])" :class="ui.linkTrailing({ class: props.ui?.linkTrailing })">
@@ -237,27 +250,27 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
237
250
  </slot>
238
251
  </DefineLinkTemplate>
239
252
 
240
- <DefineItemTemplate v-slot="{ item, index }">
253
+ <DefineItemTemplate v-slot="{ item, index, level = 0 }">
241
254
  <component
242
- :is="(orientation === 'vertical' && item.children?.length) ? UCollapsible : NavigationMenuItem"
255
+ :is="(orientation === 'vertical' && item.children?.length && !collapsed) ? UCollapsible : NavigationMenuItem"
243
256
  as="li"
244
257
  :value="item.value || String(index)"
245
258
  :default-open="item.defaultOpen"
246
- :unmount-on-hide="(orientation === 'vertical' && item.children?.length) ? unmountOnHide : undefined"
259
+ :unmount-on-hide="(orientation === 'vertical' && item.children?.length && !collapsed) ? unmountOnHide : undefined"
247
260
  :open="item.open"
248
261
  >
249
262
  <div v-if="orientation === 'vertical' && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
250
263
  <ReuseLinkTemplate :item="(item as T)" :index="index" />
251
264
  </div>
252
- <ULink v-else-if="item.type !== 'label'" v-slot="{ active, ...slotProps }" v-bind="(orientation === 'vertical' && item.children?.length) ? {} : pickLinkProps(item as Omit<NavigationMenuItem, 'type'>)" custom>
265
+ <ULink v-else-if="item.type !== 'label'" v-slot="{ active, ...slotProps }" v-bind="(orientation === 'vertical' && item.children?.length && !collapsed) ? {} : pickLinkProps(item as Omit<NavigationMenuItem, 'type'>)" custom>
253
266
  <component
254
267
  :is="(orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) ? NavigationMenuTrigger : NavigationMenuLink"
255
268
  as-child
256
- :active="active"
269
+ :active="active || item.active"
257
270
  :disabled="item.disabled"
258
271
  @select="item.onSelect"
259
272
  >
260
- <ULinkBase v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.class], active: active || item.active, disabled: !!item.disabled, level: !(orientation === 'vertical' && item.children?.length) })">
273
+ <ULinkBase v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.class], active: active || item.active, disabled: !!item.disabled, level: orientation === 'horizontal' || level > 0 })">
261
274
  <ReuseLinkTemplate :item="(item as T)" :active="active || item.active" :index="index" />
262
275
  </ULinkBase>
263
276
  </component>
@@ -275,7 +288,7 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
275
288
  <p :class="ui.childLinkLabel({ class: props.ui?.childLinkLabel, active: childActive })">
276
289
  {{ get(childItem, props.labelKey as string) }}
277
290
 
278
- <UIcon v-if="childItem.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.childLinkLabelExternalIcon({ class: props.ui?.childLinkLabelExternalIcon, active: childActive })" />
291
+ <UIcon v-if="childItem.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.childLinkLabelExternalIcon({ class: props.ui?.childLinkLabelExternalIcon, active: childActive })" />
279
292
  </p>
280
293
  <p v-if="childItem.description" :class="ui.childLinkDescription({ class: props.ui?.childLinkDescription, active: childActive })">
281
294
  {{ childItem.description }}
@@ -290,9 +303,16 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
290
303
  </NavigationMenuContent>
291
304
  </ULink>
292
305
 
293
- <template v-if="orientation === 'vertical' && item.children?.length" #content>
306
+ <template v-if="orientation === 'vertical' && item.children?.length && !collapsed" #content>
294
307
  <ul :class="ui.childList({ class: props.ui?.childList })">
295
- <ReuseItemTemplate v-for="(childItem, childIndex) in item.children" :key="childIndex" :item="childItem" :index="childIndex" :class="ui.childItem({ class: props.ui?.childItem })" />
308
+ <ReuseItemTemplate
309
+ v-for="(childItem, childIndex) in item.children"
310
+ :key="childIndex"
311
+ :item="childItem"
312
+ :index="childIndex"
313
+ :level="level + 1"
314
+ :class="ui.childItem({ class: props.ui?.childItem })"
315
+ />
296
316
  </ul>
297
317
  </template>
298
318
  </component>
@@ -134,7 +134,7 @@ extendDevtoolsMeta({ defaultProps: { items: ['Option 1', 'Option 2', 'Option 3']
134
134
 
135
135
  <script setup lang="ts" generic="T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<SelectMenuItem | AcceptableValue | boolean> = MaybeArrayOfArray<SelectMenuItem | AcceptableValue | boolean>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false">
136
136
  import { computed, toRef, toRaw } from 'vue'
137
- import { ComboboxRoot, ComboboxArrow, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxPortal, ComboboxContent, ComboboxViewport, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxSeparator, ComboboxItem, ComboboxItemIndicator, useForwardPropsEmits, useFilter } from 'reka-ui'
137
+ import { ComboboxRoot, ComboboxArrow, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxPortal, ComboboxContent, ComboboxViewport, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxSeparator, ComboboxItem, ComboboxItemIndicator, FocusScope, useForwardPropsEmits, useFilter } from 'reka-ui'
138
138
  import { defu } from 'defu'
139
139
  import { reactivePick, createReusableTemplate } from '@vueuse/core'
140
140
  import { useAppConfig } from '#imports'
@@ -337,68 +337,70 @@ function onUpdateOpen(value: boolean) {
337
337
 
338
338
  <ComboboxPortal :disabled="!portal">
339
339
  <ComboboxContent :class="ui.content({ class: props.ui?.content })" v-bind="contentProps">
340
- <ComboboxInput v-if="!!searchInput" v-model="searchTerm" :display-value="() => searchTerm" as-child>
341
- <UInput autofocus autocomplete="off" v-bind="searchInputProps" :class="ui.input({ class: props.ui?.input })" />
342
- </ComboboxInput>
340
+ <FocusScope trapped :class="ui.focusScope({ class: props.ui?.focusScope })">
341
+ <ComboboxInput v-if="!!searchInput" v-model="searchTerm" :display-value="() => searchTerm" as-child>
342
+ <UInput autofocus autocomplete="off" v-bind="searchInputProps" :class="ui.input({ class: props.ui?.input })" />
343
+ </ComboboxInput>
344
+
345
+ <ComboboxEmpty :class="ui.empty({ class: props.ui?.empty })">
346
+ <slot name="empty" :search-term="searchTerm">
347
+ {{ searchTerm ? t('selectMenu.noMatch', { searchTerm }) : t('selectMenu.noData') }}
348
+ </slot>
349
+ </ComboboxEmpty>
350
+
351
+ <ComboboxViewport :class="ui.viewport({ class: props.ui?.viewport })">
352
+ <ReuseCreateItemTemplate v-if="createItem && createItemPosition === 'top'" />
353
+
354
+ <ComboboxGroup v-for="(group, groupIndex) in filteredGroups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
355
+ <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
356
+ <ComboboxLabel v-if="item?.type === 'label'" :class="ui.label({ class: props.ui?.label })">
357
+ {{ get(item, props.labelKey as string) }}
358
+ </ComboboxLabel>
359
+
360
+ <ComboboxSeparator v-else-if="item?.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
361
+
362
+ <ComboboxItem
363
+ v-else
364
+ :class="ui.item({ class: props.ui?.item })"
365
+ :disabled="item.disabled"
366
+ :value="valueKey && typeof item === 'object' ? get(item, props.valueKey as string) : item"
367
+ @select="item.onSelect"
368
+ >
369
+ <slot name="item" :item="(item as T)" :index="index">
370
+ <slot name="item-leading" :item="(item as T)" :index="index">
371
+ <UIcon v-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
372
+ <UAvatar v-else-if="item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
373
+ <UChip
374
+ v-else-if="item.chip"
375
+ :size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
376
+ inset
377
+ standalone
378
+ v-bind="item.chip"
379
+ :class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip })"
380
+ />
381
+ </slot>
343
382
 
344
- <ComboboxEmpty :class="ui.empty({ class: props.ui?.empty })">
345
- <slot name="empty" :search-term="searchTerm">
346
- {{ searchTerm ? t('selectMenu.noMatch', { searchTerm }) : t('selectMenu.noData') }}
347
- </slot>
348
- </ComboboxEmpty>
349
-
350
- <ComboboxViewport :class="ui.viewport({ class: props.ui?.viewport })">
351
- <ReuseCreateItemTemplate v-if="createItem && createItemPosition === 'top'" />
352
-
353
- <ComboboxGroup v-for="(group, groupIndex) in filteredGroups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
354
- <template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
355
- <ComboboxLabel v-if="item?.type === 'label'" :class="ui.label({ class: props.ui?.label })">
356
- {{ get(item, props.labelKey as string) }}
357
- </ComboboxLabel>
358
-
359
- <ComboboxSeparator v-else-if="item?.type === 'separator'" :class="ui.separator({ class: props.ui?.separator })" />
360
-
361
- <ComboboxItem
362
- v-else
363
- :class="ui.item({ class: props.ui?.item })"
364
- :disabled="item.disabled"
365
- :value="valueKey && typeof item === 'object' ? get(item, props.valueKey as string) : item"
366
- @select="item.onSelect"
367
- >
368
- <slot name="item" :item="(item as T)" :index="index">
369
- <slot name="item-leading" :item="(item as T)" :index="index">
370
- <UIcon v-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon })" />
371
- <UAvatar v-else-if="item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar })" />
372
- <UChip
373
- v-else-if="item.chip"
374
- :size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
375
- inset
376
- standalone
377
- v-bind="item.chip"
378
- :class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip })"
379
- />
383
+ <span :class="ui.itemLabel({ class: props.ui?.itemLabel })">
384
+ <slot name="item-label" :item="(item as T)" :index="index">
385
+ {{ typeof item === 'object' ? get(item, props.labelKey as string) : item }}
386
+ </slot>
387
+ </span>
388
+
389
+ <span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
390
+ <slot name="item-trailing" :item="(item as T)" :index="index" />
391
+
392
+ <ComboboxItemIndicator as-child>
393
+ <UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
394
+ </ComboboxItemIndicator>
395
+ </span>
380
396
  </slot>
397
+ </ComboboxItem>
398
+ </template>
399
+ </ComboboxGroup>
381
400
 
382
- <span :class="ui.itemLabel({ class: props.ui?.itemLabel })">
383
- <slot name="item-label" :item="(item as T)" :index="index">
384
- {{ typeof item === 'object' ? get(item, props.labelKey as string) : item }}
385
- </slot>
386
- </span>
387
-
388
- <span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
389
- <slot name="item-trailing" :item="(item as T)" :index="index" />
390
-
391
- <ComboboxItemIndicator as-child>
392
- <UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
393
- </ComboboxItemIndicator>
394
- </span>
395
- </slot>
396
- </ComboboxItem>
397
- </template>
398
- </ComboboxGroup>
399
-
400
- <ReuseCreateItemTemplate v-if="createItem && createItemPosition === 'bottom'" />
401
- </ComboboxViewport>
401
+ <ReuseCreateItemTemplate v-if="createItem && createItemPosition === 'bottom'" />
402
+ </ComboboxViewport>
403
+ </FocusScope>
402
404
 
403
405
  <ComboboxArrow v-if="!!arrow" v-bind="arrowProps" :class="ui.arrow({ class: props.ui?.arrow })" />
404
406
  </ComboboxContent>
@@ -73,7 +73,7 @@ extendDevtoolsMeta({ example: 'SlideoverExample' })
73
73
 
74
74
  <script setup lang="ts">
75
75
  import { computed, toRef } from 'vue'
76
- import { DialogRoot, DialogTrigger, DialogPortal, DialogOverlay, DialogContent, DialogTitle, DialogDescription, DialogClose, useForwardPropsEmits } from 'reka-ui'
76
+ import { DialogRoot, DialogTrigger, DialogPortal, DialogOverlay, DialogContent, DialogTitle, DialogDescription, DialogClose, VisuallyHidden, useForwardPropsEmits } from 'reka-ui'
77
77
  import { reactivePick } from '@vueuse/core'
78
78
  import { useAppConfig } from '#imports'
79
79
  import { useLocale } from '../composables/useLocale'
@@ -124,6 +124,20 @@ const ui = computed(() => slideover({
124
124
  <DialogOverlay v-if="overlay" :class="ui.overlay({ class: props.ui?.overlay })" />
125
125
 
126
126
  <DialogContent :data-side="side" :class="ui.content({ class: [!slots.default && props.class, props.ui?.content] })" v-bind="contentProps" v-on="contentEvents">
127
+ <VisuallyHidden v-if="!!slots.content && ((title || !!slots.title) || (description || !!slots.description))">
128
+ <DialogTitle v-if="title || !!slots.title">
129
+ <slot name="title">
130
+ {{ title }}
131
+ </slot>
132
+ </DialogTitle>
133
+
134
+ <DialogDescription v-if="description || !!slots.description">
135
+ <slot name="description">
136
+ {{ description }}
137
+ </slot>
138
+ </DialogDescription>
139
+ </VisuallyHidden>
140
+
127
141
  <slot name="content">
128
142
  <div v-if="!!slots.header || (title || !!slots.title) || (description || !!slots.description) || (close || !!slots.close)" :class="ui.header({ class: props.ui?.header })">
129
143
  <slot name="header">
@@ -163,7 +163,7 @@ defineExpose({
163
163
 
164
164
  <div v-if="currentStep?.content || !!slots.content || (currentStep?.slot && !!slots[currentStep.slot]) || (currentStep?.value && !!slots[currentStep.value])" :class="ui.content({ class: props.ui?.description })">
165
165
  <slot
166
- :name="!!slots[currentStep?.slot ?? currentStep.value] ? currentStep.slot ?? currentStep.value : 'content'"
166
+ :name="!!slots[currentStep?.slot ?? currentStep.value!] ? currentStep.slot ?? currentStep.value : 'content'"
167
167
  :item="currentStep"
168
168
  >
169
169
  {{ currentStep?.content }}
@@ -5,24 +5,36 @@ import type { VariantProps } from 'tailwind-variants'
5
5
  import type { AppConfig } from '@nuxt/schema'
6
6
  import type { RowData } from '@tanstack/table-core'
7
7
  import type {
8
- Row,
8
+ CellContext,
9
9
  ColumnDef,
10
+ ColumnFiltersOptions,
10
11
  ColumnFiltersState,
12
+ ColumnOrderState,
13
+ ColumnPinningOptions,
11
14
  ColumnPinningState,
12
- RowSelectionState,
13
- SortingState,
15
+ ColumnSizingInfoState,
16
+ ColumnSizingOptions,
17
+ ColumnSizingState,
18
+ CoreOptions,
19
+ ExpandedOptions,
14
20
  ExpandedState,
15
- VisibilityState,
21
+ FacetedOptions,
16
22
  GlobalFilterOptions,
17
- ColumnFiltersOptions,
18
- ColumnPinningOptions,
19
- VisibilityOptions,
20
- ExpandedOptions,
21
- SortingOptions,
23
+ GroupingOptions,
24
+ GroupingState,
25
+ HeaderContext,
26
+ PaginationOptions,
27
+ PaginationState,
28
+ Row,
29
+ RowPinningOptions,
30
+ RowPinningState,
22
31
  RowSelectionOptions,
32
+ RowSelectionState,
33
+ SortingOptions,
34
+ SortingState,
23
35
  Updater,
24
- CellContext,
25
- HeaderContext
36
+ VisibilityOptions,
37
+ VisibilityState
26
38
  } from '@tanstack/vue-table'
27
39
  import _appConfig from '#build/app.config'
28
40
  import theme from '#build/ui/table'
@@ -44,13 +56,17 @@ const table = tv({ extend: tv(theme), ...(appConfigTable.ui?.table || {}) })
44
56
 
45
57
  type TableVariants = VariantProps<typeof table>
46
58
 
47
- export type TableColumn<T> = ColumnDef<T>
59
+ export type TableData = RowData
60
+
61
+ export type TableColumn<T extends TableData, D = unknown> = ColumnDef<T, D>
48
62
 
49
- export interface TableData {
50
- [key: string]: any
63
+ export interface TableOptions<T extends TableData> extends Omit<CoreOptions<T>, 'data' | 'columns' | 'getCoreRowModel' | 'state' | 'onStateChange' | 'renderFallbackValue'> {
64
+ state?: CoreOptions<T>['state']
65
+ onStateChange?: CoreOptions<T>['onStateChange']
66
+ renderFallbackValue?: CoreOptions<T>['renderFallbackValue']
51
67
  }
52
68
 
53
- export interface TableProps<T> {
69
+ export interface TableProps<T extends TableData> extends TableOptions<T> {
54
70
  /**
55
71
  * The element or component this component should render as.
56
72
  * @defaultValue 'div'
@@ -83,6 +99,11 @@ export interface TableProps<T> {
83
99
  * @link [Guide](https://tanstack.com/table/v8/docs/guide/column-pinning)
84
100
  */
85
101
  columnPinningOptions?: Omit<ColumnPinningOptions, 'onColumnPinningChange'>
102
+ /**
103
+ * @link [API Docs](https://tanstack.com/table/v8/docs/api/features/column-sizing#table-options)
104
+ * @link [Guide](https://tanstack.com/table/v8/docs/guide/column-sizing)
105
+ */
106
+ columnSizingOptions?: Omit<ColumnSizingOptions, 'onColumnSizingChange' | 'onColumnSizingInfoChange'>
86
107
  /**
87
108
  * @link [API Docs](https://tanstack.com/table/v8/docs/api/features/column-visibility#table-options)
88
109
  * @link [Guide](https://tanstack.com/table/v8/docs/guide/column-visibility)
@@ -93,6 +114,11 @@ export interface TableProps<T> {
93
114
  * @link [Guide](https://tanstack.com/table/v8/docs/guide/sorting)
94
115
  */
95
116
  sortingOptions?: Omit<SortingOptions<T>, 'getSortedRowModel' | 'onSortingChange'>
117
+ /**
118
+ * @link [API Docs](https://tanstack.com/table/v8/docs/api/features/grouping#table-options)
119
+ * @link [Guide](https://tanstack.com/table/v8/docs/guide/grouping)
120
+ */
121
+ groupingOptions?: Omit<GroupingOptions, 'onGroupingChange'>
96
122
  /**
97
123
  * @link [API Docs](https://tanstack.com/table/v8/docs/api/features/expanding#table-options)
98
124
  * @link [Guide](https://tanstack.com/table/v8/docs/guide/expanding)
@@ -103,6 +129,21 @@ export interface TableProps<T> {
103
129
  * @link [Guide](https://tanstack.com/table/v8/docs/guide/row-selection)
104
130
  */
105
131
  rowSelectionOptions?: Omit<RowSelectionOptions<T>, 'onRowSelectionChange'>
132
+ /**
133
+ * @link [API Docs](https://tanstack.com/table/v8/docs/api/features/row-pinning#table-options)
134
+ * @link [Guide](https://tanstack.com/table/v8/docs/guide/row-pinning)
135
+ */
136
+ rowPinningOptions?: Omit<RowPinningOptions<T>, 'onRowPinningChange'>
137
+ /**
138
+ * @link [API Docs](https://tanstack.com/table/v8/docs/api/features/pagination#table-options)
139
+ * @link [Guide](https://tanstack.com/table/v8/docs/guide/pagination)
140
+ */
141
+ paginationOptions?: Omit<PaginationOptions, 'onPaginationChange'>
142
+ /**
143
+ * @link [API Docs](https://tanstack.com/table/v8/docs/api/features/column-faceting#table-options)
144
+ * @link [Guide](https://tanstack.com/table/v8/docs/guide/column-faceting)
145
+ */
146
+ facetedOptions?: FacetedOptions<T>
106
147
  class?: any
107
148
  ui?: Partial<typeof table.slots>
108
149
  }
@@ -121,8 +162,9 @@ export type TableSlots<T> = {
121
162
  <script setup lang="ts" generic="T extends TableData">
122
163
  import { computed } from 'vue'
123
164
  import { Primitive } from 'reka-ui'
124
- import { FlexRender, getCoreRowModel, getFilteredRowModel, getSortedRowModel, getExpandedRowModel, useVueTable } from '@tanstack/vue-table'
125
165
  import { upperFirst } from 'scule'
166
+ import { FlexRender, getCoreRowModel, getFilteredRowModel, getSortedRowModel, getExpandedRowModel, useVueTable } from '@tanstack/vue-table'
167
+ import { reactiveOmit } from '@vueuse/core'
126
168
  import { useLocale } from '../composables/useLocale'
127
169
 
128
170
  const props = defineProps<TableProps<T>>()
@@ -142,13 +184,20 @@ const ui = computed(() => table({
142
184
 
143
185
  const globalFilterState = defineModel<string>('globalFilter', { default: undefined })
144
186
  const columnFiltersState = defineModel<ColumnFiltersState>('columnFilters', { default: [] })
187
+ const columnOrderState = defineModel<ColumnOrderState>('columnOrder', { default: [] })
145
188
  const columnVisibilityState = defineModel<VisibilityState>('columnVisibility', { default: {} })
146
189
  const columnPinningState = defineModel<ColumnPinningState>('columnPinning', { default: {} })
190
+ const columnSizingState = defineModel<ColumnSizingState>('columnSizing', { default: {} })
191
+ const columnSizingInfoState = defineModel<ColumnSizingInfoState>('columnSizingInfo', { default: {} })
147
192
  const rowSelectionState = defineModel<RowSelectionState>('rowSelection', { default: {} })
193
+ const rowPinningState = defineModel<RowPinningState>('rowPinning', { default: {} })
148
194
  const sortingState = defineModel<SortingState>('sorting', { default: [] })
195
+ const groupingState = defineModel<GroupingState>('grouping', { default: [] })
149
196
  const expandedState = defineModel<ExpandedState>('expanded', { default: {} })
197
+ const paginationState = defineModel<PaginationState>('pagination', { default: {} })
150
198
 
151
199
  const tableApi = useVueTable({
200
+ ...reactiveOmit(props, 'as', 'data', 'columns', 'caption', 'sticky', 'loading', 'loadingColor', 'loadingAnimation', 'class', 'ui'),
152
201
  data,
153
202
  columns: columns.value,
154
203
  getCoreRowModel: getCoreRowModel(),
@@ -157,18 +206,29 @@ const tableApi = useVueTable({
157
206
  ...(props.columnFiltersOptions || {}),
158
207
  getFilteredRowModel: getFilteredRowModel(),
159
208
  onColumnFiltersChange: updaterOrValue => valueUpdater(updaterOrValue, columnFiltersState),
209
+ onColumnOrderChange: updaterOrValue => valueUpdater(updaterOrValue, columnOrderState),
160
210
  ...(props.visibilityOptions || {}),
161
211
  onColumnVisibilityChange: updaterOrValue => valueUpdater(updaterOrValue, columnVisibilityState),
162
212
  ...(props.columnPinningOptions || {}),
163
213
  onColumnPinningChange: updaterOrValue => valueUpdater(updaterOrValue, columnPinningState),
214
+ ...(props.columnSizingOptions || {}),
215
+ onColumnSizingChange: updaterOrValue => valueUpdater(updaterOrValue, columnSizingState),
216
+ onColumnSizingInfoChange: updaterOrValue => valueUpdater(updaterOrValue, columnSizingInfoState),
164
217
  ...(props.rowSelectionOptions || {}),
165
218
  onRowSelectionChange: updaterOrValue => valueUpdater(updaterOrValue, rowSelectionState),
219
+ ...(props.rowPinningOptions || {}),
220
+ onRowPinningChange: updaterOrValue => valueUpdater(updaterOrValue, rowPinningState),
166
221
  ...(props.sortingOptions || {}),
167
222
  getSortedRowModel: getSortedRowModel(),
168
223
  onSortingChange: updaterOrValue => valueUpdater(updaterOrValue, sortingState),
224
+ ...(props.groupingOptions || {}),
225
+ onGroupingChange: updaterOrValue => valueUpdater(updaterOrValue, groupingState),
169
226
  ...(props.expandedOptions || {}),
170
227
  getExpandedRowModel: getExpandedRowModel(),
171
228
  onExpandedChange: updaterOrValue => valueUpdater(updaterOrValue, expandedState),
229
+ ...(props.paginationOptions || {}),
230
+ onPaginationChange: updaterOrValue => valueUpdater(updaterOrValue, paginationState),
231
+ ...(props.facetedOptions || {}),
172
232
  state: {
173
233
  get globalFilter() {
174
234
  return globalFilterState.value
@@ -176,6 +236,9 @@ const tableApi = useVueTable({
176
236
  get columnFilters() {
177
237
  return columnFiltersState.value
178
238
  },
239
+ get columnOrder() {
240
+ return columnOrderState.value
241
+ },
179
242
  get columnVisibility() {
180
243
  return columnVisibilityState.value
181
244
  },
@@ -190,6 +253,21 @@ const tableApi = useVueTable({
190
253
  },
191
254
  get sorting() {
192
255
  return sortingState.value
256
+ },
257
+ get grouping() {
258
+ return groupingState.value
259
+ },
260
+ get rowPinning() {
261
+ return rowPinningState.value
262
+ },
263
+ get columnSizing() {
264
+ return columnSizingState.value
265
+ },
266
+ get columnSizingInfo() {
267
+ return columnSizingInfoState.value
268
+ },
269
+ get pagination() {
270
+ return paginationState.value
193
271
  }
194
272
  }
195
273
  })
@@ -4,6 +4,7 @@ import type { AppConfig } from '@nuxt/schema'
4
4
  import _appConfig from '#build/app.config'
5
5
  import theme from '#build/ui/textarea'
6
6
  import { tv } from '../utils/tv'
7
+ import type { PartialString } from '../types/utils'
7
8
 
8
9
  const appConfigTextarea = _appConfig as AppConfig & { ui: { textarea: Partial<typeof theme> } }
9
10
 
@@ -34,7 +35,7 @@ export interface TextareaProps {
34
35
  autoresize?: boolean
35
36
  /** Highlight the ring color like a focus state. */
36
37
  highlight?: boolean
37
- ui?: Partial<typeof textarea.slots>
38
+ ui?: PartialString<typeof textarea.slots>
38
39
  }
39
40
 
40
41
  export interface TextareaEmits {
@@ -7,6 +7,7 @@ import theme from '#build/ui/toast'
7
7
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
8
8
  import { tv } from '../utils/tv'
9
9
  import type { AvatarProps, ButtonProps } from '../types'
10
+ import type { StringOrVNode } from '../types/utils'
10
11
 
11
12
  const appConfigToast = _appConfig as AppConfig & { ui: { toast: Partial<typeof theme> } }
12
13
 
@@ -20,15 +21,16 @@ export interface ToastProps extends Pick<ToastRootProps, 'defaultOpen' | 'open'
20
21
  * @defaultValue 'li'
21
22
  */
22
23
  as?: any
23
- title?: string
24
- description?: string
24
+ title?: StringOrVNode
25
+ description?: StringOrVNode
25
26
  icon?: string
26
27
  avatar?: AvatarProps
27
28
  color?: ToastVariants['color']
29
+ orientation?: ToastVariants['orientation']
28
30
  /**
29
31
  * Display a list of actions:
30
- * - under the title and description if multiline
31
- * - next to the close button if not multiline
32
+ * - under the title and description when orientation is `vertical`
33
+ * - next to the close button when orientation is `horizontal`
32
34
  * `{ size: 'xs' }`{lang="ts-type"}
33
35
  */
34
36
  actions?: ButtonProps[]
@@ -71,7 +73,8 @@ import UAvatar from './Avatar.vue'
71
73
  import UButton from './Button.vue'
72
74
 
73
75
  const props = withDefaults(defineProps<ToastProps>(), {
74
- close: true
76
+ close: true,
77
+ orientation: 'vertical'
75
78
  })
76
79
  const emits = defineEmits<ToastEmits>()
77
80
  const slots = defineSlots<ToastSlots>()
@@ -81,10 +84,10 @@ const appConfig = useAppConfig()
81
84
 
82
85
  const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'defaultOpen', 'open', 'duration', 'type'), emits)
83
86
 
84
- const multiline = computed(() => !!props.title && !!props.description)
85
-
86
87
  const ui = computed(() => toast({
87
- color: props.color
88
+ color: props.color,
89
+ orientation: props.orientation,
90
+ title: !!props.title || !!slots.title
88
91
  }))
89
92
 
90
93
  const el = ref()
@@ -110,7 +113,8 @@ defineExpose({
110
113
  ref="el"
111
114
  v-slot="{ remaining, duration }"
112
115
  v-bind="rootProps"
113
- :class="ui.root({ class: [props.class, props.ui?.root], multiline })"
116
+ :data-orientation="orientation"
117
+ :class="ui.root({ class: [props.class, props.ui?.root] })"
114
118
  :style="{ '--height': height }"
115
119
  >
116
120
  <slot name="leading">
@@ -121,16 +125,24 @@ defineExpose({
121
125
  <div :class="ui.wrapper({ class: props.ui?.wrapper })">
122
126
  <ToastTitle v-if="title || !!slots.title" :class="ui.title({ class: props.ui?.title })">
123
127
  <slot name="title">
124
- {{ title }}
128
+ <component :is="title()" v-if="typeof title === 'function'" />
129
+ <component :is="title" v-else-if="typeof title === 'object'" />
130
+ <template v-else>
131
+ {{ title }}
132
+ </template>
125
133
  </slot>
126
134
  </ToastTitle>
127
135
  <ToastDescription v-if="description || !!slots.description" :class="ui.description({ class: props.ui?.description })">
128
136
  <slot name="description">
129
- {{ description }}
137
+ <component :is="description()" v-if="typeof description === 'function'" />
138
+ <component :is="description" v-else-if="typeof description === 'object'" />
139
+ <template v-else>
140
+ {{ description }}
141
+ </template>
130
142
  </slot>
131
143
  </ToastDescription>
132
144
 
133
- <div v-if="multiline && actions?.length" :class="ui.actions({ class: props.ui?.actions, multiline: true })">
145
+ <div v-if="orientation === 'vertical' && actions?.length" :class="ui.actions({ class: props.ui?.actions })">
134
146
  <slot name="actions">
135
147
  <ToastAction v-for="(action, index) in actions" :key="index" :alt-text="action.label || 'Action'" as-child @click.stop>
136
148
  <UButton size="xs" :color="color" v-bind="action" />
@@ -139,8 +151,8 @@ defineExpose({
139
151
  </div>
140
152
  </div>
141
153
 
142
- <div v-if="(!multiline && actions?.length) || close !== null" :class="ui.actions({ class: props.ui?.actions, multiline: false })">
143
- <template v-if="!multiline">
154
+ <div v-if="(orientation === 'horizontal' && actions?.length) || close" :class="ui.actions({ class: props.ui?.actions, orientation: 'horizontal' })">
155
+ <template v-if="orientation === 'horizontal' && actions?.length">
144
156
  <slot name="actions">
145
157
  <ToastAction v-for="(action, index) in actions" :key="index" :alt-text="action.label || 'Action'" as-child @click.stop>
146
158
  <UButton size="xs" :color="color" v-bind="action" />
@@ -121,10 +121,10 @@ function getOffset(index: number) {
121
121
  '--transform': 'translateY(var(--translate)) scale(var(--scale))'
122
122
  }"
123
123
  :class="[ui.base(), {
124
- 'cursor-pointer': !!toast.click
124
+ 'cursor-pointer': !!toast.onClick
125
125
  }]"
126
126
  @update:open="onUpdateOpen($event, toast.id)"
127
- @click="toast.click && toast.click(toast)"
127
+ @click="toast.onClick && toast.onClick(toast)"
128
128
  />
129
129
 
130
130
  <ToastPortal :disabled="!portal">