@wipco/sdui 0.43.0 → 0.45.0
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/index.d.ts +2 -2
- package/dist/index.js +147 -48
- package/dist/meta.d.ts +1 -1
- package/dist/{types-Bx3oingj.d.ts → types--y5jCOV5.d.ts} +16 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import React__default, { CSSProperties, ReactNode, ComponentType } from 'react';
|
|
3
|
-
import { S as SduiPage, a as SduiAction, b as SduiPropValue, c as SduiRule } from './types
|
|
4
|
-
export { d as SduiArgRef, e as SduiCalcRef, f as SduiChild, g as SduiIndexRef, h as SduiItemRef, i as SduiNode, j as SduiPageQuery, k as SduiScalar, l as SduiStateRef } from './types
|
|
3
|
+
import { S as SduiPage, a as SduiAction, b as SduiPropValue, c as SduiRule } from './types--y5jCOV5.js';
|
|
4
|
+
export { d as SduiArgRef, e as SduiCalcRef, f as SduiChild, g as SduiIndexRef, h as SduiItemRef, i as SduiNode, j as SduiPageQuery, k as SduiScalar, l as SduiStateRef } from './types--y5jCOV5.js';
|
|
5
5
|
import { S as SduiBoxProps, a as SduiContainerLayoutProps, b as SduiColumnsScale, c as SduiGapScale, d as SduiWeightScale, e as SduiTextAlignScale } from './layout-C3nRXMwb.js';
|
|
6
6
|
export { C as CHILD_LAYOUT_PROPS, L as LAYOUT_CSS, f as SduiAlignScale, g as SduiChildLayoutProps, h as SduiSizeScale, i as SduiSpanScale, j as childLayoutFrom, k as columnsClass, l as containerLayoutStyle, m as joinClass, n as mergeStyle, t as typographyStyle } from './layout-C3nRXMwb.js';
|
|
7
7
|
import { D as DatePickerProps, a as DateRangePickerProps, T as TimePickerProps } from './DatePicker-BK_jsV7i.js';
|
package/dist/index.js
CHANGED
|
@@ -1863,13 +1863,16 @@ function evaluateCalc(calc, resolved, resolve) {
|
|
|
1863
1863
|
/* ── 목록·객체 ── */
|
|
1864
1864
|
case "get": {
|
|
1865
1865
|
const [container, rawKey] = resolved;
|
|
1866
|
-
const key = rawKey == null ? "" : String(rawKey);
|
|
1867
1866
|
if (Array.isArray(container)) {
|
|
1868
|
-
|
|
1867
|
+
if (typeof rawKey !== "number" && (typeof rawKey !== "string" || rawKey.trim() === "")) {
|
|
1868
|
+
return null;
|
|
1869
|
+
}
|
|
1870
|
+
const index = Number(rawKey);
|
|
1869
1871
|
if (!Number.isInteger(index) || index < 0 || index >= container.length) return null;
|
|
1870
1872
|
return container[index] ?? null;
|
|
1871
1873
|
}
|
|
1872
1874
|
if (isPlainObject(container)) {
|
|
1875
|
+
const key = rawKey == null ? "" : String(rawKey);
|
|
1873
1876
|
return Object.hasOwn(container, key) ? container[key] ?? null : null;
|
|
1874
1877
|
}
|
|
1875
1878
|
return null;
|
|
@@ -2014,6 +2017,84 @@ async function runRequestAction(action, deps) {
|
|
|
2014
2017
|
}
|
|
2015
2018
|
}
|
|
2016
2019
|
|
|
2020
|
+
// src/state-path.ts
|
|
2021
|
+
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
2022
|
+
function isPlainObject2(value) {
|
|
2023
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2024
|
+
}
|
|
2025
|
+
function normalizeSegment(raw) {
|
|
2026
|
+
if (typeof raw === "number") {
|
|
2027
|
+
return Number.isInteger(raw) && raw >= 0 ? raw : null;
|
|
2028
|
+
}
|
|
2029
|
+
if (typeof raw !== "string" || raw.trim() === "") return null;
|
|
2030
|
+
if (FORBIDDEN_KEYS.has(raw)) return null;
|
|
2031
|
+
const asNumber = Number(raw);
|
|
2032
|
+
if (Number.isInteger(asNumber) && asNumber >= 0 && String(asNumber) === raw) return asNumber;
|
|
2033
|
+
return raw;
|
|
2034
|
+
}
|
|
2035
|
+
function setAtPath(root, path, value) {
|
|
2036
|
+
if (path.length === 0) return { ok: true, next: value };
|
|
2037
|
+
const segments = [];
|
|
2038
|
+
for (const raw of path) {
|
|
2039
|
+
const segment = normalizeSegment(raw);
|
|
2040
|
+
if (segment === null) {
|
|
2041
|
+
return {
|
|
2042
|
+
ok: false,
|
|
2043
|
+
reason: `\uACBD\uB85C \uC870\uAC01\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: ${JSON.stringify(raw)} (\uBE44\uC5B4 \uC788\uC9C0 \uC54A\uC740 \uBB38\uC790\uC5F4\uC774\uB098 0 \uC774\uC0C1 \uC815\uC218\uC5EC\uC57C \uD569\uB2C8\uB2E4)`
|
|
2044
|
+
};
|
|
2045
|
+
}
|
|
2046
|
+
segments.push(segment);
|
|
2047
|
+
}
|
|
2048
|
+
const write = (container, depth) => {
|
|
2049
|
+
const segment = segments[depth];
|
|
2050
|
+
const last = depth === segments.length - 1;
|
|
2051
|
+
if (typeof segment === "number") {
|
|
2052
|
+
if (!Array.isArray(container)) {
|
|
2053
|
+
return {
|
|
2054
|
+
ok: false,
|
|
2055
|
+
reason: `${describe(segments, depth)}: \uBC30\uC5F4\uC774 \uC544\uB2CC \uC790\uB9AC\uC5D0 \uC778\uB371\uC2A4 ${segment}\uB85C \uB4E4\uC5B4\uAC08 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4`
|
|
2056
|
+
};
|
|
2057
|
+
}
|
|
2058
|
+
if (segment >= container.length) {
|
|
2059
|
+
return {
|
|
2060
|
+
ok: false,
|
|
2061
|
+
reason: `${describe(segments, depth)}: \uC778\uB371\uC2A4 ${segment}\uAC00 \uBC94\uC704 \uBC16\uC785\uB2C8\uB2E4(\uAE38\uC774 ${container.length}) \u2014 \uBC30\uC5F4\uC744 \uC778\uB371\uC2A4\uB85C \uB298\uB9AC\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`
|
|
2062
|
+
};
|
|
2063
|
+
}
|
|
2064
|
+
const nextChild2 = last ? { ok: true, next: value } : write(container[segment] ?? null, depth + 1);
|
|
2065
|
+
if (!nextChild2.ok) return nextChild2;
|
|
2066
|
+
const copy = container.slice();
|
|
2067
|
+
copy[segment] = nextChild2.next;
|
|
2068
|
+
return { ok: true, next: copy };
|
|
2069
|
+
}
|
|
2070
|
+
if (Array.isArray(container)) {
|
|
2071
|
+
return {
|
|
2072
|
+
ok: false,
|
|
2073
|
+
reason: `${describe(segments, depth)}: \uBC30\uC5F4\uC5D0 \uBB38\uC790\uC5F4 \uD0A4 '${segment}'\uB85C \uB4E4\uC5B4\uAC08 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4`
|
|
2074
|
+
};
|
|
2075
|
+
}
|
|
2076
|
+
if (container !== null && container !== void 0 && !isPlainObject2(container)) {
|
|
2077
|
+
return {
|
|
2078
|
+
ok: false,
|
|
2079
|
+
reason: `${describe(segments, depth)}: \uAC1D\uCCB4\uAC00 \uC544\uB2CC \uAC12(${typeof container}) \uC548\uC73C\uB85C \uB4E4\uC5B4\uAC08 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4`
|
|
2080
|
+
};
|
|
2081
|
+
}
|
|
2082
|
+
const base = isPlainObject2(container) ? container : {};
|
|
2083
|
+
const nextChild = last ? { ok: true, next: value } : write(base[segment] ?? null, depth + 1);
|
|
2084
|
+
if (!nextChild.ok) return nextChild;
|
|
2085
|
+
return { ok: true, next: { ...base, [segment]: nextChild.next } };
|
|
2086
|
+
};
|
|
2087
|
+
return write(root, 0);
|
|
2088
|
+
}
|
|
2089
|
+
function describe(segments, upto) {
|
|
2090
|
+
let out = "";
|
|
2091
|
+
for (let i = 0; i <= upto; i += 1) {
|
|
2092
|
+
const segment = segments[i];
|
|
2093
|
+
out += typeof segment === "number" ? `[${segment}]` : out === "" ? String(segment) : `.${segment}`;
|
|
2094
|
+
}
|
|
2095
|
+
return out;
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2017
2098
|
// src/validate.ts
|
|
2018
2099
|
var ACTION_NAMES = /* @__PURE__ */ new Set([
|
|
2019
2100
|
"navigate",
|
|
@@ -2052,7 +2133,7 @@ var DENIED_PROPS = /* @__PURE__ */ new Set([
|
|
|
2052
2133
|
"constructor",
|
|
2053
2134
|
"prototype"
|
|
2054
2135
|
]);
|
|
2055
|
-
function
|
|
2136
|
+
function isPlainObject3(v) {
|
|
2056
2137
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
2057
2138
|
}
|
|
2058
2139
|
function checkUrlValue(key, value, path, issues) {
|
|
@@ -2062,7 +2143,7 @@ function checkUrlValue(key, value, path, issues) {
|
|
|
2062
2143
|
}
|
|
2063
2144
|
function validateSpec(page, knownComponents, slotNamesOf) {
|
|
2064
2145
|
const issues = [];
|
|
2065
|
-
if (!
|
|
2146
|
+
if (!isPlainObject3(page)) return [{ path: "$", message: "\uC2A4\uD399\uC774 \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4" }];
|
|
2066
2147
|
if (page.version !== 1) issues.push({ path: "$.version", message: "version\uC740 1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4" });
|
|
2067
2148
|
validatePageData(page.data, issues);
|
|
2068
2149
|
if (!Array.isArray(page.body)) {
|
|
@@ -2076,7 +2157,7 @@ function validateSpec(page, knownComponents, slotNamesOf) {
|
|
|
2076
2157
|
}
|
|
2077
2158
|
function validatePageData(data, issues) {
|
|
2078
2159
|
if (data === void 0) return;
|
|
2079
|
-
if (!
|
|
2160
|
+
if (!isPlainObject3(data)) {
|
|
2080
2161
|
issues.push({ path: "$.data", message: "data\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2081
2162
|
return;
|
|
2082
2163
|
}
|
|
@@ -2086,7 +2167,7 @@ function validatePageData(data, issues) {
|
|
|
2086
2167
|
issues.push({ path, message: "\uC0C1\uD0DC \uD0A4\uB294 \uBE44\uC5B4 \uC788\uC9C0 \uC54A\uC544\uC57C \uD558\uACE0 $\uB85C \uC2DC\uC791\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4" });
|
|
2087
2168
|
continue;
|
|
2088
2169
|
}
|
|
2089
|
-
if (!
|
|
2170
|
+
if (!isPlainObject3(raw)) {
|
|
2090
2171
|
issues.push({ path, message: "\uC870\uD68C\uB294 { endpoint, select?, when?, fallback? } \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2091
2172
|
continue;
|
|
2092
2173
|
}
|
|
@@ -2098,7 +2179,7 @@ function validatePageData(data, issues) {
|
|
|
2098
2179
|
} else if (!raw.endpoint.startsWith("/")) {
|
|
2099
2180
|
issues.push({ path: `${path}.endpoint`, message: "endpoint\uB294 /\uB85C \uC2DC\uC791\uD558\uB294 \uACBD\uB85C\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2100
2181
|
}
|
|
2101
|
-
} else if (!
|
|
2182
|
+
} else if (!isPlainObject3(raw.endpoint)) {
|
|
2102
2183
|
issues.push({ path: `${path}.endpoint`, message: "endpoint\uB294 \uBB38\uC790\uC5F4\uC774\uAC70\uB098 \uAC12 \uCC38\uC870\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2103
2184
|
} else {
|
|
2104
2185
|
walkValue(raw.endpoint, `${path}.endpoint`, issues, false);
|
|
@@ -2121,7 +2202,7 @@ function validatePageData(data, issues) {
|
|
|
2121
2202
|
}
|
|
2122
2203
|
function walkChild(child, path, issues, known, slotNamesOf) {
|
|
2123
2204
|
if (typeof child === "string") return;
|
|
2124
|
-
if (!
|
|
2205
|
+
if (!isPlainObject3(child)) {
|
|
2125
2206
|
issues.push({ path, message: "children \uD56D\uBAA9\uC740 \uBB38\uC790\uC5F4 \uB610\uB294 \uB178\uB4DC \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2126
2207
|
return;
|
|
2127
2208
|
}
|
|
@@ -2133,7 +2214,7 @@ function walkChild(child, path, issues, known, slotNamesOf) {
|
|
|
2133
2214
|
if (known && !RENDERER_BUILTINS.has(node.component) && !known.has(node.component)) {
|
|
2134
2215
|
issues.push({ path, message: `\uB4F1\uB85D\uB418\uC9C0 \uC54A\uC740 \uCEF4\uD3EC\uB10C\uD2B8: ${node.component}` });
|
|
2135
2216
|
}
|
|
2136
|
-
if (node.props !== void 0 && !
|
|
2217
|
+
if (node.props !== void 0 && !isPlainObject3(node.props)) {
|
|
2137
2218
|
issues.push({ path: `${path}.props`, message: "props\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2138
2219
|
}
|
|
2139
2220
|
for (const [name, value] of Object.entries(node.props ?? {})) {
|
|
@@ -2147,9 +2228,9 @@ function walkChild(child, path, issues, known, slotNamesOf) {
|
|
|
2147
2228
|
checkUrlValue(name, value, `${path}.props.${name}`, issues);
|
|
2148
2229
|
walkValue(value, `${path}.props.${name}`, issues, name.startsWith("on") || name === "rowClick");
|
|
2149
2230
|
}
|
|
2150
|
-
if (node.component === "Form" &&
|
|
2231
|
+
if (node.component === "Form" && isPlainObject3(node.props) && node.props.rules !== void 0) {
|
|
2151
2232
|
const rules = node.props.rules;
|
|
2152
|
-
if (!
|
|
2233
|
+
if (!isPlainObject3(rules)) {
|
|
2153
2234
|
issues.push({ path: `${path}.props.rules`, message: "rules\uB294 { \uD544\uB4DC: \uADDC\uCE59\uBC30\uC5F4 } \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2154
2235
|
} else {
|
|
2155
2236
|
for (const [field, list] of Object.entries(rules)) {
|
|
@@ -2160,15 +2241,15 @@ function walkChild(child, path, issues, known, slotNamesOf) {
|
|
|
2160
2241
|
}
|
|
2161
2242
|
}
|
|
2162
2243
|
if (node.component === "Fragment") {
|
|
2163
|
-
const id =
|
|
2164
|
-
if ((typeof id !== "string" || id === "") && !
|
|
2244
|
+
const id = isPlainObject3(node.props) ? node.props.id : void 0;
|
|
2245
|
+
if ((typeof id !== "string" || id === "") && !isPlainObject3(id)) {
|
|
2165
2246
|
issues.push({
|
|
2166
2247
|
path: `${path}.props.id`,
|
|
2167
2248
|
message: "Fragment.id\uB294 \uBE44\uC5B4 \uC788\uC9C0 \uC54A\uC740 \uBB38\uC790\uC5F4(\uB610\uB294 \uAC12 \uCC38\uC870)\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4"
|
|
2168
2249
|
});
|
|
2169
2250
|
}
|
|
2170
|
-
const args =
|
|
2171
|
-
if (args !== void 0 && !
|
|
2251
|
+
const args = isPlainObject3(node.props) ? node.props.args : void 0;
|
|
2252
|
+
if (args !== void 0 && !isPlainObject3(args)) {
|
|
2172
2253
|
issues.push({
|
|
2173
2254
|
path: `${path}.props.args`,
|
|
2174
2255
|
message: "Fragment.args\uB294 { \uC774\uB984: \uAC12 } \uD3C9\uBA74 \uC624\uBE0C\uC81D\uD2B8\uC5EC\uC57C \uD569\uB2C8\uB2E4"
|
|
@@ -2182,7 +2263,7 @@ function walkChild(child, path, issues, known, slotNamesOf) {
|
|
|
2182
2263
|
}
|
|
2183
2264
|
}
|
|
2184
2265
|
if (node.slots !== void 0) {
|
|
2185
|
-
if (!
|
|
2266
|
+
if (!isPlainObject3(node.slots)) {
|
|
2186
2267
|
issues.push({ path: `${path}.slots`, message: "slots\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2187
2268
|
} else {
|
|
2188
2269
|
const slotNames = slotNamesOf?.(node.component) ?? null;
|
|
@@ -2218,7 +2299,7 @@ function walkValue(value, path, issues, actionEligible) {
|
|
|
2218
2299
|
value.forEach((v, i) => walkValue(v, `${path}[${i}]`, issues, actionEligible));
|
|
2219
2300
|
return;
|
|
2220
2301
|
}
|
|
2221
|
-
if (!
|
|
2302
|
+
if (!isPlainObject3(value)) return;
|
|
2222
2303
|
if (typeof value.action === "string" && (actionEligible || ACTION_NAMES.has(value.action))) {
|
|
2223
2304
|
if (actionEligible && !ACTION_NAMES.has(value.action)) {
|
|
2224
2305
|
issues.push({ path, message: `\uC54C \uC218 \uC5C6\uB294 \uC561\uC158: ${value.action}` });
|
|
@@ -2245,7 +2326,7 @@ function walkValue(value, path, issues, actionEligible) {
|
|
|
2245
2326
|
}
|
|
2246
2327
|
if ("$calc" in value) {
|
|
2247
2328
|
const calc = value.$calc;
|
|
2248
|
-
if (!
|
|
2329
|
+
if (!isPlainObject3(calc) || typeof calc.op !== "string" || !CALC_OPS.has(calc.op)) {
|
|
2249
2330
|
issues.push({ path, message: "$calc.op\uC774 \uC720\uD6A8\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4" });
|
|
2250
2331
|
} else if (!Array.isArray(calc.args)) {
|
|
2251
2332
|
issues.push({ path: `${path}.$calc.args`, message: "args\uB294 \uBC30\uC5F4\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4" });
|
|
@@ -2274,12 +2355,12 @@ function walkValue(value, path, issues, actionEligible) {
|
|
|
2274
2355
|
}
|
|
2275
2356
|
|
|
2276
2357
|
// src/page-data.ts
|
|
2277
|
-
function
|
|
2358
|
+
function isPlainObject4(value) {
|
|
2278
2359
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2279
2360
|
}
|
|
2280
2361
|
function planPageData(data, resolve) {
|
|
2281
2362
|
if (data === void 0) return [];
|
|
2282
|
-
if (!
|
|
2363
|
+
if (!isPlainObject4(data)) {
|
|
2283
2364
|
warnOnce("page-data:root", "[sdui] page.data\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4 \u2014 \uBB34\uC2DC\uD569\uB2C8\uB2E4");
|
|
2284
2365
|
return [];
|
|
2285
2366
|
}
|
|
@@ -2289,7 +2370,7 @@ function planPageData(data, resolve) {
|
|
|
2289
2370
|
warnOnce(`page-data:${key}`, `[sdui] page.data\uC758 \uC0C1\uD0DC \uD0A4 "${key}"\uB294 \uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uAC74\uB108\uB701\uB2C8\uB2E4`);
|
|
2290
2371
|
continue;
|
|
2291
2372
|
}
|
|
2292
|
-
if (!
|
|
2373
|
+
if (!isPlainObject4(raw)) {
|
|
2293
2374
|
warnOnce(`page-data:${key}`, `[sdui] page.data.${key}\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4 \u2014 \uAC74\uB108\uB701\uB2C8\uB2E4`);
|
|
2294
2375
|
continue;
|
|
2295
2376
|
}
|
|
@@ -2324,7 +2405,7 @@ function pickPath(source, path) {
|
|
|
2324
2405
|
if (path === void 0 || path === "") return source;
|
|
2325
2406
|
let value = source;
|
|
2326
2407
|
for (const segment of path.split(".")) {
|
|
2327
|
-
if (!
|
|
2408
|
+
if (!isPlainObject4(value)) return void 0;
|
|
2328
2409
|
value = value[segment];
|
|
2329
2410
|
}
|
|
2330
2411
|
return value;
|
|
@@ -2355,26 +2436,26 @@ function nearestArgsFrame(scope) {
|
|
|
2355
2436
|
}
|
|
2356
2437
|
return void 0;
|
|
2357
2438
|
}
|
|
2358
|
-
function
|
|
2439
|
+
function isPlainObject5(v) {
|
|
2359
2440
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
2360
2441
|
}
|
|
2361
2442
|
function isStateRef(v) {
|
|
2362
|
-
return
|
|
2443
|
+
return isPlainObject5(v) && typeof v.$state === "string";
|
|
2363
2444
|
}
|
|
2364
2445
|
function isItemRef(v) {
|
|
2365
|
-
return
|
|
2446
|
+
return isPlainObject5(v) && "$item" in v;
|
|
2366
2447
|
}
|
|
2367
2448
|
function isIndexRef(v) {
|
|
2368
|
-
return
|
|
2449
|
+
return isPlainObject5(v) && "$index" in v;
|
|
2369
2450
|
}
|
|
2370
2451
|
function isCalcRef(v) {
|
|
2371
|
-
return
|
|
2452
|
+
return isPlainObject5(v) && isPlainObject5(v.$calc);
|
|
2372
2453
|
}
|
|
2373
2454
|
function isArgRef(v) {
|
|
2374
|
-
return
|
|
2455
|
+
return isPlainObject5(v) && typeof v.$arg === "string";
|
|
2375
2456
|
}
|
|
2376
2457
|
function isAction(v) {
|
|
2377
|
-
return
|
|
2458
|
+
return isPlainObject5(v) && typeof v.action === "string";
|
|
2378
2459
|
}
|
|
2379
2460
|
function isActionList(v) {
|
|
2380
2461
|
return Array.isArray(v) && v.length > 0 && v.every(isAction);
|
|
@@ -2398,7 +2479,7 @@ function expandActionEntries(raw, scope) {
|
|
|
2398
2479
|
return [];
|
|
2399
2480
|
}
|
|
2400
2481
|
function eventValue(arg) {
|
|
2401
|
-
if (
|
|
2482
|
+
if (isPlainObject5(arg) && "target" in arg && typeof arg.preventDefault === "function") {
|
|
2402
2483
|
const target = arg.target;
|
|
2403
2484
|
if (target.type === "checkbox") return target.checked;
|
|
2404
2485
|
if (target.type === "number" || target.type === "range") {
|
|
@@ -2508,7 +2589,7 @@ function childrenOf(node) {
|
|
|
2508
2589
|
}
|
|
2509
2590
|
function renderChild(child, index, scope, engine) {
|
|
2510
2591
|
if (typeof child === "string") return child;
|
|
2511
|
-
if (!
|
|
2592
|
+
if (!isPlainObject5(child)) {
|
|
2512
2593
|
warnOnce2(`child:${String(child)}`, `[sdui] \uC798\uBABB\uB41C \uB178\uB4DC(\uBB38\uC790\uC5F4 \uB610\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4): ${String(child)}`);
|
|
2513
2594
|
return /* @__PURE__ */ jsx(SpecErrorCard, { children: "[sdui] \uC798\uBABB\uB41C \uB178\uB4DC \u2014 \uBB38\uC790\uC5F4 \uB610\uB294 \uB178\uB4DC \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" }, index);
|
|
2514
2595
|
}
|
|
@@ -2523,11 +2604,11 @@ function SduiNodeRenderer({
|
|
|
2523
2604
|
engine
|
|
2524
2605
|
}) {
|
|
2525
2606
|
const { registry, resolveValue, dispatch, resolveAsset } = engine;
|
|
2526
|
-
const slots =
|
|
2607
|
+
const slots = isPlainObject5(node.slots) ? node.slots : void 0;
|
|
2527
2608
|
const childList = childrenOf(node);
|
|
2528
2609
|
if (node.component === "ForEach") {
|
|
2529
2610
|
const source = resolveValue(
|
|
2530
|
-
|
|
2611
|
+
isPlainObject5(node.props) ? node.props.source ?? null : null,
|
|
2531
2612
|
scope
|
|
2532
2613
|
);
|
|
2533
2614
|
const rows = Array.isArray(source) ? source : [];
|
|
@@ -2537,7 +2618,7 @@ function SduiNodeRenderer({
|
|
|
2537
2618
|
}
|
|
2538
2619
|
return /* @__PURE__ */ jsx(Fragment, { children: rows.map((item, rowIndex) => {
|
|
2539
2620
|
const rowScope = [...scope, { item, index: rowIndex }];
|
|
2540
|
-
const rowKey =
|
|
2621
|
+
const rowKey = isPlainObject5(item) && typeof item.id === "string" ? item.id : rowIndex;
|
|
2541
2622
|
return /* @__PURE__ */ jsx(React9.Fragment, { children: childList?.map((child, i) => renderChild(child, i, rowScope, engine)) }, rowKey);
|
|
2542
2623
|
}) });
|
|
2543
2624
|
}
|
|
@@ -2556,7 +2637,7 @@ function SduiNodeRenderer({
|
|
|
2556
2637
|
] });
|
|
2557
2638
|
}
|
|
2558
2639
|
const props = {};
|
|
2559
|
-
for (const [name, raw] of Object.entries(
|
|
2640
|
+
for (const [name, raw] of Object.entries(isPlainObject5(node.props) ? node.props : {})) {
|
|
2560
2641
|
if (DENIED_PROPS2.has(name)) {
|
|
2561
2642
|
warnOnce2(`prop:${name}`, `[sdui] \uC2A4\uD399\uC5D0\uC11C \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uB294 \uD504\uB86D: ${name} \u2014 \uBB34\uC2DC\uD569\uB2C8\uB2E4`);
|
|
2562
2643
|
continue;
|
|
@@ -2595,7 +2676,7 @@ function SduiNodeRenderer({
|
|
|
2595
2676
|
if (childLayout) {
|
|
2596
2677
|
for (const name of CHILD_LAYOUT_PROPS) delete props[name];
|
|
2597
2678
|
if (childLayout.style) {
|
|
2598
|
-
props.style =
|
|
2679
|
+
props.style = isPlainObject5(props.style) ? { ...childLayout.style, ...props.style } : childLayout.style;
|
|
2599
2680
|
}
|
|
2600
2681
|
if (childLayout.className) {
|
|
2601
2682
|
props.className = typeof props.className === "string" && props.className ? `${childLayout.className} ${props.className}` : childLayout.className;
|
|
@@ -2619,7 +2700,7 @@ var FRAGMENT_MAX_DEPTH = 4;
|
|
|
2619
2700
|
function SduiFragment({ node, scope, engine }) {
|
|
2620
2701
|
const adapter = useSduiAdapter();
|
|
2621
2702
|
const chain = React9.useContext(SduiFragmentChainContext);
|
|
2622
|
-
const raw =
|
|
2703
|
+
const raw = isPlainObject5(node.props) ? node.props.id : void 0;
|
|
2623
2704
|
const id = engine.resolveValue(raw, scope);
|
|
2624
2705
|
if (typeof id !== "string" || id === "") {
|
|
2625
2706
|
warnOnce2("fragment:id", "[sdui] <Fragment>\uC5D0 \uBB38\uC790\uC5F4 id\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uB80C\uB354\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
@@ -2639,8 +2720,8 @@ function SduiFragment({ node, scope, engine }) {
|
|
|
2639
2720
|
);
|
|
2640
2721
|
return null;
|
|
2641
2722
|
}
|
|
2642
|
-
const rawArgs =
|
|
2643
|
-
if (rawArgs !== void 0 && !
|
|
2723
|
+
const rawArgs = isPlainObject5(node.props) ? node.props.args : void 0;
|
|
2724
|
+
if (rawArgs !== void 0 && !isPlainObject5(rawArgs)) {
|
|
2644
2725
|
warnOnce2(`fragment:args:${id}`, `[sdui] <Fragment ${id}>\uC758 args\uB294 \uD3C9\uBA74 \uC624\uBE0C\uC81D\uD2B8\uC5EC\uC57C \uD569\uB2C8\uB2E4 \u2014 \uBB34\uC2DC\uD569\uB2C8\uB2E4`);
|
|
2645
2726
|
}
|
|
2646
2727
|
const useSpec = adapter?.useSpec;
|
|
@@ -2655,7 +2736,7 @@ function SduiFragment({ node, scope, engine }) {
|
|
|
2655
2736
|
SduiFragmentBody,
|
|
2656
2737
|
{
|
|
2657
2738
|
id,
|
|
2658
|
-
args:
|
|
2739
|
+
args: isPlainObject5(rawArgs) ? rawArgs : void 0,
|
|
2659
2740
|
useSpec,
|
|
2660
2741
|
chain,
|
|
2661
2742
|
scope,
|
|
@@ -2676,13 +2757,13 @@ function SduiFragmentBody({
|
|
|
2676
2757
|
const nextChain = React9.useMemo(() => [...chain, id], [chain, id]);
|
|
2677
2758
|
const bodyScope = React9.useMemo(() => [...scope, { args, callSiteScope: scope }], [scope, args]);
|
|
2678
2759
|
React9.useEffect(() => {
|
|
2679
|
-
if (!DEV || !
|
|
2760
|
+
if (!DEV || !isPlainObject5(spec) || !Array.isArray(spec.body)) return;
|
|
2680
2761
|
validateSpec(spec, new Set(Object.keys(engine.registry))).forEach(
|
|
2681
2762
|
(issue) => console.warn(`[sdui:spec:${id}] ${issue.path} \u2014 ${issue.message}`)
|
|
2682
2763
|
);
|
|
2683
2764
|
}, [spec, engine.registry, id]);
|
|
2684
2765
|
if (spec === void 0) return null;
|
|
2685
|
-
if (spec === null || !
|
|
2766
|
+
if (spec === null || !isPlainObject5(spec) || !Array.isArray(spec.body)) {
|
|
2686
2767
|
warnOnce2(`fragment:missing:${id}`, `[sdui] Fragment \uC2A4\uD399\uC744 \uD574\uC11D\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${id} \u2014 \uB80C\uB354\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`);
|
|
2687
2768
|
return null;
|
|
2688
2769
|
}
|
|
@@ -2812,7 +2893,7 @@ function SduiRenderer({
|
|
|
2812
2893
|
if (head in current) {
|
|
2813
2894
|
let value = current[head];
|
|
2814
2895
|
for (const segment of segments.slice(cut)) {
|
|
2815
|
-
if (!
|
|
2896
|
+
if (!isPlainObject5(value)) return void 0;
|
|
2816
2897
|
value = value[segment];
|
|
2817
2898
|
}
|
|
2818
2899
|
return value;
|
|
@@ -2830,7 +2911,7 @@ function SduiRenderer({
|
|
|
2830
2911
|
const frame = nearestItemFrame(scope);
|
|
2831
2912
|
if (!frame) return null;
|
|
2832
2913
|
if (value.$item === true) return frame.item;
|
|
2833
|
-
return
|
|
2914
|
+
return isPlainObject5(frame.item) ? frame.item[value.$item] ?? null : null;
|
|
2834
2915
|
}
|
|
2835
2916
|
if (isIndexRef(value)) {
|
|
2836
2917
|
return nearestItemFrame(scope)?.index ?? null;
|
|
@@ -2854,7 +2935,7 @@ function SduiRenderer({
|
|
|
2854
2935
|
return evaluateCalc(calc, resolved, (late) => resolveValue(late, scope));
|
|
2855
2936
|
}
|
|
2856
2937
|
if (Array.isArray(value)) return value.map((v) => resolveValue(v, scope));
|
|
2857
|
-
if (
|
|
2938
|
+
if (isPlainObject5(value)) {
|
|
2858
2939
|
const out = {};
|
|
2859
2940
|
for (const [k, v] of Object.entries(value)) {
|
|
2860
2941
|
out[k] = deferChainEntry(value, k) ? v : resolveValue(v, scope);
|
|
@@ -2962,9 +3043,27 @@ function SduiRenderer({
|
|
|
2962
3043
|
}
|
|
2963
3044
|
hostRef.current.navigate(action.to);
|
|
2964
3045
|
break;
|
|
2965
|
-
case "setState":
|
|
2966
|
-
|
|
3046
|
+
case "setState": {
|
|
3047
|
+
const nextValue = action.fromEvent ? eventValue(arg) : action.value;
|
|
3048
|
+
if (!Array.isArray(action.path) || action.path.length === 0) {
|
|
3049
|
+
setEntries({ [action.key]: nextValue });
|
|
3050
|
+
break;
|
|
3051
|
+
}
|
|
3052
|
+
const written = setAtPath(
|
|
3053
|
+
stateRef.current[action.key],
|
|
3054
|
+
action.path,
|
|
3055
|
+
nextValue
|
|
3056
|
+
);
|
|
3057
|
+
if (!written.ok) {
|
|
3058
|
+
warnOnce2(
|
|
3059
|
+
`setState:${action.key}:${written.reason}`,
|
|
3060
|
+
`[sdui] setState(${action.key}) \uACBD\uB85C \uC4F0\uAE30\uB97C \uAC74\uB108\uB701\uB2C8\uB2E4 \u2014 ${written.reason}`
|
|
3061
|
+
);
|
|
3062
|
+
break;
|
|
3063
|
+
}
|
|
3064
|
+
setEntries({ [action.key]: written.next });
|
|
2967
3065
|
break;
|
|
3066
|
+
}
|
|
2968
3067
|
case "open":
|
|
2969
3068
|
setEntries({ [action.key]: true });
|
|
2970
3069
|
break;
|
|
@@ -3023,7 +3122,7 @@ function SduiRenderer({
|
|
|
3023
3122
|
break;
|
|
3024
3123
|
}
|
|
3025
3124
|
const row = current[index];
|
|
3026
|
-
if (!
|
|
3125
|
+
if (!isPlainObject5(row)) break;
|
|
3027
3126
|
const nextValue = (action.fromEvent ? eventValue(arg) : action.value) ?? null;
|
|
3028
3127
|
const next = [...current];
|
|
3029
3128
|
next[index] = { ...row, [action.field]: nextValue };
|
package/dist/meta.d.ts
CHANGED
|
@@ -175,6 +175,22 @@ type SduiAction = {
|
|
|
175
175
|
} | {
|
|
176
176
|
action: 'setState';
|
|
177
177
|
key: string;
|
|
178
|
+
/**
|
|
179
|
+
* 상태 항목 **안쪽 자리**. 주면 항목 전체가 아니라 그 자리만 바꾼다.
|
|
180
|
+
*
|
|
181
|
+
* 조각은 객체 키(문자열)나 배열 인덱스(0 이상 정수)이고, 값 참조를 그대로 쓸 수
|
|
182
|
+
* 있다 — 액션 객체 전체가 디스패치 직전에 풀리기 때문이다:
|
|
183
|
+
*
|
|
184
|
+
* ```json
|
|
185
|
+
* { "action": "setState", "key": "gdRules", "fromEvent": true,
|
|
186
|
+
* "path": [{ "$index": true }, "limits", { "$item": true }, "count"] }
|
|
187
|
+
* ```
|
|
188
|
+
*
|
|
189
|
+
* 이것이 없으면 **동적 키**(등급 이름처럼 사용자가 런타임에 타이핑하는 키)와
|
|
190
|
+
* **중첩 쓰기**(`arrayUpdate`는 최상위 배열의 평탄 필드 하나만 바꾼다)를 스펙으로
|
|
191
|
+
* 말할 수 없었다. 규칙과 거절 조건은 `state-path.ts` 머리말에 있다.
|
|
192
|
+
*/
|
|
193
|
+
path?: SduiPropValue[];
|
|
178
194
|
value?: SduiPropValue;
|
|
179
195
|
/** true면 이벤트 값(input value, 선택된 탭 value, 페이지 번호 등)을 그대로 저장한다. */
|
|
180
196
|
fromEvent?: boolean;
|