@nuxt/ui 3.0.0-alpha.10 → 3.0.0-alpha.11

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 (172) hide show
  1. package/.nuxt/ui/alert.ts +75 -58
  2. package/.nuxt/ui/avatar-group.ts +13 -1
  3. package/.nuxt/ui/avatar.ts +13 -1
  4. package/.nuxt/ui/badge.ts +102 -65
  5. package/.nuxt/ui/button-group.ts +13 -0
  6. package/.nuxt/ui/button.ts +124 -92
  7. package/.nuxt/ui/calendar.ts +20 -2
  8. package/.nuxt/ui/carousel.ts +5 -3
  9. package/.nuxt/ui/checkbox.ts +27 -9
  10. package/.nuxt/ui/chip.ts +36 -7
  11. package/.nuxt/ui/color-picker.ts +9 -1
  12. package/.nuxt/ui/context-menu.ts +32 -14
  13. package/.nuxt/ui/drawer.ts +11 -4
  14. package/.nuxt/ui/dropdown-menu.ts +32 -14
  15. package/.nuxt/ui/form-field.ts +9 -1
  16. package/.nuxt/ui/input-menu.ts +110 -75
  17. package/.nuxt/ui/input-number.ts +82 -51
  18. package/.nuxt/ui/input.ts +88 -53
  19. package/.nuxt/ui/kbd.ts +14 -2
  20. package/.nuxt/ui/navigation-menu.ts +114 -68
  21. package/.nuxt/ui/pin-input.ts +57 -31
  22. package/.nuxt/ui/popover.ts +1 -1
  23. package/.nuxt/ui/progress.ts +93 -54
  24. package/.nuxt/ui/radio-group.ts +25 -2
  25. package/.nuxt/ui/select-menu.ts +89 -54
  26. package/.nuxt/ui/select.ts +89 -54
  27. package/.nuxt/ui/separator.ts +52 -23
  28. package/.nuxt/ui/slideover.ts +11 -4
  29. package/.nuxt/ui/slider.ts +45 -22
  30. package/.nuxt/ui/stepper.ts +45 -23
  31. package/.nuxt/ui/switch.ts +20 -2
  32. package/.nuxt/ui/table.ts +30 -13
  33. package/.nuxt/ui/tabs.ts +67 -39
  34. package/.nuxt/ui/textarea.ts +88 -53
  35. package/.nuxt/ui/toast.ts +11 -1
  36. package/.nuxt/ui/toaster.ts +27 -11
  37. package/.nuxt/ui/tooltip.ts +1 -1
  38. package/README.md +8 -1
  39. package/cli/commands/make/component.mjs +12 -0
  40. package/cli/package.json +2 -2
  41. package/cli/templates.mjs +17 -12
  42. package/dist/client/devtools/200.html +1 -1
  43. package/dist/client/devtools/404.html +1 -1
  44. package/dist/client/devtools/_nuxt/CQ-XZFu7.js +54 -0
  45. package/dist/client/devtools/_nuxt/DNZFyo26.js +1 -0
  46. package/dist/client/devtools/_nuxt/Dtz-o9GB.js +1 -0
  47. package/dist/client/devtools/_nuxt/builds/latest.json +1 -1
  48. package/dist/client/devtools/_nuxt/builds/meta/1f5fbd7b-9d97-480e-9ae4-e02b4ff7018b.json +1 -0
  49. package/dist/client/devtools/_nuxt/entry.qOdop8tq.css +1 -0
  50. package/dist/client/devtools/_nuxt/error-404.D-rS9BDk.css +1 -0
  51. package/dist/client/devtools/_nuxt/error-500.CfcCHs91.css +1 -0
  52. package/dist/client/devtools/index.html +1 -1
  53. package/dist/module.cjs +1 -1
  54. package/dist/module.json +1 -1
  55. package/dist/module.mjs +1 -1
  56. package/dist/runtime/components/Accordion.vue +2 -1
  57. package/dist/runtime/components/Alert.vue +3 -2
  58. package/dist/runtime/components/Avatar.vue +5 -4
  59. package/dist/runtime/components/AvatarGroup.vue +2 -1
  60. package/dist/runtime/components/Badge.vue +2 -1
  61. package/dist/runtime/components/Breadcrumb.vue +1 -1
  62. package/dist/runtime/components/Button.vue +2 -1
  63. package/dist/runtime/components/ButtonGroup.vue +2 -1
  64. package/dist/runtime/components/Calendar.vue +2 -1
  65. package/dist/runtime/components/Card.vue +1 -1
  66. package/dist/runtime/components/Carousel.vue +2 -1
  67. package/dist/runtime/components/Checkbox.vue +2 -1
  68. package/dist/runtime/components/Chip.vue +3 -2
  69. package/dist/runtime/components/Collapsible.vue +4 -2
  70. package/dist/runtime/components/ColorPicker.vue +2 -1
  71. package/dist/runtime/components/CommandPalette.vue +12 -5
  72. package/dist/runtime/components/Container.vue +1 -1
  73. package/dist/runtime/components/ContextMenu.vue +2 -1
  74. package/dist/runtime/components/ContextMenuContent.vue +3 -3
  75. package/dist/runtime/components/Drawer.vue +7 -2
  76. package/dist/runtime/components/DropdownMenu.vue +2 -1
  77. package/dist/runtime/components/DropdownMenuContent.vue +3 -3
  78. package/dist/runtime/components/Form.vue +15 -14
  79. package/dist/runtime/components/FormField.vue +2 -1
  80. package/dist/runtime/components/Input.vue +3 -2
  81. package/dist/runtime/components/InputMenu.vue +13 -2
  82. package/dist/runtime/components/InputNumber.vue +2 -1
  83. package/dist/runtime/components/Kbd.vue +2 -1
  84. package/dist/runtime/components/Link.vue +1 -1
  85. package/dist/runtime/components/Modal.vue +8 -13
  86. package/dist/runtime/components/NavigationMenu.vue +14 -9
  87. package/dist/runtime/components/Pagination.vue +1 -1
  88. package/dist/runtime/components/PinInput.vue +4 -3
  89. package/dist/runtime/components/Popover.vue +7 -6
  90. package/dist/runtime/components/Progress.vue +4 -3
  91. package/dist/runtime/components/RadioGroup.vue +2 -1
  92. package/dist/runtime/components/Select.vue +3 -2
  93. package/dist/runtime/components/SelectMenu.vue +20 -4
  94. package/dist/runtime/components/Separator.vue +2 -1
  95. package/dist/runtime/components/Skeleton.vue +1 -1
  96. package/dist/runtime/components/Slideover.vue +8 -12
  97. package/dist/runtime/components/Slider.vue +2 -1
  98. package/dist/runtime/components/Stepper.vue +6 -4
  99. package/dist/runtime/components/Switch.vue +2 -1
  100. package/dist/runtime/components/Table.vue +2 -1
  101. package/dist/runtime/components/Tabs.vue +3 -1
  102. package/dist/runtime/components/Textarea.vue +3 -2
  103. package/dist/runtime/components/Toast.vue +2 -1
  104. package/dist/runtime/components/Toaster.vue +2 -1
  105. package/dist/runtime/components/Tooltip.vue +1 -1
  106. package/dist/runtime/composables/defineShortcuts.js +1 -1
  107. package/dist/runtime/composables/useFormField.d.ts +1 -1
  108. package/dist/runtime/composables/useFormField.js +6 -3
  109. package/dist/runtime/locale/ar.js +3 -1
  110. package/dist/runtime/locale/cs.js +3 -1
  111. package/dist/runtime/locale/da.d.ts +2 -0
  112. package/dist/runtime/locale/da.js +54 -0
  113. package/dist/runtime/locale/de.js +3 -1
  114. package/dist/runtime/locale/el.d.ts +2 -0
  115. package/dist/runtime/locale/el.js +54 -0
  116. package/dist/runtime/locale/en.js +3 -1
  117. package/dist/runtime/locale/es.js +3 -1
  118. package/dist/runtime/locale/et.d.ts +2 -0
  119. package/dist/runtime/locale/et.js +54 -0
  120. package/dist/runtime/locale/fa_ir.js +3 -1
  121. package/dist/runtime/locale/fi.d.ts +2 -0
  122. package/dist/runtime/locale/fi.js +54 -0
  123. package/dist/runtime/locale/fr.js +3 -1
  124. package/dist/runtime/locale/id.d.ts +2 -0
  125. package/dist/runtime/locale/id.js +54 -0
  126. package/dist/runtime/locale/index.d.ts +9 -0
  127. package/dist/runtime/locale/index.js +9 -0
  128. package/dist/runtime/locale/it.js +3 -1
  129. package/dist/runtime/locale/ja.js +3 -1
  130. package/dist/runtime/locale/ko.js +3 -1
  131. package/dist/runtime/locale/nl.js +3 -1
  132. package/dist/runtime/locale/pl.js +3 -1
  133. package/dist/runtime/locale/pt.js +3 -1
  134. package/dist/runtime/locale/pt_br.js +3 -1
  135. package/dist/runtime/locale/ru.js +3 -1
  136. package/dist/runtime/locale/sk.js +3 -1
  137. package/dist/runtime/locale/sv.d.ts +2 -0
  138. package/dist/runtime/locale/sv.js +54 -0
  139. package/dist/runtime/locale/th.d.ts +2 -0
  140. package/dist/runtime/locale/th.js +54 -0
  141. package/dist/runtime/locale/tr.js +3 -1
  142. package/dist/runtime/locale/uk.d.ts +2 -0
  143. package/dist/runtime/locale/uk.js +54 -0
  144. package/dist/runtime/locale/vi.d.ts +2 -0
  145. package/dist/runtime/locale/vi.js +54 -0
  146. package/dist/runtime/locale/zh_hans.js +3 -1
  147. package/dist/runtime/locale/zh_hant.js +11 -9
  148. package/dist/runtime/types/form.d.ts +2 -2
  149. package/dist/runtime/types/form.js +2 -2
  150. package/dist/runtime/types/locale.d.ts +2 -0
  151. package/dist/runtime/utils/form.d.ts +2 -2
  152. package/dist/runtime/utils/form.js +3 -3
  153. package/dist/runtime/utils/tv.d.ts +1 -0
  154. package/dist/runtime/utils/tv.js +4 -0
  155. package/dist/runtime/vue/components/Icon.vue +2 -2
  156. package/dist/runtime/vue/plugins/head.d.ts +1 -1
  157. package/dist/runtime/vue/plugins/head.js +3 -3
  158. package/dist/shared/{ui.D_93iuwH.mjs → ui.BKsd22-Q.mjs} +63 -36
  159. package/dist/shared/{ui.CwmIkD_Y.cjs → ui.DCjJwb6l.cjs} +63 -36
  160. package/dist/unplugin.cjs +5 -5
  161. package/dist/unplugin.mjs +5 -5
  162. package/dist/vite.cjs +1 -1
  163. package/dist/vite.mjs +1 -1
  164. package/package.json +49 -44
  165. package/dist/client/devtools/_nuxt/B1fTd_Rf.js +0 -1
  166. package/dist/client/devtools/_nuxt/CSUxkedg.js +0 -1
  167. package/dist/client/devtools/_nuxt/CbRTGpb7.js +0 -1
  168. package/dist/client/devtools/_nuxt/YQTlxbcT.js +0 -53
  169. package/dist/client/devtools/_nuxt/builds/meta/b3465abc-0a92-4ee7-ba6b-e5174891fcc0.json +0 -1
  170. package/dist/client/devtools/_nuxt/entry.DXXceQev.css +0 -1
  171. package/dist/client/devtools/_nuxt/error-404.BJpkZFyY.css +0 -1
  172. package/dist/client/devtools/_nuxt/error-500.D3i9VDlt.css +0 -1
