@sustaina/shared-ui 1.65.4 → 1.66.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4897,6 +4897,14 @@ var ClearButton = ({
4897
4897
  event.stopPropagation();
4898
4898
  triggerClear();
4899
4899
  };
4900
+ const handlePointerDown = (event) => {
4901
+ event.preventDefault();
4902
+ event.stopPropagation();
4903
+ };
4904
+ const handleMouseDown = (event) => {
4905
+ event.preventDefault();
4906
+ event.stopPropagation();
4907
+ };
4900
4908
  const handleKeyDown = (event) => {
4901
4909
  if (event.key === "Enter" || event.key === " ") {
4902
4910
  event.preventDefault();
@@ -4909,6 +4917,8 @@ var ClearButton = ({
4909
4917
  {
4910
4918
  role: "button",
4911
4919
  tabIndex: 0,
4920
+ onPointerDown: handlePointerDown,
4921
+ onMouseDown: handleMouseDown,
4912
4922
  onClick: handleClick,
4913
4923
  onKeyDown: handleKeyDown,
4914
4924
  className: `clear-button ${className}`.trim(),
@@ -6339,7 +6349,7 @@ function TooltipContent({
6339
6349
  "data-slot": "tooltip-content",
6340
6350
  sideOffset,
6341
6351
  className: cn(
6342
- "bg-primary text-primary-foreground 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 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
6352
+ "bg-primary text-primary-foreground 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 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance whitespace-pre-wrap",
6343
6353
  className
6344
6354
  ),
6345
6355
  ...props,
@@ -6785,6 +6795,7 @@ var Truncated = ({
6785
6795
  const [isTruncated, setIsTruncated] = React__namespace.useState(false);
6786
6796
  const [measureWidth, setMeasureWidth] = React__namespace.useState(0);
6787
6797
  const Comp = as;
6798
+ const isStringChildren = typeof children === "string";
6788
6799
  const normalizedChildren = typeof children === "string" ? children.replace(/>/g, ">\u200B") : children;
6789
6800
  const lineClampLines = typeof ellipsis === "number" ? ellipsis : typeof ellipsis === "object" ? ellipsis?.lineClamp ?? 3 : null;
6790
6801
  const enableMeasure = Boolean(ellipsis) && !tooltipProps?.disabled;
@@ -6824,19 +6835,31 @@ var Truncated = ({
6824
6835
  overflow: "hidden"
6825
6836
  };
6826
6837
  }, [lineClampLines, style]);
6827
- const baseContent = /* @__PURE__ */ jsxRuntime.jsx(Comp, { ref: elementRef, className: cn(truncationClass, className), style: clampedStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
6828
- EllipsisMeasure,
6838
+ const contentWhitespaceClass = React__namespace.useMemo(() => {
6839
+ if (!isStringChildren) return void 0;
6840
+ return truncationClass === "truncate" ? "whitespace-pre" : "whitespace-pre-wrap";
6841
+ }, [isStringChildren, truncationClass]);
6842
+ const baseContent = /* @__PURE__ */ jsxRuntime.jsx(
6843
+ Comp,
6829
6844
  {
6830
- enableMeasure,
6831
- text: normalizedChildren,
6832
- width: measureWidth,
6833
- rows: lineClampLines ?? 1,
6834
- expanded: false,
6835
- miscDeps: [truncationClass],
6836
- onEllipsis: setIsTruncated,
6837
- children: () => normalizedChildren
6845
+ ref: elementRef,
6846
+ className: cn(truncationClass, contentWhitespaceClass, className),
6847
+ style: clampedStyle,
6848
+ children: /* @__PURE__ */ jsxRuntime.jsx(
6849
+ EllipsisMeasure,
6850
+ {
6851
+ enableMeasure,
6852
+ text: normalizedChildren,
6853
+ width: measureWidth,
6854
+ rows: lineClampLines ?? 1,
6855
+ expanded: false,
6856
+ miscDeps: [truncationClass],
6857
+ onEllipsis: setIsTruncated,
6858
+ children: () => normalizedChildren
6859
+ }
6860
+ )
6838
6861
  }
6839
- ) });
6862
+ );
6840
6863
  let tooltipContent = normalizedChildren;
6841
6864
  if (typeof ellipsis === "object") {
6842
6865
  tooltipContent = ellipsis?.content ?? normalizedChildren;
@@ -6864,6 +6887,7 @@ var Truncated = ({
6864
6887
  side: tooltipSide,
6865
6888
  className: cn(
6866
6889
  "text-white bg-sus-secondary-gray-10 max-w-xs sm:max-w-md wrap-break-word shadow-lg",
6890
+ isStringChildren && "whitespace-pre-wrap",
6867
6891
  tooltipContentClassName
6868
6892
  ),
6869
6893
  arrowClassName: cn("bg-sus-secondary-gray-10 fill-sus-secondary-gray-10", tooltipArrowClassName),
@@ -8637,7 +8661,7 @@ var sanitizeInput = (val) => {
8637
8661
  if (/[%*~^]/.test(trimmed)) return "__INVALID_WILDCARD__";
8638
8662
  if (/[%><={}\\[\]"']/u.test(trimmed)) return "__INVALID_CHAR__";
8639
8663
  if (/\p{Cc}/u.test(val)) return "__INVALID_CONTROL_CHAR__";
8640
- return trimmed.replace(/\s+/g, " ");
8664
+ return val;
8641
8665
  };
8642
8666
  var numericTypes = ["number"];
8643
8667
  var dateTypes = ["date", "datemonth"];
@@ -10006,6 +10030,291 @@ var DataTable = ({
10006
10030
  );
10007
10031
  };
10008
10032
  var DataTable_default = DataTable;
10033
+ var defaultValueFormatter3 = (date) => dateFns.format(date, "yyyy-MM-dd'T'HH:mm:ss");
10034
+ var parseWithPatterns = (value) => {
10035
+ const patterns = ["yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd"];
10036
+ for (const pattern of patterns) {
10037
+ const parsed = dateFns.parse(value, pattern, /* @__PURE__ */ new Date());
10038
+ if (dateFns.isValid(parsed)) return parsed;
10039
+ }
10040
+ return void 0;
10041
+ };
10042
+ var defaultValueParser3 = (value) => {
10043
+ const isoParsed = dateFns.parseISO(value);
10044
+ if (dateFns.isValid(isoParsed)) return isoParsed;
10045
+ return parseWithPatterns(value);
10046
+ };
10047
+ var DateTimePicker = ({
10048
+ value,
10049
+ onChange,
10050
+ onValueChange,
10051
+ disabled = false,
10052
+ invalid = false,
10053
+ allowClear = true,
10054
+ use24Hour = false,
10055
+ placeholderDate = "Select date",
10056
+ placeholderTime = "Select time",
10057
+ className,
10058
+ datePickerClassName,
10059
+ timePickerClassName,
10060
+ popoverContentClassName,
10061
+ clearAriaLabel = "Clear date time",
10062
+ minuteStep = 5,
10063
+ minDateTime,
10064
+ maxDateTime,
10065
+ valueFormatter,
10066
+ valueParser,
10067
+ datePickerProps,
10068
+ timePickerProps
10069
+ }) => {
10070
+ const [open, setOpen] = React__namespace.default.useState(false);
10071
+ const hourListRef = React__namespace.default.useRef(null);
10072
+ const minuteListRef = React__namespace.default.useRef(null);
10073
+ const parser = React__namespace.default.useMemo(() => valueParser ?? defaultValueParser3, [valueParser]);
10074
+ const outputFormatter = React__namespace.default.useMemo(() => valueFormatter ?? defaultValueFormatter3, [valueFormatter]);
10075
+ const parseInput = React__namespace.default.useCallback(
10076
+ (input) => {
10077
+ if (input === null || input === void 0) return void 0;
10078
+ if (input instanceof Date) return dateFns.isValid(input) ? input : void 0;
10079
+ const parsed = parser(input);
10080
+ return parsed && dateFns.isValid(parsed) ? parsed : void 0;
10081
+ },
10082
+ [parser]
10083
+ );
10084
+ const isControlled = value !== void 0;
10085
+ const parsedValue = React__namespace.default.useMemo(() => parseInput(value), [parseInput, value]);
10086
+ const [internalValue, setInternalValue] = React__namespace.default.useState(() => parsedValue);
10087
+ React__namespace.default.useEffect(() => {
10088
+ if (isControlled) {
10089
+ setInternalValue(parsedValue);
10090
+ }
10091
+ }, [isControlled, parsedValue]);
10092
+ const currentValue = isControlled ? parsedValue : internalValue;
10093
+ const emitChange = React__namespace.default.useCallback(
10094
+ (next) => {
10095
+ if (!isControlled) {
10096
+ setInternalValue(next);
10097
+ }
10098
+ onChange?.(next);
10099
+ onValueChange?.(next ? outputFormatter(next) : void 0);
10100
+ },
10101
+ [isControlled, onChange, onValueChange, outputFormatter]
10102
+ );
10103
+ const makeDateTime = React__namespace.default.useCallback((baseDate, hour, minute) => {
10104
+ const clampedHour = Math.min(23, Math.max(0, hour));
10105
+ const clampedMinute = Math.min(59, Math.max(0, minute));
10106
+ return new Date(
10107
+ baseDate.getFullYear(),
10108
+ baseDate.getMonth(),
10109
+ baseDate.getDate(),
10110
+ clampedHour,
10111
+ clampedMinute,
10112
+ 0,
10113
+ 0
10114
+ );
10115
+ }, []);
10116
+ const handleDateChange = React__namespace.default.useCallback(
10117
+ (nextDate) => {
10118
+ if (!nextDate) {
10119
+ emitChange(void 0);
10120
+ return;
10121
+ }
10122
+ emitChange(new Date(nextDate.getFullYear(), nextDate.getMonth(), nextDate.getDate(), 0, 0, 0, 0));
10123
+ },
10124
+ [emitChange]
10125
+ );
10126
+ const handleTimeApply = React__namespace.default.useCallback(
10127
+ (hour, minute) => {
10128
+ const baseDate = currentValue;
10129
+ if (!baseDate) return;
10130
+ emitChange(makeDateTime(baseDate, hour, minute));
10131
+ },
10132
+ [currentValue, emitChange, makeDateTime]
10133
+ );
10134
+ const currentHour = currentValue?.getHours();
10135
+ const currentMinute = currentValue?.getMinutes();
10136
+ const handleHourSelect = React__namespace.default.useCallback(
10137
+ (hour) => {
10138
+ handleTimeApply(hour, currentMinute ?? 0);
10139
+ },
10140
+ [currentMinute, handleTimeApply]
10141
+ );
10142
+ const handleMinuteSelect = React__namespace.default.useCallback(
10143
+ (minute) => {
10144
+ handleTimeApply(currentHour ?? 0, minute);
10145
+ setOpen(false);
10146
+ },
10147
+ [currentHour, handleTimeApply]
10148
+ );
10149
+ const hours = React__namespace.default.useMemo(() => Array.from({ length: 24 }, (_, index) => 23 - index), []);
10150
+ const minuteInterval = React__namespace.default.useMemo(() => {
10151
+ const safeStep = Math.min(60, Math.max(1, minuteStep));
10152
+ return Array.from({ length: Math.ceil(60 / safeStep) }, (_, index) => index * safeStep).filter(
10153
+ (value2) => value2 < 60
10154
+ );
10155
+ }, [minuteStep]);
10156
+ const displayLabel = React__namespace.default.useMemo(() => {
10157
+ if (!currentValue) return `${placeholderDate} ${placeholderTime}`;
10158
+ return dateFns.format(currentValue, use24Hour ? "dd/MM/yyyy HH:mm" : "dd/MM/yyyy hh:mm a");
10159
+ }, [currentValue, placeholderDate, placeholderTime, use24Hour]);
10160
+ const canSelectTime = !disabled && !!currentValue;
10161
+ const isHourDisabled = React__namespace.default.useCallback(
10162
+ (hour) => {
10163
+ if (!currentValue) return true;
10164
+ const testDateTime = new Date(
10165
+ currentValue.getFullYear(),
10166
+ currentValue.getMonth(),
10167
+ currentValue.getDate(),
10168
+ hour,
10169
+ 0,
10170
+ 0,
10171
+ 0
10172
+ );
10173
+ if (minDateTime && testDateTime < minDateTime) return true;
10174
+ if (maxDateTime && testDateTime > maxDateTime) return true;
10175
+ return false;
10176
+ },
10177
+ [currentValue, minDateTime, maxDateTime]
10178
+ );
10179
+ const isMinuteDisabled = React__namespace.default.useCallback(
10180
+ (minute) => {
10181
+ if (!currentValue || typeof currentHour === "undefined") return true;
10182
+ const testDateTime = new Date(
10183
+ currentValue.getFullYear(),
10184
+ currentValue.getMonth(),
10185
+ currentValue.getDate(),
10186
+ currentHour,
10187
+ minute,
10188
+ 0,
10189
+ 0
10190
+ );
10191
+ if (minDateTime && testDateTime < minDateTime) return true;
10192
+ if (maxDateTime && testDateTime > maxDateTime) return true;
10193
+ return false;
10194
+ },
10195
+ [currentValue, currentHour, minDateTime, maxDateTime]
10196
+ );
10197
+ const scrollToSelected = React__namespace.default.useCallback((container, selector) => {
10198
+ if (!container) return;
10199
+ const element = container.querySelector(selector);
10200
+ if (!element) return;
10201
+ const target = element.offsetTop - container.clientHeight / 2 + element.clientHeight / 2;
10202
+ container.scrollTo({ top: Math.max(0, target), behavior: "smooth" });
10203
+ }, []);
10204
+ React__namespace.default.useEffect(() => {
10205
+ if (!open) return;
10206
+ if (typeof currentHour === "number") {
10207
+ scrollToSelected(hourListRef.current, `[data-hour="${currentHour}"]`);
10208
+ }
10209
+ if (typeof currentMinute === "number") {
10210
+ scrollToSelected(minuteListRef.current, `[data-minute="${currentMinute}"]`);
10211
+ }
10212
+ }, [currentHour, currentMinute, open, scrollToSelected]);
10213
+ const handleClear = React__namespace.default.useCallback(() => {
10214
+ emitChange(void 0);
10215
+ setOpen(false);
10216
+ }, [emitChange]);
10217
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative w-full", className), children: [
10218
+ /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, children: [
10219
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
10220
+ Button,
10221
+ {
10222
+ type: "button",
10223
+ variant: "outline",
10224
+ disabled,
10225
+ "aria-invalid": invalid || void 0,
10226
+ className: cn(
10227
+ "group relative flex! w-full items-center justify-between rounded-md bg-white! pl-4 text-left text-sm font-medium shadow-none border border-sus-secondary-gray-8 focus-visible:ring-0 focus-visible:ring-offset-0 data-[state=open]:border-black disabled:bg-sus-secondary-gray-3!",
10228
+ "min-h-9",
10229
+ currentValue ? "text-gray-700" : "text-gray-400",
10230
+ invalid && "border-destructive focus-visible:border-destructive focus-visible:ring-destructive/30",
10231
+ allowClear && currentValue ? "pr-8" : "pr-4"
10232
+ ),
10233
+ children: [
10234
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate font-light", children: displayLabel }),
10235
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center gap-2 text-black group-disabled:text-sus-secondary-gray-8 shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(SuiCalendarIcon2, { className: "h-4 w-4" }) })
10236
+ ]
10237
+ }
10238
+ ) }),
10239
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { className: cn("w-auto p-0", popoverContentClassName), align: "start", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sm:flex", children: [
10240
+ /* @__PURE__ */ jsxRuntime.jsx(
10241
+ DatePicker,
10242
+ {
10243
+ ...datePickerProps,
10244
+ className: cn(datePickerProps?.className, datePickerClassName),
10245
+ selectionMode: "single",
10246
+ selectedDate: currentValue,
10247
+ onDateSelect: handleDateChange,
10248
+ minDate: minDateTime,
10249
+ maxDate: maxDateTime
10250
+ }
10251
+ ),
10252
+ /* @__PURE__ */ jsxRuntime.jsx(
10253
+ "div",
10254
+ {
10255
+ className: cn(
10256
+ "flex border-t sm:border-t-0 sm:border-l p-2",
10257
+ !canSelectTime && "opacity-60",
10258
+ timePickerClassName,
10259
+ timePickerProps?.panelClassName
10260
+ ),
10261
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full", children: [
10262
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-14 border-r pr-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: hourListRef, className: "h-[300px] overflow-y-auto space-y-1", children: hours.map((hour) => {
10263
+ const selected = currentHour === hour;
10264
+ const hourDisabled = isHourDisabled(hour);
10265
+ return /* @__PURE__ */ jsxRuntime.jsx(
10266
+ "button",
10267
+ {
10268
+ type: "button",
10269
+ "data-hour": hour,
10270
+ disabled: !canSelectTime || hourDisabled,
10271
+ onClick: () => handleHourSelect(hour),
10272
+ className: cn(
10273
+ "h-8 w-full rounded-md text-sm transition-colors",
10274
+ selected ? "bg-[#379a2a] text-white hover:bg-[#379a2a]" : "text-foreground hover:bg-sus-secondary-gray-3",
10275
+ (!canSelectTime || hourDisabled) && "cursor-not-allowed opacity-50"
10276
+ ),
10277
+ children: String(hour).padStart(2, "0")
10278
+ },
10279
+ hour
10280
+ );
10281
+ }) }) }),
10282
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-14 pl-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: minuteListRef, className: "h-[300px] overflow-y-auto space-y-1", children: minuteInterval.map((minute) => {
10283
+ const selected = currentMinute === minute;
10284
+ const minuteDisabled = isMinuteDisabled(minute);
10285
+ return /* @__PURE__ */ jsxRuntime.jsx(
10286
+ "button",
10287
+ {
10288
+ type: "button",
10289
+ "data-minute": minute,
10290
+ disabled: !canSelectTime || minuteDisabled,
10291
+ onClick: () => handleMinuteSelect(minute),
10292
+ className: cn(
10293
+ "h-8 w-full rounded-md text-sm transition-colors",
10294
+ selected ? "bg-[#379a2a] text-white hover:bg-[#379a2a]" : "text-foreground hover:bg-sus-secondary-gray-3",
10295
+ (!canSelectTime || minuteDisabled) && "cursor-not-allowed opacity-50"
10296
+ ),
10297
+ children: String(minute).padStart(2, "0")
10298
+ },
10299
+ minute
10300
+ );
10301
+ }) }) })
10302
+ ] })
10303
+ }
10304
+ )
10305
+ ] }) })
10306
+ ] }),
10307
+ allowClear && !!currentValue && !disabled && /* @__PURE__ */ jsxRuntime.jsx(
10308
+ ClearButton,
10309
+ {
10310
+ onClick: handleClear,
10311
+ ariaLabel: clearAriaLabel,
10312
+ title: clearAriaLabel,
10313
+ className: "absolute right-3 top-1/2 z-10 -translate-y-1/2"
10314
+ }
10315
+ )
10316
+ ] });
10317
+ };
10009
10318
  function Dialog2(props) {
10010
10319
  return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive2__namespace.Root, { "data-slot": "dialog", ...props });
