flexdesk 0.17.8 → 0.17.9
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/CHANGELOG.md +25 -0
- package/LICENSE +0 -0
- package/README.md +0 -0
- package/THIRD_PARTY_LICENSES.md +0 -0
- package/canvas.js +0 -0
- package/charts.js +0 -0
- package/core.js +0 -0
- package/css/base.css +21 -1
- package/css/flexdesk.css +21 -1
- package/css/overrides.css +0 -0
- package/css/reset.css +0 -0
- package/dist/canvas.js +0 -0
- package/dist/canvas.js.map +0 -0
- package/dist/charts.js +7 -6
- package/dist/charts.js.map +2 -2
- package/dist/{chunk-EIYNF4BD.js → chunk-2YTM3GJE.js} +2 -2
- package/dist/chunk-2YTM3GJE.js.map +7 -0
- package/dist/chunk-3PHCPZHT.js +0 -0
- package/dist/chunk-3PHCPZHT.js.map +0 -0
- package/dist/{chunk-UURZ37SD.js → chunk-7U4IB65H.js} +27 -9
- package/dist/chunk-7U4IB65H.js.map +7 -0
- package/dist/{chunk-D3COLZZ2.js → chunk-BE2PU3LL.js} +2 -2
- package/dist/{chunk-D3COLZZ2.js.map → chunk-BE2PU3LL.js.map} +0 -0
- package/dist/chunk-CVMCZZX2.js +0 -0
- package/dist/chunk-CVMCZZX2.js.map +0 -0
- package/dist/{chunk-UWO43BZU.js → chunk-F35XSQWA.js} +16 -20
- package/dist/chunk-F35XSQWA.js.map +7 -0
- package/dist/chunk-FOOS3T5L.js +0 -0
- package/dist/chunk-FOOS3T5L.js.map +0 -0
- package/dist/chunk-GOQLR5WR.js +0 -0
- package/dist/chunk-GOQLR5WR.js.map +0 -0
- package/dist/chunk-HNU6MM2B.js +0 -0
- package/dist/chunk-HNU6MM2B.js.map +0 -0
- package/dist/chunk-JKZLNKG6.js +0 -0
- package/dist/chunk-JKZLNKG6.js.map +0 -0
- package/dist/chunk-JYWURG5T.js +0 -0
- package/dist/chunk-JYWURG5T.js.map +0 -0
- package/dist/{chunk-RKNFBX5K.js → chunk-MIW7D6WC.js} +16 -4
- package/dist/{chunk-RKNFBX5K.js.map → chunk-MIW7D6WC.js.map} +2 -2
- package/dist/chunk-N7HC3ADV.js +0 -0
- package/dist/chunk-N7HC3ADV.js.map +0 -0
- package/dist/{chunk-LWV23YVE.js → chunk-NIJEJAZ7.js} +42 -18
- package/dist/chunk-NIJEJAZ7.js.map +7 -0
- package/dist/{chunk-HYJYYEPK.js → chunk-REJ5HLIM.js} +2 -2
- package/dist/{chunk-HYJYYEPK.js.map → chunk-REJ5HLIM.js.map} +0 -0
- package/dist/{chunk-WVFGV5FT.js → chunk-WUFLGETN.js} +39 -2
- package/dist/{chunk-WVFGV5FT.js.map → chunk-WUFLGETN.js.map} +3 -3
- package/dist/core.js +0 -0
- package/dist/core.js.map +0 -0
- package/dist/editor.js +2 -2
- package/dist/editor.js.map +0 -0
- package/dist/flexdesk.css +21 -1
- package/dist/flow.js +3 -3
- package/dist/flow.js.map +0 -0
- package/dist/host.js +0 -0
- package/dist/host.js.map +0 -0
- package/dist/reset.css +0 -0
- package/dist/tile_registry-6WZPTUZV.js +0 -0
- package/dist/tile_registry-6WZPTUZV.js.map +0 -0
- package/dist/tiles.js +63 -20
- package/dist/tiles.js.map +2 -2
- package/dist/widgets.js +6 -6
- package/dist/widgets.js.map +0 -0
- package/dist/wm.js +5 -5
- package/dist/wm.js.map +0 -0
- package/docs/README.md +0 -0
- package/docs/best-practices.md +0 -0
- package/docs/components/charts.md +29 -0
- package/docs/components/command-palette.md +0 -0
- package/docs/components/conversation.md +0 -0
- package/docs/components/data-table-grid.md +0 -0
- package/docs/components/data-table.md +0 -0
- package/docs/components/editor.md +0 -0
- package/docs/components/flow-canvas-editor.md +0 -0
- package/docs/components/flow-editors.md +0 -0
- package/docs/components/flow-lane-editor.md +0 -0
- package/docs/components/flow-outline-editor.md +0 -0
- package/docs/components/forms-and-dialogs.md +0 -0
- package/docs/components/input-fields.md +0 -0
- package/docs/components/keymap.md +0 -0
- package/docs/components/markdown-and-outline.md +0 -0
- package/docs/components/menus.md +41 -0
- package/docs/components/notifications.md +0 -0
- package/docs/components/panels-and-desktops.md +0 -0
- package/docs/components/record-list-and-fact-table.md +0 -0
- package/docs/components/settings-view.md +0 -0
- package/docs/components/shell.md +0 -0
- package/docs/components/slide-out-panel.md +0 -0
- package/docs/components/tiles.md +25 -0
- package/docs/components/wizard.md +0 -0
- package/docs/concepts/building-and-packaging.md +0 -0
- package/docs/concepts/domain-neutrality.md +0 -0
- package/docs/concepts/host-port.md +0 -0
- package/docs/concepts/packages-and-entry-points.md +0 -0
- package/docs/concepts/peer-dependencies.md +0 -0
- package/docs/concepts/state-guard.md +0 -0
- package/docs/concepts/styling.md +0 -0
- package/docs/quickstart.md +0 -0
- package/editor.js +0 -0
- package/flow.js +0 -0
- package/host.js +0 -0
- package/package.json +1 -1
- package/src/canvas/canvas_adapter.js +0 -0
- package/src/canvas/edge_router.js +0 -0
- package/src/canvas/graph/connector_router.js +0 -0
- package/src/canvas/graph/history_service.js +0 -0
- package/src/canvas/graph/node_platform.js +0 -0
- package/src/canvas/index.js +0 -0
- package/src/canvas/layered_layout.js +0 -0
- package/src/charts/chart_types.js +3 -2
- package/src/charts/data_series_plot_window.js +0 -0
- package/src/charts/downsample.js +0 -0
- package/src/charts/plot_config.js +0 -0
- package/src/charts/plot_config_editor.js +8 -2
- package/src/charts/plotly_wrapper.js +0 -0
- package/src/core/event_bus.js +0 -0
- package/src/core/logging.js +0 -0
- package/src/core/settings.js +0 -0
- package/src/core/state_guard.js +0 -0
- package/src/core/state_guard_config.js +0 -0
- package/src/core/state_machine.js +0 -0
- package/src/editor/editor_pane.js +0 -0
- package/src/editor/monaco_editor_factory.js +0 -0
- package/src/editor/monaco_loader.js +0 -0
- package/src/editor/notebook_search.js +0 -0
- package/src/editor/notebook_tab_bar.js +26 -7
- package/src/editor/notebook_undo_manager.js +0 -0
- package/src/editor/split_pane_container.js +0 -0
- package/src/flow/canvas_editor/connections.js +0 -0
- package/src/flow/canvas_editor/editor.js +0 -0
- package/src/flow/canvas_editor/index.js +0 -0
- package/src/flow/canvas_editor/layout.js +0 -0
- package/src/flow/canvas_editor/strings.js +0 -0
- package/src/flow/kit/always_before.js +0 -0
- package/src/flow/kit/catalogue.js +0 -0
- package/src/flow/kit/chip_input.js +0 -0
- package/src/flow/kit/dom.js +0 -0
- package/src/flow/kit/findings.js +0 -0
- package/src/flow/kit/history.js +0 -0
- package/src/flow/kit/index.js +0 -0
- package/src/flow/kit/keys.js +0 -0
- package/src/flow/kit/logic_graph.js +0 -0
- package/src/flow/kit/references.js +0 -0
- package/src/flow/kit/settings_panel.js +0 -0
- package/src/flow/kit/settings_schema.js +0 -0
- package/src/flow/kit/step_picker.js +0 -0
- package/src/flow/kit/strings.js +0 -0
- package/src/flow/kit/value_picker.js +0 -0
- package/src/flow/kit/widgets.js +0 -0
- package/src/flow/lanes/editor.js +0 -0
- package/src/flow/lanes/index.js +0 -0
- package/src/flow/lanes/layout.js +0 -0
- package/src/flow/lanes/pipeline.js +0 -0
- package/src/flow/lanes/preview.js +0 -0
- package/src/flow/lanes/strings.js +0 -0
- package/src/flow/outline/editor.js +0 -0
- package/src/flow/outline/index.js +0 -0
- package/src/flow/outline/mapping.js +0 -0
- package/src/flow/outline/menu.js +0 -0
- package/src/flow/outline/operations.js +0 -0
- package/src/flow/outline/recognise.js +0 -0
- package/src/flow/outline/strings.js +0 -0
- package/src/help/help_modal.js +0 -0
- package/src/help/help_registry.js +0 -0
- package/src/host/external_links.js +0 -0
- package/src/host/file_picker.js +0 -0
- package/src/host/host.js +0 -0
- package/src/host/photino_host.js +0 -0
- package/src/host/photino_host.md +0 -0
- package/src/host/pywebview_host.js +0 -0
- package/src/tiles/chart_tiles.js +0 -0
- package/src/tiles/config_schema.js +0 -0
- package/src/tiles/figure_tile.js +0 -0
- package/src/tiles/layout_persistence.js +0 -0
- package/src/tiles/list_tiles.js +0 -0
- package/src/tiles/scope_picker.js +0 -0
- package/src/tiles/tile_base.js +67 -16
- package/src/tiles/tile_config_form.js +0 -0
- package/src/tiles/tile_grid.js +0 -0
- package/src/tiles/tile_registry.js +0 -0
- package/src/tiling/bottom_panel_tabs.js +0 -0
- package/src/tiling/command_palette.js +0 -0
- package/src/tiling/content_registry.js +0 -0
- package/src/tiling/desktops.js +0 -0
- package/src/tiling/entity_sources.js +0 -0
- package/src/tiling/keymap.js +0 -0
- package/src/tiling/kind_taxonomy.js +0 -0
- package/src/tiling/landing_table.js +0 -0
- package/src/tiling/loading_overlay.js +0 -0
- package/src/tiling/nav_panel.js +0 -0
- package/src/tiling/page_factory.js +0 -0
- package/src/tiling/panel_availability.js +0 -0
- package/src/tiling/panel_keys.js +0 -0
- package/src/tiling/shell.js +0 -0
- package/src/tiling/tab_strip.js +0 -0
- package/src/tiling/tile_breadcrumb.js +0 -0
- package/src/tiling/tile_renderer.js +0 -0
- package/src/tiling/tile_tab_menu.js +0 -0
- package/src/tiling/tile_tree.js +0 -0
- package/src/tiling/wm.js +0 -0
- package/src/tiling/zoom.js +0 -0
- package/src/ui/base/component_base.js +0 -0
- package/src/ui/base/controller_base.js +0 -0
- package/src/ui/base/page_base.js +0 -0
- package/src/ui/components/about_dialog.js +0 -0
- package/src/ui/components/action_dropdown.js +19 -6
- package/src/ui/components/alert_log.js +0 -0
- package/src/ui/components/alerts_pane.js +0 -0
- package/src/ui/components/attribute_list_editor.js +0 -0
- package/src/ui/components/autocomplete_field.js +0 -0
- package/src/ui/components/cell_editor_host.js +0 -0
- package/src/ui/components/cell_editors.js +0 -0
- package/src/ui/components/cell_grid.js +0 -0
- package/src/ui/components/cell_paste.js +0 -0
- package/src/ui/components/cell_selection.js +0 -0
- package/src/ui/components/choice_controls.js +0 -0
- package/src/ui/components/color_field.js +0 -0
- package/src/ui/components/color_list_field.js +0 -0
- package/src/ui/components/column_fit.js +0 -0
- package/src/ui/components/column_groups.js +0 -0
- package/src/ui/components/column_order.js +0 -0
- package/src/ui/components/computing_status_window.js +0 -0
- package/src/ui/components/confirm_dialog.js +0 -0
- package/src/ui/components/context_menu.js +20 -20
- package/src/ui/components/conversation_view.js +0 -0
- package/src/ui/components/crosstab.js +0 -0
- package/src/ui/components/data_table.js +45 -19
- package/src/ui/components/detail_header.js +0 -0
- package/src/ui/components/document_outline.js +0 -0
- package/src/ui/components/drag_reorder.js +0 -0
- package/src/ui/components/fact_table.js +0 -0
- package/src/ui/components/fill_handle.js +0 -0
- package/src/ui/components/gallery_picker.js +0 -0
- package/src/ui/components/header_actions.js +0 -0
- package/src/ui/components/inline_renamer.js +0 -0
- package/src/ui/components/job_progress.js +0 -0
- package/src/ui/components/managed_window.js +0 -0
- package/src/ui/components/menu_bar.js +0 -0
- package/src/ui/components/modal.js +0 -0
- package/src/ui/components/notification_history.js +0 -0
- package/src/ui/components/progress.js +0 -0
- package/src/ui/components/record_list.js +0 -0
- package/src/ui/components/row_activation.js +0 -0
- package/src/ui/components/section_stack.js +0 -0
- package/src/ui/components/series.js +0 -0
- package/src/ui/components/settings_view.js +0 -0
- package/src/ui/components/slide_out_panel.js +0 -0
- package/src/ui/components/slider_field.js +0 -0
- package/src/ui/components/sortable_list.js +0 -0
- package/src/ui/components/staged_edits.js +0 -0
- package/src/ui/components/staged_history.js +0 -0
- package/src/ui/components/table_filter_chips.js +0 -0
- package/src/ui/components/table_state_store.js +0 -0
- package/src/ui/components/table_structure.js +0 -0
- package/src/ui/components/table_values.js +0 -0
- package/src/ui/components/tabs.js +0 -0
- package/src/ui/components/tag_input.js +0 -0
- package/src/ui/components/toast.js +0 -0
- package/src/ui/components/toggle_field.js +0 -0
- package/src/ui/components/tree_view.js +0 -0
- package/src/ui/components/tsv.js +0 -0
- package/src/ui/components/window_taskbar.js +0 -0
- package/src/ui/components/wizard.js +0 -0
- package/src/ui/controllers/window_chrome_controller.js +0 -0
- package/src/ui/notification_center.js +0 -0
- package/src/ui/utils/auto_scrollbars.js +0 -0
- package/src/ui/utils/markdown.js +0 -0
- package/src/ui/utils/menu_viewport.js +81 -0
- package/src/ui/utils/native_context_menu.js +0 -0
- package/src/ui/utils/overlay_scrollbar.js +0 -0
- package/src/ui/utils/raf_resize_observer.js +0 -0
- package/src/ui/utils/scroll_lock.js +0 -0
- package/src/ui/utils/strip_scroll.js +0 -0
- package/src/ui/utils/tooltip_service.js +0 -0
- package/tiles.js +0 -0
- package/widgets.js +0 -0
- package/wm.js +0 -0
- package/dist/chunk-EIYNF4BD.js.map +0 -7
- package/dist/chunk-LWV23YVE.js.map +0 -7
- package/dist/chunk-UURZ37SD.js.map +0 -7
- package/dist/chunk-UWO43BZU.js.map +0 -7
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-N7HC3ADV.js";
|
|
5
5
|
import {
|
|
6
6
|
DragReorder
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-WUFLGETN.js";
|
|
8
8
|
|
|
9
9
|
// src/ui/components/tabs.js
|
|
10
10
|
var TAB_LEVELS = Object.freeze(["info", "warning", "alert"]);
|
|
@@ -372,4 +372,4 @@ export {
|
|
|
372
372
|
TAB_LEVELS,
|
|
373
373
|
createTabs
|
|
374
374
|
};
|
|
375
|
-
//# sourceMappingURL=chunk-
|
|
375
|
+
//# sourceMappingURL=chunk-REJ5HLIM.js.map
|
|
File without changes
|
|
@@ -199,7 +199,44 @@ var DragReorder = class {
|
|
|
199
199
|
}
|
|
200
200
|
};
|
|
201
201
|
|
|
202
|
+
// src/ui/utils/menu_viewport.js
|
|
203
|
+
var MENU_VIEWPORT_MARGIN = 8;
|
|
204
|
+
function placeMenuInViewport(menu, x, y, margin = MENU_VIEWPORT_MARGIN) {
|
|
205
|
+
const view = menu.ownerDocument?.defaultView || window;
|
|
206
|
+
const vw = view.innerWidth;
|
|
207
|
+
const vh = view.innerHeight;
|
|
208
|
+
const maxHeight = Math.max(0, vh - 2 * margin);
|
|
209
|
+
menu.style.maxHeight = `${maxHeight}px`;
|
|
210
|
+
menu.scrollTop = 0;
|
|
211
|
+
const rect = menu.getBoundingClientRect();
|
|
212
|
+
const left = Math.min(x, vw - rect.width - margin);
|
|
213
|
+
const top = Math.min(y, vh - rect.height - margin);
|
|
214
|
+
menu.style.left = `${Math.max(0, left)}px`;
|
|
215
|
+
menu.style.top = `${Math.max(0, top)}px`;
|
|
216
|
+
}
|
|
217
|
+
function focusMenuItem(item) {
|
|
218
|
+
if (!item) return;
|
|
219
|
+
item.focus({ preventScroll: true });
|
|
220
|
+
item.scrollIntoView?.({ block: "nearest", inline: "nearest" });
|
|
221
|
+
}
|
|
222
|
+
function moveMenuFocus(e, items) {
|
|
223
|
+
if (!items.length) return false;
|
|
224
|
+
const at = items.indexOf(items[0].ownerDocument.activeElement);
|
|
225
|
+
let next = null;
|
|
226
|
+
if (e.key === "ArrowDown") next = items[(at + 1 + items.length) % items.length];
|
|
227
|
+
else if (e.key === "ArrowUp") next = items[(at - 1 + items.length) % items.length];
|
|
228
|
+
else if (e.key === "Home") next = items[0];
|
|
229
|
+
else if (e.key === "End") next = items[items.length - 1];
|
|
230
|
+
if (!next) return false;
|
|
231
|
+
e.preventDefault();
|
|
232
|
+
focusMenuItem(next);
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
|
|
202
236
|
export {
|
|
203
|
-
DragReorder
|
|
237
|
+
DragReorder,
|
|
238
|
+
placeMenuInViewport,
|
|
239
|
+
focusMenuItem,
|
|
240
|
+
moveMenuFocus
|
|
204
241
|
};
|
|
205
|
-
//# sourceMappingURL=chunk-
|
|
242
|
+
//# sourceMappingURL=chunk-WUFLGETN.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/ui/components/drag_reorder.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * DragReorder \u2014 the one same-list drag-to-reorder implementation, with\n * the \"classic\" ghost (`.dragging` on the dragged element) + drop\n * placeholder (an indicator div inserted at the drop position) and\n * edge auto-scroll. Native HTML5 drag-and-drop.\n *\n * Extracted from the duplicated tab-bar reorder code so the notebook tab\n * bar, the workspace tab bar, and the schema column strip all share one\n * implementation. Axis-aware (`x` for horizontal strips, `y` for\n * vertical lists) and parameterised so it makes no assumptions about\n * tabs specifically.\n *\n * Usage:\n * const dr = new DragReorder({\n * container, itemSelector: '.tab', keyAttr: 'tabId', axis: 'x',\n * onReorder: (order) => { ... }, // order = array of keys\n * });\n * dr.attach(); // after each (re)render of the items\n * dr.destroy(); // on teardown\n *\n * Coexistence: the container-level handlers no-op unless THIS instance's\n * drag is active, so a host can keep its own dragover/drop handlers for\n * other concerns (e.g. cross-pane tab drops) alongside it \u2014 gate those\n * on `dr.isActive() === false`.\n */\nexport class DragReorder {\n /**\n * @param {Object} opts\n * @param {HTMLElement} opts.container\n * @param {string} [opts.itemSelector='.tab'] selector for reorderable items\n * @param {string} [opts.keyAttr='path'] dataset key / data-attr identifying an item\n * @param {'x'|'y'} [opts.axis='x']\n * @param {string} [opts.indicatorClass='tab-drop-indicator']\n * @param {boolean} [opts.autoScroll=true]\n * @param {(e: DragEvent, item: HTMLElement) => boolean} [opts.draggableGuard]\n * return false to cancel a drag start (e.g. from a close button)\n * @param {(e: DragEvent, key: string, item: HTMLElement) => void} [opts.onDragStart]\n * host hook to augment dataTransfer (e.g. add a cross-pane MIME)\n * @param {(order: string[]) => void} [opts.onReorder]\n */\n constructor(opts = {}) {\n this.container = opts.container || null;\n this.itemSelector = opts.itemSelector || '.tab';\n this.keyAttr = opts.keyAttr || 'path';\n this.axis = opts.axis === 'y' ? 'y' : 'x';\n this.indicatorClass = opts.indicatorClass || 'twm-tab-drop-indicator';\n this.autoScroll = opts.autoScroll !== false;\n this.draggableGuard = opts.draggableGuard || null;\n this.onDragStart = opts.onDragStart || null;\n this.onReorder = opts.onReorder || null;\n\n this._draggingEl = null;\n this._indicatorEl = null;\n this._lastSnapshot = [];\n\n this._onOver = this._onOver.bind(this);\n this._onDrop = this._onDrop.bind(this);\n this._onLeave = this._onLeave.bind(this);\n if (this.container) {\n this.container.addEventListener('dragover', this._onOver);\n this.container.addEventListener('drop', this._onDrop);\n this.container.addEventListener('dragleave', this._onLeave);\n }\n }\n\n /** Mark current items draggable + wire dragstart/dragend. Idempotent \u2014\n * call after every (re)render; already-wired items are skipped. */\n attach() {\n if (!this.container) return;\n for (const item of this.container.querySelectorAll(this.itemSelector)) {\n if (item.__dragReorder) continue;\n item.__dragReorder = true;\n item.setAttribute('draggable', 'true');\n item.addEventListener('dragstart', (e) => this._start(e, item));\n item.addEventListener('dragend', () => this._end());\n }\n }\n\n /** True while this instance is mid-drag. */\n isActive() { return !!this._draggingEl; }\n\n destroy() {\n if (this.container) {\n this.container.removeEventListener('dragover', this._onOver);\n this.container.removeEventListener('drop', this._onDrop);\n this.container.removeEventListener('dragleave', this._onLeave);\n }\n this._removeIndicator();\n this._draggingEl = null;\n }\n\n // \u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n _key(el) {\n if (!el) return null;\n return el.dataset?.[this.keyAttr]\n ?? el.getAttribute?.(`data-${this.keyAttr}`)\n ?? null;\n }\n\n _items() {\n return Array.from(this.container.querySelectorAll(this.itemSelector));\n }\n\n _snapshot() {\n return this._items().map((el) => this._key(el)).filter((k) => k != null);\n }\n\n _centerOf(rect) {\n return this.axis === 'y'\n ? rect.top + rect.height / 2\n : rect.left + rect.width / 2;\n }\n\n _start(e, item) {\n if (this.draggableGuard && !this.draggableGuard(e, item)) {\n e.preventDefault();\n return;\n }\n const key = this._key(item);\n this._draggingEl = item;\n this._lastSnapshot = this._snapshot();\n item.classList.add('dragging');\n try {\n e.dataTransfer.effectAllowed = 'move';\n if (key != null) e.dataTransfer.setData('text/plain', String(key));\n } catch { /* ignore */ }\n this.onDragStart?.(e, key, item);\n this._ensureIndicator();\n this._positionByNearest(this._centerOf(item.getBoundingClientRect()));\n }\n\n _end() {\n if (!this._draggingEl) return;\n this._draggingEl.classList.remove('dragging');\n this._draggingEl = null;\n this._removeIndicator();\n this._commitIfChanged();\n }\n\n _onOver(e) {\n if (!this._draggingEl) return; // not our drag \u2014 let the host handle it\n e.preventDefault();\n try { e.dataTransfer.dropEffect = 'move'; } catch { /* ignore */ }\n const coord = this.axis === 'y' ? e.clientY : e.clientX;\n this._positionByNearest(coord);\n if (this.autoScroll) this._autoScrollEdge(coord);\n }\n\n _onDrop(e) {\n if (!this._draggingEl) return;\n e.preventDefault();\n const indicator = this._ensureIndicator();\n if (indicator?.parentElement) {\n this.container.insertBefore(this._draggingEl, indicator);\n }\n this._finalize();\n }\n\n _onLeave(e) {\n if (!this._draggingEl) return;\n if (e.currentTarget !== this.container) return;\n if (this.container.contains(e.relatedTarget)) return;\n this._finalize();\n }\n\n _finalize() {\n if (this._draggingEl) this._draggingEl.classList.remove('dragging');\n this._removeIndicator();\n this._draggingEl = null;\n this._commitIfChanged();\n }\n\n _commitIfChanged() {\n const order = this._snapshot();\n if (!order.length) return;\n if (this._lastSnapshot.join('\u0000') === order.join('\u0000')) return;\n this._lastSnapshot = order;\n this.onReorder?.(order);\n }\n\n _ensureIndicator() {\n if (!this._indicatorEl) {\n this._indicatorEl = document.createElement('div');\n this._indicatorEl.className = this.indicatorClass;\n this._indicatorEl.setAttribute('aria-hidden', 'true');\n }\n if (!this._indicatorEl.parentElement) {\n this.container.appendChild(this._indicatorEl);\n }\n return this._indicatorEl;\n }\n\n _removeIndicator() { this._indicatorEl?.remove(); }\n\n _positionByNearest(coord) {\n if (!this.container || !this._indicatorEl || !this._draggingEl) return;\n const items = this._items().filter((t) => t !== this._draggingEl);\n if (!items.length) return;\n let best = null;\n let bestDist = Infinity;\n for (const it of items) {\n const center = this._centerOf(it.getBoundingClientRect());\n const dist = Math.abs(coord - center);\n if (dist < bestDist) { bestDist = dist; best = { it, center }; }\n }\n if (!best) return;\n const after = coord >= best.center;\n const ref = after ? best.it.nextElementSibling : best.it;\n this.container.insertBefore(this._indicatorEl, ref || null);\n }\n\n _autoScrollEdge(coord) {\n if (!this.container) return;\n const rect = this.container.getBoundingClientRect();\n const edge = 24;\n const step = 16;\n if (this.axis === 'y') {\n if (coord - rect.top < edge) {\n this.container.scrollTop = Math.max(0, this.container.scrollTop - step);\n } else if (rect.bottom - coord < edge) {\n this.container.scrollTop = Math.min(\n this.container.scrollHeight, this.container.scrollTop + step);\n }\n } else {\n if (coord - rect.left < edge) {\n this.container.scrollLeft = Math.max(0, this.container.scrollLeft - step);\n } else if (rect.right - coord < edge) {\n this.container.scrollLeft = Math.min(\n this.container.scrollWidth, this.container.scrollLeft + step);\n }\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
3
|
+
"sources": ["../src/ui/components/drag_reorder.js", "../src/ui/utils/menu_viewport.js"],
|
|
4
|
+
"sourcesContent": ["/**\n * DragReorder \u2014 the one same-list drag-to-reorder implementation, with\n * the \"classic\" ghost (`.dragging` on the dragged element) + drop\n * placeholder (an indicator div inserted at the drop position) and\n * edge auto-scroll. Native HTML5 drag-and-drop.\n *\n * Extracted from the duplicated tab-bar reorder code so the notebook tab\n * bar, the workspace tab bar, and the schema column strip all share one\n * implementation. Axis-aware (`x` for horizontal strips, `y` for\n * vertical lists) and parameterised so it makes no assumptions about\n * tabs specifically.\n *\n * Usage:\n * const dr = new DragReorder({\n * container, itemSelector: '.tab', keyAttr: 'tabId', axis: 'x',\n * onReorder: (order) => { ... }, // order = array of keys\n * });\n * dr.attach(); // after each (re)render of the items\n * dr.destroy(); // on teardown\n *\n * Coexistence: the container-level handlers no-op unless THIS instance's\n * drag is active, so a host can keep its own dragover/drop handlers for\n * other concerns (e.g. cross-pane tab drops) alongside it \u2014 gate those\n * on `dr.isActive() === false`.\n */\nexport class DragReorder {\n /**\n * @param {Object} opts\n * @param {HTMLElement} opts.container\n * @param {string} [opts.itemSelector='.tab'] selector for reorderable items\n * @param {string} [opts.keyAttr='path'] dataset key / data-attr identifying an item\n * @param {'x'|'y'} [opts.axis='x']\n * @param {string} [opts.indicatorClass='tab-drop-indicator']\n * @param {boolean} [opts.autoScroll=true]\n * @param {(e: DragEvent, item: HTMLElement) => boolean} [opts.draggableGuard]\n * return false to cancel a drag start (e.g. from a close button)\n * @param {(e: DragEvent, key: string, item: HTMLElement) => void} [opts.onDragStart]\n * host hook to augment dataTransfer (e.g. add a cross-pane MIME)\n * @param {(order: string[]) => void} [opts.onReorder]\n */\n constructor(opts = {}) {\n this.container = opts.container || null;\n this.itemSelector = opts.itemSelector || '.tab';\n this.keyAttr = opts.keyAttr || 'path';\n this.axis = opts.axis === 'y' ? 'y' : 'x';\n this.indicatorClass = opts.indicatorClass || 'twm-tab-drop-indicator';\n this.autoScroll = opts.autoScroll !== false;\n this.draggableGuard = opts.draggableGuard || null;\n this.onDragStart = opts.onDragStart || null;\n this.onReorder = opts.onReorder || null;\n\n this._draggingEl = null;\n this._indicatorEl = null;\n this._lastSnapshot = [];\n\n this._onOver = this._onOver.bind(this);\n this._onDrop = this._onDrop.bind(this);\n this._onLeave = this._onLeave.bind(this);\n if (this.container) {\n this.container.addEventListener('dragover', this._onOver);\n this.container.addEventListener('drop', this._onDrop);\n this.container.addEventListener('dragleave', this._onLeave);\n }\n }\n\n /** Mark current items draggable + wire dragstart/dragend. Idempotent \u2014\n * call after every (re)render; already-wired items are skipped. */\n attach() {\n if (!this.container) return;\n for (const item of this.container.querySelectorAll(this.itemSelector)) {\n if (item.__dragReorder) continue;\n item.__dragReorder = true;\n item.setAttribute('draggable', 'true');\n item.addEventListener('dragstart', (e) => this._start(e, item));\n item.addEventListener('dragend', () => this._end());\n }\n }\n\n /** True while this instance is mid-drag. */\n isActive() { return !!this._draggingEl; }\n\n destroy() {\n if (this.container) {\n this.container.removeEventListener('dragover', this._onOver);\n this.container.removeEventListener('drop', this._onDrop);\n this.container.removeEventListener('dragleave', this._onLeave);\n }\n this._removeIndicator();\n this._draggingEl = null;\n }\n\n // \u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n _key(el) {\n if (!el) return null;\n return el.dataset?.[this.keyAttr]\n ?? el.getAttribute?.(`data-${this.keyAttr}`)\n ?? null;\n }\n\n _items() {\n return Array.from(this.container.querySelectorAll(this.itemSelector));\n }\n\n _snapshot() {\n return this._items().map((el) => this._key(el)).filter((k) => k != null);\n }\n\n _centerOf(rect) {\n return this.axis === 'y'\n ? rect.top + rect.height / 2\n : rect.left + rect.width / 2;\n }\n\n _start(e, item) {\n if (this.draggableGuard && !this.draggableGuard(e, item)) {\n e.preventDefault();\n return;\n }\n const key = this._key(item);\n this._draggingEl = item;\n this._lastSnapshot = this._snapshot();\n item.classList.add('dragging');\n try {\n e.dataTransfer.effectAllowed = 'move';\n if (key != null) e.dataTransfer.setData('text/plain', String(key));\n } catch { /* ignore */ }\n this.onDragStart?.(e, key, item);\n this._ensureIndicator();\n this._positionByNearest(this._centerOf(item.getBoundingClientRect()));\n }\n\n _end() {\n if (!this._draggingEl) return;\n this._draggingEl.classList.remove('dragging');\n this._draggingEl = null;\n this._removeIndicator();\n this._commitIfChanged();\n }\n\n _onOver(e) {\n if (!this._draggingEl) return; // not our drag \u2014 let the host handle it\n e.preventDefault();\n try { e.dataTransfer.dropEffect = 'move'; } catch { /* ignore */ }\n const coord = this.axis === 'y' ? e.clientY : e.clientX;\n this._positionByNearest(coord);\n if (this.autoScroll) this._autoScrollEdge(coord);\n }\n\n _onDrop(e) {\n if (!this._draggingEl) return;\n e.preventDefault();\n const indicator = this._ensureIndicator();\n if (indicator?.parentElement) {\n this.container.insertBefore(this._draggingEl, indicator);\n }\n this._finalize();\n }\n\n _onLeave(e) {\n if (!this._draggingEl) return;\n if (e.currentTarget !== this.container) return;\n if (this.container.contains(e.relatedTarget)) return;\n this._finalize();\n }\n\n _finalize() {\n if (this._draggingEl) this._draggingEl.classList.remove('dragging');\n this._removeIndicator();\n this._draggingEl = null;\n this._commitIfChanged();\n }\n\n _commitIfChanged() {\n const order = this._snapshot();\n if (!order.length) return;\n if (this._lastSnapshot.join('\u0000') === order.join('\u0000')) return;\n this._lastSnapshot = order;\n this.onReorder?.(order);\n }\n\n _ensureIndicator() {\n if (!this._indicatorEl) {\n this._indicatorEl = document.createElement('div');\n this._indicatorEl.className = this.indicatorClass;\n this._indicatorEl.setAttribute('aria-hidden', 'true');\n }\n if (!this._indicatorEl.parentElement) {\n this.container.appendChild(this._indicatorEl);\n }\n return this._indicatorEl;\n }\n\n _removeIndicator() { this._indicatorEl?.remove(); }\n\n _positionByNearest(coord) {\n if (!this.container || !this._indicatorEl || !this._draggingEl) return;\n const items = this._items().filter((t) => t !== this._draggingEl);\n if (!items.length) return;\n let best = null;\n let bestDist = Infinity;\n for (const it of items) {\n const center = this._centerOf(it.getBoundingClientRect());\n const dist = Math.abs(coord - center);\n if (dist < bestDist) { bestDist = dist; best = { it, center }; }\n }\n if (!best) return;\n const after = coord >= best.center;\n const ref = after ? best.it.nextElementSibling : best.it;\n this.container.insertBefore(this._indicatorEl, ref || null);\n }\n\n _autoScrollEdge(coord) {\n if (!this.container) return;\n const rect = this.container.getBoundingClientRect();\n const edge = 24;\n const step = 16;\n if (this.axis === 'y') {\n if (coord - rect.top < edge) {\n this.container.scrollTop = Math.max(0, this.container.scrollTop - step);\n } else if (rect.bottom - coord < edge) {\n this.container.scrollTop = Math.min(\n this.container.scrollHeight, this.container.scrollTop + step);\n }\n } else {\n if (coord - rect.left < edge) {\n this.container.scrollLeft = Math.max(0, this.container.scrollLeft - step);\n } else if (rect.right - coord < edge) {\n this.container.scrollLeft = Math.min(\n this.container.scrollWidth, this.container.scrollLeft + step);\n }\n }\n }\n}\n", "/**\n * menu_viewport.js \u2014 keeping a context menu inside the window (BUG-0040).\n *\n * FlexDesk draws three context menus of its own: `showContextMenu`\n * (../components/context_menu.js), the DataTable's right-click menu\n * (../components/data_table.js) and `NotebookTabBar`'s tab menu\n * (../../editor/notebook_tab_bar.js). Each placed itself with its own copy of\n * `top = min(y, innerHeight - height - 8)`, and none had a max-height. A menu\n * taller than the window then opened above its top edge (the DataTable's did\n * not clamp at all: a 101-item row menu opened at y=-2153 in a 761 px window)\n * or ran off its bottom, and nothing scrolled, so the items past the edge could\n * not be reached by any means.\n *\n * One placement now, for all three:\n * - the menu is at most the window's height less a margin above and below,\n * and scrolls inside when it is longer (`overflow-y: auto` in flexdesk.css);\n * - it opens at the pointer, moved left or up just enough to fit, and never\n * above the window's top or left edge;\n * - keyboard movement focuses an item and scrolls it into view within the\n * menu, so every item can be reached with the arrows.\n */\n\n/** The gap kept between a menu and the window's edges, in px. */\nexport const MENU_VIEWPORT_MARGIN = 8;\n\n/**\n * Size and place an open (displayed) menu at `(x, y)` inside its window.\n *\n * @param {HTMLElement} menu the menu, already in the document and displayed\n * @param {number} x client x of the pointer\n * @param {number} y client y of the pointer\n * @param {number} [margin] gap to the window's edges\n */\nexport function placeMenuInViewport(menu, x, y, margin = MENU_VIEWPORT_MARGIN) {\n const view = menu.ownerDocument?.defaultView || window;\n const vw = view.innerWidth;\n const vh = view.innerHeight;\n const maxHeight = Math.max(0, vh - 2 * margin);\n menu.style.maxHeight = `${maxHeight}px`;\n menu.scrollTop = 0;\n // flexdesk.css makes the menu `box-sizing: border-box`, so its measured\n // height (padding and border included) is at most `maxHeight`.\n const rect = menu.getBoundingClientRect();\n const left = Math.min(x, vw - rect.width - margin);\n const top = Math.min(y, vh - rect.height - margin);\n menu.style.left = `${Math.max(0, left)}px`;\n menu.style.top = `${Math.max(0, top)}px`;\n}\n\n/**\n * Focus a menu item and bring it into view inside the (scrolling) menu.\n * `preventScroll` keeps the page where it is; `block: 'nearest'` scrolls the\n * menu only as far as the item needs.\n */\nexport function focusMenuItem(item) {\n if (!item) return;\n item.focus({ preventScroll: true });\n item.scrollIntoView?.({ block: 'nearest', inline: 'nearest' });\n}\n\n/**\n * Up/Down/Home/End over `items` (the enabled ones), wrapping, from the one\n * that has focus. Returns true when the key moved focus (the caller's event\n * has then been `preventDefault`ed).\n *\n * @param {KeyboardEvent} e\n * @param {HTMLElement[]} items\n */\nexport function moveMenuFocus(e, items) {\n if (!items.length) return false;\n const at = items.indexOf(items[0].ownerDocument.activeElement);\n let next = null;\n if (e.key === 'ArrowDown') next = items[(at + 1 + items.length) % items.length];\n else if (e.key === 'ArrowUp') next = items[(at - 1 + items.length) % items.length];\n else if (e.key === 'Home') next = items[0];\n else if (e.key === 'End') next = items[items.length - 1];\n if (!next) return false;\n e.preventDefault();\n focusMenuItem(next);\n return true;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/core.js
CHANGED
|
File without changes
|
package/dist/core.js.map
CHANGED
|
File without changes
|
package/dist/editor.js
CHANGED
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
NotebookTabBar,
|
|
4
4
|
getTabDragMime,
|
|
5
5
|
setTabDragMime
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7U4IB65H.js";
|
|
7
7
|
import "./chunk-N7HC3ADV.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-WUFLGETN.js";
|
|
9
9
|
import "./chunk-JYWURG5T.js";
|
|
10
10
|
|
|
11
11
|
// src/editor/editor_pane.js
|
package/dist/editor.js.map
CHANGED
|
File without changes
|
package/dist/flexdesk.css
CHANGED
|
@@ -3959,11 +3959,14 @@ body.twm-window-maximized .twm-resize-handle {
|
|
|
3959
3959
|
position: relative;
|
|
3960
3960
|
}
|
|
3961
3961
|
|
|
3962
|
+
/* While open the menu is moved to document.body and placed `position: fixed`
|
|
3963
|
+
by `ActionDropdown.position` (inline styles), so a narrow tile cannot clip
|
|
3964
|
+
it; --z-over-windows keeps it over a managed window holding the grid. */
|
|
3962
3965
|
.tile-menu-dropdown {
|
|
3963
3966
|
position: absolute;
|
|
3964
3967
|
top: 100%;
|
|
3965
3968
|
right: 0;
|
|
3966
|
-
z-index: var(--z-
|
|
3969
|
+
z-index: var(--z-over-windows);
|
|
3967
3970
|
min-width: 180px;
|
|
3968
3971
|
padding: var(--space-xs) 0;
|
|
3969
3972
|
background: var(--surface-2);
|
|
@@ -7629,6 +7632,23 @@ body.twm-dragging * { user-select: none; }
|
|
|
7629
7632
|
transition: opacity 90ms ease-out;
|
|
7630
7633
|
}
|
|
7631
7634
|
.nb-context-menu.visible { opacity: 1; }
|
|
7635
|
+
|
|
7636
|
+
/* ── Context menus stay inside the window (0.17.9, BUG-0040) ─────────
|
|
7637
|
+
* `showContextMenu`, the DataTable's right-click menu and NotebookTabBar's tab
|
|
7638
|
+
* menu are placed by src/ui/utils/menu_viewport.js, which sets an inline
|
|
7639
|
+
* max-height of the window's height less a margin top and bottom. Here: the
|
|
7640
|
+
* same cap for a menu placed before that runs, border-box so the cap includes
|
|
7641
|
+
* padding and border, and scrolling inside when the items are longer — they
|
|
7642
|
+
* had no max-height and no overflow, so a 100-item menu ran off the window and
|
|
7643
|
+
* its far items could not be reached. */
|
|
7644
|
+
.twm-context-menu,
|
|
7645
|
+
.nb-context-menu {
|
|
7646
|
+
box-sizing: border-box;
|
|
7647
|
+
max-height: calc(100vh - 2 * var(--space-md));
|
|
7648
|
+
overflow-x: hidden;
|
|
7649
|
+
overflow-y: auto;
|
|
7650
|
+
overscroll-behavior: contain;
|
|
7651
|
+
}
|
|
7632
7652
|
.nb-context-menu__item {
|
|
7633
7653
|
display: flex;
|
|
7634
7654
|
align-items: center;
|
package/dist/flow.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
modalHost
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-BE2PU3LL.js";
|
|
4
4
|
import {
|
|
5
5
|
DataTable
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-NIJEJAZ7.js";
|
|
7
7
|
import {
|
|
8
8
|
choiceList,
|
|
9
9
|
selectBox,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
toggleChips
|
|
12
12
|
} from "./chunk-CVMCZZX2.js";
|
|
13
13
|
import "./chunk-HNU6MM2B.js";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-WUFLGETN.js";
|
|
15
15
|
import {
|
|
16
16
|
CONNECTOR_STRINGS,
|
|
17
17
|
CanvasAdapter,
|
package/dist/flow.js.map
CHANGED
|
File without changes
|
package/dist/host.js
CHANGED
|
File without changes
|
package/dist/host.js.map
CHANGED
|
File without changes
|
package/dist/reset.css
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/dist/tiles.js
CHANGED
|
@@ -14,13 +14,14 @@ import {
|
|
|
14
14
|
import {
|
|
15
15
|
ActionDropdown,
|
|
16
16
|
SlideOutPanel
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-MIW7D6WC.js";
|
|
18
18
|
import {
|
|
19
19
|
showContextMenu
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-F35XSQWA.js";
|
|
21
21
|
import {
|
|
22
|
+
modalHost,
|
|
22
23
|
openModal
|
|
23
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-BE2PU3LL.js";
|
|
24
25
|
import {
|
|
25
26
|
buildHistogramTrace,
|
|
26
27
|
buildLegendLayout,
|
|
@@ -35,13 +36,13 @@ import {
|
|
|
35
36
|
purge,
|
|
36
37
|
resize,
|
|
37
38
|
strideDownsampleShared
|
|
38
|
-
} from "./chunk-
|
|
39
|
-
import "./chunk-
|
|
39
|
+
} from "./chunk-2YTM3GJE.js";
|
|
40
|
+
import "./chunk-NIJEJAZ7.js";
|
|
40
41
|
import {
|
|
41
42
|
isHexColor
|
|
42
43
|
} from "./chunk-CVMCZZX2.js";
|
|
43
44
|
import "./chunk-HNU6MM2B.js";
|
|
44
|
-
import "./chunk-
|
|
45
|
+
import "./chunk-WUFLGETN.js";
|
|
45
46
|
import {
|
|
46
47
|
__toCommonJS
|
|
47
48
|
} from "./chunk-JYWURG5T.js";
|
|
@@ -514,6 +515,10 @@ var TileBase = class {
|
|
|
514
515
|
dispose() {
|
|
515
516
|
if (this._disposed) return;
|
|
516
517
|
this._disposed = true;
|
|
518
|
+
this._closeTileMenu();
|
|
519
|
+
this._menuButton = null;
|
|
520
|
+
this._menuDropdown = null;
|
|
521
|
+
this._menuHome = null;
|
|
517
522
|
if (this._expandWindow?.isVisible) {
|
|
518
523
|
this._expandWindow.close();
|
|
519
524
|
}
|
|
@@ -594,6 +599,10 @@ var TileBase = class {
|
|
|
594
599
|
* @private
|
|
595
600
|
*/
|
|
596
601
|
_buildChrome() {
|
|
602
|
+
this._closeTileMenu();
|
|
603
|
+
this._menuButton = null;
|
|
604
|
+
this._menuDropdown = null;
|
|
605
|
+
this._menuHome = null;
|
|
597
606
|
const header = document.createElement("div");
|
|
598
607
|
header.className = "tile-header";
|
|
599
608
|
const expandBtnHtml = this.constructor.EXPANDABLE ? `<button class="tile-expand-btn twm-has-tooltip" data-tooltip="Open in window">
|
|
@@ -663,26 +672,18 @@ var TileBase = class {
|
|
|
663
672
|
const menuBtn = header.querySelector(".tile-menu-btn");
|
|
664
673
|
const menuDropdown = header.querySelector(".tile-menu-dropdown");
|
|
665
674
|
if (menuBtn && menuDropdown) {
|
|
675
|
+
this._menuButton = menuBtn;
|
|
676
|
+
this._menuDropdown = menuDropdown;
|
|
677
|
+
this._menuHome = menuDropdown.parentNode;
|
|
666
678
|
menuBtn.addEventListener("click", (e) => {
|
|
667
679
|
e.stopPropagation();
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
if (!isOpen) {
|
|
671
|
-
const closeMenu = (ev) => {
|
|
672
|
-
if (!menuDropdown.contains(ev.target) && ev.target !== menuBtn) {
|
|
673
|
-
menuDropdown.hidden = true;
|
|
674
|
-
document.removeEventListener("pointerdown", closeMenu, true);
|
|
675
|
-
}
|
|
676
|
-
};
|
|
677
|
-
requestAnimationFrame(() => {
|
|
678
|
-
document.addEventListener("pointerdown", closeMenu, true);
|
|
679
|
-
});
|
|
680
|
-
}
|
|
680
|
+
if (menuDropdown.hidden) this._openTileMenu();
|
|
681
|
+
else this._closeTileMenu();
|
|
681
682
|
});
|
|
682
683
|
menuDropdown.querySelectorAll(".tile-menu-item").forEach((itemEl) => {
|
|
683
684
|
itemEl.addEventListener("click", (e) => {
|
|
684
685
|
e.stopPropagation();
|
|
685
|
-
|
|
686
|
+
this._closeTileMenu();
|
|
686
687
|
this._onMenuAction(itemEl.dataset.action);
|
|
687
688
|
});
|
|
688
689
|
});
|
|
@@ -716,6 +717,48 @@ var TileBase = class {
|
|
|
716
717
|
});
|
|
717
718
|
}
|
|
718
719
|
}
|
|
720
|
+
/**
|
|
721
|
+
* Open the ⋯ menu. It is drawn on `document.body` (or the open modal's
|
|
722
|
+
* host, as `showContextMenu` is), not inside the tile: a tile clips its
|
|
723
|
+
* content, so a menu wider than a narrow tile lost its left part. It is
|
|
724
|
+
* placed with `ActionDropdown.position` — fixed, under the button (above
|
|
725
|
+
* when there is no room), right edges aligned, kept inside the window.
|
|
726
|
+
* @private
|
|
727
|
+
*/
|
|
728
|
+
_openTileMenu() {
|
|
729
|
+
const btn = this._menuButton;
|
|
730
|
+
const menu = this._menuDropdown;
|
|
731
|
+
if (!btn || !menu || !menu.hidden) return;
|
|
732
|
+
(modalHost() || document.body).appendChild(menu);
|
|
733
|
+
menu.hidden = false;
|
|
734
|
+
ActionDropdown.position(btn, menu, { align: "end" });
|
|
735
|
+
this._menuOutsideListener = (ev) => {
|
|
736
|
+
if (!menu.contains(ev.target) && !btn.contains(ev.target)) this._closeTileMenu();
|
|
737
|
+
};
|
|
738
|
+
const listener = this._menuOutsideListener;
|
|
739
|
+
requestAnimationFrame(() => {
|
|
740
|
+
if (this._menuOutsideListener === listener) {
|
|
741
|
+
document.addEventListener("pointerdown", listener, true);
|
|
742
|
+
}
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Close the ⋯ menu and put it back in the tile's header.
|
|
747
|
+
* @private
|
|
748
|
+
*/
|
|
749
|
+
_closeTileMenu() {
|
|
750
|
+
const menu = this._menuDropdown;
|
|
751
|
+
if (this._menuOutsideListener) {
|
|
752
|
+
document.removeEventListener("pointerdown", this._menuOutsideListener, true);
|
|
753
|
+
this._menuOutsideListener = null;
|
|
754
|
+
}
|
|
755
|
+
if (!menu) return;
|
|
756
|
+
menu.hidden = true;
|
|
757
|
+
for (const prop of ["position", "top", "bottom", "left", "right", "maxHeight", "overflowY"]) {
|
|
758
|
+
menu.style[prop] = "";
|
|
759
|
+
}
|
|
760
|
+
if (this._menuHome && menu.parentNode !== this._menuHome) this._menuHome.appendChild(menu);
|
|
761
|
+
}
|
|
719
762
|
/**
|
|
720
763
|
* Handle config button click — highlight tile and emit config request.
|
|
721
764
|
* @private
|