fis-component 0.0.79 → 0.0.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.
- package/dist/cjs/index.js +194 -17
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/src/components/Toast/index.d.ts +1 -1
- package/dist/cjs/types/src/components/Toast/styles.d.ts +1 -1
- package/dist/cjs/types/src/components/Tooltip/index.d.ts +2 -0
- package/dist/cjs/types/src/components/Tooltip/useSmartTooltipPlacement.d.ts +5 -0
- package/dist/esm/index.js +194 -17
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/src/components/Toast/index.d.ts +1 -1
- package/dist/esm/types/src/components/Toast/styles.d.ts +1 -1
- package/dist/esm/types/src/components/Tooltip/index.d.ts +2 -0
- package/dist/esm/types/src/components/Tooltip/useSmartTooltipPlacement.d.ts +5 -0
- package/dist/index.d.ts +3 -1
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -61835,13 +61835,139 @@ const DivTitleWrap = styled.div `
|
|
|
61835
61835
|
`;
|
|
61836
61836
|
const ToastWrapper = styled.div `
|
|
61837
61837
|
position: fixed;
|
|
61838
|
-
|
|
61839
|
-
left: 50%;
|
|
61840
|
-
transform: translateX(-50%);
|
|
61841
|
-
z-index: 1000;
|
|
61838
|
+
z-index: 1050; /* Cao hơn bootstrap modal (1040) và các component khác */
|
|
61842
61839
|
display: flex;
|
|
61843
61840
|
flex-direction: column;
|
|
61844
|
-
gap:
|
|
61841
|
+
gap: 12px; /* Tăng gap để toast không quá sát nhau */
|
|
61842
|
+
max-width: 420px; /* Tăng một chút cho nội dung dài */
|
|
61843
|
+
min-width: 320px; /* Tăng min-width cho đẹp hơn */
|
|
61844
|
+
pointer-events: none; /* Tránh chặn click vào các element phía sau */
|
|
61845
|
+
|
|
61846
|
+
/* Cho phép click vào các toast con */
|
|
61847
|
+
> * {
|
|
61848
|
+
pointer-events: auto;
|
|
61849
|
+
}
|
|
61850
|
+
|
|
61851
|
+
${(props) => {
|
|
61852
|
+
switch (props.$position) {
|
|
61853
|
+
case "top-center":
|
|
61854
|
+
return styled.css `
|
|
61855
|
+
top: 24px;
|
|
61856
|
+
left: 50%;
|
|
61857
|
+
transform: translateX(-50%);
|
|
61858
|
+
`;
|
|
61859
|
+
case "bottom-center":
|
|
61860
|
+
return styled.css `
|
|
61861
|
+
bottom: 24px;
|
|
61862
|
+
left: 50%;
|
|
61863
|
+
transform: translateX(-50%);
|
|
61864
|
+
flex-direction: column-reverse; /* Toast mới xuất hiện từ dưới lên */
|
|
61865
|
+
`;
|
|
61866
|
+
case "top-right":
|
|
61867
|
+
return styled.css `
|
|
61868
|
+
top: 24px;
|
|
61869
|
+
right: 24px;
|
|
61870
|
+
`;
|
|
61871
|
+
case "bottom-right":
|
|
61872
|
+
return styled.css `
|
|
61873
|
+
bottom: 24px;
|
|
61874
|
+
right: 24px;
|
|
61875
|
+
flex-direction: column-reverse;
|
|
61876
|
+
`;
|
|
61877
|
+
case "top-left":
|
|
61878
|
+
return styled.css `
|
|
61879
|
+
top: 24px;
|
|
61880
|
+
left: 24px;
|
|
61881
|
+
`;
|
|
61882
|
+
case "bottom-left":
|
|
61883
|
+
return styled.css `
|
|
61884
|
+
bottom: 24px;
|
|
61885
|
+
left: 24px;
|
|
61886
|
+
flex-direction: column-reverse;
|
|
61887
|
+
`;
|
|
61888
|
+
default:
|
|
61889
|
+
return styled.css `
|
|
61890
|
+
top: 24px;
|
|
61891
|
+
left: 50%;
|
|
61892
|
+
transform: translateX(-50%);
|
|
61893
|
+
`;
|
|
61894
|
+
}
|
|
61895
|
+
}}
|
|
61896
|
+
|
|
61897
|
+
/* Animation cho toast xuất hiện */
|
|
61898
|
+
> div {
|
|
61899
|
+
animation: toastSlideIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
61900
|
+
}
|
|
61901
|
+
|
|
61902
|
+
@keyframes toastSlideIn {
|
|
61903
|
+
from {
|
|
61904
|
+
opacity: 0;
|
|
61905
|
+
transform: translateY(-12px) scale(0.95);
|
|
61906
|
+
}
|
|
61907
|
+
to {
|
|
61908
|
+
opacity: 1;
|
|
61909
|
+
transform: translateY(0) scale(1);
|
|
61910
|
+
}
|
|
61911
|
+
}
|
|
61912
|
+
|
|
61913
|
+
/* Animation cho bottom positions */
|
|
61914
|
+
${(props) => props.$position?.includes("bottom") &&
|
|
61915
|
+
styled.css `
|
|
61916
|
+
> div {
|
|
61917
|
+
animation: toastSlideInBottom 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
61918
|
+
}
|
|
61919
|
+
|
|
61920
|
+
@keyframes toastSlideInBottom {
|
|
61921
|
+
from {
|
|
61922
|
+
opacity: 0;
|
|
61923
|
+
transform: translateY(12px) scale(0.95);
|
|
61924
|
+
}
|
|
61925
|
+
to {
|
|
61926
|
+
opacity: 1;
|
|
61927
|
+
transform: translateY(0) scale(1);
|
|
61928
|
+
}
|
|
61929
|
+
}
|
|
61930
|
+
`}
|
|
61931
|
+
|
|
61932
|
+
/* Responsive cho mobile */
|
|
61933
|
+
@media (max-width: 768px) {
|
|
61934
|
+
max-width: calc(100vw - 32px);
|
|
61935
|
+
min-width: calc(100vw - 32px);
|
|
61936
|
+
|
|
61937
|
+
${(props) => {
|
|
61938
|
+
if (props.$position?.includes("center")) {
|
|
61939
|
+
return styled.css `
|
|
61940
|
+
left: 16px;
|
|
61941
|
+
right: 16px;
|
|
61942
|
+
transform: none;
|
|
61943
|
+
`;
|
|
61944
|
+
}
|
|
61945
|
+
else if (props.$position?.includes("left")) {
|
|
61946
|
+
return styled.css `
|
|
61947
|
+
left: 16px;
|
|
61948
|
+
`;
|
|
61949
|
+
}
|
|
61950
|
+
else if (props.$position?.includes("right")) {
|
|
61951
|
+
return styled.css `
|
|
61952
|
+
right: 16px;
|
|
61953
|
+
`;
|
|
61954
|
+
}
|
|
61955
|
+
}}
|
|
61956
|
+
|
|
61957
|
+
${(props) => props.$position?.includes("top")
|
|
61958
|
+
? styled.css `
|
|
61959
|
+
top: 16px;
|
|
61960
|
+
`
|
|
61961
|
+
: styled.css `
|
|
61962
|
+
bottom: 16px;
|
|
61963
|
+
`}
|
|
61964
|
+
}
|
|
61965
|
+
|
|
61966
|
+
/* Tablet breakpoint */
|
|
61967
|
+
@media (max-width: 1024px) and (min-width: 769px) {
|
|
61968
|
+
max-width: 380px;
|
|
61969
|
+
min-width: 300px;
|
|
61970
|
+
}
|
|
61845
61971
|
`;
|
|
61846
61972
|
|
|
61847
61973
|
const getPadding = (size, borderPath) => {
|
|
@@ -62567,7 +62693,7 @@ const ToastProvider = ({ children, }) => {
|
|
|
62567
62693
|
setToasts((prev) => prev.slice(1));
|
|
62568
62694
|
}, duration);
|
|
62569
62695
|
}, []);
|
|
62570
|
-
return (jsxRuntime.jsxs(ToastContext.Provider, { value: { showToast }, children: [children, toasts.length > 0 && (jsxRuntime.jsx(ToastWrapper, { "$position": toasts[0].position || "top-
|
|
62696
|
+
return (jsxRuntime.jsxs(ToastContext.Provider, { value: { showToast }, children: [children, toasts.length > 0 && (jsxRuntime.jsx(ToastWrapper, { "$position": toasts[0].position || "top-right", children: toasts.map((toast, index) => (jsxRuntime.jsx(FISToast, { ...toast }, index))) }))] }));
|
|
62571
62697
|
};
|
|
62572
62698
|
|
|
62573
62699
|
const FISThemeProvider = ({ theme: theme$1 = theme, children, }) => (jsxRuntime.jsxs(styled.ThemeProvider, { theme: theme$1, children: [jsxRuntime.jsx(GlobalStyle, { theme: theme$1 }), jsxRuntime.jsx(NotificationProvider, { children: jsxRuntime.jsx(ToastProvider, { children: children }) })] }));
|
|
@@ -66317,18 +66443,58 @@ const DivTooltipSC = styled.div `
|
|
|
66317
66443
|
}
|
|
66318
66444
|
`;
|
|
66319
66445
|
|
|
66320
|
-
const
|
|
66446
|
+
const useSmartTooltipPlacement = () => {
|
|
66447
|
+
const [placement, setPlacement] = React.useState("right");
|
|
66448
|
+
const calculatePlacement = React.useCallback((triggerEl) => {
|
|
66449
|
+
if (!triggerEl)
|
|
66450
|
+
return;
|
|
66451
|
+
const rect = triggerEl.getBoundingClientRect();
|
|
66452
|
+
const viewportWidth = window.innerWidth;
|
|
66453
|
+
const leftSpace = rect.left;
|
|
66454
|
+
const rightSpace = viewportWidth - rect.right;
|
|
66455
|
+
if (rightSpace > leftSpace) {
|
|
66456
|
+
setPlacement("right");
|
|
66457
|
+
}
|
|
66458
|
+
else if (leftSpace > rightSpace) {
|
|
66459
|
+
setPlacement("left");
|
|
66460
|
+
}
|
|
66461
|
+
else {
|
|
66462
|
+
setPlacement("right");
|
|
66463
|
+
}
|
|
66464
|
+
}, []);
|
|
66465
|
+
return { placement, calculatePlacement };
|
|
66466
|
+
};
|
|
66467
|
+
|
|
66468
|
+
const FISTooltip = ({ className, variant = "primary", size = "md", title: titleProp, children, smartPlacement = false, ...rest }) => {
|
|
66321
66469
|
const theme = styled.useTheme();
|
|
66470
|
+
const triggerRef = React.useRef(null);
|
|
66471
|
+
const { placement, calculatePlacement } = useSmartTooltipPlacement();
|
|
66472
|
+
React.useEffect(() => {
|
|
66473
|
+
if (!smartPlacement)
|
|
66474
|
+
return;
|
|
66475
|
+
const el = triggerRef.current;
|
|
66476
|
+
if (!el)
|
|
66477
|
+
return;
|
|
66478
|
+
const handleMouseEnter = () => calculatePlacement(el);
|
|
66479
|
+
el.addEventListener("mouseenter", handleMouseEnter);
|
|
66480
|
+
calculatePlacement(el);
|
|
66481
|
+
return () => {
|
|
66482
|
+
el.removeEventListener("mouseenter", handleMouseEnter);
|
|
66483
|
+
};
|
|
66484
|
+
}, [smartPlacement, calculatePlacement]);
|
|
66485
|
+
const tooltipPlacement = smartPlacement
|
|
66486
|
+
? placement
|
|
66487
|
+
: rest.placement || "right";
|
|
66322
66488
|
if (isTooltipTitleCustom(titleProp)) {
|
|
66323
66489
|
// Create properly structured custom title
|
|
66324
66490
|
const title = (jsxRuntime.jsxs(DivTooltipContentWrapperSC, { children: [jsxRuntime.jsxs(DivTooltipContentSC, { children: [jsxRuntime.jsx(DivTooltipLabelSC, { children: titleProp.label }), titleProp.description && (jsxRuntime.jsx(DivTooltipDescriptionSC, { children: titleProp.description }))] }), titleProp.link && (jsxRuntime.jsx(ATooltipLinkSC, { href: titleProp.linkUrl, target: "_blank", rel: "noopener noreferrer", children: titleProp.link }))] }));
|
|
66325
|
-
return (jsxRuntime.jsx(DivTooltipSC, { className: className, "$size": size, "$variant": variant, children: jsxRuntime.jsx(Tooltip, { color: variant === "primary"
|
|
66326
|
-
|
|
66327
|
-
|
|
66491
|
+
return (jsxRuntime.jsx(DivTooltipSC, { className: className, "$size": size, "$variant": variant, children: jsxRuntime.jsx("span", { ref: smartPlacement ? triggerRef : undefined, children: jsxRuntime.jsx(Tooltip, { color: variant === "primary"
|
|
66492
|
+
? theme["com/tooltip/size-md/theme-black/background-color"]
|
|
66493
|
+
: theme["com/tooltip/size-md/theme-white/background-color"], title: title, getTooltipContainer: () => document.body, placement: tooltipPlacement, ...rest, children: children || jsxRuntime.jsx(Button$2, { children: "RT" }) }) }) }));
|
|
66328
66494
|
}
|
|
66329
|
-
return (jsxRuntime.jsx(DivTooltipSC, { className: className, "$size": size, "$variant": variant, children: jsxRuntime.jsx(Tooltip, { color: variant === "primary"
|
|
66330
|
-
|
|
66331
|
-
|
|
66495
|
+
return (jsxRuntime.jsx(DivTooltipSC, { className: className, "$size": size, "$variant": variant, children: jsxRuntime.jsx("span", { ref: smartPlacement ? triggerRef : undefined, children: jsxRuntime.jsx(Tooltip, { color: variant === "primary"
|
|
66496
|
+
? theme["com/tooltip/size-md/theme-black/background-color"]
|
|
66497
|
+
: theme["com/tooltip/size-md/theme-white/background-color"], title: titleProp, getTooltipContainer: () => document.body, placement: tooltipPlacement, ...rest, children: children || jsxRuntime.jsx(Button$2, { children: "RT" }) }) }) }));
|
|
66332
66498
|
};
|
|
66333
66499
|
FISTooltip.displayName = "FISTooltip";
|
|
66334
66500
|
|
|
@@ -67349,6 +67515,14 @@ const FISBadge = ({ className, icon, label, size = "sm", color, status, type = "
|
|
|
67349
67515
|
FISBadge.displayName = "FISBadge";
|
|
67350
67516
|
|
|
67351
67517
|
const FISMenuItem = ({ title, description, iconPrefix, type = "action", size = "md", selected = false, negative = false, disable, onClickMenu, }) => {
|
|
67518
|
+
const titleRef = React.useRef(null);
|
|
67519
|
+
const [isTruncated, setIsTruncated] = React.useState(false);
|
|
67520
|
+
React.useEffect(() => {
|
|
67521
|
+
const el = titleRef.current;
|
|
67522
|
+
if (el) {
|
|
67523
|
+
setIsTruncated(el.scrollWidth > el.clientWidth);
|
|
67524
|
+
}
|
|
67525
|
+
}, [title]);
|
|
67352
67526
|
const renderSuffixIcon = () => {
|
|
67353
67527
|
switch (type) {
|
|
67354
67528
|
case "action":
|
|
@@ -67365,9 +67539,12 @@ const FISMenuItem = ({ title, description, iconPrefix, type = "action", size = "
|
|
|
67365
67539
|
negative: negative,
|
|
67366
67540
|
}), "$size": size, "$selected": selected, "$type": type, "$disable": disable, onClick: onClickMenu, children: [iconPrefix && (jsxRuntime.jsx(DivPrefixIconSC, { className: classNames({
|
|
67367
67541
|
negative: negative,
|
|
67368
|
-
}), "$size": size, "$type": type, "$selected": selected, "$disable": disable, children: iconPrefix })), jsxRuntime.jsxs(DivContentSC$2, { children: [title &&
|
|
67369
|
-
|
|
67370
|
-
|
|
67542
|
+
}), "$size": size, "$type": type, "$selected": selected, "$disable": disable, children: iconPrefix })), jsxRuntime.jsxs(DivContentSC$2, { children: [title &&
|
|
67543
|
+
(isTruncated ? (jsxRuntime.jsx(FISTooltip, { title: title, variant: "primary", smartPlacement: true, children: jsxRuntime.jsx(PTitleSC$1, { ref: titleRef, className: classNames({
|
|
67544
|
+
negative: negative,
|
|
67545
|
+
}), "$selected": selected, "$type": type, "$disable": disable, children: title }) })) : (jsxRuntime.jsx(PTitleSC$1, { ref: titleRef, className: classNames({
|
|
67546
|
+
negative: negative,
|
|
67547
|
+
}), "$selected": selected, "$type": type, "$disable": disable, children: title }))), description && (jsxRuntime.jsx(PDescriptionSC, { className: classNames({
|
|
67371
67548
|
negative: negative,
|
|
67372
67549
|
}), "$type": type, "$selected": selected, "$disable": disable, children: description }))] }), renderSuffixIcon()] }));
|
|
67373
67550
|
};
|
|
@@ -67497,7 +67674,7 @@ const FISMenuSelect = ({ placeholder, groups, size = "md", multi = false, select
|
|
|
67497
67674
|
onClickMenu?.();
|
|
67498
67675
|
}
|
|
67499
67676
|
};
|
|
67500
|
-
return (jsxRuntime.jsxs(DivContainerSC$4, { "$maxHeight": maxHeight, className: className, children: [showInput && !combobox && (jsxRuntime.jsx(DivSearchSC, { children: jsxRuntime.jsx(FISInputText, { iconPrefix: jsxRuntime.jsx(SearchIcon, {}), placeholder: placeholder, value: search, onChange: handleSearchChange }) })), (shouldShowNoResult || noResult) && (jsxRuntime.jsxs(DivLoaderSC, { children: [jsxRuntime.jsx(DivIconDataSC, { children: jsxRuntime.jsx(NoResultIcon, {}) }), jsxRuntime.jsx(PTitleSC$2, { children: noResultText })] })), noData && (jsxRuntime.jsxs(DivLoaderSC, { children: [jsxRuntime.jsx(DivIconDataSC, { children: jsxRuntime.jsx(NoDataIcon, {}) }), jsxRuntime.jsx(PTitleSC$2, { children: noDataText })] })), loading && (jsxRuntime.jsxs(DivLoaderSC, { children: [jsxRuntime.jsx(FISProgressCircular, { size: size, variant: "indeterminate" }), jsxRuntime.jsx(PTitleSC$2, { children: loadingText })] })), !shouldShowNoResult && !noData && !loading && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(MenuContent, { "$removeSelectedGroup": !!removeSelectedGroup, children: groupsToRender.map((group, index) => (jsxRuntime.jsxs(DivWrapperSC$4, { children: [index !== 0 && jsxRuntime.jsx(FISMenuSection, { withDivider: true }), group?.groupLabel && (jsxRuntime.jsx(FISMenuSection, { label: group?.groupLabel })), group.items.map((item, idx) => (jsxRuntime.jsx(FISMenuItem, { title: item.label, description: item.description, size: size, onClickMenu: () => handleItemClick(item), selected: selectedValues.includes(item.value), type: "select" }, idx)))] }, index))) }), removeSelectedGroup && (jsxRuntime.jsx(FixedBottomSection, { children: jsxRuntime.jsx(DivWrapperSC$4, { children: removeSelectedGroup.items.map((item, idx) => (jsxRuntime.jsx(FISMenuItem, { title: item.label, description: item.description, size: size, onClickMenu: () => onChangeSelected?.([]), type: "select", iconPrefix: jsxRuntime.jsx(RemoveIcon, {}), negative: true }, idx))) }) }))] }))] }));
|
|
67677
|
+
return (jsxRuntime.jsxs(DivContainerSC$4, { "$maxHeight": maxHeight, className: className, children: [showInput && !combobox && (jsxRuntime.jsx(DivSearchSC, { children: jsxRuntime.jsx(FISInputText, { iconPrefix: jsxRuntime.jsx(SearchIcon, {}), placeholder: placeholder, value: search, onChange: handleSearchChange }) })), (shouldShowNoResult || noResult) && (jsxRuntime.jsxs(DivLoaderSC, { children: [jsxRuntime.jsx(DivIconDataSC, { children: jsxRuntime.jsx(NoResultIcon, {}) }), jsxRuntime.jsx(PTitleSC$2, { children: noResultText })] })), noData && (jsxRuntime.jsxs(DivLoaderSC, { children: [jsxRuntime.jsx(DivIconDataSC, { children: jsxRuntime.jsx(NoDataIcon, {}) }), jsxRuntime.jsx(PTitleSC$2, { children: noDataText })] })), loading && (jsxRuntime.jsxs(DivLoaderSC, { children: [jsxRuntime.jsx(FISProgressCircular, { size: size, variant: "indeterminate" }), jsxRuntime.jsx(PTitleSC$2, { children: loadingText })] })), !shouldShowNoResult && !noData && !loading && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(MenuContent, { "$removeSelectedGroup": !!removeSelectedGroup, children: groupsToRender.map((group, index) => (jsxRuntime.jsxs(DivWrapperSC$4, { children: [index !== 0 && jsxRuntime.jsx(FISMenuSection, { withDivider: true }), group?.groupLabel && (jsxRuntime.jsx(FISMenuSection, { label: group?.groupLabel })), group.items.map((item, idx) => (jsxRuntime.jsx(FISTooltip, { title: item.label, variant: "primary", children: jsxRuntime.jsx(FISMenuItem, { title: item.label, description: item.description, size: size, onClickMenu: () => handleItemClick(item), selected: selectedValues.includes(item.value), type: "select" }) }, idx)))] }, index))) }), removeSelectedGroup && (jsxRuntime.jsx(FixedBottomSection, { children: jsxRuntime.jsx(DivWrapperSC$4, { children: removeSelectedGroup.items.map((item, idx) => (jsxRuntime.jsx(FISTooltip, { title: item.label, variant: "primary", children: jsxRuntime.jsx(FISMenuItem, { title: item.label, description: item.description, size: size, onClickMenu: () => onChangeSelected?.([]), type: "select", iconPrefix: jsxRuntime.jsx(RemoveIcon, {}), negative: true }) }, idx))) }) }))] }))] }));
|
|
67501
67678
|
};
|
|
67502
67679
|
FISMenuSelect.displayName = "FISMenuSelect";
|
|
67503
67680
|
|