@stack-spot/citric-react 0.1.0
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/dist/citric.css +2580 -0
- package/dist/components/Accordion.d.ts +33 -0
- package/dist/components/Accordion.d.ts.map +1 -0
- package/dist/components/Accordion.js +19 -0
- package/dist/components/Accordion.js.map +1 -0
- package/dist/components/Alert.d.ts +11 -0
- package/dist/components/Alert.d.ts.map +1 -0
- package/dist/components/Alert.js +5 -0
- package/dist/components/Alert.js.map +1 -0
- package/dist/components/AsyncContent.d.ts +30 -0
- package/dist/components/AsyncContent.d.ts.map +1 -0
- package/dist/components/AsyncContent.js +33 -0
- package/dist/components/AsyncContent.js.map +1 -0
- package/dist/components/Avatar.d.ts +22 -0
- package/dist/components/Avatar.d.ts.map +1 -0
- package/dist/components/Avatar.js +9 -0
- package/dist/components/Avatar.js.map +1 -0
- package/dist/components/AvatarGroup.d.ts +25 -0
- package/dist/components/AvatarGroup.d.ts.map +1 -0
- package/dist/components/AvatarGroup.js +9 -0
- package/dist/components/AvatarGroup.js.map +1 -0
- package/dist/components/Badge.d.ts +18 -0
- package/dist/components/Badge.d.ts.map +1 -0
- package/dist/components/Badge.js +7 -0
- package/dist/components/Badge.js.map +1 -0
- package/dist/components/Blockquote.d.ts +5 -0
- package/dist/components/Blockquote.d.ts.map +1 -0
- package/dist/components/Blockquote.js +4 -0
- package/dist/components/Blockquote.js.map +1 -0
- package/dist/components/Breadcrumb.d.ts +12 -0
- package/dist/components/Breadcrumb.d.ts.map +1 -0
- package/dist/components/Breadcrumb.js +8 -0
- package/dist/components/Breadcrumb.js.map +1 -0
- package/dist/components/Button.d.ts +42 -0
- package/dist/components/Button.d.ts.map +1 -0
- package/dist/components/Button.js +25 -0
- package/dist/components/Button.js.map +1 -0
- package/dist/components/Card.d.ts +19 -0
- package/dist/components/Card.d.ts.map +1 -0
- package/dist/components/Card.js +5 -0
- package/dist/components/Card.js.map +1 -0
- package/dist/components/Checkbox.d.ts +14 -0
- package/dist/components/Checkbox.d.ts.map +1 -0
- package/dist/components/Checkbox.js +7 -0
- package/dist/components/Checkbox.js.map +1 -0
- package/dist/components/CheckboxGroup.d.ts +53 -0
- package/dist/components/CheckboxGroup.d.ts.map +1 -0
- package/dist/components/CheckboxGroup.js +17 -0
- package/dist/components/CheckboxGroup.js.map +1 -0
- package/dist/components/Circle.d.ts +18 -0
- package/dist/components/Circle.d.ts.map +1 -0
- package/dist/components/Circle.js +5 -0
- package/dist/components/Circle.js.map +1 -0
- package/dist/components/CitricComponent.d.ts +14 -0
- package/dist/components/CitricComponent.d.ts.map +1 -0
- package/dist/components/CitricComponent.js +15 -0
- package/dist/components/CitricComponent.js.map +1 -0
- package/dist/components/Divider.d.ts +14 -0
- package/dist/components/Divider.d.ts.map +1 -0
- package/dist/components/Divider.js +5 -0
- package/dist/components/Divider.js.map +1 -0
- package/dist/components/ErrorBoundary.d.ts +32 -0
- package/dist/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/components/ErrorBoundary.js +46 -0
- package/dist/components/ErrorBoundary.js.map +1 -0
- package/dist/components/ErrorMessage.d.ts +4 -0
- package/dist/components/ErrorMessage.d.ts.map +1 -0
- package/dist/components/ErrorMessage.js +7 -0
- package/dist/components/ErrorMessage.js.map +1 -0
- package/dist/components/FallbackBoundary.d.ts +13 -0
- package/dist/components/FallbackBoundary.d.ts.map +1 -0
- package/dist/components/FallbackBoundary.js +11 -0
- package/dist/components/FallbackBoundary.js.map +1 -0
- package/dist/components/Favorite.d.ts +23 -0
- package/dist/components/Favorite.d.ts.map +1 -0
- package/dist/components/Favorite.js +5 -0
- package/dist/components/Favorite.js.map +1 -0
- package/dist/components/FieldGroup.d.ts +14 -0
- package/dist/components/FieldGroup.d.ts.map +1 -0
- package/dist/components/FieldGroup.js +5 -0
- package/dist/components/FieldGroup.js.map +1 -0
- package/dist/components/Form.d.ts +5 -0
- package/dist/components/Form.d.ts.map +1 -0
- package/dist/components/Form.js +6 -0
- package/dist/components/Form.js.map +1 -0
- package/dist/components/FormGroup.d.ts +22 -0
- package/dist/components/FormGroup.d.ts.map +1 -0
- package/dist/components/FormGroup.js +8 -0
- package/dist/components/FormGroup.js.map +1 -0
- package/dist/components/IconBox.d.ts +46 -0
- package/dist/components/IconBox.d.ts.map +1 -0
- package/dist/components/IconBox.js +29 -0
- package/dist/components/IconBox.js.map +1 -0
- package/dist/components/Input.d.ts +15 -0
- package/dist/components/Input.d.ts.map +1 -0
- package/dist/components/Input.js +18 -0
- package/dist/components/Input.js.map +1 -0
- package/dist/components/Link.d.ts +20 -0
- package/dist/components/Link.d.ts.map +1 -0
- package/dist/components/Link.js +21 -0
- package/dist/components/Link.js.map +1 -0
- package/dist/components/LoadingPanel.d.ts +2 -0
- package/dist/components/LoadingPanel.d.ts.map +1 -0
- package/dist/components/LoadingPanel.js +5 -0
- package/dist/components/LoadingPanel.js.map +1 -0
- package/dist/components/MenuOverlay/Menu.d.ts +6 -0
- package/dist/components/MenuOverlay/Menu.d.ts.map +1 -0
- package/dist/components/MenuOverlay/Menu.js +100 -0
- package/dist/components/MenuOverlay/Menu.js.map +1 -0
- package/dist/components/MenuOverlay/context.d.ts +6 -0
- package/dist/components/MenuOverlay/context.d.ts.map +1 -0
- package/dist/components/MenuOverlay/context.js +16 -0
- package/dist/components/MenuOverlay/context.js.map +1 -0
- package/dist/components/MenuOverlay/index.d.ts +3 -0
- package/dist/components/MenuOverlay/index.d.ts.map +1 -0
- package/dist/components/MenuOverlay/index.js +23 -0
- package/dist/components/MenuOverlay/index.js.map +1 -0
- package/dist/components/MenuOverlay/keyboard.d.ts +2 -0
- package/dist/components/MenuOverlay/keyboard.d.ts.map +1 -0
- package/dist/components/MenuOverlay/keyboard.js +66 -0
- package/dist/components/MenuOverlay/keyboard.js.map +1 -0
- package/dist/components/MenuOverlay/types.d.ts +166 -0
- package/dist/components/MenuOverlay/types.d.ts.map +1 -0
- package/dist/components/MenuOverlay/types.js +2 -0
- package/dist/components/MenuOverlay/types.js.map +1 -0
- package/dist/components/Overlay/context.d.ts +4 -0
- package/dist/components/Overlay/context.d.ts.map +1 -0
- package/dist/components/Overlay/context.js +7 -0
- package/dist/components/Overlay/context.js.map +1 -0
- package/dist/components/Overlay/index.d.ts +14 -0
- package/dist/components/Overlay/index.d.ts.map +1 -0
- package/dist/components/Overlay/index.js +120 -0
- package/dist/components/Overlay/index.js.map +1 -0
- package/dist/components/Overlay/types.d.ts +67 -0
- package/dist/components/Overlay/types.d.ts.map +1 -0
- package/dist/components/Overlay/types.js +2 -0
- package/dist/components/Overlay/types.js.map +1 -0
- package/dist/components/Pagination.d.ts +28 -0
- package/dist/components/Pagination.d.ts.map +1 -0
- package/dist/components/Pagination.js +30 -0
- package/dist/components/Pagination.js.map +1 -0
- package/dist/components/ProgressBar.d.ts +12 -0
- package/dist/components/ProgressBar.d.ts.map +1 -0
- package/dist/components/ProgressBar.js +7 -0
- package/dist/components/ProgressBar.js.map +1 -0
- package/dist/components/ProgressCircular.d.ts +16 -0
- package/dist/components/ProgressCircular.d.ts.map +1 -0
- package/dist/components/ProgressCircular.js +7 -0
- package/dist/components/ProgressCircular.js.map +1 -0
- package/dist/components/RadioGroup.d.ts +48 -0
- package/dist/components/RadioGroup.d.ts.map +1 -0
- package/dist/components/RadioGroup.js +17 -0
- package/dist/components/RadioGroup.js.map +1 -0
- package/dist/components/Rating.d.ts +13 -0
- package/dist/components/Rating.d.ts.map +1 -0
- package/dist/components/Rating.js +4 -0
- package/dist/components/Rating.js.map +1 -0
- package/dist/components/Select/RichSelect.d.ts +5 -0
- package/dist/components/Select/RichSelect.d.ts.map +1 -0
- package/dist/components/Select/RichSelect.js +152 -0
- package/dist/components/Select/RichSelect.js.map +1 -0
- package/dist/components/Select/SimpleSelect.d.ts +5 -0
- package/dist/components/Select/SimpleSelect.d.ts.map +1 -0
- package/dist/components/Select/SimpleSelect.js +24 -0
- package/dist/components/Select/SimpleSelect.js.map +1 -0
- package/dist/components/Select/index.d.ts +4 -0
- package/dist/components/Select/index.d.ts.map +1 -0
- package/dist/components/Select/index.js +7 -0
- package/dist/components/Select/index.js.map +1 -0
- package/dist/components/Select/types.d.ts +118 -0
- package/dist/components/Select/types.d.ts.map +1 -0
- package/dist/components/Select/types.js +2 -0
- package/dist/components/Select/types.js.map +1 -0
- package/dist/components/SelectBox.d.ts +65 -0
- package/dist/components/SelectBox.d.ts.map +1 -0
- package/dist/components/SelectBox.js +26 -0
- package/dist/components/SelectBox.js.map +1 -0
- package/dist/components/Skeleton.d.ts +30 -0
- package/dist/components/Skeleton.d.ts.map +1 -0
- package/dist/components/Skeleton.js +5 -0
- package/dist/components/Skeleton.js.map +1 -0
- package/dist/components/Slider.d.ts +32 -0
- package/dist/components/Slider.d.ts.map +1 -0
- package/dist/components/Slider.js +19 -0
- package/dist/components/Slider.js.map +1 -0
- package/dist/components/SmartTable.d.ts +87 -0
- package/dist/components/SmartTable.d.ts.map +1 -0
- package/dist/components/SmartTable.js +16 -0
- package/dist/components/SmartTable.js.map +1 -0
- package/dist/components/Stepper.d.ts +52 -0
- package/dist/components/Stepper.d.ts.map +1 -0
- package/dist/components/Stepper.js +53 -0
- package/dist/components/Stepper.js.map +1 -0
- package/dist/components/Switch.d.ts +10 -0
- package/dist/components/Switch.d.ts.map +1 -0
- package/dist/components/Switch.js +7 -0
- package/dist/components/Switch.js.map +1 -0
- package/dist/components/Table.d.ts +106 -0
- package/dist/components/Table.d.ts.map +1 -0
- package/dist/components/Table.js +86 -0
- package/dist/components/Table.js.map +1 -0
- package/dist/components/Tabs/TabController.d.ts +11 -0
- package/dist/components/Tabs/TabController.d.ts.map +1 -0
- package/dist/components/Tabs/TabController.js +39 -0
- package/dist/components/Tabs/TabController.js.map +1 -0
- package/dist/components/Tabs/index.d.ts +5 -0
- package/dist/components/Tabs/index.d.ts.map +1 -0
- package/dist/components/Tabs/index.js +37 -0
- package/dist/components/Tabs/index.js.map +1 -0
- package/dist/components/Tabs/types.d.ts +46 -0
- package/dist/components/Tabs/types.d.ts.map +1 -0
- package/dist/components/Tabs/types.js +2 -0
- package/dist/components/Tabs/types.js.map +1 -0
- package/dist/components/Tabs/utils.d.ts +3 -0
- package/dist/components/Tabs/utils.d.ts.map +1 -0
- package/dist/components/Tabs/utils.js +5 -0
- package/dist/components/Tabs/utils.js.map +1 -0
- package/dist/components/Text.d.ts +27 -0
- package/dist/components/Text.d.ts.map +1 -0
- package/dist/components/Text.js +45 -0
- package/dist/components/Text.js.map +1 -0
- package/dist/components/Textarea.d.ts +8 -0
- package/dist/components/Textarea.d.ts.map +1 -0
- package/dist/components/Textarea.js +4 -0
- package/dist/components/Textarea.js.map +1 -0
- package/dist/components/Tooltip.d.ts +25 -0
- package/dist/components/Tooltip.d.ts.map +1 -0
- package/dist/components/Tooltip.js +18 -0
- package/dist/components/Tooltip.js.map +1 -0
- package/dist/components/layout.d.ts +46 -0
- package/dist/components/layout.d.ts.map +1 -0
- package/dist/components/layout.js +18 -0
- package/dist/components/layout.js.map +1 -0
- package/dist/context/CitricContext.d.ts +3 -0
- package/dist/context/CitricContext.d.ts.map +1 -0
- package/dist/context/CitricContext.js +3 -0
- package/dist/context/CitricContext.js.map +1 -0
- package/dist/context/CitricProvider.d.ts +9 -0
- package/dist/context/CitricProvider.d.ts.map +1 -0
- package/dist/context/CitricProvider.js +8 -0
- package/dist/context/CitricProvider.js.map +1 -0
- package/dist/context/hooks.d.ts +2 -0
- package/dist/context/hooks.d.ts.map +1 -0
- package/dist/context/hooks.js +6 -0
- package/dist/context/hooks.js.map +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/overlay.d.ts +83 -0
- package/dist/overlay.d.ts.map +1 -0
- package/dist/overlay.js +199 -0
- package/dist/overlay.js.map +1 -0
- package/dist/theme.css +419 -0
- package/dist/types.d.ts +175 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/ValueController.d.ts +10 -0
- package/dist/utils/ValueController.d.ts.map +1 -0
- package/dist/utils/ValueController.js +32 -0
- package/dist/utils/ValueController.js.map +1 -0
- package/dist/utils/acessibility.d.ts +52 -0
- package/dist/utils/acessibility.d.ts.map +1 -0
- package/dist/utils/acessibility.js +80 -0
- package/dist/utils/acessibility.js.map +1 -0
- package/dist/utils/css.d.ts +12 -0
- package/dist/utils/css.d.ts.map +1 -0
- package/dist/utils/css.js +72 -0
- package/dist/utils/css.js.map +1 -0
- package/dist/utils/options.d.ts +3 -0
- package/dist/utils/options.d.ts.map +1 -0
- package/dist/utils/options.js +7 -0
- package/dist/utils/options.js.map +1 -0
- package/package.json +51 -0
- package/scripts/build-css.ts +49 -0
- package/src/components/Accordion.tsx +74 -0
- package/src/components/Alert.tsx +16 -0
- package/src/components/AsyncContent.tsx +54 -0
- package/src/components/Avatar.tsx +34 -0
- package/src/components/AvatarGroup.tsx +40 -0
- package/src/components/Badge.tsx +28 -0
- package/src/components/Blockquote.tsx +9 -0
- package/src/components/Breadcrumb.tsx +24 -0
- package/src/components/Button.tsx +88 -0
- package/src/components/Card.tsx +32 -0
- package/src/components/Checkbox.tsx +36 -0
- package/src/components/CheckboxGroup.tsx +93 -0
- package/src/components/Circle.tsx +26 -0
- package/src/components/CitricComponent.ts +34 -0
- package/src/components/Divider.tsx +22 -0
- package/src/components/ErrorBoundary.tsx +62 -0
- package/src/components/ErrorMessage.tsx +11 -0
- package/src/components/FallbackBoundary.tsx +29 -0
- package/src/components/Favorite.tsx +37 -0
- package/src/components/FieldGroup.tsx +22 -0
- package/src/components/Form.tsx +17 -0
- package/src/components/FormGroup.tsx +45 -0
- package/src/components/IconBox.tsx +78 -0
- package/src/components/Input.tsx +32 -0
- package/src/components/Link.tsx +40 -0
- package/src/components/LoadingPanel.tsx +8 -0
- package/src/components/MenuOverlay/Menu.tsx +157 -0
- package/src/components/MenuOverlay/context.ts +20 -0
- package/src/components/MenuOverlay/index.tsx +35 -0
- package/src/components/MenuOverlay/keyboard.ts +60 -0
- package/src/components/MenuOverlay/types.ts +178 -0
- package/src/components/Overlay/context.ts +10 -0
- package/src/components/Overlay/index.tsx +137 -0
- package/src/components/Overlay/types.ts +71 -0
- package/src/components/Pagination.tsx +90 -0
- package/src/components/ProgressBar.tsx +25 -0
- package/src/components/ProgressCircular.tsx +29 -0
- package/src/components/RadioGroup.tsx +87 -0
- package/src/components/Rating.tsx +25 -0
- package/src/components/Select/RichSelect.tsx +214 -0
- package/src/components/Select/SimpleSelect.tsx +66 -0
- package/src/components/Select/index.tsx +8 -0
- package/src/components/Select/types.ts +121 -0
- package/src/components/SelectBox.tsx +134 -0
- package/src/components/Skeleton.tsx +41 -0
- package/src/components/Slider.tsx +77 -0
- package/src/components/SmartTable.tsx +148 -0
- package/src/components/Stepper.tsx +142 -0
- package/src/components/Switch.tsx +29 -0
- package/src/components/Table.tsx +219 -0
- package/src/components/Tabs/TabController.ts +40 -0
- package/src/components/Tabs/index.tsx +64 -0
- package/src/components/Tabs/types.ts +48 -0
- package/src/components/Tabs/utils.ts +6 -0
- package/src/components/Text.ts +75 -0
- package/src/components/Textarea.tsx +12 -0
- package/src/components/Tooltip.tsx +53 -0
- package/src/components/layout.tsx +53 -0
- package/src/context/CitricContext.tsx +4 -0
- package/src/context/CitricProvider.tsx +14 -0
- package/src/context/hooks.ts +6 -0
- package/src/index.ts +47 -0
- package/src/overlay.ts +276 -0
- package/src/types.ts +226 -0
- package/src/utils/ValueController.ts +28 -0
- package/src/utils/acessibility.ts +92 -0
- package/src/utils/css.ts +106 -0
- package/src/utils/options.ts +7 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { listToClass } from '@stack-spot/portal-theme';
|
|
3
|
+
import { useTranslate } from '@stack-spot/portal-translate';
|
|
4
|
+
import { createElement, useEffect, useMemo } from 'react';
|
|
5
|
+
import { ValueController } from '../../utils/ValueController.js';
|
|
6
|
+
import { CitricComponent } from '../CitricComponent.js';
|
|
7
|
+
import { IconButton } from '../IconBox.js';
|
|
8
|
+
import { useOverlayController } from '../Overlay/context.js';
|
|
9
|
+
import { MenuProvider, useMenuController, useMenuState } from './context.js';
|
|
10
|
+
import { keyboardNavigation } from './keyboard.js';
|
|
11
|
+
// Arbitrary time (ms) to wait before running a function that needs the view to be updated with the next state value.
|
|
12
|
+
const RENDER_DELAY = 20;
|
|
13
|
+
function Submenu({ children, label, className, icon, iconRight }) {
|
|
14
|
+
const controller = useMenuController();
|
|
15
|
+
return (_jsxs("button", { className: listToClass([className, 'submenu']), onClick: (e) => {
|
|
16
|
+
e.stopPropagation();
|
|
17
|
+
const menu = e.target instanceof HTMLElement ? e.target.closest('[data-citric="menu"]') : undefined;
|
|
18
|
+
controller?.setValue({ items: children, label, parent: controller?.getValue() });
|
|
19
|
+
const isOpenedWithMouse = e.detail > 0;
|
|
20
|
+
if (!isOpenedWithMouse) {
|
|
21
|
+
setTimeout(() => {
|
|
22
|
+
const firstFocusable = menu?.querySelector('a, button');
|
|
23
|
+
if (firstFocusable instanceof HTMLElement)
|
|
24
|
+
firstFocusable.focus();
|
|
25
|
+
}, RENDER_DELAY);
|
|
26
|
+
}
|
|
27
|
+
}, children: [icon, _jsx("span", { children: label }), iconRight] }));
|
|
28
|
+
}
|
|
29
|
+
function MenuSection({ children, label, className }) {
|
|
30
|
+
return (_jsxs("section", { className: className, children: [label && _jsx("h6", { children: label }), _jsx("nav", { children: _jsx(MenuItems, { items: children }) }), !label && _jsx("hr", {})] }));
|
|
31
|
+
}
|
|
32
|
+
function MenuAction({ label, active, href, icon, iconRight, className, onClick, ...props }) {
|
|
33
|
+
const overlayController = useOverlayController();
|
|
34
|
+
const children = _jsxs(_Fragment, { children: [icon, typeof label === 'string' ? _jsx("span", { children: label }) : label.element, iconRight] });
|
|
35
|
+
return createElement(href ? 'a' : 'button', {
|
|
36
|
+
href,
|
|
37
|
+
'aria-label': typeof label === 'string' ? label : label.id,
|
|
38
|
+
className: listToClass([className, active && 'active']),
|
|
39
|
+
onClick: (e) => {
|
|
40
|
+
overlayController?.close();
|
|
41
|
+
onClick?.(e);
|
|
42
|
+
},
|
|
43
|
+
...props,
|
|
44
|
+
}, children);
|
|
45
|
+
}
|
|
46
|
+
function hasSections(items) {
|
|
47
|
+
return items.some(i => 'children' in i && i.children.length && i.type === 'section');
|
|
48
|
+
}
|
|
49
|
+
function hasSubmenus(items) {
|
|
50
|
+
return items.some(i => 'children' in i && i.children.length && i.type === 'collapsible');
|
|
51
|
+
}
|
|
52
|
+
function MenuItems({ items }) {
|
|
53
|
+
return useMemo(() => items.map((item, index) => {
|
|
54
|
+
if ('children' in item && item.type === 'section')
|
|
55
|
+
return _jsx(MenuSection, { ...item }, item.label || index);
|
|
56
|
+
if ('children' in item && item.type === 'collapsible')
|
|
57
|
+
return _jsx(Submenu, { ...item }, item.label || index);
|
|
58
|
+
return _jsx(MenuAction, { ...item }, (typeof item.label === 'string' ? item.label : item.label?.id) || index);
|
|
59
|
+
}), [items]);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* TODO: make the height changes animated.
|
|
63
|
+
*/
|
|
64
|
+
export function Menu({ items, appearance, bgLevel, header, roundedItems, showBorders, showShadows, spaced, className, onKeyDown, ...props }) {
|
|
65
|
+
const controller = useMemo(() => new ValueController({ items }), []);
|
|
66
|
+
const current = useMenuState(controller);
|
|
67
|
+
const { sectioned, collapsible } = useMemo(() => ({ sectioned: hasSections(current.items), collapsible: hasSubmenus(current.items) }), [current.items]);
|
|
68
|
+
const tag = header || sectioned || collapsible ? 'div' : 'nav';
|
|
69
|
+
const t = useTranslate(dictionary);
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
if (items !== controller.getValue().items)
|
|
72
|
+
controller.setValue({ items });
|
|
73
|
+
}, [items]);
|
|
74
|
+
return (_jsx(MenuProvider, { value: controller, children: _jsxs(CitricComponent, { tag: tag, component: "menu", className: listToClass([
|
|
75
|
+
className, appearance, roundedItems && 'rounded-items', showBorders && 'bordered', showShadows === false && 'no-shadow',
|
|
76
|
+
spaced && 'spaced', bgLevel && `bg-${bgLevel}`,
|
|
77
|
+
]), onKeyDown: (e) => {
|
|
78
|
+
keyboardNavigation(e);
|
|
79
|
+
onKeyDown?.(e);
|
|
80
|
+
}, ...props, children: [header && _jsx("header", { children: header }), current.parent && (_jsxs("div", { className: "back-button", children: [_jsx(IconButton, { icon: "ArrowLeft", "aria-label": t.goBack, onClick: (e) => {
|
|
81
|
+
e.stopPropagation();
|
|
82
|
+
const menu = e.target instanceof HTMLElement ? e.target.closest('[data-citric="menu"]') : undefined;
|
|
83
|
+
if (current.parent)
|
|
84
|
+
controller.setValue(current.parent);
|
|
85
|
+
setTimeout(() => {
|
|
86
|
+
const lastItem = Array.from(menu?.querySelectorAll('a, button') ?? []).find(el => el.textContent === current.label);
|
|
87
|
+
if (lastItem instanceof HTMLElement)
|
|
88
|
+
lastItem.focus();
|
|
89
|
+
}, RENDER_DELAY);
|
|
90
|
+
} }), _jsx("span", { children: current.label || t.goBack })] })), sectioned ? _jsx(MenuItems, { items: current.items }) : _jsx("nav", { children: _jsx(MenuItems, { items: current.items }) })] }) }));
|
|
91
|
+
}
|
|
92
|
+
const dictionary = {
|
|
93
|
+
en: {
|
|
94
|
+
goBack: 'Go back',
|
|
95
|
+
},
|
|
96
|
+
pt: {
|
|
97
|
+
goBack: 'Voltar',
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=Menu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Menu.js","sourceRoot":"","sources":["../../../src/components/MenuOverlay/Menu.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ValueController } from '../../utils/ValueController.js';
|
|
2
|
+
import { MenuState } from './types.js';
|
|
3
|
+
export declare const MenuProvider: import("react").Provider<ValueController<MenuState> | undefined>;
|
|
4
|
+
export declare function useMenuController(): ValueController<MenuState> | undefined;
|
|
5
|
+
export declare function useMenuState(controller?: ValueController<MenuState>): MenuState;
|
|
6
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/components/MenuOverlay/context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAInC,eAAO,MAAM,YAAY,kEAAmB,CAAA;AAE5C,wBAAgB,iBAAiB,2CAEhC;AAED,wBAAgB,YAAY,CAAC,UAAU,CAAC,EAAE,eAAe,CAAC,SAAS,CAAC,aAOnE"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createContext, useContext, useEffect, useState } from 'react';
|
|
2
|
+
const context = createContext(undefined);
|
|
3
|
+
export const MenuProvider = context.Provider;
|
|
4
|
+
export function useMenuController() {
|
|
5
|
+
return useContext(context);
|
|
6
|
+
}
|
|
7
|
+
export function useMenuState(controller) {
|
|
8
|
+
const controllerFromContext = useMenuController();
|
|
9
|
+
controller ??= controllerFromContext;
|
|
10
|
+
if (!controller)
|
|
11
|
+
throw new Error('useMenuState used outside the context of a Menu');
|
|
12
|
+
const [state, setState] = useState(controller.getValue());
|
|
13
|
+
useEffect(() => controller.onChange(setState));
|
|
14
|
+
return state;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/components/MenuOverlay/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAItE,MAAM,OAAO,GAAG,aAAa,CAAyC,SAAS,CAAC,CAAA;AAEhF,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAA;AAE5C,MAAM,UAAU,iBAAiB;IAC/B,OAAO,UAAU,CAAC,OAAO,CAAC,CAAA;AAC5B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,UAAuC;IAClE,MAAM,qBAAqB,GAAG,iBAAiB,EAAE,CAAA;IACjD,UAAU,KAAK,qBAAqB,CAAA;IACpC,IAAI,CAAC,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAA;IACnF,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAA;IACzD,SAAS,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC9C,OAAO,KAAK,CAAA;AACd,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { MenuOverlayProps } from './types.js';
|
|
2
|
+
export declare const MenuOverlay: ({ id, items, appearance, bgLevel, header, roundedItems, showBorders, showShadows, spaced, menuClass, menuStyle, children, ...props }: MenuOverlayProps) => import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/MenuOverlay/index.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE1C,eAAO,MAAM,WAAW,GAAI,sIAEzB,gBAAgB,4CAgBlB,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslate } from '@stack-spot/portal-translate';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { IconButton } from '../IconBox.js';
|
|
5
|
+
import { Overlay } from '../Overlay/index.js';
|
|
6
|
+
import { Menu } from './Menu.js';
|
|
7
|
+
export const MenuOverlay = ({ id, items, appearance, bgLevel, header, roundedItems, showBorders, showShadows, spaced, menuClass, menuStyle, children, ...props }) => {
|
|
8
|
+
const t = useTranslate(dictionary);
|
|
9
|
+
const randomId = useMemo(() => `${Math.random()}`, []);
|
|
10
|
+
const menuProps = {
|
|
11
|
+
items, appearance, bgLevel, roundedItems, showBorders, showShadows, spaced, header, className: menuClass, style: menuStyle,
|
|
12
|
+
};
|
|
13
|
+
return (_jsx(Overlay, { content: _jsx(Menu, { ...menuProps }), attributes: { id: id || randomId, style: { margin: '8px' } }, triggerOn: "click", ...props, children: children ?? _jsx(IconButton, { icon: "EllipsisVertical", "aria-label": t.open }) }));
|
|
14
|
+
};
|
|
15
|
+
const dictionary = {
|
|
16
|
+
en: {
|
|
17
|
+
open: 'Open menu',
|
|
18
|
+
},
|
|
19
|
+
pt: {
|
|
20
|
+
open: 'Abrir menu',
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/MenuOverlay/index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAc,YAAY,EAAE,MAAM,8BAA8B,CAAA;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAG7B,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,EAC1B,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAC/G,EAAE,EAAE;IACrB,MAAM,CAAC,GAAG,YAAY,CAAC,UAAU,CAAC,CAAA;IAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;IACtD,MAAM,SAAS,GAAG;QAChB,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS;KAC3H,CAAA;IACD,OAAO,CACL,KAAC,OAAO,IACN,OAAO,EAAE,KAAC,IAAI,OAAK,SAAS,GAAI,EAChC,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,QAAQ,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAC5D,SAAS,EAAC,OAAO,KACb,KAAK,YAER,QAAQ,IAAI,KAAC,UAAU,IAAC,IAAI,EAAC,kBAAkB,gBAAa,CAAC,CAAC,IAAI,GAAI,GAC/D,CACX,CAAA;AACH,CAAC,CAAA;AAED,MAAM,UAAU,GAAG;IACjB,EAAE,EAAE;QACF,IAAI,EAAE,WAAW;KAClB;IACD,EAAE,EAAE;QACF,IAAI,EAAE,YAAY;KACnB;CACmB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../../src/components/MenuOverlay/keyboard.ts"],"names":[],"mappings":"AA8CA,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,aAAa,QAa5D"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// TODO: scroll the element into view when it's focused. Very important for accessibility in scrollable menus.
|
|
2
|
+
function getCurrent(element) {
|
|
3
|
+
return element instanceof HTMLElement
|
|
4
|
+
? element.querySelector('button:focus, a:focus')
|
|
5
|
+
: null;
|
|
6
|
+
}
|
|
7
|
+
function getMenuItems(element) {
|
|
8
|
+
return element instanceof HTMLElement ? element.querySelectorAll('button, a') : undefined;
|
|
9
|
+
}
|
|
10
|
+
function focusFirst(element) {
|
|
11
|
+
const first = getMenuItems(element)?.[0];
|
|
12
|
+
if (first instanceof HTMLElement)
|
|
13
|
+
first.focus();
|
|
14
|
+
}
|
|
15
|
+
function focusLast(element) {
|
|
16
|
+
const all = getMenuItems(element);
|
|
17
|
+
const last = all?.[all.length];
|
|
18
|
+
if (last instanceof HTMLElement)
|
|
19
|
+
last.focus();
|
|
20
|
+
}
|
|
21
|
+
function indexOf(elements, element) {
|
|
22
|
+
for (let i = 0; i < elements.length; i++) {
|
|
23
|
+
if (elements[i] === element)
|
|
24
|
+
return i;
|
|
25
|
+
}
|
|
26
|
+
return -1;
|
|
27
|
+
}
|
|
28
|
+
function focusPrevious(element, current) {
|
|
29
|
+
const all = getMenuItems(element);
|
|
30
|
+
const index = all ? indexOf(all, current) : -1;
|
|
31
|
+
if (!all || index === -1)
|
|
32
|
+
return;
|
|
33
|
+
const prev = index === 0 ? all[all.length - 1] : all[index - 1];
|
|
34
|
+
if (prev instanceof HTMLElement)
|
|
35
|
+
prev.focus();
|
|
36
|
+
}
|
|
37
|
+
function focusNext(element, current) {
|
|
38
|
+
const all = getMenuItems(element);
|
|
39
|
+
const index = all ? indexOf(all, current) : -1;
|
|
40
|
+
if (!all || index === -1)
|
|
41
|
+
return;
|
|
42
|
+
const next = index >= all.length - 1 ? all[0] : all[index + 1];
|
|
43
|
+
if (next instanceof HTMLElement)
|
|
44
|
+
next.focus();
|
|
45
|
+
}
|
|
46
|
+
export function keyboardNavigation(event) {
|
|
47
|
+
if (!['ArrowUp', 'ArrowDown'].includes(event.key))
|
|
48
|
+
return;
|
|
49
|
+
event.stopPropagation();
|
|
50
|
+
event.preventDefault();
|
|
51
|
+
const menu = event.target instanceof HTMLElement ? event.target.closest('[data-citric="menu"]') : undefined;
|
|
52
|
+
const current = getCurrent(menu);
|
|
53
|
+
if (event.key === 'ArrowUp') {
|
|
54
|
+
if (current)
|
|
55
|
+
focusPrevious(menu, current);
|
|
56
|
+
else
|
|
57
|
+
focusLast(menu);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
if (current)
|
|
61
|
+
focusNext(menu, current);
|
|
62
|
+
else
|
|
63
|
+
focusFirst(menu);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=keyboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyboard.js","sourceRoot":"","sources":["../../../src/components/MenuOverlay/keyboard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { HTMLExtension } from '../../types.js';
|
|
2
|
+
import { BaseOverlayProps } from '../Overlay/types.js';
|
|
3
|
+
interface CustomLabel {
|
|
4
|
+
/**
|
|
5
|
+
* A unique identifier for this label. This is also used to read this label to screen readers.
|
|
6
|
+
*/
|
|
7
|
+
id: string;
|
|
8
|
+
/**
|
|
9
|
+
* A custom label that can be made up of any React component.
|
|
10
|
+
*/
|
|
11
|
+
element: React.ReactNode;
|
|
12
|
+
}
|
|
13
|
+
interface Action {
|
|
14
|
+
/**
|
|
15
|
+
* The label of the action.
|
|
16
|
+
*/
|
|
17
|
+
label: string | CustomLabel;
|
|
18
|
+
/**
|
|
19
|
+
* Function to run on a click.
|
|
20
|
+
*/
|
|
21
|
+
onClick?: (event?: React.MouseEvent) => void;
|
|
22
|
+
/**
|
|
23
|
+
* URL to open on a click.
|
|
24
|
+
*/
|
|
25
|
+
href?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Target of the URL to open.
|
|
28
|
+
*/
|
|
29
|
+
target?: React.AnchorHTMLAttributes<HTMLAnchorElement>['target'];
|
|
30
|
+
/**
|
|
31
|
+
* Language of the linked document.
|
|
32
|
+
*/
|
|
33
|
+
lang?: React.AnchorHTMLAttributes<HTMLAnchorElement>['lang'];
|
|
34
|
+
/**
|
|
35
|
+
* Language of the destination URL.
|
|
36
|
+
*/
|
|
37
|
+
hrefLang?: React.AnchorHTMLAttributes<HTMLAnchorElement>['hrefLang'];
|
|
38
|
+
/**
|
|
39
|
+
* The title of the action.
|
|
40
|
+
*/
|
|
41
|
+
title?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Whether or not this link/button is disabled.
|
|
44
|
+
*
|
|
45
|
+
* @default false
|
|
46
|
+
*/
|
|
47
|
+
disabled?: boolean;
|
|
48
|
+
}
|
|
49
|
+
interface ItemWithIcon {
|
|
50
|
+
/**
|
|
51
|
+
* An Icon to appear at the left of the item.
|
|
52
|
+
*/
|
|
53
|
+
icon?: React.ReactElement;
|
|
54
|
+
/**
|
|
55
|
+
* An Icon to appear at the right of the item.
|
|
56
|
+
*/
|
|
57
|
+
iconRight?: React.ReactElement;
|
|
58
|
+
}
|
|
59
|
+
export interface ListAction extends ItemWithIcon, Action {
|
|
60
|
+
/**
|
|
61
|
+
* Whether or not this option is currently active.
|
|
62
|
+
*/
|
|
63
|
+
active?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* A class to be added to this item.
|
|
66
|
+
*/
|
|
67
|
+
className?: string;
|
|
68
|
+
}
|
|
69
|
+
interface ListGroup {
|
|
70
|
+
/**
|
|
71
|
+
* If this group is rendered as a section with its items right below it or a collapsible, which requires a click to open a submenu.
|
|
72
|
+
*/
|
|
73
|
+
type?: 'section' | 'collapsible';
|
|
74
|
+
/**
|
|
75
|
+
* The items of this group.
|
|
76
|
+
*/
|
|
77
|
+
children: ListItem[];
|
|
78
|
+
/**
|
|
79
|
+
* A class to be added to this item.
|
|
80
|
+
*/
|
|
81
|
+
className?: string;
|
|
82
|
+
}
|
|
83
|
+
export interface ListSection extends ListGroup {
|
|
84
|
+
type: 'section';
|
|
85
|
+
/**
|
|
86
|
+
* The section's title.
|
|
87
|
+
*/
|
|
88
|
+
label?: string;
|
|
89
|
+
}
|
|
90
|
+
export interface ListCollapsible extends ListGroup, ItemWithIcon {
|
|
91
|
+
type?: 'collapsible';
|
|
92
|
+
/**
|
|
93
|
+
* The title of the collapsible menu.
|
|
94
|
+
*/
|
|
95
|
+
label: string;
|
|
96
|
+
}
|
|
97
|
+
export type ListItem = ListSection | ListCollapsible | ListAction;
|
|
98
|
+
export interface MenuState {
|
|
99
|
+
items: ListItem[];
|
|
100
|
+
parent?: MenuState;
|
|
101
|
+
label?: string;
|
|
102
|
+
}
|
|
103
|
+
export interface BaseMenuProps {
|
|
104
|
+
/**
|
|
105
|
+
* The options in the selection list.
|
|
106
|
+
*/
|
|
107
|
+
items: ListItem[];
|
|
108
|
+
/**
|
|
109
|
+
* A header for the menu.
|
|
110
|
+
*/
|
|
111
|
+
header?: React.ReactNode;
|
|
112
|
+
/**
|
|
113
|
+
* Whether or not to render spaces between the items and the sides of the menu.
|
|
114
|
+
*
|
|
115
|
+
* @default false
|
|
116
|
+
*/
|
|
117
|
+
spaced?: boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Wheter or not to render borders.
|
|
120
|
+
*
|
|
121
|
+
* @default false
|
|
122
|
+
*/
|
|
123
|
+
showBorders?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Whether or not to use rounded corners for each menu item.
|
|
126
|
+
*
|
|
127
|
+
* @default false
|
|
128
|
+
*/
|
|
129
|
+
roundedItems?: boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Use 'square' for sharp corners and 'circle' for rounded corners.
|
|
132
|
+
*
|
|
133
|
+
* @default 'circle'
|
|
134
|
+
*/
|
|
135
|
+
appearance?: 'square' | 'circle';
|
|
136
|
+
/**
|
|
137
|
+
* The level of the background color. Use this to lighten or darken the background.
|
|
138
|
+
*
|
|
139
|
+
* @default 300
|
|
140
|
+
*/
|
|
141
|
+
bgLevel?: 300 | 400 | 500 | 600;
|
|
142
|
+
/**
|
|
143
|
+
* Whether or not to render shadows behind the menu.
|
|
144
|
+
*
|
|
145
|
+
* @default true
|
|
146
|
+
*/
|
|
147
|
+
showShadows?: boolean;
|
|
148
|
+
/**
|
|
149
|
+
* A class for the menu element.
|
|
150
|
+
*/
|
|
151
|
+
menuClass?: string;
|
|
152
|
+
/**
|
|
153
|
+
* Styles for the menu element.
|
|
154
|
+
*/
|
|
155
|
+
menuStyle?: React.CSSProperties;
|
|
156
|
+
}
|
|
157
|
+
export type MenuProps = HTMLExtension<'div', BaseMenuProps, 'children'>;
|
|
158
|
+
export interface BaseMenuOverlayProps extends BaseMenuProps, Omit<BaseOverlayProps<'div'>, 'tag' | 'onRenderChild' | 'content' | 'triggerOn' | 'reference'> {
|
|
159
|
+
/**
|
|
160
|
+
* A unique id for this menu. If not provided, a random number will be used.
|
|
161
|
+
*/
|
|
162
|
+
id?: string;
|
|
163
|
+
}
|
|
164
|
+
export type MenuOverlayProps = HTMLExtension<'div', BaseMenuOverlayProps>;
|
|
165
|
+
export {};
|
|
166
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/MenuOverlay/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/components/MenuOverlay/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/components/Overlay/context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAI3C,eAAO,MAAM,eAAe,yDAAmB,CAAA;AAE/C,wBAAgB,oBAAoB,kCAEnC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/components/Overlay/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAGjD,MAAM,OAAO,GAAG,aAAa,CAAgC,SAAS,CAAC,CAAA;AAEvE,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAA;AAE/C,MAAM,UAAU,oBAAoB;IAClC,OAAO,UAAU,CAAC,OAAO,CAAC,CAAA;AAC5B,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { OverlayProps } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* These todos are in order of priority.
|
|
4
|
+
*
|
|
5
|
+
* TODO: update position when the size changes. Currently, the top position seems out of place whenever the height changes. The same is
|
|
6
|
+
* probably true for the left position if the width changes.
|
|
7
|
+
* TODO: hoverDelayMS
|
|
8
|
+
* TODO: reposition the overlay when it's under a scrollable element other then the body and this element is scrolled.
|
|
9
|
+
* TODO: close the overlay when it's under a scrollable element other then the body and the element that triggered the tooltip becomes
|
|
10
|
+
* hidden by the scroll.
|
|
11
|
+
* TODO: use React Portal to implement overlays. The current implementation will lose every React context in the tree.
|
|
12
|
+
*/
|
|
13
|
+
export declare function Overlay<T extends keyof React.JSX.IntrinsicElements>({ tag, children, content, position, triggerOn, attributes, onRenderChild, autoFocusBehavior, ...props }: OverlayProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Overlay/index.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAqB,YAAY,EAAE,MAAM,SAAS,CAAA;AAEzD;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,KAAK,CAAC,GAAG,CAAC,iBAAiB,EAAE,EACnE,GAAG,EACH,QAAQ,EACR,OAAO,EACP,QAAgB,EAChB,SAAmB,EACnB,UAAU,EACV,aAAa,EACb,iBAA8B,EAC9B,GAAG,KAAK,EACT,EAAE,YAAY,CAAC,CAAC,CAAC,2CA6GjB"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
import { showOverlay } from '../../overlay.js';
|
|
4
|
+
import { focusFirstChild } from '../../utils/acessibility.js';
|
|
5
|
+
import { OverlayProvider } from './context.js';
|
|
6
|
+
/**
|
|
7
|
+
* These todos are in order of priority.
|
|
8
|
+
*
|
|
9
|
+
* TODO: update position when the size changes. Currently, the top position seems out of place whenever the height changes. The same is
|
|
10
|
+
* probably true for the left position if the width changes.
|
|
11
|
+
* TODO: hoverDelayMS
|
|
12
|
+
* TODO: reposition the overlay when it's under a scrollable element other then the body and this element is scrolled.
|
|
13
|
+
* TODO: close the overlay when it's under a scrollable element other then the body and the element that triggered the tooltip becomes
|
|
14
|
+
* hidden by the scroll.
|
|
15
|
+
* TODO: use React Portal to implement overlays. The current implementation will lose every React context in the tree.
|
|
16
|
+
*/
|
|
17
|
+
export function Overlay({ tag, children, content, position = 'top', triggerOn = 'hover', attributes, onRenderChild, autoFocusBehavior = 'keyboard', ...props }) {
|
|
18
|
+
const controller = useRef({ close: () => Promise.resolve() });
|
|
19
|
+
const wrapper = useRef(null);
|
|
20
|
+
// props that don't require removing and reattaching the event listeners
|
|
21
|
+
const dynamic = useRef({ tag, content, position, attributes });
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
dynamic.current = { tag, content, position, attributes };
|
|
24
|
+
}, [tag, content, position, attributes]);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
let visible = false;
|
|
27
|
+
let hideOnClickOutside;
|
|
28
|
+
let hideOnEsc;
|
|
29
|
+
let hideOverlay;
|
|
30
|
+
let removeRefocusTargetListener;
|
|
31
|
+
function getTarget() {
|
|
32
|
+
const target = wrapper.current?.firstChild;
|
|
33
|
+
return target instanceof HTMLElement ? target : undefined;
|
|
34
|
+
}
|
|
35
|
+
if (onRenderChild) {
|
|
36
|
+
const target = getTarget();
|
|
37
|
+
if (target)
|
|
38
|
+
onRenderChild(target);
|
|
39
|
+
}
|
|
40
|
+
async function show(event) {
|
|
41
|
+
if (visible)
|
|
42
|
+
return;
|
|
43
|
+
visible = true;
|
|
44
|
+
const target = getTarget();
|
|
45
|
+
if (!target)
|
|
46
|
+
return;
|
|
47
|
+
const { overlay, hide: hideFn } = showOverlay({
|
|
48
|
+
tag: dynamic.current.tag,
|
|
49
|
+
content: ['string', 'number', 'boolean'].includes(typeof dynamic.current.content)
|
|
50
|
+
? dynamic.current.content
|
|
51
|
+
: _jsx(OverlayProvider, { value: controller.current, children: dynamic.current.content }),
|
|
52
|
+
target,
|
|
53
|
+
position: dynamic.current.position,
|
|
54
|
+
attributes: dynamic.current.attributes,
|
|
55
|
+
});
|
|
56
|
+
hideOverlay = hideFn;
|
|
57
|
+
function onHide(condition) {
|
|
58
|
+
return (event) => {
|
|
59
|
+
if (condition(event))
|
|
60
|
+
controller.current.close();
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (event.type === 'click') {
|
|
64
|
+
event.stopPropagation();
|
|
65
|
+
hideOnClickOutside = onHide(e => e instanceof MouseEvent && e.button === 0 && !overlay.contains(e.target));
|
|
66
|
+
hideOnEsc = onHide(e => e instanceof KeyboardEvent && e.key === 'Escape');
|
|
67
|
+
document.addEventListener('click', hideOnClickOutside);
|
|
68
|
+
document.addEventListener('keydown', hideOnEsc);
|
|
69
|
+
}
|
|
70
|
+
//focus target when the last overlay element loses focus
|
|
71
|
+
function refocusTarget(e) {
|
|
72
|
+
if (e.key === 'Tab' && e.target instanceof HTMLElement) {
|
|
73
|
+
const allItems = Array.from(e.target.closest('[data-citric="menu"]')?.querySelectorAll('a, button') ?? []);
|
|
74
|
+
if (e.target === allItems[allItems.length - 1]) {
|
|
75
|
+
getTarget()?.focus();
|
|
76
|
+
e.preventDefault();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
overlay.addEventListener('keydown', refocusTarget);
|
|
81
|
+
removeRefocusTargetListener = () => overlay.removeEventListener('keydown', refocusTarget);
|
|
82
|
+
// auto-focus
|
|
83
|
+
const openedWithMouse = event instanceof MouseEvent && event.detail > 0;
|
|
84
|
+
if (autoFocusBehavior === 'always' || (autoFocusBehavior === 'keyboard' && !openedWithMouse)) {
|
|
85
|
+
setTimeout(() => focusFirstChild(overlay), 20);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
controller.current.close = async () => {
|
|
89
|
+
visible = false;
|
|
90
|
+
if (hideOnClickOutside)
|
|
91
|
+
document.removeEventListener('click', hideOnClickOutside);
|
|
92
|
+
if (hideOnEsc)
|
|
93
|
+
document.removeEventListener('keydown', hideOnEsc);
|
|
94
|
+
removeRefocusTargetListener?.();
|
|
95
|
+
await hideOverlay?.();
|
|
96
|
+
};
|
|
97
|
+
if (triggerOn === 'hover') {
|
|
98
|
+
getTarget()?.addEventListener('mouseenter', show);
|
|
99
|
+
getTarget()?.addEventListener('mouseleave', controller.current.close);
|
|
100
|
+
getTarget()?.addEventListener('focus', show);
|
|
101
|
+
getTarget()?.addEventListener('blur', controller.current.close);
|
|
102
|
+
return () => {
|
|
103
|
+
getTarget()?.removeEventListener('mouseenter', show);
|
|
104
|
+
getTarget()?.removeEventListener('mouseleave', controller.current.close);
|
|
105
|
+
getTarget()?.removeEventListener('focus', show);
|
|
106
|
+
getTarget()?.removeEventListener('blur', controller.current.close);
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (triggerOn === 'click') {
|
|
110
|
+
getTarget()?.addEventListener('click', show);
|
|
111
|
+
return () => {
|
|
112
|
+
getTarget()?.removeEventListener('click', show);
|
|
113
|
+
if (hideOnClickOutside)
|
|
114
|
+
document.removeEventListener('click', hideOnClickOutside);
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}, [wrapper.current, triggerOn]);
|
|
118
|
+
return _jsx("div", { ref: wrapper, ...props, children: children });
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Overlay/index.tsx"],"names":[],"mappings":"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"}
|