@dataverse-kit/form-runtime 0.1.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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/dist/businessRules-U1_MBgyG.d.cts +372 -0
  4. package/dist/businessRules-U1_MBgyG.d.ts +372 -0
  5. package/dist/context.cjs +151 -0
  6. package/dist/context.cjs.map +1 -0
  7. package/dist/context.d.cts +132 -0
  8. package/dist/context.d.ts +132 -0
  9. package/dist/context.mjs +113 -0
  10. package/dist/context.mjs.map +1 -0
  11. package/dist/control-DFOg_pc_.d.cts +1027 -0
  12. package/dist/control-DaXBm-52.d.ts +1027 -0
  13. package/dist/gridCustomizer-C0V9FAE_.d.ts +569 -0
  14. package/dist/gridCustomizer-mJO-kmQ4.d.cts +569 -0
  15. package/dist/hooks.cjs +85 -0
  16. package/dist/hooks.cjs.map +1 -0
  17. package/dist/hooks.d.cts +24 -0
  18. package/dist/hooks.d.ts +24 -0
  19. package/dist/hooks.mjs +60 -0
  20. package/dist/hooks.mjs.map +1 -0
  21. package/dist/icons.cjs +202 -0
  22. package/dist/icons.cjs.map +1 -0
  23. package/dist/icons.d.cts +130 -0
  24. package/dist/icons.d.ts +130 -0
  25. package/dist/icons.mjs +165 -0
  26. package/dist/icons.mjs.map +1 -0
  27. package/dist/index.cjs +6509 -0
  28. package/dist/index.cjs.map +1 -0
  29. package/dist/index.d.cts +410 -0
  30. package/dist/index.d.ts +410 -0
  31. package/dist/index.mjs +6490 -0
  32. package/dist/index.mjs.map +1 -0
  33. package/dist/runtime-capabilities-BdGDdu0d.d.cts +119 -0
  34. package/dist/runtime-capabilities-Brfc7loJ.d.ts +119 -0
  35. package/dist/theme-BfeZIxmZ.d.cts +74 -0
  36. package/dist/theme-BfeZIxmZ.d.ts +74 -0
  37. package/dist/theme.cjs +215 -0
  38. package/dist/theme.cjs.map +1 -0
  39. package/dist/theme.d.cts +32 -0
  40. package/dist/theme.d.ts +32 -0
  41. package/dist/theme.mjs +186 -0
  42. package/dist/theme.mjs.map +1 -0
  43. package/dist/types.cjs +976 -0
  44. package/dist/types.cjs.map +1 -0
  45. package/dist/types.d.cts +813 -0
  46. package/dist/types.d.ts +813 -0
  47. package/dist/types.mjs +902 -0
  48. package/dist/types.mjs.map +1 -0
  49. package/dist/utils.cjs +250 -0
  50. package/dist/utils.cjs.map +1 -0
  51. package/dist/utils.d.cts +99 -0
  52. package/dist/utils.d.ts +99 -0
  53. package/dist/utils.mjs +220 -0
  54. package/dist/utils.mjs.map +1 -0
  55. package/dist/v8.cjs +4622 -0
  56. package/dist/v8.cjs.map +1 -0
  57. package/dist/v8.d.cts +730 -0
  58. package/dist/v8.d.ts +730 -0
  59. package/dist/v8.mjs +4622 -0
  60. package/dist/v8.mjs.map +1 -0
  61. package/dist/v9.cjs +19 -0
  62. package/dist/v9.cjs.map +1 -0
  63. package/dist/v9.d.cts +2 -0
  64. package/dist/v9.d.ts +2 -0
  65. package/dist/v9.mjs +1 -0
  66. package/dist/v9.mjs.map +1 -0
  67. package/package.json +113 -0
