orcs-design-system 3.3.26 → 3.3.28

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.
@@ -95,6 +95,9 @@ const FloatingPanels = _ref => {
95
95
  }
96
96
  return items;
97
97
  }, [panels, selectedPanelId, togglePanel]);
98
+ const showPanelContainer = useMemo(() => {
99
+ return panels.some(panel => panel.id === selectedPanelId);
100
+ }, [panels, selectedPanelId]);
98
101
  return /*#__PURE__*/_jsxs(ComponentContainer, {
99
102
  centered: centered,
100
103
  alignPanels: alignPanels,
@@ -103,7 +106,7 @@ const FloatingPanels = _ref => {
103
106
  zIndex: zIndex,
104
107
  children: [/*#__PURE__*/_jsx(PanelBar, {
105
108
  children: panelBarItems
106
- }), /*#__PURE__*/_jsx(PanelContainer, {
109
+ }), showPanelContainer && /*#__PURE__*/_jsx(PanelContainer, {
107
110
  containerHeight: containerHeight,
108
111
  children: panels.map(panel => /*#__PURE__*/_jsx(Panel, {
109
112
  title: panel.title,
@@ -1,4 +1,4 @@
1
- import React, { useState, useMemo } from "react";
1
+ import React, { useState, useMemo, useEffect } from "react";
2
2
  import { useFloating, autoUpdate, offset, flip, shift, useHover, useFocus, useDismiss, useRole, useInteractions, FloatingPortal, safePolygon, FloatingFocusManager } from "@floating-ui/react";
3
3
  import themeGet from "@styled-system/theme-get";
4
4
  import styled from "styled-components";
@@ -29,6 +29,49 @@ const StyledPopover = styled.div.withConfig({
29
29
  displayName: "Popover__StyledPopover",
30
30
  componentId: "sc-1bwoak-2"
31
31
  })(["font-size:", ";line-height:", ";font-weight:", ";text-align:", ";word-break:break-word;color:", ";outline:0;padding:", ";border-radius:", ";width:", ";background:", ";border:1px solid ", ";box-shadow:", ";user-select:", ";&.hack-for-legacy-tests{position:absolute;pointer-events:none;opacity:0;visibility:hidden;height:0;width:0;padding:0;overflow:hidden;}&.visible{opacity:1;pointer-events:auto;visibility:visible;}& a{font-size:", ";}&:before{content:\"\";z-index:2;height:0;width:0;border-style:solid;border-width:6px 6px 6px 0;border-color:transparent;border-right-color:", ";left:-6px;top:50%;margin-top:-6px;position:absolute;}&:after{content:\"\";z-index:1;position:absolute;border-color:transparent;border-right-color:", ";height:0;width:0;border-style:solid;border-width:6px 6px 6px 0;left:-7px;top:50%;margin-top:-6px;}&.top{&:before{left:50%;top:auto;margin-top:0;bottom:-9px;margin-left:-3px;transform:rotate(-90deg);}&:after{left:50%;top:auto;margin-top:0;bottom:-10px;margin-left:-3px;transform:rotate(-90deg);}}&.topRight,&.top-end{&:before{left:1px;top:auto;margin-top:0;bottom:-5px;margin-left:-6px;transform:rotate(-45deg);border-width:5px 10px 5px 0;}&:after{left:1px;top:auto;margin-top:0;bottom:-6px;margin-left:-7px;transform:rotate(-45deg);border-width:5px 10px 5px 0;}}&.bottomRight,&.bottom-end{&:before{left:1px;bottom:auto;margin-top:0;top:-5px;margin-left:-6px;transform:rotate(45deg);border-width:5px 10px 5px 0;}&:after{left:1px;bottom:auto;margin-top:0;top:-6px;margin-left:-7px;transform:rotate(45deg);border-width:5px 10px 5px 0;}}&.bottom{&:before{left:50%;top:-9px;margin-top:0;margin-left:-3px;transform:rotate(90deg);}&:after{left:50%;top:-10px;margin-top:0;margin-left:-3px;transform:rotate(90deg);}}&.bottomLeft,&.bottom-start{&:before{right:1px;left:auto;bottom:auto;margin-top:0;top:-5px;margin-right:-6px;transform:rotate(135deg);border-width:5px 10px 5px 0;}&:after{right:1px;left:auto;bottom:auto;margin-top:0;top:-6px;margin-right:-7px;transform:rotate(135deg);border-width:5px 10px 5px 0;}}&.left{&:before{left:auto;right:-6px;transform:rotate(180deg);}&:after{left:auto;right:-7px;transform:rotate(180deg);top:50%;margin-top:-6px;}}&.topLeft,&.top-start{&:before{right:1px;left:auto;top:auto;margin-top:0;bottom:-5px;margin-right:-6px;transform:rotate(225deg);border-width:5px 10px 5px 0;}&:after{right:1px;left:auto;top:auto;margin-top:0;bottom:-6px;margin-right:-7px;transform:rotate(225deg);border-width:5px 10px 5px 0;}}"], themeGet("fontSizes.0"), themeGet("fontSizes.1"), themeGet("fontWeights.1"), props => props.textAlign ? props.textAlign : "left", themeGet("colors.greyDarkest"), themeGet("space.3"), themeGet("radii.1"), props => props.width ? props.width : "200px", themeGet("colors.white"), themeGet("colors.greyLight"), themeGet("shadows.boxDefault"), props => props.enableSelectAll ? "all" : "auto", themeGet("fontSizes.0"), themeGet("colors.white"), themeGet("colors.greyMid"));
32
+
33
+ /**
34
+ * Prevents the browser from scrolling to the previously focused element
35
+ * when a popover or tooltip closes — and skips focus entirely if it's offscreen.
36
+ */
37
+ export function usePreventScrollOnRestoreFocus(enabled) {
38
+ useEffect(() => {
39
+ if (!enabled) {
40
+ return;
41
+ }
42
+ const previouslyFocused = document.activeElement;
43
+ if (!(previouslyFocused instanceof HTMLElement)) {
44
+ return;
45
+ }
46
+ const originalFocus = previouslyFocused.focus;
47
+
48
+ // Check if element is in the viewport
49
+ const isInViewport = isElementInViewport(previouslyFocused);
50
+ if (!isInViewport) {
51
+ // Skip restoring focus entirely
52
+ previouslyFocused.focus = () => {};
53
+ } else {
54
+ // Patch focus to use preventScroll
55
+ previouslyFocused.focus = function () {
56
+ try {
57
+ originalFocus.call(this, {
58
+ preventScroll: true
59
+ });
60
+ } catch {
61
+ // fallback if preventScroll isn't accepted
62
+ originalFocus.call(this);
63
+ }
64
+ };
65
+ }
66
+ return () => {
67
+ previouslyFocused.focus = originalFocus;
68
+ };
69
+ }, [enabled]);
70
+ }
71
+ function isElementInViewport(el) {
72
+ const rect = el.getBoundingClientRect();
73
+ return rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth);
74
+ }
32
75
  export default function Popover(_ref) {
33
76
  let {
34
77
  children,
@@ -98,6 +141,7 @@ export default function Popover(_ref) {
98
141
  ...props,
99
142
  className: `${props.className} ${visiblePopoverClassName}`
100
143
  }), [getFloatingProps, props, visiblePopoverClassName]);
144
+ usePreventScrollOnRestoreFocus(!visible);
101
145
  return /*#__PURE__*/_jsxs(Container, {
102
146
  inlineBlock: inlineBlock,
103
147
  ...props,
@@ -117,7 +161,11 @@ export default function Popover(_ref) {
117
161
  children: containsLinks ? /*#__PURE__*/_jsx(FloatingFocusManager, {
118
162
  context: context,
119
163
  modal: false,
120
- initialFocus: isRenderedInReactSelectMenu(context.refs.reference) && -1,
164
+ restoreFocus: false,
165
+ initialFocus:
166
+ // If the popover is rendered in a React Select menu, don't focus the first element. Keep focus on select input else it will close the popover.
167
+ // Default to 0 to focus the first element if not rendered in a React Select menu.
168
+ isRenderedInReactSelectMenu(context.refs.reference) ? -1 : 0,
121
169
  children: /*#__PURE__*/_jsx(StyledPopover, {
122
170
  className: visiblePopoverClassName,
123
171
  ref: refs.setFloating,
@@ -359,6 +359,7 @@ const Select = /*#__PURE__*/forwardRef((props, ref) => {
359
359
  const component = /*#__PURE__*/_jsxs(Wrapper, {
360
360
  inverted: props.inverted,
361
361
  "data-testid": props["data-testid"],
362
+ "data-select-wrapper": "true",
362
363
  ...SelectStyles,
363
364
  children: [props.label && /*#__PURE__*/_jsxs(Label, {
364
365
  inverted: props.inverted,
@@ -6,15 +6,24 @@ const getFloatingUiZIndex = triggerRef => {
6
6
  return 900;
7
7
  };
8
8
  const REACT_SELECT_MENU = "react-select-menu";
9
- const isRenderedInReactSelectMenu = triggerRef => document.getElementById(REACT_SELECT_MENU)?.contains?.(triggerRef.current);
9
+ const getReactSelectMenu = triggerRef => {
10
+ const selectWrapper = triggerRef?.current?.closest('[data-select-wrapper="true"]');
11
+ if (selectWrapper) {
12
+ return selectWrapper;
13
+ }
14
+ return document.getElementById(REACT_SELECT_MENU);
15
+ };
16
+ const isRenderedInReactSelectMenu = triggerRef => {
17
+ return !!getReactSelectMenu(triggerRef);
18
+ };
10
19
  const getFloatingUiRootElement = triggerRef => {
11
20
  const activeModalRef = document.getElementById("modal-overlay");
12
- const isRenderedInModal = activeModalRef?.contains?.(triggerRef.current);
21
+ const isRenderedInModal = activeModalRef?.contains?.(triggerRef?.current);
13
22
  if (isRenderedInModal) {
14
23
  return document.getElementById("modal");
15
24
  }
16
- if (isRenderedInReactSelectMenu(triggerRef)) {
17
- return document.getElementById(REACT_SELECT_MENU).firstChild;
25
+ if (isRenderedInReactSelectMenu) {
26
+ return isRenderedInReactSelectMenu.firstChild;
18
27
  }
19
28
  return undefined;
20
29
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orcs-design-system",
3
- "version": "3.3.26",
3
+ "version": "3.3.28",
4
4
  "engines": {
5
5
  "node": "20.12.2"
6
6
  },
@@ -67,8 +67,8 @@
67
67
  "react-number-format": "^5.3.0",
68
68
  "react-router-dom": "^5.3.4",
69
69
  "react-select": "^5.7.4",
70
- "styled-system": "^5.1.5",
71
- "styled-components": "^5.2.1"
70
+ "styled-components": "^5.2.1",
71
+ "styled-system": "^5.1.5"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@babel/cli": "^7.12.10",
@@ -106,7 +106,7 @@
106
106
  "@testing-library/react": "^11.2.2",
107
107
  "@types/jest": "^27.5.2",
108
108
  "@types/styled-components": "^5.1.7",
109
- "audit-ci": "^6.1.2",
109
+ "audit-ci": "^7.1.0",
110
110
  "babel-core": "^7.0.0-bridge.0",
111
111
  "babel-eslint": "^10.0.0",
112
112
  "babel-loader": "^8.1.0",
@@ -130,7 +130,7 @@
130
130
  "jest": "^27.5.1",
131
131
  "nodemon": "^3.1.0",
132
132
  "npm-run-all": "^4.1.5",
133
- "playroom": "^0.32.1",
133
+ "playroom": "^0.43.0",
134
134
  "postcss": "8.5.2",
135
135
  "prettier": "^2.2.1",
136
136
  "react": "^18.3.1",