@pixodesk/svg-animator-core 1.0.27 → 1.0.29

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/index.cjs CHANGED
@@ -56,6 +56,7 @@ __export(index_exports, {
56
56
  DISALLOWED_SVG_TAGS_LOWER: () => DISALLOWED_SVG_TAGS_LOWER,
57
57
  INTERNAL_ATTRS: () => INTERNAL_ATTRS,
58
58
  LOOP_JUMP_SHIFT_MS: () => LOOP_JUMP_SHIFT_MS,
59
+ MISSING_GLYPH_CLASS_NAME: () => MISSING_GLYPH_CLASS_NAME,
59
60
  PCT_BASED_ATTR_NAMES: () => PCT_BASED_ATTR_NAMES,
60
61
  PX_ANIM_ATTR_NAME: () => PX_ANIM_ATTR_NAME,
61
62
  PX_ANIM_SRC_ATTR_NAME: () => PX_ANIM_SRC_ATTR_NAME,
@@ -1318,6 +1319,13 @@ var PxScrollSchema = implementsInterface()(px.object({
1318
1319
  kind: px.enum(["view", "scroll"]).optional(),
1319
1320
  axis: px.enum(["block", "inline", "x", "y"]).optional(),
1320
1321
  source: px.enum(["nearest", "root"]).optional(),
1322
+ // Free-form: the two keywords `parent`/`scroller` plus any CSS selector.
1323
+ subject: px.string().optional(),
1324
+ smoothing: px.number().optional(),
1325
+ pin: px.boolean().optional(),
1326
+ pinAlign: px.enum(["top", "center", "bottom"]).optional(),
1327
+ pinTop: px.number().optional(),
1328
+ pinDistance: px.number().optional(),
1321
1329
  range: PxScrollRangeSchema.optional()
1322
1330
  }));
1323
1331
  var PxAnimatorConfigSchema = implementsInterface()(px.object({
@@ -4589,6 +4597,19 @@ var TEXT_ATTR_KEYS = [
4589
4597
  TEXT_CONTENT_ATTR,
4590
4598
  "xml:space"
4591
4599
  ];
4600
+ var PAINT_STATIC_KEYS = [
4601
+ "fillOpacity",
4602
+ "fillRule",
4603
+ "strokeOpacity",
4604
+ "strokeDasharray",
4605
+ "strokeDashoffset",
4606
+ "strokeLinecap",
4607
+ "strokeLinejoin",
4608
+ "strokeMiterlimit",
4609
+ "mixBlendMode",
4610
+ "filter"
4611
+ ];
4612
+ var PAINT_ANIMATE_KEYS = ["fill", "stroke", "strokeWidth", "opacity", "fillOpacity", "strokeOpacity", "strokeDasharray", "strokeDashoffset"];
4592
4613
  function parseLen(v) {
4593
4614
  if (typeof v === "number") return v;
4594
4615
  if (typeof v === "string") {
@@ -4600,17 +4621,39 @@ function parseLen(v) {
4600
4621
  function str(v) {
4601
4622
  return typeof v === "string" ? v : void 0;
4602
4623
  }
4624
+ function paintAnimateOf(node) {
4625
+ const bag = node.animate;
4626
+ if (!bag || typeof bag !== "object") return void 0;
4627
+ let out;
4628
+ for (const k of PAINT_ANIMATE_KEYS) {
4629
+ if (bag[k] !== void 0) (out != null ? out : out = {})[k] = bag[k];
4630
+ }
4631
+ return out;
4632
+ }
4603
4633
  function resolveStyle2(node, parent) {
4604
- var _a, _b, _c, _d, _e, _f, _g;
4605
- return {
4634
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
4635
+ const isTextRoot = node.type === "text";
4636
+ const nodeStyle = node.style;
4637
+ const own = (key) => {
4638
+ var _a2;
4639
+ return isTextRoot ? void 0 : (_a2 = node[key]) != null ? _a2 : nodeStyle == null ? void 0 : nodeStyle[key];
4640
+ };
4641
+ const res = {
4606
4642
  fontFamily: (_a = str(node.fontFamily)) != null ? _a : parent.fontFamily,
4607
4643
  fontSize: (_b = parseLen(node.fontSize)) != null ? _b : parent.fontSize,
4608
4644
  fill: (_c = node.fill) != null ? _c : parent.fill,
4609
4645
  stroke: (_d = node.stroke) != null ? _d : parent.stroke,
4610
4646
  strokeWidth: (_e = node.strokeWidth) != null ? _e : parent.strokeWidth,
4611
4647
  letterSpacing: (_f = parseLen(node.letterSpacing)) != null ? _f : parent.letterSpacing,
4612
- wordSpacing: (_g = parseLen(node.wordSpacing)) != null ? _g : parent.wordSpacing
4648
+ wordSpacing: (_g = parseLen(node.wordSpacing)) != null ? _g : parent.wordSpacing,
4649
+ opacity: (_h = parseLen(own("opacity"))) != null ? _h : parent.opacity,
4650
+ animate: (_i = isTextRoot ? void 0 : paintAnimateOf(node)) != null ? _i : parent.animate
4613
4651
  };
4652
+ for (const key of PAINT_STATIC_KEYS) {
4653
+ const v = (_j = own(key)) != null ? _j : parent[key];
4654
+ if (v !== void 0) res[key] = v;
4655
+ }
4656
+ return res;
4614
4657
  }
4615
4658
  function rootStyleOf(node) {
4616
4659
  var _a, _b, _c;
@@ -4629,6 +4672,11 @@ function paintOf(s) {
4629
4672
  if (s.fill !== void 0) p.fill = s.fill;
4630
4673
  if (s.stroke !== void 0) p.stroke = s.stroke;
4631
4674
  if (s.strokeWidth !== void 0) p.strokeWidth = s.strokeWidth;
4675
+ if (s.opacity !== void 0 && s.opacity !== 1) p.opacity = s.opacity;
4676
+ for (const key of PAINT_STATIC_KEYS) {
4677
+ if (s[key] !== void 0) p[key] = s[key];
4678
+ }
4679
+ if (s.animate !== void 0) p.animate = s.animate;
4632
4680
  return p;
4633
4681
  }
4634
4682
  function glyphFontFor(s, glyphs, soleFont, warnings) {
@@ -4642,6 +4690,7 @@ function soleFontOf(glyphs) {
4642
4690
  return names.length === 1 ? glyphs[names[0]] : void 0;
4643
4691
  }
4644
4692
  var MISSING_GLYPH_ADVANCE_EM = 0.6;
4693
+ var MISSING_GLYPH_CLASS_NAME = "px-missing-glyph";
4645
4694
  function missingGlyphBoxEm(advanceEm, ascentEm) {
4646
4695
  if (advanceEm <= 0 || ascentEm <= 0) return "";
4647
4696
  const inset = 0.08;
@@ -4677,7 +4726,7 @@ function materialiseGlyphTextHorizontal(node, opts) {
4677
4726
  pen.x += g.width * scale;
4678
4727
  } else if (/\S/.test(ch)) {
4679
4728
  const advEm = g && g.width > 0 ? g.width : MISSING_GLYPH_ADVANCE_EM * upm;
4680
- placements.push({ glyphD: missingGlyphBoxEm(advEm, ascentEm), m: [scale, 0, 0, scale, pen.x, pen.y], paint, line, x: pen.x, y: pen.y, scale });
4729
+ placements.push({ glyphD: missingGlyphBoxEm(advEm, ascentEm), m: [scale, 0, 0, scale, pen.x, pen.y], paint, isMissing: true, line, x: pen.x, y: pen.y, scale });
4681
4730
  pen.x += advEm * scale;
4682
4731
  } else {
4683
4732
  pen.x += (g ? g.width : 0) * scale;
@@ -4868,7 +4917,7 @@ function collectAlongPathCells(node, glyphs, soleFont, warnings) {
4868
4917
  } else if (/\S/.test(ch)) {
4869
4918
  const wEm = g && g.width > 0 ? g.width : MISSING_GLYPH_ADVANCE_EM * gf.unitsPerEm;
4870
4919
  const boxAdv = wEm * scale;
4871
- cells.push({ glyphD: missingGlyphBoxEm(wEm, ascentEm), widthEm: wEm, scale, paint, midBase: adv + boxAdv / 2 });
4920
+ cells.push({ glyphD: missingGlyphBoxEm(wEm, ascentEm), widthEm: wEm, scale, paint, isMissing: true, midBase: adv + boxAdv / 2 });
4872
4921
  adv += boxAdv;
4873
4922
  } else {
4874
4923
  adv += (g ? g.width : 0) * scale;
@@ -4924,6 +4973,7 @@ function materialiseGlyphTextAlongPath(node, pathD, startOffset, opts, textLengt
4924
4973
  const placements = placeCells.map((c) => ({
4925
4974
  glyphD: c.glyphD,
4926
4975
  paint: c.paint,
4976
+ isMissing: c.isMissing,
4927
4977
  m: alongAffine(sampler, base + c.midBase * k, c.scale, c.widthEm, perp)
4928
4978
  }));
4929
4979
  return toGroup(node, buildPaths(placements, create, warnings), create);
@@ -5006,12 +5056,13 @@ function buildAnimatedAlongPath(cells, sampler, distOf, times, loop, create, isC
5006
5056
  const transform = { keyframes: kfs };
5007
5057
  if (loop !== void 0) transform.loop = loop;
5008
5058
  const animate = { transform };
5059
+ if (c.paint.animate) Object.assign(animate, c.paint.animate);
5009
5060
  if (isClip && opKfs.some((k) => k.value === 0)) {
5010
5061
  const op = { keyframes: opKfs };
5011
5062
  if (loop !== void 0) op.loop = loop;
5012
5063
  animate.opacity = op;
5013
5064
  }
5014
- out.push(create("path", __spreadProps(__spreadValues({ d }, paintProps(c.paint)), { animate }), []));
5065
+ out.push(create("path", __spreadProps(__spreadValues(__spreadValues({ d }, paintProps(c.paint)), missingGlyphProps(c.isMissing)), { animate }), []));
5015
5066
  }
5016
5067
  return out;
5017
5068
  }
@@ -5020,24 +5071,34 @@ function paintProps(paint) {
5020
5071
  if (paint.fill !== void 0) p.fill = paint.fill;
5021
5072
  if (paint.stroke !== void 0) p.stroke = paint.stroke;
5022
5073
  if (paint.strokeWidth !== void 0) p.strokeWidth = paint.strokeWidth;
5074
+ if (paint.opacity !== void 0) p.opacity = paint.opacity;
5075
+ for (const key of PAINT_STATIC_KEYS) {
5076
+ if (paint[key] !== void 0) p[key] = paint[key];
5077
+ }
5023
5078
  return p;
5024
5079
  }
5080
+ function missingGlyphProps(isMissing) {
5081
+ return isMissing ? { class: MISSING_GLYPH_CLASS_NAME } : {};
5082
+ }
5025
5083
  function buildPaths(placements, create, warnings) {
5026
- var _a, _b, _c;
5027
5084
  if (!placements.length) {
5028
5085
  warnings == null ? void 0 : warnings.push("textGlyphs: nothing to render");
5029
5086
  return [];
5030
5087
  }
5031
5088
  const byPaint = /* @__PURE__ */ new Map();
5032
5089
  for (const p of placements) {
5033
- const key = JSON.stringify([(_a = p.paint.fill) != null ? _a : null, (_b = p.paint.stroke) != null ? _b : null, (_c = p.paint.strokeWidth) != null ? _c : null]);
5090
+ const key = JSON.stringify([p.paint, !!p.isMissing]);
5034
5091
  const baked = transformPathData(p.glyphD, p.m);
5035
5092
  const entry = byPaint.get(key);
5036
5093
  if (entry) entry.d += baked;
5037
- else byPaint.set(key, { paint: p.paint, d: baked });
5094
+ else byPaint.set(key, { paint: p.paint, d: baked, isMissing: p.isMissing });
5038
5095
  }
5039
5096
  const out = [];
5040
- for (const { paint, d } of byPaint.values()) out.push(create("path", __spreadValues({ d }, paintProps(paint)), []));
5097
+ for (const { paint, d, isMissing } of byPaint.values()) {
5098
+ out.push(create("path", __spreadValues(__spreadValues(__spreadValues({
5099
+ d
5100
+ }, paintProps(paint)), missingGlyphProps(isMissing)), paint.animate !== void 0 ? { animate: __spreadValues({}, paint.animate) } : {}), []));
5101
+ }
5041
5102
  return out;
5042
5103
  }
5043
5104
  function toGroup(node, children, create) {
@@ -6149,6 +6210,7 @@ function subtractMultiset(a, b) {
6149
6210
  DISALLOWED_SVG_TAGS_LOWER,
6150
6211
  INTERNAL_ATTRS,
6151
6212
  LOOP_JUMP_SHIFT_MS,
6213
+ MISSING_GLYPH_CLASS_NAME,
6152
6214
  PCT_BASED_ATTR_NAMES,
6153
6215
  PX_ANIM_ATTR_NAME,
6154
6216
  PX_ANIM_SRC_ATTR_NAME,