@rufous/ui 0.2.78 → 0.2.81

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.
Files changed (4) hide show
  1. package/dist/main.cjs +1814 -1799
  2. package/dist/main.css +3 -8
  3. package/dist/main.js +1827 -1812
  4. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -1908,1049 +1908,682 @@ var TextField = (0, import_react17.forwardRef)(({
1908
1908
  TextField.displayName = "TextField";
1909
1909
 
1910
1910
  // lib/TextFields/AddressLookup.tsx
1911
- var import_react18 = __toESM(require("react"), 1);
1911
+ var import_react19 = __toESM(require("react"), 1);
1912
1912
  var import_axios = __toESM(require("axios"), 1);
1913
1913
  var import_country_state_city = require("country-state-city");
1914
- var AddressLookup = ({
1915
- value = {},
1916
- onChange = () => {
1917
- },
1918
- label = "Address",
1919
- error = {},
1920
- size = "medium",
1921
- sx = {},
1922
- layout = "stack",
1923
- required = false,
1924
- token = ""
1925
- }) => {
1926
- const { theme } = useRufousTheme();
1927
- const [suggestions, setSuggestions] = (0, import_react18.useState)([]);
1928
- const [loading, setLoading] = (0, import_react18.useState)(false);
1929
- const [showSuggestions, setShowSuggestions] = (0, import_react18.useState)(false);
1930
- const [googleFields, setGoogleFields] = (0, import_react18.useState)({
1931
- country: false,
1932
- state: false,
1933
- city: false,
1934
- pincode: false
1935
- });
1936
- const debounceTimeout = (0, import_react18.useRef)(null);
1914
+
1915
+ // lib/TextFields/Autocomplete.tsx
1916
+ var import_react18 = __toESM(require("react"), 1);
1917
+ var import_react_dom2 = __toESM(require("react-dom"), 1);
1918
+ var ChevronDownIcon = () => /* @__PURE__ */ import_react18.default.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react18.default.createElement("polyline", { points: "6 9 12 15 18 9" }));
1919
+ var CloseSmIcon = ({ size = 16 }) => /* @__PURE__ */ import_react18.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" }, /* @__PURE__ */ import_react18.default.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), /* @__PURE__ */ import_react18.default.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" }));
1920
+ var CheckIcon = () => /* @__PURE__ */ import_react18.default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react18.default.createElement("polyline", { points: "20 6 9 17 4 12" }));
1921
+ function defaultGetLabel(option) {
1922
+ if (option === null || option === void 0) return "";
1923
+ if (typeof option === "string") return option;
1924
+ if (typeof option === "object" && "label" in option)
1925
+ return String(option.label);
1926
+ return String(option);
1927
+ }
1928
+ function defaultFilter(options, inputValue, getLabel) {
1929
+ if (!inputValue) return options;
1930
+ const q = inputValue.toLowerCase();
1931
+ return options.filter((o) => getLabel(o).toLowerCase().includes(q));
1932
+ }
1933
+ function AutocompleteInner(props, _ref) {
1934
+ const {
1935
+ options,
1936
+ value,
1937
+ onChange,
1938
+ inputValue: controlledInput,
1939
+ onInputChange,
1940
+ getOptionLabel = defaultGetLabel,
1941
+ isOptionEqualToValue,
1942
+ groupBy,
1943
+ filterOptions,
1944
+ renderOption,
1945
+ getOptionDisabled,
1946
+ multiple = false,
1947
+ freeSolo = false,
1948
+ clearable = true,
1949
+ loading = false,
1950
+ loadingText = "Loading\u2026",
1951
+ noOptionsText = "No options",
1952
+ limitTags,
1953
+ label,
1954
+ placeholder,
1955
+ variant = "outlined",
1956
+ size = "medium",
1957
+ error = false,
1958
+ helperText,
1959
+ fullWidth = false,
1960
+ disabled = false,
1961
+ required = false,
1962
+ className = "",
1963
+ style,
1964
+ sx,
1965
+ onOpen,
1966
+ onClose
1967
+ } = props;
1968
+ const [open, setOpen] = (0, import_react18.useState)(false);
1969
+ const [inputStr, setInputStr] = (0, import_react18.useState)("");
1970
+ const [focusedIdx, setFocusedIdx] = (0, import_react18.useState)(-1);
1971
+ const [popupStyle, setPopupStyle] = (0, import_react18.useState)({});
1937
1972
  const containerRef = (0, import_react18.useRef)(null);
1938
- const apiKey = token || "";
1939
- const countries = import_country_state_city.Country.getAllCountries();
1940
- const [states, setStates] = (0, import_react18.useState)([]);
1941
- const [cities, setCities] = (0, import_react18.useState)([]);
1942
- (0, import_react18.useEffect)(() => {
1943
- const handleClickOutside = (event) => {
1944
- if (containerRef.current && !containerRef.current.contains(event.target)) {
1945
- setShowSuggestions(false);
1946
- }
1947
- };
1948
- document.addEventListener("mousedown", handleClickOutside);
1949
- return () => document.removeEventListener("mousedown", handleClickOutside);
1950
- }, []);
1951
- (0, import_react18.useEffect)(() => {
1952
- if (value.country || value.state || value.city || value.pincode) {
1953
- setGoogleFields({
1954
- country: !!value.country,
1955
- state: !!value.state,
1956
- city: !!value.city,
1957
- pincode: !!value.pincode
1973
+ const popupRef = (0, import_react18.useRef)(null);
1974
+ const inputRef = (0, import_react18.useRef)(null);
1975
+ const listRef = (0, import_react18.useRef)(null);
1976
+ const inputId = (0, import_react18.useRef)(`rf-ac-${Math.random().toString(36).slice(2, 9)}`).current;
1977
+ const sxClass = useSx(sx);
1978
+ const calcPopupStyle = (0, import_react18.useCallback)(() => {
1979
+ if (!containerRef.current) return;
1980
+ const rect = containerRef.current.getBoundingClientRect();
1981
+ const POPUP_MAX_HEIGHT = 280;
1982
+ const GAP2 = 4;
1983
+ const viewportH = window.innerHeight;
1984
+ const viewportW = window.innerWidth;
1985
+ const spaceBelow = viewportH - rect.bottom - GAP2;
1986
+ const spaceAbove = rect.top - GAP2;
1987
+ const openUpward = spaceBelow < POPUP_MAX_HEIGHT && spaceAbove > spaceBelow;
1988
+ const minLeft = 8;
1989
+ const maxLeft = viewportW - rect.width - 8;
1990
+ const left = Math.min(Math.max(rect.left, minLeft), maxLeft);
1991
+ if (openUpward) {
1992
+ setPopupStyle({
1993
+ bottom: viewportH - rect.top + GAP2,
1994
+ top: "auto",
1995
+ left,
1996
+ width: rect.width
1997
+ });
1998
+ } else {
1999
+ setPopupStyle({
2000
+ top: rect.bottom + GAP2,
2001
+ bottom: "auto",
2002
+ left,
2003
+ width: rect.width
1958
2004
  });
1959
2005
  }
1960
2006
  }, []);
1961
- (0, import_react18.useEffect)(() => {
1962
- if (value.country) {
1963
- const country = countries.find((c) => c.name === value.country);
1964
- if (country) {
1965
- const stateList = import_country_state_city.State.getStatesOfCountry(country.isoCode);
1966
- setStates(stateList);
1967
- } else {
1968
- setStates([]);
2007
+ const activeInput = controlledInput !== void 0 ? controlledInput : inputStr;
2008
+ const selectedValues = multiple ? Array.isArray(value) ? value : [] : value != null ? [value] : [];
2009
+ const isEqual = (0, import_react18.useCallback)(
2010
+ (a, b) => isOptionEqualToValue ? isOptionEqualToValue(a, b) : a === b,
2011
+ [isOptionEqualToValue]
2012
+ );
2013
+ const isSelected = (0, import_react18.useCallback)(
2014
+ (opt) => selectedValues.some((v) => isEqual(opt, v)),
2015
+ [selectedValues, isEqual]
2016
+ );
2017
+ const filtered = filterOptions ? filterOptions(options, activeInput) : defaultFilter(options, activeInput, getOptionLabel);
2018
+ const flatEntries = [];
2019
+ if (groupBy) {
2020
+ const groups = {};
2021
+ const order = [];
2022
+ filtered.forEach((opt) => {
2023
+ const g = groupBy(opt);
2024
+ if (!groups[g]) {
2025
+ groups[g] = [];
2026
+ order.push(g);
1969
2027
  }
1970
- } else {
1971
- setStates([]);
2028
+ groups[g].push(opt);
2029
+ });
2030
+ order.forEach((g) => {
2031
+ flatEntries.push({ kind: "group", label: g });
2032
+ groups[g].forEach((opt) => {
2033
+ flatEntries.push({ kind: "option", option: opt, flatIdx: flatEntries.filter((e) => e.kind === "option").length });
2034
+ });
2035
+ });
2036
+ } else {
2037
+ filtered.forEach((opt, i) => flatEntries.push({ kind: "option", option: opt, flatIdx: i }));
2038
+ }
2039
+ const selectableOptions = flatEntries.filter((e) => e.kind === "option");
2040
+ const openPopup = (0, import_react18.useCallback)(() => {
2041
+ if (disabled) return;
2042
+ calcPopupStyle();
2043
+ setOpen(true);
2044
+ setFocusedIdx(-1);
2045
+ onOpen?.();
2046
+ }, [disabled, calcPopupStyle, onOpen]);
2047
+ const closePopup = (0, import_react18.useCallback)((justSelected = false) => {
2048
+ setOpen(false);
2049
+ setFocusedIdx(-1);
2050
+ onClose?.();
2051
+ if (!justSelected && !freeSolo && !multiple && value == null) {
2052
+ setInputStr("");
2053
+ onInputChange?.("");
1972
2054
  }
1973
- }, [value.country]);
2055
+ }, [freeSolo, multiple, value, onInputChange, onClose]);
1974
2056
  (0, import_react18.useEffect)(() => {
1975
- if (value.state && value.country) {
1976
- const country = countries.find((c) => c.name === value.country);
1977
- if (country) {
1978
- const state = import_country_state_city.State.getStatesOfCountry(country.isoCode).find((s2) => s2.name === value.state);
1979
- if (state) {
1980
- const cityList = import_country_state_city.City.getCitiesOfState(country.isoCode, state.isoCode);
1981
- setCities(cityList);
1982
- } else {
1983
- setCities([]);
1984
- }
1985
- } else {
1986
- setCities([]);
2057
+ if (!open) return;
2058
+ const handleOutside = (e) => {
2059
+ const target = e.target;
2060
+ const insideContainer = containerRef.current?.contains(target);
2061
+ const insidePopup = popupRef.current?.contains(target);
2062
+ if (!insideContainer && !insidePopup) {
2063
+ closePopup();
1987
2064
  }
2065
+ };
2066
+ document.addEventListener("mousedown", handleOutside);
2067
+ window.addEventListener("scroll", calcPopupStyle, true);
2068
+ window.addEventListener("resize", calcPopupStyle);
2069
+ return () => {
2070
+ document.removeEventListener("mousedown", handleOutside);
2071
+ window.removeEventListener("scroll", calcPopupStyle, true);
2072
+ window.removeEventListener("resize", calcPopupStyle);
2073
+ };
2074
+ }, [open, closePopup, calcPopupStyle]);
2075
+ (0, import_react18.useEffect)(() => {
2076
+ if (controlledInput !== void 0) return;
2077
+ if (!multiple) {
2078
+ const v = value;
2079
+ setInputStr(v != null ? getOptionLabel(v) : "");
2080
+ }
2081
+ }, [value, multiple, getOptionLabel, controlledInput]);
2082
+ const selectOption = (opt) => {
2083
+ if (getOptionDisabled?.(opt)) return;
2084
+ if (multiple) {
2085
+ const already = isSelected(opt);
2086
+ const next = already ? selectedValues.filter((v) => !isEqual(v, opt)) : [...selectedValues, opt];
2087
+ onChange?.(next);
2088
+ setInputStr("");
2089
+ onInputChange?.("");
2090
+ inputRef.current?.focus();
1988
2091
  } else {
1989
- setCities([]);
2092
+ onChange?.(opt);
2093
+ setInputStr(getOptionLabel(opt));
2094
+ onInputChange?.(getOptionLabel(opt));
2095
+ closePopup(true);
1990
2096
  }
1991
- }, [value.state, value.country]);
1992
- const handleChange = (field, newVal) => {
1993
- onChange({
1994
- ...value,
1995
- [field]: newVal
1996
- });
2097
+ setFocusedIdx(-1);
1997
2098
  };
1998
- const fetchPlaceDetails = async (placeId, mainText = "") => {
1999
- if (!apiKey) {
2000
- console.warn("Google Places API Key (token) is missing.");
2001
- return;
2002
- }
2003
- setLoading(true);
2004
- try {
2005
- const res = await import_axios.default.get(
2006
- `https://places.googleapis.com/v1/places/${placeId}`,
2007
- {
2008
- headers: {
2009
- "Content-Type": "application/json",
2010
- "X-Goog-Api-Key": apiKey,
2011
- "X-Goog-FieldMask": "addressComponents,formattedAddress"
2012
- }
2013
- }
2014
- );
2015
- const comps = res.data.addressComponents || [];
2016
- const findComp = (type) => comps.find((c) => c.types.includes(type))?.longText || "";
2017
- const city = findComp("locality") || findComp("sublocality_level_1");
2018
- const state = findComp("administrative_area_level_1");
2019
- const country = findComp("country");
2020
- const pincode = findComp("postal_code");
2021
- setGoogleFields({
2022
- country: !!country,
2023
- state: !!state,
2024
- city: !!city,
2025
- pincode: !!pincode
2026
- });
2027
- const updatedData = {
2028
- ...value,
2029
- addressLine1: mainText || value.addressLine1,
2030
- addressLine2: res.data.formattedAddress || value.addressLine2,
2031
- city,
2032
- state,
2033
- country,
2034
- pincode
2035
- };
2036
- onChange(updatedData);
2037
- setShowSuggestions(false);
2038
- } catch (err) {
2039
- console.error("Error fetching place details:", err);
2040
- } finally {
2041
- setLoading(false);
2042
- }
2099
+ const clearAll = (e) => {
2100
+ e.stopPropagation();
2101
+ onChange?.(multiple ? [] : null);
2102
+ setInputStr("");
2103
+ onInputChange?.("");
2104
+ inputRef.current?.focus();
2043
2105
  };
2044
- const handleQuerySuggestions = async (query) => {
2045
- if (!apiKey || !query || query.length < 3) {
2046
- setSuggestions([]);
2047
- setShowSuggestions(false);
2048
- return;
2049
- }
2050
- setLoading(true);
2051
- try {
2052
- const res = await import_axios.default.post(
2053
- `https://places.googleapis.com/v1/places:autocomplete`,
2054
- { input: query },
2055
- {
2056
- headers: {
2057
- "Content-Type": "application/json",
2058
- "X-Goog-Api-Key": apiKey
2059
- }
2060
- }
2061
- );
2062
- setSuggestions(res.data.suggestions || []);
2063
- setShowSuggestions(true);
2064
- } catch (err) {
2065
- console.error("Autocomplete Error:", err);
2066
- } finally {
2067
- setLoading(false);
2068
- }
2106
+ const removeTag = (opt, e) => {
2107
+ e.stopPropagation();
2108
+ const next = selectedValues.filter((v) => !isEqual(v, opt));
2109
+ onChange?.(next);
2069
2110
  };
2070
- const handleCountryChange = (newCountry) => {
2071
- onChange({
2072
- ...value,
2073
- country: newCountry,
2074
- state: "",
2075
- city: ""
2076
- });
2077
- setGoogleFields({ ...googleFields, country: false, state: false, city: false });
2111
+ const handleInputChange = (e) => {
2112
+ const v = e.target.value;
2113
+ setInputStr(v);
2114
+ onInputChange?.(v);
2115
+ if (!open) openPopup();
2078
2116
  };
2079
- const handleStateChange = (newState) => {
2080
- onChange({
2081
- ...value,
2082
- state: newState,
2083
- city: ""
2117
+ const handleKeyDown = (e) => {
2118
+ if (e.key === "ArrowDown") {
2119
+ e.preventDefault();
2120
+ if (!open) {
2121
+ openPopup();
2122
+ return;
2123
+ }
2124
+ setFocusedIdx((i) => {
2125
+ const next = (i + 1) % selectableOptions.length;
2126
+ scrollOptionIntoView(next);
2127
+ return next;
2128
+ });
2129
+ } else if (e.key === "ArrowUp") {
2130
+ e.preventDefault();
2131
+ if (!open) {
2132
+ openPopup();
2133
+ return;
2134
+ }
2135
+ setFocusedIdx((i) => {
2136
+ const next = (i - 1 + selectableOptions.length) % selectableOptions.length;
2137
+ scrollOptionIntoView(next);
2138
+ return next;
2139
+ });
2140
+ } else if (e.key === "Enter") {
2141
+ e.preventDefault();
2142
+ if (!open) {
2143
+ openPopup();
2144
+ return;
2145
+ }
2146
+ if (focusedIdx >= 0 && focusedIdx < selectableOptions.length) {
2147
+ selectOption(selectableOptions[focusedIdx].option);
2148
+ } else if (freeSolo && activeInput) {
2149
+ onChange?.(activeInput);
2150
+ if (!multiple) closePopup();
2151
+ }
2152
+ } else if (e.key === "Escape") {
2153
+ closePopup();
2154
+ } else if (e.key === "Backspace" && multiple && !activeInput && selectedValues.length > 0) {
2155
+ removeTag(selectedValues[selectedValues.length - 1], { stopPropagation: () => {
2156
+ } });
2157
+ }
2158
+ };
2159
+ const scrollOptionIntoView = (idx) => {
2160
+ requestAnimationFrame(() => {
2161
+ const el = listRef.current?.querySelector(`[data-idx="${idx}"]`);
2162
+ el?.scrollIntoView({ block: "nearest" });
2084
2163
  });
2085
2164
  };
2086
- return /* @__PURE__ */ import_react18.default.createElement("div", { className: "address-lookup-container", style: sx, ref: containerRef }, /* @__PURE__ */ import_react18.default.createElement("div", { className: `address-lookup-grid address-lookup-grid-${layout}` }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "address-lookup-grid-item col-l1" }, /* @__PURE__ */ import_react18.default.createElement(
2087
- TextField,
2088
- {
2089
- label,
2090
- name: "addressLine1",
2091
- fullWidth: true,
2092
- value: value.addressLine1 || "",
2093
- required,
2094
- autoComplete: "off",
2095
- onChange: (e) => {
2096
- const val = e.target.value;
2097
- handleChange("addressLine1", val);
2098
- if (!val) {
2099
- onChange({
2100
- ...value,
2101
- addressLine1: "",
2102
- city: "",
2103
- state: "",
2104
- country: "",
2105
- pincode: ""
2106
- });
2107
- setSuggestions([]);
2108
- setShowSuggestions(false);
2109
- setGoogleFields({ country: false, state: false, city: false, pincode: false });
2110
- } else {
2111
- if (debounceTimeout.current) clearTimeout(debounceTimeout.current);
2112
- debounceTimeout.current = setTimeout(() => {
2113
- handleQuerySuggestions(val);
2114
- }, 500);
2115
- }
2116
- },
2117
- onFocus: () => suggestions.length > 0 && setShowSuggestions(true)
2118
- }
2119
- ), loading && /* @__PURE__ */ import_react18.default.createElement("div", { className: "loading-indicator" }, /* @__PURE__ */ import_react18.default.createElement(circularProgress_default, { size: 20 })), showSuggestions && suggestions.length > 0 && /* @__PURE__ */ import_react18.default.createElement("div", { className: "autocomplete-dropdown" }, suggestions.map((option, idx) => /* @__PURE__ */ import_react18.default.createElement(
2165
+ const hasClearable = clearable && !disabled && (multiple ? selectedValues.length > 0 : value != null);
2166
+ const visibleTags = multiple && limitTags != null ? selectedValues.slice(0, limitTags) : selectedValues;
2167
+ const hiddenCount = multiple && limitTags != null ? Math.max(0, selectedValues.length - limitTags) : 0;
2168
+ const isFloating = Boolean(
2169
+ open || activeInput || (multiple ? selectedValues.length > 0 : value != null)
2170
+ );
2171
+ const rootClasses = [
2172
+ "rf-text-field",
2173
+ `rf-text-field--${variant}`,
2174
+ `rf-text-field--${size}`,
2175
+ "rf-text-field--primary",
2176
+ error ? "rf-text-field--error" : "",
2177
+ fullWidth ? "rf-text-field--full-width" : "",
2178
+ disabled ? "rf-text-field--disabled" : "",
2179
+ isFloating ? "rf-text-field--floating" : "",
2180
+ label ? "rf-text-field--has-label" : "",
2181
+ "rf-text-field--adorned-end",
2182
+ "rf-autocomplete",
2183
+ sxClass,
2184
+ className
2185
+ ].filter(Boolean).join(" ");
2186
+ const inputPlaceholder = placeholder || (variant === "outlined" ? " " : void 0);
2187
+ return /* @__PURE__ */ import_react18.default.createElement("div", { ref: containerRef, className: rootClasses, style }, /* @__PURE__ */ import_react18.default.createElement(
2120
2188
  "div",
2121
2189
  {
2122
- key: idx,
2123
- className: "autocomplete-option",
2190
+ className: "rf-text-field__wrapper",
2124
2191
  onClick: () => {
2125
- const mainText = option?.placePrediction?.structuredFormat?.mainText?.text || "";
2126
- handleChange("addressLine1", mainText);
2127
- fetchPlaceDetails(option.placePrediction.placeId, mainText);
2192
+ if (!disabled) {
2193
+ inputRef.current?.focus();
2194
+ if (!open) openPopup();
2195
+ }
2128
2196
  }
2129
2197
  },
2130
- /* @__PURE__ */ import_react18.default.createElement("div", { className: "autocomplete-main-text" }, option?.placePrediction?.structuredFormat?.mainText?.text),
2131
- /* @__PURE__ */ import_react18.default.createElement("div", { className: "autocomplete-secondary-text" }, option?.placePrediction?.structuredFormat?.secondaryText?.text)
2132
- ))), error.addressLine1 && /* @__PURE__ */ import_react18.default.createElement("div", { className: "field-error-text" }, error.addressLine1)), layout === "compact" && /* @__PURE__ */ import_react18.default.createElement("div", { className: "address-lookup-grid-item col-l2" }, /* @__PURE__ */ import_react18.default.createElement(
2133
- TextField,
2134
- {
2135
- label: "Address Line 2",
2136
- name: "addressLine2",
2137
- fullWidth: true,
2138
- value: value.addressLine2 || "",
2139
- onChange: (e) => handleChange("addressLine2", e.target.value)
2140
- }
2141
- )), layout !== "compact" && /* @__PURE__ */ import_react18.default.createElement("div", { className: "address-lookup-grid-item col-l2" }, /* @__PURE__ */ import_react18.default.createElement(
2142
- TextField,
2143
- {
2144
- label: "Address Line 2",
2145
- name: "addressLine2",
2146
- fullWidth: true,
2147
- value: value.addressLine2 || "",
2148
- onChange: (e) => handleChange("addressLine2", e.target.value)
2149
- }
2150
- )), /* @__PURE__ */ import_react18.default.createElement("div", { className: "address-lookup-grid-item col-country" }, /* @__PURE__ */ import_react18.default.createElement(
2151
- TextField,
2152
- {
2153
- label: "Country",
2154
- name: "country",
2155
- fullWidth: true,
2156
- value: value.country || "",
2157
- required,
2158
- className: googleFields.country && value.country ? "field-disabled" : "",
2159
- readOnly: googleFields.country && !!value.country,
2160
- onChange: (e) => handleCountryChange(e.target.value),
2161
- list: "countries-list"
2162
- }
2163
- ), /* @__PURE__ */ import_react18.default.createElement("datalist", { id: "countries-list" }, countries.map((c) => /* @__PURE__ */ import_react18.default.createElement("option", { key: c.isoCode, value: c.name }))), error.country && /* @__PURE__ */ import_react18.default.createElement("div", { className: "field-error-text" }, error.country)), /* @__PURE__ */ import_react18.default.createElement("div", { className: "address-lookup-grid-item col-state" }, /* @__PURE__ */ import_react18.default.createElement(
2164
- TextField,
2165
- {
2166
- label: "State",
2167
- name: "state",
2168
- fullWidth: true,
2169
- value: value.state || "",
2170
- required,
2171
- disabled: !value.country,
2172
- className: googleFields.state && value.state ? "field-disabled" : "",
2173
- readOnly: googleFields.state && !!value.state,
2174
- onChange: (e) => handleStateChange(e.target.value),
2175
- list: "states-list"
2176
- }
2177
- ), /* @__PURE__ */ import_react18.default.createElement("datalist", { id: "states-list" }, states.map((s2) => /* @__PURE__ */ import_react18.default.createElement("option", { key: s2.isoCode, value: s2.name }))), error.state && /* @__PURE__ */ import_react18.default.createElement("div", { className: "field-error-text" }, error.state)), /* @__PURE__ */ import_react18.default.createElement("div", { className: "address-lookup-grid-item col-city" }, /* @__PURE__ */ import_react18.default.createElement(
2178
- TextField,
2179
- {
2180
- label: "City",
2181
- name: "city",
2182
- fullWidth: true,
2183
- value: value.city || "",
2184
- required,
2185
- disabled: !value.state,
2186
- className: googleFields.city && value.city ? "field-disabled" : "",
2187
- readOnly: googleFields.city && !!value.city,
2188
- onChange: (e) => handleChange("city", e.target.value),
2189
- list: "cities-list"
2190
- }
2191
- ), /* @__PURE__ */ import_react18.default.createElement("datalist", { id: "cities-list" }, cities.map((c, i) => /* @__PURE__ */ import_react18.default.createElement("option", { key: i, value: c.name }))), error.city && /* @__PURE__ */ import_react18.default.createElement("div", { className: "field-error-text" }, error.city)), /* @__PURE__ */ import_react18.default.createElement("div", { className: "address-lookup-grid-item col-pin" }, /* @__PURE__ */ import_react18.default.createElement(
2192
- TextField,
2193
- {
2194
- label: "Pincode",
2195
- name: "pincode",
2196
- fullWidth: true,
2197
- value: value.pincode || "",
2198
- required,
2199
- className: googleFields.pincode && value.pincode ? "field-disabled" : "",
2200
- readOnly: googleFields.pincode && !!value.pincode,
2201
- onChange: (e) => handleChange("pincode", e.target.value)
2202
- }
2203
- ), error.pincode && /* @__PURE__ */ import_react18.default.createElement("div", { className: "field-error-text" }, error.pincode))));
2204
- };
2205
- var AddressLookup_default = AddressLookup;
2206
-
2207
- // lib/TextFields/DateField.tsx
2208
- var import_react19 = __toESM(require("react"), 1);
2209
- var import_react_dom2 = require("react-dom");
2210
- var WEEKDAYS = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"];
2211
- var MONTHS = [
2212
- "January",
2213
- "February",
2214
- "March",
2215
- "April",
2216
- "May",
2217
- "June",
2218
- "July",
2219
- "August",
2220
- "September",
2221
- "October",
2222
- "November",
2223
- "December"
2224
- ];
2225
- var MONTHS_SHORT = [
2226
- "Jan",
2227
- "Feb",
2228
- "Mar",
2229
- "Apr",
2230
- "May",
2231
- "Jun",
2232
- "Jul",
2233
- "Aug",
2234
- "Sep",
2235
- "Oct",
2236
- "Nov",
2237
- "Dec"
2238
- ];
2239
- var formatDisplay = (d, fmt = "MM/DD/YYYY") => {
2240
- const mm = String(d.getMonth() + 1).padStart(2, "0");
2241
- const dd = String(d.getDate()).padStart(2, "0");
2242
- const yyyy = String(d.getFullYear());
2243
- const day = d.getDate();
2244
- switch (fmt) {
2245
- case "DD/MM/YYYY":
2246
- return `${dd}/${mm}/${yyyy}`;
2247
- case "YYYY-MM-DD":
2248
- return `${yyyy}-${mm}-${dd}`;
2249
- case "DD-MM-YYYY":
2250
- return `${dd}-${mm}-${yyyy}`;
2251
- case "MM-DD-YYYY":
2252
- return `${mm}-${dd}-${yyyy}`;
2253
- case "YYYY/MM/DD":
2254
- return `${yyyy}/${mm}/${dd}`;
2255
- case "DD MMM YYYY":
2256
- return `${dd} ${MONTHS_SHORT[d.getMonth()]} ${yyyy}`;
2257
- case "MMM DD, YYYY":
2258
- return `${MONTHS_SHORT[d.getMonth()]} ${dd}, ${yyyy}`;
2259
- case "DD MMMM YYYY":
2260
- return `${dd} ${MONTHS[d.getMonth()]} ${yyyy}`;
2261
- case "MMMM DD, YYYY":
2262
- return `${MONTHS[d.getMonth()]} ${dd}, ${yyyy}`;
2263
- case "MM/DD/YYYY":
2264
- default:
2265
- return `${mm}/${dd}/${yyyy}`;
2266
- }
2267
- };
2268
- var formatTimeDisplay = (h, m, ampm) => `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")} ${ampm}`;
2269
- var parseMonthName = (name) => {
2270
- const lower = name.toLowerCase();
2271
- let idx = MONTHS.findIndex((m) => m.toLowerCase() === lower);
2272
- if (idx >= 0) return idx;
2273
- idx = MONTHS_SHORT.findIndex((m) => m.toLowerCase() === lower);
2274
- return idx;
2275
- };
2276
- var parseDisplay = (str, fmt = "MM/DD/YYYY") => {
2277
- if (fmt === "DD MMM YYYY" || fmt === "DD MMMM YYYY") {
2278
- const parts2 = str.split(" ");
2279
- if (parts2.length !== 3) return null;
2280
- const dd2 = parseInt(parts2[0], 10);
2281
- const mm2 = parseMonthName(parts2[1]);
2282
- const yyyy2 = parseInt(parts2[2], 10);
2283
- if (isNaN(dd2) || mm2 < 0 || isNaN(yyyy2) || yyyy2 < 1e3) return null;
2284
- const d2 = new Date(yyyy2, mm2, dd2);
2285
- return isNaN(d2.getTime()) ? null : d2;
2286
- }
2287
- if (fmt === "MMM DD, YYYY" || fmt === "MMMM DD, YYYY") {
2288
- const cleaned = str.replace(",", "");
2289
- const parts2 = cleaned.split(" ").filter(Boolean);
2290
- if (parts2.length !== 3) return null;
2291
- const mm2 = parseMonthName(parts2[0]);
2292
- const dd2 = parseInt(parts2[1], 10);
2293
- const yyyy2 = parseInt(parts2[2], 10);
2294
- if (mm2 < 0 || isNaN(dd2) || isNaN(yyyy2) || yyyy2 < 1e3) return null;
2295
- const d2 = new Date(yyyy2, mm2, dd2);
2296
- return isNaN(d2.getTime()) ? null : d2;
2297
- }
2298
- const sep = str.includes("/") ? "/" : "-";
2299
- const parts = str.split(sep);
2300
- if (parts.length !== 3) return null;
2301
- const nums = parts.map(Number);
2302
- let yyyy, mm, dd;
2303
- switch (fmt) {
2304
- case "DD/MM/YYYY":
2305
- case "DD-MM-YYYY":
2306
- [dd, mm, yyyy] = nums;
2307
- break;
2308
- case "YYYY-MM-DD":
2309
- case "YYYY/MM/DD":
2310
- [yyyy, mm, dd] = nums;
2311
- break;
2312
- case "MM-DD-YYYY":
2313
- case "MM/DD/YYYY":
2314
- default:
2315
- [mm, dd, yyyy] = nums;
2316
- break;
2317
- }
2318
- if (!mm || !dd || !yyyy || yyyy < 1e3) return null;
2319
- const d = new Date(yyyy, mm - 1, dd);
2320
- if (isNaN(d.getTime())) return null;
2321
- return d;
2322
- };
2323
- var isoToDate = (iso) => {
2324
- if (!iso) return null;
2325
- const [datePart] = iso.split("T");
2326
- const [y, mo, d] = datePart.split("-").map(Number);
2327
- if (!y || !mo || !d) return null;
2328
- return new Date(y, mo - 1, d);
2329
- };
2330
- var today = () => {
2331
- const t = /* @__PURE__ */ new Date();
2332
- return new Date(t.getFullYear(), t.getMonth(), t.getDate());
2333
- };
2334
- var isSameDay = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
2335
- var isDatetimeType = (t) => t !== "date";
2336
- var buildISO = (date, type, hour, minute, ampm) => {
2337
- const y = date.getFullYear();
2338
- const mo = String(date.getMonth() + 1).padStart(2, "0");
2339
- const d = String(date.getDate()).padStart(2, "0");
2340
- if (type === "date") return `${y}-${mo}-${d}`;
2341
- let h24 = hour % 12;
2342
- if (ampm === "PM") h24 += 12;
2343
- return `${y}-${mo}-${d}T${String(h24).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
2344
- };
2345
- var parseTimeFromISO = (iso) => {
2346
- const timePart = iso.split("T")[1] || "";
2347
- const [hStr, mStr] = timePart.split(":");
2348
- let h24 = parseInt(hStr, 10) || 0;
2349
- const m = parseInt(mStr, 10) || 0;
2350
- const ampm = h24 < 12 ? "AM" : "PM";
2351
- let h = h24 % 12;
2352
- if (h === 0) h = 12;
2353
- return { h, m, ampm };
2354
- };
2355
- var CalendarIcon = () => /* @__PURE__ */ import_react19.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react19.default.createElement("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }), /* @__PURE__ */ import_react19.default.createElement("line", { x1: "16", y1: "2", x2: "16", y2: "6" }), /* @__PURE__ */ import_react19.default.createElement("line", { x1: "8", y1: "2", x2: "8", y2: "6" }), /* @__PURE__ */ import_react19.default.createElement("line", { x1: "3", y1: "10", x2: "21", y2: "10" }));
2356
- var ChevUp = () => /* @__PURE__ */ import_react19.default.createElement("svg", { width: "10", height: "7", viewBox: "0 0 10 7", fill: "currentColor" }, /* @__PURE__ */ import_react19.default.createElement("path", { d: "M5 0L10 7H0L5 0Z" }));
2357
- var ChevDown = () => /* @__PURE__ */ import_react19.default.createElement("svg", { width: "10", height: "7", viewBox: "0 0 10 7", fill: "currentColor" }, /* @__PURE__ */ import_react19.default.createElement("path", { d: "M5 7L0 0H10L5 7Z" }));
2358
- var ITEM_H = 36;
2359
- var ScrollColumn = ({ items, selected, onSelect, infinite = true }) => {
2360
- const listRef = (0, import_react19.useRef)(null);
2361
- const isInternalScroll = (0, import_react19.useRef)(false);
2362
- const scrollTimeout = (0, import_react19.useRef)(null);
2363
- const MULTIPLIER = infinite ? 100 : 1;
2364
- const virtualItems = infinite ? Array(MULTIPLIER).fill(items).flat() : items;
2365
- const centerOffset = infinite ? Math.floor(MULTIPLIER / 2) * items.length : 0;
2366
- const VISUAL_OFFSET = 54;
2367
- (0, import_react19.useEffect)(() => {
2368
- if (listRef.current) {
2369
- const targetIndex = centerOffset + selected;
2370
- listRef.current.scrollTop = targetIndex * ITEM_H - (infinite ? VISUAL_OFFSET : 0);
2371
- }
2372
- }, [centerOffset, infinite, selected]);
2373
- (0, import_react19.useEffect)(() => {
2374
- if (listRef.current && !isInternalScroll.current) {
2375
- const targetIndex = centerOffset + selected;
2376
- listRef.current.scrollTo({
2377
- top: targetIndex * ITEM_H - (infinite ? VISUAL_OFFSET : 0),
2378
- behavior: "smooth"
2379
- });
2380
- }
2381
- isInternalScroll.current = false;
2382
- }, [selected, centerOffset, infinite]);
2383
- const handleScroll = () => {
2384
- if (!listRef.current) return;
2385
- const scrollTop = listRef.current.scrollTop;
2386
- const adjustedScrollTop = infinite ? scrollTop + VISUAL_OFFSET : scrollTop;
2387
- const index = Math.round(adjustedScrollTop / ITEM_H);
2388
- const actualIndex = infinite ? (index % items.length + items.length) % items.length : Math.max(0, Math.min(items.length - 1, index));
2389
- if (infinite) {
2390
- const buffer = items.length * 10;
2391
- if (index < buffer || index > virtualItems.length - buffer) {
2392
- const newIndex = centerOffset + actualIndex;
2393
- listRef.current.scrollTop = newIndex * ITEM_H - VISUAL_OFFSET;
2394
- return;
2395
- }
2396
- }
2397
- if (scrollTimeout.current) clearTimeout(scrollTimeout.current);
2398
- scrollTimeout.current = setTimeout(() => {
2399
- if (actualIndex !== selected) {
2400
- isInternalScroll.current = true;
2401
- onSelect(actualIndex);
2402
- }
2403
- }, 100);
2404
- };
2405
- return /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-timescroll__col-wrapper" }, /* @__PURE__ */ import_react19.default.createElement(
2406
- "div",
2407
- {
2408
- className: "rf-timescroll__col",
2409
- ref: listRef,
2410
- onScroll: handleScroll
2411
- },
2412
- !infinite && /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-timescroll__spacer" }),
2413
- virtualItems.map((label, idx) => /* @__PURE__ */ import_react19.default.createElement(
2414
- "div",
2415
- {
2416
- key: `${label}-${idx}`,
2417
- className: `rf-timescroll__item ${idx % items.length === selected ? "rf-timescroll__item--active" : ""}`
2418
- },
2419
- label
2420
- )),
2421
- !infinite && /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-timescroll__spacer" })
2422
- ), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-timescroll__mask rf-timescroll__mask--top" }), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-timescroll__mask rf-timescroll__mask--bottom" }));
2423
- };
2424
- var SpinnerPanel = ({
2425
- hour,
2426
- minute,
2427
- ampm,
2428
- onHourChange,
2429
- onMinuteChange,
2430
- onHourInput,
2431
- onMinuteInput,
2432
- onAmpmToggle
2433
- }) => /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__time-row" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__time-input-wrap" }, /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", className: "rf-date-picker__time-spin-btn", onMouseDown: (e) => e.preventDefault(), onClick: () => onHourChange(1) }, /* @__PURE__ */ import_react19.default.createElement(ChevUp, null)), /* @__PURE__ */ import_react19.default.createElement(
2434
- "input",
2435
- {
2436
- type: "number",
2437
- className: "rf-date-picker__time-digit",
2438
- value: String(hour).padStart(2, "0"),
2439
- min: 1,
2440
- max: 12,
2441
- onChange: onHourInput,
2442
- onMouseDown: (e) => e.stopPropagation()
2443
- }
2444
- ), /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", className: "rf-date-picker__time-spin-btn", onMouseDown: (e) => e.preventDefault(), onClick: () => onHourChange(-1) }, /* @__PURE__ */ import_react19.default.createElement(ChevDown, null))), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__time-colon" }, ":"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__time-input-wrap" }, /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", className: "rf-date-picker__time-spin-btn", onMouseDown: (e) => e.preventDefault(), onClick: () => onMinuteChange(1) }, /* @__PURE__ */ import_react19.default.createElement(ChevUp, null)), /* @__PURE__ */ import_react19.default.createElement(
2445
- "input",
2446
- {
2447
- type: "number",
2448
- className: "rf-date-picker__time-digit",
2449
- value: String(minute).padStart(2, "0"),
2450
- min: 0,
2451
- max: 59,
2452
- onChange: onMinuteInput,
2453
- onMouseDown: (e) => e.stopPropagation()
2454
- }
2455
- ), /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", className: "rf-date-picker__time-spin-btn", onMouseDown: (e) => e.preventDefault(), onClick: () => onMinuteChange(-1) }, /* @__PURE__ */ import_react19.default.createElement(ChevDown, null))), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__ampm" }, /* @__PURE__ */ import_react19.default.createElement(
2456
- "button",
2457
- {
2458
- type: "button",
2459
- className: `rf-date-picker__ampm-btn ${ampm === "AM" ? "rf-date-picker__ampm-btn--active" : ""}`,
2460
- onMouseDown: (e) => e.preventDefault(),
2461
- onClick: () => onAmpmToggle("AM")
2462
- },
2463
- "AM"
2464
- ), /* @__PURE__ */ import_react19.default.createElement(
2465
- "button",
2466
- {
2467
- type: "button",
2468
- className: `rf-date-picker__ampm-btn ${ampm === "PM" ? "rf-date-picker__ampm-btn--active" : ""}`,
2469
- onMouseDown: (e) => e.preventDefault(),
2470
- onClick: () => onAmpmToggle("PM")
2471
- },
2472
- "PM"
2473
- )));
2474
- var CalendarBody = ({
2475
- viewMonth,
2476
- viewYear,
2477
- selectedDate,
2478
- todayDate,
2479
- dayCells,
2480
- onDayClick,
2481
- onPrev,
2482
- onNext,
2483
- onMonthSelect,
2484
- onYearSelect
2485
- }) => {
2486
- const [pickerView, setPickerView] = (0, import_react19.useState)("calendar");
2487
- const handleMonthClick = () => {
2488
- setPickerView(pickerView === "month" ? "calendar" : "month");
2489
- };
2490
- const handleYearClick = () => {
2491
- setPickerView(pickerView === "year" ? "calendar" : "year");
2492
- };
2493
- const handleMonthPick = (month) => {
2494
- onMonthSelect(month);
2495
- setPickerView("calendar");
2496
- };
2497
- const handleYearPick = (year) => {
2498
- onYearSelect(year);
2499
- setPickerView("calendar");
2500
- };
2501
- const currentYear = todayDate.getFullYear();
2502
- const yearStart = viewYear - 6;
2503
- const years = Array.from({ length: 16 }, (_, i) => yearStart + i);
2504
- return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__header" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__header-labels" }, /* @__PURE__ */ import_react19.default.createElement(
2505
- "span",
2506
- {
2507
- className: `rf-date-picker__month-label ${pickerView === "month" ? "rf-date-picker__month-label--active" : ""}`,
2508
- onClick: handleMonthClick
2509
- },
2510
- MONTHS[viewMonth]
2511
- ), /* @__PURE__ */ import_react19.default.createElement(
2512
- "span",
2513
- {
2514
- className: `rf-date-picker__year-label ${pickerView === "year" ? "rf-date-picker__year-label--active" : ""}`,
2515
- onClick: handleYearClick
2516
- },
2517
- viewYear
2518
- )), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__nav" }, pickerView === "year" ? /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: () => onYearSelect(viewYear - 16), "aria-label": "Previous years" }, "\u2039"), /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: () => onYearSelect(viewYear + 16), "aria-label": "Next years" }, "\u203A")) : /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: onPrev, "aria-label": "Previous month" }, "\u2039"), /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: onNext, "aria-label": "Next month" }, "\u203A")))), pickerView === "month" && /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__month-grid" }, MONTHS_SHORT.map((m, idx) => /* @__PURE__ */ import_react19.default.createElement(
2519
- "button",
2520
- {
2521
- key: m,
2522
- type: "button",
2523
- className: [
2524
- "rf-date-picker__month-cell",
2525
- idx === viewMonth ? "rf-date-picker__month-cell--selected" : "",
2526
- idx === todayDate.getMonth() && viewYear === currentYear ? "rf-date-picker__month-cell--current" : ""
2527
- ].filter(Boolean).join(" "),
2528
- onClick: () => handleMonthPick(idx)
2529
- },
2530
- m
2531
- ))), pickerView === "year" && /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__year-grid" }, years.map((y) => /* @__PURE__ */ import_react19.default.createElement(
2532
- "button",
2533
- {
2534
- key: y,
2535
- type: "button",
2536
- className: [
2537
- "rf-date-picker__year-cell",
2538
- y === viewYear ? "rf-date-picker__year-cell--selected" : "",
2539
- y === currentYear ? "rf-date-picker__year-cell--current" : ""
2540
- ].filter(Boolean).join(" "),
2541
- onClick: () => handleYearPick(y)
2542
- },
2543
- y
2544
- ))), pickerView === "calendar" && /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__weekdays" }, WEEKDAYS.map((w) => /* @__PURE__ */ import_react19.default.createElement("div", { key: w, className: "rf-date-picker__weekday" }, w))), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__grid" }, dayCells.map((day, idx) => {
2545
- if (day === null) return /* @__PURE__ */ import_react19.default.createElement("div", { key: `e-${idx}`, className: "rf-date-picker__day rf-date-picker__day--empty" });
2546
- const cellDate = new Date(viewYear, viewMonth, day);
2547
- const isSelected = selectedDate ? isSameDay(cellDate, selectedDate) : false;
2548
- const isToday = isSameDay(cellDate, todayDate);
2549
- return /* @__PURE__ */ import_react19.default.createElement(
2550
- "button",
2551
- {
2552
- key: day,
2553
- type: "button",
2554
- className: [
2555
- "rf-date-picker__day",
2556
- isSelected ? "rf-date-picker__day--selected" : "",
2557
- isToday && !isSelected ? "rf-date-picker__day--today" : ""
2558
- ].filter(Boolean).join(" "),
2559
- onClick: () => onDayClick(day)
2560
- },
2561
- day
2562
- );
2563
- }))));
2564
- };
2565
- var DateField = ({
2566
- label,
2567
- value,
2568
- onChange,
2569
- type = "date",
2570
- dateFormat = "MM/DD/YYYY",
2571
- variant = "outlined",
2572
- size = "medium",
2573
- color = "primary",
2574
- error = false,
2575
- helperText,
2576
- fullWidth = false,
2577
- disabled = false,
2578
- required = false,
2579
- placeholder,
2580
- className = "",
2581
- style,
2582
- sx
2583
- }) => {
2584
- const sxClass = useSx(sx);
2585
- const [open, setOpen] = (0, import_react19.useState)(false);
2586
- const [selectedDate, setSelectedDate] = (0, import_react19.useState)(() => value ? isoToDate(value) : null);
2587
- const [hour, setHour] = (0, import_react19.useState)(() => {
2588
- if (value && isDatetimeType(type)) return parseTimeFromISO(value).h;
2589
- return 12;
2590
- });
2591
- const [minute, setMinute] = (0, import_react19.useState)(() => {
2592
- if (value && isDatetimeType(type)) return parseTimeFromISO(value).m;
2593
- return 0;
2594
- });
2595
- const [ampm, setAmpm] = (0, import_react19.useState)(() => {
2596
- if (value && isDatetimeType(type)) return parseTimeFromISO(value).ampm;
2597
- return "AM";
2598
- });
2599
- const [viewYear, setViewYear] = (0, import_react19.useState)(() => {
2600
- const base = value ? isoToDate(value) : null;
2601
- return base ? base.getFullYear() : today().getFullYear();
2602
- });
2603
- const [viewMonth, setViewMonth] = (0, import_react19.useState)(() => {
2604
- const base = value ? isoToDate(value) : null;
2605
- return base ? base.getMonth() : today().getMonth();
2606
- });
2607
- const [inputStr, setInputStr] = (0, import_react19.useState)(() => {
2608
- if (!value) return "";
2609
- const d = isoToDate(value);
2610
- if (!d) return "";
2611
- let str = formatDisplay(d, dateFormat);
2612
- if (isDatetimeType(type)) {
2613
- const t = parseTimeFromISO(value);
2614
- str += " " + formatTimeDisplay(t.h, t.m, t.ampm);
2615
- }
2616
- return str;
2617
- });
2618
- const HOURS = Array.from({ length: 12 }, (_, i) => String(i + 1).padStart(2, "0"));
2619
- const MINUTES = Array.from({ length: 60 }, (_, i) => String(i).padStart(2, "0"));
2620
- const AMPMS = ["AM", "PM"];
2621
- const containerRef = (0, import_react19.useRef)(null);
2622
- const pickerRef = (0, import_react19.useRef)(null);
2623
- const [dropUp, setDropUp] = (0, import_react19.useState)(false);
2624
- const inputId = (0, import_react19.useRef)(`rf-df-${Math.random().toString(36).substring(2, 11)}`).current;
2625
- (0, import_react19.useEffect)(() => {
2626
- if (value === void 0) return;
2627
- if (!value) {
2628
- setSelectedDate(null);
2629
- setInputStr("");
2630
- return;
2631
- }
2632
- const d = isoToDate(value);
2633
- setSelectedDate(d);
2634
- if (d) {
2635
- setViewYear(d.getFullYear());
2636
- setViewMonth(d.getMonth());
2637
- let str = formatDisplay(d, dateFormat);
2638
- if (isDatetimeType(type)) {
2639
- const t = parseTimeFromISO(value);
2640
- setHour(t.h);
2641
- setMinute(t.m);
2642
- setAmpm(t.ampm);
2643
- str += " " + formatTimeDisplay(t.h, t.m, t.ampm);
2644
- }
2645
- setInputStr(str);
2646
- }
2647
- }, [value, type]);
2648
- (0, import_react19.useEffect)(() => {
2649
- if (!open) return;
2650
- const handler = (e) => {
2651
- const target = e.target;
2652
- if (containerRef.current?.contains(target)) return;
2653
- if (pickerRef.current?.contains(target)) return;
2654
- setOpen(false);
2655
- };
2656
- document.addEventListener("mousedown", handler);
2657
- return () => document.removeEventListener("mousedown", handler);
2658
- }, [open]);
2659
- (0, import_react19.useEffect)(() => {
2660
- if (!open || !containerRef.current) return;
2661
- const rect = containerRef.current.getBoundingClientRect();
2662
- const spaceBelow = window.innerHeight - rect.bottom;
2663
- const pickerHeight = 400;
2664
- setDropUp(spaceBelow < pickerHeight && rect.top > pickerHeight);
2665
- }, [open]);
2666
- const commitDate = (0, import_react19.useCallback)((d, h, m, ap) => {
2667
- setSelectedDate(d);
2668
- if (!d) {
2669
- setInputStr("");
2670
- onChange?.("");
2671
- return;
2672
- }
2673
- let str = formatDisplay(d, dateFormat);
2674
- if (isDatetimeType(type)) str += " " + formatTimeDisplay(h, m, ap);
2675
- setInputStr(str);
2676
- onChange?.(buildISO(d, type, h, m, ap));
2677
- }, [type, onChange, dateFormat]);
2678
- const handleDayClick = (day) => {
2679
- const d = new Date(viewYear, viewMonth, day);
2680
- setSelectedDate(d);
2681
- let str = formatDisplay(d, dateFormat);
2682
- if (isDatetimeType(type)) str += " " + formatTimeDisplay(hour, minute, ampm);
2683
- setInputStr(str);
2684
- onChange?.(buildISO(d, type, hour, minute, ampm));
2685
- if (type === "date") setOpen(false);
2686
- };
2687
- const handleToday = () => {
2688
- const t = today();
2689
- setViewYear(t.getFullYear());
2690
- setViewMonth(t.getMonth());
2691
- commitDate(t, hour, minute, ampm);
2692
- if (type === "date") setOpen(false);
2693
- };
2694
- const handleClear = () => commitDate(null, hour, minute, ampm);
2695
- const handleInputChange = (e) => {
2696
- const raw = e.target.value;
2697
- setInputStr(raw);
2698
- const parts = raw.split(" ");
2699
- const datePart = parts[0];
2700
- const parsed = parseDisplay(datePart, dateFormat);
2701
- if (parsed) {
2702
- setSelectedDate(parsed);
2703
- setViewYear(parsed.getFullYear());
2704
- setViewMonth(parsed.getMonth());
2705
- let h = hour, m = minute, ap = ampm;
2706
- if (isDatetimeType(type) && parts.length >= 3) {
2707
- const timePart = parts[1];
2708
- const periodPart = parts[2]?.toUpperCase();
2709
- if (timePart?.includes(":")) {
2710
- const [hStr, mStr] = timePart.split(":");
2711
- const parsedH = parseInt(hStr, 10);
2712
- const parsedM = parseInt(mStr, 10);
2713
- if (!isNaN(parsedH) && parsedH >= 1 && parsedH <= 12) {
2714
- h = parsedH;
2715
- setHour(h);
2716
- }
2717
- if (!isNaN(parsedM) && parsedM >= 0 && parsedM <= 59) {
2718
- m = parsedM;
2719
- setMinute(m);
2720
- }
2721
- }
2722
- if (periodPart === "AM" || periodPart === "PM") {
2723
- ap = periodPart;
2724
- setAmpm(ap);
2725
- }
2726
- }
2727
- onChange?.(buildISO(parsed, type, h, m, ap));
2728
- } else if (!raw) {
2729
- setSelectedDate(null);
2730
- onChange?.("");
2731
- }
2732
- };
2733
- const handleHourChange = (delta) => {
2734
- const h = (hour - 1 + delta + 12) % 12 + 1;
2735
- setHour(h);
2736
- if (selectedDate) commitDate(selectedDate, h, minute, ampm);
2737
- };
2738
- const handleMinuteChange = (delta) => {
2739
- const m = (minute + delta + 60) % 60;
2740
- setMinute(m);
2741
- if (selectedDate) commitDate(selectedDate, hour, m, ampm);
2742
- };
2743
- const handleAmpmToggle = (val) => {
2744
- setAmpm(val);
2745
- if (selectedDate) commitDate(selectedDate, hour, minute, val);
2746
- };
2747
- const handleHourInput = (e) => {
2748
- let v = parseInt(e.target.value, 10);
2749
- if (isNaN(v)) return;
2750
- v = Math.max(1, Math.min(12, v));
2751
- setHour(v);
2752
- if (selectedDate) commitDate(selectedDate, v, minute, ampm);
2753
- };
2754
- const handleMinuteInput = (e) => {
2755
- let v = parseInt(e.target.value, 10);
2756
- if (isNaN(v)) return;
2757
- v = Math.max(0, Math.min(59, v));
2758
- setMinute(v);
2759
- if (selectedDate) commitDate(selectedDate, hour, v, ampm);
2760
- };
2761
- const handleScrollHour = (idx) => {
2762
- const h = idx + 1;
2763
- setHour(h);
2764
- if (selectedDate) commitDate(selectedDate, h, minute, ampm);
2765
- };
2766
- const handleScrollMinute = (idx) => {
2767
- setMinute(idx);
2768
- if (selectedDate) commitDate(selectedDate, hour, idx, ampm);
2769
- };
2770
- const handleScrollAmpm = (idx) => {
2771
- const ap = AMPMS[idx];
2772
- setAmpm(ap);
2773
- if (selectedDate) commitDate(selectedDate, hour, minute, ap);
2774
- };
2775
- const prevMonth = () => {
2776
- if (viewMonth === 0) {
2777
- setViewMonth(11);
2778
- setViewYear((y) => y - 1);
2779
- } else setViewMonth((m) => m - 1);
2780
- };
2781
- const nextMonth = () => {
2782
- if (viewMonth === 11) {
2783
- setViewMonth(0);
2784
- setViewYear((y) => y + 1);
2785
- } else setViewMonth((m) => m + 1);
2786
- };
2787
- const firstDayOfWeek = new Date(viewYear, viewMonth, 1).getDay();
2788
- const daysInMonth = new Date(viewYear, viewMonth + 1, 0).getDate();
2789
- const dayCells = [
2790
- ...Array(firstDayOfWeek).fill(null),
2791
- ...Array.from({ length: daysInMonth }, (_, i) => i + 1)
2792
- ];
2793
- const isFloating = Boolean(inputStr || open);
2794
- const rootClasses = [
2795
- "rf-text-field",
2796
- `rf-text-field--${variant}`,
2797
- `rf-text-field--${size}`,
2798
- `rf-text-field--${color}`,
2799
- error ? "rf-text-field--error" : "",
2800
- fullWidth ? "rf-text-field--full-width" : "",
2801
- disabled ? "rf-text-field--disabled" : "",
2802
- isFloating ? "rf-text-field--floating" : "",
2803
- Boolean(label) ? "rf-text-field--has-label" : "",
2804
- variant !== "compact" ? "rf-text-field--adorned-end" : "",
2805
- "rf-date-field",
2806
- fullWidth ? "rf-date-field--full-width" : "",
2807
- sxClass,
2808
- className
2809
- ].filter(Boolean).join(" ");
2810
- const inputPlaceholder = placeholder || (variant === "outlined" ? " " : void 0);
2811
- const todayDate = today();
2812
- const isSideVariant = type === "datetime-side" || type === "datetime-scroll";
2813
- return /* @__PURE__ */ import_react19.default.createElement("div", { ref: containerRef, className: rootClasses, style }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-field__anchor" }, /* @__PURE__ */ import_react19.default.createElement(
2814
- "div",
2815
- {
2816
- className: "rf-text-field__wrapper",
2817
- onClick: () => {
2818
- if (!disabled) setOpen((o) => !o);
2198
+ multiple && visibleTags.map((opt, i) => /* @__PURE__ */ import_react18.default.createElement("span", { key: i, className: "rf-autocomplete__tag" }, /* @__PURE__ */ import_react18.default.createElement("span", { style: { overflow: "hidden", textOverflow: "ellipsis" } }, getOptionLabel(opt)), /* @__PURE__ */ import_react18.default.createElement(
2199
+ "button",
2200
+ {
2201
+ type: "button",
2202
+ className: "rf-autocomplete__tag-delete",
2203
+ onMouseDown: (e) => e.preventDefault(),
2204
+ onClick: (e) => removeTag(opt, e),
2205
+ tabIndex: -1
2819
2206
  },
2820
- style: { cursor: disabled ? "default" : "pointer" }
2821
- },
2822
- /* @__PURE__ */ import_react19.default.createElement(
2207
+ /* @__PURE__ */ import_react18.default.createElement(CloseSmIcon, { size: 12 })
2208
+ ))),
2209
+ hiddenCount > 0 && /* @__PURE__ */ import_react18.default.createElement("span", { className: "rf-autocomplete__tag-more" }, "+", hiddenCount, " more"),
2210
+ /* @__PURE__ */ import_react18.default.createElement(
2823
2211
  "input",
2824
2212
  {
2213
+ ref: inputRef,
2825
2214
  id: inputId,
2826
2215
  className: "rf-text-field__input",
2827
2216
  type: "text",
2828
- value: inputStr,
2217
+ value: activeInput,
2829
2218
  onChange: handleInputChange,
2830
- placeholder: inputPlaceholder,
2831
- disabled,
2832
- onClick: (e) => e.stopPropagation(),
2833
2219
  onFocus: () => {
2834
- if (!disabled) setOpen(true);
2835
- }
2220
+ if (!open) openPopup();
2221
+ },
2222
+ onKeyDown: handleKeyDown,
2223
+ placeholder: !multiple || selectedValues.length === 0 ? inputPlaceholder : void 0,
2224
+ disabled,
2225
+ autoComplete: "off",
2226
+ role: "combobox",
2227
+ "aria-expanded": open,
2228
+ "aria-haspopup": "listbox",
2229
+ "aria-autocomplete": "list"
2836
2230
  }
2837
2231
  ),
2838
- /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-text-field__adornment rf-text-field__adornment--end" }, /* @__PURE__ */ import_react19.default.createElement(
2232
+ label && /* @__PURE__ */ import_react18.default.createElement("label", { htmlFor: inputId, className: "rf-text-field__label" }, label, required && /* @__PURE__ */ import_react18.default.createElement("span", { className: "rf-text-field__asterisk" }, " *")),
2233
+ variant === "outlined" && /* @__PURE__ */ import_react18.default.createElement("fieldset", { className: "rf-text-field__notch" }, label ? /* @__PURE__ */ import_react18.default.createElement("legend", { className: "rf-text-field__legend" }, /* @__PURE__ */ import_react18.default.createElement("span", null, label, required ? " *" : "")) : /* @__PURE__ */ import_react18.default.createElement("legend", { className: "rf-text-field__legend--empty" })),
2234
+ /* @__PURE__ */ import_react18.default.createElement("div", { className: "rf-autocomplete__endgroup" }, hasClearable && /* @__PURE__ */ import_react18.default.createElement(
2839
2235
  "button",
2840
2236
  {
2841
2237
  type: "button",
2842
- className: "rf-date-field__icon-btn",
2238
+ className: "rf-autocomplete__icon-btn",
2239
+ onMouseDown: (e) => e.preventDefault(),
2240
+ onClick: clearAll,
2843
2241
  tabIndex: -1,
2844
- disabled,
2845
- onClick: (e) => {
2846
- e.stopPropagation();
2847
- if (!disabled) setOpen((o) => !o);
2242
+ "aria-label": "Clear"
2243
+ },
2244
+ /* @__PURE__ */ import_react18.default.createElement(CloseSmIcon, { size: 16 })
2245
+ ), !freeSolo && /* @__PURE__ */ import_react18.default.createElement(
2246
+ "button",
2247
+ {
2248
+ type: "button",
2249
+ className: `rf-autocomplete__icon-btn rf-autocomplete__icon-btn--popup ${open ? "rf-autocomplete__icon-btn--open" : ""}`,
2250
+ onMouseDown: (e) => {
2251
+ e.preventDefault();
2252
+ open ? closePopup() : openPopup();
2848
2253
  },
2849
- "aria-label": "Pick date"
2254
+ tabIndex: -1,
2255
+ "aria-label": open ? "Close" : "Open"
2850
2256
  },
2851
- /* @__PURE__ */ import_react19.default.createElement(CalendarIcon, null)
2852
- )),
2853
- label && /* @__PURE__ */ import_react19.default.createElement("label", { htmlFor: inputId, className: "rf-text-field__label" }, label, " ", required && /* @__PURE__ */ import_react19.default.createElement("span", { className: "rf-text-field__asterisk" }, "*")),
2854
- variant === "outlined" && /* @__PURE__ */ import_react19.default.createElement("fieldset", { className: "rf-text-field__notch" }, label && /* @__PURE__ */ import_react19.default.createElement("legend", { className: "rf-text-field__legend" }, /* @__PURE__ */ import_react19.default.createElement("span", null, label, required ? " *" : "")))
2855
- ), open && !disabled && (0, import_react_dom2.createPortal)(
2856
- /* @__PURE__ */ import_react19.default.createElement(
2857
- "div",
2257
+ /* @__PURE__ */ import_react18.default.createElement(ChevronDownIcon, null)
2258
+ ))
2259
+ ), helperText && /* @__PURE__ */ import_react18.default.createElement("div", { className: `rf-text-field__helper-text${error ? " rf-text-field__helper-text--error" : ""}` }, helperText), open && !disabled && import_react_dom2.default.createPortal(
2260
+ /* @__PURE__ */ import_react18.default.createElement("div", { ref: popupRef, className: "rf-autocomplete__popup", role: "presentation", style: popupStyle }, loading ? /* @__PURE__ */ import_react18.default.createElement("div", { className: "rf-autocomplete__loading" }, /* @__PURE__ */ import_react18.default.createElement("span", { className: "rf-ac-spinner" }), loadingText) : flatEntries.length === 0 ? /* @__PURE__ */ import_react18.default.createElement("div", { className: "rf-autocomplete__no-options" }, noOptionsText) : /* @__PURE__ */ import_react18.default.createElement("ul", { ref: listRef, className: "rf-autocomplete__listbox", role: "listbox" }, groupBy ? (
2261
+ // Grouped render
2262
+ (() => {
2263
+ const rendered = [];
2264
+ let groupItems = [];
2265
+ let currentGroup = "";
2266
+ flatEntries.forEach((entry, ei) => {
2267
+ if (entry.kind === "group") {
2268
+ if (groupItems.length > 0) {
2269
+ rendered.push(
2270
+ /* @__PURE__ */ import_react18.default.createElement("li", { key: `g-${currentGroup}`, role: "presentation" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "rf-autocomplete__group-header" }, currentGroup), /* @__PURE__ */ import_react18.default.createElement("ul", { className: "rf-autocomplete__group-items", role: "group" }, groupItems))
2271
+ );
2272
+ groupItems = [];
2273
+ }
2274
+ currentGroup = entry.label;
2275
+ } else {
2276
+ const { option, flatIdx } = entry;
2277
+ groupItems.push(renderOptionItem(option, flatIdx));
2278
+ }
2279
+ if (ei === flatEntries.length - 1 && groupItems.length > 0) {
2280
+ rendered.push(
2281
+ /* @__PURE__ */ import_react18.default.createElement("li", { key: `g-${currentGroup}`, role: "presentation" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "rf-autocomplete__group-header" }, currentGroup), /* @__PURE__ */ import_react18.default.createElement("ul", { className: "rf-autocomplete__group-items", role: "group" }, groupItems))
2282
+ );
2283
+ }
2284
+ });
2285
+ return rendered;
2286
+ })()
2287
+ ) : selectableOptions.map(({ option, flatIdx }) => renderOptionItem(option, flatIdx)))),
2288
+ document.body
2289
+ ));
2290
+ function renderOptionItem(option, flatIdx) {
2291
+ const selected = isSelected(option);
2292
+ const focused = focusedIdx === flatIdx;
2293
+ const optDisabled = getOptionDisabled?.(option) ?? false;
2294
+ const label2 = getOptionLabel(option);
2295
+ return /* @__PURE__ */ import_react18.default.createElement(
2296
+ "li",
2858
2297
  {
2859
- ref: pickerRef,
2298
+ key: label2 + flatIdx,
2299
+ "data-idx": flatIdx,
2300
+ role: "option",
2301
+ "aria-selected": selected,
2302
+ "aria-disabled": optDisabled,
2860
2303
  className: [
2861
- "rf-date-picker",
2862
- "rf-date-picker--portaled",
2863
- isSideVariant ? "rf-date-picker--side" : "",
2864
- dropUp ? "rf-date-picker--drop-up" : ""
2304
+ "rf-autocomplete__option",
2305
+ selected ? "rf-autocomplete__option--selected" : "",
2306
+ focused ? "rf-autocomplete__option--focused" : "",
2307
+ optDisabled ? "rf-autocomplete__option--disabled" : ""
2865
2308
  ].filter(Boolean).join(" "),
2866
- style: (() => {
2867
- const rect = containerRef.current?.getBoundingClientRect();
2868
- if (!rect) return {};
2869
- const top = rect.bottom + 6;
2870
- const spaceBelow = window.innerHeight - rect.bottom - 6;
2871
- const useDropUp = spaceBelow < 350 && rect.top > spaceBelow;
2872
- return {
2873
- position: "fixed",
2874
- left: rect.left,
2875
- ...useDropUp ? { bottom: window.innerHeight - rect.top + 6 } : { top },
2876
- zIndex: 99999
2877
- };
2878
- })(),
2879
- onMouseDown: (e) => e.preventDefault()
2309
+ onMouseEnter: () => setFocusedIdx(flatIdx),
2310
+ onMouseLeave: () => setFocusedIdx(-1),
2311
+ onMouseDown: (e) => e.preventDefault(),
2312
+ onClick: () => selectOption(option)
2880
2313
  },
2881
- /* @__PURE__ */ import_react19.default.createElement("div", { className: isSideVariant ? "rf-date-picker__cal-col" : void 0 }, /* @__PURE__ */ import_react19.default.createElement(
2882
- CalendarBody,
2883
- {
2884
- viewMonth,
2885
- viewYear,
2886
- selectedDate,
2887
- todayDate,
2888
- dayCells,
2889
- onDayClick: handleDayClick,
2890
- onPrev: prevMonth,
2891
- onNext: nextMonth,
2892
- onMonthSelect: setViewMonth,
2893
- onYearSelect: setViewYear
2894
- }
2895
- ), type === "datetime" && /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__time-section" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__time-label" }, "Time"), /* @__PURE__ */ import_react19.default.createElement(
2896
- SpinnerPanel,
2897
- {
2898
- hour,
2899
- minute,
2900
- ampm,
2901
- onHourChange: handleHourChange,
2902
- onMinuteChange: handleMinuteChange,
2903
- onHourInput: handleHourInput,
2904
- onMinuteInput: handleMinuteInput,
2905
- onAmpmToggle: handleAmpmToggle
2906
- }
2907
- )), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__divider" }), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__footer" }, /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", className: "rf-date-picker__footer-btn", onClick: handleToday }, "Today"), /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", className: "rf-date-picker__footer-btn rf-date-picker__footer-btn--clear", onClick: handleClear }, "Clear"))),
2908
- type === "datetime-side" && /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-spinner" }, /* @__PURE__ */ import_react19.default.createElement(
2909
- SpinnerPanel,
2910
- {
2911
- hour,
2912
- minute,
2913
- ampm,
2914
- onHourChange: handleHourChange,
2915
- onMinuteChange: handleMinuteChange,
2916
- onHourInput: handleHourInput,
2917
- onMinuteInput: handleMinuteInput,
2918
- onAmpmToggle: handleAmpmToggle
2314
+ renderOption ? renderOption(option, { selected, focused, index: flatIdx }) : /* @__PURE__ */ import_react18.default.createElement("span", { style: { flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, label2),
2315
+ !renderOption && /* @__PURE__ */ import_react18.default.createElement("span", { className: "rf-autocomplete__option-check" }, /* @__PURE__ */ import_react18.default.createElement(CheckIcon, null))
2316
+ );
2317
+ }
2318
+ }
2319
+ var Autocomplete = import_react18.default.forwardRef(AutocompleteInner);
2320
+ Autocomplete.displayName = "Autocomplete";
2321
+
2322
+ // lib/TextFields/AddressLookup.tsx
2323
+ var AddressLookup = ({
2324
+ value = {},
2325
+ onChange = () => {
2326
+ },
2327
+ label = "Address",
2328
+ error = {},
2329
+ size = "medium",
2330
+ sx = {},
2331
+ layout = "stack",
2332
+ required = false,
2333
+ token = ""
2334
+ }) => {
2335
+ const { theme } = useRufousTheme();
2336
+ const [suggestions, setSuggestions] = (0, import_react19.useState)([]);
2337
+ const [loading, setLoading] = (0, import_react19.useState)(false);
2338
+ const [showSuggestions, setShowSuggestions] = (0, import_react19.useState)(false);
2339
+ const debounceTimeout = (0, import_react19.useRef)(null);
2340
+ const containerRef = (0, import_react19.useRef)(null);
2341
+ const apiKey = token || "";
2342
+ const countries = import_country_state_city.Country.getAllCountries();
2343
+ const [states, setStates] = (0, import_react19.useState)([]);
2344
+ const [cities, setCities] = (0, import_react19.useState)([]);
2345
+ (0, import_react19.useEffect)(() => {
2346
+ const handleClickOutside = (event) => {
2347
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
2348
+ setShowSuggestions(false);
2349
+ }
2350
+ };
2351
+ document.addEventListener("mousedown", handleClickOutside);
2352
+ return () => document.removeEventListener("mousedown", handleClickOutside);
2353
+ }, []);
2354
+ (0, import_react19.useEffect)(() => {
2355
+ if (value.country) {
2356
+ const country = countries.find((c) => c.name === value.country);
2357
+ if (country) {
2358
+ const stateList = import_country_state_city.State.getStatesOfCountry(country.isoCode);
2359
+ setStates(stateList);
2360
+ } else {
2361
+ setStates([]);
2362
+ }
2363
+ } else {
2364
+ setStates([]);
2365
+ }
2366
+ }, [value.country]);
2367
+ (0, import_react19.useEffect)(() => {
2368
+ if (value.state && value.country) {
2369
+ const country = countries.find((c) => c.name === value.country);
2370
+ if (country) {
2371
+ const state = import_country_state_city.State.getStatesOfCountry(country.isoCode).find((s2) => s2.name === value.state);
2372
+ if (state) {
2373
+ const cityList = import_country_state_city.City.getCitiesOfState(country.isoCode, state.isoCode);
2374
+ setCities(cityList);
2375
+ } else {
2376
+ setCities([]);
2919
2377
  }
2920
- )), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm)),
2921
- type === "datetime-scroll" && /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-timescroll" }, /* @__PURE__ */ import_react19.default.createElement(
2922
- ScrollColumn,
2378
+ } else {
2379
+ setCities([]);
2380
+ }
2381
+ } else {
2382
+ setCities([]);
2383
+ }
2384
+ }, [value.state, value.country]);
2385
+ const handleChange = (field, newVal) => {
2386
+ onChange({
2387
+ ...value,
2388
+ [field]: newVal
2389
+ });
2390
+ };
2391
+ const fetchPlaceDetails = async (placeId, mainText = "") => {
2392
+ if (!apiKey) {
2393
+ console.warn("Google Places API Key (token) is missing.");
2394
+ return;
2395
+ }
2396
+ setLoading(true);
2397
+ try {
2398
+ const res = await import_axios.default.get(
2399
+ `https://places.googleapis.com/v1/places/${placeId}`,
2923
2400
  {
2924
- items: HOURS,
2925
- selected: hour - 1,
2926
- onSelect: handleScrollHour
2401
+ headers: {
2402
+ "Content-Type": "application/json",
2403
+ "X-Goog-Api-Key": apiKey,
2404
+ "X-Goog-FieldMask": "addressComponents,formattedAddress"
2405
+ }
2927
2406
  }
2928
- ), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-timescroll__colon" }, ":"), /* @__PURE__ */ import_react19.default.createElement(
2929
- ScrollColumn,
2407
+ );
2408
+ const comps = res.data.addressComponents || [];
2409
+ const findComp = (type) => comps.find((c) => c.types.includes(type))?.longText || "";
2410
+ const city = findComp("locality") || findComp("sublocality_level_1");
2411
+ const state = findComp("administrative_area_level_1");
2412
+ const country = findComp("country");
2413
+ const pincode = findComp("postal_code");
2414
+ const updatedData = {
2415
+ ...value,
2416
+ addressLine1: mainText || value.addressLine1,
2417
+ addressLine2: res.data.formattedAddress || value.addressLine2,
2418
+ city,
2419
+ state,
2420
+ country,
2421
+ pincode
2422
+ };
2423
+ onChange(updatedData);
2424
+ setShowSuggestions(false);
2425
+ } catch (err) {
2426
+ console.error("Error fetching place details:", err);
2427
+ } finally {
2428
+ setLoading(false);
2429
+ }
2430
+ };
2431
+ const handleQuerySuggestions = async (query) => {
2432
+ if (!apiKey || !query || query.length < 3) {
2433
+ setSuggestions([]);
2434
+ setShowSuggestions(false);
2435
+ return;
2436
+ }
2437
+ setLoading(true);
2438
+ try {
2439
+ const res = await import_axios.default.post(
2440
+ `https://places.googleapis.com/v1/places:autocomplete`,
2441
+ { input: query },
2930
2442
  {
2931
- items: MINUTES,
2932
- selected: minute,
2933
- onSelect: handleScrollMinute
2443
+ headers: {
2444
+ "Content-Type": "application/json",
2445
+ "X-Goog-Api-Key": apiKey
2446
+ }
2934
2447
  }
2935
- ), /* @__PURE__ */ import_react19.default.createElement(
2936
- ScrollColumn,
2937
- {
2938
- items: AMPMS,
2939
- selected: ampm === "AM" ? 0 : 1,
2940
- onSelect: handleScrollAmpm,
2941
- infinite: false
2448
+ );
2449
+ setSuggestions(res.data.suggestions || []);
2450
+ setShowSuggestions(true);
2451
+ } catch (err) {
2452
+ console.error("Autocomplete Error:", err);
2453
+ } finally {
2454
+ setLoading(false);
2455
+ }
2456
+ };
2457
+ const handleCountryChange = (newCountry) => {
2458
+ onChange({
2459
+ ...value,
2460
+ country: newCountry,
2461
+ state: "",
2462
+ city: ""
2463
+ });
2464
+ };
2465
+ const handleStateChange = (newState) => {
2466
+ onChange({
2467
+ ...value,
2468
+ state: newState,
2469
+ city: ""
2470
+ });
2471
+ };
2472
+ return /* @__PURE__ */ import_react19.default.createElement("div", { className: "address-lookup-container", style: sx, ref: containerRef }, /* @__PURE__ */ import_react19.default.createElement("div", { className: `address-lookup-grid address-lookup-grid-${layout}` }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "address-lookup-grid-item col-l1" }, /* @__PURE__ */ import_react19.default.createElement(
2473
+ TextField,
2474
+ {
2475
+ label,
2476
+ name: "addressLine1",
2477
+ fullWidth: true,
2478
+ value: value.addressLine1 || "",
2479
+ required,
2480
+ autoComplete: "off",
2481
+ onChange: (e) => {
2482
+ const val = e.target.value;
2483
+ handleChange("addressLine1", val);
2484
+ if (!val) {
2485
+ onChange({
2486
+ ...value,
2487
+ addressLine1: "",
2488
+ city: "",
2489
+ state: "",
2490
+ country: "",
2491
+ pincode: ""
2492
+ });
2493
+ setSuggestions([]);
2494
+ setShowSuggestions(false);
2495
+ } else {
2496
+ if (debounceTimeout.current) clearTimeout(debounceTimeout.current);
2497
+ debounceTimeout.current = setTimeout(() => {
2498
+ handleQuerySuggestions(val);
2499
+ }, 500);
2942
2500
  }
2943
- )), /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm))
2944
- ),
2945
- document.body
2946
- )), helperText && /* @__PURE__ */ import_react19.default.createElement("div", { className: "rf-text-field__helper-text" }, helperText));
2501
+ },
2502
+ onFocus: () => suggestions.length > 0 && setShowSuggestions(true)
2503
+ }
2504
+ ), loading && /* @__PURE__ */ import_react19.default.createElement("div", { className: "loading-indicator" }, /* @__PURE__ */ import_react19.default.createElement(circularProgress_default, { size: 20 })), showSuggestions && suggestions.length > 0 && /* @__PURE__ */ import_react19.default.createElement("div", { className: "autocomplete-dropdown" }, suggestions.map((option, idx) => /* @__PURE__ */ import_react19.default.createElement(
2505
+ "div",
2506
+ {
2507
+ key: idx,
2508
+ className: "autocomplete-option",
2509
+ onClick: () => {
2510
+ const mainText = option?.placePrediction?.structuredFormat?.mainText?.text || "";
2511
+ handleChange("addressLine1", mainText);
2512
+ fetchPlaceDetails(option.placePrediction.placeId, mainText);
2513
+ }
2514
+ },
2515
+ /* @__PURE__ */ import_react19.default.createElement("div", { className: "autocomplete-main-text" }, option?.placePrediction?.structuredFormat?.mainText?.text),
2516
+ /* @__PURE__ */ import_react19.default.createElement("div", { className: "autocomplete-secondary-text" }, option?.placePrediction?.structuredFormat?.secondaryText?.text)
2517
+ ))), error.addressLine1 && /* @__PURE__ */ import_react19.default.createElement("div", { className: "field-error-text" }, error.addressLine1)), layout === "compact" && /* @__PURE__ */ import_react19.default.createElement("div", { className: "address-lookup-grid-item col-l2" }, /* @__PURE__ */ import_react19.default.createElement(
2518
+ TextField,
2519
+ {
2520
+ label: "Address Line 2",
2521
+ name: "addressLine2",
2522
+ fullWidth: true,
2523
+ value: value.addressLine2 || "",
2524
+ onChange: (e) => handleChange("addressLine2", e.target.value)
2525
+ }
2526
+ )), layout !== "compact" && /* @__PURE__ */ import_react19.default.createElement("div", { className: "address-lookup-grid-item col-l2" }, /* @__PURE__ */ import_react19.default.createElement(
2527
+ TextField,
2528
+ {
2529
+ label: "Address Line 2",
2530
+ name: "addressLine2",
2531
+ fullWidth: true,
2532
+ value: value.addressLine2 || "",
2533
+ onChange: (e) => handleChange("addressLine2", e.target.value)
2534
+ }
2535
+ )), /* @__PURE__ */ import_react19.default.createElement("div", { className: "address-lookup-grid-item col-country" }, /* @__PURE__ */ import_react19.default.createElement(
2536
+ Autocomplete,
2537
+ {
2538
+ options: countries.map((c) => c.name),
2539
+ value: value.country || null,
2540
+ onChange: (v) => handleCountryChange(v || ""),
2541
+ label: "Country",
2542
+ fullWidth: true,
2543
+ required,
2544
+ error: !!error.country
2545
+ }
2546
+ ), error.country && /* @__PURE__ */ import_react19.default.createElement("div", { className: "field-error-text" }, error.country)), /* @__PURE__ */ import_react19.default.createElement("div", { className: "address-lookup-grid-item col-state" }, /* @__PURE__ */ import_react19.default.createElement(
2547
+ Autocomplete,
2548
+ {
2549
+ options: states.map((s2) => s2.name),
2550
+ value: value.state || null,
2551
+ onChange: (v) => handleStateChange(v || ""),
2552
+ label: "State",
2553
+ fullWidth: true,
2554
+ required,
2555
+ error: !!error.state
2556
+ }
2557
+ ), error.state && /* @__PURE__ */ import_react19.default.createElement("div", { className: "field-error-text" }, error.state)), /* @__PURE__ */ import_react19.default.createElement("div", { className: "address-lookup-grid-item col-city" }, /* @__PURE__ */ import_react19.default.createElement(
2558
+ Autocomplete,
2559
+ {
2560
+ options: cities.map((c) => c.name),
2561
+ value: value.city || null,
2562
+ onChange: (v) => handleChange("city", v || ""),
2563
+ label: "City",
2564
+ fullWidth: true,
2565
+ required,
2566
+ error: !!error.city
2567
+ }
2568
+ ), error.city && /* @__PURE__ */ import_react19.default.createElement("div", { className: "field-error-text" }, error.city)), /* @__PURE__ */ import_react19.default.createElement("div", { className: "address-lookup-grid-item col-pin" }, /* @__PURE__ */ import_react19.default.createElement(
2569
+ TextField,
2570
+ {
2571
+ label: "Pincode",
2572
+ name: "pincode",
2573
+ fullWidth: true,
2574
+ value: value.pincode || "",
2575
+ required,
2576
+ onChange: (e) => handleChange("pincode", e.target.value)
2577
+ }
2578
+ ), error.pincode && /* @__PURE__ */ import_react19.default.createElement("div", { className: "field-error-text" }, error.pincode))));
2947
2579
  };
2948
- DateField.displayName = "DateField";
2580
+ var AddressLookup_default = AddressLookup;
2949
2581
 
2950
- // lib/TextFields/DateRangeField.tsx
2582
+ // lib/TextFields/DateField.tsx
2951
2583
  var import_react20 = __toESM(require("react"), 1);
2952
- var WEEKDAYS2 = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"];
2953
- var MONTHS2 = [
2584
+ var import_react_dom3 = require("react-dom");
2585
+ var WEEKDAYS = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"];
2586
+ var MONTHS = [
2954
2587
  "January",
2955
2588
  "February",
2956
2589
  "March",
@@ -2964,7 +2597,7 @@ var MONTHS2 = [
2964
2597
  "November",
2965
2598
  "December"
2966
2599
  ];
2967
- var MONTHS_SHORT2 = [
2600
+ var MONTHS_SHORT = [
2968
2601
  "Jan",
2969
2602
  "Feb",
2970
2603
  "Mar",
@@ -2976,242 +2609,354 @@ var MONTHS_SHORT2 = [
2976
2609
  "Sep",
2977
2610
  "Oct",
2978
2611
  "Nov",
2979
- "Dec"
2980
- ];
2981
- var PRESETS = [
2982
- { id: "today", label: "Today" },
2983
- { id: "this_week", label: "This week" },
2984
- { id: "this_month", label: "This month" },
2985
- { id: "till_date", label: "Till date" },
2986
- { id: "all", label: "All" }
2987
- ];
2988
- var todayFn = () => {
2989
- const t = /* @__PURE__ */ new Date();
2990
- return new Date(t.getFullYear(), t.getMonth(), t.getDate());
2612
+ "Dec"
2613
+ ];
2614
+ var formatDisplay = (d, fmt = "MM/DD/YYYY") => {
2615
+ const mm = String(d.getMonth() + 1).padStart(2, "0");
2616
+ const dd = String(d.getDate()).padStart(2, "0");
2617
+ const yyyy = String(d.getFullYear());
2618
+ const day = d.getDate();
2619
+ switch (fmt) {
2620
+ case "DD/MM/YYYY":
2621
+ return `${dd}/${mm}/${yyyy}`;
2622
+ case "YYYY-MM-DD":
2623
+ return `${yyyy}-${mm}-${dd}`;
2624
+ case "DD-MM-YYYY":
2625
+ return `${dd}-${mm}-${yyyy}`;
2626
+ case "MM-DD-YYYY":
2627
+ return `${mm}-${dd}-${yyyy}`;
2628
+ case "YYYY/MM/DD":
2629
+ return `${yyyy}/${mm}/${dd}`;
2630
+ case "DD MMM YYYY":
2631
+ return `${dd} ${MONTHS_SHORT[d.getMonth()]} ${yyyy}`;
2632
+ case "MMM DD, YYYY":
2633
+ return `${MONTHS_SHORT[d.getMonth()]} ${dd}, ${yyyy}`;
2634
+ case "DD MMMM YYYY":
2635
+ return `${dd} ${MONTHS[d.getMonth()]} ${yyyy}`;
2636
+ case "MMMM DD, YYYY":
2637
+ return `${MONTHS[d.getMonth()]} ${dd}, ${yyyy}`;
2638
+ case "MM/DD/YYYY":
2639
+ default:
2640
+ return `${mm}/${dd}/${yyyy}`;
2641
+ }
2991
2642
  };
2992
- var isoToDate2 = (iso) => {
2993
- if (!iso) return null;
2994
- const parts = iso.split("-").map(Number);
2995
- if (parts.length < 3 || !parts[0] || !parts[1] || !parts[2]) return null;
2996
- return new Date(parts[0], parts[1] - 1, parts[2]);
2643
+ var formatTimeDisplay = (h, m, ampm) => `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")} ${ampm}`;
2644
+ var parseMonthName = (name) => {
2645
+ const lower = name.toLowerCase();
2646
+ let idx = MONTHS.findIndex((m) => m.toLowerCase() === lower);
2647
+ if (idx >= 0) return idx;
2648
+ idx = MONTHS_SHORT.findIndex((m) => m.toLowerCase() === lower);
2649
+ return idx;
2997
2650
  };
2998
- var dateToISO = (d) => {
2999
- const y = d.getFullYear();
3000
- const mo = String(d.getMonth() + 1).padStart(2, "0");
3001
- const dd = String(d.getDate()).padStart(2, "0");
3002
- return `${y}-${mo}-${dd}`;
2651
+ var strictDate = (yyyy, mm0, dd) => {
2652
+ if (dd < 1 || dd > 31 || mm0 < 0 || mm0 > 11) return null;
2653
+ const d = new Date(yyyy, mm0, dd);
2654
+ if (isNaN(d.getTime())) return null;
2655
+ if (d.getMonth() !== mm0 || d.getDate() !== dd) return null;
2656
+ return d;
3003
2657
  };
3004
- var formatShort = (d) => `${String(d.getDate()).padStart(2, "0")} ${MONTHS_SHORT2[d.getMonth()]} ${d.getFullYear()}`;
3005
- var parseInputDate = (str) => {
3006
- const s2 = str.trim();
3007
- if (!s2) return null;
3008
- const shortMatch = s2.match(/^(\d{1,2})\s+([A-Za-z]+)\s+(\d{4})$/);
3009
- if (shortMatch) {
3010
- const day = parseInt(shortMatch[1], 10);
3011
- const monthIdx = MONTHS_SHORT2.findIndex((m) => m.toLowerCase() === shortMatch[2].toLowerCase());
3012
- const year = parseInt(shortMatch[3], 10);
3013
- if (monthIdx !== -1 && day >= 1 && day <= 31 && year >= 1e3) {
3014
- const d = new Date(year, monthIdx, day);
3015
- if (!isNaN(d.getTime())) return d;
3016
- }
2658
+ var parseDisplay = (str, fmt = "MM/DD/YYYY") => {
2659
+ if (fmt === "DD MMM YYYY" || fmt === "DD MMMM YYYY") {
2660
+ const parts2 = str.split(" ");
2661
+ if (parts2.length !== 3) return null;
2662
+ const dd2 = parseInt(parts2[0], 10);
2663
+ const mm2 = parseMonthName(parts2[1]);
2664
+ const yyyy2 = parseInt(parts2[2], 10);
2665
+ if (isNaN(dd2) || isNaN(yyyy2) || yyyy2 < 1e3) return null;
2666
+ return strictDate(yyyy2, mm2, dd2);
3017
2667
  }
3018
- const slashMatch = s2.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
3019
- if (slashMatch) {
3020
- const d = new Date(parseInt(slashMatch[3], 10), parseInt(slashMatch[2], 10) - 1, parseInt(slashMatch[1], 10));
3021
- if (!isNaN(d.getTime())) return d;
2668
+ if (fmt === "MMM DD, YYYY" || fmt === "MMMM DD, YYYY") {
2669
+ const cleaned = str.replace(",", "");
2670
+ const parts2 = cleaned.split(" ").filter(Boolean);
2671
+ if (parts2.length !== 3) return null;
2672
+ const mm2 = parseMonthName(parts2[0]);
2673
+ const dd2 = parseInt(parts2[1], 10);
2674
+ const yyyy2 = parseInt(parts2[2], 10);
2675
+ if (isNaN(dd2) || isNaN(yyyy2) || yyyy2 < 1e3) return null;
2676
+ return strictDate(yyyy2, mm2, dd2);
3022
2677
  }
3023
- const isoMatch = s2.match(/^(\d{4})-(\d{2})-(\d{2})$/);
3024
- if (isoMatch) {
3025
- const d = new Date(parseInt(isoMatch[1], 10), parseInt(isoMatch[2], 10) - 1, parseInt(isoMatch[3], 10));
3026
- if (!isNaN(d.getTime())) return d;
2678
+ const sep = str.includes("/") ? "/" : "-";
2679
+ const parts = str.split(sep);
2680
+ if (parts.length !== 3) return null;
2681
+ const nums = parts.map(Number);
2682
+ let yyyy, mm, dd;
2683
+ switch (fmt) {
2684
+ case "DD/MM/YYYY":
2685
+ case "DD-MM-YYYY":
2686
+ [dd, mm, yyyy] = nums;
2687
+ break;
2688
+ case "YYYY-MM-DD":
2689
+ case "YYYY/MM/DD":
2690
+ [yyyy, mm, dd] = nums;
2691
+ break;
2692
+ case "MM-DD-YYYY":
2693
+ case "MM/DD/YYYY":
2694
+ default:
2695
+ [mm, dd, yyyy] = nums;
2696
+ break;
3027
2697
  }
3028
- return null;
2698
+ if (!yyyy || yyyy < 1e3) return null;
2699
+ return strictDate(yyyy, mm - 1, dd);
3029
2700
  };
3030
- var isSameDay2 = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
3031
- var daysBetween = (a, b) => Math.round((b.getTime() - a.getTime()) / (1e3 * 60 * 60 * 24));
3032
- var addDays = (d, n) => {
3033
- const r = new Date(d.getTime());
3034
- r.setDate(r.getDate() + n);
3035
- return r;
2701
+ var isoToDate = (iso) => {
2702
+ if (!iso) return null;
2703
+ const [datePart] = iso.split("T");
2704
+ const [y, mo, d] = datePart.split("-").map(Number);
2705
+ if (!y || !mo || !d) return null;
2706
+ return new Date(y, mo - 1, d);
3036
2707
  };
3037
- var getPresetRange = (preset, currentStart) => {
3038
- const today2 = todayFn();
3039
- switch (preset) {
3040
- case "today":
3041
- return { start: dateToISO(today2), end: dateToISO(today2) };
3042
- case "this_week": {
3043
- const day = today2.getDay();
3044
- const monday = addDays(today2, day === 0 ? -6 : -(day - 1));
3045
- return { start: dateToISO(monday), end: dateToISO(addDays(monday, 6)) };
3046
- }
3047
- case "this_month": {
3048
- const start = new Date(today2.getFullYear(), today2.getMonth(), 1);
3049
- const end = new Date(today2.getFullYear(), today2.getMonth() + 1, 0);
3050
- return { start: dateToISO(start), end: dateToISO(end) };
3051
- }
3052
- case "till_date": {
3053
- const start = currentStart ?? addDays(today2, -30);
3054
- return { start: dateToISO(start), end: dateToISO(today2) };
3055
- }
3056
- case "all":
3057
- return { start: dateToISO(new Date(2e3, 0, 1)), end: dateToISO(today2) };
2708
+ var today = () => {
2709
+ const t = /* @__PURE__ */ new Date();
2710
+ return new Date(t.getFullYear(), t.getMonth(), t.getDate());
2711
+ };
2712
+ var isSameDay = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
2713
+ var isDatetimeType = (t) => t !== "date";
2714
+ var buildISO = (date, type, hour, minute, ampm) => {
2715
+ const y = date.getFullYear();
2716
+ const mo = String(date.getMonth() + 1).padStart(2, "0");
2717
+ const d = String(date.getDate()).padStart(2, "0");
2718
+ if (type === "date") return `${y}-${mo}-${d}`;
2719
+ let h24 = hour % 12;
2720
+ if (ampm === "PM") h24 += 12;
2721
+ return `${y}-${mo}-${d}T${String(h24).padStart(2, "0")}:${String(minute).padStart(2, "0")}`;
2722
+ };
2723
+ var getDateWordCount = (fmt) => {
2724
+ switch (fmt) {
2725
+ case "DD MMM YYYY":
2726
+ case "MMM DD, YYYY":
2727
+ case "DD MMMM YYYY":
2728
+ case "MMMM DD, YYYY":
2729
+ return 3;
3058
2730
  default:
3059
- return { start: "", end: "" };
2731
+ return 1;
3060
2732
  }
3061
2733
  };
3062
- var detectPreset = (start, end) => {
3063
- if (!start || !end) return null;
3064
- const today2 = todayFn();
3065
- if (isSameDay2(start, today2) && isSameDay2(end, today2)) return "today";
3066
- const day = today2.getDay();
3067
- const monday = addDays(today2, day === 0 ? -6 : -(day - 1));
3068
- if (isSameDay2(start, monday) && isSameDay2(end, addDays(monday, 6))) return "this_week";
3069
- const monthStart = new Date(today2.getFullYear(), today2.getMonth(), 1);
3070
- const monthEnd = new Date(today2.getFullYear(), today2.getMonth() + 1, 0);
3071
- if (isSameDay2(start, monthStart) && isSameDay2(end, monthEnd)) return "this_month";
3072
- if (isSameDay2(end, today2)) return "till_date";
3073
- if (isSameDay2(start, new Date(2e3, 0, 1)) && isSameDay2(end, today2)) return "all";
3074
- return null;
2734
+ var parseTimeFromISO = (iso) => {
2735
+ const timePart = iso.split("T")[1] || "";
2736
+ const [hStr, mStr] = timePart.split(":");
2737
+ let h24 = parseInt(hStr, 10) || 0;
2738
+ const m = parseInt(mStr, 10) || 0;
2739
+ const ampm = h24 < 12 ? "AM" : "PM";
2740
+ let h = h24 % 12;
2741
+ if (h === 0) h = 12;
2742
+ return { h, m, ampm };
3075
2743
  };
3076
- var CalendarIcon2 = () => /* @__PURE__ */ import_react20.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react20.default.createElement("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }), /* @__PURE__ */ import_react20.default.createElement("line", { x1: "16", y1: "2", x2: "16", y2: "6" }), /* @__PURE__ */ import_react20.default.createElement("line", { x1: "8", y1: "2", x2: "8", y2: "6" }), /* @__PURE__ */ import_react20.default.createElement("line", { x1: "3", y1: "10", x2: "21", y2: "10" }));
3077
- var RangeCalendarBody = ({
3078
- viewYear,
2744
+ var CalendarIcon = () => /* @__PURE__ */ import_react20.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react20.default.createElement("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }), /* @__PURE__ */ import_react20.default.createElement("line", { x1: "16", y1: "2", x2: "16", y2: "6" }), /* @__PURE__ */ import_react20.default.createElement("line", { x1: "8", y1: "2", x2: "8", y2: "6" }), /* @__PURE__ */ import_react20.default.createElement("line", { x1: "3", y1: "10", x2: "21", y2: "10" }));
2745
+ var ChevUp = () => /* @__PURE__ */ import_react20.default.createElement("svg", { width: "10", height: "7", viewBox: "0 0 10 7", fill: "currentColor" }, /* @__PURE__ */ import_react20.default.createElement("path", { d: "M5 0L10 7H0L5 0Z" }));
2746
+ var ChevDown = () => /* @__PURE__ */ import_react20.default.createElement("svg", { width: "10", height: "7", viewBox: "0 0 10 7", fill: "currentColor" }, /* @__PURE__ */ import_react20.default.createElement("path", { d: "M5 7L0 0H10L5 7Z" }));
2747
+ var ITEM_H = 36;
2748
+ var ScrollColumn = ({ items, selected, onSelect, infinite = true }) => {
2749
+ const listRef = (0, import_react20.useRef)(null);
2750
+ const isInternalScroll = (0, import_react20.useRef)(false);
2751
+ const scrollTimeout = (0, import_react20.useRef)(null);
2752
+ const MULTIPLIER = infinite ? 100 : 1;
2753
+ const virtualItems = infinite ? Array(MULTIPLIER).fill(items).flat() : items;
2754
+ const centerOffset = infinite ? Math.floor(MULTIPLIER / 2) * items.length : 0;
2755
+ const VISUAL_OFFSET = 54;
2756
+ (0, import_react20.useEffect)(() => {
2757
+ if (listRef.current) {
2758
+ const targetIndex = centerOffset + selected;
2759
+ listRef.current.scrollTop = targetIndex * ITEM_H - (infinite ? VISUAL_OFFSET : 0);
2760
+ }
2761
+ }, [centerOffset, infinite, selected]);
2762
+ (0, import_react20.useEffect)(() => {
2763
+ if (listRef.current && !isInternalScroll.current) {
2764
+ const targetIndex = centerOffset + selected;
2765
+ listRef.current.scrollTo({
2766
+ top: targetIndex * ITEM_H - (infinite ? VISUAL_OFFSET : 0),
2767
+ behavior: "smooth"
2768
+ });
2769
+ }
2770
+ isInternalScroll.current = false;
2771
+ }, [selected, centerOffset, infinite]);
2772
+ const handleScroll = () => {
2773
+ if (!listRef.current) return;
2774
+ const scrollTop = listRef.current.scrollTop;
2775
+ const adjustedScrollTop = infinite ? scrollTop + VISUAL_OFFSET : scrollTop;
2776
+ const index = Math.round(adjustedScrollTop / ITEM_H);
2777
+ const actualIndex = infinite ? (index % items.length + items.length) % items.length : Math.max(0, Math.min(items.length - 1, index));
2778
+ if (infinite) {
2779
+ const buffer = items.length * 10;
2780
+ if (index < buffer || index > virtualItems.length - buffer) {
2781
+ const newIndex = centerOffset + actualIndex;
2782
+ listRef.current.scrollTop = newIndex * ITEM_H - VISUAL_OFFSET;
2783
+ return;
2784
+ }
2785
+ }
2786
+ if (scrollTimeout.current) clearTimeout(scrollTimeout.current);
2787
+ scrollTimeout.current = setTimeout(() => {
2788
+ if (actualIndex !== selected) {
2789
+ isInternalScroll.current = true;
2790
+ onSelect(actualIndex);
2791
+ }
2792
+ }, 100);
2793
+ };
2794
+ return /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-timescroll__col-wrapper" }, /* @__PURE__ */ import_react20.default.createElement(
2795
+ "div",
2796
+ {
2797
+ className: "rf-timescroll__col",
2798
+ ref: listRef,
2799
+ onScroll: handleScroll
2800
+ },
2801
+ !infinite && /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-timescroll__spacer" }),
2802
+ virtualItems.map((label, idx) => /* @__PURE__ */ import_react20.default.createElement(
2803
+ "div",
2804
+ {
2805
+ key: `${label}-${idx}`,
2806
+ className: `rf-timescroll__item ${idx % items.length === selected ? "rf-timescroll__item--active" : ""}`
2807
+ },
2808
+ label
2809
+ )),
2810
+ !infinite && /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-timescroll__spacer" })
2811
+ ), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-timescroll__mask rf-timescroll__mask--top" }), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-timescroll__mask rf-timescroll__mask--bottom" }));
2812
+ };
2813
+ var SpinnerPanel = ({
2814
+ hour,
2815
+ minute,
2816
+ ampm,
2817
+ onHourChange,
2818
+ onMinuteChange,
2819
+ onHourInput,
2820
+ onMinuteInput,
2821
+ onAmpmToggle
2822
+ }) => /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__time-row" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__time-input-wrap" }, /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-date-picker__time-spin-btn", onMouseDown: (e) => e.preventDefault(), onClick: () => onHourChange(1) }, /* @__PURE__ */ import_react20.default.createElement(ChevUp, null)), /* @__PURE__ */ import_react20.default.createElement(
2823
+ "input",
2824
+ {
2825
+ type: "number",
2826
+ className: "rf-date-picker__time-digit",
2827
+ value: String(hour).padStart(2, "0"),
2828
+ min: 1,
2829
+ max: 12,
2830
+ onChange: onHourInput,
2831
+ onMouseDown: (e) => e.stopPropagation()
2832
+ }
2833
+ ), /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-date-picker__time-spin-btn", onMouseDown: (e) => e.preventDefault(), onClick: () => onHourChange(-1) }, /* @__PURE__ */ import_react20.default.createElement(ChevDown, null))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__time-colon" }, ":"), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__time-input-wrap" }, /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-date-picker__time-spin-btn", onMouseDown: (e) => e.preventDefault(), onClick: () => onMinuteChange(1) }, /* @__PURE__ */ import_react20.default.createElement(ChevUp, null)), /* @__PURE__ */ import_react20.default.createElement(
2834
+ "input",
2835
+ {
2836
+ type: "number",
2837
+ className: "rf-date-picker__time-digit",
2838
+ value: String(minute).padStart(2, "0"),
2839
+ min: 0,
2840
+ max: 59,
2841
+ onChange: onMinuteInput,
2842
+ onMouseDown: (e) => e.stopPropagation()
2843
+ }
2844
+ ), /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-date-picker__time-spin-btn", onMouseDown: (e) => e.preventDefault(), onClick: () => onMinuteChange(-1) }, /* @__PURE__ */ import_react20.default.createElement(ChevDown, null))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__ampm" }, /* @__PURE__ */ import_react20.default.createElement(
2845
+ "button",
2846
+ {
2847
+ type: "button",
2848
+ className: `rf-date-picker__ampm-btn ${ampm === "AM" ? "rf-date-picker__ampm-btn--active" : ""}`,
2849
+ onMouseDown: (e) => e.preventDefault(),
2850
+ onClick: () => onAmpmToggle("AM")
2851
+ },
2852
+ "AM"
2853
+ ), /* @__PURE__ */ import_react20.default.createElement(
2854
+ "button",
2855
+ {
2856
+ type: "button",
2857
+ className: `rf-date-picker__ampm-btn ${ampm === "PM" ? "rf-date-picker__ampm-btn--active" : ""}`,
2858
+ onMouseDown: (e) => e.preventDefault(),
2859
+ onClick: () => onAmpmToggle("PM")
2860
+ },
2861
+ "PM"
2862
+ )));
2863
+ var CalendarBody = ({
3079
2864
  viewMonth,
3080
- startDate,
3081
- endDate,
3082
- hoverDate,
2865
+ viewYear,
2866
+ selectedDate,
3083
2867
  todayDate,
2868
+ dayCells,
3084
2869
  onDayClick,
3085
- onDayHover,
3086
2870
  onPrev,
3087
2871
  onNext,
3088
- showPrev = true,
3089
- showNext = true
2872
+ onMonthSelect,
2873
+ onYearSelect
3090
2874
  }) => {
3091
- const firstDay = new Date(viewYear, viewMonth, 1).getDay();
3092
- const daysInMonth = new Date(viewYear, viewMonth + 1, 0).getDate();
3093
- const dayCells = [
3094
- ...Array(firstDay).fill(null),
3095
- ...Array.from({ length: daysInMonth }, (_, i) => i + 1)
3096
- ];
3097
- const effectiveEnd = endDate ?? hoverDate;
3098
- const hasRange = startDate != null && effectiveEnd != null && !isSameDay2(startDate, effectiveEnd);
3099
- const lo = startDate && effectiveEnd ? startDate <= effectiveEnd ? startDate : effectiveEnd : null;
3100
- const hi = startDate && effectiveEnd ? startDate <= effectiveEnd ? effectiveEnd : startDate : null;
3101
- return /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-calendar" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-calendar__header" }, /* @__PURE__ */ import_react20.default.createElement(
2875
+ const [pickerView, setPickerView] = (0, import_react20.useState)("calendar");
2876
+ const handleMonthClick = () => {
2877
+ setPickerView(pickerView === "month" ? "calendar" : "month");
2878
+ };
2879
+ const handleYearClick = () => {
2880
+ setPickerView(pickerView === "year" ? "calendar" : "year");
2881
+ };
2882
+ const handleMonthPick = (month) => {
2883
+ onMonthSelect(month);
2884
+ setPickerView("calendar");
2885
+ };
2886
+ const handleYearPick = (year) => {
2887
+ onYearSelect(year);
2888
+ setPickerView("calendar");
2889
+ };
2890
+ const currentYear = todayDate.getFullYear();
2891
+ const yearStart = viewYear - 6;
2892
+ const years = Array.from({ length: 16 }, (_, i) => yearStart + i);
2893
+ return /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__header" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__header-labels" }, /* @__PURE__ */ import_react20.default.createElement(
2894
+ "span",
2895
+ {
2896
+ className: `rf-date-picker__month-label ${pickerView === "month" ? "rf-date-picker__month-label--active" : ""}`,
2897
+ onClick: handleMonthClick
2898
+ },
2899
+ MONTHS[viewMonth]
2900
+ ), /* @__PURE__ */ import_react20.default.createElement(
2901
+ "span",
2902
+ {
2903
+ className: `rf-date-picker__year-label ${pickerView === "year" ? "rf-date-picker__year-label--active" : ""}`,
2904
+ onClick: handleYearClick
2905
+ },
2906
+ viewYear
2907
+ )), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__nav" }, pickerView === "year" ? /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: () => onYearSelect(viewYear - 16), "aria-label": "Previous years" }, "\u2039"), /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: () => onYearSelect(viewYear + 16), "aria-label": "Next years" }, "\u203A")) : /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: onPrev, "aria-label": "Previous month" }, "\u2039"), /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-date-picker__nav-btn", onClick: onNext, "aria-label": "Next month" }, "\u203A")))), pickerView === "month" && /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__month-grid" }, MONTHS_SHORT.map((m, idx) => /* @__PURE__ */ import_react20.default.createElement(
3102
2908
  "button",
