cdp-material-sdk 0.1.1 → 0.1.2

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.js CHANGED
@@ -1,44 +1,47 @@
1
- import { C as e, a as t, b as n, c as i, D as E, d as o, E as T, F as _, I as O, e as N, L as A, f as R, g as r, N as C, h as D, O as l, i as u, S as I, j as S, k as d, l as P, m as L, n as Y, o as m, p, q as M, r as g, u as c, s as G, v, t as K } from "./validateManifest-ZPFDq790.js";
2
- import { D as f, a as x, b as V, P as h, r as y, s as b, u as k, c as z, d as H } from "./useFieldRegistry-CwjlA-ja.js";
1
+ import { C as e, a as t, b as n, c as E, D as i, d as T, e as _, f as o, g as O, E as N, F as R, I as A, h as D, L as r, i as I, j as C, N as L, k as l, O as S, l as u, S as d, m as P, n as Y, o as m, p, q as M, r as g, s as c, t as G, u as v, v as K, w as F, x as f, y as x } from "./validateManifest-DspYuz81.js";
2
+ import { D as y, a as h, b, P as k, r as z, s as H, u as J, c as U, d as j } from "./useFieldRegistry-CwjlA-ja.js";
3
3
  export {
4
4
  e as CATEGORY_LABELS,
5
5
  t as COMPONENT_CATEGORY,
6
6
  n as COMPONENT_STATE_KEY,
7
- i as COMPONENT_TRAIT,
8
- E as DATA_FIELD_ROLE,
9
- o as DYNAMIC_ENUM_KEY,
10
- f as DataContainerRuntimeContext,
11
- x as DataScope,
12
- V as DataScopeContext,
13
- T as ENGINE_EVENT_TYPE,
14
- _ as FIELD_ROLE_KEY,
15
- O as INJECT_PATH_ROOT,
16
- N as INJECT_PATH_SLOT_PROPS,
17
- A as LOADING_PROP_NAME,
18
- R as LOADING_STRATEGY,
19
- r as LOADING_WRAPPER_TYPE,
20
- C as NOTIFY_ERROR_STRATEGY,
21
- D as NOTIFY_TIMING,
22
- l as OptionItemSchema,
7
+ E as COMPONENT_TRAIT,
8
+ i as DATA_FIELD_ROLE,
9
+ T as DRILL_ACTION,
10
+ _ as DRILL_EVENT,
11
+ o as DRILL_STATE,
12
+ O as DYNAMIC_ENUM_KEY,
13
+ y as DataContainerRuntimeContext,
14
+ h as DataScope,
15
+ b as DataScopeContext,
16
+ N as ENGINE_EVENT_TYPE,
17
+ R as FIELD_ROLE_KEY,
18
+ A as INJECT_PATH_ROOT,
19
+ D as INJECT_PATH_SLOT_PROPS,
20
+ r as LOADING_PROP_NAME,
21
+ I as LOADING_STRATEGY,
22
+ C as LOADING_WRAPPER_TYPE,
23
+ L as NOTIFY_ERROR_STRATEGY,
24
+ l as NOTIFY_TIMING,
25
+ S as OptionItemSchema,
23
26
  u as OptionsSchema,
24
- h as PageContext,
25
- I as SLOT_KEY,
26
- S as STANDARD_EVENT_KEYS,
27
- d as diagnoseMissingActionImpls,
28
- P as diagnoseMissingStateKeys,
29
- L as isCustomEventKey,
30
- Y as isStandardEventKey,
31
- m as normalizeAdapterEvents,
32
- p as normalizeManifestEvents,
33
- M as printSingleValidationResult,
34
- g as printValidationResult,
35
- y as resolveDataContainerRuntimeValue,
36
- b as shouldUseDataContainerRuntimeFallback,
37
- c as useConcurrentLoading,
38
- k as useDataContainer,
39
- z as useDataContainerApi,
40
- G as useDualLoading,
41
- H as useFieldRegistry,
42
- v as validateManifest,
43
- K as validateManifests
27
+ k as PageContext,
28
+ d as SLOT_KEY,
29
+ P as STANDARD_EVENT_KEYS,
30
+ Y as diagnoseMissingActionImpls,
31
+ m as diagnoseMissingStateKeys,
32
+ p as isCustomEventKey,
33
+ M as isStandardEventKey,
34
+ g as normalizeAdapterEvents,
35
+ c as normalizeManifestEvents,
36
+ G as printSingleValidationResult,
37
+ v as printValidationResult,
38
+ z as resolveDataContainerRuntimeValue,
39
+ H as shouldUseDataContainerRuntimeFallback,
40
+ K as useConcurrentLoading,
41
+ J as useDataContainer,
42
+ U as useDataContainerApi,
43
+ F as useDualLoading,
44
+ j as useFieldRegistry,
45
+ f as validateManifest,
46
+ x as validateManifests
44
47
  };
@@ -7,6 +7,7 @@ export * from './hooks/useConcurrentLoading';
7
7
  export * from './hooks/useDualLoading';
8
8
  export * from './protocol/adapter';
9
9
  export * from './protocol/common-schemas';
10
+ export * from './protocol/drill';
10
11
  export * from './protocol/events';
