@homebound/beam 2.75.1 → 2.76.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.
@@ -18,9 +18,14 @@ export interface BeamContextState {
18
18
  drawerCanCloseChecks: MutableRefObject<CheckFn[]>;
19
19
  /** Checks when closing SuperDrawer Details, a double array to keep per-detail lists. */
20
20
  drawerCanCloseDetailsChecks: MutableRefObject<CheckFn[][]>;
21
+ /** The ref for defining the portal element's location for Tab actions */
22
+ tabActionsRef: MutableRefObject<HTMLDivElement | null>;
23
+ /** The div for Tab actions to portal into */
24
+ tabActionsDiv: HTMLDivElement;
21
25
  }
22
26
  /** This is only exported internally, for useModal and useSuperDrawer, it's not a public API. */
23
27
  export declare const BeamContext: import("react").Context<BeamContextState>;
24
28
  export declare function BeamProvider({ children }: {
25
29
  children: ReactNode;
26
30
  }): import("@emotion/react/jsx-runtime").JSX.Element;
31
+ export declare function useBeamContext(): BeamContextState;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BeamProvider = exports.BeamContext = void 0;
3
+ exports.useBeamContext = exports.BeamProvider = exports.BeamContext = void 0;
4
4
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const react_aria_1 = require("react-aria");
@@ -17,6 +17,8 @@ exports.BeamContext = (0, react_1.createContext)({
17
17
  drawerContentStack: new index_1.EmptyRef(),
18
18
  drawerCanCloseChecks: new index_1.EmptyRef(),
19
19
  drawerCanCloseDetailsChecks: new index_1.EmptyRef(),
20
+ tabActionsRef: new index_1.EmptyRef(),
21
+ tabActionsDiv: undefined,
20
22
  });
21
23
  function BeamProvider({ children }) {
22
24
  // We want the identity of these to be stable, b/c they end up being used as dependencies
@@ -32,6 +34,8 @@ function BeamProvider({ children }) {
32
34
  const drawerContentStackRef = (0, react_1.useRef)([]);
33
35
  const drawerCanCloseChecks = (0, react_1.useRef)([]);
34
36
  const drawerCanCloseDetailsChecks = (0, react_1.useRef)([]);
37
+ const tabActionsRef = (0, react_1.useRef)(null);
38
+ const tabActionsDiv = (0, react_1.useMemo)(() => document.createElement("div"), []);
35
39
  // We essentially expose the refs, but with our own getters/setters so that we can
36
40
  // have the setters call `tick` to re-render this Provider
37
41
  const context = (0, react_1.useMemo)(() => {
@@ -46,6 +50,8 @@ function BeamProvider({ children }) {
46
50
  modalFooterDiv,
47
51
  drawerCanCloseChecks,
48
52
  drawerCanCloseDetailsChecks,
53
+ tabActionsRef,
54
+ tabActionsDiv,
49
55
  };
50
56
  }, [modalBodyDiv, modalFooterDiv]);
51
57
  return ((0, jsx_runtime_1.jsxs)(exports.BeamContext.Provider, Object.assign({ value: { ...context } }, { children: [(0, jsx_runtime_1.jsxs)(react_aria_1.OverlayProvider, { children: [children, modalRef.current && drawerContentStackRef.current.length === 0 && (0, jsx_runtime_1.jsx)(Modal_1.Modal, Object.assign({}, modalRef.current), void 0)] }, void 0), (0, jsx_runtime_1.jsx)(SuperDrawer_1.SuperDrawer, {}, void 0)] }), void 0));
@@ -65,3 +71,7 @@ class PretendRefThatTicks {
65
71
  this.tick();
66
72
  }
67
73
  }
74
+ function useBeamContext() {
75
+ return (0, react_1.useContext)(exports.BeamContext);
76
+ }
77
+ exports.useBeamContext = useBeamContext;
@@ -23,7 +23,7 @@ function Modal(props) {
23
23
  const { size = "md", content, forceScrolling } = props;
24
24
  const isFixedHeight = typeof size !== "string";
25
25
  const ref = (0, react_1.useRef)(null);
26
- const { modalBodyDiv, modalFooterDiv, modalHeaderDiv, drawerContentStack } = (0, react_1.useContext)(BeamContext_1.BeamContext);
26
+ const { modalBodyDiv, modalFooterDiv, modalHeaderDiv, drawerContentStack } = (0, BeamContext_1.useBeamContext)();
27
27
  const { closeModal } = (0, useModal_1.useModal)();
28
28
  const { overlayProps, underlayProps } = (0, react_aria_1.useOverlay)({ ...props, isOpen: true, onClose: closeModal, isDismissable: true }, ref);
29
29
  const { modalProps } = (0, react_aria_1.useModal)();
@@ -56,20 +56,20 @@ function Modal(props) {
56
56
  }
57
57
  exports.Modal = Modal;
58
58
  function ModalHeader({ children }) {
59
- const { modalHeaderDiv } = (0, react_1.useContext)(BeamContext_1.BeamContext);
59
+ const { modalHeaderDiv } = (0, BeamContext_1.useBeamContext)();
60
60
  return (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children }, void 0), modalHeaderDiv);
61
61
  }
