UNPKG

@chakra-ui/descendant

Version:

Register child nodes of a react element for better accessibility

1 lines 5.08 kB
{"version":3,"sources":["../src/use-descendant.ts"],"sourcesContent":["import { createContext } from \"@chakra-ui/react-context\"\nimport { mergeRefs } from \"@chakra-ui/react-use-merge-refs\"\nimport { useRef, useState } from \"react\"\nimport { DescendantsManager, DescendantOptions } from \"./descendant\"\nimport { useSafeLayoutEffect, cast } from \"./utils\"\n\n/**\n * @internal\n * React hook that initializes the DescendantsManager\n */\nfunction useDescendants<\n T extends HTMLElement = HTMLElement,\n K extends Record<string, any> = {},\n>() {\n const descendants = useRef(new DescendantsManager<T, K>())\n useSafeLayoutEffect(() => {\n return () => descendants.current.destroy()\n })\n return descendants.current\n}\n\nexport interface UseDescendantsReturn\n extends ReturnType<typeof useDescendants> {}\n\n/* -------------------------------------------------------------------------------------------------\n * Descendants context to be used in component-land.\n - Mount the `DescendantsContextProvider` at the root of the component\n - Call `useDescendantsContext` anywhere you need access to the descendants information\n\n NB: I recommend using `createDescendantContext` below\n * -----------------------------------------------------------------------------------------------*/\n\nconst [DescendantsContextProvider, useDescendantsContext] =\n createContext<UseDescendantsReturn>({\n name: \"DescendantsProvider\",\n errorMessage:\n \"useDescendantsContext must be used within DescendantsProvider\",\n })\n\n/**\n * @internal\n * This hook provides information a descendant such as:\n * - Its index compared to other descendants\n * - ref callback to register the descendant\n * - Its enabled index compared to other enabled descendants\n */\nfunction useDescendant<\n T extends HTMLElement = HTMLElement,\n K extends Record<string, any> = {},\n>(options?: DescendantOptions<K>) {\n const descendants = useDescendantsContext()\n const [index, setIndex] = useState(-1)\n const ref = useRef<T>(null)\n\n useSafeLayoutEffect(() => {\n return () => {\n if (!ref.current) return\n descendants.unregister(ref.current)\n }\n }, [])\n\n useSafeLayoutEffect(() => {\n if (!ref.current) return\n const dataIndex = Number(ref.current.dataset[\"index\"])\n if (index != dataIndex && !Number.isNaN(dataIndex)) {\n setIndex(dataIndex)\n }\n })\n\n const refCallback = options\n ? cast<React.RefCallback<T>>(descendants.register(options))\n : cast<React.RefCallback<T>>(descendants.register)\n\n return {\n descendants,\n index,\n enabledIndex: descendants.enabledIndexOf(ref.current),\n register: mergeRefs(refCallback, ref),\n }\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Function that provides strongly typed versions of the context provider and hooks above.\n To be used in component-land\n * -----------------------------------------------------------------------------------------------*/\n\nexport function createDescendantContext<\n T extends HTMLElement = HTMLElement,\n K extends Record<string, any> = {},\n>() {\n type ContextProviderType = React.Provider<DescendantsManager<T, K>>\n const ContextProvider = cast<ContextProviderType>(DescendantsContextProvider)\n\n const _useDescendantsContext = () =>\n cast<DescendantsManager<T, K>>(useDescendantsContext())\n\n const _useDescendant = (options?: DescendantOptions<K>) =>\n useDescendant<T, K>(options)\n\n const _useDescendants = () => useDescendants<T, K>()\n\n return [\n // context provider\n ContextProvider,\n // call this when you need to read from context\n _useDescendantsContext,\n // descendants state information, to be called and passed to `ContextProvider`\n _useDescendants,\n // descendant index information\n _useDescendant,\n ] as const\n}\n"],"mappings":";;;;;;;;;;AAAA,SAAS,qBAAqB;AAC9B,SAAS,iBAAiB;AAC1B,SAAS,QAAQ,gBAAgB;AAQjC,SAAS,iBAGL;AACF,QAAM,cAAc,OAAO,IAAI,mBAAyB,CAAC;AACzD,sBAAoB,MAAM;AACxB,WAAO,MAAM,YAAY,QAAQ,QAAQ;AAAA,EAC3C,CAAC;AACD,SAAO,YAAY;AACrB;AAaA,IAAM,CAAC,4BAA4B,qBAAqB,IACtD,cAAoC;AAAA,EAClC,MAAM;AAAA,EACN,cACE;AACJ,CAAC;AASH,SAAS,cAGP,SAAgC;AAChC,QAAM,cAAc,sBAAsB;AAC1C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,MAAM,OAAU,IAAI;AAE1B,sBAAoB,MAAM;AACxB,WAAO,MAAM;AACX,UAAI,CAAC,IAAI;AAAS;AAClB,kBAAY,WAAW,IAAI,OAAO;AAAA,IACpC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,sBAAoB,MAAM;AACxB,QAAI,CAAC,IAAI;AAAS;AAClB,UAAM,YAAY,OAAO,IAAI,QAAQ,QAAQ,OAAO,CAAC;AACrD,QAAI,SAAS,aAAa,CAAC,OAAO,MAAM,SAAS,GAAG;AAClD,eAAS,SAAS;AAAA,IACpB;AAAA,EACF,CAAC;AAED,QAAM,cAAc,UAChB,KAA2B,YAAY,SAAS,OAAO,CAAC,IACxD,KAA2B,YAAY,QAAQ;AAEnD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,cAAc,YAAY,eAAe,IAAI,OAAO;AAAA,IACpD,UAAU,UAAU,aAAa,GAAG;AAAA,EACtC;AACF;AAOO,SAAS,0BAGZ;AAEF,QAAM,kBAAkB,KAA0B,0BAA0B;AAE5E,QAAM,yBAAyB,MAC7B,KAA+B,sBAAsB,CAAC;AAExD,QAAM,iBAAiB,CAAC,YACtB,cAAoB,OAAO;AAE7B,QAAM,kBAAkB,MAAM,eAAqB;AAEnD,SAAO;AAAA;AAAA,IAEL;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA,EACF;AACF;","names":[]}