Jesus sucks

This commit is contained in:
2024-12-17 13:23:11 -08:00
parent 3a3382ffff
commit b2dbf46d28
13060 changed files with 1310035 additions and 1 deletions

View File

@@ -0,0 +1,14 @@
import * as React from 'react';
export declare function isTrivialHref(href?: string): boolean;
export interface AnchorProps extends React.HTMLAttributes<HTMLElement> {
href?: string;
disabled?: boolean;
role?: string;
tabIndex?: number;
}
/**
* An generic `<a>` component that covers a few A11y cases, ensuring that
* cases where the `href` is missing or trivial like "#" are treated like buttons.
*/
declare const Anchor: React.ForwardRefExoticComponent<AnchorProps & React.RefAttributes<HTMLAnchorElement>>;
export default Anchor;

View File

@@ -0,0 +1,43 @@
const _excluded = ["onKeyDown"];
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/anchor-has-content */
import * as React from 'react';
import { useEventCallback } from '@restart/hooks';
import { useButtonProps } from './Button';
import { jsx as _jsx } from "react/jsx-runtime";
export function isTrivialHref(href) {
return !href || href.trim() === '#';
}
/**
* An generic `<a>` component that covers a few A11y cases, ensuring that
* cases where the `href` is missing or trivial like "#" are treated like buttons.
*/
const Anchor = /*#__PURE__*/React.forwardRef((_ref, ref) => {
let {
onKeyDown
} = _ref,
props = _objectWithoutPropertiesLoose(_ref, _excluded);
const [buttonProps] = useButtonProps(Object.assign({
tagName: 'a'
}, props));
const handleKeyDown = useEventCallback(e => {
buttonProps.onKeyDown(e);
onKeyDown == null ? void 0 : onKeyDown(e);
});
if (isTrivialHref(props.href) || props.role === 'button') {
return /*#__PURE__*/_jsx("a", Object.assign({
ref: ref
}, props, buttonProps, {
onKeyDown: handleKeyDown
}));
}
return /*#__PURE__*/_jsx("a", Object.assign({
ref: ref
}, props, {
onKeyDown: onKeyDown
}));
});
Anchor.displayName = 'Anchor';
export default Anchor;

View File

@@ -0,0 +1,50 @@
import * as React from 'react';
export type ButtonType = 'button' | 'reset' | 'submit';
export interface AnchorOptions {
href?: string;
rel?: string;
target?: string;
}
export interface UseButtonPropsOptions extends AnchorOptions {
type?: ButtonType;
disabled?: boolean;
onClick?: React.EventHandler<React.MouseEvent | React.KeyboardEvent>;
tabIndex?: number;
tagName?: keyof JSX.IntrinsicElements;
role?: React.AriaRole | undefined;
}
export declare function isTrivialHref(href?: string): boolean;
export interface AriaButtonProps {
type?: ButtonType | undefined;
disabled: boolean | undefined;
role?: React.AriaRole;
tabIndex?: number | undefined;
href?: string | undefined;
target?: string | undefined;
rel?: string | undefined;
'aria-disabled'?: true | undefined;
onClick?: (event: React.MouseEvent | React.KeyboardEvent) => void;
onKeyDown?: (event: React.KeyboardEvent) => void;
}
export interface UseButtonPropsMetadata {
tagName: React.ElementType;
}
export declare function useButtonProps({ tagName, disabled, href, target, rel, role, onClick, tabIndex, type, }: UseButtonPropsOptions): [AriaButtonProps, UseButtonPropsMetadata];
export interface BaseButtonProps {
/**
* Control the underlying rendered element directly by passing in a valid
* component type
*/
as?: keyof JSX.IntrinsicElements | undefined;
/** The disabled state of the button */
disabled?: boolean | undefined;
/** Optionally specify an href to render a `<a>` tag styled as a button */
href?: string | undefined;
/** Anchor target, when rendering an anchor as a button */
target?: string | undefined;
rel?: string | undefined;
}
export interface ButtonProps extends BaseButtonProps, React.ComponentPropsWithoutRef<'button'> {
}
declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLElement>>;
export default Button;

View File

@@ -0,0 +1,89 @@
const _excluded = ["as", "disabled"];
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
import * as React from 'react';
import { jsx as _jsx } from "react/jsx-runtime";
export function isTrivialHref(href) {
return !href || href.trim() === '#';
}
export function useButtonProps({
tagName,
disabled,
href,
target,
rel,
role,
onClick,
tabIndex = 0,
type
}) {
if (!tagName) {
if (href != null || target != null || rel != null) {
tagName = 'a';
} else {
tagName = 'button';
}
}
const meta = {
tagName
};
if (tagName === 'button') {
return [{
type: type || 'button',
disabled
}, meta];
}
const handleClick = event => {
if (disabled || tagName === 'a' && isTrivialHref(href)) {
event.preventDefault();
}
if (disabled) {
event.stopPropagation();
return;
}
onClick == null ? void 0 : onClick(event);
};
const handleKeyDown = event => {
if (event.key === ' ') {
event.preventDefault();
handleClick(event);
}
};
if (tagName === 'a') {
// Ensure there's a href so Enter can trigger anchor button.
href || (href = '#');
if (disabled) {
href = undefined;
}
}
return [{
role: role != null ? role : 'button',
// explicitly undefined so that it overrides the props disabled in a spread
// e.g. <Tag {...props} {...hookProps} />
disabled: undefined,
tabIndex: disabled ? undefined : tabIndex,
href,
target: tagName === 'a' ? target : undefined,
'aria-disabled': !disabled ? undefined : disabled,
rel: tagName === 'a' ? rel : undefined,
onClick: handleClick,
onKeyDown: handleKeyDown
}, meta];
}
const Button = /*#__PURE__*/React.forwardRef((_ref, ref) => {
let {
as: asProp,
disabled
} = _ref,
props = _objectWithoutPropertiesLoose(_ref, _excluded);
const [buttonProps, {
tagName: Component
}] = useButtonProps(Object.assign({
tagName: asProp,
disabled
}, props));
return /*#__PURE__*/_jsx(Component, Object.assign({}, props, buttonProps, {
ref: ref
}));
});
Button.displayName = 'Button';
export default Button;

View File

@@ -0,0 +1,4 @@
export declare const ATTRIBUTE_PREFIX: "data-rr-ui-";
export declare const PROPERTY_PREFIX: "rrUi";
export declare function dataAttr<T extends string>(property: T): `data-rr-ui-${T}`;
export declare function dataProp<T extends string>(property: T): `rrUi${T}`;

View File

@@ -0,0 +1,8 @@
export const ATTRIBUTE_PREFIX = `data-rr-ui-`;
export const PROPERTY_PREFIX = `rrUi`;
export function dataAttr(property) {
return `${ATTRIBUTE_PREFIX}${property}`;
}
export function dataProp(property) {
return `${PROPERTY_PREFIX}${property}`;
}

View File

@@ -0,0 +1,93 @@
import * as React from 'react';
import DropdownMenu, { DropdownMenuProps, UseDropdownMenuMetadata, UseDropdownMenuOptions } from './DropdownMenu';
import DropdownToggle, { DropdownToggleProps, UseDropdownToggleMetadata } from './DropdownToggle';
import { DropdownItemProps } from './DropdownItem';
import { SelectCallback } from './types';
import { Placement } from './usePopper';
export type { DropdownMenuProps, UseDropdownMenuMetadata, UseDropdownMenuOptions, DropdownToggleProps, UseDropdownToggleMetadata, DropdownItemProps, };
export interface DropdownInjectedProps {
onKeyDown: React.KeyboardEventHandler;
}
export type ToggleEvent = React.SyntheticEvent | KeyboardEvent | MouseEvent;
export interface ToggleMetadata {
source: string | undefined;
originalEvent: ToggleEvent | undefined;
}
export interface DropdownProps {
/**
* The PopperJS placement for positioning the Dropdown menu in relation to
* its Toggle.
*
* @default 'bottom-start'
*/
placement?: Placement;
/**
* Sets the initial visibility of the Dropdown.
*/
defaultShow?: boolean;
/**
* Whether or not the Dropdown is visible.
*
* @controllable onToggle
*/
show?: boolean;
/**
* A callback fired when a DropdownItem has been selected.
*/
onSelect?: SelectCallback;
/**
* A callback fired when the Dropdown wishes to change visibility. Called with
* the requested `show` value, the DOM event, and the source that fired it:
* `'click'`,`'keydown'`,`'rootClose'`, or `'select'`.
*
* ```ts static
* function(
* nextShow: boolean,
* meta: ToggleMetadata,
* ): void
* ```
*
* @controllable show
*/
onToggle?: (nextShow: boolean, meta: ToggleMetadata) => void;
/**
* A css selector string that will return __focusable__ menu items.
* Selectors should be relative to the menu component:
* e.g. ` > li:not('.disabled')`
*/
itemSelector?: string;
/**
* Controls the focus behavior for when the Dropdown is opened. Set to
* `true` to always focus the first menu item, `keyboard` to focus only when
* navigating via the keyboard, or `false` to disable completely
*
* The Default behavior is `false` **unless** the Menu has a `role="menu"`
* where it will default to `keyboard` to match the recommended [ARIA Authoring
* practices](https://www.w3.org/TR/wai-aria-practices-1.1/#menubutton).
*/
focusFirstItemOnShow?: boolean | 'keyboard';
/**
* A render prop that returns the root dropdown element. The `props`
* argument should spread through to an element containing _both_ the
* menu and toggle in order to handle keyboard events for focus management.
*
* @type {Function ({
* props: {
* onKeyDown: (SyntheticEvent) => void,
* },
* }) => React.Element}
*/
children: React.ReactNode;
}
/**
* @displayName Dropdown
* @public
*/
declare function Dropdown({ defaultShow, show: rawShow, onSelect, onToggle: rawOnToggle, itemSelector, focusFirstItemOnShow, placement, children, }: DropdownProps): React.JSX.Element;
declare namespace Dropdown {
var displayName: string;
var Menu: typeof DropdownMenu;
var Toggle: typeof DropdownToggle;
var Item: import("./types").DynamicRefForwardingComponent<React.ForwardRefExoticComponent<import("./Button").ButtonProps & React.RefAttributes<HTMLElement>>, DropdownItemProps>;
}
export default Dropdown;

View File

@@ -0,0 +1,195 @@
import qsa from 'dom-helpers/querySelectorAll';
import addEventListener from 'dom-helpers/addEventListener';
import { useCallback, useRef, useEffect, useMemo, useContext } from 'react';
import * as React from 'react';
import { useUncontrolledProp } from 'uncontrollable';
import usePrevious from '@restart/hooks/usePrevious';
import useForceUpdate from '@restart/hooks/useForceUpdate';
import useEventListener from '@restart/hooks/useEventListener';
import useEventCallback from '@restart/hooks/useEventCallback';
import DropdownContext from './DropdownContext';
import DropdownMenu from './DropdownMenu';
import DropdownToggle, { isRoleMenu } from './DropdownToggle';
import DropdownItem from './DropdownItem';
import SelectableContext from './SelectableContext';
import { dataAttr } from './DataKey';
import useWindow from './useWindow';
import { jsx as _jsx } from "react/jsx-runtime";
function useRefWithUpdate() {
const forceUpdate = useForceUpdate();
const ref = useRef(null);
const attachRef = useCallback(element => {
ref.current = element;
// ensure that a menu set triggers an update for consumers
forceUpdate();
}, [forceUpdate]);
return [ref, attachRef];
}
/**
* @displayName Dropdown
* @public
*/
function Dropdown({
defaultShow,
show: rawShow,
onSelect,
onToggle: rawOnToggle,
itemSelector = `* [${dataAttr('dropdown-item')}]`,
focusFirstItemOnShow,
placement = 'bottom-start',
children
}) {
const window = useWindow();
const [show, onToggle] = useUncontrolledProp(rawShow, defaultShow, rawOnToggle);
// We use normal refs instead of useCallbackRef in order to populate the
// the value as quickly as possible, otherwise the effect to focus the element
// may run before the state value is set
const [menuRef, setMenu] = useRefWithUpdate();
const menuElement = menuRef.current;
const [toggleRef, setToggle] = useRefWithUpdate();
const toggleElement = toggleRef.current;
const lastShow = usePrevious(show);
const lastSourceEvent = useRef(null);
const focusInDropdown = useRef(false);
const onSelectCtx = useContext(SelectableContext);
const toggle = useCallback((nextShow, event, source = event == null ? void 0 : event.type) => {
onToggle(nextShow, {
originalEvent: event,
source
});
}, [onToggle]);
const handleSelect = useEventCallback((key, event) => {
onSelect == null ? void 0 : onSelect(key, event);
toggle(false, event, 'select');
if (!event.isPropagationStopped()) {
onSelectCtx == null ? void 0 : onSelectCtx(key, event);
}
});
const context = useMemo(() => ({
toggle,
placement,
show,
menuElement,
toggleElement,
setMenu,
setToggle
}), [toggle, placement, show, menuElement, toggleElement, setMenu, setToggle]);
if (menuElement && lastShow && !show) {
focusInDropdown.current = menuElement.contains(menuElement.ownerDocument.activeElement);
}
const focusToggle = useEventCallback(() => {
if (toggleElement && toggleElement.focus) {
toggleElement.focus();
}
});
const maybeFocusFirst = useEventCallback(() => {
const type = lastSourceEvent.current;
let focusType = focusFirstItemOnShow;
if (focusType == null) {
focusType = menuRef.current && isRoleMenu(menuRef.current) ? 'keyboard' : false;
}
if (focusType === false || focusType === 'keyboard' && !/^key.+$/.test(type)) {
return;
}
const first = qsa(menuRef.current, itemSelector)[0];
if (first && first.focus) first.focus();
});
useEffect(() => {
if (show) maybeFocusFirst();else if (focusInDropdown.current) {
focusInDropdown.current = false;
focusToggle();
}
// only `show` should be changing
}, [show, focusInDropdown, focusToggle, maybeFocusFirst]);
useEffect(() => {
lastSourceEvent.current = null;
});
const getNextFocusedChild = (current, offset) => {
if (!menuRef.current) return null;
const items = qsa(menuRef.current, itemSelector);
let index = items.indexOf(current) + offset;
index = Math.max(0, Math.min(index, items.length));
return items[index];
};
useEventListener(useCallback(() => window.document, [window]), 'keydown', event => {
var _menuRef$current, _toggleRef$current;
const {
key
} = event;
const target = event.target;
const fromMenu = (_menuRef$current = menuRef.current) == null ? void 0 : _menuRef$current.contains(target);
const fromToggle = (_toggleRef$current = toggleRef.current) == null ? void 0 : _toggleRef$current.contains(target);
// Second only to https://github.com/twbs/bootstrap/blob/8cfbf6933b8a0146ac3fbc369f19e520bd1ebdac/js/src/dropdown.js#L400
// in inscrutability
const isInput = /input|textarea/i.test(target.tagName);
if (isInput && (key === ' ' || key !== 'Escape' && fromMenu || key === 'Escape' && target.type === 'search')) {
return;
}
if (!fromMenu && !fromToggle) {
return;
}
if (key === 'Tab' && (!menuRef.current || !show)) {
return;
}
lastSourceEvent.current = event.type;
const meta = {
originalEvent: event,
source: event.type
};
switch (key) {
case 'ArrowUp':
{
const next = getNextFocusedChild(target, -1);
if (next && next.focus) next.focus();
event.preventDefault();
return;
}
case 'ArrowDown':
event.preventDefault();
if (!show) {
onToggle(true, meta);
} else {
const next = getNextFocusedChild(target, 1);
if (next && next.focus) next.focus();
}
return;
case 'Tab':
// on keydown the target is the element being tabbed FROM, we need that
// to know if this event is relevant to this dropdown (e.g. in this menu).
// On `keyup` the target is the element being tagged TO which we use to check
// if focus has left the menu
addEventListener(target.ownerDocument, 'keyup', e => {
var _menuRef$current2;
if (e.key === 'Tab' && !e.target || !((_menuRef$current2 = menuRef.current) != null && _menuRef$current2.contains(e.target))) {
onToggle(false, meta);
}
}, {
once: true
});
break;
case 'Escape':
if (key === 'Escape') {
event.preventDefault();
event.stopPropagation();
}
onToggle(false, meta);
break;
default:
}
});
return /*#__PURE__*/_jsx(SelectableContext.Provider, {
value: handleSelect,
children: /*#__PURE__*/_jsx(DropdownContext.Provider, {
value: context,
children: children
})
});
}
Dropdown.displayName = 'Dropdown';
Dropdown.Menu = DropdownMenu;
Dropdown.Toggle = DropdownToggle;
Dropdown.Item = DropdownItem;
export default Dropdown;