3103
2909
  {
2910
+ key: m,
3104
2911
  type: "button",
3105
- className: "rf-dr-calendar__nav-btn",
3106
- onClick: onPrev,
3107
- style: { visibility: showPrev ? "visible" : "hidden" },
3108
- "aria-label": "Previous month"
2912
+ className: [
2913
+ "rf-date-picker__month-cell",
2914
+ idx === viewMonth ? "rf-date-picker__month-cell--selected" : "",
2915
+ idx === todayDate.getMonth() && viewYear === currentYear ? "rf-date-picker__month-cell--current" : ""
2916
+ ].filter(Boolean).join(" "),
2917
+ onClick: () => handleMonthPick(idx)
3109
2918
  },
3110
- "\u2039"
3111
- ), /* @__PURE__ */ import_react20.default.createElement("span", { className: "rf-dr-calendar__month-label" }, MONTHS2[viewMonth], " ", viewYear), /* @__PURE__ */ import_react20.default.createElement(
2919
+ m
2920
+ ))), pickerView === "year" && /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__year-grid" }, years.map((y) => /* @__PURE__ */ import_react20.default.createElement(
3112
2921
  "button",
3113
2922
  {
2923
+ key: y,
3114
2924
  type: "button",
3115
- className: "rf-dr-calendar__nav-btn",
3116
- onClick: onNext,
3117
- style: { visibility: showNext ? "visible" : "hidden" },
3118
- "aria-label": "Next month"
2925
+ className: [
2926
+ "rf-date-picker__year-cell",
2927
+ y === viewYear ? "rf-date-picker__year-cell--selected" : "",
2928
+ y === currentYear ? "rf-date-picker__year-cell--current" : ""
2929
+ ].filter(Boolean).join(" "),
2930
+ onClick: () => handleYearPick(y)
3119
2931
  },
