braid-design-system 33.2.0 → 33.2.1
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 +14 -0
- package/dist/lib/components/MenuRenderer/MenuRenderer.actions.cjs +2 -1
- package/dist/lib/components/MenuRenderer/MenuRenderer.actions.mjs +2 -1
- package/dist/lib/components/MenuRenderer/MenuRenderer.cjs +168 -120
- package/dist/lib/components/MenuRenderer/MenuRenderer.css.cjs +24 -13
- package/dist/lib/components/MenuRenderer/MenuRenderer.css.mjs +25 -14
- package/dist/lib/components/MenuRenderer/MenuRenderer.mjs +170 -122
- package/dist/lib/components/OverflowMenu/OverflowMenu.cjs +13 -13
- package/dist/lib/components/OverflowMenu/OverflowMenu.css.cjs +3 -3
- package/dist/lib/components/OverflowMenu/OverflowMenu.css.mjs +3 -3
- package/dist/lib/components/OverflowMenu/OverflowMenu.mjs +14 -14
- package/dist/lib/components/private/ScrollContainer/ScrollContainer.cjs +67 -0
- package/dist/lib/components/private/ScrollContainer/ScrollContainer.css.cjs +86 -0
- package/dist/lib/components/private/ScrollContainer/ScrollContainer.css.mjs +87 -0
- package/dist/lib/components/private/ScrollContainer/ScrollContainer.mjs +68 -0
- package/package.json +3 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsxs, jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
2
2
|
import assert from "assert";
|
|
3
3
|
import { useRef, useReducer, useEffect, Children } from "react";
|
|
4
4
|
import { flattenChildren } from "../../utils/flattenChildren.mjs";
|
|
@@ -7,11 +7,14 @@ import { MenuItemDivider } from "../MenuItemDivider/MenuItemDivider.mjs";
|
|
|
7
7
|
import { normalizeKey } from "../private/normalizeKey.mjs";
|
|
8
8
|
import { getNextIndex } from "../private/getNextIndex.mjs";
|
|
9
9
|
import { Overlay } from "../private/Overlay/Overlay.mjs";
|
|
10
|
+
import { ScrollContainer } from "../private/ScrollContainer/ScrollContainer.mjs";
|
|
10
11
|
import { actionTypes } from "./MenuRenderer.actions.mjs";
|
|
11
12
|
import { MenuRendererContext } from "./MenuRendererContext.mjs";
|
|
12
13
|
import { MenuRendererItemContext } from "./MenuRendererItemContext.mjs";
|
|
13
14
|
import { buildDataAttributes } from "../private/buildDataAttributes.mjs";
|
|
14
|
-
import { backdrop,
|
|
15
|
+
import { backdrop, triggerVars, menuPosition, animation, width, menuHeightLimit } from "./MenuRenderer.css.mjs";
|
|
16
|
+
import { BraidPortal } from "../BraidPortal/BraidPortal.mjs";
|
|
17
|
+
import { assignInlineVars } from "@vanilla-extract/dynamic";
|
|
15
18
|
const {
|
|
16
19
|
MENU_TRIGGER_UP,
|
|
17
20
|
MENU_ITEM_UP,
|
|
@@ -28,14 +31,29 @@ const {
|
|
|
28
31
|
MENU_TRIGGER_CLICK,
|
|
29
32
|
MENU_TRIGGER_TAB,
|
|
30
33
|
MENU_TRIGGER_ESCAPE,
|
|
31
|
-
BACKDROP_CLICK
|
|
34
|
+
BACKDROP_CLICK,
|
|
35
|
+
WINDOW_RESIZE
|
|
32
36
|
} = actionTypes;
|
|
37
|
+
const getPosition = (element) => {
|
|
38
|
+
if (!element) {
|
|
39
|
+
return void 0;
|
|
40
|
+
}
|
|
41
|
+
const { top, bottom, left, right } = element.getBoundingClientRect();
|
|
42
|
+
const { scrollX, scrollY, innerWidth, innerHeight } = window;
|
|
43
|
+
return {
|
|
44
|
+
top: innerHeight - top - scrollY,
|
|
45
|
+
bottom: bottom + scrollY,
|
|
46
|
+
left: left + scrollX,
|
|
47
|
+
right: innerWidth - right - scrollX
|
|
48
|
+
};
|
|
49
|
+
};
|
|
33
50
|
const CLOSED_INDEX = -1;
|
|
34
51
|
const CLOSE_REASON_EXIT = { reason: "exit" };
|
|
35
52
|
const initialState = {
|
|
36
53
|
open: false,
|
|
37
54
|
highlightIndex: CLOSED_INDEX,
|
|
38
|
-
closeReason: CLOSE_REASON_EXIT
|
|
55
|
+
closeReason: CLOSE_REASON_EXIT,
|
|
56
|
+
triggerPosition: void 0
|
|
39
57
|
};
|
|
40
58
|
const MenuRenderer = ({
|
|
41
59
|
onOpen,
|
|
@@ -50,6 +68,7 @@ const MenuRenderer = ({
|
|
|
50
68
|
data,
|
|
51
69
|
...restProps
|
|
52
70
|
}) => {
|
|
71
|
+
const menuContainerRef = useRef(null);
|
|
53
72
|
const buttonRef = useRef(null);
|
|
54
73
|
const lastOpen = useRef(false);
|
|
55
74
|
const items = flattenChildren(children);
|
|
@@ -61,83 +80,90 @@ const MenuRenderer = ({
|
|
|
61
80
|
),
|
|
62
81
|
"All child nodes within a menu component must be a MenuItem, MenuItemLink, MenuItemCheckbox or MenuItemDivider: https://seek-oss.github.io/braid-design-system/components/MenuRenderer"
|
|
63
82
|
);
|
|
64
|
-
const [{ open, highlightIndex, closeReason }, dispatch] = useReducer(
|
|
65
|
-
(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
return {
|
|
104
|
-
...state,
|
|
105
|
-
open: false,
|
|
106
|
-
closeReason: {
|
|
107
|
-
reason: "selection",
|
|
108
|
-
index: action.index,
|
|
109
|
-
id: action.id
|
|
110
|
-
},
|
|
111
|
-
highlightIndex: CLOSED_INDEX
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
case MENU_ITEM_HOVER: {
|
|
115
|
-
return { ...state, highlightIndex: action.value };
|
|
116
|
-
}
|
|
117
|
-
case MENU_TRIGGER_ENTER:
|
|
118
|
-
case MENU_TRIGGER_SPACE: {
|
|
119
|
-
const nextOpen = !state.open;
|
|
120
|
-
return {
|
|
121
|
-
...state,
|
|
122
|
-
open: nextOpen,
|
|
123
|
-
closeReason: CLOSE_REASON_EXIT,
|
|
124
|
-
highlightIndex: nextOpen ? 0 : CLOSED_INDEX
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
case MENU_TRIGGER_CLICK: {
|
|
128
|
-
const nextOpen = !state.open;
|
|
129
|
-
return {
|
|
130
|
-
...state,
|
|
131
|
-
open: nextOpen,
|
|
132
|
-
closeReason: CLOSE_REASON_EXIT
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
default:
|
|
83
|
+
const [{ open, highlightIndex, closeReason, triggerPosition }, dispatch] = useReducer((state, action) => {
|
|
84
|
+
switch (action.type) {
|
|
85
|
+
case MENU_TRIGGER_UP:
|
|
86
|
+
case MENU_ITEM_UP: {
|
|
87
|
+
return {
|
|
88
|
+
...state,
|
|
89
|
+
open: true,
|
|
90
|
+
closeReason: CLOSE_REASON_EXIT,
|
|
91
|
+
highlightIndex: getNextIndex(-1, state.highlightIndex, itemCount),
|
|
92
|
+
triggerPosition: getPosition(menuContainerRef.current)
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
case MENU_TRIGGER_DOWN:
|
|
96
|
+
case MENU_ITEM_DOWN: {
|
|
97
|
+
return {
|
|
98
|
+
...state,
|
|
99
|
+
open: true,
|
|
100
|
+
closeReason: CLOSE_REASON_EXIT,
|
|
101
|
+
highlightIndex: getNextIndex(1, state.highlightIndex, itemCount),
|
|
102
|
+
triggerPosition: getPosition(menuContainerRef.current)
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
case BACKDROP_CLICK:
|
|
106
|
+
case MENU_TRIGGER_ESCAPE:
|
|
107
|
+
case MENU_TRIGGER_TAB:
|
|
108
|
+
case MENU_ITEM_ESCAPE:
|
|
109
|
+
case MENU_ITEM_TAB: {
|
|
110
|
+
return {
|
|
111
|
+
...state,
|
|
112
|
+
open: false,
|
|
113
|
+
closeReason: CLOSE_REASON_EXIT,
|
|
114
|
+
highlightIndex: CLOSED_INDEX
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
case MENU_ITEM_ENTER:
|
|
118
|
+
case MENU_ITEM_SPACE:
|
|
119
|
+
case MENU_ITEM_CLICK: {
|
|
120
|
+
if ("formElement" in action && action.formElement) {
|
|
136
121
|
return state;
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
...state,
|
|
125
|
+
open: false,
|
|
126
|
+
closeReason: {
|
|
127
|
+
reason: "selection",
|
|
128
|
+
index: action.index,
|
|
129
|
+
id: action.id
|
|
130
|
+
},
|
|
131
|
+
highlightIndex: CLOSED_INDEX
|
|
132
|
+
};
|
|
137
133
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
134
|
+
case MENU_ITEM_HOVER: {
|
|
135
|
+
return { ...state, highlightIndex: action.value };
|
|
136
|
+
}
|
|
137
|
+
case MENU_TRIGGER_ENTER:
|
|
138
|
+
case MENU_TRIGGER_SPACE: {
|
|
139
|
+
const nextOpen = !state.open;
|
|
140
|
+
return {
|
|
141
|
+
...state,
|
|
142
|
+
open: nextOpen,
|
|
143
|
+
closeReason: CLOSE_REASON_EXIT,
|
|
144
|
+
highlightIndex: nextOpen ? 0 : CLOSED_INDEX,
|
|
145
|
+
triggerPosition: getPosition(menuContainerRef.current)
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
case MENU_TRIGGER_CLICK: {
|
|
149
|
+
const nextOpen = !state.open;
|
|
150
|
+
return {
|
|
151
|
+
...state,
|
|
152
|
+
open: nextOpen,
|
|
153
|
+
closeReason: CLOSE_REASON_EXIT,
|
|
154
|
+
triggerPosition: getPosition(menuContainerRef.current)
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
case WINDOW_RESIZE: {
|
|
158
|
+
return {
|
|
159
|
+
...state,
|
|
160
|
+
triggerPosition: getPosition(menuContainerRef.current)
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
default:
|
|
164
|
+
return state;
|
|
165
|
+
}
|
|
166
|
+
}, initialState);
|
|
141
167
|
useEffect(() => {
|
|
142
168
|
if (lastOpen.current === open) {
|
|
143
169
|
return;
|
|
@@ -154,6 +180,17 @@ const MenuRenderer = ({
|
|
|
154
180
|
buttonRef.current.focus();
|
|
155
181
|
}
|
|
156
182
|
};
|
|
183
|
+
useEffect(() => {
|
|
184
|
+
const handleResize = () => {
|
|
185
|
+
dispatch({ type: WINDOW_RESIZE });
|
|
186
|
+
};
|
|
187
|
+
if (open) {
|
|
188
|
+
window.addEventListener("resize", handleResize);
|
|
189
|
+
}
|
|
190
|
+
return () => {
|
|
191
|
+
window.removeEventListener("resize", handleResize);
|
|
192
|
+
};
|
|
193
|
+
}, [open]);
|
|
157
194
|
const onTriggerKeyUp = (event) => {
|
|
158
195
|
const targetKey = normalizeKey(event);
|
|
159
196
|
if (targetKey === " " && /firefox|iceweasel|fxios/i.test(navigator.userAgent)) {
|
|
@@ -195,41 +232,48 @@ const MenuRenderer = ({
|
|
|
195
232
|
dispatch({ type: MENU_TRIGGER_CLICK });
|
|
196
233
|
}
|
|
197
234
|
};
|
|
198
|
-
return /* @__PURE__ */ jsxs(
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
235
|
+
return /* @__PURE__ */ jsxs(
|
|
236
|
+
Box,
|
|
237
|
+
{
|
|
238
|
+
...buildDataAttributes({ data, validateRestProps: restProps }),
|
|
239
|
+
ref: menuContainerRef,
|
|
240
|
+
children: [
|
|
241
|
+
trigger(triggerProps, { open }),
|
|
242
|
+
open ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
243
|
+
/* @__PURE__ */ jsx(BraidPortal, { children: /* @__PURE__ */ jsx(
|
|
244
|
+
Menu,
|
|
245
|
+
{
|
|
246
|
+
align,
|
|
247
|
+
width: width2,
|
|
248
|
+
placement,
|
|
249
|
+
offsetSpace,
|
|
250
|
+
highlightIndex,
|
|
251
|
+
reserveIconSpace,
|
|
252
|
+
focusTrigger,
|
|
253
|
+
dispatch,
|
|
254
|
+
triggerPosition,
|
|
255
|
+
children: items
|
|
256
|
+
}
|
|
257
|
+
) }),
|
|
258
|
+
/* @__PURE__ */ jsx(
|
|
259
|
+
Box,
|
|
260
|
+
{
|
|
261
|
+
onClick: (event) => {
|
|
262
|
+
event.stopPropagation();
|
|
263
|
+
event.preventDefault();
|
|
264
|
+
dispatch({ type: BACKDROP_CLICK });
|
|
265
|
+
},
|
|
266
|
+
position: "fixed",
|
|
267
|
+
zIndex: "dropdownBackdrop",
|
|
268
|
+
top: 0,
|
|
269
|
+
left: 0,
|
|
270
|
+
className: backdrop
|
|
271
|
+
}
|
|
272
|
+
)
|
|
273
|
+
] }) : null
|
|
274
|
+
]
|
|
275
|
+
}
|
|
276
|
+
);
|
|
233
277
|
};
|
|
234
278
|
const isDivider = (node) => typeof node === "object" && node !== null && "type" in node && node.type === MenuItemDivider;
|
|
235
279
|
const borderRadius = "large";
|
|
@@ -239,14 +283,18 @@ function Menu({
|
|
|
239
283
|
width: width$1,
|
|
240
284
|
placement,
|
|
241
285
|
children,
|
|
242
|
-
open,
|
|
243
286
|
dispatch,
|
|
244
287
|
focusTrigger,
|
|
245
288
|
highlightIndex,
|
|
246
289
|
reserveIconSpace,
|
|
290
|
+
triggerPosition,
|
|
247
291
|
position = "absolute"
|
|
248
292
|
}) {
|
|
249
293
|
let dividerCount = 0;
|
|
294
|
+
const inlineVars = triggerPosition && assignInlineVars({
|
|
295
|
+
[triggerVars[placement]]: `${triggerPosition[placement]}px`,
|
|
296
|
+
[triggerVars[align]]: `${triggerPosition[align]}px`
|
|
297
|
+
});
|
|
250
298
|
return /* @__PURE__ */ jsx(MenuRendererContext.Provider, { value: { reserveIconSpace }, children: /* @__PURE__ */ jsxs(
|
|
251
299
|
Box,
|
|
252
300
|
{
|
|
@@ -256,19 +304,19 @@ function Menu({
|
|
|
256
304
|
boxShadow: placement === "top" ? "small" : "medium",
|
|
257
305
|
borderRadius,
|
|
258
306
|
background: "surface",
|
|
307
|
+
paddingY: "xxsmall",
|
|
259
308
|
marginTop: placement === "bottom" ? offsetSpace : void 0,
|
|
260
309
|
marginBottom: placement === "top" ? offsetSpace : void 0,
|
|
261
310
|
transition: "fast",
|
|
262
|
-
right: align === "right" ? 0 : void 0,
|
|
263
|
-
opacity: !open ? 0 : void 0,
|
|
264
311
|
overflow: "hidden",
|
|
312
|
+
style: inlineVars,
|
|
265
313
|
className: [
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
314
|
+
menuPosition,
|
|
315
|
+
animation,
|
|
316
|
+
width$1 !== "content" && width[width$1]
|
|
269
317
|
],
|
|
270
318
|
children: [
|
|
271
|
-
/* @__PURE__ */ jsx(
|
|
319
|
+
/* @__PURE__ */ jsx(ScrollContainer, { direction: "vertical", fadeSize: "small", children: /* @__PURE__ */ jsx(Box, { className: menuHeightLimit, children: Children.map(children, (item, i) => {
|
|
272
320
|
if (isDivider(item)) {
|
|
273
321
|
dividerCount++;
|
|
274
322
|
return item;
|
|
@@ -287,7 +335,7 @@ function Menu({
|
|
|
287
335
|
},
|
|
288
336
|
menuItemIndex
|
|
289
337
|
);
|
|
290
|
-
}) }),
|
|
338
|
+
}) }) }),
|
|
291
339
|
/* @__PURE__ */ jsx(
|
|
292
340
|
Overlay,
|
|
293
341
|
{
|
|
@@ -11,15 +11,15 @@ const OverflowMenu = ({
|
|
|
11
11
|
id,
|
|
12
12
|
...menuProps
|
|
13
13
|
}) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
14
|
-
|
|
14
|
+
lib_components_Box_Box_cjs.Box,
|
|
15
15
|
{
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
className: lib_components_OverflowMenu_OverflowMenu_css_cjs.wrapperPositioning,
|
|
17
|
+
display: "flex",
|
|
18
|
+
justifyContent: "flexEnd",
|
|
19
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20
|
+
lib_components_MenuRenderer_MenuRenderer_cjs.MenuRenderer,
|
|
18
21
|
{
|
|
19
|
-
|
|
20
|
-
justifyContent: "flexEnd",
|
|
21
|
-
className: lib_components_OverflowMenu_OverflowMenu_css_cjs.triggerOffset,
|
|
22
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
22
|
+
trigger: (triggerProps) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
23
23
|
lib_components_ButtonIcon_ButtonIcon_cjs.ButtonIcon,
|
|
24
24
|
{
|
|
25
25
|
id,
|
|
@@ -28,13 +28,13 @@ const OverflowMenu = ({
|
|
|
28
28
|
label,
|
|
29
29
|
...triggerProps
|
|
30
30
|
}
|
|
31
|
-
)
|
|
31
|
+
),
|
|
32
|
+
align: "right",
|
|
33
|
+
offsetSpace: "small",
|
|
34
|
+
...menuProps,
|
|
35
|
+
children
|
|
32
36
|
}
|
|
33
|
-
)
|
|
34
|
-
align: "right",
|
|
35
|
-
offsetSpace: "small",
|
|
36
|
-
...menuProps,
|
|
37
|
-
children
|
|
37
|
+
)
|
|
38
38
|
}
|
|
39
39
|
);
|
|
40
40
|
exports.OverflowMenu = OverflowMenu;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
const fileScope = require("@vanilla-extract/css/fileScope");
|
|
3
3
|
const css = require("@vanilla-extract/css");
|
|
4
4
|
fileScope.setFileScope("src/lib/components/OverflowMenu/OverflowMenu.css.ts", "braid-design-system");
|
|
5
|
-
const
|
|
5
|
+
const wrapperPositioning = css.style({
|
|
6
6
|
margin: "-1px -6px"
|
|
7
|
-
}, "
|
|
7
|
+
}, "wrapperPositioning");
|
|
8
8
|
fileScope.endFileScope();
|
|
9
|
-
exports.
|
|
9
|
+
exports.wrapperPositioning = wrapperPositioning;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { setFileScope, endFileScope } from "@vanilla-extract/css/fileScope";
|
|
2
2
|
import { style } from "@vanilla-extract/css";
|
|
3
3
|
setFileScope("src/lib/components/OverflowMenu/OverflowMenu.css.ts", "braid-design-system");
|
|
4
|
-
const
|
|
4
|
+
const wrapperPositioning = style({
|
|
5
5
|
margin: "-1px -6px"
|
|
6
|
-
}, "
|
|
6
|
+
}, "wrapperPositioning");
|
|
7
7
|
endFileScope();
|
|
8
8
|
export {
|
|
9
|
-
|
|
9
|
+
wrapperPositioning
|
|
10
10
|
};
|
|
@@ -2,7 +2,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { MenuRenderer } from "../MenuRenderer/MenuRenderer.mjs";
|
|
3
3
|
import { ButtonIcon } from "../ButtonIcon/ButtonIcon.mjs";
|
|
4
4
|
import { Box } from "../Box/Box.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { wrapperPositioning } from "./OverflowMenu.css.mjs";
|
|
6
6
|
import { IconOverflow } from "../icons/IconOverflow/IconOverflow.mjs";
|
|
7
7
|
const OverflowMenu = ({
|
|
8
8
|
label,
|
|
@@ -10,15 +10,15 @@ const OverflowMenu = ({
|
|
|
10
10
|
id,
|
|
11
11
|
...menuProps
|
|
12
12
|
}) => /* @__PURE__ */ jsx(
|
|
13
|
-
|
|
13
|
+
Box,
|
|
14
14
|
{
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
className: wrapperPositioning,
|
|
16
|
+
display: "flex",
|
|
17
|
+
justifyContent: "flexEnd",
|
|
18
|
+
children: /* @__PURE__ */ jsx(
|
|
19
|
+
MenuRenderer,
|
|
17
20
|
{
|
|
18
|
-
|
|
19
|
-
justifyContent: "flexEnd",
|
|
20
|
-
className: triggerOffset,
|
|
21
|
-
children: /* @__PURE__ */ jsx(
|
|
21
|
+
trigger: (triggerProps) => /* @__PURE__ */ jsx(
|
|
22
22
|
ButtonIcon,
|
|
23
23
|
{
|
|
24
24
|
id,
|
|
@@ -27,13 +27,13 @@ const OverflowMenu = ({
|
|
|
27
27
|
label,
|
|
28
28
|
...triggerProps
|
|
29
29
|
}
|
|
30
|
-
)
|
|
30
|
+
),
|
|
31
|
+
align: "right",
|
|
32
|
+
offsetSpace: "small",
|
|
33
|
+
...menuProps,
|
|
34
|
+
children
|
|
31
35
|
}
|
|
32
|
-
)
|
|
33
|
-
align: "right",
|
|
34
|
-
offsetSpace: "small",
|
|
35
|
-
...menuProps,
|
|
36
|
-
children
|
|
36
|
+
)
|
|
37
37
|
}
|
|
38
38
|
);
|
|
39
39
|
export {
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
3
|
+
const React = require("react");
|
|
4
|
+
const lib_hooks_useIsomorphicLayoutEffect_cjs = require("../../../hooks/useIsomorphicLayoutEffect.cjs");
|
|
5
|
+
const lib_components_Box_Box_cjs = require("../../Box/Box.cjs");
|
|
6
|
+
const lib_components_private_buildDataAttributes_cjs = require("../buildDataAttributes.cjs");
|
|
7
|
+
const throttleDebounce = require("throttle-debounce");
|
|
8
|
+
const lib_components_private_ScrollContainer_ScrollContainer_css_cjs = require("./ScrollContainer.css.cjs");
|
|
9
|
+
const scrollOffset = 2;
|
|
10
|
+
const maskOverflow = (element, direction) => {
|
|
11
|
+
const atTop = element.scrollTop <= 0;
|
|
12
|
+
const atBottom = element.scrollHeight - element.offsetHeight - element.scrollTop < scrollOffset;
|
|
13
|
+
const atLeft = element.scrollLeft <= 0;
|
|
14
|
+
const atRight = element.scrollWidth - element.offsetWidth - element.scrollLeft < scrollOffset;
|
|
15
|
+
if (direction === "vertical" || direction === "all") {
|
|
16
|
+
element.classList[atTop ? "remove" : "add"](lib_components_private_ScrollContainer_ScrollContainer_css_cjs.maskTop);
|
|
17
|
+
element.classList[atBottom ? "remove" : "add"](lib_components_private_ScrollContainer_ScrollContainer_css_cjs.maskBottom);
|
|
18
|
+
}
|
|
19
|
+
if (direction === "horizontal" || direction === "all") {
|
|
20
|
+
element.classList[atLeft ? "remove" : "add"](lib_components_private_ScrollContainer_ScrollContainer_css_cjs.maskLeft);
|
|
21
|
+
element.classList[atRight ? "remove" : "add"](lib_components_private_ScrollContainer_ScrollContainer_css_cjs.maskRight);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const ScrollContainer = ({
|
|
25
|
+
children,
|
|
26
|
+
direction = "horizontal",
|
|
27
|
+
fadeSize = "medium",
|
|
28
|
+
hideScrollbar = false,
|
|
29
|
+
data,
|
|
30
|
+
...restProps
|
|
31
|
+
}) => {
|
|
32
|
+
const containerRef = React.useRef(null);
|
|
33
|
+
const updateMask = throttleDebounce.throttle(
|
|
34
|
+
100,
|
|
35
|
+
React.useCallback(() => {
|
|
36
|
+
if (containerRef.current) {
|
|
37
|
+
maskOverflow(containerRef.current, direction);
|
|
38
|
+
}
|
|
39
|
+
}, [containerRef, direction])
|
|
40
|
+
);
|
|
41
|
+
lib_hooks_useIsomorphicLayoutEffect_cjs.useIsomorphicLayoutEffect(() => {
|
|
42
|
+
if (containerRef.current) {
|
|
43
|
+
updateMask();
|
|
44
|
+
}
|
|
45
|
+
window.addEventListener("resize", updateMask);
|
|
46
|
+
return () => window.removeEventListener("resize", updateMask);
|
|
47
|
+
}, [updateMask]);
|
|
48
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
49
|
+
lib_components_Box_Box_cjs.Box,
|
|
50
|
+
{
|
|
51
|
+
ref: containerRef,
|
|
52
|
+
onScroll: updateMask,
|
|
53
|
+
position: "relative",
|
|
54
|
+
height: "full",
|
|
55
|
+
className: [
|
|
56
|
+
lib_components_private_ScrollContainer_ScrollContainer_css_cjs.container,
|
|
57
|
+
lib_components_private_ScrollContainer_ScrollContainer_css_cjs.mask,
|
|
58
|
+
hideScrollbar ? lib_components_private_ScrollContainer_ScrollContainer_css_cjs.hideScrollbar : null,
|
|
59
|
+
lib_components_private_ScrollContainer_ScrollContainer_css_cjs.fadeSize[fadeSize],
|
|
60
|
+
lib_components_private_ScrollContainer_ScrollContainer_css_cjs.direction[direction]
|
|
61
|
+
],
|
|
62
|
+
...lib_components_private_buildDataAttributes_cjs.buildDataAttributes({ data, validateRestProps: restProps }),
|
|
63
|
+
children
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
exports.ScrollContainer = ScrollContainer;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const fileScope = require("@vanilla-extract/css/fileScope");
|
|
3
|
+
const css = require("@vanilla-extract/css");
|
|
4
|
+
fileScope.setFileScope("src/lib/components/private/ScrollContainer/ScrollContainer.css.ts", "braid-design-system");
|
|
5
|
+
const container = css.style({
|
|
6
|
+
WebkitOverflowScrolling: "touch",
|
|
7
|
+
WebkitMaskComposite: "destination-in",
|
|
8
|
+
// Fallback for browsers that don't support mask-composite
|
|
9
|
+
maskComposite: "intersect"
|
|
10
|
+
}, "container");
|
|
11
|
+
const hideScrollbar = css.style({
|
|
12
|
+
scrollbarWidth: "none",
|
|
13
|
+
msOverflowStyle: "none",
|
|
14
|
+
"::-webkit-scrollbar": {
|
|
15
|
+
width: 0,
|
|
16
|
+
height: 0
|
|
17
|
+
}
|
|
18
|
+
}, "hideScrollbar");
|
|
19
|
+
const scrollOverlaySize = css.createVar("scrollOverlaySize");
|
|
20
|
+
const fadeSize = css.styleVariants({
|
|
21
|
+
small: {
|
|
22
|
+
vars: {
|
|
23
|
+
[scrollOverlaySize]: "40px"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
medium: {
|
|
27
|
+
vars: {
|
|
28
|
+
[scrollOverlaySize]: "60px"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
large: {
|
|
32
|
+
vars: {
|
|
33
|
+
[scrollOverlaySize]: "80px"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}, "fadeSize");
|
|
37
|
+
const direction = css.styleVariants({
|
|
38
|
+
horizontal: {
|
|
39
|
+
overflowX: "auto",
|
|
40
|
+
overflowY: "hidden"
|
|
41
|
+
},
|
|
42
|
+
vertical: {
|
|
43
|
+
overflowX: "hidden",
|
|
44
|
+
overflowY: "auto"
|
|
45
|
+
},
|
|
46
|
+
all: {
|
|
47
|
+
overflow: "auto"
|
|
48
|
+
}
|
|
49
|
+
}, "direction");
|
|
50
|
+
const left = css.createVar("left");
|
|
51
|
+
const right = css.createVar("right");
|
|
52
|
+
const top = css.createVar("top");
|
|
53
|
+
const bottom = css.createVar("bottom");
|
|
54
|
+
const mask = css.style({
|
|
55
|
+
maskImage: [`linear-gradient(to bottom, transparent 0, black ${css.fallbackVar(top, "0")})`, `linear-gradient(to right, transparent 0, black ${css.fallbackVar(left, "0")})`, `linear-gradient(to left, transparent 0, black ${css.fallbackVar(right, "0")})`, `linear-gradient(to top, transparent 0, black ${css.fallbackVar(bottom, "0")})`].join(",")
|
|
56
|
+
}, "mask");
|
|
57
|
+
const maskLeft = css.style({
|
|
58
|
+
vars: {
|
|
59
|
+
[left]: scrollOverlaySize
|
|
60
|
+
}
|
|
61
|
+
}, "maskLeft");
|
|
62
|
+
const maskRight = css.style({
|
|
63
|
+
vars: {
|
|
64
|
+
[right]: scrollOverlaySize
|
|
65
|
+
}
|
|
66
|
+
}, "maskRight");
|
|
67
|
+
const maskTop = css.style({
|
|
68
|
+
vars: {
|
|
69
|
+
[top]: scrollOverlaySize
|
|
70
|
+
}
|
|
71
|
+
}, "maskTop");
|
|
72
|
+
const maskBottom = css.style({
|
|
73
|
+
vars: {
|
|
74
|
+
[bottom]: scrollOverlaySize
|
|
75
|
+
}
|
|
76
|
+
}, "maskBottom");
|
|
77
|
+
fileScope.endFileScope();
|
|
78
|
+
exports.container = container;
|
|
79
|
+
exports.direction = direction;
|
|
80
|
+
exports.fadeSize = fadeSize;
|
|
81
|
+
exports.hideScrollbar = hideScrollbar;
|
|
82
|
+
exports.mask = mask;
|
|
83
|
+
exports.maskBottom = maskBottom;
|
|
84
|
+
exports.maskLeft = maskLeft;
|
|
85
|
+
exports.maskRight = maskRight;
|
|
86
|
+
exports.maskTop = maskTop;
|