@wipco/sdui 0.23.0 → 0.25.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 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-DmHC7HCN.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-DmHC7HCN.js';
3
+ import { S as SduiPage, a as SduiAction, b as SduiPropValue, c as SduiRule } from './types-Bum2uMjl.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-Bum2uMjl.js';
5
5
  import { S as SduiBoxProps, a as SduiContainerLayoutProps, b as SduiColumnsScale, c as SduiGapScale, d as SduiWeightScale, e as SduiTextAlignScale } from './layout-B1QrIBm6.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-B1QrIBm6.js';
7
7
  import { D as DatePickerProps, a as DateRangePickerProps, T as TimePickerProps } from './DatePicker-D2EtpvkQ.js';
package/dist/index.js CHANGED
@@ -1816,6 +1816,12 @@ function looseEquals(a, b) {
1816
1816
  function isBlank(v) {
1817
1817
  return v === null || v === void 0 || v === "";
1818
1818
  }
1819
+ function isEmptyValue(v) {
1820
+ if (isBlank(v)) return true;
1821
+ if (Array.isArray(v)) return v.length === 0;
1822
+ if (isPlainObject(v)) return Object.keys(v).length === 0;
1823
+ return false;
1824
+ }
1819
1825
  function fieldOf(row, field) {
1820
1826
  if (!field) return row;
1821
1827
  if (!isPlainObject(row)) return void 0;
@@ -1833,7 +1839,8 @@ var FIELD_OPS = /* @__PURE__ */ new Set([
1833
1839
  "contains",
1834
1840
  "startsWith",
1835
1841
  "endsWith",
1836
- "isNull"
1842
+ "isNull",
1843
+ "isEmpty"
1837
1844
  ]);
1838
1845
  function isFieldOpObject(v) {
1839
1846
  return isPlainObject(v) && Object.keys(v).some((key) => FIELD_OPS.has(key));
@@ -1867,6 +1874,8 @@ function matchesFieldOps(actual, ops, resolve) {
1867
1874
  return String(actual ?? "").endsWith(String(expected ?? ""));
1868
1875
  case "isNull":
1869
1876
  return isBlank(actual) === Boolean(expected);
1877
+ case "isEmpty":
1878
+ return isEmptyValue(actual) === Boolean(expected);
1870
1879
  default:
1871
1880
  return true;
1872
1881
  }
@@ -1924,6 +1933,7 @@ var CALC_OPS = /* @__PURE__ */ new Set([
1924
1933
  "distinct",
1925
1934
  "except",
1926
1935
  "entries",
1936
+ "fromEntries",
1927
1937
  "length",
1928
1938
  "join",
1929
1939
  "split",
@@ -2058,6 +2068,16 @@ function evaluateCalc(calc, resolved, resolve) {
2058
2068
  value
2059
2069
  }));
2060
2070
  }
2071
+ case "fromEntries": {
2072
+ const out = /* @__PURE__ */ Object.create(null);
2073
+ for (const row of listOrEmpty()) {
2074
+ if (!isPlainObject(row)) continue;
2075
+ const key = row.key;
2076
+ if (key === null || key === void 0 || key === "") continue;
2077
+ out[String(key)] = row.value ?? null;
2078
+ }
2079
+ return { ...out };
2080
+ }
2061
2081
  case "length":
2062
2082
  if (Array.isArray(first)) return first.length;
2063
2083
  if (typeof first === "string") return first.length;
@@ -2094,10 +2114,16 @@ function deferChainEntry(container, key) {
2094
2114
  return typeof container.action === "string" && (key === "onSuccess" || key === "onError");
2095
2115
  }
2096
2116
  async function runRequestAction(action, deps) {
2117
+ const pendingKey = typeof action.pendingKey === "string" && action.pendingKey !== "" ? action.pendingKey : null;
2118
+ let pendingOn = false;
2097
2119
  try {
2098
2120
  if (typeof action.endpoint !== "string" || action.endpoint === "") {
2099
2121
  throw new Error("request \uC561\uC158\uC758 endpoint\uAC00 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 \u2014 $state \uCC38\uC870\uC5D0 \uC544\uC9C1 \uAC12\uC774 \uC5C6\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694");
2100
2122
  }
2123
+ if (pendingKey) {
2124
+ pendingOn = true;
2125
+ deps.dispatch({ action: "setState", key: pendingKey, value: true });
2126
+ }
2101
2127
  const response = await deps.fetch(action.endpoint, {
2102
2128
  method: action.method ?? "POST",
2103
2129
  ...action.body === void 0 ? {} : { body: action.body }
@@ -2124,6 +2150,8 @@ async function runRequestAction(action, deps) {
2124
2150
  } else {
2125
2151
  deps.toast({ tone: "danger", title: "\uC694\uCCAD \uC2E4\uD328", message });
2126
2152
  }
2153
+ } finally {
2154
+ if (pendingKey && pendingOn) deps.dispatch({ action: "setState", key: pendingKey, value: false });
2127
2155
  }
2128
2156
  }
2129
2157
 
package/dist/meta.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { b as SduiPropValue, i as SduiNode } from './types-DmHC7HCN.js';
1
+ import { b as SduiPropValue, i as SduiNode } from './types-Bum2uMjl.js';
2
2
 
3
3
  /**
4
4
  * 시각 빌더용 컴포넌트 메타데이터 스키마.
@@ -88,12 +88,13 @@ interface SduiCalcRef {
88
88
  * - `distinct` `field`(없으면 값 자체) 기준 중복 제거
89
89
  * - `except` args[0]에서 args[1]에 있는 것을 뺀다(`field`로 맞춘다)
90
90
  * - `entries` 객체를 `{key, value}` 배열로 편다 — ForEach가 돌 수 있는 모양
91
+ * - `fromEntries` 그 짝. `{key,value}` 배열을 객체로 되돌린다(걸러낸 폼 페이로드 조립)
91
92
  * - `length` 배열·문자열의 길이
92
93
  * - `join` `sep`(기본 ',')으로 잇는다
93
94
  * - `split` `sep`(기본 ',')으로 가른다. `take`를 주면 그 조각 하나(음수는 뒤에서)
94
95
  * - `sortBy` `field` 기준 정렬(`desc: true`면 내림차순). 원본은 건드리지 않는다
95
96
  */
96
- | 'get' | 'pluck' | 'filter' | 'some' | 'every' | 'includes' | 'distinct' | 'except' | 'entries' | 'length' | 'join' | 'split' | 'sortBy';
97
+ | 'get' | 'pluck' | 'filter' | 'some' | 'every' | 'includes' | 'distinct' | 'except' | 'entries' | 'fromEntries' | 'length' | 'join' | 'split' | 'sortBy';
97
98
  args: SduiPropValue[];
98
99
  /** sum/count·목록 연산에서 객체 배열의 필드를 지정 */
99
100
  field?: string;
@@ -105,7 +106,8 @@ interface SduiCalcRef {
105
106
  * "OR": [ { "status": "open" }, { "owner": { "isNull": true } } ] }
106
107
  *
107
108
  * 필드 연산: eq · ne · gt · gte · lt · lte · in · notIn · contains ·
108
- * startsWith · endsWith · isNull. 값이 연산 객체가 아니면 `eq`로 읽는다.
109
+ * startsWith · endsWith · isNull · isEmpty. 값이 연산 객체가 아니면 `eq`로 읽는다.
110
+ * (`isNull`은 null·undefined·''를, `isEmpty`는 거기에 빈 배열·빈 객체까지 본다.)
109
111
  * 같은 객체의 키들은 AND이고, `AND`/`OR`는 술어 배열, `NOT`은 술어 하나다.
110
112
  * 술어 안의 값에도 참조를 쓸 수 있는데, 이때 `$item`은 거르고 있는 행이 아니라
111
113
  * **바깥 ForEach의 행**을 가리킨다(거르는 행은 필드 이름으로 지목한다).
@@ -219,6 +221,14 @@ type SduiAction = {
219
221
  * (계약은 {@link SduiAdapter.fetch} 참고). 안 얹으면 message 만 남는다.
220
222
  */
221
223
  errorKey?: string;
224
+ /**
225
+ * 진행 상태를 담을 상태 키. 요청 직전에 `true`, 끝나면(성공·실패 모두) `false`.
226
+ *
227
+ * `submitForm`이 `{form}.$submitting`을 관리하는 것과 같은 자리다 — 그쪽은 폼이
228
+ * 있어 이름이 파생되지만 `request`는 폼이 없으므로 키를 받는다. 버튼의
229
+ * `loading`·`disabled`를 여기 물리면 이중 제출과 무반응이 함께 사라진다.
230
+ */
231
+ pendingKey?: string;
222
232
  }
223
233
  /**
224
234
  * 단발 API 호출 — submitForm에서 폼 수집·검증을 뺀 것. 서버의 2단계 커밋 계약
@@ -252,6 +262,14 @@ type SduiAction = {
252
262
  * (계약은 {@link SduiAdapter.fetch} 참고). 안 얹으면 message 만 남는다.
253
263
  */
254
264
  errorKey?: string;
265
+ /**
266
+ * 진행 상태를 담을 상태 키. 요청 직전에 `true`, 끝나면(성공·실패 모두) `false`.
267
+ *
268
+ * `submitForm`이 `{form}.$submitting`을 관리하는 것과 같은 자리다 — 그쪽은 폼이
269
+ * 있어 이름이 파생되지만 `request`는 폼이 없으므로 키를 받는다. 버튼의
270
+ * `loading`·`disabled`를 여기 물리면 이중 제출과 무반응이 함께 사라진다.
271
+ */
272
+ pendingKey?: string;
255
273
  /** 성공 시 무효화할 조회 prefix — onSuccess의 invalidate 액션 단축 */
256
274
  invalidate?: string;
257
275
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wipco/sdui",
3
- "version": "0.23.0",
3
+ "version": "0.25.0",
4
4
  "description": "WIPCO 서버 주도 UI(SDUI) 렌더러 — JSON 페이지 스펙을 React 컴포넌트로 렌더링",
5
5
  "keywords": [
6
6
  "sdui",