@underverse-ui/underverse 1.0.81 → 1.0.83

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.cjs CHANGED
@@ -7099,7 +7099,6 @@ var getOptionDisabled = (option) => {
7099
7099
  var findOptionByValue = (options, value) => {
7100
7100
  return options.find((opt) => getOptionValue(opt) === value);
7101
7101
  };
7102
- var REQUIRED_ERROR_MESSAGE = "This field is required";
7103
7102
  var Combobox = ({
7104
7103
  id,
7105
7104
  options,
@@ -7129,6 +7128,7 @@ var Combobox = ({
7129
7128
  helperText,
7130
7129
  useOverlayScrollbar = false
7131
7130
  }) => {
7131
+ const tv = useSmartTranslations("ValidationInput");
7132
7132
  const [open, setOpen] = React24.useState(false);
7133
7133
  const [query, setQuery] = React24.useState("");
7134
7134
  const [activeIndex, setActiveIndex] = React24.useState(null);
@@ -7478,13 +7478,14 @@ var Combobox = ({
7478
7478
  {
7479
7479
  tabIndex: -1,
7480
7480
  "aria-hidden": "true",
7481
- readOnly: true,
7482
7481
  value: hasValue ? "selected" : "",
7482
+ onChange: () => {
7483
+ },
7483
7484
  required,
7484
7485
  disabled,
7485
7486
  onInvalid: (e) => {
7486
7487
  e.preventDefault();
7487
- setLocalRequiredError(REQUIRED_ERROR_MESSAGE);
7488
+ setLocalRequiredError(tv("required"));
7488
7489
  },
7489
7490
  className: "pointer-events-none absolute h-0 w-0 opacity-0"
7490
7491
  }
@@ -8196,7 +8197,6 @@ var import_lucide_react15 = require("lucide-react");
8196
8197
  var React28 = __toESM(require("react"), 1);
8197
8198
  var import_react19 = require("react");
8198
8199
  var import_jsx_runtime34 = require("react/jsx-runtime");
8199
- var REQUIRED_ERROR_MESSAGE2 = "This field is required";
8200
8200
  var DatePicker = ({
8201
8201
  id,
8202
8202
  value,
@@ -8216,6 +8216,7 @@ var DatePicker = ({
8216
8216
  maxDate
8217
8217
  }) => {
8218
8218
  const t = useSmartTranslations("DatePicker");
8219
+ const tv = useSmartTranslations("ValidationInput");
8219
8220
  const locale = useSmartLocale();
8220
8221
  const [isOpen, setIsOpen] = React28.useState(false);
8221
8222
  const [viewDate, setViewDate] = React28.useState(value || /* @__PURE__ */ new Date());
@@ -8633,13 +8634,14 @@ var DatePicker = ({
8633
8634
  {
8634
8635
  tabIndex: -1,
8635
8636
  "aria-hidden": "true",
8636
- readOnly: true,
8637
8637
  value: value ? "selected" : "",
8638
+ onChange: () => {
8639
+ },
8638
8640
  required,
8639
8641
  disabled,
8640
8642
  onInvalid: (e) => {
8641
8643
  e.preventDefault();
8642
- setLocalRequiredError(REQUIRED_ERROR_MESSAGE2);
8644
+ setLocalRequiredError(tv("required"));
8643
8645
  },
8644
8646
  className: "pointer-events-none absolute h-0 w-0 opacity-0"
8645
8647
  }
@@ -8751,10 +8753,27 @@ var DatePicker = ({
8751
8753
  effectiveError && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "text-xs text-destructive", children: effectiveError })
8752
8754
  ] });
8753
8755
  };
8754
- var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select date range...", className, disablePastDates = false, minDate, maxDate, size = "md" }) => {
8756
+ var DateRangePicker = ({
8757
+ id,
8758
+ startDate,
8759
+ endDate,
8760
+ onChange,
8761
+ placeholder = "Select date range...",
8762
+ className,
8763
+ label,
8764
+ labelClassName,
8765
+ required = false,
8766
+ disablePastDates = false,
8767
+ minDate,
8768
+ maxDate,
8769
+ size = "md"
8770
+ }) => {
8755
8771
  const locale = useSmartLocale();
8756
8772
  const t = useSmartTranslations("DatePicker");
8773
+ const tv = useSmartTranslations("ValidationInput");
8757
8774
  const [isOpen, setIsOpen] = React28.useState(false);
8775
+ const [viewMode, setViewMode] = React28.useState("calendar");
8776
+ const [localRequiredError, setLocalRequiredError] = React28.useState();
8758
8777
  const wheelContainerRef = React28.useRef(null);
8759
8778
  const wheelDeltaRef = React28.useRef(0);
8760
8779
  const sizeStyles8 = {
@@ -8826,6 +8845,16 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
8826
8845
  React28.useEffect(() => {
8827
8846
  setTempEnd(normalizeToLocal(endDate));
8828
8847
  }, [endDate]);
8848
+ React28.useEffect(() => {
8849
+ if (!isOpen) {
8850
+ setViewMode("calendar");
8851
+ }
8852
+ }, [isOpen]);
8853
+ React28.useEffect(() => {
8854
+ if (!required || startDate && endDate) {
8855
+ setLocalRequiredError(void 0);
8856
+ }
8857
+ }, [endDate, required, startDate]);
8829
8858
  const isSameDay2 = (a, b) => {
8830
8859
  if (!a || !b) return false;
8831
8860
  return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
@@ -8836,6 +8865,9 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
8836
8865
  const navigateMonth = React28.useCallback((direction) => {
8837
8866
  setViewDate((prev) => new Date(prev.getFullYear(), prev.getMonth() + (direction === "next" ? 1 : -1), 1));
8838
8867
  }, []);
8868
+ const navigateYearRange = React28.useCallback((direction) => {
8869
+ setViewDate((prev) => new Date(prev.getFullYear() + (direction === "next" ? 12 : -12), prev.getMonth(), 1));
8870
+ }, []);
8839
8871
  const isElementVerticallyScrollable = (el) => {
8840
8872
  const style = window.getComputedStyle(el);
8841
8873
  const overflowY = style.overflowY;
@@ -8880,11 +8912,33 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
8880
8912
  setTempStart(localDate);
8881
8913
  } else {
8882
8914
  setTempEnd(localDate);
8915
+ setLocalRequiredError(void 0);
8883
8916
  onChange(tempStart, localDate);
8884
8917
  setIsOpen(false);
8885
8918
  }
8886
8919
  }
8887
8920
  };
8921
+ const handleSelectToday = () => {
8922
+ const today = /* @__PURE__ */ new Date();
8923
+ today.setHours(0, 0, 0, 0);
8924
+ const localToday = new Date(today.getFullYear(), today.getMonth(), today.getDate());
8925
+ const isPastDate = disablePastDates && localToday < today;
8926
+ const isOutOfRange = !!minDay && localToday < minDay || !!maxDay && localToday > maxDay;
8927
+ if (isPastDate || isOutOfRange) return;
8928
+ setTempStart(localToday);
8929
+ setTempEnd(localToday);
8930
+ setHoveredDate(null);
8931
+ setLocalRequiredError(void 0);
8932
+ onChange(localToday, localToday);
8933
+ setIsOpen(false);
8934
+ };
8935
+ const handleClear = () => {
8936
+ setTempStart(null);
8937
+ setTempEnd(null);
8938
+ setHoveredDate(null);
8939
+ onChange(void 0, void 0);
8940
+ setIsOpen(false);
8941
+ };
8888
8942
  const renderGrid = () => {
8889
8943
  const nodes = [];
8890
8944
  const daysInMonth = getDaysInMonth(viewDate);
@@ -8953,13 +9007,63 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
8953
9007
  }
8954
9008
  return nodes;
8955
9009
  };
9010
+ const renderMonthSelector = () => {
9011
+ const months = locale === "vi" ? ["Th1", "Th2", "Th3", "Th4", "Th5", "Th6", "Th7", "Th8", "Th9", "Th10", "Th11", "Th12"] : ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
9012
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "grid grid-cols-3 gap-2 p-2", children: months.map((month, idx) => {
9013
+ const isSelected = viewDate.getMonth() === idx;
9014
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
9015
+ "button",
9016
+ {
9017
+ type: "button",
9018
+ onClick: () => {
9019
+ setViewDate(new Date(viewDate.getFullYear(), idx, 1));
9020
+ setViewMode("calendar");
9021
+ },
9022
+ className: cn(
9023
+ "py-2 px-3 rounded-lg text-sm font-medium transition-all duration-200",
9024
+ isSelected ? "bg-primary text-primary-foreground shadow-md" : "hover:bg-accent/80 text-foreground hover:scale-105"
9025
+ ),
9026
+ children: month
9027
+ },
9028
+ month
9029
+ );
9030
+ }) });
9031
+ };
9032
+ const renderYearSelector = () => {
9033
+ const startYear = Math.floor(viewDate.getFullYear() / 12) * 12;
9034
+ const years = Array.from({ length: 12 }, (_, i) => startYear + i);
9035
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "grid grid-cols-3 gap-2 p-2", children: years.map((year) => {
9036
+ const isSelected = viewDate.getFullYear() === year;
9037
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
9038
+ "button",
9039
+ {
9040
+ type: "button",
9041
+ onClick: () => {
9042
+ setViewDate(new Date(year, viewDate.getMonth(), 1));
9043
+ setViewMode("month");
9044
+ },
9045
+ className: cn(
9046
+ "py-2 px-3 rounded-lg text-sm font-medium transition-all duration-200",
9047
+ isSelected ? "bg-primary text-primary-foreground shadow-md" : "hover:bg-accent/80 text-foreground hover:scale-105"
9048
+ ),
9049
+ children: year
9050
+ },
9051
+ year
9052
+ );
9053
+ }) });
9054
+ };
9055
+ const todayDate = React28.useMemo(() => {
9056
+ const today = /* @__PURE__ */ new Date();
9057
+ return new Date(today.getFullYear(), today.getMonth(), today.getDate());
9058
+ }, []);
9059
+ const isTodayUnavailable = !!minDay && todayDate < minDay || !!maxDay && todayDate > maxDay;
8956
9060
  const panel = /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { ref: wheelContainerRef, className: "w-full", children: [
8957
9061
  /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: cn("flex items-center justify-between px-1", sizeStyles8[size].headerMargin), children: [
8958
9062
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
8959
9063
  "button",
8960
9064
  {
8961
9065
  type: "button",
8962
- onClick: () => navigateMonth("prev"),
9066
+ onClick: () => viewMode === "year" ? navigateYearRange("prev") : navigateMonth("prev"),
8963
9067
  className: cn(
8964
9068
  "rounded-xl transition-all duration-200",
8965
9069
  sizeStyles8[size].navButton,
@@ -8970,15 +9074,39 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
8970
9074
  children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react15.ChevronLeft, { className: sizeStyles8[size].navIcon })
8971
9075
  }
8972
9076
  ),
8973
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex flex-col items-center", children: [
8974
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: cn("font-bold text-foreground", size === "sm" ? "text-xs" : size === "lg" ? "text-base" : "text-sm"), children: viewDate.toLocaleDateString(locale === "vi" ? "vi-VN" : "en-US", { month: "long" }) }),
8975
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: cn("text-muted-foreground font-medium", size === "sm" ? "text-[10px]" : size === "lg" ? "text-sm" : "text-xs"), children: viewDate.getFullYear() })
9077
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center gap-1", children: [
9078
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
9079
+ "button",
9080
+ {
9081
+ type: "button",
9082
+ onClick: () => setViewMode(viewMode === "month" ? "calendar" : "month"),
9083
+ className: cn(
9084
+ "rounded-lg px-2 py-0.5 font-bold transition-colors duration-200",
9085
+ size === "sm" ? "text-xs" : size === "lg" ? "text-base" : "text-sm",
9086
+ viewMode === "month" ? "bg-primary/15 text-primary" : "text-foreground hover:bg-accent/50"
9087
+ ),
9088
+ children: viewDate.toLocaleDateString(locale === "vi" ? "vi-VN" : "en-US", { month: "long" })
9089
+ }
9090
+ ),
9091
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
9092
+ "button",
9093
+ {
9094
+ type: "button",
9095
+ onClick: () => setViewMode(viewMode === "year" ? "calendar" : "year"),
9096
+ className: cn(
9097
+ "rounded-lg px-2 py-0.5 font-medium transition-colors duration-200",
9098
+ size === "sm" ? "text-[10px]" : size === "lg" ? "text-sm" : "text-xs",
9099
+ viewMode === "year" ? "bg-primary/15 text-primary" : "text-muted-foreground hover:bg-accent/50 hover:text-foreground"
9100
+ ),
9101
+ children: viewDate.getFullYear()
9102
+ }
9103
+ )
8976
9104
  ] }),
