@facter/ds-core 1.33.11 → 1.34.1

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.js CHANGED
@@ -16,12 +16,11 @@ var DialogPrimitive = require('@radix-ui/react-dialog');
16
16
  var sonner = require('sonner');
17
17
  var SwitchPrimitives = require('@radix-ui/react-switch');
18
18
  var reactHookForm = require('react-hook-form');
19
- var reactDom = require('react-dom');
19
+ var TooltipPrimitive = require('@radix-ui/react-tooltip');
20
+ var PopoverPrimitive = require('@radix-ui/react-popover');
20
21
  var RadioGroupPrimitive = require('@radix-ui/react-radio-group');
21
22
  var AvatarPrimitive = require('@radix-ui/react-avatar');
22
23
  var DropdownMenuPrimitive = require('@radix-ui/react-dropdown-menu');
23
- var PopoverPrimitive = require('@radix-ui/react-popover');
24
- var TooltipPrimitive = require('@radix-ui/react-tooltip');
25
24
  var ScrollAreaPrimitive = require('@radix-ui/react-scroll-area');
26
25
  var SeparatorPrimitive = require('@radix-ui/react-separator');
27
26
  var reactSlot = require('@radix-ui/react-slot');
@@ -51,11 +50,11 @@ var TabsPrimitive__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitive);
51
50
  var CheckboxPrimitive__namespace = /*#__PURE__*/_interopNamespace(CheckboxPrimitive);
52
51
  var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
53
52
  var SwitchPrimitives__namespace = /*#__PURE__*/_interopNamespace(SwitchPrimitives);
53
+ var TooltipPrimitive__namespace = /*#__PURE__*/_interopNamespace(TooltipPrimitive);
54
+ var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
54
55
  var RadioGroupPrimitive__namespace = /*#__PURE__*/_interopNamespace(RadioGroupPrimitive);
55
56
  var AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespace(AvatarPrimitive);
56
57
  var DropdownMenuPrimitive__namespace = /*#__PURE__*/_interopNamespace(DropdownMenuPrimitive);
57
- var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
58
- var TooltipPrimitive__namespace = /*#__PURE__*/_interopNamespace(TooltipPrimitive);
59
58
  var ScrollAreaPrimitive__namespace = /*#__PURE__*/_interopNamespace(ScrollAreaPrimitive);
60
59
  var SeparatorPrimitive__namespace = /*#__PURE__*/_interopNamespace(SeparatorPrimitive);
61
60
 
@@ -64,7 +63,7 @@ function cn(...inputs) {
64
63
  return tailwindMerge.twMerge(clsx.clsx(inputs));
65
64
  }
