@humanspeak/svelte-motion 0.5.3 → 0.6.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.
package/dist/utils/svg.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { buildSVGPath } from 'motion-dom';
1
2
  /**
2
3
  * SVG-specific properties that need special handling during animation.
3
4
  * These properties are not standard CSS properties and need to be transformed.
@@ -145,8 +146,8 @@ export const isSVGElement = (element) => {
145
146
  *
146
147
  * Normalized behavior (React/Framer Motion parity):
147
148
  * - Ensures `pathLength="1"` is set when any path prop is present
148
- * - Maps `pathLength`/`pathSpacing` → `stroke-dasharray` (px)
149
- * - Maps `pathOffset` → `stroke-dashoffset` (negative px)
149
+ * - Maps `pathLength`/`pathSpacing` → unitless `stroke-dasharray`
150
+ * - Maps `pathOffset` → unitless negative `stroke-dashoffset`
150
151
  *
151
152
  * @param {Element} element The element being animated (must be an SVG path).
152
153
  * @param {Record<string, unknown>} keyframes The input keyframes possibly containing path props.
@@ -189,46 +190,65 @@ export const transformSVGPathProperties = (element, keyframes) => {
189
190
  const n = toNum(v);
190
191
  return n ?? v;
191
192
  })();
192
- const toPx = (v) => (typeof v === 'number' ? `${v}px` : String(v));
193
- const buildDashArray = (len, spa) => `${toPx(len)} ${toPx(spa)}`;
194
- // stroke-dasharray from pathLength/pathSpacing with default spacing = 1 - length
193
+ const toUnitless = (v) => (typeof v === 'number' ? `${v}` : String(v));
194
+ const buildDashArray = (len, spa) => `${toUnitless(len)} ${toUnitless(spa)}`;
195
+ // stroke-dasharray from pathLength/pathSpacing with upstream's default spacing = 1
195
196
  if (Array.isArray(length)) {
196
197
  const lenArr = length;
197
198
  const spaArr = Array.isArray(spacing)
198
199
  ? spacing
199
- : lenArr.map((lv) => typeof lv === 'number' ? 1 - lv : spacing);
200
+ : lenArr.map(() => (spacing !== undefined ? spacing : 1));
200
201
  const dashArray = lenArr.map((lv, i) => buildDashArray(lv, spaArr[i]));
201
202
  transformed.strokeDasharray = dashArray;
202
203
  transformed['stroke-dasharray'] = dashArray;
203
204
  }
204
205
  else if (length !== undefined) {
205
- const len = length;
206
- const lenNum = toNum(len) ?? 0;
207
- const spa = spacing !== undefined ? spacing : 1 - lenNum;
208
- const dashArray = buildDashArray(len, spa);
206
+ const lenNum = toNum(length);
207
+ const spaNum = spacing === undefined ? undefined : toNum(spacing);
208
+ const offsetNum = offset === undefined ? undefined : toNum(offset);
209
+ let dashArray;
210
+ let dashOffset;
211
+ if (lenNum !== undefined &&
212
+ (spacing === undefined || spaNum !== undefined) &&
213
+ (offset === undefined || offsetNum !== undefined)) {
214
+ const attrs = {};
215
+ buildSVGPath(attrs, lenNum, spacing === undefined ? 1 : spaNum, offsetNum, true);
216
+ dashArray = String(attrs['stroke-dasharray']);
217
+ dashOffset = String(attrs['stroke-dashoffset']);
218
+ }
219
+ else {
220
+ const spa = spacing !== undefined ? spacing : 1;
221
+ dashArray = buildDashArray(length, spa);
222
+ }
223
+ ;
209
224
  transformed.strokeDasharray = dashArray;
210
225
  transformed['stroke-dasharray'] = dashArray;
226
+ if (dashOffset !== undefined) {
227
+ ;
228
+ transformed.strokeDashoffset = dashOffset;
229
+ transformed['stroke-dashoffset'] = dashOffset;
230
+ }
211
231
  }
212
232
  // stroke-dashoffset from -pathOffset
213
233
  if (Array.isArray(offset)) {
214
234
  const offs = offset.map((ov) => {
215
235
  const n = toNum(ov);
216
- return n !== undefined ? `${-n}px` : String(ov);
236
+ return n !== undefined ? `${-n}` : String(ov);
217
237
  });
218
238
  transformed.strokeDashoffset = offs;
219
239
  transformed['stroke-dashoffset'] = offs;
220
240
  }
221
241
  else if (offset !== undefined) {
222
242
  const n = toNum(offset);
223
- const off = n !== undefined ? `${-n}px` : String(offset);
243
+ const off = n !== undefined ? `${-n}` : String(offset);
224
244
  transformed.strokeDashoffset = off;
225
245
  transformed['stroke-dashoffset'] = off;
226
246
  }
227
- else {
247
+ else if (!('stroke-dashoffset' in transformed)) {
228
248
  // default 0
229
249
  ;
230
- transformed.strokeDashoffset = '0px';
231
- transformed['stroke-dashoffset'] = '0px';
250
+ transformed.strokeDashoffset = '0';
251
+ transformed['stroke-dashoffset'] = '0';
232
252
  }
233
253
  delete transformed.pathLength;
234
254
  delete transformed.pathSpacing;
@@ -273,8 +293,8 @@ export const transformInitialSVGPathProperties = (element, initial) => {
273
293
  *
274
294
  * Behavior matches React/Framer Motion parity:
275
295
  * - Always sets pathLength="1" whenever any of path props are present
276
- * - stroke-dasharray = px(pathLength) + ' ' + px(pathSpacing ?? 1 - Number(pathLength))
277
- * - stroke-dashoffset = px(-(pathOffset ?? 0))
296
+ * - stroke-dasharray = pathLength + ' ' + (pathSpacing ?? 1)
297
+ * - stroke-dashoffset = -(pathOffset ?? 0)
278
298
  *
279
299
  * The returned object is suitable for direct DOM attribute assignment (dash-cased keys).
280
300
  *
@@ -287,19 +307,18 @@ export const computeNormalizedSVGInitialAttrs = (initial) => {
287
307
  const hasAny = 'pathLength' in initial || 'pathSpacing' in initial || 'pathOffset' in initial;
288
308
  if (!hasAny)
289
309
  return null;
290
- const toPx = (v) => (typeof v === 'number' ? `${v}px` : String(v));
291
- const negatePx = (v) => {
310
+ const toUnitless = (v) => (typeof v === 'number' ? `${v}` : String(v));
311
+ const negate = (v) => {
292
312
  if (typeof v === 'number')
293
- return `${-v}px`;
313
+ return `${-v}`;
294
314
  const s = String(v);
295
- return s.startsWith('-') ? s : /^[\d.]+(px)?$/i.test(s) ? `-${s}` : s;
315
+ return s.startsWith('-') ? s : /^[\d.]+(px)?$/i.test(s) ? `-${s.replace(/px$/i, '')}` : s;
296
316
  };
297
317
  const len = initial.pathLength ?? 0;
298
- const spa = initial.pathSpacing ??
299
- (typeof len === 'number' ? 1 - len : 1);
318
+ const spa = initial.pathSpacing ?? 1;
300
319
  const off = initial.pathOffset ?? 0;
301
- const dashArray = `${toPx(len)} ${toPx(spa)}`;
302
- const dashOffset = negatePx(off);
320
+ const dashArray = `${toUnitless(len)} ${toUnitless(spa)}`;
321
+ const dashOffset = negate(off);
303
322
  // logging removed
304
323
  return {
305
324
  pathLength: '1',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@humanspeak/svelte-motion",
3
- "version": "0.5.3",
3
+ "version": "0.6.0",
4
4
  "description": "Framer Motion for Svelte 5. Declarative motion.<tag> components with AnimatePresence exit animations, gestures (hover, tap, drag, focus, in-view), variants, FLIP layout animations, shared-layout transitions, spring physics, and scroll-linked motion values. The drop-in Framer Motion alternative for Svelte and SvelteKit.",
5
5
  "keywords": [
6
6
  "svelte",