@wipco/sdui 0.20.0 → 0.22.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/chunk-K3JBSWFI.js +133 -0
- package/dist/{chunk-HPZTFZZN.js → chunk-PNVOE5VH.js} +2 -95
- package/dist/chunk-WGRB5UL4.js +99 -0
- package/dist/{chunk-SRGXODY2.js → chunk-WZKDOZL2.js} +30 -5
- package/dist/index.d.ts +9 -3
- package/dist/index.js +358 -123
- package/dist/meta.d.ts +9 -7
- package/dist/meta.js +151 -4
- package/dist/rich.js +2 -2
- package/dist/{types-opTPYysN.d.ts → types-BNdv5-jn.d.ts} +59 -3
- package/dist/widgets/AutocompleteField.d.ts +29 -2
- package/dist/widgets/AutocompleteField.js +2 -1
- package/dist/widgets/RecordSheet.d.ts +59 -0
- package/dist/widgets/RecordSheet.js +2 -0
- package/dist/widgets/index.d.ts +4 -1
- package/dist/widgets/index.js +9 -5
- package/package.json +5 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { TimePicker
|
|
1
|
+
import { TimePicker } from './chunk-PNVOE5VH.js';
|
|
2
|
+
export { TimePicker } from './chunk-PNVOE5VH.js';
|
|
3
3
|
import { ImageViewer } from './chunk-THEP3VWY.js';
|
|
4
4
|
export { ImageViewer } from './chunk-THEP3VWY.js';
|
|
5
5
|
import { normalizeSearchFields, searchValuesFromParams, splitMultiValue, includesLooseSearch, cascadingValuePaths, SearchToolbar, searchFieldKeys, Popover } from './chunk-U7ZK7WYH.js';
|
|
6
6
|
export { SearchToolbar, cascadingValuePaths, cleanSearchValues, includesLooseSearch, joinMultiValue, normalizeSearchText, searchFieldKeys, searchValuesFromParams, splitMultiValue } from './chunk-U7ZK7WYH.js';
|
|
7
|
+
import { DEV, isSafeNavigationTarget, useSduiAdapter, hostFetchOf, useSduiSandbox, resolveAdapter, assetResolverOf, SduiAdapterContext } from './chunk-WGRB5UL4.js';
|
|
8
|
+
export { defaultAdapter, useSduiAssetResolver, useSduiSandbox } from './chunk-WGRB5UL4.js';
|
|
7
9
|
import { HoistedStyle, DateRangePicker, DatePicker, OverlayLayer } from './chunk-XKLUCUVA.js';
|
|
8
10
|
export { DatePicker, DateRangePicker, OverlayContainerContext, OverlayLayer, getOverlayRoot, useOverlayLayer } from './chunk-XKLUCUVA.js';
|
|
9
11
|
import { EmptyState, Button, Checkbox, SegmentedControl, Spinner, Select, Pagination, Icon, Card, Badge, ProgressBar, Tag, Toast, Textarea, Tabs, Table, Switch, StatCard, Input, IconButton, Field, Alert, warnOnce, Dialog } from './chunk-WIDDHR7L.js';
|
|
@@ -1783,6 +1785,310 @@ function createRegistry(extensions) {
|
|
|
1783
1785
|
return { ...defaultRegistry, ...extensions };
|
|
1784
1786
|
}
|
|
1785
1787
|
|
|
1788
|
+
// src/calc.ts
|
|
1789
|
+
function isPlainObject(v) {
|
|
1790
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
1791
|
+
}
|
|
1792
|
+
function toNumber2(v) {
|
|
1793
|
+
if (typeof v === "number") return v;
|
|
1794
|
+
if (typeof v === "string") {
|
|
1795
|
+
const n = Number(v.replace(/,/g, ""));
|
|
1796
|
+
return Number.isFinite(n) ? n : 0;
|
|
1797
|
+
}
|
|
1798
|
+
return 0;
|
|
1799
|
+
}
|
|
1800
|
+
function isNumericText(v) {
|
|
1801
|
+
if (typeof v === "number") return true;
|
|
1802
|
+
if (typeof v !== "string" || v === "") return false;
|
|
1803
|
+
return Number.isFinite(Number(v.replace(/,/g, "")));
|
|
1804
|
+
}
|
|
1805
|
+
function orderingCompare(a, b) {
|
|
1806
|
+
if (typeof a === "string" && typeof b === "string" && !isNumericText(a) && !isNumericText(b)) {
|
|
1807
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
1808
|
+
}
|
|
1809
|
+
const x = toNumber2(a);
|
|
1810
|
+
const y = toNumber2(b);
|
|
1811
|
+
return x < y ? -1 : x > y ? 1 : 0;
|
|
1812
|
+
}
|
|
1813
|
+
function looseEquals(a, b) {
|
|
1814
|
+
return String(a ?? "") === String(b ?? "");
|
|
1815
|
+
}
|
|
1816
|
+
function isBlank(v) {
|
|
1817
|
+
return v === null || v === void 0 || v === "";
|
|
1818
|
+
}
|
|
1819
|
+
function fieldOf(row, field) {
|
|
1820
|
+
if (!field) return row;
|
|
1821
|
+
if (!isPlainObject(row)) return void 0;
|
|
1822
|
+
return Object.hasOwn(row, field) ? row[field] : void 0;
|
|
1823
|
+
}
|
|
1824
|
+
var FIELD_OPS = /* @__PURE__ */ new Set([
|
|
1825
|
+
"eq",
|
|
1826
|
+
"ne",
|
|
1827
|
+
"gt",
|
|
1828
|
+
"gte",
|
|
1829
|
+
"lt",
|
|
1830
|
+
"lte",
|
|
1831
|
+
"in",
|
|
1832
|
+
"notIn",
|
|
1833
|
+
"contains",
|
|
1834
|
+
"startsWith",
|
|
1835
|
+
"endsWith",
|
|
1836
|
+
"isNull"
|
|
1837
|
+
]);
|
|
1838
|
+
function isFieldOpObject(v) {
|
|
1839
|
+
return isPlainObject(v) && Object.keys(v).some((key) => FIELD_OPS.has(key));
|
|
1840
|
+
}
|
|
1841
|
+
function matchesFieldOps(actual, ops, resolve) {
|
|
1842
|
+
return Object.entries(ops).every(([op, rawExpected]) => {
|
|
1843
|
+
if (!FIELD_OPS.has(op)) return true;
|
|
1844
|
+
const expected = resolve(rawExpected);
|
|
1845
|
+
switch (op) {
|
|
1846
|
+
case "eq":
|
|
1847
|
+
return looseEquals(actual, expected);
|
|
1848
|
+
case "ne":
|
|
1849
|
+
return !looseEquals(actual, expected);
|
|
1850
|
+
case "gt":
|
|
1851
|
+
return orderingCompare(actual, expected) > 0;
|
|
1852
|
+
case "gte":
|
|
1853
|
+
return orderingCompare(actual, expected) >= 0;
|
|
1854
|
+
case "lt":
|
|
1855
|
+
return orderingCompare(actual, expected) < 0;
|
|
1856
|
+
case "lte":
|
|
1857
|
+
return orderingCompare(actual, expected) <= 0;
|
|
1858
|
+
case "in":
|
|
1859
|
+
return Array.isArray(expected) && expected.some((item) => looseEquals(actual, item));
|
|
1860
|
+
case "notIn":
|
|
1861
|
+
return !Array.isArray(expected) || !expected.some((item) => looseEquals(actual, item));
|
|
1862
|
+
case "contains":
|
|
1863
|
+
return String(actual ?? "").includes(String(expected ?? ""));
|
|
1864
|
+
case "startsWith":
|
|
1865
|
+
return String(actual ?? "").startsWith(String(expected ?? ""));
|
|
1866
|
+
case "endsWith":
|
|
1867
|
+
return String(actual ?? "").endsWith(String(expected ?? ""));
|
|
1868
|
+
case "isNull":
|
|
1869
|
+
return isBlank(actual) === Boolean(expected);
|
|
1870
|
+
default:
|
|
1871
|
+
return true;
|
|
1872
|
+
}
|
|
1873
|
+
});
|
|
1874
|
+
}
|
|
1875
|
+
function matchesWhere(row, where, resolve) {
|
|
1876
|
+
if (!isPlainObject(where)) return true;
|
|
1877
|
+
return Object.entries(where).every(([key, condition]) => {
|
|
1878
|
+
if (key === "AND") {
|
|
1879
|
+
return Array.isArray(condition) && condition.every((sub) => matchesWhere(row, sub, resolve));
|
|
1880
|
+
}
|
|
1881
|
+
if (key === "OR") {
|
|
1882
|
+
return Array.isArray(condition) && condition.some((sub) => matchesWhere(row, sub, resolve));
|
|
1883
|
+
}
|
|
1884
|
+
if (key === "NOT") {
|
|
1885
|
+
return !matchesWhere(row, condition, resolve);
|
|
1886
|
+
}
|
|
1887
|
+
const actual = fieldOf(row, key);
|
|
1888
|
+
if (isFieldOpObject(condition)) return matchesFieldOps(actual, condition, resolve);
|
|
1889
|
+
return looseEquals(actual, resolve(condition));
|
|
1890
|
+
});
|
|
1891
|
+
}
|
|
1892
|
+
var CALC_OPS = /* @__PURE__ */ new Set([
|
|
1893
|
+
// 산술 (기존)
|
|
1894
|
+
"sum",
|
|
1895
|
+
"sub",
|
|
1896
|
+
"mul",
|
|
1897
|
+
"div",
|
|
1898
|
+
"percent",
|
|
1899
|
+
"count",
|
|
1900
|
+
// 문자 (기존)
|
|
1901
|
+
"concat",
|
|
1902
|
+
"encode",
|
|
1903
|
+
// 비교·논리 (기존)
|
|
1904
|
+
"eq",
|
|
1905
|
+
"gt",
|
|
1906
|
+
"gte",
|
|
1907
|
+
"lt",
|
|
1908
|
+
"lte",
|
|
1909
|
+
"not",
|
|
1910
|
+
// 논리 (신규) — 예전에는 스펙이 eq(concat(eq(a),eq(b)),"falsefalse")로 우회했다
|
|
1911
|
+
"and",
|
|
1912
|
+
"or",
|
|
1913
|
+
// 값 고르기 (신규)
|
|
1914
|
+
"if",
|
|
1915
|
+
"match",
|
|
1916
|
+
"coalesce",
|
|
1917
|
+
// 목록·객체 (신규)
|
|
1918
|
+
"get",
|
|
1919
|
+
"pluck",
|
|
1920
|
+
"filter",
|
|
1921
|
+
"some",
|
|
1922
|
+
"every",
|
|
1923
|
+
"includes",
|
|
1924
|
+
"distinct",
|
|
1925
|
+
"except",
|
|
1926
|
+
"entries",
|
|
1927
|
+
"length",
|
|
1928
|
+
"join",
|
|
1929
|
+
"split",
|
|
1930
|
+
"sortBy"
|
|
1931
|
+
]);
|
|
1932
|
+
function evaluateCalc(calc, resolved, resolve) {
|
|
1933
|
+
const op = typeof calc.op === "string" ? calc.op : "";
|
|
1934
|
+
const field = typeof calc.field === "string" ? calc.field : void 0;
|
|
1935
|
+
const first = resolved[0];
|
|
1936
|
+
const list = Array.isArray(first) ? first : void 0;
|
|
1937
|
+
const listOrEmpty = () => {
|
|
1938
|
+
if (list) return list;
|
|
1939
|
+
if (first !== void 0 && first !== null) {
|
|
1940
|
+
warnOnce(
|
|
1941
|
+
`calc:${op}:list`,
|
|
1942
|
+
`[sdui] $calc(${op}): \uCCAB \uC778\uC790\uAC00 \uBC30\uC5F4\uC774 \uC544\uB2D9\uB2C8\uB2E4 \u2014 \uBE48 \uBAA9\uB85D\uC73C\uB85C \uCC98\uB9AC\uD569\uB2C8\uB2E4`
|
|
1943
|
+
);
|
|
1944
|
+
}
|
|
1945
|
+
return [];
|
|
1946
|
+
};
|
|
1947
|
+
const nums = (v) => {
|
|
1948
|
+
if (Array.isArray(v))
|
|
1949
|
+
return v.map((row) => field && isPlainObject(row) ? toNumber2(row[field]) : toNumber2(row));
|
|
1950
|
+
return [toNumber2(v)];
|
|
1951
|
+
};
|
|
1952
|
+
switch (op) {
|
|
1953
|
+
/* ── 산술 ── */
|
|
1954
|
+
case "sum":
|
|
1955
|
+
return resolved.flatMap(nums).reduce((a, b) => a + b, 0);
|
|
1956
|
+
case "count":
|
|
1957
|
+
return resolved.reduce(
|
|
1958
|
+
(a, v) => a + (Array.isArray(v) ? v.length : v == null ? 0 : 1),
|
|
1959
|
+
0
|
|
1960
|
+
);
|
|
1961
|
+
case "sub": {
|
|
1962
|
+
const items = resolved.map((v) => toNumber2(v));
|
|
1963
|
+
return items.length === 0 ? 0 : items.reduce((a, b) => a - b);
|
|
1964
|
+
}
|
|
1965
|
+
case "mul":
|
|
1966
|
+
return resolved.map((v) => toNumber2(v)).reduce((a, b) => a * b, 1);
|
|
1967
|
+
case "div": {
|
|
1968
|
+
const [a, b] = resolved.map((v) => toNumber2(v));
|
|
1969
|
+
return b === 0 ? 0 : a / b;
|
|
1970
|
+
}
|
|
1971
|
+
case "percent": {
|
|
1972
|
+
const [a, b] = resolved.map((v) => toNumber2(v));
|
|
1973
|
+
return b === 0 ? 0 : Math.round(a / b * 1e3) / 10;
|
|
1974
|
+
}
|
|
1975
|
+
/* ── 문자 ── */
|
|
1976
|
+
case "concat":
|
|
1977
|
+
return resolved.map((v) => v == null ? "" : String(v)).join("");
|
|
1978
|
+
case "encode":
|
|
1979
|
+
return encodeURIComponent(resolved.map((v) => v == null ? "" : String(v)).join(""));
|
|
1980
|
+
/* ── 비교·논리 ── */
|
|
1981
|
+
case "eq":
|
|
1982
|
+
return looseEquals(resolved[0], resolved[1]);
|
|
1983
|
+
case "gt":
|
|
1984
|
+
return orderingCompare(resolved[0], resolved[1]) > 0;
|
|
1985
|
+
case "gte":
|
|
1986
|
+
return orderingCompare(resolved[0], resolved[1]) >= 0;
|
|
1987
|
+
case "lt":
|
|
1988
|
+
return orderingCompare(resolved[0], resolved[1]) < 0;
|
|
1989
|
+
case "lte":
|
|
1990
|
+
return orderingCompare(resolved[0], resolved[1]) <= 0;
|
|
1991
|
+
case "not":
|
|
1992
|
+
return !resolved[0];
|
|
1993
|
+
case "and":
|
|
1994
|
+
return resolved.every(Boolean);
|
|
1995
|
+
case "or":
|
|
1996
|
+
return resolved.some(Boolean);
|
|
1997
|
+
/* ── 값 고르기 ── */
|
|
1998
|
+
case "if":
|
|
1999
|
+
return resolved[0] ? resolve(calc.then ?? null) : resolve(calc.else ?? null);
|
|
2000
|
+
case "match": {
|
|
2001
|
+
const key = String(resolved[0] ?? "");
|
|
2002
|
+
const cases = isPlainObject(calc.cases) ? calc.cases : {};
|
|
2003
|
+
if (Object.hasOwn(cases, key)) return resolve(cases[key]);
|
|
2004
|
+
return resolve(calc.default ?? null);
|
|
2005
|
+
}
|
|
2006
|
+
case "coalesce":
|
|
2007
|
+
return resolved.find((v) => !isBlank(v)) ?? null;
|
|
2008
|
+
/* ── 목록·객체 ── */
|
|
2009
|
+
case "get": {
|
|
2010
|
+
const [container, rawKey] = resolved;
|
|
2011
|
+
const key = rawKey == null ? "" : String(rawKey);
|
|
2012
|
+
if (Array.isArray(container)) {
|
|
2013
|
+
const index = Number(key);
|
|
2014
|
+
if (!Number.isInteger(index) || index < 0 || index >= container.length) return null;
|
|
2015
|
+
return container[index] ?? null;
|
|
2016
|
+
}
|
|
2017
|
+
if (isPlainObject(container)) {
|
|
2018
|
+
return Object.hasOwn(container, key) ? container[key] ?? null : null;
|
|
2019
|
+
}
|
|
2020
|
+
return null;
|
|
2021
|
+
}
|
|
2022
|
+
case "pluck":
|
|
2023
|
+
return listOrEmpty().map((row) => fieldOf(row, field)).filter((v) => v !== null && v !== void 0);
|
|
2024
|
+
case "filter":
|
|
2025
|
+
return listOrEmpty().filter((row) => matchesWhere(row, calc.where, resolve));
|
|
2026
|
+
case "some":
|
|
2027
|
+
return listOrEmpty().some((row) => matchesWhere(row, calc.where, resolve));
|
|
2028
|
+
case "every":
|
|
2029
|
+
return listOrEmpty().every((row) => matchesWhere(row, calc.where, resolve));
|
|
2030
|
+
case "includes": {
|
|
2031
|
+
const needle = resolved[1];
|
|
2032
|
+
if (typeof first === "string") return first.includes(String(needle ?? ""));
|
|
2033
|
+
return listOrEmpty().some((row) => looseEquals(fieldOf(row, field), needle));
|
|
2034
|
+
}
|
|
2035
|
+
case "distinct": {
|
|
2036
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2037
|
+
return listOrEmpty().filter((row) => {
|
|
2038
|
+
const key = String(fieldOf(row, field) ?? "");
|
|
2039
|
+
if (seen.has(key)) return false;
|
|
2040
|
+
seen.add(key);
|
|
2041
|
+
return true;
|
|
2042
|
+
});
|
|
2043
|
+
}
|
|
2044
|
+
case "except": {
|
|
2045
|
+
const remove = new Set(
|
|
2046
|
+
(Array.isArray(resolved[1]) ? resolved[1] : []).map(
|
|
2047
|
+
(row) => String(fieldOf(row, field) ?? "")
|
|
2048
|
+
)
|
|
2049
|
+
);
|
|
2050
|
+
return listOrEmpty().filter(
|
|
2051
|
+
(row) => !remove.has(String(fieldOf(row, field) ?? ""))
|
|
2052
|
+
);
|
|
2053
|
+
}
|
|
2054
|
+
case "entries": {
|
|
2055
|
+
if (!isPlainObject(first)) return [];
|
|
2056
|
+
return Object.entries(first).map(([key, value]) => ({
|
|
2057
|
+
key,
|
|
2058
|
+
value
|
|
2059
|
+
}));
|
|
2060
|
+
}
|
|
2061
|
+
case "length":
|
|
2062
|
+
if (Array.isArray(first)) return first.length;
|
|
2063
|
+
if (typeof first === "string") return first.length;
|
|
2064
|
+
return 0;
|
|
2065
|
+
case "join": {
|
|
2066
|
+
const sep = typeof calc.sep === "string" ? calc.sep : ",";
|
|
2067
|
+
return listOrEmpty().map((row) => {
|
|
2068
|
+
const value = fieldOf(row, field);
|
|
2069
|
+
return value == null ? "" : String(value);
|
|
2070
|
+
}).join(sep);
|
|
2071
|
+
}
|
|
2072
|
+
case "split": {
|
|
2073
|
+
const sep = typeof calc.sep === "string" ? calc.sep : ",";
|
|
2074
|
+
const parts = String(first ?? "").split(sep);
|
|
2075
|
+
if (calc.take === void 0) return parts;
|
|
2076
|
+
const index = toNumber2(calc.take);
|
|
2077
|
+
const at = index < 0 ? parts.length + index : index;
|
|
2078
|
+
return parts[at] ?? null;
|
|
2079
|
+
}
|
|
2080
|
+
case "sortBy": {
|
|
2081
|
+
const desc = Boolean(calc.desc);
|
|
2082
|
+
return [...listOrEmpty()].sort((a, b) => {
|
|
2083
|
+
const order = orderingCompare(fieldOf(a, field), fieldOf(b, field));
|
|
2084
|
+
return desc ? -order : order;
|
|
2085
|
+
});
|
|
2086
|
+
}
|
|
2087
|
+
default:
|
|
2088
|
+
return null;
|
|
2089
|
+
}
|
|
2090
|
+
}
|
|
2091
|
+
|
|
1786
2092
|
// src/request-action.ts
|
|
1787
2093
|
function deferChainEntry(container, key) {
|
|
1788
2094
|
return typeof container.action === "string" && (key === "onSuccess" || key === "onError");
|
|
@@ -1829,22 +2135,6 @@ var ACTION_NAMES = /* @__PURE__ */ new Set([
|
|
|
1829
2135
|
"arrayUpdate",
|
|
1830
2136
|
"custom"
|
|
1831
2137
|
]);
|
|
1832
|
-
var CALC_OPS = /* @__PURE__ */ new Set([
|
|
1833
|
-
"sum",
|
|
1834
|
-
"sub",
|
|
1835
|
-
"mul",
|
|
1836
|
-
"div",
|
|
1837
|
-
"percent",
|
|
1838
|
-
"count",
|
|
1839
|
-
"concat",
|
|
1840
|
-
"encode",
|
|
1841
|
-
"eq",
|
|
1842
|
-
"gt",
|
|
1843
|
-
"gte",
|
|
1844
|
-
"lt",
|
|
1845
|
-
"lte",
|
|
1846
|
-
"not"
|
|
1847
|
-
]);
|
|
1848
2138
|
var RULE_NAMES = /* @__PURE__ */ new Set([
|
|
1849
2139
|
"required",
|
|
1850
2140
|
"min",
|
|
@@ -1864,7 +2154,7 @@ var DENIED_PROPS = /* @__PURE__ */ new Set([
|
|
|
1864
2154
|
"constructor",
|
|
1865
2155
|
"prototype"
|
|
1866
2156
|
]);
|
|
1867
|
-
function
|
|
2157
|
+
function isPlainObject2(v) {
|
|
1868
2158
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
1869
2159
|
}
|
|
1870
2160
|
function checkUrlValue(key, value, path, issues) {
|
|
@@ -1874,7 +2164,7 @@ function checkUrlValue(key, value, path, issues) {
|
|
|
1874
2164
|
}
|
|
1875
2165
|
function validateSpec(page, knownComponents) {
|
|
1876
2166
|
const issues = [];
|
|
1877
|
-
if (!
|
|
2167
|
+
if (!isPlainObject2(page)) return [{ path: "$", message: "\uC2A4\uD399\uC774 \uAC1D\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4" }];
|
|
1878
2168
|
if (page.version !== 1) issues.push({ path: "$.version", message: "version\uC740 1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4" });
|
|
1879
2169
|
validatePageData(page.data, issues);
|
|
1880
2170
|
if (!Array.isArray(page.body)) {
|
|
@@ -1888,7 +2178,7 @@ function validateSpec(page, knownComponents) {
|
|
|
1888
2178
|
}
|
|
1889
2179
|
function validatePageData(data, issues) {
|
|
1890
2180
|
if (data === void 0) return;
|
|
1891
|
-
if (!
|
|
2181
|
+
if (!isPlainObject2(data)) {
|
|
1892
2182
|
issues.push({ path: "$.data", message: "data\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
1893
2183
|
return;
|
|
1894
2184
|
}
|
|
@@ -1898,7 +2188,7 @@ function validatePageData(data, issues) {
|
|
|
1898
2188
|
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" });
|
|
1899
2189
|
continue;
|
|
1900
2190
|
}
|
|
1901
|
-
if (!
|
|
2191
|
+
if (!isPlainObject2(raw)) {
|
|
1902
2192
|
issues.push({ path, message: "\uC870\uD68C\uB294 { endpoint, select?, when?, fallback? } \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
1903
2193
|
continue;
|
|
1904
2194
|
}
|
|
@@ -1910,7 +2200,7 @@ function validatePageData(data, issues) {
|
|
|
1910
2200
|
} else if (!raw.endpoint.startsWith("/")) {
|
|
1911
2201
|
issues.push({ path: `${path}.endpoint`, message: "endpoint\uB294 /\uB85C \uC2DC\uC791\uD558\uB294 \uACBD\uB85C\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
1912
2202
|
}
|
|
1913
|
-
} else if (!
|
|
2203
|
+
} else if (!isPlainObject2(raw.endpoint)) {
|
|
1914
2204
|
issues.push({ path: `${path}.endpoint`, message: "endpoint\uB294 \uBB38\uC790\uC5F4\uC774\uAC70\uB098 \uAC12 \uCC38\uC870\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
1915
2205
|
} else {
|
|
1916
2206
|
walkValue(raw.endpoint, `${path}.endpoint`, issues, false);
|
|
@@ -1933,7 +2223,7 @@ function validatePageData(data, issues) {
|
|
|
1933
2223
|
}
|
|
1934
2224
|
function walkChild(child, path, issues, known) {
|
|
1935
2225
|
if (typeof child === "string") return;
|
|
1936
|
-
if (!
|
|
2226
|
+
if (!isPlainObject2(child)) {
|
|
1937
2227
|
issues.push({ path, message: "children \uD56D\uBAA9\uC740 \uBB38\uC790\uC5F4 \uB610\uB294 \uB178\uB4DC \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
1938
2228
|
return;
|
|
1939
2229
|
}
|
|
@@ -1945,7 +2235,7 @@ function walkChild(child, path, issues, known) {
|
|
|
1945
2235
|
if (known && !RENDERER_BUILTINS.has(node.component) && !known.has(node.component)) {
|
|
1946
2236
|
issues.push({ path, message: `\uB4F1\uB85D\uB418\uC9C0 \uC54A\uC740 \uCEF4\uD3EC\uB10C\uD2B8: ${node.component}` });
|
|
1947
2237
|
}
|
|
1948
|
-
if (node.props !== void 0 && !
|
|
2238
|
+
if (node.props !== void 0 && !isPlainObject2(node.props)) {
|
|
1949
2239
|
issues.push({ path: `${path}.props`, message: "props\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
1950
2240
|
}
|
|
1951
2241
|
for (const [name, value] of Object.entries(node.props ?? {})) {
|
|
@@ -1959,9 +2249,9 @@ function walkChild(child, path, issues, known) {
|
|
|
1959
2249
|
checkUrlValue(name, value, `${path}.props.${name}`, issues);
|
|
1960
2250
|
walkValue(value, `${path}.props.${name}`, issues, name.startsWith("on") || name === "rowClick");
|
|
1961
2251
|
}
|
|
1962
|
-
if (node.component === "Form" &&
|
|
2252
|
+
if (node.component === "Form" && isPlainObject2(node.props) && node.props.rules !== void 0) {
|
|
1963
2253
|
const rules = node.props.rules;
|
|
1964
|
-
if (!
|
|
2254
|
+
if (!isPlainObject2(rules)) {
|
|
1965
2255
|
issues.push({ path: `${path}.props.rules`, message: "rules\uB294 { \uD544\uB4DC: \uADDC\uCE59\uBC30\uC5F4 } \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
1966
2256
|
} else {
|
|
1967
2257
|
for (const [field, list] of Object.entries(rules)) {
|
|
@@ -1972,15 +2262,15 @@ function walkChild(child, path, issues, known) {
|
|
|
1972
2262
|
}
|
|
1973
2263
|
}
|
|
1974
2264
|
if (node.component === "Fragment") {
|
|
1975
|
-
const id =
|
|
1976
|
-
if ((typeof id !== "string" || id === "") && !
|
|
2265
|
+
const id = isPlainObject2(node.props) ? node.props.id : void 0;
|
|
2266
|
+
if ((typeof id !== "string" || id === "") && !isPlainObject2(id)) {
|
|
1977
2267
|
issues.push({
|
|
1978
2268
|
path: `${path}.props.id`,
|
|
1979
2269
|
message: "Fragment.id\uB294 \uBE44\uC5B4 \uC788\uC9C0 \uC54A\uC740 \uBB38\uC790\uC5F4(\uB610\uB294 \uAC12 \uCC38\uC870)\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4"
|
|
1980
2270
|
});
|
|
1981
2271
|
}
|
|
1982
|
-
const args =
|
|
1983
|
-
if (args !== void 0 && !
|
|
2272
|
+
const args = isPlainObject2(node.props) ? node.props.args : void 0;
|
|
2273
|
+
if (args !== void 0 && !isPlainObject2(args)) {
|
|
1984
2274
|
issues.push({
|
|
1985
2275
|
path: `${path}.props.args`,
|
|
1986
2276
|
message: "Fragment.args\uB294 { \uC774\uB984: \uAC12 } \uD3C9\uBA74 \uC624\uBE0C\uC81D\uD2B8\uC5EC\uC57C \uD569\uB2C8\uB2E4"
|
|
@@ -1994,7 +2284,7 @@ function walkChild(child, path, issues, known) {
|
|
|
1994
2284
|
}
|
|
1995
2285
|
}
|
|
1996
2286
|
if (node.slots !== void 0) {
|
|
1997
|
-
if (!
|
|
2287
|
+
if (!isPlainObject2(node.slots)) {
|
|
1998
2288
|
issues.push({ path: `${path}.slots`, message: "slots\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4" });
|
|
1999
2289
|
} else {
|
|
2000
2290
|
for (const [slot, children] of Object.entries(node.slots)) {
|
|
@@ -2019,7 +2309,7 @@ function walkValue(value, path, issues, actionEligible) {
|
|
|
2019
2309
|
value.forEach((v, i) => walkValue(v, `${path}[${i}]`, issues, actionEligible));
|
|
2020
2310
|
return;
|
|
2021
2311
|
}
|
|
2022
|
-
if (!
|
|
2312
|
+
if (!isPlainObject2(value)) return;
|
|
2023
2313
|
if (typeof value.action === "string" && (actionEligible || ACTION_NAMES.has(value.action))) {
|
|
2024
2314
|
if (actionEligible && !ACTION_NAMES.has(value.action)) {
|
|
2025
2315
|
issues.push({ path, message: `\uC54C \uC218 \uC5C6\uB294 \uC561\uC158: ${value.action}` });
|
|
@@ -2046,7 +2336,7 @@ function walkValue(value, path, issues, actionEligible) {
|
|
|
2046
2336
|
}
|
|
2047
2337
|
if ("$calc" in value) {
|
|
2048
2338
|
const calc = value.$calc;
|
|
2049
|
-
if (!
|
|
2339
|
+
if (!isPlainObject2(calc) || typeof calc.op !== "string" || !CALC_OPS.has(calc.op)) {
|
|
2050
2340
|
issues.push({ path, message: "$calc.op\uC774 \uC720\uD6A8\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4" });
|
|
2051
2341
|
} else if (!Array.isArray(calc.args)) {
|
|
2052
2342
|
issues.push({ path: `${path}.$calc.args`, message: "args\uB294 \uBC30\uC5F4\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4" });
|
|
@@ -2075,12 +2365,12 @@ function walkValue(value, path, issues, actionEligible) {
|
|
|
2075
2365
|
}
|
|
2076
2366
|
|
|
2077
2367
|
// src/page-data.ts
|
|
2078
|
-
function
|
|
2368
|
+
function isPlainObject3(value) {
|
|
2079
2369
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2080
2370
|
}
|
|
2081
2371
|
function planPageData(data, resolve) {
|
|
2082
2372
|
if (data === void 0) return [];
|
|
2083
|
-
if (!
|
|
2373
|
+
if (!isPlainObject3(data)) {
|
|
2084
2374
|
warnOnce("page-data:root", "[sdui] page.data\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4 \u2014 \uBB34\uC2DC\uD569\uB2C8\uB2E4");
|
|
2085
2375
|
return [];
|
|
2086
2376
|
}
|
|
@@ -2090,7 +2380,7 @@ function planPageData(data, resolve) {
|
|
|
2090
2380
|
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`);
|
|
2091
2381
|
continue;
|
|
2092
2382
|
}
|
|
2093
|
-
if (!
|
|
2383
|
+
if (!isPlainObject3(raw)) {
|
|
2094
2384
|
warnOnce(`page-data:${key}`, `[sdui] page.data.${key}\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4 \u2014 \uAC74\uB108\uB701\uB2C8\uB2E4`);
|
|
2095
2385
|
continue;
|
|
2096
2386
|
}
|
|
@@ -2125,7 +2415,7 @@ function pickPath(source, path) {
|
|
|
2125
2415
|
if (path === void 0 || path === "") return source;
|
|
2126
2416
|
let value = source;
|
|
2127
2417
|
for (const segment of path.split(".")) {
|
|
2128
|
-
if (!
|
|
2418
|
+
if (!isPlainObject3(value)) return void 0;
|
|
2129
2419
|
value = value[segment];
|
|
2130
2420
|
}
|
|
2131
2421
|
return value;
|
|
@@ -2156,26 +2446,26 @@ function nearestArgsFrame(scope) {
|
|
|
2156
2446
|
}
|
|
2157
2447
|
return void 0;
|
|
2158
2448
|
}
|
|
2159
|
-
function
|
|
2449
|
+
function isPlainObject4(v) {
|
|
2160
2450
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
2161
2451
|
}
|
|
2162
2452
|
function isStateRef(v) {
|
|
2163
|
-
return
|
|
2453
|
+
return isPlainObject4(v) && typeof v.$state === "string";
|
|
2164
2454
|
}
|
|
2165
2455
|
function isItemRef(v) {
|
|
2166
|
-
return
|
|
2456
|
+
return isPlainObject4(v) && "$item" in v;
|
|
2167
2457
|
}
|
|
2168
2458
|
function isIndexRef(v) {
|
|
2169
|
-
return
|
|
2459
|
+
return isPlainObject4(v) && "$index" in v;
|
|
2170
2460
|
}
|
|
2171
2461
|
function isCalcRef(v) {
|
|
2172
|
-
return
|
|
2462
|
+
return isPlainObject4(v) && isPlainObject4(v.$calc);
|
|
2173
2463
|
}
|
|
2174
2464
|
function isArgRef(v) {
|
|
2175
|
-
return
|
|
2465
|
+
return isPlainObject4(v) && typeof v.$arg === "string";
|
|
2176
2466
|
}
|
|
2177
2467
|
function isAction(v) {
|
|
2178
|
-
return
|
|
2468
|
+
return isPlainObject4(v) && typeof v.action === "string";
|
|
2179
2469
|
}
|
|
2180
2470
|
function isActionList(v) {
|
|
2181
2471
|
return Array.isArray(v) && v.length > 0 && v.every(isAction);
|
|
@@ -2199,7 +2489,7 @@ function expandActionEntries(raw, scope) {
|
|
|
2199
2489
|
return [];
|
|
2200
2490
|
}
|
|
2201
2491
|
function eventValue(arg) {
|
|
2202
|
-
if (
|
|
2492
|
+
if (isPlainObject4(arg) && "target" in arg && typeof arg.preventDefault === "function") {
|
|
2203
2493
|
const target = arg.target;
|
|
2204
2494
|
if (target.type === "checkbox") return target.checked;
|
|
2205
2495
|
if (target.type === "number" || target.type === "range") {
|
|
@@ -2211,14 +2501,6 @@ function eventValue(arg) {
|
|
|
2211
2501
|
}
|
|
2212
2502
|
return arg;
|
|
2213
2503
|
}
|
|
2214
|
-
function toNumber2(v) {
|
|
2215
|
-
if (typeof v === "number") return v;
|
|
2216
|
-
if (typeof v === "string") {
|
|
2217
|
-
const n = Number(v.replace(/,/g, ""));
|
|
2218
|
-
return Number.isFinite(n) ? n : 0;
|
|
2219
|
-
}
|
|
2220
|
-
return 0;
|
|
2221
|
-
}
|
|
2222
2504
|
function toIndex(v) {
|
|
2223
2505
|
if (typeof v === "number") return Number.isInteger(v) ? v : null;
|
|
2224
2506
|
if (typeof v === "string" && /^-?\d+$/.test(v.trim())) return Number(v.trim());
|
|
@@ -2317,7 +2599,7 @@ function childrenOf(node) {
|
|
|
2317
2599
|
}
|
|
2318
2600
|
function renderChild(child, index, scope, engine) {
|
|
2319
2601
|
if (typeof child === "string") return child;
|
|
2320
|
-
if (!
|
|
2602
|
+
if (!isPlainObject4(child)) {
|
|
2321
2603
|
warnOnce2(`child:${String(child)}`, `[sdui] \uC798\uBABB\uB41C \uB178\uB4DC(\uBB38\uC790\uC5F4 \uB610\uB294 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4): ${String(child)}`);
|
|
2322
2604
|
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);
|
|
2323
2605
|
}
|
|
@@ -2332,11 +2614,11 @@ function SduiNodeRenderer({
|
|
|
2332
2614
|
engine
|
|
2333
2615
|
}) {
|
|
2334
2616
|
const { registry, resolveValue, dispatch, resolveAsset } = engine;
|
|
2335
|
-
const slots =
|
|
2617
|
+
const slots = isPlainObject4(node.slots) ? node.slots : void 0;
|
|
2336
2618
|
const childList = childrenOf(node);
|
|
2337
2619
|
if (node.component === "ForEach") {
|
|
2338
2620
|
const source = resolveValue(
|
|
2339
|
-
|
|
2621
|
+
isPlainObject4(node.props) ? node.props.source ?? null : null,
|
|
2340
2622
|
scope
|
|
2341
2623
|
);
|
|
2342
2624
|
const rows = Array.isArray(source) ? source : [];
|
|
@@ -2346,7 +2628,7 @@ function SduiNodeRenderer({
|
|
|
2346
2628
|
}
|
|
2347
2629
|
return /* @__PURE__ */ jsx(Fragment, { children: rows.map((item, rowIndex) => {
|
|
2348
2630
|
const rowScope = [...scope, { item, index: rowIndex }];
|
|
2349
|
-
const rowKey =
|
|
2631
|
+
const rowKey = isPlainObject4(item) && typeof item.id === "string" ? item.id : rowIndex;
|
|
2350
2632
|
return /* @__PURE__ */ jsx(React11.Fragment, { children: childList?.map((child, i) => renderChild(child, i, rowScope, engine)) }, rowKey);
|
|
2351
2633
|
}) });
|
|
2352
2634
|
}
|
|
@@ -2365,7 +2647,7 @@ function SduiNodeRenderer({
|
|
|
2365
2647
|
] });
|
|
2366
2648
|
}
|
|
2367
2649
|
const props = {};
|
|
2368
|
-
for (const [name, raw] of Object.entries(
|
|
2650
|
+
for (const [name, raw] of Object.entries(isPlainObject4(node.props) ? node.props : {})) {
|
|
2369
2651
|
if (DENIED_PROPS2.has(name)) {
|
|
2370
2652
|
warnOnce2(`prop:${name}`, `[sdui] \uC2A4\uD399\uC5D0\uC11C \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uB294 \uD504\uB86D: ${name} \u2014 \uBB34\uC2DC\uD569\uB2C8\uB2E4`);
|
|
2371
2653
|
continue;
|
|
@@ -2404,7 +2686,7 @@ function SduiNodeRenderer({
|
|
|
2404
2686
|
if (childLayout) {
|
|
2405
2687
|
for (const name of CHILD_LAYOUT_PROPS) delete props[name];
|
|
2406
2688
|
if (childLayout.style) {
|
|
2407
|
-
props.style =
|
|
2689
|
+
props.style = isPlainObject4(props.style) ? { ...childLayout.style, ...props.style } : childLayout.style;
|
|
2408
2690
|
}
|
|
2409
2691
|
if (childLayout.className) {
|
|
2410
2692
|
props.className = typeof props.className === "string" && props.className ? `${childLayout.className} ${props.className}` : childLayout.className;
|
|
@@ -2428,7 +2710,7 @@ var FRAGMENT_MAX_DEPTH = 4;
|
|
|
2428
2710
|
function SduiFragment({ node, scope, engine }) {
|
|
2429
2711
|
const adapter = useSduiAdapter();
|
|
2430
2712
|
const chain = React11.useContext(SduiFragmentChainContext);
|
|
2431
|
-
const raw =
|
|
2713
|
+
const raw = isPlainObject4(node.props) ? node.props.id : void 0;
|
|
2432
2714
|
const id = engine.resolveValue(raw, scope);
|
|
2433
2715
|
if (typeof id !== "string" || id === "") {
|
|
2434
2716
|
warnOnce2("fragment:id", "[sdui] <Fragment>\uC5D0 \uBB38\uC790\uC5F4 id\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uB80C\uB354\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
@@ -2448,8 +2730,8 @@ function SduiFragment({ node, scope, engine }) {
|
|
|
2448
2730
|
);
|
|
2449
2731
|
return null;
|
|
2450
2732
|
}
|
|
2451
|
-
const rawArgs =
|
|
2452
|
-
if (rawArgs !== void 0 && !
|
|
2733
|
+
const rawArgs = isPlainObject4(node.props) ? node.props.args : void 0;
|
|
2734
|
+
if (rawArgs !== void 0 && !isPlainObject4(rawArgs)) {
|
|
2453
2735
|
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`);
|
|
2454
2736
|
}
|
|
2455
2737
|
const useSpec = adapter?.useSpec;
|
|
@@ -2464,7 +2746,7 @@ function SduiFragment({ node, scope, engine }) {
|
|
|
2464
2746
|
SduiFragmentBody,
|
|
2465
2747
|
{
|
|
2466
2748
|
id,
|
|
2467
|
-
args:
|
|
2749
|
+
args: isPlainObject4(rawArgs) ? rawArgs : void 0,
|
|
2468
2750
|
useSpec,
|
|
2469
2751
|
chain,
|
|
2470
2752
|
scope,
|
|
@@ -2485,13 +2767,13 @@ function SduiFragmentBody({
|
|
|
2485
2767
|
const nextChain = React11.useMemo(() => [...chain, id], [chain, id]);
|
|
2486
2768
|
const bodyScope = React11.useMemo(() => [...scope, { args, callSiteScope: scope }], [scope, args]);
|
|
2487
2769
|
React11.useEffect(() => {
|
|
2488
|
-
if (!DEV || !
|
|
2770
|
+
if (!DEV || !isPlainObject4(spec) || !Array.isArray(spec.body)) return;
|
|
2489
2771
|
validateSpec(spec, new Set(Object.keys(engine.registry))).forEach(
|
|
2490
2772
|
(issue) => console.warn(`[sdui:spec:${id}] ${issue.path} \u2014 ${issue.message}`)
|
|
2491
2773
|
);
|
|
2492
2774
|
}, [spec, engine.registry, id]);
|
|
2493
2775
|
if (spec === void 0) return null;
|
|
2494
|
-
if (spec === null || !
|
|
2776
|
+
if (spec === null || !isPlainObject4(spec) || !Array.isArray(spec.body)) {
|
|
2495
2777
|
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`);
|
|
2496
2778
|
return null;
|
|
2497
2779
|
}
|
|
@@ -2621,7 +2903,7 @@ function SduiRenderer({
|
|
|
2621
2903
|
if (head in current) {
|
|
2622
2904
|
let value = current[head];
|
|
2623
2905
|
for (const segment of segments.slice(cut)) {
|
|
2624
|
-
if (!
|
|
2906
|
+
if (!isPlainObject4(value)) return void 0;
|
|
2625
2907
|
value = value[segment];
|
|
2626
2908
|
}
|
|
2627
2909
|
return value;
|
|
@@ -2639,7 +2921,7 @@ function SduiRenderer({
|
|
|
2639
2921
|
const frame = nearestItemFrame(scope);
|
|
2640
2922
|
if (!frame) return null;
|
|
2641
2923
|
if (value.$item === true) return frame.item;
|
|
2642
|
-
return
|
|
2924
|
+
return isPlainObject4(frame.item) ? frame.item[value.$item] ?? null : null;
|
|
2643
2925
|
}
|
|
2644
2926
|
if (isIndexRef(value)) {
|
|
2645
2927
|
return nearestItemFrame(scope)?.index ?? null;
|
|
@@ -2653,64 +2935,17 @@ function SduiRenderer({
|
|
|
2653
2935
|
return void 0;
|
|
2654
2936
|
}
|
|
2655
2937
|
if (isCalcRef(value)) {
|
|
2656
|
-
const
|
|
2657
|
-
const op = typeof
|
|
2658
|
-
if (!Array.isArray(args)) {
|
|
2938
|
+
const calc = value.$calc;
|
|
2939
|
+
const op = typeof calc.op === "string" ? calc.op : "";
|
|
2940
|
+
if (!Array.isArray(calc.args)) {
|
|
2659
2941
|
warnOnce2(`calc:${op}`, `[sdui] $calc(${op || "?"}): args\uB294 \uBC30\uC5F4\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4 \u2014 \uAC12 \uC5C6\uC74C\uC73C\uB85C \uCC98\uB9AC\uD569\uB2C8\uB2E4`);
|
|
2660
2942
|
return null;
|
|
2661
2943
|
}
|
|
2662
|
-
const
|
|
2663
|
-
|
|
2664
|
-
const nums = (v) => {
|
|
2665
|
-
if (Array.isArray(v))
|
|
2666
|
-
return v.map((row) => field && isPlainObject3(row) ? toNumber2(row[field]) : toNumber2(row));
|
|
2667
|
-
return [toNumber2(v)];
|
|
2668
|
-
};
|
|
2669
|
-
switch (op) {
|
|
2670
|
-
case "sum":
|
|
2671
|
-
return resolved.flatMap(nums).reduce((a, b) => a + b, 0);
|
|
2672
|
-
case "count":
|
|
2673
|
-
return resolved.reduce((a, v) => a + (Array.isArray(v) ? v.length : v == null ? 0 : 1), 0);
|
|
2674
|
-
case "sub": {
|
|
2675
|
-
const list = resolved.map((v) => toNumber2(v));
|
|
2676
|
-
return list.length === 0 ? 0 : list.reduce((a, b) => a - b);
|
|
2677
|
-
}
|
|
2678
|
-
case "mul":
|
|
2679
|
-
return resolved.map((v) => toNumber2(v)).reduce((a, b) => a * b, 1);
|
|
2680
|
-
case "div": {
|
|
2681
|
-
const [a, b] = resolved.map((v) => toNumber2(v));
|
|
2682
|
-
return b === 0 ? 0 : a / b;
|
|
2683
|
-
}
|
|
2684
|
-
case "percent": {
|
|
2685
|
-
const [a, b] = resolved.map((v) => toNumber2(v));
|
|
2686
|
-
return b === 0 ? 0 : Math.round(a / b * 1e3) / 10;
|
|
2687
|
-
}
|
|
2688
|
-
case "concat":
|
|
2689
|
-
return resolved.map((v) => v == null ? "" : String(v)).join("");
|
|
2690
|
-
case "encode":
|
|
2691
|
-
return encodeURIComponent(resolved.map((v) => v == null ? "" : String(v)).join(""));
|
|
2692
|
-
case "eq": {
|
|
2693
|
-
const [a, b] = resolved;
|
|
2694
|
-
return String(a ?? "") === String(b ?? "");
|
|
2695
|
-
}
|
|
2696
|
-
// 수량 비교 — 정원 초과 차단(Button.disabled), 임계값 경고(Show.when) 등
|
|
2697
|
-
case "gt":
|
|
2698
|
-
return toNumber2(resolved[0]) > toNumber2(resolved[1]);
|
|
2699
|
-
case "gte":
|
|
2700
|
-
return toNumber2(resolved[0]) >= toNumber2(resolved[1]);
|
|
2701
|
-
case "lt":
|
|
2702
|
-
return toNumber2(resolved[0]) < toNumber2(resolved[1]);
|
|
2703
|
-
case "lte":
|
|
2704
|
-
return toNumber2(resolved[0]) <= toNumber2(resolved[1]);
|
|
2705
|
-
/** 부정 — 조건을 뒤집어 "없을 때만" 렌더링하는 데 쓴다 */
|
|
2706
|
-
case "not":
|
|
2707
|
-
return !resolved[0];
|
|
2708
|
-
default:
|
|
2709
|
-
return null;
|
|
2710
|
-
}
|
|
2944
|
+
const resolved = calc.args.map((arg) => resolveValue(arg, scope));
|
|
2945
|
+
return evaluateCalc(calc, resolved, (late) => resolveValue(late, scope));
|
|
2711
2946
|
}
|
|
2712
2947
|
if (Array.isArray(value)) return value.map((v) => resolveValue(v, scope));
|
|
2713
|
-
if (
|
|
2948
|
+
if (isPlainObject4(value)) {
|
|
2714
2949
|
const out = {};
|
|
2715
2950
|
for (const [k, v] of Object.entries(value)) {
|
|
2716
2951
|
out[k] = deferChainEntry(value, k) ? v : resolveValue(v, scope);
|
|
@@ -2879,7 +3114,7 @@ function SduiRenderer({
|
|
|
2879
3114
|
break;
|
|
2880
3115
|
}
|
|
2881
3116
|
const row = current[index];
|
|
2882
|
-
if (!
|
|
3117
|
+
if (!isPlainObject4(row)) break;
|
|
2883
3118
|
const nextValue = (action.fromEvent ? eventValue(arg) : action.value) ?? null;
|
|
2884
3119
|
const next = [...current];
|
|
2885
3120
|
next[index] = { ...row, [action.field]: nextValue };
|
|
@@ -3022,4 +3257,4 @@ function SduiRenderer({
|
|
|
3022
3257
|
);
|
|
3023
3258
|
}
|
|
3024
3259
|
|
|
3025
|
-
export { Actions, Can, Col, Divider, Grid, KeyValueList, NodeErrorBoundary, PageHead, RemoteSearchResults, ResultTable, Row, SduiDialog, SduiForm, SduiPermissionProvider, SduiRenderer, SduiSearchDataProvider, SduiSearchResults, SearchResults, Section, Show, SortHandle, SortableList, Spacer, Text, cellRenderer, createRegistry, defaultRegistry, imageRenderer, normalizePageSizes, sortableDropIndex, sortableMove, useRemoteSearchPage, useSduiCan, useSduiDispatch, useSduiRuntime, useSearchFetcher, validateSpec };
|
|
3260
|
+
export { Actions, CALC_OPS, Can, Col, Divider, Grid, KeyValueList, NodeErrorBoundary, PageHead, RemoteSearchResults, ResultTable, Row, SduiDialog, SduiForm, SduiPermissionProvider, SduiRenderer, SduiSearchDataProvider, SduiSearchResults, SearchResults, Section, Show, SortHandle, SortableList, Spacer, Text, cellRenderer, createRegistry, defaultRegistry, imageRenderer, normalizePageSizes, sortableDropIndex, sortableMove, useRemoteSearchPage, useSduiCan, useSduiDispatch, useSduiRuntime, useSearchFetcher, validateSpec };
|