View File

@@ -0,0 +1,13 @@
import * as React from 'react';
import type { Placement } from './usePopper';
export type DropdownContextValue = {
toggle: (nextShow: boolean, event?: React.SyntheticEvent | Event) => void;
menuElement: HTMLElement | null;
toggleElement: HTMLElement | null;
setMenu: (ref: HTMLElement | null) => void;
setToggle: (ref: HTMLElement | null) => void;
show: boolean;
placement?: Placement;
};
declare const DropdownContext: React.Context<DropdownContextValue | null>;
export default DropdownContext;

View File

@@ -0,0 +1,3 @@
import * as React from 'react';
const DropdownContext = /*#__PURE__*/React.createContext(null);
export default DropdownContext;

View File

@@ -0,0 +1,46 @@
import * as React from 'react';
import { EventKey, DynamicRefForwardingComponent } from './types';
import Button from './Button';
export interface DropdownItemProps extends React.HTMLAttributes<HTMLElement> {
/**
* Element used to render the component.
*/
as?: React.ElementType;
/**
* Highlight the menu item as active.
*/
active?: boolean;
/**
* Disable the menu item, making it unselectable.
*/
disabled?: boolean;
/**
* Value passed to the `onSelect` handler, useful for identifying the selected menu item.
*/
eventKey?: EventKey;
/**
* HTML `href` attribute corresponding to `a.href`.
*/
href?: string;
}
interface UseDropdownItemOptions {
key?: EventKey | null;
href?: string;
active?: boolean;
disabled?: boolean;
onClick?: React.MouseEventHandler;
}
/**
* Create a dropdown item. Returns a set of props for the dropdown item component
* including an `onClick` handler that prevents selection when the item is disabled
*/
export declare function useDropdownItem({ key, href, active, disabled, onClick, }: UseDropdownItemOptions): readonly [{
readonly onClick: (event: any) => void;
readonly 'aria-disabled': true | undefined;
readonly 'aria-selected': boolean | undefined;
readonly "data-rr-ui-dropdown-item": "";
}, {
readonly isActive: boolean | undefined;
}];
declare const DropdownItem: DynamicRefForwardingComponent<typeof Button, DropdownItemProps>;
export default DropdownItem;

View File

@@ -0,0 +1,66 @@
const _excluded = ["eventKey", "disabled", "onClick", "active", "as"];
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
import * as React from 'react';
import { useContext } from 'react';
import useEventCallback from '@restart/hooks/useEventCallback';
import SelectableContext, { makeEventKey } from './SelectableContext';
import NavContext from './NavContext';
import Button from './Button';
import { dataAttr } from './DataKey';
import { jsx as _jsx } from "react/jsx-runtime";
/**
* Create a dropdown item. Returns a set of props for the dropdown item component
* including an `onClick` handler that prevents selection when the item is disabled
*/
export function useDropdownItem({
key,
href,
active,
disabled,
onClick
}) {
const onSelectCtx = useContext(SelectableContext);
const navContext = useContext(NavContext);
const {
activeKey
} = navContext || {};
const eventKey = makeEventKey(key, href);
const isActive = active == null && key != null ? makeEventKey(activeKey) === eventKey : active;
const handleClick = useEventCallback(event => {
if (disabled) return;
onClick == null ? void 0 : onClick(event);
if (onSelectCtx && !event.isPropagationStopped()) {
onSelectCtx(eventKey, event);
}
});
return [{
onClick: handleClick,
'aria-disabled': disabled || undefined,
'aria-selected': isActive,
[dataAttr('dropdown-item')]: ''
}, {
isActive
}];
}
const DropdownItem = /*#__PURE__*/React.forwardRef((_ref, ref) => {
let {
eventKey,
disabled,
onClick,
active,
as: Component = Button
} = _ref,
props = _objectWithoutPropertiesLoose(_ref, _excluded);
const [dropdownItemProps] = useDropdownItem({
key: eventKey,
href: props.href,
disabled,
onClick,
active
});
return /*#__PURE__*/_jsx(Component, Object.assign({}, props, {
ref: ref
}, dropdownItemProps));
});
DropdownItem.displayName = 'DropdownItem';
export default DropdownItem;

View File

@@ -0,0 +1,117 @@
import * as React from 'react';
import { DropdownContextValue } from './DropdownContext';
import { UsePopperOptions, Placement, Offset, UsePopperState } from './usePopper';
import { ClickOutsideOptions } from './useClickOutside';
export interface UseDropdownMenuOptions {
/**
* Enables the Popper.js `flip` modifier, allowing the Dropdown to
* automatically adjust it's placement in case of overlap with the viewport or
* toggle. See the [flip docs](https://popper.js.org/docs/v2/modifiers/flip/)
* for more info.
*/
flip?: boolean;
/**
* Controls the visible state of the menu, generally this is provided by the
* parent `Dropdown` component, but may also be specified as a prop directly.
*/
show?: boolean;
/**
* Use the `fixed` positioning strategy in Popper. This is used if the
* dropdown toggle is in a fixed container.
*/
fixed?: boolean;
/**
* The PopperJS placement for positioning the Dropdown menu in relation to it's Toggle.
* Generally this is provided by the parent `Dropdown` component,
* but may also be specified as a prop directly.
*/
placement?: Placement;
/**
* Whether or not to use Popper for positioning the menu.
*/
usePopper?: boolean;
/**
* Whether or not to add scroll and resize listeners to update menu position.
*
* See the [event listeners docs](https://popper.js.org/docs/v2/modifiers/event-listeners/)
* for more info.
*/
enableEventListeners?: boolean;
/**
* Offset of the dropdown menu from the dropdown toggle. See the
* [offset docs](https://popper.js.org/docs/v2/modifiers/offset/) for more info.
*/
offset?: Offset;
/**
* Override the default event used by RootCloseWrapper.
*/
rootCloseEvent?: ClickOutsideOptions['clickTrigger'];
/**
* A set of popper options and props passed directly to react-popper's Popper component.
*/
popperConfig?: Omit<UsePopperOptions, 'enabled' | 'placement'>;
}
export type UserDropdownMenuProps = Record<string, any> & {
ref: React.RefCallback<HTMLElement>;
style?: React.CSSProperties;
'aria-labelledby'?: string;
};
export type UserDropdownMenuArrowProps = Record<string, any> & {
ref: React.RefCallback<HTMLElement>;
style: React.CSSProperties;
};
export interface UseDropdownMenuMetadata {
show: boolean;
placement?: Placement;
hasShown: boolean;
toggle?: DropdownContextValue['toggle'];
popper: UsePopperState | null;
arrowProps: Partial<UserDropdownMenuArrowProps>;
}
/**
* @memberOf Dropdown
* @param {object} options
* @param {boolean} options.flip Automatically adjust the menu `drop` position based on viewport edge detection
* @param {[number, number]} options.offset Define an offset distance between the Menu and the Toggle
* @param {boolean} options.show Display the menu manually, ignored in the context of a `Dropdown`
* @param {boolean} options.usePopper opt in/out of using PopperJS to position menus. When disabled you must position it yourself.
* @param {string} options.rootCloseEvent The pointer event to listen for when determining "clicks outside" the menu for triggering a close.
* @param {object} options.popperConfig Options passed to the [`usePopper`](/api/usePopper) hook.
*/
export declare function useDropdownMenu(options?: UseDropdownMenuOptions): readonly [UserDropdownMenuProps, UseDropdownMenuMetadata];
export interface DropdownMenuProps extends UseDropdownMenuOptions {
/**
* A render prop that returns a Menu element. The `props`
* argument should be spread through to **a component that can accept a ref**.
*
* @type {Function ({
* show: boolean,
* close: (?SyntheticEvent) => void,
* placement: Placement,
* update: () => void,
* forceUpdate: () => void,
* props: {
* ref: (?HTMLElement) => void,
* style: { [string]: string | number },
* aria-labelledby: ?string
* },
* arrowProps: {
* ref: (?HTMLElement) => void,
* style: { [string]: string | number },
* },
* }) => React.Element}
*/
children: (props: UserDropdownMenuProps, meta: UseDropdownMenuMetadata) => React.ReactNode;
}
/**
* Also exported as `<Dropdown.Menu>` from `Dropdown`.
*
* @displayName DropdownMenu
* @memberOf Dropdown
*/
declare function DropdownMenu({ children, usePopper: usePopperProp, ...options }: DropdownMenuProps): React.JSX.Element;
declare namespace DropdownMenu {
var displayName: string;
}
/** @component */
export default DropdownMenu;

View File

@@ -0,0 +1,106 @@
const _excluded = ["children", "usePopper"];
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
import { useContext, useRef } from 'react';
import * as React from 'react';
import useCallbackRef from '@restart/hooks/useCallbackRef';
import DropdownContext from './DropdownContext';
import usePopper from './usePopper';
import useClickOutside from './useClickOutside';
import mergeOptionsWithPopperConfig from './mergeOptionsWithPopperConfig';
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
const noop = () => {};
/**
* @memberOf Dropdown
* @param {object} options
* @param {boolean} options.flip Automatically adjust the menu `drop` position based on viewport edge detection
* @param {[number, number]} options.offset Define an offset distance between the Menu and the Toggle
* @param {boolean} options.show Display the menu manually, ignored in the context of a `Dropdown`
* @param {boolean} options.usePopper opt in/out of using PopperJS to position menus. When disabled you must position it yourself.
* @param {string} options.rootCloseEvent The pointer event to listen for when determining "clicks outside" the menu for triggering a close.
* @param {object} options.popperConfig Options passed to the [`usePopper`](/api/usePopper) hook.
*/
export function useDropdownMenu(options = {}) {
const context = useContext(DropdownContext);
const [arrowElement, attachArrowRef] = useCallbackRef();
const hasShownRef = useRef(false);
const {
flip,
offset,
rootCloseEvent,
fixed = false,
placement: placementOverride,
popperConfig = {},
enableEventListeners = true,
usePopper: shouldUsePopper = !!context
} = options;
const show = (context == null ? void 0 : context.show) == null ? !!options.show : context.show;
if (show && !hasShownRef.current) {
hasShownRef.current = true;
}
const handleClose = e => {
context == null ? void 0 : context.toggle(false, e);
};
const {
placement,
setMenu,
menuElement,
toggleElement
} = context || {};
const popper = usePopper(toggleElement, menuElement, mergeOptionsWithPopperConfig({
placement: placementOverride || placement || 'bottom-start',
enabled: shouldUsePopper,
enableEvents: enableEventListeners == null ? show : enableEventListeners,
offset,
flip,
fixed,
arrowElement,
popperConfig
}));
const menuProps = Object.assign({
ref: setMenu || noop,
'aria-labelledby': toggleElement == null ? void 0 : toggleElement.id
}, popper.attributes.popper, {
style: popper.styles.popper
});
const metadata = {
show,
placement,
hasShown: hasShownRef.current,
toggle: context == null ? void 0 : context.toggle,
popper: shouldUsePopper ? popper : null,
arrowProps: shouldUsePopper ? Object.assign({
ref: attachArrowRef
}, popper.attributes.arrow, {
style: popper.styles.arrow
}) : {}
};
useClickOutside(menuElement, handleClose, {
clickTrigger: rootCloseEvent,
disabled: !show
});
return [menuProps, metadata];
}
/**
* Also exported as `<Dropdown.Menu>` from `Dropdown`.
*
* @displayName DropdownMenu
* @memberOf Dropdown
*/
function DropdownMenu(_ref) {
let {
children,
usePopper: usePopperProp = true
} = _ref,
options = _objectWithoutPropertiesLoose(_ref, _excluded);
const [props, meta] = useDropdownMenu(Object.assign({}, options, {
usePopper: usePopperProp
}));
return /*#__PURE__*/_jsx(_Fragment, {
children: children(props, meta)
});
}
DropdownMenu.displayName = 'DropdownMenu';
/** @component */
export default DropdownMenu;

View File

@@ -0,0 +1,56 @@
import * as React from 'react';
import { DropdownContextValue } from './DropdownContext';
export declare const isRoleMenu: (el: HTMLElement) => boolean;
export interface UseDropdownToggleProps {
id: string;
ref: DropdownContextValue['setToggle'];
onClick: React.MouseEventHandler;
'aria-expanded': boolean;
'aria-haspopup'?: true;
}
export interface UseDropdownToggleMetadata {
show: DropdownContextValue['show'];
toggle: DropdownContextValue['toggle'];
}
/**
* Wires up Dropdown toggle functionality, returning a set a props to attach
* to the element that functions as the dropdown toggle (generally a button).
*
* @memberOf Dropdown
*/
export declare function useDropdownToggle(): [
UseDropdownToggleProps,
UseDropdownToggleMetadata
];
export interface DropdownToggleProps {
/**
* A render prop that returns a Toggle element. The `props`
* argument should spread through to **a component that can accept a ref**. Use
* the `onToggle` argument to toggle the menu open or closed
*
* @type {Function ({
* props: {
* ref: (?HTMLElement) => void,
* aria-haspopup: true
* aria-expanded: boolean
* },
* meta: {
* show: boolean,
* toggle: (show: boolean) => void,
* }
* }) => React.Element}
*/
children: (props: UseDropdownToggleProps, meta: UseDropdownToggleMetadata) => React.ReactNode;
}
/**
* Also exported as `<Dropdown.Toggle>` from `Dropdown`.
*
* @displayName DropdownToggle
* @memberOf Dropdown
*/
declare function DropdownToggle({ children }: DropdownToggleProps): React.JSX.Element;
declare namespace DropdownToggle {
var displayName: string;
}
/** @component */
export default DropdownToggle;

View File

