@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,231 @@
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
+ pub mod stub;
14
+ mod symbol;
15
+
16
+ use itertools::Itertools;
17
+ use perspective_client::clone;
18
+ use perspective_client::config::ColumnType;
19
+ use perspective_js::utils::*;
20
+ use yew::{Callback, Html, Properties, function_component, html};
21
+
22
+ use crate::components::column_settings_sidebar::style_tab::stub::Stub;
23
+ use crate::components::column_settings_sidebar::style_tab::symbol::SymbolStyle;
24
+ use crate::components::datetime_column_style::DatetimeColumnStyle;
25
+ use crate::components::form::number_field::NumberField;
26
+ use crate::components::number_column_style::NumberColumnStyle;
27
+ use crate::components::string_column_style::StringColumnStyle;
28
+ use crate::components::style_controls::CustomNumberFormat;
29
+ use crate::config::ColumnConfigValueUpdate;
30
+ use crate::custom_events::CustomEvents;
31
+ use crate::derive_model;
32
+ use crate::model::PluginColumnStyles;
33
+ use crate::presentation::Presentation;
34
+ use crate::renderer::Renderer;
35
+ use crate::session::Session;
36
+
37
+ #[derive(Clone, PartialEq, Properties)]
38
+ pub struct StyleTabProps {
39
+ pub custom_events: CustomEvents,
40
+ pub session: Session,
41
+ pub renderer: Renderer,
42
+ pub presentation: Presentation,
43
+
44
+ pub ty: Option<ColumnType>,
45
+ pub column_name: String,
46
+ pub group_by_depth: u32,
47
+ }
48
+ derive_model!(Session, Renderer, Presentation for StyleTabProps);
49
+
50
+ impl StyleTabProps {
51
+ fn send_plugin_config(&self, update: ColumnConfigValueUpdate) {
52
+ clone!(props = self);
53
+ ApiFuture::spawn(async move {
54
+ props
55
+ .presentation
56
+ .update_columns_config_value(props.column_name.clone(), update);
57
+ let columns_configs = props.presentation.all_columns_configs();
58
+ let plugin_config = props.renderer.get_active_plugin()?.save()?;
59
+ props
60
+ .renderer
61
+ .get_active_plugin()?
62
+ .restore(&plugin_config, Some(&columns_configs))?;
63
+
64
+ props.renderer.update(&props.session).await?;
65
+ let detail = serde_wasm_bindgen::to_value(&columns_configs).unwrap();
66
+ props.custom_events.dispatch_column_style_changed(&detail);
67
+ Ok(())
68
+ })
69
+ }
70
+ }
71
+
72
+ #[function_component]
73
+ pub fn StyleTab(props: &StyleTabProps) -> Html {
74
+ let on_change = yew::use_callback(props.clone(), |config, props| {
75
+ props.send_plugin_config(config);
76
+ });
77
+
78
+ let config = props.presentation.get_columns_config(&props.column_name);
79
+ let components = props
80
+ .get_column_style_control_options(&props.column_name)
81
+ .map(|opts| {
82
+ let mut components = vec![];
83
+
84
+ if !props.session.get_view_config().group_by.is_empty() {
85
+ let aggregate_depth = config.as_ref().map(|x| x.aggregate_depth as f64);
86
+ components.push(("Aggregate Depth", html! {
87
+ <AggregateDepthSelector
88
+ group_by_depth={props.group_by_depth}
89
+ on_change={on_change.clone()}
90
+ column_name={props.column_name.to_owned()}
91
+ value={aggregate_depth.unwrap_or_default() as u32}
92
+ />
93
+ }));
94
+ }
95
+
96
+ if let Some(default_config) = opts.datagrid_number_style {
97
+ let config = config
98
+ .as_ref()
99
+ .map(|config| config.datagrid_number_style.clone());
100
+
101
+ components.push(("Number Styles", html! {
102
+ <NumberColumnStyle
103
+ session={props.session.clone()}
104
+ column_name={props.column_name.clone()}
105
+ {config}
106
+ {default_config}
107
+ on_change={on_change.clone()}
108
+ />
109
+ }));
110
+ }
111
+ if let Some(default_config) = opts.datagrid_string_style {
112
+ let config = config
113
+ .as_ref()
114
+ .map(|config| config.datagrid_string_style.clone());
115
+
116
+ components.push(("String Styles", html! {
117
+ <StringColumnStyle {config} {default_config} on_change={on_change.clone()} />
118
+ }));
119
+ }
120
+
121
+ if let Some(default_config) = opts.datagrid_datetime_style {
122
+ let config = config
123
+ .as_ref()
124
+ .map(|config| config.datagrid_datetime_style.clone());
125
+
126
+ let enable_time_config = props.ty.unwrap() == ColumnType::Datetime;
127
+ components.push(("Datetime Styles", html! {
128
+ <DatetimeColumnStyle
129
+ {enable_time_config}
130
+ {config}
131
+ {default_config}
132
+ on_change={on_change.clone()}
133
+ />
134
+ }))
135
+ }
136
+
137
+ if let Some(default_config) = opts.symbols {
138
+ let restored_config = config
139
+ .as_ref()
140
+ .map(|config| config.symbols.clone())
141
+ .unwrap_or_default();
142
+
143
+ components.push(("Symbols", html! {
144
+ <SymbolStyle
145
+ {default_config}
146
+ {restored_config}
147
+ on_change={on_change.clone()}
148
+ column_name={props.column_name.clone()}
149
+ session={props.session.clone()}
150
+ />
151
+ }))
152
+ }
153
+
154
+ if opts.number_string_format.unwrap_or_default() {
155
+ let restored_config = config
156
+ .as_ref()
157
+ .and_then(|config| config.number_format.clone())
158
+ .unwrap_or_default();
159
+
160
+ components.push(("Number Formatting", html! {
161
+ <CustomNumberFormat
162
+ {restored_config}
163
+ on_change={on_change.clone()}
164
+ view_type={props.ty.unwrap()}
165
+ column_name={props.column_name.clone()}
166
+ />
167
+ }));
168
+ }
169
+
170
+ components
171
+ .into_iter()
172
+ .map(|(_title, component)| {
173
+ html! {
174
+ <fieldset class="style-control">
175
+ // <legend >{ title }</legend>
176
+ { component }
177
+ </fieldset>
178
+ }
179
+ })
180
+ .collect_vec()
181
+ })
182
+ .unwrap_or_else(|error| {
183
+ vec![html! {
184
+ <Stub message="Could not render column styles" error={Some(format!("{error:?}"))} />
185
+ }]
186
+ });
187
+
188
+ html! {
189
+ <div id="style-tab">
190
+ <div id="column-style-container" class="tab-section">{ components }</div>
191
+ </div>
192
+ }
193
+ }
194
+
195
+ #[derive(Properties, PartialEq)]
196
+ pub struct AggregateDepthSelectorProps {
197
+ pub on_change: Callback<ColumnConfigValueUpdate>,
198
+ pub value: u32,
199
+ pub group_by_depth: u32,
200
+ pub column_name: String,
201
+ }
202
+
203
+ #[function_component]
204
+ fn AggregateDepthSelector(props: &AggregateDepthSelectorProps) -> Html {
205
+ let state = yew::use_state_eq(|| 0);
206
+ yew::use_effect_with((props.column_name.to_owned(), props.group_by_depth), {
207
+ clone!(state, props.value);
208
+ move |deps| state.set(std::cmp::min(deps.1, value))
209
+ });
210
+
211
+ let on_change = yew::use_callback(
212
+ (state.setter(), props.on_change.clone()),
213
+ |x: Option<f64>, deps| {
214
+ deps.0.set(x.unwrap_or_default() as u32);
215
+ deps.1.emit(ColumnConfigValueUpdate::AggregateDepth(
216
+ x.unwrap_or_default() as u32,
217
+ ))
218
+ },
219
+ );
220
+
221
+ html! {
222
+ <NumberField
223
+ label="aggregate-depth"
224
+ {on_change}
225
+ min=0.0
226
+ max={props.group_by_depth as f64}
227
+ default=0.0
228
+ current_value={*state as f64}
229
+ />
230
+ }
231
+ }
@@ -0,0 +1,325 @@
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::collections::HashSet;
14
+ use std::marker::PhantomData;
15
+
16
+ use derivative::Derivative;
17
+ use web_sys::*;
18
+ use yew::html::Scope;
19
+ use yew::prelude::*;
20
+
21
+ use crate::components::column_selector::{EmptyColumn, InPlaceColumn, InvalidColumn};
22
+ use crate::custom_elements::ColumnDropDownElement;
23
+ use crate::dragdrop::*;
24
+
25
+ /// Must be implemented by `Properties` of children of `DragDropList`, returning
26
+ /// the value a DragDropItem represents.
27
+ pub trait DragDropListItemProps: Properties {
28
+ type Item: Clone + PartialEq;
29
+ fn get_item(&self) -> Self::Item;
30
+ }
31
+
32
+ pub trait DragContext<T> {
33
+ fn close(index: usize) -> T;
34
+ fn dragleave() -> T;
35
+ fn dragenter(index: usize) -> T;
36
+ fn create(col: InPlaceColumn) -> T;
37
+ fn is_self_move(effect: DragTarget) -> bool;
38
+ }
39
+
40
+ #[derive(Properties, Derivative)]
41
+ #[derivative(Clone(bound = ""))]
42
+ pub struct DragDropListProps<T, U>
43
+ where
44
+ T: Component,
45
+ U: Component,
46
+ <U as Component>::Properties: DragDropListItemProps,
47
+ {
48
+ pub parent: Scope<T>,
49
+ pub dragdrop: DragDrop,
50
+ pub name: &'static str,
51
+ pub column_dropdown: ColumnDropDownElement,
52
+ pub exclude: HashSet<String>,
53
+ pub children: ChildrenWithProps<U>,
54
+
55
+ #[prop_or_default]
56
+ pub is_dragover: Option<(
57
+ usize,
58
+ <<U as Component>::Properties as DragDropListItemProps>::Item,
59
+ )>,
60
+
61
+ #[prop_or_default]
62
+ pub allow_duplicates: bool,
63
+ }
64
+
65
+ impl<T, U> PartialEq for DragDropListProps<T, U>
66
+ where
67
+ T: Component,
68
+ U: Component,
69
+ <U as Component>::Properties: DragDropListItemProps,
70
+ {
71
+ fn eq(&self, other: &Self) -> bool {
72
+ self.name == other.name
73
+ && self.children == other.children
74
+ && self.allow_duplicates == other.allow_duplicates
75
+ && self.is_dragover == other.is_dragover
76
+ }
77
+ }
78
+
79
+ pub enum DragDropListMsg {
80
+ Freeze(bool),
81
+ }
82
+
83
+ /// A sub-selector for a list-like component of a `JsViewConfig`, such as
84
+ /// `filters` and `sort`.
85
+ ///
86
+ /// `DragDropList` is parameterized by two `Component`
87
+ /// types, the parent component `T` and the inner item compnent `U`, which must
88
+ /// additionally implement `DragDropListItemProps` trait on its own `Properties`
89
+ /// associated type.
90
+ ///
91
+ /// Before you ask: yes, `frozen_size` needs to be a float64 since `flex`
92
+ /// containers can have fractional dimensions.
93
+ pub struct DragDropList<T, U, V>
94
+ where
95
+ T: Component,
96
+ U: Component,
97
+ <U as Component>::Properties: DragDropListItemProps,
98
+ V: DragContext<T::Message> + 'static,
99
+ {
100
+ parent_type: PhantomData<T>,
101
+ item_type: PhantomData<U>,
102
+ draggable_type: PhantomData<V>,
103
+ elem: NodeRef,
104
+ frozen_size: Option<f64>,
105
+ }
106
+
107
+ impl<T, U, V> Component for DragDropList<T, U, V>
108
+ where
109
+ T: Component,
110
+ U: Component,
111
+ <U as Component>::Properties: DragDropListItemProps,
112
+ V: DragContext<T::Message> + 'static,
113
+ {
114
+ type Message = DragDropListMsg;
115
+ type Properties = DragDropListProps<T, U>;
116
+
117
+ fn create(_ctx: &Context<Self>) -> Self {
118
+ Self {
119
+ parent_type: PhantomData,
120
+ item_type: PhantomData,
121
+ draggable_type: PhantomData,
122
+ elem: NodeRef::default(),
123
+ frozen_size: None,
124
+ }
125
+ }
126
+
127
+ fn changed(&mut self, _ctx: &Context<Self>, _old: &Self::Properties) -> bool {
128
+ true
129
+ }
130
+
131
+ fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
132
+ match msg {
133
+ // When a dragover occurs and a new Column is inserted into the selector,
134
+ // the geometry of the selector may expand and cause a parent reflow,
135
+ // which annoyingly changes the drag status and glitchiness occurs.
136
+ // By using `Freeze` when a dragenter occurs, the element's width will be
137
+ // frozen until `drop` or `dragleave`.
138
+ DragDropListMsg::Freeze(freeze) => {
139
+ if freeze && self.frozen_size.is_none() {
140
+ let elem = self.elem.cast::<HtmlElement>().unwrap();
141
+ self.frozen_size = Some({
142
+ // `offset_width` and family are `i32`, but Chrome _really_
143
+ // uses fractional pixel widths for these which can only be
144
+ // recovered by parsing the generated stylesheet ...
145
+ let txt = window()
146
+ .unwrap()
147
+ .get_computed_style(&elem)
148
+ .unwrap()
149
+ .unwrap()
150
+ .get_property_value("width")
151
+ .unwrap();
152
+
153
+ // Strip "px" suffix, e.g. "24.876px".
154
+ let px = &txt[..txt.len() - 2];
155
+ px.parse::<f64>().unwrap()
156
+ });
157
+ true
158
+ } else if !freeze {
159
+ // Don't render because the invoker will do so through `dragdrop`.
160
+ self.frozen_size = None;
161
+ false
162
+ } else {
163
+ false
164
+ }
165
+ },
166
+ }
167
+ }
168
+
169
+ fn view(&self, ctx: &Context<Self>) -> Html {
170
+ let dragover = Callback::from(|_event: DragEvent| _event.prevent_default());
171
+
172
+ // On dragleave, signal the parent but no need to redraw as parent will call
173
+ // `change()` when resetting props.
174
+ let drag_container = DragDropContainer::new(
175
+ {
176
+ let total = ctx.props().children.len();
177
+ let parent = ctx.props().parent.clone();
178
+ let link = ctx.link().clone();
179
+ move || {
180
+ link.send_message(DragDropListMsg::Freeze(true));
181
+ parent.send_message(V::dragenter(total))
182
+ }
183
+ },
184
+ {
185
+ let parent = ctx.props().parent.clone();
186
+ let link = ctx.link().clone();
187
+ move || {
188
+ link.send_message(DragDropListMsg::Freeze(false));
189
+ parent.send_message(V::dragleave())
190
+ }
191
+ },
192
+ );
193
+
194
+ let drop = Callback::from({
195
+ let dragdrop = ctx.props().dragdrop.clone();
196
+ let link = ctx.link().clone();
197
+ move |event| {
198
+ link.send_message(DragDropListMsg::Freeze(false));
199
+ dragdrop.notify_drop(&event);
200
+ }
201
+ });
202
+
203
+ let invalid_drag: bool;
204
+ let mut valid_duplicate_drag = false;
205
+
206
+ let columns_html = {
207
+ let mut columns = ctx
208
+ .props()
209
+ .children
210
+ .iter()
211
+ .map(|x| (true, Some(x)))
212
+ .enumerate()
213
+ .collect::<Vec<_>>();
214
+
215
+ invalid_drag = if let Some((x, column)) = &ctx.props().is_dragover {
216
+ let index = *x;
217
+ let is_append = index == columns.len();
218
+ let is_self_move = ctx
219
+ .props()
220
+ .dragdrop
221
+ .get_drag_target()
222
+ .map(|x| V::is_self_move(x))
223
+ .unwrap_or_default();
224
+
225
+ let is_duplicate = columns
226
+ .iter()
227
+ .position(|x| x.1.1.as_ref().unwrap().props.get_item() == *column);
228
+
229
+ valid_duplicate_drag = is_duplicate.is_some() && !ctx.props().allow_duplicates;
230
+ if let Some(duplicate) = is_duplicate
231
+ && !is_append
232
+ && (!ctx.props().allow_duplicates || is_self_move)
233
+ {
234
+ columns.remove(duplicate);
235
+ }
236
+
237
+ // If inserting into the middle of the list, use
238
+ // the length of the existing element to prevent
239
+ // jitter as the underlying dragover zone moves.
240
+ if index < columns.len() {
241
+ columns.insert(index, (usize::MAX, (false, None)));
242
+ false
243
+ } else if (!is_append && !ctx.props().allow_duplicates)
244
+ || ((!is_append || !is_self_move)
245
+ && (is_duplicate.is_none() || ctx.props().allow_duplicates))
246
+ {
247
+ columns.push((usize::MAX, (false, None)));
248
+ false
249
+ } else {
250
+ true
251
+ }
252
+ } else {
253
+ false
254
+ };
255
+
256
+ columns
257
+ .into_iter()
258
+ .enumerate()
259
+ .map(|(idx, column)| {
260
+ let close = ctx.props().parent.callback(move |_| V::close(idx));
261
+ let dragenter = ctx.props().parent.callback({
262
+ let link = ctx.link().clone();
263
+ move |event: DragEvent| {
264
+ event.stop_propagation();
265
+ event.prevent_default();
266
+ link.send_message(DragDropListMsg::Freeze(true));
267
+ V::dragenter(idx)
268
+ }
269
+ });
270
+
271
+ if let (key, (true, Some(column))) = column {
272
+ html! {
273
+ <div {key} class="pivot-column" ondragenter={dragenter}>
274
+ { Html::from(column) }
275
+ <span class="row_close" onmousedown={close} />
276
+ </div>
277
+ }
278
+ } else if let (key, (_, Some(column))) = column {
279
+ html! {
280
+ <div {key} class="pivot-column" ondragenter={dragenter}>
281
+ { Html::from(column) }
282
+ <span class="row_close" style="opacity: 0.3" />
283
+ </div>
284
+ }
285
+ } else {
286
+ let (key, _) = column;
287
+ html! {
288
+ <div {key} class="pivot-column" ondragenter={dragenter}>
289
+ <div class="config-drop" />
290
+ </div>
291
+ }
292
+ }
293
+ })
294
+ .collect::<Html>()
295
+ };
296
+
297
+ let column_dropdown = ctx.props().column_dropdown.clone();
298
+ let exclude = ctx.props().exclude.clone();
299
+ let on_select = ctx.props().parent.callback(V::create);
300
+ html! {
301
+ <div ref={&self.elem} class="rrow">
302
+ <div
303
+ id={ctx.props().name}
304
+ ondragover={dragover}
305
+ ondragenter={drag_container.dragenter}
306
+ ondragleave={drag_container.dragleave}
307
+ ref={drag_container.noderef}
308
+ ondrop={drop}
309
+ >
310
+ <div class="psp-text-field">
311
+ <ul class="psp-text-field__input" for={ctx.props().name}>
312
+ { columns_html }
313
+ if ctx.props().is_dragover.is_none() | (!invalid_drag && valid_duplicate_drag) {
314
+ <EmptyColumn {column_dropdown} {exclude} {on_select} />
315
+ } else if invalid_drag {
316
+ <InvalidColumn />
317
+ }
318
+ </ul>
319
+ <label class="pivot-selector-label" for={ctx.props().name} />
320
+ </div>
321
+ </div>
322
+ </div>
323
+ }
324
+ }
325
+ }
@@ -0,0 +1,104 @@
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::marker::PhantomData;
14
+ use std::rc::Rc;
15
+
16
+ use web_sys::*;
17
+ use yew::prelude::*;
18
+
19
+ use super::select::SelectItem;
20
+ use crate::components::style::LocalStyle;
21
+ use crate::*;
22
+
23
+ pub type DropDownMenuItem<T> = SelectItem<T>;
24
+
25
+ pub type DropDownMenuMsg = ();
26
+
27
+ #[derive(Properties, PartialEq)]
28
+ pub struct DropDownMenuProps<T>
29
+ where
30
+ T: Into<Html> + Clone + PartialEq + 'static,
31
+ {
32
+ pub values: Rc<Vec<DropDownMenuItem<T>>>,
33
+ pub callback: Callback<T>,
34
+ }
35
+
36
+ pub struct DropDownMenu<T>
37
+ where
38
+ T: Into<Html> + Clone + PartialEq + 'static,
39
+ {
40
+ _props: PhantomData<T>,
41
+ }
42
+
43
+ impl<T> Component for DropDownMenu<T>
44
+ where
45
+ T: Into<Html> + Clone + PartialEq + 'static,
46
+ {
47
+ type Message = DropDownMenuMsg;
48
+ type Properties = DropDownMenuProps<T>;
49
+
50
+ fn create(_ctx: &Context<Self>) -> Self {
51
+ Self {
52
+ _props: Default::default(),
53
+ }
54
+ }
55
+
56
+ fn update(&mut self, _ctx: &Context<Self>, _msg: Self::Message) -> bool {
57
+ false
58
+ }
59
+
60
+ fn view(&self, ctx: &Context<Self>) -> Html {
61
+ let values = &ctx.props().values;
62
+ let body = if !values.is_empty() {
63
+ values
64
+ .iter()
65
+ .map(|value| match value {
66
+ DropDownMenuItem::Option(x) => {
67
+ let click = ctx.props().callback.reform({
68
+ let value = x.clone();
69
+ move |_: MouseEvent| value.clone()
70
+ });
71
+
72
+ html! {
73
+ <span onmousedown={click} class="selected">{ x.clone().into() }</span>
74
+ }
75
+ },
76
+ DropDownMenuItem::OptGroup(name, xs) => {
77
+ html! {
78
+ <>
79
+ <span class="dropdown-group-label">{ name }</span>
80
+ <div class="dropdown-group-container">
81
+ { xs.iter().map(|x| {
82
+ let click = ctx.props().callback.reform({
83
+ let value = x.clone();
84
+ move |_: MouseEvent| value.clone()
85
+ });
86
+ html! {
87
+ <span onmousedown={ click }>
88
+ { x.clone().into() }
89
+ </span>
90
+ }
91
+ }).collect::<Html>() }
92
+ </div>
93
+ </>
94
+ }
95
+ },
96
+ })
97
+ .collect::<Html>()
98
+ } else {
99
+ html! { <span class="no-results">{ "No Completions" }</span> }
100
+ };
101
+
102
+ html! { <><LocalStyle href={css!("containers/dropdown-menu")} />{ body }</> }
103
+ }
104
+ }