@viasat/beam-react 2.10.2 → 2.11.0

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.
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),d=require("clsx"),m=require("../../../chunks/classNames.DAeKwerT.js");require("../../../chunks/constants.hwjHOsvT.js");const _=require("../../CloseButton/CloseButton.cjs.js"),b=require("./Panel.context.cjs.js"),l=require("../../../chunks/panel.module.BX1x4FlX.js"),{subElementClassPrefix:x}=m.getBEMClassNames("panel"),t=`${x}header`,o=({children:a,className:n,...r})=>{const{dismissible:i,closeButtonAriaLabel:c,onOpenChange:e}=b.usePanelContext(),u=d(l.styles[`${t}__row`],n);return s.jsxs("div",{className:u,...r,children:[a,i&&s.jsx("div",{className:l.styles[`${t}__close-button`],children:s.jsx(_.CloseButton,{"aria-label":c,onClick:()=>e==null?void 0:e(!1),size:"lg"})})]})};o.displayName="Panel.Header.Row";exports.Row=o;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),d=require("clsx"),m=require("../../../chunks/classNames.DAeKwerT.js");require("../../../chunks/constants.hwjHOsvT.js");const _=require("../../CloseButton/CloseButton.cjs.js"),b=require("./Panel.context.cjs.js"),s=require("../../../chunks/panel.module.BX1x4FlX.js"),{subElementClassPrefix:C}=m.getBEMClassNames("panel"),t=`${C}header`,l=({children:o,className:n,...a})=>{const{dismissible:r,closeButtonAriaLabel:i,requestClose:c}=b.usePanelContext(),u=d(s.styles[`${t}__row`],n);return e.jsxs("div",{className:u,...a,children:[o,r&&e.jsx("div",{className:s.styles[`${t}__close-button`],children:e.jsx(_.CloseButton,{"aria-label":i,onClick:()=>c("closeButton"),size:"lg"})})]})};l.displayName="Panel.Header.Row";exports.Row=l;
@@ -1,29 +1,29 @@
1
- import { jsxs as n, jsx as e } from "react/jsx-runtime";
1
+ import { jsxs as c, jsx as s } from "react/jsx-runtime";
2
2
  import p from "clsx";
3
3
  import { g as d } from "../../../chunks/classNames.BTJmrO_L.js";
4
4
  import "../../../chunks/constants.CKKGf1-i.js";
