reshaped 3.9.0 → 3.9.1-canary.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle.css +1 -1
- package/dist/bundle.js +2 -2
- package/dist/components/Accordion/AccordionControlled.js +0 -1
- package/dist/components/Actionable/Actionable.d.ts +8 -3
- package/dist/components/Actionable/Actionable.js +17 -70
- package/dist/components/Actionable/Actionable.types.d.ts +2 -36
- package/dist/components/Actionable/index.d.ts +2 -1
- package/dist/components/Badge/Badge.js +5 -4
- package/dist/components/Badge/Badge.module.css +1 -1
- package/dist/components/Calendar/Calendar.utils.js +6 -7
- package/dist/components/Card/Card.d.ts +1 -1
- package/dist/components/Carousel/Carousel.js +0 -1
- package/dist/components/Flyout/Flyout.module.css +1 -1
- package/dist/components/Flyout/Flyout.types.d.ts +7 -7
- package/dist/components/Flyout/FlyoutContent.js +3 -58
- package/dist/components/Flyout/FlyoutControlled.js +84 -83
- package/dist/components/Flyout/FlyoutTrigger.js +3 -3
- package/dist/components/Flyout/useFlyout.d.ts +3 -4
- package/dist/components/Flyout/useFlyout.js +70 -88
- package/dist/components/Flyout/utilities/safeArea.d.ts +10 -0
- package/dist/components/Flyout/utilities/safeArea.js +100 -0
- package/dist/components/Select/Select.js +1 -1
- package/dist/components/Select/SelectCustomControlled.js +0 -1
- package/dist/components/Tabs/TabsControlled.js +0 -1
- package/dist/components/Toast/ToastContainer.js +0 -1
- package/dist/components/_private/Expandable/Expandable.js +1 -3
- package/dist/components/_private/Portal/Portal.js +0 -3
- package/dist/core/Actionable/Actionable.d.ts +4 -0
- package/dist/core/Actionable/Actionable.js +73 -0
- package/dist/core/Actionable/Actionable.types.d.ts +34 -0
- package/dist/core/Actionable/Actionable.types.js +1 -0
- package/dist/core/Actionable/index.d.ts +2 -0
- package/dist/core/Actionable/index.js +1 -0
- package/dist/hooks/_private/usePrevious.js +0 -1
- package/dist/hooks/useOnClickOutside.js +8 -0
- package/dist/utilities/a11y/TrapFocus.js +9 -3
- package/dist/utilities/dom/index.d.ts +0 -1
- package/dist/utilities/dom/index.js +0 -1
- package/package.json +4 -2
- package/dist/components/Flyout/utilities/calculatePosition.d.ts +0 -31
- package/dist/components/Flyout/utilities/calculatePosition.js +0 -185
- package/dist/components/Flyout/utilities/constants.d.ts +0 -1
- package/dist/components/Flyout/utilities/constants.js +0 -1
- package/dist/components/Flyout/utilities/flyout.d.ts +0 -11
- package/dist/components/Flyout/utilities/flyout.js +0 -115
- package/dist/components/Flyout/utilities/getPositionFallbacks.d.ts +0 -3
- package/dist/components/Flyout/utilities/getPositionFallbacks.js +0 -39
- package/dist/components/Flyout/utilities/helpers.d.ts +0 -7
- package/dist/components/Flyout/utilities/helpers.js +0 -14
- package/dist/components/Flyout/utilities/isFullyVisible.d.ts +0 -13
- package/dist/components/Flyout/utilities/isFullyVisible.js +0 -23
- package/dist/utilities/dom/flyout.d.ts +0 -2
- package/dist/utilities/dom/flyout.js +0 -14
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { type ActionableRef as UnstyledActionableRef } from "../../core/Actionable";
|
|
2
|
+
declare const Actionable: import("react").ForwardRefExoticComponent<import("../../core/Actionable").ActionableProps & {
|
|
3
|
+
touchHitbox?: boolean;
|
|
4
|
+
fullWidth?: boolean;
|
|
5
|
+
insetFocus?: boolean;
|
|
6
|
+
disableFocusRing?: boolean;
|
|
7
|
+
borderRadius?: "inherit";
|
|
8
|
+
} & import("react").RefAttributes<UnstyledActionableRef>>;
|
|
4
9
|
export default Actionable;
|
|
@@ -1,77 +1,24 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx,
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { forwardRef } from "react";
|
|
4
|
-
import
|
|
5
|
-
import { classNames } from "../../utilities/props.js";
|
|
4
|
+
import UnstyledActionable from "../../core/Actionable/index.js";
|
|
6
5
|
import s from "./Actionable.module.css";
|
|
7
6
|
const Actionable = forwardRef((props, ref) => {
|
|
8
|
-
const {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
rootAttributes.href = disabled ? undefined : href || attributes?.href;
|
|
24
|
-
}
|
|
25
|
-
else if (renderedAsButton) {
|
|
26
|
-
TagName = "button";
|
|
27
|
-
rootAttributes.type = type || attributes?.type || "button";
|
|
28
|
-
rootAttributes.disabled = disabled || attributes?.disabled;
|
|
29
|
-
}
|
|
30
|
-
else if (isButton) {
|
|
31
|
-
const isFocusable = as === "label";
|
|
32
|
-
const simulateButton = !isFocusable || hasClickHandler || hasFocusHandler;
|
|
33
|
-
TagName = as || "span";
|
|
34
|
-
rootAttributes.role = simulateButton ? "button" : undefined;
|
|
35
|
-
rootAttributes.tabIndex = simulateButton ? 0 : undefined;
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
TagName = as || "span";
|
|
39
|
-
}
|
|
40
|
-
const handlePress = (event) => {
|
|
41
|
-
if (disabled)
|
|
42
|
-
return;
|
|
43
|
-
if (stopPropagation)
|
|
44
|
-
event.stopPropagation();
|
|
45
|
-
onClick?.(event);
|
|
46
|
-
attributes?.onClick?.(event);
|
|
47
|
-
};
|
|
48
|
-
const handleKeyDown = (event) => {
|
|
49
|
-
const isSpace = event.key === keys.SPACE;
|
|
50
|
-
const isEnter = event.key === keys.ENTER;
|
|
51
|
-
if (!isSpace && !isEnter)
|
|
52
|
-
return;
|
|
53
|
-
if (rootAttributes.role !== "button")
|
|
54
|
-
return;
|
|
55
|
-
if (stopPropagation)
|
|
56
|
-
event.stopPropagation();
|
|
57
|
-
event.preventDefault();
|
|
58
|
-
handlePress(event);
|
|
59
|
-
};
|
|
60
|
-
const childrenNode = (_jsxs(_Fragment, { children: [touchHitbox && (isLink || isButton) && !disabled && _jsx("span", { className: s.touch }), children] }));
|
|
61
|
-
const tagAttributes = {
|
|
62
|
-
ref: ref,
|
|
63
|
-
// rootAttributes can receive ref from Flyout
|
|
64
|
-
...rootAttributes,
|
|
65
|
-
className: rootClassNames,
|
|
66
|
-
onClick: handlePress,
|
|
67
|
-
onKeyDown: handleKeyDown,
|
|
68
|
-
"aria-disabled": disabled ? true : undefined,
|
|
69
|
-
children: childrenNode,
|
|
70
|
-
};
|
|
71
|
-
// eslint-disable-next-line react-hooks/refs
|
|
72
|
-
if (render)
|
|
73
|
-
return render(tagAttributes);
|
|
74
|
-
return _jsx(TagName, { ...tagAttributes });
|
|
7
|
+
const {
|
|
8
|
+
// Styled props
|
|
9
|
+
insetFocus, disableFocusRing, borderRadius, fullWidth, touchHitbox,
|
|
10
|
+
// Unstyled props used for internal behavior
|
|
11
|
+
children, className, disabled, ...unstyledProps } = props;
|
|
12
|
+
const rootClassNames = [
|
|
13
|
+
s.root,
|
|
14
|
+
className,
|
|
15
|
+
disabled && s["--disabled"],
|
|
16
|
+
borderRadius && s[`--radius-${borderRadius}`],
|
|
17
|
+
insetFocus && s["--inset"],
|
|
18
|
+
disableFocusRing && s["--disabled-focus-ring"],
|
|
19
|
+
fullWidth && s["--full-width"],
|
|
20
|
+
];
|
|
21
|
+
return (_jsxs(UnstyledActionable, { ...unstyledProps, className: rootClassNames, disabled: disabled, ref: ref, children: [touchHitbox && !disabled && _jsx("span", { className: s.touch }), children] }));
|
|
75
22
|
});
|
|
76
23
|
Actionable.displayName = "Actionable";
|
|
77
24
|
export default Actionable;
|
|
@@ -1,29 +1,5 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
3
|
-
export type AttributesRef = React.RefObject<HTMLButtonElement | null>;
|
|
4
|
-
type Attributes = G.Attributes<"button"> & Omit<React.JSX.IntrinsicElements["a"], keyof G.Attributes<"button">> & {
|
|
5
|
-
ref?: AttributesRef;
|
|
6
|
-
};
|
|
7
|
-
export type Props = {
|
|
8
|
-
/** Node for inserting the content */
|
|
9
|
-
children?: React.ReactNode;
|
|
10
|
-
/** Render a custom root element, useful for integrating with routers */
|
|
11
|
-
render?: (attributes: Attributes & {
|
|
12
|
-
ref: AttributesRef;
|
|
13
|
-
className: string;
|
|
14
|
-
onClick: (e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>) => void;
|
|
15
|
-
onKeyDown: (e: React.KeyboardEvent<HTMLElement>) => void;
|
|
16
|
-
"aria-disabled"?: boolean;
|
|
17
|
-
children: React.ReactNode;
|
|
18
|
-
}) => React.ReactNode;
|
|
19
|
-
/** Callback when clicked, renders it as a button tag if href is not provided */
|
|
20
|
-
onClick?: (e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>) => void;
|
|
21
|
-
/** URL, renders it as an anchor tag */
|
|
22
|
-
href?: string;
|
|
23
|
-
/** Type attribute, renders it as a button tag */
|
|
24
|
-
type?: React.ButtonHTMLAttributes<HTMLButtonElement>["type"];
|
|
25
|
-
/** Disable from user interaction */
|
|
26
|
-
disabled?: boolean;
|
|
1
|
+
import type { ActionableProps as UnstyledActionableProps } from "../../core/Actionable";
|
|
2
|
+
export type Props = UnstyledActionableProps & {
|
|
27
3
|
/** Enable a minimum required touch hitbox */
|
|
28
4
|
touchHitbox?: boolean;
|
|
29
5
|
/** Take up the full width of its parent */
|
|
@@ -34,14 +10,4 @@ export type Props = {
|
|
|
34
10
|
disableFocusRing?: boolean;
|
|
35
11
|
/** Apply the focus ring to the child and rely on its border radius */
|
|
36
12
|
borderRadius?: "inherit";
|
|
37
|
-
/** Prevent the event from bubbling up to the parent */
|
|
38
|
-
stopPropagation?: boolean;
|
|
39
|
-
/** Render as a different element */
|
|
40
|
-
as?: keyof React.JSX.IntrinsicElements;
|
|
41
|
-
/** Additional classname for the root element */
|
|
42
|
-
className?: G.ClassName;
|
|
43
|
-
/** Additional attributes for the root element */
|
|
44
|
-
attributes?: Attributes;
|
|
45
13
|
};
|
|
46
|
-
export type Ref = HTMLButtonElement | HTMLAnchorElement;
|
|
47
|
-
export {};
|
|
@@ -10,14 +10,15 @@ const Badge = forwardRef((props, ref) => {
|
|
|
10
10
|
const { children, color, rounded, size = "medium", icon, endIcon, variant, hidden, highlighted, href, onClick, onDismiss, dismissAriaLabel, className, attributes, as, } = props;
|
|
11
11
|
const isActionable = !!(onClick || href);
|
|
12
12
|
const iconSize = size === "small" ? 3 : 4;
|
|
13
|
-
const
|
|
14
|
-
const
|
|
13
|
+
const empty = !children && !icon && !endIcon;
|
|
14
|
+
const rootClassName = classNames(s.root, className, rounded && s["--rounded"], hidden && s["--hidden"], size && s[`--size-${size}`], color && s[`--color-${color}`], variant && s[`--variant-${variant}`], isActionable && s["--actionable"], highlighted && s["--highlighted"], empty && s["--empty"]);
|
|
15
|
+
const handleDismiss = (e) => {
|
|
15
16
|
e.stopPropagation();
|
|
16
17
|
onDismiss?.();
|
|
17
18
|
};
|
|
18
|
-
return (_jsxs(Actionable, { onClick: onClick, href: href, className: rootClassName, attributes: attributes, ref: ref, as: as, touchHitbox:
|
|
19
|
+
return (_jsxs(Actionable, { onClick: onClick, href: href, className: rootClassName, attributes: attributes, ref: ref, as: as, touchHitbox: isActionable, children: [icon && _jsx(Icon, { svg: icon, autoWidth: true, size: iconSize, className: s.icon }), children && (_jsx(Text, { variant: size === "large" ? "body-3" : "caption-1", weight: "medium", attributes: {
|
|
19
20
|
"aria-hidden": hidden ? "true" : undefined,
|
|
20
|
-
}, children: children })), endIcon && _jsx(Icon, { svg: endIcon, autoWidth: true, size: iconSize, className: s.icon }), onDismiss && (_jsx(Actionable, { onClick:
|
|
21
|
+
}, children: children })), endIcon && _jsx(Icon, { svg: endIcon, autoWidth: true, size: iconSize, className: s.icon }), onDismiss && (_jsx(Actionable, { onClick: handleDismiss, className: s.dismiss, as: "span", attributes: { "aria-label": dismissAriaLabel }, touchHitbox: true, children: _jsx(Icon, { svg: IconClose, size: iconSize }) }))] }));
|
|
21
22
|
});
|
|
22
23
|
Badge.displayName = "Badge";
|
|
23
24
|
export default Badge;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.root{--rs-badge-border-color:transparent;align-items:center;backface-visibility:hidden;background:var(--rs-color-background-neutral);border-radius:var(--rs-radius-small);box-shadow:0 0 0 1px var(--rs-badge-border-color) inset;box-sizing:border-box;color:var(--rs-color-foreground-neutral);display:inline-flex;gap:var(--rs-badge-gap);justify-content:center;min-height:calc(var(--rs-badge-line-height) + (var(--rs-badge-p-v) * 2));min-width:calc(var(--rs-badge-line-height) + (var(--rs-badge-p-v) * 2));padding:var(--rs-badge-p-v) var(--rs-badge-p-h);transition:var(--rs-duration-medium) var(--rs-easing-standard);transition-property:transform,opacity,box-shadow,background-color;vertical-align:top}.root
|
|
1
|
+
.root{--rs-badge-border-color:transparent;align-items:center;backface-visibility:hidden;background:var(--rs-color-background-neutral);border-radius:var(--rs-radius-small);box-shadow:0 0 0 1px var(--rs-badge-border-color) inset;box-sizing:border-box;color:var(--rs-color-foreground-neutral);display:inline-flex;gap:var(--rs-badge-gap);justify-content:center;min-height:calc(var(--rs-badge-line-height) + (var(--rs-badge-p-v) * 2));min-width:calc(var(--rs-badge-line-height) + (var(--rs-badge-p-v) * 2));padding:var(--rs-badge-p-v) var(--rs-badge-p-h);transition:var(--rs-duration-medium) var(--rs-easing-standard);transition-property:transform,opacity,box-shadow,background-color;vertical-align:top}.root.--empty{height:var(--rs-badge-empty-size);min-height:auto;min-width:auto;padding:0;width:var(--rs-badge-empty-size)}.icon:only-child{margin-inline:calc(var(--rs-unit-x1) * -1)}.dismiss{border-radius:var(--rs-radius-small);transition:var(--rs-duration-fast) var(--rs-easing-standard);transition-property:opacity}.root.--highlighted{opacity:.8}@media (hover:hover) and (pointer:fine){.root .dismiss:hover,.root.--actionable:hover:not(:has(.dismiss:hover)){opacity:.8}}.root.--variant-faded{background:var(--rs-color-background-neutral-faded);color:var(--rs-color-foreground-neutral-faded)}.root.--variant-outline{--rs-badge-border-color:var(--rs-color-border-neutral);background:none}.root.--color-positive{background:var(--rs-color-background-positive);color:var(--rs-color-on-background-positive)}.root.--color-positive.--variant-faded{background:var(--rs-color-background-positive-faded);color:var(--rs-color-foreground-positive)}.root.--color-positive.--variant-outline{--rs-badge-border-color:var(--rs-color-border-positive-faded);background:none;color:var(--rs-color-foreground-positive)}.root.--color-critical{background:var(--rs-color-background-critical);color:var(--rs-color-on-background-critical)}.root.--color-critical.--variant-faded{background:var(--rs-color-background-critical-faded);color:var(--rs-color-foreground-critical)}.root.--color-critical.--variant-outline{--rs-badge-border-color:var(--rs-color-border-critical-faded);background:none;color:var(--rs-color-foreground-critical)}.root.--color-warning{background:var(--rs-color-background-warning);color:var(--rs-color-on-background-warning)}.root.--color-warning.--variant-faded{background:var(--rs-color-background-warning-faded);color:var(--rs-color-foreground-warning)}.root.--color-warning.--variant-outline{--rs-badge-border-color:var(--rs-color-border-warning-faded);background:none;color:var(--rs-color-foreground-warning)}.root.--color-primary{background:var(--rs-color-background-primary);color:var(--rs-color-on-background-primary)}.root.--color-primary.--variant-faded{background:var(--rs-color-background-primary-faded);color:var(--rs-color-foreground-primary)}.root.--color-primary.--variant-outline{--rs-badge-border-color:var(--rs-color-border-primary-faded);background:none;color:var(--rs-color-foreground-primary)}.root.--size-small{--rs-badge-p-v:calc(var(--rs-unit-x1) / 2);--rs-badge-p-h:var(--rs-unit-x1);--rs-badge-line-height:var(--rs-line-height-caption-1);--rs-badge-empty-size:var(--rs-unit-x2);--rs-badge-gap:calc(var(--rs-unit-x1) / 2)}.root.--size-medium{--rs-badge-p-v:var(--rs-unit-x1);--rs-badge-p-h:var(--rs-unit-x2);--rs-badge-line-height:var(--rs-line-height-caption-1);--rs-badge-empty-size:var(--rs-unit-x3);--rs-badge-gap:var(--rs-unit-x1)}.root.--size-large{--rs-badge-p-v:var(--rs-unit-x1);--rs-badge-p-h:var(--rs-unit-x2);--rs-badge-line-height:var(--rs-line-height-body-3);--rs-badge-empty-size:var(--rs-unit-x4);--rs-badge-gap:var(--rs-unit-x1)}.root.--rounded{border-radius:var(--rs-radius-circular)}.root.--hidden{opacity:0;transform:scale(.2)}.container{display:inline-block;position:relative;vertical-align:top}.container .root{inset-inline-end:0;position:absolute;transform:translate(50%,var(--rs-badge-translate-y)) scale(1);user-select:none;z-index:10}.container .root.--hidden{transform:translate(50%,var(--rs-badge-translate-y)) scale(.2)}[dir=rtl] .container .root{transform:translate(-50%,var(--rs-badge-translate-y)) scale(1)}[dir=rtl] .container .root.--hidden{transform:translate(-50%,var(--rs-badge-translate-y)) scale(.2)}.--container-overlap .root{inset-inline-end:14%}.--container-position-top-end .root{--rs-badge-translate-y:-50%;top:0}.--container-position-top-end.--container-overlap .root{top:14%}.--container-position-bottom-end .root{--rs-badge-translate-y:50%;bottom:0}.--container-position-bottom-end.--container-overlap .root{bottom:14%}
|
|
@@ -108,6 +108,9 @@ export const applyNavigationBounds = (args) => {
|
|
|
108
108
|
isLastMonth: max && max < nextMonthFirstDate,
|
|
109
109
|
};
|
|
110
110
|
};
|
|
111
|
+
const isMonthMatch = (date1, date2) => {
|
|
112
|
+
return date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear();
|
|
113
|
+
};
|
|
111
114
|
/**
|
|
112
115
|
* Decide if date has to be focusable with Tab (only one date should be)
|
|
113
116
|
* 1. If there is a selected value - it's focusable
|
|
@@ -117,19 +120,15 @@ export const applyNavigationBounds = (args) => {
|
|
|
117
120
|
export const isDateFocusable = (args) => {
|
|
118
121
|
const { date, startValue, lastFocusedDate } = args;
|
|
119
122
|
const today = new Date();
|
|
120
|
-
const renderedMonth = date.getMonth();
|
|
121
|
-
const valueMonth = startValue?.getMonth();
|
|
122
|
-
const todayMonth = today.getMonth();
|
|
123
|
-
const lastFocusedMonth = lastFocusedDate?.getMonth();
|
|
124
123
|
const isoDate = getLocalISODate({ date });
|
|
125
124
|
const isoToday = getLocalISODate({ date: today });
|
|
126
125
|
const isoValueDate = startValue && getLocalISODate({ date: startValue });
|
|
127
126
|
const isoLastFocusedDate = lastFocusedDate && getLocalISODate({ date: lastFocusedDate });
|
|
128
|
-
if (lastFocusedDate &&
|
|
127
|
+
if (lastFocusedDate && isMonthMatch(date, lastFocusedDate))
|
|
129
128
|
return isoDate === isoLastFocusedDate;
|
|
130
|
-
if (startValue &&
|
|
129
|
+
if (startValue && isMonthMatch(date, startValue))
|
|
131
130
|
return isoDate === isoValueDate;
|
|
132
|
-
if (
|
|
131
|
+
if (isMonthMatch(date, today))
|
|
133
132
|
return isoDate === isoToday;
|
|
134
133
|
return true;
|
|
135
134
|
};
|
|
@@ -9,7 +9,7 @@ declare const Card: React.ForwardRefExoticComponent<{
|
|
|
9
9
|
href?: string;
|
|
10
10
|
className?: import("../../types/global").ClassName;
|
|
11
11
|
attributes?: (import("../..").Attributes<keyof React.JSX.IntrinsicElements> & ((import("../..").Attributes<"button"> & Omit<React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "form" | "slot" | "style" | "title" | "disabled" | "key" | "value" | "hidden" | "color" | "content" | "children" | "className" | "ref" | "aria-orientation" | "role" | "translate" | "suppressHydrationWarning" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "dir" | "name" | "type" | "accessKey" | "autoCapitalize" | "autoFocus" | "contentEditable" | "contextMenu" | "draggable" | "enterKeyHint" | "id" | "lang" | "nonce" | "spellCheck" | "tabIndex" | "radioGroup" | "about" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "resource" | "rev" | "typeof" | "vocab" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "popover" | "popoverTargetAction" | "popoverTarget" | "inert" | "inputMode" | "is" | "exportparts" | "part" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onScrollEnd" | "onScrollEndCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onToggle" | "onBeforeToggle" | "onTransitionCancel" | "onTransitionCancelCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "onTransitionRun" | "onTransitionRunCapture" | "onTransitionStart" | "onTransitionStartCapture"> & {
|
|
12
|
-
ref?: import("
|
|
12
|
+
ref?: import("../../core/Actionable/Actionable.types").AttributesRef;
|
|
13
13
|
}) | undefined)) | undefined;
|
|
14
14
|
as?: keyof React.JSX.IntrinsicElements | undefined;
|
|
15
15
|
} & Pick<import("../View").ViewProps, "height"> & React.RefAttributes<HTMLElement>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.content{--rs-flyout-
|
|
1
|
+
.content{--rs-flyout-max-h:100%;--rs-flyout-max-w:100%;--rs-flyout-origin-x:50%;--rs-flyout-origin-y:50%;display:flex;flex-direction:column;isolation:isolate;pointer-events:none;position:absolute;z-index:var(--rs-z-index-absolute)}.content.--hover{pointer-events:all}.content.--hover-disabled,.content.--hover-disabled .inner{pointer-events:none}.inner{backface-visibility:hidden;flex-grow:1;height:100%;max-height:var(--rs-flyout-max-h);max-width:var(--rs-flyout-max-w);opacity:0;outline:none;overflow:auto;pointer-events:all;transform:scale(.92) translateY(0);transform-origin:var(--rs-flyout-origin-x) var(--rs-flyout-origin-y);transition:1ms var(--rs-easing-accelerate)}[data-rs-keyboard] .inner:focus{box-shadow:var(--rs-shadow-focus)}.content.--width-trigger .inner{transform:scale(1) translateY(var(--rs-unit-x2))}.content.--position-top,.content.--position-top-end,.content.--position-top-start{--rs-flyout-origin-y:100%}.content.--position-bottom,.content.--position-bottom-end,.content.--position-bottom-start{--rs-flyout-origin-y:0%}.content.--position-bottom-start,.content.--position-top-start{--rs-flyout-origin-x:0%}.content.--position-bottom-end,.content.--position-start,.content.--position-start-bottom,.content.--position-start-top,.content.--position-top-end{--rs-flyout-origin-x:100%}.content.--position-end,.content.--position-end-bottom,.content.--position-end-top{--rs-flyout-origin-x:0%}.content.--position-end-top,.content.--position-start-top{--rs-flyout-origin-y:0%}.content.--position-end-bottom,.content.--position-start-bottom{--rs-flyout-origin-y:100%}.content.--visible .inner{opacity:1;transform:scale(1) translateY(0)}.content.--animated .inner{transition-duration:var(--rs-duration-rapid);transition-property:opacity,transform}.content.--animated.--visible .inner{transition-duration:var(--rs-duration-fast);transition-timing-function:var(--rs-easing-decelerate)}
|
|
@@ -15,7 +15,7 @@ export type CloseReason = "escape-key" | "outside-click"
|
|
|
15
15
|
| "item-selection" | "close-button";
|
|
16
16
|
export type Position = `${YSide}` | `${YSide}-${XSide}` | `${XSide}` | `${XSide}-${YSide}`;
|
|
17
17
|
export type Width = "trigger" | string;
|
|
18
|
-
export type Options = Pick<BaseProps, "width" | "fallbackAdjustLayout" | "
|
|
18
|
+
export type Options = Pick<BaseProps, "width" | "fallbackAdjustLayout" | "fallbackMinHeight" | "contentGap" | "contentShift"> & {
|
|
19
19
|
position: Position;
|
|
20
20
|
fallbackPositions?: Position[];
|
|
21
21
|
container?: HTMLElement | null;
|
|
@@ -25,7 +25,7 @@ export type Options = Pick<BaseProps, "width" | "fallbackAdjustLayout" | "fallba
|
|
|
25
25
|
};
|
|
26
26
|
export type State = {
|
|
27
27
|
position?: Position;
|
|
28
|
-
status: "idle" | "rendered" | "
|
|
28
|
+
status: "idle" | "rendered" | "visible" | "hidden";
|
|
29
29
|
};
|
|
30
30
|
export type FlyoutData = {
|
|
31
31
|
position: Position;
|
|
@@ -68,7 +68,7 @@ export type TriggerAttributes = {
|
|
|
68
68
|
onBlur?: (e: React.FocusEvent) => void;
|
|
69
69
|
onFocus?: () => void;
|
|
70
70
|
onMouseDown?: () => void;
|
|
71
|
-
onMouseEnter?: () => void;
|
|
71
|
+
onMouseEnter?: (e: React.MouseEvent) => void;
|
|
72
72
|
onMouseLeave?: (e: React.MouseEvent) => void;
|
|
73
73
|
onTouchStart?: () => void;
|
|
74
74
|
onClick?: () => void;
|
|
@@ -77,6 +77,7 @@ export type TriggerAttributes = {
|
|
|
77
77
|
"aria-autocomplete"?: "list";
|
|
78
78
|
"aria-expanded"?: boolean;
|
|
79
79
|
"aria-controls"?: string;
|
|
80
|
+
"data-rs-flyout-active"?: boolean;
|
|
80
81
|
};
|
|
81
82
|
type BaseProps = {
|
|
82
83
|
/** Unique id for the flyout content and trigger */
|
|
@@ -95,7 +96,7 @@ type BaseProps = {
|
|
|
95
96
|
fallbackPositions?: Position[] | false;
|
|
96
97
|
/** Adjust the content size and shift its position to fit into the container when none of the fallback positions work */
|
|
97
98
|
fallbackAdjustLayout?: boolean;
|
|
98
|
-
/** Minimum width for the content when fallbackAdjustLayout is true */
|
|
99
|
+
/** @deprecated Minimum width for the content when fallbackAdjustLayout is true */
|
|
99
100
|
fallbackMinWidth?: string;
|
|
100
101
|
/** Minimum height for the content when fallbackAdjustLayout is true */
|
|
101
102
|
fallbackMinHeight?: string;
|
|
@@ -178,11 +179,10 @@ export type ContextProps = {
|
|
|
178
179
|
reason?: CloseReason;
|
|
179
180
|
}) => void;
|
|
180
181
|
handleOpen: () => void;
|
|
181
|
-
|
|
182
|
+
handleTriggerMouseEnter: (e: React.MouseEvent) => void;
|
|
183
|
+
handleContentMouseEnter: (e: React.MouseEvent) => void;
|
|
182
184
|
handleMouseLeave: (e: React.MouseEvent) => void;
|
|
183
|
-
handleMouseDown: () => void;
|
|
184
185
|
handleTransitionEnd: (e: React.TransitionEvent) => void;
|
|
185
|
-
handleTransitionStart: (e: TransitionEvent) => void;
|
|
186
186
|
handleClick: () => void;
|
|
187
187
|
handleBlur: (e: React.FocusEvent) => void;
|
|
188
188
|
handleFocus: () => void;
|
|
@@ -3,72 +3,18 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import React from "react";
|
|
4
4
|
import Portal from "../_private/Portal/index.js";
|
|
5
5
|
import useIsomorphicLayoutEffect from "../../hooks/useIsomorphicLayoutEffect.js";
|
|
6
|
-
import { findClosestPositionContainer, findClosestScrollableContainer } from "../../utilities/dom/index.js";
|
|
7
|
-
import { rafThrottle } from "../../utilities/helpers.js";
|
|
8
6
|
import { classNames } from "../../utilities/props.js";
|
|
9
7
|
import { useFlyoutContext, ContentProvider } from "./Flyout.context.js";
|
|
10
8
|
import s from "./Flyout.module.css";
|
|
11
9
|
import cooldown from "./utilities/cooldown.js";
|
|
12
10
|
const FlyoutContent = (props) => {
|
|
13
11
|
const { children, className, attributes } = props;
|
|
14
|
-
const { flyout, id, flyoutElRef,
|
|
12
|
+
const { flyout, id, flyoutElRef, handleTransitionEnd, triggerType, handleContentMouseEnter, handleMouseLeave, handleContentMouseDown, handleContentMouseUp, contentClassName, contentAttributes, contentMaxHeight, contentMaxWidth, trapFocusMode, disableContentHover, autoFocus, width, isSubmenu, } = useFlyoutContext();
|
|
15
13
|
const { status, position } = flyout;
|
|
16
14
|
const [mounted, setMounted] = React.useState(false);
|
|
17
|
-
const closestFixedContainer = React.useMemo(() => {
|
|
18
|
-
if (!mounted)
|
|
19
|
-
return null;
|
|
20
|
-
if (!triggerElRef)
|
|
21
|
-
return null;
|
|
22
|
-
// eslint-disable-next-line react-hooks/refs
|
|
23
|
-
return findClosestPositionContainer({ el: triggerElRef.current });
|
|
24
|
-
}, [mounted, triggerElRef]);
|
|
25
|
-
const closestScrollableContainer = React.useMemo(() => {
|
|
26
|
-
if (!mounted)
|
|
27
|
-
return;
|
|
28
|
-
// eslint-disable-next-line react-hooks/refs
|
|
29
|
-
if (!triggerElRef?.current)
|
|
30
|
-
return;
|
|
31
|
-
// eslint-disable-next-line react-hooks/refs
|
|
32
|
-
return findClosestScrollableContainer({ el: triggerElRef.current });
|
|
33
|
-
}, [mounted, triggerElRef]);
|
|
34
|
-
const containerRef = passedContainerRef || { current: closestFixedContainer };
|
|
35
15
|
useIsomorphicLayoutEffect(() => {
|
|
36
16
|
setMounted(true);
|
|
37
17
|
}, []);
|
|
38
|
-
/**
|
|
39
|
-
* transitionStart doesn't exist as a jsx event handler and needs to be handled with vanilla js
|
|
40
|
-
*/
|
|
41
|
-
React.useEffect(() => {
|
|
42
|
-
const el = flyoutElRef.current;
|
|
43
|
-
if (!el)
|
|
44
|
-
return;
|
|
45
|
-
el.addEventListener("transitionstart", handleTransitionStart);
|
|
46
|
-
return () => el.removeEventListener("transitionstart", handleTransitionStart);
|
|
47
|
-
}, [handleTransitionStart, flyoutElRef, status]);
|
|
48
|
-
React.useEffect(() => {
|
|
49
|
-
if (status !== "visible")
|
|
50
|
-
return;
|
|
51
|
-
if (!closestScrollableContainer)
|
|
52
|
-
return;
|
|
53
|
-
const triggerEl = triggerElRef?.current;
|
|
54
|
-
const containerEl = closestScrollableContainer;
|
|
55
|
-
const handleScroll = rafThrottle(() => {
|
|
56
|
-
const triggerBounds = triggerEl?.getBoundingClientRect();
|
|
57
|
-
const containerBounds = containerEl.getBoundingClientRect();
|
|
58
|
-
if (triggerBounds &&
|
|
59
|
-
(triggerBounds.top < containerBounds.top ||
|
|
60
|
-
triggerBounds.left < containerBounds.left ||
|
|
61
|
-
triggerBounds.right > containerBounds.right ||
|
|
62
|
-
triggerBounds.bottom > containerBounds.bottom)) {
|
|
63
|
-
handleClose({});
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
flyout.updatePosition({ sync: true, fallback: false });
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
closestScrollableContainer.addEventListener("scroll", handleScroll, { passive: true });
|
|
70
|
-
return () => closestScrollableContainer.removeEventListener("scroll", handleScroll);
|
|
71
|
-
}, [closestScrollableContainer, flyout, status, handleClose, triggerElRef]);
|
|
72
18
|
if (status === "idle" || !mounted)
|
|
73
19
|
return null;
|
|
74
20
|
const rootClassNames = classNames(s.content, triggerType === "hover" && s["--hover"], status === "visible" && s["--visible"],
|
|
@@ -95,11 +41,10 @@ const FlyoutContent = (props) => {
|
|
|
95
41
|
role = "menubar";
|
|
96
42
|
}
|
|
97
43
|
const content = (_jsx(ContentProvider, { value: { elRef: flyoutElRef }, children: _jsx("div", { className: rootClassNames, style: {
|
|
98
|
-
"--rs-flyout-gap": contentGap,
|
|
99
44
|
"--rs-flyout-max-h": contentMaxHeight,
|
|
100
45
|
"--rs-flyout-max-w": contentMaxWidth,
|
|
101
|
-
}, ref: flyoutElRef, onTransitionEnd: handleTransitionEnd, onMouseEnter: triggerType === "hover" ?
|
|
102
|
-
return _jsx(Portal, {
|
|
46
|
+
}, ref: flyoutElRef, onTransitionEnd: handleTransitionEnd, onMouseEnter: triggerType === "hover" ? handleContentMouseEnter : undefined, onMouseLeave: triggerType === "hover" ? handleMouseLeave : undefined, onMouseDown: handleContentMouseDown, onTouchStart: handleContentMouseDown, onMouseUp: handleContentMouseUp, onTouchEnd: handleContentMouseUp, children: _jsx("div", { role: role, ...attributes, id: id, tabIndex: !autoFocus ? -1 : undefined, "aria-modal": role === "dialog" ? true : undefined, style: { ...attributes?.style, ...contentAttributes?.style }, className: innerClassNames, children: children }) }) }));
|
|
47
|
+
return _jsx(Portal, { children: content });
|
|
103
48
|
};
|
|
104
49
|
FlyoutContent.displayName = "Flyout.Content";
|
|
105
50
|
export default FlyoutContent;
|