@@ -0,0 +1,64 @@
import { useContext, useCallback } from 'react';
import * as React from 'react';
import { useSSRSafeId } from './ssr';
import DropdownContext from './DropdownContext';
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
export const isRoleMenu = el => {
var _el$getAttribute;
return ((_el$getAttribute = el.getAttribute('role')) == null ? void 0 : _el$getAttribute.toLowerCase()) === 'menu';
};
const noop = () => {};
/**
* Wires up Dropdown toggle functionality, returning a set a props to attach
* to the element that functions as the dropdown toggle (generally a button).
*
* @memberOf Dropdown
*/
export function useDropdownToggle() {
const id = useSSRSafeId();
const {
show = false,
toggle = noop,
setToggle,
menuElement
} = useContext(DropdownContext) || {};
const handleClick = useCallback(e => {
toggle(!show, e);
}, [show, toggle]);
const props = {
id,
ref: setToggle || noop,
onClick: handleClick,
'aria-expanded': !!show
};
// This is maybe better down in an effect, but
// the component is going to update anyway when the menu element
// is set so might return new props.
if (menuElement && isRoleMenu(menuElement)) {
props['aria-haspopup'] = true;
}
return [props, {
show,
toggle
}];
}
/**
* Also exported as `<Dropdown.Toggle>` from `Dropdown`.
*
* @displayName DropdownToggle
* @memberOf Dropdown
*/
function DropdownToggle({
children
}) {
const [props, meta] = useDropdownToggle();
return /*#__PURE__*/_jsx(_Fragment, {
children: children(props, meta)
});
}
DropdownToggle.displayName = 'DropdownToggle';
/** @component */
export default DropdownToggle;

View File

@@ -0,0 +1,29 @@
import React from 'react';
import { TransitionComponent, TransitionProps } from './types';
export interface TransitionFunctionOptions {
in: boolean;
element: HTMLElement;
initial: boolean;
isStale: () => boolean;
}
export type TransitionHandler = (options: TransitionFunctionOptions) => void | Promise<void>;
export interface UseTransitionOptions {
in: boolean;
onTransition: TransitionHandler;
initial?: boolean;
}
export declare function useTransition({ in: inProp, onTransition, }: UseTransitionOptions): React.RefObject<HTMLElement>;
export interface ImperativeTransitionProps extends TransitionProps {
transition: TransitionHandler;
appear: true;
mountOnEnter: true;
unmountOnExit: true;
}
/**
* Adapts an imperative transition function to a subset of the RTG `<Transition>` component API.
*
* ImperativeTransition does not support mounting options or `appear` at the moment, meaning
* that it always acts like: `mountOnEnter={true} unmountOnExit={true} appear={true}`
*/
export default function ImperativeTransition({ children, in: inProp, onExited, onEntered, transition, }: ImperativeTransitionProps): React.ReactElement<any, string | React.JSXElementConstructor<any>> | null;
export declare function renderTransition(component: TransitionComponent | undefined, runTransition: TransitionHandler | undefined, props: TransitionProps & Omit<ImperativeTransitionProps, 'transition'>): React.JSX.Element;

View File

@@ -0,0 +1,93 @@
import useMergedRefs from '@restart/hooks/useMergedRefs';
import useEventCallback from '@restart/hooks/useEventCallback';
import useIsomorphicEffect from '@restart/hooks/useIsomorphicEffect';
import React, { useRef, cloneElement, useState } from 'react';
import NoopTransition from './NoopTransition';
import RTGTransition from './RTGTransition';
import { jsx as _jsx } from "react/jsx-runtime";
export function useTransition({
in: inProp,
onTransition
}) {
const ref = useRef(null);
const isInitialRef = useRef(true);
const handleTransition = useEventCallback(onTransition);
useIsomorphicEffect(() => {
if (!ref.current) {
return undefined;
}
let stale = false;
handleTransition({
in: inProp,
element: ref.current,
initial: isInitialRef.current,
isStale: () => stale
});
return () => {
stale = true;
};
}, [inProp, handleTransition]);
useIsomorphicEffect(() => {
isInitialRef.current = false;
// this is for strict mode
return () => {
isInitialRef.current = true;
};
}, []);
return ref;
}
/**
* Adapts an imperative transition function to a subset of the RTG `<Transition>` component API.
*
* ImperativeTransition does not support mounting options or `appear` at the moment, meaning
* that it always acts like: `mountOnEnter={true} unmountOnExit={true} appear={true}`
*/
export default function ImperativeTransition({
children,
in: inProp,
onExited,
onEntered,
transition
}) {
const [exited, setExited] = useState(!inProp);
// TODO: I think this needs to be in an effect
if (inProp && exited) {
setExited(false);
}
const ref = useTransition({
in: !!inProp,
onTransition: options => {
const onFinish = () => {
if (options.isStale()) return;
if (options.in) {
onEntered == null ? void 0 : onEntered(options.element, options.initial);
} else {
setExited(true);
onExited == null ? void 0 : onExited(options.element);
}
};
Promise.resolve(transition(options)).then(onFinish, error => {
if (!options.in) setExited(true);
throw error;
});
}
});
const combinedRef = useMergedRefs(ref, children.ref);
return exited && !inProp ? null : /*#__PURE__*/cloneElement(children, {
ref: combinedRef
});
}
export function renderTransition(component, runTransition, props) {
if (component) {
return /*#__PURE__*/_jsx(RTGTransition, Object.assign({}, props, {
component: component
}));
}
if (runTransition) {
return /*#__PURE__*/_jsx(ImperativeTransition, Object.assign({}, props, {
transition: runTransition
}));
}
return /*#__PURE__*/_jsx(NoopTransition, Object.assign({}, props));
}

View File

@@ -0,0 +1,153 @@
import * as React from 'react';
import ModalManager from './ModalManager';
import { DOMContainer } from './useWaitForDOMRef';
import { TransitionCallbacks } from './types';
import { TransitionHandler } from './ImperativeTransition';
export interface ModalTransitionProps extends TransitionCallbacks {
in: boolean;
appear?: boolean;
unmountOnExit?: boolean;
children: React.ReactElement;
}
export type ModalTransitionComponent = React.ComponentType<ModalTransitionProps>;
export interface RenderModalDialogProps {
style: React.CSSProperties | undefined;
className: string | undefined;
tabIndex: number;
role: string;
ref: React.RefCallback<Element>;
'aria-modal': boolean | undefined;
}
export interface RenderModalBackdropProps {
ref: React.RefCallback<Element>;
onClick: (event: React.SyntheticEvent) => void;
}
export interface BaseModalProps extends TransitionCallbacks {
children?: React.ReactElement;
role?: string;
style?: React.CSSProperties;
className?: string;
/**
* Set the visibility of the Modal
*/
show?: boolean;
/**
* A DOM element, a `ref` to an element, or function that returns either. The Modal is appended to it's `container` element.
*
*/
container?: DOMContainer;
/**
* A callback fired when the Modal is opening.
*/
onShow?: () => void;
/**
* A callback fired when either the backdrop is clicked, or the escape key is pressed.
*
* The `onHide` callback only signals intent from the Modal,
* you must actually set the `show` prop to `false` for the Modal to close.
*/
onHide?: () => void;
/**
* A ModalManager instance used to track and manage the state of open
* Modals. Useful when customizing how modals interact within a container
*/
manager?: ModalManager;
/**
* Include a backdrop component. A `static`backdrop
* will not trigger a Modal onHide when clicked.
*/
backdrop?: true | false | 'static';
/**
* A function that returns the dialog component. Useful for custom
* rendering. **Note:** the component should make sure to apply the provided ref.
*
* ```js static
* renderDialog={props => <MyDialog {...props} />}
* ```
*/
renderDialog?: (props: RenderModalDialogProps) => React.ReactNode;
/**
* A function that returns a backdrop component. Useful for custom
* backdrop rendering.
*
* ```js
* renderBackdrop={props => <MyBackdrop {...props} />}
* ```
*/
renderBackdrop?: (props: RenderModalBackdropProps) => React.ReactNode;
/**
* A callback fired when the escape key, if specified in `keyboard`, is pressed.
*
* If preventDefault() is called on the keyboard event, closing the modal will be cancelled.
*/
onEscapeKeyDown?: (e: KeyboardEvent) => void;
/**
* A callback fired when the backdrop, if specified, is clicked.
*/
onBackdropClick?: (e: React.SyntheticEvent) => void;
/**
* Close the modal when escape key is pressed
*/
keyboard?: boolean;
/**
* A `react-transition-group` `<Transition/>` component used
* to control animations for the dialog component.
*/
transition?: ModalTransitionComponent;
/**
* A transition handler, called with the `show` state and dialog element.
* Should return a promise when the transition is complete
*/
runTransition?: TransitionHandler;
/**
* A `react-transition-group` `<Transition/>` component used
* to control animations for the backdrop components.
*/
backdropTransition?: ModalTransitionComponent;
/**
* A transition handler, called with the `show` state and backdrop element.
* Should return a promise when the transition is complete
*/
runBackdropTransition?: TransitionHandler;
/**
* When `true` The modal will automatically shift focus to itself when it opens, and
* replace it to the last focused element when it closes. This also
* works correctly with any Modal children that have the `autoFocus` prop.
*
* Generally this should never be set to `false` as it makes the Modal less
* accessible to assistive technologies, like screen readers.
*/
autoFocus?: boolean;
/**
* When `true` The modal will prevent focus from leaving the Modal while open.
*
* Generally this should never be set to `false` as it makes the Modal less
* accessible to assistive technologies, like screen readers.
*/
enforceFocus?: boolean;
/**
* When `true` The modal will restore focus to previously focused element once
* modal is hidden
*/
restoreFocus?: boolean;
/**
* Options passed to focus function when `restoreFocus` is set to `true`
*
* @link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#Parameters
*/
restoreFocusOptions?: {
preventScroll: boolean;
};
}
export interface ModalProps extends BaseModalProps {
[other: string]: any;
}
export interface ModalHandle {
dialog: HTMLElement | null;
backdrop: HTMLElement | null;
isTopModal: () => boolean;
}
declare const _default: React.ForwardRefExoticComponent<ModalProps & React.RefAttributes<ModalHandle>> & {
Manager: typeof ModalManager;
};
export default _default;

245
backend/frontend/node_modules/@restart/ui/esm/Modal.js generated vendored Normal file
View File

@@ -0,0 +1,245 @@
const _excluded = ["show", "role", "className", "style", "children", "backdrop", "keyboard", "onBackdropClick", "onEscapeKeyDown", "transition", "runTransition", "backdropTransition", "runBackdropTransition", "autoFocus", "enforceFocus", "restoreFocus", "restoreFocusOptions", "renderDialog", "renderBackdrop", "manager", "container", "onShow", "onHide", "onExit", "onExited", "onExiting", "onEnter", "onEntering", "onEntered"];
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
/* eslint-disable @typescript-eslint/no-use-before-define, react/prop-types */
import activeElement from 'dom-helpers/activeElement';
import contains from 'dom-helpers/contains';
import canUseDOM from 'dom-helpers/canUseDOM';
import listen from 'dom-helpers/listen';
import { useState, useRef, useCallback, useImperativeHandle, forwardRef, useEffect } from 'react';
import * as React from 'react';
import ReactDOM from 'react-dom';
import useMounted from '@restart/hooks/useMounted';
import useWillUnmount from '@restart/hooks/useWillUnmount';
import usePrevious from '@restart/hooks/usePrevious';
import useEventCallback from '@restart/hooks/useEventCallback';
import ModalManager from './ModalManager';
import useWaitForDOMRef from './useWaitForDOMRef';
import useWindow from './useWindow';
import { renderTransition } from './ImperativeTransition';
import { isEscKey } from './utils';
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
let manager;
/*
Modal props are split into a version with and without index signature so that you can fully use them in another projects
This is due to Typescript not playing well with index signatures e.g. when using Omit
*/
function getManager(window) {
if (!manager) manager = new ModalManager({
ownerDocument: window == null ? void 0 : window.document
});
return manager;
}
function useModalManager(provided) {
const window = useWindow();
const modalManager = provided || getManager(window);
const modal = useRef({
dialog: null,
backdrop: null
});
return Object.assign(modal.current, {
add: () => modalManager.add(modal.current),
remove: () => modalManager.remove(modal.current),
isTopModal: () => modalManager.isTopModal(modal.current),
setDialogRef: useCallback(ref => {
modal.current.dialog = ref;
}, []),
setBackdropRef: useCallback(ref => {
modal.current.backdrop = ref;
}, [])
});
}
const Modal = /*#__PURE__*/forwardRef((_ref, ref) => {
let {
show = false,
role = 'dialog',
className,
style,
children,
backdrop = true,
keyboard = true,
onBackdropClick,
onEscapeKeyDown,
transition,
runTransition,
backdropTransition,
runBackdropTransition,
autoFocus = true,
enforceFocus = true,
restoreFocus = true,
restoreFocusOptions,
renderDialog,
renderBackdrop = props => /*#__PURE__*/_jsx("div", Object.assign({}, props)),
manager: providedManager,
container: containerRef,
onShow,
onHide = () => {},
onExit,
onExited,
onExiting,
onEnter,
onEntering,
onEntered
} = _ref,
rest = _objectWithoutPropertiesLoose(_ref, _excluded);
const ownerWindow = useWindow();
const container = useWaitForDOMRef(containerRef);
const modal = useModalManager(providedManager);
const isMounted = useMounted();
const prevShow = usePrevious(show);
const [exited, setExited] = useState(!show);
const lastFocusRef = useRef(null);
useImperativeHandle(ref, () => modal, [modal]);
if (canUseDOM && !prevShow && show) {
lastFocusRef.current = activeElement(ownerWindow == null ? void 0 : ownerWindow.document);
}
// TODO: I think this needs to be in an effect
if (show && exited) {
setExited(false);
}
const handleShow = useEventCallback(() => {
modal.add();
removeKeydownListenerRef.current = listen(document, 'keydown', handleDocumentKeyDown);
removeFocusListenerRef.current = listen(document, 'focus',
// the timeout is necessary b/c this will run before the new modal is mounted
// and so steals focus from it
() => setTimeout(handleEnforceFocus), true);
if (onShow) {
onShow();
}
// autofocus after onShow to not trigger a focus event for previous
// modals before this one is shown.
if (autoFocus) {
var _modal$dialog$ownerDo, _modal$dialog;
const currentActiveElement = activeElement((_modal$dialog$ownerDo = (_modal$dialog = modal.dialog) == null ? void 0 : _modal$dialog.ownerDocument) != null ? _modal$dialog$ownerDo : ownerWindow == null ? void 0 : ownerWindow.document);
if (modal.dialog && currentActiveElement && !contains(modal.dialog, currentActiveElement)) {
lastFocusRef.current = currentActiveElement;
modal.dialog.focus();
}
}
});
const handleHide = useEventCallback(() => {
modal.remove();
removeKeydownListenerRef.current == null ? void 0 : removeKeydownListenerRef.current();
removeFocusListenerRef.current == null ? void 0 : removeFocusListenerRef.current();
if (restoreFocus) {
var _lastFocusRef$current;
// Support: <=IE11 doesn't support `focus()` on svg elements (RB: #917)
(_lastFocusRef$current = lastFocusRef.current) == null ? void 0 : _lastFocusRef$current.focus == null ? void 0 : _lastFocusRef$current.focus(restoreFocusOptions);
lastFocusRef.current = null;
}
});
// TODO: try and combine these effects: https://github.com/react-bootstrap/react-overlays/pull/794#discussion_r409954120
// Show logic when:
// - show is `true` _and_ `container` has resolved
useEffect(() => {
if (!show || !container) return;
handleShow();
}, [show, container, /* should never change: */handleShow]);
// Hide cleanup logic when:
// - `exited` switches to true
// - component unmounts;
useEffect(() => {
if (!exited) return;
handleHide();
}, [exited, handleHide]);
useWillUnmount(() => {
handleHide();
});
// --------------------------------
const handleEnforceFocus = useEventCallback(() => {
if (!enforceFocus || !isMounted() || !modal.isTopModal()) {
return;
}
const currentActiveElement = activeElement(ownerWindow == null ? void 0 : ownerWindow.document);
if (modal.dialog && currentActiveElement && !contains(modal.dialog, currentActiveElement)) {
modal.dialog.focus();
}
});
const handleBackdropClick = useEventCallback(e => {
if (e.target !== e.currentTarget) {
return;
}
onBackdropClick == null ? void 0 : onBackdropClick(e);
if (backdrop === true) {
onHide();
}
});
const handleDocumentKeyDown = useEventCallback(e => {
if (keyboard && isEscKey(e) && modal.isTopModal()) {
onEscapeKeyDown == null ? void 0 : onEscapeKeyDown(e);
if (!e.defaultPrevented) {
onHide();
}
}
});
const removeFocusListenerRef = useRef();
const removeKeydownListenerRef = useRef();
const handleHidden = (...args) => {
setExited(true);
onExited == null ? void 0 : onExited(...args);
};
if (!container) {
return null;
}
const dialogProps = Object.assign({
role,
ref: modal.setDialogRef,
// apparently only works on the dialog role element
'aria-modal': role === 'dialog' ? true : undefined
}, rest, {
style,
className,
tabIndex: -1
});
let dialog = renderDialog ? renderDialog(dialogProps) : /*#__PURE__*/_jsx("div", Object.assign({}, dialogProps, {
children: /*#__PURE__*/React.cloneElement(children, {
role: 'document'
})
}));
dialog = renderTransition(transition, runTransition, {
unmountOnExit: true,
mountOnEnter: true,
appear: true,
in: !!show,
onExit,
onExiting,
onExited: handleHidden,
onEnter,
onEntering,
onEntered,
children: dialog
});
let backdropElement = null;
if (backdrop) {
backdropElement = renderBackdrop({
ref: modal.setBackdropRef,
onClick: handleBackdropClick
});
backdropElement = renderTransition(backdropTransition, runBackdropTransition, {
in: !!show,
appear: true,
mountOnEnter: true,
unmountOnExit: true,
children: backdropElement
});
}
return /*#__PURE__*/_jsx(_Fragment, {
children: /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/_jsxs(_Fragment, {
children: [backdropElement, dialog]
}), container)
});
});
Modal.displayName = 'Modal';
export default Object.assign(Modal, {
Manager: ModalManager
});

