@perspective-dev/viewer 4.0.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 (394) hide show
  1. package/LICENSE.md +193 -0
  2. package/README.md +4 -0
  3. package/dist/cdn/perspective-viewer.js +3 -0
  4. package/dist/cdn/perspective-viewer.js.map +7 -0
  5. package/dist/css/dracula.css +1 -0
  6. package/dist/css/gruvbox-dark.css +1 -0
  7. package/dist/css/gruvbox.css +1 -0
  8. package/dist/css/icons.css +1 -0
  9. package/dist/css/intl/de.css +1 -0
  10. package/dist/css/intl/es.css +1 -0
  11. package/dist/css/intl/fr.css +1 -0
  12. package/dist/css/intl/ja.css +1 -0
  13. package/dist/css/intl/pt.css +1 -0
  14. package/dist/css/intl/zh.css +1 -0
  15. package/dist/css/intl.css +1 -0
  16. package/dist/css/monokai.css +1 -0
  17. package/dist/css/pro-dark.css +1 -0
  18. package/dist/css/pro.css +1 -0
  19. package/dist/css/solarized-dark.css +1 -0
  20. package/dist/css/solarized.css +1 -0
  21. package/dist/css/themes.css +1 -0
  22. package/dist/css/vaporwave.css +1 -0
  23. package/dist/css/variables.css +0 -0
  24. package/dist/esm/bootstrap.d.ts +1 -0
  25. package/dist/esm/extensions.d.ts +70 -0
  26. package/dist/esm/perspective-viewer.d.ts +39 -0
  27. package/dist/esm/perspective-viewer.inline.js +3 -0
  28. package/dist/esm/perspective-viewer.inline.js.map +7 -0
  29. package/dist/esm/perspective-viewer.js +3 -0
  30. package/dist/esm/perspective-viewer.js.map +7 -0
  31. package/dist/esm/plugin.d.ts +195 -0
  32. package/dist/esm/ts-rs/Aggregate.d.ts +1 -0
  33. package/dist/esm/ts-rs/ColumnConfigValues.d.ts +31 -0
  34. package/dist/esm/ts-rs/CustomDatetimeFormat.d.ts +1 -0
  35. package/dist/esm/ts-rs/CustomDatetimeStyleConfig.d.ts +15 -0
  36. package/dist/esm/ts-rs/CustomNumberFormatConfig.d.ts +18 -0
  37. package/dist/esm/ts-rs/DatetimeColorMode.d.ts +1 -0
  38. package/dist/esm/ts-rs/DatetimeFormatType.d.ts +6 -0
  39. package/dist/esm/ts-rs/Expressions.d.ts +3 -0
  40. package/dist/esm/ts-rs/Filter.d.ts +2 -0
  41. package/dist/esm/ts-rs/FilterReducer.d.ts +1 -0
  42. package/dist/esm/ts-rs/FilterTerm.d.ts +2 -0
  43. package/dist/esm/ts-rs/FormatMode.d.ts +1 -0
  44. package/dist/esm/ts-rs/FormatUnit.d.ts +1 -0
  45. package/dist/esm/ts-rs/NumberBackgroundMode.d.ts +1 -0
  46. package/dist/esm/ts-rs/NumberForegroundMode.d.ts +1 -0
  47. package/dist/esm/ts-rs/OptionalUpdate.d.ts +1 -0
  48. package/dist/esm/ts-rs/PluginConfig.d.ts +2 -0
  49. package/dist/esm/ts-rs/RoundingMode.d.ts +1 -0
  50. package/dist/esm/ts-rs/RoundingPriority.d.ts +1 -0
  51. package/dist/esm/ts-rs/Scalar.d.ts +5 -0
  52. package/dist/esm/ts-rs/SignDisplay.d.ts +1 -0
  53. package/dist/esm/ts-rs/SimpleDatetimeFormat.d.ts +1 -0
  54. package/dist/esm/ts-rs/SimpleDatetimeStyleConfig.d.ts +6 -0
  55. package/dist/esm/ts-rs/Sort.d.ts +2 -0
  56. package/dist/esm/ts-rs/SortDir.d.ts +1 -0
  57. package/dist/esm/ts-rs/StringColorMode.d.ts +1 -0
  58. package/dist/esm/ts-rs/TrailingZeroDisplay.d.ts +1 -0
  59. package/dist/esm/ts-rs/UseGrouping.d.ts +1 -0
  60. package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +102 -0
  61. package/dist/esm/ts-rs/serde_json/JsonValue.d.ts +3 -0
  62. package/dist/wasm/perspective-viewer.d.ts +1291 -0
  63. package/dist/wasm/perspective-viewer.js +3883 -0
  64. package/dist/wasm/perspective-viewer.wasm +0 -0
  65. package/dist/wasm/perspective-viewer.wasm.d.ts +142 -0
  66. package/dist/wasm/snippets/perspective-viewer-c69283f6f62a5f14/inline0.js +1 -0
  67. package/dist/wasm/snippets/perspective-viewer-c69283f6f62a5f14/inline1.js +1 -0
  68. package/dist/wasm/snippets/perspective-viewer-c69283f6f62a5f14/inline2.js +1 -0
  69. package/dist/wasm/snippets/perspective-viewer-c69283f6f62a5f14/inline3.js +44 -0
  70. package/dist/wasm/snippets/perspective-viewer-c69283f6f62a5f14/inline4.js +1 -0
  71. package/package.json +55 -0
  72. package/src/less/aggregate-selector.less +72 -0
  73. package/src/less/column-dropdown.less +95 -0
  74. package/src/less/column-selector.less +551 -0
  75. package/src/less/column-settings-panel.less +255 -0
  76. package/src/less/column-style.less +319 -0
  77. package/src/less/column-symbol-attributes.less +73 -0
  78. package/src/less/config-selector.less +363 -0
  79. package/src/less/containers/dropdown-menu.less +94 -0
  80. package/src/less/containers/pairs-list.less +46 -0
  81. package/src/less/containers/radio-list.less +29 -0
  82. package/src/less/containers/scroll-panel.less +27 -0
  83. package/src/less/containers/split-panel.less +80 -0
  84. package/src/less/containers/tabs.less +90 -0
  85. package/src/less/dom/checkbox.less +100 -0
  86. package/src/less/dom/scrollbar.less +35 -0
  87. package/src/less/dom/select.less +63 -0
  88. package/src/less/empty-column.less +72 -0
  89. package/src/less/expression-editor.less +152 -0
  90. package/src/less/filter-dropdown.less +53 -0
  91. package/src/less/filter-item.less +126 -0
  92. package/src/less/form/code-editor.less +137 -0
  93. package/src/less/form/debug.less +88 -0
  94. package/src/less/function-dropdown.less +45 -0
  95. package/src/less/plugin-selector.less +173 -0
  96. package/src/less/render-warning.less +81 -0
  97. package/src/less/status-bar.less +551 -0
  98. package/src/less/type-icon.less +68 -0
  99. package/src/less/viewer.less +368 -0
  100. package/src/rust/components/column_dropdown.rs +162 -0
  101. package/src/rust/components/column_selector/active_column.rs +462 -0
  102. package/src/rust/components/column_selector/add_expression_button.rs +59 -0
  103. package/src/rust/components/column_selector/aggregate_selector.rs +186 -0
  104. package/src/rust/components/column_selector/config_selector.rs +674 -0
  105. package/src/rust/components/column_selector/empty_column.rs +134 -0
  106. package/src/rust/components/column_selector/expression_toolbar.rs +45 -0
  107. package/src/rust/components/column_selector/filter_column.rs +530 -0
  108. package/src/rust/components/column_selector/inactive_column.rs +221 -0
  109. package/src/rust/components/column_selector/invalid_column.rs +37 -0
  110. package/src/rust/components/column_selector/pivot_column.rs +93 -0
  111. package/src/rust/components/column_selector/sort_column.rs +135 -0
  112. package/src/rust/components/column_selector.rs +426 -0
  113. package/src/rust/components/column_settings_sidebar/attributes_tab.rs +34 -0
  114. package/src/rust/components/column_settings_sidebar/mod.rs +17 -0
  115. package/src/rust/components/column_settings_sidebar/save_settings.rs +68 -0
  116. package/src/rust/components/column_settings_sidebar/sidebar.rs +396 -0
  117. package/src/rust/components/column_settings_sidebar/style_tab/column_style.rs +177 -0
  118. package/src/rust/components/column_settings_sidebar/style_tab/stub.rs +34 -0
  119. package/src/rust/components/column_settings_sidebar/style_tab/symbol/row_selector.rs +101 -0
  120. package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_config.rs +24 -0
  121. package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs.rs +185 -0
  122. package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_selector.rs +55 -0
  123. package/src/rust/components/column_settings_sidebar/style_tab/symbol.rs +131 -0
  124. package/src/rust/components/column_settings_sidebar/style_tab.rs +231 -0
  125. package/src/rust/components/containers/dragdrop_list.rs +325 -0
  126. package/src/rust/components/containers/dropdown_menu.rs +104 -0
  127. package/src/rust/components/containers/kvpair.rs +47 -0
  128. package/src/rust/components/containers/mod.rs +28 -0
  129. package/src/rust/components/containers/scroll_panel.rs +311 -0
  130. package/src/rust/components/containers/scroll_panel_item.rs +111 -0
  131. package/src/rust/components/containers/select.rs +269 -0
  132. package/src/rust/components/containers/sidebar.rs +89 -0
  133. package/src/rust/components/containers/split_panel.rs +483 -0
  134. package/src/rust/components/containers/tab_list.rs +104 -0
  135. package/src/rust/components/containers/tests/mod.rs +11 -0
  136. package/src/rust/components/containers/tests/split_panel.rs +91 -0
  137. package/src/rust/components/containers/trap_door_panel.rs +50 -0
  138. package/src/rust/components/copy_dropdown.rs +136 -0
  139. package/src/rust/components/datetime_column_style/custom.rs +222 -0
  140. package/src/rust/components/datetime_column_style/simple.rs +122 -0
  141. package/src/rust/components/datetime_column_style.rs +284 -0
  142. package/src/rust/components/editable_header.rs +183 -0
  143. package/src/rust/components/empty_row.rs +169 -0
  144. package/src/rust/components/error_message.rs +56 -0
  145. package/src/rust/components/export_dropdown.rs +153 -0
  146. package/src/rust/components/expression_editor.rs +153 -0
  147. package/src/rust/components/filter_dropdown.rs +144 -0
  148. package/src/rust/components/font_loader.rs +254 -0
  149. package/src/rust/components/form/code_editor.rs +286 -0
  150. package/src/rust/components/form/color_range_selector.rs +115 -0
  151. package/src/rust/components/form/color_selector.rs +54 -0
  152. package/src/rust/components/form/debug.rs +253 -0
  153. package/src/rust/components/form/highlight.rs +50 -0
  154. package/src/rust/components/form/mod.rs +29 -0
  155. package/src/rust/components/form/number_field.rs +72 -0
  156. package/src/rust/components/form/number_input.rs +45 -0
  157. package/src/rust/components/form/number_range_field.rs +77 -0
  158. package/src/rust/components/form/optional_field.rs +53 -0
  159. package/src/rust/components/form/select_field.rs +104 -0
  160. package/src/rust/components/function_dropdown.rs +151 -0
  161. package/src/rust/components/mod.rs +45 -0
  162. package/src/rust/components/modal.rs +171 -0
  163. package/src/rust/components/number_column_style.rs +522 -0
  164. package/src/rust/components/plugin_selector.rs +196 -0
  165. package/src/rust/components/render_warning.rs +178 -0
  166. package/src/rust/components/status_bar.rs +315 -0
  167. package/src/rust/components/status_bar_counter.rs +229 -0
  168. package/src/rust/components/status_indicator.rs +164 -0
  169. package/src/rust/components/string_column_style.rs +186 -0
  170. package/src/rust/components/style/local_style.rs +35 -0
  171. package/src/rust/components/style/mod.rs +52 -0
  172. package/src/rust/components/style/style_cache.rs +132 -0
  173. package/src/rust/components/style/style_provider.rs +65 -0
  174. package/src/rust/components/style_controls/number_string_format/digits_section.rs +140 -0
  175. package/src/rust/components/style_controls/number_string_format/misc_section.rs +56 -0
  176. package/src/rust/components/style_controls/number_string_format/style_section.rs +69 -0
  177. package/src/rust/components/style_controls/number_string_format/types.rs +31 -0
  178. package/src/rust/components/style_controls/number_string_format.rs +259 -0
  179. package/src/rust/components/style_controls.rs +15 -0
  180. package/src/rust/components/type_icon.rs +53 -0
  181. package/src/rust/components/viewer.rs +668 -0
  182. package/src/rust/config/columns_config.rs +132 -0
  183. package/src/rust/config/datetime_column_style/color_mode.rs +62 -0
  184. package/src/rust/config/datetime_column_style/custom.rs +121 -0
  185. package/src/rust/config/datetime_column_style/custom_format.rs +90 -0
  186. package/src/rust/config/datetime_column_style/simple.rs +55 -0
  187. package/src/rust/config/datetime_column_style/simple_format.rs +86 -0
  188. package/src/rust/config/datetime_column_style.rs +104 -0
  189. package/src/rust/config/mod.rs +30 -0
  190. package/src/rust/config/number_column_style.rs +138 -0
  191. package/src/rust/config/number_string_format/enums.rs +298 -0
  192. package/src/rust/config/number_string_format.rs +269 -0
  193. package/src/rust/config/string_column_style.rs +140 -0
  194. package/src/rust/config/view_config.rs +24 -0
  195. package/src/rust/config/viewer_config.rs +337 -0
  196. package/src/rust/custom_elements/column_dropdown.rs +123 -0
  197. package/src/rust/custom_elements/copy_dropdown.rs +112 -0
  198. package/src/rust/custom_elements/debug_plugin.rs +114 -0
  199. package/src/rust/custom_elements/export_dropdown.rs +112 -0
  200. package/src/rust/custom_elements/filter_dropdown.rs +179 -0
  201. package/src/rust/custom_elements/function_dropdown.rs +115 -0
  202. package/src/rust/custom_elements/mod.rs +24 -0
  203. package/src/rust/custom_elements/modal.rs +395 -0
  204. package/src/rust/custom_elements/viewer.rs +880 -0
  205. package/src/rust/custom_events.rs +214 -0
  206. package/src/rust/dragdrop.rs +362 -0
  207. package/src/rust/exprtk/cursor.rs +81 -0
  208. package/src/rust/exprtk/mod.rs +17 -0
  209. package/src/rust/exprtk/tokenize/comment.rs +21 -0
  210. package/src/rust/exprtk/tokenize/number.rs +44 -0
  211. package/src/rust/exprtk/tokenize/string.rs +98 -0
  212. package/src/rust/exprtk/tokenize/symbol.rs +26 -0
  213. package/src/rust/exprtk/tokenize.rs +190 -0
  214. package/src/rust/js/clipboard.rs +77 -0
  215. package/src/rust/js/clipboard_item.rs +21 -0
  216. package/src/rust/js/intersection_observer.rs +32 -0
  217. package/src/rust/js/mimetype.rs +42 -0
  218. package/src/rust/js/mod.rs +29 -0
  219. package/src/rust/js/plugin.rs +167 -0
  220. package/src/rust/js/resize_observer.rs +37 -0
  221. package/src/rust/js/testing.rs +149 -0
  222. package/src/rust/lib.rs +116 -0
  223. package/src/rust/model/columns_iter_set.rs +340 -0
  224. package/src/rust/model/copy_export.rs +157 -0
  225. package/src/rust/model/create_col.rs +59 -0
  226. package/src/rust/model/edit_expression.rs +95 -0
  227. package/src/rust/model/export_app.rs +58 -0
  228. package/src/rust/model/export_method.rs +151 -0
  229. package/src/rust/model/get_viewer_config.rs +85 -0
  230. package/src/rust/model/intersection_observer.rs +81 -0
  231. package/src/rust/model/is_invalid_drop.rs +36 -0
  232. package/src/rust/model/mod.rs +93 -0
  233. package/src/rust/model/plugin_column_styles.rs +106 -0
  234. package/src/rust/model/resize_observer.rs +98 -0
  235. package/src/rust/model/restore_and_render.rs +113 -0
  236. package/src/rust/model/structural.rs +73 -0
  237. package/src/rust/model/update_and_render.rs +74 -0
  238. package/src/rust/presentation.rs +370 -0
  239. package/src/rust/renderer/activate.rs +49 -0
  240. package/src/rust/renderer/limits.rs +200 -0
  241. package/src/rust/renderer/plugin_store.rs +45 -0
  242. package/src/rust/renderer/registry.rs +135 -0
  243. package/src/rust/renderer/render_timer.rs +185 -0
  244. package/src/rust/renderer.rs +463 -0
  245. package/src/rust/session/column_defaults_update.rs +141 -0
  246. package/src/rust/session/drag_drop_update.rs +179 -0
  247. package/src/rust/session/metadata.rs +308 -0
  248. package/src/rust/session/replace_expression_update.rs +131 -0
  249. package/src/rust/session/view_subscription.rs +189 -0
  250. package/src/rust/session.rs +794 -0
  251. package/src/rust/utils/browser/blob.rs +49 -0
  252. package/src/rust/utils/browser/download.rs +26 -0
  253. package/src/rust/utils/browser/mod.rs +24 -0
  254. package/src/rust/utils/browser/request_animation_frame.rs +76 -0
  255. package/src/rust/utils/browser/selection.rs +79 -0
  256. package/src/rust/utils/browser/tests/debounce.rs +114 -0
  257. package/src/rust/utils/browser/tests/mod.rs +13 -0
  258. package/src/rust/utils/custom_element.rs +85 -0
  259. package/src/rust/utils/datetime.rs +49 -0
  260. package/src/rust/utils/debounce.rs +54 -0
  261. package/src/rust/utils/hooks/mod.rs +15 -0
  262. package/src/rust/utils/hooks/use_async_callback.rs +53 -0
  263. package/src/rust/utils/mod.rs +114 -0
  264. package/src/rust/utils/number_format.rs +48 -0
  265. package/src/rust/utils/pubsub.rs +222 -0
  266. package/src/rust/utils/scope.rs +54 -0
  267. package/src/rust/utils/tee.rs +88 -0
  268. package/src/rust/utils/tests/mod.rs +14 -0
  269. package/src/rust/utils/tests/pubsub.rs +95 -0
  270. package/src/rust/utils/tests/request_animation_frame.rs +42 -0
  271. package/src/rust/utils/wasm_abi.rs +61 -0
  272. package/src/rust/utils/weak_scope.rs +39 -0
  273. package/src/svg/align-scroll-icon.svg +7 -0
  274. package/src/svg/bg-pattern.png +0 -0
  275. package/src/svg/boolean-type.svg +3 -0
  276. package/src/svg/checkbox-checked-icon.svg +7 -0
  277. package/src/svg/checkbox-hover.svg +4 -0
  278. package/src/svg/checkbox-off.svg +4 -0
  279. package/src/svg/checkbox-on.svg +4 -0
  280. package/src/svg/checkbox-unchecked-icon.svg +3 -0
  281. package/src/svg/close-icon.svg +6 -0
  282. package/src/svg/column-settings-icon.svg +6 -0
  283. package/src/svg/datagrid-select-column.svg +15 -0
  284. package/src/svg/datagrid-select-region.svg +15 -0
  285. package/src/svg/datagrid-select-row.svg +13 -0
  286. package/src/svg/datagrid.svg +13 -0
  287. package/src/svg/date-type.svg +23 -0
  288. package/src/svg/downloading.gif +0 -0
  289. package/src/svg/drag-handle.svg +10 -0
  290. package/src/svg/drawer-bg-pattern-hidpi.png +0 -0
  291. package/src/svg/drawer-tab-hover.svg +8 -0
  292. package/src/svg/drawer-tab-invert-hover.svg +9 -0
  293. package/src/svg/drawer-tab-invert.svg +8 -0
  294. package/src/svg/drawer-tab.svg +7 -0
  295. package/src/svg/dropdown-selector-light.svg +3 -0
  296. package/src/svg/dropdown-selector.svg +3 -0
  297. package/src/svg/duplicate-icon.svg +4 -0
  298. package/src/svg/editable-icon.svg +5 -0
  299. package/src/svg/export-icon.svg +4 -0
  300. package/src/svg/expression.svg +10 -0
  301. package/src/svg/free-scroll-icon.svg +5 -0
  302. package/src/svg/inactive-mouseover.svg +4 -0
  303. package/src/svg/mega-menu-icons-candlestick.svg +38 -0
  304. package/src/svg/mega-menu-icons-datagrid.svg +38 -0
  305. package/src/svg/mega-menu-icons-heatmap.svg +60 -0
  306. package/src/svg/mega-menu-icons-map-scatter.svg +43 -0
  307. package/src/svg/mega-menu-icons-ohlc.svg +40 -0
  308. package/src/svg/mega-menu-icons-sunburst.svg +39 -0
  309. package/src/svg/mega-menu-icons-treemap.svg +44 -0
  310. package/src/svg/mega-menu-icons-x-bar.svg +36 -0
  311. package/src/svg/mega-menu-icons-x-y-line.svg +38 -0
  312. package/src/svg/mega-menu-icons-x-y-scatter.svg +72 -0
  313. package/src/svg/mega-menu-icons-y-area.svg +73 -0
  314. package/src/svg/mega-menu-icons-y-bar.svg +36 -0
  315. package/src/svg/mega-menu-icons-y-line.svg +36 -0
  316. package/src/svg/mega-menu-icons-y-scatter.svg +72 -0
  317. package/src/svg/number-type.svg +4 -0
  318. package/src/svg/radio-hover.svg +4 -0
  319. package/src/svg/radio-off.svg +3 -0
  320. package/src/svg/radio-on.svg +4 -0
  321. package/src/svg/read-only-icon.svg +6 -0
  322. package/src/svg/revert-icon.svg +4 -0
  323. package/src/svg/sort-abs-asc-icon.svg +3 -0
  324. package/src/svg/sort-abs-col-asc-icon.svg +3 -0
  325. package/src/svg/sort-abs-col-desc-icon.svg +3 -0
  326. package/src/svg/sort-abs-desc-icon.svg +3 -0
  327. package/src/svg/sort-asc-icon.svg +4 -0
  328. package/src/svg/sort-col-asc-icon.svg +4 -0
  329. package/src/svg/sort-col-desc-icon.svg +4 -0
  330. package/src/svg/sort-desc-icon.svg +4 -0
  331. package/src/svg/sort-none-icon.svg +3 -0
  332. package/src/svg/status_error.svg +70 -0
  333. package/src/svg/status_ok.svg +26 -0
  334. package/src/svg/string-type.svg +8 -0
  335. package/src/svg/theme-icon.svg +5 -0
  336. package/src/svg/updating.gif +0 -0
  337. package/src/themes/dracula.less +101 -0
  338. package/src/themes/gruvbox-dark.less +116 -0
  339. package/src/themes/gruvbox.less +152 -0
  340. package/src/themes/icons.less +130 -0
  341. package/src/themes/intl/de.less +102 -0
  342. package/src/themes/intl/es.less +102 -0
  343. package/src/themes/intl/fr.less +102 -0
  344. package/src/themes/intl/ja.less +102 -0
  345. package/src/themes/intl/pt.less +102 -0
  346. package/src/themes/intl/zh.less +102 -0
  347. package/src/themes/intl.less +102 -0
  348. package/src/themes/monokai.less +107 -0
  349. package/src/themes/pro-dark.less +147 -0
  350. package/src/themes/pro.less +186 -0
  351. package/src/themes/solarized-dark.less +78 -0
  352. package/src/themes/solarized.less +102 -0
  353. package/src/themes/themes.less +21 -0
  354. package/src/themes/vaporwave.less +145 -0
  355. package/src/themes/variables.less +24 -0
  356. package/src/ts/bootstrap.ts +26 -0
  357. package/src/ts/extensions.ts +124 -0
  358. package/src/ts/perspective-viewer.cdn.ts +19 -0
  359. package/src/ts/perspective-viewer.inline.ts +23 -0
  360. package/src/ts/perspective-viewer.ts +59 -0
  361. package/src/ts/plugin.ts +279 -0
  362. package/src/ts/ts-rs/Aggregate.ts +3 -0
  363. package/src/ts/ts-rs/ColumnConfigValues.ts +14 -0
  364. package/src/ts/ts-rs/CustomDatetimeFormat.ts +3 -0
  365. package/src/ts/ts-rs/CustomDatetimeStyleConfig.ts +5 -0
  366. package/src/ts/ts-rs/CustomNumberFormatConfig.ts +8 -0
  367. package/src/ts/ts-rs/DatetimeColorMode.ts +3 -0
  368. package/src/ts/ts-rs/DatetimeFormatType.ts +8 -0
  369. package/src/ts/ts-rs/Expressions.ts +3 -0
  370. package/src/ts/ts-rs/Filter.ts +4 -0
  371. package/src/ts/ts-rs/FilterReducer.ts +3 -0
  372. package/src/ts/ts-rs/FilterTerm.ts +4 -0
  373. package/src/ts/ts-rs/FormatMode.ts +3 -0
  374. package/src/ts/ts-rs/FormatUnit.ts +3 -0
  375. package/src/ts/ts-rs/NumberBackgroundMode.ts +3 -0
  376. package/src/ts/ts-rs/NumberForegroundMode.ts +3 -0
  377. package/src/ts/ts-rs/OnUpdateData.ts +8 -0
  378. package/src/ts/ts-rs/OptionalUpdate.ts +3 -0
  379. package/src/ts/ts-rs/PluginConfig.ts +4 -0
  380. package/src/ts/ts-rs/RoundingMode.ts +3 -0
  381. package/src/ts/ts-rs/RoundingPriority.ts +3 -0
  382. package/src/ts/ts-rs/Scalar.ts +7 -0
  383. package/src/ts/ts-rs/SignDisplay.ts +3 -0
  384. package/src/ts/ts-rs/SimpleDatetimeFormat.ts +3 -0
  385. package/src/ts/ts-rs/SimpleDatetimeStyleConfig.ts +4 -0
  386. package/src/ts/ts-rs/Sort.ts +4 -0
  387. package/src/ts/ts-rs/SortDir.ts +3 -0
  388. package/src/ts/ts-rs/StringColorMode.ts +3 -0
  389. package/src/ts/ts-rs/TrailingZeroDisplay.ts +3 -0
  390. package/src/ts/ts-rs/UseGrouping.ts +3 -0
  391. package/src/ts/ts-rs/ViewOnUpdateResp.ts +3 -0
  392. package/src/ts/ts-rs/ViewerConfigUpdate.ts +90 -0
  393. package/src/ts/ts-rs/serde_json/JsonValue.ts +3 -0
  394. package/tsconfig.json +15 -0