3120
- "\u203A"
3121
- )), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-calendar__weekdays" }, WEEKDAYS2.map((w) => /* @__PURE__ */ import_react20.default.createElement("div", { key: w, className: "rf-dr-calendar__weekday" }, w))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-calendar__grid" }, dayCells.map((day, idx) => {
3122
- if (day === null) {
3123
- return /* @__PURE__ */ import_react20.default.createElement("div", { key: `e-${idx}`, className: "rf-dr-calendar__cell rf-dr-calendar__cell--empty" });
3124
- }
2932
+ y
2933
+ ))), pickerView === "calendar" && /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__weekdays" }, WEEKDAYS.map((w) => /* @__PURE__ */ import_react20.default.createElement("div", { key: w, className: "rf-date-picker__weekday" }, w))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__grid" }, dayCells.map((day, idx) => {
2934
+ if (day === null) return /* @__PURE__ */ import_react20.default.createElement("div", { key: `e-${idx}`, className: "rf-date-picker__day rf-date-picker__day--empty" });
3125
2935
  const cellDate = new Date(viewYear, viewMonth, day);
3126
- const isStart = startDate ? isSameDay2(cellDate, startDate) : false;
3127
- const isEnd = endDate ? isSameDay2(cellDate, endDate) : false;
3128
- const isToday = isSameDay2(cellDate, todayDate);
3129
- const isInRange = lo && hi ? cellDate > lo && cellDate < hi : false;
3130
- const isRangeStart = hasRange && lo ? isSameDay2(cellDate, lo) : false;
3131
- const isRangeEnd = hasRange && hi ? isSameDay2(cellDate, hi) : false;
3132
- const cellClasses = [
3133
- "rf-dr-calendar__cell",
3134
- isInRange ? "rf-dr-calendar__cell--in-range" : "",
3135
- isRangeStart ? "rf-dr-calendar__cell--range-start" : "",
3136
- isRangeEnd ? "rf-dr-calendar__cell--range-end" : ""
3137
- ].filter(Boolean).join(" ");
3138
- const dayClasses = [
3139
- "rf-dr-calendar__day",
3140
- isStart || isEnd ? "rf-dr-calendar__day--selected" : "",
3141
- isToday && !isStart && !isEnd ? "rf-dr-calendar__day--today" : ""
3142
- ].filter(Boolean).join(" ");
2936
+ const isSelected = selectedDate ? isSameDay(cellDate, selectedDate) : false;
2937
+ const isToday = isSameDay(cellDate, todayDate);
3143
2938
  return /* @__PURE__ */ import_react20.default.createElement(
3144
- "div",
3145
- {
3146
- key: day,
3147
- className: cellClasses,
3148
- onMouseEnter: () => onDayHover(cellDate),
3149
- onMouseLeave: () => onDayHover(null)
3150
- },
3151
- /* @__PURE__ */ import_react20.default.createElement(
3152
- "button",
3153
- {
3154
- type: "button",
3155
- className: dayClasses,
3156
- onClick: () => onDayClick(cellDate)
3157
- },
3158
- day
3159
- )
3160
- );
3161
- })));
3162
- };
3163
- var MiniCalendar = ({ selectedDate, todayDate, onSelect, onClose }) => {
3164
- const init = selectedDate ?? todayDate;
3165
- const [viewYear, setViewYear] = (0, import_react20.useState)(init.getFullYear());
3166
- const [viewMonth, setViewMonth] = (0, import_react20.useState)(init.getMonth());
3167
- const firstDay = new Date(viewYear, viewMonth, 1).getDay();
3168
- const daysInMonth = new Date(viewYear, viewMonth + 1, 0).getDate();
3169
- const dayCells = [
3170
- ...Array(firstDay).fill(null),
3171
- ...Array.from({ length: daysInMonth }, (_, i) => i + 1)
3172
- ];
3173
- const prevMonth = () => {
3174
- if (viewMonth === 0) {
3175
- setViewMonth(11);
3176
- setViewYear((y) => y - 1);
3177
- } else setViewMonth((m) => m - 1);
3178
- };
3179
- const nextMonth = () => {
3180
- if (viewMonth === 11) {
3181
- setViewMonth(0);
3182
- setViewYear((y) => y + 1);
3183
- } else setViewMonth((m) => m + 1);
3184
- };
3185
- return /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-mini-cal" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-mini-cal__header" }, /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-dr-calendar__nav-btn", onClick: prevMonth }, "\u2039"), /* @__PURE__ */ import_react20.default.createElement("span", { className: "rf-dr-calendar__month-label", style: { fontSize: "0.88rem" } }, MONTHS2[viewMonth], " ", viewYear), /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-dr-calendar__nav-btn", onClick: nextMonth }, "\u203A")), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-calendar__weekdays" }, WEEKDAYS2.map((w) => /* @__PURE__ */ import_react20.default.createElement("div", { key: w, className: "rf-dr-calendar__weekday" }, w))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-calendar__grid" }, dayCells.map((day, idx) => {
3186
- if (day === null) {
3187
- return /* @__PURE__ */ import_react20.default.createElement("div", { key: `e-${idx}`, className: "rf-dr-calendar__cell rf-dr-calendar__cell--empty" });
3188
- }
3189
- const cellDate = new Date(viewYear, viewMonth, day);
3190
- const isSel = selectedDate ? isSameDay2(cellDate, selectedDate) : false;
3191
- const isToday = isSameDay2(cellDate, todayDate);
3192
- return /* @__PURE__ */ import_react20.default.createElement("div", { key: day, className: "rf-dr-calendar__cell" }, /* @__PURE__ */ import_react20.default.createElement(
3193
2939
  "button",
3194
2940
  {
2941
+ key: day,
3195
2942
  type: "button",
3196
2943
  className: [
3197
- "rf-dr-calendar__day",
3198
- isSel ? "rf-dr-calendar__day--selected" : "",
3199
- isToday && !isSel ? "rf-dr-calendar__day--today" : ""
2944
+ "rf-date-picker__day",
2945
+ isSelected ? "rf-date-picker__day--selected" : "",
2946
+ isToday && !isSelected ? "rf-date-picker__day--today" : ""
3200
2947
  ].filter(Boolean).join(" "),
3201
- onClick: () => {
3202
- onSelect(cellDate);
3203
- onClose();
3204
- }
2948
+ onClick: () => onDayClick(day)
3205
2949
  },
3206
2950
  day
3207
- ));
3208
- })));
2951
+ );
2952
+ }))));
3209
2953
  };
