@seedgrid/fe-components 2026.3.20 → 2026.3.26
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/buttons/SgFloatActionButton.d.ts.map +1 -1
- package/dist/buttons/SgFloatActionButton.js +5 -26
- package/dist/buttons/SgSplitButton.d.ts.map +1 -1
- package/dist/buttons/SgSplitButton.js +3 -1
- package/dist/buttons/fab-helpers.d.ts +6 -0
- package/dist/buttons/fab-helpers.d.ts.map +1 -0
- package/dist/buttons/fab-helpers.js +29 -0
- package/dist/commons/SgAvatar.d.ts.map +1 -1
- package/dist/commons/SgAvatar.js +6 -3
- package/dist/commons/SgBadge.d.ts.map +1 -1
- package/dist/commons/SgBadge.js +5 -2
- package/dist/commons/SgToast.d.ts.map +1 -1
- package/dist/commons/SgToast.js +3 -1
- package/dist/commons/SgToaster.d.ts.map +1 -1
- package/dist/commons/SgToaster.js +3 -1
- package/dist/environment/SgEnvironmentProvider.d.ts.map +1 -1
- package/dist/environment/SgEnvironmentProvider.js +10 -15
- package/dist/environment/persistent-state.d.ts +22 -0
- package/dist/environment/persistent-state.d.ts.map +1 -0
- package/dist/environment/persistent-state.js +33 -0
- package/dist/gadgets/calendar/SgCalendar.d.ts.map +1 -1
- package/dist/gadgets/calendar/SgCalendar.js +5 -23
- package/dist/gadgets/clock/SgClock.d.ts.map +1 -1
- package/dist/gadgets/clock/SgClock.js +12 -10
- package/dist/gadgets/clock/themes/SgClockThemePicker.d.ts +2 -1
- package/dist/gadgets/clock/themes/SgClockThemePicker.d.ts.map +1 -1
- package/dist/gadgets/clock/themes/SgClockThemePicker.js +23 -28
- package/dist/gadgets/clock/themes/search.d.ts +9 -0
- package/dist/gadgets/clock/themes/search.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/search.js +15 -0
- package/dist/gadgets/gauge/SgLinearGauge.d.ts.map +1 -1
- package/dist/gadgets/gauge/SgLinearGauge.js +39 -28
- package/dist/gadgets/gauge/SgRadialGauge.d.ts.map +1 -1
- package/dist/gadgets/gauge/SgRadialGauge.js +44 -37
- package/dist/gadgets/gauge/math.d.ts +90 -0
- package/dist/gadgets/gauge/math.d.ts.map +1 -0
- package/dist/gadgets/gauge/math.js +81 -0
- package/dist/gadgets/qr-code/SgQRCode.d.ts.map +1 -1
- package/dist/gadgets/qr-code/SgQRCode.js +3 -1
- package/dist/i18n/en-US.d.ts.map +1 -1
- package/dist/i18n/en-US.js +97 -1
- package/dist/i18n/es.d.ts.map +1 -1
- package/dist/i18n/es.js +153 -57
- package/dist/i18n/fr.d.ts +3 -0
- package/dist/i18n/fr.d.ts.map +1 -0
- package/dist/i18n/fr.js +206 -0
- package/dist/i18n/index.d.ts +5 -1
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +50 -14
- package/dist/i18n/pt-BR.d.ts.map +1 -1
- package/dist/i18n/pt-BR.js +97 -1
- package/dist/i18n/pt-PT.d.ts.map +1 -1
- package/dist/i18n/pt-PT.js +97 -1
- package/dist/index.d.ts +12 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -2
- package/dist/inputs/SgAutocomplete.d.ts +1 -1
- package/dist/inputs/SgAutocomplete.d.ts.map +1 -1
- package/dist/inputs/SgAutocomplete.js +7 -4
- package/dist/inputs/SgCheckboxGroup.d.ts +2 -6
- package/dist/inputs/SgCheckboxGroup.d.ts.map +1 -1
- package/dist/inputs/SgCheckboxGroup.js +6 -6
- package/dist/inputs/SgCombobox.d.ts.map +1 -1
- package/dist/inputs/SgCombobox.js +11 -2
- package/dist/inputs/SgInputBirthDate.d.ts.map +1 -1
- package/dist/inputs/SgInputBirthDate.js +6 -1
- package/dist/inputs/SgInputCNPJ.d.ts +3 -1
- package/dist/inputs/SgInputCNPJ.d.ts.map +1 -1
- package/dist/inputs/SgInputCNPJ.js +4 -3
- package/dist/inputs/SgInputCPF.d.ts +3 -1
- package/dist/inputs/SgInputCPF.d.ts.map +1 -1
- package/dist/inputs/SgInputCPF.js +8 -3
- package/dist/inputs/SgInputCPFCNPJ.d.ts +3 -1
- package/dist/inputs/SgInputCPFCNPJ.d.ts.map +1 -1
- package/dist/inputs/SgInputCPFCNPJ.js +8 -3
- package/dist/inputs/SgInputCurrency.d.ts +3 -7
- package/dist/inputs/SgInputCurrency.d.ts.map +1 -1
- package/dist/inputs/SgInputCurrency.js +5 -2
- package/dist/inputs/SgInputDate.d.ts.map +1 -1
- package/dist/inputs/SgInputDate.js +6 -1
- package/dist/inputs/SgInputEmail.d.ts.map +1 -1
- package/dist/inputs/SgInputEmail.js +1 -1
- package/dist/inputs/SgInputNumber.d.ts +3 -7
- package/dist/inputs/SgInputNumber.d.ts.map +1 -1
- package/dist/inputs/SgInputNumber.js +5 -2
- package/dist/inputs/SgInputOTP.d.ts +5 -12
- package/dist/inputs/SgInputOTP.d.ts.map +1 -1
- package/dist/inputs/SgInputOTP.js +7 -4
- package/dist/inputs/SgInputPassword.d.ts.map +1 -1
- package/dist/inputs/SgInputPassword.js +1 -1
- package/dist/inputs/SgInputPhone.d.ts +3 -1
- package/dist/inputs/SgInputPhone.d.ts.map +1 -1
- package/dist/inputs/SgInputPhone.js +2 -1
- package/dist/inputs/SgInputPostalCode.d.ts.map +1 -1
- package/dist/inputs/SgInputPostalCode.js +2 -1
- package/dist/inputs/SgInputSelect.d.ts +4 -2
- package/dist/inputs/SgInputSelect.d.ts.map +1 -1
- package/dist/inputs/SgInputSelect.js +38 -3
- package/dist/inputs/SgInputText.d.ts +3 -7
- package/dist/inputs/SgInputText.d.ts.map +1 -1
- package/dist/inputs/SgInputText.js +5 -2
- package/dist/inputs/SgInputTextArea.d.ts +4 -2
- package/dist/inputs/SgInputTextArea.d.ts.map +1 -1
- package/dist/inputs/SgInputTextArea.js +37 -2
- package/dist/inputs/SgOrderList.d.ts +3 -1
- package/dist/inputs/SgOrderList.d.ts.map +1 -1
- package/dist/inputs/SgOrderList.js +19 -3
- package/dist/inputs/SgPickList.d.ts +3 -1
- package/dist/inputs/SgPickList.d.ts.map +1 -1
- package/dist/inputs/SgPickList.js +20 -4
- package/dist/inputs/SgRadioGroup.d.ts +2 -6
- package/dist/inputs/SgRadioGroup.d.ts.map +1 -1
- package/dist/inputs/SgRadioGroup.js +6 -6
- package/dist/inputs/SgRating.d.ts +2 -10
- package/dist/inputs/SgRating.d.ts.map +1 -1
- package/dist/inputs/SgRating.js +6 -3
- package/dist/inputs/SgSlider.d.ts +8 -2
- package/dist/inputs/SgSlider.d.ts.map +1 -1
- package/dist/inputs/SgSlider.js +62 -10
- package/dist/inputs/SgStepperInput.d.ts +8 -2
- package/dist/inputs/SgStepperInput.d.ts.map +1 -1
- package/dist/inputs/SgStepperInput.js +62 -8
- package/dist/inputs/SgTextEditor.d.ts +3 -1
- package/dist/inputs/SgTextEditor.d.ts.map +1 -1
- package/dist/inputs/SgTextEditor.js +24 -11
- package/dist/inputs/SgToggleSwitch.d.ts +3 -7
- package/dist/inputs/SgToggleSwitch.d.ts.map +1 -1
- package/dist/inputs/SgToggleSwitch.js +6 -3
- package/dist/layout/SgBreadcrumb.d.ts.map +1 -1
- package/dist/layout/SgBreadcrumb.js +7 -3
- package/dist/layout/SgCard.d.ts.map +1 -1
- package/dist/layout/SgCard.js +3 -1
- package/dist/layout/SgCarousel.d.ts.map +1 -1
- package/dist/layout/SgCarousel.js +3 -1
- package/dist/layout/SgExpandablePanel.d.ts.map +1 -1
- package/dist/layout/SgExpandablePanel.js +3 -1
- package/dist/layout/SgMenu.d.ts.map +1 -1
- package/dist/layout/SgMenu.js +173 -297
- package/dist/layout/SgPageControl.d.ts.map +1 -1
- package/dist/layout/SgPageControl.js +7 -3
- package/dist/layout/SgToolBar.d.ts.map +1 -1
- package/dist/layout/SgToolBar.js +19 -55
- package/dist/layout/SgTreeView.d.ts.map +1 -1
- package/dist/layout/SgTreeView.js +7 -3
- package/dist/layout/drag-position.d.ts +7 -0
- package/dist/layout/drag-position.d.ts.map +1 -0
- package/dist/layout/drag-position.js +30 -0
- package/dist/layout/menu-logic.d.ts +187 -0
- package/dist/layout/menu-logic.d.ts.map +1 -0
- package/dist/layout/menu-logic.js +349 -0
- package/dist/layout/toolbar-logic.d.ts +26 -0
- package/dist/layout/toolbar-logic.d.ts.map +1 -0
- package/dist/layout/toolbar-logic.js +38 -0
- package/dist/menus/SgDockMenu.d.ts.map +1 -1
- package/dist/menus/SgDockMenu.js +44 -120
- package/dist/menus/dock-menu-logic.d.ts +50 -0
- package/dist/menus/dock-menu-logic.d.ts.map +1 -0
- package/dist/menus/dock-menu-logic.js +113 -0
- package/dist/overlay/SgDialog.d.ts.map +1 -1
- package/dist/overlay/SgDialog.js +4 -2
- package/dist/overlay/SgPopup.d.ts.map +1 -1
- package/dist/overlay/SgPopup.js +4 -1
- package/dist/rhf.d.ts +8 -3
- package/dist/rhf.d.ts.map +1 -1
- package/dist/rhf.js +18 -1
- package/dist/sandbox.cjs +60 -60
- package/dist/wizard/SgWizard.d.ts.map +1 -1
- package/dist/wizard/SgWizard.js +20 -32
- package/dist/wizard/logic.d.ts +9 -0
- package/dist/wizard/logic.d.ts.map +1 -0
- package/dist/wizard/logic.js +20 -0
- package/package.json +8 -6
|
@@ -93,6 +93,7 @@ function buildRange(min, max) {
|
|
|
93
93
|
return out;
|
|
94
94
|
}
|
|
95
95
|
function AnalogClock({ size = 280, initialServerTime, timezone, locale = "pt-BR", showSeconds = true, secondHandMode = "step", themeId = "classic", theme, className, style, centerOverlay }) {
|
|
96
|
+
const i18n = useComponentsI18n();
|
|
96
97
|
const { nowMs, hasProvider, providerTick } = useClockNowMs(initialServerTime);
|
|
97
98
|
void providerTick;
|
|
98
99
|
useSecondTick(!hasProvider);
|
|
@@ -107,9 +108,10 @@ function AnalogClock({ size = 280, initialServerTime, timezone, locale = "pt-BR"
|
|
|
107
108
|
const hourDeg = (((h % 12) + m / 60 + sec / 3600) / 12) * 360;
|
|
108
109
|
const themeObj = theme ??
|
|
109
110
|
(resolver ? resolveTheme(resolver, themeId, "classic") : getTheme(themeId) ?? getTheme("classic"));
|
|
110
|
-
return (_jsx("div", { className: className, style: style, children: _jsxs("svg", { width: size, height: size, viewBox: "0 0 100 100", className: cn("block", dark ? "dark" : undefined), "aria-label": "
|
|
111
|
+
return (_jsx("div", { className: className, style: style, children: _jsxs("svg", { width: size, height: size, viewBox: "0 0 100 100", className: cn("block", dark ? "dark" : undefined), "aria-label": t(i18n, "components.gadgets.clock.analogAria"), 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] }) }));
|
|
111
112
|
}
|
|
112
113
|
function DigitalClock({ initialServerTime, timezone, locale = "pt-BR", format = "24h", showSeconds = true, size = "md", digitalStyle = "default", className, style }) {
|
|
114
|
+
const i18n = useComponentsI18n();
|
|
113
115
|
const { nowMs, hasProvider, providerTick } = useClockNowMs(initialServerTime);
|
|
114
116
|
void providerTick;
|
|
115
117
|
useSecondTick(!hasProvider);
|
|
@@ -158,7 +160,7 @@ function DigitalClock({ initialServerTime, timezone, locale = "pt-BR", format =
|
|
|
158
160
|
fontWeight: 700,
|
|
159
161
|
lineHeight: 1
|
|
160
162
|
}, children: value }) }));
|
|
161
|
-
return (_jsxs("div", { className: cn("flex items-center gap-2", className), style: style, "aria-label": "
|
|
163
|
+
return (_jsxs("div", { className: cn("flex items-center gap-2", className), style: style, "aria-label": t(i18n, "components.gadgets.clock.digitalAria"), children: [_jsx(SgFlipDigit, { value: hh.charAt(0), fontSize: digitFont }), _jsx(SgFlipDigit, { value: hh.charAt(1), fontSize: digitFont }), _jsx(Colon, {}), _jsx(SgFlipDigit, { value: mm.charAt(0), fontSize: digitFont }), _jsx(SgFlipDigit, { value: mm.charAt(1), fontSize: digitFont }), showSeconds ? (_jsxs(_Fragment, { children: [_jsx(Colon, {}), _jsx(SgFlipDigit, { value: ss.charAt(0), fontSize: digitFont }), _jsx(SgFlipDigit, { value: ss.charAt(1), fontSize: digitFont })] })) : null, format === "12h" && dayPeriod ? _jsx(PeriodCell, { value: dayPeriod.toUpperCase() }) : null] }));
|
|
162
164
|
}
|
|
163
165
|
if (digitalStyle === "roller3d") {
|
|
164
166
|
const hNum = Number.parseInt(hour, 10) || 0;
|
|
@@ -175,7 +177,7 @@ function DigitalClock({ initialServerTime, timezone, locale = "pt-BR", format =
|
|
|
175
177
|
const hh = String(safeHour).padStart(2, "0");
|
|
176
178
|
const mm = String(mNum).padStart(2, "0");
|
|
177
179
|
const ss = String(sNum).padStart(2, "0");
|
|
178
|
-
return (_jsxs("div", { className: cn("flex items-center gap-4", className), style: { ...fontSize, ...style }, "aria-label": "
|
|
180
|
+
return (_jsxs("div", { className: cn("flex items-center gap-4", className), style: { ...fontSize, ...style }, "aria-label": t(i18n, "components.gadgets.clock.digitalAria"), children: [_jsx(SgRoller3DDigit, { value: hh, items: hourItems, fontSize: digitFont }), _jsx(SgRoller3DDigit, { value: mm, items: minuteItems, fontSize: digitFont }), showSeconds ? _jsx(SgRoller3DDigit, { value: ss, items: secondItems, fontSize: digitFont }) : null, format === "12h" && dayPeriod ? (_jsx(SgRoller3DDigit, { value: dayPeriod.toUpperCase(), items: periodItems, fontSize: digitFont })) : null] }));
|
|
179
181
|
}
|
|
180
182
|
if (digitalStyle === "fade") {
|
|
181
183
|
const hNum = Number.parseInt(hour, 10) || 0;
|
|
@@ -188,7 +190,7 @@ function DigitalClock({ initialServerTime, timezone, locale = "pt-BR", format =
|
|
|
188
190
|
const digitFont = Math.round(sizePx * 1.35);
|
|
189
191
|
const cardH = Math.round(digitFont * 1.4);
|
|
190
192
|
const Colon = () => (_jsxs("div", { className: "flex flex-col items-center justify-center gap-2", style: { height: cardH }, children: [_jsx("div", { className: "h-2 w-2 rounded-full bg-neutral-500/70" }), _jsx("div", { className: "h-2 w-2 rounded-full bg-neutral-500/70" })] }));
|
|
191
|
-
return (_jsxs("div", { className: cn("flex items-center gap-2", className), style: style, "aria-label": "
|
|
193
|
+
return (_jsxs("div", { className: cn("flex items-center gap-2", className), style: style, "aria-label": t(i18n, "components.gadgets.clock.digitalAria"), children: [_jsx(SgFadeDigit, { value: hh.charAt(0), fontSize: digitFont }), _jsx(SgFadeDigit, { value: hh.charAt(1), fontSize: digitFont }), _jsx(Colon, {}), _jsx(SgFadeDigit, { value: mm.charAt(0), fontSize: digitFont }), _jsx(SgFadeDigit, { value: mm.charAt(1), fontSize: digitFont }), showSeconds ? (_jsxs(_Fragment, { children: [_jsx(Colon, {}), _jsx(SgFadeDigit, { value: ss.charAt(0), fontSize: digitFont }), _jsx(SgFadeDigit, { value: ss.charAt(1), fontSize: digitFont })] })) : null, format === "12h" && dayPeriod ? (_jsx("span", { className: "text-xs font-semibold text-muted-foreground", children: dayPeriod.toUpperCase() })) : null] }));
|
|
192
194
|
}
|
|
193
195
|
if (digitalStyle === "discard") {
|
|
194
196
|
const hNum = Number.parseInt(hour, 10) || 0;
|
|
@@ -213,15 +215,15 @@ function DigitalClock({ initialServerTime, timezone, locale = "pt-BR", format =
|
|
|
213
215
|
};
|
|
214
216
|
const Colon = () => (_jsx(SgDiscardDigit, { value: ":", fontSize: Math.max(26, Math.round(digitFont * 0.72)), totalNumberPages: 1, transitionMs: 560, animateOnChange: false }));
|
|
215
217
|
const PeriodCell = ({ value }) => (_jsx(SgDiscardDigit, { value: value, fontSize: Math.max(20, Math.round(digitFont * 0.52)), totalNumberPages: 1, transitionMs: 560, animateOnChange: false }));
|
|
216
|
-
return (_jsxs("div", { className: cn("relative z-10 flex items-end gap-2", className), style: style, "aria-label": "
|
|
218
|
+
return (_jsxs("div", { className: cn("relative z-10 flex items-end gap-2", className), style: style, "aria-label": t(i18n, "components.gadgets.clock.digitalAria"), children: [_jsx(SgDiscardDigit, { value: hh.charAt(0), fontSize: digitFont, totalNumberPages: pagesForDigit(hh.charAt(0)), transitionMs: 560, changeAnimationMode: "incoming" }), _jsx(SgDiscardDigit, { value: hh.charAt(1), fontSize: digitFont, totalNumberPages: pagesForDigit(hh.charAt(1)), transitionMs: 560, changeAnimationMode: "incoming" }), _jsx(Colon, {}), _jsx(SgDiscardDigit, { value: mm.charAt(0), fontSize: digitFont, totalNumberPages: pagesForDigit(mm.charAt(0)), transitionMs: 560, changeAnimationMode: "incoming" }), _jsx(SgDiscardDigit, { value: mm.charAt(1), fontSize: digitFont, totalNumberPages: pagesForDigit(mm.charAt(1)), transitionMs: 560, changeAnimationMode: "incoming" }), showSeconds ? (_jsxs(_Fragment, { children: [_jsx(Colon, {}), _jsx(SgDiscardDigit, { value: ss.charAt(0), fontSize: digitFont, totalNumberPages: pagesForDigit(ss.charAt(0)), transitionMs: 560, changeAnimationMode: "incoming" }), _jsx(SgDiscardDigit, { value: ss.charAt(1), fontSize: digitFont, totalNumberPages: pagesForDigit(ss.charAt(1)), transitionMs: 560, changeAnimationMode: "incoming" })] })) : null, format === "12h" && dayPeriod ? _jsx(PeriodCell, { value: dayPeriod.toUpperCase() }) : null] }));
|
|
217
219
|
}
|
|
218
220
|
if (digitalStyle === "matrix") {
|
|
219
221
|
const dotSize = Math.max(3, Math.round(sizePx * 0.32));
|
|
220
|
-
return (_jsx("div", { className: cn("flex items-center", className), style: style, "aria-label": "
|
|
222
|
+
return (_jsx("div", { className: cn("flex items-center", className), style: style, "aria-label": t(i18n, "components.gadgets.clock.digitalAria"), children: _jsx(SgMatrixDigit, { value: withPeriod, dotSize: dotSize, gap: Math.max(1, Math.round(dotSize * 0.35)), charGap: Math.max(3, Math.round(dotSize * 0.9)), padding: Math.max(6, Math.round(dotSize * 1.3)), rounded: Math.max(8, Math.round(dotSize * 1.1)) }) }));
|
|
221
223
|
}
|
|
222
224
|
if (digitalStyle === "neon") {
|
|
223
225
|
const neonFont = Math.max(18, Math.round(sizePx * 1.35));
|
|
224
|
-
return (_jsx("div", { className: cn("flex items-center", className), style: style, "aria-label": "
|
|
226
|
+
return (_jsx("div", { className: cn("flex items-center", className), style: style, "aria-label": t(i18n, "components.gadgets.clock.digitalAria"), children: _jsx(SgNeonDigit, { value: withPeriod, fontSize: neonFont, padding: Math.max(8, Math.round(sizePx * 0.6)), rounded: Math.max(10, Math.round(sizePx * 0.45)) }) }));
|
|
225
227
|
}
|
|
226
228
|
if (digitalStyle === "sevenSegment") {
|
|
227
229
|
const hNum = Number.parseInt(hour, 10) || 0;
|
|
@@ -249,7 +251,7 @@ function DigitalClock({ initialServerTime, timezone, locale = "pt-BR", format =
|
|
|
249
251
|
paddingLeft: separatorPadding,
|
|
250
252
|
paddingRight: separatorPadding
|
|
251
253
|
}, children: [_jsx("span", { className: "rounded-full bg-red-500/85", style: { width: dotSize, height: dotSize } }), _jsx("span", { className: "rounded-full bg-red-500/85", style: { width: dotSize, height: dotSize } })] }));
|
|
252
|
-
return (_jsxs("div", { className: cn("flex items-center", className), style: { gap: digitGap, ...style }, "aria-label": "
|
|
254
|
+
return (_jsxs("div", { className: cn("flex items-center", className), style: { gap: digitGap, ...style }, "aria-label": t(i18n, "components.gadgets.clock.digitalAria"), children: [_jsx(SgSevenSegmentDigit, { value: hh.charAt(0), size: digitSize, thickness: thickness }), _jsx(SgSevenSegmentDigit, { value: hh.charAt(1), size: digitSize, thickness: thickness }), _jsx(Colon, {}), _jsx(SgSevenSegmentDigit, { value: mm.charAt(0), size: digitSize, thickness: thickness }), _jsx(SgSevenSegmentDigit, { value: mm.charAt(1), size: digitSize, thickness: thickness }), showSeconds ? (_jsxs(_Fragment, { children: [_jsx(Colon, {}), _jsx(SgSevenSegmentDigit, { value: ss.charAt(0), size: digitSize, thickness: thickness }), _jsx(SgSevenSegmentDigit, { value: ss.charAt(1), size: digitSize, thickness: thickness })] })) : null, format === "12h" && dayPeriod ? (_jsx("span", { className: "text-xs font-semibold text-muted-foreground", children: dayPeriod.toUpperCase() })) : null] }));
|
|
253
255
|
}
|
|
254
256
|
if (digitalStyle === "segment") {
|
|
255
257
|
const hNum = Number.parseInt(hour, 10) || 0;
|
|
@@ -267,9 +269,9 @@ function DigitalClock({ initialServerTime, timezone, locale = "pt-BR", format =
|
|
|
267
269
|
? 42
|
|
268
270
|
: 26;
|
|
269
271
|
const gap = Math.max(2, Math.round(digitSize * 0.18));
|
|
270
|
-
return (_jsxs("div", { className: cn("flex items-end", className), style: { gap, ...style }, "aria-label": "
|
|
272
|
+
return (_jsxs("div", { className: cn("flex items-end", className), style: { gap, ...style }, "aria-label": t(i18n, "components.gadgets.clock.digitalAria"), children: [_jsx(SgSegmentDigit, { value: hh.charAt(0), size: digitSize }), _jsx(SgSegmentDigit, { value: hh.charAt(1), size: digitSize }), _jsx(SgSegmentDigit, { value: ":", size: digitSize }), _jsx(SgSegmentDigit, { value: mm.charAt(0), size: digitSize }), _jsx(SgSegmentDigit, { value: mm.charAt(1), size: digitSize }), showSeconds ? (_jsxs(_Fragment, { children: [_jsx(SgSegmentDigit, { value: ":", size: digitSize }), _jsx(SgSegmentDigit, { value: ss.charAt(0), size: digitSize }), _jsx(SgSegmentDigit, { value: ss.charAt(1), size: digitSize })] })) : null, format === "12h" && dayPeriod ? (_jsx("span", { className: "text-xs font-semibold text-muted-foreground", children: dayPeriod })) : null] }));
|
|
271
273
|
}
|
|
272
|
-
return (_jsxs("div", { className: cn("font-mono tabular-nums", classSize, className), style: { ...fontSize, ...style }, children: [text, format === "12h" && dayPeriod ? (_jsx("span", { className: "ml-2 align-top text-xs font-semibold text-muted-foreground", children: dayPeriod })) : null] }));
|
|
274
|
+
return (_jsxs("div", { className: cn("font-mono tabular-nums", classSize, className), style: { ...fontSize, ...style }, "aria-label": t(i18n, "components.gadgets.clock.digitalAria"), children: [text, format === "12h" && dayPeriod ? (_jsx("span", { className: "ml-2 align-top text-xs font-semibold text-muted-foreground", children: dayPeriod })) : null] }));
|
|
273
275
|
}
|
|
274
276
|
export function SgClock(props) {
|
|
275
277
|
const i18n = useComponentsI18n();
|
|
@@ -9,6 +9,7 @@ export type SgClockThemePickerProps = {
|
|
|
9
9
|
previewSize?: number;
|
|
10
10
|
searchable?: boolean;
|
|
11
11
|
fallbackThemeId?: string;
|
|
12
|
+
defaultOpen?: boolean;
|
|
12
13
|
};
|
|
13
|
-
export declare function SgClockThemePicker({ value, onChange, label, placeholder, className, filter, previewSize, searchable, fallbackThemeId }: SgClockThemePickerProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
export declare function SgClockThemePicker({ value, onChange, label: labelProp, placeholder: placeholderProp, className, filter, previewSize, searchable, fallbackThemeId, defaultOpen }: SgClockThemePickerProps): import("react/jsx-runtime").JSX.Element;
|
|
14
15
|
//# sourceMappingURL=SgClockThemePicker.d.ts.map
|
|
@@ -1 +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;
|
|
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;AAW5C,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;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,QAAQ,EACR,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,eAAe,EAC5B,SAAS,EACT,MAAM,EACN,WAAgB,EAChB,UAAiB,EACjB,eAA2B,EAC3B,WAAmB,EACpB,EAAE,uBAAuB,2CA6JzB"}
|
|
@@ -3,33 +3,31 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { useSgClockThemeResolver } from "./provider";
|
|
5
5
|
import { SgClockThemePreview } from "./SgClockThemePreview";
|
|
6
|
+
import { filterClockThemes, resolveClockThemeSelection } from "./search";
|
|
6
7
|
import { SgAutocomplete } from "../../../inputs/SgAutocomplete";
|
|
8
|
+
import { t, useComponentsI18n } from "../../../i18n";
|
|
7
9
|
function cn(...parts) {
|
|
8
10
|
return parts.filter(Boolean).join(" ");
|
|
9
11
|
}
|
|
10
|
-
export function SgClockThemePicker({ value, onChange, label
|
|
12
|
+
export function SgClockThemePicker({ value, onChange, label: labelProp, placeholder: placeholderProp, className, filter, previewSize = 56, searchable = true, fallbackThemeId = "classic", defaultOpen = false }) {
|
|
13
|
+
const i18n = useComponentsI18n();
|
|
14
|
+
const label = labelProp ?? t(i18n, "components.gadgets.clock.theme");
|
|
15
|
+
const placeholder = placeholderProp ?? t(i18n, "components.gadgets.clock.selectTheme");
|
|
11
16
|
const resolver = useSgClockThemeResolver();
|
|
12
17
|
const all = React.useMemo(() => {
|
|
13
18
|
const list = resolver?.list() ?? [];
|
|
14
19
|
return filter ? list.filter(filter) : list;
|
|
15
20
|
}, [resolver, filter]);
|
|
16
|
-
const
|
|
21
|
+
const popupId = React.useId();
|
|
22
|
+
const [open, setOpen] = React.useState(defaultOpen);
|
|
17
23
|
const [q, setQ] = React.useState("");
|
|
18
|
-
const currentTheme = React.useMemo(() => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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]);
|
|
24
|
+
const currentTheme = React.useMemo(() => resolveClockThemeSelection({
|
|
25
|
+
resolver,
|
|
26
|
+
allThemes: all,
|
|
27
|
+
value,
|
|
28
|
+
fallbackThemeId
|
|
29
|
+
}), [resolver, value, all, fallbackThemeId]);
|
|
30
|
+
const filtered = React.useMemo(() => filterClockThemes(all, q), [all, q]);
|
|
33
31
|
const rootRef = React.useRef(null);
|
|
34
32
|
React.useEffect(() => {
|
|
35
33
|
if (!open)
|
|
@@ -44,28 +42,25 @@ export function SgClockThemePicker({ value, onChange, label = "Theme", placehold
|
|
|
44
42
|
document.addEventListener("mousedown", onDoc);
|
|
45
43
|
return () => document.removeEventListener("mousedown", onDoc);
|
|
46
44
|
}, [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-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface,var(--sg-bg)))] px-3 py-2 text-left text-[rgb(var(--sg-text,var(--sg-fg)))] shadow-sm", "hover:bg-[rgb(var(--sg-surface-2,var(--sg-surface,var(--sg-bg))))]"), children: _jsxs("div", { className: "flex items-center gap-3", children: [currentTheme ? (_jsx("div", { className: "text-[rgb(var(--sg-text,var(--sg-fg)))]", children: _jsx(SgClockThemePreview, { theme: currentTheme, size: previewSize }) })) : (_jsx("div", { className: "h-[56px] w-[56px] rounded-md border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface-2,var(--sg-surface,var(--sg-bg))))]" })), _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-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface,var(--sg-bg)))] text-[rgb(var(--sg-text,var(--sg-fg)))] shadow-lg"), children: [searchable && (_jsx("div", { className: "p-2", children: _jsx(SgAutocomplete, { id: "sg-clock-theme-search", label:
|
|
48
|
-
const
|
|
49
|
-
const items = all.map((t) => ({
|
|
45
|
+
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), "aria-haspopup": "listbox", "aria-expanded": open, "aria-controls": popupId, className: cn("w-full rounded-lg border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface,var(--sg-bg)))] px-3 py-2 text-left text-[rgb(var(--sg-text,var(--sg-fg)))] shadow-sm", "hover:bg-[rgb(var(--sg-surface-2,var(--sg-surface,var(--sg-bg))))]"), children: _jsxs("div", { className: "flex items-center gap-3", children: [currentTheme ? (_jsx("div", { className: "text-[rgb(var(--sg-text,var(--sg-fg)))]", children: _jsx(SgClockThemePreview, { theme: currentTheme, size: previewSize }) })) : (_jsx("div", { className: "h-[56px] w-[56px] rounded-md border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface-2,var(--sg-surface,var(--sg-bg))))]" })), _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", { id: popupId, role: "listbox", className: cn("absolute z-50 mt-2 w-full overflow-hidden rounded-xl border border-[rgb(var(--sg-border))] bg-[rgb(var(--sg-surface,var(--sg-bg)))] text-[rgb(var(--sg-text,var(--sg-fg)))] shadow-lg"), children: [searchable && (_jsx("div", { className: "p-2", children: _jsx(SgAutocomplete, { value: q, onChange: setQ, id: "sg-clock-theme-search", label: t(i18n, "components.gadgets.clock.searchTheme"), placeholder: t(i18n, "components.gadgets.clock.searchThemePlaceholder"), openOnFocus: true, showDropDownButton: true, clearOnSelect: true, minLengthForSearch: 0, source: (query) => {
|
|
46
|
+
const items = filterClockThemes(all, query ?? "").map((t) => ({
|
|
50
47
|
id: t.id,
|
|
51
48
|
label: t.label ?? t.id,
|
|
52
49
|
value: t.id,
|
|
53
50
|
data: t
|
|
54
51
|
}));
|
|
55
|
-
|
|
56
|
-
return items;
|
|
57
|
-
return items.filter((item) => item.label?.toLowerCase().includes(s));
|
|
52
|
+
return items;
|
|
58
53
|
}, onSelect: (item) => {
|
|
59
54
|
const id = item.value ?? item.id;
|
|
60
55
|
onChange(String(id));
|
|
61
56
|
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: "
|
|
63
|
-
const active =
|
|
64
|
-
return (_jsx("button", { type: "button", onClick: () => {
|
|
65
|
-
onChange(
|
|
57
|
+
} }) })), _jsx("div", { className: "max-h-80 overflow-auto p-2", children: filtered.length === 0 ? (_jsx("div", { className: "p-3 text-sm opacity-60", children: t(i18n, "components.gadgets.clock.noThemesFound") })) : (_jsx("div", { className: "space-y-1", children: filtered.map((themeOption) => {
|
|
58
|
+
const active = themeOption.id === value;
|
|
59
|
+
return (_jsx("button", { type: "button", role: "option", "aria-selected": active, onClick: () => {
|
|
60
|
+
onChange(themeOption.id);
|
|
66
61
|
setOpen(false);
|
|
67
62
|
}, className: cn("w-full rounded-lg p-2 text-left transition", active
|
|
68
63
|
? "bg-[rgb(var(--sg-primary))] text-[rgb(var(--sg-primary-contrast,var(--sg-bg)))]"
|
|
69
|
-
: "hover:bg-[rgb(var(--sg-surface-2,var(--sg-surface,var(--sg-bg))))]"), children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: cn(active ? "text-[rgb(var(--sg-primary-contrast,var(--sg-bg)))]" : "text-[rgb(var(--sg-text,var(--sg-fg)))]"), children: _jsx(SgClockThemePreview, { theme:
|
|
64
|
+
: "hover:bg-[rgb(var(--sg-surface-2,var(--sg-surface,var(--sg-bg))))]"), children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: cn(active ? "text-[rgb(var(--sg-primary-contrast,var(--sg-bg)))]" : "text-[rgb(var(--sg-text,var(--sg-fg)))]"), children: _jsx(SgClockThemePreview, { theme: themeOption, size: 44 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "truncate text-sm font-medium", children: themeOption.label ?? themeOption.id }), _jsx("div", { className: cn("truncate text-xs", active ? "opacity-80" : "opacity-60"), children: themeOption.id })] }), active ? _jsx("div", { className: "text-xs opacity-80", children: t(i18n, "components.gadgets.clock.activeTheme") }) : null] }) }, themeOption.id));
|
|
70
65
|
}) })) })] }))] }));
|
|
71
66
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SgClockTheme, SgClockThemeResolver } from "./types";
|
|
2
|
+
export declare function filterClockThemes(themes: SgClockTheme[], query: string): SgClockTheme[];
|
|
3
|
+
export declare function resolveClockThemeSelection(params: {
|
|
4
|
+
resolver?: SgClockThemeResolver | null;
|
|
5
|
+
allThemes: SgClockTheme[];
|
|
6
|
+
value: string;
|
|
7
|
+
fallbackThemeId: string;
|
|
8
|
+
}): SgClockTheme | null;
|
|
9
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../../src/gadgets/clock/themes/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAElE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,MAAM,kBAOtE;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IACjD,QAAQ,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACvC,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;CACzB,uBAIA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function filterClockThemes(themes, query) {
|
|
2
|
+
const s = query.trim().toLowerCase();
|
|
3
|
+
if (!s)
|
|
4
|
+
return themes;
|
|
5
|
+
return themes.filter((theme) => {
|
|
6
|
+
const hay = `${theme.id} ${theme.label ?? ""} ${(theme.tags ?? []).join(" ")}`.toLowerCase();
|
|
7
|
+
return hay.includes(s);
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
export function resolveClockThemeSelection(params) {
|
|
11
|
+
const found = params.resolver?.resolve(params.value) ?? params.allThemes.find((t) => t.id === params.value) ?? null;
|
|
12
|
+
if (found)
|
|
13
|
+
return found;
|
|
14
|
+
return params.resolver?.resolve(params.fallbackThemeId) ?? params.allThemes.find((t) => t.id === params.fallbackThemeId) ?? null;
|
|
15
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SgLinearGauge.d.ts","sourceRoot":"","sources":["../../../src/gadgets/gauge/SgLinearGauge.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"SgLinearGauge.d.ts","sourceRoot":"","sources":["../../../src/gadgets/gauge/SgLinearGauge.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GACjC,UAAU,GACV,mBAAmB,GACnB,QAAQ,GACR,SAAS,GACT,MAAM,CAAC;AAEX,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,yBAAyB,CAAC;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAExC,QAAQ,CAAC,EAAE,oBAAoB,EAAE,CAAC;IAClC,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAEjG,MAAM,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAE9B,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,mBAAmB,CAAC,EAAE,yBAAyB,CAAC;IAChD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAEpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAWF,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,kBAAkB,CAAC,2CAkhBhE;yBAlhBe,aAAa"}
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
+
import { t, useComponentsI18n } from "../../i18n";
|
|
5
|
+
import { clampGaugeValue, clientPointToLinearGaugeValue, pointToLinearGaugeValue, ratioToGaugeValue, valueToGaugeRatio } from "./math";
|
|
4
6
|
function cn(...parts) {
|
|
5
7
|
return parts.filter(Boolean).join(" ");
|
|
6
8
|
}
|
|
7
|
-
function clamp(value, min, max) {
|
|
8
|
-
return Math.max(min, Math.min(max, value));
|
|
9
|
-
}
|
|
10
9
|
function toNumber(value, fallback) {
|
|
11
10
|
return Number.isFinite(value) ? value : fallback;
|
|
12
11
|
}
|
|
13
12
|
const MAIN_POINTER_ID = "__sg-linear-main-pointer__";
|
|
14
13
|
export function SgLinearGauge(props) {
|
|
15
|
-
const
|
|
14
|
+
const i18n = useComponentsI18n();
|
|
15
|
+
const { min = 0, max = 100, value, defaultValue = min, onValueChange, pointers = [], onPointerValueChange, ranges = [], orientation = "horizontal", isAxisInversed = false, showPrimaryPointer = true, primaryPointerShape = "triangle", primaryPointerColor = "hsl(var(--primary))", primaryPointerSize = 11, primaryPointerDraggable = false, barPointer = true, barColor = "hsl(var(--primary))", barThickness = 8, showTicks = true, showLabels = true, majorTickCount = 5, minorTicksPerInterval = 1, labelFormatter, axisColor = "hsl(var(--border))", axisThickness = 10, width = orientation === "horizontal" ? 360 : 140, height = orientation === "horizontal" ? 120 : 360, animate = true, animationDuration = 350, className, style, ariaLabel } = props;
|
|
16
|
+
const resolvedAriaLabel = ariaLabel ?? t(i18n, "components.gadgets.gauge.linearAria");
|
|
16
17
|
const safeMin = toNumber(min, 0);
|
|
17
18
|
const safeMax = toNumber(max, 100);
|
|
18
19
|
const hasRange = safeMax > safeMin;
|
|
@@ -20,9 +21,9 @@ export function SgLinearGauge(props) {
|
|
|
20
21
|
const [innerValue, setInnerValue] = React.useState(defaultValue);
|
|
21
22
|
const isControlled = value !== undefined;
|
|
22
23
|
const currentValueRaw = isControlled ? value : innerValue;
|
|
23
|
-
const currentValue =
|
|
24
|
+
const currentValue = clampGaugeValue(currentValueRaw, safeMin, safeMax);
|
|
24
25
|
const setMainValue = React.useCallback((next) => {
|
|
25
|
-
const clamped =
|
|
26
|
+
const clamped = clampGaugeValue(next, safeMin, safeMax);
|
|
26
27
|
if (!isControlled)
|
|
27
28
|
setInnerValue(clamped);
|
|
28
29
|
onValueChange?.(clamped);
|
|
@@ -30,7 +31,7 @@ export function SgLinearGauge(props) {
|
|
|
30
31
|
React.useEffect(() => {
|
|
31
32
|
if (isControlled)
|
|
32
33
|
return;
|
|
33
|
-
setInnerValue((prev) =>
|
|
34
|
+
setInnerValue((prev) => clampGaugeValue(prev, safeMin, safeMax));
|
|
34
35
|
}, [isControlled, safeMin, safeMax]);
|
|
35
36
|
const pointerIds = React.useMemo(() => pointers.map((pointer, index) => pointer.id ?? `sg-linear-pointer-${index}`), [pointers]);
|
|
36
37
|
const [dragPointerValues, setDragPointerValues] = React.useState({});
|
|
@@ -43,7 +44,7 @@ export function SgLinearGauge(props) {
|
|
|
43
44
|
if (!pointer)
|
|
44
45
|
continue;
|
|
45
46
|
const pointerId = pointerIds[i] ?? `sg-linear-pointer-${i}`;
|
|
46
|
-
const clamped =
|
|
47
|
+
const clamped = clampGaugeValue(pointer.value, safeMin, safeMax);
|
|
47
48
|
if (next[pointerId] !== clamped) {
|
|
48
49
|
next[pointerId] = clamped;
|
|
49
50
|
changed = true;
|
|
@@ -71,13 +72,10 @@ export function SgLinearGauge(props) {
|
|
|
71
72
|
? { x: totalWidth - 16, y: totalHeight - labelSpace - tickSpace - 4 }
|
|
72
73
|
: { x: totalWidth - labelSpace - tickSpace - 4, y: 16 };
|
|
73
74
|
const valueToRatio = React.useCallback((raw) => {
|
|
74
|
-
|
|
75
|
-
return isAxisInversed ? 1 - normalized : normalized;
|
|
75
|
+
return valueToGaugeRatio(raw, safeMin, safeMax, isAxisInversed);
|
|
76
76
|
}, [isAxisInversed, safeMin, span]);
|
|
77
77
|
const ratioToValue = React.useCallback((ratioRaw) => {
|
|
78
|
-
|
|
79
|
-
const normalized = isAxisInversed ? 1 - ratio : ratio;
|
|
80
|
-
return safeMin + normalized * span;
|
|
78
|
+
return ratioToGaugeValue(ratioRaw, safeMin, safeMax, isAxisInversed);
|
|
81
79
|
}, [isAxisInversed, safeMin, span]);
|
|
82
80
|
const valueToPoint = React.useCallback((raw) => {
|
|
83
81
|
const ratio = valueToRatio(raw);
|
|
@@ -86,12 +84,16 @@ export function SgLinearGauge(props) {
|
|
|
86
84
|
return { x, y };
|
|
87
85
|
}, [axisEnd.x, axisEnd.y, axisStart.x, axisStart.y, valueToRatio]);
|
|
88
86
|
const pointToValue = React.useCallback((x, y) => {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
87
|
+
return pointToLinearGaugeValue({
|
|
88
|
+
x,
|
|
89
|
+
y,
|
|
90
|
+
axisStart,
|
|
91
|
+
axisEnd,
|
|
92
|
+
orientation,
|
|
93
|
+
min: safeMin,
|
|
94
|
+
max: safeMax,
|
|
95
|
+
isAxisInversed
|
|
96
|
+
});
|
|
95
97
|
}, [axisEnd.x, axisEnd.y, axisStart.x, axisStart.y, orientation, ratioToValue]);
|
|
96
98
|
const pointerList = React.useMemo(() => {
|
|
97
99
|
const list = [];
|
|
@@ -120,7 +122,7 @@ export function SgLinearGauge(props) {
|
|
|
120
122
|
id: pointerId,
|
|
121
123
|
isPrimary: false,
|
|
122
124
|
pointer,
|
|
123
|
-
value:
|
|
125
|
+
value: clampGaugeValue(dragValue ?? pointer.value, safeMin, safeMax)
|
|
124
126
|
});
|
|
125
127
|
}
|
|
126
128
|
return list;
|
|
@@ -154,11 +156,21 @@ export function SgLinearGauge(props) {
|
|
|
154
156
|
if (!svg || !pointerMeta)
|
|
155
157
|
return;
|
|
156
158
|
const rect = svg.getBoundingClientRect();
|
|
157
|
-
|
|
159
|
+
const next = clientPointToLinearGaugeValue({
|
|
160
|
+
clientX: event.clientX,
|
|
161
|
+
clientY: event.clientY,
|
|
162
|
+
rect,
|
|
163
|
+
totalWidth,
|
|
164
|
+
totalHeight,
|
|
165
|
+
axisStart,
|
|
166
|
+
axisEnd,
|
|
167
|
+
orientation,
|
|
168
|
+
min: safeMin,
|
|
169
|
+
max: safeMax,
|
|
170
|
+
isAxisInversed
|
|
171
|
+
});
|
|
172
|
+
if (next === null)
|
|
158
173
|
return;
|
|
159
|
-
const localX = ((event.clientX - rect.left) / rect.width) * totalWidth;
|
|
160
|
-
const localY = ((event.clientY - rect.top) / rect.height) * totalHeight;
|
|
161
|
-
const next = clamp(pointToValue(localX, localY), safeMin, safeMax);
|
|
162
174
|
if (pointerMeta.isPrimary) {
|
|
163
175
|
setMainValue(next);
|
|
164
176
|
}
|
|
@@ -185,7 +197,6 @@ export function SgLinearGauge(props) {
|
|
|
185
197
|
}, [
|
|
186
198
|
draggingPointerId,
|
|
187
199
|
onPointerValueChange,
|
|
188
|
-
pointToValue,
|
|
189
200
|
pointerMap,
|
|
190
201
|
safeMax,
|
|
191
202
|
safeMin,
|
|
@@ -205,9 +216,9 @@ export function SgLinearGauge(props) {
|
|
|
205
216
|
: {};
|
|
206
217
|
const primaryBarEnd = valueToPoint(currentValue);
|
|
207
218
|
const primaryBarStart = valueToPoint(safeMin);
|
|
208
|
-
return (_jsx("div", { className: cn("inline-flex select-none", className), role: "meter", "aria-label":
|
|
209
|
-
const start =
|
|
210
|
-
const end =
|
|
219
|
+
return (_jsx("div", { className: cn("inline-flex select-none", className), role: "meter", "aria-label": resolvedAriaLabel, "aria-valuemin": safeMin, "aria-valuemax": safeMax, "aria-valuenow": currentValue, style: style, children: _jsxs("svg", { ref: svgRef, width: totalWidth, height: totalHeight, viewBox: `0 0 ${totalWidth} ${totalHeight}`, className: "overflow-visible", children: [_jsx("line", { x1: axisStart.x, y1: axisStart.y, x2: axisEnd.x, y2: axisEnd.y, stroke: axisColor, strokeLinecap: "round", strokeWidth: axisThickness }), ranges.map((range, index) => {
|
|
220
|
+
const start = clampGaugeValue(Math.min(range.start, range.end), safeMin, safeMax);
|
|
221
|
+
const end = clampGaugeValue(Math.max(range.start, range.end), safeMin, safeMax);
|
|
211
222
|
const p1 = valueToPoint(start);
|
|
212
223
|
const p2 = valueToPoint(end);
|
|
213
224
|
return (_jsx("line", { x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y, stroke: range.color ?? "hsl(var(--primary))", strokeLinecap: "round", strokeWidth: range.thickness ?? axisThickness + 2, strokeOpacity: range.opacity ?? 0.55 }, `range-${index}`));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SgRadialGauge.d.ts","sourceRoot":"","sources":["../../../src/gadgets/gauge/SgRadialGauge.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"SgRadialGauge.d.ts","sourceRoot":"","sources":["../../../src/gadgets/gauge/SgRadialGauge.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
+
import { t, useComponentsI18n } from "../../i18n";
|
|
5
|
+
import { angleToRadialGaugeValue, clampGaugeValue, clientPointToRadialGaugeValue, normalizeAngle, normalizeGaugeRange, ratioToGaugeValue, valueToGaugeRatio } from "./math";
|
|
4
6
|
function cn(...parts) {
|
|
5
7
|
return parts.filter(Boolean).join(" ");
|
|
6
8
|
}
|
|
7
|
-
function clamp(value, min, max) {
|
|
8
|
-
return Math.max(min, Math.min(max, value));
|
|
9
|
-
}
|
|
10
|
-
function normalizeAngle(angle) {
|
|
11
|
-
const normalized = angle % 360;
|
|
12
|
-
return normalized < 0 ? normalized + 360 : normalized;
|
|
13
|
-
}
|
|
14
9
|
function toSweep(startAngle, endAngle) {
|
|
15
10
|
const start = normalizeAngle(startAngle);
|
|
16
11
|
const end = normalizeAngle(endAngle);
|
|
@@ -35,16 +30,19 @@ function arcPath(cx, cy, radius, startAngle, endAngle) {
|
|
|
35
30
|
}
|
|
36
31
|
const MAIN_POINTER_ID = "__sg-radial-main-pointer__";
|
|
37
32
|
export function SgRadialGauge(props) {
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const
|
|
33
|
+
const i18n = useComponentsI18n();
|
|
34
|
+
const { min = 0, max = 100, value, defaultValue = min, onValueChange, pointers = [], onPointerValueChange, ranges = [], annotations = [], startAngle = 135, endAngle = 45, isAxisInversed = false, showPrimaryPointer = true, primaryPointerType = "needle", primaryPointerColor = "hsl(var(--primary))", primaryPointerWidth = 3, primaryPointerSize = 12, primaryPointerShape = "circle", primaryPointerDraggable = false, primaryPointerLabel, showTicks = true, showLabels = true, majorTickCount = 5, minorTicksPerInterval = 1, labelFormatter, axisColor = "hsl(var(--border))", ringThickness, axisWidth = 14, radiusFactor = 0.9, centerContent, width = 300, height = 300, animate = true, animationDuration = 350, className, style, ariaLabel } = props;
|
|
35
|
+
const resolvedAriaLabel = ariaLabel ?? t(i18n, "components.gadgets.gauge.radialAria");
|
|
36
|
+
const range = React.useMemo(() => normalizeGaugeRange(min, max), [min, max]);
|
|
37
|
+
const safeMin = range.min;
|
|
38
|
+
const safeMax = range.max;
|
|
39
|
+
const span = range.span;
|
|
42
40
|
const [innerValue, setInnerValue] = React.useState(defaultValue);
|
|
43
41
|
const isControlled = value !== undefined;
|
|
44
42
|
const currentValueRaw = isControlled ? value : innerValue;
|
|
45
|
-
const currentValue =
|
|
43
|
+
const currentValue = clampGaugeValue(currentValueRaw, safeMin, safeMax);
|
|
46
44
|
const setMainValue = React.useCallback((next) => {
|
|
47
|
-
const clamped =
|
|
45
|
+
const clamped = clampGaugeValue(next, safeMin, safeMax);
|
|
48
46
|
if (!isControlled)
|
|
49
47
|
setInnerValue(clamped);
|
|
50
48
|
onValueChange?.(clamped);
|
|
@@ -52,7 +50,7 @@ export function SgRadialGauge(props) {
|
|
|
52
50
|
React.useEffect(() => {
|
|
53
51
|
if (isControlled)
|
|
54
52
|
return;
|
|
55
|
-
setInnerValue((prev) =>
|
|
53
|
+
setInnerValue((prev) => clampGaugeValue(prev, safeMin, safeMax));
|
|
56
54
|
}, [isControlled, safeMin, safeMax]);
|
|
57
55
|
const pointerIds = React.useMemo(() => pointers.map((pointer, index) => pointer.id ?? `sg-radial-pointer-${index}`), [pointers]);
|
|
58
56
|
const [dragPointerValues, setDragPointerValues] = React.useState({});
|
|
@@ -65,7 +63,7 @@ export function SgRadialGauge(props) {
|
|
|
65
63
|
if (!pointer)
|
|
66
64
|
continue;
|
|
67
65
|
const pointerId = pointerIds[i] ?? `sg-radial-pointer-${i}`;
|
|
68
|
-
const clamped =
|
|
66
|
+
const clamped = clampGaugeValue(pointer.value, safeMin, safeMax);
|
|
69
67
|
if (next[pointerId] !== clamped) {
|
|
70
68
|
next[pointerId] = clamped;
|
|
71
69
|
changed = true;
|
|
@@ -89,27 +87,27 @@ export function SgRadialGauge(props) {
|
|
|
89
87
|
const safeRadiusFactorRaw = Number.isFinite(radiusFactor) ? radiusFactor : 0.9;
|
|
90
88
|
const safeRadiusFactor = Math.max(0.1, safeRadiusFactorRaw);
|
|
91
89
|
const availableRadius = Math.max(8, Math.min(totalWidth, totalHeight) / 2 - safeAxisWidth / 2 - 6);
|
|
92
|
-
const baseRadius =
|
|
90
|
+
const baseRadius = clampGaugeValue(availableRadius * safeRadiusFactor, 8, availableRadius);
|
|
93
91
|
const sweep = React.useMemo(() => toSweep(startAngle, endAngle), [endAngle, startAngle]);
|
|
94
92
|
const valueToRatio = React.useCallback((raw) => {
|
|
95
|
-
|
|
96
|
-
return isAxisInversed ? 1 - normalized : normalized;
|
|
93
|
+
return valueToGaugeRatio(raw, safeMin, safeMax, isAxisInversed);
|
|
97
94
|
}, [isAxisInversed, safeMin, span]);
|
|
98
95
|
const ratioToValue = React.useCallback((ratioRaw) => {
|
|
99
|
-
|
|
100
|
-
const normalized = isAxisInversed ? 1 - ratio : ratio;
|
|
101
|
-
return safeMin + normalized * span;
|
|
96
|
+
return ratioToGaugeValue(ratioRaw, safeMin, safeMax, isAxisInversed);
|
|
102
97
|
}, [isAxisInversed, safeMin, span]);
|
|
103
98
|
const valueToAngle = React.useCallback((raw) => {
|
|
104
99
|
const ratio = valueToRatio(raw);
|
|
105
100
|
return startAngle + sweep * ratio;
|
|
106
101
|
}, [startAngle, sweep, valueToRatio]);
|
|
107
102
|
const angleToValue = React.useCallback((rawAngle) => {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
103
|
+
return angleToRadialGaugeValue({
|
|
104
|
+
rawAngle,
|
|
105
|
+
startAngle,
|
|
106
|
+
sweep,
|
|
107
|
+
min: safeMin,
|
|
108
|
+
max: safeMax,
|
|
109
|
+
isAxisInversed
|
|
110
|
+
});
|
|
113
111
|
}, [ratioToValue, startAngle, sweep]);
|
|
114
112
|
const majorCount = Math.max(1, Math.floor(majorTickCount));
|
|
115
113
|
const minorCount = Math.max(0, Math.floor(minorTicksPerInterval));
|
|
@@ -143,7 +141,7 @@ export function SgRadialGauge(props) {
|
|
|
143
141
|
id,
|
|
144
142
|
isPrimary: false,
|
|
145
143
|
pointer,
|
|
146
|
-
value:
|
|
144
|
+
value: clampGaugeValue(dragValue ?? pointer.value, safeMin, safeMax)
|
|
147
145
|
});
|
|
148
146
|
}
|
|
149
147
|
return list;
|
|
@@ -180,12 +178,22 @@ export function SgRadialGauge(props) {
|
|
|
180
178
|
if (!svg || !pointerMeta)
|
|
181
179
|
return;
|
|
182
180
|
const rect = svg.getBoundingClientRect();
|
|
183
|
-
|
|
181
|
+
const next = clientPointToRadialGaugeValue({
|
|
182
|
+
clientX: event.clientX,
|
|
183
|
+
clientY: event.clientY,
|
|
184
|
+
rect,
|
|
185
|
+
totalWidth,
|
|
186
|
+
totalHeight,
|
|
187
|
+
cx,
|
|
188
|
+
cy,
|
|
189
|
+
startAngle,
|
|
190
|
+
sweep,
|
|
191
|
+
min: safeMin,
|
|
192
|
+
max: safeMax,
|
|
193
|
+
isAxisInversed
|
|
194
|
+
});
|
|
195
|
+
if (next === null)
|
|
184
196
|
return;
|
|
185
|
-
const localX = ((event.clientX - rect.left) / rect.width) * totalWidth;
|
|
186
|
-
const localY = ((event.clientY - rect.top) / rect.height) * totalHeight;
|
|
187
|
-
const angle = normalizeAngle((Math.atan2(localY - cy, localX - cx) * 180) / Math.PI);
|
|
188
|
-
const next = clamp(angleToValue(angle), safeMin, safeMax);
|
|
189
197
|
if (pointerMeta.isPrimary) {
|
|
190
198
|
setMainValue(next);
|
|
191
199
|
}
|
|
@@ -210,7 +218,6 @@ export function SgRadialGauge(props) {
|
|
|
210
218
|
window.removeEventListener("pointercancel", onEnd);
|
|
211
219
|
};
|
|
212
220
|
}, [
|
|
213
|
-
angleToValue,
|
|
214
221
|
cx,
|
|
215
222
|
cy,
|
|
216
223
|
draggingPointerId,
|
|
@@ -232,10 +239,10 @@ export function SgRadialGauge(props) {
|
|
|
232
239
|
const animatedStyle = animate
|
|
233
240
|
? { transition: `all ${animationDuration}ms ease-out` }
|
|
234
241
|
: {};
|
|
235
|
-
const centerNode = centerContent ?? (_jsxs("div", { className: "pointer-events-none select-none text-center", children: [_jsx("div", { className: "text-xs uppercase text-muted-foreground", children: "
|
|
236
|
-
return (_jsxs("div", { className: cn("relative inline-flex select-none", className), role: "meter", "aria-label":
|
|
237
|
-
const start =
|
|
238
|
-
const end =
|
|
242
|
+
const centerNode = centerContent ?? (_jsxs("div", { className: "pointer-events-none select-none text-center", children: [_jsx("div", { className: "text-xs uppercase text-muted-foreground", children: t(i18n, "components.gadgets.gauge.value") }), _jsx("div", { className: "text-xl font-semibold text-foreground", children: Math.round(currentValue) })] }));
|
|
243
|
+
return (_jsxs("div", { className: cn("relative inline-flex select-none", className), role: "meter", "aria-label": resolvedAriaLabel, "aria-valuemin": safeMin, "aria-valuemax": safeMax, "aria-valuenow": currentValue, style: style, children: [_jsxs("svg", { ref: svgRef, width: totalWidth, height: totalHeight, viewBox: `0 0 ${totalWidth} ${totalHeight}`, children: [_jsx("path", { d: arcPath(cx, cy, baseRadius, startAngle, endAngle), fill: "none", stroke: axisColor, strokeWidth: safeAxisWidth, strokeLinecap: "round" }), ranges.map((range, index) => {
|
|
244
|
+
const start = clampGaugeValue(Math.min(range.start, range.end), safeMin, safeMax);
|
|
245
|
+
const end = clampGaugeValue(Math.max(range.start, range.end), safeMin, safeMax);
|
|
239
246
|
const startA = valueToAngle(start);
|
|
240
247
|
const endA = valueToAngle(end);
|
|
241
248
|
return (_jsx("path", { d: arcPath(cx, cy, baseRadius, startA, endA), fill: "none", stroke: range.color ?? "hsl(var(--primary))", strokeWidth: range.width ?? safeAxisWidth + 2, strokeOpacity: range.opacity ?? 0.55, strokeLinecap: "round" }, `range-${index}`));
|