@siliconst/metaui 1.0.2 → 1.2.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 (183) hide show
  1. package/README.md +134 -123
  2. package/package.json +3 -2
  3. package/src/nz/co/siliconst/ui5/metaui/.library +7 -7
  4. package/src/nz/co/siliconst/ui5/metaui/controls/GeneratorHost-dbg.js +299 -163
  5. package/src/nz/co/siliconst/ui5/metaui/controls/GeneratorHost-dbg.js.map +1 -1
  6. package/src/nz/co/siliconst/ui5/metaui/controls/GeneratorHost.d.ts +54 -6
  7. package/src/nz/co/siliconst/ui5/metaui/controls/GeneratorHost.d.ts.map +1 -1
  8. package/src/nz/co/siliconst/ui5/metaui/controls/GeneratorHost.js +1 -1
  9. package/src/nz/co/siliconst/ui5/metaui/controls/GeneratorHost.js.map +1 -1
  10. package/src/nz/co/siliconst/ui5/metaui/controls/GeneratorHost.ts +292 -162
  11. package/src/nz/co/siliconst/ui5/metaui/core/ConditionEngine-dbg.js +51 -43
  12. package/src/nz/co/siliconst/ui5/metaui/core/ConditionEngine-dbg.js.map +1 -1
  13. package/src/nz/co/siliconst/ui5/metaui/core/ConditionEngine.d.ts +5 -0
  14. package/src/nz/co/siliconst/ui5/metaui/core/ConditionEngine.d.ts.map +1 -1
  15. package/src/nz/co/siliconst/ui5/metaui/core/ConditionEngine.js +1 -1
  16. package/src/nz/co/siliconst/ui5/metaui/core/ConditionEngine.js.map +1 -1
  17. package/src/nz/co/siliconst/ui5/metaui/core/ConditionEngine.ts +49 -40
  18. package/src/nz/co/siliconst/ui5/metaui/core/Engine-dbg.js +81 -58
  19. package/src/nz/co/siliconst/ui5/metaui/core/Engine-dbg.js.map +1 -1
  20. package/src/nz/co/siliconst/ui5/metaui/core/Engine.d.ts +5 -12
  21. package/src/nz/co/siliconst/ui5/metaui/core/Engine.d.ts.map +1 -1
  22. package/src/nz/co/siliconst/ui5/metaui/core/Engine.js +1 -1
  23. package/src/nz/co/siliconst/ui5/metaui/core/Engine.js.map +1 -1
  24. package/src/nz/co/siliconst/ui5/metaui/core/Engine.ts +82 -56
  25. package/src/nz/co/siliconst/ui5/metaui/core/EventBus-dbg.js +65 -50
  26. package/src/nz/co/siliconst/ui5/metaui/core/EventBus-dbg.js.map +1 -1
  27. package/src/nz/co/siliconst/ui5/metaui/core/EventBus.d.ts +9 -0
  28. package/src/nz/co/siliconst/ui5/metaui/core/EventBus.d.ts.map +1 -1
  29. package/src/nz/co/siliconst/ui5/metaui/core/EventBus.js +1 -1
  30. package/src/nz/co/siliconst/ui5/metaui/core/EventBus.js.map +1 -1
  31. package/src/nz/co/siliconst/ui5/metaui/core/EventBus.ts +60 -45
  32. package/src/nz/co/siliconst/ui5/metaui/core/PluginRegistry-dbg.js +72 -59
  33. package/src/nz/co/siliconst/ui5/metaui/core/PluginRegistry-dbg.js.map +1 -1
  34. package/src/nz/co/siliconst/ui5/metaui/core/PluginRegistry.d.ts +6 -4
  35. package/src/nz/co/siliconst/ui5/metaui/core/PluginRegistry.d.ts.map +1 -1
  36. package/src/nz/co/siliconst/ui5/metaui/core/PluginRegistry.js +1 -1
  37. package/src/nz/co/siliconst/ui5/metaui/core/PluginRegistry.js.map +1 -1
  38. package/src/nz/co/siliconst/ui5/metaui/core/PluginRegistry.ts +71 -56
  39. package/src/nz/co/siliconst/ui5/metaui/core/SchemaNormalizer-dbg.js +145 -36
  40. package/src/nz/co/siliconst/ui5/metaui/core/SchemaNormalizer-dbg.js.map +1 -1
  41. package/src/nz/co/siliconst/ui5/metaui/core/SchemaNormalizer.d.ts +13 -8
  42. package/src/nz/co/siliconst/ui5/metaui/core/SchemaNormalizer.d.ts.map +1 -1
  43. package/src/nz/co/siliconst/ui5/metaui/core/SchemaNormalizer.js +1 -1
  44. package/src/nz/co/siliconst/ui5/metaui/core/SchemaNormalizer.js.map +1 -1
  45. package/src/nz/co/siliconst/ui5/metaui/core/SchemaNormalizer.ts +157 -31
  46. package/src/nz/co/siliconst/ui5/metaui/core/StateManager-dbg.js +55 -55
  47. package/src/nz/co/siliconst/ui5/metaui/core/StateManager-dbg.js.map +1 -1
  48. package/src/nz/co/siliconst/ui5/metaui/core/StateManager.d.ts.map +1 -1
  49. package/src/nz/co/siliconst/ui5/metaui/core/StateManager.js.map +1 -1
  50. package/src/nz/co/siliconst/ui5/metaui/core/StateManager.ts +56 -56
  51. package/src/nz/co/siliconst/ui5/metaui/interfaces/IEventBus-dbg.js +1 -1
  52. package/src/nz/co/siliconst/ui5/metaui/interfaces/IEventBus-dbg.js.map +1 -1
  53. package/src/nz/co/siliconst/ui5/metaui/interfaces/IEventBus.d.ts.map +1 -1
  54. package/src/nz/co/siliconst/ui5/metaui/interfaces/IEventBus.ts +29 -29
  55. package/src/nz/co/siliconst/ui5/metaui/interfaces/ILayoutManager-dbg.js +1 -1
  56. package/src/nz/co/siliconst/ui5/metaui/interfaces/ILayoutManager-dbg.js.map +1 -1
  57. package/src/nz/co/siliconst/ui5/metaui/interfaces/ILayoutManager.d.ts +6 -12
  58. package/src/nz/co/siliconst/ui5/metaui/interfaces/ILayoutManager.d.ts.map +1 -1
  59. package/src/nz/co/siliconst/ui5/metaui/interfaces/ILayoutManager.ts +21 -26
  60. package/src/nz/co/siliconst/ui5/metaui/interfaces/IPlugin-dbg.js +1 -1
  61. package/src/nz/co/siliconst/ui5/metaui/interfaces/IPlugin-dbg.js.map +1 -1
  62. package/src/nz/co/siliconst/ui5/metaui/interfaces/IPlugin.d.ts +3 -20
  63. package/src/nz/co/siliconst/ui5/metaui/interfaces/IPlugin.d.ts.map +1 -1
  64. package/src/nz/co/siliconst/ui5/metaui/interfaces/IPlugin.ts +14 -33
  65. package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchema-dbg.js +1 -1
  66. package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchema-dbg.js.map +1 -1
  67. package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchema.d.ts +33 -43
  68. package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchema.d.ts.map +1 -1
  69. package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchema.ts +70 -70
  70. package/src/nz/co/siliconst/ui5/metaui/layouts/BaseLayout-dbg.js +23 -38
  71. package/src/nz/co/siliconst/ui5/metaui/layouts/BaseLayout-dbg.js.map +1 -1
  72. package/src/nz/co/siliconst/ui5/metaui/layouts/BaseLayout.d.ts +4 -17
  73. package/src/nz/co/siliconst/ui5/metaui/layouts/BaseLayout.d.ts.map +1 -1
  74. package/src/nz/co/siliconst/ui5/metaui/layouts/BaseLayout.js +1 -1
  75. package/src/nz/co/siliconst/ui5/metaui/layouts/BaseLayout.js.map +1 -1
  76. package/src/nz/co/siliconst/ui5/metaui/layouts/BaseLayout.ts +22 -34
  77. package/src/nz/co/siliconst/ui5/metaui/layouts/FormLayout-dbg.js +98 -56
  78. package/src/nz/co/siliconst/ui5/metaui/layouts/FormLayout-dbg.js.map +1 -1
  79. package/src/nz/co/siliconst/ui5/metaui/layouts/FormLayout.d.ts +7 -7
  80. package/src/nz/co/siliconst/ui5/metaui/layouts/FormLayout.d.ts.map +1 -1
  81. package/src/nz/co/siliconst/ui5/metaui/layouts/FormLayout.js +1 -1
  82. package/src/nz/co/siliconst/ui5/metaui/layouts/FormLayout.js.map +1 -1
  83. package/src/nz/co/siliconst/ui5/metaui/layouts/FormLayout.ts +97 -60
  84. package/src/nz/co/siliconst/ui5/metaui/layouts/TableLayout-dbg.js +102 -90
  85. package/src/nz/co/siliconst/ui5/metaui/layouts/TableLayout-dbg.js.map +1 -1
  86. package/src/nz/co/siliconst/ui5/metaui/layouts/TableLayout.d.ts +4 -8
  87. package/src/nz/co/siliconst/ui5/metaui/layouts/TableLayout.d.ts.map +1 -1
  88. package/src/nz/co/siliconst/ui5/metaui/layouts/TableLayout.js +1 -1
  89. package/src/nz/co/siliconst/ui5/metaui/layouts/TableLayout.js.map +1 -1
  90. package/src/nz/co/siliconst/ui5/metaui/layouts/TableLayout.ts +119 -102
  91. package/src/nz/co/siliconst/ui5/metaui/library-dbg.js +43 -32
  92. package/src/nz/co/siliconst/ui5/metaui/library-dbg.js.map +1 -1
  93. package/src/nz/co/siliconst/ui5/metaui/library-preload.js +22 -17
  94. package/src/nz/co/siliconst/ui5/metaui/library-preload.js.map +1 -1
  95. package/src/nz/co/siliconst/ui5/metaui/library.d.ts.map +1 -1
  96. package/src/nz/co/siliconst/ui5/metaui/library.js +1 -1
  97. package/src/nz/co/siliconst/ui5/metaui/library.js.map +1 -1
  98. package/src/nz/co/siliconst/ui5/metaui/library.ts +55 -43
  99. package/src/nz/co/siliconst/ui5/metaui/manifest.json +1 -0
  100. package/src/nz/co/siliconst/ui5/metaui/plugins/ArrayPlugin-dbg.js +68 -0
  101. package/src/nz/co/siliconst/ui5/metaui/plugins/ArrayPlugin-dbg.js.map +1 -0
  102. package/src/nz/co/siliconst/ui5/metaui/plugins/ArrayPlugin.d.ts +15 -0
  103. package/src/nz/co/siliconst/ui5/metaui/plugins/ArrayPlugin.d.ts.map +1 -0
  104. package/src/nz/co/siliconst/ui5/metaui/plugins/ArrayPlugin.js +2 -0
  105. package/src/nz/co/siliconst/ui5/metaui/plugins/ArrayPlugin.js.map +1 -0
  106. package/src/nz/co/siliconst/ui5/metaui/plugins/ArrayPlugin.ts +71 -0
  107. package/src/nz/co/siliconst/ui5/metaui/plugins/BasePlugin-dbg.js +54 -59
  108. package/src/nz/co/siliconst/ui5/metaui/plugins/BasePlugin-dbg.js.map +1 -1
  109. package/src/nz/co/siliconst/ui5/metaui/plugins/BasePlugin.d.ts +8 -27
  110. package/src/nz/co/siliconst/ui5/metaui/plugins/BasePlugin.d.ts.map +1 -1
  111. package/src/nz/co/siliconst/ui5/metaui/plugins/BasePlugin.js +1 -1
  112. package/src/nz/co/siliconst/ui5/metaui/plugins/BasePlugin.js.map +1 -1
  113. package/src/nz/co/siliconst/ui5/metaui/plugins/BasePlugin.ts +56 -58
  114. package/src/nz/co/siliconst/ui5/metaui/plugins/BooleanPlugin-dbg.js +41 -42
  115. package/src/nz/co/siliconst/ui5/metaui/plugins/BooleanPlugin-dbg.js.map +1 -1
  116. package/src/nz/co/siliconst/ui5/metaui/plugins/BooleanPlugin.d.ts +2 -2
  117. package/src/nz/co/siliconst/ui5/metaui/plugins/BooleanPlugin.d.ts.map +1 -1
  118. package/src/nz/co/siliconst/ui5/metaui/plugins/BooleanPlugin.js +1 -1
  119. package/src/nz/co/siliconst/ui5/metaui/plugins/BooleanPlugin.js.map +1 -1
  120. package/src/nz/co/siliconst/ui5/metaui/plugins/BooleanPlugin.ts +41 -42
  121. package/src/nz/co/siliconst/ui5/metaui/plugins/DatePlugin-dbg.js +68 -60
  122. package/src/nz/co/siliconst/ui5/metaui/plugins/DatePlugin-dbg.js.map +1 -1
  123. package/src/nz/co/siliconst/ui5/metaui/plugins/DatePlugin.d.ts +2 -2
  124. package/src/nz/co/siliconst/ui5/metaui/plugins/DatePlugin.d.ts.map +1 -1
  125. package/src/nz/co/siliconst/ui5/metaui/plugins/DatePlugin.js +1 -1
  126. package/src/nz/co/siliconst/ui5/metaui/plugins/DatePlugin.js.map +1 -1
  127. package/src/nz/co/siliconst/ui5/metaui/plugins/DatePlugin.ts +69 -63
  128. package/src/nz/co/siliconst/ui5/metaui/plugins/DateTimePlugin-dbg.js +68 -0
  129. package/src/nz/co/siliconst/ui5/metaui/plugins/DateTimePlugin-dbg.js.map +1 -0
  130. package/src/nz/co/siliconst/ui5/metaui/plugins/DateTimePlugin.d.ts +18 -0
  131. package/src/nz/co/siliconst/ui5/metaui/plugins/DateTimePlugin.d.ts.map +1 -0
  132. package/src/nz/co/siliconst/ui5/metaui/plugins/DateTimePlugin.js +2 -0
  133. package/src/nz/co/siliconst/ui5/metaui/plugins/DateTimePlugin.js.map +1 -0
  134. package/src/nz/co/siliconst/ui5/metaui/plugins/DateTimePlugin.ts +68 -0
  135. package/src/nz/co/siliconst/ui5/metaui/plugins/DropdownPlugin-dbg.js +66 -66
  136. package/src/nz/co/siliconst/ui5/metaui/plugins/DropdownPlugin-dbg.js.map +1 -1
  137. package/src/nz/co/siliconst/ui5/metaui/plugins/DropdownPlugin.d.ts +2 -2
  138. package/src/nz/co/siliconst/ui5/metaui/plugins/DropdownPlugin.d.ts.map +1 -1
  139. package/src/nz/co/siliconst/ui5/metaui/plugins/DropdownPlugin.js +1 -1
  140. package/src/nz/co/siliconst/ui5/metaui/plugins/DropdownPlugin.js.map +1 -1
  141. package/src/nz/co/siliconst/ui5/metaui/plugins/DropdownPlugin.ts +65 -65
  142. package/src/nz/co/siliconst/ui5/metaui/plugins/NumberPlugin-dbg.js +55 -53
  143. package/src/nz/co/siliconst/ui5/metaui/plugins/NumberPlugin-dbg.js.map +1 -1
  144. package/src/nz/co/siliconst/ui5/metaui/plugins/NumberPlugin.d.ts +3 -3
  145. package/src/nz/co/siliconst/ui5/metaui/plugins/NumberPlugin.d.ts.map +1 -1
  146. package/src/nz/co/siliconst/ui5/metaui/plugins/NumberPlugin.js +1 -1
  147. package/src/nz/co/siliconst/ui5/metaui/plugins/NumberPlugin.js.map +1 -1
  148. package/src/nz/co/siliconst/ui5/metaui/plugins/NumberPlugin.ts +56 -55
  149. package/src/nz/co/siliconst/ui5/metaui/plugins/StringPlugin-dbg.js +56 -53
  150. package/src/nz/co/siliconst/ui5/metaui/plugins/StringPlugin-dbg.js.map +1 -1
  151. package/src/nz/co/siliconst/ui5/metaui/plugins/StringPlugin.d.ts +2 -2
  152. package/src/nz/co/siliconst/ui5/metaui/plugins/StringPlugin.d.ts.map +1 -1
  153. package/src/nz/co/siliconst/ui5/metaui/plugins/StringPlugin.js +1 -1
  154. package/src/nz/co/siliconst/ui5/metaui/plugins/StringPlugin.js.map +1 -1
  155. package/src/nz/co/siliconst/ui5/metaui/plugins/StringPlugin.ts +58 -55
  156. package/src/nz/co/siliconst/ui5/metaui/plugins/SwitchPlugin-dbg.js +43 -0
  157. package/src/nz/co/siliconst/ui5/metaui/plugins/SwitchPlugin-dbg.js.map +1 -0
  158. package/src/nz/co/siliconst/ui5/metaui/plugins/SwitchPlugin.d.ts +18 -0
  159. package/src/nz/co/siliconst/ui5/metaui/plugins/SwitchPlugin.d.ts.map +1 -0
  160. package/src/nz/co/siliconst/ui5/metaui/plugins/SwitchPlugin.js +2 -0
  161. package/src/nz/co/siliconst/ui5/metaui/plugins/SwitchPlugin.js.map +1 -0
  162. package/src/nz/co/siliconst/ui5/metaui/plugins/SwitchPlugin.ts +42 -0
  163. package/src/nz/co/siliconst/ui5/metaui/plugins/TextAreaPlugin-dbg.js +58 -0
  164. package/src/nz/co/siliconst/ui5/metaui/plugins/TextAreaPlugin-dbg.js.map +1 -0
  165. package/src/nz/co/siliconst/ui5/metaui/plugins/TextAreaPlugin.d.ts +18 -0
  166. package/src/nz/co/siliconst/ui5/metaui/plugins/TextAreaPlugin.d.ts.map +1 -0
  167. package/src/nz/co/siliconst/ui5/metaui/plugins/TextAreaPlugin.js +2 -0
  168. package/src/nz/co/siliconst/ui5/metaui/plugins/TextAreaPlugin.js.map +1 -0
  169. package/src/nz/co/siliconst/ui5/metaui/plugins/TextAreaPlugin.ts +58 -0
  170. package/src/nz/co/siliconst/ui5/metaui/plugins/TimePlugin-dbg.js +74 -0
  171. package/src/nz/co/siliconst/ui5/metaui/plugins/TimePlugin-dbg.js.map +1 -0
  172. package/src/nz/co/siliconst/ui5/metaui/plugins/TimePlugin.d.ts +18 -0
  173. package/src/nz/co/siliconst/ui5/metaui/plugins/TimePlugin.d.ts.map +1 -0
  174. package/src/nz/co/siliconst/ui5/metaui/plugins/TimePlugin.js +2 -0
  175. package/src/nz/co/siliconst/ui5/metaui/plugins/TimePlugin.js.map +1 -0
  176. package/src/nz/co/siliconst/ui5/metaui/plugins/TimePlugin.ts +71 -0
  177. package/ui5.yaml +3 -3
  178. package/test-resources/App.js +0 -11
  179. package/test-resources/Main.controller.js +0 -73
  180. package/test-resources/Main.view.xml +0 -42
  181. package/test-resources/index.html +0 -21
  182. package/test-resources/mockData.json +0 -27
  183. package/test-resources/mockSchema.json +0 -98
