@cratis/components 4.25.2 → 4.26.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 (104) hide show
  1. package/compat-manifest.json +11 -11
  2. package/dist/esm/SchemaEditor/NameCell.d.ts +5 -1
  3. package/dist/esm/SchemaEditor/NameCell.d.ts.map +1 -1
  4. package/dist/esm/SchemaEditor/NameCell.js +2 -2
  5. package/dist/esm/SchemaEditor/NameCell.js.map +1 -1
  6. package/dist/esm/SchemaEditor/SchemaEditor.d.ts +63 -48
  7. package/dist/esm/SchemaEditor/SchemaEditor.d.ts.map +1 -1
  8. package/dist/esm/SchemaEditor/SchemaEditor.js +83 -25
  9. package/dist/esm/SchemaEditor/SchemaEditor.js.map +1 -1
  10. package/dist/esm/SchemaEditor/SchemaEditorLabels.d.ts +98 -0
  11. package/dist/esm/SchemaEditor/SchemaEditorLabels.d.ts.map +1 -0
  12. package/dist/esm/SchemaEditor/SchemaEditorLabels.js +4 -0
  13. package/dist/esm/SchemaEditor/SchemaEditorLabels.js.map +1 -0
  14. package/dist/esm/SchemaEditor/SchemaEditorLayout.d.ts +6 -0
  15. package/dist/esm/SchemaEditor/SchemaEditorLayout.d.ts.map +1 -0
  16. package/dist/esm/SchemaEditor/SchemaEditorLayout.js +4 -0
  17. package/dist/esm/SchemaEditor/SchemaEditorLayout.js.map +1 -0
  18. package/dist/esm/SchemaEditor/Tree/Property.d.ts +30 -0
  19. package/dist/esm/SchemaEditor/Tree/Property.d.ts.map +1 -0
  20. package/dist/esm/SchemaEditor/Tree/Property.js +4 -0
  21. package/dist/esm/SchemaEditor/Tree/Property.js.map +1 -0
  22. package/dist/esm/SchemaEditor/Tree/PropertyConcept.d.ts +15 -0
  23. package/dist/esm/SchemaEditor/Tree/PropertyConcept.d.ts.map +1 -0
  24. package/dist/esm/SchemaEditor/Tree/PropertyConcept.js +4 -0
  25. package/dist/esm/SchemaEditor/Tree/PropertyConcept.js.map +1 -0
  26. package/dist/esm/SchemaEditor/Tree/PropertyConceptsContext.d.ts +22 -0
  27. package/dist/esm/SchemaEditor/Tree/PropertyConceptsContext.d.ts.map +1 -0
  28. package/dist/esm/SchemaEditor/Tree/PropertyConceptsContext.js +10 -0
  29. package/dist/esm/SchemaEditor/Tree/PropertyConceptsContext.js.map +1 -0
  30. package/dist/esm/SchemaEditor/Tree/PropertyType.d.ts +22 -0
  31. package/dist/esm/SchemaEditor/Tree/PropertyType.d.ts.map +1 -0
  32. package/dist/esm/SchemaEditor/Tree/PropertyType.js +15 -0
  33. package/dist/esm/SchemaEditor/Tree/PropertyType.js.map +1 -0
  34. package/dist/esm/SchemaEditor/Tree/PropertyTypeBadge.d.ts +20 -0
  35. package/dist/esm/SchemaEditor/Tree/PropertyTypeBadge.d.ts.map +1 -0
  36. package/dist/esm/SchemaEditor/Tree/PropertyTypeBadge.js +11 -0
  37. package/dist/esm/SchemaEditor/Tree/PropertyTypeBadge.js.map +1 -0
  38. package/dist/esm/SchemaEditor/Tree/PropertyTypeMenu.d.ts +28 -0
  39. package/dist/esm/SchemaEditor/Tree/PropertyTypeMenu.d.ts.map +1 -0
  40. package/dist/esm/SchemaEditor/Tree/PropertyTypeMenu.js +37 -0
  41. package/dist/esm/SchemaEditor/Tree/PropertyTypeMenu.js.map +1 -0
  42. package/dist/esm/SchemaEditor/Tree/SchemaEditorContext.d.ts +42 -0
  43. package/dist/esm/SchemaEditor/Tree/SchemaEditorContext.d.ts.map +1 -0
  44. package/dist/esm/SchemaEditor/Tree/SchemaEditorContext.js +12 -0
  45. package/dist/esm/SchemaEditor/Tree/SchemaEditorContext.js.map +1 -0
  46. package/dist/esm/SchemaEditor/Tree/SchemaEditorParts.d.ts +60 -0
  47. package/dist/esm/SchemaEditor/Tree/SchemaEditorParts.d.ts.map +1 -0
  48. package/dist/esm/SchemaEditor/Tree/SchemaEditorParts.js +4 -0
  49. package/dist/esm/SchemaEditor/Tree/SchemaEditorParts.js.map +1 -0
  50. package/dist/esm/SchemaEditor/Tree/SchemaPropertyContext.d.ts +13 -0
  51. package/dist/esm/SchemaEditor/Tree/SchemaPropertyContext.d.ts.map +1 -0
  52. package/dist/esm/SchemaEditor/Tree/SchemaPropertyContext.js +4 -0
  53. package/dist/esm/SchemaEditor/Tree/SchemaPropertyContext.js.map +1 -0
  54. package/dist/esm/SchemaEditor/Tree/SchemaPropertyRow.d.ts +13 -0
  55. package/dist/esm/SchemaEditor/Tree/SchemaPropertyRow.d.ts.map +1 -0
  56. package/dist/esm/SchemaEditor/Tree/SchemaPropertyRow.js +107 -0
  57. package/dist/esm/SchemaEditor/Tree/SchemaPropertyRow.js.map +1 -0
  58. package/dist/esm/SchemaEditor/Tree/SchemaPropertyRowState.d.ts +16 -0
  59. package/dist/esm/SchemaEditor/Tree/SchemaPropertyRowState.d.ts.map +1 -0
  60. package/dist/esm/SchemaEditor/Tree/SchemaPropertyRowState.js +4 -0
  61. package/dist/esm/SchemaEditor/Tree/SchemaPropertyRowState.js.map +1 -0
  62. package/dist/esm/SchemaEditor/Tree/TreeSchemaEditor.d.ts +116 -0
  63. package/dist/esm/SchemaEditor/Tree/TreeSchemaEditor.d.ts.map +1 -0
  64. package/dist/esm/SchemaEditor/Tree/TreeSchemaEditor.js +96 -0
  65. package/dist/esm/SchemaEditor/Tree/TreeSchemaEditor.js.map +1 -0
  66. package/dist/esm/SchemaEditor/Tree/propertyNaming.d.ts +35 -0
  67. package/dist/esm/SchemaEditor/Tree/propertyNaming.d.ts.map +1 -0
  68. package/dist/esm/SchemaEditor/Tree/propertyNaming.js +34 -0
  69. package/dist/esm/SchemaEditor/Tree/propertyNaming.js.map +1 -0
  70. package/dist/esm/SchemaEditor/Tree/propertyTree.d.ts +30 -0
  71. package/dist/esm/SchemaEditor/Tree/propertyTree.d.ts.map +1 -0
  72. package/dist/esm/SchemaEditor/Tree/propertyTree.js +36 -0
  73. package/dist/esm/SchemaEditor/Tree/propertyTree.js.map +1 -0
  74. package/dist/esm/SchemaEditor/Tree/propertyTypeDisplay.d.ts +22 -0
  75. package/dist/esm/SchemaEditor/Tree/propertyTypeDisplay.d.ts.map +1 -0
  76. package/dist/esm/SchemaEditor/Tree/propertyTypeDisplay.js +45 -0
  77. package/dist/esm/SchemaEditor/Tree/propertyTypeDisplay.js.map +1 -0
  78. package/dist/esm/SchemaEditor/Tree/schemaConversion.d.ts +95 -0
  79. package/dist/esm/SchemaEditor/Tree/schemaConversion.d.ts.map +1 -0
  80. package/dist/esm/SchemaEditor/Tree/schemaConversion.js +171 -0
  81. package/dist/esm/SchemaEditor/Tree/schemaConversion.js.map +1 -0
  82. package/dist/esm/SchemaEditor/TypeCell.d.ts +3 -1
  83. package/dist/esm/SchemaEditor/TypeCell.d.ts.map +1 -1
  84. package/dist/esm/SchemaEditor/TypeCell.js +2 -2
  85. package/dist/esm/SchemaEditor/TypeCell.js.map +1 -1
  86. package/dist/esm/SchemaEditor/defaultSchemaEditorLabels.d.ts +9 -0
  87. package/dist/esm/SchemaEditor/defaultSchemaEditorLabels.d.ts.map +1 -0
  88. package/dist/esm/SchemaEditor/defaultSchemaEditorLabels.js +51 -0
  89. package/dist/esm/SchemaEditor/defaultSchemaEditorLabels.js.map +1 -0
  90. package/dist/esm/SchemaEditor/index.d.ts +12 -0
  91. package/dist/esm/SchemaEditor/index.d.ts.map +1 -1
  92. package/dist/esm/SchemaEditor/index.js +7 -1
  93. package/dist/esm/SchemaEditor/index.js.map +1 -1
  94. package/dist/esm/SchemaEditor/resolveSchemaEditorLabels.d.ts +4 -0
  95. package/dist/esm/SchemaEditor/resolveSchemaEditorLabels.d.ts.map +1 -0
  96. package/dist/esm/SchemaEditor/resolveSchemaEditorLabels.js +13 -0
  97. package/dist/esm/SchemaEditor/resolveSchemaEditorLabels.js.map +1 -0
  98. package/dist/esm/styles.SchemaEditor.css +346 -0
  99. package/dist/esm/styles.css +346 -0
  100. package/dist/esm/types/parts.d.ts +25 -0
  101. package/dist/esm/types/parts.d.ts.map +1 -1
  102. package/dist/esm/types/parts.js +25 -0
  103. package/dist/esm/types/parts.js.map +1 -1
  104. package/package.json +2 -1
