@fc3/mmcadi 0.1.50 → 0.1.52

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/dist/client.js CHANGED
@@ -968,18 +968,18 @@
968
968
  "node_modules/@fc3/time/dist/src/enum/time-interval.js"(exports) {
969
969
  "use strict";
970
970
  Object.defineProperty(exports, "__esModule", { value: true });
971
- var TimeInterval2;
972
- (function(TimeInterval3) {
973
- TimeInterval3[TimeInterval3["ONE_FRAME"] = 16] = "ONE_FRAME";
974
- TimeInterval3[TimeInterval3["ONE_SECOND"] = 1e3] = "ONE_SECOND";
975
- TimeInterval3[TimeInterval3["ONE_MINUTE"] = 6e4] = "ONE_MINUTE";
976
- TimeInterval3[TimeInterval3["ONE_HOUR"] = 36e5] = "ONE_HOUR";
977
- TimeInterval3[TimeInterval3["ONE_DAY"] = 864e5] = "ONE_DAY";
978
- TimeInterval3[TimeInterval3["ONE_WEEK"] = 6048e5] = "ONE_WEEK";
979
- TimeInterval3[TimeInterval3["ONE_MONTH"] = 2592e6] = "ONE_MONTH";
980
- TimeInterval3[TimeInterval3["ONE_YEAR"] = 31536e6] = "ONE_YEAR";
981
- })(TimeInterval2 || (TimeInterval2 = {}));
982
- exports.default = TimeInterval2;
971
+ var TimeInterval3;
972
+ (function(TimeInterval4) {
973
+ TimeInterval4[TimeInterval4["ONE_FRAME"] = 16] = "ONE_FRAME";
974
+ TimeInterval4[TimeInterval4["ONE_SECOND"] = 1e3] = "ONE_SECOND";
975
+ TimeInterval4[TimeInterval4["ONE_MINUTE"] = 6e4] = "ONE_MINUTE";
976
+ TimeInterval4[TimeInterval4["ONE_HOUR"] = 36e5] = "ONE_HOUR";
977
+ TimeInterval4[TimeInterval4["ONE_DAY"] = 864e5] = "ONE_DAY";
978
+ TimeInterval4[TimeInterval4["ONE_WEEK"] = 6048e5] = "ONE_WEEK";
979
+ TimeInterval4[TimeInterval4["ONE_MONTH"] = 2592e6] = "ONE_MONTH";
980
+ TimeInterval4[TimeInterval4["ONE_YEAR"] = 31536e6] = "ONE_YEAR";
981
+ })(TimeInterval3 || (TimeInterval3 = {}));
982
+ exports.default = TimeInterval3;
983
983
  }
984
984
  });
985
985
 
@@ -2180,7 +2180,7 @@
2180
2180
  // src/client/page/cursor.ts
2181
2181
  var import_errors9 = __toESM(require_src2());
2182
2182
  var import_array = __toESM(require_src3());
2183
- var import_time = __toESM(require_src6());
2183
+ var import_time2 = __toESM(require_src6());
2184
2184
 
2185
2185
  // src/client/utility/get-meta-value.ts
2186
2186
  var import_errors5 = __toESM(require_src2());
@@ -2243,6 +2243,7 @@
2243
2243
  var media_ready_state_default = MediaReadyState;
2244
2244
 
2245
2245
  // src/client/helper/interaction.ts
2246
+ var import_time = __toESM(require_src6());
2246
2247
  var import_errors8 = __toESM(require_src2());
2247
2248
 
2248
2249
  // src/enum/action-type.ts
@@ -2262,111 +2263,6 @@
2262
2263
  })(ActionType || {});
2263
2264
  var action_type_default = ActionType;
2264
2265
 