View File

@@ -0,0 +1,38 @@
export interface ModalInstance {
dialog: Element;
backdrop: Element;
}
export interface ModalManagerOptions {
ownerDocument?: Document;
handleContainerOverflow?: boolean;
isRTL?: boolean;
}
export type ContainerState = {
scrollBarWidth: number;
style: Record<string, any>;
[key: string]: any;
};
export declare const OPEN_DATA_ATTRIBUTE: "data-rr-ui-modal-open";
/**
* Manages a stack of Modals as well as ensuring
* body scrolling is is disabled and padding accounted for
*/
declare class ModalManager {
readonly handleContainerOverflow: boolean;
readonly isRTL: boolean;
readonly modals: ModalInstance[];
protected state: ContainerState;
protected ownerDocument: Document | undefined;
constructor({ ownerDocument, handleContainerOverflow, isRTL, }?: ModalManagerOptions);
getScrollbarWidth(): number;
getElement(): HTMLElement;
setModalAttributes(_modal: ModalInstance): void;
removeModalAttributes(_modal: ModalInstance): void;
setContainerStyle(containerState: ContainerState): void;
reset(): void;
removeContainerStyle(containerState: ContainerState): void;
add(modal: ModalInstance): number;
remove(modal: ModalInstance): void;
isTopModal(modal: ModalInstance): boolean;
}
export default ModalManager;

View File

@@ -0,0 +1,100 @@
import css from 'dom-helpers/css';
import { dataAttr } from './DataKey';
import getBodyScrollbarWidth from './getScrollbarWidth';
export const OPEN_DATA_ATTRIBUTE = dataAttr('modal-open');
/**
* Manages a stack of Modals as well as ensuring
* body scrolling is is disabled and padding accounted for
*/
class ModalManager {
constructor({
ownerDocument,
handleContainerOverflow = true,
isRTL = false
} = {}) {
this.handleContainerOverflow = handleContainerOverflow;
this.isRTL = isRTL;
this.modals = [];
this.ownerDocument = ownerDocument;
}
getScrollbarWidth() {
return getBodyScrollbarWidth(this.ownerDocument);
}
getElement() {
return (this.ownerDocument || document).body;
}
setModalAttributes(_modal) {
// For overriding
}
removeModalAttributes(_modal) {
// For overriding
}
setContainerStyle(containerState) {
const style = {
overflow: 'hidden'
};
// we are only interested in the actual `style` here
// because we will override it
const paddingProp = this.isRTL ? 'paddingLeft' : 'paddingRight';
const container = this.getElement();
containerState.style = {
overflow: container.style.overflow,
[paddingProp]: container.style[paddingProp]
};
if (containerState.scrollBarWidth) {
// use computed style, here to get the real padding
// to add our scrollbar width
style[paddingProp] = `${parseInt(css(container, paddingProp) || '0', 10) + containerState.scrollBarWidth}px`;
}
container.setAttribute(OPEN_DATA_ATTRIBUTE, '');
css(container, style);
}
reset() {
[...this.modals].forEach(m => this.remove(m));
}
removeContainerStyle(containerState) {
const container = this.getElement();
container.removeAttribute(OPEN_DATA_ATTRIBUTE);
Object.assign(container.style, containerState.style);
}
add(modal) {
let modalIdx = this.modals.indexOf(modal);
if (modalIdx !== -1) {
return modalIdx;
}
modalIdx = this.modals.length;
this.modals.push(modal);
this.setModalAttributes(modal);
if (modalIdx !== 0) {
return modalIdx;
}
this.state = {
scrollBarWidth: this.getScrollbarWidth(),
style: {}
};
if (this.handleContainerOverflow) {
this.setContainerStyle(this.state);
}
return modalIdx;
}
remove(modal) {
const modalIdx = this.modals.indexOf(modal);
if (modalIdx === -1) {
return;
}
this.modals.splice(modalIdx, 1);
// if that was the last modal in a container,
// clean up the container
if (!this.modals.length && this.handleContainerOverflow) {
this.removeContainerStyle(this.state);
}
this.removeModalAttributes(modal);
}
isTopModal(modal) {
return !!this.modals.length && this.modals[this.modals.length - 1] === modal;
}
}
export default ModalManager;

22
backend/frontend/node_modules/@restart/ui/esm/Nav.d.ts generated vendored Normal file
View File

@@ -0,0 +1,22 @@
import * as React from 'react';
import { EventKey, DynamicRefForwardingComponent, SelectCallback } from './types';
import { UseNavItemOptions, NavItemProps } from './NavItem';
export type { UseNavItemOptions, NavItemProps };
export interface NavProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onSelect'> {
/**
* Key for the currently active NavItem.
*/
activeKey?: EventKey;
/**
* Element used to render the component.
*/
as?: React.ElementType;
/**
* A callback fired when a NavItem has been selected.
*/
onSelect?: SelectCallback;
}
declare const _default: DynamicRefForwardingComponent<"div", NavProps> & {
Item: DynamicRefForwardingComponent<React.ForwardRefExoticComponent<import("./Button").ButtonProps & React.RefAttributes<HTMLElement>>, NavItemProps>;
};
export default _default;

113
backend/frontend/node_modules/@restart/ui/esm/Nav.js generated vendored Normal file
View File

@@ -0,0 +1,113 @@
const _excluded = ["as", "onSelect", "activeKey", "role", "onKeyDown"];
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
import qsa from 'dom-helpers/querySelectorAll';
import * as React from 'react';
import { useContext, useEffect, useRef } from 'react';
import useForceUpdate from '@restart/hooks/useForceUpdate';
import useMergedRefs from '@restart/hooks/useMergedRefs';
import NavContext from './NavContext';
import SelectableContext, { makeEventKey } from './SelectableContext';
import TabContext from './TabContext';
import { dataAttr, dataProp } from './DataKey';
import NavItem from './NavItem';
import { jsx as _jsx } from "react/jsx-runtime";
// eslint-disable-next-line @typescript-eslint/no-empty-function
const noop = () => {};
const EVENT_KEY_ATTR = dataAttr('event-key');
const Nav = /*#__PURE__*/React.forwardRef((_ref, ref) => {
let {
// Need to define the default "as" during prop destructuring to be compatible with styled-components github.com/react-bootstrap/react-bootstrap/issues/3595
as: Component = 'div',
onSelect,
activeKey,
role,
onKeyDown
} = _ref,
props = _objectWithoutPropertiesLoose(_ref, _excluded);
// A ref and forceUpdate for refocus, b/c we only want to trigger when needed
// and don't want to reset the set in the effect
const forceUpdate = useForceUpdate();
const needsRefocusRef = useRef(false);
const parentOnSelect = useContext(SelectableContext);
const tabContext = useContext(TabContext);
let getControlledId, getControllerId;
if (tabContext) {
role = role || 'tablist';
activeKey = tabContext.activeKey;
// TODO: do we need to duplicate these?
getControlledId = tabContext.getControlledId;
getControllerId = tabContext.getControllerId;
}
const listNode = useRef(null);
const getNextActiveTab = offset => {
const currentListNode = listNode.current;
if (!currentListNode) return null;
const items = qsa(currentListNode, `[${EVENT_KEY_ATTR}]:not([aria-disabled=true])`);
const activeChild = currentListNode.querySelector('[aria-selected=true]');
if (!activeChild || activeChild !== document.activeElement) return null;
const index = items.indexOf(activeChild);
if (index === -1) return null;
let nextIndex = index + offset;
if (nextIndex >= items.length) nextIndex = 0;
if (nextIndex < 0) nextIndex = items.length - 1;
return items[nextIndex];
};
const handleSelect = (key, event) => {
if (key == null) return;
onSelect == null ? void 0 : onSelect(key, event);
parentOnSelect == null ? void 0 : parentOnSelect(key, event);
};
const handleKeyDown = event => {
onKeyDown == null ? void 0 : onKeyDown(event);
if (!tabContext) {
return;
}
let nextActiveChild;
switch (event.key) {
case 'ArrowLeft':
case 'ArrowUp':
nextActiveChild = getNextActiveTab(-1);
break;
case 'ArrowRight':
case 'ArrowDown':
nextActiveChild = getNextActiveTab(1);
break;
default:
return;
}
if (!nextActiveChild) return;
event.preventDefault();
handleSelect(nextActiveChild.dataset[dataProp('EventKey')] || null, event);
needsRefocusRef.current = true;
forceUpdate();
};
useEffect(() => {
if (listNode.current && needsRefocusRef.current) {
const activeChild = listNode.current.querySelector(`[${EVENT_KEY_ATTR}][aria-selected=true]`);
activeChild == null ? void 0 : activeChild.focus();
}
needsRefocusRef.current = false;
});
const mergedRef = useMergedRefs(ref, listNode);
return /*#__PURE__*/_jsx(SelectableContext.Provider, {
value: handleSelect,
children: /*#__PURE__*/_jsx(NavContext.Provider, {
value: {
role,
// used by NavLink to determine it's role
activeKey: makeEventKey(activeKey),
getControlledId: getControlledId || noop,
getControllerId: getControllerId || noop
},
children: /*#__PURE__*/_jsx(Component, Object.assign({}, props, {
onKeyDown: handleKeyDown,
ref: mergedRef,
role: role
}))
})
});
});
Nav.displayName = 'Nav';
export default Object.assign(Nav, {
Item: NavItem
});

View File

@@ -0,0 +1,10 @@
import * as React from 'react';
import { EventKey } from './types';
interface NavContextType {
role?: string;
activeKey: EventKey | null;
getControlledId: (key: EventKey | null) => string;
getControllerId: (key: EventKey | null) => string;
}
declare const NavContext: React.Context<NavContextType | null>;
export default NavContext;

View File

@@ -0,0 +1,4 @@
import * as React from 'react';
const NavContext = /*#__PURE__*/React.createContext(null);
NavContext.displayName = 'NavContext';
export default NavContext;

View File

@@ -0,0 +1,38 @@
import * as React from 'react';
import { EventKey, DynamicRefForwardingComponent } from './types';
import Button from './Button';
export interface NavItemProps extends React.HTMLAttributes<HTMLElement> {
/**
* Highlight the NavItem as active.
*/
active?: boolean;
/**
* Element used to render the component.
*/
as?: React.ElementType;
/**
* Disable the NavItem, making it unselectable.
*/
disabled?: boolean;
/**
* Value passed to the `onSelect` handler, useful for identifying the selected NavItem.
*/
eventKey?: EventKey;
/**
* HTML `href` attribute corresponding to `a.href`.
*/
href?: string;
}
export interface UseNavItemOptions {
key?: string | null;
onClick?: React.MouseEventHandler;
active?: boolean;
disabled?: boolean;
id?: string;
role?: string;
}
export declare function useNavItem({ key, onClick, active, id, role, disabled, }: UseNavItemOptions): readonly [any, {
readonly isActive: boolean | undefined;
}];
declare const NavItem: DynamicRefForwardingComponent<typeof Button, NavItemProps>;
export default NavItem;

View File

@@ -0,0 +1,91 @@
const _excluded = ["as", "active", "eventKey"];
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
import * as React from 'react';
import { useContext } from 'react';
import useEventCallback from '@restart/hooks/useEventCallback';
import NavContext from './NavContext';
import SelectableContext, { makeEventKey } from './SelectableContext';
import Button from './Button';
import { dataAttr } from './DataKey';
import TabContext from './TabContext';
import { jsx as _jsx } from "react/jsx-runtime";
export function useNavItem({
key,
onClick,
active,
id,
role,
disabled
}) {
const parentOnSelect = useContext(SelectableContext);
const navContext = useContext(NavContext);
const tabContext = useContext(TabContext);
let isActive = active;
const props = {
role
};
if (navContext) {
if (!role && navContext.role === 'tablist') props.role = 'tab';
const contextControllerId = navContext.getControllerId(key != null ? key : null);
const contextControlledId = navContext.getControlledId(key != null ? key : null);
// @ts-ignore
props[dataAttr('event-key')] = key;
props.id = contextControllerId || id;
isActive = active == null && key != null ? navContext.activeKey === key : active;
/**
* Simplified scenario for `mountOnEnter`.
*
* While it would make sense to keep 'aria-controls' for tabs that have been mounted at least
* once, it would also complicate the code quite a bit, for very little gain.
* The following implementation is probably good enough.
*
* @see https://github.com/react-restart/ui/pull/40#issuecomment-1009971561
*/
if (isActive || !(tabContext != null && tabContext.unmountOnExit) && !(tabContext != null && tabContext.mountOnEnter)) props['aria-controls'] = contextControlledId;
}
if (props.role === 'tab') {
props['aria-selected'] = isActive;
if (!isActive) {
props.tabIndex = -1;
}
if (disabled) {
props.tabIndex = -1;
props['aria-disabled'] = true;
}
}
props.onClick = useEventCallback(e => {
if (disabled) return;
onClick == null ? void 0 : onClick(e);
if (key == null) {
return;
}
if (parentOnSelect && !e.isPropagationStopped()) {
parentOnSelect(key, e);
}
});
return [props, {
isActive
}];
}
const NavItem = /*#__PURE__*/React.forwardRef((_ref, ref) => {
let {
as: Component = Button,
active,
eventKey
} = _ref,
options = _objectWithoutPropertiesLoose(_ref, _excluded);
const [props, meta] = useNavItem(Object.assign({
key: makeEventKey(eventKey, options.href),
active
}, options));
// @ts-ignore
props[dataAttr('active')] = meta.isActive;
return /*#__PURE__*/_jsx(Component, Object.assign({}, options, props, {
ref: ref
}));
});
NavItem.displayName = 'NavItem';
export default NavItem;