3210
- var DateRangeField = ({
2954
+ var DateField = ({
3211
2955
  label,
3212
2956
  value,
3213
2957
  onChange,
3214
- pickerType = "panel",
2958
+ type = "date",
2959
+ dateFormat = "MM/DD/YYYY",
3215
2960
  variant = "outlined",
3216
2961
  size = "medium",
3217
2962
  color = "primary",
@@ -3220,165 +2965,230 @@ var DateRangeField = ({
3220
2965
  fullWidth = false,
3221
2966
  disabled = false,
3222
2967
  required = false,
2968
+ placeholder,
3223
2969
  className = "",
3224
2970
  style,
3225
2971
  sx
3226
2972
  }) => {
3227
2973
  const sxClass = useSx(sx);
3228
- const today2 = todayFn();
3229
- const committedStart = value?.start ? isoToDate2(value.start) : null;
3230
- const committedEnd = value?.end ? isoToDate2(value.end) : null;
3231
2974
  const [open, setOpen] = (0, import_react20.useState)(false);
3232
- const [draftStart, setDraftStart] = (0, import_react20.useState)(committedStart);
3233
- const [draftEnd, setDraftEnd] = (0, import_react20.useState)(committedEnd);
3234
- const [activePreset, setActivePreset] = (0, import_react20.useState)(
3235
- () => detectPreset(committedStart, committedEnd)
3236
- );
3237
- const [startInputStr, setStartInputStr] = (0, import_react20.useState)(() => committedStart ? formatShort(committedStart) : "");
3238
- const [endInputStr, setEndInputStr] = (0, import_react20.useState)(() => committedEnd ? formatShort(committedEnd) : "");
3239
- const [inlineCal, setInlineCal] = (0, import_react20.useState)(null);
3240
- const [hoverDate, setHoverDate] = (0, import_react20.useState)(null);
3241
- const [selecting, setSelecting] = (0, import_react20.useState)("start");
3242
- const [leftViewYear, setLeftViewYear] = (0, import_react20.useState)(() => today2.getFullYear());
3243
- const [leftViewMonth, setLeftViewMonth] = (0, import_react20.useState)(() => today2.getMonth());
2975
+ const [selectedDate, setSelectedDate] = (0, import_react20.useState)(() => value ? isoToDate(value) : null);
2976
+ const [hour, setHour] = (0, import_react20.useState)(() => {
2977
+ if (value && isDatetimeType(type)) return parseTimeFromISO(value).h;
2978
+ return 12;
2979
+ });
2980
+ const [minute, setMinute] = (0, import_react20.useState)(() => {
2981
+ if (value && isDatetimeType(type)) return parseTimeFromISO(value).m;
2982
+ return 0;
2983
+ });
2984
+ const [ampm, setAmpm] = (0, import_react20.useState)(() => {
2985
+ if (value && isDatetimeType(type)) return parseTimeFromISO(value).ampm;
2986
+ return "AM";
2987
+ });
2988
+ const [viewYear, setViewYear] = (0, import_react20.useState)(() => {
2989
+ const base = value ? isoToDate(value) : null;
2990
+ return base ? base.getFullYear() : today().getFullYear();
2991
+ });
2992
+ const [viewMonth, setViewMonth] = (0, import_react20.useState)(() => {
2993
+ const base = value ? isoToDate(value) : null;
2994
+ return base ? base.getMonth() : today().getMonth();
2995
+ });
2996
+ const [inputStr, setInputStr] = (0, import_react20.useState)(() => {
2997
+ if (!value) return "";
2998
+ const d = isoToDate(value);
2999
+ if (!d) return "";
3000
+ let str = formatDisplay(d, dateFormat);
3001
+ if (isDatetimeType(type)) {
3002
+ const t = parseTimeFromISO(value);
3003
+ str += " " + formatTimeDisplay(t.h, t.m, t.ampm);
3004
+ }
3005
+ return str;
3006
+ });
3007
+ const HOURS = Array.from({ length: 12 }, (_, i) => String(i + 1).padStart(2, "0"));
3008
+ const MINUTES = Array.from({ length: 60 }, (_, i) => String(i).padStart(2, "0"));
3009
+ const AMPMS = ["AM", "PM"];
3244
3010
  const containerRef = (0, import_react20.useRef)(null);
3245
- const inputId = (0, import_react20.useRef)(`rf-dr-${Math.random().toString(36).substr(2, 9)}`).current;
3246
- (0, import_react20.useEffect)(() => {
3247
- const s2 = value?.start ? isoToDate2(value.start) : null;
3248
- const e = value?.end ? isoToDate2(value.end) : null;
3249
- setDraftStart(s2);
3250
- setDraftEnd(e);
3251
- setStartInputStr(s2 ? formatShort(s2) : "");
3252
- setEndInputStr(e ? formatShort(e) : "");
3253
- setActivePreset(detectPreset(s2, e));
3254
- }, [value?.start, value?.end]);
3011
+ const pickerRef = (0, import_react20.useRef)(null);
3012
+ const [dropUp, setDropUp] = (0, import_react20.useState)(false);
3013
+ const inputId = (0, import_react20.useRef)(`rf-df-${Math.random().toString(36).substring(2, 11)}`).current;
3014
+ const isInternalChange = (0, import_react20.useRef)(false);
3255
3015
  (0, import_react20.useEffect)(() => {
3256
- setActivePreset(detectPreset(draftStart, draftEnd));
3257
- }, [draftStart?.getTime(), draftEnd?.getTime()]);
3016
+ if (value === void 0) return;
3017
+ if (isInternalChange.current) {
3018
+ isInternalChange.current = false;
3019
+ return;
3020
+ }
3021
+ if (!value) {
3022
+ setSelectedDate(null);
3023
+ setInputStr("");
3024
+ return;
3025
+ }
3026
+ const d = isoToDate(value);
3027
+ setSelectedDate(d);
3028
+ if (d) {
3029
+ setViewYear(d.getFullYear());
3030
+ setViewMonth(d.getMonth());
3031
+ let str = formatDisplay(d, dateFormat);
3032
+ if (isDatetimeType(type)) {
3033
+ const t = parseTimeFromISO(value);
3034
+ setHour(t.h);
3035
+ setMinute(t.m);
3036
+ setAmpm(t.ampm);
3037
+ str += " " + formatTimeDisplay(t.h, t.m, t.ampm);
3038
+ }
3039
+ setInputStr(str);
3040
+ }
3041
+ }, [value, type]);
3258
3042
  (0, import_react20.useEffect)(() => {
3259
3043
  if (!open) return;
3260
3044
  const handler = (e) => {
3261
- if (containerRef.current && !containerRef.current.contains(e.target)) {
3262
- setOpen(false);
3263
- setInlineCal(null);
3264
- setDraftStart(committedStart);
3265
- setDraftEnd(committedEnd);
3266
- setStartInputStr(committedStart ? formatShort(committedStart) : "");
3267
- setEndInputStr(committedEnd ? formatShort(committedEnd) : "");
3268
- setActivePreset(detectPreset(committedStart, committedEnd));
3269
- setSelecting("start");
3270
- }
3045
+ const target = e.target;
3046
+ if (containerRef.current?.contains(target)) return;
3047
+ if (pickerRef.current?.contains(target)) return;
3048
+ setOpen(false);
3271
3049
  };
3272
3050
  document.addEventListener("mousedown", handler);
3273
3051
  return () => document.removeEventListener("mousedown", handler);
3274
- }, [open, committedStart, committedEnd]);
3275
- const displayStr = (() => {
3276
- if (committedStart && committedEnd) {
3277
- return `${formatShort(committedStart)} \u2013 ${formatShort(committedEnd)}`;
3278
- }
3279
- if (committedStart) return `${formatShort(committedStart)} \u2013`;
3280
- return "";
3281
- })();
3282
- const handleApply = () => {
3283
- if (draftStart && draftEnd) {
3284
- const [s2, e] = draftStart <= draftEnd ? [draftStart, draftEnd] : [draftEnd, draftStart];
3285
- onChange?.({ start: dateToISO(s2), end: dateToISO(e) });
3286
- } else if (draftStart) {
3287
- onChange?.({ start: dateToISO(draftStart), end: dateToISO(draftStart) });
3052
+ }, [open]);
3053
+ (0, import_react20.useEffect)(() => {
3054
+ if (!open || !containerRef.current) return;
3055
+ const rect = containerRef.current.getBoundingClientRect();
3056
+ const spaceBelow = window.innerHeight - rect.bottom;
3057
+ const pickerHeight = 400;
3058
+ setDropUp(spaceBelow < pickerHeight && rect.top > pickerHeight);
3059
+ }, [open]);
3060
+ const commitDate = (0, import_react20.useCallback)((d, h, m, ap) => {
3061
+ setSelectedDate(d);
3062
+ if (!d) {
3063
+ setInputStr("");
3064
+ onChange?.("");
3065
+ return;
3288
3066
  }
3289
- setOpen(false);
3290
- setInlineCal(null);
3291
- };
3292
- const handleClose = () => {
3293
- setOpen(false);
3294
- setInlineCal(null);
3295
- setDraftStart(committedStart);
3296
- setDraftEnd(committedEnd);
3297
- setStartInputStr(committedStart ? formatShort(committedStart) : "");
3298
- setEndInputStr(committedEnd ? formatShort(committedEnd) : "");
3299
- setActivePreset(detectPreset(committedStart, committedEnd));
3300
- setSelecting("start");
3067
+ let str = formatDisplay(d, dateFormat);
3068
+ if (isDatetimeType(type)) str += " " + formatTimeDisplay(h, m, ap);
3069
+ setInputStr(str);
3070
+ onChange?.(buildISO(d, type, h, m, ap));
3071
+ }, [type, onChange, dateFormat]);
3072
+ const handleDayClick = (day) => {
3073
+ const d = new Date(viewYear, viewMonth, day);
3074
+ setSelectedDate(d);
3075
+ let str = formatDisplay(d, dateFormat);
3076
+ if (isDatetimeType(type)) str += " " + formatTimeDisplay(hour, minute, ampm);
3077
+ setInputStr(str);
3078
+ onChange?.(buildISO(d, type, hour, minute, ampm));
3079
+ if (type === "date") setOpen(false);
3301
3080
  };
3302
- const handlePreset = (presetId) => {
3303
- const range = getPresetRange(presetId, draftStart);
3304
- const s2 = isoToDate2(range.start);
3305
- const e = isoToDate2(range.end);
3306
- setDraftStart(s2);
3307
- setDraftEnd(e);
3308
- setStartInputStr(s2 ? formatShort(s2) : "");
3309
- setEndInputStr(e ? formatShort(e) : "");
3310
- setInlineCal(null);
3081
+ const handleToday = () => {
3082
+ const t = today();
3083
+ setViewYear(t.getFullYear());
3084
+ setViewMonth(t.getMonth());
3085
+ commitDate(t, hour, minute, ampm);
3086
+ if (type === "date") setOpen(false);
3311
3087
  };
3312
- const handleCalDayClick = (d) => {
3313
- if (selecting === "start") {
3314
- setDraftStart(d);
3315
- setDraftEnd(null);
3316
- setSelecting("end");
3317
- setActivePreset(null);
3318
- } else {
3319
- if (draftStart && d < draftStart) {
3320
- setDraftEnd(draftStart);
3321
- setDraftStart(d);
3322
- } else {
3323
- setDraftEnd(d);
3088
+ const handleClear = () => commitDate(null, hour, minute, ampm);
3089
+ const handleInputChange = (e) => {
3090
+ const raw = e.target.value;
3091
+ setInputStr(raw);
3092
+ const dateWordCount = getDateWordCount(dateFormat);
3093
+ const words = raw.split(" ");
3094
+ const datePart = words.slice(0, dateWordCount).join(" ");
3095
+ const timeParts = words.slice(dateWordCount);
3096
+ const parsed = parseDisplay(datePart, dateFormat);
3097
+ if (parsed) {
3098
+ setSelectedDate(parsed);
3099
+ setViewYear(parsed.getFullYear());
3100
+ setViewMonth(parsed.getMonth());
3101
+ let h = hour, m = minute, ap = ampm;
3102
+ if (isDatetimeType(type) && timeParts.length >= 2) {
3103
+ const timePart = timeParts[0];
3104
+ const periodPart = timeParts[1]?.toUpperCase();
3105
+ if (timePart?.includes(":")) {
3106
+ const [hStr, mStr] = timePart.split(":");
3107
+ const parsedH = parseInt(hStr, 10);
3108
+ const parsedM = parseInt(mStr, 10);
3109
+ if (!isNaN(parsedH) && parsedH >= 1 && parsedH <= 12) {
3110
+ h = parsedH;
3111
+ setHour(h);
3112
+ }
3113
+ if (!isNaN(parsedM) && parsedM >= 0 && parsedM <= 59) {
3114
+ m = parsedM;
3115
+ setMinute(m);
3116
+ }
3117
+ }
3118
+ if (periodPart === "AM" || periodPart === "PM") {
3119
+ ap = periodPart;
3120
+ setAmpm(ap);
3121
+ }
3324
3122
  }
3325
- setSelecting("start");
3326
- setActivePreset(detectPreset(draftStart, d));
3123
+ isInternalChange.current = true;
3124
+ onChange?.(buildISO(parsed, type, h, m, ap));
3125
+ } else if (!raw) {
3126
+ setSelectedDate(null);
3127
+ isInternalChange.current = true;
3128
+ onChange?.("");
3327
3129
  }
3328
3130
  };
3329
- const rightViewMonth = leftViewMonth === 11 ? 0 : leftViewMonth + 1;
3330
- const rightViewYear = leftViewMonth === 11 ? leftViewYear + 1 : leftViewYear;
3331
- const prevMonth = () => {
3332
- if (leftViewMonth === 0) {
3333
- setLeftViewMonth(11);
3334
- setLeftViewYear((y) => y - 1);
3335
- } else setLeftViewMonth((m) => m - 1);
3131
+ const handleHourChange = (delta) => {
3132
+ const h = (hour - 1 + delta + 12) % 12 + 1;
3133
+ setHour(h);
3134
+ if (selectedDate) commitDate(selectedDate, h, minute, ampm);
3336
3135
  };
3337
- const nextMonth = () => {
3338
- if (leftViewMonth === 11) {
3339
- setLeftViewMonth(0);
3340
- setLeftViewYear((y) => y + 1);
3341
- } else setLeftViewMonth((m) => m + 1);
3136
+ const handleMinuteChange = (delta) => {
3137
+ const m = (minute + delta + 60) % 60;
3138
+ setMinute(m);
3139
+ if (selectedDate) commitDate(selectedDate, hour, m, ampm);
3342
3140
  };
3343
- const daysUntilToday = draftStart ? Math.max(0, daysBetween(draftStart, today2)) : 0;
3344
- const daysFromToday = draftEnd ? Math.max(0, daysBetween(today2, draftEnd)) : 0;
3345
- const handleDaysUntilChange = (e) => {
3346
- const n = parseInt(e.target.value, 10);
3347
- if (!isNaN(n) && n >= 0) {
3348
- const d = addDays(today2, -n);
3349
- setDraftStart(d);
3350
- setStartInputStr(formatShort(d));
3351
- }
3141
+ const handleAmpmToggle = (val) => {
3142
+ setAmpm(val);
3143
+ if (selectedDate) commitDate(selectedDate, hour, minute, val);
3352
3144
  };
3353
- const handleDaysFromChange = (e) => {
3354
- const n = parseInt(e.target.value, 10);
3355
- if (!isNaN(n) && n >= 0) {
3356
- const d = addDays(today2, n);
3357
- setDraftEnd(d);
3358
- setEndInputStr(formatShort(d));
3359
- }
3145
+ const handleHourInput = (e) => {
3146
+ let v = parseInt(e.target.value, 10);
3147
+ if (isNaN(v)) return;
3148
+ v = Math.max(1, Math.min(12, v));
3149
+ setHour(v);
3150
+ if (selectedDate) commitDate(selectedDate, v, minute, ampm);
3360
3151
  };
3361
- const handleStartInputChange = (e) => {
3362
- const raw = e.target.value;
3363
- setStartInputStr(raw);
3364
- const parsed = parseInputDate(raw);
3365
- if (parsed) setDraftStart(parsed);
3366
- else if (!raw) setDraftStart(null);
3152
+ const handleMinuteInput = (e) => {
3153
+ let v = parseInt(e.target.value, 10);
3154
+ if (isNaN(v)) return;
3155
+ v = Math.max(0, Math.min(59, v));
3156
+ setMinute(v);
3157
+ if (selectedDate) commitDate(selectedDate, hour, v, ampm);
3367
3158
  };
3368
- const handleStartInputBlur = () => {
3369
- setStartInputStr(draftStart ? formatShort(draftStart) : "");
3159
+ const handleScrollHour = (idx) => {
3160
+ const h = idx + 1;
3161
+ setHour(h);
3162
+ if (selectedDate) commitDate(selectedDate, h, minute, ampm);
3370
3163
  };
3371
- const handleEndInputChange = (e) => {
3372
- const raw = e.target.value;
3373
- setEndInputStr(raw);
3374
- const parsed = parseInputDate(raw);
3375
- if (parsed) setDraftEnd(parsed);
3376
- else if (!raw) setDraftEnd(null);
3164
+ const handleScrollMinute = (idx) => {
3165
+ setMinute(idx);
3166
+ if (selectedDate) commitDate(selectedDate, hour, idx, ampm);
3377
3167
  };
3378
- const handleEndInputBlur = () => {
3379
- setEndInputStr(draftEnd ? formatShort(draftEnd) : "");
3168
+ const handleScrollAmpm = (idx) => {
3169
+ const ap = AMPMS[idx];
3170
+ setAmpm(ap);
3171
+ if (selectedDate) commitDate(selectedDate, hour, minute, ap);
3380
3172
  };
3381
- const isFloating = Boolean(displayStr || open);
3173
+ const prevMonth = () => {
3174
+ if (viewMonth === 0) {
3175
+ setViewMonth(11);
3176
+ setViewYear((y) => y - 1);
3177
+ } else setViewMonth((m) => m - 1);
3178
+ };
3179
+ const nextMonth = () => {
3180
+ if (viewMonth === 11) {
3181
+ setViewMonth(0);
3182
+ setViewYear((y) => y + 1);
3183
+ } else setViewMonth((m) => m + 1);
3184
+ };
3185
+ const firstDayOfWeek = new Date(viewYear, viewMonth, 1).getDay();
3186
+ const daysInMonth = new Date(viewYear, viewMonth + 1, 0).getDate();
3187
+ const dayCells = [
3188
+ ...Array(firstDayOfWeek).fill(null),
3189
+ ...Array.from({ length: daysInMonth }, (_, i) => i + 1)
3190
+ ];
3191
+ const isFloating = Boolean(inputStr || open);
3382
3192
  const rootClasses = [
3383
3193
  "rf-text-field",
3384
3194
  `rf-text-field--${variant}`,
@@ -3389,14 +3199,15 @@ var DateRangeField = ({
3389
3199
  disabled ? "rf-text-field--disabled" : "",
3390
3200
  isFloating ? "rf-text-field--floating" : "",
3391
3201
  Boolean(label) ? "rf-text-field--has-label" : "",
3392
- "rf-text-field--adorned-end",
3202
+ variant !== "compact" ? "rf-text-field--adorned-end" : "",
3393
3203
  "rf-date-field",
3394
- "rf-date-range-field",
3395
3204
  fullWidth ? "rf-date-field--full-width" : "",
3396
3205
  sxClass,
3397
3206
  className
3398
3207
  ].filter(Boolean).join(" ");
3399
- const inputPlaceholder = variant === "outlined" ? " " : void 0;
3208
+ const inputPlaceholder = placeholder || (variant === "outlined" ? " " : void 0);
3209
+ const todayDate = today();
3210
+ const isSideVariant = type === "datetime-side" || type === "datetime-scroll";
3400
3211
  return /* @__PURE__ */ import_react20.default.createElement("div", { ref: containerRef, className: rootClasses, style }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-field__anchor" }, /* @__PURE__ */ import_react20.default.createElement(
3401
3212
  "div",
3402
3213
  {
@@ -3412,8 +3223,8 @@ var DateRangeField = ({
3412
3223
  id: inputId,
3413
3224
  className: "rf-text-field__input",
3414
3225
  type: "text",
3415
- value: displayStr,
3416
- readOnly: true,
3226
+ value: inputStr,
3227
+ onChange: handleInputChange,
3417
3228
  placeholder: inputPlaceholder,
3418
3229
  disabled,
3419
3230
  onClick: (e) => e.stopPropagation(),
@@ -3433,551 +3244,755 @@ var DateRangeField = ({
3433
3244
  e.stopPropagation();
3434
3245
  if (!disabled) setOpen((o) => !o);
3435
3246
  },
3436
- "aria-label": "Pick date range"
3437
- },
3438
- /* @__PURE__ */ import_react20.default.createElement(CalendarIcon2, null)
3439
- )),
3440
- label && /* @__PURE__ */ import_react20.default.createElement("label", { htmlFor: inputId, className: "rf-text-field__label" }, label, " ", required && /* @__PURE__ */ import_react20.default.createElement("span", { className: "rf-text-field__asterisk" }, "*")),
3441
- variant === "outlined" && /* @__PURE__ */ import_react20.default.createElement("fieldset", { className: "rf-text-field__notch" }, label ? /* @__PURE__ */ import_react20.default.createElement("legend", { className: "rf-text-field__legend" }, /* @__PURE__ */ import_react20.default.createElement("span", null, label, required ? " *" : "")) : /* @__PURE__ */ import_react20.default.createElement("legend", { className: "rf-text-field__legend--empty" }))
3442
- ), open && !disabled && (pickerType === "panel" ? (
3443
- /* ── Panel Mode ── */
3444
- /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker rf-dr-picker--panel", onMouseDown: (e) => e.preventDefault() }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__presets" }, PRESETS.map((p, i) => /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, { key: p.id }, i > 0 && /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__preset-sep" }), /* @__PURE__ */ import_react20.default.createElement(
3445
- "button",
3446
- {
3447
- type: "button",
3448
- className: [
3449
- "rf-dr-picker__preset-btn",
3450
- activePreset === p.id ? "rf-dr-picker__preset-btn--active" : ""
3451
- ].filter(Boolean).join(" "),
3452
- onClick: () => handlePreset(p.id)
3247
+ "aria-label": "Pick date"
3453
3248
  },
3454
- p.label
3455
- )))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__manual" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__date-field-wrap" }, /* @__PURE__ */ import_react20.default.createElement(
3249
+ /* @__PURE__ */ import_react20.default.createElement(CalendarIcon, null)
3250
+ )),
3251
+ label && /* @__PURE__ */ import_react20.default.createElement("label", { htmlFor: inputId, className: "rf-text-field__label" }, label, " ", required && /* @__PURE__ */ import_react20.default.createElement("span", { className: "rf-text-field__asterisk" }, "*")),
3252
+ variant === "outlined" && /* @__PURE__ */ import_react20.default.createElement("fieldset", { className: "rf-text-field__notch" }, label && /* @__PURE__ */ import_react20.default.createElement("legend", { className: "rf-text-field__legend" }, /* @__PURE__ */ import_react20.default.createElement("span", null, label, required ? " *" : "")))
3253
+ ), open && !disabled && (0, import_react_dom3.createPortal)(
3254
+ /* @__PURE__ */ import_react20.default.createElement(
3456
3255
  "div",
3457
3256
  {
3257
+ ref: pickerRef,
3458
3258
  className: [
3459
- "rf-dr-picker__date-field",
3460
- inlineCal === "start" ? "rf-dr-picker__date-field--active" : ""
3461
- ].filter(Boolean).join(" ")
3259
+ "rf-date-picker",
3260
+ "rf-date-picker--portaled",
3261
+ isSideVariant ? "rf-date-picker--side" : "",
3262
+ dropUp ? "rf-date-picker--drop-up" : ""
3263
+ ].filter(Boolean).join(" "),
3264
+ style: (() => {
3265
+ const rect = containerRef.current?.getBoundingClientRect();
3266
+ if (!rect) return {};
3267
+ const top = rect.bottom + 6;
3268
+ const spaceBelow = window.innerHeight - rect.bottom - 6;
3269
+ const useDropUp = spaceBelow < 350 && rect.top > spaceBelow;
3270
+ return {
3271
+ position: "fixed",
3272
+ left: rect.left,
3273
+ ...useDropUp ? { bottom: window.innerHeight - rect.top + 6 } : { top },
3274
+ zIndex: 99999
3275
+ };
3276
+ })(),
3277
+ onMouseDown: (e) => e.preventDefault()
3462
3278
  },
3463
- /* @__PURE__ */ import_react20.default.createElement("span", { className: "rf-dr-picker__date-floating-label" }, "Start Date"),
3464
- /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__date-display" }, /* @__PURE__ */ import_react20.default.createElement(
3465
- "input",
3279
+ /* @__PURE__ */ import_react20.default.createElement("div", { className: isSideVariant ? "rf-date-picker__cal-col" : void 0 }, /* @__PURE__ */ import_react20.default.createElement(
3280
+ CalendarBody,
3466
3281
  {
3467
- type: "text",
3468
- className: "rf-dr-picker__date-input",
3469
- value: startInputStr,
3470
- placeholder: "DD Mon YYYY",
3471
- onChange: handleStartInputChange,
3472
- onBlur: handleStartInputBlur,
3473
- onMouseDown: (e) => e.stopPropagation()
3282
+ viewMonth,
3283
+ viewYear,
3284
+ selectedDate,
3285
+ todayDate,
3286
+ dayCells,
3287
+ onDayClick: handleDayClick,
3288
+ onPrev: prevMonth,
3289
+ onNext: nextMonth,
3290
+ onMonthSelect: setViewMonth,
3291
+ onYearSelect: setViewYear
3292
+ }
3293
+ ), type === "datetime" && /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__time-section" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__time-label" }, "Time"), /* @__PURE__ */ import_react20.default.createElement(
3294
+ SpinnerPanel,
3295
+ {
3296
+ hour,
3297
+ minute,
3298
+ ampm,
3299
+ onHourChange: handleHourChange,
3300
+ onMinuteChange: handleMinuteChange,
3301
+ onHourInput: handleHourInput,
3302
+ onMinuteInput: handleMinuteInput,
3303
+ onAmpmToggle: handleAmpmToggle
3304
+ }
3305
+ )), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__divider" }), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__footer" }, /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-date-picker__footer-btn", onClick: handleToday }, "Today"), /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-date-picker__footer-btn rf-date-picker__footer-btn--clear", onClick: handleClear }, "Clear"))),
3306
+ type === "datetime-side" && /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__side-spinner" }, /* @__PURE__ */ import_react20.default.createElement(
3307
+ SpinnerPanel,
3308
+ {
3309
+ hour,
3310
+ minute,
3311
+ ampm,
3312
+ onHourChange: handleHourChange,
3313
+ onMinuteChange: handleMinuteChange,
3314
+ onHourInput: handleHourInput,
3315
+ onMinuteInput: handleMinuteInput,
3316
+ onAmpmToggle: handleAmpmToggle
3317
+ }
3318
+ )), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm)),
3319
+ type === "datetime-scroll" && /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-timescroll" }, /* @__PURE__ */ import_react20.default.createElement(
3320
+ ScrollColumn,
3321
+ {
3322
+ items: HOURS,
3323
+ selected: hour - 1,
3324
+ onSelect: handleScrollHour
3325
+ }
3326
+ ), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-timescroll__colon" }, ":"), /* @__PURE__ */ import_react20.default.createElement(
3327
+ ScrollColumn,
3328
+ {
3329
+ items: MINUTES,
3330
+ selected: minute,
3331
+ onSelect: handleScrollMinute
3474
3332
  }
3475
3333
  ), /* @__PURE__ */ import_react20.default.createElement(
3476
- "button",
3334
+ ScrollColumn,
3477
3335
  {
3478
- type: "button",
3479
- className: "rf-dr-picker__cal-icon-btn",
3480
- onMouseDown: (e) => e.stopPropagation(),
3481
- onClick: () => setInlineCal((v) => v === "start" ? null : "start"),
3482
- "aria-label": "Pick start date"
3483
- },
3484
- /* @__PURE__ */ import_react20.default.createElement(CalendarIcon2, null)
3485
- ))
3486
- ), inlineCal === "start" && /* @__PURE__ */ import_react20.default.createElement(
3487
- MiniCalendar,
3488
- {
3489
- selectedDate: draftStart,
3490
- todayDate: today2,
3491
- onSelect: (d) => {
3492
- setDraftStart(d);
3493
- setStartInputStr(formatShort(d));
3494
- },
3495
- onClose: () => setInlineCal(null)
3496
- }
3497
- )), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__date-field-wrap" }, /* @__PURE__ */ import_react20.default.createElement(
3336
+ items: AMPMS,
3337
+ selected: ampm === "AM" ? 0 : 1,
3338
+ onSelect: handleScrollAmpm,
3339
+ infinite: false
3340
+ }
3341
+ )), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm))
3342
+ ),
3343
+ document.body
3344
+ )), helperText && /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-text-field__helper-text" }, helperText));
3345
+ };
3346
+ DateField.displayName = "DateField";
3347
+
3348
+ // lib/TextFields/DateRangeField.tsx
3349
+ var import_react21 = __toESM(require("react"), 1);
3350
+ var WEEKDAYS2 = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"];
3351
+ var MONTHS2 = [
3352
+ "January",
3353
+ "February",
3354
+ "March",
3355
+ "April",
3356
+ "May",
3357
+ "June",
3358
+ "July",
3359
+ "August",
3360
+ "September",
3361
+ "October",
3362
+ "November",
3363
+ "December"
3364
+ ];
3365
+ var MONTHS_SHORT2 = [
3366
+ "Jan",
3367
+ "Feb",
3368
+ "Mar",
3369
+ "Apr",
3370
+ "May",
3371
+ "Jun",
3372
+ "Jul",
3373
+ "Aug",
3374
+ "Sep",
3375
+ "Oct",
3376
+ "Nov",
3377
+ "Dec"
3378
+ ];
3379
+ var PRESETS = [
3380
+ { id: "today", label: "Today" },
3381
+ { id: "this_week", label: "This week" },
3382
+ { id: "this_month", label: "This month" },
3383
+ { id: "till_date", label: "Till date" },
3384
+ { id: "all", label: "All" }
3385
+ ];
3386
+ var todayFn = () => {
3387
+ const t = /* @__PURE__ */ new Date();
3388
+ return new Date(t.getFullYear(), t.getMonth(), t.getDate());
3389
+ };
3390
+ var isoToDate2 = (iso) => {
3391
+ if (!iso) return null;
3392
+ const parts = iso.split("-").map(Number);
3393
+ if (parts.length < 3 || !parts[0] || !parts[1] || !parts[2]) return null;
3394
+ return new Date(parts[0], parts[1] - 1, parts[2]);
3395
+ };
3396
+ var dateToISO = (d) => {
3397
+ const y = d.getFullYear();
3398
+ const mo = String(d.getMonth() + 1).padStart(2, "0");
3399
+ const dd = String(d.getDate()).padStart(2, "0");
3400
+ return `${y}-${mo}-${dd}`;
3401
+ };
3402
+ var formatShort = (d) => `${String(d.getDate()).padStart(2, "0")} ${MONTHS_SHORT2[d.getMonth()]} ${d.getFullYear()}`;
3403
+ var parseInputDate = (str) => {
3404
+ const s2 = str.trim();
3405
+ if (!s2) return null;
3406
+ const shortMatch = s2.match(/^(\d{1,2})\s+([A-Za-z]+)\s+(\d{4})$/);
3407
+ if (shortMatch) {
3408
+ const day = parseInt(shortMatch[1], 10);
3409
+ const monthIdx = MONTHS_SHORT2.findIndex((m) => m.toLowerCase() === shortMatch[2].toLowerCase());
3410
+ const year = parseInt(shortMatch[3], 10);
3411
+ if (monthIdx !== -1 && day >= 1 && day <= 31 && year >= 1e3) {
3412
+ const d = new Date(year, monthIdx, day);
3413
+ if (!isNaN(d.getTime())) return d;
3414
+ }
3415
+ }
3416
+ const slashMatch = s2.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
3417
+ if (slashMatch) {
3418
+ const d = new Date(parseInt(slashMatch[3], 10), parseInt(slashMatch[2], 10) - 1, parseInt(slashMatch[1], 10));
3419
+ if (!isNaN(d.getTime())) return d;
3420
+ }
3421
+ const isoMatch = s2.match(/^(\d{4})-(\d{2})-(\d{2})$/);
3422
+ if (isoMatch) {
3423
+ const d = new Date(parseInt(isoMatch[1], 10), parseInt(isoMatch[2], 10) - 1, parseInt(isoMatch[3], 10));
3424
+ if (!isNaN(d.getTime())) return d;
3425
+ }
3426
+ return null;
3427
+ };
3428
+ var isSameDay2 = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
3429
+ var daysBetween = (a, b) => Math.round((b.getTime() - a.getTime()) / (1e3 * 60 * 60 * 24));
3430
+ var addDays = (d, n) => {
3431
+ const r = new Date(d.getTime());
3432
+ r.setDate(r.getDate() + n);
3433
+ return r;
3434
+ };
3435
+ var getPresetRange = (preset, currentStart) => {
3436
+ const today2 = todayFn();
3437
+ switch (preset) {
3438
+ case "today":
3439
+ return { start: dateToISO(today2), end: dateToISO(today2) };
3440
+ case "this_week": {
3441
+ const day = today2.getDay();
3442
+ const monday = addDays(today2, day === 0 ? -6 : -(day - 1));
3443
+ return { start: dateToISO(monday), end: dateToISO(addDays(monday, 6)) };
3444
+ }
3445
+ case "this_month": {
3446
+ const start = new Date(today2.getFullYear(), today2.getMonth(), 1);
3447
+ const end = new Date(today2.getFullYear(), today2.getMonth() + 1, 0);
3448
+ return { start: dateToISO(start), end: dateToISO(end) };
3449
+ }
3450
+ case "till_date": {
3451
+ const start = currentStart ?? addDays(today2, -30);
3452
+ return { start: dateToISO(start), end: dateToISO(today2) };
3453
+ }
3454
+ case "all":
3455
+ return { start: dateToISO(new Date(2e3, 0, 1)), end: dateToISO(today2) };
3456
+ default:
3457
+ return { start: "", end: "" };
3458
+ }
3459
+ };
3460
+ var detectPreset = (start, end) => {
3461
+ if (!start || !end) return null;
3462
+ const today2 = todayFn();
3463
+ if (isSameDay2(start, today2) && isSameDay2(end, today2)) return "today";
3464
+ const day = today2.getDay();
3465
+ const monday = addDays(today2, day === 0 ? -6 : -(day - 1));
3466
+ if (isSameDay2(start, monday) && isSameDay2(end, addDays(monday, 6))) return "this_week";
3467
+ const monthStart = new Date(today2.getFullYear(), today2.getMonth(), 1);
3468
+ const monthEnd = new Date(today2.getFullYear(), today2.getMonth() + 1, 0);
3469
+ if (isSameDay2(start, monthStart) && isSameDay2(end, monthEnd)) return "this_month";
3470
+ if (isSameDay2(end, today2)) return "till_date";
3471
+ if (isSameDay2(start, new Date(2e3, 0, 1)) && isSameDay2(end, today2)) return "all";
3472
+ return null;
3473
+ };
3474
+ var CalendarIcon2 = () => /* @__PURE__ */ import_react21.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react21.default.createElement("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }), /* @__PURE__ */ import_react21.default.createElement("line", { x1: "16", y1: "2", x2: "16", y2: "6" }), /* @__PURE__ */ import_react21.default.createElement("line", { x1: "8", y1: "2", x2: "8", y2: "6" }), /* @__PURE__ */ import_react21.default.createElement("line", { x1: "3", y1: "10", x2: "21", y2: "10" }));
3475
+ var RangeCalendarBody = ({
3476
+ viewYear,
3477
+ viewMonth,
3478
+ startDate,
3479
+ endDate,
3480
+ hoverDate,
3481
+ todayDate,
3482
+ onDayClick,
3483
+ onDayHover,
3484
+ onPrev,
3485
+ onNext,
3486
+ showPrev = true,
3487
+ showNext = true
3488
+ }) => {
3489
+ const firstDay = new Date(viewYear, viewMonth, 1).getDay();
3490
+ const daysInMonth = new Date(viewYear, viewMonth + 1, 0).getDate();
3491
+ const dayCells = [
3492
+ ...Array(firstDay).fill(null),
3493
+ ...Array.from({ length: daysInMonth }, (_, i) => i + 1)
3494
+ ];
3495
+ const effectiveEnd = endDate ?? hoverDate;
3496
+ const hasRange = startDate != null && effectiveEnd != null && !isSameDay2(startDate, effectiveEnd);
3497
+ const lo = startDate && effectiveEnd ? startDate <= effectiveEnd ? startDate : effectiveEnd : null;
3498
+ const hi = startDate && effectiveEnd ? startDate <= effectiveEnd ? effectiveEnd : startDate : null;
3499
+ return /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-calendar" }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-calendar__header" }, /* @__PURE__ */ import_react21.default.createElement(
3500
+ "button",
3501
+ {
3502
+ type: "button",
3503
+ className: "rf-dr-calendar__nav-btn",
3504
+ onClick: onPrev,
3505
+ style: { visibility: showPrev ? "visible" : "hidden" },
3506
+ "aria-label": "Previous month"
3507
+ },
3508
+ "\u2039"
3509
+ ), /* @__PURE__ */ import_react21.default.createElement("span", { className: "rf-dr-calendar__month-label" }, MONTHS2[viewMonth], " ", viewYear), /* @__PURE__ */ import_react21.default.createElement(
3510
+ "button",
3511
+ {
3512
+ type: "button",
3513
+ className: "rf-dr-calendar__nav-btn",
3514
+ onClick: onNext,
3515
+ style: { visibility: showNext ? "visible" : "hidden" },
3516
+ "aria-label": "Next month"
3517
+ },
3518
+ "\u203A"
3519
+ )), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-calendar__weekdays" }, WEEKDAYS2.map((w) => /* @__PURE__ */ import_react21.default.createElement("div", { key: w, className: "rf-dr-calendar__weekday" }, w))), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-calendar__grid" }, dayCells.map((day, idx) => {
3520
+ if (day === null) {
3521
+ return /* @__PURE__ */ import_react21.default.createElement("div", { key: `e-${idx}`, className: "rf-dr-calendar__cell rf-dr-calendar__cell--empty" });
3522
+ }
3523
+ const cellDate = new Date(viewYear, viewMonth, day);
3524
+ const isStart = startDate ? isSameDay2(cellDate, startDate) : false;
3525
+ const isEnd = endDate ? isSameDay2(cellDate, endDate) : false;
3526
+ const isToday = isSameDay2(cellDate, todayDate);
3527
+ const isInRange = lo && hi ? cellDate > lo && cellDate < hi : false;
3528
+ const isRangeStart = hasRange && lo ? isSameDay2(cellDate, lo) : false;
3529
+ const isRangeEnd = hasRange && hi ? isSameDay2(cellDate, hi) : false;
3530
+ const cellClasses = [
3531
+ "rf-dr-calendar__cell",
3532
+ isInRange ? "rf-dr-calendar__cell--in-range" : "",
3533
+ isRangeStart ? "rf-dr-calendar__cell--range-start" : "",
3534
+ isRangeEnd ? "rf-dr-calendar__cell--range-end" : ""
3535
+ ].filter(Boolean).join(" ");
3536
+ const dayClasses = [
3537
+ "rf-dr-calendar__day",
3538
+ isStart || isEnd ? "rf-dr-calendar__day--selected" : "",
3539
+ isToday && !isStart && !isEnd ? "rf-dr-calendar__day--today" : ""
3540
+ ].filter(Boolean).join(" ");
3541
+ return /* @__PURE__ */ import_react21.default.createElement(
3498
3542
  "div",
3499
3543
  {
3500
- className: [
3501
- "rf-dr-picker__date-field",
3502
- inlineCal === "end" ? "rf-dr-picker__date-field--active" : ""
3503
- ].filter(Boolean).join(" ")
3544
+ key: day,
3545
+ className: cellClasses,
3546
+ onMouseEnter: () => onDayHover(cellDate),
3547
+ onMouseLeave: () => onDayHover(null)
3504
3548
  },
3505
- /* @__PURE__ */ import_react20.default.createElement("span", { className: "rf-dr-picker__date-floating-label" }, "End Date"),
3506
- /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__date-display" }, /* @__PURE__ */ import_react20.default.createElement(
3507
- "input",
3508
- {
3509
- type: "text",
3510
- className: "rf-dr-picker__date-input",
3511
- value: endInputStr,
3512
- placeholder: "DD Mon YYYY",
3513
- onChange: handleEndInputChange,
3514
- onBlur: handleEndInputBlur,
3515
- onMouseDown: (e) => e.stopPropagation()
3516
- }
3517
- ), /* @__PURE__ */ import_react20.default.createElement(
3549
+ /* @__PURE__ */ import_react21.default.createElement(
3518
3550
  "button",
3519
3551
  {
3520
3552
  type: "button",
3521
- className: "rf-dr-picker__cal-icon-btn",
3522
- onMouseDown: (e) => e.stopPropagation(),
3523
- onClick: () => setInlineCal((v) => v === "end" ? null : "end"),
3524
- "aria-label": "Pick end date"
3525
- },
3526
- /* @__PURE__ */ import_react20.default.createElement(CalendarIcon2, null)
3527
- ))
3528
- ), inlineCal === "end" && /* @__PURE__ */ import_react20.default.createElement(
3529
- MiniCalendar,
3530
- {
3531
- selectedDate: draftEnd,
3532
- todayDate: today2,
3533
- onSelect: (d) => {
3534
- setDraftEnd(d);
3535
- setEndInputStr(formatShort(d));
3553
+ className: dayClasses,
3554
+ onClick: () => onDayClick(cellDate)
3536
3555
  },
3537
- onClose: () => setInlineCal(null)
3538
- }
3539
- )), !inlineCal && /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__days-section" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__days-row" }, /* @__PURE__ */ import_react20.default.createElement("span", { className: "rf-dr-picker__days-label" }, "Days until today"), /* @__PURE__ */ import_react20.default.createElement(
3540
- "input",
3541
- {
3542
- type: "number",
3543
- className: "rf-dr-picker__days-input",
3544
- value: draftStart ? daysUntilToday : "",
3545
- min: 0,
3546
- onChange: handleDaysUntilChange,
3547
- onMouseDown: (e) => e.stopPropagation(),
3548
- placeholder: "\u2014"
3549
- }
3550
- )), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__days-row" }, /* @__PURE__ */ import_react20.default.createElement("span", { className: "rf-dr-picker__days-label" }, "Days from today"), /* @__PURE__ */ import_react20.default.createElement(
3551
- "input",
3552
- {
3553
- type: "number",
3554
- className: "rf-dr-picker__days-input",
3555
- value: draftEnd ? daysFromToday : "",
3556
- min: 0,
3557
- onChange: handleDaysFromChange,
3558
- onMouseDown: (e) => e.stopPropagation(),
3559
- placeholder: "\u2014"
3560
- }
3561
- ))), /* @__PURE__ */ import_react20.default.createElement("div", { style: { flex: 1 } }), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__footer" }, /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-dr-picker__close-btn", onClick: handleClose }, "CLOSE"), /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-dr-picker__apply-btn", onClick: handleApply }, "APPLY"))))
3562
- ) : (
3563
- /* ── Calendar Mode ── */
3564
- /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker rf-dr-picker--calendar", onMouseDown: (e) => e.preventDefault() }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__calendars" }, /* @__PURE__ */ import_react20.default.createElement(
3565
- RangeCalendarBody,
3566
- {
3567
- viewYear: leftViewYear,
3568
- viewMonth: leftViewMonth,
3569
- startDate: draftStart,
3570
- endDate: draftEnd,
3571
- hoverDate: selecting === "end" ? hoverDate : null,
3572
- todayDate: today2,
3573
- onDayClick: handleCalDayClick,
3574
- onDayHover: setHoverDate,
3575
- onPrev: prevMonth,
3576
- onNext: nextMonth,
3577
- showNext: false
3578
- }
3579
- ), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__cal-col-divider" }), /* @__PURE__ */ import_react20.default.createElement(
3580
- RangeCalendarBody,
3581
- {
3582
- viewYear: rightViewYear,
3583
- viewMonth: rightViewMonth,
3584
- startDate: draftStart,
3585
- endDate: draftEnd,
3586
- hoverDate: selecting === "end" ? hoverDate : null,
3587
- todayDate: today2,
3588
- onDayClick: handleCalDayClick,
3589
- onDayHover: setHoverDate,
3590
- onPrev: prevMonth,
3591
- onNext: nextMonth,
3592
- showPrev: false
3593
- }
3594
- )), selecting === "end" && draftStart && /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__cal-hint" }, /* @__PURE__ */ import_react20.default.createElement("span", { className: "rf-dr-picker__cal-hint-dot" }), /* @__PURE__ */ import_react20.default.createElement("span", null, "Select end date \xB7 started from ", /* @__PURE__ */ import_react20.default.createElement("strong", null, formatShort(draftStart)))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__divider" }), /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-dr-picker__cal-footer" }, draftStart && draftEnd && /* @__PURE__ */ import_react20.default.createElement("span", { className: "rf-dr-picker__cal-range-label" }, formatShort(draftStart <= draftEnd ? draftStart : draftEnd), " \u2013 ", formatShort(draftStart <= draftEnd ? draftEnd : draftStart), /* @__PURE__ */ import_react20.default.createElement("span", { className: "rf-dr-picker__cal-range-days" }, " ", "(", Math.abs(daysBetween(draftStart, draftEnd)) + 1, " days)")), /* @__PURE__ */ import_react20.default.createElement("div", { style: { flex: 1 } }), /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-dr-picker__close-btn", onClick: handleClose }, "CLOSE"), /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", className: "rf-dr-picker__apply-btn", onClick: handleApply }, "APPLY")))
3595
- ))), helperText && /* @__PURE__ */ import_react20.default.createElement("div", { className: "rf-text-field__helper-text" }, helperText));
3556
+ day
3557
+ )
3558
+ );
3559
+ })));
3596
3560
  };