66
65
  var buttonVariants = classVarianceAuthority.cva(
67
- "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50",
66
+ "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-70",
68
67
  {
69
68
  variants: {
70
69
  variant: {
@@ -197,6 +196,7 @@ var Input = React10__namespace.forwardRef(
197
196
  label,
198
197
  icon: Icon2,
199
198
  required,
199
+ labelSuffix,
200
200
  containerClassName,
201
201
  labelClassName,
202
202
  ...props
@@ -241,7 +241,7 @@ var Input = React10__namespace.forwardRef(
241
241
  "label",
242
242
  {
243
243
  className: cn(
244
- "absolute left-3 top-[-6px] text-xs font-medium bg-background px-1 cursor-pointer",
244
+ "absolute left-3 top-[-6px] text-xs font-medium bg-background px-1 cursor-pointer inline-flex items-center gap-1",
245
245
  error ? "text-red-500" : "text-foreground",
246
246
  Icon2 && "left-10",
247
247
  labelClassName
@@ -249,7 +249,8 @@ var Input = React10__namespace.forwardRef(
249
249
  onClick: focusInput,
250
250
  children: [
251
251
  label,
252
- required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 ml-0.5", children: "*" })
252
+ required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 ml-0.5", children: "*" }),
253
+ labelSuffix
253
254
  ]
254
255
  }
255
256
  ),
@@ -3257,238 +3258,487 @@ function FormFieldProvider({ name, children }) {
3257
3258
  );
3258
3259
  return /* @__PURE__ */ jsxRuntime.jsx(FormFieldContext.Provider, { value, children });
3259
3260
  }
3260
- function applyMask(value, mask) {
3261
- const digits = value.replace(/\D/g, "");
3262
- switch (mask) {
3263
- case "phone":
3264
- if (digits.length <= 10) {
3265
- return digits.replace(/(\d{2})(\d{4})(\d{0,4})/, "($1) $2-$3").trim();
3266
- }
3267
- return digits.replace(/(\d{2})(\d{5})(\d{0,4})/, "($1) $2-$3").trim();
3268
- case "cpf":
3269
- return digits.replace(/(\d{3})(\d)/, "$1.$2").replace(/(\d{3})(\d)/, "$1.$2").replace(/(\d{3})(\d{1,2})$/, "$1-$2");
3270
- case "cnpj":
3271
- return digits.replace(/(\d{2})(\d)/, "$1.$2").replace(/(\d{3})(\d)/, "$1.$2").replace(/(\d{3})(\d)/, "$1/$2").replace(/(\d{4})(\d{1,2})$/, "$1-$2");
3272
- case "cep":
3273
- return digits.replace(/(\d{5})(\d{0,3})/, "$1-$2");
3274
- case "money":
3275
- if (!digits) return "";
3276
- const cents = parseInt(digits, 10) / 100;
3277
- return new Intl.NumberFormat("pt-BR", {
3278
- style: "currency",
3279
- currency: "BRL"
3280
- }).format(cents);
3281
- case "percent":
3282
- if (!digits) return "";
3283
- const percent = parseInt(digits, 10) / 100;
3284
- return `${percent.toFixed(2)}%`;
3285
- case "plate":
3286
- const upper = value.toUpperCase().replace(/[^A-Z0-9]/g, "");
3287
- if (upper.length <= 3) return upper;
3288
- if (upper.length <= 7) {
3289
- return upper.replace(/([A-Z]{3})(\d{0,1})([A-Z0-9]{0,1})(\d{0,2})/, "$1-$2$3$4");
3290
- }
3291
- return upper.slice(0, 7).replace(/([A-Z]{3})(\d{0,1})([A-Z0-9]{0,1})(\d{0,2})/, "$1-$2$3$4");
3292
- case "date":
3293
- return digits.replace(/(\d{2})(\d)/, "$1/$2").replace(/(\d{2})(\d)/, "$1/$2").slice(0, 10);
3294
- case "time":
3295
- return digits.replace(/(\d{2})(\d{0,2})/, "$1:$2").slice(0, 5);
3296
- case "datetime":
3297
- const dateTime = digits.replace(/(\d{2})(\d)/, "$1/$2").replace(/(\d{2})(\d)/, "$1/$2").replace(/(\d{4})(\d)/, "$1 $2").replace(/(\d{2})(\d{0,2})$/, "$1:$2");
3298
- return dateTime.slice(0, 16);
3299
- default:
3300
- return value;
3301
- }
3302
- }
3303
- function getMaxLength(mask) {
3304
- switch (mask) {
3305
- case "phone":
3306
- return 15;
3307
- case "cpf":
3308
- return 14;
3309
- case "cnpj":
3310
- return 18;
3311
- case "cep":
3312
- return 9;
3313
- case "plate":
3314
- return 8;
3315
- case "date":
3316
- return 10;
3317
- case "time":
3318
- return 5;
3319
- case "datetime":
3320
- return 16;
3321
- default:
3322
- return void 0;
3323
- }
3324
- }
3325
- function parseValue(displayValue, mask) {
3326
- if (!displayValue) return void 0;
3327
- switch (mask) {
3328
- case "money":
3329
- const moneyDigits = displayValue.replace(/\D/g, "");
3330
- return moneyDigits ? parseInt(moneyDigits, 10) / 100 : void 0;
3331
- case "percent":
3332
- const percentDigits = displayValue.replace(/\D/g, "");
3333
- return percentDigits ? parseInt(percentDigits, 10) / 100 : void 0;
3334
- default:
3335
- return displayValue || void 0;
3261
+ var TooltipProvider = TooltipPrimitive__namespace.Provider;
3262
+ var TooltipRoot = TooltipPrimitive__namespace.Root;
3263
+ var TooltipTrigger = TooltipPrimitive__namespace.Trigger;
3264
+ var TooltipPortal = TooltipPrimitive__namespace.Portal;
3265
+ var TooltipArrow = React10__namespace.forwardRef(({ className, variant = "light", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3266
+ TooltipPrimitive__namespace.Arrow,
3267
+ {
3268
+ ref,
3269
+ className: cn(
3270
+ "z-50",
3271
+ variant === "dark" ? "fill-popover" : "fill-background",
3272
+ className
3273
+ ),
3274
+ ...props
3336
3275
  }
3337
- }
3338
- function FormInput({
3339
- name,
3340
- label,
3341
- description,
3342
- required,
3343
- disabled,
3344
- className,
3345
- mask,
3346
- icon,
3347
- showPasswordToggle = true,
3348
- inputSize = "default",
3349
- hideError = false,
3350
- type = "text",
3351
- maxLength,
3352
- ...inputProps
3353
- }) {
3354
- const form = reactHookForm.useFormContext();
3355
- const fieldState = form.getFieldState(name, form.formState);
3356
- const error = fieldState.error?.message;
3357
- const getInputType = React10__namespace.useCallback(() => {
3358
- if (["money", "percent", "phone", "cpf", "cnpj", "cep"].includes(mask || "")) {
3359
- return "tel";
3360
- }
3361
- return type;
3362
- }, [mask, type]);
3363
- return /* @__PURE__ */ jsxRuntime.jsx(FormFieldProvider, { name, children: /* @__PURE__ */ jsxRuntime.jsx(
3364
- reactHookForm.Controller,
3365
- {
3366
- control: form.control,
3367
- name,
3368
- render: ({ field }) => {
3369
- const getDisplayValue = () => {
3370
- if (field.value === void 0 || field.value === null) return "";
3371
- if (mask) {
3372
- return applyMask(String(field.value), mask);
3373
- }
3374
- return String(field.value);
3375
- };
3376
- const handleChange = (e) => {
3377
- let newValue = e.target.value;
3378
- if (mask) {
3379
- newValue = applyMask(newValue, mask);
3380
- const parsed = parseValue(newValue, mask);
3381
- field.onChange(parsed);
3382
- } else {
3383
- field.onChange(newValue || void 0);
3384
- }
3385
- };
3386
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-1", className), children: [
3387
- /* @__PURE__ */ jsxRuntime.jsx(
3388
- Input,
3389
- {
3390
- ...inputProps,
3391
- ref: field.ref,
3392
- name: field.name,
3393
- value: getDisplayValue(),
3394
- onChange: handleChange,
3395
- onBlur: field.onBlur,
3396
- disabled,
3397
- type: getInputType(),
3398
- label,
3399
- required,
3400
- error: !!error,
3401
- icon,
3402
- inputSize,
3403
- maxLength: maxLength ?? getMaxLength(mask)
3404
- }
3405
- ),
3406
- description && !error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground px-1", children: description }),
3407
- !hideError && error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500 px-1", children: error })
3408
- ] });
3276
+ ));
3277
+ TooltipArrow.displayName = "TooltipArrow";
3278
+ var tooltipContentVariants = classVarianceAuthority.cva(
3279
+ "z-50 overflow-hidden rounded-lg shadow-lg outline-none animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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",
3280
+ {
3281
+ variants: {
3282
+ variant: {
3283
+ light: "bg-background text-foreground border border-border",
3284
+ dark: "bg-popover text-popover-foreground border border-border"
3285
+ },
3286
+ size: {
3287
+ sm: "max-w-[200px] p-2",
3288
+ md: "max-w-[280px] p-3",
3289
+ lg: "max-w-[360px] p-4"
3409
3290
  }
3291
+ },
3292
+ defaultVariants: {
3293
+ variant: "light",
3294
+ size: "md"
3410
3295
  }
3411
- ) });
3412
- }
3413
- FormInput.displayName = "Form.Input";
3414
- function FormSelect({
3415
- name,
3416
- label,
3417
- description,
3418
- required,
3419
- disabled,
3420
- className,
3421
- options,
3422
- placeholder = "Selecione...",
3423
- icon,
3424
- hideError = false,
3425
- selectSize = "default",
3426
- emptyText = "Nenhuma op\xE7\xE3o dispon\xEDvel",
3427
- loading = false,
3428
- variant = "default",
3429
- searchable = false,
3430
- onSearch,
3431
- onLoadMore,
3432
- hasMore,
3433
- searchPlaceholder = "Buscar..."
3434
- }) {
3435
- const form = reactHookForm.useFormContext();
3436
- const fieldState = form.getFieldState(name, form.formState);
3437
- const error = fieldState.error?.message;
3438
- return /* @__PURE__ */ jsxRuntime.jsx(FormFieldProvider, { name, children: /* @__PURE__ */ jsxRuntime.jsx(
3439
- reactHookForm.Controller,
3296
+ }
3297
+ );
3298
+ var TooltipContent = React10__namespace.forwardRef(
3299
+ ({
3300
+ className,
3301
+ variant = "light",
3302
+ size = "md",
3303
+ sideOffset = 8,
3304
+ showArrow = true,
3305
+ onDismiss,
3306
+ children,
3307
+ ...props
3308
+ }, ref) => /* @__PURE__ */ jsxRuntime.jsx(TooltipPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
3309
+ TooltipPrimitive__namespace.Content,
3440
3310
  {
3441
- control: form.control,
3442
- name,
3443
- render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-1", className), children: [
3444
- variant === "card" ? /* @__PURE__ */ jsxRuntime.jsx(
3445
- CardSelect,
3311
+ ref,
3312
+ sideOffset,
3313
+ className: cn(tooltipContentVariants({ variant, size }), className),
3314
+ ...props,
3315
+ children: [
3316
+ onDismiss && /* @__PURE__ */ jsxRuntime.jsx(
3317
+ "button",
3446
3318
  {
3447
- options,
3448
- value: field.value,
3449
- onChange: (v) => field.onChange(v || void 0),
3450
- disabled,
3451
- label,
3452
- required,
3453
- error: !!error,
3454
- placeholder,
3455
- searchable,
3456
- onSearch,
3457
- onLoadMore,
3458
- hasMore,
3459
- loading,
3460
- emptyText,
3461
- searchPlaceholder
3319
+ onClick: onDismiss,
3320
+ className: "absolute top-2 right-2 p-1 rounded-full transition-colors hover:bg-muted text-muted-foreground hover:text-foreground",
3321
+ "aria-label": "Fechar",
3322
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-3.5 w-3.5" })
3462
3323
  }
3463
- ) : /* @__PURE__ */ jsxRuntime.jsx(
3464
- Select,
3324
+ ),
3325
+ children,
3326
+ showArrow && /* @__PURE__ */ jsxRuntime.jsx(TooltipArrow, { variant: variant ?? "light", width: 12, height: 6 })
3327
+ ]
3328
+ }
3329
+ ) })
3330
+ );
3331
+ TooltipContent.displayName = TooltipPrimitive__namespace.Content.displayName;
3332
+ var TooltipHeader = React10__namespace.forwardRef(
3333
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex flex-col gap-1", className), ...props })
3334
+ );
3335
+ TooltipHeader.displayName = "TooltipHeader";
3336
+ var TooltipTitle = React10__namespace.forwardRef(
3337
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3338
+ "h4",
3339
+ {
3340
+ ref,
3341
+ className: cn("text-sm font-semibold leading-tight", className),
3342
+ ...props
3343
+ }
3344
+ )
3345
+ );
3346
+ TooltipTitle.displayName = "TooltipTitle";
3347
+ var TooltipDescription = React10__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3348
+ "p",
3349
+ {
3350
+ ref,
3351
+ className: cn("text-xs leading-relaxed text-muted-foreground", className),
3352
+ ...props
3353
+ }
3354
+ ));
3355
+ TooltipDescription.displayName = "TooltipDescription";
3356
+ var TooltipActions = React10__namespace.forwardRef(
3357
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3358
+ "div",
3359
+ {
3360
+ ref,
3361
+ className: cn("flex items-center gap-2 mt-3", className),
3362
+ ...props
3363
+ }
3364
+ )
3365
+ );
3366
+ TooltipActions.displayName = "TooltipActions";
3367
+ var tooltipActionVariants = classVarianceAuthority.cva(
3368
+ "inline-flex items-center justify-center text-xs font-medium rounded-md transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
3369
+ {
3370
+ variants: {
3371
+ variant: {
3372
+ primary: "bg-primary text-primary-foreground hover:bg-primary/90 px-3 py-1.5",
3373
+ secondary: "bg-transparent text-muted-foreground hover:text-foreground hover:underline px-2 py-1.5",
3374
+ outline: "border border-border bg-background text-foreground hover:bg-muted px-3 py-1.5"
3375
+ }
3376
+ },
3377
+ defaultVariants: {
3378
+ variant: "primary"
3379
+ }
3380
+ }
3381
+ );
3382
+ var TooltipAction = React10__namespace.forwardRef(
3383
+ ({ className, variant = "primary", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3384
+ "button",
3385
+ {
3386
+ ref,
3387
+ className: cn(tooltipActionVariants({ variant }), className),
3388
+ ...props
3389
+ }
3390
+ )
3391
+ );
3392
+ TooltipAction.displayName = "TooltipAction";
3393
+ var TooltipIcon = React10__namespace.forwardRef(
3394
+ ({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
3395
+ "div",
3396
+ {
3397
+ ref,
3398
+ className: cn(
3399
+ "flex items-center justify-center w-10 h-10 rounded-full mb-3 bg-muted",
3400
+ className
3401
+ ),
3402
+ ...props,
3403
+ children
3404
+ }
3405
+ )
3406
+ );
3407
+ TooltipIcon.displayName = "TooltipIcon";
3408
+ var SimpleTooltip = ({
3409
+ children,
3410
+ content,
3411
+ variant = "light",
3412
+ side = "top",
3413
+ align = "center",
3414
+ delayDuration = 200,
3415
+ open,
3416
+ defaultOpen,
3417
+ onOpenChange
3418
+ }) => /* @__PURE__ */ jsxRuntime.jsxs(
3419
+ TooltipRoot,
3420
+ {
3421
+ open,
3422
+ defaultOpen,
3423
+ onOpenChange,
3424
+ delayDuration,
3425
+ children: [
3426
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children }),
3427
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { variant, side, align, size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", children: content }) })
3428
+ ]
3429
+ }
3430
+ );
3431
+ SimpleTooltip.displayName = "SimpleTooltip";
3432
+ var Tooltip = Object.assign(TooltipRoot, {
3433
+ Provider: TooltipProvider,
3434
+ Trigger: TooltipTrigger,
3435
+ Portal: TooltipPortal,
3436
+ Content: TooltipContent,
3437
+ Arrow: TooltipArrow,
3438
+ Header: TooltipHeader,
3439
+ Title: TooltipTitle,
3440
+ Description: TooltipDescription,
3441
+ Actions: TooltipActions,
3442
+ Action: TooltipAction,
3443
+ Icon: TooltipIcon,
3444
+ Simple: SimpleTooltip
3445
+ });
3446
+ var FormLabel = React10__namespace.forwardRef(
3447
+ ({ className, required, children, ...props }, ref) => {
3448
+ const fieldContext = useFormFieldContextOptional();
3449
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3450
+ "label",
3451
+ {
3452
+ ref,
3453
+ htmlFor: fieldContext?.id,
3454
+ className: cn(
3455
+ "text-sm font-medium leading-none",
3456
+ fieldContext?.error && "text-red-500",
3457
+ className
3458
+ ),
3459
+ ...props,
3460
+ children: [
3461
+ children,
3462
+ (required || fieldContext?.isRequired) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 ml-0.5", children: "*" })
3463
+ ]
3464
+ }
3465
+ );
3466
+ }
3467
+ );
3468
+ FormLabel.displayName = "Form.Label";
3469
+ var FormDescription = React10__namespace.forwardRef(({ className, ...props }, ref) => {
3470
+ const fieldContext = useFormFieldContextOptional();
3471
+ if (fieldContext?.error) {
3472
+ return null;
3473
+ }
3474
+ return /* @__PURE__ */ jsxRuntime.jsx(
3475
+ "p",
3476
+ {
3477
+ ref,
3478
+ className: cn("text-xs text-muted-foreground", className),
3479
+ ...props
3480
+ }
3481
+ );
3482
+ });
3483
+ FormDescription.displayName = "Form.Description";
3484
+ var FormError = React10__namespace.forwardRef(
3485
+ ({ className, message, children, ...props }, ref) => {
3486
+ const fieldContext = useFormFieldContextOptional();
3487
+ const errorMessage = message ?? fieldContext?.error;
3488
+ if (!errorMessage && !children) {
3489
+ return null;
3490
+ }
3491
+ return /* @__PURE__ */ jsxRuntime.jsx(
3492
+ "p",
3493
+ {
3494
+ ref,
3495
+ className: cn("text-xs text-red-500", className),
3496
+ ...props,
3497
+ children: children || errorMessage
3498
+ }
3499
+ );
3500
+ }
3501
+ );
3502
+ FormError.displayName = "Form.Error";
3503
+ var FormFieldWrapper = React10__namespace.forwardRef(({ className, label, description, required, error, children, ...props }, ref) => {
3504
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn("space-y-1", className), ...props, children: [
3505
+ label && /* @__PURE__ */ jsxRuntime.jsx(FormLabel, { required, children: label }),
3506
+ children,
3507
+ description && /* @__PURE__ */ jsxRuntime.jsx(FormDescription, { children: description }),
3508
+ error && /* @__PURE__ */ jsxRuntime.jsx(FormError, { message: error })
3509
+ ] });
3510
+ });
3511
+ FormFieldWrapper.displayName = "Form.FieldWrapper";
3512
+ function FieldTooltipIcon({ tooltip }) {
3513
+ return /* @__PURE__ */ jsxRuntime.jsxs(TooltipRoot, { delayDuration: 200, children: [
3514
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, { className: "h-3 w-3 text-primary cursor-help shrink-0" }) }),
3515
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", size: "md", children: typeof tooltip === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", children: tooltip }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
3516
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-semibold leading-snug", children: tooltip.title }),
3517
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground leading-snug", children: tooltip.description })
3518
+ ] }) })
3519
+ ] });
3520
+ }
3521
+ function applyMask(value, mask) {
3522
+ const digits = value.replace(/\D/g, "");
3523
+ switch (mask) {
3524
+ case "phone":
3525
+ if (digits.length <= 10) {
3526
+ return digits.replace(/(\d{2})(\d{4})(\d{0,4})/, "($1) $2-$3").trim();
3527
+ }
3528
+ return digits.replace(/(\d{2})(\d{5})(\d{0,4})/, "($1) $2-$3").trim();
3529
+ case "cpf":
3530
+ return digits.replace(/(\d{3})(\d)/, "$1.$2").replace(/(\d{3})(\d)/, "$1.$2").replace(/(\d{3})(\d{1,2})$/, "$1-$2");
3531
+ case "cnpj":
3532
+ return digits.replace(/(\d{2})(\d)/, "$1.$2").replace(/(\d{3})(\d)/, "$1.$2").replace(/(\d{3})(\d)/, "$1/$2").replace(/(\d{4})(\d{1,2})$/, "$1-$2");
3533
+ case "cep":
3534
+ return digits.replace(/(\d{5})(\d{0,3})/, "$1-$2");
3535
+ case "money":
3536
+ if (!digits) return "";
3537
+ const cents = parseInt(digits, 10) / 100;
3538
+ return new Intl.NumberFormat("pt-BR", {
3539
+ style: "currency",
3540
+ currency: "BRL"
3541
+ }).format(cents);
3542
+ case "percent":
3543
+ if (!digits) return "";
3544
+ const percent = parseInt(digits, 10) / 100;
3545
+ return `${percent.toFixed(2)}%`;
3546
+ case "plate":
3547
+ const upper = value.toUpperCase().replace(/[^A-Z0-9]/g, "");
3548
+ if (upper.length <= 3) return upper;
3549
+ if (upper.length <= 7) {
3550
+ return upper.replace(/([A-Z]{3})(\d{0,1})([A-Z0-9]{0,1})(\d{0,2})/, "$1-$2$3$4");
3551
+ }
3552
+ return upper.slice(0, 7).replace(/([A-Z]{3})(\d{0,1})([A-Z0-9]{0,1})(\d{0,2})/, "$1-$2$3$4");
3553
+ case "date":
3554
+ return digits.replace(/(\d{2})(\d)/, "$1/$2").replace(/(\d{2})(\d)/, "$1/$2").slice(0, 10);
3555
+ case "time":
3556
+ return digits.replace(/(\d{2})(\d{0,2})/, "$1:$2").slice(0, 5);
3557
+ case "datetime":
3558
+ const dateTime = digits.replace(/(\d{2})(\d)/, "$1/$2").replace(/(\d{2})(\d)/, "$1/$2").replace(/(\d{4})(\d)/, "$1 $2").replace(/(\d{2})(\d{0,2})$/, "$1:$2");
3559
+ return dateTime.slice(0, 16);
3560
+ default:
3561
+ return value;
3562
+ }
3563
+ }
3564
+ function getMaxLength(mask) {
3565
+ switch (mask) {
3566
+ case "phone":
3567
+ return 15;
3568
+ case "cpf":
3569
+ return 14;
3570
+ case "cnpj":
3571
+ return 18;
3572
+ case "cep":
3573
+ return 9;
3574
+ case "plate":
3575
+ return 8;
3576
+ case "date":
3577
+ return 10;
3578
+ case "time":
3579
+ return 5;
3580
+ case "datetime":
3581
+ return 16;
3582
+ default:
3583
+ return void 0;
3584
+ }
3585
+ }
3586
+ function parseValue(displayValue, mask) {
3587
+ if (!displayValue) return void 0;
3588
+ switch (mask) {
3589
+ case "money":
3590
+ const moneyDigits = displayValue.replace(/\D/g, "");
3591
+ return moneyDigits ? parseInt(moneyDigits, 10) / 100 : void 0;
3592
+ case "percent":
3593
+ const percentDigits = displayValue.replace(/\D/g, "");
3594
+ return percentDigits ? parseInt(percentDigits, 10) / 100 : void 0;
3595
+ default:
3596
+ return displayValue || void 0;
3597
+ }
3598
+ }
3599
+ function FormInput({
3600
+ name,
3601
+ label,
3602
+ description,
3603
+ tooltip,
3604
+ required,
3605
+ disabled,
3606
+ className,
3607
+ mask,
3608
+ icon,
3609
+ showPasswordToggle = true,
3610
+ inputSize = "default",
3611
+ hideError = false,
3612
+ type = "text",
3613
+ maxLength,
3614
+ ...inputProps
3615
+ }) {
3616
+ const form = reactHookForm.useFormContext();
3617
+ const fieldState = form.getFieldState(name, form.formState);
3618
+ const error = fieldState.error?.message;
3619
+ const getInputType = React10__namespace.useCallback(() => {
3620
+ if (["money", "percent", "phone", "cpf", "cnpj", "cep"].includes(mask || "")) {
3621
+ return "tel";
3622
+ }
3623
+ return type;
3624
+ }, [mask, type]);
3625
+ return /* @__PURE__ */ jsxRuntime.jsx(FormFieldProvider, { name, children: /* @__PURE__ */ jsxRuntime.jsx(
3626
+ reactHookForm.Controller,
3627
+ {
3628
+ control: form.control,
3629
+ name,
3630
+ render: ({ field }) => {
3631
+ const getDisplayValue = () => {
3632
+ if (field.value === void 0 || field.value === null) return "";
3633
+ if (mask) {
3634
+ return applyMask(String(field.value), mask);
3635
+ }
3636
+ return String(field.value);
3637
+ };
3638
+ const handleChange = (e) => {
3639
+ let newValue = e.target.value;
3640
+ if (mask) {
3641
+ newValue = applyMask(newValue, mask);
3642
+ const parsed = parseValue(newValue, mask);
3643
+ field.onChange(parsed);
3644
+ } else {
3645
+ field.onChange(newValue || void 0);
3646
+ }
3647
+ };
3648
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-1", className), children: [
3649
+ /* @__PURE__ */ jsxRuntime.jsx(
3650
+ Input,
3651
+ {
3652
+ ...inputProps,
3653
+ ref: field.ref,
3654
+ name: field.name,
3655
+ value: getDisplayValue(),
3656
+ onChange: handleChange,
3657
+ onBlur: field.onBlur,
3658
+ disabled,
3659
+ type: getInputType(),
3660
+ label,
3661
+ required,
3662
+ error: !!error,
3663
+ icon,
3664
+ inputSize,
3665
+ maxLength: maxLength ?? getMaxLength(mask),
3666
+ labelSuffix: tooltip ? /* @__PURE__ */ jsxRuntime.jsx(FieldTooltipIcon, { tooltip }) : void 0
3667
+ }
3668
+ ),
3669
+ description && !error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground px-1", children: description }),
3670
+ !hideError && error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500 px-1", children: error })
3671
+ ] });
3672
+ }
3673
+ }
3674
+ ) });
3675
+ }
3676
+ FormInput.displayName = "Form.Input";
3677
+ var Popover = PopoverPrimitive__namespace.Root;
3678
+ var PopoverTrigger = PopoverPrimitive__namespace.Trigger;
3679
+ var PopoverContent = React10__namespace.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
3680
+ PopoverPrimitive__namespace.Content,
3681
+ {
3682
+ ref,
3683
+ align,
3684
+ sideOffset,
3685
+ className: cn(
3686
+ "z-50 w-auto rounded-md border bg-popover p-4 text-popover-foreground shadow-lg outline-none 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",
3687
+ className
3688
+ ),
3689
+ ...props
3690
+ }
3691
+ ) }));
3692
+ PopoverContent.displayName = PopoverPrimitive__namespace.Content.displayName;
3693
+ function FormSelect({
3694
+ name,
3695
+ label,
3696
+ description,
3697
+ tooltip,
3698
+ required,
3699
+ disabled,
3700
+ className,
3701
+ options,
3702
+ placeholder = "Selecione...",
3703
+ hideError = false,
3704
+ emptyText = "Nenhuma op\xE7\xE3o dispon\xEDvel",
3705
+ loading = false,
3706
+ searchable = false,
3707
+ onSearch,
3708
+ onLoadMore,
3709
+ hasMore,
3710
+ searchPlaceholder = "Buscar...",
3711
+ dropdownPosition = "bottom"
3712
+ }) {
3713
+ const form = reactHookForm.useFormContext();
3714
+ const fieldState = form.getFieldState(name, form.formState);
3715
+ const error = fieldState.error?.message;
3716
+ return /* @__PURE__ */ jsxRuntime.jsx(FormFieldProvider, { name, children: /* @__PURE__ */ jsxRuntime.jsx(
3717
+ reactHookForm.Controller,
3718
+ {
3719
+ control: form.control,
3720
+ name,
3721
+ render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-1", className), children: [
3722
+ /* @__PURE__ */ jsxRuntime.jsx(
3723
+ SelectDropdown,
3465
3724
  {
3466
- value: field.value ?? "",
3467
- onValueChange: (value) => {
3468
- field.onChange(value || void 0);
3469
- },
3470
- disabled: disabled || loading,
3725
+ options,
3726
+ value: field.value,
3727
+ onChange: (v) => field.onChange(v || void 0),
3728
+ disabled,
3471
3729
  label,
3730
+ tooltip,
3472
3731
  required,
3473
3732
  error: !!error,
3474
- icon,
3475
- selectSize,
3476
3733
  placeholder,
3477
- children: loading ? /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "__loading__", disabled: true, children: "Carregando..." }) : options.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: "__empty__", disabled: true, children: emptyText }) : options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
3478
- SelectItem,
3479
- {
3480
- value: option.value,
3481
- disabled: option.disabled,
3482
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
3483
- option.icon && /* @__PURE__ */ jsxRuntime.jsx(option.icon, { className: "h-4 w-4 text-muted-foreground" }),
3484
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3485
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: option.label }),
3486
- option.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground ml-2", children: option.description })
3487
- ] })
3488
- ] })
3489
- },
3490
- option.value
3491
- ))
3734
+ searchable,
3735
+ onSearch,
3736
+ onLoadMore,
3737
+ hasMore,
3738
+ loading,
3739
+ emptyText,
3740
+ searchPlaceholder,
3741
+ dropdownPosition
3492
3742
  }