11
12
  export * from './protocol/manifest';
12
13
  export * from './protocol/manifest-types';
package/dist/portable.js CHANGED
@@ -1,34 +1,37 @@
1
- import { C as E, a as e, b as T, c as _, D as i, d as n, E as t, F as O, I as N, e as A, L as R, f as I, g as o, N as S, h as L, O as Y, i as P, S as d, j as l, k as M, l as r, m as C, n as D, o as m, p as G, q as g, r as p, u, s as K, v, t as c } from "./validateManifest-ZPFDq790.js";
1
+ import { C as E, a as T, b as _, c as e, D as i, d as n, e as t, f as O, g as N, E as A, F as I, I as R, h as L, L as o, i as S, j as D, N as Y, k as P, O as d, l, S as C, m as M, n as r, o as m, p as G, q as g, r as p, s as u, t as K, u as v, v as c, w as f, x as F, y as V } from "./validateManifest-DspYuz81.js";
2
2
  export {
3
3
  E as CATEGORY_LABELS,
4
- e as COMPONENT_CATEGORY,
5
- T as COMPONENT_STATE_KEY,
6
- _ as COMPONENT_TRAIT,
4
+ T as COMPONENT_CATEGORY,
5
+ _ as COMPONENT_STATE_KEY,
6
+ e as COMPONENT_TRAIT,
7
7
  i as DATA_FIELD_ROLE,
8
- n as DYNAMIC_ENUM_KEY,
9
- t as ENGINE_EVENT_TYPE,
10
- O as FIELD_ROLE_KEY,
11
- N as INJECT_PATH_ROOT,
12
- A as INJECT_PATH_SLOT_PROPS,
13
- R as LOADING_PROP_NAME,
14
- I as LOADING_STRATEGY,
15
- o as LOADING_WRAPPER_TYPE,
16
- S as NOTIFY_ERROR_STRATEGY,
17
- L as NOTIFY_TIMING,
18
- Y as OptionItemSchema,
19
- P as OptionsSchema,
20
- d as SLOT_KEY,
21
- l as STANDARD_EVENT_KEYS,
22
- M as diagnoseMissingActionImpls,
23
- r as diagnoseMissingStateKeys,
24
- C as isCustomEventKey,
25
- D as isStandardEventKey,
26
- m as normalizeAdapterEvents,
27
- G as normalizeManifestEvents,
28
- g as printSingleValidationResult,
29
- p as printValidationResult,
30
- u as useConcurrentLoading,
31
- K as useDualLoading,
32
- v as validateManifest,
33
- c as validateManifests
8
+ n as DRILL_ACTION,
9
+ t as DRILL_EVENT,
10
+ O as DRILL_STATE,
11
+ N as DYNAMIC_ENUM_KEY,
12
+ A as ENGINE_EVENT_TYPE,
13
+ I as FIELD_ROLE_KEY,
14
+ R as INJECT_PATH_ROOT,
15
+ L as INJECT_PATH_SLOT_PROPS,
16
+ o as LOADING_PROP_NAME,
17
+ S as LOADING_STRATEGY,
18
+ D as LOADING_WRAPPER_TYPE,
19
+ Y as NOTIFY_ERROR_STRATEGY,
20
+ P as NOTIFY_TIMING,
21
+ d as OptionItemSchema,
22
+ l as OptionsSchema,
23
+ C as SLOT_KEY,
24
+ M as STANDARD_EVENT_KEYS,
25
+ r as diagnoseMissingActionImpls,
26
+ m as diagnoseMissingStateKeys,
27
+ G as isCustomEventKey,
28
+ g as isStandardEventKey,
29
+ p as normalizeAdapterEvents,
30
+ u as normalizeManifestEvents,
31
+ K as printSingleValidationResult,
32
+ v as printValidationResult,
33
+ c as useConcurrentLoading,
34
+ f as useDualLoading,
35
+ F as validateManifest,
36
+ V as validateManifests
34
37
  };
@@ -0,0 +1,32 @@
1
+ export declare const DRILL_ACTION: {
2
+ readonly PUSH: "drillPush";
3
+ readonly POP_TO: "drillPopTo";
4
+ readonly RESET: "drillReset";
5
+ };
6
+ export declare const DRILL_STATE: {
7
+ readonly PATH: "drillPath";
8
+ };
9
+ export declare const DRILL_EVENT: {
10
+ readonly NAVIGATE_REQUEST: "drill:navigateRequest";
11
+ readonly RESET_REQUEST: "drill:resetRequest";
12
+ };
13
+ export interface DrillFrame {
14
+ level: string;
15
+ key: string | number;
16
+ label: string;
17
+ record?: unknown;
18
+ }
19
+ export interface DrillNavigateRequest {
20
+ index: number;
21
+ }
22
+ export interface DrillPushParams {
23
+ frame: DrillFrame;
24
+ }
25
+ export interface DrillPopToParams {
26
+ index: number;
27
+ }
28
+ export interface DrillRuntimeProps {
29
+ drillPath?: readonly DrillFrame[];
30
+ onDrillNavigateRequest?: (request: DrillNavigateRequest) => void;
31
+ onDrillResetRequest?: () => void;
32
+ }
@@ -3,5 +3,6 @@ export declare const COMPONENT_TRAIT: {
3
3
  readonly DATA_CONTAINER: "Data.Container";
4
4
  readonly LAYOUT_CONTAINER: "Layout.Container";
5
5
  readonly INTERACTION_CLICKABLE: "Interaction.Clickable";
6
+ readonly INTERACTION_DRILLABLE: "Interaction.Drillable";
6
7
  };
