@vector-im/compound-web 9.0.1 → 9.1.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.
Files changed (67) hide show
  1. package/dist/components/Badge/Badge.cjs +8 -4
  2. package/dist/components/Badge/Badge.cjs.map +1 -1
  3. package/dist/components/Badge/Badge.d.ts +5 -1
  4. package/dist/components/Badge/Badge.d.ts.map +1 -1
  5. package/dist/components/Badge/Badge.js +9 -5
  6. package/dist/components/Badge/Badge.js.map +1 -1
  7. package/dist/components/Badge/Badge.module.cjs +4 -1
  8. package/dist/components/Badge/Badge.module.cjs.map +1 -1
  9. package/dist/components/Badge/Badge.module.js +4 -1
  10. package/dist/components/Badge/Badge.module.js.map +1 -1
  11. package/dist/components/Button/IconButton/IconButton.cjs +2 -1
  12. package/dist/components/Button/IconButton/IconButton.cjs.map +1 -1
  13. package/dist/components/Button/IconButton/IconButton.d.ts +5 -0
  14. package/dist/components/Button/IconButton/IconButton.d.ts.map +1 -1
  15. package/dist/components/Button/IconButton/IconButton.js +2 -1
  16. package/dist/components/Button/IconButton/IconButton.js.map +1 -1
  17. package/dist/components/Menu/ContextMenu.cjs +17 -0
  18. package/dist/components/Menu/ContextMenu.cjs.map +1 -1
  19. package/dist/components/Menu/ContextMenu.d.ts.map +1 -1
  20. package/dist/components/Menu/ContextMenu.js +18 -1
  21. package/dist/components/Menu/ContextMenu.js.map +1 -1
  22. package/dist/components/Menu/Menu.cjs +28 -0
  23. package/dist/components/Menu/Menu.cjs.map +1 -1
  24. package/dist/components/Menu/Menu.d.ts.map +1 -1
  25. package/dist/components/Menu/Menu.js +30 -2
  26. package/dist/components/Menu/Menu.js.map +1 -1
  27. package/dist/components/Menu/MenuContext.cjs.map +1 -1
  28. package/dist/components/Menu/MenuContext.d.ts +22 -0
  29. package/dist/components/Menu/MenuContext.d.ts.map +1 -1
  30. package/dist/components/Menu/MenuContext.js.map +1 -1
  31. package/dist/components/Menu/MenuItem.module.cjs +8 -8
  32. package/dist/components/Menu/MenuItem.module.cjs.map +1 -1
  33. package/dist/components/Menu/MenuItem.module.js +8 -8
  34. package/dist/components/Menu/MenuItem.module.js.map +1 -1
  35. package/dist/components/Menu/SubMenu.cjs +24 -0
  36. package/dist/components/Menu/SubMenu.cjs.map +1 -0
  37. package/dist/components/Menu/SubMenu.d.ts +26 -0
  38. package/dist/components/Menu/SubMenu.d.ts.map +1 -0
  39. package/dist/components/Menu/SubMenu.js +22 -0
  40. package/dist/components/Menu/SubMenu.js.map +1 -0
  41. package/dist/components/Toast/Toast.cjs +29 -4
  42. package/dist/components/Toast/Toast.cjs.map +1 -1
  43. package/dist/components/Toast/Toast.d.ts +13 -1
  44. package/dist/components/Toast/Toast.d.ts.map +1 -1
  45. package/dist/components/Toast/Toast.js +29 -5
  46. package/dist/components/Toast/Toast.js.map +1 -1
  47. package/dist/components/Toast/Toast.module.cjs +10 -1
  48. package/dist/components/Toast/Toast.module.cjs.map +1 -1
  49. package/dist/components/Toast/Toast.module.js +10 -1
  50. package/dist/components/Toast/Toast.module.js.map +1 -1
  51. package/dist/index.cjs +2 -0
  52. package/dist/index.d.ts +1 -0
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +2 -1
  55. package/dist/style.css +134 -49
  56. package/package.json +2 -2
  57. package/src/components/Badge/Badge.module.css +44 -11
  58. package/src/components/Badge/Badge.tsx +10 -2
  59. package/src/components/Button/IconButton/IconButton.tsx +12 -1
  60. package/src/components/Menu/ContextMenu.tsx +24 -0
  61. package/src/components/Menu/Menu.tsx +56 -1
  62. package/src/components/Menu/MenuContext.tsx +23 -0
  63. package/src/components/Menu/MenuItem.module.css +27 -5
  64. package/src/components/Menu/SubMenu.tsx +62 -0
  65. package/src/components/Toast/Toast.module.css +32 -2
  66. package/src/components/Toast/Toast.tsx +68 -6
  67. package/src/index.ts +1 -0
@@ -10,14 +10,18 @@ let react_jsx_runtime = require("react/jsx-runtime");
10
10
  /**
11
11
  * A Badge component.
12
12
  */
13
- var Badge = ({ children, kind = "default", className }) => {
14
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Typography.Typography, {
13
+ var Badge = ({ children, Icon, kind = "default", className }) => {
14
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_Typography.Typography, {
15
15
  as: "span",
16
16
  size: "sm",
17
17
  weight: "medium",
18
- className: (0, classnames.default)(require_Badge_module.default.badge, className),
18
+ className: (0, classnames.default)(require_Badge_module.default.badge, className, { [require_Badge_module.default["has-icon"]]: !!Icon }),
19
19
  "data-kind": kind,
20
- children
20
+ children: [Icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
21
+ width: "16",
22
+ height: "16",
23
+ "aria-hidden": true
24
+ }), children]
21
25
  });
22
26
  };
23
27
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.cjs","names":[],"sources":["../../../src/components/Badge/Badge.tsx"],"sourcesContent":["/*\nCopyright 2023 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 classnames from \"classnames\";\nimport React, { type PropsWithChildren } from \"react\";\nimport styles from \"./Badge.module.css\";\nimport { Typography } from \"../Typography/Typography\";\n\ntype BadgeProps = {\n /**\n * The CSS class name.\n */\n className?: string;\n /**\n * The type of badge.\n */\n kind?: \"default\" | \"grey\" | \"on-solid\" | \"blue\" | \"green\" | \"red\";\n};\n\n/**\n * A Badge component.\n */\nexport const Badge: React.FC<PropsWithChildren<BadgeProps>> = ({\n children,\n kind = \"default\",\n className,\n}) => {\n const classes = classnames(styles.badge, className);\n return (\n <Typography\n as=\"span\"\n size=\"sm\"\n weight=\"medium\"\n className={classes}\n data-kind={kind}\n >\n {children}\n </Typography>\n );\n};\n"],"mappings":";;;;;;;;;;;;AA0BA,IAAa,SAAkD,EAC7D,UACA,OAAO,WACP,gBACI;AAEJ,QACE,iBAAA,GAAA,kBAAA,KAAC,mBAAA,YAAD;EACE,IAAG;EACH,MAAK;EACL,QAAO;EACP,YAAA,GAAA,WAAA,SANuB,qBAAA,QAAO,OAAO,UAAU;EAO/C,aAAW;EAEV;EACU,CAAA"}
1
+ {"version":3,"file":"Badge.cjs","names":[],"sources":["../../../src/components/Badge/Badge.tsx"],"sourcesContent":["/*\nCopyright 2023 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 classnames from \"classnames\";\nimport React, { type ComponentType, type PropsWithChildren } from \"react\";\nimport styles from \"./Badge.module.css\";\nimport { Typography } from \"../Typography/Typography\";\n\ntype BadgeProps = {\n /**\n * The CSS class name.\n */\n className?: string;\n /**\n * The type of badge.\n */\n kind?: \"default\" | \"grey\" | \"on-solid\" | \"blue\" | \"green\" | \"red\";\n /**\n * An icon to display within the badge.\n */\n Icon?: ComponentType<React.SVGAttributes<SVGElement>>;\n};\n\n/**\n * A Badge component.\n */\nexport const Badge: React.FC<PropsWithChildren<BadgeProps>> = ({\n children,\n Icon,\n kind = \"default\",\n className,\n}) => {\n const classes = classnames(styles.badge, className, {\n [styles[\"has-icon\"]]: !!Icon,\n });\n return (\n <Typography\n as=\"span\"\n size=\"sm\"\n weight=\"medium\"\n className={classes}\n data-kind={kind}\n >\n {Icon && <Icon width=\"16\" height=\"16\" aria-hidden={true} />}\n {children}\n </Typography>\n );\n};\n"],"mappings":";;;;;;;;;;;;AA8BA,IAAa,SAAkD,EAC7D,UACA,MACA,OAAO,WACP,gBACI;AAIJ,QACE,iBAAA,GAAA,kBAAA,MAAC,mBAAA,YAAD;EACE,IAAG;EACH,MAAK;EACL,QAAO;EACP,YAAA,GAAA,WAAA,SARuB,qBAAA,QAAO,OAAO,WAAW,GACjD,qBAAA,QAAO,cAAc,CAAC,CAAC,MACzB,CAAC;EAOE,aAAW;YALb,CAOG,QAAQ,iBAAA,GAAA,kBAAA,KAAC,MAAD;GAAM,OAAM;GAAK,QAAO;GAAK,eAAa;GAAQ,CAAA,EAC1D,SACU"}
@@ -1,4 +1,4 @@
1
- import { default as React, PropsWithChildren } from 'react';
1
+ import { default as React, ComponentType, PropsWithChildren } from 'react';
2
2
  type BadgeProps = {
3
3
  /**
4
4
  * The CSS class name.
@@ -8,6 +8,10 @@ type BadgeProps = {
8
8
  * The type of badge.
9
9
  */
10
10
  kind?: "default" | "grey" | "on-solid" | "blue" | "green" | "red";
11
+ /**
12
+ * An icon to display within the badge.
13
+ */
14
+ Icon?: ComponentType<React.SVGAttributes<SVGElement>>;
11
15
  };
12
16
  /**
13
17
  * A Badge component.
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../src/components/Badge/Badge.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAItD,KAAK,UAAU,GAAG;IAChB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;CACnE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAiBzD,CAAC"}
1
+ {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../src/components/Badge/Badge.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,EAAE,KAAK,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAI1E,KAAK,UAAU,GAAG;IAChB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;IAClE;;OAEG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC;CACvD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAqBzD,CAAC"}
@@ -2,19 +2,23 @@ import { Typography } from "../Typography/Typography.js";
2
2
  import Badge_module_default from "./Badge.module.js";
3
3
  import classNames from "classnames";
4
4
  import "react";
5
- import { jsx } from "react/jsx-runtime";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/components/Badge/Badge.tsx
7
7
  /**
8
8
  * A Badge component.
9
9
  */
10
- var Badge = ({ children, kind = "default", className }) => {
11
- return /* @__PURE__ */ jsx(Typography, {
10
+ var Badge = ({ children, Icon, kind = "default", className }) => {
11
+ return /* @__PURE__ */ jsxs(Typography, {
12
12
  as: "span",
13
13
  size: "sm",
14
14
  weight: "medium",
15
- className: classNames(Badge_module_default.badge, className),
15
+ className: classNames(Badge_module_default.badge, className, { [Badge_module_default["has-icon"]]: !!Icon }),
16
16
  "data-kind": kind,
17
- children
17
+ children: [Icon && /* @__PURE__ */ jsx(Icon, {
18
+ width: "16",
19
+ height: "16",
20
+ "aria-hidden": true
21
+ }), children]
18
22
  });
19
23
  };
20
24
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.js","names":[],"sources":["../../../src/components/Badge/Badge.tsx"],"sourcesContent":["/*\nCopyright 2023 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 classnames from \"classnames\";\nimport React, { type PropsWithChildren } from \"react\";\nimport styles from \"./Badge.module.css\";\nimport { Typography } from \"../Typography/Typography\";\n\ntype BadgeProps = {\n /**\n * The CSS class name.\n */\n className?: string;\n /**\n * The type of badge.\n */\n kind?: \"default\" | \"grey\" | \"on-solid\" | \"blue\" | \"green\" | \"red\";\n};\n\n/**\n * A Badge component.\n */\nexport const Badge: React.FC<PropsWithChildren<BadgeProps>> = ({\n children,\n kind = \"default\",\n className,\n}) => {\n const classes = classnames(styles.badge, className);\n return (\n <Typography\n as=\"span\"\n size=\"sm\"\n weight=\"medium\"\n className={classes}\n data-kind={kind}\n >\n {children}\n </Typography>\n );\n};\n"],"mappings":";;;;;;;;;AA0BA,IAAa,SAAkD,EAC7D,UACA,OAAO,WACP,gBACI;AAEJ,QACE,oBAAC,YAAD;EACE,IAAG;EACH,MAAK;EACL,QAAO;EACP,WANY,WAAW,qBAAO,OAAO,UAAU;EAO/C,aAAW;EAEV;EACU,CAAA"}
1
+ {"version":3,"file":"Badge.js","names":[],"sources":["../../../src/components/Badge/Badge.tsx"],"sourcesContent":["/*\nCopyright 2023 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 classnames from \"classnames\";\nimport React, { type ComponentType, type PropsWithChildren } from \"react\";\nimport styles from \"./Badge.module.css\";\nimport { Typography } from \"../Typography/Typography\";\n\ntype BadgeProps = {\n /**\n * The CSS class name.\n */\n className?: string;\n /**\n * The type of badge.\n */\n kind?: \"default\" | \"grey\" | \"on-solid\" | \"blue\" | \"green\" | \"red\";\n /**\n * An icon to display within the badge.\n */\n Icon?: ComponentType<React.SVGAttributes<SVGElement>>;\n};\n\n/**\n * A Badge component.\n */\nexport const Badge: React.FC<PropsWithChildren<BadgeProps>> = ({\n children,\n Icon,\n kind = \"default\",\n className,\n}) => {\n const classes = classnames(styles.badge, className, {\n [styles[\"has-icon\"]]: !!Icon,\n });\n return (\n <Typography\n as=\"span\"\n size=\"sm\"\n weight=\"medium\"\n className={classes}\n data-kind={kind}\n >\n {Icon && <Icon width=\"16\" height=\"16\" aria-hidden={true} />}\n {children}\n </Typography>\n );\n};\n"],"mappings":";;;;;;;;;AA8BA,IAAa,SAAkD,EAC7D,UACA,MACA,OAAO,WACP,gBACI;AAIJ,QACE,qBAAC,YAAD;EACE,IAAG;EACH,MAAK;EACL,QAAO;EACP,WARY,WAAW,qBAAO,OAAO,WAAW,GACjD,qBAAO,cAAc,CAAC,CAAC,MACzB,CAAC;EAOE,aAAW;YALb,CAOG,QAAQ,oBAAC,MAAD;GAAM,OAAM;GAAK,QAAO;GAAK,eAAa;GAAQ,CAAA,EAC1D,SACU"}
@@ -1,4 +1,7 @@
1
- var Badge_module_default = { badge: "_badge_18gm1_8" };
1
+ var Badge_module_default = {
2
+ badge: "_badge_10dml_8",
3
+ "has-icon": "_has-icon_10dml_18"
4
+ };
2
5
  //#endregion
3
6
  exports.default = Badge_module_default;
4
7
 
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.module.cjs","names":[],"sources":["../../../src/components/Badge/Badge.module.css"],"sourcesContent":["/*\nCopyright 2023 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\n.badge {\n display: inline-flex;\n gap: var(--cpd-space-1x);\n align-items: center;\n border-radius: 9999px; /* pill effect */\n padding: var(--cpd-space-1x) var(--cpd-space-3x);\n}\n\n.badge[data-kind=\"default\"] {\n border: 1px solid var(--cpd-color-alpha-gray-400);\n outline: none;\n color: var(--cpd-color-gray-1100);\n}\n\n.badge[data-kind=\"grey\"] {\n background: var(--cpd-color-alpha-gray-300);\n color: var(--cpd-color-gray-1100);\n}\n\n.badge[data-kind=\"on-solid\"] {\n background: var(--cpd-color-alpha-gray-1200);\n color: var(--cpd-color-text-on-solid-primary);\n}\n\n.badge[data-kind=\"blue\"] {\n background: var(--cpd-color-alpha-blue-300);\n color: var(--cpd-color-blue-1100);\n}\n\n.badge[data-kind=\"green\"] {\n background: var(--cpd-color-alpha-green-300);\n color: var(--cpd-color-green-1100);\n}\n\n.badge[data-kind=\"red\"] {\n background: var(--cpd-color-alpha-red-300);\n color: var(--cpd-color-red-1100);\n}\n\n@media (forced-colors: active) {\n .badge {\n outline: 1px solid transparent;\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Badge.module.cjs","names":[],"sources":["../../../src/components/Badge/Badge.module.css"],"sourcesContent":["/*\nCopyright 2023 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\n.badge {\n display: inline-flex;\n gap: var(--cpd-space-1x);\n align-items: center;\n border-radius: 9999px; /* pill effect */\n padding: var(--cpd-space-1x) var(--cpd-space-3x);\n box-sizing: border-box;\n min-block-size: 28px;\n}\n\n.has-icon {\n padding-inline-start: var(--cpd-space-2x);\n}\n\n.badge[data-kind=\"default\"] {\n border: 1px solid var(--cpd-color-border-interactive-secondary);\n\n /* To keep the same height than the other badges despite the border */\n padding-block: calc(var(--cpd-space-1x) - 1px);\n outline: none;\n color: var(--cpd-color-text-primary);\n\n svg {\n color: var(--cpd-color-icon-primary);\n }\n}\n\n.badge[data-kind=\"grey\"] {\n background: var(--cpd-color-bg-badge-secondary);\n color: var(--cpd-color-text-primary);\n\n svg {\n color: var(--cpd-color-icon-primary);\n }\n}\n\n.badge[data-kind=\"on-solid\"] {\n background: var(--cpd-color-bg-badge-primary);\n color: var(--cpd-color-text-on-solid-primary);\n\n svg {\n color: var(--cpd-color-icon-on-solid-primary);\n }\n}\n\n.badge[data-kind=\"blue\"] {\n background: var(--cpd-color-bg-badge-info);\n color: var(--cpd-color-text-badge-info);\n\n svg {\n color: var(--cpd-color-icon-info-primary);\n }\n}\n\n.badge[data-kind=\"green\"] {\n background: var(--cpd-color-bg-badge-accent);\n color: var(--cpd-color-text-badge-accent);\n\n svg {\n color: var(--cpd-color-icon-accent-primary);\n }\n}\n\n.badge[data-kind=\"red\"] {\n background: var(--cpd-color-bg-badge-critical);\n color: var(--cpd-color-text-critical-primary);\n\n svg {\n color: var(--cpd-color-icon-critical-primary);\n }\n}\n\n@media (forced-colors: active) {\n .badge {\n outline: 1px solid transparent;\n }\n}\n"],"mappings":""}
@@ -1,4 +1,7 @@
1
- var Badge_module_default = { badge: "_badge_18gm1_8" };
1
+ var Badge_module_default = {
2
+ badge: "_badge_10dml_8",
3
+ "has-icon": "_has-icon_10dml_18"
4
+ };
2
5
  //#endregion