View File

@@ -0,0 +1,4 @@
/// <reference types="react" />
import { TransitionProps } from './types';
declare function NoopTransition({ children, in: inProp, onExited, mountOnEnter, unmountOnExit, }: TransitionProps): import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | null;
export default NoopTransition;

View File

@@ -0,0 +1,32 @@
import useEventCallback from '@restart/hooks/useEventCallback';
import useMergedRefs from '@restart/hooks/useMergedRefs';
import { cloneElement, useEffect, useRef } from 'react';
function NoopTransition({
children,
in: inProp,
onExited,
mountOnEnter,
unmountOnExit
}) {
const ref = useRef(null);
const hasEnteredRef = useRef(inProp);
const handleExited = useEventCallback(onExited);
useEffect(() => {
if (inProp) hasEnteredRef.current = true;else {
handleExited(ref.current);
}
}, [inProp, handleExited]);
const combinedRef = useMergedRefs(ref, children.ref);
const child = /*#__PURE__*/cloneElement(children, {
ref: combinedRef
});
if (inProp) return child;
if (unmountOnExit) {
return null;
}
if (!hasEnteredRef.current && mountOnEnter) {
return null;
}
return child;
}
export default NoopTransition;

View File

@@ -0,0 +1,99 @@
import * as React from 'react';
import { Offset, Placement, UsePopperOptions, UsePopperState, VirtualElement } from './usePopper';
import { RootCloseOptions } from './useRootClose';
import { DOMContainer } from './useWaitForDOMRef';
import { TransitionCallbacks, TransitionComponent } from './types';
import { TransitionHandler } from './ImperativeTransition';
export interface OverlayArrowProps extends Record<string, any> {
ref: React.RefCallback<HTMLElement>;
style: React.CSSProperties;
}
export interface OverlayMetadata {
show: boolean;
placement: Placement | undefined;
popper: UsePopperState | null;
arrowProps: Partial<OverlayArrowProps>;
}
export interface OverlayInjectedProps extends Record<string, any> {
ref: React.RefCallback<HTMLElement>;
style: React.CSSProperties;
'aria-labelledby'?: string;
}
export interface OverlayProps extends TransitionCallbacks {
/**
* Enables the Popper.js `flip` modifier, allowing the Overlay to
* automatically adjust it's placement in case of overlap with the viewport or toggle.
* Refer to the [flip docs](https://popper.js.org/popper-documentation.html#modifiers..flip.enabled) for more info
*/
flip?: boolean;
/** Specify where the overlay element is positioned in relation to the target element */
placement?: Placement;
/**
* Control offset of the overlay to the reference element.
* A convenience shortcut to setting `popperConfig.modfiers.offset`
*/
offset?: Offset;
/**
* Control how much space there is between the edge of the boundary element and overlay.
* A convenience shortcut to setting `popperConfig.modfiers.preventOverflow.padding`
*/
containerPadding?: number;
/**
* A set of popper options and props passed directly to react-popper's Popper component.
*/
popperConfig?: Omit<UsePopperOptions, 'placement'>;
/**
* A DOM Element, [Virtual Element](https://popper.js.org/docs/v2/virtual-elements/), Ref to an element, or
* function that returns either. The `target` element is where the overlay is positioned relative to.
*/
container?: DOMContainer;
/**
* A DOM Element, Ref to an element, or function that returns either. The `target` element is where
* the overlay is positioned relative to.
*/
target: DOMContainer<HTMLElement | VirtualElement>;
/**
* Set the visibility of the Overlay
*/
show?: boolean;
/**
* A `react-transition-group` `<Transition/>` component
* used to animate the overlay as it changes visibility.
*/
transition?: TransitionComponent;
/**
* A transition handler, called with the `show` state and overlay element.
* Should return a promise when the transition is complete
*/
runTransition?: TransitionHandler;
/**
* A Callback fired by the Overlay when it wishes to be hidden.
*
* __required__ when `rootClose` is `true`.
*
* @type func
*/
onHide?: (e: Event) => void;
/**
* Specify whether the overlay should trigger `onHide` when the user clicks outside the overlay
*/
rootClose?: boolean;
/**
* Specify disabled for disable RootCloseWrapper
*/
rootCloseDisabled?: boolean;
/**
* Specify event for toggling overlay
*/
rootCloseEvent?: RootCloseOptions['clickTrigger'];
/**
* A render prop that returns an overlay element.
*/
children: (props: OverlayInjectedProps, meta: OverlayMetadata) => React.ReactNode;
}
/**
* Built on top of `Popper.js`, the overlay component is
* great for custom tooltip overlays.
*/
declare const Overlay: React.ForwardRefExoticComponent<OverlayProps & React.RefAttributes<HTMLElement>>;
export default Overlay;

View File

@@ -0,0 +1,97 @@
import * as React from 'react';
import ReactDOM from 'react-dom';
import useCallbackRef from '@restart/hooks/useCallbackRef';
import useMergedRefs from '@restart/hooks/useMergedRefs';
import { useState } from 'react';
import usePopper from './usePopper';
import useRootClose from './useRootClose';
import useWaitForDOMRef from './useWaitForDOMRef';
import mergeOptionsWithPopperConfig from './mergeOptionsWithPopperConfig';
import { renderTransition } from './ImperativeTransition';
/**
* Built on top of `Popper.js`, the overlay component is
* great for custom tooltip overlays.
*/
const Overlay = /*#__PURE__*/React.forwardRef((props, outerRef) => {
const {
flip,
offset,
placement,
containerPadding,
popperConfig = {},
transition: Transition,
runTransition
} = props;
const [rootElement, attachRef] = useCallbackRef();
const [arrowElement, attachArrowRef] = useCallbackRef();
const mergedRef = useMergedRefs(attachRef, outerRef);
const container = useWaitForDOMRef(props.container);
const target = useWaitForDOMRef(props.target);
const [exited, setExited] = useState(!props.show);
const popper = usePopper(target, rootElement, mergeOptionsWithPopperConfig({
placement,
enableEvents: !!props.show,
containerPadding: containerPadding || 5,
flip,
offset,
arrowElement,
popperConfig
}));
// TODO: I think this needs to be in an effect
if (props.show && exited) {
setExited(false);
}
const handleHidden = (...args) => {
setExited(true);
if (props.onExited) {
props.onExited(...args);
}
};
// Don't un-render the overlay while it's transitioning out.
const mountOverlay = props.show || !exited;
useRootClose(rootElement, props.onHide, {
disabled: !props.rootClose || props.rootCloseDisabled,
clickTrigger: props.rootCloseEvent
});
if (!mountOverlay) {
// Don't bother showing anything if we don't have to.
return null;
}
const {
onExit,
onExiting,
onEnter,
onEntering,
onEntered
} = props;
let child = props.children(Object.assign({}, popper.attributes.popper, {
style: popper.styles.popper,
ref: mergedRef
}), {
popper,
placement,
show: !!props.show,
arrowProps: Object.assign({}, popper.attributes.arrow, {
style: popper.styles.arrow,
ref: attachArrowRef
})
});
child = renderTransition(Transition, runTransition, {
in: !!props.show,
appear: true,
mountOnEnter: true,
unmountOnExit: true,
children: child,
onExit,
onExiting,
onExited: handleHidden,
onEnter,
onEntering,
onEntered
});
return container ? /*#__PURE__*/ReactDOM.createPortal(child, container) : null;
});
Overlay.displayName = 'Overlay';
export default Overlay;

View File

@@ -0,0 +1,22 @@
import * as React from 'react';
import { DOMContainer } from './useWaitForDOMRef';
export interface PortalProps {
children: React.ReactElement;
/**
* A DOM element, Ref to an element, or function that returns either. The `container` will have the Portal children
* appended to it.
*/
container: DOMContainer;
/**
* Callback that is triggered when the portal content is rendered.
*/
onRendered?: (element: any) => void;
}
/**
* @public
*/
declare const Portal: {
({ container, children, onRendered }: PortalProps): React.JSX.Element | null;
displayName: string;
};
export default Portal;

View File

@@ -0,0 +1,19 @@
import ReactDOM from 'react-dom';
import * as React from 'react';
import useWaitForDOMRef from './useWaitForDOMRef';
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
/**
* @public
*/
const Portal = ({
container,
children,
onRendered
}) => {
const resolvedContainer = useWaitForDOMRef(container, onRendered);
return resolvedContainer ? /*#__PURE__*/_jsx(_Fragment, {
children: /*#__PURE__*/ReactDOM.createPortal(children, resolvedContainer)
}) : null;
};
Portal.displayName = 'Portal';
export default Portal;

View File

@@ -0,0 +1,15 @@
import * as React from 'react';
import { TransitionProps } from './useRTGTransitionProps';
export type RTGTransitionProps = TransitionProps & {
component: React.ElementType;
};
declare const RTGTransition: React.ForwardRefExoticComponent<(Omit<import("react-transition-group/Transition").TimeoutProps<undefined> & {
children: React.ReactElement<any, string | React.JSXElementConstructor<any>> | ((status: import("react-transition-group").TransitionStatus, props: Record<string, unknown>) => React.ReactNode);
} & {
component: React.ElementType;
}, "ref"> | Omit<import("react-transition-group/Transition").EndListenerProps<undefined> & {
children: React.ReactElement<any, string | React.JSXElementConstructor<any>> | ((status: import("react-transition-group").TransitionStatus, props: Record<string, unknown>) => React.ReactNode);
} & {
component: React.ElementType;
}, "ref">) & React.RefAttributes<any>>;
export default RTGTransition;

View File

@@ -0,0 +1,17 @@
const _excluded = ["component"];
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
import * as React from 'react';
import useRTGTransitionProps from './useRTGTransitionProps';
import { jsx as _jsx } from "react/jsx-runtime";
// Normalizes Transition callbacks when nodeRef is used.
const RTGTransition = /*#__PURE__*/React.forwardRef((_ref, ref) => {
let {
component: Component
} = _ref,
props = _objectWithoutPropertiesLoose(_ref, _excluded);
const transitionProps = useRTGTransitionProps(props);
return /*#__PURE__*/_jsx(Component, Object.assign({
ref: ref
}, transitionProps));
});
export default RTGTransition;

View File

@@ -0,0 +1,5 @@
import * as React from 'react';
import { EventKey, SelectCallback } from './types';
declare const SelectableContext: React.Context<SelectCallback | null>;
export declare const makeEventKey: (eventKey?: EventKey | null, href?: string | null) => string | null;
export default SelectableContext;

View File

@@ -0,0 +1,7 @@
import * as React from 'react';
const SelectableContext = /*#__PURE__*/React.createContext(null);
export const makeEventKey = (eventKey, href = null) => {
if (eventKey != null) return String(eventKey);
return href || null;
};
export default SelectableContext;

View File

@@ -0,0 +1,13 @@
import * as React from 'react';
import { EventKey, SelectCallback, TransitionComponent } from './types';
export interface TabContextType {
onSelect: SelectCallback;
activeKey?: EventKey;
transition?: TransitionComponent;
mountOnEnter: boolean;
unmountOnExit: boolean;
getControlledId: (key: EventKey) => any;
getControllerId: (key: EventKey) => any;
}
declare const TabContext: React.Context<TabContextType | null>;
export default TabContext;

View File

@@ -0,0 +1,3 @@
import * as React from 'react';
const TabContext = /*#__PURE__*/React.createContext(null);
export default TabContext;

View File

@@ -0,0 +1,39 @@
import * as React from 'react';
import { EventKey, DynamicRefForwardingComponent, TransitionCallbacks, TransitionComponent } from './types';
export interface TabPanelProps extends TransitionCallbacks, React.HTMLAttributes<HTMLElement> {
/**
* Element used to render the component.
*/
as?: React.ElementType;
/**
* A key that associates the `TabPanel` with it's controlling `NavLink`.
*/
eventKey?: EventKey;
/**
* Toggles the active state of the TabPanel, this is generally controlled by `Tabs`.
*/
active?: boolean;
/**
* Use animation when showing or hiding `<TabPanel>`s. Use a react-transition-group
* `<Transition/>` component.
*/
transition?: TransitionComponent;
/**
* Wait until the first "enter" transition to mount the tab (add it to the DOM)
*/
mountOnEnter?: boolean;
/**
* Unmount the tab (remove it from the DOM) when it is no longer visible
*/
unmountOnExit?: boolean;
}
export interface TabPanelMetadata extends TransitionCallbacks {
eventKey?: EventKey;
isActive?: boolean;
transition?: TransitionComponent;
mountOnEnter?: boolean;
unmountOnExit?: boolean;
}
export declare function useTabPanel({ active, eventKey, mountOnEnter, transition, unmountOnExit, role, onEnter, onEntering, onEntered, onExit, onExiting, onExited, ...props }: TabPanelProps): [any, TabPanelMetadata];
declare const TabPanel: DynamicRefForwardingComponent<'div', TabPanelProps>;
export default TabPanel;

View File