@@ -1,60 +1,97 @@
1
- /**
2
- * @file FormLayout.ts
3
- * @description Generates a fully responsive SAP Fiori Form layout (SimpleForm).
4
- */
5
-
6
- import SimpleForm from "sap/ui/layout/form/SimpleForm";
7
- import Label from "sap/m/Label";
8
- import { IFieldMetadata } from "../interfaces/ISchema";
9
- import { PluginRegistry } from "../core/PluginRegistry";
10
-
11
- /**
12
- * Utility class strictly for constructing Form layouts without custom CSS.
13
- */
14
- export class FormLayout {
15
- /**
16
- * Builds a SimpleForm with ResponsiveGridLayout, injecting the requested plugins.
17
- * @param fields The array of root fields to render as FormElements.
18
- * @returns A fully populated sap.ui.layout.form.SimpleForm.
19
- */
20
- public static build(fields: IFieldMetadata[]): SimpleForm {
21
- const form = new SimpleForm({
22
- editable: true,
23
- layout: "ResponsiveGridLayout",
24
- labelSpanXL: 4,
25
- labelSpanL: 4,
26
- labelSpanM: 4,
27
- labelSpanS: 12,
28
- adjustLabelSpan: false,
29
- emptySpanXL: 0,
30
- emptySpanL: 0,
31
- emptySpanM: 0,
32
- emptySpanS: 0,
33
- columnsXL: 1,
34
- columnsL: 1,
35
- columnsM: 1,
36
- singleContainerFullSize: false
37
- });
38
-
39
- const registry = PluginRegistry.getInstance();
40
-
41
- fields.forEach((field) => {
42
- // Respect Fiori accessibility standards by enforcing the required flag on labels
43
- const label = new Label({
44
- text: field.label,
45
- required: field.isRequired
46
- });
47
-
48
- // Instantiate the correct plugin for the data type
49
- const plugin = registry.getPlugin(field.type);
50
-
51
- // In the isolated state manager architecture, the binding path maps exactly to the fieldName.
52
- const control = plugin.render(field, `/${field.fieldName}`);
53
-
54
- form.addContent(label);
55
- form.addContent(control);
56
- });
57
-
58
- return form;
59
- }
60
- }
1
+ /**
2
+ * @file FormLayout.ts
3
+ * @description Generates a fully responsive SAP Fiori Form layout (SimpleForm).
4
+ */
5
+
6
+ import SimpleForm from "sap/ui/layout/form/SimpleForm";
7
+ import Label from "sap/m/Label";
8
+ import Title from "sap/ui/core/Title";
9
+ import { IPropertyMetadata } from "../interfaces/ISchema";
10
+ import { PluginRegistry } from "../core/PluginRegistry";
11
+ import { IPlugin } from "../interfaces/IPlugin";
12
+
13
+ export class FormLayout {
14
+ /**
15
+ * Builds a SimpleForm with ResponsiveGridLayout, injecting the requested plugins.
16
+ * @param properties The dictionary of fields to render.
17
+ * @param modelName The dynamic model name.
18
+ * @param formTitle Optional title for the form block.
19
+ * @param trackPlugin Optional callback to track instantiated plugins.
20
+ */
21
+ public static build(properties: Record<string, IPropertyMetadata>, modelName: string = "meta", formTitle?: string, trackPlugin?: (plugin: IPlugin) => void): SimpleForm {
22
+ const form = new SimpleForm({
23
+ editable: true,
24
+ title: formTitle,
25
+ layout: "ResponsiveGridLayout",
26
+ labelSpanXL: 4,
27
+ labelSpanL: 4,
28
+ labelSpanM: 4,
29
+ labelSpanS: 12,
30
+ adjustLabelSpan: false,
31
+ emptySpanXL: 0,
32
+ emptySpanL: 0,
33
+ emptySpanM: 0,
34
+ emptySpanS: 0,
35
+ columnsXL: 1,
36
+ columnsL: 1,
37
+ columnsM: 1,
38
+ singleContainerFullSize: false
39
+ });
40
+
41
+ const registry = PluginRegistry.getInstance();
42
+
43
+ // Group fields by their ui.group directive
44
+ const groups: Record<string, { key: string; meta: IPropertyMetadata }[]> = {};
45
+ const DEFAULT_GROUP = "__DEFAULT__";
46
+
47
+ for (const key of Object.keys(properties)) {
48
+ const meta = properties[key];
49
+ const groupName = meta.ui?.group || DEFAULT_GROUP;
50
+ if (!groups[groupName]) groups[groupName] = [];
51
+ groups[groupName].push({ key, meta });
52
+ }
53
+
54
+ // Render groups
55
+ for (const groupName of Object.keys(groups)) {
56
+ if (groupName !== DEFAULT_GROUP) {
57
+ form.addContent(new Title({ text: groupName }));
58
+ }
59
+
60
+ groups[groupName].forEach((field) => {
61
+ try {
62
+ const label = new Label({
63
+ text: field.meta.ui?.label || field.key,
64
+ required: field.meta.required
65
+ });
66
+
67
+ // Attach visibility condition to label and control container logic
68
+ if (field.meta.ui?.visibleOn) {
69
+ const expr = `{= ${field.meta.ui.visibleOn.replace(/\$root\./g, `${modelName}>/`).replace(/\./g, '/')} }`;
70
+ label.bindProperty("visible", { parts: [{ path: "meta>/" }], formatter: () => false}); // temporary, condition engine does this usually
71
+ }
72
+
73
+ const plugin = registry.getPlugin(field.meta.type, field.meta.ui?.widget);
74
+ if (trackPlugin) trackPlugin(plugin);
75
+ const control = plugin.render(field.meta, `/${field.key}`, modelName);
76
+
77
+ if (field.meta.ui?.fullWidth) {
78
+ sap.ui.require(["sap/ui/layout/GridData"], (GridData: any) => {
79
+ control.setLayoutData(new GridData({
80
+ span: "XL12 L12 M12 S12"
81
+ }));
82
+ });
83
+ }
84
+
85
+ form.addContent(label);
86
+ form.addContent(control);
87
+ } catch (error) {
88
+ sap.ui.require(["sap/base/Log"], (Log: any) => {
89
+ if (Log) Log.error(`[MetaUI] Failed to render field ${field.key}`, (error as Error).message, "FormLayout");
90
+ });
91
+ }
92
+ });
93
+ }
94
+
95
+ return form;
96
+ }
97
+ }
@@ -1,91 +1,103 @@
1
- sap.ui.define(["sap/m/Table", "sap/m/Column", "sap/m/Text", "sap/m/ColumnListItem", "sap/m/Toolbar", "sap/m/Title", "sap/m/ToolbarSpacer", "sap/m/Button", "../core/PluginRegistry"], function (Table, Column, Text, ColumnListItem, Toolbar, Title, ToolbarSpacer, Button, ___core_PluginRegistry) {
2
- "use strict";
3
-
4
- const PluginRegistry = ___core_PluginRegistry["PluginRegistry"];
5
- /**
6
- * Utility class strictly for constructing sap.m.Table structures with dynamic pop-in vectors.
7
- */
8
- class TableLayout {
9
- /**
10
- * Builds a responsive Table, dynamically calculating column priorities.
11
- * @param tableMeta The metadata defining the table's columns and nested fields.
12
- * @returns A fully constructed sap.m.Table ready to be bound to a list array.
13
- */
14
- static build(tableMeta) {
15
- const table = new Table({
16
- headerToolbar: new Toolbar({
17
- content: [new Title({
18
- text: tableMeta.label || tableMeta.tableName
19
- }), new ToolbarSpacer(), new Button({
20
- text: "Add Row",
21
- icon: "sap-icon://add",
22
- press: oEvent => {
23
- const btn = oEvent.getSource();
24
- const tbl = btn.getParent().getParent();
25
- const model = tbl.getModel("meta");
26
- const path = `/${tableMeta.tableName}`;
27
- const data = model.getProperty(path) || [];
28
- data.push({}); // append empty row
29
- model.setProperty(path, data);
30
- }
31
- })]
32
- }),
33
- fixedLayout: false,
34
- // Allows native UI5 column width calculations
35
- mode: "Delete",
36
- delete: oEvent => {
37
- const item = oEvent.getParameter("listItem");
38
- const path = item.getBindingContext("meta").getPath(); // e.g. "/Contacts/0"
39
- const model = item.getModel("meta");
40
- const parts = path.split("/");
41
- const index = parseInt(parts.pop() || "0", 10);
42
- const arrayPath = parts.join("/");
43
- const data = model.getProperty(arrayPath);
44
- data.splice(index, 1);
45
- model.setProperty(arrayPath, data);
46
- }
47
- });
48
- const templateCells = [];
49
- const registry = PluginRegistry.getInstance();
50
- tableMeta.fields.forEach(field => {
51
- // Build the column header
52
- const column = new Column({
53
- header: new Text({
54
- text: field.label
55
- }),
56
- // Fiori UX: High priority for primary keys so they don't pop-in too early
57
- demandPopin: !field.isKey,
58
- minScreenWidth: field.isKey ? "" : "Tablet",
59
- popinDisplay: "Inline"
60
- });
61
- table.addColumn(column);
62
-
63
- // Instantiate the cell template (plugin)
64
- const plugin = registry.getPlugin(field.type);
65
-
66
- // In table lists, the binding path is relative to the row's context context (e.g. "{fieldName}")
67
- const control = plugin.render(field, field.fieldName);
68
- templateCells.push(control);
69
- });
70
-
71
- // Create the row template and bind it to the table via the tableName array path
72
- const rowTemplate = new ColumnListItem({
73
- cells: templateCells
74
- });
75
-
76
- // The absolute binding path from the StateManager for this table (using the named model 'meta')
77
- table.bindItems({
78
- path: `meta>/${tableMeta.tableName}`,
79
- template: rowTemplate,
80
- templateShareable: false
81
- });
82
- return table;
83
- }
84
- }
85
- var __exports = {
86
- __esModule: true
87
- };
88
- __exports.TableLayout = TableLayout;
89
- return __exports;
90
- });
1
+ sap.ui.define(["sap/m/Table", "sap/m/Column", "sap/m/Text", "sap/m/ColumnListItem", "sap/m/Toolbar", "sap/m/Title", "sap/m/ToolbarSpacer", "sap/m/Button", "../core/PluginRegistry"], function (Table, Column, Text, ColumnListItem, Toolbar, Title, ToolbarSpacer, Button, ___core_PluginRegistry) {
2
+ "use strict";
3
+
4
+ const PluginRegistry = ___core_PluginRegistry["PluginRegistry"];
5
+ class TableLayout {
6
+ /**
7
+ * Builds a responsive Table, dynamically calculating column priorities.
8
+ */
9
+ static build(tableMeta, bindingPath = "meta>/", tableTitle = "Table", trackPlugin) {
10
+ if (!tableMeta.properties) {
11
+ throw new Error("[MetaUI] Table requires an items schema with properties.");
12
+ }
13
+ const parts = bindingPath.split(">");
14
+ const actualModelName = parts.length > 1 ? parts[0] : undefined;
15
+ const actualPath = parts.length > 1 ? parts[1] : bindingPath;
16
+ // e.g. "meta>/Contacts" -> actualModelName = "meta", actualPath = "/Contacts"
17
+
18
+ const table = new Table({
19
+ headerToolbar: new Toolbar({
20
+ content: [new Title({
21
+ text: tableTitle
22
+ }), new ToolbarSpacer(), new Button({
23
+ text: "Add Row",
24
+ icon: "sap-icon://add",
25
+ press: oEvent => {
26
+ const btn = oEvent.getSource();
27
+ const tbl = btn.getParent().getParent();
28
+ const model = tbl.getModel(actualModelName);
29
+ const info = tbl.getBindingInfo("items");
30
+ if (!info || !info.path) return;
31
+ const data = model.getProperty(info.path) || [];
32
+ data.push({}); // append empty row
33
+ model.setProperty(info.path, data);
34
+ }
35
+ })]
36
+ }),
37
+ fixedLayout: false,
38
+ mode: "Delete",
39
+ delete: oEvent => {
40
+ const item = oEvent.getParameter("listItem");
41
+ const path = item.getBindingContext(actualModelName).getPath();
42
+ const model = item.getModel(actualModelName);
43
+ const splitPaths = path.split("/");
44
+ const index = parseInt(splitPaths.pop() || "0", 10);
45
+ let arrayPath = splitPaths.join("/");
46
+ if (arrayPath === "") arrayPath = "/";
47
+ const data = model.getProperty(arrayPath);
48
+ data.splice(index, 1);
49
+ model.setProperty(arrayPath, data);
50
+ }
51
+ });
52
+ const templateCells = [];
53
+ const registry = PluginRegistry.getInstance();
54
+ const props = tableMeta.properties;
55
+ Object.keys(props).forEach(key => {
56
+ try {
57
+ const fieldMeta = props[key];
58
+ const isKey = !!fieldMeta.ui?.isKey;
59
+ const column = new Column({
60
+ header: new Text({
61
+ text: fieldMeta.ui?.label || key
62
+ }),
63
+ demandPopin: !isKey,
64
+ minScreenWidth: isKey ? "" : "Tablet",
65
+ popinDisplay: "Inline"
66
+ });
67
+ table.addColumn(column);
68
+ const plugin = registry.getPlugin(fieldMeta.type, fieldMeta.ui?.widget);
69
+ if (trackPlugin) trackPlugin(plugin);
70
+ const control = plugin.render(fieldMeta, key, actualModelName); // No trailing slash for relative bindings
71
+ templateCells.push(control);
72
+ } catch (error) {
73
+ sap.ui.require(["sap/base/Log"], Log => {
74
+ if (Log) Log.error(`[MetaUI] Failed to render column ${key}`, error.message, "TableLayout");
75
+ });
76
+
77
+ // Add an empty text control as a fallback so the table columns match the cells array length
78
+ templateCells.push(new Text({
79
+ text: "Error"
80
+ }));
81
+ }
82
+ });
83
+ const rowTemplate = new ColumnListItem({
84
+ cells: templateCells
85
+ });
86
+
87
+ // V2 Fix: Actually bind the items to the table!
88
+ table.bindItems({
89
+ path: actualPath,
90
+ model: actualModelName,
91
+ template: rowTemplate,
92
+ templateShareable: false
93
+ });
94
+ return table;
95
+ }
96
+ }
97
+ var __exports = {
98
+ __esModule: true
99
+ };
100
+ __exports.TableLayout = TableLayout;
101
+ return __exports;
102
+ });
91
103
  //# sourceMappingURL=TableLayout-dbg.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TableLayout-dbg.js","names":["PluginRegistry","___core_PluginRegistry","TableLayout","build","tableMeta","table","Table","headerToolbar","Toolbar","content","Title","text","label","tableName","ToolbarSpacer","Button","icon","press","oEvent","btn","getSource","tbl","getParent","model","getModel","path","data","getProperty","push","setProperty","fixedLayout","mode","delete","item","getParameter","getBindingContext","getPath","parts","split","index","parseInt","pop","arrayPath","join","splice","templateCells","registry","getInstance","fields","forEach","field","column","Column","header","Text","demandPopin","isKey","minScreenWidth","popinDisplay","addColumn","plugin","getPlugin","type","control","render","fieldName","rowTemplate","ColumnListItem","cells","bindItems","template","templateShareable","__exports","__esModule"],"sources":["TableLayout.ts"],"sourcesContent":["/**\r\n * @file TableLayout.ts\r\n * @description Generates a responsive SAP Fiori Table layout.\r\n */\r\n\r\nimport Table from \"sap/m/Table\";\r\nimport Column from \"sap/m/Column\";\r\nimport Text from \"sap/m/Text\";\r\nimport ColumnListItem from \"sap/m/ColumnListItem\";\r\nimport Toolbar from \"sap/m/Toolbar\";\r\nimport Title from \"sap/m/Title\";\r\nimport ToolbarSpacer from \"sap/m/ToolbarSpacer\";\r\nimport Button from \"sap/m/Button\";\r\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\r\nimport { ITableMetadata, IFieldMetadata } from \"../interfaces/ISchema\";\r\nimport { PluginRegistry } from \"../core/PluginRegistry\";\r\nimport Control from \"sap/ui/core/Control\";\r\n\r\n/**\r\n * Utility class strictly for constructing sap.m.Table structures with dynamic pop-in vectors.\r\n */\r\nexport class TableLayout {\r\n /**\r\n * Builds a responsive Table, dynamically calculating column priorities.\r\n * @param tableMeta The metadata defining the table's columns and nested fields.\r\n * @returns A fully constructed sap.m.Table ready to be bound to a list array.\r\n */\r\n public static build(tableMeta: ITableMetadata): Table {\r\n const table = new Table({\r\n headerToolbar: new Toolbar({\r\n content: [\r\n new Title({ text: tableMeta.label || tableMeta.tableName }),\r\n new ToolbarSpacer(),\r\n new Button({\r\n text: \"Add Row\",\r\n icon: \"sap-icon://add\",\r\n press: (oEvent: any) => {\r\n const btn = oEvent.getSource();\r\n const tbl = btn.getParent().getParent() as Table;\r\n const model = tbl.getModel(\"meta\") as JSONModel;\r\n const path = `/${tableMeta.tableName}`;\r\n const data = model.getProperty(path) || [];\r\n data.push({}); // append empty row\r\n model.setProperty(path, data);\r\n }\r\n })\r\n ]\r\n }),\r\n fixedLayout: false, // Allows native UI5 column width calculations\r\n mode: \"Delete\",\r\n delete: (oEvent: any) => {\r\n const item = oEvent.getParameter(\"listItem\");\r\n const path = item.getBindingContext(\"meta\").getPath(); // e.g. \"/Contacts/0\"\r\n const model = item.getModel(\"meta\") as JSONModel;\r\n \r\n const parts = path.split(\"/\");\r\n const index = parseInt(parts.pop() || \"0\", 10);\r\n const arrayPath = parts.join(\"/\");\r\n \r\n const data = model.getProperty(arrayPath);\r\n data.splice(index, 1);\r\n model.setProperty(arrayPath, data);\r\n }\r\n });\r\n\r\n const templateCells: Control[] = [];\r\n const registry = PluginRegistry.getInstance();\r\n\r\n tableMeta.fields.forEach((field: IFieldMetadata) => {\r\n // Build the column header\r\n const column = new Column({\r\n header: new Text({ text: field.label }),\r\n // Fiori UX: High priority for primary keys so they don't pop-in too early\r\n demandPopin: !field.isKey, \r\n minScreenWidth: field.isKey ? \"\" : \"Tablet\",\r\n popinDisplay: \"Inline\"\r\n });\r\n table.addColumn(column);\r\n\r\n // Instantiate the cell template (plugin)\r\n const plugin = registry.getPlugin(field.type);\r\n \r\n // In table lists, the binding path is relative to the row's context context (e.g. \"{fieldName}\")\r\n const control = plugin.render(field, field.fieldName);\r\n templateCells.push(control);\r\n });\r\n\r\n // Create the row template and bind it to the table via the tableName array path\r\n const rowTemplate = new ColumnListItem({\r\n cells: templateCells\r\n });\r\n\r\n // The absolute binding path from the StateManager for this table (using the named model 'meta')\r\n table.bindItems({\r\n path: `meta>/${tableMeta.tableName}`,\r\n template: rowTemplate,\r\n templateShareable: false\r\n });\r\n\r\n return table;\r\n }\r\n}\r\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"TableLayout-dbg.js","names":["PluginRegistry","___core_PluginRegistry","TableLayout","build","tableMeta","bindingPath","tableTitle","trackPlugin","properties","Error","parts","split","actualModelName","length","undefined","actualPath","table","Table","headerToolbar","Toolbar","content","Title","text","ToolbarSpacer","Button","icon","press","oEvent","btn","getSource","tbl","getParent","model","getModel","info","getBindingInfo","path","data","getProperty","push","setProperty","fixedLayout","mode","delete","item","getParameter","getBindingContext","getPath","splitPaths","index","parseInt","pop","arrayPath","join","splice","templateCells","registry","getInstance","props","Object","keys","forEach","key","fieldMeta","isKey","ui","column","Column","header","Text","label","demandPopin","minScreenWidth","popinDisplay","addColumn","plugin","getPlugin","type","widget","control","render","error","sap","require","Log","message","rowTemplate","ColumnListItem","cells","bindItems","template","templateShareable","__exports","__esModule"],"sources":["TableLayout.ts"],"sourcesContent":["/**\n * @file TableLayout.ts\n * @description Generates a responsive SAP Fiori Table layout for v2 schema.\n */\n\nimport Table from \"sap/m/Table\";\nimport Column from \"sap/m/Column\";\nimport Text from \"sap/m/Text\";\nimport ColumnListItem from \"sap/m/ColumnListItem\";\nimport Toolbar from \"sap/m/Toolbar\";\nimport Title from \"sap/m/Title\";\nimport ToolbarSpacer from \"sap/m/ToolbarSpacer\";\nimport Button from \"sap/m/Button\";\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\nimport { PluginRegistry } from \"../core/PluginRegistry\";\nimport Control from \"sap/ui/core/Control\";\nimport { IPlugin } from \"../interfaces/IPlugin\";\nimport { IPropertyMetadata } from \"../interfaces/ISchema\";\n\nexport class TableLayout {\n /**\n * Builds a responsive Table, dynamically calculating column priorities.\n */\n public static build(tableMeta: IPropertyMetadata, bindingPath: string = \"meta>/\", tableTitle: string = \"Table\", trackPlugin?: (plugin: IPlugin) => void): Table {\n if (!tableMeta.properties) {\n throw new Error(\"[MetaUI] Table requires an items schema with properties.\");\n }\n\n const parts = bindingPath.split(\">\");\n const actualModelName = parts.length > 1 ? parts[0] : undefined;\n const actualPath = parts.length > 1 ? parts[1] : bindingPath;\n // e.g. \"meta>/Contacts\" -> actualModelName = \"meta\", actualPath = \"/Contacts\"\n\n const table = new Table({\n headerToolbar: new Toolbar({\n content: [\n new Title({ text: tableTitle }),\n new ToolbarSpacer(),\n new Button({\n text: \"Add Row\",\n icon: \"sap-icon://add\",\n press: (oEvent: any) => {\n const btn = oEvent.getSource();\n const tbl = btn.getParent().getParent() as Table;\n const model = tbl.getModel(actualModelName) as JSONModel;\n const info = tbl.getBindingInfo(\"items\");\n if (!info || !info.path) return;\n \n const data = model.getProperty(info.path) || [];\n data.push({}); // append empty row\n model.setProperty(info.path, data);\n }\n })\n ]\n }),\n fixedLayout: false,\n mode: \"Delete\",\n delete: (oEvent: any) => {\n const item = oEvent.getParameter(\"listItem\");\n const path = item.getBindingContext(actualModelName).getPath(); \n const model = item.getModel(actualModelName) as JSONModel;\n \n const splitPaths = path.split(\"/\");\n const index = parseInt(splitPaths.pop() || \"0\", 10);\n let arrayPath = splitPaths.join(\"/\");\n if (arrayPath === \"\") arrayPath = \"/\";\n \n const data = model.getProperty(arrayPath);\n data.splice(index, 1);\n model.setProperty(arrayPath, data);\n }\n });\n\n const templateCells: Control[] = [];\n const registry = PluginRegistry.getInstance();\n const props = tableMeta.properties;\n\n Object.keys(props).forEach((key) => {\n try {\n const fieldMeta = props[key];\n const isKey = !!fieldMeta.ui?.isKey;\n \n const column = new Column({\n header: new Text({ text: fieldMeta.ui?.label || key }),\n demandPopin: !isKey, \n minScreenWidth: isKey ? \"\" : \"Tablet\",\n popinDisplay: \"Inline\"\n });\n table.addColumn(column);\n\n const plugin = registry.getPlugin(fieldMeta.type, fieldMeta.ui?.widget);\n if (trackPlugin) trackPlugin(plugin);\n const control = plugin.render(fieldMeta, key, actualModelName); // No trailing slash for relative bindings\n templateCells.push(control);\n } catch (error) {\n sap.ui.require([\"sap/base/Log\"], (Log: any) => {\n if (Log) Log.error(`[MetaUI] Failed to render column ${key}`, (error as Error).message, \"TableLayout\");\n });\n \n // Add an empty text control as a fallback so the table columns match the cells array length\n templateCells.push(new Text({ text: \"Error\" }));\n }\n });\n\n const rowTemplate = new ColumnListItem({\n cells: templateCells\n });\n\n // V2 Fix: Actually bind the items to the table!\n table.bindItems({\n path: actualPath,\n model: actualModelName,\n template: rowTemplate,\n templateShareable: false\n });\n\n return table;\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,20 +1,16 @@
