@siliconst/metaui 1.4.13 → 1.4.17
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.
- package/package.json +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/DynamicHost-dbg.js +50 -3
- package/src/nz/co/siliconst/ui5/metaui/controls/DynamicHost-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/DynamicHost.d.ts +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/DynamicHost.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/DynamicHost.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/DynamicHost.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/DynamicHost.ts +57 -4
- package/src/nz/co/siliconst/ui5/metaui/controls/host/GeneratorHost-dbg.js +44 -2
- package/src/nz/co/siliconst/ui5/metaui/controls/host/GeneratorHost-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/host/GeneratorHost.d.ts +4 -0
- package/src/nz/co/siliconst/ui5/metaui/controls/host/GeneratorHost.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/host/GeneratorHost.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/host/GeneratorHost.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/host/GeneratorHost.ts +51 -4
- package/src/nz/co/siliconst/ui5/metaui/controls/host/delegates/DialogDelegate-dbg.js +42 -5
- package/src/nz/co/siliconst/ui5/metaui/controls/host/delegates/DialogDelegate-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/host/delegates/DialogDelegate.d.ts +9 -2
- package/src/nz/co/siliconst/ui5/metaui/controls/host/delegates/DialogDelegate.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/host/delegates/DialogDelegate.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/host/delegates/DialogDelegate.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/host/delegates/DialogDelegate.ts +44 -5
- package/src/nz/co/siliconst/ui5/metaui/controls/host/delegates/ValidationDelegate-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/host/delegates/ValidationDelegate.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/controls/host/delegates/ValidationDelegate.ts +2 -2
- package/src/nz/co/siliconst/ui5/metaui/core/PluginRegistry-dbg.js +1 -0
- package/src/nz/co/siliconst/ui5/metaui/core/PluginRegistry-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/core/PluginRegistry.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/core/PluginRegistry.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/core/PluginRegistry.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/core/PluginRegistry.ts +1 -0
- package/src/nz/co/siliconst/ui5/metaui/core/SchemaBuilderRegistry-dbg.js +47 -0
- package/src/nz/co/siliconst/ui5/metaui/core/SchemaBuilderRegistry-dbg.js.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/core/SchemaBuilderRegistry.d.ts +23 -0
- package/src/nz/co/siliconst/ui5/metaui/core/SchemaBuilderRegistry.d.ts.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/core/SchemaBuilderRegistry.js +2 -0
- package/src/nz/co/siliconst/ui5/metaui/core/SchemaBuilderRegistry.js.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/core/SchemaBuilderRegistry.ts +45 -0
- package/src/nz/co/siliconst/ui5/metaui/core/SchemaNormalizer-dbg.js +17 -0
- package/src/nz/co/siliconst/ui5/metaui/core/SchemaNormalizer-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/core/SchemaNormalizer.d.ts +10 -1
- package/src/nz/co/siliconst/ui5/metaui/core/SchemaNormalizer.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/core/SchemaNormalizer.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/core/SchemaNormalizer.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/core/SchemaNormalizer.ts +19 -1
- package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchema-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchema.d.ts +7 -0
- package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchema.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchema.ts +9 -0
- package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchemaBuilderPlugin-dbg.js +2 -0
- package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchemaBuilderPlugin-dbg.js.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchemaBuilderPlugin.d.ts +23 -0
- package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchemaBuilderPlugin.d.ts.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchemaBuilderPlugin.js +2 -0
- package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchemaBuilderPlugin.js.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/interfaces/ISchemaBuilderPlugin.ts +23 -0
- package/src/nz/co/siliconst/ui5/metaui/layouts/FormLayout-dbg.js +6 -1
- package/src/nz/co/siliconst/ui5/metaui/layouts/FormLayout-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/layouts/FormLayout.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/layouts/FormLayout.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/layouts/FormLayout.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/layouts/FormLayout.ts +6 -1
- package/src/nz/co/siliconst/ui5/metaui/library-preload.js +29 -20
- package/src/nz/co/siliconst/ui5/metaui/library-preload.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/BasePlugin-dbg.js +3 -20
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/BasePlugin-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/BasePlugin.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/BasePlugin.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/BasePlugin.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/BasePlugin.ts +3 -3
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/BooleanPlugin-dbg.js +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/BooleanPlugin-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/BooleanPlugin.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/BooleanPlugin.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/BooleanPlugin.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/BooleanPlugin.ts +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DatePlugin-dbg.js +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DatePlugin-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DatePlugin.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DatePlugin.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DatePlugin.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DatePlugin.ts +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DateTimePlugin-dbg.js +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DateTimePlugin-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DateTimePlugin.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DateTimePlugin.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DateTimePlugin.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DateTimePlugin.ts +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DropdownPlugin-dbg.js +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DropdownPlugin-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DropdownPlugin.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DropdownPlugin.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DropdownPlugin.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/DropdownPlugin.ts +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/FileUploaderPlugin-dbg.js +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/FileUploaderPlugin-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/FileUploaderPlugin.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/FileUploaderPlugin.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/FileUploaderPlugin.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/FileUploaderPlugin.ts +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MessageStripPlugin-dbg.js +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MessageStripPlugin-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MessageStripPlugin.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MessageStripPlugin.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MessageStripPlugin.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MessageStripPlugin.ts +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MultiInputPlugin-dbg.js +30 -17
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MultiInputPlugin-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MultiInputPlugin.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MultiInputPlugin.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MultiInputPlugin.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MultiInputPlugin.ts +33 -15
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MultiSelectPlugin-dbg.js +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MultiSelectPlugin-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MultiSelectPlugin.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MultiSelectPlugin.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MultiSelectPlugin.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/MultiSelectPlugin.ts +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/NumberPlugin-dbg.js +35 -11
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/NumberPlugin-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/NumberPlugin.d.ts +4 -4
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/NumberPlugin.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/NumberPlugin.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/NumberPlugin.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/NumberPlugin.ts +38 -14
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/RatingIndicatorPlugin-dbg.js +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/RatingIndicatorPlugin-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/RatingIndicatorPlugin.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/RatingIndicatorPlugin.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/RatingIndicatorPlugin.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/RatingIndicatorPlugin.ts +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/SliderPlugin-dbg.js +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/SliderPlugin-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/SliderPlugin.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/SliderPlugin.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/SliderPlugin.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/SliderPlugin.ts +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/StepInputPlugin-dbg.js +79 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/StepInputPlugin-dbg.js.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/StepInputPlugin.d.ts +35 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/StepInputPlugin.d.ts.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/StepInputPlugin.js +2 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/StepInputPlugin.js.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/StepInputPlugin.ts +80 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/SwitchPlugin-dbg.js +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/SwitchPlugin-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/SwitchPlugin.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/SwitchPlugin.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/SwitchPlugin.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/SwitchPlugin.ts +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/TimePlugin-dbg.js +1 -0
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/TimePlugin-dbg.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/TimePlugin.d.ts.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/TimePlugin.js +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/TimePlugin.js.map +1 -1
- package/src/nz/co/siliconst/ui5/metaui/plugins/controls/TimePlugin.ts +1 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerBuilder-dbg.js +226 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerBuilder-dbg.js.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerBuilder.d.ts +63 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerBuilder.d.ts.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerBuilder.js +2 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerBuilder.js.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerBuilder.ts +233 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerRefResolver-dbg.js +43 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerRefResolver-dbg.js.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerRefResolver.d.ts +15 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerRefResolver.d.ts.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerRefResolver.js +2 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerRefResolver.js.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerRefResolver.ts +37 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerTypeMapper-dbg.js +37 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerTypeMapper-dbg.js.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerTypeMapper.d.ts +18 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerTypeMapper.d.ts.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerTypeMapper.js +2 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerTypeMapper.js.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerTypeMapper.ts +28 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerUIMapper-dbg.js +84 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerUIMapper-dbg.js.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerUIMapper.d.ts +27 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerUIMapper.d.ts.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerUIMapper.js +2 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerUIMapper.js.map +1 -0
- package/src/nz/co/siliconst/ui5/metaui/swagger/SwaggerUIMapper.ts +80 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"library-preload.js","sections":[{"offset":{"line":1,"column":0},"map":{"version":3,"names":["BaseHardwareControlRenderer","_interopRequireDefault","__BaseHardwareControlRenderer","BaseHardwareControl","Control","extend","renderer","metadata","properties","value","type","defaultValue","schemaMetadata","readOnly","aggregations","_content","multiple","visibility","events","capture","parameters","setValueAndFire","_setValueAndFire","val","this","setProperty","fireEvent","renderContent","_renderContent","rm","control"],"sources":["BaseHardwareControl.ts"],"sourcesContent":["/**\n * @file BaseHardwareControl.ts\n * @description Foundational UI5 Custom Control for hardware plugins.\n * Exposes a standard 'value' property for pure two-way data binding.\n * \n */\n\nimport Control from \"sap/ui/core/Control\";\nimport RenderManager from \"sap/ui/core/RenderManager\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport BaseHardwareControlRenderer from \"./BaseHardwareControlRenderer\";\n\n/**\n * @namespace nz.co.siliconst.ui5.metaui.controls\n */\nexport default class BaseHardwareControl extends Control {\n static readonly metadata = {\n properties: {\n /** The raw data value. Two-way bound to the model. */\n value: { type: \"any\", defaultValue: null },\n /** The schema metadata for rendering dynamic hints (like labels/readOnly) */\n schemaMetadata: { type: \"object\", defaultValue: null },\n /** Indicates if the control should be in a read-only state */\n readOnly: { type: \"boolean\", defaultValue: false }\n },\n aggregations: {\n _content: { type: \"sap.m.VBox\", multiple: false, visibility: \"hidden\" }\n },\n events: {\n /** Fired when the hardware successfully captures a value */\n capture: {\n parameters: {\n value: { type: \"any\" }\n }\n }\n }\n };\n\n /**\n * Updates the bound value and fires the capture event.\n */\n public setValueAndFire(val: unknown): void {\n this.setProperty(\"value\", val, true); // true to suppress re-rendering if desired, but we want the binding to update\n this.fireEvent(\"capture\", { value: val });\n }\n\n /**\n * Common renderer for all hardware controls\n */\n static readonly renderer = BaseHardwareControlRenderer;\n\n /**\n * Abstract hook for subclasses to render their specific DOM/Controls.\n */\n public renderContent(rm: RenderManager, control: BaseHardwareControl): void {\n // To be overridden by hardware implementations\n }\n}\n"],"mappings":"AAAA,sPAUOA,EAA2BC,EAAAC,GAElC,MAGqBC,EAA4BC,EAAOC,OAAA,2DAkCpCC,SAAWN,EAjCXO,SAAW,CACvBC,WAAY,CAERC,MAAO,CAAEC,KAAM,MAAOC,aAAc,MAEpCC,eAAgB,CAAEF,KAAM,SAAUC,aAAc,MAEhDE,SAAU,CAAEH,KAAM,UAAWC,aAAc,QAE/CG,aAAc,CACVC,SAAU,CAAEL,KAAM,aAAcM,SAAU,MAAOC,WAAY,WAEjEC,OAAQ,CAEJC,QAAS,CACLC,WAAY,CACRX,MAAO,CAAEC,KAAM,WASxBW,gBAAe,SAAAC,EAACC,GACnBC,KAAKC,YAAY,QAASF,EAAK,MAC/BC,KAAKE,UAAU,UAAW,CAAEjB,MAAOc,GACvC,EAUOI,cAAa,SAAAC,EAACC,EAAmBC,GACpC,IACH,OAzCgB3B,CAAmB","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":2,"column":0},"map":{"version":3,"names":["__exports","apiVersion","render","rm","control","openStart","class","openEnd","content","getAggregation","renderControl","renderContent","close"],"sources":["BaseHardwareControlRenderer.ts"],"sourcesContent":["/**\n * @file BaseHardwareControlRenderer.ts\n * @description Standard renderer for all MetaUI hardware controls.\n * \n * @namespace nz.co.siliconst.ui5.metaui.controls\n */\nimport RenderManager from \"sap/ui/core/RenderManager\";\nimport BaseHardwareControl from \"./BaseHardwareControl\";\n\nexport default {\n apiVersion: 2,\n render: function (rm: RenderManager, control: BaseHardwareControl) {\n rm.openStart(\"div\", control);\n rm.class(\"sapUiSmallMarginBottom\");\n rm.openEnd();\n \n const content = control.getAggregation(\"_content\") as sap.ui.core.Control;\n if (content) {\n rm.renderControl(content);\n }\n \n if (typeof control.renderContent === \"function\") {\n control.renderContent(rm, control);\n }\n \n rm.close(\"div\");\n }\n};\n"],"mappings":"AAAA,+GAAA,IAAAA,EASe,CACXC,WAAY,EACZC,OAAQ,SAAUC,EAAmBC,GACjCD,EAAGE,UAAU,MAAOD,GACpBD,EAAGG,MAAM,0BACTH,EAAGI,UAEH,MAAMC,EAAUJ,EAAQK,eAAe,YACvC,GAAID,EAAS,CACTL,EAAGO,cAAcF,EACrB,CAEA,UAAWJ,EAAQO,gBAAkB,WAAY,CAC7CP,EAAQO,cAAcR,EAAIC,EAC9B,CAEAD,EAAGS,MAAM,MACb,GACH,OAAAZ,CAAA","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":3,"column":0},"map":{"version":3,"names":["BaseHardwareControl","_interopRequireDefault","__BaseHardwareControl","Logger","___utils_Logger","CameraControl","static","properties","events","videoEl","mediaStream","init","super","this","videoHtml","HTML","content","afterRendering","onVideoRendered","bind","addStyleClass","previewImage","Image","width","visible","startBtn","Button","icon","text","press","handleStartCameraPress","captureBtn","captureImage","retakeBtn","retakeImage","vBox","VBox","items","setAggregation","domRef","getDomRef","val","getValue","startsWith","showPreview","getVisible","startCamera","setVisible","style","display","navigator","mediaDevices","getUserMedia","video","facingMode","srcObject","err","error","message","MessageToast","show","stopCamera","getTracks","forEach","track","stop","canvas","document","createElement","videoWidth","height","videoHeight","ctx","getContext","drawImage","dataUrl","toDataURL","setValueAndFire","setSrc","setValue","value","exit"],"sources":["CameraControl.ts"],"sourcesContent":["import BaseHardwareControl from \"./BaseHardwareControl\";\nimport Button from \"sap/m/Button\";\nimport VBox from \"sap/m/VBox\";\nimport HTML from \"sap/ui/core/HTML\";\nimport MessageToast from \"sap/m/MessageToast\";\nimport Image from \"sap/m/Image\";\nimport { Logger } from \"../utils/Logger\";\n\n/**\n * CameraControl\n * Provides a live video feed to capture photos.\n */\nexport default class CameraControl extends BaseHardwareControl {\n static readonly renderer = \"nz.co.siliconst.ui5.metaui.controls.BaseHardwareControlRenderer\";\n static readonly metadata = {\n properties: {},\n events: {}\n };\n\n private startBtn!: Button;\n private vBox!: VBox;\n private captureBtn!: Button;\n private retakeBtn!: Button;\n private videoHtml!: HTML;\n private previewImage!: Image;\n \n private videoEl: HTMLVideoElement | null = null;\n private mediaStream: MediaStream | null = null;\n\n /**\n * Initializes the control and builds the internal camera UI.\n */\n public init(): void {\n super.init();\n\n this.videoHtml = new HTML({\n content: \"<video width='400' height='300' autoplay playsinline style='background-color: #000; display: none;'></video>\",\n afterRendering: this.onVideoRendered.bind(this)\n }).addStyleClass(\"sapUiSmallMarginBottom\");\n\n this.previewImage = new Image({\n width: \"400px\",\n visible: false\n }).addStyleClass(\"sapUiSmallMarginBottom\");\n\n this.startBtn = new Button({\n icon: \"sap-icon://video\",\n text: \"Start Camera\",\n press: this.handleStartCameraPress.bind(this)\n });\n\n this.captureBtn = new Button({\n icon: \"sap-icon://camera\",\n text: \"Capture\",\n visible: false,\n press: this.captureImage.bind(this)\n });\n\n this.retakeBtn = new Button({\n icon: \"sap-icon://undo\",\n text: \"Retake\",\n visible: false,\n press: this.retakeImage.bind(this)\n });\n\n this.vBox = new VBox({\n items: [this.videoHtml, this.previewImage, this.startBtn, this.captureBtn, this.retakeBtn]\n });\n\n this.setAggregation(\"_content\", this.vBox);\n }\n\n private async onVideoRendered(): void {\n const domRef = this.videoHtml.getDomRef() as HTMLElement;\n if (!domRef) return;\n \n this.videoEl = domRef as HTMLVideoElement;\n \n const val = this.getValue();\n if (val && typeof val === \"string\" && val.startsWith(\"data:image\")) {\n this.showPreview(val);\n } else if (this.captureBtn.getVisible() && this.videoHtml.getVisible()) {\n this.startCamera();\n }\n }\n\n private handleStartCameraPress(): void {\n this.startCamera();\n this.startBtn.setVisible(false);\n this.captureBtn.setVisible(true);\n if (this.videoEl) {\n this.videoEl.style.display = \"block\";\n }\n }\n\n private async startCamera(): Promise<void> {\n try {\n this.mediaStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: \"environment\" } });\n if (this.videoEl) {\n this.videoEl.srcObject = this.mediaStream;\n }\n } catch (err) {\n Logger.error(\"Camera access denied or unavailable\", (err as Error).message, \"CameraControl\");\n MessageToast.show(\"Camera access denied or unavailable.\");\n }\n }\n\n private stopCamera(): void {\n if (this.mediaStream) {\n this.mediaStream.getTracks().forEach(track => track.stop());\n this.mediaStream = null;\n }\n }\n\n private captureImage(): void {\n if (!this.videoEl) return;\n \n const canvas = document.createElement(\"canvas\");\n canvas.width = this.videoEl.videoWidth || 400;\n canvas.height = this.videoEl.videoHeight || 300;\n \n const ctx = canvas.getContext(\"2d\");\n if (ctx) {\n ctx.drawImage(this.videoEl, 0, 0, canvas.width, canvas.height);\n const dataUrl = canvas.toDataURL(\"image/jpeg\", 0.8);\n this.setValueAndFire(dataUrl);\n this.showPreview(dataUrl);\n MessageToast.show(\"Image captured successfully.\");\n }\n }\n\n private retakeImage(): void {\n this.setValueAndFire(null);\n this.previewImage.setVisible(false);\n this.videoHtml.setVisible(true);\n this.captureBtn.setVisible(true);\n this.retakeBtn.setVisible(false);\n \n // startCamera is now handled safely by onVideoRendered hook\n }\n\n private showPreview(dataUrl: string): void {\n this.stopCamera();\n this.videoHtml.setVisible(false);\n this.previewImage.setSrc(dataUrl);\n this.previewImage.setVisible(true);\n this.captureBtn.setVisible(false);\n this.retakeBtn.setVisible(true);\n }\n\n /**\n * Sets the value of the control programmatically.\n * @param value The base64 data URL string representing the image.\n */\n public setValue(value: unknown): this {\n super.setValue(value);\n if (value && typeof value === \"string\" && value.startsWith(\"data:image\")) {\n this.showPreview(value);\n } else if (!value) {\n // Only retake if we were showing a preview\n if (this.previewImage.getVisible()) {\n this.retakeImage();\n }\n }\n return this;\n }\n\n /**\n * Cleans up the hardware streams when the control is destroyed.\n */\n public exit(): void {\n this.stopCamera();\n super.exit();\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":4,"column":0},"map":{"version":3,"names":["GeneratorHost","_interopRequireDefault","__GeneratorHost","Logger","___utils_Logger","ODataDelegate","___host_delegates_ODataDelegate","DynamicHost","Control","extend","constructor","prototype","apply","this","arguments","odataDelegate","_innerHost","_initializedInner","renderer","apiVersion","render","rm","control","openStart","style","openEnd","content","getAggregation","renderControl","close","metadata","properties","schemaDefinition","type","defaultValue","data","bindable","dataJson","liveUpdate","isValid","useMessageManager","modelName","debugMode","editable","aggregations","_content","multiple","visibility","events","beforeSubmit","parameters","payload","addError","preventDefault","submit","payloadJson","cancel","fieldChange","fieldPath","value","validationStateChanged","validationError","message","validationSuccess","error","exception","initODataDelegate","_initODataDelegate","getBindingInfo","dataBinding","path","oContext","getBindingContext","debug","getPath","requestObject","syncToEngine","Object","keys","setBindingContext","_setBindingContext","sModelName","Control.prototype.setBindingContext.call","bindElement","_bindElement","vPath","mParameters","Control.prototype.bindElement.call","model","undefined","oBinding","getElementBinding","attachChange","onBeforeRendering","_onBeforeRendering","schema","getProperty","hasSchema","length","hasData","props","getMetadata","getProperties","propName","val","Control.prototype.getProperty.call","setProperty","setAggregation","getEvents","eventName","attachEvent","oEvent","params","getParameters","isLive","Control.prototype.setProperty.call","str","JSON","stringify","handleFieldChange","fireEvent","_setProperty","propertyName","suppressInvalidate","openInDialog","_openInDialog","title","submitButtonText","cancelButtonText","dialogWidth","parentView","triggerSubmit","_triggerSubmit","addCustomError","_addCustomError","clearCustomError","_clearCustomError","_getProperty"],"sources":["DynamicHost.ts"],"sourcesContent":["import Control from \"sap/ui/core/Control\";\nimport RenderManager from \"sap/ui/core/RenderManager\";\nimport GeneratorHost from \"./host/GeneratorHost\";\nimport { Logger } from \"../utils/Logger\";\nimport { ODataDelegate } from \"./host/delegates/ODataDelegate\";\nimport ODataV4Context from \"sap/ui/model/odata/v4/Context\";\n\n/**\n * A transparent wrapper control (Facade) that automatically chooses between Explicit Schema Mode \n * and Inference Mode based on the presence of a 'schemaDefinition'.\n * \n * This maintains total architectural separation of the modes without forcing developers to \n * use different XML tags.\n * \n * @namespace nz.co.siliconst.ui5.metaui.controls\n */\nexport default class DynamicHost extends Control {\n private odataDelegate: ODataDelegate | null = null;\n\n static readonly metadata = {\n properties: {\n schemaDefinition: { type: \"any\", defaultValue: null },\n data: { type: \"object\", defaultValue: null, bindable: \"bindable\" },\n dataJson: { type: \"string\", defaultValue: null, bindable: \"bindable\" },\n liveUpdate: { type: \"boolean\", defaultValue: false },\n isValid: { type: \"boolean\", defaultValue: true },\n useMessageManager: { type: \"boolean\", defaultValue: false },\n modelName: { type: \"string\", defaultValue: \"meta\" },\n debugMode: { type: \"boolean\", defaultValue: false },\n editable: { type: \"boolean\", defaultValue: true }\n },\n aggregations: {\n _content: { type: \"sap.ui.core.Control\", multiple: false, visibility: \"hidden\" }\n },\n events: {\n beforeSubmit: {\n parameters: {\n payload: { type: \"object\" },\n addError: { type: \"function\" },\n preventDefault: { type: \"function\" }\n }\n },\n submit: {\n parameters: {\n payload: { type: \"object\" },\n payloadJson: { type: \"string\" }\n }\n },\n cancel: {},\n fieldChange: {\n parameters: {\n fieldPath: { type: \"string\" },\n value: { type: \"any\" },\n payload: { type: \"object\" },\n isValid: { type: \"boolean\" }\n }\n },\n validationStateChanged: { parameters: { isValid: { type: \"boolean\" } } },\n validationError: { parameters: { fieldPath: { type: \"string\" }, message: { type: \"string\" } } },\n validationSuccess: { parameters: { fieldPath: { type: \"string\" } } },\n error: { parameters: { message: { type: \"string\" }, exception: { type: \"object\" } } }\n }\n };\n\n static renderer = {\n apiVersion: 2,\n render(rm: RenderManager, control: DynamicHost) {\n rm.openStart(\"div\", control);\n rm.style(\"width\", \"100%\");\n rm.style(\"height\", \"100%\");\n rm.openEnd();\n\n const content = control.getAggregation(\"_content\") as Control;\n if (content) {\n rm.renderControl(content);\n }\n\n rm.close(\"div\");\n }\n };\n\n /**\n * Internal reference to the generated inner host instance.\n * @private\n */\n private _innerHost: GeneratorHost | null = null;\n \n /**\n * Flag indicating if the inner host has been initialized.\n * @private\n */\n private _initializedInner: boolean = false;\n\n /**\n * Initializes the OData Delegate if an OData context is detected.\n * This allows DynamicHost to seamlessly synchronize metadata and properties from an OData model.\n * @private\n */\n private initODataDelegate(): void {\n if (!this.odataDelegate) {\n // Guard: If the user explicitly bound dataJson, do not steal the context.\n if (this.getBindingInfo(\"dataJson\")) {\n return;\n }\n\n // Guard: If the user explicitly bound 'data' to a specific property path, do not steal the context.\n const dataBinding = this.getBindingInfo(\"data\") as any;\n if (dataBinding && dataBinding.path && dataBinding.path !== \"\") {\n return;\n }\n\n const oContext = this.getBindingContext(\"odata\") || this.getBindingContext();\n if (oContext) {\n Logger.debug(\"[MetaUI DynamicHost]\", `Context found for delegate initialization: ${oContext.getPath()}`, \"DynamicHost\");\n if (oContext && (oContext as ODataV4Context).requestObject && typeof (oContext as ODataV4Context).requestObject === \"function\") {\n Logger.debug(\"[MetaUI DynamicHost]\", `Context supports requestObject/getObject. Instantiating ODataDelegate.`, \"DynamicHost\");\n this.odataDelegate = new ODataDelegate(this, oContext as ODataV4Context);\n this.odataDelegate.syncToEngine();\n } else {\n Logger.debug(\"[MetaUI DynamicHost]\", `Context does NOT support requestObject/getObject! Keys: ${Object.keys(oContext)}`, \"DynamicHost\");\n }\n }\n }\n }\n\n /**\n * Standard UI5 method override.\n * Sets the binding context for the control and attempts to initialize the OData delegate\n * if the context points to an OData model.\n * \n * @param {sap.ui.model.Context | null | undefined} oContext The binding context object\n * @param {string} [sModelName] Optional model name\n * @returns {this} The control instance for chaining\n */\n public setBindingContext(oContext: sap.ui.model.Context | null | undefined, sModelName?: string): this {\n super.setBindingContext(oContext, sModelName);\n this.initODataDelegate();\n return this;\n }\n\n /**\n * Standard UI5 method override.\n * Binds the element to the given path and attaches a change listener to re-evaluate\n * the OData delegate when the element binding resolves.\n * \n * @param {string | Record<string, unknown>} vPath The binding path or configuration object\n * @param {object} [mParameters] Optional mapping parameters\n * @returns {this} Reference to this instance for chaining\n */\n public bindElement(vPath: string | Record<string, unknown>, mParameters?: object): this {\n super.bindElement(vPath, mParameters);\n const sModelName = typeof vPath === \"object\" ? vPath.model : undefined;\n const oBinding = this.getElementBinding(sModelName);\n if (oBinding) {\n oBinding.attachChange(() => {\n this.initODataDelegate();\n });\n }\n return this;\n }\n\n /**\n * Standard UI5 Lifecycle Hook.\n * Evaluates the initial properties and spawns the GeneratorHost.\n * It handles the complex lifecycle task of copying all bindings, raw properties, and event listeners \n * down to the inner host perfectly transparently.\n */\n public onBeforeRendering(): void {\n Logger.debug(\"[MetaUI DynamicHost]\", `onBeforeRendering called. _initializedInner: ${this._initializedInner}`, \"DynamicHost\");\n\n this.initODataDelegate();\n\n if (!this._initializedInner) {\n const schema = this.getProperty(\"schemaDefinition\");\n const dataJson = this.getProperty(\"dataJson\");\n const data = this.getProperty(\"data\");\n\n let hasSchema = !!schema;\n if (hasSchema && typeof schema === \"object\" && Object.keys(schema).length === 0) {\n hasSchema = false; // Treat empty object as no schema\n }\n \n const hasData = !!dataJson || !!data;\n\n Logger.debug(\"[MetaUI DynamicHost]\", `Evaluating boot. hasSchema: ${hasSchema}, hasData: ${hasData}`, \"DynamicHost\");\n\n // Only boot if we have either a schema or some data to infer from\n if (hasSchema || hasData) {\n if (this.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI DynamicHost]\", `Booting inner host. hasSchema: ${hasSchema}, hasData: ${hasData}`, \"DynamicHost\");\n }\n // The architectural Facade router logic:\n // We've simplified this! We no longer use HostFactory or separate subclasses.\n // GeneratorHost is fully capable of inferring the schema if none is provided.\n this._innerHost = new GeneratorHost();\n\n // 1. Forward all static values to the spawned host BEFORE mounting.\n // Since we no longer use bindProperty, it's perfectly safe to set raw properties before mounting.\n const props = this.getMetadata().getProperties();\n for (const propName in props) {\n const val = super.getProperty(propName);\n if (val !== null && val !== undefined) {\n this._innerHost.setProperty(propName, val);\n }\n }\n\n // 2. Mount so it inherits models and triggers lifecycle.\n this.setAggregation(\"_content\", this._innerHost);\n\n // 3. Forward all event subscriptions.\n // By proxying the events upwards, the developer can subscribe to `<meta:DynamicHost submit=\"...\">` \n // and perfectly receive the inner host's submission event.\n const events = this.getMetadata().getEvents();\n for (const eventName in events) {\n this._innerHost.attachEvent(eventName, (oEvent: sap.ui.base.Event) => {\n // Natively push updated payload out to any bound Fiori Element properties.\n // Using super.setProperty prevents an infinite loop back down to _innerHost.\n if (eventName === \"submit\" || eventName === \"fieldChange\") {\n const params = oEvent.getParameters();\n if (params.payload) {\n const isLive = this.getProperty(\"liveUpdate\") === true;\n if (eventName === \"submit\" || isLive) {\n super.setProperty(\"data\", params.payload, true);\n\n const str = params.payloadJson || JSON.stringify(params.payload, null, 2);\n super.setProperty(\"dataJson\", str, true);\n }\n }\n if (eventName === \"fieldChange\" && this.odataDelegate) {\n this.odataDelegate.handleFieldChange(params.fieldPath, params.value);\n }\n }\n this.fireEvent(eventName, oEvent.getParameters());\n });\n }\n\n this._initializedInner = true;\n }\n }\n }\n\n /**\n * Overrides standard UI5 setProperty to act as a transparent proxy.\n * When a property is updated on the wrapper (either programmatically or via a binding update),\n * it instantly mirrors that value down to the inner instantiated host.\n */\n public setProperty(propertyName: string, value: unknown, suppressInvalidate?: boolean): this {\n if (propertyName === \"data\" || propertyName === \"dataJson\" || propertyName === \"schemaDefinition\") {\n if (this.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI DynamicHost]\", `Wrapper received setProperty: ${propertyName}`, \"DynamicHost\");\n }\n }\n super.setProperty(propertyName, value, suppressInvalidate);\n if (this._innerHost) {\n this._innerHost.setProperty(propertyName, value, suppressInvalidate);\n } else if (propertyName === \"data\" || propertyName === \"dataJson\" || propertyName === \"schemaDefinition\") {\n if (this.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI DynamicHost]\", `_innerHost not yet initialized when ${propertyName} was set. Booting will happen on next render.`, \"DynamicHost\");\n }\n }\n return this;\n }\n\n\n\n\n\n /**\n * Programmatic API support. Routes dialog commands down to the spawned inner host.\n * If the inner host has not booted yet, it forces initialization immediately.\n * \n * @param {string} [title=\"Form\"] The title of the dialog\n * @param {string} [submitButtonText=\"OK\"] The text for the primary action button\n * @param {string} [cancelButtonText=\"Cancel\"] The text for the cancel button\n * @param {string} [dialogWidth=\"800px\"] The width of the dialog\n * @param {sap.ui.core.Control} [parentView] The parent view to attach the dialog to for model inheritance.\n */\n public openInDialog(title?: string, submitButtonText?: string, cancelButtonText?: string, dialogWidth?: string, parentView?: Control): void {\n if (!this._innerHost) {\n this.onBeforeRendering(); // Force init if they bypassed UI5 rendering\n }\n this._innerHost?.openInDialog(title, submitButtonText, cancelButtonText, dialogWidth, parentView);\n }\n\n /**\n * Proxies submission triggering down to the instantiated generator host.\n * Evaluates the internal Engine validation suite and returns true if structurally sound.\n * \n * @returns {boolean} True if the internal payload passes schema validation, false otherwise.\n */\n public triggerSubmit(): boolean {\n if (!this._innerHost) {\n return false;\n }\n return this._innerHost.triggerSubmit();\n }\n\n /**\n * Injects a custom error message onto a specific field.\n * Useful for injecting custom backend validation errors.\n * \n * @param {string} fieldPath The schema key path to target.\n * @param {string} message The custom error message to display.\n */\n public addCustomError(fieldPath: string, message: string): void {\n if (this._innerHost && typeof (this._innerHost as any).addCustomError === \"function\") {\n (this._innerHost as any).addCustomError(fieldPath, message);\n }\n }\n\n /**\n * Clears a custom error message from a specific field.\n * \n * @param {string} fieldPath The schema key path to target.\n */\n public clearCustomError(fieldPath: string): void {\n if (this._innerHost && typeof (this._innerHost as any).clearCustomError === \"function\") {\n (this._innerHost as any).clearCustomError(fieldPath);\n }\n }\n\n /**\n * Overrides standard UI5 getProperty to transparently pull extracted data from the inner host.\n * Ensures that querying the DynamicHost facade for `data` always yields the freshest payload.\n * \n * @param {string} propertyName The name of the property to retrieve\n * @returns {unknown} The property value\n */\n public getProperty(propertyName: string): unknown {\n if (propertyName === \"outputData\") {\n propertyName = \"data\"; // Forward deprecated outputData to data\n }\n if (this._innerHost && (propertyName === \"data\" || propertyName === \"dataJson\")) {\n return this._innerHost.getProperty(propertyName);\n }\n return super.getProperty(propertyName);\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":5,"column":0},"map":{"version":3,"names":["BaseHardwareControl","_interopRequireDefault","__BaseHardwareControl","BaseHardwareControlRenderer","__BaseHardwareControlRenderer","GeolocationControl","static","aggregations","_content","type","multiple","visibility","init","super","this","locationBtn","Button","icon","text","press","getLocation","bind","resultInput","Input","editable","visible","vBox","VBox","items","setAggregation","onBeforeRendering","metadata","getProperty","ui","label","setText","readOnly","setEnabled","currentVal","setValue","setVisible","navigator","geolocation","MessageToast","show","getCurrentPosition","position","locStr","coords","latitude","longitude","setValueAndFire","error","__ui5_require_async","then","Logger","message"],"sources":["GeolocationControl.ts"],"sourcesContent":["/**\n * @file GeolocationControl.ts\n * @description Native UI5 Control for GPS capture.\n * \n * @namespace nz.co.siliconst.ui5.metaui.controls\n */\nimport BaseHardwareControl from \"./BaseHardwareControl\";\nimport BaseHardwareControlRenderer from \"./BaseHardwareControlRenderer\";\nimport RenderManager from \"sap/ui/core/RenderManager\";\nimport Button from \"sap/m/Button\";\nimport Input from \"sap/m/Input\";\nimport VBox from \"sap/m/VBox\";\nimport MessageToast from \"sap/m/MessageToast\";\n\nexport default class GeolocationControl extends BaseHardwareControl {\n private vBox: VBox;\n private locationBtn: Button;\n private resultInput: Input;\n\n static readonly renderer = BaseHardwareControlRenderer;\n\n static readonly metadata = {\n aggregations: {\n _content: { type: \"sap.m.VBox\", multiple: false, visibility: \"hidden\" }\n }\n };\n\n /**\n * Initializes the control and builds the internal UI components.\n */\n public init(): void {\n super.init();\n\n this.locationBtn = new Button({\n icon: \"sap-icon://map\",\n text: \"Get Location\",\n press: this.getLocation.bind(this)\n });\n\n this.resultInput = new Input({\n editable: false,\n visible: false\n });\n\n this.vBox = new VBox({\n items: [this.locationBtn, this.resultInput]\n });\n\n this.setAggregation(\"_content\", this.vBox);\n }\n\n /**\n * Lifecycle hook called before the control is rendered to the DOM.\n * Updates button state and sets any existing values.\n */\n public onBeforeRendering(): void {\n const metadata = this.getProperty(\"schemaMetadata\");\n if (metadata && metadata.ui && metadata.ui.label) {\n this.locationBtn.setText(metadata.ui.label);\n }\n\n const readOnly = this.getProperty(\"readOnly\");\n this.locationBtn.setEnabled(!readOnly);\n\n const currentVal = this.getProperty(\"value\");\n if (currentVal) {\n this.resultInput.setValue(currentVal as string);\n this.resultInput.setVisible(true);\n }\n }\n\n private getLocation(): void {\n if (!navigator.geolocation) {\n MessageToast.show(\"Geolocation is not supported by your browser\");\n return;\n }\n\n navigator.geolocation.getCurrentPosition(\n (position) => {\n const locStr = `${position.coords.latitude}, ${position.coords.longitude}`;\n this.resultInput.setValue(locStr);\n this.resultInput.setVisible(true);\n this.setValueAndFire(locStr);\n MessageToast.show(\"Location acquired.\");\n },\n (error) => {\n import(\"../utils/Logger\").then(({ Logger }) => {\n Logger.error(\"[MetaUI] Geolocation failed or denied\", error.message, \"GeolocationControl\");\n });\n MessageToast.show(\"Unable to retrieve your location\");\n }\n );\n }\n\n\n}\n"],"mappings":"AAAA,ojBAAA,MAMOA,EAAmBC,EAAAC,GAAA,MACnBC,EAA2BF,EAAAG,GAOnB,MAAMC,UAA2BL,EAK5CM,gBAA2BH,EAE3BG,gBAA2B,CACvBC,aAAc,CACVC,SAAU,CAAEC,KAAM,aAAcC,SAAU,MAAOC,WAAY,YAO9DC,OACHC,MAAMD,OAENE,KAAKC,YAAc,IAAIC,EAAO,CAC1BC,KAAM,iBACNC,KAAM,eACNC,MAAOL,KAAKM,YAAYC,KAAKP,QAGjCA,KAAKQ,YAAc,IAAIC,EAAM,CACzBC,SAAU,MACVC,QAAS,QAGbX,KAAKY,KAAO,IAAIC,EAAK,CACjBC,MAAO,CAACd,KAAKC,YAAaD,KAAKQ,eAGnCR,KAAKe,eAAe,WAAYf,KAAKY,KACzC,CAMOI,oBACH,MAAMC,EAAWjB,KAAKkB,YAAY,kBAClC,GAAID,GAAYA,EAASE,IAAMF,EAASE,GAAGC,MAAO,CAC9CpB,KAAKC,YAAYoB,QAAQJ,EAASE,GAAGC,MACzC,CAEA,MAAME,EAAWtB,KAAKkB,YAAY,YAClClB,KAAKC,YAAYsB,YAAYD,GAE7B,MAAME,EAAaxB,KAAKkB,YAAY,SACpC,GAAIM,EAAY,CACZxB,KAAKQ,YAAYiB,SAASD,GAC1BxB,KAAKQ,YAAYkB,WAAW,KAChC,CACJ,CAEQpB,cACJ,IAAKqB,UAAUC,YAAa,CACxBC,EAAaC,KAAK,gDAClB,MACJ,CAEAH,UAAUC,YAAYG,mBACjBC,IACG,MAAMC,EAAS,GAAGD,EAASE,OAAOC,aAAaH,EAASE,OAAOE,YAC/DpC,KAAKQ,YAAYiB,SAASQ,GAC1BjC,KAAKQ,YAAYkB,WAAW,MAC5B1B,KAAKqC,gBAAgBJ,GACrBJ,EAAaC,KAAK,uBAErBQ,IACGC,EAAO,mBAAmBC,KAAK,EAAGC,aAC9BA,EAAOH,MAAM,wCAAyCA,EAAMI,QAAS,wBAEzEb,EAAaC,KAAK,qCAG9B,EAGH,OAAAvC,CAAA","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":6,"column":0},"map":{"version":3,"names":["BaseHardwareControl","_interopRequireDefault","__BaseHardwareControl","BaseHardwareControlRenderer","__BaseHardwareControlRenderer","RichTextControl","extend","metadata","properties","events","aggregations","_content","type","multiple","visibility","renderer","init","_init","BaseHardwareControl.prototype.init.call","this","richTextEditor","RichTextEditor","width","height","showGroupFont","showGroupInsert","tooltip","change","oEvent","val","getParameter","setValueAndFire","vBox","VBox","items","setAggregation","onBeforeRendering","_onBeforeRendering","readOnly","getProperty","setEditable","currentVal","undefined","getValue","setValue","_setValue","setProperty"],"sources":["RichTextControl.ts"],"sourcesContent":["import BaseHardwareControl from \"./BaseHardwareControl\";\nimport BaseHardwareControlRenderer from \"./BaseHardwareControlRenderer\";\nimport RenderManager from \"sap/ui/core/RenderManager\";\nimport VBox from \"sap/m/VBox\";\nimport RichTextEditor from \"sap/ui/richtexteditor/RichTextEditor\";\n\n/**\n * @file RichTextControl.ts\n * @description Native UI5 Control for rich text input.\n * \n * @namespace nz.co.siliconst.ui5.metaui.controls\n */\nexport default class RichTextControl extends BaseHardwareControl {\n private vBox!: VBox;\n private richTextEditor!: RichTextEditor;\n\n static readonly renderer = BaseHardwareControlRenderer;\n\n static readonly metadata = {\n properties: {},\n events: {},\n aggregations: {\n _content: { type: \"sap.m.VBox\", multiple: false, visibility: \"hidden\" }\n }\n };\n\n public init(): void {\n super.init();\n\n this.richTextEditor = new RichTextEditor({\n width: \"100%\",\n height: \"300px\",\n showGroupFont: true,\n showGroupInsert: true,\n tooltip: \"Rich Text Editor\",\n change: (oEvent: sap.ui.base.Event) => {\n const val = oEvent.getParameter(\"newValue\");\n this.setValueAndFire(val);\n }\n });\n\n this.vBox = new VBox({\n items: [this.richTextEditor]\n });\n\n this.setAggregation(\"_content\", this.vBox);\n }\n\n public onBeforeRendering(): void {\n const readOnly = this.getProperty(\"readOnly\");\n this.richTextEditor.setEditable(!readOnly);\n\n const currentVal = this.getProperty(\"value\");\n if (currentVal !== undefined && currentVal !== null) {\n // Prevent recursive update if the value matches the editor's current value\n if (this.richTextEditor.getValue() !== currentVal) {\n this.richTextEditor.setValue(currentVal as string);\n }\n }\n }\n\n /**\n * Overrides the default property setter to prevent full DOM invalidation.\n * When dataJson pushes updates down to the UI5 models, UI5 typically destroys \n * and recreates the custom control if the property changes. \n * By suppressing re-rendering (true flag) and manually passing the value \n * to the inner RichTextEditor, we prevent TinyMCE from tearing down its iframe\n * and triggering expensive, redundant plugin boot sequences.\n *\n * @param {unknown} val The new string value to bind\n * @returns {this} The control instance for chaining\n */\n public setValue(val: unknown): this {\n this.setProperty(\"value\", val, true); // suppress re-rendering\n if (this.richTextEditor && val !== undefined && val !== null) {\n if (this.richTextEditor.getValue() !== val) {\n this.richTextEditor.setValue(val as string);\n }\n }\n return this;\n }\n}\n"],"mappings":"AAAA,4SAAOA,EAAmBC,EAAAC,GAAA,MACnBC,EAA2BF,EAAAG,GAKlC,MAMqBC,EAAwBL,EAAmBM,OAAA,uDAM5CC,SAAW,CACvBC,WAAY,CAAC,EACbC,OAAQ,CAAC,EACTC,aAAc,CACVC,SAAU,CAAEC,KAAM,aAAcC,SAAU,MAAOC,WAAY,YANrDC,SAAWZ,EAUpBa,KAAI,SAAAC,IACPC,sBAAAC,MAEAA,KAAKC,eAAiB,IAAIC,EAAe,CACrCC,MAAO,OACPC,OAAQ,QACRC,cAAe,KACfC,gBAAiB,KACjBC,QAAS,mBACTC,OAASC,IACL,MAAMC,EAAMD,EAAOE,aAAa,YAChCX,KAAKY,gBAAgBF,MAI7BV,KAAKa,KAAO,IAAIC,EAAK,CACjBC,MAAO,CAACf,KAAKC,kBAGjBD,KAAKgB,eAAe,WAAYhB,KAAKa,KACzC,EAEOI,kBAAiB,SAAAC,IACpB,MAAMC,EAAWnB,KAAKoB,YAAY,YAClCpB,KAAKC,eAAeoB,aAAaF,GAEjC,MAAMG,EAAatB,KAAKoB,YAAY,SACpC,GAAIE,IAAeC,WAAaD,IAAe,KAAM,CAEjD,GAAItB,KAAKC,eAAeuB,aAAeF,EAAY,CAC/CtB,KAAKC,eAAewB,SAASH,EACjC,CACJ,CACJ,EAaOG,SAAQ,SAAAC,EAAChB,GACZV,KAAK2B,YAAY,QAASjB,EAAK,MAC/B,GAAIV,KAAKC,gBAAkBS,IAAQa,WAAab,IAAQ,KAAM,CAC1D,GAAIV,KAAKC,eAAeuB,aAAed,EAAK,CACxCV,KAAKC,eAAewB,SAASf,EACjC,CACJ,CACA,OAAOV,IACX,IAAC,OApEgBd,CAAe","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":7,"column":0},"map":{"version":3,"names":["BaseHardwareControl","_interopRequireDefault","__BaseHardwareControl","SignatureControl","static","properties","events","isDrawing","canvasCtx","canvasEl","init","super","this","canvasHtml","HTML","content","afterRendering","onCanvasRendered","bind","addStyleClass","clearBtn","Button","icon","text","press","clearSignature","vBox","VBox","items","setAggregation","boundStartDrawing","startDrawing","boundDraw","draw","boundStopDrawing","stopDrawing","boundStartDrawingTouch","startDrawingTouch","boundDrawTouch","drawTouch","domRef","getDomRef","getContext","lineWidth","lineCap","strokeStyle","addEventListener","passive","val","getValue","startsWith","loadImageOntoCanvas","dataUrl","img","window","Image","onload","clearRect","width","height","drawImage","src","getCoordinates","e","x","y","rect","getBoundingClientRect","clientX","clientY","type","touches","left","top","preventDefault","pos","lineTo","stroke","beginPath","moveTo","saveSignature","setValueAndFire","MessageToast","show","toDataURL","setValue","value","exit","removeEventListener"],"sources":["SignatureControl.ts"],"sourcesContent":["import BaseHardwareControl from \"./BaseHardwareControl\";\nimport Button from \"sap/m/Button\";\nimport VBox from \"sap/m/VBox\";\nimport HTML from \"sap/ui/core/HTML\";\nimport MessageToast from \"sap/m/MessageToast\";\n\n/**\n * SignatureControl\n * Provides an HTML5 Canvas for capturing signatures.\n */\nexport default class SignatureControl extends BaseHardwareControl {\n static readonly renderer = \"nz.co.siliconst.ui5.metaui.controls.BaseHardwareControlRenderer\";\n static readonly metadata = {\n properties: {},\n events: {}\n };\n\n private vBox!: VBox;\n private clearBtn!: Button;\n private canvasHtml!: HTML;\n private isDrawing = false;\n private canvasCtx: CanvasRenderingContext2D | null = null;\n private canvasEl: HTMLCanvasElement | null = null;\n\n private boundStartDrawing!: (e: MouseEvent) => void;\n private boundDraw!: (e: MouseEvent) => void;\n private boundStopDrawing!: (e: MouseEvent | TouchEvent) => void;\n private boundStartDrawingTouch!: (e: TouchEvent) => void;\n private boundDrawTouch!: (e: TouchEvent) => void;\n\n /**\n * Initializes the control and builds the canvas drawing surface.\n */\n public init(): void {\n super.init();\n\n this.canvasHtml = new HTML({\n content: \"<canvas width='400' height='200' style='border: 1px solid #ccc; background-color: #fff; touch-action: none; cursor: crosshair;'></canvas>\",\n afterRendering: this.onCanvasRendered.bind(this)\n }).addStyleClass(\"sapUiSmallMarginBottom\");\n\n this.clearBtn = new Button({\n icon: \"sap-icon://sys-cancel\",\n text: \"Clear Signature\",\n press: this.clearSignature.bind(this)\n });\n\n this.vBox = new VBox({\n items: [this.canvasHtml, this.clearBtn]\n });\n\n this.setAggregation(\"_content\", this.vBox);\n\n this.boundStartDrawing = this.startDrawing.bind(this);\n this.boundDraw = this.draw.bind(this);\n this.boundStopDrawing = this.stopDrawing.bind(this);\n this.boundStartDrawingTouch = this.startDrawingTouch.bind(this);\n this.boundDrawTouch = this.drawTouch.bind(this);\n }\n\n private onCanvasRendered(): void {\n const domRef = this.canvasHtml.getDomRef() as HTMLElement;\n if (!domRef) return;\n \n this.canvasEl = domRef as HTMLCanvasElement;\n this.canvasCtx = this.canvasEl.getContext(\"2d\");\n if (this.canvasCtx) {\n this.canvasCtx.lineWidth = 2;\n this.canvasCtx.lineCap = \"round\";\n this.canvasCtx.strokeStyle = \"#000\";\n }\n\n // Mouse events\n this.canvasEl.addEventListener(\"mousedown\", this.boundStartDrawing);\n this.canvasEl.addEventListener(\"mousemove\", this.boundDraw);\n this.canvasEl.addEventListener(\"mouseup\", this.boundStopDrawing);\n this.canvasEl.addEventListener(\"mouseout\", this.boundStopDrawing);\n \n // Touch events\n this.canvasEl.addEventListener(\"touchstart\", this.boundStartDrawingTouch, { passive: false });\n this.canvasEl.addEventListener(\"touchmove\", this.boundDrawTouch, { passive: false });\n this.canvasEl.addEventListener(\"touchend\", this.boundStopDrawing);\n\n // Restore existing signature if any\n const val = this.getValue();\n if (val && typeof val === \"string\" && val.startsWith(\"data:image\")) {\n this.loadImageOntoCanvas(val);\n }\n }\n\n private loadImageOntoCanvas(dataUrl: string): void {\n const img = new window.Image();\n img.onload = () => {\n if (this.canvasCtx && this.canvasEl) {\n this.canvasCtx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);\n this.canvasCtx.drawImage(img, 0, 0, this.canvasEl.width, this.canvasEl.height);\n }\n };\n img.src = dataUrl;\n }\n\n private getCoordinates(e: MouseEvent | TouchEvent): { x: number, y: number } {\n if (!this.canvasEl) return { x: 0, y: 0 };\n const rect = this.canvasEl.getBoundingClientRect();\n \n let clientX, clientY;\n if (e.type.startsWith(\"touch\")) {\n clientX = (e as TouchEvent).touches[0].clientX;\n clientY = (e as TouchEvent).touches[0].clientY;\n } else {\n clientX = (e as MouseEvent).clientX;\n clientY = (e as MouseEvent).clientY;\n }\n \n return {\n x: clientX - rect.left,\n y: clientY - rect.top\n };\n }\n\n private startDrawing(e: MouseEvent): void {\n this.isDrawing = true;\n this.draw(e);\n }\n\n private startDrawingTouch(e: TouchEvent): void {\n e.preventDefault(); // Prevent scrolling\n this.isDrawing = true;\n this.drawTouch(e);\n }\n\n private draw(e: MouseEvent): void {\n if (!this.isDrawing || !this.canvasCtx) return;\n const pos = this.getCoordinates(e);\n this.canvasCtx.lineTo(pos.x, pos.y);\n this.canvasCtx.stroke();\n this.canvasCtx.beginPath();\n this.canvasCtx.moveTo(pos.x, pos.y);\n }\n\n private drawTouch(e: TouchEvent): void {\n if (!this.isDrawing || !this.canvasCtx) return;\n e.preventDefault(); // Prevent scrolling\n const pos = this.getCoordinates(e);\n this.canvasCtx.lineTo(pos.x, pos.y);\n this.canvasCtx.stroke();\n this.canvasCtx.beginPath();\n this.canvasCtx.moveTo(pos.x, pos.y);\n }\n\n private stopDrawing(): void {\n if (!this.isDrawing) return;\n this.isDrawing = false;\n if (this.canvasCtx) {\n this.canvasCtx.beginPath(); // Reset path\n this.saveSignature();\n }\n }\n\n private clearSignature(): void {\n if (this.canvasCtx && this.canvasEl) {\n this.canvasCtx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);\n }\n this.setValueAndFire(null);\n MessageToast.show(\"Signature cleared.\");\n }\n\n private saveSignature(): void {\n if (this.canvasEl) {\n const dataUrl = this.canvasEl.toDataURL(\"image/png\");\n this.setValueAndFire(dataUrl);\n }\n }\n\n /**\n * Sets the value of the control programmatically and re-draws the canvas.\n * @param value The base64 data URL string representing the signature image.\n */\n public setValue(value: unknown): this {\n super.setValue(value);\n if (value && typeof value === \"string\" && value.startsWith(\"data:image\")) {\n this.loadImageOntoCanvas(value);\n } else if (!value && this.canvasCtx && this.canvasEl) {\n this.canvasCtx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);\n }\n return this;\n }\n\n /**\n * Cleans up event listeners to prevent memory leaks when the control is destroyed.\n */\n public exit(): void {\n if (this.canvasEl) {\n this.canvasEl.removeEventListener(\"mousedown\", this.boundStartDrawing as EventListener);\n this.canvasEl.removeEventListener(\"mousemove\", this.boundDraw as EventListener);\n this.canvasEl.removeEventListener(\"mouseup\", this.boundStopDrawing as EventListener);\n this.canvasEl.removeEventListener(\"mouseout\", this.boundStopDrawing as EventListener);\n \n this.canvasEl.removeEventListener(\"touchstart\", this.boundStartDrawingTouch as EventListener);\n this.canvasEl.removeEventListener(\"touchmove\", this.boundDrawTouch as EventListener);\n this.canvasEl.removeEventListener(\"touchend\", this.boundStopDrawing as EventListener);\n }\n this.canvasEl = null;\n this.canvasCtx = null;\n super.exit();\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":8,"column":0},"map":{"version":3,"names":["BaseHardwareControl","_interopRequireDefault","__BaseHardwareControl","Logger","___utils_Logger","VoiceInputControl","static","properties","events","recognition","isRecording","init","super","this","textArea","TextArea","rows","width","placeholder","liveChange","oEvent","setValueAndFire","getParameter","startBtn","Button","icon","text","type","press","toggleDictation","bind","hBox","HBox","items","addStyleClass","vBox","VBox","setAggregation","initSpeechRecognition","stopDictation","startDictation","SpeechRecognitionClass","window","SpeechRecognition","webkitSpeechRecognition","continuous","interimResults","onresult","event","finalTranscript","interimTranscript","i","resultIndex","results","length","isFinal","transcript","currentVal","getValue","newVal","setValue","onstart","setIcon","setText","setType","MessageToast","show","onerror","error","sap","ui","require","MessageBox","onend","warn","setEnabled","setTooltip","start","err","message","String","stop","e","onBeforeRendering","readOnly","getProperty","setEditable","undefined","exit"],"sources":["VoiceInputControl.ts"],"sourcesContent":["import BaseHardwareControl from \"./BaseHardwareControl\";\nimport Button from \"sap/m/Button\";\nimport VBox from \"sap/m/VBox\";\nimport TextArea from \"sap/m/TextArea\";\nimport MessageToast from \"sap/m/MessageToast\";\nimport HBox from \"sap/m/HBox\";\nimport { Logger } from \"../utils/Logger\";\n\ndeclare global {\n interface Window {\n SpeechRecognition: new () => SpeechRecognition;\n webkitSpeechRecognition: new () => SpeechRecognition;\n }\n interface SpeechRecognition {\n continuous: boolean;\n interimResults: boolean;\n onresult: (event: SpeechRecognitionEvent) => void;\n onstart: () => void;\n onerror: (event: SpeechRecognitionErrorEvent) => void;\n onend: () => void;\n start(): void;\n stop(): void;\n }\n interface SpeechRecognitionEvent {\n resultIndex: number;\n results: {\n length: number;\n [index: number]: {\n isFinal: boolean;\n [index: number]: {\n transcript: string;\n };\n };\n };\n }\n interface SpeechRecognitionErrorEvent {\n error: string;\n }\n}\n\n/**\n * VoiceInputControl\n * Provides a UI to dictate text using the browser's native Web Speech API.\n */\nexport default class VoiceInputControl extends BaseHardwareControl {\n static readonly renderer = \"nz.co.siliconst.ui5.metaui.controls.BaseHardwareControlRenderer\";\n static readonly metadata = {\n properties: {},\n events: {}\n };\n\n private vBox!: VBox;\n private textArea!: TextArea;\n private startBtn!: Button;\n private stopBtn!: Button;\n \n private recognition: SpeechRecognition | null = null;\n private isRecording: boolean = false;\n\n /**\n * Initializes the dictation interface and requests Web Speech API setup.\n */\n public init(): void {\n super.init();\n\n this.textArea = new TextArea({\n rows: 3,\n width: \"100%\",\n placeholder: \"Dictated text will appear here...\",\n liveChange: (oEvent: sap.ui.base.Event) => {\n this.setValueAndFire(oEvent.getParameter(\"value\"));\n }\n });\n\n this.startBtn = new Button({\n icon: \"sap-icon://microphone\",\n text: \"Start Dictation\",\n type: \"Emphasized\",\n press: this.toggleDictation.bind(this)\n });\n\n const hBox = new HBox({\n items: [this.startBtn]\n }).addStyleClass(\"sapUiSmallMarginTop\");\n\n this.vBox = new VBox({\n items: [this.textArea, hBox]\n });\n\n this.setAggregation(\"_content\", this.vBox);\n this.initSpeechRecognition();\n }\n\n private toggleDictation(): void {\n if (this.isRecording) {\n this.stopDictation();\n } else {\n this.startDictation();\n }\n }\n\n private initSpeechRecognition(): void {\n const SpeechRecognitionClass = window.SpeechRecognition || window.webkitSpeechRecognition;\n if (SpeechRecognitionClass) {\n this.recognition = new SpeechRecognitionClass();\n this.recognition.continuous = true;\n this.recognition.interimResults = true;\n\n this.recognition.onresult = (event: SpeechRecognitionEvent) => {\n let finalTranscript = \"\";\n let interimTranscript = \"\";\n\n for (let i = event.resultIndex; i < event.results.length; ++i) {\n if (event.results[i].isFinal) {\n finalTranscript += event.results[i][0].transcript;\n } else {\n interimTranscript += event.results[i][0].transcript;\n }\n }\n\n // Append the new final transcript to whatever was already in the textarea\n const currentVal = this.getValue() || \"\";\n const newVal = currentVal ? currentVal + \" \" + finalTranscript : finalTranscript;\n \n if (finalTranscript) {\n this.textArea.setValue(newVal);\n this.setValueAndFire(newVal);\n } else if (interimTranscript) {\n // Just show interim temporarily in textarea without saving to model\n this.textArea.setValue(currentVal ? currentVal + \" \" + interimTranscript : interimTranscript);\n }\n };\n\n this.recognition.onstart = () => {\n this.isRecording = true;\n this.startBtn.setIcon(\"sap-icon://stop\");\n this.startBtn.setText(\"Stop Recording\");\n this.startBtn.setType(\"Reject\");\n MessageToast.show(\"Listening... Please speak now.\");\n };\n\n this.recognition.onerror = (event: SpeechRecognitionErrorEvent) => {\n Logger.error(\"Speech recognition error\", event.error, \"VoiceInputControl\");\n sap.ui.require([\"sap/m/MessageBox\"], (MessageBox: typeof import(\"sap/m/MessageBox\").default) => {\n MessageBox.error(\"Microphone Error: \" + event.error + \"\\n\\nPlease ensure you have a working microphone attached and have not blocked access in your browser settings.\");\n });\n this.stopDictation();\n };\n \n this.recognition.onend = () => {\n // If it ends natively (e.g. timeout), update UI\n this.stopDictation();\n };\n } else {\n Logger.warn(\"Web Speech API not supported in this browser.\", \"\", \"VoiceInputControl\");\n this.startBtn.setEnabled(false);\n this.startBtn.setTooltip(\"Speech Recognition is not supported in this browser.\");\n }\n }\n\n private startDictation(): void {\n if (!this.recognition) return;\n \n try {\n this.recognition.start();\n MessageToast.show(\"Requesting microphone access...\");\n // Provide immediate UI feedback in case browser delays the onstart event\n this.startBtn.setIcon(\"sap-icon://stop\");\n this.startBtn.setText(\"Requesting mic...\");\n this.startBtn.setType(\"Reject\");\n } catch (err) {\n const error = err as Error;\n Logger.error(\"Failed to start speech recognition\", error.message || String(error), \"VoiceInputControl\");\n sap.ui.require([\"sap/m/MessageBox\"], (MessageBox: typeof import(\"sap/m/MessageBox\").default) => {\n MessageBox.error(\"Failed to start dictation. Please ensure you have a working microphone and have granted browser permissions.\\n\\nDetails: \" + (error.message || String(error)));\n });\n this.stopDictation();\n }\n }\n\n private stopDictation(): void {\n if (!this.recognition) return;\n \n try {\n this.recognition.stop();\n } catch(e) {\n Logger.warn(\"Failed to gracefully stop speech recognition.\", String(e), \"VoiceInputControl\");\n }\n \n this.isRecording = false;\n this.startBtn.setIcon(\"sap-icon://microphone\");\n this.startBtn.setText(\"Start Dictation\");\n this.startBtn.setType(\"Emphasized\");\n }\n\n /**\n * Lifecycle hook called before the control is rendered to the DOM.\n * Handles browser support visual state.\n */\n public onBeforeRendering(): void {\n const readOnly = this.getProperty(\"readOnly\");\n this.textArea.setEditable(!readOnly);\n \n // Only enable if it's not readonly AND the browser supports speech recognition\n this.startBtn.setEnabled(!readOnly && !!this.recognition);\n\n const currentVal = this.getProperty(\"value\");\n if (currentVal !== undefined && currentVal !== null) {\n // Only update text area if we aren't currently dictating interim results\n if (!this.isRecording) {\n this.textArea.setValue(currentVal as string);\n }\n }\n }\n\n /**\n * Cleans up hardware event listeners when the control is destroyed.\n */\n public exit(): void {\n this.stopDictation();\n if (this.recognition) {\n this.recognition.onstart = null;\n this.recognition.onresult = null;\n this.recognition.onerror = null;\n this.recognition.onend = null;\n this.recognition = null;\n }\n super.exit();\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":9,"column":0},"map":{"version":3,"names":["Logger","____utils_Logger","SchemaNormalizer","____core_SchemaNormalizer","SchemaValidator","____core_SchemaValidator","Engine","____core_Engine","StateManager","____core_StateManager","DataSyncDelegate","___delegates_DataSyncDelegate","ValidationDelegate","___delegates_ValidationDelegate","DialogDelegate","___delegates_DialogDelegate","PluginRegistry","____core_PluginRegistry","GeneratorHost","Control","extend","renderer","apiVersion","render","rm","control","openStart","style","openEnd","content","getAggregation","renderControl","close","metadata","properties","schemaDefinition","type","defaultValue","data","bindable","dataJson","liveUpdate","isValid","useMessageManager","modelName","debugMode","editable","aggregations","_content","multiple","visibility","events","beforeSubmit","parameters","payload","addError","preventDefault","submit","payloadJson","cancel","fieldChange","fieldPath","value","validationStateChanged","validationError","message","validationSuccess","error","exception","constructor","_constructor","idOrSettings","settings","Control.prototype.constructor.call","this","stateManager","generatedContent","engine","activeModelName","parsedSchema","_generatePromise","init","_init","Control.prototype.init.call","dataSyncDelegate","validationDelegate","dialogDelegate","onInternalFieldChange","bind","setDebugMode","_setDebugMode","enabled","setProperty","_setProperty","propertyName","suppressInvalidate","Control.prototype.setProperty.call","setUseMessageManager","getStateManager","_getStateManager","tearDownGeneratedLayout","_tearDownGeneratedLayout","unregisterObject","destroy","_onInternalFieldChange","fieldKey","errorMessage","controlId","extractPayload","getProperty","debug","pushToBindings","currentValidity","fireEvent","undefined","exit","_exit","getModel","getParsedSchema","_getParsedSchema","onBeforeRendering","_onBeforeRendering","hasSchema","hasData","generate","msg","Error","triggerSubmit","_triggerSubmit","isPrevented","removeAllMessages","applyVisualFallback","errors","validateAll","length","pushMessage","err","JSON","stringify","propertyPath","plugin","getPluginByPath","setVisualValidationState","addCustomError","_addCustomError","clearCustomError","_clearCustomError","schemaValid","validate","setBusy","_setBusy","isBusy","Control.prototype.setBusy.call","_setProperty2","handleInputDataHotSwap","currentVal","setBaseProperty","_setBaseProperty","async","_generate","Promise","resolve","then","_doGenerate","e","internalPayload","rawSchema","isSchemaEmpty","Object","keys","inputData","inputDataJson","parse","finalData","schemaToNormalize","normalizedSchema","normalize","schemaErrors","validateSchemaStructure","errorMsg","join","MessageBox","title","pathsToLoad","getInstance","getPathsToLoad","needsNetworkLoad","Array","from","some","path","sap","ui","require","preloadDependencies","getId","setModel","isEditable","build","contentContainer","hasProperties","strip","MessageStrip","text","showIcon","showCloseButton","addStyleClass","VBox","items","hasPartialRenderingErrors","setAggregation","registerObject","mountCrashBoundary","openInDialog","_openInDialog","submitButtonText","cancelButtonText","dialogWidth","parentView","isGenerated"],"sources":["GeneratorHost.ts"],"sourcesContent":["import Control from \"sap/ui/core/Control\";\nimport RenderManager from \"sap/ui/core/RenderManager\";\nimport { Logger } from \"../../utils/Logger\";\nimport { SchemaNormalizer } from \"../../core/SchemaNormalizer\";\nimport { SchemaValidator } from \"../../core/SchemaValidator\";\nimport { Engine } from \"../../core/Engine\";\nimport { StateManager } from \"../../core/StateManager\";\nimport { DataSyncDelegate } from \"./delegates/DataSyncDelegate\";\nimport { ValidationDelegate } from \"./delegates/ValidationDelegate\";\nimport { DialogDelegate } from \"./delegates/DialogDelegate\";\nimport MessageBox from \"sap/m/MessageBox\";\nimport MessageStrip from \"sap/m/MessageStrip\";\nimport VBox from \"sap/m/VBox\";\nimport { PluginRegistry } from \"../../core/PluginRegistry\";\nimport type { ISchema } from \"../../interfaces/ISchema\";\n\n/**\n * Base wrapper element for embedding the dynamic form natively via Explicit Schemas.\n * \n * This class serves as the core rendering engine for standard MetaUI implementations.\n * It manages the lifecycle of the Engine, StateManager, and the delegation of \n * data synchronization, validation, and dialog interactions.\n * \n * @namespace nz.co.siliconst.ui5.metaui.controls.host\n */\nexport default class GeneratorHost extends Control {\n\n protected stateManager: StateManager | null = null;\n protected generatedContent: Control | null = null;\n protected engine: Engine | null = null;\n protected activeModelName: string = \"\";\n\n protected dataSyncDelegate!: DataSyncDelegate;\n protected validationDelegate!: ValidationDelegate;\n protected dialogDelegate!: DialogDelegate;\n\n static readonly metadata = {\n properties: {\n schemaDefinition: { type: \"any\", defaultValue: null },\n data: { type: \"object\", defaultValue: null, bindable: \"bindable\" },\n dataJson: { type: \"string\", defaultValue: null, bindable: \"bindable\" },\n liveUpdate: { type: \"boolean\", defaultValue: false },\n isValid: { type: \"boolean\", defaultValue: true },\n useMessageManager: { type: \"boolean\", defaultValue: false },\n modelName: { type: \"string\", defaultValue: \"meta\" },\n debugMode: { type: \"boolean\", defaultValue: false },\n editable: { type: \"boolean\", defaultValue: true }\n },\n aggregations: {\n _content: { type: \"sap.ui.core.Control\", multiple: false, visibility: \"hidden\" }\n },\n events: {\n beforeSubmit: {\n parameters: {\n payload: { type: \"object\" },\n addError: { type: \"function\" },\n preventDefault: { type: \"function\" }\n }\n },\n submit: {\n parameters: {\n payload: { type: \"object\" },\n payloadJson: { type: \"string\" }\n }\n },\n cancel: {},\n fieldChange: {\n parameters: {\n fieldPath: { type: \"string\" },\n value: { type: \"any\" },\n payload: { type: \"object\" },\n isValid: { type: \"boolean\" }\n }\n },\n validationStateChanged: { parameters: { isValid: { type: \"boolean\" } } },\n validationError: { parameters: { fieldPath: { type: \"string\" }, message: { type: \"string\" } } },\n validationSuccess: { parameters: { fieldPath: { type: \"string\" } } },\n error: { parameters: { message: { type: \"string\" }, exception: { type: \"object\" } } }\n }\n };\n\n static renderer = {\n apiVersion: 2,\n render(rm: RenderManager, control: GeneratorHost) {\n rm.openStart(\"div\", control);\n rm.style(\"width\", \"100%\");\n rm.style(\"height\", \"100%\");\n rm.openEnd();\n\n const content = control.getAggregation(\"_content\") as Control;\n if (content) {\n rm.renderControl(content);\n }\n\n rm.close(\"div\");\n }\n };\n\n /**\n * Standard UI5 Constructor.\n */\n constructor(idOrSettings?: string | object, settings?: object) {\n super(idOrSettings, settings);\n }\n\n /**\n * Initializes the control and instantiates the composition delegates.\n * Delegates must be initialized here rather than in the constructor so they are \n * available before `applySettings` runs during UI5's control lifecycle.\n */\n public init(): void {\n super.init();\n\n // Initialize Composition Delegates\n this.dataSyncDelegate = new DataSyncDelegate(this);\n this.validationDelegate = new ValidationDelegate(this);\n this.dialogDelegate = new DialogDelegate(this);\n\n this.onInternalFieldChange = this.onInternalFieldChange.bind(this);\n }\n\n /**\n * Enables or disables debug mode.\n */\n public setDebugMode(enabled: boolean): this {\n this.setProperty(\"debugMode\", enabled, true);\n Logger.setDebugMode(enabled);\n return this;\n }\n\n /**\n * Intercepts property updates to dynamically forward them to active delegates/managers.\n */\n public setProperty(propertyName: string, value: unknown, suppressInvalidate?: boolean): this {\n super.setProperty(propertyName, value, suppressInvalidate);\n if (propertyName === \"useMessageManager\" && this.stateManager) {\n this.stateManager.setUseMessageManager(value === true);\n }\n return this;\n }\n\n /**\n * Returns the active state manager instance managing the JSON payload.\n */\n public getStateManager(): StateManager | null {\n return this.stateManager;\n }\n\n /**\n * Safely destroys the currently generated UI tree and cleans up references.\n * This is called before every regeneration to prevent memory leaks.\n */\n public tearDownGeneratedLayout(): void {\n if (this.generatedContent) {\n this.validationDelegate.unregisterObject(this.generatedContent);\n this.generatedContent.destroy();\n this.generatedContent = null;\n }\n }\n\n /**\n * Internal event handler triggered by the Engine when a field value changes.\n * Coordinates LiveUpdate syncs, validation state tracking, and bubbling the change upwards.\n */\n protected onInternalFieldChange(isValid: boolean, fieldKey?: string, errorMessage?: string, controlId?: string): void {\n const payload = this.stateManager ? this.stateManager.extractPayload() : {};\n\n if (this.getProperty(\"liveUpdate\") === true) {\n if (this.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI]\", \"liveUpdate is enabled, pushing outbound payload.\", \"GeneratorHost\");\n }\n this.dataSyncDelegate.pushToBindings(payload);\n }\n\n const currentValidity = this.getProperty(\"isValid\") as boolean;\n if (isValid !== currentValidity) {\n this.setProperty(\"isValid\", isValid, true);\n this.fireEvent(\"validationStateChanged\", { isValid });\n if (this.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI]\", `Validation state shifted to: ${isValid}`, \"GeneratorHost\");\n }\n }\n\n this.fireEvent(\"fieldChange\", {\n fieldPath: fieldKey || \"\",\n value: undefined,\n payload: payload,\n isValid: isValid\n });\n }\n\n /**\n * Standard UI5 Exit Hook. Ensures complete teardown of the engine and state manager.\n */\n public exit(): void {\n if (this.engine) {\n this.engine.destroy();\n this.engine = null;\n }\n\n if (this.stateManager) {\n this.stateManager.getModel().destroy();\n this.stateManager = null;\n }\n\n if (this.generatedContent) {\n this.generatedContent.destroy();\n this.generatedContent = null;\n }\n }\n\n /** Cached schema for intelligent diffing during inference mode hot-swaps */\n protected parsedSchema: Record<string, unknown> | null = null;\n\n /**\n * Exposes the parsed schema to the DataSyncDelegate for diffing.\n */\n public getParsedSchema(): Record<string, unknown> | null {\n return this.parsedSchema;\n }\n\n /**\n * Standard UI5 Rendering Hook.\n * Evaluates whether it possesses a schema or data. If so, triggers the internal engine generation.\n */\n public onBeforeRendering(): void {\n if (this.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI GeneratorHost]\", `onBeforeRendering called. Engine boot state: schemaDefinition exists = ${!!this.getProperty(\"schemaDefinition\")}, data exists = ${!!this.getProperty(\"data\")}, dataJson exists = ${!!this.getProperty(\"dataJson\")}`, \"GeneratorHost\");\n }\n\n if (!this.generatedContent) {\n const hasSchema = !!this.getProperty(\"schemaDefinition\");\n const hasData = !!this.getProperty(\"dataJson\") || !!this.getProperty(\"data\");\n\n if (hasSchema || hasData) {\n this.generate();\n } else {\n const msg = \"GeneratorHost skipped rendering. Neither 'schemaDefinition' nor 'data' was provided.\";\n Logger.error(\"[MetaUI]\", msg, \"GeneratorHost\");\n this.fireEvent(\"error\", { message: msg });\n throw new Error(msg); // Eradicate silent errors\n }\n }\n }\n\n /**\n * Public API method to manually trigger form submission.\n * Executes all structural validations, clears old messages, and pushes payload to bindings.\n * @returns boolean True if submission succeeded, false if validation failed.\n */\n public triggerSubmit(): boolean {\n if (this.stateManager && this.engine) {\n let isPrevented = false;\n\n this.validationDelegate.removeAllMessages();\n\n // Only apply local fallback visual states if the global MessageManager is explicitly disabled\n const applyVisualFallback = this.getProperty(\"useMessageManager\") !== true;\n const errors = this.engine.validateAll(applyVisualFallback);\n if (errors.length > 0) {\n this.validationDelegate.pushMessage(\"\", \"One or more fields failed schema validation. Please review the highlighted fields.\");\n for (const err of errors) {\n if (err.fieldKey && err.errorMessage) {\n this.validationDelegate.pushMessage(err.fieldKey, err.errorMessage);\n }\n }\n return false;\n }\n\n const payload = this.stateManager.extractPayload();\n const payloadJson = JSON.stringify(payload);\n\n this.fireEvent(\"beforeSubmit\", {\n payload,\n preventDefault: () => { isPrevented = true; },\n addError: (propertyPath: string, errorMessage: string) => {\n isPrevented = true;\n this.validationDelegate.pushMessage(propertyPath, errorMessage);\n if (applyVisualFallback && this.engine) {\n const plugin = this.engine.getPluginByPath(propertyPath);\n if (plugin && typeof plugin.setVisualValidationState === \"function\") {\n plugin.setVisualValidationState(false, errorMessage);\n }\n }\n }\n });\n\n if (isPrevented) {\n return false;\n }\n\n this.dataSyncDelegate.pushToBindings(payload);\n this.fireEvent(\"submit\", { payload, payloadJson });\n return true;\n }\n return false;\n }\n\n /**\n * Injects a custom error message onto a specific field.\n */\n public addCustomError(fieldPath: string, message: string): void {\n this.validationDelegate.addCustomError(fieldPath, message);\n if (this.getProperty(\"useMessageManager\") !== true && this.engine) {\n const plugin = this.engine.getPluginByPath(fieldPath);\n if (plugin && typeof plugin.setVisualValidationState === \"function\") {\n plugin.setVisualValidationState(false, message);\n }\n }\n }\n\n /**\n * Clears a custom error message from a specific field.\n */\n public clearCustomError(fieldPath: string): void {\n this.validationDelegate.clearCustomError(fieldPath);\n if (this.getProperty(\"useMessageManager\") !== true && this.engine) {\n const plugin = this.engine.getPluginByPath(fieldPath);\n if (plugin && typeof plugin.setVisualValidationState === \"function\") {\n const schemaValid = plugin.validate();\n plugin.setVisualValidationState(schemaValid.isValid, schemaValid.errorMessage);\n }\n }\n }\n\n /**\n * Toggles busy state on the host control.\n */\n public setBusy(isBusy: boolean): this {\n super.setBusy(isBusy);\n return this;\n }\n\n /**\n * Intercepts property changes. Hot-swaps data gracefully if it's an inputData change,\n * or forces a full UI teardown if it's a structural property change (like schemaDefinition).\n */\n public setProperty(propertyName: string, value: unknown, suppressInvalidate?: boolean): this {\n if (propertyName === \"dataJson\" || propertyName === \"data\") {\n this.dataSyncDelegate.handleInputDataHotSwap(propertyName, value, suppressInvalidate);\n return this;\n }\n\n if (propertyName === \"editable\" || propertyName === \"debugMode\" || propertyName === \"schemaDefinition\") {\n const currentVal = this.getProperty(propertyName);\n if (currentVal !== value) {\n super.setProperty(propertyName, value, suppressInvalidate);\n this.tearDownGeneratedLayout();\n }\n return this;\n }\n\n return super.setProperty(propertyName, value, suppressInvalidate);\n }\n\n /**\n * Bypasses the interceptor to write directly to the base UI5 control.\n */\n public setBaseProperty(propertyName: string, value: unknown, suppressInvalidate?: boolean): this {\n return super.setProperty(propertyName, value, suppressInvalidate);\n }\n\n /**\n * Internal reference to the active generate promise.\n * Prevents concurrent redundant layouts from being generated when properties are set rapidly or DialogDelegate triggers it.\n */\n private _generatePromise: Promise<void> | null = null;\n\n /**\n * The core rendering pipeline entry point.\n * Uses Promise resolution to debounce concurrent or rapid consecutive calls natively without arbitrary timeouts.\n * @returns Promise that resolves when the layout is successfully built and mounted.\n */\n public async generate(): Promise<void> {\n if (this._generatePromise) {\n return this._generatePromise;\n }\n this._generatePromise = Promise.resolve().then(async () => {\n try {\n await this._doGenerate();\n } catch (e) {\n Logger.error(\"[MetaUI]\", \"Error in deferred generate: \" + e, \"GeneratorHost\");\n throw e; // Ensure it bubbles up to awaiters\n } finally {\n this._generatePromise = null;\n }\n });\n return this._generatePromise;\n }\n\n /**\n * The underlying synchronous generator orchestration method.\n * Normalizes the schema, sets up the state manager, loads missing plugins over the network,\n * orchestrates the Engine build, and mounts the generated UI components into the internal tree.\n */\n private async _doGenerate(): Promise<void> {\n try {\n this.tearDownGeneratedLayout();\n\n // CRITICAL FIX: Extract the unsaved internal payload BEFORE destroying the state manager\n // Otherwise, toggling editable (or other structural properties) will wipe user inputs!\n let internalPayload = null;\n if (this.stateManager) {\n internalPayload = this.stateManager.extractPayload();\n }\n\n if (this.engine) {\n this.engine.destroy();\n this.engine = null;\n }\n if (this.stateManager) {\n this.stateManager.getModel().destroy();\n this.stateManager = null;\n }\n\n const rawSchema = this.getProperty(\"schemaDefinition\");\n const isSchemaEmpty = !rawSchema || (typeof rawSchema === \"object\" && Object.keys(rawSchema).length === 0);\n\n let inputData = this.getProperty(\"data\");\n const inputDataJson = this.getProperty(\"dataJson\");\n\n if (inputDataJson) {\n try {\n inputData = JSON.parse(inputDataJson as string);\n } catch (e) {\n const msg = \"Failed to parse inputDataJson string: \" + (e as Error).message;\n Logger.error(\"[MetaUI]\", msg, \"GeneratorHost\");\n this.fireEvent(\"error\", { message: msg, exception: e });\n throw new Error(msg); // Critical error instead of silent fallback\n }\n } else if (typeof inputData === \"string\") {\n try {\n inputData = JSON.parse(inputData);\n } catch (e) {\n const msg = \"Failed to parse inputData string: \" + (e as Error).message;\n Logger.error(\"[MetaUI]\", msg, \"GeneratorHost\");\n this.fireEvent(\"error\", { message: msg, exception: e });\n throw new Error(msg); // Critical error instead of silent fallback\n }\n }\n\n // The internal payload represents the user's latest un-extracted edits. It must take priority.\n const finalData = internalPayload || inputData;\n\n if (!finalData || Object.keys(finalData).length === 0) {\n if (isSchemaEmpty) {\n const msg = \"No payload provided and no explicit schema defined. Cannot infer UI.\";\n Logger.error(\"[MetaUI]\", msg, \"GeneratorHost\");\n this.fireEvent(\"error\", { message: msg });\n throw new Error(msg);\n }\n }\n\n const schemaToNormalize = isSchemaEmpty ? null : rawSchema;\n const normalizedSchema = SchemaNormalizer.normalize(schemaToNormalize, finalData);\n\n // Cache the parsed/inferred schema so DataSyncDelegate can diff against it later\n this.parsedSchema = normalizedSchema as Record<string, unknown>;\n\n if (normalizedSchema) {\n const schemaErrors = SchemaValidator.validateSchemaStructure(normalizedSchema);\n if (schemaErrors.length > 0) {\n const errorMsg = \"Schema Structural Errors Found:\\n- \" + schemaErrors.join(\"\\n- \");\n // Let's log it out loudly regardless of debug mode, so developers can see why it didn't render\n Logger.error(\"[MetaUI]\", errorMsg, \"GeneratorHost\");\n if (this.getProperty(\"debugMode\")) {\n MessageBox.error(errorMsg, { title: \"MetaUI Schema Error\" });\n return;\n }\n }\n }\n\n const pathsToLoad = PluginRegistry.getInstance().getPathsToLoad(normalizedSchema as ISchema);\n const needsNetworkLoad = Array.from(pathsToLoad).some(path => !sap.ui.require(path));\n\n if (needsNetworkLoad) {\n this.setBusy(true);\n await PluginRegistry.getInstance().preloadDependencies(normalizedSchema as ISchema);\n this.setBusy(false);\n }\n\n this.activeModelName = \"metaUI_\" + this.getId();\n this.stateManager = new StateManager(finalData, normalizedSchema, this.activeModelName);\n this.stateManager.setUseMessageManager(this.getProperty(\"useMessageManager\") === true);\n this.setModel(this.stateManager.getModel(), this.activeModelName);\n\n if (!this.engine) {\n const isEditable = this.getProperty(\"editable\") !== false;\n const useMessageManager = this.getProperty(\"useMessageManager\") === true;\n this.engine = new Engine(isEditable, useMessageManager);\n }\n\n this.generatedContent = this.engine.build(\n normalizedSchema,\n this.stateManager.getModel(),\n this.activeModelName,\n this.triggerSubmit.bind(this),\n this.getId(),\n this.onInternalFieldChange.bind(this)\n );\n\n let contentContainer = this.generatedContent;\n \n const hasProperties = normalizedSchema && Object.keys(normalizedSchema).length > 0;\n \n if (!hasProperties) {\n const strip = new MessageStrip({\n text: \"Warning: The generated UI is blank. Reason: The schema (or inferred schema) contains no valid properties to render.\",\n type: \"Warning\",\n showIcon: true,\n showCloseButton: false\n });\n strip.addStyleClass(\"sapUiSmallMarginBottom\");\n contentContainer = new VBox({\n items: [strip, this.generatedContent]\n });\n } else if (this.engine.hasPartialRenderingErrors) {\n const strip = new MessageStrip({\n text: \"Layout partially rendered. Some fields failed to generate due to configuration errors.\",\n type: \"Warning\",\n showIcon: true,\n showCloseButton: true\n });\n strip.addStyleClass(\"sapUiSmallMarginBottom\");\n contentContainer = new VBox({\n items: [strip, this.generatedContent]\n });\n }\n\n this.setAggregation(\"_content\", contentContainer);\n this.validationDelegate.registerObject(this.generatedContent);\n\n const payload = this.stateManager.extractPayload();\n this.dataSyncDelegate.pushToBindings(payload);\n\n } catch (error) {\n this.setBusy(false);\n const msg = \"Fatal crash during layout generation: \" + (error as Error).message;\n Logger.error(\"[MetaUI]\", msg, \"GeneratorHost\");\n this.fireEvent(\"error\", { message: msg, exception: error });\n this.validationDelegate.mountCrashBoundary(error as Error);\n throw error; // Completely eliminate silent error swallowing\n }\n }\n\n /**\n * Programmatic API. Re-parents the generated content into a dialog and opens it.\n */\n public openInDialog(title: string = \"Form\", submitButtonText: string = \"OK\", cancelButtonText: string = \"Cancel\", dialogWidth: string = \"800px\", parentView?: Control): void {\n const isGenerated = !!this.generatedContent;\n this.dialogDelegate.openInDialog(title, submitButtonText, isGenerated, cancelButtonText, dialogWidth, parentView);\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"controls/host"}},{"offset":{"line":10,"column":0},"map":{"version":3,"names":["Logger","_____utils_Logger","SchemaNormalizer","_____core_SchemaNormalizer","DataSyncDelegate","_lastPushedPayloadJson","_lastPushedPayloadObj","_lastReceivedInputObj","constructor","host","this","pushToBindings","payload","payloadStr","JSON","stringify","deepEqual","parse","setProperty","handleInputDataHotSwap","propertyName","value","suppressInvalidate","incomingObj","e","setBaseProperty","getProperty","debug","extend","stateManager","getStateManager","invalidate","getModel","setData","getParsedSchema","newInferredSchema","inferSchemaFromData","parsedSchema","tearDownGeneratedLayout","msg","message","error","Error","__exports","__esModule"],"sources":["DataSyncDelegate.ts"],"sourcesContent":["import deepEqual from \"sap/base/util/deepEqual\";\nimport extend from \"sap/base/util/extend\";\nimport { Logger } from \"../../../utils/Logger\";\nimport { SchemaNormalizer } from \"../../../core/SchemaNormalizer\";\nimport PropertyBinding from \"sap/ui/model/PropertyBinding\";\nimport { StateManager } from \"../../../core/StateManager\";\n\nexport interface IHostDataSync {\n getProperty(name: string): unknown;\n setProperty(name: string, value: unknown, suppressInvalidate?: boolean): this;\n setBaseProperty(name: string, value: unknown, suppressInvalidate?: boolean): this;\n getBinding(name: string): unknown;\n invalidate(): void;\n getStateManager(): StateManager | null;\n getParsedSchema?(): Record<string, unknown> | null;\n tearDownGeneratedLayout(): void;\n}\n\n/**\n * Handles two-way data sync, JSON parsing, loop-breaking, and inference structural diffs.\n */\nexport class DataSyncDelegate {\n private host: IHostDataSync;\n private _lastPushedPayloadJson: string | null = null;\n private _lastPushedPayloadObj: Record<string, unknown> | null = null;\n private _lastReceivedInputObj: Record<string, unknown> | null = null;\n\n /**\n * Initializes a new DataSyncDelegate to handle data payload binding extraction.\n * @param host The parent host interface containing properties.\n */\n constructor(host: IHostDataSync) {\n this.host = host;\n }\n\n /**\n * Natively forces the UI5 framework to push updated properties back up to any bound ViewModels.\n */\n public pushToBindings(payload: Record<string, unknown>): void {\n const payloadStr = JSON.stringify(payload, null, 2);\n\n // Cache exact payload output to catch echoes on the inbound side\n this._lastPushedPayloadJson = payloadStr;\n this._lastPushedPayloadObj = deepEqual({}, payload) ? null : JSON.parse(JSON.stringify(payload)); // Safe clone\n\n this.host.setProperty(\"data\", payload, true);\n this.host.setProperty(\"dataJson\", payloadStr, true);\n }\n\n /**\n * Intercepts and parses live updates to the data payload from two-way Fiori bindings.\n */\n public handleInputDataHotSwap(propertyName: string, value: unknown, suppressInvalidate?: boolean): void {\n let incomingObj: Record<string, unknown> | null = null;\n\n if (typeof value === \"string\") {\n try {\n incomingObj = JSON.parse(value) as Record<string, unknown>;\n } catch (e) {\n this.host.setBaseProperty(propertyName, value, true);\n return;\n }\n } else {\n incomingObj = value as Record<string, unknown>;\n }\n\n if (incomingObj === null) {\n this.host.setBaseProperty(propertyName, value, true);\n return;\n }\n\n // Loop Breaker 1: Stale Data Injection\n if (this._lastReceivedInputObj && deepEqual(incomingObj, this._lastReceivedInputObj)) {\n if (this.host.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI]\", `Dropped stale data injection for ${propertyName}`, \"DataSyncDelegate\");\n }\n this.host.setBaseProperty(propertyName, value, suppressInvalidate);\n return;\n }\n\n // Loop Breaker 2: Two-Way Data Echoes\n if (this._lastPushedPayloadObj && deepEqual(incomingObj, this._lastPushedPayloadObj)) {\n if (this.host.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI]\", `Dropped echo for ${propertyName}`, \"DataSyncDelegate\");\n }\n this.host.setBaseProperty(propertyName, value, suppressInvalidate);\n return;\n }\n\n this._lastReceivedInputObj = extend(true, {}, incomingObj) as Record<string, unknown>;\n\n if (this.host.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI]\", `Accepted external injection for ${propertyName}`, \"DataSyncDelegate\");\n }\n\n this.host.setBaseProperty(propertyName, value, true);\n\n const stateManager = this.host.getStateManager();\n if (!stateManager) {\n this.host.invalidate();\n return;\n }\n\n try {\n stateManager.getModel().setData(incomingObj, false);\n\n if (!this.host.getProperty(\"schemaDefinition\") && typeof this.host.getParsedSchema === \"function\") {\n const newInferredSchema = SchemaNormalizer.inferSchemaFromData(incomingObj);\n const parsedSchema = this.host.getParsedSchema();\n if (!deepEqual(newInferredSchema, parsedSchema)) {\n this.host.tearDownGeneratedLayout();\n this.host.invalidate();\n }\n }\n } catch (e) {\n const msg = `Failed to hot-swap ${propertyName}: ` + (e as Error).message;\n Logger.error(\"[MetaUI]\", msg, \"DataSyncDelegate\");\n throw new Error(msg);\n }\n }\n}\n"],"mappings":"AAAA,yOAESA,EAAMC,EAAA,gBACNC,EAAgBC,EAAA,oBAkBlB,MAAMC,EAEDC,uBAAwC,KACxCC,sBAAwD,KACxDC,sBAAwD,KAMhEC,YAAYC,GACRC,KAAKD,KAAOA,CAChB,CAKOE,eAAeC,GAClB,MAAMC,EAAaC,KAAKC,UAAUH,EAAS,KAAM,GAGjDF,KAAKL,uBAAyBQ,EAC9BH,KAAKJ,sBAAwBU,EAAU,CAAC,EAAGJ,GAAW,KAAOE,KAAKG,MAAMH,KAAKC,UAAUH,IAEvFF,KAAKD,KAAKS,YAAY,OAAQN,EAAS,MACvCF,KAAKD,KAAKS,YAAY,WAAYL,EAAY,KAClD,CAKOM,uBAAuBC,EAAsBC,EAAgBC,GAChE,IAAIC,EAA8C,KAElD,UAAWF,IAAU,SAAU,CAC3B,IACIE,EAAcT,KAAKG,MAAMI,EAC7B,CAAE,MAAOG,GACLd,KAAKD,KAAKgB,gBAAgBL,EAAcC,EAAO,MAC/C,MACJ,CACJ,KAAO,CACHE,EAAcF,CAClB,CAEA,GAAIE,IAAgB,KAAM,CACtBb,KAAKD,KAAKgB,gBAAgBL,EAAcC,EAAO,MAC/C,MACJ,CAGA,GAAIX,KAAKH,uBAAyBS,EAAUO,EAAab,KAAKH,uBAAwB,CAClF,GAAIG,KAAKD,KAAKiB,YAAY,aAAc,CACpC1B,EAAO2B,MAAM,WAAY,oCAAoCP,IAAgB,mBACjF,CACAV,KAAKD,KAAKgB,gBAAgBL,EAAcC,EAAOC,GAC/C,MACJ,CAGA,GAAIZ,KAAKJ,uBAAyBU,EAAUO,EAAab,KAAKJ,uBAAwB,CAClF,GAAII,KAAKD,KAAKiB,YAAY,aAAc,CACpC1B,EAAO2B,MAAM,WAAY,oBAAoBP,IAAgB,mBACjE,CACAV,KAAKD,KAAKgB,gBAAgBL,EAAcC,EAAOC,GAC/C,MACJ,CAEAZ,KAAKH,sBAAwBqB,EAAO,KAAM,CAAC,EAAGL,GAE9C,GAAIb,KAAKD,KAAKiB,YAAY,aAAc,CACpC1B,EAAO2B,MAAM,WAAY,mCAAmCP,IAAgB,mBAChF,CAEAV,KAAKD,KAAKgB,gBAAgBL,EAAcC,EAAO,MAE/C,MAAMQ,EAAenB,KAAKD,KAAKqB,kBAC/B,IAAKD,EAAc,CACfnB,KAAKD,KAAKsB,aACV,MACJ,CAEA,IACIF,EAAaG,WAAWC,QAAQV,EAAa,OAE7C,IAAKb,KAAKD,KAAKiB,YAAY,4BAA8BhB,KAAKD,KAAKyB,kBAAoB,WAAY,CAC/F,MAAMC,EAAoBjC,EAAiBkC,oBAAoBb,GAC/D,MAAMc,EAAe3B,KAAKD,KAAKyB,kBAC/B,IAAKlB,EAAUmB,EAAmBE,GAAe,CAC7C3B,KAAKD,KAAK6B,0BACV5B,KAAKD,KAAKsB,YACd,CACJ,CACJ,CAAE,MAAOP,GACL,MAAMe,EAAM,sBAAsBnB,MAAoBI,EAAYgB,QAClExC,EAAOyC,MAAM,WAAYF,EAAK,oBAC9B,MAAM,IAAIG,MAAMH,EACpB,CACJ,EACH,IAAAI,EAAA,CAAAC,WAAA,MAAAD,EAAAvC,mBAAA,OAAAuC,CAAA","ignoreList":[],"sourceRoot":"controls/host/delegates"}},{"offset":{"line":11,"column":0},"map":{"version":3,"names":["Logger","_____utils_Logger","DialogDelegate","constructor","host","this","openInDialog","title","submitButtonText","isGenerated","cancelButtonText","dialogWidth","parentView","dialog","Dialog","contentWidth","content","beginButton","Button","text","type","press","success","triggerSubmit","close","err","error","message","fireEvent","fieldPath","endButton","afterClose","destroy","addDependent","open","__exports","__esModule"],"sources":["DialogDelegate.ts"],"sourcesContent":["import Dialog from \"sap/m/Dialog\";\nimport Button from \"sap/m/Button\";\nimport Control from \"sap/ui/core/Control\";\nimport { Logger } from \"../../../utils/Logger\";\n\nexport interface IHostDialog {\n generate(): void;\n triggerSubmit(): boolean;\n fireEvent(eventName: string, parameters?: Record<string, unknown>): this;\n}\n\n/**\n * Extracts all popup and dialog generation logic from the Host control.\n */\nexport class DialogDelegate {\n private host: IHostDialog & Control;\n\n /**\n * Initializes a new DialogDelegate to handle dialog-based rendering.\n * @param host The parent DynamicHost or GeneratorHost control.\n */\n constructor(host: IHostDialog & Control) {\n this.host = host;\n }\n\n /**\n * Dialog Modality: Opens the generated layout inside a sap.m.Dialog.\n * Automatically wires up customizable submit (default: 'OK') and 'Cancel' buttons.\n */\n public openInDialog(title: string = \"Form\", submitButtonText: string = \"OK\", isGenerated: boolean, cancelButtonText: string = \"Cancel\", dialogWidth: string = \"800px\", parentView?: Control): void {\n // UI5 PURITY: Do not manually force generate() here.\n // Opening the dialog mounts the host, natively firing onBeforeRendering() which triggers generation cleanly.\n\n const dialog = new Dialog({\n title: title,\n contentWidth: dialogWidth,\n content: [this.host], // Mount host inside the dialog\n beginButton: new Button({\n text: submitButtonText,\n type: \"Emphasized\",\n press: () => {\n try {\n const success = this.host.triggerSubmit();\n if (success) {\n dialog.close();\n }\n } catch (err) {\n Logger.error(\"[MetaUI] Catastrophic error during validation/submit pipeline\", (err as Error).message, \"DialogDelegate\");\n this.host.fireEvent(\"validationError\", { fieldPath: \"root\", message: (err as Error).message });\n }\n }\n }),\n endButton: new Button({\n text: cancelButtonText,\n press: () => {\n this.host.fireEvent(\"cancel\");\n dialog.close();\n }\n }),\n afterClose: () => {\n dialog.destroy();\n }\n });\n\n if (parentView && typeof parentView.addDependent === \"function\") {\n parentView.addDependent(dialog);\n }\n\n dialog.open();\n }\n}\n"],"mappings":"AAAA,iLAGSA,EAAMC,EAAA,UAWR,MAAMC,EAOTC,YAAYC,GACRC,KAAKD,KAAOA,CAChB,CAMOE,aAAaC,EAAgB,OAAQC,EAA2B,KAAMC,EAAsBC,EAA2B,SAAUC,EAAsB,QAASC,GAInK,MAAMC,EAAS,IAAIC,EAAO,CACtBP,MAAOA,EACPQ,aAAcJ,EACdK,QAAS,CAACX,KAAKD,MACfa,YAAa,IAAIC,EAAO,CACpBC,KAAMX,EACNY,KAAM,aACNC,MAAOA,KACH,IACI,MAAMC,EAAUjB,KAAKD,KAAKmB,gBAC1B,GAAID,EAAS,CACTT,EAAOW,OACX,CACJ,CAAE,MAAOC,GACLzB,EAAO0B,MAAM,gEAAkED,EAAcE,QAAS,kBACtGtB,KAAKD,KAAKwB,UAAU,kBAAmB,CAAEC,UAAW,OAAQF,QAAUF,EAAcE,SACxF,KAGRG,UAAW,IAAIZ,EAAO,CAClBC,KAAMT,EACNW,MAAOA,KACHhB,KAAKD,KAAKwB,UAAU,UACpBf,EAAOW,WAGfO,WAAYA,KACRlB,EAAOmB,aAIf,GAAIpB,UAAqBA,EAAWqB,eAAiB,WAAY,CAC7DrB,EAAWqB,aAAapB,EAC5B,CAEAA,EAAOqB,MACX,EACH,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAAjC,iBAAA,OAAAiC,CAAA","ignoreList":[],"sourceRoot":"controls/host/delegates"}},{"offset":{"line":12,"column":0},"map":{"version":3,"names":["Logger","_____utils_Logger","ODataDelegate","odataType","isSyncing","constructor","host","context","this","detectODataType","model","getModel","sClassName","getMetadata","getName","indexOf","syncToEngine","requestObject","then","oData","pushPayload","catch","err","error","message","getObject","cleanData","key","Object","keys","startsWith","setProperty","handleFieldChange","fieldPath","value","getProperty","debug","e","__exports","__esModule"],"sources":["ODataDelegate.ts"],"sourcesContent":["import { DynamicHost } from \"../DynamicHost\";\nimport { Logger } from \"../../../utils/Logger\";\nimport ODataV4Context from \"sap/ui/model/odata/v4/Context\";\nimport Context from \"sap/ui/model/Context\";\n\n/**\n * Universal OData Delegate.\n * Natively detects and manages two-way synchronization for both OData V2 and V4 contexts\n * without requiring controller-level mappings.\n */\nexport class ODataDelegate {\n private host: DynamicHost;\n private context: ODataV4Context | Context;\n private odataType: \"V2\" | \"V4\" | null = null;\n private isSyncing: boolean = false;\n\n /**\n * Initializes a new instance of the ODataDelegate.\n * \n * @param {DynamicHost} host The parent MetaUI DynamicHost instance managing the UI generation.\n * @param {Context} context The active UI5 Model Context bound to the host.\n */\n constructor(host: DynamicHost, context: ODataV4Context | Context) {\n this.host = host;\n this.context = context;\n this.detectODataType();\n }\n\n /**\n * Evaluates the underlying UI5 Model bound to the context to determine if it is an\n * OData V2 or OData V4 model. This determination drives the synchronization strategy.\n * \n * @private\n */\n private detectODataType(): void {\n const model = this.context.getModel();\n // sap.ui.model.odata.v4.ODataModel\n // sap.ui.model.odata.v2.ODataModel\n const sClassName = model.getMetadata().getName();\n if (sClassName.indexOf(\"v4\") > -1) {\n this.odataType = \"V4\";\n } else if (sClassName.indexOf(\"v2\") > -1 || sClassName.indexOf(\"ODataModel\") > -1) {\n this.odataType = \"V2\";\n }\n }\n\n /**\n * Extracts the full entity payload from the bound OData context and pushes it to the Engine.\n * V4 uses an asynchronous requestObject(), while V2 retrieves it synchronously.\n * \n * @public\n */\n public syncToEngine(): void {\n if (!this.odataType) return;\n\n if (this.odataType === \"V4\") {\n // V4 uses async requestObject()\n if (typeof this.context.requestObject === \"function\") {\n this.context.requestObject().then((oData: unknown) => {\n this.pushPayload(oData);\n }).catch((err: Error) => {\n Logger.error(\"[MetaUI]\", \"Failed to extract V4 Context payload: \" + err.message, \"ODataDelegate\");\n });\n }\n } else if (this.odataType === \"V2\") {\n // V2 uses sync getObject()\n const oData = this.context.getObject();\n if (oData) {\n this.pushPayload(oData);\n }\n }\n }\n\n /**\n * Cleans the raw OData payload by stripping framework metadata properties (keys starting with '@' or '__')\n * and pushes the sanitized business data into the MetaUI DynamicHost state manager.\n * \n * @param {unknown} oData The raw JSON object extracted from the OData model context.\n * @private\n */\n private pushPayload(oData: unknown): void {\n if (!oData) return;\n \n // Remove OData metadata properties before pushing to MetaUI\n const cleanData = { ...(oData as Record<string, unknown>) };\n for (const key of Object.keys(cleanData)) {\n if (key.startsWith(\"@\") || key.startsWith(\"__\")) {\n delete cleanData[key];\n }\n }\n\n this.isSyncing = true;\n this.host.setProperty(\"data\", cleanData);\n this.isSyncing = false;\n }\n\n /**\n * Intercepts a field change from the MetaUI Engine and translates it into an OData PATCH.\n */\n public handleFieldChange(fieldPath: string, value: unknown): void {\n if (this.isSyncing || !this.odataType) return;\n\n try {\n if (this.odataType === \"V4\") {\n // V4 sets property directly on context\n this.context.setProperty(fieldPath, value);\n } else if (this.odataType === \"V2\") {\n // V2 sets property on model, specifying the context path\n const model = this.context.getModel();\n model.setProperty(fieldPath, value, this.context);\n }\n if (this.host.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI]\", `ODataDelegate Patched ${fieldPath} = ${value} via ${this.odataType}`, \"ODataDelegate\");\n }\n } catch (e) {\n Logger.error(\"[MetaUI]\", `Failed to patch OData context: ${(e as Error).message}`, \"ODataDelegate\");\n }\n }\n}\n"],"mappings":"AAAA,8IACSA,EAAMC,EAAA,UASR,MAAMC,EAGDC,UAAgC,KAChCC,UAAqB,MAQ7BC,YAAYC,EAAmBC,GAC3BC,KAAKF,KAAOA,EACZE,KAAKD,QAAUA,EACfC,KAAKC,iBACT,CAQQA,kBACJ,MAAMC,EAAQF,KAAKD,QAAQI,WAG3B,MAAMC,EAAaF,EAAMG,cAAcC,UACvC,GAAIF,EAAWG,QAAQ,OAAS,EAAG,CAC/BP,KAAKL,UAAY,IACrB,MAAO,GAAIS,EAAWG,QAAQ,OAAS,GAAKH,EAAWG,QAAQ,eAAiB,EAAG,CAC/EP,KAAKL,UAAY,IACrB,CACJ,CAQOa,eACH,IAAKR,KAAKL,UAAW,OAErB,GAAIK,KAAKL,YAAc,KAAM,CAEzB,UAAWK,KAAKD,QAAQU,gBAAkB,WAAY,CAClDT,KAAKD,QAAQU,gBAAgBC,KAAMC,IAC/BX,KAAKY,YAAYD,KAClBE,MAAOC,IACNtB,EAAOuB,MAAM,WAAY,yCAA2CD,EAAIE,QAAS,kBAEzF,CACJ,MAAO,GAAIhB,KAAKL,YAAc,KAAM,CAEhC,MAAMgB,EAAQX,KAAKD,QAAQkB,YAC3B,GAAIN,EAAO,CACPX,KAAKY,YAAYD,EACrB,CACJ,CACJ,CASQC,YAAYD,GAChB,IAAKA,EAAO,OAGZ,MAAMO,EAAY,IAAMP,GACxB,IAAK,MAAMQ,KAAOC,OAAOC,KAAKH,GAAY,CACtC,GAAIC,EAAIG,WAAW,MAAQH,EAAIG,WAAW,MAAO,QACtCJ,EAAUC,EACrB,CACJ,CAEAnB,KAAKJ,UAAY,KACjBI,KAAKF,KAAKyB,YAAY,OAAQL,GAC9BlB,KAAKJ,UAAY,KACrB,CAKO4B,kBAAkBC,EAAmBC,GACxC,GAAI1B,KAAKJ,YAAcI,KAAKL,UAAW,OAEvC,IACI,GAAIK,KAAKL,YAAc,KAAM,CAEzBK,KAAKD,QAAQwB,YAAYE,EAAWC,EACxC,MAAO,GAAI1B,KAAKL,YAAc,KAAM,CAEhC,MAAMO,EAAQF,KAAKD,QAAQI,WAC3BD,EAAMqB,YAAYE,EAAWC,EAAO1B,KAAKD,QAC7C,CACA,GAAIC,KAAKF,KAAK6B,YAAY,aAAc,CACpCnC,EAAOoC,MAAM,WAAY,yBAAyBH,OAAeC,SAAa1B,KAAKL,YAAa,gBACpG,CACJ,CAAE,MAAOkC,GACLrC,EAAOuB,MAAM,WAAY,kCAAmCc,EAAYb,UAAW,gBACvF,CACJ,EACH,IAAAc,EAAA,CAAAC,WAAA,MAAAD,EAAApC,gBAAA,OAAAoC,CAAA","ignoreList":[],"sourceRoot":"controls/host/delegates"}},{"offset":{"line":13,"column":0},"map":{"version":3,"names":["Logger","_____utils_Logger","ValidationDelegate","constructor","host","this","registerObject","control","unregisterObject","removeAllMessages","stateManager","getStateManager","getProperty","messageManager","Messaging","messages","getMessageModel","getData","messagesToRemove","filter","m","getMessageProcessor","getId","getModel","length","removeMessages","pushMessage","path","text","targetPath","replace","displayText","warn","addMessages","Message","message","type","coreLibrary","MessageType","Error","target","processor","addCustomError","fieldPath","code","clearCustomError","processorId","getTarget","getCode","mountCrashBoundary","error","errorPage","IllustratedMessage","title","description","setAggregation","__exports","__esModule"],"sources":["ValidationDelegate.ts"],"sourcesContent":["import IllustratedMessage from \"sap/m/IllustratedMessage\";\nimport Messaging from \"sap/ui/core/Messaging\";\nimport Control from \"sap/ui/core/Control\";\nimport { StateManager } from \"../../../core/StateManager\";\nimport { Logger } from \"../../../utils/Logger\";\nimport Message from \"sap/ui/core/message/Message\";\nimport coreLibrary from \"sap/ui/core/library\";\n\nexport interface IHostValidation {\n getProperty(name: string): unknown;\n setAggregation(aggregationName: string, object: sap.ui.core.Control, suppressInvalidate?: boolean): this;\n getStateManager(): StateManager | null;\n}\n\n/**\n * Handles Fiori MessageManager integration and provides a standardized Error Boundary UI fallback.\n */\nexport class ValidationDelegate {\n private host: IHostValidation;\n\n /**\n * Initializes the ValidationDelegate for registering controls to the global MessageManager.\n * @param host The parent host interface.\n */\n constructor(host: IHostValidation) {\n this.host = host;\n }\n\n /**\n * Registers a control and all its children with the global MessageManager.\n * (Deprecated: Native registration causes UI5 to aggressively clear custom schema validation messages \n * on every keystroke. MetaUI handles valueState manually via plugins).\n */\n public registerObject(control: Control): void {\n // Do nothing to prevent UI5 from hijacking valueState and clearing our manual messages\n }\n\n /**\n * Unregisters a control from the global MessageManager.\n */\n public unregisterObject(control: Control): void {\n // Do nothing\n }\n\n public removeAllMessages(): void {\n const stateManager = this.host.getStateManager();\n if (stateManager && this.host.getProperty(\"useMessageManager\")) {\n const messageManager = Messaging;\n const messages = messageManager.getMessageModel().getData();\n const messagesToRemove = messages.filter((m: sap.ui.core.message.Message) =>\n m.getMessageProcessor() && m.getMessageProcessor().getId() === stateManager.getModel().getId()\n );\n if (messagesToRemove && messagesToRemove.length > 0) {\n messageManager.removeMessages(messagesToRemove);\n }\n }\n }\n\n /**\n * Pushes a validation message to the console, and optionally to the MessageManager.\n */\n public pushMessage(path: string, text: string): void {\n const targetPath = path ? `/${path.replace(/^\\//, \"\")}` : \"\";\n const displayText = path ? `Field '${path}': ${text}` : text;\n\n if (path) {\n Logger.warn(`[MetaUI Validation Error] ${displayText}`);\n } else {\n Logger.warn(`[MetaUI Validation Error] Global - ${text}`);\n }\n\n if (this.host.getProperty(\"useMessageManager\") === true) {\n const messageManager = Messaging;\n const stateManager = this.host.getStateManager();\n messageManager.addMessages(new Message({\n message: displayText,\n type: coreLibrary.MessageType.Error,\n target: targetPath,\n processor: stateManager?.getModel()\n }));\n }\n }\n\n /**\n * Imperatively invalidates a field and highlights it with an error message.\n * Uses a specific 'CustomError' code to distinguish it from internal schema validations.\n * \n * @param fieldPath The internal JSON path of the field to highlight.\n * @param message The custom error message to display.\n */\n public addCustomError(fieldPath: string, message: string): void {\n if (this.host.getProperty(\"useMessageManager\") !== true) {\n return;\n }\n\n const stateManager = this.host.getStateManager();\n if (!stateManager) {\n return;\n }\n\n Messaging.addMessages(new Message({\n message: message,\n type: coreLibrary.MessageType.Error,\n target: `/${fieldPath.replace(/^\\//, \"\")}`,\n processor: stateManager.getModel(),\n code: \"CustomError\"\n }));\n }\n\n /**\n * Reverts a custom error state on a field, safely ignoring native schema validations.\n * \n * @param fieldPath The internal JSON path of the field to clear.\n */\n public clearCustomError(fieldPath: string): void {\n if (this.host.getProperty(\"useMessageManager\") !== true) {\n return;\n }\n\n const stateManager = this.host.getStateManager();\n if (!stateManager) {\n return;\n }\n\n const target = `/${fieldPath.replace(/^\\//, \"\")}`;\n const processorId = stateManager.getModel().getId();\n const messages = Messaging.getMessageModel().getData() as sap.ui.core.message.Message[];\n\n const messagesToRemove = messages.filter(m => \n m.getTarget() === target && \n m.getCode() === \"CustomError\" &&\n m.getMessageProcessor()?.getId() === processorId\n );\n\n if (messagesToRemove.length > 0) {\n Messaging.removeMessages(messagesToRemove);\n }\n }\n\n /**\n * Triggers a visual Error Page (Crash Boundary) when generation catastrophically fails.\n */\n public mountCrashBoundary(error: Error): void {\n Logger.error(\"[MetaUI] Engine failed to generate layout. Preventing Launchpad crash.\", error.message, \"ValidationDelegate\");\n\n const errorPage = new IllustratedMessage({\n title: \"UI Generation Failed\",\n description: \"The dynamic schema could not be rendered. Please check the Fiori console for diagnostic logs.\"\n });\n\n this.host.setAggregation(\"_content\", errorPage);\n }\n}\n"],"mappings":"AAAA,kQAISA,EAAMC,EAAA,UAaR,MAAMC,EAOTC,YAAYC,GACRC,KAAKD,KAAOA,CAChB,CAOOE,eAAeC,GAClB,CAMGC,iBAAiBD,GACpB,CAGGE,oBACH,MAAMC,EAAeL,KAAKD,KAAKO,kBAC/B,GAAID,GAAgBL,KAAKD,KAAKQ,YAAY,qBAAsB,CAC5D,MAAMC,EAAiBC,EACvB,MAAMC,EAAWF,EAAeG,kBAAkBC,UAClD,MAAMC,EAAmBH,EAASI,OAAQC,GACtCA,EAAEC,uBAAyBD,EAAEC,sBAAsBC,UAAYZ,EAAaa,WAAWD,SAE3F,GAAIJ,GAAoBA,EAAiBM,OAAS,EAAG,CACjDX,EAAeY,eAAeP,EAClC,CACJ,CACJ,CAKOQ,YAAYC,EAAcC,GAC7B,MAAMC,EAAaF,EAAO,IAAIA,EAAKG,QAAQ,MAAO,MAAQ,GAC1D,MAAMC,EAAcJ,EAAO,UAAUA,OAAUC,IAASA,EAExD,GAAID,EAAM,CACN3B,EAAOgC,KAAK,6BAA6BD,IAC7C,KAAO,CACH/B,EAAOgC,KAAK,sCAAsCJ,IACtD,CAEA,GAAIvB,KAAKD,KAAKQ,YAAY,uBAAyB,KAAM,CACrD,MAAMC,EAAiBC,EACvB,MAAMJ,EAAeL,KAAKD,KAAKO,kBAC/BE,EAAeoB,YAAY,IAAIC,EAAQ,CACnCC,QAASJ,EACTK,KAAMC,EAAYC,YAAYC,MAC9BC,OAAQX,EACRY,UAAW/B,GAAca,aAEjC,CACJ,CASOmB,eAAeC,EAAmBR,GACrC,GAAI9B,KAAKD,KAAKQ,YAAY,uBAAyB,KAAM,CACrD,MACJ,CAEA,MAAMF,EAAeL,KAAKD,KAAKO,kBAC/B,IAAKD,EAAc,CACf,MACJ,CAEAI,EAAUmB,YAAY,IAAIC,EAAQ,CAC9BC,QAASA,EACTC,KAAMC,EAAYC,YAAYC,MAC9BC,OAAQ,IAAIG,EAAUb,QAAQ,MAAO,MACrCW,UAAW/B,EAAaa,WACxBqB,KAAM,gBAEd,CAOOC,iBAAiBF,GACpB,GAAItC,KAAKD,KAAKQ,YAAY,uBAAyB,KAAM,CACrD,MACJ,CAEA,MAAMF,EAAeL,KAAKD,KAAKO,kBAC/B,IAAKD,EAAc,CACf,MACJ,CAEA,MAAM8B,EAAS,IAAIG,EAAUb,QAAQ,MAAO,MAC5C,MAAMgB,EAAcpC,EAAaa,WAAWD,QAC5C,MAAMP,EAAWD,EAAUE,kBAAkBC,UAE7C,MAAMC,EAAmBH,EAASI,OAAOC,GACrCA,EAAE2B,cAAgBP,GAClBpB,EAAE4B,YAAc,eAChB5B,EAAEC,uBAAuBC,UAAYwB,GAGzC,GAAI5B,EAAiBM,OAAS,EAAG,CAC7BV,EAAUW,eAAeP,EAC7B,CACJ,CAKO+B,mBAAmBC,GACtBlD,EAAOkD,MAAM,yEAA0EA,EAAMf,QAAS,sBAEtG,MAAMgB,EAAY,IAAIC,EAAmB,CACrCC,MAAO,uBACPC,YAAa,kGAGjBjD,KAAKD,KAAKmD,eAAe,WAAYJ,EACzC,EACH,IAAAK,EAAA,CAAAC,WAAA,MAAAD,EAAAtD,qBAAA,OAAAsD,CAAA","ignoreList":[],"sourceRoot":"controls/host/delegates"}},{"offset":{"line":14,"column":0},"map":{"version":3,"names":["Registry","___Registry","OperatorRegistry","register","a","b","ConditionEngine","constructor","schema","this","plugins","Map","handleEvent","fieldKey","isValid","registerPlugin","bindingPath","plugin","set","destroy","clear","__exports","__esModule"],"sources":["ConditionEngine.ts"],"sourcesContent":["/**\n * @file ConditionEngine.ts\n * @description Evaluates dynamic rules to alter the schema in real-time.\n */\n\nimport { IPlugin } from \"../interfaces/IPlugin\";\nimport { ISchema } from \"../interfaces/ISchema\";\nimport { Registry } from \"./Registry\";\n\nexport type ConditionOperator = (a: unknown, b: unknown) => boolean;\n\nexport const OperatorRegistry = new Registry<ConditionOperator>(\"Operators\");\n\n// Register basic default operators\nOperatorRegistry.register(\"==\", (a, b) => a == b);\nOperatorRegistry.register(\"===\", (a, b) => a === b);\nOperatorRegistry.register(\"!=\", (a, b) => a != b);\nOperatorRegistry.register(\"!==\", (a, b) => a !== b);\nOperatorRegistry.register(\">\", (a, b) => a > b);\nOperatorRegistry.register(\"<\", (a, b) => a < b);\nOperatorRegistry.register(\">=\", (a, b) => a >= b);\nOperatorRegistry.register(\"<=\", (a, b) => a <= b);\n\n/**\n * Engine that listens to the EventBus and evaluates cross-field dependencies (e.g. visibleOn, enabledOn).\n * It delegates actual evaluations to the configurable `OperatorRegistry`.\n * \n * @namespace nz.co.siliconst.ui5.metaui.core\n * @public\n */\nexport class ConditionEngine {\n /** The active form schema being evaluated. */\n private schema: ISchema;\n /**\n * Initializes the ConditionEngine with the active schema.\n * @param schema The current UI layout schema.\n */\n constructor(schema: ISchema) {\n this.schema = schema;\n }\n\n\n\n /** Internal map tracking active plugins against their binding paths for real-time state updates. */\n private plugins: Map<string, IPlugin> = new Map();\n\n /**\n * Internal handler to evaluate business rules when a field is updated.\n * @param fieldKey The key of the field that was changed\n * @param isValid Whether the field is currently valid\n */\n public handleEvent(fieldKey: string, isValid: boolean): void {\n // Evaluate conditions via registered operators if a rule system is added later\n }\n\n /**\n * Registers a rendered plugin so the condition engine can push dynamic state updates to it.\n * \n * @param bindingPath The JSON path representing the field within the payload.\n * @param plugin The instantiated plugin handling the field.\n */\n public registerPlugin(bindingPath: string, plugin: IPlugin): void {\n this.plugins.set(bindingPath, plugin);\n }\n\n /**\n * Cleans up listeners to prevent memory leaks on destruction.\n */\n public destroy(): void {\n this.plugins.clear();\n }\n}\n"],"mappings":"AAAA,4GAAA,MAOSA,EAAQC,EAAA,YAIV,MAAMC,EAAmB,IAAIF,EAA4B,aAGhEE,EAAiBC,SAAS,KAAM,CAACC,EAAGC,IAAMD,GAAKC,GAC/CH,EAAiBC,SAAS,MAAO,CAACC,EAAGC,IAAMD,IAAMC,GACjDH,EAAiBC,SAAS,KAAM,CAACC,EAAGC,IAAMD,GAAKC,GAC/CH,EAAiBC,SAAS,MAAO,CAACC,EAAGC,IAAMD,IAAMC,GACjDH,EAAiBC,SAAS,IAAK,CAACC,EAAGC,IAAMD,EAAIC,GAC7CH,EAAiBC,SAAS,IAAK,CAACC,EAAGC,IAAMD,EAAIC,GAC7CH,EAAiBC,SAAS,KAAM,CAACC,EAAGC,IAAMD,GAAKC,GAC/CH,EAAiBC,SAAS,KAAM,CAACC,EAAGC,IAAMD,GAAKC,GASxC,MAAMC,EAOTC,YAAYC,GACRC,KAAKD,OAASA,CAClB,CAKQE,QAAgC,IAAIC,IAOrCC,YAAYC,EAAkBC,GACjC,CASGC,eAAeC,EAAqBC,GACvCR,KAAKC,QAAQQ,IAAIF,EAAaC,EAClC,CAKOE,UACHV,KAAKC,QAAQU,OACjB,EACH,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAAnB,mBAAAmB,EAAAf,kBAAA,OAAAe,CAAA","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":15,"column":0},"map":{"version":3,"names":["DefaultLayoutGenerator","ensureLayout","schema","uiLayout","Array","isArray","length","type","props","items","properties","Object","keys","elements","this","generateElementsFromProperties","filter","e","label","title","basePath","key","prop","currentPath","push","ui","scope","error","msg","message","__ui5_require_async","then","m","Logger","Error","__exports","__esModule"],"sources":["DefaultLayoutGenerator.ts"],"sourcesContent":["/**\n * @file DefaultLayoutGenerator.ts\n * @description Automatically synthesizes a default UI layout for schemas that lack an explicit mapping.\n */\n\nimport { ISchema, ILayoutElement } from \"../interfaces/ISchema\";\n\n/**\n * Encapsulates the logic to dynamically build a safe, default layout orchestration\n * when the developer or backend fails to provide an explicit `uiLayout`.\n * \n * By elevating this into a dedicated utility, we avoid polluting layout engines\n * (like FormLayout or TableLayout) with structural inference responsibilities.\n * \n * @namespace nz.co.siliconst.ui5.metaui.core\n * @public\n */\nexport class DefaultLayoutGenerator {\n /**\n * Inspects a schema. If it has properties but no `uiLayout`, it synthesizes a default.\n * @param schema The ISchema dictionary.\n * @returns boolean True if a layout was synthesized, false if it already existed or was empty.\n */\n public static ensureLayout(schema: ISchema): boolean {\n // If it already has a valid array, do nothing\n if (schema.uiLayout && Array.isArray(schema.uiLayout) && schema.uiLayout.length > 0) {\n return false;\n }\n\n const isArray = schema.type === \"array\";\n const props = isArray ? schema.items?.properties : schema.properties;\n\n if (!props || Object.keys(props).length === 0) {\n return false; // Nothing to map\n }\n\n const elements = this.generateElementsFromProperties(props, \"#/properties\");\n\n if (isArray) {\n // Table layouts expect an array of flat Controls at the root uiLayout\n // For tables, we flatten the deep elements or just render the root level\n // To keep it safe, we'll just use the flat elements for tables\n schema.uiLayout = elements.filter(e => e.type === \"Control\");\n } else {\n // Form layouts expect a grouped structure\n schema.uiLayout = [\n {\n type: \"Group\",\n label: schema.title,\n elements: elements\n }\n ];\n }\n\n return true;\n }\n\n /**\n * Recursively traverses property metadata to synthesize generic Group and Control layout definitions.\n * @param props The properties object from the schema.\n * @param basePath The absolute JSON scope path to prefix bindings.\n * @returns An array of generated layout element descriptors.\n */\n private static generateElementsFromProperties(props: Record<string, import(\"../interfaces/ISchema\").IPropertyMetadata>, basePath: string): ILayoutElement[] {\n const elements: ILayoutElement[] = [];\n for (const key of Object.keys(props)) {\n try {\n const prop = props[key];\n const currentPath = `${basePath}/${key}`;\n\n if (prop.type === \"object\" && prop.properties) {\n elements.push({\n type: \"Group\",\n label: prop.ui?.label || key,\n elements: this.generateElementsFromProperties(prop.properties, `${currentPath}/properties`)\n });\n } else {\n elements.push({\n type: \"Control\",\n scope: currentPath\n });\n }\n } catch (error) {\n // Do not swallow errors. A failure to synthesize a property is a critical failure.\n const msg = `[MetaUI] DefaultLayoutGenerator failed to synthesize property '${key}': ${(error as Error).message}`;\n import(\"../utils/Logger\").then(m => m.Logger.error(msg));\n throw new Error(msg);\n }\n }\n return elements;\n }\n}\n"],"mappings":"AAAA,kWAiBO,MAAMA,EAMT,mBAAcC,CAAaC,GAEvB,GAAIA,EAAOC,UAAYC,MAAMC,QAAQH,EAAOC,WAAaD,EAAOC,SAASG,OAAS,EAAG,CACjF,OAAO,KACX,CAEA,MAAMD,EAAUH,EAAOK,OAAS,QAChC,MAAMC,EAAQH,EAAUH,EAAOO,OAAOC,WAAaR,EAAOQ,WAE1D,IAAKF,GAASG,OAAOC,KAAKJ,GAAOF,SAAW,EAAG,CAC3C,OAAO,KACX,CAEA,MAAMO,EAAWC,KAAKC,+BAA+BP,EAAO,gBAE5D,GAAIH,EAAS,CAITH,EAAOC,SAAWU,EAASG,OAAOC,GAAKA,EAAEV,OAAS,UACtD,KAAO,CAEHL,EAAOC,SAAW,CACd,CACII,KAAM,QACNW,MAAOhB,EAAOiB,MACdN,SAAUA,GAGtB,CAEA,OAAO,IACX,CAQA,qCAAeE,CAA+BP,EAA0EY,GACpH,MAAMP,EAA6B,GACnC,IAAK,MAAMQ,KAAOV,OAAOC,KAAKJ,GAAQ,CAClC,IACI,MAAMc,EAAOd,EAAMa,GACnB,MAAME,EAAc,GAAGH,KAAYC,IAEnC,GAAIC,EAAKf,OAAS,UAAYe,EAAKZ,WAAY,CAC3CG,EAASW,KAAK,CACVjB,KAAM,QACNW,MAAOI,EAAKG,IAAIP,OAASG,EACzBR,SAAUC,KAAKC,+BAA+BO,EAAKZ,WAAY,GAAGa,iBAE1E,KAAO,CACHV,EAASW,KAAK,CACVjB,KAAM,UACNmB,MAAOH,GAEf,CACJ,CAAE,MAAOI,GAEL,MAAMC,EAAM,kEAAkEP,OAAUM,EAAgBE,UACxGC,EAAO,mBAAmBC,KAAKC,GAAKA,EAAEC,OAAON,MAAMC,IACnD,MAAM,IAAIM,MAAMN,EACpB,CACJ,CACA,OAAOf,CACX,EACH,IAAAsB,EAAA,CAAAC,WAAA,MAAAD,EAAAnC,yBAAA,OAAAmC,CAAA","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":16,"column":0},"map":{"version":3,"names":["ConditionEngine","___ConditionEngine","PluginRegistry","___PluginRegistry","Logger","___utils_Logger","DefaultLayoutGenerator","___DefaultLayoutGenerator","Engine","conditionEngine","activePlugins","isEditable","hasPartialRenderingErrors","useMessageManager","constructor","editable","this","build","schema","model","modelName","onSubmit","engineScopeId","onChange","activeModel","isValid","fieldKey","errorMessage","controlId","handleEvent","ensureLayout","warn","layoutStrategy","type","layoutManager","getInstance","getLayout","render","error","msg","message","showErrorPopup","Text","text","generateField","fieldMeta","bindingPath","isTemplate","plugin","getPlugin","ui","widget","setEditable","setUseMessageManager","push","path","scopeId","undefined","control","registerPlugin","generateLayout","validateAll","applyVisualState","errors","item","result","validate","setVisualValidationState","replace","name","getPluginByPath","cleanPath","startsWith","match","find","p","destroy","messageManager","Messaging","existingMessages","getMessageModel","getData","messagesToRemove","targetPath","matched","filter","getTarget","getMessageProcessor","getId","length","removeMessages","__exports","__esModule"],"sources":["Engine.ts"],"sourcesContent":["/**\n * @file Engine.ts\n * @description The central orchestrator that routes data between the Layout Factory and Plugin Registry (v2).\n */\n\nimport { ISchema, IPropertyMetadata } from \"../interfaces/ISchema\";\nimport { ILayoutManager } from \"../interfaces/ILayoutManager\";\nimport { IPlugin, IPluginValidationResult } from \"../interfaces/IPlugin\";\nimport { ConditionEngine } from \"./ConditionEngine\";\nimport { PluginRegistry } from \"./PluginRegistry\";\nimport Control from \"sap/ui/core/Control\";\nimport VBox from \"sap/m/VBox\";\nimport Text from \"sap/m/Text\";\nimport { Logger } from \"../utils/Logger\";\nimport { DefaultLayoutGenerator } from \"./DefaultLayoutGenerator\";\nimport Core from \"sap/ui/core/Core\";\nimport Messaging from \"sap/ui/core/Messaging\";\n\n/**\n * The Engine is responsible for translating a normalized schema into a physical UI5 layout.\n * It delegates layout generation to the configured `LayoutManager` and field generation to the `PluginRegistry`.\n * It strictly routes execution flow and tracks active plugins for validation.\n * It embodies the \"Plugin-First Philosophy\" by routing all complex field and layout rendering\n * through discrete, decoupled plugins rather than handling native overrides.\n * \n * @namespace nz.co.siliconst.ui5.metaui.core\n * @public\n */\nexport class Engine {\n /** Handles dynamic conditional logic across the active form. */\n private conditionEngine: ConditionEngine | null = null;\n\n /** Array of all instantiated plugins generated during the current build. */\n private activePlugins: { plugin: IPlugin, path: string }[] = [];\n\n /** Deterministic scope ID injected by the host control to prevent clone collisions. */\n public engineScopeId?: string;\n\n private activeModel?: sap.ui.model.Model;\n\n /** Callback to notify the host that an internal field changed. */\n public onChange?: (isValid: boolean, fieldKey?: string, errorMessage?: string, controlId?: string) => void;\n\n /** Tracks whether the entire engine is running in Editable mode. */\n public readonly isEditable: boolean = true;\n\n /** Tracks if any fields or sub-layouts failed to render, requiring a warning strip. */\n public hasPartialRenderingErrors: boolean = false;\n\n /** Tracks whether the engine should delegate visual state to the global MessageManager. */\n public readonly useMessageManager: boolean = false;\n\n /**\n * Initializes a new Engine instance.\n * @param editable Whether the engine should render form fields as editable or read-only.\n * @param useMessageManager Whether to delegate visual state to UI5 MessageManager.\n */\n constructor(editable: boolean = true, useMessageManager: boolean = false) {\n this.isEditable = editable;\n this.useMessageManager = useMessageManager;\n }\n\n /**\n * Bootstraps the layout generation process by resolving the correct layout strategy.\n * \n * @param schema The normalized JSON schema representing the view.\n * @param model The active StateManager JSONModel instance.\n * @param modelName The UI5 model alias used for isolation.\n * @param onSubmit Callback fired when form is submitted.\n * @param engineScopeId Deterministic scope ID for this engine instance.\n * @param onChange Callback fired when field values change.\n * @returns The generated root UI5 Control container.\n */\n public build(schema: ISchema, model: sap.ui.model.Model, modelName: string = \"meta\", onSubmit?: () => void, engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string, errorMessage?: string, controlId?: string) => void): Control {\n this.conditionEngine = new ConditionEngine(schema);\n this.activePlugins = [];\n this.activeModel = model;\n this.engineScopeId = engineScopeId;\n this.onChange = (isValid: boolean, fieldKey?: string, errorMessage?: string, controlId?: string) => {\n if (this.conditionEngine && fieldKey) {\n this.conditionEngine.handleEvent(fieldKey, isValid);\n }\n if (onChange) {\n onChange(isValid, fieldKey, errorMessage, controlId);\n }\n };\n\n try {\n // Intercept and synthesize a default layout if the developer/backend failed to provide one\n if (DefaultLayoutGenerator.ensureLayout(schema)) {\n Logger.warn(\"[MetaUI Engine] Missing 'uiLayout' array in schema. Synthesized a default layout mapping to prevent a blank render.\");\n }\n\n const layoutStrategy = schema.layoutStrategy || (schema.type === \"array\" ? \"table\" : \"form\");\n const layoutManager = PluginRegistry.getInstance().getLayout(layoutStrategy);\n\n return layoutManager.render(schema, modelName, this, onSubmit);\n } catch (error) {\n this.hasPartialRenderingErrors = true;\n const msg = (error as Error).message;\n Logger.error(\"[MetaUI Engine] Critical error during layout generation\", msg);\n Logger.showErrorPopup(`Engine failed to generate the layout.\\n\\nDetails: ${msg}`);\n return new Text({ text: \"Critical Layout Error\" });\n }\n }\n\n /**\n * Instantiates the correct plugin for a specific field based on type and widget hints,\n * and tracks the plugin for global validation.\n * \n * @param fieldMeta The metadata schema specific to the field.\n * @param bindingPath The JSON path representing the field within the payload.\n * @param modelName The UI5 JSONModel name used for data binding.\n * @returns The generated UI5 Control for the field.\n */\n public generateField(fieldMeta: IPropertyMetadata, bindingPath: string, modelName: string, isTemplate: boolean = false): Control {\n try {\n const plugin = PluginRegistry.getInstance().getPlugin(fieldMeta.type || \"string\", fieldMeta.ui?.widget);\n plugin.setEditable(this.isEditable);\n \n if (typeof plugin.setUseMessageManager === \"function\") {\n plugin.setUseMessageManager(this.useMessageManager);\n }\n\n if (!isTemplate) {\n this.activePlugins.push({ plugin, path: bindingPath });\n }\n const scopeId = isTemplate ? undefined : this.engineScopeId;\n const control = plugin.render(fieldMeta, bindingPath, modelName, scopeId, this.onChange);\n\n if (this.conditionEngine) {\n this.conditionEngine.registerPlugin(bindingPath, plugin);\n }\n\n return control;\n } catch (error) {\n this.hasPartialRenderingErrors = true;\n const msg = (error as Error).message;\n Logger.error(`[MetaUI Engine] Failed to generate field at ${bindingPath}`, msg);\n Logger.showErrorPopup(`Failed to generate field '${bindingPath}'.\\n\\nDetails: ${msg}`);\n return new Text({ text: `[Error generating field ${bindingPath}]` });\n }\n }\n\n /**\n * Generates a sub-layout (like an embedded table or nested form) without \n * destroying the current Engine state or Condition tracking.\n * \n * @param schema The normalized JSON schema representing the view.\n * @param modelName The UI5 JSONModel name used for data binding (defaults to \"meta\").\n * @param bindingPath Optional path to bind the sub-layout to a specific array/object property.\n * @returns The generated root UI5 Control container.\n */\n public generateLayout(schema: ISchema, modelName: string, bindingPath?: string): Control {\n try {\n const layoutStrategy = schema.layoutStrategy || (schema.type === \"array\" ? \"table\" : \"form\");\n const layoutManager = PluginRegistry.getInstance().getLayout(layoutStrategy);\n return layoutManager.render(schema, modelName, this, undefined, bindingPath);\n } catch (error) {\n this.hasPartialRenderingErrors = true;\n const msg = (error as Error).message;\n Logger.error(`[MetaUI Engine] Critical error generating sub-layout for ${bindingPath}`, msg);\n Logger.showErrorPopup(`Engine failed to generate a sub-layout.\\n\\nDetails: ${msg}`);\n return new Text({ text: \"Critical Sub-Layout Error\" });\n }\n }\n\n /**\n * Iterates through all active plugins and triggers their internal validation pipelines.\n * \n * @param applyVisualState If true, explicitly instructs the plugin to natively paint its own ValueState.\n * @returns {IPluginValidationResult[]} Array of validation error objects. Empty array if valid.\n */\n public validateAll(applyVisualState: boolean = false): IPluginValidationResult[] {\n const errors: IPluginValidationResult[] = [];\n for (const item of this.activePlugins) {\n try {\n const result = item.plugin.validate();\n if (applyVisualState && typeof item.plugin.setVisualValidationState === \"function\") {\n item.plugin.setVisualValidationState(result.isValid, result.errorMessage);\n }\n \n if (!result.isValid) {\n // Ensure the path is bound to the error so GeneratorHost knows where to target it\n result.fieldKey = result.fieldKey || item.path.replace(/^\\//, \"\");\n errors.push(result);\n // Add console log to find which plugin fails silently\n Logger.error(\"[MetaUI Validation] Plugin failed validation silently:\", item.path || item.plugin.constructor.name);\n }\n } catch (error) {\n Logger.error(`[MetaUI Engine] Error validating plugin at ${item.path}`, (error as Error).message);\n }\n }\n return errors;\n }\n\n /**\n * Retrieves an active plugin instance by its absolute binding path.\n * Useful for programmatic field manipulation (e.g., custom error injection).\n * \n * @param path The binding path (e.g. \"/General/CustomerName\").\n * @returns {IPlugin | undefined} The plugin instance, or undefined if not found.\n */\n public getPluginByPath(path: string): import(\"../interfaces/IPlugin\").IPlugin | undefined {\n const cleanPath = path.startsWith(\"/\") ? path : `/${path}`;\n const match = this.activePlugins.find(p => p.path === cleanPath || p.path === `/${cleanPath}`);\n return match ? match.plugin : undefined;\n }\n\n /**\n * Cleans up internal state and destroys the condition engine to prevent memory leaks.\n */\n public destroy(): void {\n if (this.conditionEngine) {\n this.conditionEngine.destroy();\n this.conditionEngine = null;\n }\n\n // ------------------------------------------------------------------------\n // Ghost Error Prevention\n // Flush MessageManager for active plugins before destroying their controls\n // ------------------------------------------------------------------------\n const messageManager = Messaging;\n const existingMessages = messageManager.getMessageModel().getData();\n const messagesToRemove: sap.ui.core.message.Message[] = [];\n\n for (const item of this.activePlugins) {\n if (this.activeModel) {\n const targetPath = `/${item.path.replace(/^\\//, \"\")}`;\n const matched = existingMessages.filter((msg: sap.ui.core.message.Message) =>\n msg.getTarget() === targetPath && msg.getMessageProcessor() && msg.getMessageProcessor().getId() === this.activeModel.getId()\n );\n messagesToRemove.push(...matched);\n }\n if (typeof item.plugin.destroy === \"function\") {\n item.plugin.destroy();\n }\n }\n\n if (messagesToRemove.length > 0) {\n messageManager.removeMessages(messagesToRemove);\n }\n\n this.activePlugins = [];\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":17,"column":0},"map":{"version":3,"names":["Registry","___Registry","PatternValidatorPlugin","___plugins_validators_PatternValidatorPlugin","MinLengthValidatorPlugin","___plugins_validators_MinLengthValidatorPlugin","RangeValidatorPlugin","___plugins_validators_RangeValidatorPlugin","UrlValidatorPlugin","___plugins_validators_UrlValidatorPlugin","IbanValidatorPlugin","___plugins_validators_IbanValidatorPlugin","EmailValidatorPlugin","___plugins_validators_EmailValidatorPlugin","DateFormatterPlugin","___plugins_formatters_DateFormatterPlugin","PhoneFormatterPlugin","___plugins_formatters_PhoneFormatterPlugin","TextCaseFormatterPlugin","___plugins_formatters_TextCaseFormatterPlugin","Logger","___utils_Logger","RequiredValidator","validate","parsedValue","args","undefined","isValid","errorMessage","MaxLengthValidator","length","PipelineManager","formatters","parsers","validators","constructor","this","register","executeValidation","requestedValidators","argsMap","rule","validator","get","result","error","msg","message","warn","GlobalPipeline","__exports","__esModule"],"sources":["PipelineManager.ts"],"sourcesContent":["/**\n * @file PipelineManager.ts\n * @description Central manager for the data manipulation pipeline. \n * Orchestrates Formatting, Parsing, and Validating data using the generic Registry.\n */\n\nimport { Registry } from \"./Registry\";\nimport { IFormatter, IParser, IValidator, IValidationResult } from \"../interfaces/IPipeline\";\nimport { PatternValidatorPlugin } from \"../plugins/validators/PatternValidatorPlugin\";\nimport { MinLengthValidatorPlugin } from \"../plugins/validators/MinLengthValidatorPlugin\";\nimport { RangeValidatorPlugin } from \"../plugins/validators/RangeValidatorPlugin\";\nimport { UrlValidatorPlugin } from \"../plugins/validators/UrlValidatorPlugin\";\nimport { IbanValidatorPlugin } from \"../plugins/validators/IbanValidatorPlugin\";\nimport { EmailValidatorPlugin } from \"../plugins/validators/EmailValidatorPlugin\";\nimport { DateFormatterPlugin } from \"../plugins/formatters/DateFormatterPlugin\";\nimport { PhoneFormatterPlugin } from \"../plugins/formatters/PhoneFormatterPlugin\";\nimport { TextCaseFormatterPlugin } from \"../plugins/formatters/TextCaseFormatterPlugin\";\nimport { Logger } from \"../utils/Logger\";\n\n// --- Built-in Default Validators ---\n/** Internal rule for required fields. */\nclass RequiredValidator implements IValidator {\n /** Validates that the value is not null, undefined, or empty string. */\n validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (parsedValue === null || parsedValue === undefined || parsedValue === \"\") {\n return { isValid: false, errorMessage: \"This field is required.\" };\n }\n return { isValid: true };\n }\n}\n\n/** Internal rule for string maximum length. */\nclass MaxLengthValidator implements IValidator {\n /** Validates that a string does not exceed the provided argument length. */\n validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (typeof parsedValue === \"string\" && args && typeof args === \"number\") {\n if (parsedValue.length > args) {\n return { isValid: false, errorMessage: `Maximum length is ${args} characters.` };\n }\n }\n return { isValid: true };\n }\n}\n\n\n/**\n * The core engine responsible for marshalling data through the validation, formatting, and parsing phases.\n * Pluggable design allows new validators to be registered dynamically.\n * \n * @namespace nz.co.siliconst.ui5.metaui.core\n * @public\n */\nexport class PipelineManager {\n /** Registry of data formatters applied before pushing to the UI. */\n public readonly formatters: Registry<IFormatter> = new Registry<IFormatter>(\"Formatters\");\n /** Registry of data parsers applied when pulling data from the UI. */\n public readonly parsers: Registry<IParser> = new Registry<IParser>(\"Parsers\");\n /** Registry of business logic validators. */\n public readonly validators: Registry<IValidator> = new Registry<IValidator>(\"Validators\");\n\n /**\n * Bootstraps the PipelineManager with default validators (required, maxLength, email).\n */\n constructor() {\n // Register default validators\n this.validators.register(\"required\", new RequiredValidator());\n this.validators.register(\"maxLength\", new MaxLengthValidator());\n this.validators.register(\"pattern\", new PatternValidatorPlugin());\n this.validators.register(\"minLength\", new MinLengthValidatorPlugin());\n this.validators.register(\"range\", new RangeValidatorPlugin());\n this.validators.register(\"url\", new UrlValidatorPlugin());\n this.validators.register(\"iban\", new IbanValidatorPlugin());\n this.validators.register(\"email\", new EmailValidatorPlugin());\n\n // Register default formatters\n this.formatters.register(\"date\", new DateFormatterPlugin());\n this.formatters.register(\"phone\", new PhoneFormatterPlugin());\n this.formatters.register(\"textCase\", new TextCaseFormatterPlugin());\n }\n\n /**\n * Executes the validation pipeline sequentially. Fails fast on the first encountered error.\n * \n * @param parsedValue The raw extracted value from the UI control.\n * @param requestedValidators Array of validation rule keys (e.g. ['required', 'email']).\n * @param argsMap Optional map of parameters required by specific rules (e.g. { maxLength: 50 }).\n * @returns {IValidationResult} The final result state and any associated error message.\n */\n public executeValidation(parsedValue: unknown, requestedValidators: string[], argsMap?: Record<string, unknown>): IValidationResult {\n for (const rule of requestedValidators) {\n const validator = this.validators.get(rule);\n if (validator) {\n const args = argsMap ? argsMap[rule] : undefined;\n try {\n const result = validator.validate(parsedValue, args);\n if (!result.isValid) {\n return result; // Fast fail on first error\n }\n } catch (error) {\n const msg = (error as Error).message;\n Logger.error(`[MetaUI] PipelineManager: Validator '${rule}' crashed during execution.`, msg);\n return { isValid: false, errorMessage: `System validation error: ${msg}` };\n }\n } else {\n Logger.warn(`[MetaUI] PipelineManager: Requested validator '${rule}' not found in registry.`);\n }\n }\n return { isValid: true };\n }\n}\n\n/** \n * Singleton instance for global access to the active validation pipeline. \n * @public \n */\nexport const GlobalPipeline = new PipelineManager();\n"],"mappings":"AAAA,4iBAAA,MAMSA,EAAQC,EAAA,kBAERC,EAAsBC,EAAA,gCACtBC,EAAwBC,EAAA,kCACxBC,EAAoBC,EAAA,8BACpBC,EAAkBC,EAAA,4BAClBC,EAAmBC,EAAA,6BACnBC,EAAoBC,EAAA,8BACpBC,EAAmBC,EAAA,6BACnBC,EAAoBC,EAAA,8BACpBC,EAAuBC,EAAA,iCACvBC,EAAMC,EAAA,UAIf,MAAMC,EAEFC,SAASC,EAAsBC,GAC3B,GAAID,IAAgB,MAAQA,IAAgBE,WAAaF,IAAgB,GAAI,CACzE,MAAO,CAAEG,QAAS,MAAOC,aAAc,0BAC3C,CACA,MAAO,CAAED,QAAS,KACtB,EAIJ,MAAME,EAEFN,SAASC,EAAsBC,GAC3B,UAAWD,IAAgB,UAAYC,UAAeA,IAAS,SAAU,CACrE,GAAID,EAAYM,OAASL,EAAM,CAC3B,MAAO,CAAEE,QAAS,MAAOC,aAAc,qBAAqBH,gBAChE,CACJ,CACA,MAAO,CAAEE,QAAS,KACtB,EAWG,MAAMI,EAEOC,WAAmC,IAAIhC,EAAqB,cAE5DiC,QAA6B,IAAIjC,EAAkB,WAEnDkC,WAAmC,IAAIlC,EAAqB,cAK5EmC,cAEIC,KAAKF,WAAWG,SAAS,WAAY,IAAIf,GACzCc,KAAKF,WAAWG,SAAS,YAAa,IAAIR,GAC1CO,KAAKF,WAAWG,SAAS,UAAW,IAAInC,GACxCkC,KAAKF,WAAWG,SAAS,YAAa,IAAIjC,GAC1CgC,KAAKF,WAAWG,SAAS,QAAS,IAAI/B,GACtC8B,KAAKF,WAAWG,SAAS,MAAO,IAAI7B,GACpC4B,KAAKF,WAAWG,SAAS,OAAQ,IAAI3B,GACrC0B,KAAKF,WAAWG,SAAS,QAAS,IAAIzB,GAGtCwB,KAAKJ,WAAWK,SAAS,OAAQ,IAAIvB,GACrCsB,KAAKJ,WAAWK,SAAS,QAAS,IAAIrB,GACtCoB,KAAKJ,WAAWK,SAAS,WAAY,IAAInB,EAC7C,CAUOoB,kBAAkBd,EAAsBe,EAA+BC,GAC1E,IAAK,MAAMC,KAAQF,EAAqB,CACpC,MAAMG,EAAYN,KAAKF,WAAWS,IAAIF,GACtC,GAAIC,EAAW,CACX,MAAMjB,EAAOe,EAAUA,EAAQC,GAAQf,UACvC,IACI,MAAMkB,EAASF,EAAUnB,SAASC,EAAaC,GAC/C,IAAKmB,EAAOjB,QAAS,CACjB,OAAOiB,CACX,CACJ,CAAE,MAAOC,GACL,MAAMC,EAAOD,EAAgBE,QAC7B3B,EAAOyB,MAAM,wCAAwCJ,+BAAmCK,GACxF,MAAO,CAAEnB,QAAS,MAAOC,aAAc,4BAA4BkB,IACvE,CACJ,KAAO,CACH1B,EAAO4B,KAAK,kDAAkDP,4BAClE,CACJ,CACA,MAAO,CAAEd,QAAS,KACtB,EAOG,MAAMsB,EAAiB,IAAIlB,EAAkB,IAAAmB,EAAA,CAAAC,WAAA,MAAAD,EAAAnB,kBAAAmB,EAAAD,iBAAA,OAAAC,CAAA","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":18,"column":0},"map":{"version":3,"names":["Logger","___utils_Logger","PluginRegistry","fieldIndex","actionIndex","layoutIndex","activePromises","constructor","this","registerPluginPath","undefined","registerLayoutPath","getInstance","instance","type","widgetName","path","key","registerActionPath","actionName","strategy","getFieldPath","Error","getLayoutPath","getPathsToLoad","schema","pathsToLoad","Set","layoutStrategy","add","scanProperties","props","prop","ui","widget","e","msg","message","error","properties","items","preloadDependencies","promises","Array","from","map","Promise","resolve","reject","sap","require","Module","err","all","extractConstructor","default","keys","Object","getPlugin","PluginClass","getLayout","LayoutClass","__exports","__esModule"],"sources":["PluginRegistry.ts"],"sourcesContent":["/**\n * @file PluginRegistry.ts\n * @description Centralized hub for mapping UI5 controls to SAP schema data types.\n * Enforces the Registry Pattern to decouple the core engine from specific UI5 control implementations.\n * NOW WITH UNIVERSAL LAZY LOADING.\n */\n\nimport { IPlugin } from \"../interfaces/IPlugin\";\nimport { FieldType, ISchema, IPropertyMetadata } from \"../interfaces/ISchema\";\nimport { ILayoutManager } from \"../interfaces/ILayoutManager\";\nimport { Logger } from \"../utils/Logger\";\nimport { DefaultLayoutGenerator } from \"./DefaultLayoutGenerator\";\n\nexport class PluginRegistry {\n private static instance: PluginRegistry;\n \n private fieldIndex: Record<string, string> = {};\n private actionIndex: Record<string, string> = {};\n private layoutIndex: Record<string, string> = {};\n \n private activePromises: Record<string, Promise<unknown>> = {};\n\n private constructor() {\n // Core Mappings\n this.registerPluginPath(\"string\", undefined, \"nz/co/siliconst/ui5/metaui/plugins/controls/StringPlugin\");\n this.registerPluginPath(\"number\", undefined, \"nz/co/siliconst/ui5/metaui/plugins/controls/NumberPlugin\");\n this.registerPluginPath(\"integer\", undefined, \"nz/co/siliconst/ui5/metaui/plugins/controls/NumberPlugin\");\n this.registerPluginPath(\"date\", undefined, \"nz/co/siliconst/ui5/metaui/plugins/controls/DatePlugin\");\n this.registerPluginPath(\"boolean\", undefined, \"nz/co/siliconst/ui5/metaui/plugins/controls/BooleanPlugin\");\n this.registerPluginPath(\"array\", undefined, \"nz/co/siliconst/ui5/metaui/plugins/controls/ArrayPlugin\");\n this.registerPluginPath(\"object\", undefined, \"nz/co/siliconst/ui5/metaui/plugins/controls/ObjectPlugin\");\n\n // Widget Overrides\n this.registerPluginPath(\"string\", \"time\", \"nz/co/siliconst/ui5/metaui/plugins/controls/TimePlugin\");\n this.registerPluginPath(\"string\", \"datetime\", \"nz/co/siliconst/ui5/metaui/plugins/controls/DateTimePlugin\");\n this.registerPluginPath(\"boolean\", \"switch\", \"nz/co/siliconst/ui5/metaui/plugins/controls/SwitchPlugin\");\n this.registerPluginPath(\"string\", \"select\", \"nz/co/siliconst/ui5/metaui/plugins/controls/DropdownPlugin\");\n this.registerPluginPath(\"string\", \"textArea\", \"nz/co/siliconst/ui5/metaui/plugins/controls/TextAreaPlugin\");\n this.registerPluginPath(\"string\", \"codeEditor\", \"nz/co/siliconst/ui5/metaui/plugins/controls/CodeEditorPlugin\");\n \n // Phase 1 Mappings\n this.registerPluginPath(\"string\", \"fileUploader\", \"nz/co/siliconst/ui5/metaui/plugins/controls/FileUploaderPlugin\");\n this.registerPluginPath(\"array\", \"multiSelect\", \"nz/co/siliconst/ui5/metaui/plugins/controls/MultiSelectPlugin\");\n this.registerPluginPath(\"array\", \"multiInput\", \"nz/co/siliconst/ui5/metaui/plugins/controls/MultiInputPlugin\");\n this.registerPluginPath(\"number\", \"slider\", \"nz/co/siliconst/ui5/metaui/plugins/controls/SliderPlugin\");\n this.registerPluginPath(\"number\", \"rating\", \"nz/co/siliconst/ui5/metaui/plugins/controls/RatingIndicatorPlugin\");\n this.registerPluginPath(\"string\", \"messageStrip\", \"nz/co/siliconst/ui5/metaui/plugins/controls/MessageStripPlugin\");\n\n // Phase 5 Mappings (Hardware)\n this.registerPluginPath(\"string\", \"camera\", \"nz/co/siliconst/ui5/metaui/plugins/controls/CameraPlugin\");\n this.registerPluginPath(\"string\", \"signature\", \"nz/co/siliconst/ui5/metaui/plugins/controls/SignaturePlugin\");\n this.registerPluginPath(\"object\", \"location\", \"nz/co/siliconst/ui5/metaui/plugins/controls/GeolocationPlugin\");\n this.registerPluginPath(\"string\", \"scanner\", \"nz/co/siliconst/ui5/metaui/plugins/controls/BarcodeScannerPlugin\");\n this.registerPluginPath(\"string\", \"voiceInput\", \"nz/co/siliconst/ui5/metaui/plugins/controls/VoiceInputPlugin\");\n this.registerPluginPath(\"string\", \"richText\", \"nz/co/siliconst/ui5/metaui/plugins/controls/RichTextPlugin\");\n\n // Actions & Datasources\n this.registerPluginPath(\"string\", \"urlButton\", \"nz/co/siliconst/ui5/metaui/plugins/actions/UrlNavigationActionPlugin\");\n this.registerPluginPath(\"string\", \"submitButton\", \"nz/co/siliconst/ui5/metaui/plugins/actions/SubmitFormActionPlugin\");\n this.registerPluginPath(\"string\", \"odataSelect\", \"nz/co/siliconst/ui5/metaui/plugins/datasources/ODataListBindingPlugin\");\n this.registerPluginPath(\"string\", \"remoteDropdown\", \"nz/co/siliconst/ui5/metaui/plugins/datasources/RemoteDropdownPlugin\");\n this.registerPluginPath(\"string\", \"liveSearch\", \"nz/co/siliconst/ui5/metaui/plugins/datasources/LiveSearchPlugin\");\n this.registerPluginPath(\"string\", \"remoteValueHelp\", \"nz/co/siliconst/ui5/metaui/plugins/datasources/RemoteValueHelpPlugin\");\n\n // Layouts\n this.registerLayoutPath(\"form\", \"nz/co/siliconst/ui5/metaui/layouts/FormLayout\");\n this.registerLayoutPath(\"table\", \"nz/co/siliconst/ui5/metaui/layouts/TableLayout\");\n this.registerLayoutPath(\"wizard\", \"nz/co/siliconst/ui5/metaui/layouts/WizardLayout\");\n this.registerLayoutPath(\"compact\", \"nz/co/siliconst/ui5/metaui/layouts/CompactLayout\");\n }\n\n public static getInstance(): PluginRegistry {\n if (!PluginRegistry.instance) {\n PluginRegistry.instance = new PluginRegistry();\n }\n return PluginRegistry.instance;\n }\n\n public registerPluginPath(type: FieldType, widgetName: string | undefined, path: string): void {\n const key = widgetName ? `${type}:${widgetName}` : type;\n this.fieldIndex[key] = path;\n }\n\n public registerActionPath(actionName: string, path: string): void {\n this.actionIndex[actionName] = path;\n }\n\n public registerLayoutPath(strategy: string, path: string): void {\n this.layoutIndex[strategy] = path;\n }\n\n private getFieldPath(type: FieldType, widgetName?: string): string {\n let path;\n if (widgetName) {\n path = this.fieldIndex[`${type}:${widgetName}`];\n }\n if (!path) {\n path = this.fieldIndex[type];\n }\n if (!path) {\n throw new Error(`No plugin path mapped for FieldType: ${type} (widget: ${widgetName})`);\n }\n return path;\n }\n\n private getLayoutPath(strategy: string): string {\n const path = this.layoutIndex[strategy];\n if (!path) {\n throw new Error(`No layout path mapped for strategy: ${strategy}`);\n }\n return path;\n }\n\n /**\n * Statically traverses the schema structure to identify all required plugins\n * and layouts without actually instantiating them.\n * \n * @param {ISchema} schema The root JSON schema payload to traverse\n * @returns {Set<string>} A distinct set of UI5 module paths required to render the schema\n */\n public getPathsToLoad(schema: ISchema): Set<string> {\n const pathsToLoad = new Set<string>();\n \n // 1. Gather layout strategy\n const strategy = schema.layoutStrategy || (schema.type === \"array\" ? \"table\" : \"form\");\n pathsToLoad.add(this.getLayoutPath(strategy));\n\n // 2. Recursively gather field plugins\n const scanProperties = (props: Record<string, IPropertyMetadata>) => {\n for (const key in props) {\n const prop = props[key];\n try {\n pathsToLoad.add(this.getFieldPath(prop.type || \"string\", prop.ui?.widget));\n } catch (e) {\n const msg = `[MetaUI LazyLoad] Could not find mapped plugin for field ${key}: ${(e as Error).message}`;\n Logger.error(msg);\n throw new Error(msg);\n }\n if (prop.properties) scanProperties(prop.properties);\n if (prop.items && prop.items.properties) scanProperties(prop.items.properties);\n if (prop.items && prop.items.type) {\n try {\n pathsToLoad.add(this.getFieldPath(prop.items.type, prop.items.ui?.widget));\n } catch (e) {\n const msg = `[MetaUI LazyLoad] Could not find mapped plugin for array item type ${prop.items.type}: ${(e as Error).message}`;\n Logger.error(msg);\n throw new Error(msg);\n }\n }\n }\n };\n\n if (schema.properties) {\n scanProperties(schema.properties);\n } else if (schema.items && schema.items.properties) {\n scanProperties(schema.items.properties);\n }\n\n return pathsToLoad;\n }\n\n /**\n * Defers the generation of the UI until all required UI5 modules have been\n * downloaded asynchronously. Maintains a cache of active promises to prevent\n * redundant network requests for the same module.\n * \n * @param {ISchema} schema The root JSON schema payload to parse\n * @returns {Promise<void>} Resolves when all dependencies are securely in the UI5 require cache\n */\n public async preloadDependencies(schema: ISchema): Promise<void> {\n const pathsToLoad = this.getPathsToLoad(schema);\n\n // 3. Batch execute sap.ui.require via Promises\n const promises = Array.from(pathsToLoad).map(path => {\n if (!this.activePromises[path]) {\n this.activePromises[path] = new Promise((resolve, reject) => {\n sap.ui.require([path], \n (Module: unknown) => resolve(Module), \n (err: unknown) => {\n Logger.error(`Failed to lazy load module: ${path}`);\n // CRITICAL: Delete from cache so future attempts can retry the network request\n delete this.activePromises[path];\n reject(err);\n }\n );\n });\n }\n return this.activePromises[path];\n });\n\n await Promise.all(promises);\n }\n\n /**\n * Extracts a valid constructor from a dynamically required module.\n */\n private extractConstructor(Module: unknown): new () => IPlugin | ILayoutManager | null {\n if (!Module) return null;\n if (typeof Module === \"function\") return Module as any;\n if ((Module as any).default && typeof (Module as any).default === \"function\") return (Module as any).default;\n \n // Handle namespace exports (e.g. { FormLayout: class... })\n const keys = Object.keys(Module as object);\n for (const key of keys) {\n if (typeof (Module as any)[key] === \"function\") {\n return (Module as any)[key];\n }\n }\n return null;\n }\n\n /**\n * Instantiates the requested plugin for the given field type.\n */\n public getPlugin(type: FieldType, widgetName?: string): IPlugin {\n const path = this.getFieldPath(type, widgetName);\n const Module = sap.ui.require(path);\n const PluginClass = this.extractConstructor(Module);\n \n if (!PluginClass) {\n throw new Error(`[MetaUI Plugin Instantiation] Plugin ${path} was not preloaded or has no constructor!`);\n }\n \n return new PluginClass();\n }\n\n /**\n * Instantiates the requested layout manager for the given strategy.\n */\n public getLayout(strategy: string): ILayoutManager {\n const path = this.getLayoutPath(strategy);\n const Module = sap.ui.require(path);\n const LayoutClass = this.extractConstructor(Module);\n \n if (!LayoutClass) {\n throw new Error(`[MetaUI Layout Instantiation] Layout ${path} was not preloaded or has no constructor!`);\n }\n \n return new LayoutClass();\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":19,"column":0},"map":{"version":3,"names":["Logger","___utils_Logger","Registry","items","Map","constructor","registryName","this","register","key","item","has","warn","set","get","getStrict","msg","error","Error","getKeys","Array","from","keys","clear","__exports","__esModule"],"sources":["Registry.ts"],"sourcesContent":["/**\n * @file Registry.ts\n * @description Universal generic registry pattern used across the MetaUI library \n * for registering and resolving decoupled plugins (Layouts, Controls, Validators, etc).\n */\n\nimport { Logger } from \"../utils/Logger\";\n\n/**\n * Universal generic registry pattern used across the MetaUI library \n * for registering and resolving decoupled plugins (Layouts, Controls, Validators, etc).\n * \n * @template T The type of item being stored in the registry.\n * @namespace nz.co.siliconst.ui5.metaui.core\n * @public\n */\nexport class Registry<T> {\n /** The internal map storing the registered items. */\n public readonly items = new Map<string, T>();\n\n constructor(public readonly registryName: string = \"Registry\") {}\n\n /**\n * Registers a new item (plugin/layout/validator) into the registry.\n * @param key The unique string identifier.\n * @param item The implementation class or instance.\n */\n public register(key: string, item: T): void {\n if (this.items.has(key)) {\n Logger.warn(`[MetaUI] ${this.registryName}: Overwriting existing key '${key}'.`);\n }\n this.items.set(key, item);\n }\n\n /**\n * Retrieves an item by its key.\n * @param key The unique string identifier.\n * @returns The registered item, or undefined if not found.\n */\n public get(key: string): T | undefined {\n return this.items.get(key);\n }\n\n /**\n * Retrieves an item by its key, throwing an error if it doesn't exist.\n * @param key The unique string identifier.\n * @returns The registered item.\n */\n public getStrict(key: string): T {\n const item = this.get(key);\n if (!item) {\n const msg = `[MetaUI] ${this.registryName}: Key '${key}' not found.`;\n Logger.error(msg);\n throw new Error(msg);\n }\n return item;\n }\n\n /**\n * Returns an array of all registered keys.\n */\n public getKeys(): string[] {\n return Array.from(this.items.keys());\n }\n\n /**\n * Clears the entire registry.\n */\n public clear(): void {\n this.items.clear();\n }\n}\n"],"mappings":"AAAA,0GAAA,MAMSA,EAAMC,EAAA,UAUR,MAAMC,EAEOC,MAAQ,IAAIC,IAE5BC,YAA4BC,EAAuB,YAAYC,KAAnCD,cAAoC,CAOzDE,SAASC,EAAaC,GACzB,GAAIH,KAAKJ,MAAMQ,IAAIF,GAAM,CACrBT,EAAOY,KAAK,YAAYL,KAAKD,2CAA2CG,MAC5E,CACAF,KAAKJ,MAAMU,IAAIJ,EAAKC,EACxB,CAOOI,IAAIL,GACP,OAAOF,KAAKJ,MAAMW,IAAIL,EAC1B,CAOOM,UAAUN,GACb,MAAMC,EAAOH,KAAKO,IAAIL,GACtB,IAAKC,EAAM,CACP,MAAMM,EAAM,YAAYT,KAAKD,sBAAsBG,gBACnDT,EAAOiB,MAAMD,GACb,MAAM,IAAIE,MAAMF,EACpB,CACA,OAAON,CACX,CAKOS,UACH,OAAOC,MAAMC,KAAKd,KAAKJ,MAAMmB,OACjC,CAKOC,QACHhB,KAAKJ,MAAMoB,OACf,EACH,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAAtB,WAAA,OAAAsB,CAAA","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":20,"column":0},"map":{"version":3,"names":["Logger","___utils_Logger","SchemaNormalizer","normalize","rawSchema","data","schemaObj","trim","JSON","parse","e","msg","message","error","Error","Array","isArray","this","inferSchemaFromData","normalized","title","type","items","layoutStrategy","uiLayout","additionalProperties","targetProperties","properties","inferred","deepMergeProperties","requiredKeys","required","normalizeProperties","normalizePropertyMetadata","base","override","merged","key","Object","keys","overrideVal","baseVal","normalizedProps","isRequired","includes","prop","keyName","ui","label","generateLabel","isKey","readOnly","widget","valueHelp","enum","undefined","visibleOn","enabledOn","format","validators","formatter","args","rows","fullWidth","dialogButtonText","maxLength","minLength","minimum","maximum","pattern","precision","scale","multipleOf","name","spaced","replace","split","filter","w","length","map","word","charAt","toUpperCase","slice","toLowerCase","join","schema","inferPropertiesFromObject","obj","val","nestedProps","resolveScope","scope","startsWith","meta","bindingPath","propKey","pathSegments","current","debug","stringify","i","segment","__exports","__esModule"],"sources":["SchemaNormalizer.ts"],"sourcesContent":["/**\n * @file SchemaNormalizer.ts\n * @description Transforms and validates incoming JSON payloads into the strict v2 ISchema dictionary matrix.\n */\n\nimport { ISchema, IPropertyMetadata, FieldType } from \"../interfaces/ISchema\";\nimport { Logger } from \"../utils/Logger\";\n\nexport class SchemaNormalizer {\n\n /**\n * Validates that the provided raw payload conforms to the required ISchema structures.\n */\n public static normalize(rawSchema?: unknown, data?: unknown): ISchema {\n let schemaObj = rawSchema;\n\n if (typeof schemaObj === \"string\") {\n if (!schemaObj.trim()) {\n schemaObj = null;\n } else {\n try {\n schemaObj = JSON.parse(schemaObj);\n } catch (e) {\n const msg = \"Failed to parse schema string: \" + (e as Error).message;\n Logger.error(\"[MetaUI SchemaNormalizer]\", msg);\n throw new Error(msg);\n }\n }\n }\n\n if (!schemaObj || typeof schemaObj !== 'object' || Array.isArray(schemaObj)) {\n return this.inferSchemaFromData(data);\n }\n\n try {\n // It is an object. Ensure it conforms to v2 structure.\n const normalized: ISchema = {\n title: schemaObj.title,\n type: schemaObj.type || (schemaObj.items ? \"array\" : \"object\"),\n layoutStrategy: schemaObj.layoutStrategy,\n uiLayout: schemaObj.uiLayout,\n additionalProperties: schemaObj.additionalProperties\n };\n\n let targetProperties = schemaObj.properties || {};\n\n if (schemaObj.additionalProperties === true && data) {\n const inferred = this.inferSchemaFromData(data);\n if (inferred.type === \"object\" && inferred.properties) {\n targetProperties = this.deepMergeProperties(inferred.properties, targetProperties);\n } else if (inferred.type === \"array\" && inferred.items && inferred.items.properties) {\n // Array schema merging could be added here if we want full support.\n }\n }\n\n if (normalized.type === \"object\") {\n const requiredKeys = Array.isArray(schemaObj.required) ? schemaObj.required : [];\n normalized.properties = this.normalizeProperties(targetProperties, requiredKeys);\n } else if (normalized.type === \"array\") {\n // Future expansion: array deep merge\n normalized.items = this.normalizePropertyMetadata(schemaObj.items || { type: \"object\", properties: {} }, \"items\", false);\n }\n\n return normalized;\n } catch (error) {\n const msg = \"Critical error normalizing schema object: \" + (error as Error).message;\n Logger.error(\"[MetaUI SchemaNormalizer]\", msg);\n throw new Error(msg);\n }\n }\n\n /**\n * Recursively deep merges an inferred schema over a base schema.\n * @param base The base property dictionary.\n * @param override The overriding inferred dictionary.\n * @returns A new deeply merged property dictionary.\n */\n private static deepMergeProperties(base: Record<string, unknown>, override: Record<string, unknown>): Record<string, unknown> {\n const merged = { ...base };\n for (const key of Object.keys(override)) {\n const overrideVal = override[key];\n const baseVal = merged[key];\n\n if (baseVal && typeof baseVal === \"object\" && !Array.isArray(baseVal) &&\n overrideVal && typeof overrideVal === \"object\" && !Array.isArray(overrideVal)) {\n merged[key] = this.deepMergeProperties(baseVal, overrideVal);\n } else {\n merged[key] = overrideVal;\n }\n }\n return merged;\n }\n\n /**\n * Normalizes a collection of properties.\n * @param properties The raw properties map.\n * @param requiredKeys An optional array of keys that are required by the parent object.\n * @returns A map of strict IPropertyMetadata objects.\n */\n private static normalizeProperties(properties: Record<string, unknown>, requiredKeys: string[] = []): Record<string, IPropertyMetadata> {\n const normalizedProps: Record<string, IPropertyMetadata> = {};\n for (const key of Object.keys(properties)) {\n const isRequired = requiredKeys.includes(key);\n normalizedProps[key] = this.normalizePropertyMetadata(properties[key], key, isRequired);\n }\n return normalizedProps;\n }\n\n /**\n * Normalizes a single property against the ISchema specification.\n * @param prop The raw property definition.\n * @param keyName The string key name for generating default labels.\n * @param isRequired Indicates if the parent object mandated this property as required.\n * @returns A strict IPropertyMetadata instance.\n */\n private static normalizePropertyMetadata(prop: Record<string, unknown>, keyName: string, isRequired: boolean = false): IPropertyMetadata {\n const normalized: IPropertyMetadata = {\n type: prop.type || \"string\",\n ui: {\n label: prop.ui?.label || this.generateLabel(keyName),\n isKey: !!prop.ui?.isKey,\n readOnly: !!prop.ui?.readOnly,\n widget: prop.ui?.widget || (prop.valueHelp || prop.enum ? \"select\" : undefined),\n visibleOn: prop.ui?.visibleOn,\n enabledOn: prop.ui?.enabledOn,\n format: prop.ui?.format,\n validators: prop.ui?.validators,\n formatter: prop.ui?.formatter,\n args: prop.ui?.args,\n rows: prop.ui?.rows,\n fullWidth: prop.ui?.fullWidth,\n dialogButtonText: prop.ui?.dialogButtonText\n },\n required: isRequired || !!prop.required,\n maxLength: prop.maxLength as number,\n minLength: prop.minLength as number,\n minimum: prop.minimum,\n maximum: prop.maximum,\n pattern: prop.pattern,\n precision: prop.precision,\n scale: prop.scale,\n multipleOf: prop.multipleOf as number,\n valueHelp: prop.valueHelp,\n enum: prop.enum\n };\n\n if (normalized.type === \"object\" && prop.properties) {\n const requiredKeys = Array.isArray(prop.required) ? prop.required : [];\n normalized.properties = this.normalizeProperties(prop.properties as Record<string, unknown>, requiredKeys);\n normalized.uiLayout = prop.uiLayout;\n } else if (normalized.type === \"array\" && prop.items) {\n normalized.items = this.normalizePropertyMetadata(prop.items as Record<string, unknown>, \"items\", false);\n normalized.uiLayout = prop.uiLayout;\n }\n\n return normalized;\n }\n\n /**\n * Generates a Title Case label from camelCase or snake_case technical names.\n */\n private static generateLabel(name: string): string {\n if (!name) return \"\";\n let spaced = name.replace(/([A-Z])/g, \" $1\").replace(/_/g, \" \");\n return spaced.split(' ')\n .filter(w => w.length > 0)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ')\n .trim();\n }\n\n /**\n * Infers a v2 ISchema structure dynamically from a plain data payload.\n */\n public static inferSchemaFromData(data: unknown): ISchema {\n const schema: ISchema = { type: \"object\", properties: {}, layoutStrategy: \"compact\", title: \"\" };\n\n if (!data || typeof data !== \"object\") {\n return schema;\n }\n\n if (Array.isArray(data)) {\n schema.type = \"array\";\n if (data.length > 0 && typeof data[0] !== \"object\") {\n schema.layoutStrategy = \"compact\";\n schema.items = { type: typeof data[0] as FieldType };\n } else {\n schema.layoutStrategy = \"table\";\n schema.items = {\n type: \"object\",\n layoutStrategy: \"compact\",\n properties: data.length > 0 ? this.inferPropertiesFromObject(data[0] as Record<string, unknown>) : {}\n };\n }\n } else {\n schema.type = \"object\";\n schema.properties = this.inferPropertiesFromObject(data);\n }\n\n return schema;\n }\n\n /**\n * Infers field metadata recursively from a raw data object.\n * @param obj The raw JavaScript object.\n * @returns A dictionary of inferred IPropertyMetadata.\n */\n private static inferPropertiesFromObject(obj: Record<string, unknown>): Record<string, IPropertyMetadata> {\n const properties: Record<string, IPropertyMetadata> = {};\n if (!obj || typeof obj !== \"object\") return properties;\n\n for (const key of Object.keys(obj)) {\n const val = obj[key];\n if (val === null || val === undefined) continue;\n\n let type: FieldType = \"string\";\n let items: IPropertyMetadata | undefined;\n let nestedProps: Record<string, IPropertyMetadata> | undefined;\n\n if (typeof val === \"number\") type = \"number\";\n else if (typeof val === \"boolean\") type = \"boolean\";\n else if (Array.isArray(val)) {\n type = \"array\";\n if (val.length > 0 && typeof val[0] !== \"object\") {\n items = {\n type: typeof val[0] as FieldType\n };\n } else {\n items = {\n type: \"object\",\n properties: val.length > 0 ? this.inferPropertiesFromObject(val[0] as Record<string, unknown>) : {}\n };\n }\n } else if (typeof val === \"object\") {\n type = \"object\";\n nestedProps = this.inferPropertiesFromObject(val);\n }\n\n properties[key] = {\n type,\n items,\n properties: nestedProps,\n ui: {\n label: this.generateLabel(key),\n isKey: false,\n readOnly: false,\n widget: type === \"array\" && items?.type !== \"object\" ? \"multiInput\" : undefined\n }\n };\n }\n\n return properties;\n }\n\n /**\n * Resolves a JSON Schema scope (e.g. '#/properties/header/properties/id')\n * against the ISchema, returning the PropertyMetadata and the UI5 binding path.\n */\n public static resolveScope(schema: ISchema, scope: string): { meta: IPropertyMetadata | undefined, bindingPath: string, propKey: string } {\n if (!scope || !scope.startsWith(\"#/properties/\")) {\n return { meta: undefined, bindingPath: scope || \"\", propKey: scope || \"\" };\n }\n \n const pathSegments = scope.replace(\"#/properties/\", \"\").split(\"/properties/\");\n let current: Record<string, IPropertyMetadata> | undefined = schema.properties;\n let meta: IPropertyMetadata | undefined;\n \n Logger.debug(\"[MetaUI SchemaNormalizer]\", `Resolving scope '${scope}' with segments: ${JSON.stringify(pathSegments)}`, \"SchemaNormalizer\");\n Logger.debug(\"[MetaUI SchemaNormalizer]\", `Root schema keys: ${Object.keys(schema.properties || {})}`, \"SchemaNormalizer\");\n\n for (let i = 0; i < pathSegments.length; i++) {\n const segment = pathSegments[i];\n if (!current) {\n Logger.debug(\"[MetaUI SchemaNormalizer]\", `current is undefined at segment '${segment}'`, \"SchemaNormalizer\");\n meta = undefined;\n break;\n }\n meta = current[segment];\n Logger.debug(\"[MetaUI SchemaNormalizer]\", `Segment '${segment}' resolved to meta: ${!!meta}. Available keys in current: ${Object.keys(current)}`, \"SchemaNormalizer\");\n if (i < pathSegments.length - 1) {\n current = meta?.properties;\n }\n }\n \n const bindingPath = pathSegments.join(\"/\");\n const propKey = scope.replace(\"#/properties/\", \"\"); // The original raw string for logging\n \n return {\n meta,\n bindingPath,\n propKey\n };\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":21,"column":0},"map":{"version":3,"names":["SchemaValidator","validateSchemaStructure","schema","errors","s","type","push","properties","key","Object","keys","prop","allowedTypes","includes","join","__exports","__esModule"],"sources":["SchemaValidator.ts"],"sourcesContent":["/**\n * @file SchemaValidator.ts\n * @description Structural validation utility to catch developer errors in the JSON schema itself.\n */\n\nimport { ISchema, FieldType } from \"../interfaces/ISchema\";\n\nexport class SchemaValidator {\n /**\n * Validates a parsed JSON schema object for structural correctness.\n * @param schema The schema object to validate\n * @returns An array of error strings. Empty if no errors.\n */\n public static validateSchemaStructure(schema: unknown): string[] {\n const errors: string[] = [];\n\n if (!schema || typeof schema !== \"object\") {\n return [\"Root schema must be an object.\"];\n }\n\n const s = schema as Record<string, any>;\n if (s.type !== \"object\" && s.type !== \"array\") {\n errors.push(`Root schema must have type 'object' or 'array'. Found: '${s.type}'`);\n }\n\n if (s.type === \"object\" && !s.properties) {\n errors.push(\"Object schema is missing the 'properties' node.\");\n }\n\n if (s.properties) {\n for (const key of Object.keys(s.properties)) {\n const prop = s.properties[key];\n if (!prop || typeof prop !== \"object\") {\n errors.push(`Property '${key}' must be an object.`);\n continue;\n }\n\n if (!prop.type) {\n errors.push(`Property '${key}' is missing 'type'.`);\n } else {\n const allowedTypes: FieldType[] = [\"string\", \"number\", \"boolean\", \"date\", \"object\", \"array\"];\n if (!allowedTypes.includes(prop.type)) {\n errors.push(`Property '${key}' has invalid type '${prop.type}'. Allowed: ${allowedTypes.join(\", \")}`);\n }\n }\n\n // Removed strict check for prop.items on array properties because inference handles empty definitions\n\n }\n }\n\n return errors;\n }\n}\n"],"mappings":"AAAA,+FAOO,MAAMA,EAMT,8BAAcC,CAAwBC,GAClC,MAAMC,EAAmB,GAEzB,IAAKD,UAAiBA,IAAW,SAAU,CACvC,MAAO,CAAC,iCACZ,CAEA,MAAME,EAAIF,EACV,GAAIE,EAAEC,OAAS,UAAYD,EAAEC,OAAS,QAAS,CAC3CF,EAAOG,KAAK,2DAA2DF,EAAEC,QAC7E,CAEA,GAAID,EAAEC,OAAS,WAAaD,EAAEG,WAAY,CACtCJ,EAAOG,KAAK,kDAChB,CAEA,GAAIF,EAAEG,WAAY,CACd,IAAK,MAAMC,KAAOC,OAAOC,KAAKN,EAAEG,YAAa,CACzC,MAAMI,EAAOP,EAAEG,WAAWC,GAC1B,IAAKG,UAAeA,IAAS,SAAU,CACnCR,EAAOG,KAAK,aAAaE,yBACzB,QACJ,CAEA,IAAKG,EAAKN,KAAM,CACZF,EAAOG,KAAK,aAAaE,wBAC7B,KAAO,CACH,MAAMI,EAA4B,CAAC,SAAU,SAAU,UAAW,OAAQ,SAAU,SACpF,IAAKA,EAAaC,SAASF,EAAKN,MAAO,CACnCF,EAAOG,KAAK,aAAaE,wBAA0BG,EAAKN,mBAAmBO,EAAaE,KAAK,QACjG,CACJ,CAIJ,CACJ,CAEA,OAAOX,CACX,EACH,IAAAY,EAAA,CAAAC,WAAA,MAAAD,EAAAf,kBAAA,OAAAe,CAAA","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":22,"column":0},"map":{"version":3,"names":["GlobalPipeline","___PipelineManager","StateManager","schema","_useMessageManager","constructor","initialData","modelName","this","activeModelName","safeData","JSON","parse","stringify","model","JSONModel","setDefaultBindingMode","originalSetProperty","setProperty","bind","sPath","oValue","oContext","bAsyncUpdate","result","validatePath","setUseMessageManager","use","value","fieldKey","replace","metadata","findMetadataForPath","messageManager","Messaging","targetPath","startsWith","existingMessages","getMessageModel","getData","messagesToRemove","filter","msg","isMatch","getTarget","getMessageProcessor","getId","length","removeMessages","validatorsToRun","argsMap","required","push","type","maxLength","minLength","pattern","minimum","undefined","maximum","min","max","format","ui","validators","v","name","args","validationResult","executeValidation","isValid","newMsg","Message","message","errorMessage","coreLibrary","MessageType","Error","target","processor","addMessages","path","properties","getModel","bindControl","control","property","bindingPath","bindProperty","extractPayload","data","destroy","__exports","__esModule"],"sources":["StateManager.ts"],"sourcesContent":["/**\n * @file StateManager.ts\n * @description Isolated internal state management. Decouples the MetaUI engine from external host models.\n */\n\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\nimport ManagedObject from \"sap/ui/base/ManagedObject\";\nimport { ISchema, IPropertyMetadata } from \"../interfaces/ISchema\";\nimport { GlobalPipeline } from \"./PipelineManager\";\nimport Message from \"sap/ui/core/message/Message\";\nimport coreLibrary from \"sap/ui/core/library\";\nimport Core from \"sap/ui/core/Core\";\nimport Messaging from \"sap/ui/core/Messaging\";\n\n\n/**\n * Manages the isolated internal data payload for the MetaUI engine.\n */\nexport class StateManager {\n private model: JSONModel;\n private activeModelName: string;\n private schema: ISchema | null = null;\n private _useMessageManager: boolean = false;\n\n /**\n * Initializes the state manager with an authentic SAPUI5 JSONModel.\n * @param initialData The initial JSON payload to populate the fields.\n * @param schema The normalized schema for live validation.\n * @param modelName The UI5 model alias used for isolation.\n */\n constructor(initialData: Record<string, unknown> = {}, schema: ISchema, modelName: string = \"meta\") {\n this.activeModelName = modelName;\n this.schema = schema;\n \n // Deep copy to ensure no reference leakage from the host application\n const safeData = JSON.parse(JSON.stringify(initialData));\n this.model = new JSONModel(safeData);\n this.model.setDefaultBindingMode(\"TwoWay\");\n\n // Centralized Model-Level Validation Interceptor\n const originalSetProperty = this.model.setProperty.bind(this.model);\n this.model.setProperty = (sPath: string, oValue: unknown, oContext?: unknown, bAsyncUpdate?: boolean) => {\n const result = originalSetProperty(sPath, oValue, oContext, bAsyncUpdate);\n this.validatePath(sPath, oValue);\n return result;\n };\n }\n\n /**\n * Updates the flag indicating whether this manager should push validation errors directly to the global MessageManager.\n */\n public setUseMessageManager(use: boolean): void {\n this._useMessageManager = use;\n }\n\n /**\n * Validates a specific path against the schema and updates the MessageManager.\n */\n private validatePath(sPath: string, value: unknown): void {\n const fieldKey = sPath.replace(/^\\//, \"\");\n const metadata = this.findMetadataForPath(fieldKey);\n \n const messageManager = Messaging;\n const targetPath = sPath.startsWith(\"/\") ? sPath : `/${sPath}`; // Pure UI5: target MUST be absolute path\n \n // 1. Remove existing messages (strictly for THIS model instance)\n if (this._useMessageManager) {\n const existingMessages = messageManager.getMessageModel().getData();\n const messagesToRemove = existingMessages.filter((msg: sap.ui.core.message.Message) => {\n const isMatch = msg.getTarget() === targetPath && msg.getMessageProcessor() && msg.getMessageProcessor().getId() === this.model.getId();\n return isMatch;\n });\n \n if (messagesToRemove.length > 0) {\n messageManager.removeMessages(messagesToRemove);\n }\n }\n\n if (!metadata) return;\n\n // 2. Run GlobalPipeline\n const validatorsToRun: string[] = [];\n const argsMap: Record<string, unknown> = {};\n\n if (metadata.required) {\n validatorsToRun.push(\"required\");\n }\n if (metadata.type === \"string\" && metadata.maxLength) {\n validatorsToRun.push(\"maxLength\");\n argsMap[\"maxLength\"] = metadata.maxLength;\n }\n if (metadata.minLength) {\n validatorsToRun.push(\"minLength\");\n argsMap[\"minLength\"] = metadata.minLength;\n }\n if (metadata.pattern) {\n validatorsToRun.push(\"pattern\");\n argsMap[\"pattern\"] = metadata.pattern;\n }\n if (metadata.minimum !== undefined || metadata.maximum !== undefined) {\n validatorsToRun.push(\"range\");\n argsMap[\"range\"] = { min: metadata.minimum, max: metadata.maximum };\n }\n \n const format = metadata.ui?.format;\n if (format === \"email\" || format === \"url\" || format === \"iban\") {\n validatorsToRun.push(format);\n }\n if (metadata.ui?.validators) {\n for (const v of metadata.ui.validators) {\n if (typeof v === \"string\") {\n validatorsToRun.push(v);\n } else if (v && v.name) {\n validatorsToRun.push(v.name);\n if (v.args !== undefined) {\n argsMap[v.name] = v.args;\n }\n }\n }\n }\n\n if (validatorsToRun.length > 0) {\n const validationResult = GlobalPipeline.executeValidation(value, validatorsToRun, argsMap);\n if (!validationResult.isValid && this._useMessageManager) {\n const newMsg = new Message({\n message: validationResult.errorMessage || \"Invalid value.\",\n type: coreLibrary.MessageType.Error,\n target: targetPath,\n processor: this.model\n });\n messageManager.addMessages(newMsg);\n }\n }\n }\n\n /**\n * Resolves the schema metadata for a given internal binding path.\n * @param path The flat binding path representing the field.\n * @returns The associated IPropertyMetadata, or undefined if not mapped.\n */\n private findMetadataForPath(path: string): IPropertyMetadata | undefined {\n if (!this.schema || !this.schema.properties) return undefined;\n // Basic single-level support for now. Nested object resolution would split by '.' or '/'\n return this.schema.properties[path];\n }\n\n\n\n /**\n * Retrieves the isolated JSONModel instance to attach to the root GeneratorHost control.\n * @returns The internal JSONModel.\n */\n public getModel(): JSONModel {\n return this.model;\n }\n\n /**\n * Binds a generated UI control property to a path in the internal model.\n * @param control The target UI5 Control.\n * @param property The UI5 property name (e.g., 'value').\n * @param bindingPath The exact path in the JSON payload.\n */\n public bindControl(control: ManagedObject, property: string, bindingPath: string): void {\n control.bindProperty(property, {\n path: bindingPath,\n model: \"meta\" // Assumes the model is bound to the root container with the name 'meta'\n });\n }\n\n /**\n * Extracts the flat JavaScript object representing the current state of the UI.\n * @returns A serialized record of the data payload, free of UI5 wrappers.\n */\n public extractPayload(): Record<string, unknown> {\n // Create a deep copy to prevent accidental mutations by the host\n const data = this.model.getData();\n return JSON.parse(JSON.stringify(data));\n }\n\n /**\n * Cleans up internal state and natively destroys the UI5 JSONModel to prevent memory leaks.\n */\n public destroy(): void {\n \n if (this.model) {\n this.model.destroy();\n }\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":23,"column":0},"map":{"version":3,"names":["SchemaNormalizer","___core_SchemaNormalizer","Logger","___utils_Logger","CompactLayout","render","schema","modelName","engine","onSubmit","container","VBox","renderType","addStyleClass","uiLayout","Array","isArray","warn","tableElements","renderElement","element","type","label","title","sap","m","Title","text","level","addItem","elements","forEach","scope","startsWith","error","meta","bindingPath","propKey","resolveScope","isCollectionOfRecords","items","properties","hasExplicitWidget","ui","widget","isSubLayout","debug","push","this","_renderScalarField","field","subSchema","control","generateLayout","msg","message","showErrorPopup","labelText","Label","required","effectiveMeta","generateField","fieldBox","__exports","__esModule"],"sources":["CompactLayout.ts"],"sourcesContent":["/**\n * @file CompactLayout.ts\n * @description Generates a lightweight, dense VBox layout for use inside tight spaces like table cells.\n */\n\nimport VBox from \"sap/m/VBox\";\nimport Label from \"sap/m/Label\";\nimport Title from \"sap/ui/core/Title\";\nimport { IPropertyMetadata, ISchema, ILayoutElement } from \"../interfaces/ISchema\";\nimport { ILayoutManager } from \"../interfaces/ILayoutManager\";\nimport { Engine } from \"../core/Engine\";\nimport { SchemaNormalizer } from \"../core/SchemaNormalizer\";\nimport { Logger } from \"../utils/Logger\";\nimport Control from \"sap/ui/core/Control\";\n\n/**\n * Layout Manager responsible for generating a dense, lightweight layout (no SimpleForm padding).\n * Ideal for rendering objects dynamically inside table cells or side-panels.\n * \n * @namespace nz.co.siliconst.ui5.metaui.layouts\n * @public\n */\nexport class CompactLayout implements ILayoutManager {\n /**\n * Renders the JSON Schema properties into a dense VBox layout.\n * \n * @param schema The active JSON schema subset.\n * @param modelName The bound UI5 model name.\n * @param engine The central orchestrator for delegating plugin generation.\n * @param onSubmit Optional submit hook.\n * @returns {Control} The VBox wrapper containing the generated compact form.\n */\n public render(schema: ISchema, modelName: string, engine: Engine, onSubmit?: () => void): Control {\n const container = new VBox({ renderType: \"Bare\" });\n container.addStyleClass(\"sapUiTinyMargin\");\n\n if (!schema.uiLayout || !Array.isArray(schema.uiLayout)) {\n Logger.warn(\"[MetaUI] Missing 'uiLayout' array in schema. CompactLayout will not render any fields.\");\n return container;\n }\n\n const tableElements: { scope: string, meta: IPropertyMetadata, label?: string }[] = [];\n\n // Recursively render layout elements\n const renderElement = (element: ILayoutElement) => {\n if (element.type === \"Group\") {\n if (element.label) {\n const title = new sap.m.Title({ text: element.label, level: \"H5\" });\n title.addStyleClass(\"sapUiTinyMarginTop sapUiTinyMarginBottom\");\n container.addItem(title);\n }\n \n if (element.elements && Array.isArray(element.elements)) {\n element.elements.forEach(renderElement);\n }\n } else if (element.type === \"Control\") {\n if (!element.scope || !element.scope.startsWith(\"#/properties/\")) {\n Logger.error(`[MetaUI] Invalid scope '${element.scope}' in uiLayout Control.`, \"\", \"CompactLayout\");\n return;\n }\n \n const { meta, bindingPath, propKey } = SchemaNormalizer.resolveScope(schema, element.scope);\n \n if (!meta) {\n Logger.error(`[MetaUI] Property '${propKey}' not found in schema definitions.`, \"\", \"CompactLayout\");\n return;\n }\n\n const isCollectionOfRecords = meta.items?.type === \"object\" || meta.items?.properties;\n const hasExplicitWidget = !!meta.ui?.widget;\n const isSubLayout = meta.type === \"array\" && isCollectionOfRecords && !hasExplicitWidget;\n\n if (isSubLayout) {\n Logger.debug(\"[MetaUI CompactLayout]\", `Routing property '${propKey}' to Table Sub-Layout.`, \"CompactLayout\");\n tableElements.push({ scope: bindingPath, meta, label: element.label });\n } else {\n Logger.debug(\"[MetaUI CompactLayout]\", `Rendering scalar field '${bindingPath}'.`, \"CompactLayout\");\n this._renderScalarField(container, element, bindingPath, meta, modelName, engine);\n }\n } else {\n Logger.warn(`[MetaUI] Unsupported layout element type '${element.type}'.`, \"\", \"CompactLayout\");\n }\n };\n\n // Render everything defined in the layout\n schema.uiLayout.forEach(renderElement);\n\n // Render array/table sub-layouts full width below the fields\n tableElements.forEach(field => {\n try {\n const subSchema = {\n type: \"array\",\n title: field.label || field.meta.ui?.label || field.scope,\n items: field.meta.items || { type: \"object\", properties: {} },\n uiLayout: field.meta.items?.uiLayout\n };\n \n const control = engine.generateLayout(subSchema as ISchema, modelName, `/${field.scope}`);\n if (control) {\n control.addStyleClass(\"sapUiTinyMarginTop\");\n container.addItem(control);\n }\n } catch (error) {\n const msg = (error as Error).message;\n Logger.error(`[MetaUI] Failed to render array field ${field.scope}`, msg, \"CompactLayout\");\n Logger.showErrorPopup(`Failed to render array field '${field.scope}'.\\n\\nDetails: ${msg}`);\n }\n });\n\n return container;\n }\n\n /**\n * Synthesizes a primitive field into the layout.\n * @param container The VBox container.\n * @param element The layout element definition.\n * @param propKey The bound property key.\n * @param meta The inferred metadata schema.\n * @param modelName The UI5 data model name.\n * @param engine The core Engine instance.\n */\n private _renderScalarField(container: VBox, element: ILayoutElement, propKey: string, meta: IPropertyMetadata, modelName: string, engine: Engine): void {\n try {\n const labelText = element.label || meta.ui?.label || propKey;\n const label = new Label({\n text: labelText,\n required: meta.required\n });\n label.addStyleClass(\"sapUiTinyMarginTop\");\n\n const effectiveMeta = { ...meta };\n if (element.widget) {\n effectiveMeta.ui = { ...meta.ui, widget: element.widget };\n }\n\n const control = engine.generateField(effectiveMeta, `/${propKey}`, modelName);\n control.addStyleClass(\"sapUiTinyMarginBottom\");\n\n // Wrap label and field tightly\n const fieldBox = new VBox({ renderType: \"Bare\", items: [label, control] });\n container.addItem(fieldBox);\n } catch (error) {\n const msg = (error as Error).message;\n Logger.error(`[MetaUI] Failed to render field ${propKey}`, msg, \"CompactLayout\");\n Logger.showErrorPopup(`Failed to render field '${propKey}'.\\n\\nDetails: ${msg}`);\n }\n }\n}\n"],"mappings":"AAAA,oLAWSA,EAAgBC,EAAA,0BAChBC,EAAMC,EAAA,UAUR,MAAMC,EAUFC,OAAOC,EAAiBC,EAAmBC,EAAgBC,GAC9D,MAAMC,EAAY,IAAIC,EAAK,CAAEC,WAAY,SACzCF,EAAUG,cAAc,mBAExB,IAAKP,EAAOQ,WAAaC,MAAMC,QAAQV,EAAOQ,UAAW,CACrDZ,EAAOe,KAAK,0FACZ,OAAOP,CACX,CAEA,MAAMQ,EAA8E,GAGpF,MAAMC,EAAiBC,IACnB,GAAIA,EAAQC,OAAS,QAAS,CAC1B,GAAID,EAAQE,MAAO,CACf,MAAMC,EAAQ,IAAIC,IAAIC,EAAEC,MAAM,CAAEC,KAAMP,EAAQE,MAAOM,MAAO,OAC5DL,EAAMV,cAAc,4CACpBH,EAAUmB,QAAQN,EACtB,CAEA,GAAIH,EAAQU,UAAYf,MAAMC,QAAQI,EAAQU,UAAW,CACrDV,EAAQU,SAASC,QAAQZ,EAC7B,CACJ,MAAO,GAAIC,EAAQC,OAAS,UAAW,CACnC,IAAKD,EAAQY,QAAUZ,EAAQY,MAAMC,WAAW,iBAAkB,CAC9D/B,EAAOgC,MAAM,2BAA2Bd,EAAQY,8BAA+B,GAAI,iBACnF,MACJ,CAEA,MAAMG,KAAEA,EAAIC,YAAEA,EAAWC,QAAEA,GAAYrC,EAAiBsC,aAAahC,EAAQc,EAAQY,OAErF,IAAKG,EAAM,CACPjC,EAAOgC,MAAM,sBAAsBG,sCAA6C,GAAI,iBACpF,MACJ,CAEA,MAAME,EAAwBJ,EAAKK,OAAOnB,OAAS,UAAYc,EAAKK,OAAOC,WAC3E,MAAMC,IAAsBP,EAAKQ,IAAIC,OACrC,MAAMC,EAAcV,EAAKd,OAAS,SAAWkB,IAA0BG,EAEvE,GAAIG,EAAa,CACb3C,EAAO4C,MAAM,yBAA0B,qBAAqBT,0BAAiC,iBAC7FnB,EAAc6B,KAAK,CAAEf,MAAOI,EAAaD,OAAMb,MAAOF,EAAQE,OAClE,KAAO,CACHpB,EAAO4C,MAAM,yBAA0B,2BAA2BV,MAAiB,iBACnFY,KAAKC,mBAAmBvC,EAAWU,EAASgB,EAAaD,EAAM5B,EAAWC,EAC9E,CACJ,KAAO,CACHN,EAAOe,KAAK,6CAA6CG,EAAQC,SAAU,GAAI,gBACnF,GAIJf,EAAOQ,SAASiB,QAAQZ,GAGxBD,EAAca,QAAQmB,IAClB,IACI,MAAMC,EAAY,CACd9B,KAAM,QACNE,MAAO2B,EAAM5B,OAAS4B,EAAMf,KAAKQ,IAAIrB,OAAS4B,EAAMlB,MACpDQ,MAAOU,EAAMf,KAAKK,OAAS,CAAEnB,KAAM,SAAUoB,WAAY,CAAC,GAC1D3B,SAAUoC,EAAMf,KAAKK,OAAO1B,UAGhC,MAAMsC,EAAU5C,EAAO6C,eAAeF,EAAsB5C,EAAW,IAAI2C,EAAMlB,SACjF,GAAIoB,EAAS,CACTA,EAAQvC,cAAc,sBACtBH,EAAUmB,QAAQuB,EACtB,CACJ,CAAE,MAAOlB,GACL,MAAMoB,EAAOpB,EAAgBqB,QAC7BrD,EAAOgC,MAAM,yCAAyCgB,EAAMlB,QAASsB,EAAK,iBAC1EpD,EAAOsD,eAAe,iCAAiCN,EAAMlB,uBAAuBsB,IACxF,IAGJ,OAAO5C,CACX,CAWQuC,mBAAmBvC,EAAiBU,EAAyBiB,EAAiBF,EAAyB5B,EAAmBC,GAC9H,IACI,MAAMiD,EAAYrC,EAAQE,OAASa,EAAKQ,IAAIrB,OAASe,EACrD,MAAMf,EAAQ,IAAIoC,EAAM,CACpB/B,KAAM8B,EACNE,SAAUxB,EAAKwB,WAEnBrC,EAAMT,cAAc,sBAEpB,MAAM+C,EAAgB,IAAKzB,GAC3B,GAAIf,EAAQwB,OAAQ,CAChBgB,EAAcjB,GAAK,IAAKR,EAAKQ,GAAIC,OAAQxB,EAAQwB,OACrD,CAEA,MAAMQ,EAAU5C,EAAOqD,cAAcD,EAAe,IAAIvB,IAAW9B,GACnE6C,EAAQvC,cAAc,yBAGtB,MAAMiD,EAAW,IAAInD,EAAK,CAAEC,WAAY,OAAQ4B,MAAO,CAAClB,EAAO8B,KAC/D1C,EAAUmB,QAAQiC,EACtB,CAAE,MAAO5B,GACL,MAAMoB,EAAOpB,EAAgBqB,QAC7BrD,EAAOgC,MAAM,mCAAmCG,IAAWiB,EAAK,iBAChEpD,EAAOsD,eAAe,2BAA2BnB,mBAAyBiB,IAC9E,CACJ,EACH,IAAAS,EAAA,CAAAC,WAAA,MAAAD,EAAA3D,gBAAA,OAAA2D,CAAA","ignoreList":[],"sourceRoot":"layouts"}},{"offset":{"line":24,"column":0},"map":{"version":3,"names":["SchemaNormalizer","___core_SchemaNormalizer","Logger","___utils_Logger","FormLayout","render","schema","modelName","engine","onSubmit","container","VBox","renderType","form","SimpleForm","editable","title","layout","labelSpanXL","labelSpanL","labelSpanM","labelSpanS","adjustLabelSpan","emptySpanXL","emptySpanL","emptySpanM","emptySpanS","columnsXL","columnsL","columnsM","singleContainerFullSize","uiLayout","Array","isArray","warn","addItem","tableElements","hasFormFields","renderElement","element","type","label","addContent","Title","text","elements","forEach","scope","startsWith","error","meta","bindingPath","propKey","resolveScope","isCollectionOfRecords","items","properties","hasExplicitWidget","ui","widget","isSubLayout","debug","push","this","_renderScalarField","field","subSchema","control","generateLayout","addStyleClass","msg","message","showErrorPopup","labelText","Label","required","effectiveMeta","generateField","fullWidth","sap","require","GridData","setLayoutData","span","__exports","__esModule"],"sources":["FormLayout.ts"],"sourcesContent":["/**\n * @file FormLayout.ts\n * @description Generates a fully responsive SAP Fiori Form layout (SimpleForm).\n */\n\nimport SimpleForm from \"sap/ui/layout/form/SimpleForm\";\nimport Label from \"sap/m/Label\";\nimport Title from \"sap/ui/core/Title\";\nimport VBox from \"sap/m/VBox\";\nimport { IPropertyMetadata, ISchema, ILayoutElement } from \"../interfaces/ISchema\";\nimport { ILayoutManager } from \"../interfaces/ILayoutManager\";\nimport { Engine } from \"../core/Engine\";\nimport { SchemaNormalizer } from \"../core/SchemaNormalizer\";\nimport { Logger } from \"../utils/Logger\";\nimport Control from \"sap/ui/core/Control\";\n\n/**\n * Layout Manager responsible for generating a fully responsive SAP Fiori SimpleForm.\n * It traverses the `uiLayout` tree defined in the schema to build the form groups and fields,\n * completely separating visual orchestration from data modeling.\n * @namespace nz.co.siliconst.ui5.metaui.layouts\n * @public\n */\nexport class FormLayout implements ILayoutManager {\n /**\n * Renders the JSON Schema properties into a UI5 SimpleForm using the uiLayout definitions.\n * \n * @param schema The active JSON schema subset.\n * @param modelName The bound UI5 model name.\n * @param engine The central orchestrator for delegating plugin generation.\n * @param onSubmit Optional submit hook.\n * @returns {Control} The VBox wrapper containing the generated form.\n */\n public render(schema: ISchema, modelName: string, engine: Engine, onSubmit?: () => void): Control {\n const container = new VBox({ renderType: \"Bare\" });\n const form = new SimpleForm({\n editable: true,\n title: schema.title,\n layout: \"ResponsiveGridLayout\",\n labelSpanXL: 4, labelSpanL: 4, labelSpanM: 4, labelSpanS: 12,\n adjustLabelSpan: false,\n emptySpanXL: 0, emptySpanL: 0, emptySpanM: 0, emptySpanS: 0,\n columnsXL: 1, columnsL: 1, columnsM: 1,\n singleContainerFullSize: false\n });\n\n if (!schema.uiLayout || !Array.isArray(schema.uiLayout)) {\n Logger.warn(\"[MetaUI] Missing 'uiLayout' array in schema. Form will not render any fields.\");\n container.addItem(form);\n return container;\n }\n\n const tableElements: { scope: string, meta: IPropertyMetadata, label?: string }[] = [];\n let hasFormFields = false;\n\n // Recursively render layout elements\n const renderElement = (element: ILayoutElement) => {\n if (element.type === \"Group\") {\n if (element.label) {\n form.addContent(new Title({ text: element.label }));\n }\n \n if (element.elements && Array.isArray(element.elements)) {\n element.elements.forEach(renderElement);\n }\n } else if (element.type === \"Control\") {\n if (!element.scope || !element.scope.startsWith(\"#/properties/\")) {\n Logger.error(`[MetaUI] Invalid scope '${element.scope}' in uiLayout Control.`, \"\", \"FormLayout\");\n return;\n }\n \n const { meta, bindingPath, propKey } = SchemaNormalizer.resolveScope(schema, element.scope);\n \n if (!meta) {\n Logger.error(`[MetaUI] Property '${propKey}' not found in schema definitions.`, \"\", \"FormLayout\");\n return;\n }\n\n // Architectural Boundary: Separate Field Controls (Plugins) from Sub-Layouts (LayoutManagers)\n // A property is delegated to a Sub-Layout Manager (Table) ONLY if it represents a collection of complex objects.\n // Collections of primitives, or explicitly assigned widgets (like multiSelect), remain in the Form as Field Plugins.\n const isCollectionOfRecords = meta.items?.type === \"object\" || meta.items?.properties;\n const hasExplicitWidget = !!meta.ui?.widget;\n const isSubLayout = meta.type === \"array\" && isCollectionOfRecords && !hasExplicitWidget;\n\n if (isSubLayout) {\n Logger.debug(\"[MetaUI FormLayout]\", `Routing property '${propKey}' to Table Sub-Layout.`, \"FormLayout\");\n tableElements.push({ scope: bindingPath, meta, label: element.label });\n } else {\n hasFormFields = true;\n Logger.debug(\"[MetaUI FormLayout]\", `Rendering scalar field '${bindingPath}'.`, \"FormLayout\");\n this._renderScalarField(form, element, bindingPath, meta, modelName, engine);\n }\n } else {\n Logger.warn(`[MetaUI] Unsupported layout element type '${element.type}'.`, \"\", \"FormLayout\");\n }\n };\n\n // Render everything defined in the layout\n schema.uiLayout.forEach(renderElement);\n\n if (hasFormFields) {\n container.addItem(form);\n }\n\n // Render array/table sub-layouts full width below the form\n tableElements.forEach(field => {\n try {\n const subSchema = {\n type: \"array\",\n title: field.label || field.meta.ui?.label || field.scope,\n items: field.meta.items || { type: \"object\", properties: {} },\n uiLayout: field.meta.items?.uiLayout // Pass down sub-layout if available\n };\n \n const control = engine.generateLayout(subSchema as ISchema, modelName, `/${field.scope}`);\n if (control) {\n control.addStyleClass(\"sapUiSmallMarginTop\");\n container.addItem(control);\n }\n } catch (error) {\n const msg = (error as Error).message;\n Logger.error(`[MetaUI] Failed to render array field ${field.scope}`, msg, \"FormLayout\");\n Logger.showErrorPopup(`Failed to render array field '${field.scope}'.\\n\\nDetails: ${msg}`);\n }\n });\n\n return container;\n }\n\n /**\n * Synthesizes a primitive field into the Form.\n * @param form The SimpleForm instance.\n * @param element The layout element definition.\n * @param propKey The bound property key.\n * @param meta The inferred metadata schema.\n * @param modelName The UI5 data model name.\n * @param engine The core Engine instance.\n */\n private _renderScalarField(form: SimpleForm, element: ILayoutElement, propKey: string, meta: IPropertyMetadata, modelName: string, engine: Engine): void {\n try {\n const labelText = element.label || meta.ui?.label || propKey;\n const label = new Label({\n text: labelText,\n required: meta.required\n });\n\n // Override widget if specified in the layout element\n const effectiveMeta = { ...meta };\n if (element.widget) {\n effectiveMeta.ui = { ...meta.ui, widget: element.widget };\n }\n\n const control = engine.generateField(effectiveMeta, `/${propKey}`, modelName);\n\n if (effectiveMeta.ui?.fullWidth) {\n sap.ui.require([\"sap/ui/layout/GridData\"], (GridData: typeof import(\"sap/ui/layout/GridData\").default) => {\n control.setLayoutData(new GridData({ span: \"XL12 L12 M12 S12\" }));\n });\n }\n\n form.addContent(label);\n form.addContent(control);\n } catch (error) {\n const msg = (error as Error).message;\n Logger.error(`[MetaUI] Failed to render field ${propKey}`, msg, \"FormLayout\");\n Logger.showErrorPopup(`Failed to render field '${propKey}'.\\n\\nDetails: ${msg}`);\n }\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"layouts"}},{"offset":{"line":25,"column":0},"map":{"version":3,"names":["SchemaNormalizer","___core_SchemaNormalizer","Logger","___utils_Logger","TableLayout","render","schema","modelName","engine","onSubmit","bindingPath","type","items","properties","Error","tableTitle","title","actualModelName","actualPath","table","Table","headerToolbar","Toolbar","content","Title","text","ToolbarSpacer","isEditable","Button","icon","press","oEvent","btn","getSource","tbl","getParent","model","getModel","info","getBindingInfo","path","rawData","getProperty","data","Array","isArray","newData","setProperty","onChange","replace","fixedLayout","mode","delete","item","getParameter","getBindingContext","getPath","splitPaths","split","index","parseInt","pop","arrayPath","join","splice","templateCells","props","layoutElements","uiLayout","forEach","element","scope","meta","fieldMeta","propKey","resolveScope","error","addColumn","Column","header","Text","label","ui","demandPopin","isKey","minScreenWidth","popinDisplay","effectiveMeta","widget","control","generateField","push","warn","debug","Object","keys","key","column","msg","message","showErrorPopup","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 Control from \"sap/ui/core/Control\";\nimport { IPropertyMetadata, ISchema, ILayoutElement } from \"../interfaces/ISchema\";\nimport { ILayoutManager } from \"../interfaces/ILayoutManager\";\nimport { Engine } from \"../core/Engine\";\nimport { SchemaNormalizer } from \"../core/SchemaNormalizer\";\nimport { Logger } from \"../utils/Logger\";\n\n/**\n * Layout Manager responsible for generating a responsive SAP Fiori Table.\n * It is automatically utilized by the Engine when the schema root or property is of type 'array'.\n * Includes built-in support for adding and deleting rows via dynamic data binding manipulation.\n * \n * @namespace nz.co.siliconst.ui5.metaui.layouts\n * @public\n */\nexport class TableLayout implements ILayoutManager {\n /**\n * Renders the JSON Schema array properties into a UI5 Table.\n * \n * @param schema The active JSON schema array definition.\n * @param modelName The UI5 JSONModel name used for data binding.\n * @param engine The central orchestrator for delegating column plugin generation.\n * @param onSubmit Optional submit hook.\n * @param bindingPath The JSON path representing the array within the payload.\n * @returns {Control} The generated sap.m.Table control.\n * @throws {Error} If the provided schema is not of type 'array'.\n */\n public render(schema: ISchema, modelName: string, engine: Engine, onSubmit?: () => void, bindingPath: string = \"/\"): Control {\n if (schema.type !== \"array\" || !schema.items || !schema.items.properties) {\n throw new Error(\"[MetaUI] TableLayout requires an array schema with items.properties.\");\n }\n\n const tableTitle = schema.title || \"Table\";\n const actualModelName = modelName;\n const actualPath = bindingPath;\n\n const table = new Table({\n headerToolbar: new Toolbar({\n content: [\n new Title({ text: tableTitle }),\n new ToolbarSpacer(),\n ...(!engine.isEditable ? [] : [\n new Button({\n text: \"Add Row\",\n icon: \"sap-icon://add\",\n press: (oEvent: sap.ui.base.Event) => {\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 rawData = model.getProperty(info.path);\n const data = Array.isArray(rawData) ? rawData : [];\n const newData = [...data, {}];\n model.setProperty(info.path, newData);\n\n // CRITICAL: Notify the engine so it extracts payload and triggers liveUpdate\n if (engine.onChange) {\n engine.onChange(true, actualPath.replace(/^\\//, \"\"));\n }\n }\n })\n ])\n ]\n }),\n fixedLayout: false,\n mode: !engine.isEditable ? \"None\" : \"Delete\",\n delete: (oEvent: sap.ui.base.Event) => {\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 rawData = model.getProperty(arrayPath);\n const data = Array.isArray(rawData) ? rawData : [];\n const newData = [...data];\n newData.splice(index, 1);\n model.setProperty(arrayPath, newData);\n\n // CRITICAL: Notify the engine so it extracts payload and triggers liveUpdate\n if (engine.onChange) {\n engine.onChange(true, actualPath.replace(/^\\//, \"\"));\n }\n }\n });\n\n const templateCells: Control[] = [];\n const props = schema.items.properties;\n const layoutElements = schema.uiLayout;\n\n if (layoutElements && Array.isArray(layoutElements)) {\n // Only render columns defined in uiLayout\n layoutElements.forEach((element: ILayoutElement) => {\n if (element.type === \"Control\" && element.scope) {\n const { meta: fieldMeta, bindingPath, propKey } = SchemaNormalizer.resolveScope(\n { type: \"object\", properties: props } as ISchema, \n element.scope\n );\n \n if (!fieldMeta) {\n Logger.error(`[MetaUI] Property '${propKey}' not found in schema definitions for Table.`, \"\", \"TableLayout\");\n } else {\n // The architectural boundary: Table Layout orchestrates the columns and aggregation binding,\n // but delegates the actual cell rendering to the Engine's Field Plugins.\n table.addColumn(new Column({\n header: new Text({ text: element.label || fieldMeta.ui?.label || propKey }),\n demandPopin: !fieldMeta.ui?.isKey,\n minScreenWidth: fieldMeta.ui?.isKey ? \"\" : \"Tablet\",\n popinDisplay: \"Inline\"\n }));\n\n const effectiveMeta = { ...fieldMeta };\n if (element.widget) {\n effectiveMeta.ui = { ...fieldMeta.ui, widget: element.widget };\n }\n\n // We pass the activeModel as actualModelName down. But the path must be relative to the \n // table row binding context, so we just use the bindingPath (e.g. \"id\" or \"header/id\")\n const control = engine.generateField(effectiveMeta, bindingPath, actualModelName || \"meta\", true);\n templateCells.push(control);\n }\n } else {\n Logger.warn(`[MetaUI] Unsupported layout element type '${element.type}' in Table.`, \"\", \"TableLayout\");\n }\n });\n } else {\n Logger.debug(\"[MetaUI TableLayout]\", \"No uiLayout provided. Falling back to rendering all properties as columns.\", \"TableLayout\");\n // Fallback: If no uiLayout is provided, render all properties as columns\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 control = engine.generateField(fieldMeta, key, actualModelName || \"meta\", true);\n templateCells.push(control);\n } catch (error) {\n const msg = (error as Error).message;\n Logger.error(`[MetaUI] Failed to render fallback column ${key}`, msg, \"TableLayout\");\n Logger.showErrorPopup(`Failed to render fallback table column '${key}'.\\n\\nDetails: ${msg}`);\n templateCells.push(new Text({ text: \"Error\" }));\n }\n });\n }\n\n\n\n const rowTemplate = new ColumnListItem({\n cells: templateCells\n });\n\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":[],"sourceRoot":"layouts"}},{"offset":{"line":26,"column":0},"map":{"version":3,"names":["SchemaNormalizer","___core_SchemaNormalizer","Logger","___utils_Logger","WizardLayout","render","schema","modelName","engine","onSubmit","wizard","Wizard","renderMode","showNextButton","complete","uiLayout","Array","isArray","warn","forEach","element","type","step","WizardStep","title","label","validated","form","SimpleForm","editable","layout","labelSpanXL","labelSpanL","labelSpanM","labelSpanS","adjustLabelSpan","emptySpanXL","emptySpanL","emptySpanM","emptySpanS","columnsXL","columnsL","columnsM","singleContainerFullSize","elements","childElement","this","_renderElementInForm","addContent","addStep","scope","startsWith","error","meta","bindingPath","propKey","resolveScope","labelText","ui","Label","text","required","effectiveMeta","widget","control","generateField","fullWidth","sap","require","GridData","setLayoutData","span","message","__exports","__esModule"],"sources":["WizardLayout.ts"],"sourcesContent":["/**\n * @file WizardLayout.ts\n * @description Generates a fully responsive SAP Fiori Wizard layout.\n */\n\nimport Wizard from \"sap/m/Wizard\";\nimport WizardStep from \"sap/m/WizardStep\";\nimport SimpleForm from \"sap/ui/layout/form/SimpleForm\";\nimport Label from \"sap/m/Label\";\nimport VBox from \"sap/m/VBox\";\nimport { IPropertyMetadata, ISchema, ILayoutElement } from \"../interfaces/ISchema\";\nimport { ILayoutManager } from \"../interfaces/ILayoutManager\";\nimport { Engine } from \"../core/Engine\";\nimport { SchemaNormalizer } from \"../core/SchemaNormalizer\";\nimport { Logger } from \"../utils/Logger\";\nimport Control from \"sap/ui/core/Control\";\n\n/**\n * Layout Manager responsible for generating a responsive SAP Fiori Wizard.\n * It segments the schema fields into discrete Wizard Steps based on `uiLayout` elements \n * of type `Group` or `WizardStep`.\n * \n * @namespace nz.co.siliconst.ui5.metaui.layouts\n * @public\n */\nexport class WizardLayout implements ILayoutManager {\n /**\n * Renders the JSON Schema properties into a paginated UI5 Wizard using uiLayout.\n * \n * @param schema The active JSON schema object.\n * @param modelName The bound UI5 model name.\n * @param engine The central orchestrator for delegating plugin generation.\n * @param onSubmit Hook executed when the Wizard's native 'complete' event is fired.\n * @returns {Control} The generated sap.m.Wizard control.\n */\n public render(schema: ISchema, modelName: string, engine: Engine, onSubmit?: () => void): Control {\n const wizard = new Wizard({\n renderMode: \"Page\",\n showNextButton: true,\n complete: function() {\n if (onSubmit) onSubmit();\n }\n });\n\n if (!schema.uiLayout || !Array.isArray(schema.uiLayout)) {\n Logger.warn(\"[MetaUI] Missing 'uiLayout' array in wizard schema. Wizard will not render any steps.\");\n return wizard;\n }\n\n schema.uiLayout.forEach((element: ILayoutElement) => {\n if (element.type === \"Group\" || element.type === \"WizardStep\") {\n const step = new WizardStep({\n title: element.label || \"Step\",\n validated: true // The PipelineManager handles global validation, wizard step validation can be local later\n });\n\n const form = new SimpleForm({\n editable: true,\n layout: \"ResponsiveGridLayout\",\n labelSpanXL: 4, labelSpanL: 4, labelSpanM: 4, labelSpanS: 12,\n adjustLabelSpan: false,\n emptySpanXL: 0, emptySpanL: 0, emptySpanM: 0, emptySpanS: 0,\n columnsXL: 1, columnsL: 1, columnsM: 1,\n singleContainerFullSize: false\n });\n \n if (element.elements && Array.isArray(element.elements)) {\n element.elements.forEach(childElement => {\n this._renderElementInForm(form, childElement, schema, modelName, engine);\n });\n }\n\n step.addContent(form);\n wizard.addStep(step);\n } else {\n Logger.warn(`[MetaUI] Top-level element '${element.type}' inside WizardLayout must be 'Group' or 'WizardStep'.`, \"\", \"WizardLayout\");\n }\n });\n\n return wizard;\n }\n\n /**\n * Synthesizes a field into the wizard step form.\n * @param form The SimpleForm belonging to the step.\n * @param element The layout element definition.\n * @param schema The schema reference.\n * @param modelName The UI5 data model name.\n * @param engine The core Engine instance.\n */\n private _renderElementInForm(form: SimpleForm, element: ILayoutElement, schema: ISchema, modelName: string, engine: Engine): void {\n if (element.type === \"Control\") {\n if (!element.scope || !element.scope.startsWith(\"#/properties/\")) {\n Logger.error(`[MetaUI] Invalid scope '${element.scope}' in uiLayout Control.`, \"\", \"WizardLayout\");\n return;\n }\n \n const { meta, bindingPath, propKey } = SchemaNormalizer.resolveScope(schema, element.scope);\n \n if (!meta) {\n Logger.error(`[MetaUI] Property '${propKey}' not found in schema definitions.`, \"\", \"WizardLayout\");\n return;\n }\n\n try {\n const labelText = element.label || meta.ui?.label || propKey;\n const label = new Label({\n text: labelText,\n required: meta.required\n });\n\n const effectiveMeta = { ...meta };\n if (element.widget) {\n effectiveMeta.ui = { ...meta.ui, widget: element.widget };\n }\n\n const control = engine.generateField(effectiveMeta, `/${bindingPath}`, modelName);\n\n if (effectiveMeta.ui?.fullWidth) {\n sap.ui.require([\"sap/ui/layout/GridData\"], (GridData: typeof import(\"sap/ui/layout/GridData\").default) => {\n control.setLayoutData(new GridData({ span: \"XL12 L12 M12 S12\" }));\n });\n }\n\n form.addContent(label);\n form.addContent(control);\n } catch (error) {\n Logger.error(`[MetaUI] Failed to render Wizard field ${propKey}`, (error as Error).message, \"WizardLayout\");\n form.addContent(new Label({ text: propKey }));\n }\n } else {\n Logger.warn(`[MetaUI] Nested groups within Wizard steps are not fully supported in SimpleForm yet.`, \"\", \"WizardLayout\");\n }\n }\n}\n"],"mappings":"AAAA,4OAaSA,EAAgBC,EAAA,0BAChBC,EAAMC,EAAA,UAWR,MAAMC,EAUFC,OAAOC,EAAiBC,EAAmBC,EAAgBC,GAC9D,MAAMC,EAAS,IAAIC,EAAO,CACtBC,WAAY,OACZC,eAAgB,KAChBC,SAAU,WACN,GAAIL,EAAUA,GAClB,IAGJ,IAAKH,EAAOS,WAAaC,MAAMC,QAAQX,EAAOS,UAAW,CACrDb,EAAOgB,KAAK,yFACZ,OAAOR,CACX,CAEAJ,EAAOS,SAASI,QAASC,IACrB,GAAIA,EAAQC,OAAS,SAAWD,EAAQC,OAAS,aAAc,CAC3D,MAAMC,EAAO,IAAIC,EAAW,CACxBC,MAAOJ,EAAQK,OAAS,OACxBC,UAAW,OAGf,MAAMC,EAAO,IAAIC,EAAW,CACxBC,SAAU,KACVC,OAAQ,uBACRC,YAAa,EAAGC,WAAY,EAAGC,WAAY,EAAGC,WAAY,GAC1DC,gBAAiB,MACjBC,YAAa,EAAGC,WAAY,EAAGC,WAAY,EAAGC,WAAY,EAC1DC,UAAW,EAAGC,SAAU,EAAGC,SAAU,EACrCC,wBAAyB,QAG7B,GAAIvB,EAAQwB,UAAY5B,MAAMC,QAAQG,EAAQwB,UAAW,CACrDxB,EAAQwB,SAASzB,QAAQ0B,IACrBC,KAAKC,qBAAqBpB,EAAMkB,EAAcvC,EAAQC,EAAWC,IAEzE,CAEAc,EAAK0B,WAAWrB,GAChBjB,EAAOuC,QAAQ3B,EACnB,KAAO,CACHpB,EAAOgB,KAAK,+BAA+BE,EAAQC,6DAA8D,GAAI,eACzH,IAGJ,OAAOX,CACX,CAUQqC,qBAAqBpB,EAAkBP,EAAyBd,EAAiBC,EAAmBC,GACxG,GAAIY,EAAQC,OAAS,UAAW,CAC5B,IAAKD,EAAQ8B,QAAU9B,EAAQ8B,MAAMC,WAAW,iBAAkB,CAC9DjD,EAAOkD,MAAM,2BAA2BhC,EAAQ8B,8BAA+B,GAAI,gBACnF,MACJ,CAEA,MAAMG,KAAEA,EAAIC,YAAEA,EAAWC,QAAEA,GAAYvD,EAAiBwD,aAAalD,EAAQc,EAAQ8B,OAErF,IAAKG,EAAM,CACPnD,EAAOkD,MAAM,sBAAsBG,sCAA6C,GAAI,gBACpF,MACJ,CAEA,IACI,MAAME,EAAYrC,EAAQK,OAAS4B,EAAKK,IAAIjC,OAAS8B,EACrD,MAAM9B,EAAQ,IAAIkC,EAAM,CACpBC,KAAMH,EACNI,SAAUR,EAAKQ,WAGnB,MAAMC,EAAgB,IAAKT,GAC3B,GAAIjC,EAAQ2C,OAAQ,CAChBD,EAAcJ,GAAK,IAAKL,EAAKK,GAAIK,OAAQ3C,EAAQ2C,OACrD,CAEA,MAAMC,EAAUxD,EAAOyD,cAAcH,EAAe,IAAIR,IAAe/C,GAEvE,GAAIuD,EAAcJ,IAAIQ,UAAW,CAC7BC,IAAIT,GAAGU,QAAQ,CAAC,0BAA4BC,IACxCL,EAAQM,cAAc,IAAID,EAAS,CAAEE,KAAM,uBAEnD,CAEA5C,EAAKqB,WAAWvB,GAChBE,EAAKqB,WAAWgB,EACpB,CAAE,MAAOZ,GACLlD,EAAOkD,MAAM,0CAA0CG,IAAYH,EAAgBoB,QAAS,gBAC5F7C,EAAKqB,WAAW,IAAIW,EAAM,CAAEC,KAAML,IACtC,CACJ,KAAO,CACHrD,EAAOgB,KAAK,wFAAyF,GAAI,eAC7G,CACJ,EACH,IAAAuD,EAAA,CAAAC,WAAA,MAAAD,EAAArE,eAAA,OAAAqE,CAAA","ignoreList":[],"sourceRoot":"layouts"}},{"offset":{"line":27,"column":0},"map":{"version":3,"names":["Core","initLibrary","name","version","dependencies","controls","elements","interfaces","noLibraryCSS","__exports","window","nz","co","siliconst","ui5","metaui"],"sources":["library.ts"],"sourcesContent":["/**\n * @file library.ts\n * @description Standard SAP UI5 library registration file. Exposes the MetaUI namespace \n * and automatically bootstraps the internal PluginRegistry.\n */\n\nimport Core from \"sap/ui/core/Core\";\n\n// Explicitly import core plugins to bundle them into library-preload.js\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/StringPlugin\";\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/NumberPlugin\";\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/BooleanPlugin\";\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/ObjectPlugin\";\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/ArrayPlugin\";\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/DropdownPlugin\";\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/MultiInputPlugin\";\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/DatePlugin\";\nimport \"nz/co/siliconst/ui5/metaui/core/DefaultLayoutGenerator\";\nimport \"nz/co/siliconst/ui5/metaui/utils/ExpressionBuilder\";\n\n// Explicitly import core Layouts\nimport \"nz/co/siliconst/ui5/metaui/layouts/FormLayout\";\nimport \"nz/co/siliconst/ui5/metaui/layouts/TableLayout\";\nimport \"nz/co/siliconst/ui5/metaui/layouts/WizardLayout\";\nimport \"nz/co/siliconst/ui5/metaui/layouts/CompactLayout\";\n\n// Delegate to standard library registration\nCore.initLibrary({\n name: \"nz.co.siliconst.ui5.metaui\",\n version: \"1.0.0\",\n dependencies: [\n \"sap.ui.core\",\n \"sap.m\",\n \"sap.ui.layout\",\n \"sap.ui.table\"\n ],\n controls: [\n \"nz.co.siliconst.ui5.metaui.controls.DynamicHost\",\n \"nz.co.siliconst.ui5.metaui.controls.host.GeneratorHost\",\n \"nz.co.siliconst.ui5.metaui.controls.BaseHardwareControl\",\n \"nz.co.siliconst.ui5.metaui.controls.CameraControl\",\n \"nz.co.siliconst.ui5.metaui.controls.BarcodeScannerControl\",\n \"nz.co.siliconst.ui5.metaui.controls.SignatureControl\",\n \"nz.co.siliconst.ui5.metaui.controls.VoiceInputControl\",\n \"nz.co.siliconst.ui5.metaui.controls.GeolocationControl\",\n \"nz.co.siliconst.ui5.metaui.controls.RichTextControl\"\n ],\n elements: [],\n interfaces: [],\n noLibraryCSS: true\n});\n\n// Exporting window object safely for UI5 compatibility if needed\ndeclare global {\n interface Window {\n nz: {\n co: {\n siliconst: {\n ui5: {\n metaui: Record<string, unknown>;\n };\n };\n };\n };\n }\n}\n\nexport default window.nz.co.siliconst.ui5.metaui;\n"],"mappings":"AAAA,i5BA2BAA,EAAKC,YAAY,CACbC,KAAM,6BACNC,QAAS,QACTC,aAAc,CACV,cACA,QACA,gBACA,gBAEJC,SAAU,CACN,kDACA,yDACA,0DACA,oDACA,4DACA,uDACA,wDACA,yDACA,uDAEJC,SAAU,GACVC,WAAY,GACZC,aAAc,OAGlB,IAAAC,EAeeC,OAAOC,GAAGC,GAAGC,UAAUC,IAAIC,OAAM,OAAAN,CAAA","ignoreList":[],"sourceRoot":""}},{"offset":{"line":28,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","ClearFormActionPlugin","render","fieldMetadata","bindingPath","modelName","this","metadata","isEditable","sap","ui","requireSync","TextControl","require","control","visible","Button","text","label","type","icon","press","oEvent","btn","getSource","model","getModel","setProperty","getValue","applyState","setEnabled","readOnly","__exports","__esModule"],"sources":["ClearFormActionPlugin.ts"],"sourcesContent":["/**\n * @file ClearFormActionPlugin.ts\n * @description A custom action plugin that renders a Button to reset the model data.\n */\n\nimport { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Button from \"sap/m/Button\";\nimport Control from \"sap/ui/core/Control\";\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\n\n/**\n * A custom action plugin that renders a Button to reset the model data.\n * Demonstrates how to create functional action plugins that interact with the bound model.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.actions\n * @public\n */\nexport class ClearFormActionPlugin extends BasePlugin {\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\"): Control {\n this.metadata = fieldMetadata;\n \n if (!this.isEditable) {\n sap.ui.requireSync(\"sap/m/Text\");\n const TextControl = sap.ui.require(\"sap/m/Text\");\n this.control = new TextControl({ visible: false });\n return this.control as Control;\n }\n \n this.control = new Button({\n text: fieldMetadata.ui?.label || \"Clear Data\",\n type: \"Reject\",\n icon: \"sap-icon://delete\",\n press: (oEvent: sap.ui.base.Event) => {\n const btn = oEvent.getSource() as Button;\n const model = btn.getModel(modelName) as JSONModel;\n if (model) {\n // Reset the entire model payload to an empty object\n model.setProperty(\"/\", {});\n }\n }\n });\n\n return this.control as Control;\n }\n\n protected getValue(): unknown {\n return null; // Actions do not store scalar values\n }\n\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as Button).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,0JAAA,MAKSA,EAAUC,EAAA,cAaZ,MAAMC,UAA8BF,EAChCG,OAAOC,EAAkCC,EAAqBC,EAAoB,QACrFC,KAAKC,SAAWJ,EAEhB,IAAKG,KAAKE,WAAY,CAClBC,IAAIC,GAAGC,YAAY,cACnB,MAAMC,EAAcH,IAAIC,GAAGG,QAAQ,cACnCP,KAAKQ,QAAU,IAAIF,EAAY,CAAEG,QAAS,QAC1C,OAAOT,KAAKQ,OAChB,CAEAR,KAAKQ,QAAU,IAAIE,EAAO,CACtBC,KAAMd,EAAcO,IAAIQ,OAAS,aACjCC,KAAM,SACNC,KAAM,oBACNC,MAAQC,IACJ,MAAMC,EAAMD,EAAOE,YACnB,MAAMC,EAAQF,EAAIG,SAASrB,GAC3B,GAAIoB,EAAO,CAEPA,EAAME,YAAY,IAAK,CAAC,EAC5B,KAIR,OAAOrB,KAAKQ,OAChB,CAEUc,WACN,OAAO,IACX,CAEUC,aACN,GAAIvB,KAAKQ,SAAWR,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACrBF,KAAKQ,QAAmBgB,YAAYxB,KAAKC,SAASG,IAAIqB,SAC3D,CACJ,EACH,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAA/B,wBAAA,OAAA+B,CAAA","ignoreList":[],"sourceRoot":"plugins/actions"}},{"offset":{"line":29,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","SubmitFormActionPlugin","render","fieldMetadata","bindingPath","modelName","this","metadata","isEditable","sap","ui","requireSync","TextControl","require","control","visible","Button","text","label","type","icon","press","Core","getEventBus","publish","getValue","applyState","setEnabled","readOnly","__exports","__esModule"],"sources":["SubmitFormActionPlugin.ts"],"sourcesContent":["/**\n * @file SubmitFormActionPlugin.ts\n * @description A custom action plugin that triggers form submission.\n */\n\nimport { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Button from \"sap/m/Button\";\nimport Control from \"sap/ui/core/Control\";\nimport Core from \"sap/ui/core/Core\";\n\n/**\n * Renders a Button that requests the host container to execute its submit flow.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.actions\n * @public\n */\nexport class SubmitFormActionPlugin extends BasePlugin {\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\"): Control {\n this.metadata = fieldMetadata;\n \n if (!this.isEditable) {\n sap.ui.requireSync(\"sap/m/Text\");\n const TextControl = sap.ui.require(\"sap/m/Text\");\n this.control = new TextControl({ visible: false });\n return this.control as Control;\n }\n \n this.control = new Button({\n text: fieldMetadata.ui?.label || \"Submit\",\n type: \"Emphasized\",\n icon: \"sap-icon://save\",\n press: () => {\n // Fire an event that the GeneratorHost or LayoutManager listens to\n Core.getEventBus().publish(\"MetaUI\", \"TriggerSubmit\", {});\n }\n });\n\n return this.control as Control;\n }\n\n protected getValue(): unknown {\n return null;\n }\n\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as Button).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,gLAAA,MAKSA,EAAUC,EAAA,cAYZ,MAAMC,UAA+BF,EACjCG,OAAOC,EAAkCC,EAAqBC,EAAoB,QACrFC,KAAKC,SAAWJ,EAEhB,IAAKG,KAAKE,WAAY,CAClBC,IAAIC,GAAGC,YAAY,cACnB,MAAMC,EAAcH,IAAIC,GAAGG,QAAQ,cACnCP,KAAKQ,QAAU,IAAIF,EAAY,CAAEG,QAAS,QAC1C,OAAOT,KAAKQ,OAChB,CAEAR,KAAKQ,QAAU,IAAIE,EAAO,CACtBC,KAAMd,EAAcO,IAAIQ,OAAS,SACjCC,KAAM,aACNC,KAAM,kBACNC,MAAOA,KAEHC,EAAKC,cAAcC,QAAQ,SAAU,gBAAiB,CAAC,MAI/D,OAAOlB,KAAKQ,OAChB,CAEUW,WACN,OAAO,IACX,CAEUC,aACN,GAAIpB,KAAKQ,SAAWR,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACrBF,KAAKQ,QAAmBa,YAAYrB,KAAKC,SAASG,IAAIkB,SAC3D,CACJ,EACH,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAA5B,yBAAA,OAAA4B,CAAA","ignoreList":[],"sourceRoot":"plugins/actions"}},{"offset":{"line":30,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","URLHelper","library","UrlNavigationActionPlugin","render","fieldMetadata","bindingPath","modelName","this","metadata","control","Button","text","ui","label","icon","press","targetUrl","args","redirect","getValue","applyState","setEnabled","readOnly","__exports","__esModule"],"sources":["UrlNavigationActionPlugin.ts"],"sourcesContent":["/**\n * @file UrlNavigationActionPlugin.ts\n * @description A custom action plugin that navigates to a URL.\n */\n\nimport { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Button from \"sap/m/Button\";\nimport Control from \"sap/ui/core/Control\";\nimport * as library from \"sap/m/library\";\nconst URLHelper = library.URLHelper;\n\n/**\n * Renders a Button that triggers a redirect to an external URL (defined in args).\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.actions\n * @public\n */\nexport class UrlNavigationActionPlugin extends BasePlugin {\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\"): Control {\n this.metadata = fieldMetadata;\n\n this.control = new Button({\n text: fieldMetadata.ui?.label || \"Open Link\",\n icon: \"sap-icon://action\",\n press: () => {\n // In a real scenario, the URL might come from the payload or from schema args\n const targetUrl = fieldMetadata.ui?.args || \"https://sap.com\";\n URLHelper.redirect(targetUrl as string, true); // true = open in new window\n }\n });\n\n return this.control as Control;\n }\n\n protected getValue(): unknown {\n return null;\n }\n\n protected applyState(): void {\n if (this.control && this.metadata) {\n (this.control as Button).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,gLAAA,MAKSA,EAAUC,EAAA,cAKnB,MAAMC,EAAYC,EAAQD,UAQnB,MAAME,UAAkCJ,EACpCK,OAAOC,EAAkCC,EAAqBC,EAAoB,QACrFC,KAAKC,SAAWJ,EAEhBG,KAAKE,QAAU,IAAIC,EAAO,CACtBC,KAAMP,EAAcQ,IAAIC,OAAS,YACjCC,KAAM,oBACNC,MAAOA,KAEH,MAAMC,EAAYZ,EAAcQ,IAAIK,MAAQ,kBAC5CjB,EAAUkB,SAASF,EAAqB,SAIhD,OAAOT,KAAKE,OAChB,CAEUU,WACN,OAAO,IACX,CAEUC,aACN,GAAIb,KAAKE,SAAWF,KAAKC,SAAU,CAC9BD,KAAKE,QAAmBY,YAAYd,KAAKC,SAASI,IAAIU,SAC3D,CACJ,EACH,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAArB,4BAAA,OAAAqB,CAAA","ignoreList":[],"sourceRoot":"plugins/actions"}},{"offset":{"line":31,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","ArrayPlugin","render","field","bindingPath","modelName","engineScopeId","onChange","this","metadata","propKey","startsWith","substring","subSchema","type","title","ui","label","items","properties","uiLayout","control","Button","id","generateStableId","text","isEditable","icon","press","oEvent","btn","getSource","parentModel","getModel","bindingContext","getBindingContext","updatePath","ctxPath","getPath","endsWith","nestedData","JSON","parse","stringify","getProperty","sap","require","DynamicHost","host","schemaDefinition","data","editable","attachSubmit","e","payload","getParameter","setProperty","buttonText","dialogButtonText","openInDialog","getValue","applyState","__exports","__esModule"],"sources":["ArrayPlugin.ts"],"sourcesContent":["/**\n * @file ArrayPlugin.ts\n * @description Renders a button that drills down into a nested table (array) via a recursive Dialog using v2 schema.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport Button from \"sap/m/Button\";\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\n\nexport class ArrayPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.Button` to open a nested array form dialog.\n * \n * @param field The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured Button control.\n */\n public render(field: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = field;\n const propKey = bindingPath.startsWith(\"/\") ? bindingPath.substring(1) : bindingPath;\n \n const subSchema: ISchema = {\n type: \"array\",\n title: field.ui?.label || propKey,\n items: field.items || {\n type: \"object\",\n properties: {} // inference will handle it if empty\n }\n };\n\n if (field.uiLayout) {\n subSchema.uiLayout = field.uiLayout;\n }\n\n this.control = new Button({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: !this.isEditable ? \"View Records\" : \"Edit Records\",\n icon: !this.isEditable ? \"sap-icon://display\" : \"sap-icon://list\",\n press: (oEvent: sap.ui.base.Event) => {\n const btn = oEvent.getSource() as Button;\n const parentModel = btn.getModel(modelName) as JSONModel;\n if (!parentModel) return;\n \n const bindingContext = btn.getBindingContext(modelName);\n let updatePath = bindingPath;\n if (bindingContext && !bindingPath.startsWith(\"/\")) {\n const ctxPath = bindingContext.getPath();\n updatePath = ctxPath.endsWith(\"/\") ? ctxPath + bindingPath : (ctxPath === \"/\" ? \"/\" + bindingPath : ctxPath + \"/\" + bindingPath);\n }\n \n // Deep clone to prevent live-mutations on the parent model before 'Submit' is clicked\n const nestedData = JSON.parse(JSON.stringify(parentModel.getProperty(updatePath) || []));\n\n sap.ui.require([\"nz/co/siliconst/ui5/metaui/controls/DynamicHost\"], (DynamicHost: typeof import(\"../../controls/DynamicHost\").default) => {\n const host = new DynamicHost({\n schemaDefinition: subSchema,\n data: nestedData,\n editable: this.isEditable // Pass the display mode down to the child Engine!\n });\n\n // Only attach submit event if we are not in display mode\n if (!!this.isEditable) {\n host.attachSubmit((e: sap.ui.base.Event) => {\n const payload = e.getParameter(\"payload\");\n parentModel.setProperty(updatePath, payload);\n\n // CRITICAL: Notify the parent Engine that this field mutated\n // so it can trigger LiveUpdate syncs and validate!\n if (this.onChange) {\n this.onChange(true, propKey);\n }\n });\n }\n\n const buttonText = field.ui?.dialogButtonText || (!this.isEditable ? \"Close\" : \"OK\");\n host.openInDialog(`Nested Records: ${field.ui?.label || propKey}`, buttonText);\n });\n }\n });\n \n return this.control as Control;\n }\n\n /**\n * Read-only component for the engine, returns null.\n */\n protected getValue(): unknown {\n return null;\n }\n\n /**\n * Read-only component, no dynamic state handling needed for the button itself.\n */\n protected applyState(): void {\n // dynamic state changes\n }\n}\n"],"mappings":"AAAA,uIAAA,MAKSA,EAAUC,EAAA,cAMZ,MAAMC,UAAoBF,EAWtBG,OAAOC,EAA2BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAC/GC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChB,MAAMO,EAAUN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,MAAMS,EAAqB,CACvBC,KAAM,QACNC,MAAOZ,EAAMa,IAAIC,OAASP,EAC1BQ,MAAOf,EAAMe,OAAS,CAClBJ,KAAM,SACNK,WAAY,CAAC,IAIrB,GAAIhB,EAAMiB,SAAU,CAChBP,EAAUO,SAAWjB,EAAMiB,QAC/B,CAEAZ,KAAKa,QAAU,IAAIC,EAAO,CACtBC,GAAIf,KAAKgB,iBAAiBlB,EAAeF,GACzCqB,MAAOjB,KAAKkB,WAAa,eAAiB,eAC1CC,MAAOnB,KAAKkB,WAAa,qBAAuB,kBAChDE,MAAQC,IACJ,MAAMC,EAAMD,EAAOE,YACnB,MAAMC,EAAcF,EAAIG,SAAS5B,GACjC,IAAK2B,EAAa,OAElB,MAAME,EAAiBJ,EAAIK,kBAAkB9B,GAC7C,IAAI+B,EAAahC,EACjB,GAAI8B,IAAmB9B,EAAYO,WAAW,KAAM,CAChD,MAAM0B,EAAUH,EAAeI,UAC/BF,EAAaC,EAAQE,SAAS,KAAOF,EAAUjC,EAAeiC,IAAY,IAAM,IAAMjC,EAAciC,EAAU,IAAMjC,CACxH,CAGA,MAAMoC,EAAaC,KAAKC,MAAMD,KAAKE,UAAUX,EAAYY,YAAYR,IAAe,KAEpFS,IAAI7B,GAAG8B,QAAQ,CAAC,mDAAqDC,IACjE,MAAMC,EAAO,IAAID,EAAY,CACzBE,iBAAkBpC,EAClBqC,KAAMV,EACNW,SAAU3C,KAAKkB,aAInB,KAAMlB,KAAKkB,WAAY,CACnBsB,EAAKI,aAAcC,IACf,MAAMC,EAAUD,EAAEE,aAAa,WAC/BvB,EAAYwB,YAAYpB,EAAYkB,GAIpC,GAAI9C,KAAKD,SAAU,CACfC,KAAKD,SAAS,KAAMG,EACxB,GAER,CAEA,MAAM+C,EAAatD,EAAMa,IAAI0C,oBAAsBlD,KAAKkB,WAAa,QAAU,MAC/EsB,EAAKW,aAAa,mBAAmBxD,EAAMa,IAAIC,OAASP,IAAW+C,QAK/E,OAAOjD,KAAKa,OAChB,CAKUuC,WACN,OAAO,IACX,CAKUC,aACN,EAEP,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAA7D,cAAA,OAAA6D,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":32,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","BarcodeScannerPlugin","render","metadata","bindingPath","modelName","engineScopeId","onChange","this","fieldKey","replace","isEditable","control","TextControl","id","generateStableId","text","applyCommonDirectives","inputControl","Input","value","editable","ui","readOnly","width","change","result","validateAndApplyVisualState","isValid","scannerBtn","BarcodeScannerButton","scanSuccess","oEvent","getParameter","setValue","HBox","items","addStyleClass","getValue","applyState","setEditable","__exports","__esModule"],"sources":["BarcodeScannerPlugin.ts"],"sourcesContent":["import { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport HBox from \"sap/m/HBox\";\nimport Input from \"sap/m/Input\";\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\nimport BarcodeScannerButton from \"sap/ndc/BarcodeScannerButton\";\nimport TextControl from \"sap/m/Text\";\n\nexport class BarcodeScannerPlugin extends BasePlugin {\n private inputControl!: Input;\n\n /**\n * Renders a `BarcodeScannerButton` alongside an `Input`.\n * \n * @param metadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured HBox control.\n */\n public render(metadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = metadata;\n this.fieldKey = bindingPath.replace('/', '');\n this.modelName = modelName;\n\n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`\n });\n this.applyCommonDirectives(this.control, metadata, modelName);\n return this.control as Control;\n }\n\n this.inputControl = new Input({\n id: this.generateStableId(engineScopeId, bindingPath + \"-input\"),\n value: `{${modelName}>${bindingPath}}`,\n editable: !metadata.ui?.readOnly,\n width: \"100%\",\n change: () => {\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n \n const scannerBtn = new BarcodeScannerButton({\n id: this.generateStableId(engineScopeId, bindingPath + \"-btn\"),\n scanSuccess: (oEvent: sap.ui.base.Event) => {\n const text = oEvent.getParameter(\"text\") as string;\n if (text) {\n this.inputControl.setValue(text);\n // UI5's two-way data binding on the input will sync the model automatically\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n }\n });\n\n this.control = new HBox({\n id: this.generateStableId(engineScopeId, bindingPath),\n items: [this.inputControl, scannerBtn],\n width: \"100%\"\n }).addStyleClass(\"sapUiSmallMarginBottom\");\n\n this.applyCommonDirectives(this.control, metadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current scanned text.\n * @returns {unknown} The barcode string.\n */\n protected getValue(): unknown {\n return this.inputControl ? this.inputControl.getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.inputControl && this.metadata) {\n if (!this.isEditable) return;\n this.inputControl.setEditable(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,8NAASA,EAAUC,EAAA,cASZ,MAAMC,UAA6BF,EAa/BG,OAAOC,EAA8BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAClHC,KAAKD,SAAWA,EAChBC,KAAKL,SAAWA,EAChBK,KAAKC,SAAWL,EAAYM,QAAQ,IAAK,IACzCF,KAAKH,UAAYA,EAEjB,IAAKG,KAAKG,WAAY,CAElBH,KAAKI,QAAU,IAAIC,EAAY,CAC3BC,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCY,KAAM,IAAIX,KAAaD,OAE3BI,KAAKS,sBAAsBT,KAAKI,QAAST,EAAUE,GACnD,OAAOG,KAAKI,OAChB,CAEAJ,KAAKU,aAAe,IAAIC,EAAM,CAC1BL,GAAIN,KAAKO,iBAAiBT,EAAeF,EAAc,UACvDgB,MAAO,IAAIf,KAAaD,KACxBiB,UAAWlB,EAASmB,IAAIC,SACxBC,MAAO,OACPC,OAAQA,KACJ,MAAMC,EAASlB,KAAKmB,8BACpB,GAAInB,KAAKD,SAAU,CACfC,KAAKD,SAASmB,EAAOE,QAASpB,KAAKC,SACvC,KAIR,MAAMoB,EAAa,IAAIC,EAAqB,CACxChB,GAAIN,KAAKO,iBAAiBT,EAAeF,EAAc,QACvD2B,YAAcC,IACV,MAAMhB,EAAOgB,EAAOC,aAAa,QACjC,GAAIjB,EAAM,CACNR,KAAKU,aAAagB,SAASlB,GAE3B,MAAMU,EAASlB,KAAKmB,8BACpB,GAAInB,KAAKD,SAAU,CACfC,KAAKD,SAASmB,EAAOE,QAASpB,KAAKC,SACvC,CACJ,KAIRD,KAAKI,QAAU,IAAIuB,EAAK,CACpBrB,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCgC,MAAO,CAAC5B,KAAKU,aAAcW,GAC3BL,MAAO,SACRa,cAAc,0BAEjB7B,KAAKS,sBAAsBT,KAAKI,QAAST,EAAUE,GAEnD,OAAOG,KAAKI,OAChB,CAMU0B,WACN,OAAO9B,KAAKU,aAAeV,KAAKU,aAAaoB,WAAa,IAC9D,CAKUC,aACN,GAAI/B,KAAKU,cAAgBV,KAAKL,SAAU,CACpC,IAAKK,KAAKG,WAAY,OACtBH,KAAKU,aAAasB,aAAahC,KAAKL,SAASmB,IAAIC,SACrD,CACJ,EACH,IAAAkB,EAAA,CAAAC,WAAA,MAAAD,EAAAxC,uBAAA,OAAAwC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":33,"column":0},"map":{"version":3,"names":["GlobalPipeline","____core_PipelineManager","BasePlugin","control","metadata","fieldKey","modelName","isEditable","useMessageManager","setEditable","editable","this","setUseMessageManager","generateStableId","engineScopeId","bindingPath","undefined","safePath","replace","validate","isValid","getVisible","validatorsToRun","argsMap","maxLength","required","push","minLength","pattern","minimum","maximum","min","max","format","ui","validators","v","name","args","length","errorMessage","val","getValue","result","executeValidation","setVisualValidationState","__ui5_require_async","then","m","Logger","error","setValueState","coreLibrary","ValueState","None","Error","setValueStateText","validateAndApplyVisualState","onStateChange","newMetadata","applyState","applyCommonDirectives","readOnly","visibleOn","ExpressionBuilder","sap","require","expr","build","bindProperty","parts","path","formatter","enabledOn","setEnabled","destroy","__exports","__esModule"],"sources":["BasePlugin.ts"],"sourcesContent":["/**\n * @file BasePlugin.ts\n * @description Abstract foundation for all MetaUI plugins, enforcing lifecycle hooks for v2 Schema.\n */\n\nimport { IPlugin } from \"../../interfaces/IPlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport { GlobalPipeline } from \"../../core/PipelineManager\";\nimport coreLibrary from \"sap/ui/core/library\";\n\n/**\n * Abstract class representing a standard MetaUI Plugin.\n * Enforces the required rendering, state extraction, and validation contracts.\n * \n * @abstract\n * @public\n */\nexport abstract class BasePlugin implements IPlugin {\n /** The instantiated UI5 control for this plugin. */\n protected control: Control | null = null;\n\n /** The metadata schema defining the field rules. */\n protected metadata: IPropertyMetadata | null = null;\n\n /** The internal JSON path of the field relative to its parent payload. */\n protected fieldKey: string = \"\";\n\n /** The UI5 JSONModel name used for absolute binding paths. */\n protected modelName: string = \"meta\";\n\n /** Indicates if the engine is enforcing an editable mode. */\n protected isEditable: boolean = true;\n\n /** Indicates if the plugin should delegate visual validation to the MessageManager. */\n protected useMessageManager: boolean = false;\n\n /** Internal callback provided by GeneratorHost to signal validation/data changes upwards */\n protected onChange?: (isValid: boolean, fieldKey?: string, errorMessage?: string, controlId?: string) => void;\n\n /**\n * Injects the global editable mode context into the plugin before rendering.\n * @param editable True if the plugin should render in editable mode.\n */\n public setEditable(editable: boolean): void {\n this.isEditable = editable;\n }\n\n /**\n * Injects the global MessageManager context into the plugin.\n * @param useMessageManager True if the MessageManager is handling validation visual states.\n */\n public setUseMessageManager(useMessageManager: boolean): void {\n this.useMessageManager = useMessageManager;\n }\n\n /**\n * Instantiates the raw UI5 control and binds it to the model.\n * \n * @param fieldMetadata The JSON Schema for the field.\n * @param bindingPath The JSON path to bind to.\n * @param modelName The UI5 model name.\n * @param engineScopeId The deterministic scope ID provided by the Engine to prevent cloning collisions.\n * @param onChange The callback fired natively when a field value blur/change occurs.\n * @returns {Control} The generated UI5 control.\n */\n public abstract render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName?: string, engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control;\n\n /**\n * Generates a deterministic, globally unique ID for this control.\n * Prefixes the sanitized binding path with the Engine's scoped ID.\n */\n protected generateStableId(engineScopeId: string | undefined, bindingPath: string): string | undefined {\n if (!engineScopeId) return undefined;\n // Strip leading slash and replace internal slashes with hyphens\n const safePath = bindingPath.replace(/^\\//, '').replace(/\\//g, '-');\n return `${engineScopeId}--${safePath}`;\n }\n\n /**\n * Extracts the current raw value from the underlying UI5 control.\n */\n protected abstract getValue(): unknown;\n\n /**\n * Universal pipeline validation.\n */\n public validate(): import(\"../../interfaces/IPlugin\").IPluginValidationResult {\n if (!this.control || !this.metadata) return { isValid: true };\n\n // Skip validation for hidden fields (e.g. hidden by ConditionEngine visibleOn)\n if (typeof (this.control as Control).getVisible === \"function\") {\n if (!(this.control as Control).getVisible()) {\n return { isValid: true };\n }\n }\n\n const validatorsToRun: string[] = [];\n const argsMap: Record<string, unknown> = {\n \"maxLength\": this.metadata.maxLength\n };\n\n if (this.metadata.required) {\n validatorsToRun.push(\"required\");\n }\n if (this.metadata.maxLength) validatorsToRun.push(\"maxLength\");\n if (this.metadata.minLength) {\n validatorsToRun.push(\"minLength\");\n argsMap[\"minLength\"] = this.metadata.minLength;\n }\n if (this.metadata.pattern) {\n validatorsToRun.push(\"pattern\");\n argsMap[\"pattern\"] = this.metadata.pattern;\n }\n if (this.metadata.minimum !== undefined || this.metadata.maximum !== undefined) {\n validatorsToRun.push(\"range\");\n argsMap[\"range\"] = { min: this.metadata.minimum, max: this.metadata.maximum };\n }\n \n const format = this.metadata.ui?.format;\n if (format === \"email\" || format === \"url\" || format === \"iban\") {\n validatorsToRun.push(format);\n }\n\n if (this.metadata.ui?.validators) {\n for (const v of this.metadata.ui.validators) {\n if (typeof v === \"string\") {\n validatorsToRun.push(v);\n } else if (v && v.name) {\n validatorsToRun.push(v.name);\n if (v.args !== undefined) {\n argsMap[v.name] = v.args;\n }\n }\n }\n }\n\n if (validatorsToRun.length === 0) {\n return { isValid: true, errorMessage: undefined, fieldKey: this.fieldKey };\n }\n\n const val = this.getValue();\n const result = GlobalPipeline.executeValidation(val, validatorsToRun, argsMap);\n return { isValid: result.isValid, errorMessage: result.errorMessage, fieldKey: this.fieldKey };\n }\n\n /**\n * Natively manipulates the UI5 control's valueState if the control supports it.\n * Uses reflection to safely apply styles without crashing on structural controls.\n */\n public setVisualValidationState(isValid: boolean, errorMessage?: string): void {\n if (!this.control) return;\n\n import(\"../../utils/Logger\").then(m => m.Logger.error(\"[MetaUI]\", `setVisualValidationState called on plugin: ${this.fieldKey}, isValid: ${isValid}`, \"BasePlugin\"));\n\n // Use reflection to check if the control supports ValueState (e.g. sap.m.Input does, sap.m.Text does not)\n if (typeof (this.control as any).setValueState === \"function\") {\n (this.control as any).setValueState(isValid ? coreLibrary.ValueState.None : coreLibrary.ValueState.Error);\n \n if (typeof (this.control as any).setValueStateText === \"function\") {\n (this.control as any).setValueStateText(isValid ? \"\" : (errorMessage || \"\"));\n }\n } else {\n import(\"../../utils/Logger\").then(m => m.Logger.error(\"[MetaUI]\", `Plugin ${this.fieldKey} has no setValueState function!`, \"BasePlugin\"));\n }\n }\n\n /**\n * Wraps standard validation and immediately applies the visual state.\n * Ideal for 'change' events to instantly turn fields red on blur.\n */\n protected validateAndApplyVisualState(): import(\"../../interfaces/IPlugin\").IPluginValidationResult {\n const result = this.validate();\n this.setVisualValidationState(result.isValid, result.errorMessage);\n return result;\n }\n\n /**\n * Executes when the condition engine pushes new schema metadata to this field (e.g. readOnly changing).\n * @param newMetadata The mutated schema metadata.\n */\n public onStateChange(newMetadata: IPropertyMetadata): void {\n this.metadata = newMetadata;\n this.applyState();\n }\n\n /**\n * Abstract hook for the plugin to apply state changes to its specific UI5 control (e.g. placeholders, labels).\n */\n protected abstract applyState(): void;\n\n /**\n * Helper to apply common UI directives (like readOnly, visibleOn) directly to any control.\n */\n protected applyCommonDirectives(control: Control, metadata: IPropertyMetadata, modelName: string = \"meta\"): void {\n if (metadata.ui?.readOnly !== undefined && typeof control.setEditable === \"function\") {\n control.setEditable(!metadata.ui.readOnly);\n }\n\n if (metadata.ui?.visibleOn) {\n const ExpressionBuilder = sap.ui.require(\"nz/co/siliconst/ui5/metaui/utils/ExpressionBuilder\")?.ExpressionBuilder;\n let expr = \"\";\n if (ExpressionBuilder) {\n expr = ExpressionBuilder.build(metadata.ui.visibleOn, this.fieldKey, modelName);\n } else {\n expr = `{= ${metadata.ui.visibleOn.replace(/\\$root\\./g, `${modelName}>/`).replace(/\\./g, '/')} }`;\n }\n control.bindProperty(\"visible\", { parts: [{ path: \"meta>/\" }], formatter: () => false });\n control.bindProperty(\"visible\", expr);\n }\n\n if (metadata.ui?.enabledOn && typeof control.setEnabled === \"function\") {\n const ExpressionBuilder = sap.ui.require(\"nz/co/siliconst/ui5/metaui/utils/ExpressionBuilder\")?.ExpressionBuilder;\n let expr = \"\";\n if (ExpressionBuilder) {\n expr = ExpressionBuilder.build(metadata.ui.enabledOn, this.fieldKey, modelName);\n } else {\n expr = `{= ${metadata.ui.enabledOn.replace(/\\$root\\./g, `${modelName}>/`).replace(/\\./g, '/')} }`;\n }\n control.bindProperty(\"enabled\", expr);\n }\n }\n\n\n\n /**\n * Natively destroys the instantiated UI5 control to prevent memory leaks.\n * Can be overridden by subclasses if they manage secondary controls or custom models.\n */\n public destroy(): void {\n if (this.control && typeof this.control.destroy === \"function\") {\n this.control.destroy();\n this.control = null;\n }\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":34,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","BooleanPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","isEditable","control","TextControl","id","generateStableId","text","path","formatter","val","applyCommonDirectives","CheckBox","selected","enabled","ui","readOnly","select","oEvent","getParameter","result","validateAndApplyVisualState","isValid","fieldKey","getValue","getSelected","applyState","setEnabled","__exports","__esModule"],"sources":["BooleanPlugin.ts"],"sourcesContent":["/**\n * @file BooleanPlugin.ts\n * @description Renders a sap.m.Switch for boolean states.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport CheckBox from \"sap/m/CheckBox\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering logic for toggleable booleans using `sap.m.CheckBox`.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class BooleanPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.CheckBox` component for boolean evaluation.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @returns {Control} The configured CheckBox control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n \n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n formatter: (val: boolean) => val ? \"Yes\" : \"No\"\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new CheckBox({\n id: this.generateStableId(engineScopeId, bindingPath),\n selected: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n select: (oEvent: sap.ui.base.Event) => {\n const val = oEvent.getParameter(\"selected\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current boolean state.\n * @returns {boolean} The selected state.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as CheckBox).getSelected() : false;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as CheckBox).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,0JAAA,MAKSA,EAAUC,EAAA,cAYZ,MAAMC,UAAsBF,EASxBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAEhB,IAAKK,KAAKE,WAAY,CAElBF,KAAKG,QAAU,IAAIC,EAAY,CAC3BC,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCW,KAAM,CACFC,KAAM,GAAGX,KAAaD,IACtBa,UAAYC,GAAiBA,EAAM,MAAQ,QAGnDV,KAAKW,sBAAsBX,KAAKG,QAASR,EAAeE,GACxD,OAAOG,KAAKG,OAChB,CAEAH,KAAKG,QAAU,IAAIS,EAAS,CACxBP,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCiB,SAAU,IAAIhB,KAAaD,KAC3BkB,SAAUnB,EAAcoB,IAAIC,SAC5BC,OAASC,IACL,MAAMR,EAAMQ,EAAOC,aAAa,YAChC,MAAMC,EAASpB,KAAKqB,8BACpB,GAAIrB,KAAKD,SAAU,CACfC,KAAKD,SAASqB,EAAOE,QAAStB,KAAKuB,SACvC,KAIRvB,KAAKW,sBAAsBX,KAAKG,QAASR,EAAeE,GAExD,OAAOG,KAAKG,OAChB,CAMUqB,WACN,OAAOxB,KAAKG,QAAWH,KAAKG,QAAqBsB,cAAgB,KACrE,CAKUC,aACN,GAAI1B,KAAKG,SAAWH,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACrBF,KAAKG,QAAqBwB,YAAY3B,KAAKC,SAASc,IAAIC,SAC7D,CACJ,EACH,IAAAY,EAAA,CAAAC,WAAA,MAAAD,EAAAnC,gBAAA,OAAAmC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":35,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","CameraControl","_interopRequireDefault","__CameraControl","CameraPlugin","render","metadata","bindingPath","modelName","engineScopeId","onChange","this","fieldKey","replace","isEditable","control","ImageControl","id","generateStableId","src","width","alt","ui","label","applyCommonDirectives","value","schemaMetadata","readOnly","attachCapture","result","validateAndApplyVisualState","isValid","getValue","applyState","setProperty","__exports","__esModule"],"sources":["CameraPlugin.ts"],"sourcesContent":["import { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport CameraControl from \"../../controls/CameraControl\";\nimport ImageControl from \"sap/m/Image\";\n\nexport class CameraPlugin extends BasePlugin {\n /**\n * Renders a `CameraControl` component.\n * \n * @param metadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured CameraControl.\n */\n public render(metadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = metadata;\n this.fieldKey = bindingPath.replace('/', '');\n this.modelName = modelName;\n\n if (!this.isEditable) {\n \n this.control = new ImageControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n src: `{${modelName}>${bindingPath}}`,\n width: \"400px\",\n alt: metadata.ui?.label || \"Image\"\n });\n this.applyCommonDirectives(this.control, metadata, modelName);\n return this.control as Control;\n }\n\n this.control = new CameraControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n schemaMetadata: metadata,\n readOnly: !!metadata.ui?.readOnly\n });\n\n this.applyCommonDirectives(this.control, metadata, modelName);\n\n // Validation mapping could be hooked into the 'capture' event if needed, but Two-Way binding updates the model naturally.\n (this.control as CameraControl).attachCapture(() => {\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n });\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current base64 image state.\n * @returns {unknown} The image value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as CameraControl).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as sap.ui.core.Control).setProperty(\"readOnly\", !!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,yQAASA,EAAUC,EAAA,oBAGZC,EAAaC,EAAAC,GAGb,MAAMC,UAAqBL,EAWvBM,OAAOC,EAA8BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAClHC,KAAKD,SAAWA,EAChBC,KAAKL,SAAWA,EAChBK,KAAKC,SAAWL,EAAYM,QAAQ,IAAK,IACzCF,KAAKH,UAAYA,EAEjB,IAAKG,KAAKG,WAAY,CAElBH,KAAKI,QAAU,IAAIC,EAAa,CAC5BC,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCY,IAAK,IAAIX,KAAaD,KACtBa,MAAO,QACPC,IAAKf,EAASgB,IAAIC,OAAS,UAE/BZ,KAAKa,sBAAsBb,KAAKI,QAAST,EAAUE,GACnD,OAAOG,KAAKI,OAChB,CAEAJ,KAAKI,QAAU,IAAId,EAAc,CAC7BgB,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCkB,MAAO,IAAIjB,KAAaD,KACxBmB,eAAgBpB,EAChBqB,WAAYrB,EAASgB,IAAIK,WAG7BhB,KAAKa,sBAAsBb,KAAKI,QAAST,EAAUE,GAGlDG,KAAKI,QAA0Ba,cAAc,KAC1C,MAAMC,EAASlB,KAAKmB,8BAChB,GAAInB,KAAKD,SAAU,CACfC,KAAKD,SAASmB,EAAOE,QAASpB,KAAKC,SACvC,IAGR,OAAOD,KAAKI,OAChB,CAMUiB,WACN,OAAOrB,KAAKI,QAAWJ,KAAKI,QAA0BiB,WAAa,IACvE,CAKUC,aACN,GAAItB,KAAKI,SAAWJ,KAAKL,SAAU,CAC/B,IAAKK,KAAKG,WAAY,OACrBH,KAAKI,QAAgCmB,YAAY,aAAcvB,KAAKL,SAASgB,IAAIK,SACtF,CACJ,EACH,IAAAQ,EAAA,CAAAC,WAAA,MAAAD,EAAA/B,eAAA,OAAA+B,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":36,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","CodeEditorPlugin","detectLanguage","value","trimmed","trim","startsWith","JSON","parse","e","test","adjustHeight","this","control","val","getValue","lines","split","length","newHeight","Math","max","setHeight","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","metadata","fieldKey","replace","CodeEditor","id","generateStableId","type","ui","args","editable","isEditable","readOnly","height","width","change","result","validateAndApplyVisualState","isValid","currentVal","detectedType","getType","setType","attachEventOnce","oBinding","getBinding","initLogic","applyState","attachChange","applyCommonDirectives","setEditable","__exports","__esModule"],"sources":["CodeEditorPlugin.ts"],"sourcesContent":["/**\n * @file CodeEditorPlugin.ts\n * @description Renders a sap.ui.codeeditor.CodeEditor for editing source code/JSON.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport CodeEditor from \"sap/ui/codeeditor/CodeEditor\";\n\n/**\n * Handles rendering logic for code editing.\n * Requires the `sap.ui.codeeditor` library to be loaded.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class CodeEditorPlugin extends BasePlugin {\n /**\n * Infers the language type from the content.\n * @param value The raw string.\n * @returns The language string.\n */\n private detectLanguage(value: string): string {\n if (!value || typeof value !== \"string\") return \"javascript\";\n \n const trimmed = value.trim();\n if (trimmed === \"\") return \"javascript\";\n\n // 1. JSON\n if (trimmed.startsWith(\"{\") || trimmed.startsWith(\"[\")) {\n try {\n JSON.parse(trimmed);\n return \"json\";\n } catch (e) {\n // Not valid JSON, continue testing\n }\n }\n\n // 2. XML / HTML\n if (/^\\s*<[\\s\\S]*>\\s*$/.test(trimmed)) {\n return \"xml\";\n }\n\n // 3. Fallback to JavaScript\n return \"javascript\";\n }\n\n /**\n * Dynamically adjusts the height of the editor based on content lines.\n */\n private adjustHeight(): void {\n if (!this.control) return;\n const val = (this.control as CodeEditor).getValue() || \"\";\n const lines = val.split(/\\r\\n|\\r|\\n/).length;\n // 18px per line + 20px padding, minimum 100px\n const newHeight = Math.max(100, (lines * 18) + 20);\n (this.control as CodeEditor).setHeight(newHeight + \"px\");\n }\n\n /**\n * Renders a `sap.ui.codeeditor.CodeEditor` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured CodeEditor control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.replace(\"/\", \"\"); // For EventBus\n \n \n \n this.control = new CodeEditor({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n type: fieldMetadata.ui?.args || \"javascript\", // will be dynamically overridden if args is missing\n editable: !this.isEditable ? false : !fieldMetadata.ui?.readOnly,\n height: \"100px\", // Initial minimum height\n width: \"100%\",\n change: () => {\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n \n // If language isn't explicitly defined, try to guess it dynamically\n if (!fieldMetadata.ui?.args) {\n const currentVal = (this.control as CodeEditor).getValue();\n const detectedType = this.detectLanguage(currentVal);\n if ((this.control as CodeEditor).getType() !== detectedType) {\n (this.control as CodeEditor).setType(detectedType);\n }\n }\n \n this.adjustHeight();\n }\n });\n\n // Clean architecture: Wait for the model context, then attach safely to the binding itself.\n // No timeouts, no DOM hacks, pure UI5 Eventing.\n (this.control as CodeEditor).attachEventOnce(\"modelContextChange\", () => {\n const oBinding = (this.control as CodeEditor).getBinding(\"value\");\n \n const initLogic = () => {\n if (this.control) {\n const currentVal = (this.control as CodeEditor).getValue();\n if (!fieldMetadata.ui?.args) {\n (this.control as CodeEditor).setType(this.detectLanguage(currentVal));\n }\n this.adjustHeight();\n // CRITICAL: Ace Editor sometimes loses its constructor `editable` flag \n // when the model asynchronously injects a new value string. \n // We must forcefully re-apply the correct state after binding.\n this.applyState();\n }\n };\n\n if (oBinding) {\n // Attach for future model changes\n oBinding.attachChange(initLogic);\n }\n \n // Execute immediately in case the model is synchronous (JSONModel)\n initLogic();\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current code string.\n * @returns {unknown} The code value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as CodeEditor).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) {\n (this.control as CodeEditor).setEditable(false);\n } else {\n (this.control as CodeEditor).setEditable(!this.metadata.ui?.readOnly);\n }\n }\n }\n}\n"],"mappings":"AAAA,4JAAA,MAKSA,EAAUC,EAAA,cAYZ,MAAMC,UAAyBF,EAM1BG,eAAeC,GACnB,IAAKA,UAAgBA,IAAU,SAAU,MAAO,aAEhD,MAAMC,EAAUD,EAAME,OACtB,GAAID,IAAY,GAAI,MAAO,aAG3B,GAAIA,EAAQE,WAAW,MAAQF,EAAQE,WAAW,KAAM,CACpD,IACIC,KAAKC,MAAMJ,GACX,MAAO,MACX,CAAE,MAAOK,GACL,CAER,CAGA,GAAI,oBAAoBC,KAAKN,GAAU,CACnC,MAAO,KACX,CAGA,MAAO,YACX,CAKQO,eACJ,IAAKC,KAAKC,QAAS,OACnB,MAAMC,EAAOF,KAAKC,QAAuBE,YAAc,GACvD,MAAMC,EAAQF,EAAIG,MAAM,cAAcC,OAEtC,MAAMC,EAAYC,KAAKC,IAAI,IAAML,EAAQ,GAAM,IAC9CJ,KAAKC,QAAuBS,UAAUH,EAAY,KACvD,CAYOI,OAAOC,EAAkCC,EAAqBC,EAAoB,OAAQC,EAAwBC,GACrHhB,KAAKgB,SAAWA,EAChBhB,KAAKiB,SAAWL,EAChBZ,KAAKkB,SAAWL,EAAYM,QAAQ,IAAK,IAIzCnB,KAAKC,QAAU,IAAImB,EAAW,CAC1BC,GAAIrB,KAAKsB,iBAAiBP,EAAeF,GACzCtB,MAAO,IAAIuB,KAAaD,KACxBU,KAAMX,EAAcY,IAAIC,MAAQ,aAChCC,UAAW1B,KAAK2B,WAAa,OAASf,EAAcY,IAAII,SACxDC,OAAQ,QACRC,MAAO,OACPC,OAAQA,KACJ,MAAMC,EAAShC,KAAKiC,8BACpB,GAAIjC,KAAKgB,SAAU,CACfhB,KAAKgB,SAASgB,EAAOE,QAASlC,KAAKkB,SACvC,CAGA,IAAKN,EAAcY,IAAIC,KAAM,CACzB,MAAMU,EAAcnC,KAAKC,QAAuBE,WAChD,MAAMiC,EAAepC,KAAKV,eAAe6C,GACzC,GAAKnC,KAAKC,QAAuBoC,YAAcD,EAAc,CACxDpC,KAAKC,QAAuBqC,QAAQF,EACzC,CACJ,CAEApC,KAAKD,kBAMZC,KAAKC,QAAuBsC,gBAAgB,qBAAsB,KAC/D,MAAMC,EAAYxC,KAAKC,QAAuBwC,WAAW,SAEzD,MAAMC,EAAYA,KACd,GAAI1C,KAAKC,QAAS,CACd,MAAMkC,EAAcnC,KAAKC,QAAuBE,WAChD,IAAKS,EAAcY,IAAIC,KAAM,CACxBzB,KAAKC,QAAuBqC,QAAQtC,KAAKV,eAAe6C,GAC7D,CACAnC,KAAKD,eAILC,KAAK2C,YACT,GAGJ,GAAIH,EAAU,CAEVA,EAASI,aAAaF,EAC1B,CAGAA,MAGJ1C,KAAK6C,sBAAsB7C,KAAKC,QAASW,EAAeE,GAExD,OAAOd,KAAKC,OAChB,CAMUE,WACN,OAAOH,KAAKC,QAAWD,KAAKC,QAAuBE,WAAa,IACpE,CAKUwC,aACN,GAAI3C,KAAKC,SAAWD,KAAKiB,SAAU,CAC/B,IAAKjB,KAAK2B,WAAY,CACjB3B,KAAKC,QAAuB6C,YAAY,MAC7C,KAAO,CACF9C,KAAKC,QAAuB6C,aAAa9C,KAAKiB,SAASO,IAAII,SAChE,CACJ,CACJ,EACH,IAAAmB,EAAA,CAAAC,WAAA,MAAAD,EAAA1D,mBAAA,OAAA0D,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":37,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","DatePlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","isEditable","control","TextControl","id","generateStableId","text","path","type","formatOptions","source","pattern","applyCommonDirectives","DatePicker","value","displayFormat","editable","ui","readOnly","required","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","fieldKey","getValue","applyState","dp","setEditable","setRequired","__exports","__esModule"],"sources":["DatePlugin.ts"],"sourcesContent":["/**\n * @file DatePlugin.ts\n * @description Renders a sap.m.DatePicker natively bound to ISO date strings.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport DatePicker from \"sap/m/DatePicker\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering logic for Date strings.\n */\nexport class DatePlugin extends BasePlugin {\n /**\n * Renders a `sap.m.DatePicker` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured DatePicker control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n \n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n type: \"sap.ui.model.type.Date\",\n formatOptions: {\n source: { pattern: \"yyyy-MM-dd\" },\n pattern: \"yyyy-MM-dd\"\n }\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new DatePicker({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: {\n path: `${modelName}>${bindingPath}`,\n type: \"sap.ui.model.type.Date\",\n formatOptions: {\n source: { pattern: \"yyyy-MM-dd\" },\n pattern: \"yyyy-MM-dd\"\n }\n },\n displayFormat: \"long\",\n editable: !fieldMetadata.ui?.readOnly,\n required: fieldMetadata.required,\n change: (oEvent: sap.ui.base.Event) => {\n const val = oEvent.getParameter(\"value\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current date string.\n * @returns {unknown} The date value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as DatePicker).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const dp = this.control as DatePicker;\n dp.setEditable(!this.metadata.ui?.readOnly);\n dp.setRequired(this.metadata.required);\n }\n }\n}\n"],"mappings":"AAAA,yJAAA,MAKSA,EAAUC,EAAA,cASZ,MAAMC,UAAmBF,EAWrBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAEhB,IAAKK,KAAKE,WAAY,CAElBF,KAAKG,QAAU,IAAIC,EAAY,CAC3BC,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCW,KAAM,CACFC,KAAM,GAAGX,KAAaD,IACtBa,KAAM,yBACNC,cAAe,CACXC,OAAQ,CAAEC,QAAS,cACnBA,QAAS,iBAIrBZ,KAAKa,sBAAsBb,KAAKG,QAASR,EAAeE,GACxD,OAAOG,KAAKG,OAChB,CAEAH,KAAKG,QAAU,IAAIW,EAAW,CAC1BT,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCmB,MAAO,CACHP,KAAM,GAAGX,KAAaD,IACtBa,KAAM,yBACNC,cAAe,CACXC,OAAQ,CAAEC,QAAS,cACnBA,QAAS,eAGjBI,cAAe,OACfC,UAAWtB,EAAcuB,IAAIC,SAC7BC,SAAUzB,EAAcyB,SACxBC,OAASC,IACL,MAAMC,EAAMD,EAAOE,aAAa,SAChC,MAAMC,EAASzB,KAAK0B,8BACpB,GAAI1B,KAAKD,SAAU,CACfC,KAAKD,SAAS0B,EAAOE,QAAS3B,KAAK4B,SACvC,KAIR,OAAO5B,KAAKG,OAChB,CAMU0B,WACN,OAAO7B,KAAKG,QAAWH,KAAKG,QAAuB0B,WAAa,IACpE,CAKUC,aACN,GAAI9B,KAAKG,SAAWH,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACtB,MAAM6B,EAAK/B,KAAKG,QAChB4B,EAAGC,aAAahC,KAAKC,SAASiB,IAAIC,UAClCY,EAAGE,YAAYjC,KAAKC,SAASmB,SACjC,CACJ,EACH,IAAAc,EAAA,CAAAC,WAAA,MAAAD,EAAAzC,aAAA,OAAAyC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":38,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","DateTimePlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","isEditable","control","TextControl","id","generateStableId","text","path","type","formatOptions","source","pattern","applyCommonDirectives","DateTimePicker","value","editable","ui","readOnly","required","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","fieldKey","getValue","applyState","input","setEditable","setRequired","__exports","__esModule"],"sources":["DateTimePlugin.ts"],"sourcesContent":["/**\n * @file DateTimePlugin.ts\n * @description Handles rendering logic for DateTime strings (timestamps).\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport DateTimePicker from \"sap/m/DateTimePicker\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering and logic for timestamps/datetime inputs.\n */\nexport class DateTimePlugin extends BasePlugin {\n /**\n * Renders a `sap.m.DateTimePicker` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured DateTimePicker control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n \n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n type: \"sap.ui.model.type.DateTime\",\n formatOptions: {\n source: { pattern: \"yyyy-MM-dd'T'HH:mm:ss'Z'\" },\n pattern: \"yyyy-MM-dd'T'HH:mm:ss'Z'\"\n }\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new DateTimePicker({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: {\n path: `${modelName}>${bindingPath}`,\n type: \"sap.ui.model.type.DateTime\",\n formatOptions: {\n source: { pattern: \"yyyy-MM-dd'T'HH:mm:ss'Z'\" },\n pattern: \"yyyy-MM-dd'T'HH:mm:ss'Z'\"\n }\n },\n editable: !fieldMetadata.ui?.readOnly,\n required: fieldMetadata.required,\n change: (oEvent: sap.ui.base.Event) => {\n const val = oEvent.getParameter(\"value\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current datetime string.\n * @returns {unknown} The datetime value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as DateTimePicker).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const input = this.control as DateTimePicker;\n input.setEditable(!this.metadata.ui?.readOnly);\n input.setRequired(this.metadata.required);\n }\n }\n}\n"],"mappings":"AAAA,iKAAA,MAKSA,EAAUC,EAAA,cASZ,MAAMC,UAAuBF,EAWzBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAEhB,IAAKK,KAAKE,WAAY,CAElBF,KAAKG,QAAU,IAAIC,EAAY,CAC3BC,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCW,KAAM,CACFC,KAAM,GAAGX,KAAaD,IACtBa,KAAM,6BACNC,cAAe,CACXC,OAAQ,CAAEC,QAAS,4BACnBA,QAAS,+BAIrBZ,KAAKa,sBAAsBb,KAAKG,QAASR,EAAeE,GACxD,OAAOG,KAAKG,OAChB,CAEAH,KAAKG,QAAU,IAAIW,EAAe,CAC9BT,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCmB,MAAO,CACHP,KAAM,GAAGX,KAAaD,IACtBa,KAAM,6BACNC,cAAe,CACXC,OAAQ,CAAEC,QAAS,4BACnBA,QAAS,6BAGjBI,UAAWrB,EAAcsB,IAAIC,SAC7BC,SAAUxB,EAAcwB,SACxBC,OAASC,IACL,MAAMC,EAAMD,EAAOE,aAAa,SAChC,MAAMC,EAASxB,KAAKyB,8BACpB,GAAIzB,KAAKD,SAAU,CACfC,KAAKD,SAASyB,EAAOE,QAAS1B,KAAK2B,SACvC,KAIR3B,KAAKa,sBAAsBb,KAAKG,QAASR,EAAeE,GAExD,OAAOG,KAAKG,OAChB,CAMUyB,WACN,OAAO5B,KAAKG,QAAWH,KAAKG,QAA2ByB,WAAa,IACxE,CAKUC,aACN,GAAI7B,KAAKG,SAAWH,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACtB,MAAM4B,EAAQ9B,KAAKG,QACnB2B,EAAMC,aAAa/B,KAAKC,SAASgB,IAAIC,UACrCY,EAAME,YAAYhC,KAAKC,SAASkB,SACpC,CACJ,EACH,IAAAc,EAAA,CAAAC,WAAA,MAAAD,EAAAxC,iBAAA,OAAAwC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":39,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","DropdownPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","isEditable","valueHelpArray","valueHelp","Array","isArray","enum","map","e","key","String","text","control","TextControl","id","generateStableId","path","formatter","match","find","vh","applyCommonDirectives","select","Select","selectedKey","enabled","ui","readOnly","forceSelection","change","oEvent","item","getParameter","val","getKey","result","validateAndApplyVisualState","isValid","fieldKey","length","addItem","Item","forEach","getValue","getSelectedKey","applyState","setEnabled","__exports","__esModule"],"sources":["DropdownPlugin.ts"],"sourcesContent":["/**\n * @file DropdownPlugin.ts\n * @description Renders a sap.m.Select utilizing the schema's valueHelp structure.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Select from \"sap/m/Select\";\nimport Item from \"sap/ui/core/Item\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering logic for dropdown inputs.\n * Maps the static `valueHelp` schema array to `sap.ui.core.Item` elements.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class DropdownPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.Select` component populated with schema-defined value help.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured Select control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n \n if (!this.isEditable) {\n \n \n const valueHelpArray = fieldMetadata.valueHelp && Array.isArray(fieldMetadata.valueHelp) \n ? fieldMetadata.valueHelp \n : (fieldMetadata.enum ? fieldMetadata.enum.map(e => ({ key: String(e), text: String(e) })) : []);\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n formatter: (key: string) => {\n const match = valueHelpArray.find(vh => vh.key === key);\n return match ? match.text : key;\n }\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n const select = new Select({\n id: this.generateStableId(engineScopeId, bindingPath),\n selectedKey: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n forceSelection: false,\n change: (oEvent: sap.ui.base.Event) => {\n const item = oEvent.getParameter(\"selectedItem\");\n const val = item ? item.getKey() : \"\";\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n const valueHelpArray = fieldMetadata.valueHelp && Array.isArray(fieldMetadata.valueHelp) \n ? fieldMetadata.valueHelp \n : (fieldMetadata.enum ? fieldMetadata.enum.map(e => ({ key: String(e), text: String(e) })) : []);\n\n if (valueHelpArray.length > 0) {\n // Always add the empty placeholder so that 'required' checks can actually fire if the user hasn't made a choice\n select.addItem(new Item({ key: \"\", text: \"--- Select ---\" }));\n \n valueHelpArray.forEach(vh => {\n select.addItem(new Item({ key: vh.key, text: vh.text }));\n });\n }\n\n this.control = select;\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n /**\n * Retrieves the currently selected key.\n * @returns {unknown} The selected key.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as Select).getSelectedKey() : null;\n }\n\n /**\n * Applies dynamic metadata state (e.g. readOnly) when the ConditionEngine fires.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const select = this.control as Select;\n select.setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,8KAAA,MAKSA,EAAUC,EAAA,cAcZ,MAAMC,UAAuBF,EAWzBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAEhB,IAAKK,KAAKE,WAAY,CAGlB,MAAMC,EAAiBR,EAAcS,WAAaC,MAAMC,QAAQX,EAAcS,WACxET,EAAcS,UACbT,EAAcY,KAAOZ,EAAcY,KAAKC,IAAIC,IAAC,CAAOC,IAAKC,OAAOF,GAAIG,KAAMD,OAAOF,MAAS,GAEjGT,KAAKa,QAAU,IAAIC,EAAY,CAC3BC,GAAIf,KAAKgB,iBAAiBlB,EAAeF,GACzCgB,KAAM,CACFK,KAAM,GAAGpB,KAAaD,IACtBsB,UAAYR,IACR,MAAMS,EAAQhB,EAAeiB,KAAKC,GAAMA,EAAGX,MAAQA,GACnD,OAAOS,EAAQA,EAAMP,KAAOF,MAIxCV,KAAKsB,sBAAsBtB,KAAKa,QAASlB,EAAeE,GACxD,OAAOG,KAAKa,OAChB,CAEA,MAAMU,EAAS,IAAIC,EAAO,CACtBT,GAAIf,KAAKgB,iBAAiBlB,EAAeF,GACzC6B,YAAa,IAAI5B,KAAaD,KAC9B8B,SAAU/B,EAAcgC,IAAIC,SAC5BC,eAAgB,MAChBC,OAASC,IACL,MAAMC,EAAOD,EAAOE,aAAa,gBACjC,MAAMC,EAAMF,EAAOA,EAAKG,SAAW,GACnC,MAAMC,EAASpC,KAAKqC,8BACpB,GAAIrC,KAAKD,SAAU,CACfC,KAAKD,SAASqC,EAAOE,QAAStC,KAAKuC,SACvC,KAIR,MAAMpC,EAAiBR,EAAcS,WAAaC,MAAMC,QAAQX,EAAcS,WACxET,EAAcS,UACbT,EAAcY,KAAOZ,EAAcY,KAAKC,IAAIC,IAAC,CAAOC,IAAKC,OAAOF,GAAIG,KAAMD,OAAOF,MAAS,GAEjG,GAAIN,EAAeqC,OAAS,EAAG,CAE3BjB,EAAOkB,QAAQ,IAAIC,EAAK,CAAEhC,IAAK,GAAIE,KAAM,oBAEzCT,EAAewC,QAAQtB,IACnBE,EAAOkB,QAAQ,IAAIC,EAAK,CAAEhC,IAAKW,EAAGX,IAAKE,KAAMS,EAAGT,SAExD,CAEAZ,KAAKa,QAAUU,EACfvB,KAAKsB,sBAAsBtB,KAAKa,QAASlB,EAAeE,GACxD,OAAOG,KAAKa,OAChB,CAMU+B,WACN,OAAO5C,KAAKa,QAAWb,KAAKa,QAAmBgC,iBAAmB,IACtE,CAKUC,aACN,GAAI9C,KAAKa,SAAWb,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACtB,MAAMqB,EAASvB,KAAKa,QACpBU,EAAOwB,YAAY/C,KAAKC,SAAS0B,IAAIC,SACzC,CACJ,EACH,IAAAoB,EAAA,CAAAC,WAAA,MAAAD,EAAAvD,iBAAA,OAAAuD,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":40,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","FileUploaderPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","isEditable","control","LinkControl","id","generateStableId","text","href","target","applyCommonDirectives","FileUploader","value","enabled","ui","readOnly","placeholder","label","width","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","fieldKey","getValue","applyState","setEnabled","__exports","__esModule"],"sources":["FileUploaderPlugin.ts"],"sourcesContent":["/**\n * @file FileUploaderPlugin.ts\n * @description Renders a sap.ui.unified.FileUploader.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport FileUploader from \"sap/ui/unified/FileUploader\";\nimport Control from \"sap/ui/core/Control\";\nimport LinkControl from \"sap/m/Link\";\n\n/**\n * Handles rendering logic for file uploads.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class FileUploaderPlugin extends BasePlugin {\n /**\n * Renders a `sap.ui.unified.FileUploader` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured FileUploader control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n \n if (!this.isEditable) {\n \n this.control = new LinkControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`,\n href: `{${modelName}>${bindingPath}}`, // Assuming the value is a URL to the file\n target: \"_blank\"\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new FileUploader({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n placeholder: fieldMetadata.ui?.label || \"Choose a file...\",\n width: \"100%\",\n change: (oEvent: sap.ui.base.Event) => {\n const val = oEvent.getParameter(\"newValue\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n /**\n * Retrieves the current file path.\n * @returns {unknown} The file value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as FileUploader).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as FileUploader).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,4KAAA,MAKSA,EAAUC,EAAA,cAYZ,MAAMC,UAA2BF,EAW7BG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAEhB,IAAKK,KAAKE,WAAY,CAElBF,KAAKG,QAAU,IAAIC,EAAY,CAC3BC,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCW,KAAM,IAAIV,KAAaD,KACvBY,KAAM,IAAIX,KAAaD,KACvBa,OAAQ,WAEZT,KAAKU,sBAAsBV,KAAKG,QAASR,EAAeE,GACxD,OAAOG,KAAKG,OAChB,CAEAH,KAAKG,QAAU,IAAIQ,EAAa,CAC5BN,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCgB,MAAO,IAAIf,KAAaD,KACxBiB,SAAUlB,EAAcmB,IAAIC,SAC5BC,YAAarB,EAAcmB,IAAIG,OAAS,mBACxCC,MAAO,OACPC,OAASC,IACL,MAAMC,EAAMD,EAAOE,aAAa,YAChC,MAAMC,EAASvB,KAAKwB,8BACpB,GAAIxB,KAAKD,SAAU,CACfC,KAAKD,SAASwB,EAAOE,QAASzB,KAAK0B,SACvC,KAIR1B,KAAKU,sBAAsBV,KAAKG,QAASR,EAAeE,GACxD,OAAOG,KAAKG,OAChB,CAMUwB,WACN,OAAO3B,KAAKG,QAAWH,KAAKG,QAAyBwB,WAAa,IACtE,CAKUC,aACN,GAAI5B,KAAKG,SAAWH,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACrBF,KAAKG,QAAyB0B,YAAY7B,KAAKC,SAASa,IAAIC,SACjE,CACJ,EACH,IAAAe,EAAA,CAAAC,WAAA,MAAAD,EAAArC,qBAAA,OAAAqC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":41,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","GeolocationControl","_interopRequireDefault","__GeolocationControl","GeolocationPlugin","render","metadata","bindingPath","modelName","engineScopeId","onChange","this","fieldKey","replace","isEditable","control","TextControl","id","generateStableId","text","path","formatter","val","lat","undefined","lng","applyCommonDirectives","value","schemaMetadata","readOnly","ui","attachCapture","result","validateAndApplyVisualState","isValid","getValue","applyState","setProperty","__exports","__esModule"],"sources":["GeolocationPlugin.ts"],"sourcesContent":["import { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport GeolocationControl from \"../../controls/GeolocationControl\";\nimport TextControl from \"sap/m/Text\";\n\nexport class GeolocationPlugin extends BasePlugin {\n /**\n * Renders a `GeolocationControl` component.\n * \n * @param metadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured GeolocationControl.\n */\n public render(metadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = metadata;\n this.fieldKey = bindingPath.replace('/', '');\n this.modelName = modelName;\n\n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n formatter: (val: unknown) => val && val.lat !== undefined && val.lng !== undefined ? `Lat: ${val.lat}, Lng: ${val.lng}` : \"\"\n }\n });\n this.applyCommonDirectives(this.control, metadata, modelName);\n return this.control as Control;\n }\n\n this.control = new GeolocationControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n schemaMetadata: metadata,\n readOnly: !!metadata.ui?.readOnly\n });\n\n this.applyCommonDirectives(this.control, metadata, modelName);\n\n (this.control as GeolocationControl).attachCapture(() => {\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n });\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current geolocation object.\n * @returns {unknown} The geolocation value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as GeolocationControl).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as sap.ui.core.Control).setProperty(\"readOnly\", !!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,kRAASA,EAAUC,EAAA,oBAGZC,EAAkBC,EAAAC,GAGlB,MAAMC,UAA0BL,EAW5BM,OAAOC,EAA8BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAClHC,KAAKD,SAAWA,EAChBC,KAAKL,SAAWA,EAChBK,KAAKC,SAAWL,EAAYM,QAAQ,IAAK,IACzCF,KAAKH,UAAYA,EAEjB,IAAKG,KAAKG,WAAY,CAElBH,KAAKI,QAAU,IAAIC,EAAY,CAC3BC,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCY,KAAM,CACFC,KAAM,GAAGZ,KAAaD,IACtBc,UAAYC,GAAiBA,GAAOA,EAAIC,MAAQC,WAAaF,EAAIG,MAAQD,UAAY,QAAQF,EAAIC,aAAaD,EAAIG,MAAQ,MAGlId,KAAKe,sBAAsBf,KAAKI,QAAST,EAAUE,GACnD,OAAOG,KAAKI,OAChB,CAEAJ,KAAKI,QAAU,IAAId,EAAmB,CAClCgB,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCoB,MAAO,IAAInB,KAAaD,KACxBqB,eAAgBtB,EAChBuB,WAAYvB,EAASwB,IAAID,WAG7BlB,KAAKe,sBAAsBf,KAAKI,QAAST,EAAUE,GAElDG,KAAKI,QAA+BgB,cAAc,KAC/C,MAAMC,EAASrB,KAAKsB,8BAChB,GAAItB,KAAKD,SAAU,CACfC,KAAKD,SAASsB,EAAOE,QAASvB,KAAKC,SACvC,IAGR,OAAOD,KAAKI,OAChB,CAMUoB,WACN,OAAOxB,KAAKI,QAAWJ,KAAKI,QAA+BoB,WAAa,IAC5E,CAKUC,aACN,GAAIzB,KAAKI,SAAWJ,KAAKL,SAAU,CAC/B,IAAKK,KAAKG,WAAY,OACrBH,KAAKI,QAAgCsB,YAAY,aAAc1B,KAAKL,SAASwB,IAAID,SACtF,CACJ,EACH,IAAAS,EAAA,CAAAC,WAAA,MAAAD,EAAAlC,oBAAA,OAAAkC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":42,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","MessageStripPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","control","MessageStrip","id","generateStableId","text","type","showIcon","showCloseButton","getValue","applyState","__exports","__esModule"],"sources":["MessageStripPlugin.ts"],"sourcesContent":["/**\n * @file MessageStripPlugin.ts\n * @description Renders a sap.m.MessageStrip for informational text.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport MessageStrip from \"sap/m/MessageStrip\";\nimport Control from \"sap/ui/core/Control\";\n\n/**\n * Renders read-only informational alerts within the layout.\n * Does not emit values to the payload.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class MessageStripPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.MessageStrip` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured MessageStrip control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n \n // Use binding to display text if the field has a value, otherwise use the label\n this.control = new MessageStrip({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`,\n type: \"Information\", // Can be driven by schema arguments in the future\n showIcon: true,\n showCloseButton: false\n });\n\n return this.control as Control;\n }\n\n /**\n * Read-only control, returns null.\n */\n protected getValue(): unknown {\n return null; // Read-only component\n }\n\n /**\n * Read-only control, no dynamic state needed.\n */\n protected applyState(): void {\n // Read-only component, no dynamic state needed currently\n }\n}\n"],"mappings":"AAAA,oJAAA,MAKSA,EAAUC,EAAA,cAYZ,MAAMC,UAA2BF,EAW7BG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAGhBK,KAAKE,QAAU,IAAIC,EAAa,CAC5BC,GAAIJ,KAAKK,iBAAiBP,EAAeF,GACzCU,KAAM,IAAIT,KAAaD,KACvBW,KAAM,cACNC,SAAU,KACVC,gBAAiB,QAGrB,OAAOT,KAAKE,OAChB,CAKUQ,WACN,OAAO,IACX,CAKUC,aACN,EAEP,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAAnB,qBAAA,OAAAmB,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":43,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","MultiInputPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","isEditable","control","TextControl","id","generateStableId","text","path","formatter","val","Array","isArray","join","applyCommonDirectives","mi","MultiInput","enabled","ui","readOnly","placeholder","label","showValueHelp","tokenUpdate","oEvent","params","getParameters","type","model","getModel","rawArr","getProperty","arr","addedTokens","forEach","t","push","getText","removedTokens","idx","indexOf","splice","setProperty","result","validateAndApplyVisualState","isValid","fieldKey","addValidator","args","Token","key","bindAggregation","factory","sId","oContext","getObject","getValue","tokens","getTokens","map","applyState","setEnabled","__exports","__esModule"],"sources":["MultiInputPlugin.ts"],"sourcesContent":["/**\n * @file MultiInputPlugin.ts\n * @description Renders a sap.m.MultiInput for primitive arrays (e.g. arrays of strings).\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport MultiInput from \"sap/m/MultiInput\";\nimport Token from \"sap/m/Token\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\nimport Event from \"sap/ui/base/Event\";\nimport Context from \"sap/ui/model/Context\";\n\n/**\n * Handles rendering logic for arrays of primitive strings.\n * Users can type custom strings and press Enter to add them as tokens.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class MultiInputPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.MultiInput` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured MultiInput control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n\n if (!this.isEditable) {\n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n formatter: (val: unknown[]) => Array.isArray(val) ? val.join(\", \") : \"\"\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n \n const mi = new MultiInput({\n id: this.generateStableId(engineScopeId, bindingPath),\n enabled: !fieldMetadata.ui?.readOnly,\n placeholder: fieldMetadata.ui?.label || \"Type and press Enter...\",\n showValueHelp: false, // We don't have a list of options for primitive tags\n tokenUpdate: (oEvent: Event) => {\n const params = oEvent.getParameters();\n const type = params.type;\n const model = mi.getModel(modelName) as JSONModel;\n \n // Get current array from model\n const rawArr = model.getProperty(bindingPath);\n const arr: string[] = Array.isArray(rawArr) ? [...rawArr] : [];\n \n if (type === \"added\") {\n const addedTokens = params.addedTokens as Token[];\n addedTokens.forEach(t => arr.push(t.getText()));\n } else if (type === \"removed\") {\n const removedTokens = params.removedTokens as Token[];\n removedTokens.forEach(t => {\n const text = t.getText();\n const idx = arr.indexOf(text);\n if (idx > -1) {\n arr.splice(idx, 1);\n }\n });\n }\n \n // Update model\n model.setProperty(bindingPath, arr);\n \n // Trigger engine validation/extraction\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n // Add validator to instantly accept typed text as a token\n mi.addValidator((args: { text: string }) => {\n return new Token({ key: args.text, text: args.text });\n });\n\n // Bind existing strings to tokens using a factory function\n mi.bindAggregation(\"tokens\", {\n path: `${modelName}>${bindingPath}`,\n factory: (sId: string, oContext: Context) => {\n const text = (oContext.getObject() as string) || \"\";\n return new Token(sId, { key: text, text: text });\n }\n });\n\n this.control = mi;\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n /**\n * Retrieves the current primitive array from the model.\n * @returns {unknown} The array of string tokens.\n */\n protected getValue(): unknown {\n if (!this.control) return [];\n const tokens = (this.control as MultiInput).getTokens();\n return tokens.map(t => t.getText());\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as MultiInput).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,+KAAA,MAKSA,EAAUC,EAAA,cAiBZ,MAAMC,UAAyBF,EAW3BG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAEhB,IAAKK,KAAKE,WAAY,CAClBF,KAAKG,QAAU,IAAIC,EAAY,CAC3BC,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCW,KAAM,CACFC,KAAM,GAAGX,KAAaD,IACtBa,UAAYC,GAAmBC,MAAMC,QAAQF,GAAOA,EAAIG,KAAK,MAAQ,MAG7Eb,KAAKc,sBAAsBd,KAAKG,QAASR,EAAeE,GACxD,OAAOG,KAAKG,OAChB,CAEA,MAAMY,EAAK,IAAIC,EAAW,CACtBX,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCqB,SAAUtB,EAAcuB,IAAIC,SAC5BC,YAAazB,EAAcuB,IAAIG,OAAS,0BACxCC,cAAe,MACfC,YAAcC,IACV,MAAMC,EAASD,EAAOE,gBACtB,MAAMC,EAAOF,EAAOE,KACpB,MAAMC,EAAQb,EAAGc,SAAShC,GAG1B,MAAMiC,EAASF,EAAMG,YAAYnC,GACjC,MAAMoC,EAAgBrB,MAAMC,QAAQkB,GAAU,IAAIA,GAAU,GAE5D,GAAIH,IAAS,QAAS,CAClB,MAAMM,EAAcR,EAAOQ,YAC3BA,EAAYC,QAAQC,GAAKH,EAAII,KAAKD,EAAEE,WACxC,MAAO,GAAIV,IAAS,UAAW,CAC3B,MAAMW,EAAgBb,EAAOa,cAC7BA,EAAcJ,QAAQC,IAClB,MAAM5B,EAAO4B,EAAEE,UACf,MAAME,EAAMP,EAAIQ,QAAQjC,GACxB,GAAIgC,GAAO,EAAG,CACVP,EAAIS,OAAOF,EAAK,EACpB,GAER,CAGAX,EAAMc,YAAY9C,EAAaoC,GAG/B,MAAMW,EAAS3C,KAAK4C,8BACpB,GAAI5C,KAAKD,SAAU,CACfC,KAAKD,SAAS4C,EAAOE,QAAS7C,KAAK8C,SACvC,KAKR/B,EAAGgC,aAAcC,GACN,IAAIC,EAAM,CAAEC,IAAKF,EAAKzC,KAAMA,KAAMyC,EAAKzC,QAIlDQ,EAAGoC,gBAAgB,SAAU,CACzB3C,KAAM,GAAGX,KAAaD,IACtBwD,QAASA,CAACC,EAAaC,KACnB,MAAM/C,EAAQ+C,EAASC,aAA0B,GACjD,OAAO,IAAIN,EAAMI,EAAK,CAAEH,IAAK3C,EAAMA,KAAMA,OAIjDP,KAAKG,QAAUY,EACff,KAAKc,sBAAsBd,KAAKG,QAASR,EAAeE,GACxD,OAAOG,KAAKG,OAChB,CAMUqD,WACN,IAAKxD,KAAKG,QAAS,MAAO,GAC1B,MAAMsD,EAAUzD,KAAKG,QAAuBuD,YAC5C,OAAOD,EAAOE,IAAIxB,GAAKA,EAAEE,UAC7B,CAKUuB,aACN,GAAI5D,KAAKG,SAAWH,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACrBF,KAAKG,QAAuB0D,YAAY7D,KAAKC,SAASiB,IAAIC,SAC/D,CACJ,EACH,IAAA2C,EAAA,CAAAC,WAAA,MAAAD,EAAArE,mBAAA,OAAAqE,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":44,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","MultiSelectPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","isEditable","control","TextControl","id","generateStableId","text","path","formatter","val","Array","isArray","join","applyCommonDirectives","mcb","MultiComboBox","selectedKeys","enabled","ui","readOnly","placeholder","label","selectionChange","oEvent","keys","getSelectedKeys","result","validateAndApplyVisualState","isValid","fieldKey","enum","forEach","addItem","Item","key","toString","getValue","applyState","setEnabled","__exports","__esModule"],"sources":["MultiSelectPlugin.ts"],"sourcesContent":["/**\n * @file MultiSelectPlugin.ts\n * @description Renders a sap.m.MultiComboBox for selecting multiple string values.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport MultiComboBox from \"sap/m/MultiComboBox\";\nimport Item from \"sap/ui/core/Item\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering logic for selecting multiple strings from a predefined list.\n * Expects the payload to be an array of strings.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class MultiSelectPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.MultiComboBox` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured MultiComboBox control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n\n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n formatter: (val: unknown[]) => Array.isArray(val) ? val.join(\", \") : \"\"\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n \n const mcb = new MultiComboBox({\n id: this.generateStableId(engineScopeId, bindingPath),\n selectedKeys: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n placeholder: fieldMetadata.ui?.label || \"Select items...\",\n selectionChange: (oEvent: sap.ui.base.Event) => {\n const keys = (this.control as MultiComboBox).getSelectedKeys();\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n if (fieldMetadata.enum) {\n fieldMetadata.enum.forEach((val: string | number) => {\n mcb.addItem(new Item({ key: val.toString(), text: val.toString() }));\n });\n }\n\n this.control = mcb;\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n /**\n * Retrieves the current selection keys.\n * @returns {unknown} The selected keys.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as MultiComboBox).getSelectedKeys() : [];\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as MultiComboBox).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,wLAAA,MAKSA,EAAUC,EAAA,cAcZ,MAAMC,UAA0BF,EAW5BG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAEhB,IAAKK,KAAKE,WAAY,CAElBF,KAAKG,QAAU,IAAIC,EAAY,CAC3BC,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCW,KAAM,CACFC,KAAM,GAAGX,KAAaD,IACtBa,UAAYC,GAAmBC,MAAMC,QAAQF,GAAOA,EAAIG,KAAK,MAAQ,MAG7Eb,KAAKc,sBAAsBd,KAAKG,QAASR,EAAeE,GACxD,OAAOG,KAAKG,OAChB,CAEA,MAAMY,EAAM,IAAIC,EAAc,CAC1BX,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCqB,aAAc,IAAIpB,KAAaD,KAC/BsB,SAAUvB,EAAcwB,IAAIC,SAC5BC,YAAa1B,EAAcwB,IAAIG,OAAS,kBACxCC,gBAAkBC,IACd,MAAMC,EAAQzB,KAAKG,QAA0BuB,kBAC7C,MAAMC,EAAS3B,KAAK4B,8BACpB,GAAI5B,KAAKD,SAAU,CACfC,KAAKD,SAAS4B,EAAOE,QAAS7B,KAAK8B,SACvC,KAIR,GAAInC,EAAcoC,KAAM,CACpBpC,EAAcoC,KAAKC,QAAStB,IACxBK,EAAIkB,QAAQ,IAAIC,EAAK,CAAEC,IAAKzB,EAAI0B,WAAY7B,KAAMG,EAAI0B,eAE9D,CAEApC,KAAKG,QAAUY,EACff,KAAKc,sBAAsBd,KAAKG,QAASR,EAAeE,GACxD,OAAOG,KAAKG,OAChB,CAMUkC,WACN,OAAOrC,KAAKG,QAAWH,KAAKG,QAA0BuB,kBAAoB,EAC9E,CAKUY,aACN,GAAItC,KAAKG,SAAWH,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACrBF,KAAKG,QAA0BoC,YAAYvC,KAAKC,SAASkB,IAAIC,SAClE,CACJ,EACH,IAAAoB,EAAA,CAAAC,WAAA,MAAAD,EAAA/C,oBAAA,OAAA+C,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":45,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","NumberPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","isEditable","control","TextControl","id","generateStableId","text","applyCommonDirectives","StepInput","value","displayValuePrecision","scale","undefined","type","editable","ui","readOnly","required","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","fieldKey","getValue","applyState","input","setEditable","setRequired","__exports","__esModule"],"sources":["NumberPlugin.ts"],"sourcesContent":["/**\n * @file NumberPlugin.ts\n * @description Renders a sap.m.StepInput for numeric data.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport StepInput from \"sap/m/StepInput\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering and logic for numeric inputs.\n */\nexport class NumberPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.StepInput` component for numeric evaluation.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured StepInput control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n\n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new StepInput({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n displayValuePrecision: fieldMetadata.scale !== undefined ? fieldMetadata.scale : (fieldMetadata.type === \"integer\" ? 0 : 3),\n editable: !fieldMetadata.ui?.readOnly,\n required: fieldMetadata.required,\n change: (oEvent: sap.ui.base.Event) => {\n const val = oEvent.getParameter(\"value\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current numeric state.\n * @returns {unknown} The numeric value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as StepInput).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const input = this.control as StepInput;\n input.setEditable(!this.metadata.ui?.readOnly);\n input.setRequired(this.metadata.required);\n }\n }\n}\n"],"mappings":"AAAA,0JAAA,MAKSA,EAAUC,EAAA,cASZ,MAAMC,UAAqBF,EAWvBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAEhB,IAAKK,KAAKE,WAAY,CAElBF,KAAKG,QAAU,IAAIC,EAAY,CAC3BC,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCW,KAAM,IAAIV,KAAaD,OAE3BI,KAAKQ,sBAAsBR,KAAKG,QAASR,EAAeE,GACxD,OAAOG,KAAKG,OAChB,CAEAH,KAAKG,QAAU,IAAIM,EAAU,CACzBJ,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCc,MAAO,IAAIb,KAAaD,KACxBe,sBAAuBhB,EAAciB,QAAUC,UAAYlB,EAAciB,MAASjB,EAAcmB,OAAS,UAAY,EAAI,EACzHC,UAAWpB,EAAcqB,IAAIC,SAC7BC,SAAUvB,EAAcuB,SACxBC,OAASC,IACL,MAAMC,EAAMD,EAAOE,aAAa,SAChC,MAAMC,EAASvB,KAAKwB,8BACpB,GAAIxB,KAAKD,SAAU,CACfC,KAAKD,SAASwB,EAAOE,QAASzB,KAAK0B,SACvC,KAIR1B,KAAKQ,sBAAsBR,KAAKG,QAASR,EAAeE,GAExD,OAAOG,KAAKG,OAChB,CAMUwB,WACN,OAAO3B,KAAKG,QAAWH,KAAKG,QAAsBwB,WAAa,IACnE,CAKUC,aACN,GAAI5B,KAAKG,SAAWH,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACtB,MAAM2B,EAAQ7B,KAAKG,QACnB0B,EAAMC,aAAa9B,KAAKC,SAASe,IAAIC,UACrCY,EAAME,YAAY/B,KAAKC,SAASiB,SACpC,CACJ,EACH,IAAAc,EAAA,CAAAC,WAAA,MAAAD,EAAAvC,eAAA,OAAAuC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":46,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","ObjectPlugin","render","field","bindingPath","modelName","engineScopeId","onChange","this","metadata","propKey","startsWith","substring","subSchema","type","title","ui","label","properties","uiLayout","control","Button","id","generateStableId","text","isEditable","icon","press","oEvent","btn","getSource","parentModel","getModel","bindingContext","getBindingContext","updatePath","ctxPath","getPath","endsWith","nestedData","JSON","parse","stringify","getProperty","sap","require","DynamicHost","host","schemaDefinition","data","editable","attachSubmit","e","payload","getParameter","setProperty","buttonText","dialogButtonText","openInDialog","validate","isValid","getValue","applyState","__exports","__esModule"],"sources":["ObjectPlugin.ts"],"sourcesContent":["/**\n * @file ObjectPlugin.ts\n * @description Renders a button that opens a dialog to edit a nested object structure.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPluginValidationResult } from \"../../interfaces/IPlugin\";\nimport { ISchema, IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport Event from \"sap/ui/base/Event\";\nimport Button from \"sap/m/Button\";\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\n\nexport class ObjectPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.Button` to open a nested Object form dialog.\n * \n * @param field The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured Button control.\n */\n public render(field: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = field;\n const propKey = bindingPath.startsWith(\"/\") ? bindingPath.substring(1) : bindingPath;\n \n const subSchema: ISchema = {\n type: \"object\",\n title: field.ui?.label || propKey,\n properties: field.properties || {}\n };\n \n if (field.uiLayout) {\n subSchema.uiLayout = field.uiLayout;\n }\n\n this.control = new Button({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: !this.isEditable ? \"View Details\" : \"Edit Details\",\n icon: !this.isEditable ? \"sap-icon://display\" : \"sap-icon://form\",\n press: (oEvent: Event) => {\n const btn = oEvent.getSource() as Button;\n const parentModel = btn.getModel(modelName) as JSONModel;\n if (!parentModel) return;\n \n const bindingContext = btn.getBindingContext(modelName);\n let updatePath = bindingPath;\n if (bindingContext && !bindingPath.startsWith(\"/\")) {\n const ctxPath = bindingContext.getPath();\n updatePath = ctxPath.endsWith(\"/\") ? ctxPath + bindingPath : (ctxPath === \"/\" ? \"/\" + bindingPath : ctxPath + \"/\" + bindingPath);\n }\n \n // Deep clone to prevent live-mutations on the parent model before 'Submit' is clicked\n const nestedData = JSON.parse(JSON.stringify(parentModel.getProperty(updatePath) || {}));\n\n sap.ui.require([\"nz/co/siliconst/ui5/metaui/controls/DynamicHost\"], (DynamicHost: typeof import(\"../../controls/DynamicHost\").default) => {\n const host = new DynamicHost({\n schemaDefinition: subSchema,\n data: nestedData,\n editable: this.isEditable\n });\n\n if (!!this.isEditable) {\n host.attachSubmit((e: Event) => {\n const payload = (e.getParameter(\"payload\") as unknown);\n parentModel.setProperty(updatePath, payload);\n \n // CRITICAL: Notify the parent Engine that this field mutated\n // so it can trigger LiveUpdate syncs and validate!\n if (this.onChange) {\n this.onChange(true, propKey);\n }\n });\n }\n\n const buttonText = field.ui?.dialogButtonText || (!this.isEditable ? \"Close\" : \"OK\");\n host.openInDialog(`Nested Details: ${field.ui?.label || propKey}`, buttonText);\n });\n }\n });\n\n return this.control as Control;\n }\n\n /**\n * Validates the object plugin (always true as validation is deferred to the dialog host).\n * @returns {IPluginValidationResult} The validation result.\n */\n public validate(): IPluginValidationResult {\n return { isValid: true };\n }\n\n /**\n * Read-only component for the engine, returns null.\n */\n protected getValue(): null {\n return null;\n }\n\n /**\n * Read-only component, no dynamic state handling needed for the button itself.\n */\n protected applyState(): void {\n // No dynamic state handling needed for the button\n }\n}\n"],"mappings":"AAAA,wIAAA,MAKSA,EAAUC,EAAA,cAQZ,MAAMC,UAAqBF,EAWvBG,OAAOC,EAA2BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAC/GC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChB,MAAMO,EAAUN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,MAAMS,EAAqB,CACvBC,KAAM,SACNC,MAAOZ,EAAMa,IAAIC,OAASP,EAC1BQ,WAAYf,EAAMe,YAAc,CAAC,GAGrC,GAAIf,EAAMgB,SAAU,CAChBN,EAAUM,SAAWhB,EAAMgB,QAC/B,CAEAX,KAAKY,QAAU,IAAIC,EAAO,CACtBC,GAAId,KAAKe,iBAAiBjB,EAAeF,GACzCoB,MAAOhB,KAAKiB,WAAa,eAAiB,eAC1CC,MAAOlB,KAAKiB,WAAa,qBAAuB,kBAChDE,MAAQC,IACJ,MAAMC,EAAMD,EAAOE,YACnB,MAAMC,EAAcF,EAAIG,SAAS3B,GACjC,IAAK0B,EAAa,OAElB,MAAME,EAAiBJ,EAAIK,kBAAkB7B,GAC7C,IAAI8B,EAAa/B,EACjB,GAAI6B,IAAmB7B,EAAYO,WAAW,KAAM,CAChD,MAAMyB,EAAUH,EAAeI,UAC/BF,EAAaC,EAAQE,SAAS,KAAOF,EAAUhC,EAAegC,IAAY,IAAM,IAAMhC,EAAcgC,EAAU,IAAMhC,CACxH,CAGA,MAAMmC,EAAaC,KAAKC,MAAMD,KAAKE,UAAUX,EAAYY,YAAYR,IAAe,CAAC,IAErFS,IAAI5B,GAAG6B,QAAQ,CAAC,mDAAqDC,IACjE,MAAMC,EAAO,IAAID,EAAY,CACzBE,iBAAkBnC,EAClBoC,KAAMV,EACNW,SAAU1C,KAAKiB,aAGnB,KAAMjB,KAAKiB,WAAY,CACnBsB,EAAKI,aAAcC,IACf,MAAMC,EAAWD,EAAEE,aAAa,WAChCvB,EAAYwB,YAAYpB,EAAYkB,GAIpC,GAAI7C,KAAKD,SAAU,CACfC,KAAKD,SAAS,KAAMG,EACxB,GAER,CAEA,MAAM8C,EAAarD,EAAMa,IAAIyC,oBAAsBjD,KAAKiB,WAAa,QAAU,MAC/EsB,EAAKW,aAAa,mBAAmBvD,EAAMa,IAAIC,OAASP,IAAW8C,QAK/E,OAAOhD,KAAKY,OAChB,CAMOuC,WACH,MAAO,CAAEC,QAAS,KACtB,CAKUC,WACN,OAAO,IACX,CAKUC,aACN,EAEP,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAA9D,eAAA,OAAA8D,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":47,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","RatingIndicatorPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","isEditable","control","TextControl","id","generateStableId","text","applyCommonDirectives","RatingIndicator","value","enabled","ui","readOnly","maxValue","maximum","undefined","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","fieldKey","getValue","applyState","setEnabled","__exports","__esModule"],"sources":["RatingIndicatorPlugin.ts"],"sourcesContent":["/**\n * @file RatingIndicatorPlugin.ts\n * @description Renders a sap.m.RatingIndicator for 1-5 numeric feedback.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport RatingIndicator from \"sap/m/RatingIndicator\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering logic for rating feedback.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class RatingIndicatorPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.RatingIndicator` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured RatingIndicator control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n\n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n \n this.control = new RatingIndicator({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n maxValue: fieldMetadata.maximum !== undefined ? fieldMetadata.maximum : 5,\n change: (oEvent: sap.ui.base.Event) => {\n const val = oEvent.getParameter(\"value\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current rating value.\n * @returns {unknown} The rating value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as RatingIndicator).getValue() : 0;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as RatingIndicator).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,yKAAA,MAKSA,EAAUC,EAAA,cAYZ,MAAMC,UAA8BF,EAWhCG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAEhB,IAAKK,KAAKE,WAAY,CAElBF,KAAKG,QAAU,IAAIC,EAAY,CAC3BC,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCW,KAAM,IAAIV,KAAaD,OAE3BI,KAAKQ,sBAAsBR,KAAKG,QAASR,EAAeE,GACxD,OAAOG,KAAKG,OAChB,CAEAH,KAAKG,QAAU,IAAIM,EAAgB,CAC/BJ,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCc,MAAO,IAAIb,KAAaD,KACxBe,SAAUhB,EAAciB,IAAIC,SAC5BC,SAAUnB,EAAcoB,UAAYC,UAAYrB,EAAcoB,QAAU,EACxEE,OAASC,IACL,MAAMC,EAAMD,EAAOE,aAAa,SAChC,MAAMC,EAASrB,KAAKsB,8BACpB,GAAItB,KAAKD,SAAU,CACfC,KAAKD,SAASsB,EAAOE,QAASvB,KAAKwB,SACvC,KAIRxB,KAAKQ,sBAAsBR,KAAKG,QAASR,EAAeE,GAExD,OAAOG,KAAKG,OAChB,CAMUsB,WACN,OAAOzB,KAAKG,QAAWH,KAAKG,QAA4BsB,WAAa,CACzE,CAKUC,aACN,GAAI1B,KAAKG,SAAWH,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACrBF,KAAKG,QAA4BwB,YAAY3B,KAAKC,SAASW,IAAIC,SACpE,CACJ,EACH,IAAAe,EAAA,CAAAC,WAAA,MAAAD,EAAAnC,wBAAA,OAAAmC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":48,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","RichTextControl","_interopRequireDefault","__RichTextControl","isValueAccessor","control","getValue","RichTextPlugin","render","metadata","bindingPath","modelName","engineScopeId","onChange","this","fieldKey","replace","isEditable","FormattedTextControl","id","generateStableId","htmlText","applyCommonDirectives","value","schemaMetadata","readOnly","ui","attachCapture","result","validateAndApplyVisualState","isValid","applyState","setProperty","__exports","__esModule"],"sources":["RichTextPlugin.ts"],"sourcesContent":["import { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport RichTextControl from \"../../controls/RichTextControl\";\nimport FormattedTextControl from \"sap/m/FormattedText\";\n\ninterface IValueAccessor {\n getValue(): unknown;\n attachCapture?(fn: Function): void;\n}\n\nfunction isValueAccessor(control: unknown): control is IValueAccessor {\n return control !== null && typeof (control as IValueAccessor).getValue === 'function';\n}\n\nexport class RichTextPlugin extends BasePlugin {\n /**\n * Renders a `RichTextControl` component.\n * \n * @param metadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured RichTextControl.\n */\n public render(metadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = metadata;\n this.fieldKey = bindingPath.replace('/', '');\n this.modelName = modelName;\n\n if (!this.isEditable) {\n \n this.control = new FormattedTextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n htmlText: `{${modelName}>${bindingPath}}`\n }) as Control;\n this.applyCommonDirectives(this.control, metadata, modelName);\n return this.control as Control;\n }\n\n this.control = new RichTextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n schemaMetadata: metadata,\n readOnly: !!metadata.ui?.readOnly\n }) as Control;\n\n this.applyCommonDirectives(this.control, metadata, modelName);\n\n if (isValueAccessor(this.control) && this.control.attachCapture) {\n this.control.attachCapture(() => {\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n });\n }\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current HTML string value.\n * @returns {unknown} The string value.\n */\n protected getValue(): unknown {\n if (isValueAccessor(this.control)) {\n return this.control.getValue();\n }\n return null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as sap.ui.core.Control).setProperty(\"readOnly\", !!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,qRAASA,EAAUC,EAAA,oBAGZC,EAAeC,EAAAC,GAQtB,SAASC,EAAgBC,GACrB,OAAOA,IAAY,aAAgBA,EAA2BC,WAAa,UAC/E,CAEO,MAAMC,UAAuBR,EAWzBS,OAAOC,EAA8BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAClHC,KAAKD,SAAWA,EAChBC,KAAKL,SAAWA,EAChBK,KAAKC,SAAWL,EAAYM,QAAQ,IAAK,IACzCF,KAAKH,UAAYA,EAEjB,IAAKG,KAAKG,WAAY,CAElBH,KAAKT,QAAU,IAAIa,EAAqB,CACpCC,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCW,SAAU,IAAIV,KAAaD,OAE/BI,KAAKQ,sBAAsBR,KAAKT,QAASI,EAAUE,GACnD,OAAOG,KAAKT,OAChB,CAEAS,KAAKT,QAAU,IAAIJ,EAAgB,CAC/BkB,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCa,MAAO,IAAIZ,KAAaD,KACxBc,eAAgBf,EAChBgB,WAAYhB,EAASiB,IAAID,WAG7BX,KAAKQ,sBAAsBR,KAAKT,QAASI,EAAUE,GAEnD,GAAIP,EAAgBU,KAAKT,UAAYS,KAAKT,QAAQsB,cAAe,CAC7Db,KAAKT,QAAQsB,cAAc,KACvB,MAAMC,EAASd,KAAKe,8BACpB,GAAIf,KAAKD,SAAU,CACfC,KAAKD,SAASe,EAAOE,QAAShB,KAAKC,SACvC,GAER,CAEA,OAAOD,KAAKT,OAChB,CAMUC,WACN,GAAIF,EAAgBU,KAAKT,SAAU,CAC/B,OAAOS,KAAKT,QAAQC,UACxB,CACA,OAAO,IACX,CAKUyB,aACN,GAAIjB,KAAKT,SAAWS,KAAKL,SAAU,CAC/B,IAAKK,KAAKG,WAAY,OACrBH,KAAKT,QAAgC2B,YAAY,aAAclB,KAAKL,SAASiB,IAAID,SACtF,CACJ,EACH,IAAAQ,EAAA,CAAAC,WAAA,MAAAD,EAAA1B,iBAAA,OAAA0B,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":49,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","SignatureControl","_interopRequireDefault","__SignatureControl","SignaturePlugin","render","metadata","bindingPath","modelName","engineScopeId","onChange","this","fieldKey","replace","isEditable","control","ImageControl","id","generateStableId","src","width","alt","ui","label","applyCommonDirectives","value","schemaMetadata","readOnly","attachCapture","result","validateAndApplyVisualState","isValid","getValue","applyState","setProperty","__exports","__esModule"],"sources":["SignaturePlugin.ts"],"sourcesContent":["import { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport SignatureControl from \"../../controls/SignatureControl\";\nimport ImageControl from \"sap/m/Image\";\n\nexport class SignaturePlugin extends BasePlugin {\n /**\n * Renders a `SignatureControl` component.\n * \n * @param metadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured SignatureControl.\n */\n public render(metadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = metadata;\n this.fieldKey = bindingPath.replace('/', '');\n this.modelName = modelName;\n\n if (!this.isEditable) {\n \n this.control = new ImageControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n src: `{${modelName}>${bindingPath}}`,\n width: \"400px\",\n alt: metadata.ui?.label || \"Signature\"\n }) as Control;\n this.applyCommonDirectives(this.control, metadata, modelName);\n return this.control as Control;\n }\n\n this.control = new SignatureControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n schemaMetadata: metadata,\n readOnly: !!metadata.ui?.readOnly\n }) as Control;\n\n this.applyCommonDirectives(this.control, metadata, modelName);\n\n (this.control as SignatureControl).attachCapture(() => {\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n });\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current base64 signature image state.\n * @returns {unknown} The signature image value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as SignatureControl).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as sap.ui.core.Control).setProperty(\"readOnly\", !!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,+QAASA,EAAUC,EAAA,oBAGZC,EAAgBC,EAAAC,GAGhB,MAAMC,UAAwBL,EAW1BM,OAAOC,EAA8BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAClHC,KAAKD,SAAWA,EAChBC,KAAKL,SAAWA,EAChBK,KAAKC,SAAWL,EAAYM,QAAQ,IAAK,IACzCF,KAAKH,UAAYA,EAEjB,IAAKG,KAAKG,WAAY,CAElBH,KAAKI,QAAU,IAAIC,EAAa,CAC5BC,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCY,IAAK,IAAIX,KAAaD,KACtBa,MAAO,QACPC,IAAKf,EAASgB,IAAIC,OAAS,cAE/BZ,KAAKa,sBAAsBb,KAAKI,QAAST,EAAUE,GACnD,OAAOG,KAAKI,OAChB,CAEAJ,KAAKI,QAAU,IAAId,EAAiB,CAChCgB,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCkB,MAAO,IAAIjB,KAAaD,KACxBmB,eAAgBpB,EAChBqB,WAAYrB,EAASgB,IAAIK,WAG7BhB,KAAKa,sBAAsBb,KAAKI,QAAST,EAAUE,GAElDG,KAAKI,QAA6Ba,cAAc,KAC7C,MAAMC,EAASlB,KAAKmB,8BAChB,GAAInB,KAAKD,SAAU,CACfC,KAAKD,SAASmB,EAAOE,QAASpB,KAAKC,SACvC,IAGR,OAAOD,KAAKI,OAChB,CAMUiB,WACN,OAAOrB,KAAKI,QAAWJ,KAAKI,QAA6BiB,WAAa,IAC1E,CAKUC,aACN,GAAItB,KAAKI,SAAWJ,KAAKL,SAAU,CAC/B,IAAKK,KAAKG,WAAY,OACrBH,KAAKI,QAAgCmB,YAAY,aAAcvB,KAAKL,SAASgB,IAAIK,SACtF,CACJ,EACH,IAAAQ,EAAA,CAAAC,WAAA,MAAAD,EAAA/B,kBAAA,OAAA+B,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":50,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","SliderPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","isEditable","control","TextControl","id","generateStableId","text","applyCommonDirectives","Slider","value","enabled","ui","readOnly","min","minimum","undefined","max","maximum","step","multipleOf","enableTickmarks","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","fieldKey","getValue","applyState","setEnabled","__exports","__esModule"],"sources":["SliderPlugin.ts"],"sourcesContent":["/**\n * @file SliderPlugin.ts\n * @description Renders a sap.m.Slider for picking numbers in a range.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Slider from \"sap/m/Slider\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering logic for numeric sliders.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class SliderPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.Slider` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured Slider control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n \n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new Slider({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n min: fieldMetadata.minimum !== undefined ? fieldMetadata.minimum : 0,\n max: fieldMetadata.maximum !== undefined ? fieldMetadata.maximum : 100,\n step: fieldMetadata.multipleOf !== undefined ? fieldMetadata.multipleOf : 1,\n enableTickmarks: true,\n change: (oEvent: sap.ui.base.Event) => {\n const val = (oEvent as sap.ui.base.Event).getParameter(\"value\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current slider value.\n * @returns {unknown} The numeric value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as Slider).getValue() : 0;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as Slider).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,uJAAA,MAKSA,EAAUC,EAAA,cAYZ,MAAMC,UAAqBF,EAWvBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAEhB,IAAKK,KAAKE,WAAY,CAElBF,KAAKG,QAAU,IAAIC,EAAY,CAC3BC,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCW,KAAM,IAAIV,KAAaD,OAE3BI,KAAKQ,sBAAsBR,KAAKG,QAASR,EAAeE,GACxD,OAAOG,KAAKG,OAChB,CAEAH,KAAKG,QAAU,IAAIM,EAAO,CACtBJ,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCc,MAAO,IAAIb,KAAaD,KACxBe,SAAUhB,EAAciB,IAAIC,SAC5BC,IAAKnB,EAAcoB,UAAYC,UAAYrB,EAAcoB,QAAU,EACnEE,IAAKtB,EAAcuB,UAAYF,UAAYrB,EAAcuB,QAAU,IACnEC,KAAMxB,EAAcyB,aAAeJ,UAAYrB,EAAcyB,WAAa,EAC1EC,gBAAiB,KACjBC,OAASC,IACL,MAAMC,EAAOD,EAA6BE,aAAa,SACvD,MAAMC,EAAS1B,KAAK2B,8BACpB,GAAI3B,KAAKD,SAAU,CACfC,KAAKD,SAAS2B,EAAOE,QAAS5B,KAAK6B,SACvC,KAIR7B,KAAKQ,sBAAsBR,KAAKG,QAASR,EAAeE,GAExD,OAAOG,KAAKG,OAChB,CAMU2B,WACN,OAAO9B,KAAKG,QAAWH,KAAKG,QAAmB2B,WAAa,CAChE,CAKUC,aACN,GAAI/B,KAAKG,SAAWH,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACrBF,KAAKG,QAAmB6B,YAAYhC,KAAKC,SAASW,IAAIC,SAC3D,CACJ,EACH,IAAAoB,EAAA,CAAAC,WAAA,MAAAD,EAAAxC,eAAA,OAAAwC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":51,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","StringPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","replace","isEditable","control","TextControl","id","generateStableId","text","applyCommonDirectives","Input","value","maxLength","required","showValueHelp","ui","widget","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","getValue","applyState","input","setEditable","readOnly","setRequired","__exports","__esModule"],"sources":["StringPlugin.ts"],"sourcesContent":["/**\n * @file StringPlugin.ts\n * @description Renders a sap.m.Input for string data and validates lengths.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Input from \"sap/m/Input\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering and logic for basic text inputs.\n * Maps schema properties like `maxLength` and `required` natively to `sap.m.Input`.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class StringPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.Input` control configured via the provided schema metadata.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured Input control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.replace(\"/\", \"\"); // For EventBus\n \n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new Input({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n maxLength: fieldMetadata.maxLength || 0,\n required: !!fieldMetadata.required,\n showValueHelp: fieldMetadata.ui?.widget === \"searchHelp\",\n change: (oEvent: sap.ui.base.Event) => {\n const val = (oEvent as sap.ui.base.Event).getParameter(\"value\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current string value from the input.\n * @returns {unknown} The string value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as Input).getValue() : null;\n }\n\n /**\n * Adjusts dynamic state properties (editable/required) based on ConditionEngine mutations.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) {\n // Text doesn't have editable/required state\n return;\n }\n const input = this.control as Input;\n input.setEditable(!this.metadata.ui?.readOnly);\n input.setRequired(this.metadata.required);\n }\n }\n}\n"],"mappings":"AAAA,sJAAA,MAKSA,EAAUC,EAAA,cAaZ,MAAMC,UAAqBF,EAWvBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,QAAQ,IAAK,IAEzC,IAAKH,KAAKI,WAAY,CAElBJ,KAAKK,QAAU,IAAIC,EAAY,CAC3BC,GAAIP,KAAKQ,iBAAiBV,EAAeF,GACzCa,KAAM,IAAIZ,KAAaD,OAE3BI,KAAKU,sBAAsBV,KAAKK,QAASV,EAAeE,GACxD,OAAOG,KAAKK,OAChB,CAEAL,KAAKK,QAAU,IAAIM,EAAM,CACrBJ,GAAIP,KAAKQ,iBAAiBV,EAAeF,GACzCgB,MAAO,IAAIf,KAAaD,KACxBiB,UAAWlB,EAAckB,WAAa,EACtCC,WAAYnB,EAAcmB,SAC1BC,cAAepB,EAAcqB,IAAIC,SAAW,aAC5CC,OAASC,IACL,MAAMC,EAAOD,EAA6BE,aAAa,SACvD,MAAMC,EAAStB,KAAKuB,8BACpB,GAAIvB,KAAKD,SAAU,CACfC,KAAKD,SAASuB,EAAOE,QAASxB,KAAKE,SACvC,KAIRF,KAAKU,sBAAsBV,KAAKK,QAASV,EAAeE,GAExD,OAAOG,KAAKK,OAChB,CAMUoB,WACN,OAAOzB,KAAKK,QAAWL,KAAKK,QAAkBoB,WAAa,IAC/D,CAKUC,aACN,GAAI1B,KAAKK,SAAWL,KAAKC,SAAU,CAC/B,IAAKD,KAAKI,WAAY,CAElB,MACJ,CACA,MAAMuB,EAAQ3B,KAAKK,QACnBsB,EAAMC,aAAa5B,KAAKC,SAASe,IAAIa,UACrCF,EAAMG,YAAY9B,KAAKC,SAASa,SACpC,CACJ,EACH,IAAAiB,EAAA,CAAAC,WAAA,MAAAD,EAAAtC,eAAA,OAAAsC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":52,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","SwitchPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","isEditable","control","TextControl","id","generateStableId","text","path","formatter","val","applyCommonDirectives","Switch","state","enabled","ui","readOnly","change","oEvent","getParameter","result","validateAndApplyVisualState","isValid","fieldKey","getValue","getState","applyState","sw","setEnabled","__exports","__esModule"],"sources":["SwitchPlugin.ts"],"sourcesContent":["/**\n * @file SwitchPlugin.ts\n * @description Renders a sap.m.Switch for boolean data specifically marked with the switch widget.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Switch from \"sap/m/Switch\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering logic for toggleable boolean switches.\n */\nexport class SwitchPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.Switch` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured Switch control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n\n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n formatter: (val: boolean) => val ? \"Yes\" : \"No\"\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new Switch({\n id: this.generateStableId(engineScopeId, bindingPath),\n state: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n change: (oEvent: sap.ui.base.Event) => {\n const val = (oEvent as sap.ui.base.Event).getParameter(\"state\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current switch state.\n * @returns {unknown} The boolean state.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as Switch).getState() : false;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const sw = this.control as Switch;\n sw.setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,uJAAA,MAKSA,EAAUC,EAAA,cASZ,MAAMC,UAAqBF,EAWvBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAEhB,IAAKK,KAAKE,WAAY,CAElBF,KAAKG,QAAU,IAAIC,EAAY,CAC3BC,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCW,KAAM,CACFC,KAAM,GAAGX,KAAaD,IACtBa,UAAYC,GAAiBA,EAAM,MAAQ,QAGnDV,KAAKW,sBAAsBX,KAAKG,QAASR,EAAeE,GACxD,OAAOG,KAAKG,OAChB,CAEAH,KAAKG,QAAU,IAAIS,EAAO,CACtBP,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCiB,MAAO,IAAIhB,KAAaD,KACxBkB,SAAUnB,EAAcoB,IAAIC,SAC5BC,OAASC,IACL,MAAMR,EAAOQ,EAA6BC,aAAa,SACvD,MAAMC,EAASpB,KAAKqB,8BACpB,GAAIrB,KAAKD,SAAU,CACfC,KAAKD,SAASqB,EAAOE,QAAStB,KAAKuB,SACvC,KAIRvB,KAAKW,sBAAsBX,KAAKG,QAASR,EAAeE,GAExD,OAAOG,KAAKG,OAChB,CAMUqB,WACN,OAAOxB,KAAKG,QAAWH,KAAKG,QAAmBsB,WAAa,KAChE,CAKUC,aACN,GAAI1B,KAAKG,SAAWH,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACtB,MAAMyB,EAAK3B,KAAKG,QAChBwB,EAAGC,YAAY5B,KAAKC,SAASc,IAAIC,SACrC,CACJ,EACH,IAAAa,EAAA,CAAAC,WAAA,MAAAD,EAAApC,eAAA,OAAAoC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":53,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","TextAreaPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","replace","isEditable","control","TextControl","id","generateStableId","text","applyCommonDirectives","TextArea","value","maxLength","required","rows","growing","change","oEvent","updateHeight","getSource","result","validateAndApplyVisualState","isValid","liveChange","attachEventOnce","oBinding","getBinding","initLogic","attachChange","oTextArea","val","getValue","numLines","split","length","wrappedLines","Math","ceil","totalLines","max","setRows","applyState","input","setEditable","ui","readOnly","setRequired","__exports","__esModule"],"sources":["TextAreaPlugin.ts"],"sourcesContent":["/**\n * @file TextAreaPlugin.ts\n * @description Renders a sap.m.TextArea for string data specifically marked with the textArea widget.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport TextArea from \"sap/m/TextArea\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering and logic for multi-line text areas.\n */\nexport class TextAreaPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.TextArea` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured TextArea control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.replace(\"/\", \"\"); // For EventBus\n \n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new TextArea({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n maxLength: fieldMetadata.maxLength || 0,\n required: !!fieldMetadata.required,\n rows: 3, // Start with at least 3 lines\n growing: false, // We manage height manually to maintain the +2 lines requirement\n change: (oEvent: sap.ui.base.Event) => {\n this.updateHeight(oEvent.getSource() as TextArea);\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n },\n liveChange: (oEvent: sap.ui.base.Event) => {\n this.updateHeight(oEvent.getSource() as TextArea);\n }\n });\n\n // Clean architecture: Wait for the model context, then calculate initial height\n (this.control as TextArea).attachEventOnce(\"modelContextChange\", () => {\n const oBinding = (this.control as TextArea).getBinding(\"value\");\n \n const initLogic = () => {\n if (this.control) {\n this.updateHeight(this.control as TextArea);\n }\n };\n\n if (oBinding) {\n oBinding.attachChange(initLogic);\n }\n // Execute immediately in case the model is synchronous (JSONModel)\n initLogic();\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Dynamically sets the rows to the content length + 2\n */\n private updateHeight(oTextArea: TextArea): void {\n const val = oTextArea.getValue() || \"\";\n // Count actual newlines in the string\n const numLines = val.split(/\\r\\n|\\r|\\n/).length;\n // Also estimate word wrapping if they type a really long single line without pressing enter\n // A standard character width approximation, assuming ~80 chars per line for full width\n const wrappedLines = Math.ceil(val.length / 80);\n \n const totalLines = Math.max(numLines, wrappedLines);\n \n // Ensure there is always 2 lines of extra breathing room\n oTextArea.setRows(Math.max(3, totalLines + 2));\n }\n\n /**\n * Retrieves the current text string.\n * @returns {unknown} The text string.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as TextArea).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const input = this.control as TextArea;\n input.setEditable(!this.metadata.ui?.readOnly);\n input.setRequired(this.metadata.required);\n }\n }\n}\n"],"mappings":"AAAA,2JAAA,MAKSA,EAAUC,EAAA,cASZ,MAAMC,UAAuBF,EAWzBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,QAAQ,IAAK,IAEzC,IAAKH,KAAKI,WAAY,CAElBJ,KAAKK,QAAU,IAAIC,EAAY,CAC3BC,GAAIP,KAAKQ,iBAAiBV,EAAeF,GACzCa,KAAM,IAAIZ,KAAaD,OAE3BI,KAAKU,sBAAsBV,KAAKK,QAASV,EAAeE,GACxD,OAAOG,KAAKK,OAChB,CAEAL,KAAKK,QAAU,IAAIM,EAAS,CACxBJ,GAAIP,KAAKQ,iBAAiBV,EAAeF,GACzCgB,MAAO,IAAIf,KAAaD,KACxBiB,UAAWlB,EAAckB,WAAa,EACtCC,WAAYnB,EAAcmB,SAC1BC,KAAM,EACNC,QAAS,MACTC,OAASC,IACLlB,KAAKmB,aAAaD,EAAOE,aACzB,MAAMC,EAASrB,KAAKsB,8BACpB,GAAItB,KAAKD,SAAU,CACfC,KAAKD,SAASsB,EAAOE,QAASvB,KAAKE,SACvC,GAEJsB,WAAaN,IACTlB,KAAKmB,aAAaD,EAAOE,gBAKhCpB,KAAKK,QAAqBoB,gBAAgB,qBAAsB,KAC7D,MAAMC,EAAY1B,KAAKK,QAAqBsB,WAAW,SAEvD,MAAMC,EAAYA,KACd,GAAI5B,KAAKK,QAAS,CACdL,KAAKmB,aAAanB,KAAKK,QAC3B,GAGJ,GAAIqB,EAAU,CACVA,EAASG,aAAaD,EAC1B,CAEAA,MAGJ5B,KAAKU,sBAAsBV,KAAKK,QAASV,EAAeE,GAExD,OAAOG,KAAKK,OAChB,CAKQc,aAAaW,GACjB,MAAMC,EAAMD,EAAUE,YAAc,GAEpC,MAAMC,EAAWF,EAAIG,MAAM,cAAcC,OAGzC,MAAMC,EAAeC,KAAKC,KAAKP,EAAII,OAAS,IAE5C,MAAMI,EAAaF,KAAKG,IAAIP,EAAUG,GAGtCN,EAAUW,QAAQJ,KAAKG,IAAI,EAAGD,EAAa,GAC/C,CAMUP,WACN,OAAOhC,KAAKK,QAAWL,KAAKK,QAAqB2B,WAAa,IAClE,CAKUU,aACN,GAAI1C,KAAKK,SAAWL,KAAKC,SAAU,CAC/B,IAAKD,KAAKI,WAAY,OACtB,MAAMuC,EAAQ3C,KAAKK,QACnBsC,EAAMC,aAAa5C,KAAKC,SAAS4C,IAAIC,UACrCH,EAAMI,YAAY/C,KAAKC,SAASa,SACpC,CACJ,EACH,IAAAkC,EAAA,CAAAC,WAAA,MAAAD,EAAAvD,iBAAA,OAAAuD,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":54,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","TimePlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","isEditable","control","TextControl","id","generateStableId","text","path","type","formatOptions","source","pattern","applyCommonDirectives","TimePicker","value","displayFormat","editable","ui","readOnly","required","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","fieldKey","getValue","applyState","input","setEditable","setRequired","__exports","__esModule"],"sources":["TimePlugin.ts"],"sourcesContent":["/**\n * @file TimePlugin.ts\n * @description Handles rendering logic for Time strings.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport TimePicker from \"sap/m/TimePicker\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering and logic for time inputs.\n */\nexport class TimePlugin extends BasePlugin {\n /**\n * Renders a `sap.m.TimePicker` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured TimePicker control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n \n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n type: \"sap.ui.model.type.Time\",\n formatOptions: {\n source: { pattern: \"HH:mm:ss\" },\n pattern: \"HH:mm:ss\"\n }\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new TimePicker({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: {\n path: `${modelName}>${bindingPath}`,\n type: \"sap.ui.model.type.Time\",\n formatOptions: {\n source: { pattern: \"HH:mm:ss\" },\n pattern: \"HH:mm:ss\"\n }\n },\n displayFormat: \"HH:mm:ss\",\n editable: !fieldMetadata.ui?.readOnly,\n required: fieldMetadata.required,\n change: (oEvent: sap.ui.base.Event) => {\n const val = (oEvent as sap.ui.base.Event).getParameter(\"value\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current time string.\n * @returns {unknown} The time string.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as TimePicker).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const input = this.control as TimePicker;\n input.setEditable(!this.metadata.ui?.readOnly);\n input.setRequired(this.metadata.required);\n }\n }\n}\n"],"mappings":"AAAA,yJAAA,MAKSA,EAAUC,EAAA,cASZ,MAAMC,UAAmBF,EAWrBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAEhB,IAAKK,KAAKE,WAAY,CAElBF,KAAKG,QAAU,IAAIC,EAAY,CAC3BC,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCW,KAAM,CACFC,KAAM,GAAGX,KAAaD,IACtBa,KAAM,yBACNC,cAAe,CACXC,OAAQ,CAAEC,QAAS,YACnBA,QAAS,eAIrBZ,KAAKa,sBAAsBb,KAAKG,QAASR,EAAeE,GACxD,OAAOG,KAAKG,OAChB,CAEAH,KAAKG,QAAU,IAAIW,EAAW,CAC1BT,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCmB,MAAO,CACHP,KAAM,GAAGX,KAAaD,IACtBa,KAAM,yBACNC,cAAe,CACXC,OAAQ,CAAEC,QAAS,YACnBA,QAAS,aAGjBI,cAAe,WACfC,UAAWtB,EAAcuB,IAAIC,SAC7BC,SAAUzB,EAAcyB,SACxBC,OAASC,IACL,MAAMC,EAAOD,EAA6BE,aAAa,SACvD,MAAMC,EAASzB,KAAK0B,8BACpB,GAAI1B,KAAKD,SAAU,CACfC,KAAKD,SAAS0B,EAAOE,QAAS3B,KAAK4B,SACvC,KAIR5B,KAAKa,sBAAsBb,KAAKG,QAASR,EAAeE,GAExD,OAAOG,KAAKG,OAChB,CAMU0B,WACN,OAAO7B,KAAKG,QAAWH,KAAKG,QAAuB0B,WAAa,IACpE,CAKUC,aACN,GAAI9B,KAAKG,SAAWH,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACtB,MAAM6B,EAAQ/B,KAAKG,QACnB4B,EAAMC,aAAahC,KAAKC,SAASiB,IAAIC,UACrCY,EAAME,YAAYjC,KAAKC,SAASmB,SACpC,CACJ,EACH,IAAAc,EAAA,CAAAC,WAAA,MAAAD,EAAAzC,aAAA,OAAAyC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":55,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","VoiceInputControl","_interopRequireDefault","__VoiceInputControl","VoiceInputPlugin","render","metadata","bindingPath","modelName","engineScopeId","onChange","this","fieldKey","replace","isEditable","control","TextControl","id","generateStableId","text","path","formatter","val","applyCommonDirectives","value","schemaMetadata","readOnly","ui","attachCapture","result","validateAndApplyVisualState","isValid","getValue","applyState","setProperty","__exports","__esModule"],"sources":["VoiceInputPlugin.ts"],"sourcesContent":["import { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport VoiceInputControl from \"../../controls/VoiceInputControl\";\nimport TextControl from \"sap/m/Text\";\n\nexport class VoiceInputPlugin extends BasePlugin {\n /**\n * Renders a `VoiceInputControl` component.\n * \n * @param metadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured VoiceInputControl.\n */\n public render(metadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = metadata;\n this.fieldKey = bindingPath.replace('/', '');\n this.modelName = modelName;\n\n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n formatter: (val: unknown) => {\n if (!val || val === \"undefined\" || val === \"null\") return \"\";\n return val;\n }\n }\n }) as Control;\n this.applyCommonDirectives(this.control, metadata, modelName);\n return this.control as Control;\n }\n\n this.control = new VoiceInputControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n schemaMetadata: metadata,\n readOnly: !!metadata.ui?.readOnly\n }) as Control;\n\n this.applyCommonDirectives(this.control, metadata, modelName);\n\n (this.control as VoiceInputControl).attachCapture(() => {\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n });\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current voice transcription text.\n * @returns {unknown} The text string.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as VoiceInputControl).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as sap.ui.core.Control).setProperty(\"readOnly\", !!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,gRAASA,EAAUC,EAAA,oBAGZC,EAAiBC,EAAAC,GAGjB,MAAMC,UAAyBL,EAW3BM,OAAOC,EAA8BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAClHC,KAAKD,SAAWA,EAChBC,KAAKL,SAAWA,EAChBK,KAAKC,SAAWL,EAAYM,QAAQ,IAAK,IACzCF,KAAKH,UAAYA,EAEjB,IAAKG,KAAKG,WAAY,CAElBH,KAAKI,QAAU,IAAIC,EAAY,CAC3BC,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCY,KAAM,CACFC,KAAM,GAAGZ,KAAaD,IACtBc,UAAYC,IACR,IAAKA,GAAOA,IAAQ,aAAeA,IAAQ,OAAQ,MAAO,GAC1D,OAAOA,MAInBX,KAAKY,sBAAsBZ,KAAKI,QAAST,EAAUE,GACnD,OAAOG,KAAKI,OAChB,CAEAJ,KAAKI,QAAU,IAAId,EAAkB,CACjCgB,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCiB,MAAO,IAAIhB,KAAaD,KACxBkB,eAAgBnB,EAChBoB,WAAYpB,EAASqB,IAAID,WAG7Bf,KAAKY,sBAAsBZ,KAAKI,QAAST,EAAUE,GAElDG,KAAKI,QAA8Ba,cAAc,KAC9C,MAAMC,EAASlB,KAAKmB,8BAChB,GAAInB,KAAKD,SAAU,CACfC,KAAKD,SAASmB,EAAOE,QAASpB,KAAKC,SACvC,IAGR,OAAOD,KAAKI,OAChB,CAMUiB,WACN,OAAOrB,KAAKI,QAAWJ,KAAKI,QAA8BiB,WAAa,IAC3E,CAKUC,aACN,GAAItB,KAAKI,SAAWJ,KAAKL,SAAU,CAC/B,IAAKK,KAAKG,WAAY,OACrBH,KAAKI,QAAgCmB,YAAY,aAAcvB,KAAKL,SAASqB,IAAID,SACtF,CACJ,EACH,IAAAS,EAAA,CAAAC,WAAA,MAAAD,EAAA/B,mBAAA,OAAA+B,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":56,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","Logger","____utils_Logger","LiveSearchPlugin","render","fieldMetadata","bindingPath","modelName","this","metadata","input","Input","value","enabled","ui","readOnly","placeholder","showSuggestion","suggest","oEvent","query","getParameter","fetchSuggestions","change","validate","control","vhConfig","valueHelp","url","error","removeAllSuggestionItems","setBusy","fetch","then","res","json","data","keyPath","textPath","lowerQuery","toLowerCase","filteredData","filter","item","textValue","String","includes","forEach","itemData","addSuggestionItem","Item","key","text","catch","err","message","finally","getValue","applyState","setEnabled","__exports","__esModule"],"sources":["LiveSearchPlugin.ts"],"sourcesContent":["/**\n * @file LiveSearchPlugin.ts\n * @description A custom datasource plugin that provides asynchronous live search (autocomplete) functionality.\n */\n\nimport { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata, IRemoteValueHelpConfig } from \"../../interfaces/ISchema\";\nimport Input from \"sap/m/Input\";\nimport Item from \"sap/ui/core/Item\";\nimport Control from \"sap/ui/core/Control\";\nimport { Logger } from \"../../utils/Logger\";\n\n/**\n * A custom datasource plugin that provides asynchronous live search (autocomplete) functionality.\n * As the user types, it fetches suggestions from a remote endpoint.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.datasources\n * @public\n */\nexport class LiveSearchPlugin extends BasePlugin {\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\"): Control {\n this.metadata = fieldMetadata;\n \n const input = new Input({\n value: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n placeholder: \"Type to search...\",\n showSuggestion: true,\n suggest: (oEvent: sap.ui.base.Event) => {\n const query = (oEvent as sap.ui.base.Event).getParameter(\"suggestValue\");\n this.fetchSuggestions(input, query);\n },\n change: (oEvent: sap.ui.base.Event) => {\n this.validate();\n }\n });\n\n this.control = input;\n return this.control as Control;\n }\n\n /**\n * Executes the REST fetch for suggestions based on a query. Can be overridden by mock subclasses.\n * @param input The UI5 Input to populate with suggestions.\n * @param query The text typed by the user.\n */\n protected fetchSuggestions(input: Input, query: string): void {\n const vhConfig = this.metadata?.valueHelp as IRemoteValueHelpConfig;\n if (!vhConfig || !vhConfig.url) {\n Logger.error(\"LiveSearchPlugin requires a valid valueHelp configuration with a URL.\", \"\", \"LiveSearchPlugin\");\n return;\n }\n\n if (!query) {\n input.removeAllSuggestionItems();\n return;\n }\n \n input.setBusy(true);\n \n // In a real application, the query parameter would be passed to the backend (e.g. ?q=query)\n // Here, we simulate fetching and filter locally, but subclasses can override this entirely.\n fetch(vhConfig.url)\n .then(res => res.json())\n .then((data: Record<string, unknown>[]) => {\n const keyPath = vhConfig.keyPath || \"key\";\n const textPath = vhConfig.textPath || \"text\";\n \n input.removeAllSuggestionItems();\n\n // Simple client-side filter for demonstration\n const lowerQuery = query.toLowerCase();\n const filteredData = data.filter(item => {\n const textValue = String(item[textPath] || item[keyPath]).toLowerCase();\n return textValue.includes(lowerQuery);\n });\n \n filteredData.forEach(itemData => {\n input.addSuggestionItem(new Item({ \n key: itemData[keyPath], \n text: itemData[textPath] || itemData[keyPath]\n }));\n });\n })\n .catch(err => {\n Logger.error(\"Failed to load value help from \" + vhConfig.url, err.message, \"LiveSearchPlugin\");\n })\n .finally(() => {\n input.setBusy(false);\n });\n }\n\n /**\n * Retrieves the current input value.\n * @returns {unknown} The input text.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as Input).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n (this.control as Input).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,oMAAA,MAKSA,EAAUC,EAAA,oBAKVC,EAAMC,EAAA,UASR,MAAMC,UAAyBJ,EAC3BK,OAAOC,EAAkCC,EAAqBC,EAAoB,QACrFC,KAAKC,SAAWJ,EAEhB,MAAMK,EAAQ,IAAIC,EAAM,CACpBC,MAAO,IAAIL,KAAaD,KACxBO,SAAUR,EAAcS,IAAIC,SAC5BC,YAAa,oBACbC,eAAgB,KAChBC,QAAUC,IACN,MAAMC,EAASD,EAA6BE,aAAa,gBACzDb,KAAKc,iBAAiBZ,EAAOU,IAEjCG,OAASJ,IACLX,KAAKgB,cAIbhB,KAAKiB,QAAUf,EACf,OAAOF,KAAKiB,OAChB,CAOUH,iBAAiBZ,EAAcU,GACrC,MAAMM,EAAWlB,KAAKC,UAAUkB,UAChC,IAAKD,IAAaA,EAASE,IAAK,CAC5B3B,EAAO4B,MAAM,wEAAyE,GAAI,oBAC1F,MACJ,CAEA,IAAKT,EAAO,CACRV,EAAMoB,2BACN,MACJ,CAEApB,EAAMqB,QAAQ,MAIdC,MAAMN,EAASE,KACVK,KAAKC,GAAOA,EAAIC,QAChBF,KAAMG,IACH,MAAMC,EAAUX,EAASW,SAAW,MACpC,MAAMC,EAAWZ,EAASY,UAAY,OAEtC5B,EAAMoB,2BAGN,MAAMS,EAAanB,EAAMoB,cACzB,MAAMC,EAAeL,EAAKM,OAAOC,IAC7B,MAAMC,EAAYC,OAAOF,EAAKL,IAAaK,EAAKN,IAAUG,cAC1D,OAAOI,EAAUE,SAASP,KAG9BE,EAAaM,QAAQC,IACjBtC,EAAMuC,kBAAkB,IAAIC,EAAK,CAC7BC,IAAKH,EAASX,GACde,KAAMJ,EAASV,IAAaU,EAASX,UAIhDgB,MAAMC,IACHrD,EAAO4B,MAAM,kCAAoCH,EAASE,IAAK0B,EAAIC,QAAS,sBAE/EC,QAAQ,KACL9C,EAAMqB,QAAQ,QAE1B,CAMU0B,WACN,OAAOjD,KAAKiB,QAAWjB,KAAKiB,QAAkBgC,WAAa,IAC/D,CAKUC,aACN,GAAIlD,KAAKiB,SAAWjB,KAAKC,SAAU,CAC9BD,KAAKiB,QAAkBkC,YAAYnD,KAAKC,SAASK,IAAIC,SAC1D,CACJ,EACH,IAAA6C,EAAA,CAAAC,WAAA,MAAAD,EAAAzD,mBAAA,OAAAyD,CAAA","ignoreList":[],"sourceRoot":"plugins/datasources"}},{"offset":{"line":57,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","ODataListBindingPlugin","render","fieldMetadata","bindingPath","modelName","this","metadata","args","ui","path","key","text","control","ComboBox","selectedKey","enabled","readOnly","placeholder","label","change","oEvent","val","getParameter","getKey","validate","bindAggregation","template","Item","templateShareable","getValue","getSelectedKey","applyState","setEnabled","__exports","__esModule"],"sources":["ODataListBindingPlugin.ts"],"sourcesContent":["/**\n * @file ODataListBindingPlugin.ts\n * @description A custom datasource plugin that binds a ComboBox to an OData EntitySet.\n */\n\nimport { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport ComboBox from \"sap/m/ComboBox\";\nimport Item from \"sap/ui/core/Item\";\nimport Control from \"sap/ui/core/Control\";\n\n/**\n * Renders a ComboBox natively bound to an OData Model entity set.\n * Expects args: { path: \"/Categories\", key: \"ID\", text: \"Name\" }\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.datasources\n * @public\n */\nexport class ODataListBindingPlugin extends BasePlugin {\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\"): Control {\n this.metadata = fieldMetadata;\n \n const args = fieldMetadata.ui?.args || { path: \"/\", key: \"ID\", text: \"Name\" };\n \n this.control = new ComboBox({\n selectedKey: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n placeholder: fieldMetadata.ui?.label || \"Select...\",\n change: (oEvent: sap.ui.base.Event) => {\n const val = (oEvent as sap.ui.base.Event).getParameter(\"selectedItem\")?.getKey();\n this.validate();\n }\n });\n\n // Natively bind aggregation to the default model (OData)\n (this.control as ComboBox).bindAggregation(\"items\", {\n path: args.path,\n template: new Item({\n key: `{${args.key}}`,\n text: `{${args.text}}`\n }),\n templateShareable: false\n });\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current selected key.\n * @returns {unknown} The selected key.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as ComboBox).getSelectedKey() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n (this.control as ComboBox).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,sLAAA,MAKSA,EAAUC,EAAA,cAaZ,MAAMC,UAA+BF,EACjCG,OAAOC,EAAkCC,EAAqBC,EAAoB,QACrFC,KAAKC,SAAWJ,EAEhB,MAAMK,EAAOL,EAAcM,IAAID,MAAQ,CAAEE,KAAM,IAAKC,IAAK,KAAMC,KAAM,QAErEN,KAAKO,QAAU,IAAIC,EAAS,CACxBC,YAAa,IAAIV,KAAaD,KAC9BY,SAAUb,EAAcM,IAAIQ,SAC5BC,YAAaf,EAAcM,IAAIU,OAAS,YACxCC,OAASC,IACL,MAAMC,EAAOD,EAA6BE,aAAa,iBAAiBC,SACxElB,KAAKmB,cAKZnB,KAAKO,QAAqBa,gBAAgB,QAAS,CAChDhB,KAAMF,EAAKE,KACXiB,SAAU,IAAIC,EAAK,CACfjB,IAAK,IAAIH,EAAKG,OACdC,KAAM,IAAIJ,EAAKI,UAEnBiB,kBAAmB,QAGvB,OAAOvB,KAAKO,OAChB,CAMUiB,WACN,OAAOxB,KAAKO,QAAWP,KAAKO,QAAqBkB,iBAAmB,IACxE,CAKUC,aACN,GAAI1B,KAAKO,SAAWP,KAAKC,SAAU,CAC9BD,KAAKO,QAAqBoB,YAAY3B,KAAKC,SAASE,IAAIQ,SAC7D,CACJ,EACH,IAAAiB,EAAA,CAAAC,WAAA,MAAAD,EAAAjC,yBAAA,OAAAiC,CAAA","ignoreList":[],"sourceRoot":"plugins/datasources"}},{"offset":{"line":58,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","Logger","____utils_Logger","RemoteDropdownPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","config","valueHelp","url","warn","sap","m","Text","text","isEditable","ui","requireSync","TextControl","require","control","id","generateStableId","applyCommonDirectives","select","Select","selectedKey","enabled","readOnly","forceSelection","busy","change","oEvent","result","validate","isValid","fieldKey","addItem","Item","key","fetch","then","res","ok","Error","status","json","data","arr","Array","isArray","value","forEach","item","k","keyPath","t","textPath","String","setBusy","catch","err","error","message","getValue","getSelectedKey","applyState","setEnabled","__exports","__esModule"],"sources":["RemoteDropdownPlugin.ts"],"sourcesContent":["/**\n * @file RemoteDropdownPlugin.ts\n * @description Renders a sap.m.Select that fetches valueHelp remotely via a JSON URL.\n */\n\nimport { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata, IRemoteValueHelpConfig } from \"../../interfaces/ISchema\";\nimport Select from \"sap/m/Select\";\nimport Item from \"sap/ui/core/Item\";\nimport Control from \"sap/ui/core/Control\";\nimport { Logger } from \"../../utils/Logger\";\n\n/**\n * Handles rendering logic for dropdown inputs fetching data remotely.\n * Maps a URL response array to `sap.ui.core.Item` elements.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.datasources\n * @public\n */\nexport class RemoteDropdownPlugin extends BasePlugin {\n \n /**\n * Renders a `Select` dropdown that fetches data remotely.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured Select control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n\n const config = fieldMetadata.valueHelp as IRemoteValueHelpConfig;\n if (!config || !config.url) {\n Logger.warn(\"[MetaUI RemoteDropdownPlugin] No valid URL provided for remoteDropdown.\");\n return new sap.m.Text({ text: \"Error: No URL provided\" }) as Control;\n }\n \n if (!this.isEditable) {\n sap.ui.requireSync(\"sap/m/Text\");\n const TextControl = sap.ui.require(\"sap/m/Text\");\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}` // We might not have the text mapping synchronously\n });\n \n // Optionally, we could fetch data and update the text formatter here\n \n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n const select = new Select({\n id: this.generateStableId(engineScopeId, bindingPath),\n selectedKey: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n forceSelection: false,\n busy: true, // Show busy indicator while fetching\n change: (oEvent: sap.ui.base.Event) => {\n const result = this.validate();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n // Add empty placeholder\n select.addItem(new Item({ key: \"\", text: \"--- Select ---\" }));\n\n // Fetch data remotely\n fetch(config.url)\n .then(res => {\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n })\n .then(data => {\n const arr = Array.isArray(data) ? data : (data.value || []);\n arr.forEach((item: Record<string, unknown>) => {\n const k = config.keyPath ? item[config.keyPath] : item;\n const t = config.textPath ? item[config.textPath] : item;\n select.addItem(new Item({ key: String(k), text: String(t) }));\n });\n select.setBusy(false);\n })\n .catch(err => {\n Logger.error(`[MetaUI RemoteDropdownPlugin] Failed to fetch remote data from ${config.url}`, err.message);\n select.addItem(new Item({ key: \"\", text: \"Error loading data\" }));\n select.setBusy(false);\n });\n\n this.control = select;\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n /**\n * Retrieves the current selected key.\n * @returns {unknown} The selected key.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as Select).getSelectedKey() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const select = this.control as Select;\n select.setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,yMAAA,MAKSA,EAAUC,EAAA,oBAKVC,EAAMC,EAAA,UASR,MAAMC,UAA6BJ,EAY/BK,OAAOC,EAAkCC,EAAqBC,EAAoB,OAAQC,EAAwBC,GACrHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAEhB,MAAMO,EAASP,EAAcQ,UAC7B,IAAKD,IAAWA,EAAOE,IAAK,CACxBb,EAAOc,KAAK,2EACZ,OAAO,IAAIC,IAAIC,EAAEC,KAAK,CAAEC,KAAM,0BAClC,CAEA,IAAKT,KAAKU,WAAY,CAClBJ,IAAIK,GAAGC,YAAY,cACnB,MAAMC,EAAcP,IAAIK,GAAGG,QAAQ,cAEnCd,KAAKe,QAAU,IAAIF,EAAY,CAC3BG,GAAIhB,KAAKiB,iBAAiBnB,EAAeF,GACzCa,KAAM,IAAIZ,KAAaD,OAK3BI,KAAKkB,sBAAsBlB,KAAKe,QAASpB,EAAeE,GACxD,OAAOG,KAAKe,OAChB,CAEA,MAAMI,EAAS,IAAIC,EAAO,CACtBJ,GAAIhB,KAAKiB,iBAAiBnB,EAAeF,GACzCyB,YAAa,IAAIxB,KAAaD,KAC9B0B,SAAU3B,EAAcgB,IAAIY,SAC5BC,eAAgB,MAChBC,KAAM,KACNC,OAASC,IACL,MAAMC,EAAS5B,KAAK6B,WACpB,GAAI7B,KAAKD,SAAU,CACfC,KAAKD,SAAS6B,EAAOE,QAAS9B,KAAK+B,SACvC,KAKRZ,EAAOa,QAAQ,IAAIC,EAAK,CAAEC,IAAK,GAAIzB,KAAM,oBAGzC0B,MAAMjC,EAAOE,KACRgC,KAAKC,IACF,IAAKA,EAAIC,GAAI,MAAM,IAAIC,MAAM,QAAQF,EAAIG,UACzC,OAAOH,EAAII,SAEdL,KAAKM,IACF,MAAMC,EAAMC,MAAMC,QAAQH,GAAQA,EAAQA,EAAKI,OAAS,GACxDH,EAAII,QAASC,IACT,MAAMC,EAAI/C,EAAOgD,QAAUF,EAAK9C,EAAOgD,SAAWF,EAClD,MAAMG,EAAIjD,EAAOkD,SAAWJ,EAAK9C,EAAOkD,UAAYJ,EACpD7B,EAAOa,QAAQ,IAAIC,EAAK,CAAEC,IAAKmB,OAAOJ,GAAIxC,KAAM4C,OAAOF,QAE3DhC,EAAOmC,QAAQ,SAElBC,MAAMC,IACHjE,EAAOkE,MAAM,kEAAkEvD,EAAOE,MAAOoD,EAAIE,SACjGvC,EAAOa,QAAQ,IAAIC,EAAK,CAAEC,IAAK,GAAIzB,KAAM,wBACzCU,EAAOmC,QAAQ,SAGvBtD,KAAKe,QAAUI,EACfnB,KAAKkB,sBAAsBlB,KAAKe,QAASpB,EAAeE,GACxD,OAAOG,KAAKe,OAChB,CAMU4C,WACN,OAAO3D,KAAKe,QAAWf,KAAKe,QAAmB6C,iBAAmB,IACtE,CAKUC,aACN,GAAI7D,KAAKe,SAAWf,KAAKC,SAAU,CAC/B,IAAKD,KAAKU,WAAY,OACtB,MAAMS,EAASnB,KAAKe,QACpBI,EAAO2C,YAAY9D,KAAKC,SAASU,IAAIY,SACzC,CACJ,EACH,IAAAwC,EAAA,CAAAC,WAAA,MAAAD,EAAAtE,uBAAA,OAAAsE,CAAA","ignoreList":[],"sourceRoot":"plugins/datasources"}},{"offset":{"line":59,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","Logger","____utils_Logger","RemoteValueHelpPlugin","isLoaded","render","fieldMetadata","bindingPath","modelName","this","metadata","comboBox","ComboBox","selectedKey","enabled","ui","readOnly","placeholder","change","oEvent","item","getParameter","val","getKey","validate","attachEventOnce","fetchData","control","vhConfig","valueHelp","url","error","setBusy","fetch","then","res","json","data","keyPath","textPath","forEach","itemData","addItem","Item","key","text","catch","err","message","finally","getValue","getSelectedKey","applyState","setEnabled","__exports","__esModule"],"sources":["RemoteValueHelpPlugin.ts"],"sourcesContent":["/**\n * @file RemoteValueHelpPlugin.ts\n * @description A custom datasource plugin that simulates fetching data from a remote server.\n */\n\nimport { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata, IRemoteValueHelpConfig } from \"../../interfaces/ISchema\";\nimport ComboBox from \"sap/m/ComboBox\";\nimport Item from \"sap/ui/core/Item\";\nimport Control from \"sap/ui/core/Control\";\nimport { Logger } from \"../../utils/Logger\";\n\n/**\n * A custom datasource plugin that simulates fetching data from a remote server.\n * Proves out custom data sources that dynamically load value help.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.datasources\n * @public\n */\nexport class RemoteValueHelpPlugin extends BasePlugin {\n private isLoaded = false;\n\n /**\n * Renders a `ComboBox` that simulates fetching data from a remote server.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @returns {Control} The configured ComboBox control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\"): Control {\n this.metadata = fieldMetadata;\n \n const comboBox = new ComboBox({\n selectedKey: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n placeholder: \"Select a country...\",\n change: (oEvent: sap.ui.base.Event) => {\n const item = (oEvent as sap.ui.base.Event).getParameter(\"selectedItem\");\n const val = item ? item.getKey() : (oEvent as sap.ui.base.Event).getParameter(\"value\"); // Allow free text as well\n this.validate();\n }\n });\n\n // Perform an async load against the REST endpoint\n comboBox.attachEventOnce(\"loadItems\", () => {\n this.fetchData(comboBox);\n });\n\n this.control = comboBox;\n return this.control as Control;\n }\n\n /**\n * Executes the REST fetch for data.\n * @param comboBox The UI5 ComboBox to populate.\n */\n protected fetchData(comboBox: ComboBox): void {\n const vhConfig = this.metadata?.valueHelp as IRemoteValueHelpConfig;\n if (!vhConfig || !vhConfig.url) {\n Logger.error(\"RemoteValueHelpPlugin requires a valid valueHelp configuration with a URL.\", \"\", \"RemoteValueHelpPlugin\");\n return;\n }\n \n comboBox.setBusy(true);\n \n fetch(vhConfig.url)\n .then(res => res.json())\n .then((data: Record<string, unknown>[]) => {\n const keyPath = vhConfig.keyPath || \"key\";\n const textPath = vhConfig.textPath || \"text\";\n \n data.forEach(itemData => {\n comboBox.addItem(new Item({ \n key: itemData[keyPath], \n text: itemData[textPath] || itemData[keyPath]\n }));\n });\n })\n .catch(err => {\n Logger.error(\"Failed to load value help from \" + vhConfig.url, err.message, \"RemoteValueHelpPlugin\");\n })\n .finally(() => {\n comboBox.setBusy(false);\n this.isLoaded = true;\n });\n }\n\n /**\n * Retrieves the current selected key.\n * @returns {unknown} The selected key.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as ComboBox).getSelectedKey() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n (this.control as ComboBox).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,4MAAA,MAKSA,EAAUC,EAAA,oBAKVC,EAAMC,EAAA,UASR,MAAMC,UAA8BJ,EAC/BK,SAAW,MAUZC,OAAOC,EAAkCC,EAAqBC,EAAoB,QACrFC,KAAKC,SAAWJ,EAEhB,MAAMK,EAAW,IAAIC,EAAS,CAC1BC,YAAa,IAAIL,KAAaD,KAC9BO,SAAUR,EAAcS,IAAIC,SAC5BC,YAAa,sBACbC,OAASC,IACL,MAAMC,EAAQD,EAA6BE,aAAa,gBACxD,MAAMC,EAAMF,EAAOA,EAAKG,SAAYJ,EAA6BE,aAAa,SAC9EZ,KAAKe,cAKbb,EAASc,gBAAgB,YAAa,KAClChB,KAAKiB,UAAUf,KAGnBF,KAAKkB,QAAUhB,EACf,OAAOF,KAAKkB,OAChB,CAMUD,UAAUf,GAChB,MAAMiB,EAAWnB,KAAKC,UAAUmB,UAChC,IAAKD,IAAaA,EAASE,IAAK,CAC5B7B,EAAO8B,MAAM,6EAA8E,GAAI,yBAC/F,MACJ,CAEApB,EAASqB,QAAQ,MAEjBC,MAAML,EAASE,KACVI,KAAKC,GAAOA,EAAIC,QAChBF,KAAMG,IACH,MAAMC,EAAUV,EAASU,SAAW,MACpC,MAAMC,EAAWX,EAASW,UAAY,OAEtCF,EAAKG,QAAQC,IACT9B,EAAS+B,QAAQ,IAAIC,EAAK,CACtBC,IAAKH,EAASH,GACdO,KAAMJ,EAASF,IAAaE,EAASH,UAIhDQ,MAAMC,IACH9C,EAAO8B,MAAM,kCAAoCH,EAASE,IAAKiB,EAAIC,QAAS,2BAE/EC,QAAQ,KACLtC,EAASqB,QAAQ,OACjBvB,KAAKL,SAAW,MAE5B,CAMU8C,WACN,OAAOzC,KAAKkB,QAAWlB,KAAKkB,QAAqBwB,iBAAmB,IACxE,CAKUC,aACN,GAAI3C,KAAKkB,SAAWlB,KAAKC,SAAU,CAC9BD,KAAKkB,QAAqB0B,YAAY5C,KAAKC,SAASK,IAAIC,SAC7D,CACJ,EACH,IAAAsC,EAAA,CAAAC,WAAA,MAAAD,EAAAnD,wBAAA,OAAAmD,CAAA","ignoreList":[],"sourceRoot":"plugins/datasources"}},{"offset":{"line":60,"column":0},"map":{"version":3,"names":["CurrencyFormatterPlugin","constructor","this","currencyFormat","NumberFormat","getCurrencyInstance","showMeasure","format","rawValue","args","undefined","__exports","__esModule"],"sources":["CurrencyFormatterPlugin.ts"],"sourcesContent":["/**\n * @file CurrencyFormatterPlugin.ts\n * @description Standard data formatter for currency values.\n */\n\nimport { IFormatter } from \"../../interfaces/IPipeline\";\nimport NumberFormat from \"sap/ui/core/format/NumberFormat\";\n\n/**\n * Standard data formatter for currency values.\n * Uses sap.ui.core.format.NumberFormat to format raw numbers into localized currency strings.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.formatters\n * @public\n */\nexport class CurrencyFormatterPlugin implements IFormatter {\n private currencyFormat: NumberFormat;\n\n constructor() {\n this.currencyFormat = NumberFormat.getCurrencyInstance({\n showMeasure: false\n });\n }\n\n /**\n * Formats raw JSON model data into a UI-friendly currency string.\n * @param rawValue The raw numeric value from the JSON payload.\n * @returns The formatted string for the UI control.\n */\n public format(rawValue: unknown, args?: unknown): string {\n if (rawValue === null || rawValue === undefined) {\n return \"\";\n }\n return \"$\" + this.currencyFormat.format(rawValue as number);\n }\n}\n"],"mappings":"AAAA,uJAeO,MAAMA,EAGTC,cACIC,KAAKC,eAAiBC,EAAaC,oBAAoB,CACnDC,YAAa,OAErB,CAOOC,OAAOC,EAAmBC,GAC7B,GAAID,IAAa,MAAQA,IAAaE,UAAW,CAC7C,MAAO,EACX,CACA,MAAO,IAAMR,KAAKC,eAAeI,OAAOC,EAC5C,EACH,IAAAG,EAAA,CAAAC,WAAA,MAAAD,EAAAX,0BAAA,OAAAW,CAAA","ignoreList":[],"sourceRoot":"plugins/formatters"}},{"offset":{"line":61,"column":0},"map":{"version":3,"names":["DateFormatterPlugin","constructor","this","dateFormat","DateFormat","getDateInstance","style","format","rawValue","args","dateObj","Date","e","__exports","__esModule"],"sources":["DateFormatterPlugin.ts"],"sourcesContent":["/**\n * @file DateFormatterPlugin.ts\n * @description Standard data formatter for dates.\n */\n\nimport { IFormatter } from \"../../interfaces/IPipeline\";\nimport DateFormat from \"sap/ui/core/format/DateFormat\";\n\n/**\n * Formats ISO date strings to localized Medium formats (e.g., \"Oct 15, 2026\").\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.formatters\n * @public\n */\nexport class DateFormatterPlugin implements IFormatter {\n private dateFormat: DateFormat;\n\n constructor() {\n this.dateFormat = DateFormat.getDateInstance({ style: \"medium\" });\n }\n\n /**\n * Formats raw JSON model data into a medium-style date string.\n * @param rawValue The raw date string.\n * @returns The formatted string for the UI control.\n */\n public format(rawValue: unknown, args?: unknown): string {\n if (!rawValue) return \"\";\n try {\n const dateObj = new Date(rawValue as string);\n return this.dateFormat.format(dateObj);\n } catch (e) {\n return rawValue as string; // Fallback to raw string if invalid date\n }\n }\n}\n"],"mappings":"AAAA,iJAcO,MAAMA,EAGTC,cACIC,KAAKC,WAAaC,EAAWC,gBAAgB,CAAEC,MAAO,UAC1D,CAOOC,OAAOC,EAAmBC,GAC7B,IAAKD,EAAU,MAAO,GACtB,IACI,MAAME,EAAU,IAAIC,KAAKH,GACzB,OAAON,KAAKC,WAAWI,OAAOG,EAClC,CAAE,MAAOE,GACL,OAAOJ,CACX,CACJ,EACH,IAAAK,EAAA,CAAAC,WAAA,MAAAD,EAAAb,sBAAA,OAAAa,CAAA","ignoreList":[],"sourceRoot":"plugins/formatters"}},{"offset":{"line":62,"column":0},"map":{"version":3,"names":["PhoneFormatterPlugin","format","rawValue","args","String","cleaned","replace","match","__exports","__esModule"],"sources":["PhoneFormatterPlugin.ts"],"sourcesContent":["/**\n * @file PhoneFormatterPlugin.ts\n * @description Standard data formatter for phone numbers.\n */\n\nimport { IFormatter } from \"../../interfaces/IPipeline\";\n\n/**\n * Simple mask for 10-digit phone numbers (e.g. 5551234567 -> (555) 123-4567).\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.formatters\n * @public\n */\nexport class PhoneFormatterPlugin implements IFormatter {\n /**\n * Formats raw JSON model data into a masked phone number.\n * @param rawValue The raw phone string.\n * @returns The formatted string for the UI control.\n */\n public format(rawValue: unknown, args?: unknown): string {\n if (!rawValue || typeof rawValue !== \"string\") return String(rawValue || \"\");\n \n const cleaned = ('' + rawValue).replace(/\\D/g, '');\n const match = cleaned.match(/^(\\d{3})(\\d{3})(\\d{4})$/);\n \n if (match) {\n return '(' + match[1] + ') ' + match[2] + '-' + match[3];\n }\n \n return rawValue as string;\n }\n}\n"],"mappings":"AAAA,kHAaO,MAAMA,EAMFC,OAAOC,EAAmBC,GAC7B,IAAKD,UAAmBA,IAAa,SAAU,OAAOE,OAAOF,GAAY,IAEzE,MAAMG,GAAW,GAAKH,GAAUI,QAAQ,MAAO,IAC/C,MAAMC,EAAQF,EAAQE,MAAM,2BAE5B,GAAIA,EAAO,CACP,MAAO,IAAMA,EAAM,GAAK,KAAOA,EAAM,GAAK,IAAMA,EAAM,EAC1D,CAEA,OAAOL,CACX,EACH,IAAAM,EAAA,CAAAC,WAAA,MAAAD,EAAAR,uBAAA,OAAAQ,CAAA","ignoreList":[],"sourceRoot":"plugins/formatters"}},{"offset":{"line":63,"column":0},"map":{"version":3,"names":["TextCaseFormatterPlugin","format","rawValue","args","String","toUpperCase","__exports","__esModule"],"sources":["TextCaseFormatterPlugin.ts"],"sourcesContent":["/**\n * @file TextCaseFormatterPlugin.ts\n * @description Standard data formatter for text casing.\n */\n\nimport { IFormatter } from \"../../interfaces/IPipeline\";\n\n/**\n * Transforms text to UPPERCASE, lowercase, or Title Case.\n * Defaults to uppercase.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.formatters\n * @public\n */\nexport class TextCaseFormatterPlugin implements IFormatter {\n /**\n * Formats raw JSON model data into uppercase.\n * @param rawValue The raw string.\n * @returns The uppercase formatted string for the UI control.\n */\n public format(rawValue: unknown, args?: unknown): string {\n if (typeof rawValue !== \"string\") return String(rawValue || \"\");\n \n // Default to uppercase if no specific arg could be easily parsed by simple formatter \n // (could be enhanced to support schema args if formatters allowed args).\n return rawValue.toUpperCase();\n }\n}\n"],"mappings":"AAAA,qHAcO,MAAMA,EAMFC,OAAOC,EAAmBC,GAC7B,UAAWD,IAAa,SAAU,OAAOE,OAAOF,GAAY,IAI5D,OAAOA,EAASG,aACpB,EACH,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAAN,0BAAA,OAAAM,CAAA","ignoreList":[],"sourceRoot":"plugins/formatters"}},{"offset":{"line":64,"column":0},"map":{"version":3,"names":["EmailValidatorPlugin","validate","parsedValue","args","isValid","emailRegex","test","errorMessage","__exports","__esModule"],"sources":["EmailValidatorPlugin.ts"],"sourcesContent":["/**\n * @file EmailValidatorPlugin.ts\n * @description Standard business logic validator for email addresses.\n */\n\nimport { IValidator, IValidationResult } from \"../../interfaces/IPipeline\";\n\n/**\n * Standard business logic validator for email addresses.\n * Extracts the email regex validation logic into a standalone, modular plugin.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.validators\n * @public\n */\nexport class EmailValidatorPlugin implements IValidator {\n /**\n * Validates parsed data before it enters the JSON model.\n * @param parsedValue The cleaned data to validate.\n * @param args Optional arguments provided in the schema.\n * @returns IValidationResult containing status and optional error message.\n */\n public validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (!parsedValue) return { isValid: true }; // Let RequiredValidator handle empty\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (typeof parsedValue !== \"string\" || !emailRegex.test(parsedValue)) {\n return { isValid: false, errorMessage: \"Please enter a valid email address.\" };\n }\n return { isValid: true };\n }\n}\n"],"mappings":"AAAA,kHAcO,MAAMA,EAOFC,SAASC,EAAsBC,GAClC,IAAKD,EAAa,MAAO,CAAEE,QAAS,MACpC,MAAMC,EAAa,6BACnB,UAAWH,IAAgB,WAAaG,EAAWC,KAAKJ,GAAc,CAClE,MAAO,CAAEE,QAAS,MAAOG,aAAc,sCAC3C,CACA,MAAO,CAAEH,QAAS,KACtB,EACH,IAAAI,EAAA,CAAAC,WAAA,MAAAD,EAAAR,uBAAA,OAAAQ,CAAA","ignoreList":[],"sourceRoot":"plugins/validators"}},{"offset":{"line":65,"column":0},"map":{"version":3,"names":["IbanValidatorPlugin","validate","parsedValue","args","isValid","ibanRegex","test","replace","toUpperCase","errorMessage","__exports","__esModule"],"sources":["IbanValidatorPlugin.ts"],"sourcesContent":["/**\n * @file IbanValidatorPlugin.ts\n * @description Standard business logic validator for International Bank Account Numbers.\n */\n\nimport { IValidator, IValidationResult } from \"../../interfaces/IPipeline\";\n\n/**\n * Validates a standard IBAN string.\n * This provides a simplified check for demonstration (starts with 2 chars, followed by digits/chars).\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.validators\n * @public\n */\nexport class IbanValidatorPlugin implements IValidator {\n /**\n * Validates parsed data before it enters the JSON model.\n * @param parsedValue The cleaned data to validate.\n * @param args Optional arguments provided in the schema.\n * @returns IValidationResult containing status and optional error message.\n */\n public validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (!parsedValue) return { isValid: true }; // Let RequiredValidator handle empty\n \n // Very basic IBAN structure regex (e.g. DE89370400440532013000)\n // A true IBAN check requires modulo 97 arithmetic which is out of scope for a basic mock.\n const ibanRegex = /^[A-Z]{2}\\d{2}[A-Z0-9]{1,30}$/;\n \n if (typeof parsedValue !== \"string\" || !ibanRegex.test(parsedValue.replace(/\\s+/g, '').toUpperCase())) {\n return { isValid: false, errorMessage: \"Please enter a valid IBAN.\" };\n }\n \n return { isValid: true };\n }\n}\n"],"mappings":"AAAA,iHAcO,MAAMA,EAOFC,SAASC,EAAsBC,GAClC,IAAKD,EAAa,MAAO,CAAEE,QAAS,MAIpC,MAAMC,EAAY,gCAElB,UAAWH,IAAgB,WAAaG,EAAUC,KAAKJ,EAAYK,QAAQ,OAAQ,IAAIC,eAAgB,CACnG,MAAO,CAAEJ,QAAS,MAAOK,aAAc,6BAC3C,CAEA,MAAO,CAAEL,QAAS,KACtB,EACH,IAAAM,EAAA,CAAAC,WAAA,MAAAD,EAAAV,sBAAA,OAAAU,CAAA","ignoreList":[],"sourceRoot":"plugins/validators"}},{"offset":{"line":66,"column":0},"map":{"version":3,"names":["MinLengthValidatorPlugin","validate","parsedValue","args","isValid","length","errorMessage","__exports","__esModule"],"sources":["MinLengthValidatorPlugin.ts"],"sourcesContent":["/**\n * @file MinLengthValidatorPlugin.ts\n * @description Standard business logic validator for string minimum lengths.\n */\n\nimport { IValidator, IValidationResult } from \"../../interfaces/IPipeline\";\n\n/**\n * Ensures string length meets a minimum threshold.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.validators\n * @public\n */\nexport class MinLengthValidatorPlugin implements IValidator {\n /**\n * Validates parsed data before it enters the JSON model.\n * @param parsedValue The cleaned data to validate.\n * @param args Optional arguments provided in the schema.\n * @returns IValidationResult containing status and optional error message.\n */\n public validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (!parsedValue) return { isValid: true }; // Let RequiredValidator handle empty\n if (typeof args !== \"number\") return { isValid: true }; // Invalid config\n\n if (typeof parsedValue === \"string\" && parsedValue.length < args) {\n return { isValid: false, errorMessage: `Minimum length is ${args} characters.` };\n }\n \n return { isValid: true };\n }\n}\n"],"mappings":"AAAA,sHAaO,MAAMA,EAOFC,SAASC,EAAsBC,GAClC,IAAKD,EAAa,MAAO,CAAEE,QAAS,MACpC,UAAWD,IAAS,SAAU,MAAO,CAAEC,QAAS,MAEhD,UAAWF,IAAgB,UAAYA,EAAYG,OAASF,EAAM,CAC9D,MAAO,CAAEC,QAAS,MAAOE,aAAc,qBAAqBH,gBAChE,CAEA,MAAO,CAAEC,QAAS,KACtB,EACH,IAAAG,EAAA,CAAAC,WAAA,MAAAD,EAAAP,2BAAA,OAAAO,CAAA","ignoreList":[],"sourceRoot":"plugins/validators"}},{"offset":{"line":67,"column":0},"map":{"version":3,"names":["PatternValidatorPlugin","validate","parsedValue","args","isValid","regex","RegExp","test","errorMessage","e","__exports","__esModule"],"sources":["PatternValidatorPlugin.ts"],"sourcesContent":["/**\n * @file PatternValidatorPlugin.ts\n * @description Standard business logic validator for Regex patterns.\n */\n\nimport { IValidator, IValidationResult } from \"../../interfaces/IPipeline\";\n\n/**\n * Validates a string against a regular expression pattern provided in the schema args.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.validators\n * @public\n */\nexport class PatternValidatorPlugin implements IValidator {\n /**\n * Validates parsed data before it enters the JSON model.\n * @param parsedValue The cleaned data to validate.\n * @param args Optional arguments provided in the schema.\n * @returns IValidationResult containing status and optional error message.\n */\n public validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (!parsedValue) return { isValid: true }; // Let RequiredValidator handle empty\n if (typeof args !== \"string\") {\n return { isValid: true }; // Invalid config, skip\n }\n\n try {\n const regex = new RegExp(args);\n if (typeof parsedValue !== \"string\" || !regex.test(parsedValue)) {\n return { isValid: false, errorMessage: `Input does not match the required pattern.` };\n }\n } catch (e) {\n // Invalid regex string provided\n return { isValid: false, errorMessage: `Schema configuration error: Invalid regex pattern.` };\n }\n \n return { isValid: true };\n }\n}\n"],"mappings":"AAAA,oHAaO,MAAMA,EAOFC,SAASC,EAAsBC,GAClC,IAAKD,EAAa,MAAO,CAAEE,QAAS,MACpC,UAAWD,IAAS,SAAU,CAC1B,MAAO,CAAEC,QAAS,KACtB,CAEA,IACI,MAAMC,EAAQ,IAAIC,OAAOH,GACzB,UAAWD,IAAgB,WAAaG,EAAME,KAAKL,GAAc,CAC7D,MAAO,CAAEE,QAAS,MAAOI,aAAc,6CAC3C,CACJ,CAAE,MAAOC,GAEL,MAAO,CAAEL,QAAS,MAAOI,aAAc,qDAC3C,CAEA,MAAO,CAAEJ,QAAS,KACtB,EACH,IAAAM,EAAA,CAAAC,WAAA,MAAAD,EAAAV,yBAAA,OAAAU,CAAA","ignoreList":[],"sourceRoot":"plugins/validators"}},{"offset":{"line":68,"column":0},"map":{"version":3,"names":["RangeValidatorPlugin","validate","parsedValue","args","undefined","isValid","rangeArgs","min","max","errorMessage","__exports","__esModule"],"sources":["RangeValidatorPlugin.ts"],"sourcesContent":["/**\n * @file RangeValidatorPlugin.ts\n * @description Standard business logic validator for numeric ranges.\n */\n\nimport { IValidator, IValidationResult } from \"../../interfaces/IPipeline\";\n\n/**\n * Ensures a numeric value falls within an optionally provided min and max range.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.validators\n * @public\n */\nexport class RangeValidatorPlugin implements IValidator {\n /**\n * Validates parsed data before it enters the JSON model.\n * @param parsedValue The cleaned data to validate.\n * @param args Optional arguments provided in the schema.\n * @returns IValidationResult containing status and optional error message.\n */\n public validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (parsedValue === null || parsedValue === undefined) return { isValid: true }; \n if (typeof parsedValue !== \"number\") return { isValid: true };\n\n const rangeArgs = args as { min?: number, max?: number } | undefined;\n const min = rangeArgs?.min;\n const max = rangeArgs?.max;\n\n if (min !== undefined && typeof min === \"number\" && parsedValue < min) {\n return { isValid: false, errorMessage: `Value must be greater than or equal to ${min}.` };\n }\n\n if (max !== undefined && typeof max === \"number\" && parsedValue > max) {\n return { isValid: false, errorMessage: `Value must be less than or equal to ${max}.` };\n }\n \n return { isValid: true };\n }\n}\n"],"mappings":"AAAA,kHAaO,MAAMA,EAOFC,SAASC,EAAsBC,GAClC,GAAID,IAAgB,MAAQA,IAAgBE,UAAW,MAAO,CAAEC,QAAS,MACzE,UAAWH,IAAgB,SAAU,MAAO,CAAEG,QAAS,MAEvD,MAAMC,EAAYH,EAClB,MAAMI,EAAMD,GAAWC,IACvB,MAAMC,EAAMF,GAAWE,IAEvB,GAAID,IAAQH,kBAAoBG,IAAQ,UAAYL,EAAcK,EAAK,CACnE,MAAO,CAAEF,QAAS,MAAOI,aAAc,0CAA0CF,KACrF,CAEA,GAAIC,IAAQJ,kBAAoBI,IAAQ,UAAYN,EAAcM,EAAK,CACnE,MAAO,CAAEH,QAAS,MAAOI,aAAc,uCAAuCD,KAClF,CAEA,MAAO,CAAEH,QAAS,KACtB,EACH,IAAAK,EAAA,CAAAC,WAAA,MAAAD,EAAAV,uBAAA,OAAAU,CAAA","ignoreList":[],"sourceRoot":"plugins/validators"}},{"offset":{"line":69,"column":0},"map":{"version":3,"names":["UrlValidatorPlugin","validate","parsedValue","args","isValid","url","URL","protocol","errorMessage","e","__exports","__esModule"],"sources":["UrlValidatorPlugin.ts"],"sourcesContent":["/**\n * @file UrlValidatorPlugin.ts\n * @description Standard business logic validator for URL formats.\n */\n\nimport { IValidator, IValidationResult } from \"../../interfaces/IPipeline\";\n\n/**\n * Ensures a string is a valid HTTP/HTTPS URL.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.validators\n * @public\n */\nexport class UrlValidatorPlugin implements IValidator {\n /**\n * Validates parsed data before it enters the JSON model.\n * @param parsedValue The cleaned data to validate.\n * @param args Optional arguments provided in the schema.\n * @returns IValidationResult containing status and optional error message.\n */\n public validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (!parsedValue) return { isValid: true }; // Let RequiredValidator handle empty\n if (typeof parsedValue !== \"string\") return { isValid: true };\n \n try {\n const url = new URL(parsedValue);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n return { isValid: false, errorMessage: \"URL must use http or https protocol.\" };\n }\n } catch (e) {\n return { isValid: false, errorMessage: \"Please enter a valid URL.\" };\n }\n \n return { isValid: true };\n }\n}\n"],"mappings":"AAAA,gHAaO,MAAMA,EAOFC,SAASC,EAAsBC,GAClC,IAAKD,EAAa,MAAO,CAAEE,QAAS,MACpC,UAAWF,IAAgB,SAAU,MAAO,CAAEE,QAAS,MAEvD,IACI,MAAMC,EAAM,IAAIC,IAAIJ,GACpB,GAAIG,EAAIE,WAAa,SAAWF,EAAIE,WAAa,SAAU,CACvD,MAAO,CAAEH,QAAS,MAAOI,aAAc,uCAC3C,CACJ,CAAE,MAAOC,GACL,MAAO,CAAEL,QAAS,MAAOI,aAAc,4BAC3C,CAEA,MAAO,CAAEJ,QAAS,KACtB,EACH,IAAAM,EAAA,CAAAC,WAAA,MAAAD,EAAAV,qBAAA,OAAAU,CAAA","ignoreList":[],"sourceRoot":"plugins/validators"}},{"offset":{"line":70,"column":0},"map":{"version":3,"names":["ExpressionBuilder","build","rule","bindingPath","modelName","parsedRule","replace","match","path","reserved","includes","basePath","startsWith","substring","parts","split","pop","contextPrefix","length","join","__exports","__esModule"],"sources":["ExpressionBuilder.ts"],"sourcesContent":["/**\n * @file ExpressionBuilder.ts\n * @description Safely parses and builds UI5 expression bindings from JSON Schema condition rules.\n */\n\nexport class ExpressionBuilder {\n /**\n * Safely converts a raw condition rule (e.g. \"$root.Status === 'NEW'\") into a valid UI5 \n * expression binding string, preserving relative vs absolute paths.\n * \n * @param rule The raw schema condition rule (e.g., \"$root.Category === 'A' || SubCategory === 'B'\").\n * @param bindingPath The absolute binding path of the current field (e.g., \"/Items/0/Category\").\n * @param modelName The UI5 JSONModel name (default \"meta\").\n * @returns {string} The fully formed UI5 expression binding (e.g., \"{= ${meta>/Status} === 'NEW' }\").\n */\n public static build(rule: string, bindingPath: string, modelName: string = \"meta\"): string {\n if (!rule) return \"{= true }\";\n\n let parsedRule = rule;\n\n // 1. Replace absolute $root paths\n // $root.Status -> ${meta>/Status}\n parsedRule = parsedRule.replace(/\\$root\\.([a-zA-Z0-9_.]+)/g, (match, path) => {\n return `\\${${modelName}>/${path.replace(/\\./g, '/')}}`;\n });\n\n // 2. Replace relative paths\n parsedRule = parsedRule.replace(/(?<!['\"\\${a-zA-Z0-9_.>/-])([a-zA-Z_][a-zA-Z0-9_.]+)(?!['\"a-zA-Z0-9_.(])/g, (match, path) => {\n const reserved = [\"true\", \"false\", \"null\", \"undefined\", \"Math\", \"String\", \"Number\", \"Array\", \"Object\"];\n if (reserved.includes(path)) return path;\n\n // Resolve relative to the current binding path context\n let basePath = bindingPath.startsWith(\"/\") ? bindingPath.substring(1) : bindingPath;\n const parts = basePath.split('/');\n parts.pop(); \n const contextPrefix = parts.length > 0 ? parts.join('/') + '/' : '';\n \n return `\\${${modelName}>/${contextPrefix}${path.replace(/\\./g, '/')}}`;\n });\n\n return `{= ${parsedRule} }`;\n }\n}\n"],"mappings":"AAAA,kGAKO,MAAMA,EAUT,YAAcC,CAAMC,EAAcC,EAAqBC,EAAoB,QACvE,IAAKF,EAAM,MAAO,YAElB,IAAIG,EAAaH,EAIjBG,EAAaA,EAAWC,QAAQ,4BAA6B,CAACC,EAAOC,IAC1D,MAAMJ,MAAcI,EAAKF,QAAQ,MAAO,SAInDD,EAAaA,EAAWC,QAAQ,2EAA4E,CAACC,EAAOC,KAChH,MAAMC,EAAW,CAAC,OAAQ,QAAS,OAAQ,YAAa,OAAQ,SAAU,SAAU,QAAS,UAC7F,GAAIA,EAASC,SAASF,GAAO,OAAOA,EAGpC,IAAIG,EAAWR,EAAYS,WAAW,KAAOT,EAAYU,UAAU,GAAKV,EACxE,MAAMW,EAAQH,EAASI,MAAM,KAC7BD,EAAME,MACN,MAAMC,EAAgBH,EAAMI,OAAS,EAAIJ,EAAMK,KAAK,KAAO,IAAM,GAEjE,MAAO,MAAMf,MAAca,IAAgBT,EAAKF,QAAQ,MAAO,UAGnE,MAAO,MAAMD,KACjB,EACH,IAAAe,EAAA,CAAAC,WAAA,MAAAD,EAAApB,oBAAA,OAAAoB,CAAA","ignoreList":[],"sourceRoot":"utils"}},{"offset":{"line":71,"column":0},"map":{"version":3,"names":["Logger","static","setDebugMode","enabled","this","debugMode","logInstance","sap","ui","require","Log","isDebugMode","debug","message","details","component","console","info","warn","warning","error","showErrorPopup","title","MessageBox","__exports","__esModule"],"sources":["Logger.ts"],"sourcesContent":["/**\n * @file Logger.ts\n * @description Centralized logging utility for MetaUI.\n * Wraps sap/base/Log and provides a global toggle for debug mode.\n */\n\nexport class Logger {\n private static debugMode: boolean = false;\n private static logInstance: unknown = null;\n\n /**\n * Toggles the global debug mode for MetaUI.\n * @param enabled Set to true to enable logging.\n */\n public static setDebugMode(enabled: boolean): void {\n this.debugMode = enabled;\n if (enabled && !this.logInstance) {\n sap.ui.require([\"sap/base/Log\"], (Log: Record<string, Function>) => {\n this.logInstance = Log;\n });\n }\n }\n\n /**\n * Checks if debug mode is currently active.\n */\n public static isDebugMode(): boolean {\n return this.debugMode;\n }\n\n public static debug(message: string, details?: string, component?: string): void {\n if (!this.debugMode) return;\n if (this.logInstance) {\n this.logInstance.debug(message, details, component || \"MetaUI\");\n } else {\n console.debug(`[MetaUI] ${message}`, details || \"\");\n }\n }\n\n public static info(message: string, details?: string, component?: string): void {\n if (!this.debugMode) return;\n if (this.logInstance) {\n this.logInstance.info(message, details, component || \"MetaUI\");\n } else {\n console.info(`[MetaUI] ${message}`, details || \"\");\n }\n }\n\n public static warn(message: string, details?: string, component?: string): void {\n if (!this.debugMode) return;\n if (this.logInstance) {\n this.logInstance.warning(message, details, component || \"MetaUI\");\n } else {\n console.warn(`[MetaUI] ${message}`, details || \"\");\n }\n }\n\n public static error(message: string, details?: string, component?: string): void {\n if (this.logInstance) {\n this.logInstance.error(message, details, component || \"MetaUI\");\n } else {\n console.error(`[MetaUI Error] ${message}`, details || \"\");\n }\n }\n\n /**\n * Pops up a MessageBox UI alert if debug mode is active.\n */\n public static showErrorPopup(message: string, title?: string): void {\n if (!this.debugMode) return;\n sap.ui.require([\"sap/m/MessageBox\"], (MessageBox: Record<string, Function>) => {\n (MessageBox as Record<string, Function>).error(message, { title: title || \"MetaUI Error\" });\n });\n }\n}\n"],"mappings":"AAAA,uFAMO,MAAMA,EACTC,iBAAoC,MACpCA,mBAAsC,KAMtC,mBAAcC,CAAaC,GACvBC,KAAKC,UAAYF,EACjB,GAAIA,IAAYC,KAAKE,YAAa,CAC9BC,IAAIC,GAAGC,QAAQ,CAAC,gBAAkBC,IAC9BN,KAAKE,YAAcI,GAE3B,CACJ,CAKA,kBAAcC,GACV,OAAOP,KAAKC,SAChB,CAEA,YAAcO,CAAMC,EAAiBC,EAAkBC,GACnD,IAAKX,KAAKC,UAAW,OACrB,GAAID,KAAKE,YAAa,CAClBF,KAAKE,YAAYM,MAAMC,EAASC,EAASC,GAAa,SAC1D,KAAO,CACHC,QAAQJ,MAAM,YAAYC,IAAWC,GAAW,GACpD,CACJ,CAEA,WAAcG,CAAKJ,EAAiBC,EAAkBC,GAClD,IAAKX,KAAKC,UAAW,OACrB,GAAID,KAAKE,YAAa,CAClBF,KAAKE,YAAYW,KAAKJ,EAASC,EAASC,GAAa,SACzD,KAAO,CACHC,QAAQC,KAAK,YAAYJ,IAAWC,GAAW,GACnD,CACJ,CAEA,WAAcI,CAAKL,EAAiBC,EAAkBC,GAClD,IAAKX,KAAKC,UAAW,OACrB,GAAID,KAAKE,YAAa,CAClBF,KAAKE,YAAYa,QAAQN,EAASC,EAASC,GAAa,SAC5D,KAAO,CACHC,QAAQE,KAAK,YAAYL,IAAWC,GAAW,GACnD,CACJ,CAEA,YAAcM,CAAMP,EAAiBC,EAAkBC,GACnD,GAAIX,KAAKE,YAAa,CAClBF,KAAKE,YAAYc,MAAMP,EAASC,EAASC,GAAa,SAC1D,KAAO,CACHC,QAAQI,MAAM,kBAAkBP,IAAWC,GAAW,GAC1D,CACJ,CAKA,qBAAcO,CAAeR,EAAiBS,GAC1C,IAAKlB,KAAKC,UAAW,OACrBE,IAAIC,GAAGC,QAAQ,CAAC,oBAAsBc,IACjCA,EAAwCH,MAAMP,EAAS,CAAES,MAAOA,GAAS,kBAElF,EACH,IAAAE,EAAA,CAAAC,WAAA,MAAAD,EAAAxB,SAAA,OAAAwB,CAAA","ignoreList":[],"sourceRoot":"utils"}},{"offset":{"line":72,"column":0},"map":{"version":3,"names":[],"sources":["library-preload.js?bundle-code-0"],"mappings":"AAAA;AACA","sourcesContent":["sap.ui.require.preload({\n"],"sourceRoot":""}},{"offset":{"line":74,"column":0},"map":{"version":3,"file":"ILayoutManager.js","names":[],"sources":[],"mappings":"AAAA","ignoreList":[],"sourceRoot":"interfaces"}},{"offset":{"line":77,"column":0},"map":{"version":3,"file":"IPipeline.js","names":[],"sources":[],"mappings":"AAAA","ignoreList":[],"sourceRoot":"interfaces"}},{"offset":{"line":80,"column":0},"map":{"version":3,"file":"IPlugin.js","names":[],"sources":[],"mappings":"AAAA","ignoreList":[],"sourceRoot":"interfaces"}},{"offset":{"line":83,"column":0},"map":{"version":3,"file":"ISchema.js","names":[],"sources":[],"mappings":"AAAA","ignoreList":[],"sourceRoot":"interfaces"}}]}
|
|
1
|
+
{"version":3,"file":"library-preload.js","sections":[{"offset":{"line":1,"column":0},"map":{"version":3,"names":["BaseHardwareControlRenderer","_interopRequireDefault","__BaseHardwareControlRenderer","BaseHardwareControl","Control","extend","renderer","metadata","properties","value","type","defaultValue","schemaMetadata","readOnly","aggregations","_content","multiple","visibility","events","capture","parameters","setValueAndFire","_setValueAndFire","val","this","setProperty","fireEvent","renderContent","_renderContent","rm","control"],"sources":["BaseHardwareControl.ts"],"sourcesContent":["/**\n * @file BaseHardwareControl.ts\n * @description Foundational UI5 Custom Control for hardware plugins.\n * Exposes a standard 'value' property for pure two-way data binding.\n * \n */\n\nimport Control from \"sap/ui/core/Control\";\nimport RenderManager from \"sap/ui/core/RenderManager\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport BaseHardwareControlRenderer from \"./BaseHardwareControlRenderer\";\n\n/**\n * @namespace nz.co.siliconst.ui5.metaui.controls\n */\nexport default class BaseHardwareControl extends Control {\n static readonly metadata = {\n properties: {\n /** The raw data value. Two-way bound to the model. */\n value: { type: \"any\", defaultValue: null },\n /** The schema metadata for rendering dynamic hints (like labels/readOnly) */\n schemaMetadata: { type: \"object\", defaultValue: null },\n /** Indicates if the control should be in a read-only state */\n readOnly: { type: \"boolean\", defaultValue: false }\n },\n aggregations: {\n _content: { type: \"sap.m.VBox\", multiple: false, visibility: \"hidden\" }\n },\n events: {\n /** Fired when the hardware successfully captures a value */\n capture: {\n parameters: {\n value: { type: \"any\" }\n }\n }\n }\n };\n\n /**\n * Updates the bound value and fires the capture event.\n */\n public setValueAndFire(val: unknown): void {\n this.setProperty(\"value\", val, true); // true to suppress re-rendering if desired, but we want the binding to update\n this.fireEvent(\"capture\", { value: val });\n }\n\n /**\n * Common renderer for all hardware controls\n */\n static readonly renderer = BaseHardwareControlRenderer;\n\n /**\n * Abstract hook for subclasses to render their specific DOM/Controls.\n */\n public renderContent(rm: RenderManager, control: BaseHardwareControl): void {\n // To be overridden by hardware implementations\n }\n}\n"],"mappings":"AAAA,sPAUOA,EAA2BC,EAAAC,GAElC,MAGqBC,EAA4BC,EAAOC,OAAA,2DAkCpCC,SAAWN,EAjCXO,SAAW,CACvBC,WAAY,CAERC,MAAO,CAAEC,KAAM,MAAOC,aAAc,MAEpCC,eAAgB,CAAEF,KAAM,SAAUC,aAAc,MAEhDE,SAAU,CAAEH,KAAM,UAAWC,aAAc,QAE/CG,aAAc,CACVC,SAAU,CAAEL,KAAM,aAAcM,SAAU,MAAOC,WAAY,WAEjEC,OAAQ,CAEJC,QAAS,CACLC,WAAY,CACRX,MAAO,CAAEC,KAAM,WASxBW,gBAAe,SAAAC,EAACC,GACnBC,KAAKC,YAAY,QAASF,EAAK,MAC/BC,KAAKE,UAAU,UAAW,CAAEjB,MAAOc,GACvC,EAUOI,cAAa,SAAAC,EAACC,EAAmBC,GACpC,IACH,OAzCgB3B,CAAmB","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":2,"column":0},"map":{"version":3,"names":["__exports","apiVersion","render","rm","control","openStart","class","openEnd","content","getAggregation","renderControl","renderContent","close"],"sources":["BaseHardwareControlRenderer.ts"],"sourcesContent":["/**\n * @file BaseHardwareControlRenderer.ts\n * @description Standard renderer for all MetaUI hardware controls.\n * \n * @namespace nz.co.siliconst.ui5.metaui.controls\n */\nimport RenderManager from \"sap/ui/core/RenderManager\";\nimport BaseHardwareControl from \"./BaseHardwareControl\";\n\nexport default {\n apiVersion: 2,\n render: function (rm: RenderManager, control: BaseHardwareControl) {\n rm.openStart(\"div\", control);\n rm.class(\"sapUiSmallMarginBottom\");\n rm.openEnd();\n \n const content = control.getAggregation(\"_content\") as sap.ui.core.Control;\n if (content) {\n rm.renderControl(content);\n }\n \n if (typeof control.renderContent === \"function\") {\n control.renderContent(rm, control);\n }\n \n rm.close(\"div\");\n }\n};\n"],"mappings":"AAAA,+GAAA,IAAAA,EASe,CACXC,WAAY,EACZC,OAAQ,SAAUC,EAAmBC,GACjCD,EAAGE,UAAU,MAAOD,GACpBD,EAAGG,MAAM,0BACTH,EAAGI,UAEH,MAAMC,EAAUJ,EAAQK,eAAe,YACvC,GAAID,EAAS,CACTL,EAAGO,cAAcF,EACrB,CAEA,UAAWJ,EAAQO,gBAAkB,WAAY,CAC7CP,EAAQO,cAAcR,EAAIC,EAC9B,CAEAD,EAAGS,MAAM,MACb,GACH,OAAAZ,CAAA","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":3,"column":0},"map":{"version":3,"names":["BaseHardwareControl","_interopRequireDefault","__BaseHardwareControl","Logger","___utils_Logger","CameraControl","static","properties","events","videoEl","mediaStream","init","super","this","videoHtml","HTML","content","afterRendering","onVideoRendered","bind","addStyleClass","previewImage","Image","width","visible","startBtn","Button","icon","text","press","handleStartCameraPress","captureBtn","captureImage","retakeBtn","retakeImage","vBox","VBox","items","setAggregation","domRef","getDomRef","val","getValue","startsWith","showPreview","getVisible","startCamera","setVisible","style","display","navigator","mediaDevices","getUserMedia","video","facingMode","srcObject","err","error","message","MessageToast","show","stopCamera","getTracks","forEach","track","stop","canvas","document","createElement","videoWidth","height","videoHeight","ctx","getContext","drawImage","dataUrl","toDataURL","setValueAndFire","setSrc","setValue","value","exit"],"sources":["CameraControl.ts"],"sourcesContent":["import BaseHardwareControl from \"./BaseHardwareControl\";\nimport Button from \"sap/m/Button\";\nimport VBox from \"sap/m/VBox\";\nimport HTML from \"sap/ui/core/HTML\";\nimport MessageToast from \"sap/m/MessageToast\";\nimport Image from \"sap/m/Image\";\nimport { Logger } from \"../utils/Logger\";\n\n/**\n * CameraControl\n * Provides a live video feed to capture photos.\n */\nexport default class CameraControl extends BaseHardwareControl {\n static readonly renderer = \"nz.co.siliconst.ui5.metaui.controls.BaseHardwareControlRenderer\";\n static readonly metadata = {\n properties: {},\n events: {}\n };\n\n private startBtn!: Button;\n private vBox!: VBox;\n private captureBtn!: Button;\n private retakeBtn!: Button;\n private videoHtml!: HTML;\n private previewImage!: Image;\n \n private videoEl: HTMLVideoElement | null = null;\n private mediaStream: MediaStream | null = null;\n\n /**\n * Initializes the control and builds the internal camera UI.\n */\n public init(): void {\n super.init();\n\n this.videoHtml = new HTML({\n content: \"<video width='400' height='300' autoplay playsinline style='background-color: #000; display: none;'></video>\",\n afterRendering: this.onVideoRendered.bind(this)\n }).addStyleClass(\"sapUiSmallMarginBottom\");\n\n this.previewImage = new Image({\n width: \"400px\",\n visible: false\n }).addStyleClass(\"sapUiSmallMarginBottom\");\n\n this.startBtn = new Button({\n icon: \"sap-icon://video\",\n text: \"Start Camera\",\n press: this.handleStartCameraPress.bind(this)\n });\n\n this.captureBtn = new Button({\n icon: \"sap-icon://camera\",\n text: \"Capture\",\n visible: false,\n press: this.captureImage.bind(this)\n });\n\n this.retakeBtn = new Button({\n icon: \"sap-icon://undo\",\n text: \"Retake\",\n visible: false,\n press: this.retakeImage.bind(this)\n });\n\n this.vBox = new VBox({\n items: [this.videoHtml, this.previewImage, this.startBtn, this.captureBtn, this.retakeBtn]\n });\n\n this.setAggregation(\"_content\", this.vBox);\n }\n\n private async onVideoRendered(): void {\n const domRef = this.videoHtml.getDomRef() as HTMLElement;\n if (!domRef) return;\n \n this.videoEl = domRef as HTMLVideoElement;\n \n const val = this.getValue();\n if (val && typeof val === \"string\" && val.startsWith(\"data:image\")) {\n this.showPreview(val);\n } else if (this.captureBtn.getVisible() && this.videoHtml.getVisible()) {\n this.startCamera();\n }\n }\n\n private handleStartCameraPress(): void {\n this.startCamera();\n this.startBtn.setVisible(false);\n this.captureBtn.setVisible(true);\n if (this.videoEl) {\n this.videoEl.style.display = \"block\";\n }\n }\n\n private async startCamera(): Promise<void> {\n try {\n this.mediaStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: \"environment\" } });\n if (this.videoEl) {\n this.videoEl.srcObject = this.mediaStream;\n }\n } catch (err) {\n Logger.error(\"Camera access denied or unavailable\", (err as Error).message, \"CameraControl\");\n MessageToast.show(\"Camera access denied or unavailable.\");\n }\n }\n\n private stopCamera(): void {\n if (this.mediaStream) {\n this.mediaStream.getTracks().forEach(track => track.stop());\n this.mediaStream = null;\n }\n }\n\n private captureImage(): void {\n if (!this.videoEl) return;\n \n const canvas = document.createElement(\"canvas\");\n canvas.width = this.videoEl.videoWidth || 400;\n canvas.height = this.videoEl.videoHeight || 300;\n \n const ctx = canvas.getContext(\"2d\");\n if (ctx) {\n ctx.drawImage(this.videoEl, 0, 0, canvas.width, canvas.height);\n const dataUrl = canvas.toDataURL(\"image/jpeg\", 0.8);\n this.setValueAndFire(dataUrl);\n this.showPreview(dataUrl);\n MessageToast.show(\"Image captured successfully.\");\n }\n }\n\n private retakeImage(): void {\n this.setValueAndFire(null);\n this.previewImage.setVisible(false);\n this.videoHtml.setVisible(true);\n this.captureBtn.setVisible(true);\n this.retakeBtn.setVisible(false);\n \n // startCamera is now handled safely by onVideoRendered hook\n }\n\n private showPreview(dataUrl: string): void {\n this.stopCamera();\n this.videoHtml.setVisible(false);\n this.previewImage.setSrc(dataUrl);\n this.previewImage.setVisible(true);\n this.captureBtn.setVisible(false);\n this.retakeBtn.setVisible(true);\n }\n\n /**\n * Sets the value of the control programmatically.\n * @param value The base64 data URL string representing the image.\n */\n public setValue(value: unknown): this {\n super.setValue(value);\n if (value && typeof value === \"string\" && value.startsWith(\"data:image\")) {\n this.showPreview(value);\n } else if (!value) {\n // Only retake if we were showing a preview\n if (this.previewImage.getVisible()) {\n this.retakeImage();\n }\n }\n return this;\n }\n\n /**\n * Cleans up the hardware streams when the control is destroyed.\n */\n public exit(): void {\n this.stopCamera();\n super.exit();\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":4,"column":0},"map":{"version":3,"names":["GeneratorHost","_interopRequireDefault","__GeneratorHost","Logger","___utils_Logger","ODataDelegate","___host_delegates_ODataDelegate","SchemaBuilderRegistry","___core_SchemaBuilderRegistry","DynamicHost","Control","extend","constructor","prototype","apply","this","arguments","odataDelegate","_innerHost","_initializedInner","renderer","apiVersion","render","rm","control","openStart","style","openEnd","content","getAggregation","renderControl","close","metadata","properties","schemaDefinition","type","defaultValue","data","bindable","dataJson","liveUpdate","isValid","useMessageManager","modelName","debugMode","editable","aggregations","_content","multiple","visibility","events","beforeSubmit","parameters","payload","addError","preventDefault","submit","payloadJson","cancel","fieldChange","fieldPath","value","validationStateChanged","validationError","message","validationSuccess","error","exception","initODataDelegate","_initODataDelegate","getBindingInfo","dataBinding","path","oContext","getBindingContext","debug","getPath","requestObject","syncToEngine","Object","keys","setBindingContext","_setBindingContext","sModelName","Control.prototype.setBindingContext.call","bindElement","_bindElement","vPath","mParameters","Control.prototype.bindElement.call","model","undefined","oBinding","getElementBinding","attachChange","onBeforeRendering","_onBeforeRendering","schemaRaw","getProperty","startsWith","_fetchingSchema","sap","ui","require","BusyIndicator","MessageToast","show","fetch","then","res","ok","Error","status","json","plugin","getBuilderFor","finalSchema","build","Control.prototype.setProperty.call","hide","invalidate","catch","err","warn","schema","trim","JSON","parse","e","hasSchema","length","hasData","props","getMetadata","getProperties","propName","val","Control.prototype.getProperty.call","setProperty","setAggregation","getEvents","eventName","attachEvent","oEvent","params","getParameters","isLive","str","stringify","handleFieldChange","fireEvent","_setProperty","propertyName","suppressInvalidate","openInDialog","_openInDialog","title","submitButtonText","cancelButtonText","dialogWidth","parentView","triggerSubmit","_triggerSubmit","addCustomError","_addCustomError","clearCustomError","_clearCustomError","_getProperty"],"sources":["DynamicHost.ts"],"sourcesContent":["import Control from \"sap/ui/core/Control\";\nimport RenderManager from \"sap/ui/core/RenderManager\";\nimport GeneratorHost from \"./host/GeneratorHost\";\nimport { Logger } from \"../utils/Logger\";\nimport { ODataDelegate } from \"./host/delegates/ODataDelegate\";\nimport ODataV4Context from \"sap/ui/model/odata/v4/Context\";\nimport { SchemaBuilderRegistry } from \"../core/SchemaBuilderRegistry\";\n\n/**\n * A transparent wrapper control (Facade) that automatically chooses between Explicit Schema Mode \n * and Inference Mode based on the presence of a 'schemaDefinition'.\n * \n * This maintains total architectural separation of the modes without forcing developers to \n * use different XML tags.\n * \n * @namespace nz.co.siliconst.ui5.metaui.controls\n */\nexport default class DynamicHost extends Control {\n private odataDelegate: ODataDelegate | null = null;\n\n static readonly metadata = {\n properties: {\n schemaDefinition: { type: \"any\", defaultValue: null },\n data: { type: \"object\", defaultValue: null, bindable: \"bindable\" },\n dataJson: { type: \"string\", defaultValue: null, bindable: \"bindable\" },\n liveUpdate: { type: \"boolean\", defaultValue: false },\n isValid: { type: \"boolean\", defaultValue: true },\n useMessageManager: { type: \"boolean\", defaultValue: false },\n modelName: { type: \"string\", defaultValue: \"meta\" },\n debugMode: { type: \"boolean\", defaultValue: false },\n editable: { type: \"boolean\", defaultValue: true }\n },\n aggregations: {\n _content: { type: \"sap.ui.core.Control\", multiple: false, visibility: \"hidden\" }\n },\n events: {\n beforeSubmit: {\n parameters: {\n payload: { type: \"object\" },\n addError: { type: \"function\" },\n preventDefault: { type: \"function\" }\n }\n },\n submit: {\n parameters: {\n payload: { type: \"object\" },\n payloadJson: { type: \"string\" }\n }\n },\n cancel: {},\n fieldChange: {\n parameters: {\n fieldPath: { type: \"string\" },\n value: { type: \"any\" },\n payload: { type: \"object\" },\n isValid: { type: \"boolean\" }\n }\n },\n validationStateChanged: { parameters: { isValid: { type: \"boolean\" } } },\n validationError: { parameters: { fieldPath: { type: \"string\" }, message: { type: \"string\" } } },\n validationSuccess: { parameters: { fieldPath: { type: \"string\" } } },\n error: { parameters: { message: { type: \"string\" }, exception: { type: \"object\" } } }\n }\n };\n\n static renderer = {\n apiVersion: 2,\n render(rm: RenderManager, control: DynamicHost) {\n rm.openStart(\"div\", control);\n rm.style(\"width\", \"100%\");\n rm.style(\"height\", \"100%\");\n rm.openEnd();\n\n const content = control.getAggregation(\"_content\") as Control;\n if (content) {\n rm.renderControl(content);\n }\n\n rm.close(\"div\");\n }\n };\n\n /**\n * Internal reference to the generated inner host instance.\n * @private\n */\n private _innerHost: GeneratorHost | null = null;\n\n /**\n * Flag indicating if the inner host has been initialized.\n * @private\n */\n private _initializedInner: boolean = false;\n\n /**\n * Initializes the OData Delegate if an OData context is detected.\n * This allows DynamicHost to seamlessly synchronize metadata and properties from an OData model.\n * @private\n */\n private initODataDelegate(): void {\n if (!this.odataDelegate) {\n // Guard: If the user explicitly bound dataJson, do not steal the context.\n if (this.getBindingInfo(\"dataJson\")) {\n return;\n }\n\n // Guard: If the user explicitly bound 'data' to a specific property path, do not steal the context.\n const dataBinding = this.getBindingInfo(\"data\") as any;\n if (dataBinding && dataBinding.path && dataBinding.path !== \"\") {\n return;\n }\n\n const oContext = this.getBindingContext(\"odata\") || this.getBindingContext();\n if (oContext) {\n Logger.debug(\"[MetaUI DynamicHost]\", `Context found for delegate initialization: ${oContext.getPath()}`, \"DynamicHost\");\n if (oContext && (oContext as ODataV4Context).requestObject && typeof (oContext as ODataV4Context).requestObject === \"function\") {\n Logger.debug(\"[MetaUI DynamicHost]\", `Context supports requestObject/getObject. Instantiating ODataDelegate.`, \"DynamicHost\");\n this.odataDelegate = new ODataDelegate(this, oContext as ODataV4Context);\n this.odataDelegate.syncToEngine();\n } else {\n Logger.debug(\"[MetaUI DynamicHost]\", `Context does NOT support requestObject/getObject! Keys: ${Object.keys(oContext)}`, \"DynamicHost\");\n }\n }\n }\n }\n\n /**\n * Standard UI5 method override.\n * Sets the binding context for the control and attempts to initialize the OData delegate\n * if the context points to an OData model.\n * \n * @param {sap.ui.model.Context | null | undefined} oContext The binding context object\n * @param {string} [sModelName] Optional model name\n * @returns {this} The control instance for chaining\n */\n public setBindingContext(oContext: sap.ui.model.Context | null | undefined, sModelName?: string): this {\n super.setBindingContext(oContext, sModelName);\n this.initODataDelegate();\n return this;\n }\n\n /**\n * Standard UI5 method override.\n * Binds the element to the given path and attaches a change listener to re-evaluate\n * the OData delegate when the element binding resolves.\n * \n * @param {string | Record<string, unknown>} vPath The binding path or configuration object\n * @param {object} [mParameters] Optional mapping parameters\n * @returns {this} Reference to this instance for chaining\n */\n public bindElement(vPath: string | Record<string, unknown>, mParameters?: object): this {\n super.bindElement(vPath, mParameters);\n const sModelName = typeof vPath === \"object\" ? vPath.model : undefined;\n const oBinding = this.getElementBinding(sModelName);\n if (oBinding) {\n oBinding.attachChange(() => {\n this.initODataDelegate();\n });\n }\n return this;\n }\n\n /**\n * Standard UI5 Lifecycle Hook.\n * Evaluates the initial properties and spawns the GeneratorHost.\n * It handles the complex lifecycle task of copying all bindings, raw properties, and event listeners \n * down to the inner host perfectly transparently.\n */\n public onBeforeRendering(): void {\n Logger.debug(\"[MetaUI DynamicHost]\", `onBeforeRendering called. _initializedInner: ${this._initializedInner}`, \"DynamicHost\");\n\n this.initODataDelegate();\n\n if (!this._initializedInner) {\n let schemaRaw = this.getProperty(\"schemaDefinition\");\n\n // 1. URL Detection & Fetching\n if (typeof schemaRaw === \"string\" && (schemaRaw.startsWith(\"http://\") || schemaRaw.startsWith(\"https://\"))) {\n if ((this as any)._fetchingSchema) return; // Prevent re-entry\n (this as any)._fetchingSchema = true;\n \n sap.ui.require([\"sap/ui/core/BusyIndicator\", \"sap/m/MessageToast\"], (BusyIndicator: any, MessageToast: any) => {\n BusyIndicator.show(0);\n fetch(schemaRaw as string)\n .then(res => {\n if (!res.ok) throw new Error(\"HTTP \" + res.status);\n return res.json();\n })\n .then(json => {\n const plugin = SchemaBuilderRegistry.getBuilderFor(json);\n const finalSchema = plugin ? plugin.build(json) : json;\n super.setProperty(\"schemaDefinition\", finalSchema, true);\n (this as any)._fetchingSchema = false;\n BusyIndicator.hide();\n this.invalidate(); // Force re-render with resolved schema\n })\n .catch(err => {\n Logger.warn(\"[MetaUI DynamicHost]\", \"Failed to fetch remote schema: \" + err, \"DynamicHost\");\n if (MessageToast) MessageToast.show(\"Failed to fetch remote schema\");\n super.setProperty(\"schemaDefinition\", null, true); // Fallback to full inference\n (this as any)._fetchingSchema = false;\n BusyIndicator.hide();\n this.invalidate();\n });\n });\n return; // Abort this render cycle until fetch completes\n }\n\n // 2. Local Plugin Detection (Stringified JSON or Raw Object)\n let schema = schemaRaw;\n if (schema && typeof schema === \"string\" && (schema as string).trim().startsWith(\"{\")) {\n try {\n schema = JSON.parse(schema);\n } catch (e) {\n // Ignore, let standard validation catch it\n }\n }\n\n if (schema && typeof schema === \"object\") {\n const plugin = SchemaBuilderRegistry.getBuilderFor(schema);\n if (plugin) {\n schema = plugin.build(schema);\n // Silently update the wrapper property so the inner host gets the final parsed MetaUI format\n super.setProperty(\"schemaDefinition\", schema, true);\n }\n }\n\n const dataJson = this.getProperty(\"dataJson\");\n const data = this.getProperty(\"data\");\n\n let hasSchema = !!schema;\n if (hasSchema && typeof schema === \"object\" && Object.keys(schema).length === 0) {\n hasSchema = false; // Treat empty object as no schema\n }\n\n const hasData = !!dataJson || !!data;\n\n Logger.debug(\"[MetaUI DynamicHost]\", `Evaluating boot. hasSchema: ${hasSchema}, hasData: ${hasData}`, \"DynamicHost\");\n\n // Only boot if we have either a schema or some data to infer from\n if (hasSchema || hasData) {\n if (this.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI DynamicHost]\", `Booting inner host. hasSchema: ${hasSchema}, hasData: ${hasData}`, \"DynamicHost\");\n }\n // The architectural Facade router logic:\n // We've simplified this! We no longer use HostFactory or separate subclasses.\n // GeneratorHost is fully capable of inferring the schema if none is provided.\n this._innerHost = new GeneratorHost();\n\n // 1. Forward all static values to the spawned host BEFORE mounting.\n // Since we no longer use bindProperty, it's perfectly safe to set raw properties before mounting.\n const props = this.getMetadata().getProperties();\n for (const propName in props) {\n const val = super.getProperty(propName);\n if (val !== null && val !== undefined) {\n this._innerHost.setProperty(propName, val);\n }\n }\n\n // 2. Mount so it inherits models and triggers lifecycle.\n this.setAggregation(\"_content\", this._innerHost);\n\n // 3. Forward all event subscriptions.\n // By proxying the events upwards, the developer can subscribe to `<meta:DynamicHost submit=\"...\">` \n // and perfectly receive the inner host's submission event.\n const events = this.getMetadata().getEvents();\n for (const eventName in events) {\n this._innerHost.attachEvent(eventName, (oEvent: sap.ui.base.Event) => {\n // Natively push updated payload out to any bound Fiori Element properties.\n // Using super.setProperty prevents an infinite loop back down to _innerHost.\n if (eventName === \"submit\" || eventName === \"fieldChange\") {\n const params = oEvent.getParameters();\n if (params.payload) {\n const isLive = this.getProperty(\"liveUpdate\") === true;\n if (eventName === \"submit\" || isLive) {\n super.setProperty(\"data\", params.payload, true);\n\n const str = params.payloadJson || JSON.stringify(params.payload, null, 2);\n super.setProperty(\"dataJson\", str, true);\n }\n }\n if (eventName === \"fieldChange\" && this.odataDelegate) {\n this.odataDelegate.handleFieldChange(params.fieldPath, params.value);\n }\n }\n this.fireEvent(eventName, oEvent.getParameters());\n });\n }\n\n this._initializedInner = true;\n }\n }\n }\n\n /**\n * Overrides standard UI5 setProperty to act as a transparent proxy.\n * When a property is updated on the wrapper (either programmatically or via a binding update),\n * it instantly mirrors that value down to the inner instantiated host.\n */\n public setProperty(propertyName: string, value: unknown, suppressInvalidate?: boolean): this {\n if (propertyName === \"data\" || propertyName === \"dataJson\" || propertyName === \"schemaDefinition\") {\n if (this.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI DynamicHost]\", `Wrapper received setProperty: ${propertyName}`, \"DynamicHost\");\n }\n }\n super.setProperty(propertyName, value, suppressInvalidate);\n if (this._innerHost) {\n this._innerHost.setProperty(propertyName, value, suppressInvalidate);\n } else if (propertyName === \"data\" || propertyName === \"dataJson\" || propertyName === \"schemaDefinition\") {\n if (this.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI DynamicHost]\", `_innerHost not yet initialized when ${propertyName} was set. Booting will happen on next render.`, \"DynamicHost\");\n }\n }\n return this;\n }\n\n\n\n\n\n /**\n * Programmatic API support. Routes dialog commands down to the spawned inner host.\n * If the inner host has not booted yet, it forces initialization immediately.\n * \n * @param {string} [title=\"Form\"] The title of the dialog\n * @param {string} [submitButtonText=\"OK\"] The text for the primary action button\n * @param {string} [cancelButtonText=\"Cancel\"] The text for the cancel button\n * @param {string} [dialogWidth=\"auto\"] The width of the dialog\n * @param {sap.ui.core.Control} [parentView] The parent view to attach the dialog to for model inheritance.\n */\n public openInDialog(title?: string, submitButtonText?: string, cancelButtonText?: string, dialogWidth?: string, parentView?: Control): void {\n if (!this._innerHost) {\n this.onBeforeRendering(); // Force init if they bypassed UI5 rendering\n }\n this._innerHost?.openInDialog(title, submitButtonText, cancelButtonText, dialogWidth, parentView);\n }\n\n /**\n * Proxies submission triggering down to the instantiated generator host.\n * Evaluates the internal Engine validation suite and returns true if structurally sound.\n * \n * @returns {boolean} True if the internal payload passes schema validation, false otherwise.\n */\n public triggerSubmit(): boolean {\n if (!this._innerHost) {\n return false;\n }\n return this._innerHost.triggerSubmit();\n }\n\n /**\n * Injects a custom error message onto a specific field.\n * Useful for injecting custom backend validation errors.\n * \n * @param {string} fieldPath The schema key path to target.\n * @param {string} message The custom error message to display.\n */\n public addCustomError(fieldPath: string, message: string): void {\n if (this._innerHost && typeof (this._innerHost as any).addCustomError === \"function\") {\n (this._innerHost as any).addCustomError(fieldPath, message);\n }\n }\n\n /**\n * Clears a custom error message from a specific field.\n * \n * @param {string} fieldPath The schema key path to target.\n */\n public clearCustomError(fieldPath: string): void {\n if (this._innerHost && typeof (this._innerHost as any).clearCustomError === \"function\") {\n (this._innerHost as any).clearCustomError(fieldPath);\n }\n }\n\n /**\n * Overrides standard UI5 getProperty to transparently pull extracted data from the inner host.\n * Ensures that querying the DynamicHost facade for `data` always yields the freshest payload.\n * \n * @param {string} propertyName The name of the property to retrieve\n * @returns {unknown} The property value\n */\n public getProperty(propertyName: string): unknown {\n if (propertyName === \"outputData\") {\n propertyName = \"data\"; // Forward deprecated outputData to data\n }\n if (this._innerHost && (propertyName === \"data\" || propertyName === \"dataJson\")) {\n return this._innerHost.getProperty(propertyName);\n }\n return super.getProperty(propertyName);\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":5,"column":0},"map":{"version":3,"names":["BaseHardwareControl","_interopRequireDefault","__BaseHardwareControl","BaseHardwareControlRenderer","__BaseHardwareControlRenderer","GeolocationControl","static","aggregations","_content","type","multiple","visibility","init","super","this","locationBtn","Button","icon","text","press","getLocation","bind","resultInput","Input","editable","visible","vBox","VBox","items","setAggregation","onBeforeRendering","metadata","getProperty","ui","label","setText","readOnly","setEnabled","currentVal","setValue","setVisible","navigator","geolocation","MessageToast","show","getCurrentPosition","position","locStr","coords","latitude","longitude","setValueAndFire","error","__ui5_require_async","then","Logger","message"],"sources":["GeolocationControl.ts"],"sourcesContent":["/**\n * @file GeolocationControl.ts\n * @description Native UI5 Control for GPS capture.\n * \n * @namespace nz.co.siliconst.ui5.metaui.controls\n */\nimport BaseHardwareControl from \"./BaseHardwareControl\";\nimport BaseHardwareControlRenderer from \"./BaseHardwareControlRenderer\";\nimport RenderManager from \"sap/ui/core/RenderManager\";\nimport Button from \"sap/m/Button\";\nimport Input from \"sap/m/Input\";\nimport VBox from \"sap/m/VBox\";\nimport MessageToast from \"sap/m/MessageToast\";\n\nexport default class GeolocationControl extends BaseHardwareControl {\n private vBox: VBox;\n private locationBtn: Button;\n private resultInput: Input;\n\n static readonly renderer = BaseHardwareControlRenderer;\n\n static readonly metadata = {\n aggregations: {\n _content: { type: \"sap.m.VBox\", multiple: false, visibility: \"hidden\" }\n }\n };\n\n /**\n * Initializes the control and builds the internal UI components.\n */\n public init(): void {\n super.init();\n\n this.locationBtn = new Button({\n icon: \"sap-icon://map\",\n text: \"Get Location\",\n press: this.getLocation.bind(this)\n });\n\n this.resultInput = new Input({\n editable: false,\n visible: false\n });\n\n this.vBox = new VBox({\n items: [this.locationBtn, this.resultInput]\n });\n\n this.setAggregation(\"_content\", this.vBox);\n }\n\n /**\n * Lifecycle hook called before the control is rendered to the DOM.\n * Updates button state and sets any existing values.\n */\n public onBeforeRendering(): void {\n const metadata = this.getProperty(\"schemaMetadata\");\n if (metadata && metadata.ui && metadata.ui.label) {\n this.locationBtn.setText(metadata.ui.label);\n }\n\n const readOnly = this.getProperty(\"readOnly\");\n this.locationBtn.setEnabled(!readOnly);\n\n const currentVal = this.getProperty(\"value\");\n if (currentVal) {\n this.resultInput.setValue(currentVal as string);\n this.resultInput.setVisible(true);\n }\n }\n\n private getLocation(): void {\n if (!navigator.geolocation) {\n MessageToast.show(\"Geolocation is not supported by your browser\");\n return;\n }\n\n navigator.geolocation.getCurrentPosition(\n (position) => {\n const locStr = `${position.coords.latitude}, ${position.coords.longitude}`;\n this.resultInput.setValue(locStr);\n this.resultInput.setVisible(true);\n this.setValueAndFire(locStr);\n MessageToast.show(\"Location acquired.\");\n },\n (error) => {\n import(\"../utils/Logger\").then(({ Logger }) => {\n Logger.error(\"[MetaUI] Geolocation failed or denied\", error.message, \"GeolocationControl\");\n });\n MessageToast.show(\"Unable to retrieve your location\");\n }\n );\n }\n\n\n}\n"],"mappings":"AAAA,ojBAAA,MAMOA,EAAmBC,EAAAC,GAAA,MACnBC,EAA2BF,EAAAG,GAOnB,MAAMC,UAA2BL,EAK5CM,gBAA2BH,EAE3BG,gBAA2B,CACvBC,aAAc,CACVC,SAAU,CAAEC,KAAM,aAAcC,SAAU,MAAOC,WAAY,YAO9DC,OACHC,MAAMD,OAENE,KAAKC,YAAc,IAAIC,EAAO,CAC1BC,KAAM,iBACNC,KAAM,eACNC,MAAOL,KAAKM,YAAYC,KAAKP,QAGjCA,KAAKQ,YAAc,IAAIC,EAAM,CACzBC,SAAU,MACVC,QAAS,QAGbX,KAAKY,KAAO,IAAIC,EAAK,CACjBC,MAAO,CAACd,KAAKC,YAAaD,KAAKQ,eAGnCR,KAAKe,eAAe,WAAYf,KAAKY,KACzC,CAMOI,oBACH,MAAMC,EAAWjB,KAAKkB,YAAY,kBAClC,GAAID,GAAYA,EAASE,IAAMF,EAASE,GAAGC,MAAO,CAC9CpB,KAAKC,YAAYoB,QAAQJ,EAASE,GAAGC,MACzC,CAEA,MAAME,EAAWtB,KAAKkB,YAAY,YAClClB,KAAKC,YAAYsB,YAAYD,GAE7B,MAAME,EAAaxB,KAAKkB,YAAY,SACpC,GAAIM,EAAY,CACZxB,KAAKQ,YAAYiB,SAASD,GAC1BxB,KAAKQ,YAAYkB,WAAW,KAChC,CACJ,CAEQpB,cACJ,IAAKqB,UAAUC,YAAa,CACxBC,EAAaC,KAAK,gDAClB,MACJ,CAEAH,UAAUC,YAAYG,mBACjBC,IACG,MAAMC,EAAS,GAAGD,EAASE,OAAOC,aAAaH,EAASE,OAAOE,YAC/DpC,KAAKQ,YAAYiB,SAASQ,GAC1BjC,KAAKQ,YAAYkB,WAAW,MAC5B1B,KAAKqC,gBAAgBJ,GACrBJ,EAAaC,KAAK,uBAErBQ,IACGC,EAAO,mBAAmBC,KAAK,EAAGC,aAC9BA,EAAOH,MAAM,wCAAyCA,EAAMI,QAAS,wBAEzEb,EAAaC,KAAK,qCAG9B,EAGH,OAAAvC,CAAA","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":6,"column":0},"map":{"version":3,"names":["BaseHardwareControl","_interopRequireDefault","__BaseHardwareControl","BaseHardwareControlRenderer","__BaseHardwareControlRenderer","RichTextControl","extend","metadata","properties","events","aggregations","_content","type","multiple","visibility","renderer","init","_init","BaseHardwareControl.prototype.init.call","this","richTextEditor","RichTextEditor","width","height","showGroupFont","showGroupInsert","tooltip","change","oEvent","val","getParameter","setValueAndFire","vBox","VBox","items","setAggregation","onBeforeRendering","_onBeforeRendering","readOnly","getProperty","setEditable","currentVal","undefined","getValue","setValue","_setValue","setProperty"],"sources":["RichTextControl.ts"],"sourcesContent":["import BaseHardwareControl from \"./BaseHardwareControl\";\nimport BaseHardwareControlRenderer from \"./BaseHardwareControlRenderer\";\nimport RenderManager from \"sap/ui/core/RenderManager\";\nimport VBox from \"sap/m/VBox\";\nimport RichTextEditor from \"sap/ui/richtexteditor/RichTextEditor\";\n\n/**\n * @file RichTextControl.ts\n * @description Native UI5 Control for rich text input.\n * \n * @namespace nz.co.siliconst.ui5.metaui.controls\n */\nexport default class RichTextControl extends BaseHardwareControl {\n private vBox!: VBox;\n private richTextEditor!: RichTextEditor;\n\n static readonly renderer = BaseHardwareControlRenderer;\n\n static readonly metadata = {\n properties: {},\n events: {},\n aggregations: {\n _content: { type: \"sap.m.VBox\", multiple: false, visibility: \"hidden\" }\n }\n };\n\n public init(): void {\n super.init();\n\n this.richTextEditor = new RichTextEditor({\n width: \"100%\",\n height: \"300px\",\n showGroupFont: true,\n showGroupInsert: true,\n tooltip: \"Rich Text Editor\",\n change: (oEvent: sap.ui.base.Event) => {\n const val = oEvent.getParameter(\"newValue\");\n this.setValueAndFire(val);\n }\n });\n\n this.vBox = new VBox({\n items: [this.richTextEditor]\n });\n\n this.setAggregation(\"_content\", this.vBox);\n }\n\n public onBeforeRendering(): void {\n const readOnly = this.getProperty(\"readOnly\");\n this.richTextEditor.setEditable(!readOnly);\n\n const currentVal = this.getProperty(\"value\");\n if (currentVal !== undefined && currentVal !== null) {\n // Prevent recursive update if the value matches the editor's current value\n if (this.richTextEditor.getValue() !== currentVal) {\n this.richTextEditor.setValue(currentVal as string);\n }\n }\n }\n\n /**\n * Overrides the default property setter to prevent full DOM invalidation.\n * When dataJson pushes updates down to the UI5 models, UI5 typically destroys \n * and recreates the custom control if the property changes. \n * By suppressing re-rendering (true flag) and manually passing the value \n * to the inner RichTextEditor, we prevent TinyMCE from tearing down its iframe\n * and triggering expensive, redundant plugin boot sequences.\n *\n * @param {unknown} val The new string value to bind\n * @returns {this} The control instance for chaining\n */\n public setValue(val: unknown): this {\n this.setProperty(\"value\", val, true); // suppress re-rendering\n if (this.richTextEditor && val !== undefined && val !== null) {\n if (this.richTextEditor.getValue() !== val) {\n this.richTextEditor.setValue(val as string);\n }\n }\n return this;\n }\n}\n"],"mappings":"AAAA,4SAAOA,EAAmBC,EAAAC,GAAA,MACnBC,EAA2BF,EAAAG,GAKlC,MAMqBC,EAAwBL,EAAmBM,OAAA,uDAM5CC,SAAW,CACvBC,WAAY,CAAC,EACbC,OAAQ,CAAC,EACTC,aAAc,CACVC,SAAU,CAAEC,KAAM,aAAcC,SAAU,MAAOC,WAAY,YANrDC,SAAWZ,EAUpBa,KAAI,SAAAC,IACPC,sBAAAC,MAEAA,KAAKC,eAAiB,IAAIC,EAAe,CACrCC,MAAO,OACPC,OAAQ,QACRC,cAAe,KACfC,gBAAiB,KACjBC,QAAS,mBACTC,OAASC,IACL,MAAMC,EAAMD,EAAOE,aAAa,YAChCX,KAAKY,gBAAgBF,MAI7BV,KAAKa,KAAO,IAAIC,EAAK,CACjBC,MAAO,CAACf,KAAKC,kBAGjBD,KAAKgB,eAAe,WAAYhB,KAAKa,KACzC,EAEOI,kBAAiB,SAAAC,IACpB,MAAMC,EAAWnB,KAAKoB,YAAY,YAClCpB,KAAKC,eAAeoB,aAAaF,GAEjC,MAAMG,EAAatB,KAAKoB,YAAY,SACpC,GAAIE,IAAeC,WAAaD,IAAe,KAAM,CAEjD,GAAItB,KAAKC,eAAeuB,aAAeF,EAAY,CAC/CtB,KAAKC,eAAewB,SAASH,EACjC,CACJ,CACJ,EAaOG,SAAQ,SAAAC,EAAChB,GACZV,KAAK2B,YAAY,QAASjB,EAAK,MAC/B,GAAIV,KAAKC,gBAAkBS,IAAQa,WAAab,IAAQ,KAAM,CAC1D,GAAIV,KAAKC,eAAeuB,aAAed,EAAK,CACxCV,KAAKC,eAAewB,SAASf,EACjC,CACJ,CACA,OAAOV,IACX,IAAC,OApEgBd,CAAe","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":7,"column":0},"map":{"version":3,"names":["BaseHardwareControl","_interopRequireDefault","__BaseHardwareControl","SignatureControl","static","properties","events","isDrawing","canvasCtx","canvasEl","init","super","this","canvasHtml","HTML","content","afterRendering","onCanvasRendered","bind","addStyleClass","clearBtn","Button","icon","text","press","clearSignature","vBox","VBox","items","setAggregation","boundStartDrawing","startDrawing","boundDraw","draw","boundStopDrawing","stopDrawing","boundStartDrawingTouch","startDrawingTouch","boundDrawTouch","drawTouch","domRef","getDomRef","getContext","lineWidth","lineCap","strokeStyle","addEventListener","passive","val","getValue","startsWith","loadImageOntoCanvas","dataUrl","img","window","Image","onload","clearRect","width","height","drawImage","src","getCoordinates","e","x","y","rect","getBoundingClientRect","clientX","clientY","type","touches","left","top","preventDefault","pos","lineTo","stroke","beginPath","moveTo","saveSignature","setValueAndFire","MessageToast","show","toDataURL","setValue","value","exit","removeEventListener"],"sources":["SignatureControl.ts"],"sourcesContent":["import BaseHardwareControl from \"./BaseHardwareControl\";\nimport Button from \"sap/m/Button\";\nimport VBox from \"sap/m/VBox\";\nimport HTML from \"sap/ui/core/HTML\";\nimport MessageToast from \"sap/m/MessageToast\";\n\n/**\n * SignatureControl\n * Provides an HTML5 Canvas for capturing signatures.\n */\nexport default class SignatureControl extends BaseHardwareControl {\n static readonly renderer = \"nz.co.siliconst.ui5.metaui.controls.BaseHardwareControlRenderer\";\n static readonly metadata = {\n properties: {},\n events: {}\n };\n\n private vBox!: VBox;\n private clearBtn!: Button;\n private canvasHtml!: HTML;\n private isDrawing = false;\n private canvasCtx: CanvasRenderingContext2D | null = null;\n private canvasEl: HTMLCanvasElement | null = null;\n\n private boundStartDrawing!: (e: MouseEvent) => void;\n private boundDraw!: (e: MouseEvent) => void;\n private boundStopDrawing!: (e: MouseEvent | TouchEvent) => void;\n private boundStartDrawingTouch!: (e: TouchEvent) => void;\n private boundDrawTouch!: (e: TouchEvent) => void;\n\n /**\n * Initializes the control and builds the canvas drawing surface.\n */\n public init(): void {\n super.init();\n\n this.canvasHtml = new HTML({\n content: \"<canvas width='400' height='200' style='border: 1px solid #ccc; background-color: #fff; touch-action: none; cursor: crosshair;'></canvas>\",\n afterRendering: this.onCanvasRendered.bind(this)\n }).addStyleClass(\"sapUiSmallMarginBottom\");\n\n this.clearBtn = new Button({\n icon: \"sap-icon://sys-cancel\",\n text: \"Clear Signature\",\n press: this.clearSignature.bind(this)\n });\n\n this.vBox = new VBox({\n items: [this.canvasHtml, this.clearBtn]\n });\n\n this.setAggregation(\"_content\", this.vBox);\n\n this.boundStartDrawing = this.startDrawing.bind(this);\n this.boundDraw = this.draw.bind(this);\n this.boundStopDrawing = this.stopDrawing.bind(this);\n this.boundStartDrawingTouch = this.startDrawingTouch.bind(this);\n this.boundDrawTouch = this.drawTouch.bind(this);\n }\n\n private onCanvasRendered(): void {\n const domRef = this.canvasHtml.getDomRef() as HTMLElement;\n if (!domRef) return;\n \n this.canvasEl = domRef as HTMLCanvasElement;\n this.canvasCtx = this.canvasEl.getContext(\"2d\");\n if (this.canvasCtx) {\n this.canvasCtx.lineWidth = 2;\n this.canvasCtx.lineCap = \"round\";\n this.canvasCtx.strokeStyle = \"#000\";\n }\n\n // Mouse events\n this.canvasEl.addEventListener(\"mousedown\", this.boundStartDrawing);\n this.canvasEl.addEventListener(\"mousemove\", this.boundDraw);\n this.canvasEl.addEventListener(\"mouseup\", this.boundStopDrawing);\n this.canvasEl.addEventListener(\"mouseout\", this.boundStopDrawing);\n \n // Touch events\n this.canvasEl.addEventListener(\"touchstart\", this.boundStartDrawingTouch, { passive: false });\n this.canvasEl.addEventListener(\"touchmove\", this.boundDrawTouch, { passive: false });\n this.canvasEl.addEventListener(\"touchend\", this.boundStopDrawing);\n\n // Restore existing signature if any\n const val = this.getValue();\n if (val && typeof val === \"string\" && val.startsWith(\"data:image\")) {\n this.loadImageOntoCanvas(val);\n }\n }\n\n private loadImageOntoCanvas(dataUrl: string): void {\n const img = new window.Image();\n img.onload = () => {\n if (this.canvasCtx && this.canvasEl) {\n this.canvasCtx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);\n this.canvasCtx.drawImage(img, 0, 0, this.canvasEl.width, this.canvasEl.height);\n }\n };\n img.src = dataUrl;\n }\n\n private getCoordinates(e: MouseEvent | TouchEvent): { x: number, y: number } {\n if (!this.canvasEl) return { x: 0, y: 0 };\n const rect = this.canvasEl.getBoundingClientRect();\n \n let clientX, clientY;\n if (e.type.startsWith(\"touch\")) {\n clientX = (e as TouchEvent).touches[0].clientX;\n clientY = (e as TouchEvent).touches[0].clientY;\n } else {\n clientX = (e as MouseEvent).clientX;\n clientY = (e as MouseEvent).clientY;\n }\n \n return {\n x: clientX - rect.left,\n y: clientY - rect.top\n };\n }\n\n private startDrawing(e: MouseEvent): void {\n this.isDrawing = true;\n this.draw(e);\n }\n\n private startDrawingTouch(e: TouchEvent): void {\n e.preventDefault(); // Prevent scrolling\n this.isDrawing = true;\n this.drawTouch(e);\n }\n\n private draw(e: MouseEvent): void {\n if (!this.isDrawing || !this.canvasCtx) return;\n const pos = this.getCoordinates(e);\n this.canvasCtx.lineTo(pos.x, pos.y);\n this.canvasCtx.stroke();\n this.canvasCtx.beginPath();\n this.canvasCtx.moveTo(pos.x, pos.y);\n }\n\n private drawTouch(e: TouchEvent): void {\n if (!this.isDrawing || !this.canvasCtx) return;\n e.preventDefault(); // Prevent scrolling\n const pos = this.getCoordinates(e);\n this.canvasCtx.lineTo(pos.x, pos.y);\n this.canvasCtx.stroke();\n this.canvasCtx.beginPath();\n this.canvasCtx.moveTo(pos.x, pos.y);\n }\n\n private stopDrawing(): void {\n if (!this.isDrawing) return;\n this.isDrawing = false;\n if (this.canvasCtx) {\n this.canvasCtx.beginPath(); // Reset path\n this.saveSignature();\n }\n }\n\n private clearSignature(): void {\n if (this.canvasCtx && this.canvasEl) {\n this.canvasCtx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);\n }\n this.setValueAndFire(null);\n MessageToast.show(\"Signature cleared.\");\n }\n\n private saveSignature(): void {\n if (this.canvasEl) {\n const dataUrl = this.canvasEl.toDataURL(\"image/png\");\n this.setValueAndFire(dataUrl);\n }\n }\n\n /**\n * Sets the value of the control programmatically and re-draws the canvas.\n * @param value The base64 data URL string representing the signature image.\n */\n public setValue(value: unknown): this {\n super.setValue(value);\n if (value && typeof value === \"string\" && value.startsWith(\"data:image\")) {\n this.loadImageOntoCanvas(value);\n } else if (!value && this.canvasCtx && this.canvasEl) {\n this.canvasCtx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);\n }\n return this;\n }\n\n /**\n * Cleans up event listeners to prevent memory leaks when the control is destroyed.\n */\n public exit(): void {\n if (this.canvasEl) {\n this.canvasEl.removeEventListener(\"mousedown\", this.boundStartDrawing as EventListener);\n this.canvasEl.removeEventListener(\"mousemove\", this.boundDraw as EventListener);\n this.canvasEl.removeEventListener(\"mouseup\", this.boundStopDrawing as EventListener);\n this.canvasEl.removeEventListener(\"mouseout\", this.boundStopDrawing as EventListener);\n \n this.canvasEl.removeEventListener(\"touchstart\", this.boundStartDrawingTouch as EventListener);\n this.canvasEl.removeEventListener(\"touchmove\", this.boundDrawTouch as EventListener);\n this.canvasEl.removeEventListener(\"touchend\", this.boundStopDrawing as EventListener);\n }\n this.canvasEl = null;\n this.canvasCtx = null;\n super.exit();\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":8,"column":0},"map":{"version":3,"names":["BaseHardwareControl","_interopRequireDefault","__BaseHardwareControl","Logger","___utils_Logger","VoiceInputControl","static","properties","events","recognition","isRecording","init","super","this","textArea","TextArea","rows","width","placeholder","liveChange","oEvent","setValueAndFire","getParameter","startBtn","Button","icon","text","type","press","toggleDictation","bind","hBox","HBox","items","addStyleClass","vBox","VBox","setAggregation","initSpeechRecognition","stopDictation","startDictation","SpeechRecognitionClass","window","SpeechRecognition","webkitSpeechRecognition","continuous","interimResults","onresult","event","finalTranscript","interimTranscript","i","resultIndex","results","length","isFinal","transcript","currentVal","getValue","newVal","setValue","onstart","setIcon","setText","setType","MessageToast","show","onerror","error","sap","ui","require","MessageBox","onend","warn","setEnabled","setTooltip","start","err","message","String","stop","e","onBeforeRendering","readOnly","getProperty","setEditable","undefined","exit"],"sources":["VoiceInputControl.ts"],"sourcesContent":["import BaseHardwareControl from \"./BaseHardwareControl\";\nimport Button from \"sap/m/Button\";\nimport VBox from \"sap/m/VBox\";\nimport TextArea from \"sap/m/TextArea\";\nimport MessageToast from \"sap/m/MessageToast\";\nimport HBox from \"sap/m/HBox\";\nimport { Logger } from \"../utils/Logger\";\n\ndeclare global {\n interface Window {\n SpeechRecognition: new () => SpeechRecognition;\n webkitSpeechRecognition: new () => SpeechRecognition;\n }\n interface SpeechRecognition {\n continuous: boolean;\n interimResults: boolean;\n onresult: (event: SpeechRecognitionEvent) => void;\n onstart: () => void;\n onerror: (event: SpeechRecognitionErrorEvent) => void;\n onend: () => void;\n start(): void;\n stop(): void;\n }\n interface SpeechRecognitionEvent {\n resultIndex: number;\n results: {\n length: number;\n [index: number]: {\n isFinal: boolean;\n [index: number]: {\n transcript: string;\n };\n };\n };\n }\n interface SpeechRecognitionErrorEvent {\n error: string;\n }\n}\n\n/**\n * VoiceInputControl\n * Provides a UI to dictate text using the browser's native Web Speech API.\n */\nexport default class VoiceInputControl extends BaseHardwareControl {\n static readonly renderer = \"nz.co.siliconst.ui5.metaui.controls.BaseHardwareControlRenderer\";\n static readonly metadata = {\n properties: {},\n events: {}\n };\n\n private vBox!: VBox;\n private textArea!: TextArea;\n private startBtn!: Button;\n private stopBtn!: Button;\n \n private recognition: SpeechRecognition | null = null;\n private isRecording: boolean = false;\n\n /**\n * Initializes the dictation interface and requests Web Speech API setup.\n */\n public init(): void {\n super.init();\n\n this.textArea = new TextArea({\n rows: 3,\n width: \"100%\",\n placeholder: \"Dictated text will appear here...\",\n liveChange: (oEvent: sap.ui.base.Event) => {\n this.setValueAndFire(oEvent.getParameter(\"value\"));\n }\n });\n\n this.startBtn = new Button({\n icon: \"sap-icon://microphone\",\n text: \"Start Dictation\",\n type: \"Emphasized\",\n press: this.toggleDictation.bind(this)\n });\n\n const hBox = new HBox({\n items: [this.startBtn]\n }).addStyleClass(\"sapUiSmallMarginTop\");\n\n this.vBox = new VBox({\n items: [this.textArea, hBox]\n });\n\n this.setAggregation(\"_content\", this.vBox);\n this.initSpeechRecognition();\n }\n\n private toggleDictation(): void {\n if (this.isRecording) {\n this.stopDictation();\n } else {\n this.startDictation();\n }\n }\n\n private initSpeechRecognition(): void {\n const SpeechRecognitionClass = window.SpeechRecognition || window.webkitSpeechRecognition;\n if (SpeechRecognitionClass) {\n this.recognition = new SpeechRecognitionClass();\n this.recognition.continuous = true;\n this.recognition.interimResults = true;\n\n this.recognition.onresult = (event: SpeechRecognitionEvent) => {\n let finalTranscript = \"\";\n let interimTranscript = \"\";\n\n for (let i = event.resultIndex; i < event.results.length; ++i) {\n if (event.results[i].isFinal) {\n finalTranscript += event.results[i][0].transcript;\n } else {\n interimTranscript += event.results[i][0].transcript;\n }\n }\n\n // Append the new final transcript to whatever was already in the textarea\n const currentVal = this.getValue() || \"\";\n const newVal = currentVal ? currentVal + \" \" + finalTranscript : finalTranscript;\n \n if (finalTranscript) {\n this.textArea.setValue(newVal);\n this.setValueAndFire(newVal);\n } else if (interimTranscript) {\n // Just show interim temporarily in textarea without saving to model\n this.textArea.setValue(currentVal ? currentVal + \" \" + interimTranscript : interimTranscript);\n }\n };\n\n this.recognition.onstart = () => {\n this.isRecording = true;\n this.startBtn.setIcon(\"sap-icon://stop\");\n this.startBtn.setText(\"Stop Recording\");\n this.startBtn.setType(\"Reject\");\n MessageToast.show(\"Listening... Please speak now.\");\n };\n\n this.recognition.onerror = (event: SpeechRecognitionErrorEvent) => {\n Logger.error(\"Speech recognition error\", event.error, \"VoiceInputControl\");\n sap.ui.require([\"sap/m/MessageBox\"], (MessageBox: typeof import(\"sap/m/MessageBox\").default) => {\n MessageBox.error(\"Microphone Error: \" + event.error + \"\\n\\nPlease ensure you have a working microphone attached and have not blocked access in your browser settings.\");\n });\n this.stopDictation();\n };\n \n this.recognition.onend = () => {\n // If it ends natively (e.g. timeout), update UI\n this.stopDictation();\n };\n } else {\n Logger.warn(\"Web Speech API not supported in this browser.\", \"\", \"VoiceInputControl\");\n this.startBtn.setEnabled(false);\n this.startBtn.setTooltip(\"Speech Recognition is not supported in this browser.\");\n }\n }\n\n private startDictation(): void {\n if (!this.recognition) return;\n \n try {\n this.recognition.start();\n MessageToast.show(\"Requesting microphone access...\");\n // Provide immediate UI feedback in case browser delays the onstart event\n this.startBtn.setIcon(\"sap-icon://stop\");\n this.startBtn.setText(\"Requesting mic...\");\n this.startBtn.setType(\"Reject\");\n } catch (err) {\n const error = err as Error;\n Logger.error(\"Failed to start speech recognition\", error.message || String(error), \"VoiceInputControl\");\n sap.ui.require([\"sap/m/MessageBox\"], (MessageBox: typeof import(\"sap/m/MessageBox\").default) => {\n MessageBox.error(\"Failed to start dictation. Please ensure you have a working microphone and have granted browser permissions.\\n\\nDetails: \" + (error.message || String(error)));\n });\n this.stopDictation();\n }\n }\n\n private stopDictation(): void {\n if (!this.recognition) return;\n \n try {\n this.recognition.stop();\n } catch(e) {\n Logger.warn(\"Failed to gracefully stop speech recognition.\", String(e), \"VoiceInputControl\");\n }\n \n this.isRecording = false;\n this.startBtn.setIcon(\"sap-icon://microphone\");\n this.startBtn.setText(\"Start Dictation\");\n this.startBtn.setType(\"Emphasized\");\n }\n\n /**\n * Lifecycle hook called before the control is rendered to the DOM.\n * Handles browser support visual state.\n */\n public onBeforeRendering(): void {\n const readOnly = this.getProperty(\"readOnly\");\n this.textArea.setEditable(!readOnly);\n \n // Only enable if it's not readonly AND the browser supports speech recognition\n this.startBtn.setEnabled(!readOnly && !!this.recognition);\n\n const currentVal = this.getProperty(\"value\");\n if (currentVal !== undefined && currentVal !== null) {\n // Only update text area if we aren't currently dictating interim results\n if (!this.isRecording) {\n this.textArea.setValue(currentVal as string);\n }\n }\n }\n\n /**\n * Cleans up hardware event listeners when the control is destroyed.\n */\n public exit(): void {\n this.stopDictation();\n if (this.recognition) {\n this.recognition.onstart = null;\n this.recognition.onresult = null;\n this.recognition.onerror = null;\n this.recognition.onend = null;\n this.recognition = null;\n }\n super.exit();\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"controls"}},{"offset":{"line":9,"column":0},"map":{"version":3,"names":["Logger","____utils_Logger","SchemaNormalizer","____core_SchemaNormalizer","SchemaValidator","____core_SchemaValidator","Engine","____core_Engine","StateManager","____core_StateManager","DataSyncDelegate","___delegates_DataSyncDelegate","ValidationDelegate","___delegates_ValidationDelegate","DialogDelegate","___delegates_DialogDelegate","PluginRegistry","____core_PluginRegistry","GeneratorHost","Control","extend","renderer","apiVersion","render","rm","control","openStart","style","openEnd","content","getAggregation","renderControl","close","metadata","properties","schemaDefinition","type","defaultValue","data","bindable","dataJson","liveUpdate","isValid","useMessageManager","modelName","debugMode","editable","aggregations","_content","multiple","visibility","events","beforeSubmit","parameters","payload","addError","preventDefault","submit","payloadJson","cancel","fieldChange","fieldPath","value","validationStateChanged","validationError","message","validationSuccess","error","exception","constructor","_constructor","idOrSettings","settings","Control.prototype.constructor.call","this","stateManager","generatedContent","engine","activeModelName","parsedSchema","_generatePromise","init","_init","Control.prototype.init.call","dataSyncDelegate","validationDelegate","dialogDelegate","onInternalFieldChange","bind","setDebugMode","_setDebugMode","enabled","setProperty","_setProperty","propertyName","suppressInvalidate","Control.prototype.setProperty.call","setUseMessageManager","getStateManager","_getStateManager","tearDownGeneratedLayout","_tearDownGeneratedLayout","unregisterObject","destroy","_onInternalFieldChange","fieldKey","errorMessage","controlId","extractPayload","getProperty","debug","pushToBindings","currentValidity","fireEvent","undefined","exit","_exit","getModel","getParsedSchema","_getParsedSchema","onBeforeRendering","_onBeforeRendering","hasSchema","hasData","generate","msg","Error","triggerSubmit","_triggerSubmit","isPrevented","removeAllMessages","applyVisualFallback","errors","validateAll","length","pushMessage","err","JSON","stringify","propertyPath","plugin","getPluginByPath","setVisualValidationState","addCustomError","_addCustomError","clearCustomError","_clearCustomError","schemaValid","validate","setBusy","_setBusy","isBusy","Control.prototype.setBusy.call","_setProperty2","handleInputDataHotSwap","currentVal","setBaseProperty","_setBaseProperty","async","_generate","Promise","resolve","then","_doGenerate","e","internalPayload","rawSchema","isSchemaEmpty","Object","keys","inputData","inputDataJson","parse","finalData","schemaToNormalize","normalizedSchema","normalize","schemaErrors","validateSchemaStructure","errorMsg","join","MessageBox","title","pathsToLoad","getInstance","getPathsToLoad","needsNetworkLoad","Array","from","some","path","sap","ui","require","preloadDependencies","getId","setModel","isEditable","build","contentContainer","hasProperties","strip","MessageStrip","text","showIcon","showCloseButton","addStyleClass","VBox","items","hasPartialRenderingErrors","setAggregation","registerObject","optimalWidth","calculateOptimalDialogWidth","updateDialogWidthDynamically","mountCrashBoundary","_calculateOptimalDialogWidth","schema","requiresWideDialog","scanProperties","props","key","prop","fullWidth","widget","openInDialog","_openInDialog","submitButtonText","cancelButtonText","dialogWidth","parentView","isGenerated","finalWidth"],"sources":["GeneratorHost.ts"],"sourcesContent":["import Control from \"sap/ui/core/Control\";\nimport RenderManager from \"sap/ui/core/RenderManager\";\nimport { Logger } from \"../../utils/Logger\";\nimport { SchemaNormalizer } from \"../../core/SchemaNormalizer\";\nimport { SchemaValidator } from \"../../core/SchemaValidator\";\nimport { Engine } from \"../../core/Engine\";\nimport { StateManager } from \"../../core/StateManager\";\nimport { DataSyncDelegate } from \"./delegates/DataSyncDelegate\";\nimport { ValidationDelegate } from \"./delegates/ValidationDelegate\";\nimport { DialogDelegate } from \"./delegates/DialogDelegate\";\nimport MessageBox from \"sap/m/MessageBox\";\nimport MessageStrip from \"sap/m/MessageStrip\";\nimport VBox from \"sap/m/VBox\";\nimport { PluginRegistry } from \"../../core/PluginRegistry\";\nimport type { ISchema } from \"../../interfaces/ISchema\";\n\n/**\n * Base wrapper element for embedding the dynamic form natively via Explicit Schemas.\n * \n * This class serves as the core rendering engine for standard MetaUI implementations.\n * It manages the lifecycle of the Engine, StateManager, and the delegation of \n * data synchronization, validation, and dialog interactions.\n * \n * @namespace nz.co.siliconst.ui5.metaui.controls.host\n */\nexport default class GeneratorHost extends Control {\n\n protected stateManager: StateManager | null = null;\n protected generatedContent: Control | null = null;\n protected engine: Engine | null = null;\n protected activeModelName: string = \"\";\n\n protected dataSyncDelegate!: DataSyncDelegate;\n protected validationDelegate!: ValidationDelegate;\n protected dialogDelegate!: DialogDelegate;\n\n static readonly metadata = {\n properties: {\n schemaDefinition: { type: \"any\", defaultValue: null },\n data: { type: \"object\", defaultValue: null, bindable: \"bindable\" },\n dataJson: { type: \"string\", defaultValue: null, bindable: \"bindable\" },\n liveUpdate: { type: \"boolean\", defaultValue: false },\n isValid: { type: \"boolean\", defaultValue: true },\n useMessageManager: { type: \"boolean\", defaultValue: false },\n modelName: { type: \"string\", defaultValue: \"meta\" },\n debugMode: { type: \"boolean\", defaultValue: false },\n editable: { type: \"boolean\", defaultValue: true }\n },\n aggregations: {\n _content: { type: \"sap.ui.core.Control\", multiple: false, visibility: \"hidden\" }\n },\n events: {\n beforeSubmit: {\n parameters: {\n payload: { type: \"object\" },\n addError: { type: \"function\" },\n preventDefault: { type: \"function\" }\n }\n },\n submit: {\n parameters: {\n payload: { type: \"object\" },\n payloadJson: { type: \"string\" }\n }\n },\n cancel: {},\n fieldChange: {\n parameters: {\n fieldPath: { type: \"string\" },\n value: { type: \"any\" },\n payload: { type: \"object\" },\n isValid: { type: \"boolean\" }\n }\n },\n validationStateChanged: { parameters: { isValid: { type: \"boolean\" } } },\n validationError: { parameters: { fieldPath: { type: \"string\" }, message: { type: \"string\" } } },\n validationSuccess: { parameters: { fieldPath: { type: \"string\" } } },\n error: { parameters: { message: { type: \"string\" }, exception: { type: \"object\" } } }\n }\n };\n\n static renderer = {\n apiVersion: 2,\n render(rm: RenderManager, control: GeneratorHost) {\n rm.openStart(\"div\", control);\n rm.style(\"width\", \"100%\");\n rm.style(\"height\", \"100%\");\n rm.openEnd();\n\n const content = control.getAggregation(\"_content\") as Control;\n if (content) {\n rm.renderControl(content);\n }\n\n rm.close(\"div\");\n }\n };\n\n /**\n * Standard UI5 Constructor.\n */\n constructor(idOrSettings?: string | object, settings?: object) {\n super(idOrSettings, settings);\n }\n\n /**\n * Initializes the control and instantiates the composition delegates.\n * Delegates must be initialized here rather than in the constructor so they are \n * available before `applySettings` runs during UI5's control lifecycle.\n */\n public init(): void {\n super.init();\n\n // Initialize Composition Delegates\n this.dataSyncDelegate = new DataSyncDelegate(this);\n this.validationDelegate = new ValidationDelegate(this);\n this.dialogDelegate = new DialogDelegate(this);\n\n this.onInternalFieldChange = this.onInternalFieldChange.bind(this);\n }\n\n /**\n * Enables or disables debug mode.\n */\n public setDebugMode(enabled: boolean): this {\n this.setProperty(\"debugMode\", enabled, true);\n Logger.setDebugMode(enabled);\n return this;\n }\n\n /**\n * Intercepts property updates to dynamically forward them to active delegates/managers.\n */\n public setProperty(propertyName: string, value: unknown, suppressInvalidate?: boolean): this {\n super.setProperty(propertyName, value, suppressInvalidate);\n if (propertyName === \"useMessageManager\" && this.stateManager) {\n this.stateManager.setUseMessageManager(value === true);\n }\n return this;\n }\n\n /**\n * Returns the active state manager instance managing the JSON payload.\n */\n public getStateManager(): StateManager | null {\n return this.stateManager;\n }\n\n /**\n * Safely destroys the currently generated UI tree and cleans up references.\n * This is called before every regeneration to prevent memory leaks.\n */\n public tearDownGeneratedLayout(): void {\n if (this.generatedContent) {\n this.validationDelegate.unregisterObject(this.generatedContent);\n this.generatedContent.destroy();\n this.generatedContent = null;\n }\n }\n\n /**\n * Internal event handler triggered by the Engine when a field value changes.\n * Coordinates LiveUpdate syncs, validation state tracking, and bubbling the change upwards.\n */\n protected onInternalFieldChange(isValid: boolean, fieldKey?: string, errorMessage?: string, controlId?: string): void {\n const payload = this.stateManager ? this.stateManager.extractPayload() : {};\n\n if (this.getProperty(\"liveUpdate\") === true) {\n if (this.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI]\", \"liveUpdate is enabled, pushing outbound payload.\", \"GeneratorHost\");\n }\n this.dataSyncDelegate.pushToBindings(payload);\n }\n\n const currentValidity = this.getProperty(\"isValid\") as boolean;\n if (isValid !== currentValidity) {\n this.setProperty(\"isValid\", isValid, true);\n this.fireEvent(\"validationStateChanged\", { isValid });\n if (this.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI]\", `Validation state shifted to: ${isValid}`, \"GeneratorHost\");\n }\n }\n\n this.fireEvent(\"fieldChange\", {\n fieldPath: fieldKey || \"\",\n value: undefined,\n payload: payload,\n isValid: isValid\n });\n }\n\n /**\n * Standard UI5 Exit Hook. Ensures complete teardown of the engine and state manager.\n */\n public exit(): void {\n if (this.engine) {\n this.engine.destroy();\n this.engine = null;\n }\n\n if (this.stateManager) {\n this.stateManager.getModel().destroy();\n this.stateManager = null;\n }\n\n if (this.generatedContent) {\n this.generatedContent.destroy();\n this.generatedContent = null;\n }\n }\n\n /** Cached schema for intelligent diffing during inference mode hot-swaps */\n protected parsedSchema: Record<string, unknown> | null = null;\n\n /**\n * Exposes the parsed schema to the DataSyncDelegate for diffing.\n */\n public getParsedSchema(): Record<string, unknown> | null {\n return this.parsedSchema;\n }\n\n /**\n * Standard UI5 Rendering Hook.\n * Evaluates whether it possesses a schema or data. If so, triggers the internal engine generation.\n */\n public onBeforeRendering(): void {\n if (this.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI GeneratorHost]\", `onBeforeRendering called. Engine boot state: schemaDefinition exists = ${!!this.getProperty(\"schemaDefinition\")}, data exists = ${!!this.getProperty(\"data\")}, dataJson exists = ${!!this.getProperty(\"dataJson\")}`, \"GeneratorHost\");\n }\n\n if (!this.generatedContent) {\n const hasSchema = !!this.getProperty(\"schemaDefinition\");\n const hasData = !!this.getProperty(\"dataJson\") || !!this.getProperty(\"data\");\n\n if (hasSchema || hasData) {\n this.generate();\n } else {\n const msg = \"GeneratorHost skipped rendering. Neither 'schemaDefinition' nor 'data' was provided.\";\n Logger.error(\"[MetaUI]\", msg, \"GeneratorHost\");\n this.fireEvent(\"error\", { message: msg });\n throw new Error(msg); // Eradicate silent errors\n }\n }\n }\n\n /**\n * Public API method to manually trigger form submission.\n * Executes all structural validations, clears old messages, and pushes payload to bindings.\n * @returns boolean True if submission succeeded, false if validation failed.\n */\n public triggerSubmit(): boolean {\n if (this.stateManager && this.engine) {\n let isPrevented = false;\n\n this.validationDelegate.removeAllMessages();\n\n // Only apply local fallback visual states if the global MessageManager is explicitly disabled\n const applyVisualFallback = this.getProperty(\"useMessageManager\") !== true;\n const errors = this.engine.validateAll(applyVisualFallback);\n if (errors.length > 0) {\n this.validationDelegate.pushMessage(\"\", \"One or more fields failed schema validation. Please review the highlighted fields.\");\n for (const err of errors) {\n if (err.fieldKey && err.errorMessage) {\n this.validationDelegate.pushMessage(err.fieldKey, err.errorMessage);\n }\n }\n return false;\n }\n\n const payload = this.stateManager.extractPayload();\n const payloadJson = JSON.stringify(payload);\n\n this.fireEvent(\"beforeSubmit\", {\n payload,\n preventDefault: () => { isPrevented = true; },\n addError: (propertyPath: string, errorMessage: string) => {\n isPrevented = true;\n this.validationDelegate.pushMessage(propertyPath, errorMessage);\n if (applyVisualFallback && this.engine) {\n const plugin = this.engine.getPluginByPath(propertyPath);\n if (plugin && typeof plugin.setVisualValidationState === \"function\") {\n plugin.setVisualValidationState(false, errorMessage);\n }\n }\n }\n });\n\n if (isPrevented) {\n return false;\n }\n\n this.dataSyncDelegate.pushToBindings(payload);\n this.fireEvent(\"submit\", { payload, payloadJson });\n return true;\n }\n return false;\n }\n\n /**\n * Injects a custom error message onto a specific field.\n */\n public addCustomError(fieldPath: string, message: string): void {\n this.validationDelegate.addCustomError(fieldPath, message);\n if (this.getProperty(\"useMessageManager\") !== true && this.engine) {\n const plugin = this.engine.getPluginByPath(fieldPath);\n if (plugin && typeof plugin.setVisualValidationState === \"function\") {\n plugin.setVisualValidationState(false, message);\n }\n }\n }\n\n /**\n * Clears a custom error message from a specific field.\n */\n public clearCustomError(fieldPath: string): void {\n this.validationDelegate.clearCustomError(fieldPath);\n if (this.getProperty(\"useMessageManager\") !== true && this.engine) {\n const plugin = this.engine.getPluginByPath(fieldPath);\n if (plugin && typeof plugin.setVisualValidationState === \"function\") {\n const schemaValid = plugin.validate();\n plugin.setVisualValidationState(schemaValid.isValid, schemaValid.errorMessage);\n }\n }\n }\n\n /**\n * Toggles busy state on the host control.\n */\n public setBusy(isBusy: boolean): this {\n super.setBusy(isBusy);\n return this;\n }\n\n /**\n * Intercepts property changes. Hot-swaps data gracefully if it's an inputData change,\n * or forces a full UI teardown if it's a structural property change (like schemaDefinition).\n */\n public setProperty(propertyName: string, value: unknown, suppressInvalidate?: boolean): this {\n if (propertyName === \"dataJson\" || propertyName === \"data\") {\n this.dataSyncDelegate.handleInputDataHotSwap(propertyName, value, suppressInvalidate);\n return this;\n }\n\n if (propertyName === \"editable\" || propertyName === \"debugMode\" || propertyName === \"schemaDefinition\") {\n const currentVal = this.getProperty(propertyName);\n if (currentVal !== value) {\n super.setProperty(propertyName, value, suppressInvalidate);\n this.tearDownGeneratedLayout();\n }\n return this;\n }\n\n return super.setProperty(propertyName, value, suppressInvalidate);\n }\n\n /**\n * Bypasses the interceptor to write directly to the base UI5 control.\n */\n public setBaseProperty(propertyName: string, value: unknown, suppressInvalidate?: boolean): this {\n return super.setProperty(propertyName, value, suppressInvalidate);\n }\n\n /**\n * Internal reference to the active generate promise.\n * Prevents concurrent redundant layouts from being generated when properties are set rapidly or DialogDelegate triggers it.\n */\n private _generatePromise: Promise<void> | null = null;\n\n /**\n * The core rendering pipeline entry point.\n * Uses Promise resolution to debounce concurrent or rapid consecutive calls natively without arbitrary timeouts.\n * @returns Promise that resolves when the layout is successfully built and mounted.\n */\n public async generate(): Promise<void> {\n if (this._generatePromise) {\n return this._generatePromise;\n }\n this._generatePromise = Promise.resolve().then(async () => {\n try {\n await this._doGenerate();\n } catch (e) {\n Logger.error(\"[MetaUI]\", \"Error in deferred generate: \" + e, \"GeneratorHost\");\n throw e; // Ensure it bubbles up to awaiters\n } finally {\n this._generatePromise = null;\n }\n });\n return this._generatePromise;\n }\n\n /**\n * The underlying synchronous generator orchestration method.\n * Normalizes the schema, sets up the state manager, loads missing plugins over the network,\n * orchestrates the Engine build, and mounts the generated UI components into the internal tree.\n */\n private async _doGenerate(): Promise<void> {\n try {\n this.tearDownGeneratedLayout();\n\n // CRITICAL FIX: Extract the unsaved internal payload BEFORE destroying the state manager\n // Otherwise, toggling editable (or other structural properties) will wipe user inputs!\n let internalPayload = null;\n if (this.stateManager) {\n internalPayload = this.stateManager.extractPayload();\n }\n\n if (this.engine) {\n this.engine.destroy();\n this.engine = null;\n }\n if (this.stateManager) {\n this.stateManager.getModel().destroy();\n this.stateManager = null;\n }\n\n const rawSchema = this.getProperty(\"schemaDefinition\");\n const isSchemaEmpty = !rawSchema || (typeof rawSchema === \"object\" && Object.keys(rawSchema).length === 0);\n\n let inputData = this.getProperty(\"data\");\n const inputDataJson = this.getProperty(\"dataJson\");\n\n if (inputDataJson) {\n try {\n inputData = JSON.parse(inputDataJson as string);\n } catch (e) {\n const msg = \"Failed to parse inputDataJson string: \" + (e as Error).message;\n Logger.error(\"[MetaUI]\", msg, \"GeneratorHost\");\n this.fireEvent(\"error\", { message: msg, exception: e });\n throw new Error(msg); // Critical error instead of silent fallback\n }\n } else if (typeof inputData === \"string\") {\n try {\n inputData = JSON.parse(inputData);\n } catch (e) {\n const msg = \"Failed to parse inputData string: \" + (e as Error).message;\n Logger.error(\"[MetaUI]\", msg, \"GeneratorHost\");\n this.fireEvent(\"error\", { message: msg, exception: e });\n throw new Error(msg); // Critical error instead of silent fallback\n }\n }\n\n // The internal payload represents the user's latest un-extracted edits. It must take priority.\n const finalData = internalPayload || inputData;\n\n if (!finalData || Object.keys(finalData).length === 0) {\n if (isSchemaEmpty) {\n const msg = \"No payload provided and no explicit schema defined. Cannot infer UI.\";\n Logger.error(\"[MetaUI]\", msg, \"GeneratorHost\");\n this.fireEvent(\"error\", { message: msg });\n throw new Error(msg);\n }\n }\n\n const schemaToNormalize = isSchemaEmpty ? null : rawSchema;\n const normalizedSchema = SchemaNormalizer.normalize(schemaToNormalize, finalData);\n\n // Cache the parsed/inferred schema so DataSyncDelegate can diff against it later\n this.parsedSchema = normalizedSchema as Record<string, unknown>;\n\n if (normalizedSchema) {\n const schemaErrors = SchemaValidator.validateSchemaStructure(normalizedSchema);\n if (schemaErrors.length > 0) {\n const errorMsg = \"Schema Structural Errors Found:\\n- \" + schemaErrors.join(\"\\n- \");\n // Let's log it out loudly regardless of debug mode, so developers can see why it didn't render\n Logger.error(\"[MetaUI]\", errorMsg, \"GeneratorHost\");\n if (this.getProperty(\"debugMode\")) {\n MessageBox.error(errorMsg, { title: \"MetaUI Schema Error\" });\n return;\n }\n }\n }\n\n const pathsToLoad = PluginRegistry.getInstance().getPathsToLoad(normalizedSchema as ISchema);\n const needsNetworkLoad = Array.from(pathsToLoad).some(path => !sap.ui.require(path));\n\n if (needsNetworkLoad) {\n this.setBusy(true);\n await PluginRegistry.getInstance().preloadDependencies(normalizedSchema as ISchema);\n this.setBusy(false);\n }\n\n this.activeModelName = \"metaUI_\" + this.getId();\n this.stateManager = new StateManager(finalData, normalizedSchema, this.activeModelName);\n this.stateManager.setUseMessageManager(this.getProperty(\"useMessageManager\") === true);\n this.setModel(this.stateManager.getModel(), this.activeModelName);\n\n if (!this.engine) {\n const isEditable = this.getProperty(\"editable\") !== false;\n const useMessageManager = this.getProperty(\"useMessageManager\") === true;\n this.engine = new Engine(isEditable, useMessageManager);\n }\n\n this.generatedContent = this.engine.build(\n normalizedSchema,\n this.stateManager.getModel(),\n this.activeModelName,\n this.triggerSubmit.bind(this),\n this.getId(),\n this.onInternalFieldChange.bind(this)\n );\n\n let contentContainer = this.generatedContent;\n\n const hasProperties = normalizedSchema && Object.keys(normalizedSchema).length > 0;\n\n if (!hasProperties) {\n const strip = new MessageStrip({\n text: \"Warning: The generated UI is blank. Reason: The schema (or inferred schema) contains no valid properties to render.\",\n type: \"Warning\",\n showIcon: true,\n showCloseButton: false\n });\n strip.addStyleClass(\"sapUiSmallMarginBottom\");\n contentContainer = new VBox({\n items: [strip, this.generatedContent]\n });\n } else if (this.engine.hasPartialRenderingErrors) {\n const strip = new MessageStrip({\n text: \"Layout partially rendered. Some fields failed to generate due to configuration errors.\",\n type: \"Warning\",\n showIcon: true,\n showCloseButton: true\n });\n strip.addStyleClass(\"sapUiSmallMarginBottom\");\n contentContainer = new VBox({\n items: [strip, this.generatedContent]\n });\n }\n\n this.setAggregation(\"_content\", contentContainer);\n this.validationDelegate.registerObject(this.generatedContent);\n\n const payload = this.stateManager.extractPayload();\n this.dataSyncDelegate.pushToBindings(payload);\n\n // Retroactively expand the dialog if the heuristic determines it needs more space\n const optimalWidth = this.calculateOptimalDialogWidth(this.parsedSchema);\n this.dialogDelegate.updateDialogWidthDynamically(optimalWidth);\n\n } catch (error) {\n this.setBusy(false);\n const msg = \"Fatal crash during layout generation: \" + (error as Error).message;\n Logger.error(\"[MetaUI]\", msg, \"GeneratorHost\");\n this.fireEvent(\"error\", { message: msg, exception: error });\n this.validationDelegate.mountCrashBoundary(error as Error);\n throw error; // Completely eliminate silent error swallowing\n }\n }\n\n /**\n * Helper to heuristically calculate optimal dialog width based on schema content.\n */\n private calculateOptimalDialogWidth(schema: Record<string, any> | null): string {\n if (!schema) return \"auto\";\n let requiresWideDialog = false;\n\n const scanProperties = (props: Record<string, any>) => {\n if (requiresWideDialog) return;\n for (const key in props) {\n const prop = props[key];\n if (prop.type === \"array\") {\n requiresWideDialog = true;\n return;\n }\n if (prop.ui?.fullWidth === true) {\n requiresWideDialog = true;\n return;\n }\n if (prop.ui?.widget === \"codeEditor\" || prop.ui?.widget === \"textArea\" || prop.ui?.widget === \"richText\") {\n requiresWideDialog = true;\n return;\n }\n if (prop.properties) scanProperties(prop.properties);\n if (prop.items && prop.items.properties) scanProperties(prop.items.properties);\n }\n };\n\n if (schema.type === \"array\") return \"80vw\";\n if (schema.properties) {\n scanProperties(schema.properties);\n }\n\n return requiresWideDialog ? \"80vw\" : \"auto\";\n }\n\n /**\n * Programmatic API. Re-parents the generated content into a dialog and opens it.\n */\n public openInDialog(title: string = \"Form\", submitButtonText: string = \"OK\", cancelButtonText: string = \"Cancel\", dialogWidth: string = \"auto\", parentView?: Control): void {\n const isGenerated = !!this.generatedContent;\n \n // If we already have the schema parsed, we can calculate it instantly to prevent flicker\n let finalWidth = dialogWidth;\n if (finalWidth === \"auto\" && this.parsedSchema) {\n finalWidth = this.calculateOptimalDialogWidth(this.parsedSchema);\n }\n \n this.dialogDelegate.openInDialog(title, submitButtonText, isGenerated, cancelButtonText, finalWidth, parentView);\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"controls/host"}},{"offset":{"line":10,"column":0},"map":{"version":3,"names":["Logger","_____utils_Logger","SchemaNormalizer","_____core_SchemaNormalizer","DataSyncDelegate","_lastPushedPayloadJson","_lastPushedPayloadObj","_lastReceivedInputObj","constructor","host","this","pushToBindings","payload","payloadStr","JSON","stringify","deepEqual","parse","setProperty","handleInputDataHotSwap","propertyName","value","suppressInvalidate","incomingObj","e","setBaseProperty","getProperty","debug","extend","stateManager","getStateManager","invalidate","getModel","setData","getParsedSchema","newInferredSchema","inferSchemaFromData","parsedSchema","tearDownGeneratedLayout","msg","message","error","Error","__exports","__esModule"],"sources":["DataSyncDelegate.ts"],"sourcesContent":["import deepEqual from \"sap/base/util/deepEqual\";\nimport extend from \"sap/base/util/extend\";\nimport { Logger } from \"../../../utils/Logger\";\nimport { SchemaNormalizer } from \"../../../core/SchemaNormalizer\";\nimport PropertyBinding from \"sap/ui/model/PropertyBinding\";\nimport { StateManager } from \"../../../core/StateManager\";\n\nexport interface IHostDataSync {\n getProperty(name: string): unknown;\n setProperty(name: string, value: unknown, suppressInvalidate?: boolean): this;\n setBaseProperty(name: string, value: unknown, suppressInvalidate?: boolean): this;\n getBinding(name: string): unknown;\n invalidate(): void;\n getStateManager(): StateManager | null;\n getParsedSchema?(): Record<string, unknown> | null;\n tearDownGeneratedLayout(): void;\n}\n\n/**\n * Handles two-way data sync, JSON parsing, loop-breaking, and inference structural diffs.\n */\nexport class DataSyncDelegate {\n private host: IHostDataSync;\n private _lastPushedPayloadJson: string | null = null;\n private _lastPushedPayloadObj: Record<string, unknown> | null = null;\n private _lastReceivedInputObj: Record<string, unknown> | null = null;\n\n /**\n * Initializes a new DataSyncDelegate to handle data payload binding extraction.\n * @param host The parent host interface containing properties.\n */\n constructor(host: IHostDataSync) {\n this.host = host;\n }\n\n /**\n * Natively forces the UI5 framework to push updated properties back up to any bound ViewModels.\n */\n public pushToBindings(payload: Record<string, unknown>): void {\n const payloadStr = JSON.stringify(payload, null, 2);\n\n // Cache exact payload output to catch echoes on the inbound side\n this._lastPushedPayloadJson = payloadStr;\n this._lastPushedPayloadObj = deepEqual({}, payload) ? null : JSON.parse(JSON.stringify(payload)); // Safe clone\n\n this.host.setProperty(\"data\", payload, true);\n this.host.setProperty(\"dataJson\", payloadStr, true);\n }\n\n /**\n * Intercepts and parses live updates to the data payload from two-way Fiori bindings.\n */\n public handleInputDataHotSwap(propertyName: string, value: unknown, suppressInvalidate?: boolean): void {\n let incomingObj: Record<string, unknown> | null = null;\n\n if (typeof value === \"string\") {\n try {\n incomingObj = JSON.parse(value) as Record<string, unknown>;\n } catch (e) {\n this.host.setBaseProperty(propertyName, value, true);\n return;\n }\n } else {\n incomingObj = value as Record<string, unknown>;\n }\n\n if (incomingObj === null) {\n this.host.setBaseProperty(propertyName, value, true);\n return;\n }\n\n // Loop Breaker 1: Stale Data Injection\n if (this._lastReceivedInputObj && deepEqual(incomingObj, this._lastReceivedInputObj)) {\n if (this.host.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI]\", `Dropped stale data injection for ${propertyName}`, \"DataSyncDelegate\");\n }\n this.host.setBaseProperty(propertyName, value, suppressInvalidate);\n return;\n }\n\n // Loop Breaker 2: Two-Way Data Echoes\n if (this._lastPushedPayloadObj && deepEqual(incomingObj, this._lastPushedPayloadObj)) {\n if (this.host.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI]\", `Dropped echo for ${propertyName}`, \"DataSyncDelegate\");\n }\n this.host.setBaseProperty(propertyName, value, suppressInvalidate);\n return;\n }\n\n this._lastReceivedInputObj = extend(true, {}, incomingObj) as Record<string, unknown>;\n\n if (this.host.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI]\", `Accepted external injection for ${propertyName}`, \"DataSyncDelegate\");\n }\n\n this.host.setBaseProperty(propertyName, value, true);\n\n const stateManager = this.host.getStateManager();\n if (!stateManager) {\n this.host.invalidate();\n return;\n }\n\n try {\n stateManager.getModel().setData(incomingObj, false);\n\n if (!this.host.getProperty(\"schemaDefinition\") && typeof this.host.getParsedSchema === \"function\") {\n const newInferredSchema = SchemaNormalizer.inferSchemaFromData(incomingObj);\n const parsedSchema = this.host.getParsedSchema();\n if (!deepEqual(newInferredSchema, parsedSchema)) {\n this.host.tearDownGeneratedLayout();\n this.host.invalidate();\n }\n }\n } catch (e) {\n const msg = `Failed to hot-swap ${propertyName}: ` + (e as Error).message;\n Logger.error(\"[MetaUI]\", msg, \"DataSyncDelegate\");\n throw new Error(msg);\n }\n }\n}\n"],"mappings":"AAAA,yOAESA,EAAMC,EAAA,gBACNC,EAAgBC,EAAA,oBAkBlB,MAAMC,EAEDC,uBAAwC,KACxCC,sBAAwD,KACxDC,sBAAwD,KAMhEC,YAAYC,GACRC,KAAKD,KAAOA,CAChB,CAKOE,eAAeC,GAClB,MAAMC,EAAaC,KAAKC,UAAUH,EAAS,KAAM,GAGjDF,KAAKL,uBAAyBQ,EAC9BH,KAAKJ,sBAAwBU,EAAU,CAAC,EAAGJ,GAAW,KAAOE,KAAKG,MAAMH,KAAKC,UAAUH,IAEvFF,KAAKD,KAAKS,YAAY,OAAQN,EAAS,MACvCF,KAAKD,KAAKS,YAAY,WAAYL,EAAY,KAClD,CAKOM,uBAAuBC,EAAsBC,EAAgBC,GAChE,IAAIC,EAA8C,KAElD,UAAWF,IAAU,SAAU,CAC3B,IACIE,EAAcT,KAAKG,MAAMI,EAC7B,CAAE,MAAOG,GACLd,KAAKD,KAAKgB,gBAAgBL,EAAcC,EAAO,MAC/C,MACJ,CACJ,KAAO,CACHE,EAAcF,CAClB,CAEA,GAAIE,IAAgB,KAAM,CACtBb,KAAKD,KAAKgB,gBAAgBL,EAAcC,EAAO,MAC/C,MACJ,CAGA,GAAIX,KAAKH,uBAAyBS,EAAUO,EAAab,KAAKH,uBAAwB,CAClF,GAAIG,KAAKD,KAAKiB,YAAY,aAAc,CACpC1B,EAAO2B,MAAM,WAAY,oCAAoCP,IAAgB,mBACjF,CACAV,KAAKD,KAAKgB,gBAAgBL,EAAcC,EAAOC,GAC/C,MACJ,CAGA,GAAIZ,KAAKJ,uBAAyBU,EAAUO,EAAab,KAAKJ,uBAAwB,CAClF,GAAII,KAAKD,KAAKiB,YAAY,aAAc,CACpC1B,EAAO2B,MAAM,WAAY,oBAAoBP,IAAgB,mBACjE,CACAV,KAAKD,KAAKgB,gBAAgBL,EAAcC,EAAOC,GAC/C,MACJ,CAEAZ,KAAKH,sBAAwBqB,EAAO,KAAM,CAAC,EAAGL,GAE9C,GAAIb,KAAKD,KAAKiB,YAAY,aAAc,CACpC1B,EAAO2B,MAAM,WAAY,mCAAmCP,IAAgB,mBAChF,CAEAV,KAAKD,KAAKgB,gBAAgBL,EAAcC,EAAO,MAE/C,MAAMQ,EAAenB,KAAKD,KAAKqB,kBAC/B,IAAKD,EAAc,CACfnB,KAAKD,KAAKsB,aACV,MACJ,CAEA,IACIF,EAAaG,WAAWC,QAAQV,EAAa,OAE7C,IAAKb,KAAKD,KAAKiB,YAAY,4BAA8BhB,KAAKD,KAAKyB,kBAAoB,WAAY,CAC/F,MAAMC,EAAoBjC,EAAiBkC,oBAAoBb,GAC/D,MAAMc,EAAe3B,KAAKD,KAAKyB,kBAC/B,IAAKlB,EAAUmB,EAAmBE,GAAe,CAC7C3B,KAAKD,KAAK6B,0BACV5B,KAAKD,KAAKsB,YACd,CACJ,CACJ,CAAE,MAAOP,GACL,MAAMe,EAAM,sBAAsBnB,MAAoBI,EAAYgB,QAClExC,EAAOyC,MAAM,WAAYF,EAAK,oBAC9B,MAAM,IAAIG,MAAMH,EACpB,CACJ,EACH,IAAAI,EAAA,CAAAC,WAAA,MAAAD,EAAAvC,mBAAA,OAAAuC,CAAA","ignoreList":[],"sourceRoot":"controls/host/delegates"}},{"offset":{"line":11,"column":0},"map":{"version":3,"names":["Logger","_____utils_Logger","DialogDelegate","activeDialog","requestedWidth","calculatedOptimalWidth","constructor","host","this","openInDialog","title","submitButtonText","isGenerated","cancelButtonText","dialogWidth","parentView","busyDialog","BusyDialog","text","open","genResult","generate","Promise","err","close","error","message","finalWidth","dialog","Dialog","contentWidth","content","beginButton","Button","type","press","success","triggerSubmit","fireEvent","fieldPath","endButton","afterClose","destroy","addDependent","updateDialogWidthDynamically","optimalWidth","setContentWidth","__exports","__esModule"],"sources":["DialogDelegate.ts"],"sourcesContent":["import Dialog from \"sap/m/Dialog\";\nimport Button from \"sap/m/Button\";\nimport Control from \"sap/ui/core/Control\";\nimport BusyDialog from \"sap/m/BusyDialog\";\nimport { Logger } from \"../../../utils/Logger\";\n\nexport interface IHostDialog {\n generate(): Promise<void> | void;\n triggerSubmit(): boolean;\n fireEvent(eventName: string, parameters?: Record<string, unknown>): this;\n}\n\n/**\n * Extracts all popup and dialog generation logic from the Host control.\n */\nexport class DialogDelegate {\n private host: IHostDialog & Control;\n private activeDialog: Dialog | null = null;\n private requestedWidth: string = \"auto\";\n private calculatedOptimalWidth: string = \"auto\";\n\n /**\n * Initializes a new DialogDelegate to handle dialog-based rendering.\n * @param host The parent DynamicHost or GeneratorHost control.\n */\n constructor(host: IHostDialog & Control) {\n this.host = host;\n }\n\n /**\n * Dialog Modality: Opens the generated layout inside a sap.m.Dialog.\n * Automatically wires up customizable submit (default: 'OK') and 'Cancel' buttons.\n */\n public async openInDialog(title: string = \"Form\", submitButtonText: string = \"OK\", isGenerated: boolean, cancelButtonText: string = \"Cancel\", dialogWidth: string = \"auto\", parentView?: Control): Promise<void> {\n this.requestedWidth = dialogWidth;\n this.calculatedOptimalWidth = dialogWidth; // Default fallback\n\n // Mask the complex asynchronous rendering to prevent visual snapping\n const busyDialog = new BusyDialog({ text: \"Building Form...\" });\n busyDialog.open();\n\n try {\n // Force manual generation BEFORE mounting the dialog so the optimal width is perfectly calculated first\n const genResult = this.host.generate();\n if (genResult instanceof Promise) {\n await genResult;\n }\n } catch (err) {\n busyDialog.close();\n Logger.error(\"[MetaUI] Catastrophic error during pre-generation of dialog content\", (err as Error).message, \"DialogDelegate\");\n return;\n }\n\n busyDialog.close();\n\n // The Engine heuristically updated `calculatedOptimalWidth` during `generate()`. Apply it on frame 1.\n const finalWidth = this.requestedWidth === \"auto\" && this.calculatedOptimalWidth !== \"auto\" ? this.calculatedOptimalWidth : this.requestedWidth;\n\n const dialog = new Dialog({\n title: title,\n contentWidth: finalWidth,\n content: [this.host], // Mount host inside the dialog\n beginButton: new Button({\n text: submitButtonText,\n type: \"Emphasized\",\n press: () => {\n try {\n const success = this.host.triggerSubmit();\n if (success) {\n dialog.close();\n }\n } catch (err) {\n Logger.error(\"[MetaUI] Catastrophic error during validation/submit pipeline\", (err as Error).message, \"DialogDelegate\");\n this.host.fireEvent(\"validationError\", { fieldPath: \"root\", message: (err as Error).message });\n }\n }\n }),\n endButton: new Button({\n text: cancelButtonText,\n press: () => {\n this.host.fireEvent(\"cancel\");\n dialog.close();\n }\n }),\n afterClose: () => {\n this.activeDialog = null;\n dialog.destroy();\n }\n });\n\n this.activeDialog = dialog;\n\n if (parentView && typeof parentView.addDependent === \"function\") {\n parentView.addDependent(dialog);\n }\n\n dialog.open();\n }\n\n /**\n * Allows the Engine to retroactively expand the dialog once the schema is fully parsed.\n */\n public updateDialogWidthDynamically(optimalWidth: string): void {\n this.calculatedOptimalWidth = optimalWidth;\n // Only dynamically stretch if the dialog is ALREADY open (e.g., hybrid inference late-loading)\n if (this.activeDialog && this.requestedWidth === \"auto\" && optimalWidth !== \"auto\") {\n this.activeDialog.setContentWidth(optimalWidth);\n }\n }\n}\n"],"mappings":"AAAA,sMAISA,EAAMC,EAAA,UAWR,MAAMC,EAEDC,aAA8B,KAC9BC,eAAyB,OACzBC,uBAAiC,OAMzCC,YAAYC,GACRC,KAAKD,KAAOA,CAChB,CAMA,kBAAaE,CAAaC,EAAgB,OAAQC,EAA2B,KAAMC,EAAsBC,EAA2B,SAAUC,EAAsB,OAAQC,GACxKP,KAAKJ,eAAiBU,EACtBN,KAAKH,uBAAyBS,EAG9B,MAAME,EAAa,IAAIC,EAAW,CAAEC,KAAM,qBAC1CF,EAAWG,OAEX,IAEI,MAAMC,EAAYZ,KAAKD,KAAKc,WAC5B,GAAID,aAAqBE,QAAS,OACxBF,CACV,CACJ,CAAE,MAAOG,GACLP,EAAWQ,QACXxB,EAAOyB,MAAM,sEAAwEF,EAAcG,QAAS,kBAC5G,MACJ,CAEAV,EAAWQ,QAGX,MAAMG,EAAanB,KAAKJ,iBAAmB,QAAUI,KAAKH,yBAA2B,OAASG,KAAKH,uBAAyBG,KAAKJ,eAEjI,MAAMwB,EAAS,IAAIC,EAAO,CACtBnB,MAAOA,EACPoB,aAAcH,EACdI,QAAS,CAACvB,KAAKD,MACfyB,YAAa,IAAIC,EAAO,CACpBf,KAAMP,EACNuB,KAAM,aACNC,MAAOA,KACH,IACI,MAAMC,EAAU5B,KAAKD,KAAK8B,gBAC1B,GAAID,EAAS,CACTR,EAAOJ,OACX,CACJ,CAAE,MAAOD,GACLvB,EAAOyB,MAAM,gEAAkEF,EAAcG,QAAS,kBACtGlB,KAAKD,KAAK+B,UAAU,kBAAmB,CAAEC,UAAW,OAAQb,QAAUH,EAAcG,SACxF,KAGRc,UAAW,IAAIP,EAAO,CAClBf,KAAML,EACNsB,MAAOA,KACH3B,KAAKD,KAAK+B,UAAU,UACpBV,EAAOJ,WAGfiB,WAAYA,KACRjC,KAAKL,aAAe,KACpByB,EAAOc,aAIflC,KAAKL,aAAeyB,EAEpB,GAAIb,UAAqBA,EAAW4B,eAAiB,WAAY,CAC7D5B,EAAW4B,aAAaf,EAC5B,CAEAA,EAAOT,MACX,CAKOyB,6BAA6BC,GAChCrC,KAAKH,uBAAyBwC,EAE9B,GAAIrC,KAAKL,cAAgBK,KAAKJ,iBAAmB,QAAUyC,IAAiB,OAAQ,CAChFrC,KAAKL,aAAa2C,gBAAgBD,EACtC,CACJ,EACH,IAAAE,EAAA,CAAAC,WAAA,MAAAD,EAAA7C,iBAAA,OAAA6C,CAAA","ignoreList":[],"sourceRoot":"controls/host/delegates"}},{"offset":{"line":12,"column":0},"map":{"version":3,"names":["Logger","_____utils_Logger","ODataDelegate","odataType","isSyncing","constructor","host","context","this","detectODataType","model","getModel","sClassName","getMetadata","getName","indexOf","syncToEngine","requestObject","then","oData","pushPayload","catch","err","error","message","getObject","cleanData","key","Object","keys","startsWith","setProperty","handleFieldChange","fieldPath","value","getProperty","debug","e","__exports","__esModule"],"sources":["ODataDelegate.ts"],"sourcesContent":["import { DynamicHost } from \"../DynamicHost\";\nimport { Logger } from \"../../../utils/Logger\";\nimport ODataV4Context from \"sap/ui/model/odata/v4/Context\";\nimport Context from \"sap/ui/model/Context\";\n\n/**\n * Universal OData Delegate.\n * Natively detects and manages two-way synchronization for both OData V2 and V4 contexts\n * without requiring controller-level mappings.\n */\nexport class ODataDelegate {\n private host: DynamicHost;\n private context: ODataV4Context | Context;\n private odataType: \"V2\" | \"V4\" | null = null;\n private isSyncing: boolean = false;\n\n /**\n * Initializes a new instance of the ODataDelegate.\n * \n * @param {DynamicHost} host The parent MetaUI DynamicHost instance managing the UI generation.\n * @param {Context} context The active UI5 Model Context bound to the host.\n */\n constructor(host: DynamicHost, context: ODataV4Context | Context) {\n this.host = host;\n this.context = context;\n this.detectODataType();\n }\n\n /**\n * Evaluates the underlying UI5 Model bound to the context to determine if it is an\n * OData V2 or OData V4 model. This determination drives the synchronization strategy.\n * \n * @private\n */\n private detectODataType(): void {\n const model = this.context.getModel();\n // sap.ui.model.odata.v4.ODataModel\n // sap.ui.model.odata.v2.ODataModel\n const sClassName = model.getMetadata().getName();\n if (sClassName.indexOf(\"v4\") > -1) {\n this.odataType = \"V4\";\n } else if (sClassName.indexOf(\"v2\") > -1 || sClassName.indexOf(\"ODataModel\") > -1) {\n this.odataType = \"V2\";\n }\n }\n\n /**\n * Extracts the full entity payload from the bound OData context and pushes it to the Engine.\n * V4 uses an asynchronous requestObject(), while V2 retrieves it synchronously.\n * \n * @public\n */\n public syncToEngine(): void {\n if (!this.odataType) return;\n\n if (this.odataType === \"V4\") {\n // V4 uses async requestObject()\n if (typeof this.context.requestObject === \"function\") {\n this.context.requestObject().then((oData: unknown) => {\n this.pushPayload(oData);\n }).catch((err: Error) => {\n Logger.error(\"[MetaUI]\", \"Failed to extract V4 Context payload: \" + err.message, \"ODataDelegate\");\n });\n }\n } else if (this.odataType === \"V2\") {\n // V2 uses sync getObject()\n const oData = this.context.getObject();\n if (oData) {\n this.pushPayload(oData);\n }\n }\n }\n\n /**\n * Cleans the raw OData payload by stripping framework metadata properties (keys starting with '@' or '__')\n * and pushes the sanitized business data into the MetaUI DynamicHost state manager.\n * \n * @param {unknown} oData The raw JSON object extracted from the OData model context.\n * @private\n */\n private pushPayload(oData: unknown): void {\n if (!oData) return;\n \n // Remove OData metadata properties before pushing to MetaUI\n const cleanData = { ...(oData as Record<string, unknown>) };\n for (const key of Object.keys(cleanData)) {\n if (key.startsWith(\"@\") || key.startsWith(\"__\")) {\n delete cleanData[key];\n }\n }\n\n this.isSyncing = true;\n this.host.setProperty(\"data\", cleanData);\n this.isSyncing = false;\n }\n\n /**\n * Intercepts a field change from the MetaUI Engine and translates it into an OData PATCH.\n */\n public handleFieldChange(fieldPath: string, value: unknown): void {\n if (this.isSyncing || !this.odataType) return;\n\n try {\n if (this.odataType === \"V4\") {\n // V4 sets property directly on context\n this.context.setProperty(fieldPath, value);\n } else if (this.odataType === \"V2\") {\n // V2 sets property on model, specifying the context path\n const model = this.context.getModel();\n model.setProperty(fieldPath, value, this.context);\n }\n if (this.host.getProperty(\"debugMode\")) {\n Logger.debug(\"[MetaUI]\", `ODataDelegate Patched ${fieldPath} = ${value} via ${this.odataType}`, \"ODataDelegate\");\n }\n } catch (e) {\n Logger.error(\"[MetaUI]\", `Failed to patch OData context: ${(e as Error).message}`, \"ODataDelegate\");\n }\n }\n}\n"],"mappings":"AAAA,8IACSA,EAAMC,EAAA,UASR,MAAMC,EAGDC,UAAgC,KAChCC,UAAqB,MAQ7BC,YAAYC,EAAmBC,GAC3BC,KAAKF,KAAOA,EACZE,KAAKD,QAAUA,EACfC,KAAKC,iBACT,CAQQA,kBACJ,MAAMC,EAAQF,KAAKD,QAAQI,WAG3B,MAAMC,EAAaF,EAAMG,cAAcC,UACvC,GAAIF,EAAWG,QAAQ,OAAS,EAAG,CAC/BP,KAAKL,UAAY,IACrB,MAAO,GAAIS,EAAWG,QAAQ,OAAS,GAAKH,EAAWG,QAAQ,eAAiB,EAAG,CAC/EP,KAAKL,UAAY,IACrB,CACJ,CAQOa,eACH,IAAKR,KAAKL,UAAW,OAErB,GAAIK,KAAKL,YAAc,KAAM,CAEzB,UAAWK,KAAKD,QAAQU,gBAAkB,WAAY,CAClDT,KAAKD,QAAQU,gBAAgBC,KAAMC,IAC/BX,KAAKY,YAAYD,KAClBE,MAAOC,IACNtB,EAAOuB,MAAM,WAAY,yCAA2CD,EAAIE,QAAS,kBAEzF,CACJ,MAAO,GAAIhB,KAAKL,YAAc,KAAM,CAEhC,MAAMgB,EAAQX,KAAKD,QAAQkB,YAC3B,GAAIN,EAAO,CACPX,KAAKY,YAAYD,EACrB,CACJ,CACJ,CASQC,YAAYD,GAChB,IAAKA,EAAO,OAGZ,MAAMO,EAAY,IAAMP,GACxB,IAAK,MAAMQ,KAAOC,OAAOC,KAAKH,GAAY,CACtC,GAAIC,EAAIG,WAAW,MAAQH,EAAIG,WAAW,MAAO,QACtCJ,EAAUC,EACrB,CACJ,CAEAnB,KAAKJ,UAAY,KACjBI,KAAKF,KAAKyB,YAAY,OAAQL,GAC9BlB,KAAKJ,UAAY,KACrB,CAKO4B,kBAAkBC,EAAmBC,GACxC,GAAI1B,KAAKJ,YAAcI,KAAKL,UAAW,OAEvC,IACI,GAAIK,KAAKL,YAAc,KAAM,CAEzBK,KAAKD,QAAQwB,YAAYE,EAAWC,EACxC,MAAO,GAAI1B,KAAKL,YAAc,KAAM,CAEhC,MAAMO,EAAQF,KAAKD,QAAQI,WAC3BD,EAAMqB,YAAYE,EAAWC,EAAO1B,KAAKD,QAC7C,CACA,GAAIC,KAAKF,KAAK6B,YAAY,aAAc,CACpCnC,EAAOoC,MAAM,WAAY,yBAAyBH,OAAeC,SAAa1B,KAAKL,YAAa,gBACpG,CACJ,CAAE,MAAOkC,GACLrC,EAAOuB,MAAM,WAAY,kCAAmCc,EAAYb,UAAW,gBACvF,CACJ,EACH,IAAAc,EAAA,CAAAC,WAAA,MAAAD,EAAApC,gBAAA,OAAAoC,CAAA","ignoreList":[],"sourceRoot":"controls/host/delegates"}},{"offset":{"line":13,"column":0},"map":{"version":3,"names":["Logger","_____utils_Logger","ValidationDelegate","constructor","host","this","registerObject","control","unregisterObject","removeAllMessages","stateManager","getStateManager","getProperty","messageManager","Messaging","messages","getMessageModel","getData","messagesToRemove","filter","m","getMessageProcessor","getId","getModel","length","removeMessages","pushMessage","path","text","targetPath","replace","displayText","warn","addMessages","Message","message","type","coreLibrary","MessageType","Error","target","processor","addCustomError","fieldPath","code","clearCustomError","processorId","getTarget","getCode","mountCrashBoundary","error","errorPage","IllustratedMessage","title","description","setAggregation","__exports","__esModule"],"sources":["ValidationDelegate.ts"],"sourcesContent":["import IllustratedMessage from \"sap/m/IllustratedMessage\";\nimport Messaging from \"sap/ui/core/Messaging\";\nimport Control from \"sap/ui/core/Control\";\nimport { StateManager } from \"../../../core/StateManager\";\nimport { Logger } from \"../../../utils/Logger\";\nimport Message from \"sap/ui/core/message/Message\";\nimport coreLibrary from \"sap/ui/core/library\";\n\nexport interface IHostValidation {\n getProperty(name: string): unknown;\n setAggregation(aggregationName: string, object: sap.ui.core.Control, suppressInvalidate?: boolean): this;\n getStateManager(): StateManager | null;\n}\n\n/**\n * Handles Fiori MessageManager integration and provides a standardized Error Boundary UI fallback.\n */\nexport class ValidationDelegate {\n private host: IHostValidation;\n\n /**\n * Initializes the ValidationDelegate for registering controls to the global MessageManager.\n * @param host The parent host interface.\n */\n constructor(host: IHostValidation) {\n this.host = host;\n }\n\n /**\n * Registers a control and all its children with the global MessageManager.\n * (Deprecated: Native registration causes UI5 to aggressively clear custom schema validation messages \n * on every keystroke. MetaUI handles valueState manually via plugins).\n */\n public registerObject(control: Control): void {\n // Do nothing to prevent UI5 from hijacking valueState and clearing our manual messages\n }\n\n /**\n * Unregisters a control from the global MessageManager.\n */\n public unregisterObject(control: Control): void {\n // Do nothing\n }\n\n public removeAllMessages(): void {\n const stateManager = this.host.getStateManager();\n if (stateManager && this.host.getProperty(\"useMessageManager\")) {\n const messageManager = Messaging;\n const messages = messageManager.getMessageModel().getData();\n const messagesToRemove = messages.filter((m: sap.ui.core.message.Message) =>\n m.getMessageProcessor() && m.getMessageProcessor().getId() === stateManager.getModel().getId()\n );\n if (messagesToRemove && messagesToRemove.length > 0) {\n messageManager.removeMessages(messagesToRemove);\n }\n }\n }\n\n /**\n * Pushes a validation message to the console, and optionally to the MessageManager.\n */\n public pushMessage(path: string, text: string): void {\n const targetPath = path ? `/${path.replace(/^\\//, \"\")}` : \"\";\n const displayText = path ? `Field '${path}': ${text}` : text;\n\n if (path) {\n Logger.warn(`[MetaUI Validation Error] ${displayText}`);\n } else {\n Logger.warn(`[MetaUI Validation Error] Global - ${text}`);\n }\n\n if (this.host.getProperty(\"useMessageManager\") === true) {\n const messageManager = Messaging;\n const stateManager = this.host.getStateManager();\n messageManager.addMessages(new Message({\n message: displayText,\n type: coreLibrary.MessageType.Error,\n target: targetPath,\n processor: stateManager?.getModel()\n }));\n }\n }\n\n /**\n * Imperatively invalidates a field and highlights it with an error message.\n * Uses a specific 'CustomError' code to distinguish it from internal schema validations.\n * \n * @param fieldPath The internal JSON path of the field to highlight.\n * @param message The custom error message to display.\n */\n public addCustomError(fieldPath: string, message: string): void {\n if (this.host.getProperty(\"useMessageManager\") !== true) {\n return;\n }\n\n const stateManager = this.host.getStateManager();\n if (!stateManager) {\n return;\n }\n\n Messaging.addMessages(new Message({\n message: message,\n type: coreLibrary.MessageType.Error,\n target: `/${fieldPath.replace(/^\\//, \"\")}`,\n processor: stateManager.getModel(),\n code: \"CustomError\"\n }));\n }\n\n /**\n * Reverts a custom error state on a field, safely ignoring native schema validations.\n * \n * @param fieldPath The internal JSON path of the field to clear.\n */\n public clearCustomError(fieldPath: string): void {\n if (this.host.getProperty(\"useMessageManager\") !== true) {\n return;\n }\n\n const stateManager = this.host.getStateManager();\n if (!stateManager) {\n return;\n }\n\n const target = `/${fieldPath.replace(/^\\//, \"\")}`;\n const processorId = stateManager.getModel().getId();\n const messages = Messaging.getMessageModel().getData() as sap.ui.core.message.Message[];\n\n const messagesToRemove = messages.filter(m =>\n m.getTarget() === target &&\n m.getCode() === \"CustomError\" &&\n m.getMessageProcessor()?.getId() === processorId\n );\n\n if (messagesToRemove.length > 0) {\n Messaging.removeMessages(messagesToRemove);\n }\n }\n\n /**\n * Triggers a visual Error Page (Crash Boundary) when generation catastrophically fails.\n */\n public mountCrashBoundary(error: Error): void {\n Logger.error(\"[MetaUI] Engine failed to generate layout. Preventing Launchpad crash.\", error.message, \"ValidationDelegate\");\n\n const errorPage = new IllustratedMessage({\n title: \"UI Generation Failed\",\n description: \"The dynamic schema could not be rendered. Please check the Fiori console for diagnostic logs.\"\n });\n\n this.host.setAggregation(\"_content\", errorPage);\n }\n}\n"],"mappings":"AAAA,kQAISA,EAAMC,EAAA,UAaR,MAAMC,EAOTC,YAAYC,GACRC,KAAKD,KAAOA,CAChB,CAOOE,eAAeC,GAClB,CAMGC,iBAAiBD,GACpB,CAGGE,oBACH,MAAMC,EAAeL,KAAKD,KAAKO,kBAC/B,GAAID,GAAgBL,KAAKD,KAAKQ,YAAY,qBAAsB,CAC5D,MAAMC,EAAiBC,EACvB,MAAMC,EAAWF,EAAeG,kBAAkBC,UAClD,MAAMC,EAAmBH,EAASI,OAAQC,GACtCA,EAAEC,uBAAyBD,EAAEC,sBAAsBC,UAAYZ,EAAaa,WAAWD,SAE3F,GAAIJ,GAAoBA,EAAiBM,OAAS,EAAG,CACjDX,EAAeY,eAAeP,EAClC,CACJ,CACJ,CAKOQ,YAAYC,EAAcC,GAC7B,MAAMC,EAAaF,EAAO,IAAIA,EAAKG,QAAQ,MAAO,MAAQ,GAC1D,MAAMC,EAAcJ,EAAO,UAAUA,OAAUC,IAASA,EAExD,GAAID,EAAM,CACN3B,EAAOgC,KAAK,6BAA6BD,IAC7C,KAAO,CACH/B,EAAOgC,KAAK,sCAAsCJ,IACtD,CAEA,GAAIvB,KAAKD,KAAKQ,YAAY,uBAAyB,KAAM,CACrD,MAAMC,EAAiBC,EACvB,MAAMJ,EAAeL,KAAKD,KAAKO,kBAC/BE,EAAeoB,YAAY,IAAIC,EAAQ,CACnCC,QAASJ,EACTK,KAAMC,EAAYC,YAAYC,MAC9BC,OAAQX,EACRY,UAAW/B,GAAca,aAEjC,CACJ,CASOmB,eAAeC,EAAmBR,GACrC,GAAI9B,KAAKD,KAAKQ,YAAY,uBAAyB,KAAM,CACrD,MACJ,CAEA,MAAMF,EAAeL,KAAKD,KAAKO,kBAC/B,IAAKD,EAAc,CACf,MACJ,CAEAI,EAAUmB,YAAY,IAAIC,EAAQ,CAC9BC,QAASA,EACTC,KAAMC,EAAYC,YAAYC,MAC9BC,OAAQ,IAAIG,EAAUb,QAAQ,MAAO,MACrCW,UAAW/B,EAAaa,WACxBqB,KAAM,gBAEd,CAOOC,iBAAiBF,GACpB,GAAItC,KAAKD,KAAKQ,YAAY,uBAAyB,KAAM,CACrD,MACJ,CAEA,MAAMF,EAAeL,KAAKD,KAAKO,kBAC/B,IAAKD,EAAc,CACf,MACJ,CAEA,MAAM8B,EAAS,IAAIG,EAAUb,QAAQ,MAAO,MAC5C,MAAMgB,EAAcpC,EAAaa,WAAWD,QAC5C,MAAMP,EAAWD,EAAUE,kBAAkBC,UAE7C,MAAMC,EAAmBH,EAASI,OAAOC,GACrCA,EAAE2B,cAAgBP,GAClBpB,EAAE4B,YAAc,eAChB5B,EAAEC,uBAAuBC,UAAYwB,GAGzC,GAAI5B,EAAiBM,OAAS,EAAG,CAC7BV,EAAUW,eAAeP,EAC7B,CACJ,CAKO+B,mBAAmBC,GACtBlD,EAAOkD,MAAM,yEAA0EA,EAAMf,QAAS,sBAEtG,MAAMgB,EAAY,IAAIC,EAAmB,CACrCC,MAAO,uBACPC,YAAa,kGAGjBjD,KAAKD,KAAKmD,eAAe,WAAYJ,EACzC,EACH,IAAAK,EAAA,CAAAC,WAAA,MAAAD,EAAAtD,qBAAA,OAAAsD,CAAA","ignoreList":[],"sourceRoot":"controls/host/delegates"}},{"offset":{"line":14,"column":0},"map":{"version":3,"names":["Registry","___Registry","OperatorRegistry","register","a","b","ConditionEngine","constructor","schema","this","plugins","Map","handleEvent","fieldKey","isValid","registerPlugin","bindingPath","plugin","set","destroy","clear","__exports","__esModule"],"sources":["ConditionEngine.ts"],"sourcesContent":["/**\n * @file ConditionEngine.ts\n * @description Evaluates dynamic rules to alter the schema in real-time.\n */\n\nimport { IPlugin } from \"../interfaces/IPlugin\";\nimport { ISchema } from \"../interfaces/ISchema\";\nimport { Registry } from \"./Registry\";\n\nexport type ConditionOperator = (a: unknown, b: unknown) => boolean;\n\nexport const OperatorRegistry = new Registry<ConditionOperator>(\"Operators\");\n\n// Register basic default operators\nOperatorRegistry.register(\"==\", (a, b) => a == b);\nOperatorRegistry.register(\"===\", (a, b) => a === b);\nOperatorRegistry.register(\"!=\", (a, b) => a != b);\nOperatorRegistry.register(\"!==\", (a, b) => a !== b);\nOperatorRegistry.register(\">\", (a, b) => a > b);\nOperatorRegistry.register(\"<\", (a, b) => a < b);\nOperatorRegistry.register(\">=\", (a, b) => a >= b);\nOperatorRegistry.register(\"<=\", (a, b) => a <= b);\n\n/**\n * Engine that listens to the EventBus and evaluates cross-field dependencies (e.g. visibleOn, enabledOn).\n * It delegates actual evaluations to the configurable `OperatorRegistry`.\n * \n * @namespace nz.co.siliconst.ui5.metaui.core\n * @public\n */\nexport class ConditionEngine {\n /** The active form schema being evaluated. */\n private schema: ISchema;\n /**\n * Initializes the ConditionEngine with the active schema.\n * @param schema The current UI layout schema.\n */\n constructor(schema: ISchema) {\n this.schema = schema;\n }\n\n\n\n /** Internal map tracking active plugins against their binding paths for real-time state updates. */\n private plugins: Map<string, IPlugin> = new Map();\n\n /**\n * Internal handler to evaluate business rules when a field is updated.\n * @param fieldKey The key of the field that was changed\n * @param isValid Whether the field is currently valid\n */\n public handleEvent(fieldKey: string, isValid: boolean): void {\n // Evaluate conditions via registered operators if a rule system is added later\n }\n\n /**\n * Registers a rendered plugin so the condition engine can push dynamic state updates to it.\n * \n * @param bindingPath The JSON path representing the field within the payload.\n * @param plugin The instantiated plugin handling the field.\n */\n public registerPlugin(bindingPath: string, plugin: IPlugin): void {\n this.plugins.set(bindingPath, plugin);\n }\n\n /**\n * Cleans up listeners to prevent memory leaks on destruction.\n */\n public destroy(): void {\n this.plugins.clear();\n }\n}\n"],"mappings":"AAAA,4GAAA,MAOSA,EAAQC,EAAA,YAIV,MAAMC,EAAmB,IAAIF,EAA4B,aAGhEE,EAAiBC,SAAS,KAAM,CAACC,EAAGC,IAAMD,GAAKC,GAC/CH,EAAiBC,SAAS,MAAO,CAACC,EAAGC,IAAMD,IAAMC,GACjDH,EAAiBC,SAAS,KAAM,CAACC,EAAGC,IAAMD,GAAKC,GAC/CH,EAAiBC,SAAS,MAAO,CAACC,EAAGC,IAAMD,IAAMC,GACjDH,EAAiBC,SAAS,IAAK,CAACC,EAAGC,IAAMD,EAAIC,GAC7CH,EAAiBC,SAAS,IAAK,CAACC,EAAGC,IAAMD,EAAIC,GAC7CH,EAAiBC,SAAS,KAAM,CAACC,EAAGC,IAAMD,GAAKC,GAC/CH,EAAiBC,SAAS,KAAM,CAACC,EAAGC,IAAMD,GAAKC,GASxC,MAAMC,EAOTC,YAAYC,GACRC,KAAKD,OAASA,CAClB,CAKQE,QAAgC,IAAIC,IAOrCC,YAAYC,EAAkBC,GACjC,CASGC,eAAeC,EAAqBC,GACvCR,KAAKC,QAAQQ,IAAIF,EAAaC,EAClC,CAKOE,UACHV,KAAKC,QAAQU,OACjB,EACH,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAAnB,mBAAAmB,EAAAf,kBAAA,OAAAe,CAAA","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":15,"column":0},"map":{"version":3,"names":["DefaultLayoutGenerator","ensureLayout","schema","uiLayout","Array","isArray","length","type","props","items","properties","Object","keys","elements","this","generateElementsFromProperties","filter","e","label","title","basePath","key","prop","currentPath","push","ui","scope","error","msg","message","__ui5_require_async","then","m","Logger","Error","__exports","__esModule"],"sources":["DefaultLayoutGenerator.ts"],"sourcesContent":["/**\n * @file DefaultLayoutGenerator.ts\n * @description Automatically synthesizes a default UI layout for schemas that lack an explicit mapping.\n */\n\nimport { ISchema, ILayoutElement } from \"../interfaces/ISchema\";\n\n/**\n * Encapsulates the logic to dynamically build a safe, default layout orchestration\n * when the developer or backend fails to provide an explicit `uiLayout`.\n * \n * By elevating this into a dedicated utility, we avoid polluting layout engines\n * (like FormLayout or TableLayout) with structural inference responsibilities.\n * \n * @namespace nz.co.siliconst.ui5.metaui.core\n * @public\n */\nexport class DefaultLayoutGenerator {\n /**\n * Inspects a schema. If it has properties but no `uiLayout`, it synthesizes a default.\n * @param schema The ISchema dictionary.\n * @returns boolean True if a layout was synthesized, false if it already existed or was empty.\n */\n public static ensureLayout(schema: ISchema): boolean {\n // If it already has a valid array, do nothing\n if (schema.uiLayout && Array.isArray(schema.uiLayout) && schema.uiLayout.length > 0) {\n return false;\n }\n\n const isArray = schema.type === \"array\";\n const props = isArray ? schema.items?.properties : schema.properties;\n\n if (!props || Object.keys(props).length === 0) {\n return false; // Nothing to map\n }\n\n const elements = this.generateElementsFromProperties(props, \"#/properties\");\n\n if (isArray) {\n // Table layouts expect an array of flat Controls at the root uiLayout\n // For tables, we flatten the deep elements or just render the root level\n // To keep it safe, we'll just use the flat elements for tables\n schema.uiLayout = elements.filter(e => e.type === \"Control\");\n } else {\n // Form layouts expect a grouped structure\n schema.uiLayout = [\n {\n type: \"Group\",\n label: schema.title,\n elements: elements\n }\n ];\n }\n\n return true;\n }\n\n /**\n * Recursively traverses property metadata to synthesize generic Group and Control layout definitions.\n * @param props The properties object from the schema.\n * @param basePath The absolute JSON scope path to prefix bindings.\n * @returns An array of generated layout element descriptors.\n */\n private static generateElementsFromProperties(props: Record<string, import(\"../interfaces/ISchema\").IPropertyMetadata>, basePath: string): ILayoutElement[] {\n const elements: ILayoutElement[] = [];\n for (const key of Object.keys(props)) {\n try {\n const prop = props[key];\n const currentPath = `${basePath}/${key}`;\n\n if (prop.type === \"object\" && prop.properties) {\n elements.push({\n type: \"Group\",\n label: prop.ui?.label || key,\n elements: this.generateElementsFromProperties(prop.properties, `${currentPath}/properties`)\n });\n } else {\n elements.push({\n type: \"Control\",\n scope: currentPath\n });\n }\n } catch (error) {\n // Do not swallow errors. A failure to synthesize a property is a critical failure.\n const msg = `[MetaUI] DefaultLayoutGenerator failed to synthesize property '${key}': ${(error as Error).message}`;\n import(\"../utils/Logger\").then(m => m.Logger.error(msg));\n throw new Error(msg);\n }\n }\n return elements;\n }\n}\n"],"mappings":"AAAA,kWAiBO,MAAMA,EAMT,mBAAcC,CAAaC,GAEvB,GAAIA,EAAOC,UAAYC,MAAMC,QAAQH,EAAOC,WAAaD,EAAOC,SAASG,OAAS,EAAG,CACjF,OAAO,KACX,CAEA,MAAMD,EAAUH,EAAOK,OAAS,QAChC,MAAMC,EAAQH,EAAUH,EAAOO,OAAOC,WAAaR,EAAOQ,WAE1D,IAAKF,GAASG,OAAOC,KAAKJ,GAAOF,SAAW,EAAG,CAC3C,OAAO,KACX,CAEA,MAAMO,EAAWC,KAAKC,+BAA+BP,EAAO,gBAE5D,GAAIH,EAAS,CAITH,EAAOC,SAAWU,EAASG,OAAOC,GAAKA,EAAEV,OAAS,UACtD,KAAO,CAEHL,EAAOC,SAAW,CACd,CACII,KAAM,QACNW,MAAOhB,EAAOiB,MACdN,SAAUA,GAGtB,CAEA,OAAO,IACX,CAQA,qCAAeE,CAA+BP,EAA0EY,GACpH,MAAMP,EAA6B,GACnC,IAAK,MAAMQ,KAAOV,OAAOC,KAAKJ,GAAQ,CAClC,IACI,MAAMc,EAAOd,EAAMa,GACnB,MAAME,EAAc,GAAGH,KAAYC,IAEnC,GAAIC,EAAKf,OAAS,UAAYe,EAAKZ,WAAY,CAC3CG,EAASW,KAAK,CACVjB,KAAM,QACNW,MAAOI,EAAKG,IAAIP,OAASG,EACzBR,SAAUC,KAAKC,+BAA+BO,EAAKZ,WAAY,GAAGa,iBAE1E,KAAO,CACHV,EAASW,KAAK,CACVjB,KAAM,UACNmB,MAAOH,GAEf,CACJ,CAAE,MAAOI,GAEL,MAAMC,EAAM,kEAAkEP,OAAUM,EAAgBE,UACxGC,EAAO,mBAAmBC,KAAKC,GAAKA,EAAEC,OAAON,MAAMC,IACnD,MAAM,IAAIM,MAAMN,EACpB,CACJ,CACA,OAAOf,CACX,EACH,IAAAsB,EAAA,CAAAC,WAAA,MAAAD,EAAAnC,yBAAA,OAAAmC,CAAA","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":16,"column":0},"map":{"version":3,"names":["ConditionEngine","___ConditionEngine","PluginRegistry","___PluginRegistry","Logger","___utils_Logger","DefaultLayoutGenerator","___DefaultLayoutGenerator","Engine","conditionEngine","activePlugins","isEditable","hasPartialRenderingErrors","useMessageManager","constructor","editable","this","build","schema","model","modelName","onSubmit","engineScopeId","onChange","activeModel","isValid","fieldKey","errorMessage","controlId","handleEvent","ensureLayout","warn","layoutStrategy","type","layoutManager","getInstance","getLayout","render","error","msg","message","showErrorPopup","Text","text","generateField","fieldMeta","bindingPath","isTemplate","plugin","getPlugin","ui","widget","setEditable","setUseMessageManager","push","path","scopeId","undefined","control","registerPlugin","generateLayout","validateAll","applyVisualState","errors","item","result","validate","setVisualValidationState","replace","name","getPluginByPath","cleanPath","startsWith","match","find","p","destroy","messageManager","Messaging","existingMessages","getMessageModel","getData","messagesToRemove","targetPath","matched","filter","getTarget","getMessageProcessor","getId","length","removeMessages","__exports","__esModule"],"sources":["Engine.ts"],"sourcesContent":["/**\n * @file Engine.ts\n * @description The central orchestrator that routes data between the Layout Factory and Plugin Registry (v2).\n */\n\nimport { ISchema, IPropertyMetadata } from \"../interfaces/ISchema\";\nimport { ILayoutManager } from \"../interfaces/ILayoutManager\";\nimport { IPlugin, IPluginValidationResult } from \"../interfaces/IPlugin\";\nimport { ConditionEngine } from \"./ConditionEngine\";\nimport { PluginRegistry } from \"./PluginRegistry\";\nimport Control from \"sap/ui/core/Control\";\nimport VBox from \"sap/m/VBox\";\nimport Text from \"sap/m/Text\";\nimport { Logger } from \"../utils/Logger\";\nimport { DefaultLayoutGenerator } from \"./DefaultLayoutGenerator\";\nimport Core from \"sap/ui/core/Core\";\nimport Messaging from \"sap/ui/core/Messaging\";\n\n/**\n * The Engine is responsible for translating a normalized schema into a physical UI5 layout.\n * It delegates layout generation to the configured `LayoutManager` and field generation to the `PluginRegistry`.\n * It strictly routes execution flow and tracks active plugins for validation.\n * It embodies the \"Plugin-First Philosophy\" by routing all complex field and layout rendering\n * through discrete, decoupled plugins rather than handling native overrides.\n * \n * @namespace nz.co.siliconst.ui5.metaui.core\n * @public\n */\nexport class Engine {\n /** Handles dynamic conditional logic across the active form. */\n private conditionEngine: ConditionEngine | null = null;\n\n /** Array of all instantiated plugins generated during the current build. */\n private activePlugins: { plugin: IPlugin, path: string }[] = [];\n\n /** Deterministic scope ID injected by the host control to prevent clone collisions. */\n public engineScopeId?: string;\n\n private activeModel?: sap.ui.model.Model;\n\n /** Callback to notify the host that an internal field changed. */\n public onChange?: (isValid: boolean, fieldKey?: string, errorMessage?: string, controlId?: string) => void;\n\n /** Tracks whether the entire engine is running in Editable mode. */\n public readonly isEditable: boolean = true;\n\n /** Tracks if any fields or sub-layouts failed to render, requiring a warning strip. */\n public hasPartialRenderingErrors: boolean = false;\n\n /** Tracks whether the engine should delegate visual state to the global MessageManager. */\n public readonly useMessageManager: boolean = false;\n\n /**\n * Initializes a new Engine instance.\n * @param editable Whether the engine should render form fields as editable or read-only.\n * @param useMessageManager Whether to delegate visual state to UI5 MessageManager.\n */\n constructor(editable: boolean = true, useMessageManager: boolean = false) {\n this.isEditable = editable;\n this.useMessageManager = useMessageManager;\n }\n\n /**\n * Bootstraps the layout generation process by resolving the correct layout strategy.\n * \n * @param schema The normalized JSON schema representing the view.\n * @param model The active StateManager JSONModel instance.\n * @param modelName The UI5 model alias used for isolation.\n * @param onSubmit Callback fired when form is submitted.\n * @param engineScopeId Deterministic scope ID for this engine instance.\n * @param onChange Callback fired when field values change.\n * @returns The generated root UI5 Control container.\n */\n public build(schema: ISchema, model: sap.ui.model.Model, modelName: string = \"meta\", onSubmit?: () => void, engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string, errorMessage?: string, controlId?: string) => void): Control {\n this.conditionEngine = new ConditionEngine(schema);\n this.activePlugins = [];\n this.activeModel = model;\n this.engineScopeId = engineScopeId;\n this.onChange = (isValid: boolean, fieldKey?: string, errorMessage?: string, controlId?: string) => {\n if (this.conditionEngine && fieldKey) {\n this.conditionEngine.handleEvent(fieldKey, isValid);\n }\n if (onChange) {\n onChange(isValid, fieldKey, errorMessage, controlId);\n }\n };\n\n try {\n // Intercept and synthesize a default layout if the developer/backend failed to provide one\n if (DefaultLayoutGenerator.ensureLayout(schema)) {\n Logger.warn(\"[MetaUI Engine] Missing 'uiLayout' array in schema. Synthesized a default layout mapping to prevent a blank render.\");\n }\n\n const layoutStrategy = schema.layoutStrategy || (schema.type === \"array\" ? \"table\" : \"form\");\n const layoutManager = PluginRegistry.getInstance().getLayout(layoutStrategy);\n\n return layoutManager.render(schema, modelName, this, onSubmit);\n } catch (error) {\n this.hasPartialRenderingErrors = true;\n const msg = (error as Error).message;\n Logger.error(\"[MetaUI Engine] Critical error during layout generation\", msg);\n Logger.showErrorPopup(`Engine failed to generate the layout.\\n\\nDetails: ${msg}`);\n return new Text({ text: \"Critical Layout Error\" });\n }\n }\n\n /**\n * Instantiates the correct plugin for a specific field based on type and widget hints,\n * and tracks the plugin for global validation.\n * \n * @param fieldMeta The metadata schema specific to the field.\n * @param bindingPath The JSON path representing the field within the payload.\n * @param modelName The UI5 JSONModel name used for data binding.\n * @returns The generated UI5 Control for the field.\n */\n public generateField(fieldMeta: IPropertyMetadata, bindingPath: string, modelName: string, isTemplate: boolean = false): Control {\n try {\n const plugin = PluginRegistry.getInstance().getPlugin(fieldMeta.type || \"string\", fieldMeta.ui?.widget);\n plugin.setEditable(this.isEditable);\n \n if (typeof plugin.setUseMessageManager === \"function\") {\n plugin.setUseMessageManager(this.useMessageManager);\n }\n\n if (!isTemplate) {\n this.activePlugins.push({ plugin, path: bindingPath });\n }\n const scopeId = isTemplate ? undefined : this.engineScopeId;\n const control = plugin.render(fieldMeta, bindingPath, modelName, scopeId, this.onChange);\n\n if (this.conditionEngine) {\n this.conditionEngine.registerPlugin(bindingPath, plugin);\n }\n\n return control;\n } catch (error) {\n this.hasPartialRenderingErrors = true;\n const msg = (error as Error).message;\n Logger.error(`[MetaUI Engine] Failed to generate field at ${bindingPath}`, msg);\n Logger.showErrorPopup(`Failed to generate field '${bindingPath}'.\\n\\nDetails: ${msg}`);\n return new Text({ text: `[Error generating field ${bindingPath}]` });\n }\n }\n\n /**\n * Generates a sub-layout (like an embedded table or nested form) without \n * destroying the current Engine state or Condition tracking.\n * \n * @param schema The normalized JSON schema representing the view.\n * @param modelName The UI5 JSONModel name used for data binding (defaults to \"meta\").\n * @param bindingPath Optional path to bind the sub-layout to a specific array/object property.\n * @returns The generated root UI5 Control container.\n */\n public generateLayout(schema: ISchema, modelName: string, bindingPath?: string): Control {\n try {\n const layoutStrategy = schema.layoutStrategy || (schema.type === \"array\" ? \"table\" : \"form\");\n const layoutManager = PluginRegistry.getInstance().getLayout(layoutStrategy);\n return layoutManager.render(schema, modelName, this, undefined, bindingPath);\n } catch (error) {\n this.hasPartialRenderingErrors = true;\n const msg = (error as Error).message;\n Logger.error(`[MetaUI Engine] Critical error generating sub-layout for ${bindingPath}`, msg);\n Logger.showErrorPopup(`Engine failed to generate a sub-layout.\\n\\nDetails: ${msg}`);\n return new Text({ text: \"Critical Sub-Layout Error\" });\n }\n }\n\n /**\n * Iterates through all active plugins and triggers their internal validation pipelines.\n * \n * @param applyVisualState If true, explicitly instructs the plugin to natively paint its own ValueState.\n * @returns {IPluginValidationResult[]} Array of validation error objects. Empty array if valid.\n */\n public validateAll(applyVisualState: boolean = false): IPluginValidationResult[] {\n const errors: IPluginValidationResult[] = [];\n for (const item of this.activePlugins) {\n try {\n const result = item.plugin.validate();\n if (applyVisualState && typeof item.plugin.setVisualValidationState === \"function\") {\n item.plugin.setVisualValidationState(result.isValid, result.errorMessage);\n }\n \n if (!result.isValid) {\n // Ensure the path is bound to the error so GeneratorHost knows where to target it\n result.fieldKey = result.fieldKey || item.path.replace(/^\\//, \"\");\n errors.push(result);\n // Add console log to find which plugin fails silently\n Logger.error(\"[MetaUI Validation] Plugin failed validation silently:\", item.path || item.plugin.constructor.name);\n }\n } catch (error) {\n Logger.error(`[MetaUI Engine] Error validating plugin at ${item.path}`, (error as Error).message);\n }\n }\n return errors;\n }\n\n /**\n * Retrieves an active plugin instance by its absolute binding path.\n * Useful for programmatic field manipulation (e.g., custom error injection).\n * \n * @param path The binding path (e.g. \"/General/CustomerName\").\n * @returns {IPlugin | undefined} The plugin instance, or undefined if not found.\n */\n public getPluginByPath(path: string): import(\"../interfaces/IPlugin\").IPlugin | undefined {\n const cleanPath = path.startsWith(\"/\") ? path : `/${path}`;\n const match = this.activePlugins.find(p => p.path === cleanPath || p.path === `/${cleanPath}`);\n return match ? match.plugin : undefined;\n }\n\n /**\n * Cleans up internal state and destroys the condition engine to prevent memory leaks.\n */\n public destroy(): void {\n if (this.conditionEngine) {\n this.conditionEngine.destroy();\n this.conditionEngine = null;\n }\n\n // ------------------------------------------------------------------------\n // Ghost Error Prevention\n // Flush MessageManager for active plugins before destroying their controls\n // ------------------------------------------------------------------------\n const messageManager = Messaging;\n const existingMessages = messageManager.getMessageModel().getData();\n const messagesToRemove: sap.ui.core.message.Message[] = [];\n\n for (const item of this.activePlugins) {\n if (this.activeModel) {\n const targetPath = `/${item.path.replace(/^\\//, \"\")}`;\n const matched = existingMessages.filter((msg: sap.ui.core.message.Message) =>\n msg.getTarget() === targetPath && msg.getMessageProcessor() && msg.getMessageProcessor().getId() === this.activeModel.getId()\n );\n messagesToRemove.push(...matched);\n }\n if (typeof item.plugin.destroy === \"function\") {\n item.plugin.destroy();\n }\n }\n\n if (messagesToRemove.length > 0) {\n messageManager.removeMessages(messagesToRemove);\n }\n\n this.activePlugins = [];\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":17,"column":0},"map":{"version":3,"names":["Registry","___Registry","PatternValidatorPlugin","___plugins_validators_PatternValidatorPlugin","MinLengthValidatorPlugin","___plugins_validators_MinLengthValidatorPlugin","RangeValidatorPlugin","___plugins_validators_RangeValidatorPlugin","UrlValidatorPlugin","___plugins_validators_UrlValidatorPlugin","IbanValidatorPlugin","___plugins_validators_IbanValidatorPlugin","EmailValidatorPlugin","___plugins_validators_EmailValidatorPlugin","DateFormatterPlugin","___plugins_formatters_DateFormatterPlugin","PhoneFormatterPlugin","___plugins_formatters_PhoneFormatterPlugin","TextCaseFormatterPlugin","___plugins_formatters_TextCaseFormatterPlugin","Logger","___utils_Logger","RequiredValidator","validate","parsedValue","args","undefined","isValid","errorMessage","MaxLengthValidator","length","PipelineManager","formatters","parsers","validators","constructor","this","register","executeValidation","requestedValidators","argsMap","rule","validator","get","result","error","msg","message","warn","GlobalPipeline","__exports","__esModule"],"sources":["PipelineManager.ts"],"sourcesContent":["/**\n * @file PipelineManager.ts\n * @description Central manager for the data manipulation pipeline. \n * Orchestrates Formatting, Parsing, and Validating data using the generic Registry.\n */\n\nimport { Registry } from \"./Registry\";\nimport { IFormatter, IParser, IValidator, IValidationResult } from \"../interfaces/IPipeline\";\nimport { PatternValidatorPlugin } from \"../plugins/validators/PatternValidatorPlugin\";\nimport { MinLengthValidatorPlugin } from \"../plugins/validators/MinLengthValidatorPlugin\";\nimport { RangeValidatorPlugin } from \"../plugins/validators/RangeValidatorPlugin\";\nimport { UrlValidatorPlugin } from \"../plugins/validators/UrlValidatorPlugin\";\nimport { IbanValidatorPlugin } from \"../plugins/validators/IbanValidatorPlugin\";\nimport { EmailValidatorPlugin } from \"../plugins/validators/EmailValidatorPlugin\";\nimport { DateFormatterPlugin } from \"../plugins/formatters/DateFormatterPlugin\";\nimport { PhoneFormatterPlugin } from \"../plugins/formatters/PhoneFormatterPlugin\";\nimport { TextCaseFormatterPlugin } from \"../plugins/formatters/TextCaseFormatterPlugin\";\nimport { Logger } from \"../utils/Logger\";\n\n// --- Built-in Default Validators ---\n/** Internal rule for required fields. */\nclass RequiredValidator implements IValidator {\n /** Validates that the value is not null, undefined, or empty string. */\n validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (parsedValue === null || parsedValue === undefined || parsedValue === \"\") {\n return { isValid: false, errorMessage: \"This field is required.\" };\n }\n return { isValid: true };\n }\n}\n\n/** Internal rule for string maximum length. */\nclass MaxLengthValidator implements IValidator {\n /** Validates that a string does not exceed the provided argument length. */\n validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (typeof parsedValue === \"string\" && args && typeof args === \"number\") {\n if (parsedValue.length > args) {\n return { isValid: false, errorMessage: `Maximum length is ${args} characters.` };\n }\n }\n return { isValid: true };\n }\n}\n\n\n/**\n * The core engine responsible for marshalling data through the validation, formatting, and parsing phases.\n * Pluggable design allows new validators to be registered dynamically.\n * \n * @namespace nz.co.siliconst.ui5.metaui.core\n * @public\n */\nexport class PipelineManager {\n /** Registry of data formatters applied before pushing to the UI. */\n public readonly formatters: Registry<IFormatter> = new Registry<IFormatter>(\"Formatters\");\n /** Registry of data parsers applied when pulling data from the UI. */\n public readonly parsers: Registry<IParser> = new Registry<IParser>(\"Parsers\");\n /** Registry of business logic validators. */\n public readonly validators: Registry<IValidator> = new Registry<IValidator>(\"Validators\");\n\n /**\n * Bootstraps the PipelineManager with default validators (required, maxLength, email).\n */\n constructor() {\n // Register default validators\n this.validators.register(\"required\", new RequiredValidator());\n this.validators.register(\"maxLength\", new MaxLengthValidator());\n this.validators.register(\"pattern\", new PatternValidatorPlugin());\n this.validators.register(\"minLength\", new MinLengthValidatorPlugin());\n this.validators.register(\"range\", new RangeValidatorPlugin());\n this.validators.register(\"url\", new UrlValidatorPlugin());\n this.validators.register(\"iban\", new IbanValidatorPlugin());\n this.validators.register(\"email\", new EmailValidatorPlugin());\n\n // Register default formatters\n this.formatters.register(\"date\", new DateFormatterPlugin());\n this.formatters.register(\"phone\", new PhoneFormatterPlugin());\n this.formatters.register(\"textCase\", new TextCaseFormatterPlugin());\n }\n\n /**\n * Executes the validation pipeline sequentially. Fails fast on the first encountered error.\n * \n * @param parsedValue The raw extracted value from the UI control.\n * @param requestedValidators Array of validation rule keys (e.g. ['required', 'email']).\n * @param argsMap Optional map of parameters required by specific rules (e.g. { maxLength: 50 }).\n * @returns {IValidationResult} The final result state and any associated error message.\n */\n public executeValidation(parsedValue: unknown, requestedValidators: string[], argsMap?: Record<string, unknown>): IValidationResult {\n for (const rule of requestedValidators) {\n const validator = this.validators.get(rule);\n if (validator) {\n const args = argsMap ? argsMap[rule] : undefined;\n try {\n const result = validator.validate(parsedValue, args);\n if (!result.isValid) {\n return result; // Fast fail on first error\n }\n } catch (error) {\n const msg = (error as Error).message;\n Logger.error(`[MetaUI] PipelineManager: Validator '${rule}' crashed during execution.`, msg);\n return { isValid: false, errorMessage: `System validation error: ${msg}` };\n }\n } else {\n Logger.warn(`[MetaUI] PipelineManager: Requested validator '${rule}' not found in registry.`);\n }\n }\n return { isValid: true };\n }\n}\n\n/** \n * Singleton instance for global access to the active validation pipeline. \n * @public \n */\nexport const GlobalPipeline = new PipelineManager();\n"],"mappings":"AAAA,4iBAAA,MAMSA,EAAQC,EAAA,kBAERC,EAAsBC,EAAA,gCACtBC,EAAwBC,EAAA,kCACxBC,EAAoBC,EAAA,8BACpBC,EAAkBC,EAAA,4BAClBC,EAAmBC,EAAA,6BACnBC,EAAoBC,EAAA,8BACpBC,EAAmBC,EAAA,6BACnBC,EAAoBC,EAAA,8BACpBC,EAAuBC,EAAA,iCACvBC,EAAMC,EAAA,UAIf,MAAMC,EAEFC,SAASC,EAAsBC,GAC3B,GAAID,IAAgB,MAAQA,IAAgBE,WAAaF,IAAgB,GAAI,CACzE,MAAO,CAAEG,QAAS,MAAOC,aAAc,0BAC3C,CACA,MAAO,CAAED,QAAS,KACtB,EAIJ,MAAME,EAEFN,SAASC,EAAsBC,GAC3B,UAAWD,IAAgB,UAAYC,UAAeA,IAAS,SAAU,CACrE,GAAID,EAAYM,OAASL,EAAM,CAC3B,MAAO,CAAEE,QAAS,MAAOC,aAAc,qBAAqBH,gBAChE,CACJ,CACA,MAAO,CAAEE,QAAS,KACtB,EAWG,MAAMI,EAEOC,WAAmC,IAAIhC,EAAqB,cAE5DiC,QAA6B,IAAIjC,EAAkB,WAEnDkC,WAAmC,IAAIlC,EAAqB,cAK5EmC,cAEIC,KAAKF,WAAWG,SAAS,WAAY,IAAIf,GACzCc,KAAKF,WAAWG,SAAS,YAAa,IAAIR,GAC1CO,KAAKF,WAAWG,SAAS,UAAW,IAAInC,GACxCkC,KAAKF,WAAWG,SAAS,YAAa,IAAIjC,GAC1CgC,KAAKF,WAAWG,SAAS,QAAS,IAAI/B,GACtC8B,KAAKF,WAAWG,SAAS,MAAO,IAAI7B,GACpC4B,KAAKF,WAAWG,SAAS,OAAQ,IAAI3B,GACrC0B,KAAKF,WAAWG,SAAS,QAAS,IAAIzB,GAGtCwB,KAAKJ,WAAWK,SAAS,OAAQ,IAAIvB,GACrCsB,KAAKJ,WAAWK,SAAS,QAAS,IAAIrB,GACtCoB,KAAKJ,WAAWK,SAAS,WAAY,IAAInB,EAC7C,CAUOoB,kBAAkBd,EAAsBe,EAA+BC,GAC1E,IAAK,MAAMC,KAAQF,EAAqB,CACpC,MAAMG,EAAYN,KAAKF,WAAWS,IAAIF,GACtC,GAAIC,EAAW,CACX,MAAMjB,EAAOe,EAAUA,EAAQC,GAAQf,UACvC,IACI,MAAMkB,EAASF,EAAUnB,SAASC,EAAaC,GAC/C,IAAKmB,EAAOjB,QAAS,CACjB,OAAOiB,CACX,CACJ,CAAE,MAAOC,GACL,MAAMC,EAAOD,EAAgBE,QAC7B3B,EAAOyB,MAAM,wCAAwCJ,+BAAmCK,GACxF,MAAO,CAAEnB,QAAS,MAAOC,aAAc,4BAA4BkB,IACvE,CACJ,KAAO,CACH1B,EAAO4B,KAAK,kDAAkDP,4BAClE,CACJ,CACA,MAAO,CAAEd,QAAS,KACtB,EAOG,MAAMsB,EAAiB,IAAIlB,EAAkB,IAAAmB,EAAA,CAAAC,WAAA,MAAAD,EAAAnB,kBAAAmB,EAAAD,iBAAA,OAAAC,CAAA","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":18,"column":0},"map":{"version":3,"names":["Logger","___utils_Logger","PluginRegistry","fieldIndex","actionIndex","layoutIndex","activePromises","constructor","this","registerPluginPath","undefined","registerLayoutPath","getInstance","instance","type","widgetName","path","key","registerActionPath","actionName","strategy","getFieldPath","Error","getLayoutPath","getPathsToLoad","schema","pathsToLoad","Set","layoutStrategy","add","scanProperties","props","prop","ui","widget","e","msg","message","error","properties","items","preloadDependencies","promises","Array","from","map","Promise","resolve","reject","sap","require","Module","err","all","extractConstructor","default","keys","Object","getPlugin","PluginClass","getLayout","LayoutClass","__exports","__esModule"],"sources":["PluginRegistry.ts"],"sourcesContent":["/**\n * @file PluginRegistry.ts\n * @description Centralized hub for mapping UI5 controls to SAP schema data types.\n * Enforces the Registry Pattern to decouple the core engine from specific UI5 control implementations.\n * NOW WITH UNIVERSAL LAZY LOADING.\n */\n\nimport { IPlugin } from \"../interfaces/IPlugin\";\nimport { FieldType, ISchema, IPropertyMetadata } from \"../interfaces/ISchema\";\nimport { ILayoutManager } from \"../interfaces/ILayoutManager\";\nimport { Logger } from \"../utils/Logger\";\nimport { DefaultLayoutGenerator } from \"./DefaultLayoutGenerator\";\n\nexport class PluginRegistry {\n private static instance: PluginRegistry;\n \n private fieldIndex: Record<string, string> = {};\n private actionIndex: Record<string, string> = {};\n private layoutIndex: Record<string, string> = {};\n \n private activePromises: Record<string, Promise<unknown>> = {};\n\n private constructor() {\n // Core Mappings\n this.registerPluginPath(\"string\", undefined, \"nz/co/siliconst/ui5/metaui/plugins/controls/StringPlugin\");\n this.registerPluginPath(\"number\", undefined, \"nz/co/siliconst/ui5/metaui/plugins/controls/NumberPlugin\");\n this.registerPluginPath(\"integer\", undefined, \"nz/co/siliconst/ui5/metaui/plugins/controls/NumberPlugin\");\n this.registerPluginPath(\"date\", undefined, \"nz/co/siliconst/ui5/metaui/plugins/controls/DatePlugin\");\n this.registerPluginPath(\"boolean\", undefined, \"nz/co/siliconst/ui5/metaui/plugins/controls/BooleanPlugin\");\n this.registerPluginPath(\"array\", undefined, \"nz/co/siliconst/ui5/metaui/plugins/controls/ArrayPlugin\");\n this.registerPluginPath(\"object\", undefined, \"nz/co/siliconst/ui5/metaui/plugins/controls/ObjectPlugin\");\n\n // Widget Overrides\n this.registerPluginPath(\"string\", \"time\", \"nz/co/siliconst/ui5/metaui/plugins/controls/TimePlugin\");\n this.registerPluginPath(\"string\", \"datetime\", \"nz/co/siliconst/ui5/metaui/plugins/controls/DateTimePlugin\");\n this.registerPluginPath(\"boolean\", \"switch\", \"nz/co/siliconst/ui5/metaui/plugins/controls/SwitchPlugin\");\n this.registerPluginPath(\"number\", \"step\", \"nz/co/siliconst/ui5/metaui/plugins/controls/StepInputPlugin\");\n this.registerPluginPath(\"string\", \"select\", \"nz/co/siliconst/ui5/metaui/plugins/controls/DropdownPlugin\");\n this.registerPluginPath(\"string\", \"textArea\", \"nz/co/siliconst/ui5/metaui/plugins/controls/TextAreaPlugin\");\n this.registerPluginPath(\"string\", \"codeEditor\", \"nz/co/siliconst/ui5/metaui/plugins/controls/CodeEditorPlugin\");\n \n // Phase 1 Mappings\n this.registerPluginPath(\"string\", \"fileUploader\", \"nz/co/siliconst/ui5/metaui/plugins/controls/FileUploaderPlugin\");\n this.registerPluginPath(\"array\", \"multiSelect\", \"nz/co/siliconst/ui5/metaui/plugins/controls/MultiSelectPlugin\");\n this.registerPluginPath(\"array\", \"multiInput\", \"nz/co/siliconst/ui5/metaui/plugins/controls/MultiInputPlugin\");\n this.registerPluginPath(\"number\", \"slider\", \"nz/co/siliconst/ui5/metaui/plugins/controls/SliderPlugin\");\n this.registerPluginPath(\"number\", \"rating\", \"nz/co/siliconst/ui5/metaui/plugins/controls/RatingIndicatorPlugin\");\n this.registerPluginPath(\"string\", \"messageStrip\", \"nz/co/siliconst/ui5/metaui/plugins/controls/MessageStripPlugin\");\n\n // Phase 5 Mappings (Hardware)\n this.registerPluginPath(\"string\", \"camera\", \"nz/co/siliconst/ui5/metaui/plugins/controls/CameraPlugin\");\n this.registerPluginPath(\"string\", \"signature\", \"nz/co/siliconst/ui5/metaui/plugins/controls/SignaturePlugin\");\n this.registerPluginPath(\"object\", \"location\", \"nz/co/siliconst/ui5/metaui/plugins/controls/GeolocationPlugin\");\n this.registerPluginPath(\"string\", \"scanner\", \"nz/co/siliconst/ui5/metaui/plugins/controls/BarcodeScannerPlugin\");\n this.registerPluginPath(\"string\", \"voiceInput\", \"nz/co/siliconst/ui5/metaui/plugins/controls/VoiceInputPlugin\");\n this.registerPluginPath(\"string\", \"richText\", \"nz/co/siliconst/ui5/metaui/plugins/controls/RichTextPlugin\");\n\n // Actions & Datasources\n this.registerPluginPath(\"string\", \"urlButton\", \"nz/co/siliconst/ui5/metaui/plugins/actions/UrlNavigationActionPlugin\");\n this.registerPluginPath(\"string\", \"submitButton\", \"nz/co/siliconst/ui5/metaui/plugins/actions/SubmitFormActionPlugin\");\n this.registerPluginPath(\"string\", \"odataSelect\", \"nz/co/siliconst/ui5/metaui/plugins/datasources/ODataListBindingPlugin\");\n this.registerPluginPath(\"string\", \"remoteDropdown\", \"nz/co/siliconst/ui5/metaui/plugins/datasources/RemoteDropdownPlugin\");\n this.registerPluginPath(\"string\", \"liveSearch\", \"nz/co/siliconst/ui5/metaui/plugins/datasources/LiveSearchPlugin\");\n this.registerPluginPath(\"string\", \"remoteValueHelp\", \"nz/co/siliconst/ui5/metaui/plugins/datasources/RemoteValueHelpPlugin\");\n\n // Layouts\n this.registerLayoutPath(\"form\", \"nz/co/siliconst/ui5/metaui/layouts/FormLayout\");\n this.registerLayoutPath(\"table\", \"nz/co/siliconst/ui5/metaui/layouts/TableLayout\");\n this.registerLayoutPath(\"wizard\", \"nz/co/siliconst/ui5/metaui/layouts/WizardLayout\");\n this.registerLayoutPath(\"compact\", \"nz/co/siliconst/ui5/metaui/layouts/CompactLayout\");\n }\n\n public static getInstance(): PluginRegistry {\n if (!PluginRegistry.instance) {\n PluginRegistry.instance = new PluginRegistry();\n }\n return PluginRegistry.instance;\n }\n\n public registerPluginPath(type: FieldType, widgetName: string | undefined, path: string): void {\n const key = widgetName ? `${type}:${widgetName}` : type;\n this.fieldIndex[key] = path;\n }\n\n public registerActionPath(actionName: string, path: string): void {\n this.actionIndex[actionName] = path;\n }\n\n public registerLayoutPath(strategy: string, path: string): void {\n this.layoutIndex[strategy] = path;\n }\n\n private getFieldPath(type: FieldType, widgetName?: string): string {\n let path;\n if (widgetName) {\n path = this.fieldIndex[`${type}:${widgetName}`];\n }\n if (!path) {\n path = this.fieldIndex[type];\n }\n if (!path) {\n throw new Error(`No plugin path mapped for FieldType: ${type} (widget: ${widgetName})`);\n }\n return path;\n }\n\n private getLayoutPath(strategy: string): string {\n const path = this.layoutIndex[strategy];\n if (!path) {\n throw new Error(`No layout path mapped for strategy: ${strategy}`);\n }\n return path;\n }\n\n /**\n * Statically traverses the schema structure to identify all required plugins\n * and layouts without actually instantiating them.\n * \n * @param {ISchema} schema The root JSON schema payload to traverse\n * @returns {Set<string>} A distinct set of UI5 module paths required to render the schema\n */\n public getPathsToLoad(schema: ISchema): Set<string> {\n const pathsToLoad = new Set<string>();\n \n // 1. Gather layout strategy\n const strategy = schema.layoutStrategy || (schema.type === \"array\" ? \"table\" : \"form\");\n pathsToLoad.add(this.getLayoutPath(strategy));\n\n // 2. Recursively gather field plugins\n const scanProperties = (props: Record<string, IPropertyMetadata>) => {\n for (const key in props) {\n const prop = props[key];\n try {\n pathsToLoad.add(this.getFieldPath(prop.type || \"string\", prop.ui?.widget));\n } catch (e) {\n const msg = `[MetaUI LazyLoad] Could not find mapped plugin for field ${key}: ${(e as Error).message}`;\n Logger.error(msg);\n throw new Error(msg);\n }\n if (prop.properties) scanProperties(prop.properties);\n if (prop.items && prop.items.properties) scanProperties(prop.items.properties);\n if (prop.items && prop.items.type) {\n try {\n pathsToLoad.add(this.getFieldPath(prop.items.type, prop.items.ui?.widget));\n } catch (e) {\n const msg = `[MetaUI LazyLoad] Could not find mapped plugin for array item type ${prop.items.type}: ${(e as Error).message}`;\n Logger.error(msg);\n throw new Error(msg);\n }\n }\n }\n };\n\n if (schema.properties) {\n scanProperties(schema.properties);\n } else if (schema.items && schema.items.properties) {\n scanProperties(schema.items.properties);\n }\n\n return pathsToLoad;\n }\n\n /**\n * Defers the generation of the UI until all required UI5 modules have been\n * downloaded asynchronously. Maintains a cache of active promises to prevent\n * redundant network requests for the same module.\n * \n * @param {ISchema} schema The root JSON schema payload to parse\n * @returns {Promise<void>} Resolves when all dependencies are securely in the UI5 require cache\n */\n public async preloadDependencies(schema: ISchema): Promise<void> {\n const pathsToLoad = this.getPathsToLoad(schema);\n\n // 3. Batch execute sap.ui.require via Promises\n const promises = Array.from(pathsToLoad).map(path => {\n if (!this.activePromises[path]) {\n this.activePromises[path] = new Promise((resolve, reject) => {\n sap.ui.require([path], \n (Module: unknown) => resolve(Module), \n (err: unknown) => {\n Logger.error(`Failed to lazy load module: ${path}`);\n // CRITICAL: Delete from cache so future attempts can retry the network request\n delete this.activePromises[path];\n reject(err);\n }\n );\n });\n }\n return this.activePromises[path];\n });\n\n await Promise.all(promises);\n }\n\n /**\n * Extracts a valid constructor from a dynamically required module.\n */\n private extractConstructor(Module: unknown): new () => IPlugin | ILayoutManager | null {\n if (!Module) return null;\n if (typeof Module === \"function\") return Module as any;\n if ((Module as any).default && typeof (Module as any).default === \"function\") return (Module as any).default;\n \n // Handle namespace exports (e.g. { FormLayout: class... })\n const keys = Object.keys(Module as object);\n for (const key of keys) {\n if (typeof (Module as any)[key] === \"function\") {\n return (Module as any)[key];\n }\n }\n return null;\n }\n\n /**\n * Instantiates the requested plugin for the given field type.\n */\n public getPlugin(type: FieldType, widgetName?: string): IPlugin {\n const path = this.getFieldPath(type, widgetName);\n const Module = sap.ui.require(path);\n const PluginClass = this.extractConstructor(Module);\n \n if (!PluginClass) {\n throw new Error(`[MetaUI Plugin Instantiation] Plugin ${path} was not preloaded or has no constructor!`);\n }\n \n return new PluginClass();\n }\n\n /**\n * Instantiates the requested layout manager for the given strategy.\n */\n public getLayout(strategy: string): ILayoutManager {\n const path = this.getLayoutPath(strategy);\n const Module = sap.ui.require(path);\n const LayoutClass = this.extractConstructor(Module);\n \n if (!LayoutClass) {\n throw new Error(`[MetaUI Layout Instantiation] Layout ${path} was not preloaded or has no constructor!`);\n }\n \n return new LayoutClass();\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":19,"column":0},"map":{"version":3,"names":["Logger","___utils_Logger","Registry","items","Map","constructor","registryName","this","register","key","item","has","warn","set","get","getStrict","msg","error","Error","getKeys","Array","from","keys","clear","__exports","__esModule"],"sources":["Registry.ts"],"sourcesContent":["/**\n * @file Registry.ts\n * @description Universal generic registry pattern used across the MetaUI library \n * for registering and resolving decoupled plugins (Layouts, Controls, Validators, etc).\n */\n\nimport { Logger } from \"../utils/Logger\";\n\n/**\n * Universal generic registry pattern used across the MetaUI library \n * for registering and resolving decoupled plugins (Layouts, Controls, Validators, etc).\n * \n * @template T The type of item being stored in the registry.\n * @namespace nz.co.siliconst.ui5.metaui.core\n * @public\n */\nexport class Registry<T> {\n /** The internal map storing the registered items. */\n public readonly items = new Map<string, T>();\n\n constructor(public readonly registryName: string = \"Registry\") {}\n\n /**\n * Registers a new item (plugin/layout/validator) into the registry.\n * @param key The unique string identifier.\n * @param item The implementation class or instance.\n */\n public register(key: string, item: T): void {\n if (this.items.has(key)) {\n Logger.warn(`[MetaUI] ${this.registryName}: Overwriting existing key '${key}'.`);\n }\n this.items.set(key, item);\n }\n\n /**\n * Retrieves an item by its key.\n * @param key The unique string identifier.\n * @returns The registered item, or undefined if not found.\n */\n public get(key: string): T | undefined {\n return this.items.get(key);\n }\n\n /**\n * Retrieves an item by its key, throwing an error if it doesn't exist.\n * @param key The unique string identifier.\n * @returns The registered item.\n */\n public getStrict(key: string): T {\n const item = this.get(key);\n if (!item) {\n const msg = `[MetaUI] ${this.registryName}: Key '${key}' not found.`;\n Logger.error(msg);\n throw new Error(msg);\n }\n return item;\n }\n\n /**\n * Returns an array of all registered keys.\n */\n public getKeys(): string[] {\n return Array.from(this.items.keys());\n }\n\n /**\n * Clears the entire registry.\n */\n public clear(): void {\n this.items.clear();\n }\n}\n"],"mappings":"AAAA,0GAAA,MAMSA,EAAMC,EAAA,UAUR,MAAMC,EAEOC,MAAQ,IAAIC,IAE5BC,YAA4BC,EAAuB,YAAYC,KAAnCD,cAAoC,CAOzDE,SAASC,EAAaC,GACzB,GAAIH,KAAKJ,MAAMQ,IAAIF,GAAM,CACrBT,EAAOY,KAAK,YAAYL,KAAKD,2CAA2CG,MAC5E,CACAF,KAAKJ,MAAMU,IAAIJ,EAAKC,EACxB,CAOOI,IAAIL,GACP,OAAOF,KAAKJ,MAAMW,IAAIL,EAC1B,CAOOM,UAAUN,GACb,MAAMC,EAAOH,KAAKO,IAAIL,GACtB,IAAKC,EAAM,CACP,MAAMM,EAAM,YAAYT,KAAKD,sBAAsBG,gBACnDT,EAAOiB,MAAMD,GACb,MAAM,IAAIE,MAAMF,EACpB,CACA,OAAON,CACX,CAKOS,UACH,OAAOC,MAAMC,KAAKd,KAAKJ,MAAMmB,OACjC,CAKOC,QACHhB,KAAKJ,MAAMoB,OACf,EACH,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAAtB,WAAA,OAAAsB,CAAA","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":20,"column":0},"map":{"version":3,"names":["SchemaNormalizer","___SchemaNormalizer","SwaggerBuilder","___swagger_SwaggerBuilder","Logger","___utils_Logger","SchemaBuilderRegistry","static","register","plugin","this","_plugins","push","getBuilderFor","rawSchema","canHandle","warn","__exports","__esModule"],"sources":["SchemaBuilderRegistry.ts"],"sourcesContent":["/**\n * @file SchemaBuilderRegistry.ts\n * @description Singleton registry for Schema Builder plugins.\n * Routes unknown JSON payloads to the appropriate parser plugin.\n */\n\nimport { ISchemaBuilderPlugin } from \"../interfaces/ISchemaBuilderPlugin\";\nimport { SchemaNormalizer } from \"./SchemaNormalizer\";\nimport { SwaggerBuilder } from \"../swagger/SwaggerBuilder\";\nimport { Logger } from \"../utils/Logger\";\n\nexport class SchemaBuilderRegistry {\n private static _plugins: ISchemaBuilderPlugin[] = [\n new SwaggerBuilder(),\n new SchemaNormalizer()\n ];\n\n /**\n * Registers a new schema builder plugin into the engine.\n * @param plugin An instance of ISchemaBuilderPlugin\n */\n public static register(plugin: ISchemaBuilderPlugin): void {\n this._plugins.push(plugin);\n }\n\n /**\n * Finds the first registered plugin that claims it can handle the payload.\n * @param rawSchema The raw JSON schema object to inspect.\n * @returns The matching plugin instance, or null if none match.\n */\n public static getBuilderFor(rawSchema: any): ISchemaBuilderPlugin | null {\n if (!rawSchema || typeof rawSchema !== \"object\") {\n return null;\n }\n\n for (const plugin of this._plugins) {\n if (plugin.canHandle(rawSchema)) {\n return plugin;\n }\n }\n \n Logger.warn(\"[SchemaBuilderRegistry]\", \"No suitable Schema Builder plugin found for the provided payload.\");\n return null;\n }\n}\n"],"mappings":"AAAA,4KAAA,MAOSA,EAAgBC,EAAA,0BAChBC,EAAcC,EAAA,wBACdC,EAAMC,EAAA,UAER,MAAMC,EACTC,gBAAkD,CAC9C,IAAIL,EACJ,IAAIF,GAOR,eAAcQ,CAASC,GACnBC,KAAKC,SAASC,KAAKH,EACvB,CAOA,oBAAcI,CAAcC,GACxB,IAAKA,UAAoBA,IAAc,SAAU,CAC7C,OAAO,IACX,CAEA,IAAK,MAAML,KAAUC,KAAKC,SAAU,CAChC,GAAIF,EAAOM,UAAUD,GAAY,CAC7B,OAAOL,CACX,CACJ,CAEAL,EAAOY,KAAK,0BAA2B,qEACvC,OAAO,IACX,EACH,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAAX,wBAAA,OAAAW,CAAA","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":21,"column":0},"map":{"version":3,"names":["Logger","___utils_Logger","SchemaNormalizer","canHandle","rawSchema","openapi","swagger","build","normalize","data","schemaObj","trim","JSON","parse","e","msg","message","error","Error","Array","isArray","this","inferSchemaFromData","normalized","title","type","items","layoutStrategy","uiLayout","additionalProperties","targetProperties","properties","inferred","deepMergeProperties","requiredKeys","required","normalizeProperties","normalizePropertyMetadata","base","override","merged","key","Object","keys","overrideVal","baseVal","normalizedProps","isRequired","includes","prop","keyName","ui","label","generateLabel","isKey","readOnly","widget","valueHelp","enum","undefined","visibleOn","enabledOn","format","validators","formatter","args","rows","fullWidth","dialogButtonText","maxLength","minLength","minimum","maximum","pattern","precision","scale","multipleOf","name","spaced","replace","split","filter","w","length","map","word","charAt","toUpperCase","slice","toLowerCase","join","schema","inferPropertiesFromObject","obj","val","nestedProps","resolveScope","scope","startsWith","meta","bindingPath","propKey","pathSegments","current","debug","stringify","i","segment","__exports","__esModule"],"sources":["SchemaNormalizer.ts"],"sourcesContent":["/**\n * @file SchemaNormalizer.ts\n * @description Transforms and validates incoming JSON payloads into the strict v2 ISchema dictionary matrix.\n */\n\nimport { ISchema, IPropertyMetadata, FieldType } from \"../interfaces/ISchema\";\nimport { ISchemaBuilderPlugin } from \"../interfaces/ISchemaBuilderPlugin\";\nimport { Logger } from \"../utils/Logger\";\n\nexport class SchemaNormalizer implements ISchemaBuilderPlugin {\n\n /**\n * ISchemaBuilderPlugin Contract\n */\n public canHandle(rawSchema: any): boolean {\n // MetaUI native schemas almost always have properties, items, or a layoutStrategy\n // This acts as a fallback for native schemas.\n if (rawSchema.openapi || rawSchema.swagger) return false; \n return true;\n }\n\n /**\n * ISchemaBuilderPlugin Contract\n */\n public build(rawSchema: any): ISchema {\n return SchemaNormalizer.normalize(rawSchema);\n }\n\n /**\n * Validates that the provided raw payload conforms to the required ISchema structures.\n */\n public static normalize(rawSchema?: unknown, data?: unknown): ISchema {\n let schemaObj = rawSchema;\n\n if (typeof schemaObj === \"string\") {\n if (!schemaObj.trim()) {\n schemaObj = null;\n } else {\n try {\n schemaObj = JSON.parse(schemaObj);\n } catch (e) {\n const msg = \"Failed to parse schema string: \" + (e as Error).message;\n Logger.error(\"[MetaUI SchemaNormalizer]\", msg);\n throw new Error(msg);\n }\n }\n }\n\n if (!schemaObj || typeof schemaObj !== 'object' || Array.isArray(schemaObj)) {\n return this.inferSchemaFromData(data);\n }\n\n try {\n // It is an object. Ensure it conforms to v2 structure.\n const normalized: ISchema = {\n title: schemaObj.title,\n type: schemaObj.type || (schemaObj.items ? \"array\" : \"object\"),\n layoutStrategy: schemaObj.layoutStrategy,\n uiLayout: schemaObj.uiLayout,\n additionalProperties: schemaObj.additionalProperties\n };\n\n let targetProperties = schemaObj.properties || {};\n\n if (schemaObj.additionalProperties === true && data) {\n const inferred = this.inferSchemaFromData(data);\n if (inferred.type === \"object\" && inferred.properties) {\n targetProperties = this.deepMergeProperties(inferred.properties, targetProperties);\n } else if (inferred.type === \"array\" && inferred.items && inferred.items.properties) {\n // Array schema merging could be added here if we want full support.\n }\n }\n\n if (normalized.type === \"object\") {\n const requiredKeys = Array.isArray(schemaObj.required) ? schemaObj.required : [];\n normalized.properties = this.normalizeProperties(targetProperties, requiredKeys);\n } else if (normalized.type === \"array\") {\n // Future expansion: array deep merge\n normalized.items = this.normalizePropertyMetadata(schemaObj.items || { type: \"object\", properties: {} }, \"items\", false);\n }\n\n return normalized;\n } catch (error) {\n const msg = \"Critical error normalizing schema object: \" + (error as Error).message;\n Logger.error(\"[MetaUI SchemaNormalizer]\", msg);\n throw new Error(msg);\n }\n }\n\n /**\n * Recursively deep merges an inferred schema over a base schema.\n * @param base The base property dictionary.\n * @param override The overriding inferred dictionary.\n * @returns A new deeply merged property dictionary.\n */\n private static deepMergeProperties(base: Record<string, unknown>, override: Record<string, unknown>): Record<string, unknown> {\n const merged = { ...base };\n for (const key of Object.keys(override)) {\n const overrideVal = override[key];\n const baseVal = merged[key];\n\n if (baseVal && typeof baseVal === \"object\" && !Array.isArray(baseVal) &&\n overrideVal && typeof overrideVal === \"object\" && !Array.isArray(overrideVal)) {\n merged[key] = this.deepMergeProperties(baseVal, overrideVal);\n } else {\n merged[key] = overrideVal;\n }\n }\n return merged;\n }\n\n /**\n * Normalizes a collection of properties.\n * @param properties The raw properties map.\n * @param requiredKeys An optional array of keys that are required by the parent object.\n * @returns A map of strict IPropertyMetadata objects.\n */\n private static normalizeProperties(properties: Record<string, unknown>, requiredKeys: string[] = []): Record<string, IPropertyMetadata> {\n const normalizedProps: Record<string, IPropertyMetadata> = {};\n for (const key of Object.keys(properties)) {\n const isRequired = requiredKeys.includes(key);\n normalizedProps[key] = this.normalizePropertyMetadata(properties[key], key, isRequired);\n }\n return normalizedProps;\n }\n\n /**\n * Normalizes a single property against the ISchema specification.\n * @param prop The raw property definition.\n * @param keyName The string key name for generating default labels.\n * @param isRequired Indicates if the parent object mandated this property as required.\n * @returns A strict IPropertyMetadata instance.\n */\n private static normalizePropertyMetadata(prop: Record<string, unknown>, keyName: string, isRequired: boolean = false): IPropertyMetadata {\n const normalized: IPropertyMetadata = {\n type: prop.type || \"string\",\n ui: {\n label: prop.ui?.label || this.generateLabel(keyName),\n isKey: !!prop.ui?.isKey,\n readOnly: !!prop.ui?.readOnly,\n widget: prop.ui?.widget || (prop.valueHelp || prop.enum ? \"select\" : undefined),\n visibleOn: prop.ui?.visibleOn,\n enabledOn: prop.ui?.enabledOn,\n format: prop.ui?.format,\n validators: prop.ui?.validators,\n formatter: prop.ui?.formatter,\n args: prop.ui?.args,\n rows: prop.ui?.rows,\n fullWidth: prop.ui?.fullWidth,\n dialogButtonText: prop.ui?.dialogButtonText\n },\n required: isRequired || !!prop.required,\n maxLength: prop.maxLength as number,\n minLength: prop.minLength as number,\n minimum: prop.minimum,\n maximum: prop.maximum,\n pattern: prop.pattern,\n precision: prop.precision,\n scale: prop.scale,\n multipleOf: prop.multipleOf as number,\n valueHelp: prop.valueHelp,\n enum: prop.enum\n };\n\n if (normalized.type === \"object\" && prop.properties) {\n const requiredKeys = Array.isArray(prop.required) ? prop.required : [];\n normalized.properties = this.normalizeProperties(prop.properties as Record<string, unknown>, requiredKeys);\n normalized.uiLayout = prop.uiLayout;\n } else if (normalized.type === \"array\" && prop.items) {\n normalized.items = this.normalizePropertyMetadata(prop.items as Record<string, unknown>, \"items\", false);\n normalized.uiLayout = prop.uiLayout;\n }\n\n return normalized;\n }\n\n /**\n * Generates a Title Case label from camelCase or snake_case technical names.\n */\n private static generateLabel(name: string): string {\n if (!name) return \"\";\n let spaced = name.replace(/([A-Z])/g, \" $1\").replace(/_/g, \" \");\n return spaced.split(' ')\n .filter(w => w.length > 0)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ')\n .trim();\n }\n\n /**\n * Infers a v2 ISchema structure dynamically from a plain data payload.\n */\n public static inferSchemaFromData(data: unknown): ISchema {\n const schema: ISchema = { type: \"object\", properties: {}, layoutStrategy: \"compact\", title: \"\" };\n\n if (!data || typeof data !== \"object\") {\n return schema;\n }\n\n if (Array.isArray(data)) {\n schema.type = \"array\";\n if (data.length > 0 && typeof data[0] !== \"object\") {\n schema.layoutStrategy = \"compact\";\n schema.items = { type: typeof data[0] as FieldType };\n } else {\n schema.layoutStrategy = \"table\";\n schema.items = {\n type: \"object\",\n layoutStrategy: \"compact\",\n properties: data.length > 0 ? this.inferPropertiesFromObject(data[0] as Record<string, unknown>) : {}\n };\n }\n } else {\n schema.type = \"object\";\n schema.properties = this.inferPropertiesFromObject(data);\n }\n\n return schema;\n }\n\n /**\n * Infers field metadata recursively from a raw data object.\n * @param obj The raw JavaScript object.\n * @returns A dictionary of inferred IPropertyMetadata.\n */\n private static inferPropertiesFromObject(obj: Record<string, unknown>): Record<string, IPropertyMetadata> {\n const properties: Record<string, IPropertyMetadata> = {};\n if (!obj || typeof obj !== \"object\") return properties;\n\n for (const key of Object.keys(obj)) {\n const val = obj[key];\n if (val === null || val === undefined) continue;\n\n let type: FieldType = \"string\";\n let items: IPropertyMetadata | undefined;\n let nestedProps: Record<string, IPropertyMetadata> | undefined;\n\n if (typeof val === \"number\") type = \"number\";\n else if (typeof val === \"boolean\") type = \"boolean\";\n else if (Array.isArray(val)) {\n type = \"array\";\n if (val.length > 0 && typeof val[0] !== \"object\") {\n items = {\n type: typeof val[0] as FieldType\n };\n } else {\n items = {\n type: \"object\",\n properties: val.length > 0 ? this.inferPropertiesFromObject(val[0] as Record<string, unknown>) : {}\n };\n }\n } else if (typeof val === \"object\") {\n type = \"object\";\n nestedProps = this.inferPropertiesFromObject(val);\n }\n\n properties[key] = {\n type,\n items,\n properties: nestedProps,\n ui: {\n label: this.generateLabel(key),\n isKey: false,\n readOnly: false,\n widget: type === \"array\" && items?.type !== \"object\" ? \"multiInput\" : undefined\n }\n };\n }\n\n return properties;\n }\n\n /**\n * Resolves a JSON Schema scope (e.g. '#/properties/header/properties/id')\n * against the ISchema, returning the PropertyMetadata and the UI5 binding path.\n */\n public static resolveScope(schema: ISchema, scope: string): { meta: IPropertyMetadata | undefined, bindingPath: string, propKey: string } {\n if (!scope || !scope.startsWith(\"#/properties/\")) {\n return { meta: undefined, bindingPath: scope || \"\", propKey: scope || \"\" };\n }\n \n const pathSegments = scope.replace(\"#/properties/\", \"\").split(\"/properties/\");\n let current: Record<string, IPropertyMetadata> | undefined = schema.properties;\n let meta: IPropertyMetadata | undefined;\n \n Logger.debug(\"[MetaUI SchemaNormalizer]\", `Resolving scope '${scope}' with segments: ${JSON.stringify(pathSegments)}`, \"SchemaNormalizer\");\n Logger.debug(\"[MetaUI SchemaNormalizer]\", `Root schema keys: ${Object.keys(schema.properties || {})}`, \"SchemaNormalizer\");\n\n for (let i = 0; i < pathSegments.length; i++) {\n const segment = pathSegments[i];\n if (!current) {\n Logger.debug(\"[MetaUI SchemaNormalizer]\", `current is undefined at segment '${segment}'`, \"SchemaNormalizer\");\n meta = undefined;\n break;\n }\n meta = current[segment];\n Logger.debug(\"[MetaUI SchemaNormalizer]\", `Segment '${segment}' resolved to meta: ${!!meta}. Available keys in current: ${Object.keys(current)}`, \"SchemaNormalizer\");\n if (i < pathSegments.length - 1) {\n current = meta?.properties;\n }\n }\n \n const bindingPath = pathSegments.join(\"/\");\n const propKey = scope.replace(\"#/properties/\", \"\"); // The original raw string for logging\n \n return {\n meta,\n bindingPath,\n propKey\n };\n }\n}\n"],"mappings":"AAAA,kHAAA,MAOSA,EAAMC,EAAA,UAER,MAAMC,EAKFC,UAAUC,GAGb,GAAIA,EAAUC,SAAWD,EAAUE,QAAS,OAAO,MACnD,OAAO,IACX,CAKOC,MAAMH,GACT,OAAOF,EAAiBM,UAAUJ,EACtC,CAKA,gBAAcI,CAAUJ,EAAqBK,GACzC,IAAIC,EAAYN,EAEhB,UAAWM,IAAc,SAAU,CAC/B,IAAKA,EAAUC,OAAQ,CACnBD,EAAY,IAChB,KAAO,CACH,IACIA,EAAYE,KAAKC,MAAMH,EAC3B,CAAE,MAAOI,GACL,MAAMC,EAAM,kCAAqCD,EAAYE,QAC7DhB,EAAOiB,MAAM,4BAA6BF,GAC1C,MAAM,IAAIG,MAAMH,EACpB,CACJ,CACJ,CAEA,IAAKL,UAAoBA,IAAc,UAAYS,MAAMC,QAAQV,GAAY,CACzE,OAAOW,KAAKC,oBAAoBb,EACpC,CAEA,IAEI,MAAMc,EAAsB,CACxBC,MAAOd,EAAUc,MACjBC,KAAMf,EAAUe,OAASf,EAAUgB,MAAQ,QAAU,UACrDC,eAAgBjB,EAAUiB,eAC1BC,SAAUlB,EAAUkB,SACpBC,qBAAsBnB,EAAUmB,sBAGpC,IAAIC,EAAmBpB,EAAUqB,YAAc,CAAC,EAEhD,GAAIrB,EAAUmB,uBAAyB,MAAQpB,EAAM,CACjD,MAAMuB,EAAWX,KAAKC,oBAAoBb,GAC1C,GAAIuB,EAASP,OAAS,UAAYO,EAASD,WAAY,CACnDD,EAAmBT,KAAKY,oBAAoBD,EAASD,WAAYD,EACrE,MAAO,GAAIE,EAASP,OAAS,SAAWO,EAASN,OAASM,EAASN,MAAMK,WAAY,CACjF,CAER,CAEA,GAAIR,EAAWE,OAAS,SAAU,CAC9B,MAAMS,EAAef,MAAMC,QAAQV,EAAUyB,UAAYzB,EAAUyB,SAAW,GAC9EZ,EAAWQ,WAAaV,KAAKe,oBAAoBN,EAAkBI,EACvE,MAAO,GAAIX,EAAWE,OAAS,QAAS,CAEpCF,EAAWG,MAAQL,KAAKgB,0BAA0B3B,EAAUgB,OAAS,CAAED,KAAM,SAAUM,WAAY,CAAC,GAAK,QAAS,MACtH,CAEA,OAAOR,CACX,CAAE,MAAON,GACL,MAAMF,EAAM,6CAAgDE,EAAgBD,QAC5EhB,EAAOiB,MAAM,4BAA6BF,GAC1C,MAAM,IAAIG,MAAMH,EACpB,CACJ,CAQA,0BAAekB,CAAoBK,EAA+BC,GAC9D,MAAMC,EAAS,IAAKF,GACpB,IAAK,MAAMG,KAAOC,OAAOC,KAAKJ,GAAW,CACrC,MAAMK,EAAcL,EAASE,GAC7B,MAAMI,EAAUL,EAAOC,GAEvB,GAAII,UAAkBA,IAAY,WAAa1B,MAAMC,QAAQyB,IACzDD,UAAsBA,IAAgB,WAAazB,MAAMC,QAAQwB,GAAc,CAC/EJ,EAAOC,GAAOpB,KAAKY,oBAAoBY,EAASD,EACpD,KAAO,CACHJ,EAAOC,GAAOG,CAClB,CACJ,CACA,OAAOJ,CACX,CAQA,0BAAeJ,CAAoBL,EAAqCG,EAAyB,IAC7F,MAAMY,EAAqD,CAAC,EAC5D,IAAK,MAAML,KAAOC,OAAOC,KAAKZ,GAAa,CACvC,MAAMgB,EAAab,EAAac,SAASP,GACzCK,EAAgBL,GAAOpB,KAAKgB,0BAA0BN,EAAWU,GAAMA,EAAKM,EAChF,CACA,OAAOD,CACX,CASA,gCAAeT,CAA0BY,EAA+BC,EAAiBH,EAAsB,OAC3G,MAAMxB,EAAgC,CAClCE,KAAMwB,EAAKxB,MAAQ,SACnB0B,GAAI,CACAC,MAAOH,EAAKE,IAAIC,OAAS/B,KAAKgC,cAAcH,GAC5CI,QAASL,EAAKE,IAAIG,MAClBC,WAAYN,EAAKE,IAAII,SACrBC,OAAQP,EAAKE,IAAIK,SAAWP,EAAKQ,WAAaR,EAAKS,KAAO,SAAWC,WACrEC,UAAWX,EAAKE,IAAIS,UACpBC,UAAWZ,EAAKE,IAAIU,UACpBC,OAAQb,EAAKE,IAAIW,OACjBC,WAAYd,EAAKE,IAAIY,WACrBC,UAAWf,EAAKE,IAAIa,UACpBC,KAAMhB,EAAKE,IAAIc,KACfC,KAAMjB,EAAKE,IAAIe,KACfC,UAAWlB,EAAKE,IAAIgB,UACpBC,iBAAkBnB,EAAKE,IAAIiB,kBAE/BjC,SAAUY,KAAgBE,EAAKd,SAC/BkC,UAAWpB,EAAKoB,UAChBC,UAAWrB,EAAKqB,UAChBC,QAAStB,EAAKsB,QACdC,QAASvB,EAAKuB,QACdC,QAASxB,EAAKwB,QACdC,UAAWzB,EAAKyB,UAChBC,MAAO1B,EAAK0B,MACZC,WAAY3B,EAAK2B,WACjBnB,UAAWR,EAAKQ,UAChBC,KAAMT,EAAKS,MAGf,GAAInC,EAAWE,OAAS,UAAYwB,EAAKlB,WAAY,CACjD,MAAMG,EAAef,MAAMC,QAAQ6B,EAAKd,UAAYc,EAAKd,SAAW,GACpEZ,EAAWQ,WAAaV,KAAKe,oBAAoBa,EAAKlB,WAAuCG,GAC7FX,EAAWK,SAAWqB,EAAKrB,QAC/B,MAAO,GAAIL,EAAWE,OAAS,SAAWwB,EAAKvB,MAAO,CAClDH,EAAWG,MAAQL,KAAKgB,0BAA0BY,EAAKvB,MAAkC,QAAS,OAClGH,EAAWK,SAAWqB,EAAKrB,QAC/B,CAEA,OAAOL,CACX,CAKA,oBAAe8B,CAAcwB,GACzB,IAAKA,EAAM,MAAO,GAClB,IAAIC,EAASD,EAAKE,QAAQ,WAAY,OAAOA,QAAQ,KAAM,KAC3D,OAAOD,EAAOE,MAAM,KACfC,OAAOC,GAAKA,EAAEC,OAAS,GACvBC,IAAIC,GAAQA,EAAKC,OAAO,GAAGC,cAAgBF,EAAKG,MAAM,GAAGC,eACzDC,KAAK,KACL/E,MACT,CAKA,0BAAcW,CAAoBb,GAC9B,MAAMkF,EAAkB,CAAElE,KAAM,SAAUM,WAAY,CAAC,EAAGJ,eAAgB,UAAWH,MAAO,IAE5F,IAAKf,UAAeA,IAAS,SAAU,CACnC,OAAOkF,CACX,CAEA,GAAIxE,MAAMC,QAAQX,GAAO,CACrBkF,EAAOlE,KAAO,QACd,GAAIhB,EAAK0E,OAAS,UAAY1E,EAAK,KAAO,SAAU,CAChDkF,EAAOhE,eAAiB,UACxBgE,EAAOjE,MAAQ,CAAED,YAAahB,EAAK,GACvC,KAAO,CACHkF,EAAOhE,eAAiB,QACxBgE,EAAOjE,MAAQ,CACXD,KAAM,SACNE,eAAgB,UAChBI,WAAYtB,EAAK0E,OAAS,EAAI9D,KAAKuE,0BAA0BnF,EAAK,IAAiC,CAAC,EAE5G,CACJ,KAAO,CACHkF,EAAOlE,KAAO,SACdkE,EAAO5D,WAAaV,KAAKuE,0BAA0BnF,EACvD,CAEA,OAAOkF,CACX,CAOA,gCAAeC,CAA0BC,GACrC,MAAM9D,EAAgD,CAAC,EACvD,IAAK8D,UAAcA,IAAQ,SAAU,OAAO9D,EAE5C,IAAK,MAAMU,KAAOC,OAAOC,KAAKkD,GAAM,CAChC,MAAMC,EAAMD,EAAIpD,GAChB,GAAIqD,IAAQ,MAAQA,IAAQnC,UAAW,SAEvC,IAAIlC,EAAkB,SACtB,IAAIC,EACJ,IAAIqE,EAEJ,UAAWD,IAAQ,SAAUrE,EAAO,cAC/B,UAAWqE,IAAQ,UAAWrE,EAAO,eACrC,GAAIN,MAAMC,QAAQ0E,GAAM,CACzBrE,EAAO,QACP,GAAIqE,EAAIX,OAAS,UAAYW,EAAI,KAAO,SAAU,CAC9CpE,EAAQ,CACJD,YAAaqE,EAAI,GAEzB,KAAO,CACHpE,EAAQ,CACJD,KAAM,SACNM,WAAY+D,EAAIX,OAAS,EAAI9D,KAAKuE,0BAA0BE,EAAI,IAAiC,CAAC,EAE1G,CACJ,MAAO,UAAWA,IAAQ,SAAU,CAChCrE,EAAO,SACPsE,EAAc1E,KAAKuE,0BAA0BE,EACjD,CAEA/D,EAAWU,GAAO,CACdhB,OACAC,QACAK,WAAYgE,EACZ5C,GAAI,CACAC,MAAO/B,KAAKgC,cAAcZ,GAC1Ba,MAAO,MACPC,SAAU,MACVC,OAAQ/B,IAAS,SAAWC,GAAOD,OAAS,SAAW,aAAekC,WAGlF,CAEA,OAAO5B,CACX,CAMA,mBAAciE,CAAaL,EAAiBM,GACxC,IAAKA,IAAUA,EAAMC,WAAW,iBAAkB,CAC9C,MAAO,CAAEC,KAAMxC,UAAWyC,YAAaH,GAAS,GAAII,QAASJ,GAAS,GAC1E,CAEA,MAAMK,EAAeL,EAAMlB,QAAQ,gBAAiB,IAAIC,MAAM,gBAC9D,IAAIuB,EAAyDZ,EAAO5D,WACpE,IAAIoE,EAEJnG,EAAOwG,MAAM,4BAA6B,oBAAoBP,qBAAyBrF,KAAK6F,UAAUH,KAAiB,oBACvHtG,EAAOwG,MAAM,4BAA6B,qBAAqB9D,OAAOC,KAAKgD,EAAO5D,YAAc,CAAC,KAAM,oBAEvG,IAAK,IAAI2E,EAAI,EAAGA,EAAIJ,EAAanB,OAAQuB,IAAK,CAC1C,MAAMC,EAAUL,EAAaI,GAC7B,IAAKH,EAAS,CACVvG,EAAOwG,MAAM,4BAA6B,oCAAoCG,KAAY,oBAC1FR,EAAOxC,UACP,KACJ,CACAwC,EAAOI,EAAQI,GACf3G,EAAOwG,MAAM,4BAA6B,YAAYG,0BAAgCR,iCAAoCzD,OAAOC,KAAK4D,KAAY,oBAClJ,GAAIG,EAAIJ,EAAanB,OAAS,EAAG,CAC7BoB,EAAUJ,GAAMpE,UACpB,CACJ,CAEA,MAAMqE,EAAcE,EAAaZ,KAAK,KACtC,MAAMW,EAAUJ,EAAMlB,QAAQ,gBAAiB,IAE/C,MAAO,CACHoB,OACAC,cACAC,UAER,EACH,IAAAO,EAAA,CAAAC,WAAA,MAAAD,EAAA1G,mBAAA,OAAA0G,CAAA","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":22,"column":0},"map":{"version":3,"names":["SchemaValidator","validateSchemaStructure","schema","errors","s","type","push","properties","key","Object","keys","prop","allowedTypes","includes","join","__exports","__esModule"],"sources":["SchemaValidator.ts"],"sourcesContent":["/**\n * @file SchemaValidator.ts\n * @description Structural validation utility to catch developer errors in the JSON schema itself.\n */\n\nimport { ISchema, FieldType } from \"../interfaces/ISchema\";\n\nexport class SchemaValidator {\n /**\n * Validates a parsed JSON schema object for structural correctness.\n * @param schema The schema object to validate\n * @returns An array of error strings. Empty if no errors.\n */\n public static validateSchemaStructure(schema: unknown): string[] {\n const errors: string[] = [];\n\n if (!schema || typeof schema !== \"object\") {\n return [\"Root schema must be an object.\"];\n }\n\n const s = schema as Record<string, any>;\n if (s.type !== \"object\" && s.type !== \"array\") {\n errors.push(`Root schema must have type 'object' or 'array'. Found: '${s.type}'`);\n }\n\n if (s.type === \"object\" && !s.properties) {\n errors.push(\"Object schema is missing the 'properties' node.\");\n }\n\n if (s.properties) {\n for (const key of Object.keys(s.properties)) {\n const prop = s.properties[key];\n if (!prop || typeof prop !== \"object\") {\n errors.push(`Property '${key}' must be an object.`);\n continue;\n }\n\n if (!prop.type) {\n errors.push(`Property '${key}' is missing 'type'.`);\n } else {\n const allowedTypes: FieldType[] = [\"string\", \"number\", \"boolean\", \"date\", \"object\", \"array\"];\n if (!allowedTypes.includes(prop.type)) {\n errors.push(`Property '${key}' has invalid type '${prop.type}'. Allowed: ${allowedTypes.join(\", \")}`);\n }\n }\n\n // Removed strict check for prop.items on array properties because inference handles empty definitions\n\n }\n }\n\n return errors;\n }\n}\n"],"mappings":"AAAA,+FAOO,MAAMA,EAMT,8BAAcC,CAAwBC,GAClC,MAAMC,EAAmB,GAEzB,IAAKD,UAAiBA,IAAW,SAAU,CACvC,MAAO,CAAC,iCACZ,CAEA,MAAME,EAAIF,EACV,GAAIE,EAAEC,OAAS,UAAYD,EAAEC,OAAS,QAAS,CAC3CF,EAAOG,KAAK,2DAA2DF,EAAEC,QAC7E,CAEA,GAAID,EAAEC,OAAS,WAAaD,EAAEG,WAAY,CACtCJ,EAAOG,KAAK,kDAChB,CAEA,GAAIF,EAAEG,WAAY,CACd,IAAK,MAAMC,KAAOC,OAAOC,KAAKN,EAAEG,YAAa,CACzC,MAAMI,EAAOP,EAAEG,WAAWC,GAC1B,IAAKG,UAAeA,IAAS,SAAU,CACnCR,EAAOG,KAAK,aAAaE,yBACzB,QACJ,CAEA,IAAKG,EAAKN,KAAM,CACZF,EAAOG,KAAK,aAAaE,wBAC7B,KAAO,CACH,MAAMI,EAA4B,CAAC,SAAU,SAAU,UAAW,OAAQ,SAAU,SACpF,IAAKA,EAAaC,SAASF,EAAKN,MAAO,CACnCF,EAAOG,KAAK,aAAaE,wBAA0BG,EAAKN,mBAAmBO,EAAaE,KAAK,QACjG,CACJ,CAIJ,CACJ,CAEA,OAAOX,CACX,EACH,IAAAY,EAAA,CAAAC,WAAA,MAAAD,EAAAf,kBAAA,OAAAe,CAAA","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":23,"column":0},"map":{"version":3,"names":["GlobalPipeline","___PipelineManager","StateManager","schema","_useMessageManager","constructor","initialData","modelName","this","activeModelName","safeData","JSON","parse","stringify","model","JSONModel","setDefaultBindingMode","originalSetProperty","setProperty","bind","sPath","oValue","oContext","bAsyncUpdate","result","validatePath","setUseMessageManager","use","value","fieldKey","replace","metadata","findMetadataForPath","messageManager","Messaging","targetPath","startsWith","existingMessages","getMessageModel","getData","messagesToRemove","filter","msg","isMatch","getTarget","getMessageProcessor","getId","length","removeMessages","validatorsToRun","argsMap","required","push","type","maxLength","minLength","pattern","minimum","undefined","maximum","min","max","format","ui","validators","v","name","args","validationResult","executeValidation","isValid","newMsg","Message","message","errorMessage","coreLibrary","MessageType","Error","target","processor","addMessages","path","properties","getModel","bindControl","control","property","bindingPath","bindProperty","extractPayload","data","destroy","__exports","__esModule"],"sources":["StateManager.ts"],"sourcesContent":["/**\n * @file StateManager.ts\n * @description Isolated internal state management. Decouples the MetaUI engine from external host models.\n */\n\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\nimport ManagedObject from \"sap/ui/base/ManagedObject\";\nimport { ISchema, IPropertyMetadata } from \"../interfaces/ISchema\";\nimport { GlobalPipeline } from \"./PipelineManager\";\nimport Message from \"sap/ui/core/message/Message\";\nimport coreLibrary from \"sap/ui/core/library\";\nimport Core from \"sap/ui/core/Core\";\nimport Messaging from \"sap/ui/core/Messaging\";\n\n\n/**\n * Manages the isolated internal data payload for the MetaUI engine.\n */\nexport class StateManager {\n private model: JSONModel;\n private activeModelName: string;\n private schema: ISchema | null = null;\n private _useMessageManager: boolean = false;\n\n /**\n * Initializes the state manager with an authentic SAPUI5 JSONModel.\n * @param initialData The initial JSON payload to populate the fields.\n * @param schema The normalized schema for live validation.\n * @param modelName The UI5 model alias used for isolation.\n */\n constructor(initialData: Record<string, unknown> = {}, schema: ISchema, modelName: string = \"meta\") {\n this.activeModelName = modelName;\n this.schema = schema;\n \n // Deep copy to ensure no reference leakage from the host application\n const safeData = JSON.parse(JSON.stringify(initialData));\n this.model = new JSONModel(safeData);\n this.model.setDefaultBindingMode(\"TwoWay\");\n\n // Centralized Model-Level Validation Interceptor\n const originalSetProperty = this.model.setProperty.bind(this.model);\n this.model.setProperty = (sPath: string, oValue: unknown, oContext?: unknown, bAsyncUpdate?: boolean) => {\n const result = originalSetProperty(sPath, oValue, oContext, bAsyncUpdate);\n this.validatePath(sPath, oValue);\n return result;\n };\n }\n\n /**\n * Updates the flag indicating whether this manager should push validation errors directly to the global MessageManager.\n */\n public setUseMessageManager(use: boolean): void {\n this._useMessageManager = use;\n }\n\n /**\n * Validates a specific path against the schema and updates the MessageManager.\n */\n private validatePath(sPath: string, value: unknown): void {\n const fieldKey = sPath.replace(/^\\//, \"\");\n const metadata = this.findMetadataForPath(fieldKey);\n \n const messageManager = Messaging;\n const targetPath = sPath.startsWith(\"/\") ? sPath : `/${sPath}`; // Pure UI5: target MUST be absolute path\n \n // 1. Remove existing messages (strictly for THIS model instance)\n if (this._useMessageManager) {\n const existingMessages = messageManager.getMessageModel().getData();\n const messagesToRemove = existingMessages.filter((msg: sap.ui.core.message.Message) => {\n const isMatch = msg.getTarget() === targetPath && msg.getMessageProcessor() && msg.getMessageProcessor().getId() === this.model.getId();\n return isMatch;\n });\n \n if (messagesToRemove.length > 0) {\n messageManager.removeMessages(messagesToRemove);\n }\n }\n\n if (!metadata) return;\n\n // 2. Run GlobalPipeline\n const validatorsToRun: string[] = [];\n const argsMap: Record<string, unknown> = {};\n\n if (metadata.required) {\n validatorsToRun.push(\"required\");\n }\n if (metadata.type === \"string\" && metadata.maxLength) {\n validatorsToRun.push(\"maxLength\");\n argsMap[\"maxLength\"] = metadata.maxLength;\n }\n if (metadata.minLength) {\n validatorsToRun.push(\"minLength\");\n argsMap[\"minLength\"] = metadata.minLength;\n }\n if (metadata.pattern) {\n validatorsToRun.push(\"pattern\");\n argsMap[\"pattern\"] = metadata.pattern;\n }\n if (metadata.minimum !== undefined || metadata.maximum !== undefined) {\n validatorsToRun.push(\"range\");\n argsMap[\"range\"] = { min: metadata.minimum, max: metadata.maximum };\n }\n \n const format = metadata.ui?.format;\n if (format === \"email\" || format === \"url\" || format === \"iban\") {\n validatorsToRun.push(format);\n }\n if (metadata.ui?.validators) {\n for (const v of metadata.ui.validators) {\n if (typeof v === \"string\") {\n validatorsToRun.push(v);\n } else if (v && v.name) {\n validatorsToRun.push(v.name);\n if (v.args !== undefined) {\n argsMap[v.name] = v.args;\n }\n }\n }\n }\n\n if (validatorsToRun.length > 0) {\n const validationResult = GlobalPipeline.executeValidation(value, validatorsToRun, argsMap);\n if (!validationResult.isValid && this._useMessageManager) {\n const newMsg = new Message({\n message: validationResult.errorMessage || \"Invalid value.\",\n type: coreLibrary.MessageType.Error,\n target: targetPath,\n processor: this.model\n });\n messageManager.addMessages(newMsg);\n }\n }\n }\n\n /**\n * Resolves the schema metadata for a given internal binding path.\n * @param path The flat binding path representing the field.\n * @returns The associated IPropertyMetadata, or undefined if not mapped.\n */\n private findMetadataForPath(path: string): IPropertyMetadata | undefined {\n if (!this.schema || !this.schema.properties) return undefined;\n // Basic single-level support for now. Nested object resolution would split by '.' or '/'\n return this.schema.properties[path];\n }\n\n\n\n /**\n * Retrieves the isolated JSONModel instance to attach to the root GeneratorHost control.\n * @returns The internal JSONModel.\n */\n public getModel(): JSONModel {\n return this.model;\n }\n\n /**\n * Binds a generated UI control property to a path in the internal model.\n * @param control The target UI5 Control.\n * @param property The UI5 property name (e.g., 'value').\n * @param bindingPath The exact path in the JSON payload.\n */\n public bindControl(control: ManagedObject, property: string, bindingPath: string): void {\n control.bindProperty(property, {\n path: bindingPath,\n model: \"meta\" // Assumes the model is bound to the root container with the name 'meta'\n });\n }\n\n /**\n * Extracts the flat JavaScript object representing the current state of the UI.\n * @returns A serialized record of the data payload, free of UI5 wrappers.\n */\n public extractPayload(): Record<string, unknown> {\n // Create a deep copy to prevent accidental mutations by the host\n const data = this.model.getData();\n return JSON.parse(JSON.stringify(data));\n }\n\n /**\n * Cleans up internal state and natively destroys the UI5 JSONModel to prevent memory leaks.\n */\n public destroy(): void {\n \n if (this.model) {\n this.model.destroy();\n }\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"core"}},{"offset":{"line":24,"column":0},"map":{"version":3,"names":["SchemaNormalizer","___core_SchemaNormalizer","Logger","___utils_Logger","CompactLayout","render","schema","modelName","engine","onSubmit","container","VBox","renderType","addStyleClass","uiLayout","Array","isArray","warn","tableElements","renderElement","element","type","label","title","sap","m","Title","text","level","addItem","elements","forEach","scope","startsWith","error","meta","bindingPath","propKey","resolveScope","isCollectionOfRecords","items","properties","hasExplicitWidget","ui","widget","isSubLayout","debug","push","this","_renderScalarField","field","subSchema","control","generateLayout","msg","message","showErrorPopup","labelText","Label","required","effectiveMeta","generateField","fieldBox","__exports","__esModule"],"sources":["CompactLayout.ts"],"sourcesContent":["/**\n * @file CompactLayout.ts\n * @description Generates a lightweight, dense VBox layout for use inside tight spaces like table cells.\n */\n\nimport VBox from \"sap/m/VBox\";\nimport Label from \"sap/m/Label\";\nimport Title from \"sap/ui/core/Title\";\nimport { IPropertyMetadata, ISchema, ILayoutElement } from \"../interfaces/ISchema\";\nimport { ILayoutManager } from \"../interfaces/ILayoutManager\";\nimport { Engine } from \"../core/Engine\";\nimport { SchemaNormalizer } from \"../core/SchemaNormalizer\";\nimport { Logger } from \"../utils/Logger\";\nimport Control from \"sap/ui/core/Control\";\n\n/**\n * Layout Manager responsible for generating a dense, lightweight layout (no SimpleForm padding).\n * Ideal for rendering objects dynamically inside table cells or side-panels.\n * \n * @namespace nz.co.siliconst.ui5.metaui.layouts\n * @public\n */\nexport class CompactLayout implements ILayoutManager {\n /**\n * Renders the JSON Schema properties into a dense VBox layout.\n * \n * @param schema The active JSON schema subset.\n * @param modelName The bound UI5 model name.\n * @param engine The central orchestrator for delegating plugin generation.\n * @param onSubmit Optional submit hook.\n * @returns {Control} The VBox wrapper containing the generated compact form.\n */\n public render(schema: ISchema, modelName: string, engine: Engine, onSubmit?: () => void): Control {\n const container = new VBox({ renderType: \"Bare\" });\n container.addStyleClass(\"sapUiTinyMargin\");\n\n if (!schema.uiLayout || !Array.isArray(schema.uiLayout)) {\n Logger.warn(\"[MetaUI] Missing 'uiLayout' array in schema. CompactLayout will not render any fields.\");\n return container;\n }\n\n const tableElements: { scope: string, meta: IPropertyMetadata, label?: string }[] = [];\n\n // Recursively render layout elements\n const renderElement = (element: ILayoutElement) => {\n if (element.type === \"Group\") {\n if (element.label) {\n const title = new sap.m.Title({ text: element.label, level: \"H5\" });\n title.addStyleClass(\"sapUiTinyMarginTop sapUiTinyMarginBottom\");\n container.addItem(title);\n }\n \n if (element.elements && Array.isArray(element.elements)) {\n element.elements.forEach(renderElement);\n }\n } else if (element.type === \"Control\") {\n if (!element.scope || !element.scope.startsWith(\"#/properties/\")) {\n Logger.error(`[MetaUI] Invalid scope '${element.scope}' in uiLayout Control.`, \"\", \"CompactLayout\");\n return;\n }\n \n const { meta, bindingPath, propKey } = SchemaNormalizer.resolveScope(schema, element.scope);\n \n if (!meta) {\n Logger.error(`[MetaUI] Property '${propKey}' not found in schema definitions.`, \"\", \"CompactLayout\");\n return;\n }\n\n const isCollectionOfRecords = meta.items?.type === \"object\" || meta.items?.properties;\n const hasExplicitWidget = !!meta.ui?.widget;\n const isSubLayout = meta.type === \"array\" && isCollectionOfRecords && !hasExplicitWidget;\n\n if (isSubLayout) {\n Logger.debug(\"[MetaUI CompactLayout]\", `Routing property '${propKey}' to Table Sub-Layout.`, \"CompactLayout\");\n tableElements.push({ scope: bindingPath, meta, label: element.label });\n } else {\n Logger.debug(\"[MetaUI CompactLayout]\", `Rendering scalar field '${bindingPath}'.`, \"CompactLayout\");\n this._renderScalarField(container, element, bindingPath, meta, modelName, engine);\n }\n } else {\n Logger.warn(`[MetaUI] Unsupported layout element type '${element.type}'.`, \"\", \"CompactLayout\");\n }\n };\n\n // Render everything defined in the layout\n schema.uiLayout.forEach(renderElement);\n\n // Render array/table sub-layouts full width below the fields\n tableElements.forEach(field => {\n try {\n const subSchema = {\n type: \"array\",\n title: field.label || field.meta.ui?.label || field.scope,\n items: field.meta.items || { type: \"object\", properties: {} },\n uiLayout: field.meta.items?.uiLayout\n };\n \n const control = engine.generateLayout(subSchema as ISchema, modelName, `/${field.scope}`);\n if (control) {\n control.addStyleClass(\"sapUiTinyMarginTop\");\n container.addItem(control);\n }\n } catch (error) {\n const msg = (error as Error).message;\n Logger.error(`[MetaUI] Failed to render array field ${field.scope}`, msg, \"CompactLayout\");\n Logger.showErrorPopup(`Failed to render array field '${field.scope}'.\\n\\nDetails: ${msg}`);\n }\n });\n\n return container;\n }\n\n /**\n * Synthesizes a primitive field into the layout.\n * @param container The VBox container.\n * @param element The layout element definition.\n * @param propKey The bound property key.\n * @param meta The inferred metadata schema.\n * @param modelName The UI5 data model name.\n * @param engine The core Engine instance.\n */\n private _renderScalarField(container: VBox, element: ILayoutElement, propKey: string, meta: IPropertyMetadata, modelName: string, engine: Engine): void {\n try {\n const labelText = element.label || meta.ui?.label || propKey;\n const label = new Label({\n text: labelText,\n required: meta.required\n });\n label.addStyleClass(\"sapUiTinyMarginTop\");\n\n const effectiveMeta = { ...meta };\n if (element.widget) {\n effectiveMeta.ui = { ...meta.ui, widget: element.widget };\n }\n\n const control = engine.generateField(effectiveMeta, `/${propKey}`, modelName);\n control.addStyleClass(\"sapUiTinyMarginBottom\");\n\n // Wrap label and field tightly\n const fieldBox = new VBox({ renderType: \"Bare\", items: [label, control] });\n container.addItem(fieldBox);\n } catch (error) {\n const msg = (error as Error).message;\n Logger.error(`[MetaUI] Failed to render field ${propKey}`, msg, \"CompactLayout\");\n Logger.showErrorPopup(`Failed to render field '${propKey}'.\\n\\nDetails: ${msg}`);\n }\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"layouts"}},{"offset":{"line":25,"column":0},"map":{"version":3,"names":["SchemaNormalizer","___core_SchemaNormalizer","Logger","___utils_Logger","FormLayout","render","schema","modelName","engine","onSubmit","container","VBox","renderType","form","SimpleForm","editable","title","layout","labelSpanXL","labelSpanL","labelSpanM","labelSpanS","adjustLabelSpan","emptySpanXL","emptySpanL","emptySpanM","emptySpanS","columnsXL","columnsL","columnsM","singleContainerFullSize","uiLayout","Array","isArray","warn","addItem","tableElements","hasFormFields","renderElement","element","type","label","addContent","Title","text","elements","forEach","scope","startsWith","error","meta","bindingPath","propKey","resolveScope","isCollectionOfRecords","items","properties","hasExplicitWidget","ui","widget","isSubLayout","debug","push","this","_renderScalarField","field","subSchema","control","generateLayout","addStyleClass","msg","message","showErrorPopup","labelText","Label","required","effectiveMeta","generateField","isNativelyWide","isFullWidth","fullWidth","undefined","sap","require","GridData","setLayoutData","span","__exports","__esModule"],"sources":["FormLayout.ts"],"sourcesContent":["/**\n * @file FormLayout.ts\n * @description Generates a fully responsive SAP Fiori Form layout (SimpleForm).\n */\n\nimport SimpleForm from \"sap/ui/layout/form/SimpleForm\";\nimport Label from \"sap/m/Label\";\nimport Title from \"sap/ui/core/Title\";\nimport VBox from \"sap/m/VBox\";\nimport { IPropertyMetadata, ISchema, ILayoutElement } from \"../interfaces/ISchema\";\nimport { ILayoutManager } from \"../interfaces/ILayoutManager\";\nimport { Engine } from \"../core/Engine\";\nimport { SchemaNormalizer } from \"../core/SchemaNormalizer\";\nimport { Logger } from \"../utils/Logger\";\nimport Control from \"sap/ui/core/Control\";\n\n/**\n * Layout Manager responsible for generating a fully responsive SAP Fiori SimpleForm.\n * It traverses the `uiLayout` tree defined in the schema to build the form groups and fields,\n * completely separating visual orchestration from data modeling.\n * @namespace nz.co.siliconst.ui5.metaui.layouts\n * @public\n */\nexport class FormLayout implements ILayoutManager {\n /**\n * Renders the JSON Schema properties into a UI5 SimpleForm using the uiLayout definitions.\n * \n * @param schema The active JSON schema subset.\n * @param modelName The bound UI5 model name.\n * @param engine The central orchestrator for delegating plugin generation.\n * @param onSubmit Optional submit hook.\n * @returns {Control} The VBox wrapper containing the generated form.\n */\n public render(schema: ISchema, modelName: string, engine: Engine, onSubmit?: () => void): Control {\n const container = new VBox({ renderType: \"Bare\" });\n const form = new SimpleForm({\n editable: true,\n title: schema.title,\n layout: \"ResponsiveGridLayout\",\n labelSpanXL: 4, labelSpanL: 4, labelSpanM: 4, labelSpanS: 12,\n adjustLabelSpan: false,\n emptySpanXL: 0, emptySpanL: 0, emptySpanM: 0, emptySpanS: 0,\n columnsXL: 1, columnsL: 1, columnsM: 1,\n singleContainerFullSize: false\n });\n\n if (!schema.uiLayout || !Array.isArray(schema.uiLayout)) {\n Logger.warn(\"[MetaUI] Missing 'uiLayout' array in schema. Form will not render any fields.\");\n container.addItem(form);\n return container;\n }\n\n const tableElements: { scope: string, meta: IPropertyMetadata, label?: string }[] = [];\n let hasFormFields = false;\n\n // Recursively render layout elements\n const renderElement = (element: ILayoutElement) => {\n if (element.type === \"Group\") {\n if (element.label) {\n form.addContent(new Title({ text: element.label }));\n }\n \n if (element.elements && Array.isArray(element.elements)) {\n element.elements.forEach(renderElement);\n }\n } else if (element.type === \"Control\") {\n if (!element.scope || !element.scope.startsWith(\"#/properties/\")) {\n Logger.error(`[MetaUI] Invalid scope '${element.scope}' in uiLayout Control.`, \"\", \"FormLayout\");\n return;\n }\n \n const { meta, bindingPath, propKey } = SchemaNormalizer.resolveScope(schema, element.scope);\n \n if (!meta) {\n Logger.error(`[MetaUI] Property '${propKey}' not found in schema definitions.`, \"\", \"FormLayout\");\n return;\n }\n\n // Architectural Boundary: Separate Field Controls (Plugins) from Sub-Layouts (LayoutManagers)\n // A property is delegated to a Sub-Layout Manager (Table) ONLY if it represents a collection of complex objects.\n // Collections of primitives, or explicitly assigned widgets (like multiSelect), remain in the Form as Field Plugins.\n const isCollectionOfRecords = meta.items?.type === \"object\" || meta.items?.properties;\n const hasExplicitWidget = !!meta.ui?.widget;\n const isSubLayout = meta.type === \"array\" && isCollectionOfRecords && !hasExplicitWidget;\n\n if (isSubLayout) {\n Logger.debug(\"[MetaUI FormLayout]\", `Routing property '${propKey}' to Table Sub-Layout.`, \"FormLayout\");\n tableElements.push({ scope: bindingPath, meta, label: element.label });\n } else {\n hasFormFields = true;\n Logger.debug(\"[MetaUI FormLayout]\", `Rendering scalar field '${bindingPath}'.`, \"FormLayout\");\n this._renderScalarField(form, element, bindingPath, meta, modelName, engine);\n }\n } else {\n Logger.warn(`[MetaUI] Unsupported layout element type '${element.type}'.`, \"\", \"FormLayout\");\n }\n };\n\n // Render everything defined in the layout\n schema.uiLayout.forEach(renderElement);\n\n if (hasFormFields) {\n container.addItem(form);\n }\n\n // Render array/table sub-layouts full width below the form\n tableElements.forEach(field => {\n try {\n const subSchema = {\n type: \"array\",\n title: field.label || field.meta.ui?.label || field.scope,\n items: field.meta.items || { type: \"object\", properties: {} },\n uiLayout: field.meta.items?.uiLayout // Pass down sub-layout if available\n };\n \n const control = engine.generateLayout(subSchema as ISchema, modelName, `/${field.scope}`);\n if (control) {\n control.addStyleClass(\"sapUiSmallMarginTop\");\n container.addItem(control);\n }\n } catch (error) {\n const msg = (error as Error).message;\n Logger.error(`[MetaUI] Failed to render array field ${field.scope}`, msg, \"FormLayout\");\n Logger.showErrorPopup(`Failed to render array field '${field.scope}'.\\n\\nDetails: ${msg}`);\n }\n });\n\n return container;\n }\n\n /**\n * Synthesizes a primitive field into the Form.\n * @param form The SimpleForm instance.\n * @param element The layout element definition.\n * @param propKey The bound property key.\n * @param meta The inferred metadata schema.\n * @param modelName The UI5 data model name.\n * @param engine The core Engine instance.\n */\n private _renderScalarField(form: SimpleForm, element: ILayoutElement, propKey: string, meta: IPropertyMetadata, modelName: string, engine: Engine): void {\n try {\n const labelText = element.label || meta.ui?.label || propKey;\n const label = new Label({\n text: labelText,\n required: meta.required\n });\n\n // Override widget if specified in the layout element\n const effectiveMeta = { ...meta };\n if (element.widget) {\n effectiveMeta.ui = { ...meta.ui, widget: element.widget };\n }\n\n const control = engine.generateField(effectiveMeta, `/${propKey}`, modelName);\n\n // Automatically apply fullWidth layout data if natively wide or explicitly requested\n const widget = effectiveMeta.ui?.widget;\n const isNativelyWide = widget === \"codeEditor\" || widget === \"textArea\" || widget === \"richText\";\n const isFullWidth = effectiveMeta.ui?.fullWidth !== undefined ? effectiveMeta.ui?.fullWidth : isNativelyWide;\n\n if (isFullWidth) {\n sap.ui.require([\"sap/ui/layout/GridData\"], (GridData: typeof import(\"sap/ui/layout/GridData\").default) => {\n control.setLayoutData(new GridData({ span: \"XL12 L12 M12 S12\" }));\n });\n }\n\n form.addContent(label);\n form.addContent(control);\n } catch (error) {\n const msg = (error as Error).message;\n Logger.error(`[MetaUI] Failed to render field ${propKey}`, msg, \"FormLayout\");\n Logger.showErrorPopup(`Failed to render field '${propKey}'.\\n\\nDetails: ${msg}`);\n }\n }\n}\n"],"mappings":"AAAA,yOAYSA,EAAgBC,EAAA,0BAChBC,EAAMC,EAAA,UAUR,MAAMC,EAUFC,OAAOC,EAAiBC,EAAmBC,EAAgBC,GAC9D,MAAMC,EAAY,IAAIC,EAAK,CAAEC,WAAY,SACzC,MAAMC,EAAO,IAAIC,EAAW,CACxBC,SAAU,KACVC,MAAOV,EAAOU,MACdC,OAAQ,uBACRC,YAAa,EAAGC,WAAY,EAAGC,WAAY,EAAGC,WAAY,GAC1DC,gBAAiB,MACjBC,YAAa,EAAGC,WAAY,EAAGC,WAAY,EAAGC,WAAY,EAC1DC,UAAW,EAAGC,SAAU,EAAGC,SAAU,EACrCC,wBAAyB,QAG7B,IAAKxB,EAAOyB,WAAaC,MAAMC,QAAQ3B,EAAOyB,UAAW,CACrD7B,EAAOgC,KAAK,iFACZxB,EAAUyB,QAAQtB,GAClB,OAAOH,CACX,CAEA,MAAM0B,EAA8E,GACpF,IAAIC,EAAgB,MAGpB,MAAMC,EAAiBC,IACnB,GAAIA,EAAQC,OAAS,QAAS,CAC1B,GAAID,EAAQE,MAAO,CACf5B,EAAK6B,WAAW,IAAIC,EAAM,CAAEC,KAAML,EAAQE,QAC9C,CAEA,GAAIF,EAAQM,UAAYb,MAAMC,QAAQM,EAAQM,UAAW,CACrDN,EAAQM,SAASC,QAAQR,EAC7B,CACJ,MAAO,GAAIC,EAAQC,OAAS,UAAW,CACnC,IAAKD,EAAQQ,QAAUR,EAAQQ,MAAMC,WAAW,iBAAkB,CAC9D9C,EAAO+C,MAAM,2BAA2BV,EAAQQ,8BAA+B,GAAI,cACnF,MACJ,CAEA,MAAMG,KAAEA,EAAIC,YAAEA,EAAWC,QAAEA,GAAYpD,EAAiBqD,aAAa/C,EAAQiC,EAAQQ,OAErF,IAAKG,EAAM,CACPhD,EAAO+C,MAAM,sBAAsBG,sCAA6C,GAAI,cACpF,MACJ,CAKA,MAAME,EAAwBJ,EAAKK,OAAOf,OAAS,UAAYU,EAAKK,OAAOC,WAC3E,MAAMC,IAAsBP,EAAKQ,IAAIC,OACrC,MAAMC,EAAcV,EAAKV,OAAS,SAAWc,IAA0BG,EAEvE,GAAIG,EAAa,CACb1D,EAAO2D,MAAM,sBAAuB,qBAAqBT,0BAAiC,cAC1FhB,EAAc0B,KAAK,CAAEf,MAAOI,EAAaD,OAAMT,MAAOF,EAAQE,OAClE,KAAO,CACHJ,EAAgB,KAChBnC,EAAO2D,MAAM,sBAAuB,2BAA2BV,MAAiB,cAChFY,KAAKC,mBAAmBnD,EAAM0B,EAASY,EAAaD,EAAM3C,EAAWC,EACzE,CACJ,KAAO,CACHN,EAAOgC,KAAK,6CAA6CK,EAAQC,SAAU,GAAI,aACnF,GAIJlC,EAAOyB,SAASe,QAAQR,GAExB,GAAID,EAAe,CACf3B,EAAUyB,QAAQtB,EACtB,CAGAuB,EAAcU,QAAQmB,IAClB,IACI,MAAMC,EAAY,CACd1B,KAAM,QACNxB,MAAOiD,EAAMxB,OAASwB,EAAMf,KAAKQ,IAAIjB,OAASwB,EAAMlB,MACpDQ,MAAOU,EAAMf,KAAKK,OAAS,CAAEf,KAAM,SAAUgB,WAAY,CAAC,GAC1DzB,SAAUkC,EAAMf,KAAKK,OAAOxB,UAGhC,MAAMoC,EAAU3D,EAAO4D,eAAeF,EAAsB3D,EAAW,IAAI0D,EAAMlB,SACjF,GAAIoB,EAAS,CACTA,EAAQE,cAAc,uBACtB3D,EAAUyB,QAAQgC,EACtB,CACJ,CAAE,MAAOlB,GACL,MAAMqB,EAAOrB,EAAgBsB,QAC7BrE,EAAO+C,MAAM,yCAAyCgB,EAAMlB,QAASuB,EAAK,cAC1EpE,EAAOsE,eAAe,iCAAiCP,EAAMlB,uBAAuBuB,IACxF,IAGJ,OAAO5D,CACX,CAWQsD,mBAAmBnD,EAAkB0B,EAAyBa,EAAiBF,EAAyB3C,EAAmBC,GAC/H,IACI,MAAMiE,EAAYlC,EAAQE,OAASS,EAAKQ,IAAIjB,OAASW,EACrD,MAAMX,EAAQ,IAAIiC,EAAM,CACpB9B,KAAM6B,EACNE,SAAUzB,EAAKyB,WAInB,MAAMC,EAAgB,IAAK1B,GAC3B,GAAIX,EAAQoB,OAAQ,CAChBiB,EAAclB,GAAK,IAAKR,EAAKQ,GAAIC,OAAQpB,EAAQoB,OACrD,CAEA,MAAMQ,EAAU3D,EAAOqE,cAAcD,EAAe,IAAIxB,IAAW7C,GAGnE,MAAMoD,EAASiB,EAAclB,IAAIC,OACjC,MAAMmB,EAAiBnB,IAAW,cAAgBA,IAAW,YAAcA,IAAW,WACtF,MAAMoB,EAAcH,EAAclB,IAAIsB,YAAcC,UAAYL,EAAclB,IAAIsB,UAAYF,EAE9F,GAAIC,EAAa,CACbG,IAAIxB,GAAGyB,QAAQ,CAAC,0BAA4BC,IACxCjB,EAAQkB,cAAc,IAAID,EAAS,CAAEE,KAAM,uBAEnD,CAEAzE,EAAK6B,WAAWD,GAChB5B,EAAK6B,WAAWyB,EACpB,CAAE,MAAOlB,GACL,MAAMqB,EAAOrB,EAAgBsB,QAC7BrE,EAAO+C,MAAM,mCAAmCG,IAAWkB,EAAK,cAChEpE,EAAOsE,eAAe,2BAA2BpB,mBAAyBkB,IAC9E,CACJ,EACH,IAAAiB,EAAA,CAAAC,WAAA,MAAAD,EAAAnF,aAAA,OAAAmF,CAAA","ignoreList":[],"sourceRoot":"layouts"}},{"offset":{"line":26,"column":0},"map":{"version":3,"names":["SchemaNormalizer","___core_SchemaNormalizer","Logger","___utils_Logger","TableLayout","render","schema","modelName","engine","onSubmit","bindingPath","type","items","properties","Error","tableTitle","title","actualModelName","actualPath","table","Table","headerToolbar","Toolbar","content","Title","text","ToolbarSpacer","isEditable","Button","icon","press","oEvent","btn","getSource","tbl","getParent","model","getModel","info","getBindingInfo","path","rawData","getProperty","data","Array","isArray","newData","setProperty","onChange","replace","fixedLayout","mode","delete","item","getParameter","getBindingContext","getPath","splitPaths","split","index","parseInt","pop","arrayPath","join","splice","templateCells","props","layoutElements","uiLayout","forEach","element","scope","meta","fieldMeta","propKey","resolveScope","error","addColumn","Column","header","Text","label","ui","demandPopin","isKey","minScreenWidth","popinDisplay","effectiveMeta","widget","control","generateField","push","warn","debug","Object","keys","key","column","msg","message","showErrorPopup","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 Control from \"sap/ui/core/Control\";\nimport { IPropertyMetadata, ISchema, ILayoutElement } from \"../interfaces/ISchema\";\nimport { ILayoutManager } from \"../interfaces/ILayoutManager\";\nimport { Engine } from \"../core/Engine\";\nimport { SchemaNormalizer } from \"../core/SchemaNormalizer\";\nimport { Logger } from \"../utils/Logger\";\n\n/**\n * Layout Manager responsible for generating a responsive SAP Fiori Table.\n * It is automatically utilized by the Engine when the schema root or property is of type 'array'.\n * Includes built-in support for adding and deleting rows via dynamic data binding manipulation.\n * \n * @namespace nz.co.siliconst.ui5.metaui.layouts\n * @public\n */\nexport class TableLayout implements ILayoutManager {\n /**\n * Renders the JSON Schema array properties into a UI5 Table.\n * \n * @param schema The active JSON schema array definition.\n * @param modelName The UI5 JSONModel name used for data binding.\n * @param engine The central orchestrator for delegating column plugin generation.\n * @param onSubmit Optional submit hook.\n * @param bindingPath The JSON path representing the array within the payload.\n * @returns {Control} The generated sap.m.Table control.\n * @throws {Error} If the provided schema is not of type 'array'.\n */\n public render(schema: ISchema, modelName: string, engine: Engine, onSubmit?: () => void, bindingPath: string = \"/\"): Control {\n if (schema.type !== \"array\" || !schema.items || !schema.items.properties) {\n throw new Error(\"[MetaUI] TableLayout requires an array schema with items.properties.\");\n }\n\n const tableTitle = schema.title || \"Table\";\n const actualModelName = modelName;\n const actualPath = bindingPath;\n\n const table = new Table({\n headerToolbar: new Toolbar({\n content: [\n new Title({ text: tableTitle }),\n new ToolbarSpacer(),\n ...(!engine.isEditable ? [] : [\n new Button({\n text: \"Add Row\",\n icon: \"sap-icon://add\",\n press: (oEvent: sap.ui.base.Event) => {\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 rawData = model.getProperty(info.path);\n const data = Array.isArray(rawData) ? rawData : [];\n const newData = [...data, {}];\n model.setProperty(info.path, newData);\n\n // CRITICAL: Notify the engine so it extracts payload and triggers liveUpdate\n if (engine.onChange) {\n engine.onChange(true, actualPath.replace(/^\\//, \"\"));\n }\n }\n })\n ])\n ]\n }),\n fixedLayout: false,\n mode: !engine.isEditable ? \"None\" : \"Delete\",\n delete: (oEvent: sap.ui.base.Event) => {\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 rawData = model.getProperty(arrayPath);\n const data = Array.isArray(rawData) ? rawData : [];\n const newData = [...data];\n newData.splice(index, 1);\n model.setProperty(arrayPath, newData);\n\n // CRITICAL: Notify the engine so it extracts payload and triggers liveUpdate\n if (engine.onChange) {\n engine.onChange(true, actualPath.replace(/^\\//, \"\"));\n }\n }\n });\n\n const templateCells: Control[] = [];\n const props = schema.items.properties;\n const layoutElements = schema.uiLayout;\n\n if (layoutElements && Array.isArray(layoutElements)) {\n // Only render columns defined in uiLayout\n layoutElements.forEach((element: ILayoutElement) => {\n if (element.type === \"Control\" && element.scope) {\n const { meta: fieldMeta, bindingPath, propKey } = SchemaNormalizer.resolveScope(\n { type: \"object\", properties: props } as ISchema, \n element.scope\n );\n \n if (!fieldMeta) {\n Logger.error(`[MetaUI] Property '${propKey}' not found in schema definitions for Table.`, \"\", \"TableLayout\");\n } else {\n // The architectural boundary: Table Layout orchestrates the columns and aggregation binding,\n // but delegates the actual cell rendering to the Engine's Field Plugins.\n table.addColumn(new Column({\n header: new Text({ text: element.label || fieldMeta.ui?.label || propKey }),\n demandPopin: !fieldMeta.ui?.isKey,\n minScreenWidth: fieldMeta.ui?.isKey ? \"\" : \"Tablet\",\n popinDisplay: \"Inline\"\n }));\n\n const effectiveMeta = { ...fieldMeta };\n if (element.widget) {\n effectiveMeta.ui = { ...fieldMeta.ui, widget: element.widget };\n }\n\n // We pass the activeModel as actualModelName down. But the path must be relative to the \n // table row binding context, so we just use the bindingPath (e.g. \"id\" or \"header/id\")\n const control = engine.generateField(effectiveMeta, bindingPath, actualModelName || \"meta\", true);\n templateCells.push(control);\n }\n } else {\n Logger.warn(`[MetaUI] Unsupported layout element type '${element.type}' in Table.`, \"\", \"TableLayout\");\n }\n });\n } else {\n Logger.debug(\"[MetaUI TableLayout]\", \"No uiLayout provided. Falling back to rendering all properties as columns.\", \"TableLayout\");\n // Fallback: If no uiLayout is provided, render all properties as columns\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 control = engine.generateField(fieldMeta, key, actualModelName || \"meta\", true);\n templateCells.push(control);\n } catch (error) {\n const msg = (error as Error).message;\n Logger.error(`[MetaUI] Failed to render fallback column ${key}`, msg, \"TableLayout\");\n Logger.showErrorPopup(`Failed to render fallback table column '${key}'.\\n\\nDetails: ${msg}`);\n templateCells.push(new Text({ text: \"Error\" }));\n }\n });\n }\n\n\n\n const rowTemplate = new ColumnListItem({\n cells: templateCells\n });\n\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":[],"sourceRoot":"layouts"}},{"offset":{"line":27,"column":0},"map":{"version":3,"names":["SchemaNormalizer","___core_SchemaNormalizer","Logger","___utils_Logger","WizardLayout","render","schema","modelName","engine","onSubmit","wizard","Wizard","renderMode","showNextButton","complete","uiLayout","Array","isArray","warn","forEach","element","type","step","WizardStep","title","label","validated","form","SimpleForm","editable","layout","labelSpanXL","labelSpanL","labelSpanM","labelSpanS","adjustLabelSpan","emptySpanXL","emptySpanL","emptySpanM","emptySpanS","columnsXL","columnsL","columnsM","singleContainerFullSize","elements","childElement","this","_renderElementInForm","addContent","addStep","scope","startsWith","error","meta","bindingPath","propKey","resolveScope","labelText","ui","Label","text","required","effectiveMeta","widget","control","generateField","fullWidth","sap","require","GridData","setLayoutData","span","message","__exports","__esModule"],"sources":["WizardLayout.ts"],"sourcesContent":["/**\n * @file WizardLayout.ts\n * @description Generates a fully responsive SAP Fiori Wizard layout.\n */\n\nimport Wizard from \"sap/m/Wizard\";\nimport WizardStep from \"sap/m/WizardStep\";\nimport SimpleForm from \"sap/ui/layout/form/SimpleForm\";\nimport Label from \"sap/m/Label\";\nimport VBox from \"sap/m/VBox\";\nimport { IPropertyMetadata, ISchema, ILayoutElement } from \"../interfaces/ISchema\";\nimport { ILayoutManager } from \"../interfaces/ILayoutManager\";\nimport { Engine } from \"../core/Engine\";\nimport { SchemaNormalizer } from \"../core/SchemaNormalizer\";\nimport { Logger } from \"../utils/Logger\";\nimport Control from \"sap/ui/core/Control\";\n\n/**\n * Layout Manager responsible for generating a responsive SAP Fiori Wizard.\n * It segments the schema fields into discrete Wizard Steps based on `uiLayout` elements \n * of type `Group` or `WizardStep`.\n * \n * @namespace nz.co.siliconst.ui5.metaui.layouts\n * @public\n */\nexport class WizardLayout implements ILayoutManager {\n /**\n * Renders the JSON Schema properties into a paginated UI5 Wizard using uiLayout.\n * \n * @param schema The active JSON schema object.\n * @param modelName The bound UI5 model name.\n * @param engine The central orchestrator for delegating plugin generation.\n * @param onSubmit Hook executed when the Wizard's native 'complete' event is fired.\n * @returns {Control} The generated sap.m.Wizard control.\n */\n public render(schema: ISchema, modelName: string, engine: Engine, onSubmit?: () => void): Control {\n const wizard = new Wizard({\n renderMode: \"Page\",\n showNextButton: true,\n complete: function() {\n if (onSubmit) onSubmit();\n }\n });\n\n if (!schema.uiLayout || !Array.isArray(schema.uiLayout)) {\n Logger.warn(\"[MetaUI] Missing 'uiLayout' array in wizard schema. Wizard will not render any steps.\");\n return wizard;\n }\n\n schema.uiLayout.forEach((element: ILayoutElement) => {\n if (element.type === \"Group\" || element.type === \"WizardStep\") {\n const step = new WizardStep({\n title: element.label || \"Step\",\n validated: true // The PipelineManager handles global validation, wizard step validation can be local later\n });\n\n const form = new SimpleForm({\n editable: true,\n layout: \"ResponsiveGridLayout\",\n labelSpanXL: 4, labelSpanL: 4, labelSpanM: 4, labelSpanS: 12,\n adjustLabelSpan: false,\n emptySpanXL: 0, emptySpanL: 0, emptySpanM: 0, emptySpanS: 0,\n columnsXL: 1, columnsL: 1, columnsM: 1,\n singleContainerFullSize: false\n });\n \n if (element.elements && Array.isArray(element.elements)) {\n element.elements.forEach(childElement => {\n this._renderElementInForm(form, childElement, schema, modelName, engine);\n });\n }\n\n step.addContent(form);\n wizard.addStep(step);\n } else {\n Logger.warn(`[MetaUI] Top-level element '${element.type}' inside WizardLayout must be 'Group' or 'WizardStep'.`, \"\", \"WizardLayout\");\n }\n });\n\n return wizard;\n }\n\n /**\n * Synthesizes a field into the wizard step form.\n * @param form The SimpleForm belonging to the step.\n * @param element The layout element definition.\n * @param schema The schema reference.\n * @param modelName The UI5 data model name.\n * @param engine The core Engine instance.\n */\n private _renderElementInForm(form: SimpleForm, element: ILayoutElement, schema: ISchema, modelName: string, engine: Engine): void {\n if (element.type === \"Control\") {\n if (!element.scope || !element.scope.startsWith(\"#/properties/\")) {\n Logger.error(`[MetaUI] Invalid scope '${element.scope}' in uiLayout Control.`, \"\", \"WizardLayout\");\n return;\n }\n \n const { meta, bindingPath, propKey } = SchemaNormalizer.resolveScope(schema, element.scope);\n \n if (!meta) {\n Logger.error(`[MetaUI] Property '${propKey}' not found in schema definitions.`, \"\", \"WizardLayout\");\n return;\n }\n\n try {\n const labelText = element.label || meta.ui?.label || propKey;\n const label = new Label({\n text: labelText,\n required: meta.required\n });\n\n const effectiveMeta = { ...meta };\n if (element.widget) {\n effectiveMeta.ui = { ...meta.ui, widget: element.widget };\n }\n\n const control = engine.generateField(effectiveMeta, `/${bindingPath}`, modelName);\n\n if (effectiveMeta.ui?.fullWidth) {\n sap.ui.require([\"sap/ui/layout/GridData\"], (GridData: typeof import(\"sap/ui/layout/GridData\").default) => {\n control.setLayoutData(new GridData({ span: \"XL12 L12 M12 S12\" }));\n });\n }\n\n form.addContent(label);\n form.addContent(control);\n } catch (error) {\n Logger.error(`[MetaUI] Failed to render Wizard field ${propKey}`, (error as Error).message, \"WizardLayout\");\n form.addContent(new Label({ text: propKey }));\n }\n } else {\n Logger.warn(`[MetaUI] Nested groups within Wizard steps are not fully supported in SimpleForm yet.`, \"\", \"WizardLayout\");\n }\n }\n}\n"],"mappings":"AAAA,4OAaSA,EAAgBC,EAAA,0BAChBC,EAAMC,EAAA,UAWR,MAAMC,EAUFC,OAAOC,EAAiBC,EAAmBC,EAAgBC,GAC9D,MAAMC,EAAS,IAAIC,EAAO,CACtBC,WAAY,OACZC,eAAgB,KAChBC,SAAU,WACN,GAAIL,EAAUA,GAClB,IAGJ,IAAKH,EAAOS,WAAaC,MAAMC,QAAQX,EAAOS,UAAW,CACrDb,EAAOgB,KAAK,yFACZ,OAAOR,CACX,CAEAJ,EAAOS,SAASI,QAASC,IACrB,GAAIA,EAAQC,OAAS,SAAWD,EAAQC,OAAS,aAAc,CAC3D,MAAMC,EAAO,IAAIC,EAAW,CACxBC,MAAOJ,EAAQK,OAAS,OACxBC,UAAW,OAGf,MAAMC,EAAO,IAAIC,EAAW,CACxBC,SAAU,KACVC,OAAQ,uBACRC,YAAa,EAAGC,WAAY,EAAGC,WAAY,EAAGC,WAAY,GAC1DC,gBAAiB,MACjBC,YAAa,EAAGC,WAAY,EAAGC,WAAY,EAAGC,WAAY,EAC1DC,UAAW,EAAGC,SAAU,EAAGC,SAAU,EACrCC,wBAAyB,QAG7B,GAAIvB,EAAQwB,UAAY5B,MAAMC,QAAQG,EAAQwB,UAAW,CACrDxB,EAAQwB,SAASzB,QAAQ0B,IACrBC,KAAKC,qBAAqBpB,EAAMkB,EAAcvC,EAAQC,EAAWC,IAEzE,CAEAc,EAAK0B,WAAWrB,GAChBjB,EAAOuC,QAAQ3B,EACnB,KAAO,CACHpB,EAAOgB,KAAK,+BAA+BE,EAAQC,6DAA8D,GAAI,eACzH,IAGJ,OAAOX,CACX,CAUQqC,qBAAqBpB,EAAkBP,EAAyBd,EAAiBC,EAAmBC,GACxG,GAAIY,EAAQC,OAAS,UAAW,CAC5B,IAAKD,EAAQ8B,QAAU9B,EAAQ8B,MAAMC,WAAW,iBAAkB,CAC9DjD,EAAOkD,MAAM,2BAA2BhC,EAAQ8B,8BAA+B,GAAI,gBACnF,MACJ,CAEA,MAAMG,KAAEA,EAAIC,YAAEA,EAAWC,QAAEA,GAAYvD,EAAiBwD,aAAalD,EAAQc,EAAQ8B,OAErF,IAAKG,EAAM,CACPnD,EAAOkD,MAAM,sBAAsBG,sCAA6C,GAAI,gBACpF,MACJ,CAEA,IACI,MAAME,EAAYrC,EAAQK,OAAS4B,EAAKK,IAAIjC,OAAS8B,EACrD,MAAM9B,EAAQ,IAAIkC,EAAM,CACpBC,KAAMH,EACNI,SAAUR,EAAKQ,WAGnB,MAAMC,EAAgB,IAAKT,GAC3B,GAAIjC,EAAQ2C,OAAQ,CAChBD,EAAcJ,GAAK,IAAKL,EAAKK,GAAIK,OAAQ3C,EAAQ2C,OACrD,CAEA,MAAMC,EAAUxD,EAAOyD,cAAcH,EAAe,IAAIR,IAAe/C,GAEvE,GAAIuD,EAAcJ,IAAIQ,UAAW,CAC7BC,IAAIT,GAAGU,QAAQ,CAAC,0BAA4BC,IACxCL,EAAQM,cAAc,IAAID,EAAS,CAAEE,KAAM,uBAEnD,CAEA5C,EAAKqB,WAAWvB,GAChBE,EAAKqB,WAAWgB,EACpB,CAAE,MAAOZ,GACLlD,EAAOkD,MAAM,0CAA0CG,IAAYH,EAAgBoB,QAAS,gBAC5F7C,EAAKqB,WAAW,IAAIW,EAAM,CAAEC,KAAML,IACtC,CACJ,KAAO,CACHrD,EAAOgB,KAAK,wFAAyF,GAAI,eAC7G,CACJ,EACH,IAAAuD,EAAA,CAAAC,WAAA,MAAAD,EAAArE,eAAA,OAAAqE,CAAA","ignoreList":[],"sourceRoot":"layouts"}},{"offset":{"line":28,"column":0},"map":{"version":3,"names":["Core","initLibrary","name","version","dependencies","controls","elements","interfaces","noLibraryCSS","__exports","window","nz","co","siliconst","ui5","metaui"],"sources":["library.ts"],"sourcesContent":["/**\n * @file library.ts\n * @description Standard SAP UI5 library registration file. Exposes the MetaUI namespace \n * and automatically bootstraps the internal PluginRegistry.\n */\n\nimport Core from \"sap/ui/core/Core\";\n\n// Explicitly import core plugins to bundle them into library-preload.js\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/StringPlugin\";\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/NumberPlugin\";\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/BooleanPlugin\";\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/ObjectPlugin\";\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/ArrayPlugin\";\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/DropdownPlugin\";\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/MultiInputPlugin\";\nimport \"nz/co/siliconst/ui5/metaui/plugins/controls/DatePlugin\";\nimport \"nz/co/siliconst/ui5/metaui/core/DefaultLayoutGenerator\";\nimport \"nz/co/siliconst/ui5/metaui/utils/ExpressionBuilder\";\n\n// Explicitly import core Layouts\nimport \"nz/co/siliconst/ui5/metaui/layouts/FormLayout\";\nimport \"nz/co/siliconst/ui5/metaui/layouts/TableLayout\";\nimport \"nz/co/siliconst/ui5/metaui/layouts/WizardLayout\";\nimport \"nz/co/siliconst/ui5/metaui/layouts/CompactLayout\";\n\n// Delegate to standard library registration\nCore.initLibrary({\n name: \"nz.co.siliconst.ui5.metaui\",\n version: \"1.0.0\",\n dependencies: [\n \"sap.ui.core\",\n \"sap.m\",\n \"sap.ui.layout\",\n \"sap.ui.table\"\n ],\n controls: [\n \"nz.co.siliconst.ui5.metaui.controls.DynamicHost\",\n \"nz.co.siliconst.ui5.metaui.controls.host.GeneratorHost\",\n \"nz.co.siliconst.ui5.metaui.controls.BaseHardwareControl\",\n \"nz.co.siliconst.ui5.metaui.controls.CameraControl\",\n \"nz.co.siliconst.ui5.metaui.controls.BarcodeScannerControl\",\n \"nz.co.siliconst.ui5.metaui.controls.SignatureControl\",\n \"nz.co.siliconst.ui5.metaui.controls.VoiceInputControl\",\n \"nz.co.siliconst.ui5.metaui.controls.GeolocationControl\",\n \"nz.co.siliconst.ui5.metaui.controls.RichTextControl\"\n ],\n elements: [],\n interfaces: [],\n noLibraryCSS: true\n});\n\n// Exporting window object safely for UI5 compatibility if needed\ndeclare global {\n interface Window {\n nz: {\n co: {\n siliconst: {\n ui5: {\n metaui: Record<string, unknown>;\n };\n };\n };\n };\n }\n}\n\nexport default window.nz.co.siliconst.ui5.metaui;\n"],"mappings":"AAAA,i5BA2BAA,EAAKC,YAAY,CACbC,KAAM,6BACNC,QAAS,QACTC,aAAc,CACV,cACA,QACA,gBACA,gBAEJC,SAAU,CACN,kDACA,yDACA,0DACA,oDACA,4DACA,uDACA,wDACA,yDACA,uDAEJC,SAAU,GACVC,WAAY,GACZC,aAAc,OAGlB,IAAAC,EAeeC,OAAOC,GAAGC,GAAGC,UAAUC,IAAIC,OAAM,OAAAN,CAAA","ignoreList":[],"sourceRoot":""}},{"offset":{"line":29,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","ClearFormActionPlugin","render","fieldMetadata","bindingPath","modelName","this","metadata","isEditable","sap","ui","requireSync","TextControl","require","control","visible","Button","text","label","type","icon","press","oEvent","btn","getSource","model","getModel","setProperty","getValue","applyState","setEnabled","readOnly","__exports","__esModule"],"sources":["ClearFormActionPlugin.ts"],"sourcesContent":["/**\n * @file ClearFormActionPlugin.ts\n * @description A custom action plugin that renders a Button to reset the model data.\n */\n\nimport { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Button from \"sap/m/Button\";\nimport Control from \"sap/ui/core/Control\";\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\n\n/**\n * A custom action plugin that renders a Button to reset the model data.\n * Demonstrates how to create functional action plugins that interact with the bound model.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.actions\n * @public\n */\nexport class ClearFormActionPlugin extends BasePlugin {\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\"): Control {\n this.metadata = fieldMetadata;\n \n if (!this.isEditable) {\n sap.ui.requireSync(\"sap/m/Text\");\n const TextControl = sap.ui.require(\"sap/m/Text\");\n this.control = new TextControl({ visible: false });\n return this.control as Control;\n }\n \n this.control = new Button({\n text: fieldMetadata.ui?.label || \"Clear Data\",\n type: \"Reject\",\n icon: \"sap-icon://delete\",\n press: (oEvent: sap.ui.base.Event) => {\n const btn = oEvent.getSource() as Button;\n const model = btn.getModel(modelName) as JSONModel;\n if (model) {\n // Reset the entire model payload to an empty object\n model.setProperty(\"/\", {});\n }\n }\n });\n\n return this.control as Control;\n }\n\n protected getValue(): unknown {\n return null; // Actions do not store scalar values\n }\n\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as Button).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,0JAAA,MAKSA,EAAUC,EAAA,cAaZ,MAAMC,UAA8BF,EAChCG,OAAOC,EAAkCC,EAAqBC,EAAoB,QACrFC,KAAKC,SAAWJ,EAEhB,IAAKG,KAAKE,WAAY,CAClBC,IAAIC,GAAGC,YAAY,cACnB,MAAMC,EAAcH,IAAIC,GAAGG,QAAQ,cACnCP,KAAKQ,QAAU,IAAIF,EAAY,CAAEG,QAAS,QAC1C,OAAOT,KAAKQ,OAChB,CAEAR,KAAKQ,QAAU,IAAIE,EAAO,CACtBC,KAAMd,EAAcO,IAAIQ,OAAS,aACjCC,KAAM,SACNC,KAAM,oBACNC,MAAQC,IACJ,MAAMC,EAAMD,EAAOE,YACnB,MAAMC,EAAQF,EAAIG,SAASrB,GAC3B,GAAIoB,EAAO,CAEPA,EAAME,YAAY,IAAK,CAAC,EAC5B,KAIR,OAAOrB,KAAKQ,OAChB,CAEUc,WACN,OAAO,IACX,CAEUC,aACN,GAAIvB,KAAKQ,SAAWR,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACrBF,KAAKQ,QAAmBgB,YAAYxB,KAAKC,SAASG,IAAIqB,SAC3D,CACJ,EACH,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAA/B,wBAAA,OAAA+B,CAAA","ignoreList":[],"sourceRoot":"plugins/actions"}},{"offset":{"line":30,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","SubmitFormActionPlugin","render","fieldMetadata","bindingPath","modelName","this","metadata","isEditable","sap","ui","requireSync","TextControl","require","control","visible","Button","text","label","type","icon","press","Core","getEventBus","publish","getValue","applyState","setEnabled","readOnly","__exports","__esModule"],"sources":["SubmitFormActionPlugin.ts"],"sourcesContent":["/**\n * @file SubmitFormActionPlugin.ts\n * @description A custom action plugin that triggers form submission.\n */\n\nimport { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Button from \"sap/m/Button\";\nimport Control from \"sap/ui/core/Control\";\nimport Core from \"sap/ui/core/Core\";\n\n/**\n * Renders a Button that requests the host container to execute its submit flow.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.actions\n * @public\n */\nexport class SubmitFormActionPlugin extends BasePlugin {\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\"): Control {\n this.metadata = fieldMetadata;\n \n if (!this.isEditable) {\n sap.ui.requireSync(\"sap/m/Text\");\n const TextControl = sap.ui.require(\"sap/m/Text\");\n this.control = new TextControl({ visible: false });\n return this.control as Control;\n }\n \n this.control = new Button({\n text: fieldMetadata.ui?.label || \"Submit\",\n type: \"Emphasized\",\n icon: \"sap-icon://save\",\n press: () => {\n // Fire an event that the GeneratorHost or LayoutManager listens to\n Core.getEventBus().publish(\"MetaUI\", \"TriggerSubmit\", {});\n }\n });\n\n return this.control as Control;\n }\n\n protected getValue(): unknown {\n return null;\n }\n\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as Button).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,gLAAA,MAKSA,EAAUC,EAAA,cAYZ,MAAMC,UAA+BF,EACjCG,OAAOC,EAAkCC,EAAqBC,EAAoB,QACrFC,KAAKC,SAAWJ,EAEhB,IAAKG,KAAKE,WAAY,CAClBC,IAAIC,GAAGC,YAAY,cACnB,MAAMC,EAAcH,IAAIC,GAAGG,QAAQ,cACnCP,KAAKQ,QAAU,IAAIF,EAAY,CAAEG,QAAS,QAC1C,OAAOT,KAAKQ,OAChB,CAEAR,KAAKQ,QAAU,IAAIE,EAAO,CACtBC,KAAMd,EAAcO,IAAIQ,OAAS,SACjCC,KAAM,aACNC,KAAM,kBACNC,MAAOA,KAEHC,EAAKC,cAAcC,QAAQ,SAAU,gBAAiB,CAAC,MAI/D,OAAOlB,KAAKQ,OAChB,CAEUW,WACN,OAAO,IACX,CAEUC,aACN,GAAIpB,KAAKQ,SAAWR,KAAKC,SAAU,CAC/B,IAAKD,KAAKE,WAAY,OACrBF,KAAKQ,QAAmBa,YAAYrB,KAAKC,SAASG,IAAIkB,SAC3D,CACJ,EACH,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAA5B,yBAAA,OAAA4B,CAAA","ignoreList":[],"sourceRoot":"plugins/actions"}},{"offset":{"line":31,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","URLHelper","library","UrlNavigationActionPlugin","render","fieldMetadata","bindingPath","modelName","this","metadata","control","Button","text","ui","label","icon","press","targetUrl","args","redirect","getValue","applyState","setEnabled","readOnly","__exports","__esModule"],"sources":["UrlNavigationActionPlugin.ts"],"sourcesContent":["/**\n * @file UrlNavigationActionPlugin.ts\n * @description A custom action plugin that navigates to a URL.\n */\n\nimport { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Button from \"sap/m/Button\";\nimport Control from \"sap/ui/core/Control\";\nimport * as library from \"sap/m/library\";\nconst URLHelper = library.URLHelper;\n\n/**\n * Renders a Button that triggers a redirect to an external URL (defined in args).\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.actions\n * @public\n */\nexport class UrlNavigationActionPlugin extends BasePlugin {\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\"): Control {\n this.metadata = fieldMetadata;\n\n this.control = new Button({\n text: fieldMetadata.ui?.label || \"Open Link\",\n icon: \"sap-icon://action\",\n press: () => {\n // In a real scenario, the URL might come from the payload or from schema args\n const targetUrl = fieldMetadata.ui?.args || \"https://sap.com\";\n URLHelper.redirect(targetUrl as string, true); // true = open in new window\n }\n });\n\n return this.control as Control;\n }\n\n protected getValue(): unknown {\n return null;\n }\n\n protected applyState(): void {\n if (this.control && this.metadata) {\n (this.control as Button).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,gLAAA,MAKSA,EAAUC,EAAA,cAKnB,MAAMC,EAAYC,EAAQD,UAQnB,MAAME,UAAkCJ,EACpCK,OAAOC,EAAkCC,EAAqBC,EAAoB,QACrFC,KAAKC,SAAWJ,EAEhBG,KAAKE,QAAU,IAAIC,EAAO,CACtBC,KAAMP,EAAcQ,IAAIC,OAAS,YACjCC,KAAM,oBACNC,MAAOA,KAEH,MAAMC,EAAYZ,EAAcQ,IAAIK,MAAQ,kBAC5CjB,EAAUkB,SAASF,EAAqB,SAIhD,OAAOT,KAAKE,OAChB,CAEUU,WACN,OAAO,IACX,CAEUC,aACN,GAAIb,KAAKE,SAAWF,KAAKC,SAAU,CAC9BD,KAAKE,QAAmBY,YAAYd,KAAKC,SAASI,IAAIU,SAC3D,CACJ,EACH,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAArB,4BAAA,OAAAqB,CAAA","ignoreList":[],"sourceRoot":"plugins/actions"}},{"offset":{"line":32,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","ArrayPlugin","render","field","bindingPath","modelName","engineScopeId","onChange","this","metadata","propKey","startsWith","substring","subSchema","type","title","ui","label","items","properties","uiLayout","control","Button","id","generateStableId","text","isEditable","icon","press","oEvent","btn","getSource","parentModel","getModel","bindingContext","getBindingContext","updatePath","ctxPath","getPath","endsWith","nestedData","JSON","parse","stringify","getProperty","sap","require","DynamicHost","host","schemaDefinition","data","editable","attachSubmit","e","payload","getParameter","setProperty","buttonText","dialogButtonText","openInDialog","getValue","applyState","__exports","__esModule"],"sources":["ArrayPlugin.ts"],"sourcesContent":["/**\n * @file ArrayPlugin.ts\n * @description Renders a button that drills down into a nested table (array) via a recursive Dialog using v2 schema.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport Button from \"sap/m/Button\";\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\n\nexport class ArrayPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.Button` to open a nested array form dialog.\n * \n * @param field The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured Button control.\n */\n public render(field: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = field;\n const propKey = bindingPath.startsWith(\"/\") ? bindingPath.substring(1) : bindingPath;\n \n const subSchema: ISchema = {\n type: \"array\",\n title: field.ui?.label || propKey,\n items: field.items || {\n type: \"object\",\n properties: {} // inference will handle it if empty\n }\n };\n\n if (field.uiLayout) {\n subSchema.uiLayout = field.uiLayout;\n }\n\n this.control = new Button({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: !this.isEditable ? \"View Records\" : \"Edit Records\",\n icon: !this.isEditable ? \"sap-icon://display\" : \"sap-icon://list\",\n press: (oEvent: sap.ui.base.Event) => {\n const btn = oEvent.getSource() as Button;\n const parentModel = btn.getModel(modelName) as JSONModel;\n if (!parentModel) return;\n \n const bindingContext = btn.getBindingContext(modelName);\n let updatePath = bindingPath;\n if (bindingContext && !bindingPath.startsWith(\"/\")) {\n const ctxPath = bindingContext.getPath();\n updatePath = ctxPath.endsWith(\"/\") ? ctxPath + bindingPath : (ctxPath === \"/\" ? \"/\" + bindingPath : ctxPath + \"/\" + bindingPath);\n }\n \n // Deep clone to prevent live-mutations on the parent model before 'Submit' is clicked\n const nestedData = JSON.parse(JSON.stringify(parentModel.getProperty(updatePath) || []));\n\n sap.ui.require([\"nz/co/siliconst/ui5/metaui/controls/DynamicHost\"], (DynamicHost: typeof import(\"../../controls/DynamicHost\").default) => {\n const host = new DynamicHost({\n schemaDefinition: subSchema,\n data: nestedData,\n editable: this.isEditable // Pass the display mode down to the child Engine!\n });\n\n // Only attach submit event if we are not in display mode\n if (!!this.isEditable) {\n host.attachSubmit((e: sap.ui.base.Event) => {\n const payload = e.getParameter(\"payload\");\n parentModel.setProperty(updatePath, payload);\n\n // CRITICAL: Notify the parent Engine that this field mutated\n // so it can trigger LiveUpdate syncs and validate!\n if (this.onChange) {\n this.onChange(true, propKey);\n }\n });\n }\n\n const buttonText = field.ui?.dialogButtonText || (!this.isEditable ? \"Close\" : \"OK\");\n host.openInDialog(`Nested Records: ${field.ui?.label || propKey}`, buttonText);\n });\n }\n });\n \n return this.control as Control;\n }\n\n /**\n * Read-only component for the engine, returns null.\n */\n protected getValue(): unknown {\n return null;\n }\n\n /**\n * Read-only component, no dynamic state handling needed for the button itself.\n */\n protected applyState(): void {\n // dynamic state changes\n }\n}\n"],"mappings":"AAAA,uIAAA,MAKSA,EAAUC,EAAA,cAMZ,MAAMC,UAAoBF,EAWtBG,OAAOC,EAA2BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAC/GC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChB,MAAMO,EAAUN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,MAAMS,EAAqB,CACvBC,KAAM,QACNC,MAAOZ,EAAMa,IAAIC,OAASP,EAC1BQ,MAAOf,EAAMe,OAAS,CAClBJ,KAAM,SACNK,WAAY,CAAC,IAIrB,GAAIhB,EAAMiB,SAAU,CAChBP,EAAUO,SAAWjB,EAAMiB,QAC/B,CAEAZ,KAAKa,QAAU,IAAIC,EAAO,CACtBC,GAAIf,KAAKgB,iBAAiBlB,EAAeF,GACzCqB,MAAOjB,KAAKkB,WAAa,eAAiB,eAC1CC,MAAOnB,KAAKkB,WAAa,qBAAuB,kBAChDE,MAAQC,IACJ,MAAMC,EAAMD,EAAOE,YACnB,MAAMC,EAAcF,EAAIG,SAAS5B,GACjC,IAAK2B,EAAa,OAElB,MAAME,EAAiBJ,EAAIK,kBAAkB9B,GAC7C,IAAI+B,EAAahC,EACjB,GAAI8B,IAAmB9B,EAAYO,WAAW,KAAM,CAChD,MAAM0B,EAAUH,EAAeI,UAC/BF,EAAaC,EAAQE,SAAS,KAAOF,EAAUjC,EAAeiC,IAAY,IAAM,IAAMjC,EAAciC,EAAU,IAAMjC,CACxH,CAGA,MAAMoC,EAAaC,KAAKC,MAAMD,KAAKE,UAAUX,EAAYY,YAAYR,IAAe,KAEpFS,IAAI7B,GAAG8B,QAAQ,CAAC,mDAAqDC,IACjE,MAAMC,EAAO,IAAID,EAAY,CACzBE,iBAAkBpC,EAClBqC,KAAMV,EACNW,SAAU3C,KAAKkB,aAInB,KAAMlB,KAAKkB,WAAY,CACnBsB,EAAKI,aAAcC,IACf,MAAMC,EAAUD,EAAEE,aAAa,WAC/BvB,EAAYwB,YAAYpB,EAAYkB,GAIpC,GAAI9C,KAAKD,SAAU,CACfC,KAAKD,SAAS,KAAMG,EACxB,GAER,CAEA,MAAM+C,EAAatD,EAAMa,IAAI0C,oBAAsBlD,KAAKkB,WAAa,QAAU,MAC/EsB,EAAKW,aAAa,mBAAmBxD,EAAMa,IAAIC,OAASP,IAAW+C,QAK/E,OAAOjD,KAAKa,OAChB,CAKUuC,WACN,OAAO,IACX,CAKUC,aACN,EAEP,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAA7D,cAAA,OAAA6D,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":33,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","BarcodeScannerPlugin","render","metadata","bindingPath","modelName","engineScopeId","onChange","this","fieldKey","replace","isEditable","control","TextControl","id","generateStableId","text","applyCommonDirectives","inputControl","Input","value","editable","ui","readOnly","width","change","result","validateAndApplyVisualState","isValid","scannerBtn","BarcodeScannerButton","scanSuccess","oEvent","getParameter","setValue","HBox","items","addStyleClass","getValue","applyState","setEditable","__exports","__esModule"],"sources":["BarcodeScannerPlugin.ts"],"sourcesContent":["import { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport HBox from \"sap/m/HBox\";\nimport Input from \"sap/m/Input\";\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\nimport BarcodeScannerButton from \"sap/ndc/BarcodeScannerButton\";\nimport TextControl from \"sap/m/Text\";\n\nexport class BarcodeScannerPlugin extends BasePlugin {\n private inputControl!: Input;\n\n /**\n * Renders a `BarcodeScannerButton` alongside an `Input`.\n * \n * @param metadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured HBox control.\n */\n public render(metadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = metadata;\n this.fieldKey = bindingPath.replace('/', '');\n this.modelName = modelName;\n\n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`\n });\n this.applyCommonDirectives(this.control, metadata, modelName);\n return this.control as Control;\n }\n\n this.inputControl = new Input({\n id: this.generateStableId(engineScopeId, bindingPath + \"-input\"),\n value: `{${modelName}>${bindingPath}}`,\n editable: !metadata.ui?.readOnly,\n width: \"100%\",\n change: () => {\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n \n const scannerBtn = new BarcodeScannerButton({\n id: this.generateStableId(engineScopeId, bindingPath + \"-btn\"),\n scanSuccess: (oEvent: sap.ui.base.Event) => {\n const text = oEvent.getParameter(\"text\") as string;\n if (text) {\n this.inputControl.setValue(text);\n // UI5's two-way data binding on the input will sync the model automatically\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n }\n });\n\n this.control = new HBox({\n id: this.generateStableId(engineScopeId, bindingPath),\n items: [this.inputControl, scannerBtn],\n width: \"100%\"\n }).addStyleClass(\"sapUiSmallMarginBottom\");\n\n this.applyCommonDirectives(this.control, metadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current scanned text.\n * @returns {unknown} The barcode string.\n */\n protected getValue(): unknown {\n return this.inputControl ? this.inputControl.getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.inputControl && this.metadata) {\n if (!this.isEditable) return;\n this.inputControl.setEditable(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,8NAASA,EAAUC,EAAA,cASZ,MAAMC,UAA6BF,EAa/BG,OAAOC,EAA8BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAClHC,KAAKD,SAAWA,EAChBC,KAAKL,SAAWA,EAChBK,KAAKC,SAAWL,EAAYM,QAAQ,IAAK,IACzCF,KAAKH,UAAYA,EAEjB,IAAKG,KAAKG,WAAY,CAElBH,KAAKI,QAAU,IAAIC,EAAY,CAC3BC,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCY,KAAM,IAAIX,KAAaD,OAE3BI,KAAKS,sBAAsBT,KAAKI,QAAST,EAAUE,GACnD,OAAOG,KAAKI,OAChB,CAEAJ,KAAKU,aAAe,IAAIC,EAAM,CAC1BL,GAAIN,KAAKO,iBAAiBT,EAAeF,EAAc,UACvDgB,MAAO,IAAIf,KAAaD,KACxBiB,UAAWlB,EAASmB,IAAIC,SACxBC,MAAO,OACPC,OAAQA,KACJ,MAAMC,EAASlB,KAAKmB,8BACpB,GAAInB,KAAKD,SAAU,CACfC,KAAKD,SAASmB,EAAOE,QAASpB,KAAKC,SACvC,KAIR,MAAMoB,EAAa,IAAIC,EAAqB,CACxChB,GAAIN,KAAKO,iBAAiBT,EAAeF,EAAc,QACvD2B,YAAcC,IACV,MAAMhB,EAAOgB,EAAOC,aAAa,QACjC,GAAIjB,EAAM,CACNR,KAAKU,aAAagB,SAASlB,GAE3B,MAAMU,EAASlB,KAAKmB,8BACpB,GAAInB,KAAKD,SAAU,CACfC,KAAKD,SAASmB,EAAOE,QAASpB,KAAKC,SACvC,CACJ,KAIRD,KAAKI,QAAU,IAAIuB,EAAK,CACpBrB,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCgC,MAAO,CAAC5B,KAAKU,aAAcW,GAC3BL,MAAO,SACRa,cAAc,0BAEjB7B,KAAKS,sBAAsBT,KAAKI,QAAST,EAAUE,GAEnD,OAAOG,KAAKI,OAChB,CAMU0B,WACN,OAAO9B,KAAKU,aAAeV,KAAKU,aAAaoB,WAAa,IAC9D,CAKUC,aACN,GAAI/B,KAAKU,cAAgBV,KAAKL,SAAU,CACpC,IAAKK,KAAKG,WAAY,OACtBH,KAAKU,aAAasB,aAAahC,KAAKL,SAASmB,IAAIC,SACrD,CACJ,EACH,IAAAkB,EAAA,CAAAC,WAAA,MAAAD,EAAAxC,uBAAA,OAAAwC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":34,"column":0},"map":{"version":3,"names":["GlobalPipeline","____core_PipelineManager","Logger","____utils_Logger","BasePlugin","control","metadata","fieldKey","modelName","isEditable","useMessageManager","setEditable","editable","this","setUseMessageManager","generateStableId","engineScopeId","bindingPath","undefined","safePath","replace","validate","isValid","getVisible","validatorsToRun","argsMap","maxLength","required","push","minLength","pattern","minimum","maximum","min","max","format","ui","validators","v","name","args","length","errorMessage","val","getValue","result","executeValidation","setVisualValidationState","setValueState","coreLibrary","ValueState","None","Error","setValueStateText","error","validateAndApplyVisualState","onStateChange","newMetadata","applyState","applyCommonDirectives","readOnly","visibleOn","ExpressionBuilder","sap","require","expr","build","bindProperty","parts","path","formatter","enabledOn","setEnabled","destroy","__exports","__esModule"],"sources":["BasePlugin.ts"],"sourcesContent":["/**\n * @file BasePlugin.ts\n * @description Abstract foundation for all MetaUI plugins, enforcing lifecycle hooks for v2 Schema.\n */\n\nimport { IPlugin } from \"../../interfaces/IPlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport { GlobalPipeline } from \"../../core/PipelineManager\";\nimport coreLibrary from \"sap/ui/core/library\";\nimport { Logger } from \"../../utils/Logger\";\n\n/**\n * Abstract class representing a standard MetaUI Plugin.\n * Enforces the required rendering, state extraction, and validation contracts.\n * \n * @abstract\n * @public\n */\nexport abstract class BasePlugin implements IPlugin {\n /** The instantiated UI5 control for this plugin. */\n protected control: Control | null = null;\n\n /** The metadata schema defining the field rules. */\n protected metadata: IPropertyMetadata | null = null;\n\n /** The internal JSON path of the field relative to its parent payload. */\n protected fieldKey: string = \"\";\n\n /** The UI5 JSONModel name used for absolute binding paths. */\n protected modelName: string = \"meta\";\n\n /** Indicates if the engine is enforcing an editable mode. */\n protected isEditable: boolean = true;\n\n /** Indicates if the plugin should delegate visual validation to the MessageManager. */\n protected useMessageManager: boolean = false;\n\n /** Internal callback provided by GeneratorHost to signal validation/data changes upwards */\n protected onChange?: (isValid: boolean, fieldKey?: string, errorMessage?: string, controlId?: string) => void;\n\n /**\n * Injects the global editable mode context into the plugin before rendering.\n * @param editable True if the plugin should render in editable mode.\n */\n public setEditable(editable: boolean): void {\n this.isEditable = editable;\n }\n\n /**\n * Injects the global MessageManager context into the plugin.\n * @param useMessageManager True if the MessageManager is handling validation visual states.\n */\n public setUseMessageManager(useMessageManager: boolean): void {\n this.useMessageManager = useMessageManager;\n }\n\n /**\n * Instantiates the raw UI5 control and binds it to the model.\n * \n * @param fieldMetadata The JSON Schema for the field.\n * @param bindingPath The JSON path to bind to.\n * @param modelName The UI5 model name.\n * @param engineScopeId The deterministic scope ID provided by the Engine to prevent cloning collisions.\n * @param onChange The callback fired natively when a field value blur/change occurs.\n * @returns {Control} The generated UI5 control.\n */\n public abstract render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName?: string, engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control;\n\n /**\n * Generates a deterministic, globally unique ID for this control.\n * Prefixes the sanitized binding path with the Engine's scoped ID.\n */\n protected generateStableId(engineScopeId: string | undefined, bindingPath: string): string | undefined {\n if (!engineScopeId) return undefined;\n // Strip leading slash and replace internal slashes with hyphens\n const safePath = bindingPath.replace(/^\\//, '').replace(/\\//g, '-');\n return `${engineScopeId}--${safePath}`;\n }\n\n /**\n * Extracts the current raw value from the underlying UI5 control.\n */\n protected abstract getValue(): unknown;\n\n /**\n * Universal pipeline validation.\n */\n public validate(): import(\"../../interfaces/IPlugin\").IPluginValidationResult {\n if (!this.control || !this.metadata) return { isValid: true };\n\n // Skip validation for hidden fields (e.g. hidden by ConditionEngine visibleOn)\n if (typeof (this.control as Control).getVisible === \"function\") {\n if (!(this.control as Control).getVisible()) {\n return { isValid: true };\n }\n }\n\n const validatorsToRun: string[] = [];\n const argsMap: Record<string, unknown> = {\n \"maxLength\": this.metadata.maxLength\n };\n\n if (this.metadata.required) {\n validatorsToRun.push(\"required\");\n }\n if (this.metadata.maxLength) validatorsToRun.push(\"maxLength\");\n if (this.metadata.minLength) {\n validatorsToRun.push(\"minLength\");\n argsMap[\"minLength\"] = this.metadata.minLength;\n }\n if (this.metadata.pattern) {\n validatorsToRun.push(\"pattern\");\n argsMap[\"pattern\"] = this.metadata.pattern;\n }\n if (this.metadata.minimum !== undefined || this.metadata.maximum !== undefined) {\n validatorsToRun.push(\"range\");\n argsMap[\"range\"] = { min: this.metadata.minimum, max: this.metadata.maximum };\n }\n \n const format = this.metadata.ui?.format;\n if (format === \"email\" || format === \"url\" || format === \"iban\") {\n validatorsToRun.push(format);\n }\n\n if (this.metadata.ui?.validators) {\n for (const v of this.metadata.ui.validators) {\n if (typeof v === \"string\") {\n validatorsToRun.push(v);\n } else if (v && v.name) {\n validatorsToRun.push(v.name);\n if (v.args !== undefined) {\n argsMap[v.name] = v.args;\n }\n }\n }\n }\n\n if (validatorsToRun.length === 0) {\n return { isValid: true, errorMessage: undefined, fieldKey: this.fieldKey };\n }\n\n const val = this.getValue();\n const result = GlobalPipeline.executeValidation(val, validatorsToRun, argsMap);\n return { isValid: result.isValid, errorMessage: result.errorMessage, fieldKey: this.fieldKey };\n }\n\n /**\n * Natively manipulates the UI5 control's valueState if the control supports it.\n * Uses reflection to safely apply styles without crashing on structural controls.\n */\n public setVisualValidationState(isValid: boolean, errorMessage?: string): void {\n if (!this.control) return;\n\n \n // Use reflection to check if the control supports ValueState (e.g. sap.m.Input does, sap.m.Text does not)\n if (typeof (this.control as any).setValueState === \"function\") {\n (this.control as any).setValueState(isValid ? coreLibrary.ValueState.None : coreLibrary.ValueState.Error);\n \n if (typeof (this.control as any).setValueStateText === \"function\") {\n (this.control as any).setValueStateText(isValid ? \"\" : (errorMessage || \"\"));\n }\n } else {\n Logger.error(\"[MetaUI]\", `Plugin ${this.fieldKey} has no setValueState function!`, \"BasePlugin\");\n }\n }\n\n /**\n * Wraps standard validation and immediately applies the visual state.\n * Ideal for 'change' events to instantly turn fields red on blur.\n */\n protected validateAndApplyVisualState(): import(\"../../interfaces/IPlugin\").IPluginValidationResult {\n const result = this.validate();\n this.setVisualValidationState(result.isValid, result.errorMessage);\n return result;\n }\n\n /**\n * Executes when the condition engine pushes new schema metadata to this field (e.g. readOnly changing).\n * @param newMetadata The mutated schema metadata.\n */\n public onStateChange(newMetadata: IPropertyMetadata): void {\n this.metadata = newMetadata;\n this.applyState();\n }\n\n /**\n * Abstract hook for the plugin to apply state changes to its specific UI5 control (e.g. placeholders, labels).\n */\n protected abstract applyState(): void;\n\n /**\n * Helper to apply common UI directives (like readOnly, visibleOn) directly to any control.\n */\n protected applyCommonDirectives(control: Control, metadata: IPropertyMetadata, modelName: string = \"meta\"): void {\n if (metadata.ui?.readOnly !== undefined && typeof control.setEditable === \"function\") {\n control.setEditable(!metadata.ui.readOnly);\n }\n\n if (metadata.ui?.visibleOn) {\n const ExpressionBuilder = sap.ui.require(\"nz/co/siliconst/ui5/metaui/utils/ExpressionBuilder\")?.ExpressionBuilder;\n let expr = \"\";\n if (ExpressionBuilder) {\n expr = ExpressionBuilder.build(metadata.ui.visibleOn, this.fieldKey, modelName);\n } else {\n expr = `{= ${metadata.ui.visibleOn.replace(/\\$root\\./g, `${modelName}>/`).replace(/\\./g, '/')} }`;\n }\n control.bindProperty(\"visible\", { parts: [{ path: \"meta>/\" }], formatter: () => false });\n control.bindProperty(\"visible\", expr);\n }\n\n if (metadata.ui?.enabledOn && typeof control.setEnabled === \"function\") {\n const ExpressionBuilder = sap.ui.require(\"nz/co/siliconst/ui5/metaui/utils/ExpressionBuilder\")?.ExpressionBuilder;\n let expr = \"\";\n if (ExpressionBuilder) {\n expr = ExpressionBuilder.build(metadata.ui.enabledOn, this.fieldKey, modelName);\n } else {\n expr = `{= ${metadata.ui.enabledOn.replace(/\\$root\\./g, `${modelName}>/`).replace(/\\./g, '/')} }`;\n }\n control.bindProperty(\"enabled\", expr);\n }\n }\n\n\n\n /**\n * Natively destroys the instantiated UI5 control to prevent memory leaks.\n * Can be overridden by subclasses if they manage secondary controls or custom models.\n */\n public destroy(): void {\n if (this.control && typeof this.control.destroy === \"function\") {\n this.control.destroy();\n this.control = null;\n }\n }\n}\n"],"mappings":"AAAA,kLAAA,MAQSA,EAAcC,EAAA,wBAEdC,EAAMC,EAAA,UASR,MAAeC,EAERC,QAA0B,KAG1BC,SAAqC,KAGrCC,SAAmB,GAGnBC,UAAoB,OAGpBC,WAAsB,KAGtBC,kBAA6B,MAShCC,YAAYC,GACfC,KAAKJ,WAAaG,CACtB,CAMOE,qBAAqBJ,GACxBG,KAAKH,kBAAoBA,CAC7B,CAkBUK,iBAAiBC,EAAmCC,GAC1D,IAAKD,EAAe,OAAOE,UAE3B,MAAMC,EAAWF,EAAYG,QAAQ,MAAO,IAAIA,QAAQ,MAAO,KAC/D,MAAO,GAAGJ,MAAkBG,GAChC,CAUOE,WACH,IAAKR,KAAKR,UAAYQ,KAAKP,SAAU,MAAO,CAAEgB,QAAS,MAGvD,UAAYT,KAAKR,QAAoBkB,aAAe,WAAY,CAC5D,IAAMV,KAAKR,QAAoBkB,aAAc,CACzC,MAAO,CAAED,QAAS,KACtB,CACJ,CAEA,MAAME,EAA4B,GAClC,MAAMC,EAAmC,CACrCC,UAAab,KAAKP,SAASoB,WAG/B,GAAIb,KAAKP,SAASqB,SAAU,CACxBH,EAAgBI,KAAK,WACzB,CACA,GAAIf,KAAKP,SAASoB,UAAWF,EAAgBI,KAAK,aAClD,GAAIf,KAAKP,SAASuB,UAAW,CACzBL,EAAgBI,KAAK,aACrBH,EAAQ,aAAeZ,KAAKP,SAASuB,SACzC,CACA,GAAIhB,KAAKP,SAASwB,QAAS,CACvBN,EAAgBI,KAAK,WACrBH,EAAQ,WAAaZ,KAAKP,SAASwB,OACvC,CACA,GAAIjB,KAAKP,SAASyB,UAAYb,WAAaL,KAAKP,SAAS0B,UAAYd,UAAW,CAC5EM,EAAgBI,KAAK,SACrBH,EAAQ,SAAW,CAAEQ,IAAKpB,KAAKP,SAASyB,QAASG,IAAKrB,KAAKP,SAAS0B,QACxE,CAEA,MAAMG,EAAStB,KAAKP,SAAS8B,IAAID,OACjC,GAAIA,IAAW,SAAWA,IAAW,OAASA,IAAW,OAAQ,CAC7DX,EAAgBI,KAAKO,EACzB,CAEA,GAAItB,KAAKP,SAAS8B,IAAIC,WAAY,CAC9B,IAAK,MAAMC,KAAKzB,KAAKP,SAAS8B,GAAGC,WAAY,CACzC,UAAWC,IAAM,SAAU,CACvBd,EAAgBI,KAAKU,EACzB,MAAO,GAAIA,GAAKA,EAAEC,KAAM,CACpBf,EAAgBI,KAAKU,EAAEC,MACvB,GAAID,EAAEE,OAAStB,UAAW,CACtBO,EAAQa,EAAEC,MAAQD,EAAEE,IACxB,CACJ,CACJ,CACJ,CAEA,GAAIhB,EAAgBiB,SAAW,EAAG,CAC9B,MAAO,CAAEnB,QAAS,KAAMoB,aAAcxB,UAAWX,SAAUM,KAAKN,SACpE,CAEA,MAAMoC,EAAM9B,KAAK+B,WACjB,MAAMC,EAAS7C,EAAe8C,kBAAkBH,EAAKnB,EAAiBC,GACtE,MAAO,CAAEH,QAASuB,EAAOvB,QAASoB,aAAcG,EAAOH,aAAcnC,SAAUM,KAAKN,SACxF,CAMOwC,yBAAyBzB,EAAkBoB,GAC9C,IAAK7B,KAAKR,QAAS,OAInB,UAAYQ,KAAKR,QAAgB2C,gBAAkB,WAAY,CAC1DnC,KAAKR,QAAgB2C,cAAc1B,EAAU2B,EAAYC,WAAWC,KAAOF,EAAYC,WAAWE,OAEnG,UAAYvC,KAAKR,QAAgBgD,oBAAsB,WAAY,CAC9DxC,KAAKR,QAAgBgD,kBAAkB/B,EAAU,GAAMoB,GAAgB,GAC5E,CACJ,KAAO,CACHxC,EAAOoD,MAAM,WAAY,UAAUzC,KAAKN,0CAA2C,aACvF,CACJ,CAMUgD,8BACN,MAAMV,EAAShC,KAAKQ,WACpBR,KAAKkC,yBAAyBF,EAAOvB,QAASuB,EAAOH,cACrD,OAAOG,CACX,CAMOW,cAAcC,GACjB5C,KAAKP,SAAWmD,EAChB5C,KAAK6C,YACT,CAUUC,sBAAsBtD,EAAkBC,EAA6BE,EAAoB,QAC/F,GAAIF,EAAS8B,IAAIwB,WAAa1C,kBAAoBb,EAAQM,cAAgB,WAAY,CAClFN,EAAQM,aAAaL,EAAS8B,GAAGwB,SACrC,CAEA,GAAItD,EAAS8B,IAAIyB,UAAW,CACxB,MAAMC,EAAoBC,IAAI3B,GAAG4B,QAAQ,uDAAuDF,kBAChG,IAAIG,EAAO,GACX,GAAIH,EAAmB,CACnBG,EAAOH,EAAkBI,MAAM5D,EAAS8B,GAAGyB,UAAWhD,KAAKN,SAAUC,EACzE,KAAO,CACHyD,EAAO,MAAM3D,EAAS8B,GAAGyB,UAAUzC,QAAQ,YAAa,GAAGZ,OAAeY,QAAQ,MAAO,QAC7F,CACAf,EAAQ8D,aAAa,UAAW,CAAEC,MAAO,CAAC,CAAEC,KAAM,WAAaC,UAAWA,IAAM,QAChFjE,EAAQ8D,aAAa,UAAWF,EACpC,CAEA,GAAI3D,EAAS8B,IAAImC,kBAAoBlE,EAAQmE,aAAe,WAAY,CACpE,MAAMV,EAAoBC,IAAI3B,GAAG4B,QAAQ,uDAAuDF,kBAChG,IAAIG,EAAO,GACX,GAAIH,EAAmB,CACnBG,EAAOH,EAAkBI,MAAM5D,EAAS8B,GAAGmC,UAAW1D,KAAKN,SAAUC,EACzE,KAAO,CACHyD,EAAO,MAAM3D,EAAS8B,GAAGmC,UAAUnD,QAAQ,YAAa,GAAGZ,OAAeY,QAAQ,MAAO,QAC7F,CACAf,EAAQ8D,aAAa,UAAWF,EACpC,CACJ,CAQOQ,UACH,GAAI5D,KAAKR,gBAAkBQ,KAAKR,QAAQoE,UAAY,WAAY,CAC5D5D,KAAKR,QAAQoE,UACb5D,KAAKR,QAAU,IACnB,CACJ,EACH,IAAAqE,EAAA,CAAAC,WAAA,MAAAD,EAAAtE,aAAA,OAAAsE,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":35,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","BooleanPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","startsWith","substring","isEditable","control","TextControl","id","generateStableId","text","path","formatter","val","applyCommonDirectives","CheckBox","selected","enabled","ui","readOnly","select","oEvent","getParameter","result","validateAndApplyVisualState","isValid","getValue","getSelected","applyState","setEnabled","__exports","__esModule"],"sources":["BooleanPlugin.ts"],"sourcesContent":["/**\n * @file BooleanPlugin.ts\n * @description Renders a sap.m.Switch for boolean states.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport CheckBox from \"sap/m/CheckBox\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering logic for toggleable booleans using `sap.m.CheckBox`.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class BooleanPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.CheckBox` component for boolean evaluation.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @returns {Control} The configured CheckBox control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.startsWith('/') ? bindingPath.substring(1) : bindingPath;\n \n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n formatter: (val: boolean) => val ? \"Yes\" : \"No\"\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new CheckBox({\n id: this.generateStableId(engineScopeId, bindingPath),\n selected: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n select: (oEvent: sap.ui.base.Event) => {\n const val = oEvent.getParameter(\"selected\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current boolean state.\n * @returns {boolean} The selected state.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as CheckBox).getSelected() : false;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as CheckBox).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,0JAAA,MAKSA,EAAUC,EAAA,cAYZ,MAAMC,UAAsBF,EASxBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,IAAKI,KAAKK,WAAY,CAElBL,KAAKM,QAAU,IAAIC,EAAY,CAC3BC,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCc,KAAM,CACFC,KAAM,GAAGd,KAAaD,IACtBgB,UAAYC,GAAiBA,EAAM,MAAQ,QAGnDb,KAAKc,sBAAsBd,KAAKM,QAASX,EAAeE,GACxD,OAAOG,KAAKM,OAChB,CAEAN,KAAKM,QAAU,IAAIS,EAAS,CACxBP,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCoB,SAAU,IAAInB,KAAaD,KAC3BqB,SAAUtB,EAAcuB,IAAIC,SAC5BC,OAASC,IACL,MAAMR,EAAMQ,EAAOC,aAAa,YAChC,MAAMC,EAASvB,KAAKwB,8BACpB,GAAIxB,KAAKD,SAAU,CACfC,KAAKD,SAASwB,EAAOE,QAASzB,KAAKE,SACvC,KAIRF,KAAKc,sBAAsBd,KAAKM,QAASX,EAAeE,GAExD,OAAOG,KAAKM,OAChB,CAMUoB,WACN,OAAO1B,KAAKM,QAAWN,KAAKM,QAAqBqB,cAAgB,KACrE,CAKUC,aACN,GAAI5B,KAAKM,SAAWN,KAAKC,SAAU,CAC/B,IAAKD,KAAKK,WAAY,OACrBL,KAAKM,QAAqBuB,YAAY7B,KAAKC,SAASiB,IAAIC,SAC7D,CACJ,EACH,IAAAW,EAAA,CAAAC,WAAA,MAAAD,EAAArC,gBAAA,OAAAqC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":36,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","CameraControl","_interopRequireDefault","__CameraControl","CameraPlugin","render","metadata","bindingPath","modelName","engineScopeId","onChange","this","fieldKey","replace","isEditable","control","ImageControl","id","generateStableId","src","width","alt","ui","label","applyCommonDirectives","value","schemaMetadata","readOnly","attachCapture","result","validateAndApplyVisualState","isValid","getValue","applyState","setProperty","__exports","__esModule"],"sources":["CameraPlugin.ts"],"sourcesContent":["import { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport CameraControl from \"../../controls/CameraControl\";\nimport ImageControl from \"sap/m/Image\";\n\nexport class CameraPlugin extends BasePlugin {\n /**\n * Renders a `CameraControl` component.\n * \n * @param metadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured CameraControl.\n */\n public render(metadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = metadata;\n this.fieldKey = bindingPath.replace('/', '');\n this.modelName = modelName;\n\n if (!this.isEditable) {\n \n this.control = new ImageControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n src: `{${modelName}>${bindingPath}}`,\n width: \"400px\",\n alt: metadata.ui?.label || \"Image\"\n });\n this.applyCommonDirectives(this.control, metadata, modelName);\n return this.control as Control;\n }\n\n this.control = new CameraControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n schemaMetadata: metadata,\n readOnly: !!metadata.ui?.readOnly\n });\n\n this.applyCommonDirectives(this.control, metadata, modelName);\n\n // Validation mapping could be hooked into the 'capture' event if needed, but Two-Way binding updates the model naturally.\n (this.control as CameraControl).attachCapture(() => {\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n });\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current base64 image state.\n * @returns {unknown} The image value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as CameraControl).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as sap.ui.core.Control).setProperty(\"readOnly\", !!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,yQAASA,EAAUC,EAAA,oBAGZC,EAAaC,EAAAC,GAGb,MAAMC,UAAqBL,EAWvBM,OAAOC,EAA8BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAClHC,KAAKD,SAAWA,EAChBC,KAAKL,SAAWA,EAChBK,KAAKC,SAAWL,EAAYM,QAAQ,IAAK,IACzCF,KAAKH,UAAYA,EAEjB,IAAKG,KAAKG,WAAY,CAElBH,KAAKI,QAAU,IAAIC,EAAa,CAC5BC,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCY,IAAK,IAAIX,KAAaD,KACtBa,MAAO,QACPC,IAAKf,EAASgB,IAAIC,OAAS,UAE/BZ,KAAKa,sBAAsBb,KAAKI,QAAST,EAAUE,GACnD,OAAOG,KAAKI,OAChB,CAEAJ,KAAKI,QAAU,IAAId,EAAc,CAC7BgB,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCkB,MAAO,IAAIjB,KAAaD,KACxBmB,eAAgBpB,EAChBqB,WAAYrB,EAASgB,IAAIK,WAG7BhB,KAAKa,sBAAsBb,KAAKI,QAAST,EAAUE,GAGlDG,KAAKI,QAA0Ba,cAAc,KAC1C,MAAMC,EAASlB,KAAKmB,8BAChB,GAAInB,KAAKD,SAAU,CACfC,KAAKD,SAASmB,EAAOE,QAASpB,KAAKC,SACvC,IAGR,OAAOD,KAAKI,OAChB,CAMUiB,WACN,OAAOrB,KAAKI,QAAWJ,KAAKI,QAA0BiB,WAAa,IACvE,CAKUC,aACN,GAAItB,KAAKI,SAAWJ,KAAKL,SAAU,CAC/B,IAAKK,KAAKG,WAAY,OACrBH,KAAKI,QAAgCmB,YAAY,aAAcvB,KAAKL,SAASgB,IAAIK,SACtF,CACJ,EACH,IAAAQ,EAAA,CAAAC,WAAA,MAAAD,EAAA/B,eAAA,OAAA+B,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":37,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","CodeEditorPlugin","detectLanguage","value","trimmed","trim","startsWith","JSON","parse","e","test","adjustHeight","this","control","val","getValue","lines","split","length","newHeight","Math","max","setHeight","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","metadata","fieldKey","replace","CodeEditor","id","generateStableId","type","ui","args","editable","isEditable","readOnly","height","width","change","result","validateAndApplyVisualState","isValid","currentVal","detectedType","getType","setType","attachEventOnce","oBinding","getBinding","initLogic","applyState","attachChange","applyCommonDirectives","setEditable","__exports","__esModule"],"sources":["CodeEditorPlugin.ts"],"sourcesContent":["/**\n * @file CodeEditorPlugin.ts\n * @description Renders a sap.ui.codeeditor.CodeEditor for editing source code/JSON.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport CodeEditor from \"sap/ui/codeeditor/CodeEditor\";\n\n/**\n * Handles rendering logic for code editing.\n * Requires the `sap.ui.codeeditor` library to be loaded.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class CodeEditorPlugin extends BasePlugin {\n /**\n * Infers the language type from the content.\n * @param value The raw string.\n * @returns The language string.\n */\n private detectLanguage(value: string): string {\n if (!value || typeof value !== \"string\") return \"javascript\";\n \n const trimmed = value.trim();\n if (trimmed === \"\") return \"javascript\";\n\n // 1. JSON\n if (trimmed.startsWith(\"{\") || trimmed.startsWith(\"[\")) {\n try {\n JSON.parse(trimmed);\n return \"json\";\n } catch (e) {\n // Not valid JSON, continue testing\n }\n }\n\n // 2. XML / HTML\n if (/^\\s*<[\\s\\S]*>\\s*$/.test(trimmed)) {\n return \"xml\";\n }\n\n // 3. Fallback to JavaScript\n return \"javascript\";\n }\n\n /**\n * Dynamically adjusts the height of the editor based on content lines.\n */\n private adjustHeight(): void {\n if (!this.control) return;\n const val = (this.control as CodeEditor).getValue() || \"\";\n const lines = val.split(/\\r\\n|\\r|\\n/).length;\n // 18px per line + 20px padding, minimum 100px\n const newHeight = Math.max(100, (lines * 18) + 20);\n (this.control as CodeEditor).setHeight(newHeight + \"px\");\n }\n\n /**\n * Renders a `sap.ui.codeeditor.CodeEditor` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured CodeEditor control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.replace(\"/\", \"\"); // For EventBus\n \n \n \n this.control = new CodeEditor({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n type: fieldMetadata.ui?.args || \"javascript\", // will be dynamically overridden if args is missing\n editable: !this.isEditable ? false : !fieldMetadata.ui?.readOnly,\n height: \"100px\", // Initial minimum height\n width: \"100%\",\n change: () => {\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n \n // If language isn't explicitly defined, try to guess it dynamically\n if (!fieldMetadata.ui?.args) {\n const currentVal = (this.control as CodeEditor).getValue();\n const detectedType = this.detectLanguage(currentVal);\n if ((this.control as CodeEditor).getType() !== detectedType) {\n (this.control as CodeEditor).setType(detectedType);\n }\n }\n \n this.adjustHeight();\n }\n });\n\n // Clean architecture: Wait for the model context, then attach safely to the binding itself.\n // No timeouts, no DOM hacks, pure UI5 Eventing.\n (this.control as CodeEditor).attachEventOnce(\"modelContextChange\", () => {\n const oBinding = (this.control as CodeEditor).getBinding(\"value\");\n \n const initLogic = () => {\n if (this.control) {\n const currentVal = (this.control as CodeEditor).getValue();\n if (!fieldMetadata.ui?.args) {\n (this.control as CodeEditor).setType(this.detectLanguage(currentVal));\n }\n this.adjustHeight();\n // CRITICAL: Ace Editor sometimes loses its constructor `editable` flag \n // when the model asynchronously injects a new value string. \n // We must forcefully re-apply the correct state after binding.\n this.applyState();\n }\n };\n\n if (oBinding) {\n // Attach for future model changes\n oBinding.attachChange(initLogic);\n }\n \n // Execute immediately in case the model is synchronous (JSONModel)\n initLogic();\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current code string.\n * @returns {unknown} The code value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as CodeEditor).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) {\n (this.control as CodeEditor).setEditable(false);\n } else {\n (this.control as CodeEditor).setEditable(!this.metadata.ui?.readOnly);\n }\n }\n }\n}\n"],"mappings":"AAAA,4JAAA,MAKSA,EAAUC,EAAA,cAYZ,MAAMC,UAAyBF,EAM1BG,eAAeC,GACnB,IAAKA,UAAgBA,IAAU,SAAU,MAAO,aAEhD,MAAMC,EAAUD,EAAME,OACtB,GAAID,IAAY,GAAI,MAAO,aAG3B,GAAIA,EAAQE,WAAW,MAAQF,EAAQE,WAAW,KAAM,CACpD,IACIC,KAAKC,MAAMJ,GACX,MAAO,MACX,CAAE,MAAOK,GACL,CAER,CAGA,GAAI,oBAAoBC,KAAKN,GAAU,CACnC,MAAO,KACX,CAGA,MAAO,YACX,CAKQO,eACJ,IAAKC,KAAKC,QAAS,OACnB,MAAMC,EAAOF,KAAKC,QAAuBE,YAAc,GACvD,MAAMC,EAAQF,EAAIG,MAAM,cAAcC,OAEtC,MAAMC,EAAYC,KAAKC,IAAI,IAAML,EAAQ,GAAM,IAC9CJ,KAAKC,QAAuBS,UAAUH,EAAY,KACvD,CAYOI,OAAOC,EAAkCC,EAAqBC,EAAoB,OAAQC,EAAwBC,GACrHhB,KAAKgB,SAAWA,EAChBhB,KAAKiB,SAAWL,EAChBZ,KAAKkB,SAAWL,EAAYM,QAAQ,IAAK,IAIzCnB,KAAKC,QAAU,IAAImB,EAAW,CAC1BC,GAAIrB,KAAKsB,iBAAiBP,EAAeF,GACzCtB,MAAO,IAAIuB,KAAaD,KACxBU,KAAMX,EAAcY,IAAIC,MAAQ,aAChCC,UAAW1B,KAAK2B,WAAa,OAASf,EAAcY,IAAII,SACxDC,OAAQ,QACRC,MAAO,OACPC,OAAQA,KACJ,MAAMC,EAAShC,KAAKiC,8BACpB,GAAIjC,KAAKgB,SAAU,CACfhB,KAAKgB,SAASgB,EAAOE,QAASlC,KAAKkB,SACvC,CAGA,IAAKN,EAAcY,IAAIC,KAAM,CACzB,MAAMU,EAAcnC,KAAKC,QAAuBE,WAChD,MAAMiC,EAAepC,KAAKV,eAAe6C,GACzC,GAAKnC,KAAKC,QAAuBoC,YAAcD,EAAc,CACxDpC,KAAKC,QAAuBqC,QAAQF,EACzC,CACJ,CAEApC,KAAKD,kBAMZC,KAAKC,QAAuBsC,gBAAgB,qBAAsB,KAC/D,MAAMC,EAAYxC,KAAKC,QAAuBwC,WAAW,SAEzD,MAAMC,EAAYA,KACd,GAAI1C,KAAKC,QAAS,CACd,MAAMkC,EAAcnC,KAAKC,QAAuBE,WAChD,IAAKS,EAAcY,IAAIC,KAAM,CACxBzB,KAAKC,QAAuBqC,QAAQtC,KAAKV,eAAe6C,GAC7D,CACAnC,KAAKD,eAILC,KAAK2C,YACT,GAGJ,GAAIH,EAAU,CAEVA,EAASI,aAAaF,EAC1B,CAGAA,MAGJ1C,KAAK6C,sBAAsB7C,KAAKC,QAASW,EAAeE,GAExD,OAAOd,KAAKC,OAChB,CAMUE,WACN,OAAOH,KAAKC,QAAWD,KAAKC,QAAuBE,WAAa,IACpE,CAKUwC,aACN,GAAI3C,KAAKC,SAAWD,KAAKiB,SAAU,CAC/B,IAAKjB,KAAK2B,WAAY,CACjB3B,KAAKC,QAAuB6C,YAAY,MAC7C,KAAO,CACF9C,KAAKC,QAAuB6C,aAAa9C,KAAKiB,SAASO,IAAII,SAChE,CACJ,CACJ,EACH,IAAAmB,EAAA,CAAAC,WAAA,MAAAD,EAAA1D,mBAAA,OAAA0D,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":38,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","DatePlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","startsWith","substring","isEditable","control","TextControl","id","generateStableId","text","path","type","formatOptions","source","pattern","applyCommonDirectives","DatePicker","value","displayFormat","editable","ui","readOnly","required","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","getValue","applyState","dp","setEditable","setRequired","__exports","__esModule"],"sources":["DatePlugin.ts"],"sourcesContent":["/**\n * @file DatePlugin.ts\n * @description Renders a sap.m.DatePicker natively bound to ISO date strings.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport DatePicker from \"sap/m/DatePicker\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering logic for Date strings.\n */\nexport class DatePlugin extends BasePlugin {\n /**\n * Renders a `sap.m.DatePicker` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured DatePicker control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.startsWith('/') ? bindingPath.substring(1) : bindingPath;\n \n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n type: \"sap.ui.model.type.Date\",\n formatOptions: {\n source: { pattern: \"yyyy-MM-dd\" },\n pattern: \"yyyy-MM-dd\"\n }\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new DatePicker({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: {\n path: `${modelName}>${bindingPath}`,\n type: \"sap.ui.model.type.Date\",\n formatOptions: {\n source: { pattern: \"yyyy-MM-dd\" },\n pattern: \"yyyy-MM-dd\"\n }\n },\n displayFormat: \"long\",\n editable: !fieldMetadata.ui?.readOnly,\n required: fieldMetadata.required,\n change: (oEvent: sap.ui.base.Event) => {\n const val = oEvent.getParameter(\"value\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current date string.\n * @returns {unknown} The date value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as DatePicker).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const dp = this.control as DatePicker;\n dp.setEditable(!this.metadata.ui?.readOnly);\n dp.setRequired(this.metadata.required);\n }\n }\n}\n"],"mappings":"AAAA,yJAAA,MAKSA,EAAUC,EAAA,cASZ,MAAMC,UAAmBF,EAWrBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,IAAKI,KAAKK,WAAY,CAElBL,KAAKM,QAAU,IAAIC,EAAY,CAC3BC,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCc,KAAM,CACFC,KAAM,GAAGd,KAAaD,IACtBgB,KAAM,yBACNC,cAAe,CACXC,OAAQ,CAAEC,QAAS,cACnBA,QAAS,iBAIrBf,KAAKgB,sBAAsBhB,KAAKM,QAASX,EAAeE,GACxD,OAAOG,KAAKM,OAChB,CAEAN,KAAKM,QAAU,IAAIW,EAAW,CAC1BT,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCsB,MAAO,CACHP,KAAM,GAAGd,KAAaD,IACtBgB,KAAM,yBACNC,cAAe,CACXC,OAAQ,CAAEC,QAAS,cACnBA,QAAS,eAGjBI,cAAe,OACfC,UAAWzB,EAAc0B,IAAIC,SAC7BC,SAAU5B,EAAc4B,SACxBC,OAASC,IACL,MAAMC,EAAMD,EAAOE,aAAa,SAChC,MAAMC,EAAS5B,KAAK6B,8BACpB,GAAI7B,KAAKD,SAAU,CACfC,KAAKD,SAAS6B,EAAOE,QAAS9B,KAAKE,SACvC,KAIR,OAAOF,KAAKM,OAChB,CAMUyB,WACN,OAAO/B,KAAKM,QAAWN,KAAKM,QAAuByB,WAAa,IACpE,CAKUC,aACN,GAAIhC,KAAKM,SAAWN,KAAKC,SAAU,CAC/B,IAAKD,KAAKK,WAAY,OACtB,MAAM4B,EAAKjC,KAAKM,QAChB2B,EAAGC,aAAalC,KAAKC,SAASoB,IAAIC,UAClCW,EAAGE,YAAYnC,KAAKC,SAASsB,SACjC,CACJ,EACH,IAAAa,EAAA,CAAAC,WAAA,MAAAD,EAAA3C,aAAA,OAAA2C,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":39,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","DateTimePlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","startsWith","substring","isEditable","control","TextControl","id","generateStableId","text","path","type","formatOptions","source","pattern","applyCommonDirectives","DateTimePicker","value","editable","ui","readOnly","required","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","getValue","applyState","input","setEditable","setRequired","__exports","__esModule"],"sources":["DateTimePlugin.ts"],"sourcesContent":["/**\n * @file DateTimePlugin.ts\n * @description Handles rendering logic for DateTime strings (timestamps).\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport DateTimePicker from \"sap/m/DateTimePicker\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering and logic for timestamps/datetime inputs.\n */\nexport class DateTimePlugin extends BasePlugin {\n /**\n * Renders a `sap.m.DateTimePicker` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured DateTimePicker control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.startsWith('/') ? bindingPath.substring(1) : bindingPath;\n \n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n type: \"sap.ui.model.type.DateTime\",\n formatOptions: {\n source: { pattern: \"yyyy-MM-dd'T'HH:mm:ss'Z'\" },\n pattern: \"yyyy-MM-dd'T'HH:mm:ss'Z'\"\n }\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new DateTimePicker({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: {\n path: `${modelName}>${bindingPath}`,\n type: \"sap.ui.model.type.DateTime\",\n formatOptions: {\n source: { pattern: \"yyyy-MM-dd'T'HH:mm:ss'Z'\" },\n pattern: \"yyyy-MM-dd'T'HH:mm:ss'Z'\"\n }\n },\n editable: !fieldMetadata.ui?.readOnly,\n required: fieldMetadata.required,\n change: (oEvent: sap.ui.base.Event) => {\n const val = oEvent.getParameter(\"value\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current datetime string.\n * @returns {unknown} The datetime value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as DateTimePicker).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const input = this.control as DateTimePicker;\n input.setEditable(!this.metadata.ui?.readOnly);\n input.setRequired(this.metadata.required);\n }\n }\n}\n"],"mappings":"AAAA,iKAAA,MAKSA,EAAUC,EAAA,cASZ,MAAMC,UAAuBF,EAWzBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,IAAKI,KAAKK,WAAY,CAElBL,KAAKM,QAAU,IAAIC,EAAY,CAC3BC,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCc,KAAM,CACFC,KAAM,GAAGd,KAAaD,IACtBgB,KAAM,6BACNC,cAAe,CACXC,OAAQ,CAAEC,QAAS,4BACnBA,QAAS,+BAIrBf,KAAKgB,sBAAsBhB,KAAKM,QAASX,EAAeE,GACxD,OAAOG,KAAKM,OAChB,CAEAN,KAAKM,QAAU,IAAIW,EAAe,CAC9BT,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCsB,MAAO,CACHP,KAAM,GAAGd,KAAaD,IACtBgB,KAAM,6BACNC,cAAe,CACXC,OAAQ,CAAEC,QAAS,4BACnBA,QAAS,6BAGjBI,UAAWxB,EAAcyB,IAAIC,SAC7BC,SAAU3B,EAAc2B,SACxBC,OAASC,IACL,MAAMC,EAAMD,EAAOE,aAAa,SAChC,MAAMC,EAAS3B,KAAK4B,8BACpB,GAAI5B,KAAKD,SAAU,CACfC,KAAKD,SAAS4B,EAAOE,QAAS7B,KAAKE,SACvC,KAIRF,KAAKgB,sBAAsBhB,KAAKM,QAASX,EAAeE,GAExD,OAAOG,KAAKM,OAChB,CAMUwB,WACN,OAAO9B,KAAKM,QAAWN,KAAKM,QAA2BwB,WAAa,IACxE,CAKUC,aACN,GAAI/B,KAAKM,SAAWN,KAAKC,SAAU,CAC/B,IAAKD,KAAKK,WAAY,OACtB,MAAM2B,EAAQhC,KAAKM,QACnB0B,EAAMC,aAAajC,KAAKC,SAASmB,IAAIC,UACrCW,EAAME,YAAYlC,KAAKC,SAASqB,SACpC,CACJ,EACH,IAAAa,EAAA,CAAAC,WAAA,MAAAD,EAAA1C,iBAAA,OAAA0C,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":40,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","DropdownPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","startsWith","substring","isEditable","valueHelpArray","valueHelp","Array","isArray","enum","map","e","key","String","text","control","TextControl","id","generateStableId","path","formatter","match","find","vh","applyCommonDirectives","select","Select","selectedKey","enabled","ui","readOnly","forceSelection","change","oEvent","item","getParameter","val","getKey","result","validateAndApplyVisualState","isValid","length","addItem","Item","forEach","getValue","getSelectedKey","applyState","setEnabled","__exports","__esModule"],"sources":["DropdownPlugin.ts"],"sourcesContent":["/**\n * @file DropdownPlugin.ts\n * @description Renders a sap.m.Select utilizing the schema's valueHelp structure.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Select from \"sap/m/Select\";\nimport Item from \"sap/ui/core/Item\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering logic for dropdown inputs.\n * Maps the static `valueHelp` schema array to `sap.ui.core.Item` elements.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class DropdownPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.Select` component populated with schema-defined value help.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured Select control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.startsWith('/') ? bindingPath.substring(1) : bindingPath;\n \n if (!this.isEditable) {\n \n \n const valueHelpArray = fieldMetadata.valueHelp && Array.isArray(fieldMetadata.valueHelp) \n ? fieldMetadata.valueHelp \n : (fieldMetadata.enum ? fieldMetadata.enum.map(e => ({ key: String(e), text: String(e) })) : []);\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n formatter: (key: string) => {\n const match = valueHelpArray.find(vh => vh.key === key);\n return match ? match.text : key;\n }\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n const select = new Select({\n id: this.generateStableId(engineScopeId, bindingPath),\n selectedKey: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n forceSelection: false,\n change: (oEvent: sap.ui.base.Event) => {\n const item = oEvent.getParameter(\"selectedItem\");\n const val = item ? item.getKey() : \"\";\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n const valueHelpArray = fieldMetadata.valueHelp && Array.isArray(fieldMetadata.valueHelp) \n ? fieldMetadata.valueHelp \n : (fieldMetadata.enum ? fieldMetadata.enum.map(e => ({ key: String(e), text: String(e) })) : []);\n\n if (valueHelpArray.length > 0) {\n // Always add the empty placeholder so that 'required' checks can actually fire if the user hasn't made a choice\n select.addItem(new Item({ key: \"\", text: \"--- Select ---\" }));\n \n valueHelpArray.forEach(vh => {\n select.addItem(new Item({ key: vh.key, text: vh.text }));\n });\n }\n\n this.control = select;\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n /**\n * Retrieves the currently selected key.\n * @returns {unknown} The selected key.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as Select).getSelectedKey() : null;\n }\n\n /**\n * Applies dynamic metadata state (e.g. readOnly) when the ConditionEngine fires.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const select = this.control as Select;\n select.setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,8KAAA,MAKSA,EAAUC,EAAA,cAcZ,MAAMC,UAAuBF,EAWzBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,IAAKI,KAAKK,WAAY,CAGlB,MAAMC,EAAiBX,EAAcY,WAAaC,MAAMC,QAAQd,EAAcY,WACxEZ,EAAcY,UACbZ,EAAce,KAAOf,EAAce,KAAKC,IAAIC,IAAC,CAAOC,IAAKC,OAAOF,GAAIG,KAAMD,OAAOF,MAAS,GAEjGZ,KAAKgB,QAAU,IAAIC,EAAY,CAC3BC,GAAIlB,KAAKmB,iBAAiBrB,EAAeF,GACzCmB,KAAM,CACFK,KAAM,GAAGvB,KAAaD,IACtByB,UAAYR,IACR,MAAMS,EAAQhB,EAAeiB,KAAKC,GAAMA,EAAGX,MAAQA,GACnD,OAAOS,EAAQA,EAAMP,KAAOF,MAIxCb,KAAKyB,sBAAsBzB,KAAKgB,QAASrB,EAAeE,GACxD,OAAOG,KAAKgB,OAChB,CAEA,MAAMU,EAAS,IAAIC,EAAO,CACtBT,GAAIlB,KAAKmB,iBAAiBrB,EAAeF,GACzCgC,YAAa,IAAI/B,KAAaD,KAC9BiC,SAAUlC,EAAcmC,IAAIC,SAC5BC,eAAgB,MAChBC,OAASC,IACL,MAAMC,EAAOD,EAAOE,aAAa,gBACjC,MAAMC,EAAMF,EAAOA,EAAKG,SAAW,GACnC,MAAMC,EAASvC,KAAKwC,8BACpB,GAAIxC,KAAKD,SAAU,CACfC,KAAKD,SAASwC,EAAOE,QAASzC,KAAKE,SACvC,KAIR,MAAMI,EAAiBX,EAAcY,WAAaC,MAAMC,QAAQd,EAAcY,WACxEZ,EAAcY,UACbZ,EAAce,KAAOf,EAAce,KAAKC,IAAIC,IAAC,CAAOC,IAAKC,OAAOF,GAAIG,KAAMD,OAAOF,MAAS,GAEjG,GAAIN,EAAeoC,OAAS,EAAG,CAE3BhB,EAAOiB,QAAQ,IAAIC,EAAK,CAAE/B,IAAK,GAAIE,KAAM,oBAEzCT,EAAeuC,QAAQrB,IACnBE,EAAOiB,QAAQ,IAAIC,EAAK,CAAE/B,IAAKW,EAAGX,IAAKE,KAAMS,EAAGT,SAExD,CAEAf,KAAKgB,QAAUU,EACf1B,KAAKyB,sBAAsBzB,KAAKgB,QAASrB,EAAeE,GACxD,OAAOG,KAAKgB,OAChB,CAMU8B,WACN,OAAO9C,KAAKgB,QAAWhB,KAAKgB,QAAmB+B,iBAAmB,IACtE,CAKUC,aACN,GAAIhD,KAAKgB,SAAWhB,KAAKC,SAAU,CAC/B,IAAKD,KAAKK,WAAY,OACtB,MAAMqB,EAAS1B,KAAKgB,QACpBU,EAAOuB,YAAYjD,KAAKC,SAAS6B,IAAIC,SACzC,CACJ,EACH,IAAAmB,EAAA,CAAAC,WAAA,MAAAD,EAAAzD,iBAAA,OAAAyD,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":41,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","FileUploaderPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","startsWith","substring","isEditable","control","LinkControl","id","generateStableId","text","href","target","applyCommonDirectives","FileUploader","value","enabled","ui","readOnly","placeholder","label","width","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","getValue","applyState","setEnabled","__exports","__esModule"],"sources":["FileUploaderPlugin.ts"],"sourcesContent":["/**\n * @file FileUploaderPlugin.ts\n * @description Renders a sap.ui.unified.FileUploader.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport FileUploader from \"sap/ui/unified/FileUploader\";\nimport Control from \"sap/ui/core/Control\";\nimport LinkControl from \"sap/m/Link\";\n\n/**\n * Handles rendering logic for file uploads.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class FileUploaderPlugin extends BasePlugin {\n /**\n * Renders a `sap.ui.unified.FileUploader` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured FileUploader control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.startsWith('/') ? bindingPath.substring(1) : bindingPath;\n \n if (!this.isEditable) {\n \n this.control = new LinkControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`,\n href: `{${modelName}>${bindingPath}}`, // Assuming the value is a URL to the file\n target: \"_blank\"\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new FileUploader({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n placeholder: fieldMetadata.ui?.label || \"Choose a file...\",\n width: \"100%\",\n change: (oEvent: sap.ui.base.Event) => {\n const val = oEvent.getParameter(\"newValue\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n /**\n * Retrieves the current file path.\n * @returns {unknown} The file value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as FileUploader).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as FileUploader).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,4KAAA,MAKSA,EAAUC,EAAA,cAYZ,MAAMC,UAA2BF,EAW7BG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,IAAKI,KAAKK,WAAY,CAElBL,KAAKM,QAAU,IAAIC,EAAY,CAC3BC,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCc,KAAM,IAAIb,KAAaD,KACvBe,KAAM,IAAId,KAAaD,KACvBgB,OAAQ,WAEZZ,KAAKa,sBAAsBb,KAAKM,QAASX,EAAeE,GACxD,OAAOG,KAAKM,OAChB,CAEAN,KAAKM,QAAU,IAAIQ,EAAa,CAC5BN,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCmB,MAAO,IAAIlB,KAAaD,KACxBoB,SAAUrB,EAAcsB,IAAIC,SAC5BC,YAAaxB,EAAcsB,IAAIG,OAAS,mBACxCC,MAAO,OACPC,OAASC,IACL,MAAMC,EAAMD,EAAOE,aAAa,YAChC,MAAMC,EAAS1B,KAAK2B,8BACpB,GAAI3B,KAAKD,SAAU,CACfC,KAAKD,SAAS2B,EAAOE,QAAS5B,KAAKE,SACvC,KAIRF,KAAKa,sBAAsBb,KAAKM,QAASX,EAAeE,GACxD,OAAOG,KAAKM,OAChB,CAMUuB,WACN,OAAO7B,KAAKM,QAAWN,KAAKM,QAAyBuB,WAAa,IACtE,CAKUC,aACN,GAAI9B,KAAKM,SAAWN,KAAKC,SAAU,CAC/B,IAAKD,KAAKK,WAAY,OACrBL,KAAKM,QAAyByB,YAAY/B,KAAKC,SAASgB,IAAIC,SACjE,CACJ,EACH,IAAAc,EAAA,CAAAC,WAAA,MAAAD,EAAAvC,qBAAA,OAAAuC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":42,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","GeolocationControl","_interopRequireDefault","__GeolocationControl","GeolocationPlugin","render","metadata","bindingPath","modelName","engineScopeId","onChange","this","fieldKey","replace","isEditable","control","TextControl","id","generateStableId","text","path","formatter","val","lat","undefined","lng","applyCommonDirectives","value","schemaMetadata","readOnly","ui","attachCapture","result","validateAndApplyVisualState","isValid","getValue","applyState","setProperty","__exports","__esModule"],"sources":["GeolocationPlugin.ts"],"sourcesContent":["import { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport GeolocationControl from \"../../controls/GeolocationControl\";\nimport TextControl from \"sap/m/Text\";\n\nexport class GeolocationPlugin extends BasePlugin {\n /**\n * Renders a `GeolocationControl` component.\n * \n * @param metadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured GeolocationControl.\n */\n public render(metadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = metadata;\n this.fieldKey = bindingPath.replace('/', '');\n this.modelName = modelName;\n\n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n formatter: (val: unknown) => val && val.lat !== undefined && val.lng !== undefined ? `Lat: ${val.lat}, Lng: ${val.lng}` : \"\"\n }\n });\n this.applyCommonDirectives(this.control, metadata, modelName);\n return this.control as Control;\n }\n\n this.control = new GeolocationControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n schemaMetadata: metadata,\n readOnly: !!metadata.ui?.readOnly\n });\n\n this.applyCommonDirectives(this.control, metadata, modelName);\n\n (this.control as GeolocationControl).attachCapture(() => {\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n });\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current geolocation object.\n * @returns {unknown} The geolocation value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as GeolocationControl).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as sap.ui.core.Control).setProperty(\"readOnly\", !!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,kRAASA,EAAUC,EAAA,oBAGZC,EAAkBC,EAAAC,GAGlB,MAAMC,UAA0BL,EAW5BM,OAAOC,EAA8BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAClHC,KAAKD,SAAWA,EAChBC,KAAKL,SAAWA,EAChBK,KAAKC,SAAWL,EAAYM,QAAQ,IAAK,IACzCF,KAAKH,UAAYA,EAEjB,IAAKG,KAAKG,WAAY,CAElBH,KAAKI,QAAU,IAAIC,EAAY,CAC3BC,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCY,KAAM,CACFC,KAAM,GAAGZ,KAAaD,IACtBc,UAAYC,GAAiBA,GAAOA,EAAIC,MAAQC,WAAaF,EAAIG,MAAQD,UAAY,QAAQF,EAAIC,aAAaD,EAAIG,MAAQ,MAGlId,KAAKe,sBAAsBf,KAAKI,QAAST,EAAUE,GACnD,OAAOG,KAAKI,OAChB,CAEAJ,KAAKI,QAAU,IAAId,EAAmB,CAClCgB,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCoB,MAAO,IAAInB,KAAaD,KACxBqB,eAAgBtB,EAChBuB,WAAYvB,EAASwB,IAAID,WAG7BlB,KAAKe,sBAAsBf,KAAKI,QAAST,EAAUE,GAElDG,KAAKI,QAA+BgB,cAAc,KAC/C,MAAMC,EAASrB,KAAKsB,8BAChB,GAAItB,KAAKD,SAAU,CACfC,KAAKD,SAASsB,EAAOE,QAASvB,KAAKC,SACvC,IAGR,OAAOD,KAAKI,OAChB,CAMUoB,WACN,OAAOxB,KAAKI,QAAWJ,KAAKI,QAA+BoB,WAAa,IAC5E,CAKUC,aACN,GAAIzB,KAAKI,SAAWJ,KAAKL,SAAU,CAC/B,IAAKK,KAAKG,WAAY,OACrBH,KAAKI,QAAgCsB,YAAY,aAAc1B,KAAKL,SAASwB,IAAID,SACtF,CACJ,EACH,IAAAS,EAAA,CAAAC,WAAA,MAAAD,EAAAlC,oBAAA,OAAAkC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":43,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","MessageStripPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","startsWith","substring","control","MessageStrip","id","generateStableId","text","type","showIcon","showCloseButton","getValue","applyState","__exports","__esModule"],"sources":["MessageStripPlugin.ts"],"sourcesContent":["/**\n * @file MessageStripPlugin.ts\n * @description Renders a sap.m.MessageStrip for informational text.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport MessageStrip from \"sap/m/MessageStrip\";\nimport Control from \"sap/ui/core/Control\";\n\n/**\n * Renders read-only informational alerts within the layout.\n * Does not emit values to the payload.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class MessageStripPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.MessageStrip` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured MessageStrip control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.startsWith('/') ? bindingPath.substring(1) : bindingPath;\n \n // Use binding to display text if the field has a value, otherwise use the label\n this.control = new MessageStrip({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`,\n type: \"Information\", // Can be driven by schema arguments in the future\n showIcon: true,\n showCloseButton: false\n });\n\n return this.control as Control;\n }\n\n /**\n * Read-only control, returns null.\n */\n protected getValue(): unknown {\n return null; // Read-only component\n }\n\n /**\n * Read-only control, no dynamic state needed.\n */\n protected applyState(): void {\n // Read-only component, no dynamic state needed currently\n }\n}\n"],"mappings":"AAAA,oJAAA,MAKSA,EAAUC,EAAA,cAYZ,MAAMC,UAA2BF,EAW7BG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAGzEI,KAAKK,QAAU,IAAIC,EAAa,CAC5BC,GAAIP,KAAKQ,iBAAiBV,EAAeF,GACzCa,KAAM,IAAIZ,KAAaD,KACvBc,KAAM,cACNC,SAAU,KACVC,gBAAiB,QAGrB,OAAOZ,KAAKK,OAChB,CAKUQ,WACN,OAAO,IACX,CAKUC,aACN,EAEP,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAAtB,qBAAA,OAAAsB,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":44,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","MultiInputPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","startsWith","substring","isEditable","control","TextControl","id","generateStableId","text","path","formatter","val","Array","isArray","join","applyCommonDirectives","mi","MultiInput","enabled","ui","readOnly","placeholder","label","showValueHelp","tokenUpdate","oEvent","params","getParameters","type","model","getModel","rawArr","getProperty","arr","removedTokens","forEach","t","getText","idx","indexOf","splice","setProperty","result","validateAndApplyVisualState","isValid","addValidator","args","trim","push","setValue","bindAggregation","factory","sId","oContext","getObject","Token","key","getValue","tokens","getTokens","map","applyState","setEnabled","__exports","__esModule"],"sources":["MultiInputPlugin.ts"],"sourcesContent":["/**\n * @file MultiInputPlugin.ts\n * @description Renders a sap.m.MultiInput for primitive arrays (e.g. arrays of strings).\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport MultiInput from \"sap/m/MultiInput\";\nimport Token from \"sap/m/Token\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\nimport Event from \"sap/ui/base/Event\";\nimport Context from \"sap/ui/model/Context\";\n\n/**\n * Handles rendering logic for arrays of primitive strings.\n * Users can type custom strings and press Enter to add them as tokens.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class MultiInputPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.MultiInput` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured MultiInput control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.startsWith('/') ? bindingPath.substring(1) : bindingPath;\n\n if (!this.isEditable) {\n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n formatter: (val: unknown[]) => Array.isArray(val) ? val.join(\", \") : \"\"\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n \n const mi = new MultiInput({\n id: this.generateStableId(engineScopeId, bindingPath),\n enabled: !fieldMetadata.ui?.readOnly,\n placeholder: fieldMetadata.ui?.label || \"Type and press Enter...\",\n showValueHelp: false, // We don't have a list of options for primitive tags\n tokenUpdate: (oEvent: Event) => {\n const params = oEvent.getParameters();\n const type = params.type;\n \n if (type === \"removed\") {\n const model = mi.getModel(modelName) as JSONModel;\n \n // Get current array from model\n const rawArr = model.getProperty(bindingPath);\n const arr: string[] = Array.isArray(rawArr) ? [...rawArr] : [];\n\n const removedTokens = params.removedTokens as Token[];\n removedTokens.forEach(t => {\n const text = t.getText();\n const idx = arr.indexOf(text);\n if (idx > -1) {\n arr.splice(idx, 1);\n }\n });\n \n // Update model\n model.setProperty(bindingPath, arr);\n \n // Trigger engine validation/extraction\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n }\n });\n\n // Add validator to instantly accept typed text, update model, and clear input\n mi.addValidator((args: { text: string }) => {\n const text = args.text?.trim();\n if (text) {\n const model = mi.getModel(modelName) as JSONModel;\n const rawArr = model.getProperty(bindingPath);\n const arr: string[] = Array.isArray(rawArr) ? [...rawArr] : [];\n \n arr.push(text);\n model.setProperty(bindingPath, arr);\n \n // Clear the input value immediately\n mi.setValue(\"\");\n \n // Trigger engine validation/extraction\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n // Return null to explicitly prevent MultiInput from modifying the bound aggregation\n return null;\n });\n\n // Bind existing strings to tokens using a factory function\n mi.bindAggregation(\"tokens\", {\n path: `${modelName}>${bindingPath}`,\n factory: (sId: string, oContext: Context) => {\n const text = (oContext.getObject() as string) || \"\";\n return new Token(sId, { key: text, text: text });\n }\n });\n\n this.control = mi;\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n /**\n * Retrieves the current primitive array from the model.\n * @returns {unknown} The array of string tokens.\n */\n protected getValue(): unknown {\n if (!this.control) return [];\n const tokens = (this.control as MultiInput).getTokens();\n return tokens.map(t => t.getText());\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as MultiInput).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,+KAAA,MAKSA,EAAUC,EAAA,cAiBZ,MAAMC,UAAyBF,EAW3BG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,IAAKI,KAAKK,WAAY,CAClBL,KAAKM,QAAU,IAAIC,EAAY,CAC3BC,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCc,KAAM,CACFC,KAAM,GAAGd,KAAaD,IACtBgB,UAAYC,GAAmBC,MAAMC,QAAQF,GAAOA,EAAIG,KAAK,MAAQ,MAG7EhB,KAAKiB,sBAAsBjB,KAAKM,QAASX,EAAeE,GACxD,OAAOG,KAAKM,OAChB,CAEA,MAAMY,EAAK,IAAIC,EAAW,CACtBX,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCwB,SAAUzB,EAAc0B,IAAIC,SAC5BC,YAAa5B,EAAc0B,IAAIG,OAAS,0BACxCC,cAAe,MACfC,YAAcC,IACV,MAAMC,EAASD,EAAOE,gBACtB,MAAMC,EAAOF,EAAOE,KAEpB,GAAIA,IAAS,UAAW,CACpB,MAAMC,EAAQb,EAAGc,SAASnC,GAG1B,MAAMoC,EAASF,EAAMG,YAAYtC,GACjC,MAAMuC,EAAgBrB,MAAMC,QAAQkB,GAAU,IAAIA,GAAU,GAE5D,MAAMG,EAAgBR,EAAOQ,cAC7BA,EAAcC,QAAQC,IAClB,MAAM5B,EAAO4B,EAAEC,UACf,MAAMC,EAAML,EAAIM,QAAQ/B,GACxB,GAAI8B,GAAO,EAAG,CACVL,EAAIO,OAAOF,EAAK,EACpB,IAIJT,EAAMY,YAAY/C,EAAauC,GAG/B,MAAMS,EAAS5C,KAAK6C,8BACpB,GAAI7C,KAAKD,SAAU,CACfC,KAAKD,SAAS6C,EAAOE,QAAS9C,KAAKE,SACvC,CACJ,KAKRgB,EAAG6B,aAAcC,IACb,MAAMtC,EAAOsC,EAAKtC,MAAMuC,OACxB,GAAIvC,EAAM,CACN,MAAMqB,EAAQb,EAAGc,SAASnC,GAC1B,MAAMoC,EAASF,EAAMG,YAAYtC,GACjC,MAAMuC,EAAgBrB,MAAMC,QAAQkB,GAAU,IAAIA,GAAU,GAE5DE,EAAIe,KAAKxC,GACTqB,EAAMY,YAAY/C,EAAauC,GAG/BjB,EAAGiC,SAAS,IAGZ,MAAMP,EAAS5C,KAAK6C,8BACpB,GAAI7C,KAAKD,SAAU,CACfC,KAAKD,SAAS6C,EAAOE,QAAS9C,KAAKE,SACvC,CACJ,CAEA,OAAO,OAIXgB,EAAGkC,gBAAgB,SAAU,CACzBzC,KAAM,GAAGd,KAAaD,IACtByD,QAASA,CAACC,EAAaC,KACnB,MAAM7C,EAAQ6C,EAASC,aAA0B,GACjD,OAAO,IAAIC,EAAMH,EAAK,CAAEI,IAAKhD,EAAMA,KAAMA,OAIjDV,KAAKM,QAAUY,EACflB,KAAKiB,sBAAsBjB,KAAKM,QAASX,EAAeE,GACxD,OAAOG,KAAKM,OAChB,CAMUqD,WACN,IAAK3D,KAAKM,QAAS,MAAO,GAC1B,MAAMsD,EAAU5D,KAAKM,QAAuBuD,YAC5C,OAAOD,EAAOE,IAAIxB,GAAKA,EAAEC,UAC7B,CAKUwB,aACN,GAAI/D,KAAKM,SAAWN,KAAKC,SAAU,CAC/B,IAAKD,KAAKK,WAAY,OACrBL,KAAKM,QAAuB0D,YAAYhE,KAAKC,SAASoB,IAAIC,SAC/D,CACJ,EACH,IAAA2C,EAAA,CAAAC,WAAA,MAAAD,EAAAxE,mBAAA,OAAAwE,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":45,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","MultiSelectPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","startsWith","substring","isEditable","control","TextControl","id","generateStableId","text","path","formatter","val","Array","isArray","join","applyCommonDirectives","mcb","MultiComboBox","selectedKeys","enabled","ui","readOnly","placeholder","label","selectionChange","oEvent","keys","getSelectedKeys","result","validateAndApplyVisualState","isValid","enum","forEach","addItem","Item","key","toString","getValue","applyState","setEnabled","__exports","__esModule"],"sources":["MultiSelectPlugin.ts"],"sourcesContent":["/**\n * @file MultiSelectPlugin.ts\n * @description Renders a sap.m.MultiComboBox for selecting multiple string values.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport MultiComboBox from \"sap/m/MultiComboBox\";\nimport Item from \"sap/ui/core/Item\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering logic for selecting multiple strings from a predefined list.\n * Expects the payload to be an array of strings.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class MultiSelectPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.MultiComboBox` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured MultiComboBox control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.startsWith('/') ? bindingPath.substring(1) : bindingPath;\n\n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n formatter: (val: unknown[]) => Array.isArray(val) ? val.join(\", \") : \"\"\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n \n const mcb = new MultiComboBox({\n id: this.generateStableId(engineScopeId, bindingPath),\n selectedKeys: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n placeholder: fieldMetadata.ui?.label || \"Select items...\",\n selectionChange: (oEvent: sap.ui.base.Event) => {\n const keys = (this.control as MultiComboBox).getSelectedKeys();\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n if (fieldMetadata.enum) {\n fieldMetadata.enum.forEach((val: string | number) => {\n mcb.addItem(new Item({ key: val.toString(), text: val.toString() }));\n });\n }\n\n this.control = mcb;\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n /**\n * Retrieves the current selection keys.\n * @returns {unknown} The selected keys.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as MultiComboBox).getSelectedKeys() : [];\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as MultiComboBox).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,wLAAA,MAKSA,EAAUC,EAAA,cAcZ,MAAMC,UAA0BF,EAW5BG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,IAAKI,KAAKK,WAAY,CAElBL,KAAKM,QAAU,IAAIC,EAAY,CAC3BC,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCc,KAAM,CACFC,KAAM,GAAGd,KAAaD,IACtBgB,UAAYC,GAAmBC,MAAMC,QAAQF,GAAOA,EAAIG,KAAK,MAAQ,MAG7EhB,KAAKiB,sBAAsBjB,KAAKM,QAASX,EAAeE,GACxD,OAAOG,KAAKM,OAChB,CAEA,MAAMY,EAAM,IAAIC,EAAc,CAC1BX,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCwB,aAAc,IAAIvB,KAAaD,KAC/ByB,SAAU1B,EAAc2B,IAAIC,SAC5BC,YAAa7B,EAAc2B,IAAIG,OAAS,kBACxCC,gBAAkBC,IACd,MAAMC,EAAQ5B,KAAKM,QAA0BuB,kBAC7C,MAAMC,EAAS9B,KAAK+B,8BACpB,GAAI/B,KAAKD,SAAU,CACfC,KAAKD,SAAS+B,EAAOE,QAAShC,KAAKE,SACvC,KAIR,GAAIP,EAAcsC,KAAM,CACpBtC,EAAcsC,KAAKC,QAASrB,IACxBK,EAAIiB,QAAQ,IAAIC,EAAK,CAAEC,IAAKxB,EAAIyB,WAAY5B,KAAMG,EAAIyB,eAE9D,CAEAtC,KAAKM,QAAUY,EACflB,KAAKiB,sBAAsBjB,KAAKM,QAASX,EAAeE,GACxD,OAAOG,KAAKM,OAChB,CAMUiC,WACN,OAAOvC,KAAKM,QAAWN,KAAKM,QAA0BuB,kBAAoB,EAC9E,CAKUW,aACN,GAAIxC,KAAKM,SAAWN,KAAKC,SAAU,CAC/B,IAAKD,KAAKK,WAAY,OACrBL,KAAKM,QAA0BmC,YAAYzC,KAAKC,SAASqB,IAAIC,SAClE,CACJ,EACH,IAAAmB,EAAA,CAAAC,WAAA,MAAAD,EAAAjD,oBAAA,OAAAiD,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":46,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","NumberPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","startsWith","substring","isEditable","control","TextControl","id","generateStableId","text","applyCommonDirectives","typeInstance","type","Integer","groupingEnabled","Float","minFractionDigits","scale","undefined","maxFractionDigits","Input","value","path","editable","ui","readOnly","required","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","getValue","input","binding","getBinding","applyState","setEditable","setRequired","__exports","__esModule"],"sources":["NumberPlugin.ts"],"sourcesContent":["/**\n * @file NumberPlugin.ts\n * @description Renders a sap.m.Input configured for generic dynamic numeric data.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Input from \"sap/m/Input\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\nimport Float from \"sap/ui/model/type/Float\";\nimport Integer from \"sap/ui/model/type/Integer\";\n\n/**\n * Handles rendering and logic for dynamic numeric inputs.\n */\nexport class NumberPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.Input` component for numeric evaluation with dynamic Float type.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured Input control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.startsWith('/') ? bindingPath.substring(1) : bindingPath;\n\n if (!this.isEditable) {\n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n let typeInstance;\n if (fieldMetadata.type === \"integer\") {\n typeInstance = new Integer({ groupingEnabled: false });\n } else {\n typeInstance = new Float({\n groupingEnabled: false,\n minFractionDigits: fieldMetadata.scale !== undefined ? fieldMetadata.scale : 0,\n maxFractionDigits: fieldMetadata.scale !== undefined ? fieldMetadata.scale : 9\n });\n }\n\n this.control = new Input({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: {\n path: `${modelName}>${bindingPath}`,\n type: typeInstance\n },\n type: \"Number\",\n editable: !fieldMetadata.ui?.readOnly,\n required: !!fieldMetadata.required,\n change: (oEvent: sap.ui.base.Event) => {\n const val = oEvent.getParameter(\"value\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current numeric state.\n * @returns {unknown} The numeric value.\n */\n protected getValue(): unknown {\n if (!this.control) return null;\n // In UI5, Input.getValue() returns a string. We must parse it if it's bound.\n // However, we can also extract it directly from the binding.\n const input = this.control as Input;\n const binding = input.getBinding(\"value\");\n if (binding) {\n return binding.getValue();\n }\n return input.getValue();\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const input = this.control as Input;\n input.setEditable(!this.metadata.ui?.readOnly);\n input.setRequired(!!this.metadata.required);\n }\n }\n}\n"],"mappings":"AAAA,gNAAA,MAKSA,EAAUC,EAAA,cAWZ,MAAMC,UAAqBF,EAWvBG,OAAOC,EAAkCC,EAAqBC,EAAoB,OAAQC,EAAwBC,GACrHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,IAAKI,KAAKK,WAAY,CAClBL,KAAKM,QAAU,IAAIC,EAAY,CAC3BC,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCc,KAAM,IAAIb,KAAaD,OAE3BI,KAAKW,sBAAsBX,KAAKM,QAASX,EAAeE,GACxD,OAAOG,KAAKM,OAChB,CAEA,IAAIM,EACJ,GAAIjB,EAAckB,OAAS,UAAW,CAClCD,EAAe,IAAIE,EAAQ,CAAEC,gBAAiB,OAClD,KAAO,CACHH,EAAe,IAAII,EAAM,CACrBD,gBAAiB,MACjBE,kBAAmBtB,EAAcuB,QAAUC,UAAYxB,EAAcuB,MAAQ,EAC7EE,kBAAmBzB,EAAcuB,QAAUC,UAAYxB,EAAcuB,MAAQ,GAErF,CAEAlB,KAAKM,QAAU,IAAIe,EAAM,CACrBb,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzC0B,MAAO,CACHC,KAAM,GAAG1B,KAAaD,IACtBiB,KAAMD,GAEVC,KAAM,SACNW,UAAW7B,EAAc8B,IAAIC,SAC7BC,WAAYhC,EAAcgC,SAC1BC,OAASC,IACL,MAAMC,EAAMD,EAAOE,aAAa,SAChC,MAAMC,EAAShC,KAAKiC,8BACpB,GAAIjC,KAAKD,SAAU,CACfC,KAAKD,SAASiC,EAAOE,QAASlC,KAAKE,SACvC,KAIRF,KAAKW,sBAAsBX,KAAKM,QAASX,EAAeE,GAExD,OAAOG,KAAKM,OAChB,CAMU6B,WACN,IAAKnC,KAAKM,QAAS,OAAO,KAG1B,MAAM8B,EAAQpC,KAAKM,QACnB,MAAM+B,EAAUD,EAAME,WAAW,SACjC,GAAID,EAAS,CACT,OAAOA,EAAQF,UACnB,CACA,OAAOC,EAAMD,UACjB,CAKUI,aACN,GAAIvC,KAAKM,SAAWN,KAAKC,SAAU,CAC/B,IAAKD,KAAKK,WAAY,OACtB,MAAM+B,EAAQpC,KAAKM,QACnB8B,EAAMI,aAAaxC,KAAKC,SAASwB,IAAIC,UACrCU,EAAMK,cAAczC,KAAKC,SAAS0B,SACtC,CACJ,EACH,IAAAe,EAAA,CAAAC,WAAA,MAAAD,EAAAjD,eAAA,OAAAiD,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":47,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","ObjectPlugin","render","field","bindingPath","modelName","engineScopeId","onChange","this","metadata","propKey","startsWith","substring","subSchema","type","title","ui","label","properties","uiLayout","control","Button","id","generateStableId","text","isEditable","icon","press","oEvent","btn","getSource","parentModel","getModel","bindingContext","getBindingContext","updatePath","ctxPath","getPath","endsWith","nestedData","JSON","parse","stringify","getProperty","sap","require","DynamicHost","host","schemaDefinition","data","editable","attachSubmit","e","payload","getParameter","setProperty","buttonText","dialogButtonText","openInDialog","validate","isValid","getValue","applyState","__exports","__esModule"],"sources":["ObjectPlugin.ts"],"sourcesContent":["/**\n * @file ObjectPlugin.ts\n * @description Renders a button that opens a dialog to edit a nested object structure.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPluginValidationResult } from \"../../interfaces/IPlugin\";\nimport { ISchema, IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport Event from \"sap/ui/base/Event\";\nimport Button from \"sap/m/Button\";\nimport JSONModel from \"sap/ui/model/json/JSONModel\";\n\nexport class ObjectPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.Button` to open a nested Object form dialog.\n * \n * @param field The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured Button control.\n */\n public render(field: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = field;\n const propKey = bindingPath.startsWith(\"/\") ? bindingPath.substring(1) : bindingPath;\n \n const subSchema: ISchema = {\n type: \"object\",\n title: field.ui?.label || propKey,\n properties: field.properties || {}\n };\n \n if (field.uiLayout) {\n subSchema.uiLayout = field.uiLayout;\n }\n\n this.control = new Button({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: !this.isEditable ? \"View Details\" : \"Edit Details\",\n icon: !this.isEditable ? \"sap-icon://display\" : \"sap-icon://form\",\n press: (oEvent: Event) => {\n const btn = oEvent.getSource() as Button;\n const parentModel = btn.getModel(modelName) as JSONModel;\n if (!parentModel) return;\n \n const bindingContext = btn.getBindingContext(modelName);\n let updatePath = bindingPath;\n if (bindingContext && !bindingPath.startsWith(\"/\")) {\n const ctxPath = bindingContext.getPath();\n updatePath = ctxPath.endsWith(\"/\") ? ctxPath + bindingPath : (ctxPath === \"/\" ? \"/\" + bindingPath : ctxPath + \"/\" + bindingPath);\n }\n \n // Deep clone to prevent live-mutations on the parent model before 'Submit' is clicked\n const nestedData = JSON.parse(JSON.stringify(parentModel.getProperty(updatePath) || {}));\n\n sap.ui.require([\"nz/co/siliconst/ui5/metaui/controls/DynamicHost\"], (DynamicHost: typeof import(\"../../controls/DynamicHost\").default) => {\n const host = new DynamicHost({\n schemaDefinition: subSchema,\n data: nestedData,\n editable: this.isEditable\n });\n\n if (!!this.isEditable) {\n host.attachSubmit((e: Event) => {\n const payload = (e.getParameter(\"payload\") as unknown);\n parentModel.setProperty(updatePath, payload);\n \n // CRITICAL: Notify the parent Engine that this field mutated\n // so it can trigger LiveUpdate syncs and validate!\n if (this.onChange) {\n this.onChange(true, propKey);\n }\n });\n }\n\n const buttonText = field.ui?.dialogButtonText || (!this.isEditable ? \"Close\" : \"OK\");\n host.openInDialog(`Nested Details: ${field.ui?.label || propKey}`, buttonText);\n });\n }\n });\n\n return this.control as Control;\n }\n\n /**\n * Validates the object plugin (always true as validation is deferred to the dialog host).\n * @returns {IPluginValidationResult} The validation result.\n */\n public validate(): IPluginValidationResult {\n return { isValid: true };\n }\n\n /**\n * Read-only component for the engine, returns null.\n */\n protected getValue(): null {\n return null;\n }\n\n /**\n * Read-only component, no dynamic state handling needed for the button itself.\n */\n protected applyState(): void {\n // No dynamic state handling needed for the button\n }\n}\n"],"mappings":"AAAA,wIAAA,MAKSA,EAAUC,EAAA,cAQZ,MAAMC,UAAqBF,EAWvBG,OAAOC,EAA2BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAC/GC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChB,MAAMO,EAAUN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,MAAMS,EAAqB,CACvBC,KAAM,SACNC,MAAOZ,EAAMa,IAAIC,OAASP,EAC1BQ,WAAYf,EAAMe,YAAc,CAAC,GAGrC,GAAIf,EAAMgB,SAAU,CAChBN,EAAUM,SAAWhB,EAAMgB,QAC/B,CAEAX,KAAKY,QAAU,IAAIC,EAAO,CACtBC,GAAId,KAAKe,iBAAiBjB,EAAeF,GACzCoB,MAAOhB,KAAKiB,WAAa,eAAiB,eAC1CC,MAAOlB,KAAKiB,WAAa,qBAAuB,kBAChDE,MAAQC,IACJ,MAAMC,EAAMD,EAAOE,YACnB,MAAMC,EAAcF,EAAIG,SAAS3B,GACjC,IAAK0B,EAAa,OAElB,MAAME,EAAiBJ,EAAIK,kBAAkB7B,GAC7C,IAAI8B,EAAa/B,EACjB,GAAI6B,IAAmB7B,EAAYO,WAAW,KAAM,CAChD,MAAMyB,EAAUH,EAAeI,UAC/BF,EAAaC,EAAQE,SAAS,KAAOF,EAAUhC,EAAegC,IAAY,IAAM,IAAMhC,EAAcgC,EAAU,IAAMhC,CACxH,CAGA,MAAMmC,EAAaC,KAAKC,MAAMD,KAAKE,UAAUX,EAAYY,YAAYR,IAAe,CAAC,IAErFS,IAAI5B,GAAG6B,QAAQ,CAAC,mDAAqDC,IACjE,MAAMC,EAAO,IAAID,EAAY,CACzBE,iBAAkBnC,EAClBoC,KAAMV,EACNW,SAAU1C,KAAKiB,aAGnB,KAAMjB,KAAKiB,WAAY,CACnBsB,EAAKI,aAAcC,IACf,MAAMC,EAAWD,EAAEE,aAAa,WAChCvB,EAAYwB,YAAYpB,EAAYkB,GAIpC,GAAI7C,KAAKD,SAAU,CACfC,KAAKD,SAAS,KAAMG,EACxB,GAER,CAEA,MAAM8C,EAAarD,EAAMa,IAAIyC,oBAAsBjD,KAAKiB,WAAa,QAAU,MAC/EsB,EAAKW,aAAa,mBAAmBvD,EAAMa,IAAIC,OAASP,IAAW8C,QAK/E,OAAOhD,KAAKY,OAChB,CAMOuC,WACH,MAAO,CAAEC,QAAS,KACtB,CAKUC,WACN,OAAO,IACX,CAKUC,aACN,EAEP,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAA9D,eAAA,OAAA8D,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":48,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","RatingIndicatorPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","startsWith","substring","isEditable","control","TextControl","id","generateStableId","text","applyCommonDirectives","RatingIndicator","value","enabled","ui","readOnly","maxValue","maximum","undefined","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","getValue","applyState","setEnabled","__exports","__esModule"],"sources":["RatingIndicatorPlugin.ts"],"sourcesContent":["/**\n * @file RatingIndicatorPlugin.ts\n * @description Renders a sap.m.RatingIndicator for 1-5 numeric feedback.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport RatingIndicator from \"sap/m/RatingIndicator\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering logic for rating feedback.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class RatingIndicatorPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.RatingIndicator` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured RatingIndicator control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.startsWith('/') ? bindingPath.substring(1) : bindingPath;\n\n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n \n this.control = new RatingIndicator({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n maxValue: fieldMetadata.maximum !== undefined ? fieldMetadata.maximum : 5,\n change: (oEvent: sap.ui.base.Event) => {\n const val = oEvent.getParameter(\"value\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current rating value.\n * @returns {unknown} The rating value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as RatingIndicator).getValue() : 0;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as RatingIndicator).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,yKAAA,MAKSA,EAAUC,EAAA,cAYZ,MAAMC,UAA8BF,EAWhCG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,IAAKI,KAAKK,WAAY,CAElBL,KAAKM,QAAU,IAAIC,EAAY,CAC3BC,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCc,KAAM,IAAIb,KAAaD,OAE3BI,KAAKW,sBAAsBX,KAAKM,QAASX,EAAeE,GACxD,OAAOG,KAAKM,OAChB,CAEAN,KAAKM,QAAU,IAAIM,EAAgB,CAC/BJ,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCiB,MAAO,IAAIhB,KAAaD,KACxBkB,SAAUnB,EAAcoB,IAAIC,SAC5BC,SAAUtB,EAAcuB,UAAYC,UAAYxB,EAAcuB,QAAU,EACxEE,OAASC,IACL,MAAMC,EAAMD,EAAOE,aAAa,SAChC,MAAMC,EAASxB,KAAKyB,8BACpB,GAAIzB,KAAKD,SAAU,CACfC,KAAKD,SAASyB,EAAOE,QAAS1B,KAAKE,SACvC,KAIRF,KAAKW,sBAAsBX,KAAKM,QAASX,EAAeE,GAExD,OAAOG,KAAKM,OAChB,CAMUqB,WACN,OAAO3B,KAAKM,QAAWN,KAAKM,QAA4BqB,WAAa,CACzE,CAKUC,aACN,GAAI5B,KAAKM,SAAWN,KAAKC,SAAU,CAC/B,IAAKD,KAAKK,WAAY,OACrBL,KAAKM,QAA4BuB,YAAY7B,KAAKC,SAASc,IAAIC,SACpE,CACJ,EACH,IAAAc,EAAA,CAAAC,WAAA,MAAAD,EAAArC,wBAAA,OAAAqC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":49,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","RichTextControl","_interopRequireDefault","__RichTextControl","isValueAccessor","control","getValue","RichTextPlugin","render","metadata","bindingPath","modelName","engineScopeId","onChange","this","fieldKey","replace","isEditable","FormattedTextControl","id","generateStableId","htmlText","applyCommonDirectives","value","schemaMetadata","readOnly","ui","attachCapture","result","validateAndApplyVisualState","isValid","applyState","setProperty","__exports","__esModule"],"sources":["RichTextPlugin.ts"],"sourcesContent":["import { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport RichTextControl from \"../../controls/RichTextControl\";\nimport FormattedTextControl from \"sap/m/FormattedText\";\n\ninterface IValueAccessor {\n getValue(): unknown;\n attachCapture?(fn: Function): void;\n}\n\nfunction isValueAccessor(control: unknown): control is IValueAccessor {\n return control !== null && typeof (control as IValueAccessor).getValue === 'function';\n}\n\nexport class RichTextPlugin extends BasePlugin {\n /**\n * Renders a `RichTextControl` component.\n * \n * @param metadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured RichTextControl.\n */\n public render(metadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = metadata;\n this.fieldKey = bindingPath.replace('/', '');\n this.modelName = modelName;\n\n if (!this.isEditable) {\n \n this.control = new FormattedTextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n htmlText: `{${modelName}>${bindingPath}}`\n }) as Control;\n this.applyCommonDirectives(this.control, metadata, modelName);\n return this.control as Control;\n }\n\n this.control = new RichTextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n schemaMetadata: metadata,\n readOnly: !!metadata.ui?.readOnly\n }) as Control;\n\n this.applyCommonDirectives(this.control, metadata, modelName);\n\n if (isValueAccessor(this.control) && this.control.attachCapture) {\n this.control.attachCapture(() => {\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n });\n }\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current HTML string value.\n * @returns {unknown} The string value.\n */\n protected getValue(): unknown {\n if (isValueAccessor(this.control)) {\n return this.control.getValue();\n }\n return null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as sap.ui.core.Control).setProperty(\"readOnly\", !!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,qRAASA,EAAUC,EAAA,oBAGZC,EAAeC,EAAAC,GAQtB,SAASC,EAAgBC,GACrB,OAAOA,IAAY,aAAgBA,EAA2BC,WAAa,UAC/E,CAEO,MAAMC,UAAuBR,EAWzBS,OAAOC,EAA8BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAClHC,KAAKD,SAAWA,EAChBC,KAAKL,SAAWA,EAChBK,KAAKC,SAAWL,EAAYM,QAAQ,IAAK,IACzCF,KAAKH,UAAYA,EAEjB,IAAKG,KAAKG,WAAY,CAElBH,KAAKT,QAAU,IAAIa,EAAqB,CACpCC,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCW,SAAU,IAAIV,KAAaD,OAE/BI,KAAKQ,sBAAsBR,KAAKT,QAASI,EAAUE,GACnD,OAAOG,KAAKT,OAChB,CAEAS,KAAKT,QAAU,IAAIJ,EAAgB,CAC/BkB,GAAIL,KAAKM,iBAAiBR,EAAeF,GACzCa,MAAO,IAAIZ,KAAaD,KACxBc,eAAgBf,EAChBgB,WAAYhB,EAASiB,IAAID,WAG7BX,KAAKQ,sBAAsBR,KAAKT,QAASI,EAAUE,GAEnD,GAAIP,EAAgBU,KAAKT,UAAYS,KAAKT,QAAQsB,cAAe,CAC7Db,KAAKT,QAAQsB,cAAc,KACvB,MAAMC,EAASd,KAAKe,8BACpB,GAAIf,KAAKD,SAAU,CACfC,KAAKD,SAASe,EAAOE,QAAShB,KAAKC,SACvC,GAER,CAEA,OAAOD,KAAKT,OAChB,CAMUC,WACN,GAAIF,EAAgBU,KAAKT,SAAU,CAC/B,OAAOS,KAAKT,QAAQC,UACxB,CACA,OAAO,IACX,CAKUyB,aACN,GAAIjB,KAAKT,SAAWS,KAAKL,SAAU,CAC/B,IAAKK,KAAKG,WAAY,OACrBH,KAAKT,QAAgC2B,YAAY,aAAclB,KAAKL,SAASiB,IAAID,SACtF,CACJ,EACH,IAAAQ,EAAA,CAAAC,WAAA,MAAAD,EAAA1B,iBAAA,OAAA0B,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":50,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","SignatureControl","_interopRequireDefault","__SignatureControl","SignaturePlugin","render","metadata","bindingPath","modelName","engineScopeId","onChange","this","fieldKey","replace","isEditable","control","ImageControl","id","generateStableId","src","width","alt","ui","label","applyCommonDirectives","value","schemaMetadata","readOnly","attachCapture","result","validateAndApplyVisualState","isValid","getValue","applyState","setProperty","__exports","__esModule"],"sources":["SignaturePlugin.ts"],"sourcesContent":["import { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport SignatureControl from \"../../controls/SignatureControl\";\nimport ImageControl from \"sap/m/Image\";\n\nexport class SignaturePlugin extends BasePlugin {\n /**\n * Renders a `SignatureControl` component.\n * \n * @param metadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured SignatureControl.\n */\n public render(metadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = metadata;\n this.fieldKey = bindingPath.replace('/', '');\n this.modelName = modelName;\n\n if (!this.isEditable) {\n \n this.control = new ImageControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n src: `{${modelName}>${bindingPath}}`,\n width: \"400px\",\n alt: metadata.ui?.label || \"Signature\"\n }) as Control;\n this.applyCommonDirectives(this.control, metadata, modelName);\n return this.control as Control;\n }\n\n this.control = new SignatureControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n schemaMetadata: metadata,\n readOnly: !!metadata.ui?.readOnly\n }) as Control;\n\n this.applyCommonDirectives(this.control, metadata, modelName);\n\n (this.control as SignatureControl).attachCapture(() => {\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n });\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current base64 signature image state.\n * @returns {unknown} The signature image value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as SignatureControl).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as sap.ui.core.Control).setProperty(\"readOnly\", !!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,+QAASA,EAAUC,EAAA,oBAGZC,EAAgBC,EAAAC,GAGhB,MAAMC,UAAwBL,EAW1BM,OAAOC,EAA8BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAClHC,KAAKD,SAAWA,EAChBC,KAAKL,SAAWA,EAChBK,KAAKC,SAAWL,EAAYM,QAAQ,IAAK,IACzCF,KAAKH,UAAYA,EAEjB,IAAKG,KAAKG,WAAY,CAElBH,KAAKI,QAAU,IAAIC,EAAa,CAC5BC,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCY,IAAK,IAAIX,KAAaD,KACtBa,MAAO,QACPC,IAAKf,EAASgB,IAAIC,OAAS,cAE/BZ,KAAKa,sBAAsBb,KAAKI,QAAST,EAAUE,GACnD,OAAOG,KAAKI,OAChB,CAEAJ,KAAKI,QAAU,IAAId,EAAiB,CAChCgB,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCkB,MAAO,IAAIjB,KAAaD,KACxBmB,eAAgBpB,EAChBqB,WAAYrB,EAASgB,IAAIK,WAG7BhB,KAAKa,sBAAsBb,KAAKI,QAAST,EAAUE,GAElDG,KAAKI,QAA6Ba,cAAc,KAC7C,MAAMC,EAASlB,KAAKmB,8BAChB,GAAInB,KAAKD,SAAU,CACfC,KAAKD,SAASmB,EAAOE,QAASpB,KAAKC,SACvC,IAGR,OAAOD,KAAKI,OAChB,CAMUiB,WACN,OAAOrB,KAAKI,QAAWJ,KAAKI,QAA6BiB,WAAa,IAC1E,CAKUC,aACN,GAAItB,KAAKI,SAAWJ,KAAKL,SAAU,CAC/B,IAAKK,KAAKG,WAAY,OACrBH,KAAKI,QAAgCmB,YAAY,aAAcvB,KAAKL,SAASgB,IAAIK,SACtF,CACJ,EACH,IAAAQ,EAAA,CAAAC,WAAA,MAAAD,EAAA/B,kBAAA,OAAA+B,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":51,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","SliderPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","startsWith","substring","isEditable","control","TextControl","id","generateStableId","text","applyCommonDirectives","Slider","value","enabled","ui","readOnly","min","minimum","undefined","max","maximum","step","multipleOf","enableTickmarks","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","getValue","applyState","setEnabled","__exports","__esModule"],"sources":["SliderPlugin.ts"],"sourcesContent":["/**\n * @file SliderPlugin.ts\n * @description Renders a sap.m.Slider for picking numbers in a range.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Slider from \"sap/m/Slider\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering logic for numeric sliders.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class SliderPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.Slider` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured Slider control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.startsWith('/') ? bindingPath.substring(1) : bindingPath;\n \n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new Slider({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n min: fieldMetadata.minimum !== undefined ? fieldMetadata.minimum : 0,\n max: fieldMetadata.maximum !== undefined ? fieldMetadata.maximum : 100,\n step: fieldMetadata.multipleOf !== undefined ? fieldMetadata.multipleOf : 1,\n enableTickmarks: true,\n change: (oEvent: sap.ui.base.Event) => {\n const val = (oEvent as sap.ui.base.Event).getParameter(\"value\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current slider value.\n * @returns {unknown} The numeric value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as Slider).getValue() : 0;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as Slider).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,uJAAA,MAKSA,EAAUC,EAAA,cAYZ,MAAMC,UAAqBF,EAWvBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,IAAKI,KAAKK,WAAY,CAElBL,KAAKM,QAAU,IAAIC,EAAY,CAC3BC,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCc,KAAM,IAAIb,KAAaD,OAE3BI,KAAKW,sBAAsBX,KAAKM,QAASX,EAAeE,GACxD,OAAOG,KAAKM,OAChB,CAEAN,KAAKM,QAAU,IAAIM,EAAO,CACtBJ,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCiB,MAAO,IAAIhB,KAAaD,KACxBkB,SAAUnB,EAAcoB,IAAIC,SAC5BC,IAAKtB,EAAcuB,UAAYC,UAAYxB,EAAcuB,QAAU,EACnEE,IAAKzB,EAAc0B,UAAYF,UAAYxB,EAAc0B,QAAU,IACnEC,KAAM3B,EAAc4B,aAAeJ,UAAYxB,EAAc4B,WAAa,EAC1EC,gBAAiB,KACjBC,OAASC,IACL,MAAMC,EAAOD,EAA6BE,aAAa,SACvD,MAAMC,EAAS7B,KAAK8B,8BACpB,GAAI9B,KAAKD,SAAU,CACfC,KAAKD,SAAS8B,EAAOE,QAAS/B,KAAKE,SACvC,KAIRF,KAAKW,sBAAsBX,KAAKM,QAASX,EAAeE,GAExD,OAAOG,KAAKM,OAChB,CAMU0B,WACN,OAAOhC,KAAKM,QAAWN,KAAKM,QAAmB0B,WAAa,CAChE,CAKUC,aACN,GAAIjC,KAAKM,SAAWN,KAAKC,SAAU,CAC/B,IAAKD,KAAKK,WAAY,OACrBL,KAAKM,QAAmB4B,YAAYlC,KAAKC,SAASc,IAAIC,SAC3D,CACJ,EACH,IAAAmB,EAAA,CAAAC,WAAA,MAAAD,EAAA1C,eAAA,OAAA0C,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":52,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","StepInputPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","startsWith","substring","isEditable","control","TextControl","id","generateStableId","text","applyCommonDirectives","StepInput","value","displayValuePrecision","scale","undefined","type","editable","ui","readOnly","required","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","getValue","applyState","input","setEditable","setRequired","__exports","__esModule"],"sources":["StepInputPlugin.ts"],"sourcesContent":["/**\n * @file StepInputPlugin.ts\n * @description Renders a sap.m.StepInput for numeric data requiring step increments.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport StepInput from \"sap/m/StepInput\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering and logic for step-based numeric inputs.\n */\nexport class StepInputPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.StepInput` component for numeric evaluation.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured StepInput control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.startsWith('/') ? bindingPath.substring(1) : bindingPath;\n\n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new StepInput({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n displayValuePrecision: fieldMetadata.scale !== undefined ? fieldMetadata.scale : (fieldMetadata.type === \"integer\" ? 0 : 3),\n editable: !fieldMetadata.ui?.readOnly,\n required: !!fieldMetadata.required,\n change: (oEvent: sap.ui.base.Event) => {\n const val = oEvent.getParameter(\"value\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current numeric state.\n * @returns {unknown} The numeric value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as StepInput).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const input = this.control as StepInput;\n input.setEditable(!this.metadata.ui?.readOnly);\n input.setRequired(!!this.metadata.required);\n }\n }\n}\n"],"mappings":"AAAA,6JAAA,MAKSA,EAAUC,EAAA,cASZ,MAAMC,UAAwBF,EAW1BG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,IAAKI,KAAKK,WAAY,CAElBL,KAAKM,QAAU,IAAIC,EAAY,CAC3BC,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCc,KAAM,IAAIb,KAAaD,OAE3BI,KAAKW,sBAAsBX,KAAKM,QAASX,EAAeE,GACxD,OAAOG,KAAKM,OAChB,CAEAN,KAAKM,QAAU,IAAIM,EAAU,CACzBJ,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCiB,MAAO,IAAIhB,KAAaD,KACxBkB,sBAAuBnB,EAAcoB,QAAUC,UAAYrB,EAAcoB,MAASpB,EAAcsB,OAAS,UAAY,EAAI,EACzHC,UAAWvB,EAAcwB,IAAIC,SAC7BC,WAAY1B,EAAc0B,SAC1BC,OAASC,IACL,MAAMC,EAAMD,EAAOE,aAAa,SAChC,MAAMC,EAAS1B,KAAK2B,8BACpB,GAAI3B,KAAKD,SAAU,CACfC,KAAKD,SAAS2B,EAAOE,QAAS5B,KAAKE,SACvC,KAIRF,KAAKW,sBAAsBX,KAAKM,QAASX,EAAeE,GAExD,OAAOG,KAAKM,OAChB,CAMUuB,WACN,OAAO7B,KAAKM,QAAWN,KAAKM,QAAsBuB,WAAa,IACnE,CAKUC,aACN,GAAI9B,KAAKM,SAAWN,KAAKC,SAAU,CAC/B,IAAKD,KAAKK,WAAY,OACtB,MAAM0B,EAAQ/B,KAAKM,QACnByB,EAAMC,aAAahC,KAAKC,SAASkB,IAAIC,UACrCW,EAAME,cAAcjC,KAAKC,SAASoB,SACtC,CACJ,EACH,IAAAa,EAAA,CAAAC,WAAA,MAAAD,EAAAzC,kBAAA,OAAAyC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":53,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","StringPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","replace","isEditable","control","TextControl","id","generateStableId","text","applyCommonDirectives","Input","value","maxLength","required","showValueHelp","ui","widget","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","getValue","applyState","input","setEditable","readOnly","setRequired","__exports","__esModule"],"sources":["StringPlugin.ts"],"sourcesContent":["/**\n * @file StringPlugin.ts\n * @description Renders a sap.m.Input for string data and validates lengths.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Input from \"sap/m/Input\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering and logic for basic text inputs.\n * Maps schema properties like `maxLength` and `required` natively to `sap.m.Input`.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.controls\n * @public\n */\nexport class StringPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.Input` control configured via the provided schema metadata.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured Input control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.replace(\"/\", \"\"); // For EventBus\n \n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new Input({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n maxLength: fieldMetadata.maxLength || 0,\n required: !!fieldMetadata.required,\n showValueHelp: fieldMetadata.ui?.widget === \"searchHelp\",\n change: (oEvent: sap.ui.base.Event) => {\n const val = (oEvent as sap.ui.base.Event).getParameter(\"value\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current string value from the input.\n * @returns {unknown} The string value.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as Input).getValue() : null;\n }\n\n /**\n * Adjusts dynamic state properties (editable/required) based on ConditionEngine mutations.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) {\n // Text doesn't have editable/required state\n return;\n }\n const input = this.control as Input;\n input.setEditable(!this.metadata.ui?.readOnly);\n input.setRequired(this.metadata.required);\n }\n }\n}\n"],"mappings":"AAAA,sJAAA,MAKSA,EAAUC,EAAA,cAaZ,MAAMC,UAAqBF,EAWvBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,QAAQ,IAAK,IAEzC,IAAKH,KAAKI,WAAY,CAElBJ,KAAKK,QAAU,IAAIC,EAAY,CAC3BC,GAAIP,KAAKQ,iBAAiBV,EAAeF,GACzCa,KAAM,IAAIZ,KAAaD,OAE3BI,KAAKU,sBAAsBV,KAAKK,QAASV,EAAeE,GACxD,OAAOG,KAAKK,OAChB,CAEAL,KAAKK,QAAU,IAAIM,EAAM,CACrBJ,GAAIP,KAAKQ,iBAAiBV,EAAeF,GACzCgB,MAAO,IAAIf,KAAaD,KACxBiB,UAAWlB,EAAckB,WAAa,EACtCC,WAAYnB,EAAcmB,SAC1BC,cAAepB,EAAcqB,IAAIC,SAAW,aAC5CC,OAASC,IACL,MAAMC,EAAOD,EAA6BE,aAAa,SACvD,MAAMC,EAAStB,KAAKuB,8BACpB,GAAIvB,KAAKD,SAAU,CACfC,KAAKD,SAASuB,EAAOE,QAASxB,KAAKE,SACvC,KAIRF,KAAKU,sBAAsBV,KAAKK,QAASV,EAAeE,GAExD,OAAOG,KAAKK,OAChB,CAMUoB,WACN,OAAOzB,KAAKK,QAAWL,KAAKK,QAAkBoB,WAAa,IAC/D,CAKUC,aACN,GAAI1B,KAAKK,SAAWL,KAAKC,SAAU,CAC/B,IAAKD,KAAKI,WAAY,CAElB,MACJ,CACA,MAAMuB,EAAQ3B,KAAKK,QACnBsB,EAAMC,aAAa5B,KAAKC,SAASe,IAAIa,UACrCF,EAAMG,YAAY9B,KAAKC,SAASa,SACpC,CACJ,EACH,IAAAiB,EAAA,CAAAC,WAAA,MAAAD,EAAAtC,eAAA,OAAAsC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":54,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","SwitchPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","startsWith","substring","isEditable","control","TextControl","id","generateStableId","text","path","formatter","val","applyCommonDirectives","Switch","state","enabled","ui","readOnly","change","oEvent","getParameter","result","validateAndApplyVisualState","isValid","getValue","getState","applyState","sw","setEnabled","__exports","__esModule"],"sources":["SwitchPlugin.ts"],"sourcesContent":["/**\n * @file SwitchPlugin.ts\n * @description Renders a sap.m.Switch for boolean data specifically marked with the switch widget.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Switch from \"sap/m/Switch\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering logic for toggleable boolean switches.\n */\nexport class SwitchPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.Switch` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured Switch control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.startsWith('/') ? bindingPath.substring(1) : bindingPath;\n\n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n formatter: (val: boolean) => val ? \"Yes\" : \"No\"\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new Switch({\n id: this.generateStableId(engineScopeId, bindingPath),\n state: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n change: (oEvent: sap.ui.base.Event) => {\n const val = (oEvent as sap.ui.base.Event).getParameter(\"state\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current switch state.\n * @returns {unknown} The boolean state.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as Switch).getState() : false;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const sw = this.control as Switch;\n sw.setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,uJAAA,MAKSA,EAAUC,EAAA,cASZ,MAAMC,UAAqBF,EAWvBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,IAAKI,KAAKK,WAAY,CAElBL,KAAKM,QAAU,IAAIC,EAAY,CAC3BC,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCc,KAAM,CACFC,KAAM,GAAGd,KAAaD,IACtBgB,UAAYC,GAAiBA,EAAM,MAAQ,QAGnDb,KAAKc,sBAAsBd,KAAKM,QAASX,EAAeE,GACxD,OAAOG,KAAKM,OAChB,CAEAN,KAAKM,QAAU,IAAIS,EAAO,CACtBP,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCoB,MAAO,IAAInB,KAAaD,KACxBqB,SAAUtB,EAAcuB,IAAIC,SAC5BC,OAASC,IACL,MAAMR,EAAOQ,EAA6BC,aAAa,SACvD,MAAMC,EAASvB,KAAKwB,8BACpB,GAAIxB,KAAKD,SAAU,CACfC,KAAKD,SAASwB,EAAOE,QAASzB,KAAKE,SACvC,KAIRF,KAAKc,sBAAsBd,KAAKM,QAASX,EAAeE,GAExD,OAAOG,KAAKM,OAChB,CAMUoB,WACN,OAAO1B,KAAKM,QAAWN,KAAKM,QAAmBqB,WAAa,KAChE,CAKUC,aACN,GAAI5B,KAAKM,SAAWN,KAAKC,SAAU,CAC/B,IAAKD,KAAKK,WAAY,OACtB,MAAMwB,EAAK7B,KAAKM,QAChBuB,EAAGC,YAAY9B,KAAKC,SAASiB,IAAIC,SACrC,CACJ,EACH,IAAAY,EAAA,CAAAC,WAAA,MAAAD,EAAAtC,eAAA,OAAAsC,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":55,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","TextAreaPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","replace","isEditable","control","TextControl","id","generateStableId","text","applyCommonDirectives","TextArea","value","maxLength","required","rows","growing","change","oEvent","updateHeight","getSource","result","validateAndApplyVisualState","isValid","liveChange","attachEventOnce","oBinding","getBinding","initLogic","attachChange","oTextArea","val","getValue","numLines","split","length","wrappedLines","Math","ceil","totalLines","max","setRows","applyState","input","setEditable","ui","readOnly","setRequired","__exports","__esModule"],"sources":["TextAreaPlugin.ts"],"sourcesContent":["/**\n * @file TextAreaPlugin.ts\n * @description Renders a sap.m.TextArea for string data specifically marked with the textArea widget.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport TextArea from \"sap/m/TextArea\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering and logic for multi-line text areas.\n */\nexport class TextAreaPlugin extends BasePlugin {\n /**\n * Renders a `sap.m.TextArea` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured TextArea control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.replace(\"/\", \"\"); // For EventBus\n \n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}`\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new TextArea({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n maxLength: fieldMetadata.maxLength || 0,\n required: !!fieldMetadata.required,\n rows: 3, // Start with at least 3 lines\n growing: false, // We manage height manually to maintain the +2 lines requirement\n change: (oEvent: sap.ui.base.Event) => {\n this.updateHeight(oEvent.getSource() as TextArea);\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n },\n liveChange: (oEvent: sap.ui.base.Event) => {\n this.updateHeight(oEvent.getSource() as TextArea);\n }\n });\n\n // Clean architecture: Wait for the model context, then calculate initial height\n (this.control as TextArea).attachEventOnce(\"modelContextChange\", () => {\n const oBinding = (this.control as TextArea).getBinding(\"value\");\n \n const initLogic = () => {\n if (this.control) {\n this.updateHeight(this.control as TextArea);\n }\n };\n\n if (oBinding) {\n oBinding.attachChange(initLogic);\n }\n // Execute immediately in case the model is synchronous (JSONModel)\n initLogic();\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Dynamically sets the rows to the content length + 2\n */\n private updateHeight(oTextArea: TextArea): void {\n const val = oTextArea.getValue() || \"\";\n // Count actual newlines in the string\n const numLines = val.split(/\\r\\n|\\r|\\n/).length;\n // Also estimate word wrapping if they type a really long single line without pressing enter\n // A standard character width approximation, assuming ~80 chars per line for full width\n const wrappedLines = Math.ceil(val.length / 80);\n \n const totalLines = Math.max(numLines, wrappedLines);\n \n // Ensure there is always 2 lines of extra breathing room\n oTextArea.setRows(Math.max(3, totalLines + 2));\n }\n\n /**\n * Retrieves the current text string.\n * @returns {unknown} The text string.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as TextArea).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const input = this.control as TextArea;\n input.setEditable(!this.metadata.ui?.readOnly);\n input.setRequired(this.metadata.required);\n }\n }\n}\n"],"mappings":"AAAA,2JAAA,MAKSA,EAAUC,EAAA,cASZ,MAAMC,UAAuBF,EAWzBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,QAAQ,IAAK,IAEzC,IAAKH,KAAKI,WAAY,CAElBJ,KAAKK,QAAU,IAAIC,EAAY,CAC3BC,GAAIP,KAAKQ,iBAAiBV,EAAeF,GACzCa,KAAM,IAAIZ,KAAaD,OAE3BI,KAAKU,sBAAsBV,KAAKK,QAASV,EAAeE,GACxD,OAAOG,KAAKK,OAChB,CAEAL,KAAKK,QAAU,IAAIM,EAAS,CACxBJ,GAAIP,KAAKQ,iBAAiBV,EAAeF,GACzCgB,MAAO,IAAIf,KAAaD,KACxBiB,UAAWlB,EAAckB,WAAa,EACtCC,WAAYnB,EAAcmB,SAC1BC,KAAM,EACNC,QAAS,MACTC,OAASC,IACLlB,KAAKmB,aAAaD,EAAOE,aACzB,MAAMC,EAASrB,KAAKsB,8BACpB,GAAItB,KAAKD,SAAU,CACfC,KAAKD,SAASsB,EAAOE,QAASvB,KAAKE,SACvC,GAEJsB,WAAaN,IACTlB,KAAKmB,aAAaD,EAAOE,gBAKhCpB,KAAKK,QAAqBoB,gBAAgB,qBAAsB,KAC7D,MAAMC,EAAY1B,KAAKK,QAAqBsB,WAAW,SAEvD,MAAMC,EAAYA,KACd,GAAI5B,KAAKK,QAAS,CACdL,KAAKmB,aAAanB,KAAKK,QAC3B,GAGJ,GAAIqB,EAAU,CACVA,EAASG,aAAaD,EAC1B,CAEAA,MAGJ5B,KAAKU,sBAAsBV,KAAKK,QAASV,EAAeE,GAExD,OAAOG,KAAKK,OAChB,CAKQc,aAAaW,GACjB,MAAMC,EAAMD,EAAUE,YAAc,GAEpC,MAAMC,EAAWF,EAAIG,MAAM,cAAcC,OAGzC,MAAMC,EAAeC,KAAKC,KAAKP,EAAII,OAAS,IAE5C,MAAMI,EAAaF,KAAKG,IAAIP,EAAUG,GAGtCN,EAAUW,QAAQJ,KAAKG,IAAI,EAAGD,EAAa,GAC/C,CAMUP,WACN,OAAOhC,KAAKK,QAAWL,KAAKK,QAAqB2B,WAAa,IAClE,CAKUU,aACN,GAAI1C,KAAKK,SAAWL,KAAKC,SAAU,CAC/B,IAAKD,KAAKI,WAAY,OACtB,MAAMuC,EAAQ3C,KAAKK,QACnBsC,EAAMC,aAAa5C,KAAKC,SAAS4C,IAAIC,UACrCH,EAAMI,YAAY/C,KAAKC,SAASa,SACpC,CACJ,EACH,IAAAkC,EAAA,CAAAC,WAAA,MAAAD,EAAAvD,iBAAA,OAAAuD,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":56,"column":0},"map":{"version":3,"names":["BasePlugin","___BasePlugin","TimePlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","fieldKey","startsWith","substring","isEditable","control","TextControl","id","generateStableId","text","path","type","formatOptions","source","pattern","applyCommonDirectives","TimePicker","value","displayFormat","editable","ui","readOnly","required","change","oEvent","val","getParameter","result","validateAndApplyVisualState","isValid","getValue","applyState","input","setEditable","setRequired","__exports","__esModule"],"sources":["TimePlugin.ts"],"sourcesContent":["/**\n * @file TimePlugin.ts\n * @description Handles rendering logic for Time strings.\n */\n\nimport { BasePlugin } from \"./BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport TimePicker from \"sap/m/TimePicker\";\nimport Control from \"sap/ui/core/Control\";\nimport TextControl from \"sap/m/Text\";\n\n/**\n * Handles rendering and logic for time inputs.\n */\nexport class TimePlugin extends BasePlugin {\n /**\n * Renders a `sap.m.TimePicker` component.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured TimePicker control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n this.fieldKey = bindingPath.startsWith('/') ? bindingPath.substring(1) : bindingPath;\n \n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n type: \"sap.ui.model.type.Time\",\n formatOptions: {\n source: { pattern: \"HH:mm:ss\" },\n pattern: \"HH:mm:ss\"\n }\n }\n });\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n this.control = new TimePicker({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: {\n path: `${modelName}>${bindingPath}`,\n type: \"sap.ui.model.type.Time\",\n formatOptions: {\n source: { pattern: \"HH:mm:ss\" },\n pattern: \"HH:mm:ss\"\n }\n },\n displayFormat: \"HH:mm:ss\",\n editable: !fieldMetadata.ui?.readOnly,\n required: fieldMetadata.required,\n change: (oEvent: sap.ui.base.Event) => {\n const val = (oEvent as sap.ui.base.Event).getParameter(\"value\");\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current time string.\n * @returns {unknown} The time string.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as TimePicker).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const input = this.control as TimePicker;\n input.setEditable(!this.metadata.ui?.readOnly);\n input.setRequired(this.metadata.required);\n }\n }\n}\n"],"mappings":"AAAA,yJAAA,MAKSA,EAAUC,EAAA,cASZ,MAAMC,UAAmBF,EAWrBG,OAAOC,EAAmCC,EAAsBC,EAAoB,OAAQC,EAAwBC,GACvHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAChBK,KAAKE,SAAWN,EAAYO,WAAW,KAAOP,EAAYQ,UAAU,GAAKR,EAEzE,IAAKI,KAAKK,WAAY,CAElBL,KAAKM,QAAU,IAAIC,EAAY,CAC3BC,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCc,KAAM,CACFC,KAAM,GAAGd,KAAaD,IACtBgB,KAAM,yBACNC,cAAe,CACXC,OAAQ,CAAEC,QAAS,YACnBA,QAAS,eAIrBf,KAAKgB,sBAAsBhB,KAAKM,QAASX,EAAeE,GACxD,OAAOG,KAAKM,OAChB,CAEAN,KAAKM,QAAU,IAAIW,EAAW,CAC1BT,GAAIR,KAAKS,iBAAiBX,EAAeF,GACzCsB,MAAO,CACHP,KAAM,GAAGd,KAAaD,IACtBgB,KAAM,yBACNC,cAAe,CACXC,OAAQ,CAAEC,QAAS,YACnBA,QAAS,aAGjBI,cAAe,WACfC,UAAWzB,EAAc0B,IAAIC,SAC7BC,SAAU5B,EAAc4B,SACxBC,OAASC,IACL,MAAMC,EAAOD,EAA6BE,aAAa,SACvD,MAAMC,EAAS5B,KAAK6B,8BACpB,GAAI7B,KAAKD,SAAU,CACfC,KAAKD,SAAS6B,EAAOE,QAAS9B,KAAKE,SACvC,KAIRF,KAAKgB,sBAAsBhB,KAAKM,QAASX,EAAeE,GAExD,OAAOG,KAAKM,OAChB,CAMUyB,WACN,OAAO/B,KAAKM,QAAWN,KAAKM,QAAuByB,WAAa,IACpE,CAKUC,aACN,GAAIhC,KAAKM,SAAWN,KAAKC,SAAU,CAC/B,IAAKD,KAAKK,WAAY,OACtB,MAAM4B,EAAQjC,KAAKM,QACnB2B,EAAMC,aAAalC,KAAKC,SAASoB,IAAIC,UACrCW,EAAME,YAAYnC,KAAKC,SAASsB,SACpC,CACJ,EACH,IAAAa,EAAA,CAAAC,WAAA,MAAAD,EAAA3C,aAAA,OAAA2C,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":57,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","VoiceInputControl","_interopRequireDefault","__VoiceInputControl","VoiceInputPlugin","render","metadata","bindingPath","modelName","engineScopeId","onChange","this","fieldKey","replace","isEditable","control","TextControl","id","generateStableId","text","path","formatter","val","applyCommonDirectives","value","schemaMetadata","readOnly","ui","attachCapture","result","validateAndApplyVisualState","isValid","getValue","applyState","setProperty","__exports","__esModule"],"sources":["VoiceInputPlugin.ts"],"sourcesContent":["import { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport Control from \"sap/ui/core/Control\";\nimport VoiceInputControl from \"../../controls/VoiceInputControl\";\nimport TextControl from \"sap/m/Text\";\n\nexport class VoiceInputPlugin extends BasePlugin {\n /**\n * Renders a `VoiceInputControl` component.\n * \n * @param metadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured VoiceInputControl.\n */\n public render(metadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = metadata;\n this.fieldKey = bindingPath.replace('/', '');\n this.modelName = modelName;\n\n if (!this.isEditable) {\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: {\n path: `${modelName}>${bindingPath}`,\n formatter: (val: unknown) => {\n if (!val || val === \"undefined\" || val === \"null\") return \"\";\n return val;\n }\n }\n }) as Control;\n this.applyCommonDirectives(this.control, metadata, modelName);\n return this.control as Control;\n }\n\n this.control = new VoiceInputControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n value: `{${modelName}>${bindingPath}}`,\n schemaMetadata: metadata,\n readOnly: !!metadata.ui?.readOnly\n }) as Control;\n\n this.applyCommonDirectives(this.control, metadata, modelName);\n\n (this.control as VoiceInputControl).attachCapture(() => {\n const result = this.validateAndApplyVisualState();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n });\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current voice transcription text.\n * @returns {unknown} The text string.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as VoiceInputControl).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n (this.control as sap.ui.core.Control).setProperty(\"readOnly\", !!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,gRAASA,EAAUC,EAAA,oBAGZC,EAAiBC,EAAAC,GAGjB,MAAMC,UAAyBL,EAW3BM,OAAOC,EAA8BC,EAAsBC,EAAoB,OAAQC,EAAwBC,GAClHC,KAAKD,SAAWA,EAChBC,KAAKL,SAAWA,EAChBK,KAAKC,SAAWL,EAAYM,QAAQ,IAAK,IACzCF,KAAKH,UAAYA,EAEjB,IAAKG,KAAKG,WAAY,CAElBH,KAAKI,QAAU,IAAIC,EAAY,CAC3BC,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCY,KAAM,CACFC,KAAM,GAAGZ,KAAaD,IACtBc,UAAYC,IACR,IAAKA,GAAOA,IAAQ,aAAeA,IAAQ,OAAQ,MAAO,GAC1D,OAAOA,MAInBX,KAAKY,sBAAsBZ,KAAKI,QAAST,EAAUE,GACnD,OAAOG,KAAKI,OAChB,CAEAJ,KAAKI,QAAU,IAAId,EAAkB,CACjCgB,GAAIN,KAAKO,iBAAiBT,EAAeF,GACzCiB,MAAO,IAAIhB,KAAaD,KACxBkB,eAAgBnB,EAChBoB,WAAYpB,EAASqB,IAAID,WAG7Bf,KAAKY,sBAAsBZ,KAAKI,QAAST,EAAUE,GAElDG,KAAKI,QAA8Ba,cAAc,KAC9C,MAAMC,EAASlB,KAAKmB,8BAChB,GAAInB,KAAKD,SAAU,CACfC,KAAKD,SAASmB,EAAOE,QAASpB,KAAKC,SACvC,IAGR,OAAOD,KAAKI,OAChB,CAMUiB,WACN,OAAOrB,KAAKI,QAAWJ,KAAKI,QAA8BiB,WAAa,IAC3E,CAKUC,aACN,GAAItB,KAAKI,SAAWJ,KAAKL,SAAU,CAC/B,IAAKK,KAAKG,WAAY,OACrBH,KAAKI,QAAgCmB,YAAY,aAAcvB,KAAKL,SAASqB,IAAID,SACtF,CACJ,EACH,IAAAS,EAAA,CAAAC,WAAA,MAAAD,EAAA/B,mBAAA,OAAA+B,CAAA","ignoreList":[],"sourceRoot":"plugins/controls"}},{"offset":{"line":58,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","Logger","____utils_Logger","LiveSearchPlugin","render","fieldMetadata","bindingPath","modelName","this","metadata","input","Input","value","enabled","ui","readOnly","placeholder","showSuggestion","suggest","oEvent","query","getParameter","fetchSuggestions","change","validate","control","vhConfig","valueHelp","url","error","removeAllSuggestionItems","setBusy","fetch","then","res","json","data","keyPath","textPath","lowerQuery","toLowerCase","filteredData","filter","item","textValue","String","includes","forEach","itemData","addSuggestionItem","Item","key","text","catch","err","message","finally","getValue","applyState","setEnabled","__exports","__esModule"],"sources":["LiveSearchPlugin.ts"],"sourcesContent":["/**\n * @file LiveSearchPlugin.ts\n * @description A custom datasource plugin that provides asynchronous live search (autocomplete) functionality.\n */\n\nimport { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata, IRemoteValueHelpConfig } from \"../../interfaces/ISchema\";\nimport Input from \"sap/m/Input\";\nimport Item from \"sap/ui/core/Item\";\nimport Control from \"sap/ui/core/Control\";\nimport { Logger } from \"../../utils/Logger\";\n\n/**\n * A custom datasource plugin that provides asynchronous live search (autocomplete) functionality.\n * As the user types, it fetches suggestions from a remote endpoint.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.datasources\n * @public\n */\nexport class LiveSearchPlugin extends BasePlugin {\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\"): Control {\n this.metadata = fieldMetadata;\n \n const input = new Input({\n value: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n placeholder: \"Type to search...\",\n showSuggestion: true,\n suggest: (oEvent: sap.ui.base.Event) => {\n const query = (oEvent as sap.ui.base.Event).getParameter(\"suggestValue\");\n this.fetchSuggestions(input, query);\n },\n change: (oEvent: sap.ui.base.Event) => {\n this.validate();\n }\n });\n\n this.control = input;\n return this.control as Control;\n }\n\n /**\n * Executes the REST fetch for suggestions based on a query. Can be overridden by mock subclasses.\n * @param input The UI5 Input to populate with suggestions.\n * @param query The text typed by the user.\n */\n protected fetchSuggestions(input: Input, query: string): void {\n const vhConfig = this.metadata?.valueHelp as IRemoteValueHelpConfig;\n if (!vhConfig || !vhConfig.url) {\n Logger.error(\"LiveSearchPlugin requires a valid valueHelp configuration with a URL.\", \"\", \"LiveSearchPlugin\");\n return;\n }\n\n if (!query) {\n input.removeAllSuggestionItems();\n return;\n }\n \n input.setBusy(true);\n \n // In a real application, the query parameter would be passed to the backend (e.g. ?q=query)\n // Here, we simulate fetching and filter locally, but subclasses can override this entirely.\n fetch(vhConfig.url)\n .then(res => res.json())\n .then((data: Record<string, unknown>[]) => {\n const keyPath = vhConfig.keyPath || \"key\";\n const textPath = vhConfig.textPath || \"text\";\n \n input.removeAllSuggestionItems();\n\n // Simple client-side filter for demonstration\n const lowerQuery = query.toLowerCase();\n const filteredData = data.filter(item => {\n const textValue = String(item[textPath] || item[keyPath]).toLowerCase();\n return textValue.includes(lowerQuery);\n });\n \n filteredData.forEach(itemData => {\n input.addSuggestionItem(new Item({ \n key: itemData[keyPath], \n text: itemData[textPath] || itemData[keyPath]\n }));\n });\n })\n .catch(err => {\n Logger.error(\"Failed to load value help from \" + vhConfig.url, err.message, \"LiveSearchPlugin\");\n })\n .finally(() => {\n input.setBusy(false);\n });\n }\n\n /**\n * Retrieves the current input value.\n * @returns {unknown} The input text.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as Input).getValue() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n (this.control as Input).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,oMAAA,MAKSA,EAAUC,EAAA,oBAKVC,EAAMC,EAAA,UASR,MAAMC,UAAyBJ,EAC3BK,OAAOC,EAAkCC,EAAqBC,EAAoB,QACrFC,KAAKC,SAAWJ,EAEhB,MAAMK,EAAQ,IAAIC,EAAM,CACpBC,MAAO,IAAIL,KAAaD,KACxBO,SAAUR,EAAcS,IAAIC,SAC5BC,YAAa,oBACbC,eAAgB,KAChBC,QAAUC,IACN,MAAMC,EAASD,EAA6BE,aAAa,gBACzDb,KAAKc,iBAAiBZ,EAAOU,IAEjCG,OAASJ,IACLX,KAAKgB,cAIbhB,KAAKiB,QAAUf,EACf,OAAOF,KAAKiB,OAChB,CAOUH,iBAAiBZ,EAAcU,GACrC,MAAMM,EAAWlB,KAAKC,UAAUkB,UAChC,IAAKD,IAAaA,EAASE,IAAK,CAC5B3B,EAAO4B,MAAM,wEAAyE,GAAI,oBAC1F,MACJ,CAEA,IAAKT,EAAO,CACRV,EAAMoB,2BACN,MACJ,CAEApB,EAAMqB,QAAQ,MAIdC,MAAMN,EAASE,KACVK,KAAKC,GAAOA,EAAIC,QAChBF,KAAMG,IACH,MAAMC,EAAUX,EAASW,SAAW,MACpC,MAAMC,EAAWZ,EAASY,UAAY,OAEtC5B,EAAMoB,2BAGN,MAAMS,EAAanB,EAAMoB,cACzB,MAAMC,EAAeL,EAAKM,OAAOC,IAC7B,MAAMC,EAAYC,OAAOF,EAAKL,IAAaK,EAAKN,IAAUG,cAC1D,OAAOI,EAAUE,SAASP,KAG9BE,EAAaM,QAAQC,IACjBtC,EAAMuC,kBAAkB,IAAIC,EAAK,CAC7BC,IAAKH,EAASX,GACde,KAAMJ,EAASV,IAAaU,EAASX,UAIhDgB,MAAMC,IACHrD,EAAO4B,MAAM,kCAAoCH,EAASE,IAAK0B,EAAIC,QAAS,sBAE/EC,QAAQ,KACL9C,EAAMqB,QAAQ,QAE1B,CAMU0B,WACN,OAAOjD,KAAKiB,QAAWjB,KAAKiB,QAAkBgC,WAAa,IAC/D,CAKUC,aACN,GAAIlD,KAAKiB,SAAWjB,KAAKC,SAAU,CAC9BD,KAAKiB,QAAkBkC,YAAYnD,KAAKC,SAASK,IAAIC,SAC1D,CACJ,EACH,IAAA6C,EAAA,CAAAC,WAAA,MAAAD,EAAAzD,mBAAA,OAAAyD,CAAA","ignoreList":[],"sourceRoot":"plugins/datasources"}},{"offset":{"line":59,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","ODataListBindingPlugin","render","fieldMetadata","bindingPath","modelName","this","metadata","args","ui","path","key","text","control","ComboBox","selectedKey","enabled","readOnly","placeholder","label","change","oEvent","val","getParameter","getKey","validate","bindAggregation","template","Item","templateShareable","getValue","getSelectedKey","applyState","setEnabled","__exports","__esModule"],"sources":["ODataListBindingPlugin.ts"],"sourcesContent":["/**\n * @file ODataListBindingPlugin.ts\n * @description A custom datasource plugin that binds a ComboBox to an OData EntitySet.\n */\n\nimport { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata } from \"../../interfaces/ISchema\";\nimport ComboBox from \"sap/m/ComboBox\";\nimport Item from \"sap/ui/core/Item\";\nimport Control from \"sap/ui/core/Control\";\n\n/**\n * Renders a ComboBox natively bound to an OData Model entity set.\n * Expects args: { path: \"/Categories\", key: \"ID\", text: \"Name\" }\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.datasources\n * @public\n */\nexport class ODataListBindingPlugin extends BasePlugin {\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\"): Control {\n this.metadata = fieldMetadata;\n \n const args = fieldMetadata.ui?.args || { path: \"/\", key: \"ID\", text: \"Name\" };\n \n this.control = new ComboBox({\n selectedKey: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n placeholder: fieldMetadata.ui?.label || \"Select...\",\n change: (oEvent: sap.ui.base.Event) => {\n const val = (oEvent as sap.ui.base.Event).getParameter(\"selectedItem\")?.getKey();\n this.validate();\n }\n });\n\n // Natively bind aggregation to the default model (OData)\n (this.control as ComboBox).bindAggregation(\"items\", {\n path: args.path,\n template: new Item({\n key: `{${args.key}}`,\n text: `{${args.text}}`\n }),\n templateShareable: false\n });\n\n return this.control as Control;\n }\n\n /**\n * Retrieves the current selected key.\n * @returns {unknown} The selected key.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as ComboBox).getSelectedKey() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n (this.control as ComboBox).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,sLAAA,MAKSA,EAAUC,EAAA,cAaZ,MAAMC,UAA+BF,EACjCG,OAAOC,EAAkCC,EAAqBC,EAAoB,QACrFC,KAAKC,SAAWJ,EAEhB,MAAMK,EAAOL,EAAcM,IAAID,MAAQ,CAAEE,KAAM,IAAKC,IAAK,KAAMC,KAAM,QAErEN,KAAKO,QAAU,IAAIC,EAAS,CACxBC,YAAa,IAAIV,KAAaD,KAC9BY,SAAUb,EAAcM,IAAIQ,SAC5BC,YAAaf,EAAcM,IAAIU,OAAS,YACxCC,OAASC,IACL,MAAMC,EAAOD,EAA6BE,aAAa,iBAAiBC,SACxElB,KAAKmB,cAKZnB,KAAKO,QAAqBa,gBAAgB,QAAS,CAChDhB,KAAMF,EAAKE,KACXiB,SAAU,IAAIC,EAAK,CACfjB,IAAK,IAAIH,EAAKG,OACdC,KAAM,IAAIJ,EAAKI,UAEnBiB,kBAAmB,QAGvB,OAAOvB,KAAKO,OAChB,CAMUiB,WACN,OAAOxB,KAAKO,QAAWP,KAAKO,QAAqBkB,iBAAmB,IACxE,CAKUC,aACN,GAAI1B,KAAKO,SAAWP,KAAKC,SAAU,CAC9BD,KAAKO,QAAqBoB,YAAY3B,KAAKC,SAASE,IAAIQ,SAC7D,CACJ,EACH,IAAAiB,EAAA,CAAAC,WAAA,MAAAD,EAAAjC,yBAAA,OAAAiC,CAAA","ignoreList":[],"sourceRoot":"plugins/datasources"}},{"offset":{"line":60,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","Logger","____utils_Logger","RemoteDropdownPlugin","render","fieldMetadata","bindingPath","modelName","engineScopeId","onChange","this","metadata","config","valueHelp","url","warn","sap","m","Text","text","isEditable","ui","requireSync","TextControl","require","control","id","generateStableId","applyCommonDirectives","select","Select","selectedKey","enabled","readOnly","forceSelection","busy","change","oEvent","result","validate","isValid","fieldKey","addItem","Item","key","fetch","then","res","ok","Error","status","json","data","arr","Array","isArray","value","forEach","item","k","keyPath","t","textPath","String","setBusy","catch","err","error","message","getValue","getSelectedKey","applyState","setEnabled","__exports","__esModule"],"sources":["RemoteDropdownPlugin.ts"],"sourcesContent":["/**\n * @file RemoteDropdownPlugin.ts\n * @description Renders a sap.m.Select that fetches valueHelp remotely via a JSON URL.\n */\n\nimport { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata, IRemoteValueHelpConfig } from \"../../interfaces/ISchema\";\nimport Select from \"sap/m/Select\";\nimport Item from \"sap/ui/core/Item\";\nimport Control from \"sap/ui/core/Control\";\nimport { Logger } from \"../../utils/Logger\";\n\n/**\n * Handles rendering logic for dropdown inputs fetching data remotely.\n * Maps a URL response array to `sap.ui.core.Item` elements.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.datasources\n * @public\n */\nexport class RemoteDropdownPlugin extends BasePlugin {\n \n /**\n * Renders a `Select` dropdown that fetches data remotely.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @param engineScopeId The deterministic scope ID.\n * @param onChange The callback fired on value change.\n * @returns {Control} The configured Select control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\", engineScopeId?: string, onChange?: (isValid: boolean, fieldKey?: string) => void): Control {\n this.onChange = onChange;\n this.metadata = fieldMetadata;\n\n const config = fieldMetadata.valueHelp as IRemoteValueHelpConfig;\n if (!config || !config.url) {\n Logger.warn(\"[MetaUI RemoteDropdownPlugin] No valid URL provided for remoteDropdown.\");\n return new sap.m.Text({ text: \"Error: No URL provided\" }) as Control;\n }\n \n if (!this.isEditable) {\n sap.ui.requireSync(\"sap/m/Text\");\n const TextControl = sap.ui.require(\"sap/m/Text\");\n \n this.control = new TextControl({\n id: this.generateStableId(engineScopeId, bindingPath),\n text: `{${modelName}>${bindingPath}}` // We might not have the text mapping synchronously\n });\n \n // Optionally, we could fetch data and update the text formatter here\n \n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n const select = new Select({\n id: this.generateStableId(engineScopeId, bindingPath),\n selectedKey: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n forceSelection: false,\n busy: true, // Show busy indicator while fetching\n change: (oEvent: sap.ui.base.Event) => {\n const result = this.validate();\n if (this.onChange) {\n this.onChange(result.isValid, this.fieldKey);\n }\n }\n });\n\n // Add empty placeholder\n select.addItem(new Item({ key: \"\", text: \"--- Select ---\" }));\n\n // Fetch data remotely\n fetch(config.url)\n .then(res => {\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n })\n .then(data => {\n const arr = Array.isArray(data) ? data : (data.value || []);\n arr.forEach((item: Record<string, unknown>) => {\n const k = config.keyPath ? item[config.keyPath] : item;\n const t = config.textPath ? item[config.textPath] : item;\n select.addItem(new Item({ key: String(k), text: String(t) }));\n });\n select.setBusy(false);\n })\n .catch(err => {\n Logger.error(`[MetaUI RemoteDropdownPlugin] Failed to fetch remote data from ${config.url}`, err.message);\n select.addItem(new Item({ key: \"\", text: \"Error loading data\" }));\n select.setBusy(false);\n });\n\n this.control = select;\n this.applyCommonDirectives(this.control, fieldMetadata, modelName);\n return this.control as Control;\n }\n\n /**\n * Retrieves the current selected key.\n * @returns {unknown} The selected key.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as Select).getSelectedKey() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n if (!this.isEditable) return;\n const select = this.control as Select;\n select.setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,yMAAA,MAKSA,EAAUC,EAAA,oBAKVC,EAAMC,EAAA,UASR,MAAMC,UAA6BJ,EAY/BK,OAAOC,EAAkCC,EAAqBC,EAAoB,OAAQC,EAAwBC,GACrHC,KAAKD,SAAWA,EAChBC,KAAKC,SAAWN,EAEhB,MAAMO,EAASP,EAAcQ,UAC7B,IAAKD,IAAWA,EAAOE,IAAK,CACxBb,EAAOc,KAAK,2EACZ,OAAO,IAAIC,IAAIC,EAAEC,KAAK,CAAEC,KAAM,0BAClC,CAEA,IAAKT,KAAKU,WAAY,CAClBJ,IAAIK,GAAGC,YAAY,cACnB,MAAMC,EAAcP,IAAIK,GAAGG,QAAQ,cAEnCd,KAAKe,QAAU,IAAIF,EAAY,CAC3BG,GAAIhB,KAAKiB,iBAAiBnB,EAAeF,GACzCa,KAAM,IAAIZ,KAAaD,OAK3BI,KAAKkB,sBAAsBlB,KAAKe,QAASpB,EAAeE,GACxD,OAAOG,KAAKe,OAChB,CAEA,MAAMI,EAAS,IAAIC,EAAO,CACtBJ,GAAIhB,KAAKiB,iBAAiBnB,EAAeF,GACzCyB,YAAa,IAAIxB,KAAaD,KAC9B0B,SAAU3B,EAAcgB,IAAIY,SAC5BC,eAAgB,MAChBC,KAAM,KACNC,OAASC,IACL,MAAMC,EAAS5B,KAAK6B,WACpB,GAAI7B,KAAKD,SAAU,CACfC,KAAKD,SAAS6B,EAAOE,QAAS9B,KAAK+B,SACvC,KAKRZ,EAAOa,QAAQ,IAAIC,EAAK,CAAEC,IAAK,GAAIzB,KAAM,oBAGzC0B,MAAMjC,EAAOE,KACRgC,KAAKC,IACF,IAAKA,EAAIC,GAAI,MAAM,IAAIC,MAAM,QAAQF,EAAIG,UACzC,OAAOH,EAAII,SAEdL,KAAKM,IACF,MAAMC,EAAMC,MAAMC,QAAQH,GAAQA,EAAQA,EAAKI,OAAS,GACxDH,EAAII,QAASC,IACT,MAAMC,EAAI/C,EAAOgD,QAAUF,EAAK9C,EAAOgD,SAAWF,EAClD,MAAMG,EAAIjD,EAAOkD,SAAWJ,EAAK9C,EAAOkD,UAAYJ,EACpD7B,EAAOa,QAAQ,IAAIC,EAAK,CAAEC,IAAKmB,OAAOJ,GAAIxC,KAAM4C,OAAOF,QAE3DhC,EAAOmC,QAAQ,SAElBC,MAAMC,IACHjE,EAAOkE,MAAM,kEAAkEvD,EAAOE,MAAOoD,EAAIE,SACjGvC,EAAOa,QAAQ,IAAIC,EAAK,CAAEC,IAAK,GAAIzB,KAAM,wBACzCU,EAAOmC,QAAQ,SAGvBtD,KAAKe,QAAUI,EACfnB,KAAKkB,sBAAsBlB,KAAKe,QAASpB,EAAeE,GACxD,OAAOG,KAAKe,OAChB,CAMU4C,WACN,OAAO3D,KAAKe,QAAWf,KAAKe,QAAmB6C,iBAAmB,IACtE,CAKUC,aACN,GAAI7D,KAAKe,SAAWf,KAAKC,SAAU,CAC/B,IAAKD,KAAKU,WAAY,OACtB,MAAMS,EAASnB,KAAKe,QACpBI,EAAO2C,YAAY9D,KAAKC,SAASU,IAAIY,SACzC,CACJ,EACH,IAAAwC,EAAA,CAAAC,WAAA,MAAAD,EAAAtE,uBAAA,OAAAsE,CAAA","ignoreList":[],"sourceRoot":"plugins/datasources"}},{"offset":{"line":61,"column":0},"map":{"version":3,"names":["BasePlugin","___controls_BasePlugin","Logger","____utils_Logger","RemoteValueHelpPlugin","isLoaded","render","fieldMetadata","bindingPath","modelName","this","metadata","comboBox","ComboBox","selectedKey","enabled","ui","readOnly","placeholder","change","oEvent","item","getParameter","val","getKey","validate","attachEventOnce","fetchData","control","vhConfig","valueHelp","url","error","setBusy","fetch","then","res","json","data","keyPath","textPath","forEach","itemData","addItem","Item","key","text","catch","err","message","finally","getValue","getSelectedKey","applyState","setEnabled","__exports","__esModule"],"sources":["RemoteValueHelpPlugin.ts"],"sourcesContent":["/**\n * @file RemoteValueHelpPlugin.ts\n * @description A custom datasource plugin that simulates fetching data from a remote server.\n */\n\nimport { BasePlugin } from \"../controls/BasePlugin\";\nimport { IPropertyMetadata, IRemoteValueHelpConfig } from \"../../interfaces/ISchema\";\nimport ComboBox from \"sap/m/ComboBox\";\nimport Item from \"sap/ui/core/Item\";\nimport Control from \"sap/ui/core/Control\";\nimport { Logger } from \"../../utils/Logger\";\n\n/**\n * A custom datasource plugin that simulates fetching data from a remote server.\n * Proves out custom data sources that dynamically load value help.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.datasources\n * @public\n */\nexport class RemoteValueHelpPlugin extends BasePlugin {\n private isLoaded = false;\n\n /**\n * Renders a `ComboBox` that simulates fetching data from a remote server.\n * \n * @param fieldMetadata The specific JSON schema properties for this field.\n * @param bindingPath The JSON path bound to this control.\n * @param modelName The UI5 JSONModel name.\n * @returns {Control} The configured ComboBox control.\n */\n public render(fieldMetadata: IPropertyMetadata, bindingPath: string, modelName: string = \"meta\"): Control {\n this.metadata = fieldMetadata;\n \n const comboBox = new ComboBox({\n selectedKey: `{${modelName}>${bindingPath}}`,\n enabled: !fieldMetadata.ui?.readOnly,\n placeholder: \"Select a country...\",\n change: (oEvent: sap.ui.base.Event) => {\n const item = (oEvent as sap.ui.base.Event).getParameter(\"selectedItem\");\n const val = item ? item.getKey() : (oEvent as sap.ui.base.Event).getParameter(\"value\"); // Allow free text as well\n this.validate();\n }\n });\n\n // Perform an async load against the REST endpoint\n comboBox.attachEventOnce(\"loadItems\", () => {\n this.fetchData(comboBox);\n });\n\n this.control = comboBox;\n return this.control as Control;\n }\n\n /**\n * Executes the REST fetch for data.\n * @param comboBox The UI5 ComboBox to populate.\n */\n protected fetchData(comboBox: ComboBox): void {\n const vhConfig = this.metadata?.valueHelp as IRemoteValueHelpConfig;\n if (!vhConfig || !vhConfig.url) {\n Logger.error(\"RemoteValueHelpPlugin requires a valid valueHelp configuration with a URL.\", \"\", \"RemoteValueHelpPlugin\");\n return;\n }\n \n comboBox.setBusy(true);\n \n fetch(vhConfig.url)\n .then(res => res.json())\n .then((data: Record<string, unknown>[]) => {\n const keyPath = vhConfig.keyPath || \"key\";\n const textPath = vhConfig.textPath || \"text\";\n \n data.forEach(itemData => {\n comboBox.addItem(new Item({ \n key: itemData[keyPath], \n text: itemData[textPath] || itemData[keyPath]\n }));\n });\n })\n .catch(err => {\n Logger.error(\"Failed to load value help from \" + vhConfig.url, err.message, \"RemoteValueHelpPlugin\");\n })\n .finally(() => {\n comboBox.setBusy(false);\n this.isLoaded = true;\n });\n }\n\n /**\n * Retrieves the current selected key.\n * @returns {unknown} The selected key.\n */\n protected getValue(): unknown {\n return this.control ? (this.control as ComboBox).getSelectedKey() : null;\n }\n\n /**\n * Applies dynamic read-only state.\n */\n protected applyState(): void {\n if (this.control && this.metadata) {\n (this.control as ComboBox).setEnabled(!this.metadata.ui?.readOnly);\n }\n }\n}\n"],"mappings":"AAAA,4MAAA,MAKSA,EAAUC,EAAA,oBAKVC,EAAMC,EAAA,UASR,MAAMC,UAA8BJ,EAC/BK,SAAW,MAUZC,OAAOC,EAAkCC,EAAqBC,EAAoB,QACrFC,KAAKC,SAAWJ,EAEhB,MAAMK,EAAW,IAAIC,EAAS,CAC1BC,YAAa,IAAIL,KAAaD,KAC9BO,SAAUR,EAAcS,IAAIC,SAC5BC,YAAa,sBACbC,OAASC,IACL,MAAMC,EAAQD,EAA6BE,aAAa,gBACxD,MAAMC,EAAMF,EAAOA,EAAKG,SAAYJ,EAA6BE,aAAa,SAC9EZ,KAAKe,cAKbb,EAASc,gBAAgB,YAAa,KAClChB,KAAKiB,UAAUf,KAGnBF,KAAKkB,QAAUhB,EACf,OAAOF,KAAKkB,OAChB,CAMUD,UAAUf,GAChB,MAAMiB,EAAWnB,KAAKC,UAAUmB,UAChC,IAAKD,IAAaA,EAASE,IAAK,CAC5B7B,EAAO8B,MAAM,6EAA8E,GAAI,yBAC/F,MACJ,CAEApB,EAASqB,QAAQ,MAEjBC,MAAML,EAASE,KACVI,KAAKC,GAAOA,EAAIC,QAChBF,KAAMG,IACH,MAAMC,EAAUV,EAASU,SAAW,MACpC,MAAMC,EAAWX,EAASW,UAAY,OAEtCF,EAAKG,QAAQC,IACT9B,EAAS+B,QAAQ,IAAIC,EAAK,CACtBC,IAAKH,EAASH,GACdO,KAAMJ,EAASF,IAAaE,EAASH,UAIhDQ,MAAMC,IACH9C,EAAO8B,MAAM,kCAAoCH,EAASE,IAAKiB,EAAIC,QAAS,2BAE/EC,QAAQ,KACLtC,EAASqB,QAAQ,OACjBvB,KAAKL,SAAW,MAE5B,CAMU8C,WACN,OAAOzC,KAAKkB,QAAWlB,KAAKkB,QAAqBwB,iBAAmB,IACxE,CAKUC,aACN,GAAI3C,KAAKkB,SAAWlB,KAAKC,SAAU,CAC9BD,KAAKkB,QAAqB0B,YAAY5C,KAAKC,SAASK,IAAIC,SAC7D,CACJ,EACH,IAAAsC,EAAA,CAAAC,WAAA,MAAAD,EAAAnD,wBAAA,OAAAmD,CAAA","ignoreList":[],"sourceRoot":"plugins/datasources"}},{"offset":{"line":62,"column":0},"map":{"version":3,"names":["CurrencyFormatterPlugin","constructor","this","currencyFormat","NumberFormat","getCurrencyInstance","showMeasure","format","rawValue","args","undefined","__exports","__esModule"],"sources":["CurrencyFormatterPlugin.ts"],"sourcesContent":["/**\n * @file CurrencyFormatterPlugin.ts\n * @description Standard data formatter for currency values.\n */\n\nimport { IFormatter } from \"../../interfaces/IPipeline\";\nimport NumberFormat from \"sap/ui/core/format/NumberFormat\";\n\n/**\n * Standard data formatter for currency values.\n * Uses sap.ui.core.format.NumberFormat to format raw numbers into localized currency strings.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.formatters\n * @public\n */\nexport class CurrencyFormatterPlugin implements IFormatter {\n private currencyFormat: NumberFormat;\n\n constructor() {\n this.currencyFormat = NumberFormat.getCurrencyInstance({\n showMeasure: false\n });\n }\n\n /**\n * Formats raw JSON model data into a UI-friendly currency string.\n * @param rawValue The raw numeric value from the JSON payload.\n * @returns The formatted string for the UI control.\n */\n public format(rawValue: unknown, args?: unknown): string {\n if (rawValue === null || rawValue === undefined) {\n return \"\";\n }\n return \"$\" + this.currencyFormat.format(rawValue as number);\n }\n}\n"],"mappings":"AAAA,uJAeO,MAAMA,EAGTC,cACIC,KAAKC,eAAiBC,EAAaC,oBAAoB,CACnDC,YAAa,OAErB,CAOOC,OAAOC,EAAmBC,GAC7B,GAAID,IAAa,MAAQA,IAAaE,UAAW,CAC7C,MAAO,EACX,CACA,MAAO,IAAMR,KAAKC,eAAeI,OAAOC,EAC5C,EACH,IAAAG,EAAA,CAAAC,WAAA,MAAAD,EAAAX,0BAAA,OAAAW,CAAA","ignoreList":[],"sourceRoot":"plugins/formatters"}},{"offset":{"line":63,"column":0},"map":{"version":3,"names":["DateFormatterPlugin","constructor","this","dateFormat","DateFormat","getDateInstance","style","format","rawValue","args","dateObj","Date","e","__exports","__esModule"],"sources":["DateFormatterPlugin.ts"],"sourcesContent":["/**\n * @file DateFormatterPlugin.ts\n * @description Standard data formatter for dates.\n */\n\nimport { IFormatter } from \"../../interfaces/IPipeline\";\nimport DateFormat from \"sap/ui/core/format/DateFormat\";\n\n/**\n * Formats ISO date strings to localized Medium formats (e.g., \"Oct 15, 2026\").\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.formatters\n * @public\n */\nexport class DateFormatterPlugin implements IFormatter {\n private dateFormat: DateFormat;\n\n constructor() {\n this.dateFormat = DateFormat.getDateInstance({ style: \"medium\" });\n }\n\n /**\n * Formats raw JSON model data into a medium-style date string.\n * @param rawValue The raw date string.\n * @returns The formatted string for the UI control.\n */\n public format(rawValue: unknown, args?: unknown): string {\n if (!rawValue) return \"\";\n try {\n const dateObj = new Date(rawValue as string);\n return this.dateFormat.format(dateObj);\n } catch (e) {\n return rawValue as string; // Fallback to raw string if invalid date\n }\n }\n}\n"],"mappings":"AAAA,iJAcO,MAAMA,EAGTC,cACIC,KAAKC,WAAaC,EAAWC,gBAAgB,CAAEC,MAAO,UAC1D,CAOOC,OAAOC,EAAmBC,GAC7B,IAAKD,EAAU,MAAO,GACtB,IACI,MAAME,EAAU,IAAIC,KAAKH,GACzB,OAAON,KAAKC,WAAWI,OAAOG,EAClC,CAAE,MAAOE,GACL,OAAOJ,CACX,CACJ,EACH,IAAAK,EAAA,CAAAC,WAAA,MAAAD,EAAAb,sBAAA,OAAAa,CAAA","ignoreList":[],"sourceRoot":"plugins/formatters"}},{"offset":{"line":64,"column":0},"map":{"version":3,"names":["PhoneFormatterPlugin","format","rawValue","args","String","cleaned","replace","match","__exports","__esModule"],"sources":["PhoneFormatterPlugin.ts"],"sourcesContent":["/**\n * @file PhoneFormatterPlugin.ts\n * @description Standard data formatter for phone numbers.\n */\n\nimport { IFormatter } from \"../../interfaces/IPipeline\";\n\n/**\n * Simple mask for 10-digit phone numbers (e.g. 5551234567 -> (555) 123-4567).\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.formatters\n * @public\n */\nexport class PhoneFormatterPlugin implements IFormatter {\n /**\n * Formats raw JSON model data into a masked phone number.\n * @param rawValue The raw phone string.\n * @returns The formatted string for the UI control.\n */\n public format(rawValue: unknown, args?: unknown): string {\n if (!rawValue || typeof rawValue !== \"string\") return String(rawValue || \"\");\n \n const cleaned = ('' + rawValue).replace(/\\D/g, '');\n const match = cleaned.match(/^(\\d{3})(\\d{3})(\\d{4})$/);\n \n if (match) {\n return '(' + match[1] + ') ' + match[2] + '-' + match[3];\n }\n \n return rawValue as string;\n }\n}\n"],"mappings":"AAAA,kHAaO,MAAMA,EAMFC,OAAOC,EAAmBC,GAC7B,IAAKD,UAAmBA,IAAa,SAAU,OAAOE,OAAOF,GAAY,IAEzE,MAAMG,GAAW,GAAKH,GAAUI,QAAQ,MAAO,IAC/C,MAAMC,EAAQF,EAAQE,MAAM,2BAE5B,GAAIA,EAAO,CACP,MAAO,IAAMA,EAAM,GAAK,KAAOA,EAAM,GAAK,IAAMA,EAAM,EAC1D,CAEA,OAAOL,CACX,EACH,IAAAM,EAAA,CAAAC,WAAA,MAAAD,EAAAR,uBAAA,OAAAQ,CAAA","ignoreList":[],"sourceRoot":"plugins/formatters"}},{"offset":{"line":65,"column":0},"map":{"version":3,"names":["TextCaseFormatterPlugin","format","rawValue","args","String","toUpperCase","__exports","__esModule"],"sources":["TextCaseFormatterPlugin.ts"],"sourcesContent":["/**\n * @file TextCaseFormatterPlugin.ts\n * @description Standard data formatter for text casing.\n */\n\nimport { IFormatter } from \"../../interfaces/IPipeline\";\n\n/**\n * Transforms text to UPPERCASE, lowercase, or Title Case.\n * Defaults to uppercase.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.formatters\n * @public\n */\nexport class TextCaseFormatterPlugin implements IFormatter {\n /**\n * Formats raw JSON model data into uppercase.\n * @param rawValue The raw string.\n * @returns The uppercase formatted string for the UI control.\n */\n public format(rawValue: unknown, args?: unknown): string {\n if (typeof rawValue !== \"string\") return String(rawValue || \"\");\n \n // Default to uppercase if no specific arg could be easily parsed by simple formatter \n // (could be enhanced to support schema args if formatters allowed args).\n return rawValue.toUpperCase();\n }\n}\n"],"mappings":"AAAA,qHAcO,MAAMA,EAMFC,OAAOC,EAAmBC,GAC7B,UAAWD,IAAa,SAAU,OAAOE,OAAOF,GAAY,IAI5D,OAAOA,EAASG,aACpB,EACH,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAAN,0BAAA,OAAAM,CAAA","ignoreList":[],"sourceRoot":"plugins/formatters"}},{"offset":{"line":66,"column":0},"map":{"version":3,"names":["EmailValidatorPlugin","validate","parsedValue","args","isValid","emailRegex","test","errorMessage","__exports","__esModule"],"sources":["EmailValidatorPlugin.ts"],"sourcesContent":["/**\n * @file EmailValidatorPlugin.ts\n * @description Standard business logic validator for email addresses.\n */\n\nimport { IValidator, IValidationResult } from \"../../interfaces/IPipeline\";\n\n/**\n * Standard business logic validator for email addresses.\n * Extracts the email regex validation logic into a standalone, modular plugin.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.validators\n * @public\n */\nexport class EmailValidatorPlugin implements IValidator {\n /**\n * Validates parsed data before it enters the JSON model.\n * @param parsedValue The cleaned data to validate.\n * @param args Optional arguments provided in the schema.\n * @returns IValidationResult containing status and optional error message.\n */\n public validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (!parsedValue) return { isValid: true }; // Let RequiredValidator handle empty\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (typeof parsedValue !== \"string\" || !emailRegex.test(parsedValue)) {\n return { isValid: false, errorMessage: \"Please enter a valid email address.\" };\n }\n return { isValid: true };\n }\n}\n"],"mappings":"AAAA,kHAcO,MAAMA,EAOFC,SAASC,EAAsBC,GAClC,IAAKD,EAAa,MAAO,CAAEE,QAAS,MACpC,MAAMC,EAAa,6BACnB,UAAWH,IAAgB,WAAaG,EAAWC,KAAKJ,GAAc,CAClE,MAAO,CAAEE,QAAS,MAAOG,aAAc,sCAC3C,CACA,MAAO,CAAEH,QAAS,KACtB,EACH,IAAAI,EAAA,CAAAC,WAAA,MAAAD,EAAAR,uBAAA,OAAAQ,CAAA","ignoreList":[],"sourceRoot":"plugins/validators"}},{"offset":{"line":67,"column":0},"map":{"version":3,"names":["IbanValidatorPlugin","validate","parsedValue","args","isValid","ibanRegex","test","replace","toUpperCase","errorMessage","__exports","__esModule"],"sources":["IbanValidatorPlugin.ts"],"sourcesContent":["/**\n * @file IbanValidatorPlugin.ts\n * @description Standard business logic validator for International Bank Account Numbers.\n */\n\nimport { IValidator, IValidationResult } from \"../../interfaces/IPipeline\";\n\n/**\n * Validates a standard IBAN string.\n * This provides a simplified check for demonstration (starts with 2 chars, followed by digits/chars).\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.validators\n * @public\n */\nexport class IbanValidatorPlugin implements IValidator {\n /**\n * Validates parsed data before it enters the JSON model.\n * @param parsedValue The cleaned data to validate.\n * @param args Optional arguments provided in the schema.\n * @returns IValidationResult containing status and optional error message.\n */\n public validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (!parsedValue) return { isValid: true }; // Let RequiredValidator handle empty\n \n // Very basic IBAN structure regex (e.g. DE89370400440532013000)\n // A true IBAN check requires modulo 97 arithmetic which is out of scope for a basic mock.\n const ibanRegex = /^[A-Z]{2}\\d{2}[A-Z0-9]{1,30}$/;\n \n if (typeof parsedValue !== \"string\" || !ibanRegex.test(parsedValue.replace(/\\s+/g, '').toUpperCase())) {\n return { isValid: false, errorMessage: \"Please enter a valid IBAN.\" };\n }\n \n return { isValid: true };\n }\n}\n"],"mappings":"AAAA,iHAcO,MAAMA,EAOFC,SAASC,EAAsBC,GAClC,IAAKD,EAAa,MAAO,CAAEE,QAAS,MAIpC,MAAMC,EAAY,gCAElB,UAAWH,IAAgB,WAAaG,EAAUC,KAAKJ,EAAYK,QAAQ,OAAQ,IAAIC,eAAgB,CACnG,MAAO,CAAEJ,QAAS,MAAOK,aAAc,6BAC3C,CAEA,MAAO,CAAEL,QAAS,KACtB,EACH,IAAAM,EAAA,CAAAC,WAAA,MAAAD,EAAAV,sBAAA,OAAAU,CAAA","ignoreList":[],"sourceRoot":"plugins/validators"}},{"offset":{"line":68,"column":0},"map":{"version":3,"names":["MinLengthValidatorPlugin","validate","parsedValue","args","isValid","length","errorMessage","__exports","__esModule"],"sources":["MinLengthValidatorPlugin.ts"],"sourcesContent":["/**\n * @file MinLengthValidatorPlugin.ts\n * @description Standard business logic validator for string minimum lengths.\n */\n\nimport { IValidator, IValidationResult } from \"../../interfaces/IPipeline\";\n\n/**\n * Ensures string length meets a minimum threshold.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.validators\n * @public\n */\nexport class MinLengthValidatorPlugin implements IValidator {\n /**\n * Validates parsed data before it enters the JSON model.\n * @param parsedValue The cleaned data to validate.\n * @param args Optional arguments provided in the schema.\n * @returns IValidationResult containing status and optional error message.\n */\n public validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (!parsedValue) return { isValid: true }; // Let RequiredValidator handle empty\n if (typeof args !== \"number\") return { isValid: true }; // Invalid config\n\n if (typeof parsedValue === \"string\" && parsedValue.length < args) {\n return { isValid: false, errorMessage: `Minimum length is ${args} characters.` };\n }\n \n return { isValid: true };\n }\n}\n"],"mappings":"AAAA,sHAaO,MAAMA,EAOFC,SAASC,EAAsBC,GAClC,IAAKD,EAAa,MAAO,CAAEE,QAAS,MACpC,UAAWD,IAAS,SAAU,MAAO,CAAEC,QAAS,MAEhD,UAAWF,IAAgB,UAAYA,EAAYG,OAASF,EAAM,CAC9D,MAAO,CAAEC,QAAS,MAAOE,aAAc,qBAAqBH,gBAChE,CAEA,MAAO,CAAEC,QAAS,KACtB,EACH,IAAAG,EAAA,CAAAC,WAAA,MAAAD,EAAAP,2BAAA,OAAAO,CAAA","ignoreList":[],"sourceRoot":"plugins/validators"}},{"offset":{"line":69,"column":0},"map":{"version":3,"names":["PatternValidatorPlugin","validate","parsedValue","args","isValid","regex","RegExp","test","errorMessage","e","__exports","__esModule"],"sources":["PatternValidatorPlugin.ts"],"sourcesContent":["/**\n * @file PatternValidatorPlugin.ts\n * @description Standard business logic validator for Regex patterns.\n */\n\nimport { IValidator, IValidationResult } from \"../../interfaces/IPipeline\";\n\n/**\n * Validates a string against a regular expression pattern provided in the schema args.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.validators\n * @public\n */\nexport class PatternValidatorPlugin implements IValidator {\n /**\n * Validates parsed data before it enters the JSON model.\n * @param parsedValue The cleaned data to validate.\n * @param args Optional arguments provided in the schema.\n * @returns IValidationResult containing status and optional error message.\n */\n public validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (!parsedValue) return { isValid: true }; // Let RequiredValidator handle empty\n if (typeof args !== \"string\") {\n return { isValid: true }; // Invalid config, skip\n }\n\n try {\n const regex = new RegExp(args);\n if (typeof parsedValue !== \"string\" || !regex.test(parsedValue)) {\n return { isValid: false, errorMessage: `Input does not match the required pattern.` };\n }\n } catch (e) {\n // Invalid regex string provided\n return { isValid: false, errorMessage: `Schema configuration error: Invalid regex pattern.` };\n }\n \n return { isValid: true };\n }\n}\n"],"mappings":"AAAA,oHAaO,MAAMA,EAOFC,SAASC,EAAsBC,GAClC,IAAKD,EAAa,MAAO,CAAEE,QAAS,MACpC,UAAWD,IAAS,SAAU,CAC1B,MAAO,CAAEC,QAAS,KACtB,CAEA,IACI,MAAMC,EAAQ,IAAIC,OAAOH,GACzB,UAAWD,IAAgB,WAAaG,EAAME,KAAKL,GAAc,CAC7D,MAAO,CAAEE,QAAS,MAAOI,aAAc,6CAC3C,CACJ,CAAE,MAAOC,GAEL,MAAO,CAAEL,QAAS,MAAOI,aAAc,qDAC3C,CAEA,MAAO,CAAEJ,QAAS,KACtB,EACH,IAAAM,EAAA,CAAAC,WAAA,MAAAD,EAAAV,yBAAA,OAAAU,CAAA","ignoreList":[],"sourceRoot":"plugins/validators"}},{"offset":{"line":70,"column":0},"map":{"version":3,"names":["RangeValidatorPlugin","validate","parsedValue","args","undefined","isValid","rangeArgs","min","max","errorMessage","__exports","__esModule"],"sources":["RangeValidatorPlugin.ts"],"sourcesContent":["/**\n * @file RangeValidatorPlugin.ts\n * @description Standard business logic validator for numeric ranges.\n */\n\nimport { IValidator, IValidationResult } from \"../../interfaces/IPipeline\";\n\n/**\n * Ensures a numeric value falls within an optionally provided min and max range.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.validators\n * @public\n */\nexport class RangeValidatorPlugin implements IValidator {\n /**\n * Validates parsed data before it enters the JSON model.\n * @param parsedValue The cleaned data to validate.\n * @param args Optional arguments provided in the schema.\n * @returns IValidationResult containing status and optional error message.\n */\n public validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (parsedValue === null || parsedValue === undefined) return { isValid: true }; \n if (typeof parsedValue !== \"number\") return { isValid: true };\n\n const rangeArgs = args as { min?: number, max?: number } | undefined;\n const min = rangeArgs?.min;\n const max = rangeArgs?.max;\n\n if (min !== undefined && typeof min === \"number\" && parsedValue < min) {\n return { isValid: false, errorMessage: `Value must be greater than or equal to ${min}.` };\n }\n\n if (max !== undefined && typeof max === \"number\" && parsedValue > max) {\n return { isValid: false, errorMessage: `Value must be less than or equal to ${max}.` };\n }\n \n return { isValid: true };\n }\n}\n"],"mappings":"AAAA,kHAaO,MAAMA,EAOFC,SAASC,EAAsBC,GAClC,GAAID,IAAgB,MAAQA,IAAgBE,UAAW,MAAO,CAAEC,QAAS,MACzE,UAAWH,IAAgB,SAAU,MAAO,CAAEG,QAAS,MAEvD,MAAMC,EAAYH,EAClB,MAAMI,EAAMD,GAAWC,IACvB,MAAMC,EAAMF,GAAWE,IAEvB,GAAID,IAAQH,kBAAoBG,IAAQ,UAAYL,EAAcK,EAAK,CACnE,MAAO,CAAEF,QAAS,MAAOI,aAAc,0CAA0CF,KACrF,CAEA,GAAIC,IAAQJ,kBAAoBI,IAAQ,UAAYN,EAAcM,EAAK,CACnE,MAAO,CAAEH,QAAS,MAAOI,aAAc,uCAAuCD,KAClF,CAEA,MAAO,CAAEH,QAAS,KACtB,EACH,IAAAK,EAAA,CAAAC,WAAA,MAAAD,EAAAV,uBAAA,OAAAU,CAAA","ignoreList":[],"sourceRoot":"plugins/validators"}},{"offset":{"line":71,"column":0},"map":{"version":3,"names":["UrlValidatorPlugin","validate","parsedValue","args","isValid","url","URL","protocol","errorMessage","e","__exports","__esModule"],"sources":["UrlValidatorPlugin.ts"],"sourcesContent":["/**\n * @file UrlValidatorPlugin.ts\n * @description Standard business logic validator for URL formats.\n */\n\nimport { IValidator, IValidationResult } from \"../../interfaces/IPipeline\";\n\n/**\n * Ensures a string is a valid HTTP/HTTPS URL.\n * \n * @namespace nz.co.siliconst.ui5.metaui.plugins.validators\n * @public\n */\nexport class UrlValidatorPlugin implements IValidator {\n /**\n * Validates parsed data before it enters the JSON model.\n * @param parsedValue The cleaned data to validate.\n * @param args Optional arguments provided in the schema.\n * @returns IValidationResult containing status and optional error message.\n */\n public validate(parsedValue: unknown, args?: unknown): IValidationResult {\n if (!parsedValue) return { isValid: true }; // Let RequiredValidator handle empty\n if (typeof parsedValue !== \"string\") return { isValid: true };\n \n try {\n const url = new URL(parsedValue);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n return { isValid: false, errorMessage: \"URL must use http or https protocol.\" };\n }\n } catch (e) {\n return { isValid: false, errorMessage: \"Please enter a valid URL.\" };\n }\n \n return { isValid: true };\n }\n}\n"],"mappings":"AAAA,gHAaO,MAAMA,EAOFC,SAASC,EAAsBC,GAClC,IAAKD,EAAa,MAAO,CAAEE,QAAS,MACpC,UAAWF,IAAgB,SAAU,MAAO,CAAEE,QAAS,MAEvD,IACI,MAAMC,EAAM,IAAIC,IAAIJ,GACpB,GAAIG,EAAIE,WAAa,SAAWF,EAAIE,WAAa,SAAU,CACvD,MAAO,CAAEH,QAAS,MAAOI,aAAc,uCAC3C,CACJ,CAAE,MAAOC,GACL,MAAO,CAAEL,QAAS,MAAOI,aAAc,4BAC3C,CAEA,MAAO,CAAEJ,QAAS,KACtB,EACH,IAAAM,EAAA,CAAAC,WAAA,MAAAD,EAAAV,qBAAA,OAAAU,CAAA","ignoreList":[],"sourceRoot":"plugins/validators"}},{"offset":{"line":72,"column":0},"map":{"version":3,"names":["Logger","___utils_Logger","SwaggerTypeMapper","___SwaggerTypeMapper","SwaggerUIMapper","___SwaggerUIMapper","SwaggerRefResolver","___SwaggerRefResolver","SwaggerBuilder","canHandle","rawSchema","openapi","swagger","build","fetchAndBuild","url","targetDefinition","response","fetch","ok","Error","status","swaggerRoot","json","this","error","msg","message","targetObject","components","schemas","keys","Object","length","definitions","found","schema","title","info","type","layoutStrategy","additionalProperties","requiredKeys","Array","isArray","required","properties","mapProperties","items","mapPropertyMetadata","normalizedProps","key","isRequired","includes","propDef","$ref","resolved","resolve","swaggerProp","keyName","currentProp","allOf","merged","subSchema","resolvedSub","mapType","metaProp","uiDirective","ui","maxLength","minLength","maximum","minimum","pattern","multipleOf","default","undefined","nullable","writeOnly","example","deprecated","exclusiveMinimum","exclusiveMaximum","enum","widget","childRequired","__exports","__esModule"],"sources":["SwaggerBuilder.ts"],"sourcesContent":["/**\n * @file SwaggerBuilder.ts\n * @description Facade orchestration for translating Swagger/OpenAPI JSON into native MetaUI ISchema.\n * Strict Single Responsibility architecture delegates mapping logic to dedicated utilities.\n */\n\nimport { ISchema, IPropertyMetadata } from \"../interfaces/ISchema\";\nimport { ISchemaBuilderPlugin } from \"../interfaces/ISchemaBuilderPlugin\";\nimport { Logger } from \"../utils/Logger\";\nimport { SwaggerTypeMapper } from \"./SwaggerTypeMapper\";\nimport { SwaggerUIMapper } from \"./SwaggerUIMapper\";\nimport { SwaggerRefResolver } from \"./SwaggerRefResolver\";\n\nexport class SwaggerBuilder implements ISchemaBuilderPlugin {\n\n /**\n * Determines if the provided JSON payload is a Swagger or OpenAPI document.\n * \n * @param {any} rawSchema The raw JSON schema to test.\n * @returns {boolean} True if the document contains 'openapi' or 'swagger' root keys.\n */\n public canHandle(rawSchema: any): boolean {\n return !!(rawSchema && (rawSchema.openapi || rawSchema.swagger));\n }\n\n /**\n * Builds a strict MetaUI ISchema from the provided OpenAPI payload.\n * \n * @param {any} rawSchema The OpenAPI root document.\n * @returns {ISchema} The translated MetaUI schema.\n */\n public build(rawSchema: any): ISchema {\n return SwaggerBuilder.build(rawSchema);\n }\n\n /**\n * Asynchronously fetches a remote OpenAPI document and compiles it into a MetaUI ISchema.\n * \n * @param {string} url The URL to fetch the JSON payload from.\n * @param {string} [targetDefinition] Optional. The specific entity schema to extract.\n * @returns {Promise<ISchema>} A Promise resolving to the compiled ISchema.\n */\n public static async fetchAndBuild(url: string, targetDefinition?: string): Promise<ISchema> {\n try {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n const swaggerRoot = await response.json();\n return this.build(swaggerRoot, targetDefinition);\n } catch (error) {\n const msg = \"Failed to fetch Swagger JSON from URL: \" + (error as Error).message;\n Logger.error(\"[MetaUI SwaggerBuilder]\", msg);\n throw new Error(msg);\n }\n }\n\n /**\n * Synchronously builds a MetaUI ISchema from a provided OpenAPI root document.\n * Automatically extracts the requested definition from `components.schemas` or falls back to the first available.\n * \n * @param {any} swaggerRoot The OpenAPI root document.\n * @param {string} [targetDefinition] Optional. The specific entity schema to extract.\n * @returns {ISchema} The translated MetaUI schema.\n */\n public static build(swaggerRoot: any, targetDefinition?: string): ISchema {\n if (!swaggerRoot || typeof swaggerRoot !== \"object\") {\n throw new Error(\"[MetaUI SwaggerBuilder] Invalid Swagger root object provided.\");\n }\n\n let targetObject = swaggerRoot;\n\n if (!targetDefinition) {\n if (swaggerRoot.components && swaggerRoot.components.schemas) {\n const keys = Object.keys(swaggerRoot.components.schemas);\n if (keys.length > 0) targetDefinition = keys[0];\n } else if (swaggerRoot.definitions) {\n const keys = Object.keys(swaggerRoot.definitions);\n if (keys.length > 0) targetDefinition = keys[0];\n }\n }\n\n if (targetDefinition) {\n let found = false;\n if (swaggerRoot.components && swaggerRoot.components.schemas && swaggerRoot.components.schemas[targetDefinition]) {\n targetObject = swaggerRoot.components.schemas[targetDefinition];\n found = true;\n } else if (swaggerRoot.definitions && swaggerRoot.definitions[targetDefinition]) {\n targetObject = swaggerRoot.definitions[targetDefinition];\n found = true;\n }\n\n if (!found) {\n throw new Error(`[MetaUI SwaggerBuilder] Could not find target definition '${targetDefinition}' in components/schemas or definitions.`);\n }\n }\n\n const schema: ISchema = {\n title: targetObject.title || swaggerRoot.info?.title || targetDefinition,\n type: targetObject.type === \"array\" ? \"array\" : \"object\",\n layoutStrategy: targetObject.type === \"array\" ? \"table\" : \"form\"\n };\n\n if (targetObject.additionalProperties === true) {\n schema.additionalProperties = true;\n }\n\n if (schema.type === \"object\") {\n const requiredKeys = Array.isArray(targetObject.required) ? targetObject.required : [];\n schema.properties = this.mapProperties(targetObject.properties || {}, requiredKeys, swaggerRoot);\n } else if (schema.type === \"array\" && targetObject.items) {\n schema.items = this.mapPropertyMetadata(targetObject.items, \"items\", false, swaggerRoot);\n }\n\n return schema;\n }\n\n /**\n * Recursively traverses and translates an OpenAPI properties block into MetaUI IPropertyMetadata.\n * \n * @param {Record<string, any>} properties The OpenAPI properties object.\n * @param {string[]} requiredKeys An array of keys marked as required in the parent schema.\n * @param {any} swaggerRoot The root document (used for $ref resolution).\n * @returns {Record<string, IPropertyMetadata>} The mapped MetaUI properties object.\n */\n private static mapProperties(properties: Record<string, any>, requiredKeys: string[], swaggerRoot: any): Record<string, IPropertyMetadata> {\n const normalizedProps: Record<string, IPropertyMetadata> = {};\n \n for (const key of Object.keys(properties)) {\n const isRequired = requiredKeys.includes(key);\n let propDef = properties[key];\n\n if (propDef.$ref) {\n const resolved = SwaggerRefResolver.resolve(propDef.$ref, swaggerRoot);\n if (resolved) {\n propDef = { ...resolved, ...propDef };\n }\n }\n\n normalizedProps[key] = this.mapPropertyMetadata(propDef, key, isRequired, swaggerRoot);\n }\n \n return normalizedProps;\n }\n\n /**\n * Translates a single OpenAPI property schema into a MetaUI IPropertyMetadata block.\n * Handles local $ref resolution, allOf merging, type mapping, and UI directive injection.\n * \n * @param {any} swaggerProp The OpenAPI property definition.\n * @param {string} keyName The technical key of the property.\n * @param {boolean} isRequired Whether this property is strictly required.\n * @param {any} swaggerRoot The root document (used for $ref resolution).\n * @returns {IPropertyMetadata} The compiled MetaUI property metadata.\n */\n private static mapPropertyMetadata(swaggerProp: any, keyName: string, isRequired: boolean, swaggerRoot: any): IPropertyMetadata {\n let currentProp = swaggerProp;\n\n if (currentProp.$ref) {\n const resolved = SwaggerRefResolver.resolve(currentProp.$ref, swaggerRoot);\n if (resolved) {\n currentProp = { ...resolved, ...currentProp };\n }\n }\n\n if (Array.isArray(currentProp.allOf)) {\n let merged = { ...currentProp };\n delete merged.allOf;\n for (const subSchema of currentProp.allOf) {\n let resolvedSub = subSchema;\n if (subSchema.$ref) {\n resolvedSub = SwaggerRefResolver.resolve(subSchema.$ref, swaggerRoot) || {};\n }\n merged = { ...merged, ...resolvedSub };\n }\n currentProp = merged;\n }\n\n const type = SwaggerTypeMapper.mapType(currentProp.type);\n\n const metaProp: IPropertyMetadata = {\n type: type,\n required: isRequired\n };\n\n const uiDirective = SwaggerUIMapper.build(currentProp, keyName);\n if (Object.keys(uiDirective).length > 0) {\n metaProp.ui = uiDirective;\n }\n\n if (typeof currentProp.maxLength === \"number\") metaProp.maxLength = currentProp.maxLength;\n if (typeof currentProp.minLength === \"number\") metaProp.minLength = currentProp.minLength;\n if (typeof currentProp.maximum === \"number\") metaProp.maximum = currentProp.maximum;\n if (typeof currentProp.minimum === \"number\") metaProp.minimum = currentProp.minimum;\n if (typeof currentProp.pattern === \"string\") metaProp.pattern = currentProp.pattern;\n\n if (typeof currentProp.multipleOf === \"number\") metaProp.multipleOf = currentProp.multipleOf;\n \n if (currentProp.default !== undefined) metaProp.default = currentProp.default;\n if (typeof currentProp.nullable === \"boolean\") metaProp.nullable = currentProp.nullable;\n if (typeof currentProp.writeOnly === \"boolean\") metaProp.writeOnly = currentProp.writeOnly;\n if (currentProp.example !== undefined) metaProp.example = currentProp.example;\n if (typeof currentProp.deprecated === \"boolean\") metaProp.deprecated = currentProp.deprecated;\n if (currentProp.exclusiveMinimum !== undefined) metaProp.exclusiveMinimum = currentProp.exclusiveMinimum;\n if (currentProp.exclusiveMaximum !== undefined) metaProp.exclusiveMaximum = currentProp.exclusiveMaximum;\n\n if (Array.isArray(currentProp.enum)) {\n metaProp.enum = currentProp.enum;\n if (!metaProp.ui) metaProp.ui = {};\n if (!metaProp.ui.widget) {\n if (type === \"array\") {\n metaProp.ui.widget = \"multiSelect\";\n } else {\n metaProp.ui.widget = \"select\";\n }\n }\n }\n\n if (type === \"object\") {\n if (currentProp.properties) {\n const childRequired = Array.isArray(currentProp.required) ? currentProp.required : [];\n metaProp.properties = this.mapProperties(currentProp.properties, childRequired, swaggerRoot);\n }\n if (currentProp.additionalProperties === true) {\n metaProp.additionalProperties = true;\n }\n } else if (type === \"array\" && currentProp.items) {\n metaProp.items = this.mapPropertyMetadata(currentProp.items, \"items\", false, swaggerRoot);\n }\n\n return metaProp;\n }\n}\n"],"mappings":"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","ignoreList":[],"sourceRoot":"swagger"}},{"offset":{"line":73,"column":0},"map":{"version":3,"names":["Logger","___utils_Logger","SwaggerRefResolver","resolve","refUrl","swaggerRoot","startsWith","debug","pathSegments","substring","split","current","segment","error","__exports","__esModule"],"sources":["SwaggerRefResolver.ts"],"sourcesContent":["/**\n * @file SwaggerRefResolver.ts\n * @description Utility class for resolving local $ref pointers within an OpenAPI document.\n */\nimport { Logger } from \"../utils/Logger\";\n\nexport class SwaggerRefResolver {\n /**\n * Recursively traverses a local JSON Pointer $ref path (e.g., '#/components/schemas/Pet')\n * and extracts the target object from the Swagger root document.\n * External URLs or invalid references are safely ignored.\n * \n * @param {string} refUrl The $ref string path.\n * @param {any} swaggerRoot The root OpenAPI document to query against.\n * @returns {any} The resolved schema object, or null if unresolvable.\n */\n public static resolve(refUrl: string, swaggerRoot: any): any {\n if (!refUrl || !refUrl.startsWith(\"#/\")) {\n Logger.debug(`[MetaUI SwaggerBuilder] Ignoring non-local or empty $ref: ${refUrl}`, \"SwaggerBuilder\");\n return null; // Ignore external URLs per architectural rules\n }\n\n const pathSegments = refUrl.substring(2).split(\"/\");\n let current = swaggerRoot;\n\n for (const segment of pathSegments) {\n if (current && typeof current === \"object\" && segment in current) {\n current = current[segment];\n } else {\n Logger.error(`[MetaUI SwaggerBuilder] Failed to resolve local $ref: ${refUrl}`, null, \"SwaggerBuilder\");\n return null;\n }\n }\n\n return current;\n }\n}\n"],"mappings":"AAAA,uHAAA,MAISA,EAAMC,EAAA,UAER,MAAMC,EAUT,cAAcC,CAAQC,EAAgBC,GAClC,IAAKD,IAAWA,EAAOE,WAAW,MAAO,CACrCN,EAAOO,MAAM,6DAA6DH,IAAU,kBACpF,OAAO,IACX,CAEA,MAAMI,EAAeJ,EAAOK,UAAU,GAAGC,MAAM,KAC/C,IAAIC,EAAUN,EAEd,IAAK,MAAMO,KAAWJ,EAAc,CAChC,GAAIG,UAAkBA,IAAY,UAAYC,KAAWD,EAAS,CAC9DA,EAAUA,EAAQC,EACtB,KAAO,CACHZ,EAAOa,MAAM,yDAAyDT,IAAU,KAAM,kBACtF,OAAO,IACX,CACJ,CAEA,OAAOO,CACX,EACH,IAAAG,EAAA,CAAAC,WAAA,MAAAD,EAAAZ,qBAAA,OAAAY,CAAA","ignoreList":[],"sourceRoot":"swagger"}},{"offset":{"line":74,"column":0},"map":{"version":3,"names":["SwaggerTypeMapper","mapType","swaggerType","typeMap","string","number","integer","boolean","array","object","date","__exports","__esModule"],"sources":["SwaggerTypeMapper.ts"],"sourcesContent":["/**\n * @file SwaggerTypeMapper.ts\n * @description Utility class for mapping OpenAPI 3.0 primitive types to MetaUI FieldTypes.\n */\nimport { FieldType } from \"../interfaces/ISchema\";\n\nexport class SwaggerTypeMapper {\n /**\n * Maps an OpenAPI primitive type string to the closest MetaUI FieldType.\n * If the type is omitted (common for objects) or unknown, it defaults to \"object\".\n * \n * @param {string} swaggerType The raw OpenAPI type (e.g., 'string', 'integer').\n * @returns {FieldType} The mapped MetaUI FieldType.\n */\n public static mapType(swaggerType: string): FieldType {\n const typeMap: Record<string, FieldType> = {\n \"string\": \"string\",\n \"number\": \"number\",\n \"integer\": \"integer\",\n \"boolean\": \"boolean\",\n \"array\": \"array\",\n \"object\": \"object\",\n \"date\": \"date\"\n };\n // Swagger often omits type if it's an object with properties\n return typeMap[swaggerType] || \"object\";\n }\n}\n"],"mappings":"AAAA,oGAMO,MAAMA,EAQT,cAAcC,CAAQC,GAClB,MAAMC,EAAqC,CACvCC,OAAU,SACVC,OAAU,SACVC,QAAW,UACXC,QAAW,UACXC,MAAS,QACTC,OAAU,SACVC,KAAQ,QAGZ,OAAOP,EAAQD,IAAgB,QACnC,EACH,IAAAS,EAAA,CAAAC,WAAA,MAAAD,EAAAX,oBAAA,OAAAW,CAAA","ignoreList":[],"sourceRoot":"swagger"}},{"offset":{"line":75,"column":0},"map":{"version":3,"names":["SwaggerUIMapper","build","swaggerProp","keyName","ui","title","label","description","this","generateLabel","readOnly","format","widget","validators","push","name","spaced","replace","split","filter","w","length","map","word","charAt","toUpperCase","slice","toLowerCase","join","trim","__exports","__esModule"],"sources":["SwaggerUIMapper.ts"],"sourcesContent":["/**\n * @file SwaggerUIMapper.ts\n * @description Utility class for mapping OpenAPI properties and formats into MetaUI IUIDirectives.\n */\nimport { IUIDirective } from \"../interfaces/ISchema\";\n\nexport class SwaggerUIMapper {\n /**\n * Evaluates an OpenAPI property definition and constructs a MetaUI IUIDirective block.\n * Extracts labels from title/description, maps readOnly state, and assigns \n * specific Fiori widgets based on the OpenAPI 'format' property.\n * \n * @param {any} swaggerProp The raw OpenAPI property schema.\n * @param {string} keyName The technical JSON key of the property.\n * @returns {IUIDirective} The constructed MetaUI UI orchestration directive.\n */\n public static build(swaggerProp: any, keyName: string): IUIDirective {\n const ui: IUIDirective = {};\n\n // Labeling\n if (swaggerProp.title) {\n ui.label = swaggerProp.title;\n } else if (swaggerProp.description) {\n ui.label = swaggerProp.description;\n } else {\n ui.label = this.generateLabel(keyName);\n }\n\n // State\n if (swaggerProp.readOnly === true) {\n ui.readOnly = true;\n }\n\n // Formats to Widgets\n if (swaggerProp.format) {\n switch (swaggerProp.format) {\n case \"date-time\":\n ui.widget = \"datetime\";\n break;\n case \"date\":\n ui.widget = \"date\";\n break;\n case \"password\":\n ui.format = \"password\";\n break;\n case \"email\":\n ui.format = \"email\";\n break;\n case \"uri\":\n ui.format = \"url\";\n break;\n case \"uuid\":\n case \"ipv4\":\n case \"ipv6\":\n case \"hostname\":\n if (!ui.validators) ui.validators = [];\n ui.validators.push(swaggerProp.format);\n break;\n }\n }\n\n return ui;\n }\n\n /**\n * Generates a human-readable Title Case label from camelCase or snake_case technical keys.\n * \n * @param {string} name The technical property key.\n * @returns {string} The formatted human-readable label.\n */\n private static generateLabel(name: string): string {\n if (!name) return \"\";\n let spaced = name.replace(/([A-Z])/g, \" $1\").replace(/_/g, \" \");\n return spaced.split(' ')\n .filter(w => w.length > 0)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ')\n .trim();\n }\n}\n"],"mappings":"AAAA,kGAMO,MAAMA,EAUT,YAAcC,CAAMC,EAAkBC,GAClC,MAAMC,EAAmB,CAAC,EAG1B,GAAIF,EAAYG,MAAO,CACnBD,EAAGE,MAAQJ,EAAYG,KAC3B,MAAO,GAAIH,EAAYK,YAAa,CAChCH,EAAGE,MAAQJ,EAAYK,WAC3B,KAAO,CACHH,EAAGE,MAAQE,KAAKC,cAAcN,EAClC,CAGA,GAAID,EAAYQ,WAAa,KAAM,CAC/BN,EAAGM,SAAW,IAClB,CAGA,GAAIR,EAAYS,OAAQ,CACpB,OAAQT,EAAYS,QAChB,IAAK,YACDP,EAAGQ,OAAS,WACZ,MACJ,IAAK,OACDR,EAAGQ,OAAS,OACZ,MACJ,IAAK,WACDR,EAAGO,OAAS,WACZ,MACJ,IAAK,QACDP,EAAGO,OAAS,QACZ,MACJ,IAAK,MACDP,EAAGO,OAAS,MACZ,MACJ,IAAK,OACL,IAAK,OACL,IAAK,OACL,IAAK,WACD,IAAKP,EAAGS,WAAYT,EAAGS,WAAa,GACpCT,EAAGS,WAAWC,KAAKZ,EAAYS,QAC/B,MAEZ,CAEA,OAAOP,CACX,CAQA,oBAAeK,CAAcM,GACzB,IAAKA,EAAM,MAAO,GAClB,IAAIC,EAASD,EAAKE,QAAQ,WAAY,OAAOA,QAAQ,KAAM,KAC3D,OAAOD,EAAOE,MAAM,KACfC,OAAOC,GAAKA,EAAEC,OAAS,GACvBC,IAAIC,GAAQA,EAAKC,OAAO,GAAGC,cAAgBF,EAAKG,MAAM,GAAGC,eACzDC,KAAK,KACLC,MACT,EACH,IAAAC,EAAA,CAAAC,WAAA,MAAAD,EAAA9B,kBAAA,OAAA8B,CAAA","ignoreList":[],"sourceRoot":"swagger"}},{"offset":{"line":76,"column":0},"map":{"version":3,"names":["ExpressionBuilder","build","rule","bindingPath","modelName","parsedRule","replace","match","path","reserved","includes","basePath","startsWith","substring","parts","split","pop","contextPrefix","length","join","__exports","__esModule"],"sources":["ExpressionBuilder.ts"],"sourcesContent":["/**\n * @file ExpressionBuilder.ts\n * @description Safely parses and builds UI5 expression bindings from JSON Schema condition rules.\n */\n\nexport class ExpressionBuilder {\n /**\n * Safely converts a raw condition rule (e.g. \"$root.Status === 'NEW'\") into a valid UI5 \n * expression binding string, preserving relative vs absolute paths.\n * \n * @param rule The raw schema condition rule (e.g., \"$root.Category === 'A' || SubCategory === 'B'\").\n * @param bindingPath The absolute binding path of the current field (e.g., \"/Items/0/Category\").\n * @param modelName The UI5 JSONModel name (default \"meta\").\n * @returns {string} The fully formed UI5 expression binding (e.g., \"{= ${meta>/Status} === 'NEW' }\").\n */\n public static build(rule: string, bindingPath: string, modelName: string = \"meta\"): string {\n if (!rule) return \"{= true }\";\n\n let parsedRule = rule;\n\n // 1. Replace absolute $root paths\n // $root.Status -> ${meta>/Status}\n parsedRule = parsedRule.replace(/\\$root\\.([a-zA-Z0-9_.]+)/g, (match, path) => {\n return `\\${${modelName}>/${path.replace(/\\./g, '/')}}`;\n });\n\n // 2. Replace relative paths\n parsedRule = parsedRule.replace(/(?<!['\"\\${a-zA-Z0-9_.>/-])([a-zA-Z_][a-zA-Z0-9_.]+)(?!['\"a-zA-Z0-9_.(])/g, (match, path) => {\n const reserved = [\"true\", \"false\", \"null\", \"undefined\", \"Math\", \"String\", \"Number\", \"Array\", \"Object\"];\n if (reserved.includes(path)) return path;\n\n // Resolve relative to the current binding path context\n let basePath = bindingPath.startsWith(\"/\") ? bindingPath.substring(1) : bindingPath;\n const parts = basePath.split('/');\n parts.pop(); \n const contextPrefix = parts.length > 0 ? parts.join('/') + '/' : '';\n \n return `\\${${modelName}>/${contextPrefix}${path.replace(/\\./g, '/')}}`;\n });\n\n return `{= ${parsedRule} }`;\n }\n}\n"],"mappings":"AAAA,kGAKO,MAAMA,EAUT,YAAcC,CAAMC,EAAcC,EAAqBC,EAAoB,QACvE,IAAKF,EAAM,MAAO,YAElB,IAAIG,EAAaH,EAIjBG,EAAaA,EAAWC,QAAQ,4BAA6B,CAACC,EAAOC,IAC1D,MAAMJ,MAAcI,EAAKF,QAAQ,MAAO,SAInDD,EAAaA,EAAWC,QAAQ,2EAA4E,CAACC,EAAOC,KAChH,MAAMC,EAAW,CAAC,OAAQ,QAAS,OAAQ,YAAa,OAAQ,SAAU,SAAU,QAAS,UAC7F,GAAIA,EAASC,SAASF,GAAO,OAAOA,EAGpC,IAAIG,EAAWR,EAAYS,WAAW,KAAOT,EAAYU,UAAU,GAAKV,EACxE,MAAMW,EAAQH,EAASI,MAAM,KAC7BD,EAAME,MACN,MAAMC,EAAgBH,EAAMI,OAAS,EAAIJ,EAAMK,KAAK,KAAO,IAAM,GAEjE,MAAO,MAAMf,MAAca,IAAgBT,EAAKF,QAAQ,MAAO,UAGnE,MAAO,MAAMD,KACjB,EACH,IAAAe,EAAA,CAAAC,WAAA,MAAAD,EAAApB,oBAAA,OAAAoB,CAAA","ignoreList":[],"sourceRoot":"utils"}},{"offset":{"line":77,"column":0},"map":{"version":3,"names":["Logger","static","setDebugMode","enabled","this","debugMode","logInstance","sap","ui","require","Log","isDebugMode","debug","message","details","component","console","info","warn","warning","error","showErrorPopup","title","MessageBox","__exports","__esModule"],"sources":["Logger.ts"],"sourcesContent":["/**\n * @file Logger.ts\n * @description Centralized logging utility for MetaUI.\n * Wraps sap/base/Log and provides a global toggle for debug mode.\n */\n\nexport class Logger {\n private static debugMode: boolean = false;\n private static logInstance: unknown = null;\n\n /**\n * Toggles the global debug mode for MetaUI.\n * @param enabled Set to true to enable logging.\n */\n public static setDebugMode(enabled: boolean): void {\n this.debugMode = enabled;\n if (enabled && !this.logInstance) {\n sap.ui.require([\"sap/base/Log\"], (Log: Record<string, Function>) => {\n this.logInstance = Log;\n });\n }\n }\n\n /**\n * Checks if debug mode is currently active.\n */\n public static isDebugMode(): boolean {\n return this.debugMode;\n }\n\n public static debug(message: string, details?: string, component?: string): void {\n if (!this.debugMode) return;\n if (this.logInstance) {\n this.logInstance.debug(message, details, component || \"MetaUI\");\n } else {\n console.debug(`[MetaUI] ${message}`, details || \"\");\n }\n }\n\n public static info(message: string, details?: string, component?: string): void {\n if (!this.debugMode) return;\n if (this.logInstance) {\n this.logInstance.info(message, details, component || \"MetaUI\");\n } else {\n console.info(`[MetaUI] ${message}`, details || \"\");\n }\n }\n\n public static warn(message: string, details?: string, component?: string): void {\n if (!this.debugMode) return;\n if (this.logInstance) {\n this.logInstance.warning(message, details, component || \"MetaUI\");\n } else {\n console.warn(`[MetaUI] ${message}`, details || \"\");\n }\n }\n\n public static error(message: string, details?: string, component?: string): void {\n if (this.logInstance) {\n this.logInstance.error(message, details, component || \"MetaUI\");\n } else {\n console.error(`[MetaUI Error] ${message}`, details || \"\");\n }\n }\n\n /**\n * Pops up a MessageBox UI alert if debug mode is active.\n */\n public static showErrorPopup(message: string, title?: string): void {\n if (!this.debugMode) return;\n sap.ui.require([\"sap/m/MessageBox\"], (MessageBox: Record<string, Function>) => {\n (MessageBox as Record<string, Function>).error(message, { title: title || \"MetaUI Error\" });\n });\n }\n}\n"],"mappings":"AAAA,uFAMO,MAAMA,EACTC,iBAAoC,MACpCA,mBAAsC,KAMtC,mBAAcC,CAAaC,GACvBC,KAAKC,UAAYF,EACjB,GAAIA,IAAYC,KAAKE,YAAa,CAC9BC,IAAIC,GAAGC,QAAQ,CAAC,gBAAkBC,IAC9BN,KAAKE,YAAcI,GAE3B,CACJ,CAKA,kBAAcC,GACV,OAAOP,KAAKC,SAChB,CAEA,YAAcO,CAAMC,EAAiBC,EAAkBC,GACnD,IAAKX,KAAKC,UAAW,OACrB,GAAID,KAAKE,YAAa,CAClBF,KAAKE,YAAYM,MAAMC,EAASC,EAASC,GAAa,SAC1D,KAAO,CACHC,QAAQJ,MAAM,YAAYC,IAAWC,GAAW,GACpD,CACJ,CAEA,WAAcG,CAAKJ,EAAiBC,EAAkBC,GAClD,IAAKX,KAAKC,UAAW,OACrB,GAAID,KAAKE,YAAa,CAClBF,KAAKE,YAAYW,KAAKJ,EAASC,EAASC,GAAa,SACzD,KAAO,CACHC,QAAQC,KAAK,YAAYJ,IAAWC,GAAW,GACnD,CACJ,CAEA,WAAcI,CAAKL,EAAiBC,EAAkBC,GAClD,IAAKX,KAAKC,UAAW,OACrB,GAAID,KAAKE,YAAa,CAClBF,KAAKE,YAAYa,QAAQN,EAASC,EAASC,GAAa,SAC5D,KAAO,CACHC,QAAQE,KAAK,YAAYL,IAAWC,GAAW,GACnD,CACJ,CAEA,YAAcM,CAAMP,EAAiBC,EAAkBC,GACnD,GAAIX,KAAKE,YAAa,CAClBF,KAAKE,YAAYc,MAAMP,EAASC,EAASC,GAAa,SAC1D,KAAO,CACHC,QAAQI,MAAM,kBAAkBP,IAAWC,GAAW,GAC1D,CACJ,CAKA,qBAAcO,CAAeR,EAAiBS,GAC1C,IAAKlB,KAAKC,UAAW,OACrBE,IAAIC,GAAGC,QAAQ,CAAC,oBAAsBc,IACjCA,EAAwCH,MAAMP,EAAS,CAAES,MAAOA,GAAS,kBAElF,EACH,IAAAE,EAAA,CAAAC,WAAA,MAAAD,EAAAxB,SAAA,OAAAwB,CAAA","ignoreList":[],"sourceRoot":"utils"}},{"offset":{"line":78,"column":0},"map":{"version":3,"names":[],"sources":["library-preload.js?bundle-code-0"],"mappings":"AAAA;AACA","sourcesContent":["sap.ui.require.preload({\n"],"sourceRoot":""}},{"offset":{"line":80,"column":0},"map":{"version":3,"file":"ILayoutManager.js","names":[],"sources":[],"mappings":"AAAA","ignoreList":[],"sourceRoot":"interfaces"}},{"offset":{"line":83,"column":0},"map":{"version":3,"file":"IPipeline.js","names":[],"sources":[],"mappings":"AAAA","ignoreList":[],"sourceRoot":"interfaces"}},{"offset":{"line":86,"column":0},"map":{"version":3,"file":"IPlugin.js","names":[],"sources":[],"mappings":"AAAA","ignoreList":[],"sourceRoot":"interfaces"}},{"offset":{"line":89,"column":0},"map":{"version":3,"file":"ISchema.js","names":[],"sources":[],"mappings":"AAAA","ignoreList":[],"sourceRoot":"interfaces"}},{"offset":{"line":92,"column":0},"map":{"version":3,"file":"ISchemaBuilderPlugin.js","names":[],"sources":[],"mappings":"AAAA","ignoreList":[],"sourceRoot":"interfaces"}}]}
|