@@ -0,0 +1,113 @@
const _excluded = ["active", "eventKey", "mountOnEnter", "transition", "unmountOnExit", "role", "onEnter", "onEntering", "onEntered", "onExit", "onExiting", "onExited"],
_excluded2 = ["activeKey", "getControlledId", "getControllerId"],
_excluded3 = ["as"];
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
import * as React from 'react';
import { useContext } from 'react';
import TabContext from './TabContext';
import SelectableContext, { makeEventKey } from './SelectableContext';
import NoopTransition from './NoopTransition';
import { jsx as _jsx } from "react/jsx-runtime";
export function useTabPanel(_ref) {
let {
active,
eventKey,
mountOnEnter,
transition,
unmountOnExit,
role = 'tabpanel',
onEnter,
onEntering,
onEntered,
onExit,
onExiting,
onExited
} = _ref,
props = _objectWithoutPropertiesLoose(_ref, _excluded);
const context = useContext(TabContext);
if (!context) return [Object.assign({}, props, {
role
}), {
eventKey,
isActive: active,
mountOnEnter,
transition,
unmountOnExit,
onEnter,
onEntering,
onEntered,
onExit,
onExiting,
onExited
}];
const {
activeKey,
getControlledId,
getControllerId
} = context,
rest = _objectWithoutPropertiesLoose(context, _excluded2);
const key = makeEventKey(eventKey);
return [Object.assign({}, props, {
role,
id: getControlledId(eventKey),
'aria-labelledby': getControllerId(eventKey)
}), {
eventKey,
isActive: active == null && key != null ? makeEventKey(activeKey) === key : active,
transition: transition || rest.transition,
mountOnEnter: mountOnEnter != null ? mountOnEnter : rest.mountOnEnter,
unmountOnExit: unmountOnExit != null ? unmountOnExit : rest.unmountOnExit,
onEnter,
onEntering,
onEntered,
onExit,
onExiting,
onExited
}];
}
const TabPanel = /*#__PURE__*/React.forwardRef(
// Need to define the default "as" during prop destructuring to be compatible with styled-components github.com/react-bootstrap/react-bootstrap/issues/3595
(_ref2, ref) => {
let {
as: Component = 'div'
} = _ref2,
props = _objectWithoutPropertiesLoose(_ref2, _excluded3);
const [tabPanelProps, {
isActive,
onEnter,
onEntering,
onEntered,
onExit,
onExiting,
onExited,
mountOnEnter,
unmountOnExit,
transition: Transition = NoopTransition
}] = useTabPanel(props);
// We provide an empty the TabContext so `<Nav>`s in `<TabPanel>`s don't
// conflict with the top level one.
return /*#__PURE__*/_jsx(TabContext.Provider, {
value: null,
children: /*#__PURE__*/_jsx(SelectableContext.Provider, {
value: null,
children: /*#__PURE__*/_jsx(Transition, {
in: isActive,
onEnter: onEnter,
onEntering: onEntering,
onEntered: onEntered,
onExit: onExit,
onExiting: onExiting,
onExited: onExited,
mountOnEnter: mountOnEnter,
unmountOnExit: unmountOnExit,
children: /*#__PURE__*/_jsx(Component, Object.assign({}, tabPanelProps, {
ref: ref,
hidden: !isActive,
"aria-hidden": !isActive
}))
})
})
});
});
TabPanel.displayName = 'TabPanel';
export default TabPanel;

View File

@@ -0,0 +1,53 @@
import * as React from 'react';
import { EventKey, SelectCallback, TransitionComponent } from './types';
import { TabPanelProps } from './TabPanel';
export type { TabPanelProps };
export interface TabsProps extends React.PropsWithChildren<unknown> {
id?: string;
/**
* Sets a default animation strategy for all children `<TabPanel>`s.
* Use a react-transition-group `<Transition/>` component.
*/
transition?: TransitionComponent;
/**
* Wait until the first "enter" transition to mount tabs (add them to the DOM)
*/
mountOnEnter?: boolean;
/**
* Unmount tabs (remove it from the DOM) when they are no longer visible
*/
unmountOnExit?: boolean;
/**
* A function that takes an `eventKey` and `type` and returns a unique id for
* child tab `<NavItem>`s and `<TabPane>`s. The function _must_ be a pure
* function, meaning it should always return the _same_ id for the same set
* of inputs. The default value requires that an `id` to be set for the
* `<TabContainer>`.
*
* The `type` argument will either be `"tab"` or `"pane"`.
*
* @defaultValue (eventKey, type) => `${props.id}-${type}-${eventKey}`
*/
generateChildId?: (eventKey: EventKey, type: 'tab' | 'pane') => string;
/**
* A callback fired when a tab is selected.
*
* @controllable activeKey
*/
onSelect?: SelectCallback;
/**
* The `eventKey` of the currently active tab.
*
* @controllable onSelect
*/
activeKey?: EventKey;
/**
* Default value for `eventKey`.
*/
defaultActiveKey?: EventKey;
}
declare const Tabs: {
(props: TabsProps): React.JSX.Element;
Panel: import("./types").DynamicRefForwardingComponent<"div", TabPanelProps>;
};
export default Tabs;

42
backend/frontend/node_modules/@restart/ui/esm/Tabs.js generated vendored Normal file
View File

@@ -0,0 +1,42 @@
import * as React from 'react';
import { useMemo } from 'react';
import { useUncontrolledProp } from 'uncontrollable';
import { useSSRSafeId } from './ssr';
import TabContext from './TabContext';
import SelectableContext from './SelectableContext';
import TabPanel from './TabPanel';
import { jsx as _jsx } from "react/jsx-runtime";
const Tabs = props => {
const {
id: userId,
generateChildId: generateCustomChildId,
onSelect: propsOnSelect,
activeKey: propsActiveKey,
defaultActiveKey,
transition,
mountOnEnter,
unmountOnExit,
children
} = props;
const [activeKey, onSelect] = useUncontrolledProp(propsActiveKey, defaultActiveKey, propsOnSelect);
const id = useSSRSafeId(userId);
const generateChildId = useMemo(() => generateCustomChildId || ((key, type) => id ? `${id}-${type}-${key}` : null), [id, generateCustomChildId]);
const tabContext = useMemo(() => ({
onSelect,
activeKey,
transition,
mountOnEnter: mountOnEnter || false,
unmountOnExit: unmountOnExit || false,
getControlledId: key => generateChildId(key, 'tabpane'),
getControllerId: key => generateChildId(key, 'tab')
}), [onSelect, activeKey, transition, mountOnEnter, unmountOnExit, generateChildId]);
return /*#__PURE__*/_jsx(TabContext.Provider, {
value: tabContext,
children: /*#__PURE__*/_jsx(SelectableContext.Provider, {
value: onSelect || null,
children: children
})
});
};
Tabs.Panel = TabPanel;
export default Tabs;

View File

@@ -0,0 +1,19 @@
import * as React from 'react';
import { WaypointOptions, WaypointEvent, Position } from './useWaypoint';
export { Position };
export type { WaypointEvent };
export interface WaypointProps extends WaypointOptions {
renderComponent?: (ref: React.RefCallback<any>) => React.ReactElement;
/**
* The callback fired when a waypoint's position is updated. This generally
* fires as a waypoint enters or exits the viewport but will also be called
* on mount.
*/
onPositionChange: (details: WaypointEvent, entry: IntersectionObserverEntry) => void;
}
/**
* A component that tracks when it enters or leaves the viewport. Implemented
* using IntersectionObserver, polyfill may be required for older browsers.
*/
declare function Waypoint({ renderComponent, onPositionChange, ...options }: WaypointProps): React.ReactElement<any, string | React.JSXElementConstructor<any>>;
export default Waypoint;

View File

@@ -0,0 +1,28 @@
const _excluded = ["renderComponent", "onPositionChange"];
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
import useCallbackRef from '@restart/hooks/useCallbackRef';
import * as React from 'react';
import useWaypoint, { Position } from './useWaypoint';
import { jsx as _jsx } from "react/jsx-runtime";
export { Position };
const defaultRenderComponent = ref => /*#__PURE__*/_jsx("span", {
ref: ref,
style: {
fontSize: 0
}
});
/**
* A component that tracks when it enters or leaves the viewport. Implemented
* using IntersectionObserver, polyfill may be required for older browsers.
*/
function Waypoint(_ref) {
let {
renderComponent = defaultRenderComponent,
onPositionChange
} = _ref,
options = _objectWithoutPropertiesLoose(_ref, _excluded);
const [element, setElement] = useCallbackRef();
useWaypoint(element, onPositionChange, options);
return renderComponent(setElement);
}
export default Waypoint;

View File

@@ -0,0 +1,4 @@
/**
* Get the width of the vertical window scrollbar if it's visible
*/
export default function getBodyScrollbarWidth(ownerDocument?: Document): number;

View File

@@ -0,0 +1,7 @@
/**
* Get the width of the vertical window scrollbar if it's visible
*/
export default function getBodyScrollbarWidth(ownerDocument = document) {
const window = ownerDocument.defaultView;
return Math.abs(window.innerWidth - ownerDocument.documentElement.clientWidth);
}

View File

@@ -0,0 +1,21 @@
import Dropdown from './Dropdown';
import { useDropdownMenu } from './DropdownMenu';
import { useDropdownToggle } from './DropdownToggle';
import { useDropdownItem } from './DropdownItem';
import Modal from './Modal';
import Overlay from './Overlay';
import Portal from './Portal';
import useRootClose from './useRootClose';
import Nav from './Nav';
import NavItem, { useNavItem } from './NavItem';
import Button from './Button';
import Tabs from './Tabs';
import TabPanel from './TabPanel';
export { Button, Dropdown, useDropdownMenu, useDropdownToggle, useDropdownItem, Nav, NavItem, useNavItem, Modal, Overlay, Portal, useRootClose, Tabs, TabPanel, };
export type { ButtonProps } from './Button';
export type { DropdownProps, DropdownMenuProps, UseDropdownMenuMetadata, UseDropdownMenuOptions, DropdownToggleProps, UseDropdownToggleMetadata, DropdownItemProps, } from './Dropdown';
export type { NavItemProps, UseNavItemOptions, NavProps } from './Nav';
export type { ModalProps } from './Modal';
export type { OverlayProps } from './Overlay';
export type { PortalProps } from './Portal';
export type { TabsProps, TabPanelProps } from './Tabs';

14
backend/frontend/node_modules/@restart/ui/esm/index.js generated vendored Normal file
View File

@@ -0,0 +1,14 @@
import Dropdown from './Dropdown';
import { useDropdownMenu } from './DropdownMenu';
import { useDropdownToggle } from './DropdownToggle';
import { useDropdownItem } from './DropdownItem';
import Modal from './Modal';
import Overlay from './Overlay';
import Portal from './Portal';
import useRootClose from './useRootClose';
import Nav from './Nav';
import NavItem, { useNavItem } from './NavItem';
import Button from './Button';
import Tabs from './Tabs';
import TabPanel from './TabPanel';
export { Button, Dropdown, useDropdownMenu, useDropdownToggle, useDropdownItem, Nav, NavItem, useNavItem, Modal, Overlay, Portal, useRootClose, Tabs, TabPanel };

View File

@@ -0,0 +1,16 @@
import { UsePopperOptions, Offset, Placement, Modifiers } from './usePopper';
export type Config = {
flip?: boolean;
fixed?: boolean;
alignEnd?: boolean;
enabled?: boolean;
containerPadding?: number;
arrowElement?: Element | null;
enableEvents?: boolean;
offset?: Offset;
placement?: Placement;
popperConfig?: UsePopperOptions;
};
export declare function toModifierMap(modifiers: Modifiers | undefined): Record<string, Partial<import("./usePopper").Modifier<any, any>>>;
export declare function toModifierArray(map?: Modifiers | undefined): Partial<import("@popperjs/core").Modifier<any, any>>[];
export default function mergeOptionsWithPopperConfig({ enabled, enableEvents, placement, flip, offset, fixed, containerPadding, arrowElement, popperConfig, }: Config): UsePopperOptions;

View File

@@ -0,0 +1,63 @@
export function toModifierMap(modifiers) {
const result = {};
if (!Array.isArray(modifiers)) {
return modifiers || result;
}
// eslint-disable-next-line no-unused-expressions
modifiers == null ? void 0 : modifiers.forEach(m => {
result[m.name] = m;
});
return result;
}
export function toModifierArray(map = {}) {
if (Array.isArray(map)) return map;
return Object.keys(map).map(k => {
map[k].name = k;
return map[k];
});
}
export default function mergeOptionsWithPopperConfig({
enabled,
enableEvents,
placement,
flip,
offset,
fixed,
containerPadding,
arrowElement,
popperConfig = {}
}) {
var _modifiers$eventListe, _modifiers$preventOve, _modifiers$preventOve2, _modifiers$offset, _modifiers$arrow;
const modifiers = toModifierMap(popperConfig.modifiers);
return Object.assign({}, popperConfig, {
placement,
enabled,
strategy: fixed ? 'fixed' : popperConfig.strategy,
modifiers: toModifierArray(Object.assign({}, modifiers, {
eventListeners: {
enabled: enableEvents,
options: (_modifiers$eventListe = modifiers.eventListeners) == null ? void 0 : _modifiers$eventListe.options
},
preventOverflow: Object.assign({}, modifiers.preventOverflow, {
options: containerPadding ? Object.assign({
padding: containerPadding
}, (_modifiers$preventOve = modifiers.preventOverflow) == null ? void 0 : _modifiers$preventOve.options) : (_modifiers$preventOve2 = modifiers.preventOverflow) == null ? void 0 : _modifiers$preventOve2.options
}),
offset: {
options: Object.assign({
offset
}, (_modifiers$offset = modifiers.offset) == null ? void 0 : _modifiers$offset.options)
},
arrow: Object.assign({}, modifiers.arrow, {
enabled: !!arrowElement,
options: Object.assign({}, (_modifiers$arrow = modifiers.arrow) == null ? void 0 : _modifiers$arrow.options, {
element: arrowElement
})
}),
flip: Object.assign({
enabled: !!flip
}, modifiers.flip)
}))
});
}

View File

@@ -0,0 +1,3 @@
import { placements } from '@popperjs/core/lib/enums';
export declare const createPopper: <TModifier extends Partial<import("@popperjs/core/lib/types").Modifier<any, any>>>(reference: Element | import("@popperjs/core/lib/types").VirtualElement, popper: HTMLElement, options?: Partial<import("@popperjs/core/lib/types").OptionsGeneric<TModifier>> | undefined) => import("@popperjs/core/lib/types").Instance;
export { placements };

View File

@@ -0,0 +1,17 @@
import arrow from '@popperjs/core/lib/modifiers/arrow';
import computeStyles from '@popperjs/core/lib/modifiers/computeStyles';
import eventListeners from '@popperjs/core/lib/modifiers/eventListeners';
import flip from '@popperjs/core/lib/modifiers/flip';
import hide from '@popperjs/core/lib/modifiers/hide';
import offset from '@popperjs/core/lib/modifiers/offset';
import popperOffsets from '@popperjs/core/lib/modifiers/popperOffsets';
import preventOverflow from '@popperjs/core/lib/modifiers/preventOverflow';
import { placements } from '@popperjs/core/lib/enums';
import { popperGenerator } from '@popperjs/core/lib/popper-base';
// For the common JS build we will turn this file into a bundle with no imports.
// This is b/c the Popper lib is all esm files, and would break in a common js only environment
export const createPopper = popperGenerator({
defaultModifiers: [hide, popperOffsets, computeStyles, eventListeners, offset, flip, preventOverflow, arrow]
});
export { placements };

View File

@@ -0,0 +1,3 @@
import { useSSRSafeId, useIsSSR, SSRProvider, SSRProviderProps } from '@react-aria/ssr';
export type { SSRProviderProps };
export { useSSRSafeId, useIsSSR, SSRProvider };

2
backend/frontend/node_modules/@restart/ui/esm/ssr.js generated vendored Normal file
View File

@@ -0,0 +1,2 @@
import { useSSRSafeId, useIsSSR, SSRProvider } from '@react-aria/ssr';
export { useSSRSafeId, useIsSSR, SSRProvider };

View File

