@toankhontech/arctimer-react 0.0.0

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 ADDED
@@ -0,0 +1,213 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var arctimerCore = require('@toankhontech/arctimer-core');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ // src/CountdownCircleTimer.tsx
8
+ var CountdownCircleTimer = react.forwardRef((props, ref) => {
9
+ const {
10
+ children,
11
+ trailColor = "#d9d9d9",
12
+ trailStrokeWidth,
13
+ strokeLinecap = "round",
14
+ style,
15
+ className,
16
+ size = 180,
17
+ strokeWidth = 12,
18
+ ...restProps
19
+ } = props;
20
+ const countdown = arctimerCore.useCountdown({
21
+ ...restProps,
22
+ size,
23
+ strokeWidth
24
+ });
25
+ const {
26
+ path,
27
+ pathLength,
28
+ stroke,
29
+ strokeDashoffset,
30
+ remainingTime,
31
+ elapsedTime,
32
+ progress,
33
+ color,
34
+ isComplete,
35
+ animationScale,
36
+ animationOpacity,
37
+ _play,
38
+ _pause,
39
+ _reset,
40
+ _getState
41
+ } = countdown;
42
+ react.useImperativeHandle(ref, () => ({
43
+ play: _play,
44
+ pause: _pause,
45
+ reset: _reset,
46
+ getState: _getState
47
+ }), [_play, _pause, _reset, _getState]);
48
+ const effectiveTrailStrokeWidth = trailStrokeWidth ?? strokeWidth;
49
+ const viewBox = `0 0 ${size} ${size}`;
50
+ const renderInfo = react.useMemo(
51
+ () => ({
52
+ remainingTime,
53
+ elapsedTime,
54
+ color,
55
+ progress,
56
+ isComplete
57
+ }),
58
+ [remainingTime, elapsedTime, color, progress, isComplete]
59
+ );
60
+ const hasEffects = animationScale !== 1 || animationOpacity !== 1;
61
+ const svgTransform = hasEffects ? `scale(${animationScale})` : void 0;
62
+ const svgTransformOrigin = hasEffects ? "center" : void 0;
63
+ return /* @__PURE__ */ jsxRuntime.jsxs(
64
+ "div",
65
+ {
66
+ style: {
67
+ position: "relative",
68
+ width: size,
69
+ height: size,
70
+ ...style
71
+ },
72
+ className,
73
+ children: [
74
+ /* @__PURE__ */ jsxRuntime.jsxs(
75
+ "svg",
76
+ {
77
+ viewBox,
78
+ width: size,
79
+ height: size,
80
+ xmlns: "http://www.w3.org/2000/svg",
81
+ style: {
82
+ transform: svgTransform,
83
+ transformOrigin: svgTransformOrigin,
84
+ opacity: animationOpacity
85
+ },
86
+ children: [
87
+ /* @__PURE__ */ jsxRuntime.jsx(
88
+ "path",
89
+ {
90
+ d: path,
91
+ fill: "none",
92
+ stroke: trailColor,
93
+ strokeWidth: effectiveTrailStrokeWidth
94
+ }
95
+ ),
96
+ /* @__PURE__ */ jsxRuntime.jsx(
97
+ "path",
98
+ {
99
+ d: path,
100
+ fill: "none",
101
+ stroke,
102
+ strokeLinecap,
103
+ strokeWidth,
104
+ strokeDasharray: pathLength,
105
+ strokeDashoffset,
106
+ style: {
107
+ transition: "stroke 0.5s ease"
108
+ }
109
+ }
110
+ )
111
+ ]
112
+ }
113
+ ),
114
+ typeof children === "function" && /* @__PURE__ */ jsxRuntime.jsx(
115
+ "div",
116
+ {
117
+ style: {
118
+ position: "absolute",
119
+ top: 0,
120
+ left: 0,
121
+ width: "100%",
122
+ height: "100%",
123
+ display: "flex",
124
+ justifyContent: "center",
125
+ alignItems: "center"
126
+ },
127
+ children: children(renderInfo)
128
+ }
129
+ )
130
+ ]
131
+ }
132
+ );
133
+ });
134
+ CountdownCircleTimer.displayName = "CountdownCircleTimer";
135
+ var TimerGroup = react.forwardRef(
136
+ (props, ref) => {
137
+ const {
138
+ mode = "sequential",
139
+ staggerDelay = 0,
140
+ isPlaying = false,
141
+ onGroupComplete,
142
+ onTimerComplete,
143
+ children
144
+ } = props;
145
+ const childArray = react.Children.toArray(children);
146
+ const timerCount = childArray.length;
147
+ const group = arctimerCore.useTimerGroup({
148
+ mode,
149
+ staggerDelay,
150
+ isPlaying,
151
+ timerCount,
152
+ onGroupComplete,
153
+ onTimerComplete
154
+ });
155
+ const { timers, playAll, pauseAll, resetAll } = group;
156
+ const handleTimerComplete = group._handleTimerComplete;
157
+ react.useImperativeHandle(
158
+ ref,
159
+ () => ({
160
+ playAll,
161
+ pauseAll,
162
+ resetAll
163
+ }),
164
+ [playAll, pauseAll, resetAll]
165
+ );
166
+ const contextValue = react.useMemo(
167
+ () => ({
168
+ mode,
169
+ isTimerPlaying: (index) => timers[index]?.isPlaying ?? false,
170
+ onTimerDone: handleTimerComplete,
171
+ registerTimer: () => {
172
+ }
173
+ }),
174
+ [mode, timers, handleTimerComplete]
175
+ );
176
+ const enhancedChildren = childArray.map((child, index) => {
177
+ if (!react.isValidElement(child)) return child;
178
+ const timerState = timers[index];
179
+ return react.cloneElement(child, {
180
+ key: index,
181
+ isPlaying: timerState?.isPlaying ?? false,
182
+ onComplete: (elapsed) => {
183
+ handleTimerComplete(index);
184
+ const originalOnComplete = child.props?.onComplete;
185
+ return originalOnComplete?.(elapsed);
186
+ }
187
+ });
188
+ });
189
+ return /* @__PURE__ */ jsxRuntime.jsx(arctimerCore.TimerGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", gap: 16, flexWrap: "wrap" }, children: enhancedChildren }) });
190
+ }
191
+ );
192
+ TimerGroup.displayName = "TimerGroup";
193
+
194
+ Object.defineProperty(exports, "useAnnouncer", {
195
+ enumerable: true,
196
+ get: function () { return arctimerCore.useAnnouncer; }
197
+ });
198
+ Object.defineProperty(exports, "useCountdown", {
199
+ enumerable: true,
200
+ get: function () { return arctimerCore.useCountdown; }
201
+ });
202
+ Object.defineProperty(exports, "useReducedMotion", {
203
+ enumerable: true,
204
+ get: function () { return arctimerCore.useReducedMotion; }
205
+ });
206
+ Object.defineProperty(exports, "useTimerGroup", {
207
+ enumerable: true,
208
+ get: function () { return arctimerCore.useTimerGroup; }
209
+ });
210
+ exports.CountdownCircleTimer = CountdownCircleTimer;
211
+ exports.TimerGroup = TimerGroup;
212
+ //# sourceMappingURL=index.cjs.map
213
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/CountdownCircleTimer.tsx","../src/TimerGroup.tsx"],"names":["forwardRef","useCountdown","useImperativeHandle","useMemo","jsxs","jsx","Children","useTimerGroup","isValidElement","cloneElement","TimerGroupContext"],"mappings":"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","file":"index.cjs","sourcesContent":["import { forwardRef, useImperativeHandle, useMemo } from 'react'\nimport { useCountdown } from '@toankhontech/arctimer-core'\nimport type { CountdownProps, TimerRef, RenderInfo } from '@toankhontech/arctimer-core'\n\nexport interface CountdownCircleTimerProps extends CountdownProps {\n style?: React.CSSProperties\n className?: string\n}\n\nexport const CountdownCircleTimer = forwardRef<\n TimerRef,\n CountdownCircleTimerProps\n>((props, ref) => {\n const {\n children,\n trailColor = '#d9d9d9',\n trailStrokeWidth,\n strokeLinecap = 'round',\n style,\n className,\n size = 180,\n strokeWidth = 12,\n ...restProps\n } = props\n\n const countdown = useCountdown({\n ...restProps,\n size,\n strokeWidth,\n })\n\n const {\n path,\n pathLength,\n stroke,\n strokeDashoffset,\n remainingTime,\n elapsedTime,\n progress,\n color,\n isComplete,\n animationScale,\n animationOpacity,\n _play,\n _pause,\n _reset,\n _getState,\n } = countdown\n\n useImperativeHandle(ref, () => ({\n play: _play,\n pause: _pause,\n reset: _reset,\n getState: _getState,\n }), [_play, _pause, _reset, _getState])\n\n const effectiveTrailStrokeWidth = trailStrokeWidth ?? strokeWidth\n const viewBox = `0 0 ${size} ${size}`\n\n const renderInfo: RenderInfo = useMemo(\n () => ({\n remainingTime,\n elapsedTime,\n color,\n progress,\n isComplete,\n }),\n [remainingTime, elapsedTime, color, progress, isComplete]\n )\n\n // Apply animation effects (bounce/pulse)\n const hasEffects = animationScale !== 1 || animationOpacity !== 1\n const svgTransform = hasEffects\n ? `scale(${animationScale})`\n : undefined\n const svgTransformOrigin = hasEffects ? 'center' : undefined\n\n return (\n <div\n style={{\n position: 'relative',\n width: size,\n height: size,\n ...style,\n }}\n className={className}\n >\n <svg\n viewBox={viewBox}\n width={size}\n height={size}\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{\n transform: svgTransform,\n transformOrigin: svgTransformOrigin,\n opacity: animationOpacity,\n }}\n >\n <path\n d={path}\n fill=\"none\"\n stroke={trailColor}\n strokeWidth={effectiveTrailStrokeWidth}\n />\n <path\n d={path}\n fill=\"none\"\n stroke={stroke}\n strokeLinecap={strokeLinecap}\n strokeWidth={strokeWidth}\n strokeDasharray={pathLength}\n strokeDashoffset={strokeDashoffset}\n style={{\n transition: 'stroke 0.5s ease',\n }}\n />\n </svg>\n {typeof children === 'function' && (\n <div\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n {children(renderInfo)}\n </div>\n )}\n </div>\n )\n})\n\nCountdownCircleTimer.displayName = 'CountdownCircleTimer'\n","import {\n forwardRef,\n useImperativeHandle,\n Children,\n cloneElement,\n isValidElement,\n useMemo,\n} from 'react'\nimport {\n useTimerGroup,\n TimerGroupContext,\n type TimerGroupProps,\n type TimerGroupRef,\n} from '@toankhontech/arctimer-core'\n\nexport const TimerGroup = forwardRef<TimerGroupRef, TimerGroupProps>(\n (props, ref) => {\n const {\n mode = 'sequential',\n staggerDelay = 0,\n isPlaying = false,\n onGroupComplete,\n onTimerComplete,\n children,\n } = props\n\n const childArray = Children.toArray(children)\n const timerCount = childArray.length\n\n const group = useTimerGroup({\n mode,\n staggerDelay,\n isPlaying,\n timerCount,\n onGroupComplete,\n onTimerComplete,\n })\n\n const { timers, playAll, pauseAll, resetAll } = group\n const handleTimerComplete = (group as any)._handleTimerComplete\n\n useImperativeHandle(\n ref,\n () => ({\n playAll,\n pauseAll,\n resetAll,\n }),\n [playAll, pauseAll, resetAll]\n )\n\n const contextValue = useMemo(\n () => ({\n mode,\n isTimerPlaying: (index: number) =>\n timers[index]?.isPlaying ?? false,\n onTimerDone: handleTimerComplete,\n registerTimer: () => {},\n }),\n [mode, timers, handleTimerComplete]\n )\n\n const enhancedChildren = childArray.map((child, index) => {\n if (!isValidElement(child)) return child\n\n const timerState = timers[index]\n return cloneElement(child as React.ReactElement<any>, {\n key: index,\n isPlaying: timerState?.isPlaying ?? false,\n onComplete: (elapsed: number) => {\n handleTimerComplete(index)\n const originalOnComplete = (child as any).props?.onComplete\n return originalOnComplete?.(elapsed)\n },\n })\n })\n\n return (\n <TimerGroupContext.Provider value={contextValue}>\n <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap' }}>\n {enhancedChildren}\n </div>\n </TimerGroupContext.Provider>\n )\n }\n)\n\nTimerGroup.displayName = 'TimerGroup'\n"]}
@@ -0,0 +1,13 @@
1
+ import * as react from 'react';
2
+ import { CountdownProps, TimerRef, TimerGroupProps, TimerGroupRef } from '@toankhontech/arctimer-core';
3
+ export { Color, ColorFormat, CountdownProps, EasingConfig, EasingName, OnCompleteResult, RenderInfo, Rotation, Theme, TimerGroupProps, TimerGroupRef, TimerRef, TimerStatus, UseCountdownReturn, UseTimerGroupReturn, useAnnouncer, useCountdown, useReducedMotion, useTimerGroup } from '@toankhontech/arctimer-core';
4
+
5
+ interface CountdownCircleTimerProps extends CountdownProps {
6
+ style?: React.CSSProperties;
7
+ className?: string;
8
+ }
9
+ declare const CountdownCircleTimer: react.ForwardRefExoticComponent<CountdownCircleTimerProps & react.RefAttributes<TimerRef>>;
10
+
11
+ declare const TimerGroup: react.ForwardRefExoticComponent<TimerGroupProps & react.RefAttributes<TimerGroupRef>>;
12
+
13
+ export { CountdownCircleTimer, type CountdownCircleTimerProps, TimerGroup };
@@ -0,0 +1,13 @@
1
+ import * as react from 'react';
2
+ import { CountdownProps, TimerRef, TimerGroupProps, TimerGroupRef } from '@toankhontech/arctimer-core';
3
+ export { Color, ColorFormat, CountdownProps, EasingConfig, EasingName, OnCompleteResult, RenderInfo, Rotation, Theme, TimerGroupProps, TimerGroupRef, TimerRef, TimerStatus, UseCountdownReturn, UseTimerGroupReturn, useAnnouncer, useCountdown, useReducedMotion, useTimerGroup } from '@toankhontech/arctimer-core';
4
+
5
+ interface CountdownCircleTimerProps extends CountdownProps {
6
+ style?: React.CSSProperties;
7
+ className?: string;
8
+ }
9
+ declare const CountdownCircleTimer: react.ForwardRefExoticComponent<CountdownCircleTimerProps & react.RefAttributes<TimerRef>>;
10
+
11
+ declare const TimerGroup: react.ForwardRefExoticComponent<TimerGroupProps & react.RefAttributes<TimerGroupRef>>;
12
+
13
+ export { CountdownCircleTimer, type CountdownCircleTimerProps, TimerGroup };
package/dist/index.js ADDED
@@ -0,0 +1,195 @@
1
+ import { forwardRef, useImperativeHandle, useMemo, Children, isValidElement, cloneElement } from 'react';
2
+ import { useCountdown, useTimerGroup, TimerGroupContext } from '@toankhontech/arctimer-core';
3
+ export { useAnnouncer, useCountdown, useReducedMotion, useTimerGroup } from '@toankhontech/arctimer-core';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ // src/CountdownCircleTimer.tsx
7
+ var CountdownCircleTimer = forwardRef((props, ref) => {
8
+ const {
9
+ children,
10
+ trailColor = "#d9d9d9",
11
+ trailStrokeWidth,
12
+ strokeLinecap = "round",
13
+ style,
14
+ className,
15
+ size = 180,
16
+ strokeWidth = 12,
17
+ ...restProps
18
+ } = props;
19
+ const countdown = useCountdown({
20
+ ...restProps,
21
+ size,
22
+ strokeWidth
23
+ });
24
+ const {
25
+ path,
26
+ pathLength,
27
+ stroke,
28
+ strokeDashoffset,
29
+ remainingTime,
30
+ elapsedTime,
31
+ progress,
32
+ color,
33
+ isComplete,
34
+ animationScale,
35
+ animationOpacity,
36
+ _play,
37
+ _pause,
38
+ _reset,
39
+ _getState
40
+ } = countdown;
41
+ useImperativeHandle(ref, () => ({
42
+ play: _play,
43
+ pause: _pause,
44
+ reset: _reset,
45
+ getState: _getState
46
+ }), [_play, _pause, _reset, _getState]);
47
+ const effectiveTrailStrokeWidth = trailStrokeWidth ?? strokeWidth;
48
+ const viewBox = `0 0 ${size} ${size}`;
49
+ const renderInfo = useMemo(
50
+ () => ({
51
+ remainingTime,
52
+ elapsedTime,
53
+ color,
54
+ progress,
55
+ isComplete
56
+ }),
57
+ [remainingTime, elapsedTime, color, progress, isComplete]
58
+ );
59
+ const hasEffects = animationScale !== 1 || animationOpacity !== 1;
60
+ const svgTransform = hasEffects ? `scale(${animationScale})` : void 0;
61
+ const svgTransformOrigin = hasEffects ? "center" : void 0;
62
+ return /* @__PURE__ */ jsxs(
63
+ "div",
64
+ {
65
+ style: {
66
+ position: "relative",
67
+ width: size,
68
+ height: size,
69
+ ...style
70
+ },
71
+ className,
72
+ children: [
73
+ /* @__PURE__ */ jsxs(
74
+ "svg",
75
+ {
76
+ viewBox,
77
+ width: size,
78
+ height: size,
79
+ xmlns: "http://www.w3.org/2000/svg",
80
+ style: {
81
+ transform: svgTransform,
82
+ transformOrigin: svgTransformOrigin,
83
+ opacity: animationOpacity
84
+ },
85
+ children: [
86
+ /* @__PURE__ */ jsx(
87
+ "path",
88
+ {
89
+ d: path,
90
+ fill: "none",
91
+ stroke: trailColor,
92
+ strokeWidth: effectiveTrailStrokeWidth
93
+ }
94
+ ),
95
+ /* @__PURE__ */ jsx(
96
+ "path",
97
+ {
98
+ d: path,
99
+ fill: "none",
100
+ stroke,
101
+ strokeLinecap,
102
+ strokeWidth,
103
+ strokeDasharray: pathLength,
104
+ strokeDashoffset,
105
+ style: {
106
+ transition: "stroke 0.5s ease"
107
+ }
108
+ }
109
+ )
110
+ ]
111
+ }
112
+ ),
113
+ typeof children === "function" && /* @__PURE__ */ jsx(
114
+ "div",
115
+ {
116
+ style: {
117
+ position: "absolute",
118
+ top: 0,
119
+ left: 0,
120
+ width: "100%",
121
+ height: "100%",
122
+ display: "flex",
123
+ justifyContent: "center",
124
+ alignItems: "center"
125
+ },
126
+ children: children(renderInfo)
127
+ }
128
+ )
129
+ ]
130
+ }
131
+ );
132
+ });
133
+ CountdownCircleTimer.displayName = "CountdownCircleTimer";
134
+ var TimerGroup = forwardRef(
135
+ (props, ref) => {
136
+ const {
137
+ mode = "sequential",
138
+ staggerDelay = 0,
139
+ isPlaying = false,
140
+ onGroupComplete,
141
+ onTimerComplete,
142
+ children
143
+ } = props;
144
+ const childArray = Children.toArray(children);
145
+ const timerCount = childArray.length;
146
+ const group = useTimerGroup({
147
+ mode,
148
+ staggerDelay,
149
+ isPlaying,
150
+ timerCount,
151
+ onGroupComplete,
152
+ onTimerComplete
153
+ });
154
+ const { timers, playAll, pauseAll, resetAll } = group;
155
+ const handleTimerComplete = group._handleTimerComplete;
156
+ useImperativeHandle(
157
+ ref,
158
+ () => ({
159
+ playAll,
160
+ pauseAll,
161
+ resetAll
162
+ }),
163
+ [playAll, pauseAll, resetAll]
164
+ );
165
+ const contextValue = useMemo(
166
+ () => ({
167
+ mode,
168
+ isTimerPlaying: (index) => timers[index]?.isPlaying ?? false,
169
+ onTimerDone: handleTimerComplete,
170
+ registerTimer: () => {
171
+ }
172
+ }),
173
+ [mode, timers, handleTimerComplete]
174
+ );
175
+ const enhancedChildren = childArray.map((child, index) => {
176
+ if (!isValidElement(child)) return child;
177
+ const timerState = timers[index];
178
+ return cloneElement(child, {
179
+ key: index,
180
+ isPlaying: timerState?.isPlaying ?? false,
181
+ onComplete: (elapsed) => {
182
+ handleTimerComplete(index);
183
+ const originalOnComplete = child.props?.onComplete;
184
+ return originalOnComplete?.(elapsed);
185
+ }
186
+ });
187
+ });
188
+ return /* @__PURE__ */ jsx(TimerGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: 16, flexWrap: "wrap" }, children: enhancedChildren }) });
189
+ }
190
+ );
191
+ TimerGroup.displayName = "TimerGroup";
192
+
193
+ export { CountdownCircleTimer, TimerGroup };
194
+ //# sourceMappingURL=index.js.map
195
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/CountdownCircleTimer.tsx","../src/TimerGroup.tsx"],"names":["forwardRef","useImperativeHandle","useMemo","jsx"],"mappings":"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","file":"index.js","sourcesContent":["import { forwardRef, useImperativeHandle, useMemo } from 'react'\nimport { useCountdown } from '@toankhontech/arctimer-core'\nimport type { CountdownProps, TimerRef, RenderInfo } from '@toankhontech/arctimer-core'\n\nexport interface CountdownCircleTimerProps extends CountdownProps {\n style?: React.CSSProperties\n className?: string\n}\n\nexport const CountdownCircleTimer = forwardRef<\n TimerRef,\n CountdownCircleTimerProps\n>((props, ref) => {\n const {\n children,\n trailColor = '#d9d9d9',\n trailStrokeWidth,\n strokeLinecap = 'round',\n style,\n className,\n size = 180,\n strokeWidth = 12,\n ...restProps\n } = props\n\n const countdown = useCountdown({\n ...restProps,\n size,\n strokeWidth,\n })\n\n const {\n path,\n pathLength,\n stroke,\n strokeDashoffset,\n remainingTime,\n elapsedTime,\n progress,\n color,\n isComplete,\n animationScale,\n animationOpacity,\n _play,\n _pause,\n _reset,\n _getState,\n } = countdown\n\n useImperativeHandle(ref, () => ({\n play: _play,\n pause: _pause,\n reset: _reset,\n getState: _getState,\n }), [_play, _pause, _reset, _getState])\n\n const effectiveTrailStrokeWidth = trailStrokeWidth ?? strokeWidth\n const viewBox = `0 0 ${size} ${size}`\n\n const renderInfo: RenderInfo = useMemo(\n () => ({\n remainingTime,\n elapsedTime,\n color,\n progress,\n isComplete,\n }),\n [remainingTime, elapsedTime, color, progress, isComplete]\n )\n\n // Apply animation effects (bounce/pulse)\n const hasEffects = animationScale !== 1 || animationOpacity !== 1\n const svgTransform = hasEffects\n ? `scale(${animationScale})`\n : undefined\n const svgTransformOrigin = hasEffects ? 'center' : undefined\n\n return (\n <div\n style={{\n position: 'relative',\n width: size,\n height: size,\n ...style,\n }}\n className={className}\n >\n <svg\n viewBox={viewBox}\n width={size}\n height={size}\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{\n transform: svgTransform,\n transformOrigin: svgTransformOrigin,\n opacity: animationOpacity,\n }}\n >\n <path\n d={path}\n fill=\"none\"\n stroke={trailColor}\n strokeWidth={effectiveTrailStrokeWidth}\n />\n <path\n d={path}\n fill=\"none\"\n stroke={stroke}\n strokeLinecap={strokeLinecap}\n strokeWidth={strokeWidth}\n strokeDasharray={pathLength}\n strokeDashoffset={strokeDashoffset}\n style={{\n transition: 'stroke 0.5s ease',\n }}\n />\n </svg>\n {typeof children === 'function' && (\n <div\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n }}\n >\n {children(renderInfo)}\n </div>\n )}\n </div>\n )\n})\n\nCountdownCircleTimer.displayName = 'CountdownCircleTimer'\n","import {\n forwardRef,\n useImperativeHandle,\n Children,\n cloneElement,\n isValidElement,\n useMemo,\n} from 'react'\nimport {\n useTimerGroup,\n TimerGroupContext,\n type TimerGroupProps,\n type TimerGroupRef,\n} from '@toankhontech/arctimer-core'\n\nexport const TimerGroup = forwardRef<TimerGroupRef, TimerGroupProps>(\n (props, ref) => {\n const {\n mode = 'sequential',\n staggerDelay = 0,\n isPlaying = false,\n onGroupComplete,\n onTimerComplete,\n children,\n } = props\n\n const childArray = Children.toArray(children)\n const timerCount = childArray.length\n\n const group = useTimerGroup({\n mode,\n staggerDelay,\n isPlaying,\n timerCount,\n onGroupComplete,\n onTimerComplete,\n })\n\n const { timers, playAll, pauseAll, resetAll } = group\n const handleTimerComplete = (group as any)._handleTimerComplete\n\n useImperativeHandle(\n ref,\n () => ({\n playAll,\n pauseAll,\n resetAll,\n }),\n [playAll, pauseAll, resetAll]\n )\n\n const contextValue = useMemo(\n () => ({\n mode,\n isTimerPlaying: (index: number) =>\n timers[index]?.isPlaying ?? false,\n onTimerDone: handleTimerComplete,\n registerTimer: () => {},\n }),\n [mode, timers, handleTimerComplete]\n )\n\n const enhancedChildren = childArray.map((child, index) => {\n if (!isValidElement(child)) return child\n\n const timerState = timers[index]\n return cloneElement(child as React.ReactElement<any>, {\n key: index,\n isPlaying: timerState?.isPlaying ?? false,\n onComplete: (elapsed: number) => {\n handleTimerComplete(index)\n const originalOnComplete = (child as any).props?.onComplete\n return originalOnComplete?.(elapsed)\n },\n })\n })\n\n return (\n <TimerGroupContext.Provider value={contextValue}>\n <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap' }}>\n {enhancedChildren}\n </div>\n </TimerGroupContext.Provider>\n )\n }\n)\n\nTimerGroup.displayName = 'TimerGroup'\n"]}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@toankhontech/arctimer-react",
3
+ "version": "0.0.0",
4
+ "description": "React web countdown circle timer component with SVG rendering",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": ["dist", "README.md"],
22
+ "sideEffects": false,
23
+ "scripts": {
24
+ "build": "tsup",
25
+ "dev": "tsup --watch",
26
+ "test": "vitest run",
27
+ "test:coverage": "vitest run --coverage",
28
+ "typecheck": "tsc --noEmit",
29
+ "clean": "rm -rf dist .turbo"
30
+ },
31
+ "dependencies": {
32
+ "@toankhontech/arctimer-core": "workspace:*"
33
+ },
34
+ "devDependencies": {
35
+ "@testing-library/react": "^16.1.0",
36
+ "@testing-library/jest-dom": "^6.6.0",
37
+ "@types/react": "^19.0.0",
38
+ "@types/react-dom": "^19.0.0",
39
+ "@vitest/coverage-v8": "^2.1.0",
40
+ "jsdom": "^25.0.0",
41
+ "react": "^19.0.0",
42
+ "react-dom": "^19.0.0",
43
+ "tsup": "^8.3.0",
44
+ "typescript": "^5.6.0",
45
+ "vitest": "^2.1.0"
46
+ },
47
+ "peerDependencies": {
48
+ "react": ">=18.0.0",
49
+ "react-dom": ">=18.0.0"
50
+ },
51
+ "keywords": ["react", "countdown", "timer", "circle", "svg", "web"],
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "https://github.com/toankhontech/arc-timer.git",
55
+ "directory": "packages/react"
56
+ },
57
+ "homepage": "https://github.com/toankhontech/arc-timer",
58
+ "bugs": {
59
+ "url": "https://github.com/toankhontech/arc-timer/issues"
60
+ },
61
+ "author": "toankhontech",
62
+ "license": "MIT"
63
+ }