@seedgrid/fe-components 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/blocked-email-domains.json +41 -0
- package/dist/buttons/SgButton.d.ts +43 -0
- package/dist/buttons/SgButton.d.ts.map +1 -0
- package/dist/buttons/SgButton.js +123 -0
- package/dist/buttons/SgFloatActionButton.d.ts +60 -0
- package/dist/buttons/SgFloatActionButton.d.ts.map +1 -0
- package/dist/buttons/SgFloatActionButton.js +532 -0
- package/dist/buttons/SgSpeedDial.d.ts +40 -0
- package/dist/buttons/SgSpeedDial.d.ts.map +1 -0
- package/dist/buttons/SgSpeedDial.js +149 -0
- package/dist/buttons/SgSplitButton.d.ts +32 -0
- package/dist/buttons/SgSplitButton.d.ts.map +1 -0
- package/dist/buttons/SgSplitButton.js +81 -0
- package/dist/clock/SgClock.d.ts +28 -0
- package/dist/clock/SgClock.d.ts.map +1 -0
- package/dist/clock/SgClock.js +280 -0
- package/dist/clock/SgTimeProvider.d.ts +13 -0
- package/dist/clock/SgTimeProvider.d.ts.map +1 -0
- package/dist/clock/SgTimeProvider.js +44 -0
- package/dist/clock/themes/SgClockThemePicker.d.ts +14 -0
- package/dist/clock/themes/SgClockThemePicker.d.ts.map +1 -0
- package/dist/clock/themes/SgClockThemePicker.js +71 -0
- package/dist/clock/themes/SgClockThemePreview.d.ts +7 -0
- package/dist/clock/themes/SgClockThemePreview.d.ts.map +1 -0
- package/dist/clock/themes/SgClockThemePreview.js +11 -0
- package/dist/clock/themes/builtins.d.ts +3 -0
- package/dist/clock/themes/builtins.d.ts.map +1 -0
- package/dist/clock/themes/builtins.js +241 -0
- package/dist/clock/themes/index.d.ts +9 -0
- package/dist/clock/themes/index.d.ts.map +1 -0
- package/dist/clock/themes/index.js +7 -0
- package/dist/clock/themes/provider.d.ts +19 -0
- package/dist/clock/themes/provider.d.ts.map +1 -0
- package/dist/clock/themes/provider.js +54 -0
- package/dist/clock/themes/registry.d.ts +9 -0
- package/dist/clock/themes/registry.d.ts.map +1 -0
- package/dist/clock/themes/registry.js +25 -0
- package/dist/clock/themes/renderTheme.d.ts +7 -0
- package/dist/clock/themes/renderTheme.d.ts.map +1 -0
- package/dist/clock/themes/renderTheme.js +41 -0
- package/dist/clock/themes/types.d.ts +21 -0
- package/dist/clock/themes/types.d.ts.map +1 -0
- package/dist/clock/themes/types.js +1 -0
- package/dist/clock/themes/urlThemeCache.d.ts +2 -0
- package/dist/clock/themes/urlThemeCache.d.ts.map +1 -0
- package/dist/clock/themes/urlThemeCache.js +11 -0
- package/dist/clock/themes/useDarkFlag.d.ts +2 -0
- package/dist/clock/themes/useDarkFlag.d.ts.map +1 -0
- package/dist/clock/themes/useDarkFlag.js +14 -0
- package/dist/commons/SgBadge.d.ts +51 -0
- package/dist/commons/SgBadge.d.ts.map +1 -0
- package/dist/commons/SgBadge.js +141 -0
- package/dist/commons/SgBadgeOverlay.d.ts +13 -0
- package/dist/commons/SgBadgeOverlay.d.ts.map +1 -0
- package/dist/commons/SgBadgeOverlay.js +20 -0
- package/dist/commons/SgButton.d.ts +39 -0
- package/dist/commons/SgButton.d.ts.map +1 -0
- package/dist/commons/SgButton.js +116 -0
- package/dist/commons/SgPopup.d.ts +42 -0
- package/dist/commons/SgPopup.d.ts.map +1 -0
- package/dist/commons/SgPopup.js +218 -0
- package/dist/commons/SgToast.d.ts +44 -0
- package/dist/commons/SgToast.d.ts.map +1 -0
- package/dist/commons/SgToast.js +97 -0
- package/dist/commons/SgToaster.d.ts +11 -0
- package/dist/commons/SgToaster.d.ts.map +1 -0
- package/dist/commons/SgToaster.js +85 -0
- package/dist/commons/common-passwords.d.ts +2 -0
- package/dist/commons/common-passwords.d.ts.map +1 -0
- package/dist/commons/common-passwords.js +167 -0
- package/dist/environment/SgEnvironmentProvider.d.ts +31 -0
- package/dist/environment/SgEnvironmentProvider.d.ts.map +1 -0
- package/dist/environment/SgEnvironmentProvider.js +120 -0
- package/dist/environment/persistence.d.ts +44 -0
- package/dist/environment/persistence.d.ts.map +1 -0
- package/dist/environment/persistence.js +149 -0
- package/dist/gadgets/clock/SgClock.d.ts +18 -0
- package/dist/gadgets/clock/SgClock.d.ts.map +1 -0
- package/dist/gadgets/clock/SgClock.js +407 -0
- package/dist/gadgets/clock/SgTimeProvider.d.ts +13 -0
- package/dist/gadgets/clock/SgTimeProvider.d.ts.map +1 -0
- package/dist/gadgets/clock/SgTimeProvider.js +44 -0
- package/dist/gadgets/clock/themes/SgClockThemePicker.d.ts +14 -0
- package/dist/gadgets/clock/themes/SgClockThemePicker.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/SgClockThemePicker.js +71 -0
- package/dist/gadgets/clock/themes/SgClockThemePreview.d.ts +7 -0
- package/dist/gadgets/clock/themes/SgClockThemePreview.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/SgClockThemePreview.js +11 -0
- package/dist/gadgets/clock/themes/builtins.d.ts +3 -0
- package/dist/gadgets/clock/themes/builtins.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/builtins.js +241 -0
- package/dist/gadgets/clock/themes/index.d.ts +9 -0
- package/dist/gadgets/clock/themes/index.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/index.js +7 -0
- package/dist/gadgets/clock/themes/provider.d.ts +19 -0
- package/dist/gadgets/clock/themes/provider.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/provider.js +54 -0
- package/dist/gadgets/clock/themes/registry.d.ts +9 -0
- package/dist/gadgets/clock/themes/registry.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/registry.js +25 -0
- package/dist/gadgets/clock/themes/renderTheme.d.ts +7 -0
- package/dist/gadgets/clock/themes/renderTheme.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/renderTheme.js +41 -0
- package/dist/gadgets/clock/themes/types.d.ts +21 -0
- package/dist/gadgets/clock/themes/types.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/types.js +1 -0
- package/dist/gadgets/clock/themes/urlThemeCache.d.ts +2 -0
- package/dist/gadgets/clock/themes/urlThemeCache.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/urlThemeCache.js +11 -0
- package/dist/gadgets/clock/themes/useDarkFlag.d.ts +2 -0
- package/dist/gadgets/clock/themes/useDarkFlag.d.ts.map +1 -0
- package/dist/gadgets/clock/themes/useDarkFlag.js +14 -0
- package/dist/gadgets/flip-digit/SgFlipDigit.d.ts +23 -0
- package/dist/gadgets/flip-digit/SgFlipDigit.d.ts.map +1 -0
- package/dist/gadgets/flip-digit/SgFlipDigit.js +118 -0
- package/dist/gadgets/flip-digit/index.d.ts +3 -0
- package/dist/gadgets/flip-digit/index.d.ts.map +1 -0
- package/dist/gadgets/flip-digit/index.js +1 -0
- package/dist/i18n/en-US.json +76 -0
- package/dist/i18n/es.json +76 -0
- package/dist/i18n/index.d.ts +328 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +87 -0
- package/dist/i18n/pt-BR.json +76 -0
- package/dist/i18n/pt-PT.json +76 -0
- package/dist/index.d.ts +88 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/inputs/FloatingInput.d.ts +13 -0
- package/dist/inputs/FloatingInput.d.ts.map +1 -0
- package/dist/inputs/FloatingInput.js +53 -0
- package/dist/inputs/FloatingSelect.d.ts +15 -0
- package/dist/inputs/FloatingSelect.d.ts.map +1 -0
- package/dist/inputs/FloatingSelect.js +52 -0
- package/dist/inputs/FloatingTextArea.d.ts +11 -0
- package/dist/inputs/FloatingTextArea.d.ts.map +1 -0
- package/dist/inputs/FloatingTextArea.js +34 -0
- package/dist/inputs/InputBirthDate.d.ts +13 -0
- package/dist/inputs/InputBirthDate.d.ts.map +1 -0
- package/dist/inputs/InputBirthDate.js +46 -0
- package/dist/inputs/InputDate.d.ts +8 -0
- package/dist/inputs/InputDate.d.ts.map +1 -0
- package/dist/inputs/InputDate.js +23 -0
- package/dist/inputs/InputEmail.d.ts +14 -0
- package/dist/inputs/InputEmail.d.ts.map +1 -0
- package/dist/inputs/InputEmail.js +43 -0
- package/dist/inputs/InputPassword.d.ts +12 -0
- package/dist/inputs/InputPassword.d.ts.map +1 -0
- package/dist/inputs/InputPassword.js +42 -0
- package/dist/inputs/MaskedInputs.d.ts +27 -0
- package/dist/inputs/MaskedInputs.d.ts.map +1 -0
- package/dist/inputs/MaskedInputs.js +161 -0
- package/dist/inputs/SgAutocomplete.d.ts +42 -0
- package/dist/inputs/SgAutocomplete.d.ts.map +1 -0
- package/dist/inputs/SgAutocomplete.js +241 -0
- package/dist/inputs/SgCurrencyEdit.d.ts +56 -0
- package/dist/inputs/SgCurrencyEdit.d.ts.map +1 -0
- package/dist/inputs/SgCurrencyEdit.js +496 -0
- package/dist/inputs/SgInputBirthDate.d.ts +13 -0
- package/dist/inputs/SgInputBirthDate.d.ts.map +1 -0
- package/dist/inputs/SgInputBirthDate.js +48 -0
- package/dist/inputs/SgInputCEP.d.ts +33 -0
- package/dist/inputs/SgInputCEP.d.ts.map +1 -0
- package/dist/inputs/SgInputCEP.js +117 -0
- package/dist/inputs/SgInputCNPJ.d.ts +20 -0
- package/dist/inputs/SgInputCNPJ.d.ts.map +1 -0
- package/dist/inputs/SgInputCNPJ.js +133 -0
- package/dist/inputs/SgInputCPF.d.ts +15 -0
- package/dist/inputs/SgInputCPF.d.ts.map +1 -0
- package/dist/inputs/SgInputCPF.js +70 -0
- package/dist/inputs/SgInputCPFCNPJ.d.ts +15 -0
- package/dist/inputs/SgInputCPFCNPJ.d.ts.map +1 -0
- package/dist/inputs/SgInputCPFCNPJ.js +92 -0
- package/dist/inputs/SgInputDate.d.ts +8 -0
- package/dist/inputs/SgInputDate.d.ts.map +1 -0
- package/dist/inputs/SgInputDate.js +120 -0
- package/dist/inputs/SgInputEmail.d.ts +16 -0
- package/dist/inputs/SgInputEmail.d.ts.map +1 -0
- package/dist/inputs/SgInputEmail.js +74 -0
- package/dist/inputs/SgInputFone.d.ts +15 -0
- package/dist/inputs/SgInputFone.d.ts.map +1 -0
- package/dist/inputs/SgInputFone.js +60 -0
- package/dist/inputs/SgInputMasked.d.ts +27 -0
- package/dist/inputs/SgInputMasked.d.ts.map +1 -0
- package/dist/inputs/SgInputMasked.js +161 -0
- package/dist/inputs/SgInputNumber.d.ts +49 -0
- package/dist/inputs/SgInputNumber.d.ts.map +1 -0
- package/dist/inputs/SgInputNumber.js +438 -0
- package/dist/inputs/SgInputPassword.d.ts +26 -0
- package/dist/inputs/SgInputPassword.d.ts.map +1 -0
- package/dist/inputs/SgInputPassword.js +278 -0
- package/dist/inputs/SgInputPhone.d.ts +15 -0
- package/dist/inputs/SgInputPhone.d.ts.map +1 -0
- package/dist/inputs/SgInputPhone.js +66 -0
- package/dist/inputs/SgInputPostalCode.d.ts +37 -0
- package/dist/inputs/SgInputPostalCode.d.ts.map +1 -0
- package/dist/inputs/SgInputPostalCode.js +193 -0
- package/dist/inputs/SgInputSelect.d.ts +16 -0
- package/dist/inputs/SgInputSelect.d.ts.map +1 -0
- package/dist/inputs/SgInputSelect.js +104 -0
- package/dist/inputs/SgInputText.d.ts +49 -0
- package/dist/inputs/SgInputText.d.ts.map +1 -0
- package/dist/inputs/SgInputText.js +336 -0
- package/dist/inputs/SgInputTextArea.d.ts +41 -0
- package/dist/inputs/SgInputTextArea.d.ts.map +1 -0
- package/dist/inputs/SgInputTextArea.js +216 -0
- package/dist/inputs/SgTextEditor.d.ts +27 -0
- package/dist/inputs/SgTextEditor.d.ts.map +1 -0
- package/dist/inputs/SgTextEditor.js +201 -0
- package/dist/integration/module.d.ts +39 -0
- package/dist/integration/module.d.ts.map +1 -0
- package/dist/integration/module.js +1 -0
- package/dist/layout/GroupBox.d.ts +10 -0
- package/dist/layout/GroupBox.d.ts.map +1 -0
- package/dist/layout/GroupBox.js +14 -0
- package/dist/layout/SgCard.d.ts +35 -0
- package/dist/layout/SgCard.d.ts.map +1 -0
- package/dist/layout/SgCard.js +106 -0
- package/dist/layout/SgDockLayout.d.ts +37 -0
- package/dist/layout/SgDockLayout.d.ts.map +1 -0
- package/dist/layout/SgDockLayout.js +101 -0
- package/dist/layout/SgDockZone.d.ts +12 -0
- package/dist/layout/SgDockZone.d.ts.map +1 -0
- package/dist/layout/SgDockZone.js +20 -0
- package/dist/layout/SgGrid.d.ts +18 -0
- package/dist/layout/SgGrid.d.ts.map +1 -0
- package/dist/layout/SgGrid.js +101 -0
- package/dist/layout/SgGroupBox.d.ts +10 -0
- package/dist/layout/SgGroupBox.d.ts.map +1 -0
- package/dist/layout/SgGroupBox.js +14 -0
- package/dist/layout/SgMainPanel.d.ts +11 -0
- package/dist/layout/SgMainPanel.d.ts.map +1 -0
- package/dist/layout/SgMainPanel.js +70 -0
- package/dist/layout/SgPanel.d.ts +22 -0
- package/dist/layout/SgPanel.d.ts.map +1 -0
- package/dist/layout/SgPanel.js +33 -0
- package/dist/layout/SgScreen.d.ts +11 -0
- package/dist/layout/SgScreen.d.ts.map +1 -0
- package/dist/layout/SgScreen.js +18 -0
- package/dist/layout/SgStack.d.ts +15 -0
- package/dist/layout/SgStack.d.ts.map +1 -0
- package/dist/layout/SgStack.js +32 -0
- package/dist/layout/SgToolBar.d.ts +46 -0
- package/dist/layout/SgToolBar.d.ts.map +1 -0
- package/dist/layout/SgToolBar.js +199 -0
- package/dist/layout/SgTreeView.d.ts +80 -0
- package/dist/layout/SgTreeView.d.ts.map +1 -0
- package/dist/layout/SgTreeView.js +338 -0
- package/dist/manifest.d.ts +3 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +19 -0
- package/dist/masks.d.ts +14 -0
- package/dist/masks.d.ts.map +1 -0
- package/dist/masks.js +91 -0
- package/dist/overlay/SgDialog.d.ts +39 -0
- package/dist/overlay/SgDialog.d.ts.map +1 -0
- package/dist/overlay/SgDialog.js +177 -0
- package/dist/overlay/SgPopup.d.ts +42 -0
- package/dist/overlay/SgPopup.d.ts.map +1 -0
- package/dist/overlay/SgPopup.js +218 -0
- package/dist/rhf.d.ts +6 -0
- package/dist/rhf.d.ts.map +1 -0
- package/dist/rhf.js +1 -0
- package/dist/validators.d.ts +27 -0
- package/dist/validators.d.ts.map +1 -0
- package/dist/validators.js +218 -0
- package/dist/wizard/SGWizard.d.ts +28 -0
- package/dist/wizard/SGWizard.d.ts.map +1 -0
- package/dist/wizard/SGWizard.js +124 -0
- package/package.json +53 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
function cn(...parts) {
|
|
5
|
+
return parts.filter(Boolean).join(" ");
|
|
6
|
+
}
|
|
7
|
+
function DefaultCaret({ open }) {
|
|
8
|
+
return (_jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", className: cn("shrink-0 transition-transform duration-200", open ? "rotate-90" : "rotate-0"), "aria-hidden": "true", children: _jsx("path", { fill: "currentColor", d: "M9.29 6.71a1 1 0 0 0 0 1.41L13.17 12l-3.88 3.88a1 1 0 1 0 1.41 1.41l4.59-4.59a1 1 0 0 0 0-1.41L10.7 6.7a1 1 0 0 0-1.41.01Z" }) }));
|
|
9
|
+
}
|
|
10
|
+
export function SgCard(props) {
|
|
11
|
+
const { className, headerClassName, bodyClassName, footerClassName, variant = "default", size = "md", leading, trailing, trailer, title, description, actions, header, footer, clickable = false, disabled = false, collapsible = false, defaultOpen = true, open: controlledOpen, onOpenChange, collapseIcon, collapseToggleAlign = "left", toggleOnHeaderClick = true, onClick, children, ...rest } = props;
|
|
12
|
+
const isInteractive = (clickable || typeof onClick === "function") && !collapsible;
|
|
13
|
+
const trailingNode = trailing ?? trailer;
|
|
14
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);
|
|
15
|
+
const isControlled = typeof controlledOpen === "boolean";
|
|
16
|
+
const isOpen = collapsible ? (isControlled ? controlledOpen : uncontrolledOpen) : true;
|
|
17
|
+
const setOpen = React.useCallback((next) => {
|
|
18
|
+
if (!collapsible)
|
|
19
|
+
return;
|
|
20
|
+
if (!isControlled)
|
|
21
|
+
setUncontrolledOpen(next);
|
|
22
|
+
onOpenChange?.(next);
|
|
23
|
+
}, [collapsible, isControlled, onOpenChange]);
|
|
24
|
+
const sizeClasses = size === "sm"
|
|
25
|
+
? {
|
|
26
|
+
root: "rounded-xl",
|
|
27
|
+
header: "px-3 py-2",
|
|
28
|
+
body: "px-3 py-3",
|
|
29
|
+
footer: "px-3 py-2",
|
|
30
|
+
title: "text-sm",
|
|
31
|
+
desc: "text-xs"
|
|
32
|
+
}
|
|
33
|
+
: size === "lg"
|
|
34
|
+
? {
|
|
35
|
+
root: "rounded-2xl",
|
|
36
|
+
header: "px-6 py-4",
|
|
37
|
+
body: "px-6 py-6",
|
|
38
|
+
footer: "px-6 py-4",
|
|
39
|
+
title: "text-base",
|
|
40
|
+
desc: "text-sm"
|
|
41
|
+
}
|
|
42
|
+
: {
|
|
43
|
+
root: "rounded-2xl",
|
|
44
|
+
header: "px-4 py-3",
|
|
45
|
+
body: "px-4 py-4",
|
|
46
|
+
footer: "px-4 py-3",
|
|
47
|
+
title: "text-sm",
|
|
48
|
+
desc: "text-xs"
|
|
49
|
+
};
|
|
50
|
+
const variantClasses = variant === "flat"
|
|
51
|
+
? "bg-background border border-border/60 shadow-none"
|
|
52
|
+
: variant === "outlined"
|
|
53
|
+
? "bg-background border border-border shadow-none"
|
|
54
|
+
: variant === "elevated"
|
|
55
|
+
? "bg-background border border-border shadow-md"
|
|
56
|
+
: "bg-background border border-border shadow-sm";
|
|
57
|
+
const interactiveClasses = isInteractive
|
|
58
|
+
? cn("transition-[box-shadow,transform] duration-150", "hover:shadow-md", "focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-[hsl(var(--primary)/0.35)]", disabled ? "" : "cursor-pointer", disabled ? "" : "active:translate-y-[0.5px]")
|
|
59
|
+
: "";
|
|
60
|
+
const disabledClasses = disabled ? "opacity-60 pointer-events-none select-none" : "";
|
|
61
|
+
const rootClasses = cn("w-full", sizeClasses.root, variantClasses, interactiveClasses, disabledClasses, className);
|
|
62
|
+
const toggle = React.useCallback(() => setOpen(!isOpen), [isOpen, setOpen]);
|
|
63
|
+
const onHeaderClick = () => {
|
|
64
|
+
if (!collapsible)
|
|
65
|
+
return;
|
|
66
|
+
if (!toggleOnHeaderClick)
|
|
67
|
+
return;
|
|
68
|
+
if (disabled)
|
|
69
|
+
return;
|
|
70
|
+
toggle();
|
|
71
|
+
};
|
|
72
|
+
const ToggleButton = collapsible ? (_jsx("button", { type: "button", onClick: (e) => {
|
|
73
|
+
e.stopPropagation();
|
|
74
|
+
toggle();
|
|
75
|
+
}, className: cn("inline-flex h-8 w-8 items-center justify-center rounded-md", "text-muted-foreground hover:text-foreground", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--primary)/0.35)]"), "aria-label": isOpen ? "Recolher" : "Expandir", "aria-expanded": isOpen, disabled: disabled, children: collapseIcon ?? _jsx(DefaultCaret, { open: isOpen }) })) : null;
|
|
76
|
+
const headerHasContent = Boolean(header) ||
|
|
77
|
+
Boolean(leading) ||
|
|
78
|
+
Boolean(title) ||
|
|
79
|
+
Boolean(description) ||
|
|
80
|
+
Boolean(trailingNode) ||
|
|
81
|
+
Boolean(actions) ||
|
|
82
|
+
collapsible;
|
|
83
|
+
const renderDefaultHeader = headerHasContent ? (_jsxs("div", { className: cn("flex items-start gap-3", "border-b border-border/60", sizeClasses.header, headerClassName, collapsible && toggleOnHeaderClick ? "cursor-pointer" : ""), onClick: onHeaderClick, role: collapsible && toggleOnHeaderClick ? "button" : undefined, tabIndex: collapsible && toggleOnHeaderClick && !disabled ? 0 : undefined, onKeyDown: (e) => {
|
|
84
|
+
if (!collapsible || !toggleOnHeaderClick || disabled)
|
|
85
|
+
return;
|
|
86
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
87
|
+
e.preventDefault();
|
|
88
|
+
toggle();
|
|
89
|
+
}
|
|
90
|
+
}, "aria-expanded": collapsible ? isOpen : undefined, children: [collapseToggleAlign === "left" ? ToggleButton : null, 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: cn("font-medium text-foreground", sizeClasses.title), children: title })) : null, description ? (_jsx("div", { className: cn("mt-0.5 text-muted-foreground", sizeClasses.desc), children: description })) : null] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [trailingNode ? _jsx("div", { className: "shrink-0", children: trailingNode }) : null, actions ? _jsx("div", { className: "shrink-0", children: actions }) : null, collapseToggleAlign === "right" ? ToggleButton : null] })] })) : null;
|
|
91
|
+
const headerNode = header ? (_jsx("div", { className: cn("border-b border-border/60", sizeClasses.header, headerClassName, collapsible && toggleOnHeaderClick ? "cursor-pointer" : ""), onClick: onHeaderClick, role: collapsible && toggleOnHeaderClick ? "button" : undefined, tabIndex: collapsible && toggleOnHeaderClick && !disabled ? 0 : undefined, onKeyDown: (e) => {
|
|
92
|
+
if (!collapsible || !toggleOnHeaderClick || disabled)
|
|
93
|
+
return;
|
|
94
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
95
|
+
e.preventDefault();
|
|
96
|
+
toggle();
|
|
97
|
+
}
|
|
98
|
+
}, "aria-expanded": collapsible ? isOpen : undefined, children: header })) : (renderDefaultHeader);
|
|
99
|
+
const collapsibleBodyWrapper = collapsible ? (_jsx("div", { className: cn("grid transition-all duration-200 ease-out motion-reduce:transition-none", isOpen ? "grid-rows-[1fr] opacity-100" : "grid-rows-[0fr] opacity-0"), children: _jsxs("div", { className: "overflow-hidden", children: [_jsx("div", { className: cn(sizeClasses.body, bodyClassName), children: children }), footer ? (_jsx("div", { className: cn("border-t border-border/60", sizeClasses.footer, footerClassName), children: footer })) : null] }) })) : null;
|
|
100
|
+
const bodyNode = !collapsible ? _jsx("div", { className: cn(sizeClasses.body, bodyClassName), children: children }) : null;
|
|
101
|
+
const footerNode = !collapsible && footer ? (_jsx("div", { className: cn("border-t border-border/60", sizeClasses.footer, footerClassName), children: footer })) : null;
|
|
102
|
+
const Component = isInteractive ? "button" : "section";
|
|
103
|
+
const buttonLikeProps = isInteractive ? { type: "button", onClick: disabled ? undefined : onClick, disabled } : {};
|
|
104
|
+
return (_jsxs(Component, { className: rootClasses, ...buttonLikeProps, ...rest, children: [headerNode, collapsible ? collapsibleBodyWrapper : null, !collapsible ? bodyNode : null, !collapsible ? footerNode : null] }));
|
|
105
|
+
}
|
|
106
|
+
SgCard.displayName = "SgCard";
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type SgDockZoneId = "top" | "bottom" | "left" | "right" | "free";
|
|
3
|
+
export type SgDockToolbarState = {
|
|
4
|
+
id: string;
|
|
5
|
+
zone: SgDockZoneId;
|
|
6
|
+
collapsed?: boolean;
|
|
7
|
+
orientation?: "horizontal" | "vertical";
|
|
8
|
+
order?: number;
|
|
9
|
+
};
|
|
10
|
+
export type SgDockLayoutState = {
|
|
11
|
+
version: 1;
|
|
12
|
+
toolbars: Record<string, SgDockToolbarState>;
|
|
13
|
+
};
|
|
14
|
+
export type SgDockLayoutProps = {
|
|
15
|
+
id: string;
|
|
16
|
+
className?: string;
|
|
17
|
+
children: React.ReactNode;
|
|
18
|
+
defaultState?: SgDockLayoutState;
|
|
19
|
+
};
|
|
20
|
+
type DockContextValue = {
|
|
21
|
+
layoutId: string;
|
|
22
|
+
getZoneElement: (zone: SgDockZoneId) => HTMLDivElement | null;
|
|
23
|
+
registerZone: (zone: SgDockZoneId, el: HTMLDivElement | null) => void;
|
|
24
|
+
getZoneAtPoint: (x: number, y: number) => SgDockZoneId | null;
|
|
25
|
+
getToolbarZone: (id: string) => SgDockZoneId | null;
|
|
26
|
+
moveToolbar: (id: string, zone: SgDockZoneId) => void;
|
|
27
|
+
ensureToolbar: (id: string, state: Partial<SgDockToolbarState>) => void;
|
|
28
|
+
getToolbarCollapsed: (id: string) => boolean | undefined;
|
|
29
|
+
setToolbarCollapsed: (id: string, next: boolean) => void;
|
|
30
|
+
};
|
|
31
|
+
export declare function useSgDockLayout(): DockContextValue | null;
|
|
32
|
+
export declare function SgDockLayout(props: Readonly<SgDockLayoutProps>): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
export declare namespace SgDockLayout {
|
|
34
|
+
var displayName: string;
|
|
35
|
+
}
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=SgDockLayout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgDockLayout.d.ts","sourceRoot":"","sources":["../../src/layout/SgDockLayout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAExE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,YAAY,CAAC,EAAE,iBAAiB,CAAC;CAClC,CAAC;AAIF,KAAK,gBAAgB,GAAG;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,cAAc,GAAG,IAAI,CAAC;IAC9D,YAAY,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC;IACtE,cAAc,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,YAAY,GAAG,IAAI,CAAC;IAC9D,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,YAAY,GAAG,IAAI,CAAC;IACpD,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACtD,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,kBAAkB,CAAC,KAAK,IAAI,CAAC;IACxE,mBAAmB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,GAAG,SAAS,CAAC;IACzD,mBAAmB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1D,CAAC;AAIF,wBAAgB,eAAe,4BAE9B;AAID,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,iBAAiB,CAAC,2CAqH9D;yBArHe,YAAY"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { useSgPersistentState } from "../environment/SgEnvironmentProvider";
|
|
5
|
+
const DockContext = React.createContext(null);
|
|
6
|
+
export function useSgDockLayout() {
|
|
7
|
+
return React.useContext(DockContext);
|
|
8
|
+
}
|
|
9
|
+
const EMPTY_STATE = { version: 1, toolbars: {} };
|
|
10
|
+
export function SgDockLayout(props) {
|
|
11
|
+
const { id, className, children, defaultState } = props;
|
|
12
|
+
const { value: persisted, setValue } = useSgPersistentState({
|
|
13
|
+
baseKey: `dock-layout:${id}`,
|
|
14
|
+
defaultValue: defaultState ?? EMPTY_STATE
|
|
15
|
+
});
|
|
16
|
+
const zonesRef = React.useRef(new Map());
|
|
17
|
+
const registerZone = React.useCallback((zone, el) => {
|
|
18
|
+
if (!el) {
|
|
19
|
+
zonesRef.current.delete(zone);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
zonesRef.current.set(zone, el);
|
|
23
|
+
}, []);
|
|
24
|
+
const getZoneElement = React.useCallback((zone) => {
|
|
25
|
+
return zonesRef.current.get(zone) ?? null;
|
|
26
|
+
}, []);
|
|
27
|
+
const getZoneAtPoint = React.useCallback((x, y) => {
|
|
28
|
+
for (const [zone, el] of zonesRef.current.entries()) {
|
|
29
|
+
const rect = el.getBoundingClientRect();
|
|
30
|
+
if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
|
|
31
|
+
return zone;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}, []);
|
|
36
|
+
const getToolbarZone = React.useCallback((toolbarId) => persisted.toolbars[toolbarId]?.zone ?? null, [persisted]);
|
|
37
|
+
const ensureToolbar = React.useCallback((toolbarId, state) => {
|
|
38
|
+
setValue((prev) => {
|
|
39
|
+
if (prev.toolbars[toolbarId])
|
|
40
|
+
return prev;
|
|
41
|
+
return {
|
|
42
|
+
...prev,
|
|
43
|
+
toolbars: {
|
|
44
|
+
...prev.toolbars,
|
|
45
|
+
[toolbarId]: {
|
|
46
|
+
id: toolbarId,
|
|
47
|
+
zone: state.zone ?? "free",
|
|
48
|
+
collapsed: state.collapsed ?? false,
|
|
49
|
+
orientation: state.orientation,
|
|
50
|
+
order: state.order ?? Object.keys(prev.toolbars).length
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
}, [setValue]);
|
|
56
|
+
const moveToolbar = React.useCallback((toolbarId, zone) => {
|
|
57
|
+
setValue((prev) => {
|
|
58
|
+
const current = prev.toolbars[toolbarId];
|
|
59
|
+
if (!current)
|
|
60
|
+
return prev;
|
|
61
|
+
return {
|
|
62
|
+
...prev,
|
|
63
|
+
toolbars: {
|
|
64
|
+
...prev.toolbars,
|
|
65
|
+
[toolbarId]: {
|
|
66
|
+
...current,
|
|
67
|
+
zone
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
}, [setValue]);
|
|
73
|
+
const getToolbarCollapsed = React.useCallback((toolbarId) => persisted.toolbars[toolbarId]?.collapsed, [persisted]);
|
|
74
|
+
const setToolbarCollapsed = React.useCallback((toolbarId, next) => {
|
|
75
|
+
setValue((prev) => {
|
|
76
|
+
const current = prev.toolbars[toolbarId];
|
|
77
|
+
if (!current)
|
|
78
|
+
return prev;
|
|
79
|
+
return {
|
|
80
|
+
...prev,
|
|
81
|
+
toolbars: {
|
|
82
|
+
...prev.toolbars,
|
|
83
|
+
[toolbarId]: { ...current, collapsed: next }
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
}, [setValue]);
|
|
88
|
+
const ctx = {
|
|
89
|
+
layoutId: id,
|
|
90
|
+
getZoneElement,
|
|
91
|
+
registerZone,
|
|
92
|
+
getZoneAtPoint,
|
|
93
|
+
getToolbarZone,
|
|
94
|
+
moveToolbar,
|
|
95
|
+
ensureToolbar,
|
|
96
|
+
getToolbarCollapsed,
|
|
97
|
+
setToolbarCollapsed
|
|
98
|
+
};
|
|
99
|
+
return (_jsx(DockContext.Provider, { value: ctx, children: _jsx("div", { className: className, children: children }) }));
|
|
100
|
+
}
|
|
101
|
+
SgDockLayout.displayName = "SgDockLayout";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type SgDockZoneId } from "./SgDockLayout";
|
|
3
|
+
export type SgDockZoneProps = {
|
|
4
|
+
zone: SgDockZoneId;
|
|
5
|
+
className?: string;
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
};
|
|
8
|
+
export declare function SgDockZone(props: Readonly<SgDockZoneProps>): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export declare namespace SgDockZone {
|
|
10
|
+
var displayName: string;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=SgDockZone.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgDockZone.d.ts","sourceRoot":"","sources":["../../src/layout/SgDockZone.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEpE,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAMF,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAC,2CAwB1D;yBAxBe,UAAU"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { useSgDockLayout } from "./SgDockLayout";
|
|
5
|
+
function cn(...parts) {
|
|
6
|
+
return parts.filter(Boolean).join(" ");
|
|
7
|
+
}
|
|
8
|
+
export function SgDockZone(props) {
|
|
9
|
+
const { zone, className, children } = props;
|
|
10
|
+
const dock = useSgDockLayout();
|
|
11
|
+
const ref = React.useRef(null);
|
|
12
|
+
React.useEffect(() => {
|
|
13
|
+
if (!dock)
|
|
14
|
+
return;
|
|
15
|
+
dock.registerZone(zone, ref.current);
|
|
16
|
+
return () => dock.registerZone(zone, null);
|
|
17
|
+
}, [dock, zone]);
|
|
18
|
+
return (_jsx("div", { ref: ref, "data-sg-dock-zone": zone, className: cn("relative flex gap-3 p-3", zone === "top" || zone === "bottom" ? "flex-row items-center" : "flex-col items-center", className), children: children }));
|
|
19
|
+
}
|
|
20
|
+
SgDockZone.displayName = "SgDockZone";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type SgGridColumns = number | Partial<Record<"base" | "sm" | "md" | "lg" | "xl" | "2xl", number>>;
|
|
3
|
+
export type SgGridProps = Omit<React.HTMLAttributes<HTMLDivElement>, "align" | "children"> & {
|
|
4
|
+
columns?: SgGridColumns;
|
|
5
|
+
minItemWidth?: number | string;
|
|
6
|
+
gap?: number | string;
|
|
7
|
+
padding?: number | string;
|
|
8
|
+
dense?: boolean;
|
|
9
|
+
rowHeight?: number | string;
|
|
10
|
+
justify?: "start" | "center" | "end" | "stretch" | "between" | "around" | "evenly";
|
|
11
|
+
align?: "start" | "center" | "end" | "stretch";
|
|
12
|
+
children?: React.ReactNode;
|
|
13
|
+
};
|
|
14
|
+
export declare function SgGrid(props: Readonly<SgGridProps>): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export declare namespace SgGrid {
|
|
16
|
+
var displayName: string;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=SgGrid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgGrid.d.ts","sourceRoot":"","sources":["../../src/layout/SgGrid.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;AAExE,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG;IAC3F,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACnF,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAyCF,wBAAgB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,2CA4FlD;yBA5Fe,MAAM"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
function cn(...parts) {
|
|
5
|
+
return parts.filter(Boolean).join(" ");
|
|
6
|
+
}
|
|
7
|
+
function toCssSpace(value) {
|
|
8
|
+
if (value === undefined || value === null)
|
|
9
|
+
return undefined;
|
|
10
|
+
return typeof value === "number" ? `${value}px` : value;
|
|
11
|
+
}
|
|
12
|
+
const BREAKPOINTS = {
|
|
13
|
+
sm: 640,
|
|
14
|
+
md: 768,
|
|
15
|
+
lg: 1024,
|
|
16
|
+
xl: 1280,
|
|
17
|
+
"2xl": 1536
|
|
18
|
+
};
|
|
19
|
+
function normalizeColumns(columns) {
|
|
20
|
+
if (!columns)
|
|
21
|
+
return { base: 1 };
|
|
22
|
+
if (typeof columns === "number")
|
|
23
|
+
return { base: columns };
|
|
24
|
+
return { base: columns.base ?? 1, ...columns };
|
|
25
|
+
}
|
|
26
|
+
function justifyToCss(value) {
|
|
27
|
+
if (!value)
|
|
28
|
+
return undefined;
|
|
29
|
+
const map = {
|
|
30
|
+
start: "start",
|
|
31
|
+
center: "center",
|
|
32
|
+
end: "end",
|
|
33
|
+
stretch: "stretch",
|
|
34
|
+
between: "space-between",
|
|
35
|
+
around: "space-around",
|
|
36
|
+
evenly: "space-evenly"
|
|
37
|
+
};
|
|
38
|
+
return map[value];
|
|
39
|
+
}
|
|
40
|
+
function alignToCss(value) {
|
|
41
|
+
if (!value)
|
|
42
|
+
return undefined;
|
|
43
|
+
const map = {
|
|
44
|
+
start: "start",
|
|
45
|
+
center: "center",
|
|
46
|
+
end: "end",
|
|
47
|
+
stretch: "stretch"
|
|
48
|
+
};
|
|
49
|
+
return map[value];
|
|
50
|
+
}
|
|
51
|
+
export function SgGrid(props) {
|
|
52
|
+
const { columns, minItemWidth, gap = 0, padding, dense = false, rowHeight, justify, align, className, style, children, ...rest } = props;
|
|
53
|
+
const instanceId = React.useId().replace(/:/g, "");
|
|
54
|
+
const normalized = normalizeColumns(columns);
|
|
55
|
+
const dynamicCss = React.useMemo(() => {
|
|
56
|
+
if (minItemWidth)
|
|
57
|
+
return "";
|
|
58
|
+
const rules = [];
|
|
59
|
+
rules.push(`[data-sg-grid="${instanceId}"]{--sg-grid-cols:${normalized.base};}`);
|
|
60
|
+
Object.keys(BREAKPOINTS).forEach((bp) => {
|
|
61
|
+
const next = normalized[bp];
|
|
62
|
+
if (!next || next < 1)
|
|
63
|
+
return;
|
|
64
|
+
rules.push(`@media (min-width:${BREAKPOINTS[bp]}px){[data-sg-grid="${instanceId}"]{--sg-grid-cols:${next};}}`);
|
|
65
|
+
});
|
|
66
|
+
return rules.join("\n");
|
|
67
|
+
}, [instanceId, minItemWidth, normalized]);
|
|
68
|
+
const templateColumns = minItemWidth
|
|
69
|
+
? `repeat(auto-fit, minmax(${toCssSpace(minItemWidth)}, 1fr))`
|
|
70
|
+
: "repeat(var(--sg-grid-cols), minmax(0, 1fr))";
|
|
71
|
+
const items = React.Children.toArray(children);
|
|
72
|
+
return (_jsxs(_Fragment, { children: [dynamicCss ? _jsx("style", { children: dynamicCss }) : null, _jsx("div", { "data-sg-grid": instanceId, className: cn("grid min-h-0 min-w-0", className), style: {
|
|
73
|
+
...style,
|
|
74
|
+
gridTemplateColumns: templateColumns,
|
|
75
|
+
gap: toCssSpace(gap),
|
|
76
|
+
padding: toCssSpace(padding),
|
|
77
|
+
gridAutoRows: toCssSpace(rowHeight),
|
|
78
|
+
gridAutoFlow: dense ? "dense" : undefined,
|
|
79
|
+
justifyContent: justifyToCss(justify),
|
|
80
|
+
alignItems: alignToCss(align)
|
|
81
|
+
}, ...rest, children: items.map((item, index) => {
|
|
82
|
+
if (!React.isValidElement(item)) {
|
|
83
|
+
return item;
|
|
84
|
+
}
|
|
85
|
+
const element = item;
|
|
86
|
+
const span = element.props?.span;
|
|
87
|
+
const rowSpan = element.props?.rowSpan;
|
|
88
|
+
const hasSpan = typeof span === "number" && span > 1;
|
|
89
|
+
const hasRowSpan = typeof rowSpan === "number" && rowSpan > 1;
|
|
90
|
+
if (!hasSpan && !hasRowSpan) {
|
|
91
|
+
return React.cloneElement(element, { key: element.key ?? `grid-item-${index}` });
|
|
92
|
+
}
|
|
93
|
+
const wrapperStyle = {};
|
|
94
|
+
if (hasSpan)
|
|
95
|
+
wrapperStyle.gridColumn = `span ${span} / span ${span}`;
|
|
96
|
+
if (hasRowSpan)
|
|
97
|
+
wrapperStyle.gridRow = `span ${rowSpan} / span ${rowSpan}`;
|
|
98
|
+
return (_jsx("div", { className: "min-h-0 min-w-0", style: wrapperStyle, children: element }, item.key ?? `grid-wrap-${index}`));
|
|
99
|
+
}) })] }));
|
|
100
|
+
}
|
|
101
|
+
SgGrid.displayName = "SgGrid";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export type SgGroupBoxProps = {
|
|
3
|
+
title: string;
|
|
4
|
+
height?: number | string;
|
|
5
|
+
width?: number | string;
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
className?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function SgGroupBox(props: SgGroupBoxProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=SgGroupBox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgGroupBox.d.ts","sourceRoot":"","sources":["../../src/layout/SgGroupBox.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAOF,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,2CAmBhD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
function toCssSize(value) {
|
|
4
|
+
if (value === undefined || value === null)
|
|
5
|
+
return undefined;
|
|
6
|
+
return typeof value === "number" ? `${value}px` : value;
|
|
7
|
+
}
|
|
8
|
+
export function SgGroupBox(props) {
|
|
9
|
+
const { title, height, width, children, className } = props;
|
|
10
|
+
return (_jsx("div", { className: className, style: {
|
|
11
|
+
width: toCssSize(width) ?? "100%",
|
|
12
|
+
height: toCssSize(height)
|
|
13
|
+
}, children: _jsxs("fieldset", { className: "relative rounded-lg border border-border bg-white px-4 pb-4 pt-5", children: [_jsx("legend", { className: "px-2 text-xs font-semibold uppercase tracking-wider text-foreground/70", children: title }), _jsx("div", { children: children })] }) }));
|
|
14
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type SgMainPanelProps = Omit<React.HTMLAttributes<HTMLDivElement>, "children"> & {
|
|
3
|
+
gap?: number | string;
|
|
4
|
+
padding?: number | string;
|
|
5
|
+
children?: React.ReactNode;
|
|
6
|
+
};
|
|
7
|
+
export declare function SgMainPanel(props: Readonly<SgMainPanelProps>): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare namespace SgMainPanel {
|
|
9
|
+
var displayName: string;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=SgMainPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgMainPanel.d.ts","sourceRoot":"","sources":["../../src/layout/SgMainPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAiD/B,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAAG;IACtF,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,2CA6H5D;yBA7He,WAAW"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
function cn(...parts) {
|
|
5
|
+
return parts.filter(Boolean).join(" ");
|
|
6
|
+
}
|
|
7
|
+
function toCssSpace(value) {
|
|
8
|
+
if (value === undefined || value === null)
|
|
9
|
+
return undefined;
|
|
10
|
+
return typeof value === "number" ? `${value}px` : value;
|
|
11
|
+
}
|
|
12
|
+
function toCssPercent(value) {
|
|
13
|
+
if (value === undefined || value === null)
|
|
14
|
+
return undefined;
|
|
15
|
+
return typeof value === "number" ? `${value}%` : value;
|
|
16
|
+
}
|
|
17
|
+
function cloneWithLayout(node, key, extraStyle, extraClassName) {
|
|
18
|
+
if (!React.isValidElement(node)) {
|
|
19
|
+
return (_jsx("div", { style: extraStyle, className: extraClassName, children: node }, key));
|
|
20
|
+
}
|
|
21
|
+
const element = node;
|
|
22
|
+
const mergedStyle = { ...(element.props.style ?? {}), ...extraStyle };
|
|
23
|
+
return React.cloneElement(element, {
|
|
24
|
+
key: element.key ?? key,
|
|
25
|
+
className: cn(element.props.className, extraClassName),
|
|
26
|
+
style: mergedStyle
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export function SgMainPanel(props) {
|
|
30
|
+
const { gap = 0, padding, className, style, children, ...rest } = props;
|
|
31
|
+
const allItems = React.Children.toArray(children).map((node, index) => {
|
|
32
|
+
const key = (React.isValidElement(node) ? node.key : null) ?? `dock-${index}`;
|
|
33
|
+
if (!React.isValidElement(node)) {
|
|
34
|
+
return { key, node, align: "client" };
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
key,
|
|
38
|
+
node,
|
|
39
|
+
align: node.props.align ?? "client",
|
|
40
|
+
width: node.props.width,
|
|
41
|
+
height: node.props.height
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
const top = allItems.filter((item) => item.align === "top");
|
|
45
|
+
const bottom = allItems.filter((item) => item.align === "bottom");
|
|
46
|
+
const left = allItems.filter((item) => item.align === "left");
|
|
47
|
+
const right = allItems.filter((item) => item.align === "right");
|
|
48
|
+
const client = allItems.filter((item) => item.align === "client");
|
|
49
|
+
const dockGapStyle = { gap: toCssSpace(gap) };
|
|
50
|
+
return (_jsxs("div", { className: cn("flex h-full w-full min-h-0 min-w-0 flex-col", className), style: {
|
|
51
|
+
...style,
|
|
52
|
+
padding: toCssSpace(padding)
|
|
53
|
+
}, ...rest, children: [top.length > 0 ? (_jsx("div", { className: "flex flex-col min-h-0 min-w-0", style: dockGapStyle, children: top.map((item, index) => cloneWithLayout(item.node, item.key ?? `top-${index}`, {
|
|
54
|
+
width: "100%",
|
|
55
|
+
height: toCssPercent(item.height)
|
|
56
|
+
}, "w-full")) })) : null, _jsxs("div", { className: "flex flex-1 min-h-0 min-w-0", style: dockGapStyle, children: [left.length > 0 ? (_jsx("div", { className: "flex min-h-0 min-w-0 flex-col", style: dockGapStyle, children: left.map((item, index) => cloneWithLayout(item.node, item.key ?? `left-${index}`, {
|
|
57
|
+
width: toCssPercent(item.width),
|
|
58
|
+
height: "100%"
|
|
59
|
+
}, "h-full")) })) : null, _jsx("div", { className: "flex flex-1 min-h-0 min-w-0", style: dockGapStyle, children: client.map((item, index) => (_jsx("div", { className: "flex-1 min-h-0 min-w-0", children: cloneWithLayout(item.node, item.key ?? `client-inner-${index}`, {
|
|
60
|
+
width: "100%",
|
|
61
|
+
height: "100%"
|
|
62
|
+
}, "h-full w-full") }, item.key ?? `client-${index}`))) }), right.length > 0 ? (_jsx("div", { className: "flex min-h-0 min-w-0 flex-col", style: dockGapStyle, children: right.map((item, index) => cloneWithLayout(item.node, item.key ?? `right-${index}`, {
|
|
63
|
+
width: toCssPercent(item.width),
|
|
64
|
+
height: "100%"
|
|
65
|
+
}, "h-full")) })) : null] }), bottom.length > 0 ? (_jsx("div", { className: "flex flex-col min-h-0 min-w-0", style: dockGapStyle, children: bottom.map((item, index) => cloneWithLayout(item.node, item.key ?? `bottom-${index}`, {
|
|
66
|
+
width: "100%",
|
|
67
|
+
height: toCssPercent(item.height)
|
|
68
|
+
}, "w-full")) })) : null] }));
|
|
69
|
+
}
|
|
70
|
+
SgMainPanel.displayName = "SgMainPanel";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type SgPanelAlign = "top" | "left" | "bottom" | "right" | "client";
|
|
3
|
+
export type SgPanelBorderStyle = "none" | "solid" | "dashed";
|
|
4
|
+
export type SgPanelScrollable = boolean | "auto" | "y" | "x";
|
|
5
|
+
export type SgPanelPercent = number | `${number}%`;
|
|
6
|
+
export type SgPanelProps = Omit<React.HTMLAttributes<HTMLDivElement>, "align" | "children"> & {
|
|
7
|
+
align?: SgPanelAlign;
|
|
8
|
+
width?: SgPanelPercent;
|
|
9
|
+
height?: SgPanelPercent;
|
|
10
|
+
span?: number;
|
|
11
|
+
rowSpan?: number;
|
|
12
|
+
borderStyle?: SgPanelBorderStyle;
|
|
13
|
+
padding?: number | string;
|
|
14
|
+
scrollable?: SgPanelScrollable;
|
|
15
|
+
scrollbarGutter?: boolean;
|
|
16
|
+
children?: React.ReactNode;
|
|
17
|
+
};
|
|
18
|
+
export declare function SgPanel(props: Readonly<SgPanelProps>): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export declare namespace SgPanel {
|
|
20
|
+
var displayName: string;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=SgPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgPanel.d.ts","sourceRoot":"","sources":["../../src/layout/SgPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAC1E,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAC7D,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC;AAC7D,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC;AAEnD,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG;IAC5F,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AASF,wBAAgB,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAC,2CAgCpD;yBAhCe,OAAO"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
function cn(...parts) {
|
|
4
|
+
return parts.filter(Boolean).join(" ");
|
|
5
|
+
}
|
|
6
|
+
function toCssSpace(value) {
|
|
7
|
+
if (value === undefined || value === null)
|
|
8
|
+
return undefined;
|
|
9
|
+
return typeof value === "number" ? `${value}px` : value;
|
|
10
|
+
}
|
|
11
|
+
function getScrollClass(scrollable) {
|
|
12
|
+
if (!scrollable)
|
|
13
|
+
return "";
|
|
14
|
+
if (scrollable === true || scrollable === "auto")
|
|
15
|
+
return "overflow-auto";
|
|
16
|
+
if (scrollable === "y")
|
|
17
|
+
return "overflow-y-auto overflow-x-hidden";
|
|
18
|
+
return "overflow-x-auto overflow-y-hidden";
|
|
19
|
+
}
|
|
20
|
+
export function SgPanel(props) {
|
|
21
|
+
const { borderStyle = "solid", padding, scrollable = false, scrollbarGutter = false, className, style, children, ...rest } = props;
|
|
22
|
+
const borderClass = borderStyle === "none"
|
|
23
|
+
? "border border-transparent"
|
|
24
|
+
: borderStyle === "dashed"
|
|
25
|
+
? "border border-dashed border-border"
|
|
26
|
+
: "border border-solid border-border";
|
|
27
|
+
return (_jsx("div", { className: cn("min-h-0 min-w-0 bg-background", borderClass, getScrollClass(scrollable), className), style: {
|
|
28
|
+
...style,
|
|
29
|
+
padding: toCssSpace(padding),
|
|
30
|
+
...(scrollbarGutter ? { scrollbarGutter: "stable" } : null)
|
|
31
|
+
}, ...rest, children: children }));
|
|
32
|
+
}
|
|
33
|
+
SgPanel.displayName = "SgPanel";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type SgScreenProps = Omit<React.HTMLAttributes<HTMLDivElement>, "children"> & {
|
|
3
|
+
fullscreen?: boolean;
|
|
4
|
+
padding?: number | string;
|
|
5
|
+
children?: React.ReactNode;
|
|
6
|
+
};
|
|
7
|
+
export declare function SgScreen(props: Readonly<SgScreenProps>): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare namespace SgScreen {
|
|
9
|
+
var displayName: string;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=SgScreen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgScreen.d.ts","sourceRoot":"","sources":["../../src/layout/SgScreen.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAAG;IACnF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,aAAa,CAAC,2CA0BtD;yBA1Be,QAAQ"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
function cn(...parts) {
|
|
4
|
+
return parts.filter(Boolean).join(" ");
|
|
5
|
+
}
|
|
6
|
+
function toCssSpace(value) {
|
|
7
|
+
if (value === undefined || value === null)
|
|
8
|
+
return undefined;
|
|
9
|
+
return typeof value === "number" ? `${value}px` : value;
|
|
10
|
+
}
|
|
11
|
+
export function SgScreen(props) {
|
|
12
|
+
const { fullscreen = true, padding, className, style, children, ...rest } = props;
|
|
13
|
+
return (_jsx("div", { className: cn("min-h-0 min-w-0", fullscreen ? "h-screen w-screen" : "h-full w-full", className), style: {
|
|
14
|
+
...style,
|
|
15
|
+
padding: toCssSpace(padding)
|
|
16
|
+
}, ...rest, children: children }));
|
|
17
|
+
}
|
|
18
|
+
SgScreen.displayName = "SgScreen";
|