@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,53 @@
|
|
|
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 wasm_bindgen::__rt::IntoJsResult;
|
|
14
|
+
use wasm_bindgen_futures::future_to_promise;
|
|
15
|
+
use yew::prelude::*;
|
|
16
|
+
|
|
17
|
+
use crate::renderer::*;
|
|
18
|
+
use crate::session::*;
|
|
19
|
+
use crate::*;
|
|
20
|
+
|
|
21
|
+
#[derive(Clone, Properties, PartialEq)]
|
|
22
|
+
pub struct StatusIndicatorProps {
|
|
23
|
+
pub session: Session,
|
|
24
|
+
pub renderer: Renderer,
|
|
25
|
+
pub children: Children,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// Just like `use_callback`, except convenient for an async cresult body.
|
|
29
|
+
#[hook]
|
|
30
|
+
pub fn use_async_callback<IN, OUT, F, D>(deps: D, f: F) -> Callback<IN, ()>
|
|
31
|
+
where
|
|
32
|
+
IN: Clone + 'static,
|
|
33
|
+
OUT: IntoJsResult + 'static,
|
|
34
|
+
F: AsyncFn(IN, &D) -> OUT + 'static,
|
|
35
|
+
D: Clone + PartialEq + 'static,
|
|
36
|
+
{
|
|
37
|
+
let deps = std::rc::Rc::new(deps);
|
|
38
|
+
let f = std::rc::Rc::new(f);
|
|
39
|
+
(*use_memo(deps, move |deps| {
|
|
40
|
+
let deps = deps.clone();
|
|
41
|
+
let ff = move |value: IN| {
|
|
42
|
+
let value = value.clone();
|
|
43
|
+
let f = f.clone();
|
|
44
|
+
let deps = deps.clone();
|
|
45
|
+
let _ = future_to_promise(async move {
|
|
46
|
+
f(value, &deps).await.into_js_result()?;
|
|
47
|
+
Ok(JsValue::UNDEFINED)
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
Callback::from(ff)
|
|
51
|
+
}))
|
|
52
|
+
.clone()
|
|
53
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
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
|
+
//! A catch all for project-wide macros and general-purpose functions that are
|
|
14
|
+
//! not directly related to Perspective.
|
|
15
|
+
//!
|
|
16
|
+
//! Modules below `crate::utils` strive to be single-responsibility, but some
|
|
17
|
+
//! reference other `crate::utils` modules when it helps reduce boiler-plate.
|
|
18
|
+
|
|
19
|
+
mod browser;
|
|
20
|
+
|
|
21
|
+
mod custom_element;
|
|
22
|
+
mod datetime;
|
|
23
|
+
mod debounce;
|
|
24
|
+
mod hooks;
|
|
25
|
+
mod number_format;
|
|
26
|
+
mod pubsub;
|
|
27
|
+
mod scope;
|
|
28
|
+
mod tee;
|
|
29
|
+
mod wasm_abi;
|
|
30
|
+
mod weak_scope;
|
|
31
|
+
|
|
32
|
+
#[cfg(test)]
|
|
33
|
+
mod tests;
|
|
34
|
+
|
|
35
|
+
pub use browser::*;
|
|
36
|
+
pub use custom_element::*;
|
|
37
|
+
pub use datetime::*;
|
|
38
|
+
pub use debounce::*;
|
|
39
|
+
pub use hooks::*;
|
|
40
|
+
pub use number_format::*;
|
|
41
|
+
pub use perspective_client::clone;
|
|
42
|
+
pub use pubsub::*;
|
|
43
|
+
pub use scope::*;
|
|
44
|
+
pub use tee::*;
|
|
45
|
+
pub use weak_scope::*;
|
|
46
|
+
|
|
47
|
+
#[macro_export]
|
|
48
|
+
macro_rules! maybe {
|
|
49
|
+
($($exp:stmt);*) => {{
|
|
50
|
+
let x = ({
|
|
51
|
+
#[inline(always)]
|
|
52
|
+
|| {
|
|
53
|
+
$($exp)*
|
|
54
|
+
}
|
|
55
|
+
})();
|
|
56
|
+
x
|
|
57
|
+
}};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
#[macro_export]
|
|
61
|
+
macro_rules! js_log_maybe {
|
|
62
|
+
($($exp:tt)+) => {{
|
|
63
|
+
let x = ({
|
|
64
|
+
#[inline(always)]
|
|
65
|
+
|| {
|
|
66
|
+
{
|
|
67
|
+
$($exp)+
|
|
68
|
+
};
|
|
69
|
+
Ok(())
|
|
70
|
+
}
|
|
71
|
+
})();
|
|
72
|
+
x.unwrap_or_else(|e| web_sys::console::warn_1(&e))
|
|
73
|
+
}};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
#[macro_export]
|
|
77
|
+
macro_rules! max {
|
|
78
|
+
($x:expr) => ($x);
|
|
79
|
+
($x:expr, $($z:expr),+ $(,)?) => {{
|
|
80
|
+
let x = $x;
|
|
81
|
+
let y = max!($($z),*);
|
|
82
|
+
if x > y {
|
|
83
|
+
x
|
|
84
|
+
} else {
|
|
85
|
+
y
|
|
86
|
+
}
|
|
87
|
+
}}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
#[macro_export]
|
|
91
|
+
macro_rules! min {
|
|
92
|
+
($x:expr) => ($x);
|
|
93
|
+
($x:expr, $($z:expr),+ $(,)?) => {{
|
|
94
|
+
let x = $x;
|
|
95
|
+
let y = min!($($z),*);
|
|
96
|
+
if x < y {
|
|
97
|
+
x
|
|
98
|
+
} else {
|
|
99
|
+
y
|
|
100
|
+
}
|
|
101
|
+
}}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
#[macro_export]
|
|
105
|
+
macro_rules! js_log {
|
|
106
|
+
($x:expr) => {{
|
|
107
|
+
const DEBUG_ONLY_WARNING: &str = $x;
|
|
108
|
+
web_sys::console::log_1(&wasm_bindgen::JsValue::from($x));
|
|
109
|
+
}};
|
|
110
|
+
($x:expr $(, $y:expr)*) => {{
|
|
111
|
+
const DEBUG_ONLY_WARNING: &str = $x;
|
|
112
|
+
web_sys::console::log_1(&format!($x, $($y),*).into());
|
|
113
|
+
}};
|
|
114
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
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::sync::LazyLock;
|
|
14
|
+
|
|
15
|
+
use js_sys::Intl;
|
|
16
|
+
use perspective_js::json;
|
|
17
|
+
use perspective_js::utils::global::navigator;
|
|
18
|
+
use wasm_bindgen::JsValue;
|
|
19
|
+
|
|
20
|
+
pub trait ToFormattedString {
|
|
21
|
+
fn to_formatted_string(&self) -> String;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
struct UnsafeNumberFormat(Intl::NumberFormat);
|
|
25
|
+
|
|
26
|
+
unsafe impl Send for UnsafeNumberFormat {}
|
|
27
|
+
unsafe impl Sync for UnsafeNumberFormat {}
|
|
28
|
+
|
|
29
|
+
static NUMBER_FORMAT: LazyLock<UnsafeNumberFormat> = LazyLock::new(|| {
|
|
30
|
+
let locale = navigator().languages();
|
|
31
|
+
let opts = json!({});
|
|
32
|
+
let number_format = Intl::NumberFormat::new(&locale, &opts);
|
|
33
|
+
UnsafeNumberFormat(number_format)
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
impl UnsafeNumberFormat {}
|
|
37
|
+
|
|
38
|
+
impl ToFormattedString for u32 {
|
|
39
|
+
fn to_formatted_string(&self) -> String {
|
|
40
|
+
NUMBER_FORMAT
|
|
41
|
+
.0
|
|
42
|
+
.format()
|
|
43
|
+
.call1(&NUMBER_FORMAT.0, &JsValue::from_f64(*self as f64))
|
|
44
|
+
.unwrap()
|
|
45
|
+
.as_string()
|
|
46
|
+
.unwrap()
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
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::{Cell, RefCell};
|
|
14
|
+
use std::collections::HashMap;
|
|
15
|
+
use std::rc::{Rc, Weak};
|
|
16
|
+
|
|
17
|
+
use derivative::Derivative;
|
|
18
|
+
use futures::channel::oneshot::*;
|
|
19
|
+
use yew::prelude::*;
|
|
20
|
+
|
|
21
|
+
/// An internal `HashSet` variant which supports unconstrained `T` e.g.
|
|
22
|
+
/// without `Hash`, via returning a unique `usize` index for each insert
|
|
23
|
+
/// which can be used for a reciprocal `remove(x: usize)`.
|
|
24
|
+
#[derive(Derivative)]
|
|
25
|
+
#[derivative(Default(bound = ""))]
|
|
26
|
+
struct IndexedSet<T> {
|
|
27
|
+
set: HashMap<usize, T>,
|
|
28
|
+
gen_: usize,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
impl<T> IndexedSet<T> {
|
|
32
|
+
fn insert(&mut self, v: T) -> usize {
|
|
33
|
+
let key = self.gen_;
|
|
34
|
+
self.set.insert(key, v);
|
|
35
|
+
self.gen_ += 1;
|
|
36
|
+
key
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
fn remove(&mut self, key: usize) {
|
|
40
|
+
self.set.remove(&key);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
fn iter(&self) -> impl Iterator<Item = &T> {
|
|
44
|
+
self.set.values()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
fn drain(&mut self) -> impl Iterator<Item = T> {
|
|
48
|
+
let mut x = Box::default();
|
|
49
|
+
std::mem::swap(&mut self.set, &mut x);
|
|
50
|
+
x.into_values()
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
type ListenerSet<T> = IndexedSet<Box<dyn Fn(T) + 'static>>;
|
|
55
|
+
type ListenerOnceSet<T> = IndexedSet<Box<dyn FnOnce(T) + 'static>>;
|
|
56
|
+
|
|
57
|
+
#[derive(Derivative)]
|
|
58
|
+
#[derivative(Default(bound = ""))]
|
|
59
|
+
pub struct PubSubInternal<T: Clone> {
|
|
60
|
+
deleted: Cell<bool>,
|
|
61
|
+
listeners: RefCell<ListenerSet<T>>,
|
|
62
|
+
once_listeners: RefCell<ListenerOnceSet<T>>,
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
impl<T: Clone> PubSubInternal<T> {
|
|
66
|
+
fn emit(&self, val: T) {
|
|
67
|
+
if self.deleted.get() {
|
|
68
|
+
tracing::warn!("`Callback` invoked after `PubSub` dropped");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
for listener in self.listeners.borrow().iter() {
|
|
72
|
+
listener(val.clone());
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
for listener in self.once_listeners.borrow_mut().drain() {
|
|
76
|
+
listener(val.clone());
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// A pub/sub struct which allows many listeners to subscribe to many
|
|
82
|
+
/// publishers, without leaking callbacks as listeners are dropped.
|
|
83
|
+
///
|
|
84
|
+
/// Unlike `mpsc` etc., `PubSub` has no internal queue and is completely
|
|
85
|
+
/// synchronous.
|
|
86
|
+
#[derive(Derivative)]
|
|
87
|
+
#[derivative(Default(bound = ""))]
|
|
88
|
+
pub struct PubSub<T: Clone>(Rc<PubSubInternal<T>>);
|
|
89
|
+
|
|
90
|
+
unsafe impl<T: Clone> Send for PubSub<T> {}
|
|
91
|
+
unsafe impl<T: Clone> Sync for PubSub<T> {}
|
|
92
|
+
|
|
93
|
+
pub trait AddListener<T> {
|
|
94
|
+
/// Register a listener to this `PubSub<_>`, which will be automatically
|
|
95
|
+
/// deregistered when the return `Subscription` is dropped.
|
|
96
|
+
///
|
|
97
|
+
/// # Arguments
|
|
98
|
+
/// - `f` The callback, presumably a function-like type.
|
|
99
|
+
fn add_listener(&self, f: T) -> Subscription;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
impl<T: Clone + 'static> PubSub<T> {
|
|
103
|
+
/// Emit a value to all listeners.
|
|
104
|
+
///
|
|
105
|
+
/// # Arguments
|
|
106
|
+
/// - `val` The value to emit.
|
|
107
|
+
pub fn emit(&self, val: T) {
|
|
108
|
+
self.0.emit(val);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/// Get this `PubSub<_>`'s `.emit_all()` method as a `Callback<T>`.
|
|
112
|
+
pub fn callback(&self) -> Callback<T> {
|
|
113
|
+
let internal = self.0.clone();
|
|
114
|
+
Callback::from(move |val: T| internal.emit(val))
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
pub fn as_boxfn(&self) -> Box<dyn Fn(T) + Send + Sync + 'static> {
|
|
118
|
+
let internal = PubSub(self.0.clone());
|
|
119
|
+
Box::new(move |val: T| internal.emit(val))
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/// Await this `PubSub<_>`'s next call to `emit_all()`, once.
|
|
123
|
+
pub async fn listen_once(&self) -> Result<T, Canceled> {
|
|
124
|
+
let (sender, receiver) = channel::<T>();
|
|
125
|
+
let f = move |x| sender.send(x).unwrap_or(());
|
|
126
|
+
self.0.once_listeners.borrow_mut().insert(Box::new(f));
|
|
127
|
+
receiver.await
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/// Create a `Subscriber` from this `PubSub`, which is the reciprocal of
|
|
131
|
+
/// `PubSub::callback` (a struct which only allows sending), a struct which
|
|
132
|
+
/// only allows receiving via `Subscriber::add_listener`.
|
|
133
|
+
pub fn subscriber(&self) -> Subscriber<T> {
|
|
134
|
+
Subscriber(Rc::<PubSubInternal<T>>::downgrade(&self.0))
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
impl<T: Clone> Drop for PubSub<T> {
|
|
139
|
+
fn drop(&mut self) {
|
|
140
|
+
self.0.deleted.set(true);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
impl<T: Clone + 'static> AddListener<Callback<T>> for PubSub<T> {
|
|
145
|
+
fn add_listener(&self, f: Callback<T>) -> Subscription {
|
|
146
|
+
let internal = self.0.clone();
|
|
147
|
+
let cb = Box::new(move |x| f.emit(x));
|
|
148
|
+
let key = self.0.listeners.borrow_mut().insert(cb);
|
|
149
|
+
Subscription(Box::new(move || {
|
|
150
|
+
internal.listeners.borrow_mut().remove(key)
|
|
151
|
+
}))
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
impl<T, U> AddListener<U> for PubSub<T>
|
|
156
|
+
where
|
|
157
|
+
T: Clone + 'static,
|
|
158
|
+
U: Fn(T) + 'static,
|
|
159
|
+
{
|
|
160
|
+
fn add_listener(&self, f: U) -> Subscription {
|
|
161
|
+
let internal = self.0.clone();
|
|
162
|
+
let key = self.0.listeners.borrow_mut().insert(Box::new(f));
|
|
163
|
+
Subscription(Box::new(move || {
|
|
164
|
+
internal.listeners.borrow_mut().remove(key)
|
|
165
|
+
}))
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/// Like a `PubSub` without `PubSub::emit`; the reciprocal of
|
|
170
|
+
/// `PubSub::callback`. `Subscriber` does not keep the parent `PubSub` alive.
|
|
171
|
+
#[derive(Clone)]
|
|
172
|
+
pub struct Subscriber<T: Clone>(Weak<PubSubInternal<T>>);
|
|
173
|
+
|
|
174
|
+
impl<T, U> AddListener<U> for Subscriber<T>
|
|
175
|
+
where
|
|
176
|
+
T: Clone + 'static,
|
|
177
|
+
U: Fn(T) + 'static,
|
|
178
|
+
{
|
|
179
|
+
fn add_listener(&self, f: U) -> Subscription {
|
|
180
|
+
if let Some(internal) = self.0.upgrade() {
|
|
181
|
+
let key = internal.listeners.borrow_mut().insert(Box::new(f));
|
|
182
|
+
Subscription(Box::new(move || {
|
|
183
|
+
internal.listeners.borrow_mut().remove(key)
|
|
184
|
+
}))
|
|
185
|
+
} else {
|
|
186
|
+
Subscription(Box::new(|| {}))
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
impl<T: Clone> Default for Subscriber<T> {
|
|
192
|
+
fn default() -> Self {
|
|
193
|
+
Self(Weak::new())
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
impl<T: Clone> PartialEq for Subscriber<T> {
|
|
198
|
+
fn eq(&self, other: &Self) -> bool {
|
|
199
|
+
match (self.0.upgrade(), other.0.upgrade()) {
|
|
200
|
+
(Some(x), Some(y)) => std::ptr::eq(
|
|
201
|
+
&*x as *const PubSubInternal<T>,
|
|
202
|
+
&*y as *const PubSubInternal<T>,
|
|
203
|
+
),
|
|
204
|
+
(None, None) => true,
|
|
205
|
+
_ => false,
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/// Manages the lifetime of a listener registered to a `PubSub<T>` by
|
|
211
|
+
/// deregistering the associated listener when dropped.
|
|
212
|
+
///
|
|
213
|
+
/// The wrapped `Fn` of `Subscriptions` is the deregister closure provided by
|
|
214
|
+
/// the issuing `PubSub<T>`.
|
|
215
|
+
#[must_use]
|
|
216
|
+
pub struct Subscription(Box<dyn Fn()>);
|
|
217
|
+
|
|
218
|
+
impl Drop for Subscription {
|
|
219
|
+
fn drop(&mut self) {
|
|
220
|
+
(*self.0)();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
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 extend::ext;
|
|
14
|
+
use futures::channel::oneshot::*;
|
|
15
|
+
use perspective_js::utils::ApiResult;
|
|
16
|
+
use yew::html::Scope;
|
|
17
|
+
use yew::prelude::*;
|
|
18
|
+
|
|
19
|
+
#[ext]
|
|
20
|
+
pub impl<T> Scope<T>
|
|
21
|
+
where
|
|
22
|
+
T: Component,
|
|
23
|
+
{
|
|
24
|
+
/// Send a message with a callback, then suspend until the callback is
|
|
25
|
+
/// invoked.
|
|
26
|
+
fn send_message_async<F, U>(&self, f: F) -> Receiver<U>
|
|
27
|
+
where
|
|
28
|
+
F: FnOnce(Sender<U>) -> T::Message,
|
|
29
|
+
{
|
|
30
|
+
let (sender, receiver) = channel::<U>();
|
|
31
|
+
self.send_message(f(sender));
|
|
32
|
+
receiver
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
#[ext]
|
|
37
|
+
pub(crate) impl<T> Callback<Sender<T>>
|
|
38
|
+
where
|
|
39
|
+
T: 'static,
|
|
40
|
+
{
|
|
41
|
+
/// This is "safe" because `emit()` is not called synchronously. Normally
|
|
42
|
+
/// we want this to minimize the async by doing as much work synchronous
|
|
43
|
+
/// as possible (see `send_message_async()` e.g.), but this method calls
|
|
44
|
+
/// `Yew` which _never_ wants to be called synchronously.
|
|
45
|
+
///
|
|
46
|
+
/// TODO Need test coverage for this - error behavior is that presize/render
|
|
47
|
+
/// blocking calls are out-of-order, e.g. toggle config `presize()` call.
|
|
48
|
+
/// Engineering the test to capture this faulty behavior may be difficult
|
|
49
|
+
async fn emit_async_safe(&self) -> ApiResult<T> {
|
|
50
|
+
let (sender, receiver) = channel::<T>();
|
|
51
|
+
self.emit(sender);
|
|
52
|
+
Ok(receiver.await?)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
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
|
+
/// Trait for polymorphic return value via turbofish-const-generic syntax.
|
|
14
|
+
///
|
|
15
|
+
/// The associated type `Output` is a functional dependency of the const generic
|
|
16
|
+
/// parameter `N`, so there's typically no need to specify this parameter when
|
|
17
|
+
/// invoking, which is what we want - this parameter is quite verbose and
|
|
18
|
+
/// repetitive (see below), vs `N` which is a single character.
|
|
19
|
+
pub trait TeeInternal<const N: usize> {
|
|
20
|
+
type Output: Clone;
|
|
21
|
+
fn tee_internal(self) -> Self::Output;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
pub trait Tee {
|
|
25
|
+
/// Extension method to add `tee()` method to all `T: Clone`.
|
|
26
|
+
///
|
|
27
|
+
/// This can't be done directly as part of `TeeInternal` because it makes
|
|
28
|
+
/// specifying the const param at the `tee()` invocation site
|
|
29
|
+
/// cumbersome: `TeeInternal::<N>::tee(&obj)` as opposed to
|
|
30
|
+
/// `obj.tee::<N>()`. The constraint `Self: TeeInternal<N>` collapses
|
|
31
|
+
/// the potential `impl` matches to exactly 1, which makes the call to
|
|
32
|
+
/// `tee_internal()` unambiguous. This constraint is also allowed to
|
|
33
|
+
/// contain the generic parameter `N` because it is specified as a
|
|
34
|
+
/// constraint to the method (as opposed to a constraint on the trait).
|
|
35
|
+
/// I'm honestly quite surprised this works ...
|
|
36
|
+
///
|
|
37
|
+
/// # Examples
|
|
38
|
+
///
|
|
39
|
+
/// ```
|
|
40
|
+
/// let x = "test".tee::<2>();
|
|
41
|
+
/// assert_eq!(x.0, x.1);
|
|
42
|
+
/// assert_eq!(x.0, "test");
|
|
43
|
+
/// ```
|
|
44
|
+
fn tee<const N: usize>(self) -> <Self as TeeInternal<N>>::Output
|
|
45
|
+
where
|
|
46
|
+
Self: TeeInternal<N>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
impl<T: Clone> Tee for T {
|
|
50
|
+
fn tee<const N: usize>(self) -> <Self as TeeInternal<N>>::Output
|
|
51
|
+
where
|
|
52
|
+
Self: TeeInternal<N>,
|
|
53
|
+
{
|
|
54
|
+
self.tee_internal()
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
macro_rules! gen_tee {
|
|
59
|
+
($($x:ty),*) => {
|
|
60
|
+
impl<T: Clone> TeeInternal<{${count($x)} + 1}> for T {
|
|
61
|
+
type Output = ($($x),*, T);
|
|
62
|
+
fn tee_internal(self) -> Self::Output {
|
|
63
|
+
($( ${ignore($x)} self.clone() ),*, self)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
gen_tee!(T);
|
|
70
|
+
gen_tee!(T, T);
|
|
71
|
+
gen_tee!(T, T, T);
|
|
72
|
+
gen_tee!(T, T, T, T);
|
|
73
|
+
gen_tee!(T, T, T, T, T);
|
|
74
|
+
gen_tee!(T, T, T, T, T, T);
|
|
75
|
+
gen_tee!(T, T, T, T, T, T, T);
|
|
76
|
+
gen_tee!(T, T, T, T, T, T, T, T);
|
|
77
|
+
|
|
78
|
+
#[cfg(test)]
|
|
79
|
+
mod tests {
|
|
80
|
+
use super::*;
|
|
81
|
+
|
|
82
|
+
#[test]
|
|
83
|
+
fn test_test1() {
|
|
84
|
+
let x = "test".tee::<2>();
|
|
85
|
+
assert_eq!(x.0, x.1);
|
|
86
|
+
assert_eq!(x.0, "test");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
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 pubsub;
|
|
14
|
+
mod request_animation_frame;
|