@@ -0,0 +1,214 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ use std::cell::RefCell;
14
+ use std::ops::Deref;
15
+ use std::rc::Rc;
16
+
17
+ use perspective_client::{ViewWindow, clone};
18
+ use perspective_js::json;
19
+ use wasm_bindgen::prelude::*;
20
+ use web_sys::*;
21
+ use yew::html::ImplicitClone;
22
+
23
+ use crate::config::*;
24
+ use crate::js::JsPerspectiveViewerPlugin;
25
+ use crate::model::*;
26
+ use crate::presentation::Presentation;
27
+ use crate::renderer::*;
28
+ use crate::session::Session;
29
+ use crate::utils::*;
30
+ use crate::*;
31
+
32
+ /// A collection of `Subscription` which should trigger an event on the
33
+ /// JavaScript Custom Element as a `CustomEvent`. There are no public methods
34
+ /// on `CustomElements`, but when it is `drop()` the Custom Element will no
35
+ /// longer dispatch events such as `"perspective-config-change"`.
36
+ #[derive(Clone)]
37
+ pub struct CustomEvents(Rc<(CustomEventsDataRc, [Subscription; 6])>);
38
+
39
+ impl ImplicitClone for CustomEvents {}
40
+ impl PartialEq for CustomEvents {
41
+ fn eq(&self, _: &Self) -> bool {
42
+ true
43
+ }
44
+ }
45
+
46
+ #[derive(Clone)]
47
+ struct CustomEventsDataRc(Rc<CustomEventsData>);
48
+
49
+ impl Deref for CustomEventsDataRc {
50
+ type Target = CustomEventsData;
51
+
52
+ fn deref(&self) -> &CustomEventsData {
53
+ &self.0
54
+ }
55
+ }
56
+
57
+ struct CustomEventsData {
58
+ elem: HtmlElement,
59
+ session: Session,
60
+ renderer: Renderer,
61
+ presentation: Presentation,
62
+ last_dispatched: RefCell<Option<ViewerConfig>>,
63
+ }
64
+
65
+ derive_model!(Renderer, Session, Presentation for CustomEventsData);
66
+
67
+ impl CustomEvents {
68
+ pub fn new(
69
+ elem: &HtmlElement,
70
+ session: &Session,
71
+ renderer: &Renderer,
72
+ presentation: &Presentation,
73
+ ) -> Self {
74
+ let data = CustomEventsDataRc(Rc::new(CustomEventsData {
75
+ elem: elem.clone(),
76
+ session: session.clone(),
77
+ renderer: renderer.clone(),
78
+ presentation: presentation.clone(),
79
+ last_dispatched: Default::default(),
80
+ }));
81
+
82
+ let theme_sub = presentation.theme_config_updated.add_listener({
83
+ clone!(data);
84
+ move |_| data.clone().dispatch_config_update()
85
+ });
86
+
87
+ let settings_sub = presentation.settings_open_changed.add_listener({
88
+ clone!(data);
89
+ move |open| {
90
+ data.dispatch_settings_open_changed(open);
91
+ data.clone().dispatch_config_update();
92
+ }
93
+ });
94
+
95
+ let column_settings_sub = presentation.column_settings_open_changed.add_listener({
96
+ clone!(data);
97
+ move |(open, column_name)| {
98
+ data.dispatch_column_settings_open_changed(open, column_name);
99
+ // column_settings is ethereal; do not change the config
100
+ }
101
+ });
102
+
103
+ let plugin_sub = renderer.plugin_changed.add_listener({
104
+ clone!(data);
105
+ move |plugin| {
106
+ data.dispatch_plugin_changed(&plugin);
107
+ data.clone().dispatch_config_update();
108
+ }
109
+ });
110
+
111
+ let view_sub = session.view_created.add_listener({
112
+ clone!(data);
113
+ move |_| data.clone().dispatch_config_update()
114
+ });
115
+
116
+ let title_sub = presentation.title_changed.add_listener({
117
+ clone!(data);
118
+ move |_| data.clone().dispatch_config_update()
119
+ });
120
+
121
+ Self(Rc::new((data, [
122
+ theme_sub,
123
+ settings_sub,
124
+ column_settings_sub,
125
+ plugin_sub,
126
+ view_sub,
127
+ title_sub,
128
+ ])))
129
+ }
130
+
131
+ pub fn dispatch_column_style_changed(&self, config: &JsValue) {
132
+ let event_init = web_sys::CustomEventInit::new();
133
+ event_init.set_detail(config);
134
+ let event = web_sys::CustomEvent::new_with_event_init_dict(
135
+ "perspective-column-style-change",
136
+ &event_init,
137
+ );
138
+ self.0.0.elem.dispatch_event(&event.unwrap()).unwrap();
139
+ self.0.0.clone().dispatch_config_update();
140
+ }
141
+
142
+ pub fn dispatch_select(&self, view_window: Option<&ViewWindow>) -> ApiResult<()> {
143
+ let event_init = web_sys::CustomEventInit::new();
144
+ event_init.set_detail(&serde_wasm_bindgen::to_value(&view_window)?);
145
+ let event =
146
+ web_sys::CustomEvent::new_with_event_init_dict("perspective-select", &event_init);
147
+
148
+ self.0.0.elem.dispatch_event(&event.unwrap()).unwrap();
149
+ self.0.0.clone().dispatch_config_update();
150
+ Ok(())
151
+ }
152
+ }
153
+
154
+ impl CustomEventsDataRc {
155
+ fn dispatch_settings_open_changed(&self, open: bool) {
156
+ let event_init = web_sys::CustomEventInit::new();
157
+ event_init.set_detail(&JsValue::from(open));
158
+ let event = web_sys::CustomEvent::new_with_event_init_dict(
159
+ "perspective-toggle-settings",
160
+ &event_init,
161
+ );
162
+
163
+ self.elem
164
+ .toggle_attribute_with_force("settings", open)
165
+ .unwrap();
166
+ self.elem.dispatch_event(&event.unwrap()).unwrap();
167
+ }
168
+
169
+ fn dispatch_column_settings_open_changed(&self, open: bool, column_name: Option<String>) {
170
+ let event_init = web_sys::CustomEventInit::new();
171
+ event_init.set_detail(&JsValue::from(
172
+ json!( {"open": open, "column_name": column_name} ),
173
+ ));
174
+ let event = web_sys::CustomEvent::new_with_event_init_dict(
175
+ "perspective-toggle-column-settings",
176
+ &event_init,
177
+ );
178
+
179
+ self.elem.dispatch_event(&event.unwrap()).unwrap();
180
+ }
181
+
182
+ fn dispatch_plugin_changed(&self, plugin: &JsPerspectiveViewerPlugin) {
183
+ let event_init = web_sys::CustomEventInit::new();
184
+ event_init.set_detail(plugin);
185
+ let event = web_sys::CustomEvent::new_with_event_init_dict(
186
+ "perspective-plugin-update",
187
+ &event_init,
188
+ );
189
+
190
+ self.elem.dispatch_event(&event.unwrap()).unwrap();
191
+ }
192
+
193
+ fn dispatch_config_update(self) {
194
+ ApiFuture::spawn(async move {
195
+ let viewer_config = self.get_viewer_config().await?;
196
+ if viewer_config.view_config != Default::default()
197
+ && Some(&viewer_config) != self.last_dispatched.borrow().as_ref()
198
+ {
199
+ let json_config = JsValue::from_serde_ext(&viewer_config)?;
200
+ let event_init = web_sys::CustomEventInit::new();
201
+ event_init.set_detail(&json_config);
202
+ let event = web_sys::CustomEvent::new_with_event_init_dict(
203
+ "perspective-config-update",
204
+ &event_init,
205
+ );
206
+
207
+ *self.last_dispatched.borrow_mut() = Some(viewer_config);
208
+ self.elem.dispatch_event(&event.unwrap()).unwrap();
209
+ }
210
+
211
+ Ok(())
212
+ });
213
+ }
214
+ }
@@ -0,0 +1,362 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ use std::cell::RefCell;
14
+ use std::ops::Deref;
15
+ use std::rc::Rc;
16
+
17
+ use perspective_client::clone;
18
+ use wasm_bindgen::prelude::*;
19
+ use web_sys::*;
20
+ use yew::html::ImplicitClone;
21
+ use yew::prelude::*;
22
+
23
+ use crate::utils::*;
24
+ use crate::*;
25
+
26
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
27
+ pub enum DragTarget {
28
+ Active,
29
+ GroupBy,
30
+ SplitBy,
31
+ Sort,
32
+ Filter,
33
+ }
34
+
35
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
36
+ pub enum DragEffect {
37
+ Copy,
38
+ Move(DragTarget),
39
+ }
40
+
41
+ #[derive(Clone, Debug)]
42
+ struct DragFrom {
43
+ column: String,
44
+ effect: DragEffect,
45
+ }
46
+
47
+ #[derive(Debug)]
48
+ struct DragOver {
49
+ target: DragTarget,
50
+ index: usize,
51
+ }
52
+
53
+ #[derive(Debug)]
54
+ enum DragState {
55
+ NoDrag,
56
+ DragInProgress(DragFrom),
57
+ DragOverInProgress(DragFrom, DragOver),
58
+ }
59
+
60
+ impl Default for DragState {
61
+ fn default() -> Self {
62
+ Self::NoDrag
63
+ }
64
+ }
65
+
66
+ impl DragState {
67
+ const fn is_drag_in_progress(&self) -> bool {
68
+ !matches!(self, Self::NoDrag)
69
+ }
70
+ }
71
+
72
+ #[derive(Default)]
73
+ pub struct DragDropState {
74
+ drag_state: RefCell<DragState>,
75
+ pub drop_received: PubSub<(String, DragTarget, DragEffect, usize)>,
76
+ pub dragstart_received: PubSub<DragEffect>,
77
+ pub dragend_received: PubSub<()>,
78
+ }
79
+
80
+ /// The `<perspective-viewer>` drag/drop service, which manages drag/drop user
81
+ /// interactions across components. It is a component-level service, since only
82
+ /// one drag/drop action can be executed by the user at a time.
83
+ #[derive(Clone, Default)]
84
+ pub struct DragDrop(Rc<DragDropState>);
85
+
86
+ impl Deref for DragDrop {
87
+ type Target = Rc<DragDropState>;
88
+
89
+ fn deref(&self) -> &Self::Target {
90
+ &self.0
91
+ }
92
+ }
93
+
94
+ impl PartialEq for DragDrop {
95
+ fn eq(&self, other: &Self) -> bool {
96
+ Rc::ptr_eq(&self.0, &other.0)
97
+ }
98
+ }
99
+
100
+ impl ImplicitClone for DragDrop {}
101
+
102
+ impl DragDrop {
103
+ /// Get the column name currently being drag/dropped.
104
+ pub fn get_drag_column(&self) -> Option<String> {
105
+ match *self.drag_state.borrow() {
106
+ DragState::DragInProgress(DragFrom { ref column, .. })
107
+ | DragState::DragOverInProgress(DragFrom { ref column, .. }, _) => Some(column.clone()),
108
+ _ => None,
109
+ }
110
+ }
111
+
112
+ pub fn get_drag_target(&self) -> Option<DragTarget> {
113
+ match *self.drag_state.borrow() {
114
+ DragState::DragInProgress(DragFrom {
115
+ effect: DragEffect::Move(target),
116
+ ..
117
+ })
118
+ | DragState::DragOverInProgress(
119
+ DragFrom {
120
+ effect: DragEffect::Move(target),
121
+ ..
122
+ },
123
+ _,
124
+ ) => Some(target),
125
+ _ => None,
126
+ }
127
+ }
128
+
129
+ pub fn set_drag_image(&self, event: &DragEvent) -> ApiResult<()> {
130
+ event.stop_propagation();
131
+ if let Some(dt) = event.data_transfer() {
132
+ dt.set_drop_effect("move");
133
+ dt.set_data("text/plain", "{}").unwrap();
134
+ }
135
+
136
+ let original: HtmlElement = event.target().into_apierror()?.unchecked_into();
137
+ let elem: HtmlElement = original
138
+ .children()
139
+ .get_with_index(0)
140
+ .unwrap()
141
+ .clone_node_with_deep(true)?
142
+ .unchecked_into();
143
+
144
+ elem.class_list().toggle("snap-drag-image")?;
145
+ original.append_child(&elem)?;
146
+ event.data_transfer().into_apierror()?.set_drag_image(
147
+ &elem,
148
+ event.offset_x(),
149
+ event.offset_y(),
150
+ );
151
+
152
+ ApiFuture::spawn(async move {
153
+ request_animation_frame().await;
154
+ original.remove_child(&elem)?;
155
+ Ok(())
156
+ });
157
+
158
+ Ok(())
159
+ }
160
+
161
+ // Is the drag/drop state currently in `action`?
162
+ pub fn is_dragover(&self, drag_target: DragTarget) -> Option<(usize, String)> {
163
+ match *self.drag_state.borrow() {
164
+ DragState::DragOverInProgress(
165
+ DragFrom { ref column, .. },
166
+ DragOver { target, index },
167
+ ) if target == drag_target => Some((index, column.clone())),
168
+ _ => None,
169
+ }
170
+ }
171
+
172
+ pub fn notify_drop(&self, event: &DragEvent) {
173
+ event.prevent_default();
174
+ event.stop_propagation();
175
+ let action = match &*self.drag_state.borrow() {
176
+ DragState::DragOverInProgress(
177
+ DragFrom { column, effect },
178
+ DragOver { target, index },
179
+ ) => Some((column.to_string(), *target, *effect, *index)),
180
+ _ => None,
181
+ };
182
+
183
+ *self.drag_state.borrow_mut() = DragState::NoDrag;
184
+ if let Some(action) = action {
185
+ self.drop_received.emit(action);
186
+ }
187
+ }
188
+
189
+ /// Start the drag/drop action with the name of the column being dragged.
190
+ pub fn notify_drag_start(&self, column: String, effect: DragEffect) {
191
+ *self.drag_state.borrow_mut() = DragState::DragInProgress(DragFrom { column, effect });
192
+ let emit = self.dragstart_received.callback();
193
+ ApiFuture::spawn(async move {
194
+ request_animation_frame().await;
195
+ emit.emit(effect);
196
+ Ok(())
197
+ });
198
+ }
199
+
200
+ /// End the drag/drop action by resetting the state to default.
201
+ pub fn notify_drag_end(&self) {
202
+ if self.drag_state.borrow().is_drag_in_progress() {
203
+ *self.drag_state.borrow_mut() = DragState::NoDrag;
204
+ let emit = self.dragend_received.callback();
205
+ emit.emit(());
206
+ }
207
+ }
208
+
209
+ /// Leave the `action` zone.
210
+ pub fn notify_drag_leave(&self, drag_target: DragTarget) {
211
+ let reset = match *self.drag_state.borrow() {
212
+ DragState::DragOverInProgress(
213
+ DragFrom { ref column, effect },
214
+ DragOver { target, .. },
215
+ ) if target == drag_target => Some((column.clone(), effect)),
216
+ _ => None,
217
+ };
218
+
219
+ if let Some((column, effect)) = reset {
220
+ self.notify_drag_start(column, effect);
221
+ }
222
+ }
223
+
224
+ // Enter the `action` zone at `index`, which must be <= the number of children
225
+ // in the container.
226
+ pub fn notify_drag_enter(&self, target: DragTarget, index: usize) -> bool {
227
+ let mut drag_state = self.drag_state.borrow_mut();
228
+ let should_render = match &*drag_state {
229
+ DragState::DragOverInProgress(_, drag_to) => {
230
+ drag_to.target != target || drag_to.index != index
231
+ },
232
+ _ => true,
233
+ };
234
+
235
+ *drag_state = match &*drag_state {
236
+ DragState::DragOverInProgress(drag_from, _) | DragState::DragInProgress(drag_from) => {
237
+ DragState::DragOverInProgress(drag_from.clone(), DragOver { target, index })
238
+ },
239
+ _ => DragState::NoDrag,
240
+ };
241
+
242
+ should_render
243
+ }
244
+ }
245
+
246
+ /// Safari does not set `relatedTarget` on `"dragleave"`, which makes it
247
+ /// impossible to determine whether a logical drag leave has happened with just
248
+ /// this event, so use function on `"dragenter"` to capture the `relatedTarget`.
249
+ pub fn dragenter_helper(callback: impl Fn() + 'static, target: NodeRef) -> Callback<DragEvent> {
250
+ Callback::from({
251
+ move |event: DragEvent| {
252
+ js_log_maybe!({
253
+ event.stop_propagation();
254
+ event.prevent_default();
255
+ if event.related_target().is_none() {
256
+ target
257
+ .cast::<HtmlElement>()
258
+ .into_apierror()?
259
+ .dataset()
260
+ .set("safaridragleave", "true")?;
261
+ }
262
+ });
263
+
264
+ callback();
265
+ }
266
+ })
267
+ }
268
+
269
+ /// HTML drag/drop will fire a bubbling `dragleave` event over all children of a
270
+ /// `dragleave`-listened-to element, so we need to filter out the events from
271
+ /// the children elements with this esoteric DOM arcana.
272
+ pub fn dragleave_helper(callback: impl Fn() + 'static, drag_ref: NodeRef) -> Callback<DragEvent> {
273
+ Callback::from({
274
+ clone!(drag_ref);
275
+ move |event: DragEvent| {
276
+ js_log_maybe!({
277
+ event.stop_propagation();
278
+ event.prevent_default();
279
+
280
+ let mut related_target = event
281
+ .related_target()
282
+ .or_else(|| Some(JsValue::UNDEFINED.unchecked_into::<EventTarget>()))
283
+ .and_then(|x| x.dyn_into::<Element>().ok());
284
+
285
+ // This is a wild chrome bug. `dragleave` can fire with the `relatedTarget`
286
+ // property set to an element inside the closed `ShadowRoot` hosted by a
287
+ // browser-native `<select>` tag, which fails the `.contains()` check
288
+ // below. This mystery `ShadowRoot` has a structure that looks like this
289
+ // (tested in Chrome 92), which we try to detect as best we can below.
290
+ //
291
+ // ```html
292
+ // <div aria-hidden="true">Selected Text Here</siv>
293
+ // <slot name="user-agent-custom-assign-slot"></slot>
294
+ // ```
295
+ //
296
+ // This is pretty course though, since there is no guarantee this structure
297
+ // will be maintained in future Chrome versions; the `.expect()` in this
298
+ // method chain should at least warn us if this regresses.
299
+ //
300
+ // Wait - you don't believe me? Throw a debugger statement inside this
301
+ // conditional and drag a column over a pivot-mode active columns list.
302
+ if related_target
303
+ .as_ref()
304
+ .map(|x| x.has_attribute("aria-hidden"))
305
+ .unwrap_or_default()
306
+ {
307
+ related_target = Some(
308
+ related_target
309
+ .into_apierror()?
310
+ .parent_node()
311
+ .into_apierror()?
312
+ .dyn_ref::<ShadowRoot>()
313
+ .ok_or_else(|| JsValue::from("Chrome drag/drop bug detection failed"))?
314
+ .host()
315
+ .unchecked_into::<Element>(),
316
+ )
317
+ }
318
+
319
+ let current_target = drag_ref.cast::<HtmlElement>().unwrap();
320
+ match related_target {
321
+ Some(ref related) => {
322
+ // Due to virtual dom these events sometimes fire after
323
+ // the node is removed ...
324
+ if !current_target.contains(Some(related))
325
+ && related.parent_element().is_some()
326
+ {
327
+ callback();
328
+ }
329
+ },
330
+ None => {
331
+ // Safari (OSX and iOS) don't set `relatedTarget`, so we need to
332
+ // read a memoized value from the `"dragenter"` event.
333
+ let dataset = current_target.dataset();
334
+ if dataset.get("safaridragleave").is_some() {
335
+ dataset.delete("safaridragleave");
336
+ } else {
337
+ callback();
338
+ }
339
+ },
340
+ };
341
+ })
342
+ }
343
+ })
344
+ }
345
+
346
+ #[derive(Clone)]
347
+ pub struct DragDropContainer {
348
+ pub noderef: NodeRef,
349
+ pub dragenter: Callback<DragEvent>,
350
+ pub dragleave: Callback<DragEvent>,
351
+ }
352
+
353
+ impl DragDropContainer {
354
+ pub fn new<F: Fn() + 'static, G: Fn() + 'static>(ondragenter: F, ondragleave: G) -> Self {
355
+ let noderef = NodeRef::default();
356
+ Self {
357
+ dragenter: dragenter_helper(ondragenter, noderef.clone()),
358
+ dragleave: dragleave_helper(ondragleave, noderef.clone()),
359
+ noderef,
360
+ }
361
+ }
362
+ }
@@ -0,0 +1,81 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ use perspective_client::ExprValidationError;
14
+ use yew::prelude::*;
15
+
16
+ /// A tokenizer cursor for ExprTK parsing.
17
+ ///
18
+ /// Because ExprTK reports errors in column/row coordinates and visually needs
19
+ /// to be applied to an entire token rather than a single character, we need
20
+ /// fairly obnoxious counter logic to figure out how to generate the resulting
21
+ /// syntax-highlighted HTML. The `Counter<'a>` struct encpsulates this logic,
22
+ /// generating a `NodeRef` to any autocomplete-able `<span>` tokens, as well
23
+ /// as other convenient data for HTML rendering, and can be called incrementally
24
+ /// while iterating tokens after parsing.
25
+ pub struct Cursor<'a> {
26
+ row: u32,
27
+ col: u32,
28
+ index: u32,
29
+ pub err: &'a Option<ExprValidationError>,
30
+ pub txt: &'a str,
31
+ pub noderef: NodeRef,
32
+ pub auto: Option<String>,
33
+ }
34
+
35
+ impl<'a> Cursor<'a> {
36
+ pub fn new(err: &'a Option<ExprValidationError>) -> Self {
37
+ Self {
38
+ row: 1,
39
+ col: 0,
40
+ index: 0,
41
+ err,
42
+ txt: "",
43
+ auto: None,
44
+ noderef: NodeRef::default(),
45
+ }
46
+ }
47
+
48
+ /// Is the cursor currently overlapping a token with an error?
49
+ pub const fn is_error(&self) -> bool {
50
+ if let Some(err) = &self.err {
51
+ err.line + 1 == self.row
52
+ && err.column >= self.col
53
+ && err.column < (self.col + self.txt.len() as u32)
54
+ } else {
55
+ false
56
+ }
57
+ }
58
+
59
+ /// Is the cursor currently overlapping an autocomplete-able token?
60
+ pub const fn is_autocomplete(&self, position: u32) -> bool {
61
+ position > self.index && position <= self.index + self.txt.len() as u32
62
+ }
63
+
64
+ /// TODO this is alot of type backage for what could just be `num_rows()`.
65
+ pub fn map_rows<T, F: Fn(u32) -> T>(self, f: F) -> impl Iterator<Item = T> {
66
+ (0..self.row).map(f)
67
+ }
68
+
69
+ /// Increment the counter column by `size` characters.
70
+ pub fn increment_column(&mut self, size: u32) {
71
+ self.col += size;
72
+ self.index += size;
73
+ }
74
+
75
+ /// Increment to the next line, typewriter-style.
76
+ pub fn increment_line(&mut self) {
77
+ self.row += 1;
78
+ self.col = 0;
79
+ self.index += 1;
80
+ }
81
+ }
@@ -0,0 +1,17 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ mod cursor;
14
+ mod tokenize;
15
+
16
+ pub use cursor::*;
17
+ pub use tokenize::*;