@declarion/react 0.29.0 → 0.31.1

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.
Files changed (32) hide show
  1. package/dist-lib/{ActionRunner-DtUDeH4F.js → ActionRunner-BzaZQtiI.js} +1150 -993
  2. package/dist-lib/{DraggableChildrenTable-D4WoV6ck.js → DraggableChildrenTable-DILqStHQ.js} +29 -29
  3. package/dist-lib/{Grid-CsK_TuK_.js → Grid-BIsiUwPh.js} +2 -2
  4. package/dist-lib/LayoutRenderer-3RvIsC9M.js +2885 -0
  5. package/dist-lib/{MarkdownRenderer-CwlNQju5.js → MarkdownRenderer-CaHhWrfm.js} +1 -1
  6. package/dist-lib/SmartDetailPage.impl--EO-9fos.js +1494 -0
  7. package/dist-lib/SmartRecordListPage.impl-B1iws8yf.js +763 -0
  8. package/dist-lib/components/detail-layout/DraggableChildrenTable.d.ts +1 -0
  9. package/dist-lib/components/detail-layout/EditableChildrenTable.d.ts +2 -1
  10. package/dist-lib/components/detail-layout/FieldRow.d.ts +2 -1
  11. package/dist-lib/components/detail-layout/LayoutRenderer.d.ts +2 -0
  12. package/dist-lib/components/layout/TenantChip.d.ts +2 -1
  13. package/dist-lib/components/layout/TopBar.d.ts +9 -1
  14. package/dist-lib/components/pages/SmartDetailPage.d.ts +2 -5
  15. package/dist-lib/components/pages/SmartDetailPage.impl.d.ts +4 -0
  16. package/dist-lib/components/pages/SmartRecordListPage.d.ts +2 -5
  17. package/dist-lib/components/pages/SmartRecordListPage.impl.d.ts +4 -0
  18. package/dist-lib/components/pages/list/ListHeader.d.ts +6 -1
  19. package/dist-lib/components/pages/list/cardProjection.d.ts +66 -0
  20. package/dist-lib/declarion-react.css +1 -1
  21. package/dist-lib/hooks/useResponsiveMode.d.ts +30 -0
  22. package/dist-lib/index.d.ts +2 -0
  23. package/dist-lib/index.js +6748 -15502
  24. package/dist-lib/lib/actions.d.ts +10 -0
  25. package/dist-lib/peekDraftStore-yyzMbaiI.js +468 -0
  26. package/dist-lib/registry-2KliNTHB.js +5177 -0
  27. package/dist-lib/testing.d.ts +3 -0
  28. package/dist-lib/testing.js +55 -52
  29. package/dist-lib/types/schema.d.ts +50 -4
  30. package/dist-lib/useProperties-Co3RdtuT.js +453 -0
  31. package/dist-lib/{value-CNUbJNK-.js → value-BooGwUik.js} +1 -1
  32. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import { type ReactElement, type ReactNode } from "react";
2
2
  import { type RenderResult } from "@testing-library/react";
3
3
  import { QueryClient } from "@tanstack/react-query";
4
+ import { type ResponsiveViewport } from "./hooks/useResponsiveMode";
4
5
  import { type ActionExecuteRequest, type ActionExecuteResponse } from "./api/data";
5
6
  import type { Schema } from "./types/schema";
6
7
  import type { ListMeta, ListResponse, Refs } from "./types/api";
@@ -30,6 +31,8 @@ export interface RenderWithDeclarionOptions {
30
31
  actionResults?: Record<string, ActionResult>;
31
32
  /** Initial path for the memory router (e.g. "/replay/abc/compare"). Default "/". */
32
33
  route?: string;
34
+ /** Optional responsive viewport seam for component tests that assert phone/tablet behavior. */
35
+ viewport?: ResponsiveViewport;
33
36
  }
