@sbnpmiamldw/ui-library 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +46 -0
  2. package/dist/App.d.ts +3 -0
  3. package/dist/App.js +7 -0
  4. package/dist/components/Alert/alert.d.ts +10 -0
  5. package/dist/components/Alert/alert.js +18 -0
  6. package/dist/components/Alert/index.d.ts +2 -0
  7. package/dist/components/Alert/index.js +2 -0
  8. package/dist/components/AutoComplete/autoComplete.d.ts +13 -0
  9. package/dist/components/AutoComplete/autoComplete.js +82 -0
  10. package/dist/components/AutoComplete/index.d.ts +2 -0
  11. package/dist/components/AutoComplete/index.js +2 -0
  12. package/dist/components/Button/button.d.ts +23 -0
  13. package/dist/components/Button/button.js +19 -0
  14. package/dist/components/Button/index.d.ts +2 -0
  15. package/dist/components/Button/index.js +2 -0
  16. package/dist/components/Icon/icon.d.ts +8 -0
  17. package/dist/components/Icon/icon.js +10 -0
  18. package/dist/components/Icon/index.d.ts +2 -0
  19. package/dist/components/Icon/index.js +2 -0
  20. package/dist/components/Input/index.d.ts +2 -0
  21. package/dist/components/Input/index.js +2 -0
  22. package/dist/components/Input/input.d.ts +15 -0
  23. package/dist/components/Input/input.js +13 -0
  24. package/dist/components/Menu/index.d.ts +10 -0
  25. package/dist/components/Menu/index.js +7 -0
  26. package/dist/components/Menu/menu.d.ts +21 -0
  27. package/dist/components/Menu/menu.js +37 -0
  28. package/dist/components/Menu/menuItem.d.ts +10 -0
  29. package/dist/components/Menu/menuItem.js +19 -0
  30. package/dist/components/Menu/subMenu.d.ts +9 -0
  31. package/dist/components/Menu/subMenu.js +58 -0
  32. package/dist/components/Select/index.d.ts +10 -0
  33. package/dist/components/Select/index.js +7 -0
  34. package/dist/components/Select/select.d.ts +9 -0
  35. package/dist/components/Select/select.js +66 -0
  36. package/dist/components/Select/selectItem.d.ts +9 -0
  37. package/dist/components/Select/selectItem.js +17 -0
  38. package/dist/components/Select/selectTag.d.ts +7 -0
  39. package/dist/components/Select/selectTag.js +12 -0
  40. package/dist/components/Tabs/index.d.ts +8 -0
  41. package/dist/components/Tabs/index.js +5 -0
  42. package/dist/components/Tabs/tabItem.d.ts +10 -0
  43. package/dist/components/Tabs/tabItem.js +19 -0
  44. package/dist/components/Tabs/tabs.d.ts +15 -0
  45. package/dist/components/Tabs/tabs.js +37 -0
  46. package/dist/components/Transition/index.d.ts +2 -0
  47. package/dist/components/Transition/index.js +2 -0
  48. package/dist/components/Transition/transition.d.ts +9 -0
  49. package/dist/components/Transition/transition.js +19 -0
  50. package/dist/components/Upload/dragger.d.ts +6 -0
  51. package/dist/components/Upload/dragger.js +19 -0
  52. package/dist/components/Upload/index.d.ts +13 -0
  53. package/dist/components/Upload/index.js +9 -0
  54. package/dist/components/Upload/progress.d.ts +10 -0
  55. package/dist/components/Upload/progress.js +8 -0
  56. package/dist/components/Upload/upload.d.ts +35 -0
  57. package/dist/components/Upload/upload.js +126 -0
  58. package/dist/components/Upload/uploadList.d.ts +7 -0
  59. package/dist/components/Upload/uploadList.js +9 -0
  60. package/dist/hooks/useClickOutside.d.ts +2 -0
  61. package/dist/hooks/useClickOutside.js +16 -0
  62. package/dist/hooks/useDebounce.d.ts +1 -0
  63. package/dist/hooks/useDebounce.js +13 -0
  64. package/dist/index.css +801 -0
  65. package/dist/index.css.map +1 -0
  66. package/dist/index.d.ts +10 -0
  67. package/dist/index.js +31 -0
  68. package/dist/reportWebVitals.d.ts +0 -0
  69. package/dist/reportWebVitals.js +13 -0
  70. package/dist/setupTests.d.ts +1 -0
  71. package/dist/setupTests.js +5 -0
  72. package/package.json +97 -0