2265
- // src/enum/emoji.ts
2266
- var Emoji = /* @__PURE__ */ ((Emoji2) => {
2267
- Emoji2["USER_PORTRAIT"] = "\u{1F464}";
2268
- Emoji2["WARNING_SIGN"] = "\u26A0\uFE0F";
2269
- Emoji2["BAR_CHART"] = "\u{1F4CA}";
2270
- Emoji2["FOLDER"] = "\u{1F5C2}\uFE0F";
2271
- Emoji2["FILE"] = "\u{1F4C4}";
2272
- Emoji2["HOUSE"] = "\u{1F3E0}";
2273
- Emoji2["NONE"] = "\u{1F6AB}";
2274
- Emoji2["WHITE_SQUARE"] = "\u2B1C";
2275
- Emoji2["GRID_GLOBE"] = "\u{1F310}";
2276
- Emoji2["SATELLITE_DISH"] = "\u{1F4E1}";
2277
- Emoji2["COMPLETED_CHECKMARK"] = "\u2705";
2278
- Emoji2["RED_X"] = "\u274C";
2279
- Emoji2["CLOCK"] = "\u{1F552}";
2280
- Emoji2["SUNSHINE"] = "\u{1F506}";
2281
- Emoji2["ALARM_CLOCK"] = "\u23F0";
2282
- Emoji2["MAGNIFYING_GLASS"] = "\u{1F50E}";
2283
- Emoji2["MAGIC_WAND"] = "\u{1FA84}";
2284
- Emoji2["CALENDAR"] = "\u{1F4C5}";
2285
- Emoji2["LOCKED"] = "\u{1F512}";
2286
- Emoji2["UNLOCKED"] = "\u{1F513}";
2287
- Emoji2["NORTHWEST_ARROW"] = "\u2196\uFE0F";
2288
- Emoji2["RIGHT_ARROW"] = "\u27A1\uFE0F";
2289
- Emoji2["LEFT_ARROW"] = "\u2B05\uFE0F";
2290
- Emoji2["UP_ARROW"] = "\u2B06\uFE0F";
2291
- Emoji2["UP_DOWN_ARROW"] = "\u2195\uFE0F";
2292
- Emoji2["LEFT_ARROW_UNICODE"] = "\u25C4";
2293
- Emoji2["UP_ARROW_UNICODE"] = "\u25B2";
2294
- Emoji2["RIGHT_ARROW_UNICODE"] = "\u25BA";
2295
- Emoji2["DOWN_ARROW_UNICODE"] = "\u25BC";
2296
- Emoji2["BRICK"] = "\u{1F9F1}";
2297
- Emoji2["RULER"] = "\u{1F4D0}";
2298
- Emoji2["SWORD"] = "\u{1F5E1}\uFE0F";
2299
- Emoji2["PEACE_SIGN"] = "\u270C\uFE0F";
2300
- Emoji2["SIGN"] = "\u{1FAA7}";
2301
- Emoji2["CONSTRUCTION"] = "\u{1F3D7}\uFE0F";
2302
- Emoji2["CAMERA"] = "\u{1F4F7}";
2303
- Emoji2["MOVIE_CAMERA"] = "\u{1F3A5}";
2304
- Emoji2["PAINTING"] = "\u{1F5BC}\uFE0F";
2305
- Emoji2["PALETTE"] = "\u{1F3A8}";
2306
- Emoji2["MICROPHONE"] = "\u{1F399}\uFE0F";
2307
- Emoji2["NOTEPAD"] = "\u{1F4DD}";
2308
- Emoji2["GEAR"] = "\u2699\uFE0F";
2309
- Emoji2["REPEAT"] = "\u{1F501}";
2310
- Emoji2["SNOWMAN"] = "\u2603\uFE0F";
2311
- Emoji2["SNOWFLAKE"] = "\u2744\uFE0F";
2312
- Emoji2["SNOW_CLOUD"] = "\u{1F328}\uFE0F";
2313
- Emoji2["SCARF"] = "\u{1F9E3}";
2314
- Emoji2["GLOVES"] = "\u{1F9E4}";
2315
- Emoji2["CANDLE"] = "\u{1F56F}\uFE0F";
2316
- Emoji2["CHRISTMAS_TREE"] = "\u{1F384}";
2317
- Emoji2["SOCKS"] = "\u{1F9E6}";
2318
- Emoji2["COLD_FACE"] = "\u{1F976}";
2319
- Emoji2["EYE"] = "\u{1F441}\uFE0F";
2320
- Emoji2["CHAINS"] = "\u26D3\uFE0F";
2321
- Emoji2["SPEAKER"] = "\u{1F50A}";
2322
- Emoji2["COMPACT_DISK"] = "\u{1F4BF}";
2323
- Emoji2["SEEDLING"] = "\u{1F331}";
2324
- Emoji2["TULIP"] = "\u{1F337}";
2325
- Emoji2["BEE"] = "\u{1F41D}";
2326
- Emoji2["HATCHING_CHICK"] = "\u{1F423}";
2327
- Emoji2["NEST_WITH_EGGS"] = "\u{1FABA}";
2328
- Emoji2["BLOSSOM"] = "\u{1F33C}";
2329
- Emoji2["UMBRELLA"] = "\u2614";
2330
- Emoji2["RAINBOW"] = "\u{1F308}";
2331
- Emoji2["PICNIC_BASKET"] = "\u{1F9FA}";
2332
- Emoji2["SUN_WITH_FACE"] = "\u{1F31E}";
2333
- Emoji2["BEACH_UMBRELLA"] = "\u{1F3D6}\uFE0F";
2334
- Emoji2["WATERMELON"] = "\u{1F349}";
2335
- Emoji2["SUNGLASSES"] = "\u{1F576}\uFE0F";
2336
- Emoji2["ICE_CREAM"] = "\u{1F366}";
2337
- Emoji2["SUNFLOWER"] = "\u{1F33B}";
2338
- Emoji2["CAMPING"] = "\u{1F3D5}\uFE0F";
2339
- Emoji2["JUICE_BOX"] = "\u{1F9C3}";
2340
- Emoji2["PARASOL"] = "\u26F1\uFE0F";
2341
- Emoji2["MAPLE_LEAF"] = "\u{1F341}";
2342
- Emoji2["FALLEN_LEAF"] = "\u{1F342}";
2343
- Emoji2["TURKEY"] = "\u{1F983}";
2344
- Emoji2["JACK_O_LANTERN"] = "\u{1F383}";
2345
- Emoji2["PIE"] = "\u{1F967}";
2346
- Emoji2["LOG"] = "\u{1FAB5}";
2347
- Emoji2["SPIDER_WEB"] = "\u{1F578}\uFE0F";
2348
- Emoji2["BACKPACK"] = "\u{1F392}";
2349
- Emoji2["CHESTNUT"] = "\u{1F330}";
2350
- Emoji2["PLACARD"] = "\u{1FAA7}";
2351
- Emoji2["RECEIPT"] = "\u{1F9FE}";
2352
- Emoji2["DOCUMENT"] = "\u{1F4C4}";
2353
- Emoji2["SPARKLES"] = "\u2728";
2354
- Emoji2["BOOKS"] = "\u{1F4DA}";
2355
- Emoji2["SHOPPING_BAGS"] = "\u{1F6CD}\uFE0F";
2356
- Emoji2["LINK"] = "\u{1F517}";
2357
- Emoji2["GREEN_ASTERISK"] = "\u2733\uFE0F";
2358
- Emoji2["RADIO_BUTTON"] = "\u{1F518}";
2359
- Emoji2["WINDOW"] = "\u{1FA9F}";
2360
- Emoji2["MUSIC_NOTES"] = "\u{1F3B6}";
2361
- Emoji2["INVISIBLE_FACE"] = "\u{1FAE5}";
2362
- Emoji2["PLUS_SIGN"] = "\u2795";
2363
- Emoji2["JOKER"] = "\u{1F0CF}";
2364
- Emoji2["PLAY"] = "\u25B6\uFE0F";
2365
- Emoji2["PAUSE"] = "\u23F8\uFE0F";
2366
- return Emoji2;
2367
- })(Emoji || {});
2368
- var emoji_default = Emoji;
2369
-
2370
2266
  // src/client/utility/get-index-path-for-element.ts
2371
2267
  var import_errors7 = __toESM(require_src2());
