se-design 1.0.73-dev3 → 1.0.73-dev7

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 (45) hide show
  1. package/dist/components/CustomModal/index.d.ts +4 -6
  2. package/dist/components/MenuList/index.d.ts +3 -2
  3. package/dist/components/Popover/index.d.ts +2 -2
  4. package/dist/index12.js +30 -18
  5. package/dist/index12.js.map +1 -1
  6. package/dist/index15.js +1 -1
  7. package/dist/index17.js +36 -33
  8. package/dist/index17.js.map +1 -1
  9. package/dist/index18.js +129 -124
  10. package/dist/index18.js.map +1 -1
  11. package/dist/index192.js +2 -2
  12. package/dist/{index229.js → index193.js} +1 -1
  13. package/dist/{index229.js.map → index193.js.map} +1 -1
  14. package/dist/index194.js +26 -0
  15. package/dist/index194.js.map +1 -0
  16. package/dist/index197.js +20 -80
  17. package/dist/index197.js.map +1 -1
  18. package/dist/index199.js +82 -21
  19. package/dist/index199.js.map +1 -1
  20. package/dist/{index207.js → index208.js} +1 -1
  21. package/dist/{index207.js.map → index208.js.map} +1 -1
  22. package/dist/{index215.js → index216.js} +1 -1
  23. package/dist/{index215.js.map → index216.js.map} +1 -1
  24. package/dist/{index218.js → index219.js} +1 -1
  25. package/dist/{index218.js.map → index219.js.map} +1 -1
  26. package/dist/{index227.js → index228.js} +1 -1
  27. package/dist/{index227.js.map → index228.js.map} +1 -1
  28. package/dist/index24.js +1 -1
  29. package/dist/index27.js +1 -1
  30. package/dist/index28.js +94 -90
  31. package/dist/index28.js.map +1 -1
  32. package/dist/index32.js +42 -44
  33. package/dist/index32.js.map +1 -1
  34. package/dist/index37.js +1 -1
  35. package/dist/index39.js +1 -1
  36. package/dist/index44.js +1 -1
  37. package/dist/index45.js +2 -2
  38. package/dist/index48.js +1 -1
  39. package/dist/index52.js +1 -1
  40. package/dist/index62.js +1 -1
  41. package/dist/index64.js +52 -60
  42. package/dist/index64.js.map +1 -1
  43. package/package.json +1 -1
  44. package/dist/index195.js +0 -27
  45. package/dist/index195.js.map +0 -1
@@ -11,21 +11,19 @@ export interface CustomModalProps {
11
11
  automationId?: string;
12
12
  }
13
13
  /**
14
- * A11y note: CustomModal is a dumb container consumers are responsible for adding dialog semantics
15
- * to the content rendered via `renderModalContent`. Follow the same pattern as Modal/index.tsx:
14
+ * A11y note: CustomModal handles focus trap and Escape dismissal automatically.
15
+ * Consumers are responsible for adding dialog semantics to the content rendered
16
+ * via `renderModalContent`:
16
17
  *
17
18
  * <div
18
- * ref={containerRef}
19
19
  * role="dialog"
20
20
  * aria-modal="true"
21
21
  * aria-labelledby={titleId} // or aria-label if no visible heading
22
- * tabIndex={-1}
23
22
  * >
24
23
  * <h2 id={titleId}>...</h2>
25
24
  * ...
26
25
  * </div>
27
26
  *
28
- * Also use useFocusTrap + useDismissOnEscape from 'src/utils/a11y' inside the consumer component.
29
- * See Paywall/index.tsx for a complete reference implementation.
27
+ * See Paywall/index.tsx for a reference implementation.
30
28
  */
31
29
  export declare const CustomModal: FC<CustomModalProps>;
@@ -1,4 +1,4 @@
1
- import { FC } from 'react';
1
+ import { default as React } from 'react';
2
2
  import { MenuItemProps } from '../MenuItem';
