@skygraph/react 0.5.1 → 0.5.3
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/README.md +70 -70
- package/dist/{Table-BmesoMje.d.ts → Table-CAay8MmA.d.ts} +8 -1
- package/dist/{Table-CpKMOH2x.d.cts → Table-CMKo6Pc3.d.cts} +8 -1
- package/dist/{chunk-ZJF6SJLP.js → chunk-45YW5VSP.js} +44 -10
- package/dist/chunk-45YW5VSP.js.map +1 -0
- package/dist/{chunk-Z5UGF7EO.js → chunk-EFDB2ENB.js} +87 -25
- package/dist/chunk-EFDB2ENB.js.map +1 -0
- package/dist/{chunk-UO6VJC3C.js → chunk-KGFFQGCM.js} +3 -3
- package/dist/{chunk-NXB3VAVF.js → chunk-P4J4PFBG.js} +54 -7
- package/dist/chunk-P4J4PFBG.js.map +1 -0
- package/dist/{chunk-FSV73JI4.js → chunk-PEX2UTNG.js} +2 -2
- package/dist/chunk-VLRLCHEL.js +184 -0
- package/dist/chunk-VLRLCHEL.js.map +1 -0
- package/dist/{chunk-MLEBVELO.js → chunk-YTPUWPWA.js} +51 -46
- package/dist/chunk-YTPUWPWA.js.map +1 -0
- package/dist/{chunk-GJDDPZH7.js → chunk-ZJC2QUWA.js} +12 -12
- package/dist/chunk-ZJC2QUWA.js.map +1 -0
- package/dist/datagrid.cjs +76 -21
- package/dist/datagrid.cjs.map +1 -1
- package/dist/datagrid.js +3 -3
- package/dist/devtools.cjs +11 -11
- package/dist/devtools.cjs.map +1 -1
- package/dist/devtools.js +1 -1
- package/dist/form.cjs +127 -86
- package/dist/form.cjs.map +1 -1
- package/dist/form.js +3 -3
- package/dist/index.cjs +1319 -945
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +153 -7
- package/dist/index.d.ts +153 -7
- package/dist/index.js +281 -141
- package/dist/index.js.map +1 -1
- package/dist/table.cjs +252 -169
- package/dist/table.cjs.map +1 -1
- package/dist/table.d.cts +1 -1
- package/dist/table.d.ts +1 -1
- package/dist/table.js +4 -4
- package/dist/tree.cjs.map +1 -1
- package/dist/tree.js +3 -3
- package/package.json +3 -3
- package/dist/chunk-2OCEO636.js +0 -91
- package/dist/chunk-2OCEO636.js.map +0 -1
- package/dist/chunk-GJDDPZH7.js.map +0 -1
- package/dist/chunk-MLEBVELO.js.map +0 -1
- package/dist/chunk-NXB3VAVF.js.map +0 -1
- package/dist/chunk-Z5UGF7EO.js.map +0 -1
- package/dist/chunk-ZJF6SJLP.js.map +0 -1
- /package/dist/{chunk-UO6VJC3C.js.map → chunk-KGFFQGCM.js.map} +0 -0
- /package/dist/{chunk-FSV73JI4.js.map → chunk-PEX2UTNG.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Spin,
|
|
3
3
|
useConfig
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-VLRLCHEL.js";
|
|
5
5
|
|
|
6
6
|
// src/components/ui/Checkbox.tsx
|
|
7
7
|
import React from "react";
|
|
@@ -55,4 +55,4 @@ function Checkbox({
|
|
|
55
55
|
export {
|
|
56
56
|
Checkbox
|
|
57
57
|
};
|
|
58
|
-
//# sourceMappingURL=chunk-
|
|
58
|
+
//# sourceMappingURL=chunk-PEX2UTNG.js.map
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// src/components/ConfigProvider.tsx
|
|
2
|
+
import { createContext, useContext, useMemo } from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
var SgConfigContext = createContext({});
|
|
5
|
+
var TOKEN_TO_CSS_VAR = {
|
|
6
|
+
colorPrimary: "--sg-color-primary",
|
|
7
|
+
colorSuccess: "--sg-color-success",
|
|
8
|
+
colorWarning: "--sg-color-warning",
|
|
9
|
+
colorError: "--sg-color-error",
|
|
10
|
+
colorText: "--sg-color-text",
|
|
11
|
+
colorBg: "--sg-color-bg",
|
|
12
|
+
colorBorder: "--sg-color-border",
|
|
13
|
+
borderRadius: "--sg-border-radius",
|
|
14
|
+
fontSize: "--sg-font-size",
|
|
15
|
+
fontFamily: "--sg-font-sans"
|
|
16
|
+
};
|
|
17
|
+
var PX_TOKENS = /* @__PURE__ */ new Set(["borderRadius", "fontSize"]);
|
|
18
|
+
function buildThemeVars(theme) {
|
|
19
|
+
const vars = {};
|
|
20
|
+
if (!theme) return vars;
|
|
21
|
+
if (theme.token) {
|
|
22
|
+
for (const key of Object.keys(theme.token)) {
|
|
23
|
+
const value = theme.token[key];
|
|
24
|
+
if (value == null) continue;
|
|
25
|
+
const cssVar = TOKEN_TO_CSS_VAR[key];
|
|
26
|
+
if (!cssVar) continue;
|
|
27
|
+
vars[cssVar] = typeof value === "number" && PX_TOKENS.has(key) ? `${value}px` : String(value);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (theme.cssVars) {
|
|
31
|
+
for (const [name, value] of Object.entries(theme.cssVars)) {
|
|
32
|
+
if (value == null) continue;
|
|
33
|
+
vars[name.startsWith("--") ? name : `--${name}`] = String(value);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return vars;
|
|
37
|
+
}
|
|
38
|
+
function mergeTheme(parent, child) {
|
|
39
|
+
if (!parent) return child;
|
|
40
|
+
if (!child) return parent;
|
|
41
|
+
return {
|
|
42
|
+
mode: child.mode ?? parent.mode,
|
|
43
|
+
token: { ...parent.token, ...child.token },
|
|
44
|
+
cssVars: { ...parent.cssVars, ...child.cssVars }
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function ConfigProvider({ children, ...config }) {
|
|
48
|
+
const parent = useContext(SgConfigContext);
|
|
49
|
+
const merged = useMemo(
|
|
50
|
+
() => ({
|
|
51
|
+
size: config.size ?? parent.size,
|
|
52
|
+
disabled: config.disabled ?? parent.disabled,
|
|
53
|
+
bordered: config.bordered ?? parent.bordered,
|
|
54
|
+
direction: config.direction ?? parent.direction,
|
|
55
|
+
locale: config.locale ? parent.locale ? { ...parent.locale, ...config.locale } : config.locale : parent.locale,
|
|
56
|
+
theme: mergeTheme(parent.theme, config.theme),
|
|
57
|
+
getPopupContainer: config.getPopupContainer ?? parent.getPopupContainer,
|
|
58
|
+
getTargetContainer: config.getTargetContainer ?? parent.getTargetContainer,
|
|
59
|
+
renderEmpty: config.renderEmpty ?? parent.renderEmpty,
|
|
60
|
+
csp: config.csp ?? parent.csp
|
|
61
|
+
}),
|
|
62
|
+
[
|
|
63
|
+
config.size,
|
|
64
|
+
config.disabled,
|
|
65
|
+
config.bordered,
|
|
66
|
+
config.direction,
|
|
67
|
+
config.locale,
|
|
68
|
+
config.theme,
|
|
69
|
+
config.getPopupContainer,
|
|
70
|
+
config.getTargetContainer,
|
|
71
|
+
config.renderEmpty,
|
|
72
|
+
config.csp,
|
|
73
|
+
parent
|
|
74
|
+
]
|
|
75
|
+
);
|
|
76
|
+
const ownVars = useMemo(() => buildThemeVars(config.theme), [config.theme]);
|
|
77
|
+
const mode = config.theme?.mode;
|
|
78
|
+
const direction = config.direction;
|
|
79
|
+
const needsScope = Boolean(direction || mode || Object.keys(ownVars).length > 0);
|
|
80
|
+
const content = needsScope ? /* @__PURE__ */ jsx(
|
|
81
|
+
"div",
|
|
82
|
+
{
|
|
83
|
+
className: "sg-config-provider",
|
|
84
|
+
style: { display: "contents", ...ownVars },
|
|
85
|
+
dir: direction,
|
|
86
|
+
"data-sg-theme": mode,
|
|
87
|
+
children
|
|
88
|
+
}
|
|
89
|
+
) : children;
|
|
90
|
+
return /* @__PURE__ */ jsx(SgConfigContext.Provider, { value: merged, children: content });
|
|
91
|
+
}
|
|
92
|
+
function useConfig() {
|
|
93
|
+
return useContext(SgConfigContext);
|
|
94
|
+
}
|
|
95
|
+
function useConfigWithDefaults(props, defaults) {
|
|
96
|
+
const config = useContext(SgConfigContext);
|
|
97
|
+
return useMemo(() => {
|
|
98
|
+
const resolvedSize = props.size ?? config.size ?? defaults.size ?? "middle";
|
|
99
|
+
const resolvedDisabled = props.disabled ?? config.disabled ?? defaults.disabled ?? false;
|
|
100
|
+
const resolvedDirection = props.direction ?? config.direction ?? defaults.direction ?? "ltr";
|
|
101
|
+
return { ...props, resolvedSize, resolvedDisabled, resolvedDirection };
|
|
102
|
+
}, [
|
|
103
|
+
props,
|
|
104
|
+
config.size,
|
|
105
|
+
config.disabled,
|
|
106
|
+
config.direction,
|
|
107
|
+
defaults.size,
|
|
108
|
+
defaults.disabled,
|
|
109
|
+
defaults.direction
|
|
110
|
+
]);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/components/ui/Spin.tsx
|
|
114
|
+
import React2 from "react";
|
|
115
|
+
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
116
|
+
function Spin({
|
|
117
|
+
spinning = true,
|
|
118
|
+
size: sizeProp,
|
|
119
|
+
delay,
|
|
120
|
+
tip,
|
|
121
|
+
fullscreen,
|
|
122
|
+
indicator,
|
|
123
|
+
children,
|
|
124
|
+
className,
|
|
125
|
+
style,
|
|
126
|
+
unstyled
|
|
127
|
+
}) {
|
|
128
|
+
const config = useConfig();
|
|
129
|
+
const resolvedSize = sizeProp ?? config.size ?? "middle";
|
|
130
|
+
const [visible, setVisible] = React2.useState(delay ? false : spinning);
|
|
131
|
+
React2.useEffect(() => {
|
|
132
|
+
if (!delay) {
|
|
133
|
+
setVisible(spinning);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (spinning) {
|
|
137
|
+
const timer = setTimeout(() => setVisible(true), delay);
|
|
138
|
+
return () => clearTimeout(timer);
|
|
139
|
+
}
|
|
140
|
+
setVisible(false);
|
|
141
|
+
}, [spinning, delay]);
|
|
142
|
+
if (!visible && !children) return null;
|
|
143
|
+
if (!visible && children) return /* @__PURE__ */ jsx2(Fragment, { children });
|
|
144
|
+
const spinSizeClass = resolvedSize === "middle" ? "default" : resolvedSize;
|
|
145
|
+
const spinClasses = unstyled ? className ?? "" : ["sg-spin", `sg-spin-${spinSizeClass}`, className].filter(Boolean).join(" ");
|
|
146
|
+
const spinElement = indicator ?? /* @__PURE__ */ jsx2(
|
|
147
|
+
"span",
|
|
148
|
+
{
|
|
149
|
+
className: spinClasses,
|
|
150
|
+
style,
|
|
151
|
+
role: "status",
|
|
152
|
+
"aria-live": "polite",
|
|
153
|
+
"aria-label": config.locale?.spin?.loading ?? "Loading"
|
|
154
|
+
}
|
|
155
|
+
);
|
|
156
|
+
if (fullscreen) {
|
|
157
|
+
return /* @__PURE__ */ jsx2("div", { className: unstyled ? "" : "sg-spin-fullscreen", children: /* @__PURE__ */ jsxs("div", { className: unstyled ? "" : "sg-spin-fullscreen-inner", children: [
|
|
158
|
+
spinElement,
|
|
159
|
+
tip && /* @__PURE__ */ jsx2("div", { className: unstyled ? "" : "sg-spin-tip", children: tip })
|
|
160
|
+
] }) });
|
|
161
|
+
}
|
|
162
|
+
if (!children) {
|
|
163
|
+
return /* @__PURE__ */ jsxs("span", { className: unstyled ? "" : "sg-spin-standalone", style, children: [
|
|
164
|
+
spinElement,
|
|
165
|
+
tip && /* @__PURE__ */ jsx2("div", { className: unstyled ? "" : "sg-spin-tip", children: tip })
|
|
166
|
+
] });
|
|
167
|
+
}
|
|
168
|
+
return /* @__PURE__ */ jsxs("div", { className: unstyled ? "" : "sg-spin-container", style, children: [
|
|
169
|
+
/* @__PURE__ */ jsxs("div", { className: unstyled ? "" : "sg-spin-overlay", children: [
|
|
170
|
+
spinElement,
|
|
171
|
+
tip && /* @__PURE__ */ jsx2("div", { className: unstyled ? "" : "sg-spin-tip", children: tip })
|
|
172
|
+
] }),
|
|
173
|
+
/* @__PURE__ */ jsx2("div", { className: visible ? unstyled ? "" : "sg-spin-blur" : "", children })
|
|
174
|
+
] });
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export {
|
|
178
|
+
buildThemeVars,
|
|
179
|
+
ConfigProvider,
|
|
180
|
+
useConfig,
|
|
181
|
+
useConfigWithDefaults,
|
|
182
|
+
Spin
|
|
183
|
+
};
|
|
184
|
+
//# sourceMappingURL=chunk-VLRLCHEL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ConfigProvider.tsx","../src/components/ui/Spin.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo } from 'react'\nimport type { SizeType, SgLocale } from '../types'\n\n/** Text/layout direction shared by descendant components. */\nexport type Direction = 'ltr' | 'rtl'\n\n/**\n * Friendly design-token overrides. Each entry is mapped to a `--sg-*` CSS\n * custom property and emitted onto a `display: contents` scope wrapper, so\n * overrides cascade to every descendant without affecting layout.\n *\n * Numeric values for length-like tokens (`borderRadius`, `fontSize`) are\n * suffixed with `px`; everything else is emitted verbatim.\n */\nexport interface SgThemeToken {\n /** Brand / primary color → `--sg-color-primary`. */\n colorPrimary?: string\n /** Success color → `--sg-color-success`. */\n colorSuccess?: string\n /** Warning color → `--sg-color-warning`. */\n colorWarning?: string\n /** Error / danger color → `--sg-color-error`. */\n colorError?: string\n /** Base text color → `--sg-color-text`. */\n colorText?: string\n /** Base background color → `--sg-color-bg`. */\n colorBg?: string\n /** Base border color → `--sg-color-border`. */\n colorBorder?: string\n /** Base corner radius → `--sg-border-radius` (number ⇒ px). */\n borderRadius?: number | string\n /** Base font size → `--sg-font-size` (number ⇒ px). */\n fontSize?: number | string\n /** Base font family → `--sg-font-sans`. */\n fontFamily?: string\n}\n\n/**\n * Theme configuration. Combines a built-in light/dark preset (`mode`),\n * friendly token overrides (`token`), and an escape hatch for raw CSS\n * variables (`cssVars`). All three are applied to a scope wrapper.\n */\nexport interface ThemeConfig {\n /** Built-in palette preset applied via `data-sg-theme`. */\n mode?: 'light' | 'dark'\n /** Friendly token overrides mapped to `--sg-*` variables. */\n token?: SgThemeToken\n /** Raw CSS variable overrides (full names, e.g. `{ '--sg-color-link': '#f50' }`). */\n cssVars?: Record<string, string>\n}\n\n/** Content-Security-Policy options for runtime-injected styles. */\nexport interface CSPConfig {\n /** `nonce` attribute applied to dynamically created `<style>` tags. */\n nonce?: string\n}\n\n/** Customizes the empty state rendered by data components (`Empty`, `Table`, …). */\nexport type RenderEmptyHandler = (componentName?: string) => React.ReactNode\n\n/**\n * Global Skygraph component configuration merged through React context.\n *\n * По `prefixCls`: сознательно НЕ входит в публичный API до реализации\n * (вариант A в `docs/styling-plan.md`, фаза 4). На практике все корневые классы\n * имеют стабильный префикс `.sg-*`; если нужна изоляция — используйте изолированный\n * скоуп на хосте (шадоу-рут/отдельный контейнер со своими токенами).\n */\nexport interface SgConfig {\n /** Default size token for nested components. */\n size?: SizeType\n /** Disables interactions for nested components when true. */\n disabled?: boolean\n /** Enables bordered styling for nested components when true. */\n bordered?: boolean\n /** Text / layout direction (`ltr` by default) applied via the `dir` attribute. */\n direction?: Direction\n /** Locale messages shallow-merged with the parent provider when set. */\n locale?: SgLocale\n /** Theme preset + token overrides applied to a scope wrapper. */\n theme?: ThemeConfig\n /**\n * Returns the mount node for popups (dropdowns, tooltips, pickers). Defaults\n * to `document.body` in consumers. Useful to keep overlays inside a scrolling\n * or scoped container.\n */\n getPopupContainer?: (triggerNode?: HTMLElement) => HTMLElement\n /** Returns the scroll/target container for affix-like positioning. */\n getTargetContainer?: () => HTMLElement\n /** Global override for the default empty state. */\n renderEmpty?: RenderEmptyHandler\n /** Content-Security-Policy options for injected styles. */\n csp?: CSPConfig\n}\n\nconst SgConfigContext = createContext<SgConfig>({})\n\n/** Props for `ConfigProvider`, extending `SgConfig` with React children. */\nexport interface ConfigProviderProps extends SgConfig {\n /** Tree of components that consume merged configuration from this provider. */\n children: React.ReactNode\n}\n\n/** Maps friendly token names to their `--sg-*` CSS variable. */\nconst TOKEN_TO_CSS_VAR: Record<keyof SgThemeToken, string> = {\n colorPrimary: '--sg-color-primary',\n colorSuccess: '--sg-color-success',\n colorWarning: '--sg-color-warning',\n colorError: '--sg-color-error',\n colorText: '--sg-color-text',\n colorBg: '--sg-color-bg',\n colorBorder: '--sg-color-border',\n borderRadius: '--sg-border-radius',\n fontSize: '--sg-font-size',\n fontFamily: '--sg-font-sans',\n}\n\n/** Token keys whose numeric values should be emitted as `px` lengths. */\nconst PX_TOKENS = new Set<keyof SgThemeToken>(['borderRadius', 'fontSize'])\n\n/** Builds a CSS-variable map from a theme's `token` + `cssVars`. */\nexport function buildThemeVars(theme?: ThemeConfig): Record<string, string> {\n const vars: Record<string, string> = {}\n if (!theme) return vars\n if (theme.token) {\n for (const key of Object.keys(theme.token) as Array<keyof SgThemeToken>) {\n const value = theme.token[key]\n if (value == null) continue\n const cssVar = TOKEN_TO_CSS_VAR[key]\n if (!cssVar) continue\n vars[cssVar] = typeof value === 'number' && PX_TOKENS.has(key) ? `${value}px` : String(value)\n }\n }\n if (theme.cssVars) {\n for (const [name, value] of Object.entries(theme.cssVars)) {\n if (value == null) continue\n vars[name.startsWith('--') ? name : `--${name}`] = String(value)\n }\n }\n return vars\n}\n\n/** Shallow-merges a parent and child theme (`token` / `cssVars` merged key-wise). */\nfunction mergeTheme(parent?: ThemeConfig, child?: ThemeConfig): ThemeConfig | undefined {\n if (!parent) return child\n if (!child) return parent\n return {\n mode: child.mode ?? parent.mode,\n token: { ...parent.token, ...child.token },\n cssVars: { ...parent.cssVars, ...child.cssVars },\n }\n}\n\n/**\n * Merges Skygraph configuration with any parent provider and exposes it via context.\n * Descendants read values through `useConfig` or `useConfigWithDefaults`.\n *\n * When `theme` or `direction` is set, children are wrapped in a `display: contents`\n * element that carries the `dir`/`data-sg-theme` attributes and CSS variables, so\n * the scope inherits without introducing an extra layout box.\n */\nexport function ConfigProvider({ children, ...config }: ConfigProviderProps) {\n const parent = useContext(SgConfigContext)\n\n const merged = useMemo<SgConfig>(\n () => ({\n size: config.size ?? parent.size,\n disabled: config.disabled ?? parent.disabled,\n bordered: config.bordered ?? parent.bordered,\n direction: config.direction ?? parent.direction,\n locale: config.locale\n ? parent.locale\n ? { ...parent.locale, ...config.locale }\n : config.locale\n : parent.locale,\n theme: mergeTheme(parent.theme, config.theme),\n getPopupContainer: config.getPopupContainer ?? parent.getPopupContainer,\n getTargetContainer: config.getTargetContainer ?? parent.getTargetContainer,\n renderEmpty: config.renderEmpty ?? parent.renderEmpty,\n csp: config.csp ?? parent.csp,\n }),\n [\n config.size,\n config.disabled,\n config.bordered,\n config.direction,\n config.locale,\n config.theme,\n config.getPopupContainer,\n config.getTargetContainer,\n config.renderEmpty,\n config.csp,\n parent,\n ],\n )\n\n // Only the *own* props are emitted to the DOM scope; CSS variables and the\n // `dir` attribute cascade to descendants, so nested providers stay correct.\n const ownVars = useMemo(() => buildThemeVars(config.theme), [config.theme])\n const mode = config.theme?.mode\n const direction = config.direction\n const needsScope = Boolean(direction || mode || Object.keys(ownVars).length > 0)\n\n const content = needsScope ? (\n <div\n className=\"sg-config-provider\"\n style={{ display: 'contents', ...ownVars } as React.CSSProperties}\n dir={direction}\n data-sg-theme={mode}\n >\n {children}\n </div>\n ) : (\n children\n )\n\n return <SgConfigContext.Provider value={merged}>{content}</SgConfigContext.Provider>\n}\n\n/** Returns the merged `SgConfig` from the nearest ancestor `ConfigProvider`. */\nexport function useConfig(): SgConfig {\n return useContext(SgConfigContext)\n}\n\n/**\n * Resolves effective `size`, `disabled`, and `direction` from props, context,\n * and explicit defaults. Returns the original props plus the resolved values.\n */\nexport function useConfigWithDefaults<T extends Record<string, unknown>>(\n props: T,\n defaults: { size?: SizeType; disabled?: boolean; bordered?: boolean; direction?: Direction },\n): T & { resolvedSize: SizeType; resolvedDisabled: boolean; resolvedDirection: Direction } {\n const config = useContext(SgConfigContext)\n\n return useMemo(() => {\n const resolvedSize =\n ((props as Record<string, unknown>).size as SizeType | undefined) ??\n config.size ??\n defaults.size ??\n 'middle'\n const resolvedDisabled =\n ((props as Record<string, unknown>).disabled as boolean | undefined) ??\n config.disabled ??\n defaults.disabled ??\n false\n const resolvedDirection =\n ((props as Record<string, unknown>).direction as Direction | undefined) ??\n config.direction ??\n defaults.direction ??\n 'ltr'\n\n return { ...props, resolvedSize, resolvedDisabled, resolvedDirection }\n }, [\n props,\n config.size,\n config.disabled,\n config.direction,\n defaults.size,\n defaults.disabled,\n defaults.direction,\n ])\n}\n","import React from 'react'\nimport { useConfig } from '../ConfigProvider'\nimport type { BaseComponentProps, SizableProps } from '../../types'\n\n/** Props for loading spinner, overlay, and optional content blur. */\nexport interface SpinProps extends BaseComponentProps, SizableProps {\n /** When `true`, shows the loading state (subject to `delay`). @default true */\n spinning?: boolean\n /** Milliseconds to wait before showing the spinner after `spinning` becomes true. */\n delay?: number\n /** Optional text below the indicator. */\n tip?: string\n /** When `true`, covers the viewport instead of inline or wrapping children. */\n fullscreen?: boolean\n /** Custom spinner node; defaults to a styled status element. */\n indicator?: React.ReactNode\n /** When set, shows an overlay with blur on this content while loading. */\n children?: React.ReactNode\n}\n\n/**\n * Loading indicator with optional delay, tip, fullscreen mode, and child overlay.\n */\nexport function Spin({\n spinning = true,\n size: sizeProp,\n delay,\n tip,\n fullscreen,\n indicator,\n children,\n className,\n style,\n unstyled,\n}: SpinProps) {\n const config = useConfig()\n const resolvedSize = sizeProp ?? config.size ?? 'middle'\n\n const [visible, setVisible] = React.useState(delay ? false : spinning)\n\n React.useEffect(() => {\n if (!delay) {\n setVisible(spinning)\n return\n }\n\n if (spinning) {\n const timer = setTimeout(() => setVisible(true), delay)\n return () => clearTimeout(timer)\n }\n\n setVisible(false)\n }, [spinning, delay])\n\n if (!visible && !children) return null\n if (!visible && children) return <>{children}</>\n\n const spinSizeClass = resolvedSize === 'middle' ? 'default' : resolvedSize\n const spinClasses = unstyled\n ? (className ?? '')\n : ['sg-spin', `sg-spin-${spinSizeClass}`, className].filter(Boolean).join(' ')\n\n const spinElement = indicator ?? (\n <span\n className={spinClasses}\n style={style}\n role=\"status\"\n aria-live=\"polite\"\n aria-label={config.locale?.spin?.loading ?? 'Loading'}\n />\n )\n\n if (fullscreen) {\n return (\n <div className={unstyled ? '' : 'sg-spin-fullscreen'}>\n <div className={unstyled ? '' : 'sg-spin-fullscreen-inner'}>\n {spinElement}\n {tip && <div className={unstyled ? '' : 'sg-spin-tip'}>{tip}</div>}\n </div>\n </div>\n )\n }\n\n if (!children) {\n return (\n <span className={unstyled ? '' : 'sg-spin-standalone'} style={style}>\n {spinElement}\n {tip && <div className={unstyled ? '' : 'sg-spin-tip'}>{tip}</div>}\n </span>\n )\n }\n\n return (\n <div className={unstyled ? '' : 'sg-spin-container'} style={style}>\n <div className={unstyled ? '' : 'sg-spin-overlay'}>\n {spinElement}\n {tip && <div className={unstyled ? '' : 'sg-spin-tip'}>{tip}</div>}\n </div>\n <div className={visible ? (unstyled ? '' : 'sg-spin-blur') : ''}>{children}</div>\n </div>\n )\n}\n"],"mappings":"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","names":["React","jsx","React"]}
|
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
Button,
|
|
3
3
|
Input,
|
|
4
4
|
Transition
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-45YW5VSP.js";
|
|
6
6
|
import {
|
|
7
7
|
Spin,
|
|
8
8
|
useConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-VLRLCHEL.js";
|
|
10
10
|
|
|
11
11
|
// src/hooks/useField.ts
|
|
12
12
|
import { useEffect, useState, useCallback, useRef } from "react";
|
|
@@ -876,20 +876,10 @@ function AutoField(props) {
|
|
|
876
876
|
const errorId = `${name}-error`;
|
|
877
877
|
const hasErrors = meta.errors.length > 0;
|
|
878
878
|
const hasWarnings = meta.warnings.length > 0;
|
|
879
|
-
const
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
...style
|
|
884
|
-
};
|
|
885
|
-
const inputStyle = {
|
|
886
|
-
padding: "6px 12px",
|
|
887
|
-
border: `1px solid ${hasErrors ? "var(--sg-error, #ff4d4f)" : hasWarnings ? "var(--sg-warning, #faad14)" : "var(--sg-border, #d9d9d9)"}`,
|
|
888
|
-
borderRadius: "var(--sg-radius, 6px)",
|
|
889
|
-
fontSize: 14,
|
|
890
|
-
outline: "none",
|
|
891
|
-
background: disabled ? "var(--sg-bg-disabled, #f5f5f5)" : "var(--sg-bg, #fff)"
|
|
892
|
-
};
|
|
879
|
+
const inputClass = [
|
|
880
|
+
"sg-autofield-input",
|
|
881
|
+
hasErrors ? "sg-autofield-input-error" : hasWarnings ? "sg-autofield-input-warning" : ""
|
|
882
|
+
].filter(Boolean).join(" ");
|
|
893
883
|
function renderInput() {
|
|
894
884
|
switch (inferredType) {
|
|
895
885
|
case "boolean":
|
|
@@ -920,7 +910,7 @@ function AutoField(props) {
|
|
|
920
910
|
min,
|
|
921
911
|
max,
|
|
922
912
|
step,
|
|
923
|
-
|
|
913
|
+
className: inputClass,
|
|
924
914
|
"aria-invalid": hasErrors,
|
|
925
915
|
"aria-describedby": hasErrors ? errorId : void 0
|
|
926
916
|
}
|
|
@@ -934,7 +924,7 @@ function AutoField(props) {
|
|
|
934
924
|
onBlur: () => form.onFieldBlur(name),
|
|
935
925
|
placeholder,
|
|
936
926
|
disabled,
|
|
937
|
-
|
|
927
|
+
className: `${inputClass} sg-autofield-input-textarea`,
|
|
938
928
|
"aria-invalid": hasErrors,
|
|
939
929
|
"aria-describedby": hasErrors ? errorId : void 0
|
|
940
930
|
}
|
|
@@ -946,7 +936,7 @@ function AutoField(props) {
|
|
|
946
936
|
value: value == null ? "" : String(value),
|
|
947
937
|
onChange: (e) => handleChange(e.target.value),
|
|
948
938
|
disabled,
|
|
949
|
-
|
|
939
|
+
className: inputClass,
|
|
950
940
|
"aria-invalid": hasErrors,
|
|
951
941
|
"aria-describedby": hasErrors ? errorId : void 0,
|
|
952
942
|
children: [
|
|
@@ -966,27 +956,34 @@ function AutoField(props) {
|
|
|
966
956
|
handleChange(selected);
|
|
967
957
|
},
|
|
968
958
|
disabled,
|
|
969
|
-
|
|
959
|
+
className: `${inputClass} sg-autofield-input-multiple`,
|
|
970
960
|
"aria-invalid": hasErrors,
|
|
971
961
|
"aria-describedby": hasErrors ? errorId : void 0,
|
|
972
962
|
children: options?.map((opt) => /* @__PURE__ */ jsx8("option", { value: opt.value, children: opt.label }, opt.value))
|
|
973
963
|
}
|
|
974
964
|
);
|
|
975
965
|
case "radio":
|
|
976
|
-
return /* @__PURE__ */ jsx8("div", { role: "radiogroup", style: { display: "flex", gap: 12, flexWrap: "wrap" }, children: options?.map((opt) => /* @__PURE__ */ jsxs4(
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
{
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
966
|
+
return /* @__PURE__ */ jsx8("div", { role: "radiogroup", style: { display: "flex", gap: 12, flexWrap: "wrap" }, children: options?.map((opt) => /* @__PURE__ */ jsxs4(
|
|
967
|
+
"label",
|
|
968
|
+
{
|
|
969
|
+
style: { display: "flex", alignItems: "center", gap: 4, cursor: "pointer" },
|
|
970
|
+
children: [
|
|
971
|
+
/* @__PURE__ */ jsx8(
|
|
972
|
+
"input",
|
|
973
|
+
{
|
|
974
|
+
type: "radio",
|
|
975
|
+
name,
|
|
976
|
+
value: opt.value,
|
|
977
|
+
checked: value === opt.value,
|
|
978
|
+
onChange: () => handleChange(opt.value),
|
|
979
|
+
disabled
|
|
980
|
+
}
|
|
981
|
+
),
|
|
982
|
+
opt.label
|
|
983
|
+
]
|
|
984
|
+
},
|
|
985
|
+
opt.value
|
|
986
|
+
)) });
|
|
990
987
|
case "date":
|
|
991
988
|
return /* @__PURE__ */ jsx8(
|
|
992
989
|
"input",
|
|
@@ -995,7 +992,7 @@ function AutoField(props) {
|
|
|
995
992
|
value: value == null ? "" : String(value),
|
|
996
993
|
onChange: (e) => handleChange(e.target.value),
|
|
997
994
|
disabled,
|
|
998
|
-
|
|
995
|
+
className: inputClass,
|
|
999
996
|
"aria-invalid": hasErrors,
|
|
1000
997
|
"aria-describedby": hasErrors ? errorId : void 0
|
|
1001
998
|
}
|
|
@@ -1008,7 +1005,7 @@ function AutoField(props) {
|
|
|
1008
1005
|
value: value == null ? "" : String(value),
|
|
1009
1006
|
onChange: (e) => handleChange(e.target.value),
|
|
1010
1007
|
disabled,
|
|
1011
|
-
|
|
1008
|
+
className: inputClass,
|
|
1012
1009
|
"aria-invalid": hasErrors,
|
|
1013
1010
|
"aria-describedby": hasErrors ? errorId : void 0
|
|
1014
1011
|
}
|
|
@@ -1023,7 +1020,7 @@ function AutoField(props) {
|
|
|
1023
1020
|
onBlur: () => form.onFieldBlur(name),
|
|
1024
1021
|
placeholder,
|
|
1025
1022
|
disabled,
|
|
1026
|
-
|
|
1023
|
+
className: inputClass,
|
|
1027
1024
|
"aria-invalid": hasErrors,
|
|
1028
1025
|
"aria-describedby": hasErrors ? errorId : void 0
|
|
1029
1026
|
}
|
|
@@ -1036,7 +1033,7 @@ function AutoField(props) {
|
|
|
1036
1033
|
value: value == null ? "#000000" : String(value),
|
|
1037
1034
|
onChange: (e) => handleChange(e.target.value),
|
|
1038
1035
|
disabled,
|
|
1039
|
-
|
|
1036
|
+
className: `${inputClass} sg-autofield-input-color`
|
|
1040
1037
|
}
|
|
1041
1038
|
);
|
|
1042
1039
|
case "slider":
|
|
@@ -1070,7 +1067,7 @@ function AutoField(props) {
|
|
|
1070
1067
|
border: "none",
|
|
1071
1068
|
cursor: disabled ? "default" : "pointer",
|
|
1072
1069
|
fontSize: 20,
|
|
1073
|
-
color: i < currentRate ? "var(--sg-warning, #faad14)" : "var(--sg-border, #d9d9d9)",
|
|
1070
|
+
color: i < currentRate ? "var(--sg-color-warning, #faad14)" : "var(--sg-color-border, #d9d9d9)",
|
|
1074
1071
|
padding: 0
|
|
1075
1072
|
},
|
|
1076
1073
|
"aria-label": `${i + 1} star${i !== 0 ? "s" : ""}`,
|
|
@@ -1091,7 +1088,7 @@ function AutoField(props) {
|
|
|
1091
1088
|
if (files) handleChange(multiple ? Array.from(files) : files[0] ?? null);
|
|
1092
1089
|
},
|
|
1093
1090
|
disabled,
|
|
1094
|
-
|
|
1091
|
+
className: inputClass
|
|
1095
1092
|
}
|
|
1096
1093
|
);
|
|
1097
1094
|
case "email":
|
|
@@ -1107,18 +1104,26 @@ function AutoField(props) {
|
|
|
1107
1104
|
onBlur: () => form.onFieldBlur(name),
|
|
1108
1105
|
placeholder,
|
|
1109
1106
|
disabled,
|
|
1110
|
-
|
|
1107
|
+
className: inputClass,
|
|
1111
1108
|
"aria-invalid": hasErrors,
|
|
1112
1109
|
"aria-describedby": hasErrors ? errorId : void 0
|
|
1113
1110
|
}
|
|
1114
1111
|
);
|
|
1115
1112
|
}
|
|
1116
1113
|
}
|
|
1117
|
-
return /* @__PURE__ */ jsxs4("div", { className: `sg-autofield ${className ?? ""}`, style
|
|
1118
|
-
inferredType !== "boolean" && inferredType !== "switch" && label && /* @__PURE__ */ jsx8("label", {
|
|
1114
|
+
return /* @__PURE__ */ jsxs4("div", { className: `sg-autofield ${className ?? ""}`, style, children: [
|
|
1115
|
+
inferredType !== "boolean" && inferredType !== "switch" && label && /* @__PURE__ */ jsx8("label", { className: "sg-autofield-label", children: label }),
|
|
1119
1116
|
renderInput(),
|
|
1120
|
-
hasErrors && /* @__PURE__ */ jsx8(
|
|
1121
|
-
|
|
1117
|
+
hasErrors && /* @__PURE__ */ jsx8(
|
|
1118
|
+
"span",
|
|
1119
|
+
{
|
|
1120
|
+
id: errorId,
|
|
1121
|
+
role: "alert",
|
|
1122
|
+
style: { color: "var(--sg-color-error, #ff4d4f)", fontSize: 12 },
|
|
1123
|
+
children: meta.errors.join("; ")
|
|
1124
|
+
}
|
|
1125
|
+
),
|
|
1126
|
+
hasWarnings && !hasErrors && /* @__PURE__ */ jsx8("span", { style: { color: "var(--sg-color-warning, #faad14)", fontSize: 12 }, children: meta.warnings.join("; ") })
|
|
1122
1127
|
] });
|
|
1123
1128
|
}
|
|
1124
1129
|
|
|
@@ -1409,4 +1414,4 @@ export {
|
|
|
1409
1414
|
jsonSchemaToDefaults,
|
|
1410
1415
|
SchemaForm
|
|
1411
1416
|
};
|
|
1412
|
-
//# sourceMappingURL=chunk-
|
|
1417
|
+
//# sourceMappingURL=chunk-YTPUWPWA.js.map
|