2372
2268
  function getIndexPathForElement(element) {
@@ -2383,594 +2279,351 @@
2383
2279
  // src/client/helper/interaction.ts
2384
2280
  var InteractionHelper = class {
2385
2281
  constructor() {
2386
- this.drag_active = false;
2387
- this.drag_origin_block = null;
2388
- this.drag_placeholder = null;
2389
- this.drag_ghost = null;
2390
- this.drag_start_y = null;
2391
- this.drag_pointer_offset_y = null;
2392
- this.drag_press_timer = null;
2393
- this.swipe_active = false;
2394
- this.swipe_block = null;
2395
- this.swipe_start_x = null;
2396
- this.swipe_start_y = null;
2397
- this.swipe_content = null;
2398
- this.swipe_menu_width = 0;
2399
- this.open_swipe_block = null;
2400
- this.open_swipe_content = null;
2282
+ this.drag_start_coordinate = null;
2283
+ this.drag_delay_timer = null;
2401
2284
  }
2402
2285
  attach() {
2403
- document.addEventListener("mousedown", (event) => {
2404
- this.onPressStart(event);
2405
- }, true);
2406
- document.addEventListener("touchstart", (event) => {
2407
- this.onPressStart(event);
2408
- }, { capture: true, passive: false });
2409
- document.addEventListener("mousemove", (event) => {
2410
- this.onPointerMove(event);
2411
- }, true);
2412
- document.addEventListener("touchmove", (event) => {
2413
- this.onPointerMove(event);
2286
+ document.addEventListener("pointerdown", (event) => {
2287
+ this.handlePointerDown(event);
2288
+ }, { capture: true });
2289
+ document.addEventListener("pointermove", (event) => {
2290
+ this.handlePointerMove(event);
2414
2291
  }, { capture: true, passive: false });
2415
- document.addEventListener("mouseup", (event) => {
2416
- this.onPressEnd(event);
2417
- }, true);
2418
- document.addEventListener("touchend", (event) => {
2419
- this.onPressEnd(event);
2420
- }, true);
2421
- document.addEventListener("touchstart", (event) => {
2422
- this.onGlobalTouchStart(event);
2423
- }, { capture: true, passive: true });
2292
+ document.addEventListener("pointerup", (event) => {
2293
+ this.handlePointerUp(event);
2294
+ }, { capture: true });
2295
+ document.addEventListener("pointercancel", (event) => {
2296
+ this.handlePointerCancel(event);
2297
+ }, { capture: true });
2424
2298
  document.addEventListener("dragstart", (event) => {
2425
- this.onNativeDragStart(event);
2426
- }, true);
2299
+ this.handleNativeDragStart(event);
2300
+ }, { capture: true });
2427
2301
  }
2428
2302
  isDragging() {
2429
- return this.drag_active;
2430
- }
2431
- getBlockElements() {
2432
- const elements = document.querySelectorAll("section.block");
2433
- return Array.from(elements);
2303
+ const elements = Array.from(document.querySelectorAll(".dragging"));
2304
+ return elements.length > 0;
2434
2305
  }
2435
- getSiblingBlocks(container, exclude) {
2436
- const children = Array.from(container.children);
2437
- return children.filter((element) => {
2438
- if (element === exclude) {
2439
- return false;
2440
- }
2441
- return element.classList.contains("block");
2442
- });
2443
- }
2444
- onPressStart(event) {
2445
- const target = event.target;
2306
+ handlePointerDown(event) {
2307
+ const { target } = event;
2446
2308
  if (target === null) {
2447
2309
  return;
2448
2310
  }
2449
- if (target.closest("button, input, textarea, select, label, form")) {
2450
- return;
2311
+ const target_element = target;
2312
+ let current_element = target_element;
2313
+ while (current_element) {
2314
+ const attribute = current_element.getAttribute("data-role");
2315
+ if (attribute === "block_activation") {
2316
+ break;
2317
+ }
2318
+ if (current_element instanceof HTMLAnchorElement) {
2319
+ return;
2320
+ }
2321
+ current_element = current_element.parentNode;
2322
+ if (!(current_element instanceof HTMLElement)) {
2323
+ break;
2324
+ }
2451
2325
  }
2452
- const block = target.closest("section.block");
2326
+ const block = target_element.closest("section.block");
2453
2327
  if (block === null) {
2454
2328
  return;
2455
2329
  }
2456
- if (event instanceof MouseEvent) {
2457
- const anchor = target.closest("a[href]");
2458
- if (anchor) {
2459
- event.preventDefault();
2460
- }
2330
+ if (target_element.closest("button, input, textarea, select, label, form")) {
2331
+ return;
2461
2332
  }
2462
- const touch_event = event;
2463
- const is_touch = touch_event.type === "touchstart";
2464
- const point = this.getEventPoint(event);
2465
- if (point === null) {
2333
+ const coordinate = this.getEventCoordinate(event);
2334
+ if (coordinate === null) {
2466
2335
  return;
2467
2336
  }
2468
- this.drag_origin_block = block;
2469
- this.drag_start_y = point.clientY;
2470
- if (is_touch) {
2471
- this.swipe_block = block;
2472
- this.swipe_start_x = point.clientX;
2473
- this.swipe_start_y = point.clientY;
2337
+ this.drag_start_coordinate = coordinate;
2338
+ block.classList.add("drag-candidate");
2339
+ this.scheduleDelayedDrag();
2340
+ }
2341
+ scheduleDelayedDrag() {
2342
+ this.cancelDelayedDrag();
2343
+ const delay = import_time.TimeInterval.ONE_SECOND;
2344
+ this.drag_delay_timer = setTimeout(this.beginDelayedDrag.bind(this), delay);
2345
+ }
2346
+ cancelDelayedDrag() {
2347
+ if (this.drag_delay_timer !== null) {
2348
+ clearTimeout(this.drag_delay_timer);
2474
2349
  }
2475
- const threshold_ms = is_touch ? 350 : 200;
2476
- this.clearPressTimer();
2477
- this.drag_press_timer = window.setTimeout(() => {
2478
- this.beginDrag(point.clientY);
2479
- }, threshold_ms);
2480
2350
  }
2481
- onNativeDragStart(event) {
2351
+ removeClassFromAllElements(class_name) {
2352
+ const raw_elements = document.querySelectorAll(`.${class_name}`);
2353
+ const elements = Array.from(raw_elements);
2354
+ elements.forEach((element) => {
2355
+ element.classList.remove(class_name);
2356
+ });
2357
+ return elements;
2358
+ }
2359
+ beginDelayedDrag() {
2360
+ const raw_candidates = document.querySelectorAll(".drag-candidate");
2361
+ const candidates = Array.from(raw_candidates);
2362
+ candidates.forEach((candidate) => {
2363
+ const ghost = candidate.cloneNode(true);
2364
+ const index_path = get_index_path_for_element_default(candidate);
2365
+ ghost.classList.add("ghost");
2366
+ ghost.setAttribute("data-for", index_path);
2367
+ candidate.classList.remove("drag-candidate");
2368
+ const { parentNode } = candidate;
2369
+ if (parentNode === null) {
2370
+ throw new import_errors8.InvariantViolation(`
2371
+ Expected drag candidate to be located in a parent, but it was null
2372
+ `);
2373
+ }
2374
+ const rect = candidate.getBoundingClientRect();
2375
+ Object.assign(candidate.style, {
2376
+ top: `${rect.top}px`,
2377
+ left: `${rect.left}px`,
2378
+ width: `${rect.width}px`,
2379
+ height: `${rect.height}px`
2380
+ });
2381
+ candidate.setAttribute("data-drag-start-x", rect.left.toString());
2382
+ candidate.setAttribute("data-drag-start-y", rect.top.toString());
2383
+ candidate.classList.add("dragging");
2384
+ parentNode.insertBefore(ghost, candidate);
2385
+ });
2386
+ }
2387
+ handleNativeDragStart(event) {
2482
2388
  const target = event.target;
2483
2389
  if (!target) {
2484
2390
  return;
2485
2391
  }
2486
- if (target.closest("section.block")) {
2392
+ const closest_block = target.closest("section.block");
2393
+ if (closest_block !== null) {
2487
2394
  event.preventDefault();
2488
2395
  }
2489
2396
  }
2490
- onPointerMove(event) {
2491
- const point = this.getEventPoint(event);
2492
- if (point === null) {
2397
+ handlePointerMove(event) {
2398
+ const current_coordinate = this.getEventCoordinate(event);
2399
+ const start_coordinate = this.getDragStartCoordinate();
2400
+ if (start_coordinate === null || current_coordinate === null) {
2493
2401
  return;
2494
2402
  }
2495
- const touch_event = event;
2496
- const { touches } = touch_event;
2497
- const is_touch = touches !== void 0;
2498
- if (is_touch && this.swipe_block) {
2499
- if (this.swipe_start_x === null || this.swipe_start_y === null) {
2500
- throw new import_errors8.InvariantViolation("Swipe start coordinates were not initialized");
2501
- }
2502
- const start_x = this.swipe_start_x;
2503
- const start_y = this.swipe_start_y;
2504
- const delta_x = point.clientX - start_x;
2505
- const delta_y = point.clientY - start_y;
2506
- if (!this.swipe_active) {
2507
- const abs_x = Math.abs(delta_x);
2508
- const abs_y = Math.abs(delta_y);
2509
- if (abs_x > 12 && abs_x > abs_y) {
2510
- this.clearPressTimer();
2511
- this.closeOpenSwipeMenu(this.swipe_block);
2512
- this.swipe_active = true;
2513
- this.beginSwipe(this.swipe_block);
2403
+ const { target } = event;
2404
+ if (target !== null) {
2405
+ const target_element = target;
2406
+ const block = target_element.closest("section.block");
2407
+ if (block) {
2408
+ if (!block.classList.contains("dragging")) {
2409
+ block.classList.add("drag-candidate");
2514
2410
  }
2515
2411
  }
2516
- if (this.swipe_active) {
2517
- event.preventDefault();
2518
- const content_element = this.swipe_content;
2519
- const menu_width = this.swipe_menu_width;
2520
- const translate_x = Math.max(-menu_width, Math.min(0, delta_x));
2521
- content_element.style.transition = "";
2522
- content_element.style.transform = `translateX(${translate_x}px)`;
2523
- return;
2524
- }
2525
2412
  }
2526
- if (!this.drag_active && this.drag_origin_block && this.drag_start_y !== null) {
2527
- const delta_y = Math.abs(point.clientY - this.drag_start_y);
2528
- if (delta_y > 8 && this.drag_press_timer !== null) {
2529
- this.beginDrag(point.clientY);
2530
- }
2413
+ const { x: start_x, y: start_y } = start_coordinate;
2414
+ const { x: current_x, y: current_y } = current_coordinate;
2415
+ const distance = Math.hypot(current_x - start_x, current_y - start_y);
2416
+ if (distance > 25) {
2417
+ this.removeClassFromAllElements("drag-candidate");
2531
2418
  }
2532
- if (!this.drag_active) {
2533
- return;
2419
+ this.scheduleDelayedDrag();
2420
+ const raw_targets = document.querySelectorAll(".dragging");
2421
+ const drag_target_blocks = Array.from(raw_targets);
2422
+ drag_target_blocks.forEach((target_block) => {
2423
+ this.translateDragTargetBlock(target_block, current_coordinate);
2424
+ });
2425
+ if (drag_target_blocks.length > 0) {
2426
+ event.preventDefault();
2534
2427
  }
2535
- event.preventDefault();
2536
- const origin = this.drag_origin_block;
2537
- let container = null;
2538
- if (this.drag_placeholder !== null) {
2539
- container = this.drag_placeholder.parentElement;
2428
+ }
2429
+ translateDragTargetBlock(block, current_coordinate) {
2430
+ const x_attribute = block.getAttribute("data-drag-start-x");
2431
+ const y_attribute = block.getAttribute("data-drag-start-y");
2432
+ if (x_attribute === null || y_attribute === null) {
2433
+ throw new import_errors8.InvariantViolation(`
2434
+ Drag coordinate attributes were invalid:
2435
+ x: ${x_attribute}
2436
+ y: ${y_attribute}
2437
+ `);
2540
2438
  }
2541
- if (container === null && origin !== null) {
2542
- container = origin.parentElement;
2439
+ const parsed_x = parseInt(x_attribute);
2440
+ const parsed_y = parseInt(y_attribute);
2441
+ if (isNaN(parsed_x) || isNaN(parsed_y)) {
2442
+ throw new import_errors8.InvariantViolation(`
2443
+ Drag coordinate attributes were invalid:
2444
+ x: ${x_attribute}
2445
+ y: ${y_attribute}
2446
+ `);
2543
2447
  }
2544
- if (container === null) {
2545
- return;
2448
+ const start_coordinate = this.getDragStartCoordinate();
2449
+ if (start_coordinate === null) {
2450
+ throw new import_errors8.InvariantViolation(`
2451
+ Tried to translate drag target, but drag start coordinate was null
2452
+ `);
2546
2453
  }
2547
- const blocks_before = this.getSiblingBlocks(container, origin);
2548
- const preceding_rects = /* @__PURE__ */ new Map();
2549
- blocks_before.forEach((element) => {
2550
- const rect = element.getBoundingClientRect();
2551
- preceding_rects.set(element, rect);
2552
- });
2553
- this.updatePlaceholderPosition(point.clientY);
2554
- if (this.drag_ghost && this.drag_pointer_offset_y !== null) {
2555
- const top_position = point.clientY - this.drag_pointer_offset_y;
2556
- this.drag_ghost.style.top = `${top_position}px`;
2557
- }
2558
- const blocks_after = this.getSiblingBlocks(container, origin);
2559
- this.animateWithFlip(preceding_rects, blocks_after);
2560
- }
2561
- onPressEnd(event) {
2562
- this.clearPressTimer();
2563
- if (this.swipe_active) {
2564
- const content = this.swipe_content;
2565
- const style = window.getComputedStyle(content);
2566
- let current_x = 0;
2567
- try {
2568
- const css_matrix = new WebKitCSSMatrix(style.transform);
2569
- current_x = css_matrix.m41;
2570
- } catch {
2571
- const translate_match = style.transform.match(/translateX\(([-0-9.]+)px\)/);
2572
- if (translate_match) {
2573
- current_x = parseFloat(translate_match[1]);
2454
+ const { x: start_x, y: start_y } = start_coordinate;
2455
+ const { x: current_x, y: current_y } = current_coordinate;
2456
+ const x_delta = current_x - start_x;
2457
+ const y_delta = current_y - start_y;
2458
+ const new_x = parsed_x + x_delta;
2459
+ const new_y = parsed_y + y_delta;
2460
+ block.style.left = `${new_x}px`;
2461
+ block.style.top = `${new_y}px`;
2462
+ const block_rect = block.getBoundingClientRect();
2463
+ const previous_block = this.getPreviousBlock(block);
2464
+ const next_block = this.getNextBlock(block);
2465
+ const ghost = this.getGhostForBlock(block);
2466
+ let swapped = false;
2467
+ if (previous_block !== null) {
2468
+ const previous_rect = previous_block.getBoundingClientRect();
2469
+ const previous_block_y_threshold = previous_rect.top + previous_rect.height * 0.4;
2470
+ if (block_rect.top < previous_block_y_threshold) {
2471
+ swapped = true;
2472
+ const next_sibling = ghost.nextElementSibling;
2473
+ previous_block.replaceWith(ghost);
2474
+ if (next_sibling) {
2475
+ next_sibling.before(previous_block);
2574
2476
  }
2575
2477
  }
2576
- const width = this.swipe_menu_width;
2577
- const open = Math.abs(current_x) > width / 2;
2578
- content.style.transition = "transform 150ms ease";
2579
- content.style.transform = open ? `translateX(${-width}px)` : "translateX(0)";
2580
- if (!open) {
2581
- this.teardownSwipe();
2582
- }
2583
- if (open) {
2584
- this.open_swipe_block = this.swipe_block;
2585
- this.open_swipe_content = content;
2586
- }
2587
- this.swipe_active = false;
2588
- return;
2589
- }
2590
- if (!this.drag_active) {
2591
- this.resetDragState();
2592
- return;
2593
2478
  }
2594
- event.preventDefault();
2595
- const origin = this.drag_origin_block;
2596
- const placeholder = this.drag_placeholder;
2597
- const source_index_path = get_index_path_for_element_default(origin);
2598
- const target_index_path = this.computeTargetIndexPath(placeholder);
2599
- this.cleanupDragElements();
2600
- if (target_index_path === null || target_index_path === source_index_path) {
2601
- this.resetDragState();
2602
- return;
2603
- }
2604
- const editing = new URL(window.location.href).searchParams.get("editing") === "true";
2605
- this.postReposition(source_index_path, target_index_path, editing).then((new_index_path) => {
2606
- if (new_index_path) {
2607
- const url = new URL(window.location.href);
2608
- url.searchParams.set("index_path", new_index_path);
2609
- history.replaceState({}, "", url.toString());
2479
+ if (next_block !== null && swapped === false) {
2480
+ const next_rect = next_block.getBoundingClientRect();
2481
+ const next_block_y_threshold = next_rect.top + next_rect.height * 0.6;
2482
+ if (block_rect.bottom > next_block_y_threshold) {
2483
+ const next_sibling = ghost.nextElementSibling === next_block ? ghost : ghost.nextElementSibling;
2484
+ next_block.replaceWith(ghost);
2485
+ if (next_sibling) {
2486
+ next_sibling.before(next_block);
2487
+ }
2610
2488
  }
2611
- const blocks = this.getBlockElements();
2612
- blocks.forEach((element) => {
2613
- element.classList.remove("selected");
2614
- });
2615
- origin.classList.add("selected");
2616
- this.updateTopLevelIndexPaths();
2617
- }).finally(() => {
2618
- this.resetDragState();
2619
- });
2620
- }
2621
- beginSwipe(block) {
2622
- const result = this.ensureSwipeUI(block);
2623
- const target = result.target;
2624
- const menu = result.menu;
2625
- const menu_width = result.menu_width;
2626
- this.swipe_content = target;
2627
- this.swipe_menu_width = menu_width;
2628
- if (menu) {
2629
- menu.style.display = "flex";
2630
- menu.style.opacity = "1";
2631
2489
  }
2632
2490
  }
2633
- closeOpenSwipeMenu(except) {
2634
- if (!this.open_swipe_content) {
2635
- return;
2636
- }
2637
- if (except && this.open_swipe_block === except) {
2638
- return;
2491
+ getGhostForBlock(block) {
2492
+ const index_path = get_index_path_for_element_default(block);
2493
+ const ghost = document.querySelector(`[data-for="${index_path}"]`);
2494
+ if (ghost === null) {
2495
+ throw new import_errors8.InvariantViolation(`
2496
+ Unable to find ghost for block with index path ${index_path}
2497
+ `);
2639
2498
  }
2640
- const content = this.open_swipe_content;
2641
- content.style.transition = "transform 150ms ease";
2642
- content.style.transform = "translateX(0)";
2643
- const clear_callback = () => {
2644
- content.removeEventListener("transitionend", clear_callback);
2645
- if (this.open_swipe_block) {
2646
- const menu_element = this.getSwipeMenuFor(this.open_swipe_block);
2647
- if (menu_element && menu_element.parentElement) {
2648
- menu_element.parentElement.removeChild(menu_element);
2649
- }
2650
- }
2651
- this.open_swipe_block = null;
2652
- this.open_swipe_content = null;
2653
- };
2654
- content.addEventListener("transitionend", clear_callback);
2499
+ return ghost;
2655
2500
  }
2656
- teardownSwipe() {
2657
- if (!this.swipe_block || !this.swipe_content) {
2658
- this.resetSwipeState();
2659
- return;
2501
+ getPreviousBlock(block) {
2502
+ const parent_node = block.parentNode;
2503
+ const siblings = Array.from(parent_node.children);
2504
+ const ghost = this.getGhostForBlock(block);
2505
+ let index = siblings.indexOf(ghost);
2506
+ if (index === -1) {
2507
+ throw new import_errors8.InvariantViolation("Unable to locate ghost within siblings");
2660
2508
  }
2661
- this.swipe_content.style.transition = "";
2662
- this.swipe_content.style.transform = "translateX(0)";
2663
- const menu = this.getSwipeMenuFor(this.swipe_block);
2664
- if (menu && menu.parentElement) {
2665
- menu.parentElement.removeChild(menu);
2509
+ while (index--) {
2510
+ const sibling = siblings[index];
2511
+ if (sibling === block) {
2512
+ continue;
2513
+ }
2514
+ const { classList } = sibling;
2515
+ if (!classList.contains("block")) {
2516
+ continue;
2517
+ }
2518
+ if (classList.contains("ghost")) {
2519
+ continue;
2520
+ }
2521
+ return sibling;
2666
2522
  }
2667
- this.resetSwipeState();
2523
+ return null;
2668
2524
  }
2669
- onGlobalTouchStart(event) {
2670
- if (!this.open_swipe_block || !this.open_swipe_content) {
2671
- return;
2672
- }
2673
- const target = event.target;
2674
- if (!target) {
2675
- return;
2525
+ getNextBlock(block) {
2526
+ const parent_node = block.parentNode;
2527
+ const siblings = Array.from(parent_node.children);
2528
+ const ghost = this.getGhostForBlock(block);
2529
+ let index = siblings.indexOf(ghost);
2530
+ if (index === -1) {
2531
+ throw new import_errors8.InvariantViolation("Unable to locate ghost within siblings");
2676
2532
  }
2677
- const menu = this.getSwipeMenuFor(this.open_swipe_block);
2678
- const closest_block = target.closest("section.block");
2679
- const swipe_actions = target.closest(".swipe-actions");
2680
- if (closest_block === this.open_swipe_block || swipe_actions === menu) {
2681
- return;
2533
+ while (index < siblings.length) {
2534
+ index++;
2535
+ const sibling = siblings[index];
2536
+ if (sibling === block) {
2537
+ continue;
2538
+ }
2539
+ const { classList } = sibling;
2540
+ if (!classList.contains("block")) {
2541
+ continue;
2542
+ }
2543
+ if (classList.contains("ghost")) {
2544
+ continue;
2545
+ }
2546
+ return sibling;
2682
2547
  }
2683
- this.closeOpenSwipeMenu();
2548
+ return null;
2684
2549
  }
2685
- getSwipeMenuFor(block) {
2686
- const wrapper = block.closest("main .section-wrapper");
2687
- if (!wrapper || !block.id) {
2688
- return null;
2689
- }
2690
- return wrapper.querySelector(`.swipe-actions[data-for="${block.id}"]`);
2691
- }
2692
- resetSwipeState() {
2693
- this.swipe_block = null;
2694
- this.swipe_start_x = null;
2695
- this.swipe_start_y = null;
2696
- this.swipe_content = null;
2697
- this.swipe_menu_width = 0;
2698
- }
2699
- ensureSwipeUI(block) {
2700
- const target = block;
2701
- target.style.willChange = "transform";
2702
- target.style.transform = "translateX(0)";
2703
- target.style.transition = "";
2704
- target.style.position = target.style.position || "relative";
2705
- target.style.zIndex = "1";
2706
- const wrapper = block.closest("main .section-wrapper");
2707
- let menu = null;
2708
- if (wrapper) {
2709
- if (getComputedStyle(wrapper).position === "static") {
2710
- wrapper.style.position = "relative";
2711
- }
2712
- let existing = wrapper.querySelector(`.swipe-actions[data-for="${block.id}"]`);
2713
- if (!existing) {
2714
- existing = document.createElement("div");
2715
- existing.className = "swipe-actions";
2716
- existing.setAttribute("data-for", block.id);
2717
- existing.style.position = "absolute";
2718
- existing.style.right = "0";
2719
- existing.style.display = "none";
2720
- existing.style.opacity = "0";
2721
- existing.style.gap = "8px";
2722
- existing.style.alignItems = "stretch";
2723
- existing.style.padding = "0 8px";
2724
- existing.style.background = "transparent";
2725
- existing.style.zIndex = "0";
2726
- const edit_button = document.createElement("button");
2727
- const delete_button = document.createElement("button");
2728
- const add_button = document.createElement("button");
2729
- edit_button.textContent = emoji_default.GEAR;
2730
- edit_button.setAttribute("aria-label", "Edit");
2731
- edit_button.style.background = "#f0ad4e";
2732
- edit_button.style.color = "#000";
2733
- edit_button.style.border = "none";
2734
- edit_button.style.padding = "0";
2735
- edit_button.style.fontSize = "20px";
2736
- edit_button.style.width = "48px";
2737
- edit_button.style.minWidth = "48px";
2738
- edit_button.style.display = "flex";
2739
- edit_button.style.alignItems = "center";
2740
- edit_button.style.justifyContent = "center";
2741
- edit_button.style.cursor = "pointer";
2742
- delete_button.textContent = emoji_default.RED_X;
2743
- delete_button.setAttribute("aria-label", "Delete");
2744
- delete_button.style.background = "#e74c3c";
2745
- delete_button.style.color = "#fff";
2746
- delete_button.style.border = "none";
2747
- delete_button.style.padding = "0";
2748
- delete_button.style.fontSize = "20px";
2749
- delete_button.style.width = "48px";
2750
- delete_button.style.minWidth = "48px";
2751
- delete_button.style.display = "flex";
2752
- delete_button.style.alignItems = "center";
2753
- delete_button.style.justifyContent = "center";
2754
- delete_button.style.cursor = "pointer";
2755
- add_button.textContent = emoji_default.PLUS_SIGN;
2756
- add_button.setAttribute("aria-label", "Add After");
2757
- add_button.style.background = "#27ae60";
2758
- add_button.style.color = "#fff";
2759
- add_button.style.border = "none";
2760
- add_button.style.padding = "0";
2761
- add_button.style.fontSize = "20px";
2762
- add_button.style.width = "48px";
2763
- add_button.style.minWidth = "48px";
2764
- add_button.style.display = "flex";
2765
- add_button.style.alignItems = "center";
2766
- add_button.style.justifyContent = "center";
2767
- add_button.style.cursor = "pointer";
2768
- existing.appendChild(edit_button);
2769
- existing.appendChild(delete_button);
2770
- existing.appendChild(add_button);
2771
- wrapper.appendChild(existing);
2772
- const edit_handler = (event) => {
2773
- event.preventDefault();
2774
- event.stopPropagation();
2775
- this.navigateToBlockLink(block, "edit");
2776
- };
2777
- const delete_handler = (event) => {
2778
- event.preventDefault();
2779
- event.stopPropagation();
2780
- this.navigateToBlockLink(block, "delete");
2781
- };
2782
- const add_handler = (event) => {
2783
- event.preventDefault();
2784
- event.stopPropagation();
2785
- this.navigateToAddAfter(block);
2786
- };
2787
- existing.addEventListener("touchstart", (event) => {
2788
- event.stopPropagation();
2789
- });
2790
- existing.addEventListener("mousedown", (event) => {
2791
- event.stopPropagation();
2792
- });
2793
- edit_button.addEventListener("click", edit_handler);
2794
- edit_button.addEventListener("touchend", edit_handler);
2795
- delete_button.addEventListener("click", delete_handler);
2796
- delete_button.addEventListener("touchend", delete_handler);
2797
- add_button.addEventListener("click", add_handler);
2798
- add_button.addEventListener("touchend", add_handler);
2799
- }
2800
- menu = existing;
2801
- const top = block.offsetTop;
2802
- const height = block.offsetHeight;
2803
- menu.style.top = `${top}px`;
2804
- menu.style.height = `${height}px`;
2805
- }
2806
- let menu_width = 160;
2807
- if (menu) {
2808
- const prevDisplay = menu.style.display;
2809
- const prevOpacity = menu.style.opacity;
2810
- menu.style.display = "flex";
2811
- menu.style.opacity = "0";
2812
- menu_width = menu.offsetWidth || 160;
2813
- menu.style.display = prevDisplay;
2814
- menu.style.opacity = prevOpacity;
2815
- }
2816
- this.enforceTimeVisibility(block);
2817
- return {
2818
- target,
2819
- menu,
2820
- menu_width
2821
- };
2550
+ handlePointerUp(event) {
2551
+ this.stopDragging();
2822
2552
  }
2823
- navigateToAddAfter(block) {
2824
- const current = get_index_path_for_element_default(block);
2825
- const parts = current.split(".").map((part) => {
2826
- return parseInt(part, 10);
2827
- });
2828
- const has_invalid_number = parts.some((value) => {
2829
- return isNaN(value);
2553
+ handlePointerCancel(event) {
2554
+ this.stopDragging();
2555
+ }
2556
+ stopDragging() {
2557
+ this.showFullscreenBlockingOverlay();
2558
+ this.stopDraggingAsync().then(() => {
2559
+ this.hideFullscreenBlockingOverlay();
2830
2560
  });
2831
- if (parts.length === 0 || has_invalid_number) {
2832
- throw new import_errors8.InvariantViolation("Invalid index_path for Add After");
2833
- }
2834
- const last = parts.pop();
2835
- if (last === void 0) {
2836
- throw new import_errors8.InvariantViolation("Unable to compute next index for Add After");
2837
- }
2838
- parts.push(last + 1);
2839
- const index_path = parts.join(".");
2840
- const url = new URL(window.location.href);
2841
- const editing = url.searchParams.get("editing") === "true";
2842
- const path = window.location.pathname;
2843
- const actionUrl = new URL("/actions", window.location.origin);
2844
- actionUrl.searchParams.set("path", path);
2845
- actionUrl.searchParams.set("editing", String(editing));
2846
- actionUrl.searchParams.set("action_type", "add_block");
2847
- actionUrl.searchParams.set("index_path", index_path);
2848
- window.location.href = actionUrl.toString();
2849
- }
2850
- enforceTimeVisibility(block) {
2851
- const shows_time = block.classList.contains("with-time");
2852
- const time_element = block.querySelector(":scope time");
2853
- if (!time_element) {
2854
- return;
2855
- }
2856
- if (!shows_time) {
2857
- time_element.style.display = "none";
2858
- } else {
2859
- time_element.style.display = "";
2860
- }
2861
2561
  }
2862
- navigateToBlockLink(block, type) {
2863
- const block_id = block.id;
2864
- const link_id = `${block_id}-${type}`;
2865
- const link_element = document.getElementById(link_id);
2866
- if (!link_element) {
2867
- return;
2868
- }
2869
- const href = link_element.getAttribute("href");
2870
- if (href) {
2871
- window.location.href = href;
2872
- }
2562
+ showFullscreenBlockingOverlay() {
2873
2563
  }
2874
- beginDrag(current_y) {
2875
- if (this.drag_active) {
2876
- return;
2564
+ hideFullscreenBlockingOverlay() {
2565
+ }
2566
+ async stopDraggingAsync() {
2567
+ this.cancelDelayedDrag();
2568
+ this.removeClassFromAllElements("drag-candidate");
2569
+ const dragging_elements = this.removeClassFromAllElements("dragging");
2570
+ let index = 0;
2571
+ while (index < dragging_elements.length) {
2572
+ const element = dragging_elements[index++];
2573
+ const ghost = this.getGhostForBlock(element);
2574
+ const source_index_path = get_index_path_for_element_default(element);
2575
+ const target_index_path = this.getIndexPathForGhost(ghost);
2576
+ await this.submitReposition(source_index_path, target_index_path);
2577
+ ghost.replaceWith(element);
2578
+ Object.assign(element.style, {
2579
+ left: "",
2580
+ top: "",
2581
+ right: "",
2582
+ bottom: "",
2583
+ width: "",
2584
+ height: ""
2585
+ });
2877
2586
  }
2878
- const block = this.drag_origin_block;
2879
- if (!block) {
2880
- return;
2587
+ }
2588
+ getIndexPathSafe(element) {
2589
+ const is_block = element.classList.contains("block");
2590
+ if (!is_block) {
2591
+ return null;
2881
2592
  }
2882
- this.drag_active = true;
2883
- document.body.style.userSelect = "none";
2884
- document.body.style.cursor = "grabbing";
2885
- const rect = block.getBoundingClientRect();
2886
- const ghost = block.cloneNode(true);
2887
- ghost.style.position = "fixed";
2888
- ghost.style.top = `${rect.top}px`;
2889
- ghost.style.left = `${rect.left}px`;
2890
- ghost.style.width = `${rect.width}px`;
2891
- ghost.style.pointerEvents = "none";
2892
- ghost.style.opacity = "0.9";
2893
- ghost.style.boxShadow = "0 8px 16px rgba(0,0,0,0.2)";
2894
- ghost.style.zIndex = "9999";
2895
- document.body.appendChild(ghost);
2896
- this.drag_ghost = ghost;
2897
- this.drag_pointer_offset_y = current_y - rect.top;
2898
- const placeholder = document.createElement("div");
2899
- placeholder.style.height = `${rect.height}px`;
2900
- placeholder.style.margin = getComputedStyle(block).margin;
2901
- placeholder.style.border = "2px dashed #888";
2902
- placeholder.style.borderRadius = "4px";
2903
- placeholder.style.boxSizing = "border-box";
2904
- if (block.parentElement !== null) {
2905
- block.parentElement.insertBefore(placeholder, block);
2906
- }
2907
- this.drag_placeholder = placeholder;
2908
- block.style.display = "none";
2909
- this.updatePlaceholderPosition(current_y);
2910
- }
2911
- updatePlaceholderPosition(cursor_y) {
2912
- const placeholder = this.drag_placeholder;
2913
- const origin = this.drag_origin_block;
2914
- if (!placeholder || !origin) {
2915
- return;
2593
+ const is_ghost = element.classList.contains("ghost");
2594
+ if (is_ghost) {
2595
+ return null;
2916
2596
  }
2917
- const container = placeholder.parentElement;
2918
- const blocks = this.getSiblingBlocks(container, origin);
2919
- let inserted = false;
2920
- for (let i = 0; i < blocks.length; i++) {
2921
- const element = blocks[i];
2922
- const rect = element.getBoundingClientRect();
2923
- const midpoint = rect.top + rect.height / 2;
2924
- if (cursor_y < midpoint) {
2925
- const parent = element.parentElement;
2926
- if (parent) {
2927
- parent.insertBefore(placeholder, element);
2928
- }
2929
- inserted = true;
2930
- break;
2597
+ return get_index_path_for_element_default(element);
2598
+ }
2599
+ getIndexPathForGhost(ghost) {
2600
+ let current_child = ghost;
2601
+ while (current_child) {
2602
+ const index_path = this.getIndexPathSafe(current_child);
2603
+ if (index_path !== null) {
2604
+ return index_path;
2931
2605
  }
2606
+ current_child = current_child.nextElementSibling;
2932
2607
  }
2933
- if (!inserted) {
2934
- const last_element = blocks[blocks.length - 1];
2935
- if (last_element) {
2936
- const parent = last_element.parentElement;
2937
- if (parent) {
2938
- parent.appendChild(placeholder);
2939
- }
2608
+ current_child = ghost;
2609
+ while (current_child) {
2610
+ const index_path = this.getIndexPathSafe(current_child);
2611
+ if (index_path !== null) {
2612
+ const index_major_version = parseInt(index_path);
2613
+ const next_version = index_major_version + 1;
2614
+ return next_version.toString();
2940
2615
  }
2616
+ current_child = current_child.previousElementSibling;
2941
2617
  }
2618
+ return "0";
2942
2619
  }
2943
- animateWithFlip(preceding_rects, blocks_after) {
2944
- blocks_after.forEach((element) => {
2945
- const first = preceding_rects.get(element);
2946
- if (!first) {
2947
- return;
2948
- }
2949
- const last_rect = element.getBoundingClientRect();
2950
- const delta_y = first.top - last_rect.top;
2951
- if (delta_y === 0) {
2952
- return;
2953
- }
2954
- element.style.transition = "";
2955
- element.style.transform = `translateY(${delta_y}px)`;
2956
- void element.getBoundingClientRect();
2957
- element.style.transition = "transform 120ms ease";
2958
- element.style.transform = "translateY(0)";
2959
- const cleanup = () => {
2960
- element.style.transition = "";
2961
- element.style.transform = "";
2962
- element.removeEventListener("transitionend", cleanup);
2963
- };
2964
- element.addEventListener("transitionend", cleanup);
2965
- });
2966
- }
2967
- async postReposition(source_index_path, target_index_path, editing) {
2620
+ async submitReposition(source_index_path, target_index_path) {
2968
2621
  const form = new FormData();
2969
2622
  form.set("path", window.location.pathname);
2970
2623
  form.set("action_type", action_type_default.REPOSITION_BLOCK);
2971
2624
  form.set("source_index_path", source_index_path);
2972
2625
  form.set("target_index_path", target_index_path);
2973
- const response = await fetch(`/actions?editing=${editing}`, {
2626
+ const response = await fetch(`/actions`, {
2974
2627
  method: "POST",
2975
2628
  body: form,
2976
2629
  credentials: "same-origin",
@@ -2983,91 +2636,15 @@
2983
2636
  return null;
2984
2637
  }
2985
2638
  }
2986
- computeTargetIndexPath(placeholder) {
2987
- if (!placeholder) {
2988
- return null;
2989
- }
2990
- const parent = placeholder.parentElement;
2991
- if (!parent) {
2992
- return null;
2993
- }
2994
- let index = 0;
2995
- const children_elements = Array.from(parent.children);
2996
- for (let i = 0; i < children_elements.length; i++) {
2997
- const child_element = children_elements[i];
2998
- if (child_element === placeholder) {
2999
- break;
3000
- }
3001
- if (child_element.classList.contains("block")) {
3002
- index += 1;
3003
- }
3004
- }
3005
- return index.toString();
3006
- }
3007
- updateTopLevelIndexPaths() {
3008
- const wrapper = document.querySelector("main .section-wrapper");
3009
- let blocks;
3010
- if (wrapper) {
3011
- const node_list = wrapper.querySelectorAll(":scope > section.block");
3012
- blocks = Array.from(node_list);
3013
- } else {
3014
- const node_list = document.querySelectorAll("main > section.block");
3015
- blocks = Array.from(node_list);
3016
- }
3017
- for (let i = 0; i < blocks.length; i++) {
3018
- blocks[i].setAttribute("data-index-path", i.toString());
3019
- }
3020
- }
3021
- cleanupDragElements() {
3022
- if (this.drag_ghost && this.drag_ghost.parentElement) {
3023
- this.drag_ghost.parentElement.removeChild(this.drag_ghost);
3024
- }
3025
- if (this.drag_placeholder && this.drag_placeholder.parentElement) {
3026
- if (this.drag_origin_block) {
3027
- this.drag_placeholder.parentElement.insertBefore(this.drag_origin_block, this.drag_placeholder);
3028
- }
3029
- this.drag_placeholder.parentElement.removeChild(this.drag_placeholder);
3030
- }
3031
- if (this.drag_origin_block) {
3032
- this.drag_origin_block.style.display = "";
3033
- }
3034
- this.drag_ghost = null;
3035
- this.drag_placeholder = null;
3036
- document.body.style.userSelect = "";
3037
- document.body.style.cursor = "";
3038
- }
3039
- resetDragState() {
3040
- this.cleanupDragElements();
3041
- this.drag_active = false;
3042
- this.drag_origin_block = null;
3043
- this.drag_start_y = null;
3044
- this.drag_pointer_offset_y = null;
3045
- }
3046
- clearPressTimer() {
3047
- if (this.drag_press_timer !== null) {
3048
- window.clearTimeout(this.drag_press_timer);
3049
- this.drag_press_timer = null;
3050
- }
3051
- }
3052
- getEventPoint(event) {
3053
- const touch_event = event;
3054
- const has_touches = touch_event.touches !== void 0;
3055
- if (has_touches) {
3056
- const primary_touch = touch_event.touches[0] || touch_event.changedTouches[0];
3057
- if (!primary_touch) {
3058
- return null;
3059
- }
3060
- return {
3061
- clientX: primary_touch.clientX,
3062
- clientY: primary_touch.clientY
3063
- };
3064
- }
3065
- const mouse_event = event;
2639
+ getEventCoordinate(event) {
3066
2640
  return {
3067
- clientX: mouse_event.clientX,
3068
- clientY: mouse_event.clientY
2641
+ x: event.clientX,
2642
+ y: event.clientY
3069
2643
  };
3070
2644
  }
2645
+ getDragStartCoordinate() {
2646
+ return this.drag_start_coordinate;
2647
+ }
3071
2648
  };
3072
2649
  var interaction_default = InteractionHelper;
3073
2650
 
@@ -3078,14 +2655,15 @@
3078
2655
  this.logged_in = false;
3079
2656
  this.queued_media = null;
3080
2657
  this.ready_media = [];
3081
- this.drag_helper = new interaction_default();
2658
+ this.interaction_helper = new interaction_default();
3082
2659
  }
3083
2660
  initView() {
3084
2661
  this.focusCurrentBlockElement();
3085
2662
  const meta_value = get_meta_value_default("logged_in");
3086
2663
  this.logged_in = meta_value === "true";
3087
2664
  if (this.isLoggedIn()) {
3088
- this.drag_helper.attach();
2665
+ const interaction_helper = this.getInteractionHelper();
2666
+ interaction_helper.attach();
3089
2667
  }
3090
2668
  }
3091
2669
  initEvents() {
@@ -3104,10 +2682,8 @@
3104
2682
  });
3105
2683
  }
3106
2684
  handleGenericClick(event) {
3107
- if (this.drag_helper.isDragging()) {
3108
- return;
3109
- }
3110
- if (!this.hasActiveMedia()) {
2685
+ const interaction_helper = this.getInteractionHelper();
2686
+ if (interaction_helper.isDragging()) {
3111
2687
  return;
3112
2688
  }
3113
2689
  if (event.defaultPrevented) {
@@ -3124,17 +2700,37 @@
3124
2700
  return;
3125
2701
  }
3126
2702
  const target = event.target;
3127
- const anchor = target.closest("a[href]");
3128
- if (anchor === null) {
3129
- return;
2703
+ const selector = '[data-role="block_activation"]';
2704
+ const activator = (() => {
2705
+ if (target.matches(selector)) {
2706
+ return target;
2707
+ }
2708
+ if (!target.matches("section.block")) {
2709
+ const ancestor_block = target.closest("section.block");
2710
+ if (ancestor_block === null) {
2711
+ return null;
2712
+ }
2713
+ }
2714
+ return target.querySelector(selector) || target.closest(selector);
2715
+ })();
2716
+ if (activator !== null) {
2717
+ const block = activator.closest("section.block");
2718
+ if (block === null) {
2719
+ throw new import_errors9.InvariantViolation(`
2720
+ Unable to handle activator; no wrapping block was found
2721
+ `);
2722
+ }
2723
+ return this.activateBlock(block);
3130
2724
  }
3131
- const url = new URL(anchor.href, window.location.href);
3132
- if (url.origin !== window.location.origin) {
3133
- return;
2725
+ const anchor = target.closest("a[href]");
2726
+ if (anchor !== null && this.hasActiveMedia()) {
2727
+ const url = new URL(anchor.href, window.location.href);
2728
+ if (url.origin === window.location.origin) {
2729
+ const path = url.pathname + url.search + url.hash;
2730
+ this.navigateToPath(path);
2731
+ event.preventDefault();
2732
+ }
3134
2733
  }
3135
- event.preventDefault();
3136
- const path = url.pathname + url.search + url.hash;
3137
- this.navigateToPath(path);
3138
2734
  }
3139
2735
  navigateToPath(path) {
3140
2736
  if (!this.hasActiveMedia()) {
@@ -3189,7 +2785,7 @@
3189
2785
  switch (key_code) {
3190
2786
  case key_code_default.ENTER:
3191
2787
  case key_code_default.O:
3192
- return this.activateBlock();
2788
+ return this.activateCurrentBlock();
3193
2789
  case key_code_default.G:
3194
2790
  return this.performPageJump();
3195
2791
  case key_code_default.J:
@@ -3429,11 +3025,13 @@
3429
3025
  }
3430
3026
  return previous_block.getAttribute("data-index-path");
3431
3027
  }
3432
- activateBlock() {
3028
+ activateCurrentBlock() {
3433
3029
  const block_element = this.getCurrentBlockElement();
3434
- if (block_element === null) {
3435
- return;
3030
+ if (block_element !== null) {
3031
+ this.activateBlock(block_element);
3436
3032
  }
3033
+ }
3034
+ activateBlock(block_element) {
3437
3035
  const attribute = block_element.getAttribute("data-block-type");
3438
3036
  if (attribute === null) {
3439
3037
  throw new import_errors9.InvariantViolation(`
@@ -3555,8 +3153,8 @@
3555
3153
  return;
3556
3154
  }
3557
3155
  const media_target = target;
3558
- const duration_ms = media_target.duration * import_time.TimeInterval.ONE_SECOND;
3559
- const timecode = (0, import_time.formatTimecode)(duration_ms);
3156
+ const duration_ms = media_target.duration * import_time2.TimeInterval.ONE_SECOND;
3157
+ const timecode = (0, import_time2.formatTimecode)(duration_ms);
3560
3158
  const block = media_target.closest("section.block");
3561
3159
  if (block !== null) {
3562
3160
  const duration_label = block.querySelector('[data-role="duration"]');
@@ -3627,6 +3225,9 @@
3627
3225
  media_element.pause();
3628
3226
  });
3629
3227
  }
3228
+ getInteractionHelper() {
3229
+ return this.interaction_helper;
3230
+ }
3630
3231
  isLoggedIn() {
3631
3232
  return this.logged_in;
3632
3233
  }