motion 12.13.0 → 12.15.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/cjs/index.js CHANGED
@@ -3347,6 +3347,152 @@ const acceleratedValues = new Set([
3347
3347
  // "background-color"
3348
3348
  ]);
3349
3349
 
3350
+ function camelToDash$1(str) {
3351
+ return str.replace(/([A-Z])/g, (match) => `-${match.toLowerCase()}`);
3352
+ }
3353
+
3354
+ function resolveElements(elementOrSelector, scope, selectorCache) {
3355
+ if (elementOrSelector instanceof EventTarget) {
3356
+ return [elementOrSelector];
3357
+ }
3358
+ else if (typeof elementOrSelector === "string") {
3359
+ let root = document;
3360
+ if (scope) {
3361
+ root = scope.current;
3362
+ }
3363
+ const elements = selectorCache?.[elementOrSelector] ??
3364
+ root.querySelectorAll(elementOrSelector);
3365
+ return elements ? Array.from(elements) : [];
3366
+ }
3367
+ return Array.from(elementOrSelector);
3368
+ }
3369
+
3370
+ function createSelectorEffect(subjectEffect) {
3371
+ return (subject, values) => {
3372
+ const elements = resolveElements(subject);
3373
+ const subscriptions = [];
3374
+ for (const element of elements) {
3375
+ const remove = subjectEffect(element, values);
3376
+ subscriptions.push(remove);
3377
+ }
3378
+ return () => {
3379
+ for (const remove of subscriptions)
3380
+ remove();
3381
+ };
3382
+ };
3383
+ }
3384
+
3385
+ /**
3386
+ * Provided a value and a ValueType, returns the value as that value type.
3387
+ */
3388
+ const getValueAsType = (value, type) => {
3389
+ return type && typeof value === "number"
3390
+ ? type.transform(value)
3391
+ : value;
3392
+ };
3393
+
3394
+ class MotionValueState {
3395
+ constructor() {
3396
+ this.latest = {};
3397
+ this.values = new Map();
3398
+ }
3399
+ set(name, value, render, computed, useDefaultValueType = true) {
3400
+ const existingValue = this.values.get(name);
3401
+ if (existingValue) {
3402
+ existingValue.onRemove();
3403
+ }
3404
+ const onChange = () => {
3405
+ const v = value.get();
3406
+ if (useDefaultValueType) {
3407
+ this.latest[name] = getValueAsType(v, numberValueTypes[name]);
3408
+ }
3409
+ else {
3410
+ this.latest[name] = v;
3411
+ }
3412
+ render && frame.render(render);
3413
+ };
3414
+ onChange();
3415
+ const cancelOnChange = value.on("change", onChange);
3416
+ computed && value.addDependent(computed);
3417
+ const remove = () => {
3418
+ cancelOnChange();
3419
+ render && cancelFrame(render);
3420
+ this.values.delete(name);
3421
+ computed && value.removeDependent(computed);
3422
+ };
3423
+ this.values.set(name, { value, onRemove: remove });
3424
+ return remove;
3425
+ }
3426
+ get(name) {
3427
+ return this.values.get(name)?.value;
3428
+ }
3429
+ destroy() {
3430
+ for (const value of this.values.values()) {
3431
+ value.onRemove();
3432
+ }
3433
+ }
3434
+ }
3435
+
3436
+ function createEffect(addValue) {
3437
+ const stateCache = new WeakMap();
3438
+ const subscriptions = [];
3439
+ return (subject, values) => {
3440
+ const state = stateCache.get(subject) ?? new MotionValueState();
3441
+ stateCache.set(subject, state);
3442
+ for (const key in values) {
3443
+ const value = values[key];
3444
+ const remove = addValue(subject, state, key, value);
3445
+ subscriptions.push(remove);
3446
+ }
3447
+ return () => {
3448
+ for (const cancel of subscriptions)
3449
+ cancel();
3450
+ };
3451
+ };
3452
+ }
3453
+
3454
+ function canSetAsProperty(element, name) {
3455
+ if (!(name in element))
3456
+ return false;
3457
+ const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(element), name) ||
3458
+ Object.getOwnPropertyDescriptor(element, name);
3459
+ // Check if it has a setter
3460
+ return descriptor && typeof descriptor.set === "function";
3461
+ }
3462
+ const addAttrValue = (element, state, key, value) => {
3463
+ const isProp = canSetAsProperty(element, key);
3464
+ const name = isProp
3465
+ ? key
3466
+ : key.startsWith("data") || key.startsWith("aria")
3467
+ ? camelToDash$1(key)
3468
+ : key;
3469
+ /**
3470
+ * Set attribute directly via property if available
3471
+ */
3472
+ const render = isProp
3473
+ ? () => {
3474
+ element[name] = state.latest[key];
3475
+ }
3476
+ : () => {
3477
+ const v = state.latest[key];
3478
+ if (v === null || v === undefined) {
3479
+ element.removeAttribute(name);
3480
+ }
3481
+ else {
3482
+ element.setAttribute(name, String(v));
3483
+ }
3484
+ };
3485
+ return state.set(key, value, render);
3486
+ };
3487
+ const attrEffect = /*@__PURE__*/ createSelectorEffect(
3488
+ /*@__PURE__*/ createEffect(addAttrValue));
3489
+
3490
+ const propEffect = /*@__PURE__*/ createEffect((subject, state, key, value) => {
3491
+ return state.set(key, value, () => {
3492
+ subject[key] = state.latest[key];
3493
+ }, undefined, false);
3494
+ });
3495
+
3350
3496
  /**
3351
3497
  * Maximum time between the value of two frames, beyond which we
3352
3498
  * assume the velocity has since been 0.
@@ -3669,106 +3815,6 @@ function motionValue(init, options) {
3669
3815
  return new MotionValue(init, options);
3670
3816
  }
3671
3817
 
3672
- function resolveElements(elementOrSelector, scope, selectorCache) {
3673
- if (elementOrSelector instanceof EventTarget) {
3674
- return [elementOrSelector];
3675
- }
3676
- else if (typeof elementOrSelector === "string") {
3677
- let root = document;
3678
- if (scope) {
3679
- root = scope.current;
3680
- }
3681
- const elements = selectorCache?.[elementOrSelector] ??
3682
- root.querySelectorAll(elementOrSelector);
3683
- return elements ? Array.from(elements) : [];
3684
- }
3685
- return Array.from(elementOrSelector);
3686
- }
3687
-
3688
- function createSelectorEffect(subjectEffect) {
3689
- return (subject, values) => {
3690
- const elements = resolveElements(subject);
3691
- const subscriptions = [];
3692
- for (const element of elements) {
3693
- const remove = subjectEffect(element, values);
3694
- subscriptions.push(remove);
3695
- }
3696
- return () => {
3697
- for (const remove of subscriptions)
3698
- remove();
3699
- };
3700
- };
3701
- }
3702
-
3703
- /**
3704
- * Provided a value and a ValueType, returns the value as that value type.
3705
- */
3706
- const getValueAsType = (value, type) => {
3707
- return type && typeof value === "number"
3708
- ? type.transform(value)
3709
- : value;
3710
- };
3711
-
3712
- class MotionValueState {
3713
- constructor() {
3714
- this.latest = {};
3715
- this.values = new Map();
3716
- }
3717
- set(name, value, render, computed, useDefaultValueType = true) {
3718
- const existingValue = this.values.get(name);
3719
- if (existingValue) {
3720
- existingValue.onRemove();
3721
- }
3722
- const onChange = () => {
3723
- const v = value.get();
3724
- if (useDefaultValueType) {
3725
- this.latest[name] = getValueAsType(v, numberValueTypes[name]);
3726
- }
3727
- else {
3728
- this.latest[name] = v;
3729
- }
3730
- render && frame.render(render);
3731
- };
3732
- onChange();
3733
- const cancelOnChange = value.on("change", onChange);
3734
- computed && value.addDependent(computed);
3735
- const remove = () => {
3736
- cancelOnChange();
3737
- render && cancelFrame(render);
3738
- this.values.delete(name);
3739
- computed && value.removeDependent(computed);
3740
- };
3741
- this.values.set(name, { value, onRemove: remove });
3742
- return remove;
3743
- }
3744
- get(name) {
3745
- return this.values.get(name)?.value;
3746
- }
3747
- destroy() {
3748
- for (const value of this.values.values()) {
3749
- value.onRemove();
3750
- }
3751
- }
3752
- }
3753
-
3754
- function createEffect(addValue) {
3755
- const stateCache = new WeakMap();
3756
- const subscriptions = [];
3757
- return (subject, values) => {
3758
- const state = stateCache.get(subject) ?? new MotionValueState();
3759
- stateCache.set(subject, state);
3760
- for (const key in values) {
3761
- const value = values[key];
3762
- const remove = addValue(subject, state, key, value);
3763
- subscriptions.push(remove);
3764
- }
3765
- return () => {
3766
- for (const cancel of subscriptions)
3767
- cancel();
3768
- };
3769
- };
3770
- }
3771
-
3772
3818
  const translateAlias$1 = {
3773
3819
  x: "translateX",
3774
3820
  y: "translateY",
@@ -3804,17 +3850,34 @@ function buildTransform$1(state) {
3804
3850
  return transformIsDefault ? "none" : transform.trim();
3805
3851
  }
3806
3852
 
3853
+ const originProps = new Set(["originX", "originY", "originZ"]);
3807
3854
  const addStyleValue = (element, state, key, value) => {
3808
3855
  let render = undefined;
3809
3856
  let computed = undefined;
3810
3857
  if (transformProps.has(key)) {
3811
3858
  if (!state.get("transform")) {
3859
+ // If this is an HTML element, we need to set the transform-box to fill-box
3860
+ // to normalise the transform relative to the element's bounding box
3861
+ if (!isHTMLElement(element) && !state.get("transformBox")) {
3862
+ addStyleValue(element, state, "transformBox", new MotionValue("fill-box"));
3863
+ }
3812
3864
  state.set("transform", new MotionValue("none"), () => {
3813
3865
  element.style.transform = buildTransform$1(state);
3814
3866
  });
3815
3867
  }
3816
3868
  computed = state.get("transform");
3817
3869
  }
3870
+ else if (originProps.has(key)) {
3871
+ if (!state.get("transformOrigin")) {
3872
+ state.set("transformOrigin", new MotionValue(""), () => {
3873
+ const originX = state.latest.originX ?? "50%";
3874
+ const originY = state.latest.originY ?? "50%";
3875
+ const originZ = state.latest.originZ ?? 0;
3876
+ element.style.transformOrigin = `${originX} ${originY} ${originZ}`;
3877
+ });
3878
+ }
3879
+ computed = state.get("transformOrigin");
3880
+ }
3818
3881
  else if (isCSSVar(key)) {
3819
3882
  render = () => {
3820
3883
  element.style.setProperty(key, state.latest[key]);
@@ -3827,7 +3890,40 @@ const addStyleValue = (element, state, key, value) => {
3827
3890
  }
3828
3891
  return state.set(key, value, render, computed);
3829
3892
  };
3830
- const styleEffect = createSelectorEffect(createEffect(addStyleValue));
3893
+ const styleEffect = /*@__PURE__*/ createSelectorEffect(
3894
+ /*@__PURE__*/ createEffect(addStyleValue));
3895
+
3896
+ const toPx = px.transform;
3897
+ function addSVGPathValue(element, state, key, value) {
3898
+ frame.render(() => element.setAttribute("pathLength", "1"));
3899
+ if (key === "pathOffset") {
3900
+ return state.set(key, value, () => element.setAttribute("stroke-dashoffset", toPx(-state.latest[key])));
3901
+ }
3902
+ else {
3903
+ if (!state.get("stroke-dasharray")) {
3904
+ state.set("stroke-dasharray", new MotionValue("1 1"), () => {
3905
+ const { pathLength = 1, pathSpacing } = state.latest;
3906
+ element.setAttribute("stroke-dasharray", `${toPx(pathLength)} ${toPx(pathSpacing ?? 1 - Number(pathLength))}`);
3907
+ });
3908
+ }
3909
+ return state.set(key, value, undefined, state.get("stroke-dasharray"));
3910
+ }
3911
+ }
3912
+ const addSVGValue = (element, state, key, value) => {
3913
+ if (key.startsWith("path")) {
3914
+ return addSVGPathValue(element, state, key, value);
3915
+ }
3916
+ else if (key.startsWith("attr")) {
3917
+ return addAttrValue(element, state, convertAttrKey(key), value);
3918
+ }
3919
+ const handler = key in element.style ? addStyleValue : addAttrValue;
3920
+ return handler(element, state, key, value);
3921
+ };
3922
+ const svgEffect = /*@__PURE__*/ createSelectorEffect(
3923
+ /*@__PURE__*/ createEffect(addSVGValue));
3924
+ function convertAttrKey(key) {
3925
+ return key.replace(/^attr([A-Z])/, (_, firstChar) => firstChar.toLowerCase());
3926
+ }
3831
3927
 
3832
3928
  const { schedule: microtask, cancel: cancelMicrotask } =
3833
3929
  /* @__PURE__ */ createRenderBatcher(queueMicrotask, false);
@@ -7276,6 +7372,7 @@ exports.SubscriptionManager = SubscriptionManager;
7276
7372
  exports.ViewTransitionBuilder = ViewTransitionBuilder;
7277
7373
  exports.acceleratedValues = acceleratedValues;
7278
7374
  exports.activeAnimations = activeAnimations;
7375
+ exports.addAttrValue = addAttrValue;
7279
7376
  exports.addStyleValue = addStyleValue;
7280
7377
  exports.addUniqueItem = addUniqueItem;
7281
7378
  exports.alpha = alpha;
@@ -7288,6 +7385,7 @@ exports.animationMapKey = animationMapKey;
7288
7385
  exports.anticipate = anticipate;
7289
7386
  exports.applyPxDefaults = applyPxDefaults;
7290
7387
  exports.attachSpring = attachSpring;
7388
+ exports.attrEffect = attrEffect;
7291
7389
  exports.backIn = backIn;
7292
7390
  exports.backInOut = backInOut;
7293
7391
  exports.backOut = backOut;
@@ -7396,6 +7494,7 @@ exports.positionalKeys = positionalKeys;
7396
7494
  exports.press = press;
7397
7495
  exports.progress = progress;
7398
7496
  exports.progressPercentage = progressPercentage;
7497
+ exports.propEffect = propEffect;
7399
7498
  exports.px = px;
7400
7499
  exports.readTransformValue = readTransformValue;
7401
7500
  exports.recordStats = recordStats;
@@ -7423,6 +7522,7 @@ exports.supportsFlags = supportsFlags;
7423
7522
  exports.supportsLinearEasing = supportsLinearEasing;
7424
7523
  exports.supportsPartialKeyframes = supportsPartialKeyframes;
7425
7524
  exports.supportsScrollTimeline = supportsScrollTimeline;
7525
+ exports.svgEffect = svgEffect;
7426
7526
  exports.sync = sync;
7427
7527
  exports.testValueType = testValueType;
7428
7528
  exports.time = time;
@@ -3168,6 +3168,31 @@ class DOMKeyframesResolver extends KeyframeResolver {
3168
3168
  }
3169
3169
  }
3170
3170
 
3171
+ function resolveElements(elementOrSelector, scope, selectorCache) {
3172
+ if (elementOrSelector instanceof EventTarget) {
3173
+ return [elementOrSelector];
3174
+ }
3175
+ else if (typeof elementOrSelector === "string") {
3176
+ let root = document;
3177
+ if (scope) {
3178
+ root = scope.current;
3179
+ }
3180
+ const elements = selectorCache?.[elementOrSelector] ??
3181
+ root.querySelectorAll(elementOrSelector);
3182
+ return elements ? Array.from(elements) : [];
3183
+ }
3184
+ return Array.from(elementOrSelector);
3185
+ }
3186
+
3187
+ /**
3188
+ * Provided a value and a ValueType, returns the value as that value type.
3189
+ */
3190
+ const getValueAsType = (value, type) => {
3191
+ return type && typeof value === "number"
3192
+ ? type.transform(value)
3193
+ : value;
3194
+ };
3195
+
3171
3196
  /**
3172
3197
  * Maximum time between the value of two frames, beyond which we
3173
3198
  * assume the velocity has since been 0.
@@ -3484,31 +3509,6 @@ function motionValue(init, options) {
3484
3509
  return new MotionValue(init, options);
3485
3510
  }
3486
3511
 
3487
- function resolveElements(elementOrSelector, scope, selectorCache) {
3488
- if (elementOrSelector instanceof EventTarget) {
3489
- return [elementOrSelector];
3490
- }
3491
- else if (typeof elementOrSelector === "string") {
3492
- let root = document;
3493
- if (scope) {
3494
- root = scope.current;
3495
- }
3496
- const elements = selectorCache?.[elementOrSelector] ??
3497
- root.querySelectorAll(elementOrSelector);
3498
- return elements ? Array.from(elements) : [];
3499
- }
3500
- return Array.from(elementOrSelector);
3501
- }
3502
-
3503
- /**
3504
- * Provided a value and a ValueType, returns the value as that value type.
3505
- */
3506
- const getValueAsType = (value, type) => {
3507
- return type && typeof value === "number"
3508
- ? type.transform(value)
3509
- : value;
3510
- };
3511
-
3512
3512
  const { schedule: microtask, cancel: cancelMicrotask } =
3513
3513
  /* @__PURE__ */ createRenderBatcher(queueMicrotask, false);
3514
3514
 
@@ -39,7 +39,10 @@ export { supportsPartialKeyframes } from '../../motion-dom/dist/es/animation/waa
39
39
  export { supportsBrowserAnimation } from '../../motion-dom/dist/es/animation/waapi/supports/waapi.mjs';
40
40
  export { acceleratedValues } from '../../motion-dom/dist/es/animation/waapi/utils/accelerated-values.mjs';
41
41
  export { generateLinearEasing } from '../../motion-dom/dist/es/animation/waapi/utils/linear.mjs';
42
+ export { addAttrValue, attrEffect } from '../../motion-dom/dist/es/effects/attr/index.mjs';
43
+ export { propEffect } from '../../motion-dom/dist/es/effects/prop/index.mjs';
42
44
  export { addStyleValue, styleEffect } from '../../motion-dom/dist/es/effects/style/index.mjs';
45
+ export { svgEffect } from '../../motion-dom/dist/es/effects/svg/index.mjs';
43
46
  export { createRenderBatcher } from '../../motion-dom/dist/es/frameloop/batcher.mjs';
44
47
  export { cancelMicrotask, microtask } from '../../motion-dom/dist/es/frameloop/microtask.mjs';
45
48
  export { time } from '../../motion-dom/dist/es/frameloop/sync-time.mjs';
@@ -138,7 +138,10 @@ export { supportsPartialKeyframes } from '../../motion-dom/dist/es/animation/waa
138
138
  export { supportsBrowserAnimation } from '../../motion-dom/dist/es/animation/waapi/supports/waapi.mjs';
139
139
  export { acceleratedValues } from '../../motion-dom/dist/es/animation/waapi/utils/accelerated-values.mjs';
140
140
  export { generateLinearEasing } from '../../motion-dom/dist/es/animation/waapi/utils/linear.mjs';
141
+ export { addAttrValue, attrEffect } from '../../motion-dom/dist/es/effects/attr/index.mjs';
142
+ export { propEffect } from '../../motion-dom/dist/es/effects/prop/index.mjs';
141
143
  export { addStyleValue, styleEffect } from '../../motion-dom/dist/es/effects/style/index.mjs';
144
+ export { svgEffect } from '../../motion-dom/dist/es/effects/svg/index.mjs';
142
145
  export { createRenderBatcher } from '../../motion-dom/dist/es/frameloop/batcher.mjs';
143
146
  export { cancelMicrotask, microtask } from '../../motion-dom/dist/es/frameloop/microtask.mjs';
144
147
  export { time } from '../../motion-dom/dist/es/frameloop/sync-time.mjs';
@@ -0,0 +1,41 @@
1
+ import { camelToDash } from '../../render/dom/utils/camel-to-dash.mjs';
2
+ import { createSelectorEffect } from '../utils/create-dom-effect.mjs';
3
+ import { createEffect } from '../utils/create-effect.mjs';
4
+
5
+ function canSetAsProperty(element, name) {
6
+ if (!(name in element))
7
+ return false;
8
+ const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(element), name) ||
9
+ Object.getOwnPropertyDescriptor(element, name);
10
+ // Check if it has a setter
11
+ return descriptor && typeof descriptor.set === "function";
12
+ }
13
+ const addAttrValue = (element, state, key, value) => {
14
+ const isProp = canSetAsProperty(element, key);
15
+ const name = isProp
16
+ ? key
17
+ : key.startsWith("data") || key.startsWith("aria")
18
+ ? camelToDash(key)
19
+ : key;
20
+ /**
21
+ * Set attribute directly via property if available
22
+ */
23
+ const render = isProp
24
+ ? () => {
25
+ element[name] = state.latest[key];
26
+ }
27
+ : () => {
28
+ const v = state.latest[key];
29
+ if (v === null || v === undefined) {
30
+ element.removeAttribute(name);
31
+ }
32
+ else {
33
+ element.setAttribute(name, String(v));
34
+ }
35
+ };
36
+ return state.set(key, value, render);
37
+ };
38
+ const attrEffect = /*@__PURE__*/ createSelectorEffect(
39
+ /*@__PURE__*/ createEffect(addAttrValue));
40
+
41
+ export { addAttrValue, attrEffect };
@@ -0,0 +1,9 @@
1
+ import { createEffect } from '../utils/create-effect.mjs';
2
+
3
+ const propEffect = /*@__PURE__*/ createEffect((subject, state, key, value) => {
4
+ return state.set(key, value, () => {
5
+ subject[key] = state.latest[key];
6
+ }, undefined, false);
7
+ });
8
+
9
+ export { propEffect };
@@ -1,21 +1,39 @@
1
1
  import { isCSSVar } from '../../render/dom/is-css-var.mjs';
2
2
  import { transformProps } from '../../render/utils/keys-transform.mjs';
3
+ import { isHTMLElement } from '../../utils/is-html-element.mjs';
3
4
  import { MotionValue } from '../../value/index.mjs';
4
5
  import { createSelectorEffect } from '../utils/create-dom-effect.mjs';
5
6
  import { createEffect } from '../utils/create-effect.mjs';
6
7
  import { buildTransform } from './transform.mjs';
7
8
 
9
+ const originProps = new Set(["originX", "originY", "originZ"]);
8
10
  const addStyleValue = (element, state, key, value) => {
9
11
  let render = undefined;
10
12
  let computed = undefined;
11
13
  if (transformProps.has(key)) {
12
14
  if (!state.get("transform")) {
15
+ // If this is an HTML element, we need to set the transform-box to fill-box
16
+ // to normalise the transform relative to the element's bounding box
17
+ if (!isHTMLElement(element) && !state.get("transformBox")) {
18
+ addStyleValue(element, state, "transformBox", new MotionValue("fill-box"));
19
+ }
13
20
  state.set("transform", new MotionValue("none"), () => {
14
21
  element.style.transform = buildTransform(state);
15
22
  });
16
23
  }
17
24
  computed = state.get("transform");
18
25
  }
26
+ else if (originProps.has(key)) {
27
+ if (!state.get("transformOrigin")) {
28
+ state.set("transformOrigin", new MotionValue(""), () => {
29
+ const originX = state.latest.originX ?? "50%";
30
+ const originY = state.latest.originY ?? "50%";
31
+ const originZ = state.latest.originZ ?? 0;
32
+ element.style.transformOrigin = `${originX} ${originY} ${originZ}`;
33
+ });
34
+ }
35
+ computed = state.get("transformOrigin");
36
+ }
19
37
  else if (isCSSVar(key)) {
20
38
  render = () => {
21
39
  element.style.setProperty(key, state.latest[key]);
@@ -28,6 +46,7 @@ const addStyleValue = (element, state, key, value) => {
28
46
  }
29
47
  return state.set(key, value, render, computed);
30
48
  };
31
- const styleEffect = createSelectorEffect(createEffect(addStyleValue));
49
+ const styleEffect = /*@__PURE__*/ createSelectorEffect(
50
+ /*@__PURE__*/ createEffect(addStyleValue));
32
51
 
33
52
  export { addStyleValue, styleEffect };
@@ -0,0 +1,41 @@
1
+ import { MotionValue } from '../../value/index.mjs';
2
+ import { px } from '../../value/types/numbers/units.mjs';
3
+ import { addAttrValue } from '../attr/index.mjs';
4
+ import { addStyleValue } from '../style/index.mjs';
5
+ import { createSelectorEffect } from '../utils/create-dom-effect.mjs';
6
+ import { createEffect } from '../utils/create-effect.mjs';
7
+ import { frame } from '../../frameloop/frame.mjs';
8
+
9
+ const toPx = px.transform;
10
+ function addSVGPathValue(element, state, key, value) {
11
+ frame.render(() => element.setAttribute("pathLength", "1"));
12
+ if (key === "pathOffset") {
13
+ return state.set(key, value, () => element.setAttribute("stroke-dashoffset", toPx(-state.latest[key])));
14
+ }
15
+ else {
16
+ if (!state.get("stroke-dasharray")) {
17
+ state.set("stroke-dasharray", new MotionValue("1 1"), () => {
18
+ const { pathLength = 1, pathSpacing } = state.latest;
19
+ element.setAttribute("stroke-dasharray", `${toPx(pathLength)} ${toPx(pathSpacing ?? 1 - Number(pathLength))}`);
20
+ });
21
+ }
22
+ return state.set(key, value, undefined, state.get("stroke-dasharray"));
23
+ }
24
+ }
25
+ const addSVGValue = (element, state, key, value) => {
26
+ if (key.startsWith("path")) {
27
+ return addSVGPathValue(element, state, key, value);
28
+ }
29
+ else if (key.startsWith("attr")) {
30
+ return addAttrValue(element, state, convertAttrKey(key), value);
31
+ }
32
+ const handler = key in element.style ? addStyleValue : addAttrValue;
33
+ return handler(element, state, key, value);
34
+ };
35
+ const svgEffect = /*@__PURE__*/ createSelectorEffect(
36
+ /*@__PURE__*/ createEffect(addSVGValue));
37
+ function convertAttrKey(key) {
38
+ return key.replace(/^attr([A-Z])/, (_, firstChar) => firstChar.toLowerCase());
39
+ }
40
+
41
+ export { svgEffect };
@@ -0,0 +1,5 @@
1
+ function camelToDash(str) {
2
+ return str.replace(/([A-Z])/g, (match) => `-${match.toLowerCase()}`);
3
+ }
4
+
5
+ export { camelToDash };