@gfazioli/mantine-clock 2.1.17 → 3.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.
Files changed (41) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/Clock.cjs +611 -446
  3. package/dist/cjs/Clock.cjs.map +1 -1
  4. package/dist/cjs/Clock.module.css.cjs +1 -1
  5. package/dist/cjs/ClockDigital.cjs +125 -0
  6. package/dist/cjs/ClockDigital.cjs.map +1 -0
  7. package/dist/cjs/ClockDigital.module.css.cjs +7 -0
  8. package/dist/cjs/ClockDigital.module.css.cjs.map +1 -0
  9. package/dist/cjs/geometry.cjs +217 -0
  10. package/dist/cjs/geometry.cjs.map +1 -0
  11. package/dist/cjs/hooks/use-clock-count-down.cjs +90 -122
  12. package/dist/cjs/hooks/use-clock-count-down.cjs.map +1 -1
  13. package/dist/cjs/hooks/use-clock.cjs +25 -36
  14. package/dist/cjs/hooks/use-clock.cjs.map +1 -1
  15. package/dist/cjs/index.cjs +6 -0
  16. package/dist/cjs/index.cjs.map +1 -1
  17. package/dist/esm/Clock.mjs +613 -448
  18. package/dist/esm/Clock.mjs.map +1 -1
  19. package/dist/esm/Clock.module.css.mjs +1 -1
  20. package/dist/esm/ClockDigital.mjs +123 -0
  21. package/dist/esm/ClockDigital.mjs.map +1 -0
  22. package/dist/esm/ClockDigital.module.css.mjs +5 -0
  23. package/dist/esm/ClockDigital.module.css.mjs.map +1 -0
  24. package/dist/esm/geometry.mjs +208 -0
  25. package/dist/esm/geometry.mjs.map +1 -0
  26. package/dist/esm/hooks/use-clock-count-down.mjs +90 -122
  27. package/dist/esm/hooks/use-clock-count-down.mjs.map +1 -1
  28. package/dist/esm/hooks/use-clock.mjs +25 -36
  29. package/dist/esm/hooks/use-clock.mjs.map +1 -1
  30. package/dist/esm/index.mjs +2 -0
  31. package/dist/esm/index.mjs.map +1 -1
  32. package/dist/styles.css +2 -2
  33. package/dist/styles.layer.css +2 -2
  34. package/dist/types/Clock.d.ts +70 -1
  35. package/dist/types/ClockDigital.d.ts +50 -0
  36. package/dist/types/geometry.d.ts +92 -0
  37. package/dist/types/hooks/use-clock-count-down.d.ts +25 -28
  38. package/dist/types/hooks/use-clock.d.ts +14 -10
  39. package/dist/types/index.d.mts +5 -1
  40. package/dist/types/index.d.ts +5 -1
  41. package/package.json +5 -3
@@ -2,12 +2,19 @@
2
2
  import dayjs from 'dayjs';
3
3
  import timezonePlugin from 'dayjs/plugin/timezone';
4
4
  import utc from 'dayjs/plugin/utc';
5
- import React, { useState, useRef, useEffect } from 'react';
6
- import { createVarsResolver, px, getSize, parseThemeColor, factory, useProps, useStyles, Box, Text } from '@mantine/core';
5
+ import React, { useState, useEffect, useRef, useMemo } from 'react';
6
+ import { createVarsResolver, px, getSize, Box, Text, factory, useProps, useStyles, parseThemeColor } from '@mantine/core';
7
+ import { useCallbackRef, useMergedRef } from '@mantine/hooks';
8
+ import { ClockDigital } from './ClockDigital.mjs';
9
+ import { hourAngleFromDate, minuteAngleFromDate, secondAngleFromDate, createGeometry } from './geometry.mjs';
7
10
  import classes from './Clock.module.css.mjs';
8
11
 
9
12
  dayjs.extend(utc);
10
13
  dayjs.extend(timezonePlugin);
