@kkcompany/app-ui 0.1.29 → 0.1.31
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.cjs +398 -4
- package/dist/index.d.cts +50 -2
- package/dist/index.d.mts +50 -2
- package/dist/index.mjs +398 -6
- package/package.json +7 -3
package/dist/index.cjs
CHANGED
|
@@ -712,6 +712,396 @@ const Icon = ({ style = {}, src }) => /* @__PURE__ */ (0, __emotion_react_jsx_ru
|
|
|
712
712
|
] });
|
|
713
713
|
var Icon_default = Icon;
|
|
714
714
|
|
|
715
|
+
//#endregion
|
|
716
|
+
//#region src/Modal/styles.ts
|
|
717
|
+
const modalStyle = __emotion_react.css`
|
|
718
|
+
:where(&) {
|
|
719
|
+
position: fixed;
|
|
720
|
+
top: 0;
|
|
721
|
+
right: 0;
|
|
722
|
+
bottom: 0;
|
|
723
|
+
left: 0;
|
|
724
|
+
z-index: 1000;
|
|
725
|
+
padding: 1rem;
|
|
726
|
+
overflow-x: hidden;
|
|
727
|
+
overflow-y: auto;
|
|
728
|
+
visibility: hidden;
|
|
729
|
+
opacity: 0;
|
|
730
|
+
background-color: rgba(0, 0, 0, 0.7);
|
|
731
|
+
transition: opacity 0.3s;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
:where(&.modal--show),
|
|
735
|
+
:where(&.modal--shown) {
|
|
736
|
+
display: flex;
|
|
737
|
+
justify-content: center;
|
|
738
|
+
visibility: visible;
|
|
739
|
+
opacity: 1;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
:where(.modal__content) {
|
|
743
|
+
width: 100%;
|
|
744
|
+
max-width: 700px;
|
|
745
|
+
margin: auto 0;
|
|
746
|
+
}
|
|
747
|
+
`;
|
|
748
|
+
|
|
749
|
+
//#endregion
|
|
750
|
+
//#region src/Modal/index.tsx
|
|
751
|
+
const MODAL_STATE = {
|
|
752
|
+
SHOW: "show",
|
|
753
|
+
SHOWN: "shown",
|
|
754
|
+
HIDE: "hide",
|
|
755
|
+
HIDDEN: "hidden"
|
|
756
|
+
};
|
|
757
|
+
const isShowing = (state) => state === MODAL_STATE.SHOW || state === MODAL_STATE.SHOWN;
|
|
758
|
+
const Modal = (0, react.memo)((0, react.forwardRef)(function Modal$1({ children, className = "", isHideModalOnClickOverlay = true, isShow, onHidden = () => {}, onShown = () => {}, onTriggerHiding = () => {} }, ref) {
|
|
759
|
+
const [visualState, setVisualState] = (0, react.useState)(MODAL_STATE.HIDDEN);
|
|
760
|
+
const shouldLockBody = isShowing(visualState);
|
|
761
|
+
if (isShow && !isShowing(visualState)) setVisualState(MODAL_STATE.SHOW);
|
|
762
|
+
else if (!isShow && isShowing(visualState)) setVisualState(MODAL_STATE.HIDE);
|
|
763
|
+
(0, react.useLayoutEffect)(() => {
|
|
764
|
+
if (!shouldLockBody) return;
|
|
765
|
+
const previousOverflow = document.body.style.overflow;
|
|
766
|
+
document.body.style.overflow = "hidden";
|
|
767
|
+
return () => {
|
|
768
|
+
document.body.style.overflow = previousOverflow;
|
|
769
|
+
};
|
|
770
|
+
}, [shouldLockBody]);
|
|
771
|
+
const previousVisualState = (0, react.useRef)(visualState);
|
|
772
|
+
(0, react.useLayoutEffect)(() => {
|
|
773
|
+
if (previousVisualState.current === visualState) return;
|
|
774
|
+
previousVisualState.current = visualState;
|
|
775
|
+
if (visualState === MODAL_STATE.SHOWN) onShown();
|
|
776
|
+
else if (visualState === MODAL_STATE.HIDDEN) onHidden();
|
|
777
|
+
}, [
|
|
778
|
+
visualState,
|
|
779
|
+
onShown,
|
|
780
|
+
onHidden
|
|
781
|
+
]);
|
|
782
|
+
const handleAnimationEnd = (0, react.useCallback)(() => {
|
|
783
|
+
setVisualState((previousState) => {
|
|
784
|
+
if (previousState === MODAL_STATE.SHOW) return MODAL_STATE.SHOWN;
|
|
785
|
+
if (previousState === MODAL_STATE.HIDE) return MODAL_STATE.HIDDEN;
|
|
786
|
+
return previousState;
|
|
787
|
+
});
|
|
788
|
+
}, []);
|
|
789
|
+
const handleClick = (0, react.useCallback)((event) => {
|
|
790
|
+
if (event.target.getAttribute("data-dismiss") === "modal") onTriggerHiding();
|
|
791
|
+
}, [onTriggerHiding]);
|
|
792
|
+
const handleKeyDown = (0, react.useCallback)((event) => {
|
|
793
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
794
|
+
if (event.target.getAttribute("data-dismiss") !== "modal") return;
|
|
795
|
+
event.preventDefault();
|
|
796
|
+
onTriggerHiding();
|
|
797
|
+
}, [onTriggerHiding]);
|
|
798
|
+
return /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsx)("div", {
|
|
799
|
+
css: modalStyle,
|
|
800
|
+
ref,
|
|
801
|
+
role: "presentation",
|
|
802
|
+
className: `modal modal--${visualState} ${className}`,
|
|
803
|
+
onClick: handleClick,
|
|
804
|
+
onKeyDown: handleKeyDown,
|
|
805
|
+
onAnimationEnd: handleAnimationEnd,
|
|
806
|
+
onTransitionEnd: handleAnimationEnd,
|
|
807
|
+
"data-dismiss": isHideModalOnClickOverlay ? "modal" : void 0,
|
|
808
|
+
children: /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsx)("div", {
|
|
809
|
+
className: "modal__content",
|
|
810
|
+
children
|
|
811
|
+
})
|
|
812
|
+
});
|
|
813
|
+
}));
|
|
814
|
+
var Modal_default = Modal;
|
|
815
|
+
|
|
816
|
+
//#endregion
|
|
817
|
+
//#region src/Pagination/PaginationLink.tsx
|
|
818
|
+
const PaginationLink = ({ routeData, nextLink: NextLinkComponent, children, ...anchorProps }) => {
|
|
819
|
+
const anchor = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
820
|
+
...anchorProps,
|
|
821
|
+
href: NextLinkComponent ? void 0 : routeData.route,
|
|
822
|
+
children
|
|
823
|
+
});
|
|
824
|
+
if (!NextLinkComponent) return anchor;
|
|
825
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NextLinkComponent, {
|
|
826
|
+
route: routeData.route,
|
|
827
|
+
params: routeData.routeParams,
|
|
828
|
+
...routeData.routeOptions || {},
|
|
829
|
+
children: anchor
|
|
830
|
+
});
|
|
831
|
+
};
|
|
832
|
+
var PaginationLink_default = PaginationLink;
|
|
833
|
+
|
|
834
|
+
//#endregion
|
|
835
|
+
//#region src/Pagination/ArrowButton.tsx
|
|
836
|
+
const ArrowButton = ({ type, routeData, nextLink, disabled = false, onClick }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PaginationLink_default, {
|
|
837
|
+
className: `kks-pagination__btn kks-pagination__arrow-btn kks-pagination__arrow-btn--${type}${disabled ? " kks-pagination__arrow-btn--hidden" : ""}`,
|
|
838
|
+
routeData,
|
|
839
|
+
nextLink,
|
|
840
|
+
rel: type,
|
|
841
|
+
"aria-label": type === "prev" ? "Previous page" : "Next page",
|
|
842
|
+
onClick,
|
|
843
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: `kks-pagination__icon kks-pagination__icon-${type}` })
|
|
844
|
+
});
|
|
845
|
+
var ArrowButton_default = ArrowButton;
|
|
846
|
+
|
|
847
|
+
//#endregion
|
|
848
|
+
//#region src/Pagination/DotsButton.tsx
|
|
849
|
+
const DotsButton = ({ dots }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
850
|
+
className: "kks-pagination__dots",
|
|
851
|
+
children: dots
|
|
852
|
+
});
|
|
853
|
+
var DotsButton_default = DotsButton;
|
|
854
|
+
|
|
855
|
+
//#endregion
|
|
856
|
+
//#region src/Pagination/NumberButton.tsx
|
|
857
|
+
const NumberButton = ({ totalPages, pageNumber, routeData, nextLink, active = false, onClick }) => {
|
|
858
|
+
if (active) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
859
|
+
className: "kks-pagination__btn kks-pagination__num-btn kks-pagination__num-btn--active",
|
|
860
|
+
"data-total-pages": ` / ${totalPages}`,
|
|
861
|
+
"aria-current": "page",
|
|
862
|
+
children: pageNumber
|
|
863
|
+
});
|
|
864
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PaginationLink_default, {
|
|
865
|
+
className: "kks-pagination__btn kks-pagination__num-btn",
|
|
866
|
+
routeData,
|
|
867
|
+
nextLink,
|
|
868
|
+
onClick,
|
|
869
|
+
children: pageNumber
|
|
870
|
+
});
|
|
871
|
+
};
|
|
872
|
+
var NumberButton_default = NumberButton;
|
|
873
|
+
|
|
874
|
+
//#endregion
|
|
875
|
+
//#region src/Pagination/styles.ts
|
|
876
|
+
const paginationStyle = __emotion_react.css`
|
|
877
|
+
:where(&) {
|
|
878
|
+
display: inline-block;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
:where(.kks-pagination__content) {
|
|
882
|
+
display: flex;
|
|
883
|
+
margin: 0;
|
|
884
|
+
padding-left: 0;
|
|
885
|
+
list-style: none;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
:where(.kks-pagination__num-item:not(.kks-pagination__num-item--current)) {
|
|
889
|
+
display: none;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
:where(.kks-pagination__btn) {
|
|
893
|
+
display: block;
|
|
894
|
+
margin: 0 12px;
|
|
895
|
+
padding: 0.64rem 0.8rem;
|
|
896
|
+
border-radius: 3px;
|
|
897
|
+
font-size: 1rem;
|
|
898
|
+
line-height: 1;
|
|
899
|
+
user-select: none;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
:where(.kks-pagination__num-btn) {
|
|
903
|
+
text-decoration: none;
|
|
904
|
+
color: #666;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
:where(.kks-pagination__num-btn)::after {
|
|
908
|
+
content: attr(data-total-pages);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
:where(.kks-pagination__arrow-btn--prev) {
|
|
912
|
+
margin-left: 0;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
:where(.kks-pagination__arrow-btn--next) {
|
|
916
|
+
margin-right: 0;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
:where(.kks-pagination__arrow-btn--hidden) {
|
|
920
|
+
display: none;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
:where(.kks-pagination__icon) {
|
|
924
|
+
display: block;
|
|
925
|
+
width: 1rem;
|
|
926
|
+
height: 1rem;
|
|
927
|
+
background-size: contain;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
:where(.kks-pagination__icon-prev) {
|
|
931
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath fill='%23666' d='M88.6 121.3a4.1 4.1 0 0 1-5.8 0L28.9 67.4a4.1 4.1 0 0 1 0-5.8L82.8 7.7a4.1 4.1 0 0 1 5.8 5.8l-51 51 51 51a4.1 4.1 0 0 1 0 5.8z'/%3E%3C/svg%3E");
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
:where(.kks-pagination__icon-next) {
|
|
935
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath fill='%23666' d='M40.4 121.3a4.1 4.1 0 0 1 0-5.8l51-51-51-51a4.1 4.1 0 0 1 5.8-5.8l53.9 53.9a4.1 4.1 0 0 1 0 5.8l-53.9 53.9a4.1 4.1 0 0 1-5.8 0z'/%3E%3C/svg%3E");
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
:where(.kks-pagination__dots) {
|
|
939
|
+
display: block;
|
|
940
|
+
margin: 0 12px;
|
|
941
|
+
padding: 0.64rem 0;
|
|
942
|
+
font-size: 1rem;
|
|
943
|
+
line-height: 50%;
|
|
944
|
+
color: #aaa;
|
|
945
|
+
user-select: none;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
@media (min-width: 768px) {
|
|
949
|
+
:where(.kks-pagination__num-item:not(.kks-pagination__num-item--current)) {
|
|
950
|
+
display: block;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
:where(.kks-pagination__btn),
|
|
954
|
+
:where(.kks-pagination__dots) {
|
|
955
|
+
margin: 0 6px;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
:where(.kks-pagination__num-btn)::after {
|
|
959
|
+
content: "";
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
:where(.kks-pagination__num-btn:hover:not(.kks-pagination__num-btn--active)),
|
|
963
|
+
:where(.kks-pagination__arrow-btn:hover) {
|
|
964
|
+
background: rgba(0, 161, 179, 0.1);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
:where(.kks-pagination__num-btn--active) {
|
|
968
|
+
font-weight: 500;
|
|
969
|
+
color: #fff;
|
|
970
|
+
background: #00a1b3;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
`;
|
|
974
|
+
|
|
975
|
+
//#endregion
|
|
976
|
+
//#region src/Pagination/index.tsx
|
|
977
|
+
const DEFAULT_CURRENT_PAGE = 1;
|
|
978
|
+
const DEFAULT_PAGE_NEIGHBOURS = 2;
|
|
979
|
+
const ROUTE_URL_REPLACE_STRING = "$(pageNumber)";
|
|
980
|
+
const range = (start, end) => Array.from({ length: end - start + 1 }, (_, index) => start + index);
|
|
981
|
+
const getPageNumbers = (currentPage, pageNeighbours, totalPages) => {
|
|
982
|
+
const numberBlocks = pageNeighbours * 2 + 3;
|
|
983
|
+
if (totalPages <= numberBlocks + 2) return range(1, totalPages);
|
|
984
|
+
const startPage = Math.max(2, currentPage - pageNeighbours);
|
|
985
|
+
const endPage = Math.min(totalPages - 1, currentPage + pageNeighbours);
|
|
986
|
+
let pages = range(startPage, endPage);
|
|
987
|
+
const hasLeftDots = startPage > 2;
|
|
988
|
+
const hasRightDots = totalPages - endPage > 1;
|
|
989
|
+
const offset = numberBlocks - (pages.length + 2);
|
|
990
|
+
if (hasLeftDots && !hasRightDots) pages = [
|
|
991
|
+
"...",
|
|
992
|
+
...range(startPage - offset, startPage - 1),
|
|
993
|
+
...pages
|
|
994
|
+
];
|
|
995
|
+
else if (!hasLeftDots && hasRightDots) pages = [
|
|
996
|
+
...pages,
|
|
997
|
+
...range(endPage + 1, endPage + offset),
|
|
998
|
+
"..."
|
|
999
|
+
];
|
|
1000
|
+
else pages = [
|
|
1001
|
+
"...",
|
|
1002
|
+
...pages,
|
|
1003
|
+
"..."
|
|
1004
|
+
];
|
|
1005
|
+
return [
|
|
1006
|
+
1,
|
|
1007
|
+
...pages,
|
|
1008
|
+
totalPages
|
|
1009
|
+
];
|
|
1010
|
+
};
|
|
1011
|
+
const toPositiveInt = (value, fallback) => {
|
|
1012
|
+
const parsed = Number(value);
|
|
1013
|
+
return parsed > 0 ? parsed : fallback;
|
|
1014
|
+
};
|
|
1015
|
+
const toValidPage = (value, totalPages) => {
|
|
1016
|
+
const page = Number(value);
|
|
1017
|
+
return Number.isNaN(page) || page < 1 || page > totalPages ? DEFAULT_CURRENT_PAGE : page;
|
|
1018
|
+
};
|
|
1019
|
+
const normalizePaginationParams = ({ totalCount: rawTotalCount, perPageCount: rawPerPageCount, currentPage: rawCurrentPage = DEFAULT_CURRENT_PAGE, pageNeighbours: rawPageNeighbours = DEFAULT_PAGE_NEIGHBOURS }) => {
|
|
1020
|
+
const totalCount = Number(rawTotalCount);
|
|
1021
|
+
const perPageCount = Number(rawPerPageCount);
|
|
1022
|
+
const totalPages = totalCount && perPageCount ? Math.ceil(totalCount / perPageCount) : 1;
|
|
1023
|
+
return {
|
|
1024
|
+
totalCount,
|
|
1025
|
+
perPageCount,
|
|
1026
|
+
totalPages,
|
|
1027
|
+
currentPage: toValidPage(rawCurrentPage, totalPages),
|
|
1028
|
+
pageNeighbours: toPositiveInt(rawPageNeighbours, DEFAULT_PAGE_NEIGHBOURS)
|
|
1029
|
+
};
|
|
1030
|
+
};
|
|
1031
|
+
const renderEllipsis = (ellipsis, index) => /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsx)("li", {
|
|
1032
|
+
className: "kks-pagination__num-item",
|
|
1033
|
+
children: /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsx)(DotsButton_default, { dots: ellipsis })
|
|
1034
|
+
}, `dots-${index}`);
|
|
1035
|
+
const Pagination = (props) => {
|
|
1036
|
+
const { totalCount, perPageCount, totalPages, currentPage, pageNeighbours } = normalizePaginationParams(props);
|
|
1037
|
+
const { route = null, routeParams = null, routeOptions = null, nextRouter = null, nextLink = null, className = "", onPageChange = () => {} } = props;
|
|
1038
|
+
if (totalPages === 1) return null;
|
|
1039
|
+
const getRouteData = (page) => {
|
|
1040
|
+
if (!route) return { route: "#" };
|
|
1041
|
+
const nextRouteParams = routeParams ? Object.fromEntries(Object.entries(routeParams).map(([key, value]) => [key, value === ROUTE_URL_REPLACE_STRING ? page : value])) : null;
|
|
1042
|
+
if (nextRouteParams && !Object.values(routeParams).includes(ROUTE_URL_REPLACE_STRING)) nextRouteParams.page = page;
|
|
1043
|
+
return {
|
|
1044
|
+
route: route.replace(ROUTE_URL_REPLACE_STRING, String(page)),
|
|
1045
|
+
routeParams: nextRouteParams,
|
|
1046
|
+
routeOptions
|
|
1047
|
+
};
|
|
1048
|
+
};
|
|
1049
|
+
const handleClick = (page, routeData) => (event) => {
|
|
1050
|
+
event.preventDefault();
|
|
1051
|
+
const isNavigable = routeData.route !== "#";
|
|
1052
|
+
onPageChange({
|
|
1053
|
+
currentPage: page,
|
|
1054
|
+
totalPages,
|
|
1055
|
+
totalCount,
|
|
1056
|
+
perPageCount,
|
|
1057
|
+
route: isNavigable ? routeData.route : null,
|
|
1058
|
+
...isNavigable ? routeData : {}
|
|
1059
|
+
});
|
|
1060
|
+
if (nextRouter && isNavigable) nextRouter.pushRoute(routeData.route, routeData.routeParams || {}, routeData.routeOptions || {});
|
|
1061
|
+
};
|
|
1062
|
+
const previousPage = currentPage === 1 ? 1 : currentPage - 1;
|
|
1063
|
+
const nextPage = currentPage === totalPages ? totalPages : currentPage + 1;
|
|
1064
|
+
const renderArrow = (type, page, disabled) => {
|
|
1065
|
+
const routeData = getRouteData(page);
|
|
1066
|
+
return /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsx)(ArrowButton_default, {
|
|
1067
|
+
type,
|
|
1068
|
+
routeData,
|
|
1069
|
+
nextLink,
|
|
1070
|
+
disabled,
|
|
1071
|
+
onClick: handleClick(page, routeData)
|
|
1072
|
+
});
|
|
1073
|
+
};
|
|
1074
|
+
const renderPageNumber = (page) => {
|
|
1075
|
+
const routeData = getRouteData(page);
|
|
1076
|
+
const isCurrentPage = page === currentPage;
|
|
1077
|
+
return /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsx)("li", {
|
|
1078
|
+
className: `kks-pagination__num-item${isCurrentPage ? " kks-pagination__num-item--current" : ""}`,
|
|
1079
|
+
children: /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsx)(NumberButton_default, {
|
|
1080
|
+
totalPages,
|
|
1081
|
+
pageNumber: page,
|
|
1082
|
+
routeData,
|
|
1083
|
+
nextLink,
|
|
1084
|
+
active: isCurrentPage,
|
|
1085
|
+
onClick: handleClick(page, routeData)
|
|
1086
|
+
})
|
|
1087
|
+
}, `page-${page}`);
|
|
1088
|
+
};
|
|
1089
|
+
return /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsx)("nav", {
|
|
1090
|
+
css: paginationStyle,
|
|
1091
|
+
className: `kks-pagination ${className}`,
|
|
1092
|
+
"aria-label": "Page navigation",
|
|
1093
|
+
children: /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsxs)("ul", {
|
|
1094
|
+
className: "kks-pagination__content",
|
|
1095
|
+
children: [
|
|
1096
|
+
/* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsx)("li", { children: renderArrow("prev", previousPage, currentPage === 1) }),
|
|
1097
|
+
getPageNumbers(currentPage, pageNeighbours, totalPages).map((page, index) => typeof page === "number" ? renderPageNumber(page) : renderEllipsis(page, index)),
|
|
1098
|
+
/* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsx)("li", { children: renderArrow("next", nextPage, currentPage === totalPages) })
|
|
1099
|
+
]
|
|
1100
|
+
})
|
|
1101
|
+
});
|
|
1102
|
+
};
|
|
1103
|
+
var Pagination_default = Pagination;
|
|
1104
|
+
|
|
715
1105
|
//#endregion
|
|
716
1106
|
//#region src/icons/see-more.svg
|
|
717
1107
|
var see_more_default = "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNCIgaGVpZ2h0PSI4IiBmaWxsPSJub25lIiB2aWV3Qm94PSIwIDAgMTQgOCI+CiAgPHBhdGggc3Ryb2tlPSIjY2NjIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNLjc1Ljc1IDYuNyA2LjY4cS4wNy4wNi4xNCAwbTAgMHEwIDAgMCAwWm0wIDBMMTIuNzUuNzUiLz4KPC9zdmc+";
|
|
@@ -808,17 +1198,19 @@ const SeeMore = ({ style, messages = defaultMessages, children, ...rest }) => {
|
|
|
808
1198
|
const [expandedHeight, setExpandedHeight] = (0, react.useState)();
|
|
809
1199
|
const rootRef = (0, react.useRef)(null);
|
|
810
1200
|
const containeRef = (0, react.useRef)();
|
|
811
|
-
(0, react.
|
|
1201
|
+
(0, react.useLayoutEffect)(() => {
|
|
812
1202
|
if (!rootRef.current) return;
|
|
813
|
-
|
|
1203
|
+
const updateExpandStatus = () => {
|
|
814
1204
|
if (!containeRef.current) return;
|
|
815
1205
|
const collapsedLines = Number.parseInt(window.getComputedStyle(containeRef.current).getPropertyValue("--see-more-collapsed-lines"), 10) || 2;
|
|
816
1206
|
const lineCount = getLineCount(containeRef.current);
|
|
817
1207
|
const scrollable = lineCount > collapsedLines;
|
|
818
1208
|
const fit = lineCount <= collapsedLines;
|
|
819
1209
|
setStatus((current) => current === "no-expand" && scrollable ? "collapsed" : current !== "no-expand" && fit ? "no-expand" : current);
|
|
820
|
-
setExpandedHeight(containeRef.current
|
|
821
|
-
}
|
|
1210
|
+
setExpandedHeight(containeRef.current.scrollHeight);
|
|
1211
|
+
};
|
|
1212
|
+
updateExpandStatus();
|
|
1213
|
+
return onResize(rootRef.current, updateExpandStatus);
|
|
822
1214
|
}, []);
|
|
823
1215
|
const toggle = () => setStatus((current) => current === "collapsed" ? "expanded" : "collapsing");
|
|
824
1216
|
return /* @__PURE__ */ (0, __emotion_react_jsx_runtime.jsxs)("div", {
|
|
@@ -1081,6 +1473,8 @@ exports.Banner = Banner_default;
|
|
|
1081
1473
|
exports.Dropdown = Dropdown_default;
|
|
1082
1474
|
exports.HiddenToggle = HiddenToggle_default;
|
|
1083
1475
|
exports.Icon = Icon_default;
|
|
1476
|
+
exports.Modal = Modal_default;
|
|
1477
|
+
exports.Pagination = Pagination_default;
|
|
1084
1478
|
exports.SeeMore = SeeMore_default;
|
|
1085
1479
|
exports.VideoItem = VideoItem_default;
|
|
1086
1480
|
exports.VideoThumbnail = VideoThumbnail_default;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react0 from "react";
|
|
2
|
-
import { ElementType, MouseEventHandler, ReactElement, ReactNode } from "react";
|
|
2
|
+
import { ComponentType, ElementType, MouseEventHandler, ReactElement, ReactNode } from "react";
|
|
3
3
|
import * as _emotion_react_jsx_runtime0 from "@emotion/react/jsx-runtime";
|
|
4
4
|
import { CSSObject } from "@emotion/react";
|
|
5
5
|
import Link from "next/link";
|
|
@@ -76,6 +76,54 @@ declare const Icon: ({
|
|
|
76
76
|
src: any;
|
|
77
77
|
}) => _emotion_react_jsx_runtime0.JSX.Element;
|
|
78
78
|
//#endregion
|
|
79
|
+
//#region src/Modal/index.d.ts
|
|
80
|
+
type ModalProps = {
|
|
81
|
+
children: ReactNode;
|
|
82
|
+
className?: string;
|
|
83
|
+
isHideModalOnClickOverlay?: boolean;
|
|
84
|
+
isShow: boolean;
|
|
85
|
+
onHidden?: () => void;
|
|
86
|
+
onShown?: () => void;
|
|
87
|
+
onTriggerHiding?: () => void;
|
|
88
|
+
};
|
|
89
|
+
declare const Modal: react0.MemoExoticComponent<react0.ForwardRefExoticComponent<ModalProps & react0.RefAttributes<HTMLDivElement>>>;
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/Pagination/types.d.ts
|
|
92
|
+
type RouteParams = Record<string, unknown>;
|
|
93
|
+
type RouteOptions = Record<string, unknown>;
|
|
94
|
+
type NextLinkProps = {
|
|
95
|
+
route: string;
|
|
96
|
+
params?: RouteParams | null;
|
|
97
|
+
children: ReactNode;
|
|
98
|
+
} & RouteOptions;
|
|
99
|
+
type NextLink = ComponentType<NextLinkProps>;
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/Pagination/index.d.ts
|
|
102
|
+
type PaginationProps = {
|
|
103
|
+
totalCount: number | string;
|
|
104
|
+
perPageCount: number | string;
|
|
105
|
+
currentPage?: number | string;
|
|
106
|
+
pageNeighbours?: number | string;
|
|
107
|
+
route?: string | null;
|
|
108
|
+
routeParams?: RouteParams | null;
|
|
109
|
+
routeOptions?: RouteOptions | null;
|
|
110
|
+
nextRouter?: {
|
|
111
|
+
pushRoute: (route: string, routeParams?: RouteParams, routeOptions?: RouteOptions) => void;
|
|
112
|
+
} | null;
|
|
113
|
+
nextLink?: NextLink | null;
|
|
114
|
+
className?: string;
|
|
115
|
+
onPageChange?: (page: {
|
|
116
|
+
currentPage: number;
|
|
117
|
+
totalPages: number;
|
|
118
|
+
totalCount: number;
|
|
119
|
+
perPageCount: number;
|
|
120
|
+
route: string | null;
|
|
121
|
+
routeParams?: RouteParams | null;
|
|
122
|
+
routeOptions?: RouteOptions | null;
|
|
123
|
+
}) => void;
|
|
124
|
+
};
|
|
125
|
+
declare const Pagination: (props: PaginationProps) => ReactElement | null;
|
|
126
|
+
//#endregion
|
|
79
127
|
//#region src/SeeMore.d.ts
|
|
80
128
|
declare const defaultMessages: {
|
|
81
129
|
seeMore: string;
|
|
@@ -156,4 +204,4 @@ declare const VideoThumbnail: ({
|
|
|
156
204
|
onClick?: MouseEventHandler<HTMLAnchorElement>;
|
|
157
205
|
}) => _emotion_react_jsx_runtime0.JSX.Element;
|
|
158
206
|
//#endregion
|
|
159
|
-
export { Banner, Dropdown, HiddenToggle, Icon, SeeMore, VideoItem, VideoThumbnail };
|
|
207
|
+
export { Banner, Dropdown, HiddenToggle, Icon, Modal, Pagination, SeeMore, VideoItem, VideoThumbnail };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react0 from "react";
|
|
2
|
-
import { ElementType, MouseEventHandler, ReactElement, ReactNode } from "react";
|
|
2
|
+
import { ComponentType, ElementType, MouseEventHandler, ReactElement, ReactNode } from "react";
|
|
3
3
|
import * as _emotion_react_jsx_runtime0 from "@emotion/react/jsx-runtime";
|
|
4
4
|
import { CSSObject } from "@emotion/react";
|
|
5
5
|
import Link from "next/link";
|
|
@@ -76,6 +76,54 @@ declare const Icon: ({
|
|
|
76
76
|
src: any;
|
|
77
77
|
}) => _emotion_react_jsx_runtime0.JSX.Element;
|
|
78
78
|
//#endregion
|
|
79
|
+
//#region src/Modal/index.d.ts
|
|
80
|
+
type ModalProps = {
|
|
81
|
+
children: ReactNode;
|
|
82
|
+
className?: string;
|
|
83
|
+
isHideModalOnClickOverlay?: boolean;
|
|
84
|
+
isShow: boolean;
|
|
85
|
+
onHidden?: () => void;
|
|
86
|
+
onShown?: () => void;
|
|
87
|
+
onTriggerHiding?: () => void;
|
|
88
|
+
};
|
|
89
|
+
declare const Modal: react0.MemoExoticComponent<react0.ForwardRefExoticComponent<ModalProps & react0.RefAttributes<HTMLDivElement>>>;
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/Pagination/types.d.ts
|
|
92
|
+
type RouteParams = Record<string, unknown>;
|
|
93
|
+
type RouteOptions = Record<string, unknown>;
|
|
94
|
+
type NextLinkProps = {
|
|
95
|
+
route: string;
|
|
96
|
+
params?: RouteParams | null;
|
|
97
|
+
children: ReactNode;
|
|
98
|
+
} & RouteOptions;
|
|
99
|
+
type NextLink = ComponentType<NextLinkProps>;
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/Pagination/index.d.ts
|
|
102
|
+
type PaginationProps = {
|
|
103
|
+
totalCount: number | string;
|
|
104
|
+
perPageCount: number | string;
|
|
105
|
+
currentPage?: number | string;
|
|
106
|
+
pageNeighbours?: number | string;
|
|
107
|
+
route?: string | null;
|
|
108
|
+
routeParams?: RouteParams | null;
|
|
109
|
+
routeOptions?: RouteOptions | null;
|
|
110
|
+
nextRouter?: {
|
|
111
|
+
pushRoute: (route: string, routeParams?: RouteParams, routeOptions?: RouteOptions) => void;
|
|
112
|
+
} | null;
|
|
113
|
+
nextLink?: NextLink | null;
|
|
114
|
+
className?: string;
|
|
115
|
+
onPageChange?: (page: {
|
|
116
|
+
currentPage: number;
|
|
117
|
+
totalPages: number;
|
|
118
|
+
totalCount: number;
|
|
119
|
+
perPageCount: number;
|
|
120
|
+
route: string | null;
|
|
121
|
+
routeParams?: RouteParams | null;
|
|
122
|
+
routeOptions?: RouteOptions | null;
|
|
123
|
+
}) => void;
|
|
124
|
+
};
|
|
125
|
+
declare const Pagination: (props: PaginationProps) => ReactElement | null;
|
|
126
|
+
//#endregion
|
|
79
127
|
//#region src/SeeMore.d.ts
|
|
80
128
|
declare const defaultMessages: {
|
|
81
129
|
seeMore: string;
|
|
@@ -156,4 +204,4 @@ declare const VideoThumbnail: ({
|
|
|
156
204
|
onClick?: MouseEventHandler<HTMLAnchorElement>;
|
|
157
205
|
}) => _emotion_react_jsx_runtime0.JSX.Element;
|
|
158
206
|
//#endregion
|
|
159
|
-
export { Banner, Dropdown, HiddenToggle, Icon, SeeMore, VideoItem, VideoThumbnail };
|
|
207
|
+
export { Banner, Dropdown, HiddenToggle, Icon, Modal, Pagination, SeeMore, VideoItem, VideoThumbnail };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Children, forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useReducer, useRef, useState } from "react";
|
|
1
|
+
import { Children, forwardRef, memo, useCallback, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import { jsx as jsx$1, jsxs } from "@emotion/react/jsx-runtime";
|
|
4
4
|
import { css } from "@emotion/react";
|
|
@@ -712,6 +712,396 @@ const Icon = ({ style = {}, src }) => /* @__PURE__ */ jsx$1("span", { css: [
|
|
|
712
712
|
] });
|
|
713
713
|
var Icon_default = Icon;
|
|
714
714
|
|
|
715
|
+
//#endregion
|
|
716
|
+
//#region src/Modal/styles.ts
|
|
717
|
+
const modalStyle = css`
|
|
718
|
+
:where(&) {
|
|
719
|
+
position: fixed;
|
|
720
|
+
top: 0;
|
|
721
|
+
right: 0;
|
|
722
|
+
bottom: 0;
|
|
723
|
+
left: 0;
|
|
724
|
+
z-index: 1000;
|
|
725
|
+
padding: 1rem;
|
|
726
|
+
overflow-x: hidden;
|
|
727
|
+
overflow-y: auto;
|
|
728
|
+
visibility: hidden;
|
|
729
|
+
opacity: 0;
|
|
730
|
+
background-color: rgba(0, 0, 0, 0.7);
|
|
731
|
+
transition: opacity 0.3s;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
:where(&.modal--show),
|
|
735
|
+
:where(&.modal--shown) {
|
|
736
|
+
display: flex;
|
|
737
|
+
justify-content: center;
|
|
738
|
+
visibility: visible;
|
|
739
|
+
opacity: 1;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
:where(.modal__content) {
|
|
743
|
+
width: 100%;
|
|
744
|
+
max-width: 700px;
|
|
745
|
+
margin: auto 0;
|
|
746
|
+
}
|
|
747
|
+
`;
|
|
748
|
+
|
|
749
|
+
//#endregion
|
|
750
|
+
//#region src/Modal/index.tsx
|
|
751
|
+
const MODAL_STATE = {
|
|
752
|
+
SHOW: "show",
|
|
753
|
+
SHOWN: "shown",
|
|
754
|
+
HIDE: "hide",
|
|
755
|
+
HIDDEN: "hidden"
|
|
756
|
+
};
|
|
757
|
+
const isShowing = (state) => state === MODAL_STATE.SHOW || state === MODAL_STATE.SHOWN;
|
|
758
|
+
const Modal = memo(forwardRef(function Modal$1({ children, className = "", isHideModalOnClickOverlay = true, isShow, onHidden = () => {}, onShown = () => {}, onTriggerHiding = () => {} }, ref) {
|
|
759
|
+
const [visualState, setVisualState] = useState(MODAL_STATE.HIDDEN);
|
|
760
|
+
const shouldLockBody = isShowing(visualState);
|
|
761
|
+
if (isShow && !isShowing(visualState)) setVisualState(MODAL_STATE.SHOW);
|
|
762
|
+
else if (!isShow && isShowing(visualState)) setVisualState(MODAL_STATE.HIDE);
|
|
763
|
+
useLayoutEffect(() => {
|
|
764
|
+
if (!shouldLockBody) return;
|
|
765
|
+
const previousOverflow = document.body.style.overflow;
|
|
766
|
+
document.body.style.overflow = "hidden";
|
|
767
|
+
return () => {
|
|
768
|
+
document.body.style.overflow = previousOverflow;
|
|
769
|
+
};
|
|
770
|
+
}, [shouldLockBody]);
|
|
771
|
+
const previousVisualState = useRef(visualState);
|
|
772
|
+
useLayoutEffect(() => {
|
|
773
|
+
if (previousVisualState.current === visualState) return;
|
|
774
|
+
previousVisualState.current = visualState;
|
|
775
|
+
if (visualState === MODAL_STATE.SHOWN) onShown();
|
|
776
|
+
else if (visualState === MODAL_STATE.HIDDEN) onHidden();
|
|
777
|
+
}, [
|
|
778
|
+
visualState,
|
|
779
|
+
onShown,
|
|
780
|
+
onHidden
|
|
781
|
+
]);
|
|
782
|
+
const handleAnimationEnd = useCallback(() => {
|
|
783
|
+
setVisualState((previousState) => {
|
|
784
|
+
if (previousState === MODAL_STATE.SHOW) return MODAL_STATE.SHOWN;
|
|
785
|
+
if (previousState === MODAL_STATE.HIDE) return MODAL_STATE.HIDDEN;
|
|
786
|
+
return previousState;
|
|
787
|
+
});
|
|
788
|
+
}, []);
|
|
789
|
+
const handleClick = useCallback((event) => {
|
|
790
|
+
if (event.target.getAttribute("data-dismiss") === "modal") onTriggerHiding();
|
|
791
|
+
}, [onTriggerHiding]);
|
|
792
|
+
const handleKeyDown = useCallback((event) => {
|
|
793
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
794
|
+
if (event.target.getAttribute("data-dismiss") !== "modal") return;
|
|
795
|
+
event.preventDefault();
|
|
796
|
+
onTriggerHiding();
|
|
797
|
+
}, [onTriggerHiding]);
|
|
798
|
+
return /* @__PURE__ */ jsx$1("div", {
|
|
799
|
+
css: modalStyle,
|
|
800
|
+
ref,
|
|
801
|
+
role: "presentation",
|
|
802
|
+
className: `modal modal--${visualState} ${className}`,
|
|
803
|
+
onClick: handleClick,
|
|
804
|
+
onKeyDown: handleKeyDown,
|
|
805
|
+
onAnimationEnd: handleAnimationEnd,
|
|
806
|
+
onTransitionEnd: handleAnimationEnd,
|
|
807
|
+
"data-dismiss": isHideModalOnClickOverlay ? "modal" : void 0,
|
|
808
|
+
children: /* @__PURE__ */ jsx$1("div", {
|
|
809
|
+
className: "modal__content",
|
|
810
|
+
children
|
|
811
|
+
})
|
|
812
|
+
});
|
|
813
|
+
}));
|
|
814
|
+
var Modal_default = Modal;
|
|
815
|
+
|
|
816
|
+
//#endregion
|
|
817
|
+
//#region src/Pagination/PaginationLink.tsx
|
|
818
|
+
const PaginationLink = ({ routeData, nextLink: NextLinkComponent, children, ...anchorProps }) => {
|
|
819
|
+
const anchor = /* @__PURE__ */ jsx("a", {
|
|
820
|
+
...anchorProps,
|
|
821
|
+
href: NextLinkComponent ? void 0 : routeData.route,
|
|
822
|
+
children
|
|
823
|
+
});
|
|
824
|
+
if (!NextLinkComponent) return anchor;
|
|
825
|
+
return /* @__PURE__ */ jsx(NextLinkComponent, {
|
|
826
|
+
route: routeData.route,
|
|
827
|
+
params: routeData.routeParams,
|
|
828
|
+
...routeData.routeOptions || {},
|
|
829
|
+
children: anchor
|
|
830
|
+
});
|
|
831
|
+
};
|
|
832
|
+
var PaginationLink_default = PaginationLink;
|
|
833
|
+
|
|
834
|
+
//#endregion
|
|
835
|
+
//#region src/Pagination/ArrowButton.tsx
|
|
836
|
+
const ArrowButton = ({ type, routeData, nextLink, disabled = false, onClick }) => /* @__PURE__ */ jsx(PaginationLink_default, {
|
|
837
|
+
className: `kks-pagination__btn kks-pagination__arrow-btn kks-pagination__arrow-btn--${type}${disabled ? " kks-pagination__arrow-btn--hidden" : ""}`,
|
|
838
|
+
routeData,
|
|
839
|
+
nextLink,
|
|
840
|
+
rel: type,
|
|
841
|
+
"aria-label": type === "prev" ? "Previous page" : "Next page",
|
|
842
|
+
onClick,
|
|
843
|
+
children: /* @__PURE__ */ jsx("span", { className: `kks-pagination__icon kks-pagination__icon-${type}` })
|
|
844
|
+
});
|
|
845
|
+
var ArrowButton_default = ArrowButton;
|
|
846
|
+
|
|
847
|
+
//#endregion
|
|
848
|
+
//#region src/Pagination/DotsButton.tsx
|
|
849
|
+
const DotsButton = ({ dots }) => /* @__PURE__ */ jsx("span", {
|
|
850
|
+
className: "kks-pagination__dots",
|
|
851
|
+
children: dots
|
|
852
|
+
});
|
|
853
|
+
var DotsButton_default = DotsButton;
|
|
854
|
+
|
|
855
|
+
//#endregion
|
|
856
|
+
//#region src/Pagination/NumberButton.tsx
|
|
857
|
+
const NumberButton = ({ totalPages, pageNumber, routeData, nextLink, active = false, onClick }) => {
|
|
858
|
+
if (active) return /* @__PURE__ */ jsx("span", {
|
|
859
|
+
className: "kks-pagination__btn kks-pagination__num-btn kks-pagination__num-btn--active",
|
|
860
|
+
"data-total-pages": ` / ${totalPages}`,
|
|
861
|
+
"aria-current": "page",
|
|
862
|
+
children: pageNumber
|
|
863
|
+
});
|
|
864
|
+
return /* @__PURE__ */ jsx(PaginationLink_default, {
|
|
865
|
+
className: "kks-pagination__btn kks-pagination__num-btn",
|
|
866
|
+
routeData,
|
|
867
|
+
nextLink,
|
|
868
|
+
onClick,
|
|
869
|
+
children: pageNumber
|
|
870
|
+
});
|
|
871
|
+
};
|
|
872
|
+
var NumberButton_default = NumberButton;
|
|
873
|
+
|
|
874
|
+
//#endregion
|
|
875
|
+
//#region src/Pagination/styles.ts
|
|
876
|
+
const paginationStyle = css`
|
|
877
|
+
:where(&) {
|
|
878
|
+
display: inline-block;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
:where(.kks-pagination__content) {
|
|
882
|
+
display: flex;
|
|
883
|
+
margin: 0;
|
|
884
|
+
padding-left: 0;
|
|
885
|
+
list-style: none;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
:where(.kks-pagination__num-item:not(.kks-pagination__num-item--current)) {
|
|
889
|
+
display: none;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
:where(.kks-pagination__btn) {
|
|
893
|
+
display: block;
|
|
894
|
+
margin: 0 12px;
|
|
895
|
+
padding: 0.64rem 0.8rem;
|
|
896
|
+
border-radius: 3px;
|
|
897
|
+
font-size: 1rem;
|
|
898
|
+
line-height: 1;
|
|
899
|
+
user-select: none;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
:where(.kks-pagination__num-btn) {
|
|
903
|
+
text-decoration: none;
|
|
904
|
+
color: #666;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
:where(.kks-pagination__num-btn)::after {
|
|
908
|
+
content: attr(data-total-pages);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
:where(.kks-pagination__arrow-btn--prev) {
|
|
912
|
+
margin-left: 0;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
:where(.kks-pagination__arrow-btn--next) {
|
|
916
|
+
margin-right: 0;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
:where(.kks-pagination__arrow-btn--hidden) {
|
|
920
|
+
display: none;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
:where(.kks-pagination__icon) {
|
|
924
|
+
display: block;
|
|
925
|
+
width: 1rem;
|
|
926
|
+
height: 1rem;
|
|
927
|
+
background-size: contain;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
:where(.kks-pagination__icon-prev) {
|
|
931
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath fill='%23666' d='M88.6 121.3a4.1 4.1 0 0 1-5.8 0L28.9 67.4a4.1 4.1 0 0 1 0-5.8L82.8 7.7a4.1 4.1 0 0 1 5.8 5.8l-51 51 51 51a4.1 4.1 0 0 1 0 5.8z'/%3E%3C/svg%3E");
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
:where(.kks-pagination__icon-next) {
|
|
935
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 129 129'%3E%3Cpath fill='%23666' d='M40.4 121.3a4.1 4.1 0 0 1 0-5.8l51-51-51-51a4.1 4.1 0 0 1 5.8-5.8l53.9 53.9a4.1 4.1 0 0 1 0 5.8l-53.9 53.9a4.1 4.1 0 0 1-5.8 0z'/%3E%3C/svg%3E");
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
:where(.kks-pagination__dots) {
|
|
939
|
+
display: block;
|
|
940
|
+
margin: 0 12px;
|
|
941
|
+
padding: 0.64rem 0;
|
|
942
|
+
font-size: 1rem;
|
|
943
|
+
line-height: 50%;
|
|
944
|
+
color: #aaa;
|
|
945
|
+
user-select: none;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
@media (min-width: 768px) {
|
|
949
|
+
:where(.kks-pagination__num-item:not(.kks-pagination__num-item--current)) {
|
|
950
|
+
display: block;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
:where(.kks-pagination__btn),
|
|
954
|
+
:where(.kks-pagination__dots) {
|
|
955
|
+
margin: 0 6px;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
:where(.kks-pagination__num-btn)::after {
|
|
959
|
+
content: "";
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
:where(.kks-pagination__num-btn:hover:not(.kks-pagination__num-btn--active)),
|
|
963
|
+
:where(.kks-pagination__arrow-btn:hover) {
|
|
964
|
+
background: rgba(0, 161, 179, 0.1);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
:where(.kks-pagination__num-btn--active) {
|
|
968
|
+
font-weight: 500;
|
|
969
|
+
color: #fff;
|
|
970
|
+
background: #00a1b3;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
`;
|
|
974
|
+
|
|
975
|
+
//#endregion
|
|
976
|
+
//#region src/Pagination/index.tsx
|
|
977
|
+
const DEFAULT_CURRENT_PAGE = 1;
|
|
978
|
+
const DEFAULT_PAGE_NEIGHBOURS = 2;
|
|
979
|
+
const ROUTE_URL_REPLACE_STRING = "$(pageNumber)";
|
|
980
|
+
const range = (start, end) => Array.from({ length: end - start + 1 }, (_, index) => start + index);
|
|
981
|
+
const getPageNumbers = (currentPage, pageNeighbours, totalPages) => {
|
|
982
|
+
const numberBlocks = pageNeighbours * 2 + 3;
|
|
983
|
+
if (totalPages <= numberBlocks + 2) return range(1, totalPages);
|
|
984
|
+
const startPage = Math.max(2, currentPage - pageNeighbours);
|
|
985
|
+
const endPage = Math.min(totalPages - 1, currentPage + pageNeighbours);
|
|
986
|
+
let pages = range(startPage, endPage);
|
|
987
|
+
const hasLeftDots = startPage > 2;
|
|
988
|
+
const hasRightDots = totalPages - endPage > 1;
|
|
989
|
+
const offset = numberBlocks - (pages.length + 2);
|
|
990
|
+
if (hasLeftDots && !hasRightDots) pages = [
|
|
991
|
+
"...",
|
|
992
|
+
...range(startPage - offset, startPage - 1),
|
|
993
|
+
...pages
|
|
994
|
+
];
|
|
995
|
+
else if (!hasLeftDots && hasRightDots) pages = [
|
|
996
|
+
...pages,
|
|
997
|
+
...range(endPage + 1, endPage + offset),
|
|
998
|
+
"..."
|
|
999
|
+
];
|
|
1000
|
+
else pages = [
|
|
1001
|
+
"...",
|
|
1002
|
+
...pages,
|
|
1003
|
+
"..."
|
|
1004
|
+
];
|
|
1005
|
+
return [
|
|
1006
|
+
1,
|
|
1007
|
+
...pages,
|
|
1008
|
+
totalPages
|
|
1009
|
+
];
|
|
1010
|
+
};
|
|
1011
|
+
const toPositiveInt = (value, fallback) => {
|
|
1012
|
+
const parsed = Number(value);
|
|
1013
|
+
return parsed > 0 ? parsed : fallback;
|
|
1014
|
+
};
|
|
1015
|
+
const toValidPage = (value, totalPages) => {
|
|
1016
|
+
const page = Number(value);
|
|
1017
|
+
return Number.isNaN(page) || page < 1 || page > totalPages ? DEFAULT_CURRENT_PAGE : page;
|
|
1018
|
+
};
|
|
1019
|
+
const normalizePaginationParams = ({ totalCount: rawTotalCount, perPageCount: rawPerPageCount, currentPage: rawCurrentPage = DEFAULT_CURRENT_PAGE, pageNeighbours: rawPageNeighbours = DEFAULT_PAGE_NEIGHBOURS }) => {
|
|
1020
|
+
const totalCount = Number(rawTotalCount);
|
|
1021
|
+
const perPageCount = Number(rawPerPageCount);
|
|
1022
|
+
const totalPages = totalCount && perPageCount ? Math.ceil(totalCount / perPageCount) : 1;
|
|
1023
|
+
return {
|
|
1024
|
+
totalCount,
|
|
1025
|
+
perPageCount,
|
|
1026
|
+
totalPages,
|
|
1027
|
+
currentPage: toValidPage(rawCurrentPage, totalPages),
|
|
1028
|
+
pageNeighbours: toPositiveInt(rawPageNeighbours, DEFAULT_PAGE_NEIGHBOURS)
|
|
1029
|
+
};
|
|
1030
|
+
};
|
|
1031
|
+
const renderEllipsis = (ellipsis, index) => /* @__PURE__ */ jsx$1("li", {
|
|
1032
|
+
className: "kks-pagination__num-item",
|
|
1033
|
+
children: /* @__PURE__ */ jsx$1(DotsButton_default, { dots: ellipsis })
|
|
1034
|
+
}, `dots-${index}`);
|
|
1035
|
+
const Pagination = (props) => {
|
|
1036
|
+
const { totalCount, perPageCount, totalPages, currentPage, pageNeighbours } = normalizePaginationParams(props);
|
|
1037
|
+
const { route = null, routeParams = null, routeOptions = null, nextRouter = null, nextLink = null, className = "", onPageChange = () => {} } = props;
|
|
1038
|
+
if (totalPages === 1) return null;
|
|
1039
|
+
const getRouteData = (page) => {
|
|
1040
|
+
if (!route) return { route: "#" };
|
|
1041
|
+
const nextRouteParams = routeParams ? Object.fromEntries(Object.entries(routeParams).map(([key, value]) => [key, value === ROUTE_URL_REPLACE_STRING ? page : value])) : null;
|
|
1042
|
+
if (nextRouteParams && !Object.values(routeParams).includes(ROUTE_URL_REPLACE_STRING)) nextRouteParams.page = page;
|
|
1043
|
+
return {
|
|
1044
|
+
route: route.replace(ROUTE_URL_REPLACE_STRING, String(page)),
|
|
1045
|
+
routeParams: nextRouteParams,
|
|
1046
|
+
routeOptions
|
|
1047
|
+
};
|
|
1048
|
+
};
|
|
1049
|
+
const handleClick = (page, routeData) => (event) => {
|
|
1050
|
+
event.preventDefault();
|
|
1051
|
+
const isNavigable = routeData.route !== "#";
|
|
1052
|
+
onPageChange({
|
|
1053
|
+
currentPage: page,
|
|
1054
|
+
totalPages,
|
|
1055
|
+
totalCount,
|
|
1056
|
+
perPageCount,
|
|
1057
|
+
route: isNavigable ? routeData.route : null,
|
|
1058
|
+
...isNavigable ? routeData : {}
|
|
1059
|
+
});
|
|
1060
|
+
if (nextRouter && isNavigable) nextRouter.pushRoute(routeData.route, routeData.routeParams || {}, routeData.routeOptions || {});
|
|
1061
|
+
};
|
|
1062
|
+
const previousPage = currentPage === 1 ? 1 : currentPage - 1;
|
|
1063
|
+
const nextPage = currentPage === totalPages ? totalPages : currentPage + 1;
|
|
1064
|
+
const renderArrow = (type, page, disabled) => {
|
|
1065
|
+
const routeData = getRouteData(page);
|
|
1066
|
+
return /* @__PURE__ */ jsx$1(ArrowButton_default, {
|
|
1067
|
+
type,
|
|
1068
|
+
routeData,
|
|
1069
|
+
nextLink,
|
|
1070
|
+
disabled,
|
|
1071
|
+
onClick: handleClick(page, routeData)
|
|
1072
|
+
});
|
|
1073
|
+
};
|
|
1074
|
+
const renderPageNumber = (page) => {
|
|
1075
|
+
const routeData = getRouteData(page);
|
|
1076
|
+
const isCurrentPage = page === currentPage;
|
|
1077
|
+
return /* @__PURE__ */ jsx$1("li", {
|
|
1078
|
+
className: `kks-pagination__num-item${isCurrentPage ? " kks-pagination__num-item--current" : ""}`,
|
|
1079
|
+
children: /* @__PURE__ */ jsx$1(NumberButton_default, {
|
|
1080
|
+
totalPages,
|
|
1081
|
+
pageNumber: page,
|
|
1082
|
+
routeData,
|
|
1083
|
+
nextLink,
|
|
1084
|
+
active: isCurrentPage,
|
|
1085
|
+
onClick: handleClick(page, routeData)
|
|
1086
|
+
})
|
|
1087
|
+
}, `page-${page}`);
|
|
1088
|
+
};
|
|
1089
|
+
return /* @__PURE__ */ jsx$1("nav", {
|
|
1090
|
+
css: paginationStyle,
|
|
1091
|
+
className: `kks-pagination ${className}`,
|
|
1092
|
+
"aria-label": "Page navigation",
|
|
1093
|
+
children: /* @__PURE__ */ jsxs("ul", {
|
|
1094
|
+
className: "kks-pagination__content",
|
|
1095
|
+
children: [
|
|
1096
|
+
/* @__PURE__ */ jsx$1("li", { children: renderArrow("prev", previousPage, currentPage === 1) }),
|
|
1097
|
+
getPageNumbers(currentPage, pageNeighbours, totalPages).map((page, index) => typeof page === "number" ? renderPageNumber(page) : renderEllipsis(page, index)),
|
|
1098
|
+
/* @__PURE__ */ jsx$1("li", { children: renderArrow("next", nextPage, currentPage === totalPages) })
|
|
1099
|
+
]
|
|
1100
|
+
})
|
|
1101
|
+
});
|
|
1102
|
+
};
|
|
1103
|
+
var Pagination_default = Pagination;
|
|
1104
|
+
|
|
715
1105
|
//#endregion
|
|
716
1106
|
//#region src/icons/see-more.svg
|
|
717
1107
|
var see_more_default = "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNCIgaGVpZ2h0PSI4IiBmaWxsPSJub25lIiB2aWV3Qm94PSIwIDAgMTQgOCI+CiAgPHBhdGggc3Ryb2tlPSIjY2NjIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS13aWR0aD0iMS41IiBkPSJNLjc1Ljc1IDYuNyA2LjY4cS4wNy4wNi4xNCAwbTAgMHEwIDAgMCAwWm0wIDBMMTIuNzUuNzUiLz4KPC9zdmc+";
|
|
@@ -808,17 +1198,19 @@ const SeeMore = ({ style, messages = defaultMessages, children, ...rest }) => {
|
|
|
808
1198
|
const [expandedHeight, setExpandedHeight] = useState();
|
|
809
1199
|
const rootRef = useRef(null);
|
|
810
1200
|
const containeRef = useRef();
|
|
811
|
-
|
|
1201
|
+
useLayoutEffect(() => {
|
|
812
1202
|
if (!rootRef.current) return;
|
|
813
|
-
|
|
1203
|
+
const updateExpandStatus = () => {
|
|
814
1204
|
if (!containeRef.current) return;
|
|
815
1205
|
const collapsedLines = Number.parseInt(window.getComputedStyle(containeRef.current).getPropertyValue("--see-more-collapsed-lines"), 10) || 2;
|
|
816
1206
|
const lineCount = getLineCount(containeRef.current);
|
|
817
1207
|
const scrollable = lineCount > collapsedLines;
|
|
818
1208
|
const fit = lineCount <= collapsedLines;
|
|
819
1209
|
setStatus((current) => current === "no-expand" && scrollable ? "collapsed" : current !== "no-expand" && fit ? "no-expand" : current);
|
|
820
|
-
setExpandedHeight(containeRef.current
|
|
821
|
-
}
|
|
1210
|
+
setExpandedHeight(containeRef.current.scrollHeight);
|
|
1211
|
+
};
|
|
1212
|
+
updateExpandStatus();
|
|
1213
|
+
return onResize(rootRef.current, updateExpandStatus);
|
|
822
1214
|
}, []);
|
|
823
1215
|
const toggle = () => setStatus((current) => current === "collapsed" ? "expanded" : "collapsing");
|
|
824
1216
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -1077,4 +1469,4 @@ const VideoItem = ({ style, href = "", thumbnailHref = href, imageUrl = "", data
|
|
|
1077
1469
|
var VideoItem_default = VideoItem;
|
|
1078
1470
|
|
|
1079
1471
|
//#endregion
|
|
1080
|
-
export { Banner_default as Banner, Dropdown_default as Dropdown, HiddenToggle_default as HiddenToggle, Icon_default as Icon, SeeMore_default as SeeMore, VideoItem_default as VideoItem, VideoThumbnail_default as VideoThumbnail };
|
|
1472
|
+
export { Banner_default as Banner, Dropdown_default as Dropdown, HiddenToggle_default as HiddenToggle, Icon_default as Icon, Modal_default as Modal, Pagination_default as Pagination, SeeMore_default as SeeMore, VideoItem_default as VideoItem, VideoThumbnail_default as VideoThumbnail };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kkcompany/app-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.31",
|
|
4
4
|
"module": "dist/index.mjs",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.mts",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"scripts": {
|
|
21
21
|
"dev": "next",
|
|
22
|
-
"build": "tsdown --format esm --format cjs"
|
|
22
|
+
"build": "tsdown --format esm --format cjs",
|
|
23
|
+
"test": "vitest run"
|
|
23
24
|
},
|
|
24
25
|
"dependencies": {
|
|
25
26
|
"@emotion/react": "^11.14.0"
|
|
@@ -30,10 +31,13 @@
|
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
32
33
|
"@biomejs/biome": "^2.3.5",
|
|
34
|
+
"@testing-library/react": "^13.4.0",
|
|
33
35
|
"binary-base64-loader": "^1.0.0",
|
|
36
|
+
"jsdom": "^26.1.0",
|
|
34
37
|
"next": "^16.0.2",
|
|
35
38
|
"rollup-plugin-base64": "^1.0.1",
|
|
36
39
|
"tsdown": "^0.16.4",
|
|
37
|
-
"typescript": "^5.9.3"
|
|
40
|
+
"typescript": "^5.9.3",
|
|
41
|
+
"vitest": "^4.1.0"
|
|
38
42
|
}
|
|
39
43
|
}
|