1
1
  declare module "nz/co/siliconst/ui5/metaui/layouts/TableLayout" {
2
2
  /**
3
3
  * @file TableLayout.ts
4
- * @description Generates a responsive SAP Fiori Table layout.
4
+ * @description Generates a responsive SAP Fiori Table layout for v2 schema.
5
5
  */
6
6
  import Table from "sap/m/Table";
7
- import { ITableMetadata } from "nz/co/siliconst/ui5/metaui/interfaces/ISchema";
8
- /**
9
- * Utility class strictly for constructing sap.m.Table structures with dynamic pop-in vectors.
10
- */
7
+ import { IPlugin } from "nz/co/siliconst/ui5/metaui/interfaces/IPlugin";
8
+ import { IPropertyMetadata } from "nz/co/siliconst/ui5/metaui/interfaces/ISchema";
11
9
  export class TableLayout {
12
10
  /**
13
11
  * Builds a responsive Table, dynamically calculating column priorities.
14
- * @param tableMeta The metadata defining the table's columns and nested fields.
15
- * @returns A fully constructed sap.m.Table ready to be bound to a list array.
16
12
  */
17
- static build(tableMeta: ITableMetadata): Table;
13
+ static build(tableMeta: IPropertyMetadata, bindingPath?: string, tableTitle?: string, trackPlugin?: (plugin: IPlugin) => void): Table;
18
14
  }
19
15
  }