62
62
  exports.ModalHeader = ModalHeader;
63
63
  /** Provides consistent styling and the scrolling behavior for a modal's primary content. */
64
64
  function ModalBody({ children }) {
65
- const { modalBodyDiv } = (0, react_1.useContext)(BeamContext_1.BeamContext);
65
+ const { modalBodyDiv } = (0, BeamContext_1.useBeamContext)();
66
66
  const testId = (0, utils_1.useTestIds)({}, testIdPrefix);
67
67
  return (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)("div", Object.assign({ css: Css_1.Css.px3.$ }, testId.content, { children: children }), void 0), modalBodyDiv);
68
68
  }
69
69
  exports.ModalBody = ModalBody;
70
70
  /** Provides consistent styling for modal footers, i.e. where actions are placed. */
71
71
  function ModalFooter({ children, xss, }) {
72
- const { modalFooterDiv } = (0, react_1.useContext)(BeamContext_1.BeamContext);
72
+ const { modalFooterDiv } = (0, BeamContext_1.useBeamContext)();
73
73
  const testId = (0, utils_1.useTestIds)({}, testIdPrefix);
74
74
  return (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)("div", Object.assign({ css: { ...Css_1.Css.p3.df.aic.jcfe.childGap1.$, ...xss } }, testId.footer, { children: children }), void 0), modalFooterDiv);
75
75
  }
@@ -5,7 +5,7 @@ const react_1 = require("react");
5
5
  const BeamContext_1 = require("../BeamContext");
6
6
  const utils_1 = require("../../utils");
