@cratis/scene.components 3.6.0 → 3.7.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 (82) hide show
  1. package/README.md +17 -1
  2. package/dist/cjs/forms/CommandFormRuntime.js +81 -0
  3. package/dist/cjs/forms/CommandFormRuntime.js.map +1 -0
  4. package/dist/cjs/forms/CommandFormSubmit.js +19 -0
  5. package/dist/cjs/forms/CommandFormSubmit.js.map +1 -0
  6. package/dist/cjs/forms/ExplicitCommandField.js +109 -0
  7. package/dist/cjs/forms/ExplicitCommandField.js.map +1 -0
  8. package/dist/cjs/forms/SceneCommandForm.js +26 -21
  9. package/dist/cjs/forms/SceneCommandForm.js.map +1 -1
  10. package/dist/cjs/forms/commandInputs.js +35 -0
  11. package/dist/cjs/forms/commandInputs.js.map +1 -0
  12. package/dist/esm/for_cratisComponentsPackage/when_declaring_command_form_peers.d.ts +2 -0
  13. package/dist/esm/for_cratisComponentsPackage/when_declaring_command_form_peers.d.ts.map +1 -0
  14. package/dist/esm/for_cratisComponentsPackage/when_declaring_command_form_peers.js +16 -0
  15. package/dist/esm/for_cratisComponentsPackage/when_declaring_command_form_peers.js.map +1 -0
  16. package/dist/esm/forms/CommandFormRuntime.d.ts +11 -0
  17. package/dist/esm/forms/CommandFormRuntime.d.ts.map +1 -0
  18. package/dist/esm/forms/CommandFormRuntime.js +77 -0
  19. package/dist/esm/forms/CommandFormRuntime.js.map +1 -0
  20. package/dist/esm/forms/CommandFormSubmit.d.ts +6 -0
  21. package/dist/esm/forms/CommandFormSubmit.d.ts.map +1 -0
  22. package/dist/esm/forms/CommandFormSubmit.js +17 -0
  23. package/dist/esm/forms/CommandFormSubmit.js.map +1 -0
  24. package/dist/esm/forms/ExplicitCommandField.d.ts +5 -0
  25. package/dist/esm/forms/ExplicitCommandField.d.ts.map +1 -0
  26. package/dist/esm/forms/ExplicitCommandField.js +107 -0
  27. package/dist/esm/forms/ExplicitCommandField.js.map +1 -0
  28. package/dist/esm/forms/SceneCommandForm.d.ts.map +1 -1
  29. package/dist/esm/forms/SceneCommandForm.js +27 -22
  30. package/dist/esm/forms/SceneCommandForm.js.map +1 -1
  31. package/dist/esm/forms/commandInputs.d.ts +7 -0
  32. package/dist/esm/forms/commandInputs.d.ts.map +1 -0
  33. package/dist/esm/forms/commandInputs.js +33 -0
  34. package/dist/esm/forms/commandInputs.js.map +1 -0
  35. package/dist/esm/forms/for_SceneCommandForm/given/RecordNote.d.ts +22 -0
  36. package/dist/esm/forms/for_SceneCommandForm/given/RecordNote.d.ts.map +1 -0
  37. package/dist/esm/forms/for_SceneCommandForm/given/RecordNote.js +30 -0
  38. package/dist/esm/forms/for_SceneCommandForm/given/RecordNote.js.map +1 -0
  39. package/dist/esm/forms/for_SceneCommandForm/given/StartProject.d.ts +32 -0
  40. package/dist/esm/forms/for_SceneCommandForm/given/StartProject.d.ts.map +1 -0
  41. package/dist/esm/forms/for_SceneCommandForm/given/StartProject.js +32 -0
  42. package/dist/esm/forms/for_SceneCommandForm/given/StartProject.js.map +1 -0
  43. package/dist/esm/forms/for_SceneCommandForm/when_forwarding_to_the_lazy_runtime.d.ts +2 -0
  44. package/dist/esm/forms/for_SceneCommandForm/when_forwarding_to_the_lazy_runtime.d.ts.map +1 -0
  45. package/dist/esm/forms/for_SceneCommandForm/when_forwarding_to_the_lazy_runtime.js +66 -0
  46. package/dist/esm/forms/for_SceneCommandForm/when_forwarding_to_the_lazy_runtime.js.map +1 -0
  47. package/dist/esm/forms/for_SceneCommandForm/when_native_custom_field_errors_block_submission.d.ts +2 -0
  48. package/dist/esm/forms/for_SceneCommandForm/when_native_custom_field_errors_block_submission.d.ts.map +1 -0
  49. package/dist/esm/forms/for_SceneCommandForm/when_native_custom_field_errors_block_submission.js +26 -0
  50. package/dist/esm/forms/for_SceneCommandForm/when_native_custom_field_errors_block_submission.js.map +1 -0
  51. package/dist/esm/forms/for_SceneCommandForm/when_preserving_guid_error_ownership.d.ts +2 -0
  52. package/dist/esm/forms/for_SceneCommandForm/when_preserving_guid_error_ownership.d.ts.map +1 -0
  53. package/dist/esm/forms/for_SceneCommandForm/when_preserving_guid_error_ownership.js +44 -0
  54. package/dist/esm/forms/for_SceneCommandForm/when_preserving_guid_error_ownership.js.map +1 -0
  55. package/dist/esm/forms/for_SceneCommandForm/when_rendering_submit_in_native_context.d.ts +2 -0
  56. package/dist/esm/forms/for_SceneCommandForm/when_rendering_submit_in_native_context.d.ts.map +1 -0
  57. package/dist/esm/forms/for_SceneCommandForm/when_rendering_submit_in_native_context.js +49 -0
  58. package/dist/esm/forms/for_SceneCommandForm/when_rendering_submit_in_native_context.js.map +1 -0
  59. package/dist/esm/forms/for_SceneCommandForm/when_submitting_explicit_inputs.d.ts +2 -0
  60. package/dist/esm/forms/for_SceneCommandForm/when_submitting_explicit_inputs.d.ts.map +1 -0
  61. package/dist/esm/forms/for_SceneCommandForm/when_submitting_explicit_inputs.js +176 -0
  62. package/dist/esm/forms/for_SceneCommandForm/when_submitting_explicit_inputs.js.map +1 -0
  63. package/dist/esm/forms/for_SceneCommandForm/when_submitting_the_native_form.d.ts +2 -0
  64. package/dist/esm/forms/for_SceneCommandForm/when_submitting_the_native_form.d.ts.map +1 -0
  65. package/dist/esm/forms/for_SceneCommandForm/when_submitting_the_native_form.js +110 -0
  66. package/dist/esm/forms/for_SceneCommandForm/when_submitting_the_native_form.js.map +1 -0
  67. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  68. package/for_cratisComponentsPackage/when_declaring_command_form_peers.ts +26 -0
  69. package/forms/CommandFormRuntime.tsx +71 -0
  70. package/forms/CommandFormSubmit.tsx +16 -0
  71. package/forms/ExplicitCommandField.tsx +86 -0
  72. package/forms/SceneCommandForm.tsx +30 -27
  73. package/forms/commandInputs.ts +29 -0
  74. package/forms/for_SceneCommandForm/given/RecordNote.ts +37 -0
  75. package/forms/for_SceneCommandForm/given/StartProject.ts +41 -0
  76. package/forms/for_SceneCommandForm/when_forwarding_to_the_lazy_runtime.tsx +69 -0
  77. package/forms/for_SceneCommandForm/when_native_custom_field_errors_block_submission.tsx +33 -0
  78. package/forms/for_SceneCommandForm/when_preserving_guid_error_ownership.tsx +50 -0
  79. package/forms/for_SceneCommandForm/when_rendering_submit_in_native_context.tsx +56 -0
  80. package/forms/for_SceneCommandForm/when_submitting_explicit_inputs.tsx +189 -0
  81. package/forms/for_SceneCommandForm/when_submitting_the_native_form.tsx +120 -0
  82. package/package.json +13 -13