@@ -1,5 +1,4 @@
1
1
  <script lang="ts">
2
- import { tv } from 'tailwind-variants'
3
2
  import type { ListboxRootProps, ListboxRootEmits } from 'reka-ui'
4
3
  import type { FuseResult } from 'fuse.js'
5
4
  import type { AppConfig } from '@nuxt/schema'
@@ -8,6 +7,7 @@ import _appConfig from '#build/app.config'
8
7
  import theme from '#build/ui/command-palette'
9
8
  import type { UseComponentIconsProps } from '../composables/useComponentIcons'
10
9
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
10
+ import { tv } from '../utils/tv'
11
11
  import type { AvatarProps, ButtonProps, ChipProps, KbdProps, InputProps } from '../types'
12
12
  import type { DynamicSlots, PartialString } from '../types/utils'
13
13
 
@@ -68,9 +68,15 @@ export interface CommandPaletteProps<G, T> extends Pick<ListboxRootProps, 'multi
68
68
  * @defaultValue 'Type a command or search...'
69
69
  */
70
70
  placeholder?: InputProps['placeholder']
71
+ /**
72
+ * Automatically focus the input when component is mounted.
73
+ * @defaultValue true
74
+ */
75
+ autofocus?: boolean
71
76
  /**
72
77
  * Display a close button in the input (useful when inside a Modal for example).
73
78
  * `{ size: 'md', color: 'neutral', variant: 'ghost' }`{lang="ts-type"}
79
+ * @emits 'update:open'
74
80
  * @defaultValue false
75
81
  */