3493
3743
  ),
3494
3744
  description && !error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground px-1", children: description }),
@@ -3497,229 +3747,554 @@ function FormSelect({
3497
3747
  }
3498
3748
  ) });
3499
3749
  }
3500
- FormSelect.displayName = "Form.Select";
3501
- function CardSelect({
3750
+ FormSelect.displayName = "Form.Select";
3751
+ function SelectDropdown({
3752
+ options,
3753
+ value,
3754
+ onChange,
3755
+ disabled,
3756
+ label,
3757
+ tooltip,
3758
+ required,
3759
+ error,
3760
+ placeholder = "Selecione...",
3761
+ searchable,
3762
+ onSearch,
3763
+ onLoadMore,
3764
+ hasMore,
3765
+ loading,
3766
+ emptyText = "Nenhuma op\xE7\xE3o dispon\xEDvel",
3767
+ searchPlaceholder = "Buscar...",
3768
+ dropdownPosition = "bottom"
3769
+ }) {
3770
+ const [open, setOpen] = React10__namespace.useState(false);
3771
+ const [search, setSearch] = React10__namespace.useState("");
3772
+ const selected = options.find((o) => o.value === value);
3773
+ const contentRef = React10__namespace.useRef(null);
3774
+ const listRef = React10__namespace.useRef(null);
3775
+ const searchRef = React10__namespace.useRef(null);
3776
+ const filteredOptions = React10__namespace.useMemo(() => {
3777
+ if (!searchable || onSearch || !search) return options;
3778
+ const q = search.toLowerCase();
3779
+ return options.filter(
3780
+ (o) => o.label.toLowerCase().includes(q) || o.description?.toLowerCase().includes(q)
3781
+ );
3782
+ }, [options, search, searchable, onSearch]);
3783
+ const handleSearch = React10__namespace.useCallback(
3784
+ (val) => {
3785
+ setSearch(val);
3786
+ if (onSearch) onSearch(val);
3787
+ },
3788
+ [onSearch]
3789
+ );
3790
+ const handleOpenChange = React10__namespace.useCallback(
3791
+ (nextOpen) => {
3792
+ setOpen(nextOpen);
3793
+ if (!nextOpen) {
3794
+ setSearch("");
3795
+ if (onSearch) onSearch("");
3796
+ }
3797
+ },
3798
+ [onSearch]
3799
+ );
3800
+ const handleScroll = React10__namespace.useCallback(() => {
3801
+ if (!onLoadMore || !hasMore || loading) return;
3802
+ const el = listRef.current;
3803
+ if (!el) return;
3804
+ const { scrollTop, scrollHeight, clientHeight } = el;
3805
+ if (scrollHeight - scrollTop - clientHeight < 80) {
3806
+ onLoadMore();
3807
+ }
3808
+ }, [onLoadMore, hasMore, loading]);
3809
+ React10__namespace.useEffect(() => {
3810
+ if (!open) return;
3811
+ let cancelled = false;
3812
+ let removeHandler;
3813
+ requestAnimationFrame(() => {
3814
+ if (cancelled) return;
3815
+ const content = contentRef.current;
3816
+ const list = listRef.current;
3817
+ if (!content || !list) return;
3818
+ const handleWheel = (e) => {
3819
+ if (!content.contains(e.target)) return;
3820
+ const { scrollTop, scrollHeight, clientHeight } = list;
3821
+ if (scrollHeight <= clientHeight) return;
3822
+ e.preventDefault();
3823
+ e.stopPropagation();
3824
+ list.scrollTop = Math.max(0, Math.min(scrollTop + e.deltaY, scrollHeight - clientHeight));
3825
+ };
3826
+ document.addEventListener("wheel", handleWheel, { passive: false, capture: true });
3827
+ removeHandler = () => document.removeEventListener("wheel", handleWheel, { capture: true });
3828
+ });
3829
+ return () => {
3830
+ cancelled = true;
3831
+ removeHandler?.();
3832
+ };
3833
+ }, [open]);
3834
+ const side = dropdownPosition === "top" ? "top" : "bottom";
3835
+ const avoidCollisions = dropdownPosition === "auto";
3836
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: handleOpenChange, children: [
3837
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
3838
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
3839
+ "button",
3840
+ {
3841
+ type: "button",
3842
+ disabled,
3843
+ className: cn(
3844
+ "flex w-full items-center justify-between rounded-md border-2 bg-background px-3 text-sm transition-colors",
3845
+ "focus:outline-none focus:border-primary",
3846
+ "disabled:cursor-not-allowed disabled:opacity-50",
3847
+ label ? "h-12 pt-4 pb-2" : "h-9 py-2",
3848
+ error ? "border-red-500" : "border-border",
3849
+ open && !error && "border-primary"
3850
+ ),
3851
+ children: [
3852
+ selected ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 truncate", children: [
3853
+ selected.icon && /* @__PURE__ */ jsxRuntime.jsx(selected.icon, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
3854
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: selected.label })
3855
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: placeholder }),
3856
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: cn("h-4 w-4 shrink-0 opacity-50 transition-transform", open && "rotate-180") })
3857
+ ]
3858
+ }
3859
+ ) }),
3860
+ label && /* @__PURE__ */ jsxRuntime.jsxs(
3861
+ "label",
3862
+ {
3863
+ className: cn(
3864
+ "absolute left-3 top-[-6px] text-xs font-medium bg-background px-1 inline-flex items-center gap-1",
3865
+ tooltip ? "pointer-events-auto" : "pointer-events-none",
3866
+ error ? "text-red-500" : "text-foreground"
3867
+ ),
3868
+ children: [
3869
+ label,
3870
+ required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 ml-0.5", children: "*" }),
3871
+ tooltip && /* @__PURE__ */ jsxRuntime.jsx(FieldTooltipIcon, { tooltip })
3872
+ ]
3873
+ }
3874
+ )
3875
+ ] }),
3876
+ /* @__PURE__ */ jsxRuntime.jsxs(
3877
+ PopoverContent,
3878
+ {
3879
+ ref: contentRef,
3880
+ side,
3881
+ align: "start",
3882
+ sideOffset: 4,
3883
+ avoidCollisions,
3884
+ collisionPadding: 16,
3885
+ className: "p-0 overflow-hidden flex flex-col",
3886
+ style: {
3887
+ minWidth: "var(--radix-popover-trigger-width)",
3888
+ width: "fit-content",
3889
+ maxWidth: "var(--radix-popover-content-available-width, 100%)",
3890
+ maxHeight: "min(340px, var(--radix-popover-content-available-height, 340px))"
3891
+ },
3892
+ onOpenAutoFocus: (e) => {
3893
+ e.preventDefault();
3894
+ if (searchable) {
3895
+ setTimeout(() => searchRef.current?.focus(), 0);
3896
+ }
3897
+ },
3898
+ children: [
3899
+ searchable && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-border", children: [
3900
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
3901
+ /* @__PURE__ */ jsxRuntime.jsx(
3902
+ "input",
3903
+ {
3904
+ ref: searchRef,
3905
+ type: "text",
3906
+ value: search,
3907
+ onChange: (e) => handleSearch(e.target.value),
3908
+ placeholder: searchPlaceholder,
3909
+ className: "flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
3910
+ }
3911
+ )
3912
+ ] }),
3913
+ /* @__PURE__ */ jsxRuntime.jsx(
3914
+ "div",
3915
+ {
3916
+ ref: listRef,
3917
+ className: "overflow-y-auto overscroll-contain min-h-0 flex-1",
3918
+ onScroll: handleScroll,
3919
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-1", children: [
3920
+ filteredOptions.length === 0 && !loading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "py-4 text-center text-sm text-muted-foreground", children: emptyText }) : filteredOptions.map((option) => {
3921
+ const isSelected = value === option.value;
3922
+ const isDisabled = option.disabled || disabled;
3923
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3924
+ "button",
3925
+ {
3926
+ type: "button",
3927
+ disabled: isDisabled,
3928
+ onClick: () => {
3929
+ onChange(option.value);
3930
+ setOpen(false);
3931
+ },
3932
+ className: cn(
3933
+ "flex w-full items-center gap-2 rounded-sm px-2 text-left text-sm outline-none",
3934
+ "cursor-pointer hover:bg-accent hover:text-accent-foreground",
3935
+ isSelected && "bg-accent/50",
3936
+ isDisabled && "pointer-events-none opacity-50",
3937
+ option.description ? "py-2" : "py-1.5"
3938
+ ),
3939
+ children: [
3940
+ option.icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsxRuntime.jsx(option.icon, { className: "h-3 w-3 text-primary" }) }),
3941
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
3942
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block leading-tight", children: option.label }),
3943
+ option.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-xs leading-tight text-muted-foreground", children: option.description })
3944
+ ] }),
3945
+ isSelected && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4 shrink-0 text-primary" })
3946
+ ]
3947
+ },
3948
+ option.value
3949
+ );
3950
+ }),
3951
+ loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-3", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" }) })
3952
+ ] })
3953
+ }
3954
+ )
3955
+ ]
3956
+ }
3957
+ )
3958
+ ] });
3959
+ }
3960
+ function FormMultiSelect({
3961
+ name,
3962
+ label,
3963
+ description,
3964
+ tooltip,
3965
+ required,
3966
+ disabled,
3967
+ className,
3968
+ options,
3969
+ placeholder = "Selecione...",
3970
+ hideError = false,
3971
+ emptyText = "Nenhuma op\xE7\xE3o dispon\xEDvel",
3972
+ loading = false,
3973
+ searchable = false,
3974
+ searchPlaceholder = "Buscar...",
3975
+ clearable = true,
3976
+ maxVisibleChips = 3,
3977
+ dropdownPosition = "bottom"
3978
+ }) {
3979
+ const form = reactHookForm.useFormContext();
3980
+ const fieldState = form.getFieldState(name, form.formState);
3981
+ const error = fieldState.error?.message;
3982
+ return /* @__PURE__ */ jsxRuntime.jsx(FormFieldProvider, { name, children: /* @__PURE__ */ jsxRuntime.jsx(
3983
+ reactHookForm.Controller,
3984
+ {
3985
+ control: form.control,
3986
+ name,
3987
+ render: ({ field }) => {
3988
+ const values = Array.isArray(field.value) ? field.value : [];
3989
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-1", className), children: [
3990
+ /* @__PURE__ */ jsxRuntime.jsx(
3991
+ MultiSelectDropdown,
3992
+ {
3993
+ options,
3994
+ value: values,
3995
+ onChange: (v) => field.onChange(v),
3996
+ disabled,
3997
+ label,
3998
+ tooltip,
3999
+ required,
4000
+ error: !!error,
4001
+ placeholder,
4002
+ searchable,
4003
+ loading,
4004
+ emptyText,
4005
+ searchPlaceholder,
4006
+ clearable,
4007
+ maxVisibleChips,
4008
+ dropdownPosition
4009
+ }
4010
+ ),
4011
+ description && !error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground px-1", children: description }),
4012
+ !hideError && error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500 px-1", children: error })
4013
+ ] });
4014
+ }
4015
+ }
4016
+ ) });
4017
+ }
4018
+ FormMultiSelect.displayName = "Form.MultiSelect";
4019
+ function MultiSelectDropdown({
3502
4020
  options,
3503
4021
  value,
3504
4022
  onChange,
3505
4023
  disabled,
3506
4024
  label,
4025
+ tooltip,
3507
4026
  required,
3508
4027
  error,
3509
4028
  placeholder = "Selecione...",
3510
4029
  searchable,
3511
- onSearch,
3512
- onLoadMore,
3513
- hasMore,
3514
4030
  loading,
3515
4031
  emptyText = "Nenhuma op\xE7\xE3o dispon\xEDvel",
3516
- searchPlaceholder = "Buscar..."
4032
+ searchPlaceholder = "Buscar...",
4033
+ clearable = true,
4034
+ maxVisibleChips = 3,
4035
+ dropdownPosition = "bottom"
3517
4036
  }) {
3518
4037
  const [open, setOpen] = React10__namespace.useState(false);
3519
4038
  const [search, setSearch] = React10__namespace.useState("");
3520
- const selected = options.find((o) => o.value === value);
3521
- const containerRef = React10__namespace.useRef(null);
3522
- const dropdownRef = React10__namespace.useRef(null);
4039
+ const [computedMax, setComputedMax] = React10__namespace.useState(maxVisibleChips);
4040
+ const [prevValueKey, setPrevValueKey] = React10__namespace.useState(() => value.join(","));
4041
+ const contentRef = React10__namespace.useRef(null);
3523
4042
  const listRef = React10__namespace.useRef(null);
3524
4043
  const searchRef = React10__namespace.useRef(null);
3525
- const [dropdownPos, setDropdownPos] = React10__namespace.useState({});
4044
+ const chipsRef = React10__namespace.useRef(null);
4045
+ const selectedOptions = React10__namespace.useMemo(
4046
+ () => options.filter((o) => value.includes(o.value)),
4047
+ [options, value]
4048
+ );
4049
+ const valueKey = value.join(",");
4050
+ if (valueKey !== prevValueKey) {
4051
+ setPrevValueKey(valueKey);
4052
+ setComputedMax(maxVisibleChips);
4053
+ }
4054
+ React10__namespace.useLayoutEffect(() => {
4055
+ const container = chipsRef.current;
4056
+ if (!container || selectedOptions.length === 0) return;
4057
+ const containerRect = container.getBoundingClientRect();
4058
+ const containerWidth = containerRect.width;
4059
+ const chips = container.querySelectorAll("[data-chip]");
4060
+ if (chips.length === 0 || containerWidth === 0) return;
4061
+ const gap = 4;
4062
+ const buffer = 4;
4063
+ const badge = container.querySelector("[data-badge]");
4064
+ const badgeWidth = badge ? badge.getBoundingClientRect().width : 28;
4065
+ const availableWidth = containerWidth - buffer;
4066
+ let usedWidth = 0;
4067
+ let fits = 0;
4068
+ for (let i = 0; i < chips.length; i++) {
4069
+ const chipWidth = chips[i].getBoundingClientRect().width;
4070
+ const widthWithGap = fits > 0 ? chipWidth + gap : chipWidth;
4071
+ const remaining = selectedOptions.length - (fits + 1);
4072
+ const needsBadge = remaining > 0;
4073
+ const badgeSpace = needsBadge ? badgeWidth + gap : 0;
4074
+ if (usedWidth + widthWithGap + badgeSpace > availableWidth && fits > 0) {
4075
+ break;
4076
+ }
4077
+ usedWidth += widthWithGap;
4078
+ fits++;
4079
+ }
4080
+ const newMax = Math.max(1, fits);
4081
+ if (newMax !== computedMax) {
4082
+ setComputedMax(newMax);
4083
+ }
4084
+ });
3526
4085
  const filteredOptions = React10__namespace.useMemo(() => {
3527
- if (!searchable || onSearch || !search) return options;
4086
+ if (!searchable || !search) return options;
3528
4087
  const q = search.toLowerCase();
3529
4088
  return options.filter(
3530
4089
  (o) => o.label.toLowerCase().includes(q) || o.description?.toLowerCase().includes(q)
3531
4090
  );
3532
- }, [options, search, searchable, onSearch]);
3533
- const handleSearch = React10__namespace.useCallback(
3534
- (value2) => {
3535
- setSearch(value2);
3536
- if (onSearch) onSearch(value2);
4091
+ }, [options, search, searchable]);
4092
+ const toggleOption = React10__namespace.useCallback(
4093
+ (optionValue) => {
4094
+ if (value.includes(optionValue)) {
4095
+ onChange(value.filter((v) => v !== optionValue));
4096
+ } else {
4097
+ onChange([...value, optionValue]);
4098
+ }
3537
4099
  },
3538
- [onSearch]
4100
+ [value, onChange]
3539
4101
  );
3540
- React10__namespace.useEffect(() => {
3541
- if (!open || !containerRef.current) return;
3542
- const updatePosition = () => {
3543
- const rect = containerRef.current.getBoundingClientRect();
3544
- const spaceBelow = window.innerHeight - rect.bottom;
3545
- const estimatedHeight = 340;
3546
- const showAbove = spaceBelow < estimatedHeight && rect.top > spaceBelow;
3547
- setDropdownPos({
3548
- position: "fixed",
3549
- left: rect.left,
3550
- width: rect.width,
3551
- zIndex: 9999,
3552
- ...showAbove ? { bottom: window.innerHeight - rect.top + 4 } : { top: rect.bottom + 4 }
3553
- });
3554
- };
3555
- updatePosition();
3556
- window.addEventListener("scroll", updatePosition, true);
3557
- window.addEventListener("resize", updatePosition);
3558
- return () => {
3559
- window.removeEventListener("scroll", updatePosition, true);
3560
- window.removeEventListener("resize", updatePosition);
3561
- };
3562
- }, [open]);
3563
- React10__namespace.useEffect(() => {
3564
- if (!open) return;
3565
- const handleClickOutside = (e) => {
3566
- const target = e.target;
3567
- if (containerRef.current && !containerRef.current.contains(target) && (!dropdownRef.current || !dropdownRef.current.contains(target))) {
3568
- setOpen(false);
3569
- }
3570
- };
3571
- document.addEventListener("mousedown", handleClickOutside);
3572
- return () => document.removeEventListener("mousedown", handleClickOutside);
3573
- }, [open]);
3574
- React10__namespace.useEffect(() => {
3575
- if (!open) return;
3576
- const handleEscape = (e) => {
3577
- if (e.key === "Escape") setOpen(false);
3578
- };
3579
- document.addEventListener("keydown", handleEscape);
3580
- return () => document.removeEventListener("keydown", handleEscape);
3581
- }, [open]);
3582
- React10__namespace.useEffect(() => {
3583
- if (!open) {
4102
+ const handleClearAll = React10__namespace.useCallback(
4103
+ (e) => {
4104
+ e.stopPropagation();
4105
+ onChange([]);
4106
+ },
4107
+ [onChange]
4108
+ );
4109
+ const handleRemoveChip = React10__namespace.useCallback(
4110
+ (e, optionValue) => {
4111
+ e.stopPropagation();
4112
+ onChange(value.filter((v) => v !== optionValue));
4113
+ },
4114
+ [value, onChange]
4115
+ );
4116
+ const handleOpenChange = React10__namespace.useCallback((nextOpen) => {
4117
+ setOpen(nextOpen);
4118
+ if (!nextOpen) {
3584
4119
  setSearch("");
3585
- if (onSearch) onSearch("");
3586
- }
3587
- }, [open, onSearch]);
3588
- React10__namespace.useEffect(() => {
3589
- if (open && searchable) {
3590
- setTimeout(() => searchRef.current?.focus(), 0);
3591
4120
  }
3592
- }, [open, searchable]);
4121
+ }, []);
3593
4122
  React10__namespace.useEffect(() => {
3594
- const el = listRef.current;
3595
- if (!el || !open) return;
3596
- const handleWheel = (e) => {
3597
- const { scrollTop, scrollHeight, clientHeight } = el;
3598
- const isScrollable = scrollHeight > clientHeight;
3599
- if (!isScrollable) return;
3600
- e.preventDefault();
3601
- e.stopPropagation();
3602
- el.scrollTop = Math.max(
3603
- 0,
3604
- Math.min(scrollTop + e.deltaY, scrollHeight - clientHeight)
3605
- );
4123
+ if (!open) return;
4124
+ let cancelled = false;
4125
+ let removeHandler;
4126
+ requestAnimationFrame(() => {
4127
+ if (cancelled) return;
4128
+ const content = contentRef.current;
4129
+ const list = listRef.current;
4130
+ if (!content || !list) return;
4131
+ const handleWheel = (e) => {
4132
+ if (!content.contains(e.target)) return;
4133
+ const { scrollTop, scrollHeight, clientHeight } = list;
4134
+ if (scrollHeight <= clientHeight) return;
4135
+ e.preventDefault();
4136
+ e.stopPropagation();
4137
+ list.scrollTop = Math.max(0, Math.min(scrollTop + e.deltaY, scrollHeight - clientHeight));
4138
+ };
4139
+ document.addEventListener("wheel", handleWheel, { passive: false, capture: true });
4140
+ removeHandler = () => document.removeEventListener("wheel", handleWheel, { capture: true });
4141
+ });
4142
+ return () => {
4143
+ cancelled = true;
4144
+ removeHandler?.();
3606
4145
  };
3607
- el.addEventListener("wheel", handleWheel, { passive: false, capture: true });
3608
- return () => el.removeEventListener("wheel", handleWheel, { capture: true });
3609
- }, [open, filteredOptions]);
3610
- const handleScroll = React10__namespace.useCallback(() => {
3611
- if (!onLoadMore || !hasMore || loading) return;
3612
- const el = listRef.current;
3613
- if (!el) return;
3614
- const { scrollTop, scrollHeight, clientHeight } = el;
3615
- if (scrollHeight - scrollTop - clientHeight < 80) {
3616
- onLoadMore();
3617
- }
3618
- }, [onLoadMore, hasMore, loading]);
3619
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "relative", children: [
3620
- /* @__PURE__ */ jsxRuntime.jsxs(
3621
- "button",
3622
- {
3623
- type: "button",
3624
- disabled,
3625
- onClick: () => setOpen((prev) => !prev),
3626
- className: cn(
3627
- "flex w-full items-center justify-between rounded-md border-2 bg-background px-3 text-sm transition-colors",
3628
- "focus:outline-none focus:border-primary",
3629
- "disabled:cursor-not-allowed disabled:opacity-50",
3630
- label ? "h-12 pt-4 pb-2" : "h-9 py-2",
3631
- error ? "border-red-500" : "border-border",
3632
- open && !error && "border-primary"
3633
- ),
3634
- children: [
3635
- selected ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 truncate", children: [
3636
- selected.icon && /* @__PURE__ */ jsxRuntime.jsx(selected.icon, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
3637
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: selected.label })
3638
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: placeholder }),
3639
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: cn("h-4 w-4 shrink-0 opacity-50 transition-transform", open && "rotate-180") })
3640
- ]
3641
- }
3642
- ),
3643
- label && /* @__PURE__ */ jsxRuntime.jsxs(
3644
- "label",
3645
- {
3646
- className: cn(
3647
- "absolute left-3 top-[-6px] text-xs font-medium bg-background px-1 pointer-events-none",
3648
- error ? "text-red-500" : "text-foreground"
3649
- ),
3650
- children: [
3651
- label,
3652
- required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 ml-0.5", children: "*" })
3653
- ]
3654
- }
3655
- ),
3656
- open && reactDom.createPortal(
3657
- /* @__PURE__ */ jsxRuntime.jsxs(
3658
- "div",
4146
+ }, [open]);
4147
+ const side = dropdownPosition === "top" ? "top" : "bottom";
4148
+ const avoidCollisions = dropdownPosition === "auto";
4149
+ const visibleChips = selectedOptions.slice(0, computedMax);
4150
+ const overflowCount = selectedOptions.length - computedMax;
4151
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: handleOpenChange, children: [
4152
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
4153
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
4154
+ "button",
3659
4155
  {
3660
- ref: dropdownRef,
3661
- style: dropdownPos,
3662
- className: "rounded-md border border-border bg-popover shadow-md overflow-hidden animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-150",
4156
+ type: "button",
4157
+ disabled,
4158
+ className: cn(
4159
+ "flex w-full items-center justify-between rounded-md border-2 bg-background px-3 text-sm transition-colors",
4160
+ "focus:outline-none focus:border-primary",
4161
+ "disabled:cursor-not-allowed disabled:opacity-50",
4162
+ label ? "min-h-[3rem] pt-4 pb-1.5" : "min-h-[2.25rem] py-1.5",
4163
+ error ? "border-red-500" : "border-border",
4164
+ open && !error && "border-primary"
4165
+ ),
3663
4166
  children: [
3664
- searchable && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-border", children: [
3665
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
3666
- /* @__PURE__ */ jsxRuntime.jsx(
3667
- "input",
4167
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: chipsRef, className: "flex gap-1 items-center flex-1 overflow-hidden", children: selectedOptions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4168
+ visibleChips.map((option) => /* @__PURE__ */ jsxRuntime.jsxs(
4169
+ "span",
4170
+ {
4171
+ "data-chip": true,
4172
+ className: "inline-flex items-center gap-1 max-w-[150px] shrink-0 rounded-sm bg-primary/10 px-1.5 py-0.5 text-xs font-medium text-primary",
4173
+ children: [
4174
+ option.icon && /* @__PURE__ */ jsxRuntime.jsx(option.icon, { className: "h-3 w-3 shrink-0" }),
4175
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: option.label }),
4176
+ /* @__PURE__ */ jsxRuntime.jsx(
4177
+ lucideReact.X,
4178
+ {
4179
+ className: "h-3 w-3 shrink-0 cursor-pointer hover:text-destructive",
4180
+ onClick: (e) => handleRemoveChip(e, option.value)
4181
+ }
4182
+ )
4183
+ ]
4184
+ },
4185
+ option.value
4186
+ )),
4187
+ overflowCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { "data-badge": true, className: "inline-flex items-center justify-center h-5 min-w-5 px-1.5 shrink-0 rounded-full bg-gray-100 text-gray-500 text-[10px] font-medium", children: [
4188
+ "+",
4189
+ overflowCount
4190
+ ] })
4191
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: placeholder }) }),
4192
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 ml-1 shrink-0", children: [
4193
+ clearable && selectedOptions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
4194
+ lucideReact.X,
3668
4195
  {
3669
- ref: searchRef,
3670
- type: "text",
3671
- value: search,
3672
- onChange: (e) => handleSearch(e.target.value),
3673
- placeholder: searchPlaceholder,
3674
- className: "flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
4196
+ className: "h-4 w-4 text-muted-foreground hover:text-foreground cursor-pointer",
4197
+ onClick: handleClearAll
3675
4198
  }