3
6
  export { Badge_module_default as default };
4
7
 
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.module.js","names":[],"sources":["../../../src/components/Badge/Badge.module.css"],"sourcesContent":["/*\nCopyright 2023 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\n.badge {\n display: inline-flex;\n gap: var(--cpd-space-1x);\n align-items: center;\n border-radius: 9999px; /* pill effect */\n padding: var(--cpd-space-1x) var(--cpd-space-3x);\n}\n\n.badge[data-kind=\"default\"] {\n border: 1px solid var(--cpd-color-alpha-gray-400);\n outline: none;\n color: var(--cpd-color-gray-1100);\n}\n\n.badge[data-kind=\"grey\"] {\n background: var(--cpd-color-alpha-gray-300);\n color: var(--cpd-color-gray-1100);\n}\n\n.badge[data-kind=\"on-solid\"] {\n background: var(--cpd-color-alpha-gray-1200);\n color: var(--cpd-color-text-on-solid-primary);\n}\n\n.badge[data-kind=\"blue\"] {\n background: var(--cpd-color-alpha-blue-300);\n color: var(--cpd-color-blue-1100);\n}\n\n.badge[data-kind=\"green\"] {\n background: var(--cpd-color-alpha-green-300);\n color: var(--cpd-color-green-1100);\n}\n\n.badge[data-kind=\"red\"] {\n background: var(--cpd-color-alpha-red-300);\n color: var(--cpd-color-red-1100);\n}\n\n@media (forced-colors: active) {\n .badge {\n outline: 1px solid transparent;\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Badge.module.js","names":[],"sources":["../../../src/components/Badge/Badge.module.css"],"sourcesContent":["/*\nCopyright 2023 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\n.badge {\n display: inline-flex;\n gap: var(--cpd-space-1x);\n align-items: center;\n border-radius: 9999px; /* pill effect */\n padding: var(--cpd-space-1x) var(--cpd-space-3x);\n box-sizing: border-box;\n min-block-size: 28px;\n}\n\n.has-icon {\n padding-inline-start: var(--cpd-space-2x);\n}\n\n.badge[data-kind=\"default\"] {\n border: 1px solid var(--cpd-color-border-interactive-secondary);\n\n /* To keep the same height than the other badges despite the border */\n padding-block: calc(var(--cpd-space-1x) - 1px);\n outline: none;\n color: var(--cpd-color-text-primary);\n\n svg {\n color: var(--cpd-color-icon-primary);\n }\n}\n\n.badge[data-kind=\"grey\"] {\n background: var(--cpd-color-bg-badge-secondary);\n color: var(--cpd-color-text-primary);\n\n svg {\n color: var(--cpd-color-icon-primary);\n }\n}\n\n.badge[data-kind=\"on-solid\"] {\n background: var(--cpd-color-bg-badge-primary);\n color: var(--cpd-color-text-on-solid-primary);\n\n svg {\n color: var(--cpd-color-icon-on-solid-primary);\n }\n}\n\n.badge[data-kind=\"blue\"] {\n background: var(--cpd-color-bg-badge-info);\n color: var(--cpd-color-text-badge-info);\n\n svg {\n color: var(--cpd-color-icon-info-primary);\n }\n}\n\n.badge[data-kind=\"green\"] {\n background: var(--cpd-color-bg-badge-accent);\n color: var(--cpd-color-text-badge-accent);\n\n svg {\n color: var(--cpd-color-icon-accent-primary);\n }\n}\n\n.badge[data-kind=\"red\"] {\n background: var(--cpd-color-bg-badge-critical);\n color: var(--cpd-color-text-critical-primary);\n\n svg {\n color: var(--cpd-color-icon-critical-primary);\n }\n}\n\n@media (forced-colors: active) {\n .badge {\n outline: 1px solid transparent;\n }\n}\n"],"mappings":""}
@@ -12,7 +12,7 @@ let react_jsx_runtime = require("react/jsx-runtime");
12
12
  /**
13
13
  * Display an icon as a button. Can render an indicator
14
14
  */
