dars-framework 1.9.8__tar.gz → 1.9.9__tar.gz

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 (178) hide show
  1. {dars_framework-1.9.8/dars_framework.egg-info → dars_framework-1.9.9}/PKG-INFO +1 -1
  2. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/exporters/web/resources/dap.js +251 -91
  3. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/scripts/dscript.py +12 -1
  4. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/scripts/utils_ds.py +3 -3
  5. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/version.py +2 -2
  6. {dars_framework-1.9.8 → dars_framework-1.9.9/dars_framework.egg-info}/PKG-INFO +1 -1
  7. {dars_framework-1.9.8 → dars_framework-1.9.9}/pyproject.toml +1 -1
  8. {dars_framework-1.9.8 → dars_framework-1.9.9}/Dars-logo.png +0 -0
  9. {dars_framework-1.9.8 → dars_framework-1.9.9}/LICENSE +0 -0
  10. {dars_framework-1.9.8 → dars_framework-1.9.9}/MANIFEST.in +0 -0
  11. {dars_framework-1.9.8 → dars_framework-1.9.9}/README.md +0 -0
  12. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/__init__.py +0 -0
  13. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/actionProtocol.py +0 -0
  14. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/all.py +0 -0
  15. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/backend/__init__.py +0 -0
  16. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/backend/components.py +0 -0
  17. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/backend/data.py +0 -0
  18. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/backend/http.py +0 -0
  19. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/backend/json_utils.py +0 -0
  20. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/backend/middleware.py +0 -0
  21. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/backend/route_loader.py +0 -0
  22. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/backend/ssr.py +0 -0
  23. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/backend/store.py +0 -0
  24. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/backend/upload.py +0 -0
  25. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/cli/__init__.py +0 -0
  26. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/cli/doctor/__init__.py +0 -0
  27. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/cli/doctor/detect.py +0 -0
  28. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/cli/doctor/doctor.py +0 -0
  29. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/cli/doctor/installers.py +0 -0
  30. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/cli/doctor/persist.py +0 -0
  31. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/cli/doctor/preflight.py +0 -0
  32. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/cli/doctor/ui.py +0 -0
  33. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/cli/dpm.py +0 -0
  34. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/cli/generate.py +0 -0
  35. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/cli/hot_reload.py +0 -0
  36. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/cli/main.py +0 -0
  37. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/cli/preview.py +0 -0
  38. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/cli/prompts.py +0 -0
  39. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/cli/translations.py +0 -0
  40. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/__init__.py +0 -0
  41. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/advanced/__init__.py +0 -0
  42. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/advanced/accordion.py +0 -0
  43. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/advanced/card.py +0 -0
  44. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/advanced/file_upload.py +0 -0
  45. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/advanced/head.py +0 -0
  46. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/advanced/modal.py +0 -0
  47. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/advanced/navbar.py +0 -0
  48. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/advanced/outlet.py +0 -0
  49. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/advanced/table.py +0 -0
  50. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/advanced/tabs.py +0 -0
  51. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/__init__.py +0 -0
  52. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/audio.py +0 -0
  53. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/button.py +0 -0
  54. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/checkbox.py +0 -0
  55. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/container.py +0 -0
  56. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/datepicker.py +0 -0
  57. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/each_component.py +0 -0
  58. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/if_component.py +0 -0
  59. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/image.py +0 -0
  60. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/input.py +0 -0
  61. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/link.py +0 -0
  62. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/markdown.py +0 -0
  63. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/page.py +0 -0
  64. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/progressbar.py +0 -0
  65. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/radiobutton.py +0 -0
  66. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/section.py +0 -0
  67. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/select.py +0 -0
  68. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/show_component.py +0 -0
  69. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/slider.py +0 -0
  70. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/spinner.py +0 -0
  71. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/text.py +0 -0
  72. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/textarea.py +0 -0
  73. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/tooltip.py +0 -0
  74. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/basic/video.py +0 -0
  75. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/layout/__init__.py +0 -0
  76. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/layout/anchor.py +0 -0
  77. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/layout/flex.py +0 -0
  78. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/layout/grid.py +0 -0
  79. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/visualization/__init__.py +0 -0
  80. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/visualization/chart.py +0 -0
  81. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/components/visualization/table.py +0 -0
  82. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/config.py +0 -0
  83. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/core/__init__.py +0 -0
  84. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/core/app.py +0 -0
  85. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/core/component.py +0 -0
  86. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/core/events.py +0 -0
  87. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/core/js_bridge.py +0 -0
  88. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/core/properties.py +0 -0
  89. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/core/route_types.py +0 -0
  90. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/core/routing.py +0 -0
  91. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/core/state.py +0 -0
  92. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/core/state_v2.py +0 -0
  93. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/core/utilities.py +0 -0
  94. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/dars_tests/apps_test/health_check.py +0 -0
  95. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/dars_tests/run_tests.py +0 -0
  96. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/dars_tests/tests/test_advanced_components.py +0 -0
  97. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/dars_tests/tests/test_basic_components.py +0 -0
  98. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/dars_tests/tests/test_core_and_cli.py +0 -0
  99. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/dars_tests/tests/test_layout_components.py +0 -0
  100. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/dars_tests/tests/test_version_check.py +0 -0
  101. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/desktop/__init__.py +0 -0
  102. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/desktop/api.py +0 -0
  103. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/desktop/js_generator.py +0 -0
  104. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/docs/__init__.py +0 -0
  105. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/docs/index.md +0 -0
  106. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/env.py +0 -0
  107. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/exporters/__init__.py +0 -0
  108. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/exporters/base.py +0 -0
  109. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/exporters/desktop/electron.py +0 -0
  110. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/exporters/web/__init__.py +0 -0
  111. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/exporters/web/html_css_js.py +0 -0
  112. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/exporters/web/resources/anim.js +0 -0
  113. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/exporters/web/resources/dars.min.js +0 -0
  114. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/exporters/web/resources/dompurify.js +0 -0
  115. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/exporters/web/resources/router.js +0 -0
  116. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/exporters/web/resources/ssr.js +0 -0
  117. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/exporters/web/vdom.py +0 -0
  118. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/hooks/__init__.py +0 -0
  119. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/hooks/form_helpers.py +0 -0
  120. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/hooks/form_validator.py +0 -0
  121. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/hooks/set_vref.py +0 -0
  122. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/hooks/update_vref.py +0 -0
  123. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/hooks/use_dynamic.py +0 -0
  124. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/hooks/use_fetch.py +0 -0
  125. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/hooks/use_value.py +0 -0
  126. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/hooks/use_vref.py +0 -0
  127. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/hooks/use_watch.py +0 -0
  128. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/hooks/value_helpers.py +0 -0
  129. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/scripts/__init__.py +0 -0
  130. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/scripts/animations.py +0 -0
  131. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/scripts/keycode.py +0 -0
  132. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/scripts/script.py +0 -0
  133. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/security.py +0 -0
  134. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/__init__.py +0 -0
  135. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/desktop/icon.png +0 -0
  136. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/desktop/template/backend/icons/icon.png +0 -0
  137. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/desktop/template/backend/main.js +0 -0
  138. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/desktop/template/backend/package.json +0 -0
  139. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/desktop/template/backend/preload.js +0 -0
  140. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/desktop/template/dars.config.json +0 -0
  141. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/desktop/template/icons/icon.png +0 -0
  142. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/desktop/template/main.py +0 -0
  143. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/desktop/template/public/electron-icon.png +0 -0
  144. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/desktop/template/public/icon.png +0 -0
  145. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/README.md +0 -0
  146. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/advanced/CustomComp/main.py +0 -0
  147. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/advanced/Modal_Demo/advanced_modal_demo.py +0 -0
  148. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/advanced/StateV2/README.md +0 -0
  149. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/advanced/StateV2/animation_component.py +0 -0
  150. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/advanced/StateV2/counter_component.py +0 -0
  151. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/advanced/StateV2/hero_component.py +0 -0
  152. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/advanced/StateV2/main.py +0 -0
  153. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/advanced/StateV2/styles.css +0 -0
  154. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/advanced/StateV2/timer_component.py +0 -0
  155. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/advanced/VariousComponents/all_components_demo.py +0 -0
  156. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/advanced/__init__.py +0 -0
  157. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/advanced/dState/state_mods_demo.py +0 -0
  158. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/advanced/hooks/useDynamic.py +0 -0
  159. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/advanced/hooks/useValue.py +0 -0
  160. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/advanced/hooks/useWatch.py +0 -0
  161. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/basic/HelloWorld/hello_world.py +0 -0
  162. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/basic/Layouts/flex_layout_responsive.py +0 -0
  163. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/basic/Layouts/grid_layout_responsive.py +0 -0
  164. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/basic/Layouts/layout_multipage_demo.py +0 -0
  165. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/basic/PWA/icon-192x192.png +0 -0
  166. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/basic/PWA/icon-512x512.png +0 -0
  167. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/basic/PWA/pwa_custom_icons.py +0 -0
  168. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/basic/__init__.py +0 -0
  169. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/markdown/MarkdownTemplate/README.md +0 -0
  170. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/markdown/MarkdownTemplate/markdown_template.py +0 -0
  171. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/markdown/MarkdownTemplate/other_docs.md +0 -0
  172. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars/templates/examples/markdown/__init__.py +0 -0
  173. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars_framework.egg-info/SOURCES.txt +0 -0
  174. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars_framework.egg-info/dependency_links.txt +0 -0
  175. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars_framework.egg-info/entry_points.txt +0 -0
  176. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars_framework.egg-info/requires.txt +0 -0
  177. {dars_framework-1.9.8 → dars_framework-1.9.9}/dars_framework.egg-info/top_level.txt +0 -0
  178. {dars_framework-1.9.8 → dars_framework-1.9.9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dars-framework
3
- Version: 1.9.8
3
+ Version: 1.9.9
4
4
  Summary: Dars is a Full-Stack multiplatform Python UI framework for building modern, interactive web and desktop apps with Python code. Seamlessly integrated with FastAPI, it allows you to build complete applications with Server-Side Rendering (SSR) and reactive SPA capabilities also classic multipage html and desktop apps in a single codebase.
5
5
  Author-email: ztamdev <ztadevs@gmail.com>
6
6
  Maintainer-email: ztamdev <ztadevs@gmail.com>
@@ -9,6 +9,7 @@ import {
9
9
  updateVRef,
10
10
  __registry,
11
11
  } from "./dars.min.js";
12
+ import { _executeExternalScript } from "./ssr.js";
12
13
 
13
14
  export const __commandRegistry = new Map();
14
15
  export const __darsConfig = {
@@ -85,14 +86,15 @@ _registerCommand("confirm", (args, ctx) => {
85
86
  });
86
87
  _registerCommand("log", (args) => console.log(args.message || args));
87
88
 
88
- _registerCommand("sequence", (args, ctx) => {
89
+ _registerCommand("sequence", async (args, ctx) => {
89
90
  const actions = Array.isArray(args) ? args : args.actions || [];
90
91
  for (const a of actions) {
91
92
  if (a && a.op === "delay") {
92
93
  const ms = a.args?.ms || a.ms || 0;
93
- setTimeout(() => dispatch(a.args.action, ctx), ms);
94
+ await new Promise((resolve) => setTimeout(resolve, ms));
95
+ if (a.args && a.args.action) await dispatch(a.args.action, ctx);
94
96
  } else {
95
- dispatch(a, ctx);
97
+ await dispatch(a, ctx);
96
98
  }
97
99
  }
98
100
  });
@@ -136,20 +138,87 @@ _registerCommand("dom_set_value", (args) => {
136
138
  });
137
139
  // Blocked attribute names that could introduce XSS via event handlers or dangerous protocols
138
140
  const _BLOCKED_ATTRS = new Set([
139
- "onclick","ondblclick","onmousedown","onmouseup","onmouseover","onmouseout",
140
- "onmousemove","onkeydown","onkeyup","onkeypress","onchange","oninput",
141
- "onfocus","onblur","onsubmit","onreset","onselect","onload","onunload",
142
- "onerror","onabort","onresize","onscroll","oncontextmenu","ondrag",
143
- "ondragend","ondragenter","ondragleave","ondragover","ondragstart","ondrop",
144
- "onanimationstart","onanimationend","ontransitionend","onpointerdown",
145
- "onpointerup","onpointermove","onpointerover","onpointerout","onpointerenter",
146
- "onpointerleave","onpointercancel","ontouchstart","ontouchend","ontouchmove",
147
- "ontouchcancel","onwheel","oncopy","oncut","onpaste","onbeforeinput",
148
- "onformdata","oninvalid","onprogress","onratechange","onseeked","onseeking",
149
- "onstalled","onsuspend","ontimeupdate","onvolumechange","onwaiting",
150
- "oncanplay","oncanplaythrough","ondurationchange","onemptied","onended",
151
- "onloadeddata","onloadedmetadata","onloadstart","onplay","onplaying","onpause",
152
- "srcdoc","formaction","action","href","src","data","codebase","classid",
141
+ "onclick",
142
+ "ondblclick",
143
+ "onmousedown",
144
+ "onmouseup",
145
+ "onmouseover",
146
+ "onmouseout",
147
+ "onmousemove",
148
+ "onkeydown",
149
+ "onkeyup",
150
+ "onkeypress",
151
+ "onchange",
152
+ "oninput",
153
+ "onfocus",
154
+ "onblur",
155
+ "onsubmit",
156
+ "onreset",
157
+ "onselect",
158
+ "onload",
159
+ "onunload",
160
+ "onerror",
161
+ "onabort",
162
+ "onresize",
163
+ "onscroll",
164
+ "oncontextmenu",
165
+ "ondrag",
166
+ "ondragend",
167
+ "ondragenter",
168
+ "ondragleave",
169
+ "ondragover",
170
+ "ondragstart",
171
+ "ondrop",
172
+ "onanimationstart",
173
+ "onanimationend",
174
+ "ontransitionend",
175
+ "onpointerdown",
176
+ "onpointerup",
177
+ "onpointermove",
178
+ "onpointerover",
179
+ "onpointerout",
180
+ "onpointerenter",
181
+ "onpointerleave",
182
+ "onpointercancel",
183
+ "ontouchstart",
184
+ "ontouchend",
185
+ "ontouchmove",
186
+ "ontouchcancel",
187
+ "onwheel",
188
+ "oncopy",
189
+ "oncut",
190
+ "onpaste",
191
+ "onbeforeinput",
192
+ "onformdata",
193
+ "oninvalid",
194
+ "onprogress",
195
+ "onratechange",
196
+ "onseeked",
197
+ "onseeking",
198
+ "onstalled",
199
+ "onsuspend",
200
+ "ontimeupdate",
201
+ "onvolumechange",
202
+ "onwaiting",
203
+ "oncanplay",
204
+ "oncanplaythrough",
205
+ "ondurationchange",
206
+ "onemptied",
207
+ "onended",
208
+ "onloadeddata",
209
+ "onloadedmetadata",
210
+ "onloadstart",
211
+ "onplay",
212
+ "onplaying",
213
+ "onpause",
214
+ "srcdoc",
215
+ "formaction",
216
+ "action",
217
+ "href",
218
+ "src",
219
+ "data",
220
+ "codebase",
221
+ "classid",
153
222
  ]);
154
223
 
155
224
  _registerCommand("dom_set_attr", (args) => {
@@ -157,13 +226,17 @@ _registerCommand("dom_set_attr", (args) => {
157
226
  if (!el) return;
158
227
  const attrName = String(args.name).toLowerCase().trim();
159
228
  if (_BLOCKED_ATTRS.has(attrName)) {
160
- console.warn(`[Dars:Security] Blocked attempt to set dangerous attribute: "${attrName}"`);
229
+ console.warn(
230
+ `[Dars:Security] Blocked attempt to set dangerous attribute: "${attrName}"`,
231
+ );
161
232
  return;
162
233
  }
163
234
  // Block javascript: protocol in any remaining attribute value
164
235
  const val = String(args.value);
165
236
  if (/^\s*javascript\s*:/i.test(val)) {
166
- console.warn(`[Dars:Security] Blocked javascript: URI in attribute "${attrName}"`);
237
+ console.warn(
238
+ `[Dars:Security] Blocked javascript: URI in attribute "${attrName}"`,
239
+ );
167
240
  return;
168
241
  }
169
242
  el.setAttribute(attrName, val);
@@ -306,7 +379,9 @@ _registerCommand("fetch", async (args, ctx) => {
306
379
  // When backendUrl is "/" or empty, keep the URL as-is (same-origin).
307
380
  let fetchUrl = args.url;
308
381
  if (fetchUrl && !/^https?:\/\//i.test(fetchUrl)) {
309
- const base = (window.__DARS_SPA_CONFIG__ && window.__DARS_SPA_CONFIG__.backendUrl) || "";
382
+ const base =
383
+ (window.__DARS_SPA_CONFIG__ && window.__DARS_SPA_CONFIG__.backendUrl) ||
384
+ "";
310
385
  if (base && base !== "/") fetchUrl = base.replace(/\/$/, "") + fetchUrl;
311
386
  }
312
387
  const resp = await fetch(fetchUrl, args.options || {});
@@ -370,7 +445,8 @@ _registerCommand("transform", async (args, ctx) => {
370
445
  if (args.method === "upper") return String(input).toUpperCase();
371
446
  if (args.method === "lower") return String(input).toLowerCase();
372
447
  if (args.method === "trim") return String(input == null ? "" : input).trim();
373
- if (args.method === "length") return String(input == null ? "" : input).trim().length;
448
+ if (args.method === "length")
449
+ return String(input == null ? "" : input).trim().length;
374
450
  if (args.method === "is_email") {
375
451
  const s = String(input == null ? "" : input).trim();
376
452
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(s);
@@ -378,7 +454,9 @@ _registerCommand("transform", async (args, ctx) => {
378
454
  if (args.method === "test_pattern") {
379
455
  try {
380
456
  return new RegExp(args.pattern).test(String(input == null ? "" : input));
381
- } catch (_) { return false; }
457
+ } catch (_) {
458
+ return false;
459
+ }
382
460
  }
383
461
  if (args.method === "json_stringify") {
384
462
  // Return the object itself — network_request will JSON.stringify it
@@ -391,22 +469,32 @@ _registerCommand("transform", async (args, ctx) => {
391
469
  if (args.method === "tasks_to_html") {
392
470
  try {
393
471
  const data = typeof input === "string" ? JSON.parse(input) : input;
394
- const tasks = Array.isArray(data) ? data : (data && data.tasks ? data.tasks : []);
395
- if (!tasks.length) return '<p class="text-gray-400 text-sm p-2">No tasks yet.</p>';
396
- return tasks.map(t => {
397
- // Safely extract title — handle string, number, or nested object
398
- let title = "";
399
- if (t && t.title !== undefined && t.title !== null) {
400
- title = typeof t.title === "object" ? JSON.stringify(t.title) : String(t.title);
401
- }
402
- const safeTitle = _sanitize(title);
403
- const done = t && t.done;
404
- const id = t && t.id ? t.id : "";
405
- return `<div class="flex items-center gap-2 p-2 border rounded mb-1 bg-white">
406
- <span class="flex-1 ${done ? 'line-through text-gray-400' : ''}">${safeTitle || '<em class="text-gray-300">untitled</em>'}</span>
472
+ const tasks = Array.isArray(data)
473
+ ? data
474
+ : data && data.tasks
475
+ ? data.tasks
476
+ : [];
477
+ if (!tasks.length)
478
+ return '<p class="text-gray-400 text-sm p-2">No tasks yet.</p>';
479
+ return tasks
480
+ .map((t) => {
481
+ // Safely extract title handle string, number, or nested object
482
+ let title = "";
483
+ if (t && t.title !== undefined && t.title !== null) {
484
+ title =
485
+ typeof t.title === "object"
486
+ ? JSON.stringify(t.title)
487
+ : String(t.title);
488
+ }
489
+ const safeTitle = _sanitize(title);
490
+ const done = t && t.done;
491
+ const id = t && t.id ? t.id : "";
492
+ return `<div class="flex items-center gap-2 p-2 border rounded mb-1 bg-white">
493
+ <span class="flex-1 ${done ? "line-through text-gray-400" : ""}">${safeTitle || '<em class="text-gray-300">untitled</em>'}</span>
407
494
  <span class="text-xs text-gray-400">#${id}</span>
408
495
  </div>`;
409
- }).join("");
496
+ })
497
+ .join("");
410
498
  } catch (e) {
411
499
  return `<p class="text-red-400 text-sm">Error rendering tasks: ${e.message}</p>`;
412
500
  }
@@ -537,7 +625,10 @@ _registerCommand("vref_set", async (args, ctx) => {
537
625
  */
538
626
  _registerCommand("storage_get_to_vref", async (args, ctx) => {
539
627
  const val = localStorage.getItem(args.storage_key);
540
- return dispatch({ op: "vref_update", args: { selector: args.selector, value: val } }, ctx);
628
+ return dispatch(
629
+ { op: "vref_update", args: { selector: args.selector, value: val } },
630
+ ctx,
631
+ );
541
632
  });
542
633
 
543
634
  /**
@@ -589,11 +680,17 @@ _registerCommand("network_request", async (args, ctx) => {
589
680
 
590
681
  // Set loading state
591
682
  if (loading_selector) {
592
- dispatch({ op: "vref_update", args: { selector: loading_selector, value: true } }, ctx);
683
+ dispatch(
684
+ { op: "vref_update", args: { selector: loading_selector, value: true } },
685
+ ctx,
686
+ );
593
687
  }
594
688
 
595
689
  try {
596
- const fetchConfig = { method: method.toUpperCase(), headers: { ...headers } };
690
+ const fetchConfig = {
691
+ method: method.toUpperCase(),
692
+ headers: { ...headers },
693
+ };
597
694
 
598
695
  // Inject auth token if present
599
696
  const token = localStorage.getItem("dars_auth_token");
@@ -624,10 +721,22 @@ _registerCommand("network_request", async (args, ctx) => {
624
721
  localStorage.removeItem("dars_auth_token");
625
722
  const errMsg = "Unauthorized (401)";
626
723
  if (loading_selector) {
627
- dispatch({ op: "vref_update", args: { selector: loading_selector, value: false } }, ctx);
724
+ dispatch(
725
+ {
726
+ op: "vref_update",
727
+ args: { selector: loading_selector, value: false },
728
+ },
729
+ ctx,
730
+ );
628
731
  }
629
732
  if (error_selector) {
630
- dispatch({ op: "vref_update", args: { selector: error_selector, value: errMsg } }, ctx);
733
+ dispatch(
734
+ {
735
+ op: "vref_update",
736
+ args: { selector: error_selector, value: errMsg },
737
+ },
738
+ ctx,
739
+ );
631
740
  }
632
741
  if (on_error) dispatch(on_error, { ...ctx, error: errMsg });
633
742
  return;
@@ -646,20 +755,40 @@ _registerCommand("network_request", async (args, ctx) => {
646
755
  }
647
756
 
648
757
  if (loading_selector) {
649
- dispatch({ op: "vref_update", args: { selector: loading_selector, value: false } }, ctx);
758
+ dispatch(
759
+ {
760
+ op: "vref_update",
761
+ args: { selector: loading_selector, value: false },
762
+ },
763
+ ctx,
764
+ );
650
765
  }
651
766
  if (data_selector) {
652
- dispatch({ op: "vref_update", args: { selector: data_selector, value: data } }, ctx);
767
+ dispatch(
768
+ { op: "vref_update", args: { selector: data_selector, value: data } },
769
+ ctx,
770
+ );
653
771
  }
654
772
  if (on_success) dispatch(on_success, { ...ctx, response: data });
655
-
656
773
  } catch (e) {
657
774
  const errMsg = e && e.message ? e.message : String(e);
658
775
  if (loading_selector) {
659
- dispatch({ op: "vref_update", args: { selector: loading_selector, value: false } }, ctx);
776
+ dispatch(
777
+ {
778
+ op: "vref_update",
779
+ args: { selector: loading_selector, value: false },
780
+ },
781
+ ctx,
782
+ );
660
783
  }
661
784
  if (error_selector) {
662
- dispatch({ op: "vref_update", args: { selector: error_selector, value: errMsg } }, ctx);
785
+ dispatch(
786
+ {
787
+ op: "vref_update",
788
+ args: { selector: error_selector, value: errMsg },
789
+ },
790
+ ctx,
791
+ );
663
792
  }
664
793
  if (on_error) dispatch(on_error, { ...ctx, error: errMsg });
665
794
  }
@@ -711,19 +840,21 @@ _registerCommand("render_tasks", (args, ctx) => {
711
840
  if (!el) return;
712
841
  try {
713
842
  const data = ctx && ctx.response ? ctx.response : {};
714
- const tasks = Array.isArray(data) ? data : (data.tasks || []);
843
+ const tasks = Array.isArray(data) ? data : data.tasks || [];
715
844
  if (!tasks.length) {
716
845
  el.innerHTML = '<p class="text-gray-400 text-sm p-2">No tasks yet.</p>';
717
846
  return;
718
847
  }
719
- el.innerHTML = tasks.map(t => {
720
- const title = _sanitize(String(t.title || ""));
721
- const done = t.done ? "line-through text-gray-400" : "";
722
- return `<div class="flex items-center gap-2 p-2 border rounded mb-1 bg-white shadow-sm">
848
+ el.innerHTML = tasks
849
+ .map((t) => {
850
+ const title = _sanitize(String(t.title || ""));
851
+ const done = t.done ? "line-through text-gray-400" : "";
852
+ return `<div class="flex items-center gap-2 p-2 border rounded mb-1 bg-white shadow-sm">
723
853
  <span class="flex-1 ${done}">${title || "<em class='text-gray-300'>untitled</em>"}</span>
724
854
  <span class="text-xs text-gray-400 ml-2">#${t.id || ""}</span>
725
855
  </div>`;
726
- }).join("");
856
+ })
857
+ .join("");
727
858
  } catch (e) {
728
859
  el.innerHTML = `<p class="text-red-400 text-sm p-2">Error: ${e.message}</p>`;
729
860
  }
@@ -743,7 +874,10 @@ if (_origVrefUpdate) {
743
874
  try {
744
875
  const containerSel = container.getAttribute("data-dap-each");
745
876
  if (containerSel === sel && container.id) {
746
- await dispatch({ op: "dom_each_render", args: { id: container.id } }, ctx);
877
+ await dispatch(
878
+ { op: "dom_each_render", args: { id: container.id } },
879
+ ctx,
880
+ );
747
881
  }
748
882
  } catch (_) {}
749
883
  }
@@ -819,7 +953,10 @@ _registerCommand("dom_each_render", async (args, ctx) => {
819
953
  if (items && !Array.isArray(items) && typeof items === "object") {
820
954
  const keys = ["tasks", "items", "data", "results", "list", "rows"];
821
955
  for (const k of keys) {
822
- if (Array.isArray(items[k])) { items = items[k]; break; }
956
+ if (Array.isArray(items[k])) {
957
+ items = items[k];
958
+ break;
959
+ }
823
960
  }
824
961
  }
825
962
 
@@ -837,49 +974,72 @@ _registerCommand("dom_each_render", async (args, ctx) => {
837
974
 
838
975
  if (!template) {
839
976
  // Fallback: plain text rendering
840
- container.innerHTML = items.map(item => {
841
- const text = _sanitize(String(
842
- item && typeof item === "object"
843
- ? (item.title ?? item.name ?? item.label ?? item.value ?? item.text ?? JSON.stringify(item))
844
- : item
845
- ));
846
- return `<div>${text}</div>`;
847
- }).join("");
977
+ container.innerHTML = items
978
+ .map((item) => {
979
+ const text = _sanitize(
980
+ String(
981
+ item && typeof item === "object"
982
+ ? (item.title ??
983
+ item.name ??
984
+ item.label ??
985
+ item.value ??
986
+ item.text ??
987
+ JSON.stringify(item))
988
+ : item,
989
+ ),
990
+ );
991
+ return `<div>${text}</div>`;
992
+ })
993
+ .join("");
848
994
  return;
849
995
  }
850
996
 
851
997
  // Render each item by substituting placeholders in the template
852
- const rendered = items.map(item => {
853
- if (item === null || item === undefined) return "";
854
- let html = template;
855
-
856
- if (typeof item === "object") {
857
- // Normalize empty/unknown title values before substitution
858
- if (item.title !== undefined) {
859
- const t = String(item.title || "").trim();
860
- item = { ...item, title: (t === "" || t.toLowerCase() === "unknown" || t.toLowerCase() === "null" || t.toLowerCase() === "none") ? "Unknown" : t };
861
- }
862
- // Inject a done_class placeholder value based on the done field
863
- const doneClass = item.done ? "line-through text-gray-400" : "";
864
- item = { ...item, done_class: doneClass };
865
-
866
- // Replace __item_<field>__ with the sanitized field value
867
- for (const [key, val] of Object.entries(item)) {
868
- const placeholder = `__item_${key}__`;
869
- // Don't sanitize class names — they're safe strings we control
870
- const safeVal = key === "done_class" ? String(val) : _sanitize(String(val == null ? "" : val));
871
- html = html.split(placeholder).join(safeVal);
998
+ const rendered = items
999
+ .map((item) => {
1000
+ if (item === null || item === undefined) return "";
1001
+ let html = template;
1002
+
1003
+ if (typeof item === "object") {
1004
+ // Normalize empty/unknown title values before substitution
1005
+ if (item.title !== undefined) {
1006
+ const t = String(item.title || "").trim();
1007
+ item = {
1008
+ ...item,
1009
+ title:
1010
+ t === "" ||
1011
+ t.toLowerCase() === "unknown" ||
1012
+ t.toLowerCase() === "null" ||
1013
+ t.toLowerCase() === "none"
1014
+ ? "Unknown"
1015
+ : t,
1016
+ };
1017
+ }
1018
+ // Inject a done_class placeholder value based on the done field
1019
+ const doneClass = item.done ? "line-through text-gray-400" : "";
1020
+ item = { ...item, done_class: doneClass };
1021
+
1022
+ // Replace __item_<field>__ with the sanitized field value
1023
+ for (const [key, val] of Object.entries(item)) {
1024
+ const placeholder = `__item_${key}__`;
1025
+ // Don't sanitize class names — they're safe strings we control
1026
+ const safeVal =
1027
+ key === "done_class"
1028
+ ? String(val)
1029
+ : _sanitize(String(val == null ? "" : val));
1030
+ html = html.split(placeholder).join(safeVal);
1031
+ }
1032
+ } else {
1033
+ // Scalar item — replace generic __item_value__ placeholder
1034
+ const safeVal = _sanitize(String(item));
1035
+ html = html.split("__item_value__").join(safeVal);
872
1036
  }
873
- } else {
874
- // Scalar item — replace generic __item_value__ placeholder
875
- const safeVal = _sanitize(String(item));
876
- html = html.split("__item_value__").join(safeVal);
877
- }
878
1037
 
879
- // Remove any unreplaced sentinel placeholders
880
- html = html.replace(/__item_[a-zA-Z0-9_]+__/g, "");
881
- return html;
882
- }).join("");
1038
+ // Remove any unreplaced sentinel placeholders
1039
+ html = html.replace(/__item_[a-zA-Z0-9_]+__/g, "");
1040
+ return html;
1041
+ })
1042
+ .join("");
883
1043
 
884
1044
  container.innerHTML = rendered;
885
1045
  });
@@ -171,6 +171,13 @@ def compile_val(v, is_async=False):
171
171
  return f"String({sub}).toLowerCase()"
172
172
  elif method == 'trim':
173
173
  return f"String({sub}).trim()"
174
+ elif method == 'length':
175
+ return f"String({sub} || '').trim().length"
176
+ elif method == 'is_email':
177
+ return f"/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(String({sub} || '').trim())"
178
+ elif method == 'test_pattern':
179
+ pat = json.dumps(args.get('pattern', ''))
180
+ return f"(function() {{ try {{ return new RegExp({pat}).test(String({sub} || '')); }} catch(_) {{ return false; }} }})()"
174
181
  elif method == 'validate_operator':
175
182
  ops = json.dumps(args.get('valid_ops', ['+', '-', '*', '/']), default=_ser)
176
183
  return f"(({ops}).includes({sub}) ? {sub} : '+')"
@@ -179,7 +186,11 @@ def compile_val(v, is_async=False):
179
186
  elif op == 'bool_expr':
180
187
  left = compile_val(args.get('left'), is_async=is_async)
181
188
  right = compile_val(args.get('right'), is_async=is_async)
182
- op_map = {'==': '==', '===': '===', '!=': '!=', '!==': '!==', '>': '>', '<': '<', '>=': '>=', '<=': '<='}
189
+ op_map = {
190
+ '==': '==', '===': '===', '!=': '!=', '!==': '!==',
191
+ '>': '>', '<': '<', '>=': '>=', '<=': '<=',
192
+ '&&': '&&', '||': '||'
193
+ }
183
194
  js_op = op_map.get(args.get('operator'), '==')
184
195
  return f"({left} {js_op} {right})"
185
196
 
@@ -514,7 +514,7 @@ def getValue(input_id: str, target_id: str) -> RawJS:
514
514
  return RawJS(code=Action.dom_set_text(id=target_id, text=RawJS(f"document.getElementById('{input_id}').value")))
515
515
 
516
516
 
517
- def clearInput(input_id: str) -> RawJS:
517
+ def clearInput(input_id: str) -> dScript:
518
518
  """
519
519
  Clear the value of an input field and trigger the 'input' event.
520
520
 
@@ -522,14 +522,14 @@ def clearInput(input_id: str) -> RawJS:
522
522
  input_id (str): The ID of the input or textarea.
523
523
 
524
524
  Returns:
525
- RawJS: The compiled `input_clear` action.
525
+ dScript: The compiled `input_clear` action.
526
526
 
527
527
  Example:
528
528
  ```python
529
529
  Button("Clear Search", on_click=clearInput("search_box"))
530
530
  ```
531
531
  """
532
- return RawJS(code=Action.input_clear(input_id))
532
+ return dScript(data={"op": "input_clear", "args": {"id": input_id}})
533
533
 
534
534
 
535
535
  # ============= Storage Utilities =============
@@ -6,5 +6,5 @@
6
6
  #
7
7
  # Copyright (c) 2025 ZtaDev
8
8
 
9
- __version__ = "1.9.8"
10
- __release_url__ = "https://github.com/ZtaMDev/Dars-Framework/releases/tag/1.9.8"
9
+ __version__ = "1.9.9"
10
+ __release_url__ = "https://github.com/ZtaMDev/Dars-Framework/releases/tag/1.9.9"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dars-framework
3
- Version: 1.9.8
3
+ Version: 1.9.9
4
4
  Summary: Dars is a Full-Stack multiplatform Python UI framework for building modern, interactive web and desktop apps with Python code. Seamlessly integrated with FastAPI, it allows you to build complete applications with Server-Side Rendering (SSR) and reactive SPA capabilities also classic multipage html and desktop apps in a single codebase.
5
5
  Author-email: ztamdev <ztadevs@gmail.com>
6
6
  Maintainer-email: ztamdev <ztadevs@gmail.com>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dars-framework"
7
- version = "1.9.8"
7
+ version = "1.9.9"
8
8
  description = "Dars is a Full-Stack multiplatform Python UI framework for building modern, interactive web and desktop apps with Python code. Seamlessly integrated with FastAPI, it allows you to build complete applications with Server-Side Rendering (SSR) and reactive SPA capabilities also classic multipage html and desktop apps in a single codebase."
9
9
  dependencies = [ "rich==15.0.0", "bs4==0.0.2", "uvicorn==0.46.0", "markdown2==2.5.5", "requests==2.33.1", "plotly==6.7.0", "fastapi==0.136.1", "rjsmin==1.2.5", "rcssmin==1.2.2", "starlette==0.47.3", "python-multipart==0.0.28"]
10
10
  license = "MPL-2.0"
File without changes
File without changes