8977
9105
  /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
8978
9106
  "button",
8979
9107
  {
8980
9108
  type: "button",
8981
- onClick: () => navigateMonth("next"),
9109
+ onClick: () => viewMode === "year" ? navigateYearRange("next") : navigateMonth("next"),
8982
9110
  className: cn(
8983
9111
  "rounded-xl transition-all duration-200",
8984
9112
  sizeStyles8[size].navButton,
@@ -8990,82 +9118,167 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
8990
9118
  }
8991
9119
  )
8992
9120
  ] }),
8993
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: cn("grid grid-cols-7 gap-1 px-0.5", size === "sm" ? "mb-1" : size === "lg" ? "mb-3" : "mb-2"), children: (locale === "vi" ? ["CN", "T2", "T3", "T4", "T5", "T6", "T7"] : ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]).map((d, idx) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
8994
- "div",
8995
- {
8996
- className: cn(
8997
- "text-center font-bold uppercase tracking-wide",
8998
- sizeStyles8[size].weekdayLabel,
8999
- idx === 0 || idx === 6 ? "text-primary/70" : "text-muted-foreground/60"
9000
- ),
9001
- children: d
9002
- },
9003
- d
9004
- )) }),
9005
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "grid grid-cols-7 gap-0.5 p-1 rounded-xl bg-muted/20", children: renderGrid() })
9006
- ] });
9007
- const displayFormat = (date) => formatDateShort(date);
9008
- const label = tempStart && tempEnd ? `${displayFormat(tempStart)} - ${displayFormat(tempEnd)}` : tempStart ? `${displayFormat(tempStart)} - ...` : placeholder;
9009
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
9010
- Popover,
9011
- {
9012
- open: isOpen,
9013
- onOpenChange: setIsOpen,
9014
- placement: "bottom-start",
9015
- contentWidth: size === "sm" ? 240 : 280,
9016
- contentClassName: cn(
9017
- "p-0",
9018
- "backdrop-blur-xl bg-popover/95 border-border/40 shadow-2xl",
9019
- "rounded-2xl md:rounded-3xl",
9020
- "max-w-[calc(100vw-1rem)] max-h-[calc(100vh-6rem)] overflow-auto overscroll-contain",
9021
- size === "sm" ? "p-3" : "p-5",
9022
- "animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-300"
9023
- ),
9024
- trigger: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
9121
+ viewMode === "calendar" && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
9122
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: cn("grid grid-cols-7 gap-1 px-0.5", size === "sm" ? "mb-1" : size === "lg" ? "mb-3" : "mb-2"), children: (locale === "vi" ? ["CN", "T2", "T3", "T4", "T5", "T6", "T7"] : ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]).map((d, idx) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
9123
+ "div",
9124
+ {
9125
+ className: cn(
9126
+ "text-center font-bold uppercase tracking-wide",
9127
+ sizeStyles8[size].weekdayLabel,
9128
+ idx === 0 || idx === 6 ? "text-primary/70" : "text-muted-foreground/60"
9129
+ ),
9130
+ children: d
9131
+ },
9132
+ d
9133
+ )) }),
9134
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "grid grid-cols-7 gap-0.5 p-1 rounded-xl bg-muted/20", children: renderGrid() })
9135
+ ] }),
9136
+ viewMode === "month" && renderMonthSelector(),
9137
+ viewMode === "year" && renderYearSelector(),
9138
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: cn("flex items-center border-t border-border/50", sizeStyles8[size].footerMargin), children: [
9139
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
9025
9140
  "button",
9026
9141
  {
9027
9142
  type: "button",
9143
+ onClick: handleSelectToday,
9144
+ disabled: isTodayUnavailable,
9028
9145
  className: cn(
9029
- "group flex w-full items-center justify-between rounded-full border bg-background/80 backdrop-blur-sm",
9030
- size === "sm" ? "px-2 py-1.5 text-xs" : "px-3 py-2.5 text-sm",
9031
- "border-border/60 hover:border-primary/40",
9032
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background",
9033
- "hover:bg-accent/10 hover:shadow-lg hover:shadow-primary/5 hover:-translate-y-0.5",
9034
- "transition-all duration-300 ease-out",
9035
- isOpen && "ring-2 ring-primary/30 border-primary/50 shadow-lg shadow-primary/10",
9036
- className
9146
+ "flex-1 font-semibold rounded-xl",
9147
+ "bg-linear-to-r from-primary/10 to-primary/5 border border-primary/30",
9148
+ "text-primary hover:from-primary/20 hover:to-primary/10 hover:border-primary/50",
9149
+ "transition-all duration-300 flex items-center justify-center",
9150
+ "hover:scale-[1.02] active:scale-[0.98] hover:shadow-md hover:shadow-primary/10",
9151
+ sizeStyles8[size].actionButton,
9152
+ isTodayUnavailable && "opacity-50 cursor-not-allowed hover:scale-100 active:scale-100"
9037
9153
  ),
9038
9154
  children: [
9039
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: cn("flex items-center", size === "sm" ? "gap-1.5" : "gap-2.5"), children: [
9040
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
9041
- "div",
9042
- {
9043
- className: cn(
9044
- "flex items-center justify-center transition-colors duration-300",
9045
- isOpen ? "text-primary" : "text-muted-foreground group-hover:text-primary"
9046
- ),
9047
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react15.Calendar, { className: cn("transition-transform duration-300", size === "sm" ? "h-3 w-3" : "h-4 w-4", isOpen && "scale-110") })
9048
- }
9049
- ),
9050
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
9051
- "span",
9052
- {
9053
- className: cn(
9054
- "truncate font-medium transition-colors duration-200",
9055
- !tempStart && !tempEnd && "text-muted-foreground",
9056
- (tempStart || tempEnd) && "text-foreground"
9057
- ),
9058
- children: label
9059
- }
9060
- )
9061
- ] }),
9062
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: cn("transition-all duration-300 text-muted-foreground group-hover:text-foreground", isOpen && "rotate-180 text-primary"), children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("svg", { className: cn(size === "sm" ? "h-3 w-3" : "h-4 w-4"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) }) })
9155
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react15.Sparkles, { className: sizeStyles8[size].actionIcon }),
9156
+ t("today")
9063
9157
  ]
