added searching and sorting system
This commit is contained in:
26
ui/src/components/ui/select/Select.vue
Normal file
26
ui/src/components/ui/select/Select.vue
Normal file
@@ -0,0 +1,26 @@
|
||||
<script setup>
|
||||
import { SelectRoot, useForwardPropsEmits } from "reka-ui";
|
||||
|
||||
const props = defineProps({
|
||||
open: { type: Boolean, required: false },
|
||||
defaultOpen: { type: Boolean, required: false },
|
||||
defaultValue: { type: null, required: false },
|
||||
modelValue: { type: null, required: false },
|
||||
by: { type: [String, Function], required: false },
|
||||
dir: { type: String, required: false },
|
||||
multiple: { type: Boolean, required: false },
|
||||
autocomplete: { type: String, required: false },
|
||||
disabled: { type: Boolean, required: false },
|
||||
name: { type: String, required: false },
|
||||
required: { type: Boolean, required: false },
|
||||
});
|
||||
const emits = defineEmits(["update:modelValue", "update:open"]);
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SelectRoot v-slot="slotProps" data-slot="select" v-bind="forwarded">
|
||||
<slot v-bind="slotProps" />
|
||||
</SelectRoot>
|
||||
</template>
|
||||
81
ui/src/components/ui/select/SelectContent.vue
Normal file
81
ui/src/components/ui/select/SelectContent.vue
Normal file
@@ -0,0 +1,81 @@
|
||||
<script setup>
|
||||
import { reactiveOmit } from "@vueuse/core";
|
||||
import {
|
||||
SelectContent,
|
||||
SelectPortal,
|
||||
SelectViewport,
|
||||
useForwardPropsEmits,
|
||||
} from "reka-ui";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { SelectScrollDownButton, SelectScrollUpButton } from ".";
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
});
|
||||
|
||||
const props = defineProps({
|
||||
forceMount: { type: Boolean, required: false },
|
||||
position: { type: String, required: false, default: "popper" },
|
||||
bodyLock: { type: Boolean, required: false },
|
||||
side: { type: null, required: false },
|
||||
sideOffset: { type: Number, required: false },
|
||||
sideFlip: { type: Boolean, required: false },
|
||||
align: { type: null, required: false },
|
||||
alignOffset: { type: Number, required: false },
|
||||
alignFlip: { type: Boolean, required: false },
|
||||
avoidCollisions: { type: Boolean, required: false },
|
||||
collisionBoundary: { type: null, required: false },
|
||||
collisionPadding: { type: [Number, Object], required: false },
|
||||
arrowPadding: { type: Number, required: false },
|
||||
sticky: { type: String, required: false },
|
||||
hideWhenDetached: { type: Boolean, required: false },
|
||||
positionStrategy: { type: String, required: false },
|
||||
updatePositionStrategy: { type: String, required: false },
|
||||
disableUpdateOnLayoutShift: { type: Boolean, required: false },
|
||||
prioritizePosition: { type: Boolean, required: false },
|
||||
reference: { type: null, required: false },
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
const emits = defineEmits([
|
||||
"closeAutoFocus",
|
||||
"escapeKeyDown",
|
||||
"pointerDownOutside",
|
||||
]);
|
||||
|
||||
const delegatedProps = reactiveOmit(props, "class");
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SelectPortal>
|
||||
<SelectContent
|
||||
data-slot="select-content"
|
||||
v-bind="{ ...$attrs, ...forwarded }"
|
||||
:class="
|
||||
cn(
|
||||
'bg-popover text-popover-foreground 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 relative z-50 max-h-(--reka-select-content-available-height) min-w-[8rem] overflow-x-hidden overflow-y-auto rounded-md border shadow-md',
|
||||
position === 'popper' &&
|
||||
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
>
|
||||
<SelectScrollUpButton />
|
||||
<SelectViewport
|
||||
:class="
|
||||
cn(
|
||||
'p-1',
|
||||
position === 'popper' &&
|
||||
'h-[var(--reka-select-trigger-height)] w-full min-w-[var(--reka-select-trigger-width)] scroll-my-1',
|
||||
)
|
||||
"
|
||||
>
|
||||
<slot />
|
||||
</SelectViewport>
|
||||
<SelectScrollDownButton />
|
||||
</SelectContent>
|
||||
</SelectPortal>
|
||||
</template>
|
||||
14
ui/src/components/ui/select/SelectGroup.vue
Normal file
14
ui/src/components/ui/select/SelectGroup.vue
Normal file
@@ -0,0 +1,14 @@
|
||||
<script setup>
|
||||
import { SelectGroup } from "reka-ui";
|
||||
|
||||
const props = defineProps({
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SelectGroup data-slot="select-group" v-bind="props">
|
||||
<slot />
|
||||
</SelectGroup>
|
||||
</template>
|
||||
49
ui/src/components/ui/select/SelectItem.vue
Normal file
49
ui/src/components/ui/select/SelectItem.vue
Normal file
@@ -0,0 +1,49 @@
|
||||
<script setup>
|
||||
import { reactiveOmit } from "@vueuse/core";
|
||||
import { Check } from "lucide-vue-next";
|
||||
import {
|
||||
SelectItem,
|
||||
SelectItemIndicator,
|
||||
SelectItemText,
|
||||
useForwardProps,
|
||||
} from "reka-ui";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const props = defineProps({
|
||||
value: { type: null, required: true },
|
||||
disabled: { type: Boolean, required: false },
|
||||
textValue: { type: String, required: false },
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
|
||||
const delegatedProps = reactiveOmit(props, "class");
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SelectItem
|
||||
data-slot="select-item"
|
||||
v-bind="forwardedProps"
|
||||
:class="
|
||||
cn(
|
||||
'focus:bg-accent focus:text-accent-foreground [&_svg:not([class*=\'text-\'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
>
|
||||
<span class="absolute right-2 flex size-3.5 items-center justify-center">
|
||||
<SelectItemIndicator>
|
||||
<slot name="indicator-icon">
|
||||
<Check class="size-4" />
|
||||
</slot>
|
||||
</SelectItemIndicator>
|
||||
</span>
|
||||
|
||||
<SelectItemText>
|
||||
<slot />
|
||||
</SelectItemText>
|
||||
</SelectItem>
|
||||
</template>
|
||||
14
ui/src/components/ui/select/SelectItemText.vue
Normal file
14
ui/src/components/ui/select/SelectItemText.vue
Normal file
@@ -0,0 +1,14 @@
|
||||
<script setup>
|
||||
import { SelectItemText } from "reka-ui";
|
||||
|
||||
const props = defineProps({
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SelectItemText data-slot="select-item-text" v-bind="props">
|
||||
<slot />
|
||||
</SelectItemText>
|
||||
</template>
|
||||
20
ui/src/components/ui/select/SelectLabel.vue
Normal file
20
ui/src/components/ui/select/SelectLabel.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<script setup>
|
||||
import { SelectLabel } from "reka-ui";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const props = defineProps({
|
||||
for: { type: String, required: false },
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SelectLabel
|
||||
data-slot="select-label"
|
||||
:class="cn('text-muted-foreground px-2 py-1.5 text-xs', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</SelectLabel>
|
||||
</template>
|
||||
30
ui/src/components/ui/select/SelectScrollDownButton.vue
Normal file
30
ui/src/components/ui/select/SelectScrollDownButton.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<script setup>
|
||||
import { reactiveOmit } from "@vueuse/core";
|
||||
import { ChevronDown } from "lucide-vue-next";
|
||||
import { SelectScrollDownButton, useForwardProps } from "reka-ui";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const props = defineProps({
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
|
||||
const delegatedProps = reactiveOmit(props, "class");
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SelectScrollDownButton
|
||||
data-slot="select-scroll-down-button"
|
||||
v-bind="forwardedProps"
|
||||
:class="
|
||||
cn('flex cursor-default items-center justify-center py-1', props.class)
|
||||
"
|
||||
>
|
||||
<slot>
|
||||
<ChevronDown class="size-4" />
|
||||
</slot>
|
||||
</SelectScrollDownButton>
|
||||
</template>
|
||||
30
ui/src/components/ui/select/SelectScrollUpButton.vue
Normal file
30
ui/src/components/ui/select/SelectScrollUpButton.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<script setup>
|
||||
import { reactiveOmit } from "@vueuse/core";
|
||||
import { ChevronUp } from "lucide-vue-next";
|
||||
import { SelectScrollUpButton, useForwardProps } from "reka-ui";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const props = defineProps({
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
|
||||
const delegatedProps = reactiveOmit(props, "class");
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SelectScrollUpButton
|
||||
data-slot="select-scroll-up-button"
|
||||
v-bind="forwardedProps"
|
||||
:class="
|
||||
cn('flex cursor-default items-center justify-center py-1', props.class)
|
||||
"
|
||||
>
|
||||
<slot>
|
||||
<ChevronUp class="size-4" />
|
||||
</slot>
|
||||
</SelectScrollUpButton>
|
||||
</template>
|
||||
21
ui/src/components/ui/select/SelectSeparator.vue
Normal file
21
ui/src/components/ui/select/SelectSeparator.vue
Normal file
@@ -0,0 +1,21 @@
|
||||
<script setup>
|
||||
import { reactiveOmit } from "@vueuse/core";
|
||||
import { SelectSeparator } from "reka-ui";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const props = defineProps({
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
class: { type: null, required: false },
|
||||
});
|
||||
|
||||
const delegatedProps = reactiveOmit(props, "class");
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SelectSeparator
|
||||
data-slot="select-separator"
|
||||
v-bind="delegatedProps"
|
||||
:class="cn('bg-border pointer-events-none -mx-1 my-1 h-px', props.class)"
|
||||
/>
|
||||
</template>
|
||||
37
ui/src/components/ui/select/SelectTrigger.vue
Normal file
37
ui/src/components/ui/select/SelectTrigger.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<script setup>
|
||||
import { reactiveOmit } from "@vueuse/core";
|
||||
import { ChevronDown } from "lucide-vue-next";
|
||||
import { SelectIcon, SelectTrigger, useForwardProps } from "reka-ui";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const props = defineProps({
|
||||
disabled: { type: Boolean, required: false },
|
||||
reference: { type: null, required: false },
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
class: { type: null, required: false },
|
||||
size: { type: String, required: false, default: "default" },
|
||||
});
|
||||
|
||||
const delegatedProps = reactiveOmit(props, "class", "size");
|
||||
const forwardedProps = useForwardProps(delegatedProps);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SelectTrigger
|
||||
data-slot="select-trigger"
|
||||
:data-size="size"
|
||||
v-bind="forwardedProps"
|
||||
:class="
|
||||
cn(
|
||||
'border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*=\'text-\'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\'size-\'])]:size-4',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
>
|
||||
<slot />
|
||||
<SelectIcon as-child>
|
||||
<ChevronDown class="size-4 opacity-50" />
|
||||
</SelectIcon>
|
||||
</SelectTrigger>
|
||||
</template>
|
||||
15
ui/src/components/ui/select/SelectValue.vue
Normal file
15
ui/src/components/ui/select/SelectValue.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<script setup>
|
||||
import { SelectValue } from "reka-ui";
|
||||
|
||||
const props = defineProps({
|
||||
placeholder: { type: String, required: false },
|
||||
asChild: { type: Boolean, required: false },
|
||||
as: { type: null, required: false },
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SelectValue data-slot="select-value" v-bind="props">
|
||||
<slot />
|
||||
</SelectValue>
|
||||
</template>
|
||||
11
ui/src/components/ui/select/index.js
Normal file
11
ui/src/components/ui/select/index.js
Normal file
@@ -0,0 +1,11 @@
|
||||
export { default as Select } from "./Select.vue";
|
||||
export { default as SelectContent } from "./SelectContent.vue";
|
||||
export { default as SelectGroup } from "./SelectGroup.vue";
|
||||
export { default as SelectItem } from "./SelectItem.vue";
|
||||
export { default as SelectItemText } from "./SelectItemText.vue";
|
||||
export { default as SelectLabel } from "./SelectLabel.vue";
|
||||
export { default as SelectScrollDownButton } from "./SelectScrollDownButton.vue";
|
||||
export { default as SelectScrollUpButton } from "./SelectScrollUpButton.vue";
|
||||
export { default as SelectSeparator } from "./SelectSeparator.vue";
|
||||
export { default as SelectTrigger } from "./SelectTrigger.vue";
|
||||
export { default as SelectValue } from "./SelectValue.vue";
|
||||
Reference in New Issue
Block a user