@mattermost/compass-ui 0.1.0-alpha.3 → 0.1.0-alpha.4
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/dist/components/admin-panel/AdminPanel.d.ts +1 -1
- package/dist/components/channels-sidebar/channelsSidebarModel.d.ts +1 -1
- package/dist/components/empty-state/EmptyState.d.ts +2 -2
- package/dist/components/feature-discovery-panel/FeatureDiscoveryPanel.d.ts +2 -2
- package/dist/components/message/Message.d.ts +1 -1
- package/dist/components/modal/Modal.cjs +1 -1
- package/dist/components/modal/Modal.cjs.map +1 -1
- package/dist/components/modal/Modal.d.ts +9 -1
- package/dist/components/modal/Modal.d.ts.map +1 -1
- package/dist/components/modal/Modal.js +30 -20
- package/dist/components/modal/Modal.js.map +1 -1
- package/dist/components/modal/Modal.module.css +1 -1
- package/dist/components/modal/Modal.module.scss.cjs +1 -1
- package/dist/components/modal/Modal.module.scss.js +18 -17
- package/dist/components/modal/Modal.module.scss.js.map +1 -1
- package/dist/components/modal/index.d.ts +1 -1
- package/dist/components/modal/index.d.ts.map +1 -1
- package/dist/components/right-sidebar/RightSidebarHeader/RightSidebarHeader.d.ts +1 -1
- package/dist/components/thread-list-item/ThreadListItem.d.ts +1 -1
- package/dist/components/thread-list-item/index.d.ts +1 -1
- package/dist/hooks/use-anchored-popup-portal.cjs +1 -1
- package/dist/hooks/use-anchored-popup-portal.cjs.map +1 -0
- package/dist/hooks/use-anchored-popup-portal.d.ts +1 -1
- package/dist/hooks/use-anchored-popup-portal.d.ts.map +1 -0
- package/dist/hooks/use-anchored-popup-portal.js +1 -1
- package/dist/hooks/use-anchored-popup-portal.js.map +1 -0
- package/dist/hooks/use-controllable.cjs +1 -1
- package/dist/hooks/use-controllable.cjs.map +1 -0
- package/dist/hooks/use-controllable.d.ts +1 -1
- package/dist/hooks/use-controllable.d.ts.map +1 -0
- package/dist/hooks/use-controllable.js +1 -1
- package/dist/hooks/{useControllable.cjs.map → use-controllable.js.map} +1 -1
- package/dist/hooks/use-exit-animation.cjs +1 -1
- package/dist/hooks/use-exit-animation.cjs.map +1 -0
- package/dist/hooks/use-exit-animation.d.ts +1 -1
- package/dist/hooks/use-exit-animation.d.ts.map +1 -0
- package/dist/hooks/use-exit-animation.js +1 -1
- package/dist/hooks/use-exit-animation.js.map +1 -0
- package/dist/hooks/use-outside-close.cjs +1 -1
- package/dist/hooks/use-outside-close.cjs.map +1 -0
- package/dist/hooks/use-outside-close.d.ts +1 -1
- package/dist/hooks/use-outside-close.d.ts.map +1 -0
- package/dist/hooks/use-outside-close.js +1 -1
- package/dist/hooks/use-outside-close.js.map +1 -0
- package/dist/hooks/use-popover-transition.cjs +1 -1
- package/dist/hooks/use-popover-transition.cjs.map +1 -0
- package/dist/hooks/use-popover-transition.d.ts +1 -1
- package/dist/hooks/use-popover-transition.d.ts.map +1 -0
- package/dist/hooks/use-popover-transition.js +1 -1
- package/dist/hooks/use-popover-transition.js.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +96 -96
- package/package.json +12 -12
- package/dist/hooks/useAnchoredPopupPortal.cjs.map +0 -1
- package/dist/hooks/useAnchoredPopupPortal.d.ts.map +0 -1
- package/dist/hooks/useAnchoredPopupPortal.js.map +0 -1
- package/dist/hooks/useControllable.d.ts.map +0 -1
- package/dist/hooks/useControllable.js.map +0 -1
- package/dist/hooks/useExitAnimation.cjs.map +0 -1
- package/dist/hooks/useExitAnimation.d.ts.map +0 -1
- package/dist/hooks/useExitAnimation.js.map +0 -1
- package/dist/hooks/useOutsideClose.cjs.map +0 -1
- package/dist/hooks/useOutsideClose.d.ts.map +0 -1
- package/dist/hooks/useOutsideClose.js.map +0 -1
- package/dist/hooks/usePopoverTransition.cjs.map +0 -1
- package/dist/hooks/usePopoverTransition.d.ts.map +0 -1
- package/dist/hooks/usePopoverTransition.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ChangeEvent, ReactNode } from 'react';
|
|
2
|
-
import { AdminPanelExpandedState } from '../
|
|
2
|
+
import { AdminPanelExpandedState } from '../admin-panel-header/AdminPanelHeader';
|
|
3
3
|
export type { AdminPanelExpandedState };
|
|
4
4
|
export interface AdminPanelProps {
|
|
5
5
|
title: ReactNode;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChannelSidebarItemProps } from '../
|
|
1
|
+
import { ChannelSidebarItemProps } from '../channel-sidebar-item/ChannelSidebarItem';
|
|
2
2
|
export type ChannelsSidebarItemModel = Pick<ChannelSidebarItemProps, 'name' | 'leadingVisual' | 'active' | 'status' | 'mentionCount' | 'memberCount' | 'avatarSrc' | 'avatarAlt' | 'showAvatarStatus' | 'onClick'>;
|
|
3
3
|
export interface ChannelsSidebarCategoryModel {
|
|
4
4
|
label: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import { ButtonProps } from '../
|
|
3
|
-
import { IllustrationProps } from '../
|
|
2
|
+
import { ButtonProps } from '../button/Button';
|
|
3
|
+
import { IllustrationProps } from '../illustration/Illustration';
|
|
4
4
|
export interface EmptyStateProps {
|
|
5
5
|
/** Illustration props (children = the SVG component). Rendered above the title. */
|
|
6
6
|
illustration?: IllustrationProps;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ButtonProps } from '../
|
|
2
|
-
import { IllustrationProps } from '../
|
|
1
|
+
import { ButtonProps } from '../button/Button';
|
|
2
|
+
import { IllustrationProps } from '../illustration/Illustration';
|
|
3
3
|
export interface FeatureDiscoveryPanelProps {
|
|
4
4
|
/** SKU tag label (e.g. "PROFESSIONAL"). Set to null to hide. */
|
|
5
5
|
skuLabel?: string | null;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("react/jsx-runtime"),b=require("react"),s=require("../icon-button/IconButton.cjs"),i=require("../icon/Icon.cjs"),v=require("../scrollbar/Scrollbar.cjs"),__N=require("@mattermost/compass-icons/components/close.js"),N=__N?.default??__N,__q=require("@mattermost/compass-icons/components/arrow-left.js"),q=__q?.default??__q,y=require("../../utils/string.cjs"),l=require("./Modal.module.scss.cjs");function g({size:t="small",title:r,subtitle:a,showBackButton:n=!1,onBack:u,onClose:c,headerDivider:m=!0,bodyPadding:f="default",children:_,footer:o,footerDivider:j=!0}){const d=b.useId(),x=l.default[`modal--size-${y.toKebab(t)}`],h=f==="menu";return e.jsxs("div",{className:[l.default.modal,x].filter(Boolean).join(" "),role:"dialog","aria-modal":"true","aria-labelledby":d,children:[e.jsxs("div",{className:[l.default.modal__header,!m&&l.default["modal__header--no-divider"]].filter(Boolean).join(" "),children:[e.jsxs("div",{className:l.default["modal__header-inner"],children:[n&&e.jsx(s.default,{"aria-label":"Go back",icon:e.jsx(i.default,{glyph:e.jsx(q,{}),size:"20"}),onClick:u}),e.jsxs("div",{className:l.default["modal__title-group"],children:[e.jsx("h2",{id:d,className:l.default.modal__title,children:r}),a&&e.jsx("p",{className:l.default.modal__subtitle,children:a})]})]}),e.jsx(s.default,{"aria-label":"Close",className:l.default.modal__close,icon:e.jsx(i.default,{glyph:e.jsx(N,{}),size:"20"}),onClick:c})]}),e.jsx("div",{className:l.default.modal__body,children:e.jsx(v.default,{children:e.jsx("div",{className:[l.default["modal__body-inner"],h&&l.default["modal__body-inner--menu"]].filter(Boolean).join(" "),children:_})})}),o&&e.jsx("div",{className:[l.default.modal__footer,!j&&l.default["modal__footer--no-divider"]].filter(Boolean).join(" "),children:o})]})}exports.default=g;
|
|
2
2
|
//# sourceMappingURL=Modal.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.cjs","sources":["../../../src/components/modal/Modal.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { useId } from 'react';\nimport IconButton from '@/components/icon-button/IconButton';\nimport Icon from '@/components/icon/Icon';\nimport Scrollbar from '@/components/scrollbar/Scrollbar';\nimport CloseIcon from '@mattermost/compass-icons/components/close';\nimport ArrowLeftIcon from '@mattermost/compass-icons/components/arrow-left';\nimport { toKebab } from '@/utils/string';\nimport styles from './Modal.module.scss';\n\nexport type ModalSize = 'small' | 'medium' | 'large';\n\nexport interface ModalProps {\n /** Width variant. Figma: Size — Small 600px, Medium 704px, Large 832px. */\n size?: ModalSize;\n /** Modal heading text. Always visible. */\n title: ReactNode;\n /** Optional secondary line below the title. */\n subtitle?: ReactNode;\n /** When true, shows a back-arrow button before the title. */\n showBackButton?: boolean;\n /** Called when the back button is clicked. */\n onBack?: () => void;\n /** Called when the × close button is clicked. */\n onClose?: () => void;\n /** Show divider between header and body. Figma: Divider = On. Default: true. */\n headerDivider?: boolean;\n /** Body content. */\n children: ReactNode;\n /** Footer slot — typically a group of Buttons, right-aligned by default. */\n footer?: ReactNode;\n /** Show divider between body and footer. Figma: Divider = On. Default: true. */\n footerDivider?: boolean;\n}\n\nexport default function Modal({\n size = 'small',\n title,\n subtitle,\n showBackButton = false,\n onBack,\n onClose,\n headerDivider = true,\n children,\n footer,\n footerDivider = true,\n}: ModalProps) {\n const titleId = useId();\n const sizeClass = styles[`modal--size-${toKebab(size)}`];\n\n return (\n <div\n className={[styles.modal, sizeClass].filter(Boolean).join(' ')}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n >\n <div\n className={[\n styles['modal__header'],\n !headerDivider && styles['modal__header--no-divider'],\n ]\n .filter(Boolean)\n .join(' ')}\n >\n <div className={styles['modal__header-inner']}>\n {showBackButton && (\n <IconButton\n aria-label=\"Go back\"\n icon={<Icon glyph={<ArrowLeftIcon />} size=\"20\" />}\n onClick={onBack}\n />\n )}\n <div className={styles['modal__title-group']}>\n <h2 id={titleId} className={styles['modal__title']}>\n {title}\n </h2>\n {subtitle && (\n <p className={styles['modal__subtitle']}>{subtitle}</p>\n )}\n </div>\n </div>\n <IconButton\n aria-label=\"Close\"\n className={styles['modal__close']}\n icon={<Icon glyph={<CloseIcon />} size=\"20\" />}\n onClick={onClose}\n />\n </div>\n\n <div className={styles['modal__body']}>\n <Scrollbar>\n <div
|
|
1
|
+
{"version":3,"file":"Modal.cjs","sources":["../../../src/components/modal/Modal.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { useId } from 'react';\nimport IconButton from '@/components/icon-button/IconButton';\nimport Icon from '@/components/icon/Icon';\nimport Scrollbar from '@/components/scrollbar/Scrollbar';\nimport CloseIcon from '@mattermost/compass-icons/components/close';\nimport ArrowLeftIcon from '@mattermost/compass-icons/components/arrow-left';\nimport { toKebab } from '@/utils/string';\nimport styles from './Modal.module.scss';\n\nexport type ModalSize = 'small' | 'medium' | 'large';\n\n/** Body inset. `menu` is for MenuItem lists — 8px vertical / 16px horizontal so row labels align with the 32px header/footer margins. */\nexport type ModalBodyPadding = 'default' | 'menu';\n\nexport interface ModalProps {\n /** Width variant. Figma: Size — Small 600px, Medium 704px, Large 832px. */\n size?: ModalSize;\n /** Modal heading text. Always visible. */\n title: ReactNode;\n /** Optional secondary line below the title. */\n subtitle?: ReactNode;\n /** When true, shows a back-arrow button before the title. */\n showBackButton?: boolean;\n /** Called when the back button is clicked. */\n onBack?: () => void;\n /** Called when the × close button is clicked. */\n onClose?: () => void;\n /** Show divider between header and body. Figma: Divider = On. Default: true. */\n headerDivider?: boolean;\n /**\n * Body inset. Default is 32px horizontal / 28px vertical. Use `menu` for\n * MenuItem lists (8px vertical / 16px horizontal so row labels align with\n * the 32px header/footer margins).\n */\n bodyPadding?: ModalBodyPadding;\n /** Body content. */\n children: ReactNode;\n /** Footer slot — typically a group of Buttons, right-aligned by default. */\n footer?: ReactNode;\n /** Show divider between body and footer. Figma: Divider = On. Default: true. */\n footerDivider?: boolean;\n}\n\nexport default function Modal({\n size = 'small',\n title,\n subtitle,\n showBackButton = false,\n onBack,\n onClose,\n headerDivider = true,\n bodyPadding = 'default',\n children,\n footer,\n footerDivider = true,\n}: ModalProps) {\n const titleId = useId();\n const sizeClass = styles[`modal--size-${toKebab(size)}`];\n const menuBody = bodyPadding === 'menu';\n\n return (\n <div\n className={[styles.modal, sizeClass].filter(Boolean).join(' ')}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n >\n <div\n className={[\n styles['modal__header'],\n !headerDivider && styles['modal__header--no-divider'],\n ]\n .filter(Boolean)\n .join(' ')}\n >\n <div className={styles['modal__header-inner']}>\n {showBackButton && (\n <IconButton\n aria-label=\"Go back\"\n icon={<Icon glyph={<ArrowLeftIcon />} size=\"20\" />}\n onClick={onBack}\n />\n )}\n <div className={styles['modal__title-group']}>\n <h2 id={titleId} className={styles['modal__title']}>\n {title}\n </h2>\n {subtitle && (\n <p className={styles['modal__subtitle']}>{subtitle}</p>\n )}\n </div>\n </div>\n <IconButton\n aria-label=\"Close\"\n className={styles['modal__close']}\n icon={<Icon glyph={<CloseIcon />} size=\"20\" />}\n onClick={onClose}\n />\n </div>\n\n <div className={styles['modal__body']}>\n <Scrollbar>\n <div\n className={[\n styles['modal__body-inner'],\n menuBody && styles['modal__body-inner--menu'],\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {children}\n </div>\n </Scrollbar>\n </div>\n\n {footer && (\n <div\n className={[\n styles['modal__footer'],\n !footerDivider && styles['modal__footer--no-divider'],\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {footer}\n </div>\n )}\n </div>\n );\n}\n"],"names":["Modal","size","title","subtitle","showBackButton","onBack","onClose","headerDivider","bodyPadding","children","footer","footerDivider","titleId","useId","sizeClass","styles","toKebab","menuBody","jsxs","jsx","IconButton","Icon","ArrowLeftIcon","CloseIcon","Scrollbar"],"mappings":"kdA4CA,SAAwBA,EAAM,CAC5B,KAAAC,EAAO,QACP,MAAAC,EACA,SAAAC,EACA,eAAAC,EAAiB,GACjB,OAAAC,EACA,QAAAC,EACA,cAAAC,EAAgB,GAChB,YAAAC,EAAc,UACd,SAAAC,EACA,OAAAC,EACA,cAAAC,EAAgB,EAClB,EAAe,CACb,MAAMC,EAAUC,EAAAA,MAAA,EACVC,EAAYC,EAAAA,QAAO,eAAeC,EAAAA,QAAQf,CAAI,CAAC,EAAE,EACjDgB,EAAWT,IAAgB,OAEjC,OACEU,EAAAA,KAAC,MAAA,CACC,UAAW,CAACH,UAAO,MAAOD,CAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,EAC7D,KAAK,SACL,aAAW,OACX,kBAAiBF,EAEjB,SAAA,CAAAM,EAAAA,KAAC,MAAA,CACC,UAAW,CACTH,EAAAA,QAAO,cACP,CAACR,GAAiBQ,EAAAA,QAAO,2BAA2B,CAAA,EAEnD,OAAO,OAAO,EACd,KAAK,GAAG,EAEX,SAAA,CAAAG,EAAAA,KAAC,MAAA,CAAI,UAAWH,EAAAA,QAAO,qBAAqB,EACzC,SAAA,CAAAX,GACCe,EAAAA,IAACC,EAAAA,QAAA,CACC,aAAW,UACX,WAAOC,UAAA,CAAK,YAAQC,EAAA,EAAc,EAAI,KAAK,KAAK,EAChD,QAASjB,CAAA,CAAA,EAGba,EAAAA,KAAC,MAAA,CAAI,UAAWH,EAAAA,QAAO,oBAAoB,EACzC,SAAA,CAAAI,EAAAA,IAAC,MAAG,GAAIP,EAAS,UAAWG,EAAAA,QAAO,aAChC,SAAAb,EACH,EACCC,GACCgB,EAAAA,IAAC,IAAA,CAAE,UAAWJ,EAAAA,QAAO,gBAAqB,SAAAZ,CAAA,CAAS,CAAA,CAAA,CAEvD,CAAA,EACF,EACAgB,EAAAA,IAACC,EAAAA,QAAA,CACC,aAAW,QACX,UAAWL,EAAAA,QAAO,aAClB,WAAOM,UAAA,CAAK,YAAQE,EAAA,EAAU,EAAI,KAAK,KAAK,EAC5C,QAASjB,CAAA,CAAA,CACX,CAAA,CAAA,QAGD,MAAA,CAAI,UAAWS,UAAO,YACrB,eAACS,UAAA,CACC,SAAAL,EAAAA,IAAC,MAAA,CACC,UAAW,CACTJ,EAAAA,QAAO,mBAAmB,EAC1BE,GAAYF,EAAAA,QAAO,yBAAyB,CAAA,EAE3C,OAAO,OAAO,EACd,KAAK,GAAG,EAEV,SAAAN,CAAA,CAAA,EAEL,CAAA,CACF,EAECC,GACCS,EAAAA,IAAC,MAAA,CACC,UAAW,CACTJ,EAAAA,QAAO,cACP,CAACJ,GAAiBI,EAAAA,QAAO,2BAA2B,CAAA,EAEnD,OAAO,OAAO,EACd,KAAK,GAAG,EAEV,SAAAL,CAAA,CAAA,CACH,CAAA,CAAA,CAIR"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
export type ModalSize = 'small' | 'medium' | 'large';
|
|
3
|
+
/** Body inset. `menu` is for MenuItem lists — 8px vertical / 16px horizontal so row labels align with the 32px header/footer margins. */
|
|
4
|
+
export type ModalBodyPadding = 'default' | 'menu';
|
|
3
5
|
export interface ModalProps {
|
|
4
6
|
/** Width variant. Figma: Size — Small 600px, Medium 704px, Large 832px. */
|
|
5
7
|
size?: ModalSize;
|
|
@@ -15,6 +17,12 @@ export interface ModalProps {
|
|
|
15
17
|
onClose?: () => void;
|
|
16
18
|
/** Show divider between header and body. Figma: Divider = On. Default: true. */
|
|
17
19
|
headerDivider?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Body inset. Default is 32px horizontal / 28px vertical. Use `menu` for
|
|
22
|
+
* MenuItem lists (8px vertical / 16px horizontal so row labels align with
|
|
23
|
+
* the 32px header/footer margins).
|
|
24
|
+
*/
|
|
25
|
+
bodyPadding?: ModalBodyPadding;
|
|
18
26
|
/** Body content. */
|
|
19
27
|
children: ReactNode;
|
|
20
28
|
/** Footer slot — typically a group of Buttons, right-aligned by default. */
|
|
@@ -22,5 +30,5 @@ export interface ModalProps {
|
|
|
22
30
|
/** Show divider between body and footer. Figma: Divider = On. Default: true. */
|
|
23
31
|
footerDivider?: boolean;
|
|
24
32
|
}
|
|
25
|
-
export default function Modal({ size, title, subtitle, showBackButton, onBack, onClose, headerDivider, children, footer, footerDivider, }: ModalProps): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
export default function Modal({ size, title, subtitle, showBackButton, onBack, onClose, headerDivider, bodyPadding, children, footer, footerDivider, }: ModalProps): import("react/jsx-runtime").JSX.Element;
|
|
26
34
|
//# sourceMappingURL=Modal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/components/modal/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAUvC,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAErD,MAAM,WAAW,UAAU;IACzB,2EAA2E;IAC3E,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,0CAA0C;IAC1C,KAAK,EAAE,SAAS,CAAC;IACjB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,6DAA6D;IAC7D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oBAAoB;IACpB,QAAQ,EAAE,SAAS,CAAC;IACpB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,EAC5B,IAAc,EACd,KAAK,EACL,QAAQ,EACR,cAAsB,EACtB,MAAM,EACN,OAAO,EACP,aAAoB,EACpB,QAAQ,EACR,MAAM,EACN,aAAoB,GACrB,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/components/modal/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAUvC,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAErD,yIAAyI;AACzI,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,MAAM,CAAC;AAElD,MAAM,WAAW,UAAU;IACzB,2EAA2E;IAC3E,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,0CAA0C;IAC1C,KAAK,EAAE,SAAS,CAAC;IACjB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,6DAA6D;IAC7D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,oBAAoB;IACpB,QAAQ,EAAE,SAAS,CAAC;IACpB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,EAC5B,IAAc,EACd,KAAK,EACL,QAAQ,EACR,cAAsB,EACtB,MAAM,EACN,OAAO,EACP,aAAoB,EACpB,WAAuB,EACvB,QAAQ,EACR,MAAM,EACN,aAAoB,GACrB,EAAE,UAAU,2CA0EZ"}
|
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
import { jsxs as e, jsx as l } from "react/jsx-runtime";
|
|
2
|
-
import { useId as
|
|
2
|
+
import { useId as v } from "react";
|
|
3
3
|
import d from "../icon-button/IconButton.js";
|
|
4
4
|
import m from "../icon/Icon.js";
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
5
|
+
import y from "../scrollbar/Scrollbar.js";
|
|
6
|
+
import __j from "@mattermost/compass-icons/components/close.js";const j=__j&&__j.default?__j.default:__j;
|
|
7
|
+
import __B from "@mattermost/compass-icons/components/arrow-left.js";const B=__B&&__B.default?__B.default:__B;
|
|
8
8
|
import { toKebab as I } from "../../utils/string.js";
|
|
9
9
|
import o from "./Modal.module.scss.js";
|
|
10
|
-
function
|
|
11
|
-
size:
|
|
12
|
-
title:
|
|
10
|
+
function L({
|
|
11
|
+
size: n = "small",
|
|
12
|
+
title: s,
|
|
13
13
|
subtitle: a,
|
|
14
|
-
showBackButton:
|
|
15
|
-
onBack:
|
|
14
|
+
showBackButton: t = !1,
|
|
15
|
+
onBack: c,
|
|
16
16
|
onClose: _,
|
|
17
17
|
headerDivider: f = !0,
|
|
18
|
-
|
|
18
|
+
bodyPadding: h = "default",
|
|
19
|
+
children: p,
|
|
19
20
|
footer: i,
|
|
20
|
-
footerDivider:
|
|
21
|
+
footerDivider: u = !0
|
|
21
22
|
}) {
|
|
22
|
-
const r =
|
|
23
|
+
const r = v(), b = o[`modal--size-${I(n)}`], N = h === "menu";
|
|
23
24
|
return /* @__PURE__ */ e(
|
|
24
25
|
"div",
|
|
25
26
|
{
|
|
@@ -37,16 +38,16 @@ function G({
|
|
|
37
38
|
].filter(Boolean).join(" "),
|
|
38
39
|
children: [
|
|
39
40
|
/* @__PURE__ */ e("div", { className: o["modal__header-inner"], children: [
|
|
40
|
-
|
|
41
|
+
t && /* @__PURE__ */ l(
|
|
41
42
|
d,
|
|
42
43
|
{
|
|
43
44
|
"aria-label": "Go back",
|
|
44
|
-
icon: /* @__PURE__ */ l(m, { glyph: /* @__PURE__ */ l(
|
|
45
|
-
onClick:
|
|
45
|
+
icon: /* @__PURE__ */ l(m, { glyph: /* @__PURE__ */ l(B, {}), size: "20" }),
|
|
46
|
+
onClick: c
|
|
46
47
|
}
|
|
47
48
|
),
|
|
48
49
|
/* @__PURE__ */ e("div", { className: o["modal__title-group"], children: [
|
|
49
|
-
/* @__PURE__ */ l("h2", { id: r, className: o.modal__title, children:
|
|
50
|
+
/* @__PURE__ */ l("h2", { id: r, className: o.modal__title, children: s }),
|
|
50
51
|
a && /* @__PURE__ */ l("p", { className: o.modal__subtitle, children: a })
|
|
51
52
|
] })
|
|
52
53
|
] }),
|
|
@@ -55,20 +56,29 @@ function G({
|
|
|
55
56
|
{
|
|
56
57
|
"aria-label": "Close",
|
|
57
58
|
className: o.modal__close,
|
|
58
|
-
icon: /* @__PURE__ */ l(m, { glyph: /* @__PURE__ */ l(
|
|
59
|
+
icon: /* @__PURE__ */ l(m, { glyph: /* @__PURE__ */ l(j, {}), size: "20" }),
|
|
59
60
|
onClick: _
|
|
60
61
|
}
|
|
61
62
|
)
|
|
62
63
|
]
|
|
63
64
|
}
|
|
64
65
|
),
|
|
65
|
-
/* @__PURE__ */ l("div", { className: o.modal__body, children: /* @__PURE__ */ l(
|
|
66
|
+
/* @__PURE__ */ l("div", { className: o.modal__body, children: /* @__PURE__ */ l(y, { children: /* @__PURE__ */ l(
|
|
67
|
+
"div",
|
|
68
|
+
{
|
|
69
|
+
className: [
|
|
70
|
+
o["modal__body-inner"],
|
|
71
|
+
N && o["modal__body-inner--menu"]
|
|
72
|
+
].filter(Boolean).join(" "),
|
|
73
|
+
children: p
|
|
74
|
+
}
|
|
75
|
+
) }) }),
|
|
66
76
|
i && /* @__PURE__ */ l(
|
|
67
77
|
"div",
|
|
68
78
|
{
|
|
69
79
|
className: [
|
|
70
80
|
o.modal__footer,
|
|
71
|
-
!
|
|
81
|
+
!u && o["modal__footer--no-divider"]
|
|
72
82
|
].filter(Boolean).join(" "),
|
|
73
83
|
children: i
|
|
74
84
|
}
|
|
@@ -78,6 +88,6 @@ function G({
|
|
|
78
88
|
);
|
|
79
89
|
}
|
|
80
90
|
export {
|
|
81
|
-
|
|
91
|
+
L as default
|
|
82
92
|
};
|
|
83
93
|
//# sourceMappingURL=Modal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.js","sources":["../../../src/components/modal/Modal.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { useId } from 'react';\nimport IconButton from '@/components/icon-button/IconButton';\nimport Icon from '@/components/icon/Icon';\nimport Scrollbar from '@/components/scrollbar/Scrollbar';\nimport CloseIcon from '@mattermost/compass-icons/components/close';\nimport ArrowLeftIcon from '@mattermost/compass-icons/components/arrow-left';\nimport { toKebab } from '@/utils/string';\nimport styles from './Modal.module.scss';\n\nexport type ModalSize = 'small' | 'medium' | 'large';\n\nexport interface ModalProps {\n /** Width variant. Figma: Size — Small 600px, Medium 704px, Large 832px. */\n size?: ModalSize;\n /** Modal heading text. Always visible. */\n title: ReactNode;\n /** Optional secondary line below the title. */\n subtitle?: ReactNode;\n /** When true, shows a back-arrow button before the title. */\n showBackButton?: boolean;\n /** Called when the back button is clicked. */\n onBack?: () => void;\n /** Called when the × close button is clicked. */\n onClose?: () => void;\n /** Show divider between header and body. Figma: Divider = On. Default: true. */\n headerDivider?: boolean;\n /** Body content. */\n children: ReactNode;\n /** Footer slot — typically a group of Buttons, right-aligned by default. */\n footer?: ReactNode;\n /** Show divider between body and footer. Figma: Divider = On. Default: true. */\n footerDivider?: boolean;\n}\n\nexport default function Modal({\n size = 'small',\n title,\n subtitle,\n showBackButton = false,\n onBack,\n onClose,\n headerDivider = true,\n children,\n footer,\n footerDivider = true,\n}: ModalProps) {\n const titleId = useId();\n const sizeClass = styles[`modal--size-${toKebab(size)}`];\n\n return (\n <div\n className={[styles.modal, sizeClass].filter(Boolean).join(' ')}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n >\n <div\n className={[\n styles['modal__header'],\n !headerDivider && styles['modal__header--no-divider'],\n ]\n .filter(Boolean)\n .join(' ')}\n >\n <div className={styles['modal__header-inner']}>\n {showBackButton && (\n <IconButton\n aria-label=\"Go back\"\n icon={<Icon glyph={<ArrowLeftIcon />} size=\"20\" />}\n onClick={onBack}\n />\n )}\n <div className={styles['modal__title-group']}>\n <h2 id={titleId} className={styles['modal__title']}>\n {title}\n </h2>\n {subtitle && (\n <p className={styles['modal__subtitle']}>{subtitle}</p>\n )}\n </div>\n </div>\n <IconButton\n aria-label=\"Close\"\n className={styles['modal__close']}\n icon={<Icon glyph={<CloseIcon />} size=\"20\" />}\n onClick={onClose}\n />\n </div>\n\n <div className={styles['modal__body']}>\n <Scrollbar>\n <div
|
|
1
|
+
{"version":3,"file":"Modal.js","sources":["../../../src/components/modal/Modal.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { useId } from 'react';\nimport IconButton from '@/components/icon-button/IconButton';\nimport Icon from '@/components/icon/Icon';\nimport Scrollbar from '@/components/scrollbar/Scrollbar';\nimport CloseIcon from '@mattermost/compass-icons/components/close';\nimport ArrowLeftIcon from '@mattermost/compass-icons/components/arrow-left';\nimport { toKebab } from '@/utils/string';\nimport styles from './Modal.module.scss';\n\nexport type ModalSize = 'small' | 'medium' | 'large';\n\n/** Body inset. `menu` is for MenuItem lists — 8px vertical / 16px horizontal so row labels align with the 32px header/footer margins. */\nexport type ModalBodyPadding = 'default' | 'menu';\n\nexport interface ModalProps {\n /** Width variant. Figma: Size — Small 600px, Medium 704px, Large 832px. */\n size?: ModalSize;\n /** Modal heading text. Always visible. */\n title: ReactNode;\n /** Optional secondary line below the title. */\n subtitle?: ReactNode;\n /** When true, shows a back-arrow button before the title. */\n showBackButton?: boolean;\n /** Called when the back button is clicked. */\n onBack?: () => void;\n /** Called when the × close button is clicked. */\n onClose?: () => void;\n /** Show divider between header and body. Figma: Divider = On. Default: true. */\n headerDivider?: boolean;\n /**\n * Body inset. Default is 32px horizontal / 28px vertical. Use `menu` for\n * MenuItem lists (8px vertical / 16px horizontal so row labels align with\n * the 32px header/footer margins).\n */\n bodyPadding?: ModalBodyPadding;\n /** Body content. */\n children: ReactNode;\n /** Footer slot — typically a group of Buttons, right-aligned by default. */\n footer?: ReactNode;\n /** Show divider between body and footer. Figma: Divider = On. Default: true. */\n footerDivider?: boolean;\n}\n\nexport default function Modal({\n size = 'small',\n title,\n subtitle,\n showBackButton = false,\n onBack,\n onClose,\n headerDivider = true,\n bodyPadding = 'default',\n children,\n footer,\n footerDivider = true,\n}: ModalProps) {\n const titleId = useId();\n const sizeClass = styles[`modal--size-${toKebab(size)}`];\n const menuBody = bodyPadding === 'menu';\n\n return (\n <div\n className={[styles.modal, sizeClass].filter(Boolean).join(' ')}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n >\n <div\n className={[\n styles['modal__header'],\n !headerDivider && styles['modal__header--no-divider'],\n ]\n .filter(Boolean)\n .join(' ')}\n >\n <div className={styles['modal__header-inner']}>\n {showBackButton && (\n <IconButton\n aria-label=\"Go back\"\n icon={<Icon glyph={<ArrowLeftIcon />} size=\"20\" />}\n onClick={onBack}\n />\n )}\n <div className={styles['modal__title-group']}>\n <h2 id={titleId} className={styles['modal__title']}>\n {title}\n </h2>\n {subtitle && (\n <p className={styles['modal__subtitle']}>{subtitle}</p>\n )}\n </div>\n </div>\n <IconButton\n aria-label=\"Close\"\n className={styles['modal__close']}\n icon={<Icon glyph={<CloseIcon />} size=\"20\" />}\n onClick={onClose}\n />\n </div>\n\n <div className={styles['modal__body']}>\n <Scrollbar>\n <div\n className={[\n styles['modal__body-inner'],\n menuBody && styles['modal__body-inner--menu'],\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {children}\n </div>\n </Scrollbar>\n </div>\n\n {footer && (\n <div\n className={[\n styles['modal__footer'],\n !footerDivider && styles['modal__footer--no-divider'],\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {footer}\n </div>\n )}\n </div>\n );\n}\n"],"names":["Modal","size","title","subtitle","showBackButton","onBack","onClose","headerDivider","bodyPadding","children","footer","footerDivider","titleId","useId","sizeClass","styles","toKebab","menuBody","jsxs","jsx","IconButton","Icon","ArrowLeftIcon","CloseIcon","Scrollbar"],"mappings":";;;;;;;;;AA4CA,SAAwBA,EAAM;AAAA,EAC5B,MAAAC,IAAO;AAAA,EACP,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,gBAAAC,IAAiB;AAAA,EACjB,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,eAAAC,IAAgB;AAAA,EAChB,aAAAC,IAAc;AAAA,EACd,UAAAC;AAAA,EACA,QAAAC;AAAA,EACA,eAAAC,IAAgB;AAClB,GAAe;AACb,QAAMC,IAAUC,EAAA,GACVC,IAAYC,EAAO,eAAeC,EAAQf,CAAI,CAAC,EAAE,GACjDgB,IAAWT,MAAgB;AAEjC,SACE,gBAAAU;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,CAACH,EAAO,OAAOD,CAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,MAC7D,MAAK;AAAA,MACL,cAAW;AAAA,MACX,mBAAiBF;AAAA,MAEjB,UAAA;AAAA,QAAA,gBAAAM;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW;AAAA,cACTH,EAAO;AAAA,cACP,CAACR,KAAiBQ,EAAO,2BAA2B;AAAA,YAAA,EAEnD,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,YAEX,UAAA;AAAA,cAAA,gBAAAG,EAAC,OAAA,EAAI,WAAWH,EAAO,qBAAqB,GACzC,UAAA;AAAA,gBAAAX,KACC,gBAAAe;AAAA,kBAACC;AAAA,kBAAA;AAAA,oBACC,cAAW;AAAA,oBACX,wBAAOC,GAAA,EAAK,yBAAQC,GAAA,EAAc,GAAI,MAAK,MAAK;AAAA,oBAChD,SAASjB;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAGb,gBAAAa,EAAC,OAAA,EAAI,WAAWH,EAAO,oBAAoB,GACzC,UAAA;AAAA,kBAAA,gBAAAI,EAAC,QAAG,IAAIP,GAAS,WAAWG,EAAO,cAChC,UAAAb,GACH;AAAA,kBACCC,KACC,gBAAAgB,EAAC,KAAA,EAAE,WAAWJ,EAAO,iBAAqB,UAAAZ,EAAA,CAAS;AAAA,gBAAA,EAAA,CAEvD;AAAA,cAAA,GACF;AAAA,cACA,gBAAAgB;AAAA,gBAACC;AAAA,gBAAA;AAAA,kBACC,cAAW;AAAA,kBACX,WAAWL,EAAO;AAAA,kBAClB,wBAAOM,GAAA,EAAK,yBAAQE,GAAA,EAAU,GAAI,MAAK,MAAK;AAAA,kBAC5C,SAASjB;AAAA,gBAAA;AAAA,cAAA;AAAA,YACX;AAAA,UAAA;AAAA,QAAA;AAAA,0BAGD,OAAA,EAAI,WAAWS,EAAO,aACrB,4BAACS,GAAA,EACC,UAAA,gBAAAL;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW;AAAA,cACTJ,EAAO,mBAAmB;AAAA,cAC1BE,KAAYF,EAAO,yBAAyB;AAAA,YAAA,EAE3C,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,YAEV,UAAAN;AAAA,UAAA;AAAA,QAAA,GAEL,EAAA,CACF;AAAA,QAECC,KACC,gBAAAS;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW;AAAA,cACTJ,EAAO;AAAA,cACP,CAACJ,KAAiBI,EAAO,2BAA2B;AAAA,YAAA,EAEnD,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,YAEV,UAAAL;AAAA,UAAA;AAAA,QAAA;AAAA,MACH;AAAA,IAAA;AAAA,EAAA;AAIR;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.
|
|
1
|
+
._modal_1wwq4_2{background-color:var(--center-channel-bg);border:1px solid rgba(var(--center-channel-color-rgb),.16);border-radius:var(--radius-l);box-shadow:var(--elevation-6);display:flex;flex-direction:column;overflow:hidden}._modal--size-small_1wwq4_11{width:600px}._modal--size-medium_1wwq4_14{width:704px}._modal--size-large_1wwq4_17{width:832px}._modal__header_1wwq4_20{display:flex;align-items:flex-start;gap:var(--spacing-s);padding:var(--spacing-xxl) var(--spacing-xxxl);border-bottom:1px solid rgba(var(--center-channel-color-rgb),.12);flex-shrink:0}._modal__header--no-divider_1wwq4_28{border-bottom:none;padding-bottom:0}._modal__header-inner_1wwq4_32{display:flex;align-items:center;gap:var(--spacing-m);flex:1;min-width:0;padding:var(--spacing-xxxxs) 0}._modal__title-group_1wwq4_40{display:flex;flex-direction:column;gap:var(--spacing-xxxs);min-width:0}._modal__title_1wwq4_40{font-family:var(--font-family-heading);font-size:var(--font-size-500);font-weight:var(--font-weight-semibold);line-height:var(--line-height-500);color:var(--center-channel-color);margin:0}._modal__subtitle_1wwq4_54{font-family:var(--font-family-body);font-size:var(--font-size-100);line-height:var(--line-height-200);color:rgba(var(--center-channel-color-rgb),.72);margin:0}._modal__close_1wwq4_61{margin-right:-12px;margin-top:-6px;margin-bottom:-6px}._modal__body_1wwq4_66{flex:1;min-height:0}._modal__body-inner_1wwq4_70{padding:28px var(--spacing-xxxl)}._modal__body-inner--menu_1wwq4_73{padding:var(--spacing-xs) var(--spacing-l)}._modal__footer_1wwq4_76{display:flex;align-items:center;justify-content:flex-end;gap:var(--spacing-xs);padding:var(--spacing-xxl) var(--spacing-xxxl);border-top:1px solid rgba(var(--center-channel-color-rgb),.12);flex-shrink:0}._modal__footer--no-divider_1wwq4_85{border-top:none;padding-top:0}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});require('./Modal.module.css');const _="
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});require('./Modal.module.css');const _="_modal_1wwq4_2",o="_modal__header_1wwq4_20",d="_modal__title_1wwq4_40",l="_modal__subtitle_1wwq4_54",e="_modal__close_1wwq4_61",a="_modal__body_1wwq4_66",m="_modal__footer_1wwq4_76",t={modal:_,"modal--size-small":"_modal--size-small_1wwq4_11","modal--size-medium":"_modal--size-medium_1wwq4_14","modal--size-large":"_modal--size-large_1wwq4_17",modal__header:o,"modal__header--no-divider":"_modal__header--no-divider_1wwq4_28","modal__header-inner":"_modal__header-inner_1wwq4_32","modal__title-group":"_modal__title-group_1wwq4_40",modal__title:d,modal__subtitle:l,modal__close:e,modal__body:a,"modal__body-inner":"_modal__body-inner_1wwq4_70","modal__body-inner--menu":"_modal__body-inner--menu_1wwq4_73",modal__footer:m,"modal__footer--no-divider":"_modal__footer--no-divider_1wwq4_85"};exports.default=t;exports.modal=_;exports.modal__body=a;exports.modal__close=e;exports.modal__footer=m;exports.modal__header=o;exports.modal__subtitle=l;exports.modal__title=d;
|
|
2
2
|
//# sourceMappingURL=Modal.module.scss.cjs.map
|
|
@@ -1,28 +1,29 @@
|
|
|
1
|
-
import './Modal.module.css';const _ = "
|
|
1
|
+
import './Modal.module.css';const _ = "_modal_1wwq4_2", o = "_modal__header_1wwq4_20", d = "_modal__title_1wwq4_40", l = "_modal__subtitle_1wwq4_54", e = "_modal__close_1wwq4_61", a = "_modal__body_1wwq4_66", m = "_modal__footer_1wwq4_76", t = {
|
|
2
2
|
modal: _,
|
|
3
|
-
"modal--size-small": "_modal--size-
|
|
4
|
-
"modal--size-medium": "_modal--size-
|
|
5
|
-
"modal--size-large": "_modal--size-
|
|
6
|
-
modal__header:
|
|
7
|
-
"modal__header--no-divider": "_modal__header--no-
|
|
8
|
-
"modal__header-inner": "_modal__header-
|
|
9
|
-
"modal__title-group": "_modal__title-
|
|
10
|
-
modal__title:
|
|
11
|
-
modal__subtitle:
|
|
12
|
-
modal__close:
|
|
3
|
+
"modal--size-small": "_modal--size-small_1wwq4_11",
|
|
4
|
+
"modal--size-medium": "_modal--size-medium_1wwq4_14",
|
|
5
|
+
"modal--size-large": "_modal--size-large_1wwq4_17",
|
|
6
|
+
modal__header: o,
|
|
7
|
+
"modal__header--no-divider": "_modal__header--no-divider_1wwq4_28",
|
|
8
|
+
"modal__header-inner": "_modal__header-inner_1wwq4_32",
|
|
9
|
+
"modal__title-group": "_modal__title-group_1wwq4_40",
|
|
10
|
+
modal__title: d,
|
|
11
|
+
modal__subtitle: l,
|
|
12
|
+
modal__close: e,
|
|
13
13
|
modal__body: a,
|
|
14
|
-
"modal__body-inner": "_modal__body-
|
|
14
|
+
"modal__body-inner": "_modal__body-inner_1wwq4_70",
|
|
15
|
+
"modal__body-inner--menu": "_modal__body-inner--menu_1wwq4_73",
|
|
15
16
|
modal__footer: m,
|
|
16
|
-
"modal__footer--no-divider": "_modal__footer--no-
|
|
17
|
+
"modal__footer--no-divider": "_modal__footer--no-divider_1wwq4_85"
|
|
17
18
|
};
|
|
18
19
|
export {
|
|
19
20
|
t as default,
|
|
20
21
|
_ as modal,
|
|
21
22
|
a as modal__body,
|
|
22
|
-
|
|
23
|
+
e as modal__close,
|
|
23
24
|
m as modal__footer,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
o as modal__header,
|
|
26
|
+
l as modal__subtitle,
|
|
27
|
+
d as modal__title
|
|
27
28
|
};
|
|
28
29
|
//# sourceMappingURL=Modal.module.scss.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Modal.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/modal/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,SAAS,CAAC;AAC3C,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/modal/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,SAAS,CAAC;AAC3C,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MouseEvent } from 'react';
|
|
2
|
-
import { UserAvatarGroupItem } from '../
|
|
2
|
+
import { UserAvatarGroupItem } from '../user-avatar-group/UserAvatarGroup';
|
|
3
3
|
export interface ThreadListItemProps {
|
|
4
4
|
/** Whether this item is the active/selected thread. */
|
|
5
5
|
active?: boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { default as ThreadListItem } from './ThreadListItem';
|
|
2
2
|
export type { ThreadListItemProps } from './ThreadListItem';
|
|
3
|
-
export type { UserAvatarGroupItem } from '../
|
|
3
|
+
export type { UserAvatarGroupItem } from '../user-avatar-group/UserAvatarGroup';
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react"),I=require("react-dom"),c=require("../utils/anchoredPopupPlacement.cjs"),N="below";function E(r){return typeof document>"u"?null:r??document.body}function O(r){return r===document.body}function R(r,s,y){const{preferredHeight:p,maxHeightCap:f,contentRef:o,portalContainer:d=null,zIndex:h=c.ANCHORED_POPUP_Z_INDEX,matchWidth:l=!0,gap:m=c.ANCHORED_POPUP_GAP}=y,P=n.useRef(null),[A,C]=n.useState(N),[L,z]=n.useState(f??p),[F,S]=n.useState({position:"fixed",top:0,left:0,width:l?0:void 0,zIndex:h}),i=n.useCallback(()=>{var x,H;const e=r.current;if(!e)return;const t=E(d);if(!t)return;const g=e.getBoundingClientRect(),v=window.innerHeight,a=O(t)?void 0:c.getAnchoredPopupContainerFrame(t),b=((x=o==null?void 0:o.current)==null?void 0:x.offsetHeight)??((H=P.current)==null?void 0:H.offsetHeight)??0,D=b>0?b:p,{placement:w,maxHeight:M}=c.computeAnchoredPopupPlacement(g,v,{gap:m,preferredHeight:D,maxHeightCap:f,bounds:a==null?void 0:a.bounds}),u=c.computeAnchoredPopupFixedStyle(g,w,{gap:m,zIndex:h,width:l?g.width:void 0,viewportHeight:v,containerFrame:a});C(w),z(M),S({position:u.position,left:u.left,zIndex:u.zIndex,...l?{width:u.width}:null,...w==="below"?{top:u.top,bottom:"auto"}:{bottom:u.bottom,top:"auto"}})},[r,o,m,l,f,d,p,h]);n.useLayoutEffect(()=>{if(!s)return;i();function e(){i()}return window.addEventListener("resize",e),document.addEventListener("scroll",e,!0),()=>{window.removeEventListener("resize",e),document.removeEventListener("scroll",e,!0)}},[s,i]),n.useLayoutEffect(()=>{if(!s)return;const e=(o==null?void 0:o.current)??P.current;if(!e||typeof ResizeObserver>"u")return;const t=new ResizeObserver(()=>i());return t.observe(e),()=>t.disconnect()},[s,o,i]);const _=n.useCallback(e=>{const t=E(d);return t?I.createPortal(e,t):null},[d]);return{placement:A,maxHeight:L,style:F,portalRef:P,renderPortal:_}}exports.useAnchoredPopupPortal=R;
|
|
2
|
-
//# sourceMappingURL=
|
|
2
|
+
//# sourceMappingURL=use-anchored-popup-portal.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-anchored-popup-portal.cjs","sources":["../../src/hooks/use-anchored-popup-portal.ts"],"sourcesContent":["import {\n useCallback,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n type RefObject,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n ANCHORED_POPUP_GAP,\n ANCHORED_POPUP_Z_INDEX,\n computeAnchoredPopupFixedStyle,\n computeAnchoredPopupPlacement,\n getAnchoredPopupContainerFrame,\n type PopupPlacement,\n} from '@/utils/anchoredPopupPlacement';\n\nexport interface UseAnchoredPopupPortalOptions {\n /** Height used for the flip decision when content isn’t measured yet. */\n preferredHeight: number;\n /** Cap for scrollable menus (Select/Combobox). Omit for intrinsic panels. */\n maxHeightCap?: number;\n /** Ref to the portaled panel for measuring intrinsic height (DateRangePicker). */\n contentRef?: RefObject<HTMLElement | null>;\n /**\n * Portal mount node; defaults to `document.body` with viewport-fixed coords.\n * Custom containers must establish a positioning context (`position` other\n * than `static`); coords are converted to that container’s space.\n */\n portalContainer?: HTMLElement | null;\n zIndex?: number;\n /**\n * When true (default), fixed width matches the trigger.\n * DateRangePicker sets false and keeps its CSS width.\n */\n matchWidth?: boolean;\n gap?: number;\n}\n\nexport interface UseAnchoredPopupPortalResult {\n placement: PopupPlacement;\n maxHeight: number;\n style: CSSProperties;\n /** Ref for the portaled surface — pass to `useOutsideClose` as a second root. */\n portalRef: RefObject<HTMLDivElement | null>;\n /** Wraps children in a portal to `portalContainer` or `document.body`. */\n renderPortal: (children: ReactNode) => ReactNode;\n}\n\nconst DEFAULT_PLACEMENT: PopupPlacement = 'below';\n\nfunction resolvePortalMount(\n portalContainer: HTMLElement | null | undefined,\n): HTMLElement | null {\n if (typeof document === 'undefined') return null;\n return portalContainer ?? document.body;\n}\n\nfunction usesViewportFixedCoords(mount: HTMLElement): boolean {\n return mount === document.body;\n}\n\n/**\n * Positions a form-widget popup in a portal with viewport-aware above/below flip.\n * Internal to compass-ui form widgets — not a general overlay positioning API.\n */\nexport function useAnchoredPopupPortal(\n anchorRef: RefObject<HTMLElement | null>,\n isOpen: boolean,\n options: UseAnchoredPopupPortalOptions,\n): UseAnchoredPopupPortalResult {\n const {\n preferredHeight,\n maxHeightCap,\n contentRef,\n portalContainer = null,\n zIndex = ANCHORED_POPUP_Z_INDEX,\n matchWidth = true,\n gap = ANCHORED_POPUP_GAP,\n } = options;\n\n const portalRef = useRef<HTMLDivElement | null>(null);\n const [placement, setPlacement] = useState<PopupPlacement>(DEFAULT_PLACEMENT);\n const [maxHeight, setMaxHeight] = useState(\n maxHeightCap ?? preferredHeight,\n );\n const [style, setStyle] = useState<CSSProperties>({\n position: 'fixed',\n top: 0,\n left: 0,\n width: matchWidth ? 0 : undefined,\n zIndex,\n });\n\n const update = useCallback(() => {\n const anchor = anchorRef.current;\n if (!anchor) return;\n\n const mount = resolvePortalMount(portalContainer);\n if (!mount) return;\n\n const rect = anchor.getBoundingClientRect();\n const viewportHeight = window.innerHeight;\n const viewportFixed = usesViewportFixedCoords(mount);\n const containerFrame = viewportFixed\n ? undefined\n : getAnchoredPopupContainerFrame(mount);\n\n const measured =\n contentRef?.current?.offsetHeight ??\n portalRef.current?.offsetHeight ??\n 0;\n const heightForFlip = measured > 0 ? measured : preferredHeight;\n\n const { placement: nextPlacement, maxHeight: nextMaxHeight } =\n computeAnchoredPopupPlacement(rect, viewportHeight, {\n gap,\n preferredHeight: heightForFlip,\n maxHeightCap,\n bounds: containerFrame?.bounds,\n });\n\n const fixed = computeAnchoredPopupFixedStyle(rect, nextPlacement, {\n gap,\n zIndex,\n width: matchWidth ? rect.width : undefined,\n viewportHeight,\n containerFrame,\n });\n\n setPlacement(nextPlacement);\n setMaxHeight(nextMaxHeight);\n setStyle({\n position: fixed.position,\n left: fixed.left,\n zIndex: fixed.zIndex,\n ...(matchWidth ? { width: fixed.width } : null),\n ...(nextPlacement === 'below'\n ? { top: fixed.top, bottom: 'auto' }\n : { bottom: fixed.bottom, top: 'auto' }),\n });\n }, [\n anchorRef,\n contentRef,\n gap,\n matchWidth,\n maxHeightCap,\n portalContainer,\n preferredHeight,\n zIndex,\n ]);\n\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n update();\n\n function handle() {\n update();\n }\n\n window.addEventListener('resize', handle);\n // Capture phase so nested scroll containers (modals, RHS) are covered.\n document.addEventListener('scroll', handle, true);\n return () => {\n window.removeEventListener('resize', handle);\n document.removeEventListener('scroll', handle, true);\n };\n }, [isOpen, update]);\n\n // Re-measure after content mounts / changes size (calendar, long lists).\n useLayoutEffect(() => {\n if (!isOpen) return;\n const el = contentRef?.current ?? portalRef.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n\n const ro = new ResizeObserver(() => update());\n ro.observe(el);\n return () => ro.disconnect();\n }, [isOpen, contentRef, update]);\n\n const renderPortal = useCallback(\n (children: ReactNode) => {\n const mount = resolvePortalMount(portalContainer);\n if (!mount) return null;\n return createPortal(children, mount);\n },\n [portalContainer],\n );\n\n return {\n placement,\n maxHeight,\n style,\n portalRef,\n renderPortal,\n };\n}\n"],"names":["DEFAULT_PLACEMENT","resolvePortalMount","portalContainer","usesViewportFixedCoords","mount","useAnchoredPopupPortal","anchorRef","isOpen","options","preferredHeight","maxHeightCap","contentRef","zIndex","ANCHORED_POPUP_Z_INDEX","matchWidth","gap","ANCHORED_POPUP_GAP","portalRef","useRef","placement","setPlacement","useState","maxHeight","setMaxHeight","style","setStyle","update","useCallback","anchor","rect","viewportHeight","containerFrame","getAnchoredPopupContainerFrame","measured","_a","_b","heightForFlip","nextPlacement","nextMaxHeight","computeAnchoredPopupPlacement","fixed","computeAnchoredPopupFixedStyle","useLayoutEffect","handle","el","ro","renderPortal","children","createPortal"],"mappings":"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"}
|
|
@@ -35,4 +35,4 @@ export interface UseAnchoredPopupPortalResult {
|
|
|
35
35
|
* Internal to compass-ui form widgets — not a general overlay positioning API.
|
|
36
36
|
*/
|
|
37
37
|
export declare function useAnchoredPopupPortal(anchorRef: RefObject<HTMLElement | null>, isOpen: boolean, options: UseAnchoredPopupPortalOptions): UseAnchoredPopupPortalResult;
|
|
38
|
-
//# sourceMappingURL=
|
|
38
|
+
//# sourceMappingURL=use-anchored-popup-portal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-anchored-popup-portal.d.ts","sourceRoot":"","sources":["../../src/hooks/use-anchored-popup-portal.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,gCAAgC,CAAC;AAExC,MAAM,WAAW,6BAA6B;IAC5C,yEAAyE;IACzE,eAAe,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,UAAU,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC3C;;;;OAIG;IACH,eAAe,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,4BAA4B;IAC3C,SAAS,EAAE,cAAc,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,aAAa,CAAC;IACrB,iFAAiF;IACjF,SAAS,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC5C,0EAA0E;IAC1E,YAAY,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,SAAS,CAAC;CAClD;AAeD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EACxC,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,6BAA6B,GACrC,4BAA4B,CA+H9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-anchored-popup-portal.js","sources":["../../src/hooks/use-anchored-popup-portal.ts"],"sourcesContent":["import {\n useCallback,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n type RefObject,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n ANCHORED_POPUP_GAP,\n ANCHORED_POPUP_Z_INDEX,\n computeAnchoredPopupFixedStyle,\n computeAnchoredPopupPlacement,\n getAnchoredPopupContainerFrame,\n type PopupPlacement,\n} from '@/utils/anchoredPopupPlacement';\n\nexport interface UseAnchoredPopupPortalOptions {\n /** Height used for the flip decision when content isn’t measured yet. */\n preferredHeight: number;\n /** Cap for scrollable menus (Select/Combobox). Omit for intrinsic panels. */\n maxHeightCap?: number;\n /** Ref to the portaled panel for measuring intrinsic height (DateRangePicker). */\n contentRef?: RefObject<HTMLElement | null>;\n /**\n * Portal mount node; defaults to `document.body` with viewport-fixed coords.\n * Custom containers must establish a positioning context (`position` other\n * than `static`); coords are converted to that container’s space.\n */\n portalContainer?: HTMLElement | null;\n zIndex?: number;\n /**\n * When true (default), fixed width matches the trigger.\n * DateRangePicker sets false and keeps its CSS width.\n */\n matchWidth?: boolean;\n gap?: number;\n}\n\nexport interface UseAnchoredPopupPortalResult {\n placement: PopupPlacement;\n maxHeight: number;\n style: CSSProperties;\n /** Ref for the portaled surface — pass to `useOutsideClose` as a second root. */\n portalRef: RefObject<HTMLDivElement | null>;\n /** Wraps children in a portal to `portalContainer` or `document.body`. */\n renderPortal: (children: ReactNode) => ReactNode;\n}\n\nconst DEFAULT_PLACEMENT: PopupPlacement = 'below';\n\nfunction resolvePortalMount(\n portalContainer: HTMLElement | null | undefined,\n): HTMLElement | null {\n if (typeof document === 'undefined') return null;\n return portalContainer ?? document.body;\n}\n\nfunction usesViewportFixedCoords(mount: HTMLElement): boolean {\n return mount === document.body;\n}\n\n/**\n * Positions a form-widget popup in a portal with viewport-aware above/below flip.\n * Internal to compass-ui form widgets — not a general overlay positioning API.\n */\nexport function useAnchoredPopupPortal(\n anchorRef: RefObject<HTMLElement | null>,\n isOpen: boolean,\n options: UseAnchoredPopupPortalOptions,\n): UseAnchoredPopupPortalResult {\n const {\n preferredHeight,\n maxHeightCap,\n contentRef,\n portalContainer = null,\n zIndex = ANCHORED_POPUP_Z_INDEX,\n matchWidth = true,\n gap = ANCHORED_POPUP_GAP,\n } = options;\n\n const portalRef = useRef<HTMLDivElement | null>(null);\n const [placement, setPlacement] = useState<PopupPlacement>(DEFAULT_PLACEMENT);\n const [maxHeight, setMaxHeight] = useState(\n maxHeightCap ?? preferredHeight,\n );\n const [style, setStyle] = useState<CSSProperties>({\n position: 'fixed',\n top: 0,\n left: 0,\n width: matchWidth ? 0 : undefined,\n zIndex,\n });\n\n const update = useCallback(() => {\n const anchor = anchorRef.current;\n if (!anchor) return;\n\n const mount = resolvePortalMount(portalContainer);\n if (!mount) return;\n\n const rect = anchor.getBoundingClientRect();\n const viewportHeight = window.innerHeight;\n const viewportFixed = usesViewportFixedCoords(mount);\n const containerFrame = viewportFixed\n ? undefined\n : getAnchoredPopupContainerFrame(mount);\n\n const measured =\n contentRef?.current?.offsetHeight ??\n portalRef.current?.offsetHeight ??\n 0;\n const heightForFlip = measured > 0 ? measured : preferredHeight;\n\n const { placement: nextPlacement, maxHeight: nextMaxHeight } =\n computeAnchoredPopupPlacement(rect, viewportHeight, {\n gap,\n preferredHeight: heightForFlip,\n maxHeightCap,\n bounds: containerFrame?.bounds,\n });\n\n const fixed = computeAnchoredPopupFixedStyle(rect, nextPlacement, {\n gap,\n zIndex,\n width: matchWidth ? rect.width : undefined,\n viewportHeight,\n containerFrame,\n });\n\n setPlacement(nextPlacement);\n setMaxHeight(nextMaxHeight);\n setStyle({\n position: fixed.position,\n left: fixed.left,\n zIndex: fixed.zIndex,\n ...(matchWidth ? { width: fixed.width } : null),\n ...(nextPlacement === 'below'\n ? { top: fixed.top, bottom: 'auto' }\n : { bottom: fixed.bottom, top: 'auto' }),\n });\n }, [\n anchorRef,\n contentRef,\n gap,\n matchWidth,\n maxHeightCap,\n portalContainer,\n preferredHeight,\n zIndex,\n ]);\n\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n update();\n\n function handle() {\n update();\n }\n\n window.addEventListener('resize', handle);\n // Capture phase so nested scroll containers (modals, RHS) are covered.\n document.addEventListener('scroll', handle, true);\n return () => {\n window.removeEventListener('resize', handle);\n document.removeEventListener('scroll', handle, true);\n };\n }, [isOpen, update]);\n\n // Re-measure after content mounts / changes size (calendar, long lists).\n useLayoutEffect(() => {\n if (!isOpen) return;\n const el = contentRef?.current ?? portalRef.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n\n const ro = new ResizeObserver(() => update());\n ro.observe(el);\n return () => ro.disconnect();\n }, [isOpen, contentRef, update]);\n\n const renderPortal = useCallback(\n (children: ReactNode) => {\n const mount = resolvePortalMount(portalContainer);\n if (!mount) return null;\n return createPortal(children, mount);\n },\n [portalContainer],\n );\n\n return {\n placement,\n maxHeight,\n style,\n portalRef,\n renderPortal,\n };\n}\n"],"names":["DEFAULT_PLACEMENT","resolvePortalMount","portalContainer","usesViewportFixedCoords","mount","useAnchoredPopupPortal","anchorRef","isOpen","options","preferredHeight","maxHeightCap","contentRef","zIndex","ANCHORED_POPUP_Z_INDEX","matchWidth","gap","ANCHORED_POPUP_GAP","portalRef","useRef","placement","setPlacement","useState","maxHeight","setMaxHeight","style","setStyle","update","useCallback","anchor","rect","viewportHeight","containerFrame","getAnchoredPopupContainerFrame","measured","_a","_b","heightForFlip","nextPlacement","nextMaxHeight","computeAnchoredPopupPlacement","fixed","computeAnchoredPopupFixedStyle","useLayoutEffect","handle","el","ro","renderPortal","children","createPortal"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react");function u(t,r,e){const l=t!==void 0,[s,c]=n.useState(r??!1);return[l?t:s,o=>{l||c(o.target.checked),e==null||e(o)}]}exports.useControllable=u;
|
|
2
|
-
//# sourceMappingURL=
|
|
2
|
+
//# sourceMappingURL=use-controllable.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-controllable.cjs","sources":["../../src/hooks/use-controllable.ts"],"sourcesContent":["import type { ChangeEvent } from 'react';\nimport { useState } from 'react';\n\n/**\n * Handles the controlled/uncontrolled pattern for boolean inputs (checkbox, radio, switch).\n *\n * - If `controlled` is provided (not undefined), the component is controlled and the\n * caller owns the value. Changes are forwarded to `onChange` only.\n * - If `controlled` is undefined, the component manages its own state, initialised\n * from `defaultValue`.\n *\n * Returns `[value, handleChange]`.\n */\nexport function useControllable(\n controlled: boolean | undefined,\n defaultValue: boolean | undefined,\n onChange?: (e: ChangeEvent<HTMLInputElement>) => void,\n): [boolean, (e: ChangeEvent<HTMLInputElement>) => void] {\n const isControlled = controlled !== undefined;\n const [uncontrolled, setUncontrolled] = useState(defaultValue ?? false);\n\n const value = isControlled ? controlled! : uncontrolled;\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) setUncontrolled(e.target.checked);\n onChange?.(e);\n };\n\n return [value, handleChange];\n}\n"],"names":["useControllable","controlled","defaultValue","onChange","isControlled","uncontrolled","setUncontrolled","useState","e"],"mappings":"yGAaO,SAASA,EACdC,EACAC,EACAC,EACuD,CACvD,MAAMC,EAAeH,IAAe,OAC9B,CAACI,EAAcC,CAAe,EAAIC,EAAAA,SAASL,GAAgB,EAAK,EAStE,MAAO,CAPOE,EAAeH,EAAcI,EAErBG,GAAqC,CACpDJ,GAAcE,EAAgBE,EAAE,OAAO,OAAO,EACnDL,GAAA,MAAAA,EAAWK,EACb,CAE2B,CAC7B"}
|
|
@@ -10,4 +10,4 @@ import { ChangeEvent } from 'react';
|
|
|
10
10
|
* Returns `[value, handleChange]`.
|
|
11
11
|
*/
|
|
12
12
|
export declare function useControllable(controlled: boolean | undefined, defaultValue: boolean | undefined, onChange?: (e: ChangeEvent<HTMLInputElement>) => void): [boolean, (e: ChangeEvent<HTMLInputElement>) => void];
|
|
13
|
-
//# sourceMappingURL=
|
|
13
|
+
//# sourceMappingURL=use-controllable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-controllable.d.ts","sourceRoot":"","sources":["../../src/hooks/use-controllable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAGzC;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,OAAO,GAAG,SAAS,EAC/B,YAAY,EAAE,OAAO,GAAG,SAAS,EACjC,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,GACpD,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC,CAYvD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"
|
|
1
|
+
{"version":3,"file":"use-controllable.js","sources":["../../src/hooks/use-controllable.ts"],"sourcesContent":["import type { ChangeEvent } from 'react';\nimport { useState } from 'react';\n\n/**\n * Handles the controlled/uncontrolled pattern for boolean inputs (checkbox, radio, switch).\n *\n * - If `controlled` is provided (not undefined), the component is controlled and the\n * caller owns the value. Changes are forwarded to `onChange` only.\n * - If `controlled` is undefined, the component manages its own state, initialised\n * from `defaultValue`.\n *\n * Returns `[value, handleChange]`.\n */\nexport function useControllable(\n controlled: boolean | undefined,\n defaultValue: boolean | undefined,\n onChange?: (e: ChangeEvent<HTMLInputElement>) => void,\n): [boolean, (e: ChangeEvent<HTMLInputElement>) => void] {\n const isControlled = controlled !== undefined;\n const [uncontrolled, setUncontrolled] = useState(defaultValue ?? false);\n\n const value = isControlled ? controlled! : uncontrolled;\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) setUncontrolled(e.target.checked);\n onChange?.(e);\n };\n\n return [value, handleChange];\n}\n"],"names":["useControllable","controlled","defaultValue","onChange","isControlled","uncontrolled","setUncontrolled","useState","e"],"mappings":";AAaO,SAASA,EACdC,GACAC,GACAC,GACuD;AACvD,QAAMC,IAAeH,MAAe,QAC9B,CAACI,GAAcC,CAAe,IAAIC,EAASL,KAAgB,EAAK;AAStE,SAAO,CAPOE,IAAeH,IAAcI,GAEtB,CAACG,MAAqC;AACzD,IAAKJ,KAAcE,EAAgBE,EAAE,OAAO,OAAO,GACnDL,KAAA,QAAAA,EAAWK;AAAA,EACb,CAE2B;AAC7B;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react");function a(e,r){const[t,s]=n.useState(e),[u,i]=n.useState(!1);return n.useEffect(()=>{if(e){s(!0),i(!1);return}if(!t)return;i(!0);const o=window.setTimeout(()=>{s(!1),i(!1)},r);return()=>window.clearTimeout(o)},[e,t,r]),{rendered:t,exiting:u}}exports.useExitAnimation=a;
|
|
2
|
-
//# sourceMappingURL=
|
|
2
|
+
//# sourceMappingURL=use-exit-animation.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-exit-animation.cjs","sources":["../../src/hooks/use-exit-animation.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\n/**\n * Keeps a panel mounted through its exit animation. While `open` is true the\n * panel renders normally. When `open` flips false, the panel keeps rendering\n * for `durationMs` with `exiting: true` so an exit animation can play before\n * the DOM node is removed.\n */\nexport function useExitAnimation(open: boolean, durationMs: number) {\n const [rendered, setRendered] = useState(open);\n const [exiting, setExiting] = useState(false);\n\n useEffect(() => {\n if (open) {\n setRendered(true);\n setExiting(false);\n return;\n }\n if (!rendered) return;\n setExiting(true);\n const t = window.setTimeout(() => {\n setRendered(false);\n setExiting(false);\n }, durationMs);\n return () => window.clearTimeout(t);\n }, [open, rendered, durationMs]);\n\n return { rendered, exiting };\n}\n"],"names":["useExitAnimation","open","durationMs","rendered","setRendered","useState","exiting","setExiting","useEffect","t"],"mappings":"yGAQO,SAASA,EAAiBC,EAAeC,EAAoB,CAClE,KAAM,CAACC,EAAUC,CAAW,EAAIC,EAAAA,SAASJ,CAAI,EACvC,CAACK,EAASC,CAAU,EAAIF,EAAAA,SAAS,EAAK,EAE5CG,OAAAA,EAAAA,UAAU,IAAM,CACd,GAAIP,EAAM,CACRG,EAAY,EAAI,EAChBG,EAAW,EAAK,EAChB,MACF,CACA,GAAI,CAACJ,EAAU,OACfI,EAAW,EAAI,EACf,MAAME,EAAI,OAAO,WAAW,IAAM,CAChCL,EAAY,EAAK,EACjBG,EAAW,EAAK,CAClB,EAAGL,CAAU,EACb,MAAO,IAAM,OAAO,aAAaO,CAAC,CACpC,EAAG,CAACR,EAAME,EAAUD,CAAU,CAAC,EAExB,CAAE,SAAAC,EAAU,QAAAG,CAAA,CACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-exit-animation.d.ts","sourceRoot":"","sources":["../../src/hooks/use-exit-animation.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM;;;EAoBjE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-exit-animation.js","sources":["../../src/hooks/use-exit-animation.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\n/**\n * Keeps a panel mounted through its exit animation. While `open` is true the\n * panel renders normally. When `open` flips false, the panel keeps rendering\n * for `durationMs` with `exiting: true` so an exit animation can play before\n * the DOM node is removed.\n */\nexport function useExitAnimation(open: boolean, durationMs: number) {\n const [rendered, setRendered] = useState(open);\n const [exiting, setExiting] = useState(false);\n\n useEffect(() => {\n if (open) {\n setRendered(true);\n setExiting(false);\n return;\n }\n if (!rendered) return;\n setExiting(true);\n const t = window.setTimeout(() => {\n setRendered(false);\n setExiting(false);\n }, durationMs);\n return () => window.clearTimeout(t);\n }, [open, rendered, durationMs]);\n\n return { rendered, exiting };\n}\n"],"names":["useExitAnimation","open","durationMs","rendered","setRendered","useState","exiting","setExiting","useEffect","t"],"mappings":";AAQO,SAASA,EAAiBC,GAAeC,GAAoB;AAClE,QAAM,CAACC,GAAUC,CAAW,IAAIC,EAASJ,CAAI,GACvC,CAACK,GAASC,CAAU,IAAIF,EAAS,EAAK;AAE5C,SAAAG,EAAU,MAAM;AACd,QAAIP,GAAM;AACR,MAAAG,EAAY,EAAI,GAChBG,EAAW,EAAK;AAChB;AAAA,IACF;AACA,QAAI,CAACJ,EAAU;AACf,IAAAI,EAAW,EAAI;AACf,UAAME,IAAI,OAAO,WAAW,MAAM;AAChC,MAAAL,EAAY,EAAK,GACjBG,EAAW,EAAK;AAAA,IAClB,GAAGL,CAAU;AACb,WAAO,MAAM,OAAO,aAAaO,CAAC;AAAA,EACpC,GAAG,CAACR,GAAME,GAAUD,CAAU,CAAC,GAExB,EAAE,UAAAC,GAAU,SAAAG,EAAA;AACrB;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react");function m(t,n,u,e){o.useEffect(()=>{if(!n)return;function r(d){var i,c;const s=d.target;(i=t.current)!=null&&i.contains(s)||(c=e==null?void 0:e.current)!=null&&c.contains(s)||u()}return document.addEventListener("mousedown",r),()=>document.removeEventListener("mousedown",r)},[t,e,n,u])}exports.useOutsideClose=m;
|
|
2
|
-
//# sourceMappingURL=
|
|
2
|
+
//# sourceMappingURL=use-outside-close.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-outside-close.cjs","sources":["../../src/hooks/use-outside-close.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport type { RefObject } from 'react';\n\ntype MaybeRef = RefObject<HTMLElement | null>;\n\n/**\n * Closes a dropdown or popover when the user mousedowns outside the container(s).\n * Listeners attach only while `open` is true.\n *\n * Pass `portalRef` when the popup is portaled outside `ref` so menu clicks\n * still count as inside.\n *\n * @param ref - Primary container (e.g. field root).\n * @param open - When true, the listener is active.\n * @param onClose - Called when a mousedown lands outside all containers.\n * @param portalRef - Optional portaled surface to treat as inside.\n */\nexport function useOutsideClose(\n ref: MaybeRef,\n open: boolean,\n onClose: () => void,\n portalRef?: MaybeRef,\n): void {\n useEffect(() => {\n if (!open) return;\n function handle(e: MouseEvent) {\n const target = e.target as Node;\n if (ref.current?.contains(target)) return;\n if (portalRef?.current?.contains(target)) return;\n onClose();\n }\n document.addEventListener('mousedown', handle);\n return () => document.removeEventListener('mousedown', handle);\n }, [ref, portalRef, open, onClose]);\n}\n"],"names":["useOutsideClose","ref","open","onClose","portalRef","useEffect","handle","e","target","_a","_b"],"mappings":"yGAiBO,SAASA,EACdC,EACAC,EACAC,EACAC,EACM,CACNC,EAAAA,UAAU,IAAM,CACd,GAAI,CAACH,EAAM,OACX,SAASI,EAAOC,EAAe,SAC7B,MAAMC,EAASD,EAAE,QACbE,EAAAR,EAAI,UAAJ,MAAAQ,EAAa,SAASD,KACtBE,EAAAN,GAAA,YAAAA,EAAW,UAAX,MAAAM,EAAoB,SAASF,IACjCL,EAAA,CACF,CACA,gBAAS,iBAAiB,YAAaG,CAAM,EACtC,IAAM,SAAS,oBAAoB,YAAaA,CAAM,CAC/D,EAAG,CAACL,EAAKG,EAAWF,EAAMC,CAAO,CAAC,CACpC"}
|
|
@@ -14,4 +14,4 @@ type MaybeRef = RefObject<HTMLElement | null>;
|
|
|
14
14
|
*/
|
|
15
15
|
export declare function useOutsideClose(ref: MaybeRef, open: boolean, onClose: () => void, portalRef?: MaybeRef): void;
|
|
16
16
|
export {};
|
|
17
|
-
//# sourceMappingURL=
|
|
17
|
+
//# sourceMappingURL=use-outside-close.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-outside-close.d.ts","sourceRoot":"","sources":["../../src/hooks/use-outside-close.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,KAAK,QAAQ,GAAG,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,IAAI,EACnB,SAAS,CAAC,EAAE,QAAQ,GACnB,IAAI,CAYN"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-outside-close.js","sources":["../../src/hooks/use-outside-close.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport type { RefObject } from 'react';\n\ntype MaybeRef = RefObject<HTMLElement | null>;\n\n/**\n * Closes a dropdown or popover when the user mousedowns outside the container(s).\n * Listeners attach only while `open` is true.\n *\n * Pass `portalRef` when the popup is portaled outside `ref` so menu clicks\n * still count as inside.\n *\n * @param ref - Primary container (e.g. field root).\n * @param open - When true, the listener is active.\n * @param onClose - Called when a mousedown lands outside all containers.\n * @param portalRef - Optional portaled surface to treat as inside.\n */\nexport function useOutsideClose(\n ref: MaybeRef,\n open: boolean,\n onClose: () => void,\n portalRef?: MaybeRef,\n): void {\n useEffect(() => {\n if (!open) return;\n function handle(e: MouseEvent) {\n const target = e.target as Node;\n if (ref.current?.contains(target)) return;\n if (portalRef?.current?.contains(target)) return;\n onClose();\n }\n document.addEventListener('mousedown', handle);\n return () => document.removeEventListener('mousedown', handle);\n }, [ref, portalRef, open, onClose]);\n}\n"],"names":["useOutsideClose","ref","open","onClose","portalRef","useEffect","handle","e","target","_a","_b"],"mappings":";AAiBO,SAASA,EACdC,GACAC,GACAC,GACAC,GACM;AACN,EAAAC,EAAU,MAAM;AACd,QAAI,CAACH,EAAM;AACX,aAASI,EAAOC,GAAe;;AAC7B,YAAMC,IAASD,EAAE;AACjB,OAAIE,IAAAR,EAAI,YAAJ,QAAAQ,EAAa,SAASD,OACtBE,IAAAN,KAAA,gBAAAA,EAAW,YAAX,QAAAM,EAAoB,SAASF,MACjCL,EAAA;AAAA,IACF;AACA,oBAAS,iBAAiB,aAAaG,CAAM,GACtC,MAAM,SAAS,oBAAoB,aAAaA,CAAM;AAAA,EAC/D,GAAG,CAACL,GAAKG,GAAWF,GAAMC,CAAO,CAAC;AACpC;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react"),o=150;function l(e){const[s,i]=n.useState(e),[a,r]=n.useState(!1);return n.useEffect(()=>{if(e){i(!0);let t=0;const c=requestAnimationFrame(()=>{t=requestAnimationFrame(()=>r(!0))});return()=>{cancelAnimationFrame(c),t&&cancelAnimationFrame(t)}}r(!1);const u=window.setTimeout(()=>i(!1),o);return()=>window.clearTimeout(u)},[e]),{mounted:s,visible:a}}exports.POPOVER_TRANSITION_MS=o;exports.usePopoverTransition=l;
|
|
2
|
-
//# sourceMappingURL=
|
|
2
|
+
//# sourceMappingURL=use-popover-transition.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-popover-transition.cjs","sources":["../../src/hooks/use-popover-transition.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\n// --duration-quick is 150ms; keep in sync if that token changes.\nexport const POPOVER_TRANSITION_MS = 150;\n\n/**\n * Keeps a popover mounted for the duration of its exit animation so the close\n * transition can play before React unmounts the node. See CLAUDE.md:\n * \"Animation: popover panel open/close\".\n */\nexport function usePopoverTransition(open: boolean) {\n const [mounted, setMounted] = useState(open);\n const [visible, setVisible] = useState(false);\n\n useEffect(() => {\n if (open) {\n setMounted(true);\n let raf2 = 0;\n const raf1 = requestAnimationFrame(() => {\n raf2 = requestAnimationFrame(() => setVisible(true));\n });\n return () => {\n cancelAnimationFrame(raf1);\n if (raf2) cancelAnimationFrame(raf2);\n };\n }\n setVisible(false);\n const t = window.setTimeout(() => setMounted(false), POPOVER_TRANSITION_MS);\n return () => window.clearTimeout(t);\n }, [open]);\n\n return { mounted, visible };\n}\n"],"names":["POPOVER_TRANSITION_MS","usePopoverTransition","open","mounted","setMounted","useState","visible","setVisible","useEffect","raf2","raf1","t"],"mappings":"yGAGaA,EAAwB,IAO9B,SAASC,EAAqBC,EAAe,CAClD,KAAM,CAACC,EAASC,CAAU,EAAIC,EAAAA,SAASH,CAAI,EACrC,CAACI,EAASC,CAAU,EAAIF,EAAAA,SAAS,EAAK,EAE5CG,OAAAA,EAAAA,UAAU,IAAM,CACd,GAAIN,EAAM,CACRE,EAAW,EAAI,EACf,IAAIK,EAAO,EACX,MAAMC,EAAO,sBAAsB,IAAM,CACvCD,EAAO,sBAAsB,IAAMF,EAAW,EAAI,CAAC,CACrD,CAAC,EACD,MAAO,IAAM,CACX,qBAAqBG,CAAI,EACrBD,wBAA2BA,CAAI,CACrC,CACF,CACAF,EAAW,EAAK,EAChB,MAAMI,EAAI,OAAO,WAAW,IAAMP,EAAW,EAAK,EAAGJ,CAAqB,EAC1E,MAAO,IAAM,OAAO,aAAaW,CAAC,CACpC,EAAG,CAACT,CAAI,CAAC,EAEF,CAAE,QAAAC,EAAS,QAAAG,CAAA,CACpB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-popover-transition.d.ts","sourceRoot":"","sources":["../../src/hooks/use-popover-transition.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO;;;EAsBjD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-popover-transition.js","sources":["../../src/hooks/use-popover-transition.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\n// --duration-quick is 150ms; keep in sync if that token changes.\nexport const POPOVER_TRANSITION_MS = 150;\n\n/**\n * Keeps a popover mounted for the duration of its exit animation so the close\n * transition can play before React unmounts the node. See CLAUDE.md:\n * \"Animation: popover panel open/close\".\n */\nexport function usePopoverTransition(open: boolean) {\n const [mounted, setMounted] = useState(open);\n const [visible, setVisible] = useState(false);\n\n useEffect(() => {\n if (open) {\n setMounted(true);\n let raf2 = 0;\n const raf1 = requestAnimationFrame(() => {\n raf2 = requestAnimationFrame(() => setVisible(true));\n });\n return () => {\n cancelAnimationFrame(raf1);\n if (raf2) cancelAnimationFrame(raf2);\n };\n }\n setVisible(false);\n const t = window.setTimeout(() => setMounted(false), POPOVER_TRANSITION_MS);\n return () => window.clearTimeout(t);\n }, [open]);\n\n return { mounted, visible };\n}\n"],"names":["POPOVER_TRANSITION_MS","usePopoverTransition","open","mounted","setMounted","useState","visible","setVisible","useEffect","raf2","raf1","t"],"mappings":";AAGO,MAAMA,IAAwB;AAO9B,SAASC,EAAqBC,GAAe;AAClD,QAAM,CAACC,GAASC,CAAU,IAAIC,EAASH,CAAI,GACrC,CAACI,GAASC,CAAU,IAAIF,EAAS,EAAK;AAE5C,SAAAG,EAAU,MAAM;AACd,QAAIN,GAAM;AACR,MAAAE,EAAW,EAAI;AACf,UAAIK,IAAO;AACX,YAAMC,IAAO,sBAAsB,MAAM;AACvC,QAAAD,IAAO,sBAAsB,MAAMF,EAAW,EAAI,CAAC;AAAA,MACrD,CAAC;AACD,aAAO,MAAM;AACX,6BAAqBG,CAAI,GACrBD,0BAA2BA,CAAI;AAAA,MACrC;AAAA,IACF;AACA,IAAAF,EAAW,EAAK;AAChB,UAAMI,IAAI,OAAO,WAAW,MAAMP,EAAW,EAAK,GAAGJ,CAAqB;AAC1E,WAAO,MAAM,OAAO,aAAaW,CAAC;AAAA,EACpC,GAAG,CAACT,CAAI,CAAC,GAEF,EAAE,SAAAC,GAAS,SAAAG,EAAA;AACpB;"}
|
package/dist/index.css
CHANGED
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
|
|
77
77
|
@charset "UTF-8";._message_1s7r2_3{display:flex;flex-direction:column;gap:var(--spacing-xs);padding:var(--spacing-xs) var(--spacing-xxl);background-color:var(--center-channel-bg);transition:background-color var(--duration-quick) var(--ease-transition)}._message_1s7r2_3:hover{background-color:color-mix(in srgb,var(--center-channel-color) 4%,var(--center-channel-bg))}._message--actions-visible_1s7r2_18 ._message__actions-slot_1s7r2_18{opacity:1;pointer-events:auto}._message--state-hover_1s7r2_25{background-color:color-mix(in srgb,var(--center-channel-color) 4%,var(--center-channel-bg))}._message--state-hover_1s7r2_25 ._message__actions-slot_1s7r2_18{opacity:1;pointer-events:auto}._message__pinned_1s7r2_32{flex-shrink:0;width:100%;min-width:0}._message__layout_1s7r2_37{display:flex;gap:var(--spacing-m);align-items:flex-start}._message__avatar-col_1s7r2_42{flex-shrink:0;display:flex;flex-direction:column;align-items:center}._message__content_1s7r2_48{display:flex;flex-direction:column;gap:var(--spacing-xxxs);flex:1;min-width:0}._message__header-row_1s7r2_55{position:relative;min-width:0}._message__header-block_1s7r2_59{min-width:0}._message__actions-slot_1s7r2_18{position:absolute;top:-16px;right:0;z-index:1;opacity:0;pointer-events:none;transition:opacity var(--duration-quick) var(--ease-transition)}._message_1s7r2_3:hover ._message__actions-slot_1s7r2_18,._message_1s7r2_3:focus-within ._message__actions-slot_1s7r2_18{opacity:1;pointer-events:auto}._message__body_1s7r2_75{display:flex;flex-direction:column;gap:var(--spacing-xs)}._message__body-text_1s7r2_83{font-family:var(--font-family-body);font-size:var(--font-size-100);line-height:var(--line-height-100);color:var(--center-channel-color);margin:0}._message__link-preview-slot_1s7r2_90{min-width:0}._message__footer-slot_1s7r2_93{display:flex;flex-direction:column;gap:var(--spacing-xs);min-width:0}._message__images-slot_1s7r2_99{position:relative;z-index:2;display:flex;flex-wrap:wrap;gap:var(--spacing-xs);min-width:0}._message__images-slot_1s7r2_99>*{flex:0 1 auto;align-self:flex-start;max-width:100%;min-width:0}
|
|
78
78
|
|
|
79
|
-
.
|
|
79
|
+
._modal_1wwq4_2{background-color:var(--center-channel-bg);border:1px solid rgba(var(--center-channel-color-rgb),.16);border-radius:var(--radius-l);box-shadow:var(--elevation-6);display:flex;flex-direction:column;overflow:hidden}._modal--size-small_1wwq4_11{width:600px}._modal--size-medium_1wwq4_14{width:704px}._modal--size-large_1wwq4_17{width:832px}._modal__header_1wwq4_20{display:flex;align-items:flex-start;gap:var(--spacing-s);padding:var(--spacing-xxl) var(--spacing-xxxl);border-bottom:1px solid rgba(var(--center-channel-color-rgb),.12);flex-shrink:0}._modal__header--no-divider_1wwq4_28{border-bottom:none;padding-bottom:0}._modal__header-inner_1wwq4_32{display:flex;align-items:center;gap:var(--spacing-m);flex:1;min-width:0;padding:var(--spacing-xxxxs) 0}._modal__title-group_1wwq4_40{display:flex;flex-direction:column;gap:var(--spacing-xxxs);min-width:0}._modal__title_1wwq4_40{font-family:var(--font-family-heading);font-size:var(--font-size-500);font-weight:var(--font-weight-semibold);line-height:var(--line-height-500);color:var(--center-channel-color);margin:0}._modal__subtitle_1wwq4_54{font-family:var(--font-family-body);font-size:var(--font-size-100);line-height:var(--line-height-200);color:rgba(var(--center-channel-color-rgb),.72);margin:0}._modal__close_1wwq4_61{margin-right:-12px;margin-top:-6px;margin-bottom:-6px}._modal__body_1wwq4_66{flex:1;min-height:0}._modal__body-inner_1wwq4_70{padding:28px var(--spacing-xxxl)}._modal__body-inner--menu_1wwq4_73{padding:var(--spacing-xs) var(--spacing-l)}._modal__footer_1wwq4_76{display:flex;align-items:center;justify-content:flex-end;gap:var(--spacing-xs);padding:var(--spacing-xxl) var(--spacing-xxxl);border-top:1px solid rgba(var(--center-channel-color-rgb),.12);flex-shrink:0}._modal__footer--no-divider_1wwq4_85{border-top:none;padding-top:0}
|
|
80
80
|
|
|
81
81
|
._more-unreads-banner_1fap4_2{display:inline-flex;flex-direction:row;align-items:center;gap:var(--spacing-s);padding:var(--spacing-xs) var(--spacing-m);background-color:var(--mention-bg);border:1px solid rgba(var(--center-channel-color-rgb),.08);border-radius:var(--radius-s);box-shadow:var(--elevation-1);cursor:pointer;transition:background-color var(--duration-quick) var(--ease-transition),box-shadow var(--duration-quick) var(--ease-transition)}._more-unreads-banner_1fap4_2:hover{background-color:rgba(var(--mention-bg-rgb),.92);box-shadow:var(--elevation-2)}._more-unreads-banner_1fap4_2:active{box-shadow:var(--elevation-1)}._more-unreads-banner_1fap4_2:focus-visible{outline:none;box-shadow:0 0 0 3px var(--center-channel-bg),0 0 0 5px var(--link-color)}._more-unreads-banner__icon_1fap4_26{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--mention-color)}._more-unreads-banner__label_1fap4_33{font-size:var(--font-size-75);font-weight:var(--font-weight-semibold);line-height:var(--line-height-75);color:var(--mention-color);white-space:nowrap}._more-unreads-banner--size-small_1fap4_40{padding:var(--spacing-xxs) var(--spacing-s)}._more-unreads-banner--size-small_1fap4_40 ._more-unreads-banner__label_1fap4_33{font-size:var(--font-size-75)}._more-unreads-banner--size-large_1fap4_46{padding:var(--spacing-s) var(--spacing-l)}._more-unreads-banner--size-large_1fap4_46 ._more-unreads-banner__label_1fap4_33{font-size:var(--font-size-100)}._more-unreads-banner--size-large_1fap4_46 ._more-unreads-banner__icon_1fap4_26 svg{width:var(--icon-size-16);height:var(--icon-size-16)}
|
|
82
82
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,98 +1,98 @@
|
|
|
1
|
-
export { default as ActionButton } from './components/
|
|
2
|
-
export type * from './components/
|
|
3
|
-
export * from './components/
|
|
4
|
-
export * from './components/
|
|
5
|
-
export * from './components/
|
|
6
|
-
export * from './components/
|
|
7
|
-
export * from './components/
|
|
8
|
-
export * from './components/
|
|
9
|
-
export * from './components/
|
|
10
|
-
export * from './components/
|
|
11
|
-
export * from './components/
|
|
12
|
-
export * from './components/
|
|
13
|
-
export * from './components/
|
|
14
|
-
export * from './components/
|
|
15
|
-
export * from './components/
|
|
16
|
-
export * from './components/
|
|
17
|
-
export * from './components/
|
|
18
|
-
export * from './components/
|
|
19
|
-
export * from './components/
|
|
20
|
-
export * from './components/
|
|
21
|
-
export * from './components/
|
|
22
|
-
export { default as Divider } from './components/
|
|
23
|
-
export type * from './components/
|
|
24
|
-
export * from './components/
|
|
25
|
-
export * from './components/
|
|
26
|
-
export * from './components/
|
|
27
|
-
export * from './components/
|
|
28
|
-
export * from './components/
|
|
29
|
-
export * from './components/
|
|
30
|
-
export * from './components/
|
|
31
|
-
export * from './components/
|
|
32
|
-
export * from './components/
|
|
33
|
-
export * from './components/
|
|
34
|
-
export * from './components/
|
|
35
|
-
export * from './components/
|
|
36
|
-
export * from './components/
|
|
37
|
-
export * from './components/
|
|
38
|
-
export * from './components/
|
|
39
|
-
export * from './components/
|
|
40
|
-
export { default as Message } from './components/
|
|
41
|
-
export type * from './components/
|
|
42
|
-
export * from './components/
|
|
43
|
-
export { default as MessageHeader } from './components/
|
|
44
|
-
export type * from './components/
|
|
45
|
-
export * from './components/
|
|
46
|
-
export * from './components/
|
|
47
|
-
export * from './components/
|
|
48
|
-
export * from './components/
|
|
49
|
-
export * from './components/
|
|
50
|
-
export * from './components/
|
|
51
|
-
export * from './components/
|
|
52
|
-
export * from './components/
|
|
53
|
-
export * from './components/
|
|
54
|
-
export * from './components/
|
|
55
|
-
export * from './components/
|
|
56
|
-
export * from './components/
|
|
57
|
-
export * from './components/
|
|
58
|
-
export * from './components/
|
|
59
|
-
export { default as ProfilePopover } from './components/
|
|
60
|
-
export type * from './components/
|
|
61
|
-
export * from './components/
|
|
62
|
-
export * from './components/
|
|
63
|
-
export * from './components/
|
|
64
|
-
export * from './components/
|
|
65
|
-
export * from './components/
|
|
66
|
-
export * from './components/
|
|
67
|
-
export * from './components/
|
|
68
|
-
export * from './components/
|
|
69
|
-
export * from './components/
|
|
70
|
-
export * from './components/
|
|
71
|
-
export { default as Spinner } from './components/
|
|
72
|
-
export type * from './components/
|
|
73
|
-
export * from './components/
|
|
74
|
-
export * from './components/
|
|
75
|
-
export * from './components/
|
|
76
|
-
export * from './components/
|
|
77
|
-
export * from './components/
|
|
78
|
-
export * from './components/
|
|
79
|
-
export * from './components/
|
|
80
|
-
export * from './components/
|
|
81
|
-
export * from './components/
|
|
82
|
-
export * from './components/
|
|
83
|
-
export * from './components/
|
|
84
|
-
export * from './components/
|
|
85
|
-
export * from './components/
|
|
86
|
-
export * from './components/
|
|
87
|
-
export * from './components/
|
|
88
|
-
export * from './components/
|
|
89
|
-
export * from './components/
|
|
90
|
-
export * from './hooks/
|
|
91
|
-
export * from './hooks/
|
|
92
|
-
export * from './hooks/
|
|
93
|
-
export * from './hooks/
|
|
1
|
+
export { default as ActionButton } from './components/action-button/ActionButton';
|
|
2
|
+
export type * from './components/action-button/ActionButton';
|
|
3
|
+
export * from './components/admin-console-header/index';
|
|
4
|
+
export * from './components/admin-console-sidebar/index';
|
|
5
|
+
export * from './components/admin-panel/index';
|
|
6
|
+
export * from './components/admin-panel-footer/index';
|
|
7
|
+
export * from './components/admin-panel-header/index';
|
|
8
|
+
export * from './components/app-bar-item/index';
|
|
9
|
+
export * from './components/attachment-card/index';
|
|
10
|
+
export * from './components/button/index';
|
|
11
|
+
export * from './components/channel-header/index';
|
|
12
|
+
export * from './components/channel-header-menu/index';
|
|
13
|
+
export * from './components/channel-info-msg-header/index';
|
|
14
|
+
export * from './components/channel-menu/index';
|
|
15
|
+
export * from './components/channel-category-menu/index';
|
|
16
|
+
export * from './components/channel-sidebar-item/index';
|
|
17
|
+
export * from './components/channels-sidebar/index';
|
|
18
|
+
export * from './components/checkbox/index';
|
|
19
|
+
export * from './components/chip/index';
|
|
20
|
+
export * from './components/combobox/index';
|
|
21
|
+
export * from './components/date-range-picker/index';
|
|
22
|
+
export { default as Divider } from './components/divider/Divider';
|
|
23
|
+
export type * from './components/divider/Divider';
|
|
24
|
+
export * from './components/dropdown/index';
|
|
25
|
+
export * from './components/emoji/index';
|
|
26
|
+
export * from './components/empty-state/index';
|
|
27
|
+
export * from './components/error-message/index';
|
|
28
|
+
export * from './components/feature-discovery-panel/index';
|
|
29
|
+
export * from './components/global-banner/index';
|
|
30
|
+
export * from './components/global-header/index';
|
|
31
|
+
export * from './components/help-menu/index';
|
|
32
|
+
export * from './components/icon/index';
|
|
33
|
+
export * from './components/icon-button/index';
|
|
34
|
+
export * from './components/illustration/index';
|
|
35
|
+
export * from './components/image-preview/index';
|
|
36
|
+
export * from './components/tag/index';
|
|
37
|
+
export * from './components/link-preview/index';
|
|
38
|
+
export * from './components/mention-badge/index';
|
|
39
|
+
export * from './components/menu-item/index';
|
|
40
|
+
export { default as Message } from './components/message/Message';
|
|
41
|
+
export type * from './components/message/Message';
|
|
42
|
+
export * from './components/message-actions/index';
|
|
43
|
+
export { default as MessageHeader } from './components/message-header/MessageHeader';
|
|
44
|
+
export type * from './components/message-header/MessageHeader';
|
|
45
|
+
export * from './components/message-input/index';
|
|
46
|
+
export * from './components/message-more-options-menu/index';
|
|
47
|
+
export * from './components/message-reactions/index';
|
|
48
|
+
export * from './components/message-separator/index';
|
|
49
|
+
export * from './components/modal/index';
|
|
50
|
+
export * from './components/more-unreads-banner/index';
|
|
51
|
+
export * from './components/new-message-banner/index';
|
|
52
|
+
export * from './components/pagination-dots/index';
|
|
53
|
+
export * from './components/permalink-preview/index';
|
|
54
|
+
export * from './components/pinned-saved-indicators/index';
|
|
55
|
+
export * from './components/plus-menu/index';
|
|
56
|
+
export * from './components/popover-menu/index';
|
|
57
|
+
export * from './components/popover-notice/index';
|
|
58
|
+
export * from './components/product-switcher-menu/index';
|
|
59
|
+
export { default as ProfilePopover } from './components/profile-popover/ProfilePopover';
|
|
60
|
+
export type * from './components/profile-popover/ProfilePopover';
|
|
61
|
+
export * from './components/progress-bar/index';
|
|
62
|
+
export * from './components/radio/index';
|
|
63
|
+
export * from './components/reaction-pill/index';
|
|
64
|
+
export * from './components/right-sidebar/index';
|
|
65
|
+
export * from './components/scrollbar/index';
|
|
66
|
+
export * from './components/search-input/index';
|
|
67
|
+
export * from './components/search-tip-banner/index';
|
|
68
|
+
export * from './components/shortcut-tag/index';
|
|
69
|
+
export * from './components/section-notice/index';
|
|
70
|
+
export * from './components/select/index';
|
|
71
|
+
export { default as Spinner } from './components/spinner/Spinner';
|
|
72
|
+
export type * from './components/spinner/Spinner';
|
|
73
|
+
export * from './components/status-badge/index';
|
|
74
|
+
export * from './components/switch/index';
|
|
75
|
+
export * from './components/tabs/index';
|
|
76
|
+
export * from './components/team-avatar/index';
|
|
77
|
+
export * from './components/team-menu/index';
|
|
78
|
+
export * from './components/team-sidebar/index';
|
|
79
|
+
export * from './components/text-area/index';
|
|
80
|
+
export * from './components/text-input/index';
|
|
81
|
+
export * from './components/thread-actions-menu/index';
|
|
82
|
+
export * from './components/thread-footer/index';
|
|
83
|
+
export * from './components/thread-list-item/index';
|
|
84
|
+
export * from './components/toast/index';
|
|
85
|
+
export * from './components/tooltip/index';
|
|
86
|
+
export * from './components/tour-point/index';
|
|
87
|
+
export * from './components/unread-badge/index';
|
|
88
|
+
export * from './components/user-avatar/index';
|
|
89
|
+
export * from './components/user-avatar-group/index';
|
|
90
|
+
export * from './hooks/use-controllable';
|
|
91
|
+
export * from './hooks/use-exit-animation';
|
|
92
|
+
export * from './hooks/use-outside-close';
|
|
93
|
+
export * from './hooks/use-popover-transition';
|
|
94
94
|
export { toKebab } from './utils/string';
|
|
95
|
-
export { default as btnStyles } from './components/
|
|
96
|
-
export { default as messageStyles } from './components/
|
|
97
|
-
export { default as channelsSidebarStyles } from './components/
|
|
95
|
+
export { default as btnStyles } from './components/button/Button.module.scss';
|
|
96
|
+
export { default as messageStyles } from './components/message/Message.module.scss';
|
|
97
|
+
export { default as channelsSidebarStyles } from './components/channels-sidebar/ChannelsSidebar.module.scss';
|
|
98
98
|
//# sourceMappingURL=index.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mattermost/compass-ui",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.4",
|
|
4
4
|
"description": "Compass design system UI components for Mattermost products",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -16,24 +16,24 @@
|
|
|
16
16
|
"types": "./dist/index.d.ts",
|
|
17
17
|
"exports": {
|
|
18
18
|
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
19
20
|
"import": "./dist/index.js",
|
|
20
|
-
"require": "./dist/index.cjs"
|
|
21
|
-
"types": "./dist/index.d.ts"
|
|
21
|
+
"require": "./dist/index.cjs"
|
|
22
22
|
},
|
|
23
23
|
"./components/*": {
|
|
24
|
+
"types": "./dist/components/*/index.d.ts",
|
|
24
25
|
"import": "./dist/components/*/index.js",
|
|
25
|
-
"require": "./dist/components/*/index.cjs"
|
|
26
|
-
"types": "./dist/components/*/index.d.ts"
|
|
26
|
+
"require": "./dist/components/*/index.cjs"
|
|
27
27
|
},
|
|
28
28
|
"./hooks/*": {
|
|
29
|
+
"types": "./dist/hooks/*.d.ts",
|
|
29
30
|
"import": "./dist/hooks/*.js",
|
|
30
|
-
"require": "./dist/hooks/*.cjs"
|
|
31
|
-
"types": "./dist/hooks/*.d.ts"
|
|
31
|
+
"require": "./dist/hooks/*.cjs"
|
|
32
32
|
},
|
|
33
33
|
"./utils/string": {
|
|
34
|
+
"types": "./dist/utils/string.d.ts",
|
|
34
35
|
"import": "./dist/utils/string.js",
|
|
35
|
-
"require": "./dist/utils/string.cjs"
|
|
36
|
-
"types": "./dist/utils/string.d.ts"
|
|
36
|
+
"require": "./dist/utils/string.cjs"
|
|
37
37
|
},
|
|
38
38
|
"./styles": {
|
|
39
39
|
"import": "./dist/compass-ui.css",
|
|
@@ -98,9 +98,6 @@
|
|
|
98
98
|
},
|
|
99
99
|
"typesVersions": {
|
|
100
100
|
">=3.1": {
|
|
101
|
-
"*": [
|
|
102
|
-
"./dist/index.d.ts"
|
|
103
|
-
],
|
|
104
101
|
"components/*": [
|
|
105
102
|
"./dist/components/*/index.d.ts"
|
|
106
103
|
],
|
|
@@ -373,6 +370,9 @@
|
|
|
373
370
|
],
|
|
374
371
|
"hooks/use-popover-transition": [
|
|
375
372
|
"./dist/hooks/use-popover-transition.d.ts"
|
|
373
|
+
],
|
|
374
|
+
"*": [
|
|
375
|
+
"./dist/index.d.ts"
|
|
376
376
|
]
|
|
377
377
|
}
|
|
378
378
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useAnchoredPopupPortal.cjs","sources":["../../src/hooks/use-anchored-popup-portal.ts"],"sourcesContent":["import {\n useCallback,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n type RefObject,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n ANCHORED_POPUP_GAP,\n ANCHORED_POPUP_Z_INDEX,\n computeAnchoredPopupFixedStyle,\n computeAnchoredPopupPlacement,\n getAnchoredPopupContainerFrame,\n type PopupPlacement,\n} from '@/utils/anchoredPopupPlacement';\n\nexport interface UseAnchoredPopupPortalOptions {\n /** Height used for the flip decision when content isn’t measured yet. */\n preferredHeight: number;\n /** Cap for scrollable menus (Select/Combobox). Omit for intrinsic panels. */\n maxHeightCap?: number;\n /** Ref to the portaled panel for measuring intrinsic height (DateRangePicker). */\n contentRef?: RefObject<HTMLElement | null>;\n /**\n * Portal mount node; defaults to `document.body` with viewport-fixed coords.\n * Custom containers must establish a positioning context (`position` other\n * than `static`); coords are converted to that container’s space.\n */\n portalContainer?: HTMLElement | null;\n zIndex?: number;\n /**\n * When true (default), fixed width matches the trigger.\n * DateRangePicker sets false and keeps its CSS width.\n */\n matchWidth?: boolean;\n gap?: number;\n}\n\nexport interface UseAnchoredPopupPortalResult {\n placement: PopupPlacement;\n maxHeight: number;\n style: CSSProperties;\n /** Ref for the portaled surface — pass to `useOutsideClose` as a second root. */\n portalRef: RefObject<HTMLDivElement | null>;\n /** Wraps children in a portal to `portalContainer` or `document.body`. */\n renderPortal: (children: ReactNode) => ReactNode;\n}\n\nconst DEFAULT_PLACEMENT: PopupPlacement = 'below';\n\nfunction resolvePortalMount(\n portalContainer: HTMLElement | null | undefined,\n): HTMLElement | null {\n if (typeof document === 'undefined') return null;\n return portalContainer ?? document.body;\n}\n\nfunction usesViewportFixedCoords(mount: HTMLElement): boolean {\n return mount === document.body;\n}\n\n/**\n * Positions a form-widget popup in a portal with viewport-aware above/below flip.\n * Internal to compass-ui form widgets — not a general overlay positioning API.\n */\nexport function useAnchoredPopupPortal(\n anchorRef: RefObject<HTMLElement | null>,\n isOpen: boolean,\n options: UseAnchoredPopupPortalOptions,\n): UseAnchoredPopupPortalResult {\n const {\n preferredHeight,\n maxHeightCap,\n contentRef,\n portalContainer = null,\n zIndex = ANCHORED_POPUP_Z_INDEX,\n matchWidth = true,\n gap = ANCHORED_POPUP_GAP,\n } = options;\n\n const portalRef = useRef<HTMLDivElement | null>(null);\n const [placement, setPlacement] = useState<PopupPlacement>(DEFAULT_PLACEMENT);\n const [maxHeight, setMaxHeight] = useState(\n maxHeightCap ?? preferredHeight,\n );\n const [style, setStyle] = useState<CSSProperties>({\n position: 'fixed',\n top: 0,\n left: 0,\n width: matchWidth ? 0 : undefined,\n zIndex,\n });\n\n const update = useCallback(() => {\n const anchor = anchorRef.current;\n if (!anchor) return;\n\n const mount = resolvePortalMount(portalContainer);\n if (!mount) return;\n\n const rect = anchor.getBoundingClientRect();\n const viewportHeight = window.innerHeight;\n const viewportFixed = usesViewportFixedCoords(mount);\n const containerFrame = viewportFixed\n ? undefined\n : getAnchoredPopupContainerFrame(mount);\n\n const measured =\n contentRef?.current?.offsetHeight ??\n portalRef.current?.offsetHeight ??\n 0;\n const heightForFlip = measured > 0 ? measured : preferredHeight;\n\n const { placement: nextPlacement, maxHeight: nextMaxHeight } =\n computeAnchoredPopupPlacement(rect, viewportHeight, {\n gap,\n preferredHeight: heightForFlip,\n maxHeightCap,\n bounds: containerFrame?.bounds,\n });\n\n const fixed = computeAnchoredPopupFixedStyle(rect, nextPlacement, {\n gap,\n zIndex,\n width: matchWidth ? rect.width : undefined,\n viewportHeight,\n containerFrame,\n });\n\n setPlacement(nextPlacement);\n setMaxHeight(nextMaxHeight);\n setStyle({\n position: fixed.position,\n left: fixed.left,\n zIndex: fixed.zIndex,\n ...(matchWidth ? { width: fixed.width } : null),\n ...(nextPlacement === 'below'\n ? { top: fixed.top, bottom: 'auto' }\n : { bottom: fixed.bottom, top: 'auto' }),\n });\n }, [\n anchorRef,\n contentRef,\n gap,\n matchWidth,\n maxHeightCap,\n portalContainer,\n preferredHeight,\n zIndex,\n ]);\n\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n update();\n\n function handle() {\n update();\n }\n\n window.addEventListener('resize', handle);\n // Capture phase so nested scroll containers (modals, RHS) are covered.\n document.addEventListener('scroll', handle, true);\n return () => {\n window.removeEventListener('resize', handle);\n document.removeEventListener('scroll', handle, true);\n };\n }, [isOpen, update]);\n\n // Re-measure after content mounts / changes size (calendar, long lists).\n useLayoutEffect(() => {\n if (!isOpen) return;\n const el = contentRef?.current ?? portalRef.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n\n const ro = new ResizeObserver(() => update());\n ro.observe(el);\n return () => ro.disconnect();\n }, [isOpen, contentRef, update]);\n\n const renderPortal = useCallback(\n (children: ReactNode) => {\n const mount = resolvePortalMount(portalContainer);\n if (!mount) return null;\n return createPortal(children, mount);\n },\n [portalContainer],\n );\n\n return {\n placement,\n maxHeight,\n style,\n portalRef,\n renderPortal,\n };\n}\n"],"names":["DEFAULT_PLACEMENT","resolvePortalMount","portalContainer","usesViewportFixedCoords","mount","useAnchoredPopupPortal","anchorRef","isOpen","options","preferredHeight","maxHeightCap","contentRef","zIndex","ANCHORED_POPUP_Z_INDEX","matchWidth","gap","ANCHORED_POPUP_GAP","portalRef","useRef","placement","setPlacement","useState","maxHeight","setMaxHeight","style","setStyle","update","useCallback","anchor","rect","viewportHeight","containerFrame","getAnchoredPopupContainerFrame","measured","_a","_b","heightForFlip","nextPlacement","nextMaxHeight","computeAnchoredPopupPlacement","fixed","computeAnchoredPopupFixedStyle","useLayoutEffect","handle","el","ro","renderPortal","children","createPortal"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useAnchoredPopupPortal.d.ts","sourceRoot":"","sources":["../../src/hooks/use-anchored-popup-portal.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,gCAAgC,CAAC;AAExC,MAAM,WAAW,6BAA6B;IAC5C,yEAAyE;IACzE,eAAe,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,UAAU,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC3C;;;;OAIG;IACH,eAAe,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,4BAA4B;IAC3C,SAAS,EAAE,cAAc,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,aAAa,CAAC;IACrB,iFAAiF;IACjF,SAAS,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC5C,0EAA0E;IAC1E,YAAY,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,SAAS,CAAC;CAClD;AAeD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EACxC,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,6BAA6B,GACrC,4BAA4B,CA+H9B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useAnchoredPopupPortal.js","sources":["../../src/hooks/use-anchored-popup-portal.ts"],"sourcesContent":["import {\n useCallback,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n type RefObject,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n ANCHORED_POPUP_GAP,\n ANCHORED_POPUP_Z_INDEX,\n computeAnchoredPopupFixedStyle,\n computeAnchoredPopupPlacement,\n getAnchoredPopupContainerFrame,\n type PopupPlacement,\n} from '@/utils/anchoredPopupPlacement';\n\nexport interface UseAnchoredPopupPortalOptions {\n /** Height used for the flip decision when content isn’t measured yet. */\n preferredHeight: number;\n /** Cap for scrollable menus (Select/Combobox). Omit for intrinsic panels. */\n maxHeightCap?: number;\n /** Ref to the portaled panel for measuring intrinsic height (DateRangePicker). */\n contentRef?: RefObject<HTMLElement | null>;\n /**\n * Portal mount node; defaults to `document.body` with viewport-fixed coords.\n * Custom containers must establish a positioning context (`position` other\n * than `static`); coords are converted to that container’s space.\n */\n portalContainer?: HTMLElement | null;\n zIndex?: number;\n /**\n * When true (default), fixed width matches the trigger.\n * DateRangePicker sets false and keeps its CSS width.\n */\n matchWidth?: boolean;\n gap?: number;\n}\n\nexport interface UseAnchoredPopupPortalResult {\n placement: PopupPlacement;\n maxHeight: number;\n style: CSSProperties;\n /** Ref for the portaled surface — pass to `useOutsideClose` as a second root. */\n portalRef: RefObject<HTMLDivElement | null>;\n /** Wraps children in a portal to `portalContainer` or `document.body`. */\n renderPortal: (children: ReactNode) => ReactNode;\n}\n\nconst DEFAULT_PLACEMENT: PopupPlacement = 'below';\n\nfunction resolvePortalMount(\n portalContainer: HTMLElement | null | undefined,\n): HTMLElement | null {\n if (typeof document === 'undefined') return null;\n return portalContainer ?? document.body;\n}\n\nfunction usesViewportFixedCoords(mount: HTMLElement): boolean {\n return mount === document.body;\n}\n\n/**\n * Positions a form-widget popup in a portal with viewport-aware above/below flip.\n * Internal to compass-ui form widgets — not a general overlay positioning API.\n */\nexport function useAnchoredPopupPortal(\n anchorRef: RefObject<HTMLElement | null>,\n isOpen: boolean,\n options: UseAnchoredPopupPortalOptions,\n): UseAnchoredPopupPortalResult {\n const {\n preferredHeight,\n maxHeightCap,\n contentRef,\n portalContainer = null,\n zIndex = ANCHORED_POPUP_Z_INDEX,\n matchWidth = true,\n gap = ANCHORED_POPUP_GAP,\n } = options;\n\n const portalRef = useRef<HTMLDivElement | null>(null);\n const [placement, setPlacement] = useState<PopupPlacement>(DEFAULT_PLACEMENT);\n const [maxHeight, setMaxHeight] = useState(\n maxHeightCap ?? preferredHeight,\n );\n const [style, setStyle] = useState<CSSProperties>({\n position: 'fixed',\n top: 0,\n left: 0,\n width: matchWidth ? 0 : undefined,\n zIndex,\n });\n\n const update = useCallback(() => {\n const anchor = anchorRef.current;\n if (!anchor) return;\n\n const mount = resolvePortalMount(portalContainer);\n if (!mount) return;\n\n const rect = anchor.getBoundingClientRect();\n const viewportHeight = window.innerHeight;\n const viewportFixed = usesViewportFixedCoords(mount);\n const containerFrame = viewportFixed\n ? undefined\n : getAnchoredPopupContainerFrame(mount);\n\n const measured =\n contentRef?.current?.offsetHeight ??\n portalRef.current?.offsetHeight ??\n 0;\n const heightForFlip = measured > 0 ? measured : preferredHeight;\n\n const { placement: nextPlacement, maxHeight: nextMaxHeight } =\n computeAnchoredPopupPlacement(rect, viewportHeight, {\n gap,\n preferredHeight: heightForFlip,\n maxHeightCap,\n bounds: containerFrame?.bounds,\n });\n\n const fixed = computeAnchoredPopupFixedStyle(rect, nextPlacement, {\n gap,\n zIndex,\n width: matchWidth ? rect.width : undefined,\n viewportHeight,\n containerFrame,\n });\n\n setPlacement(nextPlacement);\n setMaxHeight(nextMaxHeight);\n setStyle({\n position: fixed.position,\n left: fixed.left,\n zIndex: fixed.zIndex,\n ...(matchWidth ? { width: fixed.width } : null),\n ...(nextPlacement === 'below'\n ? { top: fixed.top, bottom: 'auto' }\n : { bottom: fixed.bottom, top: 'auto' }),\n });\n }, [\n anchorRef,\n contentRef,\n gap,\n matchWidth,\n maxHeightCap,\n portalContainer,\n preferredHeight,\n zIndex,\n ]);\n\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n update();\n\n function handle() {\n update();\n }\n\n window.addEventListener('resize', handle);\n // Capture phase so nested scroll containers (modals, RHS) are covered.\n document.addEventListener('scroll', handle, true);\n return () => {\n window.removeEventListener('resize', handle);\n document.removeEventListener('scroll', handle, true);\n };\n }, [isOpen, update]);\n\n // Re-measure after content mounts / changes size (calendar, long lists).\n useLayoutEffect(() => {\n if (!isOpen) return;\n const el = contentRef?.current ?? portalRef.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n\n const ro = new ResizeObserver(() => update());\n ro.observe(el);\n return () => ro.disconnect();\n }, [isOpen, contentRef, update]);\n\n const renderPortal = useCallback(\n (children: ReactNode) => {\n const mount = resolvePortalMount(portalContainer);\n if (!mount) return null;\n return createPortal(children, mount);\n },\n [portalContainer],\n );\n\n return {\n placement,\n maxHeight,\n style,\n portalRef,\n renderPortal,\n };\n}\n"],"names":["DEFAULT_PLACEMENT","resolvePortalMount","portalContainer","usesViewportFixedCoords","mount","useAnchoredPopupPortal","anchorRef","isOpen","options","preferredHeight","maxHeightCap","contentRef","zIndex","ANCHORED_POPUP_Z_INDEX","matchWidth","gap","ANCHORED_POPUP_GAP","portalRef","useRef","placement","setPlacement","useState","maxHeight","setMaxHeight","style","setStyle","update","useCallback","anchor","rect","viewportHeight","containerFrame","getAnchoredPopupContainerFrame","measured","_a","_b","heightForFlip","nextPlacement","nextMaxHeight","computeAnchoredPopupPlacement","fixed","computeAnchoredPopupFixedStyle","useLayoutEffect","handle","el","ro","renderPortal","children","createPortal"],"mappings":";;;AAmDA,MAAMA,IAAoC;AAE1C,SAASC,EACPC,GACoB;AACpB,SAAI,OAAO,WAAa,MAAoB,OACrCA,KAAmB,SAAS;AACrC;AAEA,SAASC,EAAwBC,GAA6B;AAC5D,SAAOA,MAAU,SAAS;AAC5B;AAMO,SAASC,EACdC,GACAC,GACAC,GAC8B;AAC9B,QAAM;AAAA,IACJ,iBAAAC;AAAA,IACA,cAAAC;AAAA,IACA,YAAAC;AAAA,IACA,iBAAAT,IAAkB;AAAA,IAClB,QAAAU,IAASC;AAAA,IACT,YAAAC,IAAa;AAAA,IACb,KAAAC,IAAMC;AAAA,EAAA,IACJR,GAEES,IAAYC,EAA8B,IAAI,GAC9C,CAACC,GAAWC,CAAY,IAAIC,EAAyBrB,CAAiB,GACtE,CAACsB,GAAWC,CAAY,IAAIF;AAAA,IAChCX,KAAgBD;AAAA,EAAA,GAEZ,CAACe,GAAOC,CAAQ,IAAIJ,EAAwB;AAAA,IAChD,UAAU;AAAA,IACV,KAAK;AAAA,IACL,MAAM;AAAA,IACN,OAAOP,IAAa,IAAI;AAAA,IACxB,QAAAF;AAAA,EAAA,CACD,GAEKc,IAASC,EAAY,MAAM;;AAC/B,UAAMC,IAAStB,EAAU;AACzB,QAAI,CAACsB,EAAQ;AAEb,UAAMxB,IAAQH,EAAmBC,CAAe;AAChD,QAAI,CAACE,EAAO;AAEZ,UAAMyB,IAAOD,EAAO,sBAAA,GACdE,IAAiB,OAAO,aAExBC,IADgB5B,EAAwBC,CAAK,IAE/C,SACA4B,EAA+B5B,CAAK,GAElC6B,MACJC,IAAAvB,KAAA,gBAAAA,EAAY,YAAZ,gBAAAuB,EAAqB,mBACrBC,IAAAlB,EAAU,YAAV,gBAAAkB,EAAmB,iBACnB,GACIC,IAAgBH,IAAW,IAAIA,IAAWxB,GAE1C,EAAE,WAAW4B,GAAe,WAAWC,MAC3CC,EAA8BV,GAAMC,GAAgB;AAAA,MAClD,KAAAf;AAAA,MACA,iBAAiBqB;AAAA,MACjB,cAAA1B;AAAA,MACA,QAAQqB,KAAA,gBAAAA,EAAgB;AAAA,IAAA,CACzB,GAEGS,IAAQC,EAA+BZ,GAAMQ,GAAe;AAAA,MAChE,KAAAtB;AAAA,MACA,QAAAH;AAAA,MACA,OAAOE,IAAae,EAAK,QAAQ;AAAA,MACjC,gBAAAC;AAAA,MACA,gBAAAC;AAAA,IAAA,CACD;AAED,IAAAX,EAAaiB,CAAa,GAC1Bd,EAAae,CAAa,GAC1Bb,EAAS;AAAA,MACP,UAAUe,EAAM;AAAA,MAChB,MAAMA,EAAM;AAAA,MACZ,QAAQA,EAAM;AAAA,MACd,GAAI1B,IAAa,EAAE,OAAO0B,EAAM,UAAU;AAAA,MAC1C,GAAIH,MAAkB,UAClB,EAAE,KAAKG,EAAM,KAAK,QAAQ,OAAA,IAC1B,EAAE,QAAQA,EAAM,QAAQ,KAAK,OAAA;AAAA,IAAO,CACzC;AAAA,EACH,GAAG;AAAA,IACDlC;AAAA,IACAK;AAAA,IACAI;AAAA,IACAD;AAAA,IACAJ;AAAA,IACAR;AAAA,IACAO;AAAA,IACAG;AAAA,EAAA,CACD;AAED,EAAA8B,EAAgB,MAAM;AACpB,QAAI,CAACnC,EAAQ;AAEb,IAAAmB,EAAA;AAEA,aAASiB,IAAS;AAChB,MAAAjB,EAAA;AAAA,IACF;AAEA,kBAAO,iBAAiB,UAAUiB,CAAM,GAExC,SAAS,iBAAiB,UAAUA,GAAQ,EAAI,GACzC,MAAM;AACX,aAAO,oBAAoB,UAAUA,CAAM,GAC3C,SAAS,oBAAoB,UAAUA,GAAQ,EAAI;AAAA,IACrD;AAAA,EACF,GAAG,CAACpC,GAAQmB,CAAM,CAAC,GAGnBgB,EAAgB,MAAM;AACpB,QAAI,CAACnC,EAAQ;AACb,UAAMqC,KAAKjC,KAAA,gBAAAA,EAAY,YAAWM,EAAU;AAC5C,QAAI,CAAC2B,KAAM,OAAO,iBAAmB,IAAa;AAElD,UAAMC,IAAK,IAAI,eAAe,MAAMnB,GAAQ;AAC5C,WAAAmB,EAAG,QAAQD,CAAE,GACN,MAAMC,EAAG,WAAA;AAAA,EAClB,GAAG,CAACtC,GAAQI,GAAYe,CAAM,CAAC;AAE/B,QAAMoB,IAAenB;AAAA,IACnB,CAACoB,MAAwB;AACvB,YAAM3C,IAAQH,EAAmBC,CAAe;AAChD,aAAKE,IACE4C,EAAaD,GAAU3C,CAAK,IADhB;AAAA,IAErB;AAAA,IACA,CAACF,CAAe;AAAA,EAAA;AAGlB,SAAO;AAAA,IACL,WAAAiB;AAAA,IACA,WAAAG;AAAA,IACA,OAAAE;AAAA,IACA,WAAAP;AAAA,IACA,cAAA6B;AAAA,EAAA;AAEJ;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useControllable.d.ts","sourceRoot":"","sources":["../../src/hooks/use-controllable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAGzC;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,OAAO,GAAG,SAAS,EAC/B,YAAY,EAAE,OAAO,GAAG,SAAS,EACjC,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,GACpD,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC,CAYvD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useControllable.js","sources":["../../src/hooks/use-controllable.ts"],"sourcesContent":["import type { ChangeEvent } from 'react';\nimport { useState } from 'react';\n\n/**\n * Handles the controlled/uncontrolled pattern for boolean inputs (checkbox, radio, switch).\n *\n * - If `controlled` is provided (not undefined), the component is controlled and the\n * caller owns the value. Changes are forwarded to `onChange` only.\n * - If `controlled` is undefined, the component manages its own state, initialised\n * from `defaultValue`.\n *\n * Returns `[value, handleChange]`.\n */\nexport function useControllable(\n controlled: boolean | undefined,\n defaultValue: boolean | undefined,\n onChange?: (e: ChangeEvent<HTMLInputElement>) => void,\n): [boolean, (e: ChangeEvent<HTMLInputElement>) => void] {\n const isControlled = controlled !== undefined;\n const [uncontrolled, setUncontrolled] = useState(defaultValue ?? false);\n\n const value = isControlled ? controlled! : uncontrolled;\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) setUncontrolled(e.target.checked);\n onChange?.(e);\n };\n\n return [value, handleChange];\n}\n"],"names":["useControllable","controlled","defaultValue","onChange","isControlled","uncontrolled","setUncontrolled","useState","e"],"mappings":";AAaO,SAASA,EACdC,GACAC,GACAC,GACuD;AACvD,QAAMC,IAAeH,MAAe,QAC9B,CAACI,GAAcC,CAAe,IAAIC,EAASL,KAAgB,EAAK;AAStE,SAAO,CAPOE,IAAeH,IAAcI,GAEtB,CAACG,MAAqC;AACzD,IAAKJ,KAAcE,EAAgBE,EAAE,OAAO,OAAO,GACnDL,KAAA,QAAAA,EAAWK;AAAA,EACb,CAE2B;AAC7B;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useExitAnimation.cjs","sources":["../../src/hooks/use-exit-animation.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\n/**\n * Keeps a panel mounted through its exit animation. While `open` is true the\n * panel renders normally. When `open` flips false, the panel keeps rendering\n * for `durationMs` with `exiting: true` so an exit animation can play before\n * the DOM node is removed.\n */\nexport function useExitAnimation(open: boolean, durationMs: number) {\n const [rendered, setRendered] = useState(open);\n const [exiting, setExiting] = useState(false);\n\n useEffect(() => {\n if (open) {\n setRendered(true);\n setExiting(false);\n return;\n }\n if (!rendered) return;\n setExiting(true);\n const t = window.setTimeout(() => {\n setRendered(false);\n setExiting(false);\n }, durationMs);\n return () => window.clearTimeout(t);\n }, [open, rendered, durationMs]);\n\n return { rendered, exiting };\n}\n"],"names":["useExitAnimation","open","durationMs","rendered","setRendered","useState","exiting","setExiting","useEffect","t"],"mappings":"yGAQO,SAASA,EAAiBC,EAAeC,EAAoB,CAClE,KAAM,CAACC,EAAUC,CAAW,EAAIC,EAAAA,SAASJ,CAAI,EACvC,CAACK,EAASC,CAAU,EAAIF,EAAAA,SAAS,EAAK,EAE5CG,OAAAA,EAAAA,UAAU,IAAM,CACd,GAAIP,EAAM,CACRG,EAAY,EAAI,EAChBG,EAAW,EAAK,EAChB,MACF,CACA,GAAI,CAACJ,EAAU,OACfI,EAAW,EAAI,EACf,MAAME,EAAI,OAAO,WAAW,IAAM,CAChCL,EAAY,EAAK,EACjBG,EAAW,EAAK,CAClB,EAAGL,CAAU,EACb,MAAO,IAAM,OAAO,aAAaO,CAAC,CACpC,EAAG,CAACR,EAAME,EAAUD,CAAU,CAAC,EAExB,CAAE,SAAAC,EAAU,QAAAG,CAAA,CACrB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useExitAnimation.d.ts","sourceRoot":"","sources":["../../src/hooks/use-exit-animation.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM;;;EAoBjE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useExitAnimation.js","sources":["../../src/hooks/use-exit-animation.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\n/**\n * Keeps a panel mounted through its exit animation. While `open` is true the\n * panel renders normally. When `open` flips false, the panel keeps rendering\n * for `durationMs` with `exiting: true` so an exit animation can play before\n * the DOM node is removed.\n */\nexport function useExitAnimation(open: boolean, durationMs: number) {\n const [rendered, setRendered] = useState(open);\n const [exiting, setExiting] = useState(false);\n\n useEffect(() => {\n if (open) {\n setRendered(true);\n setExiting(false);\n return;\n }\n if (!rendered) return;\n setExiting(true);\n const t = window.setTimeout(() => {\n setRendered(false);\n setExiting(false);\n }, durationMs);\n return () => window.clearTimeout(t);\n }, [open, rendered, durationMs]);\n\n return { rendered, exiting };\n}\n"],"names":["useExitAnimation","open","durationMs","rendered","setRendered","useState","exiting","setExiting","useEffect","t"],"mappings":";AAQO,SAASA,EAAiBC,GAAeC,GAAoB;AAClE,QAAM,CAACC,GAAUC,CAAW,IAAIC,EAASJ,CAAI,GACvC,CAACK,GAASC,CAAU,IAAIF,EAAS,EAAK;AAE5C,SAAAG,EAAU,MAAM;AACd,QAAIP,GAAM;AACR,MAAAG,EAAY,EAAI,GAChBG,EAAW,EAAK;AAChB;AAAA,IACF;AACA,QAAI,CAACJ,EAAU;AACf,IAAAI,EAAW,EAAI;AACf,UAAME,IAAI,OAAO,WAAW,MAAM;AAChC,MAAAL,EAAY,EAAK,GACjBG,EAAW,EAAK;AAAA,IAClB,GAAGL,CAAU;AACb,WAAO,MAAM,OAAO,aAAaO,CAAC;AAAA,EACpC,GAAG,CAACR,GAAME,GAAUD,CAAU,CAAC,GAExB,EAAE,UAAAC,GAAU,SAAAG,EAAA;AACrB;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useOutsideClose.cjs","sources":["../../src/hooks/use-outside-close.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport type { RefObject } from 'react';\n\ntype MaybeRef = RefObject<HTMLElement | null>;\n\n/**\n * Closes a dropdown or popover when the user mousedowns outside the container(s).\n * Listeners attach only while `open` is true.\n *\n * Pass `portalRef` when the popup is portaled outside `ref` so menu clicks\n * still count as inside.\n *\n * @param ref - Primary container (e.g. field root).\n * @param open - When true, the listener is active.\n * @param onClose - Called when a mousedown lands outside all containers.\n * @param portalRef - Optional portaled surface to treat as inside.\n */\nexport function useOutsideClose(\n ref: MaybeRef,\n open: boolean,\n onClose: () => void,\n portalRef?: MaybeRef,\n): void {\n useEffect(() => {\n if (!open) return;\n function handle(e: MouseEvent) {\n const target = e.target as Node;\n if (ref.current?.contains(target)) return;\n if (portalRef?.current?.contains(target)) return;\n onClose();\n }\n document.addEventListener('mousedown', handle);\n return () => document.removeEventListener('mousedown', handle);\n }, [ref, portalRef, open, onClose]);\n}\n"],"names":["useOutsideClose","ref","open","onClose","portalRef","useEffect","handle","e","target","_a","_b"],"mappings":"yGAiBO,SAASA,EACdC,EACAC,EACAC,EACAC,EACM,CACNC,EAAAA,UAAU,IAAM,CACd,GAAI,CAACH,EAAM,OACX,SAASI,EAAOC,EAAe,SAC7B,MAAMC,EAASD,EAAE,QACbE,EAAAR,EAAI,UAAJ,MAAAQ,EAAa,SAASD,KACtBE,EAAAN,GAAA,YAAAA,EAAW,UAAX,MAAAM,EAAoB,SAASF,IACjCL,EAAA,CACF,CACA,gBAAS,iBAAiB,YAAaG,CAAM,EACtC,IAAM,SAAS,oBAAoB,YAAaA,CAAM,CAC/D,EAAG,CAACL,EAAKG,EAAWF,EAAMC,CAAO,CAAC,CACpC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useOutsideClose.d.ts","sourceRoot":"","sources":["../../src/hooks/use-outside-close.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,KAAK,QAAQ,GAAG,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,IAAI,EACnB,SAAS,CAAC,EAAE,QAAQ,GACnB,IAAI,CAYN"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useOutsideClose.js","sources":["../../src/hooks/use-outside-close.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport type { RefObject } from 'react';\n\ntype MaybeRef = RefObject<HTMLElement | null>;\n\n/**\n * Closes a dropdown or popover when the user mousedowns outside the container(s).\n * Listeners attach only while `open` is true.\n *\n * Pass `portalRef` when the popup is portaled outside `ref` so menu clicks\n * still count as inside.\n *\n * @param ref - Primary container (e.g. field root).\n * @param open - When true, the listener is active.\n * @param onClose - Called when a mousedown lands outside all containers.\n * @param portalRef - Optional portaled surface to treat as inside.\n */\nexport function useOutsideClose(\n ref: MaybeRef,\n open: boolean,\n onClose: () => void,\n portalRef?: MaybeRef,\n): void {\n useEffect(() => {\n if (!open) return;\n function handle(e: MouseEvent) {\n const target = e.target as Node;\n if (ref.current?.contains(target)) return;\n if (portalRef?.current?.contains(target)) return;\n onClose();\n }\n document.addEventListener('mousedown', handle);\n return () => document.removeEventListener('mousedown', handle);\n }, [ref, portalRef, open, onClose]);\n}\n"],"names":["useOutsideClose","ref","open","onClose","portalRef","useEffect","handle","e","target","_a","_b"],"mappings":";AAiBO,SAASA,EACdC,GACAC,GACAC,GACAC,GACM;AACN,EAAAC,EAAU,MAAM;AACd,QAAI,CAACH,EAAM;AACX,aAASI,EAAOC,GAAe;;AAC7B,YAAMC,IAASD,EAAE;AACjB,OAAIE,IAAAR,EAAI,YAAJ,QAAAQ,EAAa,SAASD,OACtBE,IAAAN,KAAA,gBAAAA,EAAW,YAAX,QAAAM,EAAoB,SAASF,MACjCL,EAAA;AAAA,IACF;AACA,oBAAS,iBAAiB,aAAaG,CAAM,GACtC,MAAM,SAAS,oBAAoB,aAAaA,CAAM;AAAA,EAC/D,GAAG,CAACL,GAAKG,GAAWF,GAAMC,CAAO,CAAC;AACpC;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"usePopoverTransition.cjs","sources":["../../src/hooks/use-popover-transition.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\n// --duration-quick is 150ms; keep in sync if that token changes.\nexport const POPOVER_TRANSITION_MS = 150;\n\n/**\n * Keeps a popover mounted for the duration of its exit animation so the close\n * transition can play before React unmounts the node. See CLAUDE.md:\n * \"Animation: popover panel open/close\".\n */\nexport function usePopoverTransition(open: boolean) {\n const [mounted, setMounted] = useState(open);\n const [visible, setVisible] = useState(false);\n\n useEffect(() => {\n if (open) {\n setMounted(true);\n let raf2 = 0;\n const raf1 = requestAnimationFrame(() => {\n raf2 = requestAnimationFrame(() => setVisible(true));\n });\n return () => {\n cancelAnimationFrame(raf1);\n if (raf2) cancelAnimationFrame(raf2);\n };\n }\n setVisible(false);\n const t = window.setTimeout(() => setMounted(false), POPOVER_TRANSITION_MS);\n return () => window.clearTimeout(t);\n }, [open]);\n\n return { mounted, visible };\n}\n"],"names":["POPOVER_TRANSITION_MS","usePopoverTransition","open","mounted","setMounted","useState","visible","setVisible","useEffect","raf2","raf1","t"],"mappings":"yGAGaA,EAAwB,IAO9B,SAASC,EAAqBC,EAAe,CAClD,KAAM,CAACC,EAASC,CAAU,EAAIC,EAAAA,SAASH,CAAI,EACrC,CAACI,EAASC,CAAU,EAAIF,EAAAA,SAAS,EAAK,EAE5CG,OAAAA,EAAAA,UAAU,IAAM,CACd,GAAIN,EAAM,CACRE,EAAW,EAAI,EACf,IAAIK,EAAO,EACX,MAAMC,EAAO,sBAAsB,IAAM,CACvCD,EAAO,sBAAsB,IAAMF,EAAW,EAAI,CAAC,CACrD,CAAC,EACD,MAAO,IAAM,CACX,qBAAqBG,CAAI,EACrBD,wBAA2BA,CAAI,CACrC,CACF,CACAF,EAAW,EAAK,EAChB,MAAMI,EAAI,OAAO,WAAW,IAAMP,EAAW,EAAK,EAAGJ,CAAqB,EAC1E,MAAO,IAAM,OAAO,aAAaW,CAAC,CACpC,EAAG,CAACT,CAAI,CAAC,EAEF,CAAE,QAAAC,EAAS,QAAAG,CAAA,CACpB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"usePopoverTransition.d.ts","sourceRoot":"","sources":["../../src/hooks/use-popover-transition.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO;;;EAsBjD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"usePopoverTransition.js","sources":["../../src/hooks/use-popover-transition.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\n// --duration-quick is 150ms; keep in sync if that token changes.\nexport const POPOVER_TRANSITION_MS = 150;\n\n/**\n * Keeps a popover mounted for the duration of its exit animation so the close\n * transition can play before React unmounts the node. See CLAUDE.md:\n * \"Animation: popover panel open/close\".\n */\nexport function usePopoverTransition(open: boolean) {\n const [mounted, setMounted] = useState(open);\n const [visible, setVisible] = useState(false);\n\n useEffect(() => {\n if (open) {\n setMounted(true);\n let raf2 = 0;\n const raf1 = requestAnimationFrame(() => {\n raf2 = requestAnimationFrame(() => setVisible(true));\n });\n return () => {\n cancelAnimationFrame(raf1);\n if (raf2) cancelAnimationFrame(raf2);\n };\n }\n setVisible(false);\n const t = window.setTimeout(() => setMounted(false), POPOVER_TRANSITION_MS);\n return () => window.clearTimeout(t);\n }, [open]);\n\n return { mounted, visible };\n}\n"],"names":["POPOVER_TRANSITION_MS","usePopoverTransition","open","mounted","setMounted","useState","visible","setVisible","useEffect","raf2","raf1","t"],"mappings":";AAGO,MAAMA,IAAwB;AAO9B,SAASC,EAAqBC,GAAe;AAClD,QAAM,CAACC,GAASC,CAAU,IAAIC,EAASH,CAAI,GACrC,CAACI,GAASC,CAAU,IAAIF,EAAS,EAAK;AAE5C,SAAAG,EAAU,MAAM;AACd,QAAIN,GAAM;AACR,MAAAE,EAAW,EAAI;AACf,UAAIK,IAAO;AACX,YAAMC,IAAO,sBAAsB,MAAM;AACvC,QAAAD,IAAO,sBAAsB,MAAMF,EAAW,EAAI,CAAC;AAAA,MACrD,CAAC;AACD,aAAO,MAAM;AACX,6BAAqBG,CAAI,GACrBD,0BAA2BA,CAAI;AAAA,MACrC;AAAA,IACF;AACA,IAAAF,EAAW,EAAK;AAChB,UAAMI,IAAI,OAAO,WAAW,MAAMP,EAAW,EAAK,GAAGJ,CAAqB;AAC1E,WAAO,MAAM,OAAO,aAAaW,CAAC;AAAA,EACpC,GAAG,CAACT,CAAI,CAAC,GAEF,EAAE,SAAAC,GAAS,SAAAG,EAAA;AACpB;"}
|