@cratis/scene.react 4.29.0 → 4.31.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 (133) hide show
  1. package/core/CoreToolbar.tsx +37 -6
  2. package/core/coreComponentMetadata.ts +1 -0
  3. package/core/coreComponents.ts +2 -0
  4. package/core/coreDescriptors.ts +13 -0
  5. package/core/corePackage.ts +1 -0
  6. package/dist/cjs/core/CoreToolbar.js +44 -4
  7. package/dist/cjs/core/CoreToolbar.js.map +1 -1
  8. package/dist/cjs/core/coreComponentMetadata.js +6 -0
  9. package/dist/cjs/core/coreComponentMetadata.js.map +1 -1
  10. package/dist/cjs/core/coreComponents.js +3 -1
  11. package/dist/cjs/core/coreComponents.js.map +1 -1
  12. package/dist/cjs/core/coreDescriptors.js +27 -0
  13. package/dist/cjs/core/coreDescriptors.js.map +1 -1
  14. package/dist/cjs/core/corePackage.js +2 -1
  15. package/dist/cjs/core/corePackage.js.map +1 -1
  16. package/dist/cjs/index.js +20 -0
  17. package/dist/cjs/index.js.map +1 -1
  18. package/dist/cjs/navigation/SceneNavigationContext.js.map +1 -1
  19. package/dist/cjs/navigation/SceneNavigationHost.js +10 -5
  20. package/dist/cjs/navigation/SceneNavigationHost.js.map +1 -1
  21. package/dist/cjs/navigation/useSceneHistoryNavigation.js +3 -1
  22. package/dist/cjs/navigation/useSceneHistoryNavigation.js.map +1 -1
  23. package/dist/cjs/slices/CoreSliceDialog.js +21 -0
  24. package/dist/cjs/slices/CoreSliceDialog.js.map +1 -0
  25. package/dist/cjs/slices/SliceCommandFieldsContext.js +22 -0
  26. package/dist/cjs/slices/SliceCommandFieldsContext.js.map +1 -0
  27. package/dist/cjs/slices/SliceDialogView.js +262 -0
  28. package/dist/cjs/slices/SliceDialogView.js.map +1 -0
  29. package/dist/cjs/slices/SliceInvokerContext.js +40 -0
  30. package/dist/cjs/slices/SliceInvokerContext.js.map +1 -0
  31. package/dist/cjs/slices/createAnnouncingInvoker.js +27 -0
  32. package/dist/cjs/slices/createAnnouncingInvoker.js.map +1 -0
  33. package/dist/cjs/slices/createDryRunInvoker.js +38 -0
  34. package/dist/cjs/slices/createDryRunInvoker.js.map +1 -0
  35. package/dist/cjs/slices/sliceDialogDestination.js +41 -0
  36. package/dist/cjs/slices/sliceDialogDestination.js.map +1 -0
  37. package/dist/esm/core/CoreToolbar.d.ts.map +1 -1
  38. package/dist/esm/core/CoreToolbar.js +47 -7
  39. package/dist/esm/core/CoreToolbar.js.map +1 -1
  40. package/dist/esm/core/coreComponentMetadata.d.ts.map +1 -1
  41. package/dist/esm/core/coreComponentMetadata.js +6 -0
  42. package/dist/esm/core/coreComponentMetadata.js.map +1 -1
  43. package/dist/esm/core/coreComponents.d.ts.map +1 -1
  44. package/dist/esm/core/coreComponents.js +3 -1
  45. package/dist/esm/core/coreComponents.js.map +1 -1
  46. package/dist/esm/core/coreDescriptors.d.ts.map +1 -1
  47. package/dist/esm/core/coreDescriptors.js +27 -0
  48. package/dist/esm/core/coreDescriptors.js.map +1 -1
  49. package/dist/esm/core/corePackage.d.ts.map +1 -1
  50. package/dist/esm/core/corePackage.js +2 -1
  51. package/dist/esm/core/corePackage.js.map +1 -1
  52. package/dist/esm/index.d.ts +1 -0
  53. package/dist/esm/index.d.ts.map +1 -1
  54. package/dist/esm/index.js +7 -0
  55. package/dist/esm/index.js.map +1 -1
  56. package/dist/esm/navigation/SceneNavigationContext.d.ts +1 -0
  57. package/dist/esm/navigation/SceneNavigationContext.d.ts.map +1 -1
  58. package/dist/esm/navigation/SceneNavigationContext.js.map +1 -1
  59. package/dist/esm/navigation/SceneNavigationHost.d.ts.map +1 -1
  60. package/dist/esm/navigation/SceneNavigationHost.js +10 -5
  61. package/dist/esm/navigation/SceneNavigationHost.js.map +1 -1
  62. package/dist/esm/navigation/SceneNavigationState.d.ts +1 -0
  63. package/dist/esm/navigation/SceneNavigationState.d.ts.map +1 -1
  64. package/dist/esm/navigation/useSceneHistoryNavigation.d.ts.map +1 -1
  65. package/dist/esm/navigation/useSceneHistoryNavigation.js +3 -1
  66. package/dist/esm/navigation/useSceneHistoryNavigation.js.map +1 -1
  67. package/dist/esm/slices/CoreSliceDialog.d.ts +3 -0
  68. package/dist/esm/slices/CoreSliceDialog.d.ts.map +1 -0
  69. package/dist/esm/slices/CoreSliceDialog.js +19 -0
  70. package/dist/esm/slices/CoreSliceDialog.js.map +1 -0
  71. package/dist/esm/slices/InvocationResult.d.ts +10 -0
  72. package/dist/esm/slices/InvocationResult.d.ts.map +1 -0
  73. package/dist/esm/slices/InvocationResult.js +2 -0
  74. package/dist/esm/slices/InvocationResult.js.map +1 -0
  75. package/dist/esm/slices/InvocationValidationError.d.ts +5 -0
  76. package/dist/esm/slices/InvocationValidationError.d.ts.map +1 -0
  77. package/dist/esm/slices/InvocationValidationError.js +2 -0
  78. package/dist/esm/slices/InvocationValidationError.js.map +1 -0
  79. package/dist/esm/slices/SliceCommandField.d.ts +8 -0
  80. package/dist/esm/slices/SliceCommandField.d.ts.map +1 -0
  81. package/dist/esm/slices/SliceCommandField.js +2 -0
  82. package/dist/esm/slices/SliceCommandField.js.map +1 -0
  83. package/dist/esm/slices/SliceCommandFieldsContext.d.ts +10 -0
  84. package/dist/esm/slices/SliceCommandFieldsContext.d.ts.map +1 -0
  85. package/dist/esm/slices/SliceCommandFieldsContext.js +19 -0
  86. package/dist/esm/slices/SliceCommandFieldsContext.js.map +1 -0
  87. package/dist/esm/slices/SliceDialogView.d.ts +12 -0
  88. package/dist/esm/slices/SliceDialogView.d.ts.map +1 -0
  89. package/dist/esm/slices/SliceDialogView.js +258 -0
  90. package/dist/esm/slices/SliceDialogView.js.map +1 -0
  91. package/dist/esm/slices/SliceInvoker.d.ts +5 -0
  92. package/dist/esm/slices/SliceInvoker.d.ts.map +1 -0
  93. package/dist/esm/slices/SliceInvoker.js +2 -0
  94. package/dist/esm/slices/SliceInvoker.js.map +1 -0
  95. package/dist/esm/slices/SliceInvokerContext.d.ts +11 -0
  96. package/dist/esm/slices/SliceInvokerContext.d.ts.map +1 -0
  97. package/dist/esm/slices/SliceInvokerContext.js +36 -0
  98. package/dist/esm/slices/SliceInvokerContext.js.map +1 -0
  99. package/dist/esm/slices/createAnnouncingInvoker.d.ts +3 -0
  100. package/dist/esm/slices/createAnnouncingInvoker.d.ts.map +1 -0
  101. package/dist/esm/slices/createAnnouncingInvoker.js +25 -0
  102. package/dist/esm/slices/createAnnouncingInvoker.js.map +1 -0
  103. package/dist/esm/slices/createDryRunInvoker.d.ts +15 -0
  104. package/dist/esm/slices/createDryRunInvoker.d.ts.map +1 -0
  105. package/dist/esm/slices/createDryRunInvoker.js +36 -0
  106. package/dist/esm/slices/createDryRunInvoker.js.map +1 -0
  107. package/dist/esm/slices/index.d.ts +12 -0
  108. package/dist/esm/slices/index.d.ts.map +1 -0
  109. package/dist/esm/slices/index.js +12 -0
  110. package/dist/esm/slices/index.js.map +1 -0
  111. package/dist/esm/slices/sliceDialogDestination.d.ts +10 -0
  112. package/dist/esm/slices/sliceDialogDestination.d.ts.map +1 -0
  113. package/dist/esm/slices/sliceDialogDestination.js +38 -0
  114. package/dist/esm/slices/sliceDialogDestination.js.map +1 -0
  115. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  116. package/index.ts +1 -0
  117. package/navigation/SceneNavigationContext.tsx +3 -0
  118. package/navigation/SceneNavigationHost.tsx +8 -3
  119. package/navigation/SceneNavigationState.ts +3 -0
  120. package/navigation/useSceneHistoryNavigation.ts +2 -1
  121. package/package.json +5 -5
  122. package/slices/CoreSliceDialog.tsx +14 -0
  123. package/slices/InvocationResult.ts +27 -0
  124. package/slices/InvocationValidationError.ts +13 -0
  125. package/slices/SliceCommandField.ts +22 -0
  126. package/slices/SliceCommandFieldsContext.tsx +28 -0
  127. package/slices/SliceDialogView.tsx +187 -0
  128. package/slices/SliceInvoker.ts +19 -0
  129. package/slices/SliceInvokerContext.tsx +47 -0
  130. package/slices/createAnnouncingInvoker.ts +17 -0
  131. package/slices/createDryRunInvoker.ts +43 -0
  132. package/slices/index.ts +14 -0
  133. package/slices/sliceDialogDestination.ts +40 -0
