@sanity/preview-kit
Version:
General purpose utils for live content and visual editing
1 lines • 15.1 kB
Source Map (JSON)
{"version":3,"file":"hooks.cjs","sources":["../../../../node_modules/.pnpm/react-fast-compare@3.2.2/node_modules/react-fast-compare/index.js","../../src/context.ts","../../src/hooks.ts"],"sourcesContent":["/* global Map:readonly, Set:readonly, ArrayBuffer:readonly */\n\nvar hasElementType = typeof Element !== 'undefined';\nvar hasMap = typeof Map === 'function';\nvar hasSet = typeof Set === 'function';\nvar hasArrayBuffer = typeof ArrayBuffer === 'function' && !!ArrayBuffer.isView;\n\n// Note: We **don't** need `envHasBigInt64Array` in fde es6/index.js\n\nfunction equal(a, b) {\n // START: fast-deep-equal es6/index.js 3.1.3\n if (a === b) return true;\n\n if (a && b && typeof a == 'object' && typeof b == 'object') {\n if (a.constructor !== b.constructor) return false;\n\n var length, i, keys;\n if (Array.isArray(a)) {\n length = a.length;\n if (length != b.length) return false;\n for (i = length; i-- !== 0;)\n if (!equal(a[i], b[i])) return false;\n return true;\n }\n\n // START: Modifications:\n // 1. Extra `has<Type> &&` helpers in initial condition allow es6 code\n // to co-exist with es5.\n // 2. Replace `for of` with es5 compliant iteration using `for`.\n // Basically, take:\n //\n // ```js\n // for (i of a.entries())\n // if (!b.has(i[0])) return false;\n // ```\n //\n // ... and convert to:\n //\n // ```js\n // it = a.entries();\n // while (!(i = it.next()).done)\n // if (!b.has(i.value[0])) return false;\n // ```\n //\n // **Note**: `i` access switches to `i.value`.\n var it;\n if (hasMap && (a instanceof Map) && (b instanceof Map)) {\n if (a.size !== b.size) return false;\n it = a.entries();\n while (!(i = it.next()).done)\n if (!b.has(i.value[0])) return false;\n it = a.entries();\n while (!(i = it.next()).done)\n if (!equal(i.value[1], b.get(i.value[0]))) return false;\n return true;\n }\n\n if (hasSet && (a instanceof Set) && (b instanceof Set)) {\n if (a.size !== b.size) return false;\n it = a.entries();\n while (!(i = it.next()).done)\n if (!b.has(i.value[0])) return false;\n return true;\n }\n // END: Modifications\n\n if (hasArrayBuffer && ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {\n length = a.length;\n if (length != b.length) return false;\n for (i = length; i-- !== 0;)\n if (a[i] !== b[i]) return false;\n return true;\n }\n\n if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;\n // START: Modifications:\n // Apply guards for `Object.create(null)` handling. See:\n // - https://github.com/FormidableLabs/react-fast-compare/issues/64\n // - https://github.com/epoberezkin/fast-deep-equal/issues/49\n if (a.valueOf !== Object.prototype.valueOf && typeof a.valueOf === 'function' && typeof b.valueOf === 'function') return a.valueOf() === b.valueOf();\n if (a.toString !== Object.prototype.toString && typeof a.toString === 'function' && typeof b.toString === 'function') return a.toString() === b.toString();\n // END: Modifications\n\n keys = Object.keys(a);\n length = keys.length;\n if (length !== Object.keys(b).length) return false;\n\n for (i = length; i-- !== 0;)\n if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;\n // END: fast-deep-equal\n\n // START: react-fast-compare\n // custom handling for DOM elements\n if (hasElementType && a instanceof Element) return false;\n\n // custom handling for React/Preact\n for (i = length; i-- !== 0;) {\n if ((keys[i] === '_owner' || keys[i] === '__v' || keys[i] === '__o') && a.$$typeof) {\n // React-specific: avoid traversing React elements' _owner\n // Preact-specific: avoid traversing Preact elements' __v and __o\n // __v = $_original / $_vnode\n // __o = $_owner\n // These properties contain circular references and are not needed when\n // comparing the actual elements (and not their owners)\n // .$$typeof and ._store on just reasonable markers of elements\n\n continue;\n }\n\n // all other properties should be traversed as usual\n if (!equal(a[keys[i]], b[keys[i]])) return false;\n }\n // END: react-fast-compare\n\n // START: fast-deep-equal\n return true;\n }\n\n return a !== a && b !== b;\n}\n// end fast-deep-equal\n\nmodule.exports = function isEqual(a, b) {\n try {\n return equal(a, b);\n } catch (error) {\n if (((error.message || '').match(/stack|recursion/i))) {\n // warn on circular references, don't crash\n // browsers give this different errors name and messages:\n // chrome/safari: \"RangeError\", \"Maximum call stack size exceeded\"\n // firefox: \"InternalError\", too much recursion\"\n // edge: \"Error\", \"Out of stack space\"\n console.warn('react-fast-compare cannot handle circular refs');\n return false;\n }\n // some other error. we should definitely know about these\n throw error;\n }\n};\n","import {createContext} from 'react'\n\nimport type {DefineListenerContext} from './types'\n\n/**\n * @internal\n */\nexport const defineStoreContext = createContext<DefineListenerContext | null>(null)\n","import type {QueryParams as ClientQueryParams, QueryParams} from '@sanity/client'\nimport {useCallback, useContext, useEffect, useMemo, useState, useSyncExternalStore} from 'react'\nimport isFastEqual from 'react-fast-compare'\nimport {useSyncExternalStoreWithSelector} from 'use-sync-external-store/with-selector'\n\nimport {defineStoreContext} from './context'\nimport type {ListenerGetSnapshot, ListenerSubscribe, QueryEnabled, QueryLoading} from './types'\n\n/**\n * By default 'react-fast-compare' is used to check if the query result has changed.\n * It's reasonably fast, but you can make it even faster by providing your own function as you know which\n * part of the query result is visible to the user, and which parts can skip rendering.\n * @public\n */\nexport type isEqualFn<QueryResult> = (a: QueryResult, b: QueryResult) => boolean\n\n/** @public */\nexport interface LiveQueryHookOptions<QueryResult> {\n isEqual?: isEqualFn<QueryResult>\n}\n\n/** @public */\nexport function useLiveQuery<\n QueryResult,\n QueryParams extends ClientQueryParams = ClientQueryParams,\n>(\n initialData: QueryResult,\n query: string,\n queryParams?: QueryParams,\n options?: LiveQueryHookOptions<QueryResult>,\n): [QueryResult, QueryLoading, QueryEnabled] {\n const {isEqual = isFastEqual} = options || {}\n\n const defineStore = useContext(defineStoreContext)\n const params = useQueryParams(queryParams)\n const noStore = useMemo(\n () => ({\n subscribe: (() => () => {}) satisfies ListenerSubscribe,\n getSnapshot: () => initialData,\n }),\n [initialData],\n )\n const store = useMemo<\n | {\n subscribe: ListenerSubscribe\n getSnapshot: ListenerGetSnapshot<QueryResult>\n }\n | undefined\n >(\n () =>\n defineStore?.<QueryResult>(initialData, query, params) || {\n subscribe: (() => () => {}) satisfies ListenerSubscribe,\n getSnapshot: () => initialData,\n },\n [defineStore, initialData, params, query],\n )\n // initialSnapshot might change before hydration is done, so deep cloning it on the first hook call\n // helps ensure that we don't get a mismatch between the server and client snapshots\n const [serverSnapshot] = useState(() => {\n if (initialData === undefined) {\n throw new Error(\n `initialSnapshot can't be undefined, if you don't want an initial value use null instead`,\n )\n }\n try {\n return JSON.parse(JSON.stringify(initialData))\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn(\n \"Failed to deep clone initialSnapshot, this is likely an error and an indication that the snapshot isn't JSON serializable\",\n {initialSnapshot: initialData, error},\n )\n return initialData\n }\n })\n const getServerSnapshot = useCallback(() => serverSnapshot, [serverSnapshot])\n const selector = useCallback((snapshot: QueryResult) => snapshot, [])\n\n const snapshot = useSyncExternalStoreWithSelector(\n store?.subscribe || noStore.subscribe,\n store?.getSnapshot || noStore.getSnapshot,\n getServerSnapshot,\n selector,\n isEqual,\n )\n const enabled = defineStore !== null\n const loading = enabled && serverSnapshot === snapshot\n\n return [snapshot, loading, enabled]\n}\n\n/**\n * The `useLiveQuery` hook is designed to work in environments where the parent `LiveQueryProvider` may be lazy loaded.\n * Thus if it can't \"know\" if it's \"live\" or not, or of it will be later. When everything is setup correctly this is fine.\n * This hook on the other hand does know. If it returns `false` then sibling `useLiveQuery` hooks are not \"live\".\n * If it returns `true` then sibling `useLiveQuery` hooks are \"live\" as there is a parent `LiveQueryProvider` in the tree that is loaded and active.\n * @public\n * @deprecated use `useLiveQuery` instead: `const [,,enabled] = useLiveQuery(initialData, query, params)`\n */\nexport function useIsEnabled(): boolean {\n return useContext(defineStoreContext) !== null\n}\n\n/**\n * Return params that are stable with deep equal as long as the key order is the same\n * @internal\n */\nexport function useQueryParams(params?: undefined | null | QueryParams): QueryParams {\n const stringifiedParams = useMemo(() => JSON.stringify(params || {}), [params])\n return useMemo(() => JSON.parse(stringifiedParams) as QueryParams, [stringifiedParams])\n}\n\n/**\n * Keeps track of when revalidation and activities should be paused\n */\nexport function useShouldPause(): boolean {\n const [online, setOnline] = useState(false)\n useEffect(() => {\n setOnline(navigator.onLine)\n const online = () => setOnline(true)\n const offline = () => setOnline(false)\n window.addEventListener('online', online)\n window.addEventListener('offline', offline)\n return () => {\n window.removeEventListener('online', online)\n window.removeEventListener('offline', offline)\n }\n }, [])\n const visibilityState = useSyncExternalStore(\n onVisibilityChange,\n () => document.visibilityState,\n () => 'hidden' satisfies DocumentVisibilityState,\n )\n\n // Should pause activity when offline\n if (!online) {\n return true\n }\n\n // Should pause when the document isn't visible, as it's likely the user isn't looking at the page\n if (visibilityState === 'hidden') {\n return true\n }\n\n return false\n}\n\nfunction onVisibilityChange(onStoreChange: () => void): () => void {\n document.addEventListener('visibilitychange', onStoreChange)\n return () => document.removeEventListener('visibilitychange', onStoreChange)\n}\n"],"names":["createContext","isEqual","isFastEqual","useContext","useMemo","useState","useCallback","snapshot","useSyncExternalStoreWithSelector","useEffect","online","useSyncExternalStore"],"mappings":"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","x_google_ignoreList":[0]}