10011
10320
  }
@@ -16283,7 +16592,10 @@ var DefaultHeader = ({
16283
16592
  "span",
16284
16593
  {
16285
16594
  ref: titleRef,
16286
- className: cn("text-lg font-semibold text-sus-green-1 truncate", classNames?.title),
16595
+ className: cn(
16596
+ "text-lg font-semibold text-sus-green-1 truncate whitespace-pre",
16597
+ classNames?.title
16598
+ ),
16287
16599
  children: title
16288
16600
  }
16289
16601
  ) : null;
@@ -16300,10 +16612,10 @@ var DefaultHeader = ({
16300
16612
  }
16301
16613
  ) : null,
16302
16614
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0", children: [
16303
- subtitle ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-xs text-gray-500", classNames?.subtitle), children: subtitle }) : null,
16615
+ subtitle ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-xs text-gray-500 whitespace-pre-wrap", classNames?.subtitle), children: subtitle }) : null,
16304
16616
  textElement ? isTruncated ? /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
16305
16617
  /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: textElement }),
16306
- /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: title })
16618
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { className: "whitespace-pre-wrap", children: title })
16307
16619
  ] }) : textElement : null
16308
16620
  ] })
16309
16621
  ] }),
@@ -16359,351 +16671,6 @@ var RightPanelContainer = ({
16359
16671
  );
16360
16672
  };
