@seedgrid/fe-components 2026.3.9 → 2026.3.11-1
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/SgButton.d.ts +2 -0
- package/dist/buttons/SgButton.d.ts.map +1 -1
- package/dist/buttons/SgButton.js +4 -3
- package/dist/digits/segment-digit/SgSegmentDigit.d.ts +15 -0
- package/dist/digits/segment-digit/SgSegmentDigit.d.ts.map +1 -0
- package/dist/digits/segment-digit/SgSegmentDigit.js +96 -0
- package/dist/digits/segment-digit/index.d.ts +3 -0
- package/dist/digits/segment-digit/index.d.ts.map +1 -0
- package/dist/digits/segment-digit/index.js +1 -0
- package/dist/digits/seven-segment-digit/SgSevenSegmentDigit.d.ts +36 -0
- package/dist/digits/seven-segment-digit/SgSevenSegmentDigit.d.ts.map +1 -0
- package/dist/digits/seven-segment-digit/SgSevenSegmentDigit.js +123 -0
- package/dist/digits/seven-segment-digit/index.d.ts +3 -0
- package/dist/digits/seven-segment-digit/index.d.ts.map +1 -0
- package/dist/digits/seven-segment-digit/index.js +1 -0
- package/dist/gadgets/calendar/SgCalendar.d.ts +29 -0
- package/dist/gadgets/calendar/SgCalendar.d.ts.map +1 -0
- package/dist/gadgets/calendar/SgCalendar.js +248 -0
- package/dist/gadgets/calendar/index.d.ts +3 -0
- package/dist/gadgets/calendar/index.d.ts.map +1 -0
- package/dist/gadgets/calendar/index.js +1 -0
- package/dist/gadgets/clock/SgClock.d.ts +4 -1
- package/dist/gadgets/clock/SgClock.d.ts.map +1 -1
- package/dist/gadgets/clock/SgClock.js +74 -115
- package/dist/i18n/en-US.d.ts.map +1 -1
- package/dist/i18n/en-US.js +11 -1
- package/dist/i18n/es.d.ts.map +1 -1
- package/dist/i18n/es.js +11 -1
- package/dist/i18n/pt-BR.d.ts.map +1 -1
- package/dist/i18n/pt-BR.js +11 -1
- package/dist/i18n/pt-PT.d.ts.map +1 -1
- package/dist/i18n/pt-PT.js +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/inputs/SgDatatable.d.ts +104 -0
- package/dist/inputs/SgDatatable.d.ts.map +1 -0
- package/dist/inputs/SgDatatable.js +441 -0
- package/dist/layout/SgCard.d.ts +12 -0
- package/dist/layout/SgCard.d.ts.map +1 -1
- package/dist/layout/SgCard.js +228 -12
- package/dist/overlay/SgConfirmationDialog.d.ts +34 -0
- package/dist/overlay/SgConfirmationDialog.d.ts.map +1 -0
- package/dist/overlay/SgConfirmationDialog.js +81 -0
- package/dist/overlay/SgDialog.d.ts +5 -0
- package/dist/overlay/SgDialog.d.ts.map +1 -1
- package/dist/overlay/SgDialog.js +28 -3
- package/dist/sandbox.cjs +83 -83
- package/package.json +1 -1
|
@@ -20,6 +20,7 @@ export type SgButtonProps = Omit<React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
|
20
20
|
size?: Size;
|
|
21
21
|
shape?: Shape;
|
|
22
22
|
elevation?: Elevation;
|
|
23
|
+
label?: React.ReactNode;
|
|
23
24
|
iconOnly?: boolean;
|
|
24
25
|
leftIcon?: React.ReactNode;
|
|
25
26
|
rightIcon?: React.ReactNode;
|
|
@@ -33,6 +34,7 @@ export declare const SgButton: React.ForwardRefExoticComponent<Omit<React.Button
|
|
|
33
34
|
size?: Size;
|
|
34
35
|
shape?: Shape;
|
|
35
36
|
elevation?: Elevation;
|
|
37
|
+
label?: React.ReactNode;
|
|
36
38
|
iconOnly?: boolean;
|
|
37
39
|
leftIcon?: React.ReactNode;
|
|
38
40
|
rightIcon?: React.ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SgButton.d.ts","sourceRoot":"","sources":["../../src/buttons/SgButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,KAAK,QAAQ,GACT,SAAS,GACT,WAAW,GACX,SAAS,GACT,MAAM,GACN,SAAS,GACT,MAAM,GACN,QAAQ,CAAC;AAEb,KAAK,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AAEhD,KAAK,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE/B,KAAK,KAAK,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEzD,KAAK,SAAS,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;AAEtC,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC,GAAG;IACzF,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,oBAAoB,CAAC;CACrC,CAAC;AAsEF,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,QAAQ,EAClB,MAAM,CAAC,EAAE,oBAAoB,GAC5B,QAAQ,CAAC,oBAAoB,CAAC,CAYhC;AAoDD,eAAO,MAAM,QAAQ;
|
|
1
|
+
{"version":3,"file":"SgButton.d.ts","sourceRoot":"","sources":["../../src/buttons/SgButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,KAAK,QAAQ,GACT,SAAS,GACT,WAAW,GACX,SAAS,GACT,MAAM,GACN,SAAS,GACT,MAAM,GACN,QAAQ,CAAC;AAEb,KAAK,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AAEhD,KAAK,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE/B,KAAK,KAAK,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEzD,KAAK,SAAS,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;AAEtC,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC,GAAG;IACzF,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,oBAAoB,CAAC;CACrC,CAAC;AAsEF,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,QAAQ,EAClB,MAAM,CAAC,EAAE,oBAAoB,GAC5B,QAAQ,CAAC,oBAAoB,CAAC,CAYhC;AAoDD,eAAO,MAAM,QAAQ;eApJR,QAAQ;iBACN,UAAU;WAChB,IAAI;YACH,KAAK;gBACD,SAAS;YACb,KAAK,CAAC,SAAS;eACZ,OAAO;eACP,KAAK,CAAC,SAAS;gBACd,KAAK,CAAC,SAAS;cACjB,OAAO;mBACF,oBAAoB;2CAmNpC,CAAC"}
|
package/dist/buttons/SgButton.js
CHANGED
|
@@ -108,15 +108,16 @@ function elevationClass(elevation) {
|
|
|
108
108
|
return "";
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
-
export const SgButton = React.forwardRef(({ severity = "primary", appearance = "solid", size, shape, elevation = "none", iconOnly, leftIcon, rightIcon, loading = false, disabled, className, children, style, customColors, type = "button", ...rest }, ref) => {
|
|
111
|
+
export const SgButton = React.forwardRef(({ severity = "primary", appearance = "solid", size, shape, elevation = "none", label, iconOnly, leftIcon, rightIcon, loading = false, disabled, className, children, style, customColors, type = "button", ...rest }, ref) => {
|
|
112
|
+
const resolvedChildren = children ?? label;
|
|
112
113
|
const isDisabled = Boolean(disabled || loading);
|
|
113
|
-
const inferredIconOnly = !
|
|
114
|
+
const inferredIconOnly = !resolvedChildren && (leftIcon || rightIcon);
|
|
114
115
|
const isIconOnly = iconOnly ?? inferredIconOnly;
|
|
115
116
|
const resolvedSize = size ?? (isIconOnly ? "sm" : "md");
|
|
116
117
|
const resolvedShape = shape ?? (isIconOnly ? "circle" : "default");
|
|
117
118
|
const s = SIZE[resolvedSize];
|
|
118
119
|
const contentClass = cn("inline-flex min-w-0 items-center justify-center", !isIconOnly ? "w-full" : undefined, s.gap);
|
|
119
|
-
return (_jsx("button", { ref: ref, type: type, disabled: isDisabled, style: { ...buildVars(severity, customColors), ...style }, className: cn("inline-flex min-w-0 max-w-full items-center justify-center select-none whitespace-normal break-words text-center", "font-medium", "transition-[background-color,color,border-color,box-shadow,transform] duration-150", "focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-[var(--sg-btn-ring)]", "disabled:opacity-60 disabled:cursor-not-allowed", isIconOnly ? cn("aspect-square", s.h) : cn(s.minH, s.py, s.px), s.text, resolvedShape === "rounded" ? "rounded-full" : resolvedShape === "circle" ? "rounded-full" : resolvedShape === "square" ? "rounded-none" : s.radius, appearanceClass(appearance), elevationClass(elevation), !isDisabled ? "active:translate-y-[0.5px]" : false, className), ...rest, children: loading ? (_jsxs("span", { className: contentClass, children: [_jsx(Spinner, { className: s.icon }),
|
|
120
|
+
return (_jsx("button", { ref: ref, type: type, disabled: isDisabled, style: { ...buildVars(severity, customColors), ...style }, className: cn("inline-flex min-w-0 max-w-full items-center justify-center select-none whitespace-normal break-words text-center", "font-medium", "transition-[background-color,color,border-color,box-shadow,transform] duration-150", "focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-[var(--sg-btn-ring)]", "disabled:opacity-60 disabled:cursor-not-allowed", isIconOnly ? cn("aspect-square", s.h) : cn(s.minH, s.py, s.px), s.text, resolvedShape === "rounded" ? "rounded-full" : resolvedShape === "circle" ? "rounded-full" : resolvedShape === "square" ? "rounded-none" : s.radius, appearanceClass(appearance), elevationClass(elevation), !isDisabled ? "active:translate-y-[0.5px]" : false, className), ...rest, children: loading ? (_jsxs("span", { className: contentClass, children: [_jsx(Spinner, { className: s.icon }), resolvedChildren ? _jsx("span", { className: "min-w-0 whitespace-normal break-words", children: resolvedChildren }) : null] })) : (_jsxs("span", { className: contentClass, children: [leftIcon ? _jsx("span", { className: cn("shrink-0", s.icon), children: leftIcon }) : null, resolvedChildren ? _jsx("span", { className: "min-w-0 whitespace-normal break-words", children: resolvedChildren }) : null, rightIcon ? _jsx("span", { className: cn("shrink-0", s.icon), children: rightIcon }) : null] })) }));
|
|
120
121
|
});
|
|
121
122
|
SgButton.displayName = "SgButton";
|
|
122
123
|
function Spinner({ className }) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type SgSegmentDigitProps = {
|
|
3
|
+
/** Character rendered by the component (first character is used). */
|
|
4
|
+
value: string;
|
|
5
|
+
/** Display height in pixels. */
|
|
6
|
+
size?: number;
|
|
7
|
+
/** Color of active segments. */
|
|
8
|
+
color?: string;
|
|
9
|
+
/** Additional classes on outer wrapper. */
|
|
10
|
+
className?: string;
|
|
11
|
+
/** Additional inline styles on outer wrapper. */
|
|
12
|
+
style?: React.CSSProperties;
|
|
13
|
+
};
|
|
14
|
+
export declare function SgSegmentDigit({ value, size, color, className, style }: Readonly<SgSegmentDigitProps>): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
//# sourceMappingURL=SgSegmentDigit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgSegmentDigit.d.ts","sourceRoot":"","sources":["../../../src/digits/segment-digit/SgSegmentDigit.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA2F/B,MAAM,MAAM,mBAAmB,GAAG;IAChC,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B,CAAC;AAEF,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,IAAS,EACT,KAAK,EACL,SAAS,EACT,KAAK,EACN,EAAE,QAAQ,CAAC,mBAAmB,CAAC,2CAkC/B"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
function cn(...parts) {
|
|
3
|
+
return parts.filter(Boolean).join(" ");
|
|
4
|
+
}
|
|
5
|
+
function round(n) {
|
|
6
|
+
return Math.round(n * 1000) / 1000;
|
|
7
|
+
}
|
|
8
|
+
const DIGIT_GLYPHS = {
|
|
9
|
+
"0": [
|
|
10
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
11
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
12
|
+
{ x: 5, y: 5, w: 1, h: 4 },
|
|
13
|
+
{ x: 1, y: 9, w: 4, h: 1 },
|
|
14
|
+
{ x: 0, y: 5, w: 1, h: 4 },
|
|
15
|
+
{ x: 0, y: 1, w: 1, h: 4 }
|
|
16
|
+
],
|
|
17
|
+
"1": [
|
|
18
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
19
|
+
{ x: 5, y: 5, w: 1, h: 4 }
|
|
20
|
+
],
|
|
21
|
+
"2": [
|
|
22
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
23
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
24
|
+
{ x: 1, y: 4.5, w: 4, h: 1 },
|
|
25
|
+
{ x: 0, y: 5, w: 1, h: 4 },
|
|
26
|
+
{ x: 1, y: 9, w: 4, h: 1 }
|
|
27
|
+
],
|
|
28
|
+
"3": [
|
|
29
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
30
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
31
|
+
{ x: 1, y: 4.5, w: 4, h: 1 },
|
|
32
|
+
{ x: 5, y: 5, w: 1, h: 4 },
|
|
33
|
+
{ x: 1, y: 9, w: 4, h: 1 }
|
|
34
|
+
],
|
|
35
|
+
"4": [
|
|
36
|
+
{ x: 0, y: 1, w: 1, h: 4 },
|
|
37
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
38
|
+
{ x: 1, y: 4.5, w: 4, h: 1 },
|
|
39
|
+
{ x: 5, y: 5, w: 1, h: 4 }
|
|
40
|
+
],
|
|
41
|
+
"5": [
|
|
42
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
43
|
+
{ x: 0, y: 1, w: 1, h: 4 },
|
|
44
|
+
{ x: 1, y: 4.5, w: 4, h: 1 },
|
|
45
|
+
{ x: 5, y: 5, w: 1, h: 4 },
|
|
46
|
+
{ x: 1, y: 9, w: 4, h: 1 }
|
|
47
|
+
],
|
|
48
|
+
"6": [
|
|
49
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
50
|
+
{ x: 0, y: 1, w: 1, h: 4 },
|
|
51
|
+
{ x: 1, y: 4.5, w: 4, h: 1 },
|
|
52
|
+
{ x: 0, y: 5, w: 1, h: 4 },
|
|
53
|
+
{ x: 5, y: 5, w: 1, h: 4 },
|
|
54
|
+
{ x: 1, y: 9, w: 4, h: 1 }
|
|
55
|
+
],
|
|
56
|
+
"7": [
|
|
57
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
58
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
59
|
+
{ x: 5, y: 5, w: 1, h: 4 }
|
|
60
|
+
],
|
|
61
|
+
"8": [
|
|
62
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
63
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
64
|
+
{ x: 5, y: 5, w: 1, h: 4 },
|
|
65
|
+
{ x: 1, y: 9, w: 4, h: 1 },
|
|
66
|
+
{ x: 0, y: 5, w: 1, h: 4 },
|
|
67
|
+
{ x: 0, y: 1, w: 1, h: 4 },
|
|
68
|
+
{ x: 1, y: 4.5, w: 4, h: 1 }
|
|
69
|
+
],
|
|
70
|
+
"9": [
|
|
71
|
+
{ x: 1, y: 0, w: 4, h: 1 },
|
|
72
|
+
{ x: 5, y: 1, w: 1, h: 4 },
|
|
73
|
+
{ x: 5, y: 5, w: 1, h: 4 },
|
|
74
|
+
{ x: 1, y: 9, w: 4, h: 1 },
|
|
75
|
+
{ x: 0, y: 1, w: 1, h: 4 },
|
|
76
|
+
{ x: 1, y: 4.5, w: 4, h: 1 }
|
|
77
|
+
],
|
|
78
|
+
"-": [{ x: 1, y: 4.5, w: 4, h: 1 }],
|
|
79
|
+
" ": []
|
|
80
|
+
};
|
|
81
|
+
const COLON_GLYPH = [
|
|
82
|
+
{ x: 1.5, y: 2, w: 1, h: 1 },
|
|
83
|
+
{ x: 1.5, y: 7, w: 1, h: 1 }
|
|
84
|
+
];
|
|
85
|
+
export function SgSegmentDigit({ value, size = 16, color, className, style }) {
|
|
86
|
+
const char = (value ?? " ").charAt(0);
|
|
87
|
+
const normalized = char === ":" ? ":" : (DIGIT_GLYPHS[char] ? char : " ");
|
|
88
|
+
const isColon = normalized === ":";
|
|
89
|
+
const glyph = isColon ? COLON_GLYPH : DIGIT_GLYPHS[normalized] ?? DIGIT_GLYPHS[" "] ?? [];
|
|
90
|
+
const viewWidth = isColon ? 4 : 6;
|
|
91
|
+
const viewHeight = 10;
|
|
92
|
+
const scale = Math.max(0.2, size / viewHeight);
|
|
93
|
+
const width = round(viewWidth * scale);
|
|
94
|
+
const height = round(viewHeight * scale);
|
|
95
|
+
return (_jsx("svg", { role: "img", "aria-label": value, width: width, height: height, viewBox: `0 0 ${viewWidth} ${viewHeight}`, className: cn("inline-block align-middle text-neutral-800 dark:text-neutral-200", className), style: { color, ...style }, children: glyph.map((segment, idx) => (_jsx("rect", { x: segment.x, y: segment.y, width: segment.w, height: segment.h, rx: 0.3, fill: "currentColor" }, `${normalized}-${idx}`))) }));
|
|
96
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/digits/segment-digit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SgSegmentDigit } from "./SgSegmentDigit";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type SgSevenSegmentDigitPalette = "red" | "blue" | "yellow" | "green" | "white";
|
|
3
|
+
export type SgSevenSegmentDigitProps = {
|
|
4
|
+
/** Character rendered by the component (first character is used). */
|
|
5
|
+
value: string;
|
|
6
|
+
/** Preset visual palette for active, inactive and background colors. */
|
|
7
|
+
palette?: SgSevenSegmentDigitPalette;
|
|
8
|
+
/** Color of active segments. */
|
|
9
|
+
color?: string;
|
|
10
|
+
/** Background color of the component panel. */
|
|
11
|
+
backgroundColor?: string;
|
|
12
|
+
/** Color of inactive segments. */
|
|
13
|
+
offColor?: string;
|
|
14
|
+
/** Component height in pixels. */
|
|
15
|
+
size?: number;
|
|
16
|
+
/** Component width in pixels. By default, derived from `size`. */
|
|
17
|
+
width?: number;
|
|
18
|
+
/** Segment thickness in pixels. */
|
|
19
|
+
thickness?: number;
|
|
20
|
+
/** Internal panel padding in pixels. */
|
|
21
|
+
padding?: number;
|
|
22
|
+
/** Border radius of the panel in pixels. */
|
|
23
|
+
rounded?: number;
|
|
24
|
+
/** Applies a subtle skew to mimic classic LED displays. */
|
|
25
|
+
skew?: number;
|
|
26
|
+
/** Enables glow effect on active segments. */
|
|
27
|
+
glow?: boolean;
|
|
28
|
+
/** Segment transition duration in milliseconds. */
|
|
29
|
+
transitionMs?: number;
|
|
30
|
+
/** Additional classes on outer wrapper. */
|
|
31
|
+
className?: string;
|
|
32
|
+
/** Additional inline styles on outer wrapper. */
|
|
33
|
+
style?: React.CSSProperties;
|
|
34
|
+
};
|
|
35
|
+
export declare function SgSevenSegmentDigit({ value, palette, color, backgroundColor, offColor, size, width, thickness, padding, rounded, skew, glow, transitionMs, className, style }: Readonly<SgSevenSegmentDigitProps>): import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
//# sourceMappingURL=SgSevenSegmentDigit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgSevenSegmentDigit.d.ts","sourceRoot":"","sources":["../../../src/digits/seven-segment-digit/SgSevenSegmentDigit.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAsC/B,MAAM,MAAM,0BAA0B,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AAiCvF,MAAM,MAAM,wBAAwB,GAAG;IACrC,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,OAAO,CAAC,EAAE,0BAA0B,CAAC;IACrC,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B,CAAC;AAQF,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,OAAe,EACf,KAAK,EACL,eAAe,EACf,QAAQ,EACR,IAAU,EACV,KAAK,EACL,SAAc,EACd,OAAY,EACZ,OAAY,EACZ,IAAS,EACT,IAAW,EACX,YAAkB,EAClB,SAAS,EACT,KAAK,EACN,EAAE,QAAQ,CAAC,wBAAwB,CAAC,2CA+EpC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
function cn(...parts) {
|
|
4
|
+
return parts.filter(Boolean).join(" ");
|
|
5
|
+
}
|
|
6
|
+
const SEGMENT_ORDER = ["a", "b", "c", "d", "e", "f", "g"];
|
|
7
|
+
const GLYPHS = {
|
|
8
|
+
" ": [],
|
|
9
|
+
"-": ["g"],
|
|
10
|
+
_: ["d"],
|
|
11
|
+
"0": ["a", "b", "c", "d", "e", "f"],
|
|
12
|
+
"1": ["b", "c"],
|
|
13
|
+
"2": ["a", "b", "d", "e", "g"],
|
|
14
|
+
"3": ["a", "b", "c", "d", "g"],
|
|
15
|
+
"4": ["b", "c", "f", "g"],
|
|
16
|
+
"5": ["a", "c", "d", "f", "g"],
|
|
17
|
+
"6": ["a", "c", "d", "e", "f", "g"],
|
|
18
|
+
"7": ["a", "b", "c"],
|
|
19
|
+
"8": ["a", "b", "c", "d", "e", "f", "g"],
|
|
20
|
+
"9": ["a", "b", "c", "d", "f", "g"],
|
|
21
|
+
A: ["a", "b", "c", "e", "f", "g"],
|
|
22
|
+
B: ["c", "d", "e", "f", "g"],
|
|
23
|
+
C: ["a", "d", "e", "f"],
|
|
24
|
+
D: ["b", "c", "d", "e", "g"],
|
|
25
|
+
E: ["a", "d", "e", "f", "g"],
|
|
26
|
+
F: ["a", "e", "f", "g"],
|
|
27
|
+
H: ["b", "c", "e", "f", "g"],
|
|
28
|
+
J: ["b", "c", "d", "e"],
|
|
29
|
+
L: ["d", "e", "f"],
|
|
30
|
+
P: ["a", "b", "e", "f", "g"],
|
|
31
|
+
U: ["b", "c", "d", "e", "f"],
|
|
32
|
+
Y: ["b", "c", "d", "f", "g"]
|
|
33
|
+
};
|
|
34
|
+
const PALETTES = {
|
|
35
|
+
red: {
|
|
36
|
+
color: "#ef4444",
|
|
37
|
+
backgroundColor: "#120909",
|
|
38
|
+
offColor: "rgba(127, 29, 29, 0.28)"
|
|
39
|
+
},
|
|
40
|
+
blue: {
|
|
41
|
+
color: "#60a5fa",
|
|
42
|
+
backgroundColor: "#061226",
|
|
43
|
+
offColor: "rgba(30, 64, 175, 0.3)"
|
|
44
|
+
},
|
|
45
|
+
yellow: {
|
|
46
|
+
color: "#facc15",
|
|
47
|
+
backgroundColor: "#1a1303",
|
|
48
|
+
offColor: "rgba(161, 98, 7, 0.32)"
|
|
49
|
+
},
|
|
50
|
+
green: {
|
|
51
|
+
color: "#22c55e",
|
|
52
|
+
backgroundColor: "#04120a",
|
|
53
|
+
offColor: "rgba(20, 83, 45, 0.28)"
|
|
54
|
+
},
|
|
55
|
+
white: {
|
|
56
|
+
color: "#f8fafc",
|
|
57
|
+
backgroundColor: "#111827",
|
|
58
|
+
offColor: "rgba(148, 163, 184, 0.3)"
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
function segmentSetFor(value) {
|
|
62
|
+
const char = (value ?? " ").charAt(0).toUpperCase();
|
|
63
|
+
const segments = GLYPHS[char] ?? GLYPHS[" "] ?? [];
|
|
64
|
+
return new Set(segments);
|
|
65
|
+
}
|
|
66
|
+
export function SgSevenSegmentDigit({ value, palette = "red", color, backgroundColor, offColor, size = 108, width, thickness = 14, padding = 10, rounded = 12, skew = -8, glow = true, transitionMs = 180, className, style }) {
|
|
67
|
+
const active = React.useMemo(() => segmentSetFor(value), [value]);
|
|
68
|
+
const paletteTokens = PALETTES[palette];
|
|
69
|
+
const activeColor = color ?? paletteTokens.color;
|
|
70
|
+
const panelBackground = backgroundColor ?? paletteTokens.backgroundColor;
|
|
71
|
+
const inactiveColor = offColor ?? paletteTokens.offColor;
|
|
72
|
+
const h = Math.max(48, Math.round(size));
|
|
73
|
+
const w = Math.max(28, Math.round(width ?? h * 0.62));
|
|
74
|
+
const t = Math.max(4, Math.round(thickness));
|
|
75
|
+
const p = Math.max(2, Math.round(padding));
|
|
76
|
+
const innerW = Math.max(1, w - p * 2);
|
|
77
|
+
const innerH = Math.max(1, h - p * 2);
|
|
78
|
+
const halfInner = Math.floor(innerH / 2);
|
|
79
|
+
const segmentLength = Math.max(1, innerW - t);
|
|
80
|
+
const verticalLength = Math.max(1, halfInner - t);
|
|
81
|
+
const glowSize = Math.max(4, Math.round(t * 1.25));
|
|
82
|
+
const horizontalStyle = (top) => ({
|
|
83
|
+
left: p + t / 2,
|
|
84
|
+
top,
|
|
85
|
+
width: segmentLength,
|
|
86
|
+
height: t,
|
|
87
|
+
borderRadius: t / 2
|
|
88
|
+
});
|
|
89
|
+
const verticalStyle = (left, top) => ({
|
|
90
|
+
left,
|
|
91
|
+
top,
|
|
92
|
+
width: t,
|
|
93
|
+
height: verticalLength,
|
|
94
|
+
borderRadius: t / 2
|
|
95
|
+
});
|
|
96
|
+
const segmentStyles = {
|
|
97
|
+
a: horizontalStyle(p),
|
|
98
|
+
b: verticalStyle(w - p - t, p + t / 2),
|
|
99
|
+
c: verticalStyle(w - p - t, p + halfInner + t / 2),
|
|
100
|
+
d: horizontalStyle(h - p - t),
|
|
101
|
+
e: verticalStyle(p, p + halfInner + t / 2),
|
|
102
|
+
f: verticalStyle(p, p + t / 2),
|
|
103
|
+
g: horizontalStyle(p + halfInner - t / 2)
|
|
104
|
+
};
|
|
105
|
+
return (_jsx("div", { role: "img", "aria-label": value, className: cn("inline-flex", className), style: {
|
|
106
|
+
width: w,
|
|
107
|
+
height: h,
|
|
108
|
+
borderRadius: rounded,
|
|
109
|
+
overflow: "hidden",
|
|
110
|
+
backgroundColor: panelBackground,
|
|
111
|
+
boxShadow: "inset 0 0 0 1px rgba(255,255,255,0.06), inset 0 10px 20px rgba(0,0,0,0.16)",
|
|
112
|
+
...style
|
|
113
|
+
}, children: _jsx("div", { className: "relative h-full w-full", style: { transform: `skewX(${skew}deg)` }, children: SEGMENT_ORDER.map((segmentName) => {
|
|
114
|
+
const isOn = active.has(segmentName);
|
|
115
|
+
return (_jsx("span", { "aria-hidden": "true", style: {
|
|
116
|
+
position: "absolute",
|
|
117
|
+
...segmentStyles[segmentName],
|
|
118
|
+
backgroundColor: isOn ? activeColor : inactiveColor,
|
|
119
|
+
boxShadow: isOn && glow ? `0 0 ${glowSize}px ${activeColor}` : "none",
|
|
120
|
+
transition: `background-color ${transitionMs}ms ease, box-shadow ${transitionMs}ms ease`
|
|
121
|
+
} }, segmentName));
|
|
122
|
+
}) }) }));
|
|
123
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/digits/seven-segment-digit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SgSevenSegmentDigit } from "./SgSevenSegmentDigit";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type SgCardProps } from "../../layout/SgCard";
|
|
3
|
+
export type SgCalendarWeekdayFormat = "narrow" | "short" | "long";
|
|
4
|
+
export type SgCalendarProps = Omit<React.HTMLAttributes<HTMLDivElement>, "children" | "onChange"> & {
|
|
5
|
+
value?: Date | string;
|
|
6
|
+
defaultValue?: Date | string;
|
|
7
|
+
onValueChange?: (date: Date) => void;
|
|
8
|
+
viewDate?: Date | string;
|
|
9
|
+
defaultViewDate?: Date | string;
|
|
10
|
+
onViewDateChange?: (viewDate: Date) => void;
|
|
11
|
+
locale?: string;
|
|
12
|
+
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
|
|
13
|
+
weekdayFormat?: SgCalendarWeekdayFormat;
|
|
14
|
+
numberOfMonths?: number;
|
|
15
|
+
monthsPerLine?: number;
|
|
16
|
+
monthMinWidth?: number | string;
|
|
17
|
+
showAdjacentMonths?: boolean;
|
|
18
|
+
minDate?: Date | string;
|
|
19
|
+
maxDate?: Date | string;
|
|
20
|
+
isDateDisabled?: (date: Date) => boolean;
|
|
21
|
+
showTodayShortcut?: boolean;
|
|
22
|
+
cardTitle?: React.ReactNode;
|
|
23
|
+
cardProps?: Omit<SgCardProps, "children" | "title">;
|
|
24
|
+
};
|
|
25
|
+
export declare function SgCalendar(props: Readonly<SgCalendarProps>): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
export declare namespace SgCalendar {
|
|
27
|
+
var displayName: string;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=SgCalendar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgCalendar.d.ts","sourceRoot":"","sources":["../../../src/gadgets/calendar/SgCalendar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AA8H/D,MAAM,MAAM,uBAAuB,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAElE,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC,GAAG;IAClG,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAC7B,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,KAAK,IAAI,CAAC;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzC,aAAa,CAAC,EAAE,uBAAuB,CAAC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,OAAO,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;IACzC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B,SAAS,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC;CACrD,CAAC;AAEF,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAC,2CAyT1D;yBAzTe,UAAU"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { SgCard } from "../../layout/SgCard";
|
|
5
|
+
import { t, useComponentsI18n } from "../../i18n";
|
|
6
|
+
function cn(...parts) {
|
|
7
|
+
return parts.filter(Boolean).join(" ");
|
|
8
|
+
}
|
|
9
|
+
function normalizeDate(date) {
|
|
10
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
11
|
+
}
|
|
12
|
+
function startOfMonth(date) {
|
|
13
|
+
return new Date(date.getFullYear(), date.getMonth(), 1);
|
|
14
|
+
}
|
|
15
|
+
function addMonths(date, amount) {
|
|
16
|
+
return new Date(date.getFullYear(), date.getMonth() + amount, 1);
|
|
17
|
+
}
|
|
18
|
+
function addDays(date, amount) {
|
|
19
|
+
const next = new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
20
|
+
next.setDate(next.getDate() + amount);
|
|
21
|
+
return normalizeDate(next);
|
|
22
|
+
}
|
|
23
|
+
function isValidDate(date) {
|
|
24
|
+
return date instanceof Date && Number.isFinite(date.getTime());
|
|
25
|
+
}
|
|
26
|
+
const DATE_ONLY_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
27
|
+
function parseDateInput(value) {
|
|
28
|
+
if (value === undefined || value === null)
|
|
29
|
+
return null;
|
|
30
|
+
if (isValidDate(value))
|
|
31
|
+
return normalizeDate(value);
|
|
32
|
+
if (typeof value === "string") {
|
|
33
|
+
const trimmed = value.trim();
|
|
34
|
+
if (!trimmed)
|
|
35
|
+
return null;
|
|
36
|
+
const dateOnlyMatch = DATE_ONLY_RE.exec(trimmed);
|
|
37
|
+
if (dateOnlyMatch) {
|
|
38
|
+
const year = Number.parseInt(dateOnlyMatch[1] ?? "0", 10);
|
|
39
|
+
const month = Number.parseInt(dateOnlyMatch[2] ?? "1", 10) - 1;
|
|
40
|
+
const day = Number.parseInt(dateOnlyMatch[3] ?? "1", 10);
|
|
41
|
+
const localDate = new Date(year, month, day);
|
|
42
|
+
return isValidDate(localDate) ? normalizeDate(localDate) : null;
|
|
43
|
+
}
|
|
44
|
+
const parsed = new Date(trimmed);
|
|
45
|
+
return isValidDate(parsed) ? normalizeDate(parsed) : null;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
function isSameDay(a, b) {
|
|
50
|
+
return (a.getFullYear() === b.getFullYear() &&
|
|
51
|
+
a.getMonth() === b.getMonth() &&
|
|
52
|
+
a.getDate() === b.getDate());
|
|
53
|
+
}
|
|
54
|
+
function isSameMonth(a, b) {
|
|
55
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
|
|
56
|
+
}
|
|
57
|
+
function clampWeekStart(value) {
|
|
58
|
+
if (!Number.isFinite(value))
|
|
59
|
+
return 0;
|
|
60
|
+
const normalized = Math.trunc(value) % 7;
|
|
61
|
+
return normalized < 0 ? normalized + 7 : normalized;
|
|
62
|
+
}
|
|
63
|
+
function clampInt(value, fallback, min, max) {
|
|
64
|
+
if (!Number.isFinite(value))
|
|
65
|
+
return fallback;
|
|
66
|
+
const numeric = Math.trunc(value);
|
|
67
|
+
if (numeric < min)
|
|
68
|
+
return min;
|
|
69
|
+
if (numeric > max)
|
|
70
|
+
return max;
|
|
71
|
+
return numeric;
|
|
72
|
+
}
|
|
73
|
+
function resolveCssLength(value, fallback) {
|
|
74
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
|
|
75
|
+
return `${value}px`;
|
|
76
|
+
}
|
|
77
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
78
|
+
return value.trim();
|
|
79
|
+
}
|
|
80
|
+
return fallback;
|
|
81
|
+
}
|
|
82
|
+
function dateKey(date) {
|
|
83
|
+
const y = date.getFullYear();
|
|
84
|
+
const m = String(date.getMonth() + 1).padStart(2, "0");
|
|
85
|
+
const d = String(date.getDate()).padStart(2, "0");
|
|
86
|
+
return `${y}-${m}-${d}`;
|
|
87
|
+
}
|
|
88
|
+
function capitalizeFirst(value, locale) {
|
|
89
|
+
if (!value)
|
|
90
|
+
return value;
|
|
91
|
+
return value.charAt(0).toLocaleUpperCase(locale) + value.slice(1);
|
|
92
|
+
}
|
|
93
|
+
function resolveCalendarUiLabels(locale) {
|
|
94
|
+
const lower = locale.toLowerCase();
|
|
95
|
+
if (lower.startsWith("pt")) {
|
|
96
|
+
return {
|
|
97
|
+
previousMonth: "Mes anterior",
|
|
98
|
+
nextMonth: "Proximo mes",
|
|
99
|
+
goToday: "Ir para hoje"
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (lower.startsWith("es")) {
|
|
103
|
+
return {
|
|
104
|
+
previousMonth: "Mes anterior",
|
|
105
|
+
nextMonth: "Mes siguiente",
|
|
106
|
+
goToday: "Ir a hoy"
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
previousMonth: "Previous month",
|
|
111
|
+
nextMonth: "Next month",
|
|
112
|
+
goToday: "Go to today"
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
export function SgCalendar(props) {
|
|
116
|
+
const i18n = useComponentsI18n();
|
|
117
|
+
const { value, defaultValue, onValueChange, viewDate, defaultViewDate, onViewDateChange, locale = "pt-BR", weekStartsOn = 0, weekdayFormat = "narrow", numberOfMonths = 1, monthsPerLine = 3, monthMinWidth, showAdjacentMonths = true, minDate, maxDate, isDateDisabled, showTodayShortcut = true, className, style, cardTitle, cardProps, ...rest } = props;
|
|
118
|
+
const resolvedCardTitle = cardTitle ?? t(i18n, "components.gadgets.calendar.title");
|
|
119
|
+
const today = React.useMemo(() => normalizeDate(new Date()), []);
|
|
120
|
+
const valueControlled = value !== undefined;
|
|
121
|
+
const viewControlled = viewDate !== undefined;
|
|
122
|
+
const parsedControlledValue = React.useMemo(() => parseDateInput(value), [value]);
|
|
123
|
+
const parsedMinDate = React.useMemo(() => parseDateInput(minDate), [minDate]);
|
|
124
|
+
const parsedMaxDate = React.useMemo(() => parseDateInput(maxDate), [maxDate]);
|
|
125
|
+
const [internalValue, setInternalValue] = React.useState(() => {
|
|
126
|
+
const parsedDefault = parseDateInput(defaultValue);
|
|
127
|
+
return parsedDefault ?? today;
|
|
128
|
+
});
|
|
129
|
+
const selectedDate = valueControlled ? parsedControlledValue ?? today : internalValue;
|
|
130
|
+
const [internalViewDate, setInternalViewDate] = React.useState(() => {
|
|
131
|
+
const parsedDefaultView = parseDateInput(defaultViewDate);
|
|
132
|
+
const parsedDefaultValue = parseDateInput(defaultValue);
|
|
133
|
+
return startOfMonth(parsedDefaultView ?? parsedDefaultValue ?? today);
|
|
134
|
+
});
|
|
135
|
+
const parsedControlledViewDate = React.useMemo(() => parseDateInput(viewDate), [viewDate]);
|
|
136
|
+
const monthViewDate = viewControlled
|
|
137
|
+
? startOfMonth(parsedControlledViewDate ?? selectedDate)
|
|
138
|
+
: internalViewDate;
|
|
139
|
+
React.useEffect(() => {
|
|
140
|
+
if (viewControlled)
|
|
141
|
+
return;
|
|
142
|
+
if (!valueControlled)
|
|
143
|
+
return;
|
|
144
|
+
if (!parsedControlledValue)
|
|
145
|
+
return;
|
|
146
|
+
setInternalViewDate((current) => {
|
|
147
|
+
if (isSameMonth(current, parsedControlledValue))
|
|
148
|
+
return current;
|
|
149
|
+
return startOfMonth(parsedControlledValue);
|
|
150
|
+
});
|
|
151
|
+
}, [parsedControlledValue, valueControlled, viewControlled]);
|
|
152
|
+
const safeWeekStartsOn = clampWeekStart(weekStartsOn);
|
|
153
|
+
const safeNumberOfMonths = clampInt(numberOfMonths, 1, 1, 12);
|
|
154
|
+
const safeMonthsPerLine = Math.min(safeNumberOfMonths, clampInt(monthsPerLine, 3, 1, 12));
|
|
155
|
+
const uiLabels = resolveCalendarUiLabels(locale);
|
|
156
|
+
const formatSelectedDate = React.useMemo(() => new Intl.DateTimeFormat(locale, {
|
|
157
|
+
weekday: "long",
|
|
158
|
+
day: "numeric",
|
|
159
|
+
month: "long"
|
|
160
|
+
}), [locale]);
|
|
161
|
+
const formatMonthYear = React.useMemo(() => new Intl.DateTimeFormat(locale, {
|
|
162
|
+
month: "long",
|
|
163
|
+
year: "numeric"
|
|
164
|
+
}), [locale]);
|
|
165
|
+
const weekdayLabels = React.useMemo(() => {
|
|
166
|
+
const formatter = new Intl.DateTimeFormat(locale, { weekday: weekdayFormat });
|
|
167
|
+
const sundayAnchor = new Date(2026, 2, 1);
|
|
168
|
+
return Array.from({ length: 7 }, (_, index) => {
|
|
169
|
+
const weekDay = (safeWeekStartsOn + index) % 7;
|
|
170
|
+
const dayDate = addDays(sundayAnchor, weekDay);
|
|
171
|
+
const raw = formatter.format(dayDate);
|
|
172
|
+
return capitalizeFirst(raw, locale);
|
|
173
|
+
});
|
|
174
|
+
}, [locale, safeWeekStartsOn, weekdayFormat]);
|
|
175
|
+
const setMonthViewDate = React.useCallback((next) => {
|
|
176
|
+
const normalized = startOfMonth(next);
|
|
177
|
+
if (!viewControlled) {
|
|
178
|
+
setInternalViewDate(normalized);
|
|
179
|
+
}
|
|
180
|
+
onViewDateChange?.(new Date(normalized));
|
|
181
|
+
}, [onViewDateChange, viewControlled]);
|
|
182
|
+
const isCellDisabled = React.useCallback((date) => {
|
|
183
|
+
if (parsedMinDate && date.getTime() < parsedMinDate.getTime())
|
|
184
|
+
return true;
|
|
185
|
+
if (parsedMaxDate && date.getTime() > parsedMaxDate.getTime())
|
|
186
|
+
return true;
|
|
187
|
+
if (isDateDisabled?.(date))
|
|
188
|
+
return true;
|
|
189
|
+
return false;
|
|
190
|
+
}, [isDateDisabled, parsedMaxDate, parsedMinDate]);
|
|
191
|
+
const handleSelectDate = React.useCallback((date) => {
|
|
192
|
+
if (isCellDisabled(date))
|
|
193
|
+
return;
|
|
194
|
+
if (!valueControlled) {
|
|
195
|
+
setInternalValue(date);
|
|
196
|
+
}
|
|
197
|
+
onValueChange?.(new Date(date));
|
|
198
|
+
if (!isSameMonth(date, monthViewDate)) {
|
|
199
|
+
setMonthViewDate(date);
|
|
200
|
+
}
|
|
201
|
+
}, [isCellDisabled, monthViewDate, onValueChange, setMonthViewDate, valueControlled]);
|
|
202
|
+
const handleGoToday = React.useCallback(() => {
|
|
203
|
+
const now = normalizeDate(new Date());
|
|
204
|
+
if (!isCellDisabled(now)) {
|
|
205
|
+
if (!valueControlled) {
|
|
206
|
+
setInternalValue(now);
|
|
207
|
+
}
|
|
208
|
+
onValueChange?.(new Date(now));
|
|
209
|
+
}
|
|
210
|
+
setMonthViewDate(now);
|
|
211
|
+
}, [isCellDisabled, onValueChange, setMonthViewDate, valueControlled]);
|
|
212
|
+
const monthDates = React.useMemo(() => Array.from({ length: safeNumberOfMonths }, (_, index) => addMonths(monthViewDate, index)), [monthViewDate, safeNumberOfMonths]);
|
|
213
|
+
const selectedLabel = capitalizeFirst(formatSelectedDate.format(selectedDate), locale);
|
|
214
|
+
const visibleColumns = Math.min(safeMonthsPerLine, safeNumberOfMonths);
|
|
215
|
+
const monthColumnMinWidth = resolveCssLength(monthMinWidth, visibleColumns === 1 ? "20.75rem" : "16rem");
|
|
216
|
+
const monthGridStyle = {
|
|
217
|
+
gridTemplateColumns: `repeat(${visibleColumns}, minmax(${monthColumnMinWidth}, 1fr))`,
|
|
218
|
+
width: visibleColumns === 1 ? "max-content" : "100%"
|
|
219
|
+
};
|
|
220
|
+
const mergedCardClassName = cn("max-w-full", cardProps?.className);
|
|
221
|
+
const mergedCardBodyClassName = cn("max-h-full max-w-full overflow-auto", cardProps?.bodyClassName);
|
|
222
|
+
const mergedCardStyle = {
|
|
223
|
+
width: "fit-content",
|
|
224
|
+
maxWidth: "100%",
|
|
225
|
+
...(cardProps?.style ?? {})
|
|
226
|
+
};
|
|
227
|
+
return (_jsx(SgCard, { title: resolvedCardTitle, collapsible: true, defaultOpen: true, collapseToggleAlign: "right", collapseIconSize: 20, draggable: true, bgColor: "#ffffff", bgColorTitle: "#f3f4f6", cardStyle: "outlined", ...cardProps, className: mergedCardClassName, bodyClassName: mergedCardBodyClassName, style: mergedCardStyle, children: _jsxs("div", { className: cn("inline-flex max-w-full select-none flex-col gap-3", className), style: style, ...rest, children: [_jsxs("div", { className: "flex items-center justify-between gap-3 rounded-lg border border-border/70 bg-background px-4 py-3", children: [_jsx("div", { className: "min-h-6 text-sm font-medium text-foreground", children: selectedLabel }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { type: "button", onClick: () => setMonthViewDate(addMonths(monthViewDate, -1)), className: "inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", "aria-label": uiLabels.previousMonth, title: uiLabels.previousMonth, children: _jsx("svg", { viewBox: "0 0 20 20", className: "h-4 w-4", "aria-hidden": "true", children: _jsx("path", { d: "m12.5 5.8-4.2 4.2 4.2 4.2", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), _jsx("button", { type: "button", onClick: () => setMonthViewDate(addMonths(monthViewDate, 1)), className: "inline-flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", "aria-label": uiLabels.nextMonth, title: uiLabels.nextMonth, children: _jsx("svg", { viewBox: "0 0 20 20", className: "h-4 w-4", "aria-hidden": "true", children: _jsx("path", { d: "m7.5 5.8 4.2 4.2-4.2 4.2", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) }), showTodayShortcut ? (_jsx("button", { type: "button", onClick: handleGoToday, className: "inline-flex h-8 w-8 items-center justify-center rounded-md border border-border/70 bg-muted/40 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", "aria-label": uiLabels.goToday, title: uiLabels.goToday, children: _jsx("svg", { viewBox: "0 0 20 20", className: "h-4 w-4", "aria-hidden": "true", children: _jsx("path", { d: "M5.6 7.6 10 12l4.4-4.4", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) })) : null] })] }), _jsx("div", { className: "max-h-full max-w-full overflow-auto", children: _jsx("div", { className: "grid gap-4", style: monthGridStyle, children: monthDates.map((monthDate) => {
|
|
228
|
+
const firstDayOfMonth = startOfMonth(monthDate);
|
|
229
|
+
const firstDayOffset = (firstDayOfMonth.getDay() - safeWeekStartsOn + 7) % 7;
|
|
230
|
+
const gridStart = addDays(firstDayOfMonth, -firstDayOffset);
|
|
231
|
+
const days = Array.from({ length: 42 }, (_, index) => addDays(gridStart, index));
|
|
232
|
+
const monthLabel = capitalizeFirst(formatMonthYear.format(monthDate), locale);
|
|
233
|
+
return (_jsxs("div", { className: "rounded-xl border border-border/70 bg-background", children: [_jsx("div", { className: "border-b border-border/70 px-4 py-3", children: _jsx("div", { className: "text-[1.1rem] font-semibold text-foreground", children: monthLabel }) }), _jsxs("div", { className: "px-4 pb-4 pt-3", children: [_jsx("div", { className: "mb-2 grid grid-cols-7 text-center text-[0.79rem] font-medium uppercase tracking-wide text-muted-foreground", children: weekdayLabels.map((label, index) => (_jsx("span", { className: "py-1", children: label }, `${label}-${index}`))) }), _jsx("div", { className: "grid grid-cols-7 gap-y-1", children: days.map((day) => {
|
|
234
|
+
const inCurrentMonth = isSameMonth(day, monthDate);
|
|
235
|
+
const hiddenAdjacentDay = !showAdjacentMonths && !inCurrentMonth;
|
|
236
|
+
const disabled = isCellDisabled(day);
|
|
237
|
+
const selected = isSameDay(day, selectedDate) && inCurrentMonth;
|
|
238
|
+
const isToday = isSameDay(day, today) && inCurrentMonth;
|
|
239
|
+
if (hiddenAdjacentDay) {
|
|
240
|
+
return (_jsx("span", { className: "mx-auto inline-flex h-10 w-10", "aria-hidden": "true" }, `${dateKey(day)}-blank`));
|
|
241
|
+
}
|
|
242
|
+
return (_jsx("button", { type: "button", onClick: () => handleSelectDate(day), disabled: disabled, className: cn("mx-auto inline-flex h-10 w-10 items-center justify-center rounded-full text-sm font-medium transition-colors", selected
|
|
243
|
+
? "bg-primary text-primary-foreground shadow-sm"
|
|
244
|
+
: "hover:bg-muted", inCurrentMonth ? "text-foreground" : "text-muted-foreground", disabled ? "cursor-not-allowed opacity-40" : "", isToday && !selected ? "ring-1 ring-primary/45 ring-offset-1 ring-offset-background" : ""), "aria-pressed": selected, children: day.getDate() }, dateKey(day)));
|
|
245
|
+
}) })] })] }, `${monthDate.getFullYear()}-${monthDate.getMonth()}`));
|
|
246
|
+
}) }) })] }) }));
|
|
247
|
+
}
|
|
248
|
+
SgCalendar.displayName = "SgCalendar";
|