fis-component 0.1.14 → 0.1.16

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.
@@ -0,0 +1,3 @@
1
+ import { SvgIconProps } from "./SVGIconProps";
2
+ declare function DownloadIcon(props: SvgIconProps): import("react/jsx-runtime").JSX.Element;
3
+ export default DownloadIcon;
@@ -28,6 +28,7 @@ export { default as ArrowUpIcon } from "./ArrowUpIcon";
28
28
  export { default as CloseChipIcon } from "./CloseChipIcon";
29
29
  export { default as TimeIcon } from "./TimeIcon";
30
30
  export { default as DateIcon } from "./DateIcon";
31
+ export { default as DownloadIcon } from "./DownloadIcon";
31
32
  export { default as ChevronSelectorIcon } from "./ChevronSelector";
32
33
  export { default as EditIcon } from "./EditIcon";
33
34
  export { default as DeleteIcon } from "./DeleteIcon";
@@ -33,6 +33,7 @@ export interface MenuProps {
33
33
  focusSearchInput?: boolean;
34
34
  onPopupScroll?: (e: React.UIEvent<HTMLElement>) => void;
35
35
  normalizeTextSearch?: boolean;
36
+ renderOption?: (item: MenuItem) => React.ReactNode;
36
37
  }
37
38
  export interface MenuState {
38
39
  search: string;
@@ -10,3 +10,4 @@ export declare const Secondary: Story;
10
10
  export declare const Disabled: Story;
11
11
  export declare const Loading: Story;
12
12
  export declare const Active: Story;
13
+ export declare const WithMenu: Story;
@@ -14,5 +14,7 @@ declare const FISSplitButton: React.ForwardRefExoticComponent<{
14
14
  onIconClick?: () => void;
15
15
  } & {
16
16
  className?: string;
17
+ menuProps?: import("./types").SplitButtonMenuProps;
18
+ portal?: boolean;
17
19
  } & React.RefAttributes<HTMLDivElement>>;
18
20
  export default FISSplitButton;
@@ -8,6 +8,7 @@ export type SplitButtonProps = {
8
8
  $loading?: boolean;
9
9
  };
10
10
  export declare const DivContainerSC: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, SplitButtonProps>> & string;
11
+ export declare const DivDropdownMenuSC: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
11
12
  export declare const ButtonItem: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, SplitButtonProps>> & string;
12
13
  export declare const ButtonIconItem: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, SplitButtonProps>> & string;
13
14
  export declare const DivIconItemSC: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, SplitButtonProps>> & string;
@@ -1,4 +1,5 @@
1
1
  import React, { ComponentPropsWithoutRef } from "react";
2
+ import type { MenuItem, MenuProps, MenuSize } from "../MenuSelect/types";
2
3
  export type SplitButtonSize = "xs" | "sm" | "md" | "lg";
3
4
  export type SplitButtonVariant = "primary" | "secondary" | "tertiary" | "primary-white" | "secondary-white";
4
5
  export type SplitButtonItemProps = {
@@ -16,6 +17,12 @@ export type SplitButtonIconProps = {
16
17
  activeIcon?: boolean;
17
18
  onIconClick?: () => void;
18
19
  } & ComponentPropsWithoutRef<"button">;
20
+ export type SplitButtonMenuProps = Omit<MenuProps, "size"> & {
21
+ size?: MenuSize;
22
+ onMenuItemClick?: (item: MenuItem) => void;
23
+ };
19
24
  export type SplitButtonProps = SplitButtonItemProps & SplitButtonIconProps & {
20
25
  className?: string;
26
+ menuProps?: SplitButtonMenuProps;
27
+ portal?: boolean;
21
28
  };
package/dist/esm/index.js CHANGED
@@ -68615,7 +68615,7 @@ const normalizeText = (value) => {
68615
68615
  .trim();
68616
68616
  };
68617
68617
 
68618
- 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, }) => {
68618
+ 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, renderOption, }) => {
68619
68619
  const [localSearch, setLocalSearch] = useState(searchValue);
68620
68620
  const [debouncedSearchValue, setDebouncedSearchValue] = useState(searchValue);
68621
68621
  const searchInputRef = useRef(null);
@@ -68719,7 +68719,7 @@ const FISMenuSelect = ({ placeholder, groups, size = "md", multi = false, select
68719
68719
  searchInputRef.current.focus();
68720
68720
  }
68721
68721
  }, [focusSearchInput]);
