@vector-im/compound-web 7.6.3 → 7.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ChatFilter/ChatFilter.cjs +22 -0
- package/dist/components/ChatFilter/ChatFilter.cjs.map +1 -0
- package/dist/components/ChatFilter/ChatFilter.d.ts +14 -0
- package/dist/components/ChatFilter/ChatFilter.d.ts.map +1 -0
- package/dist/components/ChatFilter/ChatFilter.js +22 -0
- package/dist/components/ChatFilter/ChatFilter.js.map +1 -0
- package/dist/components/ChatFilter/ChatFilter.module.css.cjs +7 -0
- package/dist/components/ChatFilter/ChatFilter.module.css.cjs.map +1 -0
- package/dist/components/ChatFilter/ChatFilter.module.css.js +7 -0
- package/dist/components/ChatFilter/ChatFilter.module.css.js.map +1 -0
- package/dist/components/ChatFilter/index.d.ts +2 -0
- package/dist/components/ChatFilter/index.d.ts.map +1 -0
- package/dist/components/Menu/CheckboxMenuItem.d.ts +23 -0
- package/dist/components/Menu/CheckboxMenuItem.d.ts.map +1 -0
- package/dist/components/Menu/FloatingMenu.cjs +2 -3
- package/dist/components/Menu/FloatingMenu.cjs.map +1 -1
- package/dist/components/Menu/FloatingMenu.d.ts.map +1 -1
- package/dist/components/Menu/FloatingMenu.js +2 -3
- package/dist/components/Menu/FloatingMenu.js.map +1 -1
- package/dist/components/Menu/FloatingMenu.module.css.cjs +2 -2
- package/dist/components/Menu/FloatingMenu.module.css.js +2 -2
- package/dist/components/Menu/MenuItem.cjs +2 -1
- package/dist/components/Menu/MenuItem.cjs.map +1 -1
- package/dist/components/Menu/MenuItem.d.ts +11 -2
- package/dist/components/Menu/MenuItem.d.ts.map +1 -1
- package/dist/components/Menu/MenuItem.js +2 -1
- package/dist/components/Menu/MenuItem.js.map +1 -1
- package/dist/components/Menu/MenuTitle.cjs +16 -0
- package/dist/components/Menu/MenuTitle.cjs.map +1 -0
- package/dist/components/Menu/MenuTitle.d.ts +18 -0
- package/dist/components/Menu/MenuTitle.d.ts.map +1 -0
- package/dist/components/Menu/MenuTitle.js +16 -0
- package/dist/components/Menu/MenuTitle.js.map +1 -0
- package/dist/components/Menu/MenuTitle.module.css.cjs +7 -0
- package/dist/components/Menu/MenuTitle.module.css.cjs.map +1 -0
- package/dist/components/Menu/MenuTitle.module.css.js +7 -0
- package/dist/components/Menu/MenuTitle.module.css.js.map +1 -0
- package/dist/components/Menu/ToggleMenuItem.cjs +2 -1
- package/dist/components/Menu/ToggleMenuItem.cjs.map +1 -1
- package/dist/components/Menu/ToggleMenuItem.d.ts +3 -1
- package/dist/components/Menu/ToggleMenuItem.d.ts.map +1 -1
- package/dist/components/Menu/ToggleMenuItem.js +2 -1
- package/dist/components/Menu/ToggleMenuItem.js.map +1 -1
- package/dist/components/Tooltip/Tooltip.cjs +6 -1
- package/dist/components/Tooltip/Tooltip.cjs.map +1 -1
- package/dist/components/Tooltip/Tooltip.js +6 -1
- package/dist/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/style.css +59 -15
- package/package.json +1 -1
- package/src/components/ChatFilter/ChatFilter.module.css +33 -0
- package/src/components/ChatFilter/ChatFilter.tsx +41 -0
- package/src/components/ChatFilter/index.ts +8 -0
- package/src/components/Menu/CheckboxMenuItem.tsx +62 -0
- package/src/components/Menu/FloatingMenu.module.css +2 -5
- package/src/components/Menu/FloatingMenu.tsx +4 -13
- package/src/components/Menu/MenuItem.tsx +12 -2
- package/src/components/Menu/MenuTitle.module.css +14 -0
- package/src/components/Menu/MenuTitle.tsx +40 -0
- package/src/components/Menu/ToggleMenuItem.tsx +3 -2
- package/src/components/Tooltip/Tooltip.tsx +6 -1
- package/src/index.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.cjs","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["/*\nCopyright 2023, 2024 New Vector Ltd.\n\nSPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial\nPlease see LICENSE files in the repository root for full details.\n*/\n\nimport { TooltipContext, useTooltipContext } from \"./TooltipContext\";\nimport {\n FloatingArrow,\n FloatingPortal,\n useMergeRefs,\n} from \"@floating-ui/react\";\nimport React, {\n PropsWithChildren,\n Ref,\n JSX,\n isValidElement,\n cloneElement,\n useMemo,\n ReactNode,\n FC,\n ReactElement,\n} from \"react\";\n\nimport classNames from \"classnames\";\nimport styles from \"./Tooltip.module.css\";\nimport {\n CommonUseTooltipProps,\n TooltipDescription,\n TooltipLabel,\n useTooltip,\n} from \"./useTooltip\";\n\n// Unfortunately Omit doesn't distribute nicely over sum types, so we have to\n// piece together the useTooltip options type by hand\ntype TooltipProps = Omit<CommonUseTooltipProps, \"isTriggerInteractive\"> &\n (TooltipLabel | TooltipDescription) & {\n /**\n * Whether the trigger element is interactive.\n * When trigger is interactive:\n * - tooltip will be shown after a 300ms delay.\n * When trigger is not interactive:\n * - tooltip will be shown instantly when pointer enters trigger.\n * - trigger will be wrapped in a span with a tab index from prop nonInteractiveTriggerTabIndex\n * @default true\n */\n isTriggerInteractive?: boolean;\n /**\n * The tab index for the non interactive trigger.\n * @default 0\n */\n nonInteractiveTriggerTabIndex?: number;\n };\n\nconst hasLabel = (\n props: TooltipLabel | TooltipDescription,\n): props is TooltipLabel => \"label\" in props && !!props.label;\n\n/**\n * A tooltip component\n */\nexport function Tooltip({\n children,\n isTriggerInteractive = true,\n nonInteractiveTriggerTabIndex = 0,\n ...props\n}: PropsWithChildren<TooltipProps>): JSX.Element {\n const context = useTooltip({ isTriggerInteractive, ...props });\n\n return (\n <TooltipContext.Provider value={context}>\n <TooltipAnchor\n isTriggerInteractive={isTriggerInteractive}\n nonInteractiveTriggerTabIndex={nonInteractiveTriggerTabIndex}\n >\n {children}\n </TooltipAnchor>\n <TooltipContent>\n <span id={context.labelId}>\n {hasLabel(props) ? props.label : props.description}\n </span>\n <Caption />\n </TooltipContent>\n </TooltipContext.Provider>\n );\n}\n\nfunction Caption() {\n const { caption, captionId } = useTooltipContext();\n if (!caption) return null;\n\n const isCaptionString = typeof caption === \"string\";\n const Container = isCaptionString ? \"span\" : \"div\";\n\n /**\n * Forcing dark theme, so that we have the correct contrast when\n * using the text color secondary on a solid dark background.\n * This is temporary and should only remain until we figure out\n * the approach to on-solid tokens\n **/\n return (\n <Container\n id={captionId}\n className={classNames(styles.caption, \"cpd-theme-dark\")}\n >\n {caption}\n </Container>\n );\n}\n\n/**\n * The content of the tooltip\n * @param children\n */\nfunction TooltipContent({\n children,\n}: Readonly<PropsWithChildren>): JSX.Element | null {\n const {\n context: floatingContext,\n open,\n arrowRef,\n purpose,\n ...rest\n } = useTooltipContext();\n\n // Label tooltips are kept in the DOM even when not visually open\n if (!open && purpose !== \"label\") return null;\n\n return (\n <FloatingPortal>\n <div\n ref={rest.refs.setFloating}\n style={rest.floatingStyles}\n {...rest.tooltipProps}\n {...rest.getFloatingProps()}\n className={classNames(styles.tooltip, {\n [styles.invisible]: purpose === \"label\" && !open,\n })}\n >\n <FloatingArrow\n ref={arrowRef}\n context={floatingContext}\n // design absolute value\n width={10}\n height={6}\n className={styles.arrow}\n />\n {children}\n </div>\n </FloatingPortal>\n );\n}\n\ninterface TooltipAnchorProps {\n children: ReactNode;\n isTriggerInteractive: boolean;\n nonInteractiveTriggerTabIndex?: number;\n}\n\n/**\n * The anchor of the tooltip\n * @param children\n */\nconst TooltipAnchor: FC<TooltipAnchorProps> = ({\n children,\n isTriggerInteractive,\n nonInteractiveTriggerTabIndex,\n}) => {\n const context = useTooltipContext();\n\n // The children can have a ref and we don't want to discard it\n // Doing a dirty cast to get the optional ref\n const childrenRef = (children as unknown as { ref?: Ref<HTMLElement> })?.ref;\n const ref = useMergeRefs([context.refs.setReference, childrenRef]);\n\n const element = useMemo(() => {\n if (!isValidElement(children)) return;\n\n if (isTriggerInteractive) {\n const props = context.getReferenceProps({ ref });\n return cloneElement(children, props);\n } else {\n // For a non-interactive trigger, we want most of the props to go on the\n // span element that we provide, since that's what receives focus, but it\n // should still be the trigger that receives the label/description. It\n // would be wrong to label the span element, as it lacks a role.\n const props = context.getReferenceProps({\n ref,\n tabIndex: nonInteractiveTriggerTabIndex,\n });\n const {\n \"aria-labelledby\": labelId,\n \"aria-describedby\": descriptionId,\n ...spanProps\n } = props;\n return (\n <span tabIndex={nonInteractiveTriggerTabIndex} {...spanProps}>\n {cloneElement(children as ReactElement<Record<string, unknown>>, {\n \"aria-labelledby\": labelId,\n \"aria-describedby\": descriptionId,\n })}\n </span>\n );\n }\n }, [context, ref, children]);\n\n if (!element) {\n throw new Error(\"Tooltip anchor must be a single valid React element\");\n }\n\n return element;\n};\n"],"names":["useTooltip","jsxs","TooltipContext","jsx","useTooltipContext","styles","FloatingPortal","FloatingArrow","useMergeRefs","useMemo","isValidElement","cloneElement"],"mappings":";;;;;;;;;AAuDA,MAAM,WAAW,CACf,UAC0B,WAAW,SAAS,CAAC,CAAC,MAAM;AAKjD,SAAS,QAAQ;AAAA,EACtB;AAAA,EACA,uBAAuB;AAAA,EACvB,gCAAgC;AAAA,EAChC,GAAG;AACL,GAAiD;AAC/C,QAAM,UAAUA,WAAW,WAAA,EAAE,sBAAsB,GAAG,OAAO;AAE7D,SACGC,2BAAAA,KAAAC,eAAAA,eAAe,UAAf,EAAwB,OAAO,SAC9B,UAAA;AAAA,IAAAC,2BAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QAEC;AAAA,MAAA;AAAA,IACH;AAAA,oCACC,gBACC,EAAA,UAAA;AAAA,MAACA,2BAAAA,IAAA,QAAA,EAAK,IAAI,QAAQ,SACf,UAAA,SAAS,KAAK,IAAI,MAAM,QAAQ,MAAM,YACzC,CAAA;AAAA,qCACC,SAAQ,CAAA,CAAA;AAAA,IAAA,EACX,CAAA;AAAA,EAAA,GACF;AAEJ;AAEA,SAAS,UAAU;AACjB,QAAM,EAAE,SAAS,UAAU,IAAIC,iCAAkB;AAC7C,MAAA,CAAC,QAAgB,QAAA;AAEf,QAAA,kBAAkB,OAAO,YAAY;AACrC,QAAA,YAAY,kBAAkB,SAAS;AAS3C,SAAAD,2BAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,IAAI;AAAA,MACJ,WAAW,WAAWE,uBAAO,SAAS,gBAAgB;AAAA,MAErD,UAAA;AAAA,IAAA;AAAA,EACH;AAEJ;AAMA,SAAS,eAAe;AAAA,EACtB;AACF,GAAoD;AAC5C,QAAA;AAAA,IACJ,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,MACDD,iCAAkB;AAGtB,MAAI,CAAC,QAAQ,YAAY,QAAgB,QAAA;AAEzC,wCACGE,MAAAA,gBACC,EAAA,UAAAL,2BAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK,KAAK,KAAK;AAAA,MACf,OAAO,KAAK;AAAA,MACX,GAAG,KAAK;AAAA,MACR,GAAG,KAAK,iBAAiB;AAAA,MAC1B,WAAW,WAAWI,eAAA,QAAO,SAAS;AAAA,QACpC,CAACA,uBAAO,SAAS,GAAG,YAAY,WAAW,CAAC;AAAA,MAAA,CAC7C;AAAA,MAED,UAAA;AAAA,QAAAF,2BAAA;AAAA,UAACI,MAAA;AAAA,UAAA;AAAA,YACC,KAAK;AAAA,YACL,SAAS;AAAA,YAET,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,WAAWF,eAAAA,QAAO;AAAA,UAAA;AAAA,QACpB;AAAA,QACC;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAEL;AAEJ;AAYA,MAAM,gBAAwC,CAAC;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,UAAUD,eAAAA,kBAAkB;AAIlC,QAAM,cAAe,UAAoD;AACzE,QAAM,MAAMI,MAAAA,aAAa,CAAC,QAAQ,KAAK,cAAc,WAAW,CAAC;AAE3D,QAAA,UAAUC,MAAAA,QAAQ,MAAM;AACxB,QAAA,CAACC,MAAAA,eAAe,QAAQ,EAAG;AAE/B,QAAI,sBAAsB;
|
|
1
|
+
{"version":3,"file":"Tooltip.cjs","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["/*\nCopyright 2023, 2024 New Vector Ltd.\n\nSPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial\nPlease see LICENSE files in the repository root for full details.\n*/\n\nimport { TooltipContext, useTooltipContext } from \"./TooltipContext\";\nimport {\n FloatingArrow,\n FloatingPortal,\n useMergeRefs,\n} from \"@floating-ui/react\";\nimport React, {\n PropsWithChildren,\n Ref,\n JSX,\n isValidElement,\n cloneElement,\n useMemo,\n ReactNode,\n FC,\n ReactElement,\n} from \"react\";\n\nimport classNames from \"classnames\";\nimport styles from \"./Tooltip.module.css\";\nimport {\n CommonUseTooltipProps,\n TooltipDescription,\n TooltipLabel,\n useTooltip,\n} from \"./useTooltip\";\n\n// Unfortunately Omit doesn't distribute nicely over sum types, so we have to\n// piece together the useTooltip options type by hand\ntype TooltipProps = Omit<CommonUseTooltipProps, \"isTriggerInteractive\"> &\n (TooltipLabel | TooltipDescription) & {\n /**\n * Whether the trigger element is interactive.\n * When trigger is interactive:\n * - tooltip will be shown after a 300ms delay.\n * When trigger is not interactive:\n * - tooltip will be shown instantly when pointer enters trigger.\n * - trigger will be wrapped in a span with a tab index from prop nonInteractiveTriggerTabIndex\n * @default true\n */\n isTriggerInteractive?: boolean;\n /**\n * The tab index for the non interactive trigger.\n * @default 0\n */\n nonInteractiveTriggerTabIndex?: number;\n };\n\nconst hasLabel = (\n props: TooltipLabel | TooltipDescription,\n): props is TooltipLabel => \"label\" in props && !!props.label;\n\n/**\n * A tooltip component\n */\nexport function Tooltip({\n children,\n isTriggerInteractive = true,\n nonInteractiveTriggerTabIndex = 0,\n ...props\n}: PropsWithChildren<TooltipProps>): JSX.Element {\n const context = useTooltip({ isTriggerInteractive, ...props });\n\n return (\n <TooltipContext.Provider value={context}>\n <TooltipAnchor\n isTriggerInteractive={isTriggerInteractive}\n nonInteractiveTriggerTabIndex={nonInteractiveTriggerTabIndex}\n >\n {children}\n </TooltipAnchor>\n <TooltipContent>\n <span id={context.labelId}>\n {hasLabel(props) ? props.label : props.description}\n </span>\n <Caption />\n </TooltipContent>\n </TooltipContext.Provider>\n );\n}\n\nfunction Caption() {\n const { caption, captionId } = useTooltipContext();\n if (!caption) return null;\n\n const isCaptionString = typeof caption === \"string\";\n const Container = isCaptionString ? \"span\" : \"div\";\n\n /**\n * Forcing dark theme, so that we have the correct contrast when\n * using the text color secondary on a solid dark background.\n * This is temporary and should only remain until we figure out\n * the approach to on-solid tokens\n **/\n return (\n <Container\n id={captionId}\n className={classNames(styles.caption, \"cpd-theme-dark\")}\n >\n {caption}\n </Container>\n );\n}\n\n/**\n * The content of the tooltip\n * @param children\n */\nfunction TooltipContent({\n children,\n}: Readonly<PropsWithChildren>): JSX.Element | null {\n const {\n context: floatingContext,\n open,\n arrowRef,\n purpose,\n ...rest\n } = useTooltipContext();\n\n // Label tooltips are kept in the DOM even when not visually open\n if (!open && purpose !== \"label\") return null;\n\n return (\n <FloatingPortal>\n <div\n ref={rest.refs.setFloating}\n style={rest.floatingStyles}\n {...rest.tooltipProps}\n {...rest.getFloatingProps()}\n className={classNames(styles.tooltip, {\n [styles.invisible]: purpose === \"label\" && !open,\n })}\n >\n <FloatingArrow\n ref={arrowRef}\n context={floatingContext}\n // design absolute value\n width={10}\n height={6}\n className={styles.arrow}\n />\n {children}\n </div>\n </FloatingPortal>\n );\n}\n\ninterface TooltipAnchorProps {\n children: ReactNode;\n isTriggerInteractive: boolean;\n nonInteractiveTriggerTabIndex?: number;\n}\n\n/**\n * The anchor of the tooltip\n * @param children\n */\nconst TooltipAnchor: FC<TooltipAnchorProps> = ({\n children,\n isTriggerInteractive,\n nonInteractiveTriggerTabIndex,\n}) => {\n const context = useTooltipContext();\n\n // The children can have a ref and we don't want to discard it\n // Doing a dirty cast to get the optional ref\n const childrenRef = (children as unknown as { ref?: Ref<HTMLElement> })?.ref;\n const ref = useMergeRefs([context.refs.setReference, childrenRef]);\n\n const element = useMemo(() => {\n if (!isValidElement(children)) return;\n\n if (isTriggerInteractive) {\n const props = context.getReferenceProps({\n // To support React 18, we need to explicitly pass the children's props. See https://github.com/element-hq/compound/issues/333\n // In React 19, this is not necessary. `getReferenceProps` is able to get the props directly from the ref.\n ...(typeof children.props === \"object\" ? children.props : {}),\n ref,\n });\n return cloneElement(children, props);\n } else {\n // For a non-interactive trigger, we want most of the props to go on the\n // span element that we provide, since that's what receives focus, but it\n // should still be the trigger that receives the label/description. It\n // would be wrong to label the span element, as it lacks a role.\n const props = context.getReferenceProps({\n ref,\n tabIndex: nonInteractiveTriggerTabIndex,\n });\n const {\n \"aria-labelledby\": labelId,\n \"aria-describedby\": descriptionId,\n ...spanProps\n } = props;\n return (\n <span tabIndex={nonInteractiveTriggerTabIndex} {...spanProps}>\n {cloneElement(children as ReactElement<Record<string, unknown>>, {\n \"aria-labelledby\": labelId,\n \"aria-describedby\": descriptionId,\n })}\n </span>\n );\n }\n }, [context, ref, children]);\n\n if (!element) {\n throw new Error(\"Tooltip anchor must be a single valid React element\");\n }\n\n return element;\n};\n"],"names":["useTooltip","jsxs","TooltipContext","jsx","useTooltipContext","styles","FloatingPortal","FloatingArrow","useMergeRefs","useMemo","isValidElement","cloneElement"],"mappings":"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"}
|
|
@@ -90,7 +90,12 @@ const TooltipAnchor = ({
|
|
|
90
90
|
const element = useMemo(() => {
|
|
91
91
|
if (!isValidElement(children)) return;
|
|
92
92
|
if (isTriggerInteractive) {
|
|
93
|
-
const props = context.getReferenceProps({
|
|
93
|
+
const props = context.getReferenceProps({
|
|
94
|
+
// To support React 18, we need to explicitly pass the children's props. See https://github.com/element-hq/compound/issues/333
|
|
95
|
+
// In React 19, this is not necessary. `getReferenceProps` is able to get the props directly from the ref.
|
|
96
|
+
...typeof children.props === "object" ? children.props : {},
|
|
97
|
+
ref
|
|
98
|
+
});
|
|
94
99
|
return cloneElement(children, props);
|
|
95
100
|
} else {
|
|
96
101
|
const props = context.getReferenceProps({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.js","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["/*\nCopyright 2023, 2024 New Vector Ltd.\n\nSPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial\nPlease see LICENSE files in the repository root for full details.\n*/\n\nimport { TooltipContext, useTooltipContext } from \"./TooltipContext\";\nimport {\n FloatingArrow,\n FloatingPortal,\n useMergeRefs,\n} from \"@floating-ui/react\";\nimport React, {\n PropsWithChildren,\n Ref,\n JSX,\n isValidElement,\n cloneElement,\n useMemo,\n ReactNode,\n FC,\n ReactElement,\n} from \"react\";\n\nimport classNames from \"classnames\";\nimport styles from \"./Tooltip.module.css\";\nimport {\n CommonUseTooltipProps,\n TooltipDescription,\n TooltipLabel,\n useTooltip,\n} from \"./useTooltip\";\n\n// Unfortunately Omit doesn't distribute nicely over sum types, so we have to\n// piece together the useTooltip options type by hand\ntype TooltipProps = Omit<CommonUseTooltipProps, \"isTriggerInteractive\"> &\n (TooltipLabel | TooltipDescription) & {\n /**\n * Whether the trigger element is interactive.\n * When trigger is interactive:\n * - tooltip will be shown after a 300ms delay.\n * When trigger is not interactive:\n * - tooltip will be shown instantly when pointer enters trigger.\n * - trigger will be wrapped in a span with a tab index from prop nonInteractiveTriggerTabIndex\n * @default true\n */\n isTriggerInteractive?: boolean;\n /**\n * The tab index for the non interactive trigger.\n * @default 0\n */\n nonInteractiveTriggerTabIndex?: number;\n };\n\nconst hasLabel = (\n props: TooltipLabel | TooltipDescription,\n): props is TooltipLabel => \"label\" in props && !!props.label;\n\n/**\n * A tooltip component\n */\nexport function Tooltip({\n children,\n isTriggerInteractive = true,\n nonInteractiveTriggerTabIndex = 0,\n ...props\n}: PropsWithChildren<TooltipProps>): JSX.Element {\n const context = useTooltip({ isTriggerInteractive, ...props });\n\n return (\n <TooltipContext.Provider value={context}>\n <TooltipAnchor\n isTriggerInteractive={isTriggerInteractive}\n nonInteractiveTriggerTabIndex={nonInteractiveTriggerTabIndex}\n >\n {children}\n </TooltipAnchor>\n <TooltipContent>\n <span id={context.labelId}>\n {hasLabel(props) ? props.label : props.description}\n </span>\n <Caption />\n </TooltipContent>\n </TooltipContext.Provider>\n );\n}\n\nfunction Caption() {\n const { caption, captionId } = useTooltipContext();\n if (!caption) return null;\n\n const isCaptionString = typeof caption === \"string\";\n const Container = isCaptionString ? \"span\" : \"div\";\n\n /**\n * Forcing dark theme, so that we have the correct contrast when\n * using the text color secondary on a solid dark background.\n * This is temporary and should only remain until we figure out\n * the approach to on-solid tokens\n **/\n return (\n <Container\n id={captionId}\n className={classNames(styles.caption, \"cpd-theme-dark\")}\n >\n {caption}\n </Container>\n );\n}\n\n/**\n * The content of the tooltip\n * @param children\n */\nfunction TooltipContent({\n children,\n}: Readonly<PropsWithChildren>): JSX.Element | null {\n const {\n context: floatingContext,\n open,\n arrowRef,\n purpose,\n ...rest\n } = useTooltipContext();\n\n // Label tooltips are kept in the DOM even when not visually open\n if (!open && purpose !== \"label\") return null;\n\n return (\n <FloatingPortal>\n <div\n ref={rest.refs.setFloating}\n style={rest.floatingStyles}\n {...rest.tooltipProps}\n {...rest.getFloatingProps()}\n className={classNames(styles.tooltip, {\n [styles.invisible]: purpose === \"label\" && !open,\n })}\n >\n <FloatingArrow\n ref={arrowRef}\n context={floatingContext}\n // design absolute value\n width={10}\n height={6}\n className={styles.arrow}\n />\n {children}\n </div>\n </FloatingPortal>\n );\n}\n\ninterface TooltipAnchorProps {\n children: ReactNode;\n isTriggerInteractive: boolean;\n nonInteractiveTriggerTabIndex?: number;\n}\n\n/**\n * The anchor of the tooltip\n * @param children\n */\nconst TooltipAnchor: FC<TooltipAnchorProps> = ({\n children,\n isTriggerInteractive,\n nonInteractiveTriggerTabIndex,\n}) => {\n const context = useTooltipContext();\n\n // The children can have a ref and we don't want to discard it\n // Doing a dirty cast to get the optional ref\n const childrenRef = (children as unknown as { ref?: Ref<HTMLElement> })?.ref;\n const ref = useMergeRefs([context.refs.setReference, childrenRef]);\n\n const element = useMemo(() => {\n if (!isValidElement(children)) return;\n\n if (isTriggerInteractive) {\n const props = context.getReferenceProps({ ref });\n return cloneElement(children, props);\n } else {\n // For a non-interactive trigger, we want most of the props to go on the\n // span element that we provide, since that's what receives focus, but it\n // should still be the trigger that receives the label/description. It\n // would be wrong to label the span element, as it lacks a role.\n const props = context.getReferenceProps({\n ref,\n tabIndex: nonInteractiveTriggerTabIndex,\n });\n const {\n \"aria-labelledby\": labelId,\n \"aria-describedby\": descriptionId,\n ...spanProps\n } = props;\n return (\n <span tabIndex={nonInteractiveTriggerTabIndex} {...spanProps}>\n {cloneElement(children as ReactElement<Record<string, unknown>>, {\n \"aria-labelledby\": labelId,\n \"aria-describedby\": descriptionId,\n })}\n </span>\n );\n }\n }, [context, ref, children]);\n\n if (!element) {\n throw new Error(\"Tooltip anchor must be a single valid React element\");\n }\n\n return element;\n};\n"],"names":[],"mappings":";;;;;;;AAuDA,MAAM,WAAW,CACf,UAC0B,WAAW,SAAS,CAAC,CAAC,MAAM;AAKjD,SAAS,QAAQ;AAAA,EACtB;AAAA,EACA,uBAAuB;AAAA,EACvB,gCAAgC;AAAA,EAChC,GAAG;AACL,GAAiD;AAC/C,QAAM,UAAU,WAAW,EAAE,sBAAsB,GAAG,OAAO;AAE7D,SACG,qBAAA,eAAe,UAAf,EAAwB,OAAO,SAC9B,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QAEC;AAAA,MAAA;AAAA,IACH;AAAA,yBACC,gBACC,EAAA,UAAA;AAAA,MAAC,oBAAA,QAAA,EAAK,IAAI,QAAQ,SACf,UAAA,SAAS,KAAK,IAAI,MAAM,QAAQ,MAAM,YACzC,CAAA;AAAA,0BACC,SAAQ,CAAA,CAAA;AAAA,IAAA,EACX,CAAA;AAAA,EAAA,GACF;AAEJ;AAEA,SAAS,UAAU;AACjB,QAAM,EAAE,SAAS,UAAU,IAAI,kBAAkB;AAC7C,MAAA,CAAC,QAAgB,QAAA;AAEf,QAAA,kBAAkB,OAAO,YAAY;AACrC,QAAA,YAAY,kBAAkB,SAAS;AAS3C,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,IAAI;AAAA,MACJ,WAAW,WAAW,OAAO,SAAS,gBAAgB;AAAA,MAErD,UAAA;AAAA,IAAA;AAAA,EACH;AAEJ;AAMA,SAAS,eAAe;AAAA,EACtB;AACF,GAAoD;AAC5C,QAAA;AAAA,IACJ,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,MACD,kBAAkB;AAGtB,MAAI,CAAC,QAAQ,YAAY,QAAgB,QAAA;AAEzC,6BACG,gBACC,EAAA,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK,KAAK,KAAK;AAAA,MACf,OAAO,KAAK;AAAA,MACX,GAAG,KAAK;AAAA,MACR,GAAG,KAAK,iBAAiB;AAAA,MAC1B,WAAW,WAAW,OAAO,SAAS;AAAA,QACpC,CAAC,OAAO,SAAS,GAAG,YAAY,WAAW,CAAC;AAAA,MAAA,CAC7C;AAAA,MAED,UAAA;AAAA,QAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAK;AAAA,YACL,SAAS;AAAA,YAET,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,WAAW,OAAO;AAAA,UAAA;AAAA,QACpB;AAAA,QACC;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAEL;AAEJ;AAYA,MAAM,gBAAwC,CAAC;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,UAAU,kBAAkB;AAIlC,QAAM,cAAe,UAAoD;AACzE,QAAM,MAAM,aAAa,CAAC,QAAQ,KAAK,cAAc,WAAW,CAAC;AAE3D,QAAA,UAAU,QAAQ,MAAM;AACxB,QAAA,CAAC,eAAe,QAAQ,EAAG;AAE/B,QAAI,sBAAsB;
|
|
1
|
+
{"version":3,"file":"Tooltip.js","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["/*\nCopyright 2023, 2024 New Vector Ltd.\n\nSPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial\nPlease see LICENSE files in the repository root for full details.\n*/\n\nimport { TooltipContext, useTooltipContext } from \"./TooltipContext\";\nimport {\n FloatingArrow,\n FloatingPortal,\n useMergeRefs,\n} from \"@floating-ui/react\";\nimport React, {\n PropsWithChildren,\n Ref,\n JSX,\n isValidElement,\n cloneElement,\n useMemo,\n ReactNode,\n FC,\n ReactElement,\n} from \"react\";\n\nimport classNames from \"classnames\";\nimport styles from \"./Tooltip.module.css\";\nimport {\n CommonUseTooltipProps,\n TooltipDescription,\n TooltipLabel,\n useTooltip,\n} from \"./useTooltip\";\n\n// Unfortunately Omit doesn't distribute nicely over sum types, so we have to\n// piece together the useTooltip options type by hand\ntype TooltipProps = Omit<CommonUseTooltipProps, \"isTriggerInteractive\"> &\n (TooltipLabel | TooltipDescription) & {\n /**\n * Whether the trigger element is interactive.\n * When trigger is interactive:\n * - tooltip will be shown after a 300ms delay.\n * When trigger is not interactive:\n * - tooltip will be shown instantly when pointer enters trigger.\n * - trigger will be wrapped in a span with a tab index from prop nonInteractiveTriggerTabIndex\n * @default true\n */\n isTriggerInteractive?: boolean;\n /**\n * The tab index for the non interactive trigger.\n * @default 0\n */\n nonInteractiveTriggerTabIndex?: number;\n };\n\nconst hasLabel = (\n props: TooltipLabel | TooltipDescription,\n): props is TooltipLabel => \"label\" in props && !!props.label;\n\n/**\n * A tooltip component\n */\nexport function Tooltip({\n children,\n isTriggerInteractive = true,\n nonInteractiveTriggerTabIndex = 0,\n ...props\n}: PropsWithChildren<TooltipProps>): JSX.Element {\n const context = useTooltip({ isTriggerInteractive, ...props });\n\n return (\n <TooltipContext.Provider value={context}>\n <TooltipAnchor\n isTriggerInteractive={isTriggerInteractive}\n nonInteractiveTriggerTabIndex={nonInteractiveTriggerTabIndex}\n >\n {children}\n </TooltipAnchor>\n <TooltipContent>\n <span id={context.labelId}>\n {hasLabel(props) ? props.label : props.description}\n </span>\n <Caption />\n </TooltipContent>\n </TooltipContext.Provider>\n );\n}\n\nfunction Caption() {\n const { caption, captionId } = useTooltipContext();\n if (!caption) return null;\n\n const isCaptionString = typeof caption === \"string\";\n const Container = isCaptionString ? \"span\" : \"div\";\n\n /**\n * Forcing dark theme, so that we have the correct contrast when\n * using the text color secondary on a solid dark background.\n * This is temporary and should only remain until we figure out\n * the approach to on-solid tokens\n **/\n return (\n <Container\n id={captionId}\n className={classNames(styles.caption, \"cpd-theme-dark\")}\n >\n {caption}\n </Container>\n );\n}\n\n/**\n * The content of the tooltip\n * @param children\n */\nfunction TooltipContent({\n children,\n}: Readonly<PropsWithChildren>): JSX.Element | null {\n const {\n context: floatingContext,\n open,\n arrowRef,\n purpose,\n ...rest\n } = useTooltipContext();\n\n // Label tooltips are kept in the DOM even when not visually open\n if (!open && purpose !== \"label\") return null;\n\n return (\n <FloatingPortal>\n <div\n ref={rest.refs.setFloating}\n style={rest.floatingStyles}\n {...rest.tooltipProps}\n {...rest.getFloatingProps()}\n className={classNames(styles.tooltip, {\n [styles.invisible]: purpose === \"label\" && !open,\n })}\n >\n <FloatingArrow\n ref={arrowRef}\n context={floatingContext}\n // design absolute value\n width={10}\n height={6}\n className={styles.arrow}\n />\n {children}\n </div>\n </FloatingPortal>\n );\n}\n\ninterface TooltipAnchorProps {\n children: ReactNode;\n isTriggerInteractive: boolean;\n nonInteractiveTriggerTabIndex?: number;\n}\n\n/**\n * The anchor of the tooltip\n * @param children\n */\nconst TooltipAnchor: FC<TooltipAnchorProps> = ({\n children,\n isTriggerInteractive,\n nonInteractiveTriggerTabIndex,\n}) => {\n const context = useTooltipContext();\n\n // The children can have a ref and we don't want to discard it\n // Doing a dirty cast to get the optional ref\n const childrenRef = (children as unknown as { ref?: Ref<HTMLElement> })?.ref;\n const ref = useMergeRefs([context.refs.setReference, childrenRef]);\n\n const element = useMemo(() => {\n if (!isValidElement(children)) return;\n\n if (isTriggerInteractive) {\n const props = context.getReferenceProps({\n // To support React 18, we need to explicitly pass the children's props. See https://github.com/element-hq/compound/issues/333\n // In React 19, this is not necessary. `getReferenceProps` is able to get the props directly from the ref.\n ...(typeof children.props === \"object\" ? children.props : {}),\n ref,\n });\n return cloneElement(children, props);\n } else {\n // For a non-interactive trigger, we want most of the props to go on the\n // span element that we provide, since that's what receives focus, but it\n // should still be the trigger that receives the label/description. It\n // would be wrong to label the span element, as it lacks a role.\n const props = context.getReferenceProps({\n ref,\n tabIndex: nonInteractiveTriggerTabIndex,\n });\n const {\n \"aria-labelledby\": labelId,\n \"aria-describedby\": descriptionId,\n ...spanProps\n } = props;\n return (\n <span tabIndex={nonInteractiveTriggerTabIndex} {...spanProps}>\n {cloneElement(children as ReactElement<Record<string, unknown>>, {\n \"aria-labelledby\": labelId,\n \"aria-describedby\": descriptionId,\n })}\n </span>\n );\n }\n }, [context, ref, children]);\n\n if (!element) {\n throw new Error(\"Tooltip anchor must be a single valid React element\");\n }\n\n return element;\n};\n"],"names":[],"mappings":";;;;;;;AAuDA,MAAM,WAAW,CACf,UAC0B,WAAW,SAAS,CAAC,CAAC,MAAM;AAKjD,SAAS,QAAQ;AAAA,EACtB;AAAA,EACA,uBAAuB;AAAA,EACvB,gCAAgC;AAAA,EAChC,GAAG;AACL,GAAiD;AAC/C,QAAM,UAAU,WAAW,EAAE,sBAAsB,GAAG,OAAO;AAE7D,SACG,qBAAA,eAAe,UAAf,EAAwB,OAAO,SAC9B,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QAEC;AAAA,MAAA;AAAA,IACH;AAAA,yBACC,gBACC,EAAA,UAAA;AAAA,MAAC,oBAAA,QAAA,EAAK,IAAI,QAAQ,SACf,UAAA,SAAS,KAAK,IAAI,MAAM,QAAQ,MAAM,YACzC,CAAA;AAAA,0BACC,SAAQ,CAAA,CAAA;AAAA,IAAA,EACX,CAAA;AAAA,EAAA,GACF;AAEJ;AAEA,SAAS,UAAU;AACjB,QAAM,EAAE,SAAS,UAAU,IAAI,kBAAkB;AAC7C,MAAA,CAAC,QAAgB,QAAA;AAEf,QAAA,kBAAkB,OAAO,YAAY;AACrC,QAAA,YAAY,kBAAkB,SAAS;AAS3C,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,IAAI;AAAA,MACJ,WAAW,WAAW,OAAO,SAAS,gBAAgB;AAAA,MAErD,UAAA;AAAA,IAAA;AAAA,EACH;AAEJ;AAMA,SAAS,eAAe;AAAA,EACtB;AACF,GAAoD;AAC5C,QAAA;AAAA,IACJ,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,MACD,kBAAkB;AAGtB,MAAI,CAAC,QAAQ,YAAY,QAAgB,QAAA;AAEzC,6BACG,gBACC,EAAA,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK,KAAK,KAAK;AAAA,MACf,OAAO,KAAK;AAAA,MACX,GAAG,KAAK;AAAA,MACR,GAAG,KAAK,iBAAiB;AAAA,MAC1B,WAAW,WAAW,OAAO,SAAS;AAAA,QACpC,CAAC,OAAO,SAAS,GAAG,YAAY,WAAW,CAAC;AAAA,MAAA,CAC7C;AAAA,MAED,UAAA;AAAA,QAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAK;AAAA,YACL,SAAS;AAAA,YAET,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,WAAW,OAAO;AAAA,UAAA;AAAA,QACpB;AAAA,QACC;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAEL;AAEJ;AAYA,MAAM,gBAAwC,CAAC;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,UAAU,kBAAkB;AAIlC,QAAM,cAAe,UAAoD;AACzE,QAAM,MAAM,aAAa,CAAC,QAAQ,KAAK,cAAc,WAAW,CAAC;AAE3D,QAAA,UAAU,QAAQ,MAAM;AACxB,QAAA,CAAC,eAAe,QAAQ,EAAG;AAE/B,QAAI,sBAAsB;AAClB,YAAA,QAAQ,QAAQ,kBAAkB;AAAA;AAAA;AAAA,QAGtC,GAAI,OAAO,SAAS,UAAU,WAAW,SAAS,QAAQ,CAAC;AAAA,QAC3D;AAAA,MAAA,CACD;AACM,aAAA,aAAa,UAAU,KAAK;AAAA,IAAA,OAC9B;AAKC,YAAA,QAAQ,QAAQ,kBAAkB;AAAA,QACtC;AAAA,QACA,UAAU;AAAA,MAAA,CACX;AACK,YAAA;AAAA,QACJ,mBAAmB;AAAA,QACnB,oBAAoB;AAAA,QACpB,GAAG;AAAA,MAAA,IACD;AACJ,iCACG,QAAK,EAAA,UAAU,+BAAgC,GAAG,WAChD,uBAAa,UAAmD;AAAA,QAC/D,mBAAmB;AAAA,QACnB,oBAAoB;AAAA,MACrB,CAAA,GACH;AAAA,IAAA;AAAA,EAGH,GAAA,CAAC,SAAS,KAAK,QAAQ,CAAC;AAE3B,MAAI,CAAC,SAAS;AACN,UAAA,IAAI,MAAM,qDAAqD;AAAA,EAAA;AAGhE,SAAA;AACT;"}
|
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,7 @@ const InlineSpinner = require("./components/InlineSpinner/InlineSpinner.cjs");
|
|
|
35
35
|
const Breadcrumb = require("./components/Breadcrumb/Breadcrumb.cjs");
|
|
36
36
|
const VisualList = require("./components/VisualList/VisualList.cjs");
|
|
37
37
|
const VisualListItem = require("./components/VisualList/VisualListItem.cjs");
|
|
38
|
+
const ChatFilter = require("./components/ChatFilter/ChatFilter.cjs");
|
|
38
39
|
const Text$1 = require("./components/Form/Controls/Text/Text.cjs");
|
|
39
40
|
const Action = require("./components/Form/Controls/Action/Action.cjs");
|
|
40
41
|
const Password = require("./components/Form/Controls/Password/Password.cjs");
|
|
@@ -90,6 +91,7 @@ exports.InlineSpinner = InlineSpinner.InlineSpinner;
|
|
|
90
91
|
exports.Breadcrumb = Breadcrumb.Breadcrumb;
|
|
91
92
|
exports.VisualList = VisualList.VisualList;
|
|
92
93
|
exports.VisualListItem = VisualListItem.VisualListItem;
|
|
94
|
+
exports.ChatFilter = ChatFilter.ChatFilter;
|
|
93
95
|
exports.Control = Text$1.TextControl;
|
|
94
96
|
exports.TextControl = Text$1.TextControl;
|
|
95
97
|
exports.TextInput = Text$1.TextInput;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export { Dropdown } from './components/Dropdown';
|
|
|
29
29
|
export { InlineSpinner } from './components/InlineSpinner';
|
|
30
30
|
export { Breadcrumb } from './components/Breadcrumb';
|
|
31
31
|
export { VisualList, VisualListItem } from './components/VisualList';
|
|
32
|
+
export { ChatFilter } from './components/ChatFilter';
|
|
32
33
|
export { TextControl, TextControl as Control, TextInput, ActionControl, ActionInput, PasswordControl, PasswordInput, MFAControl, MFAInput, CheckboxControl, CheckboxInput, CheckboxInput as Checkbox, RadioControl, RadioInput, RadioInput as Radio, ToggleControl, ToggleInput, ToggleInput as Toggle, Root, Submit, Message, ErrorMessage, HelpMessage, ValidityState, Field, InlineField, Label, EditInPlace, } from './components/Form';
|
|
33
34
|
export * as Form from './components/Form';
|
|
34
35
|
/**
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACjD,OAAO,EACL,OAAO,EACP,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,GACH,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,+CAA+C,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACjD,OAAO,EACL,OAAO,EACP,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,EACF,EAAE,GACH,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,+CAA+C,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,OAAO,EACL,WAAW,EAEX,WAAW,IAAI,OAAO,EACtB,SAAS,EACT,aAAa,EACb,WAAW,EACX,eAAe,EACf,aAAa,EACb,UAAU,EACV,QAAQ,EACR,eAAe,EACf,aAAa,EAEb,aAAa,IAAI,QAAQ,EACzB,YAAY,EACZ,UAAU,EAEV,UAAU,IAAI,KAAK,EACnB,aAAa,EACb,WAAW,EAEX,WAAW,IAAI,MAAM,EACrB,IAAI,EACJ,MAAM,EACN,OAAO,EACP,YAAY,EACZ,WAAW,EACX,aAAa,EACb,KAAK,EACL,WAAW,EACX,KAAK,EACL,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,IAAI,MAAM,mBAAmB,CAAC;AAE1C;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ import { InlineSpinner } from "./components/InlineSpinner/InlineSpinner.js";
|
|
|
33
33
|
import { Breadcrumb } from "./components/Breadcrumb/Breadcrumb.js";
|
|
34
34
|
import { VisualList } from "./components/VisualList/VisualList.js";
|
|
35
35
|
import { VisualListItem } from "./components/VisualList/VisualListItem.js";
|
|
36
|
+
import { ChatFilter } from "./components/ChatFilter/ChatFilter.js";
|
|
36
37
|
import { TextControl, TextControl as TextControl2, TextInput } from "./components/Form/Controls/Text/Text.js";
|
|
37
38
|
import { ActionControl, ActionInput } from "./components/Form/Controls/Action/Action.js";
|
|
38
39
|
import { PasswordControl, PasswordInput } from "./components/Form/Controls/Password/Password.js";
|
|
@@ -59,6 +60,7 @@ export {
|
|
|
59
60
|
Body,
|
|
60
61
|
Breadcrumb,
|
|
61
62
|
Button,
|
|
63
|
+
ChatFilter,
|
|
62
64
|
CheckboxInput as Checkbox,
|
|
63
65
|
CheckboxControl,
|
|
64
66
|
CheckboxInput2 as CheckboxInput,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/style.css
CHANGED
|
@@ -594,7 +594,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
|
594
594
|
Please see LICENSE files in the repository root for full details.
|
|
595
595
|
*/
|
|
596
596
|
|
|
597
|
-
.
|
|
597
|
+
._menu_19sse_8 {
|
|
598
598
|
border-radius: var(--cpd-space-3x);
|
|
599
599
|
background: var(--cpd-color-bg-canvas-default);
|
|
600
600
|
|
|
@@ -616,56 +616,67 @@ Please see LICENSE files in the repository root for full details.
|
|
|
616
616
|
--cpd-separator-inset: var(--cpd-space-4x);
|
|
617
617
|
}
|
|
618
618
|
|
|
619
|
-
@keyframes _slide-
|
|
619
|
+
@keyframes _slide-in_19sse_1 {
|
|
620
620
|
from {
|
|
621
621
|
opacity: 0;
|
|
622
622
|
transform: translate(0, var(--cpd-space-3x));
|
|
623
623
|
}
|
|
624
624
|
}
|
|
625
625
|
|
|
626
|
-
@keyframes _slide-
|
|
626
|
+
@keyframes _slide-out_19sse_1 {
|
|
627
627
|
to {
|
|
628
628
|
opacity: 0;
|
|
629
629
|
transform: translate(0, var(--cpd-space-2x));
|
|
630
630
|
}
|
|
631
631
|
}
|
|
632
632
|
|
|
633
|
-
.
|
|
634
|
-
animation: _slide-
|
|
633
|
+
._menu_19sse_8[data-state="open"] {
|
|
634
|
+
animation: _slide-in_19sse_1 180ms;
|
|
635
635
|
}
|
|
636
636
|
|
|
637
|
-
.
|
|
638
|
-
animation: _slide-
|
|
637
|
+
._menu_19sse_8[data-state="closed"] {
|
|
638
|
+
animation: _slide-out_19sse_1 110ms;
|
|
639
639
|
}
|
|
640
640
|
|
|
641
|
-
@keyframes _fade-
|
|
641
|
+
@keyframes _fade-in_19sse_1 {
|
|
642
642
|
from {
|
|
643
643
|
opacity: 0;
|
|
644
644
|
}
|
|
645
645
|
}
|
|
646
646
|
|
|
647
|
-
@keyframes _fade-
|
|
647
|
+
@keyframes _fade-out_19sse_1 {
|
|
648
648
|
to {
|
|
649
649
|
opacity: 0;
|
|
650
650
|
}
|
|
651
651
|
}
|
|
652
652
|
|
|
653
653
|
@media (prefers-reduced-motion) {
|
|
654
|
-
.
|
|
655
|
-
animation-name: _fade-
|
|
654
|
+
._menu_19sse_8[data-state="open"] {
|
|
655
|
+
animation-name: _fade-in_19sse_1;
|
|
656
656
|
}
|
|
657
657
|
|
|
658
|
-
.
|
|
659
|
-
animation-name: _fade-
|
|
658
|
+
._menu_19sse_8[data-state="closed"] {
|
|
659
|
+
animation-name: _fade-out_19sse_1;
|
|
660
660
|
}
|
|
661
661
|
}
|
|
662
662
|
|
|
663
|
-
.
|
|
663
|
+
._title_19sse_74 {
|
|
664
|
+
/** Override MenuTitle margin top **/
|
|
665
|
+
margin-block-start: 0 !important;
|
|
666
|
+
}
|
|
667
|
+
/*
|
|
668
|
+
* Copyright 2025 New Vector Ltd
|
|
669
|
+
*
|
|
670
|
+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
671
|
+
* Please see LICENSE files in the repository root for full details.
|
|
672
|
+
*/
|
|
673
|
+
|
|
674
|
+
._menu-title_1sgvx_8 {
|
|
664
675
|
color: var(--cpd-color-text-secondary);
|
|
665
676
|
padding-inline: var(--cpd-space-4x);
|
|
666
677
|
padding-block-end: calc(var(--cpd-space-2x) - var(--cpd-border-width-1));
|
|
667
678
|
border-block-end: var(--cpd-border-width-1) solid var(--cpd-color-gray-400);
|
|
668
|
-
margin-block:
|
|
679
|
+
margin-block: var(--cpd-space-2x);
|
|
669
680
|
}
|
|
670
681
|
/*
|
|
671
682
|
Copyright 2023 New Vector Ltd.
|
|
@@ -2582,3 +2593,36 @@ Please see LICENSE files in the repository root for full details.
|
|
|
2582
2593
|
._visual-list-item-icon-destructive_1ma3e_26 {
|
|
2583
2594
|
color: var(--cpd-color-icon-critical-primary);
|
|
2584
2595
|
}
|
|
2596
|
+
/*
|
|
2597
|
+
* Copyright 2025 New Vector Ltd
|
|
2598
|
+
*
|
|
2599
|
+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
2600
|
+
* Please see LICENSE files in the repository root for full details.
|
|
2601
|
+
*/
|
|
2602
|
+
|
|
2603
|
+
._chat-filter_5qdp0_8 {
|
|
2604
|
+
font: var(--cpd-font-body-sm-medium);
|
|
2605
|
+
color: var(--cpd-color-text-primary);
|
|
2606
|
+
background-color: transparent;
|
|
2607
|
+
border: var(--cpd-border-width-1) solid
|
|
2608
|
+
var(--cpd-color-border-interactive-secondary);
|
|
2609
|
+
border-radius: 99px;
|
|
2610
|
+
cursor: pointer;
|
|
2611
|
+
display: flex;
|
|
2612
|
+
align-items: center;
|
|
2613
|
+
justify-content: center;
|
|
2614
|
+
padding: var(--cpd-space-1x) var(--cpd-space-2x);
|
|
2615
|
+
}
|
|
2616
|
+
|
|
2617
|
+
@media (hover) {
|
|
2618
|
+
._chat-filter_5qdp0_8:hover {
|
|
2619
|
+
border-color: var(--cpd-color-border-interactive-primary);
|
|
2620
|
+
background: var(--cpd-color-bg-subtle-primary);
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
|
|
2624
|
+
._chat-filter_5qdp0_8[aria-selected="true"] {
|
|
2625
|
+
border-color: var(--cpd-color-bg-action-primary-rest);
|
|
2626
|
+
background: var(--cpd-color-bg-action-primary-rest);
|
|
2627
|
+
color: var(--cpd-color-text-on-solid-primary);
|
|
2628
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 New Vector Ltd
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
5
|
+
* Please see LICENSE files in the repository root for full details.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
.chat-filter {
|
|
9
|
+
font: var(--cpd-font-body-sm-medium);
|
|
10
|
+
color: var(--cpd-color-text-primary);
|
|
11
|
+
background-color: transparent;
|
|
12
|
+
border: var(--cpd-border-width-1) solid
|
|
13
|
+
var(--cpd-color-border-interactive-secondary);
|
|
14
|
+
border-radius: 99px;
|
|
15
|
+
cursor: pointer;
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
justify-content: center;
|
|
19
|
+
padding: var(--cpd-space-1x) var(--cpd-space-2x);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@media (hover) {
|
|
23
|
+
.chat-filter:hover {
|
|
24
|
+
border-color: var(--cpd-color-border-interactive-primary);
|
|
25
|
+
background: var(--cpd-color-bg-subtle-primary);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.chat-filter[aria-selected="true"] {
|
|
30
|
+
border-color: var(--cpd-color-bg-action-primary-rest);
|
|
31
|
+
background: var(--cpd-color-bg-action-primary-rest);
|
|
32
|
+
color: var(--cpd-color-text-on-solid-primary);
|
|
33
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 New Vector Ltd
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
5
|
+
* Please see LICENSE files in the repository root for full details.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, { ForwardedRef, forwardRef } from "react";
|
|
9
|
+
import {
|
|
10
|
+
UnstyledButton,
|
|
11
|
+
UnstyledButtonPropsFor,
|
|
12
|
+
} from "../Button/UnstyledButton";
|
|
13
|
+
import styles from "./ChatFilter.module.css";
|
|
14
|
+
|
|
15
|
+
type ChatFilterProps = Omit<UnstyledButtonPropsFor<"button">, "disabled"> & {
|
|
16
|
+
/**
|
|
17
|
+
* Whether the filter is selected.
|
|
18
|
+
*/
|
|
19
|
+
selected?: boolean;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A chat filter button.
|
|
24
|
+
*/
|
|
25
|
+
export const ChatFilter = forwardRef(function ChatFilter(
|
|
26
|
+
{ children, selected, ...props }: ChatFilterProps,
|
|
27
|
+
ref: ForwardedRef<HTMLButtonElement>,
|
|
28
|
+
): React.ReactElement {
|
|
29
|
+
return (
|
|
30
|
+
<UnstyledButton
|
|
31
|
+
{...props}
|
|
32
|
+
className={styles["chat-filter"]}
|
|
33
|
+
aria-selected={selected}
|
|
34
|
+
as="button"
|
|
35
|
+
ref={ref}
|
|
36
|
+
tabIndex={0}
|
|
37
|
+
>
|
|
38
|
+
{children}
|
|
39
|
+
</UnstyledButton>
|
|
40
|
+
);
|
|
41
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 New Vector Ltd
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
5
|
+
* Please see LICENSE files in the repository root for full details.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, { ComponentProps, forwardRef, useCallback, useId } from "react";
|
|
9
|
+
import { MenuItem } from "./MenuItem";
|
|
10
|
+
import { CheckboxInput } from "../Form";
|
|
11
|
+
|
|
12
|
+
type Props = Pick<
|
|
13
|
+
ComponentProps<typeof MenuItem>,
|
|
14
|
+
"className" | "label" | "onSelect" | "disabled"
|
|
15
|
+
> & {
|
|
16
|
+
/**
|
|
17
|
+
* Whether the checkbox is checked.
|
|
18
|
+
*/
|
|
19
|
+
checked: boolean;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A menu item with a checkbox control.
|
|
24
|
+
* Must be used within a compound Menu or other `menu` or `menubar` aria role subtree.
|
|
25
|
+
*/
|
|
26
|
+
export const CheckboxMenuItem = forwardRef<HTMLInputElement, Props>(
|
|
27
|
+
function CheckboxMenuItem(
|
|
28
|
+
{ className, label, onSelect, checked, disabled },
|
|
29
|
+
ref,
|
|
30
|
+
) {
|
|
31
|
+
const toggleId = useId();
|
|
32
|
+
// The checkbox is controlled and we intend to ignore its events. We do need
|
|
33
|
+
// to at least set onChange though to make React happy.
|
|
34
|
+
const onChange = useCallback(() => {}, []);
|
|
35
|
+
|
|
36
|
+
// <label> elements are not allowed to have a role like menuitemcheckbox, so
|
|
37
|
+
// we must instead use a plain <div> for the menu item and use aria-checked
|
|
38
|
+
// etc. to communicate its state.
|
|
39
|
+
return (
|
|
40
|
+
<MenuItem
|
|
41
|
+
as="div"
|
|
42
|
+
role="menuitemcheckbox"
|
|
43
|
+
aria-checked={checked}
|
|
44
|
+
className={className}
|
|
45
|
+
label={label}
|
|
46
|
+
onSelect={onSelect}
|
|
47
|
+
disabled={disabled}
|
|
48
|
+
Icon={
|
|
49
|
+
<CheckboxInput
|
|
50
|
+
id={toggleId}
|
|
51
|
+
ref={ref}
|
|
52
|
+
// This is purely cosmetic; really the whole MenuItem is the toggle.
|
|
53
|
+
aria-hidden
|
|
54
|
+
checked={checked}
|
|
55
|
+
disabled={disabled}
|
|
56
|
+
onChange={onChange}
|
|
57
|
+
/>
|
|
58
|
+
}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
61
|
+
},
|
|
62
|
+
);
|
|
@@ -72,9 +72,6 @@ Please see LICENSE files in the repository root for full details.
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
.title {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
padding-block-end: calc(var(--cpd-space-2x) - var(--cpd-border-width-1));
|
|
78
|
-
border-block-end: var(--cpd-border-width-1) solid var(--cpd-color-gray-400);
|
|
79
|
-
margin-block: 0 var(--cpd-space-2x);
|
|
75
|
+
/** Override MenuTitle margin top **/
|
|
76
|
+
margin-block-start: 0 !important;
|
|
80
77
|
}
|
|
@@ -13,18 +13,7 @@ import React, {
|
|
|
13
13
|
useId,
|
|
14
14
|
} from "react";
|
|
15
15
|
import styles from "./FloatingMenu.module.css";
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
interface TitleProps {
|
|
19
|
-
title: string;
|
|
20
|
-
id: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const MenuTitle: React.FC<TitleProps> = ({ title, id }) => (
|
|
24
|
-
<Text as="h3" id={id} className={styles.title} size="sm" weight="semibold">
|
|
25
|
-
{title}
|
|
26
|
-
</Text>
|
|
27
|
-
);
|
|
16
|
+
import { MenuTitle } from "./MenuTitle.tsx";
|
|
28
17
|
|
|
29
18
|
interface Props extends ComponentPropsWithoutRef<"div"> {
|
|
30
19
|
/**
|
|
@@ -62,7 +51,9 @@ export const FloatingMenu = forwardRef<HTMLDivElement, Props>(
|
|
|
62
51
|
className={classnames(className, styles.menu)}
|
|
63
52
|
{...props}
|
|
64
53
|
>
|
|
65
|
-
{showTitle &&
|
|
54
|
+
{showTitle && (
|
|
55
|
+
<MenuTitle className={styles.title} title={title} id={titleId} />
|
|
56
|
+
)}
|
|
66
57
|
{children}
|
|
67
58
|
</div>
|
|
68
59
|
);
|
|
@@ -55,13 +55,22 @@ type Props<C extends MenuItemElement> = {
|
|
|
55
55
|
*/
|
|
56
56
|
// This prop is required because it's rare to not want a selection handler
|
|
57
57
|
onSelect: ((e: Event) => void) | null;
|
|
58
|
+
/**
|
|
59
|
+
* Event callback for when the item is clicked.
|
|
60
|
+
* @param e
|
|
61
|
+
*/
|
|
62
|
+
onClick?: (e: Event) => void;
|
|
58
63
|
/**
|
|
59
64
|
* The color variant of the menu item.
|
|
60
65
|
* @default primary
|
|
61
66
|
*/
|
|
62
67
|
kind?: "primary" | "critical";
|
|
63
68
|
disabled?: boolean;
|
|
64
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Whether to hide the chevron navigation hint.
|
|
71
|
+
*/
|
|
72
|
+
hideChevron?: boolean;
|
|
73
|
+
} & Omit<ComponentPropsWithoutRef<C>, "onSelect" | "onClick">;
|
|
65
74
|
|
|
66
75
|
/**
|
|
67
76
|
* An item within a menu, acting either as a navigation button, or simply a
|
|
@@ -79,6 +88,7 @@ export const MenuItem = <C extends MenuItemElement = "button">({
|
|
|
79
88
|
children,
|
|
80
89
|
onClick: onClickProp,
|
|
81
90
|
disabled,
|
|
91
|
+
hideChevron,
|
|
82
92
|
...props
|
|
83
93
|
}: Props<C>): React.ReactElement => {
|
|
84
94
|
const Component = as ?? ("button" as ElementType);
|
|
@@ -143,7 +153,7 @@ export const MenuItem = <C extends MenuItemElement = "button">({
|
|
|
143
153
|
)}
|
|
144
154
|
{/* We use CSS to swap between this navigation hint and the provided
|
|
145
155
|
children on hover - see the styles module. */}
|
|
146
|
-
{(Component === "button" || Component === "a") && (
|
|
156
|
+
{!hideChevron && (Component === "button" || Component === "a") && (
|
|
147
157
|
<ChevronRightIcon
|
|
148
158
|
width={8}
|
|
149
159
|
height={24}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 New Vector Ltd
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
5
|
+
* Please see LICENSE files in the repository root for full details.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
.menu-title {
|
|
9
|
+
color: var(--cpd-color-text-secondary);
|
|
10
|
+
padding-inline: var(--cpd-space-4x);
|
|
11
|
+
padding-block-end: calc(var(--cpd-space-2x) - var(--cpd-border-width-1));
|
|
12
|
+
border-block-end: var(--cpd-border-width-1) solid var(--cpd-color-gray-400);
|
|
13
|
+
margin-block: var(--cpd-space-2x);
|
|
14
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 New Vector Ltd
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
5
|
+
* Please see LICENSE files in the repository root for full details.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React from "react";
|
|
9
|
+
import { Text } from "../Typography/Text.tsx";
|
|
10
|
+
import styles from "./MenuTitle.module.css";
|
|
11
|
+
import classnames from "classnames";
|
|
12
|
+
|
|
13
|
+
interface MenuTitleProps {
|
|
14
|
+
/**
|
|
15
|
+
* The title of the menu.
|
|
16
|
+
*/
|
|
17
|
+
title: string;
|
|
18
|
+
/**
|
|
19
|
+
* The id of the menu title.
|
|
20
|
+
*/
|
|
21
|
+
id?: string;
|
|
22
|
+
/**
|
|
23
|
+
* The CSS class.
|
|
24
|
+
*/
|
|
25
|
+
className?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const MenuTitle: React.FC<MenuTitleProps> = ({
|
|
29
|
+
title,
|
|
30
|
+
id,
|
|
31
|
+
className,
|
|
32
|
+
}) => {
|
|
33
|
+
const classes = classnames(styles["menu-title"], className);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Text as="h3" id={id} className={classes} size="sm" weight="semibold">
|
|
37
|
+
{title}
|
|
38
|
+
</Text>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
@@ -11,7 +11,7 @@ import { ToggleInput } from "../Form/Controls/Toggle";
|
|
|
11
11
|
|
|
12
12
|
type Props = Pick<
|
|
13
13
|
ComponentProps<typeof MenuItem>,
|
|
14
|
-
"className" | "Icon" | "label" | "onSelect" | "disabled"
|
|
14
|
+
"className" | "Icon" | "label" | "onSelect" | "disabled" | "onClick"
|
|
15
15
|
> & {
|
|
16
16
|
/**
|
|
17
17
|
* Whether the toggle is checked.
|
|
@@ -25,7 +25,7 @@ type Props = Pick<
|
|
|
25
25
|
*/
|
|
26
26
|
export const ToggleMenuItem = forwardRef<HTMLInputElement, Props>(
|
|
27
27
|
function ToggleMenuItem(
|
|
28
|
-
{ className, Icon, label, onSelect, checked, disabled },
|
|
28
|
+
{ className, Icon, label, onSelect, checked, disabled, onClick },
|
|
29
29
|
ref,
|
|
30
30
|
) {
|
|
31
31
|
const toggleId = useId();
|
|
@@ -46,6 +46,7 @@ export const ToggleMenuItem = forwardRef<HTMLInputElement, Props>(
|
|
|
46
46
|
label={label}
|
|
47
47
|
onSelect={onSelect}
|
|
48
48
|
disabled={disabled}
|
|
49
|
+
onClick={onClick}
|
|
49
50
|
>
|
|
50
51
|
<ToggleInput
|
|
51
52
|
id={toggleId}
|
|
@@ -178,7 +178,12 @@ const TooltipAnchor: FC<TooltipAnchorProps> = ({
|
|
|
178
178
|
if (!isValidElement(children)) return;
|
|
179
179
|
|
|
180
180
|
if (isTriggerInteractive) {
|
|
181
|
-
const props = context.getReferenceProps({
|
|
181
|
+
const props = context.getReferenceProps({
|
|
182
|
+
// To support React 18, we need to explicitly pass the children's props. See https://github.com/element-hq/compound/issues/333
|
|
183
|
+
// In React 19, this is not necessary. `getReferenceProps` is able to get the props directly from the ref.
|
|
184
|
+
...(typeof children.props === "object" ? children.props : {}),
|
|
185
|
+
ref,
|
|
186
|
+
});
|
|
182
187
|
return cloneElement(children, props);
|
|
183
188
|
} else {
|
|
184
189
|
// For a non-interactive trigger, we want most of the props to go on the
|
package/src/index.ts
CHANGED
|
@@ -46,6 +46,7 @@ export { Dropdown } from "./components/Dropdown";
|
|
|
46
46
|
export { InlineSpinner } from "./components/InlineSpinner";
|
|
47
47
|
export { Breadcrumb } from "./components/Breadcrumb";
|
|
48
48
|
export { VisualList, VisualListItem } from "./components/VisualList";
|
|
49
|
+
export { ChatFilter } from "./components/ChatFilter";
|
|
49
50
|
|
|
50
51
|
export {
|
|
51
52
|
TextControl,
|