diff --git a/packages/ui/src/components/index.ts b/packages/ui/src/components/index.ts index fd300ed5..b363b30f 100644 --- a/packages/ui/src/components/index.ts +++ b/packages/ui/src/components/index.ts @@ -23,6 +23,7 @@ export * from './label'; export * from './menu'; export * from './menubar'; export * from './navigation-menu'; +export * from './number-field'; export * from './pagination'; export * from './pin-input'; export * from './popover'; diff --git a/packages/ui/src/components/number-field/index.ts b/packages/ui/src/components/number-field/index.ts new file mode 100644 index 00000000..c56b37ea --- /dev/null +++ b/packages/ui/src/components/number-field/index.ts @@ -0,0 +1,9 @@ +import SNumberFieldDecrement from './number-field-decrement.vue'; +import SNumberFieldIncrement from './number-field-increment.vue'; +import SNumberFieldInput from './number-field-input.vue'; +import SNumberFieldRoot from './number-field-root.vue'; +import SNumberField from './number-field.vue'; + +export { SNumberFieldDecrement, SNumberFieldIncrement, SNumberFieldInput, SNumberFieldRoot, SNumberField }; + +export * from './types'; diff --git a/packages/ui/src/components/number-field/number-field-decrement.vue b/packages/ui/src/components/number-field/number-field-decrement.vue new file mode 100644 index 00000000..78cec941 --- /dev/null +++ b/packages/ui/src/components/number-field/number-field-decrement.vue @@ -0,0 +1,31 @@ + + + diff --git a/packages/ui/src/components/number-field/number-field-increment.vue b/packages/ui/src/components/number-field/number-field-increment.vue new file mode 100644 index 00000000..e7756603 --- /dev/null +++ b/packages/ui/src/components/number-field/number-field-increment.vue @@ -0,0 +1,32 @@ + + + diff --git a/packages/ui/src/components/number-field/number-field-input.vue b/packages/ui/src/components/number-field/number-field-input.vue new file mode 100644 index 00000000..db72e15b --- /dev/null +++ b/packages/ui/src/components/number-field/number-field-input.vue @@ -0,0 +1,22 @@ + + + diff --git a/packages/ui/src/components/number-field/number-field-root.vue b/packages/ui/src/components/number-field/number-field-root.vue new file mode 100644 index 00000000..a2086ba5 --- /dev/null +++ b/packages/ui/src/components/number-field/number-field-root.vue @@ -0,0 +1,28 @@ + + + diff --git a/packages/ui/src/components/number-field/number-field.vue b/packages/ui/src/components/number-field/number-field.vue new file mode 100644 index 00000000..5faed437 --- /dev/null +++ b/packages/ui/src/components/number-field/number-field.vue @@ -0,0 +1,50 @@ + + + diff --git a/packages/ui/src/components/number-field/types.ts b/packages/ui/src/components/number-field/types.ts new file mode 100644 index 00000000..1e829087 --- /dev/null +++ b/packages/ui/src/components/number-field/types.ts @@ -0,0 +1,43 @@ +import type { + ClassValue, + NumberFieldRootEmits, + NumberFieldDecrementProps as _NumberFieldDecrementProps, + NumberFieldIncrementProps as _NumberFieldIncrementProps, + NumberFieldInputProps as _NumberFieldInputProps, + NumberFieldRootProps as _NumberFieldRootProps +} from '@soybean-ui/primitives'; +import type { NumberFieldSlots, ThemeSize } from '@soybean-ui/variants'; + +export interface NumberFieldRootProps extends _NumberFieldRootProps { + size?: ThemeSize; +} + +export interface NumberFieldInputProps extends _NumberFieldInputProps { + size?: ThemeSize; + center?: boolean; +} + +export interface NumberFieldDecrementProps extends _NumberFieldDecrementProps { + size?: ThemeSize; + center?: boolean; + iconClass?: ClassValue; +} + +export interface NumberFieldIncrementProps extends _NumberFieldIncrementProps { + size?: ThemeSize; + center?: boolean; + iconClass?: ClassValue; +} + +export type NumberFieldUi = Partial>; + +export interface NumberFieldProps extends NumberFieldRootProps { + center?: boolean; + disabledDecrement?: boolean; + disabledIncrement?: boolean; + ui?: NumberFieldUi; +} + +export type NumberFieldEmits = NumberFieldRootEmits; + +export type { NumberFieldRootEmits }; diff --git a/packages/variants/src/index.ts b/packages/variants/src/index.ts index 30952a98..5f46b890 100644 --- a/packages/variants/src/index.ts +++ b/packages/variants/src/index.ts @@ -21,6 +21,7 @@ export * from './variants/label'; export * from './variants/menu'; export * from './variants/menubar'; export * from './variants/navigation-menu'; +export * from './variants/number-field'; export * from './variants/pagination'; export * from './variants/pin-input'; export * from './variants/popover'; diff --git a/packages/variants/src/variants/number-field.ts b/packages/variants/src/variants/number-field.ts new file mode 100644 index 00000000..0becdd4d --- /dev/null +++ b/packages/variants/src/variants/number-field.ts @@ -0,0 +1,119 @@ +// @unocss-include +import { tv } from 'tailwind-variants'; + +export const numberFieldVariants = tv({ + slots: { + root: 'flex items-center w-full rounded-md border border-input bg-background focus-within:(border-input ring-2 ring-offset-2 ring-primary) disabled:(cursor-not-allowed opacity-50)', + decrement: `flex h-full shrink-0 items-center justify-center bg-transparent outline-none disabled:(cursor-not-allowed opacity-20)`, + decrementIcon: '', + increment: `flex h-full shrink-0 items-center justify-center bg-transparent outline-none disabled:(cursor-not-allowed opacity-20)`, + incrementIcon: '', + input: [ + `h-full w-full grow bg-transparent`, + `placeholder:text-muted-foreground outline-none disabled:(cursor-not-allowed opacity-50)` + ] + }, + variants: { + size: { + xs: { + decrement: 'p-1', + decrementIcon: 'text-xs', + increment: 'p-1', + incrementIcon: 'text-xs', + input: 'h-6 text-xs' + }, + sm: { + decrement: 'p-1.25', + decrementIcon: 'text-sm', + increment: 'p-1.25', + incrementIcon: 'text-sm', + input: 'h-7 text-sm' + }, + md: { + decrement: 'p-1.25', + decrementIcon: 'text-sm', + increment: 'p-1.25', + incrementIcon: 'text-sm', + input: 'h-8 text-sm' + }, + lg: { + decrement: 'p-1.5', + decrementIcon: 'text-base', + increment: 'p-1.5', + incrementIcon: 'text-base', + input: 'h-9 text-base' + }, + xl: { + decrement: 'p-1.5', + decrementIcon: 'text-lg', + increment: 'p-1.5', + incrementIcon: 'text-lg', + input: 'h-10 text-base' + }, + xxl: { + decrement: 'p-2', + decrementIcon: 'text-xl', + increment: 'p-2', + incrementIcon: 'text-xl', + input: 'h-12 text-lg' + } + }, + center: { + true: { + decrement: 'order-1', + input: 'text-center order-2', + increment: 'order-3' + } + } + }, + compoundVariants: [ + { + size: 'xs', + center: false, + class: { + input: 'pl-1.5' + } + }, + { + size: 'sm', + center: false, + class: { + input: 'pl-2' + } + }, + { + size: 'md', + center: false, + class: { + input: 'pl-2.5' + } + }, + { + size: 'lg', + center: false, + class: { + input: 'pl-3' + } + }, + { + size: 'xl', + center: false, + class: { + input: 'pl-3.5' + } + }, + { + size: 'xxl', + center: false, + class: { + input: 'pl-4' + } + } + ], + defaultVariants: { + size: 'md', + center: false + } +}); + +export type NumberFieldSlots = keyof typeof numberFieldVariants.slots; diff --git a/src/views/ui/index.vue b/src/views/ui/index.vue index 3fad048d..83e0f628 100644 --- a/src/views/ui/index.vue +++ b/src/views/ui/index.vue @@ -29,6 +29,7 @@ import UiInput from './modules/input.vue'; import UiKeyboardKey from './modules/keyboard-key.vue'; import UiMenubar from './modules/menubar.vue'; import UiNavigationMenu from './modules/navigation-menu.vue'; +import UiNumberField from './modules/number-field.vue'; import UiPagination from './modules/pagination.vue'; import UiPinInput from './modules/pin-input.vue'; import UiPopover from './modules/popover.vue'; @@ -189,6 +190,11 @@ const tabs: TabConfig[] = [ label: 'NavigationMenu', component: UiNavigationMenu }, + { + value: 'number-field', + label: 'NumberField', + component: UiNumberField + }, { value: 'popover', label: 'Popover', diff --git a/src/views/ui/modules/number-field.vue b/src/views/ui/modules/number-field.vue new file mode 100644 index 00000000..4babf8c3 --- /dev/null +++ b/src/views/ui/modules/number-field.vue @@ -0,0 +1,41 @@ + + +