9064
9158
  }
9065
9159
  ),
9066
- children: panel
9067
- }
9068
- );
9160
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
9161
+ "button",
9162
+ {
9163
+ type: "button",
9164
+ onClick: handleClear,
9165
+ className: cn(
9166
+ "flex-1 font-semibold rounded-xl",
9167
+ "bg-linear-to-r from-destructive/10 to-destructive/5 border border-destructive/30",
9168
+ "text-destructive hover:from-destructive/20 hover:to-destructive/10 hover:border-destructive/50",
9169
+ "transition-all duration-300 flex items-center justify-center",
9170
+ "hover:scale-[1.02] active:scale-[0.98] hover:shadow-md hover:shadow-destructive/10",
9171
+ sizeStyles8[size].actionButton
9172
+ ),
9173
+ children: [
9174
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react15.X, { className: sizeStyles8[size].actionIcon }),
9175
+ t("clear")
9176
+ ]
9177
+ }
9178
+ )
9179
+ ] })
9180
+ ] });
9181
+ const displayFormat = (date) => formatDateShort(date);
9182
+ const displayLabel = tempStart && tempEnd ? `${displayFormat(tempStart)} - ${displayFormat(tempEnd)}` : tempStart ? `${displayFormat(tempStart)} - ...` : placeholder;
9183
+ const effectiveError = localRequiredError;
9184
+ const autoId = (0, import_react19.useId)();
9185
+ const resolvedId = id ? String(id) : `daterangepicker-${autoId}`;
9186
+ const labelId = label ? `${resolvedId}-label` : void 0;
9187
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: cn("space-y-1.5", className), children: [
9188
+ label && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
9189
+ "label",
9190
+ {
9191
+ id: labelId,
9192
+ htmlFor: resolvedId,
9193
+ className: cn(size === "sm" ? "text-xs" : size === "lg" ? "text-base" : "text-sm", "font-medium text-foreground", effectiveError && "text-destructive", labelClassName),
9194
+ children: [
9195
+ label,
9196
+ required && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-destructive ml-1", children: "*" })
9197
+ ]
9198
+ }
9199
+ ),
9200
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
9201
+ "input",
9202
+ {
9203
+ tabIndex: -1,
9204
+ "aria-hidden": "true",
9205
+ value: startDate && endDate ? "selected" : "",
9206
+ onChange: () => {
9207
+ },
9208
+ required,
9209
+ onInvalid: (e) => {
9210
+ e.preventDefault();
9211
+ setLocalRequiredError(tv("required"));
9212
+ },
9213
+ className: "pointer-events-none absolute h-0 w-0 opacity-0"
9214
+ }
9215
+ ),
9216
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
9217
+ Popover,
9218
+ {
9219
+ open: isOpen,
9220
+ onOpenChange: setIsOpen,
9221
+ placement: "bottom-start",
9222
+ contentWidth: sizeStyles8[size].contentWidth,
9223
+ contentClassName: cn(
9224
+ "p-0",
9225
+ "backdrop-blur-xl bg-popover/95 border-border/40 shadow-2xl",
9226
+ "rounded-2xl md:rounded-3xl",
9227
+ "max-w-[calc(100vw-1rem)] max-h-[calc(100vh-6rem)] overflow-auto overscroll-contain",
9228
+ sizeStyles8[size].contentPadding,
9229
+ "animate-in fade-in-0 zoom-in-95 slide-in-from-top-2 duration-300"
9230
+ ),
9231
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
9232
+ "button",
9233
+ {
9234
+ id: resolvedId,
9235
+ type: "button",
9236
+ "aria-labelledby": labelId,
9237
+ "aria-required": required,
9238
+ "aria-invalid": !!effectiveError,
9239
+ className: cn(
9240
+ "group flex w-full items-center justify-between rounded-full border bg-background/80 backdrop-blur-sm",
9241
+ sizeStyles8[size].trigger,
9242
+ "border-border/60 hover:border-primary/40",
9243
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background",
9244
+ "hover:bg-accent/10 hover:shadow-lg hover:shadow-primary/5 hover:-translate-y-0.5",
9245
+ "transition-all duration-300 ease-out",
9246
+ isOpen && "ring-2 ring-primary/30 border-primary/50 shadow-lg shadow-primary/10",
9247
+ effectiveError && "border-destructive/60 focus-visible:ring-destructive/50 bg-destructive/5"
9248
+ ),
9249
+ children: [
9250
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: cn("flex items-center", size === "sm" ? "gap-1.5" : "gap-2.5"), children: [
9251
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
9252
+ "div",
9253
+ {
9254
+ className: cn(
9255
+ "flex items-center justify-center transition-colors duration-300",
9256
+ effectiveError ? "text-destructive" : isOpen ? "text-primary" : "text-muted-foreground group-hover:text-primary"
9257
+ ),
9258
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react15.Calendar, { className: cn("transition-transform duration-300", sizeStyles8[size].calendarIcon, isOpen && "scale-110") })
9259
+ }
9260
+ ),
9261
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
9262
+ "span",
9263
+ {
9264
+ className: cn(
9265
+ "truncate font-medium transition-colors duration-200",
9266
+ !tempStart && !tempEnd && "text-muted-foreground",
9267
+ (tempStart || tempEnd) && "text-foreground"
9268
+ ),
9269
+ children: displayLabel
9270
+ }
9271
+ )
9272
+ ] }),
9273
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: cn("transition-all duration-300 text-muted-foreground group-hover:text-foreground", isOpen && "rotate-180 text-primary"), children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("svg", { className: cn(sizeStyles8[size].navIcon), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) }) })
9274
+ ]
9275
+ }
9276
+ ),
9277
+ children: panel
9278
+ }
9279
+ ),
9280
+ effectiveError && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "text-xs text-destructive", children: effectiveError })
9281
+ ] });
9069
9282
  };
