@fc3/mmcadi 0.1.55 → 0.1.57

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.
@@ -1 +1 @@
1
- 1767658924
1
+ 1767736645
@@ -1 +1 @@
1
- 1767659000
1
+ 1767736776
package/dist/client.js CHANGED
@@ -2283,17 +2283,21 @@
2283
2283
  this.drag_delay_timer = null;
2284
2284
  }
2285
2285
  attach() {
2286
- document.addEventListener("pointerdown", (event) => {
2287
- this.handlePointerDown(event);
2286
+ if (!this.isTouchDevice()) {
2287
+ return;
2288
+ }
2289
+ this.applyNonInteractiveClasses();
2290
+ document.addEventListener("touchstart", (event) => {
2291
+ this.handleTouchStart(event);
2288
2292
  }, { capture: true });
2289
- document.addEventListener("pointermove", (event) => {
2290
- this.handlePointerMove(event);
2293
+ document.addEventListener("touchmove", (event) => {
2294
+ this.handleTouchMove(event);
2291
2295
  }, { capture: true, passive: false });
2292
- document.addEventListener("pointerup", (event) => {
2293
- this.handlePointerUp(event);
2296
+ document.addEventListener("touchend", (event) => {
2297
+ this.handleTouchEnd(event);
2294
2298
  }, { capture: true });
2295
- document.addEventListener("pointercancel", (event) => {
2296
- this.handlePointerCancel(event);
2299
+ document.addEventListener("click", (event) => {
2300
+ this.handleGenericClick(event);
2297
2301
  }, { capture: true });
2298
2302
  document.addEventListener("dragstart", (event) => {
2299
2303
  this.handleNativeDragStart(event);
@@ -2303,14 +2307,29 @@
2303
2307
  const elements = Array.from(document.querySelectorAll(".dragging"));
2304
2308
  return elements.length > 0;
2305
2309
  }
2306
- handlePointerDown(event) {
2310
+ applyNonInteractiveClasses() {
2311
+ const raw_elements = document.querySelectorAll("section.block");
2312
+ const elements = Array.from(raw_elements);
2313
+ elements.forEach((element) => {
2314
+ element.classList.add("no-interaction");
2315
+ });
2316
+ }
2317
+ isTouchDevice() {
2318
+ if (Math.random() > 0) {
2319
+ return true;
2320
+ }
2321
+ const pointer_matches = window.matchMedia("(pointer: coarse)").matches;
2322
+ const hover_none_matches = window.matchMedia("(hover: none)").matches;
2323
+ return pointer_matches && hover_none_matches;
2324
+ }
2325
+ handleTouchStart(event) {
2307
2326
  const { target } = event;
2308
2327
  if (target === null) {
2309
2328
  return;
2310
2329
  }
2311
2330
  const target_element = target;
2312
2331
  let current_element = target_element;
2313
- while (current_element) {
2332
+ while (current_element instanceof HTMLElement) {
2314
2333
  const attribute = current_element.getAttribute("data-role");
2315
2334
  if (attribute === "block_activation") {
2316
2335
  break;
@@ -2319,15 +2338,12 @@
2319
2338
  return;
2320
2339
  }
2321
2340
  current_element = current_element.parentNode;
2322
- if (!(current_element instanceof HTMLElement)) {
2323
- break;
2324
- }
2325
2341
  }
2326
2342
  const block = target_element.closest("section.block");
2327
2343
  if (block === null) {
2328
2344
  return;
2329
2345
  }
2330
- if (target_element.closest("button, input, textarea, select, label, form")) {
2346
+ if (target_element.closest("input, textarea, select, label, form")) {
2331
2347
  return;
2332
2348
  }
2333
2349
  const coordinate = this.getEventCoordinate(event);
@@ -2337,6 +2353,7 @@
2337
2353
  this.drag_start_coordinate = coordinate;
2338
2354
  block.classList.add("drag-candidate");
2339
2355
  this.scheduleDelayedDrag();
2356
+ event.preventDefault();
2340
2357
  }
2341
2358
  scheduleDelayedDrag() {
2342
2359
  this.cancelDelayedDrag();
@@ -2348,7 +2365,8 @@
2348
2365
  clearTimeout(this.drag_delay_timer);
2349
2366
  }
2350
2367
  }
2351
- removeClassFromAllElements(class_name) {
2368
+ demoteAllDragCandidates() {
2369
+ const class_name = "drag-candidate";
2352
2370
  const raw_elements = document.querySelectorAll(`.${class_name}`);
2353
2371
  const elements = Array.from(raw_elements);
2354
2372
  elements.forEach((element) => {
@@ -2356,7 +2374,22 @@
2356
2374
  });
2357
2375
  return elements;
2358
2376
  }
2377
+ createDragMask() {
2378
+ const mask = document.createElement("div");
2379
+ mask.classList.add("drag-mask");
2380
+ document.body.appendChild(mask);
2381
+ document.body.style.overflow = "hidden";
2382
+ }
2383
+ hideDragMask() {
2384
+ const raw_elements = document.querySelectorAll(".drag-mask");
2385
+ const elements = Array.from(raw_elements);
2386
+ elements.forEach((element) => {
2387
+ document.body.removeChild(element);
2388
+ });
2389
+ document.body.style.overflow = "auto";
2390
+ }
2359
2391
  beginDelayedDrag() {
2392
+ this.createDragMask();
2360
2393
  const raw_candidates = document.querySelectorAll(".drag-candidate");
2361
2394
  const candidates = Array.from(raw_candidates);
2362
2395
  candidates.forEach((candidate) => {
@@ -2380,6 +2413,7 @@
2380
2413
  });
2381
2414
  candidate.setAttribute("data-drag-start-x", rect.left.toString());
2382
2415
  candidate.setAttribute("data-drag-start-y", rect.top.toString());
2416
+ candidate.setAttribute("data-dragging", "true");
2383
2417
  candidate.classList.add("dragging");
2384
2418
  parentNode.insertBefore(ghost, candidate);
2385
2419
  });
@@ -2394,28 +2428,13 @@
2394
2428
  event.preventDefault();
2395
2429
  }
2396
2430
  }
2397
- handlePointerMove(event) {
2431
+ handleTouchMove(event) {
2398
2432
  const current_coordinate = this.getEventCoordinate(event);
2399
2433
  const start_coordinate = this.getDragStartCoordinate();
2400
2434
  if (start_coordinate === null || current_coordinate === null) {
2401
2435
  return;
2402
2436
  }
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");
2410
- }
2411
- }
2412
- }
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");
2418
- }
2437
+ this.demoteAllDragCandidates();
2419
2438
  this.scheduleDelayedDrag();
2420
2439
  const raw_targets = document.querySelectorAll(".dragging");
2421
2440
  const drag_target_blocks = Array.from(raw_targets);
@@ -2547,26 +2566,36 @@
2547
2566
  }
2548
2567
  return null;
2549
2568
  }
2550
- handlePointerUp(event) {
2569
+ handleTouchEnd(event) {
2551
2570
  this.stopDragging();
2552
2571
  }
2553
- handlePointerCancel(event) {
2554
- this.stopDragging();
2572
+ handleGenericClick(event) {
2573
+ const { target } = event;
2574
+ if (target === null) {
2575
+ return;
2576
+ }
2577
+ const target_element = target;
2578
+ const block = target_element.closest("section.block");
2579
+ if (block === null) {
2580
+ return;
2581
+ }
2582
+ const attribute = block.getAttribute("data-dragging");
2583
+ if (attribute === "true") {
2584
+ block.removeAttribute("data-dragging");
2585
+ event.preventDefault();
2586
+ event.stopPropagation();
2587
+ }
2555
2588
  }
2556
2589
  stopDragging() {
2557
- this.showFullscreenBlockingOverlay();
2558
2590
  this.stopDraggingAsync().then(() => {
2559
- this.hideFullscreenBlockingOverlay();
2591
+ this.hideDragMask();
2560
2592
  });
2561
2593
  }
2562
- showFullscreenBlockingOverlay() {
2563
- }
2564
- hideFullscreenBlockingOverlay() {
2565
- }
2566
2594
  async stopDraggingAsync() {
2567
2595
  this.cancelDelayedDrag();
2568
- this.removeClassFromAllElements("drag-candidate");
2569
- const dragging_elements = this.removeClassFromAllElements("dragging");
2596
+ this.demoteAllDragCandidates();
2597
+ const raw_elements = document.querySelectorAll(".dragging");
2598
+ const dragging_elements = Array.from(raw_elements);
2570
2599
  let index = 0;
2571
2600
  while (index < dragging_elements.length) {
2572
2601
  const element = dragging_elements[index++];
@@ -2574,8 +2603,8 @@
2574
2603
  const source_index_path = get_index_path_for_element_default(element);
2575
2604
  const target_index_path = this.getIndexPathForGhost(ghost);
2576
2605
  await this.submitReposition(source_index_path, target_index_path);
2577
- ghost.replaceWith(element);
2578
2606
  Object.assign(element.style, {
2607
+ opacity: "0",
2579
2608
  left: "",
2580
2609
  top: "",
2581
2610
  right: "",
@@ -2583,39 +2612,55 @@
2583
2612
  width: "",
2584
2613
  height: ""
2585
2614
  });
2615
+ element.classList.remove("dragging");
2616
+ ghost.replaceWith(element);
2617
+ element.style.opacity = "1";
2586
2618
  }
2619
+ this.recomputeIndexPaths();
2587
2620
  }
2588
- getIndexPathSafe(element) {
2589
- const is_block = element.classList.contains("block");
2590
- if (!is_block) {
2591
- return null;
2592
- }
2593
- const is_ghost = element.classList.contains("ghost");
2594
- if (is_ghost) {
2595
- return null;
2596
- }
2597
- return get_index_path_for_element_default(element);
2621
+ recomputeIndexPaths() {
2622
+ const raw_blocks = document.querySelectorAll("section.block");
2623
+ const blocks = Array.from(raw_blocks);
2624
+ let index = 0;
2625
+ blocks.forEach((block) => {
2626
+ const block_parent = block.parentNode;
2627
+ if (block_parent === null) {
2628
+ throw new import_errors8.InvariantViolation(`
2629
+ Tried to read block parent element, but it was not set
2630
+ `);
2631
+ }
2632
+ const multicolumn_ancestor = block_parent.closest("section.block.multi_column");
2633
+ if (multicolumn_ancestor === null) {
2634
+ const index_path = index.toString();
2635
+ block.setAttribute("data-index-path", index_path);
2636
+ index++;
2637
+ }
2638
+ });
2598
2639
  }
2599
2640
  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;
2605
- }
2606
- current_child = current_child.nextElementSibling;
2641
+ const parent_element = ghost.parentNode;
2642
+ if (parent_element === null) {
2643
+ throw new import_errors8.InvariantViolation(`
2644
+ Tried to read parent element for ghost, but it was not set
2645
+ `);
2607
2646
  }
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();
2647
+ const siblings = Array.from(parent_element.children);
2648
+ let index = 0;
2649
+ let effective_index = 0;
2650
+ while (index < siblings.length) {
2651
+ const sibling = siblings[index++];
2652
+ if (!sibling.classList.contains("block")) {
2653
+ continue;
2654
+ }
2655
+ if (sibling.classList.contains("dragging")) {
2656
+ continue;
2657
+ }
2658
+ if (sibling === ghost) {
2659
+ break;
2615
2660
  }
2616
- current_child = current_child.previousElementSibling;
2661
+ effective_index++;
2617
2662
  }
2618
- return "0";
2663
+ return effective_index.toString();
2619
2664
  }
2620
2665
  async submitReposition(source_index_path, target_index_path) {
2621
2666
  const form = new FormData();
@@ -2637,9 +2682,17 @@
2637
2682
  }
2638
2683
  }
2639
2684
  getEventCoordinate(event) {
2685
+ const { touches } = event;
2686
+ if (touches === void 0) {
2687
+ return null;
2688
+ }
2689
+ const touch = touches[0];
2690
+ if (touch === void 0) {
2691
+ return null;
2692
+ }
2640
2693
  return {
2641
- x: event.clientX,
2642
- y: event.clientY
2694
+ x: touch.clientX,
2695
+ y: touch.clientY
2643
2696
  };
2644
2697
  }
2645
2698
  getDragStartCoordinate() {
@@ -3079,13 +3132,21 @@
3079
3132
  window.location.href = href;
3080
3133
  }
3081
3134
  activateAudioBlock(block_element) {
3082
- const audio_element = block_element.querySelectorAll("audio")[0];
3083
- if (audio_element === void 0) {
3135
+ const audio_element = block_element.querySelector("audio");
3136
+ if (audio_element === null) {
3084
3137
  throw new import_errors9.InvariantViolation(`
3085
3138
  Tried to read audio element for block, but it was not present
3086
3139
  `);
3087
3140
  }
3088
- this.enqueueMedia(audio_element);
3141
+ const persistent_element = document.getElementById("persistent-audio");
3142
+ const persistent_audio = persistent_element;
3143
+ const is_toggling = persistent_audio.src === audio_element.src;
3144
+ const is_playing = this.hasActiveMedia();
3145
+ if (is_toggling && is_playing) {
3146
+ this.pauseActiveMedia();
3147
+ } else {
3148
+ this.enqueueMedia(audio_element);
3149
+ }
3089
3150
  }
3090
3151
  enqueueMedia(element) {
3091
3152
  this.pauseActiveMedia();
@@ -3111,15 +3172,19 @@
3111
3172
  this.focusCurrentBlockElement();
3112
3173
  const persistent_element = document.getElementById("persistent-audio");
3113
3174
  const persistent_audio = persistent_element;
3114
- const track_target = document.getElementById("persistent-track-name");
3115
- const artist_target = document.getElementById("persistent-artist-name");
3116
- const track_source = media_block.querySelector('[data-role="track_name"]');
3117
- const artist_source = media_block.querySelector('[data-role="artist_name"]');
3118
3175
  if (persistent_audio === null) {
3119
3176
  throw new import_errors9.InvariantViolation(`
3120
3177
  Tried to access persistent audio element, but it was not found
3121
3178
  `);
3122
3179
  }
3180
+ if (persistent_audio.src === element.src) {
3181
+ persistent_audio.play();
3182
+ return;
3183
+ }
3184
+ const track_target = document.getElementById("persistent-track-name");
3185
+ const artist_target = document.getElementById("persistent-artist-name");
3186
+ const track_source = media_block.querySelector('[data-role="track_name"]');
3187
+ const artist_source = media_block.querySelector('[data-role="artist_name"]');
3123
3188
  if (track_target === null) {
3124
3189
  throw new import_errors9.InvariantViolation(`
3125
3190
  Tried to access persistent track name element, but it was not found
@@ -3140,12 +3205,51 @@
3140
3205
  Tried to read artist name source, but it was not found
3141
3206
  `);
3142
3207
  }
3208
+ const track_name = track_source.innerHTML;
3209
+ const artist_name = artist_source.innerHTML;
3210
+ const album_name = "";
3143
3211
  persistent_audio.src = element.src;
3144
- track_target.innerHTML = track_source.innerHTML;
3145
- artist_target.innerHTML = artist_source.innerHTML;
3212
+ track_target.innerHTML = track_name;
3213
+ artist_target.innerHTML = artist_name;
3146
3214
  document.body.classList.add("media-visible");
3147
3215
  persistent_audio.currentTime = 0;
3148
3216
  persistent_audio.play();
3217
+ if (typeof navigator.mediaSession === void 0) {
3218
+ return;
3219
+ }
3220
+ this.determineMediaSessionArtworkUrl().then((artwork_url) => {
3221
+ const artwork = (() => {
3222
+ if (artwork_url === null) {
3223
+ return [];
3224
+ }
3225
+ return [
3226
+ { src: artwork_url, sizes: "256x256", type: "image/png" }
3227
+ ];
3228
+ })();
3229
+ navigator.mediaSession.metadata = new MediaMetadata({
3230
+ title: track_name,
3231
+ artist: artist_name,
3232
+ album: album_name,
3233
+ artwork
3234
+ });
3235
+ }).catch((error) => {
3236
+ throw error;
3237
+ });
3238
+ }
3239
+ async determineMediaSessionArtworkUrl() {
3240
+ const elements = Array.from(document.querySelectorAll("section.block"));
3241
+ const blocks = elements;
3242
+ let index = 0;
3243
+ while (index < blocks.length) {
3244
+ const block = blocks[index++];
3245
+ if (block.classList.contains("image")) {
3246
+ const img = block.querySelector("img");
3247
+ if (img !== null) {
3248
+ return img.src;
3249
+ }
3250
+ }
3251
+ }
3252
+ return null;
3149
3253
  }
3150
3254
  handleMediaCanPlay(event) {
3151
3255
  const target = event.target;
@@ -3209,15 +3313,18 @@
3209
3313
  const elements = document.querySelectorAll("audio,video");
3210
3314
  const media_elements = Array.from(elements);
3211
3315
  return media_elements.filter((media_element) => {
3212
- if (media_element.paused || media_element.ended) {
3213
- return false;
3214
- }
3215
- if (media_element.readyState < media_ready_state_default.HAVE_CURRENT_DATA) {
3216
- return false;
3217
- }
3218
- return true;
3316
+ return this.mediaIsActive(media_element);
3219
3317
  });
3220
3318
  }
3319
+ mediaIsActive(media_element) {
3320
+ if (media_element.paused || media_element.ended) {
3321
+ return false;
3322
+ }
3323
+ if (media_element.readyState < media_ready_state_default.HAVE_CURRENT_DATA) {
3324
+ return false;
3325
+ }
3326
+ return true;
3327
+ }
3221
3328
  pauseActiveMedia() {
3222
3329
  this.setQueuedMedia(null);
3223
3330
  const active_media = this.getActiveMedia();
@@ -4,24 +4,26 @@ declare class InteractionHelper {
4
4
  constructor();
5
5
  attach(): void;
6
6
  isDragging(): boolean;
7
- private handlePointerDown;
7
+ private applyNonInteractiveClasses;
8
+ private isTouchDevice;
9
+ private handleTouchStart;
8
10
  private scheduleDelayedDrag;
9
11
  private cancelDelayedDrag;
10
- private removeClassFromAllElements;
12
+ private demoteAllDragCandidates;
13
+ private createDragMask;
14
+ private hideDragMask;
11
15
  private beginDelayedDrag;
12
16
  private handleNativeDragStart;
13
- private handlePointerMove;
17
+ private handleTouchMove;
14
18
  private translateDragTargetBlock;
15
19
  private getGhostForBlock;
16
20
  private getPreviousBlock;
17
21
  private getNextBlock;
18
- private handlePointerUp;
19
- private handlePointerCancel;
22
+ private handleTouchEnd;
23
+ private handleGenericClick;
20
24
  private stopDragging;
21
- private showFullscreenBlockingOverlay;
22
- private hideFullscreenBlockingOverlay;
23
25
  private stopDraggingAsync;
24
- private getIndexPathSafe;
26
+ private recomputeIndexPaths;
25
27
  private getIndexPathForGhost;
26
28
  private submitReposition;
27
29
  private getEventCoordinate;