@povio/ui 2.3.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -108,7 +108,8 @@ var DatePickerInput = ({ ref, as, groupProps, fieldProps, endFieldProps, buttonP
108
108
  icon: TodayIcon,
109
109
  size: "none",
110
110
  onPress: onToday,
111
- className: "relative z-1"
111
+ className: "relative z-1",
112
+ isDisabled
112
113
  }),
113
114
  disableManualEntry && placeholder && !fieldProps.value ? /* @__PURE__ */ jsx(Typography, {
114
115
  size: "label-1",
@@ -33,7 +33,8 @@ var NumberInputBase = (props) => {
33
33
  locale,
34
34
  formatOptions
35
35
  };
36
- const { labelProps, inputProps } = useNumberField(numberProps, useNumberFieldState(numberProps), numberFieldRef);
36
+ const state = useNumberFieldState(numberProps);
37
+ const { labelProps, inputProps } = useNumberField(numberProps, state, numberFieldRef);
37
38
  const formFieldProps = {
38
39
  error,
39
40
  label,
@@ -47,6 +48,10 @@ var NumberInputBase = (props) => {
47
48
  headerClassName,
48
49
  errorClassName
49
50
  };
51
+ const handleInputBlur = useCallback((e) => {
52
+ const target = numberFieldRef.current ?? e?.target;
53
+ onBlur?.({ target });
54
+ }, [onBlur]);
50
55
  const inputContentProps = {
51
56
  unit,
52
57
  isLoading,
@@ -55,12 +60,12 @@ var NumberInputBase = (props) => {
55
60
  leadingIcon,
56
61
  trailingIcon,
57
62
  isClearable,
58
- value,
59
- onChange: (val) => onChange?.(val === "" ? null : Number(val)),
60
- onBlur: useCallback((e) => {
61
- const target = numberFieldRef.current ?? e?.target;
62
- onBlur?.({ target });
63
- }, [onBlur])
63
+ onChange: (val) => {
64
+ if (val === "") state.setInputValue("");
65
+ onChange?.(val === "" ? null : Number(val));
66
+ },
67
+ value: state.inputValue,
68
+ onBlur: handleInputBlur
64
69
  };
65
70
  const headerProps = {
66
71
  label,
@@ -97,10 +102,10 @@ var NumberInputBase = (props) => {
97
102
  size,
98
103
  children: /* @__PURE__ */ jsx(Input, {
99
104
  ...inputProps,
100
- ref: mergeRefs(ref, inputRef),
105
+ ref: mergeRefs(ref, inputRef, numberFieldRef),
101
106
  "data-is-dirty": isDirty || void 0,
102
107
  "data-is-required": isRequired || void 0,
103
- "data-is-empty": value === null || value === void 0 || void 0,
108
+ "data-is-empty": state.inputValue === "" || state.inputValue === void 0 || state.inputValue === null || void 0,
104
109
  placeholder: as === "floating" ? "\xA0" : inputProps.placeholder,
105
110
  className: "w-full outline-none",
106
111
  onFocus: (e) => {
@@ -19,13 +19,14 @@ var TextInputBase = (props) => {
19
19
  const { ref, inputClassName, label, tooltipText, helperText, isRequired, rightContent, isDisabled, isDirty, headerClassName, errorClassName, isHeaderHidden, error, className, unit, isLoading, action, leadingIcon, trailingIcon, value, onChange, onBlur, as = ui.input.as, hideLabel = ui.input.hideLabel, variant = ui.input.variant, size = ui.input.size, isClearable = ui.input.isClearable, ...rest } = props;
20
20
  const textFieldRef = useRef(null);
21
21
  const { isFocusVisible } = useFocusVisible();
22
+ const inputValue = value ?? "";
22
23
  const { labelProps, inputProps } = useTextField({
23
24
  ...rest,
24
25
  label,
25
26
  isDisabled,
26
27
  isInvalid: !!error,
27
28
  isRequired,
28
- value,
29
+ value: inputValue,
29
30
  onChange,
30
31
  onBlur
31
32
  }, textFieldRef);
@@ -50,7 +51,7 @@ var TextInputBase = (props) => {
50
51
  leadingIcon,
51
52
  trailingIcon,
52
53
  isClearable,
53
- value,
54
+ value: inputValue,
54
55
  onChange,
55
56
  onBlur
56
57
  };
@@ -90,7 +91,7 @@ var TextInputBase = (props) => {
90
91
  children: /* @__PURE__ */ jsx(Input, {
91
92
  ...inputProps,
92
93
  ref: mergeRefs(ref, inputRef),
93
- "data-is-empty": value === "" || value === null || value === void 0 || void 0,
94
+ "data-is-empty": inputValue === "" || void 0,
94
95
  "data-is-dirty": isDirty || void 0,
95
96
  "data-is-required": isRequired || void 0,
96
97
  "data-is-disabled": isDisabled || void 0,
@@ -27,7 +27,7 @@ var SelectInput = ({ ref, placeholder, variant, as, size, isDisabled, isInvalid,
27
27
  const { fieldState, isOpen, setIsOpen, listItems, selectedItems, onChange, onClear, onRemove, isMultiple, isLoading } = SelectContext.useSelect();
28
28
  const isEmpty = selectedItems.length === 0;
29
29
  const showTags = isMultiple && !isEmpty;
30
- const showClearButton = isClearable && isHovered && (selectedItems.length > 0 || isSearchable && fieldState.inputValue !== "");
30
+ const showClearButton = isClearable && (selectedItems.length > 0 || isSearchable && fieldState.inputValue !== "");
31
31
  const labelProps = useMemo(() => {
32
32
  const { labelProps: headerLabelProps } = headerProps ?? {};
33
33
  if (!(as && ["filter", "floating"].includes(as)) || isSearchable) return headerLabelProps;
@@ -1,4 +1,5 @@
1
1
  import { CloseIcon } from "../../../assets/icons/Close.js";
2
+ import { UIConfig } from "../../../config/uiConfig.context.js";
2
3
  import { InlineIconButton } from "../../buttons/InlineIconButton/InlineIconButton.js";
3
4
  import "../../../config/i18n.js";
4
5
  import { jsx } from "react/jsx-runtime";
@@ -7,12 +8,14 @@ import { useTranslation } from "react-i18next";
7
8
  //#region src/components/inputs/shared/InputClear.tsx
8
9
  var InputClear = ({ onClear, className, style, show }) => {
9
10
  const { t } = useTranslation("ui");
11
+ const alwaysShowClear = UIConfig.useConfig().input.alwaysShowClear;
10
12
  return /* @__PURE__ */ jsx(InlineIconButton, {
11
13
  color: "secondary",
12
- className: clsx("invisible relative z-1 flex items-center", "group-focus-within:visible group-hover/date-picker-content:visible group-hover/select-content:visible group-hover/text-area:visible group-hover:visible", "border-0!", !show && "invisible!", className),
14
+ className: clsx("relative z-1 flex items-center", !alwaysShowClear && "md:invisible group-focus-within:visible group-hover/date-picker-content:visible group-hover/select-content:visible group-hover/text-area:visible group-hover:visible", "border-0!", !show && "invisible!", className),
13
15
  label: t(($) => $.ui.clearAlt),
14
16
  icon: CloseIcon,
15
17
  onPress: onClear,
18
+ onMouseDown: (e) => e.preventDefault(),
16
19
  excludeFromTabOrder: true,
17
20
  style
18
21
  });
@@ -26,6 +26,7 @@ var staticTransition = {
26
26
  1
27
27
  ]
28
28
  };
29
+ var KEYBOARD_INSET_THRESHOLD = 48;
29
30
  var BottomSheetBase = ({ isOpen, onOpenChange, onStateChange, isDismissable = true, isScrollable = true, height = "full", label, portalContainerRef, children, footer, hideHeader, hideThumb: hideThumbProp, sheetMarginTop = 96, sheetMarginBottom = 128, closeDragThreshold: closeDragThresholdProp, closeVelocityThreshold: closeVelocityThresholdProp, shouldCloseOnInteractOutside, containerClassName, overlayClassName, headerTypography: headerTypographyProp }) => {
30
31
  const uiConfig = UIConfig.useConfig();
31
32
  const closeDragThreshold = closeDragThresholdProp ?? uiConfig.bottomSheet.closeDragThreshold;
@@ -48,6 +49,27 @@ var BottomSheetBase = ({ isOpen, onOpenChange, onStateChange, isDismissable = tr
48
49
  const focusTrapRef = useRef(null);
49
50
  const [footerElement, footerRef, setFooterElement] = useStateAndRef(null);
50
51
  const [footerHeight, setFooterHeight] = useState(0);
52
+ const [keyboardInset, setKeyboardInset] = useState(0);
53
+ useEffect(() => {
54
+ if (!isOpen) {
55
+ setKeyboardInset(0);
56
+ return;
57
+ }
58
+ const vv = window.visualViewport;
59
+ if (!vv) return;
60
+ const update = () => {
61
+ const naturalHeight = vv.height * Math.max(vv.scale, 1);
62
+ const next = Math.max(0, window.innerHeight - naturalHeight);
63
+ setKeyboardInset(next > KEYBOARD_INSET_THRESHOLD ? Math.round(next) : 0);
64
+ };
65
+ update();
66
+ vv.addEventListener("resize", update);
67
+ vv.addEventListener("scroll", update);
68
+ return () => {
69
+ vv.removeEventListener("resize", update);
70
+ vv.removeEventListener("scroll", update);
71
+ };
72
+ }, [isOpen]);
51
73
  useEffect(() => {
52
74
  if (!footerElement) return;
53
75
  const onResize = () => {
@@ -77,6 +99,7 @@ var BottomSheetBase = ({ isOpen, onOpenChange, onStateChange, isDismissable = tr
77
99
  isOpen: true,
78
100
  UNSTABLE_portalContainer: portalContainerRef?.current,
79
101
  className: clsx("fixed top-0 left-0 z-10 w-screen h-dvh", containerClassName),
102
+ style: { "--bottom-sheet-keyboard-inset": `${keyboardInset}px` },
80
103
  onOpenChange,
81
104
  isDismissable,
82
105
  ref: overlayRef,
@@ -110,7 +133,8 @@ var BottomSheetBase = ({ isOpen, onOpenChange, onStateChange, isDismissable = tr
110
133
  transition: staticTransition,
111
134
  style: {
112
135
  y,
113
- minHeight: "100%"
136
+ height: "calc(100dvh - var(--bottom-sheet-keyboard-inset, 0px))",
137
+ minHeight: "calc(100dvh - var(--bottom-sheet-keyboard-inset, 0px))"
114
138
  },
115
139
  drag: "y",
116
140
  dragListener: false,
@@ -188,7 +212,7 @@ var BottomSheetBase = ({ isOpen, onOpenChange, onStateChange, isDismissable = tr
188
212
  initial: { opacity: 0 },
189
213
  exit: { opacity: 0 },
190
214
  ref: setFooterElement,
191
- className: clsx("pointer-events-auto absolute z-50 w-full bg-elevation-fill-default-2", "top-[100dvh] left-0 translate-y-[calc(-100%-var(--scroll-position,0px))]"),
215
+ className: clsx("pointer-events-auto absolute z-50 w-full bg-elevation-fill-default-2", "top-[calc(100dvh-var(--bottom-sheet-keyboard-inset,0))] left-0 translate-y-[calc(-100%-var(--scroll-position,0))]"),
192
216
  children: footer
193
217
  })
194
218
  ] })
@@ -19,7 +19,9 @@ export declare namespace UIConfig {
19
19
  [P in keyof T]-?: T[P] extends object ? DeepRequired<T[P]> : Exclude<T[P], null | undefined>;
20
20
  };
21
21
  export interface Options {
22
- input: Pick<TextInputProps, "variant" | "isClearable" | "hideLabel" | "as" | "size">;
22
+ input: Pick<TextInputProps, "variant" | "isClearable" | "hideLabel" | "as" | "size"> & {
23
+ alwaysShowClear: boolean;
24
+ };
23
25
  button: Pick<ButtonProps, "variant" | "size">;
24
26
  numberInput: Pick<NumberInputProps, "formatOptions">;
25
27
  radioGroup: Pick<RadioGroupProps, "variant" | "hideLabel">;
@@ -11,7 +11,8 @@ var UIConfig;
11
11
  as: "default",
12
12
  size: "default",
13
13
  isClearable: false,
14
- hideLabel: false
14
+ hideLabel: false,
15
+ alwaysShowClear: false
15
16
  },
16
17
  button: {
17
18
  variant: "contained",
@@ -9,7 +9,7 @@ var DomUtils;
9
9
  "image"
10
10
  ]);
11
11
  _DomUtils.isKeyboardInput = (elem) => {
12
- return elem.tagName === "INPUT" && !KEYBOARD_INPUTS.has(elem.type) || elem.hasAttribute("contenteditable");
12
+ return elem.tagName === "INPUT" && !KEYBOARD_INPUTS.has(elem.type) || elem.tagName === "TEXTAREA" || elem.hasAttribute("contenteditable");
13
13
  };
14
14
  _DomUtils.isKeyboardEvent = (event) => {
15
15
  return event.nativeEvent instanceof KeyboardEvent;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@povio/ui",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
4
4
  "type": "module",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",