14
+ const TICK_OFFSET_RATIO = 0.028;
15
+ const CENTER_DOT_RATIO = 0.034;
16
+ const COUNTERWEIGHT_MULTIPLIER = 3;
17
+ const round2 = (n) => Math.round(n * 100) / 100;
11
18
  const defaultProps = {
12
19
  size: 400,
13
20
  hourHandSize: 0.017,
@@ -19,6 +26,7 @@ const defaultProps = {
19
26
  secondHandOpacity: 1,
20
27
  minuteHandOpacity: 1,
21
28
  hourHandOpacity: 1,
29
+ secondHandBehavior: "tick",
22
30
  running: true
23
31
  };
24
32
  const defaultClockSizes = {
@@ -28,83 +36,37 @@ const defaultClockSizes = {
28
36
  lg: 480,
29
37
  xl: 512
30
38
  };
31
- const varsResolver = createVarsResolver(
32
- (theme, {
33
- size,
34
- color,
35
- hourTicksColor,
36
- hourTicksOpacity,
37
- minuteTicksColor,
38
- minuteTicksOpacity,
39
- primaryNumbersColor,
40
- primaryNumbersOpacity,
41
- secondaryNumbersColor,
42
- secondaryNumbersOpacity,
43
- secondHandColor,
44
- minuteHandColor,
45
- hourHandColor,
46
- secondsArcColor,
47
- minutesArcColor,
48
- hoursArcColor
49
- }) => {
50
- const sizeValue = size || "md";
51
- const clockSize = typeof sizeValue === "string" && sizeValue in defaultClockSizes ? defaultClockSizes[sizeValue] : sizeValue;
52
- const effectiveSize = Math.round(px(getSize(clockSize, "clock-size")));
53
- return {
54
- root: {
55
- "--clock-size": `${effectiveSize}px`,
56
- "--clock-color": parseThemeColor({
57
- color: color || "",
58
- theme
59
- }).value,
60
- "--clock-hour-ticks-color": parseThemeColor({
61
- color: hourTicksColor || "",
62
- theme
63
- }).value,
64
- "--clock-hour-ticks-opacity": (Math.round((hourTicksOpacity || 1) * 100) / 100).toString(),
65
- "--clock-minute-ticks-color": parseThemeColor({
66
- color: minuteTicksColor || "",
67
- theme
68
- }).value,
69
- "--clock-minute-ticks-opacity": (Math.round((minuteTicksOpacity || 1) * 100) / 100).toString(),
70
- "--clock-primary-numbers-color": parseThemeColor({
71
- color: primaryNumbersColor || "",
72
- theme
73
- }).value,
74
- "--clock-primary-numbers-opacity": (Math.round((primaryNumbersOpacity || 1) * 100) / 100).toString(),
75
- "--clock-secondary-numbers-color": parseThemeColor({
76
- color: secondaryNumbersColor || "",
77
- theme
78
- }).value,
79
- "--clock-secondary-numbers-opacity": (Math.round((secondaryNumbersOpacity || 1) * 100) / 100).toString(),
80
- "--clock-second-hand-color": parseThemeColor({
81
- color: secondHandColor || "",
82
- theme
83
- }).value,
84
- "--clock-minute-hand-color": parseThemeColor({
85
- color: minuteHandColor || "",
86
- theme
87
- }).value,
88
- "--clock-hour-hand-color": parseThemeColor({
89
- color: hourHandColor || "",
90
- theme
91
- }).value,
92
- "--clock-seconds-arc-color": parseThemeColor({
93
- color: secondsArcColor || secondHandColor || "",
94
- theme
95
- }).value,
96
- "--clock-minutes-arc-color": parseThemeColor({
97
- color: minutesArcColor || minuteHandColor || "",
98
- theme
99
- }).value,
100
- "--clock-hours-arc-color": parseThemeColor({
101
- color: hoursArcColor || hourHandColor || "",
102
- theme
103
- }).value
104
- }
105
- };
39
+ const buildCssVars = (theme, clockSizePx, props) => {
40
+ const c = (color) => parseThemeColor({ color, theme }).value;
41
+ return {
42
+ "--clock-size": clockSizePx,
43
+ "--clock-color": c(props.color || ""),
44
+ "--clock-hour-ticks-color": c(props.hourTicksColor || ""),
45
+ "--clock-hour-ticks-opacity": round2(props.hourTicksOpacity ?? 1).toString(),
46
+ "--clock-minute-ticks-color": c(props.minuteTicksColor || ""),
47
+ "--clock-minute-ticks-opacity": round2(props.minuteTicksOpacity ?? 1).toString(),
48
+ "--clock-primary-numbers-color": c(props.primaryNumbersColor || ""),
49
+ "--clock-primary-numbers-opacity": round2(props.primaryNumbersOpacity ?? 1).toString(),
50
+ "--clock-secondary-numbers-color": c(props.secondaryNumbersColor || ""),
51
+ "--clock-secondary-numbers-opacity": round2(props.secondaryNumbersOpacity ?? 1).toString(),
52
+ "--clock-second-hand-color": c(props.secondHandColor || ""),
53
+ "--clock-minute-hand-color": c(props.minuteHandColor || ""),
54
+ "--clock-hour-hand-color": c(props.hourHandColor || ""),
55
+ "--clock-seconds-arc-color": c(props.secondsArcColor || props.secondHandColor || ""),
56
+ "--clock-minutes-arc-color": c(props.minutesArcColor || props.minuteHandColor || ""),
57
+ "--clock-hours-arc-color": c(props.hoursArcColor || props.hourHandColor || "")
58
+ };
59
+ };
60
+ const varsResolver = createVarsResolver((theme, props) => {
61
+ const { size } = props;
62
+ if (size === "auto") {
63
+ return { root: buildCssVars(theme, "400px", props) };
106
64
  }
107
- );
65
+ const sizeValue = size || "md";
66
+ const clockSize = typeof sizeValue === "string" && sizeValue in defaultClockSizes ? defaultClockSizes[sizeValue] : sizeValue;
67
+ const effectiveSize = Math.round(px(getSize(clockSize, "clock-size")));
68
+ return { root: buildCssVars(theme, `${effectiveSize}px`, props) };
69
+ });
108
70
  const parseTimeValue = (value) => {
109
71
  if (!value) {
110
72
  return null;
@@ -133,12 +95,99 @@ const parseTimeValue = (value) => {
133
95
  }
134
96
  return null;
135
97
  };
136
- const RealClock = (props) => {
98
+ const ClockFaceStatic = React.memo(
99
+ ({
100
+ getStyles,
101
+ effectiveSize,
102
+ geometry,
103
+ hourTicksOpacity,
104
+ minuteTicksOpacity,
105
+ primaryNumbersOpacity,
106
+ secondaryNumbersOpacity,
107
+ hourNumbersDistance = 0.75,
108
+ primaryNumbersProps,
109
+ secondaryNumbersProps
110
+ }) => {
111
+ const clockRadius = Math.round(effectiveSize / 2);
112
+ const numberRadius = Math.round(clockRadius * hourNumbersDistance);
113
+ const tickOffset = Math.round(effectiveSize * TICK_OFFSET_RATIO);
114
+ return /* @__PURE__ */ React.createElement(Box, { ...getStyles("hourMarks") }, (hourTicksOpacity ?? 1) !== 0 && Array.from({ length: 12 }, (_, i) => {
115
+ const pos = geometry.tickPosition(i, 12, tickOffset);
116
+ const tickStyle = pos.positioning === "absolute" ? {
117
+ top: pos.y,
118
+ left: pos.x,
119
+ transformOrigin: pos.transformOrigin,
120
+ transform: `translate(-50%, -50%) rotate(${pos.angle}deg)`
121
+ } : {
122
+ top: pos.y,
123
+ left: "50%",
124
+ transformOrigin: pos.transformOrigin,
125
+ transform: `translateX(-50%) rotate(${pos.angle}deg)`
126
+ };
127
+ return /* @__PURE__ */ React.createElement(Box, { key: `hour-tick-${i}`, ...getStyles("hourTick", { style: tickStyle }) });
128
+ }), (minuteTicksOpacity ?? 1) !== 0 && Array.from({ length: 60 }, (_, i) => {
129
+ if (i % 5 === 0) {
130
+ return null;
131
+ }
132
+ const pos = geometry.tickPosition(i, 60, tickOffset);
133
+ const tickStyle = pos.positioning === "absolute" ? {
134
+ top: pos.y,
135
+ left: pos.x,
136
+ transformOrigin: pos.transformOrigin,
137
+ transform: `translate(-50%, -50%) rotate(${pos.angle}deg)`
138
+ } : {
139
+ top: pos.y,
140
+ left: "50%",
141
+ transformOrigin: pos.transformOrigin,
142
+ transform: `translateX(-50%) rotate(${pos.angle}deg)`
143
+ };
144
+ return /* @__PURE__ */ React.createElement(Box, { key: `minute-tick-${i}`, ...getStyles("minuteTick", { style: tickStyle }) });
145
+ }), (primaryNumbersOpacity ?? 1) !== 0 && [12, 3, 6, 9].map((num) => {
146
+ const hourIndex = num === 12 ? 0 : num;
147
+ const pos = geometry.numberPosition(hourIndex, numberRadius);
148
+ return /* @__PURE__ */ React.createElement(
149
+ Text,
150
+ {
151
+ key: `primary-number-${num}`,
152
+ ...primaryNumbersProps,
153
+ ...getStyles("primaryNumber", {
154
+ className: getStyles("number").className,
155
+ style: {
156
+ left: pos.x,
157
+ top: pos.y
158
+ }
159
+ })
160
+ },
161
+ num
162
+ );
163
+ }), (secondaryNumbersOpacity ?? 1) !== 0 && [1, 2, 4, 5, 7, 8, 10, 11].map((num) => {
164
+ const pos = geometry.numberPosition(num, numberRadius);
165
+ return /* @__PURE__ */ React.createElement(
166
+ Text,
167
+ {
168
+ key: `secondary-number-${num}`,
169
+ ...secondaryNumbersProps,
170
+ ...getStyles("secondaryNumber", {
171
+ className: getStyles("number").className,
172
+ style: {
173
+ left: pos.x,
174
+ top: pos.y
175
+ }
176
+ })
177
+ },
178
+ num
179
+ );
180
+ }));
181
+ }
182
+ );
183
+ ClockFaceStatic.displayName = "ClockFaceStatic";
184
+ const RealClock = React.memo((props) => {
137
185
  const {
138
186
  time,
139
187
  timezone: timezone2,
140
188
  getStyles,
141
189
  effectiveSize,
190
+ geometry,
142
191
  hourHandSize,
143
192
  minuteHandSize,
144
193
  secondHandSize,
@@ -168,7 +217,14 @@ const RealClock = (props) => {
168
217
  hoursArcDirection = "clockwise",
169
218
  secondsArcOpacity,
170
219
  minutesArcOpacity,
171
- hoursArcOpacity
220
+ hoursArcOpacity,
221
+ renderHourHand,
222
+ renderMinuteHand,
223
+ renderSecondHand,
224
+ sectors,
225
+ faceContent,
226
+ animateOnMount,
227
+ animateOnMountDuration
172
228
  } = props;
173
229
  const timezoneTime = timezone2 && timezone2 !== "" ? dayjs(time).tz(timezone2) : dayjs(time);
174
230
  const hours = timezoneTime.hour() % 12;
@@ -179,9 +235,6 @@ const RealClock = (props) => {
179
235
  const minuteAngle = minutes * 6;
180
236
  let secondAngle = 0;
181
237
  switch (secondHandBehavior) {
182
- case "tick":
183
- secondAngle = seconds * 6;
184
- break;
185
238
  case "tick-half":
186
239
  secondAngle = (seconds + Math.floor(milliseconds / 500) * 0.5) * 6;
187
240
  break;
@@ -189,303 +242,319 @@ const RealClock = (props) => {
189
242
  secondAngle = (seconds + Math.floor(milliseconds / 125) * 0.125) * 6;
190
243
  break;
191
244
  case "smooth":
192
- default:
193
245
  secondAngle = (seconds + milliseconds / 1e3) * 6;
194
246
  break;
247
+ case "tick":
248
+ default:
249
+ secondAngle = seconds * 6;
250
+ break;
195
251
  }
252
+ const [mountPhase, setMountPhase] = useState(
253
+ animateOnMount ? "initial" : "done"
254
+ );
255
+ useEffect(() => {
256
+ if (mountPhase === "initial") {
257
+ const rafId = requestAnimationFrame(() => {
258
+ setMountPhase("animating");
259
+ });
260
+ return () => cancelAnimationFrame(rafId);
261
+ } else if (mountPhase === "animating") {
262
+ const timer = setTimeout(
263
+ () => {
264
+ setMountPhase("done");
265
+ },
266
+ (animateOnMountDuration ?? 1e3) + 50
267
+ );
268
+ return () => clearTimeout(timer);
269
+ }
270
+ }, [mountPhase, animateOnMountDuration]);
271
+ const showTransition = mountPhase === "animating";
272
+ const handAngles = mountPhase === "initial" ? { hour: 0, minute: 0, second: 0 } : { hour: round2(hourAngle), minute: round2(minuteAngle), second: round2(secondAngle) };
273
+ const transitionStyle = showTransition ? {
274
+ transition: `transform ${animateOnMountDuration ?? 1e3}ms cubic-bezier(0.34, 1.56, 0.64, 1)`
275
+ } : void 0;
196
276
  const size = effectiveSize;
197
- const clockRadius = Math.round(size / 2);
198
- const numberRadius = Math.round(clockRadius * hourNumbersDistance);
199
- const calculatedHourHandLength = Math.round(
200
- clockRadius * (hourHandLength ?? defaultProps.hourHandLength)
277
+ const { centerX, centerY } = geometry;
278
+ const calculatedHourHandLength = geometry.handLength(
279
+ hourHandLength ?? defaultProps.hourHandLength
201
280
  );
202
- const calculatedMinuteHandLength = Math.round(
203
- clockRadius * (minuteHandLength ?? defaultProps.minuteHandLength)
281
+ const calculatedMinuteHandLength = geometry.handLength(
282
+ minuteHandLength ?? defaultProps.minuteHandLength
204
283
  );
205
- const calculatedSecondHandLength = Math.round(
206
- clockRadius * (secondHandLength ?? defaultProps.secondHandLength)
284
+ const calculatedSecondHandLength = geometry.handLength(
285
+ secondHandLength ?? defaultProps.secondHandLength
207
286
  );
208
- const centerSize = Math.round(size * 0.034);
209
- const tickOffset = Math.round(size * 0.028);
210
- const toClockAngle = (deg) => (deg % 360 + 360) % 360;
211
- const secAngleFromDate = (d) => {
212
- if (!d) {
213
- return 0;
214
- }
215
- const dt = timezone2 && timezone2 !== "" ? dayjs(d).tz(timezone2) : dayjs(d);
216
- const s = dt.second();
217
- const ms = dt.millisecond();
218
- return toClockAngle((s + ms / 1e3) * 6);
219
- };
220
- const minAngleFromDate = (d) => {
221
- if (!d) {
222
- return 0;
223
- }
224
- const dt = timezone2 && timezone2 !== "" ? dayjs(d).tz(timezone2) : dayjs(d);
225
- const m = dt.minute();
226
- return toClockAngle(m * 6);
227
- };
228
- const hourAngleFromDate = (d) => {
229
- if (!d) {
230
- return 0;
231
- }
232
- const dt = timezone2 && timezone2 !== "" ? dayjs(d).tz(timezone2) : dayjs(d);
233
- const h = dt.hour() % 12;
234
- const m = dt.minute();
235
- return toClockAngle(h * 30 + m * 0.5);
236
- };
237
- const describeSector = (cx, cy, r, startDeg, endDeg, direction) => {
238
- const start = toClockAngle(startDeg);
239
- const end = toClockAngle(endDeg);
240
- let delta = 0;
241
- if (direction === "clockwise") {
242
- delta = end - start;
243
- if (delta < 0) {
244
- delta += 360;
245
- }
246
- } else {
247
- delta = start - end;
248
- if (delta < 0) {
249
- delta += 360;
250
- }
251
- }
252
- const largeArc = delta >= 180 ? 1 : 0;
253
- const sweep = direction === "clockwise" ? 1 : 0;
254
- const aStart = start * Math.PI / 180;
255
- const aEnd = end * Math.PI / 180;
256
- const x1 = cx + r * Math.sin(aStart);
257
- const y1 = cy - r * Math.cos(aStart);
258
- const x2 = cx + r * Math.sin(aEnd);
259
- const y2 = cy - r * Math.cos(aEnd);
260
- const fmt = (n) => Number.isFinite(n) ? n.toFixed(3) : "0";
261
- return `M ${fmt(cx)} ${fmt(cy)} L ${fmt(x1)} ${fmt(y1)} A ${fmt(r)} ${fmt(r)} 0 ${largeArc} ${sweep} ${fmt(x2)} ${fmt(y2)} Z`;
262
- };
287
+ const centerSize = Math.round(size * CENTER_DOT_RATIO);
263
288
  const showSecArc = withSecondsArc === true && (secondsArcOpacity ?? 1) !== 0;
264
289
  const showMinArc = withMinutesArc === true && (minutesArcOpacity ?? 1) !== 0;
265
290
  const showHrArc = withHoursArc === true && (hoursArcOpacity ?? 1) !== 0;
266
- return /* @__PURE__ */ React.createElement(Box, { ...getStyles("clockContainer") }, /* @__PURE__ */ React.createElement(Box, { ...getStyles("glassWrapper") }, /* @__PURE__ */ React.createElement(Box, { ...getStyles("clockFace") }, (showSecArc || showMinArc || showHrArc) && /* @__PURE__ */ React.createElement(
267
- "svg",
268
- {
269
- ...getStyles("arcsLayer", { style: { width: size, height: size } }),
270
- viewBox: `0 0 ${size} ${size}`
271
- },
272
- showHrArc && /* @__PURE__ */ React.createElement(
273
- "path",
274
- {
275
- d: describeSector(
276
- clockRadius,
277
- clockRadius,
278
- calculatedHourHandLength,
279
- hourAngleFromDate(parseTimeValue(hoursArcFrom) ?? null),
280
- hourAngle,
281
- hoursArcDirection
282
- ),
283
- fill: "var(--clock-hours-arc-color-resolved)",
284
- fillOpacity: Math.round((hoursArcOpacity ?? 1) * 100) / 100
285
- }
286
- ),
287
- showMinArc && /* @__PURE__ */ React.createElement(
288
- "path",
289
- {
290
- d: describeSector(
291
- clockRadius,
292
- clockRadius,
293
- calculatedMinuteHandLength,
294
- minAngleFromDate(parseTimeValue(minutesArcFrom) ?? null),
295
- minuteAngle,
296
- minutesArcDirection
297
- ),
298
- fill: "var(--clock-minutes-arc-color-resolved)",
299
- fillOpacity: Math.round((minutesArcOpacity ?? 1) * 100) / 100
300
- }
301
- ),
302
- showSecArc && /* @__PURE__ */ React.createElement(
303
- "path",
304
- {
305
- d: describeSector(
306
- clockRadius,
307
- clockRadius,
308
- calculatedSecondHandLength,
309
- secAngleFromDate(parseTimeValue(secondsArcFrom) ?? null),
310
- secondAngle,
311
- secondsArcDirection
312
- ),
313
- fill: "var(--clock-seconds-arc-color-resolved)",
314
- fillOpacity: Math.round((secondsArcOpacity ?? 1) * 100) / 100
315
- }
316
- )
317
- ), /* @__PURE__ */ React.createElement(Box, { ...getStyles("hourMarks") }, hourTicksOpacity !== 0 && Array.from({ length: 12 }, (_, i) => /* @__PURE__ */ React.createElement(
291
+ const counterweightWidth = round2(
292
+ size * (secondHandSize ?? defaultProps.secondHandSize) * COUNTERWEIGHT_MULTIPLIER
293
+ );
294
+ return /* @__PURE__ */ React.createElement(
318
295
  Box,
319
296
  {
320
- key: `hour-tick-${i}`,
321
- ...getStyles("hourTick", {
297
+ ...getStyles("clockContainer", {
322
298
  style: {
323
- top: tickOffset,
324
- left: "50%",
325
- transformOrigin: `50% ${clockRadius - tickOffset}px`,
326
- transform: `translateX(-50%) rotate(${i * 30}deg)`
299
+ width: geometry.width,
300
+ height: geometry.height
327
301
  }
328
302
  })
329
- }
330
- )), minuteTicksOpacity !== 0 && Array.from({ length: 60 }, (_, i) => {
331
- if (i % 5 === 0) {
332
- return null;
333
- }
334
- return /* @__PURE__ */ React.createElement(
303
+ },
304
+ /* @__PURE__ */ React.createElement(
335
305
  Box,
336
306
  {
337
- key: `minute-tick-${i}`,
338
- ...getStyles("minuteTick", {
339
- style: {
340
- top: tickOffset,
341
- left: "50%",
342
- transformOrigin: `50% ${clockRadius - tickOffset}px`,
343
- transform: `translateX(-50%) rotate(${i * 6}deg)`
344
- }
345
- })
346
- }
347
- );
348
- }), primaryNumbersOpacity !== 0 && [12, 3, 6, 9].map((num) => {
349
- const i = num === 12 ? 0 : num;
350
- const angle = (i * 30 - 90) * (Math.PI / 180);
351
- const x = Math.round(clockRadius + Math.cos(angle) * numberRadius);
352
- const y = Math.round(clockRadius + Math.sin(angle) * numberRadius);
353
- return /* @__PURE__ */ React.createElement(
354
- Text,
355
- {
356
- key: `primary-number-${num}`,
357
- ...primaryNumbersProps,
358
- ...getStyles("primaryNumber", {
359
- className: getStyles("number").className,
360
- style: {
361
- left: x,
362
- top: y
363
- }
307
+ ...getStyles("glassWrapper", {
308
+ style: { width: geometry.width, height: geometry.height }
364
309
  })
365
310
  },
366
- num
367
- );
368
- }), secondaryNumbersOpacity !== 0 && [1, 2, 4, 5, 7, 8, 10, 11].map((num) => {
369
- const i = num;
370
- const angle = (i * 30 - 90) * (Math.PI / 180);
371
- const x = Math.round(clockRadius + Math.cos(angle) * numberRadius);
372
- const y = Math.round(clockRadius + Math.sin(angle) * numberRadius);
373
- return /* @__PURE__ */ React.createElement(
374
- Text,
375
- {
376
- key: `secondary-number-${num}`,
377
- ...secondaryNumbersProps,
378
- ...getStyles("secondaryNumber", {
379
- className: getStyles("number").className,
380
- style: {
381
- left: x,
382
- top: y
311
+ /* @__PURE__ */ React.createElement(
312
+ Box,
313
+ {
314
+ ...getStyles("clockFace", {
315
+ style: {
316
+ width: geometry.width,
317
+ height: geometry.height,
318
+ borderRadius: geometry.borderRadius(),
319
+ clipPath: geometry.clipPath()
320
+ }
321
+ })
322
+ },
323
+ faceContent && /* @__PURE__ */ React.createElement(Box, { ...getStyles("faceContent") }, faceContent),
324
+ (showSecArc || showMinArc || showHrArc || sectors && sectors.length > 0) && /* @__PURE__ */ React.createElement(
325
+ "svg",
326
+ {
327
+ ...getStyles("arcsLayer", {
328
+ style: { width: geometry.width, height: geometry.height }
329
+ }),
330
+ viewBox: `0 0 ${geometry.width} ${geometry.height}`
331
+ },
332
+ sectors && sectors.length > 0 && sectors.map((sector, idx) => {
333
+ const fromDate = parseTimeValue(sector.from);
334
+ const toDate = parseTimeValue(sector.to);
335
+ if (!fromDate || !toDate) {
336
+ return null;
337
+ }
338
+ const startAngle = hourAngleFromDate(fromDate, timezone2);
339
+ const endAngle = hourAngleFromDate(toDate, timezone2);
340
+ const sectorRadius = calculatedMinuteHandLength;
341
+ return /* @__PURE__ */ React.createElement(
342
+ "path",
343
+ {
344
+ key: `sector-${idx}`,
345
+ d: geometry.sectorPath(startAngle, endAngle, sectorRadius, "clockwise"),
346
+ fill: sector.color || "var(--clock-second-hand-color-resolved)",
347
+ fillOpacity: round2(sector.opacity ?? 0.2),
348
+ style: sector.interactive ? { cursor: "pointer" } : void 0,
349
+ role: sector.interactive ? "button" : void 0,
350
+ tabIndex: sector.interactive ? 0 : void 0,
351
+ "aria-label": sector.interactive ? sector.label : void 0,
352
+ onClick: sector.interactive && sector.onClick ? () => sector.onClick(sector) : void 0,
353
+ onKeyDown: sector.interactive && sector.onClick ? (e) => {
354
+ if (e.key === "Enter" || e.key === " ") {
355
+ e.preventDefault();
356
+ sector.onClick(sector);
357
+ }
358
+ } : void 0,
359
+ onMouseEnter: sector.interactive && sector.onHover ? () => sector.onHover(sector, true) : void 0,
360
+ onMouseLeave: sector.interactive && sector.onHover ? () => sector.onHover(sector, false) : void 0
361
+ },
362
+ sector.label && /* @__PURE__ */ React.createElement("title", null, sector.label)
363
+ );
364
+ }),
365
+ showHrArc && /* @__PURE__ */ React.createElement(
366
+ "path",
367
+ {
368
+ d: geometry.sectorPath(
369
+ hourAngleFromDate(parseTimeValue(hoursArcFrom) ?? null, timezone2),
370
+ hourAngle,
371
+ calculatedHourHandLength,
372
+ hoursArcDirection
373
+ ),
374
+ fill: "var(--clock-hours-arc-color-resolved)",
375
+ fillOpacity: round2(hoursArcOpacity ?? 1)
376
+ }
377
+ ),
378
+ showMinArc && /* @__PURE__ */ React.createElement(
379
+ "path",
380
+ {
381
+ d: geometry.sectorPath(
382
+ minuteAngleFromDate(parseTimeValue(minutesArcFrom) ?? null, timezone2),
383
+ minuteAngle,
384
+ calculatedMinuteHandLength,
385
+ minutesArcDirection
386
+ ),
387
+ fill: "var(--clock-minutes-arc-color-resolved)",
388
+ fillOpacity: round2(minutesArcOpacity ?? 1)
389
+ }
390
+ ),
391
+ showSecArc && /* @__PURE__ */ React.createElement(
392
+ "path",
393
+ {
394
+ d: geometry.sectorPath(
395
+ secondAngleFromDate(parseTimeValue(secondsArcFrom) ?? null, timezone2),
396
+ secondAngle,
397
+ calculatedSecondHandLength,
398
+ secondsArcDirection
399
+ ),
400
+ fill: "var(--clock-seconds-arc-color-resolved)",
401
+ fillOpacity: round2(secondsArcOpacity ?? 1)
402
+ }
403
+ )
404
+ ),
405
+ /* @__PURE__ */ React.createElement(
406
+ ClockFaceStatic,
407
+ {
408
+ getStyles,
409
+ effectiveSize: size,
410
+ geometry,
411
+ hourTicksOpacity,
412
+ minuteTicksOpacity,
413
+ primaryNumbersOpacity,
414
+ secondaryNumbersOpacity,
415
+ hourNumbersDistance,
416
+ primaryNumbersProps,
417
+ secondaryNumbersProps
383
418
  }
384
- })
385
- },
386
- num
387
- );
388
- })), (hourHandOpacity ?? defaultProps.hourHandOpacity) !== 0 && /* @__PURE__ */ React.createElement(
389
- Box,
390
- {
391
- ...getStyles("hand", {
392
- className: getStyles("hourHand").className,
393
- style: {
394
- width: Math.round(size * (hourHandSize ?? defaultProps.hourHandSize) * 100) / 100,
395
- height: calculatedHourHandLength,
396
- opacity: Math.round((hourHandOpacity ?? defaultProps.hourHandOpacity) * 100) / 100,
397
- bottom: clockRadius,
398
- left: clockRadius,
399
- marginLeft: Math.round(-(size * (hourHandSize ?? defaultProps.hourHandSize)) / 2 * 100) / 100,
400
- borderRadius: `${Math.round(size * (hourHandSize ?? defaultProps.hourHandSize) * 100) / 100}px`,
401
- transform: `rotate(${Math.round(hourAngle * 100) / 100}deg)`
402
- }
403
- })
404
- }
405
- ), (minuteHandOpacity ?? defaultProps.minuteHandOpacity) !== 0 && /* @__PURE__ */ React.createElement(
406
- Box,
407
- {
408
- ...getStyles("hand", {
409
- className: getStyles("minuteHand").className,
410
- style: {
411
- width: Math.round(size * (minuteHandSize ?? defaultProps.minuteHandSize) * 100) / 100,
412
- height: calculatedMinuteHandLength,
413
- opacity: Math.round((minuteHandOpacity ?? defaultProps.minuteHandOpacity) * 100) / 100,
414
- bottom: clockRadius,
415
- left: clockRadius,
416
- marginLeft: Math.round(
417
- -(size * (minuteHandSize ?? defaultProps.minuteHandSize)) / 2 * 100
418
- ) / 100,
419
- borderRadius: `${Math.round(size * (minuteHandSize ?? defaultProps.minuteHandSize) * 100) / 100}px`,
420
- transform: `rotate(${Math.round(minuteAngle * 100) / 100}deg)`
421
- }
422
- })
423
- }
424
- ), (secondHandOpacity ?? defaultProps.secondHandOpacity) !== 0 && /* @__PURE__ */ React.createElement(
425
- Box,
426
- {
427
- ...getStyles("secondHandContainer", {
428
- style: {
429
- width: Math.round(size * (secondHandSize ?? defaultProps.secondHandSize) * 100) / 100,
430
- height: calculatedSecondHandLength,
431
- top: clockRadius - calculatedSecondHandLength,
432
- left: clockRadius,
433
- marginLeft: Math.round(
434
- -(size * (secondHandSize ?? defaultProps.secondHandSize)) / 2 * 100
435
- ) / 100,
436
- transformOrigin: `${Math.round(size * (secondHandSize ?? defaultProps.secondHandSize) / 2 * 100) / 100}px ${calculatedSecondHandLength}px`,
437
- transform: `rotate(${Math.round(secondAngle * 100) / 100}deg)`
438
- }
439
- })
440
- },
441
- /* @__PURE__ */ React.createElement(
442
- Box,
443
- {
444
- ...getStyles("secondHand", {
445
- style: {
446
- width: Math.round(size * (secondHandSize ?? defaultProps.secondHandSize) * 100) / 100,
447
- height: calculatedSecondHandLength,
448
- opacity: Math.round((secondHandOpacity ?? defaultProps.secondHandOpacity) * 100) / 100
419
+ ),
420
+ (hourHandOpacity ?? defaultProps.hourHandOpacity) !== 0 && (renderHourHand ? renderHourHand({
421
+ angle: handAngles.hour,
422
+ length: calculatedHourHandLength,
423
+ width: round2(size * (hourHandSize ?? defaultProps.hourHandSize)),
424
+ centerX: geometry.centerX,
425
+ centerY: geometry.centerY,
426
+ clockSize: size
427
+ }) : /* @__PURE__ */ React.createElement(
428
+ Box,
429
+ {
430
+ ...getStyles("hand", {
431
+ className: getStyles("hourHand").className,
432
+ style: {
433
+ width: round2(size * (hourHandSize ?? defaultProps.hourHandSize)),
434
+ height: calculatedHourHandLength,
435
+ opacity: round2(hourHandOpacity ?? defaultProps.hourHandOpacity),
436
+ bottom: centerY,
437
+ left: centerX,
438
+ marginLeft: round2(-(size * (hourHandSize ?? defaultProps.hourHandSize)) / 2),
439
+ borderRadius: `${round2(size * (hourHandSize ?? defaultProps.hourHandSize))}px`,
440
+ transform: `rotate(${handAngles.hour}deg)`,
441
+ ...transitionStyle
442
+ }
443
+ })
449
444
  }
450
- })
451
- }
452
- ),
453
- /* @__PURE__ */ React.createElement(
454
- Box,
455
- {
456
- ...getStyles("secondHandCounterweight", {
457
- style: {
458
- width: Math.round(size * 6e-3 * 3 * 100) / 100,
459
- opacity: Math.round((secondHandOpacity ?? defaultProps.secondHandOpacity) * 100) / 100,
460
- left: Math.round(
461
- size * (secondHandSize ?? defaultProps.secondHandSize) / 2 - size * 6e-3 * 3 / 2
462
- )
445
+ )),
446
+ (minuteHandOpacity ?? defaultProps.minuteHandOpacity) !== 0 && (renderMinuteHand ? renderMinuteHand({
447
+ angle: handAngles.minute,
448
+ length: calculatedMinuteHandLength,
449
+ width: round2(size * (minuteHandSize ?? defaultProps.minuteHandSize)),
450
+ centerX: geometry.centerX,
451
+ centerY: geometry.centerY,
452
+ clockSize: size
453
+ }) : /* @__PURE__ */ React.createElement(
454
+ Box,
455
+ {
456
+ ...getStyles("hand", {
457
+ className: getStyles("minuteHand").className,
458
+ style: {
459
+ width: round2(size * (minuteHandSize ?? defaultProps.minuteHandSize)),
460
+ height: calculatedMinuteHandLength,
461
+ opacity: round2(minuteHandOpacity ?? defaultProps.minuteHandOpacity),
462
+ bottom: centerY,
463
+ left: centerX,
464
+ marginLeft: round2(
465
+ -(size * (minuteHandSize ?? defaultProps.minuteHandSize)) / 2
466
+ ),
467
+ borderRadius: `${round2(size * (minuteHandSize ?? defaultProps.minuteHandSize))}px`,
468
+ transform: `rotate(${handAngles.minute}deg)`,
469
+ ...transitionStyle
470
+ }
471
+ })
463
472
  }
464
- })
465
- }
473
+ )),
474
+ (secondHandOpacity ?? defaultProps.secondHandOpacity) !== 0 && (renderSecondHand ? renderSecondHand({
475
+ angle: handAngles.second,
476
+ length: calculatedSecondHandLength,
477
+ width: round2(size * (secondHandSize ?? defaultProps.secondHandSize)),
478
+ centerX: geometry.centerX,
479
+ centerY: geometry.centerY,
480
+ clockSize: size
481
+ }) : /* @__PURE__ */ React.createElement(
482
+ Box,
483
+ {
484
+ ...getStyles("secondHandContainer", {
485
+ style: {
486
+ width: round2(size * (secondHandSize ?? defaultProps.secondHandSize)),
487
+ height: calculatedSecondHandLength,
488
+ top: centerY - calculatedSecondHandLength,
489
+ left: centerX,
490
+ marginLeft: round2(
491
+ -(size * (secondHandSize ?? defaultProps.secondHandSize)) / 2
492
+ ),
493
+ transformOrigin: `${round2(size * (secondHandSize ?? defaultProps.secondHandSize) / 2)}px ${calculatedSecondHandLength}px`,
494
+ transform: `rotate(${handAngles.second}deg)`,
495
+ ...transitionStyle
496
+ }
497
+ })
498
+ },
499
+ /* @__PURE__ */ React.createElement(
500
+ Box,
501
+ {
502
+ ...getStyles("secondHand", {
503
+ style: {
504
+ width: round2(size * (secondHandSize ?? defaultProps.secondHandSize)),
505
+ height: calculatedSecondHandLength,
506
+ opacity: round2(secondHandOpacity ?? defaultProps.secondHandOpacity)
507
+ }
508
+ })
509
+ }
510
+ ),
511
+ /* @__PURE__ */ React.createElement(
512
+ Box,
513
+ {
514
+ ...getStyles("secondHandCounterweight", {
515
+ style: {
516
+ width: counterweightWidth,
517
+ opacity: round2(secondHandOpacity ?? defaultProps.secondHandOpacity),
518
+ left: Math.round(
519
+ size * (secondHandSize ?? defaultProps.secondHandSize) / 2 - counterweightWidth / 2
520
+ )
521
+ }
522
+ })
523
+ }
524
+ )
525
+ )),
526
+ /* @__PURE__ */ React.createElement(Box, { ...getStyles("centerBlur") }),
527
+ /* @__PURE__ */ React.createElement(
528
+ Box,
529
+ {
530
+ ...getStyles("centerDot", {
531
+ style: {
532
+ width: centerSize,
533
+ height: centerSize,
534
+ opacity: round2(secondHandOpacity ?? defaultProps.secondHandOpacity),
535
+ top: Math.round(centerY - centerSize / 2),
536
+ left: Math.round(centerX - centerSize / 2)
537
+ }
538
+ })
539
+ }
540
+ )
541
+ )
466
542
  )
467
- ), /* @__PURE__ */ React.createElement(Box, { ...getStyles("centerBlur") }), /* @__PURE__ */ React.createElement(
468
- Box,
469
- {
470
- ...getStyles("centerDot", {
471
- style: {
472
- width: centerSize,
473
- height: centerSize,
474
- opacity: Math.round((secondHandOpacity ?? defaultProps.secondHandOpacity) * 100) / 100,
475
- top: Math.round(clockRadius - centerSize / 2),
476
- left: Math.round(clockRadius - centerSize / 2)
477
- }
478
- })
479
- }
480
- ))));
481
- };
543
+ );
544
+ });
545
+ RealClock.displayName = "RealClock";
482
546
  const Clock = factory((_props, ref) => {
483
547
  const props = useProps("Clock", defaultProps, _props);
484
548
  const [time, setTime] = useState(/* @__PURE__ */ new Date());
485
549
  const [hasMounted, setHasMounted] = useState(false);
486
550
  const intervalRef = useRef(null);
551
+ const rafRef = useRef(null);
487
552
  const startTimeRef = useRef(null);
488
553
  const realStartTimeRef = useRef(null);
554
+ const onTimeChange = useCallbackRef(_props.onTimeChange);
555
+ const containerRef = useRef(null);
556
+ const [measuredSize, setMeasuredSize] = useState(null);
557
+ const mergedRef = useMergedRef(ref, containerRef);
489
558
  const {
490
559
  // Clock-specific props that should not be passed to DOM
491
560
  size,
@@ -511,14 +580,13 @@ const Clock = factory((_props, ref) => {
511
580
  hourHandOpacity,
512
581
  hourHandSize,
513
582
  hourHandLength,
514
- hourTicksOpacity: _hourTicksOpacity,
515
- minuteTicksOpacity: _minuteTicksOpacity,
516
583
  hourNumbersDistance,
517
584
  primaryNumbersProps,
518
585
  secondaryNumbersProps,
519
586
  timezone: timezone2,
520
587
  running,
521
588
  value,
589
+ ariaLabel,
522
590
  withSecondsArc,
523
591
  secondsArcFrom,
524
592
  secondsArcDirection,
@@ -534,6 +602,17 @@ const Clock = factory((_props, ref) => {
534
602
  hoursArcDirection,
535
603
  hoursArcColor,
536
604
  hoursArcOpacity,
605
+ sectors,
606
+ faceContent,
607
+ animateOnMount,
608
+ animateOnMountDuration,
609
+ shape,
610
+ aspectRatio,
611
+ borderRadius,
612
+ onTimeChange: _onTimeChange,
613
+ renderHourHand,
614
+ renderMinuteHand,
615
+ renderSecondHand,
537
616
  // Styles API props
538
617
  classNames,
539
618
  style,
@@ -555,7 +634,7 @@ const Clock = factory((_props, ref) => {
555
634
  vars,
556
635
  varsResolver
557
636
  });
558
- const effectiveSize = Math.round(
637
+ const effectiveSize = size === "auto" ? measuredSize ?? 400 : Math.round(
559
638
  px(
560
639
  getSize(
561
640
  typeof size === "string" && size in defaultClockSizes ? defaultClockSizes[size] : size || defaultProps.size,
@@ -563,9 +642,34 @@ const Clock = factory((_props, ref) => {
563
642
  )
564
643
  )
565
644
  );
645
+ const geometry = useMemo(
646
+ () => createGeometry(effectiveSize, shape, { aspectRatio, borderRadius }),
647
+ [effectiveSize, shape, aspectRatio, borderRadius]
648
+ );
566
649
  useEffect(() => {
567
650
  setHasMounted(true);
568
651
  }, []);
652
+ useEffect(() => {
653
+ if (size !== "auto" || !hasMounted) {
654
+ return;
655
+ }
656
+ const element = containerRef.current;
657
+ if (!element || typeof ResizeObserver === "undefined") {
658
+ return;
659
+ }
660
+ const observer = new ResizeObserver((entries) => {
661
+ const entry = entries[0];
662
+ if (entry) {
663
+ const { width, height } = entry.contentRect;
664
+ const newSize = Math.round(Math.min(width, height));
665
+ if (newSize > 0) {
666
+ setMeasuredSize(newSize);
667
+ }
668
+ }
669
+ });
670
+ observer.observe(element);
671
+ return () => observer.disconnect();
672
+ }, [size, hasMounted]);
569
673
  const getEffectiveTime = () => {
570
674
  const parsedValue = parseTimeValue(value);
571
675
  if (!running) {
@@ -586,6 +690,10 @@ const Clock = factory((_props, ref) => {
586
690
  clearInterval(intervalRef.current);
587
691
  intervalRef.current = null;
588
692
  }
693
+ if (rafRef.current !== null) {
694
+ cancelAnimationFrame(rafRef.current);
695
+ rafRef.current = null;
696
+ }
589
697
  if (!running) {
590
698
  return;
591
699
  }
@@ -597,122 +705,179 @@ const Clock = factory((_props, ref) => {
597
705
  startTimeRef.current = null;
598
706
  realStartTimeRef.current = null;
599
707
  }
600
- let interval = 1e3;
601
- switch (secondHandBehavior) {
602
- case "smooth":
603
- interval = 16;
604
- break;
605
- case "tick-half":
606
- interval = 500;
607
- break;
608
- case "tick-high-freq":
609
- interval = 125;
610
- break;
611
- case "tick":
612
- default:
613
- interval = 1e3;
614
- break;
615
- }
708
+ const fireOnTimeChange = (now) => {
709
+ const tz = timezone2 && timezone2 !== "" ? dayjs(now).tz(timezone2) : dayjs(now);
710
+ onTimeChange({
711
+ hours: tz.hour(),
712
+ minutes: tz.minute(),
713
+ seconds: tz.second(),
714
+ milliseconds: tz.millisecond()
715
+ });
716
+ };
616
717
  const updateTime = () => {
617
- setTime(/* @__PURE__ */ new Date());
718
+ const now = /* @__PURE__ */ new Date();
719
+ setTime(now);
720
+ fireOnTimeChange(now);
618
721
  };
619
722
  updateTime();
620
- intervalRef.current = setInterval(updateTime, interval);
723
+ if (secondHandBehavior === "smooth") {
724
+ const animate = () => {
725
+ const now = /* @__PURE__ */ new Date();
726
+ setTime(now);
727
+ fireOnTimeChange(now);
728
+ rafRef.current = requestAnimationFrame(animate);
729
+ };
730
+ animate();
731
+ } else {
732
+ let interval = 1e3;
733
+ switch (secondHandBehavior) {
734
+ case "tick-half":
735
+ interval = 500;
736
+ break;
737
+ case "tick-high-freq":
738
+ interval = 125;
739
+ break;
740
+ case "tick":
741
+ default:
742
+ interval = 1e3;
743
+ break;
744
+ }
745
+ intervalRef.current = setInterval(updateTime, interval);
746
+ }
621
747
  return () => {
622
748
  if (intervalRef.current) {
623
749
  clearInterval(intervalRef.current);
624
750
  }
751
+ if (rafRef.current !== null) {
752
+ cancelAnimationFrame(rafRef.current);
753
+ }
625
754
  };
626
- }, [running, value, secondHandBehavior, secondHandOpacity]);
755
+ }, [running, value, secondHandBehavior, timezone2]);
627
756
  if (!hasMounted) {
628
- return /* @__PURE__ */ React.createElement(Box, { ...getStyles("root"), ref, ...others }, /* @__PURE__ */ React.createElement(Box, { ...getStyles("clockContainer") }, /* @__PURE__ */ React.createElement(Box, { ...getStyles("glassWrapper") }, /* @__PURE__ */ React.createElement(Box, { ...getStyles("clockFace") }, /* @__PURE__ */ React.createElement(Box, { ...getStyles("hourMarks") }, (hourTicksOpacity || 1) !== 0 && Array.from({ length: 12 }, (_, i) => /* @__PURE__ */ React.createElement(
757
+ return /* @__PURE__ */ React.createElement(
629
758
  Box,
630
759
  {
631
- key: `hour-tick-${i}`,
632
- ...getStyles("hourTick", {
633
- style: {
634
- top: Math.round(effectiveSize * 0.028),
635
- left: "50%",
636
- transformOrigin: `50% ${Math.round(effectiveSize / 2) - Math.round(effectiveSize * 0.028)}px`,
637
- transform: `translateX(-50%) rotate(${i * 30}deg)`
638
- }
639
- })
640
- }
641
- )), (minuteTicksOpacity || 1) !== 0 && Array.from({ length: 60 }, (_, i) => {
642
- if (i % 5 === 0) {
643
- return null;
644
- }
645
- return /* @__PURE__ */ React.createElement(
760
+ ...getStyles("root", {
761
+ style: size === "auto" ? { width: "100%", height: "100%", "--clock-size": `${effectiveSize}px` } : { width: geometry.width, height: geometry.height }
762
+ }),
763
+ ref: mergedRef,
764
+ role: "img",
765
+ "aria-label": ariaLabel || "Clock",
766
+ ...others
767
+ },
768
+ /* @__PURE__ */ React.createElement(
646
769
  Box,
647
770
  {
648
- key: `minute-tick-${i}`,
649
- ...getStyles("minuteTick", {
650
- style: {
651
- top: Math.round(effectiveSize * 0.028),
652
- left: "50%",
653
- transformOrigin: `50% ${Math.round(effectiveSize / 2) - Math.round(effectiveSize * 0.028)}px`,
654
- transform: `translateX(-50%) rotate(${i * 6}deg)`
655
- }
656
- })
657
- }
658
- );
659
- }), (primaryNumbersOpacity || 1) !== 0 && [12, 3, 6, 9].map((num) => {
660
- const i = num === 12 ? 0 : num;
661
- const angle = (i * 30 - 90) * (Math.PI / 180);
662
- const clockRadius = Math.round(effectiveSize / 2);
663
- const numberRadius = Math.round(clockRadius * (hourNumbersDistance || 0.75));
664
- const x = Math.round(clockRadius + Math.cos(angle) * numberRadius);
665
- const y = Math.round(clockRadius + Math.sin(angle) * numberRadius);
666
- return /* @__PURE__ */ React.createElement(
667
- Text,
668
- {
669
- key: `primary-number-${num}`,
670
- ...primaryNumbersProps,
671
- ...getStyles("primaryNumber", {
672
- className: getStyles("number").className,
673
- style: {
674
- left: x,
675
- top: y
676
- }
677
- })
678
- },
679
- num
680
- );
681
- }), (secondaryNumbersOpacity || 1) !== 0 && [1, 2, 4, 5, 7, 8, 10, 11].map((num) => {
682
- const i = num;
683
- const angle = (i * 30 - 90) * (Math.PI / 180);
684
- const clockRadius = Math.round(effectiveSize / 2);
685
- const numberRadius = Math.round(clockRadius * (hourNumbersDistance || 0.75));
686
- const x = Math.round(clockRadius + Math.cos(angle) * numberRadius);
687
- const y = Math.round(clockRadius + Math.sin(angle) * numberRadius);
688
- return /* @__PURE__ */ React.createElement(
689
- Text,
690
- {
691
- key: `secondary-number-${num}`,
692
- ...secondaryNumbersProps,
693
- ...getStyles("secondaryNumber", {
694
- className: getStyles("number").className,
771
+ ...getStyles("clockContainer", {
695
772
  style: {
696
- left: x,
697
- top: y
773
+ width: geometry.width,
774
+ height: geometry.height
698
775
  }
699
776
  })
700
777
  },
701
- num
702
- );
703
- }))))));
778
+ /* @__PURE__ */ React.createElement(
779
+ Box,
780
+ {
781
+ ...getStyles("glassWrapper", {
782
+ style: { width: geometry.width, height: geometry.height }
783
+ })
784
+ },
785
+ /* @__PURE__ */ React.createElement(
786
+ Box,
787
+ {
788
+ ...getStyles("clockFace", {
789
+ style: {
790
+ width: geometry.width,
791
+ height: geometry.height,
792
+ borderRadius: geometry.borderRadius(),
793
+ clipPath: geometry.clipPath()
794
+ }
795
+ })
796
+ },
797
+ faceContent && /* @__PURE__ */ React.createElement(Box, { ...getStyles("faceContent") }, faceContent),
798
+ /* @__PURE__ */ React.createElement(
799
+ ClockFaceStatic,
800
+ {
801
+ getStyles,
802
+ effectiveSize,
803
+ geometry,
804
+ hourTicksOpacity,
805
+ minuteTicksOpacity,
806
+ primaryNumbersOpacity,
807
+ secondaryNumbersOpacity,
808
+ hourNumbersDistance,
809
+ primaryNumbersProps,
810
+ secondaryNumbersProps
811
+ }
812
+ )
813
+ )
814
+ )
815
+ )
816
+ );
704
817
  }
705
818
  const effectiveTime = getEffectiveTime();
706
- return /* @__PURE__ */ React.createElement(Box, { ...getStyles("root"), ref, ...others }, /* @__PURE__ */ React.createElement(
707
- RealClock,
819
+ const timezoneTime = timezone2 && timezone2 !== "" ? dayjs(effectiveTime).tz(timezone2) : dayjs(effectiveTime);
820
+ const computedAriaLabel = ariaLabel || `Clock showing ${String(timezoneTime.hour()).padStart(2, "0")}:${String(timezoneTime.minute()).padStart(2, "0")}:${String(timezoneTime.second()).padStart(2, "0")}`;
821
+ return /* @__PURE__ */ React.createElement(
822
+ Box,
708
823
  {
709
- time: effectiveTime,
710
- getStyles,
711
- effectiveSize,
712
- ...props
713
- }
714
- ));
824
+ ...getStyles("root", {
825
+ style: size === "auto" ? { width: "100%", height: "100%", "--clock-size": `${effectiveSize}px` } : { width: geometry.width, height: geometry.height }
826
+ }),
827
+ ref: mergedRef,
828
+ role: "img",
829
+ "aria-label": computedAriaLabel,
830
+ ...others
831
+ },
832
+ /* @__PURE__ */ React.createElement(
833
+ RealClock,
834
+ {
835
+ time: effectiveTime,
836
+ getStyles,
837
+ effectiveSize,
838
+ geometry,
839
+ timezone: timezone2,
840
+ hourHandSize,
841
+ minuteHandSize,
842
+ secondHandSize,
843
+ hourHandLength,
844
+ minuteHandLength,
845
+ secondHandLength,
846
+ secondHandBehavior,
847
+ secondHandOpacity,
848
+ minuteHandOpacity,
849
+ hourHandOpacity,
850
+ hourTicksOpacity,
851
+ minuteTicksOpacity,
852
+ primaryNumbersOpacity,
853
+ secondaryNumbersOpacity,
854
+ hourNumbersDistance,
855
+ primaryNumbersProps,
856
+ secondaryNumbersProps,
857
+ withSecondsArc,
858
+ secondsArcFrom,
859
+ secondsArcDirection,
860
+ secondsArcOpacity,
861
+ withMinutesArc,
862
+ minutesArcFrom,
863
+ minutesArcDirection,
864
+ minutesArcOpacity,
865
+ withHoursArc,
866
+ hoursArcFrom,
867
+ hoursArcDirection,
868
+ hoursArcOpacity,
869
+ sectors,
870
+ faceContent,
871
+ animateOnMount,
872
+ animateOnMountDuration,
873
+ renderHourHand,
874
+ renderMinuteHand,
875
+ renderSecondHand
876
+ }
877
+ )
878
+ );
715
879
  });
880
+ Clock.Digital = ClockDigital;
716
881
  Clock.classes = classes;
717
882
  Clock.displayName = "Clock";
718
883