@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,218 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { createPortal } from "react-dom";
|
|
5
|
+
function cn(...parts) {
|
|
6
|
+
return parts.filter(Boolean).join(" ");
|
|
7
|
+
}
|
|
8
|
+
function clamp(value, min, max) {
|
|
9
|
+
return Math.max(min, Math.min(value, max));
|
|
10
|
+
}
|
|
11
|
+
function useEvent(fn) {
|
|
12
|
+
const ref = React.useRef(fn);
|
|
13
|
+
React.useEffect(() => {
|
|
14
|
+
ref.current = fn;
|
|
15
|
+
}, [fn]);
|
|
16
|
+
return React.useCallback((...args) => ref.current?.(...args), []);
|
|
17
|
+
}
|
|
18
|
+
const ACTION_CLS = {
|
|
19
|
+
primary: "text-primary-foreground bg-primary hover:brightness-95",
|
|
20
|
+
secondary: "text-secondary-foreground bg-secondary hover:brightness-95",
|
|
21
|
+
success: "text-white bg-emerald-600 hover:brightness-95",
|
|
22
|
+
info: "text-white bg-sky-600 hover:brightness-95",
|
|
23
|
+
warning: "text-white bg-amber-600 hover:brightness-95",
|
|
24
|
+
help: "text-white bg-violet-600 hover:brightness-95",
|
|
25
|
+
danger: "text-destructive-foreground bg-destructive hover:brightness-95",
|
|
26
|
+
plain: "text-foreground bg-muted hover:bg-muted/80"
|
|
27
|
+
};
|
|
28
|
+
const ACTION_DEFAULT_CLS = "text-foreground bg-transparent hover:bg-muted/80";
|
|
29
|
+
function computeAlignedLeft(anchor, popup, align) {
|
|
30
|
+
if (align === "start")
|
|
31
|
+
return anchor.left;
|
|
32
|
+
if (align === "center")
|
|
33
|
+
return anchor.left + anchor.width / 2 - popup.width / 2;
|
|
34
|
+
return anchor.right - popup.width;
|
|
35
|
+
}
|
|
36
|
+
function computeAlignedTop(anchor, popup, align) {
|
|
37
|
+
if (align === "start")
|
|
38
|
+
return anchor.top;
|
|
39
|
+
if (align === "center")
|
|
40
|
+
return anchor.top + anchor.height / 2 - popup.height / 2;
|
|
41
|
+
return anchor.bottom - popup.height;
|
|
42
|
+
}
|
|
43
|
+
function chooseAutoPlacement(opts) {
|
|
44
|
+
const { anchor, popup, offset, prefer, viewportW, viewportH } = opts;
|
|
45
|
+
const space = {
|
|
46
|
+
right: viewportW - anchor.right,
|
|
47
|
+
left: anchor.left,
|
|
48
|
+
bottom: viewportH - anchor.bottom,
|
|
49
|
+
top: anchor.top
|
|
50
|
+
};
|
|
51
|
+
const fits = (placement) => {
|
|
52
|
+
if (placement === "left" || placement === "right") {
|
|
53
|
+
return space[placement] >= popup.width + offset;
|
|
54
|
+
}
|
|
55
|
+
return space[placement] >= popup.height + offset;
|
|
56
|
+
};
|
|
57
|
+
const opposite = {
|
|
58
|
+
right: "left",
|
|
59
|
+
left: "right",
|
|
60
|
+
top: "bottom",
|
|
61
|
+
bottom: "top"
|
|
62
|
+
};
|
|
63
|
+
const candidates = [
|
|
64
|
+
prefer,
|
|
65
|
+
opposite[prefer],
|
|
66
|
+
"bottom",
|
|
67
|
+
"top",
|
|
68
|
+
"right",
|
|
69
|
+
"left"
|
|
70
|
+
];
|
|
71
|
+
return candidates.find(fits) ?? prefer;
|
|
72
|
+
}
|
|
73
|
+
function computePosition(opts) {
|
|
74
|
+
const { anchor, popup, placement, preferPlacement, align, offset, padding } = opts;
|
|
75
|
+
const vw = window.innerWidth;
|
|
76
|
+
const vh = window.innerHeight;
|
|
77
|
+
const finalPlacement = placement === "auto"
|
|
78
|
+
? chooseAutoPlacement({
|
|
79
|
+
anchor,
|
|
80
|
+
popup,
|
|
81
|
+
offset,
|
|
82
|
+
prefer: preferPlacement,
|
|
83
|
+
viewportW: vw,
|
|
84
|
+
viewportH: vh
|
|
85
|
+
})
|
|
86
|
+
: placement;
|
|
87
|
+
let top = 0;
|
|
88
|
+
let left = 0;
|
|
89
|
+
if (finalPlacement === "right") {
|
|
90
|
+
left = anchor.right + offset;
|
|
91
|
+
top = computeAlignedTop(anchor, popup, align);
|
|
92
|
+
}
|
|
93
|
+
else if (finalPlacement === "left") {
|
|
94
|
+
left = anchor.left - popup.width - offset;
|
|
95
|
+
top = computeAlignedTop(anchor, popup, align);
|
|
96
|
+
}
|
|
97
|
+
else if (finalPlacement === "bottom") {
|
|
98
|
+
top = anchor.bottom + offset;
|
|
99
|
+
left = computeAlignedLeft(anchor, popup, align);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
top = anchor.top - popup.height - offset;
|
|
103
|
+
left = computeAlignedLeft(anchor, popup, align);
|
|
104
|
+
}
|
|
105
|
+
left = clamp(left, padding, vw - popup.width - padding);
|
|
106
|
+
top = clamp(top, padding, vh - popup.height - padding);
|
|
107
|
+
return { top, left };
|
|
108
|
+
}
|
|
109
|
+
export function SgPopup(props) {
|
|
110
|
+
const { title, subtitle, open, onOpenChange, defaultOpen = false, onOpen, onClose, anchorRef, placement = "auto", preferPlacement = "right", align = "start", offset = 8, padding = 8, closeOnOutsideClick = true, closeOnEscape = true, className, style, zIndex = 60, minWidth = 180, actions, children } = props;
|
|
111
|
+
const isControlled = typeof open === "boolean";
|
|
112
|
+
const [internalOpen, setInternalOpen] = React.useState(defaultOpen);
|
|
113
|
+
const isOpen = isControlled ? open : internalOpen;
|
|
114
|
+
const setOpen = React.useCallback((next) => {
|
|
115
|
+
if (!isControlled)
|
|
116
|
+
setInternalOpen(next);
|
|
117
|
+
onOpenChange?.(next);
|
|
118
|
+
}, [isControlled, onOpenChange]);
|
|
119
|
+
const onOpenEvt = useEvent(onOpen);
|
|
120
|
+
const onCloseEvt = useEvent(onClose);
|
|
121
|
+
const prevOpen = React.useRef(isOpen);
|
|
122
|
+
React.useEffect(() => {
|
|
123
|
+
if (prevOpen.current !== isOpen) {
|
|
124
|
+
if (isOpen)
|
|
125
|
+
onOpenEvt?.();
|
|
126
|
+
else
|
|
127
|
+
onCloseEvt?.();
|
|
128
|
+
prevOpen.current = isOpen;
|
|
129
|
+
}
|
|
130
|
+
}, [isOpen, onOpenEvt, onCloseEvt]);
|
|
131
|
+
const panelRef = React.useRef(null);
|
|
132
|
+
const [pos, setPos] = React.useState(null);
|
|
133
|
+
const recompute = React.useCallback(() => {
|
|
134
|
+
const anchorEl = anchorRef.current;
|
|
135
|
+
const panelEl = panelRef.current;
|
|
136
|
+
if (!anchorEl || !panelEl)
|
|
137
|
+
return;
|
|
138
|
+
const anchorRect = anchorEl.getBoundingClientRect();
|
|
139
|
+
const popupRect = panelEl.getBoundingClientRect();
|
|
140
|
+
const next = computePosition({
|
|
141
|
+
anchor: anchorRect,
|
|
142
|
+
popup: popupRect,
|
|
143
|
+
placement,
|
|
144
|
+
preferPlacement,
|
|
145
|
+
align,
|
|
146
|
+
offset,
|
|
147
|
+
padding
|
|
148
|
+
});
|
|
149
|
+
setPos({ top: next.top, left: next.left });
|
|
150
|
+
}, [anchorRef, placement, preferPlacement, align, offset, padding]);
|
|
151
|
+
React.useLayoutEffect(() => {
|
|
152
|
+
if (!isOpen)
|
|
153
|
+
return;
|
|
154
|
+
recompute();
|
|
155
|
+
const raf = requestAnimationFrame(recompute);
|
|
156
|
+
return () => cancelAnimationFrame(raf);
|
|
157
|
+
}, [isOpen, recompute]);
|
|
158
|
+
React.useEffect(() => {
|
|
159
|
+
if (!isOpen)
|
|
160
|
+
return;
|
|
161
|
+
const onResize = () => recompute();
|
|
162
|
+
const onScroll = () => recompute();
|
|
163
|
+
window.addEventListener("resize", onResize);
|
|
164
|
+
window.addEventListener("scroll", onScroll, { passive: true, capture: true });
|
|
165
|
+
return () => {
|
|
166
|
+
window.removeEventListener("resize", onResize);
|
|
167
|
+
window.removeEventListener("scroll", onScroll, true);
|
|
168
|
+
};
|
|
169
|
+
}, [isOpen, recompute]);
|
|
170
|
+
React.useEffect(() => {
|
|
171
|
+
if (!isOpen)
|
|
172
|
+
return;
|
|
173
|
+
const onDown = (e) => {
|
|
174
|
+
if (!closeOnOutsideClick)
|
|
175
|
+
return;
|
|
176
|
+
const panel = panelRef.current;
|
|
177
|
+
const anchor = anchorRef.current;
|
|
178
|
+
const target = e.target;
|
|
179
|
+
if (panel && panel.contains(target))
|
|
180
|
+
return;
|
|
181
|
+
if (anchor && anchor.contains(target))
|
|
182
|
+
return;
|
|
183
|
+
setOpen(false);
|
|
184
|
+
};
|
|
185
|
+
const onKey = (e) => {
|
|
186
|
+
if (!closeOnEscape)
|
|
187
|
+
return;
|
|
188
|
+
if (e.key === "Escape")
|
|
189
|
+
setOpen(false);
|
|
190
|
+
};
|
|
191
|
+
document.addEventListener("mousedown", onDown);
|
|
192
|
+
document.addEventListener("keydown", onKey);
|
|
193
|
+
return () => {
|
|
194
|
+
document.removeEventListener("mousedown", onDown);
|
|
195
|
+
document.removeEventListener("keydown", onKey);
|
|
196
|
+
};
|
|
197
|
+
}, [isOpen, closeOnOutsideClick, closeOnEscape, setOpen, anchorRef]);
|
|
198
|
+
const close = React.useCallback(() => setOpen(false), [setOpen]);
|
|
199
|
+
if (!isOpen)
|
|
200
|
+
return null;
|
|
201
|
+
const body = (_jsxs("div", { ref: panelRef, className: cn("fixed overflow-hidden rounded-md border border-border bg-background shadow-lg", "min-w-[180px]", className), style: {
|
|
202
|
+
zIndex,
|
|
203
|
+
top: pos?.top ?? -9999,
|
|
204
|
+
left: pos?.left ?? -9999,
|
|
205
|
+
minWidth,
|
|
206
|
+
...style
|
|
207
|
+
}, role: "dialog", "aria-modal": "false", children: [title ? (_jsx("div", { className: "bg-primary px-3 py-2 text-xs font-medium text-primary-foreground", children: title })) : null, subtitle ? (_jsx("div", { className: "border-b border-border bg-background px-3 py-2 text-xs text-muted-foreground", children: subtitle })) : null, children ? _jsx("div", { className: "p-2", children: children }) : null, actions && actions.length > 0 ? (_jsx("div", { className: cn(children ? "border-t border-border" : "", "p-1"), children: actions.map((a, idx) => {
|
|
208
|
+
const hasSeverity = a.severity !== undefined;
|
|
209
|
+
const sev = a.severity ?? "plain";
|
|
210
|
+
return (_jsx("button", { type: "button", disabled: a.disabled, title: a.hint, className: cn("w-full select-none rounded px-3 py-2 text-left text-sm", "transition-[filter,background-color] duration-150", "disabled:opacity-50 disabled:cursor-not-allowed", idx > 0 ? "border-t border-border" : "", hasSeverity ? ACTION_CLS[sev] : ACTION_DEFAULT_CLS), onClick: () => {
|
|
211
|
+
a.onClick?.();
|
|
212
|
+
if (a.closeOnClick ?? true)
|
|
213
|
+
close();
|
|
214
|
+
}, children: _jsxs("span", { className: "inline-flex items-center gap-2", children: [a.icon ? _jsx("span", { className: "inline-flex", children: a.icon }) : null, _jsx("span", { children: a.label })] }) }, idx));
|
|
215
|
+
}) })) : null] }));
|
|
216
|
+
return createPortal(body, document.body);
|
|
217
|
+
}
|
|
218
|
+
SgPopup.displayName = "SgPopup";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export type SgToastId = string;
|
|
3
|
+
export type SgToastType = "default" | "success" | "info" | "warning" | "error" | "loading";
|
|
4
|
+
export type SgToastAction = {
|
|
5
|
+
label: React.ReactNode;
|
|
6
|
+
onClick?: () => void;
|
|
7
|
+
};
|
|
8
|
+
export type SgToastOptions = {
|
|
9
|
+
id?: SgToastId;
|
|
10
|
+
description?: React.ReactNode;
|
|
11
|
+
duration?: number;
|
|
12
|
+
action?: SgToastAction;
|
|
13
|
+
closeButton?: boolean;
|
|
14
|
+
className?: string;
|
|
15
|
+
style?: React.CSSProperties;
|
|
16
|
+
};
|
|
17
|
+
export type SgToastRecord = Omit<SgToastOptions, "id"> & {
|
|
18
|
+
id: SgToastId;
|
|
19
|
+
type: SgToastType;
|
|
20
|
+
title?: React.ReactNode;
|
|
21
|
+
createdAt: number;
|
|
22
|
+
};
|
|
23
|
+
type SgToastListener = (toasts: SgToastRecord[]) => void;
|
|
24
|
+
export declare function dismissSgToast(id?: SgToastId): void;
|
|
25
|
+
export declare function subscribeSgToasts(listener: SgToastListener): () => void;
|
|
26
|
+
export type SgToastPromiseMessages<T> = {
|
|
27
|
+
loading?: React.ReactNode;
|
|
28
|
+
success?: React.ReactNode | ((value: T) => React.ReactNode);
|
|
29
|
+
error?: React.ReactNode | ((error: unknown) => React.ReactNode);
|
|
30
|
+
};
|
|
31
|
+
export type SgToastFn = ((title?: React.ReactNode, options?: SgToastOptions) => SgToastId) & {
|
|
32
|
+
message: (title?: React.ReactNode, options?: SgToastOptions) => SgToastId;
|
|
33
|
+
success: (title?: React.ReactNode, options?: SgToastOptions) => SgToastId;
|
|
34
|
+
info: (title?: React.ReactNode, options?: SgToastOptions) => SgToastId;
|
|
35
|
+
warning: (title?: React.ReactNode, options?: SgToastOptions) => SgToastId;
|
|
36
|
+
error: (title?: React.ReactNode, options?: SgToastOptions) => SgToastId;
|
|
37
|
+
loading: (title?: React.ReactNode, options?: SgToastOptions) => SgToastId;
|
|
38
|
+
custom: (renderer: React.ReactNode | ((id: SgToastId) => React.ReactNode), options?: SgToastOptions) => SgToastId;
|
|
39
|
+
dismiss: (id?: SgToastId) => void;
|
|
40
|
+
promise: <T>(promiseOrFactory: Promise<T> | (() => Promise<T>), messages: SgToastPromiseMessages<T>, options?: SgToastOptions) => Promise<T>;
|
|
41
|
+
};
|
|
42
|
+
export declare const toast: SgToastFn;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=SgToast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgToast.d.ts","sourceRoot":"","sources":["../../src/commons/SgToast.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
const listeners = new Set();
|
|
2
|
+
let toasts = [];
|
|
3
|
+
let toastCounter = 0;
|
|
4
|
+
function emitToasts() {
|
|
5
|
+
const snapshot = [...toasts];
|
|
6
|
+
listeners.forEach((listener) => listener(snapshot));
|
|
7
|
+
}
|
|
8
|
+
function createToastId() {
|
|
9
|
+
toastCounter += 1;
|
|
10
|
+
return `sg-toast-${Date.now()}-${toastCounter}`;
|
|
11
|
+
}
|
|
12
|
+
function upsertToast(nextToast) {
|
|
13
|
+
const currentIndex = toasts.findIndex((item) => item.id === nextToast.id);
|
|
14
|
+
if (currentIndex < 0) {
|
|
15
|
+
toasts = [...toasts, nextToast];
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
const currentToast = toasts[currentIndex];
|
|
19
|
+
const merged = {
|
|
20
|
+
...currentToast,
|
|
21
|
+
...nextToast
|
|
22
|
+
};
|
|
23
|
+
toasts = [...toasts.slice(0, currentIndex), merged, ...toasts.slice(currentIndex + 1)];
|
|
24
|
+
}
|
|
25
|
+
emitToasts();
|
|
26
|
+
return nextToast.id;
|
|
27
|
+
}
|
|
28
|
+
function showToast(type, title, options = {}) {
|
|
29
|
+
const id = options.id ?? createToastId();
|
|
30
|
+
return upsertToast({
|
|
31
|
+
...options,
|
|
32
|
+
id,
|
|
33
|
+
type,
|
|
34
|
+
title,
|
|
35
|
+
createdAt: Date.now()
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
export function dismissSgToast(id) {
|
|
39
|
+
if (!id) {
|
|
40
|
+
toasts = [];
|
|
41
|
+
emitToasts();
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const previousCount = toasts.length;
|
|
45
|
+
toasts = toasts.filter((item) => item.id !== id);
|
|
46
|
+
if (toasts.length !== previousCount) {
|
|
47
|
+
emitToasts();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export function subscribeSgToasts(listener) {
|
|
51
|
+
listeners.add(listener);
|
|
52
|
+
listener([...toasts]);
|
|
53
|
+
return () => {
|
|
54
|
+
listeners.delete(listener);
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const baseToast = ((title, options) => showToast("default", title, options));
|
|
58
|
+
baseToast.message = (title, options) => showToast("default", title, options);
|
|
59
|
+
baseToast.success = (title, options) => showToast("success", title, options);
|
|
60
|
+
baseToast.info = (title, options) => showToast("info", title, options);
|
|
61
|
+
baseToast.warning = (title, options) => showToast("warning", title, options);
|
|
62
|
+
baseToast.error = (title, options) => showToast("error", title, options);
|
|
63
|
+
baseToast.loading = (title, options) => showToast("loading", title, options);
|
|
64
|
+
baseToast.custom = (renderer, options) => {
|
|
65
|
+
const id = options?.id ?? createToastId();
|
|
66
|
+
const title = typeof renderer === "function" ? renderer(id) : renderer;
|
|
67
|
+
return showToast("default", title, { ...options, id });
|
|
68
|
+
};
|
|
69
|
+
baseToast.dismiss = (id) => {
|
|
70
|
+
dismissSgToast(id);
|
|
71
|
+
};
|
|
72
|
+
baseToast.promise = async (promiseOrFactory, messages, options) => {
|
|
73
|
+
const runPromise = typeof promiseOrFactory === "function" ? promiseOrFactory() : promiseOrFactory;
|
|
74
|
+
const loadingId = baseToast.loading(messages.loading ?? "Loading...", options);
|
|
75
|
+
try {
|
|
76
|
+
const value = await runPromise;
|
|
77
|
+
if (messages.success !== undefined) {
|
|
78
|
+
const successTitle = typeof messages.success === "function" ? messages.success(value) : messages.success;
|
|
79
|
+
baseToast.success(successTitle, { ...options, id: loadingId });
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
baseToast.dismiss(loadingId);
|
|
83
|
+
}
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
if (messages.error !== undefined) {
|
|
88
|
+
const errorTitle = typeof messages.error === "function" ? messages.error(error) : messages.error;
|
|
89
|
+
baseToast.error(errorTitle, { ...options, id: loadingId });
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
baseToast.dismiss(loadingId);
|
|
93
|
+
}
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
export const toast = baseToast;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export type SgToasterPosition = "top-right" | "top-left" | "top-center" | "bottom-right" | "bottom-left" | "bottom-center";
|
|
3
|
+
export type SgToasterProps = Omit<React.HTMLAttributes<HTMLDivElement>, "children"> & {
|
|
4
|
+
position?: SgToasterPosition;
|
|
5
|
+
duration?: number;
|
|
6
|
+
visibleToasts?: number;
|
|
7
|
+
closeButton?: boolean;
|
|
8
|
+
richColors?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare function SgToaster(props: SgToasterProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=SgToaster.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgToaster.d.ts","sourceRoot":"","sources":["../../src/commons/SgToaster.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,MAAM,MAAM,iBAAiB,GACzB,WAAW,GACX,UAAU,GACV,YAAY,GACZ,cAAc,GACd,aAAa,GACb,eAAe,CAAC;AAEpB,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAAG;IACpF,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AA6BF,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,2CAyH9C"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { dismissSgToast, subscribeSgToasts } from "./SgToast";
|
|
5
|
+
function cn(...parts) {
|
|
6
|
+
return parts.filter(Boolean).join(" ");
|
|
7
|
+
}
|
|
8
|
+
const POSITION_CLASS = {
|
|
9
|
+
"top-right": "top-4 right-4 items-end",
|
|
10
|
+
"top-left": "top-4 left-4 items-start",
|
|
11
|
+
"top-center": "top-4 left-1/2 -translate-x-1/2 items-center",
|
|
12
|
+
"bottom-right": "bottom-4 right-4 items-end",
|
|
13
|
+
"bottom-left": "bottom-4 left-4 items-start",
|
|
14
|
+
"bottom-center": "bottom-4 left-1/2 -translate-x-1/2 items-center"
|
|
15
|
+
};
|
|
16
|
+
const RICH_TYPE_CLASS = {
|
|
17
|
+
default: "border-border bg-background text-foreground",
|
|
18
|
+
success: "border-green-500 bg-green-600 text-white",
|
|
19
|
+
info: "border-sky-500 bg-sky-600 text-white",
|
|
20
|
+
warning: "border-amber-500 bg-amber-500 text-black",
|
|
21
|
+
error: "border-red-500 bg-red-600 text-white",
|
|
22
|
+
loading: "border-blue-500 bg-blue-600 text-white"
|
|
23
|
+
};
|
|
24
|
+
const SOFT_TYPE_CLASS = {
|
|
25
|
+
default: "border-border bg-background text-foreground",
|
|
26
|
+
success: "border-green-300 bg-green-50 text-green-900",
|
|
27
|
+
info: "border-sky-300 bg-sky-50 text-sky-900",
|
|
28
|
+
warning: "border-amber-300 bg-amber-50 text-amber-900",
|
|
29
|
+
error: "border-red-300 bg-red-50 text-red-900",
|
|
30
|
+
loading: "border-blue-300 bg-blue-50 text-blue-900"
|
|
31
|
+
};
|
|
32
|
+
export function SgToaster(props) {
|
|
33
|
+
const { position = "top-right", duration = 4000, visibleToasts = 6, closeButton = true, richColors = true, className, style, ...rest } = props;
|
|
34
|
+
const [toasts, setToasts] = React.useState([]);
|
|
35
|
+
const timersRef = React.useRef({});
|
|
36
|
+
React.useEffect(() => subscribeSgToasts(setToasts), []);
|
|
37
|
+
const visible = React.useMemo(() => {
|
|
38
|
+
if (visibleToasts <= 0) {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
return toasts.slice(-visibleToasts);
|
|
42
|
+
}, [toasts, visibleToasts]);
|
|
43
|
+
React.useEffect(() => {
|
|
44
|
+
const activeIds = new Set();
|
|
45
|
+
visible.forEach((toast) => {
|
|
46
|
+
const toastId = toast.id;
|
|
47
|
+
activeIds.add(toastId);
|
|
48
|
+
if (timersRef.current[toastId]) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (toast.type === "loading") {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const timeout = toast.duration ?? duration;
|
|
55
|
+
if (timeout <= 0) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
timersRef.current[toastId] = setTimeout(() => {
|
|
59
|
+
dismissSgToast(toastId);
|
|
60
|
+
delete timersRef.current[toastId];
|
|
61
|
+
}, timeout);
|
|
62
|
+
});
|
|
63
|
+
Object.entries(timersRef.current).forEach(([toastId, timeoutRef]) => {
|
|
64
|
+
if (activeIds.has(toastId)) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
clearTimeout(timeoutRef);
|
|
68
|
+
delete timersRef.current[toastId];
|
|
69
|
+
});
|
|
70
|
+
}, [visible, duration]);
|
|
71
|
+
React.useEffect(() => {
|
|
72
|
+
return () => {
|
|
73
|
+
Object.values(timersRef.current).forEach((timeoutRef) => clearTimeout(timeoutRef));
|
|
74
|
+
timersRef.current = {};
|
|
75
|
+
};
|
|
76
|
+
}, []);
|
|
77
|
+
return (_jsx("div", { className: cn("pointer-events-none fixed z-[1100] flex max-h-screen w-full flex-col gap-2 p-4 sm:w-auto", POSITION_CLASS[position], className), style: style, ...rest, children: visible.map((toast) => {
|
|
78
|
+
const typeClass = richColors ? RICH_TYPE_CLASS[toast.type] : SOFT_TYPE_CLASS[toast.type];
|
|
79
|
+
const canClose = toast.closeButton ?? closeButton;
|
|
80
|
+
return (_jsxs("div", { className: cn("pointer-events-auto flex min-w-[260px] max-w-[420px] items-start gap-3 rounded-md border px-3 py-2 shadow-lg", typeClass, toast.className), style: toast.style, role: "status", "aria-live": "polite", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [toast.title ? _jsx("div", { className: "text-sm font-semibold", children: toast.title }) : null, toast.description ? _jsx("div", { className: "mt-0.5 text-xs opacity-90", children: toast.description }) : null] }), toast.action ? (_jsx("button", { type: "button", className: "rounded border border-current/30 px-2 py-1 text-xs font-medium opacity-95 hover:opacity-100", onClick: () => {
|
|
81
|
+
toast.action?.onClick?.();
|
|
82
|
+
dismissSgToast(toast.id);
|
|
83
|
+
}, children: toast.action.label })) : null, canClose ? (_jsx("button", { type: "button", className: "rounded px-1.5 py-0.5 text-xs opacity-80 hover:opacity-100", onClick: () => dismissSgToast(toast.id), "aria-label": "Close toast", children: "x" })) : null] }, toast.id));
|
|
84
|
+
}) }));
|
|
85
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common-passwords.d.ts","sourceRoot":"","sources":["../../src/commons/common-passwords.ts"],"names":[],"mappings":"AAuJA,wBAAgB,sBAAsB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,eAyBtD"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
const BASE_COMMON_PASSWORDS = [
|
|
2
|
+
"123456",
|
|
3
|
+
"1234567",
|
|
4
|
+
"12345678",
|
|
5
|
+
"123456789",
|
|
6
|
+
"1234567890",
|
|
7
|
+
"111111",
|
|
8
|
+
"222222",
|
|
9
|
+
"333333",
|
|
10
|
+
"444444",
|
|
11
|
+
"555555",
|
|
12
|
+
"666666",
|
|
13
|
+
"777777",
|
|
14
|
+
"888888",
|
|
15
|
+
"999999",
|
|
16
|
+
"000000",
|
|
17
|
+
"password",
|
|
18
|
+
"password1",
|
|
19
|
+
"password12",
|
|
20
|
+
"password123",
|
|
21
|
+
"senha",
|
|
22
|
+
"senha1",
|
|
23
|
+
"senha12",
|
|
24
|
+
"senha123",
|
|
25
|
+
"senha1234",
|
|
26
|
+
"admin",
|
|
27
|
+
"admin1",
|
|
28
|
+
"admin123",
|
|
29
|
+
"qwerty",
|
|
30
|
+
"qwerty1",
|
|
31
|
+
"qwerty123",
|
|
32
|
+
"abc123",
|
|
33
|
+
"abc12345",
|
|
34
|
+
"abcdef",
|
|
35
|
+
"abcdefg",
|
|
36
|
+
"abcdefg1",
|
|
37
|
+
"abcdefg123",
|
|
38
|
+
"letmein",
|
|
39
|
+
"welcome",
|
|
40
|
+
"iloveyou",
|
|
41
|
+
"love",
|
|
42
|
+
"football",
|
|
43
|
+
"monkey",
|
|
44
|
+
"dragon",
|
|
45
|
+
"master",
|
|
46
|
+
"sunshine",
|
|
47
|
+
"princess",
|
|
48
|
+
"baseball",
|
|
49
|
+
"passw0rd",
|
|
50
|
+
"p@ssword",
|
|
51
|
+
"pa55word",
|
|
52
|
+
"qazwsx",
|
|
53
|
+
"qazwsx123",
|
|
54
|
+
"asdfgh",
|
|
55
|
+
"asdfgh123",
|
|
56
|
+
"zxcvbn",
|
|
57
|
+
"zxcvbn123",
|
|
58
|
+
"login",
|
|
59
|
+
"user",
|
|
60
|
+
"root",
|
|
61
|
+
"teste",
|
|
62
|
+
"test",
|
|
63
|
+
"test123",
|
|
64
|
+
"teste123",
|
|
65
|
+
"123123",
|
|
66
|
+
"123123123",
|
|
67
|
+
"321321",
|
|
68
|
+
"654321",
|
|
69
|
+
"987654",
|
|
70
|
+
"112233",
|
|
71
|
+
"121212",
|
|
72
|
+
"00000000",
|
|
73
|
+
"aaaaaa",
|
|
74
|
+
"aaaaaaa",
|
|
75
|
+
"aaaaaaaa",
|
|
76
|
+
"bbbbbb",
|
|
77
|
+
"cccccc",
|
|
78
|
+
"dddddd",
|
|
79
|
+
"eeeeee",
|
|
80
|
+
"fffffff",
|
|
81
|
+
"gggggg",
|
|
82
|
+
"hhhhhh",
|
|
83
|
+
"iiiiii",
|
|
84
|
+
"jjjjjj",
|
|
85
|
+
"kkkkkk",
|
|
86
|
+
"llllll",
|
|
87
|
+
"mmmmmm",
|
|
88
|
+
"nnnnnn",
|
|
89
|
+
"oooooo",
|
|
90
|
+
"pppppp",
|
|
91
|
+
"qqqqqq",
|
|
92
|
+
"rrrrrr",
|
|
93
|
+
"ssssss",
|
|
94
|
+
"tttttt",
|
|
95
|
+
"uuuuuu",
|
|
96
|
+
"vvvvvv",
|
|
97
|
+
"wwwwww",
|
|
98
|
+
"xxxxxx",
|
|
99
|
+
"yyyyyy",
|
|
100
|
+
"zzzzzz",
|
|
101
|
+
"secret",
|
|
102
|
+
"senha2020",
|
|
103
|
+
"senha2021",
|
|
104
|
+
"senha2022",
|
|
105
|
+
"senha2023",
|
|
106
|
+
"senha2024",
|
|
107
|
+
"password2020",
|
|
108
|
+
"password2021",
|
|
109
|
+
"password2022",
|
|
110
|
+
"password2023",
|
|
111
|
+
"password2024",
|
|
112
|
+
"admin2020",
|
|
113
|
+
"admin2021",
|
|
114
|
+
"admin2022",
|
|
115
|
+
"admin2023",
|
|
116
|
+
"admin2024",
|
|
117
|
+
"qwerty2020",
|
|
118
|
+
"qwerty2021",
|
|
119
|
+
"qwerty2022",
|
|
120
|
+
"qwerty2023",
|
|
121
|
+
"qwerty2024"
|
|
122
|
+
];
|
|
123
|
+
const PREFIXES = [
|
|
124
|
+
"senha",
|
|
125
|
+
"password",
|
|
126
|
+
"admin",
|
|
127
|
+
"qwerty",
|
|
128
|
+
"abc",
|
|
129
|
+
"teste",
|
|
130
|
+
"test",
|
|
131
|
+
"user",
|
|
132
|
+
"login",
|
|
133
|
+
"welcome",
|
|
134
|
+
"love",
|
|
135
|
+
"iloveyou",
|
|
136
|
+
"football",
|
|
137
|
+
"master",
|
|
138
|
+
"monkey",
|
|
139
|
+
"dragon",
|
|
140
|
+
"sunshine",
|
|
141
|
+
"princess",
|
|
142
|
+
"pass",
|
|
143
|
+
"secret",
|
|
144
|
+
"root",
|
|
145
|
+
"letmein"
|
|
146
|
+
];
|
|
147
|
+
const SUFFIX_NUMBERS = Array.from({ length: 40 }, (_, i) => String(i + 1));
|
|
148
|
+
const YEARS = Array.from({ length: 56 }, (_, index) => String(1970 + index));
|
|
149
|
+
export function buildCommonPasswordSet(extra) {
|
|
150
|
+
const list = [];
|
|
151
|
+
const add = (value) => {
|
|
152
|
+
if (value)
|
|
153
|
+
list.push(value);
|
|
154
|
+
};
|
|
155
|
+
BASE_COMMON_PASSWORDS.forEach(add);
|
|
156
|
+
PREFIXES.forEach((prefix) => {
|
|
157
|
+
SUFFIX_NUMBERS.forEach((num) => add(`${prefix}${num}`));
|
|
158
|
+
YEARS.forEach((year) => add(`${prefix}${year}`));
|
|
159
|
+
});
|
|
160
|
+
["123", "1234", "12345", "123456", "1234567", "12345678", "123456789"].forEach((seq) => add(seq));
|
|
161
|
+
["1111", "2222", "3333", "4444", "5555", "6666", "7777", "8888", "9999"].forEach((seq) => add(seq));
|
|
162
|
+
if (extra && extra.length > 0) {
|
|
163
|
+
extra.forEach((value) => add(value));
|
|
164
|
+
}
|
|
165
|
+
const normalized = Array.from(new Set(list.map((item) => item.trim().toLowerCase()).filter(Boolean)));
|
|
166
|
+
return new Set(normalized.slice(0, 1000));
|
|
167
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { NamespaceProvider, PersistenceStrategy, SgPersistenceRecordDTO, SgPersistenceMode, SgPersistenceConfig, SgEnvironmentValue, SgEnvironment } from "./persistence";
|
|
3
|
+
export type { NamespaceProvider, PersistenceStrategy, SgPersistenceRecordDTO, SgPersistenceMode, SgPersistenceConfig, SgEnvironmentValue, SgEnvironment, };
|
|
4
|
+
export { buildSgPersistenceKey, createLocalStorageStrategy, createApiPersistenceStrategy, createCompositePersistenceStrategy, } from "./persistence";
|
|
5
|
+
export declare function SgEnvironmentProvider(props: {
|
|
6
|
+
value?: Partial<SgEnvironmentValue>;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export declare function useSgEnvironment(): SgEnvironmentValue;
|
|
10
|
+
export declare function useSgNamespaceProvider(): NamespaceProvider;
|
|
11
|
+
export declare function useSgPersistence(): {
|
|
12
|
+
namespace: string | null;
|
|
13
|
+
scope: string;
|
|
14
|
+
mode: SgPersistenceMode;
|
|
15
|
+
stateVersion: number;
|
|
16
|
+
load: (baseKey: string) => Promise<unknown>;
|
|
17
|
+
save: (baseKey: string, state: unknown) => Promise<void>;
|
|
18
|
+
clear: (baseKey: string) => Promise<void>;
|
|
19
|
+
};
|
|
20
|
+
export declare function useSgPersistentState<T>(args: {
|
|
21
|
+
baseKey: string;
|
|
22
|
+
defaultValue: T;
|
|
23
|
+
serialize?: (value: T) => unknown;
|
|
24
|
+
deserialize?: (value: unknown) => T;
|
|
25
|
+
}): {
|
|
26
|
+
value: T;
|
|
27
|
+
setValue: (next: T | ((prev: T) => T)) => void;
|
|
28
|
+
clear: () => Promise<void>;
|
|
29
|
+
hydrated: boolean;
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=SgEnvironmentProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgEnvironmentProvider.d.ts","sourceRoot":"","sources":["../../src/environment/SgEnvironmentProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,KAAK,EACV,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACd,MAAM,eAAe,CAAC;AAGvB,YAAY,EACV,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,GACd,CAAC;AACF,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,4BAA4B,EAC5B,kCAAkC,GACnC,MAAM,eAAe,CAAC;AAkBvB,wBAAgB,qBAAqB,CAAC,KAAK,EAAE;IAC3C,KAAK,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACpC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,2CAyBA;AAED,wBAAgB,gBAAgB,IAAI,kBAAkB,CAErD;AAED,wBAAgB,sBAAsB,IAAI,iBAAiB,CAE1D;AAED,wBAAgB,gBAAgB;;;;;oBAOZ,MAAM;oBASN,MAAM,SAAS,OAAO;qBAStB,MAAM;EAiBzB;AAED,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,IAAI,EAAE;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,CAAC,CAAC;IAChB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC;IAClC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC,CAAC;CACrC;;qBAgCU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC;;;EAgB9B"}
|