iobroker.mywebui 1.84.0 → 1.86.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/default-controls/controls/analog_points/scada_point_panel.control +1 -1
  2. package/default-controls/controls/input_controls/input_with_button.control +1 -1
  3. package/default-controls/controls/theme/theme-toggle.control +1 -0
  4. package/default-controls/controls/txtviewer/TextViewer.control +1 -1
  5. package/dist/backend/3d-editor-integration.js +1 -1
  6. package/dist/backend/ImportmapCreator.js +1 -1
  7. package/dist/backend/UploadHelper.js +1 -1
  8. package/dist/backend/main.js +1 -1
  9. package/io-package.json +1 -1
  10. package/package.json +1 -1
  11. package/scripts/_build_themetoggle.py +84 -0
  12. package/scripts/_theme_all.py +91 -21
  13. package/www/3d-editor/js/Animation.js +1 -1
  14. package/www/3d-editor/js/AnimationResizer.js +1 -1
  15. package/www/3d-editor/js/Command.js +1 -1
  16. package/www/3d-editor/js/Config.js +1 -1
  17. package/www/3d-editor/js/Editor.js +1 -1
  18. package/www/3d-editor/js/EditorControls.js +1 -1
  19. package/www/3d-editor/js/GLTFImportDialog.js +1 -1
  20. package/www/3d-editor/js/History.js +1 -1
  21. package/www/3d-editor/js/Loader.js +1 -1
  22. package/www/3d-editor/js/LoaderUtils.js +1 -1
  23. package/www/3d-editor/js/Menubar.Add.js +1 -1
  24. package/www/3d-editor/js/Menubar.Edit.js +1 -1
  25. package/www/3d-editor/js/Menubar.File.js +1 -1
  26. package/www/3d-editor/js/Menubar.Help.js +1 -1
  27. package/www/3d-editor/js/Menubar.Render.js +1 -1
  28. package/www/3d-editor/js/Menubar.Status.js +1 -1
  29. package/www/3d-editor/js/Menubar.View.js +1 -1
  30. package/www/3d-editor/js/Menubar.js +1 -1
  31. package/www/3d-editor/js/Player.js +1 -1
  32. package/www/3d-editor/js/Resizer.js +1 -1
  33. package/www/3d-editor/js/Script.js +1 -1
  34. package/www/3d-editor/js/Selector.js +1 -1
  35. package/www/3d-editor/js/Sidebar.Geometry.BoxGeometry.js +1 -1
  36. package/www/3d-editor/js/Sidebar.Geometry.BufferGeometry.js +1 -1
  37. package/www/3d-editor/js/Sidebar.Geometry.CapsuleGeometry.js +1 -1
  38. package/www/3d-editor/js/Sidebar.Geometry.CircleGeometry.js +1 -1
  39. package/www/3d-editor/js/Sidebar.Geometry.CylinderGeometry.js +1 -1
  40. package/www/3d-editor/js/Sidebar.Geometry.DodecahedronGeometry.js +1 -1
  41. package/www/3d-editor/js/Sidebar.Geometry.ExtrudeGeometry.js +1 -1
  42. package/www/3d-editor/js/Sidebar.Geometry.IcosahedronGeometry.js +1 -1
  43. package/www/3d-editor/js/Sidebar.Geometry.LatheGeometry.js +1 -1
  44. package/www/3d-editor/js/Sidebar.Geometry.Modifiers.js +1 -1
  45. package/www/3d-editor/js/Sidebar.Geometry.OctahedronGeometry.js +1 -1
  46. package/www/3d-editor/js/Sidebar.Geometry.PlaneGeometry.js +1 -1
  47. package/www/3d-editor/js/Sidebar.Geometry.RingGeometry.js +1 -1
  48. package/www/3d-editor/js/Sidebar.Geometry.ShapeGeometry.js +1 -1
  49. package/www/3d-editor/js/Sidebar.Geometry.SphereGeometry.js +1 -1
  50. package/www/3d-editor/js/Sidebar.Geometry.TetrahedronGeometry.js +1 -1
  51. package/www/3d-editor/js/Sidebar.Geometry.TextGeometry.js +1 -1
  52. package/www/3d-editor/js/Sidebar.Geometry.TorusGeometry.js +1 -1
  53. package/www/3d-editor/js/Sidebar.Geometry.TorusKnotGeometry.js +1 -1
  54. package/www/3d-editor/js/Sidebar.Geometry.TubeGeometry.js +1 -1
  55. package/www/3d-editor/js/Sidebar.Geometry.js +1 -1
  56. package/www/3d-editor/js/Sidebar.Material.BooleanProperty.js +1 -1
  57. package/www/3d-editor/js/Sidebar.Material.ColorProperty.js +1 -1
  58. package/www/3d-editor/js/Sidebar.Material.ConstantProperty.js +1 -1
  59. package/www/3d-editor/js/Sidebar.Material.MapProperty.js +1 -1
  60. package/www/3d-editor/js/Sidebar.Material.NumberProperty.js +1 -1
  61. package/www/3d-editor/js/Sidebar.Material.Program.js +1 -1
  62. package/www/3d-editor/js/Sidebar.Material.RangeValueProperty.js +1 -1
  63. package/www/3d-editor/js/Sidebar.Material.js +1 -1
  64. package/www/3d-editor/js/Sidebar.Object.js +1 -1
  65. package/www/3d-editor/js/Sidebar.Project.App.js +1 -1
  66. package/www/3d-editor/js/Sidebar.Project.Materials.js +1 -1
  67. package/www/3d-editor/js/Sidebar.Project.Renderer.js +1 -1
  68. package/www/3d-editor/js/Sidebar.Project.Resources.js +1 -1
  69. package/www/3d-editor/js/Sidebar.Project.js +1 -1
  70. package/www/3d-editor/js/Sidebar.Properties.js +1 -1
  71. package/www/3d-editor/js/Sidebar.Scene.js +1 -1
  72. package/www/3d-editor/js/Sidebar.Script.js +1 -1
  73. package/www/3d-editor/js/Sidebar.Settings.History.js +1 -1
  74. package/www/3d-editor/js/Sidebar.Settings.Shortcuts.js +1 -1
  75. package/www/3d-editor/js/Sidebar.Settings.js +1 -1
  76. package/www/3d-editor/js/Sidebar.js +1 -1
  77. package/www/3d-editor/js/Storage.js +1 -1
  78. package/www/3d-editor/js/Strings.js +1 -1
  79. package/www/3d-editor/js/TextureParametersDialog.js +1 -1
  80. package/www/3d-editor/js/Toolbar.js +1 -1
  81. package/www/3d-editor/js/Viewport.Controls.js +1 -1
  82. package/www/3d-editor/js/Viewport.Info.js +1 -1
  83. package/www/3d-editor/js/Viewport.Pathtracer.js +1 -1
  84. package/www/3d-editor/js/Viewport.ViewHelper.js +1 -1
  85. package/www/3d-editor/js/Viewport.XR.js +1 -1
  86. package/www/3d-editor/js/Viewport.js +1 -1
  87. package/www/3d-editor/js/commands/AddObjectCommand.js +1 -1
  88. package/www/3d-editor/js/commands/AddScriptCommand.js +1 -1
  89. package/www/3d-editor/js/commands/Commands.js +1 -1
  90. package/www/3d-editor/js/commands/MoveObjectCommand.js +1 -1
  91. package/www/3d-editor/js/commands/MultiCmdsCommand.js +1 -1
  92. package/www/3d-editor/js/commands/RemoveObjectCommand.js +1 -1
  93. package/www/3d-editor/js/commands/RemoveScriptCommand.js +1 -1
  94. package/www/3d-editor/js/commands/SetColorCommand.js +1 -1
  95. package/www/3d-editor/js/commands/SetGeometryCommand.js +1 -1
  96. package/www/3d-editor/js/commands/SetGeometryValueCommand.js +1 -1
  97. package/www/3d-editor/js/commands/SetMaterialColorCommand.js +1 -1
  98. package/www/3d-editor/js/commands/SetMaterialCommand.js +1 -1
  99. package/www/3d-editor/js/commands/SetMaterialMapCommand.js +1 -1
  100. package/www/3d-editor/js/commands/SetMaterialRangeCommand.js +1 -1
  101. package/www/3d-editor/js/commands/SetMaterialValueCommand.js +1 -1
  102. package/www/3d-editor/js/commands/SetMaterialVectorCommand.js +1 -1
  103. package/www/3d-editor/js/commands/SetPositionCommand.js +1 -1
  104. package/www/3d-editor/js/commands/SetRotationCommand.js +1 -1
  105. package/www/3d-editor/js/commands/SetScaleCommand.js +1 -1
  106. package/www/3d-editor/js/commands/SetSceneCommand.js +1 -1
  107. package/www/3d-editor/js/commands/SetScriptValueCommand.js +1 -1
  108. package/www/3d-editor/js/commands/SetShadowValueCommand.js +1 -1
  109. package/www/3d-editor/js/commands/SetTextureParametersCommand.js +1 -1
  110. package/www/3d-editor/js/commands/SetUuidCommand.js +1 -1
  111. package/www/3d-editor/js/commands/SetValueCommand.js +1 -1
  112. package/www/dist/frontend/bundle/chunk-3C6XC7RW.js +1 -1
  113. package/www/dist/frontend/bundle/chunk-3WGNLIWJ.js +3 -3
  114. package/www/dist/frontend/bundle/chunk-3YK3Y2SJ.js +1 -1
  115. package/www/dist/frontend/bundle/chunk-43HEBO5G.js +3 -3
  116. package/www/dist/frontend/bundle/chunk-5MUGMRXU.js +1 -1
  117. package/www/dist/frontend/bundle/chunk-5UBRCTRX.js +3 -3
  118. package/www/dist/frontend/bundle/chunk-65A3PNMG.js +1 -1
  119. package/www/dist/frontend/bundle/chunk-7CWDQGAG.js +3 -3
  120. package/www/dist/frontend/bundle/chunk-7PT7IGUJ.js +3 -3
  121. package/www/dist/frontend/bundle/chunk-AI5PDLDE.js +2 -2
  122. package/www/dist/frontend/bundle/chunk-AWKVUUKN.js +3 -3
  123. package/www/dist/frontend/bundle/chunk-B6NXWGSB.js +1 -1
  124. package/www/dist/frontend/bundle/chunk-BHSHNRXW.js +1 -1
  125. package/www/dist/frontend/bundle/chunk-BVONDEOL.js +3 -3
  126. package/www/dist/frontend/bundle/chunk-CHDKROX5.js +3 -3
  127. package/www/dist/frontend/bundle/chunk-DNCD2F6X.js +3 -3
  128. package/www/dist/frontend/bundle/chunk-FHF6DL5U.js +1 -1
  129. package/www/dist/frontend/bundle/chunk-FO56TEZH.js +3 -3
  130. package/www/dist/frontend/bundle/chunk-FSRRPQMX.js +3 -3
  131. package/www/dist/frontend/bundle/chunk-GLQNGCFL.js +1 -1
  132. package/www/dist/frontend/bundle/chunk-JBDSDK2C.js +3 -3
  133. package/www/dist/frontend/bundle/chunk-JSC66ZLQ.js +1 -1
  134. package/www/dist/frontend/bundle/chunk-K6IV7LKW.js +1 -1
  135. package/www/dist/frontend/bundle/chunk-KY73TL6O.js +3 -3
  136. package/www/dist/frontend/bundle/chunk-M6VVTDVX.js +3 -3
  137. package/www/dist/frontend/bundle/chunk-MECWXZRN.js +1 -1
  138. package/www/dist/frontend/bundle/chunk-N2YIZTB2.js +1 -1
  139. package/www/dist/frontend/bundle/chunk-NQ7L7KNT.js +3 -3
  140. package/www/dist/frontend/bundle/chunk-P7EOR36H.js +1 -1
  141. package/www/dist/frontend/bundle/chunk-PJYK24KZ.js +1 -1
  142. package/www/dist/frontend/bundle/chunk-PYLAW6UA.js +2 -2
  143. package/www/dist/frontend/bundle/chunk-QJJGP23I.js +1 -1
  144. package/www/dist/frontend/bundle/chunk-QV4IBWXA.js +1 -1
  145. package/www/dist/frontend/bundle/chunk-R6IQDPAP.js +3 -3
  146. package/www/dist/frontend/bundle/chunk-RTTBZOQU.js +3 -3
  147. package/www/dist/frontend/bundle/chunk-S4TLNW5D.js +1 -1
  148. package/www/dist/frontend/bundle/chunk-SE6N4ZEN.js +1 -1
  149. package/www/dist/frontend/bundle/chunk-SQHXO2IT.js +3 -3
  150. package/www/dist/frontend/bundle/chunk-T4AIQBBH.js +3 -3
  151. package/www/dist/frontend/bundle/chunk-U5Q332OH.js +1 -1
  152. package/www/dist/frontend/bundle/chunk-UIP324PP.js +1 -1
  153. package/www/dist/frontend/bundle/chunk-V27IRYSL.js +1 -1
  154. package/www/dist/frontend/bundle/chunk-V4C5FGJL.js +3 -3
  155. package/www/dist/frontend/bundle/chunk-WED7CGWA.js +3 -3
  156. package/www/dist/frontend/bundle/chunk-WQ5H5LTG.js +2 -2
  157. package/www/dist/frontend/bundle/chunk-WU54NCEU.js +1 -1
  158. package/www/dist/frontend/bundle/chunk-XFO5FUCN.js +1 -1
  159. package/www/dist/frontend/bundle/chunk-XWAQ2BWM.js +3 -3
  160. package/www/dist/frontend/bundle/chunk-YTQCHNRQ.js +3 -3
  161. package/www/dist/frontend/bundle/chunk-YUSK4FN3.js +3 -3
  162. package/www/dist/frontend/bundle/chunk-Z34BSG5O.js +3 -3
  163. package/www/dist/frontend/bundle/common/IobrokerHandler.js +1 -1
  164. package/www/dist/frontend/bundle/runtime/CustomControls.js +1 -1
  165. package/www/dist/frontend/bundle/runtime/ScreenViewer.js +1 -1
  166. package/www/dist/frontend/bundle/runtime/controls.js +3 -3
  167. package/www/dist/frontend/bundle/runtime/init.js +3 -3
  168. package/www/dist/frontend/common/Common.globals.js +1 -1
  169. package/www/dist/frontend/common/IobrokerHandler.js +1 -1
  170. package/www/dist/frontend/common/Runtime.js +1 -1
  171. package/www/dist/frontend/config/CommandHandling.js +1 -1
  172. package/www/dist/frontend/config/ConfigureWebcomponentDesigner.js +1 -1
  173. package/www/dist/frontend/config/DockHelper.js +1 -1
  174. package/www/dist/frontend/config/IobrokerWebui3DDriveEngine.js +1 -1
  175. package/www/dist/frontend/config/IobrokerWebui3DScreenEditor.js +3 -3
  176. package/www/dist/frontend/config/IobrokerWebui3DScreenPropertiesPanel.js +2 -2
  177. package/www/dist/frontend/config/IobrokerWebui3DScreenViewer.js +3 -3
  178. package/www/dist/frontend/config/IobrokerWebuiAppShell.js +3 -3
  179. package/www/dist/frontend/config/IobrokerWebuiBindingsEditor.js +1 -1
  180. package/www/dist/frontend/config/IobrokerWebuiConfirmationWrapper.js +3 -3
  181. package/www/dist/frontend/config/IobrokerWebuiControlPropertiesEditor.js +3 -3
  182. package/www/dist/frontend/config/IobrokerWebuiDynamicPropsEditor.js +1 -1
  183. package/www/dist/frontend/config/IobrokerWebuiEventAssignment.js +1 -1
  184. package/www/dist/frontend/config/IobrokerWebuiIconsView.js +2 -2
  185. package/www/dist/frontend/config/IobrokerWebuiMonacoEditor.js +3 -3
  186. package/www/dist/frontend/config/IobrokerWebuiPropertyGrid.js +1 -1
  187. package/www/dist/frontend/config/IobrokerWebuiScreenEditor.js +1 -1
  188. package/www/dist/frontend/config/IobrokerWebuiScreensView.js +2 -2
  189. package/www/dist/frontend/config/IobrokerWebuiSignalPropertyEditor.js +1 -1
  190. package/www/dist/frontend/config/IobrokerWebuiSolutionExplorer.js +3 -3
  191. package/www/dist/frontend/config/IobrokerWebuiTranslationEditor.js +1 -1
  192. package/www/dist/frontend/config/IobrokerWebuiWidgetGallery.js +3 -3
  193. package/www/dist/frontend/helper/DialogHelper.js +3 -3
  194. package/www/dist/frontend/helper/EsprimaHelper.js +1 -1
  195. package/www/dist/frontend/helper/Helper.js +1 -1
  196. package/www/dist/frontend/helper/LayoutHelper.js +1 -1
  197. package/www/dist/frontend/helper/XmlHelper.js +1 -1
  198. package/www/dist/frontend/helper/ZipHelper.js +1 -1
  199. package/www/dist/frontend/runtime/AnimationService.js +1 -1
  200. package/www/dist/frontend/runtime/CustomControls.js +1 -1
  201. package/www/dist/frontend/runtime/DynamicElementProperties.js +1 -1
  202. package/www/dist/frontend/runtime/HabPanelLikeMenu.js +3 -3
  203. package/www/dist/frontend/runtime/NavigationShell.js +1 -1
  204. package/www/dist/frontend/runtime/RuntimeTheme.js +1 -1
  205. package/www/dist/frontend/runtime/ScreenViewer.js +3 -3
  206. package/www/dist/frontend/runtime/TranslateableText.js +2 -2
  207. package/www/dist/frontend/runtime/VisibilityService.js +1 -1
  208. package/www/dist/frontend/runtime/controls.js +1 -1
  209. package/www/dist/frontend/runtime/init.js +1 -1
  210. package/www/dist/frontend/scripting/IobrokerWebuiScriptSystem.js +1 -1
  211. package/www/dist/frontend/scripting/blockly/OpenScreen.js +1 -1
  212. package/www/dist/frontend/scripting/blockly/webuiBlocklyToolbox.js +1 -1
  213. package/www/dist/frontend/services/DynamicPropertiesHelper.js +1 -1
  214. package/www/dist/frontend/services/IobrokerWebuiBindableLocalObjectsService.js +1 -1
  215. package/www/dist/frontend/services/IobrokerWebuiBindableObjectDragDropService.js +1 -1
  216. package/www/dist/frontend/services/IobrokerWebuiBindableObjectsForPropertiesService.js +1 -1
  217. package/www/dist/frontend/services/IobrokerWebuiBindableObjectsService.js +1 -1
  218. package/www/dist/frontend/services/IobrokerWebuiConfigButtonProvider.js +1 -1
  219. package/www/dist/frontend/services/IobrokerWebuiCopyPasteService.js +1 -1
  220. package/www/dist/frontend/services/IobrokerWebuiCustomControlEventsService.js +1 -1
  221. package/www/dist/frontend/services/IobrokerWebuiCustomElementContextMenu.js +1 -1
  222. package/www/dist/frontend/services/IobrokerWebuiDemoProviderService.js +1 -1
  223. package/www/dist/frontend/services/IobrokerWebuiDynamicPropertiesService.js +1 -1
  224. package/www/dist/frontend/services/IobrokerWebuiEventsService.js +1 -1
  225. package/www/dist/frontend/services/IobrokerWebuiExternalDragDropService.js +1 -1
  226. package/www/dist/frontend/services/IobrokerWebuiLitPropertiesService.js +1 -1
  227. package/www/dist/frontend/services/IobrokerWebuiPropertiesService.js +1 -1
  228. package/www/dist/frontend/services/IobrokerWebuiPropertyGroupsService.js +1 -1
  229. package/www/dist/frontend/services/IobrokerWebuiRefactorService.js +1 -1
  230. package/www/dist/frontend/services/IobrokerWebuiScreenContextMenu.js +1 -1
  231. package/www/dist/frontend/services/IobrokerWebuiSpecialPropertiesService.js +1 -1
  232. package/www/dist/frontend/services/IobrokerWebuiSpectrumEditorService.js +1 -1
  233. package/www/dist/frontend/services/IobrokerWebuiVisibilityPropertiesService.js +1 -1
  234. package/www/dist/frontend/services/LayoutComponentsPropertiesService.js +1 -1
  235. package/www/dist/frontend/widgets/OrthoFlowLineTool.js +1 -1
  236. package/www/dist/frontend/widgets/customElementsObserver.js +1 -1
  237. package/www/dist/frontend/widgets/importWidgetFiles.js +1 -1
  238. package/www/dist/frontend/widgets/importWidgetFilesRuntime.js +1 -1
  239. package/www/dist/frontend/widgets/layout-components.js +1 -1
  240. package/www/dist/frontend/widgets/layout-placement-services.js +1 -1
  241. package/www/dist/frontend/widgets/testElement.js +1 -1
