{ "version": 3, "sources": ["../../drag_and_drop.tsx"], "sourcesContent": ["import {\n AddCard,\n AddCardValue,\n as_CardUID,\n Board,\n BoardUID,\n Card,\n CardChangelogEntry,\n CardPatchOpType,\n CardUID,\n Column,\n ColumnCard,\n create_CardUID,\n EngagementType,\n InboxCard,\n is_BoardUID,\n MoveCard,\n RemoveCard,\n} from \"@cling/lib.shared.model\"\nimport * as React from \"react\"\nimport {observer} from \"mobx-react\"\nimport {report_error, report_info} from \"@cling/lib.shared.debug\"\nimport {action, observable, runInAction, makeObservable} from \"mobx\"\nimport {current_user, ui_actions, ui_state} from \"./state/index\"\nimport {assert, safe_to_string} from \"@cling/lib.shared.utils\"\nimport {log} from \"@cling/lib.shared.logging\"\nimport {board_resource} from \"@cling/lib.web.resources\"\nimport {Snackbar} from \"@cling/lib.web.mdc\"\nimport {i18n} from \"@cling/lib.web.i18n\"\nimport {optimistic_update} from \"./state/patch\"\nimport {report_user_engagement} from \"@cling/lib.web.analytics\"\n\nconst MIN_DRAG_DISTANCE = 11\nconst ADD_NEW_COLUMN_AREA_WIDTH = 50\nconst ADD_NEW_COLUMN_DELAY = 250\nconst SCROLL_DELAY = 300\n\nlet current_ghost: any\n\ntype Props = {\n render_card: React.ComponentType<{\n card: Card\n dnd_ghost_ref: (ref: ReactRef<HTMLDivElement>) => void\n }>\n}\n\nexport const DragAndDropGhost = observer(\n class DragAndDropGhost extends React.Component<Props> {\n static readonly instance: DragAndDropGhost\n\n drag_and_drop?: DragAndDrop = undefined\n dom_node: ReactRef<HTMLDivElement>\n left?: string\n top?: string\n width?: string\n\n constructor(props: any) {\n super(props)\n makeObservable<DragAndDropGhost, \"drag_and_drop\">(this, {\n drag_and_drop: observable.ref,\n on_drag_and_drop_started: action,\n reset: action,\n })\n }\n\n on_drag_and_drop_started(drag_and_drop: DragAndDrop) {\n this.left = \"\"\n this.top = \"\"\n this.width = \"\"\n this.drag_and_drop = drag_and_drop\n }\n\n update_ghost_ref = (ref: ReactRef<HTMLDivElement>) => {\n this.dom_node = ref\n if (ref) {\n const {style} = ref\n const {left, top, width} = this\n if (left) {\n style.left = left\n }\n if (top) {\n style.top = top\n }\n if (width) {\n style.width = width\n }\n }\n }\n\n move_to = (x: number, y: number) => {\n this.left = x + \"px\"\n this.top = y + \"px\"\n if (this.dom_node) {\n const {style} = this.dom_node\n style.left = this.left\n style.top = this.top\n }\n }\n\n set_width = (w: number) => {\n this.width = w + \"px\"\n if (this.dom_node) {\n const {style} = this.dom_node\n style.width = this.width\n }\n }\n\n reset() {\n this.left = \"\"\n this.top = \"\"\n this.width = \"\"\n this.drag_and_drop = undefined\n }\n\n componentDidMount() {\n if (current_ghost) {\n report_error(\"DragAndDropGhost already mounted\")\n }\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n current_ghost = this\n cling.drag_and_drop_ready = true\n }\n\n componentWillUnmount() {\n current_ghost = undefined as any\n }\n\n render() {\n const {drag_and_drop} = this\n if (!drag_and_drop) {\n return null\n }\n const {ghost_card} = drag_and_drop\n return React.createElement(this.props.render_card, {\n card: ghost_card,\n dnd_ghost_ref: this.update_ghost_ref,\n })\n }\n },\n)\n\n/**\n * @param ignore_click_at A callback, which will be called on `mouseup` if the mouse cursor\n * was moved at least 10 pixels while the left mouse button was pressed\n */\nexport function start_drag_card(\n mousedown_event: React.MouseEvent<any>,\n card_uid: CardUID,\n ignore_click_at: (timestamp: number) => void,\n) {\n if (!current_ghost) {\n report_error(\"DragAndDropGhost not mounted\")\n return\n }\n const dragged_card_elm = (mousedown_event.target as HTMLElement).closest(\n \".dnd__card\",\n ) as HTMLElement | null\n if (!dragged_card_elm) {\n return\n }\n assert(\n dragged_card_elm.dataset.cardUid === card_uid,\n \"dragged_card_elm.dataset.cardUid !== card_uid\",\n )\n let source: DragSource\n try {\n source = determine_source(card_uid, dragged_card_elm)\n // Prevent that text is selected ...\n mousedown_event.stopPropagation()\n mousedown_event.preventDefault()\n // Ignore margins of dragged card div ...\n const dragged_card_rect = dragged_card_elm\n .querySelector(\".mdc-card\")!\n .getBoundingClientRect()\n const dragged_card_width = dragged_card_rect.width\n let ignore_click = false\n let drag_and_drop: DragAndDrop\n let move_ghost_request_id: any = 0\n let mouse_cursor_x: number\n let mouse_cursor_y: number\n const {clientX: x0, clientY: y0} = mousedown_event\n const grabbed_at = {\n x: x0 - dragged_card_rect.left,\n y: y0 - dragged_card_rect.top,\n }\n const move_ghost = () => {\n move_ghost_request_id = 0\n if (drag_and_drop) {\n current_ghost.move_to(mouse_cursor_x - grabbed_at.x, mouse_cursor_y - grabbed_at.y)\n }\n }\n const handle_error = <T extends Event>(f: (event: T) => void) => {\n return (event: T) => {\n try {\n f(event)\n } catch (error) {\n if (drag_and_drop) {\n remove_event_listeners()\n drag_and_drop.on_error(error)\n } else {\n throw error\n }\n }\n }\n }\n const on_mousemove = handle_error((event: MouseEvent) => {\n mouse_cursor_x = event.clientX\n mouse_cursor_y = event.clientY\n if (!move_ghost_request_id) {\n move_ghost_request_id = requestAnimationFrame(move_ghost)\n }\n if (drag_and_drop) {\n drag_and_drop.on_drag(event)\n } else {\n const d = Math.max(Math.abs(mouse_cursor_x - x0), Math.abs(mouse_cursor_y - y0))\n if (d >= MIN_DRAG_DISTANCE) {\n ignore_click = true\n document.body.classList.add(\"dnd--dragging\")\n runInAction(() => {\n drag_and_drop = new DragAndDrop(current_ghost, source, grabbed_at, event)\n ;(cling as any).drag_and_drop = drag_and_drop\n ui_actions.disable_card_menus()\n current_ghost.set_width(dragged_card_width)\n current_ghost.move_to(\n mouse_cursor_x - grabbed_at.x,\n mouse_cursor_y - grabbed_at.y,\n )\n })\n }\n }\n })\n const on_mouseup = handle_error((event: MouseEvent) => {\n remove_event_listeners()\n if (drag_and_drop) {\n ui_actions.enable_card_menus()\n event.stopPropagation()\n event.preventDefault()\n if (move_ghost_request_id) {\n cancelAnimationFrame(move_ghost_request_id)\n }\n if (ignore_click) {\n ignore_click_at(event.timeStamp)\n }\n drag_and_drop.on_drop(event)\n }\n })\n const on_keydown = handle_error((event: KeyboardEvent) => {\n if (drag_and_drop) {\n if (event.key === \"Escape\" || event.key === \"Esc\") {\n event.stopPropagation()\n event.preventDefault()\n remove_event_listeners()\n ui_actions.enable_card_menus()\n drag_and_drop.abort({reason: \"Esc key pressed\"})\n }\n }\n })\n const on_window_blur = handle_error(() => {\n remove_event_listeners()\n if (drag_and_drop) {\n drag_and_drop.abort({reason: \"Browser tab lost focus\"})\n }\n })\n document.addEventListener(\"mousemove\", on_mousemove, true)\n document.addEventListener(\"mouseup\", on_mouseup, true)\n document.addEventListener(\"keydown\", on_keydown, true)\n addEventListener(\"blur\", on_window_blur)\n const remove_event_listeners = () => {\n document.removeEventListener(\"mousemove\", on_mousemove, true)\n document.removeEventListener(\"mouseup\", on_mouseup, true)\n document.removeEventListener(\"keydown\", on_keydown, true)\n removeEventListener(\"blur\", on_window_blur)\n }\n // For testing purposes ...\n return {on_mousemove, on_mouseup, on_keydown}\n } catch (error) {\n report_error(\"start_drag_card(...) failed\", error)\n return\n }\n}\n\ntype DragSource = Readonly<{\n readonly board: Board\n /**\n * The top level card containing the dragged card as descendant when dragging started.\n */\n readonly top_level_card: ColumnCard | InboxCard\n /** The parent card of the dragged card when dragging started. */\n readonly parent_card: Card\n /** The index of the dragged card in `this.parent_card.children` when dragging started. */\n readonly index_of_dragged_card: number\n readonly dragged_card: Card\n}>\n\ntype DragTarget =\n | {\n readonly board: Board\n readonly new_column?: never\n readonly top_level_card: ColumnCard | InboxCard\n readonly parent_card: Card\n /** The index of the dragged card in `this.parent_card.children`. */\n readonly index_of_dragged_card: number\n }\n | {\n readonly board: Board\n readonly new_column: true\n /* The new column card. */\n readonly top_level_card: ColumnCard\n /** The index of the new column card in `this.board.root.children`. */\n readonly index_of_new_column_card: number\n readonly parent_card?: never\n readonly index_of_dragged_card?: never\n }\n\ninterface GrabbedAt {\n x: number\n y: number\n}\n\ninterface ScrollOnDragArea {\n is_inside: (x: number, y: number) => boolean\n scroll: (delta: number) => void\n}\n\nfunction _scroll_horizontal() {\n let _block_horizontal_scroll = false\n function scroll(dir: \"left\" | \"right\") {\n if (_block_horizontal_scroll) {\n return\n }\n if (dir === \"right\") {\n ui_state.layout_state.scroll_to_column(\n ui_state.layout_state.first_visible_column_index + 1,\n )\n } else {\n ui_state.layout_state.scroll_to_column(\n ui_state.layout_state.first_visible_column_index - 1,\n )\n }\n _block_horizontal_scroll = true\n setTimeout(() => (_block_horizontal_scroll = false), 500)\n }\n return {scroll_left: () => scroll(\"left\"), scroll_right: () => scroll(\"right\")}\n}\n\nfunction _scroll_up(elm: HTMLElement, delta: number): void {\n const scroll_top = elm.scrollTop\n if (scroll_top > delta) {\n elm.scrollTop = scroll_top - delta\n } else if (scroll_top > 0) {\n elm.scrollTop = 0\n }\n}\n\nfunction _scroll_down(elm: HTMLElement, delta: number): void {\n const scroll_top = elm.scrollTop\n const max_scroll_top = elm.scrollHeight - elm.getBoundingClientRect().height\n if (scroll_top < max_scroll_top - delta) {\n elm.scrollTop = scroll_top + delta\n } else if (scroll_top < max_scroll_top) {\n elm.scrollTop = max_scroll_top\n }\n}\n\ninterface BoundingClientRect {\n readonly bottom: number\n readonly height: number\n readonly left: number\n readonly right: number\n readonly top: number\n readonly width: number\n}\n\nclass DragAndDrop {\n readonly dragged_card: Card\n readonly ghost_card: Card\n readonly grabbed_at: GrabbedAt\n target: DragTarget\n private readonly desc: string\n private readonly dragged_card_descendants_uids: Set<CardUID>\n private pending_add_new_column_key?: string\n private pending_add_new_column_timeout_id: any\n private aborted = false\n private on_drop_called = false\n private mouse_cursor_x = 0\n private mouse_cursor_y = 0\n private sync_model_timeout_id: any\n private scroll_horizontal_on_drag_areas: Array<ScrollOnDragArea> = []\n private active_scroll_horizontal_drag_area?: ScrollOnDragArea\n private scroll_horizontal_start_time?: number\n private scroll_vertical_on_drag_areas: Array<ScrollOnDragArea> = []\n private active_scroll_vertical_drag_area?: ScrollOnDragArea\n private scroll_vertical_start_time?: number\n private scroll_on_drag_interval_id?: any\n private new_column_card_uid?: CardUID\n private ghost_rect_when_moved?: BoundingClientRect\n private get_card_cache = new Map<string, Card>()\n\n constructor(\n private ghost: any,\n public readonly source: DragSource,\n grabbed_at?: GrabbedAt,\n mouse_down_event?: MouseEvent,\n ) {\n const {board, top_level_card, parent_card, index_of_dragged_card, dragged_card} = source\n this.dragged_card = dragged_card\n this.desc = `dragged card ${dragged_card.uid}`\n this.ghost_card = new Card({\n ...dragged_card,\n children: dragged_card.children.slice(0, dragged_card.children.length),\n })\n ;(this.ghost_card as any)._parent = dragged_card.parent\n this.dragged_card_descendants_uids = new Set(dragged_card.deep_children.map((c) => c.uid))\n this.target = {board, top_level_card, parent_card, index_of_dragged_card}\n this.assert_consistent_state()\n log.debug(`[dnd] Dragging card ${dragged_card.uid} ...`, {source: this.source})\n this.grabbed_at = grabbed_at || {x: 20, y: 8}\n ui_state.layout_state.freeze_layout()\n if (mouse_down_event) {\n this.on_drag(mouse_down_event)\n }\n // Setup scroll on drag in another time slice ...\n setTimeout(this.setup_scroll_on_drag, 1)\n dragged_card._is_dragged = this\n ghost.on_drag_and_drop_started(this)\n }\n\n assert_consistent_state() {\n const {dragged_card, target} = this\n if (target.new_column) {\n const {board, top_level_card: new_column_card, index_of_new_column_card: index} = target\n assert(\n board === ui_state.current_board.board,\n \"Invalid target: new_column && board !== ui_state.current_board\",\n )\n assert(\n board.root.children[index] === new_column_card,\n \"Invalid target: board.root.children[index_of_new_column_card] !== new_column_card\",\n )\n assert(\n new_column_card.parent === board.root,\n \"Invalid state: new_column_card.parent !== board.root\",\n )\n assert(new_column_card.column, \"Invalid state: !new_column_card.column\")\n assert(\n new_column_card.uid === this.new_column_card_uid,\n \"Invalid state: new_column_card.uid !== this.new_column_card_uid\",\n )\n const n = new_column_card.children.length\n assert(n === 1, `Invalid state: new_column_card.children.length === ${n}`)\n assert(\n new_column_card.children[0] === dragged_card,\n `Invalid state: new_column_card.children[0] !== dragged_card`,\n )\n assert(\n dragged_card.parent === new_column_card,\n `Invalid state: dragged_card.parent !== new_column_card`,\n )\n } else {\n const {board, top_level_card, parent_card, index_of_dragged_card: index} = target\n assert(\n board.root.children.some((c) => c === top_level_card),\n \"Invalid target: top_level_card is not in board.root.children\",\n )\n assert(\n top_level_card.parent === board.root,\n \"Invalid state: top_level_card.parent !== board.root\",\n )\n assert(\n parent_card.children.length > index,\n \"Invalid target: parent_card.children.length <= index_of_dragged_card\",\n )\n assert(\n parent_card.children[index] === dragged_card,\n \"Invalid target: parent_card.children[index_of_dragged_card] !== dragged_card\",\n )\n assert(parent_card !== board.root, \"Invalid state: parent_card === board.root\")\n // `parent_card` must be either `top_level_card` or a descendant of `top_level_card` ...\n let level = parent_card.level\n assert(level > 0, `Invalid state: parent_card.level === ${level}`)\n let temp = parent_card\n while (level > 1) {\n temp = temp.parent\n --level\n assert(temp.level === level, \"temp.parent has unexpected level\")\n }\n assert(\n temp === top_level_card,\n \"Invalid state: parent_card is not (descendant of) top_level_card\",\n )\n }\n }\n\n /**\n * Returns `true` if the DOM reflects the current model.\n */\n is_DOM_in_sync_with_model(preview_elm: HTMLElement) {\n const preview_column_elm = preview_elm.closest(\".dnd__column\") as HTMLElement\n assert(\n preview_column_elm,\n `preview_elm.closest(\".dnd__column\") returned: ${preview_column_elm}`,\n )\n const preview_board = determine_board(preview_elm)\n const preview_top_level_card = determine_top_level_card(preview_board, preview_column_elm)\n const {target} = this\n if (preview_board !== target.board) {\n return false\n }\n if (preview_top_level_card !== target.top_level_card) {\n return false\n }\n if (target.new_column) {\n return true\n }\n try {\n const {elm: preview_parent_elm, card: preview_parent_card} = determine_parent(\n preview_board,\n preview_elm,\n )\n if (preview_parent_card !== target.parent_card) {\n return false\n }\n const model_children_uids = preview_parent_card.children.map((card) => card.uid)\n const dragged_card_uid = this.dragged_card.uid\n assert(\n model_children_uids[target.index_of_dragged_card] === dragged_card_uid,\n \"model_children_uids[target.index_of_dragged_card] !== dragged_card_uid\",\n )\n const temp = new Set(model_children_uids)\n const dom_children_uids = (\n [...preview_parent_elm.querySelectorAll(\".dnd__card\")] as HTMLElement[]\n )\n .map((elm) => elm.dataset.cardUid as CardUID)\n .filter((uid) => temp.has(uid))\n // Note: `model_children_uids` might contain more items because of archived cards,\n // therefore we check only the order here ...\n const uids_above = new Set(model_children_uids.splice(0, target.index_of_dragged_card))\n const uids_below = new Set(model_children_uids)\n let visited_dragged_card_uid = false\n for (const uid of dom_children_uids) {\n if (uid === dragged_card_uid) {\n visited_dragged_card_uid = true\n } else {\n const set = visited_dragged_card_uid ? uids_below : uids_above\n if (!set.has(uid)) {\n return false\n }\n }\n }\n return true\n } catch (error) {\n log.debug(\"[dnd] DragAndDrop.is_DOM_in_sync failed\", error)\n return false\n }\n }\n\n setup_scroll_on_drag = () => {\n this.init_scroll_horizontal_on_drag_areas()\n this.init_scroll_vertical_on_drag_areas()\n const scroll_on_drag_interval_handler = () => {\n if (this.active_scroll_horizontal_drag_area) {\n const ms = performance.now() - this.scroll_horizontal_start_time!\n if (ms > SCROLL_DELAY) {\n const delta = Math.min((ms - SCROLL_DELAY) / 20, 250)\n this.active_scroll_horizontal_drag_area.scroll(delta)\n }\n }\n if (this.active_scroll_vertical_drag_area) {\n const ms = performance.now() - this.scroll_vertical_start_time!\n if (ms > SCROLL_DELAY) {\n const delta = Math.min((ms - SCROLL_DELAY) / 20, 250)\n this.active_scroll_vertical_drag_area.scroll(delta)\n }\n }\n }\n this.scroll_on_drag_interval_id = setInterval(scroll_on_drag_interval_handler, 33)\n }\n\n init_scroll_horizontal_on_drag_areas() {\n const {scroll_left, scroll_right} = _scroll_horizontal()\n this.scroll_horizontal_on_drag_areas.push({\n is_inside: (x) => {\n const layout = ui_state.layout_state.layout\n let min = 50\n if (layout.aux_layout.visible) {\n min += layout.aux_layout.column_width\n }\n if (ui_state.desktop_board_chooser_state !== \"hidden\") {\n min += 305\n }\n return x < min\n },\n scroll: scroll_left,\n })\n this.scroll_horizontal_on_drag_areas.push({\n is_inside: (x: number) => {\n let min = ui_state.layout_state.view_port_width\n if (!min) {\n return false\n }\n min = Math.max(min - 50, 0)\n if (ui_state.desktop_board_chooser_state !== \"hidden\") {\n min += 305\n }\n return x > min\n },\n scroll: scroll_right,\n })\n }\n\n init_scroll_vertical_on_drag_areas() {\n const elements = document.getElementsByClassName(\"dnd--scroll-vertically\")\n const n = elements.length\n if (!n) {\n log.warn(\"No elements with CSS class 'dnd--scroll-vertically'\")\n return\n }\n for (let i = 0; i < n; ++i) {\n const elm = elements.item(i) as HTMLElement\n const r = elm.getBoundingClientRect()\n const y_scroll_up = r.top + Math.min(r.height * 0.15, 100)\n this.scroll_vertical_on_drag_areas.push({\n is_inside: (x, y) => {\n const {left, right} = elm.getBoundingClientRect()\n return x >= left && x < right && y < y_scroll_up\n },\n scroll: _scroll_up.bind(null, elm),\n })\n const y_scroll_down = r.bottom - Math.min(r.height * 0.15, 100)\n this.scroll_vertical_on_drag_areas.push({\n is_inside: (x, y) => {\n const {left, right} = elm.getBoundingClientRect()\n return x >= left && x < right && y > y_scroll_down\n },\n scroll: _scroll_down.bind(null, elm),\n })\n }\n }\n\n on_drag(event: MouseEvent) {\n const {aborted} = this\n if (aborted) {\n return\n }\n const x = event.clientX\n const y = event.clientY\n this.mouse_cursor_x = x\n this.mouse_cursor_y = y\n // Check if we must update `this.active_scroll_horizontal_drag_area`\n // and `this.scroll_horizontal_start_time` ...\n const h = this.active_scroll_horizontal_drag_area\n if (!(h && h.is_inside(x, y))) {\n this.active_scroll_horizontal_drag_area = undefined\n for (const area of this.scroll_horizontal_on_drag_areas) {\n if (area.is_inside(x, y)) {\n this.active_scroll_horizontal_drag_area = area\n this.scroll_horizontal_start_time = performance.now()\n break\n }\n }\n }\n // Check if we must update `this.active_scroll_vertical_drag_area`\n // and `this.scroll_vertical_start_time` ...\n const v = this.active_scroll_vertical_drag_area\n if (!(v && v.is_inside(x, y))) {\n this.active_scroll_vertical_drag_area = undefined\n for (const area of this.scroll_vertical_on_drag_areas) {\n if (area.is_inside(x, y)) {\n this.active_scroll_vertical_drag_area = area\n this.scroll_vertical_start_time = performance.now()\n break\n }\n }\n }\n // Syncing the model is CPU intensive, therefore we schedule it after 50 ms ...\n if (!this.sync_model_timeout_id) {\n this.sync_model_timeout_id = setTimeout(this.sync_model, 50)\n }\n }\n\n on_drop(event?: MouseEvent) {\n const t0 = performance.now()\n try {\n this.on_drop_called = true\n if (this.aborted) {\n return\n }\n if (this.board_changed()) {\n this.abort({reason: \"Board changed during drag & drop\", report: true})\n return\n }\n clearInterval(this.scroll_on_drag_interval_id)\n let card_moved = false\n runInAction(() => {\n this.ghost.reset()\n // Note: During testing the \"pointerUp\" action will lead to a \"mouseup\" event\n // with the coordinates 0, 0 ...\n if (event && (event.clientX !== 0 || event.clientY !== 0)) {\n this.on_drag(event)\n }\n if (this.sync_model_timeout_id) {\n clearTimeout(this.sync_model_timeout_id)\n this.sync_model()\n }\n this.dragged_card._is_dragged = undefined\n const {dragged_card, source, target} = this\n card_moved =\n target.new_column ||\n source.parent_card !== target.parent_card ||\n source.index_of_dragged_card !== target.index_of_dragged_card\n log.debug(`[dnd] Dropped ${this.desc}${card_moved ? \"\" : \" at source location\"}`)\n this.cancel_pending_add_new_column()\n if (card_moved) {\n this.restore_state()\n if (target.new_column) {\n const {top_level_card: new_column_card, index_of_new_column_card} = target\n optimistic_update(\n target.board.uid,\n new AddCard({\n value: new AddCardValue({\n uid: new_column_card.uid,\n column: new Column({}),\n }),\n target_card_uid: target.board.root.uid,\n target_pos: index_of_new_column_card,\n }),\n )\n optimistic_update(\n source.board.uid,\n new MoveCard({\n uid: dragged_card.uid,\n target_board_uid: target.board.uid,\n target_card_uid: new_column_card.uid,\n target_pos: 0,\n }),\n )\n } else {\n const {parent_card, index_of_dragged_card} = target\n optimistic_update(\n source.board.uid,\n new MoveCard({\n uid: dragged_card.uid,\n target_board_uid: target.board.uid,\n target_card_uid: parent_card.uid,\n target_pos: index_of_dragged_card,\n }),\n )\n }\n report_user_engagement(EngagementType.move_card)\n const undo_op = new MoveCard({\n uid: dragged_card.uid,\n target_board_uid: source.board.uid,\n target_card_uid: source.parent_card.uid,\n target_pos: source.index_of_dragged_card,\n })\n Snackbar.show_message(\n i18n.moved_cards(1 + dragged_card.num_deep_children),\n i18n.undo,\n () => {\n optimistic_update(target.board.uid, undo_op)\n if (target.new_column) {\n const {top_level_card: new_column_card} = target\n optimistic_update(\n target.board.uid,\n new RemoveCard({uid: new_column_card.uid}),\n )\n }\n },\n )\n }\n })\n } finally {\n const dt = performance.now() - t0\n if (dt > 500) {\n report_info(`DragAndDrop.on_drop() took very long: ${Math.round(dt)} ms`)\n }\n ui_state.layout_state.unfreeze_layout()\n ;(cling as any).drag_and_drop = undefined\n document.body.classList.remove(\"dnd--dragging\")\n }\n }\n\n abort({reason, report, error}: {reason: string; report?: true; error?: Error}) {\n const m = `[dnd] ${reason}${this.aborted ? \"\" : \" -- aborting drag & drop\"}`\n if (error) {\n report_error(m, error)\n } else if (report) {\n report_info(m)\n } else {\n log.info(m)\n }\n if (this.aborted) {\n return\n }\n this.aborted = true\n clearInterval(this.scroll_on_drag_interval_id)\n this.cancel_pending_add_new_column()\n runInAction(() => {\n this.ghost.reset()\n this.dragged_card._is_dragged = undefined\n this.restore_state()\n })\n ui_state.layout_state.unfreeze_layout()\n ;(cling as any).drag_and_drop = undefined\n document.body.classList.remove(\"dnd--dragging\")\n }\n\n on_error(error: Error) {\n this.abort({\n reason: `Error while ${this.on_drop_called ? \"dropping\" : \"dragging\"} card`,\n error,\n })\n }\n\n sync_model = () => {\n const t0 = performance.now()\n try {\n if (this.aborted) {\n return\n }\n if (this.board_changed()) {\n this.abort({reason: \"Board changed during drag & drop\"})\n return\n }\n const ghost_elm = document.querySelector(\".dnd__ghost\") as HTMLElement\n if (!ghost_elm) {\n log.debug(\"[dnd] Ghost not mounted\")\n return\n }\n const preview_elm = document.querySelector(\".dnd__preview\") as HTMLElement\n if (!preview_elm) {\n log.debug(\"[dnd] Preview not mounted\")\n return\n }\n if (!this.is_DOM_in_sync_with_model(preview_elm)) {\n log.debug(\"[dnd] DOM not in sync with model\")\n return\n }\n let ghost_rect = ghost_elm.getBoundingClientRect() as BoundingClientRect\n // The ghost might be smaller than the grabbed card, fix `grabbed_at` if needed ...\n const {mouse_cursor_x: x, mouse_cursor_y: y, grabbed_at} = this\n let move_ghost = false\n if (grabbed_at.x > ghost_rect.width) {\n grabbed_at.x = ghost_rect.width\n move_ghost = true\n }\n if (grabbed_at.y < 0) {\n grabbed_at.y = 0\n }\n if (grabbed_at.y > ghost_rect.height) {\n grabbed_at.y = ghost_rect.height\n move_ghost = true\n }\n const ghost_left = x - grabbed_at.x\n const ghost_top = y - grabbed_at.y\n const {width: ghost_width, height: ghost_height} = ghost_rect\n ghost_rect = {\n left: ghost_left,\n width: ghost_width,\n right: ghost_left + ghost_width,\n top: ghost_top,\n height: ghost_height,\n bottom: ghost_top + ghost_height,\n }\n if (move_ghost && this.ghost) {\n this.ghost.move_to(ghost_left, ghost_top)\n }\n // Prevent flickering ...\n if (\n this.ghost_rect_when_moved &&\n Math.abs(this.ghost_rect_when_moved.left - ghost_rect.left) < 5 &&\n Math.abs(this.ghost_rect_when_moved.top - ghost_rect.top) < 5\n ) {\n // Do nothing.\n return\n }\n // Update model if needed ...\n const {target} = this\n const a = [...document.querySelectorAll(\".dnd__column\")] as HTMLElement[]\n let max_i = a.length - 1\n // We must first check, if the mouse cursor is over the aux column ...\n if (a[max_i].id === \"dnd__aux-column\") {\n const column_elm = a.pop()!\n const r = column_elm.getBoundingClientRect()\n if (x < r.right) {\n // Jep, drag & drop target is the aux column ...\n const board = determine_board(column_elm)\n const inbox_card = determine_top_level_card(board, column_elm)\n assert(inbox_card.inbox, \"Top level card of aux column is not an inbox card\")\n if (target.top_level_card === inbox_card) {\n this.move_card_in_column(\n board,\n inbox_card,\n column_elm,\n ghost_rect,\n preview_elm,\n )\n } else {\n this.move_card_to_another_column(board, inbox_card, column_elm, ghost_rect)\n }\n return\n }\n --max_i\n }\n for (let i = 0; i <= max_i; ++i) {\n let column_elm = a[i]\n const r = column_elm.getBoundingClientRect()\n if ((i === 0 || x >= r.left) && (x < r.right || i === max_i)) {\n const board = determine_board(column_elm)\n let top_level_card = determine_top_level_card(board, column_elm)\n assert(\n top_level_card.column || top_level_card.inbox,\n \"Top level card is neither a column nor an inbox card\",\n )\n if (\n target.new_column &&\n target.top_level_card === top_level_card &&\n x >= r.left + r.width / 2 &&\n i < max_i - 1\n ) {\n // Special case: We just inserted a new column before an existing column\n // and the mouse cursor is over the right half of the new column -- move\n // the dragged card into the next column (removing the new column) ...\n column_elm = a[i + 1]\n top_level_card = determine_top_level_card(board, column_elm)\n this.move_card_to_another_column(\n board,\n top_level_card,\n column_elm,\n ghost_rect,\n )\n return\n }\n // Special cases for inserting a new column ...\n if (x < r.left + ADD_NEW_COLUMN_AREA_WIDTH / 2) {\n if (target.new_column) {\n // Do nothing.\n } else {\n this.move_card_to_new_column(board, {before: top_level_card})\n }\n return\n } else if (x >= r.right - ADD_NEW_COLUMN_AREA_WIDTH / 2) {\n if (target.new_column) {\n // Do nothing.\n } else {\n this.move_card_to_new_column(board, {after: top_level_card})\n }\n return\n }\n if (target.top_level_card === top_level_card) {\n this.move_card_in_column(\n board,\n top_level_card,\n column_elm,\n ghost_rect,\n preview_elm,\n )\n } else {\n this.move_card_to_another_column(\n board,\n top_level_card,\n column_elm,\n ghost_rect,\n )\n }\n return\n }\n }\n // If this point is reached, we just removed the new column\n // and the animation, which moves the remaining columns to\n // their correct location has not finished yet -- do nothing.\n } catch (error) {\n this.on_error(error)\n } finally {\n this.sync_model_timeout_id = 0\n const dt = performance.now() - t0\n if (dt > 500) {\n report_info(`DragAndDrop.sync_model() took very long: ${Math.round(dt)} ms`)\n }\n }\n }\n\n private move_card_to_new_column(board: Board, where: {before: Card}): void\n private move_card_to_new_column(board: Board, where: {after: Card}): void\n private move_card_to_new_column(board: Board, where: {first_column: true}): void\n private move_card_to_new_column(\n board: Board,\n {before, after, first_column}: {before?: Card; after?: Card; first_column?: true},\n ): void {\n const key = before\n ? `before ${before.uid}`\n : after\n ? `after ${after.uid}`\n : first_column\n ? \"first_column\"\n : (() => {\n throw new Error(\"Invalid `where`\")\n })()\n if (this.pending_add_new_column_key === key) {\n return\n }\n const add_new_column = () => {\n try {\n this.pending_add_new_column_key = \"\"\n if (this.aborted || this.on_drop_called) {\n report_error(\"cancel_pending_add_new_column() not called\")\n return\n }\n log.debug(`[dnd] Moving ${this.desc} to new column ...`)\n if (!this.new_column_card_uid) {\n this.new_column_card_uid = create_CardUID()\n }\n runInAction(() => {\n const dragged_card = this.remove_preview()\n let index: number\n if (before) {\n index = board.root.children.findIndex((c) => c === before)\n assert(index >= 0, \"Did not find column card `before`\")\n } else if (after) {\n index = board.root.children.findIndex((c) => c === after) + 1\n assert(index > 0, \"Did not find column card `after`\")\n } else {\n index = 0\n }\n assert(this.new_column_card_uid)\n const new_column_card = new Card({\n uid: this.new_column_card_uid,\n changelog: [\n new CardChangelogEntry({\n patch_op_type: CardPatchOpType.AddCard,\n board_version: board.version,\n account_uid: current_user.account.uid,\n date: new Date(),\n }),\n ],\n column: new Column({}),\n children: [dragged_card],\n }) as ColumnCard\n board.root.children.splice(index, 0, new_column_card)\n ;(new_column_card as any)._parent = board.root\n ;(dragged_card as any)._parent = new_column_card\n this.target = {\n board,\n new_column: true,\n top_level_card: new_column_card,\n index_of_new_column_card: index,\n }\n this.assert_consistent_state()\n log.debug(`[dnd] Moved ${this.desc} to new column`)\n this.ghost_rect_when_moved = undefined\n })\n } catch (error) {\n this.on_error(error)\n }\n }\n // For a better UX, we do not immediately create a new column, but wait a little bit ...\n log.debug(`[dnd] Defer moving ${this.desc} to new column ...`)\n this.cancel_pending_add_new_column()\n this.pending_add_new_column_key = key\n this.pending_add_new_column_timeout_id = setTimeout(add_new_column, ADD_NEW_COLUMN_DELAY)\n }\n\n private cancel_pending_add_new_column() {\n if (this.pending_add_new_column_key) {\n log.debug(`[dnd] Canceled moving ${this.desc} to new column`)\n this.pending_add_new_column_key = \"\"\n clearTimeout(this.pending_add_new_column_timeout_id)\n }\n }\n\n private move_card_to_another_column(\n board: Board,\n top_level_card: ColumnCard | InboxCard,\n column_elm: HTMLElement,\n ghost_rect: BoundingClientRect,\n ) {\n this.cancel_pending_add_new_column()\n const {target} = this\n const from_aux_column = target.top_level_card.inbox\n let insert_pos = this.find_insert_position_in_column(\n board,\n top_level_card,\n column_elm,\n ghost_rect,\n )\n if (!insert_pos) {\n return\n }\n if (insert_pos.parent_card === board.root) {\n // Adapt `insert_pos` -- we don't replace column cards ...\n insert_pos = {parent_card: top_level_card, index: 0}\n }\n const {parent_card, index} = insert_pos\n if (target.parent_card === parent_card && target.index_of_dragged_card === index) {\n // Do nothing.\n return\n }\n log.debug(\n `[dnd] Moving ${this.desc} to ${top_level_card.inbox ? \"aux\" : \"another\"} column ...`,\n )\n runInAction(() => {\n const dragged_card = this.remove_preview()\n parent_card.children.splice(index, 0, dragged_card)\n ;(dragged_card as any)._parent = parent_card\n this.target = {\n board,\n top_level_card,\n parent_card,\n index_of_dragged_card: index,\n }\n this.assert_consistent_state()\n const to_aux_column = this.target.top_level_card.inbox\n if (from_aux_column && to_aux_column) {\n log.debug(`[dnd] Moved ${this.desc} from aux column to aux column`)\n } else if (from_aux_column) {\n log.debug(`[dnd] Moved ${this.desc} from aux column to another column`)\n } else if (to_aux_column) {\n log.debug(`[dnd] Moved ${this.desc} to aux column`)\n } else {\n log.debug(`[dnd] Moved ${this.desc} to another column`)\n }\n this.ghost_rect_when_moved = ghost_rect\n })\n }\n\n private move_card_in_column(\n board: Board,\n top_level_card: ColumnCard | InboxCard,\n column_elm: HTMLElement,\n ghost_rect: BoundingClientRect,\n preview_elm: HTMLElement,\n ) {\n this.cancel_pending_add_new_column()\n const {target} = this\n assert(target.top_level_card === top_level_card)\n if (target.new_column) {\n // Do nothing.\n return\n }\n const insert_pos = this.find_insert_position_in_column(\n board,\n top_level_card,\n column_elm,\n ghost_rect,\n preview_elm,\n )\n if (!insert_pos) {\n return\n }\n const {parent_card} = insert_pos\n if (parent_card === this.dragged_card) {\n // Do nothing.\n return\n }\n assert(target.board === board, \"target.board !== board\")\n const {index} = insert_pos\n if (parent_card === target.parent_card && index === target.index_of_dragged_card) {\n // Do nothing.\n return\n }\n log.debug(`[dnd] Moving ${this.desc} in ${top_level_card.inbox ? \"aux \" : \"\"}column ...`)\n runInAction(() => {\n const dragged_card = this.remove_preview()\n parent_card.children.splice(index, 0, dragged_card)\n ;(dragged_card as any)._parent = parent_card\n this.target = {\n board,\n top_level_card,\n parent_card,\n index_of_dragged_card: index,\n }\n this.assert_consistent_state()\n log.debug(`[dnd] Moved ${this.desc} in ${top_level_card.inbox ? \"aux \" : \"\"}column`)\n this.ghost_rect_when_moved = ghost_rect\n })\n }\n\n private find_insert_position_in_column(\n board: Board,\n top_level_card: ColumnCard | InboxCard,\n column_elm: HTMLElement,\n ghost_rect: BoundingClientRect,\n preview_elm_if_preview_in_same_column?: HTMLElement,\n ):\n | {\n parent_card: Card\n index: number\n }\n | undefined {\n const {top: ghost_top} = ghost_rect\n let a = [\n ...column_elm.querySelectorAll(\n \".dnd__card,.dnd__collapsed-cards,.dnd__insertion-point\",\n ),\n ] as HTMLElement[]\n if (preview_elm_if_preview_in_same_column) {\n a = a.filter((x) => !this.dragged_card_descendants_uids.has(x.dataset.cardUid as any))\n }\n const max_i = a.length - 1\n if (process.env.NODE_ENV !== \"production\") {\n assert(max_i >= 0, \"At least one insertion point expected\")\n for (let j = 0; j <= max_i; ++j) {\n if (j < max_i) {\n assert(\n a[j].classList.contains(\"dnd__card\") ||\n a[j].classList.contains(\"dnd__collapsed-cards\"),\n \"Unexpected insertion point\",\n )\n } else {\n assert(\n a[j].classList.contains(\"dnd__insertion-point\"),\n \"a[max_i] should be an insertion point\",\n )\n }\n }\n }\n const insert_as_last_visible_child_of = (parent_card: Card) => {\n // Note: We try to insert the dragged card below the last visible card,\n // so that it will be inserted *before* any hidden archived cards ...\n const visible_children = ui_state.search_state.visible_children(parent_card)\n const n = visible_children.length\n if (n === 0) {\n return {parent_card, index: 0}\n }\n const last_visible_card_uid = visible_children[n - 1].uid\n if (last_visible_card_uid !== this.dragged_card.uid) {\n let index = parent_card.children.findIndex((c) => c.uid === last_visible_card_uid)\n // Because the dragged card should be inserted after the last visible children,\n // we need to add 1 unless the dragged card is already a child of `parent_card` ...\n if (\n !preview_elm_if_preview_in_same_column ||\n !parent_card.children.includes(this.dragged_card)\n ) {\n index += 1\n }\n return {parent_card, index}\n }\n }\n const insert_here = (best_i: number, best_elm: HTMLElement) => {\n assert(a[best_i] === best_elm)\n const {parent_card: preview_parent, index_of_dragged_card: preview_index} = this.target\n const card_uid = best_elm.dataset.cardUid\n if (best_elm.classList.contains(\"dnd__card\")) {\n let p = determine_parent(board, best_elm).card\n let i = p.children.findIndex((c) => c.uid === card_uid)\n assert(i >= 0)\n const elm_above = best_i > 0 && a[best_i - 1]\n // The dragged card should take the place of `best_elm` ...\n if (elm_above && elm_above === preview_elm_if_preview_in_same_column) {\n // Special case: We can't just remove the dragged card and insert it again\n // where the card represented by `best_elm` is located, because that would\n // leave the preview in the same place. Instead ...\n if (best_elm.classList.contains(\"dnd__has-visible-children\")) {\n p = p.children[i]\n i = 0\n } else {\n // Do nothing -- Because we don't adapt i, when the dragged card is\n // removed and inserted again, it will be inserted *after* the card\n // represented by `best_elm`.\n }\n } else {\n // We might need to adapt i, because the dragged card will be removed,\n // before it is inserted again ...\n if (p === preview_parent && i > preview_index!) {\n i -= 1\n }\n }\n if (elm_above) {\n const elm_above_bottom = bounds(elm_above).bottom\n // Adapt the indentation level if necessary/possible ...\n if (\n ghost_top < elm_above_bottom &&\n (!preview_elm_if_preview_in_same_column ||\n best_elm === preview_elm_if_preview_in_same_column) &&\n elm_above.classList.contains(\"dnd__card\") &&\n !elm_above.classList.contains(\"dnd__has-visible-children\")\n ) {\n // The dragged card should be a sibling of the card\n // represented by `elm_above` ...\n const card_above_uid = as_CardUID(elm_above.dataset.cardUid)\n const card_above = this.get_card(board, card_above_uid)\n const parent_of_card_above = card_above.parent\n if (parent_of_card_above !== p) {\n p = parent_of_card_above\n i = p.children.findIndex((c) => c.uid === card_above_uid) + 1\n }\n } else if (\n ghost_top > elm_above_bottom &&\n best_elm === preview_elm_if_preview_in_same_column &&\n elm_above.classList.contains(\"dnd__card\")\n ) {\n // Try to decrease indent ...\n const card_above_uid = as_CardUID(elm_above.dataset.cardUid)\n const card_above = this.get_card(board, card_above_uid)\n const parent_of_card_above = card_above.parent\n if (parent_of_card_above === p) {\n assert(best_i < max_i)\n const elm_below = a[best_i + 1]\n if (elm_below.classList.contains(\"dnd__card\")) {\n const card_below_uid = as_CardUID(elm_below.dataset.cardUid)\n const card_below = this.get_card(board, card_below_uid)\n const parent_of_card_below = card_below.parent\n if (parent_of_card_below !== p) {\n p = parent_of_card_below\n i = p.children.findIndex((c) => c.uid === card_below_uid)\n }\n } else if (elm_below.classList.contains(\"dnd__insertion-point\")) {\n return insert_as_last_visible_child_of(top_level_card)\n }\n }\n }\n }\n return {parent_card: p, index: i}\n } else if (best_elm.classList.contains(\"dnd__collapsed-cards\")) {\n // The dragged card should be the first child of `best_elm` ...\n const parent_card = determine_parent(board, best_elm).card\n return {parent_card, index: 0}\n } else if (best_elm.classList.contains(\"dnd__insertion-point\")) {\n // Insert dragged card at bottom of column ...\n return insert_as_last_visible_child_of(top_level_card)\n } else {\n throw new Error(\"Unexpected `best_elm`: \" + safe_to_string(best_elm))\n }\n }\n // Here is the idea: Find the insertion position for the preview,\n // where the vertical distance to the ghost is minimal ...\n if (preview_elm_if_preview_in_same_column) {\n // PERF: Start searching for the best insertion position at the preview ...\n const preview_top = bounds(preview_elm_if_preview_in_same_column).top\n let best_elm = preview_elm_if_preview_in_same_column\n let best_i = a.indexOf(best_elm)\n assert(best_i >= 0)\n const d = ghost_top - preview_top\n if (d < 0 && best_i > 0) {\n // Check if the preview would fit better above its current position ...\n let best_top = preview_top!\n let i = best_i - 1\n let elm = a[i]\n let {top} = bounds(elm)\n while (Math.abs(top - ghost_top) < Math.abs(best_top - ghost_top)) {\n best_i = i\n best_elm = elm\n best_top = top\n if (best_i === 0) {\n break\n }\n elm = a[--i]\n top = bounds(elm).top\n }\n } else {\n assert(best_i < max_i) // ... because a[max_i] cannot be the preview\n // Check if the preview would fit better below its current position ...\n let best_d = d\n let i = best_i + 1\n let elm = a[i]\n let {top} = bounds(elm)\n const preview_height = top - preview_top\n while (i < max_i) {\n const elm_below = a[i + 1]\n const top_below = bounds(elm_below).top\n const elm_height = top_below - top\n const preview_top_if_moved = top + elm_height - preview_height\n const d_if_moved = Math.abs(preview_top_if_moved - ghost_top)\n if (d_if_moved > best_d) {\n break\n }\n best_i = i\n best_elm = elm\n best_d = d_if_moved\n i += 1\n elm = elm_below\n top = top_below\n }\n if (i === max_i) {\n const d_if_moved = Math.abs(top - ghost_top)\n if (d_if_moved < best_d) {\n best_i = i\n best_elm = elm\n }\n }\n }\n return insert_here(best_i, best_elm)\n } else {\n // Find best insert position in column without preview ...\n let best_elm = a[0]\n let best_r = bounds(best_elm)\n if (ghost_top < best_r.top) {\n // Best insert position is top of column ...\n return {\n parent_card: top_level_card,\n index: 0,\n }\n }\n for (let i = 1; i <= max_i; ++i) {\n const elm = a[i]\n const r = bounds(elm)\n if (r.top < ghost_top) {\n best_elm = elm\n best_r = r\n } else {\n // best_r.top < ghost_top <= r.top\n if (ghost_top - best_r.top < r.top - ghost_top) {\n // The top border of the ghost is in the upper half of `best_elm` ...\n return insert_here(i - 1, best_elm)\n } else {\n // The top border of the ghost is in the lower half of `best_elm` ...\n return insert_here(i, elm)\n }\n }\n }\n // Best insert position is bottom of column ...\n return insert_as_last_visible_child_of(top_level_card)\n }\n }\n\n private restore_state() {\n const target_board = this.target.board\n const target_board_changed = target_board !== board_resource.read(target_board.uid)\n if (!target_board_changed) {\n try {\n this.remove_preview()\n } catch (error) {\n const m = \"DragAndDrop.remove_preview() failed\"\n report_error(m, error)\n if (process.env.NODE_ENV === \"production\") {\n reload(m)\n }\n }\n }\n const {\n dragged_card,\n source: {board: source_board, parent_card, index_of_dragged_card},\n } = this\n const source_board_changed = source_board !== board_resource.read(source_board.uid)\n if (!source_board_changed) {\n parent_card.children.splice(index_of_dragged_card, 0, dragged_card)\n ;(dragged_card as any)._parent = parent_card\n }\n }\n\n /**\n * Returns the dragged card.\n */\n private remove_preview() {\n this.assert_consistent_state()\n const {dragged_card, target} = this\n if (target.new_column) {\n const {board, index_of_new_column_card: i, top_level_card} = target\n const new_column_card = board.root.children[i]\n assert(\n new_column_card === top_level_card,\n \"board.root.children[target.index_of_new_column_card] !== target.top_level_card\",\n )\n assert(\n new_column_card === top_level_card,\n \"board.root.children[target.index_of_new_column_card] !== target.top_level_card\",\n )\n assert(\n new_column_card.children[0] === this.dragged_card,\n \"new_column_card.children[0] !== dragged_card\",\n )\n board.root.children.splice(i, 1)\n } else {\n const {parent_card, index_of_dragged_card: i} = target\n assert(\n parent_card!.children[i] === dragged_card,\n \"target.parent_card.children[target.index_of_dragged_card] !== dragged_card\",\n )\n parent_card!.children.splice(i, 1)\n }\n return dragged_card\n }\n\n private get_card(board: Board, card_uid: CardUID): Card {\n const cache_key = board.uid + \":\" + card_uid\n let card = this.get_card_cache.get(cache_key)\n if (!card) {\n card = board.card(card_uid)\n this.get_card_cache.set(cache_key, card)\n }\n return card\n }\n\n private board_changed() {\n const source_board = this.source.board\n if (source_board !== board_resource.read(source_board.uid)) {\n return true\n }\n const target_board = this.target.board\n if (\n target_board !== source_board &&\n target_board !== board_resource.read(target_board.uid)\n ) {\n return true\n }\n }\n}\n\nfunction bounds(elm: HTMLElement) {\n if (elm.classList.contains(\"dnd__card\")) {\n elm = elm.querySelector(\".card\")!\n }\n return elm.getBoundingClientRect()\n}\n\nfunction determine_board(elm: HTMLElement): Board {\n const board_elm = elm.closest(\".dnd__board\") as HTMLElement\n assert(board_elm, `elm.closest(\".dnd__board\") => ${board_elm}`)\n const board_uid = board_elm.dataset.boardUid as BoardUID\n assert(is_BoardUID(board_uid), `board_elm.dataset.boardUid => ${board_uid}`)\n const board = board_resource.read(board_uid)\n assert(board, \"board not in board_resource.cached\")\n return board!\n}\n\nfunction determine_top_level_card(board: Board, column_elm: HTMLElement): ColumnCard | InboxCard {\n const top_level_card_elm = column_elm.querySelector(\".dnd__top-level-card\") as HTMLElement\n const top_level_card_uid = top_level_card_elm.dataset.cardUid\n const top_level_card = board.root.children.find((c) => c.uid === top_level_card_uid)!\n assert(\n top_level_card,\n `board.root.children.find(c => c.uid === top_level_card_uid) => ${top_level_card}`,\n )\n assert(top_level_card.column || top_level_card.inbox, \"Invalid top level card\")\n return top_level_card as ColumnCard | InboxCard\n}\n\nfunction determine_parent(\n board: Board,\n elm: HTMLElement,\n): {\n card: Card\n elm: HTMLElement\n} {\n let parent_elm: HTMLElement | undefined\n const ancestor_uids = [] as Array<CardUID>\n for (;;) {\n const parent_card_elm = elm.parentElement!.closest(\".dnd__card\") as HTMLElement\n if (!parent_card_elm) {\n break\n }\n elm = parent_card_elm\n if (!parent_elm) {\n parent_elm = elm\n }\n ancestor_uids.unshift(elm.dataset.cardUid as CardUID)\n }\n const top_level_card_elm = elm.closest(\".dnd__top-level-card\") as HTMLElement\n assert(\n top_level_card_elm,\n \"Did not find enclosing element with CSS class 'dnd__top-level-card'\",\n )\n if (!parent_elm) {\n parent_elm = top_level_card_elm\n }\n ancestor_uids.unshift(top_level_card_elm.dataset.cardUid as CardUID)\n let card = board.root\n for (const uid of ancestor_uids) {\n card = card.children.find((c) => c.uid === uid)!\n assert(\n card,\n `Did not find card ${uid} in children of card ${card.uid} on board ${board.uid}`,\n )\n }\n return {elm: parent_elm, card}\n}\n\nfunction determine_source(card_uid: CardUID, card_elm: HTMLElement): DragSource {\n const board = determine_board(card_elm)\n const column_elm = card_elm.closest(\".dnd__column\") as HTMLElement\n assert(column_elm, `card_elm.closest(\".dnd__column\") => ${column_elm}`)\n const top_level_card = determine_top_level_card(board, column_elm)\n const parent_card = determine_parent(board, card_elm).card\n const i = parent_card.children.findIndex((c) => c.uid === card_uid)\n assert(i >= 0, `Did not find card ${card_uid} in children of card ${parent_card.uid}`)\n const dragged_card = parent_card.children[i]\n return {\n board,\n top_level_card,\n parent_card,\n index_of_dragged_card: i,\n dragged_card,\n }\n}\n\nexport default DragAndDropGhost\n"], "mappings": "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", "names": ["init_compat_module", "MIN_DRAG_DISTANCE", "ADD_NEW_COLUMN_AREA_WIDTH", "ADD_NEW_COLUMN_DELAY", "SCROLL_DELAY", "current_ghost", "_a", "DragAndDropGhost", "observer", "x", "props", "__publicField", "__name", "ref", "style", "left", "top", "width", "y", "w", "makeObservable", "observable", "action", "drag_and_drop", "report_error", "ghost_card", "_", "start_drag_card", "mousedown_event", "card_uid", "ignore_click_at", "dragged_card_elm", "assert", "source", "determine_source", "dragged_card_rect", "dragged_card_width", "ignore_click", "move_ghost_request_id", "mouse_cursor_x", "mouse_cursor_y", "x0", "y0", "grabbed_at", "move_ghost", "handle_error", "f", "event", "error", "remove_event_listeners", "on_mousemove", "runInAction", "DragAndDrop", "ui_actions", "on_mouseup", "on_keydown", "on_window_blur", "_scroll_horizontal", "_block_horizontal_scroll", "scroll", "dir", "ui_state", "_scroll_up", "elm", "delta", "scroll_top", "_scroll_down", "max_scroll_top", "_DragAndDrop", "ghost", "mouse_down_event", "scroll_on_drag_interval_handler", "ms", "t0", "ghost_elm", "log", "preview_elm", "ghost_rect", "ghost_left", "ghost_top", "ghost_width", "ghost_height", "target", "a", "max_i", "column_elm", "r", "board", "determine_board", "inbox_card", "determine_top_level_card", "i", "top_level_card", "dt", "report_info", "parent_card", "index_of_dragged_card", "dragged_card", "Card", "c", "new_column_card", "index", "n", "level", "temp", "preview_column_elm", "preview_board", "preview_top_level_card", "preview_parent_elm", "preview_parent_card", "determine_parent", "model_children_uids", "card", "dragged_card_uid", "dom_children_uids", "uid", "uids_above", "uids_below", "visited_dragged_card_uid", "scroll_left", "scroll_right", "layout", "min", "elements", "y_scroll_up", "right", "y_scroll_down", "aborted", "h", "area", "v", "card_moved", "index_of_new_column_card", "optimistic_update", "AddCard", "AddCardValue", "Column", "MoveCard", "report_user_engagement", "undo_op", "Snackbar", "i18n", "RemoveCard", "reason", "report", "m", "before", "after", "first_column", "key", "add_new_column", "create_CardUID", "CardChangelogEntry", "current_user", "from_aux_column", "insert_pos", "to_aux_column", "preview_elm_if_preview_in_same_column", "insert_as_last_visible_child_of", "visible_children", "last_visible_card_uid", "insert_here", "best_i", "best_elm", "preview_parent", "preview_index", "p", "elm_above", "elm_above_bottom", "bounds", "card_above_uid", "as_CardUID", "parent_of_card_above", "elm_below", "card_below_uid", "parent_of_card_below", "safe_to_string", "preview_top", "d", "best_top", "best_d", "preview_height", "top_below", "elm_height", "preview_top_if_moved", "d_if_moved", "best_r", "target_board", "board_resource", "source_board", "cache_key", "board_elm", "board_uid", "is_BoardUID", "top_level_card_uid", "parent_elm", "ancestor_uids", "parent_card_elm", "top_level_card_elm", "card_elm", "drag_and_drop_default"] }