68722
- 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))) }) }))] }))] }));
68722
+ 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: renderOption ? (jsx("div", { onClick: () => handleItemClick(item), children: renderOption(item) })) : (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))) }) }))] }))] }));
68723
68723
  };
68724
68724
  FISMenuSelect.displayName = "FISMenuSelect";
68725
68725
 
@@ -71303,7 +71303,7 @@ const DivInputWrapperSC$2 = styled.div `
71303
71303
  display: inline-block;
71304
71304
  width: 100%;
71305
71305
  `;
71306
- const DivDropdownMenuSC$1 = styled.div `
71306
+ const DivDropdownMenuSC$2 = styled.div `
71307
71307
  margin-top: ${getTheme("com/select/vertical-gap")};
71308
71308
  `;
71309
71309
  const SelectedTagsWrapper$1 = styled.div `
@@ -72149,7 +72149,7 @@ const FISCombobox = forwardRef(({ className, options, value, disabled = false, t
72149
72149
  }, [filteredOptions, searchValue]);
72150
72150
  return (jsxs(DivWrapperSC$3, { className: className, children: [(textLabel || iconLabel) && (jsx(FISInputLabel, { textLabel: textLabel, required: required, iconLabel: iconLabel, onClickIconLabel: onClickIconLabel })), jsx(DivInputWrapperSC$2, { ref: setReferenceElement, onClick: handleToggle, children: jsx(FISInputField, { ...restProps, ref: ref, iconSuffix: isOpen ? jsx(ArrowUpIcon, {}) : jsx(ArrowDownIcon, {}), value: isOpen && searchValue !== undefined
72151
72151
  ? searchValue
72152
- : computedDisplayValue, disabled: disabled, onClickSuffix: handleToggle, onChange: handleInputChange, onKeyDown: handleInputKeyDown, "$isPointer": true }) }), message && (jsx(SpanHintSC$3, { className: classNames({ disabled, negative, positive }), children: message })), multi && value.length > 0 && (jsx(SelectedTagsWrapper$1, { children: jsx(MultipleValue, { options: selectedOptions, onRemove: handleOptionRemove }) })), isOpen && (jsx(Portal, { children: jsx(DivDropdownMenuSC$1, { ref: setPopperElement, style: { ...styles.popper, width: referenceElement?.offsetWidth }, ...attributes.popper, children: jsx(FISMenuSelect, { groups: filteredOptions, placeholder: placeholderSearch, loading: loading, multi: multi, combobox: true, noResult: hasNoResults, noResultText: noResultText, maxHeight: maxHeight, selectedValues: multi ? value : value ? [value] : [], onChangeSelected: (values) => {
72152
+ : computedDisplayValue, disabled: disabled, onClickSuffix: handleToggle, onChange: handleInputChange, onKeyDown: handleInputKeyDown, "$isPointer": true }) }), message && (jsx(SpanHintSC$3, { className: classNames({ disabled, negative, positive }), children: message })), multi && value.length > 0 && (jsx(SelectedTagsWrapper$1, { children: jsx(MultipleValue, { options: selectedOptions, onRemove: handleOptionRemove }) })), isOpen && (jsx(Portal, { children: jsx(DivDropdownMenuSC$2, { ref: setPopperElement, style: { ...styles.popper, width: referenceElement?.offsetWidth }, ...attributes.popper, children: jsx(FISMenuSelect, { groups: filteredOptions, placeholder: placeholderSearch, loading: loading, multi: multi, combobox: true, noResult: hasNoResults, noResultText: noResultText, maxHeight: maxHeight, selectedValues: multi ? value : value ? [value] : [], onChangeSelected: (values) => {
72153
72153
  if (multi) {
72154
72154
  onChange(values);
72155
72155
  }
@@ -73401,6 +73401,9 @@ FISProgressLinear.displayName = "FISProgressLinear";
73401
73401
  const DivContainerSC$1 = styled.div `
73402
73402
  display: inline-flex;
73403
73403
  `;
73404
+ const DivDropdownMenuSC$1 = styled.div `
73405
+ margin-top: ${getTheme("com/select/vertical-gap")};
73406
+ `;
73404
73407
  const ButtonItem = styled.button `
73405
73408
  display: flex;
73406
73409
  justify-content: center;
@@ -74369,8 +74372,99 @@ const SplitButtonIcon$1 = ({ size, variant, onIconClick, disabled = false, activ
74369
74372
  var SplitButtonIcon = memo(SplitButtonIcon$1);
74370
74373
 
74371
74374
  const FISSplitButton = forwardRef((props, ref) => {
74372
- const { className, label, icon, size = "md", variant = "primary", disabled = false, activeButton = false, activeIcon = false, loading = false, onButtonClick, onIconClick, } = props;
74373
- return (jsxs(DivContainerSC$1, { ref: ref, className: className, role: "group", "aria-label": `${label} split button`, children: [jsx(SplitButtonItem, { icon: icon, label: label, size: size, variant: variant, disabled: disabled || loading, activeButton: activeButton, loading: loading, onButtonClick: onButtonClick, "aria-label": `${label} main action` }), jsx(SplitButtonIcon, { size: size, variant: variant, disabled: disabled || loading, activeIcon: activeIcon, onIconClick: onIconClick, "aria-label": "Toggle dropdown", "aria-expanded": activeIcon })] }));
74375
+ const { className, label, icon, size = "md", variant = "primary", disabled = false, activeButton = false, activeIcon, loading = false, onButtonClick, onIconClick, menuProps, portal, } = props;
74376
+ const [isOpen, setIsOpen] = useState(false);
74377
+ const [referenceElement, setReferenceElement] = useState(null);
74378
+ const [popperElement, setPopperElement] = useState(null);
74379
+ const hasMenu = !!menuProps?.groups;
74380
+ const isMenuOpen = hasMenu && isOpen;
74381
+ const isButtonActive = isMenuOpen || activeButton;
74382
+ const isIconActive = isMenuOpen || !!activeIcon;
74383
+ const menuSize = menuProps?.size ?? (size === "lg" ? "lg" : "md");
74384
+ const isActionMenu = !!menuProps?.onMenuItemClick;
74385
+ const popperOptions = useMemo$1(() => ({
74386
+ modifiers: [
74387
+ { name: "preventOverflow", options: { padding: 0, altAxis: true } },
74388
+ {
74389
+ name: "offset",
74390
+ options: {
74391
+ offset: [0, 4],
74392
+ },
74393
+ },
74394
+ ],
74395
+ placement: "bottom-start",
74396
+ strategy: "fixed",
74397
+ }), []);
74398
+ const { styles, attributes } = usePopper(referenceElement, popperElement, popperOptions);
74399
+ const handleContainerRef = useCallback((node) => {
74400
+ setReferenceElement(node);
74401
+ if (typeof ref === "function") {
74402
+ ref(node);
74403
+ return;
74404
+ }
74405
+ if (ref) {
74406
+ ref.current =
74407
+ node;
74408
+ }
74409
+ }, [ref]);
74410
+ const handleIconClick = useCallback(() => {
74411
+ if (hasMenu) {
74412
+ setIsOpen((prev) => !prev);
74413
+ }
74414
+ onIconClick?.();
74415
+ }, [hasMenu, onIconClick]);
74416
+ const handleButtonClick = useCallback(() => {
74417
+ if (hasMenu) {
74418
+ setIsOpen(true);
74419
+ return;
74420
+ }
74421
+ onButtonClick?.();
74422
+ }, [hasMenu, onButtonClick]);
74423
+ const handleMenuClick = useCallback(() => {
74424
+ if (!menuProps?.multi) {
74425
+ setIsOpen(false);
74426
+ }
74427
+ menuProps?.onClickMenu?.();
74428
+ }, [menuProps]);
74429
+ const handleChangeSelected = useCallback((values) => {
74430
+ if (menuProps?.onMenuItemClick) {
74431
+ const clickedValue = values[values.length - 1];
74432
+ const clickedItem = menuProps.groups
74433
+ .flatMap((group) => group.items)
74434
+ .find((item) => item.value === clickedValue);
74435
+ if (clickedItem) {
74436
+ menuProps.onMenuItemClick(clickedItem);
74437
+ setIsOpen(false);
74438
+ }
74439
+ return;
74440
+ }
74441
+ menuProps?.onChangeSelected?.(values);
74442
+ }, [menuProps]);
74443
+ useEffect(() => {
74444
+ if (!isMenuOpen)
74445
+ return;
74446
+ const handleClickOutside = (event) => {
74447
+ const target = event.target;
74448
+ if (referenceElement &&
74449
+ !referenceElement.contains(target) &&
74450
+ popperElement &&
74451
+ !popperElement.contains(target)) {
74452
+ setIsOpen(false);
74453
+ }
74454
+ };
74455
+ document.addEventListener("mousedown", handleClickOutside);
74456
+ return () => document.removeEventListener("mousedown", handleClickOutside);
74457
+ }, [isMenuOpen, popperElement, referenceElement]);
74458
+ useEffect(() => {
74459
+ if (disabled || loading || !hasMenu) {
74460
+ setIsOpen(false);
74461
+ }
74462
+ }, [disabled, hasMenu, loading]);
74463
+ return (jsxs(Fragment, { children: [jsxs(DivContainerSC$1, { ref: handleContainerRef, className: className, role: "group", "aria-label": `${label} split button`, children: [jsx(SplitButtonItem, { icon: icon, label: label, size: size, variant: variant, disabled: disabled || loading, activeButton: isButtonActive, loading: loading, onButtonClick: handleButtonClick, "aria-label": `${label} main action`, "aria-haspopup": hasMenu ? "menu" : undefined, "aria-expanded": hasMenu ? isMenuOpen : undefined }), jsx(SplitButtonIcon, { size: size, variant: variant, disabled: disabled || loading, activeIcon: isIconActive, onIconClick: handleIconClick, "aria-label": "Toggle dropdown", "aria-expanded": isMenuOpen })] }), isMenuOpen && menuProps && (jsx(Portal, { portal: portal, children: jsx(DivDropdownMenuSC$1, { ref: setPopperElement, style: {
74464
+ ...styles.popper,
74465
+ width: referenceElement?.offsetWidth,
74466
+ zIndex: 9999,
74467
+ }, ...attributes.popper, children: jsx(FISMenuSelect, { ...menuProps, size: menuSize, selectedValues: isActionMenu ? [] : menuProps.selectedValues, focusSearchInput: menuProps.focusSearchInput ?? false, onChangeSelected: handleChangeSelected, onClickMenu: handleMenuClick }) }) }))] }));
74374
74468
  });
74375
74469
  FISSplitButton.displayName = "FISSplitButton";
74376
74470
 
@@ -74848,6 +74942,7 @@ const FISSelect = forwardRef(({ className, style, size = "md", options, value, d
74848
74942
  onSearchChange,
74849
74943
  maxHeight,
74850
74944
  onPopupScroll,
74945
+ renderOption,
74851
74946
  ...restProps,
74852
74947
  }), [
74853
74948
  options,
@@ -74862,6 +74957,7 @@ const FISSelect = forwardRef(({ className, style, size = "md", options, value, d
74862
74957
  onSearchChange,
74863
74958
  maxHeight,
74864
74959
  onPopupScroll,
74960
+ renderOption,
74865
74961
  restProps,
74866
74962
  ]);
74867
74963
  useEffect(() => {