9070
9283
  var CompactDatePicker = ({ value, onChange, className }) => {
9071
9284
  return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
@@ -9092,7 +9305,6 @@ var React30 = __toESM(require("react"), 1);
9092
9305
  var React29 = __toESM(require("react"), 1);
9093
9306
  var import_lucide_react16 = require("lucide-react");
9094
9307
  var import_jsx_runtime35 = require("react/jsx-runtime");
9095
- var REQUIRED_ERROR_MESSAGE3 = "This field is required";
9096
9308
  var DEFAULT_MONTH_NAMES = [
9097
9309
  "January",
9098
9310
  "February",
@@ -9570,6 +9782,7 @@ function MonthYearPicker({
9570
9782
  className,
9571
9783
  ...rest
9572
9784
  }) {
9785
+ const tv = useSmartTranslations("ValidationInput");
9573
9786
  const now = /* @__PURE__ */ new Date();
9574
9787
  const currentYear = now.getFullYear();
9575
9788
  const resolvedMinYear = minYear ?? minDate?.getFullYear() ?? currentYear - 50;
@@ -9587,6 +9800,7 @@ function MonthYearPicker({
9587
9800
  const [parts, setParts] = React29.useState(initial);
9588
9801
  const [focusedColumn, setFocusedColumn] = React29.useState(null);
9589
9802
  const [localRequiredError, setLocalRequiredError] = React29.useState();
9803
+ const [hasCommittedValue, setHasCommittedValue] = React29.useState(Boolean(parseValue(isControlled ? value : defaultValue)));
9590
9804
  const monthScrollRef = React29.useRef(null);
9591
9805
  const yearScrollRef = React29.useRef(null);
9592
9806
  React29.useEffect(() => {
@@ -9595,7 +9809,12 @@ function MonthYearPicker({
9595
9809
  if (parsed) setParts(parsed);
9596
9810
  }
9597
9811
  }, [value, isControlled]);
9598
- const hasValue = isControlled ? !!value : !!defaultValue || parts !== initial;
9812
+ React29.useEffect(() => {
9813
+ if (isControlled) {
9814
+ setHasCommittedValue(Boolean(parseValue(value)));
9815
+ }
9816
+ }, [isControlled, value]);
9817
+ const hasValue = hasCommittedValue;
9599
9818
  const effectiveError = error ?? localRequiredError;
9600
9819
  React29.useEffect(() => {
9601
9820
  if (disabled || !required || hasValue) {
@@ -9626,15 +9845,17 @@ function MonthYearPicker({
9626
9845
  (next) => {
9627
9846
  if (!next) {
9628
9847
  setLocalRequiredError(void 0);
9848
+ if (!isControlled) setHasCommittedValue(false);
9629
9849
  onChange?.(void 0);
9630
9850
  return;
9631
9851
  }
9632
9852
  if (!isDateInRange(next.month, next.year)) return;
9633
9853
  const date = new Date(next.year, next.month, 1);
9634
9854
  setLocalRequiredError(void 0);
9855
+ if (!isControlled) setHasCommittedValue(true);
9635
9856
  onChange?.({ ...next, date });
9636
9857
  },
9637
- [isDateInRange, onChange]
9858
+ [isControlled, isDateInRange, onChange]
9638
9859
  );
9639
9860
  const tryUpdate = React29.useCallback(
9640
9861
  (next) => {
@@ -9882,13 +10103,14 @@ function MonthYearPicker({
9882
10103
  {
9883
10104
  tabIndex: -1,
9884
10105
  "aria-hidden": "true",
9885
- readOnly: true,
9886
10106
  value: hasValue ? "selected" : "",
10107
+ onChange: () => {
10108
+ },
9887
10109
  required,
9888
10110
  disabled,
9889
10111
  onInvalid: (e) => {
9890
10112
  e.preventDefault();
9891
- setLocalRequiredError(REQUIRED_ERROR_MESSAGE3);
10113
+ setLocalRequiredError(tv("required"));
9892
10114
  },
9893
10115
  className: "pointer-events-none absolute h-0 w-0 opacity-0"
9894
10116
  }
@@ -9917,13 +10139,14 @@ function MonthYearPicker({
9917
10139
  {
9918
10140
  tabIndex: -1,
9919
10141
  "aria-hidden": "true",
9920
- readOnly: true,
9921
10142
  value: hasValue ? "selected" : "",
10143
+ onChange: () => {
10144
+ },
9922
10145
  required,
9923
10146
  disabled,
9924
10147
  onInvalid: (e) => {
9925
10148
  e.preventDefault();
9926
- setLocalRequiredError(REQUIRED_ERROR_MESSAGE3);
10149
+ setLocalRequiredError(tv("required"));
9927
10150
  },
9928
10151
  className: "pointer-events-none absolute h-0 w-0 opacity-0"
9929
10152
  }
@@ -10599,7 +10822,6 @@ function Calendar3({
10599
10822
  var React31 = __toESM(require("react"), 1);
10600
10823
  var import_lucide_react18 = require("lucide-react");
10601
10824
  var import_jsx_runtime37 = require("react/jsx-runtime");
10602
- var REQUIRED_ERROR_MESSAGE4 = "This field is required";
10603
10825
  var pad = (n) => n.toString().padStart(2, "0");
10604
10826
  var clamp4 = (n, min, max) => Math.min(max, Math.max(min, n));
10605
10827
  var WHEEL_ITEM_HEIGHT2 = {
@@ -11083,6 +11305,7 @@ function TimePicker({
11083
11305
  className,
11084
11306
  ...rest
11085
11307
  }) {
11308
+ const tv = useSmartTranslations("ValidationInput");
11086
11309
  const isControlled = value !== void 0;
11087
11310
  const now = /* @__PURE__ */ new Date();
11088
11311
  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() });
@@ -11663,13 +11886,14 @@ function TimePicker({
11663
11886
  {
11664
11887
  tabIndex: -1,
11665
11888
  "aria-hidden": "true",
11666
- readOnly: true,
11667
11889
  value: hasCommittedValue ? "selected" : "",
11890
+ onChange: () => {
11891
+ },
11668
11892
  required,
11669
11893
  disabled,
11670
11894
  onInvalid: (e) => {
11671
11895
  e.preventDefault();
11672
- setLocalRequiredError(REQUIRED_ERROR_MESSAGE4);
11896
+ setLocalRequiredError(tv("required"));
11673
11897
  },
11674
11898
  className: "pointer-events-none absolute h-0 w-0 opacity-0"
11675
11899
  }
@@ -11712,13 +11936,14 @@ function TimePicker({
11712
11936
  {
11713
11937
  tabIndex: -1,
11714
11938
  "aria-hidden": "true",
11715
- readOnly: true,
11716
11939
  value: hasCommittedValue ? "selected" : "",
11940
+ onChange: () => {
11941
+ },
11717
11942
  required,
11718
11943
  disabled,
11719
11944
  onInvalid: (e) => {
11720
11945
  e.preventDefault();
11721
- setLocalRequiredError(REQUIRED_ERROR_MESSAGE4);
11946
+ setLocalRequiredError(tv("required"));
11722
11947
  },
11723
11948
  className: "pointer-events-none absolute h-0 w-0 opacity-0"
11724
11949
  }
@@ -11760,7 +11985,6 @@ function TimePicker({
11760
11985
 
11761
11986
  // src/components/DateTimePicker.tsx
11762
11987
  var import_jsx_runtime38 = require("react/jsx-runtime");
11763
- var REQUIRED_ERROR_MESSAGE5 = "This field is required";
11764
11988
  var DateTimePicker = ({
11765
11989
  value,
11766
11990
  onChange,
@@ -11779,6 +12003,7 @@ var DateTimePicker = ({
11779
12003
  size = "md"
11780
12004
  }) => {
11781
12005
  const t = useSmartTranslations("DateTimePicker");
12006
+ const tv = useSmartTranslations("ValidationInput");
11782
12007
  const locale = useSmartLocale();
11783
12008
  const [open, setOpen] = React32.useState(false);
11784
12009
  const [localRequiredError, setLocalRequiredError] = React32.useState();
@@ -11930,13 +12155,14 @@ var DateTimePicker = ({
11930
12155
  {
11931
12156
  tabIndex: -1,
11932
12157
  "aria-hidden": "true",
11933
- readOnly: true,
11934
12158
  value: value ? "selected" : "",
12159
+ onChange: () => {
12160
+ },
11935
12161
  required,
11936
12162
  disabled,
11937
12163
  onInvalid: (e) => {
11938
12164
  e.preventDefault();
11939
- setLocalRequiredError(REQUIRED_ERROR_MESSAGE5);
12165
+ setLocalRequiredError(tv("required"));
11940
12166
  },
11941
12167
  className: "pointer-events-none absolute h-0 w-0 opacity-0"
11942
12168
  }
@@ -14957,7 +15183,6 @@ var React39 = __toESM(require("react"), 1);
14957
15183
  var import_react20 = require("react");
14958
15184
  var import_lucide_react24 = require("lucide-react");
14959
15185
  var import_jsx_runtime45 = require("react/jsx-runtime");
14960
- var REQUIRED_ERROR_MESSAGE6 = "This field is required";
14961
15186
  var MultiCombobox = ({
14962
15187
  id,
14963
15188
  options,
@@ -14991,6 +15216,7 @@ var MultiCombobox = ({
14991
15216
  maxTagsVisible = 3,
14992
15217
  useOverlayScrollbar = false
14993
15218
  }) => {
15219
+ const tv = useSmartTranslations("ValidationInput");
14994
15220
  const [query, setQuery] = React39.useState("");
14995
15221
  const [open, setOpen] = React39.useState(false);
14996
15222
  const [activeIndex, setActiveIndex] = React39.useState(null);
@@ -15404,13 +15630,14 @@ var MultiCombobox = ({
15404
15630
  {
15405
15631
  tabIndex: -1,
15406
15632
  "aria-hidden": "true",
15407
- readOnly: true,
15408
15633
  value: value.length > 0 ? "selected" : "",
15634
+ onChange: () => {
15635
+ },
15409
15636
  required,
15410
15637
  disabled,
15411
15638
  onInvalid: (e) => {
15412
15639
  e.preventDefault();
15413
- setLocalRequiredError(REQUIRED_ERROR_MESSAGE6);
15640
+ setLocalRequiredError(tv("required"));
15414
15641
  },
15415
15642
  className: "pointer-events-none absolute h-0 w-0 opacity-0"
15416
15643
  }
@@ -16585,7 +16812,6 @@ var defaultLabels = {
16585
16812
  searchPlaceholder: "Search...",
16586
16813
  noResultsText: "No results found"
16587
16814
  };
16588
- var REQUIRED_ERROR_MESSAGE7 = "This field is required";
16589
16815
  function getInitialExpandedNodes(categories, defaultExpanded, viewOnly, inline) {
16590
16816
  if (!(viewOnly || inline) || !defaultExpanded) return /* @__PURE__ */ new Set();
16591
16817
  const parentIds = /* @__PURE__ */ new Set();
@@ -16597,6 +16823,7 @@ function getInitialExpandedNodes(categories, defaultExpanded, viewOnly, inline)
16597
16823
  return parentIds;
16598
16824
  }
16599
16825
  function CategoryTreeSelect(props) {
16826
+ const tv = useSmartTranslations("ValidationInput");
16600
16827
  const {
16601
16828
  id,
16602
16829
  label,
@@ -16917,13 +17144,14 @@ function CategoryTreeSelect(props) {
16917
17144
  {
16918
17145
  tabIndex: -1,
16919
17146
  "aria-hidden": "true",
16920
- readOnly: true,
16921
17147
  value: valueArray.length > 0 ? "selected" : "",
17148
+ onChange: () => {
17149
+ },
16922
17150
  required,
16923
17151
  disabled,
16924
17152
  onInvalid: (e) => {
16925
17153
  e.preventDefault();
16926
- setLocalRequiredError(REQUIRED_ERROR_MESSAGE7);
17154
+ setLocalRequiredError(tv("required"));
16927
17155
  },
16928
17156
  className: "pointer-events-none absolute h-0 w-0 opacity-0"
16929
17157
  }
@@ -16952,13 +17180,14 @@ function CategoryTreeSelect(props) {
16952
17180
  {
16953
17181
  tabIndex: -1,
16954
17182
  "aria-hidden": "true",
16955
- readOnly: true,
16956
17183
  value: valueArray.length > 0 ? "selected" : "",
17184
+ onChange: () => {
17185
+ },
16957
17186
  required,
16958
17187
  disabled,
16959
17188
  onInvalid: (e) => {
16960
17189
  e.preventDefault();
16961
- setLocalRequiredError(REQUIRED_ERROR_MESSAGE7);
17190
+ setLocalRequiredError(tv("required"));
16962
17191
  },
16963
17192
  className: "pointer-events-none absolute h-0 w-0 opacity-0"
16964
17193
  }
@@ -17067,13 +17296,14 @@ function CategoryTreeSelect(props) {
17067
17296
  {
17068
17297
  tabIndex: -1,
17069
17298
  "aria-hidden": "true",
17070
- readOnly: true,
17071
17299
  value: valueArray.length > 0 ? "selected" : "",
17300
+ onChange: () => {
17301
+ },
17072
17302
  required,
17073
17303
  disabled,
17074
17304
  onInvalid: (e) => {
17075
17305
  e.preventDefault();
17076
- setLocalRequiredError(REQUIRED_ERROR_MESSAGE7);
17306
+ setLocalRequiredError(tv("required"));
17077
17307
  },
17078
17308
  className: "pointer-events-none absolute h-0 w-0 opacity-0"
17079
17309
  }