@loomwork/blueprint-runtime 0.0.0-stage → 0.1.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 (117) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +8 -0
  3. package/README.md +83 -2
  4. package/dist/Blueprint.d.ts +14 -0
  5. package/dist/Blueprint.d.ts.map +1 -0
  6. package/dist/Blueprint.js +18 -0
  7. package/dist/Blueprint.js.map +1 -0
  8. package/dist/RendererRegistry.d.ts +9 -0
  9. package/dist/RendererRegistry.d.ts.map +1 -0
  10. package/dist/RendererRegistry.js +39 -0
  11. package/dist/RendererRegistry.js.map +1 -0
  12. package/dist/catalog.d.ts +129 -0
  13. package/dist/catalog.d.ts.map +1 -0
  14. package/dist/catalog.js +435 -0
  15. package/dist/catalog.js.map +1 -0
  16. package/dist/coverage.d.ts +18 -0
  17. package/dist/coverage.d.ts.map +1 -0
  18. package/dist/coverage.js +22 -0
  19. package/dist/coverage.js.map +1 -0
  20. package/dist/customWidget.d.ts +10 -0
  21. package/dist/customWidget.d.ts.map +1 -0
  22. package/dist/customWidget.js +34 -0
  23. package/dist/customWidget.js.map +1 -0
  24. package/dist/esm/Blueprint.js +15 -0
  25. package/dist/esm/Blueprint.js.map +1 -0
  26. package/dist/esm/RendererRegistry.js +35 -0
  27. package/dist/esm/RendererRegistry.js.map +1 -0
  28. package/dist/esm/catalog.js +430 -0
  29. package/dist/esm/catalog.js.map +1 -0
  30. package/dist/esm/coverage.js +19 -0
  31. package/dist/esm/coverage.js.map +1 -0
  32. package/dist/esm/customWidget.js +31 -0
  33. package/dist/esm/customWidget.js.map +1 -0
  34. package/dist/esm/identity.js +116 -0
  35. package/dist/esm/identity.js.map +1 -0
  36. package/dist/esm/index.js +15 -0
  37. package/dist/esm/index.js.map +1 -0
  38. package/dist/esm/irVersion.js +150 -0
  39. package/dist/esm/irVersion.js.map +1 -0
  40. package/dist/esm/layout.js +63 -0
  41. package/dist/esm/layout.js.map +1 -0
  42. package/dist/esm/normalize.js +115 -0
  43. package/dist/esm/normalize.js.map +1 -0
  44. package/dist/esm/pins.js +82 -0
  45. package/dist/esm/pins.js.map +1 -0
  46. package/dist/esm/traverseBlueprint.js +38 -0
  47. package/dist/esm/traverseBlueprint.js.map +1 -0
  48. package/dist/esm/traverseBlueprintAsync.js +48 -0
  49. package/dist/esm/traverseBlueprintAsync.js.map +1 -0
  50. package/dist/esm/types.js +2 -0
  51. package/dist/esm/types.js.map +1 -0
  52. package/dist/esm/widgetStatus.js +137 -0
  53. package/dist/esm/widgetStatus.js.map +1 -0
  54. package/dist/esm/widgets.js +105 -0
  55. package/dist/esm/widgets.js.map +1 -0
  56. package/dist/identity.d.ts +58 -0
  57. package/dist/identity.d.ts.map +1 -0
  58. package/dist/identity.js +122 -0
  59. package/dist/identity.js.map +1 -0
  60. package/dist/index.d.ts +24 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +61 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/irVersion.d.ts +23 -0
  65. package/dist/irVersion.d.ts.map +1 -0
  66. package/dist/irVersion.js +153 -0
  67. package/dist/irVersion.js.map +1 -0
  68. package/dist/layout.d.ts +57 -0
  69. package/dist/layout.d.ts.map +1 -0
  70. package/dist/layout.js +71 -0
  71. package/dist/layout.js.map +1 -0
  72. package/dist/normalize.d.ts +29 -0
  73. package/dist/normalize.d.ts.map +1 -0
  74. package/dist/normalize.js +126 -0
  75. package/dist/normalize.js.map +1 -0
  76. package/dist/pins.d.ts +27 -0
  77. package/dist/pins.d.ts.map +1 -0
  78. package/dist/pins.js +86 -0
  79. package/dist/pins.js.map +1 -0
  80. package/dist/traverseBlueprint.d.ts +27 -0
  81. package/dist/traverseBlueprint.d.ts.map +1 -0
  82. package/dist/traverseBlueprint.js +40 -0
  83. package/dist/traverseBlueprint.js.map +1 -0
  84. package/dist/traverseBlueprintAsync.d.ts +18 -0
  85. package/dist/traverseBlueprintAsync.d.ts.map +1 -0
  86. package/dist/traverseBlueprintAsync.js +51 -0
  87. package/dist/traverseBlueprintAsync.js.map +1 -0
  88. package/dist/types.d.ts +176 -0
  89. package/dist/types.d.ts.map +1 -0
  90. package/dist/types.js +3 -0
  91. package/dist/types.js.map +1 -0
  92. package/dist/widgetStatus.d.ts +66 -0
  93. package/dist/widgetStatus.d.ts.map +1 -0
  94. package/dist/widgetStatus.js +141 -0
  95. package/dist/widgetStatus.js.map +1 -0
  96. package/dist/widgets.d.ts +101 -0
  97. package/dist/widgets.d.ts.map +1 -0
  98. package/dist/widgets.js +115 -0
  99. package/dist/widgets.js.map +1 -0
  100. package/package.json +60 -3
  101. package/src/Blueprint.ts +28 -0
  102. package/src/RendererRegistry.ts +38 -0
  103. package/src/catalog.ts +638 -0
  104. package/src/coverage.ts +52 -0
  105. package/src/customWidget.ts +42 -0
  106. package/src/identity.ts +178 -0
  107. package/src/index.ts +84 -0
  108. package/src/irVersion.ts +195 -0
  109. package/src/layout.ts +105 -0
  110. package/src/normalize.ts +130 -0
  111. package/src/pins.ts +84 -0
  112. package/src/traverseBlueprint.bench.ts +47 -0
  113. package/src/traverseBlueprint.ts +94 -0
  114. package/src/traverseBlueprintAsync.ts +92 -0
  115. package/src/types.ts +195 -0
  116. package/src/widgetStatus.ts +231 -0
  117. package/src/widgets.ts +213 -0
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolvePath = void 0;
4
+ exports.resolveWidgetValue = resolveWidgetValue;
5
+ exports.traverseBlueprint = traverseBlueprint;
6
+ const normalize_1 = require("./normalize");
7
+ Object.defineProperty(exports, "resolvePath", { enumerable: true, get: function () { return normalize_1.resolvePath; } });
8
+ // ── Value resolution ──────────────────────────────────────────────────────────
9
+ function resolveWidgetValue(widget, stateMap) {
10
+ if (!widget.binding)
11
+ return undefined;
12
+ const state = stateMap.get(widget.binding.projectionId);
13
+ return (0, normalize_1.resolvePath)(state, widget.binding.path);
14
+ }
15
+ function traverseBlueprint(node, stateMap, options) {
16
+ const { renderWidget, renderContainer, onAction } = options;
17
+ if ((0, normalize_1.isWidget)(node)) {
18
+ const status = (0, normalize_1.resolveWidgetStatus)(node, stateMap);
19
+ return renderWidget({
20
+ widget: node,
21
+ value: resolveWidgetValue(node, stateMap),
22
+ ...(status !== undefined && { status }),
23
+ ...(onAction !== undefined && { onAction }),
24
+ });
25
+ }
26
+ const layout = node;
27
+ if (layout.type === "grid") {
28
+ const cells = layout.children.map(normalize_1.asCell).map((c) => ({
29
+ span: c.span ?? 1,
30
+ ...(c.row !== undefined && { row: c.row }),
31
+ ...(c.rowSpan !== undefined && { rowSpan: c.rowSpan }),
32
+ ...(c.column !== undefined && { column: c.column }),
33
+ child: traverseBlueprint(c.node, stateMap, options),
34
+ }));
35
+ return renderContainer({ layout, children: cells.map((c) => c.child), cells });
36
+ }
37
+ const children = layout.children.map((child) => traverseBlueprint(child, stateMap, options));
38
+ return renderContainer({ layout, children });
39
+ }
40
+ //# sourceMappingURL=traverseBlueprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traverseBlueprint.js","sourceRoot":"","sources":["../src/traverseBlueprint.ts"],"names":[],"mappings":";;;AAuBA,gDAIC;AAkCD,8CAgCC;AA7FD,2CAAiF;AAMxE,4FANkB,uBAAW,OAMlB;AAepB,iFAAiF;AAEjF,SAAgB,kBAAkB,CAAC,MAAc,EAAE,QAA8B;IAC/E,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IACtC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACxD,OAAO,IAAA,uBAAW,EAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACjD,CAAC;AAkCD,SAAgB,iBAAiB,CAC/B,IAAqB,EACrB,QAA8B,EAC9B,OAAyC;IAEzC,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAE5D,IAAI,IAAA,oBAAQ,EAAC,IAAI,CAAC,EAAE,CAAC;QACnB,MAAM,MAAM,GAAG,IAAA,+BAAmB,EAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACnD,OAAO,YAAY,CAAC;YAClB,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC;YACzC,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,EAAE,CAAC;YACvC,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,CAAC;SAC5C,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,kBAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACpD,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC;YACjB,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,SAAS,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;YAC1C,GAAG,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YACtD,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;YACnD,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC;SACpD,CAAC,CAAC,CAAC;QACJ,OAAO,eAAe,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IAE7F,OAAO,eAAe,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { Layout, Widget, WidgetAction, WidgetRendererProps } from "./types";
2
+ export interface IncrementalRenderer<TNode> {
3
+ createContainer(layout: Layout): TNode;
4
+ createWidget(ctx: WidgetRendererProps): TNode;
5
+ appendChild(parent: TNode, child: TNode): void;
6
+ }
7
+ export interface AsyncTraversalOptions<TNode> {
8
+ renderer: IncrementalRenderer<TNode>;
9
+ onAction?: (action: WidgetAction) => void;
10
+ /** Abort a stale/interrupted render; checked at every node. */
11
+ signal?: AbortSignal;
12
+ /** Whether to yield before processing the next node. Default: every 64 nodes. */
13
+ shouldYield?: (nodesSinceYield: number) => boolean;
14
+ /** How to yield. Default: @loomwork/scheduler yieldControl (macrotask). */
15
+ yieldTo?: () => Promise<void>;
16
+ }
17
+ export declare function traverseBlueprintAsync<TNode>(node: Layout | Widget, stateMap: Map<string, unknown>, options: AsyncTraversalOptions<TNode>): Promise<TNode>;
18
+ //# sourceMappingURL=traverseBlueprintAsync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traverseBlueprintAsync.d.ts","sourceRoot":"","sources":["../src/traverseBlueprintAsync.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAiBjF,MAAM,WAAW,mBAAmB,CAAC,KAAK;IACxC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IACvC,YAAY,CAAC,GAAG,EAAE,mBAAmB,GAAG,KAAK,CAAC;IAC9C,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CAChD;AAED,MAAM,WAAW,qBAAqB,CAAC,KAAK;IAC1C,QAAQ,EAAE,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAC1C,+DAA+D;IAC/D,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,iFAAiF;IACjF,WAAW,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,OAAO,CAAC;IACnD,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAID,wBAAsB,sBAAsB,CAAC,KAAK,EAChD,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,EAAE,qBAAqB,CAAC,KAAK,CAAC,GACpC,OAAO,CAAC,KAAK,CAAC,CAgDhB"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.traverseBlueprintAsync = traverseBlueprintAsync;
4
+ const scheduler_1 = require("@loomwork/scheduler");
5
+ const normalize_1 = require("./normalize");
6
+ const traverseBlueprint_1 = require("./traverseBlueprint");
7
+ const DEFAULT_YIELD_EVERY = 64;
8
+ async function traverseBlueprintAsync(node, stateMap, options) {
9
+ const { renderer, onAction, signal } = options;
10
+ const yieldTo = options.yieldTo ?? scheduler_1.yieldControl;
11
+ const shouldYield = options.shouldYield ?? ((n) => n >= DEFAULT_YIELD_EVERY);
12
+ // Counter-based budget (no clock) so behavior is deterministic and testable.
13
+ let nodesSinceYield = 0;
14
+ const tick = async () => {
15
+ (0, scheduler_1.throwIfAborted)(signal);
16
+ nodesSinceYield++;
17
+ if (shouldYield(nodesSinceYield)) {
18
+ nodesSinceYield = 0;
19
+ await yieldTo();
20
+ (0, scheduler_1.throwIfAborted)(signal);
21
+ }
22
+ };
23
+ const walk = async (current) => {
24
+ await tick();
25
+ if ((0, normalize_1.isWidget)(current)) {
26
+ const status = (0, normalize_1.resolveWidgetStatus)(current, stateMap);
27
+ return renderer.createWidget({
28
+ widget: current,
29
+ value: (0, traverseBlueprint_1.resolveWidgetValue)(current, stateMap),
30
+ ...(status !== undefined && { status }),
31
+ ...(onAction !== undefined && { onAction }),
32
+ });
33
+ }
34
+ const layout = current;
35
+ // Create the container FIRST so children can be committed into it as they
36
+ // resolve (incremental commit / progressive paint between yields).
37
+ const container = renderer.createContainer(layout);
38
+ // Only the iteration source changes for a grid (unwrap each child via `asCell`) — this
39
+ // walker has no `cells`/span surface of its own: the container is created and committed
40
+ // to before its children resolve, so there is nowhere to hand spans alongside them. A
41
+ // renderer that needs them can read `layout.children` itself in `createContainer`.
42
+ const nodes = layout.type === "grid" ? layout.children.map((c) => (0, normalize_1.asCell)(c).node) : layout.children;
43
+ for (const child of nodes) {
44
+ const childNode = await walk(child);
45
+ renderer.appendChild(container, childNode);
46
+ }
47
+ return container;
48
+ };
49
+ return walk(node);
50
+ }
51
+ //# sourceMappingURL=traverseBlueprintAsync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traverseBlueprintAsync.js","sourceRoot":"","sources":["../src/traverseBlueprintAsync.ts"],"names":[],"mappings":";;AAuCA,wDAoDC;AA3FD,mDAAmE;AACnE,2CAAoE;AACpE,2DAAyD;AAmCzD,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAExB,KAAK,UAAU,sBAAsB,CAC1C,IAAqB,EACrB,QAA8B,EAC9B,OAAqC;IAErC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,wBAAY,CAAC;IAChD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,mBAAmB,CAAC,CAAC;IAE7E,6EAA6E;IAC7E,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,MAAM,IAAI,GAAG,KAAK,IAAmB,EAAE;QACrC,IAAA,0BAAc,EAAC,MAAM,CAAC,CAAC;QACvB,eAAe,EAAE,CAAC;QAClB,IAAI,WAAW,CAAC,eAAe,CAAC,EAAE,CAAC;YACjC,eAAe,GAAG,CAAC,CAAC;YACpB,MAAM,OAAO,EAAE,CAAC;YAChB,IAAA,0BAAc,EAAC,MAAM,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,KAAK,EAAE,OAAwB,EAAkB,EAAE;QAC9D,MAAM,IAAI,EAAE,CAAC;QAEb,IAAI,IAAA,oBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,IAAA,+BAAmB,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YACtD,OAAO,QAAQ,CAAC,YAAY,CAAC;gBAC3B,MAAM,EAAE,OAAO;gBACf,KAAK,EAAE,IAAA,sCAAkB,EAAC,OAAO,EAAE,QAAQ,CAAC;gBAC5C,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,EAAE,CAAC;gBACvC,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,CAAC;aAC5C,CAAC,CAAC;QACL,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC;QACvB,0EAA0E;QAC1E,mEAAmE;QACnE,MAAM,SAAS,GAAG,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QACnD,uFAAuF;QACvF,wFAAwF;QACxF,sFAAsF;QACtF,mFAAmF;QACnF,MAAM,KAAK,GACT,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,kBAAM,EAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;QACxF,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;YAC1B,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC;YACpC,QAAQ,CAAC,WAAW,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IAEF,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,176 @@
1
+ export type WidgetKind = "MetricCard" | "Timeline" | "ApprovalCard" | "StatusBadge" | "ProgressBar" | "DataTable" | "AlertCard" | "StreamingText";
2
+ import type { DataClass } from "@loomwork/classify";
3
+ /**
4
+ * `empty` (IR 2.3.0, ADR 0100): delivery succeeded and the upstream answered with NO subject to
5
+ * show (e.g. a template indexed past the end of an empty array). It is not an error and triggers
6
+ * nothing; a value written beside it is ignored by every renderer.
7
+ */
8
+ export type BindingState = "pending" | "ready" | "stale" | "error" | "empty";
9
+ /** A binding's delivery state, read from the same projection state as its value (IR 2.0.0). */
10
+ export interface BindingStatus {
11
+ state: BindingState;
12
+ /** Monotonic per binding; lets a renderer coalesce out-of-order updates. */
13
+ seq?: number;
14
+ finding?: {
15
+ code: string;
16
+ message: string;
17
+ };
18
+ }
19
+ export interface DataBinding {
20
+ projectionId: string;
21
+ path: string;
22
+ /** Where, in the SAME projection state, this binding's status lives. Absent ⇒ no status channel. */
23
+ status?: {
24
+ path: string;
25
+ };
26
+ /** `@loomwork/classify` DataClass. Read by compilers and delivery; never by renderers. */
27
+ sensitivity?: DataClass;
28
+ }
29
+ /** What a widget stands for: the semantic type it renders and the degradations that led to `kind`. */
30
+ export interface WidgetSource {
31
+ type: string;
32
+ version: string;
33
+ /** Outermost first. */
34
+ degradedFrom?: Array<{
35
+ type: string;
36
+ version: string;
37
+ }>;
38
+ /**
39
+ * IR 2.5.0 (ADR 0097, amendment 2026-10-11): `true` asserts this widget's content was WITHHELD
40
+ * for the audience the surface was compiled for. A renderer draws NO value and NO label from a
41
+ * redacted widget (not `title`, `props`, `binding` or `kind`) and draws a redaction marker
42
+ * instead. The compiler records the RESULT of resolving audience, never the audience itself.
43
+ * Only `true` is legal (absent = not redacted); with it `binding` and `degradedFrom` MUST be
44
+ * absent, and `type`/`version` are a generic placeholder (`"redacted"`/`"1"`) — the original
45
+ * widget's type may itself be sensitive.
46
+ */
47
+ redacted?: true;
48
+ }
49
+ export interface Widget {
50
+ readonly _tag: "Widget";
51
+ id: string;
52
+ kind: string;
53
+ title?: string;
54
+ props: Record<string, unknown>;
55
+ binding?: DataBinding;
56
+ source?: WidgetSource;
57
+ }
58
+ /**
59
+ * One child of a grid: the columns it occupies (`span`, default 1) and, since IR 2.1.0
60
+ * (ADR 0098), an optional explicit placement. Every placement field is independently optional;
61
+ * all absent = flow placement (the grid's auto-placement, exactly as under 2.0.0). Coordinates
62
+ * are 1-based grid lines: `column` is the start column (the cell occupies `column..column+span-1`),
63
+ * `row` the start row, `rowSpan` the rows occupied (default 1).
64
+ */
65
+ export interface GridCell {
66
+ span?: number;
67
+ row?: number;
68
+ rowSpan?: number;
69
+ column?: number;
70
+ node: Widget | Layout;
71
+ }
72
+ export interface GridLayout {
73
+ type: "grid";
74
+ /**
75
+ * This container's stable identity (IR 2.4.0, ADR 0101) — the same rule as `Widget.id`: a
76
+ * non-empty string, no charset, no length cap, and ONE namespace with widget ids
77
+ * (`duplicate-node-id` spans both). A renderer that reconciles keys the container by it, so a
78
+ * sibling inserted or moved around it keeps its subtree's state. A renderer uses it only as a
79
+ * `Map` key — never markup. Absent or malformed (`layout-id-invalid`) ⇒ keyed positionally, as
80
+ * under 2.3.0.
81
+ */
82
+ id?: string;
83
+ columns: number;
84
+ gap?: number;
85
+ /** A section heading for this container (IR 2.1.0). Absent ⇒ no heading. */
86
+ title?: string;
87
+ /**
88
+ * What this container IS to a renderer that knows it (IR 2.2.0, ADR 0099) — the open,
89
+ * app-defined axis for containers that `Widget.kind` is for widgets (`"stepped"`, `"tabbed"`,
90
+ * …). `type` stays the geometry. Absent, malformed (see `isLayoutRole`) or unknown to the
91
+ * renderer in use ⇒ the plain container. Never an ARIA role, never display text.
92
+ */
93
+ role?: string;
94
+ children: GridCell[];
95
+ }
96
+ export interface FlexLayout {
97
+ type: "flex";
98
+ /**
99
+ * This container's stable identity (IR 2.4.0, ADR 0101) — the same rule as `Widget.id`: a
100
+ * non-empty string, no charset, no length cap, and ONE namespace with widget ids
101
+ * (`duplicate-node-id` spans both). A renderer that reconciles keys the container by it, so a
102
+ * sibling inserted or moved around it keeps its subtree's state. A renderer uses it only as a
103
+ * `Map` key — never markup. Absent or malformed (`layout-id-invalid`) ⇒ keyed positionally, as
104
+ * under 2.3.0.
105
+ */
106
+ id?: string;
107
+ direction: "row" | "column";
108
+ gap?: number;
109
+ /** A section heading for this container (IR 2.1.0). Absent ⇒ no heading. */
110
+ title?: string;
111
+ /**
112
+ * What this container IS to a renderer that knows it (IR 2.2.0, ADR 0099) — the open,
113
+ * app-defined axis for containers that `Widget.kind` is for widgets (`"stepped"`, `"tabbed"`,
114
+ * …). `type` stays the geometry. Absent, malformed (see `isLayoutRole`) or unknown to the
115
+ * renderer in use ⇒ the plain container. Never an ARIA role, never display text.
116
+ */
117
+ role?: string;
118
+ children: Array<Widget | Layout>;
119
+ }
120
+ export interface StackLayout {
121
+ type: "stack";
122
+ /**
123
+ * This container's stable identity (IR 2.4.0, ADR 0101) — the same rule as `Widget.id`: a
124
+ * non-empty string, no charset, no length cap, and ONE namespace with widget ids
125
+ * (`duplicate-node-id` spans both). A renderer that reconciles keys the container by it, so a
126
+ * sibling inserted or moved around it keeps its subtree's state. A renderer uses it only as a
127
+ * `Map` key — never markup. Absent or malformed (`layout-id-invalid`) ⇒ keyed positionally, as
128
+ * under 2.3.0.
129
+ */
130
+ id?: string;
131
+ gap?: number;
132
+ /** A section heading for this container (IR 2.1.0). Absent ⇒ no heading. */
133
+ title?: string;
134
+ /**
135
+ * What this container IS to a renderer that knows it (IR 2.2.0, ADR 0099) — the open,
136
+ * app-defined axis for containers that `Widget.kind` is for widgets (`"stepped"`, `"tabbed"`,
137
+ * …). `type` stays the geometry. Absent, malformed (see `isLayoutRole`) or unknown to the
138
+ * renderer in use ⇒ the plain container. Never an ARIA role, never display text.
139
+ */
140
+ role?: string;
141
+ children: Array<Widget | Layout>;
142
+ }
143
+ export type Layout = GridLayout | FlexLayout | StackLayout;
144
+ export interface Blueprint {
145
+ readonly _tag: "Blueprint";
146
+ /** The IR shape this artifact was written in. Absent ⇒ "1.0.0". Writers always set it. */
147
+ irVersion?: string;
148
+ id: string;
149
+ title: string;
150
+ layout: Layout;
151
+ projections: string[];
152
+ /**
153
+ * ADR 0095 — the declared semantics of the projections this view binds to, by id, as they
154
+ * were at composition.
155
+ *
156
+ * It lives on the blueprint rather than beside it because a composed surface is
157
+ * content-addressed: a field of the value is part of the address, so this is what makes
158
+ * "the meaning of a view never changes silently" a property of the artifact instead of a
159
+ * paragraph. A binding freezes a NAME; this freezes what that name meant.
160
+ *
161
+ * Read it with `blueprintPins`, compare it with `checkBlueprintPins`.
162
+ */
163
+ projectionVersions?: Readonly<Record<string, string>>;
164
+ }
165
+ export interface WidgetAction {
166
+ type: string;
167
+ widgetId: string;
168
+ payload?: unknown;
169
+ }
170
+ export interface WidgetRendererProps {
171
+ widget: Widget;
172
+ value: unknown;
173
+ status?: BindingStatus;
174
+ onAction?: (action: WidgetAction) => void;
175
+ }
176
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,66 @@
1
+ import type { BindingStatus, Widget } from "./types";
2
+ /** A caller-supplied value-contract check — the slot the matrix leaves between `empty` and `stale`. */
3
+ export type WidgetValueCheck = (widget: Widget, value: unknown) => {
4
+ code: string;
5
+ message: string;
6
+ } | undefined;
7
+ /** What a widget with a declared status channel is showing. */
8
+ export type WidgetShownState = "redacted" | "error" | "empty" | "stale" | "pending" | "loading" | "ready";
9
+ /** The decided status of one widget. `inert` = no status channel declared (IR 1.0.0 behaviour). */
10
+ export type WidgetStatusDescriptor = {
11
+ /** The widget (or its `source`) is malformed; draw the error placeholder, never the cause. */
12
+ readonly tag: "invalid";
13
+ readonly reason: string;
14
+ } | {
15
+ readonly tag: "inert" | WidgetShownState;
16
+ /** The finding message (a failed contract check wins), with the matrix default applied. */
17
+ readonly message: string;
18
+ /** The raw finding message, no default: what a `stale` marker carries as its tooltip. */
19
+ readonly finding: string | undefined;
20
+ /** Whether a value is present beside the status. */
21
+ readonly hasValue: boolean;
22
+ /** Whether the widget's own body is drawn (inert, ready, pending, or stale with a value). */
23
+ readonly showBody: boolean;
24
+ /** `type@version › …`, outermost first; undefined when the widget is not degraded. */
25
+ readonly degradedChain: string | undefined;
26
+ };
27
+ /**
28
+ * Decide what a widget shows. `check` is the optional caller value-contract check; it runs only
29
+ * for a widget whose binding declares a status channel, and only when there is a subject to check
30
+ * (not under `error` or `empty`). A finding outranks `stale`, `pending` and `ready`.
31
+ */
32
+ export declare function describeWidgetStatus(widget: Widget, value: unknown, status: BindingStatus | undefined, check?: WidgetValueCheck): WidgetStatusDescriptor;
33
+ /** The marker one status draws. `text` is the whole line for the markers that carry one. */
34
+ export interface WidgetStatusMarker {
35
+ /** `data-binding-marker`. */
36
+ readonly name: Exclude<WidgetShownState, "ready">;
37
+ /** `alert` for error; `status` for empty and redacted (a polite live region); otherwise none. */
38
+ readonly role: "alert" | "status" | undefined;
39
+ readonly glyph: string;
40
+ /** `glyph title: message` (error, empty), `… — no value` (stale, no value); else undefined. */
41
+ readonly text: string | undefined;
42
+ /** A stale marker beside a drawn value is glyph-only and carries the finding as its tooltip. */
43
+ readonly tooltip: string | undefined;
44
+ /** Block-level (a row) vs inline (a glyph beside the body). */
45
+ readonly block: boolean;
46
+ }
47
+ export interface WidgetStatusFrame {
48
+ /** `data-binding-state`; undefined for an inert widget. */
49
+ readonly state: WidgetShownState | undefined;
50
+ readonly sourceType: string | undefined;
51
+ readonly sourceVersion: string | undefined;
52
+ /** `data-degraded`: the chain, outermost first. */
53
+ readonly degraded: string | undefined;
54
+ /** The `title` attribute of a degraded widget. */
55
+ readonly tooltip: string | undefined;
56
+ /** The marker to draw before the body, or undefined (inert, ready). */
57
+ readonly marker: WidgetStatusMarker | undefined;
58
+ }
59
+ /**
60
+ * The surface-independent facts of a decided status. A redacted widget yields the constant marker
61
+ * and no source/degraded facts (nothing of the widget may reach the output).
62
+ */
63
+ export declare function describeWidgetFrame(widget: Widget, d: Exclude<WidgetStatusDescriptor, {
64
+ tag: "invalid";
65
+ }>): WidgetStatusFrame;
66
+ //# sourceMappingURL=widgetStatus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widgetStatus.d.ts","sourceRoot":"","sources":["../src/widgetStatus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAYrD,uGAAuG;AACvG,MAAM,MAAM,gBAAgB,GAAG,CAC7B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,KACX;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC;AAEnD,+DAA+D;AAC/D,MAAM,MAAM,gBAAgB,GACxB,UAAU,GACV,OAAO,GACP,OAAO,GACP,OAAO,GACP,SAAS,GACT,SAAS,GACT,OAAO,CAAC;AAEZ,mGAAmG;AACnG,MAAM,MAAM,sBAAsB,GAC9B;IACE,8FAA8F;IAC9F,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,GACD;IACE,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAAC;IACzC,2FAA2F;IAC3F,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,yFAAyF;IACzF,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,6FAA6F;IAC7F,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,sFAAsF;IACtF,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5C,CAAC;AA2BN;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,aAAa,GAAG,SAAS,EACjC,KAAK,CAAC,EAAE,gBAAgB,GACvB,sBAAsB,CAyCxB;AAUD,4FAA4F;AAC5F,MAAM,WAAW,kBAAkB;IACjC,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;IAClD,iGAAiG;IACjG,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,+FAA+F;IAC/F,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,gGAAgG;IAChG,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,kDAAkD;IAClD,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,kBAAkB,GAAG,SAAS,CAAC;CACjD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,CAAC,EAAE,OAAO,CAAC,sBAAsB,EAAE;IAAE,GAAG,EAAE,SAAS,CAAA;CAAE,CAAC,GACrD,iBAAiB,CA4DnB"}
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.describeWidgetStatus = describeWidgetStatus;
4
+ exports.describeWidgetFrame = describeWidgetFrame;
5
+ const DEFAULT_MESSAGE = {
6
+ redacted: "redacted",
7
+ error: "error",
8
+ empty: "no data",
9
+ stale: "stale",
10
+ pending: "",
11
+ loading: "",
12
+ ready: "",
13
+ };
14
+ const INVALID = Symbol("invalid");
15
+ const degradedChainOf = (widget) => {
16
+ const degraded = widget.source?.degradedFrom;
17
+ if (degraded === undefined)
18
+ return undefined;
19
+ if (!Array.isArray(degraded))
20
+ return INVALID;
21
+ const parts = [];
22
+ for (const d of degraded) {
23
+ if (typeof d !== "object" || d === null)
24
+ return INVALID;
25
+ const { type, version } = d;
26
+ parts.push(`${String(type)}@${String(version)}`);
27
+ }
28
+ return parts.join(" › ") || undefined;
29
+ };
30
+ /**
31
+ * Decide what a widget shows. `check` is the optional caller value-contract check; it runs only
32
+ * for a widget whose binding declares a status channel, and only when there is a subject to check
33
+ * (not under `error` or `empty`). A finding outranks `stale`, `pending` and `ready`.
34
+ */
35
+ function describeWidgetStatus(widget, value, status, check) {
36
+ // IR 2.5.0: a redacted widget outranks everything — it is decided before `value`, `status`,
37
+ // `check`, `binding`, `title` or a malformed `source.degradedFrom` is looked at, so none of them
38
+ // can reach a renderer's output. The message is the constant, never data from the widget.
39
+ if (widget.source?.redacted === true) {
40
+ return {
41
+ tag: "redacted",
42
+ message: DEFAULT_MESSAGE.redacted,
43
+ finding: undefined,
44
+ hasValue: false,
45
+ showBody: false,
46
+ degradedChain: undefined,
47
+ };
48
+ }
49
+ const chain = degradedChainOf(widget);
50
+ if (chain === INVALID)
51
+ return { tag: "invalid", reason: "source.degradedFrom is not an array of objects" };
52
+ const hasValue = value !== undefined;
53
+ const base = { hasValue, degradedChain: chain };
54
+ if (widget.binding?.status === undefined) {
55
+ return { tag: "inert", message: "", finding: undefined, showBody: true, ...base };
56
+ }
57
+ const noValue = status?.state === "error" || status?.state === "empty";
58
+ const contract = noValue ? undefined : check?.(widget, value);
59
+ const finding = contract ? contract.message : status?.finding?.message;
60
+ let tag;
61
+ if (status?.state === "error")
62
+ tag = "error";
63
+ else if (status?.state === "empty")
64
+ tag = "empty";
65
+ else if (contract)
66
+ tag = "error";
67
+ else if (status?.state === "stale")
68
+ tag = "stale";
69
+ // `status` undefined (not yet written, or malformed) is treated like `ready`: a value that
70
+ // already exists is shown rather than hidden behind a spinner.
71
+ else if (!hasValue)
72
+ tag = "loading";
73
+ else
74
+ tag = status?.state === "pending" ? "pending" : "ready";
75
+ return {
76
+ tag,
77
+ message: finding ?? DEFAULT_MESSAGE[tag],
78
+ finding,
79
+ showBody: tag === "ready" || tag === "pending" || (tag === "stale" && hasValue),
80
+ ...base,
81
+ };
82
+ }
83
+ /**
84
+ * The surface-independent facts of a decided status. A redacted widget yields the constant marker
85
+ * and no source/degraded facts (nothing of the widget may reach the output).
86
+ */
87
+ function describeWidgetFrame(widget, d) {
88
+ if (d.tag === "redacted") {
89
+ return {
90
+ state: "redacted",
91
+ sourceType: undefined,
92
+ sourceVersion: undefined,
93
+ degraded: undefined,
94
+ tooltip: undefined,
95
+ marker: {
96
+ name: "redacted",
97
+ role: "status",
98
+ glyph: "⊘",
99
+ text: `⊘ ${d.message}`,
100
+ tooltip: undefined,
101
+ block: true,
102
+ },
103
+ };
104
+ }
105
+ const label = widget.title ?? widget.kind;
106
+ const degraded = d.degradedChain;
107
+ let marker;
108
+ const row = (name, role, glyph, text, block, tooltip) => ({ name, role, glyph, text, tooltip, block });
109
+ switch (d.tag) {
110
+ case "error":
111
+ marker = row("error", "alert", "✗", `✗ ${label}: ${d.message}`, true);
112
+ break;
113
+ case "empty":
114
+ marker = row("empty", "status", "○", `○ ${label}: ${d.message}`, true);
115
+ break;
116
+ case "stale":
117
+ marker = d.hasValue
118
+ ? row("stale", undefined, "~", undefined, false, d.finding)
119
+ : row("stale", undefined, "~", `~ ${label}: ${d.message} — no value`, true);
120
+ break;
121
+ case "pending":
122
+ marker = row("pending", undefined, "⋯", undefined, false);
123
+ break;
124
+ case "loading":
125
+ marker = row("loading", undefined, "…", undefined, true);
126
+ break;
127
+ default:
128
+ marker = undefined;
129
+ }
130
+ return {
131
+ state: d.tag === "inert" ? undefined : d.tag,
132
+ sourceType: widget.source?.type,
133
+ sourceVersion: widget.source?.version,
134
+ degraded,
135
+ tooltip: degraded
136
+ ? `${widget.source?.type}@${widget.source?.version} shown as ${widget.kind} (degraded from ${degraded})`
137
+ : undefined,
138
+ marker,
139
+ };
140
+ }
141
+ //# sourceMappingURL=widgetStatus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widgetStatus.js","sourceRoot":"","sources":["../src/widgetStatus.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ import type { DataBinding, Widget } from "./types";
2
+ export interface MetricCardProps {
3
+ title: string;
4
+ binding: DataBinding;
5
+ unit?: string;
6
+ format?: "number" | "percent" | "bytes";
7
+ /**
8
+ * Stable node id. Supply it when a composer will REVISE this view: the derived
9
+ * id is a hash of kind + props, so editing any prop re-identifies the node —
10
+ * remounting it, and breaking anything keyed on it (a pin, an annotation, an
11
+ * agent's reference to it).
12
+ */
13
+ id?: string;
14
+ }
15
+ export declare function MetricCard(props: MetricCardProps): Widget;
16
+ export interface TimelineProps {
17
+ title?: string;
18
+ binding: DataBinding;
19
+ maxItems?: number;
20
+ /**
21
+ * Stable node id. Supply it when a composer will REVISE this view: the derived
22
+ * id is a hash of kind + props, so editing any prop re-identifies the node —
23
+ * remounting it, and breaking anything keyed on it (a pin, an annotation, an
24
+ * agent's reference to it).
25
+ */
26
+ id?: string;
27
+ }
28
+ export declare function Timeline(props: TimelineProps): Widget;
29
+ export interface ApprovalCardProps {
30
+ title: string;
31
+ binding: DataBinding;
32
+ approveLabel?: string;
33
+ rejectLabel?: string;
34
+ /**
35
+ * Stable node id. Supply it when a composer will REVISE this view: the derived
36
+ * id is a hash of kind + props, so editing any prop re-identifies the node —
37
+ * remounting it, and breaking anything keyed on it (a pin, an annotation, an
38
+ * agent's reference to it).
39
+ */
40
+ id?: string;
41
+ }
42
+ export declare function ApprovalCard(props: ApprovalCardProps): Widget;
43
+ export interface StatusBadgeProps {
44
+ title?: string;
45
+ binding: DataBinding;
46
+ /**
47
+ * Stable node id. Supply it when a composer will REVISE this view: the derived
48
+ * id is a hash of kind + props, so editing any prop re-identifies the node —
49
+ * remounting it, and breaking anything keyed on it (a pin, an annotation, an
50
+ * agent's reference to it).
51
+ */
52
+ id?: string;
53
+ }
54
+ export declare function StatusBadge(props: StatusBadgeProps): Widget;
55
+ export interface ProgressBarProps {
56
+ title?: string;
57
+ binding: DataBinding;
58
+ max?: number;
59
+ /**
60
+ * Stable node id. Supply it when a composer will REVISE this view: the derived
61
+ * id is a hash of kind + props, so editing any prop re-identifies the node —
62
+ * remounting it, and breaking anything keyed on it (a pin, an annotation, an
63
+ * agent's reference to it).
64
+ */
65
+ id?: string;
66
+ }
67
+ export declare function ProgressBar(props: ProgressBarProps): Widget;
68
+ export interface DataTableProps {
69
+ title?: string;
70
+ binding: DataBinding;
71
+ columns?: string[];
72
+ /**
73
+ * Stable node id. Supply it when a composer will REVISE this view: the derived
74
+ * id is a hash of kind + props, so editing any prop re-identifies the node —
75
+ * remounting it, and breaking anything keyed on it (a pin, an annotation, an
76
+ * agent's reference to it).
77
+ */
78
+ id?: string;
79
+ }
80
+ export declare function DataTable(props: DataTableProps): Widget;
81
+ export interface AlertCardProps {
82
+ title?: string;
83
+ binding: DataBinding;
84
+ severity?: "info" | "warning" | "error" | "critical";
85
+ /**
86
+ * Stable node id. Supply it when a composer will REVISE this view: the derived
87
+ * id is a hash of kind + props, so editing any prop re-identifies the node —
88
+ * remounting it, and breaking anything keyed on it (a pin, an annotation, an
89
+ * agent's reference to it).
90
+ */
91
+ id?: string;
92
+ }
93
+ export declare function AlertCard(props: AlertCardProps): Widget;
94
+ export interface StreamingTextProps {
95
+ title?: string;
96
+ binding: DataBinding;
97
+ placeholder?: string;
98
+ id?: string;
99
+ }
100
+ export declare function StreamingText(props: StreamingTextProps): Widget;
101
+ //# sourceMappingURL=widgets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widgets.d.ts","sourceRoot":"","sources":["../src/widgets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAmBnD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;IACxC;;;;;OAKG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAUzD;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAUrD;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAU7D;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,WAAW,CAAC;IACrB;;;;;OAKG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAU3D;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,WAAW,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAU3D;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;;OAKG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAUvD;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;IACrD;;;;;OAKG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAUvD;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,WAAW,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAU/D"}