23 changed files with 422 additions and 19 deletions
@ -0,0 +1,34 @@ |
|||
<script setup lang="ts"> |
|||
import type { HTMLAttributes } from 'vue'; |
|||
|
|||
import { cn } from '@vben-core/toolkit'; |
|||
|
|||
import { useVModel } from '@vueuse/core'; |
|||
|
|||
const props = defineProps<{ |
|||
class?: HTMLAttributes['class']; |
|||
defaultValue?: number | string; |
|||
modelValue?: number | string; |
|||
}>(); |
|||
|
|||
const emits = defineEmits<{ |
|||
(e: 'update:modelValue', payload: number | string): void; |
|||
}>(); |
|||
|
|||
const modelValue = useVModel(props, 'modelValue', emits, { |
|||
defaultValue: props.defaultValue, |
|||
passive: true, |
|||
}); |
|||
</script> |
|||
|
|||
<template> |
|||
<input |
|||
v-model="modelValue" |
|||
:class=" |
|||
cn( |
|||
'border-input placeholder:text-muted-foreground focus-visible:ring-ring flex h-9 w-full rounded-md border bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50', |
|||
props.class, |
|||
) |
|||
" |
|||
/> |
|||
</template> |
|||
@ -0,0 +1 @@ |
|||
export { default as Input } from './Input.vue'; |
|||
@ -0,0 +1,28 @@ |
|||
<script setup lang="ts"> |
|||
import type { NumberFieldRootEmits, NumberFieldRootProps } from 'radix-vue'; |
|||
|
|||
import { type HTMLAttributes, computed } from 'vue'; |
|||
|
|||
import { cn } from '@vben-core/toolkit'; |
|||
|
|||
import { NumberFieldRoot, useForwardPropsEmits } from 'radix-vue'; |
|||
|
|||
const props = defineProps< |
|||
{ class?: HTMLAttributes['class'] } & NumberFieldRootProps |
|||
>(); |
|||
const emits = defineEmits<NumberFieldRootEmits>(); |
|||
|
|||
const delegatedProps = computed(() => { |
|||
const { class: _, ...delegated } = props; |
|||
|
|||
return delegated; |
|||
}); |
|||
|
|||
const forwarded = useForwardPropsEmits(delegatedProps, emits); |
|||
</script> |
|||
|
|||
<template> |
|||
<NumberFieldRoot v-bind="forwarded" :class="cn('grid gap-1.5', props.class)"> |
|||
<slot></slot> |
|||
</NumberFieldRoot> |
|||
</template> |
|||
@ -0,0 +1,22 @@ |
|||
<script setup lang="ts"> |
|||
import type { HTMLAttributes } from 'vue'; |
|||
|
|||
import { cn } from '@vben-core/toolkit'; |
|||
|
|||
const props = defineProps<{ |
|||
class?: HTMLAttributes['class']; |
|||
}>(); |
|||
</script> |
|||
|
|||
<template> |
|||
<div |
|||
:class=" |
|||
cn( |
|||
'relative [&>[data-slot=input]]:has-[[data-slot=decrement]]:pl-5 [&>[data-slot=input]]:has-[[data-slot=increment]]:pr-5', |
|||
props.class, |
|||
) |
|||
" |
|||
> |
|||
<slot></slot> |
|||
</div> |
|||
</template> |
|||
@ -0,0 +1,39 @@ |
|||
<script setup lang="ts"> |
|||
import type { NumberFieldDecrementProps } from 'radix-vue'; |
|||
|
|||
import { type HTMLAttributes, computed } from 'vue'; |
|||
|
|||
import { cn } from '@vben-core/toolkit'; |
|||
|
|||
import { Minus } from 'lucide-vue-next'; |
|||
import { NumberFieldDecrement, useForwardProps } from 'radix-vue'; |
|||
|
|||
const props = defineProps< |
|||
{ class?: HTMLAttributes['class'] } & NumberFieldDecrementProps |
|||
>(); |
|||
|
|||
const delegatedProps = computed(() => { |
|||
const { class: _, ...delegated } = props; |
|||
|
|||
return delegated; |
|||
}); |
|||
|
|||
const forwarded = useForwardProps(delegatedProps); |
|||
</script> |
|||
|
|||
<template> |
|||
<NumberFieldDecrement |
|||
data-slot="decrement" |
|||
v-bind="forwarded" |
|||
:class=" |
|||
cn( |
|||
'absolute left-0 top-1/2 -translate-y-1/2 p-3 disabled:cursor-not-allowed disabled:opacity-20', |
|||
props.class, |
|||
) |
|||
" |
|||
> |
|||
<slot> |
|||
<Minus class="h-4 w-4" /> |
|||
</slot> |
|||
</NumberFieldDecrement> |
|||
</template> |
|||
@ -0,0 +1,39 @@ |
|||
<script setup lang="ts"> |
|||
import type { NumberFieldIncrementProps } from 'radix-vue'; |
|||
|
|||
import { type HTMLAttributes, computed } from 'vue'; |
|||
|
|||
import { cn } from '@vben-core/toolkit'; |
|||
|
|||
import { Plus } from 'lucide-vue-next'; |
|||
import { NumberFieldIncrement, useForwardProps } from 'radix-vue'; |
|||
|
|||
const props = defineProps< |
|||
{ class?: HTMLAttributes['class'] } & NumberFieldIncrementProps |
|||
>(); |
|||
|
|||
const delegatedProps = computed(() => { |
|||
const { class: _, ...delegated } = props; |
|||
|
|||
return delegated; |
|||
}); |
|||
|
|||
const forwarded = useForwardProps(delegatedProps); |
|||
</script> |
|||
|
|||
<template> |
|||
<NumberFieldIncrement |
|||
data-slot="increment" |
|||
v-bind="forwarded" |
|||
:class=" |
|||
cn( |
|||
'absolute right-0 top-1/2 -translate-y-1/2 p-3 disabled:cursor-not-allowed disabled:opacity-20', |
|||
props.class, |
|||
) |
|||
" |
|||
> |
|||
<slot> |
|||
<Plus class="h-4 w-4" /> |
|||
</slot> |
|||
</NumberFieldIncrement> |
|||
</template> |
|||
@ -0,0 +1,16 @@ |
|||
<script setup lang="ts"> |
|||
import { cn } from '@vben-core/toolkit'; |
|||
|
|||
import { NumberFieldInput } from 'radix-vue'; |
|||
</script> |
|||
|
|||
<template> |
|||
<NumberFieldInput |
|||
:class=" |
|||
cn( |
|||
'border-input placeholder:text-muted-foreground focus-visible:ring-ring flex h-9 w-full rounded-md border bg-transparent py-1 text-center text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50', |
|||
) |
|||
" |
|||
data-slot="input" |
|||
/> |
|||
</template> |
|||
@ -0,0 +1,5 @@ |
|||
export { default as NumberField } from './NumberField.vue'; |
|||
export { default as NumberFieldContent } from './NumberFieldContent.vue'; |
|||
export { default as NumberFieldDecrement } from './NumberFieldDecrement.vue'; |
|||
export { default as NumberFieldIncrement } from './NumberFieldIncrement.vue'; |
|||
export { default as NumberFieldInput } from './NumberFieldInput.vue'; |
|||
@ -0,0 +1,51 @@ |
|||
<script setup lang="ts"> |
|||
import type { SelectListItem } from '@vben/types'; |
|||
|
|||
import { useSlots } from 'vue'; |
|||
|
|||
import { MdiQuestionMarkCircleOutline } from '@vben-core/iconify'; |
|||
import { Input, VbenTooltip } from '@vben-core/shadcn-ui'; |
|||
|
|||
defineOptions({ |
|||
name: 'PreferenceSelectItem', |
|||
}); |
|||
|
|||
withDefaults( |
|||
defineProps<{ |
|||
disabled?: boolean; |
|||
items?: SelectListItem[]; |
|||
placeholder?: string; |
|||
}>(), |
|||
{ |
|||
disabled: false, |
|||
placeholder: '', |
|||
items: () => [], |
|||
}, |
|||
); |
|||
|
|||
const inputValue = defineModel<string>(); |
|||
|
|||
const slots = useSlots(); |
|||
</script> |
|||
|
|||
<template> |
|||
<div |
|||
:class="{ |
|||
'hover:bg-accent': !slots.tip, |
|||
'pointer-events-none opacity-50': disabled, |
|||
}" |
|||
class="my-1 flex w-full items-center justify-between rounded-md px-2 py-1" |
|||
> |
|||
<span class="flex items-center text-sm"> |
|||
<slot></slot> |
|||
|
|||
<VbenTooltip v-if="slots.tip" side="bottom"> |
|||
<template #trigger> |
|||
<MdiQuestionMarkCircleOutline class="ml-1 cursor-help" /> |
|||
</template> |
|||
<slot name="tip"></slot> |
|||
</VbenTooltip> |
|||
</span> |
|||
<Input v-model="inputValue" class="h-8 w-[160px]" /> |
|||
</div> |
|||
</template> |
|||
@ -0,0 +1,65 @@ |
|||
<script setup lang="ts"> |
|||
import type { SelectListItem } from '@vben/types'; |
|||
|
|||
import { useSlots } from 'vue'; |
|||
|
|||
import { MdiQuestionMarkCircleOutline } from '@vben-core/iconify'; |
|||
import { |
|||
NumberField, |
|||
NumberFieldContent, |
|||
NumberFieldDecrement, |
|||
NumberFieldIncrement, |
|||
NumberFieldInput, |
|||
VbenTooltip, |
|||
} from '@vben-core/shadcn-ui'; |
|||
|
|||
defineOptions({ |
|||
name: 'PreferenceSelectItem', |
|||
}); |
|||
|
|||
withDefaults( |
|||
defineProps<{ |
|||
disabled?: boolean; |
|||
items?: SelectListItem[]; |
|||
placeholder?: string; |
|||
}>(), |
|||
{ |
|||
disabled: false, |
|||
placeholder: '', |
|||
items: () => [], |
|||
}, |
|||
); |
|||
|
|||
const inputValue = defineModel<number>(); |
|||
|
|||
const slots = useSlots(); |
|||
</script> |
|||
|
|||
<template> |
|||
<div |
|||
:class="{ |
|||
'hover:bg-accent': !slots.tip, |
|||
'pointer-events-none opacity-50': disabled, |
|||
}" |
|||
class="my-1 flex w-full items-center justify-between rounded-md px-2 py-1" |
|||
> |
|||
<span class="flex items-center text-sm"> |
|||
<slot></slot> |
|||
|
|||
<VbenTooltip v-if="slots.tip" side="bottom"> |
|||
<template #trigger> |
|||
<MdiQuestionMarkCircleOutline class="ml-1 cursor-help" /> |
|||
</template> |
|||
<slot name="tip"></slot> |
|||
</VbenTooltip> |
|||
</span> |
|||
|
|||
<NumberField v-model="inputValue" v-bind="$attrs" class="w-[160px]"> |
|||
<NumberFieldContent> |
|||
<NumberFieldDecrement /> |
|||
<NumberFieldInput /> |
|||
<NumberFieldIncrement /> |
|||
</NumberFieldContent> |
|||
</NumberField> |
|||
</div> |
|||
</template> |
|||
Loading…
Reference in new issue