@byyuurin/ui 0.0.8 → 0.0.10
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/README.md +0 -3
- package/dist/module.json +1 -1
- package/dist/module.mjs +4 -3
- package/dist/module.mjs.map +1 -1
- package/dist/runtime/app/injections.d.ts +9299 -8
- package/dist/runtime/app/injections.js +35 -5
- package/dist/runtime/components/Accordion.vue +17 -19
- package/dist/runtime/components/Alert.vue +6 -9
- package/dist/runtime/components/App.vue +14 -19
- package/dist/runtime/components/Avatar.vue +5 -8
- package/dist/runtime/components/AvatarGroup.vue +2 -5
- package/dist/runtime/components/Badge.vue +3 -6
- package/dist/runtime/components/Breadcrumb.vue +22 -23
- package/dist/runtime/components/Button.vue +2 -3
- package/dist/runtime/components/ButtonGroup.vue +2 -5
- package/dist/runtime/components/Calendar.vue +185 -0
- package/dist/runtime/components/Card.vue +2 -5
- package/dist/runtime/components/Carousel.vue +11 -16
- package/dist/runtime/components/Checkbox.vue +13 -11
- package/dist/runtime/components/Chip.vue +6 -9
- package/dist/runtime/components/Collapsible.vue +2 -5
- package/dist/runtime/components/Drawer.vue +88 -45
- package/dist/runtime/components/DropdownMenu.vue +143 -0
- package/dist/runtime/components/DropdownMenuContent.vue +188 -0
- package/dist/runtime/components/Form.vue +311 -0
- package/dist/runtime/components/FormItem.vue +129 -0
- package/dist/runtime/components/Input.vue +34 -23
- package/dist/runtime/components/InputNumber.vue +23 -18
- package/dist/runtime/components/Kbd.vue +2 -6
- package/dist/runtime/components/Link.vue +25 -7
- package/dist/runtime/components/Modal.vue +31 -22
- package/dist/runtime/components/OverlayProvider.vue +29 -0
- package/dist/runtime/components/Pagination.vue +34 -27
- package/dist/runtime/components/PinInput.vue +23 -17
- package/dist/runtime/components/Popover.vue +5 -8
- package/dist/runtime/components/Progress.vue +2 -5
- package/dist/runtime/components/RadioGroup.vue +52 -49
- package/dist/runtime/components/ScrollArea.vue +2 -6
- package/dist/runtime/components/Select.vue +96 -89
- package/dist/runtime/components/Separator.vue +2 -6
- package/dist/runtime/components/Skeleton.vue +2 -5
- package/dist/runtime/components/Slider.vue +13 -11
- package/dist/runtime/components/Switch.vue +18 -11
- package/dist/runtime/components/Table.vue +23 -13
- package/dist/runtime/components/Tabs.vue +14 -16
- package/dist/runtime/components/Textarea.vue +20 -17
- package/dist/runtime/components/Toast.vue +12 -13
- package/dist/runtime/components/{Toaster.vue → ToastProvider.vue} +18 -16
- package/dist/runtime/components/Tooltip.vue +5 -8
- package/dist/runtime/composables/useFormItem.d.ts +27 -0
- package/dist/runtime/composables/useFormItem.js +64 -0
- package/dist/runtime/composables/useKbd.d.ts +1 -1
- package/dist/runtime/composables/useOverlay.d.ts +29 -0
- package/dist/runtime/composables/useOverlay.js +69 -0
- package/dist/runtime/composables/useTheme.d.ts +6 -2
- package/dist/runtime/composables/useTheme.js +10 -3
- package/dist/runtime/composables/useToast.d.ts +4 -20
- package/dist/runtime/composables/useToast.js +6 -5
- package/dist/runtime/index.d.ts +6 -2
- package/dist/runtime/index.js +6 -2
- package/dist/runtime/locale/en.js +6 -0
- package/dist/runtime/locale/zh-tw.js +6 -0
- package/dist/runtime/theme/accordion.js +3 -3
- package/dist/runtime/theme/alert.js +3 -3
- package/dist/runtime/theme/app.d.ts +1 -0
- package/dist/runtime/theme/app.js +2 -1
- package/dist/runtime/theme/avatar.js +2 -2
- package/dist/runtime/theme/badge.d.ts +21 -45
- package/dist/runtime/theme/breadcrumb.d.ts +3 -3
- package/dist/runtime/theme/breadcrumb.js +5 -5
- package/dist/runtime/theme/button.d.ts +111 -57
- package/dist/runtime/theme/button.js +13 -13
- package/dist/runtime/theme/calendar.d.ts +56 -0
- package/dist/runtime/theme/calendar.js +69 -0
- package/dist/runtime/theme/card.js +6 -6
- package/dist/runtime/theme/carousel.js +1 -1
- package/dist/runtime/theme/checkbox.js +5 -5
- package/dist/runtime/theme/chip.d.ts +11 -44
- package/dist/runtime/theme/chip.js +3 -3
- package/dist/runtime/theme/drawer.d.ts +85 -47
- package/dist/runtime/theme/drawer.js +46 -19
- package/dist/runtime/theme/dropdown-menu.d.ts +71 -0
- package/dist/runtime/theme/dropdown-menu.js +83 -0
- package/dist/runtime/theme/form-item.d.ts +76 -0
- package/dist/runtime/theme/form-item.js +34 -0
- package/dist/runtime/theme/form.d.ts +8 -0
- package/dist/runtime/theme/form.js +7 -0
- package/dist/runtime/theme/index.d.ts +5 -1
- package/dist/runtime/theme/index.js +5 -1
- package/dist/runtime/theme/input-number.d.ts +41 -61
- package/dist/runtime/theme/input-number.js +1 -1
- package/dist/runtime/theme/input.d.ts +99 -71
- package/dist/runtime/theme/input.js +15 -15
- package/dist/runtime/theme/kbd.d.ts +2 -2
- package/dist/runtime/theme/kbd.js +1 -1
- package/dist/runtime/theme/link.d.ts +1 -1
- package/dist/runtime/theme/link.js +3 -3
- package/dist/runtime/theme/modal.d.ts +5 -33
- package/dist/runtime/theme/modal.js +4 -4
- package/dist/runtime/theme/pagination.d.ts +27 -3
- package/dist/runtime/theme/pagination.js +6 -2
- package/dist/runtime/theme/pinInput.d.ts +42 -42
- package/dist/runtime/theme/pinInput.js +13 -13
- package/dist/runtime/theme/progress.d.ts +117 -53
- package/dist/runtime/theme/progress.js +4 -4
- package/dist/runtime/theme/radio-group.d.ts +2 -2
- package/dist/runtime/theme/radio-group.js +7 -7
- package/dist/runtime/theme/select.d.ts +100 -84
- package/dist/runtime/theme/select.js +21 -20
- package/dist/runtime/theme/separator.d.ts +13 -28
- package/dist/runtime/theme/separator.js +1 -1
- package/dist/runtime/theme/skeleton.d.ts +1 -1
- package/dist/runtime/theme/skeleton.js +1 -1
- package/dist/runtime/theme/slider.js +1 -1
- package/dist/runtime/theme/switch.js +5 -5
- package/dist/runtime/theme/table.d.ts +3 -0
- package/dist/runtime/theme/table.js +8 -7
- package/dist/runtime/theme/tabs.d.ts +51 -68
- package/dist/runtime/theme/tabs.js +10 -10
- package/dist/runtime/theme/textarea.d.ts +37 -43
- package/dist/runtime/theme/textarea.js +13 -13
- package/dist/runtime/theme/{toaster.d.ts → toast-provider.d.ts} +26 -41
- package/dist/runtime/theme/toast.js +5 -5
- package/dist/runtime/theme/tooltip.js +1 -1
- package/dist/runtime/types/components.d.ts +6 -1
- package/dist/runtime/types/form.d.ts +45 -0
- package/dist/runtime/types/form.js +0 -0
- package/dist/runtime/types/index.d.ts +5 -2
- package/dist/runtime/types/index.js +1 -0
- package/dist/runtime/types/locale.d.ts +6 -0
- package/dist/runtime/types/utils.d.ts +35 -12
- package/dist/runtime/utils/extend-theme.js +15 -4
- package/dist/runtime/utils/form.d.ts +5 -0
- package/dist/runtime/utils/form.js +24 -0
- package/dist/runtime/utils/index.d.ts +2 -0
- package/dist/runtime/utils/index.js +4 -0
- package/dist/runtime/utils/link.d.ts +4 -26
- package/dist/runtime/utils/link.js +10 -3
- package/dist/shared/ui.3e7fad19.mjs +5 -0
- package/dist/shared/ui.3e7fad19.mjs.map +1 -0
- package/dist/unocss.mjs +21 -16
- package/dist/unocss.mjs.map +1 -1
- package/dist/unplugin.mjs +1 -1
- package/dist/vite.mjs +1 -1
- package/package.json +20 -18
- package/dist/runtime/components/ModalProvider.vue +0 -11
- package/dist/runtime/composables/useModal.d.ts +0 -10
- package/dist/runtime/composables/useModal.js +0 -47
- package/dist/shared/ui.ba24b380.mjs +0 -4
- package/dist/shared/ui.ba24b380.mjs.map +0 -1
- /package/dist/runtime/theme/{toaster.js → toast-provider.js} +0 -0
|
@@ -11,13 +11,15 @@ import type { AcceptableValue, PrimitiveProps } from 'reka-ui'
|
|
|
11
11
|
import type { carousel } from '../theme'
|
|
12
12
|
import type { ButtonProps, ComponentAttrs } from '../types'
|
|
13
13
|
|
|
14
|
-
export
|
|
14
|
+
export type CarouselItem = AcceptableValue
|
|
15
|
+
|
|
16
|
+
export interface CarouselSlots<T extends CarouselItem = CarouselItem> {
|
|
15
17
|
default?: (props: { item: T, index: number }) => any
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
type CarouselVariants = VariantProps<typeof carousel>
|
|
19
21
|
|
|
20
|
-
export interface CarouselProps<T> extends ComponentAttrs<typeof carousel>, Omit<EmblaOptionsType, 'axis' | 'container' | 'slides' | 'direction'> {
|
|
22
|
+
export interface CarouselProps<T extends CarouselItem = CarouselItem> extends ComponentAttrs<typeof carousel>, Omit<EmblaOptionsType, 'axis' | 'container' | 'slides' | 'direction'> {
|
|
21
23
|
/**
|
|
22
24
|
* The element or component this component should render as.
|
|
23
25
|
* @default "div"
|
|
@@ -55,7 +57,6 @@ export interface CarouselProps<T> extends ComponentAttrs<typeof carousel>, Omit<
|
|
|
55
57
|
dots?: boolean
|
|
56
58
|
orientation?: CarouselVariants['orientation']
|
|
57
59
|
items?: T[]
|
|
58
|
-
dir?: 'rtl' | 'ltr'
|
|
59
60
|
/**
|
|
60
61
|
* Enable Autoplay plugin
|
|
61
62
|
* @link https://www.embla-carousel.com/plugins/autoplay/
|
|
@@ -89,7 +90,7 @@ export interface CarouselProps<T> extends ComponentAttrs<typeof carousel>, Omit<
|
|
|
89
90
|
}
|
|
90
91
|
</script>
|
|
91
92
|
|
|
92
|
-
<script setup lang="ts" generic="T extends
|
|
93
|
+
<script setup lang="ts" generic="T extends CarouselItem">
|
|
93
94
|
import { computedAsync, reactivePick } from '@vueuse/core'
|
|
94
95
|
import useEmblaCarousel from 'embla-carousel-vue'
|
|
95
96
|
import { Primitive, useForwardProps } from 'reka-ui'
|
|
@@ -103,8 +104,6 @@ const props = withDefaults(defineProps<CarouselProps<T>>(), {
|
|
|
103
104
|
arrows: false,
|
|
104
105
|
dots: false,
|
|
105
106
|
|
|
106
|
-
dir: 'ltr',
|
|
107
|
-
|
|
108
107
|
// Embla Options
|
|
109
108
|
active: true,
|
|
110
109
|
align: 'center',
|
|
@@ -135,21 +134,18 @@ defineSlots<CarouselSlots<T>>()
|
|
|
135
134
|
|
|
136
135
|
const rootProps = useForwardProps(reactivePick(props, 'active', 'align', 'breakpoints', 'containScroll', 'dragFree', 'dragThreshold', 'duration', 'inViewThreshold', 'loop', 'skipSnaps', 'slidesToScroll', 'startIndex', 'watchDrag', 'watchResize', 'watchSlides', 'watchFocus'))
|
|
137
136
|
|
|
138
|
-
const { t } = useLocale()
|
|
139
|
-
const { theme,
|
|
140
|
-
const style = computed(() =>
|
|
141
|
-
const styler = createStyler(theme.value.carousel)
|
|
142
|
-
return styler(props)
|
|
143
|
-
})
|
|
137
|
+
const { t, dir } = useLocale()
|
|
138
|
+
const { theme, generateStyle } = useTheme()
|
|
139
|
+
const style = computed(() => generateStyle('carousel', props))
|
|
144
140
|
|
|
145
|
-
const prevIcon = computed(() => props.prevIcon || (
|
|
146
|
-
const nextIcon = computed(() => props.nextIcon || (
|
|
141
|
+
const prevIcon = computed(() => props.prevIcon || (dir.value === 'rtl' ? theme.value.app.icons.chevronRight : theme.value.app.icons.chevronLeft))
|
|
142
|
+
const nextIcon = computed(() => props.nextIcon || (dir.value === 'rtl' ? theme.value.app.icons.chevronLeft : theme.value.app.icons.chevronRight))
|
|
147
143
|
|
|
148
144
|
const options = computed<EmblaOptionsType>(() => ({
|
|
149
145
|
...(props.fade ? { align: 'center', containScroll: false } : {}),
|
|
150
146
|
...rootProps.value,
|
|
151
147
|
axis: props.orientation === 'horizontal' ? 'x' : 'y',
|
|
152
|
-
direction:
|
|
148
|
+
direction: dir.value === 'rtl' ? 'rtl' : 'ltr',
|
|
153
149
|
}))
|
|
154
150
|
|
|
155
151
|
const plugins = computedAsync<EmblaPluginType[]>(async () => {
|
|
@@ -261,7 +257,6 @@ defineExpose({
|
|
|
261
257
|
role="region"
|
|
262
258
|
aria-roledescription="carousel"
|
|
263
259
|
tabindex="0"
|
|
264
|
-
:dir="props.dir"
|
|
265
260
|
:class="style.root({ class: [props.class, props.ui?.root] })"
|
|
266
261
|
@keydown="onKeyDown"
|
|
267
262
|
>
|
|
@@ -5,7 +5,7 @@ import type { checkbox } from '../theme'
|
|
|
5
5
|
import type { ComponentAttrs } from '../types'
|
|
6
6
|
|
|
7
7
|
export interface CheckboxEmits {
|
|
8
|
-
|
|
8
|
+
change: [payload: Event]
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export interface CheckboxSlots {
|
|
@@ -41,6 +41,7 @@ export interface CheckboxProps extends ComponentAttrs<typeof checkbox>, Pick<Che
|
|
|
41
41
|
import { reactivePick } from '@vueuse/core'
|
|
42
42
|
import { CheckboxIndicator, CheckboxRoot, Label, Primitive, useForwardProps } from 'reka-ui'
|
|
43
43
|
import { computed, useId } from 'vue'
|
|
44
|
+
import { useFormItem } from '../composables/useFormItem'
|
|
44
45
|
import { useTheme } from '../composables/useTheme'
|
|
45
46
|
|
|
46
47
|
const props = withDefaults(defineProps<CheckboxProps>(), {
|
|
@@ -53,18 +54,22 @@ const slots = defineSlots<CheckboxSlots>()
|
|
|
53
54
|
const innerValue = defineModel<boolean | 'indeterminate'>({ default: undefined })
|
|
54
55
|
const rootProps = useForwardProps(reactivePick(props, 'required', 'value', 'defaultValue'))
|
|
55
56
|
|
|
56
|
-
const id
|
|
57
|
+
const { id: _id, size, name, disabled, ariaAttrs, emitFormChange, emitFormInput } = useFormItem<CheckboxProps>(props)
|
|
58
|
+
const id = _id.value ?? useId()
|
|
57
59
|
|
|
58
|
-
const { theme,
|
|
59
|
-
const style = computed(() => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
const { theme, generateStyle } = useTheme()
|
|
61
|
+
const style = computed(() => generateStyle('checkbox', {
|
|
62
|
+
...props,
|
|
63
|
+
size: size.value,
|
|
64
|
+
disabled: disabled.value,
|
|
65
|
+
}))
|
|
63
66
|
|
|
64
67
|
function onUpdate(value: any) {
|
|
65
68
|
// @ts-expect-error - 'target' does not exist in type 'EventInit'
|
|
66
69
|
const event = new Event('change', { target: value })
|
|
67
70
|
emit('change', event)
|
|
71
|
+
emitFormChange()
|
|
72
|
+
emitFormInput()
|
|
68
73
|
}
|
|
69
74
|
</script>
|
|
70
75
|
|
|
@@ -72,12 +77,9 @@ function onUpdate(value: any) {
|
|
|
72
77
|
<Primitive :as="props.as" :class="style.root({ class: [props.class, props.ui?.root] })">
|
|
73
78
|
<div :class="style.container({ class: props.ui?.container })">
|
|
74
79
|
<CheckboxRoot
|
|
75
|
-
:id="id"
|
|
76
|
-
v-bind="rootProps"
|
|
77
80
|
v-slot="{ modelValue }"
|
|
81
|
+
v-bind="{ ...rootProps, ...ariaAttrs, id, name, disabled }"
|
|
78
82
|
v-model="innerValue"
|
|
79
|
-
:name="props.name"
|
|
80
|
-
:disabled="props.disabled"
|
|
81
83
|
:class="style.base({ class: props.ui?.base })"
|
|
82
84
|
@update:model-value="onUpdate"
|
|
83
85
|
>
|
|
@@ -41,15 +41,12 @@ const slots = defineSlots<ChipSlots>()
|
|
|
41
41
|
const { size, orientation } = useButtonGroup(props)
|
|
42
42
|
const { isLeading, leadingIconName, isTrailing, trailingIconName } = useComponentIcons(props)
|
|
43
43
|
|
|
44
|
-
const {
|
|
45
|
-
const style = computed(() => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
groupOrientation: orientation.value,
|
|
51
|
-
})
|
|
52
|
-
})
|
|
44
|
+
const { generateStyle } = useTheme()
|
|
45
|
+
const style = computed(() => generateStyle('chip', {
|
|
46
|
+
...props,
|
|
47
|
+
size: size.value,
|
|
48
|
+
groupOrientation: orientation.value,
|
|
49
|
+
}))
|
|
53
50
|
</script>
|
|
54
51
|
|
|
55
52
|
<template>
|
|
@@ -28,11 +28,8 @@ const slots = defineSlots<CollapsibleSlots>()
|
|
|
28
28
|
|
|
29
29
|
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'defaultOpen', 'open', 'disabled', 'unmountOnHide'), emit)
|
|
30
30
|
|
|
31
|
-
const {
|
|
32
|
-
const style = computed(() =>
|
|
33
|
-
const styler = createStyler(theme.value.collapsible)
|
|
34
|
-
return styler(props)
|
|
35
|
-
})
|
|
31
|
+
const { generateStyle } = useTheme()
|
|
32
|
+
const style = computed(() => generateStyle('collapsible', props))
|
|
36
33
|
</script>
|
|
37
34
|
|
|
38
35
|
<template>
|
|
@@ -1,46 +1,59 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
2
|
+
import type { VariantProps } from '@byyuurin/ui-kit'
|
|
3
|
+
import type { DialogContentEmits, DialogContentProps, DialogRootEmits, DialogRootProps } from 'reka-ui'
|
|
4
4
|
import type { drawer } from '../theme'
|
|
5
|
-
import type { ComponentAttrs } from '../types'
|
|
5
|
+
import type { ButtonProps, ComponentAttrs, EmitsToProps } from '../types'
|
|
6
6
|
|
|
7
|
-
export interface DrawerEmits extends
|
|
7
|
+
export interface DrawerEmits extends DialogRootEmits {
|
|
8
|
+
'after-leave': []
|
|
9
|
+
}
|
|
8
10
|
|
|
9
11
|
export interface DrawerSlots {
|
|
10
|
-
default?:
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
body?:
|
|
17
|
-
footer?:
|
|
12
|
+
default?: any
|
|
13
|
+
content?: any
|
|
14
|
+
header?: any
|
|
15
|
+
title?: any
|
|
16
|
+
description?: any
|
|
17
|
+
close?: (props: { ui: ComponentAttrs<typeof drawer>['ui'] }) => any
|
|
18
|
+
body?: any
|
|
19
|
+
footer?: any
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
type DrawerVariants = VariantProps<typeof drawer>
|
|
23
|
+
|
|
24
|
+
export interface DrawerProps extends ComponentAttrs<typeof drawer>, DialogRootProps {
|
|
21
25
|
title?: string
|
|
22
26
|
description?: string
|
|
23
27
|
/** The content of the drawer. */
|
|
24
|
-
content?: Omit<DialogContentProps, 'as' | 'asChild' | 'forceMount'>
|
|
28
|
+
content?: Omit<DialogContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<DialogContentEmits>>
|
|
25
29
|
/**
|
|
26
30
|
* Render an overlay behind the drawer.
|
|
27
31
|
* @default true
|
|
28
32
|
*/
|
|
29
33
|
overlay?: boolean
|
|
34
|
+
/** @default true */
|
|
35
|
+
transition?: boolean
|
|
36
|
+
/**
|
|
37
|
+
* The direction of the drawer.
|
|
38
|
+
* @default "bottom"
|
|
39
|
+
*/
|
|
40
|
+
direction?: DrawerVariants['direction']
|
|
30
41
|
/**
|
|
31
42
|
* Whether to inset the drawer from the edges.
|
|
32
43
|
*/
|
|
33
44
|
inset?: boolean
|
|
34
45
|
/**
|
|
35
|
-
* Render
|
|
46
|
+
* Render the drawer in a portal.
|
|
36
47
|
* @default true
|
|
37
48
|
*/
|
|
38
|
-
|
|
49
|
+
portal?: boolean
|
|
39
50
|
/**
|
|
40
|
-
*
|
|
51
|
+
* Display a close button to dismiss the drawer.
|
|
41
52
|
* @default true
|
|
42
53
|
*/
|
|
43
|
-
|
|
54
|
+
close?: ButtonProps | boolean
|
|
55
|
+
/** @default app.icons.close */
|
|
56
|
+
closeIcon?: string
|
|
44
57
|
/**
|
|
45
58
|
* When `false`, the drawer will not close when clicking outside or pressing escape.
|
|
46
59
|
* @default true
|
|
@@ -51,71 +64,101 @@ export interface DrawerProps extends ComponentAttrs<typeof drawer>, Pick<DrawerR
|
|
|
51
64
|
|
|
52
65
|
<script setup lang="ts">
|
|
53
66
|
import { reactivePick } from '@vueuse/core'
|
|
54
|
-
import { useForwardPropsEmits } from 'reka-ui'
|
|
55
|
-
import { DrawerContent, DrawerDescription, DrawerOverlay, DrawerPortal, DrawerRoot, DrawerTitle, DrawerTrigger } from 'vaul-vue'
|
|
67
|
+
import { DialogClose, DialogContent, DialogDescription, DialogOverlay, DialogPortal, DialogRoot, DialogTitle, DialogTrigger, useForwardPropsEmits, VisuallyHidden } from 'reka-ui'
|
|
56
68
|
import { computed, toRef } from 'vue'
|
|
69
|
+
import { useLocale } from '../composables/useLocale'
|
|
57
70
|
import { useTheme } from '../composables/useTheme'
|
|
71
|
+
import Button from './Button.vue'
|
|
58
72
|
|
|
59
73
|
const props = withDefaults(defineProps<DrawerProps>(), {
|
|
60
74
|
direction: 'bottom',
|
|
75
|
+
modal: true,
|
|
61
76
|
portal: true,
|
|
62
77
|
overlay: true,
|
|
63
|
-
|
|
78
|
+
transition: true,
|
|
79
|
+
dismissible: true,
|
|
80
|
+
close: true,
|
|
64
81
|
})
|
|
65
82
|
const emit = defineEmits<DrawerEmits>()
|
|
66
83
|
const slots = defineSlots<DrawerSlots>()
|
|
67
84
|
|
|
68
|
-
const rootProps = useForwardPropsEmits(reactivePick(props, '
|
|
69
|
-
const contentProps = toRef(() =>
|
|
85
|
+
const rootProps = useForwardPropsEmits(reactivePick(props, 'open', 'defaultOpen', 'modal'), emit)
|
|
86
|
+
const contentProps = toRef(() => ({
|
|
87
|
+
...props.content,
|
|
88
|
+
...(slots.content || slots.header || (!props.description && !slots.description)) ? { 'aria-describedby': undefined } : {},
|
|
89
|
+
}))
|
|
90
|
+
const contentEvents = computed(() => {
|
|
91
|
+
if (props.dismissible)
|
|
92
|
+
return {}
|
|
70
93
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
94
|
+
return {
|
|
95
|
+
pointerDownOutside: (e: Event) => e.preventDefault(),
|
|
96
|
+
interactOutside: (e: Event) => e.preventDefault(),
|
|
97
|
+
escapeKeyDown: (e: Event) => e.preventDefault(),
|
|
98
|
+
}
|
|
75
99
|
})
|
|
100
|
+
|
|
101
|
+
const { t } = useLocale()
|
|
102
|
+
const { theme, generateStyle } = useTheme()
|
|
103
|
+
const style = computed(() => generateStyle('drawer', props))
|
|
76
104
|
</script>
|
|
77
105
|
|
|
78
106
|
<template>
|
|
79
|
-
<
|
|
80
|
-
<
|
|
81
|
-
<slot></slot>
|
|
82
|
-
</
|
|
107
|
+
<DialogRoot v-slot="{ open }" v-bind="rootProps">
|
|
108
|
+
<DialogTrigger v-if="slots.default" as-child :class="props.class">
|
|
109
|
+
<slot :open="open"></slot>
|
|
110
|
+
</DialogTrigger>
|
|
83
111
|
|
|
84
|
-
<
|
|
85
|
-
<
|
|
112
|
+
<DialogPortal :disabled="!props.portal">
|
|
113
|
+
<DialogOverlay v-if="props.overlay" :class="style.overlay({ class: props.ui?.overlay })" />
|
|
86
114
|
|
|
87
|
-
<
|
|
115
|
+
<DialogContent
|
|
88
116
|
:class="style.content({ class: [!slots.default && props.class, props.ui?.content] })"
|
|
117
|
+
:data-direction="props.direction"
|
|
89
118
|
v-bind="contentProps"
|
|
119
|
+
v-on="contentEvents"
|
|
120
|
+
@after-leave="emit('after-leave')"
|
|
90
121
|
>
|
|
91
|
-
<
|
|
92
|
-
<
|
|
93
|
-
</
|
|
122
|
+
<VisuallyHidden v-if="slots.content || slots.header || (!props.title && !slots.title)">
|
|
123
|
+
<DialogTitle />
|
|
124
|
+
</VisuallyHidden>
|
|
94
125
|
|
|
95
126
|
<slot name="content">
|
|
96
127
|
<div :class="style.container({ class: props.ui?.container })">
|
|
97
128
|
<div
|
|
98
|
-
v-if="slots.header || props.title || slots.title || props.description || slots.description"
|
|
129
|
+
v-if="slots.header || props.title || slots.title || props.description || slots.description || props.close || slots.close"
|
|
99
130
|
:class="style.header({ class: props.ui?.header })"
|
|
100
131
|
>
|
|
101
132
|
<slot name="header">
|
|
102
|
-
<
|
|
133
|
+
<DialogTitle
|
|
103
134
|
v-if="props.title || slots.title"
|
|
104
135
|
:class="style.title({ class: props.ui?.title })"
|
|
105
136
|
>
|
|
106
137
|
<slot name="title">
|
|
107
138
|
{{ props.title }}
|
|
108
139
|
</slot>
|
|
109
|
-
</
|
|
140
|
+
</DialogTitle>
|
|
141
|
+
|
|
142
|
+
<DialogClose v-if="props.close || slots.close" as-child>
|
|
143
|
+
<slot name="close" :ui="props.ui">
|
|
144
|
+
<Button
|
|
145
|
+
variant="ghost"
|
|
146
|
+
:icon="props.closeIcon || theme.app.icons.close"
|
|
147
|
+
v-bind="typeof props.close === 'boolean' ? {} : props.close"
|
|
148
|
+
:class="style.close({ class: props.ui?.close })"
|
|
149
|
+
:aria-label="t('modal.close')"
|
|
150
|
+
/>
|
|
151
|
+
</slot>
|
|
152
|
+
</DialogClose>
|
|
110
153
|
|
|
111
|
-
<
|
|
154
|
+
<DialogDescription
|
|
112
155
|
v-if="props.description || slots.description"
|
|
113
156
|
:class="style.description({ class: props.ui?.description })"
|
|
114
157
|
>
|
|
115
158
|
<slot name="description">
|
|
116
159
|
{{ props.description }}
|
|
117
160
|
</slot>
|
|
118
|
-
</
|
|
161
|
+
</DialogDescription>
|
|
119
162
|
</slot>
|
|
120
163
|
</div>
|
|
121
164
|
|
|
@@ -128,7 +171,7 @@ const style = computed(() => {
|
|
|
128
171
|
</div>
|
|
129
172
|
</div>
|
|
130
173
|
</slot>
|
|
131
|
-
</
|
|
132
|
-
</
|
|
133
|
-
</
|
|
174
|
+
</DialogContent>
|
|
175
|
+
</DialogPortal>
|
|
176
|
+
</DialogRoot>
|
|
134
177
|
</template>
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { VariantProps } from '@byyuurin/ui-kit'
|
|
3
|
+
import type { DropdownMenuArrowProps, DropdownMenuContentEmits, DropdownMenuContentProps, DropdownMenuRootEmits, DropdownMenuRootProps } from 'reka-ui'
|
|
4
|
+
import type { dropdownMenu } from '../theme'
|
|
5
|
+
import type { ArrayOrNested, AvatarProps, ComponentAttrs, DynamicSlots, EmitsToProps, KbdProps, LinkProps, MergeTypes, NestedItem } from '../types'
|
|
6
|
+
|
|
7
|
+
export interface DropdownMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'custom' | 'underline'> {
|
|
8
|
+
icon?: string
|
|
9
|
+
avatar?: AvatarProps
|
|
10
|
+
content?: Omit<DropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<DropdownMenuContentEmits>>
|
|
11
|
+
kbds?: Array<string | KbdProps['value']>
|
|
12
|
+
/**
|
|
13
|
+
* The item type.
|
|
14
|
+
* @default 'link'
|
|
15
|
+
*/
|
|
16
|
+
type?: 'label' | 'separator' | 'link' | 'checkbox'
|
|
17
|
+
slot?: string
|
|
18
|
+
loading?: boolean
|
|
19
|
+
disabled?: boolean
|
|
20
|
+
checked?: boolean
|
|
21
|
+
open?: boolean
|
|
22
|
+
defaultOpen?: boolean
|
|
23
|
+
children?: ArrayOrNested<DropdownMenuItem>
|
|
24
|
+
onSelect?: (e: Event) => void
|
|
25
|
+
onUpdateChecked?: (checked: boolean) => void
|
|
26
|
+
[key: string]: any
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type SlotProps<T extends DropdownMenuItem> = (props: { item: T, active?: boolean, index: number }) => any
|
|
30
|
+
|
|
31
|
+
export type DropdownMenuSlots<
|
|
32
|
+
T extends ArrayOrNested<DropdownMenuItem> = ArrayOrNested<DropdownMenuItem>,
|
|
33
|
+
I extends NestedItem<T> = NestedItem<T>,
|
|
34
|
+
> = {
|
|
35
|
+
'default'?: (props: { open: boolean }) => any
|
|
36
|
+
'item'?: SlotProps<I>
|
|
37
|
+
'item-leading'?: SlotProps<I>
|
|
38
|
+
'item-label'?: SlotProps<I>
|
|
39
|
+
'item-trailing'?: SlotProps<I>
|
|
40
|
+
} & DynamicSlots<MergeTypes<I>, 'leading' | 'label' | 'trailing', SlotProps<I>>
|
|
41
|
+
|
|
42
|
+
export interface DropdownMenuEmits extends DropdownMenuRootEmits {}
|
|
43
|
+
|
|
44
|
+
type DropdownMenuVariants = VariantProps<typeof dropdownMenu>
|
|
45
|
+
|
|
46
|
+
export interface DropdownMenuProps<
|
|
47
|
+
T extends ArrayOrNested<DropdownMenuItem> = ArrayOrNested<DropdownMenuItem>,
|
|
48
|
+
> extends ComponentAttrs<typeof dropdownMenu>, Omit<DropdownMenuRootProps, 'dir'> {
|
|
49
|
+
/** @default "md" */
|
|
50
|
+
size?: DropdownMenuVariants['size']
|
|
51
|
+
items?: T
|
|
52
|
+
/**
|
|
53
|
+
* The icon displayed when an item is checked.
|
|
54
|
+
* @default app.icons.check
|
|
55
|
+
*/
|
|
56
|
+
checkedIcon?: string
|
|
57
|
+
/**
|
|
58
|
+
* The icon displayed when an item is loading.
|
|
59
|
+
* @default app.icons.loading
|
|
60
|
+
*/
|
|
61
|
+
loadingIcon?: string
|
|
62
|
+
/**
|
|
63
|
+
* The icon displayed when the item is an external link.
|
|
64
|
+
* Set to `false` to hide the external icon.
|
|
65
|
+
* @default app.icons.external
|
|
66
|
+
*/
|
|
67
|
+
externalIcon?: boolean | string
|
|
68
|
+
/**
|
|
69
|
+
* The content of the menu.
|
|
70
|
+
* @default { side: 'bottom', sideOffset: 8, collisionPadding: 8 }
|
|
71
|
+
*/
|
|
72
|
+
content?: Omit<DropdownMenuContentProps, 'as' | 'asChild' | 'forceMount'> & Partial<EmitsToProps<DropdownMenuContentEmits>>
|
|
73
|
+
/**
|
|
74
|
+
* Display an arrow alongside the menu.
|
|
75
|
+
* @default false
|
|
76
|
+
*/
|
|
77
|
+
arrow?: boolean | Omit<DropdownMenuArrowProps, 'as' | 'asChild'>
|
|
78
|
+
/**
|
|
79
|
+
* Render the menu in a portal.
|
|
80
|
+
* @default true
|
|
81
|
+
*/
|
|
82
|
+
portal?: boolean
|
|
83
|
+
/**
|
|
84
|
+
* The key used to get the label from the item.
|
|
85
|
+
* @default "label"
|
|
86
|
+
*/
|
|
87
|
+
labelKey?: keyof NestedItem<T>
|
|
88
|
+
disabled?: boolean
|
|
89
|
+
}
|
|
90
|
+
</script>
|
|
91
|
+
|
|
92
|
+
<script setup lang="ts" generic="T extends ArrayOrNested<DropdownMenuItem>">
|
|
93
|
+
import { reactivePick } from '@vueuse/core'
|
|
94
|
+
import { DropdownMenuArrow, DropdownMenuRoot, DropdownMenuTrigger, useForwardPropsEmits } from 'reka-ui'
|
|
95
|
+
import { computed, toRef } from 'vue'
|
|
96
|
+
import { useTheme } from '../composables/useTheme'
|
|
97
|
+
import { omit } from '../utils'
|
|
98
|
+
import DropdownMenuContent from './DropdownMenuContent.vue'
|
|
99
|
+
|
|
100
|
+
const props = withDefaults(defineProps<DropdownMenuProps<T>>(), {
|
|
101
|
+
portal: true,
|
|
102
|
+
modal: true,
|
|
103
|
+
externalIcon: true,
|
|
104
|
+
labelKey: 'label',
|
|
105
|
+
})
|
|
106
|
+
const emit = defineEmits<DropdownMenuEmits>()
|
|
107
|
+
const slots = defineSlots<DropdownMenuSlots<T>>()
|
|
108
|
+
|
|
109
|
+
const rootProps = useForwardPropsEmits(reactivePick(props, 'defaultOpen', 'open', 'modal'), emit)
|
|
110
|
+
const contentProps = toRef(() => ({ side: 'bottom', sideOffset: 8, collisionPadding: 8, ...props.content }) as DropdownMenuContentProps)
|
|
111
|
+
const arrowProps = toRef(() => props.arrow as DropdownMenuArrowProps)
|
|
112
|
+
const proxySlots = omit(slots, ['default'])
|
|
113
|
+
|
|
114
|
+
const { generateStyle } = useTheme()
|
|
115
|
+
const style = computed(() => generateStyle('dropdownMenu', props))
|
|
116
|
+
</script>
|
|
117
|
+
|
|
118
|
+
<template>
|
|
119
|
+
<DropdownMenuRoot v-slot="{ open }" v-bind="rootProps">
|
|
120
|
+
<DropdownMenuTrigger v-if="slots.default" as-child :class="props.class" :disabled="props.disabled">
|
|
121
|
+
<slot :open="open"></slot>
|
|
122
|
+
</DropdownMenuTrigger>
|
|
123
|
+
|
|
124
|
+
<DropdownMenuContent
|
|
125
|
+
:class="style.content({ class: [!slots.default && props.class, props.ui?.content] })"
|
|
126
|
+
:ui="props.ui"
|
|
127
|
+
v-bind="contentProps"
|
|
128
|
+
:size="props.size"
|
|
129
|
+
:items="props.items"
|
|
130
|
+
:portal="props.portal"
|
|
131
|
+
:label-key="(props.labelKey as keyof NestedItem<T>)"
|
|
132
|
+
:checked-icon="props.checkedIcon"
|
|
133
|
+
:loading-icon="props.loadingIcon"
|
|
134
|
+
:external-icon="props.externalIcon"
|
|
135
|
+
>
|
|
136
|
+
<template v-for="(_, name) in proxySlots" #[name]="slotProps">
|
|
137
|
+
<slot :name="(name as keyof DropdownMenuSlots<T>)" v-bind="slotProps"></slot>
|
|
138
|
+
</template>
|
|
139
|
+
|
|
140
|
+
<DropdownMenuArrow v-if="props.arrow" v-bind="arrowProps" :class="style.arrow({ class: props.ui?.arrow })" />
|
|
141
|
+
</DropdownMenuContent>
|
|
142
|
+
</DropdownMenuRoot>
|
|
143
|
+
</template>
|