UNPKG

1.78 kBPlain TextView Raw
1/*
2 * Copyright 2020 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12
13import {AriaLabelingProps} from '@react-types/shared';
14import {useLayoutEffect} from './useLayoutEffect';
15import {useState} from 'react';
16
17let descriptionId = 0;
18const descriptionNodes = new Map<string, {refCount: number, element: HTMLElement}>();
19
20export function useDescription(description: string): AriaLabelingProps {
21 let [id, setId] = useState(null);
22
23 useLayoutEffect(() => {
24 if (!description) {
25 return;
26 }
27
28 let desc = descriptionNodes.get(description);
29 if (!desc) {
30 let id = `react-aria-description-${descriptionId++}`;
31 setId(id);
32
33 let node = document.createElement('div');
34 node.id = id;
35 node.style.display = 'none';
36 node.textContent = description;
37 document.body.appendChild(node);
38 desc = {refCount: 0, element: node};
39 descriptionNodes.set(description, desc);
40 } else {
41 setId(desc.element.id);
42 }
43
44 desc.refCount++;
45 return () => {
46 if (--desc.refCount === 0) {
47 desc.element.remove();
48 descriptionNodes.delete(description);
49 }
50 };
51 }, [description]);
52
53 return {
54 'aria-describedby': description ? id : undefined
55 };
56}