@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.
- package/LICENSE.md +193 -0
- package/README.md +4 -0
- package/dist/cdn/perspective-viewer.js +3 -0
- package/dist/cdn/perspective-viewer.js.map +7 -0
- package/dist/css/dracula.css +1 -0
- package/dist/css/gruvbox-dark.css +1 -0
- package/dist/css/gruvbox.css +1 -0
- package/dist/css/icons.css +1 -0
- package/dist/css/intl/de.css +1 -0
- package/dist/css/intl/es.css +1 -0
- package/dist/css/intl/fr.css +1 -0
- package/dist/css/intl/ja.css +1 -0
- package/dist/css/intl/pt.css +1 -0
- package/dist/css/intl/zh.css +1 -0
- package/dist/css/intl.css +1 -0
- package/dist/css/monokai.css +1 -0
- package/dist/css/pro-dark.css +1 -0
- package/dist/css/pro.css +1 -0
- package/dist/css/solarized-dark.css +1 -0
- package/dist/css/solarized.css +1 -0
- package/dist/css/themes.css +1 -0
- package/dist/css/vaporwave.css +1 -0
- package/dist/css/variables.css +0 -0
- package/dist/esm/bootstrap.d.ts +1 -0
- package/dist/esm/extensions.d.ts +70 -0
- package/dist/esm/perspective-viewer.d.ts +39 -0
- package/dist/esm/perspective-viewer.inline.js +3 -0
- package/dist/esm/perspective-viewer.inline.js.map +7 -0
- package/dist/esm/perspective-viewer.js +3 -0
- package/dist/esm/perspective-viewer.js.map +7 -0
- package/dist/esm/plugin.d.ts +195 -0
- package/dist/esm/ts-rs/Aggregate.d.ts +1 -0
- package/dist/esm/ts-rs/ColumnConfigValues.d.ts +31 -0
- package/dist/esm/ts-rs/CustomDatetimeFormat.d.ts +1 -0
- package/dist/esm/ts-rs/CustomDatetimeStyleConfig.d.ts +15 -0
- package/dist/esm/ts-rs/CustomNumberFormatConfig.d.ts +18 -0
- package/dist/esm/ts-rs/DatetimeColorMode.d.ts +1 -0
- package/dist/esm/ts-rs/DatetimeFormatType.d.ts +6 -0
- package/dist/esm/ts-rs/Expressions.d.ts +3 -0
- package/dist/esm/ts-rs/Filter.d.ts +2 -0
- package/dist/esm/ts-rs/FilterReducer.d.ts +1 -0
- package/dist/esm/ts-rs/FilterTerm.d.ts +2 -0
- package/dist/esm/ts-rs/FormatMode.d.ts +1 -0
- package/dist/esm/ts-rs/FormatUnit.d.ts +1 -0
- package/dist/esm/ts-rs/NumberBackgroundMode.d.ts +1 -0
- package/dist/esm/ts-rs/NumberForegroundMode.d.ts +1 -0
- package/dist/esm/ts-rs/OptionalUpdate.d.ts +1 -0
- package/dist/esm/ts-rs/PluginConfig.d.ts +2 -0
- package/dist/esm/ts-rs/RoundingMode.d.ts +1 -0
- package/dist/esm/ts-rs/RoundingPriority.d.ts +1 -0
- package/dist/esm/ts-rs/Scalar.d.ts +5 -0
- package/dist/esm/ts-rs/SignDisplay.d.ts +1 -0
- package/dist/esm/ts-rs/SimpleDatetimeFormat.d.ts +1 -0
- package/dist/esm/ts-rs/SimpleDatetimeStyleConfig.d.ts +6 -0
- package/dist/esm/ts-rs/Sort.d.ts +2 -0
- package/dist/esm/ts-rs/SortDir.d.ts +1 -0
- package/dist/esm/ts-rs/StringColorMode.d.ts +1 -0
- package/dist/esm/ts-rs/TrailingZeroDisplay.d.ts +1 -0
- package/dist/esm/ts-rs/UseGrouping.d.ts +1 -0
- package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +102 -0
- package/dist/esm/ts-rs/serde_json/JsonValue.d.ts +3 -0
- package/dist/wasm/perspective-viewer.d.ts +1291 -0
- package/dist/wasm/perspective-viewer.js +3883 -0
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +142 -0
- package/dist/wasm/snippets/perspective-viewer-c69283f6f62a5f14/inline0.js +1 -0
- package/dist/wasm/snippets/perspective-viewer-c69283f6f62a5f14/inline1.js +1 -0
- package/dist/wasm/snippets/perspective-viewer-c69283f6f62a5f14/inline2.js +1 -0
- package/dist/wasm/snippets/perspective-viewer-c69283f6f62a5f14/inline3.js +44 -0
- package/dist/wasm/snippets/perspective-viewer-c69283f6f62a5f14/inline4.js +1 -0
- package/package.json +55 -0
- package/src/less/aggregate-selector.less +72 -0
- package/src/less/column-dropdown.less +95 -0
- package/src/less/column-selector.less +551 -0
- package/src/less/column-settings-panel.less +255 -0
- package/src/less/column-style.less +319 -0
- package/src/less/column-symbol-attributes.less +73 -0
- package/src/less/config-selector.less +363 -0
- package/src/less/containers/dropdown-menu.less +94 -0
- package/src/less/containers/pairs-list.less +46 -0
- package/src/less/containers/radio-list.less +29 -0
- package/src/less/containers/scroll-panel.less +27 -0
- package/src/less/containers/split-panel.less +80 -0
- package/src/less/containers/tabs.less +90 -0
- package/src/less/dom/checkbox.less +100 -0
- package/src/less/dom/scrollbar.less +35 -0
- package/src/less/dom/select.less +63 -0
- package/src/less/empty-column.less +72 -0
- package/src/less/expression-editor.less +152 -0
- package/src/less/filter-dropdown.less +53 -0
- package/src/less/filter-item.less +126 -0
- package/src/less/form/code-editor.less +137 -0
- package/src/less/form/debug.less +88 -0
- package/src/less/function-dropdown.less +45 -0
- package/src/less/plugin-selector.less +173 -0
- package/src/less/render-warning.less +81 -0
- package/src/less/status-bar.less +551 -0
- package/src/less/type-icon.less +68 -0
- package/src/less/viewer.less +368 -0
- package/src/rust/components/column_dropdown.rs +162 -0
- package/src/rust/components/column_selector/active_column.rs +462 -0
- package/src/rust/components/column_selector/add_expression_button.rs +59 -0
- package/src/rust/components/column_selector/aggregate_selector.rs +186 -0
- package/src/rust/components/column_selector/config_selector.rs +674 -0
- package/src/rust/components/column_selector/empty_column.rs +134 -0
- package/src/rust/components/column_selector/expression_toolbar.rs +45 -0
- package/src/rust/components/column_selector/filter_column.rs +530 -0
- package/src/rust/components/column_selector/inactive_column.rs +221 -0
- package/src/rust/components/column_selector/invalid_column.rs +37 -0
- package/src/rust/components/column_selector/pivot_column.rs +93 -0
- package/src/rust/components/column_selector/sort_column.rs +135 -0
- package/src/rust/components/column_selector.rs +426 -0
- package/src/rust/components/column_settings_sidebar/attributes_tab.rs +34 -0
- package/src/rust/components/column_settings_sidebar/mod.rs +17 -0
- package/src/rust/components/column_settings_sidebar/save_settings.rs +68 -0
- package/src/rust/components/column_settings_sidebar/sidebar.rs +396 -0
- package/src/rust/components/column_settings_sidebar/style_tab/column_style.rs +177 -0
- package/src/rust/components/column_settings_sidebar/style_tab/stub.rs +34 -0
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/row_selector.rs +101 -0
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_config.rs +24 -0
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_pairs.rs +185 -0
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_selector.rs +55 -0
- package/src/rust/components/column_settings_sidebar/style_tab/symbol.rs +131 -0
- package/src/rust/components/column_settings_sidebar/style_tab.rs +231 -0
- package/src/rust/components/containers/dragdrop_list.rs +325 -0
- package/src/rust/components/containers/dropdown_menu.rs +104 -0
- package/src/rust/components/containers/kvpair.rs +47 -0
- package/src/rust/components/containers/mod.rs +28 -0
- package/src/rust/components/containers/scroll_panel.rs +311 -0
- package/src/rust/components/containers/scroll_panel_item.rs +111 -0
- package/src/rust/components/containers/select.rs +269 -0
- package/src/rust/components/containers/sidebar.rs +89 -0
- package/src/rust/components/containers/split_panel.rs +483 -0
- package/src/rust/components/containers/tab_list.rs +104 -0
- package/src/rust/components/containers/tests/mod.rs +11 -0
- package/src/rust/components/containers/tests/split_panel.rs +91 -0
- package/src/rust/components/containers/trap_door_panel.rs +50 -0
- package/src/rust/components/copy_dropdown.rs +136 -0
- package/src/rust/components/datetime_column_style/custom.rs +222 -0
- package/src/rust/components/datetime_column_style/simple.rs +122 -0
- package/src/rust/components/datetime_column_style.rs +284 -0
- package/src/rust/components/editable_header.rs +183 -0
- package/src/rust/components/empty_row.rs +169 -0
- package/src/rust/components/error_message.rs +56 -0
- package/src/rust/components/export_dropdown.rs +153 -0
- package/src/rust/components/expression_editor.rs +153 -0
- package/src/rust/components/filter_dropdown.rs +144 -0
- package/src/rust/components/font_loader.rs +254 -0
- package/src/rust/components/form/code_editor.rs +286 -0
- package/src/rust/components/form/color_range_selector.rs +115 -0
- package/src/rust/components/form/color_selector.rs +54 -0
- package/src/rust/components/form/debug.rs +253 -0
- package/src/rust/components/form/highlight.rs +50 -0
- package/src/rust/components/form/mod.rs +29 -0
- package/src/rust/components/form/number_field.rs +72 -0
- package/src/rust/components/form/number_input.rs +45 -0
- package/src/rust/components/form/number_range_field.rs +77 -0
- package/src/rust/components/form/optional_field.rs +53 -0
- package/src/rust/components/form/select_field.rs +104 -0
- package/src/rust/components/function_dropdown.rs +151 -0
- package/src/rust/components/mod.rs +45 -0
- package/src/rust/components/modal.rs +171 -0
- package/src/rust/components/number_column_style.rs +522 -0
- package/src/rust/components/plugin_selector.rs +196 -0
- package/src/rust/components/render_warning.rs +178 -0
- package/src/rust/components/status_bar.rs +315 -0
- package/src/rust/components/status_bar_counter.rs +229 -0
- package/src/rust/components/status_indicator.rs +164 -0
- package/src/rust/components/string_column_style.rs +186 -0
- package/src/rust/components/style/local_style.rs +35 -0
- package/src/rust/components/style/mod.rs +52 -0
- package/src/rust/components/style/style_cache.rs +132 -0
- package/src/rust/components/style/style_provider.rs +65 -0
- package/src/rust/components/style_controls/number_string_format/digits_section.rs +140 -0
- package/src/rust/components/style_controls/number_string_format/misc_section.rs +56 -0
- package/src/rust/components/style_controls/number_string_format/style_section.rs +69 -0
- package/src/rust/components/style_controls/number_string_format/types.rs +31 -0
- package/src/rust/components/style_controls/number_string_format.rs +259 -0
- package/src/rust/components/style_controls.rs +15 -0
- package/src/rust/components/type_icon.rs +53 -0
- package/src/rust/components/viewer.rs +668 -0
- package/src/rust/config/columns_config.rs +132 -0
- package/src/rust/config/datetime_column_style/color_mode.rs +62 -0
- package/src/rust/config/datetime_column_style/custom.rs +121 -0
- package/src/rust/config/datetime_column_style/custom_format.rs +90 -0
- package/src/rust/config/datetime_column_style/simple.rs +55 -0
- package/src/rust/config/datetime_column_style/simple_format.rs +86 -0
- package/src/rust/config/datetime_column_style.rs +104 -0
- package/src/rust/config/mod.rs +30 -0
- package/src/rust/config/number_column_style.rs +138 -0
- package/src/rust/config/number_string_format/enums.rs +298 -0
- package/src/rust/config/number_string_format.rs +269 -0
- package/src/rust/config/string_column_style.rs +140 -0
- package/src/rust/config/view_config.rs +24 -0
- package/src/rust/config/viewer_config.rs +337 -0
- package/src/rust/custom_elements/column_dropdown.rs +123 -0
- package/src/rust/custom_elements/copy_dropdown.rs +112 -0
- package/src/rust/custom_elements/debug_plugin.rs +114 -0
- package/src/rust/custom_elements/export_dropdown.rs +112 -0
- package/src/rust/custom_elements/filter_dropdown.rs +179 -0
- package/src/rust/custom_elements/function_dropdown.rs +115 -0
- package/src/rust/custom_elements/mod.rs +24 -0
- package/src/rust/custom_elements/modal.rs +395 -0
- package/src/rust/custom_elements/viewer.rs +880 -0
- package/src/rust/custom_events.rs +214 -0
- package/src/rust/dragdrop.rs +362 -0
- package/src/rust/exprtk/cursor.rs +81 -0
- package/src/rust/exprtk/mod.rs +17 -0
- package/src/rust/exprtk/tokenize/comment.rs +21 -0
- package/src/rust/exprtk/tokenize/number.rs +44 -0
- package/src/rust/exprtk/tokenize/string.rs +98 -0
- package/src/rust/exprtk/tokenize/symbol.rs +26 -0
- package/src/rust/exprtk/tokenize.rs +190 -0
- package/src/rust/js/clipboard.rs +77 -0
- package/src/rust/js/clipboard_item.rs +21 -0
- package/src/rust/js/intersection_observer.rs +32 -0
- package/src/rust/js/mimetype.rs +42 -0
- package/src/rust/js/mod.rs +29 -0
- package/src/rust/js/plugin.rs +167 -0
- package/src/rust/js/resize_observer.rs +37 -0
- package/src/rust/js/testing.rs +149 -0
- package/src/rust/lib.rs +116 -0
- package/src/rust/model/columns_iter_set.rs +340 -0
- package/src/rust/model/copy_export.rs +157 -0
- package/src/rust/model/create_col.rs +59 -0
- package/src/rust/model/edit_expression.rs +95 -0
- package/src/rust/model/export_app.rs +58 -0
- package/src/rust/model/export_method.rs +151 -0
- package/src/rust/model/get_viewer_config.rs +85 -0
- package/src/rust/model/intersection_observer.rs +81 -0
- package/src/rust/model/is_invalid_drop.rs +36 -0
- package/src/rust/model/mod.rs +93 -0
- package/src/rust/model/plugin_column_styles.rs +106 -0
- package/src/rust/model/resize_observer.rs +98 -0
- package/src/rust/model/restore_and_render.rs +113 -0
- package/src/rust/model/structural.rs +73 -0
- package/src/rust/model/update_and_render.rs +74 -0
- package/src/rust/presentation.rs +370 -0
- package/src/rust/renderer/activate.rs +49 -0
- package/src/rust/renderer/limits.rs +200 -0
- package/src/rust/renderer/plugin_store.rs +45 -0
- package/src/rust/renderer/registry.rs +135 -0
- package/src/rust/renderer/render_timer.rs +185 -0
- package/src/rust/renderer.rs +463 -0
- package/src/rust/session/column_defaults_update.rs +141 -0
- package/src/rust/session/drag_drop_update.rs +179 -0
- package/src/rust/session/metadata.rs +308 -0
- package/src/rust/session/replace_expression_update.rs +131 -0
- package/src/rust/session/view_subscription.rs +189 -0
- package/src/rust/session.rs +794 -0
- package/src/rust/utils/browser/blob.rs +49 -0
- package/src/rust/utils/browser/download.rs +26 -0
- package/src/rust/utils/browser/mod.rs +24 -0
- package/src/rust/utils/browser/request_animation_frame.rs +76 -0
- package/src/rust/utils/browser/selection.rs +79 -0
- package/src/rust/utils/browser/tests/debounce.rs +114 -0
- package/src/rust/utils/browser/tests/mod.rs +13 -0
- package/src/rust/utils/custom_element.rs +85 -0
- package/src/rust/utils/datetime.rs +49 -0
- package/src/rust/utils/debounce.rs +54 -0
- package/src/rust/utils/hooks/mod.rs +15 -0
- package/src/rust/utils/hooks/use_async_callback.rs +53 -0
- package/src/rust/utils/mod.rs +114 -0
- package/src/rust/utils/number_format.rs +48 -0
- package/src/rust/utils/pubsub.rs +222 -0
- package/src/rust/utils/scope.rs +54 -0
- package/src/rust/utils/tee.rs +88 -0
- package/src/rust/utils/tests/mod.rs +14 -0
- package/src/rust/utils/tests/pubsub.rs +95 -0
- package/src/rust/utils/tests/request_animation_frame.rs +42 -0
- package/src/rust/utils/wasm_abi.rs +61 -0
- package/src/rust/utils/weak_scope.rs +39 -0
- package/src/svg/align-scroll-icon.svg +7 -0
- package/src/svg/bg-pattern.png +0 -0
- package/src/svg/boolean-type.svg +3 -0
- package/src/svg/checkbox-checked-icon.svg +7 -0
- package/src/svg/checkbox-hover.svg +4 -0
- package/src/svg/checkbox-off.svg +4 -0
- package/src/svg/checkbox-on.svg +4 -0
- package/src/svg/checkbox-unchecked-icon.svg +3 -0
- package/src/svg/close-icon.svg +6 -0
- package/src/svg/column-settings-icon.svg +6 -0
- package/src/svg/datagrid-select-column.svg +15 -0
- package/src/svg/datagrid-select-region.svg +15 -0
- package/src/svg/datagrid-select-row.svg +13 -0
- package/src/svg/datagrid.svg +13 -0
- package/src/svg/date-type.svg +23 -0
- package/src/svg/downloading.gif +0 -0
- package/src/svg/drag-handle.svg +10 -0
- package/src/svg/drawer-bg-pattern-hidpi.png +0 -0
- package/src/svg/drawer-tab-hover.svg +8 -0
- package/src/svg/drawer-tab-invert-hover.svg +9 -0
- package/src/svg/drawer-tab-invert.svg +8 -0
- package/src/svg/drawer-tab.svg +7 -0
- package/src/svg/dropdown-selector-light.svg +3 -0
- package/src/svg/dropdown-selector.svg +3 -0
- package/src/svg/duplicate-icon.svg +4 -0
- package/src/svg/editable-icon.svg +5 -0
- package/src/svg/export-icon.svg +4 -0
- package/src/svg/expression.svg +10 -0
- package/src/svg/free-scroll-icon.svg +5 -0
- package/src/svg/inactive-mouseover.svg +4 -0
- package/src/svg/mega-menu-icons-candlestick.svg +38 -0
- package/src/svg/mega-menu-icons-datagrid.svg +38 -0
- package/src/svg/mega-menu-icons-heatmap.svg +60 -0
- package/src/svg/mega-menu-icons-map-scatter.svg +43 -0
- package/src/svg/mega-menu-icons-ohlc.svg +40 -0
- package/src/svg/mega-menu-icons-sunburst.svg +39 -0
- package/src/svg/mega-menu-icons-treemap.svg +44 -0
- package/src/svg/mega-menu-icons-x-bar.svg +36 -0
- package/src/svg/mega-menu-icons-x-y-line.svg +38 -0
- package/src/svg/mega-menu-icons-x-y-scatter.svg +72 -0
- package/src/svg/mega-menu-icons-y-area.svg +73 -0
- package/src/svg/mega-menu-icons-y-bar.svg +36 -0
- package/src/svg/mega-menu-icons-y-line.svg +36 -0
- package/src/svg/mega-menu-icons-y-scatter.svg +72 -0
- package/src/svg/number-type.svg +4 -0
- package/src/svg/radio-hover.svg +4 -0
- package/src/svg/radio-off.svg +3 -0
- package/src/svg/radio-on.svg +4 -0
- package/src/svg/read-only-icon.svg +6 -0
- package/src/svg/revert-icon.svg +4 -0
- package/src/svg/sort-abs-asc-icon.svg +3 -0
- package/src/svg/sort-abs-col-asc-icon.svg +3 -0
- package/src/svg/sort-abs-col-desc-icon.svg +3 -0
- package/src/svg/sort-abs-desc-icon.svg +3 -0
- package/src/svg/sort-asc-icon.svg +4 -0
- package/src/svg/sort-col-asc-icon.svg +4 -0
- package/src/svg/sort-col-desc-icon.svg +4 -0
- package/src/svg/sort-desc-icon.svg +4 -0
- package/src/svg/sort-none-icon.svg +3 -0
- package/src/svg/status_error.svg +70 -0
- package/src/svg/status_ok.svg +26 -0
- package/src/svg/string-type.svg +8 -0
- package/src/svg/theme-icon.svg +5 -0
- package/src/svg/updating.gif +0 -0
- package/src/themes/dracula.less +101 -0
- package/src/themes/gruvbox-dark.less +116 -0
- package/src/themes/gruvbox.less +152 -0
- package/src/themes/icons.less +130 -0
- package/src/themes/intl/de.less +102 -0
- package/src/themes/intl/es.less +102 -0
- package/src/themes/intl/fr.less +102 -0
- package/src/themes/intl/ja.less +102 -0
- package/src/themes/intl/pt.less +102 -0
- package/src/themes/intl/zh.less +102 -0
- package/src/themes/intl.less +102 -0
- package/src/themes/monokai.less +107 -0
- package/src/themes/pro-dark.less +147 -0
- package/src/themes/pro.less +186 -0
- package/src/themes/solarized-dark.less +78 -0
- package/src/themes/solarized.less +102 -0
- package/src/themes/themes.less +21 -0
- package/src/themes/vaporwave.less +145 -0
- package/src/themes/variables.less +24 -0
- package/src/ts/bootstrap.ts +26 -0
- package/src/ts/extensions.ts +124 -0
- package/src/ts/perspective-viewer.cdn.ts +19 -0
- package/src/ts/perspective-viewer.inline.ts +23 -0
- package/src/ts/perspective-viewer.ts +59 -0
- package/src/ts/plugin.ts +279 -0
- package/src/ts/ts-rs/Aggregate.ts +3 -0
- package/src/ts/ts-rs/ColumnConfigValues.ts +14 -0
- package/src/ts/ts-rs/CustomDatetimeFormat.ts +3 -0
- package/src/ts/ts-rs/CustomDatetimeStyleConfig.ts +5 -0
- package/src/ts/ts-rs/CustomNumberFormatConfig.ts +8 -0
- package/src/ts/ts-rs/DatetimeColorMode.ts +3 -0
- package/src/ts/ts-rs/DatetimeFormatType.ts +8 -0
- package/src/ts/ts-rs/Expressions.ts +3 -0
- package/src/ts/ts-rs/Filter.ts +4 -0
- package/src/ts/ts-rs/FilterReducer.ts +3 -0
- package/src/ts/ts-rs/FilterTerm.ts +4 -0
- package/src/ts/ts-rs/FormatMode.ts +3 -0
- package/src/ts/ts-rs/FormatUnit.ts +3 -0
- package/src/ts/ts-rs/NumberBackgroundMode.ts +3 -0
- package/src/ts/ts-rs/NumberForegroundMode.ts +3 -0
- package/src/ts/ts-rs/OnUpdateData.ts +8 -0
- package/src/ts/ts-rs/OptionalUpdate.ts +3 -0
- package/src/ts/ts-rs/PluginConfig.ts +4 -0
- package/src/ts/ts-rs/RoundingMode.ts +3 -0
- package/src/ts/ts-rs/RoundingPriority.ts +3 -0
- package/src/ts/ts-rs/Scalar.ts +7 -0
- package/src/ts/ts-rs/SignDisplay.ts +3 -0
- package/src/ts/ts-rs/SimpleDatetimeFormat.ts +3 -0
- package/src/ts/ts-rs/SimpleDatetimeStyleConfig.ts +4 -0
- package/src/ts/ts-rs/Sort.ts +4 -0
- package/src/ts/ts-rs/SortDir.ts +3 -0
- package/src/ts/ts-rs/StringColorMode.ts +3 -0
- package/src/ts/ts-rs/TrailingZeroDisplay.ts +3 -0
- package/src/ts/ts-rs/UseGrouping.ts +3 -0
- package/src/ts/ts-rs/ViewOnUpdateResp.ts +3 -0
- package/src/ts/ts-rs/ViewerConfigUpdate.ts +90 -0
- package/src/ts/ts-rs/serde_json/JsonValue.ts +3 -0
- 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::*;
|