@underverse-ui/underverse 1.0.80 → 1.0.82

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
@@ -6943,11 +6943,12 @@ var Combobox = ({
6943
6943
  helperText,
6944
6944
  useOverlayScrollbar = false
6945
6945
  }) => {
6946
+ const tv = useSmartTranslations("ValidationInput");
6946
6947
  const [open, setOpen] = React24.useState(false);
6947
6948
  const [query, setQuery] = React24.useState("");
6948
6949
  const [activeIndex, setActiveIndex] = React24.useState(null);
6950
+ const [localRequiredError, setLocalRequiredError] = React24.useState();
6949
6951
  useShadCNAnimations();
6950
- const listRef = React24.useRef([]);
6951
6952
  const inputRef = React24.useRef(null);
6952
6953
  const optionsViewportRef = React24.useRef(null);
6953
6954
  useOverlayScrollbarTarget(optionsViewportRef, { enabled: useOverlayScrollbar });
@@ -6964,6 +6965,7 @@ var Combobox = ({
6964
6965
  if (getOptionDisabled(option)) return;
6965
6966
  const val = getOptionValue(option);
6966
6967
  if (val !== void 0 && val !== null) {
6968
+ setLocalRequiredError(void 0);
6967
6969
  onChange(val);
6968
6970
  setOpen(false);
6969
6971
  triggerRef.current?.focus();
@@ -6987,6 +6989,13 @@ var Combobox = ({
6987
6989
  const selectedOption = findOptionByValue(options, value);
6988
6990
  const displayValue = selectedOption ? getOptionLabel(selectedOption) : "";
6989
6991
  const selectedIcon = selectedOption ? getOptionIcon(selectedOption) : void 0;
6992
+ const hasValue = value !== void 0 && value !== null && value !== "";
6993
+ const effectiveError = error ?? localRequiredError;
6994
+ React24.useEffect(() => {
6995
+ if (disabled || !required || hasValue) {
6996
+ setLocalRequiredError(void 0);
6997
+ }
6998
+ }, [disabled, hasValue, required]);
6990
6999
  const groupedOptions = React24.useMemo(() => {
6991
7000
  if (!groupBy) return null;
6992
7001
  const groups = {};
@@ -7019,27 +7028,24 @@ var Combobox = ({
7019
7028
  const itemDescription = getOptionDescription(item);
7020
7029
  const itemDisabled = getOptionDisabled(item);
7021
7030
  const isSelected = itemValue === value;
7022
- return /* @__PURE__ */ jsxs22(
7023
- "li",
7031
+ return /* @__PURE__ */ jsx29("li", { className: "list-none", children: /* @__PURE__ */ jsxs22(
7032
+ "button",
7024
7033
  {
7025
- ref: (node) => {
7026
- listRef.current[index] = node;
7027
- },
7028
7034
  id: `combobox-item-${index}`,
7029
- role: "option",
7035
+ type: "button",
7030
7036
  tabIndex: -1,
7031
- "aria-selected": isSelected,
7032
- "aria-disabled": itemDisabled,
7033
- onClick: () => !itemDisabled && handleSelect(item),
7037
+ disabled: itemDisabled,
7038
+ "aria-pressed": isSelected,
7039
+ onClick: () => handleSelect(item),
7034
7040
  style: {
7035
7041
  animationDelay: open ? `${Math.min(index * 15, 150)}ms` : "0ms"
7036
7042
  },
7037
7043
  className: cn(
7038
- "dropdown-item group flex cursor-pointer items-center rounded-full",
7044
+ "dropdown-item group flex w-full items-center rounded-full text-left",
7039
7045
  itemSizeStyles[size],
7040
7046
  "outline-none focus:outline-none focus-visible:outline-none",
7041
7047
  "transition-all duration-150",
7042
- !itemDisabled && "hover:bg-accent/70 hover:shadow-sm",
7048
+ !itemDisabled && "cursor-pointer hover:bg-accent/70 hover:shadow-sm",
7043
7049
  !itemDisabled && "focus:bg-accent/80 focus:text-accent-foreground",
7044
7050
  index === activeIndex && !itemDisabled && "bg-accent/60",
7045
7051
  isSelected && "bg-primary/10 text-primary font-medium",
@@ -7059,16 +7065,14 @@ var Combobox = ({
7059
7065
  ] }),
7060
7066
  isSelected && showSelectedIcon && /* @__PURE__ */ jsx29("span", { className: "shrink-0 ml-auto", children: /* @__PURE__ */ jsx29(Check3, { className: cn(checkIconSizeStyles[size], "text-primary") }) })
7061
7067
  ]
7062
- },
7063
- `${itemValue}-${index}`
7064
- );
7068
+ }
7069
+ ) }, `${itemValue}-${index}`);
7065
7070
  };
7066
7071
  const dropdownBody = /* @__PURE__ */ jsxs22(
7067
7072
  "div",
7068
7073
  {
7069
7074
  "data-combobox-dropdown": true,
7070
7075
  "data-state": open ? "open" : "closed",
7071
- role: "listbox",
7072
7076
  id: `${resolvedId}-listbox`,
7073
7077
  className: "w-full rounded-2xl md:rounded-3xl overflow-hidden",
7074
7078
  children: [
@@ -7123,8 +7127,7 @@ var Combobox = ({
7123
7127
  "transition-all duration-200",
7124
7128
  "placeholder:text-muted-foreground/50"
7125
7129
  ),
7126
- "aria-autocomplete": "list",
7127
- "aria-activedescendant": activeIndex != null ? `combobox-item-${activeIndex}` : void 0
7130
+ "aria-autocomplete": "list"
7128
7131
  }
7129
7132
  ),
7130
7133
  query && /* @__PURE__ */ jsx29(
@@ -7196,7 +7199,8 @@ var Combobox = ({
7196
7199
  "aria-haspopup": "listbox",
7197
7200
  "aria-expanded": open,
7198
7201
  "aria-controls": `${resolvedId}-listbox`,
7199
- "aria-invalid": !!error,
7202
+ "aria-required": required,
7203
+ "aria-invalid": !!effectiveError,
7200
7204
  id: resolvedId,
7201
7205
  "aria-labelledby": labelId,
7202
7206
  onKeyDown: (e) => {
@@ -7217,7 +7221,7 @@ var Combobox = ({
7217
7221
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 focus-visible:border-primary",
7218
7222
  "disabled:cursor-not-allowed disabled:opacity-50",
7219
7223
  open && "ring-2 ring-primary/20 border-primary",
7220
- !!error && "border-destructive focus-visible:ring-destructive/30",
7224
+ !!effectiveError && "border-destructive focus-visible:ring-destructive/30",
7221
7225
  className
7222
7226
  )
7223
7227
  };
@@ -7275,6 +7279,7 @@ var Combobox = ({
7275
7279
  labelSize,
7276
7280
  "font-medium transition-colors duration-200",
7277
7281
  disabled ? "text-muted-foreground" : "text-foreground group-focus-within:text-primary",
7282
+ effectiveError && "text-destructive",
7278
7283
  labelClassName
7279
7284
  ),
7280
7285
  children: [
@@ -7283,6 +7288,23 @@ var Combobox = ({
7283
7288
  ]
7284
7289
  }
7285
7290
  ) }),
7291
+ /* @__PURE__ */ jsx29(
7292
+ "input",
7293
+ {
7294
+ tabIndex: -1,
7295
+ "aria-hidden": "true",
7296
+ value: hasValue ? "selected" : "",
7297
+ onChange: () => {
7298
+ },
7299
+ required,
7300
+ disabled,
7301
+ onInvalid: (e) => {
7302
+ e.preventDefault();
7303
+ setLocalRequiredError(tv("required"));
7304
+ },
7305
+ className: "pointer-events-none absolute h-0 w-0 opacity-0"
7306
+ }
7307
+ ),
7286
7308
  usePortal ? /* @__PURE__ */ jsx29(
7287
7309
  Popover,
7288
7310
  {
@@ -7299,17 +7321,26 @@ var Combobox = ({
7299
7321
  triggerButtonInline,
7300
7322
  open && /* @__PURE__ */ jsx29("div", { className: "absolute left-0 top-full mt-1 z-50 w-full", children: /* @__PURE__ */ jsx29("div", { className: "rounded-2xl md:rounded-3xl overflow-hidden border text-popover-foreground shadow-md backdrop-blur-sm bg-popover/95 border-border/60", children: dropdownBody }) })
7301
7323
  ] }),
7302
- (helperText || error) && /* @__PURE__ */ jsxs22("p", { className: cn("text-xs transition-colors duration-200 flex items-center gap-1.5", error ? "text-destructive" : "text-muted-foreground"), children: [
7303
- error && /* @__PURE__ */ jsx29("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", className: "w-3.5 h-3.5 shrink-0", children: /* @__PURE__ */ jsx29(
7304
- "path",
7305
- {
7306
- fillRule: "evenodd",
7307
- d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z",
7308
- clipRule: "evenodd"
7309
- }
7310
- ) }),
7311
- error || helperText
7312
- ] })
7324
+ (helperText || effectiveError) && /* @__PURE__ */ jsxs22(
7325
+ "p",
7326
+ {
7327
+ className: cn(
7328
+ "text-xs transition-colors duration-200 flex items-center gap-1.5",
7329
+ effectiveError ? "text-destructive" : "text-muted-foreground"
7330
+ ),
7331
+ children: [
7332
+ effectiveError && /* @__PURE__ */ jsx29("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", className: "w-3.5 h-3.5 shrink-0", children: /* @__PURE__ */ jsx29(
7333
+ "path",
7334
+ {
7335
+ fillRule: "evenodd",
7336
+ d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z",
7337
+ clipRule: "evenodd"
7338
+ }
7339
+ ) }),
7340
+ effectiveError || helperText
7341
+ ]
7342
+ }
7343
+ )
7313
7344
  ] });
7314
7345
  };
7315
7346
 
@@ -8000,10 +8031,12 @@ var DatePicker = ({
8000
8031
  maxDate
8001
8032
  }) => {
8002
8033
  const t = useSmartTranslations("DatePicker");
8034
+ const tv = useSmartTranslations("ValidationInput");
8003
8035
  const locale = useSmartLocale();
8004
8036
  const [isOpen, setIsOpen] = React28.useState(false);
8005
8037
  const [viewDate, setViewDate] = React28.useState(value || /* @__PURE__ */ new Date());
8006
8038
  const [viewMode, setViewMode] = React28.useState("calendar");
8039
+ const [localRequiredError, setLocalRequiredError] = React28.useState();
8007
8040
  const triggerRef = React28.useRef(null);
8008
8041
  const wheelContainerRef = React28.useRef(null);
8009
8042
  const wheelDeltaRef = React28.useRef(0);
@@ -8089,6 +8122,11 @@ var DatePicker = ({
8089
8122
  setViewDate(/* @__PURE__ */ new Date());
8090
8123
  }
8091
8124
  }, [value]);
8125
+ React28.useEffect(() => {
8126
+ if (disabled || !required || value) {
8127
+ setLocalRequiredError(void 0);
8128
+ }
8129
+ }, [disabled, required, value]);
8092
8130
  React28.useEffect(() => {
8093
8131
  if (!isOpen) {
8094
8132
  setViewMode("calendar");
@@ -8103,6 +8141,7 @@ var DatePicker = ({
8103
8141
  selectedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
8104
8142
  }
8105
8143
  onChange(selectedDate);
8144
+ setLocalRequiredError(void 0);
8106
8145
  setIsOpen(false);
8107
8146
  };
8108
8147
  const formatDateDisplay = (date) => {
@@ -8384,6 +8423,7 @@ var DatePicker = ({
8384
8423
  const labelSize = sizeStyles8[size].label;
8385
8424
  const radiusClass = size === "sm" ? "rounded-md" : "rounded-lg";
8386
8425
  const verticalGap = size === "sm" ? "space-y-1.5" : size === "lg" ? "space-y-2.5" : "space-y-2";
8426
+ const effectiveError = localRequiredError;
8387
8427
  return /* @__PURE__ */ jsxs24("div", { className: cn("w-full group", verticalGap), children: [
8388
8428
  label && /* @__PURE__ */ jsx34("div", { className: "flex items-center justify-between mb-2", children: /* @__PURE__ */ jsxs24(
8389
8429
  "label",
@@ -8395,6 +8435,7 @@ var DatePicker = ({
8395
8435
  labelSize,
8396
8436
  "font-semibold transition-colors duration-300 cursor-pointer",
8397
8437
  disabled ? "text-muted-foreground" : "text-foreground group-focus-within:text-primary hover:text-primary",
8438
+ effectiveError && "text-destructive",
8398
8439
  labelClassName
8399
8440
  ),
8400
8441
  children: [
@@ -8403,6 +8444,23 @@ var DatePicker = ({
8403
8444
  ]
8404
8445
  }
8405
8446
  ) }),
8447
+ /* @__PURE__ */ jsx34(
8448
+ "input",
8449
+ {
8450
+ tabIndex: -1,
8451
+ "aria-hidden": "true",
8452
+ value: value ? "selected" : "",
8453
+ onChange: () => {
8454
+ },
8455
+ required,
8456
+ disabled,
8457
+ onInvalid: (e) => {
8458
+ e.preventDefault();
8459
+ setLocalRequiredError(tv("required"));
8460
+ },
8461
+ className: "pointer-events-none absolute h-0 w-0 opacity-0"
8462
+ }
8463
+ ),
8406
8464
  /* @__PURE__ */ jsx34(
8407
8465
  Popover,
8408
8466
  {
@@ -8428,6 +8486,8 @@ var DatePicker = ({
8428
8486
  disabled,
8429
8487
  id: resolvedId,
8430
8488
  "aria-labelledby": labelId,
8489
+ "aria-required": required,
8490
+ "aria-invalid": !!effectiveError,
8431
8491
  className: cn(
8432
8492
  "group flex w-full items-center justify-between border bg-background/80 backdrop-blur-sm",
8433
8493
  "rounded-full",
@@ -8438,6 +8498,7 @@ var DatePicker = ({
8438
8498
  "hover:bg-accent/10 hover:shadow-lg hover:shadow-primary/5 hover:-translate-y-0.5",
8439
8499
  "transition-all duration-300 ease-out",
8440
8500
  isOpen && "ring-2 ring-primary/30 border-primary/50 shadow-lg shadow-primary/10",
8501
+ effectiveError && "border-destructive/60 focus-visible:ring-destructive/50 bg-destructive/5",
8441
8502
  className
8442
8503
  ),
8443
8504
  children: [
@@ -8478,6 +8539,7 @@ var DatePicker = ({
8478
8539
  e.preventDefault();
8479
8540
  e.stopPropagation();
8480
8541
  onChange(void 0);
8542
+ setLocalRequiredError(void 0);
8481
8543
  setViewDate(/* @__PURE__ */ new Date());
8482
8544
  }
8483
8545
  },
@@ -8502,7 +8564,8 @@ var DatePicker = ({
8502
8564
  ),
8503
8565
  children: datePickerContent
8504
8566
  }
8505
- )
8567
+ ),
8568
+ effectiveError && /* @__PURE__ */ jsx34("div", { className: "text-xs text-destructive", children: effectiveError })
8506
8569
  ] });
8507
8570
  };
8508
8571
  var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select date range...", className, disablePastDates = false, minDate, maxDate, size = "md" }) => {
@@ -9323,6 +9386,7 @@ function MonthYearPicker({
9323
9386
  className,
9324
9387
  ...rest
9325
9388
  }) {
9389
+ const tv = useSmartTranslations("ValidationInput");
9326
9390
  const now = /* @__PURE__ */ new Date();
9327
9391
  const currentYear = now.getFullYear();
9328
9392
  const resolvedMinYear = minYear ?? minDate?.getFullYear() ?? currentYear - 50;
@@ -9339,6 +9403,8 @@ function MonthYearPicker({
9339
9403
  const [open, setOpen] = React29.useState(false);
9340
9404
  const [parts, setParts] = React29.useState(initial);
9341
9405
  const [focusedColumn, setFocusedColumn] = React29.useState(null);
9406
+ const [localRequiredError, setLocalRequiredError] = React29.useState();
9407
+ const [hasCommittedValue, setHasCommittedValue] = React29.useState(Boolean(parseValue(isControlled ? value : defaultValue)));
9342
9408
  const monthScrollRef = React29.useRef(null);
9343
9409
  const yearScrollRef = React29.useRef(null);
9344
9410
  React29.useEffect(() => {
@@ -9347,6 +9413,18 @@ function MonthYearPicker({
9347
9413
  if (parsed) setParts(parsed);
9348
9414
  }
9349
9415
  }, [value, isControlled]);
9416
+ React29.useEffect(() => {
9417
+ if (isControlled) {
9418
+ setHasCommittedValue(Boolean(parseValue(value)));
9419
+ }
9420
+ }, [isControlled, value]);
9421
+ const hasValue = hasCommittedValue;
9422
+ const effectiveError = error ?? localRequiredError;
9423
+ React29.useEffect(() => {
9424
+ if (disabled || !required || hasValue) {
9425
+ setLocalRequiredError(void 0);
9426
+ }
9427
+ }, [disabled, hasValue, required]);
9350
9428
  const years = React29.useMemo(() => {
9351
9429
  return Array.from({ length: resolvedMaxYear - resolvedMinYear + 1 }, (_, i) => resolvedMinYear + i);
9352
9430
  }, [resolvedMinYear, resolvedMaxYear]);
@@ -9370,14 +9448,18 @@ function MonthYearPicker({
9370
9448
  const emit = React29.useCallback(
9371
9449
  (next) => {
9372
9450
  if (!next) {
9451
+ setLocalRequiredError(void 0);
9452
+ if (!isControlled) setHasCommittedValue(false);
9373
9453
  onChange?.(void 0);
9374
9454
  return;
9375
9455
  }
9376
9456
  if (!isDateInRange(next.month, next.year)) return;
9377
9457
  const date = new Date(next.year, next.month, 1);
9458
+ setLocalRequiredError(void 0);
9459
+ if (!isControlled) setHasCommittedValue(true);
9378
9460
  onChange?.({ ...next, date });
9379
9461
  },
9380
- [isDateInRange, onChange]
9462
+ [isControlled, isDateInRange, onChange]
9381
9463
  );
9382
9464
  const tryUpdate = React29.useCallback(
9383
9465
  (next) => {
@@ -9449,7 +9531,6 @@ function MonthYearPicker({
9449
9531
  const monthIndex = parts.month;
9450
9532
  const yearIndex = years.indexOf(parts.year);
9451
9533
  const display = `${shortMonthNames[parts.month]} ${parts.year}`;
9452
- const hasValue = isControlled ? !!value : !!defaultValue || parts !== initial;
9453
9534
  const trigger = variant === "inline" ? null : /* @__PURE__ */ jsxs25(
9454
9535
  "button",
9455
9536
  {
@@ -9458,6 +9539,8 @@ function MonthYearPicker({
9458
9539
  "aria-label": "Select month and year",
9459
9540
  "aria-haspopup": "dialog",
9460
9541
  "aria-expanded": open,
9542
+ "aria-required": required,
9543
+ "aria-invalid": !!effectiveError,
9461
9544
  className: cn(
9462
9545
  "group flex w-full items-center justify-between rounded-full border bg-background/80 backdrop-blur-sm",
9463
9546
  sz.height,
@@ -9466,9 +9549,9 @@ function MonthYearPicker({
9466
9549
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background",
9467
9550
  "disabled:opacity-50 disabled:cursor-not-allowed",
9468
9551
  "transition-all duration-300 ease-out",
9469
- error && "border-destructive/60 focus-visible:ring-destructive/50 bg-destructive/5",
9470
- success && "border-success/60 focus-visible:ring-success/50 bg-success/5",
9471
- !error && !success && "border-border/60 hover:border-primary/40 hover:bg-accent/10",
9552
+ effectiveError && "border-destructive/60 focus-visible:ring-destructive/50 bg-destructive/5",
9553
+ success && !effectiveError && "border-success/60 focus-visible:ring-success/50 bg-success/5",
9554
+ !effectiveError && !success && "border-border/60 hover:border-primary/40 hover:bg-accent/10",
9472
9555
  animate && !disabled && "hover:shadow-lg hover:shadow-primary/5 hover:-translate-y-0.5",
9473
9556
  open && "ring-2 ring-primary/30 border-primary/50 shadow-lg shadow-primary/10",
9474
9557
  className
@@ -9480,7 +9563,7 @@ function MonthYearPicker({
9480
9563
  {
9481
9564
  className: cn(
9482
9565
  "flex items-center justify-center transition-colors duration-300",
9483
- error ? "text-destructive" : success ? "text-success" : open ? "text-primary" : "text-muted-foreground group-hover:text-primary"
9566
+ effectiveError ? "text-destructive" : success ? "text-success" : open ? "text-primary" : "text-muted-foreground group-hover:text-primary"
9484
9567
  ),
9485
9568
  children: /* @__PURE__ */ jsx35(Calendar2, { className: cn(sz.icon, "transition-transform duration-300", open && "rotate-12") })
9486
9569
  }
@@ -9615,19 +9698,63 @@ function MonthYearPicker({
9615
9698
  ] });
9616
9699
  if (variant === "inline") {
9617
9700
  return /* @__PURE__ */ jsxs25("div", { className: cn("w-full", className), ...rest, children: [
9618
- label && /* @__PURE__ */ jsxs25("label", { className: cn(sz.label, "block mb-1.5 font-medium text-foreground/80", labelClassName), children: [
9701
+ label && /* @__PURE__ */ jsxs25("label", { className: cn(sz.label, "block mb-1.5 font-medium text-foreground/80", effectiveError && "text-destructive", labelClassName), children: [
9619
9702
  label,
9620
9703
  required && /* @__PURE__ */ jsx35("span", { className: "text-destructive ml-0.5", children: "*" })
9621
9704
  ] }),
9622
- /* @__PURE__ */ jsx35("div", { className: cn(panelSz.contentPadding, "rounded-2xl border border-border/50 bg-background/80 backdrop-blur-sm"), children: pickerContent }),
9623
- (helperText || error) && /* @__PURE__ */ jsx35("div", { className: cn("mt-1.5 text-xs", error ? "text-destructive" : "text-muted-foreground"), children: error || helperText })
9705
+ /* @__PURE__ */ jsx35(
9706
+ "input",
9707
+ {
9708
+ tabIndex: -1,
9709
+ "aria-hidden": "true",
9710
+ value: hasValue ? "selected" : "",
9711
+ onChange: () => {
9712
+ },
9713
+ required,
9714
+ disabled,
9715
+ onInvalid: (e) => {
9716
+ e.preventDefault();
9717
+ setLocalRequiredError(tv("required"));
9718
+ },
9719
+ className: "pointer-events-none absolute h-0 w-0 opacity-0"
9720
+ }
9721
+ ),
9722
+ /* @__PURE__ */ jsx35(
9723
+ "div",
9724
+ {
9725
+ className: cn(
9726
+ panelSz.contentPadding,
9727
+ "rounded-2xl border bg-background/80 backdrop-blur-sm",
9728
+ effectiveError ? "border-destructive/60 bg-destructive/5" : "border-border/50"
9729
+ ),
9730
+ children: pickerContent
9731
+ }
9732
+ ),
9733
+ (helperText || effectiveError) && /* @__PURE__ */ jsx35("div", { className: cn("mt-1.5 text-xs", effectiveError ? "text-destructive" : "text-muted-foreground"), children: effectiveError || helperText })
9624
9734
  ] });
9625
9735
  }
9626
9736
  return /* @__PURE__ */ jsxs25("div", { className: cn("w-full", className), ...rest, children: [
9627
- label && /* @__PURE__ */ jsxs25("label", { className: cn(sz.label, "block mb-1.5 font-medium text-foreground/80", labelClassName), children: [
9737
+ label && /* @__PURE__ */ jsxs25("label", { className: cn(sz.label, "block mb-1.5 font-medium text-foreground/80", effectiveError && "text-destructive", labelClassName), children: [
9628
9738
  label,
9629
9739
  required && /* @__PURE__ */ jsx35("span", { className: "text-destructive ml-0.5", children: "*" })
9630
9740
  ] }),
9741
+ /* @__PURE__ */ jsx35(
9742
+ "input",
9743
+ {
9744
+ tabIndex: -1,
9745
+ "aria-hidden": "true",
9746
+ value: hasValue ? "selected" : "",
9747
+ onChange: () => {
9748
+ },
9749
+ required,
9750
+ disabled,
9751
+ onInvalid: (e) => {
9752
+ e.preventDefault();
9753
+ setLocalRequiredError(tv("required"));
9754
+ },
9755
+ className: "pointer-events-none absolute h-0 w-0 opacity-0"
9756
+ }
9757
+ ),
9631
9758
  /* @__PURE__ */ jsx35(
9632
9759
  Popover,
9633
9760
  {
@@ -9642,7 +9769,7 @@ function MonthYearPicker({
9642
9769
  children: pickerContent
9643
9770
  }
9644
9771
  ),
9645
- (helperText || error) && /* @__PURE__ */ jsx35("div", { className: cn("mt-1.5 text-xs", error ? "text-destructive" : "text-muted-foreground"), children: error || helperText })
9772
+ (helperText || effectiveError) && /* @__PURE__ */ jsx35("div", { className: cn("mt-1.5 text-xs", effectiveError ? "text-destructive" : "text-muted-foreground"), children: effectiveError || helperText })
9646
9773
  ] });
9647
9774
  }
9648
9775
 
@@ -10782,6 +10909,7 @@ function TimePicker({
10782
10909
  className,
10783
10910
  ...rest
10784
10911
  }) {
10912
+ const tv = useSmartTranslations("ValidationInput");
10785
10913
  const isControlled = value !== void 0;
10786
10914
  const now = /* @__PURE__ */ new Date();
10787
10915
  const initial = parseTime(isControlled ? value : defaultValue, format, includeSeconds) || (format === "12" ? { h: now.getHours() % 12 || 12, m: now.getMinutes(), s: now.getSeconds(), p: now.getHours() >= 12 ? "PM" : "AM" } : { h: now.getHours(), m: now.getMinutes(), s: now.getSeconds() });
@@ -10789,6 +10917,8 @@ function TimePicker({
10789
10917
  const [parts, setParts] = React31.useState(initial);
10790
10918
  const [manualInput, setManualInput] = React31.useState("");
10791
10919
  const [focusedColumn, setFocusedColumn] = React31.useState(null);
10920
+ const [localRequiredError, setLocalRequiredError] = React31.useState();
10921
+ const [hasCommittedValue, setHasCommittedValue] = React31.useState(Boolean(isControlled ? value : defaultValue));
10792
10922
  const hourScrollRef = React31.useRef(null);
10793
10923
  const minuteScrollRef = React31.useRef(null);
10794
10924
  const secondScrollRef = React31.useRef(null);
@@ -10798,6 +10928,11 @@ function TimePicker({
10798
10928
  if (parsed) setParts(parsed);
10799
10929
  }
10800
10930
  }, [value, isControlled, format, includeSeconds]);
10931
+ React31.useEffect(() => {
10932
+ if (isControlled) {
10933
+ setHasCommittedValue(Boolean(value));
10934
+ }
10935
+ }, [isControlled, value]);
10801
10936
  const isTimeDisabled = React31.useCallback(
10802
10937
  (timeStr) => {
10803
10938
  if (!disabledTimes) return false;
@@ -10852,9 +10987,13 @@ function TimePicker({
10852
10987
  (next) => {
10853
10988
  const timeStr = next ? formatTime2(next, format, includeSeconds) : void 0;
10854
10989
  if (!canEmit(next)) return;
10990
+ setLocalRequiredError(void 0);
10991
+ if (!isControlled) {
10992
+ setHasCommittedValue(Boolean(next));
10993
+ }
10855
10994
  onChange?.(timeStr);
10856
10995
  },
10857
- [canEmit, format, includeSeconds, onChange]
10996
+ [canEmit, format, includeSeconds, isControlled, onChange]
10858
10997
  );
10859
10998
  const tryUpdate = React31.useCallback(
10860
10999
  (next) => {
@@ -10874,6 +11013,11 @@ function TimePicker({
10874
11013
  setFocusedColumn(null);
10875
11014
  }
10876
11015
  };
11016
+ React31.useEffect(() => {
11017
+ if (disabled || !required || hasCommittedValue) {
11018
+ setLocalRequiredError(void 0);
11019
+ }
11020
+ }, [disabled, hasCommittedValue, required]);
10877
11021
  const handleKeyDown2 = (e, column) => {
10878
11022
  if (!["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End", "PageUp", "PageDown"].includes(e.key)) return;
10879
11023
  e.preventDefault();
@@ -11016,6 +11160,7 @@ function TimePicker({
11016
11160
  const panelSz = panelSizeClasses[effectivePanelSize];
11017
11161
  const shouldMatchTriggerWidth = matchTriggerWidth ?? variant !== "compact";
11018
11162
  const compactPanel = variant === "compact";
11163
+ const effectiveError = error ?? localRequiredError;
11019
11164
  const display = formatTime2(parts, format, includeSeconds);
11020
11165
  const trigger = variant === "inline" ? null : /* @__PURE__ */ jsxs27(
11021
11166
  "button",
@@ -11025,6 +11170,8 @@ function TimePicker({
11025
11170
  "aria-label": "Select time",
11026
11171
  "aria-haspopup": "dialog",
11027
11172
  "aria-expanded": open,
11173
+ "aria-required": required,
11174
+ "aria-invalid": !!effectiveError,
11028
11175
  className: cn(
11029
11176
  "group flex w-full items-center justify-between rounded-full border bg-background/80 backdrop-blur-sm",
11030
11177
  sz.height,
@@ -11033,9 +11180,9 @@ function TimePicker({
11033
11180
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background",
11034
11181
  "disabled:opacity-50 disabled:cursor-not-allowed",
11035
11182
  "transition-all duration-300 ease-out",
11036
- error && "border-destructive/60 focus-visible:ring-destructive/50 bg-destructive/5",
11037
- success && "border-success/60 focus-visible:ring-success/50 bg-success/5",
11038
- !error && !success && "border-border/60 hover:border-primary/40 hover:bg-accent/10",
11183
+ effectiveError && "border-destructive/60 focus-visible:ring-destructive/50 bg-destructive/5",
11184
+ success && !effectiveError && "border-success/60 focus-visible:ring-success/50 bg-success/5",
11185
+ !effectiveError && !success && "border-border/60 hover:border-primary/40 hover:bg-accent/10",
11039
11186
  animate && !disabled && "hover:shadow-lg hover:shadow-primary/5 hover:-translate-y-0.5",
11040
11187
  open && "ring-2 ring-primary/30 border-primary/50 shadow-lg shadow-primary/10",
11041
11188
  className
@@ -11047,7 +11194,7 @@ function TimePicker({
11047
11194
  {
11048
11195
  className: cn(
11049
11196
  "flex items-center justify-center transition-colors duration-300",
11050
- error ? "text-destructive" : success ? "text-success" : open ? "text-primary" : "text-muted-foreground group-hover:text-primary"
11197
+ effectiveError ? "text-destructive" : success ? "text-success" : open ? "text-primary" : "text-muted-foreground group-hover:text-primary"
11051
11198
  ),
11052
11199
  children: /* @__PURE__ */ jsx37(Clock2, { className: cn(sz.icon, "transition-transform duration-300", open && "rotate-12") })
11053
11200
  }
@@ -11334,17 +11481,40 @@ function TimePicker({
11334
11481
  ] });
11335
11482
  if (variant === "inline") {
11336
11483
  return /* @__PURE__ */ jsxs27("div", { className: "w-fit max-w-full", ...rest, children: [
11337
- label && /* @__PURE__ */ jsx37("div", { className: "flex items-center justify-between mb-3", children: /* @__PURE__ */ jsxs27("label", { className: cn(sz.label, "font-semibold", disabled ? "text-muted-foreground" : "text-foreground"), children: [
11484
+ label && /* @__PURE__ */ jsx37("div", { className: "flex items-center justify-between mb-3", children: /* @__PURE__ */ jsxs27("label", { className: cn(sz.label, "font-semibold", disabled ? "text-muted-foreground" : "text-foreground", effectiveError && "text-destructive"), children: [
11338
11485
  label,
11339
11486
  required && /* @__PURE__ */ jsx37("span", { className: "text-destructive ml-1", children: "*" })
11340
11487
  ] }) }),
11488
+ /* @__PURE__ */ jsx37(
11489
+ "input",
11490
+ {
11491
+ tabIndex: -1,
11492
+ "aria-hidden": "true",
11493
+ value: hasCommittedValue ? "selected" : "",
11494
+ onChange: () => {
11495
+ },
11496
+ required,
11497
+ disabled,
11498
+ onInvalid: (e) => {
11499
+ e.preventDefault();
11500
+ setLocalRequiredError(tv("required"));
11501
+ },
11502
+ className: "pointer-events-none absolute h-0 w-0 opacity-0"
11503
+ }
11504
+ ),
11341
11505
  /* @__PURE__ */ jsx37(
11342
11506
  "div",
11343
11507
  {
11344
- className: cn(panelSz.contentPadding, "rounded-2xl md:rounded-3xl border border-border/60 bg-card/95 backdrop-blur-sm shadow-xl", className),
11508
+ className: cn(
11509
+ panelSz.contentPadding,
11510
+ "rounded-2xl md:rounded-3xl border bg-card/95 backdrop-blur-sm shadow-xl",
11511
+ effectiveError ? "border-destructive/60 bg-destructive/5" : "border-border/60",
11512
+ className
11513
+ ),
11345
11514
  children: timePickerContent
11346
11515
  }
11347
- )
11516
+ ),
11517
+ effectiveError && /* @__PURE__ */ jsx37("div", { className: cn("mt-2", sz.label, "text-destructive"), children: effectiveError })
11348
11518
  ] });
11349
11519
  }
11350
11520
  return /* @__PURE__ */ jsxs27("div", { className: "w-full", ...rest, children: [
@@ -11355,6 +11525,7 @@ function TimePicker({
11355
11525
  sz.label,
11356
11526
  "font-semibold",
11357
11527
  disabled ? "text-muted-foreground" : "text-foreground",
11528
+ effectiveError && "text-destructive",
11358
11529
  "cursor-pointer transition-colors hover:text-primary"
11359
11530
  ),
11360
11531
  onClick: () => !disabled && handleOpenChange(true),
@@ -11364,6 +11535,23 @@ function TimePicker({
11364
11535
  ]
11365
11536
  }
11366
11537
  ) }),
11538
+ /* @__PURE__ */ jsx37(
11539
+ "input",
11540
+ {
11541
+ tabIndex: -1,
11542
+ "aria-hidden": "true",
11543
+ value: hasCommittedValue ? "selected" : "",
11544
+ onChange: () => {
11545
+ },
11546
+ required,
11547
+ disabled,
11548
+ onInvalid: (e) => {
11549
+ e.preventDefault();
11550
+ setLocalRequiredError(tv("required"));
11551
+ },
11552
+ className: "pointer-events-none absolute h-0 w-0 opacity-0"
11553
+ }
11554
+ ),
11367
11555
  /* @__PURE__ */ jsx37(
11368
11556
  Popover,
11369
11557
  {
@@ -11377,24 +11565,24 @@ function TimePicker({
11377
11565
  panelSz.contentPadding,
11378
11566
  compactPanel && "max-w-[calc(100vw-2rem)] p-4 rounded-2xl",
11379
11567
  "rounded-2xl md:rounded-3xl border bg-popover/98 backdrop-blur-md shadow-2xl",
11380
- error && "border-destructive/40",
11381
- success && "border-success/40",
11382
- !error && !success && "border-border/60",
11568
+ effectiveError && "border-destructive/40",
11569
+ success && !effectiveError && "border-success/40",
11570
+ !effectiveError && !success && "border-border/60",
11383
11571
  animate && "animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-300"
11384
11572
  ),
11385
11573
  children: timePickerContent
11386
11574
  }
11387
11575
  ),
11388
- (error || success || helperText) && /* @__PURE__ */ jsxs27("div", { className: cn("mt-2 flex items-start gap-2", sz.label), children: [
11389
- error && /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2 text-destructive bg-destructive/10 px-3 py-1.5 rounded-lg", children: [
11576
+ (effectiveError || success || helperText) && /* @__PURE__ */ jsxs27("div", { className: cn("mt-2 flex items-start gap-2", sz.label), children: [
11577
+ effectiveError && /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2 text-destructive bg-destructive/10 px-3 py-1.5 rounded-lg", children: [
11390
11578
  /* @__PURE__ */ jsx37(X11, { className: "w-3.5 h-3.5 shrink-0" }),
11391
- /* @__PURE__ */ jsx37("span", { className: "font-medium", children: error })
11579
+ /* @__PURE__ */ jsx37("span", { className: "font-medium", children: effectiveError })
11392
11580
  ] }),
11393
- success && !error && /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2 text-success bg-success/10 px-3 py-1.5 rounded-lg", children: [
11581
+ success && !effectiveError && /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2 text-success bg-success/10 px-3 py-1.5 rounded-lg", children: [
11394
11582
  /* @__PURE__ */ jsx37(Check5, { className: "w-3.5 h-3.5 shrink-0" }),
11395
11583
  /* @__PURE__ */ jsx37("span", { className: "font-medium", children: "Valid time selected" })
11396
11584
  ] }),
11397
- helperText && !error && !success && /* @__PURE__ */ jsx37("span", { className: "text-muted-foreground/80 italic", children: helperText })
11585
+ helperText && !effectiveError && !success && /* @__PURE__ */ jsx37("span", { className: "text-muted-foreground/80 italic", children: helperText })
11398
11586
  ] })
11399
11587
  ] });
11400
11588
  }
@@ -11419,8 +11607,10 @@ var DateTimePicker = ({
11419
11607
  size = "md"
11420
11608
  }) => {
11421
11609
  const t = useSmartTranslations("DateTimePicker");
11610
+ const tv = useSmartTranslations("ValidationInput");
11422
11611
  const locale = useSmartLocale();
11423
11612
  const [open, setOpen] = React32.useState(false);
11613
+ const [localRequiredError, setLocalRequiredError] = React32.useState();
11424
11614
  const sizeStyles8 = {
11425
11615
  sm: {
11426
11616
  trigger: "h-8 px-2.5 py-1.5 text-sm md:h-7 md:text-xs",
@@ -11459,6 +11649,11 @@ var DateTimePicker = ({
11459
11649
  setTempDate(value);
11460
11650
  setCalendarMonth(value ?? /* @__PURE__ */ new Date());
11461
11651
  }, [value, open]);
11652
+ React32.useEffect(() => {
11653
+ if (disabled || !required || value) {
11654
+ setLocalRequiredError(void 0);
11655
+ }
11656
+ }, [disabled, required, value]);
11462
11657
  const getTimeString = (date) => {
11463
11658
  if (!date) return "";
11464
11659
  const h = date.getHours();
@@ -11515,11 +11710,13 @@ var DateTimePicker = ({
11515
11710
  };
11516
11711
  const handleApply = () => {
11517
11712
  onChange(tempDate);
11713
+ setLocalRequiredError(void 0);
11518
11714
  setOpen(false);
11519
11715
  };
11520
11716
  const handleClear = () => {
11521
11717
  onChange(void 0);
11522
11718
  setTempDate(void 0);
11719
+ setLocalRequiredError(void 0);
11523
11720
  setOpen(false);
11524
11721
  };
11525
11722
  const displayValue = value ? value.toLocaleString(locale === "vi" ? "vi-VN" : "en-US", {
@@ -11550,12 +11747,30 @@ var DateTimePicker = ({
11550
11747
  }
11551
11748
  };
11552
11749
  const weekdays = getWeekdays(locale);
11750
+ const effectiveError = localRequiredError;
11553
11751
  return /* @__PURE__ */ jsxs28("div", { className: cn("space-y-1.5", className), children: [
11554
- label && /* @__PURE__ */ jsxs28("label", { className: cn(sizeStyles8[size].label, "font-medium text-foreground flex items-center gap-1", labelClassName), children: [
11752
+ label && /* @__PURE__ */ jsxs28("label", { className: cn(sizeStyles8[size].label, "font-medium text-foreground flex items-center gap-1", effectiveError && "text-destructive", labelClassName), children: [
11555
11753
  label,
11556
11754
  " ",
11557
11755
  required && /* @__PURE__ */ jsx38("span", { className: "text-destructive", children: "*" })
11558
11756
  ] }),
11757
+ /* @__PURE__ */ jsx38(
11758
+ "input",
11759
+ {
11760
+ tabIndex: -1,
11761
+ "aria-hidden": "true",
11762
+ value: value ? "selected" : "",
11763
+ onChange: () => {
11764
+ },
11765
+ required,
11766
+ disabled,
11767
+ onInvalid: (e) => {
11768
+ e.preventDefault();
11769
+ setLocalRequiredError(tv("required"));
11770
+ },
11771
+ className: "pointer-events-none absolute h-0 w-0 opacity-0"
11772
+ }
11773
+ ),
11559
11774
  /* @__PURE__ */ jsxs28(
11560
11775
  Popover,
11561
11776
  {
@@ -11566,12 +11781,15 @@ var DateTimePicker = ({
11566
11781
  {
11567
11782
  type: "button",
11568
11783
  disabled,
11784
+ "aria-required": required,
11785
+ "aria-invalid": !!effectiveError,
11569
11786
  className: cn(
11570
11787
  "flex w-full items-center justify-between rounded-full border border-input bg-background",
11571
11788
  sizeStyles8[size].trigger,
11572
11789
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
11573
11790
  disabled && "opacity-50 cursor-not-allowed",
11574
- !displayValue && "text-muted-foreground"
11791
+ !displayValue && "text-muted-foreground",
11792
+ effectiveError && "border-destructive/60 bg-destructive/5"
11575
11793
  ),
11576
11794
  children: [
11577
11795
  /* @__PURE__ */ jsx38("span", { className: "truncate", children: displayValue || placeholder || "Select date & time" }),
@@ -11584,6 +11802,7 @@ var DateTimePicker = ({
11584
11802
  onClick: (e) => {
11585
11803
  e.stopPropagation();
11586
11804
  onChange(void 0);
11805
+ setLocalRequiredError(void 0);
11587
11806
  },
11588
11807
  className: "hover:text-foreground p-0.5 rounded-md hover:bg-accent",
11589
11808
  children: /* @__PURE__ */ jsx38(X12, { className: sizeStyles8[size].icon })
@@ -11643,7 +11862,8 @@ var DateTimePicker = ({
11643
11862
  ] })
11644
11863
  ]
11645
11864
  }
11646
- )
11865
+ ),
11866
+ effectiveError && /* @__PURE__ */ jsx38("div", { className: "text-xs text-destructive", children: effectiveError })
11647
11867
  ] });
11648
11868
  };
11649
11869
 
@@ -14600,9 +14820,11 @@ var MultiCombobox = ({
14600
14820
  maxTagsVisible = 3,
14601
14821
  useOverlayScrollbar = false
14602
14822
  }) => {
14823
+ const tv = useSmartTranslations("ValidationInput");
14603
14824
  const [query, setQuery] = React39.useState("");
14604
14825
  const [open, setOpen] = React39.useState(false);
14605
14826
  const [activeIndex, setActiveIndex] = React39.useState(null);
14827
+ const [localRequiredError, setLocalRequiredError] = React39.useState();
14606
14828
  const inputRef = React39.useRef(null);
14607
14829
  const listRef = React39.useRef([]);
14608
14830
  const optionsListRef = React39.useRef(null);
@@ -14639,6 +14861,7 @@ var MultiCombobox = ({
14639
14861
  onChange(value.filter((v) => v !== optionValue));
14640
14862
  } else {
14641
14863
  if (!maxSelected || value.length < maxSelected) {
14864
+ setLocalRequiredError(void 0);
14642
14865
  onChange([...value, optionValue]);
14643
14866
  }
14644
14867
  }
@@ -14658,6 +14881,12 @@ var MultiCombobox = ({
14658
14881
  const handleClearAll = () => {
14659
14882
  onChange([]);
14660
14883
  };
14884
+ const effectiveError = error ?? localRequiredError;
14885
+ React39.useEffect(() => {
14886
+ if (disabled || !required || value.length > 0) {
14887
+ setLocalRequiredError(void 0);
14888
+ }
14889
+ }, [disabled, required, value.length]);
14661
14890
  React39.useEffect(() => {
14662
14891
  if (open && enableSearch) {
14663
14892
  setTimeout(() => {
@@ -14868,7 +15097,8 @@ var MultiCombobox = ({
14868
15097
  "aria-haspopup": "listbox",
14869
15098
  "aria-expanded": open,
14870
15099
  "aria-controls": listboxId,
14871
- "aria-invalid": !!error,
15100
+ "aria-required": required,
15101
+ "aria-invalid": !!effectiveError,
14872
15102
  className: cn(
14873
15103
  "group flex w-full items-center gap-2 rounded-full transition-all duration-200",
14874
15104
  sizeStyles8[size].trigger,
@@ -14876,7 +15106,7 @@ var MultiCombobox = ({
14876
15106
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 focus-visible:border-primary",
14877
15107
  "disabled:cursor-not-allowed disabled:opacity-50",
14878
15108
  open && "ring-2 ring-primary/20 border-primary",
14879
- !!error && "border-destructive focus-visible:ring-destructive/30"
15109
+ !!effectiveError && "border-destructive focus-visible:ring-destructive/30"
14880
15110
  ),
14881
15111
  children: [
14882
15112
  /* @__PURE__ */ jsx45("div", { className: cn("flex items-center gap-1.5 flex-1 overflow-hidden", size === "sm" ? "min-h-4" : size === "lg" ? "min-h-8" : "min-h-6"), children: value.length > 0 ? showTags ? /* @__PURE__ */ jsxs35(Fragment13, { children: [
@@ -14972,6 +15202,7 @@ var MultiCombobox = ({
14972
15202
  size === "sm" ? "text-xs" : size === "lg" ? "text-base" : "text-sm",
14973
15203
  "font-medium transition-colors duration-200",
14974
15204
  disabled ? "text-muted-foreground" : "text-foreground group-focus-within:text-primary",
15205
+ effectiveError && "text-destructive",
14975
15206
  labelClassName
14976
15207
  ),
14977
15208
  children: [
@@ -14989,6 +15220,7 @@ var MultiCombobox = ({
14989
15220
  labelSize,
14990
15221
  "font-medium transition-colors duration-200",
14991
15222
  disabled ? "text-muted-foreground" : "text-foreground group-focus-within:text-primary",
15223
+ effectiveError && "text-destructive",
14992
15224
  labelClassName
14993
15225
  ),
14994
15226
  children: [
@@ -14997,6 +15229,23 @@ var MultiCombobox = ({
14997
15229
  ]
14998
15230
  }
14999
15231
  ),
15232
+ /* @__PURE__ */ jsx45(
15233
+ "input",
15234
+ {
15235
+ tabIndex: -1,
15236
+ "aria-hidden": "true",
15237
+ value: value.length > 0 ? "selected" : "",
15238
+ onChange: () => {
15239
+ },
15240
+ required,
15241
+ disabled,
15242
+ onInvalid: (e) => {
15243
+ e.preventDefault();
15244
+ setLocalRequiredError(tv("required"));
15245
+ },
15246
+ className: "pointer-events-none absolute h-0 w-0 opacity-0"
15247
+ }
15248
+ ),
15000
15249
  /* @__PURE__ */ jsx45(
15001
15250
  Popover,
15002
15251
  {
@@ -15010,17 +15259,26 @@ var MultiCombobox = ({
15010
15259
  children: dropdownBody
15011
15260
  }
15012
15261
  ),
15013
- (helperText || error) && /* @__PURE__ */ jsxs35("p", { className: cn("text-xs transition-colors duration-200 flex items-center gap-1.5", error ? "text-destructive" : "text-muted-foreground"), children: [
15014
- error && /* @__PURE__ */ jsx45("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", className: "w-3.5 h-3.5 shrink-0", children: /* @__PURE__ */ jsx45(
15015
- "path",
15016
- {
15017
- fillRule: "evenodd",
15018
- d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z",
15019
- clipRule: "evenodd"
15020
- }
15021
- ) }),
15022
- error || helperText
15023
- ] })
15262
+ (helperText || effectiveError) && /* @__PURE__ */ jsxs35(
15263
+ "p",
15264
+ {
15265
+ className: cn(
15266
+ "text-xs transition-colors duration-200 flex items-center gap-1.5",
15267
+ effectiveError ? "text-destructive" : "text-muted-foreground"
15268
+ ),
15269
+ children: [
15270
+ effectiveError && /* @__PURE__ */ jsx45("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", className: "w-3.5 h-3.5 shrink-0", children: /* @__PURE__ */ jsx45(
15271
+ "path",
15272
+ {
15273
+ fillRule: "evenodd",
15274
+ d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z",
15275
+ clipRule: "evenodd"
15276
+ }
15277
+ ) }),
15278
+ effectiveError || helperText
15279
+ ]
15280
+ }
15281
+ )
15024
15282
  ] });
15025
15283
  };
15026
15284
 
@@ -16169,6 +16427,7 @@ function getInitialExpandedNodes(categories, defaultExpanded, viewOnly, inline)
16169
16427
  return parentIds;
16170
16428
  }
16171
16429
  function CategoryTreeSelect(props) {
16430
+ const tv = useSmartTranslations("ValidationInput");
16172
16431
  const {
16173
16432
  id,
16174
16433
  label,
@@ -16196,14 +16455,16 @@ function CategoryTreeSelect(props) {
16196
16455
  const [isOpen, setIsOpen] = useState30(false);
16197
16456
  const [expandedNodes, setExpandedNodes] = useState30(() => getInitialExpandedNodes(categories, defaultExpanded, viewOnly, inline));
16198
16457
  const [query, setQuery] = useState30("");
16458
+ const [localRequiredError, setLocalRequiredError] = useState30();
16199
16459
  const searchInputRef = useRef19(null);
16200
16460
  const dropdownViewportRef = useRef19(null);
16201
16461
  useOverlayScrollbarTarget(dropdownViewportRef, { enabled: useOverlayScrollbar });
16202
16462
  const autoId = useId9();
16203
16463
  const resolvedId = id ? String(id) : `category-tree-select-${autoId}`;
16204
16464
  const labelId = label ? `${resolvedId}-label` : void 0;
16205
- const helperId = helperText && !error ? `${resolvedId}-helper` : void 0;
16206
- const errorId = error ? `${resolvedId}-error` : void 0;
16465
+ const effectiveError = error ?? localRequiredError;
16466
+ const helperId = helperText && !effectiveError ? `${resolvedId}-helper` : void 0;
16467
+ const errorId = effectiveError ? `${resolvedId}-error` : void 0;
16207
16468
  const describedBy = errorId || helperId;
16208
16469
  const mergedLabels = { ...defaultLabels, ...labels };
16209
16470
  const valueArray = useMemo19(
@@ -16274,6 +16535,11 @@ function CategoryTreeSelect(props) {
16274
16535
  const t = setTimeout(() => searchInputRef.current?.focus(), 50);
16275
16536
  return () => clearTimeout(t);
16276
16537
  }, [isOpen, isSearchEnabled]);
16538
+ useEffect24(() => {
16539
+ if (disabled || !required || valueArray.length > 0) {
16540
+ setLocalRequiredError(void 0);
16541
+ }
16542
+ }, [disabled, required, valueArray.length]);
16277
16543
  const toggleExpand = (id2) => {
16278
16544
  if (isSearchMode) return;
16279
16545
  const newExpanded = new Set(expandedNodes);
@@ -16292,6 +16558,7 @@ function CategoryTreeSelect(props) {
16292
16558
  toggleExpand(categoryId);
16293
16559
  return;
16294
16560
  }
16561
+ setLocalRequiredError(void 0);
16295
16562
  if (!props.onChange) return;
16296
16563
  if (singleSelect) {
16297
16564
  const onChange = props.onChange;
@@ -16463,7 +16730,7 @@ function CategoryTreeSelect(props) {
16463
16730
  className: cn(
16464
16731
  size === "sm" ? "text-xs" : size === "lg" ? "text-base" : "text-sm",
16465
16732
  disabled ? "text-muted-foreground" : "text-foreground",
16466
- error && "text-destructive",
16733
+ effectiveError && "text-destructive",
16467
16734
  labelClassName
16468
16735
  ),
16469
16736
  children: [
@@ -16472,10 +16739,27 @@ function CategoryTreeSelect(props) {
16472
16739
  ]
16473
16740
  }
16474
16741
  ) }) : null;
16475
- const renderAssistiveText = () => error ? /* @__PURE__ */ jsx49("p", { id: errorId, className: "text-sm text-destructive", children: error }) : helperText ? /* @__PURE__ */ jsx49("p", { id: helperId, className: "text-sm text-muted-foreground", children: helperText }) : null;
16742
+ const renderAssistiveText = () => effectiveError ? /* @__PURE__ */ jsx49("p", { id: errorId, className: "text-sm text-destructive", children: effectiveError }) : helperText ? /* @__PURE__ */ jsx49("p", { id: helperId, className: "text-sm text-muted-foreground", children: helperText }) : null;
16476
16743
  if (viewOnly) {
16477
16744
  return /* @__PURE__ */ jsxs39("div", { className: cn("w-full space-y-2", className), children: [
16478
16745
  renderLabel(),
16746
+ /* @__PURE__ */ jsx49(
16747
+ "input",
16748
+ {
16749
+ tabIndex: -1,
16750
+ "aria-hidden": "true",
16751
+ value: valueArray.length > 0 ? "selected" : "",
16752
+ onChange: () => {
16753
+ },
16754
+ required,
16755
+ disabled,
16756
+ onInvalid: (e) => {
16757
+ e.preventDefault();
16758
+ setLocalRequiredError(tv("required"));
16759
+ },
16760
+ className: "pointer-events-none absolute h-0 w-0 opacity-0"
16761
+ }
16762
+ ),
16479
16763
  /* @__PURE__ */ jsxs39(
16480
16764
  "div",
16481
16765
  {
@@ -16495,6 +16779,23 @@ function CategoryTreeSelect(props) {
16495
16779
  if (inline) {
16496
16780
  return /* @__PURE__ */ jsxs39("div", { className: cn("w-full space-y-2", className), children: [
16497
16781
  renderLabel(),
16782
+ /* @__PURE__ */ jsx49(
16783
+ "input",
16784
+ {
16785
+ tabIndex: -1,
16786
+ "aria-hidden": "true",
16787
+ value: valueArray.length > 0 ? "selected" : "",
16788
+ onChange: () => {
16789
+ },
16790
+ required,
16791
+ disabled,
16792
+ onInvalid: (e) => {
16793
+ e.preventDefault();
16794
+ setLocalRequiredError(tv("required"));
16795
+ },
16796
+ className: "pointer-events-none absolute h-0 w-0 opacity-0"
16797
+ }
16798
+ ),
16498
16799
  /* @__PURE__ */ jsxs39(
16499
16800
  "div",
16500
16801
  {
@@ -16594,6 +16895,23 @@ function CategoryTreeSelect(props) {
16594
16895
  ] });
16595
16896
  return /* @__PURE__ */ jsxs39("div", { className: cn("w-full space-y-2", className), children: [
16596
16897
  renderLabel(),
16898
+ /* @__PURE__ */ jsx49(
16899
+ "input",
16900
+ {
16901
+ tabIndex: -1,
16902
+ "aria-hidden": "true",
16903
+ value: valueArray.length > 0 ? "selected" : "",
16904
+ onChange: () => {
16905
+ },
16906
+ required,
16907
+ disabled,
16908
+ onInvalid: (e) => {
16909
+ e.preventDefault();
16910
+ setLocalRequiredError(tv("required"));
16911
+ },
16912
+ className: "pointer-events-none absolute h-0 w-0 opacity-0"
16913
+ }
16914
+ ),
16597
16915
  /* @__PURE__ */ jsx49(
16598
16916
  Popover,
16599
16917
  {
@@ -16620,7 +16938,8 @@ function CategoryTreeSelect(props) {
16620
16938
  "aria-controls": `${resolvedId}-tree`,
16621
16939
  "aria-labelledby": labelId,
16622
16940
  "aria-describedby": describedBy,
16623
- "aria-invalid": !!error,
16941
+ "aria-required": required,
16942
+ "aria-invalid": !!effectiveError,
16624
16943
  className: cn(
16625
16944
  "group flex w-full items-center justify-between rounded-full transition-all duration-200",
16626
16945
  "backdrop-blur-sm",
@@ -16629,7 +16948,7 @@ function CategoryTreeSelect(props) {
16629
16948
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background",
16630
16949
  disabled && "opacity-50 cursor-not-allowed hover:transform-none hover:shadow-none",
16631
16950
  isOpen && "ring-2 ring-primary/30 border-primary/50 shadow-lg shadow-primary/10",
16632
- error && "border-destructive focus-visible:ring-destructive/30"
16951
+ effectiveError && "border-destructive focus-visible:ring-destructive/30"
16633
16952
  ),
16634
16953
  children: [
16635
16954
  /* @__PURE__ */ jsxs39("div", { className: "flex min-w-0 flex-1 items-center gap-2.5 text-left", children: [
@@ -20624,7 +20943,7 @@ function DataTableHeader({
20624
20943
  className: cn(
20625
20944
  "absolute inset-y-0 right-0 z-10 w-3 -mr-1",
20626
20945
  "cursor-col-resize select-none bg-transparent",
20627
- "after:absolute after:inset-y-2 after:right-[3px] after:w-px after:bg-border/0 after:transition-colors",
20946
+ "after:absolute after:inset-y-2 after:right-0.8 after:w-px after:bg-border/0 after:transition-colors",
20628
20947
  "hover:after:bg-primary/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary"
20629
20948
  )
20630
20949
  }
@@ -23903,7 +24222,7 @@ var TableInsertGrid = ({
23903
24222
  onFocus: () => setSelection({ rows, cols }),
23904
24223
  onClick: () => onInsert(rows, cols),
23905
24224
  className: cn(
23906
- "h-5 w-5 rounded-[4px] border transition-colors",
24225
+ "h-5 w-5 rounded-sm border transition-colors",
23907
24226
  active ? "border-primary bg-primary/20" : "border-border/70 bg-background hover:border-primary/60 hover:bg-primary/10"
23908
24227
  )
23909
24228
  },