3676
- )
3677
- ] }),
4199
+ ),
4200
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: cn("h-4 w-4 opacity-50 transition-transform", open && "rotate-180") })
4201
+ ] })
4202
+ ]
4203
+ }
4204
+ ) }),
4205
+ label && /* @__PURE__ */ jsxRuntime.jsxs(
4206
+ "label",
4207
+ {
4208
+ className: cn(
4209
+ "absolute left-3 top-[-6px] text-xs font-medium bg-background px-1 inline-flex items-center gap-1",
4210
+ tooltip ? "pointer-events-auto" : "pointer-events-none",
4211
+ error ? "text-red-500" : "text-foreground"
4212
+ ),
4213
+ children: [
4214
+ label,
4215
+ required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 ml-0.5", children: "*" }),
4216
+ tooltip && /* @__PURE__ */ jsxRuntime.jsx(FieldTooltipIcon, { tooltip })
4217
+ ]
4218
+ }
4219
+ )
4220
+ ] }),
4221
+ /* @__PURE__ */ jsxRuntime.jsxs(
4222
+ PopoverContent,
4223
+ {
4224
+ ref: contentRef,
4225
+ side,
4226
+ align: "start",
4227
+ sideOffset: 4,
4228
+ avoidCollisions,
4229
+ collisionPadding: 16,
4230
+ className: "p-0 overflow-hidden flex flex-col",
4231
+ style: {
4232
+ minWidth: "var(--radix-popover-trigger-width)",
4233
+ width: "fit-content",
4234
+ maxWidth: "var(--radix-popover-content-available-width, 100%)",
4235
+ maxHeight: "min(340px, var(--radix-popover-content-available-height, 340px))"
4236
+ },
4237
+ onOpenAutoFocus: (e) => {
4238
+ e.preventDefault();
4239
+ if (searchable) {
4240
+ setTimeout(() => searchRef.current?.focus(), 0);
4241
+ }
4242
+ },
4243
+ children: [
4244
+ searchable && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-border", children: [
4245
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
3678
4246
  /* @__PURE__ */ jsxRuntime.jsx(
3679
- "div",
4247
+ "input",
3680
4248
  {
3681
- ref: listRef,
3682
- className: "overflow-y-auto overscroll-contain max-h-[300px]",
3683
- onScroll: handleScroll,
3684
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "divide-y divide-border/50 p-2", children: [
3685
- filteredOptions.length === 0 && !loading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "py-4 text-center text-sm text-muted-foreground", children: emptyText }) : filteredOptions.map((option) => {
3686
- const isSelected = value === option.value;
3687
- const isDisabled = option.disabled || disabled;
3688
- return /* @__PURE__ */ jsxRuntime.jsxs(
3689
- "button",
3690
- {
3691
- type: "button",
3692
- disabled: isDisabled,
3693
- onClick: () => {
3694
- onChange(option.value);
3695
- setOpen(false);
3696
- },
3697
- className: cn(
3698
- "flex w-full items-center gap-3 p-3 text-left transition-all",
3699
- "cursor-pointer hover:bg-accent",
3700
- isSelected && "bg-primary/5",
3701
- isDisabled && "cursor-not-allowed opacity-50 hover:bg-transparent"
3702
- ),
3703
- children: [
3704
- option.icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsxRuntime.jsx(option.icon, { className: "h-3.5 w-3.5 text-primary" }) }),
3705
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
3706
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium leading-tight", children: option.label }),
3707
- option.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-xs leading-tight text-muted-foreground", children: option.description })
3708
- ] }),
3709
- isSelected && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3 w-3" }) })
3710
- ]
3711
- },
3712
- option.value
3713
- );
3714
- }),
3715
- loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-3", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" }) })
3716
- ] })
4249
+ ref: searchRef,
4250
+ type: "text",
4251
+ value: search,
4252
+ onChange: (e) => setSearch(e.target.value),
4253
+ placeholder: searchPlaceholder,
4254
+ className: "flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
3717
4255
  }