16361
16673
  var RightPanelContainer_default = RightPanelContainer;
16362
- var defaultDisplayFormatter3 = (date, use24Hour) => use24Hour ? dateFns.format(date, "HH:mm") : dateFns.format(date, "hh:mm a");
16363
- var defaultValueFormatter3 = (date) => dateFns.format(date, "HH:mm");
16364
- var defaultValueParser3 = (value) => {
16365
- let parsed = dateFns.parse(value, "HH:mm", /* @__PURE__ */ new Date());
16366
- if (dateFns.isValid(parsed)) return parsed;
16367
- parsed = dateFns.parse(value, "HH:mm:ss", /* @__PURE__ */ new Date());
16368
- if (dateFns.isValid(parsed)) return parsed;
16369
- parsed = dateFns.parse(value, "hh:mm a", /* @__PURE__ */ new Date());
16370
- if (dateFns.isValid(parsed)) return parsed;
16371
- return void 0;
16372
- };
16373
- var TimePicker = React__namespace.forwardRef(
16374
- ({
16375
- value,
16376
- onChange,
16377
- onValueChange,
16378
- disabled = false,
16379
- className,
16380
- buttonClassName,
16381
- wrapperClassName,
16382
- placeholder: placeholder2,
16383
- use24Hour = false,
16384
- iconPosition = "start",
16385
- icon,
16386
- allowClear = true,
16387
- clearAriaLabel = "Clear time",
16388
- displayFormatter,
16389
- valueFormatter,
16390
- valueParser,
16391
- invalid = false
16392
- }, ref) => {
16393
- const [open, setOpen] = React__namespace.useState(false);
16394
- const [hours, setHours] = React__namespace.useState("12");
16395
- const [minutes, setMinutes] = React__namespace.useState("00");
16396
- const [period, setPeriod] = React__namespace.useState("AM");
16397
- const parser = React__namespace.useMemo(() => valueParser ?? defaultValueParser3, [valueParser]);
16398
- const outputFormatter = React__namespace.useMemo(
16399
- () => valueFormatter ?? defaultValueFormatter3,
16400
- [valueFormatter]
16401
- );
16402
- const labelFormatter = React__namespace.useMemo(
16403
- () => displayFormatter ?? defaultDisplayFormatter3,
16404
- [displayFormatter]
16405
- );
16406
- const parseInput = React__namespace.useCallback(
16407
- (input) => {
16408
- if (input === null || input === void 0) return void 0;
16409
- if (input instanceof Date) return dateFns.isValid(input) ? input : void 0;
16410
- const parsed = parser(input);
16411
- return parsed && dateFns.isValid(parsed) ? parsed : void 0;
16412
- },
16413
- [parser]
16414
- );
16415
- const parsedValue = React__namespace.useMemo(() => parseInput(value), [parseInput, value]);
16416
- const hasValue = parsedValue !== void 0;
16417
- React__namespace.useEffect(() => {
16418
- if (parsedValue) {
16419
- const hour24 = parsedValue.getHours();
16420
- const minute = parsedValue.getMinutes();
16421
- if (use24Hour) {
16422
- setHours(String(hour24).padStart(2, "0"));
16423
- } else {
16424
- const newPeriod = hour24 >= 12 ? "PM" : "AM";
16425
- const hour12 = hour24 === 0 ? 12 : hour24 > 12 ? hour24 - 12 : hour24;
16426
- setHours(String(hour12).padStart(2, "0"));
16427
- setPeriod(newPeriod);
16428
- }
16429
- setMinutes(String(minute).padStart(2, "0"));
16430
- } else {
16431
- setHours(use24Hour ? "00" : "12");
16432
- setMinutes("00");
16433
- setPeriod("AM");
16434
- }
16435
- }, [parsedValue, use24Hour]);
16436
- const createTimeDate = (h, m, p) => {
16437
- let hour = parseInt(h) || 0;
16438
- const minute = parseInt(m) || 0;
16439
- if (!use24Hour) {
16440
- if (p === "PM" && hour !== 12) {
16441
- hour += 12;
16442
- } else if (p === "AM" && hour === 12) {
16443
- hour = 0;
16444
- }
16445
- }
16446
- const today = /* @__PURE__ */ new Date();
16447
- return new Date(today.getFullYear(), today.getMonth(), today.getDate(), hour, minute, 0, 0);
16448
- };
16449
- const emitChange = (date) => {
16450
- onChange?.(date);
16451
- onValueChange?.(outputFormatter(date));
16452
- };
16453
- const handleClear = () => {
16454
- onChange?.(void 0);
16455
- onValueChange?.(void 0);
16456
- };
16457
- const handleHourChange = (newHour) => {
16458
- const hour = parseInt(newHour) || 0;
16459
- const maxHour = use24Hour ? 23 : 12;
16460
- const minHour = use24Hour ? 0 : 1;
16461
- if (hour <= maxHour && hour >= minHour) {
16462
- setHours(newHour.padStart(2, "0"));
16463
- emitChange(createTimeDate(newHour, minutes, period));
16464
- }
16465
- };
16466
- const handleMinuteChange = (newMinute) => {
16467
- const minute = parseInt(newMinute) || 0;
16468
- if (minute <= 59 && minute >= 0) {
16469
- setMinutes(newMinute.padStart(2, "0"));
16470
- emitChange(createTimeDate(hours, newMinute, period));
16471
- }
16472
- };
16473
- const handlePeriodToggle = () => {
16474
- const newPeriod = period === "AM" ? "PM" : "AM";
16475
- setPeriod(newPeriod);
16476
- emitChange(createTimeDate(hours, minutes, newPeriod));
16477
- };
16478
- const incrementHour = () => {
16479
- const hour = parseInt(hours) || 0;
16480
- const maxHour = use24Hour ? 23 : 12;
16481
- const minHour = use24Hour ? 0 : 1;
16482
- const newHour = hour >= maxHour ? minHour : hour + 1;
16483
- handleHourChange(String(newHour));
16484
- };
16485
- const decrementHour = () => {
16486
- const hour = parseInt(hours) || 0;
16487
- const maxHour = use24Hour ? 23 : 12;
16488
- const minHour = use24Hour ? 0 : 1;
16489
- const newHour = hour <= minHour ? maxHour : hour - 1;
16490
- handleHourChange(String(newHour));
16491
- };
16492
- const incrementMinute = () => {
16493
- const minute = parseInt(minutes) || 0;
16494
- const newMinute = minute >= 59 ? 0 : minute + 1;
16495
- handleMinuteChange(String(newMinute));
16496
- };
16497
- const decrementMinute = () => {
16498
- const minute = parseInt(minutes) || 0;
16499
- const newMinute = minute <= 0 ? 59 : minute - 1;
16500
- handleMinuteChange(String(newMinute));
16501
- };
16502
- const displayValue = parsedValue ? labelFormatter(parsedValue, use24Hour) : placeholder2;
16503
- const displayIcon = icon || /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "h-4 w-4" });
16504
- const showClear = allowClear && hasValue && !disabled;
16505
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative inline-flex w-full", wrapperClassName), children: [
16506
- /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, children: [
16507
- /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
16508
- Button,
16509
- {
16510
- variant: "outline",
16511
- disabled,
16512
- className: cn(
16513
- "w-full justify-between text-left font-normal",
16514
- !hasValue && "text-muted-foreground",
16515
- invalid && "border-destructive focus-visible:ring-destructive",
16516
- showClear && "pr-8",
16517
- buttonClassName,
16518
- className
16519
- ),
16520
- children: [
16521
- iconPosition === "start" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: displayIcon }),
16522
- /* @__PURE__ */ jsxRuntime.jsx(
16523
- "span",
16524
- {
16525
- className: cn(
16526
- "flex-1 truncate",
16527
- iconPosition === "start" && "ml-2",
16528
- iconPosition === "end" && "mr-2"
16529
- ),
16530
- children: displayValue || placeholder2 || "Select time"
16531
- }
16532
- ),
16533
- iconPosition === "end" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: displayIcon })
16534
- ]
16535
- }
16536
- ) }),
16537
- /* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { className: "w-auto p-4", align: "start", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
16538
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-1", children: [
16539
- /* @__PURE__ */ jsxRuntime.jsx(
16540
- Button,
16541
- {
16542
- variant: "ghost",
16543
- size: "icon",
16544
- className: "h-8 w-8",
16545
- onClick: incrementHour,
16546
- type: "button",
16547
- children: /* @__PURE__ */ jsxRuntime.jsx(
16548
- "svg",
16549
- {
16550
- xmlns: "http://www.w3.org/2000/svg",
16551
- width: "16",
16552
- height: "16",
16553
- viewBox: "0 0 24 24",
16554
- fill: "none",
16555
- stroke: "currentColor",
16556
- strokeWidth: "2",
16557
- strokeLinecap: "round",
16558
- strokeLinejoin: "round",
16559
- children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "18 15 12 9 6 15" })
16560
- }
16561
- )
16562
- }
16563
- ),
16564
- /* @__PURE__ */ jsxRuntime.jsx(
16565
- Input,
16566
- {
16567
- ref,
16568
- type: "text",
16569
- inputMode: "numeric",
16570
- value: hours,
16571
- onChange: (e) => handleHourChange(e.target.value),
16572
- className: "w-16 text-center",
16573
- maxLength: 2
16574
- }
16575
- ),
16576
- /* @__PURE__ */ jsxRuntime.jsx(
16577
- Button,
16578
- {
16579
- variant: "ghost",
16580
- size: "icon",
16581
- className: "h-8 w-8",
16582
- onClick: decrementHour,
16583
- type: "button",
16584
- children: /* @__PURE__ */ jsxRuntime.jsx(
16585
- "svg",
16586
- {
16587
- xmlns: "http://www.w3.org/2000/svg",
16588
- width: "16",
16589
- height: "16",
16590
- viewBox: "0 0 24 24",
16591
- fill: "none",
16592
- stroke: "currentColor",
16593
- strokeWidth: "2",
16594
- strokeLinecap: "round",
16595
- strokeLinejoin: "round",
16596
- children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" })
16597
- }
16598
- )
16599
- }
16600
- )
16601
- ] }),
16602
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-2xl font-semibold", children: ":" }),
16603
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-1", children: [
16604
- /* @__PURE__ */ jsxRuntime.jsx(
16605
- Button,
16606
- {
16607
- variant: "ghost",
16608
- size: "icon",
16609
- className: "h-8 w-8",
16610
- onClick: incrementMinute,
16611
- type: "button",
16612
- children: /* @__PURE__ */ jsxRuntime.jsx(
16613
- "svg",
16614
- {
16615
- xmlns: "http://www.w3.org/2000/svg",
16616
- width: "16",
16617
- height: "16",
16618
- viewBox: "0 0 24 24",
16619
- fill: "none",
16620
- stroke: "currentColor",
16621
- strokeWidth: "2",
16622
- strokeLinecap: "round",
16623
- strokeLinejoin: "round",
16624
- children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "18 15 12 9 6 15" })
16625
- }
16626
- )
16627
- }
16628
- ),
16629
- /* @__PURE__ */ jsxRuntime.jsx(
16630
- Input,
16631
- {
16632
- type: "text",
16633
- inputMode: "numeric",
16634
- value: minutes,
16635
- onChange: (e) => handleMinuteChange(e.target.value),
16636
- className: "w-16 text-center",
16637
- maxLength: 2
16638
- }
16639
- ),
16640
- /* @__PURE__ */ jsxRuntime.jsx(
16641
- Button,
16642
- {
16643
- variant: "ghost",
16644
- size: "icon",
16645
- className: "h-8 w-8",
16646
- onClick: decrementMinute,
16647
- type: "button",
16648
- children: /* @__PURE__ */ jsxRuntime.jsx(
16649
- "svg",
16650
- {
16651
- xmlns: "http://www.w3.org/2000/svg",
16652
- width: "16",
16653
- height: "16",
16654
- viewBox: "0 0 24 24",
16655
- fill: "none",
16656
- stroke: "currentColor",
16657
- strokeWidth: "2",
16658
- strokeLinecap: "round",
16659
- strokeLinejoin: "round",
16660
- children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" })
16661
- }
16662
- )
16663
- }
16664
- )
16665
- ] }),
16666
- !use24Hour && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
16667
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-16 bg-border mx-1" }),
16668
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-1", children: [
16669
- /* @__PURE__ */ jsxRuntime.jsx(
16670
- Button,
16671
- {
16672
- variant: period === "AM" ? "default" : "outline",
16673
- size: "sm",
16674
- className: "w-14 h-12",
16675
- onClick: handlePeriodToggle,
16676
- type: "button",
16677
- children: "AM"
16678
- }
16679
- ),
16680
- /* @__PURE__ */ jsxRuntime.jsx(
16681
- Button,
16682
- {
16683
- variant: period === "PM" ? "default" : "outline",
16684
- size: "sm",
16685
- className: "w-14 h-12",
16686
- onClick: handlePeriodToggle,
16687
- type: "button",
16688
- children: "PM"
16689
- }
16690
- )
16691
- ] })
16692
- ] })
16693
- ] }) })
16694
- ] }),
16695
- showClear && /* @__PURE__ */ jsxRuntime.jsx(
16696
- ClearButton,
16697
- {
16698
- onClick: handleClear,
16699
- ariaLabel: clearAriaLabel,
16700
- className: "absolute right-2 top-1/2 -translate-y-1/2"
16701
- }
16702
- )
16703
- ] });
16704
- }
16705
- );
16706
- TimePicker.displayName = "TimePicker";
16707
16674
 
