forstok-ui-lib 3.0.1 → 4.0.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.
- package/dist/index.d.ts +92 -1
- package/dist/index.js +406 -65
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +406 -65
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -2
- package/src/assets/stylesheets/shares.styles.ts +1 -1
- package/src/components/dropdown/dropdown.styles.ts +325 -0
- package/src/components/dropdown/dropdown.tsx +254 -0
- package/src/components/dropdown/dropdown.typed.ts +24 -0
- package/src/components/index.ts +9 -0
- package/src/components/message/message.styles.ts +211 -0
- package/src/components/message/message.tsx +62 -0
- package/src/components/message/message.typed.ts +18 -0
- package/src/components/message/message_question.tsx +72 -0
- package/src/components/popup/popup.styles.ts +315 -0
- package/src/components/popup/popup.tsx +92 -0
- package/src/components/popup/popup.typed.ts +33 -0
- package/src/components/portal/react_portal.tsx +37 -0
- package/src/typeds/shares.typed.ts +18 -0
- package/tsconfig.json +6 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { type ReactNode, isValidElement, useEffect, useRef, useCallback } from 'react';
|
|
2
|
+
import ReactTooltip from 'react-tooltip';
|
|
3
|
+
import { useStateWithCallbackLazy } from 'use-state-with-callback';
|
|
4
|
+
import ButtonComponent from '../button/button';
|
|
5
|
+
import IconComponent from '../icon/icon';
|
|
6
|
+
import { PopupPanel, PopupOverlay, PopupContainer, PopupWrapper, PopupHeaderWrapper, PopupHeader, PopupBody, PopupFooter, PopupQuestionWrapper } from './popup.styles';
|
|
7
|
+
import type { TPopup } from './popup.typed';
|
|
8
|
+
|
|
9
|
+
type TPopupOtherProp = {
|
|
10
|
+
children: ReactNode[]
|
|
11
|
+
'data-qa-id'?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let timerHandle:ReturnType<typeof setTimeout>
|
|
15
|
+
const PopupComponent = ({ children, body, mode, height, width, isOpen, evTooglePopup, ...props }: TPopup & TPopupOtherProp) => {
|
|
16
|
+
const [isOpenWrapper, setOpenWrapper] = useStateWithCallbackLazy<boolean>(false);
|
|
17
|
+
|
|
18
|
+
const popupContainerRef = useRef<HTMLElement | null>(null);
|
|
19
|
+
useEffect(() => { ReactTooltip.rebuild(); }, [])
|
|
20
|
+
|
|
21
|
+
const evOpen = useCallback((isOpen: boolean) => {
|
|
22
|
+
timerHandle = setTimeout(() => {
|
|
23
|
+
setOpenWrapper(isOpen, () => {
|
|
24
|
+
const popupContainerEl = (popupContainerRef && popupContainerRef.current) ? popupContainerRef.current : null;
|
|
25
|
+
popupContainerEl && (popupContainerEl.scrollTop = 0);
|
|
26
|
+
});
|
|
27
|
+
clearTimeout(timerHandle);
|
|
28
|
+
}, 1);
|
|
29
|
+
}, [setOpenWrapper])
|
|
30
|
+
|
|
31
|
+
const initialize = () => {
|
|
32
|
+
evOpen(isOpen);
|
|
33
|
+
}
|
|
34
|
+
const initRef = useRef({ init: initialize });
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const { init } = initRef.current;
|
|
38
|
+
init();
|
|
39
|
+
|
|
40
|
+
return(() => {
|
|
41
|
+
clearTimeout(timerHandle);
|
|
42
|
+
})
|
|
43
|
+
}, [])
|
|
44
|
+
|
|
45
|
+
useEffect(()=> {
|
|
46
|
+
evOpen(isOpen);
|
|
47
|
+
}, [isOpen, evOpen])
|
|
48
|
+
|
|
49
|
+
let newChildren = [...children];
|
|
50
|
+
const HeadChildrenFilter = newChildren?.filter((child: any) => isValidElement(child) && (child.props as any)['aria-label'] === 'head') || null;
|
|
51
|
+
const SubHeadChildrenFilter = newChildren?.filter((child: any) => isValidElement(child) && (child.props as any)['aria-label'] === 'sub-head') || null;
|
|
52
|
+
const BodyChildrenFilter = newChildren?.filter((child: any) => isValidElement(child) && (child.props as any)['aria-label'] === 'body') || null;
|
|
53
|
+
const FootChildrenFilter = newChildren?.filter((child: any) => isValidElement(child) && (child.props as any)['aria-label'] === 'foot') || null;
|
|
54
|
+
const LeftFootChildrenFilter = newChildren?.filter((child: any) => isValidElement(child) && (child.props as any)['aria-label'] === 'left-foot') || null;
|
|
55
|
+
const SubHeadChildrenEl = SubHeadChildrenFilter.length ? <aside>{(SubHeadChildrenFilter[0] && isValidElement(SubHeadChildrenFilter[0])) ? (SubHeadChildrenFilter[0].props as any).children : null}</aside> : null;
|
|
56
|
+
const popupHeaderQaId = HeadChildrenFilter.length ? (HeadChildrenFilter[0] && isValidElement(HeadChildrenFilter[0])) ? (HeadChildrenFilter[0].props as any)['data-qa-id'] : '' : '';
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<PopupPanel $isOpen={isOpen}>
|
|
60
|
+
<PopupOverlay />
|
|
61
|
+
<PopupContainer ref={popupContainerRef} {...props['data-qa-id'] && { 'data-qa-id': props['data-qa-id'] }}>
|
|
62
|
+
{
|
|
63
|
+
mode === 'question' ? (
|
|
64
|
+
<PopupWrapper $isOpen={isOpenWrapper}>
|
|
65
|
+
<PopupQuestionWrapper $width={width}>
|
|
66
|
+
<IconComponent $name='warning' $width='30px' />
|
|
67
|
+
<PopupHeaderWrapper $mode={mode}>
|
|
68
|
+
{ HeadChildrenFilter.length ? <PopupHeader>{(HeadChildrenFilter[0] && isValidElement(HeadChildrenFilter[0])) ? (HeadChildrenFilter[0].props as any).children : null}</PopupHeader> : null }
|
|
69
|
+
{SubHeadChildrenEl}
|
|
70
|
+
{ FootChildrenFilter.length ? <PopupFooter>{(FootChildrenFilter[0] && isValidElement(FootChildrenFilter[0])) ? <aside data-type={(FootChildrenFilter[0].props as any).type || ""}>{(FootChildrenFilter[0].props as any).children}</aside> : null}</PopupFooter> : null }
|
|
71
|
+
</PopupHeaderWrapper>
|
|
72
|
+
</PopupQuestionWrapper>
|
|
73
|
+
</PopupWrapper>
|
|
74
|
+
) : (
|
|
75
|
+
<>
|
|
76
|
+
<PopupHeaderWrapper $width={width} $isOpen={isOpenWrapper} $mode={mode}>
|
|
77
|
+
{HeadChildrenFilter.length ? <><ButtonComponent $mode='round-close' onClick={evTooglePopup}></ButtonComponent><PopupHeader data-qa-id={popupHeaderQaId}>{(HeadChildrenFilter[0] && isValidElement(HeadChildrenFilter[0])) && (HeadChildrenFilter[0].props as any).children}</PopupHeader></> : null}
|
|
78
|
+
</PopupHeaderWrapper>
|
|
79
|
+
<PopupWrapper $width={width} $isOpen={isOpenWrapper} $withHeader={HeadChildrenFilter.length ? true : false}>
|
|
80
|
+
{SubHeadChildrenEl}
|
|
81
|
+
{ BodyChildrenFilter.length ? <PopupBody $mode={body} $width={width} $height={height}>{(BodyChildrenFilter[0] && isValidElement(BodyChildrenFilter[0])) && (BodyChildrenFilter[0].props as any).children}</PopupBody> : null }
|
|
82
|
+
{ FootChildrenFilter.length ? <PopupFooter $isLeft={LeftFootChildrenFilter.length ? true : false}><aside>{(LeftFootChildrenFilter && LeftFootChildrenFilter.length && LeftFootChildrenFilter[0] && isValidElement(LeftFootChildrenFilter[0])) ? (LeftFootChildrenFilter[0].props as any).children : null}</aside>{(FootChildrenFilter[0] && isValidElement(FootChildrenFilter[0])) ? <aside data-type={(FootChildrenFilter[0].props as any).type || ""}>{mode && mode === 'info' ? <ButtonComponent $mode='white' $size='small' onClick={evTooglePopup}>Close</ButtonComponent> : <ButtonComponent $mode='white' $size='small' onClick={evTooglePopup} data-qa-id='popup-button-cancel'>Cancel</ButtonComponent>}{(FootChildrenFilter[0].props as any).children}</aside> : null}</PopupFooter> : null }
|
|
83
|
+
</PopupWrapper>
|
|
84
|
+
</>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
</PopupContainer>
|
|
88
|
+
</PopupPanel>
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export default PopupComponent
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { MouseEvent } from 'react'
|
|
2
|
+
|
|
3
|
+
import type { TMessageFunction } from '../message/message.typed'
|
|
4
|
+
|
|
5
|
+
export type TPopupOpenFunction = (e: MouseEvent, el?: string) => void
|
|
6
|
+
|
|
7
|
+
export type TPopupFunctionParam = {
|
|
8
|
+
mode?: string | null
|
|
9
|
+
path?: string | null
|
|
10
|
+
action?: string | null
|
|
11
|
+
detail?: any
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type TPopupFunction = (props?: TPopupFunctionParam) => void
|
|
15
|
+
|
|
16
|
+
export type TPopupFunctionGroup = {
|
|
17
|
+
evTooglePopup?: TPopupFunction
|
|
18
|
+
evCreateMessage?: TMessageFunction
|
|
19
|
+
evForcePopUp?: TPopupFunction
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type TPopupContainer = {
|
|
23
|
+
isOpen: boolean
|
|
24
|
+
} & Required<TPopupFunctionParam> & Required<TPopupFunctionGroup>
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
export type TPopup = {
|
|
28
|
+
isOpen: boolean
|
|
29
|
+
body?: string
|
|
30
|
+
height?: string|number
|
|
31
|
+
width?: string|number
|
|
32
|
+
type?: string
|
|
33
|
+
} & TPopupFunctionParam & TPopupFunctionGroup
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useState, useLayoutEffect, type ReactNode } from 'react';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
3
|
+
|
|
4
|
+
function createWrapperAndAppendToBody(wrapperId: string) {
|
|
5
|
+
const wrapperElement = document.createElement('div');
|
|
6
|
+
wrapperElement.setAttribute('id', wrapperId);
|
|
7
|
+
document.body.appendChild(wrapperElement);
|
|
8
|
+
return wrapperElement;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function ReactPortalComponent({ children, wrapperId='popup-portal' }:{ children: ReactNode, wrapperId?: string }) {
|
|
12
|
+
const [wrapperElement, setWrapperElement] = useState<Element | DocumentFragment>();
|
|
13
|
+
|
|
14
|
+
useLayoutEffect(() => {
|
|
15
|
+
let element = document.getElementById(wrapperId);
|
|
16
|
+
let systemCreated = false;
|
|
17
|
+
if (!element) {
|
|
18
|
+
systemCreated = true;
|
|
19
|
+
element = createWrapperAndAppendToBody(wrapperId);
|
|
20
|
+
}
|
|
21
|
+
setWrapperElement(element);
|
|
22
|
+
|
|
23
|
+
return () => {
|
|
24
|
+
if (systemCreated && (element && element.parentNode)) {
|
|
25
|
+
element.parentNode.removeChild(element);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}, [wrapperId])
|
|
29
|
+
|
|
30
|
+
if (typeof wrapperElement === 'undefined') {
|
|
31
|
+
return <></>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return createPortal(children, wrapperElement);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default ReactPortalComponent;
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import { TObject } from './base.typed';
|
|
2
|
+
import { TCloseDropdownFunction } from '../components/dropdown/dropdown.typed';
|
|
3
|
+
import { TMessageFunction, TMessageQuestionFunction } from '../components/message/message.typed';
|
|
4
|
+
import { TPopupFunction, TPopupOpenFunction } from '../components/popup/popup.typed';
|
|
5
|
+
|
|
1
6
|
export type TUser = {
|
|
2
7
|
profile_id: number,
|
|
3
8
|
profile_name: string,
|
|
@@ -15,4 +20,17 @@ export type TUser = {
|
|
|
15
20
|
shopee_partner_key: string
|
|
16
21
|
},
|
|
17
22
|
has_access_orderV1: boolean
|
|
23
|
+
}
|
|
24
|
+
export type THierarchy = {
|
|
25
|
+
evTooglePopup?: TPopupFunction
|
|
26
|
+
evCreateMessage?: TMessageFunction
|
|
27
|
+
evForcePopUp?: TPopupFunction
|
|
28
|
+
isOpenPopup: boolean
|
|
29
|
+
modePopup: string
|
|
30
|
+
pathPopup: string
|
|
31
|
+
actionPopup: string
|
|
32
|
+
detailPopup?: TObject
|
|
33
|
+
evOpenPopup?: TPopupOpenFunction
|
|
34
|
+
evCloseDropdown?: TCloseDropdownFunction
|
|
35
|
+
evCreateMessageQuestion?: TMessageQuestionFunction
|
|
18
36
|
}
|
package/tsconfig.json
CHANGED