@@ -0,0 +1,70 @@
import * as React from 'react';
export type EventKey = string | number;
export type IntrinsicElementTypes = keyof JSX.IntrinsicElements;
export type AssignPropsWithRef<Inner extends string | React.ComponentType<any>, P> = Omit<React.ComponentPropsWithRef<Inner extends React.ElementType ? Inner : never>, keyof P> & P;
export type { AssignPropsWithRef as AssignProps };
export type AssignPropsWithoutRef<Inner extends string | React.ComponentType<any>, P> = Omit<React.ComponentPropsWithoutRef<Inner extends React.ElementType ? Inner : never>, keyof P> & P;
export interface DynamicRefForwardingComponent<TInitial extends string | React.ComponentType<any>, P = {
children?: React.ReactNode;
}> {
<As extends string | React.ComponentType<any> = TInitial>(props: AssignPropsWithRef<As, {
as?: As;
} & P>, context?: any): React.ReactElement | null;
propTypes?: any;
contextTypes?: any;
defaultProps?: Partial<P>;
displayName?: string;
}
export interface DynamicFunctionComponent<TInitial extends string | React.ComponentType<any>, P = {
children?: React.ReactNode;
}> {
<As extends string | React.ComponentType<any> = TInitial>(props: AssignPropsWithoutRef<As, {
as?: As;
} & P>, context?: any): React.ReactElement | null;
propTypes?: any;
contextTypes?: any;
defaultProps?: Partial<P>;
displayName?: string;
}
export declare class DynamicComponent<As extends string | React.ComponentType<any>, P = unknown> extends React.Component<AssignPropsWithRef<As, {
as?: As;
} & P>> {
}
export type DynamicComponentClass<As extends string | React.ComponentType<any>, P = unknown> = React.ComponentClass<AssignPropsWithRef<As, {
as?: As;
} & P>>;
export type SelectCallback = (eventKey: string | null, e: React.SyntheticEvent<unknown>) => void;
export interface TransitionCallbacks {
/**
* Callback fired before the component transitions in
*/
onEnter?(node: HTMLElement, isAppearing: boolean): any;
/**
* Callback fired as the component begins to transition in
*/
onEntering?(node: HTMLElement, isAppearing: boolean): any;
/**
* Callback fired after the component finishes transitioning in
*/
onEntered?(node: HTMLElement, isAppearing: boolean): any;
/**
* Callback fired right before the component transitions out
*/
onExit?(node: HTMLElement): any;
/**
* Callback fired as the component begins to transition out
*/
onExiting?(node: HTMLElement): any;
/**
* Callback fired after the component finishes transitioning out
*/
onExited?(node: HTMLElement): any;
}
export interface TransitionProps extends TransitionCallbacks {
in?: boolean;
appear?: boolean;
children: React.ReactElement;
mountOnEnter?: boolean;
unmountOnExit?: boolean;
}
export type TransitionComponent = React.ComponentType<TransitionProps>;

View File

@@ -0,0 +1,4 @@
import * as React from 'react';
export class DynamicComponent extends React.Component {}
// Need to use this instead of typeof Component to get proper type checking.

View File

@@ -0,0 +1,21 @@
/// <reference types="react" />
export type MouseEvents = {
[K in keyof GlobalEventHandlersEventMap]: GlobalEventHandlersEventMap[K] extends MouseEvent ? K : never;
}[keyof GlobalEventHandlersEventMap];
export declare const getRefTarget: (ref: React.RefObject<Element> | Element | null | undefined) => Element | null | undefined;
export interface ClickOutsideOptions {
disabled?: boolean;
clickTrigger?: MouseEvents;
}
/**
* The `useClickOutside` hook registers your callback on the document that fires
* when a pointer event is registered outside of the provided ref or element.
*
* @param {Ref<HTMLElement>| HTMLElement} ref The element boundary
* @param {function} onClickOutside
* @param {object=} options
* @param {boolean=} options.disabled
* @param {string=} options.clickTrigger The DOM event name (click, mousedown, etc) to attach listeners on
*/
declare function useClickOutside(ref: React.RefObject<Element> | Element | null | undefined, onClickOutside?: (e: Event) => void, { disabled, clickTrigger }?: ClickOutsideOptions): void;
export default useClickOutside;

View File

@@ -0,0 +1,99 @@
import contains from 'dom-helpers/contains';
import listen from 'dom-helpers/listen';
import ownerDocument from 'dom-helpers/ownerDocument';
import { useCallback, useEffect, useRef } from 'react';
import useEventCallback from '@restart/hooks/useEventCallback';
import warning from 'warning';
const noop = () => {};
function isLeftClickEvent(event) {
return event.button === 0;
}
function isModifiedEvent(event) {
return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
}
export const getRefTarget = ref => ref && ('current' in ref ? ref.current : ref);
const InitialTriggerEvents = {
click: 'mousedown',
mouseup: 'mousedown',
pointerup: 'pointerdown'
};
/**
* The `useClickOutside` hook registers your callback on the document that fires
* when a pointer event is registered outside of the provided ref or element.
*
* @param {Ref<HTMLElement>| HTMLElement} ref The element boundary
* @param {function} onClickOutside
* @param {object=} options
* @param {boolean=} options.disabled
* @param {string=} options.clickTrigger The DOM event name (click, mousedown, etc) to attach listeners on
*/
function useClickOutside(ref, onClickOutside = noop, {
disabled,
clickTrigger = 'click'
} = {}) {
const preventMouseClickOutsideRef = useRef(false);
const waitingForTrigger = useRef(false);
const handleMouseCapture = useCallback(e => {
const currentTarget = getRefTarget(ref);
warning(!!currentTarget, 'ClickOutside captured a close event but does not have a ref to compare it to. ' + 'useClickOutside(), should be passed a ref that resolves to a DOM node');
preventMouseClickOutsideRef.current = !currentTarget || isModifiedEvent(e) || !isLeftClickEvent(e) || !!contains(currentTarget, e.target) || waitingForTrigger.current;
waitingForTrigger.current = false;
}, [ref]);
const handleInitialMouse = useEventCallback(e => {
const currentTarget = getRefTarget(ref);
if (currentTarget && contains(currentTarget, e.target)) {
waitingForTrigger.current = true;
} else {
// When clicking on scrollbars within current target, click events are not triggered, so this ref
// is never reset inside `handleMouseCapture`. This would cause a bug where it requires 2 clicks
// to close the overlay.
waitingForTrigger.current = false;
}
});
const handleMouse = useEventCallback(e => {
if (!preventMouseClickOutsideRef.current) {
onClickOutside(e);
}
});
useEffect(() => {
var _ownerWindow$event, _ownerWindow$parent;
if (disabled || ref == null) return undefined;
const doc = ownerDocument(getRefTarget(ref));
const ownerWindow = doc.defaultView || window;
// Store the current event to avoid triggering handlers immediately
// For things rendered in an iframe, the event might originate on the parent window
// so we should fall back to that global event if the local one doesn't exist
// https://github.com/facebook/react/issues/20074
let currentEvent = (_ownerWindow$event = ownerWindow.event) != null ? _ownerWindow$event : (_ownerWindow$parent = ownerWindow.parent) == null ? void 0 : _ownerWindow$parent.event;
let removeInitialTriggerListener = null;
if (InitialTriggerEvents[clickTrigger]) {
removeInitialTriggerListener = listen(doc, InitialTriggerEvents[clickTrigger], handleInitialMouse, true);
}
// Use capture for this listener so it fires before React's listener, to
// avoid false positives in the contains() check below if the target DOM
// element is removed in the React mouse callback.
const removeMouseCaptureListener = listen(doc, clickTrigger, handleMouseCapture, true);
const removeMouseListener = listen(doc, clickTrigger, e => {
// skip if this event is the same as the one running when we added the handlers
if (e === currentEvent) {
currentEvent = undefined;
return;
}
handleMouse(e);
});
let mobileSafariHackListeners = [];
if ('ontouchstart' in doc.documentElement) {
mobileSafariHackListeners = [].slice.call(doc.body.children).map(el => listen(el, 'mousemove', noop));
}
return () => {
removeInitialTriggerListener == null ? void 0 : removeInitialTriggerListener();
removeMouseCaptureListener();
removeMouseListener();
mobileSafariHackListeners.forEach(remove => remove());
};
}, [ref, disabled, clickTrigger, handleMouseCapture, handleInitialMouse, handleMouse]);
}
export default useClickOutside;

View File

@@ -0,0 +1,50 @@
import * as Popper from '@popperjs/core';
export type Modifier<Name, Options extends Popper.Obj> = Popper.Modifier<Name, Options>;
export type Options = Popper.Options;
export type Instance = Popper.Instance;
export type Placement = Popper.Placement;
export type VirtualElement = Popper.VirtualElement;
export type State = Popper.State;
export type OffsetValue = [
number | null | undefined,
number | null | undefined
];
export type OffsetFunction = (details: {
popper: Popper.Rect;
reference: Popper.Rect;
placement: Placement;
}) => OffsetValue;
export type Offset = OffsetFunction | OffsetValue;
export type ModifierMap = Record<string, Partial<Modifier<any, any>>>;
export type Modifiers = Popper.Options['modifiers'] | Record<string, Partial<Modifier<any, any>>>;
export type UsePopperOptions = Omit<Options, 'modifiers' | 'placement' | 'strategy'> & {
enabled?: boolean;
placement?: Options['placement'];
strategy?: Options['strategy'];
modifiers?: Options['modifiers'];
};
export interface UsePopperState {
placement: Placement;
update: () => void;
forceUpdate: () => void;
attributes: Record<string, Record<string, any>>;
styles: Record<string, Partial<CSSStyleDeclaration>>;
state?: State;
}
/**
* Position an element relative some reference element using Popper.js
*
* @param referenceElement
* @param popperElement
* @param {object} options
* @param {object=} options.modifiers Popper.js modifiers
* @param {boolean=} options.enabled toggle the popper functionality on/off
* @param {string=} options.placement The popper element placement relative to the reference element
* @param {string=} options.strategy the positioning strategy
* @param {function=} options.onCreate called when the popper is created
* @param {function=} options.onUpdate called when the popper is updated
*
* @returns {UsePopperState} The popper state
*/
declare function usePopper(referenceElement: VirtualElement | null | undefined, popperElement: HTMLElement | null | undefined, { enabled, placement, strategy, modifiers, ...config }?: UsePopperOptions): UsePopperState;
export default usePopper;

View File