3
3
  export type MenuListProps = {
4
4
  items: MenuItemProps[];
@@ -7,5 +7,6 @@ export type MenuListProps = {
7
7
  searchPlaceholder?: string;
8
8
  searchBy?: string;
9
9
  searchResultEmptyMessage?: string;
10
+ className?: string;
10
11
  };
11
- export declare const MenuList: FC<MenuListProps>;
12
+ export declare const MenuList: React.ForwardRefExoticComponent<MenuListProps & React.RefAttributes<HTMLDivElement>>;
@@ -1,6 +1,6 @@
1
1
  import { default as React, ReactNode } from 'react';
2
2
  export interface PopoverHandle {
3
- togglePopover: (focusFirst?: boolean) => void;
3
+ togglePopover: (focusFirst?: boolean | 'last') => void;
4
4
  }
5
5
  export interface PopoverProps {
6
6
  className?: string;
@@ -11,7 +11,7 @@ export interface PopoverProps {
11
11
  }) => ReactNode;
12
12
  renderPopoverSrcElement: (props: {
13
13
  displayPopover: boolean;
14
- togglePopover: (focusFirst?: boolean) => void;
14
+ togglePopover: (focusFirst?: boolean | 'last') => void;
15
15
  }) => ReactNode;
16
16
  position?: 'bottom-center' | 'bottom-left' | 'bottom-right' | 'top-center' | 'top-left' | 'top-right';
17
17
  onPopoverToggle?: (displayPopover: boolean) => void;
package/dist/index12.js CHANGED
@@ -1,28 +1,40 @@
1
- import e from "react";
2
- const c = (t) => {
1
+ import o, { useRef as c } from "react";
2
+ import { useFocusTrap as u } from "./index193.js";
3
+ import { useDismissOnEscape as f } from "./index194.js";
4
+ const v = (s) => {
3
5
  const {
4
- renderModalContent: a,
5
- isOpen: o,
6
- width: n = "500px",
7
- className: s = "",
8
- contentClassName: i = "",
9
- automationId: l = "",
6
+ renderModalContent: n,
7
+ isOpen: e,
8
+ width: a = "500px",
9
+ className: i = "",
10
+ contentClassName: l = "",
11
+ automationId: r = "",
10
12
  onModalClick: d = () => {
11
- }
12
- } = t;
13
- return /* @__PURE__ */ e.createElement("div", {
14
- className: `se-design-modal fixed inset-0 flex items-start justify-center z-[2001] backdrop-brightness-50 backdrop-blur-sm ${o ? "visible" : "invisible pointer-events-none"} ${s}`,
15
- "data-automation-id": l,
13
+ },
14
+ onClose: m
15
+ } = s, t = c(null);
16
+ return u({
17
+ enabled: e,
18
+ containerRef: t,
19
+ restoreFocus: !0
20
+ }), f({
21
+ enabled: e,
22
+ containerRef: t,
23
+ onDismiss: m
24
+ }), /* @__PURE__ */ o.createElement("div", {
25
+ className: `se-design-modal fixed inset-0 flex items-start justify-center z-[2001] backdrop-brightness-50 backdrop-blur-sm ${e ? "visible" : "invisible pointer-events-none"} ${i}`,
26
+ "data-automation-id": r,
16
27
  onClick: d
17
- }, /* @__PURE__ */ e.createElement("div", {
18
- className: `modal-content flex flex-col gap-3 bg-[var(--color-white)] rounded shadow-lg p-8 mt-[48px] ${i}`,
28
+ }, /* @__PURE__ */ o.createElement("div", {
29
+ ref: t,
30
+ className: `modal-content flex flex-col gap-3 bg-[var(--color-white)] rounded shadow-lg p-8 mt-[48px] ${l}`,
19
31
  style: {
20
- width: n,
32
+ width: a,
21
33
  maxWidth: "100vw"
22
34
  }
23
- }, a()));
35
+ }, n()));
24
36
  };
25
37
  export {
26
- c as CustomModal
38
+ v as CustomModal
27
39
  };