3718
4256
  )
3719
- ]
3720
- }
3721
- ),
3722
- document.body
4257
+ ] }),
4258
+ /* @__PURE__ */ jsxRuntime.jsx(
4259
+ "div",
4260
+ {
4261
+ ref: listRef,
4262
+ className: "overflow-y-auto overscroll-contain min-h-0 flex-1",
4263
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-1", children: [
4264
+ filteredOptions.length === 0 && !loading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "py-4 text-center text-sm text-muted-foreground", children: emptyText }) : filteredOptions.map((option) => {
4265
+ const isSelected = value.includes(option.value);
4266
+ const isDisabled = option.disabled || disabled;
4267
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4268
+ "button",
4269
+ {
4270
+ type: "button",
4271
+ disabled: isDisabled,
4272
+ onClick: () => toggleOption(option.value),
4273
+ className: cn(
4274
+ "flex w-full items-center gap-2 rounded-sm px-2 text-left text-sm outline-none",
4275
+ "cursor-pointer hover:bg-accent hover:text-accent-foreground",
4276
+ isSelected && "bg-accent/50",
4277
+ isDisabled && "pointer-events-none opacity-50",
4278
+ option.description ? "py-2" : "py-1.5"
4279
+ ),
4280
+ children: [
4281
+ option.icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsxRuntime.jsx(option.icon, { className: "h-3 w-3 text-primary" }) }),
4282
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
4283
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block leading-tight", children: option.label }),
4284
+ option.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-xs leading-tight text-muted-foreground", children: option.description })
4285
+ ] }),
4286
+ isSelected && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4 shrink-0 text-primary" })
4287
+ ]
4288
+ },
4289
+ option.value
4290
+ );
4291
+ }),
4292
+ loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-3", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" }) })
4293
+ ] })
4294
+ }
4295
+ )
4296
+ ]
4297
+ }
3723
4298
  )