@@ -0,0 +1,158 @@
const _excluded = ["enabled", "placement", "strategy", "modifiers"];
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { dequal } from 'dequal';
import useSafeState from '@restart/hooks/useSafeState';
import { createPopper } from './popper';
const disabledApplyStylesModifier = {
name: 'applyStyles',
enabled: false,
phase: 'afterWrite',
fn: () => undefined
};
// until docjs supports type exports...
const ariaDescribedByModifier = {
name: 'ariaDescribedBy',
enabled: true,
phase: 'afterWrite',
effect: ({
state
}) => () => {
const {
reference,
popper
} = state.elements;
if ('removeAttribute' in reference) {
const ids = (reference.getAttribute('aria-describedby') || '').split(',').filter(id => id.trim() !== popper.id);
if (!ids.length) reference.removeAttribute('aria-describedby');else reference.setAttribute('aria-describedby', ids.join(','));
}
},
fn: ({
state
}) => {
var _popper$getAttribute;
const {
popper,
reference
} = state.elements;
const role = (_popper$getAttribute = popper.getAttribute('role')) == null ? void 0 : _popper$getAttribute.toLowerCase();
if (popper.id && role === 'tooltip' && 'setAttribute' in reference) {
const ids = reference.getAttribute('aria-describedby');
if (ids && ids.split(',').indexOf(popper.id) !== -1) {
return;
}
reference.setAttribute('aria-describedby', ids ? `${ids},${popper.id}` : popper.id);
}
}
};
const EMPTY_MODIFIERS = [];
/**
* Position an element relative some reference element using Popper.js
*
* @param referenceElement
* @param popperElement
* @param {object} options
* @param {object=} options.modifiers Popper.js modifiers
* @param {boolean=} options.enabled toggle the popper functionality on/off
* @param {string=} options.placement The popper element placement relative to the reference element
* @param {string=} options.strategy the positioning strategy
* @param {function=} options.onCreate called when the popper is created
* @param {function=} options.onUpdate called when the popper is updated
*
* @returns {UsePopperState} The popper state
*/
function usePopper(referenceElement, popperElement, _ref = {}) {
let {
enabled = true,
placement = 'bottom',
strategy = 'absolute',
modifiers = EMPTY_MODIFIERS
} = _ref,
config = _objectWithoutPropertiesLoose(_ref, _excluded);
const prevModifiers = useRef(modifiers);
const popperInstanceRef = useRef();
const update = useCallback(() => {
var _popperInstanceRef$cu;
(_popperInstanceRef$cu = popperInstanceRef.current) == null ? void 0 : _popperInstanceRef$cu.update();
}, []);
const forceUpdate = useCallback(() => {
var _popperInstanceRef$cu2;
(_popperInstanceRef$cu2 = popperInstanceRef.current) == null ? void 0 : _popperInstanceRef$cu2.forceUpdate();
}, []);
const [popperState, setState] = useSafeState(useState({
placement,
update,
forceUpdate,
attributes: {},
styles: {
popper: {},
arrow: {}
}
}));
const updateModifier = useMemo(() => ({
name: 'updateStateModifier',
enabled: true,
phase: 'write',
requires: ['computeStyles'],
fn: ({
state
}) => {
const styles = {};
const attributes = {};
Object.keys(state.elements).forEach(element => {
styles[element] = state.styles[element];
attributes[element] = state.attributes[element];
});
setState({
state,
styles,
attributes,
update,
forceUpdate,
placement: state.placement
});
}
}), [update, forceUpdate, setState]);
const nextModifiers = useMemo(() => {
if (!dequal(prevModifiers.current, modifiers)) {
prevModifiers.current = modifiers;
}
return prevModifiers.current;
}, [modifiers]);
useEffect(() => {
if (!popperInstanceRef.current || !enabled) return;
popperInstanceRef.current.setOptions({
placement,
strategy,
modifiers: [...nextModifiers, updateModifier, disabledApplyStylesModifier]
});
}, [strategy, placement, updateModifier, enabled, nextModifiers]);
useEffect(() => {
if (!enabled || referenceElement == null || popperElement == null) {
return undefined;
}
popperInstanceRef.current = createPopper(referenceElement, popperElement, Object.assign({}, config, {
placement,
strategy,
modifiers: [...nextModifiers, ariaDescribedByModifier, updateModifier]
}));
return () => {
if (popperInstanceRef.current != null) {
popperInstanceRef.current.destroy();
popperInstanceRef.current = undefined;
setState(s => Object.assign({}, s, {
attributes: {},
styles: {
popper: {}
}
}));
}
};
// This is only run once to _create_ the popper
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [enabled, referenceElement, popperElement]);
return popperState;
}
export default usePopper;

View File

@@ -0,0 +1,49 @@
/// <reference types="react" />
import { TransitionProps as RTGTransitionProps, TransitionStatus } from 'react-transition-group/Transition';
export type TransitionProps = RTGTransitionProps & {
children: React.ReactElement | ((status: TransitionStatus, props: Record<string, unknown>) => React.ReactNode);
};
/**
* Normalizes RTG transition callbacks with nodeRef to better support
* strict mode.
*
* @param props Transition props.
* @returns Normalized transition props.
*/
export default function useRTGTransitionProps({ onEnter, onEntering, onEntered, onExit, onExiting, onExited, addEndListener, children, ...props }: TransitionProps): {
children: any;
addEndListener?: ((param: any) => void) | undefined;
onExited?: ((param: any) => void) | undefined;
onExiting?: ((param: any) => void) | undefined;
onExit?: ((param: any) => void) | undefined;
onEntered?: ((param: any) => void) | undefined;
onEntering?: ((param: any) => void) | undefined;
onEnter?: ((param: any) => void) | undefined;
nodeRef: import("react").RefObject<HTMLElement>;
timeout: number | {
appear?: number | undefined;
enter?: number | undefined;
exit?: number | undefined;
};
in?: boolean | undefined;
mountOnEnter?: boolean | undefined;
unmountOnExit?: boolean | undefined;
} | {
children: any;
addEndListener?: ((param: any) => void) | undefined;
onExited?: ((param: any) => void) | undefined;
onExiting?: ((param: any) => void) | undefined;
onExit?: ((param: any) => void) | undefined;
onEntered?: ((param: any) => void) | undefined;
onEntering?: ((param: any) => void) | undefined;
onEnter?: ((param: any) => void) | undefined;
nodeRef: import("react").RefObject<HTMLElement>;
timeout?: number | {
appear?: number | undefined;
enter?: number | undefined;
exit?: number | undefined;
} | undefined;
in?: boolean | undefined;
mountOnEnter?: boolean | undefined;
unmountOnExit?: boolean | undefined;
};

View File

@@ -0,0 +1,68 @@
const _excluded = ["onEnter", "onEntering", "onEntered", "onExit", "onExiting", "onExited", "addEndListener", "children"];
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
import { cloneElement, useCallback, useRef } from 'react';
import useMergedRefs from '@restart/hooks/useMergedRefs';
import { getChildRef } from './utils';
/**
* Normalizes RTG transition callbacks with nodeRef to better support
* strict mode.
*
* @param props Transition props.
* @returns Normalized transition props.
*/
export default function useRTGTransitionProps(_ref) {
let {
onEnter,
onEntering,
onEntered,
onExit,
onExiting,
onExited,
addEndListener,
children
} = _ref,
props = _objectWithoutPropertiesLoose(_ref, _excluded);
const nodeRef = useRef(null);
const mergedRef = useMergedRefs(nodeRef, getChildRef(children));
const normalize = callback => param => {
if (callback && nodeRef.current) {
callback(nodeRef.current, param);
}
};
/* eslint-disable react-hooks/exhaustive-deps */
const handleEnter = useCallback(normalize(onEnter), [onEnter]);
const handleEntering = useCallback(normalize(onEntering), [onEntering]);
const handleEntered = useCallback(normalize(onEntered), [onEntered]);
const handleExit = useCallback(normalize(onExit), [onExit]);
const handleExiting = useCallback(normalize(onExiting), [onExiting]);
const handleExited = useCallback(normalize(onExited), [onExited]);
const handleAddEndListener = useCallback(normalize(addEndListener), [addEndListener]);
/* eslint-enable react-hooks/exhaustive-deps */
return Object.assign({}, props, {
nodeRef
}, onEnter && {
onEnter: handleEnter
}, onEntering && {
onEntering: handleEntering
}, onEntered && {
onEntered: handleEntered
}, onExit && {
onExit: handleExit
}, onExiting && {
onExiting: handleExiting
}, onExited && {
onExited: handleExited
}, addEndListener && {
addEndListener: handleAddEndListener
}, {
children: typeof children === 'function' ? (status, innerProps) =>
// TODO: Types for RTG missing innerProps, so need to cast.
children(status, Object.assign({}, innerProps, {
ref: mergedRef
})) : /*#__PURE__*/cloneElement(children, {
ref: mergedRef
})
});
}

View File

@@ -0,0 +1,19 @@
/// <reference types="react" />
import { ClickOutsideOptions } from './useClickOutside';
export interface RootCloseOptions extends ClickOutsideOptions {
disabled?: boolean;
}
/**
* The `useRootClose` hook registers your callback on the document
* when rendered. Powers the `<Overlay/>` component. This is used achieve modal
* style behavior where your callback is triggered when the user tries to
* interact with the rest of the document or hits the `esc` key.
*
* @param {Ref<HTMLElement>| HTMLElement} ref The element boundary
* @param {function} onRootClose
* @param {object=} options
* @param {boolean=} options.disabled
* @param {string=} options.clickTrigger The DOM event name (click, mousedown, etc) to attach listeners on
*/
declare function useRootClose(ref: React.RefObject<Element> | Element | null | undefined, onRootClose: (e: Event) => void, { disabled, clickTrigger }?: RootCloseOptions): void;
export default useRootClose;

View File

@@ -0,0 +1,54 @@
import listen from 'dom-helpers/listen';
import ownerDocument from 'dom-helpers/ownerDocument';
import { useEffect } from 'react';
import useEventCallback from '@restart/hooks/useEventCallback';
import useClickOutside, { getRefTarget } from './useClickOutside';
import { isEscKey } from './utils';
const noop = () => {};
/**
* The `useRootClose` hook registers your callback on the document
* when rendered. Powers the `<Overlay/>` component. This is used achieve modal
* style behavior where your callback is triggered when the user tries to
* interact with the rest of the document or hits the `esc` key.
*
* @param {Ref<HTMLElement>| HTMLElement} ref The element boundary
* @param {function} onRootClose
* @param {object=} options
* @param {boolean=} options.disabled
* @param {string=} options.clickTrigger The DOM event name (click, mousedown, etc) to attach listeners on
*/
function useRootClose(ref, onRootClose, {
disabled,
clickTrigger
} = {}) {
const onClose = onRootClose || noop;
useClickOutside(ref, onClose, {
disabled,
clickTrigger
});
const handleKeyUp = useEventCallback(e => {
if (isEscKey(e)) {
onClose(e);
}
});
useEffect(() => {
if (disabled || ref == null) return undefined;
const doc = ownerDocument(getRefTarget(ref));
// Store the current event to avoid triggering handlers immediately
// https://github.com/facebook/react/issues/20074
let currentEvent = (doc.defaultView || window).event;
const removeKeyupListener = listen(doc, 'keyup', e => {
// skip if this event is the same as the one running when we added the handlers
if (e === currentEvent) {
currentEvent = undefined;
return;
}
handleKeyUp(e);
});
return () => {
removeKeyupListener();
};
}, [ref, disabled, handleKeyUp]);
}
export default useRootClose;

View File

@@ -0,0 +1 @@
export default function useScrollParent(element: null | Element): Element | Document | null | undefined;

View File

@@ -0,0 +1,12 @@
import useIsomorphicEffect from '@restart/hooks/useIsomorphicEffect';
import getScrollParent from 'dom-helpers/scrollParent';
import { useState } from 'react';
export default function useScrollParent(element) {
const [parent, setParent] = useState(null);
useIsomorphicEffect(() => {
if (element) {
setParent(getScrollParent(element, true));
}
}, [element]);
return parent;
}

View File

@@ -0,0 +1,5 @@
/// <reference types="react" />
import { VirtualElement } from './usePopper';
export type DOMContainer<T extends HTMLElement | VirtualElement = HTMLElement> = T | React.RefObject<T> | null | (() => T | React.RefObject<T> | null);
export declare const resolveContainerRef: <T extends HTMLElement | import("@popperjs/core").VirtualElement>(ref: DOMContainer<T> | undefined, document?: Document) => HTMLBodyElement | T | null;
export default function useWaitForDOMRef<T extends HTMLElement | VirtualElement = HTMLElement>(ref: DOMContainer<T> | undefined, onResolved?: (element: T | HTMLBodyElement) => void): HTMLBodyElement | T | null;

View File

@@ -0,0 +1,32 @@
import ownerDocument from 'dom-helpers/ownerDocument';
import canUseDOM from 'dom-helpers/canUseDOM';
import { useState, useEffect } from 'react';
import useWindow from './useWindow';
export const resolveContainerRef = (ref, document) => {
if (!canUseDOM) return null;
if (ref == null) return (document || ownerDocument()).body;
if (typeof ref === 'function') ref = ref();
if (ref && 'current' in ref) ref = ref.current;
if (ref && ('nodeType' in ref || ref.getBoundingClientRect)) return ref;
return null;
};
export default function useWaitForDOMRef(ref, onResolved) {
const window = useWindow();
const [resolvedRef, setRef] = useState(() => resolveContainerRef(ref, window == null ? void 0 : window.document));
if (!resolvedRef) {
const earlyRef = resolveContainerRef(ref);
if (earlyRef) setRef(earlyRef);
}
useEffect(() => {
if (onResolved && resolvedRef) {
onResolved(resolvedRef);
}
}, [onResolved, resolvedRef]);
useEffect(() => {
const nextRef = resolveContainerRef(ref);
if (nextRef !== resolvedRef) {
setRef(nextRef);
}
}, [ref, resolvedRef]);
return resolvedRef;
}

View File

@@ -0,0 +1,41 @@
export interface WaypointEvent {
position: Position;
previousPosition: Position | null;
}
export interface Rect {
top?: number;
bottom?: number;
left?: number;
right?: number;
}
export type WaypointCallback = (details: WaypointEvent, entry: IntersectionObserverEntry, observer: IntersectionObserver) => void;
export type RootElement = Element | Document | null | undefined;
/** Accepts all options an IntersectionObserver accepts */
export interface WaypointOptions extends Omit<IntersectionObserverInit, 'rootMargin' | 'root'> {
/**
* The "root" element to observe. This should be the scrollable view your waypoint
* is rendered into. Accepts a DOM element, a function that returns a DOM element, `null`
* indicating that the root is not ready yet, or the string "scrollParent" to
* have the waypoint calculate the scroll parent itself.
*/
root?: RootElement | 'scrollParent' | ((element: Element) => RootElement);
/**
* A valid CSS `margin` property or object containing the specific "top", "left", etc properties.
* The root margin functionally adjusts the "size" of the viewport when considering the waypoint's
* position. A positive margin will cause the waypoint to "enter" the waypoint early while a
* negative margin will have the opposite effect.
*/
rootMargin?: string | Rect;
/**
* Set the direction of the scroll to consider when tracking the waypoint's position
*/
scrollDirection?: 'vertical' | 'horizontal';
}
export declare enum Position {
UNKNOWN = 0,
BEFORE = 1,
INSIDE = 2,
AFTER = 3
}
declare function useWaypoint(element: Element | null, callback: WaypointCallback, options?: WaypointOptions): void;
export default useWaypoint;

View File

@@ -0,0 +1,89 @@
import useEventCallback from '@restart/hooks/useEventCallback';
import useIntersectionObserver from '@restart/hooks/useIntersectionObserver';
import { useMemo, useRef } from 'react';
import getScrollParent from 'dom-helpers/scrollParent';
/** Accepts all options an IntersectionObserver accepts */
export let Position;
(function (Position) {
Position[Position["UNKNOWN"] = 0] = "UNKNOWN";
Position[Position["BEFORE"] = 1] = "BEFORE";
Position[Position["INSIDE"] = 2] = "INSIDE";
Position[Position["AFTER"] = 3] = "AFTER";
})(Position || (Position = {}));
function toCss(margin) {
if (!margin || typeof margin === 'string') return margin;
const {
top = 0,
right = 0,
bottom = 0,
left = 0
} = margin;
return `${top}px ${right}px ${bottom}px ${left}px`;
}
const findRoot = el => getScrollParent(el, true);
function useWaypoint(element, callback, options = {}) {
const {
rootMargin,
threshold,
scrollDirection = 'vertical'
} = options;
let {
root
} = options;
const handler = useEventCallback(callback);
const prevPositionRef = useRef(null);
if (root === 'scrollParent') {
root = findRoot;
}
const scrollParent = useMemo(() => element && typeof root === 'function' ? root(element) : null, [element, root]);
let realRoot = typeof root === 'function' ? scrollParent : root;
if (realRoot && realRoot.nodeType === document.DOCUMENT_NODE) {
// explicit undefined means "use the viewport", instead of `null`
// which means "no root yet". This works around a bug in safari
// where document is not accepted in older versions,
// or is accepted but doesn't work (as of v14)
realRoot = undefined;
}
useIntersectionObserver(
// We change the meaning of explicit null to "not provided yet"
// this is to allow easier synchronizing between element and roots derived
// from it. Otherwise if the root updates later an observer will be created
// for the document and then for the root
element, ([entry], observer) => {
var _entry$rootBounds, _entry$rootBounds2;
if (!entry) return;
const [start, end, point] = scrollDirection === 'vertical' ? ['top', 'bottom', 'y'] : ['left', 'right', 'x'];
const {
[point]: coord
} = entry.boundingClientRect;
const rootStart = ((_entry$rootBounds = entry.rootBounds) == null ? void 0 : _entry$rootBounds[start]) || 0;
const rootEnd = ((_entry$rootBounds2 = entry.rootBounds) == null ? void 0 : _entry$rootBounds2[end]) || 0;
// The position may remain UNKNOWN if the root
// is 0 width/height or everything is hidden.
let position = Position.UNKNOWN;
if (entry.isIntersecting) {
position = Position.INSIDE;
} else if (coord > rootEnd) {
position = Position.AFTER;
} else if (coord < rootStart) {
position = Position.BEFORE;
}
const previousPosition = prevPositionRef.current;
if (previousPosition === position) {
return;
}
handler({
position,
previousPosition
}, entry, observer);
prevPositionRef.current = position;
}, {
threshold,
root: realRoot,
rootMargin: toCss(rootMargin)
});
}
export default useWaypoint;

View File

@@ -0,0 +1,9 @@
/// <reference types="react" />
export declare const WindowProvider: import("react").Provider<(Window & typeof globalThis) | undefined>;
/**
* The document "window" placed in React context. Helpful for determining
* SSR context, or when rendering into an iframe.
*
* @returns the current window
*/
export default function useWindow(): (Window & typeof globalThis) | undefined;

View File

@@ -0,0 +1,14 @@
import { createContext, useContext } from 'react';
import canUseDOM from 'dom-helpers/canUseDOM';
const Context = /*#__PURE__*/createContext(canUseDOM ? window : undefined);
export const WindowProvider = Context.Provider;
/**
* The document "window" placed in React context. Helpful for determining
* SSR context, or when rendering into an iframe.
*
* @returns the current window
*/
export default function useWindow() {
return useContext(Context);
}

View File

@@ -0,0 +1,8 @@
import * as React from 'react';
export declare function isEscKey(e: KeyboardEvent): boolean;
export declare function getReactVersion(): {
major: number;
minor: number;
patch: number;
};
export declare function getChildRef(element?: React.ReactElement | ((...args: any[]) => React.ReactNode) | null): any;

22
backend/frontend/node_modules/@restart/ui/esm/utils.js generated vendored Normal file
View File

@@ -0,0 +1,22 @@
import * as React from 'react';
export function isEscKey(e) {
return e.code === 'Escape' || e.keyCode === 27;
}
export function getReactVersion() {
const parts = React.version.split('.');
return {
major: +parts[0],
minor: +parts[1],
patch: +parts[2]
};
}
export function getChildRef(element) {
if (!element || typeof element === 'function') {
return null;
}
const {
major
} = getReactVersion();
const childRef = major >= 19 ? element.props.ref : element.ref;
return childRef;
}