@facter/ds-core 1.34.1 → 1.35.0

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/dist/index.mjs CHANGED
@@ -3042,6 +3042,163 @@ var toast = Object.assign(
3042
3042
  promise: (promise, options) => toast$1.promise(promise, options)
3043
3043
  }
3044
3044
  );
3045
+ var NumberStepper = React10.forwardRef(
3046
+ ({
3047
+ value = 1,
3048
+ onChange,
3049
+ onBlur,
3050
+ min = 0,
3051
+ max,
3052
+ step = 0.5,
3053
+ defaultValue,
3054
+ label,
3055
+ required,
3056
+ disabled,
3057
+ error,
3058
+ labelSuffix,
3059
+ className,
3060
+ name
3061
+ }, ref) => {
3062
+ const inputRef = React10.useRef(null);
3063
+ const [displayValue, setDisplayValue] = React10.useState(String(value));
3064
+ const [isFocused, setIsFocused] = React10.useState(false);
3065
+ React10.useImperativeHandle(ref, () => inputRef.current, []);
3066
+ React10.useEffect(() => {
3067
+ if (!isFocused) {
3068
+ setDisplayValue(String(value));
3069
+ }
3070
+ }, [value, isFocused]);
3071
+ const canDecrement = value - step >= min;
3072
+ const canIncrement = max === void 0 || value + step <= max;
3073
+ const handleDecrement = React10.useCallback(() => {
3074
+ if (!canDecrement || disabled) return;
3075
+ const newValue = Math.round((value - step) * 1e3) / 1e3;
3076
+ onChange?.(newValue);
3077
+ }, [value, step, min, disabled, onChange, canDecrement]);
3078
+ const handleIncrement = React10.useCallback(() => {
3079
+ if (!canIncrement || disabled) return;
3080
+ const newValue = Math.round((value + step) * 1e3) / 1e3;
3081
+ onChange?.(newValue);
3082
+ }, [value, step, max, disabled, onChange, canIncrement]);
3083
+ const handleInputChange = React10.useCallback(
3084
+ (e) => {
3085
+ const raw = e.target.value;
3086
+ setDisplayValue(raw);
3087
+ if (raw === "" || raw === "-" || raw === ".") return;
3088
+ const parsed = parseFloat(raw);
3089
+ if (isNaN(parsed)) return;
3090
+ onChange?.(parsed);
3091
+ },
3092
+ [onChange]
3093
+ );
3094
+ const handleInputFocus = React10.useCallback(() => {
3095
+ setIsFocused(true);
3096
+ }, []);
3097
+ const handleInputBlur = React10.useCallback(() => {
3098
+ setIsFocused(false);
3099
+ const parsed = parseFloat(displayValue);
3100
+ if (isNaN(parsed) || displayValue === "") {
3101
+ const resetValue = defaultValue ?? min;
3102
+ setDisplayValue(String(resetValue));
3103
+ if (value !== resetValue) onChange?.(resetValue);
3104
+ onBlur?.();
3105
+ return;
3106
+ }
3107
+ let clamped = parsed;
3108
+ if (clamped < min) clamped = min;
3109
+ if (max !== void 0 && clamped > max) clamped = max;
3110
+ setDisplayValue(String(clamped));
3111
+ if (clamped !== value) onChange?.(clamped);
3112
+ onBlur?.();
3113
+ }, [displayValue, value, min, max, onChange, onBlur]);
3114
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
3115
+ /* @__PURE__ */ jsxs(
3116
+ "div",
3117
+ {
3118
+ className: cn(
3119
+ "flex items-center h-12 rounded-md border-2 transition-colors overflow-hidden bg-background",
3120
+ error ? "border-red-500 focus-within:border-red-600" : "border-border focus-within:border-primary",
3121
+ disabled && "opacity-50 cursor-not-allowed"
3122
+ ),
3123
+ children: [
3124
+ /* @__PURE__ */ jsx(
3125
+ "button",
3126
+ {
3127
+ type: "button",
3128
+ tabIndex: -1,
3129
+ onClick: handleDecrement,
3130
+ disabled: disabled || !canDecrement,
3131
+ className: cn(
3132
+ "flex items-center justify-center w-11 h-full transition-colors select-none shrink-0",
3133
+ "text-muted-foreground hover:text-foreground hover:bg-muted",
3134
+ "disabled:opacity-30 disabled:hover:bg-transparent disabled:hover:text-muted-foreground disabled:cursor-not-allowed"
3135
+ ),
3136
+ "aria-label": "Diminuir",
3137
+ children: /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: /* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" }) })
3138
+ }
3139
+ ),
3140
+ /* @__PURE__ */ jsx("div", { className: "w-px h-6 bg-border shrink-0" }),
3141
+ /* @__PURE__ */ jsx(
3142
+ "input",
3143
+ {
3144
+ ref: inputRef,
3145
+ name,
3146
+ type: "text",
3147
+ inputMode: "decimal",
3148
+ value: displayValue,
3149
+ onChange: handleInputChange,
3150
+ onFocus: handleInputFocus,
3151
+ onBlur: handleInputBlur,
3152
+ disabled,
3153
+ className: cn(
3154
+ "flex-1 min-w-0 h-full text-center text-sm font-medium bg-transparent outline-none",
3155
+ "disabled:cursor-not-allowed",
3156
+ label ? "pt-1" : ""
3157
+ )
3158
+ }
3159
+ ),
3160
+ /* @__PURE__ */ jsx("div", { className: "w-px h-6 bg-border shrink-0" }),
3161
+ /* @__PURE__ */ jsx(
3162
+ "button",
3163
+ {
3164
+ type: "button",
3165
+ tabIndex: -1,
3166
+ onClick: handleIncrement,
3167
+ disabled: disabled || !canIncrement,
3168
+ className: cn(
3169
+ "flex items-center justify-center w-11 h-full transition-colors select-none shrink-0",
3170
+ "text-muted-foreground hover:text-foreground hover:bg-muted",
3171
+ "disabled:opacity-30 disabled:hover:bg-transparent disabled:hover:text-muted-foreground disabled:cursor-not-allowed"
3172
+ ),
3173
+ "aria-label": "Aumentar",
3174
+ children: /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: [
3175
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
3176
+ /* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
3177
+ ] })
3178
+ }
3179
+ )
3180
+ ]
3181
+ }
3182
+ ),
3183
+ label && /* @__PURE__ */ jsxs(
3184
+ "label",
3185
+ {
3186
+ className: cn(
3187
+ "absolute left-3 top-[-6px] text-xs font-medium bg-background px-1 cursor-pointer inline-flex items-center gap-1",
3188
+ error ? "text-red-500" : "text-foreground"
3189
+ ),
3190
+ onClick: () => inputRef.current?.focus(),
3191
+ children: [
3192
+ label,
3193
+ required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-0.5", children: "*" }),
3194
+ labelSuffix
3195
+ ]
3196
+ }
3197
+ )
3198
+ ] });
3199
+ }
3200
+ );
3201
+ NumberStepper.displayName = "NumberStepper";
3045
3202
  var switchVariants = cva(
3046
3203
  [
3047
3204
  "peer inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent",
@@ -4566,6 +4723,55 @@ function FormRadioGroup({
4566
4723
  ) });
4567
4724
  }
4568
4725
  FormRadioGroup.displayName = "Form.RadioGroup";
4726
+ function FormNumberStepper({
4727
+ name,
4728
+ label,
4729
+ description,
4730
+ tooltip,
4731
+ required,
4732
+ disabled,
4733
+ className,
4734
+ min = 0,
4735
+ max,
4736
+ step = 0.5,
4737
+ defaultValue,
4738
+ hideError = false
4739
+ }) {
4740
+ const form = useFormContext();
4741
+ const fieldState = form.getFieldState(name, form.formState);
4742
+ const error = fieldState.error?.message;
4743
+ return /* @__PURE__ */ jsx(FormFieldProvider, { name, children: /* @__PURE__ */ jsx(
4744
+ Controller,
4745
+ {
4746
+ control: form.control,
4747
+ name,
4748
+ render: ({ field }) => /* @__PURE__ */ jsxs("div", { className: cn("space-y-1", className), children: [
4749
+ /* @__PURE__ */ jsx(
4750
+ NumberStepper,
4751
+ {
4752
+ ref: field.ref,
4753
+ name: field.name,
4754
+ value: typeof field.value === "number" ? field.value : 0,
4755
+ onChange: field.onChange,
4756
+ onBlur: field.onBlur,
4757
+ min,
4758
+ max,
4759
+ step,
4760
+ defaultValue,
4761
+ label,
4762
+ required,
4763
+ disabled,
4764
+ error: !!error,
4765
+ labelSuffix: tooltip ? /* @__PURE__ */ jsx(FieldTooltipIcon, { tooltip }) : void 0
4766
+ }
4767
+ ),
4768
+ description && !error && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground px-1", children: description }),
4769
+ !hideError && error && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-500 px-1", children: error })
4770
+ ] })
4771
+ }
4772
+ ) });
4773
+ }
4774
+ FormNumberStepper.displayName = "Form.NumberStepper";
4569
4775
  function FormRoot({
4570
4776
  form,
4571
4777
  onSubmit,
@@ -4594,6 +4800,7 @@ var Form = Object.assign(FormRoot, {
4594
4800
  Checkbox: FormCheckbox,
4595
4801
  Switch: FormSwitch,
4596
4802
  RadioGroup: FormRadioGroup,
4803
+ NumberStepper: FormNumberStepper,
4597
4804
  // Partes auxiliares
4598
4805
  Label: FormLabel,
4599
4806
  Description: FormDescription,
@@ -8987,6 +9194,6 @@ var THEME_INFO = {
8987
9194
  }
8988
9195
  };
8989
9196
 
8990
- export { AuthLayout, Avatar, AvatarFallback, AvatarImage, Badge, BigNumberCard, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, DENSITY_CONFIG, DashboardLayout, DataTable, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DialogWrapper, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, FACTER_THEMES, FloatingBarCompound as FloatingBar, FloatingBarAction, FloatingBarCounter, FloatingBarDivider, FloatingBarIconAction, Form, FormCheckbox, FormDescription, FormError, FormFieldProvider, FormFieldWrapper, FormInput, FormLabel, FormRadioGroup, FormSelect, FormSwitch, FormTextarea, GlobalLoaderController, Input, ItemCard, ItemCardActionButton, ItemCardActions, ItemCardActionsRow, ItemCardBadge, ItemCardContent, ItemCardContentItem, ItemCardEmpty, ItemCardFooter, ItemCardFooterDivider, ItemCardFooterItem, ItemCardHeader, ItemCardIcon, ItemCardRoot, ItemCardSubtitle, ItemCardTitle, ItemCardTitleGroup, Kanban, Loader, LoaderProvider, Logo, MobileNav, MobileNavItem, Navbar, NavbarCompanyProfile, NavbarNotification, NavbarUserMenu, PageHeader, Popover, PopoverContent, PopoverTrigger, RippleBackground, RippleEffect, RippleWrapper, ScrollArea, ScrollBar, SectionHeader, SectionHeaderActions, SectionHeaderBadge, SectionHeaderContent, SectionHeaderIcon, SectionHeaderRoot, SectionHeaderSubtitle, SectionHeaderTitle, Select, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectionLayout, Separator3 as Separator, Sidebar, SimpleTooltip, Skeleton, Sparkline, StatsCard, Switch, THEME_INFO, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ThemeProvider, ThemeToggle, Toaster, Tooltip, TooltipAction, TooltipActions, TooltipArrow, TooltipContent, TooltipDescription, TooltipHeader, TooltipIcon, TooltipPortal, TooltipProvider, TooltipRoot, TooltipTitle, TooltipTrigger, Wizard, WizardContent, WizardNavigation, WizardPanel, WizardProgress, WizardProvider, WizardStepConnector, WizardStepIndicator, WizardSteps, cn, itemCardBadgeVariants, itemCardIconVariants, itemCardVariants, loader, toast, useAutoPageSize, useAvailableHeight, useDashboardLayout, useDataTable, useDataTableColumnVisibility, useDataTableDensity, useDataTableEmpty, useDataTableInstance, useDataTableLoading, useDataTableMeta, useDataTablePagination, useDataTableSelection, useDataTableSorting, useDataTableState, useDebounce, useDebouncedCallback, useFormFieldContext, useItemCard, useKanban, useKanbanOptional, useLoader, useMediaQuery2 as useMediaQuery, useSidebar, useSidebarOptional, useTheme, useWizardContext, useWizardContextOptional };
9197
+ export { AuthLayout, Avatar, AvatarFallback, AvatarImage, Badge, BigNumberCard, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, DENSITY_CONFIG, DashboardLayout, DataTable, Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DialogWrapper, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, FACTER_THEMES, FloatingBarCompound as FloatingBar, FloatingBarAction, FloatingBarCounter, FloatingBarDivider, FloatingBarIconAction, Form, FormCheckbox, FormDescription, FormError, FormFieldProvider, FormFieldWrapper, FormInput, FormLabel, FormMultiSelect, FormNumberStepper, FormRadioGroup, FormSelect, FormSwitch, FormTextarea, GlobalLoaderController, Input, ItemCard, ItemCardActionButton, ItemCardActions, ItemCardActionsRow, ItemCardBadge, ItemCardContent, ItemCardContentItem, ItemCardEmpty, ItemCardFooter, ItemCardFooterDivider, ItemCardFooterItem, ItemCardHeader, ItemCardIcon, ItemCardRoot, ItemCardSubtitle, ItemCardTitle, ItemCardTitleGroup, Kanban, Loader, LoaderProvider, Logo, MobileNav, MobileNavItem, Navbar, NavbarCompanyProfile, NavbarNotification, NavbarUserMenu, NumberStepper, PageHeader, Popover, PopoverContent, PopoverTrigger, RippleBackground, RippleEffect, RippleWrapper, ScrollArea, ScrollBar, SectionHeader, SectionHeaderActions, SectionHeaderBadge, SectionHeaderContent, SectionHeaderIcon, SectionHeaderRoot, SectionHeaderSubtitle, SectionHeaderTitle, Select, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectionLayout, Separator3 as Separator, Sidebar, SimpleTooltip, Skeleton, Sparkline, StatsCard, Switch, THEME_INFO, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ThemeProvider, ThemeToggle, Toaster, Tooltip, TooltipAction, TooltipActions, TooltipArrow, TooltipContent, TooltipDescription, TooltipHeader, TooltipIcon, TooltipPortal, TooltipProvider, TooltipRoot, TooltipTitle, TooltipTrigger, Wizard, WizardContent, WizardNavigation, WizardPanel, WizardProgress, WizardProvider, WizardStepConnector, WizardStepIndicator, WizardSteps, cn, itemCardBadgeVariants, itemCardIconVariants, itemCardVariants, loader, toast, useAutoPageSize, useAvailableHeight, useDashboardLayout, useDataTable, useDataTableColumnVisibility, useDataTableDensity, useDataTableEmpty, useDataTableInstance, useDataTableLoading, useDataTableMeta, useDataTablePagination, useDataTableSelection, useDataTableSorting, useDataTableState, useDebounce, useDebouncedCallback, useFormFieldContext, useItemCard, useKanban, useKanbanOptional, useLoader, useMediaQuery2 as useMediaQuery, useSidebar, useSidebarOptional, useTheme, useWizardContext, useWizardContextOptional };
8991
9198
  //# sourceMappingURL=index.mjs.map
8992
9199
  //# sourceMappingURL=index.mjs.map