@expcat/tigercat-react 0.2.0 → 0.2.27
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/README.md +59 -0
- package/dist/{chunk-6DYS4PJT.mjs → chunk-2UVQIL26.mjs} +1 -1
- package/dist/chunk-4MMT4EJJ.mjs +78 -0
- package/dist/chunk-67EK62HG.mjs +65 -0
- package/dist/{chunk-VXHBQTZS.js → chunk-GY6D4XS3.js} +13 -5
- package/dist/chunk-GZPMLPRW.js +107 -0
- package/dist/{chunk-7JQ7LURS.mjs → chunk-H36CWHUP.mjs} +9 -4
- package/dist/chunk-HUZVBDHV.js +81 -0
- package/dist/chunk-JOHKSMJM.mjs +266 -0
- package/dist/{chunk-WEGU7O4J.mjs → chunk-KOLLAGRK.mjs} +1 -1
- package/dist/{chunk-IS7YOBR7.mjs → chunk-NDOYQK2R.mjs} +13 -5
- package/dist/{chunk-2DOPHSZP.js → chunk-OWUGXP6K.js} +8 -3
- package/dist/chunk-Q2GPRAF4.js +66 -0
- package/dist/{chunk-6PUSRC6S.js → chunk-T3GSXTDU.js} +2 -2
- package/dist/{chunk-UG3I4PCY.js → chunk-VR5OP4MO.js} +2 -2
- package/dist/chunk-X4F6NSI5.mjs +104 -0
- package/dist/chunk-Y6557RWE.mjs +62 -0
- package/dist/chunk-YIF5VX7K.mjs +158 -0
- package/dist/chunk-Z5DDULTA.js +72 -0
- package/dist/chunk-Z6G4HABF.js +272 -0
- package/dist/chunk-ZPWDDAFE.js +162 -0
- package/dist/components/Anchor.d.mts +38 -0
- package/dist/components/Anchor.d.ts +38 -0
- package/dist/components/Anchor.js +20 -0
- package/dist/components/Anchor.mjs +1 -0
- package/dist/components/AnchorLink.d.mts +23 -0
- package/dist/components/AnchorLink.d.ts +23 -0
- package/dist/components/AnchorLink.js +17 -0
- package/dist/components/AnchorLink.mjs +2 -0
- package/dist/components/AreaChart.js +5 -5
- package/dist/components/AreaChart.mjs +3 -3
- package/dist/components/BackTop.d.mts +21 -0
- package/dist/components/BackTop.d.ts +21 -0
- package/dist/components/BackTop.js +16 -0
- package/dist/components/BackTop.mjs +1 -0
- package/dist/components/BarChart.js +5 -5
- package/dist/components/BarChart.mjs +3 -3
- package/dist/components/Breadcrumb.d.mts +4 -0
- package/dist/components/Breadcrumb.d.ts +4 -0
- package/dist/components/Breadcrumb.js +3 -3
- package/dist/components/Breadcrumb.mjs +1 -1
- package/dist/components/BreadcrumbItem.js +3 -3
- package/dist/components/BreadcrumbItem.mjs +2 -2
- package/dist/components/Carousel.d.mts +26 -0
- package/dist/components/Carousel.d.ts +26 -0
- package/dist/components/Carousel.js +10 -0
- package/dist/components/Carousel.mjs +1 -0
- package/dist/components/Collapse.d.mts +29 -0
- package/dist/components/Collapse.d.ts +29 -0
- package/dist/components/Collapse.js +20 -0
- package/dist/components/Collapse.mjs +1 -0
- package/dist/components/CollapsePanel.d.mts +24 -0
- package/dist/components/CollapsePanel.d.ts +24 -0
- package/dist/components/CollapsePanel.js +17 -0
- package/dist/components/CollapsePanel.mjs +2 -0
- package/dist/components/DonutChart.js +5 -5
- package/dist/components/DonutChart.mjs +3 -3
- package/dist/components/LineChart.js +5 -5
- package/dist/components/LineChart.mjs +3 -3
- package/dist/components/Pagination.js +3 -3
- package/dist/components/Pagination.mjs +1 -1
- package/dist/components/PieChart.js +4 -4
- package/dist/components/PieChart.mjs +2 -2
- package/dist/components/RadarChart.js +4 -4
- package/dist/components/RadarChart.mjs +2 -2
- package/dist/components/ScatterChart.js +5 -5
- package/dist/components/ScatterChart.mjs +3 -3
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +142 -104
- package/dist/index.mjs +34 -28
- package/package.json +6 -2
- package/dist/{chunk-N32MAX4A.js → chunk-2VXA4YOP.js} +1 -1
- package/dist/{chunk-VBSK4TGO.mjs → chunk-2WLSB7K2.mjs} +2 -2
- package/dist/{chunk-CBALIFPW.mjs → chunk-324UKFG2.mjs} +2 -2
- package/dist/{chunk-YER7IQF4.mjs → chunk-5QKBBGIA.mjs} +1 -1
- package/dist/{chunk-OONM7FO7.js → chunk-67WZRMD6.js} +2 -2
- package/dist/{chunk-QI6WAP6Y.js → chunk-7SOL3UJ2.js} +2 -2
- package/dist/{chunk-KBGURVTD.mjs → chunk-AFFSBNYB.mjs} +2 -2
- package/dist/{chunk-LZNG2HGC.mjs → chunk-E6GLWHRL.mjs} +1 -1
- package/dist/{chunk-ZUUG3WOL.js → chunk-KKHKQP6Z.js} +1 -1
- package/dist/{chunk-EJLJYOO7.js → chunk-LWW2LXCP.js} +2 -2
- package/dist/{chunk-A2UW5OKX.mjs → chunk-RKBNIEGF.mjs} +2 -2
- package/dist/{chunk-42UKIFFQ.js → chunk-ZYF5GI2Q.js} +2 -2
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { createContext, useContext, useState, useRef, useMemo, useCallback, useEffect } from 'react';
|
|
2
|
+
import { scrollToAnchor, classNames, getAnchorWrapperClasses, getAnchorInkContainerClasses, getAnchorInkActiveClasses, getAnchorLinkListClasses, findActiveAnchor } from '@expcat/tigercat-core';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/components/Anchor.tsx
|
|
6
|
+
var AnchorContext = createContext(null);
|
|
7
|
+
function useAnchorContext() {
|
|
8
|
+
return useContext(AnchorContext);
|
|
9
|
+
}
|
|
10
|
+
var Anchor = ({
|
|
11
|
+
affix = true,
|
|
12
|
+
bounds = 5,
|
|
13
|
+
offsetTop = 0,
|
|
14
|
+
showInkInFixed = false,
|
|
15
|
+
targetOffset,
|
|
16
|
+
getCurrentAnchor,
|
|
17
|
+
getContainer = () => window,
|
|
18
|
+
direction = "vertical",
|
|
19
|
+
className,
|
|
20
|
+
style,
|
|
21
|
+
onClick,
|
|
22
|
+
onChange,
|
|
23
|
+
children
|
|
24
|
+
}) => {
|
|
25
|
+
const [activeLink, setActiveLink] = useState("");
|
|
26
|
+
const [links, setLinks] = useState([]);
|
|
27
|
+
const anchorRef = useRef(null);
|
|
28
|
+
const inkRef = useRef(null);
|
|
29
|
+
const isScrollingRef = useRef(false);
|
|
30
|
+
const animationFrameRef = useRef(null);
|
|
31
|
+
const getContainerRef = useRef(getContainer);
|
|
32
|
+
getContainerRef.current = getContainer;
|
|
33
|
+
const scrollOffset = useMemo(() => targetOffset ?? offsetTop, [targetOffset, offsetTop]);
|
|
34
|
+
const registerLink = useCallback((href) => {
|
|
35
|
+
setLinks((prevLinks) => {
|
|
36
|
+
if (href && !prevLinks.includes(href)) {
|
|
37
|
+
return [...prevLinks, href];
|
|
38
|
+
}
|
|
39
|
+
return prevLinks;
|
|
40
|
+
});
|
|
41
|
+
}, []);
|
|
42
|
+
const unregisterLink = useCallback((href) => {
|
|
43
|
+
setLinks((prevLinks) => prevLinks.filter((l) => l !== href));
|
|
44
|
+
}, []);
|
|
45
|
+
const scrollTo = useCallback(
|
|
46
|
+
(href) => {
|
|
47
|
+
const container = getContainerRef.current();
|
|
48
|
+
scrollToAnchor(href, container, scrollOffset);
|
|
49
|
+
},
|
|
50
|
+
[scrollOffset]
|
|
51
|
+
);
|
|
52
|
+
const handleLinkClick = useCallback(
|
|
53
|
+
(href, event) => {
|
|
54
|
+
onClick?.(event, href);
|
|
55
|
+
isScrollingRef.current = true;
|
|
56
|
+
setActiveLink(href);
|
|
57
|
+
scrollTo(href);
|
|
58
|
+
setTimeout(() => {
|
|
59
|
+
isScrollingRef.current = false;
|
|
60
|
+
}, 500);
|
|
61
|
+
},
|
|
62
|
+
[onClick, scrollTo]
|
|
63
|
+
);
|
|
64
|
+
const scrollHandlerRef = useRef(null);
|
|
65
|
+
const boundContainerRef = useRef(null);
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
const timeoutId = setTimeout(() => {
|
|
68
|
+
const container = getContainerRef.current();
|
|
69
|
+
boundContainerRef.current = container;
|
|
70
|
+
const handleScroll = () => {
|
|
71
|
+
if (isScrollingRef.current) return;
|
|
72
|
+
if (animationFrameRef.current !== null) {
|
|
73
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
74
|
+
}
|
|
75
|
+
animationFrameRef.current = requestAnimationFrame(() => {
|
|
76
|
+
const currentContainer = getContainerRef.current();
|
|
77
|
+
const newActiveLink = findActiveAnchor(links, currentContainer, bounds, scrollOffset);
|
|
78
|
+
const finalActiveLink = getCurrentAnchor ? getCurrentAnchor(newActiveLink) : newActiveLink;
|
|
79
|
+
setActiveLink((prevActiveLink) => {
|
|
80
|
+
if (finalActiveLink !== prevActiveLink) {
|
|
81
|
+
onChange?.(finalActiveLink);
|
|
82
|
+
return finalActiveLink;
|
|
83
|
+
}
|
|
84
|
+
return prevActiveLink;
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
scrollHandlerRef.current = handleScroll;
|
|
89
|
+
container.addEventListener("scroll", handleScroll, { passive: true });
|
|
90
|
+
handleScroll();
|
|
91
|
+
}, 0);
|
|
92
|
+
return () => {
|
|
93
|
+
clearTimeout(timeoutId);
|
|
94
|
+
if (boundContainerRef.current && scrollHandlerRef.current) {
|
|
95
|
+
boundContainerRef.current.removeEventListener("scroll", scrollHandlerRef.current);
|
|
96
|
+
}
|
|
97
|
+
if (animationFrameRef.current !== null) {
|
|
98
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}, [links, bounds, scrollOffset, getCurrentAnchor, onChange]);
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
if (!inkRef.current || !anchorRef.current || !activeLink) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const activeLinkElement = anchorRef.current.querySelector(
|
|
107
|
+
`[data-anchor-href="${activeLink}"]`
|
|
108
|
+
);
|
|
109
|
+
if (!activeLinkElement) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const anchorRect = anchorRef.current.getBoundingClientRect();
|
|
113
|
+
const linkRect = activeLinkElement.getBoundingClientRect();
|
|
114
|
+
if (direction === "vertical") {
|
|
115
|
+
inkRef.current.style.top = `${linkRect.top - anchorRect.top}px`;
|
|
116
|
+
inkRef.current.style.height = `${linkRect.height}px`;
|
|
117
|
+
} else {
|
|
118
|
+
inkRef.current.style.left = `${linkRect.left - anchorRect.left}px`;
|
|
119
|
+
inkRef.current.style.width = `${linkRect.width}px`;
|
|
120
|
+
}
|
|
121
|
+
}, [activeLink, direction]);
|
|
122
|
+
const wrapperClasses = useMemo(
|
|
123
|
+
() => classNames(getAnchorWrapperClasses(affix, className)),
|
|
124
|
+
[affix, className]
|
|
125
|
+
);
|
|
126
|
+
const inkContainerClasses = useMemo(() => getAnchorInkContainerClasses(direction), [direction]);
|
|
127
|
+
const inkActiveClasses = useMemo(() => getAnchorInkActiveClasses(direction), [direction]);
|
|
128
|
+
const linkListClasses = useMemo(() => getAnchorLinkListClasses(direction), [direction]);
|
|
129
|
+
const showInk = useMemo(() => {
|
|
130
|
+
if (!affix) return true;
|
|
131
|
+
return showInkInFixed;
|
|
132
|
+
}, [affix, showInkInFixed]);
|
|
133
|
+
const wrapperStyle = useMemo(() => {
|
|
134
|
+
const baseStyle = {};
|
|
135
|
+
if (affix && offsetTop > 0) {
|
|
136
|
+
baseStyle.top = `${offsetTop}px`;
|
|
137
|
+
}
|
|
138
|
+
return { ...baseStyle, ...style };
|
|
139
|
+
}, [affix, offsetTop, style]);
|
|
140
|
+
const contextValue = useMemo(
|
|
141
|
+
() => ({
|
|
142
|
+
activeLink,
|
|
143
|
+
direction,
|
|
144
|
+
registerLink,
|
|
145
|
+
unregisterLink,
|
|
146
|
+
handleLinkClick,
|
|
147
|
+
scrollTo
|
|
148
|
+
}),
|
|
149
|
+
[activeLink, direction, registerLink, unregisterLink, handleLinkClick, scrollTo]
|
|
150
|
+
);
|
|
151
|
+
return /* @__PURE__ */ jsx(AnchorContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs("div", { ref: anchorRef, className: wrapperClasses, style: wrapperStyle, children: [
|
|
152
|
+
showInk && /* @__PURE__ */ jsx("div", { className: inkContainerClasses, children: /* @__PURE__ */ jsx("div", { ref: inkRef, className: inkActiveClasses }) }),
|
|
153
|
+
/* @__PURE__ */ jsx("div", { className: linkListClasses, children })
|
|
154
|
+
] }) });
|
|
155
|
+
};
|
|
156
|
+
var Anchor_default = Anchor;
|
|
157
|
+
|
|
158
|
+
export { Anchor, Anchor_default, useAnchorContext };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkZPWDDAFE_js = require('./chunk-ZPWDDAFE.js');
|
|
4
|
+
var React = require('react');
|
|
5
|
+
var tigercatCore = require('@expcat/tigercat-core');
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
|
|
8
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
|
|
10
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
11
|
+
|
|
12
|
+
var AnchorLink = ({
|
|
13
|
+
href,
|
|
14
|
+
title,
|
|
15
|
+
target,
|
|
16
|
+
className,
|
|
17
|
+
children,
|
|
18
|
+
...props
|
|
19
|
+
}) => {
|
|
20
|
+
const anchorContext = chunkZPWDDAFE_js.useAnchorContext();
|
|
21
|
+
React.useEffect(() => {
|
|
22
|
+
anchorContext?.registerLink(href);
|
|
23
|
+
return () => {
|
|
24
|
+
anchorContext?.unregisterLink(href);
|
|
25
|
+
};
|
|
26
|
+
}, [href, anchorContext]);
|
|
27
|
+
const handleClick = (event) => {
|
|
28
|
+
event.preventDefault();
|
|
29
|
+
anchorContext?.handleLinkClick(href, event);
|
|
30
|
+
};
|
|
31
|
+
const linkClasses = React.useMemo(() => {
|
|
32
|
+
const isActive = anchorContext?.activeLink === href;
|
|
33
|
+
return tigercatCore.classNames(tigercatCore.getAnchorLinkClasses(isActive, className));
|
|
34
|
+
}, [anchorContext?.activeLink, href, className]);
|
|
35
|
+
const hasNestedLinks = React__default.default.Children.toArray(children).some(
|
|
36
|
+
(child) => React__default.default.isValidElement(child) && child.type === AnchorLink
|
|
37
|
+
);
|
|
38
|
+
if (hasNestedLinks) {
|
|
39
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "anchor-link-wrapper", children: [
|
|
40
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
41
|
+
"a",
|
|
42
|
+
{
|
|
43
|
+
href,
|
|
44
|
+
target,
|
|
45
|
+
className: linkClasses,
|
|
46
|
+
"data-anchor-href": href,
|
|
47
|
+
onClick: handleClick,
|
|
48
|
+
...props,
|
|
49
|
+
children: title
|
|
50
|
+
}
|
|
51
|
+
),
|
|
52
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pl-3 mt-1 space-y-1", children })
|
|
53
|
+
] });
|
|
54
|
+
}
|
|
55
|
+
const content = children ?? title;
|
|
56
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
57
|
+
"a",
|
|
58
|
+
{
|
|
59
|
+
href,
|
|
60
|
+
target,
|
|
61
|
+
className: linkClasses,
|
|
62
|
+
"data-anchor-href": href,
|
|
63
|
+
onClick: handleClick,
|
|
64
|
+
...props,
|
|
65
|
+
children: content
|
|
66
|
+
}
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
var AnchorLink_default = AnchorLink;
|
|
70
|
+
|
|
71
|
+
exports.AnchorLink = AnchorLink;
|
|
72
|
+
exports.AnchorLink_default = AnchorLink_default;
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var tigercatCore = require('@expcat/tigercat-core');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
|
|
9
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
10
|
+
|
|
11
|
+
// src/components/Carousel.tsx
|
|
12
|
+
var Carousel = React.forwardRef(
|
|
13
|
+
({
|
|
14
|
+
autoplay = false,
|
|
15
|
+
autoplaySpeed = 3e3,
|
|
16
|
+
dots = true,
|
|
17
|
+
dotPosition = "bottom",
|
|
18
|
+
effect = "scroll",
|
|
19
|
+
arrows = false,
|
|
20
|
+
infinite = true,
|
|
21
|
+
speed = 500,
|
|
22
|
+
initialSlide = 0,
|
|
23
|
+
pauseOnHover = true,
|
|
24
|
+
pauseOnFocus = true,
|
|
25
|
+
className,
|
|
26
|
+
style,
|
|
27
|
+
onChange,
|
|
28
|
+
onBeforeChange,
|
|
29
|
+
children
|
|
30
|
+
}, ref) => {
|
|
31
|
+
const [currentIndex, setCurrentIndex] = React.useState(initialSlide);
|
|
32
|
+
const [isPaused, setIsPaused] = React.useState(false);
|
|
33
|
+
const autoplayTimerRef = React.useRef(null);
|
|
34
|
+
const slides = React.useMemo(() => {
|
|
35
|
+
return React__default.default.Children.toArray(children).filter((child) => React__default.default.isValidElement(child));
|
|
36
|
+
}, [children]);
|
|
37
|
+
const slideCount = slides.length;
|
|
38
|
+
const containerClasses = React.useMemo(
|
|
39
|
+
() => tigercatCore.classNames(tigercatCore.getCarouselContainerClasses(className)),
|
|
40
|
+
[className]
|
|
41
|
+
);
|
|
42
|
+
const trackClasses = React.useMemo(() => {
|
|
43
|
+
if (effect === "fade") {
|
|
44
|
+
return tigercatCore.carouselTrackFadeClasses;
|
|
45
|
+
}
|
|
46
|
+
return tigercatCore.carouselTrackScrollClasses;
|
|
47
|
+
}, [effect]);
|
|
48
|
+
const trackStyle = React.useMemo(() => {
|
|
49
|
+
if (effect === "scroll") {
|
|
50
|
+
return {
|
|
51
|
+
transform: tigercatCore.getScrollTransform(currentIndex),
|
|
52
|
+
transitionDuration: `${speed}ms`
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return {};
|
|
56
|
+
}, [effect, currentIndex, speed]);
|
|
57
|
+
const getSlideClasses = React.useCallback(
|
|
58
|
+
(index) => {
|
|
59
|
+
const isActive = index === currentIndex;
|
|
60
|
+
if (effect === "fade") {
|
|
61
|
+
const positionClass = index === 0 ? "relative" : "absolute inset-0";
|
|
62
|
+
return tigercatCore.classNames(
|
|
63
|
+
positionClass,
|
|
64
|
+
"w-full transition-opacity ease-in-out",
|
|
65
|
+
isActive ? "opacity-100 z-10" : "opacity-0 z-0"
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
return tigercatCore.carouselSlideBaseClasses;
|
|
69
|
+
},
|
|
70
|
+
[effect, currentIndex]
|
|
71
|
+
);
|
|
72
|
+
const getSlideStyle = React.useCallback(() => {
|
|
73
|
+
return {
|
|
74
|
+
transitionDuration: `${speed}ms`
|
|
75
|
+
};
|
|
76
|
+
}, [speed]);
|
|
77
|
+
const dotsClasses = React.useMemo(() => {
|
|
78
|
+
return tigercatCore.getCarouselDotsClasses(dotPosition);
|
|
79
|
+
}, [dotPosition]);
|
|
80
|
+
const goTo = React.useCallback(
|
|
81
|
+
(index) => {
|
|
82
|
+
const clampedIndex = tigercatCore.clampSlideIndex(index, slideCount);
|
|
83
|
+
if (clampedIndex === currentIndex) return;
|
|
84
|
+
onBeforeChange?.(currentIndex, clampedIndex);
|
|
85
|
+
const prevIndex = currentIndex;
|
|
86
|
+
setCurrentIndex(clampedIndex);
|
|
87
|
+
onChange?.(clampedIndex, prevIndex);
|
|
88
|
+
},
|
|
89
|
+
[currentIndex, slideCount, onBeforeChange, onChange]
|
|
90
|
+
);
|
|
91
|
+
const next = React.useCallback(() => {
|
|
92
|
+
const nextIdx = tigercatCore.getNextSlideIndex(currentIndex, slideCount, infinite);
|
|
93
|
+
if (nextIdx !== currentIndex) {
|
|
94
|
+
goTo(nextIdx);
|
|
95
|
+
}
|
|
96
|
+
}, [currentIndex, slideCount, infinite, goTo]);
|
|
97
|
+
const prev = React.useCallback(() => {
|
|
98
|
+
const prevIdx = tigercatCore.getPrevSlideIndex(currentIndex, slideCount, infinite);
|
|
99
|
+
if (prevIdx !== currentIndex) {
|
|
100
|
+
goTo(prevIdx);
|
|
101
|
+
}
|
|
102
|
+
}, [currentIndex, slideCount, infinite, goTo]);
|
|
103
|
+
React.useImperativeHandle(
|
|
104
|
+
ref,
|
|
105
|
+
() => ({
|
|
106
|
+
next,
|
|
107
|
+
prev,
|
|
108
|
+
goTo
|
|
109
|
+
}),
|
|
110
|
+
[next, prev, goTo]
|
|
111
|
+
);
|
|
112
|
+
React.useEffect(() => {
|
|
113
|
+
if (autoplay && !isPaused) {
|
|
114
|
+
if (autoplayTimerRef.current) {
|
|
115
|
+
clearInterval(autoplayTimerRef.current);
|
|
116
|
+
}
|
|
117
|
+
autoplayTimerRef.current = setInterval(() => {
|
|
118
|
+
setCurrentIndex((prevIndex) => {
|
|
119
|
+
const nextIdx = tigercatCore.getNextSlideIndex(prevIndex, slideCount, infinite);
|
|
120
|
+
if (nextIdx !== prevIndex) {
|
|
121
|
+
onBeforeChange?.(prevIndex, nextIdx);
|
|
122
|
+
onChange?.(nextIdx, prevIndex);
|
|
123
|
+
}
|
|
124
|
+
return nextIdx;
|
|
125
|
+
});
|
|
126
|
+
}, autoplaySpeed);
|
|
127
|
+
}
|
|
128
|
+
return () => {
|
|
129
|
+
if (autoplayTimerRef.current) {
|
|
130
|
+
clearInterval(autoplayTimerRef.current);
|
|
131
|
+
autoplayTimerRef.current = null;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}, [autoplay, autoplaySpeed, isPaused, slideCount, infinite, onChange, onBeforeChange]);
|
|
135
|
+
const handleMouseEnter = React.useCallback(() => {
|
|
136
|
+
if (pauseOnHover && autoplay) {
|
|
137
|
+
setIsPaused(true);
|
|
138
|
+
}
|
|
139
|
+
}, [pauseOnHover, autoplay]);
|
|
140
|
+
const handleMouseLeave = React.useCallback(() => {
|
|
141
|
+
if (pauseOnHover && autoplay) {
|
|
142
|
+
setIsPaused(false);
|
|
143
|
+
}
|
|
144
|
+
}, [pauseOnHover, autoplay]);
|
|
145
|
+
const handleFocus = React.useCallback(() => {
|
|
146
|
+
if (pauseOnFocus && autoplay) {
|
|
147
|
+
setIsPaused(true);
|
|
148
|
+
}
|
|
149
|
+
}, [pauseOnFocus, autoplay]);
|
|
150
|
+
const handleBlur = React.useCallback(() => {
|
|
151
|
+
if (pauseOnFocus && autoplay) {
|
|
152
|
+
setIsPaused(false);
|
|
153
|
+
}
|
|
154
|
+
}, [pauseOnFocus, autoplay]);
|
|
155
|
+
const isPrevArrowDisabled = React.useMemo(
|
|
156
|
+
() => tigercatCore.isPrevDisabled(currentIndex, slideCount, infinite),
|
|
157
|
+
[currentIndex, slideCount, infinite]
|
|
158
|
+
);
|
|
159
|
+
const isNextArrowDisabled = React.useMemo(
|
|
160
|
+
() => tigercatCore.isNextDisabled(currentIndex, slideCount, infinite),
|
|
161
|
+
[currentIndex, slideCount, infinite]
|
|
162
|
+
);
|
|
163
|
+
const renderArrows = () => {
|
|
164
|
+
if (!arrows) return null;
|
|
165
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
166
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
167
|
+
"button",
|
|
168
|
+
{
|
|
169
|
+
type: "button",
|
|
170
|
+
className: tigercatCore.getCarouselArrowClasses("prev", isPrevArrowDisabled),
|
|
171
|
+
onClick: prev,
|
|
172
|
+
disabled: isPrevArrowDisabled,
|
|
173
|
+
"aria-label": "Previous slide",
|
|
174
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
175
|
+
"svg",
|
|
176
|
+
{
|
|
177
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
178
|
+
viewBox: "0 0 24 24",
|
|
179
|
+
fill: "none",
|
|
180
|
+
stroke: "currentColor",
|
|
181
|
+
strokeWidth: "2",
|
|
182
|
+
strokeLinecap: "round",
|
|
183
|
+
strokeLinejoin: "round",
|
|
184
|
+
className: "w-6 h-6",
|
|
185
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: tigercatCore.carouselPrevArrowPath })
|
|
186
|
+
}
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
),
|
|
190
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
191
|
+
"button",
|
|
192
|
+
{
|
|
193
|
+
type: "button",
|
|
194
|
+
className: tigercatCore.getCarouselArrowClasses("next", isNextArrowDisabled),
|
|
195
|
+
onClick: next,
|
|
196
|
+
disabled: isNextArrowDisabled,
|
|
197
|
+
"aria-label": "Next slide",
|
|
198
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
199
|
+
"svg",
|
|
200
|
+
{
|
|
201
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
202
|
+
viewBox: "0 0 24 24",
|
|
203
|
+
fill: "none",
|
|
204
|
+
stroke: "currentColor",
|
|
205
|
+
strokeWidth: "2",
|
|
206
|
+
strokeLinecap: "round",
|
|
207
|
+
strokeLinejoin: "round",
|
|
208
|
+
className: "w-6 h-6",
|
|
209
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: tigercatCore.carouselNextArrowPath })
|
|
210
|
+
}
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
)
|
|
214
|
+
] });
|
|
215
|
+
};
|
|
216
|
+
const renderDots = () => {
|
|
217
|
+
if (!dots || slideCount <= 1) return null;
|
|
218
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: dotsClasses, role: "tablist", "aria-label": "Carousel navigation", children: slides.map((_, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
219
|
+
"button",
|
|
220
|
+
{
|
|
221
|
+
type: "button",
|
|
222
|
+
className: tigercatCore.getCarouselDotClasses(index === currentIndex),
|
|
223
|
+
onClick: () => goTo(index),
|
|
224
|
+
"aria-label": `Go to slide ${index + 1}`,
|
|
225
|
+
"aria-current": index === currentIndex ? "true" : "false"
|
|
226
|
+
},
|
|
227
|
+
index
|
|
228
|
+
)) });
|
|
229
|
+
};
|
|
230
|
+
const renderSlides = () => {
|
|
231
|
+
const slideElements = slides.map((slide, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
232
|
+
"div",
|
|
233
|
+
{
|
|
234
|
+
className: getSlideClasses(index),
|
|
235
|
+
style: effect === "fade" ? getSlideStyle() : void 0,
|
|
236
|
+
role: "group",
|
|
237
|
+
"aria-roledescription": "slide",
|
|
238
|
+
"aria-label": `Slide ${index + 1} of ${slideCount}`,
|
|
239
|
+
"aria-hidden": index !== currentIndex,
|
|
240
|
+
children: slide
|
|
241
|
+
},
|
|
242
|
+
index
|
|
243
|
+
));
|
|
244
|
+
if (effect === "fade") {
|
|
245
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: tigercatCore.classNames(trackClasses, "h-full"), children: slideElements });
|
|
246
|
+
}
|
|
247
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: trackClasses, style: trackStyle, children: slideElements });
|
|
248
|
+
};
|
|
249
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
250
|
+
"div",
|
|
251
|
+
{
|
|
252
|
+
className: containerClasses,
|
|
253
|
+
style,
|
|
254
|
+
role: "region",
|
|
255
|
+
"aria-roledescription": "carousel",
|
|
256
|
+
"aria-label": "Image carousel",
|
|
257
|
+
onMouseEnter: handleMouseEnter,
|
|
258
|
+
onMouseLeave: handleMouseLeave,
|
|
259
|
+
onFocus: handleFocus,
|
|
260
|
+
onBlur: handleBlur,
|
|
261
|
+
children: [
|
|
262
|
+
renderSlides(),
|
|
263
|
+
renderArrows(),
|
|
264
|
+
renderDots()
|
|
265
|
+
]
|
|
266
|
+
}
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
);
|
|
270
|
+
Carousel.displayName = "Carousel";
|
|
271
|
+
|
|
272
|
+
exports.Carousel = Carousel;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var tigercatCore = require('@expcat/tigercat-core');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
// src/components/Anchor.tsx
|
|
8
|
+
var AnchorContext = react.createContext(null);
|
|
9
|
+
function useAnchorContext() {
|
|
10
|
+
return react.useContext(AnchorContext);
|
|
11
|
+
}
|
|
12
|
+
var Anchor = ({
|
|
13
|
+
affix = true,
|
|
14
|
+
bounds = 5,
|
|
15
|
+
offsetTop = 0,
|
|
16
|
+
showInkInFixed = false,
|
|
17
|
+
targetOffset,
|
|
18
|
+
getCurrentAnchor,
|
|
19
|
+
getContainer = () => window,
|
|
20
|
+
direction = "vertical",
|
|
21
|
+
className,
|
|
22
|
+
style,
|
|
23
|
+
onClick,
|
|
24
|
+
onChange,
|
|
25
|
+
children
|
|
26
|
+
}) => {
|
|
27
|
+
const [activeLink, setActiveLink] = react.useState("");
|
|
28
|
+
const [links, setLinks] = react.useState([]);
|
|
29
|
+
const anchorRef = react.useRef(null);
|
|
30
|
+
const inkRef = react.useRef(null);
|
|
31
|
+
const isScrollingRef = react.useRef(false);
|
|
32
|
+
const animationFrameRef = react.useRef(null);
|
|
33
|
+
const getContainerRef = react.useRef(getContainer);
|
|
34
|
+
getContainerRef.current = getContainer;
|
|
35
|
+
const scrollOffset = react.useMemo(() => targetOffset ?? offsetTop, [targetOffset, offsetTop]);
|
|
36
|
+
const registerLink = react.useCallback((href) => {
|
|
37
|
+
setLinks((prevLinks) => {
|
|
38
|
+
if (href && !prevLinks.includes(href)) {
|
|
39
|
+
return [...prevLinks, href];
|
|
40
|
+
}
|
|
41
|
+
return prevLinks;
|
|
42
|
+
});
|
|
43
|
+
}, []);
|
|
44
|
+
const unregisterLink = react.useCallback((href) => {
|
|
45
|
+
setLinks((prevLinks) => prevLinks.filter((l) => l !== href));
|
|
46
|
+
}, []);
|
|
47
|
+
const scrollTo = react.useCallback(
|
|
48
|
+
(href) => {
|
|
49
|
+
const container = getContainerRef.current();
|
|
50
|
+
tigercatCore.scrollToAnchor(href, container, scrollOffset);
|
|
51
|
+
},
|
|
52
|
+
[scrollOffset]
|
|
53
|
+
);
|
|
54
|
+
const handleLinkClick = react.useCallback(
|
|
55
|
+
(href, event) => {
|
|
56
|
+
onClick?.(event, href);
|
|
57
|
+
isScrollingRef.current = true;
|
|
58
|
+
setActiveLink(href);
|
|
59
|
+
scrollTo(href);
|
|
60
|
+
setTimeout(() => {
|
|
61
|
+
isScrollingRef.current = false;
|
|
62
|
+
}, 500);
|
|
63
|
+
},
|
|
64
|
+
[onClick, scrollTo]
|
|
65
|
+
);
|
|
66
|
+
const scrollHandlerRef = react.useRef(null);
|
|
67
|
+
const boundContainerRef = react.useRef(null);
|
|
68
|
+
react.useEffect(() => {
|
|
69
|
+
const timeoutId = setTimeout(() => {
|
|
70
|
+
const container = getContainerRef.current();
|
|
71
|
+
boundContainerRef.current = container;
|
|
72
|
+
const handleScroll = () => {
|
|
73
|
+
if (isScrollingRef.current) return;
|
|
74
|
+
if (animationFrameRef.current !== null) {
|
|
75
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
76
|
+
}
|
|
77
|
+
animationFrameRef.current = requestAnimationFrame(() => {
|
|
78
|
+
const currentContainer = getContainerRef.current();
|
|
79
|
+
const newActiveLink = tigercatCore.findActiveAnchor(links, currentContainer, bounds, scrollOffset);
|
|
80
|
+
const finalActiveLink = getCurrentAnchor ? getCurrentAnchor(newActiveLink) : newActiveLink;
|
|
81
|
+
setActiveLink((prevActiveLink) => {
|
|
82
|
+
if (finalActiveLink !== prevActiveLink) {
|
|
83
|
+
onChange?.(finalActiveLink);
|
|
84
|
+
return finalActiveLink;
|
|
85
|
+
}
|
|
86
|
+
return prevActiveLink;
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
scrollHandlerRef.current = handleScroll;
|
|
91
|
+
container.addEventListener("scroll", handleScroll, { passive: true });
|
|
92
|
+
handleScroll();
|
|
93
|
+
}, 0);
|
|
94
|
+
return () => {
|
|
95
|
+
clearTimeout(timeoutId);
|
|
96
|
+
if (boundContainerRef.current && scrollHandlerRef.current) {
|
|
97
|
+
boundContainerRef.current.removeEventListener("scroll", scrollHandlerRef.current);
|
|
98
|
+
}
|
|
99
|
+
if (animationFrameRef.current !== null) {
|
|
100
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
}, [links, bounds, scrollOffset, getCurrentAnchor, onChange]);
|
|
104
|
+
react.useEffect(() => {
|
|
105
|
+
if (!inkRef.current || !anchorRef.current || !activeLink) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const activeLinkElement = anchorRef.current.querySelector(
|
|
109
|
+
`[data-anchor-href="${activeLink}"]`
|
|
110
|
+
);
|
|
111
|
+
if (!activeLinkElement) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const anchorRect = anchorRef.current.getBoundingClientRect();
|
|
115
|
+
const linkRect = activeLinkElement.getBoundingClientRect();
|
|
116
|
+
if (direction === "vertical") {
|
|
117
|
+
inkRef.current.style.top = `${linkRect.top - anchorRect.top}px`;
|
|
118
|
+
inkRef.current.style.height = `${linkRect.height}px`;
|
|
119
|
+
} else {
|
|
120
|
+
inkRef.current.style.left = `${linkRect.left - anchorRect.left}px`;
|
|
121
|
+
inkRef.current.style.width = `${linkRect.width}px`;
|
|
122
|
+
}
|
|
123
|
+
}, [activeLink, direction]);
|
|
124
|
+
const wrapperClasses = react.useMemo(
|
|
125
|
+
() => tigercatCore.classNames(tigercatCore.getAnchorWrapperClasses(affix, className)),
|
|
126
|
+
[affix, className]
|
|
127
|
+
);
|
|
128
|
+
const inkContainerClasses = react.useMemo(() => tigercatCore.getAnchorInkContainerClasses(direction), [direction]);
|
|
129
|
+
const inkActiveClasses = react.useMemo(() => tigercatCore.getAnchorInkActiveClasses(direction), [direction]);
|
|
130
|
+
const linkListClasses = react.useMemo(() => tigercatCore.getAnchorLinkListClasses(direction), [direction]);
|
|
131
|
+
const showInk = react.useMemo(() => {
|
|
132
|
+
if (!affix) return true;
|
|
133
|
+
return showInkInFixed;
|
|
134
|
+
}, [affix, showInkInFixed]);
|
|
135
|
+
const wrapperStyle = react.useMemo(() => {
|
|
136
|
+
const baseStyle = {};
|
|
137
|
+
if (affix && offsetTop > 0) {
|
|
138
|
+
baseStyle.top = `${offsetTop}px`;
|
|
139
|
+
}
|
|
140
|
+
return { ...baseStyle, ...style };
|
|
141
|
+
}, [affix, offsetTop, style]);
|
|
142
|
+
const contextValue = react.useMemo(
|
|
143
|
+
() => ({
|
|
144
|
+
activeLink,
|
|
145
|
+
direction,
|
|
146
|
+
registerLink,
|
|
147
|
+
unregisterLink,
|
|
148
|
+
handleLinkClick,
|
|
149
|
+
scrollTo
|
|
150
|
+
}),
|
|
151
|
+
[activeLink, direction, registerLink, unregisterLink, handleLinkClick, scrollTo]
|
|
152
|
+
);
|
|
153
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AnchorContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: anchorRef, className: wrapperClasses, style: wrapperStyle, children: [
|
|
154
|
+
showInk && /* @__PURE__ */ jsxRuntime.jsx("div", { className: inkContainerClasses, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: inkRef, className: inkActiveClasses }) }),
|
|
155
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: linkListClasses, children })
|
|
156
|
+
] }) });
|
|
157
|
+
};
|
|
158
|
+
var Anchor_default = Anchor;
|
|
159
|
+
|
|
160
|
+
exports.Anchor = Anchor;
|
|
161
|
+
exports.Anchor_default = Anchor_default;
|
|
162
|
+
exports.useAnchorContext = useAnchorContext;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AnchorProps as AnchorProps$1, AnchorDirection } from '@expcat/tigercat-core';
|
|
3
|
+
|
|
4
|
+
interface AnchorContextValue {
|
|
5
|
+
activeLink: string;
|
|
6
|
+
direction: AnchorDirection;
|
|
7
|
+
registerLink: (href: string) => void;
|
|
8
|
+
unregisterLink: (href: string) => void;
|
|
9
|
+
handleLinkClick: (href: string, event: React.MouseEvent) => void;
|
|
10
|
+
scrollTo: (href: string) => void;
|
|
11
|
+
}
|
|
12
|
+
declare function useAnchorContext(): AnchorContextValue | null;
|
|
13
|
+
interface AnchorProps extends Omit<AnchorProps$1, 'style'> {
|
|
14
|
+
/**
|
|
15
|
+
* Target element to listen for scroll events
|
|
16
|
+
* @default () => window
|
|
17
|
+
*/
|
|
18
|
+
getContainer?: () => HTMLElement | Window;
|
|
19
|
+
/**
|
|
20
|
+
* Click event handler
|
|
21
|
+
*/
|
|
22
|
+
onClick?: (event: React.MouseEvent, href: string) => void;
|
|
23
|
+
/**
|
|
24
|
+
* Change event handler when active anchor changes
|
|
25
|
+
*/
|
|
26
|
+
onChange?: (currentActiveLink: string) => void;
|
|
27
|
+
/**
|
|
28
|
+
* Children (AnchorLink components)
|
|
29
|
+
*/
|
|
30
|
+
children?: React.ReactNode;
|
|
31
|
+
/**
|
|
32
|
+
* Custom styles
|
|
33
|
+
*/
|
|
34
|
+
style?: React.CSSProperties;
|
|
35
|
+
}
|
|
36
|
+
declare const Anchor: React.FC<AnchorProps>;
|
|
37
|
+
|
|
38
|
+
export { Anchor, type AnchorContextValue, type AnchorProps, Anchor as default, useAnchorContext };
|