34
37
  export interface RenderWithDeclarionResult extends RenderResult {
35
38
  /** The live QueryClient, for advanced cache assertions or manual refetch. */
@@ -1,12 +1,12 @@
1
- import { H as e, X as t, Y as n, Z as r, mt as i, t as a } from "./ActionRunner-DtUDeH4F.js";
2
- import { useState as o } from "react";
3
- import { MemoryRouter as s } from "react-router-dom";
4
- import { QueryClient as c, QueryClientProvider as l } from "@tanstack/react-query";
5
- import { Toaster as u } from "sonner";
6
- import { jsx as d, jsxs as f } from "react/jsx-runtime";
7
- import { render as p } from "@testing-library/react";
1
+ import { H as e, Nn as t, X as n, Y as r, Z as i, mt as a, t as o } from "./ActionRunner-BzaZQtiI.js";
2
+ import { useState as s } from "react";
3
+ import { MemoryRouter as c } from "react-router-dom";
4
+ import { QueryClient as l, QueryClientProvider as u } from "@tanstack/react-query";
5
+ import { Toaster as d } from "sonner";
6
+ import { jsx as f, jsxs as p } from "react/jsx-runtime";
7
+ import { render as m } from "@testing-library/react";
8
8
  //#region src/testing.tsx
9
- function m(e = {}) {
9
+ function h(e = {}) {
10
10
  return {
11
11
  languages: [],
12
12
  structures: {},
@@ -19,7 +19,7 @@ function m(e = {}) {
19
19
  ...e
20
20
  };
21
21
  }
22
- function h(e, t = {}, n) {
22
+ function g(e, t = {}, n) {
23
23
  return {
24
24
  data: e,
25
25
  meta: {
@@ -33,27 +33,27 @@ function h(e, t = {}, n) {
33
33
  ...n === void 0 ? {} : { $refs: n }
34
34
  };
35
35
  }
36
- function g(e) {
36
+ function _(e) {
37
37
  return e;
38
38
  }
39
- var _ = Symbol("declarion.testing.actionEnvelope");
40
- function v(e) {
39
+ var v = Symbol("declarion.testing.actionEnvelope");
40
+ function y(e) {
41
41
  return {
42
42
  ...e,
43
- [_]: !0
43
+ [v]: !0
44
44
  };
45
45
  }
46
- function y(e) {
47
- if (e && typeof e == "object" && e[_]) {
46
+ function b(e) {
47
+ if (e && typeof e == "object" && e[v]) {
48
48
  let t = { ...e };
49
- return delete t[_], t;
49
+ return delete t[v], t;
50
50
  }
51
51
  return {
52
52
  status: "success",
53
53
  result: e
54
54
  };
55
55
  }
56
- function b() {
56
+ function x() {
57
57
  let e = {
58
58
  id: "test-tenant",
59
59
  code: "test",
@@ -70,9 +70,9 @@ function b() {
70
70
  created_at: "2026-01-01T00:00:00Z",
71
71
  updated_at: "2026-01-01T00:00:00Z"
72
72
  };
73
- i.getState().setUser(t, e);
73
+ a.getState().setUser(t, e);
74
74
  }
75
- function x(e) {
75
+ function S(e) {
76
76
  if (e === void 0) return { rows: [] };
77
77
  if (Array.isArray(e)) return { rows: e };
78
78
  if (Array.isArray(e.data)) {
@@ -85,10 +85,10 @@ function x(e) {
85
85
  }
86
86
  return e;
87
87
  }
88
- function S(i) {
89
- let a = i.entityData ?? {};
90
- r((e, t) => {
91
- let n = a[e], r = x(n), i = r.meta?.per_page ?? 50, o = r.meta?.total ?? r.rows.length;
88
+ function C(t) {
89
+ let a = t.entityData ?? {};
90
+ i((e, t) => {
91
+ let n = a[e], r = S(n), i = r.meta?.per_page ?? 50, o = r.meta?.total ?? r.rows.length;
92
92
  return t.count === "only" ? {
93
93
  data: [],
94
94
  meta: {
@@ -108,62 +108,65 @@ function S(i) {
108
108
  ...r.refs === void 0 ? {} : { $refs: r.refs }
109
109
  };
110
110
  });
111
- let o = i.entityItems ?? {};
112
- t((t, n) => {
111
+ let o = t.entityItems ?? {};
112
+ n((t, n) => {
113
113
  let r = typeof n == "string" ? n : e(n);
114
114
  return { data: o[t]?.[r] };
115
115
  });
116
- let s = i.actionResults ?? {};
117
- n(async (e, t) => {
116
+ let s = t.actionResults ?? {};
117
+ r(async (e, t) => {
118
118
  if (!(e in s)) throw Error(`renderWithDeclarion: no action result registered for "${e}" (seed it via actionResults)`);
119
119
  let n = s[e];
120
- return y(typeof n == "function" ? await n(t) : n);
120
+ return b(typeof n == "function" ? await n(t) : n);
121
121
  });
122
122
  }
123
- function C() {
124
- r(null), t(null), n(null), i.setState({
123
+ function w() {
124
+ i(null), n(null), r(null), a.setState({
125
125
  user: null,
126
126
  isAuthenticated: !1,
127
127
  activeTenant: null,
128
128
  tenants: []
129
129
  });
130
130
  }
131
- function w(e, t = {}) {
132
- let n = new c({ defaultOptions: { queries: {
131
+ function T(e, n = {}) {
132
+ let r = new l({ defaultOptions: { queries: {
133
133
  retry: !1,
134
134
  gcTime: Infinity
135
135
  } } });
136
- b(), n.setQueryData(["schema", !0], t.schema ?? m()), S(t);
137
- let r = p(/* @__PURE__ */ f(l, {
138
- client: n,
139
- children: [/* @__PURE__ */ d(s, {
140
- initialEntries: [t.route ?? "/"],
141
- children: /* @__PURE__ */ d(a, { children: e })
142
- }), /* @__PURE__ */ d(u, {})]
143
- }));
144
- return Object.assign(r, { queryClient: n });
136
+ x(), r.setQueryData(["schema", !0], n.schema ?? h()), C(n);
137
+ let i = /* @__PURE__ */ p(u, {
138
+ client: r,
139
+ children: [/* @__PURE__ */ f(c, {
140
+ initialEntries: [n.route ?? "/"],
141
+ children: /* @__PURE__ */ f(o, { children: e })
142
+ }), /* @__PURE__ */ f(d, {})]
143
+ }), a = m(n.viewport ? /* @__PURE__ */ f(t, {
144
+ viewportOverride: n.viewport,
145
+ children: i
146
+ }) : i);
147
+ return Object.assign(a, { queryClient: r });
145
148
  }
146
- function T({ children: e, authenticated: t = !0, ...n }) {
147
- let [r] = o(() => {
148
- let e = new c({ defaultOptions: { queries: {
149
+ function E({ children: e, authenticated: t = !0, ...n }) {
150
+ let [r] = s(() => {
151
+ let e = new l({ defaultOptions: { queries: {
149
152
  retry: !1,
150
153
  gcTime: Infinity
151
154
  } } });
152
- return t ? (b(), e.setQueryData(["schema", !0], n.schema ?? m())) : i.setState({
155
+ return t ? (x(), e.setQueryData(["schema", !0], n.schema ?? h())) : a.setState({
153
156
  user: null,
154
157
  isAuthenticated: !1,
155
158
  activeTenant: null,
156
159
  tenants: []
157
- }), S(n), e;
160
+ }), C(n), e;
158
161
  });
159
- return /* @__PURE__ */ f(l, {
162
+ return /* @__PURE__ */ p(u, {
160
163
  client: r,
161
- children: [/* @__PURE__ */ d(s, {
164
+ children: [/* @__PURE__ */ f(c, {
162
165
  initialEntries: [n.route ?? "/"],
163
- children: /* @__PURE__ */ d(a, { children: e })
164
- }), /* @__PURE__ */ d(u, {})]
166
+ children: /* @__PURE__ */ f(o, { children: e })
167
+ }), /* @__PURE__ */ f(d, {})]
165
168
  });
166
169
  }
167
- typeof afterEach == "function" && afterEach(() => C());
170
+ typeof afterEach == "function" && afterEach(() => w());
168
171
  //#endregion
169
- export { T as PreviewHarness, v as actionEnvelope, g as actionResults, C as cleanupDeclarion, h as entityDataFixture, w as renderWithDeclarion, m as schemaFixture };
172
+ export { E as PreviewHarness, y as actionEnvelope, _ as actionResults, w as cleanupDeclarion, g as entityDataFixture, T as renderWithDeclarion, h as schemaFixture };
@@ -186,6 +186,7 @@ export interface ChildQuickAdd {
186
186
  }
187
187
  export interface ChildDisplay {
188
188
  name: LocalizedString;
189
+ description?: LocalizedString;
189
190
  icon?: string;
190
191
  mode?: ChildDisplayMode;
191
192
  columns?: string[];
@@ -268,6 +269,7 @@ export interface ParameterDef {
268
269
  }
269
270
  export interface AssociationDisplay {
270
271
  name?: LocalizedString;
272
+ description?: LocalizedString;
271
273
  icon?: string;
272
274
  }
273
275
  export interface AssociationDef {
@@ -294,6 +296,15 @@ export interface OpSet {
294
296
  write?: boolean;
295
297
  delete?: boolean;
296
298
  }
299
+ export interface CardSpec {
300
+ title_field?: string;
301
+ subtitle_field?: string;
302
+ badge_fields?: string[];
303
+ fields?: string[];
304
+ meta_fields?: string[];
305
+ hide_empty_fields?: boolean;
306
+ max_body_fields?: number;
307
+ }
297
308
  export interface Entity {
298
309
  table: string;
299
310
  primary_key?: string[];
@@ -310,6 +321,7 @@ export interface Entity {
310
321
  display_template?: string;
311
322
  empty_state?: EmptyStateDef;
312
323
  };
324
+ card?: CardSpec;
313
325
  fields: OrderedMap<EntityField>;
314
326
  soft_delete?: string;
315
327
  tenant_key?: string;
@@ -518,6 +530,32 @@ export interface ScreenVisibility {
518
530
  required_permission: string;
519
531
  source: string;
520
532
  }
533
+ export type ViewportKey = "phone" | "tablet" | "desktop";
534
+ export type ListPresentation = "table" | "cards";
535
+ export type RecordListPresentation = "split" | "drilldown" | "stacked";
536
+ export type DetailTabsPresentation = "sections" | "scroll";
537
+ export type DetailSidebarPresentation = "inline" | "hidden";
538
+ export type RelatedRecordsPresentation = "cards" | "table";
539
+ export interface ResponsiveDetailLayout {
540
+ header_card?: boolean;
541
+ tabs?: DetailTabsPresentation;
542
+ sidebar?: DetailSidebarPresentation;
543
+ related_records?: RelatedRecordsPresentation;
544
+ }
545
+ export interface ResponsiveListBranch {
546
+ presentation?: ListPresentation;
547
+ }
548
+ export interface ResponsiveDetailBranch {
549
+ header_card?: boolean;
550
+ tabs?: DetailTabsPresentation;
551
+ }
552
+ export interface ScreenResponsiveViewport {
553
+ presentation?: ListPresentation | RecordListPresentation;
554
+ layout?: ResponsiveDetailLayout;
555
+ list?: ResponsiveListBranch;
556
+ detail?: ResponsiveDetailBranch;
557
+ }
558
+ export type ScreenResponsive = Partial<Record<ViewportKey, ScreenResponsiveViewport>>;
521
559
  export interface Screen {
522
560
  type: "list" | "detail" | "custom" | "record_list";
523
561
  entity?: string;
@@ -536,10 +574,15 @@ export interface Screen {
536
574
  visibility?: ScreenVisibility;
537
575
  display?: {
538
576
  name: LocalizedString;
577
+ /** Localized explanation of the screen, surfaced via the list-header info
578
+ * affordance (falls back to the entity description). Optional. */
579
+ description?: LocalizedString;
539
580
  icon: string;
540
581
  };
541
582
  columns?: string[];
542
583
  default_columns?: string[];
584
+ card?: CardSpec;
585
+ responsive?: ScreenResponsive;
543
586
  filters?: string[];
544
587
  default_filters?: string[];
545
588
  search_fields?: string[];
@@ -617,6 +660,7 @@ export interface ActivityRailConfig {
617
660
  export interface ViewDefinition {
618
661
  code: string;
619
662
  name: LocalizedString;
663
+ description?: LocalizedString;
620
664
  icon?: string;
621
665
  filters?: Array<{
622
666
  field: string;
@@ -806,11 +850,12 @@ export interface Action {
806
850
  */
807
851
  shortcut?: string;
808
852
  /**
809
- * Localized help text for tooltip/popover.
810
- * Reason: separate from display.name so the title stays terse while a
811
- * longer explanation surfaces on hover.
853
+ * Localized explanation of what the action does. Surfaces as the control
854
+ * tooltip (precedence: disabled-reason > description > name) and the
855
+ * ActionDialog subtitle. Optional; absent renders exactly as before.
856
+ * (Supersedes the removed `help` field - plan 2026-07-02 Decision 16.)
812
857
  */
813
- help?: LocalizedString;
858
+ description?: LocalizedString;
814
859
  };
815
860
  visibility?: string[];
816
861
  confirmation?: LocalizedString;
@@ -874,6 +919,7 @@ export interface HandlerDef {
874
919
  entity?: string;
875
920
  display?: {
876
921
  name?: LocalizedString;
922
+ description?: LocalizedString;
877
923
  icon?: string;
878
924
  };
879
925
  params?: OrderedMap<HandlerParam>;