@perspective-dev/viewer 4.3.0 → 4.4.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 (227) hide show
  1. package/dist/cdn/perspective-viewer.js +2 -2
  2. package/dist/cdn/perspective-viewer.js.map +4 -4
  3. package/dist/css/botanical.css +1 -1
  4. package/dist/css/dracula.css +1 -1
  5. package/dist/css/gruvbox-dark.css +1 -1
  6. package/dist/css/gruvbox.css +1 -1
  7. package/dist/css/icons.css +1 -1
  8. package/dist/css/intl/de.css +1 -1
  9. package/dist/css/intl/es.css +1 -1
  10. package/dist/css/intl/fr.css +1 -1
  11. package/dist/css/intl/ja.css +1 -1
  12. package/dist/css/intl/pt.css +1 -1
  13. package/dist/css/intl/zh.css +1 -1
  14. package/dist/css/intl.css +1 -1
  15. package/dist/css/monokai.css +1 -1
  16. package/dist/css/pro-dark.css +1 -1
  17. package/dist/css/pro.css +1 -1
  18. package/dist/css/solarized-dark.css +1 -1
  19. package/dist/css/solarized.css +1 -1
  20. package/dist/css/themes.css +1 -1
  21. package/dist/css/vaporwave.css +1 -1
  22. package/dist/esm/perspective-viewer.inline.js +2 -2
  23. package/dist/esm/perspective-viewer.inline.js.map +4 -4
  24. package/dist/esm/perspective-viewer.js +2 -2
  25. package/dist/esm/perspective-viewer.js.map +4 -4
  26. package/dist/wasm/perspective-viewer.d.ts +57 -53
  27. package/dist/wasm/perspective-viewer.js +190 -165
  28. package/dist/wasm/perspective-viewer.wasm +0 -0
  29. package/dist/wasm/perspective-viewer.wasm.d.ts +17 -18
  30. package/package.json +7 -5
  31. package/src/{less/aggregate-selector.less → css/aggregate-selector.css} +23 -20
  32. package/src/css/column-dropdown.css +109 -0
  33. package/src/{less/column-selector.less → css/column-selector.css} +160 -158
  34. package/src/{less/column-settings-panel.less → css/column-settings-panel.css} +69 -59
  35. package/src/{less/column-style.less → css/column-style.css} +52 -66
  36. package/src/{less/column-symbol-attributes.less → css/column-symbol-attributes.css} +15 -14
  37. package/src/{less/config-selector.less → css/config-selector.css} +151 -135
  38. package/src/{less/containers/dropdown-menu.less → css/containers/dropdown-menu.css} +20 -19
  39. package/src/{less/containers/pairs-list.less → css/containers/pairs-list.css} +13 -12
  40. package/src/{themes/variables.less → css/containers/scroll-panel.css} +25 -22
  41. package/src/{less/containers/split-panel.less → css/containers/split-panel.css} +15 -14
  42. package/src/{less/containers/tabs.less → css/containers/tabs.css} +17 -19
  43. package/src/css/dom/checkbox.css +102 -0
  44. package/src/css/dom/scrollbar.css +35 -0
  45. package/src/{less/dom/select.less → css/dom/select.css} +17 -18
  46. package/src/{less/empty-column.less → css/empty-column.css} +19 -18
  47. package/src/{less/expression-editor.less → css/expression-editor.css} +19 -18
  48. package/src/{less/filter-dropdown.less → css/filter-dropdown.css} +12 -11
  49. package/src/{less/filter-item.less → css/filter-item.css} +16 -15
  50. package/src/{less/form/code-editor.less → css/form/code-editor.css} +26 -30
  51. package/src/{less/form/debug.less → css/form/debug.css} +19 -18
  52. package/src/{less/function-dropdown.less → css/function-dropdown.css} +12 -11
  53. package/src/css/plugin-selector.css +261 -0
  54. package/src/{less/render-warning.less → css/render-warning.css} +18 -17
  55. package/src/{less/status-bar.less → css/status-bar.css} +156 -144
  56. package/src/css/type-icon.css +116 -0
  57. package/src/{less/viewer.less → css/viewer.css} +112 -146
  58. package/src/rust/components/column_dropdown.rs +229 -119
  59. package/src/rust/components/column_selector/active_column.rs +81 -62
  60. package/src/rust/components/column_selector/add_expression_button.rs +1 -0
  61. package/src/rust/components/column_selector/aggregate_selector.rs +25 -15
  62. package/src/rust/components/column_selector/config_selector.rs +315 -199
  63. package/src/rust/components/column_selector/empty_column.rs +2 -2
  64. package/src/rust/components/column_selector/expr_edit_button.rs +8 -2
  65. package/src/rust/components/column_selector/filter_column.rs +37 -26
  66. package/src/rust/components/column_selector/inactive_column.rs +41 -29
  67. package/src/rust/components/column_selector/invalid_column.rs +7 -18
  68. package/src/rust/components/column_selector/pivot_column.rs +11 -5
  69. package/src/rust/components/column_selector/sort_column.rs +23 -13
  70. package/src/rust/components/column_selector.rs +163 -84
  71. package/src/rust/components/column_settings_sidebar/style_tab/symbol/row_selector.rs +1 -1
  72. package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs.rs +3 -2
  73. package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs_item.rs +3 -2
  74. package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_selector.rs +2 -3
  75. package/src/rust/components/column_settings_sidebar/style_tab/symbol.rs +7 -1
  76. package/src/rust/components/column_settings_sidebar/style_tab.rs +153 -112
  77. package/src/rust/components/column_settings_sidebar.rs +91 -53
  78. package/src/rust/components/containers/dragdrop_list.rs +2 -1
  79. package/src/rust/components/containers/sidebar_close_button.rs +1 -1
  80. package/src/rust/components/containers/split_panel.rs +1 -0
  81. package/src/rust/components/containers/tab_list.rs +1 -1
  82. package/src/rust/components/copy_dropdown.rs +7 -28
  83. package/src/rust/components/datetime_column_style/custom.rs +2 -2
  84. package/src/rust/components/datetime_column_style/simple.rs +2 -2
  85. package/src/rust/components/datetime_column_style.rs +4 -2
  86. package/src/rust/components/editable_header.rs +7 -4
  87. package/src/rust/components/empty_row.rs +1 -1
  88. package/src/rust/components/export_dropdown.rs +4 -30
  89. package/src/rust/components/expression_editor.rs +19 -10
  90. package/src/rust/components/filter_dropdown.rs +246 -102
  91. package/src/rust/components/font_loader.rs +11 -28
  92. package/src/rust/components/form/code_editor.rs +17 -2
  93. package/src/rust/components/form/color_range_selector.rs +19 -6
  94. package/src/rust/components/form/debug.rs +30 -13
  95. package/src/rust/components/function_dropdown.rs +186 -113
  96. package/src/rust/components/main_panel.rs +71 -89
  97. package/src/rust/components/mod.rs +1 -1
  98. package/src/rust/components/modal.rs +7 -1
  99. package/src/rust/components/number_column_style.rs +22 -7
  100. package/src/rust/components/plugin_selector.rs +34 -102
  101. package/src/rust/components/portal.rs +274 -0
  102. package/src/rust/components/render_warning.rs +72 -123
  103. package/src/rust/components/settings_panel.rs +115 -11
  104. package/src/rust/components/status_bar.rs +222 -98
  105. package/src/rust/components/status_bar_counter.rs +8 -20
  106. package/src/rust/components/status_indicator.rs +64 -114
  107. package/src/rust/components/string_column_style.rs +2 -2
  108. package/src/rust/components/style/style_cache.rs +5 -1
  109. package/src/rust/components/viewer.rs +391 -39
  110. package/src/rust/custom_elements/copy_dropdown.rs +102 -21
  111. package/src/rust/custom_elements/export_dropdown.rs +102 -20
  112. package/src/rust/custom_elements/mod.rs +0 -7
  113. package/src/rust/custom_elements/modal.rs +7 -103
  114. package/src/rust/custom_elements/viewer.rs +99 -35
  115. package/src/rust/custom_events.rs +23 -2
  116. package/src/rust/dragdrop.rs +149 -10
  117. package/src/{less/containers/scroll-panel.less → rust/engines.rs} +15 -13
  118. package/src/rust/js/plugin.rs +1 -1
  119. package/src/rust/lib.rs +5 -4
  120. package/src/rust/presentation/props.rs +39 -0
  121. package/src/rust/presentation/sheets.rs +3 -3
  122. package/src/rust/presentation.rs +44 -8
  123. package/src/rust/renderer/limits.rs +32 -3
  124. package/src/{less/dom/scrollbar.less → rust/renderer/props.rs} +18 -19
  125. package/src/rust/renderer.rs +83 -9
  126. package/src/rust/session/column_defaults_update.rs +1 -1
  127. package/src/rust/session/metadata.rs +23 -2
  128. package/src/rust/session/props.rs +178 -0
  129. package/src/rust/session.rs +124 -117
  130. package/src/rust/tasks/column_locator.rs +133 -0
  131. package/src/rust/{model → tasks}/columns_iter_set.rs +14 -23
  132. package/src/rust/{model → tasks}/edit_expression.rs +34 -10
  133. package/src/rust/{model → tasks}/eject.rs +2 -2
  134. package/src/rust/{model → tasks}/get_viewer_config.rs +0 -11
  135. package/src/rust/{model → tasks}/intersection_observer.rs +19 -3
  136. package/src/{less/containers/radio-list.less → rust/tasks/is_invalid_drop.rs} +21 -14
  137. package/src/rust/tasks/mod.rs +52 -0
  138. package/src/rust/{model → tasks}/plugin_column_styles.rs +69 -46
  139. package/src/rust/{model → tasks}/resize_observer.rs +39 -6
  140. package/src/rust/{model → tasks}/send_plugin_config.rs +1 -1
  141. package/src/rust/tasks/structural.rs +53 -0
  142. package/src/rust/utils/mod.rs +4 -0
  143. package/src/rust/utils/modal_position.rs +110 -0
  144. package/src/rust/utils/ptr_eq_rc.rs +74 -0
  145. package/src/rust/utils/pubsub.rs +11 -1
  146. package/src/svg/bg-pattern.png +0 -0
  147. package/src/svg/close-icon.svg +1 -1
  148. package/src/svg/expression.svg +1 -1
  149. package/src/svg/mega-menu-icons-candlestick.svg +1 -1
  150. package/src/svg/mega-menu-icons-datagrid.svg +1 -2
  151. package/src/svg/mega-menu-icons-heatmap.svg +1 -1
  152. package/src/svg/mega-menu-icons-map-scatter.svg +1 -1
  153. package/src/svg/mega-menu-icons-ohlc.svg +1 -1
  154. package/src/svg/mega-menu-icons-sunburst.svg +1 -1
  155. package/src/svg/mega-menu-icons-treemap.svg +1 -1
  156. package/src/svg/mega-menu-icons-x-bar.svg +1 -1
  157. package/src/svg/mega-menu-icons-x-y-line.svg +1 -1
  158. package/src/svg/mega-menu-icons-x-y-scatter.svg +1 -1
  159. package/src/svg/mega-menu-icons-y-area.svg +1 -1
  160. package/src/svg/mega-menu-icons-y-bar.svg +1 -1
  161. package/src/svg/mega-menu-icons-y-line.svg +1 -1
  162. package/src/svg/mega-menu-icons-y-scatter.svg +1 -1
  163. package/src/svg/radio-hover.svg +1 -1
  164. package/src/svg/radio-off.svg +1 -1
  165. package/src/svg/radio-on.svg +1 -1
  166. package/src/themes/botanical.css +157 -0
  167. package/src/themes/defaults.css +139 -0
  168. package/src/themes/dracula.css +233 -0
  169. package/src/themes/gruvbox-dark.css +255 -0
  170. package/src/themes/gruvbox.css +134 -0
  171. package/src/themes/icons.css +124 -0
  172. package/src/themes/intl/de.css +102 -0
  173. package/src/themes/intl/es.css +102 -0
  174. package/src/themes/intl/fr.css +102 -0
  175. package/src/themes/intl/ja.css +102 -0
  176. package/src/themes/intl/pt.css +102 -0
  177. package/src/themes/intl/zh.css +102 -0
  178. package/src/themes/intl.css +102 -0
  179. package/src/themes/monokai.css +233 -0
  180. package/src/themes/pro-dark.css +158 -0
  181. package/src/themes/{themes.less → pro.css} +17 -21
  182. package/src/themes/solarized-dark.css +135 -0
  183. package/src/themes/solarized.css +95 -0
  184. package/src/themes/themes.css +22 -0
  185. package/src/themes/vaporwave.css +256 -0
  186. package/dist/css/variables.css +0 -0
  187. package/src/less/column-dropdown.less +0 -95
  188. package/src/less/dom/checkbox.less +0 -100
  189. package/src/less/plugin-selector.less +0 -183
  190. package/src/less/type-icon.less +0 -68
  191. package/src/rust/components/error_message.rs +0 -56
  192. package/src/rust/custom_elements/column_dropdown.rs +0 -123
  193. package/src/rust/custom_elements/filter_dropdown.rs +0 -179
  194. package/src/rust/custom_elements/function_dropdown.rs +0 -115
  195. package/src/rust/model/column_locator.rs +0 -82
  196. package/src/rust/model/is_invalid_drop.rs +0 -36
  197. package/src/rust/model/mod.rs +0 -100
  198. package/src/rust/model/reset_all.rs +0 -38
  199. package/src/rust/model/structural.rs +0 -244
  200. package/src/themes/botanical.less +0 -142
  201. package/src/themes/dracula.less +0 -101
  202. package/src/themes/gruvbox-dark.less +0 -116
  203. package/src/themes/gruvbox.less +0 -152
  204. package/src/themes/icons.less +0 -130
  205. package/src/themes/intl/de.less +0 -102
  206. package/src/themes/intl/es.less +0 -102
  207. package/src/themes/intl/fr.less +0 -102
  208. package/src/themes/intl/ja.less +0 -102
  209. package/src/themes/intl/pt.less +0 -102
  210. package/src/themes/intl/zh.less +0 -102
  211. package/src/themes/intl.less +0 -102
  212. package/src/themes/monokai.less +0 -107
  213. package/src/themes/pro-dark.less +0 -147
  214. package/src/themes/pro.less +0 -186
  215. package/src/themes/solarized-dark.less +0 -78
  216. package/src/themes/solarized.less +0 -102
  217. package/src/themes/vaporwave.less +0 -145
  218. /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-68fef752754ffbc6}/inline0.js +0 -0
  219. /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-68fef752754ffbc6}/inline1.js +0 -0
  220. /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-68fef752754ffbc6}/inline2.js +0 -0
  221. /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-68fef752754ffbc6}/inline3.js +0 -0
  222. /package/dist/wasm/snippets/{perspective-viewer-d729f682ba5c19df → perspective-viewer-68fef752754ffbc6}/inline4.js +0 -0
  223. /package/src/rust/{model → tasks}/copy_export.rs +0 -0
  224. /package/src/rust/{model → tasks}/export_app.rs +0 -0
  225. /package/src/rust/{model → tasks}/export_method.rs +0 -0
  226. /package/src/rust/{model → tasks}/restore_and_render.rs +0 -0
  227. /package/src/rust/{model → tasks}/update_and_render.rs +0 -0