@@ -0,0 +1,372 @@
1
+ /**
2
+ * Business Rules Engine — Type Definitions
3
+ *
4
+ * Defines the complete type system for visual business rules:
5
+ * rule definitions, conditions, actions, variables, data sources,
6
+ * execution context, workflows, highlights, and canvas layout.
7
+ *
8
+ * Design principles:
9
+ * - FetchXML-style operator names (eq, gt, like) for Dynamics consultant familiarity
10
+ * - Discriminated unions with `kind` for exhaustive pattern matching on action configs
11
+ * - Record<string, unknown> for JSON-serializable state (not Map/Set)
12
+ * - Reuses existing FormDataSource for FetchXML data sources
13
+ */
14
+
15
+ /** A complete business rule — stored at entity level, enforced at form level */
16
+ interface BusinessRuleDefinition {
17
+ id: string;
18
+ name: string;
19
+ description?: string;
20
+ /** Entity logical name (e.g., "stn_order", "account") */
21
+ entityLogicalName: string;
22
+ /** Where the rule runs */
23
+ scope: 'entity' | 'form' | 'global';
24
+ /** For form-scoped rules */
25
+ targetFormId?: string;
26
+ /** When the rule evaluates */
27
+ trigger: RuleTrigger;
28
+ /** Execution priority (lower = first) */
29
+ priority: number;
30
+ /** Active/inactive toggle */
31
+ enabled: boolean;
32
+ /** Rule-specific data sources (beyond form-level shared ones) */
33
+ dataSources: RuleDataSource[];
34
+ /** Variables computed from data sources, fields, or expressions */
35
+ variables: RuleVariable[];
36
+ /** The IF condition tree */
37
+ conditionTree: RuleConditionGroup;
38
+ /** Actions when condition is TRUE */
39
+ thenActions: RuleAction[];
40
+ /** Actions when condition is FALSE */
41
+ elseActions: RuleAction[];
42
+ /** Visual layout for SVG canvas (Phase 2b) */
43
+ canvas?: RuleCanvasLayout;
44
+ /** Metadata */
45
+ createdAt: string;
46
+ updatedAt: string;
47
+ createdBy?: string;
48
+ }
49
+ interface RuleTrigger {
50
+ type: 'onLoad' | 'onChange' | 'onSave' | 'manual';
51
+ /** For onChange: which fields trigger re-evaluation */
52
+ watchFields?: string[];
53
+ /** For manual: command/button id */
54
+ commandId?: string;
55
+ }
56
+ /** Event that triggers rule evaluation */
57
+ interface TriggerEvent {
58
+ type: RuleTrigger['type'];
59
+ /** For onChange: which field changed */
60
+ fieldName?: string;
61
+ }
62
+ /** A group of conditions joined by AND/OR */
63
+ interface RuleConditionGroup {
64
+ id: string;
65
+ logic: 'and' | 'or';
66
+ conditions: (RuleCondition | RuleConditionGroup)[];
67
+ }
68
+ /** A single condition that evaluates to true/false */
69
+ interface RuleCondition {
70
+ id: string;
71
+ /** Left-hand side source */
72
+ source: 'field' | 'data-source' | 'calculated' | 'form-state';
73
+ /** Field logical name (when source = 'field' or 'form-state') */
74
+ fieldName?: string;
75
+ /** Comparison operator — matches FetchXML operator names */
76
+ operator: ConditionOperator;
77
+ /** Right-hand side literal value */
78
+ value?: ConditionValue;
79
+ /** Right-hand side is another field */
80
+ compareToField?: string;
81
+ /** Data source reference (when source = 'data-source') */
82
+ dataSourceId?: string;
83
+ dataSourceField?: string;
84
+ /** Expression string (when source = 'calculated') */
85
+ expression?: string;
86
+ }
87
+ /** Type guard: is this a condition group (has `logic`) or a leaf condition? */
88
+ declare function isConditionGroup(c: RuleCondition | RuleConditionGroup): c is RuleConditionGroup;
89
+ /** Operators match FetchXML names for consultant familiarity */
90
+ type ConditionOperator = 'eq' | 'ne' | 'gt' | 'ge' | 'lt' | 'le' | 'like' | 'not-like' | 'begins-with' | 'ends-with' | 'null' | 'not-null' | 'between' | 'in' | 'not-in' | 'contain-values' | 'not-contain-values' | 'changed' | 'not-changed';
91
+ type ConditionValue = string | number | boolean | null | string[] | [unknown, unknown];
92
+ interface RuleAction {
93
+ id: string;
94
+ type: RuleActionType;
95
+ /** Primary target — always synced to targets[0] */
96
+ target: ActionTarget;
97
+ /** Multi-target list (when action applies to multiple fields/sections/tabs) */
98
+ targets?: ActionTarget[];
99
+ /** Optional label for the target group (e.g., "Meter Fields") */
100
+ groupName?: string;
101
+ config: ActionConfig;
102
+ /** Execution order within the branch */
103
+ order: number;
104
+ }
105
+ /** Returns targets array, falling back to [action.target] for legacy data */
106
+ declare function getActionTargets(action: RuleAction): ActionTarget[];
107
+ type RuleActionType = 'setFieldValue' | 'setDefaultValue' | 'setVisibility' | 'setLockState' | 'setRequired' | 'showErrorMessage' | 'showRecommendation' | 'setHighlight' | 'setSectionVisibility' | 'setTabVisibility' | 'setSectionLockState' | 'setFormReadOnly' | 'setFormNotification' | 'preventSave' | 'setButtonVisibility' | 'setButtonEnabled' | 'blockCreate' | 'blockUpdate' | 'blockDelete' | 'callCustomAction' | 'callCustomApi' | 'triggerWorkflow' | 'navigateToForm' | 'openDialog';
108
+ interface ActionTarget {
109
+ type: 'field' | 'section' | 'tab' | 'form' | 'button' | 'control';
110
+ /** Control name, section id, tab id, or form id */
111
+ id: string;
112
+ displayName?: string;
113
+ }
114
+ type ActionConfig = SetFieldValueConfig | SetDefaultValueConfig | SetVisibilityConfig | SetLockConfig | SetRequiredConfig | ShowMessageConfig | SetHighlightConfig | SetFormReadOnlyConfig | SetFormNotificationConfig | PreventSaveConfig | CrudBlockConfig | CallApiConfig | TriggerWorkflowConfig | NavigateToFormConfig | OpenDialogConfig;
115
+ interface SetFieldValueConfig {
116
+ kind: 'setFieldValue';
117
+ source: 'constant' | 'variable' | 'expression' | 'field';
118
+ value: unknown;
119
+ }
120
+ interface SetDefaultValueConfig {
121
+ kind: 'setDefaultValue';
122
+ source: 'constant' | 'variable' | 'expression' | 'field';
123
+ value: unknown;
124
+ /** Only apply if field is currently empty */
125
+ onlyIfEmpty: boolean;
126
+ }
127
+ interface SetVisibilityConfig {
128
+ kind: 'setVisibility';
129
+ visible: boolean;
130
+ }
131
+ interface SetLockConfig {
132
+ kind: 'setLock';
133
+ locked: boolean;
134
+ }
135
+ interface SetRequiredConfig {
136
+ kind: 'setRequired';
137
+ level: 'required' | 'recommended' | 'none';
138
+ }
139
+ interface ShowMessageConfig {
140
+ kind: 'showMessage';
141
+ messageType: 'error' | 'warning' | 'info' | 'recommendation';
142
+ message: string;
143
+ /** Supports {{variableName}} interpolation */
144
+ interpolateVariables: boolean;
145
+ }
146
+ interface SetHighlightConfig {
147
+ kind: 'setHighlight';
148
+ /** Hex color (e.g., "#63d868") */
149
+ color: string;
150
+ /** Higher priority wins when multiple rules match */
151
+ priority: number;
152
+ }
153
+ interface SetFormReadOnlyConfig {
154
+ kind: 'setFormReadOnly';
155
+ readOnly: boolean;
156
+ }
157
+ interface SetFormNotificationConfig {
158
+ kind: 'setFormNotification';
159
+ messageType: 'error' | 'warning' | 'info';
160
+ message: string;
161
+ interpolateVariables: boolean;
162
+ }
163
+ interface PreventSaveConfig {
164
+ kind: 'preventSave';
165
+ message: string;
166
+ }
167
+ interface CrudBlockConfig {
168
+ kind: 'crudBlock';
169
+ operation: 'create' | 'update' | 'delete';
170
+ message?: string;
171
+ }
172
+ interface CallApiConfig {
173
+ kind: 'callApi';
174
+ dataSourceId: string;
175
+ resultVariableId?: string;
176
+ onSuccessActions?: RuleAction[];
177
+ onFailureActions?: RuleAction[];
178
+ }
179
+ interface TriggerWorkflowConfig {
180
+ kind: 'triggerWorkflow';
181
+ workflowId: string;
182
+ }
183
+ interface NavigateToFormConfig {
184
+ kind: 'navigateToForm';
185
+ formId: string;
186
+ /** Pass field values to the target form */
187
+ parameterMapping?: Record<string, string>;
188
+ }
189
+ interface OpenDialogConfig {
190
+ kind: 'openDialog';
191
+ formId: string;
192
+ width?: number;
193
+ height?: number;
194
+ }
195
+ interface RuleVariable {
196
+ id: string;
197
+ name: string;
198
+ displayName: string;
199
+ type: 'string' | 'number' | 'boolean' | 'datetime' | 'lookup' | 'optionset';
200
+ source: {
201
+ kind: 'field';
202
+ fieldName: string;
203
+ } | {
204
+ kind: 'dataSource';
205
+ dataSourceId: string;
206
+ outputField: string;
207
+ } | {
208
+ kind: 'expression';
209
+ expression: string;
210
+ } | {
211
+ kind: 'constant';
212
+ value: unknown;
213
+ } | {
214
+ kind: 'context';
215
+ contextPath: string;
216
+ };
217
+ defaultValue?: unknown;
218
+ }
219
+ /**
220
+ * Rule data source — wraps existing FormDataSource with caching,
221
+ * or defines a Custom Action / API source.
222
+ */
223
+ interface RuleDataSource {
224
+ id: string;
225
+ name: string;
226
+ displayName: string;
227
+ type: 'fetchXml' | 'aggregateFetchXml' | 'customAction' | 'customApi';
228
+ /**
229
+ * For fetchXml/aggregateFetchXml: reference an existing FormDataSource by id.
230
+ * Avoids duplicating FetchXML definitions.
231
+ */
232
+ formDataSourceId?: string;
233
+ /**
234
+ * Inline FetchXML when not referencing a shared FormDataSource.
235
+ * Supports {{fieldName}} placeholders.
236
+ */
237
+ fetchXml?: string;
238
+ /** Custom Action / API configuration (Phase 3) */
239
+ apiConfig?: {
240
+ actionName: string;
241
+ inputParameters: ApiParameter[];
242
+ outputParameters: ApiParameter[];
243
+ };
244
+ /** Caching strategy */
245
+ cache: {
246
+ enabled: boolean;
247
+ ttlSeconds: number;
248
+ invalidateOn?: string[];
249
+ };
250
+ }
251
+ interface ApiParameter {
252
+ name: string;
253
+ type: string;
254
+ source: 'field' | 'variable' | 'constant';
255
+ value: string;
256
+ }
257
+ /** Full runtime context — plain objects for JSON-serializable portions */
258
+ interface RuleExecutionContext {
259
+ /** Current form field values */
260
+ formData: Record<string, unknown>;
261
+ /** Original values at load time (for dirty detection) */
262
+ originalData: Record<string, unknown>;
263
+ /** Fields changed since load (runtime only, not serialized) */
264
+ dirtyFields: Set<string>;
265
+ /** Resolved data source results */
266
+ dataSourceResults: Record<string, unknown>;
267
+ /** Resolved variable values */
268
+ variableValues: Record<string, unknown>;
269
+ /** Form-level state */
270
+ formState: {
271
+ isNew: boolean;
272
+ isDirty: boolean;
273
+ isValid: boolean;
274
+ isSaving: boolean;
275
+ formId: string;
276
+ entityLogicalName: string;
277
+ recordId?: string;
278
+ lastSaved?: string;
279
+ };
280
+ /** Custom Action results (Phase 3) */
281
+ customActionResults: Record<string, unknown>;
282
+ }
283
+ interface RuleExecutionResult {
284
+ ruleId: string;
285
+ ruleName: string;
286
+ conditionMet: boolean;
287
+ actionsExecuted: ActionResult[];
288
+ error?: string;
289
+ durationMs: number;
290
+ }
291
+ interface ActionResult {
292
+ actionId: string;
293
+ actionType: RuleActionType;
294
+ targetId: string;
295
+ success: boolean;
296
+ error?: string;
297
+ }
298
+ interface FieldState {
299
+ visible: boolean;
300
+ locked: boolean;
301
+ required: 'required' | 'recommended' | 'none';
302
+ errorMessage?: string;
303
+ warningMessage?: string;
304
+ recommendationMessage?: string;
305
+ highlightColor?: string;
306
+ }
307
+ interface SectionState {
308
+ visible: boolean;
309
+ locked: boolean;
310
+ }
311
+ interface TabState {
312
+ visible: boolean;
313
+ }
314
+ interface FormNotification {
315
+ id: string;
316
+ type: 'error' | 'warning' | 'info';
317
+ message: string;
318
+ ruleId: string;
319
+ }
320
+ interface WorkflowDefinition {
321
+ id: string;
322
+ name: string;
323
+ description?: string;
324
+ trigger: 'on-save' | 'on-field-change' | 'on-load' | 'manual';
325
+ triggerField?: string;
326
+ steps: WorkflowStep[];
327
+ }
328
+ interface WorkflowStep {
329
+ id: string;
330
+ type: 'validate' | 'save' | 'call-action' | 'refresh' | 'evaluate-rules' | 'set-field';
331
+ actionName?: string;
332
+ fieldName?: string;
333
+ fieldValue?: unknown;
334
+ onError: 'stop' | 'continue' | 'rollback';
335
+ }
336
+ interface WorkflowResult {
337
+ workflowId: string;
338
+ success: boolean;
339
+ steps: WorkflowStepResult[];
340
+ }
341
+ interface WorkflowStepResult {
342
+ stepId: string;
343
+ success: boolean;
344
+ result?: unknown;
345
+ error?: string;
346
+ }
347
+ interface RuleCanvasLayout {
348
+ nodes: CanvasNode[];
349
+ connections: CanvasConnection[];
350
+ zoom: number;
351
+ panX: number;
352
+ panY: number;
353
+ }
354
+ interface CanvasNode {
355
+ id: string;
356
+ type: 'condition' | 'action' | 'branch';
357
+ x: number;
358
+ y: number;
359
+ width: number;
360
+ height: number;
361
+ }
362
+ interface CanvasConnection {
363
+ fromNodeId: string;
364
+ toNodeId: string;
365
+ type: 'then' | 'else' | 'sequence';
366
+ }
367
+ /** Creates a minimal empty rule definition */
368
+ declare function createDefaultBusinessRule(entityLogicalName: string, name?: string): BusinessRuleDefinition;
369
+ /** Creates a default field state (visible, unlocked, not required) */
370
+ declare function createDefaultFieldState(): FieldState;
371
+
372
+ export { type ActionConfig as A, type BusinessRuleDefinition as B, type CallApiConfig as C, type ShowMessageConfig as D, type TriggerEvent as E, type FieldState as F, type TriggerWorkflowConfig as G, type WorkflowResult as H, type WorkflowStep as I, type WorkflowStepResult as J, createDefaultBusinessRule as K, createDefaultFieldState as L, getActionTargets as M, type NavigateToFormConfig as N, type OpenDialogConfig as O, type PreventSaveConfig as P, isConditionGroup as Q, type RuleAction as R, type SectionState as S, type TabState as T, type WorkflowDefinition as W, type ActionResult as a, type ActionTarget as b, type ApiParameter as c, type CanvasConnection as d, type CanvasNode as e, type ConditionOperator as f, type ConditionValue as g, type CrudBlockConfig as h, type FormNotification as i, type RuleActionType as j, type RuleCanvasLayout as k, type RuleCondition as l, type RuleConditionGroup as m, type RuleDataSource as n, type RuleExecutionContext as o, type RuleExecutionResult as p, type RuleTrigger as q, type RuleVariable as r, type SetDefaultValueConfig as s, type SetFieldValueConfig as t, type SetFormNotificationConfig as u, type SetFormReadOnlyConfig as v, type SetHighlightConfig as w, type SetLockConfig as x, type SetRequiredConfig as y, type SetVisibilityConfig as z };
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/context/index.ts
21
+ var context_exports = {};
22
+ __export(context_exports, {
23
+ CalloutsProvider: () => CalloutsProvider,
24
+ FormRuntimeProvider: () => FormRuntimeProvider,
25
+ RuleStatesProvider: () => RuleStatesProvider,
26
+ TabContentSlotsProvider: () => TabContentSlotsProvider,
27
+ useCallout: () => useCallout,
28
+ useFieldState: () => useFieldState,
29
+ useFormRuntimeContext: () => useFormRuntimeContext,
30
+ useOptionalFormRuntimeContext: () => useOptionalFormRuntimeContext,
31
+ useRuleStates: () => useRuleStates,
32
+ useSectionState: () => useSectionState,
33
+ useTabContentSlots: () => useTabContentSlots,
34
+ useTabState: () => useTabState
35
+ });
36
+ module.exports = __toCommonJS(context_exports);
37
+
38
+ // src/context/FormRuntimeContext.tsx
39
+ var import_react = require("react");
40
+ var import_jsx_runtime = require("react/jsx-runtime");
41
+ var FormRuntimeContext = (0, import_react.createContext)(null);
42
+ FormRuntimeContext.displayName = "FormRuntimeContext";
43
+ var FormRuntimeProvider = ({
44
+ capabilities,
45
+ children
46
+ }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FormRuntimeContext.Provider, { value: capabilities, children });
47
+ function useFormRuntimeContext() {
48
+ const value = (0, import_react.useContext)(FormRuntimeContext);
49
+ if (value === null) {
50
+ throw new Error(
51
+ "[@dataverse-kit/form-runtime] useFormRuntimeContext was called outside of a <FormRuntimeProvider>. Wrap your <FormRuntime> mount with a provider that supplies FormRuntimeCapabilities (the editor app uses EditorFormRuntimeProvider; generated host code uses ServiceFactory-backed capabilities). See packages/form-runtime/src/context/FormRuntimeContext.tsx."
52
+ );
53
+ }
54
+ return value;
55
+ }
56
+ function useOptionalFormRuntimeContext() {
57
+ return (0, import_react.useContext)(FormRuntimeContext);
58
+ }
59
+
60
+ // src/context/CalloutsContext.tsx
61
+ var import_react2 = require("react");
62
+ var import_jsx_runtime2 = require("react/jsx-runtime");
63
+ var EMPTY = { byId: /* @__PURE__ */ new Map() };
64
+ var CalloutsContext = (0, import_react2.createContext)(EMPTY);
65
+ CalloutsContext.displayName = "CalloutsContext";
66
+ var CalloutsProvider = ({ callouts, children }) => {
67
+ const value = (0, import_react2.useMemo)(() => {
68
+ if (!callouts || callouts.length === 0) return EMPTY;
69
+ return { byId: new Map(callouts.map((c) => [c.id, c])) };
70
+ }, [callouts]);
71
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CalloutsContext.Provider, { value, children });
72
+ };
73
+ function useCallout(id) {
74
+ const ctx = (0, import_react2.useContext)(CalloutsContext);
75
+ if (!id) return void 0;
76
+ return ctx.byId.get(id);
77
+ }
78
+
79
+ // src/context/RuleStatesContext.tsx
80
+ var import_react3 = require("react");
81
+ var import_jsx_runtime3 = require("react/jsx-runtime");
82
+ var EMPTY2 = {
83
+ fieldStates: {},
84
+ sectionStates: {},
85
+ tabStates: {}
86
+ };
87
+ var RuleStatesContext = (0, import_react3.createContext)(EMPTY2);
88
+ RuleStatesContext.displayName = "RuleStatesContext";
89
+ var RuleStatesProvider = ({
90
+ fieldStates,
91
+ sectionStates,
92
+ tabStates,
93
+ children
94
+ }) => {
95
+ const value = (0, import_react3.useMemo)(
96
+ () => ({
97
+ fieldStates: fieldStates ?? {},
98
+ sectionStates: sectionStates ?? {},
99
+ tabStates: tabStates ?? {}
100
+ }),
101
+ [fieldStates, sectionStates, tabStates]
102
+ );
103
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RuleStatesContext.Provider, { value, children });
104
+ };
105
+ function useRuleStates() {
106
+ return (0, import_react3.useContext)(RuleStatesContext);
107
+ }
108
+ function useFieldState(controlName) {
109
+ const ctx = (0, import_react3.useContext)(RuleStatesContext);
110
+ if (!controlName) return void 0;
111
+ return ctx.fieldStates[controlName];
112
+ }
113
+ function useSectionState(sectionId) {
114
+ return (0, import_react3.useContext)(RuleStatesContext).sectionStates[sectionId];
115
+ }
116
+ function useTabState(tabId) {
117
+ return (0, import_react3.useContext)(RuleStatesContext).tabStates[tabId];
118
+ }
119
+
120
+ // src/context/TabContentSlotsContext.tsx
121
+ var import_react4 = require("react");
122
+ var import_jsx_runtime4 = require("react/jsx-runtime");
123
+ var EMPTY3 = {};
124
+ var TabContentSlotsContext = (0, import_react4.createContext)(EMPTY3);
125
+ TabContentSlotsContext.displayName = "TabContentSlotsContext";
126
+ var TabContentSlotsProvider = ({
127
+ slots,
128
+ children
129
+ }) => {
130
+ const value = (0, import_react4.useMemo)(() => slots ?? EMPTY3, [slots]);
131
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TabContentSlotsContext.Provider, { value, children });
132
+ };
133
+ function useTabContentSlots() {
134
+ return (0, import_react4.useContext)(TabContentSlotsContext);
135
+ }
136
+ // Annotate the CommonJS export names for ESM import in node:
137
+ 0 && (module.exports = {
138
+ CalloutsProvider,
139
+ FormRuntimeProvider,
140
+ RuleStatesProvider,
141
+ TabContentSlotsProvider,
142
+ useCallout,
143
+ useFieldState,
144
+ useFormRuntimeContext,
145
+ useOptionalFormRuntimeContext,
146
+ useRuleStates,
147
+ useSectionState,
148
+ useTabContentSlots,
149
+ useTabState
150
+ });
151
+ //# sourceMappingURL=context.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context/index.ts","../src/context/FormRuntimeContext.tsx","../src/context/CalloutsContext.tsx","../src/context/RuleStatesContext.tsx","../src/context/TabContentSlotsContext.tsx"],"sourcesContent":["// Public surface for `@dataverse-kit/form-runtime/context`.\n\nexport {\n FormRuntimeProvider,\n useFormRuntimeContext,\n useOptionalFormRuntimeContext,\n type FormRuntimeProviderProps,\n} from './FormRuntimeContext';\n\nexport {\n CalloutsProvider,\n useCallout,\n type CalloutsProviderProps,\n} from './CalloutsContext';\n\nexport {\n RuleStatesProvider,\n useRuleStates,\n useFieldState,\n useSectionState,\n useTabState,\n type RuleStatesProviderProps,\n type RuleStatesContextValue,\n} from './RuleStatesContext';\n\nexport {\n TabContentSlotsProvider,\n useTabContentSlots,\n type TabContentSlots,\n type TabContentSlotsProviderProps,\n} from './TabContentSlotsContext';\n\nexport type {\n FormRuntimeCapabilities,\n FormRuntimeConnection,\n FormRuntimePreviewContext,\n LiveDataResult,\n WebResourceData,\n LookupResult,\n LookupSearchOptions,\n TimelineItem,\n} from '../types/runtime-capabilities';\n","import React, { createContext, useContext } from 'react';\nimport type { FormRuntimeCapabilities } from '../types/runtime-capabilities';\n\n/**\n * Context that exposes editor- or host-supplied async capabilities to\n * the runtime's controls.\n *\n * Two implementations exist (Phase 1 Task 6.5 onwards):\n * - `EditorFormRuntimeProvider` in `apps/form-builder/src/contexts/` —\n * wires capabilities to the form-builder's Zustand stores (designer,\n * dataverse, previewRecord, gridCustomizer).\n * - Generated host code's provider (Phase 3) — wires capabilities to\n * `IApiService` from `@dataverse-kit/api-service`.\n *\n * Per `feedback_v1_migrations`, the runtime DOES NOT define a default\n * mock or no-op provider. Controls that depend on capabilities throw if\n * the consumer hasn't wrapped them in a provider — the error names the\n * provider that's expected, so the failure points at the integration\n * gap rather than masking it with silent no-ops.\n */\nconst FormRuntimeContext = createContext<FormRuntimeCapabilities | null>(null);\n\nFormRuntimeContext.displayName = 'FormRuntimeContext';\n\nexport interface FormRuntimeProviderProps {\n capabilities: FormRuntimeCapabilities;\n children: React.ReactNode;\n}\n\n/**\n * Provider wrapper. Caller supplies a `FormRuntimeCapabilities` value;\n * descendants read it via `useFormRuntimeContext()`. Wrap the runtime's\n * mount point (`<FormRuntime>`) with this; failing to do so causes\n * capability-consuming controls to throw on first render.\n */\nexport const FormRuntimeProvider: React.FC<FormRuntimeProviderProps> = ({\n capabilities,\n children,\n}) => <FormRuntimeContext.Provider value={capabilities}>{children}</FormRuntimeContext.Provider>;\n\n/**\n * Hook for runtime-internal callers that REQUIRE capabilities. Throws\n * with a directed error message if no provider is present so the\n * integration gap is visible at the call site (rather than a vague\n * \"Cannot read properties of null\" that points at the consumer).\n */\nexport function useFormRuntimeContext(): FormRuntimeCapabilities {\n const value = useContext(FormRuntimeContext);\n if (value === null) {\n throw new Error(\n '[@dataverse-kit/form-runtime] useFormRuntimeContext was called outside of a ' +\n '<FormRuntimeProvider>. Wrap your <FormRuntime> mount with a provider that ' +\n 'supplies FormRuntimeCapabilities (the editor app uses ' +\n 'EditorFormRuntimeProvider; generated host code uses ServiceFactory-backed ' +\n 'capabilities). See packages/form-runtime/src/context/FormRuntimeContext.tsx.',\n );\n }\n return value;\n}\n\n/**\n * Same as `useFormRuntimeContext()` but returns `null` when no provider\n * is present. Use for OPTIONAL capability access — controls that have a\n * sensible offline rendering (e.g. timeline, which renders a placeholder\n * when not connected) prefer this over the throwing variant.\n */\nexport function useOptionalFormRuntimeContext(): FormRuntimeCapabilities | null {\n return useContext(FormRuntimeContext);\n}\n","/**\n * CalloutsContext — exposes `form.callouts` to descendants so\n * SectionShell's CellShell can look up the CalloutDefinition that a\n * control's `calloutId` references without prop-drilling the array\n * through every shell layer.\n *\n * The runtime emits a provider once, at the FormRuntime mount point;\n * shells use {@link useCallout} to resolve an id to its definition (or\n * undefined when no provider is mounted, when the array is empty, or\n * when the id doesn't match — all of which should render the host\n * control without callout chrome).\n */\n\nimport React, { createContext, useContext, useMemo } from 'react';\nimport type { CalloutDefinition } from '../types';\n\ninterface CalloutsContextValue {\n /** Map from callout id -> definition for O(1) lookup. */\n byId: Map<string, CalloutDefinition>;\n}\n\nconst EMPTY: CalloutsContextValue = { byId: new Map() };\n\nconst CalloutsContext = createContext<CalloutsContextValue>(EMPTY);\nCalloutsContext.displayName = 'CalloutsContext';\n\nexport interface CalloutsProviderProps {\n callouts?: CalloutDefinition[];\n children: React.ReactNode;\n}\n\nexport const CalloutsProvider: React.FC<CalloutsProviderProps> = ({ callouts, children }) => {\n const value = useMemo<CalloutsContextValue>(() => {\n if (!callouts || callouts.length === 0) return EMPTY;\n return { byId: new Map(callouts.map((c) => [c.id, c])) };\n }, [callouts]);\n return <CalloutsContext.Provider value={value}>{children}</CalloutsContext.Provider>;\n};\n\n/**\n * Look up a callout by id. Returns undefined when no provider is\n * mounted, when the id is undefined, or when no callout with that id\n * exists — all should render the host control without chrome.\n */\nexport function useCallout(id: string | undefined): CalloutDefinition | undefined {\n const ctx = useContext(CalloutsContext);\n if (!id) return undefined;\n return ctx.byId.get(id);\n}\n","/**\n * RuleStatesContext — exposes business-rule evaluation outputs\n * (fieldStates / sectionStates / tabStates) to the runtime's shells so\n * they can gate visibility and override control props (readOnly,\n * required) at render time.\n *\n * The runtime does NOT own the rule engine — that's editor/host state.\n * It only consumes pre-computed state maps. The form-builder's\n * `useRuleExecutionStore` feeds these in via FormRuntime's `ruleStates`\n * prop; generated apps pass equivalent maps from their host integration.\n *\n * Missing entries are treated as \"no rule constraint\" — the underlying\n * control's own props (hidden / readOnly / required) take effect. This\n * matches the legacy SectionPreview's fallthrough behavior.\n */\n\nimport React, { createContext, useContext, useMemo } from 'react';\nimport type { FieldState, SectionState, TabState } from '../types/businessRules';\n\nexport interface RuleStatesContextValue {\n fieldStates: Record<string, FieldState>;\n sectionStates: Record<string, SectionState>;\n tabStates: Record<string, TabState>;\n}\n\nconst EMPTY: RuleStatesContextValue = {\n fieldStates: {},\n sectionStates: {},\n tabStates: {},\n};\n\nconst RuleStatesContext = createContext<RuleStatesContextValue>(EMPTY);\nRuleStatesContext.displayName = 'RuleStatesContext';\n\nexport interface RuleStatesProviderProps {\n fieldStates?: Record<string, FieldState>;\n sectionStates?: Record<string, SectionState>;\n tabStates?: Record<string, TabState>;\n children: React.ReactNode;\n}\n\nexport const RuleStatesProvider: React.FC<RuleStatesProviderProps> = ({\n fieldStates,\n sectionStates,\n tabStates,\n children,\n}) => {\n const value = useMemo<RuleStatesContextValue>(\n () => ({\n fieldStates: fieldStates ?? {},\n sectionStates: sectionStates ?? {},\n tabStates: tabStates ?? {},\n }),\n [fieldStates, sectionStates, tabStates],\n );\n return <RuleStatesContext.Provider value={value}>{children}</RuleStatesContext.Provider>;\n};\n\n/**\n * Returns the full rule-state maps. Use this when you need to walk\n * multiple field/section ids in a single render pass (e.g. RowShell\n * checking \"is every cell in this row hidden\") — avoids violating\n * the rules of hooks by calling useFieldState in a loop.\n */\nexport function useRuleStates(): RuleStatesContextValue {\n return useContext(RuleStatesContext);\n}\n\n/** Returns the field's rule state, or undefined if no rule has set one. */\nexport function useFieldState(controlName: string | undefined): FieldState | undefined {\n const ctx = useContext(RuleStatesContext);\n if (!controlName) return undefined;\n return ctx.fieldStates[controlName];\n}\n\n/** Returns the section's rule state, or undefined if no rule has set one. */\nexport function useSectionState(sectionId: string): SectionState | undefined {\n return useContext(RuleStatesContext).sectionStates[sectionId];\n}\n\n/** Returns the tab's rule state, or undefined if no rule has set one. */\nexport function useTabState(tabId: string): TabState | undefined {\n return useContext(RuleStatesContext).tabStates[tabId];\n}\n","/**\n * TabContentSlotsContext — pluggable render slots for non-main tabs\n * (related-records, audit-history). The runtime ships a placeholder\n * for these tab types because they depend on host-specific concerns\n * (dataverse queries, related-record metadata) that don't belong in\n * the runtime itself.\n *\n * Hosts that want full fidelity (form-builder preview, generated\n * apps) provide render functions for these slots via\n * `TabContentSlotsProvider`. TabsShell consumes them via\n * `useTabContentSlots()`; missing slots fall through to the\n * placeholder.\n *\n * Phase 3 m6 — replaces the legacy preview's direct imports of\n * RelatedTabPreview / AuditTabPreview without making the runtime\n * depend on either component.\n */\n\nimport React, { createContext, useContext, useMemo } from 'react';\nimport type { RelatedFormTab, AuditFormTab } from '../types';\n\nexport interface TabContentSlots {\n /** Render override for related-records tabs. */\n renderRelatedTab?: (tab: RelatedFormTab) => React.ReactNode;\n /** Render override for audit-history tabs. */\n renderAuditTab?: (tab: AuditFormTab) => React.ReactNode;\n}\n\nconst EMPTY: TabContentSlots = {};\n\nconst TabContentSlotsContext = createContext<TabContentSlots>(EMPTY);\nTabContentSlotsContext.displayName = 'TabContentSlotsContext';\n\nexport interface TabContentSlotsProviderProps {\n slots?: TabContentSlots;\n children: React.ReactNode;\n}\n\nexport const TabContentSlotsProvider: React.FC<TabContentSlotsProviderProps> = ({\n slots,\n children,\n}) => {\n const value = useMemo<TabContentSlots>(() => slots ?? EMPTY, [slots]);\n return <TabContentSlotsContext.Provider value={value}>{children}</TabContentSlotsContext.Provider>;\n};\n\nexport function useTabContentSlots(): TabContentSlots {\n return useContext(TabContentSlotsContext);\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_react","import_jsx_runtime","EMPTY","import_react","import_jsx_runtime","EMPTY"]}
@@ -0,0 +1,132 @@
1
+ import React from 'react';
2
+ import { F as FormRuntimeCapabilities } from './runtime-capabilities-BdGDdu0d.cjs';
3
+ export { a as FormRuntimeConnection, b as FormRuntimePreviewContext, L as LiveDataResult, c as LookupResult, d as LookupSearchOptions, T as TimelineItem, W as WebResourceData } from './runtime-capabilities-BdGDdu0d.cjs';
4
+ import { h as CalloutDefinition, ai as RelatedFormTab, A as AuditFormTab } from './control-DFOg_pc_.cjs';
5
+ import { F as FieldState, S as SectionState, T as TabState } from './businessRules-U1_MBgyG.cjs';
6
+ import './theme-BfeZIxmZ.cjs';
7
+
8
+ interface FormRuntimeProviderProps {
9
+ capabilities: FormRuntimeCapabilities;
10
+ children: React.ReactNode;
11
+ }
12
+ /**
13
+ * Provider wrapper. Caller supplies a `FormRuntimeCapabilities` value;
14
+ * descendants read it via `useFormRuntimeContext()`. Wrap the runtime's
15
+ * mount point (`<FormRuntime>`) with this; failing to do so causes
16
+ * capability-consuming controls to throw on first render.
17
+ */
18
+ declare const FormRuntimeProvider: React.FC<FormRuntimeProviderProps>;
19
+ /**
20
+ * Hook for runtime-internal callers that REQUIRE capabilities. Throws
21
+ * with a directed error message if no provider is present so the
22
+ * integration gap is visible at the call site (rather than a vague
23
+ * "Cannot read properties of null" that points at the consumer).
24
+ */
25
+ declare function useFormRuntimeContext(): FormRuntimeCapabilities;
26
+ /**
27
+ * Same as `useFormRuntimeContext()` but returns `null` when no provider
28
+ * is present. Use for OPTIONAL capability access — controls that have a
29
+ * sensible offline rendering (e.g. timeline, which renders a placeholder
30
+ * when not connected) prefer this over the throwing variant.
31
+ */
32
+ declare function useOptionalFormRuntimeContext(): FormRuntimeCapabilities | null;
33
+
34
+ /**
35
+ * CalloutsContext — exposes `form.callouts` to descendants so
36
+ * SectionShell's CellShell can look up the CalloutDefinition that a
37
+ * control's `calloutId` references without prop-drilling the array
38
+ * through every shell layer.
39
+ *
40
+ * The runtime emits a provider once, at the FormRuntime mount point;
41
+ * shells use {@link useCallout} to resolve an id to its definition (or
42
+ * undefined when no provider is mounted, when the array is empty, or
43
+ * when the id doesn't match — all of which should render the host
44
+ * control without callout chrome).
45
+ */
46
+
47
+ interface CalloutsProviderProps {
48
+ callouts?: CalloutDefinition[];
49
+ children: React.ReactNode;
50
+ }
51
+ declare const CalloutsProvider: React.FC<CalloutsProviderProps>;
52
+ /**
53
+ * Look up a callout by id. Returns undefined when no provider is
54
+ * mounted, when the id is undefined, or when no callout with that id
55
+ * exists — all should render the host control without chrome.
56
+ */
57
+ declare function useCallout(id: string | undefined): CalloutDefinition | undefined;
58
+
59
+ /**
60
+ * RuleStatesContext — exposes business-rule evaluation outputs
61
+ * (fieldStates / sectionStates / tabStates) to the runtime's shells so
62
+ * they can gate visibility and override control props (readOnly,
63
+ * required) at render time.
64
+ *
65
+ * The runtime does NOT own the rule engine — that's editor/host state.
66
+ * It only consumes pre-computed state maps. The form-builder's
67
+ * `useRuleExecutionStore` feeds these in via FormRuntime's `ruleStates`
68
+ * prop; generated apps pass equivalent maps from their host integration.
69
+ *
70
+ * Missing entries are treated as "no rule constraint" — the underlying
71
+ * control's own props (hidden / readOnly / required) take effect. This
72
+ * matches the legacy SectionPreview's fallthrough behavior.
73
+ */
74
+
75
+ interface RuleStatesContextValue {
76
+ fieldStates: Record<string, FieldState>;
77
+ sectionStates: Record<string, SectionState>;
78
+ tabStates: Record<string, TabState>;
79
+ }
80
+ interface RuleStatesProviderProps {
81
+ fieldStates?: Record<string, FieldState>;
82
+ sectionStates?: Record<string, SectionState>;
83
+ tabStates?: Record<string, TabState>;
84
+ children: React.ReactNode;
85
+ }
86
+ declare const RuleStatesProvider: React.FC<RuleStatesProviderProps>;
87
+ /**
88
+ * Returns the full rule-state maps. Use this when you need to walk
89
+ * multiple field/section ids in a single render pass (e.g. RowShell
90
+ * checking "is every cell in this row hidden") — avoids violating
91
+ * the rules of hooks by calling useFieldState in a loop.
92
+ */
93
+ declare function useRuleStates(): RuleStatesContextValue;
94
+ /** Returns the field's rule state, or undefined if no rule has set one. */
95
+ declare function useFieldState(controlName: string | undefined): FieldState | undefined;
96
+ /** Returns the section's rule state, or undefined if no rule has set one. */
97
+ declare function useSectionState(sectionId: string): SectionState | undefined;
98
+ /** Returns the tab's rule state, or undefined if no rule has set one. */
99
+ declare function useTabState(tabId: string): TabState | undefined;
100
+
101
+ /**
102
+ * TabContentSlotsContext — pluggable render slots for non-main tabs
103
+ * (related-records, audit-history). The runtime ships a placeholder
104
+ * for these tab types because they depend on host-specific concerns
105
+ * (dataverse queries, related-record metadata) that don't belong in
106
+ * the runtime itself.
107
+ *
108
+ * Hosts that want full fidelity (form-builder preview, generated
109
+ * apps) provide render functions for these slots via
110
+ * `TabContentSlotsProvider`. TabsShell consumes them via
111
+ * `useTabContentSlots()`; missing slots fall through to the
112
+ * placeholder.
113
+ *
114
+ * Phase 3 m6 — replaces the legacy preview's direct imports of
115
+ * RelatedTabPreview / AuditTabPreview without making the runtime
116
+ * depend on either component.
117
+ */
118
+
119
+ interface TabContentSlots {
120
+ /** Render override for related-records tabs. */
121
+ renderRelatedTab?: (tab: RelatedFormTab) => React.ReactNode;
122
+ /** Render override for audit-history tabs. */
123
+ renderAuditTab?: (tab: AuditFormTab) => React.ReactNode;
124
+ }
125
+ interface TabContentSlotsProviderProps {
126
+ slots?: TabContentSlots;
127
+ children: React.ReactNode;
128
+ }
129
+ declare const TabContentSlotsProvider: React.FC<TabContentSlotsProviderProps>;
130
+ declare function useTabContentSlots(): TabContentSlots;
131
+
132
+ export { CalloutsProvider, type CalloutsProviderProps, FormRuntimeCapabilities, FormRuntimeProvider, type FormRuntimeProviderProps, type RuleStatesContextValue, RuleStatesProvider, type RuleStatesProviderProps, type TabContentSlots, TabContentSlotsProvider, type TabContentSlotsProviderProps, useCallout, useFieldState, useFormRuntimeContext, useOptionalFormRuntimeContext, useRuleStates, useSectionState, useTabContentSlots, useTabState };