5
- import { CloseButton as f } from "../../CloseButton/CloseButton.es.js";
6
- import { usePanelContext as b } from "./Panel.context.es.js";
7
- import { s as o } from "../../../chunks/panel.module.BVm3KvDs.js";
8
- const { subElementClassPrefix: u } = d("panel"), a = `${u}header`, x = ({
9
- children: l,
10
- className: t,
11
- ...r
5
+ import { CloseButton as u } from "../../CloseButton/CloseButton.es.js";
6
+ import { usePanelContext as f } from "./Panel.context.es.js";
7
+ import { s as e } from "../../../chunks/panel.module.BVm3KvDs.js";
8
+ const { subElementClassPrefix: C } = d("panel"), o = `${C}header`, b = ({
9
+ children: t,
10
+ className: l,
11
+ ...a
12
12
  }) => {
13
- const { dismissible: i, closeButtonAriaLabel: m, onOpenChange: s } = b(), c = p(o[`${a}__row`], t);
14
- return /* @__PURE__ */ n("div", { className: c, ...r, children: [
15
- l,
16
- i && /* @__PURE__ */ e("div", { className: o[`${a}__close-button`], children: /* @__PURE__ */ e(
17
- f,
13
+ const { dismissible: r, closeButtonAriaLabel: i, requestClose: m } = f(), n = p(e[`${o}__row`], l);
14
+ return /* @__PURE__ */ c("div", { className: n, ...a, children: [
15
+ t,
16
+ r && /* @__PURE__ */ s("div", { className: e[`${o}__close-button`], children: /* @__PURE__ */ s(
17
+ u,
18
18
  {
19
- "aria-label": m,
20
- onClick: () => s == null ? void 0 : s(!1),
19
+ "aria-label": i,
20
+ onClick: () => m("closeButton"),
21
21
  size: "lg"
22
22
  }
23
23
  ) })
24
24
  ] });
25
25
  };
26
- x.displayName = "Panel.Header.Row";
26
+ b.displayName = "Panel.Header.Row";
27
27
  export {
28
- x as Row
28
+ b as Row
29
29
  };
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),u=require("clsx"),S=require("../../../chunks/classNames.DAeKwerT.js");require("../../../chunks/constants.hwjHOsvT.js");const $=require("./Panel.context.cjs.js"),R=require("./Panel.Header.cjs.js"),U=require("./Panel.Body.cjs.js"),B=require("./Panel.Footer.cjs.js"),r=require("./Panel.helpers.cjs.js"),T=require("../../FloatingUI/FloatingUI.root.cjs.js"),A=require("../../FloatingUI/FloatingUI.content.cjs.js"),H=require("../../Divider/Divider.cjs.js"),s=require("../../../chunks/panel.module.BX1x4FlX.js"),{baseClassNamePrefix:t}=S.getBEMClassNames("panel"),a=({position:l,className:d})=>e.jsx(H.Divider,{borderColor:"01",orientation:l==="bottom"?"horizontal":"vertical",className:d}),n=({children:l,className:d,padding:q="md",onOpenChange:v,open:p,size:c,dismissible:g=!0,closeButtonAriaLabel:I="Close panel",kind:o="inline",position:P,divider:f=!0,isAnimated:y=!0,...x})=>{const i=r.getResolvedPanelPosition(P),m=u(s.styles[t],s.styles[`${t}--${o}`],c&&s.styles[`${t}--size-${c}`],s.styles[`${t}--padding-${q}`],s.styles[`${t}--position-${i}`],d),w=u(s.styles[`${t}__inline-wrapper`],c==="full"&&s.styles[`${t}__inline-wrapper--full`]),b={dismissible:g,closeButtonAriaLabel:I,onOpenChange:v,position:P},{inlineStatus:C,isInlineVisible:N}=r.useInlineTransition(o==="inline"?p:void 0,y),{showDivider:j,dividerBefore:D,dividerAfter:F}=r.getPanelDividerState(f,i),h=o==="overlay"?u(s.styles[`${t}__overlay-divider`],s.styles[`${t}__overlay-divider--${i}`]):void 0,_=j&&N;return o==="inline"?N?e.jsxs($.PanelContext.Provider,{value:b,children:[D&&_&&e.jsx(a,{position:i}),e.jsx("div",{className:w,"data-position":i,"data-status":C,children:e.jsxs("div",{className:s.styles[`${t}__inline-wrapper-content`],children:[i==="bottom"&&_&&e.jsx(a,{position:i}),e.jsx("aside",{className:m,...x,children:l})]})}),F&&_&&e.jsx(a,{position:i})]}):null:e.jsx($.PanelContext.Provider,{value:b,children:e.jsx(T.FloatingUIRoot,{open:p,onOpenChange:v,portalled:!0,transitionConfig:{duration:y?r.PANEL_TRANSITION_DURATION_MS:0},children:e.jsxs(A.Content,{className:m,skipFloatingStyles:!0,overlay:!0,...x,"data-position":i,children:[l,j&&e.jsx(a,{position:i,className:h})]})})})};n.displayName="Panel";n.Header=R.Header;n.Body=U.Body;n.Footer=B.Footer;exports.Panel=n;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),u=require("clsx"),U=require("../../../chunks/classNames.DAeKwerT.js");require("../../../chunks/constants.hwjHOsvT.js");const N=require("./Panel.context.cjs.js"),B=require("./Panel.Header.cjs.js"),T=require("./Panel.Body.cjs.js"),A=require("./Panel.Footer.cjs.js"),t=require("./Panel.helpers.cjs.js"),H=require("../../FloatingUI/FloatingUI.root.cjs.js"),M=require("../../FloatingUI/FloatingUI.content.cjs.js"),E=require("../../Divider/Divider.cjs.js"),n=require("../../../chunks/panel.module.BX1x4FlX.js"),{baseClassNamePrefix:s}=U.getBEMClassNames("panel"),a=({position:o,className:d})=>e.jsx(E.Divider,{borderColor:"01",orientation:o==="bottom"?"horizontal":"vertical",className:d}),l=({children:o,className:d,padding:j="md",onOpenChange:q,open:v,size:c,dismissible:C=!0,closeButtonAriaLabel:$="Close panel",kind:r="inline",position:p,divider:h=!0,isAnimated:P=!0,onBeforeClose:I,...y})=>{const i=t.getResolvedPanelPosition(p),x=u(n.styles[s],n.styles[`${s}--${r}`],c&&n.styles[`${s}--size-${c}`],n.styles[`${s}--padding-${j}`],n.styles[`${s}--position-${i}`],d),f=u(n.styles[`${s}__inline-wrapper`],c==="full"&&n.styles[`${s}__inline-wrapper--full`]),{requestClose:w,handleOverlayOpenChange:D}=t.usePanelClose(I,q),m={dismissible:C,closeButtonAriaLabel:$,position:p,requestClose:w},{inlineStatus:F,isInlineVisible:b}=t.useInlineTransition(r==="inline"?v:void 0,P),{showDivider:g,dividerBefore:S,dividerAfter:O}=t.getPanelDividerState(h,i),R=r==="overlay"?u(n.styles[`${s}__overlay-divider`],n.styles[`${s}__overlay-divider--${i}`]):void 0,_=g&&b;return r==="inline"?b?e.jsxs(N.PanelContext.Provider,{value:m,children:[S&&_&&e.jsx(a,{position:i}),e.jsx("div",{className:f,"data-position":i,"data-status":F,children:e.jsxs("div",{className:n.styles[`${s}__inline-wrapper-content`],children:[i==="bottom"&&_&&e.jsx(a,{position:i}),e.jsx("aside",{className:x,...y,children:o})]})}),O&&_&&e.jsx(a,{position:i})]}):null:e.jsx(N.PanelContext.Provider,{value:m,children:e.jsx(H.FloatingUIRoot,{open:v,onOpenChange:D,portalled:!0,transitionConfig:{duration:P?t.PANEL_TRANSITION_DURATION_MS:0},children:e.jsxs(M.Content,{className:x,skipFloatingStyles:!0,overlay:!0,...y,"data-position":i,children:[o,g&&e.jsx(a,{position:i,className:R})]})})})};l.displayName="Panel";l.Header=B.Header;l.Body=T.Body;l.Footer=A.Footer;exports.Panel=l;
@@ -1,4 +1,4 @@
1
- import { PanelPosition } from './Panel.types';
1
+ import { PanelCloseReason, PanelPosition } from './Panel.types';
2
2
  export interface PanelContextValue {
3
3
  /**
4
4
  * Whether to show a dismissible button
@@ -8,14 +8,15 @@ export interface PanelContextValue {
8
8
  * Aria label for the dismissible button
9
9
  */
10
10
  closeButtonAriaLabel?: string;
11
- /**
12
- * Callback when panel open state changes
13
- */
14
- onOpenChange?: (open: boolean) => void;
15
11
  /**
16
12
  * Panel position (determines divider placement)
17
13
  */
18
14
  position?: PanelPosition;
15
+ /**
16
+ * Request the panel to close for the given reason. Runs `onBeforeClose` if
17
+ * provided and only calls `onOpenChange(false)` when the guard returns `true`.
18
+ */
19
+ requestClose: (reason: PanelCloseReason) => void;
19
20
  }
20
21
  export declare const PanelContext: import('react').Context<PanelContextValue | undefined>;
21
22
  export declare const usePanelContext: () => PanelContextValue;
@@ -1,6 +1,6 @@
1
1
  import { PanelProps } from './Panel.types';
2
2
  export declare const Panel: {
3
- ({ children, className: _className, padding, onOpenChange, open, size, dismissible, closeButtonAriaLabel, kind, position, divider, isAnimated, ...props }: PanelProps): JSX.Element | null;
3
+ ({ children, className: _className, padding, onOpenChange, open, size, dismissible, closeButtonAriaLabel, kind, position, divider, isAnimated, onBeforeClose, ...props }: PanelProps): JSX.Element | null;
4
4
  displayName: string;
5
5
  Header: {
6
6
  ({ children, className: _className, divider, ...props }: import('./Panel.Header').PanelHeaderProps): import("react/jsx-runtime").JSX.Element;
@@ -1,105 +1,106 @@
1
1
  import { jsxs as p, jsx as r } from "react/jsx-runtime";
2
2
  import v from "clsx";
3
- import { g as F } from "../../../chunks/classNames.BTJmrO_L.js";
3
+ import { g as A } from "../../../chunks/classNames.BTJmrO_L.js";
4
4
  import "../../../chunks/constants.CKKGf1-i.js";
5
- import { PanelContext as I } from "./Panel.context.es.js";
6
- import { Header as T } from "./Panel.Header.es.js";
7
- import { Body as A } from "./Panel.Body.es.js";
8
- import { Footer as j } from "./Panel.Footer.es.js";
9
- import { useInlineTransition as E, getPanelDividerState as H, PANEL_TRANSITION_DURATION_MS as M, getResolvedPanelPosition as U } from "./Panel.helpers.es.js";
10
- import { FloatingUIRoot as V } from "../../FloatingUI/FloatingUI.root.es.js";
11
- import { Content as L } from "../../FloatingUI/FloatingUI.content.es.js";
12
- import { Divider as O } from "../../Divider/Divider.es.js";
13
- import { s as i } from "../../../chunks/panel.module.BVm3KvDs.js";
14
- const { baseClassNamePrefix: o } = F("panel"), l = ({
5
+ import { PanelContext as h } from "./Panel.context.es.js";
6
+ import { Header as j } from "./Panel.Header.es.js";
7
+ import { Body as E } from "./Panel.Body.es.js";
8
+ import { Footer as H } from "./Panel.Footer.es.js";
9
+ import { usePanelClose as M, useInlineTransition as U, getPanelDividerState as V, PANEL_TRANSITION_DURATION_MS as q, getResolvedPanelPosition as L } from "./Panel.helpers.es.js";
10
+ import { FloatingUIRoot as W } from "../../FloatingUI/FloatingUI.root.es.js";
11
+ import { Content as z } from "../../FloatingUI/FloatingUI.content.es.js";
12
+ import { Divider as G } from "../../Divider/Divider.es.js";
13
+ import { s as o } from "../../../chunks/panel.module.BVm3KvDs.js";
14
+ const { baseClassNamePrefix: i } = A("panel"), a = ({
15
15
  position: t,
16
- className: a
16
+ className: s
17
17
  }) => /* @__PURE__ */ r(
18
- O,
18
+ G,
19
19
  {
20
20
  borderColor: "01",
21
21
  orientation: t === "bottom" ? "horizontal" : "vertical",
22
- className: a
22
+ className: s
23
23
  }
24
- ), s = ({
24
+ ), l = ({
25
25
  children: t,
26
- className: a,
27
- padding: g = "md",
28
- onOpenChange: c,
29
- open: f,
26
+ className: s,
27
+ padding: y = "md",
28
+ onOpenChange: g,
29
+ open: c,
30
30
  size: d,
31
- dismissible: h = !0,
31
+ dismissible: I = !0,
32
32
  closeButtonAriaLabel: x = "Close panel",
33
33
  kind: n = "inline",
34
34
  position: u,
35
35
  divider: D = !0,
36
- isAnimated: N = !0,
37
- ...$
36
+ isAnimated: f = !0,
37
+ onBeforeClose: b,
38
+ ...N
38
39
  }) => {
39
- const e = U(u), _ = v(
40
- i[o],
41
- i[`${o}--${n}`],
42
- d && i[`${o}--size-${d}`],
43
- i[`${o}--padding-${g}`],
44
- i[`${o}--position-${e}`],
45
- a
46
- ), b = v(
47
- i[`${o}__inline-wrapper`],
48
- d === "full" && i[`${o}__inline-wrapper--full`]
49
- ), P = {
50
- dismissible: h,
40
+ const e = L(u), $ = v(
41
+ o[i],
42
+ o[`${i}--${n}`],
43
+ d && o[`${i}--size-${d}`],
44
+ o[`${i}--padding-${y}`],
45
+ o[`${i}--position-${e}`],
46
+ s
47
+ ), O = v(
48
+ o[`${i}__inline-wrapper`],
49
+ d === "full" && o[`${i}__inline-wrapper--full`]
50
+ ), { requestClose: R, handleOverlayOpenChange: S } = M(b, g), C = {
51
+ dismissible: I,
51
52
  closeButtonAriaLabel: x,
52
- onOpenChange: c,
53
- position: u
54
- }, { inlineStatus: R, isInlineVisible: y } = E(
55
- n === "inline" ? f : void 0,
56
- N
57
- ), { showDivider: C, dividerBefore: S, dividerAfter: w } = H(
53
+ position: u,
54
+ requestClose: R
55
+ }, { inlineStatus: w, isInlineVisible: _ } = U(
56
+ n === "inline" ? c : void 0,
57
+ f
58
+ ), { showDivider: P, dividerBefore: B, dividerAfter: F } = V(
58
59
  D,
59
60
  e
60
- ), B = n === "overlay" ? v(
61
- i[`${o}__overlay-divider`],
62
- i[`${o}__overlay-divider--${e}`]
63
- ) : void 0, m = C && y;
64
- return n === "inline" ? y ? /* @__PURE__ */ p(I.Provider, { value: P, children: [
65
- S && m && /* @__PURE__ */ r(l, { position: e }),
61
+ ), T = n === "overlay" ? v(
62
+ o[`${i}__overlay-divider`],
63
+ o[`${i}__overlay-divider--${e}`]
64
+ ) : void 0, m = P && _;
65
+ return n === "inline" ? _ ? /* @__PURE__ */ p(h.Provider, { value: C, children: [
66
+ B && m && /* @__PURE__ */ r(a, { position: e }),
66
67
  /* @__PURE__ */ r(
67
68
  "div",
68
69
  {
69
- className: b,
70
+ className: O,
70
71
  "data-position": e,
71
- "data-status": R,
72
- children: /* @__PURE__ */ p("div", { className: i[`${o}__inline-wrapper-content`], children: [
73
- e === "bottom" && m && /* @__PURE__ */ r(l, { position: e }),
74
- /* @__PURE__ */ r("aside", { className: _, ...$, children: t })
72
+ "data-status": w,
73
+ children: /* @__PURE__ */ p("div", { className: o[`${i}__inline-wrapper-content`], children: [
74
+ e === "bottom" && m && /* @__PURE__ */ r(a, { position: e }),
75
+ /* @__PURE__ */ r("aside", { className: $, ...N, children: t })
75
76
  ] })
76
77
  }
77
78
  ),
78
- w && m && /* @__PURE__ */ r(l, { position: e })
79
- ] }) : null : /* @__PURE__ */ r(I.Provider, { value: P, children: /* @__PURE__ */ r(
80
- V,
79
+ F && m && /* @__PURE__ */ r(a, { position: e })
80
+ ] }) : null : /* @__PURE__ */ r(h.Provider, { value: C, children: /* @__PURE__ */ r(
81
+ W,
81
82
  {
82
- open: f,
83
- onOpenChange: c,
83
+ open: c,
84
+ onOpenChange: S,
84
85
  portalled: !0,
85
86
  transitionConfig: {
86
- duration: N ? M : 0
87
+ duration: f ? q : 0
87
88
  },
88
89
  children: /* @__PURE__ */ p(
89
- L,
90
+ z,
90
91
  {
91
- className: _,
92
+ className: $,
92
93
  skipFloatingStyles: !0,
93
94
  overlay: !0,
94
- ...$,
95
+ ...N,
95
96
  "data-position": e,
96
97
  children: [
97
98
  t,
98
- C && /* @__PURE__ */ r(
99
- l,
99
+ P && /* @__PURE__ */ r(
100
+ a,
100
101
  {
101
102
  position: e,
102
- className: B
103
+ className: T
103
104
  }
104
105
  )
105
106
  ]
@@ -108,10 +109,10 @@ const { baseClassNamePrefix: o } = F("panel"), l = ({
108
109
  }
109
110
  ) });
110
111
  };
111
- s.displayName = "Panel";
112
- s.Header = T;
113
- s.Body = A;
114
- s.Footer = j;
112
+ l.displayName = "Panel";
113
+ l.Header = j;
114
+ l.Body = E;
115
+ l.Footer = H;
115
116
  export {
116
- s as Panel
117
+ l as Panel
117
118
  };
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react"),o=400,c=e=>e||"end",d=(e,t)=>{const n=e&&t!=="full";return{showDivider:n,dividerBefore:n&&t!=="start"&&t!=="bottom",dividerAfter:n&&t==="start"}},I=(e,t)=>{const[n,i]=a.useState(void 0),[l,s]=a.useState(e!==!1);return a.useEffect(()=>{if(!t){s(e!==!1),i(void 0);return}if(e!==void 0)if(e){s(!0),i("close");let r;const u=requestAnimationFrame(()=>{r=requestAnimationFrame(()=>i("open"))});return()=>{cancelAnimationFrame(u),cancelAnimationFrame(r)}}else{i("close");const r=setTimeout(()=>{s(!1),i(void 0)},o);return()=>clearTimeout(r)}},[t,e]),{inlineStatus:n,isInlineVisible:l}};exports.PANEL_TRANSITION_DURATION_MS=o;exports.getPanelDividerState=d;exports.getResolvedPanelPosition=c;exports.useInlineTransition=I;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("react"),a=400,f=e=>e||"end",o=(e,t)=>{const s=e&&t!=="full";return{showDivider:s,dividerBefore:s&&t!=="start"&&t!=="bottom",dividerAfter:s&&t==="start"}},m=e=>e==="escape-key"?"escapeKey":e==="outside-press"?"outsidePress":"programmatic",v=(e,t)=>{const s=c.useCallback(u=>{if(!e){t==null||t(!1);return}const r=e(u);r instanceof Promise?r.then(i=>{i&&(t==null||t(!1))}).catch(()=>{}):r&&(t==null||t(!1))},[e,t]),l=c.useCallback((u,r,i)=>{u?t==null||t(!0):s(m(i))},[t,s]);return{requestClose:s,handleOverlayOpenChange:l}},I=(e,t)=>{const[s,l]=c.useState(void 0),[u,r]=c.useState(e!==!1);return c.useEffect(()=>{if(!t){r(e!==!1),l(void 0);return}if(e!==void 0)if(e){r(!0),l("close");let i;const d=requestAnimationFrame(()=>{i=requestAnimationFrame(()=>l("open"))});return()=>{cancelAnimationFrame(d),cancelAnimationFrame(i)}}else{l("close");const i=setTimeout(()=>{r(!1),l(void 0)},a);return()=>clearTimeout(i)}},[t,e]),{inlineStatus:s,isInlineVisible:u}};exports.PANEL_TRANSITION_DURATION_MS=a;exports.getPanelDividerState=o;exports.getResolvedPanelPosition=f;exports.useInlineTransition=I;exports.usePanelClose=v;
@@ -1,4 +1,5 @@
1
- import { PanelPosition } from './Panel.types';
1
+ import { OpenChangeReason } from '@floating-ui/react';
2
+ import { PanelCloseReason, PanelPosition, PanelProps } from './Panel.types';
2
3
  export declare const PANEL_TRANSITION_DURATION_MS = 400;
3
4
  export type PanelInlineStatus = 'open' | 'close' | undefined;
4
5
  export declare const getResolvedPanelPosition: (position?: PanelPosition) => PanelPosition;
@@ -7,6 +8,10 @@ export declare const getPanelDividerState: (divider: boolean, position?: PanelPo
7
8
  dividerBefore: boolean;
8
9
  dividerAfter: boolean;
9
10
  };
11
+ export declare const usePanelClose: (onBeforeClose: PanelProps["onBeforeClose"], onOpenChange: PanelProps["onOpenChange"]) => {
12
+ requestClose: (reason: PanelCloseReason) => void;
13
+ handleOverlayOpenChange: (nextOpen: boolean, _event?: Event, floatingReason?: OpenChangeReason) => void;
14
+ };
10
15
  export declare const useInlineTransition: (open: boolean | undefined, isAnimated: boolean) => {
11
16
  inlineStatus: PanelInlineStatus;
12
17
  isInlineVisible: boolean;
@@ -1,40 +1,62 @@
1
- import { useState as o, useEffect as u } from "react";
2
- const c = 400, m = (e) => e || "end", f = (e, t) => {
3
- const n = e && t !== "full";
1
+ import { useState as c, useEffect as m, useCallback as f } from "react";
2
+ const a = 400, I = (s) => s || "end", A = (s, t) => {
3
+ const r = s && t !== "full";
4
4
  return {
5
- showDivider: n,
6
- dividerBefore: n && t !== "start" && t !== "bottom",
7
- dividerAfter: n && t === "start"
5
+ showDivider: r,
6
+ dividerBefore: r && t !== "start" && t !== "bottom",
7
+ dividerAfter: r && t === "start"
8
8
  };
9
- }, I = (e, t) => {
10
- const [n, i] = o(void 0), [a, s] = o(e !== !1);
11
- return u(() => {
9
+ }, v = (s) => s === "escape-key" ? "escapeKey" : s === "outside-press" ? "outsidePress" : "programmatic", P = (s, t) => {
10
+ const r = f(
11
+ (u) => {
12
+ if (!s) {
13
+ t == null || t(!1);
14
+ return;
15
+ }
16
+ const e = s(u);
17
+ e instanceof Promise ? e.then((i) => {
18
+ i && (t == null || t(!1));
19
+ }).catch(() => {
20
+ }) : e && (t == null || t(!1));
21
+ },
22
+ [s, t]
23
+ ), l = f(
24
+ (u, e, i) => {
25
+ u ? t == null || t(!0) : r(v(i));
26
+ },
27
+ [t, r]
28
+ );
29
+ return { requestClose: r, handleOverlayOpenChange: l };
30
+ }, S = (s, t) => {
31
+ const [r, l] = c(void 0), [u, e] = c(s !== !1);
32
+ return m(() => {
12
33
  if (!t) {
13
- s(e !== !1), i(void 0);
34
+ e(s !== !1), l(void 0);
14
35
  return;
15
36
  }
16
- if (e !== void 0)
17
- if (e) {
18
- s(!0), i("close");
19
- let r;
20
- const l = requestAnimationFrame(() => {
21
- r = requestAnimationFrame(() => i("open"));
37
+ if (s !== void 0)
38
+ if (s) {
39
+ e(!0), l("close");
40
+ let i;
41
+ const d = requestAnimationFrame(() => {
42
+ i = requestAnimationFrame(() => l("open"));
22
43
  });
23
44
  return () => {
24
- cancelAnimationFrame(l), cancelAnimationFrame(r);
45
+ cancelAnimationFrame(d), cancelAnimationFrame(i);
25
46
  };
26
47
  } else {
27
- i("close");
28
- const r = setTimeout(() => {
29
- s(!1), i(void 0);
30
- }, c);
31
- return () => clearTimeout(r);
48
+ l("close");
49
+ const i = setTimeout(() => {
50
+ e(!1), l(void 0);
51
+ }, a);
52
+ return () => clearTimeout(i);
32
53
  }
33
- }, [t, e]), { inlineStatus: n, isInlineVisible: a };
54
+ }, [t, s]), { inlineStatus: r, isInlineVisible: u };
34
55
  };
35
56
  export {
36
- c as PANEL_TRANSITION_DURATION_MS,
37
- f as getPanelDividerState,
38
- m as getResolvedPanelPosition,
39
- I as useInlineTransition
57
+ a as PANEL_TRANSITION_DURATION_MS,
58
+ A as getPanelDividerState,
59
+ I as getResolvedPanelPosition,
60
+ S as useInlineTransition,
61
+ P as usePanelClose
40
62
  };
@@ -4,6 +4,15 @@ export type PanelPosition = 'start' | 'end' | 'bottom' | 'full';
4
4
  export type PanelModalType = 'nonModal' | 'isModal' | 'alert';
5
5
  export type PanelSize = 'sm' | 'md' | 'lg' | 'full' | 'custom';
6
6
  export type PanelPadding = 'sm' | 'md';
7
+ /**
8
+ * The reason a Panel close was requested via user interaction.
9
+ *
10
+ * - `'escapeKey'` — user pressed Escape (overlay panels only)
11
+ * - `'outsidePress'` — user clicked outside the panel (overlay panels only)
12
+ * - `'closeButton'` — user clicked the header close button
13
+ * - `'programmatic'` — close was triggered by another interaction not covered above
14
+ */
15
+ export type PanelCloseReason = 'escapeKey' | 'outsidePress' | 'closeButton' | 'programmatic';
7
16
  interface BasePanelProps extends ComponentPropsWithoutRef<'aside'> {
8
17
  /**
9
18
  * Specify the content of the Panel
@@ -54,6 +63,31 @@ interface BasePanelProps extends ComponentPropsWithoutRef<'aside'> {
54
63
  * @default 'end'
55
64
  */
56
65
  position?: PanelPosition;
66
+ /**
67
+ * Called before the Panel closes due to a user interaction. Return `false` (or
68
+ * `Promise<false>`) to cancel the close — for example, when the panel contains
69
+ * a form with unsaved changes.
70
+ *
71
+ * This callback is **not** invoked when the `open` prop is changed programmatically
72
+ * by the parent; it only fires for UI-triggered close events (close button, Escape
73
+ * key, or outside press).
74
+ *
75
+ * @example
76
+ * ```tsx
77
+ * // Use a stateful confirmation dialog — avoid window.confirm (blocking, breaks iframes).
78
+ * // See the `onBeforeClose (Unsaved Changes Guard)` story for a full reference implementation.
79
+ * <Panel
80
+ * onBeforeClose={(reason) => {
81
+ * if (!isDirty) return true;
82
+ * return new Promise(resolve => {
83
+ * setResolveClose(() => resolve);
84
+ * setShowConfirmDialog(true);
85
+ * });
86
+ * }}
87
+ * />
88
+ * ```
89
+ */
90
+ onBeforeClose?: (reason: PanelCloseReason) => boolean | Promise<boolean>;
57
91
  }
58
92
  export interface InlinePanelProps extends BasePanelProps {
59
93
  /**
@@ -1,5 +1,5 @@
1
1
  export { Panel } from './Panel';
2
- export type { PanelProps, InlinePanelProps, OverlayPanelProps, PanelKind, PanelPosition, PanelModalType, PanelSize, PanelPadding, } from './Panel.types';
2
+ export type { PanelProps, InlinePanelProps, OverlayPanelProps, PanelKind, PanelPosition, PanelModalType, PanelSize, PanelPadding, PanelCloseReason, } from './Panel.types';
3
3
  export type { PanelHeaderProps } from './Panel.Header';
4
4
  export type { PanelHeaderRowProps } from './Panel.Header.Row';
5
5
  export type { PanelHeaderContentBeforeProps } from './Panel.Header.ContentBefore';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viasat/beam-react",
3
- "version": "2.10.2",
3
+ "version": "2.11.0",
4
4
  "description": "React component library for the Beam design system",
5
5
  "license": "MIT",
6
6
  "author": "Viasat",
@@ -59,11 +59,11 @@
59
59
  "access": "public"
60
60
  },
61
61
  "dependencies": {
62
- "@viasat/beam-fonts": "2.10.2",
63
- "@viasat/beam-shared": "2.10.2",
64
- "@viasat/beam-styles": "2.10.2",
65
- "@viasat/beam-tokens": "2.10.2",
66
- "@viasat/beam-icons": "2.10.2",
62
+ "@viasat/beam-fonts": "2.11.0",
63
+ "@viasat/beam-shared": "2.11.0",
64
+ "@viasat/beam-styles": "2.11.0",
65
+ "@viasat/beam-tokens": "2.11.0",
66
+ "@viasat/beam-icons": "2.11.0",
67
67
  "clsx": "^1.2.1",
68
68
  "@floating-ui/react": "^0.26.18",
69
69
  "@stepperize/react": "^5.1.5",