20
16
  //# sourceMappingURL=TableLayout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TableLayout.d.ts","sourceRoot":"..\\..\\..\\..\\..\\..\\..\\..","sources":["src\\nz\\co\\siliconst\\ui5\\metaui\\layouts\\TableLayout.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,gDAAgD,CAAC;IAChE;;;OAGG;IAEH,OAAO,KAAK,MAAM,aAAa,CAAC;IAShC,OAAO,EAAE,cAAc,EAAkB,MAAM,+CAA+C,CAAC;IAI/F;;OAEG;IACH,MAAa,WAAW;QACpB;;;;WAIG;eACW,KAAK,CAAC,SAAS,EAAE,cAAc,GAAG,KAAK;KA0ExD;CAEA"}
1
+ {"version":3,"file":"TableLayout.d.ts","sourceRoot":"../../../../../../../..","sources":["src/nz/co/siliconst/ui5/metaui/layouts/TableLayout.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,gDAAgD,CAAC;IAChE;;;OAGG;IAEH,OAAO,KAAK,MAAM,aAAa,CAAC;IAWhC,OAAO,EAAE,OAAO,EAAE,MAAM,+CAA+C,CAAC;IACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;IAElF,MAAa,WAAW;QACpB;;WAEG;eACW,KAAK,CAAC,SAAS,EAAE,iBAAiB,EAAE,WAAW,GAAE,MAAiB,EAAE,UAAU,GAAE,MAAgB,EAAE,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,GAAG,KAAK;KA+FlK;CAEA"}
@@ -1,2 +1,2 @@
1
- sap.ui.define(["sap/m/Table","sap/m/Column","sap/m/Text","sap/m/ColumnListItem","sap/m/Toolbar","sap/m/Title","sap/m/ToolbarSpacer","sap/m/Button","../core/PluginRegistry"],function(e,t,n,s,a,o,l,r,c){"use strict";const i=c["PluginRegistry"];class p{static build(c){const p=new e({headerToolbar:new a({content:[new o({text:c.label||c.tableName}),new l,new r({text:"Add Row",icon:"sap-icon://add",press:e=>{const t=e.getSource();const n=t.getParent().getParent();const s=n.getModel("meta");const a=`/${c.tableName}`;const o=s.getProperty(a)||[];o.push({});s.setProperty(a,o)}})]}),fixedLayout:false,mode:"Delete",delete:e=>{const t=e.getParameter("listItem");const n=t.getBindingContext("meta").getPath();const s=t.getModel("meta");const a=n.split("/");const o=parseInt(a.pop()||"0",10);const l=a.join("/");const r=s.getProperty(l);r.splice(o,1);s.setProperty(l,r)}});const m=[];const d=i.getInstance();c.fields.forEach(e=>{const s=new t({header:new n({text:e.label}),demandPopin:!e.isKey,minScreenWidth:e.isKey?"":"Tablet",popinDisplay:"Inline"});p.addColumn(s);const a=d.getPlugin(e.type);const o=a.render(e,e.fieldName);m.push(o)});const u=new s({cells:m});p.bindItems({path:`meta>/${c.tableName}`,template:u,templateShareable:false});return p}}var m={__esModule:true};m.TableLayout=p;return m});
1
+ sap.ui.define(["sap/m/Table","sap/m/Column","sap/m/Text","sap/m/ColumnListItem","sap/m/Toolbar","sap/m/Title","sap/m/ToolbarSpacer","sap/m/Button","../core/PluginRegistry"],function(e,t,n,s,o,a,r,i,c){"use strict";const l=c["PluginRegistry"];class p{static build(c,p="meta>/",u="Table",d){if(!c.properties){throw new Error("[MetaUI] Table requires an items schema with properties.")}const m=p.split(">");const g=m.length>1?m[0]:undefined;const h=m.length>1?m[1]:p;const b=new e({headerToolbar:new o({content:[new a({text:u}),new r,new i({text:"Add Row",icon:"sap-icon://add",press:e=>{const t=e.getSource();const n=t.getParent().getParent();const s=n.getModel(g);const o=n.getBindingInfo("items");if(!o||!o.path)return;const a=s.getProperty(o.path)||[];a.push({});s.setProperty(o.path,a)}})]}),fixedLayout:false,mode:"Delete",delete:e=>{const t=e.getParameter("listItem");const n=t.getBindingContext(g).getPath();const s=t.getModel(g);const o=n.split("/");const a=parseInt(o.pop()||"0",10);let r=o.join("/");if(r==="")r="/";const i=s.getProperty(r);i.splice(a,1);s.setProperty(r,i)}});const w=[];const y=l.getInstance();const f=c.properties;Object.keys(f).forEach(e=>{try{const s=f[e];const o=!!s.ui?.isKey;const a=new t({header:new n({text:s.ui?.label||e}),demandPopin:!o,minScreenWidth:o?"":"Tablet",popinDisplay:"Inline"});b.addColumn(a);const r=y.getPlugin(s.type,s.ui?.widget);if(d)d(r);const i=r.render(s,e,g);w.push(i)}catch(t){sap.ui.require(["sap/base/Log"],n=>{if(n)n.error(`[MetaUI] Failed to render column ${e}`,t.message,"TableLayout")});w.push(new n({text:"Error"}))}});const P=new s({cells:w});b.bindItems({path:h,model:g,template:P,templateShareable:false});return b}}var u={__esModule:true};u.TableLayout=p;return u});
2
2
  //# sourceMappingURL=TableLayout.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TableLayout.js","names":["PluginRegistry","___core_PluginRegistry","TableLayout","build","tableMeta","table","Table","headerToolbar","Toolbar","content","Title","text","label","tableName","ToolbarSpacer","Button","icon","press","oEvent","btn","getSource","tbl","getParent","model","getModel","path","data","getProperty","push","setProperty","fixedLayout","mode","delete","item","getParameter","getBindingContext","getPath","parts","split","index","parseInt","pop","arrayPath","join","splice","templateCells","registry","getInstance","fields","forEach","field","column","Column","header","Text","demandPopin","isKey","minScreenWidth","popinDisplay","addColumn","plugin","getPlugin","type","control","render","fieldName","rowTemplate","ColumnListItem","cells","bindItems","template","templateShareable","__exports","__esModule"],"sources":["TableLayout.ts"],"sourcesContent":["/**\r\n * @file TableLayout.ts\r\n * @description Generates a responsive SAP Fiori Table layout.\r\n */\r\n\r\nimport Table from \"sap/m/Table\";\r\nimport Column from \"sap/m/Column\";\r\nimport Text from \"sap/m/Text\";\r\nimport ColumnListItem from \"sap/m/ColumnListItem\";\r\nimport Toolbar from \"sap/m/Toolbar\";\r\nimport Title from \"sap/m/Title\";\r\nimport ToolbarSpacer from \"sap/m/ToolbarSpacer\";\r\nimport Button from \"sap/m/Button\";\r\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\r\nimport { ITableMetadata, IFieldMetadata } from \"../interfaces/ISchema\";\r\nimport { PluginRegistry } from \"../core/PluginRegistry\";\r\nimport Control from \"sap/ui/core/Control\";\r\n\r\n/**\r\n * Utility class strictly for constructing sap.m.Table structures with dynamic pop-in vectors.\r\n */\r\nexport class TableLayout {\r\n /**\r\n * Builds a responsive Table, dynamically calculating column priorities.\r\n * @param tableMeta The metadata defining the table's columns and nested fields.\r\n * @returns A fully constructed sap.m.Table ready to be bound to a list array.\r\n */\r\n public static build(tableMeta: ITableMetadata): Table {\r\n const table = new Table({\r\n headerToolbar: new Toolbar({\r\n content: [\r\n new Title({ text: tableMeta.label || tableMeta.tableName }),\r\n new ToolbarSpacer(),\r\n new Button({\r\n text: \"Add Row\",\r\n icon: \"sap-icon://add\",\r\n press: (oEvent: any) => {\r\n const btn = oEvent.getSource();\r\n const tbl = btn.getParent().getParent() as Table;\r\n const model = tbl.getModel(\"meta\") as JSONModel;\r\n const path = `/${tableMeta.tableName}`;\r\n const data = model.getProperty(path) || [];\r\n data.push({}); // append empty row\r\n model.setProperty(path, data);\r\n }\r\n })\r\n ]\r\n }),\r\n fixedLayout: false, // Allows native UI5 column width calculations\r\n mode: \"Delete\",\r\n delete: (oEvent: any) => {\r\n const item = oEvent.getParameter(\"listItem\");\r\n const path = item.getBindingContext(\"meta\").getPath(); // e.g. \"/Contacts/0\"\r\n const model = item.getModel(\"meta\") as JSONModel;\r\n \r\n const parts = path.split(\"/\");\r\n const index = parseInt(parts.pop() || \"0\", 10);\r\n const arrayPath = parts.join(\"/\");\r\n \r\n const data = model.getProperty(arrayPath);\r\n data.splice(index, 1);\r\n model.setProperty(arrayPath, data);\r\n }\r\n });\r\n\r\n const templateCells: Control[] = [];\r\n const registry = PluginRegistry.getInstance();\r\n\r\n tableMeta.fields.forEach((field: IFieldMetadata) => {\r\n // Build the column header\r\n const column = new Column({\r\n header: new Text({ text: field.label }),\r\n // Fiori UX: High priority for primary keys so they don't pop-in too early\r\n demandPopin: !field.isKey, \r\n minScreenWidth: field.isKey ? \"\" : \"Tablet\",\r\n popinDisplay: \"Inline\"\r\n });\r\n table.addColumn(column);\r\n\r\n // Instantiate the cell template (plugin)\r\n const plugin = registry.getPlugin(field.type);\r\n \r\n // In table lists, the binding path is relative to the row's context context (e.g. \"{fieldName}\")\r\n const control = plugin.render(field, field.fieldName);\r\n templateCells.push(control);\r\n });\r\n\r\n // Create the row template and bind it to the table via the tableName array path\r\n const rowTemplate = new ColumnListItem({\r\n cells: templateCells\r\n });\r\n\r\n // The absolute binding path from the StateManager for this table (using the named model 'meta')\r\n table.bindItems({\r\n path: `meta>/${tableMeta.tableName}`,\r\n template: rowTemplate,\r\n templateShareable: false\r\n });\r\n\r\n return table;\r\n }\r\n}\r\n"],"mappings":"4NAeSA,EAAcC,EAAA,kBAMhB,MAAMC,EAMT,YAAcC,CAAMC,GAChB,MAAMC,EAAQ,IAAIC,EAAM,CACpBC,cAAe,IAAIC,EAAQ,CACvBC,QAAS,CACL,IAAIC,EAAM,CAAEC,KAAMP,EAAUQ,OAASR,EAAUS,YAC/C,IAAIC,EACJ,IAAIC,EAAO,CACPJ,KAAM,UACNK,KAAM,iBACNC,MAAQC,IACJ,MAAMC,EAAMD,EAAOE,YACnB,MAAMC,EAAMF,EAAIG,YAAYA,YAC5B,MAAMC,EAAQF,EAAIG,SAAS,QAC3B,MAAMC,EAAO,IAAIrB,EAAUS,YAC3B,MAAMa,EAAOH,EAAMI,YAAYF,IAAS,GACxCC,EAAKE,KAAK,CAAC,GACXL,EAAMM,YAAYJ,EAAMC,SAKxCI,YAAa,MACbC,KAAM,SACNC,OAASd,IACL,MAAMe,EAAOf,EAAOgB,aAAa,YACjC,MAAMT,EAAOQ,EAAKE,kBAAkB,QAAQC,UAC5C,MAAMb,EAAQU,EAAKT,SAAS,QAE5B,MAAMa,EAAQZ,EAAKa,MAAM,KACzB,MAAMC,EAAQC,SAASH,EAAMI,OAAS,IAAK,IAC3C,MAAMC,EAAYL,EAAMM,KAAK,KAE7B,MAAMjB,EAAOH,EAAMI,YAAYe,GAC/BhB,EAAKkB,OAAOL,EAAO,GACnBhB,EAAMM,YAAYa,EAAWhB,MAIrC,MAAMmB,EAA2B,GACjC,MAAMC,EAAW9C,EAAe+C,cAEhC3C,EAAU4C,OAAOC,QAASC,IAEtB,MAAMC,EAAS,IAAIC,EAAO,CACtBC,OAAQ,IAAIC,EAAK,CAAE3C,KAAMuC,EAAMtC,QAE/B2C,aAAcL,EAAMM,MACpBC,eAAgBP,EAAMM,MAAQ,GAAK,SACnCE,aAAc,WAElBrD,EAAMsD,UAAUR,GAGhB,MAAMS,EAASd,EAASe,UAAUX,EAAMY,MAGxC,MAAMC,EAAUH,EAAOI,OAAOd,EAAOA,EAAMe,WAC3CpB,EAAcjB,KAAKmC,KAIvB,MAAMG,EAAc,IAAIC,EAAe,CACnCC,MAAOvB,IAIXxC,EAAMgE,UAAU,CACZ5C,KAAM,SAASrB,EAAUS,YACzByD,SAAUJ,EACVK,kBAAmB,QAGvB,OAAOlE,CACX,EACH,IAAAmE,EAAA,CAAAC,WAAA,MAAAD,EAAAtE,cAAA,OAAAsE,CAAA","ignoreList":[]}
1
+ {"version":3,"file":"TableLayout.js","names":["PluginRegistry","___core_PluginRegistry","TableLayout","build","tableMeta","bindingPath","tableTitle","trackPlugin","properties","Error","parts","split","actualModelName","length","undefined","actualPath","table","Table","headerToolbar","Toolbar","content","Title","text","ToolbarSpacer","Button","icon","press","oEvent","btn","getSource","tbl","getParent","model","getModel","info","getBindingInfo","path","data","getProperty","push","setProperty","fixedLayout","mode","delete","item","getParameter","getBindingContext","getPath","splitPaths","index","parseInt","pop","arrayPath","join","splice","templateCells","registry","getInstance","props","Object","keys","forEach","key","fieldMeta","isKey","ui","column","Column","header","Text","label","demandPopin","minScreenWidth","popinDisplay","addColumn","plugin","getPlugin","type","widget","control","render","error","sap","require","Log","message","rowTemplate","ColumnListItem","cells","bindItems","template","templateShareable","__exports","__esModule"],"sources":["TableLayout.ts"],"sourcesContent":["/**\n * @file TableLayout.ts\n * @description Generates a responsive SAP Fiori Table layout for v2 schema.\n */\n\nimport Table from \"sap/m/Table\";\nimport Column from \"sap/m/Column\";\nimport Text from \"sap/m/Text\";\nimport ColumnListItem from \"sap/m/ColumnListItem\";\nimport Toolbar from \"sap/m/Toolbar\";\nimport Title from \"sap/m/Title\";\nimport ToolbarSpacer from \"sap/m/ToolbarSpacer\";\nimport Button from \"sap/m/Button\";\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\nimport { PluginRegistry } from \"../core/PluginRegistry\";\nimport Control from \"sap/ui/core/Control\";\nimport { IPlugin } from \"../interfaces/IPlugin\";\nimport { IPropertyMetadata } from \"../interfaces/ISchema\";\n\nexport class TableLayout {\n /**\n * Builds a responsive Table, dynamically calculating column priorities.\n */\n public static build(tableMeta: IPropertyMetadata, bindingPath: string = \"meta>/\", tableTitle: string = \"Table\", trackPlugin?: (plugin: IPlugin) => void): Table {\n if (!tableMeta.properties) {\n throw new Error(\"[MetaUI] Table requires an items schema with properties.\");\n }\n\n const parts = bindingPath.split(\">\");\n const actualModelName = parts.length > 1 ? parts[0] : undefined;\n const actualPath = parts.length > 1 ? parts[1] : bindingPath;\n // e.g. \"meta>/Contacts\" -> actualModelName = \"meta\", actualPath = \"/Contacts\"\n\n const table = new Table({\n headerToolbar: new Toolbar({\n content: [\n new Title({ text: tableTitle }),\n new ToolbarSpacer(),\n new Button({\n text: \"Add Row\",\n icon: \"sap-icon://add\",\n press: (oEvent: any) => {\n const btn = oEvent.getSource();\n const tbl = btn.getParent().getParent() as Table;\n const model = tbl.getModel(actualModelName) as JSONModel;\n const info = tbl.getBindingInfo(\"items\");\n if (!info || !info.path) return;\n \n const data = model.getProperty(info.path) || [];\n data.push({}); // append empty row\n model.setProperty(info.path, data);\n }\n })\n ]\n }),\n fixedLayout: false,\n mode: \"Delete\",\n delete: (oEvent: any) => {\n const item = oEvent.getParameter(\"listItem\");\n const path = item.getBindingContext(actualModelName).getPath(); \n const model = item.getModel(actualModelName) as JSONModel;\n \n const splitPaths = path.split(\"/\");\n const index = parseInt(splitPaths.pop() || \"0\", 10);\n let arrayPath = splitPaths.join(\"/\");\n if (arrayPath === \"\") arrayPath = \"/\";\n \n const data = model.getProperty(arrayPath);\n data.splice(index, 1);\n model.setProperty(arrayPath, data);\n }\n });\n\n const templateCells: Control[] = [];\n const registry = PluginRegistry.getInstance();\n const props = tableMeta.properties;\n\n Object.keys(props).forEach((key) => {\n try {\n const fieldMeta = props[key];\n const isKey = !!fieldMeta.ui?.isKey;\n \n const column = new Column({\n header: new Text({ text: fieldMeta.ui?.label || key }),\n demandPopin: !isKey, \n minScreenWidth: isKey ? \"\" : \"Tablet\",\n popinDisplay: \"Inline\"\n });\n table.addColumn(column);\n\n const plugin = registry.getPlugin(fieldMeta.type, fieldMeta.ui?.widget);\n if (trackPlugin) trackPlugin(plugin);\n const control = plugin.render(fieldMeta, key, actualModelName); // No trailing slash for relative bindings\n templateCells.push(control);\n } catch (error) {\n sap.ui.require([\"sap/base/Log\"], (Log: any) => {\n if (Log) Log.error(`[MetaUI] Failed to render column ${key}`, (error as Error).message, \"TableLayout\");\n });\n \n // Add an empty text control as a fallback so the table columns match the cells array length\n templateCells.push(new Text({ text: \"Error\" }));\n }\n });\n\n const rowTemplate = new ColumnListItem({\n cells: templateCells\n });\n\n // V2 Fix: Actually bind the items to the table!\n table.bindItems({\n path: actualPath,\n model: actualModelName,\n template: rowTemplate,\n templateShareable: false\n });\n\n return table;\n }\n}\n"],"mappings":"4NAcSA,EAAcC,EAAA,kBAKhB,MAAMC,EAIT,YAAcC,CAAMC,EAA8BC,EAAsB,SAAUC,EAAqB,QAASC,GAC5G,IAAKH,EAAUI,WAAY,CACvB,MAAM,IAAIC,MAAM,2DACpB,CAEA,MAAMC,EAAQL,EAAYM,MAAM,KAChC,MAAMC,EAAkBF,EAAMG,OAAS,EAAIH,EAAM,GAAKI,UACtD,MAAMC,EAAaL,EAAMG,OAAS,EAAIH,EAAM,GAAKL,EAGjD,MAAMW,EAAQ,IAAIC,EAAM,CACpBC,cAAe,IAAIC,EAAQ,CACvBC,QAAS,CACL,IAAIC,EAAM,CAAEC,KAAMhB,IAClB,IAAIiB,EACJ,IAAIC,EAAO,CACPF,KAAM,UACNG,KAAM,iBACNC,MAAQC,IACJ,MAAMC,EAAMD,EAAOE,YACnB,MAAMC,EAAMF,EAAIG,YAAYA,YAC5B,MAAMC,EAAQF,EAAIG,SAASrB,GAC3B,MAAMsB,EAAOJ,EAAIK,eAAe,SAChC,IAAKD,IAASA,EAAKE,KAAM,OAEzB,MAAMC,EAAOL,EAAMM,YAAYJ,EAAKE,OAAS,GAC7CC,EAAKE,KAAK,CAAC,GACXP,EAAMQ,YAAYN,EAAKE,KAAMC,SAK7CI,YAAa,MACbC,KAAM,SACNC,OAAShB,IACL,MAAMiB,EAAOjB,EAAOkB,aAAa,YACjC,MAAMT,EAAOQ,EAAKE,kBAAkBlC,GAAiBmC,UACrD,MAAMf,EAAQY,EAAKX,SAASrB,GAE5B,MAAMoC,EAAaZ,EAAKzB,MAAM,KAC9B,MAAMsC,EAAQC,SAASF,EAAWG,OAAS,IAAK,IAChD,IAAIC,EAAYJ,EAAWK,KAAK,KAChC,GAAID,IAAc,GAAIA,EAAY,IAElC,MAAMf,EAAOL,EAAMM,YAAYc,GAC/Bf,EAAKiB,OAAOL,EAAO,GACnBjB,EAAMQ,YAAYY,EAAWf,MAIrC,MAAMkB,EAA2B,GACjC,MAAMC,EAAWxD,EAAeyD,cAChC,MAAMC,EAAQtD,EAAUI,WAExBmD,OAAOC,KAAKF,GAAOG,QAASC,IACxB,IACI,MAAMC,EAAYL,EAAMI,GACxB,MAAME,IAAUD,EAAUE,IAAID,MAE9B,MAAME,EAAS,IAAIC,EAAO,CACtBC,OAAQ,IAAIC,EAAK,CAAE/C,KAAMyC,EAAUE,IAAIK,OAASR,IAChDS,aAAcP,EACdQ,eAAgBR,EAAQ,GAAK,SAC7BS,aAAc,WAElBzD,EAAM0D,UAAUR,GAEhB,MAAMS,EAASnB,EAASoB,UAAUb,EAAUc,KAAMd,EAAUE,IAAIa,QAChE,GAAIvE,EAAaA,EAAYoE,GAC7B,MAAMI,EAAUJ,EAAOK,OAAOjB,EAAWD,EAAKlD,GAC9C2C,EAAchB,KAAKwC,EACvB,CAAE,MAAOE,GACLC,IAAIjB,GAAGkB,QAAQ,CAAC,gBAAkBC,IAC9B,GAAIA,EAAKA,EAAIH,MAAM,oCAAoCnB,IAAQmB,EAAgBI,QAAS,iBAI5F9B,EAAchB,KAAK,IAAI8B,EAAK,CAAE/C,KAAM,UACxC,IAGJ,MAAMgE,EAAc,IAAIC,EAAe,CACnCC,MAAOjC,IAIXvC,EAAMyE,UAAU,CACZrD,KAAMrB,EACNiB,MAAOpB,EACP8E,SAAUJ,EACVK,kBAAmB,QAGvB,OAAO3E,CACX,EACH,IAAA4E,EAAA,CAAAC,WAAA,MAAAD,EAAA1F,cAAA,OAAA0F,CAAA","ignoreList":[]}