@nuxt/ui 3.0.0-alpha.7 → 3.0.0-alpha.9
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.
- package/.nuxt/ui/accordion.ts +20 -0
- package/.nuxt/ui/alert.ts +242 -0
- package/.nuxt/ui/avatar-group.ts +40 -0
- package/.nuxt/ui/avatar.ts +42 -0
- package/.nuxt/ui/badge.ts +194 -0
- package/.nuxt/ui/breadcrumb.ts +45 -0
- package/.nuxt/ui/button-group.ts +16 -0
- package/.nuxt/ui/button.ts +344 -0
- package/.nuxt/ui/card.ts +8 -0
- package/.nuxt/ui/carousel.ts +41 -0
- package/.nuxt/ui/checkbox.ts +105 -0
- package/.nuxt/ui/chip.ts +67 -0
- package/.nuxt/ui/collapsible.ts +6 -0
- package/.nuxt/ui/command-palette.ts +40 -0
- package/.nuxt/ui/container.ts +3 -0
- package/.nuxt/ui/context-menu.ts +198 -0
- package/.nuxt/ui/drawer.ts +55 -0
- package/.nuxt/ui/dropdown-menu.ts +199 -0
- package/.nuxt/ui/form-field.ts +40 -0
- package/.nuxt/ui/form.ts +3 -0
- package/.nuxt/ui/index.ts +45 -0
- package/.nuxt/ui/input-menu.ts +411 -0
- package/.nuxt/ui/input-number.ts +204 -0
- package/.nuxt/ui/input.ts +263 -0
- package/.nuxt/ui/kbd.ts +19 -0
- package/.nuxt/ui/link.ts +15 -0
- package/.nuxt/ui/modal.ts +28 -0
- package/.nuxt/ui/navigation-menu.ts +390 -0
- package/.nuxt/ui/pagination.ts +8 -0
- package/.nuxt/ui/pin-input.ts +145 -0
- package/.nuxt/ui/popover.ts +6 -0
- package/.nuxt/ui/progress.ts +258 -0
- package/.nuxt/ui/radio-group.ts +112 -0
- package/.nuxt/ui/select-menu.ts +316 -0
- package/.nuxt/ui/select.ts +314 -0
- package/.nuxt/ui/separator.ts +143 -0
- package/.nuxt/ui/skeleton.ts +3 -0
- package/.nuxt/ui/slideover.ts +63 -0
- package/.nuxt/ui/slider.ts +148 -0
- package/.nuxt/ui/switch.ts +113 -0
- package/.nuxt/ui/table.ts +129 -0
- package/.nuxt/ui/tabs.ts +227 -0
- package/.nuxt/ui/textarea.ts +263 -0
- package/.nuxt/ui/toast.ts +66 -0
- package/.nuxt/ui/toaster.ts +75 -0
- package/.nuxt/ui/tooltip.ts +9 -0
- package/README.md +52 -12
- package/cli/commands/{init.mjs → make/component.mjs} +4 -4
- package/cli/commands/make/index.mjs +14 -0
- package/cli/commands/make/locale.mjs +64 -0
- package/cli/index.mjs +2 -2
- package/cli/templates.mjs +47 -2
- package/cli/utils.mjs +14 -0
- package/dist/chunks/component-meta.cjs +77249 -0
- package/dist/chunks/component-meta.mjs +77247 -0
- package/dist/client/devtools/200.html +1 -0
- package/dist/client/devtools/404.html +1 -0
- package/dist/client/devtools/_fonts/rP2Wp2ywxg089UriCZaSExd86J3t9jz86MvyyKK58UfivUw4aw-SK92LTmKP0.woff2 +0 -0
- package/dist/client/devtools/_fonts/rP2Wp2ywxg089UriCZaSExd86J3t9jz86MvyyKy58UfivUw-9uYm8d48E4.woff2 +0 -0
- package/dist/client/devtools/_fonts/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu0-K6z9mXg-VNw7NHvqnp.woff2 +0 -0
- package/dist/client/devtools/_fonts/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu6-K6z9mXgjU0-EkYdMs3MAX.woff2 +0 -0
- package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat-7DW3w-R7n06NbhGy.woff +0 -0
- package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat-JDG3w-leGNfkTmsj.woff +0 -0
- package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat-JDW3w-ciElMF03ku.woff +0 -0
- package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat8JCm3w-sB722Uoa0f.woff +0 -0
- package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat8JDW3w-PBDI1JDjwV.woff +0 -0
- package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat8gCm3w-0q1hqVn09O.woff +0 -0
- package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat9XCm3w-ByvzuLy2fa.woff +0 -0
- package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat9uCm3w-5TKCIs6EEw.woff +0 -0
- package/dist/client/devtools/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat_XDW3w-r2swRDGfn2.woff +0 -0
- package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAC5thTQ-ldB60l5U8r.woff +0 -0
- package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAIpthTQ-wbFKGFDrgo.woff +0 -0
- package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAIpxhTQ-LLUBv5jskj.woff +0 -0
- package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwARZthTQ-F71RdTRbNg.woff +0 -0
- package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwA_JxhTQ-6nh65gZkc0.woff +0 -0
- package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAfJthTQ-aMoWEJLmTt.woff +0 -0
- package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAkJxhTQ-WMBvmLOgKm.woff +0 -0
- package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAop1hTQ-utGC2hnWq2.woff +0 -0
- package/dist/client/devtools/_fonts/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAopxhTQ-YpyTieVa5B.woff +0 -0
- package/dist/client/devtools/_nuxt/BDC8ywlR.js +1 -0
- package/dist/client/devtools/_nuxt/BT004Uxp.js +53 -0
- package/dist/client/devtools/_nuxt/C1H2Soz3.js +1 -0
- package/dist/client/devtools/_nuxt/builds/latest.json +1 -0
- package/dist/client/devtools/_nuxt/builds/meta/f98c13ea-d751-4b37-8ce3-94e99708745f.json +1 -0
- package/dist/client/devtools/_nuxt/entry.Bx6WJjrx.css +1 -0
- package/dist/client/devtools/_nuxt/error-404.Cq4qshcf.css +1 -0
- package/dist/client/devtools/_nuxt/error-500.ax1aM34m.css +1 -0
- package/dist/client/devtools/favicon.svg +1 -0
- package/dist/client/devtools/index.html +1 -0
- package/dist/devtools/runtime/DevtoolsRenderer.vue +53 -0
- package/dist/devtools/runtime/examples/AvatarGroupExample.vue +7 -0
- package/dist/devtools/runtime/examples/ButtonGroupExample.vue +8 -0
- package/dist/devtools/runtime/examples/CardExample.vue +13 -0
- package/dist/devtools/runtime/examples/CarouselExample.vue +13 -0
- package/dist/devtools/runtime/examples/ChipExample.vue +5 -0
- package/dist/devtools/runtime/examples/CollapsibleExample.vue +8 -0
- package/dist/devtools/runtime/examples/CommandPaletteExample.vue +29 -0
- package/dist/devtools/runtime/examples/ContainerExample.vue +5 -0
- package/dist/devtools/runtime/examples/ContextMenuExample.vue +5 -0
- package/dist/devtools/runtime/examples/DrawerExample.vue +8 -0
- package/dist/devtools/runtime/examples/DropdownMenuExample.vue +5 -0
- package/dist/devtools/runtime/examples/FormExample.vue +30 -0
- package/dist/devtools/runtime/examples/FormFieldExample.vue +5 -0
- package/dist/devtools/runtime/examples/LinkExample.vue +5 -0
- package/dist/devtools/runtime/examples/ModalExample.vue +8 -0
- package/dist/devtools/runtime/examples/PopoverExample.vue +8 -0
- package/dist/devtools/runtime/examples/SkeletonExample.vue +3 -0
- package/dist/devtools/runtime/examples/SlideoverExample.vue +8 -0
- package/dist/devtools/runtime/examples/ToasterExample.vue +11 -0
- package/dist/devtools/runtime/examples/TooltipExample.vue +5 -0
- package/dist/module.cjs +223 -4
- package/dist/module.d.cts +54 -0
- package/dist/module.d.mts +10 -0
- package/dist/module.d.ts +10 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +158 -2763
- package/dist/runtime/components/Accordion.vue +32 -1
- package/dist/runtime/components/Alert.vue +8 -1
- package/dist/runtime/components/App.vue +19 -5
- package/dist/runtime/components/Avatar.vue +23 -5
- package/dist/runtime/components/AvatarGroup.vue +3 -0
- package/dist/runtime/components/Badge.vue +33 -3
- package/dist/runtime/components/Breadcrumb.vue +33 -4
- package/dist/runtime/components/Button.vue +6 -1
- package/dist/runtime/components/ButtonGroup.vue +4 -1
- package/dist/runtime/components/Card.vue +3 -0
- package/dist/runtime/components/Carousel.vue +17 -8
- package/dist/runtime/components/Checkbox.vue +4 -0
- package/dist/runtime/components/Chip.vue +9 -2
- package/dist/runtime/components/Collapsible.vue +3 -0
- package/dist/runtime/components/CommandPalette.vue +8 -4
- package/dist/runtime/components/Container.vue +3 -0
- package/dist/runtime/components/ContextMenu.vue +64 -3
- package/dist/runtime/components/ContextMenuContent.vue +10 -8
- package/dist/runtime/components/Drawer.vue +3 -0
- package/dist/runtime/components/DropdownMenu.vue +52 -3
- package/dist/runtime/components/DropdownMenuContent.vue +10 -8
- package/dist/runtime/components/Form.vue +21 -20
- package/dist/runtime/components/FormField.vue +10 -3
- package/dist/runtime/components/Input.vue +1 -0
- package/dist/runtime/components/InputMenu.vue +118 -31
- package/dist/runtime/components/InputNumber.vue +192 -0
- package/dist/runtime/components/Kbd.vue +2 -0
- package/dist/runtime/components/Link.vue +69 -6
- package/dist/runtime/components/Modal.vue +15 -3
- package/dist/runtime/components/NavigationMenu.vue +95 -46
- package/dist/runtime/components/Pagination.vue +17 -6
- package/dist/runtime/components/PinInput.vue +96 -0
- package/dist/runtime/components/Popover.vue +20 -1
- package/dist/runtime/components/Progress.vue +1 -1
- package/dist/runtime/components/RadioGroup.vue +4 -1
- package/dist/runtime/components/Select.vue +24 -13
- package/dist/runtime/components/SelectMenu.vue +130 -42
- package/dist/runtime/components/Separator.vue +1 -1
- package/dist/runtime/components/Skeleton.vue +3 -0
- package/dist/runtime/components/Slideover.vue +15 -3
- package/dist/runtime/components/Slider.vue +1 -1
- package/dist/runtime/components/Switch.vue +5 -1
- package/dist/runtime/components/Table.vue +27 -8
- package/dist/runtime/components/Tabs.vue +20 -1
- package/dist/runtime/components/Textarea.vue +1 -1
- package/dist/runtime/components/Toast.vue +8 -1
- package/dist/runtime/components/Toaster.vue +29 -14
- package/dist/runtime/components/Tooltip.vue +3 -0
- package/dist/runtime/composables/defineLocale.d.ts +9 -0
- package/dist/runtime/composables/defineLocale.js +4 -0
- package/dist/runtime/composables/defineShortcuts.js +0 -6
- package/dist/runtime/composables/extendDevtoolsMeta.d.ts +7 -0
- package/dist/runtime/composables/extendDevtoolsMeta.js +2 -0
- package/dist/runtime/composables/useFormField.d.ts +4 -1
- package/dist/runtime/composables/useFormField.js +1 -1
- package/dist/runtime/composables/useKbd.d.ts +10 -3
- package/dist/runtime/composables/useKbd.js +14 -8
- package/dist/runtime/composables/useLocale.d.ts +4 -0
- package/dist/runtime/composables/useLocale.js +10 -0
- package/dist/runtime/index.css +1 -1
- package/dist/runtime/locale/ar.d.ts +2 -0
- package/dist/runtime/locale/ar.js +47 -0
- package/dist/runtime/locale/cs.d.ts +2 -0
- package/dist/runtime/locale/cs.js +46 -0
- package/dist/runtime/locale/de.d.ts +2 -0
- package/dist/runtime/locale/de.js +46 -0
- package/dist/runtime/locale/en.d.ts +2 -0
- package/dist/runtime/locale/en.js +46 -0
- package/dist/runtime/locale/es.d.ts +2 -0
- package/dist/runtime/locale/es.js +46 -0
- package/dist/runtime/locale/fa_ir.d.ts +2 -0
- package/dist/runtime/locale/fa_ir.js +47 -0
- package/dist/runtime/locale/fr.d.ts +2 -0
- package/dist/runtime/locale/fr.js +46 -0
- package/dist/runtime/locale/index.d.ts +12 -0
- package/dist/runtime/locale/index.js +12 -0
- package/dist/runtime/locale/it.d.ts +2 -0
- package/dist/runtime/locale/it.js +46 -0
- package/dist/runtime/locale/pl.d.ts +2 -0
- package/dist/runtime/locale/pl.js +46 -0
- package/dist/runtime/locale/ru.d.ts +2 -0
- package/dist/runtime/locale/ru.js +46 -0
- package/dist/runtime/locale/zh_hans.d.ts +2 -0
- package/dist/runtime/locale/zh_hans.js +46 -0
- package/dist/runtime/locale/zh_hant.d.ts +2 -0
- package/dist/runtime/locale/zh_hant.js +46 -0
- package/dist/runtime/types/form.d.ts +7 -2
- package/dist/runtime/types/index.d.ts +3 -0
- package/dist/runtime/types/index.js +3 -0
- package/dist/runtime/types/locale.d.ts +48 -0
- package/dist/runtime/types/locale.js +0 -0
- package/dist/runtime/types/utils.d.ts +7 -0
- package/dist/runtime/utils/form.d.ts +5 -9
- package/dist/runtime/utils/form.js +115 -50
- package/dist/runtime/utils/index.js +1 -1
- package/dist/runtime/utils/link.d.ts +2 -2
- package/dist/runtime/utils/locale.d.ts +15 -0
- package/dist/runtime/utils/locale.js +25 -0
- package/dist/runtime/vue/components/Icon.vue +15 -0
- package/dist/runtime/vue/components/Link.vue +195 -0
- package/dist/runtime/vue/plugins/color-mode.d.ts +4 -0
- package/dist/runtime/vue/plugins/color-mode.js +6 -0
- package/dist/runtime/vue/plugins/head.d.ts +4 -0
- package/dist/runtime/vue/plugins/head.js +6 -0
- package/dist/runtime/vue/stubs.d.ts +15 -0
- package/dist/runtime/vue/stubs.js +27 -0
- package/dist/shared/ui.BPnAe4QS.cjs +3030 -0
- package/dist/shared/ui.d52SSCwA.mjs +3023 -0
- package/dist/unplugin.cjs +192 -0
- package/dist/unplugin.d.cts +49 -0
- package/dist/unplugin.d.mts +49 -0
- package/dist/unplugin.d.ts +49 -0
- package/dist/unplugin.mjs +181 -0
- package/dist/vite.cjs +22 -0
- package/dist/vite.d.cts +13 -0
- package/dist/vite.d.mts +13 -0
- package/dist/vite.d.ts +13 -0
- package/dist/vite.mjs +20 -0
- package/package.json +78 -33
- package/vue-plugin.d.ts +5 -0
- package/cli/node_modules/.ignored/citty/LICENSE +0 -36
- package/cli/node_modules/.ignored/citty/README.md +0 -134
- package/cli/node_modules/.ignored/citty/dist/index.cjs +0 -475
- package/cli/node_modules/.ignored/citty/dist/index.d.cts +0 -80
- package/cli/node_modules/.ignored/citty/dist/index.d.mts +0 -80
- package/cli/node_modules/.ignored/citty/dist/index.d.ts +0 -80
- package/cli/node_modules/.ignored/citty/dist/index.mjs +0 -463
- package/cli/node_modules/.ignored/citty/package.json +0 -49
- package/cli/node_modules/.ignored/consola/LICENSE +0 -47
- package/cli/node_modules/.ignored/consola/README.md +0 -318
- package/cli/node_modules/.ignored/consola/core.d.ts +0 -1
- package/cli/node_modules/.ignored/consola/dist/basic.cjs +0 -32
- package/cli/node_modules/.ignored/consola/dist/basic.d.ts +0 -9
- package/cli/node_modules/.ignored/consola/dist/basic.mjs +0 -24
- package/cli/node_modules/.ignored/consola/dist/browser.cjs +0 -80
- package/cli/node_modules/.ignored/consola/dist/browser.d.ts +0 -7
- package/cli/node_modules/.ignored/consola/dist/browser.mjs +0 -72
- package/cli/node_modules/.ignored/consola/dist/chunks/prompt.cjs +0 -436
- package/cli/node_modules/.ignored/consola/dist/chunks/prompt.mjs +0 -429
- package/cli/node_modules/.ignored/consola/dist/core.cjs +0 -415
- package/cli/node_modules/.ignored/consola/dist/core.d.ts +0 -124
- package/cli/node_modules/.ignored/consola/dist/core.mjs +0 -410
- package/cli/node_modules/.ignored/consola/dist/index.cjs +0 -21
- package/cli/node_modules/.ignored/consola/dist/index.d.ts +0 -9
- package/cli/node_modules/.ignored/consola/dist/index.mjs +0 -8
- package/cli/node_modules/.ignored/consola/dist/shared/consola.06ad8a64.mjs +0 -62
- package/cli/node_modules/.ignored/consola/dist/shared/consola.36c0034f.mjs +0 -636
- package/cli/node_modules/.ignored/consola/dist/shared/consola.4bbae468.cjs +0 -645
- package/cli/node_modules/.ignored/consola/dist/shared/consola.deac7d5a.cjs +0 -65
- package/cli/node_modules/.ignored/consola/dist/utils.cjs +0 -308
- package/cli/node_modules/.ignored/consola/dist/utils.d.ts +0 -169
- package/cli/node_modules/.ignored/consola/dist/utils.mjs +0 -284
- package/cli/node_modules/.ignored/consola/lib/index.cjs +0 -9
- package/cli/node_modules/.ignored/consola/package.json +0 -101
- package/cli/node_modules/.ignored/consola/utils.d.ts +0 -1
- package/cli/node_modules/.ignored/pathe/LICENSE +0 -44
- package/cli/node_modules/.ignored/pathe/README.md +0 -69
- package/cli/node_modules/.ignored/pathe/dist/index.cjs +0 -23
- package/cli/node_modules/.ignored/pathe/dist/index.d.cts +0 -36
- package/cli/node_modules/.ignored/pathe/dist/index.d.mts +0 -36
- package/cli/node_modules/.ignored/pathe/dist/index.d.ts +0 -36
- package/cli/node_modules/.ignored/pathe/dist/index.mjs +0 -1
- package/cli/node_modules/.ignored/pathe/dist/shared/pathe.1f0a373c.cjs +0 -238
- package/cli/node_modules/.ignored/pathe/dist/shared/pathe.ff20891b.mjs +0 -221
- package/cli/node_modules/.ignored/pathe/dist/utils.cjs +0 -58
- package/cli/node_modules/.ignored/pathe/dist/utils.d.cts +0 -5
- package/cli/node_modules/.ignored/pathe/dist/utils.d.mts +0 -5
- package/cli/node_modules/.ignored/pathe/dist/utils.d.ts +0 -5
- package/cli/node_modules/.ignored/pathe/dist/utils.mjs +0 -54
- package/cli/node_modules/.ignored/pathe/package.json +0 -48
- package/cli/node_modules/.ignored/pathe/utils.d.ts +0 -1
- package/cli/node_modules/.ignored/scule/LICENSE +0 -21
- package/cli/node_modules/.ignored/scule/README.md +0 -149
- package/cli/node_modules/.ignored/scule/dist/index.cjs +0 -92
- package/cli/node_modules/.ignored/scule/dist/index.d.cts +0 -57
- package/cli/node_modules/.ignored/scule/dist/index.d.mts +0 -57
- package/cli/node_modules/.ignored/scule/dist/index.d.ts +0 -57
- package/cli/node_modules/.ignored/scule/dist/index.mjs +0 -80
- package/cli/node_modules/.ignored/scule/package.json +0 -43
- package/cli/node_modules/.package-lock.json +0 -33
|
@@ -6,8 +6,9 @@ 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
|
+
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
|
9
10
|
import type { AvatarProps, ChipProps, InputProps } from '../types'
|
|
10
|
-
import type { AcceptableValue, ArrayOrWrapped, PartialString } from '../types/utils'
|
|
11
|
+
import type { AcceptableValue, ArrayOrWrapped, PartialString, MaybeArrayOfArray, MaybeArrayOfArrayItem, SelectModelValue, SelectModelValueEmits, SelectItemKey } from '../types/utils'
|
|
11
12
|
|
|
12
13
|
const appConfig = _appConfig as AppConfig & { ui: { inputMenu: Partial<typeof theme> } }
|
|
13
14
|
|
|
@@ -29,7 +30,7 @@ export interface InputMenuItem {
|
|
|
29
30
|
|
|
30
31
|
type InputMenuVariants = VariantProps<typeof inputMenu>
|
|
31
32
|
|
|
32
|
-
export interface InputMenuProps<T> extends Pick<ComboboxRootProps<T>, '
|
|
33
|
+
export interface InputMenuProps<T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<InputMenuItem | AcceptableValue> = MaybeArrayOfArray<InputMenuItem | AcceptableValue>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false> extends Pick<ComboboxRootProps<T>, 'defaultValue' | 'selectedValue' | 'open' | 'defaultOpen' | 'searchTerm' | 'disabled' | 'name' | 'resetSearchTermOnBlur'>, UseComponentIconsProps {
|
|
33
34
|
/**
|
|
34
35
|
* The element or component this component should render as.
|
|
35
36
|
* @defaultValue 'div'
|
|
@@ -77,33 +78,44 @@ export interface InputMenuProps<T> extends Pick<ComboboxRootProps<T>, 'modelValu
|
|
|
77
78
|
*/
|
|
78
79
|
portal?: boolean
|
|
79
80
|
/**
|
|
80
|
-
* Whether to filter items or not, can be an array of fields to filter.
|
|
81
|
-
* When `false`, items will not be filtered which is useful for custom filtering.
|
|
82
|
-
*
|
|
81
|
+
* Whether to filter items or not, can be an array of fields to filter. Defaults to `[labelKey]`.
|
|
82
|
+
* When `false`, items will not be filtered which is useful for custom filtering (useAsyncData, useFetch, etc.).
|
|
83
|
+
* `['label']`{lang="ts-type"}
|
|
84
|
+
* @defaultValue true
|
|
83
85
|
*/
|
|
84
86
|
filter?: boolean | string[]
|
|
85
87
|
/**
|
|
86
88
|
* When `items` is an array of objects, select the field to use as the value instead of the object itself.
|
|
87
89
|
* @defaultValue undefined
|
|
88
90
|
*/
|
|
89
|
-
valueKey?:
|
|
91
|
+
valueKey?: V
|
|
90
92
|
/**
|
|
91
93
|
* When `items` is an array of objects, select the field to use as the label.
|
|
92
94
|
* @defaultValue 'label'
|
|
93
95
|
*/
|
|
94
|
-
labelKey?:
|
|
95
|
-
items?:
|
|
96
|
+
labelKey?: V
|
|
97
|
+
items?: I
|
|
96
98
|
/** Highlight the ring color like a focus state. */
|
|
97
99
|
highlight?: boolean
|
|
100
|
+
/**
|
|
101
|
+
* Determines if custom user input that does not exist in options can be added.
|
|
102
|
+
* @defaultValue false
|
|
103
|
+
*/
|
|
104
|
+
createItem?: boolean | 'always' | { placement?: 'top' | 'bottom', when?: 'empty' | 'always' }
|
|
98
105
|
class?: any
|
|
99
106
|
ui?: PartialString<typeof inputMenu.slots>
|
|
107
|
+
/** The controlled value of the Combobox. Can be binded-with with `v-model`. */
|
|
108
|
+
modelValue?: SelectModelValue<T, V, M>
|
|
109
|
+
/** Whether multiple options can be selected or not. */
|
|
110
|
+
multiple?: M
|
|
100
111
|
}
|
|
101
112
|
|
|
102
|
-
export type InputMenuEmits<T> = ComboboxRootEmits<T> & {
|
|
113
|
+
export type InputMenuEmits<T, V, M extends boolean> = Omit<ComboboxRootEmits<T>, 'update:modelValue'> & {
|
|
103
114
|
change: [payload: Event]
|
|
104
115
|
blur: [payload: FocusEvent]
|
|
105
116
|
focus: [payload: FocusEvent]
|
|
106
|
-
|
|
117
|
+
create: [payload: Event, item: T]
|
|
118
|
+
} & SelectModelValueEmits<T, V, M>
|
|
107
119
|
|
|
108
120
|
type SlotProps<T> = (props: { item: T, index: number }) => any
|
|
109
121
|
|
|
@@ -117,19 +129,23 @@ export interface InputMenuSlots<T> {
|
|
|
117
129
|
'item-trailing': SlotProps<T>
|
|
118
130
|
'tags-item-text': SlotProps<T>
|
|
119
131
|
'tags-item-delete': SlotProps<T>
|
|
132
|
+
'create-item-label'(props: { item: T }): any
|
|
120
133
|
}
|
|
134
|
+
|
|
135
|
+
extendDevtoolsMeta({ defaultProps: { items: ['Option 1', 'Option 2', 'Option 3'] } })
|
|
121
136
|
</script>
|
|
122
137
|
|
|
123
|
-
<script setup lang="ts" generic="T extends InputMenuItem | AcceptableValue">
|
|
124
|
-
import { computed, ref, toRef, onMounted } from 'vue'
|
|
125
|
-
import { ComboboxRoot, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxPortal, ComboboxContent, ComboboxViewport, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxSeparator, ComboboxItem, ComboboxItemIndicator, TagsInputRoot, TagsInputItem, TagsInputItemText, TagsInputItemDelete, TagsInputInput, useForwardPropsEmits } from 'radix-vue'
|
|
138
|
+
<script setup lang="ts" generic="T extends MaybeArrayOfArrayItem<I>, I extends MaybeArrayOfArray<InputMenuItem | AcceptableValue> = MaybeArrayOfArray<InputMenuItem | AcceptableValue>, V extends SelectItemKey<T> | undefined = undefined, M extends boolean = false">
|
|
139
|
+
import { computed, ref, toRef, onMounted, toRaw } from 'vue'
|
|
140
|
+
import { ComboboxRoot, ComboboxArrow, ComboboxAnchor, ComboboxInput, ComboboxTrigger, ComboboxPortal, ComboboxContent, ComboboxViewport, ComboboxEmpty, ComboboxGroup, ComboboxLabel, ComboboxSeparator, ComboboxItem, ComboboxItemIndicator, TagsInputRoot, TagsInputItem, TagsInputItemText, TagsInputItemDelete, TagsInputInput, useForwardPropsEmits } from 'radix-vue'
|
|
126
141
|
import { defu } from 'defu'
|
|
127
|
-
import isEqual from '
|
|
128
|
-
import { reactivePick } from '@vueuse/core'
|
|
142
|
+
import { isEqual } from 'ohash'
|
|
143
|
+
import { reactivePick, createReusableTemplate } from '@vueuse/core'
|
|
129
144
|
import { useAppConfig } from '#imports'
|
|
130
145
|
import { useButtonGroup } from '../composables/useButtonGroup'
|
|
131
146
|
import { useComponentIcons } from '../composables/useComponentIcons'
|
|
132
147
|
import { useFormField } from '../composables/useFormField'
|
|
148
|
+
import { useLocale } from '../composables/useLocale'
|
|
133
149
|
import { get, escapeRegExp } from '../utils'
|
|
134
150
|
import UIcon from './Icon.vue'
|
|
135
151
|
import UAvatar from './Avatar.vue'
|
|
@@ -137,25 +153,32 @@ import UChip from './Chip.vue'
|
|
|
137
153
|
|
|
138
154
|
defineOptions({ inheritAttrs: false })
|
|
139
155
|
|
|
140
|
-
const props = withDefaults(defineProps<InputMenuProps<T>>(), {
|
|
156
|
+
const props = withDefaults(defineProps<InputMenuProps<T, I, V, M>>(), {
|
|
141
157
|
type: 'text',
|
|
142
158
|
autofocusDelay: 0,
|
|
143
159
|
portal: true,
|
|
144
|
-
filter:
|
|
145
|
-
labelKey: 'label' as
|
|
160
|
+
filter: true,
|
|
161
|
+
labelKey: 'label' as never
|
|
146
162
|
})
|
|
147
|
-
const emits = defineEmits<InputMenuEmits<T>>()
|
|
163
|
+
const emits = defineEmits<InputMenuEmits<T, V, M>>()
|
|
148
164
|
const slots = defineSlots<InputMenuSlots<T>>()
|
|
149
165
|
|
|
150
166
|
const searchTerm = defineModel<string>('searchTerm', { default: '' })
|
|
151
167
|
|
|
152
168
|
const appConfig = useAppConfig()
|
|
153
|
-
const
|
|
169
|
+
const { t } = useLocale()
|
|
170
|
+
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'selectedValue', 'open', 'defaultOpen', 'resetSearchTermOnBlur'), emits)
|
|
154
171
|
const contentProps = toRef(() => defu(props.content, { side: 'bottom', sideOffset: 8, position: 'popper' }) as ComboboxContentProps)
|
|
172
|
+
const arrowProps = toRef(() => props.arrow as ComboboxArrowProps)
|
|
173
|
+
// This is a hack due to generic boolean casting (see https://github.com/nuxt/ui/issues/2541)
|
|
174
|
+
const multiple = toRef(() => typeof props.multiple === 'string' ? true : props.multiple)
|
|
175
|
+
|
|
155
176
|
const { emitFormBlur, emitFormChange, emitFormInput, size: formGroupSize, color, id, name, highlight, disabled } = useFormField<InputProps>(props)
|
|
156
177
|
const { orientation, size: buttonGroupSize } = useButtonGroup<InputProps>(props)
|
|
157
178
|
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(toRef(() => defu(props, { trailingIcon: appConfig.ui.icons.chevronDown })))
|
|
158
179
|
|
|
180
|
+
const [DefineCreateItemTemplate, ReuseCreateItemTemplate] = createReusableTemplate()
|
|
181
|
+
|
|
159
182
|
const inputSize = computed(() => buttonGroupSize.value || formGroupSize.value)
|
|
160
183
|
|
|
161
184
|
const ui = computed(() => inputMenu({
|
|
@@ -166,33 +189,41 @@ const ui = computed(() => inputMenu({
|
|
|
166
189
|
highlight: highlight.value,
|
|
167
190
|
leading: isLeading.value || !!props.avatar || !!slots.leading,
|
|
168
191
|
trailing: isTrailing.value || !!slots.trailing,
|
|
169
|
-
multiple:
|
|
192
|
+
multiple: multiple.value,
|
|
170
193
|
buttonGroup: orientation.value
|
|
171
194
|
}))
|
|
172
195
|
|
|
173
|
-
function displayValue(value:
|
|
174
|
-
|
|
196
|
+
function displayValue(value: T): string {
|
|
197
|
+
if (!props.valueKey) {
|
|
198
|
+
return value && (typeof value === 'object' ? get(value, props.labelKey as string) : value)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const item = items.value.find(item => isEqual(get(item as Record<string, any>, props.valueKey as string), value))
|
|
175
202
|
|
|
176
203
|
return item && (typeof item === 'object' ? get(item, props.labelKey as string) : item)
|
|
177
204
|
}
|
|
178
205
|
|
|
179
|
-
function filterFunction(
|
|
206
|
+
function filterFunction(
|
|
207
|
+
inputItems: ArrayOrWrapped<T> = items.value as ArrayOrWrapped<T>,
|
|
208
|
+
filterSearchTerm: string = searchTerm.value,
|
|
209
|
+
comparator = (item: any, term: string) => String(item).search(new RegExp(term, 'i')) !== -1
|
|
210
|
+
): ArrayOrWrapped<T> {
|
|
180
211
|
if (props.filter === false) {
|
|
181
|
-
return
|
|
212
|
+
return inputItems
|
|
182
213
|
}
|
|
183
214
|
|
|
184
215
|
const fields = Array.isArray(props.filter) ? props.filter : [props.labelKey]
|
|
185
|
-
const escapedSearchTerm = escapeRegExp(
|
|
216
|
+
const escapedSearchTerm = escapeRegExp(filterSearchTerm ?? '')
|
|
186
217
|
|
|
187
|
-
return
|
|
218
|
+
return inputItems.filter((item) => {
|
|
188
219
|
if (typeof item !== 'object') {
|
|
189
|
-
return
|
|
220
|
+
return comparator(item, escapedSearchTerm)
|
|
190
221
|
}
|
|
191
222
|
|
|
192
223
|
return fields.some((field) => {
|
|
193
224
|
const child = get(item, field as string)
|
|
194
225
|
|
|
195
|
-
return child !== null && child !== undefined &&
|
|
226
|
+
return child !== null && child !== undefined && comparator(child, escapedSearchTerm)
|
|
196
227
|
})
|
|
197
228
|
}) as ArrayOrWrapped<T>
|
|
198
229
|
}
|
|
@@ -201,6 +232,36 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
|
|
|
201
232
|
// eslint-disable-next-line vue/no-dupe-keys
|
|
202
233
|
const items = computed(() => groups.value.flatMap(group => group) as T[])
|
|
203
234
|
|
|
235
|
+
const creatable = computed(() => {
|
|
236
|
+
if (!props.createItem) {
|
|
237
|
+
return false
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const isModelValueCustom = props.modelValue && filterFunction((props.multiple && Array.isArray(props.modelValue) ? props.modelValue : [props.modelValue]) as ArrayOrWrapped<T>, searchTerm.value, (item, term) => String(item) === term).length === 1
|
|
241
|
+
|
|
242
|
+
if (isModelValueCustom) {
|
|
243
|
+
return false
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const filteredItems = filterFunction()
|
|
247
|
+
const newItem = searchTerm.value && {
|
|
248
|
+
item: props.valueKey ? { [props.valueKey]: searchTerm.value, [props.labelKey ?? 'label']: searchTerm.value } : searchTerm.value,
|
|
249
|
+
position: ((typeof props.createItem === 'object' && props.createItem.placement) || 'bottom') as 'top' | 'bottom'
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if ((typeof props.createItem === 'object' && props.createItem.when === 'always') || props.createItem === 'always') {
|
|
253
|
+
return (filteredItems.length === 1 && filterFunction(filteredItems, searchTerm.value, (item, term) => String(item) === term).length === 1) ? false : newItem
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return filteredItems.length > 0 ? false : newItem
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
const rootItems = computed(() => [
|
|
260
|
+
...(creatable.value && creatable.value.position === 'top' ? [creatable.value.item] : []),
|
|
261
|
+
...filterFunction(),
|
|
262
|
+
...(creatable.value && creatable.value.position === 'bottom' ? [creatable.value.item] : [])
|
|
263
|
+
] as ArrayOrWrapped<T>)
|
|
264
|
+
|
|
204
265
|
const inputRef = ref<InstanceType<typeof ComboboxInput> | null>(null)
|
|
205
266
|
|
|
206
267
|
function autoFocus() {
|
|
@@ -216,6 +277,9 @@ onMounted(() => {
|
|
|
216
277
|
})
|
|
217
278
|
|
|
218
279
|
function onUpdate(value: any) {
|
|
280
|
+
if (toRaw(props.modelValue) === value) {
|
|
281
|
+
return
|
|
282
|
+
}
|
|
219
283
|
// @ts-expect-error - 'target' does not exist in type 'EventInit'
|
|
220
284
|
const event = new Event('change', { target: { value } })
|
|
221
285
|
emits('change', event)
|
|
@@ -249,6 +313,22 @@ defineExpose({
|
|
|
249
313
|
</script>
|
|
250
314
|
|
|
251
315
|
<template>
|
|
316
|
+
<DefineCreateItemTemplate>
|
|
317
|
+
<ComboboxGroup v-if="creatable" :class="ui.group({ class: props.ui?.group })">
|
|
318
|
+
<ComboboxItem
|
|
319
|
+
:class="ui.item({ class: props.ui?.item })"
|
|
320
|
+
:value="valueKey && typeof creatable.item === 'object' ? get(creatable.item, props.valueKey as string) : creatable.item"
|
|
321
|
+
@select="e => emits('create', e, (creatable as any).item as T)"
|
|
322
|
+
>
|
|
323
|
+
<span :class="ui.itemLabel({ class: props.ui?.itemLabel })">
|
|
324
|
+
<slot name="create-item-label" :item="(creatable.item as T)">
|
|
325
|
+
{{ t('inputMenu.create', { label: typeof creatable.item === 'object' ? get(creatable.item, props.labelKey as string) : creatable.item }) }}
|
|
326
|
+
</slot>
|
|
327
|
+
</span>
|
|
328
|
+
</ComboboxItem>
|
|
329
|
+
</ComboboxGroup>
|
|
330
|
+
</DefineCreateItemTemplate>
|
|
331
|
+
|
|
252
332
|
<ComboboxRoot
|
|
253
333
|
:id="id"
|
|
254
334
|
v-slot="{ modelValue, open }"
|
|
@@ -256,8 +336,9 @@ defineExpose({
|
|
|
256
336
|
v-model:search-term="searchTerm"
|
|
257
337
|
:name="name"
|
|
258
338
|
:disabled="disabled"
|
|
339
|
+
:multiple="multiple"
|
|
259
340
|
:display-value="displayValue"
|
|
260
|
-
:filter-function="
|
|
341
|
+
:filter-function="() => rootItems"
|
|
261
342
|
:class="ui.root({ class: [props.class, props.ui?.root] })"
|
|
262
343
|
:as-child="!!multiple"
|
|
263
344
|
@update:model-value="onUpdate"
|
|
@@ -331,11 +412,13 @@ defineExpose({
|
|
|
331
412
|
<ComboboxContent :class="ui.content({ class: props.ui?.content })" v-bind="contentProps">
|
|
332
413
|
<ComboboxEmpty :class="ui.empty({ class: props.ui?.empty })">
|
|
333
414
|
<slot name="empty" :search-term="searchTerm">
|
|
334
|
-
{{ searchTerm ?
|
|
415
|
+
{{ searchTerm ? t('inputMenu.noMatch', { searchTerm }) : t('inputMenu.noData') }}
|
|
335
416
|
</slot>
|
|
336
417
|
</ComboboxEmpty>
|
|
337
418
|
|
|
338
419
|
<ComboboxViewport :class="ui.viewport({ class: props.ui?.viewport })">
|
|
420
|
+
<ReuseCreateItemTemplate v-if="creatable && creatable.position === 'top'" />
|
|
421
|
+
|
|
339
422
|
<ComboboxGroup v-for="(group, groupIndex) in groups" :key="`group-${groupIndex}`" :class="ui.group({ class: props.ui?.group })">
|
|
340
423
|
<template v-for="(item, index) in group" :key="`group-${groupIndex}-${index}`">
|
|
341
424
|
<ComboboxLabel v-if="item?.type === 'label'" :class="ui.label({ class: props.ui?.label })">
|
|
@@ -382,7 +465,11 @@ defineExpose({
|
|
|
382
465
|
</ComboboxItem>
|
|
383
466
|
</template>
|
|
384
467
|
</ComboboxGroup>
|
|
468
|
+
|
|
469
|
+
<ReuseCreateItemTemplate v-if="creatable && creatable.position === 'bottom'" />
|
|
385
470
|
</ComboboxViewport>
|
|
471
|
+
|
|
472
|
+
<ComboboxArrow v-if="!!arrow" v-bind="arrowProps" :class="ui.arrow({ class: props.ui?.arrow })" />
|
|
386
473
|
</ComboboxContent>
|
|
387
474
|
</ComboboxPortal>
|
|
388
475
|
</ComboboxRoot>
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { tv, type VariantProps } from 'tailwind-variants'
|
|
3
|
+
import type { NumberFieldRootProps } from 'radix-vue'
|
|
4
|
+
import type { AppConfig } from '@nuxt/schema'
|
|
5
|
+
import _appConfig from '#build/app.config'
|
|
6
|
+
import theme from '#build/ui/input-number'
|
|
7
|
+
import type { ButtonProps } from '../types'
|
|
8
|
+
|
|
9
|
+
const appConfig = _appConfig as AppConfig & { ui: { inputNumber: Partial<typeof theme> } }
|
|
10
|
+
|
|
11
|
+
const inputNumber = tv({ extend: tv(theme), ...(appConfig.ui?.inputNumber || {}) })
|
|
12
|
+
|
|
13
|
+
type InputNumberVariants = VariantProps<typeof inputNumber>
|
|
14
|
+
|
|
15
|
+
export interface InputNumberProps extends Pick<NumberFieldRootProps, 'modelValue' | 'defaultValue' | 'min' | 'max' | 'step' | 'disabled' | 'required' | 'id' | 'name' | 'formatOptions'> {
|
|
16
|
+
/**
|
|
17
|
+
* The element or component this component should render as.
|
|
18
|
+
* @defaultValue 'div'
|
|
19
|
+
*/
|
|
20
|
+
as?: any
|
|
21
|
+
class?: any
|
|
22
|
+
/** The placeholder text when the input is empty. */
|
|
23
|
+
placeholder?: string
|
|
24
|
+
ui?: Partial<typeof inputNumber.slots>
|
|
25
|
+
color?: InputNumberVariants['color']
|
|
26
|
+
variant?: InputNumberVariants['variant']
|
|
27
|
+
size?: InputNumberVariants['size']
|
|
28
|
+
/** Highlight the ring color like a focus state. */
|
|
29
|
+
highlight?: boolean
|
|
30
|
+
/**
|
|
31
|
+
* The orientation of the input menu.
|
|
32
|
+
* @defaultValue 'horizontal'
|
|
33
|
+
*/
|
|
34
|
+
orientation?: 'vertical' | 'horizontal'
|
|
35
|
+
/**
|
|
36
|
+
* Configure the increment button. The `color` and `size` are inherited.
|
|
37
|
+
* @defaultValue { variant: 'link' }
|
|
38
|
+
*/
|
|
39
|
+
increment?: ButtonProps
|
|
40
|
+
/**
|
|
41
|
+
* The icon displayed to increment the value.
|
|
42
|
+
* @defaultValue appConfig.ui.icons.plus
|
|
43
|
+
*/
|
|
44
|
+
incrementIcon?: string
|
|
45
|
+
/**
|
|
46
|
+
* Configure the decrement button. The `color` and `size` are inherited.
|
|
47
|
+
* @defaultValue { variant: 'link' }
|
|
48
|
+
*/
|
|
49
|
+
decrement?: ButtonProps
|
|
50
|
+
/**
|
|
51
|
+
* The icon displayed to decrement the value.
|
|
52
|
+
* @defaultValue appConfig.ui.icons.minus
|
|
53
|
+
*/
|
|
54
|
+
decrementIcon?: string
|
|
55
|
+
autofocus?: boolean
|
|
56
|
+
autofocusDelay?: number
|
|
57
|
+
/**
|
|
58
|
+
* The locale to use for formatting and parsing numbers.
|
|
59
|
+
* @defaultValue UApp.locale.code
|
|
60
|
+
*/
|
|
61
|
+
locale?: string
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface InputNumberEmits {
|
|
65
|
+
(e: 'update:modelValue', payload: number): void
|
|
66
|
+
(e: 'blur', event: FocusEvent): void
|
|
67
|
+
(e: 'change', payload: Event): void
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface InputNumberSlots {
|
|
71
|
+
increment(props?: {}): any
|
|
72
|
+
decrement(props?: {}): any
|
|
73
|
+
}
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<script setup lang="ts">
|
|
77
|
+
import { onMounted, ref, computed } from 'vue'
|
|
78
|
+
import { NumberFieldRoot, NumberFieldInput, NumberFieldDecrement, NumberFieldIncrement, useForwardPropsEmits } from 'radix-vue'
|
|
79
|
+
import { reactivePick } from '@vueuse/core'
|
|
80
|
+
import { useFormField } from '../composables/useFormField'
|
|
81
|
+
import { useLocale } from '../composables/useLocale'
|
|
82
|
+
import UButton from './Button.vue'
|
|
83
|
+
|
|
84
|
+
defineOptions({ inheritAttrs: false })
|
|
85
|
+
|
|
86
|
+
const props = withDefaults(defineProps<InputNumberProps>(), {
|
|
87
|
+
orientation: 'horizontal'
|
|
88
|
+
})
|
|
89
|
+
const emits = defineEmits<InputNumberEmits>()
|
|
90
|
+
defineSlots<InputNumberSlots>()
|
|
91
|
+
|
|
92
|
+
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'modelValue', 'defaultValue', 'min', 'max', 'step', 'formatOptions'), emits)
|
|
93
|
+
|
|
94
|
+
const { emitFormBlur, emitFormChange, emitFormInput, id, color, size, name, highlight, disabled } = useFormField<InputNumberProps>(props)
|
|
95
|
+
|
|
96
|
+
const { t, code: codeLocale } = useLocale()
|
|
97
|
+
const locale = computed(() => props.locale || codeLocale.value)
|
|
98
|
+
|
|
99
|
+
const ui = computed(() => inputNumber({
|
|
100
|
+
color: color.value,
|
|
101
|
+
variant: props.variant,
|
|
102
|
+
size: size.value,
|
|
103
|
+
highlight: highlight.value,
|
|
104
|
+
orientation: props.orientation
|
|
105
|
+
}))
|
|
106
|
+
|
|
107
|
+
const incrementIcon = computed(() => props.incrementIcon || (props.orientation === 'horizontal' ? appConfig.ui.icons.plus : appConfig.ui.icons.chevronUp))
|
|
108
|
+
const decrementIcon = computed(() => props.decrementIcon || (props.orientation === 'horizontal' ? appConfig.ui.icons.minus : appConfig.ui.icons.chevronDown))
|
|
109
|
+
|
|
110
|
+
const inputRef = ref<InstanceType<typeof NumberFieldInput> | null>(null)
|
|
111
|
+
|
|
112
|
+
function autoFocus() {
|
|
113
|
+
if (props.autofocus) {
|
|
114
|
+
inputRef.value?.$el?.focus()
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
onMounted(() => {
|
|
119
|
+
setTimeout(() => {
|
|
120
|
+
autoFocus()
|
|
121
|
+
}, props.autofocusDelay)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
function onUpdate(value: number) {
|
|
125
|
+
// @ts-expect-error - 'target' does not exist in type 'EventInit'
|
|
126
|
+
const event = new Event('change', { target: { value } })
|
|
127
|
+
emits('change', event)
|
|
128
|
+
|
|
129
|
+
emitFormChange()
|
|
130
|
+
emitFormInput()
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function onBlur(event: FocusEvent) {
|
|
134
|
+
emitFormBlur()
|
|
135
|
+
emits('blur', event)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
defineExpose({
|
|
139
|
+
inputRef
|
|
140
|
+
})
|
|
141
|
+
</script>
|
|
142
|
+
|
|
143
|
+
<template>
|
|
144
|
+
<NumberFieldRoot
|
|
145
|
+
v-bind="rootProps"
|
|
146
|
+
:id="id"
|
|
147
|
+
:class="ui.root({ class: [props.class, props.ui?.root] })"
|
|
148
|
+
:name="name"
|
|
149
|
+
:disabled="disabled"
|
|
150
|
+
:locale="locale"
|
|
151
|
+
@update:model-value="onUpdate"
|
|
152
|
+
>
|
|
153
|
+
<NumberFieldInput
|
|
154
|
+
v-bind="$attrs"
|
|
155
|
+
ref="inputRef"
|
|
156
|
+
:placeholder="placeholder"
|
|
157
|
+
:required="required"
|
|
158
|
+
:class="ui.base({ class: props.ui?.base })"
|
|
159
|
+
@blur="onBlur"
|
|
160
|
+
/>
|
|
161
|
+
|
|
162
|
+
<div :class="ui.increment({ class: props.ui?.increment })">
|
|
163
|
+
<NumberFieldIncrement as-child :disabled="disabled">
|
|
164
|
+
<slot name="increment">
|
|
165
|
+
<UButton
|
|
166
|
+
:icon="incrementIcon"
|
|
167
|
+
:color="color"
|
|
168
|
+
:size="size"
|
|
169
|
+
variant="link"
|
|
170
|
+
:aria-label="t('inputNumber.increment')"
|
|
171
|
+
v-bind="typeof increment === 'object' ? increment : undefined"
|
|
172
|
+
/>
|
|
173
|
+
</slot>
|
|
174
|
+
</NumberFieldIncrement>
|
|
175
|
+
</div>
|
|
176
|
+
|
|
177
|
+
<div :class="ui.decrement({ class: props.ui?.decrement })">
|
|
178
|
+
<NumberFieldDecrement as-child :disabled="disabled">
|
|
179
|
+
<slot name="decrement">
|
|
180
|
+
<UButton
|
|
181
|
+
:icon="decrementIcon"
|
|
182
|
+
:color="color"
|
|
183
|
+
:size="size"
|
|
184
|
+
variant="link"
|
|
185
|
+
:aria-label="t('inputNumber.decrement')"
|
|
186
|
+
v-bind="typeof decrement === 'object' ? decrement : undefined"
|
|
187
|
+
/>
|
|
188
|
+
</slot>
|
|
189
|
+
</NumberFieldDecrement>
|
|
190
|
+
</div>
|
|
191
|
+
</NumberFieldRoot>
|
|
192
|
+
</template>
|
|
@@ -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/kbd'
|
|
6
6
|
import type { KbdKey } from '../composables/useKbd'
|
|
7
|
+
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
|
7
8
|
|
|
8
9
|
const appConfig = _appConfig as AppConfig & { ui: { kbd: Partial<typeof theme> } }
|
|
9
10
|
|
|
@@ -26,6 +27,7 @@ export interface KbdProps {
|
|
|
26
27
|
export interface KbdSlots {
|
|
27
28
|
default(props?: {}): any
|
|
28
29
|
}
|
|
30
|
+
extendDevtoolsMeta({ defaultProps: { value: 'K' } })
|
|
29
31
|
</script>
|
|
30
32
|
|
|
31
33
|
<script setup lang="ts">
|
|
@@ -3,8 +3,55 @@ import type { ButtonHTMLAttributes } from 'vue'
|
|
|
3
3
|
import { tv } from 'tailwind-variants'
|
|
4
4
|
import type { AppConfig } from '@nuxt/schema'
|
|
5
5
|
import _appConfig from '#build/app.config'
|
|
6
|
+
import type { RouterLinkProps, RouteLocationRaw } from 'vue-router'
|
|
6
7
|
import theme from '#build/ui/link'
|
|
7
|
-
import
|
|
8
|
+
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
|
9
|
+
|
|
10
|
+
interface NuxtLinkProps extends Omit<RouterLinkProps, 'to'> {
|
|
11
|
+
/**
|
|
12
|
+
* Route Location the link should navigate to when clicked on.
|
|
13
|
+
*/
|
|
14
|
+
to?: RouteLocationRaw // need to manually type to avoid breaking typedPages
|
|
15
|
+
/**
|
|
16
|
+
* An alias for `to`. If used with `to`, `href` will be ignored
|
|
17
|
+
*/
|
|
18
|
+
href?: NuxtLinkProps['to']
|
|
19
|
+
/**
|
|
20
|
+
* Forces the link to be considered as external (true) or internal (false). This is helpful to handle edge-cases
|
|
21
|
+
*/
|
|
22
|
+
external?: boolean
|
|
23
|
+
/**
|
|
24
|
+
* Where to display the linked URL, as the name for a browsing context.
|
|
25
|
+
*/
|
|
26
|
+
target?: '_blank' | '_parent' | '_self' | '_top' | (string & {}) | null
|
|
27
|
+
/**
|
|
28
|
+
* A rel attribute value to apply on the link. Defaults to "noopener noreferrer" for external links.
|
|
29
|
+
*/
|
|
30
|
+
rel?: 'noopener' | 'noreferrer' | 'nofollow' | 'sponsored' | 'ugc' | (string & {}) | null
|
|
31
|
+
/**
|
|
32
|
+
* If set to true, no rel attribute will be added to the link
|
|
33
|
+
*/
|
|
34
|
+
noRel?: boolean
|
|
35
|
+
/**
|
|
36
|
+
* A class to apply to links that have been prefetched.
|
|
37
|
+
*/
|
|
38
|
+
prefetchedClass?: string
|
|
39
|
+
/**
|
|
40
|
+
* When enabled will prefetch middleware, layouts and payloads of links in the viewport.
|
|
41
|
+
*/
|
|
42
|
+
prefetch?: boolean
|
|
43
|
+
/**
|
|
44
|
+
* Allows controlling when to prefetch links. By default, prefetch is triggered only on visibility.
|
|
45
|
+
*/
|
|
46
|
+
prefetchOn?: 'visibility' | 'interaction' | Partial<{
|
|
47
|
+
visibility: boolean
|
|
48
|
+
interaction: boolean
|
|
49
|
+
}>
|
|
50
|
+
/**
|
|
51
|
+
* Escape hatch to disable `prefetch` attribute.
|
|
52
|
+
*/
|
|
53
|
+
noPrefetch?: boolean
|
|
54
|
+
}
|
|
8
55
|
|
|
9
56
|
const appConfig = _appConfig as AppConfig & { ui: { link: Partial<typeof theme> } }
|
|
10
57
|
|
|
@@ -26,8 +73,8 @@ export interface LinkProps extends NuxtLinkProps {
|
|
|
26
73
|
active?: boolean
|
|
27
74
|
/** Will only be active if the current route is an exact match. */
|
|
28
75
|
exact?: boolean
|
|
29
|
-
/**
|
|
30
|
-
exactQuery?: boolean
|
|
76
|
+
/** Allows controlling how the current route query sets the link as active. */
|
|
77
|
+
exactQuery?: boolean | 'partial'
|
|
31
78
|
/** Will only be active if the current route hash is an exact match. */
|
|
32
79
|
exactHash?: boolean
|
|
33
80
|
/** The class to apply when the link is inactive. */
|
|
@@ -41,14 +88,17 @@ export interface LinkProps extends NuxtLinkProps {
|
|
|
41
88
|
export interface LinkSlots {
|
|
42
89
|
default(props: { active: boolean }): any
|
|
43
90
|
}
|
|
91
|
+
|
|
92
|
+
extendDevtoolsMeta({ example: 'LinkExample' })
|
|
44
93
|
</script>
|
|
45
94
|
|
|
46
95
|
<script setup lang="ts">
|
|
47
96
|
import { computed } from 'vue'
|
|
48
|
-
import { isEqual } from 'ohash'
|
|
97
|
+
import { isEqual, diff } from 'ohash'
|
|
49
98
|
import { useForwardProps } from 'radix-vue'
|
|
50
99
|
import { reactiveOmit } from '@vueuse/core'
|
|
51
100
|
import { useRoute } from '#imports'
|
|
101
|
+
import ULinkBase from './LinkBase.vue'
|
|
52
102
|
|
|
53
103
|
defineOptions({ inheritAttrs: false })
|
|
54
104
|
|
|
@@ -74,14 +124,27 @@ const ui = computed(() => tv({
|
|
|
74
124
|
}
|
|
75
125
|
}))
|
|
76
126
|
|
|
127
|
+
function isPartiallyEqual(item1: any, item2: any) {
|
|
128
|
+
const diffedKeys = diff(item1, item2).reduce((filtered, q) => {
|
|
129
|
+
if (q.type === 'added') {
|
|
130
|
+
filtered.push(q.key)
|
|
131
|
+
}
|
|
132
|
+
return filtered
|
|
133
|
+
}, [] as string[])
|
|
134
|
+
return isEqual(item1, item2, { excludeKeys: key => diffedKeys.includes(key) })
|
|
135
|
+
}
|
|
136
|
+
|
|
77
137
|
function isLinkActive({ route: linkRoute, isActive, isExactActive }: any) {
|
|
78
138
|
if (props.active !== undefined) {
|
|
79
139
|
return props.active
|
|
80
140
|
}
|
|
81
141
|
|
|
82
|
-
if (props.exactQuery
|
|
83
|
-
return false
|
|
142
|
+
if (props.exactQuery === 'partial') {
|
|
143
|
+
if (!isPartiallyEqual(linkRoute.query, route.query)) return false
|
|
144
|
+
} else if (props.exactQuery === true) {
|
|
145
|
+
if (!isEqual(linkRoute.query, route.query)) return false
|
|
84
146
|
}
|
|
147
|
+
|
|
85
148
|
if (props.exactHash && linkRoute.hash !== route.hash) {
|
|
86
149
|
return false
|
|
87
150
|
}
|
|
@@ -4,6 +4,7 @@ import type { DialogRootProps, DialogRootEmits, DialogContentProps } from 'radix
|
|
|
4
4
|
import type { AppConfig } from '@nuxt/schema'
|
|
5
5
|
import _appConfig from '#build/app.config'
|
|
6
6
|
import theme from '#build/ui/modal'
|
|
7
|
+
import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
|
|
7
8
|
import type { ButtonProps } from '../types'
|
|
8
9
|
|
|
9
10
|
const appConfig = _appConfig as AppConfig & { ui: { modal: Partial<typeof theme> } }
|
|
@@ -67,6 +68,8 @@ export interface ModalSlots {
|
|
|
67
68
|
body(props?: {}): any
|
|
68
69
|
footer(props?: {}): any
|
|
69
70
|
}
|
|
71
|
+
|
|
72
|
+
extendDevtoolsMeta({ example: 'ModalExample' })
|
|
70
73
|
</script>
|
|
71
74
|
|
|
72
75
|
<script setup lang="ts">
|
|
@@ -74,6 +77,7 @@ import { computed, toRef } from 'vue'
|
|
|
74
77
|
import { DialogRoot, DialogTrigger, DialogPortal, DialogOverlay, DialogContent, DialogTitle, DialogDescription, DialogClose, useForwardPropsEmits } from 'radix-vue'
|
|
75
78
|
import { reactivePick } from '@vueuse/core'
|
|
76
79
|
import { useAppConfig } from '#imports'
|
|
80
|
+
import { useLocale } from '../composables/useLocale'
|
|
77
81
|
import UButton from './Button.vue'
|
|
78
82
|
|
|
79
83
|
const props = withDefaults(defineProps<ModalProps>(), {
|
|
@@ -92,14 +96,22 @@ const contentEvents = computed(() => {
|
|
|
92
96
|
if (props.preventClose) {
|
|
93
97
|
return {
|
|
94
98
|
pointerDownOutside: (e: Event) => e.preventDefault(),
|
|
95
|
-
interactOutside: (e: Event) => e.preventDefault()
|
|
99
|
+
interactOutside: (e: Event) => e.preventDefault(),
|
|
100
|
+
escapeKeyDown: (e: Event) => e.preventDefault()
|
|
96
101
|
}
|
|
97
102
|
}
|
|
98
103
|
|
|
99
|
-
return {
|
|
104
|
+
return {
|
|
105
|
+
interactOutside: (e: Event) => {
|
|
106
|
+
if (e.target instanceof Element && e.target.closest('[data-sonner-toaster]')) {
|
|
107
|
+
return e.preventDefault()
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
100
111
|
})
|
|
101
112
|
|
|
102
113
|
const appConfig = useAppConfig()
|
|
114
|
+
const { t } = useLocale()
|
|
103
115
|
|
|
104
116
|
const ui = computed(() => modal({
|
|
105
117
|
transition: props.transition,
|
|
@@ -140,7 +152,7 @@ const ui = computed(() => modal({
|
|
|
140
152
|
size="md"
|
|
141
153
|
color="neutral"
|
|
142
154
|
variant="ghost"
|
|
143
|
-
aria-label="
|
|
155
|
+
:aria-label="t('modal.close')"
|
|
144
156
|
v-bind="typeof close === 'object' ? close : undefined"
|
|
145
157
|
:class="ui.close({ class: props.ui?.close })"
|
|
146
158
|
/>
|