28
40
  //# sourceMappingURL=index12.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index12.js","sources":["../src/components/CustomModal/index.tsx"],"sourcesContent":["import React, { FC } from 'react';\n\nexport interface CustomModalProps {\n onSubmit?: () => void;\n onClose?: () => void;\n onModalClick?: () => void;\n renderModalContent: () => React.ReactNode;\n isOpen: boolean;\n width?: string;\n className?: string;\n contentClassName?: string;\n automationId?: string;\n}\n\n/**\n * A11y note: CustomModal is a dumb container consumers are responsible for adding dialog semantics\n * to the content rendered via `renderModalContent`. Follow the same pattern as Modal/index.tsx:\n *\n * <div\n * ref={containerRef}\n * role=\"dialog\"\n * aria-modal=\"true\"\n * aria-labelledby={titleId} // or aria-label if no visible heading\n * tabIndex={-1}\n * >\n * <h2 id={titleId}>...</h2>\n * ...\n * </div>\n *\n * Also use useFocusTrap + useDismissOnEscape from 'src/utils/a11y' inside the consumer component.\n * See Paywall/index.tsx for a complete reference implementation.\n */\nexport const CustomModal: FC<CustomModalProps> = (props) => {\n const {\n renderModalContent,\n isOpen,\n width = '500px',\n className = '',\n contentClassName = '',\n automationId = '',\n onModalClick = () => {}\n } = props;\n\n return (\n <div\n className={`se-design-modal fixed inset-0 flex items-start justify-center z-[2001] backdrop-brightness-50 backdrop-blur-sm ${\n isOpen ? 'visible' : 'invisible pointer-events-none'\n } ${className}`}\n data-automation-id={automationId}\n onClick={onModalClick}\n >\n <div\n className={`modal-content flex flex-col gap-3 bg-[var(--color-white)] rounded shadow-lg p-8 mt-[48px] ${contentClassName}`}\n style={{ width, maxWidth: '100vw' }}\n >\n {renderModalContent()}\n </div>\n </div>\n );\n};\n"],"names":["React__default","CustomModal","props","renderModalContent","isOpen","width","className","contentClassName","automationId","onModalClick","React","createElement","onClick","style","maxWidth"],"mappings":"AAgCO,OAAAA,OAAA;AAAA,MAAMC,IAAqCC,CAAAA,MAAU;AAC1D,QAAM;AAAA,IACJC,oBAAAA;AAAAA,IACAC,QAAAA;AAAAA,IACAC,OAAAA,IAAQ;AAAA,IACRC,WAAAA,IAAY;AAAA,IACZC,kBAAAA,IAAmB;AAAA,IACnBC,cAAAA,IAAe;AAAA,IACfC,cAAAA,IAAeA,MAAM;AAAA,IAAC;AAAA,EAAA,IACpBP;AAEJ,SACEQ,gBAAAA,EAAAC,cAAA,OAAA;AAAA,IACEL,WAAW,kHACTF,IAAS,YAAY,+BAA+B,IAClDE,CAAS;AAAA,IACb,sBAAoBE;AAAAA,IACpBI,SAASH;AAAAA,EAAAA,GAETC,gBAAAA,EAAAC,cAAA,OAAA;AAAA,IACEL,WAAW,6FAA6FC,CAAgB;AAAA,IACxHM,OAAO;AAAA,MAAER,OAAAA;AAAAA,MAAOS,UAAU;AAAA,IAAA;AAAA,EAAQ,GAEjCX,EAAAA,CACE,CACF;AAET;"}