@@ -1,68 +0,0 @@
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
- :host #selected-columns .type-icon,
14
- :host #sub-columns .type-icon {
15
- position: absolute;
16
- left: 15px;
17
- }
18
-
19
- :host .type-icon {
20
- height: 13px;
21
- width: 13px;
22
- background-repeat: no-repeat;
23
- background-color: var(--icon--color);
24
- content: "";
25
- display: inline-block;
26
- -webkit-mask-size: cover;
27
- mask-size: cover;
28
- flex-shrink: 0;
29
-
30
- &.none {
31
- content: none;
32
- }
33
-
34
- &.integer {
35
- -webkit-mask-image: var(--column-type-integer--mask-image);
36
- mask-image: var(--column-type-integer--mask-image);
37
- }
38
-
39
- &.float {
40
- -webkit-mask-image: var(--column-type-float--mask-image);
41
- mask-image: var(--column-type-float--mask-image);
42
- }
43
-
44
- &.string {
45
- -webkit-mask-image: var(--column-type-string--mask-image);
46
- mask-image: var(--column-type-string--mask-image);
47
- }
48
-
49
- &.boolean {
50
- -webkit-mask-image: var(--column-type-boolean--mask-image);
51
- mask-image: var(--column-type-boolean--mask-image);
52
- }
53
-
54
- &.date {
55
- -webkit-mask-image: var(--column-type-date--mask-image);
56
- mask-image: var(--column-type-date--mask-image);
57
- }
58
-
59
- &.datetime {
60
- -webkit-mask-image: var(--column-type-datetime--mask-image);
61
- mask-image: var(--column-type-datetime--mask-image);
62
- }
63
-
64
- &.expression {
65
- -webkit-mask-image: var(--add-expression-icon--mask-image);
66
- mask-image: var(--add-expression-icon--mask-image);
67
- }
68
- }
@@ -1,56 +0,0 @@
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::clone;
14
- use yew::prelude::*;
15
- use yew::{Properties, function_component, html};
16
-
17
- use crate::components::style::LocalStyle;
18
- use crate::css;
19
- use crate::session::Session;
20
- use crate::utils::AddListener;
21
-
22
- #[derive(PartialEq, Properties)]
23
- pub struct ErrorMessageProps {
24
- pub session: Session,
25
- }
26
-
27
- #[function_component(ErrorMessage)]
28
- pub fn error_message(p: &ErrorMessageProps) -> yew::Html {
29
- let error = use_state(|| p.session.get_error());
30
- use_effect_with(
31
- (error.setter(), p.session.clone()),
32
- |(set_error, session)| {
33
- let sub = session.table_errored.add_listener({
34
- clone!(set_error);
35
- move |y| set_error.set(Some(y))
36
- });
37
-
38
- || drop(sub)
39
- },
40
- );
41
-
42
- html! {
43
- <>
44
- <LocalStyle href={css!("render-warning")} />
45
- <div
46
- class="plugin_information plugin_information--warning"
47
- id="plugin_information--size"
48
- >
49
- <span class="plugin_information__icon" />
50
- <span class="plugin_information__text" id="plugin_information_count">
51
- if let Some(msg) = error.as_ref() { { msg } }
52
- </span>
53
- </div>
54
- </>
55
- }
56
- }
@@ -1,123 +0,0 @@
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
-
15
- use perspective_client::clone;
16
- use perspective_client::config::Expression;
17
- use perspective_js::json;
18
- use perspective_js::utils::global;
19
- use wasm_bindgen::JsCast;
20
- use wasm_bindgen::prelude::*;
21
- use web_sys::*;
22
- use yew::html::ImplicitClone;
23
- use yew::{Callback, props};
24
-
25
- use crate::components::column_dropdown::*;
26
- use crate::components::column_selector::InPlaceColumn;
27
- use crate::custom_elements::modal::*;
28
- use crate::session::Session;
29
- use crate::*;
30
-
31
- #[wasm_bindgen]
32
- #[derive(Clone)]
33
- pub struct ColumnDropDownElement {
34
- modal: ModalElement<ColumnDropDown>,
35
- session: Session,
36
- }
37
-
38
- impl ImplicitClone for ColumnDropDownElement {}
39
-
40
- impl ColumnDropDownElement {
41
- pub fn new(session: Session) -> Self {
42
- let dropdown = global::document()
43
- .create_element("perspective-dropdown")
44
- .unwrap()
45
- .unchecked_into::<HtmlElement>();
46
-
47
- let props = props!(ColumnDropDownProps {});
48
- let modal = ModalElement::new(dropdown, props, false, None);
49
- Self { modal, session }
50
- }
51
-
52
- pub fn autocomplete(
53
- &self,
54
- target: HtmlInputElement,
55
- exclude: HashSet<String>,
56
- callback: Callback<InPlaceColumn>,
57
- ) -> Option<()> {
58
- let input = target.value();
59
- let metadata = self.session.metadata();
60
- let mut values: Vec<InPlaceColumn> = vec![];
61
- let small_input = input.to_lowercase();
62
- for col in metadata.get_table_columns()? {
63
- if !exclude.contains(col) && col.to_lowercase().contains(&small_input) {
64
- values.push(InPlaceColumn::Column(col.to_owned()));
65
- }
66
- }
67
-
68
- for col in self.session.metadata().get_expression_columns() {
69
- if !exclude.contains(col) && col.to_lowercase().contains(&small_input) {
70
- values.push(InPlaceColumn::Column(col.to_owned()));
71
- }
72
- }
73
-
74
- clone!(self.modal, self.session);
75
- ApiFuture::spawn(async move {
76
- if !exclude.contains(&input) {
77
- let is_expr = session.validate_expr(&input).await?.is_none();
78
-
79
- if is_expr {
80
- values.push(InPlaceColumn::Expression(Expression::new(
81
- None,
82
- input.into(),
83
- )));
84
- }
85
- }
86
-
87
- let classes = modal.custom_element.class_list();
88
- let no_results = json!(["no-results"]);
89
- if values.is_empty() {
90
- classes.add(&no_results).unwrap();
91
- } else {
92
- classes.remove(&no_results).unwrap();
93
- }
94
-
95
- modal.send_message_batch(vec![
96
- ColumnDropDownMsg::SetCallback(callback),
97
- ColumnDropDownMsg::SetValues(values, target.get_bounding_client_rect().width()),
98
- ]);
99
-
100
- modal.open(target.unchecked_into(), None).await
101
- });
102
-
103
- Some(())
104
- }
105
-
106
- pub fn item_select(&self) {
107
- self.modal.send_message(ColumnDropDownMsg::ItemSelect);
108
- }
109
-
110
- pub fn item_down(&self) {
111
- self.modal.send_message(ColumnDropDownMsg::ItemDown);
112
- }
113
-
114
- pub fn item_up(&self) {
115
- self.modal.send_message(ColumnDropDownMsg::ItemUp);
116
- }
117
-
118
- pub fn hide(&self) -> ApiResult<()> {
119
- self.modal.hide()
120
- }
121
-
122
- pub fn connected_callback(&self) {}
123
- }
@@ -1,179 +0,0 @@
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::collections::HashSet;
15
- use std::rc::Rc;
16
-
17
- use perspective_client::clone;
18
- use perspective_js::utils::global;
19
- use wasm_bindgen::JsCast;
20
- use wasm_bindgen::prelude::*;
21
- use web_sys::*;
22
- use yew::html::ImplicitClone;
23
- use yew::*;
24
-
25
- use crate::components::filter_dropdown::*;
26
- use crate::custom_elements::modal::*;
27
- use crate::session::Session;
28
- use crate::*;
29
-
30
- #[wasm_bindgen]
31
- #[derive(Clone)]
32
- pub struct FilterDropDownElement {
33
- modal: ModalElement<FilterDropDown>,
34
- session: Session,
35
- column: Rc<RefCell<Option<(usize, String)>>>,
36
- values: Rc<RefCell<Option<Vec<String>>>>,
37
- target: Rc<RefCell<Option<HtmlElement>>>,
38
- }
39
-
40
- impl PartialEq for FilterDropDownElement {
41
- fn eq(&self, other: &Self) -> bool {
42
- self.column == other.column && self.values == other.values && self.target == other.target
43
- }
44
- }
45
-
46
- impl ImplicitClone for FilterDropDownElement {}
47
-
48
- impl FilterDropDownElement {
49
- pub fn new(session: Session) -> Self {
50
- let dropdown = global::document()
51
- .create_element("perspective-dropdown")
52
- .unwrap()
53
- .unchecked_into::<HtmlElement>();
54
-
55
- let column: Rc<RefCell<Option<(usize, String)>>> = Rc::new(RefCell::new(None));
56
- let props = props!(FilterDropDownProps {});
57
- let modal = ModalElement::new(dropdown, props, false, None);
58
- let values = Rc::new(RefCell::new(None));
59
- Self {
60
- modal,
61
- session,
62
- column,
63
- values,
64
- target: Default::default(),
65
- }
66
- }
67
-
68
- pub fn reautocomplete(&self) {
69
- ApiFuture::spawn(
70
- self.modal
71
- .clone()
72
- .open(self.target.borrow().clone().unwrap(), None),
73
- );
74
- }
75
-
76
- pub fn autocomplete(
77
- &self,
78
- column: (usize, String),
79
- input: String,
80
- exclude: HashSet<String>,
81
- target: HtmlElement,
82
- callback: Callback<String>,
83
- ) {
84
- let current_column = self.column.borrow().clone();
85
- match current_column {
86
- Some(filter_col) if filter_col == column => {
87
- let values = filter_values(&input, &self.values, &exclude);
88
- if values.len() == 1 && values[0] == input {
89
- self.hide().unwrap();
90
- } else {
91
- self.modal.send_message_batch(vec![
92
- FilterDropDownMsg::SetCallback(callback),
93
- FilterDropDownMsg::SetValues(values),
94
- ]);
95
-
96
- if let Some(x) = self.target.borrow().clone()
97
- && !self.modal.is_open()
98
- {
99
- ApiFuture::spawn(self.modal.clone().open(x, None))
100
- }
101
- }
102
- },
103
- _ => {
104
- ApiFuture::spawn({
105
- clone!(
106
- self.modal,
107
- self.session,
108
- self.values,
109
- old_column = self.column,
110
- old_target = self.target
111
- );
112
- async move {
113
- let all_values = session.get_column_values(column.1.clone()).await?;
114
- *values.borrow_mut() = Some(all_values);
115
- let filter_values = filter_values(&input, &values, &exclude);
116
- if filter_values.len() == 1 && filter_values[0] == input {
117
- *old_column.borrow_mut() = Some(column);
118
- *old_target.borrow_mut() = Some(target.clone());
119
- let filter_values = self::filter_values("", &values, &exclude);
120
- modal.send_message_batch(vec![
121
- FilterDropDownMsg::SetCallback(callback),
122
- FilterDropDownMsg::SetValues(filter_values),
123
- ]);
124
-
125
- modal.hide()
126
- } else {
127
- *old_column.borrow_mut() = Some(column);
128
- *old_target.borrow_mut() = Some(target.clone());
129
- modal.send_message_batch(vec![
130
- FilterDropDownMsg::SetCallback(callback),
131
- FilterDropDownMsg::SetValues(filter_values),
132
- ]);
133
-
134
- modal.open(target, None).await
135
- }
136
- }
137
- });
138
- },
139
- }
140
- }
141
-
142
- pub fn item_select(&self) {
143
- self.modal.send_message(FilterDropDownMsg::ItemSelect);
144
- }
145
-
146
- pub fn item_down(&self) {
147
- self.modal.send_message(FilterDropDownMsg::ItemDown);
148
- }
149
-
150
- pub fn item_up(&self) {
151
- self.modal.send_message(FilterDropDownMsg::ItemUp);
152
- }
153
-
154
- pub fn hide(&self) -> ApiResult<()> {
155
- let result = self.modal.hide();
156
- drop(self.column.borrow_mut().take());
157
- result
158
- }
159
-
160
- pub fn connected_callback(&self) {}
161
- }
162
-
163
- fn filter_values(
164
- input: &str,
165
- values: &Rc<RefCell<Option<Vec<String>>>>,
166
- exclude: &HashSet<String>,
167
- ) -> Vec<String> {
168
- let input = input.to_lowercase();
169
- if let Some(values) = &*values.borrow() {
170
- values
171
- .iter()
172
- .filter(|x| x.to_lowercase().contains(&input) && !exclude.contains(x.as_str()))
173
- .take(10)
174
- .cloned()
175
- .collect::<Vec<String>>()
176
- } else {
177
- vec![]
178
- }
179
- }
@@ -1,115 +0,0 @@
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::rc::Rc;
15
-
16
- use perspective_client::config::{COMPLETIONS, CompletionItemSuggestion};
17
- use perspective_js::utils::global;
18
- use wasm_bindgen::JsCast;
19
- use wasm_bindgen::prelude::*;
20
- use web_sys::*;
21
- use yew::html::ImplicitClone;
22
- use yew::*;
23
-
24
- use crate::components::function_dropdown::*;
25
- use crate::custom_elements::modal::*;
26
- use crate::*;
27
-
28
- #[wasm_bindgen]
29
- #[derive(Clone)]
30
- pub struct FunctionDropDownElement {
31
- modal: ModalElement<FunctionDropDown>,
32
- target: Rc<RefCell<Option<HtmlElement>>>,
33
- }
34
-
35
- impl PartialEq for FunctionDropDownElement {
36
- fn eq(&self, _other: &Self) -> bool {
37
- true
38
- }
39
- }
40
-
41
- impl ImplicitClone for FunctionDropDownElement {}
42
-
43
- impl FunctionDropDownElement {
44
- pub fn reautocomplete(&self) {
45
- ApiFuture::spawn(
46
- self.modal
47
- .clone()
48
- .open(self.target.borrow().clone().unwrap(), None),
49
- );
50
- }
51
-
52
- pub fn autocomplete(
53
- &self,
54
- input: String,
55
- target: HtmlElement,
56
- callback: Callback<CompletionItemSuggestion>,
57
- ) -> ApiResult<()> {
58
- let values = filter_values(&input);
59
- if values.is_empty() {
60
- self.modal.hide()?;
61
- } else {
62
- self.modal.send_message_batch(vec![
63
- FunctionDropDownMsg::SetCallback(callback),
64
- FunctionDropDownMsg::SetValues(values),
65
- ]);
66
-
67
- ApiFuture::spawn(self.modal.clone().open(target, None));
68
- }
69
-
70
- Ok(())
71
- }
72
-
73
- pub fn item_select(&self) {
74
- self.modal.send_message(FunctionDropDownMsg::ItemSelect);
75
- }
76
-
77
- pub fn item_down(&self) {
78
- self.modal.send_message(FunctionDropDownMsg::ItemDown);
79
- }
80
-
81
- pub fn item_up(&self) {
82
- self.modal.send_message(FunctionDropDownMsg::ItemUp);
83
- }
84
-
85
- pub fn hide(&self) -> ApiResult<()> {
86
- self.modal.hide()
87
- }
88
-
89
- pub fn connected_callback(&self) {}
90
- }
91
-
92
- impl Default for FunctionDropDownElement {
93
- fn default() -> Self {
94
- let dropdown = global::document()
95
- .create_element("perspective-dropdown")
96
- .unwrap()
97
- .unchecked_into::<HtmlElement>();
98
-
99
- let props = props!(FunctionDropDownProps {});
100
- let modal = ModalElement::new(dropdown, props, false, None);
101
- Self {
102
- modal,
103
- target: Default::default(),
104
- }
105
- }
106
- }
107
-
108
- fn filter_values(input: &str) -> Vec<CompletionItemSuggestion> {
109
- let input = input.to_lowercase();
110
- COMPLETIONS
111
- .iter()
112
- .filter(|x| x.label.to_lowercase().starts_with(&input))
113
- .cloned()
114
- .collect::<Vec<_>>()
115
- }
@@ -1,82 +0,0 @@
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::config::ColumnType;
14
-
15
- use super::HasSession;
16
- use crate::model::{HasPresentation, HasRenderer, PluginColumnStyles};
17
- use crate::presentation::ColumnLocator;
18
-
19
- pub trait ColumnLocatorExt: HasSession {
20
- fn locator_name_or_default(&self, locator: &ColumnLocator) -> String {
21
- match locator {
22
- ColumnLocator::Table(s) | ColumnLocator::Expression(s) => s.clone(),
23
- ColumnLocator::NewExpression => self.session().metadata().make_new_column_name(None),
24
- }
25
- }
26
-
27
- fn is_locator_active(&self, locator: &ColumnLocator) -> bool {
28
- locator
29
- .name()
30
- .map(|name| self.session().is_column_active(name))
31
- .unwrap_or_default()
32
- }
33
-
34
- fn locator_view_type(&self, locator: &ColumnLocator) -> Option<ColumnType> {
35
- let name = locator.name().cloned().unwrap_or_default();
36
- self.session()
37
- .metadata()
38
- .get_column_view_type(name.as_str())
39
- }
40
-
41
- /// This function will return a [`ColumnLocator`] for agiven column name, or
42
- /// [`None`] if no such column already exists. If you want to
43
- /// create a new expression column, use ColumnLocator::Expr(None)
44
- fn get_column_locator(&self, name: Option<String>) -> Option<ColumnLocator> {
45
- name.and_then(|name| {
46
- if self.session().metadata().is_column_expression(&name) {
47
- Some(ColumnLocator::Expression(name))
48
- } else {
49
- self.session().metadata().get_table_columns().and_then(|x| {
50
- x.iter()
51
- .find_map(|n| (n == &name).then_some(ColumnLocator::Table(name.clone())))
52
- })
53
- }
54
- })
55
- }
56
- }
57
-
58
- impl<T: HasSession> ColumnLocatorExt for T {}
59
-
60
- pub trait ColumnLocatorCurrentExt:
61
- HasPresentation + HasRenderer + HasSession + PluginColumnStyles
62
- {
63
- /// Gets a [`ColumnLocator`] for the current UI's column settings state,
64
- /// or [`None`] if it is not currently active.
65
- fn get_current_column_locator(&self) -> Option<ColumnLocator> {
66
- self.presentation()
67
- .get_open_column_settings()
68
- .locator
69
- .filter(|locator| match locator {
70
- ColumnLocator::Table(name) => {
71
- self.session().is_locator_active(locator)
72
- && self.can_render_column_styles(name).unwrap_or_default()
73
- },
74
- _ => true,
75
- })
76
- }
77
- }
78
-
79
- impl<T: HasPresentation + HasRenderer + HasSession + PluginColumnStyles> ColumnLocatorCurrentExt
80
- for T
81
- {
82
- }
@@ -1,36 +0,0 @@
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 super::{HasRenderer, HasSession};
14
-
15
- pub trait IsInvalidDrop: HasRenderer + HasSession {
16
- fn is_invalid_columns_column(&self, from_column: &String, to_index: usize) -> bool {
17
- let config = self.session().get_view_config();
18
- let from_index = config
19
- .columns
20
- .iter()
21
- .position(|x| x.as_ref() == Some(from_column));
22
-
23
- let min_cols = self.renderer().metadata().min;
24
- let is_to_empty = !config
25
- .columns
26
- .get(to_index)
27
- .map(|x| x.is_some())
28
- .unwrap_or_default();
29
- min_cols
30
- .and_then(|x| from_index.map(|from_index| from_index < x))
31
- .unwrap_or_default()
32
- && is_to_empty
33
- }
34
- }
35
-
36
- impl<T: HasRenderer + HasSession> IsInvalidDrop for T {}