@seedgrid/fe-components 0.2.8 → 0.2.10
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/commons/SgToaster.d.ts +9 -0
- package/dist/commons/SgToaster.d.ts.map +1 -1
- package/dist/commons/SgToaster.js +86 -17
- package/dist/gadgets/qr-code/SgQRCode.d.ts +25 -0
- package/dist/gadgets/qr-code/SgQRCode.d.ts.map +1 -0
- package/dist/gadgets/qr-code/SgQRCode.js +75 -0
- package/dist/gadgets/qr-code/index.d.ts +3 -0
- package/dist/gadgets/qr-code/index.d.ts.map +1 -0
- package/dist/gadgets/qr-code/index.js +1 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/inputs/SgCombobox.d.ts +26 -0
- package/dist/inputs/SgCombobox.d.ts.map +1 -0
- package/dist/inputs/SgCombobox.js +349 -0
- package/dist/inputs/SgInputOTP.d.ts +74 -0
- package/dist/inputs/SgInputOTP.d.ts.map +1 -0
- package/dist/inputs/SgInputOTP.js +499 -0
- package/dist/inputs/SgToggleSwitch.d.ts +36 -0
- package/dist/inputs/SgToggleSwitch.d.ts.map +1 -0
- package/dist/inputs/SgToggleSwitch.js +174 -0
- package/dist/others/SgPlayground.d.ts.map +1 -1
- package/dist/others/SgPlayground.js +2 -1
- package/package.json +8 -2
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { Controller } from "react-hook-form";
|
|
5
|
+
import { t, useComponentsI18n } from "../i18n";
|
|
6
|
+
function cn(...parts) {
|
|
7
|
+
return parts.filter(Boolean).join(" ");
|
|
8
|
+
}
|
|
9
|
+
function toBoolean(value, fallback = false) {
|
|
10
|
+
if (typeof value === "boolean")
|
|
11
|
+
return value;
|
|
12
|
+
if (typeof value === "number")
|
|
13
|
+
return value !== 0;
|
|
14
|
+
if (typeof value === "string") {
|
|
15
|
+
const normalized = value.trim().toLowerCase();
|
|
16
|
+
return normalized === "true" || normalized === "1" || normalized === "on" || normalized === "yes";
|
|
17
|
+
}
|
|
18
|
+
return fallback;
|
|
19
|
+
}
|
|
20
|
+
function mergeRefs(...refs) {
|
|
21
|
+
return (node) => {
|
|
22
|
+
for (const ref of refs) {
|
|
23
|
+
if (!ref)
|
|
24
|
+
continue;
|
|
25
|
+
if (typeof ref === "function") {
|
|
26
|
+
ref(node);
|
|
27
|
+
}
|
|
28
|
+
else if (typeof ref === "object" && "current" in ref) {
|
|
29
|
+
ref.current = node;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function ErrorText(props) {
|
|
35
|
+
if (!props.message)
|
|
36
|
+
return null;
|
|
37
|
+
return (_jsx("p", { id: props.id, "data-sg-error": true, className: "text-xs text-red-600", children: props.message }));
|
|
38
|
+
}
|
|
39
|
+
function mergeInputPropsWithField(inputProps, field) {
|
|
40
|
+
return {
|
|
41
|
+
...inputProps,
|
|
42
|
+
checked: toBoolean(field.value, false),
|
|
43
|
+
onChange: (event) => {
|
|
44
|
+
field.onChange(event.currentTarget.checked);
|
|
45
|
+
inputProps?.onChange?.(event);
|
|
46
|
+
},
|
|
47
|
+
onBlur: (event) => {
|
|
48
|
+
field.onBlur();
|
|
49
|
+
inputProps?.onBlur?.(event);
|
|
50
|
+
},
|
|
51
|
+
ref: (node) => {
|
|
52
|
+
field.ref(node);
|
|
53
|
+
const ref = inputProps?.ref;
|
|
54
|
+
if (!ref)
|
|
55
|
+
return;
|
|
56
|
+
if (typeof ref === "function") {
|
|
57
|
+
ref(node);
|
|
58
|
+
}
|
|
59
|
+
else if (ref && typeof ref === "object" && "current" in ref) {
|
|
60
|
+
ref.current = node;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function SgToggleSwitchBase(props) {
|
|
66
|
+
const i18n = useComponentsI18n();
|
|
67
|
+
const inputProps = props.inputProps ?? {};
|
|
68
|
+
const { checked: inputChecked, defaultChecked: inputDefaultChecked, onChange: inputOnChange, onBlur: inputOnBlur, onClick: inputOnClick, disabled: inputDisabled, readOnly: inputReadOnly, className: inputClassName, ref: inputRef, style: inputStyle, ...restInputProps } = inputProps;
|
|
69
|
+
const isControlled = props.checked !== undefined || inputChecked !== undefined;
|
|
70
|
+
const [internalChecked, setInternalChecked] = React.useState(() => toBoolean(props.defaultChecked ?? inputDefaultChecked, false));
|
|
71
|
+
const [internalError, setInternalError] = React.useState(null);
|
|
72
|
+
const [hasInteracted, setHasInteracted] = React.useState(false);
|
|
73
|
+
const inputNodeRef = React.useRef(null);
|
|
74
|
+
const errorId = `${props.id}-error`;
|
|
75
|
+
const checked = isControlled ? toBoolean(props.checked ?? inputChecked, false) : internalChecked;
|
|
76
|
+
const isReadOnly = Boolean(props.readOnly ?? inputReadOnly);
|
|
77
|
+
const isDisabled = props.enabled === false || Boolean(inputDisabled);
|
|
78
|
+
const setRefs = React.useMemo(() => mergeRefs((node) => {
|
|
79
|
+
inputNodeRef.current = node;
|
|
80
|
+
}, inputRef), [inputRef]);
|
|
81
|
+
React.useEffect(() => {
|
|
82
|
+
if (isControlled)
|
|
83
|
+
return;
|
|
84
|
+
const domChecked = inputNodeRef.current?.checked ?? false;
|
|
85
|
+
setInternalChecked((prev) => (prev === domChecked ? prev : domChecked));
|
|
86
|
+
}, [isControlled]);
|
|
87
|
+
const runValidation = React.useCallback((nextChecked) => {
|
|
88
|
+
if ((props.required ?? false) && !nextChecked) {
|
|
89
|
+
const message = props.requiredMessage ?? t(i18n, "components.inputs.required");
|
|
90
|
+
setInternalError(message);
|
|
91
|
+
props.onValidation?.(message);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (props.validation) {
|
|
95
|
+
const message = props.validation(nextChecked);
|
|
96
|
+
setInternalError(message);
|
|
97
|
+
props.onValidation?.(message ?? null);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
setInternalError(null);
|
|
101
|
+
props.onValidation?.(null);
|
|
102
|
+
}, [i18n, props]);
|
|
103
|
+
const handleChange = (event) => {
|
|
104
|
+
if (isReadOnly) {
|
|
105
|
+
event.preventDefault();
|
|
106
|
+
event.currentTarget.checked = checked;
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const nextChecked = event.currentTarget.checked;
|
|
110
|
+
if (!isControlled)
|
|
111
|
+
setInternalChecked(nextChecked);
|
|
112
|
+
setHasInteracted(true);
|
|
113
|
+
if (props.validateOnBlur === false) {
|
|
114
|
+
runValidation(nextChecked);
|
|
115
|
+
}
|
|
116
|
+
inputOnChange?.(event);
|
|
117
|
+
props.onChange?.(nextChecked);
|
|
118
|
+
};
|
|
119
|
+
const handleBlur = (event) => {
|
|
120
|
+
if ((props.validateOnBlur ?? true) || hasInteracted) {
|
|
121
|
+
runValidation(event.currentTarget.checked);
|
|
122
|
+
}
|
|
123
|
+
inputOnBlur?.(event);
|
|
124
|
+
};
|
|
125
|
+
const handleClick = (event) => {
|
|
126
|
+
if (isReadOnly) {
|
|
127
|
+
event.preventDefault();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
inputOnClick?.(event);
|
|
131
|
+
};
|
|
132
|
+
const hasError = Boolean(props.error ?? internalError);
|
|
133
|
+
const resolvedBorderRadius = 9999;
|
|
134
|
+
const switchWidth = props.width
|
|
135
|
+
? typeof props.width === "number"
|
|
136
|
+
? `${props.width}px`
|
|
137
|
+
: props.width
|
|
138
|
+
: undefined;
|
|
139
|
+
return (_jsxs("div", { className: cn("space-y-1", props.className), style: switchWidth ? { width: switchWidth } : undefined, children: [_jsxs("label", { htmlFor: props.id, className: cn("inline-flex items-start gap-3 select-none", isDisabled
|
|
140
|
+
? "cursor-not-allowed opacity-70"
|
|
141
|
+
: isReadOnly
|
|
142
|
+
? "cursor-default"
|
|
143
|
+
: "cursor-pointer"), children: [_jsx("input", { id: props.id, type: "checkbox", role: "switch", "aria-invalid": hasError, "aria-describedby": hasError ? errorId : undefined, "aria-label": props.label ? undefined : props.id, checked: isControlled ? checked : undefined, defaultChecked: isControlled ? undefined : toBoolean(props.defaultChecked ?? inputDefaultChecked, false), disabled: isDisabled, readOnly: isReadOnly, ...restInputProps, className: cn("peer sr-only", inputClassName), style: inputStyle, ref: setRefs, onChange: handleChange, onBlur: handleBlur, onClick: handleClick }), _jsxs("span", { className: cn("relative inline-flex h-6 w-11 items-center", props.switchClassName), children: [_jsx("span", { "aria-hidden": "true", className: cn("absolute inset-0 rounded-full border transition-colors duration-200", checked
|
|
144
|
+
? hasError
|
|
145
|
+
? "border-[hsl(var(--destructive))] bg-[hsl(var(--destructive)/0.2)]"
|
|
146
|
+
: "border-[hsl(var(--primary))] bg-[hsl(var(--primary))]"
|
|
147
|
+
: hasError
|
|
148
|
+
? "border-[hsl(var(--destructive))] bg-[hsl(var(--destructive)/0.05)]"
|
|
149
|
+
: "border-border bg-muted", "peer-focus-visible:ring-2 peer-focus-visible:ring-[hsl(var(--primary)/0.25)]", hasError ? "peer-focus-visible:ring-[hsl(var(--destructive)/0.25)]" : undefined, props.trackClassName), style: { borderRadius: resolvedBorderRadius } }), _jsx("span", { "aria-hidden": "true", className: cn("pointer-events-none relative z-10 inline-flex size-5 items-center justify-center rounded-full bg-white text-[11px] text-foreground/70 shadow-sm transition-transform duration-200", checked ? "translate-x-5" : "translate-x-0", props.thumbClassName), children: checked ? props.onIcon ?? null : props.offIcon ?? null })] }), props.label ? (_jsxs("span", { className: cn("pt-0.5 text-sm text-foreground", props.labelClassName), children: [props.label, props.required ? _jsx("span", { className: "ml-1 text-[hsl(var(--destructive))]", children: "*" }) : null, props.description ? (_jsx("span", { className: "mt-0.5 block text-xs text-muted-foreground", children: props.description })) : null] })) : null] }), _jsx(ErrorText, { id: errorId, message: props.error ?? internalError ?? undefined })] }));
|
|
150
|
+
}
|
|
151
|
+
export function SgToggleSwitch(props) {
|
|
152
|
+
const { control, name, register, rules, ...rest } = props;
|
|
153
|
+
if (name && register) {
|
|
154
|
+
const reg = register(name, rules);
|
|
155
|
+
return (_jsx(SgToggleSwitchBase, { ...rest, inputProps: {
|
|
156
|
+
...rest.inputProps,
|
|
157
|
+
name,
|
|
158
|
+
onChange: (event) => {
|
|
159
|
+
reg.onChange(event);
|
|
160
|
+
rest.inputProps?.onChange?.(event);
|
|
161
|
+
},
|
|
162
|
+
onBlur: (event) => {
|
|
163
|
+
reg.onBlur(event);
|
|
164
|
+
rest.inputProps?.onBlur?.(event);
|
|
165
|
+
},
|
|
166
|
+
ref: mergeRefs(reg.ref, rest.inputProps?.ref)
|
|
167
|
+
} }));
|
|
168
|
+
}
|
|
169
|
+
if (control && name) {
|
|
170
|
+
return (_jsx(Controller, { name: name, control: control, render: ({ field, fieldState }) => (_jsx(SgToggleSwitchBase, { ...rest, error: rest.error ?? fieldState.error?.message, inputProps: mergeInputPropsWithField(rest.inputProps, field) })) }));
|
|
171
|
+
}
|
|
172
|
+
return _jsx(SgToggleSwitchBase, { ...rest });
|
|
173
|
+
}
|
|
174
|
+
export const SgSwitch = SgToggleSwitch;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SgPlayground.d.ts","sourceRoot":"","sources":["../../src/others/SgPlayground.tsx"],"names":[],"mappings":"AAiBA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,GAAG,YAAY,GAAG,MAAM,CAAC;IAChD,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;
|
|
1
|
+
{"version":3,"file":"SgPlayground.d.ts","sourceRoot":"","sources":["../../src/others/SgPlayground.tsx"],"names":[],"mappings":"AAiBA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,GAAG,YAAY,GAAG,MAAM,CAAC;IAChD,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAqVF,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,iBAAiB,CAAC,2CAoMtE"}
|
|
@@ -7,8 +7,9 @@ import { SgCard } from "../layout/SgCard";
|
|
|
7
7
|
function cn(...parts) {
|
|
8
8
|
return parts.filter(Boolean).join(" ");
|
|
9
9
|
}
|
|
10
|
-
const DEFAULT_SEEDGRID_DEPENDENCY = "0.2.
|
|
10
|
+
const DEFAULT_SEEDGRID_DEPENDENCY = "0.2.9";
|
|
11
11
|
const DEFAULT_SEEDGRID_PEER_DEPENDENCIES = {
|
|
12
|
+
"@codesandbox/sandpack-react": "^2.20.0",
|
|
12
13
|
"react-hook-form": "^7.0.0",
|
|
13
14
|
"lucide-react": "^0.468.0",
|
|
14
15
|
"@tiptap/react": "^2.9.1",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seedgrid/fe-components",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -38,6 +38,8 @@
|
|
|
38
38
|
"@tiptap/extension-font-family": "^2.9.1"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
+
"react": "19.0.0",
|
|
42
|
+
"react-dom": "19.0.0",
|
|
41
43
|
"react-hook-form": "^7.0.0",
|
|
42
44
|
"@codesandbox/sandpack-react": "^2.20.0",
|
|
43
45
|
"lucide-react": "^0.468.0",
|
|
@@ -52,6 +54,10 @@
|
|
|
52
54
|
"@tiptap/extension-highlight": "^2.9.1",
|
|
53
55
|
"@tiptap/extension-subscript": "^2.9.1",
|
|
54
56
|
"@tiptap/extension-superscript": "^2.9.1",
|
|
55
|
-
"@tiptap/extension-font-family": "^2.9.1"
|
|
57
|
+
"@tiptap/extension-font-family": "^2.9.1",
|
|
58
|
+
"@types/qrcode": "^1.5.6"
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"qrcode": "^1.5.4"
|
|
56
62
|
}
|
|
57
63
|
}
|