7
7
  function useModal() {
8
- const { modalState, modalCanCloseChecks } = (0, react_1.useContext)(BeamContext_1.BeamContext);
8
+ const { modalState, modalCanCloseChecks } = (0, BeamContext_1.useBeamContext)();
9
9
  const lastCanClose = (0, react_1.useRef)();
10
10
  return (0, react_1.useMemo)(() => ({
11
11
  openModal(props) {
@@ -2,12 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ConfirmCloseModal = void 0;
4
4
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
- const react_1 = require("react");
6
5
  const src_1 = require("../..");
7
6
  const BeamContext_1 = require("../BeamContext");
8
7
  /** Modal content to appear when a close checks fails */
9
8
  function ConfirmCloseModal({ onClose }) {
10
- const { modalState } = (0, react_1.useContext)(BeamContext_1.BeamContext);
9
+ const { modalState } = (0, BeamContext_1.useBeamContext)();
11
10
  // TODO: Change to closeModal from useModal when canCloseChecks are reset
12
11
  function closeModal() {
13
12
  // Not using closeModal from useModal since the canClose checks are not reset
@@ -32,7 +32,7 @@ const utils_1 = require("../../utils");
32
32
  * above the SuperDrawer.
33
33
  */
34
34
  function SuperDrawer() {
35
- const { drawerContentStack: contentStack, modalState, modalBodyDiv, modalFooterDiv, modalHeaderDiv, } = (0, react_3.useContext)(BeamContext_1.BeamContext);
35
+ const { drawerContentStack: contentStack, modalState, modalBodyDiv, modalFooterDiv, modalHeaderDiv, } = (0, BeamContext_1.useBeamContext)();
36
36
  const { closeDrawer } = (0, components_1.useSuperDrawer)();
37
37
  const drawerHeaderRef = (0, react_3.useRef)(null);
38
38
  const modalBodyRef = (0, react_3.useRef)(null);
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SuperDrawerContent = void 0;
4
4
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
5
  const framer_motion_1 = require("framer-motion");
6
- const react_1 = require("react");
7
6
  const BeamContext_1 = require("../BeamContext");
8
7
  const Button_1 = require("../Button");
9
8
  const useSuperDrawer_1 = require("./useSuperDrawer");
@@ -17,7 +16,7 @@ const Css_1 = require("../../Css");
17
16
  */
18
17
  const SuperDrawerContent = ({ children, actions }) => {
19
18
  const { closeDrawerDetail } = (0, useSuperDrawer_1.useSuperDrawer)();
20
- const { drawerContentStack: contentStack } = (0, react_1.useContext)(BeamContext_1.BeamContext);
19
+ const { drawerContentStack: contentStack } = (0, BeamContext_1.useBeamContext)();
21
20
  // Determine if the current element is a new content element or an detail element
22
21
  const { kind } = contentStack.current[contentStack.current.length - 1];
23
22
  function wrapWithMotionAndMaybeBack(children) {
@@ -7,7 +7,7 @@ const BeamContext_1 = require("../BeamContext");
7
7
  const Modal_1 = require("../Modal");
8
8
  const ConfirmCloseModal_1 = require("./ConfirmCloseModal");
9
9
  function useSuperDrawer() {
10
- const { drawerContentStack: contentStack, modalState, drawerCanCloseChecks: canCloseChecks, drawerCanCloseDetailsChecks: canCloseDetailsChecks, } = (0, react_1.useContext)(BeamContext_1.BeamContext);
10
+ const { drawerContentStack: contentStack, modalState, drawerCanCloseChecks: canCloseChecks, drawerCanCloseDetailsChecks: canCloseDetailsChecks, } = (0, BeamContext_1.useBeamContext)();
11
11
  const { openModal } = (0, Modal_1.useModal)();
12
12
  function canCloseDrawerDetails(i, doChange) {
13
13
  var _a;
@@ -1,4 +1,4 @@
1
- import { ReactNode } from "react";
1
+ import { PropsWithChildren, ReactNode, ReactPortal } from "react";
2
2
  import type { IconKey } from "./";
3
3
  import { Margin, Only, Xss } from "../Css";
4
4
  export interface Tab<V extends string = string> {
@@ -97,4 +97,5 @@ export declare function getTabStyles(): {
97
97
  };
98
98
  };
99
99
  export declare function getNextTabValue<V extends string>(selected: V, key: "ArrowLeft" | "ArrowRight", tabs: Tab<V>[] | RouteTab<V>[]): V;
100
+ export declare function TabActions({ children }: PropsWithChildren<{}>): ReactPortal;
100
101
  export {};
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getNextTabValue = exports.getTabStyles = exports.Tabs = exports.TabContent = exports.TabsWithContent = void 0;
3
+ exports.TabActions = exports.getNextTabValue = exports.getTabStyles = exports.Tabs = exports.TabContent = exports.TabsWithContent = void 0;
4
4
  const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
5
5
  const change_case_1 = require("change-case");
6
6
  const react_1 = require("react");
7
7
  const react_aria_1 = require("react-aria");
8
+ const react_dom_1 = require("react-dom");
8
9
  const react_router_1 = require("react-router");
9
10
  const react_router_dom_1 = require("react-router-dom");
11
+ const BeamContext_1 = require("./BeamContext");
10
12
  const Css_1 = require("../Css");
11
13
  const utils_1 = require("../utils");
12
14
  const defaultTestId_1 = require("../utils/defaultTestId");
@@ -21,11 +23,7 @@ const Icon_1 = require("./Icon");
21
23
  * and `TabContent` components directly.
22
24
  */
23
25
  function TabsWithContent(props) {
24
- // Hide the tabs if only one tab is enabled, and `alwaysShowAllTabs` is not true
25
- const hideTabs = props.alwaysShowAllTabs
26
- ? false
27
- : props.tabs.filter((t) => !t.disabled).length === 1;
28
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [!hideTabs && (0, jsx_runtime_1.jsx)(Tabs, Object.assign({}, props), void 0), (0, jsx_runtime_1.jsx)(TabContent, Object.assign({}, props), void 0)] }, void 0));
26
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Tabs, Object.assign({}, props), void 0), (0, jsx_runtime_1.jsx)(TabContent, Object.assign({}, props), void 0)] }, void 0));
29
27
  }
30
28
  exports.TabsWithContent = TabsWithContent;
31
29
  function TabContent(props) {
@@ -44,6 +42,7 @@ function TabContent(props) {
44
42
  exports.TabContent = TabContent;
45
43
  /** The top list of tabs. */
46
44
  function Tabs(props) {
45
+ const { tabActionsRef, tabActionsDiv } = (0, BeamContext_1.useBeamContext)();
47
46
  const { ariaLabel, tabs, ...others } = props;
48
47
  const location = (0, react_router_1.useLocation)();
49
48
  const selected = isRouteTabs(props)
@@ -55,6 +54,11 @@ function Tabs(props) {
55
54
  const ref = (0, react_1.useRef)(null);
56
55
  // Whenever selected changes, reset active
57
56
  (0, react_1.useEffect)(() => setActive(selected), [selected]);
57
+ (0, react_1.useEffect)(() => {
58
+ if (tabActionsRef && tabActionsDiv) {
59
+ tabActionsRef.current.appendChild(tabActionsDiv);
60
+ }
61
+ }, [tabActionsRef, tabActionsDiv]);
58
62
  // the active tab is highlighted, but not necessarily "selected"
59
63
  // the selected tab dictates what is displayed in the content panel
60
64
  function onKeyUp(e) {
@@ -78,15 +82,16 @@ function Tabs(props) {
78
82
  setActive(selected);
79
83
  }
80
84
  }
81
- // We also check this in TabsWithContent, but if someone is using Tabs standalone, check it here as well
85
+ const actionsDiv = (0, jsx_runtime_1.jsx)("div", { css: Css_1.Css.ml("auto").addIn("&>div", Css_1.Css.df.aic.childGap1.$).$, ref: tabActionsRef }, void 0);
86
+ // Check to see if we should hide the tabs. We will still return something so that the Tab Actions (if any) can render
82
87
  const hideTabs = props.alwaysShowAllTabs ? false : props.tabs.filter((t) => !t.disabled).length === 1;
83
88
  if (hideTabs) {
84
- return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {}, void 0);
89
+ return (0, jsx_runtime_1.jsx)("div", Object.assign({ css: Css_1.Css.df.aic.$ }, { children: actionsDiv }), void 0);
85
90
  }
86
- return ((0, jsx_runtime_1.jsx)("div", Object.assign({ ref: ref, css: Css_1.Css.dif.childGap1.$, "aria-label": ariaLabel, role: "tablist" }, tid, { children: tabs.map((tab) => {
87
- const uniqueValue = uniqueTabValue(tab);
88
- return ((0, jsx_runtime_1.jsx)(TabImpl, Object.assign({ active: active === uniqueValue, focusProps: focusProps, isFocusVisible: isFocusVisible, onClick: onClick, onKeyUp: onKeyUp, onBlur: onBlur, tab: tab }, tid[(0, defaultTestId_1.defaultTestId)(uniqueValue)]), uniqueValue));
89
- }) }), void 0));
91
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ css: Css_1.Css.df.aic.$ }, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ ref: ref, css: Css_1.Css.dif.childGap1.$, "aria-label": ariaLabel, role: "tablist" }, tid, { children: tabs.map((tab) => {
92
+ const uniqueValue = uniqueTabValue(tab);
93
+ return ((0, jsx_runtime_1.jsx)(TabImpl, Object.assign({ active: active === uniqueValue, focusProps: focusProps, isFocusVisible: isFocusVisible, onClick: onClick, onKeyUp: onKeyUp, onBlur: onBlur, tab: tab }, tid[(0, defaultTestId_1.defaultTestId)(uniqueValue)]), uniqueValue));
94
+ }) }), void 0), actionsDiv] }), void 0));
90
95
  }
