server-time-timer-yolabs-ui 1.0.10 → 1.0.11

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.
@@ -1,12 +1,10 @@
1
- export declare function useServerTimer({ serverNow, endTime, onEnd }: {
2
- serverNow: string;
3
- endTime: string;
4
- onEnd?: () => void;
5
- }): {
1
+ type TimeState = {
2
+ totalMs: number;
6
3
  days: number;
7
4
  hours: number;
8
5
  minutes: number;
9
6
  seconds: number;
10
- totalMs: number;
11
7
  progress: number;
12
8
  };
9
+ export declare const useServerTimer: (endTime: string, onEnd?: () => void) => TimeState;
10
+ export {};
@@ -1,34 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useServerTimer = useServerTimer;
3
+ exports.useServerTimer = void 0;
4
4
  const react_1 = require("react");
5
5
  const server_time_timer_yolabs_1 = require("server-time-timer-yolabs");
6
- function useServerTimer({ serverNow, endTime, onEnd }) {
6
+ const useServerTimer = (endTime, onEnd) => {
7
7
  const [time, setTime] = (0, react_1.useState)({
8
+ totalMs: 0,
8
9
  days: 0,
9
10
  hours: 0,
10
11
  minutes: 0,
11
12
  seconds: 0,
12
- totalMs: 0,
13
- progress: 100
13
+ progress: 100,
14
14
  });
15
15
  (0, react_1.useEffect)(() => {
16
- const timer = (0, server_time_timer_yolabs_1.createServerTimer)({ serverNow, endTime });
17
- timer.onTick((t) => {
18
- const totalDuration = new Date(endTime).getTime() - new Date(serverNow).getTime();
19
- setTime({
20
- days: t.days,
21
- hours: t.hours,
22
- minutes: t.minutes,
23
- seconds: t.seconds,
24
- totalMs: t.totalMs,
25
- progress: Math.max(0, (t.totalMs / totalDuration) * 100)
26
- });
27
- if (t.totalMs <= 0 && onEnd)
28
- onEnd();
16
+ const timer = (0, server_time_timer_yolabs_1.createServerTimer)({
17
+ endTime,
18
+ onTick: setTime,
19
+ onEnd,
29
20
  });
30
21
  timer.start();
31
22
  return () => timer.stop();
32
- }, [serverNow, endTime, onEnd]);
23
+ }, [endTime, onEnd]);
33
24
  return time;
34
- }
25
+ };
26
+ exports.useServerTimer = useServerTimer;
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { ServerTimerUI } from './ui/ServerTimerUI';
2
- export type { ServerTimerUIProps } from './ui/types';
1
+ export * from './ui/ServerTimerUI';
2
+ export * from './ui/types';
package/dist/index.js CHANGED
@@ -1,5 +1,18 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ServerTimerUI = void 0;
4
- var ServerTimerUI_1 = require("./ui/ServerTimerUI");
5
- Object.defineProperty(exports, "ServerTimerUI", { enumerable: true, get: function () { return ServerTimerUI_1.ServerTimerUI; } });
17
+ __exportStar(require("./ui/ServerTimerUI"), exports);
18
+ __exportStar(require("./ui/types"), exports);
@@ -9,23 +9,14 @@ const TimerContainer_1 = __importDefault(require("./components/TimerContainer"))
9
9
  const TimerUnit_1 = __importDefault(require("./components/TimerUnit"));
10
10
  const TimerProgress_1 = __importDefault(require("./components/TimerProgress"));
11
11
  const useServerTimer_1 = require("../hooks/useServerTimer");
12
- const light_1 = require("./themes/light");
13
- const dark_1 = require("./themes/dark");
14
- const brand_1 = require("./themes/brand");
15
- const ServerTimerUI = ({ serverNow, endTime, size = 'md', layout = 'horizontal', theme = 'light', showProgress = true, customColors, showUnits = { days: true, hours: true, minutes: true, seconds: true }, onEnd }) => {
16
- var _a, _b, _c, _d;
17
- const time = (0, useServerTimer_1.useServerTimer)({ serverNow, endTime, onEnd });
18
- // 1️⃣ Base theme (ALWAYS defined)
19
- const baseTheme = theme === 'dark' ? dark_1.dark :
20
- theme === 'brand' ? brand_1.brand :
21
- light_1.light;
22
- // 2️⃣ Final resolved colors (NO undefined)
23
- const colors = {
24
- background: (_a = customColors === null || customColors === void 0 ? void 0 : customColors.background) !== null && _a !== void 0 ? _a : baseTheme.background,
25
- text: (_b = customColors === null || customColors === void 0 ? void 0 : customColors.text) !== null && _b !== void 0 ? _b : baseTheme.text,
26
- unitBackground: (_c = customColors === null || customColors === void 0 ? void 0 : customColors.unitBackground) !== null && _c !== void 0 ? _c : baseTheme.unitBackground,
27
- progress: (_d = customColors === null || customColors === void 0 ? void 0 : customColors.progress) !== null && _d !== void 0 ? _d : baseTheme.progress
12
+ const ServerTimerUI = ({ endTime, size = 'md', layout = 'horizontal', theme = 'light', showProgress = true, customColors = {}, showUnits = { days: true, hours: true, minutes: true, seconds: true }, numberSize = 'md', onEnd, className, }) => {
13
+ const time = (0, useServerTimer_1.useServerTimer)(endTime, onEnd);
14
+ const themeColors = {
15
+ light: { background: '#ffffff', text: '#323130', unitBackground: '#f3f2f1', progress: '#0078d4' },
16
+ dark: { background: '#323130', text: '#ffffff', unitBackground: '#505050', progress: '#0078d4' },
17
+ brand: { background: '#fef9f3', text: '#323130', unitBackground: '#fffbdd', progress: '#0078d4' },
28
18
  };
29
- return ((0, jsx_runtime_1.jsxs)(TimerContainer_1.default, { size: size, layout: layout, background: colors.background, color: colors.text, children: [showUnits.days && ((0, jsx_runtime_1.jsx)(TimerUnit_1.default, { label: "Days", value: time.days, size: size, layout: layout, background: colors.unitBackground, color: colors.text })), showUnits.hours && ((0, jsx_runtime_1.jsx)(TimerUnit_1.default, { label: "Hours", value: time.hours, size: size, layout: layout, background: colors.unitBackground, color: colors.text })), showUnits.minutes && ((0, jsx_runtime_1.jsx)(TimerUnit_1.default, { label: "Minutes", value: time.minutes, size: size, layout: layout, background: colors.unitBackground, color: colors.text })), showUnits.seconds && ((0, jsx_runtime_1.jsx)(TimerUnit_1.default, { label: "Seconds", value: time.seconds, size: size, layout: layout, background: colors.unitBackground, color: colors.text })), showProgress && ((0, jsx_runtime_1.jsx)(TimerProgress_1.default, { value: time.progress, color: colors.progress }))] }));
19
+ const colors = Object.assign(Object.assign({}, themeColors[theme]), customColors);
20
+ return ((0, jsx_runtime_1.jsxs)(TimerContainer_1.default, { size: size, layout: layout, background: colors.background, color: colors.text, className: className, children: [showUnits.days && (0, jsx_runtime_1.jsx)(TimerUnit_1.default, { label: "Days", value: time.days, size: size, background: colors.unitBackground, color: colors.text, numberSize: numberSize }), showUnits.hours && (0, jsx_runtime_1.jsx)(TimerUnit_1.default, { label: "Hours", value: time.hours, size: size, background: colors.unitBackground, color: colors.text, numberSize: numberSize }), showUnits.minutes && (0, jsx_runtime_1.jsx)(TimerUnit_1.default, { label: "Minutes", value: time.minutes, size: size, background: colors.unitBackground, color: colors.text, numberSize: numberSize }), showUnits.seconds && (0, jsx_runtime_1.jsx)(TimerUnit_1.default, { label: "Seconds", value: time.seconds, size: size, background: colors.unitBackground, color: colors.text, numberSize: numberSize }), showProgress && (0, jsx_runtime_1.jsx)(TimerProgress_1.default, { value: time.progress, color: colors.progress })] }));
30
21
  };
31
22
  exports.ServerTimerUI = ServerTimerUI;
@@ -1,11 +1,12 @@
1
1
  import React from 'react';
2
- import { TimerLayout, TimerSize } from '../types';
3
- interface Props {
2
+ import { TimerSize } from '../types';
3
+ interface TimerContainerProps {
4
4
  children: React.ReactNode;
5
- size: TimerSize;
6
- layout: TimerLayout;
7
- background: string;
8
- color: string;
5
+ size?: TimerSize;
6
+ className?: string;
7
+ background?: string;
8
+ color?: string;
9
+ layout?: 'horizontal' | 'vertical' | 'compact';
9
10
  }
10
- export default function TimerContainer({ children, size, layout, background, color }: Props): import("react/jsx-runtime").JSX.Element;
11
- export {};
11
+ declare const TimerContainer: React.FC<TimerContainerProps>;
12
+ export default TimerContainer;
@@ -1,26 +1,37 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = TimerContainer;
4
3
  const jsx_runtime_1 = require("react/jsx-runtime");
5
4
  const paddingMap = {
6
- sm: '6px 10px',
7
- md: '10px 16px',
8
- lg: '16px 22px'
5
+ sm: '0.5rem 1rem',
6
+ md: '1rem 1.5rem',
7
+ lg: '1.5rem 2rem',
8
+ };
9
+ const gapMap = {
10
+ horizontal: '0.625rem',
11
+ vertical: '0.625rem',
12
+ compact: '0.25rem',
9
13
  };
10
- function TimerContainer({ children, size, layout, background, color }) {
11
- return ((0, jsx_runtime_1.jsx)("div", { style: {
12
- display: 'flex',
13
- flexDirection: layout === 'vertical' ? 'column' : 'row',
14
- alignItems: 'center',
15
- justifyContent: 'center',
16
- gap: layout === 'compact' ? '4px' : '10px',
17
- padding: paddingMap[size],
18
- background,
19
- color,
20
- border: '1px solid #e1e1e1',
21
- borderRadius: 4,
22
- fontFamily: `'Segoe UI', system-ui`,
23
- flexWrap: 'wrap',
24
- maxWidth: '100%'
25
- }, children: children }));
26
- }
14
+ const TimerContainer = ({ children, size = 'md', className = '', background = '#ffffff', color = '#323130', layout = 'horizontal', }) => {
15
+ const getFlexStyles = () => {
16
+ switch (layout) {
17
+ case 'vertical':
18
+ return {
19
+ flexDirection: 'column',
20
+ flexWrap: 'nowrap',
21
+ };
22
+ case 'compact':
23
+ return {
24
+ flexDirection: 'row',
25
+ flexWrap: 'wrap',
26
+ };
27
+ default: // horizontal
28
+ return {
29
+ flexDirection: 'row',
30
+ flexWrap: 'nowrap',
31
+ };
32
+ }
33
+ };
34
+ const flexStyles = getFlexStyles();
35
+ return ((0, jsx_runtime_1.jsx)("div", { className: `timer-container ${className}`, style: Object.assign(Object.assign({ display: 'flex' }, flexStyles), { alignItems: 'center', justifyContent: 'center', gap: gapMap[layout], backgroundColor: background, color: color, border: '1px solid #e1e1e1', borderRadius: '4px', padding: paddingMap[size], fontFamily: `'Segoe UI', -apple-system, BlinkMacSystemFont, sans-serif`, fontSize: '1rem', overflow: 'hidden', transition: 'all 0.2s ease', boxSizing: 'border-box', minWidth: layout === 'compact' ? 'fit-content' : undefined }), role: "timer", "aria-label": "timer container", children: children }));
36
+ };
37
+ exports.default = TimerContainer;
@@ -1,4 +1,27 @@
1
- export default function TimerProgress({ value, color }: {
1
+ import React from 'react';
2
+ interface TimerProgressProps {
3
+ /** Current progress value (0-100) */
2
4
  value: number;
3
- color: string;
4
- }): import("react/jsx-runtime").JSX.Element;
5
+ /** Color of the progress bar */
6
+ color?: string;
7
+ /** Height of the progress bar */
8
+ height?: number | string;
9
+ /** Background color of the track */
10
+ trackColor?: string;
11
+ /** Border radius of the progress bar */
12
+ borderRadius?: number | string;
13
+ /** Whether to show an animated glow effect */
14
+ animated?: boolean;
15
+ /** Animation duration for value changes (ms) */
16
+ animationDuration?: number;
17
+ /** Optional label text */
18
+ label?: string;
19
+ /** Show percentage text */
20
+ showPercentage?: boolean;
21
+ /** Custom CSS class */
22
+ className?: string;
23
+ /** Callback when progress reaches 100% */
24
+ onComplete?: () => void;
25
+ }
26
+ declare const TimerProgress: React.FC<TimerProgressProps>;
27
+ export default TimerProgress;
@@ -1,12 +1,91 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = TimerProgress;
4
3
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- function TimerProgress({ value, color }) {
6
- return ((0, jsx_runtime_1.jsx)("div", { style: { width: '100%', height: 4, background: '#e1e1e1', borderRadius: 2 }, children: (0, jsx_runtime_1.jsx)("div", { style: {
7
- width: `${value}%`,
8
- height: '100%',
9
- background: color,
10
- transition: 'width 0.3s linear'
11
- } }) }));
12
- }
4
+ const react_1 = require("react");
5
+ const TimerProgress = ({ value, color = '#0078d4', height = 8, trackColor = '#e1e1e1', borderRadius = 4, animated = true, animationDuration = 300, label, showPercentage = false, className = '', onComplete, }) => {
6
+ const progressRef = (0, react_1.useRef)(null);
7
+ const previousValueRef = (0, react_1.useRef)(value);
8
+ const isCompleteRef = (0, react_1.useRef)(false);
9
+ // Handle completion callback
10
+ (0, react_1.useEffect)(() => {
11
+ if (value >= 100 && !isCompleteRef.current && onComplete) {
12
+ isCompleteRef.current = true;
13
+ onComplete();
14
+ }
15
+ else if (value < 100) {
16
+ isCompleteRef.current = false;
17
+ }
18
+ }, [value, onComplete]);
19
+ // Handle animation
20
+ (0, react_1.useEffect)(() => {
21
+ if (progressRef.current && animated) {
22
+ progressRef.current.style.transition = `width ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1)`;
23
+ }
24
+ }, [animated, animationDuration]);
25
+ // Calculate percentage for display
26
+ const displayValue = Math.max(0, Math.min(100, value));
27
+ const percentageText = `${Math.round(displayValue)}%`;
28
+ // Determine if we should show label
29
+ const shouldShowLabel = label || showPercentage;
30
+ return ((0, jsx_runtime_1.jsxs)("div", { className: `timer-progress ${className}`, style: {
31
+ width: '100%',
32
+ display: 'flex',
33
+ flexDirection: 'column',
34
+ gap: '4px',
35
+ }, role: "progressbar", "aria-valuenow": displayValue, "aria-valuemin": 0, "aria-valuemax": 100, "aria-label": label || "Progress", children: [shouldShowLabel && ((0, jsx_runtime_1.jsxs)("div", { style: {
36
+ display: 'flex',
37
+ justifyContent: 'space-between',
38
+ alignItems: 'center',
39
+ fontSize: '0.875rem',
40
+ color: '#666',
41
+ }, children: [label && (0, jsx_runtime_1.jsx)("span", { children: label }), showPercentage && (0, jsx_runtime_1.jsx)("span", { children: percentageText })] })), (0, jsx_runtime_1.jsxs)("div", { style: {
42
+ width: '100%',
43
+ height: typeof height === 'number' ? `${height}px` : height,
44
+ backgroundColor: trackColor,
45
+ borderRadius: typeof borderRadius === 'number' ? `${borderRadius}px` : borderRadius,
46
+ overflow: 'hidden',
47
+ position: 'relative',
48
+ }, children: [(0, jsx_runtime_1.jsx)("div", { ref: progressRef, style: {
49
+ width: `${displayValue}%`,
50
+ height: '100%',
51
+ backgroundColor: color,
52
+ borderRadius: typeof borderRadius === 'number' ? `${borderRadius}px` : borderRadius,
53
+ transition: animated ? undefined : 'none',
54
+ } }), animated && value > 0 && value < 100 && ((0, jsx_runtime_1.jsx)("div", { style: {
55
+ position: 'absolute',
56
+ top: 0,
57
+ left: 0,
58
+ width: '100%',
59
+ height: '100%',
60
+ background: `linear-gradient(90deg,
61
+ transparent 0%,
62
+ rgba(255, 255, 255, 0.3) 50%,
63
+ transparent 100%)`,
64
+ backgroundSize: '200% 100%',
65
+ animation: 'shimmer 2s infinite',
66
+ opacity: 0.6,
67
+ pointerEvents: 'none',
68
+ } })), value >= 100 && animated && ((0, jsx_runtime_1.jsx)("div", { style: {
69
+ position: 'absolute',
70
+ top: 0,
71
+ left: 0,
72
+ width: '100%',
73
+ height: '100%',
74
+ backgroundColor: color,
75
+ borderRadius: typeof borderRadius === 'number' ? `${borderRadius}px` : borderRadius,
76
+ animation: 'pulse 1.5s infinite',
77
+ opacity: 0.5,
78
+ pointerEvents: 'none',
79
+ } }))] }), (0, jsx_runtime_1.jsx)("style", { children: `
80
+ @keyframes shimmer {
81
+ 0% { transform: translateX(-100%); }
82
+ 100% { transform: translateX(100%); }
83
+ }
84
+
85
+ @keyframes pulse {
86
+ 0%, 100% { opacity: 0.5; }
87
+ 50% { opacity: 0.8; }
88
+ }
89
+ ` })] }));
90
+ };
91
+ exports.default = TimerProgress;
@@ -1,11 +1,12 @@
1
- import { TimerLayout, TimerSize } from '../types';
2
- interface Props {
1
+ import React from 'react';
2
+ import { TimerSize } from '../types';
3
+ interface TimerUnitProps {
3
4
  label: string;
4
5
  value: number;
5
- size: TimerSize;
6
- layout: TimerLayout;
7
- background: string;
8
- color: string;
6
+ size?: TimerSize;
7
+ background?: string;
8
+ color?: string;
9
+ numberSize?: 'sm' | 'md' | 'lg';
9
10
  }
10
- export default function TimerUnit({ label, value, size, layout, background, color }: Props): import("react/jsx-runtime").JSX.Element;
11
- export {};
11
+ declare const TimerUnit: React.FC<TimerUnitProps>;
12
+ export default TimerUnit;
@@ -1,36 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = TimerUnit;
4
3
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const numberSizeMap = {
6
- sm: '0.9rem',
7
- md: '1.2rem',
8
- lg: '1.6rem'
9
- };
10
- const minWidthMap = {
11
- sm: '2ch',
12
- md: '2.5ch',
13
- lg: '3ch'
14
- };
15
- function TimerUnit({ label, value, size, layout, background, color }) {
16
- return ((0, jsx_runtime_1.jsxs)("div", { role: "group", "aria-label": label, style: {
17
- display: 'flex',
18
- flexDirection: layout === 'compact' ? 'row' : 'column',
19
- alignItems: 'center',
20
- padding: '6px 8px',
21
- background,
22
- borderRadius: 4,
23
- minWidth: layout === 'compact' ? 'auto' : '64px'
24
- }, children: [(0, jsx_runtime_1.jsx)("span", { "aria-live": "polite", "aria-atomic": "true", style: {
25
- fontSize: numberSizeMap[size],
26
- fontWeight: 600,
27
- fontFamily: `'Segoe UI Mono', Consolas, monospace`,
28
- minWidth: minWidthMap[size],
29
- textAlign: 'center',
30
- transition: 'transform 0.15s ease, opacity 0.15s ease'
31
- }, children: value.toString().padStart(2, '0') }), layout !== 'compact' && ((0, jsx_runtime_1.jsx)("span", { style: {
32
- fontSize: '0.7rem',
33
- opacity: 0.75,
34
- marginTop: 2
35
- }, children: label }))] }));
36
- }
4
+ const fontSizeMap = { sm: '0.9rem', md: '1.2rem', lg: '1.5rem' };
5
+ const TimerUnit = ({ label, value, size = 'md', background = '#f3f2f1', color = '#323130', numberSize = 'md', }) => ((0, jsx_runtime_1.jsxs)("div", { style: {
6
+ backgroundColor: background,
7
+ color,
8
+ padding: '0.5rem',
9
+ borderRadius: '4px',
10
+ textAlign: 'center',
11
+ minWidth: '50px',
12
+ }, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontSize: fontSizeMap[numberSize], fontWeight: 'bold' }, children: value.toString().padStart(2, '0') }), (0, jsx_runtime_1.jsx)("div", { style: { fontSize: '0.8rem' }, children: label })] }));
13
+ exports.default = TimerUnit;
@@ -14,7 +14,6 @@ export interface ShowUnits {
14
14
  seconds?: boolean;
15
15
  }
16
16
  export interface ServerTimerUIProps {
17
- serverNow: string;
18
17
  endTime: string;
19
18
  size?: TimerSize;
20
19
  layout?: TimerLayout;
@@ -23,4 +22,6 @@ export interface ServerTimerUIProps {
23
22
  customColors?: CustomColors;
24
23
  showUnits?: ShowUnits;
25
24
  onEnd?: () => void;
25
+ className?: string;
26
+ numberSize?: 'sm' | 'md' | 'lg';
26
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "server-time-timer-yolabs-ui",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "description": "FluentUI/SharePoint styled React countdown timer UI for server-time-timer-yoLabs",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -33,7 +33,7 @@
33
33
  "license": "yolabs",
34
34
  "author": "Yonas <+251930327375>",
35
35
  "dependencies": {
36
- "server-time-timer-yolabs": "^1.0.2"
36
+ "server-time-timer-yolabs": "^1.0.4"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/react": "^19.2.7",