1
+ {"version":3,"file":"index12.js","sources":["../src/components/CustomModal/index.tsx"],"sourcesContent":["import React, { FC, useRef } from 'react';\nimport { useFocusTrap, useDismissOnEscape } from 'src/utils/a11y';\n\nexport interface CustomModalProps {\n onSubmit?: () => void;\n onClose?: () => void;\n onModalClick?: () => void;\n renderModalContent: () => React.ReactNode;\n isOpen: boolean;\n width?: string;\n className?: string;\n contentClassName?: string;\n automationId?: string;\n}\n\n/**\n * A11y note: CustomModal handles focus trap and Escape dismissal automatically.\n * Consumers are responsible for adding dialog semantics to the content rendered\n * via `renderModalContent`:\n *\n * <div\n * role=\"dialog\"\n * aria-modal=\"true\"\n * aria-labelledby={titleId} // or aria-label if no visible heading\n * >\n * <h2 id={titleId}>...</h2>\n * ...\n * </div>\n *\n * See Paywall/index.tsx for a reference implementation.\n */\nexport const CustomModal: FC<CustomModalProps> = (props) => {\n const {\n renderModalContent,\n isOpen,\n width = '500px',\n className = '',\n contentClassName = '',\n automationId = '',\n onModalClick = () => {},\n onClose,\n } = props;\n\n const modalContentRef = useRef<HTMLDivElement>(null);\n\n useFocusTrap({\n enabled: isOpen,\n containerRef: modalContentRef,\n restoreFocus: true,\n });\n\n useDismissOnEscape({\n enabled: isOpen,\n containerRef: modalContentRef,\n onDismiss: onClose,\n });\n\n return (\n <div\n className={`se-design-modal fixed inset-0 flex items-start justify-center z-[2001] backdrop-brightness-50 backdrop-blur-sm ${\n isOpen ? 'visible' : 'invisible pointer-events-none'\n } ${className}`}\n data-automation-id={automationId}\n onClick={onModalClick}\n >\n <div\n ref={modalContentRef}\n className={`modal-content flex flex-col gap-3 bg-[var(--color-white)] rounded shadow-lg p-8 mt-[48px] ${contentClassName}`}\n style={{ width, maxWidth: '100vw' }}\n >\n {renderModalContent()}\n </div>\n </div>\n );\n};\n"],"names":["React__default","useRef","useFocusTrap","useDismissOnEscape","CustomModal","props","renderModalContent","isOpen","width","className","contentClassName","automationId","onModalClick","onClose","modalContentRef","enabled","containerRef","restoreFocus","onDismiss","React","createElement","onClick","ref","style","maxWidth"],"mappings":"AA+BO,OAAAA,KAAA,UAAAC,SAAA;AAAA,SAAA,gBAAAC,SAAA;AAAA,SAAA,sBAAAC,SAAA;AAAA,MAAMC,IAAqCC,CAAAA,MAAU;AAC1D,QAAM;AAAA,IACJC,oBAAAA;AAAAA,IACAC,QAAAA;AAAAA,IACAC,OAAAA,IAAQ;AAAA,IACRC,WAAAA,IAAY;AAAA,IACZC,kBAAAA,IAAmB;AAAA,IACnBC,cAAAA,IAAe;AAAA,IACfC,cAAAA,IAAeA,MAAM;AAAA,IAAC;AAAA,IACtBC,SAAAA;AAAAA,EAAAA,IACER,GAEES,IAAkBb,EAAuB,IAAI;AAEnDC,SAAAA,EAAa;AAAA,IACXa,SAASR;AAAAA,IACTS,cAAcF;AAAAA,IACdG,cAAc;AAAA,EAAA,CACf,GAEDd,EAAmB;AAAA,IACjBY,SAASR;AAAAA,IACTS,cAAcF;AAAAA,IACdI,WAAWL;AAAAA,EAAAA,CACZ,GAGCM,gBAAAA,EAAAC,cAAA,OAAA;AAAA,IACEX,WAAW,kHACTF,IAAS,YAAY,+BAA+B,IAClDE,CAAS;AAAA,IACb,sBAAoBE;AAAAA,IACpBU,SAAST;AAAAA,EAAAA,GAETO,gBAAAA,EAAAC,cAAA,OAAA;AAAA,IACEE,KAAKR;AAAAA,IACLL,WAAW,6FAA6FC,CAAgB;AAAA,IACxHa,OAAO;AAAA,MAAEf,OAAAA;AAAAA,MAAOgB,UAAU;AAAA,IAAA;AAAA,EAAQ,GAEjClB,EAAAA,CACE,CACF;AAET;"}
package/dist/index15.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import m, { useState as N, useRef as $, useEffect as P } from "react";
2
2
  import V, { flushSync as Z } from "react-dom";
3
3
  import { useStableId as O } from "./index190.js";
