@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.
Files changed (84) hide show
  1. package/README.md +59 -0
  2. package/dist/{chunk-6DYS4PJT.mjs → chunk-2UVQIL26.mjs} +1 -1
  3. package/dist/chunk-4MMT4EJJ.mjs +78 -0
  4. package/dist/chunk-67EK62HG.mjs +65 -0
  5. package/dist/{chunk-VXHBQTZS.js → chunk-GY6D4XS3.js} +13 -5
  6. package/dist/chunk-GZPMLPRW.js +107 -0
  7. package/dist/{chunk-7JQ7LURS.mjs → chunk-H36CWHUP.mjs} +9 -4
  8. package/dist/chunk-HUZVBDHV.js +81 -0
  9. package/dist/chunk-JOHKSMJM.mjs +266 -0
  10. package/dist/{chunk-WEGU7O4J.mjs → chunk-KOLLAGRK.mjs} +1 -1
  11. package/dist/{chunk-IS7YOBR7.mjs → chunk-NDOYQK2R.mjs} +13 -5
  12. package/dist/{chunk-2DOPHSZP.js → chunk-OWUGXP6K.js} +8 -3
  13. package/dist/chunk-Q2GPRAF4.js +66 -0
  14. package/dist/{chunk-6PUSRC6S.js → chunk-T3GSXTDU.js} +2 -2
  15. package/dist/{chunk-UG3I4PCY.js → chunk-VR5OP4MO.js} +2 -2
  16. package/dist/chunk-X4F6NSI5.mjs +104 -0
  17. package/dist/chunk-Y6557RWE.mjs +62 -0
  18. package/dist/chunk-YIF5VX7K.mjs +158 -0
  19. package/dist/chunk-Z5DDULTA.js +72 -0
  20. package/dist/chunk-Z6G4HABF.js +272 -0
  21. package/dist/chunk-ZPWDDAFE.js +162 -0
  22. package/dist/components/Anchor.d.mts +38 -0
  23. package/dist/components/Anchor.d.ts +38 -0
  24. package/dist/components/Anchor.js +20 -0
  25. package/dist/components/Anchor.mjs +1 -0
  26. package/dist/components/AnchorLink.d.mts +23 -0
  27. package/dist/components/AnchorLink.d.ts +23 -0
  28. package/dist/components/AnchorLink.js +17 -0
  29. package/dist/components/AnchorLink.mjs +2 -0
  30. package/dist/components/AreaChart.js +5 -5
  31. package/dist/components/AreaChart.mjs +3 -3
  32. package/dist/components/BackTop.d.mts +21 -0
  33. package/dist/components/BackTop.d.ts +21 -0
  34. package/dist/components/BackTop.js +16 -0
  35. package/dist/components/BackTop.mjs +1 -0
  36. package/dist/components/BarChart.js +5 -5
  37. package/dist/components/BarChart.mjs +3 -3
  38. package/dist/components/Breadcrumb.d.mts +4 -0
  39. package/dist/components/Breadcrumb.d.ts +4 -0
  40. package/dist/components/Breadcrumb.js +3 -3
  41. package/dist/components/Breadcrumb.mjs +1 -1
  42. package/dist/components/BreadcrumbItem.js +3 -3
  43. package/dist/components/BreadcrumbItem.mjs +2 -2
  44. package/dist/components/Carousel.d.mts +26 -0
  45. package/dist/components/Carousel.d.ts +26 -0
  46. package/dist/components/Carousel.js +10 -0
  47. package/dist/components/Carousel.mjs +1 -0
  48. package/dist/components/Collapse.d.mts +29 -0
  49. package/dist/components/Collapse.d.ts +29 -0
  50. package/dist/components/Collapse.js +20 -0
  51. package/dist/components/Collapse.mjs +1 -0
  52. package/dist/components/CollapsePanel.d.mts +24 -0
  53. package/dist/components/CollapsePanel.d.ts +24 -0
  54. package/dist/components/CollapsePanel.js +17 -0
  55. package/dist/components/CollapsePanel.mjs +2 -0
  56. package/dist/components/DonutChart.js +5 -5
  57. package/dist/components/DonutChart.mjs +3 -3
  58. package/dist/components/LineChart.js +5 -5
  59. package/dist/components/LineChart.mjs +3 -3
  60. package/dist/components/Pagination.js +3 -3
  61. package/dist/components/Pagination.mjs +1 -1
  62. package/dist/components/PieChart.js +4 -4
  63. package/dist/components/PieChart.mjs +2 -2
  64. package/dist/components/RadarChart.js +4 -4
  65. package/dist/components/RadarChart.mjs +2 -2
  66. package/dist/components/ScatterChart.js +5 -5
  67. package/dist/components/ScatterChart.mjs +3 -3
  68. package/dist/index.d.mts +6 -0
  69. package/dist/index.d.ts +6 -0
  70. package/dist/index.js +142 -104
  71. package/dist/index.mjs +34 -28
  72. package/package.json +6 -2
  73. package/dist/{chunk-N32MAX4A.js → chunk-2VXA4YOP.js} +1 -1
  74. package/dist/{chunk-VBSK4TGO.mjs → chunk-2WLSB7K2.mjs} +2 -2
  75. package/dist/{chunk-CBALIFPW.mjs → chunk-324UKFG2.mjs} +2 -2
  76. package/dist/{chunk-YER7IQF4.mjs → chunk-5QKBBGIA.mjs} +1 -1
  77. package/dist/{chunk-OONM7FO7.js → chunk-67WZRMD6.js} +2 -2
  78. package/dist/{chunk-QI6WAP6Y.js → chunk-7SOL3UJ2.js} +2 -2
  79. package/dist/{chunk-KBGURVTD.mjs → chunk-AFFSBNYB.mjs} +2 -2
  80. package/dist/{chunk-LZNG2HGC.mjs → chunk-E6GLWHRL.mjs} +1 -1
  81. package/dist/{chunk-ZUUG3WOL.js → chunk-KKHKQP6Z.js} +1 -1
  82. package/dist/{chunk-EJLJYOO7.js → chunk-LWW2LXCP.js} +2 -2
  83. package/dist/{chunk-A2UW5OKX.mjs → chunk-RKBNIEGF.mjs} +2 -2
  84. 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 };