76
82
  close?: ButtonProps | boolean
@@ -139,8 +145,8 @@ import UInput from './Input.vue'
139
145
 
140
146
  const props = withDefaults(defineProps<CommandPaletteProps<G, T>>(), {
141
147
  modelValue: '',
142
- placeholder: 'Type a command or search...',
143
- labelKey: 'label'
148
+ labelKey: 'label',
149
+ autofocus: true
144
150
  })
145
151
  const emits = defineEmits<CommandPaletteEmits<T>>()
146
152
  const slots = defineSlots<CommandPaletteSlots<G, T>>()
@@ -151,7 +157,7 @@ const { t } = useLocale()
151
157
  const appConfig = useAppConfig()
152
158
 
153
159
  const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'disabled', 'multiple', 'modelValue', 'defaultValue', 'highlightOnHover'), emits)
154
- const inputProps = useForwardProps(reactivePick(props, 'loading', 'loadingIcon', 'placeholder'))
160
+ const inputProps = useForwardProps(reactivePick(props, 'loading', 'loadingIcon'))
155
161
 
156
162
  // eslint-disable-next-line vue/no-dupe-keys
157
163
  const ui = commandPalette()
@@ -237,8 +243,9 @@ const groups = computed(() => {
237
243
  <ListboxRoot v-bind="rootProps" :class="ui.root({ class: [props.class, props.ui?.root] })">
238
244
  <ListboxFilter v-model="searchTerm" as-child>
239
245
  <UInput
246
+ :placeholder="placeholder || t('commandPalette.placeholder')"
240
247
  variant="none"
241
- autofocus
248
+ :autofocus="autofocus"
242
249
  size="lg"
243
250
  v-bind="inputProps"
244
251
  :icon="icon || appConfig.ui.icons.search"
@@ -1,9 +1,9 @@
1
1
  <script lang="ts">
2
- import { tv } from 'tailwind-variants'
3
2
  import type { AppConfig } from '@nuxt/schema'
4
3
  import _appConfig from '#build/app.config'
5
4
  import theme from '#build/ui/container'
6
5
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
6
+ import { tv } from '../utils/tv'
7
7
 
8
8
  const appConfig = _appConfig as AppConfig & { ui: { container: Partial<typeof theme> } }
9
9
 
@@ -1,10 +1,11 @@
1
1
  <script lang="ts">
2
- import { tv, type VariantProps } from 'tailwind-variants'
2
+ import type { VariantProps } from 'tailwind-variants'
3
3
  import type { ContextMenuRootProps, ContextMenuRootEmits, ContextMenuContentProps } from 'reka-ui'
4
4
  import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/context-menu'
7
7
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
8
+ import { tv } from '../utils/tv'
8
9
  import type { AvatarProps, KbdProps, LinkProps } from '../types'
9
10
  import type { DynamicSlots, PartialString } from '../types/utils'
10
11
 
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
- import { tv } from 'tailwind-variants'
3
2
  import type { ContextMenuContentProps as RekaContextMenuContentProps, ContextMenuContentEmits as RekaContextMenuContentEmits } from 'reka-ui'
4
3
  import theme from '#build/ui/context-menu'
4
+ import { tv } from '../utils/tv'
5
5
  import type { KbdProps, AvatarProps, ContextMenuItem, ContextMenuSlots } from '../types'
6
6
 
7
7
  const _contextMenu = tv(theme)()
@@ -121,11 +121,11 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
121
121
  </ContextMenu.Sub>
122
122
  <ContextMenu.CheckboxItem
123
123
  v-else-if="item.type === 'checkbox'"
124
- :checked="item.checked"
124
+ :model-value="item.checked"
125
125
  :disabled="item.disabled"
126
126
  :text-value="get(item, props.labelKey as string)"
127
127
  :class="ui.item({ class: [uiOverride?.item, item.class], color: item?.color })"
128
- @update:checked="item.onUpdateChecked"
128
+ @update:model-value="item.onUpdateChecked"
129
129
  @select="item.onSelect"
130
130
  >
131
131
  <ReuseItemTemplate :item="item" :index="index" />
@@ -1,17 +1,17 @@
1
1
  <script lang="ts">
2
- import { tv } from 'tailwind-variants'
3
2
  import type { DrawerRootProps, DrawerRootEmits } from 'vaul-vue'
4
3
  import type { DialogContentProps } from 'reka-ui'
5
4
  import type { AppConfig } from '@nuxt/schema'
6
5
  import _appConfig from '#build/app.config'
7
6
  import theme from '#build/ui/drawer'
8
7
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
8
+ import { tv } from '../utils/tv'
9
9
 
10
10
  const appConfig = _appConfig as AppConfig & { ui: { drawer: Partial<typeof theme> } }
11
11
 
12
12
  const drawer = tv({ extend: tv(theme), ...(appConfig.ui?.drawer || {}) })
13
13
 
14
- export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | 'closeThreshold' | 'defaultOpen' | 'direction' | 'dismissible' | 'fadeFromIndex' | 'fixed' | 'modal' | 'nested' | 'direction' | 'open' | 'scrollLockTimeout' | 'shouldScaleBackground' | 'snapPoints'> {
14
+ export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | 'closeThreshold' | 'defaultOpen' | 'direction' | 'fadeFromIndex' | 'fixed' | 'modal' | 'nested' | 'direction' | 'open' | 'scrollLockTimeout' | 'shouldScaleBackground' | 'snapPoints'> {
15
15
  /**
16
16
  * The element or component this component should render as.
17
17
  * @defaultValue 'div'
@@ -36,6 +36,11 @@ export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | '
36
36
  * @defaultValue true
37
37
  */
38
38
  portal?: boolean
39
+ /**
40
+ * When `false`, the drawer will not close when clicking outside or pressing escape.
41
+ * @defaultValue true
42
+ */
43
+ dismissible?: boolean
39
44
  class?: any
40
45
  ui?: Partial<typeof drawer.slots>
41
46
  }
@@ -1,10 +1,11 @@
1
1
  <script lang="ts">
2
- import { tv, type VariantProps } from 'tailwind-variants'
2
+ import type { VariantProps } from 'tailwind-variants'
3
3
  import type { DropdownMenuRootProps, DropdownMenuRootEmits, DropdownMenuContentProps, DropdownMenuArrowProps } from 'reka-ui'
4
4
  import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/dropdown-menu'
7
7
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
8
+ import { tv } from '../utils/tv'
8
9
  import type { AvatarProps, KbdProps, LinkProps } from '../types'
9
10
  import type { DynamicSlots, PartialString } from '../types/utils'
10
11
 
@@ -1,8 +1,8 @@
1
1
  <!-- eslint-disable vue/block-tag-newline -->
2
2
  <script lang="ts">
3
- import { tv } from 'tailwind-variants'
4
3
  import type { DropdownMenuContentProps as RekaDropdownMenuContentProps, DropdownMenuContentEmits as RekaDropdownMenuContentEmits } from 'reka-ui'
5
4
  import theme from '#build/ui/dropdown-menu'
5
+ import { tv } from '../utils/tv'
6
6
  import type { KbdProps, AvatarProps, DropdownMenuItem, DropdownMenuSlots } from '../types'
7
7
 
8
8
  const _dropdownMenu = tv(theme)()
@@ -130,11 +130,11 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
130
130
  </DropdownMenu.Sub>
131
131
  <DropdownMenu.CheckboxItem
132
132
  v-else-if="item.type === 'checkbox'"
133
- :checked="item.checked"
133
+ :model-value="item.checked"
134
134
  :disabled="item.disabled"
135
135
  :text-value="get(item, props.labelKey as string)"
136
136
  :class="ui.item({ class: [uiOverride?.item, item.class], color: item?.color })"
137
- @update:checked="item.onUpdateChecked"
137
+ @update:model-value="item.onUpdateChecked"
138
138
  @select="item.onSelect"
139
139
  >
140
140
  <ReuseItemTemplate :item="item" :index="index" />
@@ -1,9 +1,9 @@
1
1
  <script lang="ts">
2
- import { tv } from 'tailwind-variants'
3
2
  import type { AppConfig } from '@nuxt/schema'
4
3
  import _appConfig from '#build/app.config'
5
4
  import theme from '#build/ui/form'
6
5
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
6
+ import { tv } from '../utils/tv'
7
7
  import type { FormSchema, FormError, FormInputEvents, FormErrorEvent, FormSubmitEvent, FormEvent, Form, FormErrorWithId } from '../types/form'
8
8
 
9
9
  const appConfig = _appConfig as AppConfig & { ui: { form: Partial<typeof theme> } }
@@ -38,7 +38,7 @@ extendDevtoolsMeta({ example: 'FormExample' })
38
38
  import { provide, inject, nextTick, ref, onUnmounted, onMounted, computed, useId, readonly } from 'vue'
39
39
  import { useEventBus } from '@vueuse/core'
40
40
  import { formOptionsInjectionKey, formInputsInjectionKey, formBusInjectionKey, formLoadingInjectionKey } from '../composables/useFormField'
41
- import { parseSchema } from '../utils/form'
41
+ import { validateSchema } from '../utils/form'
42
42
  import { FormValidationException } from '../types/form'
43
43
 
44
44
  const props = withDefaults(defineProps<FormProps<T>>(), {
@@ -104,16 +104,17 @@ function resolveErrorIds(errs: FormError[]): FormErrorWithId[] {
104
104
  }))
105
105
  }
106
106
 
107
- const parsedValue = ref<T | null>(null)
107
+ const transformedState = ref<T | null>(null)
108
+
108
109
  async function getErrors(): Promise<FormErrorWithId[]> {
109
110
  let errs = props.validate ? (await props.validate(props.state)) ?? [] : []
110
111
 
111
112
  if (props.schema) {
112
- const { errors, result } = await parseSchema(props.state, props.schema as FormSchema<typeof props.state>)
113
+ const { errors, result } = await validateSchema(props.state, props.schema as FormSchema<typeof props.state>)
113
114
  if (errors) {
114
115
  errs = errs.concat(errors)
115
116
  } else {
116
- parsedValue.value = result
117
+ transformedState.value = result
117
118
  }
118
119
  }
119
120
 
@@ -125,13 +126,13 @@ async function _validate(opts: { name?: string | string[], silent?: boolean, nes
125
126
 
126
127
  const nestedValidatePromises = !names && opts.nested
127
128
  ? Array.from(nestedForms.value.values()).map(
128
- ({ validate }) => validate().then(() => undefined).catch((error: Error) => {
129
- if (!(error instanceof FormValidationException)) {
130
- throw error
131
- }
132
- return error
133
- })
134
- )
129
+ ({ validate }) => validate().then(() => undefined).catch((error: Error) => {
130
+ if (!(error instanceof FormValidationException)) {
131
+ throw error
132
+ }
133
+ return error
134
+ })
135
+ )
135
136
  : []
136
137
 
137
138
  if (names) {
@@ -170,7 +171,7 @@ async function onSubmitWrapper(payload: Event) {
170
171
 
171
172
  try {
172
173
  await _validate({ nested: true })
173
- event.data = props.schema ? parsedValue.value : props.state
174
+ event.data = props.schema ? transformedState.value : props.state
174
175
  await props.onSubmit?.(event)
175
176
  } catch (error) {
176
177
  if (!(error instanceof FormValidationException)) {
@@ -180,7 +181,7 @@ async function onSubmitWrapper(payload: Event) {
180
181
  const errorEvent: FormErrorEvent = {
181
182
  ...event,
182
183
  errors: error.errors,
183
- childrens: error.childrens
184
+ children: error.children
184
185
  }
185
186
  emits('error', errorEvent)
186
187
  }
@@ -1,8 +1,9 @@
1
1
  <script lang="ts">
2
- import { tv, type VariantProps } from 'tailwind-variants'
2
+ import type { VariantProps } from 'tailwind-variants'
3
3
  import type { AppConfig } from '@nuxt/schema'
4
4
  import _appConfig from '#build/app.config'
5
5
  import theme from '#build/ui/form-field'
6
+ import { tv } from '../utils/tv'
6
7
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
7
8
 
8
9
  const appConfig = _appConfig as AppConfig & { ui: { formField: Partial<typeof theme> } }
@@ -1,10 +1,11 @@
1
1
  <script lang="ts">
2
2
  import type { InputHTMLAttributes } from 'vue'
3
- import { tv, type VariantProps } from 'tailwind-variants'
3
+ import type { VariantProps } from 'tailwind-variants'
4
4
  import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/input'
7
7
  import type { UseComponentIconsProps } from '../composables/useComponentIcons'
8
+ import { tv } from '../utils/tv'
8
9
  import type { AvatarProps } from '../types'
9
10
  import type { PartialString } from '../types/utils'
10
11
 
@@ -74,7 +75,7 @@ const slots = defineSlots<InputSlots>()
74
75
 
75
76
  const [modelValue, modelModifiers] = defineModel<string | number>()
76
77
 
77
- const { emitFormBlur, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled } = useFormField<InputProps>(props)
78
+ const { emitFormBlur, emitFormInput, emitFormChange, size: formGroupSize, color, id, name, highlight, disabled } = useFormField<InputProps>(props, { deferInputValidation: true })
78
79
  const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
79
80
  const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(props)
80
81
 
@@ -1,12 +1,13 @@
1
1
  <script lang="ts">
2
2
  import type { InputHTMLAttributes } from 'vue'
3
- import { tv, type VariantProps } from 'tailwind-variants'
3
+ import type { VariantProps } from 'tailwind-variants'
4
4
  import type { ComboboxRootProps, ComboboxRootEmits, ComboboxContentProps, ComboboxArrowProps, AcceptableValue } from 'reka-ui'
5
5
  import type { AppConfig } from '@nuxt/schema'
6
6
  import _appConfig from '#build/app.config'
7
7
  import theme from '#build/ui/input-menu'
8
8
  import type { UseComponentIconsProps } from '../composables/useComponentIcons'
9
9
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
10
+ import { tv } from '../utils/tv'
10
11
  import type { AvatarProps, ChipProps, InputProps } from '../types'
11
12
  import type { PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey } from '../types/utils'
12
13
 
@@ -144,6 +145,7 @@ extendDevtoolsMeta({ defaultProps: { items: ['Option 1', 'Option 2', 'Option 3']
144
145
  import { computed, ref, toRef, onMounted, toRaw } from 'vue'
145
146
  import { ComboboxRoot, ComboboxArrow, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxPortal, ComboboxContent, ComboboxViewport, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxSeparator, ComboboxItem, ComboboxItemIndicator, TagsInputRoot, TagsInputItem, TagsInputItemText, TagsInputItemDelete, TagsInputInput, useForwardPropsEmits, useFilter } from 'reka-ui'
146
147
  import { defu } from 'defu'
148
+ import { isEqual } from 'ohash'
147
149
  import { reactivePick, createReusableTemplate } from '@vueuse/core'
148
150
  import { useAppConfig } from '#imports'
149
151
  import { useButtonGroup } from '../composables/useButtonGroup'
@@ -201,7 +203,7 @@ function displayValue(value: T): string {
201
203
  return value && (typeof value === 'object' ? get(value, props.labelKey as string) : value)
202
204
  }
203
205
 
204
- const item = items.value.find(item => compare(typeof item === 'object' ? get(item, props.valueKey as string) : item, value))
206
+ const item = items.value.find(item => compare(typeof item === 'object' ? get(item as Record<string, any>, props.valueKey as string) : item, value))
205
207
  return item && (typeof item === 'object' ? get(item, props.labelKey as string) : item)
206
208
  }
207
209
 
@@ -290,6 +292,14 @@ function onUpdateOpen(value: boolean) {
290
292
  }
291
293
  }
292
294
 
295
+ function onRemoveTag(event: any) {
296
+ if (props.multiple) {
297
+ const modelValue = props.modelValue as SelectModelValue<T, V, true>
298
+ const filteredValue = modelValue.filter(value => !isEqual(value, event))
299
+ emits('update:modelValue', filteredValue as SelectModelValue<T, V, M>)
300
+ }
301
+ }
302
+
293
303
  defineExpose({
294
304
  inputRef
295
305
  })
@@ -336,6 +346,7 @@ defineExpose({
336
346
  as-child
337
347
  @blur="onBlur"
338
348
  @focus="onFocus"
349
+ @remove-tag="onRemoveTag"
339
350
  >
340
351
  <TagsInputItem v-for="(item, index) in tags" :key="index" :value="(item as string)" :class="ui.tagsItem({ class: props.ui?.tagsItem })">
341
352
  <TagsInputItemText :class="ui.tagsItemText({ class: props.ui?.tagsItemText })">
@@ -1,9 +1,10 @@
1
1
  <script lang="ts">
2
- import { tv, type VariantProps } from 'tailwind-variants'
2
+ import type { VariantProps } from 'tailwind-variants'
3
3
  import type { NumberFieldRootProps } from 'reka-ui'
4
4
  import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/input-number'
7
+ import { tv } from '../utils/tv'
7
8
  import type { ButtonProps } from '../types'
8
9
 
9
10
  const appConfig = _appConfig as AppConfig & { ui: { inputNumber: Partial<typeof theme> } }
@@ -1,10 +1,11 @@
1
1
  <script lang="ts">
2
- import { tv, type VariantProps } from 'tailwind-variants'
2
+ import type { VariantProps } from 'tailwind-variants'
3
3
  import type { AppConfig } from '@nuxt/schema'
4
4
  import _appConfig from '#build/app.config'
5
5
  import theme from '#build/ui/kbd'
6
6
  import type { KbdKey } from '../composables/useKbd'
7
7
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
8
+ import { tv } from '../utils/tv'
8
9
 
9
10
  const appConfig = _appConfig as AppConfig & { ui: { kbd: Partial<typeof theme> } }
10
11
 
@@ -1,10 +1,10 @@
1
1
  <script lang="ts">
2
2
  import type { ButtonHTMLAttributes } from 'vue'
3
- import { tv } from 'tailwind-variants'
4
3
  import type { AppConfig } from '@nuxt/schema'
5
4
  import _appConfig from '#build/app.config'
6
5
  import type { RouterLinkProps, RouteLocationRaw } from 'vue-router'
7
6
  import theme from '#build/ui/link'
7
+ import { tv } from '../utils/tv'
8
8
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
9
9
 
10
10
  interface NuxtLinkProps extends Omit<RouterLinkProps, 'to'> {
@@ -1,10 +1,10 @@
1
1
  <script lang="ts">
2
- import { tv } from 'tailwind-variants'
3
2
  import type { DialogRootProps, DialogRootEmits, DialogContentProps } from 'reka-ui'
4
3
  import type { AppConfig } from '@nuxt/schema'
5
4
  import _appConfig from '#build/app.config'
6
5
  import theme from '#build/ui/modal'
7
6
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
7
+ import { tv } from '../utils/tv'
8
8
  import type { ButtonProps } from '../types'
9
9
 
10
10
  const appConfig = _appConfig as AppConfig & { ui: { modal: Partial<typeof theme> } }
@@ -48,10 +48,10 @@ export interface ModalProps extends DialogRootProps {
48
48
  */
49
49
  closeIcon?: string
50
50
  /**
51
- * When `true`, the modal will not close when clicking outside.
52
- * @defaultValue false
51
+ * When `false`, the modal will not close when clicking outside or pressing escape.
52
+ * @defaultValue true
53
53
  */
54
- preventClose?: boolean
54
+ dismissible?: boolean
55
55
  class?: any
56
56
  ui?: Partial<typeof modal.slots>
57
57
  }
@@ -85,7 +85,8 @@ const props = withDefaults(defineProps<ModalProps>(), {
85
85
  portal: true,
86
86
  overlay: true,
87
87
  transition: true,
88
- modal: true
88
+ modal: true,
89
+ dismissible: true
89
90
  })
90
91
  const emits = defineEmits<ModalEmits>()
91
92
  const slots = defineSlots<ModalSlots>()
@@ -96,7 +97,7 @@ const appConfig = useAppConfig()
96
97
  const rootProps = useForwardPropsEmits(reactivePick(props, 'open', 'defaultOpen', 'modal'), emits)
97
98
  const contentProps = toRef(() => props.content)
98
99
  const contentEvents = computed(() => {
99
- if (props.preventClose) {
100
+ if (!props.dismissible) {
100
101
  return {
101
102
  pointerDownOutside: (e: Event) => e.preventDefault(),
102
103
  interactOutside: (e: Event) => e.preventDefault(),
@@ -104,13 +105,7 @@ const contentEvents = computed(() => {
104
105
  }
105
106
  }
106
107
 
107
- return {
108
- interactOutside: (e: Event) => {
109
- if (e.target instanceof Element && e.target.closest('[data-sonner-toaster]')) {
110
- return e.preventDefault()
111
- }
112
- }
113
- }
108
+ return {}
114
109
  })
115
110
 
116
111
  const ui = computed(() => modal({
@@ -1,10 +1,11 @@
1
1
  <script lang="ts">
2
- import { tv, type VariantProps } from 'tailwind-variants'
2
+ import type { VariantProps } from 'tailwind-variants'
3
3
  import type { NavigationMenuRootProps, NavigationMenuRootEmits, NavigationMenuContentProps, CollapsibleRootProps } from 'reka-ui'
4
4
  import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/navigation-menu'
7
7
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
8
+ import { tv } from '../utils/tv'
8
9
  import type { AvatarProps, BadgeProps, LinkProps } from '../types'
9
10
  import type { DynamicSlots, MaybeArrayOfArray, MaybeArrayOfArrayItem, PartialString } from '../types/utils'
10
11
 
@@ -21,6 +22,10 @@ export interface NavigationMenuItem extends Omit<LinkProps, 'raw' | 'custom'>, P
21
22
  label?: string
22
23
  icon?: string
23
24
  avatar?: AvatarProps
25
+ /**
26
+ * Display a badge on the item.
27
+ * `{ size: 'sm', color: 'neutral', variant: 'outline' }`{lang="ts-type"}
28
+ */
24
29
  badge?: string | number | BadgeProps
25
30
  trailingIcon?: string
26
31
  slot?: string
@@ -137,8 +142,8 @@ import UCollapsible from './Collapsible.vue'
137
142
  const props = withDefaults(defineProps<NavigationMenuProps<I>>(), {
138
143
  orientation: 'horizontal',
139
144
  delayDuration: 0,
140
- labelKey: 'label',
141
- unmountOnHide: true
145
+ unmountOnHide: true,
146
+ labelKey: 'label'
142
147
  })
143
148
  const emits = defineEmits<NavigationMenuEmits>()
144
149
  const slots = defineSlots<NavigationMenuSlots<T>>()
@@ -209,17 +214,17 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
209
214
  <template v-for="(list, listIndex) in lists" :key="`list-${listIndex}`">
210
215
  <NavigationMenuList :class="ui.list({ class: props.ui?.list })">
211
216
  <component
212
- :is="(item.children?.length && orientation === 'vertical') ? UCollapsible : NavigationMenuItem"
217
+ :is="(orientation === 'vertical' && item.children?.length) ? UCollapsible : NavigationMenuItem"
213
218
  v-for="(item, index) in list"
214
219
  :key="`list-${listIndex}-${index}`"
215
220
  as="li"
216
221
  :value="item.value || String(index)"
217
222
  :default-open="item.defaultOpen"
218
- :unmount-on-hide="(item.children?.length && orientation === 'vertical') ? unmountOnHide : undefined"
223
+ :unmount-on-hide="(orientation === 'vertical' && item.children?.length) ? unmountOnHide : undefined"
219
224
  :open="item.open"
220
225
  :class="ui.item({ class: props.ui?.item })"
221
226
  >
222
- <ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
227
+ <ULink v-slot="{ active, ...slotProps }" v-bind="(orientation === 'vertical' && item.children?.length) ? {} : pickLinkProps(item)" custom>
223
228
  <component
224
229
  :is="(orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) ? NavigationMenuTrigger : NavigationMenuLink"
225
230
  as-child
@@ -227,8 +232,8 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
227
232
  :disabled="item.disabled"
228
233
  @select="item.onSelect"
229
234
  >
230
- <ULinkBase v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.class], active, disabled: !!item.disabled })">
231
- <ReuseItemTemplate :item="(item as T)" :active="active" :index="index" />
235
+ <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) })">
236
+ <ReuseItemTemplate :item="(item as T)" :active="active || item.active" :index="index" />
232
237
  </ULinkBase>
233
238
  </component>
234
239
 
@@ -265,7 +270,7 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
265
270
  <li v-for="(childItem, childIndex) in item.children" :key="childIndex" :class="ui.childItem({ class: props.ui?.childItem })">
266
271
  <ULink v-slot="{ active: childActive, ...childSlotProps }" v-bind="pickLinkProps(childItem)" custom>
267
272
  <NavigationMenuLink as-child :active="childActive" @select="childItem.onSelect">
268
- <ULinkBase v-bind="childSlotProps" :class="ui.link({ class: [props.ui?.link, childItem.class], active: childActive, disabled: !!childItem.disabled })">
273
+ <ULinkBase v-bind="childSlotProps" :class="ui.link({ class: [props.ui?.link, childItem.class], active: childActive, disabled: !!childItem.disabled, level: true })">
269
274
  <ReuseItemTemplate :item="(childItem as T)" :active="childActive" :index="childIndex" />
270
275
  </ULinkBase>
271
276
  </NavigationMenuLink>
@@ -1,11 +1,11 @@
1
1
  <script lang="ts">
2
- import { tv } from 'tailwind-variants'
3
2
  import type { PaginationRootProps, PaginationRootEmits } from 'reka-ui'
4
3
  import type { AppConfig } from '@nuxt/schema'
5
4
  import type { RouteLocationRaw } from '#vue-router'
6
5
  import _appConfig from '#build/app.config'
7
6
  import theme from '#build/ui/pagination'
8
7
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
8
+ import { tv } from '../utils/tv'
9
9
  import type { ButtonProps } from '../types'
10
10
 
11
11
  const appConfig = _appConfig as AppConfig & { ui: { pagination: Partial<typeof theme> } }
@@ -1,9 +1,10 @@
1
1
  <script lang="ts">
2
+ import type { VariantProps } from 'tailwind-variants'
3
+ import type { PinInputRootEmits, PinInputRootProps } from 'reka-ui'
4
+ import type { AppConfig } from '@nuxt/schema'
2
5
  import _appConfig from '#build/app.config'
3
6
  import theme from '#build/ui/pin-input'
4
- import type { AppConfig } from '@nuxt/schema'
5
- import type { PinInputRootEmits, PinInputRootProps } from 'reka-ui'
6
- import { tv, type VariantProps } from 'tailwind-variants'
7
+ import { tv } from '../utils/tv'
7
8
  import type { PartialString } from '../types/utils'
8
9
 
9
10
  const appConfig = _appConfig as AppConfig & { ui: { pinInput: Partial<typeof theme> } }
@@ -1,9 +1,9 @@
1
1
  <script lang="ts">
2
- import { tv } from 'tailwind-variants'
3
2
  import type { PopoverRootProps, HoverCardRootProps, PopoverRootEmits, PopoverContentProps, PopoverArrowProps } from 'reka-ui'
4
3
  import type { AppConfig } from '@nuxt/schema'
5
4
  import _appConfig from '#build/app.config'
6
5
  import theme from '#build/ui/popover'
6
+ import { tv } from '../utils/tv'
7
7
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
8
8
 
9
9
  const appConfig = _appConfig as AppConfig & { ui: { popover: Partial<typeof theme> } }
@@ -32,10 +32,10 @@ export interface PopoverProps extends PopoverRootProps, Pick<HoverCardRootProps,
32
32
  */
33
33
  portal?: boolean
34
34
  /**
35
- * When `true`, the popover will not close when clicking outside.
36
- * @defaultValue false
35
+ * When `false`, the popover will not close when clicking outside or pressing escape.
36
+ * @defaultValue true
37
37
  */
38
- preventClose?: boolean
38
+ dismissible?: boolean
39
39
  class?: any
40
40
  ui?: Partial<typeof popover.slots>
41
41
  }
@@ -61,7 +61,8 @@ const props = withDefaults(defineProps<PopoverProps>(), {
61
61
  portal: true,
62
62
  mode: 'click',
63
63
  openDelay: 0,
64
- closeDelay: 0
64
+ closeDelay: 0,
65
+ dismissible: true
65
66
  })
66
67
  const emits = defineEmits<PopoverEmits>()
67
68
  const slots = defineSlots<PopoverSlots>()
@@ -70,7 +71,7 @@ const pick = props.mode === 'hover' ? reactivePick(props, 'defaultOpen', 'open',
70
71
  const rootProps = useForwardPropsEmits(pick, emits)
71
72
  const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, collisionPadding: 8 }) as PopoverContentProps)
72
73
  const contentEvents = computed(() => {
73
- if (props.preventClose) {
74
+ if (!props.dismissible) {
74
75
  return {
75
76
  pointerDownOutside: (e: Event) => e.preventDefault(),
76
77
  interactOutside: (e: Event) => e.preventDefault(),
@@ -1,10 +1,11 @@
1
1
  <!-- eslint-disable vue/block-tag-newline -->
2
2
  <script lang="ts">
3
- import { tv, type VariantProps } from 'tailwind-variants'
3
+ import type { VariantProps } from 'tailwind-variants'
4
4
  import type { ProgressRootProps, ProgressRootEmits } from 'reka-ui'
5
5
  import type { AppConfig } from '@nuxt/schema'
6
6
  import _appConfig from '#build/app.config'
7
7
  import theme from '#build/ui/progress'
8
+ import { tv } from '../utils/tv'
8
9
 
9
10
  const appConfig = _appConfig as AppConfig & { ui: { progress: Partial<typeof theme> } }
10
11
 
@@ -58,7 +59,7 @@ const props = withDefaults(defineProps<ProgressProps>(), {
58
59
  orientation: 'horizontal'
59
60
  })
60
61
  const emits = defineEmits<ProgressEmits>()
61
- defineSlots<ProgressSlots>()
62
+ const slots = defineSlots<ProgressSlots>()
62
63
 
63
64
  const { dir } = useLocale()
64
65
 
@@ -160,7 +161,7 @@ const ui = computed(() => progress({
160
161
 
161
162
  <template>
162
163
  <Primitive :as="as" :class="ui.root({ class: [props.class, props.ui?.root] })">
163
- <div v-if="!isIndeterminate && (status || $slots.status)" :class="ui.status({ class: props.ui?.status })" :style="statusStyle">
164
+ <div v-if="!isIndeterminate && (status || !!slots.status)" :class="ui.status({ class: props.ui?.status })" :style="statusStyle">
164
165
  <slot name="status" :percent="percent">
165
166
  {{ percent }}%
166
167
  </slot>
@@ -1,10 +1,11 @@
1
1
  <script lang="ts">
2
- import { tv, type VariantProps } from 'tailwind-variants'
2
+ import type { VariantProps } from 'tailwind-variants'
3
3
  import type { RadioGroupRootProps, RadioGroupRootEmits, AcceptableValue } from 'reka-ui'
4
4
  import type { AppConfig } from '@nuxt/schema'
5
5
  import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/radio-group'
7
7
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
8
+ import { tv } from '../utils/tv'
8
9
 
9
10
  const appConfig = _appConfig as AppConfig & { ui: { radioGroup: Partial<typeof theme> } }
10
11