@skygraph/react 0.5.2 → 0.6.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/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-NXB3VAVF.js → chunk-7AA2JPZB.js} +148 -61
- package/dist/chunk-7AA2JPZB.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-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-Y6XZ5TLD.js} +93 -47
- package/dist/chunk-Y6XZ5TLD.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 +168 -86
- package/dist/form.cjs.map +1 -1
- package/dist/form.d.cts +1 -1
- package/dist/form.d.ts +1 -1
- package/dist/form.js +3 -3
- package/dist/index.cjs +1549 -1021
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +157 -7
- package/dist/index.d.ts +157 -7
- package/dist/index.js +444 -231
- package/dist/index.js.map +1 -1
- package/dist/table.cjs +344 -221
- 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 +2 -2
- 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
package/dist/devtools.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/devtools.ts","../src/hooks/useHistory.ts","../src/components/devtools/HistoryPanel.tsx"],"sourcesContent":["export { useHistory } from './hooks/useHistory'\nexport type { UseHistoryReturn } from './hooks/useHistory'\nexport { HistoryPanel } from './components/devtools/HistoryPanel'\nexport type { HistoryPanelProps } from './components/devtools/HistoryPanel'\n","import { useState, useCallback, useEffect, useRef, useMemo } from 'react'\nimport type { Core } from '@skygraph/core'\nimport { createHistory } from '@skygraph/core'\nimport type { HistoryPlugin, HistoryOptions } from '@skygraph/core'\n\nexport interface UseHistoryReturn {\n history: HistoryPlugin\n canUndo: boolean\n canRedo: boolean\n cursor: number\n entries: HistoryPlugin['entries']\n undo: () => void\n redo: () => void\n jumpTo: (index: number) => void\n clear: () => void\n}\n\nexport function useHistory(core: Core, options?: HistoryOptions): UseHistoryReturn {\n const [, forceUpdate] = useState(0)\n const historyRef = useRef<HistoryPlugin | null>(null)\n const optionsRef = useRef(options)\n\n if (!historyRef.current) {\n historyRef.current = createHistory(core, optionsRef.current)\n }\n\n const tick = useCallback(() => forceUpdate((n) => n + 1), [])\n\n const undo = useCallback(() => {\n historyRef.current!.undo()\n tick()\n }, [tick])\n\n const redo = useCallback(() => {\n historyRef.current!.redo()\n tick()\n }, [tick])\n\n const jumpTo = useCallback(\n (index: number) => {\n historyRef.current!.jumpTo(index)\n tick()\n },\n [tick],\n )\n\n const clear = useCallback(() => {\n historyRef.current!.clear()\n tick()\n }, [tick])\n\n useEffect(() => {\n return () => {\n historyRef.current?.destroy()\n }\n }, [])\n\n const h = historyRef.current\n\n return useMemo(\n () => ({\n history: h,\n canUndo: h.canUndo,\n canRedo: h.canRedo,\n cursor: h.cursor,\n entries: h.entries,\n undo,\n redo,\n jumpTo,\n clear,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [h, h.cursor, h.entries.length, undo, redo, jumpTo, clear],\n )\n}\n","import React, { useState } from 'react'\nimport type { UseHistoryReturn } from '../../hooks/useHistory'\nimport type { BaseComponentProps } from '../../types'\n\n/** Props for the devtools time-travel history panel (base layout props come from `BaseComponentProps`). */\nexport interface HistoryPanelProps extends BaseComponentProps {\n /** History controller from `useHistory` (entries, cursor, undo/redo, jump, clear). */\n history: UseHistoryReturn\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n root: {\n fontFamily: 'ui-monospace, \"Cascadia Code\", \"Fira Code\", monospace',\n fontSize: 12,\n border: '1px solid var(--sg-border, #d9d9d9)',\n borderRadius: 8,\n background: 'var(--sg-bg-elevated, #fff)',\n overflow: 'hidden',\n },\n header: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '8px 12px',\n borderBottom: '1px solid var(--sg-border, #d9d9d9)',\n fontWeight: 600,\n fontSize: 13,\n },\n controls: {\n display: 'flex',\n gap: 4,\n },\n btn: {\n padding: '2px 8px',\n border: '1px solid var(--sg-border, #d9d9d9)',\n borderRadius: 4,\n background: 'var(--sg-bg, #fafafa)',\n cursor: 'pointer',\n fontSize: 11,\n },\n btnDisabled: {\n opacity: 0.4,\n cursor: 'not-allowed',\n },\n list: {\n maxHeight: 300,\n overflowY: 'auto' as const,\n margin: 0,\n padding: 0,\n listStyle: 'none',\n },\n entry: {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: '4px 12px',\n cursor: 'pointer',\n borderBottom: '1px solid var(--sg-border-light, #f0f0f0)',\n transition: 'background 0.15s',\n },\n entryActive: {\n background: 'var(--sg-primary-bg, #e6f4ff)',\n fontWeight: 600,\n },\n entryFuture: {\n opacity: 0.5,\n },\n badge: {\n display: 'inline-block',\n padding: '1px 6px',\n borderRadius: 4,\n fontSize: 10,\n background: 'var(--sg-primary-bg, #e6f4ff)',\n color: 'var(--sg-primary, #1677ff)',\n },\n patches: {\n padding: '4px 12px 8px 32px',\n background: 'var(--sg-bg-subtle, #fafafa)',\n fontSize: 11,\n lineHeight: 1.6,\n },\n empty: {\n padding: '24px 12px',\n textAlign: 'center' as const,\n color: 'var(--sg-text-tertiary, #999)',\n },\n}\n\n/**\n * Time-travel UI listing history entries with undo/redo controls and expandable patch details.\n */\nexport function HistoryPanel({ history, className, style }: HistoryPanelProps) {\n const { entries, cursor, canUndo, canRedo, undo, redo, jumpTo, clear } = history\n const [expanded, setExpanded] = useState<number | null>(null)\n\n return (\n <div className={className} style={{ ...styles.root, ...style }}>\n <div style={styles.header}>\n <span>Time-Travel ({entries.length})</span>\n <div style={styles.controls}>\n <button\n style={{ ...styles.btn, ...(canUndo ? {} : styles.btnDisabled) }}\n disabled={!canUndo}\n onClick={undo}\n >\n Undo\n </button>\n <button\n style={{ ...styles.btn, ...(canRedo ? {} : styles.btnDisabled) }}\n disabled={!canRedo}\n onClick={redo}\n >\n Redo\n </button>\n <button style={styles.btn} onClick={clear}>\n Clear\n </button>\n </div>\n </div>\n\n {entries.length === 0 ? (\n <div style={styles.empty}>No history yet</div>\n ) : (\n <ul style={styles.list}>\n {entries.map((entry, i) => {\n const isCurrent = i === cursor\n const isFuture = i > cursor\n\n return (\n <li key={i}>\n <div\n style={{\n ...styles.entry,\n ...(isCurrent ? styles.entryActive : {}),\n ...(isFuture ? styles.entryFuture : {}),\n }}\n onClick={() => jumpTo(i)}\n onDoubleClick={() => setExpanded(expanded === i ? null : i)}\n >\n <span style={styles.badge}>{i}</span>\n <span>\n {entry.patches.length} write{entry.patches.length !== 1 ? 's' : ''}\n </span>\n <span style={{ marginLeft: 'auto', fontSize: 10, opacity: 0.6 }}>\n {formatTime(entry.timestamp)}\n </span>\n </div>\n\n {expanded === i && (\n <div style={styles.patches}>\n {entry.patches.map((p, pi) => (\n <div key={pi}>\n <code>{p.path}</code>:{' '}\n <span style={{ opacity: 0.5 }}>{formatValue(p.oldValue)}</span>\n {' → '}\n <span>{formatValue(p.value)}</span>\n </div>\n ))}\n </div>\n )}\n </li>\n )\n })}\n </ul>\n )}\n </div>\n )\n}\n\nfunction formatTime(ts: number): string {\n const d = new Date(ts)\n return d.toLocaleTimeString(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n })\n}\n\nfunction formatValue(v: unknown): string {\n if (v === undefined) return 'undefined'\n if (v === null) return 'null'\n if (typeof v === 'string') return `\"${v}\"`\n try {\n return JSON.stringify(v)\n } catch {\n return String(v)\n }\n}\n"],"mappings":"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","names":["import_react"]}
|
|
1
|
+
{"version":3,"sources":["../src/devtools.ts","../src/hooks/useHistory.ts","../src/components/devtools/HistoryPanel.tsx"],"sourcesContent":["export { useHistory } from './hooks/useHistory'\nexport type { UseHistoryReturn } from './hooks/useHistory'\nexport { HistoryPanel } from './components/devtools/HistoryPanel'\nexport type { HistoryPanelProps } from './components/devtools/HistoryPanel'\n","import { useState, useCallback, useEffect, useRef, useMemo } from 'react'\nimport type { Core } from '@skygraph/core'\nimport { createHistory } from '@skygraph/core'\nimport type { HistoryPlugin, HistoryOptions } from '@skygraph/core'\n\nexport interface UseHistoryReturn {\n history: HistoryPlugin\n canUndo: boolean\n canRedo: boolean\n cursor: number\n entries: HistoryPlugin['entries']\n undo: () => void\n redo: () => void\n jumpTo: (index: number) => void\n clear: () => void\n}\n\nexport function useHistory(core: Core, options?: HistoryOptions): UseHistoryReturn {\n const [, forceUpdate] = useState(0)\n const historyRef = useRef<HistoryPlugin | null>(null)\n const optionsRef = useRef(options)\n\n if (!historyRef.current) {\n historyRef.current = createHistory(core, optionsRef.current)\n }\n\n const tick = useCallback(() => forceUpdate((n) => n + 1), [])\n\n const undo = useCallback(() => {\n historyRef.current!.undo()\n tick()\n }, [tick])\n\n const redo = useCallback(() => {\n historyRef.current!.redo()\n tick()\n }, [tick])\n\n const jumpTo = useCallback(\n (index: number) => {\n historyRef.current!.jumpTo(index)\n tick()\n },\n [tick],\n )\n\n const clear = useCallback(() => {\n historyRef.current!.clear()\n tick()\n }, [tick])\n\n useEffect(() => {\n return () => {\n historyRef.current?.destroy()\n }\n }, [])\n\n const h = historyRef.current\n\n return useMemo(\n () => ({\n history: h,\n canUndo: h.canUndo,\n canRedo: h.canRedo,\n cursor: h.cursor,\n entries: h.entries,\n undo,\n redo,\n jumpTo,\n clear,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [h, h.cursor, h.entries.length, undo, redo, jumpTo, clear],\n )\n}\n","import React, { useState } from 'react'\nimport type { UseHistoryReturn } from '../../hooks/useHistory'\nimport type { BaseComponentProps } from '../../types'\n\n/** Props for the devtools time-travel history panel (base layout props come from `BaseComponentProps`). */\nexport interface HistoryPanelProps extends BaseComponentProps {\n /** History controller from `useHistory` (entries, cursor, undo/redo, jump, clear). */\n history: UseHistoryReturn\n}\n\nconst styles: Record<string, React.CSSProperties> = {\n root: {\n fontFamily: 'ui-monospace, \"Cascadia Code\", \"Fira Code\", monospace',\n fontSize: 12,\n border: '1px solid var(--sg-color-border, #d9d9d9)',\n borderRadius: 8,\n background: 'var(--sg-color-bg-elevated, #fff)',\n overflow: 'hidden',\n },\n header: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '8px 12px',\n borderBottom: '1px solid var(--sg-color-border, #d9d9d9)',\n fontWeight: 600,\n fontSize: 13,\n },\n controls: {\n display: 'flex',\n gap: 4,\n },\n btn: {\n padding: '2px 8px',\n border: '1px solid var(--sg-color-border, #d9d9d9)',\n borderRadius: 4,\n background: 'var(--sg-color-bg-secondary, #fafafa)',\n cursor: 'pointer',\n fontSize: 11,\n },\n btnDisabled: {\n opacity: 0.4,\n cursor: 'not-allowed',\n },\n list: {\n maxHeight: 300,\n overflowY: 'auto' as const,\n margin: 0,\n padding: 0,\n listStyle: 'none',\n },\n entry: {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: '4px 12px',\n cursor: 'pointer',\n borderBottom: '1px solid var(--sg-color-border-secondary, #f0f0f0)',\n transition: 'background 0.15s',\n },\n entryActive: {\n background: 'var(--sg-color-primary-bg, #e6f4ff)',\n fontWeight: 600,\n },\n entryFuture: {\n opacity: 0.5,\n },\n badge: {\n display: 'inline-block',\n padding: '1px 6px',\n borderRadius: 4,\n fontSize: 10,\n background: 'var(--sg-color-primary-bg, #e6f4ff)',\n color: 'var(--sg-color-primary, #1677ff)',\n },\n patches: {\n padding: '4px 12px 8px 32px',\n background: 'var(--sg-color-bg-secondary, #fafafa)',\n fontSize: 11,\n lineHeight: 1.6,\n },\n empty: {\n padding: '24px 12px',\n textAlign: 'center' as const,\n color: 'var(--sg-color-text-tertiary, #999)',\n },\n}\n\n/**\n * Time-travel UI listing history entries with undo/redo controls and expandable patch details.\n */\nexport function HistoryPanel({ history, className, style }: HistoryPanelProps) {\n const { entries, cursor, canUndo, canRedo, undo, redo, jumpTo, clear } = history\n const [expanded, setExpanded] = useState<number | null>(null)\n\n return (\n <div className={className} style={{ ...styles.root, ...style }}>\n <div style={styles.header}>\n <span>Time-Travel ({entries.length})</span>\n <div style={styles.controls}>\n <button\n style={{ ...styles.btn, ...(canUndo ? {} : styles.btnDisabled) }}\n disabled={!canUndo}\n onClick={undo}\n >\n Undo\n </button>\n <button\n style={{ ...styles.btn, ...(canRedo ? {} : styles.btnDisabled) }}\n disabled={!canRedo}\n onClick={redo}\n >\n Redo\n </button>\n <button style={styles.btn} onClick={clear}>\n Clear\n </button>\n </div>\n </div>\n\n {entries.length === 0 ? (\n <div style={styles.empty}>No history yet</div>\n ) : (\n <ul style={styles.list}>\n {entries.map((entry, i) => {\n const isCurrent = i === cursor\n const isFuture = i > cursor\n\n return (\n <li key={i}>\n <div\n style={{\n ...styles.entry,\n ...(isCurrent ? styles.entryActive : {}),\n ...(isFuture ? styles.entryFuture : {}),\n }}\n onClick={() => jumpTo(i)}\n onDoubleClick={() => setExpanded(expanded === i ? null : i)}\n >\n <span style={styles.badge}>{i}</span>\n <span>\n {entry.patches.length} write{entry.patches.length !== 1 ? 's' : ''}\n </span>\n <span style={{ marginLeft: 'auto', fontSize: 10, opacity: 0.6 }}>\n {formatTime(entry.timestamp)}\n </span>\n </div>\n\n {expanded === i && (\n <div style={styles.patches}>\n {entry.patches.map((p, pi) => (\n <div key={pi}>\n <code>{p.path}</code>:{' '}\n <span style={{ opacity: 0.5 }}>{formatValue(p.oldValue)}</span>\n {' → '}\n <span>{formatValue(p.value)}</span>\n </div>\n ))}\n </div>\n )}\n </li>\n )\n })}\n </ul>\n )}\n </div>\n )\n}\n\nfunction formatTime(ts: number): string {\n const d = new Date(ts)\n return d.toLocaleTimeString(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n })\n}\n\nfunction formatValue(v: unknown): string {\n if (v === undefined) return 'undefined'\n if (v === null) return 'null'\n if (typeof v === 'string') return `\"${v}\"`\n try {\n return JSON.stringify(v)\n } catch {\n return String(v)\n }\n}\n"],"mappings":"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","names":["import_react"]}
|
package/dist/devtools.js
CHANGED
package/dist/form.cjs
CHANGED
|
@@ -421,7 +421,10 @@ function Form({
|
|
|
421
421
|
}
|
|
422
422
|
|
|
423
423
|
// src/components/complex/Field.tsx
|
|
424
|
-
var
|
|
424
|
+
var import_react14 = require("react");
|
|
425
|
+
|
|
426
|
+
// src/components/ui/Input.tsx
|
|
427
|
+
var import_react10 = __toESM(require("react"), 1);
|
|
425
428
|
|
|
426
429
|
// src/components/ui/Spin.tsx
|
|
427
430
|
var import_react9 = __toESM(require("react"), 1);
|
|
@@ -498,9 +501,14 @@ function Input({
|
|
|
498
501
|
size: sizeProp,
|
|
499
502
|
disabled: disabledProp,
|
|
500
503
|
loading,
|
|
504
|
+
allowClear = false,
|
|
505
|
+
status,
|
|
506
|
+
prefix,
|
|
507
|
+
suffix,
|
|
501
508
|
onChange,
|
|
502
509
|
onBlur,
|
|
503
510
|
onFocus,
|
|
511
|
+
onClear,
|
|
504
512
|
"aria-invalid": ariaInvalid,
|
|
505
513
|
"aria-required": ariaRequired,
|
|
506
514
|
"aria-describedby": ariaDescribedBy,
|
|
@@ -512,45 +520,73 @@ function Input({
|
|
|
512
520
|
const config = useConfig();
|
|
513
521
|
const size = sizeProp ?? config.size ?? "middle";
|
|
514
522
|
const disabled = disabledProp ?? config.disabled ?? false;
|
|
523
|
+
const [internalValue, setInternalValue] = import_react10.default.useState(defaultValue ?? "");
|
|
524
|
+
const currentValue = value ?? internalValue;
|
|
525
|
+
const isControlled = value !== void 0;
|
|
515
526
|
const wrapperClasses = unstyled ? className ?? "" : [
|
|
516
527
|
"sg-input-wrapper",
|
|
517
528
|
`sg-input-wrapper-${size}`,
|
|
518
529
|
loading ? "sg-input-wrapper-loading" : "",
|
|
519
530
|
readOnly ? "sg-input-wrapper-readonly" : "",
|
|
531
|
+
status ? `sg-input-wrapper-status-${status}` : "",
|
|
520
532
|
className
|
|
521
533
|
].filter(Boolean).join(" ");
|
|
522
534
|
const inputClasses = unstyled ? "" : [
|
|
523
535
|
"sg-input",
|
|
524
536
|
`sg-input-${size}`,
|
|
525
|
-
readOnly ? "sg-input-readonly" : ""
|
|
537
|
+
readOnly ? "sg-input-readonly" : "",
|
|
538
|
+
status ? `sg-input-status-${status}` : ""
|
|
526
539
|
].filter(Boolean).join(" ");
|
|
540
|
+
const clearLabel = config.locale?.input?.clear ?? "Clear";
|
|
541
|
+
const showClear = allowClear && !disabled && !readOnly && !loading && currentValue !== "";
|
|
542
|
+
const handleChange = (e) => {
|
|
543
|
+
if (!isControlled) setInternalValue(e.target.value);
|
|
544
|
+
onChange?.(e.target.value);
|
|
545
|
+
};
|
|
546
|
+
const handleClear = () => {
|
|
547
|
+
if (!isControlled) setInternalValue("");
|
|
548
|
+
onChange?.("");
|
|
549
|
+
onClear?.();
|
|
550
|
+
};
|
|
551
|
+
const resolvedAriaInvalid = ariaInvalid ?? (status === "error" ? true : void 0);
|
|
527
552
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: wrapperClasses, style, children: [
|
|
553
|
+
prefix && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "sg-input-prefix", children: prefix }),
|
|
528
554
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
529
555
|
"input",
|
|
530
556
|
{
|
|
531
557
|
id,
|
|
532
558
|
type,
|
|
533
559
|
className: inputClasses,
|
|
534
|
-
value,
|
|
535
|
-
defaultValue,
|
|
560
|
+
value: currentValue,
|
|
536
561
|
placeholder,
|
|
537
562
|
disabled: disabled || loading,
|
|
538
563
|
readOnly,
|
|
539
|
-
"aria-invalid":
|
|
564
|
+
"aria-invalid": resolvedAriaInvalid,
|
|
540
565
|
"aria-required": ariaRequired,
|
|
541
566
|
"aria-readonly": readOnly || void 0,
|
|
542
567
|
"aria-describedby": ariaDescribedBy,
|
|
543
|
-
onChange:
|
|
568
|
+
onChange: handleChange,
|
|
544
569
|
onBlur,
|
|
545
570
|
onFocus
|
|
546
571
|
}
|
|
547
572
|
),
|
|
548
|
-
|
|
573
|
+
showClear && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
574
|
+
"button",
|
|
575
|
+
{
|
|
576
|
+
type: "button",
|
|
577
|
+
className: "sg-input-clear",
|
|
578
|
+
"aria-label": clearLabel,
|
|
579
|
+
onClick: handleClear,
|
|
580
|
+
children: "\xD7"
|
|
581
|
+
}
|
|
582
|
+
),
|
|
583
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Spin, { size: "small", unstyled }),
|
|
584
|
+
suffix && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "sg-input-suffix", children: suffix })
|
|
549
585
|
] });
|
|
550
586
|
}
|
|
551
587
|
|
|
552
588
|
// src/components/ui/Textarea.tsx
|
|
553
|
-
var
|
|
589
|
+
var import_react11 = __toESM(require("react"), 1);
|
|
554
590
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
555
591
|
function Textarea({
|
|
556
592
|
value,
|
|
@@ -576,7 +612,7 @@ function Textarea({
|
|
|
576
612
|
const config = useConfig();
|
|
577
613
|
const disabled = disabledProp ?? config.disabled;
|
|
578
614
|
const size = sizeProp ?? config.size ?? "middle";
|
|
579
|
-
const [internalValue, setInternalValue] =
|
|
615
|
+
const [internalValue, setInternalValue] = import_react11.default.useState(value ?? defaultValue ?? "");
|
|
580
616
|
const currentValue = value ?? internalValue;
|
|
581
617
|
const handleChange = (e) => {
|
|
582
618
|
const v = e.target.value;
|
|
@@ -613,10 +649,10 @@ function Textarea({
|
|
|
613
649
|
}
|
|
614
650
|
|
|
615
651
|
// src/components/ui/Tooltip.tsx
|
|
616
|
-
var
|
|
652
|
+
var import_react13 = require("react");
|
|
617
653
|
|
|
618
654
|
// src/components/ui/Transition.tsx
|
|
619
|
-
var
|
|
655
|
+
var import_react12 = __toESM(require("react"), 1);
|
|
620
656
|
function Transition({
|
|
621
657
|
visible,
|
|
622
658
|
name = "sg-fade",
|
|
@@ -630,20 +666,20 @@ function Transition({
|
|
|
630
666
|
children,
|
|
631
667
|
unmountOnExit = true
|
|
632
668
|
}) {
|
|
633
|
-
const [mounted, setMounted] = (0,
|
|
634
|
-
const [phase, setPhase] = (0,
|
|
635
|
-
const nodeRef = (0,
|
|
636
|
-
const timerRef = (0,
|
|
637
|
-
const prevVisible = (0,
|
|
638
|
-
const getEnterClasses = (0,
|
|
669
|
+
const [mounted, setMounted] = (0, import_react12.useState)(visible);
|
|
670
|
+
const [phase, setPhase] = (0, import_react12.useState)(visible ? "idle" : "idle");
|
|
671
|
+
const nodeRef = (0, import_react12.useRef)(null);
|
|
672
|
+
const timerRef = (0, import_react12.useRef)(void 0);
|
|
673
|
+
const prevVisible = (0, import_react12.useRef)(visible);
|
|
674
|
+
const getEnterClasses = (0, import_react12.useCallback)(() => {
|
|
639
675
|
if (enterFrom && enterTo) return { from: enterFrom, active: `${name}-enter-active`, to: enterTo };
|
|
640
676
|
return { from: `${name}-enter-from`, active: `${name}-enter-active`, to: `${name}-enter-to` };
|
|
641
677
|
}, [name, enterFrom, enterTo]);
|
|
642
|
-
const getLeaveClasses = (0,
|
|
678
|
+
const getLeaveClasses = (0, import_react12.useCallback)(() => {
|
|
643
679
|
if (leaveFrom && leaveTo) return { from: leaveFrom, active: `${name}-leave-active`, to: leaveTo };
|
|
644
680
|
return { from: `${name}-leave-from`, active: `${name}-leave-active`, to: `${name}-leave-to` };
|
|
645
681
|
}, [name, leaveFrom, leaveTo]);
|
|
646
|
-
(0,
|
|
682
|
+
(0, import_react12.useEffect)(() => {
|
|
647
683
|
if (visible === prevVisible.current) return;
|
|
648
684
|
prevVisible.current = visible;
|
|
649
685
|
clearTimeout(timerRef.current);
|
|
@@ -669,7 +705,7 @@ function Transition({
|
|
|
669
705
|
}, duration);
|
|
670
706
|
}
|
|
671
707
|
}, [visible, duration, unmountOnExit, onAfterEnter, onAfterLeave]);
|
|
672
|
-
(0,
|
|
708
|
+
(0, import_react12.useEffect)(() => {
|
|
673
709
|
return () => clearTimeout(timerRef.current);
|
|
674
710
|
}, []);
|
|
675
711
|
if (!mounted && unmountOnExit) return null;
|
|
@@ -690,7 +726,7 @@ function Transition({
|
|
|
690
726
|
transitionClass = `${leaveC.to} ${leaveC.active}`;
|
|
691
727
|
break;
|
|
692
728
|
}
|
|
693
|
-
return
|
|
729
|
+
return import_react12.default.cloneElement(children, {
|
|
694
730
|
ref: nodeRef,
|
|
695
731
|
className: [children.props.className, transitionClass].filter(Boolean).join(" ")
|
|
696
732
|
});
|
|
@@ -705,10 +741,10 @@ function Tooltip({
|
|
|
705
741
|
className,
|
|
706
742
|
unstyled
|
|
707
743
|
}) {
|
|
708
|
-
const [visible, setVisible] = (0,
|
|
709
|
-
const ref = (0,
|
|
710
|
-
const tooltipId = (0,
|
|
711
|
-
const triggerWithAria = (0,
|
|
744
|
+
const [visible, setVisible] = (0, import_react13.useState)(false);
|
|
745
|
+
const ref = (0, import_react13.useRef)(null);
|
|
746
|
+
const tooltipId = (0, import_react13.useId)();
|
|
747
|
+
const triggerWithAria = (0, import_react13.isValidElement)(children) ? (0, import_react13.cloneElement)(children, {
|
|
712
748
|
"aria-describedby": visible ? [children.props["aria-describedby"], tooltipId].filter(Boolean).join(" ") : children.props["aria-describedby"],
|
|
713
749
|
onFocus: (e) => {
|
|
714
750
|
setVisible(true);
|
|
@@ -786,6 +822,7 @@ function Field({
|
|
|
786
822
|
noStyle,
|
|
787
823
|
normalize,
|
|
788
824
|
getValueFromEvent: _getValueFromEvent,
|
|
825
|
+
valuePropName,
|
|
789
826
|
validateFirst,
|
|
790
827
|
validateStatus: manualStatus,
|
|
791
828
|
hasFeedback,
|
|
@@ -800,12 +837,12 @@ function Field({
|
|
|
800
837
|
const formLocale = useConfig().locale?.form;
|
|
801
838
|
const requiredMarker = formLocale?.required ?? "*";
|
|
802
839
|
const optionalMarker = formLocale?.optional ?? "(optional)";
|
|
803
|
-
const autoId = (0,
|
|
840
|
+
const autoId = (0, import_react14.useId)();
|
|
804
841
|
const fieldId = `sg-field-${autoId.replace(/:/g, "")}-${name.replace(/\./g, "-")}`;
|
|
805
842
|
const helpId = `${fieldId}-help`;
|
|
806
843
|
const field = useField(core, form, name);
|
|
807
|
-
const prevValueRef = (0,
|
|
808
|
-
(0,
|
|
844
|
+
const prevValueRef = (0, import_react14.useRef)(field.value);
|
|
845
|
+
(0, import_react14.useEffect)(() => {
|
|
809
846
|
const allRules = [...rules];
|
|
810
847
|
if (required) {
|
|
811
848
|
allRules.unshift({ required: true });
|
|
@@ -826,6 +863,18 @@ function Field({
|
|
|
826
863
|
prevValueRef.current = normalized;
|
|
827
864
|
field.onChange(normalized);
|
|
828
865
|
} : field.onChange;
|
|
866
|
+
const valueProp = valuePropName ?? "value";
|
|
867
|
+
const extractValue = (...args) => {
|
|
868
|
+
if (_getValueFromEvent) return _getValueFromEvent(...args);
|
|
869
|
+
const first = args[0];
|
|
870
|
+
if (first !== null && typeof first === "object" && "target" in first) {
|
|
871
|
+
const target = first.target;
|
|
872
|
+
if (target && typeof target === "object" && "value" in target) {
|
|
873
|
+
return valueProp === "checked" ? target.checked : target.value;
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
return first;
|
|
877
|
+
};
|
|
829
878
|
const effectiveStatus = manualStatus ?? field.status;
|
|
830
879
|
const hasErrors = field.errors.length > 0;
|
|
831
880
|
const hasWarnings = field.warnings.length > 0;
|
|
@@ -861,6 +910,34 @@ function Field({
|
|
|
861
910
|
] });
|
|
862
911
|
}
|
|
863
912
|
if (children) {
|
|
913
|
+
if ((0, import_react14.isValidElement)(children)) {
|
|
914
|
+
const childProps = children.props;
|
|
915
|
+
const childOnChange = childProps.onChange;
|
|
916
|
+
const childOnBlur = childProps.onBlur;
|
|
917
|
+
const injected = {
|
|
918
|
+
[valueProp]: field.value,
|
|
919
|
+
onChange: (...args) => {
|
|
920
|
+
wrappedOnChange(extractValue(...args));
|
|
921
|
+
childOnChange?.(...args);
|
|
922
|
+
},
|
|
923
|
+
onBlur: (...args) => {
|
|
924
|
+
field.onBlur();
|
|
925
|
+
childOnBlur?.(...args);
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
if (childProps.id === void 0) injected.id = fieldId;
|
|
929
|
+
if (childProps.disabled === void 0 && disabled) injected.disabled = true;
|
|
930
|
+
if (childProps["aria-describedby"] === void 0 && describedBy) {
|
|
931
|
+
injected["aria-describedby"] = describedBy;
|
|
932
|
+
}
|
|
933
|
+
if (childProps["aria-invalid"] === void 0 && hasErrors) {
|
|
934
|
+
injected["aria-invalid"] = true;
|
|
935
|
+
}
|
|
936
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
937
|
+
(0, import_react14.cloneElement)(children, injected),
|
|
938
|
+
feedbackIcon
|
|
939
|
+
] });
|
|
940
|
+
}
|
|
864
941
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
865
942
|
children,
|
|
866
943
|
feedbackIcon
|
|
@@ -1035,7 +1112,7 @@ function SubmitButton({
|
|
|
1035
1112
|
}
|
|
1036
1113
|
|
|
1037
1114
|
// src/components/complex/FormList.tsx
|
|
1038
|
-
var
|
|
1115
|
+
var import_react15 = __toESM(require("react"), 1);
|
|
1039
1116
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1040
1117
|
var listUid = 0;
|
|
1041
1118
|
function genKey() {
|
|
@@ -1043,15 +1120,15 @@ function genKey() {
|
|
|
1043
1120
|
}
|
|
1044
1121
|
function FormList({ name, initialValue, draggable, children }) {
|
|
1045
1122
|
const { core, form } = useFormContext();
|
|
1046
|
-
|
|
1123
|
+
import_react15.default.useEffect(() => {
|
|
1047
1124
|
if (initialValue && !Array.isArray(core.get(name))) {
|
|
1048
1125
|
core.set(name, initialValue);
|
|
1049
1126
|
}
|
|
1050
1127
|
}, []);
|
|
1051
1128
|
const listValue = useWatch(core, name);
|
|
1052
1129
|
const items = Array.isArray(listValue) ? listValue : [];
|
|
1053
|
-
const [keys, setKeys] = (0,
|
|
1054
|
-
|
|
1130
|
+
const [keys, setKeys] = (0, import_react15.useState)(() => items.map(() => genKey()));
|
|
1131
|
+
import_react15.default.useEffect(() => {
|
|
1055
1132
|
setKeys((prev) => {
|
|
1056
1133
|
if (prev.length === items.length) return prev;
|
|
1057
1134
|
if (items.length > prev.length) {
|
|
@@ -1060,11 +1137,11 @@ function FormList({ name, initialValue, draggable, children }) {
|
|
|
1060
1137
|
return prev.slice(0, items.length);
|
|
1061
1138
|
});
|
|
1062
1139
|
}, [items.length]);
|
|
1063
|
-
const fields = (0,
|
|
1140
|
+
const fields = (0, import_react15.useMemo)(
|
|
1064
1141
|
() => keys.slice(0, items.length).map((key, index) => ({ key, index })),
|
|
1065
1142
|
[keys, items.length]
|
|
1066
1143
|
);
|
|
1067
|
-
const add = (0,
|
|
1144
|
+
const add = (0, import_react15.useCallback)(
|
|
1068
1145
|
(defaultValue, insertIndex) => {
|
|
1069
1146
|
form.listAdd(name, defaultValue, insertIndex);
|
|
1070
1147
|
setKeys((prev) => {
|
|
@@ -1079,7 +1156,7 @@ function FormList({ name, initialValue, draggable, children }) {
|
|
|
1079
1156
|
},
|
|
1080
1157
|
[form, name]
|
|
1081
1158
|
);
|
|
1082
|
-
const remove = (0,
|
|
1159
|
+
const remove = (0, import_react15.useCallback)(
|
|
1083
1160
|
(index) => {
|
|
1084
1161
|
form.listRemove(name, index);
|
|
1085
1162
|
setKeys((prev) => {
|
|
@@ -1092,7 +1169,7 @@ function FormList({ name, initialValue, draggable, children }) {
|
|
|
1092
1169
|
},
|
|
1093
1170
|
[form, name]
|
|
1094
1171
|
);
|
|
1095
|
-
const move = (0,
|
|
1172
|
+
const move = (0, import_react15.useCallback)(
|
|
1096
1173
|
(from, to) => {
|
|
1097
1174
|
form.listMove(name, from, to);
|
|
1098
1175
|
setKeys((prev) => {
|
|
@@ -1104,20 +1181,20 @@ function FormList({ name, initialValue, draggable, children }) {
|
|
|
1104
1181
|
},
|
|
1105
1182
|
[form, name]
|
|
1106
1183
|
);
|
|
1107
|
-
const replace = (0,
|
|
1184
|
+
const replace = (0, import_react15.useCallback)(
|
|
1108
1185
|
(values) => {
|
|
1109
1186
|
form.listReplace(name, values);
|
|
1110
1187
|
setKeys(values.map(() => genKey()));
|
|
1111
1188
|
},
|
|
1112
1189
|
[form, name]
|
|
1113
1190
|
);
|
|
1114
|
-
const operation = (0,
|
|
1191
|
+
const operation = (0, import_react15.useMemo)(
|
|
1115
1192
|
() => ({ add, remove, move, replace }),
|
|
1116
1193
|
[add, remove, move, replace]
|
|
1117
1194
|
);
|
|
1118
|
-
const meta = (0,
|
|
1119
|
-
const dragIdx = (0,
|
|
1120
|
-
const dragOverIdx = (0,
|
|
1195
|
+
const meta = (0, import_react15.useMemo)(() => ({ errors: form.getFieldErrors(name) }), [form, name]);
|
|
1196
|
+
const dragIdx = (0, import_react15.useRef)(-1);
|
|
1197
|
+
const dragOverIdx = (0, import_react15.useRef)(-1);
|
|
1121
1198
|
if (!draggable) {
|
|
1122
1199
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, { children: children(fields, operation, meta) });
|
|
1123
1200
|
}
|
|
@@ -1149,7 +1226,7 @@ function FormList({ name, initialValue, draggable, children }) {
|
|
|
1149
1226
|
}
|
|
1150
1227
|
|
|
1151
1228
|
// src/components/complex/AutoField/AutoField.tsx
|
|
1152
|
-
var
|
|
1229
|
+
var import_react16 = require("react");
|
|
1153
1230
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1154
1231
|
function AutoField(props) {
|
|
1155
1232
|
const {
|
|
@@ -1172,7 +1249,7 @@ function AutoField(props) {
|
|
|
1172
1249
|
const { form } = useFormContext();
|
|
1173
1250
|
const value = form.getValue(name);
|
|
1174
1251
|
const meta = form.getFieldState(name);
|
|
1175
|
-
const inferredType = (0,
|
|
1252
|
+
const inferredType = (0, import_react16.useMemo)(() => {
|
|
1176
1253
|
if (forcedType) return forcedType;
|
|
1177
1254
|
if (options && options.length > 0) return "select";
|
|
1178
1255
|
if (typeof value === "boolean") return "boolean";
|
|
@@ -1189,20 +1266,10 @@ function AutoField(props) {
|
|
|
1189
1266
|
const errorId = `${name}-error`;
|
|
1190
1267
|
const hasErrors = meta.errors.length > 0;
|
|
1191
1268
|
const hasWarnings = meta.warnings.length > 0;
|
|
1192
|
-
const
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
...style
|
|
1197
|
-
};
|
|
1198
|
-
const inputStyle = {
|
|
1199
|
-
padding: "6px 12px",
|
|
1200
|
-
border: `1px solid ${hasErrors ? "var(--sg-error, #ff4d4f)" : hasWarnings ? "var(--sg-warning, #faad14)" : "var(--sg-border, #d9d9d9)"}`,
|
|
1201
|
-
borderRadius: "var(--sg-radius, 6px)",
|
|
1202
|
-
fontSize: 14,
|
|
1203
|
-
outline: "none",
|
|
1204
|
-
background: disabled ? "var(--sg-bg-disabled, #f5f5f5)" : "var(--sg-bg, #fff)"
|
|
1205
|
-
};
|
|
1269
|
+
const inputClass = [
|
|
1270
|
+
"sg-autofield-input",
|
|
1271
|
+
hasErrors ? "sg-autofield-input-error" : hasWarnings ? "sg-autofield-input-warning" : ""
|
|
1272
|
+
].filter(Boolean).join(" ");
|
|
1206
1273
|
function renderInput() {
|
|
1207
1274
|
switch (inferredType) {
|
|
1208
1275
|
case "boolean":
|
|
@@ -1233,7 +1300,7 @@ function AutoField(props) {
|
|
|
1233
1300
|
min,
|
|
1234
1301
|
max,
|
|
1235
1302
|
step,
|
|
1236
|
-
|
|
1303
|
+
className: inputClass,
|
|
1237
1304
|
"aria-invalid": hasErrors,
|
|
1238
1305
|
"aria-describedby": hasErrors ? errorId : void 0
|
|
1239
1306
|
}
|
|
@@ -1247,7 +1314,7 @@ function AutoField(props) {
|
|
|
1247
1314
|
onBlur: () => form.onFieldBlur(name),
|
|
1248
1315
|
placeholder,
|
|
1249
1316
|
disabled,
|
|
1250
|
-
|
|
1317
|
+
className: `${inputClass} sg-autofield-input-textarea`,
|
|
1251
1318
|
"aria-invalid": hasErrors,
|
|
1252
1319
|
"aria-describedby": hasErrors ? errorId : void 0
|
|
1253
1320
|
}
|
|
@@ -1259,7 +1326,7 @@ function AutoField(props) {
|
|
|
1259
1326
|
value: value == null ? "" : String(value),
|
|
1260
1327
|
onChange: (e) => handleChange(e.target.value),
|
|
1261
1328
|
disabled,
|
|
1262
|
-
|
|
1329
|
+
className: inputClass,
|
|
1263
1330
|
"aria-invalid": hasErrors,
|
|
1264
1331
|
"aria-describedby": hasErrors ? errorId : void 0,
|
|
1265
1332
|
children: [
|
|
@@ -1279,27 +1346,34 @@ function AutoField(props) {
|
|
|
1279
1346
|
handleChange(selected);
|
|
1280
1347
|
},
|
|
1281
1348
|
disabled,
|
|
1282
|
-
|
|
1349
|
+
className: `${inputClass} sg-autofield-input-multiple`,
|
|
1283
1350
|
"aria-invalid": hasErrors,
|
|
1284
1351
|
"aria-describedby": hasErrors ? errorId : void 0,
|
|
1285
1352
|
children: options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: opt.value, children: opt.label }, opt.value))
|
|
1286
1353
|
}
|
|
1287
1354
|
);
|
|
1288
1355
|
case "radio":
|
|
1289
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { role: "radiogroup", style: { display: "flex", gap: 12, flexWrap: "wrap" }, children: options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
{
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1356
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { role: "radiogroup", style: { display: "flex", gap: 12, flexWrap: "wrap" }, children: options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1357
|
+
"label",
|
|
1358
|
+
{
|
|
1359
|
+
style: { display: "flex", alignItems: "center", gap: 4, cursor: "pointer" },
|
|
1360
|
+
children: [
|
|
1361
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1362
|
+
"input",
|
|
1363
|
+
{
|
|
1364
|
+
type: "radio",
|
|
1365
|
+
name,
|
|
1366
|
+
value: opt.value,
|
|
1367
|
+
checked: value === opt.value,
|
|
1368
|
+
onChange: () => handleChange(opt.value),
|
|
1369
|
+
disabled
|
|
1370
|
+
}
|
|
1371
|
+
),
|
|
1372
|
+
opt.label
|
|
1373
|
+
]
|
|
1374
|
+
},
|
|
1375
|
+
opt.value
|
|
1376
|
+
)) });
|
|
1303
1377
|
case "date":
|
|
1304
1378
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1305
1379
|
"input",
|
|
@@ -1308,7 +1382,7 @@ function AutoField(props) {
|
|
|
1308
1382
|
value: value == null ? "" : String(value),
|
|
1309
1383
|
onChange: (e) => handleChange(e.target.value),
|
|
1310
1384
|
disabled,
|
|
1311
|
-
|
|
1385
|
+
className: inputClass,
|
|
1312
1386
|
"aria-invalid": hasErrors,
|
|
1313
1387
|
"aria-describedby": hasErrors ? errorId : void 0
|
|
1314
1388
|
}
|
|
@@ -1321,7 +1395,7 @@ function AutoField(props) {
|
|
|
1321
1395
|
value: value == null ? "" : String(value),
|
|
1322
1396
|
onChange: (e) => handleChange(e.target.value),
|
|
1323
1397
|
disabled,
|
|
1324
|
-
|
|
1398
|
+
className: inputClass,
|
|
1325
1399
|
"aria-invalid": hasErrors,
|
|
1326
1400
|
"aria-describedby": hasErrors ? errorId : void 0
|
|
1327
1401
|
}
|
|
@@ -1336,7 +1410,7 @@ function AutoField(props) {
|
|
|
1336
1410
|
onBlur: () => form.onFieldBlur(name),
|
|
1337
1411
|
placeholder,
|
|
1338
1412
|
disabled,
|
|
1339
|
-
|
|
1413
|
+
className: inputClass,
|
|
1340
1414
|
"aria-invalid": hasErrors,
|
|
1341
1415
|
"aria-describedby": hasErrors ? errorId : void 0
|
|
1342
1416
|
}
|
|
@@ -1349,7 +1423,7 @@ function AutoField(props) {
|
|
|
1349
1423
|
value: value == null ? "#000000" : String(value),
|
|
1350
1424
|
onChange: (e) => handleChange(e.target.value),
|
|
1351
1425
|
disabled,
|
|
1352
|
-
|
|
1426
|
+
className: `${inputClass} sg-autofield-input-color`
|
|
1353
1427
|
}
|
|
1354
1428
|
);
|
|
1355
1429
|
case "slider":
|
|
@@ -1383,7 +1457,7 @@ function AutoField(props) {
|
|
|
1383
1457
|
border: "none",
|
|
1384
1458
|
cursor: disabled ? "default" : "pointer",
|
|
1385
1459
|
fontSize: 20,
|
|
1386
|
-
color: i < currentRate ? "var(--sg-warning, #faad14)" : "var(--sg-border, #d9d9d9)",
|
|
1460
|
+
color: i < currentRate ? "var(--sg-color-warning, #faad14)" : "var(--sg-color-border, #d9d9d9)",
|
|
1387
1461
|
padding: 0
|
|
1388
1462
|
},
|
|
1389
1463
|
"aria-label": `${i + 1} star${i !== 0 ? "s" : ""}`,
|
|
@@ -1404,7 +1478,7 @@ function AutoField(props) {
|
|
|
1404
1478
|
if (files) handleChange(multiple ? Array.from(files) : files[0] ?? null);
|
|
1405
1479
|
},
|
|
1406
1480
|
disabled,
|
|
1407
|
-
|
|
1481
|
+
className: inputClass
|
|
1408
1482
|
}
|
|
1409
1483
|
);
|
|
1410
1484
|
case "email":
|
|
@@ -1420,18 +1494,26 @@ function AutoField(props) {
|
|
|
1420
1494
|
onBlur: () => form.onFieldBlur(name),
|
|
1421
1495
|
placeholder,
|
|
1422
1496
|
disabled,
|
|
1423
|
-
|
|
1497
|
+
className: inputClass,
|
|
1424
1498
|
"aria-invalid": hasErrors,
|
|
1425
1499
|
"aria-describedby": hasErrors ? errorId : void 0
|
|
1426
1500
|
}
|
|
1427
1501
|
);
|
|
1428
1502
|
}
|
|
1429
1503
|
}
|
|
1430
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `sg-autofield ${className ?? ""}`, style
|
|
1431
|
-
inferredType !== "boolean" && inferredType !== "switch" && label && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("label", {
|
|
1504
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `sg-autofield ${className ?? ""}`, style, children: [
|
|
1505
|
+
inferredType !== "boolean" && inferredType !== "switch" && label && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("label", { className: "sg-autofield-label", children: label }),
|
|
1432
1506
|
renderInput(),
|
|
1433
|
-
hasErrors && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1434
|
-
|
|
1507
|
+
hasErrors && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1508
|
+
"span",
|
|
1509
|
+
{
|
|
1510
|
+
id: errorId,
|
|
1511
|
+
role: "alert",
|
|
1512
|
+
style: { color: "var(--sg-color-error, #ff4d4f)", fontSize: 12 },
|
|
1513
|
+
children: meta.errors.join("; ")
|
|
1514
|
+
}
|
|
1515
|
+
),
|
|
1516
|
+
hasWarnings && !hasErrors && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { color: "var(--sg-color-warning, #faad14)", fontSize: 12 }, children: meta.warnings.join("; ") })
|
|
1435
1517
|
] });
|
|
1436
1518
|
}
|
|
1437
1519
|
|