package/README.md CHANGED
@@ -73,7 +73,7 @@ unbound table costs one dashed box, not the whole screen.
73
73
 
74
74
  `@cratis/arc`, `@cratis/arc.react` and `@cratis/fundamentals` are peer dependencies of `@cratis/components`
75
75
  that the *host* supplies. This package also declares Arc and Arc React as optional peers and pins
76
- 22.16.1 as development dependencies for native integration tests. A design surface is not a host.
76
+ 22.19.1 as development dependencies for native integration tests. A design surface is not a host.
77
77
 
78
78
  Every adapter that reaches them does so through a dynamic `import()` inside `React.lazy`, wrapped in
79
79
  `ArcRuntimeBoundary` (`Suspense` + the library's own `ErrorBoundary`). A screen built only from the library's
@@ -88,6 +88,22 @@ This splits the library cleanly, and the split is the library's own:
88
88
  The Storybook build externalizes the Arc packages (`.storybook/main.ts`) so the lazy chunk can be emitted
89
89
  with its imports left bare. No story loads that chunk, because no story registers a binding.
90
90
 
91
+ ## Actionable command forms
92
+
93
+ `commandForm` supplies a native submit button via `AutoCommandForm`'s optional `footer` ReactNode seam.
94
+ `submitLabel` is an optional string, defaulting to `Submit`. A private lazy runtime keeps Arc out of unbound
95
+ previews; its footer child reads the actual native form context for execution and authorization state.
96
+ Validity does not disable submission: native validation must be able to show errors on untouched forms.
97
+ Scene neither executes the command directly nor creates another form or command context.
98
+
99
+ Optional explicit `inputs` use exact native proxy descriptor names and types (`string`/`guid`) in one
100
+ Arc CommandForm; missing, ambiguous, uncovered required or unsupported declarations block the form. Auto
101
+ mode is fields-only and only supports String/Number/Boolean/Date providers, so required Guid does not silently
102
+ disappear. The content slot is not connected to either mode. A valid Guid draft becomes a typed Guid; Guid
103
+ JSON canonicalizes textual case without changing identity. No ID is generated. The declared peers require
104
+ published Components >=4.13.0 for the footer and Arc/Arc React >=22.19.1 for native custom-error gating.
105
+ Arc peers remain optional so unbound previews stay Arc-free.
106
+
91
107
  ## Optional single-result view (read-only)
92
108
 
93
109
  `Cratis.Components:singleResult` is a narrow adapter for an optional **single model**, not a collection.
@@ -0,0 +1,81 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var CommandForm = require('@cratis/components/CommandForm');
7
+ var commands = require('@cratis/arc.react/commands');
8
+ var fundamentals = require('@cratis/fundamentals');
9
+ var CommandFormSubmit = require('./CommandFormSubmit.js');
10
+ var ExplicitCommandField = require('./ExplicitCommandField.js');
11
+
12
+ // Copyright (c) Cratis. All rights reserved.
13
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
14
+ // Runtime bindings erase the proxy's keys; the optional footer is a Components >=4.13 contract.
15
+ const NativeAutoCommandForm = CommandForm.AutoCommandForm;
16
+ /** Verify the whole command before mounting any native form: partial forms must never execute. */ function capability(command, inputs, exclude) {
17
+ let descriptors;
18
+ try {
19
+ descriptors = new command().propertyDescriptors;
20
+ } catch {
21
+ return 'Unable to inspect command proxy';
22
+ }
23
+ if (!Array.isArray(descriptors)) return 'Command proxy has no property descriptors';
24
+ const byName = new Map();
25
+ for (const descriptor of descriptors){
26
+ if (!descriptor || typeof descriptor.name !== 'string' || !descriptor.name || typeof descriptor.isOptional !== 'boolean' || byName.has(descriptor.name)) return 'Ambiguous or invalid command property descriptors';
27
+ byName.set(descriptor.name, descriptor);
28
+ }
29
+ if (inputs) {
30
+ for (const input of inputs){
31
+ const descriptor = byName.get(input.property);
32
+ if (!descriptor) return `Unknown command property '${input.property}'`;
33
+ if (descriptor.type !== (input.type === 'guid' ? fundamentals.Guid : String)) return `Command property '${input.property}' type does not match '${input.type}'`;
34
+ }
35
+ for (const descriptor of byName.values()){
36
+ if (!descriptor.isOptional && !inputs.some((input)=>input.property === descriptor.name)) return `Required command property '${descriptor.name}' has no input`;
37
+ }
38
+ } else {
39
+ for (const descriptor of byName.values()){
40
+ if (!descriptor.isOptional && (exclude?.includes(descriptor.name) || ![
41
+ String,
42
+ Number,
43
+ Boolean,
44
+ Date
45
+ ].includes(descriptor.type))) {
46
+ return `Required command property '${descriptor.name}' has no supported automatic field; declare inputs`;
47
+ }
48
+ }
49
+ }
50
+ return undefined;
51
+ }
52
+ /** Private lazy entry point: importing the Scene registry must not import Arc. */ function CommandFormRuntime({ command, inputs, exclude, submitLabel }) {
53
+ const error = capability(command, inputs, exclude);
54
+ if (error) return /*#__PURE__*/ jsxRuntime.jsx("div", {
55
+ role: "alert",
56
+ children: error
57
+ });
58
+ // The registry's never-argument constructor is erased; Arc creates this checked proxy with no args.
59
+ if (inputs) return /*#__PURE__*/ jsxRuntime.jsxs(commands.CommandForm, {
60
+ command: command,
61
+ showTitles: false,
62
+ children: [
63
+ inputs.map((input)=>/*#__PURE__*/ jsxRuntime.jsx(ExplicitCommandField.ExplicitCommandField, {
64
+ input: input
65
+ }, input.property)),
66
+ /*#__PURE__*/ jsxRuntime.jsx(CommandFormSubmit.CommandFormSubmit, {
67
+ label: submitLabel
68
+ })
69
+ ]
70
+ });
71
+ return /*#__PURE__*/ jsxRuntime.jsx(NativeAutoCommandForm, {
72
+ command: command,
73
+ exclude: exclude,
74
+ footer: /*#__PURE__*/ jsxRuntime.jsx(CommandFormSubmit.CommandFormSubmit, {
75
+ label: submitLabel
76
+ })
77
+ });
78
+ }
79
+
80
+ exports.default = CommandFormRuntime;
81
+ //# sourceMappingURL=CommandFormRuntime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandFormRuntime.js","sources":["../../../forms/CommandFormRuntime.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 type { ComponentType, ReactNode } from 'react';\nimport { AutoCommandForm } from '@cratis/components/CommandForm';\nimport { CommandForm } from '@cratis/arc.react/commands';\nimport { Guid } from '@cratis/fundamentals';\nimport type { BoundConstructor } from '../bindings';\nimport type { CommandInput } from './commandInputs';\nimport { CommandFormSubmit } from './CommandFormSubmit';\nimport { ExplicitCommandField } from './ExplicitCommandField';\n\ninterface CommandFormRuntimeProps {\n command: BoundConstructor;\n inputs?: CommandInput[];\n exclude?: string[];\n submitLabel: string;\n}\n\n// Runtime bindings erase the proxy's keys; the optional footer is a Components >=4.13 contract.\nconst NativeAutoCommandForm = AutoCommandForm as unknown as ComponentType<{\n command: BoundConstructor;\n exclude?: string[];\n footer?: ReactNode;\n}>;\n\ntype Descriptor = { name: string; type: unknown; isOptional: boolean };\n\n/** Verify the whole command before mounting any native form: partial forms must never execute. */\nfunction capability(command: BoundConstructor, inputs?: CommandInput[], exclude?: string[]): string | undefined {\n let descriptors: unknown;\n try { descriptors = (new command() as { propertyDescriptors?: unknown }).propertyDescriptors; }\n catch { return 'Unable to inspect command proxy'; }\n if (!Array.isArray(descriptors)) return 'Command proxy has no property descriptors';\n const byName = new Map<string, Descriptor>();\n for (const descriptor of descriptors) {\n if (!descriptor || typeof descriptor.name !== 'string' || !descriptor.name ||\n typeof descriptor.isOptional !== 'boolean' || byName.has(descriptor.name)) return 'Ambiguous or invalid command property descriptors';\n byName.set(descriptor.name, descriptor);\n }\n if (inputs) {\n for (const input of inputs) {\n const descriptor = byName.get(input.property);\n if (!descriptor) return `Unknown command property '${input.property}'`;\n if (descriptor.type !== (input.type === 'guid' ? Guid : String)) return `Command property '${input.property}' type does not match '${input.type}'`;\n }\n for (const descriptor of byName.values()) {\n if (!descriptor.isOptional && !inputs.some(input => input.property === descriptor.name)) return `Required command property '${descriptor.name}' has no input`;\n }\n } else {\n for (const descriptor of byName.values()) {\n if (!descriptor.isOptional && (exclude?.includes(descriptor.name) ||\n ![String, Number, Boolean, Date].includes(descriptor.type as typeof String))) {\n return `Required command property '${descriptor.name}' has no supported automatic field; declare inputs`;\n }\n }\n }\n return undefined;\n}\n\n/** Private lazy entry point: importing the Scene registry must not import Arc. */\nexport default function CommandFormRuntime({ command, inputs, exclude, submitLabel }: CommandFormRuntimeProps) {\n const error = capability(command, inputs, exclude);\n if (error) return <div role='alert'>{error}</div>;\n // The registry's never-argument constructor is erased; Arc creates this checked proxy with no args.\n if (inputs) return <CommandForm command={command as unknown as new () => object} showTitles={false}>\n {inputs.map(input => <ExplicitCommandField key={input.property} input={input} />)}\n <CommandFormSubmit label={submitLabel} />\n </CommandForm>;\n return <NativeAutoCommandForm command={command} exclude={exclude} footer={<CommandFormSubmit label={submitLabel} />} />;\n}\n"],"names":["NativeAutoCommandForm","AutoCommandForm","capability","command","inputs","exclude","descriptors","propertyDescriptors","Array","isArray","byName","Map","descriptor","name","isOptional","has","set","input","get","property","type","Guid","String","values","some","includes","Number","Boolean","Date","undefined","CommandFormRuntime","submitLabel","error","_jsx","div","role","_jsxs","CommandForm","showTitles","map","ExplicitCommandField","CommandFormSubmit","label","footer"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var commands = require('@cratis/arc.react/commands');
5
+
6
+ /** Internal footer child; only rendered under the native form's context. */ function CommandFormSubmit({ label }) {
7
+ const { isExecuting, isAuthorized } = commands.useCommandFormContext();
8
+ // Do not gate on isValid: submitting untouched invalid fields must reveal native validation.
9
+ // No click handler: the containing Arc form owns submission, validation and execution.
10
+ return /*#__PURE__*/ jsxRuntime.jsx("button", {
11
+ type: "submit",
12
+ disabled: isExecuting || !isAuthorized,
13
+ "aria-busy": isExecuting,
14
+ children: label
15
+ });
16
+ }
17
+
18
+ exports.CommandFormSubmit = CommandFormSubmit;
19
+ //# sourceMappingURL=CommandFormSubmit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandFormSubmit.js","sources":["../../../forms/CommandFormSubmit.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 { useCommandFormContext } from '@cratis/arc.react/commands';\n\ninterface CommandFormSubmitProps {\n label: string;\n}\n\n/** Internal footer child; only rendered under the native form's context. */\nexport function CommandFormSubmit({ label }: CommandFormSubmitProps) {\n const { isExecuting, isAuthorized } = useCommandFormContext();\n // Do not gate on isValid: submitting untouched invalid fields must reveal native validation.\n // No click handler: the containing Arc form owns submission, validation and execution.\n return <button type='submit' disabled={isExecuting || !isAuthorized} aria-busy={isExecuting}>{label}</button>;\n}\n"],"names":["CommandFormSubmit","label","isExecuting","isAuthorized","useCommandFormContext","_jsx","button","type","disabled","aria-busy"],"mappings":";;;;;AASA,6EACO,SAASA,iBAAAA,CAAkB,EAAEC,KAAK,EAA0B,EAAA;AAC/D,IAAA,MAAM,EAAEC,WAAW,EAAEC,YAAY,EAAE,GAAGC,8BAAAA,EAAAA;;;AAGtC,IAAA,qBAAOC,cAAA,CAACC,QAAAA,EAAAA;QAAOC,IAAAA,EAAK,QAAA;AAASC,QAAAA,QAAAA,EAAUN,eAAe,CAACC,YAAAA;QAAcM,WAAAA,EAAWP,WAAAA;AAAcD,QAAAA,QAAAA,EAAAA;;AAClG;;"}
@@ -0,0 +1,109 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var react = require('react');
5
+ var commands = require('@cratis/arc.react/commands');
6
+ var fundamentals = require('@cratis/fundamentals');
7
+
8
+ function TextControl({ value, onChange, onBlur, invalid, required, errors, label, property, guid }) {
9
+ const id = react.useId();
10
+ const context = commands.useCommandFormContext();
11
+ const { setCustomFieldError } = context;
12
+ // Keep the latest native getter: the context snapshot can be stale when another field sets an
13
+ // error and this field unmounts in the same event.
14
+ const contextRef = react.useRef(context);
15
+ contextRef.current = context;
16
+ // The draft is intentionally independent of the typed proxy value: malformed text must never
17
+ // reappear as a stale previously valid Guid in the command's serialized payload.
18
+ const [draft, setDraft] = react.useState(()=>value instanceof fundamentals.Guid && !value.equals(fundamentals.Guid.empty) ? value.toString() : '');
19
+ const draftRef = react.useRef(draft);
20
+ const ownedError = react.useRef(undefined);
21
+ const updateError = (error)=>{
22
+ const current = contextRef.current.getFieldError(property);
23
+ // Do not replace or erase another producer's error for this field.
24
+ if (ownedError.current !== undefined && current !== ownedError.current) {
25
+ ownedError.current = undefined;
26
+ return;
27
+ }
28
+ if (ownedError.current === undefined && Object.hasOwn(contextRef.current.customFieldErrors, property)) return;
29
+ if (error === undefined && ownedError.current === undefined) return;
30
+ ownedError.current = error;
31
+ setCustomFieldError(property, error);
32
+ };
33
+ // A label/required change must recalculate the message without disposing the field's error.
34
+ // Only a different field/type or an actual unmount relinquishes ownership.
35
+ react.useLayoutEffect(()=>()=>{
36
+ if (ownedError.current !== undefined && contextRef.current.getFieldError(property) === ownedError.current) {
37
+ contextRef.current.setCustomFieldError(property, undefined);
38
+ }
39
+ ownedError.current = undefined;
40
+ }, [
41
+ property,
42
+ guid
43
+ ]);
44
+ react.useLayoutEffect(()=>{
45
+ if (guid) {
46
+ const current = draftRef.current || (value instanceof fundamentals.Guid && !value.equals(fundamentals.Guid.empty) ? value.toString() : '');
47
+ updateError(!current ? required ? `${label} is required` : undefined : !fundamentals.Guid.isGuid(current) ? `${label} must be a valid GUID` : undefined);
48
+ }
49
+ }, [
50
+ guid,
51
+ required,
52
+ property,
53
+ label,
54
+ setCustomFieldError
55
+ ]);
56
+ const text = guid ? draft : typeof value === 'string' ? value : '';
57
+ return /*#__PURE__*/ jsxRuntime.jsxs("div", {
58
+ children: [
59
+ /*#__PURE__*/ jsxRuntime.jsx("label", {
60
+ htmlFor: id,
61
+ children: label
62
+ }),
63
+ /*#__PURE__*/ jsxRuntime.jsx("input", {
64
+ id: id,
65
+ name: property,
66
+ type: "text",
67
+ required: required,
68
+ value: text,
69
+ "aria-invalid": invalid,
70
+ "aria-describedby": errors.length ? `${id}-error` : undefined,
71
+ onBlur: onBlur,
72
+ onChange: (event)=>{
73
+ const next = event.currentTarget.value;
74
+ if (!guid) {
75
+ onChange(next);
76
+ return;
77
+ }
78
+ draftRef.current = next;
79
+ setDraft(next);
80
+ const error = !next ? required ? `${label} is required` : undefined : !fundamentals.Guid.isGuid(next) ? `${label} must be a valid GUID` : undefined;
81
+ // A malformed draft clears the previously typed value, not just its display.
82
+ onChange(error || !next ? undefined : fundamentals.Guid.parse(next));
83
+ updateError(error);
84
+ }
85
+ }),
86
+ errors.length > 0 && /*#__PURE__*/ jsxRuntime.jsx("div", {
87
+ id: `${id}-error`,
88
+ role: "alert",
89
+ children: errors[0]
90
+ })
91
+ ]
92
+ });
93
+ }
94
+ const NativeTextField = commands.asCommandFormField(TextControl, {
95
+ defaultValue: ''
96
+ });
97
+ /** Opaque child is self-bound by Arc's native runtime binding, with an exact fieldName. */ function ExplicitCommandField({ input }) {
98
+ return /*#__PURE__*/ jsxRuntime.jsx(NativeTextField, {
99
+ fieldName: input.property,
100
+ value: (command)=>command[input.property],
101
+ property: input.property,
102
+ guid: input.type === 'guid',
103
+ label: input.label,
104
+ title: input.label
105
+ });
106
+ }
107
+
108
+ exports.ExplicitCommandField = ExplicitCommandField;
109
+ //# sourceMappingURL=ExplicitCommandField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExplicitCommandField.js","sources":["../../../forms/ExplicitCommandField.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 { useId, useLayoutEffect, useRef, useState } from 'react';\nimport { asCommandFormField, useCommandFormContext } from '@cratis/arc.react/commands';\nimport { Guid } from '@cratis/fundamentals';\nimport type { CommandInput } from './commandInputs';\n\ninterface TextProps {\n value: unknown;\n onChange: (value: unknown) => void;\n onBlur?: () => void;\n invalid: boolean;\n required: boolean;\n errors: string[];\n label: string;\n property: string;\n guid: boolean;\n}\n\nfunction TextControl({ value, onChange, onBlur, invalid, required, errors, label, property, guid }: TextProps) {\n const id = useId();\n const context = useCommandFormContext();\n const { setCustomFieldError } = context;\n // Keep the latest native getter: the context snapshot can be stale when another field sets an\n // error and this field unmounts in the same event.\n const contextRef = useRef(context);\n contextRef.current = context;\n // The draft is intentionally independent of the typed proxy value: malformed text must never\n // reappear as a stale previously valid Guid in the command's serialized payload.\n const [draft, setDraft] = useState(() => value instanceof Guid && !value.equals(Guid.empty) ? value.toString() : '');\n const draftRef = useRef(draft);\n const ownedError = useRef<string | undefined>(undefined);\n const updateError = (error: string | undefined) => {\n const current = contextRef.current.getFieldError(property);\n // Do not replace or erase another producer's error for this field.\n if (ownedError.current !== undefined && current !== ownedError.current) {\n ownedError.current = undefined;\n return;\n }\n if (ownedError.current === undefined && Object.hasOwn(contextRef.current.customFieldErrors, property)) return;\n if (error === undefined && ownedError.current === undefined) return;\n ownedError.current = error;\n setCustomFieldError(property, error);\n };\n // A label/required change must recalculate the message without disposing the field's error.\n // Only a different field/type or an actual unmount relinquishes ownership.\n useLayoutEffect(() => () => {\n if (ownedError.current !== undefined && contextRef.current.getFieldError(property) === ownedError.current) {\n contextRef.current.setCustomFieldError(property, undefined);\n }\n ownedError.current = undefined;\n }, [property, guid]);\n useLayoutEffect(() => {\n if (guid) {\n const current = draftRef.current || (value instanceof Guid && !value.equals(Guid.empty) ? value.toString() : '');\n updateError(!current ? required ? `${label} is required` : undefined :\n !Guid.isGuid(current) ? `${label} must be a valid GUID` : undefined);\n }\n }, [guid, required, property, label, setCustomFieldError]);\n const text = guid ? draft : typeof value === 'string' ? value : '';\n return <div>\n <label htmlFor={id}>{label}</label>\n <input id={id} name={property} type='text' required={required} value={text}\n aria-invalid={invalid} aria-describedby={errors.length ? `${id}-error` : undefined}\n onBlur={onBlur} onChange={event => {\n const next = event.currentTarget.value;\n if (!guid) { onChange(next); return; }\n draftRef.current = next;\n setDraft(next);\n const error = !next ? required ? `${label} is required` : undefined : !Guid.isGuid(next) ? `${label} must be a valid GUID` : undefined;\n // A malformed draft clears the previously typed value, not just its display.\n onChange(error || !next ? undefined : Guid.parse(next));\n updateError(error);\n }} />\n {errors.length > 0 && <div id={`${id}-error`} role='alert'>{errors[0]}</div>}\n </div>;\n}\n\nconst NativeTextField = asCommandFormField<TextProps>(TextControl, { defaultValue: '' });\n\n/** Opaque child is self-bound by Arc's native runtime binding, with an exact fieldName. */\nexport function ExplicitCommandField({ input }: { input: CommandInput }) {\n return <NativeTextField fieldName={input.property} value={(command: Record<string, unknown>) => command[input.property]}\n property={input.property} guid={input.type === 'guid'} label={input.label} title={input.label} />;\n}\n"],"names":["TextControl","value","onChange","onBlur","invalid","required","errors","label","property","guid","id","useId","context","useCommandFormContext","setCustomFieldError","contextRef","useRef","current","draft","setDraft","useState","Guid","equals","empty","toString","draftRef","ownedError","undefined","updateError","error","getFieldError","Object","hasOwn","customFieldErrors","useLayoutEffect","isGuid","text","_jsxs","div","_jsx","htmlFor","input","name","type","aria-invalid","aria-describedby","length","event","next","currentTarget","parse","role","NativeTextField","asCommandFormField","defaultValue","ExplicitCommandField","fieldName","command","title"],"mappings":"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"}
@@ -7,26 +7,24 @@ var resolveElementBinding = require('../bindings/resolveElementBinding.js');
7
7
  var MissingBinding = require('../bindings/MissingBinding.js');
8
8
  var ArcRuntimeBoundary = require('../bindings/ArcRuntimeBoundary.js');
9
9
  var properties = require('../properties.js');
10
+ var commandInputs = require('./commandInputs.js');
10
11
 
12
+ const CommandFormRuntime = /*#__PURE__*/ react.lazy(()=>Promise.resolve().then(function () { return require('./CommandFormRuntime.js'); }));
13
+ // Arc's useCommand constructs the proxy only on mount. Key by the actual registered class,
14
+ // not its Scene name (which may be re-registered with a different route or roles).
15
+ const commandKeys = new WeakMap();
16
+ let nextCommandKey = 0;
17
+ function commandKey(command) {
18
+ let key = commandKeys.get(command);
19
+ if (key === undefined) {
20
+ key = ++nextCommandKey;
21
+ commandKeys.set(command, key);
22
+ }
23
+ return key;
24
+ }
11
25
  /**
12
- * `AutoCommandForm` types `exclude` as `(keyof TCommand)[]`, which collapses to `never[]` when the
13
- * command type is only known at runtime - as it always is here, since the class arrives from the binding
14
- * registry rather than from a type annotation. The conversion states the shape this adapter actually
15
- * passes; the underlying component reads `exclude` as property names either way.
16
- */ const AutoCommandForm = /*#__PURE__*/ react.lazy(async ()=>({
17
- default: (await import('@cratis/components/CommandForm')).AutoCommandForm
18
- }));
19
- /**
20
- * The `Cratis.Components:commandForm` component - `AutoCommandForm` from `@cratis/components/CommandForm`.
21
- *
22
- * `AutoCommandForm` rather than `CommandForm`, because a screen that had to list every field by hand
23
- * would go stale the moment a property is added to the command on the backend. `AutoCommandForm` reads
24
- * the command's own property descriptors and picks a field component per property type, so the form
25
- * follows the command - which is the same guarantee Arc's generated proxies give the rest of the stack.
26
- *
27
- * A screen that does want to place fields itself puts the field components from this package in the
28
- * `content` slot and names them individually; `exclude` keeps `AutoCommandForm` from generating a second
29
- * copy of anything placed that way.
26
+ * Auto mode follows supported native proxy descriptors; opt-in inputs bind exactly named fields
27
+ * inside a single native Arc form. Neither mode consumes the content slot.
30
28
  */ function SceneCommandForm({ element }) {
31
29
  const { name, target } = resolveElementBinding.resolveElementBinding(element, BindingKind.BindingKind.Command);
32
30
  if (!target) return /*#__PURE__*/ jsxRuntime.jsx(MissingBinding.MissingBinding, {
@@ -34,11 +32,18 @@ var properties = require('../properties.js');
34
32
  kind: BindingKind.BindingKind.Command,
35
33
  name: name
36
34
  });
35
+ const inputs = Object.hasOwn(element.properties, 'inputs') ? commandInputs.commandInputs(element.properties) : undefined;
36
+ if (Object.hasOwn(element.properties, 'inputs') && !inputs) return /*#__PURE__*/ jsxRuntime.jsx("div", {
37
+ role: "alert",
38
+ children: "Invalid command form inputs declaration"
39
+ });
37
40
  return /*#__PURE__*/ jsxRuntime.jsx(ArcRuntimeBoundary.ArcRuntimeBoundary, {
38
- children: /*#__PURE__*/ jsxRuntime.jsx(AutoCommandForm, {
41
+ children: /*#__PURE__*/ jsxRuntime.jsx(CommandFormRuntime, {
39
42
  command: target,
40
- exclude: properties.stringArrayProperty(element.properties, 'exclude')
41
- })
43
+ inputs: inputs,
44
+ exclude: properties.stringArrayProperty(element.properties, 'exclude'),
45
+ submitLabel: properties.stringProperty(element.properties, 'submitLabel') ?? 'Submit'
46
+ }, commandKey(target))
42
47
  });
43
48
  }
44
49
 
@@ -1 +1 @@
1
- {"version":3,"file":"SceneCommandForm.js","sources":["../../../forms/SceneCommandForm.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 { ComponentType, lazy } from 'react';\nimport { RegisteredComponentProps } from '@cratis/scene.react';\nimport { ArcRuntimeBoundary, BindingKind, BoundConstructor, MissingBinding, resolveElementBinding } from '../bindings';\nimport { stringArrayProperty } from '../properties';\n\ninterface AutoCommandFormElementProps {\n command: BoundConstructor;\n exclude?: string[];\n}\n\n/**\n * `AutoCommandForm` types `exclude` as `(keyof TCommand)[]`, which collapses to `never[]` when the\n * command type is only known at runtime - as it always is here, since the class arrives from the binding\n * registry rather than from a type annotation. The conversion states the shape this adapter actually\n * passes; the underlying component reads `exclude` as property names either way.\n */\nconst AutoCommandForm = lazy(async () => ({\n default: (await import('@cratis/components/CommandForm')).AutoCommandForm as unknown as ComponentType<AutoCommandFormElementProps>,\n}));\n\n/**\n * The `Cratis.Components:commandForm` component - `AutoCommandForm` from `@cratis/components/CommandForm`.\n *\n * `AutoCommandForm` rather than `CommandForm`, because a screen that had to list every field by hand\n * would go stale the moment a property is added to the command on the backend. `AutoCommandForm` reads\n * the command's own property descriptors and picks a field component per property type, so the form\n * follows the command - which is the same guarantee Arc's generated proxies give the rest of the stack.\n *\n * A screen that does want to place fields itself puts the field components from this package in the\n * `content` slot and names them individually; `exclude` keeps `AutoCommandForm` from generating a second\n * copy of anything placed that way.\n */\nexport function SceneCommandForm({ element }: RegisteredComponentProps) {\n const { name, target } = resolveElementBinding(element, BindingKind.Command);\n if (!target) return <MissingBinding element={element} kind={BindingKind.Command} name={name} />;\n\n return (\n <ArcRuntimeBoundary>\n <AutoCommandForm command={target} exclude={stringArrayProperty(element.properties, 'exclude')} />\n </ArcRuntimeBoundary>\n );\n}\n"],"names":["AutoCommandForm","lazy","default","SceneCommandForm","element","name","target","resolveElementBinding","BindingKind","Command","_jsx","MissingBinding","kind","ArcRuntimeBoundary","command","exclude","stringArrayProperty","properties"],"mappings":";;;;;;;;;;AAaA;;;;;AAKC,IACD,MAAMA,eAAAA,iBAAkBC,UAAAA,CAAK,WAAa;AACtCC,QAAAA,OAAAA,EAAS,CAAC,MAAM,OAAO,gCAAA,CAAgC,EAAGF;KAC9D,CAAA,CAAA;AAEA;;;;;;;;;;;AAWC,IACM,SAASG,gBAAAA,CAAiB,EAAEC,OAAO,EAA4B,EAAA;IAClE,MAAM,EAAEC,IAAI,EAAEC,MAAM,EAAE,GAAGC,2CAAAA,CAAsBH,OAAAA,EAASI,uBAAAA,CAAYC,OAAO,CAAA;IAC3E,IAAI,CAACH,MAAAA,EAAQ,qBAAOI,cAAA,CAACC,6BAAAA,EAAAA;QAAeP,OAAAA,EAASA,OAAAA;AAASQ,QAAAA,IAAAA,EAAMJ,wBAAYC,OAAO;QAAEJ,IAAAA,EAAMA;;AAEvF,IAAA,qBACIK,cAAA,CAACG,qCAAAA,EAAAA;AACG,QAAA,QAAA,gBAAAH,cAAA,CAACV,eAAAA,EAAAA;YAAgBc,OAAAA,EAASR,MAAAA;YAAQS,OAAAA,EAASC,8BAAAA,CAAoBZ,OAAAA,CAAQa,UAAU,EAAE,SAAA;;;AAG/F;;"}
1
+ {"version":3,"file":"SceneCommandForm.js","sources":["../../../forms/SceneCommandForm.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 { lazy } from 'react';\nimport { RegisteredComponentProps } from '@cratis/scene.react';\nimport { ArcRuntimeBoundary, BindingKind, MissingBinding, resolveElementBinding } from '../bindings';\nimport type { BoundConstructor } from '../bindings';\nimport { stringArrayProperty, stringProperty } from '../properties';\nimport { commandInputs } from './commandInputs';\n\nconst CommandFormRuntime = lazy(() => import('./CommandFormRuntime'));\n\n// Arc's useCommand constructs the proxy only on mount. Key by the actual registered class,\n// not its Scene name (which may be re-registered with a different route or roles).\nconst commandKeys = new WeakMap<BoundConstructor, number>();\nlet nextCommandKey = 0;\nfunction commandKey(command: BoundConstructor): number {\n let key = commandKeys.get(command);\n if (key === undefined) {\n key = ++nextCommandKey;\n commandKeys.set(command, key);\n }\n return key;\n}\n\n/**\n * Auto mode follows supported native proxy descriptors; opt-in inputs bind exactly named fields\n * inside a single native Arc form. Neither mode consumes the content slot.\n */\nexport function SceneCommandForm({ element }: RegisteredComponentProps) {\n const { name, target } = resolveElementBinding(element, BindingKind.Command);\n if (!target) return <MissingBinding element={element} kind={BindingKind.Command} name={name} />;\n\n const inputs = Object.hasOwn(element.properties, 'inputs') ? commandInputs(element.properties) : undefined;\n if (Object.hasOwn(element.properties, 'inputs') && !inputs) return <div role='alert'>Invalid command form inputs declaration</div>;\n\n return (\n <ArcRuntimeBoundary>\n <CommandFormRuntime\n key={commandKey(target)}\n command={target}\n inputs={inputs}\n exclude={stringArrayProperty(element.properties, 'exclude')}\n submitLabel={stringProperty(element.properties, 'submitLabel') ?? 'Submit'}\n />\n </ArcRuntimeBoundary>\n );\n}\n"],"names":["CommandFormRuntime","lazy","commandKeys","WeakMap","nextCommandKey","commandKey","command","key","get","undefined","set","SceneCommandForm","element","name","target","resolveElementBinding","BindingKind","Command","_jsx","MissingBinding","kind","inputs","Object","hasOwn","properties","commandInputs","div","role","ArcRuntimeBoundary","exclude","stringArrayProperty","submitLabel","stringProperty"],"mappings":";;;;;;;;;;;AAUA,MAAMA,kBAAAA,iBAAqBC,UAAAA,CAAK,IAAM,oDAAO,yBAAA,KAAA,CAAA;AAE7C;AACA;AACA,MAAMC,cAAc,IAAIC,OAAAA,EAAAA;AACxB,IAAIC,cAAAA,GAAiB,CAAA;AACrB,SAASC,WAAWC,OAAyB,EAAA;IACzC,IAAIC,GAAAA,GAAML,WAAAA,CAAYM,GAAG,CAACF,OAAAA,CAAAA;AAC1B,IAAA,IAAIC,QAAQE,SAAAA,EAAW;AACnBF,QAAAA,GAAAA,GAAM,EAAEH,cAAAA;QACRF,WAAAA,CAAYQ,GAAG,CAACJ,OAAAA,EAASC,GAAAA,CAAAA;AAC7B,IAAA;IACA,OAAOA,GAAAA;AACX;AAEA;;;AAGC,IACM,SAASI,gBAAAA,CAAiB,EAAEC,OAAO,EAA4B,EAAA;IAClE,MAAM,EAAEC,IAAI,EAAEC,MAAM,EAAE,GAAGC,2CAAAA,CAAsBH,OAAAA,EAASI,uBAAAA,CAAYC,OAAO,CAAA;IAC3E,IAAI,CAACH,MAAAA,EAAQ,qBAAOI,cAAA,CAACC,6BAAAA,EAAAA;QAAeP,OAAAA,EAASA,OAAAA;AAASQ,QAAAA,IAAAA,EAAMJ,wBAAYC,OAAO;QAAEJ,IAAAA,EAAMA;;IAEvF,MAAMQ,MAAAA,GAASC,MAAAA,CAAOC,MAAM,CAACX,OAAAA,CAAQY,UAAU,EAAE,QAAA,CAAA,GAAYC,2BAAAA,CAAcb,OAAAA,CAAQY,UAAU,CAAA,GAAIf,SAAAA;IACjG,IAAIa,MAAAA,CAAOC,MAAM,CAACX,OAAAA,CAAQY,UAAU,EAAE,QAAA,CAAA,IAAa,CAACH,MAAAA,EAAQ,qBAAOH,cAAA,CAACQ,KAAAA,EAAAA;QAAIC,IAAAA,EAAK,OAAA;AAAQ,QAAA,QAAA,EAAA;;AAErF,IAAA,qBACIT,cAAA,CAACU,qCAAAA,EAAAA;AACG,QAAA,QAAA,gBAAAV,cAAA,CAAClB,kBAAAA,EAAAA;YAEGM,OAAAA,EAASQ,MAAAA;YACTO,MAAAA,EAAQA,MAAAA;YACRQ,OAAAA,EAASC,8BAAAA,CAAoBlB,OAAAA,CAAQY,UAAU,EAAE,SAAA,CAAA;AACjDO,YAAAA,WAAAA,EAAaC,yBAAAA,CAAepB,OAAAA,CAAQY,UAAU,EAAE,aAAA,CAAA,IAAkB;WAJ7DnB,UAAAA,CAAWS,MAAAA,CAAAA;;AAQhC;;"}
@@ -0,0 +1,35 @@
1
+ 'use strict';
2
+
3
+ var properties = require('../properties.js');
4
+
5
+ // Copyright (c) Cratis. All rights reserved.
6
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
7
+ /** An absent declaration selects legacy auto mode; a present but invalid declaration never does. */ function commandInputs(properties$1) {
8
+ const values = properties.arrayProperty(properties$1, 'inputs');
9
+ if (!values?.length) return undefined;
10
+ const inputs = [];
11
+ const seen = new Set();
12
+ for (const value of values){
13
+ const input = properties.objectProperty({
14
+ value
15
+ }, 'value');
16
+ if (!input || Object.keys(input).some((key)=>![
17
+ 'property',
18
+ 'type',
19
+ 'label'
20
+ ].includes(key))) return undefined;
21
+ const property = properties.stringProperty(input, 'property');
22
+ const label = properties.stringProperty(input, 'label');
23
+ if (!property?.trim() || !label?.trim() || input.type !== 'string' && input.type !== 'guid' || seen.has(property)) return undefined;
24
+ seen.add(property);
25
+ inputs.push({
26
+ property,
27
+ type: input.type,
28
+ label
29
+ });
30
+ }
31
+ return inputs;
32
+ }
33
+
34
+ exports.commandInputs = commandInputs;
35
+ //# sourceMappingURL=commandInputs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandInputs.js","sources":["../../../forms/commandInputs.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 { arrayProperty, objectProperty, stringProperty } from '../properties';\n\n/** Exact, case-sensitive names from a generated command's propertyDescriptors. */\nexport interface CommandInput {\n property: string;\n type: 'string' | 'guid';\n label: string;\n}\n\n/** An absent declaration selects legacy auto mode; a present but invalid declaration never does. */\nexport function commandInputs(properties: Record<string, unknown>): CommandInput[] | undefined {\n const values = arrayProperty(properties, 'inputs');\n if (!values?.length) return undefined;\n const inputs: CommandInput[] = [];\n const seen = new Set<string>();\n for (const value of values) {\n const input = objectProperty({ value }, 'value');\n if (!input || Object.keys(input).some(key => !['property', 'type', 'label'].includes(key))) return undefined;\n const property = stringProperty(input, 'property');\n const label = stringProperty(input, 'label');\n if (!property?.trim() || !label?.trim() || (input.type !== 'string' && input.type !== 'guid') || seen.has(property)) return undefined;\n seen.add(property);\n inputs.push({ property, type: input.type, label });\n }\n return inputs;\n}\n"],"names":["commandInputs","properties","values","arrayProperty","length","undefined","inputs","seen","Set","value","input","objectProperty","Object","keys","some","key","includes","property","stringProperty","label","trim","type","has","add","push"],"mappings":";;;;AAAA;AACA;AAWA,qGACO,SAASA,aAAAA,CAAcC,YAAmC,EAAA;IAC7D,MAAMC,MAAAA,GAASC,yBAAcF,YAAAA,EAAY,QAAA,CAAA;IACzC,IAAI,CAACC,MAAAA,EAAQE,MAAAA,EAAQ,OAAOC,SAAAA;AAC5B,IAAA,MAAMC,SAAyB,EAAE;AACjC,IAAA,MAAMC,OAAO,IAAIC,GAAAA,EAAAA;IACjB,KAAK,MAAMC,SAASP,MAAAA,CAAQ;AACxB,QAAA,MAAMQ,QAAQC,yBAAAA,CAAe;AAAEF,YAAAA;SAAM,EAAG,OAAA,CAAA;QACxC,IAAI,CAACC,KAAAA,IAASE,MAAAA,CAAOC,IAAI,CAACH,OAAOI,IAAI,CAACC,CAAAA,GAAAA,GAAO,CAAC;AAAC,gBAAA,UAAA;AAAY,gBAAA,MAAA;AAAQ,gBAAA;aAAQ,CAACC,QAAQ,CAACD,GAAAA,CAAAA,CAAAA,EAAO,OAAOV,SAAAA;QACnG,MAAMY,QAAAA,GAAWC,0BAAeR,KAAAA,EAAO,UAAA,CAAA;QACvC,MAAMS,KAAAA,GAAQD,0BAAeR,KAAAA,EAAO,OAAA,CAAA;AACpC,QAAA,IAAI,CAACO,QAAAA,EAAUG,IAAAA,EAAAA,IAAU,CAACD,KAAAA,EAAOC,IAAAA,EAAAA,IAAWV,MAAMW,IAAI,KAAK,QAAA,IAAYX,KAAAA,CAAMW,IAAI,KAAK,MAAA,IAAWd,KAAKe,GAAG,CAACL,WAAW,OAAOZ,SAAAA;AAC5HE,QAAAA,IAAAA,CAAKgB,GAAG,CAACN,QAAAA,CAAAA;AACTX,QAAAA,MAAAA,CAAOkB,IAAI,CAAC;AAAEP,YAAAA,QAAAA;AAAUI,YAAAA,IAAAA,EAAMX,MAAMW,IAAI;AAAEF,YAAAA;AAAM,SAAA,CAAA;AACpD,IAAA;IACA,OAAOb,MAAAA;AACX;;"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=when_declaring_command_form_peers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"when_declaring_command_form_peers.d.ts","sourceRoot":"","sources":["../../../for_cratisComponentsPackage/when_declaring_command_form_peers.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { expect } from 'vitest';
3
+ const packageJson = JSON.parse(readFileSync('package.json', 'utf8'));
4
+ describe('when declaring native command form peers', () => {
5
+ it('requires the published footer and native custom-error execution contracts', () => {
6
+ expect(packageJson.name).toBe('@cratis/scene.components');
7
+ expect(packageJson.peerDependencies['@cratis/components']).toBe('^4.13.0');
8
+ expect(packageJson.peerDependencies['@cratis/arc']).toBe('^22.19.1');
9
+ expect(packageJson.peerDependencies['@cratis/arc.react']).toBe('^22.19.1');
10
+ });
11
+ it('keeps Arc optional for an unbound design-time preview', () => {
12
+ expect(packageJson.peerDependenciesMeta['@cratis/arc'].optional).toBe(true);
13
+ expect(packageJson.peerDependenciesMeta['@cratis/arc.react'].optional).toBe(true);
14
+ });
15
+ });
16
+ //# sourceMappingURL=when_declaring_command_form_peers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"when_declaring_command_form_peers.js","sourceRoot":"","sources":["../../../for_cratisComponentsPackage/when_declaring_command_form_peers.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGhC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,cAAc,EAAE,MAAM,CAAC,CAIlE,CAAC;AAEF,QAAQ,CAAC,0CAA0C,EAAE,GAAG,EAAE;IACtD,EAAE,CAAC,2EAA2E,EAAE,GAAG,EAAE;QACjF,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAC1D,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC3E,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACrE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC7D,MAAM,CAAC,WAAW,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5E,MAAM,CAAC,WAAW,CAAC,oBAAoB,CAAC,mBAAmB,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { BoundConstructor } from '../bindings';
2
+ import type { CommandInput } from './commandInputs';
3
+ interface CommandFormRuntimeProps {
4
+ command: BoundConstructor;
5
+ inputs?: CommandInput[];
6
+ exclude?: string[];
7
+ submitLabel: string;
8
+ }
9
+ export default function CommandFormRuntime({ command, inputs, exclude, submitLabel }: CommandFormRuntimeProps): import("react").JSX.Element;
10
+ export {};
11
+ //# sourceMappingURL=CommandFormRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandFormRuntime.d.ts","sourceRoot":"","sources":["../../../forms/CommandFormRuntime.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAIpD,UAAU,uBAAuB;IAC7B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACvB;AA4CD,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,uBAAuB,+BAS5G"}
@@ -0,0 +1,77 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { AutoCommandForm } from '@cratis/components/CommandForm';
3
+ import { CommandForm } from '@cratis/arc.react/commands';
4
+ import { Guid } from '@cratis/fundamentals';
5
+ import { CommandFormSubmit } from './CommandFormSubmit.js';
6
+ import { ExplicitCommandField } from './ExplicitCommandField.js';
7
+
8
+ // Copyright (c) Cratis. All rights reserved.
9
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
10
+ // Runtime bindings erase the proxy's keys; the optional footer is a Components >=4.13 contract.
11
+ const NativeAutoCommandForm = AutoCommandForm;
12
+ /** Verify the whole command before mounting any native form: partial forms must never execute. */ function capability(command, inputs, exclude) {
13
+ let descriptors;
14
+ try {
15
+ descriptors = new command().propertyDescriptors;
16
+ } catch {
17
+ return 'Unable to inspect command proxy';
18
+ }
19
+ if (!Array.isArray(descriptors)) return 'Command proxy has no property descriptors';
20
+ const byName = new Map();
21
+ for (const descriptor of descriptors){
22
+ if (!descriptor || typeof descriptor.name !== 'string' || !descriptor.name || typeof descriptor.isOptional !== 'boolean' || byName.has(descriptor.name)) return 'Ambiguous or invalid command property descriptors';
23
+ byName.set(descriptor.name, descriptor);
24
+ }
25
+ if (inputs) {
26
+ for (const input of inputs){
27
+ const descriptor = byName.get(input.property);
28
+ if (!descriptor) return `Unknown command property '${input.property}'`;
29
+ if (descriptor.type !== (input.type === 'guid' ? Guid : String)) return `Command property '${input.property}' type does not match '${input.type}'`;
30
+ }
31
+ for (const descriptor of byName.values()){
32
+ if (!descriptor.isOptional && !inputs.some((input)=>input.property === descriptor.name)) return `Required command property '${descriptor.name}' has no input`;
33
+ }
34
+ } else {
35
+ for (const descriptor of byName.values()){
36
+ if (!descriptor.isOptional && (exclude?.includes(descriptor.name) || ![
37
+ String,
38
+ Number,
39
+ Boolean,
40
+ Date
41
+ ].includes(descriptor.type))) {
42
+ return `Required command property '${descriptor.name}' has no supported automatic field; declare inputs`;
43
+ }
44
+ }
45
+ }
46
+ return undefined;
47
+ }
48
+ /** Private lazy entry point: importing the Scene registry must not import Arc. */ function CommandFormRuntime({ command, inputs, exclude, submitLabel }) {
49
+ const error = capability(command, inputs, exclude);
50
+ if (error) return /*#__PURE__*/ jsx("div", {
51
+ role: "alert",
52
+ children: error
53
+ });
54
+ // The registry's never-argument constructor is erased; Arc creates this checked proxy with no args.
55
+ if (inputs) return /*#__PURE__*/ jsxs(CommandForm, {
56
+ command: command,
57
+ showTitles: false,
58
+ children: [
59
+ inputs.map((input)=>/*#__PURE__*/ jsx(ExplicitCommandField, {
60
+ input: input
61
+ }, input.property)),
62
+ /*#__PURE__*/ jsx(CommandFormSubmit, {
63
+ label: submitLabel
64
+ })
65
+ ]
66
+ });
67
+ return /*#__PURE__*/ jsx(NativeAutoCommandForm, {
68
+ command: command,
69
+ exclude: exclude,
70
+ footer: /*#__PURE__*/ jsx(CommandFormSubmit, {
71
+ label: submitLabel
72
+ })
73
+ });
74
+ }
75
+
76
+ export { CommandFormRuntime as default };
77
+ //# sourceMappingURL=CommandFormRuntime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandFormRuntime.js","sources":["../../../forms/CommandFormRuntime.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 type { ComponentType, ReactNode } from 'react';\nimport { AutoCommandForm } from '@cratis/components/CommandForm';\nimport { CommandForm } from '@cratis/arc.react/commands';\nimport { Guid } from '@cratis/fundamentals';\nimport type { BoundConstructor } from '../bindings';\nimport type { CommandInput } from './commandInputs';\nimport { CommandFormSubmit } from './CommandFormSubmit';\nimport { ExplicitCommandField } from './ExplicitCommandField';\n\ninterface CommandFormRuntimeProps {\n command: BoundConstructor;\n inputs?: CommandInput[];\n exclude?: string[];\n submitLabel: string;\n}\n\n// Runtime bindings erase the proxy's keys; the optional footer is a Components >=4.13 contract.\nconst NativeAutoCommandForm = AutoCommandForm as unknown as ComponentType<{\n command: BoundConstructor;\n exclude?: string[];\n footer?: ReactNode;\n}>;\n\ntype Descriptor = { name: string; type: unknown; isOptional: boolean };\n\n/** Verify the whole command before mounting any native form: partial forms must never execute. */\nfunction capability(command: BoundConstructor, inputs?: CommandInput[], exclude?: string[]): string | undefined {\n let descriptors: unknown;\n try { descriptors = (new command() as { propertyDescriptors?: unknown }).propertyDescriptors; }\n catch { return 'Unable to inspect command proxy'; }\n if (!Array.isArray(descriptors)) return 'Command proxy has no property descriptors';\n const byName = new Map<string, Descriptor>();\n for (const descriptor of descriptors) {\n if (!descriptor || typeof descriptor.name !== 'string' || !descriptor.name ||\n typeof descriptor.isOptional !== 'boolean' || byName.has(descriptor.name)) return 'Ambiguous or invalid command property descriptors';\n byName.set(descriptor.name, descriptor);\n }\n if (inputs) {\n for (const input of inputs) {\n const descriptor = byName.get(input.property);\n if (!descriptor) return `Unknown command property '${input.property}'`;\n if (descriptor.type !== (input.type === 'guid' ? Guid : String)) return `Command property '${input.property}' type does not match '${input.type}'`;\n }\n for (const descriptor of byName.values()) {\n if (!descriptor.isOptional && !inputs.some(input => input.property === descriptor.name)) return `Required command property '${descriptor.name}' has no input`;\n }\n } else {\n for (const descriptor of byName.values()) {\n if (!descriptor.isOptional && (exclude?.includes(descriptor.name) ||\n ![String, Number, Boolean, Date].includes(descriptor.type as typeof String))) {\n return `Required command property '${descriptor.name}' has no supported automatic field; declare inputs`;\n }\n }\n }\n return undefined;\n}\n\n/** Private lazy entry point: importing the Scene registry must not import Arc. */\nexport default function CommandFormRuntime({ command, inputs, exclude, submitLabel }: CommandFormRuntimeProps) {\n const error = capability(command, inputs, exclude);\n if (error) return <div role='alert'>{error}</div>;\n // The registry's never-argument constructor is erased; Arc creates this checked proxy with no args.\n if (inputs) return <CommandForm command={command as unknown as new () => object} showTitles={false}>\n {inputs.map(input => <ExplicitCommandField key={input.property} input={input} />)}\n <CommandFormSubmit label={submitLabel} />\n </CommandForm>;\n return <NativeAutoCommandForm command={command} exclude={exclude} footer={<CommandFormSubmit label={submitLabel} />} />;\n}\n"],"names":["NativeAutoCommandForm","AutoCommandForm","capability","command","inputs","exclude","descriptors","propertyDescriptors","Array","isArray","byName","Map","descriptor","name","isOptional","has","set","input","get","property","type","Guid","String","values","some","includes","Number","Boolean","Date","undefined","CommandFormRuntime","submitLabel","error","_jsx","div","role","_jsxs","CommandForm","showTitles","map","ExplicitCommandField","CommandFormSubmit","label","footer"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ interface CommandFormSubmitProps {
2
+ label: string;
3
+ }
4
+ export declare function CommandFormSubmit({ label }: CommandFormSubmitProps): import("react").JSX.Element;
5
+ export {};
6
+ //# sourceMappingURL=CommandFormSubmit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandFormSubmit.d.ts","sourceRoot":"","sources":["../../../forms/CommandFormSubmit.tsx"],"names":[],"mappings":"AAKA,UAAU,sBAAsB;IAC5B,KAAK,EAAE,MAAM,CAAC;CACjB;AAGD,wBAAgB,iBAAiB,CAAC,EAAE,KAAK,EAAE,EAAE,sBAAsB,+BAKlE"}
@@ -0,0 +1,17 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useCommandFormContext } from '@cratis/arc.react/commands';
3
+
4
+ /** Internal footer child; only rendered under the native form's context. */ function CommandFormSubmit({ label }) {
5
+ const { isExecuting, isAuthorized } = useCommandFormContext();
6
+ // Do not gate on isValid: submitting untouched invalid fields must reveal native validation.
7
+ // No click handler: the containing Arc form owns submission, validation and execution.
8
+ return /*#__PURE__*/ jsx("button", {
9
+ type: "submit",
10
+ disabled: isExecuting || !isAuthorized,
11
+ "aria-busy": isExecuting,
12
+ children: label
13
+ });
14
+ }
15
+
16
+ export { CommandFormSubmit };
17
+ //# sourceMappingURL=CommandFormSubmit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommandFormSubmit.js","sources":["../../../forms/CommandFormSubmit.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 { useCommandFormContext } from '@cratis/arc.react/commands';\n\ninterface CommandFormSubmitProps {\n label: string;\n}\n\n/** Internal footer child; only rendered under the native form's context. */\nexport function CommandFormSubmit({ label }: CommandFormSubmitProps) {\n const { isExecuting, isAuthorized } = useCommandFormContext();\n // Do not gate on isValid: submitting untouched invalid fields must reveal native validation.\n // No click handler: the containing Arc form owns submission, validation and execution.\n return <button type='submit' disabled={isExecuting || !isAuthorized} aria-busy={isExecuting}>{label}</button>;\n}\n"],"names":["CommandFormSubmit","label","isExecuting","isAuthorized","useCommandFormContext","_jsx","button","type","disabled","aria-busy"],"mappings":";;;AASA,6EACO,SAASA,iBAAAA,CAAkB,EAAEC,KAAK,EAA0B,EAAA;AAC/D,IAAA,MAAM,EAAEC,WAAW,EAAEC,YAAY,EAAE,GAAGC,qBAAAA,EAAAA;;;AAGtC,IAAA,qBAAOC,GAAA,CAACC,QAAAA,EAAAA;QAAOC,IAAAA,EAAK,QAAA;AAASC,QAAAA,QAAAA,EAAUN,eAAe,CAACC,YAAAA;QAAcM,WAAAA,EAAWP,WAAAA;AAAcD,QAAAA,QAAAA,EAAAA;;AAClG;;"}
@@ -0,0 +1,5 @@
1
+ import type { CommandInput } from './commandInputs';
2
+ export declare function ExplicitCommandField({ input }: {
3
+ input: CommandInput;
4
+ }): import("react").JSX.Element;
5
+ //# sourceMappingURL=ExplicitCommandField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExplicitCommandField.d.ts","sourceRoot":"","sources":["../../../forms/ExplicitCommandField.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AA4EpD,wBAAgB,oBAAoB,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,YAAY,CAAA;CAAE,+BAGtE"}