morphicons 1.7.0 → 1.7.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.
package/README.md CHANGED
@@ -141,7 +141,7 @@ ref.current?.morphTo(Check); // animates
141
141
  ref.current?.set(X); // jumps without animating
142
142
  ```
143
143
 
144
- The DOM-free core beyond the browser: the dom driver is reused verbatim as the engine (React Native has a global `requestAnimationFrame`, and `PathEl` is structural), so the whole platform difference is a shim that forwards the per-frame `d` write to `Path.setNativeProps` of react-native-svg — outside the React render, exactly like the web mutation. Same surface as the React binding (`size`, `strokeWidth`, `absoluteStrokeWidth`, `color`, plus the native `Svg` props: `testID`, touch handlers…), same accessibility defaults (`aria-hidden` unless you pass `label` → `role="img"` + `aria-label`). With `reducedMotion="user"`, the OS setting comes from `AccessibilityInfo` (best-effort: the query is async; a `reduceMotionChanged` subscription keeps it exact from then on). Requires Metro with package `exports` resolution — default since React Native 0.79; on older versions enable `unstable_enablePackageExports`.
144
+ The DOM-free core beyond the browser: the dom driver is reused verbatim as the engine (React Native has a global `requestAnimationFrame`, and `PathEl` is structural), so the whole platform difference is a shim that forwards the per-frame `d` write to `Path.setNativeProps` of react-native-svg — outside the React render, exactly like the web mutation. On the New Architecture that write is not the last word, because every Fabric commit rebuilds the native path from the props React declares: the binding therefore publishes the driver's live `d` on each render, and re-applies it in a layout effect when a frame landed in between, so an unrelated re-render (a color or selection change, at rest or mid-flight) can no longer restore the icon the component mounted with. Same surface as the React binding (`size`, `strokeWidth`, `absoluteStrokeWidth`, `color`, plus the native `Svg` props: `testID`, touch handlers…), same accessibility defaults (`aria-hidden` unless you pass `label` → `role="img"` + `aria-label`). With `reducedMotion="user"`, the OS setting comes from `AccessibilityInfo` (best-effort: the query is async; a `reduceMotionChanged` subscription keeps it exact from then on). Requires Metro with package `exports` resolution — default since React Native 0.79; on older versions enable `unstable_enablePackageExports`.
145
145
 
146
146
  ### Astro — same three modes, zero framework runtime
147
147
 
@@ -5,8 +5,10 @@ import { forwardRef, useCallback, useEffect, useImperativeHandle, useLayoutEffec
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  import { AccessibilityInfo } from "react-native";
7
7
  import Svg, { Path } from "react-native-svg";
8
+ //#region src/react-native/iso-layout-effect.ts
9
+ const useIsoLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
10
+ //#endregion
8
11
  //#region src/react-native/index.tsx
9
- const useIsoLayoutEffect = typeof document === "undefined" ? useEffect : useLayoutEffect;
10
12
  let reduced = false;
11
13
  let rmInit = false;
12
14
  function initReducedMotion() {
@@ -39,6 +41,8 @@ const MorphIcon = forwardRef(function MorphIcon(props, ref) {
39
41
  if (controlled) return frozenD(from, to, progress ?? 0);
40
42
  return initialIcon !== void 0 ? canonicalD(initialIcon) : "";
41
43
  });
44
+ const liveD = useRef(initialD);
45
+ const declaredD = liveD.current;
42
46
  const pathRef = useRef(null);
43
47
  const morphRef = useRef(null);
44
48
  const springRef = useRef(spring);
@@ -53,7 +57,9 @@ const MorphIcon = forwardRef(function MorphIcon(props, ref) {
53
57
  /** The PathEl shim: createMorph only ever writes `d`, and Path forwards
54
58
  * it to the native view without re-rendering. Stable identity. */
55
59
  const el = useRef({ setAttribute: (name, value) => {
56
- if (name === "d") pathRef.current?.setNativeProps({ d: value });
60
+ if (name !== "d") return;
61
+ liveD.current = value;
62
+ pathRef.current?.setNativeProps({ d: value });
57
63
  } });
58
64
  /** morphTo that applies the reduced-motion policy ("user" reads the OS
59
65
  * setting via AccessibilityInfo, best-effort). */
@@ -99,6 +105,9 @@ const MorphIcon = forwardRef(function MorphIcon(props, ref) {
99
105
  pair.current = null;
100
106
  };
101
107
  }, []);
108
+ useIsoLayoutEffect(() => {
109
+ if (liveD.current !== declaredD) pathRef.current?.setNativeProps({ d: liveD.current });
110
+ });
102
111
  useEffect(() => {
103
112
  if (reducedMotion === "user") initReducedMotion();
104
113
  }, [reducedMotion]);
@@ -180,7 +189,7 @@ const MorphIcon = forwardRef(function MorphIcon(props, ref) {
180
189
  ...rest,
181
190
  children: /* @__PURE__ */ jsx(Path, {
182
191
  ref: pathRef,
183
- d: initialD
192
+ d: declaredD
184
193
  })
185
194
  });
186
195
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "morphicons",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "description": "Universal morphing for stroke-based icons with spring physics — zero runtime dependencies",
5
5
  "license": "MIT",
6
6
  "author": "Guillermo (https://guillermolg.com)",