@seedgrid/fe-components 0.2.4
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/blocked-email-domains.json +41 -0
- package/dist/buttons/SgButton.d.ts +43 -0
- package/dist/buttons/SgButton.d.ts.map +1 -0
- package/dist/buttons/SgButton.js +123 -0
- package/dist/buttons/SgFloatActionButton.d.ts +60 -0
- package/dist/buttons/SgFloatActionButton.d.ts.map +1 -0
- package/dist/buttons/SgFloatActionButton.js +532 -0
- package/dist/buttons/SgSpeedDial.d.ts +40 -0
- package/dist/buttons/SgSpeedDial.d.ts.map +1 -0
- package/dist/buttons/SgSpeedDial.js +149 -0
- package/dist/buttons/SgSplitButton.d.ts +32 -0
- package/dist/buttons/SgSplitButton.d.ts.map +1 -0
- package/dist/buttons/SgSplitButton.js +81 -0
- package/dist/clock/SgClock.d.ts +28 -0
- package/dist/clock/SgClock.d.ts.map +1 -0
- package/dist/clock/SgClock.js +280 -0
- package/dist/clock/SgTimeProvider.d.ts +13 -0
- package/dist/clock/SgTimeProvider.d.ts.map +1 -0
- package/dist/clock/SgTimeProvider.js +44 -0
- package/dist/clock/themes/SgClockThemePicker.d.ts +14 -0
- package/dist/clock/themes/SgClockThemePicker.d.ts.map +1 -0
- package/dist/clock/themes/SgClockThemePicker.js +71 -0
- package/dist/clock/themes/SgClockThemePreview.d.ts +7 -0
- package/dist/clock/themes/SgClockThemePreview.d.ts.map +1 -0
- package/dist/clock/themes/SgClockThemePreview.js +11 -0
- package/dist/clock/themes/builtins.d.ts +3 -0
- package/dist/clock/themes/builtins.d.ts.map +1 -0
- package/dist/clock/themes/builtins.js +241 -0
- package/dist/clock/themes/index.d.ts +9 -0
- package/dist/clock/themes/index.d.ts.map +1 -0
- package/dist/clock/themes/index.js +7 -0
- package/dist/clock/themes/provider.d.ts +19 -0
- package/dist/clock/themes/provider.d.ts.map +1 -0
- package/dist/clock/themes/provider.js +54 -0
- package/dist/clock/themes/registry.d.ts +9 -0
- package/dist/clock/themes/registry.d.ts.map +1 -0
- package/dist/clock/themes/registry.js +25 -0
- package/dist/clock/themes/renderTheme.d.ts +7 -0
- package/dist/clock/themes/renderTheme.d.ts.map +1 -0
- package/dist/clock/themes/renderTheme.js +41 -0
- package/dist/clock/themes/types.d.ts +21 -0
- package/dist/clock/themes/types.d.ts.map +1 -0
- package/dist/clock/themes/types.js +1 -0
- package/dist/clock/themes/urlThemeCache.d.ts +2 -0
- package/dist/clock/themes/urlThemeCache.d.ts.map +1 -0
- package/dist/clock/themes/urlThemeCache.js +11 -0
- package/dist/clock/themes/useDarkFlag.d.ts +2 -0
- package/dist/clock/themes/useDarkFlag.d.ts.map +1 -0
- package/dist/clock/themes/useDarkFlag.js +14 -0
- package/dist/commons/SgBadge.d.ts +51 -0
- package/dist/commons/SgBadge.d.ts.map +1 -0
- package/dist/commons/SgBadge.js +141 -0
- package/dist/commons/SgBadgeOverlay.d.ts +13 -0
- package/dist/commons/SgBadgeOverlay.d.ts.map +1 -0
- package/dist/commons/SgBadgeOverlay.js +20 -0
- package/dist/commons/SgButton.d.ts +39 -0
- package/dist/commons/SgButton.d.ts.map +1 -0
- package/dist/commons/SgButton.js +116 -0
- package/dist/commons/SgPopup.d.ts +42 -0
- package/dist/commons/SgPopup.d.ts.map +1 -0
- package/dist/commons/SgPopup.js +218 -0
- package/dist/commons/SgToast.d.ts +44 -0
- package/dist/commons/SgToast.d.ts.map +1 -0
- package/dist/commons/SgToast.js +97 -0
- package/dist/commons/SgToaster.d.ts +11 -0
- package/dist/commons/SgToaster.d.ts.map +1 -0
- package/dist/commons/SgToaster.js +85 -0
- package/dist/commons/common-passwords.d.ts +2 -0
- package/dist/commons/common-passwords.d.ts.map +1 -0
- package/dist/commons/common-passwords.js +167 -0
- package/dist/environment/SgEnvironmentProvider.d.ts +31 -0
- package/dist/environment/SgEnvironmentProvider.d.ts.map +1 -0
- package/dist/environment/SgEnvironmentProvider.js +120 -0
- package/dist/environment/persistence.d.ts +44 -0
- package/dist/environment/persistence.d.ts.map +1 -0
- package/dist/environment/persistence.js +149 -0
- package/dist/gadgets/clock/SgClock.d.ts +18 -0
- package/dist/gadgets/clock/SgClock.d.ts.map +1 -0
- package/dist/gadgets/clock/SgClock.js +407 -0
- package/dist/gadgets/clock/SgTimeProvider.d.ts +13 -0
- package/dist/gadgets/clock/SgTimeProvider.d.ts.map +1 -0
- package/dist/gadgets/clock/SgTimeProvider.js +44 -0
- package/dist/gadgets/clock/themes/SgClockThemePicker.d.ts +14 -0
- package/dist/gadgets/clock/themes/SgClockThemePicker.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/SgClockThemePicker.js +71 -0
- package/dist/gadgets/clock/themes/SgClockThemePreview.d.ts +7 -0
- package/dist/gadgets/clock/themes/SgClockThemePreview.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/SgClockThemePreview.js +11 -0
- package/dist/gadgets/clock/themes/builtins.d.ts +3 -0
- package/dist/gadgets/clock/themes/builtins.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/builtins.js +241 -0
- package/dist/gadgets/clock/themes/index.d.ts +9 -0
- package/dist/gadgets/clock/themes/index.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/index.js +7 -0
- package/dist/gadgets/clock/themes/provider.d.ts +19 -0
- package/dist/gadgets/clock/themes/provider.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/provider.js +54 -0
- package/dist/gadgets/clock/themes/registry.d.ts +9 -0
- package/dist/gadgets/clock/themes/registry.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/registry.js +25 -0
- package/dist/gadgets/clock/themes/renderTheme.d.ts +7 -0
- package/dist/gadgets/clock/themes/renderTheme.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/renderTheme.js +41 -0
- package/dist/gadgets/clock/themes/types.d.ts +21 -0
- package/dist/gadgets/clock/themes/types.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/types.js +1 -0
- package/dist/gadgets/clock/themes/urlThemeCache.d.ts +2 -0
- package/dist/gadgets/clock/themes/urlThemeCache.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/urlThemeCache.js +11 -0
- package/dist/gadgets/clock/themes/useDarkFlag.d.ts +2 -0
- package/dist/gadgets/clock/themes/useDarkFlag.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/useDarkFlag.js +14 -0
- package/dist/gadgets/flip-digit/SgFlipDigit.d.ts +23 -0
- package/dist/gadgets/flip-digit/SgFlipDigit.d.ts.map +1 -0
- package/dist/gadgets/flip-digit/SgFlipDigit.js +118 -0
- package/dist/gadgets/flip-digit/index.d.ts +3 -0
- package/dist/gadgets/flip-digit/index.d.ts.map +1 -0
- package/dist/gadgets/flip-digit/index.js +1 -0
- package/dist/i18n/en-US.json +76 -0
- package/dist/i18n/es.json +76 -0
- package/dist/i18n/index.d.ts +328 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +87 -0
- package/dist/i18n/pt-BR.json +76 -0
- package/dist/i18n/pt-PT.json +76 -0
- package/dist/index.d.ts +88 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/inputs/FloatingInput.d.ts +13 -0
- package/dist/inputs/FloatingInput.d.ts.map +1 -0
- package/dist/inputs/FloatingInput.js +53 -0
- package/dist/inputs/FloatingSelect.d.ts +15 -0
- package/dist/inputs/FloatingSelect.d.ts.map +1 -0
- package/dist/inputs/FloatingSelect.js +52 -0
- package/dist/inputs/FloatingTextArea.d.ts +11 -0
- package/dist/inputs/FloatingTextArea.d.ts.map +1 -0
- package/dist/inputs/FloatingTextArea.js +34 -0
- package/dist/inputs/InputBirthDate.d.ts +13 -0
- package/dist/inputs/InputBirthDate.d.ts.map +1 -0
- package/dist/inputs/InputBirthDate.js +46 -0
- package/dist/inputs/InputDate.d.ts +8 -0
- package/dist/inputs/InputDate.d.ts.map +1 -0
- package/dist/inputs/InputDate.js +23 -0
- package/dist/inputs/InputEmail.d.ts +14 -0
- package/dist/inputs/InputEmail.d.ts.map +1 -0
- package/dist/inputs/InputEmail.js +43 -0
- package/dist/inputs/InputPassword.d.ts +12 -0
- package/dist/inputs/InputPassword.d.ts.map +1 -0
- package/dist/inputs/InputPassword.js +42 -0
- package/dist/inputs/MaskedInputs.d.ts +27 -0
- package/dist/inputs/MaskedInputs.d.ts.map +1 -0
- package/dist/inputs/MaskedInputs.js +161 -0
- package/dist/inputs/SgAutocomplete.d.ts +42 -0
- package/dist/inputs/SgAutocomplete.d.ts.map +1 -0
- package/dist/inputs/SgAutocomplete.js +241 -0
- package/dist/inputs/SgCurrencyEdit.d.ts +56 -0
- package/dist/inputs/SgCurrencyEdit.d.ts.map +1 -0
- package/dist/inputs/SgCurrencyEdit.js +496 -0
- package/dist/inputs/SgInputBirthDate.d.ts +13 -0
- package/dist/inputs/SgInputBirthDate.d.ts.map +1 -0
- package/dist/inputs/SgInputBirthDate.js +48 -0
- package/dist/inputs/SgInputCEP.d.ts +33 -0
- package/dist/inputs/SgInputCEP.d.ts.map +1 -0
- package/dist/inputs/SgInputCEP.js +117 -0
- package/dist/inputs/SgInputCNPJ.d.ts +20 -0
- package/dist/inputs/SgInputCNPJ.d.ts.map +1 -0
- package/dist/inputs/SgInputCNPJ.js +133 -0
- package/dist/inputs/SgInputCPF.d.ts +15 -0
- package/dist/inputs/SgInputCPF.d.ts.map +1 -0
- package/dist/inputs/SgInputCPF.js +70 -0
- package/dist/inputs/SgInputCPFCNPJ.d.ts +15 -0
- package/dist/inputs/SgInputCPFCNPJ.d.ts.map +1 -0
- package/dist/inputs/SgInputCPFCNPJ.js +92 -0
- package/dist/inputs/SgInputDate.d.ts +8 -0
- package/dist/inputs/SgInputDate.d.ts.map +1 -0
- package/dist/inputs/SgInputDate.js +120 -0
- package/dist/inputs/SgInputEmail.d.ts +16 -0
- package/dist/inputs/SgInputEmail.d.ts.map +1 -0
- package/dist/inputs/SgInputEmail.js +74 -0
- package/dist/inputs/SgInputFone.d.ts +15 -0
- package/dist/inputs/SgInputFone.d.ts.map +1 -0
- package/dist/inputs/SgInputFone.js +60 -0
- package/dist/inputs/SgInputMasked.d.ts +27 -0
- package/dist/inputs/SgInputMasked.d.ts.map +1 -0
- package/dist/inputs/SgInputMasked.js +161 -0
- package/dist/inputs/SgInputNumber.d.ts +49 -0
- package/dist/inputs/SgInputNumber.d.ts.map +1 -0
- package/dist/inputs/SgInputNumber.js +438 -0
- package/dist/inputs/SgInputPassword.d.ts +26 -0
- package/dist/inputs/SgInputPassword.d.ts.map +1 -0
- package/dist/inputs/SgInputPassword.js +278 -0
- package/dist/inputs/SgInputPhone.d.ts +15 -0
- package/dist/inputs/SgInputPhone.d.ts.map +1 -0
- package/dist/inputs/SgInputPhone.js +66 -0
- package/dist/inputs/SgInputPostalCode.d.ts +37 -0
- package/dist/inputs/SgInputPostalCode.d.ts.map +1 -0
- package/dist/inputs/SgInputPostalCode.js +193 -0
- package/dist/inputs/SgInputSelect.d.ts +16 -0
- package/dist/inputs/SgInputSelect.d.ts.map +1 -0
- package/dist/inputs/SgInputSelect.js +104 -0
- package/dist/inputs/SgInputText.d.ts +49 -0
- package/dist/inputs/SgInputText.d.ts.map +1 -0
- package/dist/inputs/SgInputText.js +336 -0
- package/dist/inputs/SgInputTextArea.d.ts +41 -0
- package/dist/inputs/SgInputTextArea.d.ts.map +1 -0
- package/dist/inputs/SgInputTextArea.js +216 -0
- package/dist/inputs/SgTextEditor.d.ts +27 -0
- package/dist/inputs/SgTextEditor.d.ts.map +1 -0
- package/dist/inputs/SgTextEditor.js +201 -0
- package/dist/integration/module.d.ts +39 -0
- package/dist/integration/module.d.ts.map +1 -0
- package/dist/integration/module.js +1 -0
- package/dist/layout/GroupBox.d.ts +10 -0
- package/dist/layout/GroupBox.d.ts.map +1 -0
- package/dist/layout/GroupBox.js +14 -0
- package/dist/layout/SgCard.d.ts +35 -0
- package/dist/layout/SgCard.d.ts.map +1 -0
- package/dist/layout/SgCard.js +106 -0
- package/dist/layout/SgDockLayout.d.ts +37 -0
- package/dist/layout/SgDockLayout.d.ts.map +1 -0
- package/dist/layout/SgDockLayout.js +101 -0
- package/dist/layout/SgDockZone.d.ts +12 -0
- package/dist/layout/SgDockZone.d.ts.map +1 -0
- package/dist/layout/SgDockZone.js +20 -0
- package/dist/layout/SgGrid.d.ts +18 -0
- package/dist/layout/SgGrid.d.ts.map +1 -0
- package/dist/layout/SgGrid.js +101 -0
- package/dist/layout/SgGroupBox.d.ts +10 -0
- package/dist/layout/SgGroupBox.d.ts.map +1 -0
- package/dist/layout/SgGroupBox.js +14 -0
- package/dist/layout/SgMainPanel.d.ts +11 -0
- package/dist/layout/SgMainPanel.d.ts.map +1 -0
- package/dist/layout/SgMainPanel.js +70 -0
- package/dist/layout/SgPanel.d.ts +22 -0
- package/dist/layout/SgPanel.d.ts.map +1 -0
- package/dist/layout/SgPanel.js +33 -0
- package/dist/layout/SgScreen.d.ts +11 -0
- package/dist/layout/SgScreen.d.ts.map +1 -0
- package/dist/layout/SgScreen.js +18 -0
- package/dist/layout/SgStack.d.ts +15 -0
- package/dist/layout/SgStack.d.ts.map +1 -0
- package/dist/layout/SgStack.js +32 -0
- package/dist/layout/SgToolBar.d.ts +46 -0
- package/dist/layout/SgToolBar.d.ts.map +1 -0
- package/dist/layout/SgToolBar.js +199 -0
- package/dist/layout/SgTreeView.d.ts +80 -0
- package/dist/layout/SgTreeView.d.ts.map +1 -0
- package/dist/layout/SgTreeView.js +338 -0
- package/dist/manifest.d.ts +3 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +19 -0
- package/dist/masks.d.ts +14 -0
- package/dist/masks.d.ts.map +1 -0
- package/dist/masks.js +91 -0
- package/dist/overlay/SgDialog.d.ts +39 -0
- package/dist/overlay/SgDialog.d.ts.map +1 -0
- package/dist/overlay/SgDialog.js +177 -0
- package/dist/overlay/SgPopup.d.ts +42 -0
- package/dist/overlay/SgPopup.d.ts.map +1 -0
- package/dist/overlay/SgPopup.js +218 -0
- package/dist/rhf.d.ts +6 -0
- package/dist/rhf.d.ts.map +1 -0
- package/dist/rhf.js +1 -0
- package/dist/validators.d.ts +27 -0
- package/dist/validators.d.ts.map +1 -0
- package/dist/validators.js +218 -0
- package/dist/wizard/SGWizard.d.ts +28 -0
- package/dist/wizard/SGWizard.d.ts.map +1 -0
- package/dist/wizard/SGWizard.js +124 -0
- package/package.json +53 -0
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { useSgTime } from "./SgTimeProvider";
|
|
5
|
+
import { useSgClockThemeResolver } from "./themes/provider";
|
|
6
|
+
import { ThemeLayer, resolveTheme } from "./themes/renderTheme";
|
|
7
|
+
import { useDarkFlag } from "./themes/useDarkFlag";
|
|
8
|
+
import { getTheme } from "./themes/registry";
|
|
9
|
+
function cn(...parts) {
|
|
10
|
+
return parts.filter(Boolean).join(" ");
|
|
11
|
+
}
|
|
12
|
+
function useSecondTick() {
|
|
13
|
+
const [, setTick] = React.useState(0);
|
|
14
|
+
React.useEffect(() => {
|
|
15
|
+
const id = window.setInterval(() => setTick((v) => v + 1), 1000);
|
|
16
|
+
return () => window.clearInterval(id);
|
|
17
|
+
}, []);
|
|
18
|
+
}
|
|
19
|
+
function getHmsForTimezone(date, locale, timeZone) {
|
|
20
|
+
const parts = new Intl.DateTimeFormat(locale, {
|
|
21
|
+
timeZone,
|
|
22
|
+
hour: "2-digit",
|
|
23
|
+
minute: "2-digit",
|
|
24
|
+
second: "2-digit",
|
|
25
|
+
hour12: false
|
|
26
|
+
}).formatToParts(date);
|
|
27
|
+
const get = (type) => {
|
|
28
|
+
const p = parts.find((x) => x.type === type)?.value ?? "0";
|
|
29
|
+
const n = Number.parseInt(p, 10);
|
|
30
|
+
return Number.isFinite(n) ? n : 0;
|
|
31
|
+
};
|
|
32
|
+
return { h: get("hour"), m: get("minute"), s: get("second") };
|
|
33
|
+
}
|
|
34
|
+
function sizeToClass(size) {
|
|
35
|
+
if (typeof size === "number")
|
|
36
|
+
return "";
|
|
37
|
+
if (size === "sm")
|
|
38
|
+
return "text-sm";
|
|
39
|
+
if (size === "lg")
|
|
40
|
+
return "text-2xl";
|
|
41
|
+
return "text-base";
|
|
42
|
+
}
|
|
43
|
+
function digitalSizeToNumber(size) {
|
|
44
|
+
if (typeof size === "number")
|
|
45
|
+
return size;
|
|
46
|
+
if (size === "sm")
|
|
47
|
+
return 12;
|
|
48
|
+
if (size === "lg")
|
|
49
|
+
return 28;
|
|
50
|
+
return 16;
|
|
51
|
+
}
|
|
52
|
+
function getPrevNext(value, min, max) {
|
|
53
|
+
const range = max - min + 1;
|
|
54
|
+
const prev = ((value - 1 - min + range) % range) + min;
|
|
55
|
+
const next = ((value + 1 - min) % range) + min;
|
|
56
|
+
return { prev, next };
|
|
57
|
+
}
|
|
58
|
+
function buildRange(min, max) {
|
|
59
|
+
const out = [];
|
|
60
|
+
for (let i = min; i <= max; i += 1)
|
|
61
|
+
out.push(i);
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
const SEGMENTS = {
|
|
65
|
+
"0": [
|
|
66
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
67
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
68
|
+
{ x: 5, y: 5, w: 1, h: 4 },
|
|
69
|
+
{ x: 1, y: 9, w: 4, h: 1 },
|
|
70
|
+
{ x: 0, y: 5, w: 1, h: 4 },
|
|
71
|
+
{ x: 0, y: 1, w: 1, h: 4 }
|
|
72
|
+
],
|
|
73
|
+
"1": [
|
|
74
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
75
|
+
{ x: 5, y: 5, w: 1, h: 4 }
|
|
76
|
+
],
|
|
77
|
+
"2": [
|
|
78
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
79
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
80
|
+
{ x: 1, y: 4.5, w: 4, h: 1 },
|
|
81
|
+
{ x: 0, y: 5, w: 1, h: 4 },
|
|
82
|
+
{ x: 1, y: 9, w: 4, h: 1 }
|
|
83
|
+
],
|
|
84
|
+
"3": [
|
|
85
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
86
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
87
|
+
{ x: 1, y: 4.5, w: 4, h: 1 },
|
|
88
|
+
{ x: 5, y: 5, w: 1, h: 4 },
|
|
89
|
+
{ x: 1, y: 9, w: 4, h: 1 }
|
|
90
|
+
],
|
|
91
|
+
"4": [
|
|
92
|
+
{ x: 0, y: 1, w: 1, h: 4 },
|
|
93
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
94
|
+
{ x: 1, y: 4.5, w: 4, h: 1 },
|
|
95
|
+
{ x: 5, y: 5, w: 1, h: 4 }
|
|
96
|
+
],
|
|
97
|
+
"5": [
|
|
98
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
99
|
+
{ x: 0, y: 1, w: 1, h: 4 },
|
|
100
|
+
{ x: 1, y: 4.5, w: 4, h: 1 },
|
|
101
|
+
{ x: 5, y: 5, w: 1, h: 4 },
|
|
102
|
+
{ x: 1, y: 9, w: 4, h: 1 }
|
|
103
|
+
],
|
|
104
|
+
"6": [
|
|
105
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
106
|
+
{ x: 0, y: 1, w: 1, h: 4 },
|
|
107
|
+
{ x: 1, y: 4.5, w: 4, h: 1 },
|
|
108
|
+
{ x: 0, y: 5, w: 1, h: 4 },
|
|
109
|
+
{ x: 5, y: 5, w: 1, h: 4 },
|
|
110
|
+
{ x: 1, y: 9, w: 4, h: 1 }
|
|
111
|
+
],
|
|
112
|
+
"7": [
|
|
113
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
114
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
115
|
+
{ x: 5, y: 5, w: 1, h: 4 }
|
|
116
|
+
],
|
|
117
|
+
"8": [
|
|
118
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
119
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
120
|
+
{ x: 5, y: 5, w: 1, h: 4 },
|
|
121
|
+
{ x: 1, y: 9, w: 4, h: 1 },
|
|
122
|
+
{ x: 0, y: 5, w: 1, h: 4 },
|
|
123
|
+
{ x: 0, y: 1, w: 1, h: 4 },
|
|
124
|
+
{ x: 1, y: 4.5, w: 4, h: 1 }
|
|
125
|
+
],
|
|
126
|
+
"9": [
|
|
127
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
128
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
129
|
+
{ x: 5, y: 5, w: 1, h: 4 },
|
|
130
|
+
{ x: 1, y: 9, w: 4, h: 1 },
|
|
131
|
+
{ x: 0, y: 1, w: 1, h: 4 },
|
|
132
|
+
{ x: 1, y: 4.5, w: 4, h: 1 }
|
|
133
|
+
]
|
|
134
|
+
};
|
|
135
|
+
function round(n) {
|
|
136
|
+
return Math.round(n * 1000) / 1000;
|
|
137
|
+
}
|
|
138
|
+
function renderSegmentDigit(digit, x, y, scale, keyPrefix) {
|
|
139
|
+
const segs = SEGMENTS[digit] ?? [];
|
|
140
|
+
return segs.map((s, idx) => (_jsx("rect", { x: round(x + s.x * scale), y: round(y + s.y * scale), width: round(s.w * scale), height: round(s.h * scale), className: "fill-neutral-800 dark:fill-neutral-200", rx: round(0.3 * scale) }, `${keyPrefix}-${idx}`)));
|
|
141
|
+
}
|
|
142
|
+
function renderSegmentChar(ch, x, y, scale, keyPrefix) {
|
|
143
|
+
if (ch === ":") {
|
|
144
|
+
return (_jsxs("g", { children: [_jsx("rect", { x: round(x + 2.2 * scale), y: round(y + 2 * scale), width: round(1 * scale), height: round(1 * scale), className: "fill-neutral-800 dark:fill-neutral-200" }), _jsx("rect", { x: round(x + 2.2 * scale), y: round(y + 7 * scale), width: round(1 * scale), height: round(1 * scale), className: "fill-neutral-800 dark:fill-neutral-200" })] }, keyPrefix));
|
|
145
|
+
}
|
|
146
|
+
if (!SEGMENTS[ch])
|
|
147
|
+
return null;
|
|
148
|
+
return _jsx("g", { children: renderSegmentDigit(ch, x, y, scale, keyPrefix) }, keyPrefix);
|
|
149
|
+
}
|
|
150
|
+
function renderSegmentText(text, sizePx) {
|
|
151
|
+
const baseScale = sizePx / 16;
|
|
152
|
+
const digitW = 6 * baseScale;
|
|
153
|
+
const digitH = 10 * baseScale;
|
|
154
|
+
const gap = 1.4 * baseScale;
|
|
155
|
+
const colonW = 4 * baseScale;
|
|
156
|
+
let width = 0;
|
|
157
|
+
for (const ch of text) {
|
|
158
|
+
width += ch === ":" ? colonW : digitW;
|
|
159
|
+
width += gap;
|
|
160
|
+
}
|
|
161
|
+
width -= gap;
|
|
162
|
+
const height = digitH;
|
|
163
|
+
let cursor = 0;
|
|
164
|
+
const nodes = [];
|
|
165
|
+
text.split("").forEach((ch, idx) => {
|
|
166
|
+
const w = ch === ":" ? colonW : digitW;
|
|
167
|
+
nodes.push(renderSegmentChar(ch, cursor, 0, baseScale, `seg-${idx}`));
|
|
168
|
+
cursor += w + gap;
|
|
169
|
+
});
|
|
170
|
+
return { width, height, nodes };
|
|
171
|
+
}
|
|
172
|
+
function wrapRange(value, start, end) {
|
|
173
|
+
const size = end - start + 1;
|
|
174
|
+
const v = ((value - start) % size + size) % size;
|
|
175
|
+
return start + v;
|
|
176
|
+
}
|
|
177
|
+
function getTimeValue(date, locale, timeZone, mode, smooth) {
|
|
178
|
+
const { h, m, s } = getHmsForTimezone(date, locale, timeZone);
|
|
179
|
+
const ms = date.getMilliseconds();
|
|
180
|
+
if (mode === "hours") {
|
|
181
|
+
if (!smooth)
|
|
182
|
+
return { base: h, frac: 0 };
|
|
183
|
+
const value = h + m / 60 + s / 3600;
|
|
184
|
+
return { base: Math.floor(value), frac: value - Math.floor(value) };
|
|
185
|
+
}
|
|
186
|
+
if (mode === "minutes") {
|
|
187
|
+
if (!smooth)
|
|
188
|
+
return { base: m, frac: 0 };
|
|
189
|
+
const value = m + s / 60;
|
|
190
|
+
return { base: Math.floor(value), frac: value - Math.floor(value) };
|
|
191
|
+
}
|
|
192
|
+
if (!smooth)
|
|
193
|
+
return { base: s, frac: 0 };
|
|
194
|
+
const value = s + ms / 1000;
|
|
195
|
+
return { base: Math.floor(value), frac: value - Math.floor(value) };
|
|
196
|
+
}
|
|
197
|
+
function AnalogClock({ size = 280, timezone, locale = "pt-BR", showSeconds = true, secondHandMode = "step", themeId = "classic", theme, className, centerOverlay }) {
|
|
198
|
+
const { tick, nowMs } = useSgTime();
|
|
199
|
+
void tick;
|
|
200
|
+
useSecondTick();
|
|
201
|
+
const resolver = useSgClockThemeResolver();
|
|
202
|
+
const dark = useDarkFlag();
|
|
203
|
+
const date = new Date(nowMs());
|
|
204
|
+
const { h, m, s } = getHmsForTimezone(date, locale, timezone);
|
|
205
|
+
const ms = date.getMilliseconds();
|
|
206
|
+
const sec = secondHandMode === "smooth" ? s + ms / 1000 : s;
|
|
207
|
+
const secDeg = (sec / 60) * 360;
|
|
208
|
+
const minDeg = ((m + sec / 60) / 60) * 360;
|
|
209
|
+
const hourDeg = (((h % 12) + m / 60 + sec / 3600) / 12) * 360;
|
|
210
|
+
const themeObj = theme ??
|
|
211
|
+
(resolver ? resolveTheme(resolver, themeId, "classic") : getTheme(themeId) ?? getTheme("classic"));
|
|
212
|
+
return (_jsx("div", { className: className, children: _jsxs("svg", { width: size, height: size, viewBox: "0 0 100 100", className: "block", "aria-label": "Analog clock", children: [_jsx("g", { id: "theme", children: themeObj ? _jsx(ThemeLayer, { theme: themeObj, args: { size, dark } }) : null }), _jsxs("g", { id: "hands", children: [_jsx("g", { transform: `rotate(${hourDeg} 50 50)`, children: _jsx("line", { x1: "50", y1: "50", x2: "50", y2: "28", className: "stroke-neutral-800 dark:stroke-neutral-200", strokeWidth: "2.6", strokeLinecap: "round" }) }), _jsx("g", { transform: `rotate(${minDeg} 50 50)`, children: _jsx("line", { x1: "50", y1: "50", x2: "50", y2: "18", className: "stroke-neutral-800 dark:stroke-neutral-200", strokeWidth: "1.7", strokeLinecap: "round" }) }), showSeconds && (_jsx("g", { transform: `rotate(${secDeg} 50 50)`, children: _jsx("line", { x1: "50", y1: "54", x2: "50", y2: "14", className: "stroke-rose-500", strokeWidth: "0.9", strokeLinecap: "round" }) }))] }), _jsx("circle", { cx: "50", cy: "50", r: "2.2", className: "fill-neutral-800 dark:fill-neutral-200" }), showSeconds ? _jsx("circle", { cx: "50", cy: "50", r: "1.1", className: "fill-rose-500" }) : null, centerOverlay ? (_jsx("foreignObject", { x: "35", y: "35", width: "30", height: "30", children: _jsx("div", { className: "flex h-full w-full items-center justify-center", children: centerOverlay }) })) : null] }) }));
|
|
213
|
+
}
|
|
214
|
+
function FlipDigitCard({ ch, w, h, digitFont }) {
|
|
215
|
+
const prevRef = React.useRef(ch);
|
|
216
|
+
const [prev, setPrev] = React.useState(ch);
|
|
217
|
+
const [flip, setFlip] = React.useState(false);
|
|
218
|
+
const [animKey, setAnimKey] = React.useState(0);
|
|
219
|
+
React.useEffect(() => {
|
|
220
|
+
if (ch === prevRef.current)
|
|
221
|
+
return;
|
|
222
|
+
setPrev(prevRef.current);
|
|
223
|
+
setFlip(false);
|
|
224
|
+
const raf = window.requestAnimationFrame(() => {
|
|
225
|
+
setAnimKey((v) => v + 1);
|
|
226
|
+
setFlip(true);
|
|
227
|
+
});
|
|
228
|
+
const id = window.setTimeout(() => {
|
|
229
|
+
setFlip(false);
|
|
230
|
+
prevRef.current = ch;
|
|
231
|
+
}, 1200);
|
|
232
|
+
return () => {
|
|
233
|
+
window.cancelAnimationFrame(raf);
|
|
234
|
+
window.clearTimeout(id);
|
|
235
|
+
};
|
|
236
|
+
}, [ch]);
|
|
237
|
+
const panel = "relative overflow-hidden rounded-lg bg-neutral-900 text-white shadow-[0_10px_24px_rgba(0,0,0,0.4)]";
|
|
238
|
+
const seam = "absolute left-0 right-0 top-1/2 z-10 h-[3px] bg-gradient-to-b from-black/70 to-transparent shadow-[0_3px_8px_rgba(0,0,0,0.7),0_-2px_6px_rgba(255,255,255,0.25)]";
|
|
239
|
+
const half = "absolute left-0 w-full overflow-hidden";
|
|
240
|
+
const glossTop = "before:absolute before:inset-0 before:bg-gradient-to-b before:from-white/10 before:to-transparent before:content-['']";
|
|
241
|
+
const glossBottom = "after:absolute after:inset-0 after:bg-gradient-to-t after:from-black/30 after:to-transparent after:content-['']";
|
|
242
|
+
return (_jsxs("div", { className: cn(panel, glossTop, glossBottom), style: { width: w, height: h, transformStyle: "preserve-3d", perspective: "1000px" }, children: [_jsx("div", { className: seam }), _jsx("div", { className: cn(half, "top-0"), style: { height: h / 2 }, children: _jsx("div", { className: "absolute flex items-center justify-center font-bold font-mono", style: {
|
|
243
|
+
fontSize: digitFont,
|
|
244
|
+
lineHeight: 1,
|
|
245
|
+
width: "100%",
|
|
246
|
+
height: h,
|
|
247
|
+
top: 0,
|
|
248
|
+
left: 0
|
|
249
|
+
}, children: flip ? prev : ch }) }), _jsx("div", { className: cn(half, "bottom-0"), style: { height: h / 2 }, children: _jsx("div", { className: "absolute flex items-center justify-center font-bold font-mono", style: {
|
|
250
|
+
fontSize: digitFont,
|
|
251
|
+
lineHeight: 1,
|
|
252
|
+
width: "100%",
|
|
253
|
+
height: h,
|
|
254
|
+
top: `-${h / 2}px`,
|
|
255
|
+
left: 0
|
|
256
|
+
}, children: ch }) }), flip ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute left-0 top-0 z-20 w-full overflow-hidden rounded-t-lg", style: { height: h / 2 }, children: _jsx("div", { className: "flip-top", style: {
|
|
257
|
+
transformOrigin: "center bottom",
|
|
258
|
+
height: "100%",
|
|
259
|
+
width: "100%"
|
|
260
|
+
}, children: _jsx("div", { className: "absolute flex items-center justify-center font-bold font-mono", style: {
|
|
261
|
+
fontSize: digitFont,
|
|
262
|
+
lineHeight: 1,
|
|
263
|
+
width: "100%",
|
|
264
|
+
height: h,
|
|
265
|
+
top: 0,
|
|
266
|
+
left: 0
|
|
267
|
+
}, children: prev }) }, `top-${animKey}`) }), _jsx("div", { className: "absolute bottom-0 left-0 z-20 w-full overflow-hidden rounded-b-lg", style: { height: h / 2 }, children: _jsx("div", { className: "flip-bottom", style: {
|
|
268
|
+
transformOrigin: "center top",
|
|
269
|
+
height: "100%",
|
|
270
|
+
width: "100%"
|
|
271
|
+
}, children: _jsx("div", { className: "absolute flex items-center justify-center font-bold font-mono", style: {
|
|
272
|
+
fontSize: digitFont,
|
|
273
|
+
lineHeight: 1,
|
|
274
|
+
width: "100%",
|
|
275
|
+
height: h,
|
|
276
|
+
top: `-${h / 2}px`,
|
|
277
|
+
left: 0
|
|
278
|
+
}, children: ch }) }, `bottom-${animKey}`) })] })) : null] }));
|
|
279
|
+
}
|
|
280
|
+
function DigitalClock({ timezone, locale = "pt-BR", format = "24h", showSeconds = true, size = "md", digitalStyle = "default", className }) {
|
|
281
|
+
const { tick, nowMs } = useSgTime();
|
|
282
|
+
void tick;
|
|
283
|
+
useSecondTick();
|
|
284
|
+
const d = new Date(nowMs());
|
|
285
|
+
const parts = new Intl.DateTimeFormat(locale, {
|
|
286
|
+
timeZone: timezone,
|
|
287
|
+
hour: "2-digit",
|
|
288
|
+
minute: "2-digit",
|
|
289
|
+
second: showSeconds ? "2-digit" : undefined,
|
|
290
|
+
hour12: format === "12h"
|
|
291
|
+
}).formatToParts(d);
|
|
292
|
+
const getPart = (type) => parts.find((p) => p.type === type)?.value ?? "";
|
|
293
|
+
const hour = getPart("hour");
|
|
294
|
+
const minute = getPart("minute");
|
|
295
|
+
const second = getPart("second");
|
|
296
|
+
let dayPeriod = getPart("dayPeriod");
|
|
297
|
+
if (format === "12h" && !dayPeriod) {
|
|
298
|
+
const { h } = getHmsForTimezone(d, locale, timezone);
|
|
299
|
+
dayPeriod = h >= 12 ? "PM" : "AM";
|
|
300
|
+
}
|
|
301
|
+
const text = `${hour}:${minute}${showSeconds ? `:${second}` : ""}`;
|
|
302
|
+
const classSize = sizeToClass(size);
|
|
303
|
+
const fontSize = typeof size === "number" ? { fontSize: `${size}px`, lineHeight: 1 } : undefined;
|
|
304
|
+
const sizePx = digitalSizeToNumber(size);
|
|
305
|
+
if (digitalStyle === "flip") {
|
|
306
|
+
const hNum = Number.parseInt(hour, 10) || 0;
|
|
307
|
+
const mNum = Number.parseInt(minute, 10) || 0;
|
|
308
|
+
const sNum = Number.parseInt(second || "0", 10) || 0;
|
|
309
|
+
const safeHour = format === "12h" ? (hNum === 0 ? 12 : hNum) : hNum;
|
|
310
|
+
const hh = String(safeHour).padStart(2, "0");
|
|
311
|
+
const mm = String(mNum).padStart(2, "0");
|
|
312
|
+
const ss = String(sNum).padStart(2, "0");
|
|
313
|
+
const w = Math.round(sizePx * 1.62);
|
|
314
|
+
const h = Math.round(sizePx * 2.35);
|
|
315
|
+
const digitFont = Math.round(sizePx * 1.4);
|
|
316
|
+
const panel = "relative overflow-hidden rounded-lg bg-neutral-900 text-white shadow-[0_10px_24px_rgba(0,0,0,0.4)]";
|
|
317
|
+
const glossTop = "before:absolute before:inset-0 before:bg-gradient-to-b before:from-white/10 before:to-transparent before:content-['']";
|
|
318
|
+
const glossBottom = "after:absolute after:inset-0 after:bg-gradient-to-t after:from-black/30 after:to-transparent after:content-['']";
|
|
319
|
+
const Colon = () => (_jsxs("div", { className: "flex flex-col items-center justify-center", style: { height: h }, children: [_jsx("div", { className: "h-2 w-2 rounded-full bg-white/80" }), _jsx("div", { className: "mt-2 h-2 w-2 rounded-full bg-white/80" })] }));
|
|
320
|
+
const PeriodCell = ({ value }) => (_jsx("div", { className: cn(panel, glossTop, glossBottom, "flex items-center justify-center"), style: { width: Math.round(w * 1.35), height: h }, children: _jsx("span", { className: "font-semibold text-white/90", style: { fontSize: Math.round(sizePx * 1.05), lineHeight: 1 }, children: value }) }));
|
|
321
|
+
return (_jsxs("div", { className: cn("flex items-center gap-2", className), "aria-label": "Digital clock", children: [_jsx("style", { children: `
|
|
322
|
+
.flip-top {
|
|
323
|
+
background: #1a1a1a;
|
|
324
|
+
border-radius: 8px 8px 0 0;
|
|
325
|
+
animation: sgFlipTop 0.6s cubic-bezier(0.4, 0.0, 0.2, 1) both;
|
|
326
|
+
backface-visibility: hidden;
|
|
327
|
+
transform-style: preserve-3d;
|
|
328
|
+
will-change: transform;
|
|
329
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.3), inset 0 -2px 4px rgba(0,0,0,0.2);
|
|
330
|
+
}
|
|
331
|
+
.flip-bottom {
|
|
332
|
+
background: #1a1a1a;
|
|
333
|
+
border-radius: 0 0 8px 8px;
|
|
334
|
+
animation: sgFlipBottom 0.6s cubic-bezier(0.4, 0.0, 0.2, 1) both;
|
|
335
|
+
animation-delay: 0.6s;
|
|
336
|
+
backface-visibility: hidden;
|
|
337
|
+
transform-style: preserve-3d;
|
|
338
|
+
will-change: transform;
|
|
339
|
+
box-shadow: 0 -2px 8px rgba(0,0,0,0.3), inset 0 2px 4px rgba(0,0,0,0.2);
|
|
340
|
+
}
|
|
341
|
+
@keyframes sgFlipTop {
|
|
342
|
+
0% {
|
|
343
|
+
transform: rotateX(0deg);
|
|
344
|
+
z-index: 30;
|
|
345
|
+
}
|
|
346
|
+
100% {
|
|
347
|
+
transform: rotateX(-180deg);
|
|
348
|
+
z-index: 5;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
@keyframes sgFlipBottom {
|
|
352
|
+
0% {
|
|
353
|
+
transform: rotateX(180deg);
|
|
354
|
+
z-index: 5;
|
|
355
|
+
}
|
|
356
|
+
100% {
|
|
357
|
+
transform: rotateX(0deg);
|
|
358
|
+
z-index: 30;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
` }), _jsx(FlipDigitCard, { ch: hh.charAt(0), w: w, h: h, digitFont: digitFont }), _jsx(FlipDigitCard, { ch: hh.charAt(1), w: w, h: h, digitFont: digitFont }), _jsx(Colon, {}), _jsx(FlipDigitCard, { ch: mm.charAt(0), w: w, h: h, digitFont: digitFont }), _jsx(FlipDigitCard, { ch: mm.charAt(1), w: w, h: h, digitFont: digitFont }), showSeconds ? (_jsxs(_Fragment, { children: [_jsx(Colon, {}), _jsx(FlipDigitCard, { ch: ss.charAt(0), w: w, h: h, digitFont: digitFont }), _jsx(FlipDigitCard, { ch: ss.charAt(1), w: w, h: h, digitFont: digitFont })] })) : null, format === "12h" && dayPeriod ? _jsx(PeriodCell, { value: dayPeriod.toUpperCase() }) : null] }));
|
|
362
|
+
}
|
|
363
|
+
if (digitalStyle === "roller3d") {
|
|
364
|
+
const hNum = Number.parseInt(hour, 10) || 0;
|
|
365
|
+
const mNum = Number.parseInt(minute, 10) || 0;
|
|
366
|
+
const sNum = Number.parseInt(second || "0", 10) || 0;
|
|
367
|
+
const hourMax = format === "12h" ? 12 : 23;
|
|
368
|
+
const hourMin = format === "12h" ? 1 : 0;
|
|
369
|
+
const safeHour = format === "12h" ? (hNum === 0 ? 12 : hNum) : hNum;
|
|
370
|
+
const hours = buildRange(hourMin, hourMax);
|
|
371
|
+
const minutes = buildRange(0, 59);
|
|
372
|
+
const seconds = buildRange(0, 59);
|
|
373
|
+
const periodList = ["AM", "PM"];
|
|
374
|
+
const w = Math.round(sizePx * 2.8);
|
|
375
|
+
const h = Math.round(sizePx * 3.6);
|
|
376
|
+
const itemH = Math.round(sizePx * 1.6);
|
|
377
|
+
const glow = "shadow-[inset_0_0_28px_rgba(0,0,0,0.08),0_8px_28px_rgba(0,0,0,0.12)]";
|
|
378
|
+
const face = "relative overflow-hidden rounded-2xl bg-white text-neutral-900 ring-1 ring-black/5";
|
|
379
|
+
const topShade = "before:absolute before:inset-0 before:bg-gradient-to-b before:from-black/6 before:to-transparent before:content-['']";
|
|
380
|
+
const bottomShade = "after:absolute after:inset-0 after:bg-gradient-to-t after:from-black/12 after:to-transparent after:content-['']";
|
|
381
|
+
const divider = "absolute left-0 right-0 top-1/2 h-px bg-red-500/70";
|
|
382
|
+
const mask = "[mask-image:linear-gradient(to_bottom,transparent,black_22%,black_78%,transparent)]";
|
|
383
|
+
const renderRoll = (list, value, pad = 2) => {
|
|
384
|
+
const idx = typeof value === "string" ? list.indexOf(value) : list.indexOf(value);
|
|
385
|
+
const translateY = -idx * itemH + h / 2 - itemH / 2;
|
|
386
|
+
return (_jsxs("div", { className: cn("relative", glow, face, topShade, bottomShade), style: { width: w, height: h }, children: [_jsx("div", { className: divider }), _jsx("div", { className: cn("absolute left-0 top-0 w-full transition-transform duration-500 [transition-timing-function:cubic-bezier(0.22,1,0.36,1)]", mask), style: { transform: `translateY(${translateY}px)` }, children: list.map((v, i) => (_jsx("div", { className: "flex h-[var(--sg-roll-h)] items-center justify-center font-medium tabular-nums text-neutral-400", style: {
|
|
387
|
+
height: itemH,
|
|
388
|
+
fontSize: Math.round(sizePx * 1.35),
|
|
389
|
+
color: i === idx ? "rgb(30 30 34)" : "rgb(163 163 170)"
|
|
390
|
+
}, children: typeof v === "number" ? String(v).padStart(pad, "0") : v }, `${v}-${i}`))) })] }));
|
|
391
|
+
};
|
|
392
|
+
return (_jsxs("div", { className: cn("flex items-center gap-4", className), style: fontSize, "aria-label": "Digital clock", children: [renderRoll(hours, safeHour), renderRoll(minutes, mNum), showSeconds ? renderRoll(seconds, sNum) : null, format === "12h" && dayPeriod ? renderRoll(periodList, dayPeriod.toUpperCase(), 0) : null] }));
|
|
393
|
+
}
|
|
394
|
+
if (digitalStyle === "segment") {
|
|
395
|
+
const seg = renderSegmentText(text, sizePx);
|
|
396
|
+
return (_jsxs("div", { className: cn("flex items-end gap-2", className), "aria-label": "Digital clock", children: [_jsx("svg", { width: seg.width, height: seg.height, viewBox: `0 0 ${seg.width} ${seg.height}`, className: "block", children: seg.nodes }), format === "12h" && dayPeriod ? (_jsx("span", { className: "text-xs font-semibold text-muted-foreground", children: dayPeriod })) : null] }));
|
|
397
|
+
}
|
|
398
|
+
return (_jsxs("div", { className: cn("font-mono tabular-nums", classSize, className), style: fontSize, children: [text, format === "12h" && dayPeriod ? (_jsx("span", { className: "ml-2 align-top text-xs font-semibold text-muted-foreground", children: dayPeriod })) : null] }));
|
|
399
|
+
}
|
|
400
|
+
export function SgClock(props) {
|
|
401
|
+
const { variant = "digital", size = "md", timezone, locale = "pt-BR", format = "24h", showSeconds = true, digitalStyle = "default", secondHandMode = "step", themeId = "classic", theme, className, centerOverlay } = props;
|
|
402
|
+
if (variant === "analog") {
|
|
403
|
+
const analogSize = typeof size === "number" ? size : size === "sm" ? 140 : size === "lg" ? 320 : 240;
|
|
404
|
+
return (_jsx(AnalogClock, { size: analogSize, themeId: themeId, theme: theme, timezone: timezone, locale: locale, showSeconds: showSeconds, secondHandMode: secondHandMode, className: className, centerOverlay: centerOverlay }));
|
|
405
|
+
}
|
|
406
|
+
return (_jsx(DigitalClock, { timezone: timezone, locale: locale, format: format, showSeconds: showSeconds, size: size, digitalStyle: digitalStyle, className: className }));
|
|
407
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type SgTimeContextValue = {
|
|
3
|
+
serverStartMs: number;
|
|
4
|
+
perfStartMs: number;
|
|
5
|
+
tick: number;
|
|
6
|
+
nowMs: () => number;
|
|
7
|
+
};
|
|
8
|
+
export declare function useSgTime(): SgTimeContextValue;
|
|
9
|
+
export declare function SgTimeProvider({ initialServerTime, children }: {
|
|
10
|
+
initialServerTime: string;
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=SgTimeProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgTimeProvider.d.ts","sourceRoot":"","sources":["../../../src/gadgets/clock/SgTimeProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,kBAAkB,GAAG;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,MAAM,CAAC;CACrB,CAAC;AAIF,wBAAgB,SAAS,uBAIxB;AAED,wBAAgB,cAAc,CAAC,EAC7B,iBAAiB,EACjB,QAAQ,EACT,EAAE;IACD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,2CAyCA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
const SgTimeContext = React.createContext(null);
|
|
5
|
+
export function useSgTime() {
|
|
6
|
+
const ctx = React.useContext(SgTimeContext);
|
|
7
|
+
if (!ctx)
|
|
8
|
+
throw new Error("useSgTime must be used within <SgTimeProvider />");
|
|
9
|
+
return ctx;
|
|
10
|
+
}
|
|
11
|
+
export function SgTimeProvider({ initialServerTime, children }) {
|
|
12
|
+
const serverStartMsRef = React.useRef(Date.parse(initialServerTime));
|
|
13
|
+
const perfStartMsRef = React.useRef(0);
|
|
14
|
+
const [tick, setTick] = React.useState(0);
|
|
15
|
+
const [hydrated, setHydrated] = React.useState(false);
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
perfStartMsRef.current = performance.now();
|
|
18
|
+
setHydrated(true);
|
|
19
|
+
const alignDelay = 1000 - (Date.now() % 1000);
|
|
20
|
+
let intervalId = null;
|
|
21
|
+
const timeoutId = window.setTimeout(() => {
|
|
22
|
+
setTick((x) => x + 1);
|
|
23
|
+
intervalId = window.setInterval(() => setTick((x) => x + 1), 1000);
|
|
24
|
+
}, alignDelay);
|
|
25
|
+
return () => {
|
|
26
|
+
window.clearTimeout(timeoutId);
|
|
27
|
+
if (intervalId)
|
|
28
|
+
window.clearInterval(intervalId);
|
|
29
|
+
};
|
|
30
|
+
}, []);
|
|
31
|
+
const nowMs = React.useCallback(() => {
|
|
32
|
+
if (!hydrated)
|
|
33
|
+
return serverStartMsRef.current;
|
|
34
|
+
const delta = performance.now() - perfStartMsRef.current;
|
|
35
|
+
return serverStartMsRef.current + delta;
|
|
36
|
+
}, [hydrated]);
|
|
37
|
+
const value = React.useMemo(() => ({
|
|
38
|
+
serverStartMs: serverStartMsRef.current,
|
|
39
|
+
perfStartMs: perfStartMsRef.current,
|
|
40
|
+
tick,
|
|
41
|
+
nowMs
|
|
42
|
+
}), [tick, nowMs]);
|
|
43
|
+
return _jsx(SgTimeContext.Provider, { value: value, children: children });
|
|
44
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SgClockTheme } from "./types";
|
|
2
|
+
export type SgClockThemePickerProps = {
|
|
3
|
+
value: string;
|
|
4
|
+
onChange: (id: string) => void;
|
|
5
|
+
label?: string;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
filter?: (theme: SgClockTheme) => boolean;
|
|
9
|
+
previewSize?: number;
|
|
10
|
+
searchable?: boolean;
|
|
11
|
+
fallbackThemeId?: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function SgClockThemePicker({ value, onChange, label, placeholder, className, filter, previewSize, searchable, fallbackThemeId }: SgClockThemePickerProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=SgClockThemePicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgClockThemePicker.d.ts","sourceRoot":"","sources":["../../../../src/gadgets/clock/themes/SgClockThemePicker.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAS5C,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,QAAQ,EACR,KAAe,EACf,WAAiC,EACjC,SAAS,EACT,MAAM,EACN,WAAgB,EAChB,UAAiB,EACjB,eAA2B,EAC5B,EAAE,uBAAuB,2CAsJzB"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { useSgClockThemeResolver } from "./provider";
|
|
5
|
+
import { SgClockThemePreview } from "./SgClockThemePreview";
|
|
6
|
+
import { SgAutocomplete } from "../../../inputs/SgAutocomplete";
|
|
7
|
+
function cn(...parts) {
|
|
8
|
+
return parts.filter(Boolean).join(" ");
|
|
9
|
+
}
|
|
10
|
+
export function SgClockThemePicker({ value, onChange, label = "Theme", placeholder = "Select a theme...", className, filter, previewSize = 56, searchable = true, fallbackThemeId = "classic" }) {
|
|
11
|
+
const resolver = useSgClockThemeResolver();
|
|
12
|
+
const all = React.useMemo(() => {
|
|
13
|
+
const list = resolver?.list() ?? [];
|
|
14
|
+
return filter ? list.filter(filter) : list;
|
|
15
|
+
}, [resolver, filter]);
|
|
16
|
+
const [open, setOpen] = React.useState(false);
|
|
17
|
+
const [q, setQ] = React.useState("");
|
|
18
|
+
const currentTheme = React.useMemo(() => {
|
|
19
|
+
const found = resolver?.resolve(value) ?? all.find((t) => t.id === value) ?? null;
|
|
20
|
+
if (found)
|
|
21
|
+
return found;
|
|
22
|
+
return resolver?.resolve(fallbackThemeId) ?? all.find((t) => t.id === fallbackThemeId) ?? null;
|
|
23
|
+
}, [resolver, value, all, fallbackThemeId]);
|
|
24
|
+
const filtered = React.useMemo(() => {
|
|
25
|
+
const s = q.trim().toLowerCase();
|
|
26
|
+
if (!s)
|
|
27
|
+
return all;
|
|
28
|
+
return all.filter((t) => {
|
|
29
|
+
const hay = `${t.id} ${t.label ?? ""} ${(t.tags ?? []).join(" ")}`.toLowerCase();
|
|
30
|
+
return hay.includes(s);
|
|
31
|
+
});
|
|
32
|
+
}, [all, q]);
|
|
33
|
+
const rootRef = React.useRef(null);
|
|
34
|
+
React.useEffect(() => {
|
|
35
|
+
if (!open)
|
|
36
|
+
return;
|
|
37
|
+
const onDoc = (e) => {
|
|
38
|
+
const el = rootRef.current;
|
|
39
|
+
if (!el)
|
|
40
|
+
return;
|
|
41
|
+
if (!el.contains(e.target))
|
|
42
|
+
setOpen(false);
|
|
43
|
+
};
|
|
44
|
+
document.addEventListener("mousedown", onDoc);
|
|
45
|
+
return () => document.removeEventListener("mousedown", onDoc);
|
|
46
|
+
}, [open]);
|
|
47
|
+
return (_jsxs("div", { ref: rootRef, className: cn("relative", className), children: [label ? _jsx("div", { className: "mb-1 text-xs font-medium opacity-70", children: label }) : null, _jsx("button", { type: "button", onClick: () => setOpen((v) => !v), className: cn("w-full rounded-lg border border-neutral-200 bg-white px-3 py-2 text-left shadow-sm", "hover:bg-neutral-50", "dark:border-neutral-800 dark:bg-neutral-950 dark:hover:bg-neutral-900/40"), children: _jsxs("div", { className: "flex items-center gap-3", children: [currentTheme ? (_jsx("div", { className: "text-neutral-800 dark:text-neutral-200", children: _jsx(SgClockThemePreview, { theme: currentTheme, size: previewSize }) })) : (_jsx("div", { className: "h-[56px] w-[56px] rounded-md border border-neutral-200 dark:border-neutral-800" })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-sm font-medium", children: currentTheme?.label ?? currentTheme?.id ?? placeholder }), _jsx("div", { className: "truncate text-xs opacity-60", children: currentTheme?.id ?? "" })] }), _jsx("div", { className: "text-xs opacity-60", children: open ? "^" : "v" })] }) }), open && (_jsxs("div", { className: cn("absolute z-50 mt-2 w-full overflow-hidden rounded-xl border border-neutral-200 bg-white shadow-lg", "dark:border-neutral-800 dark:bg-neutral-950"), children: [searchable && (_jsx("div", { className: "p-2", children: _jsx(SgAutocomplete, { id: "sg-clock-theme-search", label: "Search theme", placeholder: "Search theme...", openOnFocus: true, showDropDownButton: true, clearOnSelect: true, minLengthForSearch: 0, source: (query) => {
|
|
48
|
+
const s = (query ?? "").trim().toLowerCase();
|
|
49
|
+
const items = all.map((t) => ({
|
|
50
|
+
id: t.id,
|
|
51
|
+
label: t.label ?? t.id,
|
|
52
|
+
value: t.id,
|
|
53
|
+
data: t
|
|
54
|
+
}));
|
|
55
|
+
if (!s)
|
|
56
|
+
return items;
|
|
57
|
+
return items.filter((item) => item.label?.toLowerCase().includes(s));
|
|
58
|
+
}, onSelect: (item) => {
|
|
59
|
+
const id = item.value ?? item.id;
|
|
60
|
+
onChange(String(id));
|
|
61
|
+
setOpen(false);
|
|
62
|
+
} }) })), _jsx("div", { className: "max-h-80 overflow-auto p-2", children: filtered.length === 0 ? (_jsx("div", { className: "p-3 text-sm opacity-60", children: "No themes found." })) : (_jsx("div", { className: "space-y-1", children: filtered.map((t) => {
|
|
63
|
+
const active = t.id === value;
|
|
64
|
+
return (_jsx("button", { type: "button", onClick: () => {
|
|
65
|
+
onChange(t.id);
|
|
66
|
+
setOpen(false);
|
|
67
|
+
}, className: cn("w-full rounded-lg p-2 text-left transition", active
|
|
68
|
+
? "bg-neutral-900 text-white dark:bg-white dark:text-neutral-900"
|
|
69
|
+
: "hover:bg-neutral-50 dark:hover:bg-neutral-900/40"), children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: cn(active ? "text-white dark:text-neutral-900" : "text-neutral-800 dark:text-neutral-200"), children: _jsx(SgClockThemePreview, { theme: t, size: 44 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-sm font-medium", children: t.label ?? t.id }), _jsx("div", { className: cn("truncate text-xs", active ? "opacity-80" : "opacity-60"), children: t.id })] }), active ? _jsx("div", { className: "text-xs opacity-80", children: "OK" }) : null] }) }, t.id));
|
|
70
|
+
}) })) })] }))] }));
|
|
71
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SgClockTheme } from "./types";
|
|
2
|
+
export declare function SgClockThemePreview({ theme, size, className }: {
|
|
3
|
+
theme: SgClockTheme;
|
|
4
|
+
size?: number;
|
|
5
|
+
className?: string;
|
|
6
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=SgClockThemePreview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgClockThemePreview.d.ts","sourceRoot":"","sources":["../../../../src/gadgets/clock/themes/SgClockThemePreview.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAI5C,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,IAAS,EACT,SAAS,EACV,EAAE;IACD,KAAK,EAAE,YAAY,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,2CAiCA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { ThemeLayer } from "./renderTheme";
|
|
4
|
+
import { useDarkFlag } from "./useDarkFlag";
|
|
5
|
+
export function SgClockThemePreview({ theme, size = 64, className }) {
|
|
6
|
+
const dark = useDarkFlag();
|
|
7
|
+
const hourDeg = 305;
|
|
8
|
+
const minDeg = 60;
|
|
9
|
+
const secDeg = 180;
|
|
10
|
+
return (_jsxs("svg", { width: size, height: size, viewBox: "0 0 100 100", className: className ?? "block", "aria-hidden": "true", children: [_jsx("g", { id: "theme", children: _jsx(ThemeLayer, { theme: theme, args: { size, dark } }) }), _jsxs("g", { id: "hands", opacity: "0.9", children: [_jsx("g", { transform: `rotate(${hourDeg} 50 50)`, children: _jsx("line", { x1: "50", y1: "50", x2: "50", y2: "32", stroke: "currentColor", strokeWidth: "2.8", strokeLinecap: "round" }) }), _jsx("g", { transform: `rotate(${minDeg} 50 50)`, children: _jsx("line", { x1: "50", y1: "50", x2: "50", y2: "22", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }) }), _jsx("g", { transform: `rotate(${secDeg} 50 50)`, opacity: "0.7", children: _jsx("line", { x1: "50", y1: "54", x2: "50", y2: "16", stroke: "currentColor", strokeWidth: "0.9", strokeLinecap: "round" }) }), _jsx("circle", { cx: "50", cy: "50", r: "2.2", fill: "currentColor" })] })] }));
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../../../../src/gadgets/clock/themes/builtins.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAgjB5C,eAAO,MAAM,oBAAoB,EAAE,YAAY,EAW9C,CAAC"}
|