7
8
  export type ComponentTrait = typeof COMPONENT_TRAIT[keyof typeof COMPONENT_TRAIT];
@@ -1,24 +1,24 @@
1
- import { useState as m, useRef as g, useEffect as h, useCallback as E, useMemo as T } from "react";
2
- const _ = () => {
3
- const [t, e] = m(0), [o, n] = m(void 0), c = g(0);
4
- h(() => {
1
+ import { useState as T, useRef as g, useEffect as L, useCallback as u, useMemo as m } from "react";
2
+ const S = () => {
3
+ const [t, e] = T(0), [o, n] = T(void 0), c = g(0);
4
+ L(() => {
5
5
  c.current = t;
6
6
  }, [t]);
7
- const a = E(() => c.current > 0, []), s = E((l) => (e((u) => u + 1), l && n(l), a()), [a]), p = E(() => (e((l) => {
8
- const u = Math.max(0, l - 1);
9
- return u === 0 && n(void 0), u;
10
- }), a()), [a]), r = E(() => {
7
+ const a = u(() => c.current > 0, []), s = u((p) => (e((E) => E + 1), p && n(p), a()), [a]), l = u(() => (e((p) => {
8
+ const E = Math.max(0, p - 1);
9
+ return E === 0 && n(void 0), E;
10
+ }), a()), [a]), r = u(() => {
11
11
  e(0), n(void 0);
12
12
  }, []);
13
- return T(() => ({
13
+ return m(() => ({
14
14
  isLoading: t > 0,
15
15
  loadingText: o,
16
16
  startLoading: s,
17
- stopLoading: p,
17
+ stopLoading: l,
18
18
  getLoading: a,
19
19
  resetLoading: r
20
- }), [a, t, o, r, s, p]);
21
- }, x = () => {
20
+ }), [a, t, o, r, s, l]);
21
+ }, V = () => {
22
22
  const {
23
23
  isLoading: t,
24
24
  loadingText: e,
@@ -26,10 +26,10 @@ const _ = () => {
26
26
  stopLoading: n,
27
27
  getLoading: c,
28
28
  resetLoading: a
29
- } = _(), [s, p] = m(!1), r = T(() => t || s, [t, s]), l = g(!1);
30
- return h(() => {
31
- l.current = r;
32
- }, [r]), T(() => ({
29
+ } = S(), [s, l] = T(!1), r = m(() => t || s, [t, s]), p = g(!1);
30
+ return L(() => {
31
+ p.current = r;
32
+ }, [r]), m(() => ({
33
33
  actionLoading: t,
34
34
  actionLoadingText: e,
35
35
  startActionLoading: o,
@@ -37,9 +37,9 @@ const _ = () => {
37
37
  getActionLoading: c,
38
38
  resetActionLoading: a,
39
39
  dataLoading: s,
40
- setDataLoading: p,
40
+ setDataLoading: l,
41
41
  isLoading: r,
42
- isLoadingRef: l
42
+ isLoadingRef: p
43
43
  }), [
44
44
  t,
45
45
  e,
@@ -62,7 +62,7 @@ function N(t) {
62
62
  });
63
63
  return e;
64
64
  }
65
- function S(t) {
65
+ function O(t) {
66
66
  if (!t)
67
67
  return [];
68
68
  const e = [];
@@ -73,8 +73,8 @@ function S(t) {
73
73
  });
74
74
  return e;
75
75
  }
76
- function v(t) {
77
- const e = N(t?.events), o = S(t?.customEvents);
76
+ function I(t) {
77
+ const e = N(t?.events), o = O(t?.customEvents);
78
78
  return {
79
79
  standard: e,
80
80
  custom: o,
@@ -82,25 +82,34 @@ function v(t) {
82
82
  allKeys: [...e.map((n) => n.type), ...o.map((n) => n.type)]
83
83
  };
84
84
  }
85
- const $ = {
85
+ const v = {
86
86
  type: "object",
87
87
  properties: {
88
88
  label: { type: "string", title: "显示名称" },
89
89
  value: { type: "string", title: "选项值" },
90
90
  disabled: { type: "boolean", title: "是否禁用" }
91
91
  }
92
- }, V = {
92
+ }, x = {
93
93
  type: "array",
94
94
  title: "选项列表",
95
- items: $
95
+ items: v
96
96
  }, J = {
97
+ PUSH: "drillPush",
98
+ POP_TO: "drillPopTo",
99
+ RESET: "drillReset"
100
+ }, W = {
101
+ PATH: "drillPath"
102
+ }, q = {
103
+ NAVIGATE_REQUEST: "drill:navigateRequest",
104
+ RESET_REQUEST: "drill:resetRequest"
105
+ }, Q = {
97
106
  BEFORE: "before",
98
107
  AFTER: "after",
99
108
  BOTH: "both"
100
- }, W = {
109
+ }, X = {
101
110
  IGNORE: "ignore",
102
111
  STOP: "stop"
103
- }, C = {
112
+ }, R = {
104
113
  MOUNT: "mount",
105
114
  UNMOUNT: "unmount",
106
115
  CLICK: "click",
@@ -113,14 +122,14 @@ const $ = {
113
122
  ITEM_LONG_PRESS: "itemLongPress",
114
123
  DATA_FETCH: "dataFetch",
115
124
  OPTIONS_FETCH: "optionsFetch"
116
- }, I = Object.values(C), L = new Set(I), R = /^[^:\s]+:[^:\s]+$/;
117
- function f(t) {
118
- return L.has(t);
119
- }
125
+ }, $ = Object.values(R), h = new Set($), C = /^[^:\s]+:[^:\s]+$/;
120
126
  function y(t) {
121
- return R.test(t) && !L.has(t);
127
+ return h.has(t);
122
128
  }
123
- const q = "x-dynamic-enum", Q = "x-slot", D = "$root", X = "__state", Z = "x-fieldRole", tt = {
129
+ function f(t) {
130
+ return C.test(t) && !h.has(t);
131
+ }
132
+ const Z = "x-dynamic-enum", tt = "x-slot", D = "$root", et = "__state", nt = "x-fieldRole", ot = {
124
133
  ATTRIBUTE: "attribute",
125
134
  DIMENSION: "dimension",
126
135
  MEASURE: "measure"
@@ -156,19 +165,20 @@ function w(t) {
156
165
  allKeys: [...e.map((n) => n.type), ...o.map((n) => n.type)]
157
166
  };
158
167
  }
159
- const et = {
168
+ const at = {
160
169
  NATIVE: "native",
161
170
  WRAPPER: "wrapper",
162
171
  NONE: "none"
163
- }, nt = {
172
+ }, st = {
164
173
  SPIN: "spin",
165
174
  SKELETON: "skeleton",
166
175
  WAVE: "wave"
167
- }, ot = "loading", A = {
176
+ }, rt = "loading", A = {
168
177
  DATA_FIELD: "Data.Field",
169
178
  DATA_CONTAINER: "Data.Container",
170
179
  LAYOUT_CONTAINER: "Layout.Container",
171
- INTERACTION_CLICKABLE: "Interaction.Clickable"
180
+ INTERACTION_CLICKABLE: "Interaction.Clickable",
181
+ INTERACTION_DRILLABLE: "Interaction.Drillable"
172
182
  }, d = {
173
183
  GENERAL: "General",
174
184
  FLOAT: "Float",
@@ -181,7 +191,7 @@ const et = {
181
191
  PAGE: "Page",
182
192
  DEV: "Dev",
183
193
  HTML_TEMPLATE: "HtmlTemplate"
184
- }, at = {
194
+ }, it = {
185
195
  [d.GENERAL]: "通用",
186
196
  [d.FLOAT]: "悬浮",
187
197
  [d.LAYOUT]: "布局",
@@ -193,17 +203,17 @@ const et = {
193
203
  [d.PAGE]: "页面",
194
204
  [d.DEV]: "调试",
195
205
  [d.HTML_TEMPLATE]: "HTML 模板"
196
- }, b = "slotProps.root", Y = [A.DATA_FIELD, A.DATA_CONTAINER], K = [D, b], O = ["string", "number", "boolean", "array", "object", "integer", "null"];
206
+ }, b = "slotProps.root", Y = [A.DATA_FIELD, A.DATA_CONTAINER], K = [D, b], _ = ["string", "number", "boolean", "array", "object", "integer", "null"];
197
207
  function i(t, e, o, n, c) {
198
208
  t.push({ type: e, field: o, message: n, severity: c });
199
209
  }
200
- function F(t, e, o) {
210
+ function U(t, e, o) {
201
211
  const n = t.type;
202
212
  if (!t.meta)
203
213
  return i(e, n, "meta", "meta 字段是必填的", "error"), !1;
204
214
  if (t.meta.title || i(e, n, "meta.title", "title 是必填的", "error"), t.meta.category ? Object.values(d).includes(t.meta.category) || i(e, n, "meta.category", `无效的 category: ${t.meta.category}`, "error") : i(e, n, "meta.category", "category 是必填的", "error"), t.meta.valueSchema) {
205
215
  const a = t.meta.valueSchema.type;
206
- a && typeof a == "string" && !O.includes(a) && i(e, n, "meta.valueSchema.type", `无效的 valueSchema type: ${a}`, "error");
216
+ a && typeof a == "string" && !_.includes(a) && i(e, n, "meta.valueSchema.type", `无效的 valueSchema type: ${a}`, "error");
207
217
  }
208
218
  return t.traits?.some((a) => Y.includes(a)) && !t.meta.valueSchema && i(
209
219
  o,
@@ -213,28 +223,28 @@ function F(t, e, o) {
213
223
  "warning"
214
224
  ), !0;
215
225
  }
216
- function j(t, e, o) {
217
- const n = t.type, c = w(t), a = new Set(c.standard.map((p) => p.type)), s = new Set(c.custom.map((p) => p.type));
218
- if (c.all.length > 0 && (c.standard.forEach((p, r) => {
219
- p.type || i(e, n, `events[${r}].type`, "事件类型不能为空", "error"), p.type && !f(p.type) && i(e, n, `events[${r}].type`, `标准事件类型必须属于 EngineEventProtocol: ${p.type}`, "error");
220
- }), c.custom.forEach((p) => {
221
- p.type || i(e, n, "customEvents.type", "自定义事件类型不能为空", "error"), p.type && !y(p.type) && i(e, n, `customEvents.${p.type}`, `自定义事件类型必须是 namespaced 形态: ${p.type}`, "error"), p.payloadSchema || i(e, n, `customEvents.${p.type}.payloadSchema`, "自定义事件必须声明 payloadSchema", "error");
226
+ function H(t, e, o) {
227
+ const n = t.type, c = w(t), a = new Set(c.standard.map((l) => l.type)), s = new Set(c.custom.map((l) => l.type));
228
+ if (c.all.length > 0 && (c.standard.forEach((l, r) => {
229
+ l.type || i(e, n, `events[${r}].type`, "事件类型不能为空", "error"), l.type && !y(l.type) && i(e, n, `events[${r}].type`, `标准事件类型必须属于 EngineEventProtocol: ${l.type}`, "error");
230
+ }), c.custom.forEach((l) => {
231
+ l.type || i(e, n, "customEvents.type", "自定义事件类型不能为空", "error"), l.type && !f(l.type) && i(e, n, `customEvents.${l.type}`, `自定义事件类型必须是 namespaced 形态: ${l.type}`, "error"), l.payloadSchema || i(e, n, `customEvents.${l.type}.payloadSchema`, "自定义事件必须声明 payloadSchema", "error");
222
232
  })), t.adapter) {
223
- const p = v(t.adapter);
224
- p.standard.forEach((r, l) => {
225
- r.type || i(e, n, `adapter.events[${l}].type`, "Adapter 事件类型不能为空", "error"), r.type && !f(r.type) && i(e, n, `adapter.events[${l}].type`, `Adapter 标准事件类型必须属于 EngineEventProtocol: ${r.type}`, "error"), r.type && f(r.type) && !a.has(r.type) && i(e, n, `adapter.events[${l}].type`, `Adapter 标准事件必须先在 manifest.events 中声明: ${r.type}`, "error"), r.propName || i(e, n, `adapter.events[${l}].propName`, "Adapter propName 不能为空", "error");
226
- }), p.custom.forEach((r) => {
227
- r.type || i(e, n, "adapter.customEvents.type", "Adapter 自定义事件类型不能为空", "error"), r.type && !y(r.type) && i(e, n, `adapter.customEvents.${r.type}`, `Adapter 自定义事件类型必须是 namespaced 形态: ${r.type}`, "error"), r.type && y(r.type) && !s.has(r.type) && i(e, n, `adapter.customEvents.${r.type}`, `Adapter 自定义事件必须先在 manifest.customEvents 中声明: ${r.type}`, "error"), r.propName || i(e, n, `adapter.customEvents.${r.type}.propName`, "Adapter customEvents propName 不能为空", "error");
233
+ const l = I(t.adapter);
234
+ l.standard.forEach((r, p) => {
235
+ r.type || i(e, n, `adapter.events[${p}].type`, "Adapter 事件类型不能为空", "error"), r.type && !y(r.type) && i(e, n, `adapter.events[${p}].type`, `Adapter 标准事件类型必须属于 EngineEventProtocol: ${r.type}`, "error"), r.type && y(r.type) && !a.has(r.type) && i(e, n, `adapter.events[${p}].type`, `Adapter 标准事件必须先在 manifest.events 中声明: ${r.type}`, "error"), r.propName || i(e, n, `adapter.events[${p}].propName`, "Adapter propName 不能为空", "error");
236
+ }), l.custom.forEach((r) => {
237
+ r.type || i(e, n, "adapter.customEvents.type", "Adapter 自定义事件类型不能为空", "error"), r.type && !f(r.type) && i(e, n, `adapter.customEvents.${r.type}`, `Adapter 自定义事件类型必须是 namespaced 形态: ${r.type}`, "error"), r.type && f(r.type) && !s.has(r.type) && i(e, n, `adapter.customEvents.${r.type}`, `Adapter 自定义事件必须先在 manifest.customEvents 中声明: ${r.type}`, "error"), r.propName || i(e, n, `adapter.customEvents.${r.type}.propName`, "Adapter customEvents propName 不能为空", "error");
228
238
  });
229
239
  }
230
240
  }
231
- function G(t, e, o) {
241
+ function F(t, e, o) {
232
242
  const n = t.type, c = t.actions;
233
243
  if (c)
234
244
  for (const [a, s] of Object.entries(c))
235
245
  s && (s.title || i(e, n, `actions.${a}.title`, `动作 "${a}" 缺少 title`, "error"), s.returns || i(o, n, `actions.${a}.returns`, `动作 "${a}" 未声明 returns schema,建议补充`, "warning"), s.params && s.params.type !== "object" && i(e, n, `actions.${a}.params.type`, '动作参数 schema 的 type 必须为 "object"', "error"));
236
246
  }
237
- function H(t, e, o) {
247
+ function G(t, e, o) {
238
248
  const n = t.type, c = t.engine?.render?.injection?.rootPath;
239
249
  c ? typeof c == "string" && !K.includes(c) && i(
240
250
  o,
@@ -250,7 +260,7 @@ function H(t, e, o) {
250
260
  "warning"
251
261
  );
252
262
  }
253
- function U(t, e, o) {
263
+ function j(t, e, o) {
254
264
  const n = t.type, c = t.slots;
255
265
  if (c)
256
266
  for (const [a, s] of Object.entries(c))
@@ -266,17 +276,17 @@ function k(t, e, o) {
266
276
  const n = t.type, c = t.state;
267
277
  if (c)
268
278
  for (const [a, s] of Object.entries(c))
269
- s && (s.title || i(e, n, `state.${a}.title`, `状态 "${a}" 缺少 title`, "error"), s.schema ? s.schema.type && typeof s.schema.type == "string" && !O.includes(s.schema.type) && i(e, n, `state.${a}.schema.type`, `状态 "${a}" 的 schema.type 无效: ${s.schema.type}`, "error") : i(e, n, `state.${a}.schema`, `状态 "${a}" 缺少 schema`, "error"));
279
+ s && (s.title || i(e, n, `state.${a}.title`, `状态 "${a}" 缺少 title`, "error"), s.schema ? s.schema.type && typeof s.schema.type == "string" && !_.includes(s.schema.type) && i(e, n, `state.${a}.schema.type`, `状态 "${a}" 的 schema.type 无效: ${s.schema.type}`, "error") : i(e, n, `state.${a}.schema`, `状态 "${a}" 缺少 schema`, "error"));
270
280
  }
271
281
  function z(t) {
272
282
  const e = [], o = [];
273
- return t.type || i(e, t.type || "Unknown", "type", "type 字段是必填的", "error"), F(t, e, o) ? (j(t, e), G(t, e, o), k(t, e), U(t, e, o), H(t, e, o), {
283
+ return t.type || i(e, t.type || "Unknown", "type", "type 字段是必填的", "error"), U(t, e, o) ? (H(t, e), F(t, e, o), k(t, e), j(t, e, o), G(t, e, o), {
274
284
  valid: e.length === 0,
275
285
  errors: e,
276
286
  warnings: o
277
287
  }) : { valid: !1, errors: e, warnings: o };
278
288
  }
279
- function st(t) {
289
+ function ct(t) {
280
290
  const e = [], o = [];
281
291
  for (const n of t) {
282
292
  const c = z(n);
@@ -288,13 +298,13 @@ function st(t) {
288
298
  warnings: o
289
299
  };
290
300
  }
291
- function rt(t, e) {
301
+ function lt(t, e) {
292
302
  return !t || !e ? [] : t.filter((o) => typeof e[o] != "function");
293
303
  }
294
- function it(t, e) {
304
+ function pt(t, e) {
295
305
  return !t?.state || !e ? [] : Object.keys(t.state).filter((o) => !(o in e));
296
306
  }
297
- function ct(t) {
307
+ function dt(t) {
298
308
  t.valid ? console.log("✅ 所有 Manifest 验证通过") : console.error(`❌ 发现 ${t.errors.length} 个错误`), t.errors.length > 0 && (console.error(`
299
309
  错误列表:`), t.errors.forEach((e) => {
300
310
  console.error(` ❌ [${e.type}] ${e.field}: ${e.message}`);
@@ -303,7 +313,7 @@ function ct(t) {
303
313
  console.warn(` ⚠️ [${e.type}] ${e.field}: ${e.message}`);
304
314
  }));
305
315
  }
306
- function pt(t, e = "[Registry]") {
316
+ function Et(t, e = "[Registry]") {
307
317
  if (!t.valid && t.errors.length > 0) {
308
318
  const o = t.errors[0]?.type || "Unknown";
309
319
  console.error(`${e} ❌ Manifest validation failed for '${o}':`), t.errors.forEach((n) => console.error(` - ${n.field}: ${n.message}`));
@@ -314,35 +324,38 @@ function pt(t, e = "[Registry]") {
314
324
  }
315
325
  }
316
326
  export {
317
- at as C,
318
- tt as D,
319
- C as E,
320
- Z as F,
327
+ it as C,
328
+ ot as D,
329
+ R as E,
330
+ nt as F,
321
331
  D as I,
322
- ot as L,
323
- W as N,
324
- $ as O,
325
- Q as S,
332
+ rt as L,
333
+ X as N,
334
+ v as O,
335
+ tt as S,
326
336
  d as a,
327
- X as b,
337
+ et as b,
328
338
  A as c,
329
- q as d,
330
- b as e,
331
- et as f,
332
- nt as g,
333
- J as h,
334
- V as i,
335
- I as j,
336
- rt as k,
337
- it as l,
338
- y as m,
339
- f as n,
340
- v as o,
341
- w as p,
342
- pt as q,
343
- ct as r,
344
- x as s,
345
- st as t,
346
- _ as u,
347
- z as v
339
+ J as d,
340
+ q as e,
341
+ W as f,
342
+ Z as g,
343
+ b as h,
344
+ at as i,
345
+ st as j,
346
+ Q as k,
347
+ x as l,
348
+ $ as m,
349
+ lt as n,
350
+ pt as o,
351
+ f as p,
352
+ y as q,
353
+ I as r,
354
+ w as s,
355
+ Et as t,
356
+ dt as u,
357
+ S as v,
358
+ V as w,
359
+ z as x,
360
+ ct as y
348
361
  };
@@ -83,6 +83,13 @@
83
83
  - [声明事件](./recipes/声明事件.md)
84
84
  - [Events 模型](./reference/Events模型.md)
85
85
 
86
+ ### 我要让组件支持层级下钻
87
+
88
+ 阅读:
89
+
90
+ - [声明层级下钻能力](./recipes/声明层级下钻能力.md)
91
+ - [层级下钻能力模型](./reference/层级下钻能力模型.md)
92
+
86
93
  ### 我要让流程或 AI 调用组件方法
87
94
 
88
95
  阅读:
@@ -0,0 +1,34 @@
1
+ ---
2
+ type: recipe
3
+ capability: drill
4
+ related:
5
+ - reference/层级下钻能力模型.md
6
+ - recipes/声明事件.md
7
+ - recipes/声明动作与状态.md
8
+ ---
9
+
10
+ # 声明层级下钻能力
11
+
12
+ ## 适用场景
13
+
14
+ 组件需要展示宿主维护的层级路径,并请求返回历史层或根层时使用。普通详情跳转不属于层级下钻。
15
+
16
+ ## 步骤
17
+
18
+ 1. 在 manifest 的 `traits` 中加入 `COMPONENT_TRAIT.INTERACTION_DRILLABLE`。
19
+ 2. 组件接收 `DrillRuntimeProps`,受控渲染 `drillPath`。
20
+ 3. 点击历史节点时调用 `onDrillNavigateRequest({ index })`;返回根层时调用 `onDrillResetRequest()`。
21
+ 4. 在组件库内共享路径视图,不在每个 Chart、Table 或 CardList 重复实现。
22
+ 5. 用 `validateManifest()` 检查 manifest。
23
+
24
+ 不要在组件内保存第二份路径,也不要重复声明 trait 自动提供的 actions、state 和 events。数据查询、参数加工与更新成功后的 `drillPush` / `drillPopTo` / `drillReset` 由宿主事件编排完成。
25
+
26
+ ## 自检
27
+
28
+ - 空路径不产生额外 DOM 或高度。
29
+ - 路径点击只发请求,不立即修改状态。
30
+ - 查询成功后再调用对应下钻 action。
31
+
32
+ ## 关联文档
33
+
34
+ - [层级下钻能力模型](../reference/层级下钻能力模型.md)
@@ -24,6 +24,7 @@ Traits 之间不互斥,一个组件可以同时声明多个 trait。例如 For
24
24
  | `Data.Container` | `COMPONENT_TRAIT.DATA_CONTAINER` | Form、Table、List、CardList | 组件管理一组数据作用域 |
25
25
  | `Layout.Container` | `COMPONENT_TRAIT.LAYOUT_CONTAINER` | 通用容器:Card、Grid、Section;强组合关系:Tabs、Steps、Form(带 `nesting` 类型约束) | 组件具备**默认 children 区域**(与 `manifest.slots` 是两条独立机制) |
26
26
  | `Interaction.Clickable` | `COMPONENT_TRAIT.INTERACTION_CLICKABLE` | Button、Link、ClickableCard | 组件具备点击交互语义 |
27
+ | `Interaction.Drillable` | `COMPONENT_TRAIT.INTERACTION_DRILLABLE` | Chart、Table、CardList | 宿主为组件实例提供受控下钻路径、动作和导航请求事件 |
27
28
 
28
29
  ---
29
30
 
@@ -154,6 +155,23 @@ Traits 之间不互斥,一个组件可以同时声明多个 trait。例如 For
154
155
 
155
156
  ---
156
157
 
158
+ ## INTERACTION_DRILLABLE
159
+
160
+ ### 什么时候声明
161
+
162
+ 组件能够沿数据层级进入下一层并返回历史层,例如图表维度下钻、表格或卡片列表的下一级记录。
163
+
164
+ ### 作者要做什么
165
+
166
+ - 声明 `COMPONENT_TRAIT.INTERACTION_DRILLABLE`。
167
+ - 接收宿主注入的 `drillPath`,并以适合自身布局的方式展示路径。
168
+ - 用户选择历史层时调用 `onDrillNavigateRequest({ index })`。
169
+ - 不在组件内部维护第二份路径状态,也不在 manifest 重复声明 trait 自动提供的 props、event、actions 和 state。
170
+
171
+ 完整契约与编排边界见 [层级下钻能力模型](./层级下钻能力模型.md)。
172
+
173
+ ---
174
+
157
175
  ## Traits 与 valueSchema
158
176
 
159
177
  声明 `DATA_FIELD` 或 `DATA_CONTAINER` 时,建议同时声明 `meta.valueSchema`。
@@ -194,6 +212,7 @@ meta: {
194
212
  | `DATA_CONTAINER` | 用于管理子字段数据作用域;必须在子组件渲染区域提供 `DataScope`。与 `LAYOUT_CONTAINER` 不互斥,Form 这类容器应同时声明 |
195
213
  | `LAYOUT_CONTAINER` | 控制**默认 children 区域**开关,仅影响 `schema.children` 是否被宿主递归渲染。具名子区域走 `manifest.slots`,与本 trait 互不依赖 |
196
214
  | `INTERACTION_CLICKABLE` | 表示具备点击语义;需要编排响应时再声明 click event |
215
+ | `INTERACTION_DRILLABLE` | 表示具备层级下钻语义;宿主维护路径状态,组件只做受控展示与导航请求 |
197
216
 
198
217
  数据 trait 与 `meta.valueSchema` 的校验级别见 [validateManifest 校验规则](./validateManifest校验规则.md)。
199
218
 
@@ -0,0 +1,80 @@
1
+ ---
2
+ type: reference
3
+ capability: drill
4
+ related:
5
+ - recipes/声明层级下钻能力.md
6
+ - reference/Traits能力模型.md
7
+ - reference/Events模型.md
8
+ - reference/ActionsState模型.md
9
+ ---
10
+
11
+ # 层级下钻能力模型
12
+
13
+ `INTERACTION_DRILLABLE` 声明组件能够沿数据层级进入、返回和复位。它只定义跨包契约:宿主维护路径状态并执行编排,组件通过受控 props 展示路径并发出导航请求。当 `drillPath` 为空时表示根层,当前层由末帧派生,不单独保存。
14
+
15
+ ## 组件作者接入
16
+
17
+ ```tsx
18
+ import type { DrillRuntimeProps } from 'cdp-material-sdk/portable';
19
+ import { COMPONENT_TRAIT } from 'cdp-material-sdk/portable';
20
+
21
+ export const manifest = {
22
+ // ...
23
+ traits: [COMPONENT_TRAIT.INTERACTION_DRILLABLE],
24
+ };
25
+
26
+ export function Chart({
27
+ drillPath = [],
28
+ onDrillNavigateRequest,
29
+ onDrillResetRequest,
30
+ }: DrillRuntimeProps) {
31
+ return (
32
+ <DrillPathView
33
+ items={drillPath}
34
+ onNavigate={(index) => onDrillNavigateRequest?.({ index })}
35
+ onReset={() => onDrillResetRequest?.()}
36
+ />
37
+ );
38
+ }
39
+ ```
40
+
41
+ 组件负责路径 UI 的位置与样式,但不自行保存第二份路径状态。一个组件库内的 Chart、Table、CardList 应复用库内共享的纯展示组件。
42
+
43
+ ## 宿主自动提供的契约
44
+
45
+ | 类别 | 名称 | 语义 |
46
+ |---|---|---|
47
+ | Prop | `drillPath` | 当前组件实例的受控路径,类型为 `DrillFrame[]` |
48
+ | Prop | `onDrillNavigateRequest` | 用户点击历史路径节点时调用,参数为 `{ index }` |
49
+ | Prop | `onDrillResetRequest` | 用户请求返回根层时调用 |
50
+ | Event | `drill:navigateRequest` | 将返回请求交给事件编排 |
51
+ | Event | `drill:resetRequest` | 将返回根层请求交给事件编排 |
52
+ | Action | `drillPush({ frame })` | 成功取得下一层数据后追加路径 |
53
+ | Action | `drillPopTo({ index })` | 成功取得历史层数据后截断路径 |
54
+ | Action | `drillReset()` | 返回根层 |
55
+ | State | `drillPath` | 供表达式读取的当前路径快照 |
56
+
57
+ 以上字段由 trait 对应的宿主 Feature 自动注入,组件 manifest 不要重复声明 props、event、actions 或 state。
58
+
59
+ ## 编排边界
60
+
61
+ 下钻状态不负责查询。推荐顺序是:
62
+
63
+ ```text
64
+ itemClick
65
+ → 参数加工 / 条件判断
66
+ → 查询并更新组件数据
67
+ → component.invoke(drillPush, { frame })
68
+ ```
69
+
70
+ 返回历史层同理:先查询并更新数据,成功后再调用 `drillPopTo`。查询失败时路径保持不变。
71
+
72
+ ## 公共导出
73
+
74
+ 以下内容均从 `cdp-material-sdk/portable` 导入:
75
+
76
+ - `COMPONENT_TRAIT.INTERACTION_DRILLABLE`
77
+ - `DRILL_ACTION`、`DRILL_STATE`、`DRILL_EVENT`
78
+ - `DrillFrame`、`DrillNavigateRequest`、`DrillPushParams`、`DrillPopToParams`、`DrillRuntimeProps`
79
+
80
+ SDK 不提供下钻 Hook、HOC 或面包屑 UI;这些分别属于宿主 Feature 和外置 UI 库。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cdp-material-sdk",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public",