@wipco/sdui 0.44.0 → 0.46.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 +144 -47
- package/dist/meta.d.ts +1 -1
- package/dist/{types-Bx3oingj.d.ts → types-C6cOUNPz.d.ts} +21 -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-C6cOUNPz.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-C6cOUNPz.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
|
@@ -1953,7 +1953,8 @@ function evaluateCalc(calc, resolved, resolve) {
|
|
|
1953
1953
|
}
|
|
1954
1954
|
case "split": {
|
|
1955
1955
|
const sep = typeof calc.sep === "string" ? calc.sep : ",";
|
|
1956
|
-
|
|
1956
|
+
let parts = String(first ?? "").split(sep);
|
|
1957
|
+
if (calc.trim === true) parts = parts.map((part) => part.trim());
|
|
1957
1958
|
if (calc.take === void 0) return parts;
|
|
1958
1959
|
const index = toNumber2(calc.take);
|
|
1959
1960
|
const at = index < 0 ? parts.length + index : index;
|
|
@@ -2017,6 +2018,84 @@ async function runRequestAction(action, deps) {
|
|
|
2017
2018
|
}
|
|
2018
2019
|
}
|
|
2019
2020
|
|
|
2021
|
+
// src/state-path.ts
|
|
2022
|
+
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
2023
|
+
function isPlainObject2(value) {
|
|
2024
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2025
|
+
}
|
|
2026
|
+
function normalizeSegment(raw) {
|
|
2027
|
+
if (typeof raw === "number") {
|
|
2028
|
+
return Number.isInteger(raw) && raw >= 0 ? raw : null;
|
|
2029
|
+
}
|
|
2030
|
+
if (typeof raw !== "string" || raw.trim() === "") return null;
|
|
2031
|
+
if (FORBIDDEN_KEYS.has(raw)) return null;
|
|
2032
|
+
const asNumber = Number(raw);
|
|
2033
|
+
if (Number.isInteger(asNumber) && asNumber >= 0 && String(asNumber) === raw) return asNumber;
|
|
2034
|
+
return raw;
|
|
2035
|
+
}
|
|
2036
|
+
function setAtPath(root, path, value) {
|
|
2037
|
+
if (path.length === 0) return { ok: true, next: value };
|
|
2038
|
+
const segments = [];
|
|
2039
|
+
for (const raw of path) {
|
|
2040
|
+
const segment = normalizeSegment(raw);
|
|
2041
|
+
if (segment === null) {
|
|
2042
|
+
return {
|
|
2043
|
+
ok: false,
|
|
2044
|
+
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)`
|
|
2045
|
+
};
|
|
2046
|
+
}
|
|
2047
|
+
segments.push(segment);
|
|
2048
|
+
}
|
|
2049
|
+
const write = (container, depth) => {
|
|
2050
|
+
const segment = segments[depth];
|
|
2051
|
+
const last = depth === segments.length - 1;
|
|
2052
|
+
if (typeof segment === "number") {
|
|
2053
|
+
if (!Array.isArray(container)) {
|
|
2054
|
+
return {
|
|
2055
|
+
ok: false,
|
|
2056
|
+
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`
|
|
2057
|
+
};
|
|
2058
|
+
}
|
|
2059
|
+
if (segment >= container.length) {
|
|
2060
|
+
return {
|
|
2061
|
+
ok: false,
|
|
2062
|
+
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`
|
|
2063
|
+
};
|
|
2064
|
+
}
|
|
2065
|
+
const nextChild2 = last ? { ok: true, next: value } : write(container[segment] ?? null, depth + 1);
|
|
2066
|
+
if (!nextChild2.ok) return nextChild2;
|
|
2067
|
+
const copy = container.slice();
|
|
2068
|
+
copy[segment] = nextChild2.next;
|
|
2069
|
+
return { ok: true, next: copy };
|
|
2070
|
+
}
|
|
2071
|
+
if (Array.isArray(container)) {
|
|
2072
|
+
return {
|
|
2073
|
+
ok: false,
|
|
2074
|
+
reason: `${describe(segments, depth)}: \uBC30\uC5F4\uC5D0 \uBB38\uC790\uC5F4 \uD0A4 '${segment}'\uB85C \uB4E4\uC5B4\uAC08 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4`
|
|
2075
|
+
};
|
|
2076
|
+
}
|
|
2077
|
+
if (container !== null && container !== void 0 && !isPlainObject2(container)) {
|
|
2078
|
+
return {
|
|
2079
|
+
ok: false,
|
|
2080
|
+
reason: `${describe(segments, depth)}: \uAC1D\uCCB4\uAC00 \uC544\uB2CC \uAC12(${typeof container}) \uC548\uC73C\uB85C \uB4E4\uC5B4\uAC08 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4`
|
|
2081
|
+
};
|
|
2082
|
+
}
|
|
2083
|
+
const base = isPlainObject2(container) ? container : {};
|
|
2084
|
+
const nextChild = last ? { ok: true, next: value } : write(base[segment] ?? null, depth + 1);
|
|
2085
|
+
if (!nextChild.ok) return nextChild;
|
|
2086
|
+
return { ok: true, next: { ...base, [segment]: nextChild.next } };
|
|
2087
|
+
};
|
|
2088
|
+
return write(root, 0);
|
|
2089
|
+
}
|
|
2090
|
+
function describe(segments, upto) {
|
|
2091
|
+
let out = "";
|
|
2092
|
+
for (let i = 0; i <= upto; i += 1) {
|
|
2093
|
+
const segment = segments[i];
|
|
2094
|
+
out += typeof segment === "number" ? `[${segment}]` : out === "" ? String(segment) : `.${segment}`;
|
|
2095
|
+
}
|
|
2096
|
+
return out;
|
|
2097
|
+
}
|
|
2098
|
+
|
|
2020
2099
|
// src/validate.ts
|
|
2021
2100
|
var ACTION_NAMES = /* @__PURE__ */ new Set([
|
|
2022
2101
|
"navigate",
|
|
@@ -2055,7 +2134,7 @@ var DENIED_PROPS = /* @__PURE__ */ new Set([
|
|
|
2055
2134
|
"constructor",
|
|
2056
2135
|
"prototype"
|
|
2057
2136
|
]);
|
|
2058
|
-
function
|
|
2137
|
+
function isPlainObject3(v) {
|
|
2059
2138
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
2060
2139
|
}
|
|
2061
2140
|
function checkUrlValue(key, value, path, issues) {
|
|
@@ -2065,7 +2144,7 @@ function checkUrlValue(key, value, path, issues) {
|
|
|
2065
2144
|
}
|
|
2066
2145
|
function validateSpec(page, knownComponents, slotNamesOf) {
|
|
2067
2146
|
const issues = [];
|
|
2068
|
-
if (!
|
|
2147
|
+
if (!isPlainObject3(page)) return [{ path: "$", message: "\uC2A4\uD399\uC774 \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4" }];
|
|
2069
2148
|
if (page.version !== 1) issues.push({ path: "$.version", message: "version\uC740 1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4" });
|
|
2070
2149
|
validatePageData(page.data, issues);
|
|
2071
2150
|
if (!Array.isArray(page.body)) {
|
|
@@ -2079,7 +2158,7 @@ function validateSpec(page, knownComponents, slotNamesOf) {
|
|
|
2079
2158
|
}
|
|
2080
2159
|
function validatePageData(data, issues) {
|
|
2081
2160
|
if (data === void 0) return;
|
|
2082
|
-
if (!
|
|
2161
|
+
if (!isPlainObject3(data)) {
|
|
2083
2162
|
issues.push({ path: "$.data", message: "data\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2084
2163
|
return;
|
|
2085
2164
|
}
|
|
@@ -2089,7 +2168,7 @@ function validatePageData(data, issues) {
|
|
|
2089
2168
|
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" });
|
|
2090
2169
|
continue;
|
|
2091
2170
|
}
|
|
2092
|
-
if (!
|
|
2171
|
+
if (!isPlainObject3(raw)) {
|
|
2093
2172
|
issues.push({ path, message: "\uC870\uD68C\uB294 { endpoint, select?, when?, fallback? } \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2094
2173
|
continue;
|
|
2095
2174
|
}
|
|
@@ -2101,7 +2180,7 @@ function validatePageData(data, issues) {
|
|
|
2101
2180
|
} else if (!raw.endpoint.startsWith("/")) {
|
|
2102
2181
|
issues.push({ path: `${path}.endpoint`, message: "endpoint\uB294 /\uB85C \uC2DC\uC791\uD558\uB294 \uACBD\uB85C\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2103
2182
|
}
|
|
2104
|
-
} else if (!
|
|
2183
|
+
} else if (!isPlainObject3(raw.endpoint)) {
|
|
2105
2184
|
issues.push({ path: `${path}.endpoint`, message: "endpoint\uB294 \uBB38\uC790\uC5F4\uC774\uAC70\uB098 \uAC12 \uCC38\uC870\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2106
2185
|
} else {
|
|
2107
2186
|
walkValue(raw.endpoint, `${path}.endpoint`, issues, false);
|
|
@@ -2124,7 +2203,7 @@ function validatePageData(data, issues) {
|
|
|
2124
2203
|
}
|
|
2125
2204
|
function walkChild(child, path, issues, known, slotNamesOf) {
|
|
2126
2205
|
if (typeof child === "string") return;
|
|
2127
|
-
if (!
|
|
2206
|
+
if (!isPlainObject3(child)) {
|
|
2128
2207
|
issues.push({ path, message: "children \uD56D\uBAA9\uC740 \uBB38\uC790\uC5F4 \uB610\uB294 \uB178\uB4DC \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2129
2208
|
return;
|
|
2130
2209
|
}
|
|
@@ -2136,7 +2215,7 @@ function walkChild(child, path, issues, known, slotNamesOf) {
|
|
|
2136
2215
|
if (known && !RENDERER_BUILTINS.has(node.component) && !known.has(node.component)) {
|
|
2137
2216
|
issues.push({ path, message: `\uB4F1\uB85D\uB418\uC9C0 \uC54A\uC740 \uCEF4\uD3EC\uB10C\uD2B8: ${node.component}` });
|
|
2138
2217
|
}
|
|
2139
|
-
if (node.props !== void 0 && !
|
|
2218
|
+
if (node.props !== void 0 && !isPlainObject3(node.props)) {
|
|
2140
2219
|
issues.push({ path: `${path}.props`, message: "props\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2141
2220
|
}
|
|
2142
2221
|
for (const [name, value] of Object.entries(node.props ?? {})) {
|
|
@@ -2150,9 +2229,9 @@ function walkChild(child, path, issues, known, slotNamesOf) {
|
|
|
2150
2229
|
checkUrlValue(name, value, `${path}.props.${name}`, issues);
|
|
2151
2230
|
walkValue(value, `${path}.props.${name}`, issues, name.startsWith("on") || name === "rowClick");
|
|
2152
2231
|
}
|
|
2153
|
-
if (node.component === "Form" &&
|
|
2232
|
+
if (node.component === "Form" && isPlainObject3(node.props) && node.props.rules !== void 0) {
|
|
2154
2233
|
const rules = node.props.rules;
|
|
2155
|
-
if (!
|
|
2234
|
+
if (!isPlainObject3(rules)) {
|
|
2156
2235
|
issues.push({ path: `${path}.props.rules`, message: "rules\uB294 { \uD544\uB4DC: \uADDC\uCE59\uBC30\uC5F4 } \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2157
2236
|
} else {
|
|
2158
2237
|
for (const [field, list] of Object.entries(rules)) {
|
|
@@ -2163,15 +2242,15 @@ function walkChild(child, path, issues, known, slotNamesOf) {
|
|
|
2163
2242
|
}
|
|
2164
2243
|
}
|
|
2165
2244
|
if (node.component === "Fragment") {
|
|
2166
|
-
const id =
|
|
2167
|
-
if ((typeof id !== "string" || id === "") && !
|
|
2245
|
+
const id = isPlainObject3(node.props) ? node.props.id : void 0;
|
|
2246
|
+
if ((typeof id !== "string" || id === "") && !isPlainObject3(id)) {
|
|
2168
2247
|
issues.push({
|
|
2169
2248
|
path: `${path}.props.id`,
|
|
2170
2249
|
message: "Fragment.id\uB294 \uBE44\uC5B4 \uC788\uC9C0 \uC54A\uC740 \uBB38\uC790\uC5F4(\uB610\uB294 \uAC12 \uCC38\uC870)\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4"
|
|
2171
2250
|
});
|
|
2172
2251
|
}
|
|
2173
|
-
const args =
|
|
2174
|
-
if (args !== void 0 && !
|
|
2252
|
+
const args = isPlainObject3(node.props) ? node.props.args : void 0;
|
|
2253
|
+
if (args !== void 0 && !isPlainObject3(args)) {
|
|
2175
2254
|
issues.push({
|
|
2176
2255
|
path: `${path}.props.args`,
|
|
2177
2256
|
message: "Fragment.args\uB294 { \uC774\uB984: \uAC12 } \uD3C9\uBA74 \uC624\uBE0C\uC81D\uD2B8\uC5EC\uC57C \uD569\uB2C8\uB2E4"
|
|
@@ -2185,7 +2264,7 @@ function walkChild(child, path, issues, known, slotNamesOf) {
|
|
|
2185
2264
|
}
|
|
2186
2265
|
}
|
|
2187
2266
|
if (node.slots !== void 0) {
|
|
2188
|
-
if (!
|
|
2267
|
+
if (!isPlainObject3(node.slots)) {
|
|
2189
2268
|
issues.push({ path: `${path}.slots`, message: "slots\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
2190
2269
|
} else {
|
|
2191
2270
|
const slotNames = slotNamesOf?.(node.component) ?? null;
|
|
@@ -2221,7 +2300,7 @@ function walkValue(value, path, issues, actionEligible) {
|
|
|
2221
2300
|
value.forEach((v, i) => walkValue(v, `${path}[${i}]`, issues, actionEligible));
|
|
2222
2301
|
return;
|
|
2223
2302
|
}
|
|
2224
|
-
if (!
|
|
2303
|
+
if (!isPlainObject3(value)) return;
|
|
2225
2304
|
if (typeof value.action === "string" && (actionEligible || ACTION_NAMES.has(value.action))) {
|
|
2226
2305
|
if (actionEligible && !ACTION_NAMES.has(value.action)) {
|
|
2227
2306
|
issues.push({ path, message: `\uC54C \uC218 \uC5C6\uB294 \uC561\uC158: ${value.action}` });
|
|
@@ -2248,7 +2327,7 @@ function walkValue(value, path, issues, actionEligible) {
|
|
|
2248
2327
|
}
|
|
2249
2328
|
if ("$calc" in value) {
|
|
2250
2329
|
const calc = value.$calc;
|
|
2251
|
-
if (!
|
|
2330
|
+
if (!isPlainObject3(calc) || typeof calc.op !== "string" || !CALC_OPS.has(calc.op)) {
|
|
2252
2331
|
issues.push({ path, message: "$calc.op\uC774 \uC720\uD6A8\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4" });
|
|
2253
2332
|
} else if (!Array.isArray(calc.args)) {
|
|
2254
2333
|
issues.push({ path: `${path}.$calc.args`, message: "args\uB294 \uBC30\uC5F4\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4" });
|
|
@@ -2277,12 +2356,12 @@ function walkValue(value, path, issues, actionEligible) {
|
|
|
2277
2356
|
}
|
|
2278
2357
|
|
|
2279
2358
|
// src/page-data.ts
|
|
2280
|
-
function
|
|
2359
|
+
function isPlainObject4(value) {
|
|
2281
2360
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2282
2361
|
}
|
|
2283
2362
|
function planPageData(data, resolve) {
|
|
2284
2363
|
if (data === void 0) return [];
|
|
2285
|
-
if (!
|
|
2364
|
+
if (!isPlainObject4(data)) {
|
|
2286
2365
|
warnOnce("page-data:root", "[sdui] page.data\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4 \u2014 \uBB34\uC2DC\uD569\uB2C8\uB2E4");
|
|
2287
2366
|
return [];
|
|
2288
2367
|
}
|
|
@@ -2292,7 +2371,7 @@ function planPageData(data, resolve) {
|
|
|
2292
2371
|
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`);
|
|
2293
2372
|
continue;
|
|
2294
2373
|
}
|
|
2295
|
-
if (!
|
|
2374
|
+
if (!isPlainObject4(raw)) {
|
|
2296
2375
|
warnOnce(`page-data:${key}`, `[sdui] page.data.${key}\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4 \u2014 \uAC74\uB108\uB701\uB2C8\uB2E4`);
|
|
2297
2376
|
continue;
|
|
2298
2377
|
}
|
|
@@ -2327,7 +2406,7 @@ function pickPath(source, path) {
|
|
|
2327
2406
|
if (path === void 0 || path === "") return source;
|
|
2328
2407
|
let value = source;
|
|
2329
2408
|
for (const segment of path.split(".")) {
|
|
2330
|
-
if (!
|
|
2409
|
+
if (!isPlainObject4(value)) return void 0;
|
|
2331
2410
|
value = value[segment];
|
|
2332
2411
|
}
|
|
2333
2412
|
return value;
|
|
@@ -2358,26 +2437,26 @@ function nearestArgsFrame(scope) {
|
|
|
2358
2437
|
}
|
|
2359
2438
|
return void 0;
|
|
2360
2439
|
}
|
|
2361
|
-
function
|
|
2440
|
+
function isPlainObject5(v) {
|
|
2362
2441
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
2363
2442
|
}
|
|
2364
2443
|
function isStateRef(v) {
|
|
2365
|
-
return
|
|
2444
|
+
return isPlainObject5(v) && typeof v.$state === "string";
|
|
2366
2445
|
}
|
|
2367
2446
|
function isItemRef(v) {
|
|
2368
|
-
return
|
|
2447
|
+
return isPlainObject5(v) && "$item" in v;
|
|
2369
2448
|
}
|
|
2370
2449
|
function isIndexRef(v) {
|
|
2371
|
-
return
|
|
2450
|
+
return isPlainObject5(v) && "$index" in v;
|
|
2372
2451
|
}
|
|
2373
2452
|
function isCalcRef(v) {
|
|
2374
|
-
return
|
|
2453
|
+
return isPlainObject5(v) && isPlainObject5(v.$calc);
|
|
2375
2454
|
}
|
|
2376
2455
|
function isArgRef(v) {
|
|
2377
|
-
return
|
|
2456
|
+
return isPlainObject5(v) && typeof v.$arg === "string";
|
|
2378
2457
|
}
|
|
2379
2458
|
function isAction(v) {
|
|
2380
|
-
return
|
|
2459
|
+
return isPlainObject5(v) && typeof v.action === "string";
|
|
2381
2460
|
}
|
|
2382
2461
|
function isActionList(v) {
|
|
2383
2462
|
return Array.isArray(v) && v.length > 0 && v.every(isAction);
|
|
@@ -2401,7 +2480,7 @@ function expandActionEntries(raw, scope) {
|
|
|
2401
2480
|
return [];
|
|
2402
2481
|
}
|
|
2403
2482
|
function eventValue(arg) {
|
|
2404
|
-
if (
|
|
2483
|
+
if (isPlainObject5(arg) && "target" in arg && typeof arg.preventDefault === "function") {
|
|
2405
2484
|
const target = arg.target;
|
|
2406
2485
|
if (target.type === "checkbox") return target.checked;
|
|
2407
2486
|
if (target.type === "number" || target.type === "range") {
|
|
@@ -2511,7 +2590,7 @@ function childrenOf(node) {
|
|
|
2511
2590
|
}
|
|
2512
2591
|
function renderChild(child, index, scope, engine) {
|
|
2513
2592
|
if (typeof child === "string") return child;
|
|
2514
|
-
if (!
|
|
2593
|
+
if (!isPlainObject5(child)) {
|
|
2515
2594
|
warnOnce2(`child:${String(child)}`, `[sdui] \uC798\uBABB\uB41C \uB178\uB4DC(\uBB38\uC790\uC5F4 \uB610\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4): ${String(child)}`);
|
|
2516
2595
|
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);
|
|
2517
2596
|
}
|
|
@@ -2526,11 +2605,11 @@ function SduiNodeRenderer({
|
|
|
2526
2605
|
engine
|
|
2527
2606
|
}) {
|
|
2528
2607
|
const { registry, resolveValue, dispatch, resolveAsset } = engine;
|
|
2529
|
-
const slots =
|
|
2608
|
+
const slots = isPlainObject5(node.slots) ? node.slots : void 0;
|
|
2530
2609
|
const childList = childrenOf(node);
|
|
2531
2610
|
if (node.component === "ForEach") {
|
|
2532
2611
|
const source = resolveValue(
|
|
2533
|
-
|
|
2612
|
+
isPlainObject5(node.props) ? node.props.source ?? null : null,
|
|
2534
2613
|
scope
|
|
2535
2614
|
);
|
|
2536
2615
|
const rows = Array.isArray(source) ? source : [];
|
|
@@ -2540,7 +2619,7 @@ function SduiNodeRenderer({
|
|
|
2540
2619
|
}
|
|
2541
2620
|
return /* @__PURE__ */ jsx(Fragment, { children: rows.map((item, rowIndex) => {
|
|
2542
2621
|
const rowScope = [...scope, { item, index: rowIndex }];
|
|
2543
|
-
const rowKey =
|
|
2622
|
+
const rowKey = isPlainObject5(item) && typeof item.id === "string" ? item.id : rowIndex;
|
|
2544
2623
|
return /* @__PURE__ */ jsx(React9.Fragment, { children: childList?.map((child, i) => renderChild(child, i, rowScope, engine)) }, rowKey);
|
|
2545
2624
|
}) });
|
|
2546
2625
|
}
|
|
@@ -2559,7 +2638,7 @@ function SduiNodeRenderer({
|
|
|
2559
2638
|
] });
|
|
2560
2639
|
}
|
|
2561
2640
|
const props = {};
|
|
2562
|
-
for (const [name, raw] of Object.entries(
|
|
2641
|
+
for (const [name, raw] of Object.entries(isPlainObject5(node.props) ? node.props : {})) {
|
|
2563
2642
|
if (DENIED_PROPS2.has(name)) {
|
|
2564
2643
|
warnOnce2(`prop:${name}`, `[sdui] \uC2A4\uD399\uC5D0\uC11C \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uB294 \uD504\uB86D: ${name} \u2014 \uBB34\uC2DC\uD569\uB2C8\uB2E4`);
|
|
2565
2644
|
continue;
|
|
@@ -2598,7 +2677,7 @@ function SduiNodeRenderer({
|
|
|
2598
2677
|
if (childLayout) {
|
|
2599
2678
|
for (const name of CHILD_LAYOUT_PROPS) delete props[name];
|
|
2600
2679
|
if (childLayout.style) {
|
|
2601
|
-
props.style =
|
|
2680
|
+
props.style = isPlainObject5(props.style) ? { ...childLayout.style, ...props.style } : childLayout.style;
|
|
2602
2681
|
}
|
|
2603
2682
|
if (childLayout.className) {
|
|
2604
2683
|
props.className = typeof props.className === "string" && props.className ? `${childLayout.className} ${props.className}` : childLayout.className;
|
|
@@ -2622,7 +2701,7 @@ var FRAGMENT_MAX_DEPTH = 4;
|
|
|
2622
2701
|
function SduiFragment({ node, scope, engine }) {
|
|
2623
2702
|
const adapter = useSduiAdapter();
|
|
2624
2703
|
const chain = React9.useContext(SduiFragmentChainContext);
|
|
2625
|
-
const raw =
|
|
2704
|
+
const raw = isPlainObject5(node.props) ? node.props.id : void 0;
|
|
2626
2705
|
const id = engine.resolveValue(raw, scope);
|
|
2627
2706
|
if (typeof id !== "string" || id === "") {
|
|
2628
2707
|
warnOnce2("fragment:id", "[sdui] <Fragment>\uC5D0 \uBB38\uC790\uC5F4 id\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uB80C\uB354\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
@@ -2642,8 +2721,8 @@ function SduiFragment({ node, scope, engine }) {
|
|
|
2642
2721
|
);
|
|
2643
2722
|
return null;
|
|
2644
2723
|
}
|
|
2645
|
-
const rawArgs =
|
|
2646
|
-
if (rawArgs !== void 0 && !
|
|
2724
|
+
const rawArgs = isPlainObject5(node.props) ? node.props.args : void 0;
|
|
2725
|
+
if (rawArgs !== void 0 && !isPlainObject5(rawArgs)) {
|
|
2647
2726
|
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`);
|
|
2648
2727
|
}
|
|
2649
2728
|
const useSpec = adapter?.useSpec;
|
|
@@ -2658,7 +2737,7 @@ function SduiFragment({ node, scope, engine }) {
|
|
|
2658
2737
|
SduiFragmentBody,
|
|
2659
2738
|
{
|
|
2660
2739
|
id,
|
|
2661
|
-
args:
|
|
2740
|
+
args: isPlainObject5(rawArgs) ? rawArgs : void 0,
|
|
2662
2741
|
useSpec,
|
|
2663
2742
|
chain,
|
|
2664
2743
|
scope,
|
|
@@ -2679,13 +2758,13 @@ function SduiFragmentBody({
|
|
|
2679
2758
|
const nextChain = React9.useMemo(() => [...chain, id], [chain, id]);
|
|
2680
2759
|
const bodyScope = React9.useMemo(() => [...scope, { args, callSiteScope: scope }], [scope, args]);
|
|
2681
2760
|
React9.useEffect(() => {
|
|
2682
|
-
if (!DEV || !
|
|
2761
|
+
if (!DEV || !isPlainObject5(spec) || !Array.isArray(spec.body)) return;
|
|
2683
2762
|
validateSpec(spec, new Set(Object.keys(engine.registry))).forEach(
|
|
2684
2763
|
(issue) => console.warn(`[sdui:spec:${id}] ${issue.path} \u2014 ${issue.message}`)
|
|
2685
2764
|
);
|
|
2686
2765
|
}, [spec, engine.registry, id]);
|
|
2687
2766
|
if (spec === void 0) return null;
|
|
2688
|
-
if (spec === null || !
|
|
2767
|
+
if (spec === null || !isPlainObject5(spec) || !Array.isArray(spec.body)) {
|
|
2689
2768
|
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`);
|
|
2690
2769
|
return null;
|
|
2691
2770
|
}
|
|
@@ -2815,7 +2894,7 @@ function SduiRenderer({
|
|
|
2815
2894
|
if (head in current) {
|
|
2816
2895
|
let value = current[head];
|
|
2817
2896
|
for (const segment of segments.slice(cut)) {
|
|
2818
|
-
if (!
|
|
2897
|
+
if (!isPlainObject5(value)) return void 0;
|
|
2819
2898
|
value = value[segment];
|
|
2820
2899
|
}
|
|
2821
2900
|
return value;
|
|
@@ -2833,7 +2912,7 @@ function SduiRenderer({
|
|
|
2833
2912
|
const frame = nearestItemFrame(scope);
|
|
2834
2913
|
if (!frame) return null;
|
|
2835
2914
|
if (value.$item === true) return frame.item;
|
|
2836
|
-
return
|
|
2915
|
+
return isPlainObject5(frame.item) ? frame.item[value.$item] ?? null : null;
|
|
2837
2916
|
}
|
|
2838
2917
|
if (isIndexRef(value)) {
|
|
2839
2918
|
return nearestItemFrame(scope)?.index ?? null;
|
|
@@ -2857,7 +2936,7 @@ function SduiRenderer({
|
|
|
2857
2936
|
return evaluateCalc(calc, resolved, (late) => resolveValue(late, scope));
|
|
2858
2937
|
}
|
|
2859
2938
|
if (Array.isArray(value)) return value.map((v) => resolveValue(v, scope));
|
|
2860
|
-
if (
|
|
2939
|
+
if (isPlainObject5(value)) {
|
|
2861
2940
|
const out = {};
|
|
2862
2941
|
for (const [k, v] of Object.entries(value)) {
|
|
2863
2942
|
out[k] = deferChainEntry(value, k) ? v : resolveValue(v, scope);
|
|
@@ -2965,9 +3044,27 @@ function SduiRenderer({
|
|
|
2965
3044
|
}
|
|
2966
3045
|
hostRef.current.navigate(action.to);
|
|
2967
3046
|
break;
|
|
2968
|
-
case "setState":
|
|
2969
|
-
|
|
3047
|
+
case "setState": {
|
|
3048
|
+
const nextValue = action.fromEvent ? eventValue(arg) : action.value;
|
|
3049
|
+
if (!Array.isArray(action.path) || action.path.length === 0) {
|
|
3050
|
+
setEntries({ [action.key]: nextValue });
|
|
3051
|
+
break;
|
|
3052
|
+
}
|
|
3053
|
+
const written = setAtPath(
|
|
3054
|
+
stateRef.current[action.key],
|
|
3055
|
+
action.path,
|
|
3056
|
+
nextValue
|
|
3057
|
+
);
|
|
3058
|
+
if (!written.ok) {
|
|
3059
|
+
warnOnce2(
|
|
3060
|
+
`setState:${action.key}:${written.reason}`,
|
|
3061
|
+
`[sdui] setState(${action.key}) \uACBD\uB85C \uC4F0\uAE30\uB97C \uAC74\uB108\uB701\uB2C8\uB2E4 \u2014 ${written.reason}`
|
|
3062
|
+
);
|
|
3063
|
+
break;
|
|
3064
|
+
}
|
|
3065
|
+
setEntries({ [action.key]: written.next });
|
|
2970
3066
|
break;
|
|
3067
|
+
}
|
|
2971
3068
|
case "open":
|
|
2972
3069
|
setEntries({ [action.key]: true });
|
|
2973
3070
|
break;
|
|
@@ -3026,7 +3123,7 @@ function SduiRenderer({
|
|
|
3026
3123
|
break;
|
|
3027
3124
|
}
|
|
3028
3125
|
const row = current[index];
|
|
3029
|
-
if (!
|
|
3126
|
+
if (!isPlainObject5(row)) break;
|
|
3030
3127
|
const nextValue = (action.fromEvent ? eventValue(arg) : action.value) ?? null;
|
|
3031
3128
|
const next = [...current];
|
|
3032
3129
|
next[index] = { ...row, [action.field]: nextValue };
|
package/dist/meta.d.ts
CHANGED
|
@@ -129,6 +129,11 @@ interface SduiCalcRef {
|
|
|
129
129
|
sep?: string;
|
|
130
130
|
/** `split`에서 꺼낼 조각의 인덱스. 음수는 뒤에서부터 센다 */
|
|
131
131
|
take?: number;
|
|
132
|
+
/**
|
|
133
|
+
* `split`의 조각에서 앞뒤 공백을 턴다. 사람이 치는 쉼표 목록("S, A, B")이
|
|
134
|
+
* 이 연산의 주된 입력인데, 그 조각이 **키로 쓰이면** 공백 하나가 사고가 된다.
|
|
135
|
+
*/
|
|
136
|
+
trim?: boolean;
|
|
132
137
|
/** `sortBy`를 내림차순으로 */
|
|
133
138
|
desc?: boolean;
|
|
134
139
|
};
|
|
@@ -175,6 +180,22 @@ type SduiAction = {
|
|
|
175
180
|
} | {
|
|
176
181
|
action: 'setState';
|
|
177
182
|
key: string;
|
|
183
|
+
/**
|
|
184
|
+
* 상태 항목 **안쪽 자리**. 주면 항목 전체가 아니라 그 자리만 바꾼다.
|
|
185
|
+
*
|
|
186
|
+
* 조각은 객체 키(문자열)나 배열 인덱스(0 이상 정수)이고, 값 참조를 그대로 쓸 수
|
|
187
|
+
* 있다 — 액션 객체 전체가 디스패치 직전에 풀리기 때문이다:
|
|
188
|
+
*
|
|
189
|
+
* ```json
|
|
190
|
+
* { "action": "setState", "key": "gdRules", "fromEvent": true,
|
|
191
|
+
* "path": [{ "$index": true }, "limits", { "$item": true }, "count"] }
|
|
192
|
+
* ```
|
|
193
|
+
*
|
|
194
|
+
* 이것이 없으면 **동적 키**(등급 이름처럼 사용자가 런타임에 타이핑하는 키)와
|
|
195
|
+
* **중첩 쓰기**(`arrayUpdate`는 최상위 배열의 평탄 필드 하나만 바꾼다)를 스펙으로
|
|
196
|
+
* 말할 수 없었다. 규칙과 거절 조건은 `state-path.ts` 머리말에 있다.
|
|
197
|
+
*/
|
|
198
|
+
path?: SduiPropValue[];
|
|
178
199
|
value?: SduiPropValue;
|
|
179
200
|
/** true면 이벤트 값(input value, 선택된 탭 value, 페이지 번호 등)을 그대로 저장한다. */
|
|
180
201
|
fromEvent?: boolean;
|