91
96
  exports.Tabs = Tabs;
92
97
  function TabImpl(props) {
@@ -149,3 +154,11 @@ function isRouteTab(tab) {
149
154
  function uniqueTabValue(tab) {
150
155
  return isRouteTab(tab) ? (0, change_case_1.camelCase)(tab.name) : tab.value;
151
156
  }
157
+ function TabActions({ children }) {
158
+ const { tabActionsDiv } = (0, BeamContext_1.useBeamContext)();
159
+ if (!tabActionsDiv) {
160
+ throw new Error("Tab Actions element is not defined");
161
+ }
162
+ return (0, react_dom_1.createPortal)(children, tabActionsDiv);
163
+ }
164
+ exports.TabActions = TabActions;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/beam",
3
- "version": "2.75.1",
3
+ "version": "2.76.3",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -33,7 +33,9 @@
33
33
  "format": "prettier --loglevel warn --write \"**/*.{ts,tsx,css,md}\""
34
34
  },
35
35
  "dependencies": {
36
+ "@react-aria/utils": "^3.8.1",
36
37
  "@react-hook/resize-observer": "^1.2.2",
38
+ "@types/tinycolor2": "^1.4.2",
37
39
  "change-case": "^4.1.2",
38
40
  "date-fns": "^2.21.3",
39
41
  "dompurify": "^2.3.0",
@@ -46,6 +48,7 @@
46
48
  "react-router-dom": "^5.2.0",
47
49
  "react-stately": "^3.7.0",
48
50
  "react-virtuoso": "^1.9.0",
51
+ "tinycolor2": "^1.4.2",
49
52
  "tributejs": "^5.1.3",
50
53
  "trix": "^1.3.1",
51
54
  "use-query-params": "^1.2.2"
@@ -54,8 +57,7 @@
54
57
  "@emotion/react": ">=11",
55
58
  "mobx-react": ">=7",
56
59
  "react": ">=16",
57
- "react-router-dom": ">=5.2",
58
- "tinycolor2": ">=1.4"
60
+ "react-router-dom": ">=5.2"
59
61
  },
60
62
  "peerDependenciesMeta": {
61
63
  "mobx-react": {
@@ -63,9 +65,6 @@
63
65
  },
64
66
  "react-router-dom": {
65
67
  "optional": false
66
- },
67
- "tinycolor2": {
68
- "optional": true
69
68
  }
70
69
  },
71
70
  "devDependencies": {
@@ -92,7 +91,6 @@
92
91
  "@types/react": "^17.0.5",
93
92
  "@types/react-dom": "^16.9.11",
94
93
  "@types/react-router-dom": "^5.1.7",
95
- "@types/tinycolor2": "^1.4.2",
96
94
  "@typescript-eslint/eslint-plugin": "^4.17.0",
97
95
  "@typescript-eslint/parser": "^4.17.0",
98
96
  "babel-eslint": "^10.1.0",