@personizely/ui 0.0.42
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/LICENSE.md +21 -0
- package/README.md +1 -0
- package/dist/personizely-ui.css +6 -0
- package/dist/personizely-ui.js +26854 -0
- package/dist/personizely-ui.umd.cjs +111 -0
- package/package.json +117 -0
- package/src/assets/index.css +136 -0
- package/src/components/ui/accordion/Accordion.vue +19 -0
- package/src/components/ui/accordion/AccordionContent.vue +24 -0
- package/src/components/ui/accordion/AccordionItem.vue +37 -0
- package/src/components/ui/accordion/AccordionTrigger.vue +39 -0
- package/src/components/ui/accordion/index.ts +2 -0
- package/src/components/ui/alert/Alert.vue +68 -0
- package/src/components/ui/alert/index.ts +22 -0
- package/src/components/ui/alert-dialog/AlertDialog.vue +66 -0
- package/src/components/ui/alert-dialog/AlertDialogContent.vue +44 -0
- package/src/components/ui/alert-dialog/AlertDialogProvider.vue +27 -0
- package/src/components/ui/alert-dialog/AlertDialogTrigger.vue +11 -0
- package/src/components/ui/alert-dialog/index.ts +3 -0
- package/src/components/ui/alert-dialog/useAlertDialog.ts +19 -0
- package/src/components/ui/autocomplete/Autocomplete.vue +170 -0
- package/src/components/ui/autocomplete/AutocompleteContent.vue +27 -0
- package/src/components/ui/autocomplete/AutocompleteEmpty.vue +20 -0
- package/src/components/ui/autocomplete/AutocompleteGroup.vue +29 -0
- package/src/components/ui/autocomplete/AutocompleteItem.vue +26 -0
- package/src/components/ui/autocomplete/AutocompleteRoot.vue +31 -0
- package/src/components/ui/autocomplete/AutocompleteSeparator.vue +23 -0
- package/src/components/ui/autocomplete/index.ts +1 -0
- package/src/components/ui/avatar/Avatar.vue +31 -0
- package/src/components/ui/avatar/AvatarFallback.vue +11 -0
- package/src/components/ui/avatar/AvatarImage.vue +9 -0
- package/src/components/ui/avatar/index.ts +19 -0
- package/src/components/ui/badge/Badge.vue +16 -0
- package/src/components/ui/badge/index.ts +22 -0
- package/src/components/ui/button/Button.vue +123 -0
- package/src/components/ui/button/index.ts +78 -0
- package/src/components/ui/calendar/Calendar.vue +76 -0
- package/src/components/ui/calendar/CalendarCell.vue +24 -0
- package/src/components/ui/calendar/CalendarCellTrigger.vue +38 -0
- package/src/components/ui/calendar/CalendarGrid.vue +24 -0
- package/src/components/ui/calendar/CalendarGridBody.vue +11 -0
- package/src/components/ui/calendar/CalendarGridHead.vue +11 -0
- package/src/components/ui/calendar/CalendarGridRow.vue +21 -0
- package/src/components/ui/calendar/CalendarHeadCell.vue +21 -0
- package/src/components/ui/calendar/CalendarHeader.vue +21 -0
- package/src/components/ui/calendar/CalendarHeading.vue +27 -0
- package/src/components/ui/calendar/CalendarNextButton.vue +32 -0
- package/src/components/ui/calendar/CalendarPrevButton.vue +32 -0
- package/src/components/ui/calendar/index.ts +1 -0
- package/src/components/ui/card/Card.vue +57 -0
- package/src/components/ui/card/CardContent.vue +14 -0
- package/src/components/ui/card/CardDescription.vue +14 -0
- package/src/components/ui/card/CardFooter.vue +14 -0
- package/src/components/ui/card/CardHeader.vue +14 -0
- package/src/components/ui/card/CardTitle.vue +18 -0
- package/src/components/ui/card/CardTray.vue +14 -0
- package/src/components/ui/card/index.ts +1 -0
- package/src/components/ui/checkbox/Checkbox.vue +63 -0
- package/src/components/ui/checkbox/CheckboxBase.vue +39 -0
- package/src/components/ui/checkbox/index.ts +1 -0
- package/src/components/ui/checkbox-group/CheckboxGroup.vue +65 -0
- package/src/components/ui/checkbox-group/index.ts +15 -0
- package/src/components/ui/color-picker/Alpha.vue +63 -0
- package/src/components/ui/color-picker/Angle.vue +145 -0
- package/src/components/ui/color-picker/Checkboard.vue +43 -0
- package/src/components/ui/color-picker/Color.vue +255 -0
- package/src/components/ui/color-picker/ColorPicker.vue +25 -0
- package/src/components/ui/color-picker/Gradient.vue +172 -0
- package/src/components/ui/color-picker/Handle.vue +19 -0
- package/src/components/ui/color-picker/Hue.vue +80 -0
- package/src/components/ui/color-picker/LabelInput.vue +16 -0
- package/src/components/ui/color-picker/Rail.vue +100 -0
- package/src/components/ui/color-picker/Saturation.vue +142 -0
- package/src/components/ui/color-picker/index.ts +4 -0
- package/src/components/ui/combobox/Combobox.vue +202 -0
- package/src/components/ui/combobox/ComboboxContent.vue +27 -0
- package/src/components/ui/combobox/ComboboxEmpty.vue +20 -0
- package/src/components/ui/combobox/ComboboxGroup.vue +29 -0
- package/src/components/ui/combobox/ComboboxInput.vue +52 -0
- package/src/components/ui/combobox/ComboboxItem.vue +26 -0
- package/src/components/ui/combobox/ComboboxRoot.vue +31 -0
- package/src/components/ui/combobox/ComboboxSeparator.vue +23 -0
- package/src/components/ui/combobox/index.ts +1 -0
- package/src/components/ui/date-picker/DatePicker.vue +55 -0
- package/src/components/ui/date-picker/index.ts +1 -0
- package/src/components/ui/date-range-picker/DateRangePicker.vue +137 -0
- package/src/components/ui/date-range-picker/index.ts +1 -0
- package/src/components/ui/dialog/Dialog.vue +78 -0
- package/src/components/ui/dialog/DialogContent.vue +46 -0
- package/src/components/ui/dialog/DialogDescription.vue +24 -0
- package/src/components/ui/dialog/DialogFooter.vue +19 -0
- package/src/components/ui/dialog/DialogHeader.vue +16 -0
- package/src/components/ui/dialog/DialogTitle.vue +29 -0
- package/src/components/ui/dialog/DialogTrigger.vue +11 -0
- package/src/components/ui/dialog/index.ts +1 -0
- package/src/components/ui/drawer/Drawer.vue +88 -0
- package/src/components/ui/drawer/DrawerContent.vue +57 -0
- package/src/components/ui/drawer/DrawerDescription.vue +22 -0
- package/src/components/ui/drawer/DrawerFooter.vue +19 -0
- package/src/components/ui/drawer/DrawerHeader.vue +16 -0
- package/src/components/ui/drawer/DrawerTitle.vue +22 -0
- package/src/components/ui/drawer/DrawerTrigger.vue +11 -0
- package/src/components/ui/drawer/index.ts +21 -0
- package/src/components/ui/dropdown-menu/DropdownCheckboxGroupMenu.vue +87 -0
- package/src/components/ui/dropdown-menu/DropdownMenu.vue +72 -0
- package/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +40 -0
- package/src/components/ui/dropdown-menu/DropdownMenuContent.vue +37 -0
- package/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +11 -0
- package/src/components/ui/dropdown-menu/DropdownMenuHelp.vue +14 -0
- package/src/components/ui/dropdown-menu/DropdownMenuItem.vue +28 -0
- package/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +24 -0
- package/src/components/ui/dropdown-menu/DropdownMenuPart.vue +64 -0
- package/src/components/ui/dropdown-menu/DropdownMenuPartItem.vue +76 -0
- package/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +19 -0
- package/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +41 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +22 -0
- package/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +14 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSub.vue +19 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +30 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +33 -0
- package/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +13 -0
- package/src/components/ui/dropdown-menu/DropdownRadioGroupMenu.vue +75 -0
- package/src/components/ui/dropdown-menu/index.ts +36 -0
- package/src/components/ui/file-upload-button/FileUploadButton.vue +55 -0
- package/src/components/ui/file-upload-button/index.ts +1 -0
- package/src/components/ui/form/Form.vue +13 -0
- package/src/components/ui/form/FormControl.vue +16 -0
- package/src/components/ui/form/FormDescription.vue +20 -0
- package/src/components/ui/form/FormField.vue +61 -0
- package/src/components/ui/form/FormLabel.vue +23 -0
- package/src/components/ui/form/FormMessage.vue +16 -0
- package/src/components/ui/form/index.ts +2 -0
- package/src/components/ui/form/useFormField.ts +30 -0
- package/src/components/ui/icon/Icon.vue +16 -0
- package/src/components/ui/icon/index.ts +1 -0
- package/src/components/ui/input/Input.vue +51 -0
- package/src/components/ui/input/InputBase.vue +18 -0
- package/src/components/ui/input/index.ts +1 -0
- package/src/components/ui/label/Label.vue +27 -0
- package/src/components/ui/label/index.ts +1 -0
- package/src/components/ui/pagination/Pagination.vue +50 -0
- package/src/components/ui/pagination/PaginationContent.vue +21 -0
- package/src/components/ui/pagination/PaginationEllipsis.vue +24 -0
- package/src/components/ui/pagination/PaginationFirst.vue +32 -0
- package/src/components/ui/pagination/PaginationItem.vue +32 -0
- package/src/components/ui/pagination/PaginationLast.vue +32 -0
- package/src/components/ui/pagination/PaginationNext.vue +32 -0
- package/src/components/ui/pagination/PaginationPrevious.vue +32 -0
- package/src/components/ui/pagination/index.ts +1 -0
- package/src/components/ui/popover/Popover.vue +57 -0
- package/src/components/ui/popover/PopoverTrigger.vue +15 -0
- package/src/components/ui/popover/index.ts +1 -0
- package/src/components/ui/progress/Progress.vue +35 -0
- package/src/components/ui/progress/ProgressIndicator.vue +19 -0
- package/src/components/ui/progress/index.ts +2 -0
- package/src/components/ui/progress-circular/ProgressCircular.vue +85 -0
- package/src/components/ui/progress-circular/index.ts +1 -0
- package/src/components/ui/radio-group/RadioGroup.vue +81 -0
- package/src/components/ui/radio-group/RadioGroupItem.vue +39 -0
- package/src/components/ui/radio-group/index.ts +15 -0
- package/src/components/ui/range-calendar/RangeCalendar.vue +71 -0
- package/src/components/ui/range-calendar/RangeCalendarCell.vue +28 -0
- package/src/components/ui/range-calendar/RangeCalendarCellTrigger.vue +40 -0
- package/src/components/ui/range-calendar/RangeCalendarGrid.vue +24 -0
- package/src/components/ui/range-calendar/RangeCalendarGridBody.vue +11 -0
- package/src/components/ui/range-calendar/RangeCalendarGridHead.vue +11 -0
- package/src/components/ui/range-calendar/RangeCalendarGridRow.vue +21 -0
- package/src/components/ui/range-calendar/RangeCalendarHeadCell.vue +21 -0
- package/src/components/ui/range-calendar/RangeCalendarHeader.vue +21 -0
- package/src/components/ui/range-calendar/RangeCalendarHeading.vue +27 -0
- package/src/components/ui/range-calendar/RangeCalendarNextButton.vue +32 -0
- package/src/components/ui/range-calendar/RangeCalendarPrevButton.vue +32 -0
- package/src/components/ui/range-calendar/index.ts +1 -0
- package/src/components/ui/select/Select.vue +120 -0
- package/src/components/ui/select/SelectContent.vue +45 -0
- package/src/components/ui/select/SelectGroup.vue +19 -0
- package/src/components/ui/select/SelectItem.vue +43 -0
- package/src/components/ui/select/SelectLabel.vue +13 -0
- package/src/components/ui/select/SelectSeparator.vue +17 -0
- package/src/components/ui/select/SelectTrigger.vue +31 -0
- package/src/components/ui/select/SelectValue.vue +11 -0
- package/src/components/ui/select/index.ts +1 -0
- package/src/components/ui/slider/Slider.vue +100 -0
- package/src/components/ui/slider/index.ts +1 -0
- package/src/components/ui/switch/Switch.vue +40 -0
- package/src/components/ui/switch/SwitchBase.vue +36 -0
- package/src/components/ui/switch/index.ts +1 -0
- package/src/components/ui/tabs/Tabs.vue +63 -0
- package/src/components/ui/tabs/TabsContent.vue +26 -0
- package/src/components/ui/tabs/TabsTrigger.vue +27 -0
- package/src/components/ui/tabs/index.ts +28 -0
- package/src/components/ui/textarea/Textarea.vue +13 -0
- package/src/components/ui/textarea/index.ts +1 -0
- package/src/components/ui/toast/Toast.vue +28 -0
- package/src/components/ui/toast/ToastAction.vue +26 -0
- package/src/components/ui/toast/ToastClose.vue +29 -0
- package/src/components/ui/toast/ToastDescription.vue +19 -0
- package/src/components/ui/toast/ToastProvider.vue +11 -0
- package/src/components/ui/toast/ToastTitle.vue +19 -0
- package/src/components/ui/toast/ToastViewport.vue +17 -0
- package/src/components/ui/toast/Toaster.vue +30 -0
- package/src/components/ui/toast/index.ts +34 -0
- package/src/components/ui/toast/useToast.ts +163 -0
- package/src/components/ui/toggle/Toggle.vue +51 -0
- package/src/components/ui/toggle/index.ts +71 -0
- package/src/components/ui/toggle-group/ToggleGroup.vue +58 -0
- package/src/components/ui/toggle-group/ToggleGroupItem.vue +54 -0
- package/src/components/ui/toggle-group/index.ts +1 -0
- package/src/components/ui/tooltip/Tooltip.vue +42 -0
- package/src/components/ui/tooltip/TooltipProvider.vue +11 -0
- package/src/components/ui/tooltip/index.ts +2 -0
- package/src/composables/delegated-props.ts +6 -0
- package/src/composables/emits-as-props.ts +17 -0
- package/src/composables/forward-props-emits.ts +11 -0
- package/src/directives/autofocus.ts +7 -0
- package/src/index.ts +159 -0
- package/src/options-provider.ts +19 -0
- package/src/utils/gradient.ts +158 -0
- package/src/utils/options.ts +40 -0
- package/src/utils/tailwind.ts +14 -0
- package/web-types.json +10560 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SelectRoot v-bind="forwarded"
|
|
3
|
+
v-model="modelValue"
|
|
4
|
+
@change.stop
|
|
5
|
+
>
|
|
6
|
+
<SelectTrigger :class="cn((multiple && Array.isArray(modelValue) && modelValue.length === 0) || !modelValue ? 'text-muted-foreground' : '', props.class)">
|
|
7
|
+
<SelectValue :placeholder="placeholder">
|
|
8
|
+
<slot v-if="multiple && Array.isArray(modelValue) && (modelValue.length || $slots.label)" name="label" v-bind="{ options: selectedOptions }">
|
|
9
|
+
{{ selectedOptionsLabel || modelValue!.length + ' selected' }}
|
|
10
|
+
</slot>
|
|
11
|
+
<slot v-else-if="!multiple && (modelValue || $slots.label)" name="label" v-bind="{ option: selectedOption }">
|
|
12
|
+
{{ selectedOptionLabel || modelValue }}
|
|
13
|
+
</slot>
|
|
14
|
+
</SelectValue>
|
|
15
|
+
</SelectTrigger>
|
|
16
|
+
<SelectPortal :disabled="disablePortal" :to="opts.portalTo">
|
|
17
|
+
<SelectContent :body-lock="false">
|
|
18
|
+
<SelectItem
|
|
19
|
+
v-for="(option, index) in preparedOptions"
|
|
20
|
+
:key="option[keys.id] || index"
|
|
21
|
+
:value="option[keys.value]"
|
|
22
|
+
:disabled="option[keys.disabled] || disabled"
|
|
23
|
+
>
|
|
24
|
+
<slot name="option" v-bind="{ option }">
|
|
25
|
+
{{ option[keys.label] || option }}
|
|
26
|
+
</slot>
|
|
27
|
+
</SelectItem>
|
|
28
|
+
</SelectContent>
|
|
29
|
+
</SelectPortal>
|
|
30
|
+
</SelectRoot>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script setup lang="ts">
|
|
34
|
+
import {
|
|
35
|
+
SelectRoot,
|
|
36
|
+
SelectPortal,
|
|
37
|
+
type SelectRootEmits,
|
|
38
|
+
type SelectRootProps
|
|
39
|
+
} from 'reka-ui'
|
|
40
|
+
import { computed, type HTMLAttributes } from 'vue'
|
|
41
|
+
import { type CustomOption, type Keys, type Option, prepareOptions } from '@/utils/options'
|
|
42
|
+
import SelectContent from './SelectContent.vue'
|
|
43
|
+
import SelectTrigger from './SelectTrigger.vue'
|
|
44
|
+
import SelectValue from './SelectValue.vue'
|
|
45
|
+
import SelectItem from './SelectItem.vue'
|
|
46
|
+
import { cn } from '@/utils/tailwind'
|
|
47
|
+
import { useDelegatedProps } from '@/composables/delegated-props'
|
|
48
|
+
import { useForwardPropsEmits } from '@/composables/forward-props-emits'
|
|
49
|
+
import { useEmitAsProps } from '@/composables/emits-as-props'
|
|
50
|
+
import { getOptions } from '@/options-provider'
|
|
51
|
+
|
|
52
|
+
const modelValue = defineModel<SelectRootProps['modelValue']>()
|
|
53
|
+
|
|
54
|
+
const props = withDefaults(defineProps<Omit<SelectRootProps, 'modelValue'> & {
|
|
55
|
+
class?: HTMLAttributes['class']
|
|
56
|
+
placeholder?: string
|
|
57
|
+
disablePortal?: boolean
|
|
58
|
+
keys?: Keys
|
|
59
|
+
options: string[] | Option[] | CustomOption[] | { [key:string]: string }
|
|
60
|
+
}>(), {
|
|
61
|
+
disablePortal: false,
|
|
62
|
+
placeholder: 'Select a value...',
|
|
63
|
+
keys: () => ({
|
|
64
|
+
id: 'id',
|
|
65
|
+
label: 'label',
|
|
66
|
+
help: 'help',
|
|
67
|
+
value: 'value',
|
|
68
|
+
disabled: 'disabled'
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
const emits = defineEmits<Omit<SelectRootEmits, 'update:modelValue'>>()
|
|
72
|
+
|
|
73
|
+
const delegatedProps = useDelegatedProps(props, ['class', 'placeholder', 'keys', 'options', 'disablePortal', 'modelValue'])
|
|
74
|
+
const delegatedEmits = useEmitAsProps(emits, ['update:modelValue'])
|
|
75
|
+
const forwarded = useForwardPropsEmits(delegatedProps, delegatedEmits)
|
|
76
|
+
const opts = getOptions()
|
|
77
|
+
|
|
78
|
+
defineSlots<{
|
|
79
|
+
'label'(props: { option: CustomOption | undefined | null } | { options: Array<Option | CustomOption> }): any
|
|
80
|
+
'option'(props: { option: Option | CustomOption }): any
|
|
81
|
+
}>()
|
|
82
|
+
|
|
83
|
+
const selectedOption = computed(() => {
|
|
84
|
+
if (modelValue.value) {
|
|
85
|
+
return preparedOptions.value.find((o) => {
|
|
86
|
+
return o[props.keys.value] === modelValue.value
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return null
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
const selectedOptions = computed(() => {
|
|
94
|
+
if (Array.isArray(modelValue.value)) {
|
|
95
|
+
return preparedOptions.value.filter((o) => {
|
|
96
|
+
return (<Array<unknown>>modelValue.value).includes(o[props.keys.value])
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return []
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
const selectedOptionLabel = computed(() => {
|
|
104
|
+
if (selectedOption.value) {
|
|
105
|
+
return selectedOption.value[props.keys.label]
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return null
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
const selectedOptionsLabel = computed(() => {
|
|
112
|
+
if (selectedOptions.value) {
|
|
113
|
+
return selectedOptions.value.map(o => o[props.keys.label]).join(', ')
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return null
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
const preparedOptions = computed(() => prepareOptions(props.options, props.keys))
|
|
120
|
+
</script>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SelectContent
|
|
3
|
+
v-bind="{ ...forwarded, ...$attrs }"
|
|
4
|
+
:class="cn(
|
|
5
|
+
'relative z-50 max-h-96 min-w-32 overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
|
6
|
+
position === 'popper'
|
|
7
|
+
&& 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
|
|
8
|
+
props.class,
|
|
9
|
+
)
|
|
10
|
+
"
|
|
11
|
+
>
|
|
12
|
+
<SelectViewport :class="cn('p-1', position === 'popper' && 'h-(--reka-select-trigger-height) w-full min-w-(--reka-select-trigger-width)')">
|
|
13
|
+
<slot />
|
|
14
|
+
</SelectViewport>
|
|
15
|
+
</SelectContent>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script setup lang="ts">
|
|
19
|
+
import { type HTMLAttributes, computed } from 'vue'
|
|
20
|
+
import {
|
|
21
|
+
SelectContent,
|
|
22
|
+
type SelectContentEmits,
|
|
23
|
+
type SelectContentProps,
|
|
24
|
+
SelectViewport,
|
|
25
|
+
useForwardPropsEmits
|
|
26
|
+
} from 'reka-ui'
|
|
27
|
+
import { cn } from '@/utils/tailwind'
|
|
28
|
+
|
|
29
|
+
defineOptions({
|
|
30
|
+
inheritAttrs: false
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const props = withDefaults(defineProps<SelectContentProps & { class?: HTMLAttributes['class'] }>(), {
|
|
34
|
+
position: 'popper'
|
|
35
|
+
})
|
|
36
|
+
const emits = defineEmits<SelectContentEmits>()
|
|
37
|
+
|
|
38
|
+
const delegatedProps = computed(() => {
|
|
39
|
+
const { class: _, ...delegated } = props
|
|
40
|
+
|
|
41
|
+
return delegated
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
|
45
|
+
</script>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SelectGroup :class="cn('p-1 w-full', props.class)" v-bind="delegatedProps">
|
|
3
|
+
<slot />
|
|
4
|
+
</SelectGroup>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts">
|
|
8
|
+
import { type HTMLAttributes, computed } from 'vue'
|
|
9
|
+
import { SelectGroup, type SelectGroupProps } from 'reka-ui'
|
|
10
|
+
import { cn } from '@/utils/tailwind'
|
|
11
|
+
|
|
12
|
+
const props = defineProps<SelectGroupProps & { class?: HTMLAttributes['class'] }>()
|
|
13
|
+
|
|
14
|
+
const delegatedProps = computed(() => {
|
|
15
|
+
const { class: _, ...delegated } = props
|
|
16
|
+
|
|
17
|
+
return delegated
|
|
18
|
+
})
|
|
19
|
+
</script>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SelectItem
|
|
3
|
+
v-bind="forwardedProps"
|
|
4
|
+
:class="
|
|
5
|
+
cn(
|
|
6
|
+
'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 aria-selected:font-medium',
|
|
7
|
+
props.class,
|
|
8
|
+
)
|
|
9
|
+
"
|
|
10
|
+
>
|
|
11
|
+
<SelectItemText>
|
|
12
|
+
<slot />
|
|
13
|
+
</SelectItemText>
|
|
14
|
+
<SelectItemIndicator as-child>
|
|
15
|
+
<span class="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
16
|
+
<Check class="h-4 w-4" />
|
|
17
|
+
</span>
|
|
18
|
+
</SelectItemIndicator>
|
|
19
|
+
</SelectItem>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script setup lang="ts">
|
|
23
|
+
import { type HTMLAttributes, computed } from 'vue'
|
|
24
|
+
import {
|
|
25
|
+
SelectItem,
|
|
26
|
+
SelectItemIndicator,
|
|
27
|
+
SelectItemText,
|
|
28
|
+
useForwardProps,
|
|
29
|
+
type SelectItemProps
|
|
30
|
+
} from 'reka-ui'
|
|
31
|
+
import { Check } from 'lucide-vue-next'
|
|
32
|
+
import { cn } from '@/utils/tailwind'
|
|
33
|
+
|
|
34
|
+
const props = defineProps<SelectItemProps & { class?: HTMLAttributes['class'] }>()
|
|
35
|
+
|
|
36
|
+
const delegatedProps = computed(() => {
|
|
37
|
+
const { class: _, ...delegated } = props
|
|
38
|
+
|
|
39
|
+
return delegated
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const forwardedProps = useForwardProps(delegatedProps)
|
|
43
|
+
</script>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SelectLabel :class="cn('py-1.5 pl-2 pr-8 text-sm font-medium', props.class)">
|
|
3
|
+
<slot />
|
|
4
|
+
</SelectLabel>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts">
|
|
8
|
+
import type { HTMLAttributes } from 'vue'
|
|
9
|
+
import { SelectLabel, type SelectLabelProps } from 'reka-ui'
|
|
10
|
+
import { cn } from '@/utils/tailwind'
|
|
11
|
+
|
|
12
|
+
const props = defineProps<SelectLabelProps & { class?: HTMLAttributes['class'] }>()
|
|
13
|
+
</script>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SelectSeparator v-bind="delegatedProps" :class="cn('-mx-1 my-1 h-px bg-muted', props.class)" />
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script setup lang="ts">
|
|
6
|
+
import { type HTMLAttributes, computed } from 'vue'
|
|
7
|
+
import { SelectSeparator, type SelectSeparatorProps } from 'reka-ui'
|
|
8
|
+
import { cn } from '@/utils/tailwind'
|
|
9
|
+
|
|
10
|
+
const props = defineProps<SelectSeparatorProps & { class?: HTMLAttributes['class'] }>()
|
|
11
|
+
|
|
12
|
+
const delegatedProps = computed(() => {
|
|
13
|
+
const { class: _, ...delegated } = props
|
|
14
|
+
|
|
15
|
+
return delegated
|
|
16
|
+
})
|
|
17
|
+
</script>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SelectTrigger
|
|
3
|
+
v-bind="forwardedProps"
|
|
4
|
+
:class="cn(
|
|
5
|
+
'flex gap-1.5 text-left h-8 w-full items-center justify-between rounded-md border border-input bg-background px-2 py-1 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1 [&>span]:break-all',
|
|
6
|
+
props.class,
|
|
7
|
+
)"
|
|
8
|
+
>
|
|
9
|
+
<slot />
|
|
10
|
+
<SelectIcon as-child>
|
|
11
|
+
<ChevronDown class="w-4 h-4 min-w-4 opacity-50" />
|
|
12
|
+
</SelectIcon>
|
|
13
|
+
</SelectTrigger>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script setup lang="ts">
|
|
17
|
+
import { type HTMLAttributes, computed } from 'vue'
|
|
18
|
+
import { SelectIcon, SelectTrigger, type SelectTriggerProps, useForwardProps } from 'reka-ui'
|
|
19
|
+
import { ChevronDown } from 'lucide-vue-next'
|
|
20
|
+
import { cn } from '@/utils/tailwind'
|
|
21
|
+
|
|
22
|
+
const props = defineProps<SelectTriggerProps & { class?: HTMLAttributes['class'] }>()
|
|
23
|
+
|
|
24
|
+
const delegatedProps = computed(() => {
|
|
25
|
+
const { class: _, ...delegated } = props
|
|
26
|
+
|
|
27
|
+
return delegated
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const forwardedProps = useForwardProps(delegatedProps)
|
|
31
|
+
</script>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SelectValue v-bind="props">
|
|
3
|
+
<slot v-if="$slots.default" />
|
|
4
|
+
</SelectValue>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts">
|
|
8
|
+
import { SelectValue, type SelectValueProps } from 'reka-ui'
|
|
9
|
+
|
|
10
|
+
const props = defineProps<SelectValueProps>()
|
|
11
|
+
</script>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Select } from './Select.vue'
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SliderRoot
|
|
3
|
+
v-bind="forwarded"
|
|
4
|
+
v-model="value"
|
|
5
|
+
:class="cn(
|
|
6
|
+
'relative flex touch-none select-none data-disabled:opacity-50',
|
|
7
|
+
(orientation === 'horizontal' ? 'w-full h-2 items-center' : 'h-full w-2 justify-center'),
|
|
8
|
+
props.class,
|
|
9
|
+
)"
|
|
10
|
+
>
|
|
11
|
+
<SliderTrack
|
|
12
|
+
class="relative grow overflow-hidden rounded-full bg-secondary"
|
|
13
|
+
:class="orientation === 'horizontal' ? 'h-2 w-full' : 'h-full w-2'"
|
|
14
|
+
>
|
|
15
|
+
<SliderRange
|
|
16
|
+
class="absolute bg-primary"
|
|
17
|
+
:class="orientation === 'horizontal' ? 'h-full' : 'w-full'"
|
|
18
|
+
/>
|
|
19
|
+
</SliderTrack>
|
|
20
|
+
<SliderThumb
|
|
21
|
+
v-for="(thumbValue, index) in value ? value : []"
|
|
22
|
+
:key="index"
|
|
23
|
+
class="flex h-5 w-5 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 data-disabled:pointer-events-none"
|
|
24
|
+
:class="orientation === 'horizontal' ? 'justify-center' : 'items-center'"
|
|
25
|
+
@focus="onFocus({ index, value: thumbValue }, $event)"
|
|
26
|
+
@blur="onBlur({ value: thumbValue }, $event)"
|
|
27
|
+
>
|
|
28
|
+
<div
|
|
29
|
+
v-if="showMarker && (visibleMarker === index)"
|
|
30
|
+
class="absolute z-1 bg-primary rounded-sm px-1.5 py-1 shadow-sm text-xs text-primary-foreground min-w-6 text-center"
|
|
31
|
+
:class="orientation === 'horizontal' ? 'bottom-6' : 'left-6'"
|
|
32
|
+
>
|
|
33
|
+
<slot name="marker" v-bind="{ value: thumbValue }">
|
|
34
|
+
{{ thumbValue }}
|
|
35
|
+
</slot>
|
|
36
|
+
</div>
|
|
37
|
+
</SliderThumb>
|
|
38
|
+
</SliderRoot>
|
|
39
|
+
</template>
|
|
40
|
+
|
|
41
|
+
<script setup lang="ts">
|
|
42
|
+
import { type HTMLAttributes, computed, ref } from 'vue'
|
|
43
|
+
import {
|
|
44
|
+
SliderRange,
|
|
45
|
+
SliderRoot,
|
|
46
|
+
SliderThumb,
|
|
47
|
+
SliderTrack,
|
|
48
|
+
type SliderRootProps,
|
|
49
|
+
type SliderRootEmits
|
|
50
|
+
} from 'reka-ui'
|
|
51
|
+
import { cn } from '@/utils/tailwind'
|
|
52
|
+
import { useDelegatedProps } from '@/composables/delegated-props'
|
|
53
|
+
import { useEmitAsProps } from '@/composables/emits-as-props'
|
|
54
|
+
import { useForwardPropsEmits } from '@/composables/forward-props-emits'
|
|
55
|
+
|
|
56
|
+
const props = withDefaults(defineProps<Omit<SliderRootProps, 'modelValue'> & {
|
|
57
|
+
class?: HTMLAttributes['class']
|
|
58
|
+
showMarker?: boolean
|
|
59
|
+
modelValue: number | number[]
|
|
60
|
+
}>(), {
|
|
61
|
+
min: 0,
|
|
62
|
+
max: 100,
|
|
63
|
+
step: 10,
|
|
64
|
+
orientation: 'horizontal',
|
|
65
|
+
showMarker: false
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const emits = defineEmits<Omit<SliderRootEmits, 'update:modelValue'> & {
|
|
69
|
+
focus: [payload: number, event: FocusEvent]
|
|
70
|
+
blur: [payload: number, event: FocusEvent]
|
|
71
|
+
dragstart: [payload: number]
|
|
72
|
+
dragend: [payload: number]
|
|
73
|
+
'update:modelValue': [value: number | number[]]
|
|
74
|
+
}>()
|
|
75
|
+
|
|
76
|
+
const delegatedProps = useDelegatedProps(props, ['class', 'showMarker', 'modelValue'])
|
|
77
|
+
const delegatedEmits = useEmitAsProps(emits, ['update:modelValue', 'focus', 'blur', 'dragstart', 'dragend'])
|
|
78
|
+
const forwarded = useForwardPropsEmits(delegatedProps, delegatedEmits)
|
|
79
|
+
|
|
80
|
+
const visibleMarker = ref<number | null>(null)
|
|
81
|
+
|
|
82
|
+
const value = computed({
|
|
83
|
+
get () {
|
|
84
|
+
return Array.isArray(props.modelValue) ? props.modelValue : [props.modelValue]
|
|
85
|
+
},
|
|
86
|
+
set (value) {
|
|
87
|
+
emits('update:modelValue', value ? (value.length === 2 ? value : value[0]) : value)
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
const onFocus = ({ index, value }: { index: number, value: number }, e: FocusEvent) => {
|
|
92
|
+
emits('focus', value, e)
|
|
93
|
+
visibleMarker.value = index
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const onBlur = ({ value }: { value: number }, e: FocusEvent) => {
|
|
97
|
+
emits('blur', value, e)
|
|
98
|
+
visibleMarker.value = null
|
|
99
|
+
}
|
|
100
|
+
</script>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Slider } from './Slider.vue'
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex items-center gap-x-2">
|
|
3
|
+
<SwitchBase
|
|
4
|
+
:id="id"
|
|
5
|
+
v-model="modelValue"
|
|
6
|
+
:disabled="disabled"
|
|
7
|
+
:required="required"
|
|
8
|
+
:name="name"
|
|
9
|
+
:value="value"
|
|
10
|
+
@blur="$emit('blur', $event)"
|
|
11
|
+
@focus="$emit('focus', $event)"
|
|
12
|
+
/>
|
|
13
|
+
<Label v-if="label || $slots.default" :for="id">
|
|
14
|
+
<slot>{{ label }}</slot>
|
|
15
|
+
</Label>
|
|
16
|
+
</div>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script setup lang="ts">
|
|
20
|
+
import { Label } from '@/components/ui/label'
|
|
21
|
+
import SwitchBase from './SwitchBase.vue'
|
|
22
|
+
import { useId } from 'reka-ui'
|
|
23
|
+
import type { Events } from 'vue'
|
|
24
|
+
|
|
25
|
+
const modelValue = defineModel<boolean>()
|
|
26
|
+
withDefaults(defineProps<{
|
|
27
|
+
name?: string
|
|
28
|
+
id?: string
|
|
29
|
+
label?: string
|
|
30
|
+
value?: string
|
|
31
|
+
required?: boolean
|
|
32
|
+
disabled?: boolean
|
|
33
|
+
}>(), {
|
|
34
|
+
id: () => useId()
|
|
35
|
+
})
|
|
36
|
+
defineEmits<{
|
|
37
|
+
focus: [event: Events['onFocus']]
|
|
38
|
+
blur: [event: Events['onBlur']]
|
|
39
|
+
}>()
|
|
40
|
+
</script>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SwitchRoot
|
|
3
|
+
v-bind="forwarded"
|
|
4
|
+
:class="cn(
|
|
5
|
+
'peer inline-flex h-5 w-8 shrink-0 cursor-pointer items-center rounded-full p-1 border-transparent transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',
|
|
6
|
+
props.class,
|
|
7
|
+
)"
|
|
8
|
+
>
|
|
9
|
+
<SwitchThumb
|
|
10
|
+
:class="cn('pointer-events-none block h-3.5 w-3.5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-2.5 data-[state=unchecked]:translate-x-0')"
|
|
11
|
+
/>
|
|
12
|
+
</SwitchRoot>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script setup lang="ts">
|
|
16
|
+
import { type HTMLAttributes, computed } from 'vue'
|
|
17
|
+
import {
|
|
18
|
+
SwitchRoot,
|
|
19
|
+
SwitchThumb,
|
|
20
|
+
type SwitchRootEmits,
|
|
21
|
+
type SwitchRootProps,
|
|
22
|
+
useForwardPropsEmits
|
|
23
|
+
} from 'reka-ui'
|
|
24
|
+
import { cn } from '@/utils/tailwind'
|
|
25
|
+
|
|
26
|
+
const props = defineProps<SwitchRootProps & { class?: HTMLAttributes['class'] }>()
|
|
27
|
+
const emits = defineEmits<SwitchRootEmits>()
|
|
28
|
+
|
|
29
|
+
const delegatedProps = computed(() => {
|
|
30
|
+
const { class: _, ...delegated } = props
|
|
31
|
+
|
|
32
|
+
return delegated
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
|
36
|
+
</script>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Switch } from './Switch.vue'
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<TabsRoot v-bind="forwarded" :class="cn(tabsVariants({ orientation }), props.class)">
|
|
3
|
+
<TabsList :class="cn(tabsListVariants({ orientation }), 'rounded-md bg-muted p-1 text-muted-foreground')">
|
|
4
|
+
<template v-for="tab in getTabs($slots.default ? $slots.default() : [])">
|
|
5
|
+
<Tooltip v-if="tab.props?.tooltip" :key="'tooltip-' + tab.props?.value">
|
|
6
|
+
<template #trigger>
|
|
7
|
+
<TabsTrigger :value="tab.props?.value" :disabled="tab.props?.disabled">
|
|
8
|
+
<template v-if="tab.props?.title">
|
|
9
|
+
{{ tab.props?.title }}
|
|
10
|
+
</template>
|
|
11
|
+
<Icon v-else-if="tab.props?.icon" :icon="tab.props.icon" />
|
|
12
|
+
</TabsTrigger>
|
|
13
|
+
</template>
|
|
14
|
+
{{ tab.props?.tooltip }}
|
|
15
|
+
</Tooltip>
|
|
16
|
+
<TabsTrigger
|
|
17
|
+
v-else
|
|
18
|
+
:key="tab.props?.value"
|
|
19
|
+
:value="tab.props?.value"
|
|
20
|
+
:disabled="tab.props?.disabled"
|
|
21
|
+
>
|
|
22
|
+
<template v-if="tab.props?.title">
|
|
23
|
+
{{ tab.props?.title }}
|
|
24
|
+
</template>
|
|
25
|
+
<Icon v-else-if="tab.props?.icon" :icon="tab.props.icon" />
|
|
26
|
+
</TabsTrigger>
|
|
27
|
+
</template>
|
|
28
|
+
</TabsList>
|
|
29
|
+
<slot />
|
|
30
|
+
</TabsRoot>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script setup lang="ts">
|
|
34
|
+
import { TabsRoot, useForwardPropsEmits, TabsList } from 'reka-ui'
|
|
35
|
+
import type { TabsRootEmits, TabsRootProps } from 'reka-ui'
|
|
36
|
+
import TabsTrigger from './TabsTrigger.vue'
|
|
37
|
+
import { Icon } from '@/components/ui/icon'
|
|
38
|
+
import { Tooltip } from '@/components/ui/tooltip'
|
|
39
|
+
import { cn } from '@/utils/tailwind'
|
|
40
|
+
import { tabsVariants, tabsListVariants } from '@/components/ui/tabs/index'
|
|
41
|
+
import type { HTMLAttributes, VNode } from 'vue'
|
|
42
|
+
const props = defineProps<TabsRootProps & {
|
|
43
|
+
class?: HTMLAttributes['class']
|
|
44
|
+
}>()
|
|
45
|
+
const emits = defineEmits<TabsRootEmits>()
|
|
46
|
+
|
|
47
|
+
const isFragment = (vNode: VNode) => vNode.type === Symbol.for('v-fgt')
|
|
48
|
+
|
|
49
|
+
const getTabs = (nodes: VNode[]) => {
|
|
50
|
+
const tabs = [] as VNode[]
|
|
51
|
+
nodes.forEach((node) => {
|
|
52
|
+
if (isFragment(node) && node.children) {
|
|
53
|
+
tabs.push(...getTabs(node.children as VNode[]))
|
|
54
|
+
} else {
|
|
55
|
+
tabs.push(node)
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
return tabs
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const forwarded = useForwardPropsEmits(props, emits)
|
|
63
|
+
</script>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<TabsContent
|
|
3
|
+
:class="cn('data-[orientation=horizontal]:mt-4 data-[orientation=vertical]:ml-4 rounded-sm ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2', props.class)"
|
|
4
|
+
v-bind="delegatedProps"
|
|
5
|
+
>
|
|
6
|
+
<slot />
|
|
7
|
+
</TabsContent>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script setup lang="ts">
|
|
11
|
+
import { type HTMLAttributes, computed } from 'vue'
|
|
12
|
+
import { TabsContent, type TabsContentProps } from 'reka-ui'
|
|
13
|
+
import { cn } from '@/utils/tailwind'
|
|
14
|
+
|
|
15
|
+
const props = defineProps<TabsContentProps & { class?: HTMLAttributes['class'] }>()
|
|
16
|
+
|
|
17
|
+
const delegatedProps = computed(() => {
|
|
18
|
+
const { class: _, ...delegated } = props
|
|
19
|
+
|
|
20
|
+
return delegated
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
defineOptions({
|
|
24
|
+
inheritAttrs: false
|
|
25
|
+
})
|
|
26
|
+
</script>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<TabsTrigger
|
|
3
|
+
v-bind="forwardedProps"
|
|
4
|
+
:class="cn(
|
|
5
|
+
'inline-flex items-center whitespace-nowrap rounded-sm px-3 text-xs font-medium ring-offset-background transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-xs',
|
|
6
|
+
props.class,
|
|
7
|
+
)"
|
|
8
|
+
>
|
|
9
|
+
<slot />
|
|
10
|
+
</TabsTrigger>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
import { type HTMLAttributes, computed } from 'vue'
|
|
15
|
+
import { TabsTrigger, type TabsTriggerProps, useForwardProps } from 'reka-ui'
|
|
16
|
+
import { cn } from '@/utils/tailwind'
|
|
17
|
+
|
|
18
|
+
const props = defineProps<TabsTriggerProps & { class?: HTMLAttributes['class'] }>()
|
|
19
|
+
|
|
20
|
+
const delegatedProps = computed(() => {
|
|
21
|
+
const { class: _, ...delegated } = props
|
|
22
|
+
|
|
23
|
+
return delegated
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const forwardedProps = useForwardProps(delegatedProps)
|
|
27
|
+
</script>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { cva } from 'class-variance-authority'
|
|
2
|
+
|
|
3
|
+
export { default as Tabs } from './Tabs.vue'
|
|
4
|
+
export { default as TabsContent } from './TabsContent.vue'
|
|
5
|
+
|
|
6
|
+
export const tabsVariants = cva('', {
|
|
7
|
+
variants: {
|
|
8
|
+
orientation: {
|
|
9
|
+
vertical: 'flex',
|
|
10
|
+
horizontal: ''
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
defaultVariants: {
|
|
14
|
+
orientation: 'horizontal'
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
export const tabsListVariants = cva('*:h-8', {
|
|
19
|
+
variants: {
|
|
20
|
+
orientation: {
|
|
21
|
+
vertical: 'flex flex-col items-start *:w-full',
|
|
22
|
+
horizontal: 'grid auto-cols-[1fr] grid-flow-col h-10 inline-grid items-center justify-center *:justify-center'
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
defaultVariants: {
|
|
26
|
+
orientation: 'horizontal'
|
|
27
|
+
}
|
|
28
|
+
})
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<textarea v-model="modelValue" :class="cn('flex min-h-20 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', props.class)" />
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script setup lang="ts">
|
|
6
|
+
import type { HTMLAttributes } from 'vue'
|
|
7
|
+
import { cn } from '@/utils/tailwind'
|
|
8
|
+
|
|
9
|
+
const modelValue = defineModel<string | undefined | null>()
|
|
10
|
+
const props = defineProps<{
|
|
11
|
+
class?: HTMLAttributes['class']
|
|
12
|
+
}>()
|
|
13
|
+
</script>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Textarea } from './Textarea.vue'
|