@@ -0,0 +1,258 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useContext, useMemo, useState, useRef, useId, useEffect } from 'react';
3
+ import { ApplicationStructureIndex } from '@cratis/scene.engine';
4
+ import { SceneNavigationContextInternal } from '../navigation/SceneNavigationContext.js';
5
+ import { useSceneNavigationModel } from '../navigation/region/SceneNavigationModelContext.js';
6
+ import { useSliceCommandFields } from './SliceCommandFieldsContext.js';
7
+ import { useSliceInvoker } from './SliceInvokerContext.js';
8
+ import { sliceDialogParameters } from './sliceDialogDestination.js';
9
+
10
+ const focusable = 'input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href], [tabindex]:not([tabindex="-1"])';
11
+ /** A label for a command property: `customerName` becomes `Customer name`. */ function sliceFieldLabel(field) {
12
+ if (field.label) return field.label;
13
+ const spaced = field.name.replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/[_-]+/g, ' ').trim().toLowerCase();
14
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
15
+ }
16
+ function inputTypeOf(field) {
17
+ switch(field.type.toLowerCase()){
18
+ case 'number':
19
+ case 'int':
20
+ case 'integer':
21
+ case 'long':
22
+ case 'double':
23
+ case 'decimal':
24
+ case 'float':
25
+ case 'single':
26
+ case 'int32':
27
+ case 'int64':
28
+ return 'number';
29
+ case 'boolean':
30
+ case 'bool':
31
+ return 'checkbox';
32
+ case 'date':
33
+ case 'dateonly':
34
+ return 'date';
35
+ default:
36
+ return 'text';
37
+ }
38
+ }
39
+ /** What the form starts with: the fields that carry an initial value, as the strings and booleans the inputs hold. */ function initialValuesOf(fields) {
40
+ const values = {};
41
+ for (const field of fields){
42
+ if (field.initialValue === undefined) continue;
43
+ values[field.name] = typeof field.initialValue === 'boolean' && inputTypeOf(field) === 'checkbox' ? field.initialValue : String(field.initialValue);
44
+ }
45
+ return values;
46
+ }
47
+ /** The payload a form's values make: numbers and booleans as such, an empty number left out. */ function slicePayload(fields, values) {
48
+ const payload = {};
49
+ for (const field of fields){
50
+ const value = values[field.name];
51
+ const type = inputTypeOf(field);
52
+ if (type === 'checkbox') payload[field.name] = value === true;
53
+ else if (type === 'number') {
54
+ if (value !== undefined && value !== '') payload[field.name] = Number(value);
55
+ } else payload[field.name] = value ?? '';
56
+ }
57
+ return payload;
58
+ }
59
+ /**
60
+ * The task dialog of a toolbar slice button (TB4): a modal card with the button's title, the slice as its subtitle, a labelled
61
+ * field for each command property, and Cancel and a submit button labelled with the title.
62
+ *
63
+ * - The first field takes focus when it opens, Tab stays inside, Escape cancels, and focus returns to the button that opened it.
64
+ * - Submit validates required fields, then calls the `SliceInvoker` in scope - real, dry-run or the announcing default. The
65
+ * problems it reports are shown against their fields (`aria-invalid`, `aria-describedby`) or for the form; success closes the
66
+ * dialog and hands the result to the host (`dialogResult`).
67
+ * - The fields come from the `SliceCommandFieldsProvider`; the subtitle names the slice from the navigation model.
68
+ *
69
+ * Inside a navigation host it is the content of the dialog a toolbar button opens; `core:sliceDialog` registers it so a host can
70
+ * author the dialog template with it.
71
+ */ function SliceDialogView({ slice: sliceProp, command: commandProp, title: titleProp, onClose }) {
72
+ const navigation = useContext(SceneNavigationContextInternal);
73
+ const opened = sliceDialogParameters(navigation?.currentDialogParameters);
74
+ const slice = sliceProp ?? opened?.slice ?? '';
75
+ const command = commandProp ?? opened?.command ?? slice;
76
+ const title = titleProp ?? opened?.title ?? command;
77
+ const invoker = useSliceInvoker();
78
+ const fieldsFor = useSliceCommandFields();
79
+ const model = useSceneNavigationModel();
80
+ const fields = useMemo(()=>fieldsFor?.(command, slice) ?? [], [
81
+ command,
82
+ fieldsFor,
83
+ slice
84
+ ]);
85
+ const sliceName = useMemo(()=>{
86
+ if (!model) return slice.split('.').pop() ?? slice;
87
+ const index = model.structure instanceof ApplicationStructureIndex ? model.structure : new ApplicationStructureIndex(model.structure);
88
+ return index.findSlice(slice)?.id ?? slice.split('.').pop() ?? slice;
89
+ }, [
90
+ model,
91
+ slice
92
+ ]);
93
+ const [values, setValues] = useState(()=>initialValuesOf(fields));
94
+ const [errors, setErrors] = useState([]);
95
+ const [submitting, setSubmitting] = useState(false);
96
+ const form = useRef(null);
97
+ const identity = useId();
98
+ const close = (result)=>onClose ? onClose(result) : navigation?.closeDialog(result);
99
+ // Focus the first field, and give focus back to whatever opened the dialog when it goes.
100
+ useEffect(()=>{
101
+ const opener = document.activeElement;
102
+ (form.current?.querySelector('input, select, textarea') ?? form.current?.querySelector('button'))?.focus();
103
+ return ()=>{
104
+ if (opener && opener.isConnected) opener.focus();
105
+ };
106
+ }, []);
107
+ const errorsOf = (name)=>errors.filter((error)=>error.field === name);
108
+ const fieldNames = new Set(fields.map((field)=>field.name));
109
+ const general = errors.filter((error)=>error.field === undefined || !fieldNames.has(error.field));
110
+ const submit = async (event)=>{
111
+ event.preventDefault();
112
+ if (submitting) return;
113
+ const missing = fields.filter((field)=>field.required && (values[field.name] === undefined || values[field.name] === '')).map((field)=>({
114
+ field: field.name,
115
+ message: `${sliceFieldLabel(field)} is required.`
116
+ }));
117
+ setErrors(missing);
118
+ if (missing.length > 0) {
119
+ form.current?.querySelector('[aria-invalid="true"]')?.focus();
120
+ return;
121
+ }
122
+ setSubmitting(true);
123
+ try {
124
+ const result = await invoker.invoke(slice, slicePayload(fields, values), command);
125
+ if (result.succeeded) {
126
+ close(result);
127
+ } else {
128
+ const reported = result.validationErrors ?? [];
129
+ setErrors(reported.length > 0 || !result.message ? reported : [
130
+ {
131
+ message: result.message
132
+ }
133
+ ]);
134
+ }
135
+ } finally{
136
+ setSubmitting(false);
137
+ }
138
+ };
139
+ const onKeyDown = (event)=>{
140
+ if (event.key === 'Escape') {
141
+ event.preventDefault();
142
+ close();
143
+ } else if (event.key === 'Tab') {
144
+ const targets = Array.from(form.current?.querySelectorAll(focusable) ?? []);
145
+ if (targets.length === 0) return;
146
+ const first = targets[0];
147
+ const last = targets[targets.length - 1];
148
+ if (event.shiftKey && document.activeElement === first) {
149
+ event.preventDefault();
150
+ last.focus();
151
+ } else if (!event.shiftKey && document.activeElement === last) {
152
+ event.preventDefault();
153
+ first.focus();
154
+ }
155
+ }
156
+ };
157
+ return /*#__PURE__*/ jsxs("form", {
158
+ ref: form,
159
+ className: "scene-slice-dialog",
160
+ "data-scene-slice-dialog": slice,
161
+ "data-scene-command": command,
162
+ noValidate: true,
163
+ onSubmit: submit,
164
+ onKeyDown: onKeyDown,
165
+ children: [
166
+ /*#__PURE__*/ jsxs("header", {
167
+ className: "scene-slice-dialog-header",
168
+ children: [
169
+ /*#__PURE__*/ jsx("h2", {
170
+ className: "scene-slice-dialog-title",
171
+ children: title
172
+ }),
173
+ /*#__PURE__*/ jsxs("p", {
174
+ className: "scene-slice-dialog-subtitle",
175
+ children: [
176
+ "State Change · ",
177
+ sliceName
178
+ ]
179
+ })
180
+ ]
181
+ }),
182
+ /*#__PURE__*/ jsx("div", {
183
+ className: "scene-slice-dialog-fields",
184
+ children: fields.map((field)=>{
185
+ const id = `${identity}-${field.name}`;
186
+ const own = errorsOf(field.name);
187
+ const type = inputTypeOf(field);
188
+ const description = own.length > 0 ? `${id}-error` : undefined;
189
+ return /*#__PURE__*/ jsxs("div", {
190
+ className: "scene-slice-dialog-field",
191
+ "data-type": type,
192
+ children: [
193
+ /*#__PURE__*/ jsxs("label", {
194
+ htmlFor: id,
195
+ children: [
196
+ sliceFieldLabel(field),
197
+ field.required ? /*#__PURE__*/ jsx("span", {
198
+ "aria-hidden": "true",
199
+ children: " *"
200
+ }) : null
201
+ ]
202
+ }),
203
+ /*#__PURE__*/ jsx("input", {
204
+ id: id,
205
+ name: field.name,
206
+ type: type,
207
+ required: field.required,
208
+ "aria-required": field.required || undefined,
209
+ "aria-invalid": own.length > 0 ? true : undefined,
210
+ "aria-describedby": description,
211
+ ...type === 'checkbox' ? {
212
+ checked: values[field.name] === true
213
+ } : {
214
+ value: values[field.name] ?? ''
215
+ },
216
+ onChange: (event)=>setValues({
217
+ ...values,
218
+ [field.name]: type === 'checkbox' ? event.target.checked : event.target.value
219
+ })
220
+ }),
221
+ own.length > 0 && /*#__PURE__*/ jsx("p", {
222
+ id: description,
223
+ className: "scene-slice-dialog-error",
224
+ role: "alert",
225
+ children: own.map((error)=>error.message).join(' ')
226
+ })
227
+ ]
228
+ }, field.name);
229
+ })
230
+ }),
231
+ general.length > 0 && /*#__PURE__*/ jsx("p", {
232
+ className: "scene-slice-dialog-error scene-slice-dialog-summary",
233
+ role: "alert",
234
+ children: general.map((error)=>error.message).join(' ')
235
+ }),
236
+ /*#__PURE__*/ jsxs("footer", {
237
+ className: "scene-slice-dialog-footer",
238
+ children: [
239
+ /*#__PURE__*/ jsx("button", {
240
+ type: "button",
241
+ className: "scene-slice-dialog-cancel",
242
+ onClick: ()=>close(),
243
+ children: "Cancel"
244
+ }),
245
+ /*#__PURE__*/ jsx("button", {
246
+ type: "submit",
247
+ className: "scene-slice-dialog-submit",
248
+ disabled: submitting,
249
+ children: title
250
+ })
251
+ ]
252
+ })
253
+ ]
254
+ });
255
+ }
256
+
257
+ export { SliceDialogView, sliceFieldLabel, slicePayload };
258
+ //# sourceMappingURL=SliceDialogView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SliceDialogView.js","sources":["../../../slices/SliceDialogView.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { FormEvent, KeyboardEvent, useContext, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { ApplicationStructureIndex } from '@cratis/scene.engine';\nimport { SceneNavigationContextInternal } from '../navigation/SceneNavigationContext';\nimport { useSceneNavigationModel } from '../navigation/region/SceneNavigationModelContext';\nimport { InvocationResult } from './InvocationResult';\nimport { InvocationValidationError } from './InvocationValidationError';\nimport { SliceCommandField } from './SliceCommandField';\nimport { useSliceCommandFields } from './SliceCommandFieldsContext';\nimport { useSliceInvoker } from './SliceInvokerContext';\nimport { sliceDialogParameters } from './sliceDialogDestination';\n\nexport interface SliceDialogViewProps {\n /** The qualified id of the slice; the open dialog's `slice` parameter when absent. */\n slice?: string;\n\n /** The command the slice accepts; the open dialog's `command` parameter when absent. */\n command?: string;\n\n /** The title - the toolbar button's - also the label of the submit button; the open dialog's `title` parameter when absent. */\n title?: string;\n\n /** Called when the dialog is cancelled or the slice accepted the command; the host's `closeDialog` when absent. */\n onClose?(result?: InvocationResult): void;\n}\n\nconst focusable = 'input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href], [tabindex]:not([tabindex=\"-1\"])';\n\n/** A label for a command property: `customerName` becomes `Customer name`. */\nexport function sliceFieldLabel(field: SliceCommandField): string {\n if (field.label) return field.label;\n const spaced = field.name.replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/[_-]+/g, ' ').trim().toLowerCase();\n return spaced.charAt(0).toUpperCase() + spaced.slice(1);\n}\n\nfunction inputTypeOf(field: SliceCommandField): string {\n switch (field.type.toLowerCase()) {\n case 'number': case 'int': case 'integer': case 'long': case 'double': case 'decimal': case 'float': case 'single': case 'int32': case 'int64': return 'number';\n case 'boolean': case 'bool': return 'checkbox';\n case 'date': case 'dateonly': return 'date';\n default: return 'text';\n }\n}\n\n/** What the form starts with: the fields that carry an initial value, as the strings and booleans the inputs hold. */\nfunction initialValuesOf(fields: SliceCommandField[]): Record<string, string | boolean> {\n const values: Record<string, string | boolean> = {};\n for (const field of fields) {\n if (field.initialValue === undefined) continue;\n values[field.name] = typeof field.initialValue === 'boolean' && inputTypeOf(field) === 'checkbox' ? field.initialValue : String(field.initialValue);\n }\n\n return values;\n}\n\n/** The payload a form's values make: numbers and booleans as such, an empty number left out. */\nexport function slicePayload(fields: SliceCommandField[], values: Record<string, string | boolean>): Record<string, unknown> {\n const payload: Record<string, unknown> = {};\n for (const field of fields) {\n const value = values[field.name];\n const type = inputTypeOf(field);\n if (type === 'checkbox') payload[field.name] = value === true;\n else if (type === 'number') { if (value !== undefined && value !== '') payload[field.name] = Number(value); }\n else payload[field.name] = value ?? '';\n }\n\n return payload;\n}\n\n/**\n * The task dialog of a toolbar slice button (TB4): a modal card with the button's title, the slice as its subtitle, a labelled\n * field for each command property, and Cancel and a submit button labelled with the title.\n *\n * - The first field takes focus when it opens, Tab stays inside, Escape cancels, and focus returns to the button that opened it.\n * - Submit validates required fields, then calls the `SliceInvoker` in scope - real, dry-run or the announcing default. The\n * problems it reports are shown against their fields (`aria-invalid`, `aria-describedby`) or for the form; success closes the\n * dialog and hands the result to the host (`dialogResult`).\n * - The fields come from the `SliceCommandFieldsProvider`; the subtitle names the slice from the navigation model.\n *\n * Inside a navigation host it is the content of the dialog a toolbar button opens; `core:sliceDialog` registers it so a host can\n * author the dialog template with it.\n */\nexport function SliceDialogView({ slice: sliceProp, command: commandProp, title: titleProp, onClose }: SliceDialogViewProps) {\n const navigation = useContext(SceneNavigationContextInternal);\n const opened = sliceDialogParameters(navigation?.currentDialogParameters);\n const slice = sliceProp ?? opened?.slice ?? '';\n const command = commandProp ?? opened?.command ?? slice;\n const title = titleProp ?? opened?.title ?? command;\n\n const invoker = useSliceInvoker();\n const fieldsFor = useSliceCommandFields();\n const model = useSceneNavigationModel();\n const fields = useMemo(() => fieldsFor?.(command, slice) ?? [], [command, fieldsFor, slice]);\n const sliceName = useMemo(() => {\n if (!model) return slice.split('.').pop() ?? slice;\n const index = model.structure instanceof ApplicationStructureIndex ? model.structure : new ApplicationStructureIndex(model.structure);\n return index.findSlice(slice)?.id ?? slice.split('.').pop() ?? slice;\n }, [model, slice]);\n\n const [values, setValues] = useState<Record<string, string | boolean>>(() => initialValuesOf(fields));\n const [errors, setErrors] = useState<InvocationValidationError[]>([]);\n const [submitting, setSubmitting] = useState(false);\n const form = useRef<HTMLFormElement>(null);\n const identity = useId();\n\n const close = (result?: InvocationResult) => onClose ? onClose(result) : navigation?.closeDialog(result);\n\n // Focus the first field, and give focus back to whatever opened the dialog when it goes.\n useEffect(() => {\n const opener = document.activeElement as HTMLElement | null;\n (form.current?.querySelector<HTMLElement>('input, select, textarea') ?? form.current?.querySelector<HTMLElement>('button'))?.focus();\n return () => { if (opener && opener.isConnected) opener.focus(); };\n }, []);\n\n const errorsOf = (name: string | undefined) => errors.filter(error => error.field === name);\n const fieldNames = new Set(fields.map(field => field.name));\n const general = errors.filter(error => error.field === undefined || !fieldNames.has(error.field));\n\n const submit = async (event: FormEvent) => {\n event.preventDefault();\n if (submitting) return;\n\n const missing = fields.filter(field => field.required && (values[field.name] === undefined || values[field.name] === '')).map(field => ({ field: field.name, message: `${sliceFieldLabel(field)} is required.` }));\n setErrors(missing);\n if (missing.length > 0) {\n form.current?.querySelector<HTMLElement>('[aria-invalid=\"true\"]')?.focus();\n return;\n }\n\n setSubmitting(true);\n try {\n const result = await invoker.invoke(slice, slicePayload(fields, values), command);\n if (result.succeeded) {\n close(result);\n } else {\n const reported = result.validationErrors ?? [];\n setErrors(reported.length > 0 || !result.message ? reported : [{ message: result.message }]);\n }\n } finally {\n setSubmitting(false);\n }\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLFormElement>) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n close();\n } else if (event.key === 'Tab') {\n const targets = Array.from(form.current?.querySelectorAll<HTMLElement>(focusable) ?? []);\n if (targets.length === 0) return;\n const first = targets[0];\n const last = targets[targets.length - 1];\n if (event.shiftKey && document.activeElement === first) { event.preventDefault(); last.focus(); }\n else if (!event.shiftKey && document.activeElement === last) { event.preventDefault(); first.focus(); }\n }\n };\n\n return <form ref={form} className='scene-slice-dialog' data-scene-slice-dialog={slice} data-scene-command={command} noValidate onSubmit={submit} onKeyDown={onKeyDown}>\n <header className='scene-slice-dialog-header'>\n <h2 className='scene-slice-dialog-title'>{title}</h2>\n <p className='scene-slice-dialog-subtitle'>State Change · {sliceName}</p>\n </header>\n <div className='scene-slice-dialog-fields'>\n {fields.map(field => {\n const id = `${identity}-${field.name}`;\n const own = errorsOf(field.name);\n const type = inputTypeOf(field);\n const description = own.length > 0 ? `${id}-error` : undefined;\n return <div key={field.name} className='scene-slice-dialog-field' data-type={type}>\n <label htmlFor={id}>{sliceFieldLabel(field)}{field.required ? <span aria-hidden='true'> *</span> : null}</label>\n <input id={id} name={field.name} type={type} required={field.required} aria-required={field.required || undefined}\n aria-invalid={own.length > 0 ? true : undefined} aria-describedby={description}\n {...(type === 'checkbox' ? { checked: values[field.name] === true } : { value: (values[field.name] as string | undefined) ?? '' })}\n onChange={event => setValues({ ...values, [field.name]: type === 'checkbox' ? event.target.checked : event.target.value })} />\n {own.length > 0 && <p id={description} className='scene-slice-dialog-error' role='alert'>{own.map(error => error.message).join(' ')}</p>}\n </div>;\n })}\n </div>\n {general.length > 0 && <p className='scene-slice-dialog-error scene-slice-dialog-summary' role='alert'>{general.map(error => error.message).join(' ')}</p>}\n <footer className='scene-slice-dialog-footer'>\n <button type='button' className='scene-slice-dialog-cancel' onClick={() => close()}>Cancel</button>\n <button type='submit' className='scene-slice-dialog-submit' disabled={submitting}>{title}</button>\n </footer>\n </form>;\n}\n"],"names":["focusable","sliceFieldLabel","field","label","spaced","name","replace","trim","toLowerCase","charAt","toUpperCase","slice","inputTypeOf","type","initialValuesOf","fields","values","initialValue","undefined","String","slicePayload","payload","value","Number","SliceDialogView","sliceProp","command","commandProp","title","titleProp","onClose","navigation","useContext","SceneNavigationContextInternal","opened","sliceDialogParameters","currentDialogParameters","invoker","useSliceInvoker","fieldsFor","useSliceCommandFields","model","useSceneNavigationModel","useMemo","sliceName","split","pop","index","structure","ApplicationStructureIndex","findSlice","id","setValues","useState","errors","setErrors","submitting","setSubmitting","form","useRef","identity","useId","close","result","closeDialog","useEffect","opener","document","activeElement","current","querySelector","focus","isConnected","errorsOf","filter","error","fieldNames","Set","map","general","has","submit","event","preventDefault","missing","required","message","length","invoke","succeeded","reported","validationErrors","onKeyDown","key","targets","Array","from","querySelectorAll","first","last","shiftKey","_jsxs","ref","className","data-scene-slice-dialog","data-scene-command","noValidate","onSubmit","header","_jsx","h2","p","div","own","description","data-type","htmlFor","span","aria-hidden","input","aria-required","aria-invalid","aria-describedby","checked","onChange","target","role","join","footer","button","onClick","disabled"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { InvocationResult } from './InvocationResult';
2
+ export interface SliceInvoker {
3
+ invoke(sliceId: string, payload: Record<string, unknown>, command?: string): Promise<InvocationResult>;
4
+ }
5
+ //# sourceMappingURL=SliceInvoker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SliceInvoker.d.ts","sourceRoot":"","sources":["../../../slices/SliceInvoker.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAOtD,MAAM,WAAW,YAAY;IAOzB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC1G"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=SliceInvoker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SliceInvoker.js","sourceRoot":"","sources":["../../../slices/SliceInvoker.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import { ReactNode } from 'react';
2
+ import { SliceInvoker } from './SliceInvoker';
3
+ export interface SliceInvokerProviderProps {
4
+ invoker: SliceInvoker;
5
+ warnEmptySlices?: boolean;
6
+ children?: ReactNode;
7
+ }
8
+ export declare function SliceInvokerProvider({ invoker, warnEmptySlices, children }: SliceInvokerProviderProps): import("react").JSX.Element;
9
+ export declare function useSliceInvoker(): SliceInvoker;
10
+ export declare function useWarnEmptySlices(): boolean;
11
+ //# sourceMappingURL=SliceInvokerContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SliceInvokerContext.d.ts","sourceRoot":"","sources":["../../../slices/SliceInvokerContext.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAsC,MAAM,OAAO,CAAC;AAEtE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAW9C,MAAM,WAAW,yBAAyB;IAEtC,OAAO,EAAE,YAAY,CAAC;IAMtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,SAAS,CAAC;CACxB;AAMD,wBAAgB,oBAAoB,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,EAAE,yBAAyB,+BAIrG;AAGD,wBAAgB,eAAe,IAAI,YAAY,CAE9C;AAGD,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C"}
@@ -0,0 +1,36 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useMemo, useContext, createContext } from 'react';
3
+ import { createAnnouncingInvoker } from './createAnnouncingInvoker.js';
4
+
5
+ const announcing = createAnnouncingInvoker();
6
+ const defaultScope = {
7
+ invoker: announcing,
8
+ warnEmptySlices: false
9
+ };
10
+ const Context = /*#__PURE__*/ createContext(defaultScope);
11
+ /**
12
+ * Supplies the `sliceInvoker` every toolbar dialog below it submits through: a real one in Stage, a dry-run one in the Studio
13
+ * preview. Without a provider the command is announced as `cratis.scene.command`.
14
+ */ function SliceInvokerProvider({ invoker, warnEmptySlices, children }) {
15
+ const warn = warnEmptySlices ?? invoker.dryRun === true;
16
+ const value = useMemo(()=>({
17
+ invoker,
18
+ warnEmptySlices: warn
19
+ }), [
20
+ invoker,
21
+ warn
22
+ ]);
23
+ return /*#__PURE__*/ jsx(Context.Provider, {
24
+ value: value,
25
+ children: children
26
+ });
27
+ }
28
+ /** The invoker in scope: the provider's, or the one that announces the command. */ function useSliceInvoker() {
29
+ return useContext(Context).invoker;
30
+ }
31
+ /** Whether a button without a slice should show a warning badge here. */ function useWarnEmptySlices() {
32
+ return useContext(Context).warnEmptySlices;
33
+ }
34
+
35
+ export { SliceInvokerProvider, useSliceInvoker, useWarnEmptySlices };
36
+ //# sourceMappingURL=SliceInvokerContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SliceInvokerContext.js","sources":["../../../slices/SliceInvokerContext.tsx"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { ReactNode, createContext, useContext, useMemo } from 'react';\nimport { createAnnouncingInvoker } from './createAnnouncingInvoker';\nimport { SliceInvoker } from './SliceInvoker';\n\ninterface SliceInvokerScope {\n invoker: SliceInvoker;\n warnEmptySlices: boolean;\n}\n\nconst announcing = createAnnouncingInvoker();\nconst defaultScope: SliceInvokerScope = { invoker: announcing, warnEmptySlices: false };\nconst Context = createContext<SliceInvokerScope>(defaultScope);\n\nexport interface SliceInvokerProviderProps {\n /** The invoker toolbar dialogs submit through. */\n invoker: SliceInvoker;\n\n /**\n * Whether a toolbar button without a slice shows a warning badge. Design and preview hosts turn it on (TB5); a\n * running application never shows it. A dry-run invoker implies it.\n */\n warnEmptySlices?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Supplies the `sliceInvoker` every toolbar dialog below it submits through: a real one in Stage, a dry-run one in the Studio\n * preview. Without a provider the command is announced as `cratis.scene.command`.\n */\nexport function SliceInvokerProvider({ invoker, warnEmptySlices, children }: SliceInvokerProviderProps) {\n const warn = warnEmptySlices ?? (invoker as { dryRun?: boolean }).dryRun === true;\n const value = useMemo(() => ({ invoker, warnEmptySlices: warn }), [invoker, warn]);\n return <Context.Provider value={value}>{children}</Context.Provider>;\n}\n\n/** The invoker in scope: the provider's, or the one that announces the command. */\nexport function useSliceInvoker(): SliceInvoker {\n return useContext(Context).invoker;\n}\n\n/** Whether a button without a slice should show a warning badge here. */\nexport function useWarnEmptySlices(): boolean {\n return useContext(Context).warnEmptySlices;\n}\n"],"names":["announcing","createAnnouncingInvoker","defaultScope","invoker","warnEmptySlices","Context","createContext","SliceInvokerProvider","children","warn","dryRun","value","useMemo","_jsx","Provider","useSliceInvoker","useContext","useWarnEmptySlices"],"mappings":";;;;AAYA,MAAMA,UAAAA,GAAaC,uBAAAA,EAAAA;AACnB,MAAMC,YAAAA,GAAkC;IAAEC,OAAAA,EAASH,UAAAA;IAAYI,eAAAA,EAAiB;AAAM,CAAA;AACtF,MAAMC,wBAAUC,aAAAA,CAAiCJ,YAAAA,CAAAA;AAcjD;;;IAIO,SAASK,oBAAAA,CAAqB,EAAEJ,OAAO,EAAEC,eAAe,EAAEI,QAAQ,EAA6B,EAAA;AAClG,IAAA,MAAMC,IAAAA,GAAOL,eAAAA,IAAmB,OAACD,CAAiCO,MAAM,KAAK,IAAA;IAC7E,MAAMC,KAAAA,GAAQC,OAAAA,CAAQ,KAAO;AAAET,YAAAA,OAAAA;YAASC,eAAAA,EAAiBK;AAAK,SAAA,CAAA,EAAI;AAACN,QAAAA,OAAAA;AAASM,QAAAA;AAAK,KAAA,CAAA;IACjF,qBAAOI,GAAA,CAACR,QAAQS,QAAQ,EAAA;QAACH,KAAAA,EAAOA,KAAAA;AAAQH,QAAAA,QAAAA,EAAAA;;AAC5C;AAEA,oFACO,SAASO,eAAAA,GAAAA;IACZ,OAAOC,UAAAA,CAAWX,SAASF,OAAO;AACtC;AAEA,0EACO,SAASc,kBAAAA,GAAAA;IACZ,OAAOD,UAAAA,CAAWX,SAASD,eAAe;AAC9C;;"}
@@ -0,0 +1,3 @@
1
+ import { SliceInvoker } from './SliceInvoker';
2
+ export declare function createAnnouncingInvoker(): SliceInvoker;
3
+ //# sourceMappingURL=createAnnouncingInvoker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAnnouncingInvoker.d.ts","sourceRoot":"","sources":["../../../slices/createAnnouncingInvoker.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAM9C,wBAAgB,uBAAuB,IAAI,YAAY,CAOtD"}
@@ -0,0 +1,25 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+ /**
4
+ * The invoker used when a host provides none: it announces the command with the host-neutral `cratis.scene.command` event,
5
+ * as a `core:toolbarItem` action always has, and reports success. A host that listens for the event runs the command.
6
+ */ function createAnnouncingInvoker() {
7
+ return {
8
+ async invoke (sliceId, payload, command) {
9
+ globalThis.dispatchEvent(new CustomEvent('cratis.scene.command', {
10
+ detail: {
11
+ command: command ?? sliceId,
12
+ slice: sliceId,
13
+ arguments: payload
14
+ }
15
+ }));
16
+ return {
17
+ succeeded: true,
18
+ payload
19
+ };
20
+ }
21
+ };
22
+ }
23
+
24
+ export { createAnnouncingInvoker };
25
+ //# sourceMappingURL=createAnnouncingInvoker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAnnouncingInvoker.js","sources":["../../../slices/createAnnouncingInvoker.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { SliceInvoker } from './SliceInvoker';\n\n/**\n * The invoker used when a host provides none: it announces the command with the host-neutral `cratis.scene.command` event,\n * as a `core:toolbarItem` action always has, and reports success. A host that listens for the event runs the command.\n */\nexport function createAnnouncingInvoker(): SliceInvoker {\n return {\n async invoke(sliceId, payload, command) {\n globalThis.dispatchEvent(new CustomEvent('cratis.scene.command', { detail: { command: command ?? sliceId, slice: sliceId, arguments: payload } }));\n return { succeeded: true, payload };\n },\n };\n}\n"],"names":["createAnnouncingInvoker","invoke","sliceId","payload","command","globalThis","dispatchEvent","CustomEvent","detail","slice","arguments","succeeded"],"mappings":"AAAA;AACA;AAIA;;;AAGC,IACM,SAASA,uBAAAA,GAAAA;IACZ,OAAO;AACH,QAAA,MAAMC,MAAAA,CAAAA,CAAOC,OAAO,EAAEC,OAAO,EAAEC,OAAO,EAAA;AAClCC,YAAAA,UAAAA,CAAWC,aAAa,CAAC,IAAIC,WAAAA,CAAY,sBAAA,EAAwB;gBAAEC,MAAAA,EAAQ;AAAEJ,oBAAAA,OAAAA,EAASA,OAAAA,IAAWF,OAAAA;oBAASO,KAAAA,EAAOP,OAAAA;oBAASQ,SAAAA,EAAWP;AAAQ;AAAE,aAAA,CAAA,CAAA;YAC/I,OAAO;gBAAEQ,SAAAA,EAAW,IAAA;AAAMR,gBAAAA;AAAQ,aAAA;AACtC,QAAA;AACJ,KAAA;AACJ;;"}
@@ -0,0 +1,15 @@
1
+ import { InvocationValidationError } from './InvocationValidationError';
2
+ import { SliceInvoker } from './SliceInvoker';
3
+ export interface DryRunInvocation {
4
+ sliceId: string;
5
+ command?: string;
6
+ payload: Record<string, unknown>;
7
+ }
8
+ export interface DryRunInvokerOptions {
9
+ onInvoked?(invocation: DryRunInvocation): void;
10
+ validate?(invocation: DryRunInvocation): InvocationValidationError[];
11
+ }
12
+ export declare function createDryRunInvoker(options?: DryRunInvokerOptions): SliceInvoker & {
13
+ readonly dryRun: true;
14
+ };
15
+ //# sourceMappingURL=createDryRunInvoker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createDryRunInvoker.d.ts","sourceRoot":"","sources":["../../../slices/createDryRunInvoker.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,MAAM,WAAW,gBAAgB;IAE7B,OAAO,EAAE,MAAM,CAAC;IAGhB,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,oBAAoB;IAEjC,SAAS,CAAC,CAAC,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAG/C,QAAQ,CAAC,CAAC,UAAU,EAAE,gBAAgB,GAAG,yBAAyB,EAAE,CAAC;CACxE;AAMD,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB,GAAG,YAAY,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,CAYhH"}
@@ -0,0 +1,36 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+ /**
4
+ * An invoker that sends nothing (PRV5): it validates, reports what it would have sent and succeeds, so a preview can walk a
5
+ * toolbar button through its dialog without touching a backend.
6
+ */ function createDryRunInvoker(options = {}) {
7
+ return {
8
+ dryRun: true,
9
+ async invoke (sliceId, payload, command) {
10
+ const invocation = {
11
+ sliceId,
12
+ payload,
13
+ ...command === undefined ? {} : {
14
+ command
15
+ }
16
+ };
17
+ const validationErrors = options.validate?.(invocation) ?? [];
18
+ if (validationErrors.length > 0) return {
19
+ succeeded: false,
20
+ validationErrors,
21
+ payload,
22
+ dryRun: true
23
+ };
24
+ options.onInvoked?.(invocation);
25
+ return {
26
+ succeeded: true,
27
+ payload,
28
+ dryRun: true,
29
+ message: `Dry run: ${command ?? sliceId} was not sent.`
30
+ };
31
+ }
32
+ };
33
+ }
34
+
35
+ export { createDryRunInvoker };
36
+ //# sourceMappingURL=createDryRunInvoker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createDryRunInvoker.js","sources":["../../../slices/createDryRunInvoker.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { InvocationValidationError } from './InvocationValidationError';\nimport { SliceInvoker } from './SliceInvoker';\n\n/** What a dry run is told about each invocation. */\nexport interface DryRunInvocation {\n /** The qualified id of the slice. */\n sliceId: string;\n\n /** The command the slice accepts, when known. */\n command?: string;\n\n /** The payload that would have been sent. */\n payload: Record<string, unknown>;\n}\n\nexport interface DryRunInvokerOptions {\n /** Called for every invocation that passes validation, with the would-be payload - the Studio preview shows it as a toast. */\n onInvoked?(invocation: DryRunInvocation): void;\n\n /** Extra validation of the payload; the problems it returns are reported like the real ones and nothing is invoked. */\n validate?(invocation: DryRunInvocation): InvocationValidationError[];\n}\n\n/**\n * An invoker that sends nothing (PRV5): it validates, reports what it would have sent and succeeds, so a preview can walk a\n * toolbar button through its dialog without touching a backend.\n */\nexport function createDryRunInvoker(options: DryRunInvokerOptions = {}): SliceInvoker & { readonly dryRun: true } {\n return {\n dryRun: true,\n async invoke(sliceId, payload, command) {\n const invocation: DryRunInvocation = { sliceId, payload, ...(command === undefined ? {} : { command }) };\n const validationErrors = options.validate?.(invocation) ?? [];\n if (validationErrors.length > 0) return { succeeded: false, validationErrors, payload, dryRun: true };\n\n options.onInvoked?.(invocation);\n return { succeeded: true, payload, dryRun: true, message: `Dry run: ${command ?? sliceId} was not sent.` };\n },\n };\n}\n"],"names":["createDryRunInvoker","options","dryRun","invoke","sliceId","payload","command","invocation","undefined","validationErrors","validate","length","succeeded","onInvoked","message"],"mappings":"AAAA;AACA;AAyBA;;;AAGC,IACM,SAASA,mBAAAA,CAAoBC,OAAAA,GAAgC,EAAE,EAAA;IAClE,OAAO;QACHC,MAAAA,EAAQ,IAAA;AACR,QAAA,MAAMC,MAAAA,CAAAA,CAAOC,OAAO,EAAEC,OAAO,EAAEC,OAAO,EAAA;AAClC,YAAA,MAAMC,UAAAA,GAA+B;AAAEH,gBAAAA,OAAAA;AAASC,gBAAAA,OAAAA;gBAAS,GAAIC,OAAAA,KAAYE,SAAAA,GAAY,EAAC,GAAI;AAAEF,oBAAAA;;AAAW,aAAA;AACvG,YAAA,MAAMG,gBAAAA,GAAmBR,OAAAA,CAAQS,QAAQ,GAAGH,eAAe,EAAE;AAC7D,YAAA,IAAIE,gBAAAA,CAAiBE,MAAM,GAAG,CAAA,EAAG,OAAO;gBAAEC,SAAAA,EAAW,KAAA;AAAOH,gBAAAA,gBAAAA;AAAkBJ,gBAAAA,OAAAA;gBAASH,MAAAA,EAAQ;AAAK,aAAA;AAEpGD,YAAAA,OAAAA,CAAQY,SAAS,GAAGN,UAAAA,CAAAA;YACpB,OAAO;gBAAEK,SAAAA,EAAW,IAAA;AAAMP,gBAAAA,OAAAA;gBAASH,MAAAA,EAAQ,IAAA;AAAMY,gBAAAA,OAAAA,EAAS,CAAC,SAAS,EAAER,OAAAA,IAAWF,OAAAA,CAAQ,cAAc;AAAE,aAAA;AAC7G,QAAA;AACJ,KAAA;AACJ;;"}
@@ -0,0 +1,12 @@
1
+ export * from './InvocationValidationError';
2
+ export * from './InvocationResult';
3
+ export * from './SliceInvoker';
4
+ export * from './createAnnouncingInvoker';
5
+ export * from './createDryRunInvoker';
6
+ export * from './SliceInvokerContext';
7
+ export * from './SliceCommandField';
8
+ export * from './SliceCommandFieldsContext';
9
+ export * from './sliceDialogDestination';
10
+ export * from './SliceDialogView';
11
+ export * from './CoreSliceDialog';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../slices/index.ts"],"names":[],"mappings":"AAGA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,12 @@
1
+ export * from './InvocationValidationError';
2
+ export * from './InvocationResult';
3
+ export * from './SliceInvoker';
4
+ export * from './createAnnouncingInvoker';
5
+ export * from './createDryRunInvoker';
6
+ export * from './SliceInvokerContext';
7
+ export * from './SliceCommandField';
8
+ export * from './SliceCommandFieldsContext';
9
+ export * from './sliceDialogDestination';
10
+ export * from './SliceDialogView';
11
+ export * from './CoreSliceDialog';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../slices/index.ts"],"names":[],"mappings":"AAGA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { DestinationReference } from '@cratis/scene.model';
2
+ import { ResolvedToolbarButton } from '@cratis/scene.engine';
3
+ export interface SliceDialogParameters {
4
+ slice: string;
5
+ command: string;
6
+ title: string;
7
+ }
8
+ export declare function sliceDialogDestination(button: ResolvedToolbarButton): DestinationReference | undefined;
9
+ export declare function sliceDialogParameters(parameters: Record<string, string> | undefined): SliceDialogParameters | undefined;
10
+ //# sourceMappingURL=sliceDialogDestination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sliceDialogDestination.d.ts","sourceRoot":"","sources":["../../../slices/sliceDialogDestination.ts"],"names":[],"mappings":"AAGA,OAAO,EAAyD,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAClH,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAK7D,MAAM,WAAW,qBAAqB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACjB;AAQD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,qBAAqB,GAAG,oBAAoB,GAAG,SAAS,CAWtG;AAGD,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,qBAAqB,GAAG,SAAS,CAIvH"}
@@ -0,0 +1,38 @@
1
+ import { DestinationKind, BindingSourceKind } from '@cratis/scene.model';
2
+
3
+ // Copyright (c) Cratis. All rights reserved.
4
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
5
+ const literal = (value)=>({
6
+ kind: BindingSourceKind.Literal,
7
+ path: '',
8
+ value
9
+ });
10
+ /**
11
+ * The destination that opens a toolbar button's task dialog through the navigation host: the dialog template the slice
12
+ * resolves to (`sliceDialogFor`), with the slice, its command and the button's title as parameters.
13
+ * @param button The resolved button.
14
+ * @returns The destination, or undefined when the button has no state change slice to open.
15
+ */ function sliceDialogDestination(button) {
16
+ if (!button.dialog) return undefined;
17
+ return {
18
+ kind: DestinationKind.Dialog,
19
+ dialog: button.dialog.template,
20
+ routeParameterBindings: {
21
+ slice: literal(button.dialog.slice),
22
+ command: literal(button.dialog.command),
23
+ title: literal(button.title)
24
+ }
25
+ };
26
+ }
27
+ /** Reads the slice dialog parameters back from what the host carries; undefined when they are not those of a slice dialog. */ function sliceDialogParameters(parameters) {
28
+ const slice = parameters?.slice;
29
+ const command = parameters?.command;
30
+ return slice && command ? {
31
+ slice,
32
+ command,
33
+ title: parameters?.title || command
34
+ } : undefined;
35
+ }
36
+
37
+ export { sliceDialogDestination, sliceDialogParameters };
38
+ //# sourceMappingURL=sliceDialogDestination.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sliceDialogDestination.js","sources":["../../../slices/sliceDialogDestination.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { BindingExpression, BindingSourceKind, DestinationKind, DestinationReference } from '@cratis/scene.model';\nimport { ResolvedToolbarButton } from '@cratis/scene.engine';\n\nconst literal = (value: string): BindingExpression => ({ kind: BindingSourceKind.Literal, path: '', value }) as BindingExpression;\n\n/** The dialog parameters a slice dialog is opened with; the navigation host hands them back as `currentDialogParameters`. */\nexport interface SliceDialogParameters {\n slice: string;\n command: string;\n title: string;\n}\n\n/**\n * The destination that opens a toolbar button's task dialog through the navigation host: the dialog template the slice\n * resolves to (`sliceDialogFor`), with the slice, its command and the button's title as parameters.\n * @param button The resolved button.\n * @returns The destination, or undefined when the button has no state change slice to open.\n */\nexport function sliceDialogDestination(button: ResolvedToolbarButton): DestinationReference | undefined {\n if (!button.dialog) return undefined;\n return {\n kind: DestinationKind.Dialog,\n dialog: button.dialog.template,\n routeParameterBindings: {\n slice: literal(button.dialog.slice),\n command: literal(button.dialog.command),\n title: literal(button.title),\n },\n };\n}\n\n/** Reads the slice dialog parameters back from what the host carries; undefined when they are not those of a slice dialog. */\nexport function sliceDialogParameters(parameters: Record<string, string> | undefined): SliceDialogParameters | undefined {\n const slice = parameters?.slice;\n const command = parameters?.command;\n return slice && command ? { slice, command, title: parameters?.title || command } : undefined;\n}\n"],"names":["literal","value","kind","BindingSourceKind","Literal","path","sliceDialogDestination","button","dialog","undefined","DestinationKind","Dialog","template","routeParameterBindings","slice","command","title","sliceDialogParameters","parameters"],"mappings":";;AAAA;AACA;AAKA,MAAMA,OAAAA,GAAU,CAACC,KAAAA,IAAsC;AAAEC,QAAAA,IAAAA,EAAMC,kBAAkBC,OAAO;QAAEC,IAAAA,EAAM,EAAA;AAAIJ,QAAAA;KAAM,CAAA;AAS1G;;;;;IAMO,SAASK,sBAAAA,CAAuBC,MAA6B,EAAA;AAChE,IAAA,IAAI,CAACA,MAAAA,CAAOC,MAAM,EAAE,OAAOC,SAAAA;IAC3B,OAAO;AACHP,QAAAA,IAAAA,EAAMQ,gBAAgBC,MAAM;QAC5BH,MAAAA,EAAQD,MAAAA,CAAOC,MAAM,CAACI,QAAQ;QAC9BC,sBAAAA,EAAwB;AACpBC,YAAAA,KAAAA,EAAOd,OAAAA,CAAQO,MAAAA,CAAOC,MAAM,CAACM,KAAK,CAAA;AAClCC,YAAAA,OAAAA,EAASf,OAAAA,CAAQO,MAAAA,CAAOC,MAAM,CAACO,OAAO,CAAA;YACtCC,KAAAA,EAAOhB,OAAAA,CAAQO,OAAOS,KAAK;AAC/B;AACJ,KAAA;AACJ;AAEA,+HACO,SAASC,qBAAAA,CAAsBC,UAA8C,EAAA;AAChF,IAAA,MAAMJ,QAAQI,UAAAA,EAAYJ,KAAAA;AAC1B,IAAA,MAAMC,UAAUG,UAAAA,EAAYH,OAAAA;AAC5B,IAAA,OAAOD,SAASC,OAAAA,GAAU;AAAED,QAAAA,KAAAA;AAAOC,QAAAA,OAAAA;AAASC,QAAAA,KAAAA,EAAOE,YAAYF,KAAAA,IAASD;KAAQ,GAAIN,SAAAA;AACxF;;"}