@rebasepro/ui 0.21.2-canary.g1ea48be → 0.23.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.
@@ -12,6 +12,14 @@ export type DateTimeFieldProps = {
12
12
  style?: React.CSSProperties;
13
13
  inputClassName?: string;
14
14
  invisible?: boolean;
15
+ /**
16
+ * Whether the field draws its own calendar button. A table cell turns it
17
+ * off: the cell draws one opener for every kind of editor, in the same
18
+ * place, and opens the picker through `inputRef`.
19
+ */
20
+ pickerButton?: boolean;
21
+ /** The native input, for a caller that opens the picker itself (`showPicker()`). */
22
+ inputRef?: React.Ref<HTMLInputElement>;
15
23
  locale?: string;
16
24
  /**
17
25
  * IANA timezone string (e.g., "America/New_York", "Europe/London").
@@ -34,6 +34,17 @@ interface MultiSelectProps<T extends MultiSelectValue = string> {
34
34
  inputRef?: React.Ref<HTMLButtonElement>;
35
35
  padding?: boolean;
36
36
  invisible?: boolean;
37
+ /**
38
+ * Whether the trigger draws its own chevron. A table cell turns it off:
39
+ * the cell draws one opener for every kind of editor, in the same place.
40
+ */
41
+ chevron?: boolean;
42
+ /**
43
+ * Positions the list against this element instead of the trigger. A
44
+ * table cell passes itself: chips that wrap make the trigger taller than
45
+ * the cell that clips it, and the list belongs under what can be seen.
46
+ */
47
+ anchorRef?: React.RefObject<HTMLElement | null>;
37
48
  children: React.ReactNode;
38
49
  renderValues?: (values: T[]) => React.ReactNode;
39
50
  portalContainer?: HTMLElement | null;
@@ -23,6 +23,11 @@ export type SelectProps<T extends SelectValue = string> = {
23
23
  inputRef?: React.Ref<HTMLButtonElement>;
24
24
  padding?: boolean;
25
25
  invisible?: boolean;
26
+ /**
27
+ * Whether the trigger draws its own chevron. A table cell turns it off:
28
+ * the cell draws one opener for every kind of editor, in the same place.
29
+ */
30
+ chevron?: boolean;
26
31
  children?: React.ReactNode;
27
32
  dataType?: "string" | "number" | "boolean";
28
33
  portalContainer?: HTMLElement | null;
@@ -4,6 +4,8 @@ export type TextFieldProps<T extends string | number> = {
4
4
  type?: InputType;
5
5
  value?: T;
6
6
  onChange?: (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
7
+ onFocus?: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
8
+ onBlur?: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
7
9
  label?: React.ReactNode;
8
10
  multiline?: boolean;
9
11
  disabled?: boolean;
@@ -27,11 +29,13 @@ export type TextFieldProps<T extends string | number> = {
27
29
  * @default 1
28
30
  */
29
31
  minRows?: number | string;
30
- } & Omit<React.InputHTMLAttributes<HTMLInputElement>, "size" | "value">;
32
+ } & Omit<React.InputHTMLAttributes<HTMLInputElement>, "size" | "value" | "onFocus" | "onBlur">;
31
33
  export declare const TextField: React.ForwardRefExoticComponent<{
32
34
  type?: InputType;
33
35
  value?: string | number | undefined;
34
36
  onChange?: (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
37
+ onFocus?: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
38
+ onBlur?: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
35
39
  label?: React.ReactNode;
36
40
  multiline?: boolean;
37
41
  disabled?: boolean;
@@ -55,4 +59,4 @@ export declare const TextField: React.ForwardRefExoticComponent<{
55
59
  * @default 1
56
60
  */
57
61
  minRows?: number | string;
58
- } & Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "size"> & React.RefAttributes<HTMLDivElement>>;
62
+ } & Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "onFocus" | "onBlur" | "size"> & React.RefAttributes<HTMLDivElement>>;
@@ -10,5 +10,13 @@ export declare function VirtualTableDateField(props: {
10
10
  disabled: boolean;
11
11
  small?: boolean;
12
12
  locale?: string;
13
+ /**
14
+ * Whether the field draws its own calendar button. A table that draws its
15
+ * own opener for the cell turns it off, and the value then sits flush with
16
+ * the text of the cells beside it rather than indented like a form field.
17
+ */
18
+ pickerButton?: boolean;
19
+ /** The native input, for a caller that opens the picker itself (`showPicker()`). */
20
+ inputRef?: React.Ref<HTMLInputElement>;
13
21
  onBlur?: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
14
22
  }): React.JSX.Element;
package/dist/index.es.js CHANGED
@@ -3008,9 +3008,10 @@ var Alert = ({ children, onDismiss, color = "info", size = "medium", action, out
3008
3008
  //#endregion
3009
3009
  //#region src/components/Avatar.tsx
3010
3010
  var AvatarInner = ({ src, alt, children, className, style, outerClassName, hover = true, ...props }, ref) => {
3011
- const [isImageError, setIsImageError] = useState(false);
3011
+ const [failedSrc, setFailedSrc] = useState(void 0);
3012
+ const isImageError = src !== void 0 && failedSrc === src;
3012
3013
  const handleImageError = () => {
3013
- setIsImageError(true);
3014
+ setFailedSrc(src);
3014
3015
  };
3015
3016
  return /* @__PURE__ */ jsx("button", {
3016
3017
  ref,
@@ -3941,7 +3942,7 @@ var defaultIconSize = {
3941
3942
  medium: 20,
3942
3943
  large: 24
3943
3944
  };
3944
- var IconButtonInner = ({ children, className, size = "medium", variant = "ghost", shape = "circular", disabled, toggled, component, ...props }, ref) => {
3945
+ var IconButtonInner = ({ children, className, size = "medium", variant = "ghost", shape = "circular", disabled, toggled, component, onClick, ...props }, ref) => {
3945
3946
  const bgClasses = variant === "ghost" ? "bg-transparent hover:bg-surface-hover" : "bg-surface-raised hover:bg-surface-raised-hover";
3946
3947
  const Component = component || "button";
3947
3948
  const isNativeButton = Component === "button";
@@ -3954,8 +3955,10 @@ var IconButtonInner = ({ children, className, size = "medium", variant = "ghost"
3954
3955
  type: isNativeButton ? "button" : void 0,
3955
3956
  role: isNativeButton ? void 0 : "button",
3956
3957
  ref,
3958
+ disabled: isNativeButton ? disabled : void 0,
3957
3959
  "aria-disabled": disabled || void 0,
3958
3960
  tabIndex: disabled ? -1 : void 0,
3961
+ onClick: disabled ? void 0 : onClick,
3959
3962
  ...props,
3960
3963
  className: cls(disabled ? "opacity-50 pointer-events-none" : "cursor-pointer", toggled ? "outline outline-2 outline-primary" : "", "text-inherit dark:text-inherit", colorClasses$1, bgClasses, baseClasses, buttonClasses, shapeClasses[shape], sizeClasses$1[size], className),
3961
3964
  children: sizedChildren
@@ -3983,8 +3986,13 @@ var InputLabel = React$1.forwardRef(function InputLabel(inProps, ref) {
3983
3986
  });
3984
3987
  //#endregion
3985
3988
  //#region src/components/DateTimeField.tsx
3986
- var DateTimeField = ({ value, label, onChange, disabled, clearable, mode = "date", error, size = "large", className, style, inputClassName, invisible, timezone, "aria-label": ariaLabel }) => {
3989
+ var DateTimeField = ({ value, label, onChange, disabled, clearable, mode = "date", error, size = "large", className, style, inputClassName, invisible, pickerButton = true, inputRef: inputRefProp, timezone, "aria-label": ariaLabel }) => {
3987
3990
  const inputRef = useRef(null);
3991
+ const setInputRef = useCallback((node) => {
3992
+ inputRef.current = node;
3993
+ if (typeof inputRefProp === "function") inputRefProp(node);
3994
+ else if (inputRefProp) inputRefProp.current = node;
3995
+ }, [inputRefProp]);
3988
3996
  const [focused, setFocused] = useState(false);
3989
3997
  const inputId = useId();
3990
3998
  const labelId = `${inputId}-label`;
@@ -4061,11 +4069,19 @@ var DateTimeField = ({ value, label, onChange, disabled, clearable, mode = "date
4061
4069
  [hours, minutes] = timePart.split(":").map(Number);
4062
4070
  }
4063
4071
  let resultDate;
4064
- if (!timezone) resultDate = new Date(year, month - 1, day, hours, minutes);
4065
- else {
4066
- const refUtcDate = new Date(Date.UTC(year, month - 1, day, hours, minutes));
4067
- const offsetMinutes = getTimezoneOffsetMinutes(refUtcDate, timezone);
4068
- resultDate = /* @__PURE__ */ new Date(Date.UTC(year, month - 1, day, hours, minutes) - offsetMinutes * 6e4);
4072
+ if (!timezone) {
4073
+ resultDate = /* @__PURE__ */ new Date(0);
4074
+ resultDate.setFullYear(year, month - 1, day);
4075
+ resultDate.setHours(hours, minutes, 0, 0);
4076
+ } else {
4077
+ const wallClock = /* @__PURE__ */ new Date(0);
4078
+ wallClock.setUTCFullYear(year, month - 1, day);
4079
+ wallClock.setUTCHours(hours, minutes, 0, 0);
4080
+ const wallClockAsUtc = wallClock.getTime();
4081
+ const firstGuess = getTimezoneOffsetMinutes(new Date(wallClockAsUtc), timezone);
4082
+ const offsetMinutes = getTimezoneOffsetMinutes(/* @__PURE__ */ new Date(wallClockAsUtc - firstGuess * 6e4), timezone);
4083
+ resultDate = /* @__PURE__ */ new Date(wallClockAsUtc - offsetMinutes * 6e4);
4084
+ if (getTimezoneOffsetMinutes(resultDate, timezone) !== offsetMinutes) resultDate = /* @__PURE__ */ new Date(wallClockAsUtc - firstGuess * 6e4);
4069
4085
  }
4070
4086
  if (isNaN(resultDate.getTime())) throw new Error("Invalid date");
4071
4087
  onChange?.(resultDate);
@@ -4104,7 +4120,7 @@ var DateTimeField = ({ value, label, onChange, disabled, clearable, mode = "date
4104
4120
  children: label
4105
4121
  }),
4106
4122
  /* @__PURE__ */ jsx("input", {
4107
- ref: inputRef,
4123
+ ref: setInputRef,
4108
4124
  id: inputId,
4109
4125
  "aria-labelledby": label ? labelId : void 0,
4110
4126
  "aria-label": label ? void 0 : ariaLabel,
@@ -4114,7 +4130,7 @@ var DateTimeField = ({ value, label, onChange, disabled, clearable, mode = "date
4114
4130
  onFocus: handleFocus,
4115
4131
  onBlur: handleBlur,
4116
4132
  disabled,
4117
- className: cls("w-full outline-hidden bg-transparent leading-normal text-sm px-3", clearable ? "pr-14" : "pr-12", "rounded-lg", {
4133
+ className: cls("w-full outline-hidden bg-transparent leading-normal text-sm px-3", pickerButton ? clearable ? "pr-14" : "pr-12" : clearable ? "pr-12" : "", "rounded-lg", {
4118
4134
  "min-h-[28px]": size === "smallest",
4119
4135
  "min-h-[32px]": size === "small",
4120
4136
  "min-h-[40px]": size === "medium",
@@ -4126,7 +4142,7 @@ var DateTimeField = ({ value, label, onChange, disabled, clearable, mode = "date
4126
4142
  large: "py-3"
4127
4143
  }[size], inputClassName, disabled && "border border-transparent outline-hidden opacity-50 dark:opacity-50 text-surface-accent-600 dark:text-surface-accent-500")
4128
4144
  }),
4129
- /* @__PURE__ */ jsx(IconButton, {
4145
+ pickerButton && /* @__PURE__ */ jsx(IconButton, {
4130
4146
  size: adornmentSize,
4131
4147
  onClick: (e) => {
4132
4148
  e.stopPropagation();
@@ -4757,7 +4773,21 @@ function SelectInputLabel({ children, error }) {
4757
4773
  //#endregion
4758
4774
  //#region src/components/MultiSelect.tsx
4759
4775
  var MultiSelectContext = React$1.createContext(null);
4760
- var MultiSelect = React$1.forwardRef(({ value, size = "large", label, error, onValueChange, invisible, disabled, placeholder, modalPopover = true, includeClear = true, includeSelectAll = true, useChips = true, className, inputClassName, inputRef, children, renderValues, open, onOpenChange, portalContainer, "aria-label": ariaLabel }, ref) => {
4776
+ /**
4777
+ * The popover's trigger, or — given an anchor — a plain child beside a
4778
+ * `Popover.Anchor` on that element. Not both: Radix's trigger registers itself
4779
+ * as the anchor through a ref callback, which under StrictMode runs again
4780
+ * after the custom anchor's effect and wins, leaving the list anchored to a
4781
+ * trigger the custom anchor then unmounts. The button toggles the list itself.
4782
+ */
4783
+ function MultiSelectTrigger({ anchorRef, children }) {
4784
+ if (!anchorRef) return /* @__PURE__ */ jsx(PopoverPrimitive.Trigger, {
4785
+ asChild: true,
4786
+ children
4787
+ });
4788
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(PopoverPrimitive.Anchor, { virtualRef: anchorRef }), children] });
4789
+ }
4790
+ var MultiSelect = React$1.forwardRef(({ value, size = "large", label, error, onValueChange, invisible, chevron = true, anchorRef, disabled, placeholder, modalPopover = true, includeClear = true, includeSelectAll = true, useChips = true, className, inputClassName, inputRef, children, renderValues, open, onOpenChange, portalContainer, "aria-label": ariaLabel }, ref) => {
4761
4791
  const [isMounted, setIsMounted] = useState(false);
4762
4792
  const [isPopoverOpen, setIsPopoverOpen] = useState(open ?? false);
4763
4793
  const [selectedValues, setSelectedValues] = useState(value ?? []);
@@ -4788,9 +4818,10 @@ var MultiSelect = React$1.forwardRef(({ value, size = "large", label, error, onV
4788
4818
  setSelectedValues(value ?? []);
4789
4819
  }, [value]);
4790
4820
  const updateValues = React$1.useCallback((values) => {
4821
+ if (disabled) return;
4791
4822
  setSelectedValues(values);
4792
4823
  onValueChange?.(values);
4793
- }, [onValueChange]);
4824
+ }, [onValueChange, disabled]);
4794
4825
  const onItemClick = React$1.useCallback((newValue) => {
4795
4826
  let newSelectedValues;
4796
4827
  if (selectedValues.some((v) => String(v) === String(newValue))) newSelectedValues = selectedValues.filter((v) => String(v) !== String(newValue));
@@ -4838,10 +4869,11 @@ var MultiSelect = React$1.forwardRef(({ value, size = "large", label, error, onV
4838
4869
  open: isMounted && isPopoverOpen,
4839
4870
  onOpenChange: onPopoverOpenChange,
4840
4871
  modal: modalPopover,
4841
- children: [/* @__PURE__ */ jsx(PopoverPrimitive.Trigger, {
4842
- asChild: true,
4872
+ children: [/* @__PURE__ */ jsx(MultiSelectTrigger, {
4873
+ anchorRef,
4843
4874
  children: /* @__PURE__ */ jsx("button", {
4844
4875
  ref: inputRef ?? ref,
4876
+ disabled,
4845
4877
  "aria-label": ariaLabel ?? (typeof label === "string" ? label : void 0),
4846
4878
  onClick: handleTogglePopover,
4847
4879
  className: cls(invisible ? {
@@ -4890,7 +4922,7 @@ var MultiSelect = React$1.forwardRef(({ value, size = "large", label, error, onV
4890
4922
  event.stopPropagation();
4891
4923
  handleClear();
4892
4924
  }
4893
- }), /* @__PURE__ */ jsx("div", {
4925
+ }), chevron && /* @__PURE__ */ jsx("div", {
4894
4926
  className: cls("px-2 h-full flex items-center"),
4895
4927
  children: /* @__PURE__ */ jsx(ChevronDownIcon$1, {
4896
4928
  size: size === "large" ? iconSize.medium : iconSize.small,
@@ -4903,7 +4935,7 @@ var MultiSelect = React$1.forwardRef(({ value, size = "large", label, error, onV
4903
4935
  children: [/* @__PURE__ */ jsx("span", {
4904
4936
  className: "text-sm",
4905
4937
  children: placeholder
4906
- }), /* @__PURE__ */ jsx("div", {
4938
+ }), chevron && /* @__PURE__ */ jsx("div", {
4907
4939
  className: cls("px-2 h-full flex items-center"),
4908
4940
  children: /* @__PURE__ */ jsx(ChevronDownIcon$1, {
4909
4941
  size: size === "large" ? iconSize.medium : iconSize.small,
@@ -5179,7 +5211,7 @@ function SearchBar({ onClick, onTextSearch, placeholder = "Search", expandable =
5179
5211
  }
5180
5212
  //#endregion
5181
5213
  //#region src/components/Select.tsx
5182
- var Select = forwardRef(({ inputRef, open, name, fullWidth = false, id, onOpenChange, value, onChange, onValueChange, className, inputClassName, viewportClassName, placeholder, renderValue, label, size = "large", error, disabled, padding = true, position = "item-aligned", endAdornment, invisible, children, dataType = "string", portalContainer: manualContainer, "aria-label": ariaLabel, ...props }, ref) => {
5214
+ var Select = forwardRef(({ inputRef, open, name, fullWidth = false, id, onOpenChange, value, onChange, onValueChange, className, inputClassName, viewportClassName, placeholder, renderValue, label, size = "large", error, disabled, padding = true, position = "item-aligned", endAdornment, invisible, chevron = true, children, dataType = "string", portalContainer: manualContainer, "aria-label": ariaLabel, ...props }, ref) => {
5183
5215
  const [openInternal, setOpenInternal] = useState(open ?? false);
5184
5216
  useEffect(() => {
5185
5217
  setOpenInternal(open ?? false);
@@ -5220,6 +5252,17 @@ var Select = forwardRef(({ inputRef, open, name, fullWidth = false, id, onOpenCh
5220
5252
  renderValue,
5221
5253
  value
5222
5254
  ]);
5255
+ const emptyItemDisplay = useMemo(() => {
5256
+ if (stringValue !== "") return null;
5257
+ const emptyItem = Children.toArray(children).find((child) => React.isValidElement(child) && String(child.props.value) === "");
5258
+ if (!emptyItem) return null;
5259
+ return value !== void 0 && renderValue ? renderValue(value) : emptyItem.props.children;
5260
+ }, [
5261
+ children,
5262
+ renderValue,
5263
+ stringValue,
5264
+ value
5265
+ ]);
5223
5266
  return /* @__PURE__ */ jsxs(SelectPrimitive.Root, {
5224
5267
  name,
5225
5268
  value: stringValue,
@@ -5277,11 +5320,11 @@ var Select = forwardRef(({ inputRef, open, name, fullWidth = false, id, onOpenCh
5277
5320
  e.preventDefault();
5278
5321
  e.stopPropagation();
5279
5322
  },
5280
- placeholder,
5323
+ placeholder: emptyItemDisplay ?? placeholder,
5281
5324
  className: "w-full",
5282
5325
  children: hasValue && value !== void 0 && renderValue ? renderValue(value) : displayChildren || placeholder
5283
5326
  })
5284
- }), /* @__PURE__ */ jsx(SelectPrimitive.Icon, {
5327
+ }), chevron && /* @__PURE__ */ jsx(SelectPrimitive.Icon, {
5285
5328
  asChild: true,
5286
5329
  children: /* @__PURE__ */ jsx(ChevronDownIcon$1, {
5287
5330
  size: size === "large" ? iconSize.medium : iconSize.small,
@@ -5371,7 +5414,7 @@ var Slider = React$1.forwardRef(({ className, size = "regular", ...props }, ref)
5371
5414
  "bg-primary": !props.disabled,
5372
5415
  "bg-surface-raised-hover": props.disabled
5373
5416
  }) })
5374
- }), (props.value ?? [0]).map((_, index) => /* @__PURE__ */ jsx(SliderThumb, {
5417
+ }), (props.value ?? props.defaultValue ?? [0]).map((_, index) => /* @__PURE__ */ jsx(SliderThumb, {
5375
5418
  index,
5376
5419
  props,
5377
5420
  hovered,
@@ -5605,7 +5648,7 @@ function setRef(ref, value) {
5605
5648
  }
5606
5649
  //#endregion
5607
5650
  //#region src/components/TextField.tsx
5608
- var TextField = forwardRef(({ value, onChange, label, type = "text", multiline = false, invisible, maxRows, minRows, disabled, error, endAdornment, autoFocus, placeholder, size = "large", className, style, inputClassName, inputStyle, inputRef: inputRefProp, ...inputProps }, ref) => {
5651
+ var TextField = forwardRef(({ value, onChange, onFocus, onBlur, label, type = "text", multiline = false, invisible, maxRows, minRows, disabled, error, endAdornment, autoFocus, placeholder, size = "large", className, style, inputClassName, inputStyle, inputRef: inputRefProp, ...inputProps }, ref) => {
5609
5652
  const fallbackRef = useRef(null);
5610
5653
  const inputRef = inputRefProp ?? fallbackRef;
5611
5654
  const autoId = useId();
@@ -5613,21 +5656,22 @@ var TextField = forwardRef(({ value, onChange, label, type = "text", multiline =
5613
5656
  const labelId = `${inputId}-label`;
5614
5657
  const [focused, setFocused] = React.useState(false);
5615
5658
  const hasValue = value !== void 0 && value !== null && value !== "";
5659
+ const handleFocus = (event) => {
5660
+ setFocused(true);
5661
+ onFocus?.(event);
5662
+ };
5663
+ const handleBlur = (event) => {
5664
+ setFocused(false);
5665
+ onBlur?.(event);
5666
+ };
5616
5667
  useEffect(() => {
5617
5668
  const element = inputRef && "current" in inputRef ? inputRef.current : null;
5618
5669
  if (element && document.activeElement === element) setFocused(true);
5619
5670
  }, []);
5620
- useEffect(() => {
5621
- if (type !== "number") return;
5622
- const handleWheel = (event) => {
5623
- if (event.target instanceof HTMLElement) event.target.blur();
5624
- };
5625
- const element = "current" in inputRef ? inputRef.current : inputRef;
5626
- element?.addEventListener("wheel", handleWheel);
5627
- return () => {
5628
- element?.removeEventListener("wheel", handleWheel);
5629
- };
5630
- }, [inputRef, type]);
5671
+ const handleWheel = (event) => {
5672
+ if (type === "number") event.currentTarget.blur();
5673
+ inputProps.onWheel?.(event);
5674
+ };
5631
5675
  const input = multiline ? /* @__PURE__ */ jsx("textarea", {
5632
5676
  ...inputProps,
5633
5677
  ref: inputRef,
@@ -5635,13 +5679,14 @@ var TextField = forwardRef(({ value, onChange, label, type = "text", multiline =
5635
5679
  "aria-labelledby": label ? labelId : inputProps["aria-labelledby"],
5636
5680
  "aria-invalid": error || void 0,
5637
5681
  "aria-disabled": disabled || void 0,
5682
+ disabled,
5638
5683
  placeholder: focused || hasValue || !label ? placeholder : void 0,
5639
5684
  autoFocus,
5640
5685
  rows: typeof minRows === "string" ? parseInt(minRows) : minRows ?? 3,
5641
5686
  value: value ?? "",
5642
5687
  onChange,
5643
- onFocus: () => setFocused(true),
5644
- onBlur: () => setFocused(false),
5688
+ onFocus: handleFocus,
5689
+ onBlur: handleBlur,
5645
5690
  style: inputStyle,
5646
5691
  className: cls(invisible ? focusedInvisibleMixin : "", "rounded-lg resize-none w-full outline-none text-sm bg-transparent min-h-[64px] px-3", label ? "pt-8 pb-2" : "py-2", disabled && "outline-none opacity-50 text-surface-accent-600 dark:text-surface-accent-500", inputClassName)
5647
5692
  }) : /* @__PURE__ */ jsx("input", {
@@ -5666,8 +5711,9 @@ var TextField = forwardRef(({ value, onChange, label, type = "text", multiline =
5666
5711
  }[size] : size === "smallest" ? "py-0.5" : size === "small" ? "py-1" : "py-2", endAdornment ? "pr-12" : "pr-3", disabled && "outline-none opacity-65 dark:opacity-60 text-surface-accent-800 dark:text-white", inputClassName),
5667
5712
  placeholder: focused || hasValue || !label ? placeholder : void 0,
5668
5713
  autoFocus,
5669
- onFocus: () => setFocused(true),
5670
- onBlur: () => setFocused(false),
5714
+ onFocus: handleFocus,
5715
+ onBlur: handleBlur,
5716
+ onWheel: handleWheel,
5671
5717
  type,
5672
5718
  value: type === "number" && Number.isNaN(value) ? "" : value ?? "",
5673
5719
  onChange
@@ -7035,12 +7081,12 @@ function VirtualTableInput(props) {
7035
7081
  //#endregion
7036
7082
  //#region src/components/VirtualTable/fields/VirtualTableNumberInput.tsx
7037
7083
  function VirtualTableNumberInput(props) {
7038
- const { align = "left", value, updateValue, focused } = props;
7039
- const propStringValue = value && typeof value === "number" ? value.toString() : "";
7084
+ const { align = "left", value, updateValue, focused, disabled } = props;
7085
+ const propStringValue = typeof value === "number" ? value.toString() : "";
7040
7086
  const [internalValue, setInternalValue] = useState(propStringValue);
7041
7087
  const prevValue = useRef(value);
7042
7088
  useEffect(() => {
7043
- if (prevValue.current !== value && String(value) !== internalValue) setInternalValue(value ? value.toString() : null);
7089
+ if (prevValue.current !== value && String(value) !== internalValue) setInternalValue(value !== void 0 && value !== null ? value.toString() : null);
7044
7090
  prevValue.current = value;
7045
7091
  }, [value]);
7046
7092
  useDebouncedCallback(internalValue, React.useCallback(() => {
@@ -7061,6 +7107,7 @@ function VirtualTableNumberInput(props) {
7061
7107
  return /* @__PURE__ */ jsx(TextField, {
7062
7108
  inputRef,
7063
7109
  invisible: true,
7110
+ disabled,
7064
7111
  size: "small",
7065
7112
  className: "w-full",
7066
7113
  inputClassName: cls("p-0 m-0 bg-transparent border-none outline-hidden font-normal leading-normal text-unset", focusedDisabled),
@@ -7076,7 +7123,7 @@ function VirtualTableNumberInput(props) {
7076
7123
  //#endregion
7077
7124
  //#region src/components/VirtualTable/fields/VirtualTableSwitch.tsx
7078
7125
  function VirtualTableSwitch(props) {
7079
- const { internalValue, updateValue, focused } = props;
7126
+ const { internalValue, updateValue, focused, disabled } = props;
7080
7127
  const ref = React.useRef(null);
7081
7128
  useEffect(() => {
7082
7129
  if (ref.current && focused) ref.current.focus({ preventScroll: true });
@@ -7085,26 +7132,71 @@ function VirtualTableSwitch(props) {
7085
7132
  ref,
7086
7133
  size: "small",
7087
7134
  value: Boolean(internalValue),
7135
+ disabled,
7088
7136
  onValueChange: updateValue
7089
7137
  });
7090
7138
  }
7091
7139
  //#endregion
7092
7140
  //#region src/components/VirtualTable/fields/VirtualTableDateField.tsx
7093
7141
  function VirtualTableDateField(props) {
7094
- const { name, disabled, error, mode, timezone, internalValue, updateValue, small = false, locale } = props;
7095
- return /* @__PURE__ */ jsx(DateTimeField, {
7096
- value: internalValue ?? void 0,
7097
- onChange: (dateValue) => updateValue(dateValue ?? null),
7098
- disabled,
7099
- error: Boolean(error),
7100
- "aria-label": name,
7101
- invisible: true,
7102
- size: small ? "small" : "medium",
7103
- inputClassName: cls("w-full h-full", focusedDisabled),
7104
- className: cls("w-full h-full", focusedDisabled),
7105
- mode,
7106
- timezone,
7107
- locale
7142
+ const { name, disabled, error, mode, timezone, internalValue, updateValue, small = false, locale, pickerButton = true, inputRef } = props;
7143
+ const [focused, setFocused] = useState(false);
7144
+ const focusedRef = useRef(false);
7145
+ const [draft, setDraft] = useState(null);
7146
+ const draftRef = useRef(null);
7147
+ const timerRef = useRef(void 0);
7148
+ const updateValueRef = useRef(updateValue);
7149
+ useEffect(() => {
7150
+ updateValueRef.current = updateValue;
7151
+ }, [updateValue]);
7152
+ const commit = useCallback(() => {
7153
+ clearTimeout(timerRef.current);
7154
+ const pending = draftRef.current;
7155
+ if (!pending) return;
7156
+ draftRef.current = null;
7157
+ setDraft(null);
7158
+ updateValueRef.current(pending.value);
7159
+ }, []);
7160
+ const onDateChange = (dateValue) => {
7161
+ const pending = { value: dateValue ?? null };
7162
+ draftRef.current = pending;
7163
+ setDraft(pending);
7164
+ clearTimeout(timerRef.current);
7165
+ if (!focusedRef.current) commit();
7166
+ else if (!pending.value || pending.value.getFullYear() >= 1e3) timerRef.current = setTimeout(commit, 400);
7167
+ };
7168
+ useEffect(() => () => {
7169
+ clearTimeout(timerRef.current);
7170
+ if (draftRef.current) updateValueRef.current(draftRef.current.value);
7171
+ }, []);
7172
+ const shownValue = draft ? draft.value : internalValue;
7173
+ return /* @__PURE__ */ jsx("div", {
7174
+ className: "w-full h-full flex items-center",
7175
+ onFocus: () => {
7176
+ focusedRef.current = true;
7177
+ setFocused(true);
7178
+ },
7179
+ onBlur: () => {
7180
+ focusedRef.current = false;
7181
+ setFocused(false);
7182
+ commit();
7183
+ },
7184
+ children: /* @__PURE__ */ jsx(DateTimeField, {
7185
+ value: shownValue ?? void 0,
7186
+ onChange: onDateChange,
7187
+ disabled,
7188
+ error: Boolean(error),
7189
+ "aria-label": name,
7190
+ invisible: true,
7191
+ pickerButton,
7192
+ inputRef,
7193
+ size: small ? "small" : "medium",
7194
+ inputClassName: cls("w-full h-full", focusedDisabled, !pickerButton && "px-0", !shownValue && !focused && "text-transparent"),
7195
+ className: cls("w-full h-full", focusedDisabled),
7196
+ mode,
7197
+ timezone,
7198
+ locale
7199
+ })
7108
7200
  });
7109
7201
  }
7110
7202
  //#endregion