16708
16675
  // src/components/cropperModal/type.ts
16709
16676
  var CropperModalError = class extends Error {
@@ -17798,7 +17765,7 @@ var TruncatedMouseEnterDiv = ({
17798
17765
  ref: textRef,
17799
17766
  onMouseEnter: checkTruncation,
17800
17767
  onMouseLeave: () => setIsTruncated(false),
17801
- className: cn("truncate", className),
17768
+ className: cn("truncate whitespace-pre", className),
17802
17769
  children: value
17803
17770
  }
17804
17771
  ) }),
@@ -18707,6 +18674,7 @@ exports.DashboardIcon = DashboardIcon;
18707
18674
  exports.DataEntryIcon = DataEntryIcon;
18708
18675
  exports.DataTable = DataTable_default;
18709
18676
  exports.DatePicker = DatePicker2;
18677
+ exports.DateTimePicker = DateTimePicker;
18710
18678
  exports.DecreaseIcon = DecreaseIcon;
18711
18679
  exports.Dialog = Dialog2;
18712
18680
  exports.DialogAlert = DialogAlert;
@@ -18871,7 +18839,6 @@ exports.TableOfContents = TableOfContents;
18871
18839
  exports.TableRow = TableRow;
18872
18840
  exports.TagListViewIcon = TagListViewIcon;
18873
18841
  exports.TextArea = TextArea;
18874
- exports.TimePicker = TimePicker;
18875
18842
  exports.ToolBoxIcon = ToolBoxIcon;
18876
18843
  exports.Tooltip = Tooltip2;
18877
18844
  exports.TooltipArrow = TooltipArrow;