fis-component 0.1.5 → 0.1.7

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.
@@ -30,7 +30,9 @@ export interface MenuProps {
30
30
  removeSelectedText?: string;
31
31
  selectedGroupLabel?: string;
32
32
  maxHeight?: string | number;
33
+ focusSearchInput?: boolean;
33
34
  onPopupScroll?: (e: React.UIEvent<HTMLElement>) => void;
35
+ normalizeTextSearch?: boolean;
34
36
  }
35
37
  export interface MenuState {
36
38
  search: string;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Normalizes a text value by:
3
+ * - Removing all diacritic marks (e.g. Vietnamese accents)
4
+ * - Converting the result to lowercase
5
+ * - Trimming leading and trailing whitespace
6
+ *
7
+ * This is useful for case-insensitive and accent-insensitive text comparisons
8
+ * or searches, especially for languages that use diacritics.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * normalizeText("Công nghệ thông tin"); // "cong nghe thong tin"
13
+ * normalizeText(""); // ""
14
+ * ```
15
+ *
16
+ * @param value - The input text to normalize. If falsy, an empty string is returned.
17
+ * @returns The normalized, accent-stripped, lowercase, and trimmed string.
18
+ */
19
+ export declare const normalizeText: (value: string) => string;
package/dist/esm/index.js CHANGED
@@ -66642,7 +66642,7 @@ const DivWrapperSC$5 = styled.div `
66642
66642
  gap: ${getTheme("com/input/vertical-gap")};
66643
66643
  `;
66644
66644
 
66645
- const FISInputStepper = forwardRef((props) => {
66645
+ const FISInputStepper = forwardRef((props, ref) => {
66646
66646
  const { min, max, step = 1, defaultValue, sizeInput = "md", StartIcon, EndIcon, negative, positive, message, iconLabel, textLabel = "", onClickIconLabel, disabled, readOnly, onChange, ...rest } = props;
66647
66647
  const [count, setCount] = useState(defaultValue !== undefined ? defaultValue : undefined);
66648
66648
  const handleIncrement = () => {
@@ -66674,7 +66674,7 @@ const FISInputStepper = forwardRef((props) => {
66674
66674
  "input-text-lg": sizeInput === "lg",
66675
66675
  }), children: [jsx(FISIconButton, { icon: StartIcon ? StartIcon : jsx(DecreIcon, {}), size: sizeInput === "lg" ? "md" : "sm", variant: "tertiary-invisible", onClick: handleDecrement, disabled: min !== undefined && count !== undefined && count <= min, className: classNames("decrement", {
66676
66676
  "disabled-button": disabled || readOnly,
66677
- }) }), jsx(InputSC$1, { ...rest, disabled: disabled, readOnly: readOnly, type: "number", value: count !== undefined ? count : "", className: classNames({
66677
+ }) }), jsx(InputSC$1, { ...rest, ref: ref, disabled: disabled, readOnly: readOnly, type: "number", value: count !== undefined ? count : "", className: classNames({
66678
66678
  negative: negative,
66679
66679
  "input-text-lg": sizeInput === "lg",
66680
66680
  }), onChange: handleChange }), jsx(FISIconButton, { icon: EndIcon ? EndIcon : jsx(IncreIcon, {}), size: sizeInput === "lg" ? "md" : "sm", variant: "tertiary-invisible", onClick: handleIncrement, disabled: max !== undefined && count !== undefined && count >= max, className: classNames("increment", {
@@ -68543,9 +68543,40 @@ const FISMenuSection = ({ label, withAction = false, actionText, actionLabel = f
68543
68543
  };
68544
68544
  FISMenuSection.displayName = "FISMenuSection";
68545
68545
 
68546
- const FISMenuSelect = ({ placeholder, groups, size = "md", multi = false, selectedValues = [], onChangeSelected, searchValue = "", onSearchChange, loading = false, noData = false, noResult = false, combobox, className, onClickMenu, loadingText = "Data loading...", noDataText = "No data", noResultText = "No result", removeSelectedText = "Remove selected", selectedGroupLabel = "Selected", maxHeight, onPopupScroll, }) => {
68546
+ /**
68547
+ * Normalizes a text value by:
68548
+ * - Removing all diacritic marks (e.g. Vietnamese accents)
68549
+ * - Converting the result to lowercase
68550
+ * - Trimming leading and trailing whitespace
68551
+ *
68552
+ * This is useful for case-insensitive and accent-insensitive text comparisons
68553
+ * or searches, especially for languages that use diacritics.
68554
+ *
68555
+ * @example
68556
+ * ```ts
68557
+ * normalizeText("Công nghệ thông tin"); // "cong nghe thong tin"
68558
+ * normalizeText(""); // ""
68559
+ * ```
68560
+ *
68561
+ * @param value - The input text to normalize. If falsy, an empty string is returned.
68562
+ * @returns The normalized, accent-stripped, lowercase, and trimmed string.
68563
+ */
68564
+ const normalizeText = (value) => {
68565
+ if (!value)
68566
+ return "";
68567
+ return value
68568
+ .normalize("NFD")
68569
+ .replace(/[\u0300-\u036f]/g, "")
68570
+ .replace(/đ/g, "d")
68571
+ .replace(/Đ/g, "D")
68572
+ .toLowerCase()
68573
+ .trim();
68574
+ };
68575
+
68576
+ const FISMenuSelect = ({ placeholder, groups, size = "md", multi = false, selectedValues = [], onChangeSelected, searchValue = "", onSearchChange, loading = false, noData = false, noResult = false, combobox, className, onClickMenu, loadingText = "Data loading...", noDataText = "No data", noResultText = "No result", removeSelectedText = "Remove selected", selectedGroupLabel = "Selected", maxHeight, focusSearchInput = true, onPopupScroll, normalizeTextSearch = false, }) => {
68547
68577
  const [localSearch, setLocalSearch] = useState(searchValue);
68548
68578
  const [debouncedSearchValue, setDebouncedSearchValue] = useState(searchValue);
68579
+ const searchInputRef = useRef(null);
68549
68580
  const debouncedSetSearch = useMemo$1(() => debounce$1((value) => setDebouncedSearchValue(value), 300), []);
68550
68581
  useEffect(() => {
68551
68582
  debouncedSetSearch(localSearch);
@@ -68575,11 +68606,13 @@ const FISMenuSelect = ({ placeholder, groups, size = "md", multi = false, select
68575
68606
  if (search.trim()) {
68576
68607
  filteredItems = filteredItems.map((group) => ({
68577
68608
  ...group,
68578
- items: group.items.filter((item) => item?.label?.toLowerCase()?.includes(search?.toLowerCase())),
68609
+ items: group.items.filter((item) => normalizeTextSearch
68610
+ ? normalizeText(item?.label).includes(normalizeText(search))
68611
+ : item?.label?.toLowerCase()?.includes(search?.toLowerCase())),
68579
68612
  }));
68580
68613
  }
68581
68614
  return filteredItems.filter((group) => group.items.length > 0);
68582
- }, [groups, multi, selectedValues, search]);
68615
+ }, [groups, multi, selectedValues, search, normalizeTextSearch]);
68583
68616
  const selectedItemsGroup = useMemo$1(() => {
68584
68617
  if (!multi)
68585
68618
  return null;
@@ -68639,7 +68672,12 @@ const FISMenuSelect = ({ placeholder, groups, size = "md", multi = false, select
68639
68672
  onClickMenu?.();
68640
68673
  }
68641
68674
  };
68642
- return (jsxs(DivContainerSC$4, { "$maxHeight": maxHeight, className: className, children: [showInput && !combobox && (jsx(DivSearchSC, { children: jsx(FISInputText, { iconPrefix: jsx(SearchIcon, {}), placeholder: placeholder, value: search, onChange: handleSearchChange }) })), loading && (jsxs(DivLoaderSC, { children: [jsx(FISProgressCircular, { size: size, variant: "indeterminate" }), jsx(PTitleSC$2, { children: loadingText })] })), !loading && noData && (jsxs(DivLoaderSC, { children: [jsx(DivIconDataSC, { children: jsx(NoDataIcon, {}) }), jsx(PTitleSC$2, { children: noDataText })] })), !loading && !noData && (shouldShowNoResult || noResult) && (jsxs(DivLoaderSC, { children: [jsx(DivIconDataSC, { children: jsx(NoResultIcon, {}) }), jsx(PTitleSC$2, { children: noResultText })] })), !shouldShowNoResult && !noData && !loading && (jsxs(Fragment, { children: [jsx(MenuContent, { "$removeSelectedGroup": !!removeSelectedGroup, onScroll: onPopupScroll, children: groupsToRender.map((group, index) => (jsxs(DivWrapperSC$4, { children: [index !== 0 && jsx(FISMenuSection, { withDivider: true }), group?.groupLabel && (jsx(FISMenuSection, { label: group?.groupLabel })), group.items.map((item, idx) => (jsx(FISTooltip, { title: item.label, variant: "primary", children: jsx(FISMenuItem, { title: item.label, description: item.description, size: size, onClickMenu: () => handleItemClick(item), selected: selectedValues.includes(item.value), type: "select" }) }, idx)))] }, index))) }), removeSelectedGroup && (jsx(FixedBottomSection, { children: jsx(DivWrapperSC$4, { children: removeSelectedGroup.items.map((item, idx) => (jsx(FISTooltip, { title: item.label, variant: "primary", children: jsx(FISMenuItem, { title: item.label, description: item.description, size: size, onClickMenu: () => onChangeSelected?.([]), type: "select", iconPrefix: jsx(RemoveIcon, {}), negative: true }) }, idx))) }) }))] }))] }));
68675
+ useEffect(() => {
68676
+ if (focusSearchInput && searchInputRef.current) {
68677
+ searchInputRef.current.focus();
68678
+ }
68679
+ }, [focusSearchInput]);
68680
+ return (jsxs(DivContainerSC$4, { "$maxHeight": maxHeight, className: className, children: [showInput && !combobox && (jsx(DivSearchSC, { children: jsx(FISInputText, { iconPrefix: jsx(SearchIcon, {}), placeholder: placeholder, value: search, onChange: handleSearchChange, ref: searchInputRef }) })), loading && (jsxs(DivLoaderSC, { children: [jsx(FISProgressCircular, { size: size, variant: "indeterminate" }), jsx(PTitleSC$2, { children: loadingText })] })), !loading && noData && (jsxs(DivLoaderSC, { children: [jsx(DivIconDataSC, { children: jsx(NoDataIcon, {}) }), jsx(PTitleSC$2, { children: noDataText })] })), !loading && !noData && (shouldShowNoResult || noResult) && (jsxs(DivLoaderSC, { children: [jsx(DivIconDataSC, { children: jsx(NoResultIcon, {}) }), jsx(PTitleSC$2, { children: noResultText })] })), !shouldShowNoResult && !noData && !loading && (jsxs(Fragment, { children: [jsx(MenuContent, { "$removeSelectedGroup": !!removeSelectedGroup, onScroll: onPopupScroll, children: groupsToRender.map((group, index) => (jsxs(DivWrapperSC$4, { children: [index !== 0 && jsx(FISMenuSection, { withDivider: true }), group?.groupLabel && (jsx(FISMenuSection, { label: group?.groupLabel })), group.items.map((item, idx) => (jsx(FISTooltip, { title: item.label, variant: "primary", children: jsx(FISMenuItem, { title: item.label, description: item.description, size: size, onClickMenu: () => handleItemClick(item), selected: selectedValues.includes(item.value), type: "select" }) }, idx)))] }, index))) }), removeSelectedGroup && (jsx(FixedBottomSection, { children: jsx(DivWrapperSC$4, { children: removeSelectedGroup.items.map((item, idx) => (jsx(FISTooltip, { title: item.label, variant: "primary", children: jsx(FISMenuItem, { title: item.label, description: item.description, size: size, onClickMenu: () => onChangeSelected?.([]), type: "select", iconPrefix: jsx(RemoveIcon, {}), negative: true }) }, idx))) }) }))] }))] }));
68643
68681
  };
68644
68682
  FISMenuSelect.displayName = "FISMenuSelect";
68645
68683