3724
4299
  ] });
3725
4300
  }
@@ -3987,107 +4562,41 @@ function FormRadioGroup({
3987
4562
  id: optionId,
3988
4563
  value: option.value,
3989
4564
  disabled: option.disabled || disabled,
3990
- className: cn(
3991
- "aspect-square h-4 w-4 rounded-full border",
3992
- isSelected ? styles.radio : "border-border text-muted-foreground",
3993
- "ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
3994
- "disabled:cursor-not-allowed disabled:opacity-50"
3995
- ),
3996
- children: /* @__PURE__ */ jsxRuntime.jsx(RadioGroupPrimitive__namespace.Indicator, { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Circle, { className: "h-2.5 w-2.5 fill-current text-current" }) })
3997
- }
3998
- ),
3999
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-0.5 leading-none", children: [
4000
- /* @__PURE__ */ jsxRuntime.jsx(
4001
- "span",
4002
- {
4003
- className: cn(
4004
- "text-sm font-medium leading-none",
4005
- isSelected && styles.text
4006
- ),
4007
- children: option.label
4008
- }
4009
- ),
4010
- option.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: option.description })
4011
- ] })
4012
- ]
4013
- },
4014
- option.value
4015
- );
4016
- })
4017
- }
4018
- ),
4019
- !hideError && error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
4020
- ] })
4021
- }
4022
- ) });
4023
- }
4024
- FormRadioGroup.displayName = "Form.RadioGroup";
4025
- var FormLabel = React10__namespace.forwardRef(
4026
- ({ className, required, children, ...props }, ref) => {
4027
- const fieldContext = useFormFieldContextOptional();
4028
- return /* @__PURE__ */ jsxRuntime.jsxs(
4029
- "label",
4030
- {
4031
- ref,
4032
- htmlFor: fieldContext?.id,
4033
- className: cn(
4034
- "text-sm font-medium leading-none",
4035
- fieldContext?.error && "text-red-500",
4036
- className
4037
- ),
4038
- ...props,
4039
- children: [
4040
- children,
4041
- (required || fieldContext?.isRequired) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500 ml-0.5", children: "*" })
4042
- ]
4043
- }
4044
- );
4045
- }
4046
- );
4047
- FormLabel.displayName = "Form.Label";
4048
- var FormDescription = React10__namespace.forwardRef(({ className, ...props }, ref) => {
4049
- const fieldContext = useFormFieldContextOptional();
4050
- if (fieldContext?.error) {
4051
- return null;
4052
- }
4053
- return /* @__PURE__ */ jsxRuntime.jsx(
4054
- "p",
4055
- {
4056
- ref,
4057
- className: cn("text-xs text-muted-foreground", className),
4058
- ...props
4059
- }
4060
- );
4061
- });
4062
- FormDescription.displayName = "Form.Description";
4063
- var FormError = React10__namespace.forwardRef(
4064
- ({ className, message, children, ...props }, ref) => {
4065
- const fieldContext = useFormFieldContextOptional();
4066
- const errorMessage = message ?? fieldContext?.error;
4067
- if (!errorMessage && !children) {
4068
- return null;
4565
+ className: cn(
4566
+ "aspect-square h-4 w-4 rounded-full border",
4567
+ isSelected ? styles.radio : "border-border text-muted-foreground",
4568
+ "ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
4569
+ "disabled:cursor-not-allowed disabled:opacity-50"
4570
+ ),
4571
+ children: /* @__PURE__ */ jsxRuntime.jsx(RadioGroupPrimitive__namespace.Indicator, { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Circle, { className: "h-2.5 w-2.5 fill-current text-current" }) })
4572
+ }
4573
+ ),
4574
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-0.5 leading-none", children: [
4575
+ /* @__PURE__ */ jsxRuntime.jsx(
4576
+ "span",
4577
+ {
4578
+ className: cn(
4579
+ "text-sm font-medium leading-none",
4580
+ isSelected && styles.text
4581
+ ),
4582
+ children: option.label
4583
+ }
4584
+ ),
4585
+ option.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: option.description })
4586
+ ] })
4587
+ ]
4588
+ },
4589
+ option.value
4590
+ );
4591
+ })
4592
+ }
4593
+ ),
4594
+ !hideError && error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
4595
+ ] })
4069
4596
  }
