@sliiu/present-transition-fx 0.0.0-stage → 0.1.1

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.
Files changed (48) hide show
  1. package/COPYRIGHT +5 -0
  2. package/LICENSE +661 -0
  3. package/README.md +8 -2
  4. package/THIRD-PARTY-NOTICES.md +221 -0
  5. package/dist/cjs/2d.js +487 -0
  6. package/dist/cjs/3d.js +566 -0
  7. package/dist/cjs/geometry.js +141 -0
  8. package/dist/cjs/index.js +98 -0
  9. package/dist/cjs/morph-audit.js +603 -0
  10. package/dist/cjs/morph-match.js +103 -0
  11. package/dist/cjs/morph-path.js +649 -0
  12. package/dist/cjs/morph.js +223 -0
  13. package/dist/cjs/package.json +1 -0
  14. package/dist/cjs/registry.js +130 -0
  15. package/dist/cjs/snapshot.js +420 -0
  16. package/dist/cjs/twin.js +88 -0
  17. package/dist/cjs/types.js +2 -0
  18. package/dist/cjs/util.js +50 -0
  19. package/dist/cjs/webgl.js +271 -0
  20. package/dist/esm/2d.js +454 -0
  21. package/dist/esm/3d.js +538 -0
  22. package/dist/esm/geometry.js +127 -0
  23. package/dist/esm/index.js +6 -0
  24. package/dist/esm/morph-audit.js +558 -0
  25. package/dist/esm/morph-match.js +97 -0
  26. package/dist/esm/morph-path.js +636 -0
  27. package/dist/esm/morph.js +219 -0
  28. package/dist/esm/registry.js +91 -0
  29. package/dist/esm/snapshot.js +414 -0
  30. package/dist/esm/twin.js +84 -0
  31. package/dist/esm/types.js +1 -0
  32. package/dist/esm/util.js +43 -0
  33. package/dist/esm/webgl.js +231 -0
  34. package/dist/types/2d.d.ts +40 -0
  35. package/dist/types/3d.d.ts +38 -0
  36. package/dist/types/geometry.d.ts +38 -0
  37. package/dist/types/index.d.ts +7 -0
  38. package/dist/types/morph-audit.d.ts +127 -0
  39. package/dist/types/morph-match.d.ts +28 -0
  40. package/dist/types/morph-path.d.ts +37 -0
  41. package/dist/types/morph.d.ts +2 -0
  42. package/dist/types/registry.d.ts +6 -0
  43. package/dist/types/snapshot.d.ts +19 -0
  44. package/dist/types/twin.d.ts +2 -0
  45. package/dist/types/types.d.ts +13 -0
  46. package/dist/types/util.d.ts +12 -0
  47. package/dist/types/webgl.d.ts +5 -0
  48. package/package.json +36 -4
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.morphGeometryHash = morphGeometryHash;
4
+ exports.morphSimilarity = morphSimilarity;
5
+ exports.morphMatchReason = morphMatchReason;
6
+ exports.matchMorphShapePairs = matchMorphShapePairs;
7
+ const morph_path_1 = require("./morph-path");
8
+ function morphGeometryHash(c) {
9
+ const aspect = c.rect.height > 0 ? c.rect.width / c.rect.height : 1;
10
+ const area = Math.round(Math.log2(c.rect.width * c.rect.height + 1));
11
+ const pathSig = c.pathD ? (0, morph_path_1.morphPathSignature)(c.pathD) : "0";
12
+ return `${c.tag}|${aspect.toFixed(1)}|${area}|${pathSig}`;
13
+ }
14
+ function pathScore(a, b) {
15
+ const sa = (0, morph_path_1.morphPathSignature)(a);
16
+ const sb = (0, morph_path_1.morphPathSignature)(b);
17
+ if (sa === sb)
18
+ return 1;
19
+ const m = Math.min(sa.length, sb.length);
20
+ let same = 0;
21
+ for (let i = 0; i < m; i++)
22
+ if (sa[i] === sb[i])
23
+ same++;
24
+ return same / Math.max(1, Math.max(sa.length, sb.length));
25
+ }
26
+ function morphSimilarity(a, b) {
27
+ const w1 = a.rect.width || 1;
28
+ const h1 = a.rect.height || 1;
29
+ const w2 = b.rect.width || 1;
30
+ const h2 = b.rect.height || 1;
31
+ const ar1 = w1 / h1;
32
+ const ar2 = w2 / h2;
33
+ const arDiff = Math.abs(ar1 - ar2) / Math.max(ar1, ar2);
34
+ const sizeDiff = Math.abs(Math.log2(w1 * h1 + 1) - Math.log2(w2 * h2 + 1)) / 4;
35
+ let score = 1 - arDiff * 0.5 - sizeDiff * 0.3;
36
+ if (a.pathD && b.pathD) {
37
+ const ps = (0, morph_path_1.morphPathSignature)(a.pathD) === (0, morph_path_1.morphPathSignature)(b.pathD) ? 1 : pathScore(a.pathD, b.pathD);
38
+ score = score * 0.6 + ps * 0.4;
39
+ }
40
+ return Math.max(0, score);
41
+ }
42
+ // cNvPr ids are only unique within one slide, so `sp_2` on two slides is usually two
43
+ // unrelated shapes; PowerPoint pairs by name. The id tier only covers shapes that carry no name.
44
+ const EXACT_TIERS = [
45
+ { reason: "name", same: (s, g) => !!s.name && g.name === s.name },
46
+ { reason: "id", same: (s, g) => !s.name && !g.name && g.id === s.id },
47
+ { reason: "placeholder", same: (s, g) => !!s.placeholderType && g.placeholderType === s.placeholderType },
48
+ ];
49
+ /** How a morph pair was matched (mirrors `matchMorphShapePairs` priority). */
50
+ function morphMatchReason(ghost, stage) {
51
+ return EXACT_TIERS.find((t) => t.same(stage, ghost))?.reason ?? "geometry";
52
+ }
53
+ // 1 = same top-left, → 0 as the offset grows relative to the larger of the two boxes.
54
+ function morphPositionScore(a, b) {
55
+ const d = Math.hypot(a.left - b.left, a.top - b.top);
56
+ const scale = Math.max(a.width, a.height, b.width, b.height, 1);
57
+ return 1 / (1 + d / scale);
58
+ }
59
+ /**
60
+ * name/id/placeholder/geometry matching for morph FLIP (testable without DOM).
61
+ * Each tier is resolved for every shape before the next one, and geometry pairs are assigned
62
+ * best-score-first: a stage-order greedy pass lets an early shape take the ghost that an
63
+ * unchanged later shape (same kicker, same folio) matches exactly.
64
+ */
65
+ function matchMorphShapePairs(ghost, stage) {
66
+ const usedGhost = new Set();
67
+ const matched = new Map();
68
+ for (const { same } of EXACT_TIERS) {
69
+ for (const s of stage) {
70
+ if (matched.has(s))
71
+ continue;
72
+ const g = ghost.find((c) => !usedGhost.has(c.id) && same(s, c));
73
+ if (!g)
74
+ continue;
75
+ usedGhost.add(g.id);
76
+ matched.set(s, g);
77
+ }
78
+ }
79
+ const scored = [];
80
+ for (const s of stage) {
81
+ if (matched.has(s))
82
+ continue;
83
+ for (const g of ghost) {
84
+ if (usedGhost.has(g.id) || g.tag !== s.tag)
85
+ continue;
86
+ const shape = morphSimilarity(s, g);
87
+ if (shape <= 0.45)
88
+ continue;
89
+ scored.push({ s, g, score: shape * 0.7 + morphPositionScore(s.rect, g.rect) * 0.3 });
90
+ }
91
+ }
92
+ scored.sort((a, b) => b.score - a.score);
93
+ for (const { s, g } of scored) {
94
+ if (matched.has(s) || usedGhost.has(g.id))
95
+ continue;
96
+ usedGhost.add(g.id);
97
+ matched.set(s, g);
98
+ }
99
+ return stage.flatMap((s) => {
100
+ const g = matched.get(s);
101
+ return g ? [{ ghost: g, stage: s }] : [];
102
+ });
103
+ }