package/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # Getting Started with Create React App
2
+
3
+ This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4
+
5
+ ## Available Scripts
6
+
7
+ In the project directory, you can run:
8
+
9
+ ### `npm start`
10
+
11
+ Runs the app in the development mode.\
12
+ Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13
+
14
+ The page will reload if you make edits.\
15
+ You will also see any lint errors in the console.
16
+
17
+ ### `npm test`
18
+
19
+ Launches the test runner in the interactive watch mode.\
20
+ See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21
+
22
+ ### `npm run build`
23
+
24
+ Builds the app for production to the `build` folder.\
25
+ It correctly bundles React in production mode and optimizes the build for the best performance.
26
+
27
+ The build is minified and the filenames include the hashes.\
28
+ Your app is ready to be deployed!
29
+
30
+ See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31
+
32
+ ### `npm run eject`
33
+
34
+ **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
35
+
36
+ If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37
+
38
+ Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
39
+
40
+ You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
41
+
42
+ ## Learn More
43
+
44
+ You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45
+
46
+ To learn React, check out the [React documentation](https://reactjs.org/).
package/dist/App.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import './App.css';
2
+ declare function App(): import("react/jsx-runtime").JSX.Element;
3
+ export default App;
package/dist/App.js ADDED
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // import logo from './logo.svg';
3
+ import './App.css';
4
+ function App() {
5
+ return (_jsx("div", { children: _jsxs("header", { children: [_jsxs("p", { children: ["Edit ", _jsx("code", { children: "src/App.tsx" }), " and save to reload."] }), _jsx("a", { className: "App-link", href: "https://reactjs.org", target: "_blank", rel: "noopener noreferrer", children: "Learn React" })] }) }));
6
+ }
7
+ export default App;
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ export type AlertType = 'success' | 'default' | 'danger' | 'warning';
3
+ export interface BaseAlertProps {
4
+ className?: string;
5
+ alertType?: AlertType;
6
+ title?: string;
7
+ children: React.ReactNode;
8
+ }
9
+ declare const Alert: React.FC<BaseAlertProps>;
10
+ export default Alert;
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import classNames from 'classnames';
4
+ import Button from '../Button/button';
5
+ import Icon from '../Icon/icon';
6
+ import Transition from '../Transition/transition';
7
+ import { faXmark } from '@fortawesome/free-solid-svg-icons';
8
+ const Alert = ({ className, alertType = 'default', title, children }) => {
9
+ const [closeAlert, setCloseAlert] = useState(false);
10
+ const classes = classNames('alert', className, {
11
+ [`alert-${alertType}`]: alertType
12
+ });
13
+ return (_jsx(Transition, { in: !closeAlert, timeout: 500, animation: 'zoom-in-top', children: _jsxs("div", { className: classes, children: [title && _jsx("strong", { className: 'alert-title', children: title }), _jsx(Button, { className: 'alert-button', role: 'button', onClick: (e) => {
14
+ e.preventDefault();
15
+ setCloseAlert(!closeAlert);
16
+ }, children: _jsx(Icon, { icon: faXmark, className: 'alert-close-icon', theme: 'light' }) }), children] }) }));
17
+ };
18
+ export default Alert;
@@ -0,0 +1,2 @@
1
+ import Alert from "./alert";
2
+ export default Alert;
@@ -0,0 +1,2 @@
1
+ import Alert from "./alert";
2
+ export default Alert;
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ import { InputProps } from '../Input/input';
3
+ export interface AutoCompleteProps extends Omit<InputProps, 'onSelect'> {
4
+ fetchSuggestions: (query: string) => DataSourceType[] | Promise<DataSourceType[]>;
5
+ onSelect?: (item: DataSourceType) => void;
6
+ renderOption?: (item: DataSourceType) => React.ReactNode;
7
+ }
8
+ interface DataSourceObject {
9
+ value: string;
10
+ }
11
+ export type DataSourceType<T = {}> = T & DataSourceObject;
12
+ export declare const AutoComplete: React.FC<AutoCompleteProps>;
13
+ export {};
@@ -0,0 +1,82 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from "react";
3
+ import classNames from "classnames";
4
+ import { Input } from '../Input/input';
5
+ // import Transition from "../Transition/transition";
6
+ import { useDebounce } from "../../hooks/useDebounce";
7
+ import { useClickOutside } from "../../hooks/useClickOutside";
8
+ import { faSpinner } from "@fortawesome/free-solid-svg-icons";
9
+ export const AutoComplete = ({ fetchSuggestions, onSelect, renderOption, ...restProps }) => {
10
+ const [inputValue, setInputValue] = React.useState('');
11
+ const [suggestions, setSuggestions] = React.useState([]);
12
+ const [loading, setLoading] = React.useState(false);
13
+ const [highlightIndex, setHighlightIndex] = React.useState(-1);
14
+ const debouncedValue = useDebounce(inputValue);
15
+ const triggerSearch = React.useRef(false);
16
+ const componentRef = React.useRef(null);
17
+ React.useEffect(() => {
18
+ if (debouncedValue && !triggerSearch.current) {
19
+ let suggestion = fetchSuggestions(debouncedValue);
20
+ if (suggestion instanceof Promise) {
21
+ setLoading(true);
22
+ suggestion.then(data => {
23
+ setLoading(false);
24
+ setSuggestions(data);
25
+ });
26
+ }
27
+ else
28
+ setSuggestions(suggestion);
29
+ }
30
+ else
31
+ setSuggestions([]);
32
+ setHighlightIndex(-1);
33
+ }, [debouncedValue, fetchSuggestions]);
34
+ const handleChange = (e) => {
35
+ let value = e.target.value.trim();
36
+ setInputValue(value);
37
+ triggerSearch.current = false;
38
+ };
39
+ const handleSelect = (item) => {
40
+ if (onSelect) {
41
+ onSelect(item);
42
+ }
43
+ setInputValue(item.value);
44
+ setSuggestions([]);
45
+ triggerSearch.current = true;
46
+ };
47
+ const handleKeyDown = (e) => {
48
+ if (e.key === 'ArrowUp') {
49
+ setHighlightIndex(highlightIndex <= 0 ? 0 : highlightIndex - 1);
50
+ }
51
+ else if (e.key === 'ArrowDown') {
52
+ setHighlightIndex(highlightIndex >= suggestions.length - 1 ? suggestions.length - 1 : highlightIndex + 1);
53
+ }
54
+ else if (e.key === 'Enter') {
55
+ if (suggestions.length) {
56
+ handleSelect(suggestions[highlightIndex]);
57
+ }
58
+ }
59
+ };
60
+ const renderItem = (item) => {
61
+ return renderOption ? renderOption(item) : item.value;
62
+ };
63
+ const genDropdown = () => (
64
+ // <Transition
65
+ // in = {suggestions.length!==0}
66
+ // timeout={300}
67
+ // classNames='autoComplete-lists'
68
+ // >
69
+ _jsx("ul", { className: "autoComplete-ul", children: suggestions.map((item, index) => {
70
+ const cnames = classNames('suggestion-item', {
71
+ 'is-active': index === highlightIndex
72
+ });
73
+ return (_jsx("li", { className: cnames, onClick: () => handleSelect(item), children: renderItem(item) }, index));
74
+ }) })
75
+ // </Transition>
76
+ );
77
+ useClickOutside(componentRef, () => {
78
+ setSuggestions([]);
79
+ setHighlightIndex(-1);
80
+ });
81
+ return (_jsxs("div", { className: "autoComplete-wrapper", ref: componentRef, children: [_jsx(Input, { value: inputValue, onChange: handleChange, onKeyDown: handleKeyDown, icon: faSpinner, iconProps: { className: "autoComplete-icon", spin: true }, iconLoading: loading, ...restProps }), suggestions.length > 0 && genDropdown()] }));
82
+ };
@@ -0,0 +1,2 @@
1
+ import { AutoComplete } from "./autoComplete";
2
+ export default AutoComplete;
@@ -0,0 +1,2 @@
1
+ import { AutoComplete } from "./autoComplete";
2
+ export default AutoComplete;
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ export type ButtonSize = 'lg' | 'sm';
3
+ export type ButtonType = 'primary' | 'default' | 'danger' | 'link';
4
+ interface BaseButtonProps {
5
+ className?: string;
6
+ /** 设置 Button 的禁用 */
7
+ disabled?: boolean;
8
+ /** 设置 Button 的大小 */
9
+ size?: ButtonSize;
10
+ /** 设置 Button 的类型 */
11
+ btnType?: 'primary' | 'default' | 'danger' | 'link';
12
+ children?: React.ReactNode;
13
+ /** 当 Button 是 link 时,设置链接 */
14
+ href?: string;
15
+ }
16
+ type NativeButtonProps = BaseButtonProps & Partial<React.ButtonHTMLAttributes<HTMLElement>>;
17
+ type AnchorButtonProps = BaseButtonProps & Partial<React.AnchorHTMLAttributes<HTMLElement>>;
18
+ export type ButtonProps = NativeButtonProps & AnchorButtonProps;
19
+ /**
20
+ * ***Button*** 组件可以作为 ***button*** 和 ***a*** 使用
21
+ */
22
+ export declare const Button: React.FC<ButtonProps>;
23
+ export default Button;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import classNames from 'classnames';
3
+ /**
4
+ * ***Button*** 组件可以作为 ***button*** 和 ***a*** 使用
5
+ */
6
+ export const Button = ({ btnType = 'default', className, disabled = false, size, children, href, ...restProps }) => {
7
+ const classes = classNames('btn', className, {
8
+ [`btn-${btnType}`]: btnType,
9
+ [`btn-${size}`]: size,
10
+ 'disabled': (btnType === 'link') && disabled
11
+ });
12
+ if (btnType === 'link' && href) { // link
13
+ return (_jsx("a", { className: classes, href: href, ...restProps, children: children }));
14
+ }
15
+ else { // button
16
+ return (_jsx("button", { className: classes, disabled: disabled, ...restProps, children: children }));
17
+ }
18
+ };
19
+ export default Button;
@@ -0,0 +1,2 @@
1
+ import Button from "./button";
2
+ export default Button;
@@ -0,0 +1,2 @@
1
+ import Button from "./button";
2
+ export default Button;
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { FontAwesomeIconProps } from '@fortawesome/react-fontawesome';
3
+ export type ThemeProps = 'primary' | 'secondary' | 'success' | 'info' | 'warning' | 'danger' | 'light' | 'dark';
4
+ export interface IconProps extends FontAwesomeIconProps {
5
+ theme?: ThemeProps;
6
+ }
7
+ declare const Icon: React.FC<IconProps>;
8
+ export default Icon;
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import classNames from 'classnames';
3
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4
+ const Icon = ({ className, theme, ...restProps }) => {
5
+ const classes = classNames('icon', className, {
6
+ [`icon-${theme}`]: theme
7
+ });
8
+ return (_jsx(FontAwesomeIcon, { className: classes, ...restProps }));
9
+ };
10
+ export default Icon;
@@ -0,0 +1,2 @@
1
+ import Icon from "./icon";
2
+ export default Icon;
@@ -0,0 +1,2 @@
1
+ import Icon from "./icon";
2
+ export default Icon;
@@ -0,0 +1,2 @@
1
+ import { Input } from "./input";
2
+ export default Input;
@@ -0,0 +1,2 @@
1
+ import { Input } from "./input";
2
+ export default Input;
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import { IconProp } from '@fortawesome/fontawesome-svg-core';
3
+ import { IconProps } from '../Icon/icon';
4
+ type InputSize = 'lg' | 'sm';
5
+ export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {
6
+ disabled?: boolean;
7
+ size?: InputSize;
8
+ icon?: IconProp;
9
+ iconProps?: Omit<IconProps, 'icon'>;
10
+ iconLoading?: boolean;
11
+ prepend?: React.ReactNode;
12
+ append?: React.ReactNode;
13
+ }
14
+ export declare const Input: React.FC<InputProps>;
15
+ export {};
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import classNames from 'classnames';
3
+ import Icon from '../Icon/icon';
4
+ export const Input = ({ disabled = false, size, icon, iconProps, iconLoading = true, prepend, append, ...restProps }) => {
5
+ const classes = classNames('input-wrapper', {
6
+ 'disabled': disabled,
7
+ [`input-size-${size}`]: size,
8
+ });
9
+ const iconClasses = classNames('input-icon', iconProps === null || iconProps === void 0 ? void 0 : iconProps.className, {
10
+ 'icon-hidden': !iconLoading,
11
+ });
12
+ return (_jsxs("div", { className: classes, children: [prepend && _jsx("div", { className: "input-prepend", children: prepend }), _jsxs("div", { className: "input-inner-wrapper", children: [_jsx("input", { className: "input-inner", disabled: disabled, ...restProps }), icon && _jsx(Icon, { ...iconProps, className: iconClasses, icon: icon })] }), append && _jsx("div", { className: "input-append", children: append })] }));
13
+ };
@@ -0,0 +1,10 @@
1
+ import { FC } from 'react';
2
+ import { MenuProps } from './menu';
3
+ import { MenuItemProps } from './menuItem';
4
+ import { SubMenuProps } from './subMenu';
5
+ export type IMenuComponent = FC<MenuProps> & {
6
+ Item: FC<MenuItemProps>;
7
+ SubMenu: FC<SubMenuProps>;
8
+ };
9
+ declare const TransMenu: IMenuComponent;
10
+ export default TransMenu;
@@ -0,0 +1,7 @@
1
+ import Menu from './menu';
2
+ import MenuItem from './menuItem';
3
+ import SubMenu from './subMenu';
4
+ const TransMenu = Menu;
5
+ TransMenu.Item = MenuItem;
6
+ TransMenu.SubMenu = SubMenu;
7
+ export default TransMenu;
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ type MenuMode = 'horizontal' | 'vertical';
3
+ type SelectCallback = (selectedIndex: string) => void;
4
+ export interface MenuProps {
5
+ defaultIndex?: string;
6
+ className?: string;
7
+ mode?: MenuMode;
8
+ style?: React.CSSProperties;
9
+ onSelect?: SelectCallback;
10
+ defaultOpenSubMenus?: string[];
11
+ children: React.ReactNode;
12
+ }
13
+ interface IMenuContext {
14
+ index: string;
15
+ onSelect?: SelectCallback;
16
+ mode?: MenuMode;
17
+ defaultOpenSubMenus?: string[];
18
+ }
19
+ export declare const MenuContext: React.Context<IMenuContext>;
20
+ declare const Menu: React.FC<MenuProps>;
21
+ export default Menu;
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React, { useState, createContext } from 'react';
3
+ import classNames from 'classnames';
4
+ export const MenuContext = createContext({ index: '0' });
5
+ const Menu = ({ className, mode = 'horizontal', style, children, defaultIndex = '0', onSelect, defaultOpenSubMenus = [] }) => {
6
+ const [currentActive, setActive] = useState(defaultIndex);
7
+ const classes = classNames('menu', className, {
8
+ [`menu-${mode}`]: mode
9
+ });
10
+ const handleClick = (index) => {
11
+ setActive(index);
12
+ if (onSelect) {
13
+ onSelect(index);
14
+ }
15
+ };
16
+ const passedContext = {
17
+ index: currentActive,
18
+ onSelect: handleClick,
19
+ mode,
20
+ defaultOpenSubMenus
21
+ };
22
+ const renderChildren = () => {
23
+ return React.Children.map(children, (child, index) => {
24
+ const childElement = child;
25
+ if (typeof childElement.type === 'function' &&
26
+ (childElement.type.displayName === 'MenuItem'
27
+ || childElement.type.displayName === 'SubMenu')) {
28
+ return React.cloneElement(childElement, { index: index.toString() });
29
+ }
30
+ else {
31
+ console.error('Warning: Menu has a child which is not a MenuItem component');
32
+ }
33
+ });
34
+ };
35
+ return (_jsx("ul", { className: classes, style: style, "data-testid": "test-menu", children: _jsx(MenuContext.Provider, { value: passedContext, children: renderChildren() }) }));
36
+ };
37
+ export default Menu;
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ export interface MenuItemProps {
3
+ index?: string;
4
+ disabled?: boolean;
5
+ className?: string;
6
+ style?: React.CSSProperties;
7
+ children: React.ReactNode;
8
+ }
9
+ declare const MenuItem: React.FC<MenuItemProps>;
10
+ export default MenuItem;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useContext } from 'react';
3
+ import classNames from 'classnames';
4
+ import { MenuContext } from './menu';
5
+ const MenuItem = ({ index, disabled = false, className, style, children }) => {
6
+ const context = useContext(MenuContext);
7
+ const classes = classNames('menu-item', className, {
8
+ 'is-disabled': disabled,
9
+ 'is-active': context.index === index
10
+ });
11
+ const handleClick = () => {
12
+ if (context.onSelect && !disabled && (typeof index === 'string')) {
13
+ context.onSelect(index);
14
+ }
15
+ };
16
+ return (_jsx("li", { className: classes, style: style, onClick: handleClick, "data-testid": "test-menu-item", children: children }));
17
+ };
18
+ MenuItem.displayName = 'MenuItem';
19
+ export default MenuItem;
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ export interface SubMenuProps {
3
+ index?: string;
4
+ title: string;
5
+ className?: string;
6
+ children: React.ReactNode;
7
+ }
8
+ declare const SubMenu: React.FC<SubMenuProps>;
9
+ export default SubMenu;
@@ -0,0 +1,58 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { Children, useState, useContext } from 'react';
3
+ import classNames from 'classnames';
4
+ import { MenuContext } from './menu';
5
+ import Icon from '../Icon/icon';
6
+ import Transition from '../Transition/transition';
7
+ import { faAngleDown } from "@fortawesome/free-solid-svg-icons";
8
+ const SubMenu = ({ index, title, className, children }) => {
9
+ const context = useContext(MenuContext);
10
+ const openedSubMenus = context.defaultOpenSubMenus;
11
+ const isOpened = (index && context.mode === 'vertical') ? openedSubMenus.includes(index) : false;
12
+ const [menuOpen, setOpen] = useState(isOpened);
13
+ const classes = classNames('menu-item submenu-item', className, {
14
+ 'is-active': context.index === index,
15
+ 'is-opened': menuOpen,
16
+ 'is-vertical': context.mode === 'vertical'
17
+ });
18
+ const handleClick = (e) => {
19
+ e.preventDefault();
20
+ setOpen(!menuOpen);
21
+ };
22
+ let timer;
23
+ const handleMouse = (e, toggle) => {
24
+ e.preventDefault();
25
+ clearTimeout(timer);
26
+ timer = setTimeout(() => {
27
+ setOpen(toggle);
28
+ }, 300);
29
+ };
30
+ const clickEvents = context.mode === 'vertical' ? {
31
+ onClick: handleClick
32
+ } : {};
33
+ const hoverEvents = context.mode !== 'vertical' ? {
34
+ onMouseEnter: (e) => { handleMouse(e, true); },
35
+ onMouseLeave: (e) => { handleMouse(e, false); }
36
+ } : {};
37
+ const renderChildren = () => {
38
+ const subMenuClasses = classNames('submenu', {
39
+ 'submenu-opened': menuOpen
40
+ });
41
+ const childrenComponent = Children.map(children, (child, i) => {
42
+ const childElement = child;
43
+ if (typeof childElement.type === 'function'
44
+ && childElement.type.displayName === 'MenuItem') {
45
+ return React.cloneElement(childElement, {
46
+ index: `${index}-${i}`
47
+ });
48
+ }
49
+ else {
50
+ console.error('Warning: SubMenu has a child which is not a MenuItem component');
51
+ }
52
+ });
53
+ return (_jsx(Transition, { in: menuOpen, timeout: 300, animation: 'zoom-in-bottom', children: _jsx("ul", { className: subMenuClasses, children: childrenComponent }) }));
54
+ };
55
+ return (_jsxs("li", { className: classes, ...hoverEvents, children: [_jsxs("div", { className: 'submenu-title', ...clickEvents, children: [title, _jsx(Icon, { icon: faAngleDown, className: 'arrow-icon' })] }), renderChildren()] }, index));
56
+ };
57
+ SubMenu.displayName = 'SubMenu';
58
+ export default SubMenu;
@@ -0,0 +1,10 @@
1
+ import { FC } from "react";
2
+ import { SelectProps } from './select';
3
+ import { SelectItemProps } from "./selectItem";
4
+ import { SelectTagProps } from "./selectTag";
5
+ export type ISelectComponent = FC<SelectProps> & {
6
+ Item: FC<SelectItemProps>;
7
+ Tag: FC<SelectTagProps>;
8
+ };
9
+ declare const TransSelect: ISelectComponent;
10
+ export default TransSelect;
@@ -0,0 +1,7 @@
1
+ import Select from './select';
2
+ import SelectItem from "./selectItem";
3
+ import SelectTag from "./selectTag";
4
+ const TransSelect = Select;
5
+ TransSelect.Item = SelectItem;
6
+ TransSelect.Tag = SelectTag;
7
+ export default TransSelect;
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ export interface SelectProps {
3
+ singleChoice?: boolean;
4
+ onChange?: (items: string[]) => void;
5
+ placeholder?: string;
6
+ children?: React.ReactNode;
7
+ }
8
+ declare const Select: React.FC<SelectProps>;
9
+ export default Select;
@@ -0,0 +1,66 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { useState, useEffect, useRef } from "react";
3
+ import classNames from "classnames";
4
+ import SelectTag from "./selectTag";
5
+ import Button from "../Button/button";
6
+ import Icon from "../Icon/icon";
7
+ import Transition from '../Transition/transition';
8
+ import { faAngleDown } from "@fortawesome/free-solid-svg-icons";
9
+ const Select = ({ singleChoice = true, onChange, placeholder = '', children, }) => {
10
+ const [selectItems, setSelectItems] = useState([]);
11
+ const [openList, setOpenList] = useState(false);
12
+ const isInitialise = useRef(false);
13
+ const buttonClasses = classNames('select-button', {
14
+ 'open-list': openList,
15
+ });
16
+ useEffect(() => {
17
+ if (!isInitialise.current)
18
+ isInitialise.current = true;
19
+ else if (isInitialise.current && onChange)
20
+ onChange(selectItems);
21
+ }, [selectItems, onChange]);
22
+ const handlItemClick = (value) => {
23
+ let index = selectItems.indexOf(value);
24
+ if (index !== -1) {
25
+ setSelectItems([...selectItems.slice(0, index), ...selectItems.slice(index + 1)]);
26
+ }
27
+ else {
28
+ if (!singleChoice)
29
+ setSelectItems([...selectItems, value]);
30
+ else if (selectItems.length === 0)
31
+ setSelectItems([...selectItems, value]);
32
+ }
33
+ };
34
+ const handleTagClick = (value) => {
35
+ let index = selectItems.indexOf(value);
36
+ if (index !== -1) {
37
+ setSelectItems([...selectItems.slice(0, index), ...selectItems.slice(index + 1)]);
38
+ }
39
+ };
40
+ const renderTags = () => {
41
+ const tags = selectItems.map(item => (_jsx(SelectTag, { value: item, handleTagClick: handleTagClick }, item)));
42
+ return (_jsx("div", { className: "select-tags-wrapper", "data-testid": 'tags', children: tags.length === 0 ?
43
+ _jsx("div", { className: "select-tags-placeholder", children: placeholder })
44
+ : tags }));
45
+ };
46
+ const renderChildren = () => {
47
+ return React.Children.map(children, (child) => {
48
+ const childElement = child;
49
+ // console.log(childElement.key);
50
+ if (typeof childElement.type === 'function' &&
51
+ childElement.type.displayName === 'SelectItem') {
52
+ return React.cloneElement(childElement, {
53
+ isSelect: selectItems.includes(childElement.props.value),
54
+ handleItemClick: handlItemClick,
55
+ // key: childElement.key,
56
+ });
57
+ }
58
+ else
59
+ console.error('Warning: Select has a child which is not a SelectItem component');
60
+ });
61
+ };
62
+ return (_jsxs("div", { className: "select-wrapper", children: [_jsxs("div", { className: "select-inner-wrapper", children: [renderTags(), _jsx(Button, { className: buttonClasses, onClick: () => {
63
+ setOpenList(!openList);
64
+ }, children: _jsx(Icon, { icon: faAngleDown, className: "select-icon", "aria-label": "select list button" }) })] }), _jsx(Transition, { in: openList, timeout: 300, unmountOnExit: true, classNames: "select-list-transition", children: _jsx("ul", { className: "select-list", children: openList && renderChildren() }) })] }));
65
+ };
66
+ export default Select;
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ export interface SelectItemProps extends React.LiHTMLAttributes<HTMLLIElement> {
3
+ value: string;
4
+ isSelect?: boolean;
5
+ disabled?: boolean;
6
+ handleItemClick?: (value: string) => void;
7
+ }
8
+ declare const SelectItem: React.FC<SelectItemProps>;
9
+ export default SelectItem;
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import classNames from "classnames";
3
+ import Icon from "../Icon/icon";
4
+ import { faCheck } from "@fortawesome/free-solid-svg-icons";
5
+ const SelectItem = ({ value, isSelect, disabled, handleItemClick, }) => {
6
+ const handleClick = () => {
7
+ if (!disabled && handleItemClick)
8
+ handleItemClick(value);
9
+ };
10
+ const classes = classNames('select-item', {
11
+ 'is-select': isSelect,
12
+ 'is-disabled': disabled,
13
+ });
14
+ return (_jsx("li", { onClick: () => handleClick(), className: classes, children: _jsxs("div", { className: "select-item-inner-wrapper", children: [_jsx("div", { className: "select-item-text", children: value }), isSelect && _jsx(Icon, { icon: faCheck, className: "select-item-icon", "aria-label": `select item ${value}` })] }) }));
15
+ };
16
+ SelectItem.displayName = 'SelectItem';
17
+ export default SelectItem;