reshaped 3.2.0-canary.5 → 3.2.0-canary.7
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/CHANGELOG.md +26 -1
- package/dist/bundle.css +1 -1
- package/dist/bundle.d.ts +2 -0
- package/dist/bundle.js +16 -16
- package/dist/cjs/constants/breakpoints.d.ts +6 -0
- package/dist/cjs/constants/breakpoints.js +7 -0
- package/dist/cjs/themes/_generator/definitions/reshaped.js +8 -4
- package/dist/cjs/themes/_generator/tokens/viewport/viewport.transforms.js +10 -1
- package/dist/cjs/themes/figma/theme.css +1 -1
- package/dist/cjs/themes/reshaped/theme.css +1 -1
- package/dist/cjs/themes/slate/theme.css +1 -1
- package/dist/components/Actionable/Actionable.d.ts +1 -1
- package/dist/components/Actionable/Actionable.module.css +1 -1
- package/dist/components/Autocomplete/Autocomplete.js +2 -2
- package/dist/components/Button/Button.js +1 -1
- package/dist/components/Button/Button.module.css +1 -1
- package/dist/components/Card/Card.d.ts +1 -1
- package/dist/components/Card/Card.module.css +1 -1
- package/dist/components/Card/tests/Card.stories.d.ts +1 -1
- package/dist/components/Checkbox/Checkbox.module.css +1 -1
- package/dist/components/Divider/Divider.js +4 -3
- package/dist/components/Divider/Divider.module.css +1 -1
- package/dist/components/Divider/Divider.types.d.ts +3 -0
- package/dist/components/Divider/tests/Divider.stories.d.ts +1 -0
- package/dist/components/Divider/tests/Divider.stories.js +21 -0
- package/dist/components/DropdownMenu/DropdownMenu.types.d.ts +1 -1
- package/dist/components/FormControl/FormControl.context.d.ts +2 -1
- package/dist/components/Grid/Grid.d.ts +6 -0
- package/dist/components/Grid/Grid.js +46 -0
- package/dist/components/Grid/Grid.module.css +1 -0
- package/dist/components/Grid/Grid.types.d.ts +31 -0
- package/dist/components/Grid/Grid.types.js +1 -0
- package/dist/components/Grid/index.d.ts +2 -0
- package/dist/components/Grid/index.js +1 -0
- package/dist/components/Grid/tests/Grid.stories.d.ts +18 -0
- package/dist/components/Grid/tests/Grid.stories.js +170 -0
- package/dist/components/Icon/Icon.module.css +1 -1
- package/dist/components/Link/Link.d.ts +1 -1
- package/dist/components/Link/tests/Link.stories.d.ts +1 -1
- package/dist/components/Loader/Loader.module.css +1 -1
- package/dist/components/Loader/Loader.types.d.ts +1 -1
- package/dist/components/Loader/tests/Loader.stories.js +5 -3
- package/dist/components/Modal/Modal.js +7 -4
- package/dist/components/Modal/Modal.module.css +1 -1
- package/dist/components/Modal/Modal.types.d.ts +1 -1
- package/dist/components/Modal/tests/Modal.stories.d.ts +1 -0
- package/dist/components/Modal/tests/Modal.stories.js +28 -1
- package/dist/components/Overlay/Overlay.js +45 -27
- package/dist/components/Overlay/Overlay.module.css +1 -1
- package/dist/components/Overlay/Overlay.types.d.ts +1 -0
- package/dist/components/Overlay/tests/Overlay.stories.js +1 -1
- package/dist/components/Popover/Popover.js +2 -4
- package/dist/components/Popover/Popover.types.d.ts +1 -1
- package/dist/components/Radio/Radio.module.css +1 -1
- package/dist/components/Resizable/Resizable.module.css +1 -1
- package/dist/components/ScrollArea/ScrollArea.js +1 -1
- package/dist/components/Slider/Slider.module.css +1 -1
- package/dist/components/Slider/SliderControlled.js +2 -1
- package/dist/components/Switch/Switch.module.css +1 -1
- package/dist/components/Tabs/Tabs.d.ts +1 -1
- package/dist/components/Tabs/Tabs.module.css +1 -1
- package/dist/components/Tabs/TabsContext.d.ts +1 -1
- package/dist/components/Tabs/TabsItem.d.ts +1 -1
- package/dist/components/Tabs/TabsItem.js +2 -3
- package/dist/components/Tabs/TabsList.js +1 -1
- package/dist/components/Tabs/tests/Tabs.stories.d.ts +15 -13
- package/dist/components/Tabs/tests/Tabs.stories.js +71 -8
- package/dist/components/TextField/TextField.js +5 -1
- package/dist/components/TextField/TextField.module.css +1 -1
- package/dist/components/TextField/tests/TextField.stories.js +4 -0
- package/dist/components/Toast/ToastContainer.js +1 -2
- package/dist/components/Toast/ToastRegion.js +1 -1
- package/dist/components/Tooltip/Tooltip.js +1 -1
- package/dist/components/View/View.js +7 -3
- package/dist/components/View/View.module.css +1 -1
- package/dist/components/View/View.types.d.ts +2 -2
- package/dist/components/_private/Expandable/Expandable.js +9 -5
- package/dist/components/_private/Flyout/Flyout.module.css +1 -1
- package/dist/components/_private/Flyout/Flyout.types.d.ts +12 -3
- package/dist/components/_private/Flyout/FlyoutContent.js +1 -1
- package/dist/components/_private/Flyout/FlyoutControlled.js +34 -21
- package/dist/components/_private/Flyout/tests/Flyout.stories.d.ts +3 -1
- package/dist/components/_private/Flyout/tests/Flyout.stories.js +54 -32
- package/dist/components/_private/Flyout/useFlyout.d.ts +2 -1
- package/dist/components/_private/Flyout/useFlyout.js +45 -55
- package/dist/components/_private/Flyout/utilities/calculatePosition.js +16 -11
- package/dist/components/_private/Flyout/utilities/cooldown.d.ts +1 -1
- package/dist/components/_private/Flyout/utilities/cooldown.js +17 -5
- package/dist/components/_private/Flyout/utilities/getPositionFallbacks.d.ts +3 -0
- package/dist/components/_private/Flyout/utilities/getPositionFallbacks.js +39 -0
- package/dist/components/_private/Portal/Portal.js +3 -3
- package/dist/config/tailwind.d.ts +1 -1
- package/dist/constants/breakpoints.d.ts +6 -0
- package/dist/constants/breakpoints.js +5 -0
- package/dist/hooks/_private/useIsDismissible.js +7 -14
- package/dist/hooks/_private/useSingletonHotkeys.js +5 -3
- package/dist/hooks/_private/useSingletonKeyboardMode.js +1 -1
- package/dist/hooks/tests/useHotkeys.stories.js +3 -0
- package/dist/hooks/tests/useResponsiveClientValue.stories.d.ts +1 -2
- package/dist/hooks/tests/useResponsiveClientValue.stories.js +1 -2
- package/dist/hooks/useDrag.js +2 -1
- package/dist/hooks/useResponsiveClientValue.js +22 -11
- package/dist/hooks/useScrollLock.d.ts +4 -1
- package/dist/hooks/useScrollLock.js +14 -40
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/styles/align/align.module.css +1 -0
- package/dist/styles/align/index.d.ts +3 -0
- package/dist/styles/align/index.js +10 -0
- package/dist/styles/justify/index.d.ts +3 -0
- package/dist/styles/justify/index.js +10 -0
- package/dist/styles/justify/justify.module.css +1 -0
- package/dist/styles/types.d.ts +2 -0
- package/dist/themes/_generator/definitions/reshaped.js +5 -4
- package/dist/themes/_generator/tokens/viewport/viewport.transforms.js +10 -1
- package/dist/themes/figma/theme.css +1 -1
- package/dist/themes/reshaped/theme.css +1 -1
- package/dist/themes/slate/theme.css +1 -1
- package/dist/utilities/a11y/TrapFocus.d.ts +1 -1
- package/dist/utilities/a11y/TrapFocus.js +1 -1
- package/dist/utilities/a11y/focus.js +1 -1
- package/dist/utilities/a11y/index.d.ts +4 -0
- package/dist/utilities/a11y/index.js +3 -0
- package/dist/utilities/css.d.ts +7 -0
- package/dist/utilities/css.js +18 -0
- package/dist/utilities/dom/flyout.d.ts +1 -0
- package/dist/utilities/{dom.js → dom/flyout.js} +1 -19
- package/dist/utilities/dom/index.d.ts +3 -0
- package/dist/utilities/dom/index.js +3 -0
- package/dist/utilities/dom/shadowDom.d.ts +1 -0
- package/dist/utilities/dom/shadowDom.js +4 -0
- package/dist/utilities/dom/userSelect.d.ts +2 -0
- package/dist/utilities/dom/userSelect.js +6 -0
- package/dist/utilities/platform.d.ts +1 -0
- package/dist/utilities/platform.js +15 -0
- package/dist/utilities/scroll/disable.d.ts +7 -0
- package/dist/utilities/scroll/disable.js +13 -0
- package/dist/utilities/scroll/helpers.d.ts +1 -0
- package/dist/utilities/scroll/helpers.js +17 -0
- package/dist/utilities/scroll/index.d.ts +2 -0
- package/dist/utilities/scroll/index.js +2 -0
- package/dist/utilities/scroll/lock.d.ts +5 -0
- package/dist/utilities/scroll/lock.js +24 -0
- package/dist/utilities/scroll/lockSafari.d.ts +2 -0
- package/dist/utilities/scroll/lockSafari.js +21 -0
- package/dist/utilities/scroll/lockStandard.d.ts +2 -0
- package/dist/utilities/scroll/lockStandard.js +17 -0
- package/dist/utilities/storybook/Placeholder.d.ts +1 -0
- package/dist/utilities/storybook/Placeholder.js +2 -2
- package/package.json +47 -50
- package/dist/utilities/dom.d.ts +0 -6
@@ -8,13 +8,14 @@ type PassedFlyoutOptions = {
|
|
8
8
|
width?: T.Width;
|
9
9
|
position?: T.Position;
|
10
10
|
defaultActive?: boolean;
|
11
|
-
|
11
|
+
fallbackPositions?: T.Position[];
|
12
12
|
container?: HTMLElement | null;
|
13
13
|
};
|
14
14
|
type UseFlyout = (args: PassedFlyoutOptions & {
|
15
15
|
triggerElRef: ElementRef;
|
16
16
|
flyoutElRef: ElementRef;
|
17
17
|
triggerBoundsRef: React.RefObject<DOMRect | undefined>;
|
18
|
+
contentGap?: number;
|
18
19
|
}) => Pick<T.State, "styles" | "position" | "status"> & {
|
19
20
|
updatePosition: (options?: {
|
20
21
|
sync?: boolean;
|
@@ -1,25 +1,8 @@
|
|
1
1
|
import React from "react";
|
2
2
|
import useRTL from "../../../hooks/useRTL.js";
|
3
|
-
import { getClosestFlyoutTarget, getShadowRoot } from "../../../utilities/dom.js";
|
3
|
+
import { getClosestFlyoutTarget, getShadowRoot } from "../../../utilities/dom/index.js";
|
4
4
|
import calculatePosition from "./utilities/calculatePosition.js";
|
5
|
-
|
6
|
-
const bottomPos = ["bottom-start", "bottom", "bottom-end"];
|
7
|
-
const startPos = ["start", "start-bottom", "start-top"];
|
8
|
-
const endPos = ["end", "end-bottom", "end-top"];
|
9
|
-
const order = {
|
10
|
-
top: [...topPos, ...bottomPos, ...endPos, ...startPos],
|
11
|
-
bottom: [...bottomPos, ...topPos, ...endPos, ...startPos],
|
12
|
-
start: [...startPos, ...endPos, ...topPos, ...bottomPos],
|
13
|
-
end: [...endPos, ...startPos, ...topPos, ...bottomPos],
|
14
|
-
};
|
15
|
-
/**
|
16
|
-
* Get an order of positions to try to fit popover on the screen based on its starting position
|
17
|
-
*/
|
18
|
-
const getPositionOrder = (position) => {
|
19
|
-
const types = ["top", "bottom", "start", "end"];
|
20
|
-
const type = types.find((type) => position.startsWith(type)) || "bottom";
|
21
|
-
return order[type];
|
22
|
-
};
|
5
|
+
import getPositionFallbacks from "./utilities/getPositionFallbacks.js";
|
23
6
|
/**
|
24
7
|
* Check if element visually fits on the screen
|
25
8
|
*/
|
@@ -60,12 +43,13 @@ const resetStyles = {
|
|
60
43
|
* Set position of the target element to fit on the screen
|
61
44
|
*/
|
62
45
|
const flyout = (args) => {
|
63
|
-
const { triggerEl, flyoutEl, triggerBounds: passedTriggerBounds, ...options } = args;
|
64
|
-
const { position,
|
46
|
+
const { triggerEl, flyoutEl, triggerBounds: passedTriggerBounds, contentGap = 0, ...options } = args;
|
47
|
+
const { position, fallbackPositions, width, container, lastUsedFallback, onFallback } = options;
|
65
48
|
const targetClone = flyoutEl.cloneNode(true);
|
66
49
|
const triggerBounds = passedTriggerBounds || triggerEl.getBoundingClientRect();
|
50
|
+
const contentGapModifier = parseInt(getComputedStyle(flyoutEl).getPropertyValue("--rs-unit-x1"));
|
67
51
|
// Reset all styles applied on the previous hook execution
|
68
|
-
targetClone.style = "";
|
52
|
+
targetClone.style.cssText = "";
|
69
53
|
Object.keys(resetStyles).forEach((key) => {
|
70
54
|
const value = resetStyles[key];
|
71
55
|
targetClone.style[key] = value.toString();
|
@@ -88,37 +72,30 @@ const flyout = (args) => {
|
|
88
72
|
top: containerBounds.top + document.documentElement.scrollTop - containerParent.scrollTop,
|
89
73
|
left: containerBounds.left + document.documentElement.scrollLeft - containerParent.scrollLeft,
|
90
74
|
};
|
91
|
-
let calculated =
|
92
|
-
|
93
|
-
|
94
|
-
const
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
});
|
109
|
-
if (fullyVisible(tested)) {
|
110
|
-
calculated = tested;
|
111
|
-
return true;
|
112
|
-
}
|
113
|
-
return false;
|
114
|
-
});
|
115
|
-
};
|
116
|
-
test(order);
|
117
|
-
if (!fullyVisible(calculated)) {
|
118
|
-
test(mobileOrder, { fullWidth: true });
|
75
|
+
let calculated = null;
|
76
|
+
const testOrder = getPositionFallbacks(position, fallbackPositions);
|
77
|
+
testOrder.some((currentPosition, index) => {
|
78
|
+
const tested = calculatePosition({
|
79
|
+
...options,
|
80
|
+
triggerBounds,
|
81
|
+
flyoutBounds,
|
82
|
+
scopeOffset,
|
83
|
+
position: currentPosition,
|
84
|
+
contentGap: contentGap * contentGapModifier,
|
85
|
+
});
|
86
|
+
const visible = fullyVisible(tested);
|
87
|
+
const validPosition = visible || fallbackPositions?.length === 0;
|
88
|
+
// Saving first try in case non of the options work
|
89
|
+
if (validPosition || lastUsedFallback === currentPosition) {
|
90
|
+
calculated = tested;
|
91
|
+
onFallback(currentPosition);
|
119
92
|
}
|
93
|
+
return validPosition;
|
94
|
+
});
|
95
|
+
if (!calculated) {
|
96
|
+
throw new Error(`Reshaped: Can't calculate styles for the ${position} position`);
|
120
97
|
}
|
121
|
-
targetClone.parentNode
|
98
|
+
targetClone.parentNode?.removeChild(targetClone);
|
122
99
|
return calculated;
|
123
100
|
};
|
124
101
|
const flyoutReducer = (state, action) => {
|
@@ -156,8 +133,13 @@ const flyoutReducer = (state, action) => {
|
|
156
133
|
}
|
157
134
|
};
|
158
135
|
const useFlyout = (args) => {
|
159
|
-
const { triggerElRef, flyoutElRef, triggerBoundsRef, ...options } = args;
|
160
|
-
const { position: defaultPosition = "bottom",
|
136
|
+
const { triggerElRef, flyoutElRef, triggerBoundsRef, contentGap, ...options } = args;
|
137
|
+
const { position: defaultPosition = "bottom", fallbackPositions, width, container } = options;
|
138
|
+
const lastUsedFallbackRef = React.useRef(defaultPosition);
|
139
|
+
// Memo the array internally to avoid new arrays triggering useCallback
|
140
|
+
const cachedFallbackPositions = React.useMemo(() => fallbackPositions,
|
141
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
142
|
+
[fallbackPositions?.join(" ")]);
|
161
143
|
const [isRTL] = useRTL();
|
162
144
|
const [state, dispatch] = React.useReducer(flyoutReducer, {
|
163
145
|
position: defaultPosition,
|
@@ -176,6 +158,9 @@ const useFlyout = (args) => {
|
|
176
158
|
const remove = React.useCallback(() => {
|
177
159
|
dispatch({ type: "remove" });
|
178
160
|
}, []);
|
161
|
+
const handleFallback = React.useCallback((position) => {
|
162
|
+
lastUsedFallbackRef.current = position;
|
163
|
+
}, []);
|
179
164
|
const updatePosition = React.useCallback((options) => {
|
180
165
|
if (!triggerElRef.current || !flyoutElRef.current)
|
181
166
|
return;
|
@@ -185,21 +170,26 @@ const useFlyout = (args) => {
|
|
185
170
|
triggerBounds: triggerBoundsRef.current,
|
186
171
|
width,
|
187
172
|
position: defaultPosition,
|
188
|
-
|
173
|
+
fallbackPositions: cachedFallbackPositions,
|
174
|
+
lastUsedFallback: lastUsedFallbackRef.current,
|
175
|
+
onFallback: handleFallback,
|
189
176
|
rtl: isRTL,
|
190
177
|
container,
|
178
|
+
contentGap,
|
191
179
|
});
|
192
180
|
if (nextFlyoutData)
|
193
181
|
dispatch({ type: "position", payload: { ...nextFlyoutData, sync: options?.sync } });
|
194
182
|
}, [
|
195
183
|
container,
|
196
184
|
defaultPosition,
|
197
|
-
|
185
|
+
cachedFallbackPositions,
|
198
186
|
isRTL,
|
199
187
|
flyoutElRef,
|
200
188
|
triggerElRef,
|
201
189
|
triggerBoundsRef,
|
202
190
|
width,
|
191
|
+
contentGap,
|
192
|
+
handleFallback,
|
203
193
|
]);
|
204
194
|
React.useEffect(() => {
|
205
195
|
if (state.status === "rendered")
|
@@ -16,24 +16,29 @@ const centerBySize = (originSize, targetSize) => {
|
|
16
16
|
* Calculate styles for the current position
|
17
17
|
*/
|
18
18
|
const calculatePosition = (args) => {
|
19
|
-
const { triggerBounds, flyoutBounds, scopeOffset, position: passedPosition, rtl, width } = args;
|
19
|
+
const { triggerBounds, flyoutBounds, scopeOffset, position: passedPosition, rtl, width, contentGap = 0, } = args;
|
20
|
+
const isFullWidth = width === "full" || width === "100%";
|
20
21
|
let left = 0;
|
21
22
|
let top = 0;
|
22
23
|
let position = passedPosition;
|
23
24
|
if (rtl)
|
24
25
|
position = getRTLPosition(position);
|
25
|
-
if (
|
26
|
+
if (isFullWidth || width === "trigger") {
|
26
27
|
position = position.includes("top") ? "top" : "bottom";
|
27
28
|
}
|
29
|
+
const isHorizontalPosition = position.match(/^(start|end)/);
|
30
|
+
const isVerticalPosition = position.match(/^(top|bottom)/);
|
31
|
+
const flyoutWidth = flyoutBounds.width + (isHorizontalPosition ? contentGap : 0);
|
32
|
+
const flyoutHeight = flyoutBounds.height + (isVerticalPosition ? contentGap : 0);
|
28
33
|
switch (position) {
|
29
34
|
case "bottom":
|
30
35
|
case "top":
|
31
|
-
left = centerBySize(triggerBounds.width,
|
36
|
+
left = centerBySize(triggerBounds.width, flyoutWidth) + triggerBounds.left;
|
32
37
|
break;
|
33
38
|
case "start":
|
34
39
|
case "start-top":
|
35
40
|
case "start-bottom":
|
36
|
-
left = triggerBounds.left -
|
41
|
+
left = triggerBounds.left - flyoutWidth;
|
37
42
|
break;
|
38
43
|
case "end":
|
39
44
|
case "end-top":
|
@@ -46,7 +51,7 @@ const calculatePosition = (args) => {
|
|
46
51
|
break;
|
47
52
|
case "top-end":
|
48
53
|
case "bottom-end":
|
49
|
-
left = triggerBounds.right -
|
54
|
+
left = triggerBounds.right - flyoutWidth;
|
50
55
|
break;
|
51
56
|
default:
|
52
57
|
break;
|
@@ -55,7 +60,7 @@ const calculatePosition = (args) => {
|
|
55
60
|
case "top":
|
56
61
|
case "top-start":
|
57
62
|
case "top-end":
|
58
|
-
top = triggerBounds.top -
|
63
|
+
top = triggerBounds.top - flyoutHeight;
|
59
64
|
break;
|
60
65
|
case "bottom":
|
61
66
|
case "bottom-start":
|
@@ -64,7 +69,7 @@ const calculatePosition = (args) => {
|
|
64
69
|
break;
|
65
70
|
case "start":
|
66
71
|
case "end":
|
67
|
-
top = centerBySize(triggerBounds.height,
|
72
|
+
top = centerBySize(triggerBounds.height, flyoutHeight) + triggerBounds.top;
|
68
73
|
break;
|
69
74
|
case "start-top":
|
70
75
|
case "end-top":
|
@@ -72,7 +77,7 @@ const calculatePosition = (args) => {
|
|
72
77
|
break;
|
73
78
|
case "start-bottom":
|
74
79
|
case "end-bottom":
|
75
|
-
top = triggerBounds.bottom -
|
80
|
+
top = triggerBounds.bottom - flyoutHeight;
|
76
81
|
break;
|
77
82
|
default:
|
78
83
|
break;
|
@@ -82,9 +87,9 @@ const calculatePosition = (args) => {
|
|
82
87
|
}
|
83
88
|
top = Math.round(top + (window.scrollY || 0) - scopeOffset.top);
|
84
89
|
left = Math.round(left + (window.scrollX || 0) - scopeOffset.left);
|
85
|
-
let widthStyle = Math.ceil(
|
86
|
-
const height = Math.ceil(
|
87
|
-
if (
|
90
|
+
let widthStyle = Math.ceil(flyoutWidth);
|
91
|
+
const height = Math.ceil(flyoutHeight);
|
92
|
+
if (isFullWidth) {
|
88
93
|
left = SCREEN_OFFSET;
|
89
94
|
widthStyle = window.innerWidth - SCREEN_OFFSET * 2;
|
90
95
|
}
|
@@ -1,18 +1,30 @@
|
|
1
|
+
import * as timeouts from "../Flyout.constants.js";
|
1
2
|
class Cooldown {
|
2
3
|
status = "cold";
|
3
4
|
timer;
|
4
5
|
warm = () => {
|
5
6
|
clearTimeout(this.timer);
|
6
|
-
this.status
|
7
|
+
if (this.status === "cooling") {
|
8
|
+
this.status = "warm";
|
9
|
+
return;
|
10
|
+
}
|
11
|
+
this.status = "warming";
|
12
|
+
this.timer = setTimeout(() => {
|
13
|
+
this.status = "warm";
|
14
|
+
this.timer = undefined;
|
15
|
+
}, timeouts.mouseEnterShort);
|
7
16
|
};
|
8
17
|
cool = () => {
|
18
|
+
clearTimeout(this.timer);
|
19
|
+
if (this.status === "warming") {
|
20
|
+
this.status = "cold";
|
21
|
+
return;
|
22
|
+
}
|
9
23
|
this.status = "cooling";
|
10
|
-
|
24
|
+
this.timer = setTimeout(() => {
|
11
25
|
this.status = "cold";
|
12
|
-
|
13
|
-
this.timer = undefined;
|
26
|
+
this.timer = undefined;
|
14
27
|
}, 500);
|
15
|
-
this.timer = currentTimer;
|
16
28
|
};
|
17
29
|
}
|
18
30
|
export default new Cooldown();
|
@@ -0,0 +1,39 @@
|
|
1
|
+
// All available positions for each side
|
2
|
+
const positions = {
|
3
|
+
top: ["top-start", "top-end", "top"],
|
4
|
+
bottom: ["bottom-start", "bottom-end", "bottom"],
|
5
|
+
start: ["start-top", "start-bottom", "start"],
|
6
|
+
end: ["end-top", "end-bottom", "end"],
|
7
|
+
};
|
8
|
+
// Order of sides to try depending on the starting side
|
9
|
+
const fallbackOrder = {
|
10
|
+
top: ["bottom", "start", "end"],
|
11
|
+
bottom: ["top", "end", "start"],
|
12
|
+
start: ["end", "top", "bottom"],
|
13
|
+
end: ["start", "bottom", "top"],
|
14
|
+
};
|
15
|
+
// Get an order of positions to try to fit flyout on the screen based on its starting position
|
16
|
+
const getPositionFallbacks = (position, availableFallbacks) => {
|
17
|
+
const result = [position];
|
18
|
+
const chunks = position.split("-");
|
19
|
+
const [firstChunk] = chunks;
|
20
|
+
const passedPositionOrder = positions[firstChunk];
|
21
|
+
const startingFallbackIndex = passedPositionOrder.indexOf(position);
|
22
|
+
const fallbackIndexOrder = [startingFallbackIndex];
|
23
|
+
passedPositionOrder.forEach((_, index) => {
|
24
|
+
if (index === startingFallbackIndex)
|
25
|
+
return;
|
26
|
+
fallbackIndexOrder.push(index);
|
27
|
+
});
|
28
|
+
[firstChunk, ...fallbackOrder[firstChunk]].forEach((fallbackSide) => {
|
29
|
+
const fallbackOrder = positions[fallbackSide];
|
30
|
+
fallbackIndexOrder.forEach((index) => {
|
31
|
+
const position = fallbackOrder[index];
|
32
|
+
if (availableFallbacks?.indexOf(position) === -1)
|
33
|
+
return;
|
34
|
+
result.push(position);
|
35
|
+
});
|
36
|
+
});
|
37
|
+
return result;
|
38
|
+
};
|
39
|
+
export default getPositionFallbacks;
|
@@ -3,7 +3,6 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
3
3
|
import React from "react";
|
4
4
|
import ReactDOM from "react-dom";
|
5
5
|
import Theme from "../../Theme/index.js";
|
6
|
-
import { getShadowRoot } from "../../../utilities/dom.js";
|
7
6
|
import s from "./Portal.module.css";
|
8
7
|
const PortalScopeContext = React.createContext({});
|
9
8
|
export const usePortalScope = () => {
|
@@ -16,8 +15,9 @@ export const usePortalScope = () => {
|
|
16
15
|
const Portal = (props) => {
|
17
16
|
const { children, targetRef } = props;
|
18
17
|
const rootRef = React.useRef(null);
|
19
|
-
const
|
20
|
-
const
|
18
|
+
const rootNode = rootRef.current?.getRootNode();
|
19
|
+
const isShadowDom = rootNode instanceof ShadowRoot;
|
20
|
+
const defaultTargetEl = isShadowDom ? rootNode : document.body;
|
21
21
|
/**
|
22
22
|
* Check for parent portal to render inside it
|
23
23
|
* To avoid z-iondex issues
|
@@ -1,2 +1,2 @@
|
|
1
1
|
import type { ThemeDefinition } from "../themes/_generator/tokens/types";
|
2
|
-
export declare const getTheme: (theme?: ThemeDefinition) => Record<"borderRadius" | "backgroundColor" | "borderColor" | "
|
2
|
+
export declare const getTheme: (theme?: ThemeDefinition) => Record<"borderRadius" | "backgroundColor" | "borderColor" | "boxShadow" | "textColor" | "colors" | "spacing" | "screens", Record<string, string>>;
|
@@ -18,26 +18,19 @@ const removeFromQueue = (id) => {
|
|
18
18
|
queue = {};
|
19
19
|
};
|
20
20
|
const addToQueue = (id, contentRef, triggerRef) => {
|
21
|
-
const parentItem = latestId ? queue[latestId] : undefined;
|
22
|
-
const insideParent = triggerRef?.current &&
|
23
|
-
parentItem &&
|
24
|
-
parentItem.contentRef.current?.contains(triggerRef.current);
|
25
|
-
if (!insideParent && triggerRef && latestId) {
|
26
|
-
removeFromQueue(latestId);
|
27
|
-
}
|
28
21
|
queue[id] = { parentId: latestId, triggerRef, contentRef };
|
29
22
|
latestId = id;
|
30
23
|
};
|
31
24
|
const useIsDismissible = (active = false, contentRef, triggerRef) => {
|
32
25
|
const id = useElementId();
|
33
|
-
const isDismissible = React.useCallback(() =>
|
26
|
+
const isDismissible = React.useCallback(() => {
|
27
|
+
return active ? latestId === id : true;
|
28
|
+
}, [id, active]);
|
34
29
|
React.useEffect(() => {
|
35
|
-
if (active)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
removeFromQueue(id);
|
40
|
-
}
|
30
|
+
if (!active)
|
31
|
+
return;
|
32
|
+
addToQueue(id, contentRef, triggerRef);
|
33
|
+
return () => removeFromQueue(id);
|
41
34
|
}, [active, id, contentRef, triggerRef]);
|
42
35
|
return isDismissible;
|
43
36
|
};
|
@@ -70,10 +70,12 @@ export class HotkeyStore {
|
|
70
70
|
const hotkeyData = this.hotkeyMap[pressedId];
|
71
71
|
/**
|
72
72
|
* Support for `mod` that represents both Mac and Win keyboards
|
73
|
+
* We create the hotkeyId again to sort the mod key correctly
|
73
74
|
*/
|
74
|
-
const
|
75
|
-
|
76
|
-
const
|
75
|
+
const controlToModPressedId = getHotkeyId(pressedId.replace("control", "mod"));
|
76
|
+
const metaToModPressedId = getHotkeyId(pressedId.replace("meta", "mod"));
|
77
|
+
const hotkeyControlModData = pressedFormattedKeys.includes("control") && this.hotkeyMap[controlToModPressedId];
|
78
|
+
const hotkeyMetaModData = pressedFormattedKeys.includes("meta") && this.hotkeyMap[metaToModPressedId];
|
77
79
|
[hotkeyData, hotkeyControlModData, hotkeyMetaModData].forEach((hotkeyData) => {
|
78
80
|
if (!hotkeyData)
|
79
81
|
return;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import React from "react";
|
2
|
-
import { enableKeyboardMode, disableKeyboardMode } from "../../utilities/a11y/
|
2
|
+
import { enableKeyboardMode, disableKeyboardMode } from "../../utilities/a11y/index.js";
|
3
3
|
const useSingletonKeyboardMode = () => {
|
4
4
|
React.useEffect(() => {
|
5
5
|
const handleKeyDown = (e) => {
|
@@ -6,6 +6,9 @@ function Example() {
|
|
6
6
|
"shift + b + n": () => console.log("pressed"),
|
7
7
|
"c + v": () => console.log(111),
|
8
8
|
"Meta + v": () => console.log(222),
|
9
|
+
"control + enter": () => console.log("control + enter"),
|
10
|
+
"meta + enter": () => console.log("meta + enter"),
|
11
|
+
"mod + enter": () => console.log("mod + enter"),
|
9
12
|
"mod + ArrowRight": () => console.log("right"),
|
10
13
|
"mod + ArrowUp": () => console.log("top"),
|
11
14
|
"shift + ArrowRight": () => console.log("right"),
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import React from "react";
|
2
1
|
import useResponsiveClientValue from "../useResponsiveClientValue.js";
|
3
2
|
import View from "../../components/View/index.js";
|
4
3
|
export default { title: "Hooks/useResponsiveClientValue" };
|
@@ -10,4 +9,4 @@ function Example() {
|
|
10
9
|
});
|
11
10
|
return <View width={25} height={25} backgroundColor={value}/>;
|
12
11
|
}
|
13
|
-
export const
|
12
|
+
export const base = () => <Example />;
|
package/dist/hooks/useDrag.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
"use client";
|
2
2
|
import React from "react";
|
3
|
-
import { disableUserSelect, enableUserSelect
|
3
|
+
import { disableUserSelect, enableUserSelect } from "../utilities/dom/index.js";
|
4
|
+
import { disableScroll, enableScroll } from "../utilities/scroll/index.js";
|
4
5
|
import useToggle from "./useToggle.js";
|
5
6
|
import useHotkeys from "./useHotkeys.js";
|
6
7
|
import * as keys from "../constants/keys.js";
|
@@ -2,21 +2,32 @@
|
|
2
2
|
import React from "react";
|
3
3
|
import { SingletonEnvironmentContext } from "./_private/useSingletonEnvironment.js";
|
4
4
|
import useIsomorphicLayoutEffect from "./useIsomorphicLayoutEffect.js";
|
5
|
-
|
6
|
-
m: 660,
|
7
|
-
l: 900,
|
8
|
-
xl: 1280,
|
9
|
-
};
|
10
|
-
const mediaQueries = {
|
11
|
-
s: `(max-width: ${breakpoints.m - 1}px)`,
|
12
|
-
m: `(min-width: ${breakpoints.m}px) and (max-width: ${breakpoints.l - 1}px)`,
|
13
|
-
l: `(min-width: ${breakpoints.l}px) and (max-width: ${breakpoints.xl - 1}px)`,
|
14
|
-
xl: `(min-width: ${breakpoints.xl}px)`,
|
15
|
-
};
|
5
|
+
import defaultBreakpoints from "../constants/breakpoints.js";
|
16
6
|
const useResponsiveClientValue = (value) => {
|
17
7
|
const { defaultViewport } = React.useContext(SingletonEnvironmentContext);
|
18
8
|
const [viewport, setViewport] = React.useState(defaultViewport);
|
19
9
|
useIsomorphicLayoutEffect(() => {
|
10
|
+
const rootThemeEl = document.querySelector("[data-rs-theme]");
|
11
|
+
const rootStyle = rootThemeEl && window.getComputedStyle(rootThemeEl);
|
12
|
+
/**
|
13
|
+
* We generate variables for the viewport breakpoints in the themes
|
14
|
+
* We use them here in case they're custom and fallback to the default values
|
15
|
+
* in case there is no SSR passing the data-rs-theme attribute
|
16
|
+
*/
|
17
|
+
const breakpoints = {
|
18
|
+
m: (rootStyle && Number(rootStyle.getPropertyValue("--rs-viewport-m-min"))) ||
|
19
|
+
defaultBreakpoints.m,
|
20
|
+
l: (rootStyle && Number(rootStyle.getPropertyValue("--rs-viewport-l-min"))) ||
|
21
|
+
defaultBreakpoints.l,
|
22
|
+
xl: (rootStyle && Number(rootStyle.getPropertyValue("--rs-viewport-xl-min"))) ||
|
23
|
+
defaultBreakpoints.xl,
|
24
|
+
};
|
25
|
+
const mediaQueries = {
|
26
|
+
s: `(max-width: ${breakpoints.m - 1}px)`,
|
27
|
+
m: `(min-width: ${breakpoints.m}px) and (max-width: ${breakpoints.l - 1}px)`,
|
28
|
+
l: `(min-width: ${breakpoints.l}px) and (max-width: ${breakpoints.xl - 1}px)`,
|
29
|
+
xl: `(min-width: ${breakpoints.xl}px)`,
|
30
|
+
};
|
20
31
|
const viewports = Object.keys(mediaQueries);
|
21
32
|
const matchers = viewports.map((viewport) => {
|
22
33
|
const mq = window.matchMedia(mediaQueries[viewport]);
|
@@ -1,45 +1,19 @@
|
|
1
1
|
"use client";
|
2
2
|
import React from "react";
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
if (scrollbarWidth)
|
7
|
-
return scrollbarWidth;
|
8
|
-
const scrollDiv = document.createElement("div");
|
9
|
-
scrollDiv.style.position = "absolute";
|
10
|
-
scrollDiv.style.top = "-9999px";
|
11
|
-
scrollDiv.style.width = "50px";
|
12
|
-
scrollDiv.style.height = "50px";
|
13
|
-
scrollDiv.style.overflow = "scroll";
|
14
|
-
document.body.appendChild(scrollDiv);
|
15
|
-
scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth;
|
16
|
-
document.body.removeChild(scrollDiv);
|
17
|
-
return scrollbarWidth;
|
18
|
-
};
|
19
|
-
})();
|
20
|
-
const useScrollLock = () => {
|
3
|
+
import { lockScroll, unlockScroll } from "../utilities/scroll/index.js";
|
4
|
+
const useScrollLock = (props) => {
|
5
|
+
const { containerRef } = props || {};
|
21
6
|
const [locked, setLocked] = React.useState(false);
|
22
|
-
const
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
}
|
34
|
-
setLocked(true);
|
35
|
-
}, [setLocked, isOverflowingRef, overflowStyleRef]);
|
36
|
-
const unlockScroll = React.useCallback(() => {
|
37
|
-
const targetEl = document.body;
|
38
|
-
targetEl.style.overflow = overflowStyleRef.current || "";
|
39
|
-
if (isOverflowingRef.current)
|
40
|
-
targetEl.style.paddingRight = "";
|
41
|
-
setLocked(false);
|
42
|
-
}, [setLocked, isOverflowingRef, overflowStyleRef]);
|
43
|
-
return { scrollLocked: locked, lockScroll, unlockScroll };
|
7
|
+
const handleLockScroll = React.useCallback(() => {
|
8
|
+
lockScroll({ containerEl: containerRef?.current, cb: () => setLocked(true) });
|
9
|
+
}, [containerRef]);
|
10
|
+
const handleUnlockScroll = React.useCallback(() => {
|
11
|
+
unlockScroll(() => setLocked(false));
|
12
|
+
}, []);
|
13
|
+
return React.useMemo(() => ({
|
14
|
+
scrollLocked: locked,
|
15
|
+
lockScroll: handleLockScroll,
|
16
|
+
unlockScroll: handleUnlockScroll,
|
17
|
+
}), [locked, handleLockScroll, handleUnlockScroll]);
|
44
18
|
};
|
45
19
|
export default useScrollLock;
|
package/dist/index.d.ts
CHANGED
@@ -41,6 +41,8 @@ export { default as FileUpload } from "./components/FileUpload";
|
|
41
41
|
export type { FileUploadProps } from "./components/FileUpload";
|
42
42
|
export { default as FormControl } from "./components/FormControl";
|
43
43
|
export type { FormControlProps } from "./components/FormControl";
|
44
|
+
export { default as Grid } from "./components/Grid";
|
45
|
+
export type { GridProps, GridItemProps } from "./components/Grid";
|
44
46
|
export { default as Hidden } from "./components/Hidden";
|
45
47
|
export type { HiddenProps } from "./components/Hidden";
|
46
48
|
export { default as HiddenVisually } from "./components/HiddenVisually";
|
package/dist/index.js
CHANGED
@@ -21,6 +21,7 @@ export { default as Divider } from "./components/Divider/index.js";
|
|
21
21
|
export { default as DropdownMenu } from "./components/DropdownMenu/index.js";
|
22
22
|
export { default as FileUpload } from "./components/FileUpload/index.js";
|
23
23
|
export { default as FormControl } from "./components/FormControl/index.js";
|
24
|
+
export { default as Grid } from "./components/Grid/index.js";
|
24
25
|
export { default as Hidden } from "./components/Hidden/index.js";
|
25
26
|
export { default as HiddenVisually } from "./components/HiddenVisually/index.js";
|
26
27
|
export { default as Hotkey } from "./components/Hotkey/index.js";
|
@@ -0,0 +1 @@
|
|
1
|
+
.--align-start{align-items:flex-start!important}.--align-end{align-items:flex-end!important}.--align-center{align-items:center!important}.--align-stretch{align-items:stretch!important}.--align-baseline{align-items:baseline!important}@media (--rs-viewport-m ){.--align-start--m{align-items:flex-start!important}.--align-end--m{align-items:flex-end!important}.--align-center--m{align-items:center!important}.--align-stretch--m{align-items:stretch!important}.--align-baseline--m{align-items:baseline!important}}@media (--rs-viewport-l ){.--align-start--l{align-items:flex-start!important}.--align-end--l{align-items:flex-end!important}.--align-center--l{align-items:center!important}.--align-stretch--l{align-items:stretch!important}.--align-baseline--l{align-items:baseline!important}}@media (--rs-viewport-xl ){.--align-start--xl{align-items:flex-start!important}.--align-end--xl{align-items:flex-end!important}.--align-center--xl{align-items:center!important}.--align-stretch--xl{align-items:stretch!important}.--align-baseline--xl{align-items:baseline!important}}
|