15
- var IconButton = (0, react.forwardRef)(function IconButton({ kind = "primary", children, className, indicator, size = "32px", style, disabled, destructive, tooltip, noBackground = false, ...props }, ref) {
15
+ var IconButton = (0, react.forwardRef)(function IconButton({ kind = "primary", children, className, indicator, size = "32px", style, disabled, destructive, tooltip, tooltipPlacement, noBackground = false, ...props }, ref) {
16
16
  const button = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_UnstyledButton.UnstyledButton, {
17
17
  as: "button",
18
18
  ref,
@@ -36,6 +36,7 @@ var IconButton = (0, react.forwardRef)(function IconButton({ kind = "primary", c
36
36
  });
37
37
  return tooltip ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Tooltip.Tooltip, {
38
38
  label: tooltip,
39
+ placement: tooltipPlacement,
39
40
  children: button
40
41
  }) : button;
41
42
  });
@@ -1 +1 @@
1
- {"version":3,"file":"IconButton.cjs","names":[],"sources":["../../../../src/components/Button/IconButton/IconButton.tsx"],"sourcesContent":["/*\nCopyright 2023 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 React, { type PropsWithChildren, forwardRef } from \"react\";\nimport classnames from \"classnames\";\n\nimport styles from \"./IconButton.module.css\";\nimport { UnstyledButton, type UnstyledButtonPropsFor } from \"../UnstyledButton\";\nimport { IndicatorIcon } from \"../../Icon/IndicatorIcon/IndicatorIcon\";\nimport { Tooltip } from \"../../Tooltip/Tooltip\";\n\ntype IconButtonProps = UnstyledButtonPropsFor<\"button\"> & {\n /**\n * The type of button.\n * @default \"primary\"\n */\n kind?: \"primary\" | \"secondary\";\n /**\n * The CSS class name.\n */\n className?: string;\n /**\n * The size of the button in CSS units, e.g. `\"24px\"`.\n * Note that this is the size of the *button* itself: the icon will be 0.75 * this size\n * @default 32px\n */\n size?: CSSStyleDeclaration[\"height\"];\n /**\n * The icon button indicator dot displayed on the top right\n * As in IndicatorIcon\n */\n indicator?: \"default\" | \"success\" | \"critical\";\n /**\n * Whether the button is interactable\n */\n disabled?: boolean;\n /**\n * Whether this button triggers a destructive action.\n * @default false\n */\n destructive?: boolean;\n /**\n * Optional tooltip for the button\n */\n tooltip?: string;\n /**\n * Hide the background when the button is not active or hovered.\n * @default false\n */\n noBackground?: boolean;\n};\n\n/**\n * Display an icon as a button. Can render an indicator\n */\nexport const IconButton = forwardRef<\n HTMLButtonElement,\n PropsWithChildren<IconButtonProps>\n>(function IconButton(\n {\n kind = \"primary\",\n children,\n className,\n indicator,\n size = \"32px\",\n style,\n disabled,\n destructive,\n tooltip,\n noBackground = false,\n ...props\n },\n ref,\n) {\n const classes = classnames(styles[\"icon-button\"], className, {\n [styles.destructive]: destructive,\n [styles[\"no-background\"]]: noBackground,\n });\n\n const button = (\n <UnstyledButton\n as=\"button\"\n ref={ref}\n className={classes}\n style={\n {\n \"--cpd-icon-button-size\": size,\n ...style,\n } as React.CSSProperties\n }\n disabled={disabled}\n {...props}\n data-indicator={indicator}\n data-kind={kind}\n >\n <IndicatorIcon\n indicator={indicator}\n colour={disabled ? \"var(--cpd-color-icon-disabled)\" : undefined}\n >\n {React.Children.only(children)}\n </IndicatorIcon>\n </UnstyledButton>\n );\n\n return tooltip ? <Tooltip label={tooltip}>{button}</Tooltip> : button;\n});\n"],"mappings":";;;;;;;;;;;;;;AA2DA,IAAa,cAAA,GAAA,MAAA,YAGX,SAAS,WACT,EACE,OAAO,WACP,UACA,WACA,WACA,OAAO,QACP,OACA,UACA,aACA,SACA,eAAe,OACf,GAAG,SAEL,KACA;CAMA,MAAM,SACJ,iBAAA,GAAA,kBAAA,KAAC,uBAAA,gBAAD;EACE,IAAG;EACE;EACL,YAAA,GAAA,WAAA,SATuB,0BAAA,QAAO,gBAAgB,WAAW;IAC1D,0BAAA,QAAO,cAAc;IACrB,0BAAA,QAAO,mBAAmB;GAC5B,CAAC;EAOE,OACE;GACE,0BAA0B;GAC1B,GAAG;GACJ;EAEO;EACV,GAAI;EACJ,kBAAgB;EAChB,aAAW;YAEX,iBAAA,GAAA,kBAAA,KAAC,sBAAA,eAAD;GACa;GACX,QAAQ,WAAW,mCAAmC,KAAA;aAErD,MAAA,QAAM,SAAS,KAAK,SAAS;GAChB,CAAA;EACD,CAAA;AAGnB,QAAO,UAAU,iBAAA,GAAA,kBAAA,KAAC,gBAAA,SAAD;EAAS,OAAO;YAAU;EAAiB,CAAA,GAAG;EAC/D"}
1
+ {"version":3,"file":"IconButton.cjs","names":[],"sources":["../../../../src/components/Button/IconButton/IconButton.tsx"],"sourcesContent":["/*\nCopyright 2023 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 React, { type PropsWithChildren, forwardRef } from \"react\";\nimport classnames from \"classnames\";\n\nimport styles from \"./IconButton.module.css\";\nimport { UnstyledButton, type UnstyledButtonPropsFor } from \"../UnstyledButton\";\nimport { IndicatorIcon } from \"../../Icon/IndicatorIcon/IndicatorIcon\";\nimport { Tooltip } from \"../../Tooltip/Tooltip\";\n\ntype IconButtonProps = UnstyledButtonPropsFor<\"button\"> & {\n /**\n * The type of button.\n * @default \"primary\"\n */\n kind?: \"primary\" | \"secondary\";\n /**\n * The CSS class name.\n */\n className?: string;\n /**\n * The size of the button in CSS units, e.g. `\"24px\"`.\n * Note that this is the size of the *button* itself: the icon will be 0.75 * this size\n * @default 32px\n */\n size?: CSSStyleDeclaration[\"height\"];\n /**\n * The icon button indicator dot displayed on the top right\n * As in IndicatorIcon\n */\n indicator?: \"default\" | \"success\" | \"critical\";\n /**\n * Whether the button is interactable\n */\n disabled?: boolean;\n /**\n * Whether this button triggers a destructive action.\n * @default false\n */\n destructive?: boolean;\n /**\n * Optional tooltip for the button\n */\n tooltip?: string;\n /**\n * The placement of the tooltip, if `tooltip` is provided.\n */\n tooltipPlacement?: React.ComponentProps<typeof Tooltip>[\"placement\"];\n /**\n * Hide the background when the button is not active or hovered.\n * @default false\n */\n noBackground?: boolean;\n};\n\n/**\n * Display an icon as a button. Can render an indicator\n */\nexport const IconButton = forwardRef<\n HTMLButtonElement,\n PropsWithChildren<IconButtonProps>\n>(function IconButton(\n {\n kind = \"primary\",\n children,\n className,\n indicator,\n size = \"32px\",\n style,\n disabled,\n destructive,\n tooltip,\n tooltipPlacement,\n noBackground = false,\n ...props\n },\n ref,\n) {\n const classes = classnames(styles[\"icon-button\"], className, {\n [styles.destructive]: destructive,\n [styles[\"no-background\"]]: noBackground,\n });\n\n const button = (\n <UnstyledButton\n as=\"button\"\n ref={ref}\n className={classes}\n style={\n {\n \"--cpd-icon-button-size\": size,\n ...style,\n } as React.CSSProperties\n }\n disabled={disabled}\n {...props}\n data-indicator={indicator}\n data-kind={kind}\n >\n <IndicatorIcon\n indicator={indicator}\n colour={disabled ? \"var(--cpd-color-icon-disabled)\" : undefined}\n >\n {React.Children.only(children)}\n </IndicatorIcon>\n </UnstyledButton>\n );\n\n return tooltip ? (\n <Tooltip label={tooltip} placement={tooltipPlacement}>\n {button}\n </Tooltip>\n ) : (\n button\n );\n});\n"],"mappings":";;;;;;;;;;;;;;AA+DA,IAAa,cAAA,GAAA,MAAA,YAGX,SAAS,WACT,EACE,OAAO,WACP,UACA,WACA,WACA,OAAO,QACP,OACA,UACA,aACA,SACA,kBACA,eAAe,OACf,GAAG,SAEL,KACA;CAMA,MAAM,SACJ,iBAAA,GAAA,kBAAA,KAAC,uBAAA,gBAAD;EACE,IAAG;EACE;EACL,YAAA,GAAA,WAAA,SATuB,0BAAA,QAAO,gBAAgB,WAAW;IAC1D,0BAAA,QAAO,cAAc;IACrB,0BAAA,QAAO,mBAAmB;GAC5B,CAAC;EAOE,OACE;GACE,0BAA0B;GAC1B,GAAG;GACJ;EAEO;EACV,GAAI;EACJ,kBAAgB;EAChB,aAAW;YAEX,iBAAA,GAAA,kBAAA,KAAC,sBAAA,eAAD;GACa;GACX,QAAQ,WAAW,mCAAmC,KAAA;aAErD,MAAA,QAAM,SAAS,KAAK,SAAS;GAChB,CAAA;EACD,CAAA;AAGnB,QAAO,UACL,iBAAA,GAAA,kBAAA,KAAC,gBAAA,SAAD;EAAS,OAAO;EAAS,WAAW;YACjC;EACO,CAAA,GAEV;EAEF"}
@@ -1,5 +1,6 @@
1
1
  import { default as React } from 'react';
2
2
  import { UnstyledButtonPropsFor } from '../UnstyledButton';
3
+ import { Tooltip } from '../../Tooltip/Tooltip';
3
4
  type IconButtonProps = UnstyledButtonPropsFor<"button"> & {
4
5
  /**
5
6
  * The type of button.
@@ -34,6 +35,10 @@ type IconButtonProps = UnstyledButtonPropsFor<"button"> & {
34
35
  * Optional tooltip for the button
35
36
  */
36
37
  tooltip?: string;
38
+ /**
39
+ * The placement of the tooltip, if `tooltip` is provided.
40
+ */
41
+ tooltipPlacement?: React.ComponentProps<typeof Tooltip>["placement"];
37
42
  /**
38
43
  * Hide the background when the button is not active or hovered.
39
44
  * @default false
@@ -1 +1 @@
1
- {"version":3,"file":"IconButton.d.ts","sourceRoot":"","sources":["../../../../src/components/Button/IconButton/IconButton.tsx"],"names":[],"mappings":"AAOA,OAAO,KAA6C,MAAM,OAAO,CAAC;AAIlE,OAAO,EAAkB,KAAK,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAIhF,KAAK,eAAe,GAAG,sBAAsB,CAAC,QAAQ,CAAC,GAAG;IACxD;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;IAC/B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,IAAI,CAAC,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IACrC;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;IAC/C;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,iIAkDrB,CAAC"}
1
+ {"version":3,"file":"IconButton.d.ts","sourceRoot":"","sources":["../../../../src/components/Button/IconButton/IconButton.tsx"],"names":[],"mappings":"AAOA,OAAO,KAA6C,MAAM,OAAO,CAAC;AAIlE,OAAO,EAAkB,KAAK,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEhF,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,KAAK,eAAe,GAAG,sBAAsB,CAAC,QAAQ,CAAC,GAAG;IACxD;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;IAC/B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,IAAI,CAAC,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IACrC;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;IAC/C;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,gBAAgB,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC;IACrE;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,iIAyDrB,CAAC"}
@@ -9,7 +9,7 @@ import { jsx } from "react/jsx-runtime";
9
9
  /**
10
10
  * Display an icon as a button. Can render an indicator
11
11
  */
12
- var IconButton = forwardRef(function IconButton({ kind = "primary", children, className, indicator, size = "32px", style, disabled, destructive, tooltip, noBackground = false, ...props }, ref) {
12
+ var IconButton = forwardRef(function IconButton({ kind = "primary", children, className, indicator, size = "32px", style, disabled, destructive, tooltip, tooltipPlacement, noBackground = false, ...props }, ref) {
13
13
  const button = /* @__PURE__ */ jsx(UnstyledButton, {
14
14
  as: "button",
15
15
  ref,
@@ -33,6 +33,7 @@ var IconButton = forwardRef(function IconButton({ kind = "primary", children, cl
33
33
  });
34
34
  return tooltip ? /* @__PURE__ */ jsx(Tooltip, {
35
35
  label: tooltip,
36
+ placement: tooltipPlacement,
36
37
  children: button
37
38
  }) : button;
38
39
  });
@@ -1 +1 @@
1
- {"version":3,"file":"IconButton.js","names":[],"sources":["../../../../src/components/Button/IconButton/IconButton.tsx"],"sourcesContent":["/*\nCopyright 2023 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 React, { type PropsWithChildren, forwardRef } from \"react\";\nimport classnames from \"classnames\";\n\nimport styles from \"./IconButton.module.css\";\nimport { UnstyledButton, type UnstyledButtonPropsFor } from \"../UnstyledButton\";\nimport { IndicatorIcon } from \"../../Icon/IndicatorIcon/IndicatorIcon\";\nimport { Tooltip } from \"../../Tooltip/Tooltip\";\n\ntype IconButtonProps = UnstyledButtonPropsFor<\"button\"> & {\n /**\n * The type of button.\n * @default \"primary\"\n */\n kind?: \"primary\" | \"secondary\";\n /**\n * The CSS class name.\n */\n className?: string;\n /**\n * The size of the button in CSS units, e.g. `\"24px\"`.\n * Note that this is the size of the *button* itself: the icon will be 0.75 * this size\n * @default 32px\n */\n size?: CSSStyleDeclaration[\"height\"];\n /**\n * The icon button indicator dot displayed on the top right\n * As in IndicatorIcon\n */\n indicator?: \"default\" | \"success\" | \"critical\";\n /**\n * Whether the button is interactable\n */\n disabled?: boolean;\n /**\n * Whether this button triggers a destructive action.\n * @default false\n */\n destructive?: boolean;\n /**\n * Optional tooltip for the button\n */\n tooltip?: string;\n /**\n * Hide the background when the button is not active or hovered.\n * @default false\n */\n noBackground?: boolean;\n};\n\n/**\n * Display an icon as a button. Can render an indicator\n */\nexport const IconButton = forwardRef<\n HTMLButtonElement,\n PropsWithChildren<IconButtonProps>\n>(function IconButton(\n {\n kind = \"primary\",\n children,\n className,\n indicator,\n size = \"32px\",\n style,\n disabled,\n destructive,\n tooltip,\n noBackground = false,\n ...props\n },\n ref,\n) {\n const classes = classnames(styles[\"icon-button\"], className, {\n [styles.destructive]: destructive,\n [styles[\"no-background\"]]: noBackground,\n });\n\n const button = (\n <UnstyledButton\n as=\"button\"\n ref={ref}\n className={classes}\n style={\n {\n \"--cpd-icon-button-size\": size,\n ...style,\n } as React.CSSProperties\n }\n disabled={disabled}\n {...props}\n data-indicator={indicator}\n data-kind={kind}\n >\n <IndicatorIcon\n indicator={indicator}\n colour={disabled ? \"var(--cpd-color-icon-disabled)\" : undefined}\n >\n {React.Children.only(children)}\n </IndicatorIcon>\n </UnstyledButton>\n );\n\n return tooltip ? <Tooltip label={tooltip}>{button}</Tooltip> : button;\n});\n"],"mappings":";;;;;;;;;;;AA2DA,IAAa,aAAa,WAGxB,SAAS,WACT,EACE,OAAO,WACP,UACA,WACA,WACA,OAAO,QACP,OACA,UACA,aACA,SACA,eAAe,OACf,GAAG,SAEL,KACA;CAMA,MAAM,SACJ,oBAAC,gBAAD;EACE,IAAG;EACE;EACL,WATY,WAAW,0BAAO,gBAAgB,WAAW;IAC1D,0BAAO,cAAc;IACrB,0BAAO,mBAAmB;GAC5B,CAAC;EAOE,OACE;GACE,0BAA0B;GAC1B,GAAG;GACJ;EAEO;EACV,GAAI;EACJ,kBAAgB;EAChB,aAAW;YAEX,oBAAC,eAAD;GACa;GACX,QAAQ,WAAW,mCAAmC,KAAA;aAErD,MAAM,SAAS,KAAK,SAAS;GAChB,CAAA;EACD,CAAA;AAGnB,QAAO,UAAU,oBAAC,SAAD;EAAS,OAAO;YAAU;EAAiB,CAAA,GAAG;EAC/D"}
1
+ {"version":3,"file":"IconButton.js","names":[],"sources":["../../../../src/components/Button/IconButton/IconButton.tsx"],"sourcesContent":["/*\nCopyright 2023 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 React, { type PropsWithChildren, forwardRef } from \"react\";\nimport classnames from \"classnames\";\n\nimport styles from \"./IconButton.module.css\";\nimport { UnstyledButton, type UnstyledButtonPropsFor } from \"../UnstyledButton\";\nimport { IndicatorIcon } from \"../../Icon/IndicatorIcon/IndicatorIcon\";\nimport { Tooltip } from \"../../Tooltip/Tooltip\";\n\ntype IconButtonProps = UnstyledButtonPropsFor<\"button\"> & {\n /**\n * The type of button.\n * @default \"primary\"\n */\n kind?: \"primary\" | \"secondary\";\n /**\n * The CSS class name.\n */\n className?: string;\n /**\n * The size of the button in CSS units, e.g. `\"24px\"`.\n * Note that this is the size of the *button* itself: the icon will be 0.75 * this size\n * @default 32px\n */\n size?: CSSStyleDeclaration[\"height\"];\n /**\n * The icon button indicator dot displayed on the top right\n * As in IndicatorIcon\n */\n indicator?: \"default\" | \"success\" | \"critical\";\n /**\n * Whether the button is interactable\n */\n disabled?: boolean;\n /**\n * Whether this button triggers a destructive action.\n * @default false\n */\n destructive?: boolean;\n /**\n * Optional tooltip for the button\n */\n tooltip?: string;\n /**\n * The placement of the tooltip, if `tooltip` is provided.\n */\n tooltipPlacement?: React.ComponentProps<typeof Tooltip>[\"placement\"];\n /**\n * Hide the background when the button is not active or hovered.\n * @default false\n */\n noBackground?: boolean;\n};\n\n/**\n * Display an icon as a button. Can render an indicator\n */\nexport const IconButton = forwardRef<\n HTMLButtonElement,\n PropsWithChildren<IconButtonProps>\n>(function IconButton(\n {\n kind = \"primary\",\n children,\n className,\n indicator,\n size = \"32px\",\n style,\n disabled,\n destructive,\n tooltip,\n tooltipPlacement,\n noBackground = false,\n ...props\n },\n ref,\n) {\n const classes = classnames(styles[\"icon-button\"], className, {\n [styles.destructive]: destructive,\n [styles[\"no-background\"]]: noBackground,\n });\n\n const button = (\n <UnstyledButton\n as=\"button\"\n ref={ref}\n className={classes}\n style={\n {\n \"--cpd-icon-button-size\": size,\n ...style,\n } as React.CSSProperties\n }\n disabled={disabled}\n {...props}\n data-indicator={indicator}\n data-kind={kind}\n >\n <IndicatorIcon\n indicator={indicator}\n colour={disabled ? \"var(--cpd-color-icon-disabled)\" : undefined}\n >\n {React.Children.only(children)}\n </IndicatorIcon>\n </UnstyledButton>\n );\n\n return tooltip ? (\n <Tooltip label={tooltip} placement={tooltipPlacement}>\n {button}\n </Tooltip>\n ) : (\n button\n );\n});\n"],"mappings":";;;;;;;;;;;AA+DA,IAAa,aAAa,WAGxB,SAAS,WACT,EACE,OAAO,WACP,UACA,WACA,WACA,OAAO,QACP,OACA,UACA,aACA,SACA,kBACA,eAAe,OACf,GAAG,SAEL,KACA;CAMA,MAAM,SACJ,oBAAC,gBAAD;EACE,IAAG;EACE;EACL,WATY,WAAW,0BAAO,gBAAgB,WAAW;IAC1D,0BAAO,cAAc;IACrB,0BAAO,mBAAmB;GAC5B,CAAC;EAOE,OACE;GACE,0BAA0B;GAC1B,GAAG;GACJ;EAEO;EACV,GAAI;EACJ,kBAAgB;EAChB,aAAW;YAEX,oBAAC,eAAD;GACa;GACX,QAAQ,WAAW,mCAAmC,KAAA;aAErD,MAAM,SAAS,KAAK,SAAS;GAChB,CAAA;EACD,CAAA;AAGnB,QAAO,UACL,oBAAC,SAAD;EAAS,OAAO;EAAS,WAAW;YACjC;EACO,CAAA,GAEV;EAEF"}
@@ -17,6 +17,22 @@ var ContextMenuItemWrapper = ({ onSelect, children }) => /* @__PURE__ */ (0, rea
17
17
  asChild: true,
18
18
  children
19
19
  });
20
+ var ContextSubMenuWrapper = ({ trigger, children, open, onOpenChange }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_radix_ui_react_context_menu.ContextMenuSub, {
21
+ open,
22
+ onOpenChange,
23
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_context_menu.ContextMenuSubTrigger, {
24
+ asChild: true,
25
+ children: trigger
26
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_context_menu.ContextMenuPortal, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_context_menu.ContextMenuSubContent, {
27
+ asChild: true,
28
+ alignOffset: -20,
29
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_FloatingMenu.FloatingMenu, {
30
+ title: "",
31
+ showTitle: false,
32
+ children
33
+ })
34
+ }) })]
35
+ });
20
36
  /**
21
37
  * A menu opened by right-clicking or long-pressing another UI element.
22
38
  */
@@ -30,6 +46,7 @@ var ContextMenu = ({ title, showTitle = true, onOpenChange: onOpenChangeProp, tr
30
46
  const drawer = platform === "android" || platform === "ios";
31
47
  const context = (0, react.useMemo)(() => ({
32
48
  MenuItemWrapper: drawer ? null : ContextMenuItemWrapper,
49
+ SubMenuWrapper: drawer ? null : ContextSubMenuWrapper,
33
50
  onOpenChange
34
51
  }), [onOpenChange]);
35
52
  const children = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MenuContext.MenuContext.Provider, {
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMenu.cjs","names":[],"sources":["../../../src/components/Menu/ContextMenu.tsx"],"sourcesContent":["/*\nCopyright 2023 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 React, {\n type FC,\n type ReactNode,\n useCallback,\n useMemo,\n useState,\n} from \"react\";\nimport {\n Root,\n Trigger,\n Portal,\n Content,\n ContextMenuItem,\n} from \"@radix-ui/react-context-menu\";\nimport { FloatingMenu } from \"./FloatingMenu\";\nimport { Drawer } from \"vaul\";\nimport classnames from \"classnames\";\nimport drawerStyles from \"./DrawerMenu.module.css\";\nimport {\n MenuContext,\n type MenuData,\n type MenuItemWrapperProps,\n} from \"./MenuContext\";\nimport { DrawerMenu } from \"./DrawerMenu\";\nimport { getPlatform } from \"../../utils/platform\";\n\ninterface Props {\n /**\n * The menu title.\n */\n title: string;\n /**\n * Wether the title is displayed.\n * @default true\n */\n showTitle?: boolean;\n /**\n * Event handler called when the open state of the menu changes.\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * The trigger that can be right-clicked or long-pressed to open the menu.\n * This must be a component that accepts a ref and spreads props.\n * https://www.radix-ui.com/primitives/docs/guides/composition\n */\n trigger: ReactNode;\n /**\n * Whether the functionality of this menu is available through some other\n * keyboard-accessible means. Preferably this should be true, because context\n * menus are potentially difficult to discover, but if false the trigger will\n * become focusable so that it can be opened via keyboard navigation.\n */\n hasAccessibleAlternative: boolean;\n /**\n * The menu contents.\n */\n children: ReactNode;\n}\n\nconst ContextMenuItemWrapper: FC<MenuItemWrapperProps> = ({\n onSelect,\n children,\n}) => (\n <ContextMenuItem onSelect={onSelect ?? undefined} asChild>\n {children}\n </ContextMenuItem>\n);\n\n/**\n * A menu opened by right-clicking or long-pressing another UI element.\n */\nexport const ContextMenu: FC<Props> = ({\n title,\n showTitle = true,\n onOpenChange: onOpenChangeProp,\n trigger: triggerProp,\n hasAccessibleAlternative,\n children: childrenProp,\n}) => {\n const [open, setOpen] = useState(false);\n const onOpenChange = useCallback(\n (value: boolean) => {\n setOpen(value);\n onOpenChangeProp?.(value);\n },\n [setOpen, onOpenChangeProp],\n );\n\n // Normally, the menu takes the form of a floating box. But on Android and\n // iOS, the menu should morph into a drawer\n const platform = getPlatform();\n const drawer = platform === \"android\" || platform === \"ios\";\n const context: MenuData = useMemo(\n () => ({\n MenuItemWrapper: drawer ? null : ContextMenuItemWrapper,\n onOpenChange,\n }),\n [onOpenChange],\n );\n const children = (\n <MenuContext.Provider value={context}>{childrenProp}</MenuContext.Provider>\n );\n\n const trigger = (\n <Trigger\n aria-haspopup=\"menu\"\n tabIndex={hasAccessibleAlternative ? undefined : 0}\n asChild\n >\n {triggerProp}\n </Trigger>\n );\n\n // This is a small hack: Vaul drawers only support buttons as triggers, so\n // we end up mounting an empty Radix context menu tree alongside the\n // drawer tree, purely so we can use its Trigger component (which supports\n // touch for free). The resulting behavior and DOM tree looks exactly the\n // same as if Vaul provided a long-press trigger of its own, so I think\n // this is fine.\n return drawer ? (\n <>\n <Root onOpenChange={onOpenChange}>{trigger}</Root>\n <Drawer.Root open={open} onOpenChange={onOpenChange}>\n <Drawer.Portal>\n <Drawer.Overlay className={classnames(drawerStyles.bg)} />\n <Drawer.Content asChild>\n <DrawerMenu title={title}>{children}</DrawerMenu>\n </Drawer.Content>\n </Drawer.Portal>\n </Drawer.Root>\n </>\n ) : (\n <Root onOpenChange={onOpenChange}>\n {trigger}\n <Portal>\n <Content asChild>\n <FloatingMenu showTitle={showTitle} title={title}>\n {children}\n </FloatingMenu>\n </Content>\n </Portal>\n </Root>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;AAkEA,IAAM,0BAAoD,EACxD,UACA,eAEA,iBAAA,GAAA,kBAAA,KAAC,6BAAA,iBAAD;CAAiB,UAAU,YAAY,KAAA;CAAW,SAAA;CAC/C;CACe,CAAA;;;;AAMpB,IAAa,eAA0B,EACrC,OACA,YAAY,MACZ,cAAc,kBACd,SAAS,aACT,0BACA,UAAU,mBACN;CACJ,MAAM,CAAC,MAAM,YAAA,GAAA,MAAA,UAAoB,MAAM;CACvC,MAAM,gBAAA,GAAA,MAAA,cACH,UAAmB;AAClB,UAAQ,MAAM;AACd,qBAAmB,MAAM;IAE3B,CAAC,SAAS,iBAAiB,CAC5B;CAID,MAAM,WAAW,iBAAA,aAAa;CAC9B,MAAM,SAAS,aAAa,aAAa,aAAa;CACtD,MAAM,WAAA,GAAA,MAAA,gBACG;EACL,iBAAiB,SAAS,OAAO;EACjC;EACD,GACD,CAAC,aAAa,CACf;CACD,MAAM,WACJ,iBAAA,GAAA,kBAAA,KAAC,oBAAA,YAAY,UAAb;EAAsB,OAAO;YAAU;EAAoC,CAAA;CAG7E,MAAM,UACJ,iBAAA,GAAA,kBAAA,KAAC,6BAAA,SAAD;EACE,iBAAc;EACd,UAAU,2BAA2B,KAAA,IAAY;EACjD,SAAA;YAEC;EACO,CAAA;AASZ,QAAO,SACL,iBAAA,GAAA,kBAAA,MAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAC,6BAAA,MAAD;EAAoB;YAAe;EAAe,CAAA,EAClD,iBAAA,GAAA,kBAAA,KAAC,KAAA,OAAO,MAAR;EAAmB;EAAoB;YACrC,iBAAA,GAAA,kBAAA,MAAC,KAAA,OAAO,QAAR,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAC,KAAA,OAAO,SAAR,EAAgB,YAAA,GAAA,WAAA,SAAsB,0BAAA,QAAa,GAAG,EAAI,CAAA,EAC1D,iBAAA,GAAA,kBAAA,KAAC,KAAA,OAAO,SAAR;GAAgB,SAAA;aACd,iBAAA,GAAA,kBAAA,KAAC,mBAAA,YAAD;IAAmB;IAAQ;IAAsB,CAAA;GAClC,CAAA,CACH,EAAA,CAAA;EACJ,CAAA,CACb,EAAA,CAAA,GAEH,iBAAA,GAAA,kBAAA,MAAC,6BAAA,MAAD;EAAoB;YAApB,CACG,SACD,iBAAA,GAAA,kBAAA,KAAC,6BAAA,QAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAC,6BAAA,SAAD;GAAS,SAAA;aACP,iBAAA,GAAA,kBAAA,KAAC,qBAAA,cAAD;IAAyB;IAAkB;IACxC;IACY,CAAA;GACP,CAAA,EACH,CAAA,CACJ"}
1
+ {"version":3,"file":"ContextMenu.cjs","names":[],"sources":["../../../src/components/Menu/ContextMenu.tsx"],"sourcesContent":["/*\nCopyright 2023 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 React, {\n type FC,\n type ReactNode,\n useCallback,\n useMemo,\n useState,\n} from \"react\";\nimport {\n Root,\n Trigger,\n Portal,\n Content,\n ContextMenuItem,\n ContextMenuSub,\n ContextMenuSubTrigger,\n ContextMenuSubContent,\n ContextMenuPortal,\n} from \"@radix-ui/react-context-menu\";\nimport { FloatingMenu } from \"./FloatingMenu\";\nimport { Drawer } from \"vaul\";\nimport classnames from \"classnames\";\nimport drawerStyles from \"./DrawerMenu.module.css\";\nimport {\n MenuContext,\n type MenuData,\n type MenuItemWrapperProps,\n type SubMenuWrapperProps,\n} from \"./MenuContext\";\nimport { DrawerMenu } from \"./DrawerMenu\";\nimport { getPlatform } from \"../../utils/platform\";\n\ninterface Props {\n /**\n * The menu title.\n */\n title: string;\n /**\n * Wether the title is displayed.\n * @default true\n */\n showTitle?: boolean;\n /**\n * Event handler called when the open state of the menu changes.\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * The trigger that can be right-clicked or long-pressed to open the menu.\n * This must be a component that accepts a ref and spreads props.\n * https://www.radix-ui.com/primitives/docs/guides/composition\n */\n trigger: ReactNode;\n /**\n * Whether the functionality of this menu is available through some other\n * keyboard-accessible means. Preferably this should be true, because context\n * menus are potentially difficult to discover, but if false the trigger will\n * become focusable so that it can be opened via keyboard navigation.\n */\n hasAccessibleAlternative: boolean;\n /**\n * The menu contents.\n */\n children: ReactNode;\n}\n\nconst ContextMenuItemWrapper: FC<MenuItemWrapperProps> = ({\n onSelect,\n children,\n}) => (\n <ContextMenuItem onSelect={onSelect ?? undefined} asChild>\n {children}\n </ContextMenuItem>\n);\n\nconst ContextSubMenuWrapper: FC<SubMenuWrapperProps> = ({\n trigger,\n children,\n open,\n onOpenChange,\n}) => (\n <ContextMenuSub open={open} onOpenChange={onOpenChange}>\n <ContextMenuSubTrigger asChild>{trigger}</ContextMenuSubTrigger>\n <ContextMenuPortal>\n <ContextMenuSubContent asChild alignOffset={-20}>\n <FloatingMenu title=\"\" showTitle={false}>\n {children}\n </FloatingMenu>\n </ContextMenuSubContent>\n </ContextMenuPortal>\n </ContextMenuSub>\n);\n\n/**\n * A menu opened by right-clicking or long-pressing another UI element.\n */\nexport const ContextMenu: FC<Props> = ({\n title,\n showTitle = true,\n onOpenChange: onOpenChangeProp,\n trigger: triggerProp,\n hasAccessibleAlternative,\n children: childrenProp,\n}) => {\n const [open, setOpen] = useState(false);\n const onOpenChange = useCallback(\n (value: boolean) => {\n setOpen(value);\n onOpenChangeProp?.(value);\n },\n [setOpen, onOpenChangeProp],\n );\n\n // Normally, the menu takes the form of a floating box. But on Android and\n // iOS, the menu should morph into a drawer\n const platform = getPlatform();\n const drawer = platform === \"android\" || platform === \"ios\";\n const context: MenuData = useMemo(\n () => ({\n MenuItemWrapper: drawer ? null : ContextMenuItemWrapper,\n SubMenuWrapper: drawer ? null : ContextSubMenuWrapper,\n onOpenChange,\n }),\n [onOpenChange],\n );\n const children = (\n <MenuContext.Provider value={context}>{childrenProp}</MenuContext.Provider>\n );\n\n const trigger = (\n <Trigger\n aria-haspopup=\"menu\"\n tabIndex={hasAccessibleAlternative ? undefined : 0}\n asChild\n >\n {triggerProp}\n </Trigger>\n );\n\n // This is a small hack: Vaul drawers only support buttons as triggers, so\n // we end up mounting an empty Radix context menu tree alongside the\n // drawer tree, purely so we can use its Trigger component (which supports\n // touch for free). The resulting behavior and DOM tree looks exactly the\n // same as if Vaul provided a long-press trigger of its own, so I think\n // this is fine.\n return drawer ? (\n <>\n <Root onOpenChange={onOpenChange}>{trigger}</Root>\n <Drawer.Root open={open} onOpenChange={onOpenChange}>\n <Drawer.Portal>\n <Drawer.Overlay className={classnames(drawerStyles.bg)} />\n <Drawer.Content asChild>\n <DrawerMenu title={title}>{children}</DrawerMenu>\n </Drawer.Content>\n </Drawer.Portal>\n </Drawer.Root>\n </>\n ) : (\n <Root onOpenChange={onOpenChange}>\n {trigger}\n <Portal>\n <Content asChild>\n <FloatingMenu showTitle={showTitle} title={title}>\n {children}\n </FloatingMenu>\n </Content>\n </Portal>\n </Root>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;AAuEA,IAAM,0BAAoD,EACxD,UACA,eAEA,iBAAA,GAAA,kBAAA,KAAC,6BAAA,iBAAD;CAAiB,UAAU,YAAY,KAAA;CAAW,SAAA;CAC/C;CACe,CAAA;AAGpB,IAAM,yBAAkD,EACtD,SACA,UACA,MACA,mBAEA,iBAAA,GAAA,kBAAA,MAAC,6BAAA,gBAAD;CAAsB;CAAoB;WAA1C,CACE,iBAAA,GAAA,kBAAA,KAAC,6BAAA,uBAAD;EAAuB,SAAA;YAAS;EAAgC,CAAA,EAChE,iBAAA,GAAA,kBAAA,KAAC,6BAAA,mBAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAC,6BAAA,uBAAD;EAAuB,SAAA;EAAQ,aAAa;YAC1C,iBAAA,GAAA,kBAAA,KAAC,qBAAA,cAAD;GAAc,OAAM;GAAG,WAAW;GAC/B;GACY,CAAA;EACO,CAAA,EACN,CAAA,CACL;;;;;AAMnB,IAAa,eAA0B,EACrC,OACA,YAAY,MACZ,cAAc,kBACd,SAAS,aACT,0BACA,UAAU,mBACN;CACJ,MAAM,CAAC,MAAM,YAAA,GAAA,MAAA,UAAoB,MAAM;CACvC,MAAM,gBAAA,GAAA,MAAA,cACH,UAAmB;AAClB,UAAQ,MAAM;AACd,qBAAmB,MAAM;IAE3B,CAAC,SAAS,iBAAiB,CAC5B;CAID,MAAM,WAAW,iBAAA,aAAa;CAC9B,MAAM,SAAS,aAAa,aAAa,aAAa;CACtD,MAAM,WAAA,GAAA,MAAA,gBACG;EACL,iBAAiB,SAAS,OAAO;EACjC,gBAAgB,SAAS,OAAO;EAChC;EACD,GACD,CAAC,aAAa,CACf;CACD,MAAM,WACJ,iBAAA,GAAA,kBAAA,KAAC,oBAAA,YAAY,UAAb;EAAsB,OAAO;YAAU;EAAoC,CAAA;CAG7E,MAAM,UACJ,iBAAA,GAAA,kBAAA,KAAC,6BAAA,SAAD;EACE,iBAAc;EACd,UAAU,2BAA2B,KAAA,IAAY;EACjD,SAAA;YAEC;EACO,CAAA;AASZ,QAAO,SACL,iBAAA,GAAA,kBAAA,MAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAC,6BAAA,MAAD;EAAoB;YAAe;EAAe,CAAA,EAClD,iBAAA,GAAA,kBAAA,KAAC,KAAA,OAAO,MAAR;EAAmB;EAAoB;YACrC,iBAAA,GAAA,kBAAA,MAAC,KAAA,OAAO,QAAR,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAC,KAAA,OAAO,SAAR,EAAgB,YAAA,GAAA,WAAA,SAAsB,0BAAA,QAAa,GAAG,EAAI,CAAA,EAC1D,iBAAA,GAAA,kBAAA,KAAC,KAAA,OAAO,SAAR;GAAgB,SAAA;aACd,iBAAA,GAAA,kBAAA,KAAC,mBAAA,YAAD;IAAmB;IAAQ;IAAsB,CAAA;GAClC,CAAA,CACH,EAAA,CAAA;EACJ,CAAA,CACb,EAAA,CAAA,GAEH,iBAAA,GAAA,kBAAA,MAAC,6BAAA,MAAD;EAAoB;YAApB,CACG,SACD,iBAAA,GAAA,kBAAA,KAAC,6BAAA,QAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAC,6BAAA,SAAD;GAAS,SAAA;aACP,iBAAA,GAAA,kBAAA,KAAC,qBAAA,cAAD;IAAyB;IAAkB;IACxC;IACY,CAAA;GACP,CAAA,EACH,CAAA,CACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMenu.d.ts","sourceRoot":"","sources":["../../../src/components/Menu/ContextMenu.tsx"],"names":[],"mappings":"AAOA,OAAc,EACZ,KAAK,EAAE,EACP,KAAK,SAAS,EAIf,MAAM,OAAO,CAAC;AAoBf,UAAU,KAAK;IACb;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC;;;;OAIG;IACH,OAAO,EAAE,SAAS,CAAC;IACnB;;;;;OAKG;IACH,wBAAwB,EAAE,OAAO,CAAC;IAClC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAWD;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,KAAK,CAwEjC,CAAC"}
1
+ {"version":3,"file":"ContextMenu.d.ts","sourceRoot":"","sources":["../../../src/components/Menu/ContextMenu.tsx"],"names":[],"mappings":"AAOA,OAAc,EACZ,KAAK,EAAE,EACP,KAAK,SAAS,EAIf,MAAM,OAAO,CAAC;AAyBf,UAAU,KAAK;IACb;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC;;;;OAIG;IACH,OAAO,EAAE,SAAS,CAAC;IACnB;;;;;OAKG;IACH,wBAAwB,EAAE,OAAO,CAAC;IAClC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AA6BD;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,KAAK,CAyEjC,CAAC"}
@@ -6,7 +6,7 @@ import { DrawerMenu } from "./DrawerMenu.js";
6
6
  import classNames from "classnames";
7
7
  import { useCallback, useMemo, useState } from "react";
8
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
- import { Content, ContextMenuItem, Portal, Root, Trigger } from "@radix-ui/react-context-menu";
9
+ import { Content, ContextMenuItem, ContextMenuPortal, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, Portal, Root, Trigger } from "@radix-ui/react-context-menu";
10
10
  import { Drawer } from "vaul";
11
11
  //#region src/components/Menu/ContextMenu.tsx
12
12
  var ContextMenuItemWrapper = ({ onSelect, children }) => /* @__PURE__ */ jsx(ContextMenuItem, {
@@ -14,6 +14,22 @@ var ContextMenuItemWrapper = ({ onSelect, children }) => /* @__PURE__ */ jsx(Con
14
14
  asChild: true,
15
15
  children
16
16
  });
17
+ var ContextSubMenuWrapper = ({ trigger, children, open, onOpenChange }) => /* @__PURE__ */ jsxs(ContextMenuSub, {
18
+ open,
19
+ onOpenChange,
20
+ children: [/* @__PURE__ */ jsx(ContextMenuSubTrigger, {
21
+ asChild: true,
22
+ children: trigger
23
+ }), /* @__PURE__ */ jsx(ContextMenuPortal, { children: /* @__PURE__ */ jsx(ContextMenuSubContent, {
24
+ asChild: true,
25
+ alignOffset: -20,
26
+ children: /* @__PURE__ */ jsx(FloatingMenu, {
27
+ title: "",
28
+ showTitle: false,
29
+ children
30
+ })
31
+ }) })]
32
+ });
17
33
  /**
18
34
  * A menu opened by right-clicking or long-pressing another UI element.
19
35
  */
@@ -27,6 +43,7 @@ var ContextMenu = ({ title, showTitle = true, onOpenChange: onOpenChangeProp, tr
27
43
  const drawer = platform === "android" || platform === "ios";
28
44
  const context = useMemo(() => ({
29
45
  MenuItemWrapper: drawer ? null : ContextMenuItemWrapper,
46
+ SubMenuWrapper: drawer ? null : ContextSubMenuWrapper,
30
47
  onOpenChange
31
48
  }), [onOpenChange]);
32
49
  const children = /* @__PURE__ */ jsx(MenuContext.Provider, {
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMenu.js","names":[],"sources":["../../../src/components/Menu/ContextMenu.tsx"],"sourcesContent":["/*\nCopyright 2023 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 React, {\n type FC,\n type ReactNode,\n useCallback,\n useMemo,\n useState,\n} from \"react\";\nimport {\n Root,\n Trigger,\n Portal,\n Content,\n ContextMenuItem,\n} from \"@radix-ui/react-context-menu\";\nimport { FloatingMenu } from \"./FloatingMenu\";\nimport { Drawer } from \"vaul\";\nimport classnames from \"classnames\";\nimport drawerStyles from \"./DrawerMenu.module.css\";\nimport {\n MenuContext,\n type MenuData,\n type MenuItemWrapperProps,\n} from \"./MenuContext\";\nimport { DrawerMenu } from \"./DrawerMenu\";\nimport { getPlatform } from \"../../utils/platform\";\n\ninterface Props {\n /**\n * The menu title.\n */\n title: string;\n /**\n * Wether the title is displayed.\n * @default true\n */\n showTitle?: boolean;\n /**\n * Event handler called when the open state of the menu changes.\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * The trigger that can be right-clicked or long-pressed to open the menu.\n * This must be a component that accepts a ref and spreads props.\n * https://www.radix-ui.com/primitives/docs/guides/composition\n */\n trigger: ReactNode;\n /**\n * Whether the functionality of this menu is available through some other\n * keyboard-accessible means. Preferably this should be true, because context\n * menus are potentially difficult to discover, but if false the trigger will\n * become focusable so that it can be opened via keyboard navigation.\n */\n hasAccessibleAlternative: boolean;\n /**\n * The menu contents.\n */\n children: ReactNode;\n}\n\nconst ContextMenuItemWrapper: FC<MenuItemWrapperProps> = ({\n onSelect,\n children,\n}) => (\n <ContextMenuItem onSelect={onSelect ?? undefined} asChild>\n {children}\n </ContextMenuItem>\n);\n\n/**\n * A menu opened by right-clicking or long-pressing another UI element.\n */\nexport const ContextMenu: FC<Props> = ({\n title,\n showTitle = true,\n onOpenChange: onOpenChangeProp,\n trigger: triggerProp,\n hasAccessibleAlternative,\n children: childrenProp,\n}) => {\n const [open, setOpen] = useState(false);\n const onOpenChange = useCallback(\n (value: boolean) => {\n setOpen(value);\n onOpenChangeProp?.(value);\n },\n [setOpen, onOpenChangeProp],\n );\n\n // Normally, the menu takes the form of a floating box. But on Android and\n // iOS, the menu should morph into a drawer\n const platform = getPlatform();\n const drawer = platform === \"android\" || platform === \"ios\";\n const context: MenuData = useMemo(\n () => ({\n MenuItemWrapper: drawer ? null : ContextMenuItemWrapper,\n onOpenChange,\n }),\n [onOpenChange],\n );\n const children = (\n <MenuContext.Provider value={context}>{childrenProp}</MenuContext.Provider>\n );\n\n const trigger = (\n <Trigger\n aria-haspopup=\"menu\"\n tabIndex={hasAccessibleAlternative ? undefined : 0}\n asChild\n >\n {triggerProp}\n </Trigger>\n );\n\n // This is a small hack: Vaul drawers only support buttons as triggers, so\n // we end up mounting an empty Radix context menu tree alongside the\n // drawer tree, purely so we can use its Trigger component (which supports\n // touch for free). The resulting behavior and DOM tree looks exactly the\n // same as if Vaul provided a long-press trigger of its own, so I think\n // this is fine.\n return drawer ? (\n <>\n <Root onOpenChange={onOpenChange}>{trigger}</Root>\n <Drawer.Root open={open} onOpenChange={onOpenChange}>\n <Drawer.Portal>\n <Drawer.Overlay className={classnames(drawerStyles.bg)} />\n <Drawer.Content asChild>\n <DrawerMenu title={title}>{children}</DrawerMenu>\n </Drawer.Content>\n </Drawer.Portal>\n </Drawer.Root>\n </>\n ) : (\n <Root onOpenChange={onOpenChange}>\n {trigger}\n <Portal>\n <Content asChild>\n <FloatingMenu showTitle={showTitle} title={title}>\n {children}\n </FloatingMenu>\n </Content>\n </Portal>\n </Root>\n );\n};\n"],"mappings":";;;;;;;;;;;AAkEA,IAAM,0BAAoD,EACxD,UACA,eAEA,oBAAC,iBAAD;CAAiB,UAAU,YAAY,KAAA;CAAW,SAAA;CAC/C;CACe,CAAA;;;;AAMpB,IAAa,eAA0B,EACrC,OACA,YAAY,MACZ,cAAc,kBACd,SAAS,aACT,0BACA,UAAU,mBACN;CACJ,MAAM,CAAC,MAAM,WAAW,SAAS,MAAM;CACvC,MAAM,eAAe,aAClB,UAAmB;AAClB,UAAQ,MAAM;AACd,qBAAmB,MAAM;IAE3B,CAAC,SAAS,iBAAiB,CAC5B;CAID,MAAM,WAAW,aAAa;CAC9B,MAAM,SAAS,aAAa,aAAa,aAAa;CACtD,MAAM,UAAoB,eACjB;EACL,iBAAiB,SAAS,OAAO;EACjC;EACD,GACD,CAAC,aAAa,CACf;CACD,MAAM,WACJ,oBAAC,YAAY,UAAb;EAAsB,OAAO;YAAU;EAAoC,CAAA;CAG7E,MAAM,UACJ,oBAAC,SAAD;EACE,iBAAc;EACd,UAAU,2BAA2B,KAAA,IAAY;EACjD,SAAA;YAEC;EACO,CAAA;AASZ,QAAO,SACL,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,MAAD;EAAoB;YAAe;EAAe,CAAA,EAClD,oBAAC,OAAO,MAAR;EAAmB;EAAoB;YACrC,qBAAC,OAAO,QAAR,EAAA,UAAA,CACE,oBAAC,OAAO,SAAR,EAAgB,WAAW,WAAW,0BAAa,GAAG,EAAI,CAAA,EAC1D,oBAAC,OAAO,SAAR;GAAgB,SAAA;aACd,oBAAC,YAAD;IAAmB;IAAQ;IAAsB,CAAA;GAClC,CAAA,CACH,EAAA,CAAA;EACJ,CAAA,CACb,EAAA,CAAA,GAEH,qBAAC,MAAD;EAAoB;YAApB,CACG,SACD,oBAAC,QAAD,EAAA,UACE,oBAAC,SAAD;GAAS,SAAA;aACP,oBAAC,cAAD;IAAyB;IAAkB;IACxC;IACY,CAAA;GACP,CAAA,EACH,CAAA,CACJ"}
1
+ {"version":3,"file":"ContextMenu.js","names":[],"sources":["../../../src/components/Menu/ContextMenu.tsx"],"sourcesContent":["/*\nCopyright 2023 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 React, {\n type FC,\n type ReactNode,\n useCallback,\n useMemo,\n useState,\n} from \"react\";\nimport {\n Root,\n Trigger,\n Portal,\n Content,\n ContextMenuItem,\n ContextMenuSub,\n ContextMenuSubTrigger,\n ContextMenuSubContent,\n ContextMenuPortal,\n} from \"@radix-ui/react-context-menu\";\nimport { FloatingMenu } from \"./FloatingMenu\";\nimport { Drawer } from \"vaul\";\nimport classnames from \"classnames\";\nimport drawerStyles from \"./DrawerMenu.module.css\";\nimport {\n MenuContext,\n type MenuData,\n type MenuItemWrapperProps,\n type SubMenuWrapperProps,\n} from \"./MenuContext\";\nimport { DrawerMenu } from \"./DrawerMenu\";\nimport { getPlatform } from \"../../utils/platform\";\n\ninterface Props {\n /**\n * The menu title.\n */\n title: string;\n /**\n * Wether the title is displayed.\n * @default true\n */\n showTitle?: boolean;\n /**\n * Event handler called when the open state of the menu changes.\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * The trigger that can be right-clicked or long-pressed to open the menu.\n * This must be a component that accepts a ref and spreads props.\n * https://www.radix-ui.com/primitives/docs/guides/composition\n */\n trigger: ReactNode;\n /**\n * Whether the functionality of this menu is available through some other\n * keyboard-accessible means. Preferably this should be true, because context\n * menus are potentially difficult to discover, but if false the trigger will\n * become focusable so that it can be opened via keyboard navigation.\n */\n hasAccessibleAlternative: boolean;\n /**\n * The menu contents.\n */\n children: ReactNode;\n}\n\nconst ContextMenuItemWrapper: FC<MenuItemWrapperProps> = ({\n onSelect,\n children,\n}) => (\n <ContextMenuItem onSelect={onSelect ?? undefined} asChild>\n {children}\n </ContextMenuItem>\n);\n\nconst ContextSubMenuWrapper: FC<SubMenuWrapperProps> = ({\n trigger,\n children,\n open,\n onOpenChange,\n}) => (\n <ContextMenuSub open={open} onOpenChange={onOpenChange}>\n <ContextMenuSubTrigger asChild>{trigger}</ContextMenuSubTrigger>\n <ContextMenuPortal>\n <ContextMenuSubContent asChild alignOffset={-20}>\n <FloatingMenu title=\"\" showTitle={false}>\n {children}\n </FloatingMenu>\n </ContextMenuSubContent>\n </ContextMenuPortal>\n </ContextMenuSub>\n);\n\n/**\n * A menu opened by right-clicking or long-pressing another UI element.\n */\nexport const ContextMenu: FC<Props> = ({\n title,\n showTitle = true,\n onOpenChange: onOpenChangeProp,\n trigger: triggerProp,\n hasAccessibleAlternative,\n children: childrenProp,\n}) => {\n const [open, setOpen] = useState(false);\n const onOpenChange = useCallback(\n (value: boolean) => {\n setOpen(value);\n onOpenChangeProp?.(value);\n },\n [setOpen, onOpenChangeProp],\n );\n\n // Normally, the menu takes the form of a floating box. But on Android and\n // iOS, the menu should morph into a drawer\n const platform = getPlatform();\n const drawer = platform === \"android\" || platform === \"ios\";\n const context: MenuData = useMemo(\n () => ({\n MenuItemWrapper: drawer ? null : ContextMenuItemWrapper,\n SubMenuWrapper: drawer ? null : ContextSubMenuWrapper,\n onOpenChange,\n }),\n [onOpenChange],\n );\n const children = (\n <MenuContext.Provider value={context}>{childrenProp}</MenuContext.Provider>\n );\n\n const trigger = (\n <Trigger\n aria-haspopup=\"menu\"\n tabIndex={hasAccessibleAlternative ? undefined : 0}\n asChild\n >\n {triggerProp}\n </Trigger>\n );\n\n // This is a small hack: Vaul drawers only support buttons as triggers, so\n // we end up mounting an empty Radix context menu tree alongside the\n // drawer tree, purely so we can use its Trigger component (which supports\n // touch for free). The resulting behavior and DOM tree looks exactly the\n // same as if Vaul provided a long-press trigger of its own, so I think\n // this is fine.\n return drawer ? (\n <>\n <Root onOpenChange={onOpenChange}>{trigger}</Root>\n <Drawer.Root open={open} onOpenChange={onOpenChange}>\n <Drawer.Portal>\n <Drawer.Overlay className={classnames(drawerStyles.bg)} />\n <Drawer.Content asChild>\n <DrawerMenu title={title}>{children}</DrawerMenu>\n </Drawer.Content>\n </Drawer.Portal>\n </Drawer.Root>\n </>\n ) : (\n <Root onOpenChange={onOpenChange}>\n {trigger}\n <Portal>\n <Content asChild>\n <FloatingMenu showTitle={showTitle} title={title}>\n {children}\n </FloatingMenu>\n </Content>\n </Portal>\n </Root>\n );\n};\n"],"mappings":";;;;;;;;;;;AAuEA,IAAM,0BAAoD,EACxD,UACA,eAEA,oBAAC,iBAAD;CAAiB,UAAU,YAAY,KAAA;CAAW,SAAA;CAC/C;CACe,CAAA;AAGpB,IAAM,yBAAkD,EACtD,SACA,UACA,MACA,mBAEA,qBAAC,gBAAD;CAAsB;CAAoB;WAA1C,CACE,oBAAC,uBAAD;EAAuB,SAAA;YAAS;EAAgC,CAAA,EAChE,oBAAC,mBAAD,EAAA,UACE,oBAAC,uBAAD;EAAuB,SAAA;EAAQ,aAAa;YAC1C,oBAAC,cAAD;GAAc,OAAM;GAAG,WAAW;GAC/B;GACY,CAAA;EACO,CAAA,EACN,CAAA,CACL;;;;;AAMnB,IAAa,eAA0B,EACrC,OACA,YAAY,MACZ,cAAc,kBACd,SAAS,aACT,0BACA,UAAU,mBACN;CACJ,MAAM,CAAC,MAAM,WAAW,SAAS,MAAM;CACvC,MAAM,eAAe,aAClB,UAAmB;AAClB,UAAQ,MAAM;AACd,qBAAmB,MAAM;IAE3B,CAAC,SAAS,iBAAiB,CAC5B;CAID,MAAM,WAAW,aAAa;CAC9B,MAAM,SAAS,aAAa,aAAa,aAAa;CACtD,MAAM,UAAoB,eACjB;EACL,iBAAiB,SAAS,OAAO;EACjC,gBAAgB,SAAS,OAAO;EAChC;EACD,GACD,CAAC,aAAa,CACf;CACD,MAAM,WACJ,oBAAC,YAAY,UAAb;EAAsB,OAAO;YAAU;EAAoC,CAAA;CAG7E,MAAM,UACJ,oBAAC,SAAD;EACE,iBAAc;EACd,UAAU,2BAA2B,KAAA,IAAY;EACjD,SAAA;YAEC;EACO,CAAA;AASZ,QAAO,SACL,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,MAAD;EAAoB;YAAe;EAAe,CAAA,EAClD,oBAAC,OAAO,MAAR;EAAmB;EAAoB;YACrC,qBAAC,OAAO,QAAR,EAAA,UAAA,CACE,oBAAC,OAAO,SAAR,EAAgB,WAAW,WAAW,0BAAa,GAAG,EAAI,CAAA,EAC1D,oBAAC,OAAO,SAAR;GAAgB,SAAA;aACd,oBAAC,YAAD;IAAmB;IAAQ;IAAsB,CAAA;GAClC,CAAA,CACH,EAAA,CAAA;EACJ,CAAA,CACb,EAAA,CAAA,GAEH,qBAAC,MAAD;EAAoB;YAApB,CACG,SACD,oBAAC,QAAD,EAAA,UACE,oBAAC,SAAD;GAAS,SAAA;aACP,oBAAC,cAAD;IAAyB;IAAkB;IACxC;IACY,CAAA;GACP,CAAA,EACH,CAAA,CACJ"}
@@ -17,6 +17,33 @@ var DropdownMenuItemWrapper = ({ onSelect, children }) => /* @__PURE__ */ (0, re
17
17
  asChild: true,
18
18
  children
19
19
  });
20
+ /** Duration of the parent menu's slide-in animation (ms). */
21
+ var MENU_ANIMATION_DURATION = 180;
22
+ var DropdownSubMenuWrapper = ({ trigger, children, open: openProp, onOpenChange }) => {
23
+ const [deferredOpen, setDeferredOpen] = (0, react.useState)(false);
24
+ (0, react.useEffect)(() => {
25
+ if (openProp) {
26
+ const timer = setTimeout(() => setDeferredOpen(true), MENU_ANIMATION_DURATION);
27
+ return () => clearTimeout(timer);
28
+ } else setDeferredOpen(false);
29
+ }, [openProp]);
30
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_radix_ui_react_dropdown_menu.DropdownMenuSub, {
31
+ open: openProp ? deferredOpen : openProp,
32
+ onOpenChange,
33
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dropdown_menu.DropdownMenuSubTrigger, {
34
+ asChild: true,
35
+ children: trigger
36
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dropdown_menu.DropdownMenuPortal, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dropdown_menu.DropdownMenuSubContent, {
37
+ asChild: true,
38
+ alignOffset: -20,
39
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_FloatingMenu.FloatingMenu, {
40
+ title: "",
41
+ showTitle: false,
42
+ children
43
+ })
44
+ }) })]
45
+ });
46
+ };
20
47
  /**
21
48
  * A menu opened by pressing a button.
22
49
  */
@@ -25,6 +52,7 @@ var Menu = ({ className, title, showTitle = true, open, onOpenChange, trigger, c
25
52
  const drawer = platform === "android" || platform === "ios";
26
53
  const context = (0, react.useMemo)(() => ({
27
54
  MenuItemWrapper: drawer ? null : DropdownMenuItemWrapper,
55
+ SubMenuWrapper: drawer ? null : DropdownSubMenuWrapper,
28
56
  onOpenChange
29
57
  }), [onOpenChange]);
30
58
  const children = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MenuContext.MenuContext.Provider, {
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.cjs","names":[],"sources":["../../../src/components/Menu/Menu.tsx"],"sourcesContent":["/*\nCopyright 2023 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 React, { type FC, type ReactNode, useMemo } from \"react\";\nimport {\n Root,\n Trigger,\n Portal,\n Content,\n DropdownMenuItem,\n} from \"@radix-ui/react-dropdown-menu\";\nimport { FloatingMenu } from \"./FloatingMenu\";\nimport { Drawer } from \"vaul\";\nimport classnames from \"classnames\";\nimport drawerMenu from \"./DrawerMenu.module.css\";\nimport {\n MenuContext,\n type MenuData,\n type MenuItemWrapperProps,\n} from \"./MenuContext\";\nimport { DrawerMenu } from \"./DrawerMenu\";\nimport { getPlatform } from \"../../utils/platform\";\n\ninterface Props {\n /**\n * CSS classes for the menu.\n */\n className?: string;\n\n /**\n * The menu title. This can be hidden with `showTitle={false}` in which case it will only\n * be a label for screen readers.\n */\n title: string;\n /**\n * Controls whether the title is displayed (see `title` prop). Titles are only displayed on\n * web: on mobile, this parameter is ignored.\n */\n showTitle?: boolean;\n /**\n * Whether the menu is open.\n */\n open: boolean;\n /**\n * Event handler called when the open state of the menu changes. This includes\n * anything like clicking the trigger, selecting a menu item, or dismissing\n * the menu with the mouse or keyboard.\n */\n onOpenChange: (open: boolean) => void;\n /**\n * The button that opens the menu. This must be a component that accepts a ref\n * and spreads props.\n * https://www.radix-ui.com/primitives/docs/guides/composition\n */\n trigger: ReactNode;\n /**\n * The menu contents.\n */\n children: ReactNode;\n /**\n * The side of the trigger on which to place the menu. Note that the menu may\n * still end up on a different side than the one you request if there isn't\n * enough space.\n * @default bottom\n */\n side?: \"top\" | \"right\" | \"bottom\" | \"left\";\n /**\n * The edge along which the menu and trigger will be aligned.\n * @default center\n */\n align?: \"start\" | \"center\" | \"end\";\n}\n\nconst DropdownMenuItemWrapper: FC<MenuItemWrapperProps> = ({\n onSelect,\n children,\n}) => (\n <DropdownMenuItem onSelect={onSelect ?? undefined} asChild>\n {children}\n </DropdownMenuItem>\n);\n\n/**\n * A menu opened by pressing a button.\n */\nexport const Menu: FC<Props> = ({\n className,\n title,\n showTitle = true,\n open,\n onOpenChange,\n trigger,\n children: childrenProp,\n side = \"bottom\",\n align = \"center\",\n}) => {\n // Normally, the menu takes the form of a floating box. But on Android and\n // iOS, the menu should morph into a drawer\n const platform = getPlatform();\n const drawer = platform === \"android\" || platform === \"ios\";\n const context: MenuData = useMemo(\n () => ({\n MenuItemWrapper: drawer ? null : DropdownMenuItemWrapper,\n onOpenChange,\n }),\n [onOpenChange],\n );\n const children = (\n <MenuContext.Provider value={context}>{childrenProp}</MenuContext.Provider>\n );\n\n return drawer ? (\n <Drawer.Root open={open} onOpenChange={onOpenChange}>\n <Drawer.Trigger asChild>{trigger}</Drawer.Trigger>\n <Drawer.Portal>\n <Drawer.Overlay className={classnames(drawerMenu.bg)} />\n <Drawer.Content asChild>\n <DrawerMenu title={title}>{children}</DrawerMenu>\n </Drawer.Content>\n </Drawer.Portal>\n </Drawer.Root>\n ) : (\n <Root open={open} onOpenChange={onOpenChange}>\n <Trigger asChild>{trigger}</Trigger>\n <Portal>\n <Content asChild side={side} align={align} sideOffset={8}>\n <FloatingMenu\n className={className}\n title={title}\n showTitle={showTitle}\n >\n {children}\n </FloatingMenu>\n </Content>\n </Portal>\n </Root>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;AA6EA,IAAM,2BAAqD,EACzD,UACA,eAEA,iBAAA,GAAA,kBAAA,KAAC,8BAAA,kBAAD;CAAkB,UAAU,YAAY,KAAA;CAAW,SAAA;CAChD;CACgB,CAAA;;;;AAMrB,IAAa,QAAmB,EAC9B,WACA,OACA,YAAY,MACZ,MACA,cACA,SACA,UAAU,cACV,OAAO,UACP,QAAQ,eACJ;CAGJ,MAAM,WAAW,iBAAA,aAAa;CAC9B,MAAM,SAAS,aAAa,aAAa,aAAa;CACtD,MAAM,WAAA,GAAA,MAAA,gBACG;EACL,iBAAiB,SAAS,OAAO;EACjC;EACD,GACD,CAAC,aAAa,CACf;CACD,MAAM,WACJ,iBAAA,GAAA,kBAAA,KAAC,oBAAA,YAAY,UAAb;EAAsB,OAAO;YAAU;EAAoC,CAAA;AAG7E,QAAO,SACL,iBAAA,GAAA,kBAAA,MAAC,KAAA,OAAO,MAAR;EAAmB;EAAoB;YAAvC,CACE,iBAAA,GAAA,kBAAA,KAAC,KAAA,OAAO,SAAR;GAAgB,SAAA;aAAS;GAAyB,CAAA,EAClD,iBAAA,GAAA,kBAAA,MAAC,KAAA,OAAO,QAAR,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAC,KAAA,OAAO,SAAR,EAAgB,YAAA,GAAA,WAAA,SAAsB,0BAAA,QAAW,GAAG,EAAI,CAAA,EACxD,iBAAA,GAAA,kBAAA,KAAC,KAAA,OAAO,SAAR;GAAgB,SAAA;aACd,iBAAA,GAAA,kBAAA,KAAC,mBAAA,YAAD;IAAmB;IAAQ;IAAsB,CAAA;GAClC,CAAA,CACH,EAAA,CAAA,CACJ;MAEd,iBAAA,GAAA,kBAAA,MAAC,8BAAA,MAAD;EAAY;EAAoB;YAAhC,CACE,iBAAA,GAAA,kBAAA,KAAC,8BAAA,SAAD;GAAS,SAAA;aAAS;GAAkB,CAAA,EACpC,iBAAA,GAAA,kBAAA,KAAC,8BAAA,QAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAC,8BAAA,SAAD;GAAS,SAAA;GAAc;GAAa;GAAO,YAAY;aACrD,iBAAA,GAAA,kBAAA,KAAC,qBAAA,cAAD;IACa;IACJ;IACI;IAEV;IACY,CAAA;GACP,CAAA,EACH,CAAA,CACJ"}
1
+ {"version":3,"file":"Menu.cjs","names":[],"sources":["../../../src/components/Menu/Menu.tsx"],"sourcesContent":["/*\nCopyright 2023 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 React, {\n type FC,\n type ReactNode,\n useMemo,\n useEffect,\n useState,\n} from \"react\";\nimport {\n Root,\n Trigger,\n Portal,\n Content,\n DropdownMenuItem,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n DropdownMenuPortal,\n} from \"@radix-ui/react-dropdown-menu\";\nimport { FloatingMenu } from \"./FloatingMenu\";\nimport { Drawer } from \"vaul\";\nimport classnames from \"classnames\";\nimport drawerMenu from \"./DrawerMenu.module.css\";\nimport {\n MenuContext,\n type MenuData,\n type MenuItemWrapperProps,\n type SubMenuWrapperProps,\n} from \"./MenuContext\";\nimport { DrawerMenu } from \"./DrawerMenu\";\nimport { getPlatform } from \"../../utils/platform\";\n\ninterface Props {\n /**\n * CSS classes for the menu.\n */\n className?: string;\n\n /**\n * The menu title. This can be hidden with `showTitle={false}` in which case it will only\n * be a label for screen readers.\n */\n title: string;\n /**\n * Controls whether the title is displayed (see `title` prop). Titles are only displayed on\n * web: on mobile, this parameter is ignored.\n */\n showTitle?: boolean;\n /**\n * Whether the menu is open.\n */\n open: boolean;\n /**\n * Event handler called when the open state of the menu changes. This includes\n * anything like clicking the trigger, selecting a menu item, or dismissing\n * the menu with the mouse or keyboard.\n */\n onOpenChange: (open: boolean) => void;\n /**\n * The button that opens the menu. This must be a component that accepts a ref\n * and spreads props.\n * https://www.radix-ui.com/primitives/docs/guides/composition\n */\n trigger: ReactNode;\n /**\n * The menu contents.\n */\n children: ReactNode;\n /**\n * The side of the trigger on which to place the menu. Note that the menu may\n * still end up on a different side than the one you request if there isn't\n * enough space.\n * @default bottom\n */\n side?: \"top\" | \"right\" | \"bottom\" | \"left\";\n /**\n * The edge along which the menu and trigger will be aligned.\n * @default center\n */\n align?: \"start\" | \"center\" | \"end\";\n}\n\nconst DropdownMenuItemWrapper: FC<MenuItemWrapperProps> = ({\n onSelect,\n children,\n}) => (\n <DropdownMenuItem onSelect={onSelect ?? undefined} asChild>\n {children}\n </DropdownMenuItem>\n);\n\n/** Duration of the parent menu's slide-in animation (ms). */\nconst MENU_ANIMATION_DURATION = 180;\n\nconst DropdownSubMenuWrapper: FC<SubMenuWrapperProps> = ({\n trigger,\n children,\n open: openProp,\n onOpenChange,\n}) => {\n // When the submenu is programmatically opened at the same time as the parent\n // menu (e.g. open={true} on mount), the parent is still mid-animation and\n // the trigger position hasn't settled. Defer the open so the submenu\n // positions correctly after the parent animation completes.\n const [deferredOpen, setDeferredOpen] = useState(false);\n\n useEffect(() => {\n if (openProp) {\n const timer = setTimeout(\n () => setDeferredOpen(true),\n MENU_ANIMATION_DURATION,\n );\n return () => clearTimeout(timer);\n } else {\n setDeferredOpen(false);\n }\n }, [openProp]);\n\n const open = openProp ? deferredOpen : openProp;\n\n return (\n <DropdownMenuSub open={open} onOpenChange={onOpenChange}>\n <DropdownMenuSubTrigger asChild>{trigger}</DropdownMenuSubTrigger>\n <DropdownMenuPortal>\n <DropdownMenuSubContent asChild alignOffset={-20}>\n <FloatingMenu title=\"\" showTitle={false}>\n {children}\n </FloatingMenu>\n </DropdownMenuSubContent>\n </DropdownMenuPortal>\n </DropdownMenuSub>\n );\n};\n\n/**\n * A menu opened by pressing a button.\n */\nexport const Menu: FC<Props> = ({\n className,\n title,\n showTitle = true,\n open,\n onOpenChange,\n trigger,\n children: childrenProp,\n side = \"bottom\",\n align = \"center\",\n}) => {\n // Normally, the menu takes the form of a floating box. But on Android and\n // iOS, the menu should morph into a drawer\n const platform = getPlatform();\n const drawer = platform === \"android\" || platform === \"ios\";\n const context: MenuData = useMemo(\n () => ({\n MenuItemWrapper: drawer ? null : DropdownMenuItemWrapper,\n SubMenuWrapper: drawer ? null : DropdownSubMenuWrapper,\n onOpenChange,\n }),\n [onOpenChange],\n );\n const children = (\n <MenuContext.Provider value={context}>{childrenProp}</MenuContext.Provider>\n );\n\n return drawer ? (\n <Drawer.Root open={open} onOpenChange={onOpenChange}>\n <Drawer.Trigger asChild>{trigger}</Drawer.Trigger>\n <Drawer.Portal>\n <Drawer.Overlay className={classnames(drawerMenu.bg)} />\n <Drawer.Content asChild>\n <DrawerMenu title={title}>{children}</DrawerMenu>\n </Drawer.Content>\n </Drawer.Portal>\n </Drawer.Root>\n ) : (\n <Root open={open} onOpenChange={onOpenChange}>\n <Trigger asChild>{trigger}</Trigger>\n <Portal>\n <Content asChild side={side} align={align} sideOffset={8}>\n <FloatingMenu\n className={className}\n title={title}\n showTitle={showTitle}\n >\n {children}\n </FloatingMenu>\n </Content>\n </Portal>\n </Root>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;AAwFA,IAAM,2BAAqD,EACzD,UACA,eAEA,iBAAA,GAAA,kBAAA,KAAC,8BAAA,kBAAD;CAAkB,UAAU,YAAY,KAAA;CAAW,SAAA;CAChD;CACgB,CAAA;;AAIrB,IAAM,0BAA0B;AAEhC,IAAM,0BAAmD,EACvD,SACA,UACA,MAAM,UACN,mBACI;CAKJ,MAAM,CAAC,cAAc,oBAAA,GAAA,MAAA,UAA4B,MAAM;AAEvD,EAAA,GAAA,MAAA,iBAAgB;AACd,MAAI,UAAU;GACZ,MAAM,QAAQ,iBACN,gBAAgB,KAAK,EAC3B,wBACD;AACD,gBAAa,aAAa,MAAM;QAEhC,iBAAgB,MAAM;IAEvB,CAAC,SAAS,CAAC;AAId,QACE,iBAAA,GAAA,kBAAA,MAAC,8BAAA,iBAAD;EAAuB,MAHZ,WAAW,eAAe;EAGM;YAA3C,CACE,iBAAA,GAAA,kBAAA,KAAC,8BAAA,wBAAD;GAAwB,SAAA;aAAS;GAAiC,CAAA,EAClE,iBAAA,GAAA,kBAAA,KAAC,8BAAA,oBAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAC,8BAAA,wBAAD;GAAwB,SAAA;GAAQ,aAAa;aAC3C,iBAAA,GAAA,kBAAA,KAAC,qBAAA,cAAD;IAAc,OAAM;IAAG,WAAW;IAC/B;IACY,CAAA;GACQ,CAAA,EACN,CAAA,CACL;;;;;;AAOtB,IAAa,QAAmB,EAC9B,WACA,OACA,YAAY,MACZ,MACA,cACA,SACA,UAAU,cACV,OAAO,UACP,QAAQ,eACJ;CAGJ,MAAM,WAAW,iBAAA,aAAa;CAC9B,MAAM,SAAS,aAAa,aAAa,aAAa;CACtD,MAAM,WAAA,GAAA,MAAA,gBACG;EACL,iBAAiB,SAAS,OAAO;EACjC,gBAAgB,SAAS,OAAO;EAChC;EACD,GACD,CAAC,aAAa,CACf;CACD,MAAM,WACJ,iBAAA,GAAA,kBAAA,KAAC,oBAAA,YAAY,UAAb;EAAsB,OAAO;YAAU;EAAoC,CAAA;AAG7E,QAAO,SACL,iBAAA,GAAA,kBAAA,MAAC,KAAA,OAAO,MAAR;EAAmB;EAAoB;YAAvC,CACE,iBAAA,GAAA,kBAAA,KAAC,KAAA,OAAO,SAAR;GAAgB,SAAA;aAAS;GAAyB,CAAA,EAClD,iBAAA,GAAA,kBAAA,MAAC,KAAA,OAAO,QAAR,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAC,KAAA,OAAO,SAAR,EAAgB,YAAA,GAAA,WAAA,SAAsB,0BAAA,QAAW,GAAG,EAAI,CAAA,EACxD,iBAAA,GAAA,kBAAA,KAAC,KAAA,OAAO,SAAR;GAAgB,SAAA;aACd,iBAAA,GAAA,kBAAA,KAAC,mBAAA,YAAD;IAAmB;IAAQ;IAAsB,CAAA;GAClC,CAAA,CACH,EAAA,CAAA,CACJ;MAEd,iBAAA,GAAA,kBAAA,MAAC,8BAAA,MAAD;EAAY;EAAoB;YAAhC,CACE,iBAAA,GAAA,kBAAA,KAAC,8BAAA,SAAD;GAAS,SAAA;aAAS;GAAkB,CAAA,EACpC,iBAAA,GAAA,kBAAA,KAAC,8BAAA,QAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAC,8BAAA,SAAD;GAAS,SAAA;GAAc;GAAa;GAAO,YAAY;aACrD,iBAAA,GAAA,kBAAA,KAAC,qBAAA,cAAD;IACa;IACJ;IACI;IAEV;IACY,CAAA;GACP,CAAA,EACH,CAAA,CACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../../../src/components/Menu/Menu.tsx"],"names":[],"mappings":"AAOA,OAAc,EAAE,KAAK,EAAE,EAAE,KAAK,SAAS,EAAW,MAAM,OAAO,CAAC;AAoBhE,UAAU,KAAK;IACb;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC;IACd;;;;OAIG;IACH,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC;;;;OAIG;IACH,OAAO,EAAE,SAAS,CAAC;IACnB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC3C;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;CACpC;AAWD;;GAEG;AACH,eAAO,MAAM,IAAI,EAAE,EAAE,CAAC,KAAK,CAoD1B,CAAC"}
1
+ {"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../../../src/components/Menu/Menu.tsx"],"names":[],"mappings":"AAOA,OAAc,EACZ,KAAK,EAAE,EACP,KAAK,SAAS,EAIf,MAAM,OAAO,CAAC;AAyBf,UAAU,KAAK;IACb;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC;IACd;;;;OAIG;IACH,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC;;;;OAIG;IACH,OAAO,EAAE,SAAS,CAAC;IACnB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC3C;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;CACpC;AAsDD;;GAEG;AACH,eAAO,MAAM,IAAI,EAAE,EAAE,CAAC,KAAK,CAqD1B,CAAC"}
@@ -4,16 +4,43 @@ import { MenuContext } from "./MenuContext.js";
4
4
  import { getPlatform } from "../../utils/platform.js";
5
5
  import { DrawerMenu } from "./DrawerMenu.js";
6
6
  import classNames from "classnames";
7
- import { useMemo } from "react";
7
+ import { useEffect, useMemo, useState } from "react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
9
  import { Drawer } from "vaul";
10
- import { Content, DropdownMenuItem, Portal, Root, Trigger } from "@radix-ui/react-dropdown-menu";
10
+ import { Content, DropdownMenuItem, DropdownMenuPortal, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, Portal, Root, Trigger } from "@radix-ui/react-dropdown-menu";
11
11
  //#region src/components/Menu/Menu.tsx
12
12
  var DropdownMenuItemWrapper = ({ onSelect, children }) => /* @__PURE__ */ jsx(DropdownMenuItem, {
13
13
  onSelect: onSelect ?? void 0,
14
14
  asChild: true,
15
15
  children
16
16
  });
17
+ /** Duration of the parent menu's slide-in animation (ms). */
18
+ var MENU_ANIMATION_DURATION = 180;
19
+ var DropdownSubMenuWrapper = ({ trigger, children, open: openProp, onOpenChange }) => {
20
+ const [deferredOpen, setDeferredOpen] = useState(false);
21
+ useEffect(() => {
22
+ if (openProp) {
23
+ const timer = setTimeout(() => setDeferredOpen(true), MENU_ANIMATION_DURATION);
24
+ return () => clearTimeout(timer);
25
+ } else setDeferredOpen(false);
26
+ }, [openProp]);
27
+ return /* @__PURE__ */ jsxs(DropdownMenuSub, {
28
+ open: openProp ? deferredOpen : openProp,
29
+ onOpenChange,
30
+ children: [/* @__PURE__ */ jsx(DropdownMenuSubTrigger, {
31
+ asChild: true,
32
+ children: trigger
33
+ }), /* @__PURE__ */ jsx(DropdownMenuPortal, { children: /* @__PURE__ */ jsx(DropdownMenuSubContent, {
34
+ asChild: true,
35
+ alignOffset: -20,
36
+ children: /* @__PURE__ */ jsx(FloatingMenu, {
37
+ title: "",
38
+ showTitle: false,
39
+ children
40
+ })
41
+ }) })]
42
+ });
43
+ };
17
44
  /**
18
45
  * A menu opened by pressing a button.
19
46
  */
@@ -22,6 +49,7 @@ var Menu = ({ className, title, showTitle = true, open, onOpenChange, trigger, c
22
49
  const drawer = platform === "android" || platform === "ios";
23
50
  const context = useMemo(() => ({
24
51
  MenuItemWrapper: drawer ? null : DropdownMenuItemWrapper,
52
+ SubMenuWrapper: drawer ? null : DropdownSubMenuWrapper,
25
53
  onOpenChange
26
54
  }), [onOpenChange]);
27
55
  const children = /* @__PURE__ */ jsx(MenuContext.Provider, {
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.js","names":[],"sources":["../../../src/components/Menu/Menu.tsx"],"sourcesContent":["/*\nCopyright 2023 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 React, { type FC, type ReactNode, useMemo } from \"react\";\nimport {\n Root,\n Trigger,\n Portal,\n Content,\n DropdownMenuItem,\n} from \"@radix-ui/react-dropdown-menu\";\nimport { FloatingMenu } from \"./FloatingMenu\";\nimport { Drawer } from \"vaul\";\nimport classnames from \"classnames\";\nimport drawerMenu from \"./DrawerMenu.module.css\";\nimport {\n MenuContext,\n type MenuData,\n type MenuItemWrapperProps,\n} from \"./MenuContext\";\nimport { DrawerMenu } from \"./DrawerMenu\";\nimport { getPlatform } from \"../../utils/platform\";\n\ninterface Props {\n /**\n * CSS classes for the menu.\n */\n className?: string;\n\n /**\n * The menu title. This can be hidden with `showTitle={false}` in which case it will only\n * be a label for screen readers.\n */\n title: string;\n /**\n * Controls whether the title is displayed (see `title` prop). Titles are only displayed on\n * web: on mobile, this parameter is ignored.\n */\n showTitle?: boolean;\n /**\n * Whether the menu is open.\n */\n open: boolean;\n /**\n * Event handler called when the open state of the menu changes. This includes\n * anything like clicking the trigger, selecting a menu item, or dismissing\n * the menu with the mouse or keyboard.\n */\n onOpenChange: (open: boolean) => void;\n /**\n * The button that opens the menu. This must be a component that accepts a ref\n * and spreads props.\n * https://www.radix-ui.com/primitives/docs/guides/composition\n */\n trigger: ReactNode;\n /**\n * The menu contents.\n */\n children: ReactNode;\n /**\n * The side of the trigger on which to place the menu. Note that the menu may\n * still end up on a different side than the one you request if there isn't\n * enough space.\n * @default bottom\n */\n side?: \"top\" | \"right\" | \"bottom\" | \"left\";\n /**\n * The edge along which the menu and trigger will be aligned.\n * @default center\n */\n align?: \"start\" | \"center\" | \"end\";\n}\n\nconst DropdownMenuItemWrapper: FC<MenuItemWrapperProps> = ({\n onSelect,\n children,\n}) => (\n <DropdownMenuItem onSelect={onSelect ?? undefined} asChild>\n {children}\n </DropdownMenuItem>\n);\n\n/**\n * A menu opened by pressing a button.\n */\nexport const Menu: FC<Props> = ({\n className,\n title,\n showTitle = true,\n open,\n onOpenChange,\n trigger,\n children: childrenProp,\n side = \"bottom\",\n align = \"center\",\n}) => {\n // Normally, the menu takes the form of a floating box. But on Android and\n // iOS, the menu should morph into a drawer\n const platform = getPlatform();\n const drawer = platform === \"android\" || platform === \"ios\";\n const context: MenuData = useMemo(\n () => ({\n MenuItemWrapper: drawer ? null : DropdownMenuItemWrapper,\n onOpenChange,\n }),\n [onOpenChange],\n );\n const children = (\n <MenuContext.Provider value={context}>{childrenProp}</MenuContext.Provider>\n );\n\n return drawer ? (\n <Drawer.Root open={open} onOpenChange={onOpenChange}>\n <Drawer.Trigger asChild>{trigger}</Drawer.Trigger>\n <Drawer.Portal>\n <Drawer.Overlay className={classnames(drawerMenu.bg)} />\n <Drawer.Content asChild>\n <DrawerMenu title={title}>{children}</DrawerMenu>\n </Drawer.Content>\n </Drawer.Portal>\n </Drawer.Root>\n ) : (\n <Root open={open} onOpenChange={onOpenChange}>\n <Trigger asChild>{trigger}</Trigger>\n <Portal>\n <Content asChild side={side} align={align} sideOffset={8}>\n <FloatingMenu\n className={className}\n title={title}\n showTitle={showTitle}\n >\n {children}\n </FloatingMenu>\n </Content>\n </Portal>\n </Root>\n );\n};\n"],"mappings":";;;;;;;;;;;AA6EA,IAAM,2BAAqD,EACzD,UACA,eAEA,oBAAC,kBAAD;CAAkB,UAAU,YAAY,KAAA;CAAW,SAAA;CAChD;CACgB,CAAA;;;;AAMrB,IAAa,QAAmB,EAC9B,WACA,OACA,YAAY,MACZ,MACA,cACA,SACA,UAAU,cACV,OAAO,UACP,QAAQ,eACJ;CAGJ,MAAM,WAAW,aAAa;CAC9B,MAAM,SAAS,aAAa,aAAa,aAAa;CACtD,MAAM,UAAoB,eACjB;EACL,iBAAiB,SAAS,OAAO;EACjC;EACD,GACD,CAAC,aAAa,CACf;CACD,MAAM,WACJ,oBAAC,YAAY,UAAb;EAAsB,OAAO;YAAU;EAAoC,CAAA;AAG7E,QAAO,SACL,qBAAC,OAAO,MAAR;EAAmB;EAAoB;YAAvC,CACE,oBAAC,OAAO,SAAR;GAAgB,SAAA;aAAS;GAAyB,CAAA,EAClD,qBAAC,OAAO,QAAR,EAAA,UAAA,CACE,oBAAC,OAAO,SAAR,EAAgB,WAAW,WAAW,0BAAW,GAAG,EAAI,CAAA,EACxD,oBAAC,OAAO,SAAR;GAAgB,SAAA;aACd,oBAAC,YAAD;IAAmB;IAAQ;IAAsB,CAAA;GAClC,CAAA,CACH,EAAA,CAAA,CACJ;MAEd,qBAAC,MAAD;EAAY;EAAoB;YAAhC,CACE,oBAAC,SAAD;GAAS,SAAA;aAAS;GAAkB,CAAA,EACpC,oBAAC,QAAD,EAAA,UACE,oBAAC,SAAD;GAAS,SAAA;GAAc;GAAa;GAAO,YAAY;aACrD,oBAAC,cAAD;IACa;IACJ;IACI;IAEV;IACY,CAAA;GACP,CAAA,EACH,CAAA,CACJ"}
1
+ {"version":3,"file":"Menu.js","names":[],"sources":["../../../src/components/Menu/Menu.tsx"],"sourcesContent":["/*\nCopyright 2023 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 React, {\n type FC,\n type ReactNode,\n useMemo,\n useEffect,\n useState,\n} from \"react\";\nimport {\n Root,\n Trigger,\n Portal,\n Content,\n DropdownMenuItem,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n DropdownMenuPortal,\n} from \"@radix-ui/react-dropdown-menu\";\nimport { FloatingMenu } from \"./FloatingMenu\";\nimport { Drawer } from \"vaul\";\nimport classnames from \"classnames\";\nimport drawerMenu from \"./DrawerMenu.module.css\";\nimport {\n MenuContext,\n type MenuData,\n type MenuItemWrapperProps,\n type SubMenuWrapperProps,\n} from \"./MenuContext\";\nimport { DrawerMenu } from \"./DrawerMenu\";\nimport { getPlatform } from \"../../utils/platform\";\n\ninterface Props {\n /**\n * CSS classes for the menu.\n */\n className?: string;\n\n /**\n * The menu title. This can be hidden with `showTitle={false}` in which case it will only\n * be a label for screen readers.\n */\n title: string;\n /**\n * Controls whether the title is displayed (see `title` prop). Titles are only displayed on\n * web: on mobile, this parameter is ignored.\n */\n showTitle?: boolean;\n /**\n * Whether the menu is open.\n */\n open: boolean;\n /**\n * Event handler called when the open state of the menu changes. This includes\n * anything like clicking the trigger, selecting a menu item, or dismissing\n * the menu with the mouse or keyboard.\n */\n onOpenChange: (open: boolean) => void;\n /**\n * The button that opens the menu. This must be a component that accepts a ref\n * and spreads props.\n * https://www.radix-ui.com/primitives/docs/guides/composition\n */\n trigger: ReactNode;\n /**\n * The menu contents.\n */\n children: ReactNode;\n /**\n * The side of the trigger on which to place the menu. Note that the menu may\n * still end up on a different side than the one you request if there isn't\n * enough space.\n * @default bottom\n */\n side?: \"top\" | \"right\" | \"bottom\" | \"left\";\n /**\n * The edge along which the menu and trigger will be aligned.\n * @default center\n */\n align?: \"start\" | \"center\" | \"end\";\n}\n\nconst DropdownMenuItemWrapper: FC<MenuItemWrapperProps> = ({\n onSelect,\n children,\n}) => (\n <DropdownMenuItem onSelect={onSelect ?? undefined} asChild>\n {children}\n </DropdownMenuItem>\n);\n\n/** Duration of the parent menu's slide-in animation (ms). */\nconst MENU_ANIMATION_DURATION = 180;\n\nconst DropdownSubMenuWrapper: FC<SubMenuWrapperProps> = ({\n trigger,\n children,\n open: openProp,\n onOpenChange,\n}) => {\n // When the submenu is programmatically opened at the same time as the parent\n // menu (e.g. open={true} on mount), the parent is still mid-animation and\n // the trigger position hasn't settled. Defer the open so the submenu\n // positions correctly after the parent animation completes.\n const [deferredOpen, setDeferredOpen] = useState(false);\n\n useEffect(() => {\n if (openProp) {\n const timer = setTimeout(\n () => setDeferredOpen(true),\n MENU_ANIMATION_DURATION,\n );\n return () => clearTimeout(timer);\n } else {\n setDeferredOpen(false);\n }\n }, [openProp]);\n\n const open = openProp ? deferredOpen : openProp;\n\n return (\n <DropdownMenuSub open={open} onOpenChange={onOpenChange}>\n <DropdownMenuSubTrigger asChild>{trigger}</DropdownMenuSubTrigger>\n <DropdownMenuPortal>\n <DropdownMenuSubContent asChild alignOffset={-20}>\n <FloatingMenu title=\"\" showTitle={false}>\n {children}\n </FloatingMenu>\n </DropdownMenuSubContent>\n </DropdownMenuPortal>\n </DropdownMenuSub>\n );\n};\n\n/**\n * A menu opened by pressing a button.\n */\nexport const Menu: FC<Props> = ({\n className,\n title,\n showTitle = true,\n open,\n onOpenChange,\n trigger,\n children: childrenProp,\n side = \"bottom\",\n align = \"center\",\n}) => {\n // Normally, the menu takes the form of a floating box. But on Android and\n // iOS, the menu should morph into a drawer\n const platform = getPlatform();\n const drawer = platform === \"android\" || platform === \"ios\";\n const context: MenuData = useMemo(\n () => ({\n MenuItemWrapper: drawer ? null : DropdownMenuItemWrapper,\n SubMenuWrapper: drawer ? null : DropdownSubMenuWrapper,\n onOpenChange,\n }),\n [onOpenChange],\n );\n const children = (\n <MenuContext.Provider value={context}>{childrenProp}</MenuContext.Provider>\n );\n\n return drawer ? (\n <Drawer.Root open={open} onOpenChange={onOpenChange}>\n <Drawer.Trigger asChild>{trigger}</Drawer.Trigger>\n <Drawer.Portal>\n <Drawer.Overlay className={classnames(drawerMenu.bg)} />\n <Drawer.Content asChild>\n <DrawerMenu title={title}>{children}</DrawerMenu>\n </Drawer.Content>\n </Drawer.Portal>\n </Drawer.Root>\n ) : (\n <Root open={open} onOpenChange={onOpenChange}>\n <Trigger asChild>{trigger}</Trigger>\n <Portal>\n <Content asChild side={side} align={align} sideOffset={8}>\n <FloatingMenu\n className={className}\n title={title}\n showTitle={showTitle}\n >\n {children}\n </FloatingMenu>\n </Content>\n </Portal>\n </Root>\n );\n};\n"],"mappings":";;;;;;;;;;;AAwFA,IAAM,2BAAqD,EACzD,UACA,eAEA,oBAAC,kBAAD;CAAkB,UAAU,YAAY,KAAA;CAAW,SAAA;CAChD;CACgB,CAAA;;AAIrB,IAAM,0BAA0B;AAEhC,IAAM,0BAAmD,EACvD,SACA,UACA,MAAM,UACN,mBACI;CAKJ,MAAM,CAAC,cAAc,mBAAmB,SAAS,MAAM;AAEvD,iBAAgB;AACd,MAAI,UAAU;GACZ,MAAM,QAAQ,iBACN,gBAAgB,KAAK,EAC3B,wBACD;AACD,gBAAa,aAAa,MAAM;QAEhC,iBAAgB,MAAM;IAEvB,CAAC,SAAS,CAAC;AAId,QACE,qBAAC,iBAAD;EAAuB,MAHZ,WAAW,eAAe;EAGM;YAA3C,CACE,oBAAC,wBAAD;GAAwB,SAAA;aAAS;GAAiC,CAAA,EAClE,oBAAC,oBAAD,EAAA,UACE,oBAAC,wBAAD;GAAwB,SAAA;GAAQ,aAAa;aAC3C,oBAAC,cAAD;IAAc,OAAM;IAAG,WAAW;IAC/B;IACY,CAAA;GACQ,CAAA,EACN,CAAA,CACL;;;;;;AAOtB,IAAa,QAAmB,EAC9B,WACA,OACA,YAAY,MACZ,MACA,cACA,SACA,UAAU,cACV,OAAO,UACP,QAAQ,eACJ;CAGJ,MAAM,WAAW,aAAa;CAC9B,MAAM,SAAS,aAAa,aAAa,aAAa;CACtD,MAAM,UAAoB,eACjB;EACL,iBAAiB,SAAS,OAAO;EACjC,gBAAgB,SAAS,OAAO;EAChC;EACD,GACD,CAAC,aAAa,CACf;CACD,MAAM,WACJ,oBAAC,YAAY,UAAb;EAAsB,OAAO;YAAU;EAAoC,CAAA;AAG7E,QAAO,SACL,qBAAC,OAAO,MAAR;EAAmB;EAAoB;YAAvC,CACE,oBAAC,OAAO,SAAR;GAAgB,SAAA;aAAS;GAAyB,CAAA,EAClD,qBAAC,OAAO,QAAR,EAAA,UAAA,CACE,oBAAC,OAAO,SAAR,EAAgB,WAAW,WAAW,0BAAW,GAAG,EAAI,CAAA,EACxD,oBAAC,OAAO,SAAR;GAAgB,SAAA;aACd,oBAAC,YAAD;IAAmB;IAAQ;IAAsB,CAAA;GAClC,CAAA,CACH,EAAA,CAAA,CACJ;MAEd,qBAAC,MAAD;EAAY;EAAoB;YAAhC,CACE,oBAAC,SAAD;GAAS,SAAA;aAAS;GAAkB,CAAA,EACpC,oBAAC,QAAD,EAAA,UACE,oBAAC,SAAD;GAAS,SAAA;GAAc;GAAa;GAAO,YAAY;aACrD,oBAAC,cAAD;IACa;IACJ;IACI;IAEV;IACY,CAAA;GACP,CAAA,EACH,CAAA,CACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"MenuContext.cjs","names":[],"sources":["../../../src/components/Menu/MenuContext.tsx"],"sourcesContent":["/*\nCopyright 2023 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 { type ComponentType, type ReactNode, createContext } from \"react\";\n\nexport interface MenuItemWrapperProps {\n /**\n * Event callback for when the item is selected via mouse, touch, or keyboard.\n * Calling event.preventDefault in this handler will prevent the menu from\n * being dismissed.\n */\n onSelect: (e: Event) => void;\n children: ReactNode;\n}\n\nexport interface MenuData {\n /**\n * A component that wraps interactive menu items.\n */\n MenuItemWrapper: ComponentType<MenuItemWrapperProps> | null;\n /**\n * Event handler called when the open state of the menu changes.\n */\n onOpenChange: (open: boolean) => void;\n}\n\n/**\n * A React context providing information about the menu in which a given\n * component resides.\n */\nexport const MenuContext = createContext<MenuData | null>(null);\n"],"mappings":";;;;;;AAkCA,IAAa,eAAA,oBAAA,eAA6C,KAAK"}
1
+ {"version":3,"file":"MenuContext.cjs","names":[],"sources":["../../../src/components/Menu/MenuContext.tsx"],"sourcesContent":["/*\nCopyright 2023 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 { type ComponentType, type ReactNode, createContext } from \"react\";\n\nexport interface MenuItemWrapperProps {\n /**\n * Event callback for when the item is selected via mouse, touch, or keyboard.\n * Calling event.preventDefault in this handler will prevent the menu from\n * being dismissed.\n */\n onSelect: (e: Event) => void;\n children: ReactNode;\n}\n\nexport interface SubMenuWrapperProps {\n /**\n * The trigger element that opens the submenu (typically a MenuItem).\n */\n trigger: ReactNode;\n /**\n * The submenu contents.\n */\n children: ReactNode;\n /**\n * Whether the submenu is open (controlled).\n */\n open?: boolean;\n /**\n * Event handler called when the open state of the submenu changes.\n */\n onOpenChange?: (open: boolean) => void;\n}\n\nexport interface MenuData {\n /**\n * A component that wraps interactive menu items.\n */\n MenuItemWrapper: ComponentType<MenuItemWrapperProps> | null;\n /**\n * A component that wraps submenus.\n */\n SubMenuWrapper: ComponentType<SubMenuWrapperProps> | null;\n /**\n * Event handler called when the open state of the menu changes.\n */\n onOpenChange: (open: boolean) => void;\n}\n\n/**\n * A React context providing information about the menu in which a given\n * component resides.\n */\nexport const MenuContext = createContext<MenuData | null>(null);\n"],"mappings":";;;;;;AAyDA,IAAa,eAAA,oBAAA,eAA6C,KAAK"}