4
- import { useDismissOnFocusOut as ee } from "./index195.js";
4
+ import { useDismissOnFocusOut as ee } from "./index197.js";
5
5
  function I() {
6
6
  return I = Object.assign ? Object.assign.bind() : function(g) {
7
7
  for (var h = 1; h < arguments.length; h++) {
package/dist/index17.js CHANGED
@@ -1,7 +1,7 @@
1
- import t, { useState as $, useMemo as y } from "react";
2
- import { MenuItem as k } from "./index16.js";
3
- import { InputWithIcon as F } from "./index51.js";
4
- import { useRovingFocus as R } from "./index68.js";
1
+ import t, { forwardRef as k, useState as F, useMemo as g } from "react";
2
+ import { MenuItem as L } from "./index16.js";
3
+ import { InputWithIcon as S } from "./index51.js";
4
+ import { useRovingFocus as C } from "./index68.js";
5
5
  function m() {
6
6
  return m = Object.assign ? Object.assign.bind() : function(a) {
7
7
  for (var o = 1; o < arguments.length; o++) {
@@ -11,17 +11,18 @@ function m() {
11
11
  return a;
12
12
  }, m.apply(null, arguments);
13
13
  }
14
- const P = ({
14
+ const O = /* @__PURE__ */ k(({
15
15
  items: a,
16
16
  maxHeight: o,
17
17
  shouldShowSearch: n = !1,
18
18
  searchPlaceholder: l = "Search...",
19
- searchBy: g = "label",
20
- searchResultEmptyMessage: v = "No results found"
21
- }) => {
22
- const [i, b] = $(""), I = () => i.trim() ? a.filter((e) => (e[g]?.toString().toLowerCase() || "").includes(i.toLowerCase())) : a, h = () => /* @__PURE__ */ t.createElement("div", {
19
+ searchBy: v = "label",
20
+ searchResultEmptyMessage: b = "No results found",
21
+ className: p = ""
22
+ }, I) => {
23
+ const [i, h] = F(""), x = () => i.trim() ? a.filter((e) => (e[v]?.toString().toLowerCase() || "").includes(i.toLowerCase())) : a, w = () => /* @__PURE__ */ t.createElement("div", {
23
24
  className: "w-full relative flex items-center border-b border-[var(--color-gray-300)] px-1"
24
- }, /* @__PURE__ */ t.createElement(F, {
25
+ }, /* @__PURE__ */ t.createElement(S, {
25
26
  leftIcon: {
26
27
  name: "search",
27
28
  position: "left",
@@ -30,7 +31,7 @@ const P = ({
30
31
  }
31
32
  },
32
33
  value: i,
33
- onChange: (e) => b(e),
34
+ onChange: (e) => h(e),
34
35
  placeholder: l,
35
36
  style: {
36
37
  margin: 0,
@@ -42,31 +43,32 @@ const P = ({
42
43
  outline: "none"
43
44
  },
44
45
  automationId: "se-design-menu-list-search"
45
- })), c = I(), x = o ? {
46
+ })), c = x(), E = o ? {
46
47
  maxHeight: o,
47
48
  overflowY: "auto"
48
- } : {}, d = y(() => {
49
+ } : {}, d = g(() => {
49
50
  const e = /* @__PURE__ */ new WeakMap(), r = /* @__PURE__ */ new Set();
50
- return a.forEach((s, p) => {
51
- const f = s.id || s.automationId || `menu-item-${p}`;
52
- let u = f;
53
- r.has(u) && (u = `${f}-${p}`), r.add(u), e.set(s, u);
51
+ return a.forEach((s, f) => {
52
+ const y = s.id || s.automationId || `menu-item-${f}`;
53
+ let u = y;
54
+ r.has(u) && (u = `${y}-${f}`), r.add(u), e.set(s, u);
54
55
  }), e;
55
- }, [a]), w = y(() => c.filter((e) => e.type !== "header" && e.type !== "separator").map((e) => d.get(e)), [c, d]), {
56
- getRovingItemProps: E,
57
- handleKeyDown: N,
58
- setFocusedId: M
59
- } = R({
60
- itemIds: w,
56
+ }, [a]), N = g(() => c.filter((e) => e.type !== "header" && e.type !== "separator").map((e) => d.get(e)), [c, d]), {
57
+ getRovingItemProps: $,
58
+ handleKeyDown: M,
59
+ setFocusedId: R
60
+ } = C({
61
+ itemIds: N,
61
62
  orientation: "vertical",
62
63
  loop: !0
63
64
  });
64
65
  return /* @__PURE__ */ t.createElement("div", {
65
- className: `se-design-menu-list border border-[var(--color-gray-200)] rounded shadow-md ${n ? "" : "py-2"}`,
66
+ ref: I,
67
+ className: `se-design-menu-list border border-[var(--color-gray-200)] rounded shadow-md ${n ? "" : "py-2"}${p ? ` ${p}` : ""}`,
66
68
  role: "menu",
67
69
  "aria-label": "Menu"
68
- }, n && h(), /* @__PURE__ */ t.createElement("div", {
69
- style: x,
70
+ }, n && w(), /* @__PURE__ */ t.createElement("div", {
71
+ style: E,
70
72
  className: `overflow-y-auto ${n ? "py-2" : ""}`
71
73
  }, c.length > 0 ? c.map((e) => {
72
74
  const r = d.get(e);
@@ -81,21 +83,22 @@ const P = ({
81
83
  className: "se-design-menu-header cursor-default px-2 mx-1 text-sm pt-2 text-[var(--color-gray-650)]",
82
84
  role: "presentation"
83
85
  }, e.label);
84
- const s = E(r);
85
- return /* @__PURE__ */ t.createElement(k, m({}, e, {
86
+ const s = $(r);
87
+ return /* @__PURE__ */ t.createElement(L, m({}, e, {
86
88
  key: r,
87
89
  ref: s.ref,
88
90
  tabIndex: s.tabIndex,
89
- onKeyDown: N,
90
- onFocus: () => M(r)
91
+ onKeyDown: M,
92
+ onFocus: () => R(r)
91
93
  }));
92
94
  }) : /* @__PURE__ */ t.createElement("div", {
93
95
  className: "px-3 py-4 text-center text-[var(--color-gray-700)] text-sm",
94
96
  role: "status",
95
97
  "aria-live": "polite"
96
- }, v)));
97
- };
98
+ }, b)));
99
+ });
100
+ O.displayName = "MenuList";
98
101
  export {
99
- P as MenuList
102
+ O as MenuList
100
103
  };
101
104
  //# sourceMappingURL=index17.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index17.js","sources":["../src/components/MenuList/index.tsx"],"sourcesContent":["import React, { FC, useState, useMemo } from 'react';\nimport { MenuItem, MenuItemProps } from 'src/components/MenuItem';\nimport { InputWithIcon } from '../InputWithIcon';\nimport { useRovingFocus } from 'src/utils/a11y/useRovingFocus';\n\nexport type MenuListProps = {\n items: MenuItemProps[];\n maxHeight?: string;\n shouldShowSearch?: boolean;\n searchPlaceholder?: string;\n searchBy?: string;\n searchResultEmptyMessage?: string;\n};\n\nexport const MenuList: FC<MenuListProps> = ({\n items,\n maxHeight,\n shouldShowSearch = false,\n searchPlaceholder = 'Search...',\n searchBy = 'label',\n searchResultEmptyMessage = 'No results found'\n}) => {\n const [searchQuery, setSearchQuery] = useState('');\n\n const getFilteredItems = () => {\n if (!searchQuery.trim()) {\n return items;\n }\n return items.filter((item) => {\n const searchValue = item[searchBy as keyof MenuItemProps]?.toString().toLowerCase() || '';\n return searchValue.includes(searchQuery.toLowerCase());\n });\n };\n\n const renderSearchBar = () => {\n return (\n <div className=\"w-full relative flex items-center border-b border-[var(--color-gray-300)] px-1\">\n <InputWithIcon\n leftIcon={{ name: 'search', position: 'left', style: { color: 'var(--color-gray-500)' } }}\n value={searchQuery}\n onChange={(value) => setSearchQuery(value)}\n placeholder={searchPlaceholder}\n style={{ margin: 0, gap: 0 }}\n inputStyle={{ width: '100%', border: 'none', outline: 'none' }}\n automationId=\"se-design-menu-list-search\"\n />\n </div>\n );\n };\n\n const filteredItems = getFilteredItems();\n const containerStyle = maxHeight\n ? {\n maxHeight,\n overflowY: 'auto' as const\n }\n : {};\n\n \n const itemIdByRef = useMemo(() => {\n const map = new WeakMap<MenuItemProps, string>();\n const seen = new Set<string>();\n\n items.forEach((item, index) => {\n const baseId = item.id || item.automationId || `menu-item-${index}`;\n let uniqueId = baseId;\n\n if (seen.has(uniqueId)) {\n uniqueId = `${baseId}-${index}`;\n }\n\n seen.add(uniqueId);\n map.set(item, uniqueId);\n });\n\n return map;\n }, [items]);\n\n const itemIds = useMemo(() => {\n return filteredItems\n .filter((item) => item.type !== 'header' && item.type !== 'separator')\n .map((item) => itemIdByRef.get(item) as string);\n }, [filteredItems, itemIdByRef]);\n\n // Use roving focus for arrow key navigation\n const { getRovingItemProps, handleKeyDown, setFocusedId } = useRovingFocus({\n itemIds,\n orientation: 'vertical',\n loop: true\n });\n\n return (\n <div\n className={`se-design-menu-list border border-[var(--color-gray-200)] rounded shadow-md ${\n shouldShowSearch ? '' : 'py-2'\n }`}\n role=\"menu\"\n aria-label=\"Menu\"\n >\n {shouldShowSearch && renderSearchBar()}\n <div style={containerStyle} className={`overflow-y-auto ${shouldShowSearch ? 'py-2' : ''}`}>\n {filteredItems.length > 0 ? (\n filteredItems.map((item) => {\n const stableId = itemIdByRef.get(item) as string;\n\n if (item.type === 'separator') {\n return (\n <hr key={stableId} className=\"se-design-menu-separator cursor-default border-[var(--color-gray-200)]\" />\n );\n }\n\n if (item.type === 'header') {\n return (\n <div\n key={stableId}\n className=\"se-design-menu-header cursor-default px-2 mx-1 text-sm pt-2 text-[var(--color-gray-650)]\"\n role=\"presentation\"\n >\n {item.label}\n </div>\n );\n }\n\n const rovingProps = getRovingItemProps(stableId);\n return (\n <MenuItem\n {...item}\n key={stableId}\n ref={rovingProps.ref}\n tabIndex={rovingProps.tabIndex}\n onKeyDown={handleKeyDown}\n onFocus={() => setFocusedId(stableId)}\n />\n );\n })\n ) : (\n <div className=\"px-3 py-4 text-center text-[var(--color-gray-700)] text-sm\" role=\"status\" aria-live=\"polite\">{searchResultEmptyMessage}</div>\n )}\n </div>\n </div>\n );\n};\n"],"names":["MenuList","items","maxHeight","shouldShowSearch","searchPlaceholder","searchBy","searchResultEmptyMessage","searchQuery","setSearchQuery","useState","getFilteredItems","trim","filter","item","toString","toLowerCase","includes","renderSearchBar","React","createElement","className","InputWithIcon","leftIcon","name","position","style","color","value","onChange","placeholder","margin","gap","inputStyle","width","border","outline","automationId","filteredItems","containerStyle","overflowY","itemIdByRef","useMemo","map","WeakMap","seen","Set","forEach","index","baseId","id","uniqueId","has","add","set","itemIds","type","get","getRovingItemProps","handleKeyDown","setFocusedId","useRovingFocus","orientation","loop","role","length","stableId","key","label","rovingProps","MenuItem","_extends","ref","tabIndex","onKeyDown","onFocus"],"mappings":"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"}
1
+ {"version":3,"file":"index17.js","sources":["../src/components/MenuList/index.tsx"],"sourcesContent":["import React, { forwardRef, useState, useMemo } from 'react';\nimport { MenuItem, MenuItemProps } from 'src/components/MenuItem';\nimport { InputWithIcon } from '../InputWithIcon';\nimport { useRovingFocus } from 'src/utils/a11y/useRovingFocus';\n\nexport type MenuListProps = {\n items: MenuItemProps[];\n maxHeight?: string;\n shouldShowSearch?: boolean;\n searchPlaceholder?: string;\n searchBy?: string;\n searchResultEmptyMessage?: string;\n className?: string;\n};\n\nexport const MenuList = forwardRef<HTMLDivElement, MenuListProps>(({\n items,\n maxHeight,\n shouldShowSearch = false,\n searchPlaceholder = 'Search...',\n searchBy = 'label',\n searchResultEmptyMessage = 'No results found',\n className = ''\n}, ref) => {\n const [searchQuery, setSearchQuery] = useState('');\n\n const getFilteredItems = () => {\n if (!searchQuery.trim()) {\n return items;\n }\n return items.filter((item) => {\n const searchValue = item[searchBy as keyof MenuItemProps]?.toString().toLowerCase() || '';\n return searchValue.includes(searchQuery.toLowerCase());\n });\n };\n\n const renderSearchBar = () => {\n return (\n <div className=\"w-full relative flex items-center border-b border-[var(--color-gray-300)] px-1\">\n <InputWithIcon\n leftIcon={{ name: 'search', position: 'left', style: { color: 'var(--color-gray-500)' } }}\n value={searchQuery}\n onChange={(value) => setSearchQuery(value)}\n placeholder={searchPlaceholder}\n style={{ margin: 0, gap: 0 }}\n inputStyle={{ width: '100%', border: 'none', outline: 'none' }}\n automationId=\"se-design-menu-list-search\"\n />\n </div>\n );\n };\n\n const filteredItems = getFilteredItems();\n const containerStyle = maxHeight\n ? {\n maxHeight,\n overflowY: 'auto' as const\n }\n : {};\n\n \n const itemIdByRef = useMemo(() => {\n const map = new WeakMap<MenuItemProps, string>();\n const seen = new Set<string>();\n\n items.forEach((item, index) => {\n const baseId = item.id || item.automationId || `menu-item-${index}`;\n let uniqueId = baseId;\n\n if (seen.has(uniqueId)) {\n uniqueId = `${baseId}-${index}`;\n }\n\n seen.add(uniqueId);\n map.set(item, uniqueId);\n });\n\n return map;\n }, [items]);\n\n const itemIds = useMemo(() => {\n return filteredItems\n .filter((item) => item.type !== 'header' && item.type !== 'separator')\n .map((item) => itemIdByRef.get(item) as string);\n }, [filteredItems, itemIdByRef]);\n\n // Use roving focus for arrow key navigation\n const { getRovingItemProps, handleKeyDown, setFocusedId } = useRovingFocus({\n itemIds,\n orientation: 'vertical',\n loop: true\n });\n\n return (\n <div\n ref={ref}\n className={`se-design-menu-list border border-[var(--color-gray-200)] rounded shadow-md ${\n shouldShowSearch ? '' : 'py-2'\n }${className ? ` ${className}` : ''}`}\n role=\"menu\"\n aria-label=\"Menu\"\n >\n {shouldShowSearch && renderSearchBar()}\n <div style={containerStyle} className={`overflow-y-auto ${shouldShowSearch ? 'py-2' : ''}`}>\n {filteredItems.length > 0 ? (\n filteredItems.map((item) => {\n const stableId = itemIdByRef.get(item) as string;\n\n if (item.type === 'separator') {\n return (\n <hr key={stableId} className=\"se-design-menu-separator cursor-default border-[var(--color-gray-200)]\" />\n );\n }\n\n if (item.type === 'header') {\n return (\n <div\n key={stableId}\n className=\"se-design-menu-header cursor-default px-2 mx-1 text-sm pt-2 text-[var(--color-gray-650)]\"\n role=\"presentation\"\n >\n {item.label}\n </div>\n );\n }\n\n const rovingProps = getRovingItemProps(stableId);\n return (\n <MenuItem\n {...item}\n key={stableId}\n ref={rovingProps.ref}\n tabIndex={rovingProps.tabIndex}\n onKeyDown={handleKeyDown}\n onFocus={() => setFocusedId(stableId)}\n />\n );\n })\n ) : (\n <div className=\"px-3 py-4 text-center text-[var(--color-gray-700)] text-sm\" role=\"status\" aria-live=\"polite\">{searchResultEmptyMessage}</div>\n )}\n </div>\n </div>\n );\n});\n\nMenuList.displayName = 'MenuList';\n"],"names":["MenuList","items","maxHeight","shouldShowSearch","searchPlaceholder","searchBy","searchResultEmptyMessage","className","ref","searchQuery","setSearchQuery","useState","getFilteredItems","trim","filter","item","toString","toLowerCase","includes","renderSearchBar","React","createElement","InputWithIcon","leftIcon","name","position","style","color","value","onChange","placeholder","margin","gap","inputStyle","width","border","outline","automationId","filteredItems","containerStyle","overflowY","itemIdByRef","useMemo","map","WeakMap","seen","Set","forEach","index","baseId","id","uniqueId","has","add","set","itemIds","type","get","getRovingItemProps","handleKeyDown","setFocusedId","useRovingFocus","orientation","loop","role","length","stableId","key","label","rovingProps","MenuItem","_extends","tabIndex","onKeyDown","onFocus","displayName"],"mappings":"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"}