@povio/ui 2.2.9-rc.20 → 2.2.9-rc.22

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.
@@ -172,6 +172,7 @@ var DatePicker = ({ fullIso = true, minValue, maxValue, renderStaticInput, ...pr
172
172
  const ui = UIConfig.useConfig();
173
173
  const datePickerInputContentRowCva = UIStyle.useCva("datePickerInput.contentRowCva", datePickerInputContentRow);
174
174
  const { locale } = useLocale();
175
+ const shouldForceLeadingZeros = props.shouldForceLeadingZeros ?? ui.dateInput.shouldForceLeadingZeros;
175
176
  const [renderInput, setRenderInput] = useState(!(renderStaticInput ?? ui.renderStaticInput));
176
177
  const [shouldFocus, setShouldFocus] = useState(false);
177
178
  const inputRef = useRef(null);
@@ -218,8 +219,8 @@ var DatePicker = ({ fullIso = true, minValue, maxValue, renderStaticInput, ...pr
218
219
  const disableManualEntry = props.disableManualEntry ?? ui.dateInput.disableManualEntry;
219
220
  const showDropdown = !props.disableDropdown || disableManualEntry;
220
221
  const staticDateValue = rawValue ? parseCalendarDate(rawValue) : null;
221
- const displayValue = staticDateValue ? DateTimeUtils.formatCalendarDateLocalized(staticDateValue, locale) : "";
222
- const staticPlaceholder = rawValue ? "" : props.placeholder ?? DateTimeUtils.getDatePlaceholder(locale);
222
+ const displayValue = staticDateValue ? DateTimeUtils.formatCalendarDateLocalized(staticDateValue, locale, { shouldForceLeadingZeros }) : "";
223
+ const staticPlaceholder = props.placeholder ?? DateTimeUtils.getDatePlaceholder(locale, { shouldForceLeadingZeros });
223
224
  return /* @__PURE__ */ jsx(StaticInput, {
224
225
  ...props,
225
226
  onInteract: (focus) => {
@@ -548,6 +548,7 @@ var DateRangePicker = ({ fullIso = true, minValue, maxValue, renderStaticInput,
548
548
  const ui = UIConfig.useConfig();
549
549
  const datePickerInputContentRowCva = UIStyle.useCva("datePickerInput.contentRowCva", datePickerInputContentRow);
550
550
  const { locale } = useLocale$1();
551
+ const shouldForceLeadingZeros = props.shouldForceLeadingZeros ?? ui.dateInput.shouldForceLeadingZeros;
551
552
  const [renderInput, setRenderInput] = useState(!(renderStaticInput ?? ui.renderStaticInput));
552
553
  const [shouldFocus, setShouldFocus] = useState(false);
553
554
  const inputRef = useRef(null);
@@ -615,8 +616,9 @@ var DateRangePicker = ({ fullIso = true, minValue, maxValue, renderStaticInput,
615
616
  const todayIconButtonSize = props.todayIconButtonSize ?? ui.dateInput.todayIconButtonSize;
616
617
  const disableManualEntry = props.disableManualEntry ?? ui.dateInput.disableManualEntry;
617
618
  const showDropdown = !props.disableDropdown || disableManualEntry;
618
- const defaultDatePlaceholder = DateTimeUtils.getDatePlaceholder(locale);
619
- const staticPlaceholder = !!(rawValue?.start || rawValue?.end) ? "" : props.placeholder ?? /* @__PURE__ */ jsxs(Fragment, { children: [
619
+ const defaultDatePlaceholder = DateTimeUtils.getDatePlaceholder(locale, { shouldForceLeadingZeros });
620
+ const hasProvidedRangeValue = !!(rawValue?.start || rawValue?.end);
621
+ const staticPlaceholder = props.placeholder ?? /* @__PURE__ */ jsxs(Fragment, { children: [
620
622
  /* @__PURE__ */ jsx("span", { children: defaultDatePlaceholder }),
621
623
  /* @__PURE__ */ jsx("span", {
622
624
  className: "pointer-events-none select-none",
@@ -628,7 +630,7 @@ var DateRangePicker = ({ fullIso = true, minValue, maxValue, renderStaticInput,
628
630
  if (!value) return "";
629
631
  const parsedDate = parseCalendarDate(value);
630
632
  if (!parsedDate) return "";
631
- return DateTimeUtils.formatCalendarDateLocalized(parsedDate, locale);
633
+ return DateTimeUtils.formatCalendarDateLocalized(parsedDate, locale, { shouldForceLeadingZeros });
632
634
  };
633
635
  const start = formatStaticDate(rawValue?.start ?? null);
634
636
  const end = formatStaticDate(rawValue?.end ?? null);
@@ -657,7 +659,7 @@ var DateRangePicker = ({ fullIso = true, minValue, maxValue, renderStaticInput,
657
659
  isDisabled,
658
660
  placeholder: staticPlaceholder,
659
661
  displayValue,
660
- isEmpty: !hasRangeValue,
662
+ isEmpty: !hasProvidedRangeValue,
661
663
  dataAttributes: {
662
664
  dataIsEmpty: !hasRangeValue,
663
665
  dataIsFilled: hasRangeValue,
@@ -192,6 +192,7 @@ var DateTimePicker = ({ fullIso = true, renderStaticInput, ...props }) => {
192
192
  const ui = UIConfig.useConfig();
193
193
  const datePickerInputContentRowCva = UIStyle.useCva("datePickerInput.contentRowCva", datePickerInputContentRow);
194
194
  const { locale } = useLocale();
195
+ const shouldForceLeadingZeros = props.shouldForceLeadingZeros ?? ui.dateInput.shouldForceLeadingZeros;
195
196
  const [renderInput, setRenderInput] = useState(!(renderStaticInput ?? ui.renderStaticInput));
196
197
  const [shouldFocus, setShouldFocus] = useState(false);
197
198
  const inputRef = useRef(null);
@@ -231,8 +232,8 @@ var DateTimePicker = ({ fullIso = true, renderStaticInput, ...props }) => {
231
232
  const disableManualEntry = props.disableManualEntry ?? ui.dateInput.disableManualEntry;
232
233
  const showDropdown = !props.disableDropdown || disableManualEntry;
233
234
  const staticDateTimeValue = rawValue ? parseDateValue(rawValue) : null;
234
- const displayValue = staticDateTimeValue && "hour" in staticDateTimeValue ? DateTimeUtils.formatCalendarDateTimeLocalized(staticDateTimeValue, locale) : "";
235
- const staticPlaceholder = rawValue ? "" : props.placeholder ?? DateTimeUtils.getDateTimePlaceholder(locale);
235
+ const displayValue = staticDateTimeValue && "hour" in staticDateTimeValue ? DateTimeUtils.formatCalendarDateTimeLocalized(staticDateTimeValue, locale, { shouldForceLeadingZeros }) : "";
236
+ const staticPlaceholder = props.placeholder ?? DateTimeUtils.getDateTimePlaceholder(locale, { shouldForceLeadingZeros });
236
237
  return /* @__PURE__ */ jsx(StaticInput, {
237
238
  ...props,
238
239
  onInteract: (focus) => {
@@ -179,7 +179,7 @@ var TimePicker = ({ renderStaticInput, ...props }) => {
179
179
  const showDropdown = !props.disableDropdown || disableManualEntry;
180
180
  const staticTimeValue = rawValue ? parseTimeValue(rawValue) : null;
181
181
  const displayValue = staticTimeValue ? DateTimeUtils.formatTimeLocalized(staticTimeValue, locale) : "";
182
- const staticPlaceholder = rawValue ? "" : props.placeholder ?? DateTimeUtils.getTimePlaceholder(locale);
182
+ const staticPlaceholder = props.placeholder ?? DateTimeUtils.getTimePlaceholder(locale);
183
183
  return /* @__PURE__ */ jsx(StaticInput, {
184
184
  ...props,
185
185
  onInteract: (focus) => {
@@ -177,16 +177,16 @@ var NumberInput = ({ renderStaticInput, ...props }) => {
177
177
  isDisabled,
178
178
  className: clsx("group w-full", as === "inline" && "h-full", props.className),
179
179
  inputClassName: props.inputClassName,
180
- placeholder: as === "floating" || staticValue ? "" : props.placeholder,
180
+ placeholder: props.placeholder,
181
181
  displayValue,
182
182
  isEmpty: !hasValue,
183
183
  dataAttributes: {
184
- dataIsEmpty: !!!staticValue,
184
+ dataIsEmpty: !staticValue,
185
185
  dataIsFilled: !(`${staticValue}` === "" || staticValue === null || staticValue === void 0),
186
186
  dataIsDirty: props.isDirty,
187
187
  dataIsRequired: props.isRequired,
188
- dataIsDisabled: isDisabled,
189
- dataDisabled: isDisabled,
188
+ dataIsDisabled: props.isDisabled,
189
+ dataDisabled: props.isDisabled,
190
190
  dataInvalid: !!props.error,
191
191
  dataHasSelection: hasValue
192
192
  },
@@ -0,0 +1,38 @@
1
+ import { FocusEvent, Ref } from 'react';
2
+ import { NumberFieldProps as AriaNumberFieldProps } from 'react-aria-components';
3
+ import { FieldValues } from 'react-hook-form';
4
+ import { FormFieldProps } from '../../FormField/FormField';
5
+ import { ControlProps } from '../../shared/form.types';
6
+ import { InputVariantProps } from '../../shared/input.cva';
7
+ export interface NumberRangeValue {
8
+ min: number | null;
9
+ max: number | null;
10
+ }
11
+ interface NumberRangeInputBaseProps extends FormFieldProps, InputVariantProps, Omit<AriaNumberFieldProps, "className" | "defaultValue" | "label" | "maxValue" | "minValue" | "onBlur" | "onChange" | "value"> {
12
+ ref?: Ref<HTMLDivElement>;
13
+ value?: NumberRangeValue | null;
14
+ minValue?: number | null;
15
+ maxValue?: number | null;
16
+ minPlaceholder?: string;
17
+ maxPlaceholder?: string;
18
+ minLabel?: string;
19
+ maxLabel?: string;
20
+ invalidRangeError?: string;
21
+ inputClassName?: string;
22
+ minInputClassName?: string;
23
+ maxInputClassName?: string;
24
+ hideInnerLabels?: boolean;
25
+ isDirty?: boolean;
26
+ isClearable?: boolean;
27
+ autoFocusOnMount?: boolean;
28
+ onChange?: (value: NumberRangeValue) => void;
29
+ onMinChange?: (value: number | null) => void;
30
+ onMaxChange?: (value: number | null) => void;
31
+ onBlur?: (e: FocusEvent<HTMLInputElement>) => void;
32
+ }
33
+ export type NumberRangeInputProps = NumberRangeInputBaseProps & {
34
+ renderStaticInput?: boolean;
35
+ };
36
+ export type ControlledNumberRangeInputProps<TFieldValues extends FieldValues> = ControlProps<NumberRangeInputProps, TFieldValues>;
37
+ export declare const NumberRangeInput: <TFieldValues extends FieldValues>({ renderStaticInput, ...props }: ControlledNumberRangeInputProps<TFieldValues>) => import("react/jsx-runtime").JSX.Element;
38
+ export {};
@@ -0,0 +1,317 @@
1
+ import { UIStyle } from "../../../../config/uiStyle.context.js";
2
+ import { UIConfig } from "../../../../config/uiConfig.context.js";
3
+ import { FormFieldLabel } from "../../FormField/FormFieldLabel.js";
4
+ import { InputClear } from "../../shared/InputClear.js";
5
+ import { inputBase, inputSize } from "../../shared/input.cva.js";
6
+ import { FormField } from "../../FormField/FormField.js";
7
+ import { StaticInput } from "../../shared/StaticInput.js";
8
+ import { TooltipWrapper } from "../../shared/TooltipWrapper.js";
9
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
+ import { clsx } from "clsx";
11
+ import { useEffect, useRef, useState } from "react";
12
+ import { Input, useLocale } from "react-aria-components";
13
+ import { useFocusVisible, useFocusWithin, useHover, useNumberField } from "react-aria";
14
+ import { mergeRefs } from "@react-aria/utils";
15
+ import { Controller, useWatch } from "react-hook-form";
16
+ import { useNumberFieldState } from "react-stately";
17
+ //#region src/components/inputs/Input/NumberRangeInput/NumberRangeInput.tsx
18
+ var EMPTY_RANGE = {
19
+ min: null,
20
+ max: null
21
+ };
22
+ var normalizeRangeValue = (value, minValue, maxValue) => {
23
+ if (value) return value;
24
+ return {
25
+ min: minValue ?? null,
26
+ max: maxValue ?? null
27
+ };
28
+ };
29
+ var NumberRangeField = ({ label, value, placeholder, isDisabled, isInvalid, isRequired, formatOptions, hideInnerLabels, autoFocusOnMount, className, onChange, onBlur, ...rest }) => {
30
+ const ui = UIConfig.useConfig();
31
+ const { locale } = useLocale();
32
+ const { isFocusVisible } = useFocusVisible();
33
+ const inputRef = useRef(null);
34
+ const numberFieldRef = useRef(null);
35
+ useEffect(() => {
36
+ if (!autoFocusOnMount || isDisabled) return;
37
+ requestAnimationFrame(() => inputRef.current?.focus());
38
+ }, [autoFocusOnMount, isDisabled]);
39
+ const numberProps = {
40
+ ...rest,
41
+ label,
42
+ value: value ?? void 0,
43
+ placeholder,
44
+ isDisabled,
45
+ isInvalid,
46
+ isRequired,
47
+ onChange,
48
+ onBlur: (e) => onBlur?.({ target: e.target }),
49
+ locale,
50
+ formatOptions: formatOptions ?? ui.numberInput.formatOptions
51
+ };
52
+ const { labelProps, inputProps } = useNumberField(numberProps, useNumberFieldState(numberProps), numberFieldRef);
53
+ return /* @__PURE__ */ jsxs("div", {
54
+ className: "min-w-0 flex-1",
55
+ children: [/* @__PURE__ */ jsx(FormFieldLabel, {
56
+ label,
57
+ labelProps,
58
+ isRequired,
59
+ isDisabled,
60
+ className: clsx(hideInnerLabels && "sr-only")
61
+ }), /* @__PURE__ */ jsx(Input, {
62
+ ...inputProps,
63
+ ref: mergeRefs(inputRef, numberFieldRef),
64
+ placeholder: inputProps.placeholder,
65
+ className: clsx("w-full bg-transparent outline-none", className),
66
+ onFocus: (e) => {
67
+ inputProps.onFocus?.(e);
68
+ if (isFocusVisible) e.target.select();
69
+ }
70
+ })]
71
+ });
72
+ };
73
+ var NumberRangeInputBase = (props) => {
74
+ const ui = UIConfig.useConfig();
75
+ const inputBaseCva = UIStyle.useCva("input.baseCva", inputBase);
76
+ const inputSizeCva = UIStyle.useCva("input.sizeCva", inputSize);
77
+ const { ref, label, tooltipText, helperText, isRequired, rightContent, isDisabled, headerClassName, errorClassName, isHeaderHidden, error, className, inputClassName, minInputClassName, maxInputClassName, value, minValue, maxValue, minPlaceholder = "Min", maxPlaceholder = "Max", minLabel = "Minimum", maxLabel = "Maximum", invalidRangeError = "Minimum cannot be greater than maximum", hideInnerLabels = true, isDirty, autoFocusOnMount, onChange, onMinChange, onMaxChange, onBlur, isClearable: isClearableProps, as: asProp, variant: variantProps, size: sizeProps, hideLabel: hideLabelProps, ...rest } = props;
78
+ const isClearable = isClearableProps ?? ui.input.isClearable;
79
+ const as = asProp ?? ui.input.as;
80
+ const variant = variantProps ?? ui.input.variant;
81
+ const size = sizeProps ?? ui.input.size;
82
+ const hideLabel = hideLabelProps ?? ui.input.hideLabel;
83
+ const rangeValue = normalizeRangeValue(value, minValue, maxValue);
84
+ const isEmpty = rangeValue.min === null && rangeValue.max === null;
85
+ const rangeError = rangeValue.min !== null && rangeValue.max !== null && rangeValue.min > rangeValue.max ? invalidRangeError : void 0;
86
+ const effectiveError = error || rangeError;
87
+ const { hoverProps, isHovered } = useHover({ isDisabled });
88
+ const { isFocusVisible } = useFocusVisible();
89
+ const [isFocused, setIsFocused] = useState(false);
90
+ const { focusWithinProps } = useFocusWithin({ onFocusWithinChange: setIsFocused });
91
+ const formFieldProps = {
92
+ error: effectiveError,
93
+ label,
94
+ tooltipText,
95
+ helperText,
96
+ isRequired,
97
+ rightContent,
98
+ isHeaderHidden: isHeaderHidden || as === "inline" || as === "filter" || as === "floating",
99
+ hideLabel,
100
+ isDisabled,
101
+ headerClassName,
102
+ errorClassName
103
+ };
104
+ const headerProps = {
105
+ label,
106
+ tooltipText,
107
+ helperText,
108
+ isRequired,
109
+ rightContent,
110
+ isHeaderHidden: hideLabel || isHeaderHidden,
111
+ isDisabled,
112
+ className: headerClassName
113
+ };
114
+ const updateRange = (side, nextValue) => {
115
+ const nextRange = {
116
+ ...rangeValue,
117
+ [side]: nextValue
118
+ };
119
+ onChange?.(nextRange);
120
+ if (side === "min") onMinChange?.(nextValue);
121
+ else onMaxChange?.(nextValue);
122
+ };
123
+ const onClear = () => {
124
+ const nextRange = { ...EMPTY_RANGE };
125
+ onChange?.(nextRange);
126
+ onMinChange?.(null);
127
+ onMaxChange?.(null);
128
+ onBlur?.({ target: { value: "" } });
129
+ };
130
+ return /* @__PURE__ */ jsx(TooltipWrapper, {
131
+ as,
132
+ error: effectiveError,
133
+ triggerTabIndex: as === "inline" ? -1 : void 0,
134
+ children: /* @__PURE__ */ jsx(FormField, {
135
+ ...formFieldProps,
136
+ ref,
137
+ as,
138
+ className: clsx("group w-full", className),
139
+ tabIndex: as === "inline" ? -1 : void 0,
140
+ children: /* @__PURE__ */ jsxs("div", {
141
+ className: clsx(inputBaseCva({
142
+ variant,
143
+ as
144
+ }), "group/date-picker-content relative flex min-w-input-width-min-width items-center justify-between gap-2", inputClassName),
145
+ "data-rac": "",
146
+ "data-hovered": isHovered || void 0,
147
+ "data-disabled": isDisabled || void 0,
148
+ "data-invalid": !!effectiveError || void 0,
149
+ "data-is-empty": isEmpty || void 0,
150
+ "data-focus-within": isFocused || void 0,
151
+ "data-focus-visible": isFocused && isFocusVisible || void 0,
152
+ "data-has-selection": !isEmpty || void 0,
153
+ "data-is-dirty": isDirty || void 0,
154
+ "data-is-required": isRequired || void 0,
155
+ "data-is-filled": !isEmpty || void 0,
156
+ ...focusWithinProps,
157
+ ...hoverProps,
158
+ children: [/* @__PURE__ */ jsxs("div", {
159
+ className: clsx("flex w-full items-center gap-input-gap-input-text-to-elements pr-0!", inputSizeCva({
160
+ size,
161
+ as
162
+ })),
163
+ children: [
164
+ as && ["filter", "floating"].includes(as) && headerProps && /* @__PURE__ */ jsx(FormFieldLabel, {
165
+ as,
166
+ ...headerProps
167
+ }),
168
+ /* @__PURE__ */ jsx(NumberRangeField, {
169
+ ...rest,
170
+ label: minLabel,
171
+ placeholder: minPlaceholder,
172
+ value: rangeValue.min,
173
+ onChange: (nextValue) => {
174
+ updateRange("min", nextValue);
175
+ },
176
+ onBlur,
177
+ isDisabled,
178
+ isInvalid: !!effectiveError,
179
+ isRequired,
180
+ hideInnerLabels,
181
+ autoFocusOnMount,
182
+ className: minInputClassName
183
+ }),
184
+ /* @__PURE__ */ jsx("span", {
185
+ className: clsx("pointer-events-none shrink-0 select-none text-label-2 text-text-default-3", isDisabled && "text-interactive-text-secondary-disabled"),
186
+ children: "-"
187
+ }),
188
+ /* @__PURE__ */ jsx(NumberRangeField, {
189
+ ...rest,
190
+ label: maxLabel,
191
+ placeholder: maxPlaceholder,
192
+ value: rangeValue.max,
193
+ onChange: (nextValue) => {
194
+ updateRange("max", nextValue);
195
+ },
196
+ onBlur,
197
+ isDisabled,
198
+ isInvalid: !!effectiveError,
199
+ isRequired,
200
+ hideInnerLabels,
201
+ className: maxInputClassName
202
+ })
203
+ ]
204
+ }), /* @__PURE__ */ jsx("div", {
205
+ className: clsx("flex items-center gap-input-gap-trailing-elements py-0! pl-0!", inputSizeCva({
206
+ size,
207
+ as
208
+ })),
209
+ children: isClearable && /* @__PURE__ */ jsx(InputClear, {
210
+ onClear,
211
+ show: !isEmpty && !isDisabled
212
+ })
213
+ })]
214
+ })
215
+ })
216
+ });
217
+ };
218
+ var NumberRangeInput = ({ renderStaticInput, ...props }) => {
219
+ const ui = UIConfig.useConfig();
220
+ const { locale } = useLocale();
221
+ const [renderInput, setRenderInput] = useState(!(renderStaticInput ?? ui.renderStaticInput));
222
+ const [shouldFocus, setShouldFocus] = useState(false);
223
+ const watchedValue = "formControl" in props && props.formControl ? useWatch({
224
+ control: props.formControl.control,
225
+ name: props.formControl.name
226
+ }) : props.value;
227
+ let isFormControlDisabled = false;
228
+ if ("formControl" in props && props.formControl) isFormControlDisabled = !!props.formControl.control._options?.disabled;
229
+ useEffect(() => {
230
+ if (!renderInput || !shouldFocus) return;
231
+ setShouldFocus(false);
232
+ }, [renderInput, shouldFocus]);
233
+ if (!renderInput) {
234
+ const staticValue = normalizeRangeValue(watchedValue, props.minValue, props.maxValue);
235
+ const formatOptions = props.formatOptions ?? ui.numberInput.formatOptions;
236
+ const formatter = new Intl.NumberFormat(locale, formatOptions);
237
+ const minDisplay = staticValue.min == null ? null : formatter.format(staticValue.min);
238
+ const maxDisplay = staticValue.max == null ? null : formatter.format(staticValue.max);
239
+ const hasValue = minDisplay !== "" || maxDisplay !== "";
240
+ const displayValue = /* @__PURE__ */ jsxs(Fragment, { children: [
241
+ /* @__PURE__ */ jsx("span", {
242
+ className: clsx("w-full bg-transparent outline-none", minDisplay ? props.minInputClassName : "text-text-default-3"),
243
+ children: minDisplay ?? props.minPlaceholder
244
+ }),
245
+ /* @__PURE__ */ jsx("span", {
246
+ className: "pointer-events-none shrink-0 select-none text-label-2 text-text-default-3",
247
+ children: "-"
248
+ }),
249
+ /* @__PURE__ */ jsx("span", {
250
+ className: clsx("w-full bg-transparent outline-none", maxDisplay ? props.maxInputClassName : "text-text-default-3"),
251
+ children: maxDisplay ?? props.maxPlaceholder
252
+ })
253
+ ] });
254
+ const rangeError = staticValue.min !== null && staticValue.max !== null && staticValue.min > staticValue.max ? props.invalidRangeError ?? "Minimum cannot be greater than maximum" : void 0;
255
+ const effectiveError = props.error || rangeError;
256
+ const as = props.as ?? ui.input.as;
257
+ const size = props.size ?? ui.input.size;
258
+ const variant = props.variant ?? ui.input.variant;
259
+ const hideLabel = props.hideLabel ?? ui.input.hideLabel;
260
+ const isClearable = props.isClearable ?? ui.input.isClearable;
261
+ const isHeaderHidden = props.isHeaderHidden || as === "inline" || as === "filter" || as === "floating";
262
+ let isDisabled = !!props.isDisabled;
263
+ if (isFormControlDisabled) isDisabled = true;
264
+ return /* @__PURE__ */ jsx(StaticInput, {
265
+ ...props,
266
+ error: effectiveError,
267
+ onInteract: (focus) => {
268
+ setShouldFocus(focus);
269
+ setRenderInput(true);
270
+ },
271
+ as,
272
+ size,
273
+ variant,
274
+ hideLabel,
275
+ isHeaderHidden,
276
+ isDisabled,
277
+ className: clsx("group w-full", as === "inline" && "h-full", props.className),
278
+ inputClassName: props.inputClassName,
279
+ displayValue,
280
+ isEmpty: !hasValue,
281
+ hasClearIcon: !props.isDisabled && isClearable,
282
+ dataAttributes: {
283
+ dataIsEmpty: !hasValue,
284
+ dataIsFilled: hasValue,
285
+ dataIsDirty: props.isDirty,
286
+ dataIsRequired: props.isRequired,
287
+ dataIsDisabled: isDisabled,
288
+ dataDisabled: isDisabled,
289
+ dataInvalid: !!effectiveError,
290
+ dataHasSelection: hasValue
291
+ }
292
+ });
293
+ }
294
+ if ("formControl" in props && props.formControl) {
295
+ const { formControl, ref, ...innerProps } = props;
296
+ return /* @__PURE__ */ jsx(Controller, {
297
+ control: formControl.control,
298
+ name: formControl.name,
299
+ render: ({ field, fieldState: { error } }) => /* @__PURE__ */ jsx(NumberRangeInputBase, {
300
+ ...innerProps,
301
+ ref,
302
+ value: field.value ?? EMPTY_RANGE,
303
+ onChange: field.onChange,
304
+ onBlur: field.onBlur,
305
+ isDisabled: field.disabled || props.isDisabled,
306
+ error: props.error ?? error?.message,
307
+ autoFocusOnMount: shouldFocus
308
+ })
309
+ });
310
+ }
311
+ return /* @__PURE__ */ jsx(NumberRangeInputBase, {
312
+ ...props,
313
+ autoFocusOnMount: shouldFocus
314
+ });
315
+ };
316
+ //#endregion
317
+ export { NumberRangeInput };
@@ -175,7 +175,7 @@ var TextInput = ({ renderStaticInput, ...props }) => {
175
175
  isDisabled,
176
176
  className: clsx("group w-full", as === "inline" && "h-full", props.className),
177
177
  inputClassName: props.inputClassName,
178
- placeholder: as === "floating" ? "" : props.placeholder,
178
+ placeholder: props.placeholder,
179
179
  displayValue,
180
180
  isEmpty: !hasValue,
181
181
  dataAttributes: {
@@ -8,6 +8,7 @@ declare const componentRegistry: {
8
8
  readonly toggle: <TFieldValues extends import('react-hook-form').FieldValues>(props: import('../Toggle/Toggle').ControlledToggleProps<TFieldValues>) => import("react/jsx-runtime").JSX.Element;
9
9
  readonly checkbox: <TFieldValues extends import('react-hook-form').FieldValues>(props: import('../Checkbox/Checkbox').ControlledCheckboxProps<TFieldValues>) => import("react/jsx-runtime").JSX.Element;
10
10
  readonly numberInput: <TFieldValues extends import('react-hook-form').FieldValues>({ renderStaticInput, ...props }: import('../Input/NumberInput/NumberInput').ControlledNumberInputProps<TFieldValues>) => import("react/jsx-runtime").JSX.Element;
11
+ readonly numberRangeInput: <TFieldValues extends import('react-hook-form').FieldValues>({ renderStaticInput, ...props }: import('../Input/NumberRangeInput/NumberRangeInput').ControlledNumberRangeInputProps<TFieldValues>) => import("react/jsx-runtime").JSX.Element;
11
12
  readonly slider: <TFieldValues extends import('react-hook-form').FieldValues, IsRange extends boolean = false>(props: import('../Slider/Slider').ControlledSliderProps<TFieldValues, IsRange>) => import("react/jsx-runtime").JSX.Element;
12
13
  readonly textInput: <TFieldValues extends import('react-hook-form').FieldValues>({ renderStaticInput, ...props }: import('../Input/TextInput/TextInput').ControlledTextInputProps<TFieldValues>) => import("react/jsx-runtime").JSX.Element;
13
14
  readonly passwordInput: <TFieldValues extends import('react-hook-form').FieldValues>(props: import('../Input/PasswordInput/PasswordInput').ControlledPasswordInputProps<TFieldValues>) => import("react/jsx-runtime").JSX.Element;
@@ -6,6 +6,7 @@ import { DateRangePicker } from "../DateTime/DateRangePicker/DateRangePicker.js"
6
6
  import { DateTimePicker } from "../DateTime/DateTimePicker/DateTimePicker.js";
7
7
  import { TimePicker } from "../DateTime/TimePicker/TimePicker.js";
8
8
  import { NumberInput } from "../Input/NumberInput/NumberInput.js";
9
+ import { NumberRangeInput } from "../Input/NumberRangeInput/NumberRangeInput.js";
9
10
  import { PasswordInput } from "../Input/PasswordInput/PasswordInput.js";
10
11
  import { TextArea } from "../Input/TextArea/TextArea.js";
11
12
  import { Autocomplete } from "../Selection/Autocomplete/Autocomplete.js";
@@ -21,6 +22,7 @@ var componentRegistry = {
21
22
  toggle: Toggle,
22
23
  checkbox: Checkbox,
23
24
  numberInput: NumberInput,
25
+ numberRangeInput: NumberRangeInput,
24
26
  slider: Slider,
25
27
  textInput: TextInput,
26
28
  passwordInput: PasswordInput,
@@ -84,7 +84,8 @@ function Autocomplete({ renderStaticInput, ...props }) {
84
84
  isDisabled,
85
85
  className: clsx("w-full", props.containerClassName),
86
86
  inputClassName: clsx(props.className, props.inputClassName),
87
- placeholder: as === "floating" || mode === "single" && !isEmpty ? "" : props.placeholder,
87
+ placeholder: props.placeholder,
88
+ showPlacholderIfFilled: mode !== "single",
88
89
  displayValue,
89
90
  isEmpty,
90
91
  dataAttributes: {
@@ -53,6 +53,7 @@ function Select({ renderStaticInput, ...props }) {
53
53
  const as = props.as ?? ui.input.as;
54
54
  let isDisabled = !!props.isDisabled;
55
55
  if (isFormControlDisabled) isDisabled = true;
56
+ const isClearable = props.isClearable ?? ui.input.isClearable;
56
57
  const mode = props.selectionMode ?? ui.select.selectionMode;
57
58
  const { displayValue, isEmpty } = getStaticSelectValue({
58
59
  items: props.items,
@@ -73,6 +74,7 @@ function Select({ renderStaticInput, ...props }) {
73
74
  setRenderInput(true);
74
75
  },
75
76
  as,
77
+ typographySize: "label-1",
76
78
  size: props.size ?? ui.input.size,
77
79
  variant: props.variant ?? ui.input.variant,
78
80
  isHeaderHidden: props.isHeaderHidden || as === "inline" || as === "filter" || as === "floating",
@@ -80,7 +82,8 @@ function Select({ renderStaticInput, ...props }) {
80
82
  isDisabled,
81
83
  className: clsx("w-full", props.containerClassName),
82
84
  inputClassName: clsx(props.className, props.inputClassName),
83
- placeholder: as === "floating" || mode === "single" && !isEmpty ? "" : props.placeholder,
85
+ placeholder: props.placeholder,
86
+ showPlacholderIfFilled: mode !== "single",
84
87
  displayValue,
85
88
  isEmpty,
86
89
  dataAttributes: {
@@ -95,6 +98,7 @@ function Select({ renderStaticInput, ...props }) {
95
98
  dataHasSearch: false
96
99
  },
97
100
  leadingContent: props.leadingContent,
101
+ hasClearIcon: isClearable,
98
102
  trailingContent
99
103
  });
100
104
  }
@@ -27,7 +27,10 @@ var getStaticSelectValue = ({ items, value, selectionMode, initialSelection, map
27
27
  return {
28
28
  selectedItem,
29
29
  selectedItems,
30
- displayValue: selectedItem != null ? showSelectionContent && selectedItem.content ? selectedItem.content : selectedItem.label : "",
30
+ displayValue: selectedItem != null ? showSelectionContent && selectedItem.content ? selectedItem.content : /* @__PURE__ */ jsx("div", {
31
+ className: "min-w-0 flex-1 truncate",
32
+ children: selectedItem.label
33
+ }) : "",
31
34
  isEmpty: selectedItem == null
32
35
  };
33
36
  };
@@ -2,6 +2,7 @@ import { ReactNode } from 'react';
2
2
  import { FormFieldProps } from '../FormField/FormField';
3
3
  import { TextInputProps } from '../Input/TextInput/TextInput';
4
4
  import { InputSizeProps, InputVariantProps } from './input.cva';
5
+ import { TypographyVariantProps } from '../../text/Typography/typography.cva';
5
6
  type StaticInputDataAttributes = {
6
7
  dataDisabled?: boolean;
7
8
  dataHasSearch?: boolean;
@@ -16,19 +17,22 @@ type StaticInputDataAttributes = {
16
17
  interface StaticInputProps extends FormFieldProps {
17
18
  onInteract: (shouldFocus: boolean) => void;
18
19
  as?: TextInputProps["as"];
20
+ typographySize?: TypographyVariantProps["size"];
19
21
  size?: InputSizeProps["size"];
20
22
  variant?: InputVariantProps["variant"];
21
23
  applyMinInputWidth?: boolean;
22
24
  placeholder?: ReactNode;
25
+ showPlacholderIfFilled?: boolean;
23
26
  displayValue?: ReactNode;
24
27
  isEmpty?: boolean;
25
28
  leadingVisual?: ReactNode;
26
29
  leadingContent?: ReactNode;
27
30
  leadingContentClassName?: string;
31
+ hasClearIcon?: boolean;
28
32
  trailingContent?: ReactNode;
29
33
  contentRowClassName?: string;
30
34
  inputClassName?: string;
31
35
  dataAttributes?: StaticInputDataAttributes;
32
36
  }
33
- export declare const StaticInput: ({ onInteract, as, size, variant, applyMinInputWidth, placeholder, displayValue, isEmpty, leadingVisual, leadingContent, leadingContentClassName, trailingContent, contentRowClassName, inputClassName, dataAttributes, className, ...formFieldProps }: StaticInputProps) => import("react/jsx-runtime").JSX.Element;
37
+ export declare const StaticInput: ({ onInteract, as, typographySize, size, variant, applyMinInputWidth, placeholder, showPlacholderIfFilled, displayValue, isEmpty, leadingVisual, leadingContent, leadingContentClassName, hasClearIcon, trailingContent, contentRowClassName, inputClassName, dataAttributes, className, ...formFieldProps }: StaticInputProps) => import("react/jsx-runtime").JSX.Element;
34
38
  export {};
@@ -1,18 +1,21 @@
1
1
  import { UIStyle } from "../../../config/uiStyle.context.js";
2
+ import { typography } from "../../text/Typography/typography.cva.js";
2
3
  import { FormFieldLabel } from "../FormField/FormFieldLabel.js";
3
4
  import { inputBase, inputSize } from "./input.cva.js";
4
5
  import { FormField } from "../FormField/FormField.js";
5
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
7
  import { clsx } from "clsx";
7
8
  //#region src/components/inputs/shared/StaticInput.tsx
8
- var StaticInput = ({ onInteract, as, size, variant, applyMinInputWidth, placeholder, displayValue, isEmpty, leadingVisual, leadingContent, leadingContentClassName, trailingContent, contentRowClassName, inputClassName, dataAttributes, className, ...formFieldProps }) => {
9
+ var StaticInput = ({ onInteract, as, typographySize, size, variant, applyMinInputWidth, placeholder, showPlacholderIfFilled = false, displayValue, isEmpty, leadingVisual, leadingContent, leadingContentClassName, hasClearIcon, trailingContent, contentRowClassName, inputClassName, dataAttributes, className, ...formFieldProps }) => {
9
10
  const inputBaseCva = UIStyle.useCva("input.baseCva", inputBase);
10
11
  const inputSizeCva = UIStyle.useCva("input.sizeCva", inputSize);
12
+ const typographyCva = UIStyle.useCva("typography.cva", typography);
11
13
  let hasValue = !!displayValue;
12
14
  if (isEmpty != null) hasValue = !isEmpty;
13
15
  let staticDisplayContent = placeholder;
14
16
  if (hasValue) staticDisplayContent = displayValue;
15
17
  else if (as === "floating") staticDisplayContent = null;
18
+ const shouldRenderPlaceholderAfterValue = showPlacholderIfFilled && placeholder && hasValue;
16
19
  const shouldRenderFloatingLineSpacer = as === "floating" && !hasValue;
17
20
  const inputDataAttributes = {
18
21
  dataIsEmpty: !hasValue,
@@ -45,42 +48,55 @@ var StaticInput = ({ onInteract, as, size, variant, applyMinInputWidth, placehol
45
48
  className: clsx("group/static-input group/input-content group/select-content relative flex items-center gap-input-gap-input-text-to-elements", applyMinInputWidth && "min-w-input-width-min-width", inputBaseCva({
46
49
  as,
47
50
  variant
48
- }), !hasValue && "text-text-default-3", inputClassName),
49
- children: [/* @__PURE__ */ jsxs("div", {
50
- className: clsx("group/input-content flex w-full items-center gap-input-gap-input-text-to-elements pr-0!", inputSizeCva({
51
- size,
52
- as
53
- }), contentRowClassName),
54
- children: [
55
- leadingVisual && /* @__PURE__ */ jsx("div", {
56
- className: "pointer-events-none shrink-0",
57
- children: leadingVisual
58
- }),
59
- as && ["filter", "floating"].includes(as) && /* @__PURE__ */ jsx(FormFieldLabel, {
60
- as,
51
+ }), inputClassName),
52
+ children: [
53
+ /* @__PURE__ */ jsxs("div", {
54
+ className: clsx("group/input-content flex min-w-0 w-full items-center gap-input-gap-input-text-to-elements pr-0!", inputSizeCva({
61
55
  size,
62
- label: formFieldProps.label,
63
- isRequired: formFieldProps.isRequired,
64
- isDisabled: formFieldProps.isDisabled
65
- }),
66
- leadingContent && /* @__PURE__ */ jsx("div", {
67
- className: clsx("ml-input-side-default flex shrink-0 items-center", leadingContentClassName),
68
- children: leadingContent
69
- }),
70
- staticDisplayContent,
71
- shouldRenderFloatingLineSpacer && /* @__PURE__ */ jsx(Fragment, { children: "\xA0" }),
72
- placeholder && hasValue && /* @__PURE__ */ jsx("div", {
73
- className: "text-text-default-3",
74
- children: placeholder
75
- })
76
- ]
77
- }), trailingContent && /* @__PURE__ */ jsx("div", {
78
- className: clsx(inputSizeCva({
79
- size,
80
- as
81
- }), "pointer-events-none flex items-center gap-input-gap-trailing-elements py-0! pl-0!"),
82
- children: trailingContent
83
- })]
56
+ as
57
+ }), typographySize && typographyCva({ size: typographySize }), contentRowClassName),
58
+ children: [
59
+ leadingVisual && /* @__PURE__ */ jsx("div", {
60
+ className: "pointer-events-none shrink-0",
61
+ children: leadingVisual
62
+ }),
63
+ as && ["filter", "floating"].includes(as) && /* @__PURE__ */ jsx(FormFieldLabel, {
64
+ as,
65
+ size,
66
+ label: formFieldProps.label,
67
+ isRequired: formFieldProps.isRequired,
68
+ isDisabled: formFieldProps.isDisabled
69
+ }),
70
+ leadingContent && /* @__PURE__ */ jsx("div", {
71
+ className: clsx("ml-input-side-default flex shrink-0 items-center", leadingContentClassName),
72
+ children: leadingContent
73
+ }),
74
+ !hasValue ? /* @__PURE__ */ jsx("div", {
75
+ className: "text-text-default-3",
76
+ children: staticDisplayContent
77
+ }) : staticDisplayContent,
78
+ shouldRenderFloatingLineSpacer && /* @__PURE__ */ jsx(Fragment, { children: "\xA0" }),
79
+ shouldRenderPlaceholderAfterValue && /* @__PURE__ */ jsx("div", {
80
+ className: "shrink-0 text-text-default-3",
81
+ children: placeholder
82
+ })
83
+ ]
84
+ }),
85
+ hasClearIcon && /* @__PURE__ */ jsx("div", {
86
+ className: clsx("flex items-center gap-input-gap-trailing-elements py-0! pl-0!", inputSizeCva({
87
+ size,
88
+ as
89
+ })),
90
+ children: /* @__PURE__ */ jsx("div", { className: "size-6 shrink-0" })
91
+ }),
92
+ trailingContent && /* @__PURE__ */ jsx("div", {
93
+ className: clsx(inputSizeCva({
94
+ size,
95
+ as
96
+ }), "pointer-events-none flex items-center gap-input-gap-trailing-elements py-0! pl-0!"),
97
+ children: trailingContent
98
+ })
99
+ ]
84
100
  })
85
101
  });
86
102
  };
package/dist/index.d.ts CHANGED
@@ -78,6 +78,8 @@ export type { FormFieldProps } from './components/inputs/FormField/FormField';
78
78
  export { FormField } from './components/inputs/FormField/FormField';
79
79
  export type { ControlledNumberInputProps, NumberInputProps } from './components/inputs/Input/NumberInput/NumberInput';
80
80
  export { NumberInput } from './components/inputs/Input/NumberInput/NumberInput';
81
+ export type { ControlledNumberRangeInputProps, NumberRangeInputProps, NumberRangeValue, } from './components/inputs/Input/NumberRangeInput/NumberRangeInput';
82
+ export { NumberRangeInput } from './components/inputs/Input/NumberRangeInput/NumberRangeInput';
81
83
  export type { ControlledPasswordInputProps, PasswordInputProps, } from './components/inputs/Input/PasswordInput/PasswordInput';
82
84
  export { PasswordInput } from './components/inputs/Input/PasswordInput/PasswordInput';
83
85
  export type { ControlledTextAreaProps, TextAreaProps } from './components/inputs/Input/TextArea/TextArea';
package/dist/index.js CHANGED
@@ -85,6 +85,7 @@ import { FileUpload } from "./components/inputs/File/FileUpload.js";
85
85
  import { FileUploadContainer } from "./components/inputs/File/FileUploadContainer.js";
86
86
  import { InputUpload } from "./components/inputs/File/InputUpload.js";
87
87
  import { NumberInput } from "./components/inputs/Input/NumberInput/NumberInput.js";
88
+ import { NumberRangeInput } from "./components/inputs/Input/NumberRangeInput/NumberRangeInput.js";
88
89
  import { PasswordInput } from "./components/inputs/Input/PasswordInput/PasswordInput.js";
89
90
  import { TextArea } from "./components/inputs/Input/TextArea/TextArea.js";
90
91
  import { Autocomplete } from "./components/inputs/Selection/Autocomplete/Autocomplete.js";
@@ -136,4 +137,4 @@ import { useTableColumnConfig } from "./hooks/useTableColumnConfig.js";
136
137
  import { ArrayUtils } from "./utils/array.utils.js";
137
138
  import { QueriesUtils } from "./utils/queries.utils.js";
138
139
  import { RoutingUtils } from "./utils/routing.utils.js";
139
- export { Accordion, ActionModal, Alert, AlignCenterIcon, AlignLeftIcon, AlignLeftRightIcon, AlignRightIcon, ArrayUtils, ArrowDropDownIcon, ArrowDropUpIcon, ArrowLeftIcon, ArrowRightIcon, Autocomplete, BoldIcon, BottomSheet, Breadcrumbs, BulletedListIcon, Button, CalendarIcon, CellText, CheckIcon, Checkbox, CheckboxCheckmarkIcon, CheckboxIndeterminateIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronsLeftIcon, ChevronsRightIcon, ClockIcon, CloseIcon, ColumnConfigModal, Confirmation, DatePicker, DateRangePicker, DateTimeIcon, DateTimePicker, DateTimeUtils, DateUtils, DomUtils, Drawer, FileUpload, FileUploadContainer, FileUtils, Form, FormField, HeaderText, HighlightIcon, HighlightOnIcon, HomeIcon, IconButton, InfiniteTable, InfoIcon, InlineIconButton, InputUpload, Inputs, ItalicIcon, Link, LinkContext, LinkIcon, Loader, Menu, MenuIcon, MenuItem, MenuPopover, Modal, NumberInput, NumberedListIcon, ObjectUtils, PaginatedTable, Pagination, PaginationList, PasswordInput, PillButton, PointerHorizontalIcon, PointerVerticalIcon, ProgressBar, QueriesUtils, QueryAutocomplete, QuerySelect, RadioGroup, ResponsivePopover, RestUtils, RoutingUtils, Segment, Select, SendIcon, Slider, SplitButton, Stepper, StrikethroughIcon, StringUtils, Table, Tag, TextArea, TextButton, TextColorIcon, TextInput, ThemeContext, TimePicker, Toast, ToastContainer, Toggle, ToggleButton, Tooltip, TooltipEllipsis, Typography, UIConfig, UIRouter, UIStyle, UnderlinedIcon, VisibilityIcon, VisibilityOffIcon, compoundMapper, dynamicColumns, dynamicInputs, isEqual, logger, ns, resources, uiOutlineClass, useAutosave, useBreakpoint, useDebounceCallback, useDeepCompareEffect, useDeepCompareLayoutEffect, useDeepCompareMemo, useFilters, useForm, useFormAutosave, useIntersectionObserver, useLocalStorage, useLongPressRepeat, usePagination, useScrollableListBox, useSorting, useStateAndRef, useTableColumnConfig, useTableNav, useToast, useTranslationMemo };
140
+ export { Accordion, ActionModal, Alert, AlignCenterIcon, AlignLeftIcon, AlignLeftRightIcon, AlignRightIcon, ArrayUtils, ArrowDropDownIcon, ArrowDropUpIcon, ArrowLeftIcon, ArrowRightIcon, Autocomplete, BoldIcon, BottomSheet, Breadcrumbs, BulletedListIcon, Button, CalendarIcon, CellText, CheckIcon, Checkbox, CheckboxCheckmarkIcon, CheckboxIndeterminateIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ChevronsLeftIcon, ChevronsRightIcon, ClockIcon, CloseIcon, ColumnConfigModal, Confirmation, DatePicker, DateRangePicker, DateTimeIcon, DateTimePicker, DateTimeUtils, DateUtils, DomUtils, Drawer, FileUpload, FileUploadContainer, FileUtils, Form, FormField, HeaderText, HighlightIcon, HighlightOnIcon, HomeIcon, IconButton, InfiniteTable, InfoIcon, InlineIconButton, InputUpload, Inputs, ItalicIcon, Link, LinkContext, LinkIcon, Loader, Menu, MenuIcon, MenuItem, MenuPopover, Modal, NumberInput, NumberRangeInput, NumberedListIcon, ObjectUtils, PaginatedTable, Pagination, PaginationList, PasswordInput, PillButton, PointerHorizontalIcon, PointerVerticalIcon, ProgressBar, QueriesUtils, QueryAutocomplete, QuerySelect, RadioGroup, ResponsivePopover, RestUtils, RoutingUtils, Segment, Select, SendIcon, Slider, SplitButton, Stepper, StrikethroughIcon, StringUtils, Table, Tag, TextArea, TextButton, TextColorIcon, TextInput, ThemeContext, TimePicker, Toast, ToastContainer, Toggle, ToggleButton, Tooltip, TooltipEllipsis, Typography, UIConfig, UIRouter, UIStyle, UnderlinedIcon, VisibilityIcon, VisibilityOffIcon, compoundMapper, dynamicColumns, dynamicInputs, isEqual, logger, ns, resources, uiOutlineClass, useAutosave, useBreakpoint, useDebounceCallback, useDeepCompareEffect, useDeepCompareLayoutEffect, useDeepCompareMemo, useFilters, useForm, useFormAutosave, useIntersectionObserver, useLocalStorage, useLongPressRepeat, usePagination, useScrollableListBox, useSorting, useStateAndRef, useTableColumnConfig, useTableNav, useToast, useTranslationMemo };
@@ -1,24 +1,28 @@
1
1
  import { CalendarDate, CalendarDateTime, DateValue, ZonedDateTime } from '@internationalized/date';
2
2
  export declare namespace DateTimeUtils {
3
- function getDatePlaceholder(locale?: string): string;
4
- function getTimePlaceholder(locale?: string): string;
5
- function getDateTimePlaceholder(locale?: string): string;
6
- function getDateRangePlaceholder(locale?: string): string;
7
- function formatCalendarDateLocalized(calendarDate: CalendarDate, locale?: string): string;
8
- function formatTimeLocalized(timeValue: {
3
+ interface LocalizedDateFormatOptions {
4
+ shouldForceLeadingZeros?: boolean;
5
+ }
6
+ export function getDatePlaceholder(locale?: string, options?: LocalizedDateFormatOptions): string;
7
+ export function getTimePlaceholder(locale?: string): string;
8
+ export function getDateTimePlaceholder(locale?: string, options?: LocalizedDateFormatOptions): string;
9
+ export function getDateRangePlaceholder(locale?: string, options?: LocalizedDateFormatOptions): string;
10
+ export function formatCalendarDateLocalized(calendarDate: CalendarDate, locale?: string, options?: LocalizedDateFormatOptions): string;
11
+ export function formatTimeLocalized(timeValue: {
9
12
  hour: number;
10
13
  minute: number;
11
14
  }, locale?: string): string;
12
- function formatCalendarDateTimeLocalized(calendarDateTime: Pick<CalendarDateTime, "day" | "month" | "year" | "hour" | "minute">, locale?: string): string;
13
- function fromISOtoZonedDateTime(isoString: string): ZonedDateTime;
14
- function fromDateValueToISO(dateValue: DateValue): string;
15
- function fromLocalToZonedDateTime(date: Date): ZonedDateTime;
16
- function fromDateValueToLocal(dateValue: DateValue): Date;
17
- function fromCalendarDateToUTCISO(calendarDate: CalendarDate, options?: {
15
+ export function formatCalendarDateTimeLocalized(calendarDateTime: Pick<CalendarDateTime, "day" | "month" | "year" | "hour" | "minute">, locale?: string, options?: LocalizedDateFormatOptions): string;
16
+ export function fromISOtoZonedDateTime(isoString: string): ZonedDateTime;
17
+ export function fromDateValueToISO(dateValue: DateValue): string;
18
+ export function fromLocalToZonedDateTime(date: Date): ZonedDateTime;
19
+ export function fromDateValueToLocal(dateValue: DateValue): Date;
20
+ export function fromCalendarDateToUTCISO(calendarDate: CalendarDate, options?: {
18
21
  endOfDay?: boolean;
19
22
  }): string;
20
- function fromUTCISOToCalendarDate(isoString: string): CalendarDate;
21
- function fromCalendarDateTimeToUTCISO(calendarDateTime: CalendarDateTime): string;
22
- function fromUTCISOToCalendarDateTime(isoString: string): CalendarDateTime;
23
- function formatTextDateToCalendarDateTime(textDate: string | null): CalendarDateTime | null;
23
+ export function fromUTCISOToCalendarDate(isoString: string): CalendarDate;
24
+ export function fromCalendarDateTimeToUTCISO(calendarDateTime: CalendarDateTime): string;
25
+ export function fromUTCISOToCalendarDateTime(isoString: string): CalendarDateTime;
26
+ export function formatTextDateToCalendarDateTime(textDate: string | null): CalendarDateTime | null;
27
+ export {};
24
28
  }
@@ -4,9 +4,10 @@ var DateTimeUtils;
4
4
  (function(_DateTimeUtils) {
5
5
  const DATE_SAMPLE_DATE_UTC = new Date(Date.UTC(2e3, 10, 22));
6
6
  const TIME_SAMPLE_DATE_UTC = new Date(Date.UTC(2e3, 10, 22, 13, 45));
7
- const getDatePlaceholderFormatter = (locale) => new Intl.DateTimeFormat(locale, {
8
- day: "2-digit",
9
- month: "2-digit",
7
+ const getDayMonthFormat = (shouldForceLeadingZeros = false) => shouldForceLeadingZeros ? "2-digit" : "numeric";
8
+ const getDatePlaceholderFormatter = (locale, options) => new Intl.DateTimeFormat(locale, {
9
+ day: getDayMonthFormat(options?.shouldForceLeadingZeros),
10
+ month: getDayMonthFormat(options?.shouldForceLeadingZeros),
10
11
  year: "numeric"
11
12
  });
12
13
  const getTimePlaceholderFormatter = (locale) => new Intl.DateTimeFormat(locale, {
@@ -18,9 +19,9 @@ var DateTimeUtils;
18
19
  if (locale) return locale;
19
20
  return new Intl.DateTimeFormat().resolvedOptions().locale;
20
21
  };
21
- const getDateFormatter = (locale) => new DateFormatter(getResolvedLocale(locale), {
22
- day: "2-digit",
23
- month: "2-digit",
22
+ const getDateFormatter = (locale, options) => new Intl.DateTimeFormat(getResolvedLocale(locale), {
23
+ day: getDayMonthFormat(options?.shouldForceLeadingZeros),
24
+ month: getDayMonthFormat(options?.shouldForceLeadingZeros),
24
25
  year: "numeric",
25
26
  timeZone: "UTC"
26
27
  });
@@ -30,9 +31,9 @@ var DateTimeUtils;
30
31
  hourCycle: "h23",
31
32
  timeZone: "UTC"
32
33
  });
33
- const getDateTimeFormatter = (locale) => new DateFormatter(getResolvedLocale(locale), {
34
- day: "2-digit",
35
- month: "2-digit",
34
+ const getDateTimeFormatter = (locale, options) => new Intl.DateTimeFormat(getResolvedLocale(locale), {
35
+ day: getDayMonthFormat(options?.shouldForceLeadingZeros),
36
+ month: getDayMonthFormat(options?.shouldForceLeadingZeros),
36
37
  year: "numeric",
37
38
  hour: "2-digit",
38
39
  minute: "2-digit",
@@ -57,25 +58,34 @@ var DateTimeUtils;
57
58
  const formatPlaceholder = (formatter, sampleDate) => {
58
59
  return formatter.formatToParts(sampleDate).map((part) => mapTypeToPlaceholder(part.type, formatter.resolvedOptions().locale) ?? part.value.replace(/\s+/gu, "")).join("");
59
60
  };
60
- function getDatePlaceholder(locale) {
61
- return formatPlaceholder(getDatePlaceholderFormatter(locale), DATE_SAMPLE_DATE_UTC);
61
+ const removeLeadingZero = (value) => value.replace(/^0+(?=\d)/u, "");
62
+ const removeDateSeparatorSpacing = (value) => value.replace(/([./-])\s+(?=\d)/gu, "$1");
63
+ const formatLocalizedDateParts = (formatter, date, options) => {
64
+ if (options?.shouldForceLeadingZeros !== false) return removeDateSeparatorSpacing(formatter.format(date));
65
+ return removeDateSeparatorSpacing(formatter.formatToParts(date).map((part) => {
66
+ if (part.type === "day" || part.type === "month") return removeLeadingZero(part.value);
67
+ return part.value;
68
+ }).join(""));
69
+ };
70
+ function getDatePlaceholder(locale, options) {
71
+ return formatPlaceholder(getDatePlaceholderFormatter(locale, options), DATE_SAMPLE_DATE_UTC);
62
72
  }
63
73
  _DateTimeUtils.getDatePlaceholder = getDatePlaceholder;
64
74
  function getTimePlaceholder(locale) {
65
75
  return formatPlaceholder(getTimePlaceholderFormatter(locale), TIME_SAMPLE_DATE_UTC);
66
76
  }
67
77
  _DateTimeUtils.getTimePlaceholder = getTimePlaceholder;
68
- function getDateTimePlaceholder(locale) {
69
- return `${getDatePlaceholder(locale)}, ${getTimePlaceholder(locale)}`;
78
+ function getDateTimePlaceholder(locale, options) {
79
+ return `${getDatePlaceholder(locale, options)}, ${getTimePlaceholder(locale)}`;
70
80
  }
71
81
  _DateTimeUtils.getDateTimePlaceholder = getDateTimePlaceholder;
72
- function getDateRangePlaceholder(locale) {
73
- const datePlaceholder = getDatePlaceholder(locale);
82
+ function getDateRangePlaceholder(locale, options) {
83
+ const datePlaceholder = getDatePlaceholder(locale, options);
74
84
  return `${datePlaceholder} – ${datePlaceholder}`;
75
85
  }
76
86
  _DateTimeUtils.getDateRangePlaceholder = getDateRangePlaceholder;
77
- function formatCalendarDateLocalized(calendarDate, locale) {
78
- return getDateFormatter(locale).format(calendarDate.toDate("UTC"));
87
+ function formatCalendarDateLocalized(calendarDate, locale, options) {
88
+ return formatLocalizedDateParts(getDateFormatter(locale, options), calendarDate.toDate("UTC"), options);
79
89
  }
80
90
  _DateTimeUtils.formatCalendarDateLocalized = formatCalendarDateLocalized;
81
91
  function formatTimeLocalized(timeValue, locale) {
@@ -83,9 +93,9 @@ var DateTimeUtils;
83
93
  return getTimeFormatter(locale).format(dateTime.toDate("UTC"));
84
94
  }
85
95
  _DateTimeUtils.formatTimeLocalized = formatTimeLocalized;
86
- function formatCalendarDateTimeLocalized(calendarDateTime, locale) {
96
+ function formatCalendarDateTimeLocalized(calendarDateTime, locale, options) {
87
97
  const normalizedValue = new CalendarDateTime(calendarDateTime.year, calendarDateTime.month, calendarDateTime.day, calendarDateTime.hour, calendarDateTime.minute);
88
- return getDateTimeFormatter(locale).format(normalizedValue.toDate("UTC"));
98
+ return formatLocalizedDateParts(getDateTimeFormatter(locale, options), normalizedValue.toDate("UTC"), options);
89
99
  }
90
100
  _DateTimeUtils.formatCalendarDateTimeLocalized = formatCalendarDateTimeLocalized;
91
101
  function fromISOtoZonedDateTime(isoString) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@povio/ui",
3
- "version": "2.2.9-rc.20",
3
+ "version": "2.2.9-rc.22",
4
4
  "type": "module",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",