3597
- DateRangeField.displayName = "DateRangeField";
3598
-
3599
- // lib/TextFields/Autocomplete.tsx
3600
- var import_react21 = __toESM(require("react"), 1);
3601
- var import_react_dom3 = __toESM(require("react-dom"), 1);
3602
- var ChevronDownIcon = () => /* @__PURE__ */ import_react21.default.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react21.default.createElement("polyline", { points: "6 9 12 15 18 9" }));
3603
- var CloseSmIcon = ({ size = 16 }) => /* @__PURE__ */ import_react21.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" }, /* @__PURE__ */ import_react21.default.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), /* @__PURE__ */ import_react21.default.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" }));
3604
- var CheckIcon = () => /* @__PURE__ */ import_react21.default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react21.default.createElement("polyline", { points: "20 6 9 17 4 12" }));
3605
- function defaultGetLabel(option) {
3606
- if (option === null || option === void 0) return "";
3607
- if (typeof option === "string") return option;
3608
- if (typeof option === "object" && "label" in option)
3609
- return String(option.label);
3610
- return String(option);
3611
- }
3612
- function defaultFilter(options, inputValue, getLabel) {
3613
- if (!inputValue) return options;
3614
- const q = inputValue.toLowerCase();
3615
- return options.filter((o) => getLabel(o).toLowerCase().includes(q));
3616
- }
3617
- function AutocompleteInner(props, _ref) {
3618
- const {
3619
- options,
3620
- value,
3621
- onChange,
3622
- inputValue: controlledInput,
3623
- onInputChange,
3624
- getOptionLabel = defaultGetLabel,
3625
- isOptionEqualToValue,
3626
- groupBy,
3627
- filterOptions,
3628
- renderOption,
3629
- getOptionDisabled,
3630
- multiple = false,
3631
- freeSolo = false,
3632
- clearable = true,
3633
- loading = false,
3634
- loadingText = "Loading\u2026",
3635
- noOptionsText = "No options",
3636
- limitTags,
3637
- label,
3638
- placeholder,
3639
- variant = "outlined",
3640
- size = "medium",
3641
- error = false,
3642
- helperText,
3643
- fullWidth = false,
3644
- disabled = false,
3645
- required = false,
3646
- className = "",
3647
- style,
3648
- sx,
3649
- onOpen,
3650
- onClose
3651
- } = props;
3652
- const [open, setOpen] = (0, import_react21.useState)(false);
3653
- const [inputStr, setInputStr] = (0, import_react21.useState)("");
3654
- const [focusedIdx, setFocusedIdx] = (0, import_react21.useState)(-1);
3655
- const [popupStyle, setPopupStyle] = (0, import_react21.useState)({});
3656
- const containerRef = (0, import_react21.useRef)(null);
3657
- const inputRef = (0, import_react21.useRef)(null);
3658
- const listRef = (0, import_react21.useRef)(null);
3659
- const inputId = (0, import_react21.useRef)(`rf-ac-${Math.random().toString(36).slice(2, 9)}`).current;
3660
- const sxClass = useSx(sx);
3661
- const calcPopupStyle = (0, import_react21.useCallback)(() => {
3662
- if (!containerRef.current) return;
3663
- const rect = containerRef.current.getBoundingClientRect();
3664
- setPopupStyle({
3665
- top: rect.bottom + 4,
3666
- left: rect.left,
3667
- width: rect.width
3668
- });
3669
- }, []);
3670
- const activeInput = controlledInput !== void 0 ? controlledInput : inputStr;
3671
- const selectedValues = multiple ? Array.isArray(value) ? value : [] : value != null ? [value] : [];
3672
- const isEqual = (0, import_react21.useCallback)(
3673
- (a, b) => isOptionEqualToValue ? isOptionEqualToValue(a, b) : a === b,
3674
- [isOptionEqualToValue]
3675
- );
3676
- const isSelected = (0, import_react21.useCallback)(
3677
- (opt) => selectedValues.some((v) => isEqual(opt, v)),
3678
- [selectedValues, isEqual]
3679
- );
3680
- const filtered = filterOptions ? filterOptions(options, activeInput) : defaultFilter(options, activeInput, getOptionLabel);
3681
- const flatEntries = [];
3682
- if (groupBy) {
3683
- const groups = {};
3684
- const order = [];
3685
- filtered.forEach((opt) => {
3686
- const g = groupBy(opt);
3687
- if (!groups[g]) {
3688
- groups[g] = [];
3689
- order.push(g);
3690
- }
3691
- groups[g].push(opt);
3692
- });
3693
- order.forEach((g) => {
3694
- flatEntries.push({ kind: "group", label: g });
3695
- groups[g].forEach((opt) => {
3696
- flatEntries.push({ kind: "option", option: opt, flatIdx: flatEntries.filter((e) => e.kind === "option").length });
3697
- });
3698
- });
3699
- } else {
3700
- filtered.forEach((opt, i) => flatEntries.push({ kind: "option", option: opt, flatIdx: i }));
3701
- }
3702
- const selectableOptions = flatEntries.filter((e) => e.kind === "option");
3703
- const openPopup = (0, import_react21.useCallback)(() => {
3704
- if (disabled) return;
3705
- calcPopupStyle();
3706
- setOpen(true);
3707
- setFocusedIdx(-1);
3708
- onOpen?.();
3709
- }, [disabled, calcPopupStyle, onOpen]);
3710
- const closePopup = (0, import_react21.useCallback)(() => {
3711
- setOpen(false);
3712
- setFocusedIdx(-1);
3713
- onClose?.();
3714
- if (!freeSolo && !multiple && value == null) {
3715
- setInputStr("");
3716
- onInputChange?.("");
3561
+ var MiniCalendar = ({ selectedDate, todayDate, onSelect, onClose }) => {
3562
+ const init = selectedDate ?? todayDate;
3563
+ const [viewYear, setViewYear] = (0, import_react21.useState)(init.getFullYear());
3564
+ const [viewMonth, setViewMonth] = (0, import_react21.useState)(init.getMonth());
3565
+ const firstDay = new Date(viewYear, viewMonth, 1).getDay();
3566
+ const daysInMonth = new Date(viewYear, viewMonth + 1, 0).getDate();
3567
+ const dayCells = [
3568
+ ...Array(firstDay).fill(null),
3569
+ ...Array.from({ length: daysInMonth }, (_, i) => i + 1)
3570
+ ];
3571
+ const prevMonth = () => {
3572
+ if (viewMonth === 0) {
3573
+ setViewMonth(11);
3574
+ setViewYear((y) => y - 1);
3575
+ } else setViewMonth((m) => m - 1);
3576
+ };
3577
+ const nextMonth = () => {
3578
+ if (viewMonth === 11) {
3579
+ setViewMonth(0);
3580
+ setViewYear((y) => y + 1);
3581
+ } else setViewMonth((m) => m + 1);
3582
+ };
3583
+ return /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-mini-cal" }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-mini-cal__header" }, /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-dr-calendar__nav-btn", onClick: prevMonth }, "\u2039"), /* @__PURE__ */ import_react21.default.createElement("span", { className: "rf-dr-calendar__month-label", style: { fontSize: "0.88rem" } }, MONTHS2[viewMonth], " ", viewYear), /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-dr-calendar__nav-btn", onClick: nextMonth }, "\u203A")), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-calendar__weekdays" }, WEEKDAYS2.map((w) => /* @__PURE__ */ import_react21.default.createElement("div", { key: w, className: "rf-dr-calendar__weekday" }, w))), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-calendar__grid" }, dayCells.map((day, idx) => {
3584
+ if (day === null) {
3585
+ return /* @__PURE__ */ import_react21.default.createElement("div", { key: `e-${idx}`, className: "rf-dr-calendar__cell rf-dr-calendar__cell--empty" });
3717
3586
  }
3718
- }, [freeSolo, multiple, value, onInputChange, onClose]);
3587
+ const cellDate = new Date(viewYear, viewMonth, day);
3588
+ const isSel = selectedDate ? isSameDay2(cellDate, selectedDate) : false;
3589
+ const isToday = isSameDay2(cellDate, todayDate);
3590
+ return /* @__PURE__ */ import_react21.default.createElement("div", { key: day, className: "rf-dr-calendar__cell" }, /* @__PURE__ */ import_react21.default.createElement(
3591
+ "button",
3592
+ {
3593
+ type: "button",
3594
+ className: [
3595
+ "rf-dr-calendar__day",
3596
+ isSel ? "rf-dr-calendar__day--selected" : "",
3597
+ isToday && !isSel ? "rf-dr-calendar__day--today" : ""
3598
+ ].filter(Boolean).join(" "),
3599
+ onClick: () => {
3600
+ onSelect(cellDate);
3601
+ onClose();
3602
+ }
3603
+ },
3604
+ day
3605
+ ));
3606
+ })));
3607
+ };
3608
+ var DateRangeField = ({
3609
+ label,
3610
+ value,
3611
+ onChange,
3612
+ pickerType = "panel",
3613
+ variant = "outlined",
3614
+ size = "medium",
3615
+ color = "primary",
3616
+ error = false,
3617
+ helperText,
3618
+ fullWidth = false,
3619
+ disabled = false,
3620
+ required = false,
3621
+ className = "",
3622
+ style,
3623
+ sx
3624
+ }) => {
3625
+ const sxClass = useSx(sx);
3626
+ const today2 = todayFn();
3627
+ const committedStart = value?.start ? isoToDate2(value.start) : null;
3628
+ const committedEnd = value?.end ? isoToDate2(value.end) : null;
3629
+ const [open, setOpen] = (0, import_react21.useState)(false);
3630
+ const [draftStart, setDraftStart] = (0, import_react21.useState)(committedStart);
3631
+ const [draftEnd, setDraftEnd] = (0, import_react21.useState)(committedEnd);
3632
+ const [activePreset, setActivePreset] = (0, import_react21.useState)(
3633
+ () => detectPreset(committedStart, committedEnd)
3634
+ );
3635
+ const [startInputStr, setStartInputStr] = (0, import_react21.useState)(() => committedStart ? formatShort(committedStart) : "");
3636
+ const [endInputStr, setEndInputStr] = (0, import_react21.useState)(() => committedEnd ? formatShort(committedEnd) : "");
3637
+ const [inlineCal, setInlineCal] = (0, import_react21.useState)(null);
3638
+ const [hoverDate, setHoverDate] = (0, import_react21.useState)(null);
3639
+ const [selecting, setSelecting] = (0, import_react21.useState)("start");
3640
+ const [leftViewYear, setLeftViewYear] = (0, import_react21.useState)(() => today2.getFullYear());
3641
+ const [leftViewMonth, setLeftViewMonth] = (0, import_react21.useState)(() => today2.getMonth());
3642
+ const containerRef = (0, import_react21.useRef)(null);
3643
+ const inputId = (0, import_react21.useRef)(`rf-dr-${Math.random().toString(36).substr(2, 9)}`).current;
3644
+ (0, import_react21.useEffect)(() => {
3645
+ const s2 = value?.start ? isoToDate2(value.start) : null;
3646
+ const e = value?.end ? isoToDate2(value.end) : null;
3647
+ setDraftStart(s2);
3648
+ setDraftEnd(e);
3649
+ setStartInputStr(s2 ? formatShort(s2) : "");
3650
+ setEndInputStr(e ? formatShort(e) : "");
3651
+ setActivePreset(detectPreset(s2, e));
3652
+ }, [value?.start, value?.end]);
3653
+ (0, import_react21.useEffect)(() => {
3654
+ setActivePreset(detectPreset(draftStart, draftEnd));
3655
+ }, [draftStart?.getTime(), draftEnd?.getTime()]);
3719
3656
  (0, import_react21.useEffect)(() => {
3720
3657
  if (!open) return;
3721
- const handleOutside = (e) => {
3658
+ const handler = (e) => {
3722
3659
  if (containerRef.current && !containerRef.current.contains(e.target)) {
3723
- closePopup();
3660
+ setOpen(false);
3661
+ setInlineCal(null);
3662
+ setDraftStart(committedStart);
3663
+ setDraftEnd(committedEnd);
3664
+ setStartInputStr(committedStart ? formatShort(committedStart) : "");
3665
+ setEndInputStr(committedEnd ? formatShort(committedEnd) : "");
3666
+ setActivePreset(detectPreset(committedStart, committedEnd));
3667
+ setSelecting("start");
3724
3668
  }
3725
3669
  };
3726
- document.addEventListener("mousedown", handleOutside);
3727
- window.addEventListener("scroll", calcPopupStyle, true);
3728
- window.addEventListener("resize", calcPopupStyle);
3729
- return () => {
3730
- document.removeEventListener("mousedown", handleOutside);
3731
- window.removeEventListener("scroll", calcPopupStyle, true);
3732
- window.removeEventListener("resize", calcPopupStyle);
3733
- };
3734
- }, [open, closePopup, calcPopupStyle]);
3735
- (0, import_react21.useEffect)(() => {
3736
- if (controlledInput !== void 0) return;
3737
- if (!multiple) {
3738
- const v = value;
3739
- setInputStr(v != null ? getOptionLabel(v) : "");
3670
+ document.addEventListener("mousedown", handler);
3671
+ return () => document.removeEventListener("mousedown", handler);
3672
+ }, [open, committedStart, committedEnd]);
3673
+ const displayStr = (() => {
3674
+ if (committedStart && committedEnd) {
3675
+ return `${formatShort(committedStart)} \u2013 ${formatShort(committedEnd)}`;
3740
3676
  }
3741
- }, [value, multiple, getOptionLabel, controlledInput]);
3742
- const selectOption = (opt) => {
3743
- if (getOptionDisabled?.(opt)) return;
3744
- if (multiple) {
3745
- const already = isSelected(opt);
3746
- const next = already ? selectedValues.filter((v) => !isEqual(v, opt)) : [...selectedValues, opt];
3747
- onChange?.(next);
3748
- setInputStr("");
3749
- onInputChange?.("");
3750
- inputRef.current?.focus();
3677
+ if (committedStart) return `${formatShort(committedStart)} \u2013`;
3678
+ return "";
3679
+ })();
3680
+ const handleApply = () => {
3681
+ if (draftStart && draftEnd) {
3682
+ const [s2, e] = draftStart <= draftEnd ? [draftStart, draftEnd] : [draftEnd, draftStart];
3683
+ onChange?.({ start: dateToISO(s2), end: dateToISO(e) });
3684
+ } else if (draftStart) {
3685
+ onChange?.({ start: dateToISO(draftStart), end: dateToISO(draftStart) });
3686
+ }
3687
+ setOpen(false);
3688
+ setInlineCal(null);
3689
+ };
3690
+ const handleClose = () => {
3691
+ setOpen(false);
3692
+ setInlineCal(null);
3693
+ setDraftStart(committedStart);
3694
+ setDraftEnd(committedEnd);
3695
+ setStartInputStr(committedStart ? formatShort(committedStart) : "");
3696
+ setEndInputStr(committedEnd ? formatShort(committedEnd) : "");
3697
+ setActivePreset(detectPreset(committedStart, committedEnd));
3698
+ setSelecting("start");
3699
+ };
3700
+ const handlePreset = (presetId) => {
3701
+ const range = getPresetRange(presetId, draftStart);
3702
+ const s2 = isoToDate2(range.start);
3703
+ const e = isoToDate2(range.end);
3704
+ setDraftStart(s2);
3705
+ setDraftEnd(e);
3706
+ setStartInputStr(s2 ? formatShort(s2) : "");
3707
+ setEndInputStr(e ? formatShort(e) : "");
3708
+ setInlineCal(null);
3709
+ };
3710
+ const handleCalDayClick = (d) => {
3711
+ if (selecting === "start") {
3712
+ setDraftStart(d);
3713
+ setDraftEnd(null);
3714
+ setSelecting("end");
3715
+ setActivePreset(null);
3751
3716
  } else {
3752
- onChange?.(opt);
3753
- setInputStr(getOptionLabel(opt));
3754
- onInputChange?.(getOptionLabel(opt));
3755
- closePopup();
3717
+ if (draftStart && d < draftStart) {
3718
+ setDraftEnd(draftStart);
3719
+ setDraftStart(d);
3720
+ } else {
3721
+ setDraftEnd(d);
3722
+ }
3723
+ setSelecting("start");
3724
+ setActivePreset(detectPreset(draftStart, d));
3756
3725
  }
3757
- setFocusedIdx(-1);
3758
3726
  };
3759
- const clearAll = (e) => {
3760
- e.stopPropagation();
3761
- onChange?.(multiple ? [] : null);
3762
- setInputStr("");
3763
- onInputChange?.("");
3764
- inputRef.current?.focus();
3727
+ const rightViewMonth = leftViewMonth === 11 ? 0 : leftViewMonth + 1;
3728
+ const rightViewYear = leftViewMonth === 11 ? leftViewYear + 1 : leftViewYear;
3729
+ const prevMonth = () => {
3730
+ if (leftViewMonth === 0) {
3731
+ setLeftViewMonth(11);
3732
+ setLeftViewYear((y) => y - 1);
3733
+ } else setLeftViewMonth((m) => m - 1);
3765
3734
  };
3766
- const removeTag = (opt, e) => {
3767
- e.stopPropagation();
3768
- const next = selectedValues.filter((v) => !isEqual(v, opt));
3769
- onChange?.(next);
3735
+ const nextMonth = () => {
3736
+ if (leftViewMonth === 11) {
3737
+ setLeftViewMonth(0);
3738
+ setLeftViewYear((y) => y + 1);
3739
+ } else setLeftViewMonth((m) => m + 1);
3770
3740
  };
3771
- const handleInputChange = (e) => {
3772
- const v = e.target.value;
3773
- setInputStr(v);
3774
- onInputChange?.(v);
3775
- if (!open) openPopup();
3741
+ const daysUntilToday = draftStart ? Math.max(0, daysBetween(draftStart, today2)) : 0;
3742
+ const daysFromToday = draftEnd ? Math.max(0, daysBetween(today2, draftEnd)) : 0;
3743
+ const handleDaysUntilChange = (e) => {
3744
+ const n = parseInt(e.target.value, 10);
3745
+ if (!isNaN(n) && n >= 0) {
3746
+ const d = addDays(today2, -n);
3747
+ setDraftStart(d);
3748
+ setStartInputStr(formatShort(d));
3749
+ }
3776
3750
  };
3777
- const handleKeyDown = (e) => {
3778
- if (e.key === "ArrowDown") {
3779
- e.preventDefault();
3780
- if (!open) {
3781
- openPopup();
3782
- return;
3783
- }
3784
- setFocusedIdx((i) => {
3785
- const next = (i + 1) % selectableOptions.length;
3786
- scrollOptionIntoView(next);
3787
- return next;
3788
- });
3789
- } else if (e.key === "ArrowUp") {
3790
- e.preventDefault();
3791
- if (!open) {
3792
- openPopup();
3793
- return;
3794
- }
3795
- setFocusedIdx((i) => {
3796
- const next = (i - 1 + selectableOptions.length) % selectableOptions.length;
3797
- scrollOptionIntoView(next);
3798
- return next;
3799
- });
3800
- } else if (e.key === "Enter") {
3801
- e.preventDefault();
3802
- if (!open) {
3803
- openPopup();
3804
- return;
3805
- }
3806
- if (focusedIdx >= 0 && focusedIdx < selectableOptions.length) {
3807
- selectOption(selectableOptions[focusedIdx].option);
3808
- } else if (freeSolo && activeInput) {
3809
- onChange?.(activeInput);
3810
- if (!multiple) closePopup();
3811
- }
3812
- } else if (e.key === "Escape") {
3813
- closePopup();
3814
- } else if (e.key === "Backspace" && multiple && !activeInput && selectedValues.length > 0) {
3815
- removeTag(selectedValues[selectedValues.length - 1], { stopPropagation: () => {
3816
- } });
3751
+ const handleDaysFromChange = (e) => {
3752
+ const n = parseInt(e.target.value, 10);
3753
+ if (!isNaN(n) && n >= 0) {
3754
+ const d = addDays(today2, n);
3755
+ setDraftEnd(d);
3756
+ setEndInputStr(formatShort(d));
3817
3757
  }
3818
3758
  };
3819
- const scrollOptionIntoView = (idx) => {
3820
- requestAnimationFrame(() => {
3821
- const el = listRef.current?.querySelector(`[data-idx="${idx}"]`);
3822
- el?.scrollIntoView({ block: "nearest" });
3823
- });
3759
+ const handleStartInputChange = (e) => {
3760
+ const raw = e.target.value;
3761
+ setStartInputStr(raw);
3762
+ const parsed = parseInputDate(raw);
3763
+ if (parsed) setDraftStart(parsed);
3764
+ else if (!raw) setDraftStart(null);
3765
+ };
3766
+ const handleStartInputBlur = () => {
3767
+ setStartInputStr(draftStart ? formatShort(draftStart) : "");
3768
+ };
3769
+ const handleEndInputChange = (e) => {
3770
+ const raw = e.target.value;
3771
+ setEndInputStr(raw);
3772
+ const parsed = parseInputDate(raw);
3773
+ if (parsed) setDraftEnd(parsed);
3774
+ else if (!raw) setDraftEnd(null);
3775
+ };
3776
+ const handleEndInputBlur = () => {
3777
+ setEndInputStr(draftEnd ? formatShort(draftEnd) : "");
3824
3778
  };
3825
- const hasClearable = clearable && !disabled && (multiple ? selectedValues.length > 0 : value != null);
3826
- const visibleTags = multiple && limitTags != null ? selectedValues.slice(0, limitTags) : selectedValues;
3827
- const hiddenCount = multiple && limitTags != null ? Math.max(0, selectedValues.length - limitTags) : 0;
3828
- const isFloating = Boolean(
3829
- open || activeInput || (multiple ? selectedValues.length > 0 : value != null)
3830
- );
3779
+ const isFloating = Boolean(displayStr || open);
3831
3780
  const rootClasses = [
3832
3781
  "rf-text-field",
3833
3782
  `rf-text-field--${variant}`,
3834
3783
  `rf-text-field--${size}`,
3835
- "rf-text-field--primary",
3784
+ `rf-text-field--${color}`,
3836
3785
  error ? "rf-text-field--error" : "",
3837
3786
  fullWidth ? "rf-text-field--full-width" : "",
3838
3787
  disabled ? "rf-text-field--disabled" : "",
3839
3788
  isFloating ? "rf-text-field--floating" : "",
3840
- label ? "rf-text-field--has-label" : "",
3789
+ Boolean(label) ? "rf-text-field--has-label" : "",
3841
3790
  "rf-text-field--adorned-end",
3842
- "rf-autocomplete",
3791
+ "rf-date-field",
3792
+ "rf-date-range-field",
3793
+ fullWidth ? "rf-date-field--full-width" : "",
3843
3794
  sxClass,
3844
3795
  className
3845
3796
  ].filter(Boolean).join(" ");
3846
- const inputPlaceholder = placeholder || (variant === "outlined" ? " " : void 0);
3847
- return /* @__PURE__ */ import_react21.default.createElement("div", { ref: containerRef, className: rootClasses, style }, /* @__PURE__ */ import_react21.default.createElement(
3797
+ const inputPlaceholder = variant === "outlined" ? " " : void 0;
3798
+ return /* @__PURE__ */ import_react21.default.createElement("div", { ref: containerRef, className: rootClasses, style }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-date-field__anchor" }, /* @__PURE__ */ import_react21.default.createElement(
3848
3799
  "div",
3849
3800
  {
3850
3801
  className: "rf-text-field__wrapper",
3851
3802
  onClick: () => {
3852
- if (!disabled) {
3853
- inputRef.current?.focus();
3854
- if (!open) openPopup();
3855
- }
3856
- }
3857
- },
3858
- multiple && visibleTags.map((opt, i) => /* @__PURE__ */ import_react21.default.createElement("span", { key: i, className: "rf-autocomplete__tag" }, /* @__PURE__ */ import_react21.default.createElement("span", { style: { overflow: "hidden", textOverflow: "ellipsis" } }, getOptionLabel(opt)), /* @__PURE__ */ import_react21.default.createElement(
3859
- "button",
3860
- {
3861
- type: "button",
3862
- className: "rf-autocomplete__tag-delete",
3863
- onMouseDown: (e) => e.preventDefault(),
3864
- onClick: (e) => removeTag(opt, e),
3865
- tabIndex: -1
3803
+ if (!disabled) setOpen((o) => !o);
3866
3804
  },
3867
- /* @__PURE__ */ import_react21.default.createElement(CloseSmIcon, { size: 12 })
3868
- ))),
3869
- hiddenCount > 0 && /* @__PURE__ */ import_react21.default.createElement("span", { className: "rf-autocomplete__tag-more" }, "+", hiddenCount, " more"),
3805
+ style: { cursor: disabled ? "default" : "pointer" }
3806
+ },
3870
3807
  /* @__PURE__ */ import_react21.default.createElement(
3871
3808
  "input",
3872
3809
  {
3873
- ref: inputRef,
3874
3810
  id: inputId,
3875
3811
  className: "rf-text-field__input",
3876
3812
  type: "text",
3877
- value: activeInput,
3878
- onChange: handleInputChange,
3879
- onFocus: () => {
3880
- if (!open) openPopup();
3881
- },
3882
- onKeyDown: handleKeyDown,
3883
- placeholder: !multiple || selectedValues.length === 0 ? inputPlaceholder : void 0,
3813
+ value: displayStr,
3814
+ readOnly: true,
3815
+ placeholder: inputPlaceholder,
3884
3816
  disabled,
3885
- autoComplete: "off",
3886
- role: "combobox",
3887
- "aria-expanded": open,
3888
- "aria-haspopup": "listbox",
3889
- "aria-autocomplete": "list"
3817
+ onClick: (e) => e.stopPropagation(),
3818
+ onFocus: () => {
3819
+ if (!disabled) setOpen(true);
3820
+ }
3890
3821
  }
3891
3822
  ),
3892
- label && /* @__PURE__ */ import_react21.default.createElement("label", { htmlFor: inputId, className: "rf-text-field__label" }, label, required && /* @__PURE__ */ import_react21.default.createElement("span", { className: "rf-text-field__asterisk" }, " *")),
3893
- variant === "outlined" && /* @__PURE__ */ import_react21.default.createElement("fieldset", { className: "rf-text-field__notch" }, label ? /* @__PURE__ */ import_react21.default.createElement("legend", { className: "rf-text-field__legend" }, /* @__PURE__ */ import_react21.default.createElement("span", null, label, required ? " *" : "")) : /* @__PURE__ */ import_react21.default.createElement("legend", { className: "rf-text-field__legend--empty" })),
3894
- /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-autocomplete__endgroup" }, hasClearable && /* @__PURE__ */ import_react21.default.createElement(
3823
+ /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-text-field__adornment rf-text-field__adornment--end" }, /* @__PURE__ */ import_react21.default.createElement(
3895
3824
  "button",
3896
3825
  {
3897
3826
  type: "button",
3898
- className: "rf-autocomplete__icon-btn",
3899
- onMouseDown: (e) => e.preventDefault(),
3900
- onClick: clearAll,
3827
+ className: "rf-date-field__icon-btn",
3901
3828
  tabIndex: -1,
3902
- "aria-label": "Clear"
3829
+ disabled,
3830
+ onClick: (e) => {
3831
+ e.stopPropagation();
3832
+ if (!disabled) setOpen((o) => !o);
3833
+ },
3834
+ "aria-label": "Pick date range"
3903
3835
  },
3904
- /* @__PURE__ */ import_react21.default.createElement(CloseSmIcon, { size: 16 })
3905
- ), !freeSolo && /* @__PURE__ */ import_react21.default.createElement(
3836
+ /* @__PURE__ */ import_react21.default.createElement(CalendarIcon2, null)
3837
+ )),
3838
+ label && /* @__PURE__ */ import_react21.default.createElement("label", { htmlFor: inputId, className: "rf-text-field__label" }, label, " ", required && /* @__PURE__ */ import_react21.default.createElement("span", { className: "rf-text-field__asterisk" }, "*")),
3839
+ variant === "outlined" && /* @__PURE__ */ import_react21.default.createElement("fieldset", { className: "rf-text-field__notch" }, label ? /* @__PURE__ */ import_react21.default.createElement("legend", { className: "rf-text-field__legend" }, /* @__PURE__ */ import_react21.default.createElement("span", null, label, required ? " *" : "")) : /* @__PURE__ */ import_react21.default.createElement("legend", { className: "rf-text-field__legend--empty" }))
3840
+ ), open && !disabled && (pickerType === "panel" ? (
3841
+ /* ── Panel Mode ── */
3842
+ /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker rf-dr-picker--panel", onMouseDown: (e) => e.preventDefault() }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__presets" }, PRESETS.map((p, i) => /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, { key: p.id }, i > 0 && /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__preset-sep" }), /* @__PURE__ */ import_react21.default.createElement(
3906
3843
  "button",
3907
3844
  {
3908
3845
  type: "button",
3909
- className: `rf-autocomplete__icon-btn rf-autocomplete__icon-btn--popup ${open ? "rf-autocomplete__icon-btn--open" : ""}`,
3910
- onMouseDown: (e) => {
3911
- e.preventDefault();
3912
- open ? closePopup() : openPopup();
3913
- },
3914
- tabIndex: -1,
3915
- "aria-label": open ? "Close" : "Open"
3846
+ className: [
3847
+ "rf-dr-picker__preset-btn",
3848
+ activePreset === p.id ? "rf-dr-picker__preset-btn--active" : ""
3849
+ ].filter(Boolean).join(" "),
3850
+ onClick: () => handlePreset(p.id)
3916
3851
  },
3917
- /* @__PURE__ */ import_react21.default.createElement(ChevronDownIcon, null)
3918
- ))
3919
- ), helperText && /* @__PURE__ */ import_react21.default.createElement("div", { className: `rf-text-field__helper-text${error ? " rf-text-field__helper-text--error" : ""}` }, helperText), open && !disabled && import_react_dom3.default.createPortal(
3920
- /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-autocomplete__popup", role: "presentation", style: popupStyle }, loading ? /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-autocomplete__loading" }, /* @__PURE__ */ import_react21.default.createElement("span", { className: "rf-ac-spinner" }), loadingText) : flatEntries.length === 0 ? /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-autocomplete__no-options" }, noOptionsText) : /* @__PURE__ */ import_react21.default.createElement("ul", { ref: listRef, className: "rf-autocomplete__listbox", role: "listbox" }, groupBy ? (
3921
- // Grouped render
3922
- (() => {
3923
- const rendered = [];
3924
- let groupItems = [];
3925
- let currentGroup = "";
3926
- flatEntries.forEach((entry, ei) => {
3927
- if (entry.kind === "group") {
3928
- if (groupItems.length > 0) {
3929
- rendered.push(
3930
- /* @__PURE__ */ import_react21.default.createElement("li", { key: `g-${currentGroup}`, role: "presentation" }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-autocomplete__group-header" }, currentGroup), /* @__PURE__ */ import_react21.default.createElement("ul", { className: "rf-autocomplete__group-items", role: "group" }, groupItems))
3931
- );
3932
- groupItems = [];
3933
- }
3934
- currentGroup = entry.label;
3935
- } else {
3936
- const { option, flatIdx } = entry;
3937
- groupItems.push(renderOptionItem(option, flatIdx));
3938
- }
3939
- if (ei === flatEntries.length - 1 && groupItems.length > 0) {
3940
- rendered.push(
3941
- /* @__PURE__ */ import_react21.default.createElement("li", { key: `g-${currentGroup}`, role: "presentation" }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-autocomplete__group-header" }, currentGroup), /* @__PURE__ */ import_react21.default.createElement("ul", { className: "rf-autocomplete__group-items", role: "group" }, groupItems))
3942
- );
3943
- }
3944
- });
3945
- return rendered;
3946
- })()
3947
- ) : selectableOptions.map(({ option, flatIdx }) => renderOptionItem(option, flatIdx)))),
3948
- document.body
3949
- ));
3950
- function renderOptionItem(option, flatIdx) {
3951
- const selected = isSelected(option);
3952
- const focused = focusedIdx === flatIdx;
3953
- const optDisabled = getOptionDisabled?.(option) ?? false;
3954
- const label2 = getOptionLabel(option);
3955
- return /* @__PURE__ */ import_react21.default.createElement(
3956
- "li",
3852
+ p.label
3853
+ )))), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__manual" }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__date-field-wrap" }, /* @__PURE__ */ import_react21.default.createElement(
3854
+ "div",
3957
3855
  {
3958
- key: label2 + flatIdx,
3959
- "data-idx": flatIdx,
3960
- role: "option",
3961
- "aria-selected": selected,
3962
- "aria-disabled": optDisabled,
3963
3856
  className: [
3964
- "rf-autocomplete__option",
3965
- selected ? "rf-autocomplete__option--selected" : "",
3966
- focused ? "rf-autocomplete__option--focused" : "",
3967
- optDisabled ? "rf-autocomplete__option--disabled" : ""
3968
- ].filter(Boolean).join(" "),
3969
- onMouseEnter: () => setFocusedIdx(flatIdx),
3970
- onMouseLeave: () => setFocusedIdx(-1),
3971
- onMouseDown: (e) => e.preventDefault(),
3972
- onClick: () => selectOption(option)
3857
+ "rf-dr-picker__date-field",
3858
+ inlineCal === "start" ? "rf-dr-picker__date-field--active" : ""
3859
+ ].filter(Boolean).join(" ")
3973
3860
  },
