@wordpress/compose
Version:
WordPress higher-order components (HOCs).
8 lines (7 loc) • 7.12 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../../../src/hooks/use-resize-observer/legacy/index.tsx"],
"sourcesContent": ["/**\n * External dependencies\n */\nimport type { ReactElement } from 'react';\n\n/**\n * WordPress dependencies\n */\nimport { useCallback, useRef, useState } from '@wordpress/element';\n/**\n * Internal dependencies\n */\nimport { useResizeObserver } from '../use-resize-observer';\n\nexport type ObservedSize = {\n\twidth: number | null;\n\theight: number | null;\n};\n\n// We're only using the first element of the size sequences, until future versions of the spec solidify on how\n// exactly it'll be used for fragments in multi-column scenarios:\n// From the spec:\n// > The box size properties are exposed as FrozenArray in order to support elements that have multiple fragments,\n// > which occur in multi-column scenarios. However the current definitions of content rect and border box do not\n// > mention how those boxes are affected by multi-column layout. In this spec, there will only be a single\n// > ResizeObserverSize returned in the FrozenArray, which will correspond to the dimensions of the first column.\n// > A future version of this spec will extend the returned FrozenArray to contain the per-fragment size information.\n// (https://drafts.csswg.org/resize-observer/#resize-observer-entry-interface)\n//\n// Also, testing these new box options revealed that in both Chrome and FF everything is returned in the callback,\n// regardless of the \"box\" option.\n// The spec states the following on this:\n// > This does not have any impact on which box dimensions are returned to the defined callback when the event\n// > is fired, it solely defines which box the author wishes to observe layout changes on.\n// (https://drafts.csswg.org/resize-observer/#resize-observer-interface)\n// I'm not exactly clear on what this means, especially when you consider a later section stating the following:\n// > This section is non-normative. An author may desire to observe more than one CSS box.\n// > In this case, author will need to use multiple ResizeObservers.\n// (https://drafts.csswg.org/resize-observer/#resize-observer-interface)\n// Which is clearly not how current browser implementations behave, and seems to contradict the previous quote.\n// For this reason I decided to only return the requested size,\n// even though it seems we have access to results for all box types.\n// This also means that we get to keep the current api, being able to return a simple { width, height } pair,\n// regardless of box option.\nconst extractSize = ( entry: ResizeObserverEntry ): ObservedSize => {\n\tlet entrySize;\n\tif ( ! entry.contentBoxSize ) {\n\t\t// The dimensions in `contentBoxSize` and `contentRect` are equivalent according to the spec.\n\t\t// See the 6th step in the description for the RO algorithm:\n\t\t// https://drafts.csswg.org/resize-observer/#create-and-populate-resizeobserverentry-h\n\t\t// > Set this.contentRect to logical this.contentBoxSize given target and observedBox of \"content-box\".\n\t\t// In real browser implementations of course these objects differ, but the width/height values should be equivalent.\n\t\tentrySize = [ entry.contentRect.width, entry.contentRect.height ];\n\t} else if ( entry.contentBoxSize[ 0 ] ) {\n\t\tconst contentBoxSize = entry.contentBoxSize[ 0 ];\n\t\tentrySize = [ contentBoxSize.inlineSize, contentBoxSize.blockSize ];\n\t} else {\n\t\t// TS complains about this, because the RO entry type follows the spec and does not reflect Firefox's buggy\n\t\t// behaviour of returning objects instead of arrays for `borderBoxSize` and `contentBoxSize`.\n\t\tconst contentBoxSize =\n\t\t\tentry.contentBoxSize as unknown as ResizeObserverSize;\n\t\tentrySize = [ contentBoxSize.inlineSize, contentBoxSize.blockSize ];\n\t}\n\n\tconst [ width, height ] = entrySize.map( ( d ) => Math.round( d ) );\n\treturn { width, height };\n};\n\nconst RESIZE_ELEMENT_STYLES = {\n\tposition: 'absolute',\n\ttop: 0,\n\tleft: 0,\n\tright: 0,\n\tbottom: 0,\n\tpointerEvents: 'none',\n\topacity: 0,\n\toverflow: 'hidden',\n\tzIndex: -1,\n} as const;\n\ntype ResizeElementProps = {\n\tonResize: ( s: ObservedSize ) => void;\n};\n\nfunction ResizeElement( { onResize }: ResizeElementProps ) {\n\tconst resizeElementRef = useResizeObserver( ( entries ) => {\n\t\tconst newSize = extractSize( entries.at( -1 )! ); // Entries are never empty.\n\t\tonResize( newSize );\n\t} );\n\n\treturn (\n\t\t<div\n\t\t\tref={ resizeElementRef }\n\t\t\tstyle={ RESIZE_ELEMENT_STYLES }\n\t\t\taria-hidden=\"true\"\n\t\t/>\n\t);\n}\n\nfunction sizeEquals( a: ObservedSize, b: ObservedSize ) {\n\treturn a.width === b.width && a.height === b.height;\n}\n\nconst NULL_SIZE: ObservedSize = { width: null, height: null };\n\n/**\n * Hook which allows to listen to the resize event of any target element when it changes size.\n * _Note: `useResizeObserver` will report `null` sizes until after first render.\n *\n * @example\n *\n * ```js\n * const App = () => {\n * \tconst [ resizeListener, sizes ] = useResizeObserver();\n *\n * \treturn (\n * \t\t<div>\n * \t\t\t{ resizeListener }\n * \t\t\tYour content here\n * \t\t</div>\n * \t);\n * };\n * ```\n */\nexport default function useLegacyResizeObserver(): [\n\tReactElement,\n\tObservedSize,\n] {\n\tconst [ size, setSize ] = useState( NULL_SIZE );\n\n\t// Using a ref to track the previous width / height to avoid unnecessary renders.\n\tconst previousSizeRef = useRef( NULL_SIZE );\n\n\tconst handleResize = useCallback( ( newSize: ObservedSize ) => {\n\t\tif ( ! sizeEquals( previousSizeRef.current, newSize ) ) {\n\t\t\tpreviousSizeRef.current = newSize;\n\t\t\tsetSize( newSize );\n\t\t}\n\t}, [] );\n\n\tconst resizeElement = <ResizeElement onResize={ handleResize } />;\n\treturn [ resizeElement, size ];\n}\n"],
"mappings": ";AAQA,SAAS,aAAa,QAAQ,gBAAgB;AAI9C,SAAS,yBAAyB;AA+EhC;AA/CF,IAAM,cAAc,CAAE,UAA8C;AACnE,MAAI;AACJ,MAAK,CAAE,MAAM,gBAAiB;AAM7B,gBAAY,CAAE,MAAM,YAAY,OAAO,MAAM,YAAY,MAAO;AAAA,EACjE,WAAY,MAAM,eAAgB,CAAE,GAAI;AACvC,UAAM,iBAAiB,MAAM,eAAgB,CAAE;AAC/C,gBAAY,CAAE,eAAe,YAAY,eAAe,SAAU;AAAA,EACnE,OAAO;AAGN,UAAM,iBACL,MAAM;AACP,gBAAY,CAAE,eAAe,YAAY,eAAe,SAAU;AAAA,EACnE;AAEA,QAAM,CAAE,OAAO,MAAO,IAAI,UAAU,IAAK,CAAE,MAAO,KAAK,MAAO,CAAE,CAAE;AAClE,SAAO,EAAE,OAAO,OAAO;AACxB;AAEA,IAAM,wBAAwB;AAAA,EAC7B,UAAU;AAAA,EACV,KAAK;AAAA,EACL,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AACT;AAMA,SAAS,cAAe,EAAE,SAAS,GAAwB;AAC1D,QAAM,mBAAmB,kBAAmB,CAAE,YAAa;AAC1D,UAAM,UAAU,YAAa,QAAQ,GAAI,EAAG,CAAG;AAC/C,aAAU,OAAQ;AAAA,EACnB,CAAE;AAEF,SACC;AAAA,IAAC;AAAA;AAAA,MACA,KAAM;AAAA,MACN,OAAQ;AAAA,MACR,eAAY;AAAA;AAAA,EACb;AAEF;AAEA,SAAS,WAAY,GAAiB,GAAkB;AACvD,SAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE;AAC9C;AAEA,IAAM,YAA0B,EAAE,OAAO,MAAM,QAAQ,KAAK;AAqB7C,SAAR,0BAGL;AACD,QAAM,CAAE,MAAM,OAAQ,IAAI,SAAU,SAAU;AAG9C,QAAM,kBAAkB,OAAQ,SAAU;AAE1C,QAAM,eAAe,YAAa,CAAE,YAA2B;AAC9D,QAAK,CAAE,WAAY,gBAAgB,SAAS,OAAQ,GAAI;AACvD,sBAAgB,UAAU;AAC1B,cAAS,OAAQ;AAAA,IAClB;AAAA,EACD,GAAG,CAAC,CAAE;AAEN,QAAM,gBAAgB,oBAAC,iBAAc,UAAW,cAAe;AAC/D,SAAO,CAAE,eAAe,IAAK;AAC9B;",
"names": []
}