@seedgrid/fe-components 2026.3.11 → 2026.3.13
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/LICENSE +21 -0
- package/README.md +181 -0
- 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/roller3d-digit/SgRoller3DDigit.d.ts.map +1 -1
- package/dist/digits/roller3d-digit/SgRoller3DDigit.js +4 -2
- package/dist/digits/segment-digit/SgSegmentDigit.js +1 -1
- package/dist/gadgets/calendar/SgCalendar.js +1 -1
- package/dist/gadgets/clock/SgClock.d.ts.map +1 -1
- package/dist/gadgets/clock/SgClock.js +10 -5
- package/dist/gadgets/clock/themes/SgClockThemePicker.d.ts.map +1 -1
- package/dist/gadgets/clock/themes/SgClockThemePicker.js +3 -3
- package/dist/gadgets/clock/themes/renderTheme.d.ts.map +1 -1
- package/dist/gadgets/clock/themes/renderTheme.js +3 -1
- package/dist/gadgets/clock/themes/useDarkFlag.d.ts.map +1 -1
- package/dist/gadgets/clock/themes/useDarkFlag.js +34 -3
- package/dist/inputs/SgAutocomplete.js +3 -3
- package/dist/inputs/SgCombobox.js +4 -4
- package/dist/inputs/SgDatatable.js +3 -3
- package/dist/inputs/SgInputCurrency.d.ts.map +1 -1
- package/dist/inputs/SgInputCurrency.js +5 -3
- package/dist/inputs/SgInputDate.js +2 -2
- package/dist/inputs/SgInputNumber.d.ts.map +1 -1
- package/dist/inputs/SgInputNumber.js +8 -4
- package/dist/inputs/SgInputOTP.js +1 -1
- package/dist/inputs/SgInputSelect.js +3 -3
- package/dist/inputs/SgInputText.d.ts.map +1 -1
- package/dist/inputs/SgInputText.js +8 -4
- package/dist/inputs/SgInputTextArea.d.ts.map +1 -1
- package/dist/inputs/SgInputTextArea.js +8 -4
- package/dist/inputs/SgOrderList.js +2 -2
- package/dist/inputs/SgPickList.js +3 -3
- package/dist/inputs/SgTextEditor.d.ts.map +1 -1
- package/dist/inputs/SgTextEditor.js +9 -4
- package/dist/inputs/SgToggleSwitch.js +1 -1
- package/dist/layout/SgCarousel.js +3 -3
- package/dist/layout/SgGroupBox.js +1 -1
- package/dist/layout/SgMenu.js +1 -1
- package/dist/menus/SgDockMenu.d.ts.map +1 -1
- package/dist/menus/SgDockMenu.js +20 -10
- package/dist/others/SgPlayground.d.ts.map +1 -1
- package/dist/others/SgPlayground.js +24 -1
- package/dist/overlay/SgDialog.d.ts.map +1 -1
- package/dist/overlay/SgDialog.js +203 -1
- package/dist/sandbox.cjs +80 -80
- package/dist/wizard/SgWizard.js +4 -4
- package/package.json +5 -4
|
@@ -383,6 +383,7 @@ const SANDPACK_NODE_FS_PROMISES_PACKAGE_JSON_SHIM = JSON.stringify({
|
|
|
383
383
|
module: "index.js"
|
|
384
384
|
});
|
|
385
385
|
const SANDPACK_FALLBACK_THEME_VARS = {
|
|
386
|
+
"--sg-mode": "light",
|
|
386
387
|
// shadcn/ui design tokens (HSL)
|
|
387
388
|
"--background": "0 0% 100%",
|
|
388
389
|
"--foreground": "222.2 84% 4.9%",
|
|
@@ -564,6 +565,7 @@ const SANDPACK_CORE_THEME_VARS = [
|
|
|
564
565
|
// CSSStyleDeclaration.length/.item() does NOT enumerate CSS custom properties,
|
|
565
566
|
// so we must call getPropertyValue() for each var by name.
|
|
566
567
|
const SANDPACK_SG_VARS = [
|
|
568
|
+
"--sg-mode",
|
|
567
569
|
// Neutrals
|
|
568
570
|
"--sg-bg", "--sg-surface", "--sg-muted-surface",
|
|
569
571
|
"--sg-text", "--sg-muted", "--sg-border", "--sg-ring",
|
|
@@ -856,6 +858,25 @@ function readThemeVarsFromHost() {
|
|
|
856
858
|
Object.assign(themeVars, mapSgVarsToCoreVars(themeVars));
|
|
857
859
|
return themeVars;
|
|
858
860
|
}
|
|
861
|
+
function resolveSandpackThemeFromHost() {
|
|
862
|
+
if (typeof window === "undefined")
|
|
863
|
+
return "light";
|
|
864
|
+
const root = document.documentElement;
|
|
865
|
+
const computed = window.getComputedStyle(root);
|
|
866
|
+
const mode = computed.getPropertyValue("--sg-mode").trim().toLowerCase();
|
|
867
|
+
if (mode === "dark")
|
|
868
|
+
return "dark";
|
|
869
|
+
if (mode === "light")
|
|
870
|
+
return "light";
|
|
871
|
+
const dataTheme = root.getAttribute("data-theme")?.trim().toLowerCase();
|
|
872
|
+
if (dataTheme === "dark")
|
|
873
|
+
return "dark";
|
|
874
|
+
if (dataTheme === "light")
|
|
875
|
+
return "light";
|
|
876
|
+
if (root.classList.contains("dark"))
|
|
877
|
+
return "dark";
|
|
878
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
879
|
+
}
|
|
859
880
|
function getStyleSheetHref(styleSheet) {
|
|
860
881
|
const cssSheet = styleSheet;
|
|
861
882
|
if (cssSheet.href)
|
|
@@ -1035,6 +1056,7 @@ export default function SgPlayground(props) {
|
|
|
1035
1056
|
const { code, interactive = false, codeContract = "renderBody", preset = "auto", title, description, height = 360, expandedHeight = "70vh", expandable = true, resizable = true, resizeAxis = "vertical", previewPadding, className, style, dependencies, defaultImports, previewWrapperClassName = "h-[420px] rounded-xl border border-border bg-muted/30 p-3", seedgridDependency, bundlerURL, bundlerTimeoutMs, npmRegistries, withCard = true, collapsible = true, defaultOpen = true, cardId } = props;
|
|
1036
1057
|
const effectivePreviewPadding = normalizeCssSize(previewPadding ?? (codeContract === "appFile" ? 12 : 0));
|
|
1037
1058
|
const [sandpackStylesCss, setSandpackStylesCss] = React.useState(() => buildSandpackStylesCss({}, effectivePreviewPadding));
|
|
1059
|
+
const [sandpackTheme, setSandpackTheme] = React.useState(() => resolveSandpackThemeFromHost());
|
|
1038
1060
|
const [isExpanded, setIsExpanded] = React.useState(false);
|
|
1039
1061
|
const [activePanel, setActivePanel] = React.useState("code");
|
|
1040
1062
|
React.useEffect(() => {
|
|
@@ -1045,6 +1067,7 @@ export default function SgPlayground(props) {
|
|
|
1045
1067
|
const liveThemeVars = readThemeVarsFromHost();
|
|
1046
1068
|
const hostCss = readHostNextCssText();
|
|
1047
1069
|
setSandpackStylesCss(buildSandpackStylesCss(liveThemeVars, effectivePreviewPadding, hostCss));
|
|
1070
|
+
setSandpackTheme(resolveSandpackThemeFromHost());
|
|
1048
1071
|
};
|
|
1049
1072
|
let frameId = null;
|
|
1050
1073
|
const scheduleRefresh = () => {
|
|
@@ -1427,7 +1450,7 @@ export default function SgPlayground(props) {
|
|
|
1427
1450
|
visibleFiles: ["/App.tsx"],
|
|
1428
1451
|
externalResources: includeSeedgridDependency ? SANDPACK_EXTERNAL_RESOURCES : []
|
|
1429
1452
|
}), [includeSeedgridDependency, resolvedBundlerTimeoutMs, resolvedBundlerURL]);
|
|
1430
|
-
const content = interactive ? (_jsx("div", { className: cn(withCard ? "" : "rounded-lg border border-border", withCard ? undefined : className), style: withCard ? undefined : style, children: _jsxs(SandpackProvider, { template: "react-ts", files: files, customSetup: sandpackCustomSetup, options: sandpackOptions, children: [_jsx("style", { children: SANDPACK_HOST_STYLES_CSS }), _jsxs("div", { className: "flex items-center justify-between border-b border-border px-3 py-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [withCard ? null : _jsx("span", { className: "text-sm font-medium", children: title ?? "Example" }), _jsx("span", { className: "text-xs text-muted-foreground", children: codeContract === "renderBody" ? "editable snippet" : "editable App.tsx" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [expandable ? (_jsx(SgButton, { appearance: "outline", size: "sm", onClick: () => setIsExpanded((prev) => !prev), children: isExpanded ? "Reduzir" : "Expandir" })) : null, _jsx(RunButton, { onRun: () => setActivePanel("preview") })] })] }), _jsxs("div", { className: "flex md:hidden border-b border-border", children: [_jsx("button", { type: "button", className: cn("flex-1 py-2 text-sm font-medium border-b-2 -mb-px transition-colors", activePanel === "code"
|
|
1453
|
+
const content = interactive ? (_jsx("div", { className: cn(withCard ? "" : "rounded-lg border border-border", withCard ? undefined : className), style: withCard ? undefined : style, children: _jsxs(SandpackProvider, { template: "react-ts", files: files, customSetup: sandpackCustomSetup, options: sandpackOptions, theme: sandpackTheme, children: [_jsx("style", { children: SANDPACK_HOST_STYLES_CSS }), _jsxs("div", { className: "flex items-center justify-between border-b border-border px-3 py-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [withCard ? null : _jsx("span", { className: "text-sm font-medium", children: title ?? "Example" }), _jsx("span", { className: "text-xs text-muted-foreground", children: codeContract === "renderBody" ? "editable snippet" : "editable App.tsx" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [expandable ? (_jsx(SgButton, { appearance: "outline", size: "sm", onClick: () => setIsExpanded((prev) => !prev), children: isExpanded ? "Reduzir" : "Expandir" })) : null, _jsx(RunButton, { onRun: () => setActivePanel("preview") })] })] }), _jsxs("div", { className: "flex md:hidden border-b border-border", children: [_jsx("button", { type: "button", className: cn("flex-1 py-2 text-sm font-medium border-b-2 -mb-px transition-colors", activePanel === "code"
|
|
1431
1454
|
? "border-primary text-foreground"
|
|
1432
1455
|
: "border-transparent text-muted-foreground hover:text-foreground"), onClick: () => setActivePanel("code"), children: "C\u00F3digo" }), _jsx("button", { type: "button", className: cn("flex-1 py-2 text-sm font-medium border-b-2 -mb-px transition-colors", activePanel === "preview"
|
|
1433
1456
|
? "border-primary text-foreground"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SgDialog.d.ts","sourceRoot":"","sources":["../../src/overlay/SgDialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAC9D,MAAM,MAAM,gBAAgB,GACxB,SAAS,GACT,WAAW,GACX,SAAS,GACT,MAAM,GACN,SAAS,GACT,MAAM,GACN,QAAQ,GACR,OAAO,CAAC;AACZ,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAE5D,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAEzB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,WAAW,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAC;IACrD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAC3E,gCAAgC;IAChC,MAAM,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAC1C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC/C,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;
|
|
1
|
+
{"version":3,"file":"SgDialog.d.ts","sourceRoot":"","sources":["../../src/overlay/SgDialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAC9D,MAAM,MAAM,gBAAgB,GACxB,SAAS,GACT,WAAW,GACX,SAAS,GACT,MAAM,GACN,SAAS,GACT,MAAM,GACN,QAAQ,GACR,OAAO,CAAC;AACZ,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAE5D,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAEzB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,WAAW,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAC;IACrD,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAC3E,gCAAgC;IAChC,MAAM,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IAC1C,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC/C,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAsRF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,4BA4QtD;yBA5Qe,QAAQ"}
|
package/dist/overlay/SgDialog.js
CHANGED
|
@@ -69,6 +69,199 @@ function resolveDialogShadow(elevation, shadow) {
|
|
|
69
69
|
return elevation;
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
+
function clampByte(value) {
|
|
73
|
+
return Math.min(255, Math.max(0, Math.round(value)));
|
|
74
|
+
}
|
|
75
|
+
function parseHexColor(input) {
|
|
76
|
+
const hex = input.replace("#", "").trim();
|
|
77
|
+
if (!hex)
|
|
78
|
+
return null;
|
|
79
|
+
if (hex.length === 3 || hex.length === 4) {
|
|
80
|
+
const r = Number.parseInt((hex.slice(0, 1) || "0").repeat(2), 16);
|
|
81
|
+
const g = Number.parseInt((hex.slice(1, 2) || "0").repeat(2), 16);
|
|
82
|
+
const b = Number.parseInt((hex.slice(2, 3) || "0").repeat(2), 16);
|
|
83
|
+
if (!Number.isFinite(r) || !Number.isFinite(g) || !Number.isFinite(b))
|
|
84
|
+
return null;
|
|
85
|
+
return { r, g, b };
|
|
86
|
+
}
|
|
87
|
+
if (hex.length === 6 || hex.length === 8) {
|
|
88
|
+
const r = Number.parseInt(hex.slice(0, 2), 16);
|
|
89
|
+
const g = Number.parseInt(hex.slice(2, 4), 16);
|
|
90
|
+
const b = Number.parseInt(hex.slice(4, 6), 16);
|
|
91
|
+
if (!Number.isFinite(r) || !Number.isFinite(g) || !Number.isFinite(b))
|
|
92
|
+
return null;
|
|
93
|
+
return { r, g, b };
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
function parseRgbChannel(token) {
|
|
98
|
+
const value = token.trim();
|
|
99
|
+
if (!value)
|
|
100
|
+
return null;
|
|
101
|
+
if (value.endsWith("%")) {
|
|
102
|
+
const numeric = Number.parseFloat(value.slice(0, -1));
|
|
103
|
+
if (!Number.isFinite(numeric))
|
|
104
|
+
return null;
|
|
105
|
+
return clampByte((numeric / 100) * 255);
|
|
106
|
+
}
|
|
107
|
+
const numeric = Number.parseFloat(value);
|
|
108
|
+
if (!Number.isFinite(numeric))
|
|
109
|
+
return null;
|
|
110
|
+
return clampByte(numeric);
|
|
111
|
+
}
|
|
112
|
+
function parseRgbColor(input) {
|
|
113
|
+
const match = input.match(/^rgba?\((.+)\)$/i);
|
|
114
|
+
if (!match)
|
|
115
|
+
return null;
|
|
116
|
+
const raw = match[1]?.trim() ?? "";
|
|
117
|
+
const withoutAlpha = raw.replace(/\s*\/\s*[\d.]+%?\s*$/, "");
|
|
118
|
+
const tokens = withoutAlpha.includes(",")
|
|
119
|
+
? withoutAlpha.split(",")
|
|
120
|
+
: withoutAlpha.split(/\s+/);
|
|
121
|
+
if (tokens.length < 3)
|
|
122
|
+
return null;
|
|
123
|
+
const r = parseRgbChannel(tokens[0] ?? "");
|
|
124
|
+
const g = parseRgbChannel(tokens[1] ?? "");
|
|
125
|
+
const b = parseRgbChannel(tokens[2] ?? "");
|
|
126
|
+
if (r === null || g === null || b === null)
|
|
127
|
+
return null;
|
|
128
|
+
return { r, g, b };
|
|
129
|
+
}
|
|
130
|
+
function parseHue(token) {
|
|
131
|
+
const value = token.trim().toLowerCase();
|
|
132
|
+
if (!value)
|
|
133
|
+
return null;
|
|
134
|
+
if (value.endsWith("turn")) {
|
|
135
|
+
const numeric = Number.parseFloat(value.slice(0, -4));
|
|
136
|
+
if (!Number.isFinite(numeric))
|
|
137
|
+
return null;
|
|
138
|
+
return numeric * 360;
|
|
139
|
+
}
|
|
140
|
+
if (value.endsWith("rad")) {
|
|
141
|
+
const numeric = Number.parseFloat(value.slice(0, -3));
|
|
142
|
+
if (!Number.isFinite(numeric))
|
|
143
|
+
return null;
|
|
144
|
+
return (numeric * 180) / Math.PI;
|
|
145
|
+
}
|
|
146
|
+
if (value.endsWith("deg")) {
|
|
147
|
+
const numeric = Number.parseFloat(value.slice(0, -3));
|
|
148
|
+
if (!Number.isFinite(numeric))
|
|
149
|
+
return null;
|
|
150
|
+
return numeric;
|
|
151
|
+
}
|
|
152
|
+
const numeric = Number.parseFloat(value);
|
|
153
|
+
return Number.isFinite(numeric) ? numeric : null;
|
|
154
|
+
}
|
|
155
|
+
function parsePercent(token) {
|
|
156
|
+
const value = token.trim();
|
|
157
|
+
if (!value.endsWith("%"))
|
|
158
|
+
return null;
|
|
159
|
+
const numeric = Number.parseFloat(value.slice(0, -1));
|
|
160
|
+
if (!Number.isFinite(numeric))
|
|
161
|
+
return null;
|
|
162
|
+
return Math.min(100, Math.max(0, numeric));
|
|
163
|
+
}
|
|
164
|
+
function hslToRgb(h, s, l) {
|
|
165
|
+
const sat = Math.min(1, Math.max(0, s / 100));
|
|
166
|
+
const lig = Math.min(1, Math.max(0, l / 100));
|
|
167
|
+
const hue = ((h % 360) + 360) % 360;
|
|
168
|
+
const c = (1 - Math.abs(2 * lig - 1)) * sat;
|
|
169
|
+
const x = c * (1 - Math.abs(((hue / 60) % 2) - 1));
|
|
170
|
+
const m = lig - c / 2;
|
|
171
|
+
let r = 0;
|
|
172
|
+
let g = 0;
|
|
173
|
+
let b = 0;
|
|
174
|
+
if (hue < 60) {
|
|
175
|
+
r = c;
|
|
176
|
+
g = x;
|
|
177
|
+
}
|
|
178
|
+
else if (hue < 120) {
|
|
179
|
+
r = x;
|
|
180
|
+
g = c;
|
|
181
|
+
}
|
|
182
|
+
else if (hue < 180) {
|
|
183
|
+
g = c;
|
|
184
|
+
b = x;
|
|
185
|
+
}
|
|
186
|
+
else if (hue < 240) {
|
|
187
|
+
g = x;
|
|
188
|
+
b = c;
|
|
189
|
+
}
|
|
190
|
+
else if (hue < 300) {
|
|
191
|
+
r = x;
|
|
192
|
+
b = c;
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
r = c;
|
|
196
|
+
b = x;
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
r: clampByte((r + m) * 255),
|
|
200
|
+
g: clampByte((g + m) * 255),
|
|
201
|
+
b: clampByte((b + m) * 255)
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function parseHslColor(input) {
|
|
205
|
+
const match = input.match(/^hsla?\((.+)\)$/i);
|
|
206
|
+
if (!match)
|
|
207
|
+
return null;
|
|
208
|
+
const raw = match[1]?.trim() ?? "";
|
|
209
|
+
const withoutAlpha = raw.replace(/\s*\/\s*[\d.]+%?\s*$/, "");
|
|
210
|
+
const tokens = withoutAlpha.includes(",")
|
|
211
|
+
? withoutAlpha.split(",")
|
|
212
|
+
: withoutAlpha.split(/\s+/);
|
|
213
|
+
if (tokens.length < 3)
|
|
214
|
+
return null;
|
|
215
|
+
const h = parseHue(tokens[0] ?? "");
|
|
216
|
+
const s = parsePercent(tokens[1] ?? "");
|
|
217
|
+
const l = parsePercent(tokens[2] ?? "");
|
|
218
|
+
if (h === null || s === null || l === null)
|
|
219
|
+
return null;
|
|
220
|
+
return hslToRgb(h, s, l);
|
|
221
|
+
}
|
|
222
|
+
function parseCssColorToRgb(color) {
|
|
223
|
+
const input = color.trim();
|
|
224
|
+
if (!input)
|
|
225
|
+
return null;
|
|
226
|
+
if (input.startsWith("#"))
|
|
227
|
+
return parseHexColor(input);
|
|
228
|
+
if (/^rgba?\(/i.test(input))
|
|
229
|
+
return parseRgbColor(input);
|
|
230
|
+
if (/^hsla?\(/i.test(input))
|
|
231
|
+
return parseHslColor(input);
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
function relativeLuminance({ r, g, b }) {
|
|
235
|
+
const normalize = (channel) => {
|
|
236
|
+
const n = channel / 255;
|
|
237
|
+
return n <= 0.03928 ? n / 12.92 : ((n + 0.055) / 1.055) ** 2.4;
|
|
238
|
+
};
|
|
239
|
+
return 0.2126 * normalize(r) + 0.7152 * normalize(g) + 0.0722 * normalize(b);
|
|
240
|
+
}
|
|
241
|
+
function resolveCustomSurfacePalette(backgroundColor) {
|
|
242
|
+
if (typeof backgroundColor !== "string")
|
|
243
|
+
return null;
|
|
244
|
+
const parsed = parseCssColorToRgb(backgroundColor);
|
|
245
|
+
if (!parsed)
|
|
246
|
+
return null;
|
|
247
|
+
const lightSurface = relativeLuminance(parsed) >= 0.56;
|
|
248
|
+
if (lightSurface) {
|
|
249
|
+
return {
|
|
250
|
+
foreground: "rgb(17 24 39)",
|
|
251
|
+
mutedForeground: "rgb(71 85 105)",
|
|
252
|
+
border: "rgba(15, 23, 42, 0.16)",
|
|
253
|
+
hoverBg: "rgba(15, 23, 42, 0.08)",
|
|
254
|
+
activeBg: "rgba(15, 23, 42, 0.14)"
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
foreground: "rgb(243 244 246)",
|
|
259
|
+
mutedForeground: "rgb(203 213 225)",
|
|
260
|
+
border: "rgba(248, 250, 252, 0.18)",
|
|
261
|
+
hoverBg: "rgba(248, 250, 252, 0.08)",
|
|
262
|
+
activeBg: "rgba(248, 250, 252, 0.14)"
|
|
263
|
+
};
|
|
264
|
+
}
|
|
72
265
|
export function SgDialog(props) {
|
|
73
266
|
const { open: openProp, onOpenChange, defaultOpen = false, title, subtitle, leading, trailing, children, footer, size = "md", severity = "plain", animation = "zoom", transitionMs = 160, autoCloseMs, className, style, customColor, elevation, shadow, showTopAccent = true, overlayClassName, contentClassName, headerClassName, bodyClassName, footerClassName, closeable = true, onClose, closeOnOverlayClick = true, closeOnEsc = true, lockBodyScroll = true, initialFocusRef, restoreFocus = true, ariaLabel } = props;
|
|
74
267
|
const isControlled = openProp !== undefined;
|
|
@@ -188,13 +381,22 @@ export function SgDialog(props) {
|
|
|
188
381
|
"max-h-[85vh] flex flex-col transition duration-150 ease-out" +
|
|
189
382
|
(showTopAccent ? " border-t-4" : "");
|
|
190
383
|
const resolvedShadow = resolveDialogShadow(elevation, shadow);
|
|
384
|
+
const customPalette = resolveCustomSurfacePalette(customColor);
|
|
385
|
+
const dialogVars = {
|
|
386
|
+
"--sg-dialog-muted-foreground": customPalette?.mutedForeground ?? "hsl(var(--muted-foreground))",
|
|
387
|
+
"--sg-dialog-divider": customPalette?.border ?? "hsl(var(--border))",
|
|
388
|
+
"--sg-dialog-hover-bg": customPalette?.hoverBg ?? "hsl(var(--muted) / 0.6)",
|
|
389
|
+
"--sg-dialog-active-bg": customPalette?.activeBg ?? "hsl(var(--muted))"
|
|
390
|
+
};
|
|
191
391
|
const transitionStyle = { transitionDuration: `${transitionMs}ms` };
|
|
192
392
|
const contentStyle = {
|
|
393
|
+
...dialogVars,
|
|
193
394
|
...transitionStyle,
|
|
194
395
|
...(customColor !== undefined ? { backgroundColor: customColor } : {}),
|
|
396
|
+
...(customPalette ? { color: customPalette.foreground, borderColor: customPalette.border } : {}),
|
|
195
397
|
...(resolvedShadow !== undefined ? { boxShadow: resolvedShadow } : {})
|
|
196
398
|
};
|
|
197
|
-
return createPortal(_jsxs("div", { className: cn("fixed inset-0 z-[1000]", className), style: style, role: "dialog", "aria-modal": "true", "aria-label": a11yLabel, children: [_jsx("div", { ref: overlayRef, onMouseDown: onOverlayMouseDown, className: cn(overlayBase, overlayState, overlayClassName), style: transitionStyle }), _jsx("div", { className: "fixed inset-0 flex items-center justify-center p-4", children: _jsxs("div", { ref: contentRef, className: cn(contentBase, sizeClass(size), contentStateClass(animation, entered), showTopAccent ? severityClass(severity) : false, contentClassName), style: contentStyle, children: [(title || subtitle || closeable || leading || trailing) && (_jsxs("div", { className: cn("px-5 py-4 border-b border-
|
|
399
|
+
return createPortal(_jsxs("div", { className: cn("fixed inset-0 z-[1000]", className), style: style, role: "dialog", "aria-modal": "true", "aria-label": a11yLabel, children: [_jsx("div", { ref: overlayRef, onMouseDown: onOverlayMouseDown, className: cn(overlayBase, overlayState, overlayClassName), style: transitionStyle }), _jsx("div", { className: "fixed inset-0 flex items-center justify-center p-4", children: _jsxs("div", { ref: contentRef, className: cn(contentBase, sizeClass(size), contentStateClass(animation, entered), showTopAccent ? severityClass(severity) : false, contentClassName), style: contentStyle, children: [(title || subtitle || closeable || leading || trailing) && (_jsxs("div", { className: cn("px-5 py-4 border-b border-[var(--sg-dialog-divider)] flex items-start gap-3", headerClassName), children: [leading ? _jsx("div", { className: "shrink-0 pt-0.5", children: leading }) : null, _jsxs("div", { className: "min-w-0 flex-1", children: [title ? _jsx("div", { className: "text-base font-semibold leading-6", children: title }) : null, subtitle ? _jsx("div", { className: "mt-1 text-sm text-[var(--sg-dialog-muted-foreground)]", children: subtitle }) : null] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [trailing ? _jsx("div", { className: "shrink-0", children: trailing }) : null, closeable ? (_jsx("button", { type: "button", onClick: close, className: cn("inline-flex items-center justify-center h-9 w-9 rounded-lg", "hover:bg-[var(--sg-dialog-hover-bg)] active:bg-[var(--sg-dialog-active-bg)]", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--ring,var(--primary)))]"), "aria-label": "Close", children: _jsx(CloseIcon, {}) })) : null] })] })), _jsx("div", { className: cn("px-5 py-4 overflow-auto", bodyClassName), children: children }), footer ? (_jsx("div", { className: cn("px-5 py-4 border-t border-[var(--sg-dialog-divider)] flex items-center justify-end gap-2", footerClassName), children: footer })) : null] }) })] }), document.body);
|
|
198
400
|
}
|
|
199
401
|
function CloseIcon() {
|
|
200
402
|
return (_jsx("svg", { viewBox: "0 0 24 24", className: "size-5", "aria-hidden": "true", children: _jsx("path", { d: "M18 6L6 18M6 6l12 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }));
|