react-snapshot-bridge 1.1.0 → 1.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.
package/README.md CHANGED
@@ -1,3 +1,11 @@
1
+ <p align="center">
2
+ <img
3
+ src="https://react-snapshot-bridge.vercel.app/logo.png"
4
+ alt="react-snapshot-bridge logo"
5
+ width="500"
6
+ />
7
+ </p>
8
+
1
9
  # react-snapshot-bridge
2
10
 
3
11
  > Use React's class-only `getSnapshotBeforeUpdate` lifecycle from **function components**.
@@ -212,7 +220,8 @@ The captured value is forwarded to `componentDidUpdate`, which calls `apply`. Fr
212
220
 
213
221
  ## Caveats
214
222
 
215
- - **No call on initial mount.** Like the underlying class lifecycle, neither `capture` nor `apply` runs the first time the component appears — only on subsequent updates.
223
+ - **No call on initial mount.** Like the underlying class lifecycle, neither `capture` nor `apply` runs the first time the component appears — only on subsequent updates. `getSnapshotBeforeUpdate` is **update-only**, so you cannot use this bridge to snapshot the DOM immediately before the component's **initial** appearance on screen. When someone says "before first paint," clarify whether they mean the **first mount paint** (not covered by this lifecycle) or a **later update commit** (see next bullet).
224
+ - **Updates run before DOM mutation for that commit.** After mount, whenever the bridge commits an update, `capture` runs in the **before mutation** phase: before the DOM reflects that commit's output and before the browser paints that update. That is the timing slot this library occupies (see [How it works](#how-it-works)).
216
225
  - **Requires a re-render in the right place.** If a `React.memo` (or `shouldComponentUpdate`) ancestor short-circuits the render, or the bridge is placed as a sibling of a different component that updates on its own, neither callback will fire. See [Where to place it](#where-to-place-it).
217
226
  - **`enabled={false}` does not buffer updates.** Updates that occur while disabled are silently dropped. There is no "catch up" call when you re-enable the bridge — the next regular update is what triggers `capture`/`apply` again.
218
227
  - **Concurrent rendering safe.** React 18+ concurrent features may discard render results, but the commit phase itself is synchronous, so `capture`/`apply` always run as a paired set.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/SnapshotBeforeUpdate.tsx"],"names":["Component"],"mappings":";;;;;AAQA,IAAM,IAAA,0BAAc,4BAA4B,CAAA;AA0CzC,IAAM,oBAAA,GAAN,cAAgDA,eAAA,CAGrD;AAAA,EACS,uBAAA,GAA6B;AACpC,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,OAAA,KAAY,KAAA,EAAO;AAChC,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA,CAAK,MAAM,OAAA,EAAQ;AAAA,EAC5B;AAAA,EAES,kBAAA,CACP,UAAA,EACA,UAAA,EACA,QAAA,EACM;AACN,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,OAAA,KAAY,KAAA,EAAO;AAClC,IAAA,IAAK,aAAiC,IAAA,EAAM;AAE5C,IAAA,IAAA,CAAK,KAAA,CAAM,MAAM,QAAQ,CAAA;AAAA,EAC3B;AAAA,EAES,MAAA,GAAoB;AAC3B,IAAA,OAAO,IAAA,CAAK,MAAM,QAAA,IAAY,IAAA;AAAA,EAChC;AACF","file":"index.cjs","sourcesContent":["import { Component } from \"react\";\nimport type { ReactNode } from \"react\";\n\ntype EmptyState = Record<string, never>;\n\n/**\n * Symbol used to indicate that the snapshot should be skipped.\n */\nconst SKIP = Symbol(\"react-snapshot-bridge-skip\");\ntype Skip = typeof SKIP;\n\nexport interface SnapshotBeforeUpdateProps<T> {\n /**\n * Runs synchronously **before** the DOM is mutated for this commit.\n * Whatever you return here is forwarded to {@link SnapshotBeforeUpdateProps.apply}.\n */\n capture: () => T;\n\n /**\n * Runs synchronously **after** the DOM is mutated, before the browser paints.\n * Receives the value previously returned from {@link SnapshotBeforeUpdateProps.capture}.\n */\n apply: (snapshot: T) => void;\n\n /**\n * When `false`, both `capture` and `apply` are skipped for that commit.\n * Evaluated against the **current** props at commit time, so toggling\n * `true` -> `false` skips both callbacks for that update, and `false` -> `true`\n * runs both as usual on the next update. Defaults to `true`.\n *\n * Updates that occur while disabled are not buffered or replayed later.\n */\n enabled?: boolean;\n\n /**\n * Optional children. When provided, this component acts as a wrapper and\n * renders its children. When omitted, it renders nothing and you can place\n * it as a sibling next to the elements you care about.\n */\n children?: ReactNode;\n}\n\n/**\n * Bridges React's class-only `getSnapshotBeforeUpdate` lifecycle into trees\n * built with function components.\n *\n * The component re-renders alongside its parent and uses the `getSnapshotBeforeUpdate`\n * / `componentDidUpdate` pair internally to invoke {@link SnapshotBeforeUpdateProps.capture}\n * before DOM mutation and {@link SnapshotBeforeUpdateProps.apply} immediately after.\n */\nexport class SnapshotBeforeUpdate<T = unknown> extends Component<\n SnapshotBeforeUpdateProps<T>,\n EmptyState\n> {\n override getSnapshotBeforeUpdate(): T {\n if (this.props.enabled === false) {\n return SKIP as unknown as T;\n }\n return this.props.capture();\n }\n\n override componentDidUpdate(\n _prevProps: Readonly<SnapshotBeforeUpdateProps<T>>,\n _prevState: Readonly<EmptyState>,\n snapshot: T,\n ): void {\n if (this.props.enabled === false) return;\n if ((snapshot as unknown as Skip) === SKIP) return;\n\n this.props.apply(snapshot);\n }\n\n override render(): ReactNode {\n return this.props.children ?? null;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/SnapshotBeforeUpdate.tsx"],"names":["Component"],"mappings":";;;;;AAQA,IAAM,IAAA,0BAAc,4BAA4B,CAAA;AA0CzC,IAAM,oBAAA,GAAN,cAAgDA,eAAA,CAGrD;AAAA,EACS,uBAAA,GAA6B;AACpC,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,OAAA,KAAY,KAAA,EAAO;AAChC,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA,CAAK,MAAM,OAAA,EAAQ;AAAA,EAC5B;AAAA,EAES,kBAAA,CACP,UAAA,EACA,UAAA,EACA,QAAA,EACM;AACN,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,OAAA,KAAY,KAAA,EAAO;AAClC,IAAA,IAAK,aAAiC,IAAA,EAAM;AAE5C,IAAA,IAAA,CAAK,KAAA,CAAM,MAAM,QAAQ,CAAA;AAAA,EAC3B;AAAA,EAES,MAAA,GAAoB;AAC3B,IAAA,OAAO,IAAA,CAAK,MAAM,QAAA,IAAY,IAAA;AAAA,EAChC;AACF","file":"index.cjs","sourcesContent":["import type { ReactNode } from 'react';\nimport { Component } from 'react';\n\ntype EmptyState = Record<string, never>;\n\n/**\n * Symbol used to indicate that the snapshot should be skipped.\n */\nconst SKIP = Symbol('react-snapshot-bridge-skip');\ntype Skip = typeof SKIP;\n\nexport interface SnapshotBeforeUpdateProps<T> {\n /**\n * Runs synchronously **before** the DOM is mutated for this commit.\n * Whatever you return here is forwarded to {@link SnapshotBeforeUpdateProps.apply}.\n */\n capture: () => T;\n\n /**\n * Runs synchronously **after** the DOM is mutated, before the browser paints.\n * Receives the value previously returned from {@link SnapshotBeforeUpdateProps.capture}.\n */\n apply: (snapshot: T) => void;\n\n /**\n * When `false`, both `capture` and `apply` are skipped for that commit.\n * Evaluated against the **current** props at commit time, so toggling\n * `true` -> `false` skips both callbacks for that update, and `false` -> `true`\n * runs both as usual on the next update. Defaults to `true`.\n *\n * Updates that occur while disabled are not buffered or replayed later.\n */\n enabled?: boolean;\n\n /**\n * Optional children. When provided, this component acts as a wrapper and\n * renders its children. When omitted, it renders nothing and you can place\n * it as a sibling next to the elements you care about.\n */\n children?: ReactNode;\n}\n\n/**\n * Bridges React's class-only `getSnapshotBeforeUpdate` lifecycle into trees\n * built with function components.\n *\n * The component re-renders alongside its parent and uses the `getSnapshotBeforeUpdate`\n * / `componentDidUpdate` pair internally to invoke {@link SnapshotBeforeUpdateProps.capture}\n * before DOM mutation and {@link SnapshotBeforeUpdateProps.apply} immediately after.\n */\nexport class SnapshotBeforeUpdate<T = unknown> extends Component<\n SnapshotBeforeUpdateProps<T>,\n EmptyState\n> {\n override getSnapshotBeforeUpdate(): T {\n if (this.props.enabled === false) {\n return SKIP as unknown as T;\n }\n return this.props.capture();\n }\n\n override componentDidUpdate(\n _prevProps: Readonly<SnapshotBeforeUpdateProps<T>>,\n _prevState: Readonly<EmptyState>,\n snapshot: T,\n ): void {\n if (this.props.enabled === false) return;\n if ((snapshot as unknown as Skip) === SKIP) return;\n\n this.props.apply(snapshot);\n }\n\n override render(): ReactNode {\n return this.props.children ?? null;\n }\n}\n"]}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/SnapshotBeforeUpdate.tsx"],"names":[],"mappings":";;;AAQA,IAAM,IAAA,0BAAc,4BAA4B,CAAA;AA0CzC,IAAM,oBAAA,GAAN,cAAgD,SAAA,CAGrD;AAAA,EACS,uBAAA,GAA6B;AACpC,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,OAAA,KAAY,KAAA,EAAO;AAChC,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA,CAAK,MAAM,OAAA,EAAQ;AAAA,EAC5B;AAAA,EAES,kBAAA,CACP,UAAA,EACA,UAAA,EACA,QAAA,EACM;AACN,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,OAAA,KAAY,KAAA,EAAO;AAClC,IAAA,IAAK,aAAiC,IAAA,EAAM;AAE5C,IAAA,IAAA,CAAK,KAAA,CAAM,MAAM,QAAQ,CAAA;AAAA,EAC3B;AAAA,EAES,MAAA,GAAoB;AAC3B,IAAA,OAAO,IAAA,CAAK,MAAM,QAAA,IAAY,IAAA;AAAA,EAChC;AACF","file":"index.js","sourcesContent":["import { Component } from \"react\";\nimport type { ReactNode } from \"react\";\n\ntype EmptyState = Record<string, never>;\n\n/**\n * Symbol used to indicate that the snapshot should be skipped.\n */\nconst SKIP = Symbol(\"react-snapshot-bridge-skip\");\ntype Skip = typeof SKIP;\n\nexport interface SnapshotBeforeUpdateProps<T> {\n /**\n * Runs synchronously **before** the DOM is mutated for this commit.\n * Whatever you return here is forwarded to {@link SnapshotBeforeUpdateProps.apply}.\n */\n capture: () => T;\n\n /**\n * Runs synchronously **after** the DOM is mutated, before the browser paints.\n * Receives the value previously returned from {@link SnapshotBeforeUpdateProps.capture}.\n */\n apply: (snapshot: T) => void;\n\n /**\n * When `false`, both `capture` and `apply` are skipped for that commit.\n * Evaluated against the **current** props at commit time, so toggling\n * `true` -> `false` skips both callbacks for that update, and `false` -> `true`\n * runs both as usual on the next update. Defaults to `true`.\n *\n * Updates that occur while disabled are not buffered or replayed later.\n */\n enabled?: boolean;\n\n /**\n * Optional children. When provided, this component acts as a wrapper and\n * renders its children. When omitted, it renders nothing and you can place\n * it as a sibling next to the elements you care about.\n */\n children?: ReactNode;\n}\n\n/**\n * Bridges React's class-only `getSnapshotBeforeUpdate` lifecycle into trees\n * built with function components.\n *\n * The component re-renders alongside its parent and uses the `getSnapshotBeforeUpdate`\n * / `componentDidUpdate` pair internally to invoke {@link SnapshotBeforeUpdateProps.capture}\n * before DOM mutation and {@link SnapshotBeforeUpdateProps.apply} immediately after.\n */\nexport class SnapshotBeforeUpdate<T = unknown> extends Component<\n SnapshotBeforeUpdateProps<T>,\n EmptyState\n> {\n override getSnapshotBeforeUpdate(): T {\n if (this.props.enabled === false) {\n return SKIP as unknown as T;\n }\n return this.props.capture();\n }\n\n override componentDidUpdate(\n _prevProps: Readonly<SnapshotBeforeUpdateProps<T>>,\n _prevState: Readonly<EmptyState>,\n snapshot: T,\n ): void {\n if (this.props.enabled === false) return;\n if ((snapshot as unknown as Skip) === SKIP) return;\n\n this.props.apply(snapshot);\n }\n\n override render(): ReactNode {\n return this.props.children ?? null;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/SnapshotBeforeUpdate.tsx"],"names":[],"mappings":";;;AAQA,IAAM,IAAA,0BAAc,4BAA4B,CAAA;AA0CzC,IAAM,oBAAA,GAAN,cAAgD,SAAA,CAGrD;AAAA,EACS,uBAAA,GAA6B;AACpC,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,OAAA,KAAY,KAAA,EAAO;AAChC,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA,CAAK,MAAM,OAAA,EAAQ;AAAA,EAC5B;AAAA,EAES,kBAAA,CACP,UAAA,EACA,UAAA,EACA,QAAA,EACM;AACN,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,OAAA,KAAY,KAAA,EAAO;AAClC,IAAA,IAAK,aAAiC,IAAA,EAAM;AAE5C,IAAA,IAAA,CAAK,KAAA,CAAM,MAAM,QAAQ,CAAA;AAAA,EAC3B;AAAA,EAES,MAAA,GAAoB;AAC3B,IAAA,OAAO,IAAA,CAAK,MAAM,QAAA,IAAY,IAAA;AAAA,EAChC;AACF","file":"index.js","sourcesContent":["import type { ReactNode } from 'react';\nimport { Component } from 'react';\n\ntype EmptyState = Record<string, never>;\n\n/**\n * Symbol used to indicate that the snapshot should be skipped.\n */\nconst SKIP = Symbol('react-snapshot-bridge-skip');\ntype Skip = typeof SKIP;\n\nexport interface SnapshotBeforeUpdateProps<T> {\n /**\n * Runs synchronously **before** the DOM is mutated for this commit.\n * Whatever you return here is forwarded to {@link SnapshotBeforeUpdateProps.apply}.\n */\n capture: () => T;\n\n /**\n * Runs synchronously **after** the DOM is mutated, before the browser paints.\n * Receives the value previously returned from {@link SnapshotBeforeUpdateProps.capture}.\n */\n apply: (snapshot: T) => void;\n\n /**\n * When `false`, both `capture` and `apply` are skipped for that commit.\n * Evaluated against the **current** props at commit time, so toggling\n * `true` -> `false` skips both callbacks for that update, and `false` -> `true`\n * runs both as usual on the next update. Defaults to `true`.\n *\n * Updates that occur while disabled are not buffered or replayed later.\n */\n enabled?: boolean;\n\n /**\n * Optional children. When provided, this component acts as a wrapper and\n * renders its children. When omitted, it renders nothing and you can place\n * it as a sibling next to the elements you care about.\n */\n children?: ReactNode;\n}\n\n/**\n * Bridges React's class-only `getSnapshotBeforeUpdate` lifecycle into trees\n * built with function components.\n *\n * The component re-renders alongside its parent and uses the `getSnapshotBeforeUpdate`\n * / `componentDidUpdate` pair internally to invoke {@link SnapshotBeforeUpdateProps.capture}\n * before DOM mutation and {@link SnapshotBeforeUpdateProps.apply} immediately after.\n */\nexport class SnapshotBeforeUpdate<T = unknown> extends Component<\n SnapshotBeforeUpdateProps<T>,\n EmptyState\n> {\n override getSnapshotBeforeUpdate(): T {\n if (this.props.enabled === false) {\n return SKIP as unknown as T;\n }\n return this.props.capture();\n }\n\n override componentDidUpdate(\n _prevProps: Readonly<SnapshotBeforeUpdateProps<T>>,\n _prevState: Readonly<EmptyState>,\n snapshot: T,\n ): void {\n if (this.props.enabled === false) return;\n if ((snapshot as unknown as Skip) === SKIP) return;\n\n this.props.apply(snapshot);\n }\n\n override render(): ReactNode {\n return this.props.children ?? null;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-snapshot-bridge",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Use React's class-only `getSnapshotBeforeUpdate` lifecycle from function components.",
5
5
  "keywords": [
6
6
  "react",