4070
- return /* @__PURE__ */ jsxRuntime.jsx(
4071
- "p",
4072
- {
4073
- ref,
4074
- className: cn("text-xs text-red-500", className),
4075
- ...props,
4076
- children: children || errorMessage
4077
- }
4078
- );
4079
- }
4080
- );
4081
- FormError.displayName = "Form.Error";
4082
- var FormFieldWrapper = React10__namespace.forwardRef(({ className, label, description, required, error, children, ...props }, ref) => {
4083
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn("space-y-1", className), ...props, children: [
4084
- label && /* @__PURE__ */ jsxRuntime.jsx(FormLabel, { required, children: label }),
4085
- children,
4086
- description && /* @__PURE__ */ jsxRuntime.jsx(FormDescription, { children: description }),
4087
- error && /* @__PURE__ */ jsxRuntime.jsx(FormError, { message: error })
4088
- ] });
4089
- });
4090
- FormFieldWrapper.displayName = "Form.FieldWrapper";
4597
+ ) });
4598
+ }
4599
+ FormRadioGroup.displayName = "Form.RadioGroup";
4091
4600
  function FormRoot({
4092
4601
  form,
4093
4602
  onSubmit,
@@ -4111,6 +4620,7 @@ var Form = Object.assign(FormRoot, {
4111
4620
  // Campos com auto-bind
4112
4621
  Input: FormInput,
4113
4622
  Select: FormSelect,
4623
+ MultiSelect: FormMultiSelect,
4114
4624
  Textarea: FormTextarea,
4115
4625
  Checkbox: FormCheckbox,
4116
4626
  Switch: FormSwitch,
@@ -4284,207 +4794,6 @@ var DropdownMenuShortcut = ({
4284
4794
  );
4285
4795
  };
4286
4796
  DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
4287
- var Popover = PopoverPrimitive__namespace.Root;
4288
- var PopoverTrigger = PopoverPrimitive__namespace.Trigger;
4289
- var PopoverContent = React10__namespace.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
4290
- PopoverPrimitive__namespace.Content,
4291
- {
4292
- ref,
4293
- align,
4294
- sideOffset,
4295
- className: cn(
4296
- "z-50 w-auto rounded-md border bg-popover p-4 text-popover-foreground shadow-lg outline-none 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",
4297
- className
4298
- ),
4299
- ...props
4300
- }
4301
- ) }));
4302
- PopoverContent.displayName = PopoverPrimitive__namespace.Content.displayName;
4303
- var TooltipProvider = TooltipPrimitive__namespace.Provider;
4304
- var TooltipRoot = TooltipPrimitive__namespace.Root;
4305
- var TooltipTrigger = TooltipPrimitive__namespace.Trigger;
4306
- var TooltipPortal = TooltipPrimitive__namespace.Portal;
4307
- var TooltipArrow = React10__namespace.forwardRef(({ className, variant = "light", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4308
- TooltipPrimitive__namespace.Arrow,
4309
- {
4310
- ref,
4311
- className: cn(
4312
- "z-50",
4313
- variant === "dark" ? "fill-popover" : "fill-background",
4314
- className
4315
- ),
4316
- ...props
4317
- }
4318
- ));
4319
- TooltipArrow.displayName = "TooltipArrow";
4320
- var tooltipContentVariants = classVarianceAuthority.cva(
4321
- "z-50 overflow-hidden rounded-lg shadow-lg outline-none animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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",
4322
- {
4323
- variants: {
4324
- variant: {
4325
- light: "bg-background text-foreground border border-border",
4326
- dark: "bg-popover text-popover-foreground border border-border"
4327
- },
4328
- size: {
4329
- sm: "max-w-[200px] p-2",
4330
- md: "max-w-[280px] p-3",
4331
- lg: "max-w-[360px] p-4"
4332
- }
4333
- },
4334
- defaultVariants: {
4335
- variant: "light",
4336
- size: "md"
4337
- }
4338
- }
4339
- );
4340
- var TooltipContent = React10__namespace.forwardRef(
4341
- ({
4342
- className,
4343
- variant = "light",
4344
- size = "md",
4345
- sideOffset = 8,
4346
- showArrow = true,
4347
- onDismiss,
4348
- children,
4349
- ...props
4350
- }, ref) => /* @__PURE__ */ jsxRuntime.jsx(TooltipPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
4351
- TooltipPrimitive__namespace.Content,
4352
- {
4353
- ref,
4354
- sideOffset,
4355
- className: cn(tooltipContentVariants({ variant, size }), className),
4356
- ...props,
4357
- children: [
4358
- onDismiss && /* @__PURE__ */ jsxRuntime.jsx(
4359
- "button",
4360
- {
4361
- onClick: onDismiss,
4362
- className: "absolute top-2 right-2 p-1 rounded-full transition-colors hover:bg-muted text-muted-foreground hover:text-foreground",
4363
- "aria-label": "Fechar",
4364
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-3.5 w-3.5" })
4365
- }
4366
- ),
4367
- children,
4368
- showArrow && /* @__PURE__ */ jsxRuntime.jsx(TooltipArrow, { variant: variant ?? "light", width: 12, height: 6 })
4369
- ]
4370
- }
4371
- ) })
4372
- );
4373
- TooltipContent.displayName = TooltipPrimitive__namespace.Content.displayName;
4374
- var TooltipHeader = React10__namespace.forwardRef(
4375
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex flex-col gap-1", className), ...props })
4376
- );
4377
- TooltipHeader.displayName = "TooltipHeader";
4378
- var TooltipTitle = React10__namespace.forwardRef(
4379
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4380
- "h4",
4381
- {
4382
- ref,
4383
- className: cn("text-sm font-semibold leading-tight", className),
4384
- ...props
4385
- }
4386
- )
4387
- );
4388
- TooltipTitle.displayName = "TooltipTitle";
4389
- var TooltipDescription = React10__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4390
- "p",
4391
- {
4392
- ref,
4393
- className: cn("text-xs leading-relaxed text-muted-foreground", className),
4394
- ...props
4395
- }
4396
- ));
4397
- TooltipDescription.displayName = "TooltipDescription";
4398
- var TooltipActions = React10__namespace.forwardRef(
4399
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4400
- "div",
4401
- {
4402
- ref,
4403
- className: cn("flex items-center gap-2 mt-3", className),
4404
- ...props
4405
- }
4406
- )
4407
- );
4408
- TooltipActions.displayName = "TooltipActions";
4409
- var tooltipActionVariants = classVarianceAuthority.cva(
4410
- "inline-flex items-center justify-center text-xs font-medium rounded-md transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
4411
- {
4412
- variants: {
4413
- variant: {
4414
- primary: "bg-primary text-primary-foreground hover:bg-primary/90 px-3 py-1.5",
4415
- secondary: "bg-transparent text-muted-foreground hover:text-foreground hover:underline px-2 py-1.5",
4416
- outline: "border border-border bg-background text-foreground hover:bg-muted px-3 py-1.5"
4417
- }
4418
- },
4419
- defaultVariants: {
4420
- variant: "primary"
4421
- }
4422
- }
4423
- );
4424
- var TooltipAction = React10__namespace.forwardRef(
4425
- ({ className, variant = "primary", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4426
- "button",
4427
- {
4428
- ref,
4429
- className: cn(tooltipActionVariants({ variant }), className),
4430
- ...props
4431
- }
4432
- )
4433
- );
4434
- TooltipAction.displayName = "TooltipAction";
4435
- var TooltipIcon = React10__namespace.forwardRef(
4436
- ({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4437
- "div",
4438
- {
4439
- ref,
4440
- className: cn(
4441
- "flex items-center justify-center w-10 h-10 rounded-full mb-3 bg-muted",
4442
- className
4443
- ),
4444
- ...props,
4445
- children
4446
- }
4447
- )
4448
- );
4449
- TooltipIcon.displayName = "TooltipIcon";
4450
- var SimpleTooltip = ({
4451
- children,
4452
- content,
4453
- variant = "light",
4454
- side = "top",
4455
- align = "center",
4456
- delayDuration = 200,
4457
- open,
4458
- defaultOpen,
4459
- onOpenChange
4460
- }) => /* @__PURE__ */ jsxRuntime.jsxs(
4461
- TooltipRoot,
4462
- {
4463
- open,
4464
- defaultOpen,
4465
- onOpenChange,
4466
- delayDuration,
4467
- children: [
4468
- /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children }),
4469
- /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { variant, side, align, size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", children: content }) })
4470
- ]
4471
- }
4472
- );
4473
- SimpleTooltip.displayName = "SimpleTooltip";
4474
- var Tooltip = Object.assign(TooltipRoot, {
4475
- Provider: TooltipProvider,
4476
- Trigger: TooltipTrigger,
4477
- Portal: TooltipPortal,
4478
- Content: TooltipContent,
4479
- Arrow: TooltipArrow,
4480
- Header: TooltipHeader,
4481
- Title: TooltipTitle,
4482
- Description: TooltipDescription,
4483
- Actions: TooltipActions,
4484
- Action: TooltipAction,
4485
- Icon: TooltipIcon,
4486
- Simple: SimpleTooltip
4487
- });
4488
4797
  var AuthLayoutContext = React10__namespace.createContext({
4489
4798
  imagePosition: "left"
4490
4799
  });