3974
- renderOption ? renderOption(option, { selected, focused, index: flatIdx }) : /* @__PURE__ */ import_react21.default.createElement("span", { style: { flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, label2),
3975
- !renderOption && /* @__PURE__ */ import_react21.default.createElement("span", { className: "rf-autocomplete__option-check" }, /* @__PURE__ */ import_react21.default.createElement(CheckIcon, null))
3976
- );
3977
- }
3978
- }
3979
- var Autocomplete = import_react21.default.forwardRef(AutocompleteInner);
3980
- Autocomplete.displayName = "Autocomplete";
3861
+ /* @__PURE__ */ import_react21.default.createElement("span", { className: "rf-dr-picker__date-floating-label" }, "Start Date"),
3862
+ /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__date-display" }, /* @__PURE__ */ import_react21.default.createElement(
3863
+ "input",
3864
+ {
3865
+ type: "text",
3866
+ className: "rf-dr-picker__date-input",
3867
+ value: startInputStr,
3868
+ placeholder: "DD Mon YYYY",
3869
+ onChange: handleStartInputChange,
3870
+ onBlur: handleStartInputBlur,
3871
+ onMouseDown: (e) => e.stopPropagation()
3872
+ }
3873
+ ), /* @__PURE__ */ import_react21.default.createElement(
3874
+ "button",
3875
+ {
3876
+ type: "button",
3877
+ className: "rf-dr-picker__cal-icon-btn",
3878
+ onMouseDown: (e) => e.stopPropagation(),
3879
+ onClick: () => setInlineCal((v) => v === "start" ? null : "start"),
3880
+ "aria-label": "Pick start date"
3881
+ },
3882
+ /* @__PURE__ */ import_react21.default.createElement(CalendarIcon2, null)
3883
+ ))
3884
+ ), inlineCal === "start" && /* @__PURE__ */ import_react21.default.createElement(
3885
+ MiniCalendar,
3886
+ {
3887
+ selectedDate: draftStart,
3888
+ todayDate: today2,
3889
+ onSelect: (d) => {
3890
+ setDraftStart(d);
3891
+ setStartInputStr(formatShort(d));
3892
+ },
3893
+ onClose: () => setInlineCal(null)
3894
+ }
3895
+ )), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__date-field-wrap" }, /* @__PURE__ */ import_react21.default.createElement(
3896
+ "div",
3897
+ {
3898
+ className: [
3899
+ "rf-dr-picker__date-field",
3900
+ inlineCal === "end" ? "rf-dr-picker__date-field--active" : ""
3901
+ ].filter(Boolean).join(" ")
3902
+ },
3903
+ /* @__PURE__ */ import_react21.default.createElement("span", { className: "rf-dr-picker__date-floating-label" }, "End Date"),
3904
+ /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__date-display" }, /* @__PURE__ */ import_react21.default.createElement(
3905
+ "input",
3906
+ {
3907
+ type: "text",
3908
+ className: "rf-dr-picker__date-input",
3909
+ value: endInputStr,
3910
+ placeholder: "DD Mon YYYY",
3911
+ onChange: handleEndInputChange,
3912
+ onBlur: handleEndInputBlur,
3913
+ onMouseDown: (e) => e.stopPropagation()
3914
+ }
3915
+ ), /* @__PURE__ */ import_react21.default.createElement(
3916
+ "button",
3917
+ {
3918
+ type: "button",
3919
+ className: "rf-dr-picker__cal-icon-btn",
3920
+ onMouseDown: (e) => e.stopPropagation(),
3921
+ onClick: () => setInlineCal((v) => v === "end" ? null : "end"),
3922
+ "aria-label": "Pick end date"
3923
+ },
3924
+ /* @__PURE__ */ import_react21.default.createElement(CalendarIcon2, null)
3925
+ ))
3926
+ ), inlineCal === "end" && /* @__PURE__ */ import_react21.default.createElement(
3927
+ MiniCalendar,
3928
+ {
3929
+ selectedDate: draftEnd,
3930
+ todayDate: today2,
3931
+ onSelect: (d) => {
3932
+ setDraftEnd(d);
3933
+ setEndInputStr(formatShort(d));
3934
+ },
3935
+ onClose: () => setInlineCal(null)
3936
+ }
3937
+ )), !inlineCal && /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__days-section" }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__days-row" }, /* @__PURE__ */ import_react21.default.createElement("span", { className: "rf-dr-picker__days-label" }, "Days until today"), /* @__PURE__ */ import_react21.default.createElement(
3938
+ "input",
3939
+ {
3940
+ type: "number",
3941
+ className: "rf-dr-picker__days-input",
3942
+ value: draftStart ? daysUntilToday : "",
3943
+ min: 0,
3944
+ onChange: handleDaysUntilChange,
3945
+ onMouseDown: (e) => e.stopPropagation(),
3946
+ placeholder: "\u2014"
3947
+ }
3948
+ )), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__days-row" }, /* @__PURE__ */ import_react21.default.createElement("span", { className: "rf-dr-picker__days-label" }, "Days from today"), /* @__PURE__ */ import_react21.default.createElement(
3949
+ "input",
3950
+ {
3951
+ type: "number",
3952
+ className: "rf-dr-picker__days-input",
3953
+ value: draftEnd ? daysFromToday : "",
3954
+ min: 0,
3955
+ onChange: handleDaysFromChange,
3956
+ onMouseDown: (e) => e.stopPropagation(),
3957
+ placeholder: "\u2014"
3958
+ }
3959
+ ))), /* @__PURE__ */ import_react21.default.createElement("div", { style: { flex: 1 } }), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__footer" }, /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-dr-picker__close-btn", onClick: handleClose }, "CLOSE"), /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-dr-picker__apply-btn", onClick: handleApply }, "APPLY"))))
3960
+ ) : (
3961
+ /* ── Calendar Mode ── */
3962
+ /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker rf-dr-picker--calendar", onMouseDown: (e) => e.preventDefault() }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__calendars" }, /* @__PURE__ */ import_react21.default.createElement(
3963
+ RangeCalendarBody,
3964
+ {
3965
+ viewYear: leftViewYear,
3966
+ viewMonth: leftViewMonth,
3967
+ startDate: draftStart,
3968
+ endDate: draftEnd,
3969
+ hoverDate: selecting === "end" ? hoverDate : null,
3970
+ todayDate: today2,
3971
+ onDayClick: handleCalDayClick,
3972
+ onDayHover: setHoverDate,
3973
+ onPrev: prevMonth,
3974
+ onNext: nextMonth,
3975
+ showNext: false
3976
+ }
3977
+ ), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__cal-col-divider" }), /* @__PURE__ */ import_react21.default.createElement(
3978
+ RangeCalendarBody,
3979
+ {
3980
+ viewYear: rightViewYear,
3981
+ viewMonth: rightViewMonth,
3982
+ startDate: draftStart,
3983
+ endDate: draftEnd,
3984
+ hoverDate: selecting === "end" ? hoverDate : null,
3985
+ todayDate: today2,
3986
+ onDayClick: handleCalDayClick,
3987
+ onDayHover: setHoverDate,
3988
+ onPrev: prevMonth,
3989
+ onNext: nextMonth,
3990
+ showPrev: false
3991
+ }
3992
+ )), selecting === "end" && draftStart && /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__cal-hint" }, /* @__PURE__ */ import_react21.default.createElement("span", { className: "rf-dr-picker__cal-hint-dot" }), /* @__PURE__ */ import_react21.default.createElement("span", null, "Select end date \xB7 started from ", /* @__PURE__ */ import_react21.default.createElement("strong", null, formatShort(draftStart)))), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__divider" }), /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-dr-picker__cal-footer" }, draftStart && draftEnd && /* @__PURE__ */ import_react21.default.createElement("span", { className: "rf-dr-picker__cal-range-label" }, formatShort(draftStart <= draftEnd ? draftStart : draftEnd), " \u2013 ", formatShort(draftStart <= draftEnd ? draftEnd : draftStart), /* @__PURE__ */ import_react21.default.createElement("span", { className: "rf-dr-picker__cal-range-days" }, " ", "(", Math.abs(daysBetween(draftStart, draftEnd)) + 1, " days)")), /* @__PURE__ */ import_react21.default.createElement("div", { style: { flex: 1 } }), /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-dr-picker__close-btn", onClick: handleClose }, "CLOSE"), /* @__PURE__ */ import_react21.default.createElement("button", { type: "button", className: "rf-dr-picker__apply-btn", onClick: handleApply }, "APPLY")))
3993
+ ))), helperText && /* @__PURE__ */ import_react21.default.createElement("div", { className: "rf-text-field__helper-text" }, helperText));
3994
+ };
3995
+ DateRangeField.displayName = "DateRangeField";
3981
3996
 
3982
3997
  // lib/Progress/RufousLogoLoader.tsx
3983
3998
  var React73 = __toESM(require("react"), 1);