@@ -1 +1 @@
1
- {"html": "<div id=\"panel-container\" style=\"width:100%;height:100%;border:2px solid rgb(58, 90, 90);border-radius:4px;padding:8px;display:flex;flex-direction:column;font:&quot;Times New Roman&quot;, serif;background:rgb(90, 122, 122);\">\n <div style=\"display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;flex-shrink:0;\">\n <div id=\"point-name\" style=\"color:#fff;text-align:center;flex:1;font:bold 14px &quot;Times New Roman&quot;, serif;\">Point</div>\n <svg id=\"trend-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" title=\"Show Trend\" style=\"cursor:pointer;fill:none;stroke:#fff;stroke-width:2;margin-left:4px;flex-shrink:0;\">\n <polyline points=\"3 17 9 11 13 15 21 7\"></polyline>\n <polyline points=\"14 7 21 7 21 14\"></polyline>\n </svg>\n </div>\n <div style=\"display:grid;grid-template-columns:auto 1fr auto;gap:4px 8px;align-items:center;flex:1;\">\n <div id=\"label1\" style=\"color:#e0e0e0;font:italic 12px &quot;Times New Roman&quot;, serif;\"></div>\n <div id=\"value1\" bind-content:text=\"??value1_value\" style=\"color:#fff;text-align:center;font:bold 16px &quot;Times New Roman&quot;, serif;\">NaN</div>\n <div id=\"unit1\" style=\"color:#e0e0e0;font:italic 11px &quot;Times New Roman&quot;, serif;\"></div>\n <div id=\"label2\" style=\"color:#e0e0e0;display:none;font:italic 12px &quot;Times New Roman&quot;, serif;\"></div>\n <div id=\"value2\" style=\"color:#fff;text-align:center;display:none;font:bold 16px &quot;Times New Roman&quot;, serif;\"></div>\n <div id=\"unit2\" style=\"color:#e0e0e0;display:none;font:italic 11px &quot;Times New Roman&quot;, serif;\"></div>\n </div>\n <div id=\"action-button\" style=\"margin-top:8px;text-align:center;display:none;flex-shrink:0;\">\n<button id=\"action-btn\" style=\"border:1px solid rgb(58, 90, 90);color:#fff;border-radius:3px;cursor:pointer;background:rgb(74, 106, 106);font:11px &quot;Times New Roman&quot;, serif;padding:4px 12px;\">Button</button>\n </div>\n</div>\n<dialog id=\"trend-dialog\" bind-css:width=\"??grafana_dialogwidth\" bind-css:height=\"??grafana_dialogheight\" style=\"overflow:hidden;border:2px solid rgb(58, 90, 90);border-radius:8px;padding:0px;background:rgb(255, 255, 255);\">\n <div id=\"dialog-header\" style=\"color:#fff;padding:12px;display:flex;justify-content:space-between;align-items:center;background:rgb(90, 122, 122);\">\n <h3 id=\"dialog-title\" style=\"margin:0px;font:16px &quot;Times New Roman&quot;, serif;\">Trend</h3>\n <button id=\"close-dialog\" style=\"border:initial none initial;color:#fff;cursor:pointer;padding:0px;width:30px;height:30px;background:transparent;font:24px &quot;Times New Roman&quot;, serif;\">×</button>\n </div>\n <div id=\"iframecontainerdiv1\" style=\"padding:0px;width:100%;height:91%;\">\n<iframe id=\"grafana-iframe\" frameborder=\"0\" style=\"width:100%;height:100%;border:initial none initial;\"></iframe>\n </div>\n</dialog>\n", "style": "#trend-dialog{\r\n width: 600px;\r\n height: 600px;\r\n}\r\n", "script": "let protocol = window.location.protocol;\nlet ip = window.location.hostname;\nlet port = window.location.port;\nlet baseaddress = protocol+\"//\"+ip+\":\"+port;\nfunction formatValue(value, options) {\n if (value === null || value === undefined || value === '' || isNaN(value)) {\n return 'NaN';\n }\n\n let numValue = Number(value);\n\n // Apply scaling\n if (options.scale && options.scale !== 1) {\n numValue = numValue * Number(options.scale);\n }\n\n // Apply offset\n if (options.offset && options.offset !== 0) {\n numValue = numValue + Number(options.offset);\n }\n\n // Apply min/max limits\n if (options.minLimit !== undefined && options.minLimit !== null && options.minLimit !== '') {\n const min = Number(options.minLimit);\n if (numValue < min) numValue = min;\n }\n if (options.maxLimit !== undefined && options.maxLimit !== null && options.maxLimit !== '') {\n const max = Number(options.maxLimit);\n if (numValue > max) numValue = max;\n }\n\n // Apply rounding\n let formattedValue;\n const decimals = options.decimals !== undefined ? Number(options.decimals) : 2;\n\n switch (options.roundMode) {\n case 'floor':\n formattedValue = Math.floor(numValue * Math.pow(10, decimals)) / Math.pow(10, decimals);\n break;\n case 'ceil':\n formattedValue = Math.ceil(numValue * Math.pow(10, decimals)) / Math.pow(10, decimals);\n break;\n case 'round':\n default:\n formattedValue = Math.round(numValue * Math.pow(10, decimals)) / Math.pow(10, decimals);\n break;\n }\n\n // Format to fixed decimals\n let result = formattedValue.toFixed(decimals);\n\n // Add thousand separator if enabled\n if (options.thousandSep) {\n const parts = result.split('.');\n parts[0] = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, options.thousandSep);\n result = parts.join('.');\n }\n\n // Add prefix/suffix\n if (options.prefix) result = options.prefix + result;\n if (options.suffix) result = result + options.suffix;\n\n return result;\n}\nexport async function init(instance) {\n instance._bindingsRefresh();\n\n applyTheming(instance);\n updatePanel(instance);\n\n instance._assignEvent('point-name-changed', () => updatePanel(instance));\n instance._assignEvent('value1_label-changed', () => updatePanel(instance));\n instance._assignEvent('value1_value-changed', () => updatePanel(instance));\n instance._assignEvent('value1_unit-changed', () => updatePanel(instance));\n instance._assignEvent('value2_label-changed', () => updatePanel(instance));\n instance._assignEvent('value2_value-changed', () => updatePanel(instance));\n instance._assignEvent('value2_unit-changed', () => updatePanel(instance));\n instance._assignEvent('theme-changed', () => applyTheming(instance));\n instance._assignEvent('grafana_url-changed', () => { });\n\n instance._assignEvent('show-button-changed', () => updatePanel(instance));\n instance._assignEvent('button-text-changed', () => updatePanel(instance));\n\n // SCADA functions event listeners\n instance._assignEvent('value1_decimals-changed', () => updatePanel(instance));\n instance._assignEvent('value1_roundmode-changed', () => updatePanel(instance));\n instance._assignEvent('value1_scale-changed', () => updatePanel(instance));\n instance._assignEvent('value1_offset-changed', () => updatePanel(instance));\n instance._assignEvent('value1_minlimit-changed', () => updatePanel(instance));\n instance._assignEvent('value1_maxlimit-changed', () => updatePanel(instance));\n instance._assignEvent('value1_prefix-changed', () => updatePanel(instance));\n instance._assignEvent('value1_suffix-changed', () => updatePanel(instance));\n instance._assignEvent('value1_thousandsep-changed', () => updatePanel(instance));\n instance._assignEvent('value2_decimals-changed', () => updatePanel(instance));\n instance._assignEvent('value2_roundmode-changed', () => updatePanel(instance));\n instance._assignEvent('value2_scale-changed', () => updatePanel(instance));\n instance._assignEvent('value2_offset-changed', () => updatePanel(instance));\n instance._assignEvent('value2_minlimit-changed', () => updatePanel(instance));\n instance._assignEvent('value2_maxlimit-changed', () => updatePanel(instance));\n instance._assignEvent('value2_prefix-changed', () => updatePanel(instance));\n instance._assignEvent('value2_suffix-changed', () => updatePanel(instance));\n instance._assignEvent('value2_thousandsep-changed', () => updatePanel(instance));\n\n const trendIcon = instance._getDomElement('trend-icon');\n const dialog = instance._getDomElement('trend-dialog');\n const closeBtn = instance._getDomElement('close-dialog');\n const iframe = instance._getDomElement('grafana-iframe');\n const dialogTitle = instance._getDomElement('dialog-title');\n\n /*if (!instance.grafanaUrl || instance.grafanaUrl.trim() === \"\") {\n console.log(\"Grafana URL boşdur!\");\n } else {\n // URL boş deyilsə, parametrləri əlavə et\n const params = new URLSearchParams({\n \"var-selected_state\": instance.grafana_selected_state_name1,\n \"var-selected_state2\": instance.grafana_selected_state_name2,\n \"var-tag_name\": instance.pointName,\n kiosk: \"\" // kiosk parametri əlavə olunur\n });\n\n\n\n const finalUrl = `${instance.grafanaUrl}?${params.toString()}`;\n // instance.grafanaUrl = finalUrl;\n }*/\n\n\n\n\n\n if (trendIcon && dialog) {\n trendIcon.addEventListener('click', async() => {\n if (!instance.grafana_url || instance.grafana_url.trim() === \"\") {\n console.log(\"Grafana URL boşdur!\");\n } else {\n // URL obyektini qururuq\n const url = new URL(instance.grafana_url, baseaddress); // baza hostu əlavə et\n\n // Mövcud parametrləri götürürük\n const params = url.searchParams;\n\n // İstədiyin parametrlərə dəyər ver\n params.set(\"var-selected_state\", instance.grafana_selected_state_name1);\n params.set(\"var-selected_state2\", instance.grafana_selected_state_name2);\n params.set(\"var-tag_name\", instance.pointName);\n\n\n // Yenilənmiş URL\n const finalUrl = `${url.href}&kiosk`;\n //console.log(finalUrl);\n\n //const grafanaUrl = instance.grafanaUrl || 'about:blank';\n // ioBroker-dən cari useri al\n iframe.src = finalUrl;\n dialogTitle.textContent = (instance.pointName || 'Trend') + ' - Trend';\n dialog.showModal();\n \n\n /*const pointName = instance.pointName || 'Trend';\n iframe.src = finalUrl;\n dialogTitle.textContent = pointName + ' - Trend';\n dialog.showModal();*/\n }\n });\n }\n\n if (closeBtn && dialog) {\n closeBtn.addEventListener('click', () => {\n dialog.close();\n iframe.src = 'about:blank';\n });\n }\n\n if (dialog) {\n dialog.addEventListener('click', (e) => {\n const rect = dialog.getBoundingClientRect();\n if (e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom) {\n dialog.close();\n iframe.src = 'about:blank';\n }\n });\n }\n\n const actionBtn = instance._getDomElement('action-btn');\n if (actionBtn) {\n actionBtn.addEventListener('click', () => {\n const event = new CustomEvent('scada-point-button-clicked', {\n detail: { pointName: instance.pointName },\n bubbles: true\n });\n instance.dispatchEvent(event);\n });\n }\n}\n\nfunction updatePanel(instance) {\n const nameEl = instance._getDomElement('point-name');\n if (nameEl) nameEl.textContent = instance.pointName || 'Point';\n\n const label1El = instance._getDomElement('label1');\n const value1El = instance._getDomElement('value1');\n const unit1El = instance._getDomElement('unit1');\n if (label1El) label1El.textContent = instance.value1_label || '';\n\n // Format value1 with SCADA functions\n if (value1El) {\n const value1Options = {\n decimals: instance.value1_decimals,\n roundMode: instance.value1_roundmode,\n scale: instance.value1_scale,\n offset: instance.value1_offset,\n minLimit: instance.value1_minlimit,\n maxLimit: instance.value1_maxlimit,\n prefix: instance.value1_prefix,\n suffix: instance.value1_suffix,\n thousandSep: instance.value1_thousandsep\n };\n value1El.textContent = formatValue(instance.value1_value, value1Options);\n }\n\n if (unit1El) unit1El.textContent = instance.value1_unit || '';\n\n const label2El = instance._getDomElement('label2');\n const value2El = instance._getDomElement('value2');\n const unit2El = instance._getDomElement('unit2');\n const hasRow2 = instance.value2_label || instance.value2_value || instance.value2_unit;\n\n if (label2El) {\n label2El.textContent = instance.value2_label || '';\n label2El.style.display = hasRow2 ? 'block' : 'none';\n }\n if (value2El) {\n const value2Options = {\n decimals: instance.value2_decimals,\n roundMode: instance.value2_roundmode,\n scale: instance.value2_scale,\n offset: instance.value2_offset,\n minLimit: instance.value2_minlimit,\n maxLimit: instance.value2_maxlimit,\n prefix: instance.value2_prefix,\n suffix: instance.value2_suffix,\n thousandSep: instance.value2_thousandsep\n };\n value2El.textContent = formatValue(instance.value2_value, value2Options);\n value2El.style.display = hasRow2 ? 'block' : 'none';\n }\n if (unit2El) {\n unit2El.textContent = instance.value2_unit || '';\n unit2El.style.display = hasRow2 ? 'block' : 'none';\n }\n\n const buttonEl = instance._getDomElement('action-button');\n const buttonTextEl = instance._getDomElement('action-btn');\n if (buttonEl && buttonTextEl) {\n const showButton = instance.showButton === true || instance.showButton === 'true';\n buttonEl.style.display = showButton ? 'block' : 'none';\n buttonTextEl.textContent = instance.buttonText || 'Button';\n }\n}\n\nfunction applyTheming(instance) {\n const theme = instance.theme || 'default';\n const container = instance._getDomElement('panel-container');\n if (!container) return;\n\n const themes = {\n 'default': { bg: '#5a7a7a', border: '#3a5a5a', text: '#fff', label: '#e0e0e0', btnBg: '#4a6a6a' },\n 'dark': { bg: '#2d3436', border: '#000', text: '#fff', label: '#dfe6e9', btnBg: '#636e72' },\n 'light': { bg: '#dfe6e9', border: '#b2bec3', text: '#2d3436', label: '#636e72', btnBg: '#b2bec3' },\n 'blue': { bg: '#0984e3', border: '#0652DD', text: '#fff', label: '#dfe6e9', btnBg: '#74b9ff' },\n 'green': { bg: '#00b894', border: '#00a383', text: '#fff', label: '#d4f1e8', btnBg: '#55efc4' },\n 'red': { bg: '#d63031', border: '#b71c1c', text: '#fff', label: '#ffcccc', btnBg: '#ff7675' },\n 'purple': { bg: '#6c5ce7', border: '#5f3dc4', text: '#fff', label: '#e5dbff', btnBg: '#a29bfe' }\n };\n\n const colors = themes[theme] || themes['default'];\n container.style.background = colors.bg;\n container.style.borderColor = colors.border;\n\n const nameEl = instance._getDomElement('point-name');\n const value1El = instance._getDomElement('value1');\n const value2El = instance._getDomElement('value2');\n if (nameEl) nameEl.style.color = colors.text;\n if (value1El) value1El.style.color = colors.text;\n if (value2El) value2El.style.color = colors.text;\n\n const label1El = instance._getDomElement('label1');\n const label2El = instance._getDomElement('label2');\n const unit1El = instance._getDomElement('unit1');\n const unit2El = instance._getDomElement('unit2');\n if (label1El) label1El.style.color = colors.label;\n if (label2El) label2El.style.color = colors.label;\n if (unit1El) unit1El.style.color = colors.label;\n if (unit2El) unit2El.style.color = colors.label;\n\n const trendIcon = instance._getDomElement('trend-icon');\n if (trendIcon) trendIcon.style.stroke = colors.text;\n\n const actionBtn = instance._getDomElement('action-btn');\n if (actionBtn) {\n actionBtn.style.background = colors.btnBg;\n actionBtn.style.borderColor = colors.border;\n actionBtn.style.color = colors.text;\n }\n\n const dialog = instance._getDomElement('trend-dialog');\n if (dialog) {\n dialog.style.borderColor = colors.border;\n const header = instance._getDomElement('dialog-header');\n if (header) {\n header.style.background = colors.bg;\n header.style.color = colors.text;\n }\n }\n}\n\nexport function connectedCallback(instance)\n{\n \n}\n\nfunction getResolvedSignalId() {\n // bind-prop:value1 atributundan ham pattern-i oxu\n const raw = element.getAttribute('bind-prop:value1');\n if (!raw) return null;\n\n // {??propName} → screen[propName] ilə replace et\n return raw.replace(/\\{(\\?\\?([^}]+))\\}/g, (_, __, propName) => {\n return screen?.[propName] ?? '';\n });\n }", "properties": {"pointName": {"type": "string", "default": "DPT 010"}, "value1_value": {"type": "number"}, "value1_label": {"type": "string"}, "value1_unit": {"type": "string", "default": "kPa"}, "value2_label": {"type": "string"}, "value2_value": {"type": "number"}, "theme": {"type": "enum", "default": "default", "values": ["default", "dark", "light", "blue", "green", "red", "purple"]}, "value2_unit": {"type": "string"}, "grafana_url": {"type": "string"}, "grafana_selected_state_name1": {"type": "string"}, "grafana_selected_state_name2": {"type": "string"}, "showButton": {"type": "boolean"}, "buttonText": {"type": "string", "default": "Button"}, "grafana_dialogheight": {"type": "string"}, "grafana_dialogwidth": {"type": "string"}, "value1_decimals": {"type": "number", "default": "2"}, "value1_roundmode": {"type": "enum", "default": "round", "values": ["round", "floor", "ceil"]}, "value1_scale": {"type": "number", "default": "1"}, "value1_offset": {"type": "number"}, "value1_maxlimit": {"type": "number"}, "value1_minlimit": {"type": "number"}, "value1_prefix": {"type": "string"}, "value1_suffix": {"type": "string"}, "value1_thousandsep": {"type": "string"}, "value2_decimals": {"type": "number", "default": "2"}, "value2_roundmode": {"type": "enum", "default": "round", "values": ["round", "floor", "ceil"]}, "value2_scale": {"type": "number", "default": "1"}, "value2_offset": {"type": "number"}, "value2_minlimit": {"type": "number"}, "value2_maxlimit": {"type": "number"}, "value2_prefix": {"type": "string"}, "value2_suffix": {"type": "string"}, "value2_thousandsep": {"type": "string"}}, "settings": {"visibilityEnabled": "false", "visibilityGroups": "", "visibilityAction": "hide", "visibilityRedirectScreen": ""}}
1
+ {"html": "<div id=\"panel-container\" style=\"width:100%;height:100%;border:2px solid var(--ui-border,rgb(58, 90, 90));border-radius:4px;padding:8px;display:flex;flex-direction:column;font:&quot;Times New Roman&quot;, serif;background:var(--ui-surface,rgb(90, 122, 122));\">\n <div style=\"display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;flex-shrink:0;\">\n <div id=\"point-name\" style=\"color:var(--ui-text,#fff);text-align:center;flex:1;font:bold 14px &quot;Times New Roman&quot;, serif;\">Point</div>\n <svg id=\"trend-icon\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" title=\"Show Trend\" style=\"cursor:pointer;fill:none;stroke:#fff;stroke-width:2;margin-left:4px;flex-shrink:0;\">\n <polyline points=\"3 17 9 11 13 15 21 7\"></polyline>\n <polyline points=\"14 7 21 7 21 14\"></polyline>\n </svg>\n </div>\n <div style=\"display:grid;grid-template-columns:auto 1fr auto;gap:4px 8px;align-items:center;flex:1;\">\n <div id=\"label1\" style=\"color:var(--ui-text,#e0e0e0);font:italic 12px &quot;Times New Roman&quot;, serif;\"></div>\n <div id=\"value1\" bind-content:text=\"??value1_value\" style=\"color:var(--ui-text,#fff);text-align:center;font:bold 16px &quot;Times New Roman&quot;, serif;\">NaN</div>\n <div id=\"unit1\" style=\"color:var(--ui-text,#e0e0e0);font:italic 11px &quot;Times New Roman&quot;, serif;\"></div>\n <div id=\"label2\" style=\"color:var(--ui-text,#e0e0e0);display:none;font:italic 12px &quot;Times New Roman&quot;, serif;\"></div>\n <div id=\"value2\" style=\"color:var(--ui-text,#fff);text-align:center;display:none;font:bold 16px &quot;Times New Roman&quot;, serif;\"></div>\n <div id=\"unit2\" style=\"color:var(--ui-text,#e0e0e0);display:none;font:italic 11px &quot;Times New Roman&quot;, serif;\"></div>\n </div>\n <div id=\"action-button\" style=\"margin-top:8px;text-align:center;display:none;flex-shrink:0;\">\n<button id=\"action-btn\" style=\"border:1px solid var(--ui-border,rgb(58, 90, 90));color:var(--ui-text,#fff);border-radius:3px;cursor:pointer;background:rgb(74, 106, 106);font:11px &quot;Times New Roman&quot;, serif;padding:4px 12px;\">Button</button>\n </div>\n</div>\n<dialog id=\"trend-dialog\" bind-css:width=\"??grafana_dialogwidth\" bind-css:height=\"??grafana_dialogheight\" style=\"overflow:hidden;border:2px solid var(--ui-border,rgb(58, 90, 90));border-radius:8px;padding:0px;background:var(--ui-input,rgb(255, 255, 255));\">\n <div id=\"dialog-header\" style=\"color:var(--ui-text,#fff);padding:12px;display:flex;justify-content:space-between;align-items:center;background:var(--ui-surface,rgb(90, 122, 122));\">\n <h3 id=\"dialog-title\" style=\"margin:0px;font:16px &quot;Times New Roman&quot;, serif;\">Trend</h3>\n <button id=\"close-dialog\" style=\"border:initial none initial;color:var(--ui-text,#fff);cursor:pointer;padding:0px;width:30px;height:30px;background:transparent;font:24px &quot;Times New Roman&quot;, serif;\">×</button>\n </div>\n <div id=\"iframecontainerdiv1\" style=\"padding:0px;width:100%;height:91%;\">\n<iframe id=\"grafana-iframe\" frameborder=\"0\" style=\"width:100%;height:100%;border:initial none initial;\"></iframe>\n </div>\n</dialog>\n", "style": "#trend-dialog{\r\n width: 600px;\r\n height: 600px;\r\n}\r\n", "script": "let protocol = window.location.protocol;\nlet ip = window.location.hostname;\nlet port = window.location.port;\nlet baseaddress = protocol+\"//\"+ip+\":\"+port;\nfunction formatValue(value, options) {\n if (value === null || value === undefined || value === '' || isNaN(value)) {\n return 'NaN';\n }\n\n let numValue = Number(value);\n\n // Apply scaling\n if (options.scale && options.scale !== 1) {\n numValue = numValue * Number(options.scale);\n }\n\n // Apply offset\n if (options.offset && options.offset !== 0) {\n numValue = numValue + Number(options.offset);\n }\n\n // Apply min/max limits\n if (options.minLimit !== undefined && options.minLimit !== null && options.minLimit !== '') {\n const min = Number(options.minLimit);\n if (numValue < min) numValue = min;\n }\n if (options.maxLimit !== undefined && options.maxLimit !== null && options.maxLimit !== '') {\n const max = Number(options.maxLimit);\n if (numValue > max) numValue = max;\n }\n\n // Apply rounding\n let formattedValue;\n const decimals = options.decimals !== undefined ? Number(options.decimals) : 2;\n\n switch (options.roundMode) {\n case 'floor':\n formattedValue = Math.floor(numValue * Math.pow(10, decimals)) / Math.pow(10, decimals);\n break;\n case 'ceil':\n formattedValue = Math.ceil(numValue * Math.pow(10, decimals)) / Math.pow(10, decimals);\n break;\n case 'round':\n default:\n formattedValue = Math.round(numValue * Math.pow(10, decimals)) / Math.pow(10, decimals);\n break;\n }\n\n // Format to fixed decimals\n let result = formattedValue.toFixed(decimals);\n\n // Add thousand separator if enabled\n if (options.thousandSep) {\n const parts = result.split('.');\n parts[0] = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, options.thousandSep);\n result = parts.join('.');\n }\n\n // Add prefix/suffix\n if (options.prefix) result = options.prefix + result;\n if (options.suffix) result = result + options.suffix;\n\n return result;\n}\nexport async function init(instance) {\n instance._bindingsRefresh();\n\n applyTheming(instance);\n updatePanel(instance);\n\n instance._assignEvent('point-name-changed', () => updatePanel(instance));\n instance._assignEvent('value1_label-changed', () => updatePanel(instance));\n instance._assignEvent('value1_value-changed', () => updatePanel(instance));\n instance._assignEvent('value1_unit-changed', () => updatePanel(instance));\n instance._assignEvent('value2_label-changed', () => updatePanel(instance));\n instance._assignEvent('value2_value-changed', () => updatePanel(instance));\n instance._assignEvent('value2_unit-changed', () => updatePanel(instance));\n instance._assignEvent('theme-changed', () => applyTheming(instance));\n instance._assignEvent('grafana_url-changed', () => { });\n\n instance._assignEvent('show-button-changed', () => updatePanel(instance));\n instance._assignEvent('button-text-changed', () => updatePanel(instance));\n\n // SCADA functions event listeners\n instance._assignEvent('value1_decimals-changed', () => updatePanel(instance));\n instance._assignEvent('value1_roundmode-changed', () => updatePanel(instance));\n instance._assignEvent('value1_scale-changed', () => updatePanel(instance));\n instance._assignEvent('value1_offset-changed', () => updatePanel(instance));\n instance._assignEvent('value1_minlimit-changed', () => updatePanel(instance));\n instance._assignEvent('value1_maxlimit-changed', () => updatePanel(instance));\n instance._assignEvent('value1_prefix-changed', () => updatePanel(instance));\n instance._assignEvent('value1_suffix-changed', () => updatePanel(instance));\n instance._assignEvent('value1_thousandsep-changed', () => updatePanel(instance));\n instance._assignEvent('value2_decimals-changed', () => updatePanel(instance));\n instance._assignEvent('value2_roundmode-changed', () => updatePanel(instance));\n instance._assignEvent('value2_scale-changed', () => updatePanel(instance));\n instance._assignEvent('value2_offset-changed', () => updatePanel(instance));\n instance._assignEvent('value2_minlimit-changed', () => updatePanel(instance));\n instance._assignEvent('value2_maxlimit-changed', () => updatePanel(instance));\n instance._assignEvent('value2_prefix-changed', () => updatePanel(instance));\n instance._assignEvent('value2_suffix-changed', () => updatePanel(instance));\n instance._assignEvent('value2_thousandsep-changed', () => updatePanel(instance));\n\n const trendIcon = instance._getDomElement('trend-icon');\n const dialog = instance._getDomElement('trend-dialog');\n const closeBtn = instance._getDomElement('close-dialog');\n const iframe = instance._getDomElement('grafana-iframe');\n const dialogTitle = instance._getDomElement('dialog-title');\n\n /*if (!instance.grafanaUrl || instance.grafanaUrl.trim() === \"\") {\n console.log(\"Grafana URL boşdur!\");\n } else {\n // URL boş deyilsə, parametrləri əlavə et\n const params = new URLSearchParams({\n \"var-selected_state\": instance.grafana_selected_state_name1,\n \"var-selected_state2\": instance.grafana_selected_state_name2,\n \"var-tag_name\": instance.pointName,\n kiosk: \"\" // kiosk parametri əlavə olunur\n });\n\n\n\n const finalUrl = `${instance.grafanaUrl}?${params.toString()}`;\n // instance.grafanaUrl = finalUrl;\n }*/\n\n\n\n\n\n if (trendIcon && dialog) {\n trendIcon.addEventListener('click', async() => {\n if (!instance.grafana_url || instance.grafana_url.trim() === \"\") {\n console.log(\"Grafana URL boşdur!\");\n } else {\n // URL obyektini qururuq\n const url = new URL(instance.grafana_url, baseaddress); // baza hostu əlavə et\n\n // Mövcud parametrləri götürürük\n const params = url.searchParams;\n\n // İstədiyin parametrlərə dəyər ver\n params.set(\"var-selected_state\", instance.grafana_selected_state_name1);\n params.set(\"var-selected_state2\", instance.grafana_selected_state_name2);\n params.set(\"var-tag_name\", instance.pointName);\n\n\n // Yenilənmiş URL\n const finalUrl = `${url.href}&kiosk`;\n //console.log(finalUrl);\n\n //const grafanaUrl = instance.grafanaUrl || 'about:blank';\n // ioBroker-dən cari useri al\n iframe.src = finalUrl;\n dialogTitle.textContent = (instance.pointName || 'Trend') + ' - Trend';\n dialog.showModal();\n \n\n /*const pointName = instance.pointName || 'Trend';\n iframe.src = finalUrl;\n dialogTitle.textContent = pointName + ' - Trend';\n dialog.showModal();*/\n }\n });\n }\n\n if (closeBtn && dialog) {\n closeBtn.addEventListener('click', () => {\n dialog.close();\n iframe.src = 'about:blank';\n });\n }\n\n if (dialog) {\n dialog.addEventListener('click', (e) => {\n const rect = dialog.getBoundingClientRect();\n if (e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom) {\n dialog.close();\n iframe.src = 'about:blank';\n }\n });\n }\n\n const actionBtn = instance._getDomElement('action-btn');\n if (actionBtn) {\n actionBtn.addEventListener('click', () => {\n const event = new CustomEvent('scada-point-button-clicked', {\n detail: { pointName: instance.pointName },\n bubbles: true\n });\n instance.dispatchEvent(event);\n });\n }\n}\n\nfunction updatePanel(instance) {\n const nameEl = instance._getDomElement('point-name');\n if (nameEl) nameEl.textContent = instance.pointName || 'Point';\n\n const label1El = instance._getDomElement('label1');\n const value1El = instance._getDomElement('value1');\n const unit1El = instance._getDomElement('unit1');\n if (label1El) label1El.textContent = instance.value1_label || '';\n\n // Format value1 with SCADA functions\n if (value1El) {\n const value1Options = {\n decimals: instance.value1_decimals,\n roundMode: instance.value1_roundmode,\n scale: instance.value1_scale,\n offset: instance.value1_offset,\n minLimit: instance.value1_minlimit,\n maxLimit: instance.value1_maxlimit,\n prefix: instance.value1_prefix,\n suffix: instance.value1_suffix,\n thousandSep: instance.value1_thousandsep\n };\n value1El.textContent = formatValue(instance.value1_value, value1Options);\n }\n\n if (unit1El) unit1El.textContent = instance.value1_unit || '';\n\n const label2El = instance._getDomElement('label2');\n const value2El = instance._getDomElement('value2');\n const unit2El = instance._getDomElement('unit2');\n const hasRow2 = instance.value2_label || instance.value2_value || instance.value2_unit;\n\n if (label2El) {\n label2El.textContent = instance.value2_label || '';\n label2El.style.display = hasRow2 ? 'block' : 'none';\n }\n if (value2El) {\n const value2Options = {\n decimals: instance.value2_decimals,\n roundMode: instance.value2_roundmode,\n scale: instance.value2_scale,\n offset: instance.value2_offset,\n minLimit: instance.value2_minlimit,\n maxLimit: instance.value2_maxlimit,\n prefix: instance.value2_prefix,\n suffix: instance.value2_suffix,\n thousandSep: instance.value2_thousandsep\n };\n value2El.textContent = formatValue(instance.value2_value, value2Options);\n value2El.style.display = hasRow2 ? 'block' : 'none';\n }\n if (unit2El) {\n unit2El.textContent = instance.value2_unit || '';\n unit2El.style.display = hasRow2 ? 'block' : 'none';\n }\n\n const buttonEl = instance._getDomElement('action-button');\n const buttonTextEl = instance._getDomElement('action-btn');\n if (buttonEl && buttonTextEl) {\n const showButton = instance.showButton === true || instance.showButton === 'true';\n buttonEl.style.display = showButton ? 'block' : 'none';\n buttonTextEl.textContent = instance.buttonText || 'Button';\n }\n}\n\nfunction applyTheming(instance) {\n const theme = instance.theme || 'default';\n const container = instance._getDomElement('panel-container');\n if (!container) return;\n\n const themes = {\n 'default': { bg: 'var(--ui-surface,#5a7a7a)', border: 'var(--ui-border,#3a5a5a)', text: 'var(--ui-text,#fff)', label: 'var(--ui-dim,#e0e0e0)', btnBg: 'var(--ui-surface-2,#4a6a6a)' },\n 'dark': { bg: '#2d3436', border: '#000', text: '#fff', label: '#dfe6e9', btnBg: '#636e72' },\n 'light': { bg: '#dfe6e9', border: '#b2bec3', text: '#2d3436', label: '#636e72', btnBg: '#b2bec3' },\n 'blue': { bg: '#0984e3', border: '#0652DD', text: '#fff', label: '#dfe6e9', btnBg: '#74b9ff' },\n 'green': { bg: '#00b894', border: '#00a383', text: '#fff', label: '#d4f1e8', btnBg: '#55efc4' },\n 'red': { bg: '#d63031', border: '#b71c1c', text: '#fff', label: '#ffcccc', btnBg: '#ff7675' },\n 'purple': { bg: '#6c5ce7', border: '#5f3dc4', text: '#fff', label: '#e5dbff', btnBg: '#a29bfe' }\n };\n\n const colors = themes[theme] || themes['default'];\n container.style.background = colors.bg;\n container.style.borderColor = colors.border;\n\n const nameEl = instance._getDomElement('point-name');\n const value1El = instance._getDomElement('value1');\n const value2El = instance._getDomElement('value2');\n if (nameEl) nameEl.style.color = colors.text;\n if (value1El) value1El.style.color = colors.text;\n if (value2El) value2El.style.color = colors.text;\n\n const label1El = instance._getDomElement('label1');\n const label2El = instance._getDomElement('label2');\n const unit1El = instance._getDomElement('unit1');\n const unit2El = instance._getDomElement('unit2');\n if (label1El) label1El.style.color = colors.label;\n if (label2El) label2El.style.color = colors.label;\n if (unit1El) unit1El.style.color = colors.label;\n if (unit2El) unit2El.style.color = colors.label;\n\n const trendIcon = instance._getDomElement('trend-icon');\n if (trendIcon) trendIcon.style.stroke = colors.text;\n\n const actionBtn = instance._getDomElement('action-btn');\n if (actionBtn) {\n actionBtn.style.background = colors.btnBg;\n actionBtn.style.borderColor = colors.border;\n actionBtn.style.color = colors.text;\n }\n\n const dialog = instance._getDomElement('trend-dialog');\n if (dialog) {\n dialog.style.borderColor = colors.border;\n const header = instance._getDomElement('dialog-header');\n if (header) {\n header.style.background = colors.bg;\n header.style.color = colors.text;\n }\n }\n}\n\nexport function connectedCallback(instance)\n{\n \n}\n\nfunction getResolvedSignalId() {\n // bind-prop:value1 atributundan ham pattern-i oxu\n const raw = element.getAttribute('bind-prop:value1');\n if (!raw) return null;\n\n // {??propName} → screen[propName] ilə replace et\n return raw.replace(/\\{(\\?\\?([^}]+))\\}/g, (_, __, propName) => {\n return screen?.[propName] ?? '';\n });\n }", "properties": {"pointName": {"type": "string", "default": "DPT 010"}, "value1_value": {"type": "number"}, "value1_label": {"type": "string"}, "value1_unit": {"type": "string", "default": "kPa"}, "value2_label": {"type": "string"}, "value2_value": {"type": "number"}, "theme": {"type": "enum", "default": "default", "values": ["default", "dark", "light", "blue", "green", "red", "purple"]}, "value2_unit": {"type": "string"}, "grafana_url": {"type": "string"}, "grafana_selected_state_name1": {"type": "string"}, "grafana_selected_state_name2": {"type": "string"}, "showButton": {"type": "boolean"}, "buttonText": {"type": "string", "default": "Button"}, "grafana_dialogheight": {"type": "string"}, "grafana_dialogwidth": {"type": "string"}, "value1_decimals": {"type": "number", "default": "2"}, "value1_roundmode": {"type": "enum", "default": "round", "values": ["round", "floor", "ceil"]}, "value1_scale": {"type": "number", "default": "1"}, "value1_offset": {"type": "number"}, "value1_maxlimit": {"type": "number"}, "value1_minlimit": {"type": "number"}, "value1_prefix": {"type": "string"}, "value1_suffix": {"type": "string"}, "value1_thousandsep": {"type": "string"}, "value2_decimals": {"type": "number", "default": "2"}, "value2_roundmode": {"type": "enum", "default": "round", "values": ["round", "floor", "ceil"]}, "value2_scale": {"type": "number", "default": "1"}, "value2_offset": {"type": "number"}, "value2_minlimit": {"type": "number"}, "value2_maxlimit": {"type": "number"}, "value2_prefix": {"type": "string"}, "value2_suffix": {"type": "string"}, "value2_thousandsep": {"type": "string"}}, "settings": {"visibilityEnabled": "false", "visibilityGroups": "", "visibilityAction": "hide", "visibilityRedirectScreen": ""}}
@@ -1 +1 @@
1
- {"html": "<div id=\"main-container\" style=\"display:flex;gap:8px;align-items:stretch;width:100%;height:100%;font:&quot;Times New Roman&quot;, serif;\">\n <!-- Input Container -->\n <div id=\"input-container\" style=\"position:relative;flex:1;display:flex;align-items:center;border:1px solid rgb(204, 204, 204);border-radius:4px;background:rgb(240, 240, 240);padding:4px 8px;\">\n <input id=\"text-input\" type=\"text\" placeholder style=\"flex:1;border:initial none initial;outline:none;padding:4px;color:#333;background:transparent;font:14px &quot;Times New Roman&quot;, serif;\">\n <!-- Numberpad Icon (hidden by default) --> <svg id=\"numberpad-icon\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" title=\"Numberpad\" style=\"cursor:pointer;fill:#666;margin-left:4px;display:none;\">\n <rect x=\"3\" y=\"3\" width=\"4\" height=\"4\" rx=\"1\"></rect>\n <rect x=\"10\" y=\"3\" width=\"4\" height=\"4\" rx=\"1\"></rect>\n <rect x=\"17\" y=\"3\" width=\"4\" height=\"4\" rx=\"1\"></rect>\n <rect x=\"3\" y=\"10\" width=\"4\" height=\"4\" rx=\"1\"></rect>\n <rect x=\"10\" y=\"10\" width=\"4\" height=\"4\" rx=\"1\"></rect>\n <rect x=\"17\" y=\"10\" width=\"4\" height=\"4\" rx=\"1\"></rect>\n <rect x=\"3\" y=\"17\" width=\"4\" height=\"4\" rx=\"1\"></rect>\n <rect x=\"10\" y=\"17\" width=\"11\" height=\"4\" rx=\"1\"></rect>\n </svg>\n </div>\n <!-- Button -->\n <button id=\"submit-btn\" style=\"color:#fff;border:initial none initial;border-radius:4px;cursor:pointer;white-space:nowrap;min-width:80px;background:rgb(108, 117, 125);font:14px &quot;Times New Roman&quot;, serif;padding:8px 16px;\">\n<t-t>input_with_button.volume</t-t>\n </button>\n</div>\n<!-- Numberpad Dialog -->\n<dialog id=\"numberpad-dialog\" style=\"border:2px solid rgb(90, 122, 122);border-radius:8px;padding:0px;background:rgb(255, 255, 255);\">\n <div id=\"dialog-header\" style=\"color:#fff;padding:12px;display:flex;justify-content:space-between;align-items:center;background:rgb(90, 122, 122);\">\n <h3 id=\"dialog-title\" style=\"margin:0px;font:16px &quot;Times New Roman&quot;, serif;\">Numberpad</h3>\n <button id=\"close-numberpad\" style=\"border:initial none initial;color:#fff;cursor:pointer;padding:0px;width:30px;height:30px;background:transparent;font:24px &quot;Times New Roman&quot;, serif;\">×</button>\n </div>\n <div id=\"numberpad-body\" style=\"padding:16px;\">\n <!-- Display --><input id=\"numberpad-display\" type=\"text\" readonly style=\"width:100%;padding:2px;text-align:right;border:1px solid rgb(204, 204, 204);border-radius:4px;margin-bottom:12px;background:rgb(249, 249, 249);font:20px &quot;Times New Roman&quot;, serif;\"><!-- Numberpad Grid -->\n<div style=\"display:grid;grid-template-columns:repeat(3, 60px);gap:8px;\">\n <button class=\"num-btn\" data-value=\"7\" style=\"padding:16px;border:1px solid rgb(204, 204, 204);border-radius:4px;cursor:pointer;background:rgb(255, 255, 255);font:18px &quot;Times New Roman&quot;, serif;\">7</button>\n <button class=\"num-btn\" data-value=\"8\" style=\"padding:16px;border:1px solid rgb(204, 204, 204);border-radius:4px;cursor:pointer;background:rgb(255, 255, 255);font:18px &quot;Times New Roman&quot;, serif;\">8</button>\n <button class=\"num-btn\" data-value=\"9\" style=\"padding:16px;border:1px solid rgb(204, 204, 204);border-radius:4px;cursor:pointer;background:rgb(255, 255, 255);font:18px &quot;Times New Roman&quot;, serif;\">9</button>\n <button class=\"num-btn\" data-value=\"4\" style=\"padding:16px;border:1px solid rgb(204, 204, 204);border-radius:4px;cursor:pointer;background:rgb(255, 255, 255);font:18px &quot;Times New Roman&quot;, serif;\">4</button>\n <button class=\"num-btn\" data-value=\"5\" style=\"padding:16px;border:1px solid rgb(204, 204, 204);border-radius:4px;cursor:pointer;background:rgb(255, 255, 255);font:18px &quot;Times New Roman&quot;, serif;\">5</button>\n <button class=\"num-btn\" data-value=\"6\" style=\"padding:16px;border:1px solid rgb(204, 204, 204);border-radius:4px;cursor:pointer;background:rgb(255, 255, 255);font:18px &quot;Times New Roman&quot;, serif;\">6</button>\n <button class=\"num-btn\" data-value=\"1\" style=\"padding:16px;border:1px solid rgb(204, 204, 204);border-radius:4px;cursor:pointer;background:rgb(255, 255, 255);font:18px &quot;Times New Roman&quot;, serif;\">1</button>\n <button class=\"num-btn\" data-value=\"2\" style=\"padding:16px;border:1px solid rgb(204, 204, 204);border-radius:4px;cursor:pointer;background:rgb(255, 255, 255);font:18px &quot;Times New Roman&quot;, serif;\">2</button>\n <button class=\"num-btn\" data-value=\"3\" style=\"padding:16px;border:1px solid rgb(204, 204, 204);border-radius:4px;cursor:pointer;background:rgb(255, 255, 255);font:18px &quot;Times New Roman&quot;, serif;\">3</button>\n <button class=\"num-btn\" data-value=\"0\" style=\"padding:16px;border:1px solid rgb(204, 204, 204);border-radius:4px;cursor:pointer;grid-column:span 2;background:rgb(255, 255, 255);font:18px &quot;Times New Roman&quot;, serif;\">0</button>\n <button class=\"num-btn\" data-value=\".\" style=\"padding:16px;border:1px solid rgb(204, 204, 204);border-radius:4px;cursor:pointer;background:rgb(255, 255, 255);font:18px &quot;Times New Roman&quot;, serif;\">.</button>\n <button id=\"num-clear\" style=\"padding:16px;border:1px solid rgb(204, 204, 204);border-radius:4px;color:#fff;cursor:pointer;grid-column:span 2;background:rgb(255, 107, 107);font:14px &quot;Times New Roman&quot;, serif;\">\n<t-t>input_with_button.clear</t-t>\n </button>\n <button id=\"num-backspace\" style=\"padding:16px;border:1px solid rgb(204, 204, 204);border-radius:4px;color:#fff;cursor:pointer;background:rgb(255, 165, 0);font:14px &quot;Times New Roman&quot;, serif;\">←</button>\n </div>\n <!-- OK Button --><button id=\"num-ok\" style=\"width:100%;padding:12px;margin-top:12px;border:initial none initial;border-radius:4px;color:#fff;cursor:pointer;background:rgb(90, 122, 122);font:16px &quot;Times New Roman&quot;, serif;\">OK</button>\n </div>\n</dialog>\n", "script": "export function init(instance) {\n //instance._bindingsRefresh();\n\n applyTheming(instance);\n updateControl(instance);\n\n instance._assignEvent('input-type-changed', () => updateControl(instance));\n instance._assignEvent('button-text-changed', () => updateControl(instance));\n instance._assignEvent('placeholder-changed', () => updateControl(instance));\n instance._assignEvent('theme-changed', () => applyTheming(instance));\n instance._assignEvent('state-id-changed', () => { });\n\n const input = instance._getDomElement('text-input');\n const submitBtn = instance._getDomElement('submit-btn');\n const numberpadIcon = instance._getDomElement('numberpad-icon');\n const numberpadDialog = instance._getDomElement('numberpad-dialog');\n const numberpadDisplay = instance._getDomElement('numberpad-display');\n const closeNumberpad = instance._getDomElement('close-numberpad');\n const numOk = instance._getDomElement('num-ok');\n const numClear = instance._getDomElement('num-clear');\n const numBackspace = instance._getDomElement('num-backspace');\n\n window.addEventListener('languageChanged', () => {\n if (input) {\n input.placeholder = t('input_with_button.addvalue');\n }\n });\n\n // Subscribe to state changes\n let stateSubscription = null;\n function subscribeToState() {\n // Unsubscribe from previous state\n if (stateSubscription) {\n window.IOB.unsubscribeState(stateSubscription);\n stateSubscription = null;\n }\n\n // Subscribe to new state\n const stateId = instance.stateId;\n if (stateId) {\n stateSubscription = window.IOB.subscribeState(stateId, (id, state) => {\n const input = instance._getDomElement('text-input');\n if (input && state && state.val !== undefined) {\n input.value = state.val;\n }\n });\n\n // Load initial value\n window.IOB.getState(stateId).then(state => {\n const input = instance._getDomElement('text-input');\n if (input && state && state.val !== undefined) {\n input.value = state.val;\n }\n });\n }\n }\n\n subscribeToState();\n\n // Submit function\n async function submitValue() {\n const value = input.value;\n const stateId = instance.stateId;\n\n if (!stateId) {\n console.error('State ID not configured');\n return;\n }\n\n try {\n let finalValue = value;\n\n // Convert based on input type\n if (instance.inputType === 'number') {\n finalValue = parseFloat(value);\n if (isNaN(finalValue)) {\n console.error('Invalid number:', value);\n return;\n }\n } else if (instance.inputType === 'integer') {\n finalValue = parseInt(value);\n if (isNaN(finalValue)) {\n console.error('Invalid integer:', value);\n return;\n }\n }\n\n await window.IOB.setState(stateId, finalValue);\n console.log('Value written to state:', stateId, finalValue);\n\n // Optional: Clear input after submit\n if (instance.clearAfterSubmit === true) {\n input.value = '';\n }\n } catch (err) {\n console.error('Error writing to state:', err);\n }\n }\n\n // Enter key handler\n if (input) {\n input.addEventListener('keypress', (e) => {\n if (e.key === 'Enter') {\n submitValue();\n }\n });\n }\n\n // Submit button handler\n if (submitBtn) {\n submitBtn.addEventListener('click', () => {\n submitValue();\n });\n }\n\n // Numberpad icon handler\n if (numberpadIcon && numberpadDialog) {\n numberpadIcon.addEventListener('click', () => {\n numberpadDisplay.value = input.value || '';\n numberpadDialog.showModal();\n });\n }\n // Numberpad buttons\n const numBtns = instance.shadowRoot.querySelectorAll('.num-btn');\n numBtns.forEach(btn => {\n btn.addEventListener('click', () => {\n numberpadDisplay.value += btn.dataset.value;\n });\n });\n\n // Numberpad clear\n if (numClear) {\n numClear.addEventListener('click', () => {\n numberpadDisplay.value = '';\n });\n }\n\n // Numberpad backspace\n if (numBackspace) {\n numBackspace.addEventListener('click', () => {\n numberpadDisplay.value = numberpadDisplay.value.slice(0, -1);\n });\n }\n\n // Numberpad OK\n if (numOk) {\n numOk.addEventListener('click', () => {\n input.value = numberpadDisplay.value;\n numberpadDialog.close();\n });\n }\n\n // Close numberpad\n if (closeNumberpad) {\n closeNumberpad.addEventListener('click', () => {\n numberpadDialog.close();\n });\n }\n\n // Close dialog on outside click\n if (numberpadDialog) {\n numberpadDialog.addEventListener('click', (e) => {\n const rect = numberpadDialog.getBoundingClientRect();\n if (e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom) {\n numberpadDialog.close();\n }\n });\n }\n}\n\n\nfunction updateControl(instance) {\n const input = instance._getDomElement('text-input');\n const submitBtn = instance._getDomElement('submit-btn');\n const numberpadIcon = instance._getDomElement('numberpad-icon');\n\n // Update input type\n if (input) {\n const inputType = instance.inputType || 'string';\n\n if (inputType === 'password') {\n input.type = 'password';\n } else if (inputType === 'number' || inputType === 'integer') {\n input.type = 'text';\n } else {\n input.type = 'text';\n }\n\n //input.placeholder = instance.placeholder || 'Dəyər daxil edin';\n }\n\n // Show/hide numberpad icon\n if (numberpadIcon) {\n const showNumberpad = instance.inputType === 'number' || instance.inputType === 'integer';\n numberpadIcon.style.display = showNumberpad ? 'block' : 'none';\n }\n\n}\n\nfunction applyTheming(instance) {\n const theme = instance.theme || 'default';\n\n const themes = {\n 'default': { inputBg: '#f0f0f0', inputBorder: '#ccc', inputText: '#333', btnBg: '#6c757d', btnText: '#fff', headerBg: '#5a7a7a' },\n 'dark': { inputBg: '#2d3436', inputBorder: '#000', inputText: '#fff', btnBg: '#636e72', btnText: '#fff', headerBg: '#2d3436' },\n 'light': { inputBg: '#fff', inputBorder: '#dfe6e9', inputText: '#2d3436', btnBg: '#b2bec3', btnText: '#2d3436', headerBg: '#dfe6e9' },\n 'blue': { inputBg: '#dfe6e9', inputBorder: '#74b9ff', inputText: '#0984e3', btnBg: '#0984e3', btnText: '#fff', headerBg: '#0984e3' },\n 'green': { inputBg: '#d4f1e8', inputBorder: '#55efc4', inputText: '#00b894', btnBg: '#00b894', btnText: '#fff', headerBg: '#00b894' },\n 'red': { inputBg: '#ffcccc', inputBorder: '#ff7675', inputText: '#d63031', btnBg: '#d63031', btnText: '#fff', headerBg: '#d63031' },\n 'purple': { inputBg: '#e5dbff', inputBorder: '#a29bfe', inputText: '#6c5ce7', btnBg: '#6c5ce7', btnText: '#fff', headerBg: '#6c5ce7' }\n };\n\n const colors = themes[theme] || themes['default'];\n\n // Input container\n const inputContainer = instance._getDomElement('input-container');\n if (inputContainer) {\n inputContainer.style.background = colors.inputBg;\n inputContainer.style.borderColor = colors.inputBorder;\n }\n\n // Input text\n const input = instance._getDomElement('text-input');\n if (input) {\n input.style.color = colors.inputText;\n }\n\n // Numberpad icon\n const numberpadIcon = instance._getDomElement('numberpad-icon');\n if (numberpadIcon) {\n numberpadIcon.style.fill = colors.inputText;\n }\n\n // Submit button\n const submitBtn = instance._getDomElement('submit-btn');\n if (submitBtn) {\n submitBtn.style.background = colors.btnBg;\n submitBtn.style.color = colors.btnText;\n }\n\n // Dialog header\n const dialogHeader = instance._getDomElement('dialog-header');\n if (dialogHeader) {\n dialogHeader.style.background = colors.headerBg;\n }\n\n // Dialog\n const dialog = instance._getDomElement('numberpad-dialog');\n if (dialog) {\n dialog.style.borderColor = colors.headerBg;\n }\n\n // OK button in numberpad\n const numOk = instance._getDomElement('num-ok');\n if (numOk) {\n numOk.style.background = colors.headerBg;\n }\n}", "properties": {"inputType": {"type": "enum", "default": "string", "values": ["string", "number", "integer", "password"]}, "placeholder": {"type": "string", "default": "Dəyər daxil edin"}, "stateId": {"type": "signal"}, "clearAfterSubmit": {"type": "boolean"}, "theme": {"type": "enum", "default": "default", "values": ["default", "dark", "light", "blue", "green", "red", "purple"]}}, "settings": {"visibilityEnabled": "false", "visibilityGroups": "", "visibilityAction": "hide", "visibilityRedirectScreen": ""}}
1
+ {"html": "<div id=\"main-container\" style=\"display:flex;gap:8px;align-items:stretch;width:100%;height:100%;font:&quot;Times New Roman&quot;, serif;\">\n <!-- Input Container -->\n <div id=\"input-container\" style=\"position:relative;flex:1;display:flex;align-items:center;border:1px solid var(--ui-border,rgb(204, 204, 204));border-radius:4px;background:rgb(240, 240, 240);padding:4px 8px;\">\n <input id=\"text-input\" type=\"text\" placeholder style=\"flex:1;border:initial none initial;outline:none;padding:4px;color:var(--ui-text,#333);background:transparent;font:14px &quot;Times New Roman&quot;, serif;\">\n <!-- Numberpad Icon (hidden by default) --> <svg id=\"numberpad-icon\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" title=\"Numberpad\" style=\"cursor:pointer;fill:#666;margin-left:4px;display:none;\">\n <rect x=\"3\" y=\"3\" width=\"4\" height=\"4\" rx=\"1\"></rect>\n <rect x=\"10\" y=\"3\" width=\"4\" height=\"4\" rx=\"1\"></rect>\n <rect x=\"17\" y=\"3\" width=\"4\" height=\"4\" rx=\"1\"></rect>\n <rect x=\"3\" y=\"10\" width=\"4\" height=\"4\" rx=\"1\"></rect>\n <rect x=\"10\" y=\"10\" width=\"4\" height=\"4\" rx=\"1\"></rect>\n <rect x=\"17\" y=\"10\" width=\"4\" height=\"4\" rx=\"1\"></rect>\n <rect x=\"3\" y=\"17\" width=\"4\" height=\"4\" rx=\"1\"></rect>\n <rect x=\"10\" y=\"17\" width=\"11\" height=\"4\" rx=\"1\"></rect>\n </svg>\n </div>\n <!-- Button -->\n <button id=\"submit-btn\" style=\"color:var(--ui-text,#fff);border:initial none initial;border-radius:4px;cursor:pointer;white-space:nowrap;min-width:80px;background:rgb(108, 117, 125);font:14px &quot;Times New Roman&quot;, serif;padding:8px 16px;\">\n<t-t>input_with_button.volume</t-t>\n </button>\n</div>\n<!-- Numberpad Dialog -->\n<dialog id=\"numberpad-dialog\" style=\"border:2px solid var(--ui-surface,rgb(90, 122, 122));border-radius:8px;padding:0px;background:var(--ui-input,rgb(255, 255, 255));\">\n <div id=\"dialog-header\" style=\"color:var(--ui-text,#fff);padding:12px;display:flex;justify-content:space-between;align-items:center;background:var(--ui-surface,rgb(90, 122, 122));\">\n <h3 id=\"dialog-title\" style=\"margin:0px;font:16px &quot;Times New Roman&quot;, serif;\">Numberpad</h3>\n <button id=\"close-numberpad\" style=\"border:initial none initial;color:var(--ui-text,#fff);cursor:pointer;padding:0px;width:30px;height:30px;background:transparent;font:24px &quot;Times New Roman&quot;, serif;\">×</button>\n </div>\n <div id=\"numberpad-body\" style=\"padding:16px;\">\n <!-- Display --><input id=\"numberpad-display\" type=\"text\" readonly style=\"width:100%;padding:2px;text-align:right;border:1px solid var(--ui-border,rgb(204, 204, 204));border-radius:4px;margin-bottom:12px;background:rgb(249, 249, 249);font:20px &quot;Times New Roman&quot;, serif;\"><!-- Numberpad Grid -->\n<div style=\"display:grid;grid-template-columns:repeat(3, 60px);gap:8px;\">\n <button class=\"num-btn\" data-value=\"7\" style=\"padding:16px;border:1px solid var(--ui-border,rgb(204, 204, 204));border-radius:4px;cursor:pointer;background:var(--ui-input,rgb(255, 255, 255));font:18px &quot;Times New Roman&quot;, serif;\">7</button>\n <button class=\"num-btn\" data-value=\"8\" style=\"padding:16px;border:1px solid var(--ui-border,rgb(204, 204, 204));border-radius:4px;cursor:pointer;background:var(--ui-input,rgb(255, 255, 255));font:18px &quot;Times New Roman&quot;, serif;\">8</button>\n <button class=\"num-btn\" data-value=\"9\" style=\"padding:16px;border:1px solid var(--ui-border,rgb(204, 204, 204));border-radius:4px;cursor:pointer;background:var(--ui-input,rgb(255, 255, 255));font:18px &quot;Times New Roman&quot;, serif;\">9</button>\n <button class=\"num-btn\" data-value=\"4\" style=\"padding:16px;border:1px solid var(--ui-border,rgb(204, 204, 204));border-radius:4px;cursor:pointer;background:var(--ui-input,rgb(255, 255, 255));font:18px &quot;Times New Roman&quot;, serif;\">4</button>\n <button class=\"num-btn\" data-value=\"5\" style=\"padding:16px;border:1px solid var(--ui-border,rgb(204, 204, 204));border-radius:4px;cursor:pointer;background:var(--ui-input,rgb(255, 255, 255));font:18px &quot;Times New Roman&quot;, serif;\">5</button>\n <button class=\"num-btn\" data-value=\"6\" style=\"padding:16px;border:1px solid var(--ui-border,rgb(204, 204, 204));border-radius:4px;cursor:pointer;background:var(--ui-input,rgb(255, 255, 255));font:18px &quot;Times New Roman&quot;, serif;\">6</button>\n <button class=\"num-btn\" data-value=\"1\" style=\"padding:16px;border:1px solid var(--ui-border,rgb(204, 204, 204));border-radius:4px;cursor:pointer;background:var(--ui-input,rgb(255, 255, 255));font:18px &quot;Times New Roman&quot;, serif;\">1</button>\n <button class=\"num-btn\" data-value=\"2\" style=\"padding:16px;border:1px solid var(--ui-border,rgb(204, 204, 204));border-radius:4px;cursor:pointer;background:var(--ui-input,rgb(255, 255, 255));font:18px &quot;Times New Roman&quot;, serif;\">2</button>\n <button class=\"num-btn\" data-value=\"3\" style=\"padding:16px;border:1px solid var(--ui-border,rgb(204, 204, 204));border-radius:4px;cursor:pointer;background:var(--ui-input,rgb(255, 255, 255));font:18px &quot;Times New Roman&quot;, serif;\">3</button>\n <button class=\"num-btn\" data-value=\"0\" style=\"padding:16px;border:1px solid var(--ui-border,rgb(204, 204, 204));border-radius:4px;cursor:pointer;grid-column:span 2;background:var(--ui-input,rgb(255, 255, 255));font:18px &quot;Times New Roman&quot;, serif;\">0</button>\n <button class=\"num-btn\" data-value=\".\" style=\"padding:16px;border:1px solid var(--ui-border,rgb(204, 204, 204));border-radius:4px;cursor:pointer;background:var(--ui-input,rgb(255, 255, 255));font:18px &quot;Times New Roman&quot;, serif;\">.</button>\n <button id=\"num-clear\" style=\"padding:16px;border:1px solid var(--ui-border,rgb(204, 204, 204));border-radius:4px;color:var(--ui-text,#fff);cursor:pointer;grid-column:span 2;background:rgb(255, 107, 107);font:14px &quot;Times New Roman&quot;, serif;\">\n<t-t>input_with_button.clear</t-t>\n </button>\n <button id=\"num-backspace\" style=\"padding:16px;border:1px solid var(--ui-border,rgb(204, 204, 204));border-radius:4px;color:var(--ui-text,#fff);cursor:pointer;background:rgb(255, 165, 0);font:14px &quot;Times New Roman&quot;, serif;\">←</button>\n </div>\n <!-- OK Button --><button id=\"num-ok\" style=\"width:100%;padding:12px;margin-top:12px;border:initial none initial;border-radius:4px;color:var(--ui-text,#fff);cursor:pointer;background:var(--ui-surface,rgb(90, 122, 122));font:16px &quot;Times New Roman&quot;, serif;\">OK</button>\n </div>\n</dialog>\n", "script": "export function init(instance) {\n //instance._bindingsRefresh();\n\n applyTheming(instance);\n updateControl(instance);\n\n instance._assignEvent('input-type-changed', () => updateControl(instance));\n instance._assignEvent('button-text-changed', () => updateControl(instance));\n instance._assignEvent('placeholder-changed', () => updateControl(instance));\n instance._assignEvent('theme-changed', () => applyTheming(instance));\n instance._assignEvent('state-id-changed', () => { });\n\n const input = instance._getDomElement('text-input');\n const submitBtn = instance._getDomElement('submit-btn');\n const numberpadIcon = instance._getDomElement('numberpad-icon');\n const numberpadDialog = instance._getDomElement('numberpad-dialog');\n const numberpadDisplay = instance._getDomElement('numberpad-display');\n const closeNumberpad = instance._getDomElement('close-numberpad');\n const numOk = instance._getDomElement('num-ok');\n const numClear = instance._getDomElement('num-clear');\n const numBackspace = instance._getDomElement('num-backspace');\n\n window.addEventListener('languageChanged', () => {\n if (input) {\n input.placeholder = t('input_with_button.addvalue');\n }\n });\n\n // Subscribe to state changes\n let stateSubscription = null;\n function subscribeToState() {\n // Unsubscribe from previous state\n if (stateSubscription) {\n window.IOB.unsubscribeState(stateSubscription);\n stateSubscription = null;\n }\n\n // Subscribe to new state\n const stateId = instance.stateId;\n if (stateId) {\n stateSubscription = window.IOB.subscribeState(stateId, (id, state) => {\n const input = instance._getDomElement('text-input');\n if (input && state && state.val !== undefined) {\n input.value = state.val;\n }\n });\n\n // Load initial value\n window.IOB.getState(stateId).then(state => {\n const input = instance._getDomElement('text-input');\n if (input && state && state.val !== undefined) {\n input.value = state.val;\n }\n });\n }\n }\n\n subscribeToState();\n\n // Submit function\n async function submitValue() {\n const value = input.value;\n const stateId = instance.stateId;\n\n if (!stateId) {\n console.error('State ID not configured');\n return;\n }\n\n try {\n let finalValue = value;\n\n // Convert based on input type\n if (instance.inputType === 'number') {\n finalValue = parseFloat(value);\n if (isNaN(finalValue)) {\n console.error('Invalid number:', value);\n return;\n }\n } else if (instance.inputType === 'integer') {\n finalValue = parseInt(value);\n if (isNaN(finalValue)) {\n console.error('Invalid integer:', value);\n return;\n }\n }\n\n await window.IOB.setState(stateId, finalValue);\n console.log('Value written to state:', stateId, finalValue);\n\n // Optional: Clear input after submit\n if (instance.clearAfterSubmit === true) {\n input.value = '';\n }\n } catch (err) {\n console.error('Error writing to state:', err);\n }\n }\n\n // Enter key handler\n if (input) {\n input.addEventListener('keypress', (e) => {\n if (e.key === 'Enter') {\n submitValue();\n }\n });\n }\n\n // Submit button handler\n if (submitBtn) {\n submitBtn.addEventListener('click', () => {\n submitValue();\n });\n }\n\n // Numberpad icon handler\n if (numberpadIcon && numberpadDialog) {\n numberpadIcon.addEventListener('click', () => {\n numberpadDisplay.value = input.value || '';\n numberpadDialog.showModal();\n });\n }\n // Numberpad buttons\n const numBtns = instance.shadowRoot.querySelectorAll('.num-btn');\n numBtns.forEach(btn => {\n btn.addEventListener('click', () => {\n numberpadDisplay.value += btn.dataset.value;\n });\n });\n\n // Numberpad clear\n if (numClear) {\n numClear.addEventListener('click', () => {\n numberpadDisplay.value = '';\n });\n }\n\n // Numberpad backspace\n if (numBackspace) {\n numBackspace.addEventListener('click', () => {\n numberpadDisplay.value = numberpadDisplay.value.slice(0, -1);\n });\n }\n\n // Numberpad OK\n if (numOk) {\n numOk.addEventListener('click', () => {\n input.value = numberpadDisplay.value;\n numberpadDialog.close();\n });\n }\n\n // Close numberpad\n if (closeNumberpad) {\n closeNumberpad.addEventListener('click', () => {\n numberpadDialog.close();\n });\n }\n\n // Close dialog on outside click\n if (numberpadDialog) {\n numberpadDialog.addEventListener('click', (e) => {\n const rect = numberpadDialog.getBoundingClientRect();\n if (e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom) {\n numberpadDialog.close();\n }\n });\n }\n}\n\n\nfunction updateControl(instance) {\n const input = instance._getDomElement('text-input');\n const submitBtn = instance._getDomElement('submit-btn');\n const numberpadIcon = instance._getDomElement('numberpad-icon');\n\n // Update input type\n if (input) {\n const inputType = instance.inputType || 'string';\n\n if (inputType === 'password') {\n input.type = 'password';\n } else if (inputType === 'number' || inputType === 'integer') {\n input.type = 'text';\n } else {\n input.type = 'text';\n }\n\n //input.placeholder = instance.placeholder || 'Dəyər daxil edin';\n }\n\n // Show/hide numberpad icon\n if (numberpadIcon) {\n const showNumberpad = instance.inputType === 'number' || instance.inputType === 'integer';\n numberpadIcon.style.display = showNumberpad ? 'block' : 'none';\n }\n\n}\n\nfunction applyTheming(instance) {\n const theme = instance.theme || 'default';\n\n const themes = {\n 'default': { inputBg: 'var(--ui-input,#f0f0f0)', inputBorder: 'var(--ui-border,#ccc)', inputText: 'var(--ui-text,#333)', btnBg: 'var(--ui-surface-2,#6c757d)', btnText: 'var(--ui-text,#fff)', headerBg: 'var(--ui-surface,#5a7a7a)' },\n 'dark': { inputBg: '#2d3436', inputBorder: '#000', inputText: '#fff', btnBg: '#636e72', btnText: '#fff', headerBg: '#2d3436' },\n 'light': { inputBg: '#fff', inputBorder: '#dfe6e9', inputText: '#2d3436', btnBg: '#b2bec3', btnText: '#2d3436', headerBg: '#dfe6e9' },\n 'blue': { inputBg: '#dfe6e9', inputBorder: '#74b9ff', inputText: '#0984e3', btnBg: '#0984e3', btnText: '#fff', headerBg: '#0984e3' },\n 'green': { inputBg: '#d4f1e8', inputBorder: '#55efc4', inputText: '#00b894', btnBg: '#00b894', btnText: '#fff', headerBg: '#00b894' },\n 'red': { inputBg: '#ffcccc', inputBorder: '#ff7675', inputText: '#d63031', btnBg: '#d63031', btnText: '#fff', headerBg: '#d63031' },\n 'purple': { inputBg: '#e5dbff', inputBorder: '#a29bfe', inputText: '#6c5ce7', btnBg: '#6c5ce7', btnText: '#fff', headerBg: '#6c5ce7' }\n };\n\n const colors = themes[theme] || themes['default'];\n\n // Input container\n const inputContainer = instance._getDomElement('input-container');\n if (inputContainer) {\n inputContainer.style.background = colors.inputBg;\n inputContainer.style.borderColor = colors.inputBorder;\n }\n\n // Input text\n const input = instance._getDomElement('text-input');\n if (input) {\n input.style.color = colors.inputText;\n }\n\n // Numberpad icon\n const numberpadIcon = instance._getDomElement('numberpad-icon');\n if (numberpadIcon) {\n numberpadIcon.style.fill = colors.inputText;\n }\n\n // Submit button\n const submitBtn = instance._getDomElement('submit-btn');\n if (submitBtn) {\n submitBtn.style.background = colors.btnBg;\n submitBtn.style.color = colors.btnText;\n }\n\n // Dialog header\n const dialogHeader = instance._getDomElement('dialog-header');\n if (dialogHeader) {\n dialogHeader.style.background = colors.headerBg;\n }\n\n // Dialog\n const dialog = instance._getDomElement('numberpad-dialog');\n if (dialog) {\n dialog.style.borderColor = colors.headerBg;\n }\n\n // OK button in numberpad\n const numOk = instance._getDomElement('num-ok');\n if (numOk) {\n numOk.style.background = colors.headerBg;\n }\n}", "properties": {"inputType": {"type": "enum", "default": "string", "values": ["string", "number", "integer", "password"]}, "placeholder": {"type": "string", "default": "Dəyər daxil edin"}, "stateId": {"type": "signal"}, "clearAfterSubmit": {"type": "boolean"}, "theme": {"type": "enum", "default": "default", "values": ["default", "dark", "light", "blue", "green", "red", "purple"]}}, "settings": {"visibilityEnabled": "false", "visibilityGroups": "", "visibilityAction": "hide", "visibilityRedirectScreen": ""}}
@@ -0,0 +1 @@
1
+ {"properties": {"lighttheme": {"type": "string", "default": "light"}, "darktheme": {"type": "string", "default": "dark"}}, "settings": {"width": "170px", "height": "40px"}, "html": "<div id=\"wrap\" class=\"tt-wrap\"><button class=\"tt-seg\" id=\"seg-auto\" data-mode=\"auto\" title=\"Auto (system)\" type=\"button\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M10.85 12.65h2.3L12 9l-1.15 3.65zM20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69zm-5.35 7.31L14 14H10l-.65 2H7.4l3.05-8h1.9l3.05 8h-1.75z\"/></svg></button><button class=\"tt-seg\" id=\"seg-light\" data-mode=\"light\" title=\"Light\" type=\"button\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zM2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1zm18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1zM11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1zm0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1zM5.99 4.58c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41L5.99 4.58zm12.37 12.37c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0 .39-.39.39-1.03 0-1.41l-1.06-1.06zm1.06-10.96c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06zM7.05 18.36c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0l1.06-1.06z\"/></svg></button><button class=\"tt-seg\" id=\"seg-dark\" data-mode=\"dark\" title=\"Dark\" type=\"button\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z\"/></svg></button></div>", "style": ":host{display:inline-block;font-family:'Segoe UI',Roboto,sans-serif;}.tt-wrap{display:inline-flex;align-items:stretch;border-radius:999px;overflow:hidden;border:1px solid var(--ui-border,#3b4250);background:var(--ui-surface-2,#2f3545);height:100%;box-sizing:border-box;}.tt-seg{appearance:none;border:none;margin:0;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:8px 16px;background:transparent;color:var(--ui-dim,#9aa3b0);transition:background .15s,color .15s;}.tt-seg + .tt-seg{border-left:1px solid var(--ui-border,#3b4250);}.tt-seg svg{width:20px;height:20px;fill:currentColor;display:block;}.tt-seg:hover{color:var(--ui-text,#e2e6ec);}.tt-seg.active{background:color-mix(in srgb,var(--accent,#2680eb) 22%,transparent);color:var(--accent,#2680eb);}.tt-seg[data-mode=auto].active svg{filter:drop-shadow(0 0 1px var(--accent,#2680eb));}", "script": "const KEY='webui-theme-mode';\nfunction resolved(instance,mode){\n if(mode==='light') return instance.lighttheme||'light';\n if(mode==='dark') return instance.darktheme||'dark';\n return window.matchMedia('(prefers-color-scheme: dark)').matches?(instance.darktheme||'dark'):(instance.lighttheme||'light');\n}\nfunction getMode(){ try{ return localStorage.getItem(KEY)||'auto'; }catch(e){ return 'auto'; } }\nfunction mark(instance){\n const m=getMode();\n for(const md of ['auto','light','dark']){\n const b=instance._getDomElement('seg-'+md);\n if(b) b.classList.toggle('active', md===m);\n }\n}\nfunction setMode(instance,mode){\n try{ localStorage.setItem(KEY,mode); }catch(e){}\n if(window.mywebuiTheme) window.mywebuiTheme.apply(resolved(instance,mode));\n mark(instance);\n}\nexport function init(instance){\n for(const md of ['auto','light','dark']){\n const b=instance._getDomElement('seg-'+md);\n if(b) b.addEventListener('click',()=>setMode(instance,md));\n }\n try{\n window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change',()=>{\n if(getMode()==='auto') setMode(instance,'auto');\n });\n }catch(e){}\n window.addEventListener('webui-theme-changed',()=>mark(instance));\n // re-apply on load so 'auto' resolves against the CURRENT system scheme\n if(window.mywebuiTheme && getMode()==='auto') setMode(instance,'auto'); else mark(instance);\n}\nexport function connectedCallback(instance){}"}
@@ -1 +1 @@
1
- {"html":"<div id=\"textViewerContainer\" style=\"width:100%;height:100%;display:flex;flex-direction:column;\">\n <div id=\"toolbar\" style=\"padding:8px;border-bottom:1px solid var(--border-color);display:flex;gap:8px;background:var(--toolbar-bg);\">\n <button id=\"btnPrintPreview\" style=\"padding:6px 12px 6px 12px;cursor:pointer;border:1px solid var(--border-color);background:var(--button-bg);color:var(--text-color);border-radius:4px;\">Print Preview</button>\n <button id=\"btnPrint\" style=\"padding:6px 12px 6px 12px;cursor:pointer;border:1px solid var(--border-color);background:var(--button-bg);color:var(--text-color);border-radius:4px;\">Print</button>\n <select id=\"themeSelector\" style=\"padding:6px;border:1px solid var(--border-color);background:var(--button-bg);color:var(--text-color);border-radius:4px;\">\n <option value=\"default\">Default</option>\n <option value=\"light\">Light</option>\n <option value=\"dark\">Dark</option>\n <option value=\"blue\">Blue</option>\n <option value=\"sepia\">Sepia</option>\n </select>\n <select id=\"fontSizeSelector\" style=\"padding:6px;border:1px solid var(--border-color);background:var(--button-bg);color:var(--text-color);border-radius:4px;\">\n <option value=\"12px\">Small</option>\n <option value=\"16px\" selected>Medium</option>\n <option value=\"20px\">Large</option>\n <option value=\"24px\">Extra Large</option>\n </select>\n </div>\n <div id=\"textContent\" bind-content:text=\"??textState\" style=\"flex:1;padding:16px;overflow:auto;background:var(--content-bg);color:var(--text-color);font-family:monospace;font-size:var(--font-size);line-height:1.6;white-space:pre-wrap;word-wrap:break-word;\"></div>\n</div>\n<div id=\"printPreviewModal\" style=\"display:none;position:fixed;top:0;left:0;width:100%;height:100%;z-index:10000;background:rgba(0, 0, 0, 0.8);\">\n <div style=\"position:relative;width:90%;height:90%;margin:5% auto 5% auto;border-radius:8px;display:flex;flex-direction:column;background:white;\">\n <div style=\"padding:16px;border-bottom:1px solid #ddd;display:flex;justify-content:space-between;align-items:center;\">\n <h3 style=\"margin:0px;color:#333;\">Print Preview</h3>\n <button id=\"btnClosePrintPreview\" style=\"padding:6px 12px 6px 12px;cursor:pointer;border:1px solid rgb(221, 221, 221);border-radius:4px;background:rgb(245, 245, 245);\">Close</button>\n </div>\n <div id=\"previewContent\" style=\"flex:1;padding:32px;overflow:auto;background:white;\">\n <pre id=\"previewText\" style=\"color:#000;white-space:pre-wrap;word-wrap:break-word;margin:0px;font:normal normal 14px/1.6 monospace;\"></pre>\n </div>\n <div style=\"padding:16px;border-top:1px solid #ddd;text-align:right;\">\n <button id=\"btnPrintFromPreview\" style=\"padding:8px 16px 8px 16px;cursor:pointer;border:1px solid rgb(0, 123, 255);color:white;border-radius:4px;font-size:16px;background:rgb(0, 123, 255);\">Print</button>\n </div>\n </div>\n</div>\n","style":":host {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n* {\n box-sizing: border-box;\n}\n\nbutton {\n transition: opacity 0.2s;\n}\n\nbutton:hover {\n opacity: 0.8;\n}\n\nbutton:active {\n transform: scale(0.98);\n}\n\n@media print {\n #toolbar {\n display: none !important;\n }\n #textContent {\n padding: 0;\n background: white !important;\n color: black !important;\n }\n}","script":"/**\n * @param {BaseScreenViewerAndControl} instance\n */\nexport function init(instance) {\n const themeSelector = instance._getDomElement('themeSelector');\n const fontSizeSelector = instance._getDomElement('fontSizeSelector');\n const btnPrintPreview = instance._getDomElement('btnPrintPreview');\n const btnPrint = instance._getDomElement('btnPrint');\n const textContent = instance._getDomElement('textContent');\n const printPreviewModal = instance._getDomElement('printPreviewModal');\n const btnClosePrintPreview = instance._getDomElement('btnClosePrintPreview');\n const btnPrintFromPreview = instance._getDomElement('btnPrintFromPreview');\n const previewText = instance._getDomElement('previewText');\n const toolbar = instance._getDomElement('toolbar');\n const textViewerContainer = instance._getDomElement('textViewerContainer');\n\n // Theme-i yükləyirik\n let currentTheme = instance.theme || 'default';\n if (instance.saveTheme) {\n const savedTheme = localStorage.getItem('textviewer_theme');\n if (savedTheme) {\n currentTheme = savedTheme;\n }\n }\n themeSelector.value = currentTheme;\n applyTheming(instance, currentTheme);\n \n // Theme dəyişdirmə event-i\n themeSelector.addEventListener('change', (e) => {\n const selectedTheme = e.target.value;\n applyTheming(instance, selectedTheme);\n if (instance.saveTheme) {\n localStorage.setItem('textviewer_theme', selectedTheme);\n }\n });\n\n function applyTheming(inst, theme) {\n const themes = {\n 'light': {\n borderColor: '#ddd',\n toolbarBg: '#f5f5f5',\n buttonBg: '#fff',\n contentBg: '#fff',\n textColor: '#333'\n },\n 'dark': {\n borderColor: '#444',\n toolbarBg: '#2d2d2d',\n buttonBg: '#3d3d3d',\n contentBg: '#1e1e1e',\n textColor: '#e0e0e0'\n },\n 'sepia': {\n borderColor: '#d4c5a9',\n toolbarBg: '#f4ecd8',\n buttonBg: '#f9f6ed',\n contentBg: '#f9f6ed',\n textColor: '#5b4636'\n },\n 'blue': {\n borderColor: '#4a90e2',\n toolbarBg: '#e3f2fd',\n buttonBg: '#f5f9ff',\n contentBg: '#f5f9ff',\n textColor: '#1565c0'\n }\n };\n \n const colors = themes[theme] || themes['light'];\n \n // Toolbar\n if (toolbar) {\n toolbar.style.background = colors.toolbarBg;\n toolbar.style.borderBottomColor = colors.borderColor;\n }\n \n // Buttons\n [btnPrintPreview, btnPrint].forEach(btn => {\n if (btn) {\n btn.style.background = colors.buttonBg;\n btn.style.color = colors.textColor;\n btn.style.borderColor = colors.borderColor;\n }\n });\n \n // Selectors\n [themeSelector, fontSizeSelector].forEach(sel => {\n if (sel) {\n sel.style.background = colors.buttonBg;\n sel.style.color = colors.textColor;\n sel.style.borderColor = colors.borderColor;\n }\n });\n \n // Text content\n if (textContent) {\n textContent.style.background = colors.contentBg;\n textContent.style.color = colors.textColor;\n }\n }\n\n // Font ölçüsünü yükləyirik\n let currentFontSize = instance.fontSize || '16px';\n if (instance.saveFontSize) {\n const savedFontSize = localStorage.getItem('textviewer_fontsize');\n if (savedFontSize) {\n currentFontSize = savedFontSize;\n }\n }\n fontSizeSelector.value = currentFontSize;\n applyFontSize(currentFontSize);\n \n // Font ölçüsü dəyişdirmə event-i\n fontSizeSelector.addEventListener('change', (e) => {\n const selectedSize = e.target.value;\n applyFontSize(selectedSize);\n if (instance.saveFontSize) {\n localStorage.setItem('textviewer_fontsize', selectedSize);\n }\n });\n\n function applyFontSize(size) {\n if (textContent) {\n textContent.style.fontSize = size;\n }\n }\n\n // Property dəyişiklikləri üçün event-lər (WebUI Designer-də dəyişəndə)\n instance._assignEvent('theme-changed', () => {\n applyTheming(instance, instance.theme || 'light');\n if (themeSelector) {\n themeSelector.value = instance.theme || 'light';\n }\n });\n \n instance._assignEvent('font-size-changed', () => {\n const newSize = instance.fontSize || '16px';\n applyFontSize(newSize);\n if (fontSizeSelector) {\n fontSizeSelector.value = newSize;\n }\n });\n \n //instance._assignEvent('text-state-changed', loadStateContent);\n\n // State yükləmə funksiyası\n /*function loadStateContent() {\n if (instance.textState && textContent) {\n window.IOB.getState(instance.textState).then(state => {\n if (state && state.val !== null && state.val !== undefined) {\n textContent.textContent = state.val;\n }\n }).catch(err => {\n console.error('Error loading state:', err);\n textContent.textContent = 'Error loading text from state';\n });\n\n // State dəyişikliklərini dinləyirik\n window.IOB.subscribe(instance.textState, (id, state) => {\n if (state && state.val !== null && state.val !== undefined) {\n textContent.textContent = state.val;\n }\n });\n }\n }\n\n // İlk yükləmə\\n //loadStateContent();*/\n\n // Print funksiyası\n function printContent() {\n const content = textContent.textContent || 'No content to print';\n const printWindow = window.open('', '_blank', 'width=800,height=600');\n \n if (!printWindow) {\n alert('Please allow popups for print functionality');\n return;\n }\n \n printWindow.document.write(`<!DOCTYPE html>\n<html>\n<head>\n <title>Print - Text Viewer</title>\n <style>\n body {\n font-family: monospace;\n padding: 5mm;\n line-height: 1.3;\n color: #000;\n margin: 0;\n font-size: 9pt;\n }\n pre {\n white-space: pre-wrap;\n word-wrap: break-word;\n font-family: monospace;\n margin: 0; page-break-inside: avoid; } @media print { @page { size: A4; margin: 10mm; } body {\n padding: 10mm;\n }\n }\n </style>\n</head>\n<body>\n <pre>${content.replace(/</g, '&lt;').replace(/>/g, '&gt;')}</pre>\n <script>\n window.onload = function() {\n setTimeout(() => {\n window.print();\n }, 250);\n };\n </script>\n</body>\n</html>`);\n printWindow.document.close();\n }\n\n // Print Preview\n btnPrintPreview.addEventListener('click', () => {\n const content = textContent.textContent || 'No content';\n previewText.textContent = content;\n printPreviewModal.style.display = 'block';\n });\n\n // Close Print Preview\n btnClosePrintPreview.addEventListener('click', () => {\n printPreviewModal.style.display = 'none';\n });\n\n // Print from Preview\n btnPrintFromPreview.addEventListener('click', () => {\n printContent();\n printPreviewModal.style.display = 'none';\n });\n\n // Direct Print\n btnPrint.addEventListener('click', () => {\n printContent();\n });\n}\n\n/**\n * @param {BaseScreenViewerAndControl} instance\n */\nexport function disconnectedCallback(instance) {\n \n}","properties":{"textState":{"type":"ioBrokerObject"},"theme":{"type":"enum","default":"default","values":["default","dark","light","blue","sepia"]},"fontSize":{"type":"string","default":"16px"},"saveTheme":{"type":"boolean"},"saveFontSize":{"type":"boolean"}},"settings":{"width":"800px","height":"600px","visibilityEnabled":"false","visibilityGroups":"","visibilityAction":"hide","visibilityRedirectScreen":""}}
1
+ {"html": "<div id=\"textViewerContainer\" style=\"width:100%;height:100%;display:flex;flex-direction:column;\">\n <div id=\"toolbar\" style=\"padding:8px;border-bottom:1px solid var(--border-color);display:flex;gap:8px;background:var(--toolbar-bg);\">\n <button id=\"btnPrintPreview\" style=\"padding:6px 12px 6px 12px;cursor:pointer;border:1px solid var(--border-color);background:var(--button-bg);color:var(--text-color);border-radius:4px;\">Print Preview</button>\n <button id=\"btnPrint\" style=\"padding:6px 12px 6px 12px;cursor:pointer;border:1px solid var(--border-color);background:var(--button-bg);color:var(--text-color);border-radius:4px;\">Print</button>\n <select id=\"themeSelector\" style=\"padding:6px;border:1px solid var(--border-color);background:var(--button-bg);color:var(--text-color);border-radius:4px;\">\n <option value=\"default\">Default</option>\n <option value=\"light\">Light</option>\n <option value=\"dark\">Dark</option>\n <option value=\"blue\">Blue</option>\n <option value=\"sepia\">Sepia</option>\n </select>\n <select id=\"fontSizeSelector\" style=\"padding:6px;border:1px solid var(--border-color);background:var(--button-bg);color:var(--text-color);border-radius:4px;\">\n <option value=\"12px\">Small</option>\n <option value=\"16px\" selected>Medium</option>\n <option value=\"20px\">Large</option>\n <option value=\"24px\">Extra Large</option>\n </select>\n </div>\n <div id=\"textContent\" bind-content:text=\"??textState\" style=\"flex:1;padding:16px;overflow:auto;background:var(--content-bg);color:var(--text-color);font-family:monospace;font-size:var(--font-size);line-height:1.6;white-space:pre-wrap;word-wrap:break-word;\"></div>\n</div>\n<div id=\"printPreviewModal\" style=\"display:none;position:fixed;top:0;left:0;width:100%;height:100%;z-index:10000;background:rgba(0, 0, 0, 0.8);\">\n <div style=\"position:relative;width:90%;height:90%;margin:5% auto 5% auto;border-radius:8px;display:flex;flex-direction:column;background:white;\">\n <div style=\"padding:16px;border-bottom:1px solid var(--ui-border,#ddd);display:flex;justify-content:space-between;align-items:center;\">\n <h3 style=\"margin:0px;color:#333;\">Print Preview</h3>\n <button id=\"btnClosePrintPreview\" style=\"padding:6px 12px 6px 12px;cursor:pointer;border:1px solid rgb(221, 221, 221);border-radius:4px;background:rgb(245, 245, 245);\">Close</button>\n </div>\n <div id=\"previewContent\" style=\"flex:1;padding:32px;overflow:auto;background:white;\">\n <pre id=\"previewText\" style=\"color:#000;white-space:pre-wrap;word-wrap:break-word;margin:0px;font:normal normal 14px/1.6 monospace;\"></pre>\n </div>\n <div style=\"padding:16px;border-top:1px solid var(--ui-border,#ddd);text-align:right;\">\n <button id=\"btnPrintFromPreview\" style=\"padding:8px 16px 8px 16px;cursor:pointer;border:1px solid rgb(0, 123, 255);color:white;border-radius:4px;font-size:16px;background:rgb(0, 123, 255);\">Print</button>\n </div>\n </div>\n</div>\n", "style": ":host {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n* {\n box-sizing: border-box;\n}\n\nbutton {\n transition: opacity 0.2s;\n}\n\nbutton:hover {\n opacity: 0.8;\n}\n\nbutton:active {\n transform: scale(0.98);\n}\n\n@media print {\n #toolbar {\n display: none !important;\n }\n #textContent {\n padding: 0;\n background: white !important;\n color: black !important;\n }\n}", "script": "/**\n * @param {BaseScreenViewerAndControl} instance\n */\nexport function init(instance) {\n const themeSelector = instance._getDomElement('themeSelector');\n const fontSizeSelector = instance._getDomElement('fontSizeSelector');\n const btnPrintPreview = instance._getDomElement('btnPrintPreview');\n const btnPrint = instance._getDomElement('btnPrint');\n const textContent = instance._getDomElement('textContent');\n const printPreviewModal = instance._getDomElement('printPreviewModal');\n const btnClosePrintPreview = instance._getDomElement('btnClosePrintPreview');\n const btnPrintFromPreview = instance._getDomElement('btnPrintFromPreview');\n const previewText = instance._getDomElement('previewText');\n const toolbar = instance._getDomElement('toolbar');\n const textViewerContainer = instance._getDomElement('textViewerContainer');\n\n // Theme-i yükləyirik\n let currentTheme = instance.theme || 'default';\n if (instance.saveTheme) {\n const savedTheme = localStorage.getItem('textviewer_theme');\n if (savedTheme) {\n currentTheme = savedTheme;\n }\n }\n themeSelector.value = currentTheme;\n applyTheming(instance, currentTheme);\n \n // Theme dəyişdirmə event-i\n themeSelector.addEventListener('change', (e) => {\n const selectedTheme = e.target.value;\n applyTheming(instance, selectedTheme);\n if (instance.saveTheme) {\n localStorage.setItem('textviewer_theme', selectedTheme);\n }\n });\n\n function applyTheming(inst, theme) {\n const themes = {\n 'light': {\n borderColor: '#ddd',\n toolbarBg: '#f5f5f5',\n buttonBg: '#fff',\n contentBg: '#fff',\n textColor: '#333'\n },\n 'dark': {\n borderColor: '#444',\n toolbarBg: '#2d2d2d',\n buttonBg: '#3d3d3d',\n contentBg: '#1e1e1e',\n textColor: '#e0e0e0'\n },\n 'sepia': {\n borderColor: '#d4c5a9',\n toolbarBg: '#f4ecd8',\n buttonBg: '#f9f6ed',\n contentBg: '#f9f6ed',\n textColor: '#5b4636'\n },\n 'blue': {\n borderColor: '#4a90e2',\n toolbarBg: '#e3f2fd',\n buttonBg: '#f5f9ff',\n contentBg: '#f5f9ff',\n textColor: '#1565c0'\n }\n };\n \n const colors = themes[theme] || themes['light'];\n \n // Toolbar\n if (toolbar) {\n toolbar.style.background = colors.toolbarBg;\n toolbar.style.borderBottomColor = colors.borderColor;\n }\n \n // Buttons\n [btnPrintPreview, btnPrint].forEach(btn => {\n if (btn) {\n btn.style.background = colors.buttonBg;\n btn.style.color = colors.textColor;\n btn.style.borderColor = colors.borderColor;\n }\n });\n \n // Selectors\n [themeSelector, fontSizeSelector].forEach(sel => {\n if (sel) {\n sel.style.background = colors.buttonBg;\n sel.style.color = colors.textColor;\n sel.style.borderColor = colors.borderColor;\n }\n });\n \n // Text content\n if (textContent) {\n textContent.style.background = colors.contentBg;\n textContent.style.color = colors.textColor;\n }\n }\n\n // Font ölçüsünü yükləyirik\n let currentFontSize = instance.fontSize || '16px';\n if (instance.saveFontSize) {\n const savedFontSize = localStorage.getItem('textviewer_fontsize');\n if (savedFontSize) {\n currentFontSize = savedFontSize;\n }\n }\n fontSizeSelector.value = currentFontSize;\n applyFontSize(currentFontSize);\n \n // Font ölçüsü dəyişdirmə event-i\n fontSizeSelector.addEventListener('change', (e) => {\n const selectedSize = e.target.value;\n applyFontSize(selectedSize);\n if (instance.saveFontSize) {\n localStorage.setItem('textviewer_fontsize', selectedSize);\n }\n });\n\n function applyFontSize(size) {\n if (textContent) {\n textContent.style.fontSize = size;\n }\n }\n\n // Property dəyişiklikləri üçün event-lər (WebUI Designer-də dəyişəndə)\n instance._assignEvent('theme-changed', () => {\n applyTheming(instance, instance.theme || 'light');\n if (themeSelector) {\n themeSelector.value = instance.theme || 'light';\n }\n });\n \n instance._assignEvent('font-size-changed', () => {\n const newSize = instance.fontSize || '16px';\n applyFontSize(newSize);\n if (fontSizeSelector) {\n fontSizeSelector.value = newSize;\n }\n });\n \n //instance._assignEvent('text-state-changed', loadStateContent);\n\n // State yükləmə funksiyası\n /*function loadStateContent() {\n if (instance.textState && textContent) {\n window.IOB.getState(instance.textState).then(state => {\n if (state && state.val !== null && state.val !== undefined) {\n textContent.textContent = state.val;\n }\n }).catch(err => {\n console.error('Error loading state:', err);\n textContent.textContent = 'Error loading text from state';\n });\n\n // State dəyişikliklərini dinləyirik\n window.IOB.subscribe(instance.textState, (id, state) => {\n if (state && state.val !== null && state.val !== undefined) {\n textContent.textContent = state.val;\n }\n });\n }\n }\n\n // İlk yükləmə\\n //loadStateContent();*/\n\n // Print funksiyası\n function printContent() {\n const content = textContent.textContent || 'No content to print';\n const printWindow = window.open('', '_blank', 'width=800,height=600');\n \n if (!printWindow) {\n alert('Please allow popups for print functionality');\n return;\n }\n \n printWindow.document.write(`<!DOCTYPE html>\n<html>\n<head>\n <title>Print - Text Viewer</title>\n <style>\n body {\n font-family: monospace;\n padding: 5mm;\n line-height: 1.3;\n color: #000;\n margin: 0;\n font-size: 9pt;\n }\n pre {\n white-space: pre-wrap;\n word-wrap: break-word;\n font-family: monospace;\n margin: 0; page-break-inside: avoid; } @media print { @page { size: A4; margin: 10mm; } body {\n padding: 10mm;\n }\n }\n </style>\n</head>\n<body>\n <pre>${content.replace(/</g, '&lt;').replace(/>/g, '&gt;')}</pre>\n <script>\n window.onload = function() {\n setTimeout(() => {\n window.print();\n }, 250);\n };\n </script>\n</body>\n</html>`);\n printWindow.document.close();\n }\n\n // Print Preview\n btnPrintPreview.addEventListener('click', () => {\n const content = textContent.textContent || 'No content';\n previewText.textContent = content;\n printPreviewModal.style.display = 'block';\n });\n\n // Close Print Preview\n btnClosePrintPreview.addEventListener('click', () => {\n printPreviewModal.style.display = 'none';\n });\n\n // Print from Preview\n btnPrintFromPreview.addEventListener('click', () => {\n printContent();\n printPreviewModal.style.display = 'none';\n });\n\n // Direct Print\n btnPrint.addEventListener('click', () => {\n printContent();\n });\n}\n\n/**\n * @param {BaseScreenViewerAndControl} instance\n */\nexport function disconnectedCallback(instance) {\n \n}", "properties": {"textState": {"type": "ioBrokerObject"}, "theme": {"type": "enum", "default": "default", "values": ["default", "dark", "light", "blue", "sepia"]}, "fontSize": {"type": "string", "default": "16px"}, "saveTheme": {"type": "boolean"}, "saveFontSize": {"type": "boolean"}}, "settings": {"width": "800px", "height": "600px", "visibilityEnabled": "false", "visibilityGroups": "", "visibilityAction": "hide", "visibilityRedirectScreen": ""}}