@@ -68,7 +68,7 @@
68
68
  {
69
69
  "name": "@cratis/components",
70
70
  "role": "core",
71
- "version": "4.25.2",
71
+ "version": "4.26.0",
72
72
  "releaseMajorRange": ">=4 <5",
73
73
  "independentRelease": false,
74
74
  "private": false,
@@ -92,7 +92,7 @@
92
92
  {
93
93
  "name": "@cratis/eslint-plugin-components",
94
94
  "role": "eslint",
95
- "version": "4.25.2",
95
+ "version": "4.26.0",
96
96
  "releaseMajorRange": ">=4 <5",
97
97
  "independentRelease": false,
98
98
  "private": false,
@@ -105,7 +105,7 @@
105
105
  {
106
106
  "name": "@cratis/components.migrator",
107
107
  "role": "migrator",
108
- "version": "4.25.2",
108
+ "version": "4.26.0",
109
109
  "releaseMajorRange": ">=4 <5",
110
110
  "independentRelease": false,
111
111
  "private": false,
@@ -116,13 +116,13 @@
116
116
  {
117
117
  "name": "@cratis/components.conformance",
118
118
  "role": "conformance",
119
- "version": "4.25.2",
119
+ "version": "4.26.0",
120
120
  "releaseMajorRange": ">=4 <5",
121
121
  "independentRelease": false,
122
122
  "private": false,
123
123
  "packageAccess": "public",
124
124
  "peerDependencies": {
125
- "@cratis/components": "4.25.2",
125
+ "@cratis/components": "4.26.0",
126
126
  "react": "^19.0.0",
127
127
  "react-dom": "^19.0.0"
128
128
  },
@@ -132,13 +132,13 @@
132
132
  {
133
133
  "name": "@cratis/components.mui",
134
134
  "role": "renderer-adapter",
135
- "version": "4.25.2",
135
+ "version": "4.26.0",
136
136
  "releaseMajorRange": ">=4 <5",
137
137
  "independentRelease": false,
138
138
  "private": false,
139
139
  "packageAccess": "public",
140
140
  "peerDependencies": {
141
- "@cratis/components": "4.25.2",
141
+ "@cratis/components": "4.26.0",
142
142
  "@emotion/react": ">=11.5 <12",
143
143
  "@emotion/styled": ">=11.11 <12",
144
144
  "@mui/material": ">=9 <10",
@@ -188,13 +188,13 @@
188
188
  {
189
189
  "name": "@cratis/components.primereact",
190
190
  "role": "renderer-adapter",
191
- "version": "4.25.2",
191
+ "version": "4.26.0",
192
192
  "releaseMajorRange": ">=4 <5",
193
193
  "independentRelease": false,
194
194
  "private": false,
195
195
  "packageAccess": "public",
196
196
  "peerDependencies": {
197
- "@cratis/components": "4.25.2",
197
+ "@cratis/components": "4.26.0",
198
198
  "@primereact/core": ">=11 <12",
199
199
  "@primereact/ui": ">=11 <12",
200
200
  "@primeuix/themes": ">=3 <4",
@@ -256,13 +256,13 @@
256
256
  {
257
257
  "name": "@cratis/components.primereact10",
258
258
  "role": "renderer-adapter",
259
- "version": "4.25.2",
259
+ "version": "4.26.0",
260
260
  "releaseMajorRange": ">=4 <5",
261
261
  "independentRelease": false,
262
262
  "private": false,
263
263
  "packageAccess": "public",
264
264
  "peerDependencies": {
265
- "@cratis/components": "4.25.2",
265
+ "@cratis/components": "4.26.0",
266
266
  "primereact": ">=10.9.9 <11",
267
267
  "react": "^19.0.0",
268
268
  "react-dom": "^19.0.0"
@@ -6,6 +6,10 @@ export interface NameCellProps {
6
6
  validationError?: string;
7
7
  /** Accessible name for the property-name input. */
8
8
  propertyNameLabel: string;
9
+ /** When true the name cannot be edited (a protected property). */
10
+ isLocked?: boolean;
11
+ /** Tooltip explaining why the name is locked. */
12
+ lockedReason?: string;
9
13
  }
10
- export declare const NameCell: ({ rowData, isEditMode, onUpdate, validationError, propertyNameLabel, }: NameCellProps) => import("react").JSX.Element;
14
+ export declare const NameCell: ({ rowData, isEditMode, onUpdate, validationError, propertyNameLabel, isLocked, lockedReason, }: NameCellProps) => import("react").JSX.Element;
11
15
  //# sourceMappingURL=NameCell.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NameCell.d.ts","sourceRoot":"","sources":["../../../SchemaEditor/NameCell.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAqB,CAAC;AAEzD,MAAM,WAAW,aAAa;IAC1B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,kBAAkB,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACrF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,iBAAiB,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,QAAQ,2EAMlB,aAAa,gCAwDf,CAAC"}
1
+ {"version":3,"file":"NameCell.d.ts","sourceRoot":"","sources":["../../../SchemaEditor/NameCell.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAqB,CAAC;AAEzD,MAAM,WAAW,aAAa;IAC1B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,kBAAkB,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACrF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,QAAQ,mGAQlB,aAAa,gCAyDf,CAAC"}
@@ -2,7 +2,7 @@ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import * as faIcons from 'react-icons/fa6';
3
3
  import { Tooltip } from '../Common/Tooltip.js';
4
4
 
5
- const NameCell = ({ rowData, isEditMode, onUpdate, validationError, propertyNameLabel, }) => {
5
+ const NameCell = ({ rowData, isEditMode, onUpdate, validationError, propertyNameLabel, isLocked = false, lockedReason, }) => {
6
6
  if (!isEditMode) {
7
7
  const isNavigable = rowData.type === 'object' ||
8
8
  (rowData.type === 'array' && rowData.items?.type === 'object');
@@ -20,7 +20,7 @@ const NameCell = ({ rowData, isEditMode, onUpdate, validationError, propertyName
20
20
  fontSize: '0.875rem',
21
21
  } }) }) }))] }));
22
22
  }
23
- return (jsx(Tooltip, { content: validationError, position: 'top', className: 'cratis:w-full', children: jsx("input", { "aria-label": propertyNameLabel, value: rowData.name || '', onChange: (event) => onUpdate(rowData.name || '', 'name', event.target.value), className: 'cratis-field-input cratis:w-full', "aria-invalid": Boolean(validationError) || undefined, "data-invalid": Boolean(validationError) || undefined }) }));
23
+ return (jsx(Tooltip, { content: isLocked ? lockedReason : validationError, position: 'top', className: 'cratis:w-full', children: jsx("input", { "aria-label": propertyNameLabel, value: rowData.name || '', onChange: (event) => onUpdate(rowData.name || '', 'name', event.target.value), className: 'cratis-field-input cratis:w-full', disabled: isLocked || undefined, "aria-invalid": Boolean(validationError) || undefined, "data-invalid": Boolean(validationError) || undefined }) }));
24
24
  };
25
25
 
26
26
  export { NameCell };
@@ -1 +1 @@
1
- {"version":3,"file":"NameCell.js","sources":["../../../SchemaEditor/NameCell.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 * as faIcons from 'react-icons/fa6';\nimport { Tooltip } from '../Common/Tooltip';\nimport { JsonSchemaProperty } from '../types/JsonSchema';\n\nexport interface NameCellProps {\n rowData: JsonSchemaProperty;\n isEditMode: boolean;\n onUpdate: (oldName: string, field: keyof JsonSchemaProperty, value: unknown) => void;\n validationError?: string;\n /** Accessible name for the property-name input. */\n propertyNameLabel: string;\n}\n\nexport const NameCell = ({\n rowData,\n isEditMode,\n onUpdate,\n validationError,\n propertyNameLabel,\n}: NameCellProps) => {\n if (!isEditMode) {\n const isNavigable =\n rowData.type === 'object' ||\n (rowData.type === 'array' && rowData.items?.type === 'object');\n const navigationTooltipText =\n rowData.type === 'object'\n ? 'Click to navigate to object properties'\n : 'Click to navigate to item definition';\n\n return (\n <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>\n <span title={isNavigable ? navigationTooltipText : undefined}>\n {rowData.name}\n </span>\n {rowData.description && (\n <Tooltip content={rowData.description} position='right'>\n <button\n type='button'\n aria-label='Property description'\n style={{\n display: 'inline-flex',\n padding: 0,\n border: 0,\n background: 'transparent',\n color: 'inherit',\n }}\n >\n <faIcons.FaCircleInfo\n aria-hidden='true'\n style={{\n color: 'var(--cratis-text-color-secondary)',\n fontSize: '0.875rem',\n }}\n />\n </button>\n </Tooltip>\n )}\n </div>\n );\n }\n\n return (\n <Tooltip content={validationError} position='top' className='cratis:w-full'>\n <input\n aria-label={propertyNameLabel}\n value={rowData.name || ''}\n onChange={(event) =>\n onUpdate(rowData.name || '', 'name', event.target.value)\n }\n className='cratis-field-input cratis:w-full'\n aria-invalid={Boolean(validationError) || undefined}\n data-invalid={Boolean(validationError) || undefined}\n />\n </Tooltip>\n );\n};\n"],"names":["_jsxs","_jsx"],"mappings":";;;;AAgBO,MAAM,QAAQ,GAAG,CAAC,EACrB,OAAO,EACP,UAAU,EACV,QAAQ,EACR,eAAe,EACf,iBAAiB,GACL,KAAI;IAChB,IAAI,CAAC,UAAU,EAAE;AACb,QAAA,MAAM,WAAW,GACb,OAAO,CAAC,IAAI,KAAK,QAAQ;AACzB,aAAC,OAAO,CAAC,IAAI,KAAK,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,IAAI,KAAK,QAAQ,CAAC;AAClE,QAAA,MAAM,qBAAqB,GACvB,OAAO,CAAC,IAAI,KAAK;AACb,cAAE;cACA,sCAAsC;AAEhD,QAAA,QACIA,IAAA,CAAA,KAAA,EAAA,EAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAA,QAAA,EAAA,CAChEC,GAAA,CAAA,MAAA,EAAA,EAAM,KAAK,EAAE,WAAW,GAAG,qBAAqB,GAAG,SAAS,EAAA,QAAA,EACvD,OAAO,CAAC,IAAI,EAAA,CACV,EACN,OAAO,CAAC,WAAW,KAChBA,GAAA,CAAC,OAAO,EAAA,EAAC,OAAO,EAAE,OAAO,CAAC,WAAW,EAAE,QAAQ,EAAC,OAAO,EAAA,QAAA,EACnDA,GAAA,CAAA,QAAA,EAAA,EACI,IAAI,EAAC,QAAQ,EAAA,YAAA,EACF,sBAAsB,EACjC,KAAK,EAAE;AACH,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,OAAO,EAAE,CAAC;AACV,4BAAA,MAAM,EAAE,CAAC;AACT,4BAAA,UAAU,EAAE,aAAa;AACzB,4BAAA,KAAK,EAAE,SAAS;yBACnB,EAAA,QAAA,EAEDA,GAAA,CAAC,OAAO,CAAC,YAAY,mBACL,MAAM,EAClB,KAAK,EAAE;AACH,gCAAA,KAAK,EAAE,oCAAoC;AAC3C,gCAAA,QAAQ,EAAE,UAAU;AACvB,6BAAA,EAAA,CACH,EAAA,CACG,EAAA,CACH,CACb,CAAA,EAAA,CACC;IAEd;AAEA,IAAA,QACIA,GAAA,CAAC,OAAO,EAAA,EAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAC,KAAK,EAAC,SAAS,EAAC,eAAe,EAAA,QAAA,EACvEA,GAAA,CAAA,OAAA,EAAA,EAAA,YAAA,EACgB,iBAAiB,EAC7B,KAAK,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE,EACzB,QAAQ,EAAE,CAAC,KAAK,KACZ,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAE5D,SAAS,EAAC,kCAAkC,EAAA,cAAA,EAC9B,OAAO,CAAC,eAAe,CAAC,IAAI,SAAS,EAAA,cAAA,EACrC,OAAO,CAAC,eAAe,CAAC,IAAI,SAAS,EAAA,CACrD,EAAA,CACI;AAElB;;"}
1
+ {"version":3,"file":"NameCell.js","sources":["../../../SchemaEditor/NameCell.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 * as faIcons from 'react-icons/fa6';\nimport { Tooltip } from '../Common/Tooltip';\nimport { JsonSchemaProperty } from '../types/JsonSchema';\n\nexport interface NameCellProps {\n rowData: JsonSchemaProperty;\n isEditMode: boolean;\n onUpdate: (oldName: string, field: keyof JsonSchemaProperty, value: unknown) => void;\n validationError?: string;\n /** Accessible name for the property-name input. */\n propertyNameLabel: string;\n /** When true the name cannot be edited (a protected property). */\n isLocked?: boolean;\n /** Tooltip explaining why the name is locked. */\n lockedReason?: string;\n}\n\nexport const NameCell = ({\n rowData,\n isEditMode,\n onUpdate,\n validationError,\n propertyNameLabel,\n isLocked = false,\n lockedReason,\n}: NameCellProps) => {\n if (!isEditMode) {\n const isNavigable =\n rowData.type === 'object' ||\n (rowData.type === 'array' && rowData.items?.type === 'object');\n const navigationTooltipText =\n rowData.type === 'object'\n ? 'Click to navigate to object properties'\n : 'Click to navigate to item definition';\n\n return (\n <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>\n <span title={isNavigable ? navigationTooltipText : undefined}>\n {rowData.name}\n </span>\n {rowData.description && (\n <Tooltip content={rowData.description} position='right'>\n <button\n type='button'\n aria-label='Property description'\n style={{\n display: 'inline-flex',\n padding: 0,\n border: 0,\n background: 'transparent',\n color: 'inherit',\n }}\n >\n <faIcons.FaCircleInfo\n aria-hidden='true'\n style={{\n color: 'var(--cratis-text-color-secondary)',\n fontSize: '0.875rem',\n }}\n />\n </button>\n </Tooltip>\n )}\n </div>\n );\n }\n\n return (\n <Tooltip content={isLocked ? lockedReason : validationError} position='top' className='cratis:w-full'>\n <input\n aria-label={propertyNameLabel}\n value={rowData.name || ''}\n onChange={(event) =>\n onUpdate(rowData.name || '', 'name', event.target.value)\n }\n className='cratis-field-input cratis:w-full'\n disabled={isLocked || undefined}\n aria-invalid={Boolean(validationError) || undefined}\n data-invalid={Boolean(validationError) || undefined}\n />\n </Tooltip>\n );\n};\n"],"names":["_jsxs","_jsx"],"mappings":";;;;MAoBa,QAAQ,GAAG,CAAC,EACrB,OAAO,EACP,UAAU,EACV,QAAQ,EACR,eAAe,EACf,iBAAiB,EACjB,QAAQ,GAAG,KAAK,EAChB,YAAY,GACA,KAAI;IAChB,IAAI,CAAC,UAAU,EAAE;AACb,QAAA,MAAM,WAAW,GACb,OAAO,CAAC,IAAI,KAAK,QAAQ;AACzB,aAAC,OAAO,CAAC,IAAI,KAAK,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,IAAI,KAAK,QAAQ,CAAC;AAClE,QAAA,MAAM,qBAAqB,GACvB,OAAO,CAAC,IAAI,KAAK;AACb,cAAE;cACA,sCAAsC;AAEhD,QAAA,QACIA,IAAA,CAAA,KAAA,EAAA,EAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAA,QAAA,EAAA,CAChEC,GAAA,CAAA,MAAA,EAAA,EAAM,KAAK,EAAE,WAAW,GAAG,qBAAqB,GAAG,SAAS,EAAA,QAAA,EACvD,OAAO,CAAC,IAAI,EAAA,CACV,EACN,OAAO,CAAC,WAAW,KAChBA,GAAA,CAAC,OAAO,EAAA,EAAC,OAAO,EAAE,OAAO,CAAC,WAAW,EAAE,QAAQ,EAAC,OAAO,EAAA,QAAA,EACnDA,GAAA,CAAA,QAAA,EAAA,EACI,IAAI,EAAC,QAAQ,EAAA,YAAA,EACF,sBAAsB,EACjC,KAAK,EAAE;AACH,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,OAAO,EAAE,CAAC;AACV,4BAAA,MAAM,EAAE,CAAC;AACT,4BAAA,UAAU,EAAE,aAAa;AACzB,4BAAA,KAAK,EAAE,SAAS;yBACnB,EAAA,QAAA,EAEDA,GAAA,CAAC,OAAO,CAAC,YAAY,mBACL,MAAM,EAClB,KAAK,EAAE;AACH,gCAAA,KAAK,EAAE,oCAAoC;AAC3C,gCAAA,QAAQ,EAAE,UAAU;AACvB,6BAAA,EAAA,CACH,EAAA,CACG,EAAA,CACH,CACb,CAAA,EAAA,CACC;IAEd;AAEA,IAAA,QACIA,GAAA,CAAC,OAAO,IAAC,OAAO,EAAE,QAAQ,GAAG,YAAY,GAAG,eAAe,EAAE,QAAQ,EAAC,KAAK,EAAC,SAAS,EAAC,eAAe,EAAA,QAAA,EACjGA,GAAA,CAAA,OAAA,EAAA,EAAA,YAAA,EACgB,iBAAiB,EAC7B,KAAK,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE,EACzB,QAAQ,EAAE,CAAC,KAAK,KACZ,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAE5D,SAAS,EAAC,kCAAkC,EAC5C,QAAQ,EAAE,QAAQ,IAAI,SAAS,EAAA,cAAA,EACjB,OAAO,CAAC,eAAe,CAAC,IAAI,SAAS,kBACrC,OAAO,CAAC,eAAe,CAAC,IAAI,SAAS,EAAA,CACrD,EAAA,CACI;AAElB;;"}
@@ -1,49 +1,31 @@
1
+ import type { ReactNode } from 'react';
1
2
  import type { ChangeHandler } from '../types/ChangeHandler.js';
2
3
  import type { JsonSchema } from '../types/JsonSchema.js';
3
4
  import { type TypeFormat } from '../types/TypeFormat.js';
4
- /**
5
- * User-facing strings for {@link SchemaEditor}. Every field is optional; pass a
6
- * partial `labels` to override any of them (for localization). Omitted fields
7
- * fall back to {@link defaultSchemaEditorLabels} (English).
8
- */
9
- export interface SchemaEditorLabels {
10
- /** Menu action that enters edit mode. */
11
- edit: string;
12
- /** Menu action that saves changes. */
13
- save: string;
14
- /** Menu action that cancels editing. */
15
- cancel: string;
16
- /** Menu action that adds a property. */
17
- addProperty: string;
18
- /** Accessible name for the action menubar. */
19
- actions: string;
20
- /** Accessible name and tooltip for the back button. */
21
- navigateBack: string;
22
- /** Shown when the schema has no properties. */
23
- emptyMessage: string;
24
- /** Accessible name for the "drill into array item definition" button. */
25
- navigateToItemDefinition: string;
26
- /** Accessible name for the "drill into object properties" button. */
27
- navigateToProperties: string;
28
- /** Accessible name for a property-name input. */
29
- propertyName: string;
30
- /** Accessible name for a property-type selector. */
31
- propertyType: string;
32
- /** Accessible name for an array item-type selector. */
33
- arrayItemType: string;
34
- /** Accessible name for the "remove property" button. */
35
- deleteProperty: string;
36
- /** Validation message shown when the schema cannot be represented as valid JSON. */
37
- invalidJson: string;
38
- }
39
- /** English defaults for {@link SchemaEditorLabels}. */
40
- export declare const defaultSchemaEditorLabels: SchemaEditorLabels;
5
+ import { defaultSchemaEditorLabels } from './defaultSchemaEditorLabels.js';
6
+ import type { SchemaEditorLabels } from './SchemaEditorLabels.js';
7
+ import type { SchemaEditorLayout } from './SchemaEditorLayout.js';
8
+ import type { Property } from './Tree/Property.js';
9
+ import { type TreeSchemaEditorProps } from './Tree/TreeSchemaEditor.js';
10
+ export { defaultSchemaEditorLabels };
11
+ export type { SchemaEditorLabels };
12
+ /** Properties of the tree layout the table layout has no counterpart for. They are ignored when `layout` is `'table'`. */
13
+ type TreeOnlyProps = Omit<TreeSchemaEditorProps, 'schema' | 'onChange' | 'labels' | 'className' | 'allowKeyProperty' | 'allowRequired' | 'readOnly' | 'isPropertyProtected' | 'validatePropertyName' | 'onPropertyRemoved' | 'onPropertyRenamed' | 'header' | 'footer'>;
41
14
  /**
42
15
  * Props for {@link SchemaEditor}.
43
16
  */
44
- export interface SchemaEditorProps {
45
- /** The JSON Schema being viewed or edited. */
46
- schema: JsonSchema;
17
+ export interface SchemaEditorProps extends TreeOnlyProps {
18
+ /**
19
+ * Which editor to render. `'table'` (the default) is the breadcrumb-navigated table with an Edit, Save and
20
+ * Cancel workflow; `'tree'` is the inline tree editor that applies every edit live. See the layout notes in
21
+ * the documentation for the props each layout honors.
22
+ */
23
+ layout?: SchemaEditorLayout;
24
+ /**
25
+ * The JSON Schema being viewed or edited. Required unless the tree layout is controlled through
26
+ * `properties`.
27
+ */
28
+ schema?: JsonSchema;
47
29
  /** Optional event-type label displayed in the editor header. */
48
30
  eventTypeName?: string;
49
31
  /** When false, the Edit action remains visible but cannot enter edit mode; defaults to `true`. */
@@ -79,18 +61,51 @@ export interface SchemaEditorProps {
79
61
  className?: string;
80
62
  /** Override any user-facing string (for localization). See {@link SchemaEditorLabels}. */
81
63
  labels?: Partial<SchemaEditorLabels>;
64
+ /**
65
+ * Offers the key toggle (`x-key`, at most one property per object). In the table layout this adds a Key
66
+ * column, editable in edit mode; a function enables the column for every row. In the tree layout it is
67
+ * offered on every property, or per property when a function is given.
68
+ */
69
+ allowKeyProperty?: TreeSchemaEditorProps['allowKeyProperty'];
70
+ /**
71
+ * Offers the toggle for whether a property must be present (the `required` list). In the table layout this
72
+ * adds a Required column, editable in edit mode.
73
+ */
74
+ allowRequired?: boolean;
75
+ /** Offers no edits at all. Tree layout only: the table layout is read-only until Edit is chosen, controlled by `canEdit`. */
76
+ readOnly?: boolean;
77
+ /** Decides which properties can be neither renamed nor removed. By default none. Both layouts. */
78
+ isPropertyProtected?: (property: Property) => boolean;
79
+ /**
80
+ * Extra check of a new name, after the editor has rejected blank, reserved and duplicate names. Return the
81
+ * message to show, or `undefined` to accept the name. Both layouts.
82
+ */
83
+ validatePropertyName?: (name: string, property: Property, siblings: Property[]) => string | undefined;
84
+ /** Called after a property was removed, with the property and everything nested under it. Both layouts. */
85
+ onPropertyRemoved?: (property: Property) => void;
86
+ /** Called after a property was renamed, with the renamed property and the name it had. Both layouts. */
87
+ onPropertyRenamed?: (property: Property, previousName: string) => void;
88
+ /** Content above the editor, for example the title of the schema. Both layouts. */
89
+ header?: ReactNode;
90
+ /** Content below the properties, for example further actions. Both layouts. */
91
+ footer?: ReactNode;
82
92
  }
83
93
  /**
84
- * A breadcrumb-navigated editor for JSON Schemas. Lets users browse nested
85
- * `object` and `array` property definitions, add or remove properties, change
86
- * types and formats, and validate naming rules in place. Designed to drive
87
- * UIs around event payload schemas and similar structural documents.
94
+ * Edits the properties of a JSON Schema. By default (`layout='table'`) it is a breadcrumb-navigated table: it
95
+ * lets users browse nested `object` and `array` property definitions, add or remove properties, change types and
96
+ * formats, and validate naming rules in place, behind an Edit, Save and Cancel workflow. With `layout='tree'` it
97
+ * is an inline tree that shows nested properties in place and applies every edit live. Designed to drive UIs
98
+ * around event payload schemas and similar structural documents.
99
+ *
100
+ * Both layouts accept `allowRequired`, `allowKeyProperty`, `isPropertyProtected`, `validatePropertyName`,
101
+ * `onPropertyRenamed`, `onPropertyRemoved`, `header` and `footer`. The tree layout also takes concepts, controlled
102
+ * mode, per-row slots and selection; see the documentation for the exact split.
88
103
  *
89
- * The editor composes a Cratis data table, action toolbar, and form widgets
90
- * internally. Restyle it through semantic tokens, the editor root `className`,
91
- * and documented `data-cratis-part` values rather than a provider preset.
104
+ * The table layout composes a Cratis data table, action toolbar, and form widgets internally. Restyle it through
105
+ * semantic tokens, the editor root `className`, and documented `data-cratis-part` values rather than a provider
106
+ * preset.
92
107
  *
93
108
  * @param props - {@link SchemaEditorProps}.
94
109
  */
95
- export declare const SchemaEditor: ({ schema, eventTypeName, canEdit, canNotEditReason, onChange, onSave, onCancel, editMode, saveDisabled, cancelDisabled, typeFormats, className, labels, }: SchemaEditorProps) => import("react").JSX.Element;
110
+ export declare const SchemaEditor: (props: SchemaEditorProps) => import("react").JSX.Element;
96
111
  //# sourceMappingURL=SchemaEditor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SchemaEditor.d.ts","sourceRoot":"","sources":["../../../SchemaEditor/SchemaEditor.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAsB,MAAM,wBAAqB,CAAC;AAC1E,OAAO,EAAE,KAAK,UAAU,EAAwB,MAAM,wBAAqB,CAAC;AAG5E;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IAC/B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,YAAY,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,wBAAwB,EAAE,MAAM,CAAC;IACjC,qEAAqE;IACrE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iDAAiD;IACjD,YAAY,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,aAAa,EAAE,MAAM,CAAC;IACtB,wDAAwD;IACxD,cAAc,EAAE,MAAM,CAAC;IACvB,oFAAoF;IACpF,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,uDAAuD;AACvD,eAAO,MAAM,yBAAyB,EAAE,kBAevC,CAAC;AAmEF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B,8CAA8C;IAC9C,MAAM,EAAE,UAAU,CAAC;IAEnB,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,kGAAkG;IAClG,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,yFAAyF;IACzF,QAAQ,CAAC,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAErC,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAEtB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,mEAAmE;IACnE,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,qEAAqE;IACrE,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;OAIG;IACH,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAE3B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,0FAA0F;IAC1F,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACxC;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,8JActB,iBAAiB,gCA2mBnB,CAAC"}
1
+ {"version":3,"file":"SchemaEditor.d.ts","sourceRoot":"","sources":["../../../SchemaEditor/SchemaEditor.tsx"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { useMemo, useState, useEffect, useCallback } from 'react';
3
3
  import { Button } from '../Common/Button.js';
4
+ import { Checkbox } from '../Common/Checkbox.js';
4
5
  import { DataTableCore } from '../DataTables/DataTableCore.js';
5
6
  import { Column } from '../DataTables/Column.js';
6
7
  import { ActionMenubar } from '../Common/ActionMenubar.js';
@@ -11,23 +12,11 @@ import { NameCell } from './NameCell.js';
11
12
  import { TypeCell } from './TypeCell.js';
12
13
  import { DEFAULT_TYPE_FORMATS } from '../types/TypeFormat.js';
13
14
  import { validatePropertyName, buildBreadcrumbItems } from './schemaHelpers.js';
15
+ import { defaultSchemaEditorLabels } from './defaultSchemaEditorLabels.js';
16
+ import { jsonSchemaToProperties, KEY_KEYWORD } from './Tree/schemaConversion.js';
17
+ import { TreeSchemaEditor } from './Tree/TreeSchemaEditor.js';
14
18
 
15
- const defaultSchemaEditorLabels = {
16
- edit: 'Edit',
17
- save: 'Save',
18
- cancel: 'Cancel',
19
- addProperty: 'Add Property',
20
- actions: 'Actions',
21
- navigateBack: 'Navigate back',
22
- emptyMessage: 'No properties defined',
23
- navigateToItemDefinition: 'Navigate to item definition',
24
- navigateToProperties: 'Navigate to object properties',
25
- propertyName: 'Property name',
26
- propertyType: 'Property type',
27
- arrayItemType: 'Array item type',
28
- deleteProperty: 'Delete property',
29
- invalidJson: 'The schema must contain valid JSON before it can be edited.',
30
- };
19
+ const emptySchema = {};
31
20
  const isPlainObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
32
21
  const isValidSchemaNode = (node) => {
33
22
  if (!isPlainObject(node)) {
@@ -68,14 +57,32 @@ const cloneSchema = (schema) => {
68
57
  return undefined;
69
58
  }
70
59
  };
60
+ const findSchemaAtPath = (root, path) => {
61
+ let target = root;
62
+ for (const segment of path) {
63
+ if (target.type === 'array' && segment === '$items') {
64
+ target = target.items || {};
65
+ }
66
+ else if (target.properties && target.properties[segment]) {
67
+ target = target.properties[segment];
68
+ }
69
+ else {
70
+ return undefined;
71
+ }
72
+ }
73
+ return target;
74
+ };
71
75
  const asJsonSchema = (property) => {
72
76
  return property;
73
77
  };
74
78
  const asJsonSchemaProperty = (schema) => {
75
79
  return schema;
76
80
  };
77
- const SchemaEditor = ({ schema, eventTypeName = '', canEdit = true, canNotEditReason, onChange, onSave, onCancel, editMode, saveDisabled = false, cancelDisabled = false, typeFormats = DEFAULT_TYPE_FORMATS, className, labels, }) => {
81
+ const TableSchemaEditor = ({ schema: suppliedSchema, eventTypeName = '', canEdit = true, canNotEditReason, onChange, onSave, onCancel, editMode, saveDisabled = false, cancelDisabled = false, typeFormats = DEFAULT_TYPE_FORMATS, className, labels, allowKeyProperty, allowRequired, isPropertyProtected, validatePropertyName: validateCustomPropertyName, onPropertyRemoved, onPropertyRenamed, header, footer, }) => {
82
+ const schema = suppliedSchema ?? emptySchema;
78
83
  const l = useMemo(() => ({ ...defaultSchemaEditorLabels, ...labels }), [labels]);
84
+ const showKey = allowKeyProperty !== undefined && allowKeyProperty !== false;
85
+ const showRequired = allowRequired === true;
79
86
  const [currentPath, setCurrentPath] = useState([]);
80
87
  const [properties, setProperties] = useState([]);
81
88
  const [initialParsedSchema] = useState(() => cloneSchema(schema));
@@ -89,17 +96,23 @@ const SchemaEditor = ({ schema, eventTypeName = '', canEdit = true, canNotEditRe
89
96
  setCurrentPath([]);
90
97
  }
91
98
  }, [isEditMode]);
92
- const validateAllProperties = useCallback((properties) => {
99
+ const validateAllProperties = useCallback((properties, level = []) => {
93
100
  const errors = {};
94
101
  properties.forEach((prop) => {
95
- const error = validatePropertyName(prop.name ?? '', prop.id, properties);
102
+ let error = validatePropertyName(prop.name ?? '', prop.id, properties);
103
+ if (!error && validateCustomPropertyName) {
104
+ const property = level.find((candidate) => candidate.name === prop.name);
105
+ if (property) {
106
+ error = validateCustomPropertyName(property.name, property, level);
107
+ }
108
+ }
96
109
  if (error) {
97
110
  errors[prop.id] = error;
98
111
  }
99
112
  });
100
113
  setValidationErrors(errors);
101
114
  return Object.keys(errors).length === 0;
102
- }, [validatePropertyName]);
115
+ }, [validatePropertyName, validateCustomPropertyName]);
103
116
  useEffect(() => {
104
117
  const parsedSchema = cloneSchema(schema);
105
118
  if (!parsedSchema) {
@@ -144,7 +157,7 @@ const SchemaEditor = ({ schema, eventTypeName = '', canEdit = true, canNotEditRe
144
157
  }
145
158
  setProperties(schemaProps);
146
159
  if (isEditMode) {
147
- validateAllProperties(schemaProps);
160
+ validateAllProperties(schemaProps, jsonSchemaToProperties(targetSchema));
148
161
  }
149
162
  };
150
163
  const updateSchemaAtPath = useCallback((path, updater) => {
@@ -198,7 +211,17 @@ const SchemaEditor = ({ schema, eventTypeName = '', canEdit = true, canNotEditRe
198
211
  return { ...schema, properties: newProps };
199
212
  });
200
213
  }, [currentPath, updateSchemaAtPath]);
214
+ const getLevelProperties = useCallback(() => jsonSchemaToProperties(findSchemaAtPath(currentSchema, currentPath)), [currentSchema, currentPath]);
215
+ const isProtected = useCallback((propertyName) => {
216
+ if (!isPropertyProtected)
217
+ return false;
218
+ const property = getLevelProperties().find((candidate) => candidate.name === propertyName);
219
+ return property !== undefined && isPropertyProtected(property);
220
+ }, [isPropertyProtected, getLevelProperties]);
201
221
  const removeProperty = useCallback((propertyName) => {
222
+ const removed = getLevelProperties().find((candidate) => candidate.name === propertyName);
223
+ if (removed && isPropertyProtected?.(removed))
224
+ return;
202
225
  updateSchemaAtPath(currentPath, (schema) => {
203
226
  const newProps = { ...(schema.properties || {}) };
204
227
  delete newProps[propertyName];
@@ -208,15 +231,44 @@ const SchemaEditor = ({ schema, eventTypeName = '', canEdit = true, canNotEditRe
208
231
  }
209
232
  return updated;
210
233
  });
234
+ if (removed)
235
+ onPropertyRemoved?.(removed);
236
+ }, [currentPath, updateSchemaAtPath, getLevelProperties, isPropertyProtected, onPropertyRemoved]);
237
+ const setRequired = useCallback((propertyName, isRequired) => {
238
+ updateSchemaAtPath(currentPath, (schema) => {
239
+ const others = (schema.required ?? []).filter((name) => name !== propertyName);
240
+ const required = isRequired ? [...others, propertyName] : others;
241
+ const updated = { ...schema };
242
+ if (required.length > 0) {
243
+ updated.required = required;
244
+ }
245
+ else {
246
+ delete updated.required;
247
+ }
248
+ return updated;
249
+ });
250
+ }, [currentPath, updateSchemaAtPath]);
251
+ const setKey = useCallback((propertyName) => {
252
+ updateSchemaAtPath(currentPath, (schema) => {
253
+ const newProps = {};
254
+ for (const [name, property] of Object.entries(schema.properties || {})) {
255
+ const { [KEY_KEYWORD]: previousKey, ...rest } = property;
256
+ const makeKey = name === propertyName && previousKey !== true;
257
+ newProps[name] = (makeKey ? { ...rest, [KEY_KEYWORD]: true } : rest);
258
+ }
259
+ return { ...schema, properties: newProps };
260
+ });
211
261
  }, [currentPath, updateSchemaAtPath]);
212
262
  const updateProperty = useCallback((oldName, field, value, additionalUpdates) => {
263
+ let renamed;
213
264
  updateSchemaAtPath(currentPath, (schema) => {
214
265
  const newProps = { ...(schema.properties || {}) };
215
266
  const prop = { ...(newProps[oldName] || {}) };
216
267
  let newRequired = schema.required;
217
268
  if (field === 'name') {
218
269
  const newName = value;
219
- if (newName !== oldName && !newProps[newName]) {
270
+ if (newName !== oldName && !newProps[newName] && !isProtected(oldName)) {
271
+ renamed = jsonSchemaToProperties({ properties: { [newName]: prop } })[0];
220
272
  newProps[newName] = prop;
221
273
  delete newProps[oldName];
222
274
  if (schema.required?.includes(oldName)) {
@@ -226,6 +278,7 @@ const SchemaEditor = ({ schema, eventTypeName = '', canEdit = true, canNotEditRe
226
278
  }
227
279
  else if (field === 'type') {
228
280
  prop.type = value;
281
+ delete prop['x-concept'];
229
282
  if (value === 'array') {
230
283
  prop.items = { type: 'string' };
231
284
  delete prop.format;
@@ -265,7 +318,9 @@ const SchemaEditor = ({ schema, eventTypeName = '', canEdit = true, canNotEditRe
265
318
  }
266
319
  return { ...schema, properties: newProps, required: newRequired };
267
320
  });
268
- }, [currentPath, updateSchemaAtPath]);
321
+ if (renamed)
322
+ onPropertyRenamed?.(renamed, oldName);
323
+ }, [currentPath, updateSchemaAtPath, isProtected, onPropertyRenamed]);
269
324
  const updateArrayItemType = useCallback((propertyName, itemType) => {
270
325
  updateSchemaAtPath(currentPath, (schema) => {
271
326
  const newProps = { ...(schema.properties || {}) };
@@ -417,7 +472,8 @@ const SchemaEditor = ({ schema, eventTypeName = '', canEdit = true, canNotEditRe
417
472
  const breadcrumbItems = getBreadcrumbItems();
418
473
  const isAtRoot = currentPath.length === 0;
419
474
  const currentDescription = getCurrentDescription();
420
- return (jsxs("div", { className: className ? `schema-editor ${className}` : 'schema-editor', style: { display: 'flex', flexDirection: 'column', height: '100%' }, children: [jsxs("div", { className: 'cratis:px-4 cratis:py-4', children: [jsx("div", { className: 'schema-editor-menubar', children: jsx(ActionMenubar, { "aria-label": l.actions, model: menuItems }) }), schemaJsonIsInvalid && (jsx(Message, { severity: 'error', text: l.invalidJson, className: 'cratis:mt-3' }))] }), jsxs("div", { className: 'cratis:px-4 cratis:py-2 cratis-schema-editor-bottom-border', children: [jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '0.5rem' }, children: [jsx(Tooltip, { content: l.navigateBack, position: 'top', children: jsx(Button, { variant: 'ghost', size: 'small', icon: jsx(faIcons.FaArrowLeft, {}), onClick: navigateBack, disabled: isAtRoot, "aria-label": l.navigateBack }) }), jsx("div", { style: {
475
+ const currentLevel = findSchemaAtPath(currentSchema, currentPath);
476
+ return (jsxs("div", { className: className ? `schema-editor ${className}` : 'schema-editor', style: { display: 'flex', flexDirection: 'column', height: '100%' }, children: [header, jsxs("div", { className: 'cratis:px-4 cratis:py-4', children: [jsx("div", { className: 'schema-editor-menubar', children: jsx(ActionMenubar, { "aria-label": l.actions, model: menuItems }) }), schemaJsonIsInvalid && (jsx(Message, { severity: 'error', text: l.invalidJson, className: 'cratis:mt-3' }))] }), jsxs("div", { className: 'cratis:px-4 cratis:py-2 cratis-schema-editor-bottom-border', children: [jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '0.5rem' }, children: [jsx(Tooltip, { content: l.navigateBack, position: 'top', children: jsx(Button, { variant: 'ghost', size: 'small', icon: jsx(faIcons.FaArrowLeft, {}), onClick: navigateBack, disabled: isAtRoot, "aria-label": l.navigateBack }) }), jsx("div", { style: {
421
477
  fontSize: '0.9rem',
422
478
  color: 'var(--cratis-text-color-secondary)',
423
479
  cursor: 'pointer',
@@ -470,8 +526,10 @@ const SchemaEditor = ({ schema, eventTypeName = '', canEdit = true, canNotEditRe
470
526
  borderTop: '1px solid var(--cratis-surface-border)',
471
527
  },
472
528
  },
473
- }, children: [jsx(Column, { field: 'name', header: 'Property', body: (rowData) => (jsx(NameCell, { rowData: rowData, isEditMode: isEditMode, onUpdate: updateProperty, validationError: validationErrors[rowData.id], propertyNameLabel: l.propertyName })), style: { width: '30%' } }), jsx(Column, { header: 'Type', body: (rowData) => (jsx(TypeCell, { rowData: rowData, isEditMode: isEditMode, typeFormats: typeFormats, onUpdateProperty: updateProperty, onUpdateArrayItemType: updateArrayItemType, onNavigateToProperty: navigateToProperty, onNavigateToArrayItems: navigateToArrayItems, onRemoveProperty: removeProperty, labels: l })), style: { width: '70%' } })] }, `${isEditMode}-${currentPath.join('/')}`) })] }));
529
+ }, children: [jsx(Column, { field: 'name', header: 'Property', body: (rowData) => (jsx(NameCell, { rowData: rowData, isEditMode: isEditMode, onUpdate: updateProperty, validationError: validationErrors[rowData.id], propertyNameLabel: l.propertyName, isLocked: isProtected(rowData.name ?? ''), lockedReason: l.protectedProperty })), style: { width: '30%' } }), showRequired && (jsx(Column, { header: l.requiredColumn, body: (rowData) => (jsx(Checkbox, { "aria-label": l.requiredProperty(rowData.name ?? ''), checked: Boolean(currentLevel?.required?.includes(rowData.name ?? '')), readOnly: !isEditMode, onChange: (checked) => setRequired(rowData.name ?? '', checked) })), style: { width: '6rem' } })), showKey && (jsx(Column, { header: l.keyColumn, body: (rowData) => (jsx(Checkbox, { "aria-label": l.keyProperty(rowData.name ?? ''), checked: isKeyProperty(currentLevel, rowData.name ?? ''), readOnly: !isEditMode, onChange: () => setKey(rowData.name ?? '') })), style: { width: '6rem' } })), jsx(Column, { header: 'Type', body: (rowData) => (jsx(TypeCell, { rowData: rowData, isEditMode: isEditMode, typeFormats: typeFormats, onUpdateProperty: updateProperty, onUpdateArrayItemType: updateArrayItemType, onNavigateToProperty: navigateToProperty, onNavigateToArrayItems: navigateToArrayItems, onRemoveProperty: removeProperty, canRemove: !isProtected(rowData.name ?? ''), labels: l })), style: { width: '70%' } })] }, `${isEditMode}-${currentPath.join('/')}`) }), footer] }));
474
530
  };
531
+ const isKeyProperty = (level, propertyName) => level?.properties?.[propertyName]?.[KEY_KEYWORD] === true;
532
+ const SchemaEditor = (props) => props.layout === 'tree' ? jsx(TreeSchemaEditor, { ...props }) : jsx(TableSchemaEditor, { ...props });
475
533
 
476
534
  export { SchemaEditor, defaultSchemaEditorLabels };
477
535
  //# sourceMappingURL=SchemaEditor.js.map