@pixerate/editor 0.265.0 → 0.266.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -392,276 +392,6 @@ function eitherKey(chord) {
392
392
  return [(chord.mod || chord.ctrl || chord.meta) && "Mod", chord.alt && "Alt", chord.shift && "Shift", chord.key].filter(Boolean).join("+");
393
393
  }
394
394
 
395
- // src/canvas/arrangeShortcuts.ts
396
- var DEFAULT_ARRANGE_SHORTCUTS = [
397
- { action: "alignLeft", code: "KeyA", alt: true, label: "Alt+A" },
398
- { action: "alignCenter", code: "KeyH", alt: true, label: "Alt+H" },
399
- { action: "alignRight", code: "KeyD", alt: true, label: "Alt+D" },
400
- { action: "alignTop", code: "KeyW", alt: true, label: "Alt+W" },
401
- { action: "alignMiddle", code: "KeyV", alt: true, label: "Alt+V" },
402
- { action: "alignBottom", code: "KeyS", alt: true, label: "Alt+S" },
403
- { action: "distributeHorizontal", code: "KeyH", alt: true, shift: true, label: "Alt+Shift+H" },
404
- { action: "distributeVertical", code: "KeyV", alt: true, shift: true, label: "Alt+Shift+V" },
405
- { action: "lock", code: "KeyL", mod: true, label: "Mod+L" },
406
- { action: "unlock", code: "KeyL", mod: true, alt: true, label: "Mod+Alt+L" },
407
- { action: "bringForward", code: "BracketRight", mod: true, label: "Mod+]" },
408
- { action: "sendBackward", code: "BracketLeft", mod: true, label: "Mod+[" },
409
- { action: "bringToFront", code: "BracketRight", mod: true, alt: true, label: "Mod+Alt+]" },
410
- { action: "sendToBack", code: "BracketLeft", mod: true, alt: true, label: "Mod+Alt+[" },
411
- { action: "nextScene", code: "PageDown", label: "PageDown" },
412
- { action: "previousScene", code: "PageUp", label: "PageUp" }
413
- ];
414
- var maps = /* @__PURE__ */ new WeakMap();
415
- function arrangeShortcutMap(bindings) {
416
- let map = maps.get(bindings);
417
- if (!map) {
418
- map = new ShortcutMap(
419
- bindings.map((b) => ({
420
- command: b.action,
421
- chord: { key: b.code, mod: b.mod, alt: b.alt, shift: b.shift }
422
- })),
423
- { modifierMode: "either" }
424
- );
425
- maps.set(bindings, map);
426
- }
427
- return map;
428
- }
429
- function matchArrangeShortcut(event, bindings = DEFAULT_ARRANGE_SHORTCUTS) {
430
- return arrangeShortcutMap(bindings).resolve(event)?.command ?? null;
431
- }
432
-
433
- // src/canvas/gestures.ts
434
- function gestureRandom(seed) {
435
- let a = seed >>> 0;
436
- return () => {
437
- a = a + 1831565813 >>> 0;
438
- let t = a;
439
- t = Math.imul(t ^ t >>> 15, t | 1);
440
- t ^= t + Math.imul(t ^ t >>> 7, t | 61);
441
- return ((t ^ t >>> 14) >>> 0) / 4294967296;
442
- };
443
- }
444
- function gestureSeed(value) {
445
- const text = JSON.stringify(value) ?? "";
446
- let h = 2166136261;
447
- for (let i = 0; i < text.length; i++) {
448
- h ^= text.charCodeAt(i);
449
- h = Math.imul(h, 16777619);
450
- }
451
- return h >>> 0;
452
- }
453
- function gestureUnion(rects) {
454
- if (!rects.length) throw new Error("Pass at least one rect.");
455
- const x = Math.min(...rects.map((r) => r.x));
456
- const y = Math.min(...rects.map((r) => r.y));
457
- const right = Math.max(...rects.map((r) => r.x + r.width));
458
- const bottom = Math.max(...rects.map((r) => r.y + r.height));
459
- return { x, y, width: right - x, height: bottom - y };
460
- }
461
- var clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
462
- var centre = (r) => [r.x + r.width / 2, r.y + r.height / 2];
463
- function smoothNoise(rand, octaves = 3) {
464
- const waves = Array.from({ length: octaves }, (_, i) => ({ f: (i + 1) * (0.6 + rand() * 0.8), phase: rand() * Math.PI * 2, amp: 1 / (i + 1) }));
465
- const total = waves.reduce((sum, w) => sum + w.amp, 0);
466
- return (t) => waves.reduce((sum, w) => sum + w.amp * Math.sin(2 * Math.PI * w.f * t + w.phase), 0) / total;
467
- }
468
- function handPressure(rand) {
469
- const r = (lo, hi) => Math.round((lo + rand() * (hi - lo)) * 100) / 100;
470
- return [r(0.35, 0.55), r(0.8, 0.95), r(0.9, 1), r(0.75, 0.95), r(0.4, 0.65)];
471
- }
472
- var round = (p) => [Math.round(p[0] * 100) / 100, Math.round(p[1] * 100) / 100];
473
- function wobblyLine(a, b, rand, amp, bow = 0) {
474
- const dx = b[0] - a[0];
475
- const dy = b[1] - a[1];
476
- const len = Math.hypot(dx, dy);
477
- if (len === 0) return [a];
478
- const nx = -dy / len;
479
- const ny = dx / len;
480
- const noise = smoothNoise(rand);
481
- const n = clamp(Math.ceil(len / 4), 8, 200);
482
- return Array.from({ length: n + 1 }, (_, i) => {
483
- const t = i / n;
484
- const off = bow * 4 * t * (1 - t) + amp * noise(t) * Math.sqrt(Math.sin(Math.PI * t));
485
- return [a[0] + dx * t + nx * off, a[1] + dy * t + ny * off];
486
- });
487
- }
488
- function circleGesture(rect, seed, options = {}) {
489
- const rand = gestureRandom(seed);
490
- const pad = Math.max(0, options.padding ?? 8);
491
- const [cx, cy] = centre(rect);
492
- const tilt = (rand() - 0.5) * 0.08;
493
- const c = Math.abs(Math.cos(tilt));
494
- const s = Math.abs(Math.sin(tilt));
495
- const a = (rect.width / 2 * c + rect.height / 2 * s) * Math.SQRT2 + pad;
496
- const b = (rect.width / 2 * s + rect.height / 2 * c) * Math.SQRT2 + pad;
497
- const dir = rand() < 0.7 ? -1 : 1;
498
- const start = -Math.PI * 0.75 + (rand() - 0.5) * 0.6;
499
- const sweep = Math.PI * 2 + Math.PI * (0.1 + rand() * 0.12);
500
- const jitter = 0.03 + rand() * 0.03;
501
- const drift = 0.04 + rand() * 0.05;
502
- const noise = smoothNoise(rand, 4);
503
- const perimeter = Math.PI * (3 * (a + b) - Math.sqrt((3 * a + b) * (a + 3 * b)));
504
- const n = clamp(Math.ceil(perimeter * (sweep / (Math.PI * 2)) / 5), 48, 360);
505
- const points = Array.from({ length: n + 1 }, (_, i) => {
506
- const t = i / n;
507
- const angle = start + dir * sweep * t;
508
- const grow = 1 + jitter * (0.5 + 0.5 * noise(t)) + drift * t * t;
509
- const ex = a * grow * Math.cos(angle);
510
- const ey = b * grow * Math.sin(angle);
511
- return round([cx + ex * Math.cos(tilt) - ey * Math.sin(tilt), cy + ex * Math.sin(tilt) + ey * Math.cos(tilt)]);
512
- });
513
- return { points, pressure: handPressure(rand) };
514
- }
515
- function underlineGesture(rect, seed, options = {}) {
516
- const rand = gestureRandom(seed);
517
- const offset = Math.max(0, options.offset ?? 4);
518
- const amp = options.wave ? clamp(rect.width * 0.02, 2, 4) : 0;
519
- const shake = Math.min(1.5, offset * 0.4);
520
- const base = rect.y + rect.height + offset + amp + shake;
521
- const slope = Math.min(6, rect.width * 0.03);
522
- const x0 = rect.x - rect.width * (0.01 + rand() * 0.04);
523
- const x1 = rect.x + rect.width * (0.96 + rand() * 0.08);
524
- const line = wobblyLine([x0, base + rand() * slope], [x1, base + rand() * slope], rand, shake, (rand() - 0.5) * 2 * shake);
525
- const wavelength = clamp(rect.width / 8, 12, 28);
526
- const phase = rand() * Math.PI * 2;
527
- const points = amp ? line.map(([x, y]) => [x, y + amp * Math.sin(2 * Math.PI * (x - x0) / wavelength + phase)]) : line;
528
- return { points: points.map(round), pressure: handPressure(rand) };
529
- }
530
- function gestureEdgePoint(rect, toward, gap = 0) {
531
- const [cx, cy] = centre(rect);
532
- const dx = toward[0] - cx;
533
- const dy = toward[1] - cy;
534
- const len = Math.hypot(dx, dy);
535
- if (len === 0) return [cx, cy];
536
- const t = Math.min(dx ? rect.width / 2 / Math.abs(dx) : Infinity, dy ? rect.height / 2 / Math.abs(dy) : Infinity);
537
- return [cx + dx * t + dx / len * gap, cy + dy * t + dy / len * gap];
538
- }
539
- var isRect = (end) => !Array.isArray(end);
540
- function arrowGesture(from, to, seed, options = {}) {
541
- const rand = gestureRandom(seed);
542
- const gap = Math.max(0, options.gap ?? 6);
543
- const fromCentre = isRect(from) ? centre(from) : from;
544
- const toCentre = isRect(to) ? centre(to) : to;
545
- const start = isRect(from) ? gestureEdgePoint(from, toCentre, gap) : from;
546
- const tip = isRect(to) ? gestureEdgePoint(to, fromCentre, gap) : to;
547
- const dx = tip[0] - start[0];
548
- const dy = tip[1] - start[1];
549
- const len = Math.hypot(dx, dy);
550
- if (len < 4) throw new Error("The arrow's ends are too close together (or overlap): pass ends at least a few canvas units apart.");
551
- const curve = clamp(options.curve ?? (0.08 + rand() * 0.08) * (rand() < 0.5 ? -1 : 1), -1, 1);
552
- const nx = -dy / len;
553
- const ny = dx / len;
554
- const control = [(start[0] + tip[0]) / 2 + nx * curve * len, (start[1] + tip[1]) / 2 + ny * curve * len];
555
- const noise = smoothNoise(rand);
556
- const amp = Math.min(2, len * 0.01);
557
- const n = clamp(Math.ceil(len / 4), 12, 200);
558
- const shaft = Array.from({ length: n + 1 }, (_, i) => {
559
- const t = i / n;
560
- const u = 1 - t;
561
- const x = u * u * start[0] + 2 * u * t * control[0] + t * t * tip[0];
562
- const y = u * u * start[1] + 2 * u * t * control[1] + t * t * tip[1];
563
- const off = amp * noise(t) * Math.sqrt(Math.sin(Math.PI * t));
564
- return [x + nx * off, y + ny * off];
565
- });
566
- const tx = tip[0] - control[0];
567
- const ty = tip[1] - control[1];
568
- const tl = Math.hypot(tx, ty) || 1;
569
- const head = clamp(len * 0.15, 8, 22);
570
- const barb = (angle2, length) => {
571
- const c = Math.cos(angle2);
572
- const s = Math.sin(angle2);
573
- const bx = -(tx / tl) * c + ty / tl * s;
574
- const by = -(ty / tl) * c - tx / tl * s;
575
- return [1 / 3, 2 / 3, 1].map((f) => [tip[0] + bx * length * f, tip[1] + by * length * f]);
576
- };
577
- const clear = (pts) => !isRect(to) || pts.every(([x, y]) => x <= to.x || x >= to.x + to.width || y <= to.y || y >= to.y + to.height);
578
- const fit = (angle2) => {
579
- const length = head * (0.85 + rand() * 0.3);
580
- for (let k = 1; k > 0.05; k -= 0.15) {
581
- const pts = barb(angle2 * k, length);
582
- if (clear(pts)) return pts;
583
- }
584
- return barb(0, length);
585
- };
586
- const angle = () => (25 + rand() * 8) * Math.PI / 180;
587
- const first = fit(angle());
588
- const second = fit(-angle());
589
- const points = [...shaft, ...first, ...first.slice(0, -1).reverse(), tip, ...second];
590
- return { points: points.map(round), pressure: handPressure(rand) };
591
- }
592
- function bracketGesture(rect, side, seed, options = {}) {
593
- const rand = gestureRandom(seed);
594
- const pad = Math.max(0, options.padding ?? 8);
595
- const vertical = side === "left" || side === "right";
596
- const span = vertical ? rect.height : rect.width;
597
- const depth = Math.max(1, options.depth ?? clamp(span * 0.08, 6, 20));
598
- const from = vertical ? rect.y : rect.x;
599
- const edge = side === "left" ? rect.x - pad : side === "right" ? rect.x + rect.width + pad : side === "top" ? rect.y - pad : rect.y + rect.height + pad;
600
- const out = side === "left" || side === "top" ? -1 : 1;
601
- const at = (s, d) => vertical ? [edge + out * d, from + s * span] : [from + s * span, edge + out * d];
602
- const noise = smoothNoise(rand);
603
- const shake = Math.min(1, depth * 0.06);
604
- const n = clamp(Math.ceil(span / 4), 24, 240);
605
- let points;
606
- if (options.shape === "square") {
607
- const arm = depth * (0.8 + rand() * 0.2);
608
- const spine = Array.from({ length: n + 1 }, (_, i) => at(i / n, depth + shake * (1 + noise(i / n))));
609
- points = [at(0, depth - arm), at(0, depth * 0.5), ...spine, at(1, depth * 0.5), at(1, depth - arm * (0.85 + rand() * 0.15))];
610
- } else {
611
- const e = clamp(depth / Math.max(span, 1), 0.04, 0.2);
612
- const brace = (s) => {
613
- const u = s <= 0.5 ? s : 1 - s;
614
- if (u < e) return depth / 2 * Math.sin(Math.PI / 2 * u / e);
615
- if (u < 0.5 - e) return depth / 2;
616
- return depth / 2 + depth / 2 * (1 - Math.cos(Math.PI / 2 * (u - (0.5 - e)) / e));
617
- };
618
- points = Array.from({ length: n + 1 }, (_, i) => {
619
- const s = i / n;
620
- return at(s, brace(s) + shake * (1 + noise(s)) * Math.sin(Math.PI * s));
621
- });
622
- }
623
- return { points: points.map(round), pressure: handPressure(rand) };
624
- }
625
- function strikeGesture(rect, seed) {
626
- const rand = gestureRandom(seed);
627
- const [, cy] = centre(rect);
628
- const slope = rect.height * 0.08;
629
- const x0 = rect.x - rect.width * (0.01 + rand() * 0.03);
630
- const x1 = rect.x + rect.width * (1.01 + rand() * 0.03);
631
- const y0 = cy + (rand() - 0.5) * rect.height * 0.1 + slope * (rand() - 0.5);
632
- const y1 = cy + (rand() - 0.5) * rect.height * 0.1 + slope * (rand() - 0.5);
633
- const points = wobblyLine([x0, y0], [x1, y1], rand, Math.min(1.5, rect.height * 0.05));
634
- return { points: points.map(round), pressure: handPressure(rand) };
635
- }
636
- function crossGesture(rect, seed) {
637
- const rand = gestureRandom(seed);
638
- const over = () => 0.02 + rand() * 0.04;
639
- const left = () => rect.x - rect.width * over();
640
- const right = () => rect.x + rect.width * (1 + over());
641
- const top = () => rect.y - rect.height * over();
642
- const bottom = () => rect.y + rect.height * (1 + over());
643
- const amp = Math.min(1.5, Math.min(rect.width, rect.height) * 0.03);
644
- const first = wobblyLine([left(), top()], [right(), bottom()], rand, amp);
645
- const second = wobblyLine([right(), top()], [left(), bottom()], rand, amp);
646
- const mid1 = Math.floor(first.length / 2);
647
- const mid2 = Math.floor(second.length / 2);
648
- const points = [...first, ...first.slice(mid1, -1).reverse(), ...second.slice(1, mid2 + 1).reverse(), ...second];
649
- return { points: points.map(round), pressure: handPressure(rand) };
650
- }
651
- function checkGesture(at, seed, options = {}) {
652
- const rand = gestureRandom(seed);
653
- const [cx, cy] = isRect(at) ? centre(at) : at;
654
- const s = Math.max(4, options.size ?? (isRect(at) ? clamp(Math.min(at.width, at.height) * 0.6, 12, 48) : 20));
655
- const turn = (rand() - 0.5) * 12 * Math.PI / 180;
656
- const place = ([x, y]) => [cx + s * (x * Math.cos(turn) - y * Math.sin(turn)), cy + s * (x * Math.sin(turn) + y * Math.cos(turn))];
657
- const p0 = [-0.42 + rand() * 0.08, -0.05 + rand() * 0.08];
658
- const p1 = [-0.12 + rand() * 0.06, 0.38 + rand() * 0.06];
659
- const p2 = [0.48 + rand() * 0.06, -0.5 + rand() * 0.06];
660
- const short = wobblyLine(place(p0), place(p1), rand, 0, -s * 0.03);
661
- const long = wobblyLine(place(p1), place(p2), rand, Math.min(1, s * 0.02), s * 0.06);
662
- return { points: [...short, ...long.slice(1)].map(round), pressure: [0.5, 0.95, 0.9, 0.7, 0.35] };
663
- }
664
-
665
395
  export {
666
396
  PLATFORMS,
667
397
  detectPlatform,
@@ -678,18 +408,5 @@ export {
678
408
  codeFromKey,
679
409
  isEditableEventTarget,
680
410
  toShortcutBindings,
681
- ShortcutMap,
682
- DEFAULT_ARRANGE_SHORTCUTS,
683
- matchArrangeShortcut,
684
- gestureRandom,
685
- gestureSeed,
686
- gestureUnion,
687
- circleGesture,
688
- underlineGesture,
689
- gestureEdgePoint,
690
- arrowGesture,
691
- bracketGesture,
692
- strikeGesture,
693
- crossGesture,
694
- checkGesture
411
+ ShortcutMap
695
412
  };
@@ -2,8 +2,8 @@
2
2
  var PLATFORMS = ["mac", "windows", "linux"];
3
3
  function detectPlatform() {
4
4
  const nav = typeof navigator !== "undefined" ? navigator : void 0;
5
- const text = `${_nullishCoalesce(_optionalChain([nav, 'optionalAccess', _2 => _2.platform]), () => ( ""))} ${_nullishCoalesce(_optionalChain([nav, 'optionalAccess', _3 => _3.userAgent]), () => ( ""))}`;
6
- if (/Mac|iPod|iPhone|iPad/.test(_optionalChain([nav, 'optionalAccess', _4 => _4.platform]) || _optionalChain([nav, 'optionalAccess', _5 => _5.userAgent]) || "")) return "mac";
5
+ const text = `${_nullishCoalesce(_optionalChain([nav, 'optionalAccess', _ => _.platform]), () => ( ""))} ${_nullishCoalesce(_optionalChain([nav, 'optionalAccess', _2 => _2.userAgent]), () => ( ""))}`;
6
+ if (/Mac|iPod|iPhone|iPad/.test(_optionalChain([nav, 'optionalAccess', _3 => _3.platform]) || _optionalChain([nav, 'optionalAccess', _4 => _4.userAgent]) || "")) return "mac";
7
7
  if (/Win/.test(text)) return "windows";
8
8
  return "linux";
9
9
  }
@@ -222,7 +222,7 @@ function isEditableEventTarget(event) {
222
222
  if (!target) target = typeof document !== "undefined" ? document.activeElement : null;
223
223
  if (!target || typeof target.tagName !== "string") return false;
224
224
  const tag = target.tagName.toUpperCase();
225
- return !!(tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || target.isContentEditable || _optionalChain([target, 'access', _6 => _6.getAttribute, 'optionalCall', _7 => _7("contenteditable")]) === "true" || _optionalChain([target, 'access', _8 => _8.closest, 'optionalCall', _9 => _9('[contenteditable="true"]')]) || _optionalChain([target, 'access', _10 => _10.closest, 'optionalCall', _11 => _11(".ProseMirror")]));
225
+ return !!(tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || target.isContentEditable || _optionalChain([target, 'access', _5 => _5.getAttribute, 'optionalCall', _6 => _6("contenteditable")]) === "true" || _optionalChain([target, 'access', _7 => _7.closest, 'optionalCall', _8 => _8('[contenteditable="true"]')]) || _optionalChain([target, 'access', _9 => _9.closest, 'optionalCall', _10 => _10(".ProseMirror")]));
226
226
  }
227
227
 
228
228
  // src/commands/shortcuts.ts
@@ -392,289 +392,6 @@ function eitherKey(chord) {
392
392
  return [(chord.mod || chord.ctrl || chord.meta) && "Mod", chord.alt && "Alt", chord.shift && "Shift", chord.key].filter(Boolean).join("+");
393
393
  }
394
394
 
395
- // src/canvas/arrangeShortcuts.ts
396
- var DEFAULT_ARRANGE_SHORTCUTS = [
397
- { action: "alignLeft", code: "KeyA", alt: true, label: "Alt+A" },
398
- { action: "alignCenter", code: "KeyH", alt: true, label: "Alt+H" },
399
- { action: "alignRight", code: "KeyD", alt: true, label: "Alt+D" },
400
- { action: "alignTop", code: "KeyW", alt: true, label: "Alt+W" },
401
- { action: "alignMiddle", code: "KeyV", alt: true, label: "Alt+V" },
402
- { action: "alignBottom", code: "KeyS", alt: true, label: "Alt+S" },
403
- { action: "distributeHorizontal", code: "KeyH", alt: true, shift: true, label: "Alt+Shift+H" },
404
- { action: "distributeVertical", code: "KeyV", alt: true, shift: true, label: "Alt+Shift+V" },
405
- { action: "lock", code: "KeyL", mod: true, label: "Mod+L" },
406
- { action: "unlock", code: "KeyL", mod: true, alt: true, label: "Mod+Alt+L" },
407
- { action: "bringForward", code: "BracketRight", mod: true, label: "Mod+]" },
408
- { action: "sendBackward", code: "BracketLeft", mod: true, label: "Mod+[" },
409
- { action: "bringToFront", code: "BracketRight", mod: true, alt: true, label: "Mod+Alt+]" },
410
- { action: "sendToBack", code: "BracketLeft", mod: true, alt: true, label: "Mod+Alt+[" },
411
- { action: "nextScene", code: "PageDown", label: "PageDown" },
412
- { action: "previousScene", code: "PageUp", label: "PageUp" }
413
- ];
414
- var maps = /* @__PURE__ */ new WeakMap();
415
- function arrangeShortcutMap(bindings) {
416
- let map = maps.get(bindings);
417
- if (!map) {
418
- map = new ShortcutMap(
419
- bindings.map((b) => ({
420
- command: b.action,
421
- chord: { key: b.code, mod: b.mod, alt: b.alt, shift: b.shift }
422
- })),
423
- { modifierMode: "either" }
424
- );
425
- maps.set(bindings, map);
426
- }
427
- return map;
428
- }
429
- function matchArrangeShortcut(event, bindings = DEFAULT_ARRANGE_SHORTCUTS) {
430
- return _nullishCoalesce(_optionalChain([arrangeShortcutMap, 'call', _12 => _12(bindings), 'access', _13 => _13.resolve, 'call', _14 => _14(event), 'optionalAccess', _15 => _15.command]), () => ( null));
431
- }
432
-
433
- // src/canvas/gestures.ts
434
- function gestureRandom(seed) {
435
- let a = seed >>> 0;
436
- return () => {
437
- a = a + 1831565813 >>> 0;
438
- let t = a;
439
- t = Math.imul(t ^ t >>> 15, t | 1);
440
- t ^= t + Math.imul(t ^ t >>> 7, t | 61);
441
- return ((t ^ t >>> 14) >>> 0) / 4294967296;
442
- };
443
- }
444
- function gestureSeed(value) {
445
- const text = _nullishCoalesce(JSON.stringify(value), () => ( ""));
446
- let h = 2166136261;
447
- for (let i = 0; i < text.length; i++) {
448
- h ^= text.charCodeAt(i);
449
- h = Math.imul(h, 16777619);
450
- }
451
- return h >>> 0;
452
- }
453
- function gestureUnion(rects) {
454
- if (!rects.length) throw new Error("Pass at least one rect.");
455
- const x = Math.min(...rects.map((r) => r.x));
456
- const y = Math.min(...rects.map((r) => r.y));
457
- const right = Math.max(...rects.map((r) => r.x + r.width));
458
- const bottom = Math.max(...rects.map((r) => r.y + r.height));
459
- return { x, y, width: right - x, height: bottom - y };
460
- }
461
- var clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
462
- var centre = (r) => [r.x + r.width / 2, r.y + r.height / 2];
463
- function smoothNoise(rand, octaves = 3) {
464
- const waves = Array.from({ length: octaves }, (_, i) => ({ f: (i + 1) * (0.6 + rand() * 0.8), phase: rand() * Math.PI * 2, amp: 1 / (i + 1) }));
465
- const total = waves.reduce((sum, w) => sum + w.amp, 0);
466
- return (t) => waves.reduce((sum, w) => sum + w.amp * Math.sin(2 * Math.PI * w.f * t + w.phase), 0) / total;
467
- }
468
- function handPressure(rand) {
469
- const r = (lo, hi) => Math.round((lo + rand() * (hi - lo)) * 100) / 100;
470
- return [r(0.35, 0.55), r(0.8, 0.95), r(0.9, 1), r(0.75, 0.95), r(0.4, 0.65)];
471
- }
472
- var round = (p) => [Math.round(p[0] * 100) / 100, Math.round(p[1] * 100) / 100];
473
- function wobblyLine(a, b, rand, amp, bow = 0) {
474
- const dx = b[0] - a[0];
475
- const dy = b[1] - a[1];
476
- const len = Math.hypot(dx, dy);
477
- if (len === 0) return [a];
478
- const nx = -dy / len;
479
- const ny = dx / len;
480
- const noise = smoothNoise(rand);
481
- const n = clamp(Math.ceil(len / 4), 8, 200);
482
- return Array.from({ length: n + 1 }, (_, i) => {
483
- const t = i / n;
484
- const off = bow * 4 * t * (1 - t) + amp * noise(t) * Math.sqrt(Math.sin(Math.PI * t));
485
- return [a[0] + dx * t + nx * off, a[1] + dy * t + ny * off];
486
- });
487
- }
488
- function circleGesture(rect, seed, options = {}) {
489
- const rand = gestureRandom(seed);
490
- const pad = Math.max(0, _nullishCoalesce(options.padding, () => ( 8)));
491
- const [cx, cy] = centre(rect);
492
- const tilt = (rand() - 0.5) * 0.08;
493
- const c = Math.abs(Math.cos(tilt));
494
- const s = Math.abs(Math.sin(tilt));
495
- const a = (rect.width / 2 * c + rect.height / 2 * s) * Math.SQRT2 + pad;
496
- const b = (rect.width / 2 * s + rect.height / 2 * c) * Math.SQRT2 + pad;
497
- const dir = rand() < 0.7 ? -1 : 1;
498
- const start = -Math.PI * 0.75 + (rand() - 0.5) * 0.6;
499
- const sweep = Math.PI * 2 + Math.PI * (0.1 + rand() * 0.12);
500
- const jitter = 0.03 + rand() * 0.03;
501
- const drift = 0.04 + rand() * 0.05;
502
- const noise = smoothNoise(rand, 4);
503
- const perimeter = Math.PI * (3 * (a + b) - Math.sqrt((3 * a + b) * (a + 3 * b)));
504
- const n = clamp(Math.ceil(perimeter * (sweep / (Math.PI * 2)) / 5), 48, 360);
505
- const points = Array.from({ length: n + 1 }, (_, i) => {
506
- const t = i / n;
507
- const angle = start + dir * sweep * t;
508
- const grow = 1 + jitter * (0.5 + 0.5 * noise(t)) + drift * t * t;
509
- const ex = a * grow * Math.cos(angle);
510
- const ey = b * grow * Math.sin(angle);
511
- return round([cx + ex * Math.cos(tilt) - ey * Math.sin(tilt), cy + ex * Math.sin(tilt) + ey * Math.cos(tilt)]);
512
- });
513
- return { points, pressure: handPressure(rand) };
514
- }
515
- function underlineGesture(rect, seed, options = {}) {
516
- const rand = gestureRandom(seed);
517
- const offset = Math.max(0, _nullishCoalesce(options.offset, () => ( 4)));
518
- const amp = options.wave ? clamp(rect.width * 0.02, 2, 4) : 0;
519
- const shake = Math.min(1.5, offset * 0.4);
520
- const base = rect.y + rect.height + offset + amp + shake;
521
- const slope = Math.min(6, rect.width * 0.03);
522
- const x0 = rect.x - rect.width * (0.01 + rand() * 0.04);
523
- const x1 = rect.x + rect.width * (0.96 + rand() * 0.08);
524
- const line = wobblyLine([x0, base + rand() * slope], [x1, base + rand() * slope], rand, shake, (rand() - 0.5) * 2 * shake);
525
- const wavelength = clamp(rect.width / 8, 12, 28);
526
- const phase = rand() * Math.PI * 2;
527
- const points = amp ? line.map(([x, y]) => [x, y + amp * Math.sin(2 * Math.PI * (x - x0) / wavelength + phase)]) : line;
528
- return { points: points.map(round), pressure: handPressure(rand) };
529
- }
530
- function gestureEdgePoint(rect, toward, gap = 0) {
531
- const [cx, cy] = centre(rect);
532
- const dx = toward[0] - cx;
533
- const dy = toward[1] - cy;
534
- const len = Math.hypot(dx, dy);
535
- if (len === 0) return [cx, cy];
536
- const t = Math.min(dx ? rect.width / 2 / Math.abs(dx) : Infinity, dy ? rect.height / 2 / Math.abs(dy) : Infinity);
537
- return [cx + dx * t + dx / len * gap, cy + dy * t + dy / len * gap];
538
- }
539
- var isRect = (end) => !Array.isArray(end);
540
- function arrowGesture(from, to, seed, options = {}) {
541
- const rand = gestureRandom(seed);
542
- const gap = Math.max(0, _nullishCoalesce(options.gap, () => ( 6)));
543
- const fromCentre = isRect(from) ? centre(from) : from;
544
- const toCentre = isRect(to) ? centre(to) : to;
545
- const start = isRect(from) ? gestureEdgePoint(from, toCentre, gap) : from;
546
- const tip = isRect(to) ? gestureEdgePoint(to, fromCentre, gap) : to;
547
- const dx = tip[0] - start[0];
548
- const dy = tip[1] - start[1];
549
- const len = Math.hypot(dx, dy);
550
- if (len < 4) throw new Error("The arrow's ends are too close together (or overlap): pass ends at least a few canvas units apart.");
551
- const curve = clamp(_nullishCoalesce(options.curve, () => ( (0.08 + rand() * 0.08) * (rand() < 0.5 ? -1 : 1))), -1, 1);
552
- const nx = -dy / len;
553
- const ny = dx / len;
554
- const control = [(start[0] + tip[0]) / 2 + nx * curve * len, (start[1] + tip[1]) / 2 + ny * curve * len];
555
- const noise = smoothNoise(rand);
556
- const amp = Math.min(2, len * 0.01);
557
- const n = clamp(Math.ceil(len / 4), 12, 200);
558
- const shaft = Array.from({ length: n + 1 }, (_, i) => {
559
- const t = i / n;
560
- const u = 1 - t;
561
- const x = u * u * start[0] + 2 * u * t * control[0] + t * t * tip[0];
562
- const y = u * u * start[1] + 2 * u * t * control[1] + t * t * tip[1];
563
- const off = amp * noise(t) * Math.sqrt(Math.sin(Math.PI * t));
564
- return [x + nx * off, y + ny * off];
565
- });
566
- const tx = tip[0] - control[0];
567
- const ty = tip[1] - control[1];
568
- const tl = Math.hypot(tx, ty) || 1;
569
- const head = clamp(len * 0.15, 8, 22);
570
- const barb = (angle2, length) => {
571
- const c = Math.cos(angle2);
572
- const s = Math.sin(angle2);
573
- const bx = -(tx / tl) * c + ty / tl * s;
574
- const by = -(ty / tl) * c - tx / tl * s;
575
- return [1 / 3, 2 / 3, 1].map((f) => [tip[0] + bx * length * f, tip[1] + by * length * f]);
576
- };
577
- const clear = (pts) => !isRect(to) || pts.every(([x, y]) => x <= to.x || x >= to.x + to.width || y <= to.y || y >= to.y + to.height);
578
- const fit = (angle2) => {
579
- const length = head * (0.85 + rand() * 0.3);
580
- for (let k = 1; k > 0.05; k -= 0.15) {
581
- const pts = barb(angle2 * k, length);
582
- if (clear(pts)) return pts;
583
- }
584
- return barb(0, length);
585
- };
586
- const angle = () => (25 + rand() * 8) * Math.PI / 180;
587
- const first = fit(angle());
588
- const second = fit(-angle());
589
- const points = [...shaft, ...first, ...first.slice(0, -1).reverse(), tip, ...second];
590
- return { points: points.map(round), pressure: handPressure(rand) };
591
- }
592
- function bracketGesture(rect, side, seed, options = {}) {
593
- const rand = gestureRandom(seed);
594
- const pad = Math.max(0, _nullishCoalesce(options.padding, () => ( 8)));
595
- const vertical = side === "left" || side === "right";
596
- const span = vertical ? rect.height : rect.width;
597
- const depth = Math.max(1, _nullishCoalesce(options.depth, () => ( clamp(span * 0.08, 6, 20))));
598
- const from = vertical ? rect.y : rect.x;
599
- const edge = side === "left" ? rect.x - pad : side === "right" ? rect.x + rect.width + pad : side === "top" ? rect.y - pad : rect.y + rect.height + pad;
600
- const out = side === "left" || side === "top" ? -1 : 1;
601
- const at = (s, d) => vertical ? [edge + out * d, from + s * span] : [from + s * span, edge + out * d];
602
- const noise = smoothNoise(rand);
603
- const shake = Math.min(1, depth * 0.06);
604
- const n = clamp(Math.ceil(span / 4), 24, 240);
605
- let points;
606
- if (options.shape === "square") {
607
- const arm = depth * (0.8 + rand() * 0.2);
608
- const spine = Array.from({ length: n + 1 }, (_, i) => at(i / n, depth + shake * (1 + noise(i / n))));
609
- points = [at(0, depth - arm), at(0, depth * 0.5), ...spine, at(1, depth * 0.5), at(1, depth - arm * (0.85 + rand() * 0.15))];
610
- } else {
611
- const e = clamp(depth / Math.max(span, 1), 0.04, 0.2);
612
- const brace = (s) => {
613
- const u = s <= 0.5 ? s : 1 - s;
614
- if (u < e) return depth / 2 * Math.sin(Math.PI / 2 * u / e);
615
- if (u < 0.5 - e) return depth / 2;
616
- return depth / 2 + depth / 2 * (1 - Math.cos(Math.PI / 2 * (u - (0.5 - e)) / e));
617
- };
618
- points = Array.from({ length: n + 1 }, (_, i) => {
619
- const s = i / n;
620
- return at(s, brace(s) + shake * (1 + noise(s)) * Math.sin(Math.PI * s));
621
- });
622
- }
623
- return { points: points.map(round), pressure: handPressure(rand) };
624
- }
625
- function strikeGesture(rect, seed) {
626
- const rand = gestureRandom(seed);
627
- const [, cy] = centre(rect);
628
- const slope = rect.height * 0.08;
629
- const x0 = rect.x - rect.width * (0.01 + rand() * 0.03);
630
- const x1 = rect.x + rect.width * (1.01 + rand() * 0.03);
631
- const y0 = cy + (rand() - 0.5) * rect.height * 0.1 + slope * (rand() - 0.5);
632
- const y1 = cy + (rand() - 0.5) * rect.height * 0.1 + slope * (rand() - 0.5);
633
- const points = wobblyLine([x0, y0], [x1, y1], rand, Math.min(1.5, rect.height * 0.05));
634
- return { points: points.map(round), pressure: handPressure(rand) };
635
- }
636
- function crossGesture(rect, seed) {
637
- const rand = gestureRandom(seed);
638
- const over = () => 0.02 + rand() * 0.04;
639
- const left = () => rect.x - rect.width * over();
640
- const right = () => rect.x + rect.width * (1 + over());
641
- const top = () => rect.y - rect.height * over();
642
- const bottom = () => rect.y + rect.height * (1 + over());
643
- const amp = Math.min(1.5, Math.min(rect.width, rect.height) * 0.03);
644
- const first = wobblyLine([left(), top()], [right(), bottom()], rand, amp);
645
- const second = wobblyLine([right(), top()], [left(), bottom()], rand, amp);
646
- const mid1 = Math.floor(first.length / 2);
647
- const mid2 = Math.floor(second.length / 2);
648
- const points = [...first, ...first.slice(mid1, -1).reverse(), ...second.slice(1, mid2 + 1).reverse(), ...second];
649
- return { points: points.map(round), pressure: handPressure(rand) };
650
- }
651
- function checkGesture(at, seed, options = {}) {
652
- const rand = gestureRandom(seed);
653
- const [cx, cy] = isRect(at) ? centre(at) : at;
654
- const s = Math.max(4, _nullishCoalesce(options.size, () => ( (isRect(at) ? clamp(Math.min(at.width, at.height) * 0.6, 12, 48) : 20))));
655
- const turn = (rand() - 0.5) * 12 * Math.PI / 180;
656
- const place = ([x, y]) => [cx + s * (x * Math.cos(turn) - y * Math.sin(turn)), cy + s * (x * Math.sin(turn) + y * Math.cos(turn))];
657
- const p0 = [-0.42 + rand() * 0.08, -0.05 + rand() * 0.08];
658
- const p1 = [-0.12 + rand() * 0.06, 0.38 + rand() * 0.06];
659
- const p2 = [0.48 + rand() * 0.06, -0.5 + rand() * 0.06];
660
- const short = wobblyLine(place(p0), place(p1), rand, 0, -s * 0.03);
661
- const long = wobblyLine(place(p1), place(p2), rand, Math.min(1, s * 0.02), s * 0.06);
662
- return { points: [...short, ...long.slice(1)].map(round), pressure: [0.5, 0.95, 0.9, 0.7, 0.35] };
663
- }
664
-
665
-
666
-
667
-
668
-
669
-
670
-
671
-
672
-
673
-
674
-
675
-
676
-
677
-
678
395
 
679
396
 
680
397
 
@@ -692,4 +409,4 @@ function checkGesture(at, seed, options = {}) {
692
409
 
693
410
 
694
411
 
695
- exports.PLATFORMS = PLATFORMS; exports.detectPlatform = detectPlatform; exports.keyToCode = keyToCode; exports.codeToKeyText = codeToKeyText; exports.parseChord = parseChord; exports.chordToString = chordToString; exports.normalizeChord = normalizeChord; exports.effectiveChord = effectiveChord; exports.effectiveChordKey = effectiveChordKey; exports.formatShortcut = formatShortcut; exports.eventCode = eventCode; exports.shortcutCode = shortcutCode; exports.codeFromKey = codeFromKey; exports.isEditableEventTarget = isEditableEventTarget; exports.toShortcutBindings = toShortcutBindings; exports.ShortcutMap = ShortcutMap; exports.DEFAULT_ARRANGE_SHORTCUTS = DEFAULT_ARRANGE_SHORTCUTS; exports.matchArrangeShortcut = matchArrangeShortcut; exports.gestureRandom = gestureRandom; exports.gestureSeed = gestureSeed; exports.gestureUnion = gestureUnion; exports.circleGesture = circleGesture; exports.underlineGesture = underlineGesture; exports.gestureEdgePoint = gestureEdgePoint; exports.arrowGesture = arrowGesture; exports.bracketGesture = bracketGesture; exports.strikeGesture = strikeGesture; exports.crossGesture = crossGesture; exports.checkGesture = checkGesture;
412
+ exports.PLATFORMS = PLATFORMS; exports.detectPlatform = detectPlatform; exports.keyToCode = keyToCode; exports.codeToKeyText = codeToKeyText; exports.parseChord = parseChord; exports.chordToString = chordToString; exports.normalizeChord = normalizeChord; exports.effectiveChord = effectiveChord; exports.effectiveChordKey = effectiveChordKey; exports.formatShortcut = formatShortcut; exports.eventCode = eventCode; exports.shortcutCode = shortcutCode; exports.codeFromKey = codeFromKey; exports.isEditableEventTarget = isEditableEventTarget; exports.toShortcutBindings = toShortcutBindings; exports.ShortcutMap = ShortcutMap;