@misael703/ui 1.0.1 → 1.2.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 (178) hide show
  1. package/dist/chunk-2S6JJYN7.js +209 -0
  2. package/dist/chunk-2S6JJYN7.js.map +1 -0
  3. package/dist/{chunk-GDFYAUHT.mjs → chunk-3N4IBCLW.mjs} +11 -29
  4. package/dist/chunk-3N4IBCLW.mjs.map +1 -0
  5. package/dist/{chunk-TB6EHWRF.mjs → chunk-3OVWAAGP.mjs} +3 -3
  6. package/dist/{chunk-TB6EHWRF.mjs.map → chunk-3OVWAAGP.mjs.map} +1 -1
  7. package/dist/chunk-427NHGTX.js +4 -0
  8. package/dist/chunk-427NHGTX.js.map +1 -0
  9. package/dist/chunk-6P2TKRTL.mjs +45 -0
  10. package/dist/chunk-6P2TKRTL.mjs.map +1 -0
  11. package/dist/chunk-6RVCYULF.mjs +78 -0
  12. package/dist/chunk-6RVCYULF.mjs.map +1 -0
  13. package/dist/chunk-BVQRDAR7.mjs +3 -0
  14. package/dist/chunk-BVQRDAR7.mjs.map +1 -0
  15. package/dist/{chunk-TXKFCVCN.mjs → chunk-C35GKQJO.mjs} +3 -3
  16. package/dist/{chunk-TXKFCVCN.mjs.map → chunk-C35GKQJO.mjs.map} +1 -1
  17. package/dist/chunk-DPMUWQHL.js +95 -0
  18. package/dist/chunk-DPMUWQHL.js.map +1 -0
  19. package/dist/chunk-GIOMV3J7.js +48 -0
  20. package/dist/chunk-GIOMV3J7.js.map +1 -0
  21. package/dist/chunk-GLYGO7WX.js +13 -0
  22. package/dist/chunk-GLYGO7WX.js.map +1 -0
  23. package/dist/chunk-H3PRT76O.mjs +73 -0
  24. package/dist/chunk-H3PRT76O.mjs.map +1 -0
  25. package/dist/{chunk-Z4GRQHIG.mjs → chunk-IEJXZ67E.mjs} +3 -3
  26. package/dist/{chunk-Z4GRQHIG.mjs.map → chunk-IEJXZ67E.mjs.map} +1 -1
  27. package/dist/chunk-IMHLJKYR.mjs +176 -0
  28. package/dist/chunk-IMHLJKYR.mjs.map +1 -0
  29. package/dist/{chunk-EJJDJJEM.js → chunk-K5S3SV2U.js} +108 -106
  30. package/dist/chunk-K5S3SV2U.js.map +1 -0
  31. package/dist/{chunk-ADIKHOEG.js → chunk-KOIRRZRD.js} +72 -6
  32. package/dist/chunk-KOIRRZRD.js.map +1 -0
  33. package/dist/{chunk-ZXSSOEIM.js → chunk-LXNHGGAK.js} +4 -4
  34. package/dist/{chunk-ZXSSOEIM.js.map → chunk-LXNHGGAK.js.map} +1 -1
  35. package/dist/{chunk-HI3JT6SI.mjs → chunk-MM7VE7YN.mjs} +72 -6
  36. package/dist/chunk-MM7VE7YN.mjs.map +1 -0
  37. package/dist/chunk-MUL2FKYF.js +100 -0
  38. package/dist/chunk-MUL2FKYF.js.map +1 -0
  39. package/dist/chunk-N2Y2KWX5.mjs +216 -0
  40. package/dist/chunk-N2Y2KWX5.mjs.map +1 -0
  41. package/dist/{chunk-CVXS7IHA.js → chunk-N7LFCAAY.js} +112 -113
  42. package/dist/chunk-N7LFCAAY.js.map +1 -0
  43. package/dist/chunk-OCLBAGNF.mjs +184 -0
  44. package/dist/chunk-OCLBAGNF.mjs.map +1 -0
  45. package/dist/{chunk-QSCJ2CER.mjs → chunk-OHCS5CYV.mjs} +108 -106
  46. package/dist/chunk-OHCS5CYV.mjs.map +1 -0
  47. package/dist/{chunk-LUXTZOTJ.js → chunk-OHMFYAB2.js} +4 -4
  48. package/dist/{chunk-LUXTZOTJ.js.map → chunk-OHMFYAB2.js.map} +1 -1
  49. package/dist/{chunk-T4R2LSRL.js → chunk-PROKTOL7.js} +3 -2
  50. package/dist/chunk-PROKTOL7.js.map +1 -0
  51. package/dist/{chunk-3UHX7ITQ.mjs → chunk-QI4JT3V3.mjs} +29 -34
  52. package/dist/chunk-QI4JT3V3.mjs.map +1 -0
  53. package/dist/{chunk-Z3FAKG3E.mjs → chunk-QW2CSXPH.mjs} +3 -2
  54. package/dist/chunk-QW2CSXPH.mjs.map +1 -0
  55. package/dist/chunk-QX5GGPV5.mjs +11 -0
  56. package/dist/chunk-QX5GGPV5.mjs.map +1 -0
  57. package/dist/{chunk-2RVSLQEA.mjs → chunk-R76SJURE.mjs} +3 -3
  58. package/dist/{chunk-2RVSLQEA.mjs.map → chunk-R76SJURE.mjs.map} +1 -1
  59. package/dist/{chunk-E2XOUDAH.js → chunk-REL2RZTI.js} +14 -32
  60. package/dist/chunk-REL2RZTI.js.map +1 -0
  61. package/dist/{chunk-R76YER7O.js → chunk-TBAKKSAN.js} +4 -4
  62. package/dist/{chunk-R76YER7O.js.map → chunk-TBAKKSAN.js.map} +1 -1
  63. package/dist/chunk-V7MK42GX.js +238 -0
  64. package/dist/chunk-V7MK42GX.js.map +1 -0
  65. package/dist/chunk-VR4OXVKE.js +198 -0
  66. package/dist/chunk-VR4OXVKE.js.map +1 -0
  67. package/dist/chunk-WLDQP4KD.mjs +75 -0
  68. package/dist/chunk-WLDQP4KD.mjs.map +1 -0
  69. package/dist/{chunk-W6YOBPL5.js → chunk-WVN5JJVV.js} +27 -40
  70. package/dist/chunk-WVN5JJVV.js.map +1 -0
  71. package/dist/chunk-XMLBKK7X.js +67 -0
  72. package/dist/chunk-XMLBKK7X.js.map +1 -0
  73. package/dist/chunk-XXUSZD5I.mjs +26 -0
  74. package/dist/chunk-XXUSZD5I.mjs.map +1 -0
  75. package/dist/{chunk-IIYQO6BL.js → chunk-YAORRBMU.js} +29 -34
  76. package/dist/chunk-YAORRBMU.js.map +1 -0
  77. package/dist/{chunk-AAQ7KUZH.mjs → chunk-YFLVB62R.mjs} +112 -113
  78. package/dist/chunk-YFLVB62R.mjs.map +1 -0
  79. package/dist/{chunk-UIKCTWKG.js → chunk-YRACSKAT.js} +4 -4
  80. package/dist/{chunk-UIKCTWKG.js.map → chunk-YRACSKAT.js.map} +1 -1
  81. package/dist/components/AdvancedPickers.js +8 -5
  82. package/dist/components/AdvancedPickers.mjs +4 -1
  83. package/dist/components/AppShell.js +3 -3
  84. package/dist/components/AppShell.mjs +1 -1
  85. package/dist/components/Comments.js +8 -5
  86. package/dist/components/Comments.mjs +5 -2
  87. package/dist/components/Commerce.js +14 -13
  88. package/dist/components/Commerce.mjs +3 -2
  89. package/dist/components/ContextMenu.js +5 -2
  90. package/dist/components/ContextMenu.mjs +4 -1
  91. package/dist/components/Display2.js +8 -5
  92. package/dist/components/Display2.mjs +4 -1
  93. package/dist/components/Display3.js +11 -8
  94. package/dist/components/Display3.mjs +5 -2
  95. package/dist/components/Editing.js +8 -7
  96. package/dist/components/Editing.mjs +3 -2
  97. package/dist/components/HoverCard.js +4 -2
  98. package/dist/components/HoverCard.mjs +3 -1
  99. package/dist/components/Layout.js +20 -18
  100. package/dist/components/Layout.mjs +3 -1
  101. package/dist/components/Menubar.js +5 -2
  102. package/dist/components/Menubar.mjs +4 -1
  103. package/dist/components/NavigationMenu.js +5 -2
  104. package/dist/components/NavigationMenu.mjs +4 -1
  105. package/dist/components/Overlay.js +4 -3
  106. package/dist/components/Overlay.mjs +2 -1
  107. package/dist/components/Pickers.js +7 -4
  108. package/dist/components/Pickers.mjs +4 -1
  109. package/dist/components/Popover.js +5 -2
  110. package/dist/components/Popover.mjs +4 -1
  111. package/dist/components/Portal.d.mts +30 -0
  112. package/dist/components/Portal.d.ts +30 -0
  113. package/dist/components/Portal.js +12 -0
  114. package/dist/components/Portal.js.map +1 -0
  115. package/dist/components/Portal.mjs +3 -0
  116. package/dist/components/Portal.mjs.map +1 -0
  117. package/dist/hooks/index.d.mts +4 -0
  118. package/dist/hooks/index.d.ts +4 -0
  119. package/dist/hooks/index.js +23 -0
  120. package/dist/hooks/index.js.map +1 -0
  121. package/dist/hooks/index.mjs +6 -0
  122. package/dist/hooks/index.mjs.map +1 -0
  123. package/dist/hooks/useDelayedUnmount.d.mts +22 -0
  124. package/dist/hooks/useDelayedUnmount.d.ts +22 -0
  125. package/dist/hooks/useDelayedUnmount.js +12 -0
  126. package/dist/hooks/useDelayedUnmount.js.map +1 -0
  127. package/dist/hooks/useDelayedUnmount.mjs +3 -0
  128. package/dist/hooks/useDelayedUnmount.mjs.map +1 -0
  129. package/dist/hooks/useDismiss.d.mts +23 -0
  130. package/dist/hooks/useDismiss.d.ts +23 -0
  131. package/dist/hooks/useDismiss.js +12 -0
  132. package/dist/hooks/useDismiss.js.map +1 -0
  133. package/dist/hooks/useDismiss.mjs +3 -0
  134. package/dist/hooks/useDismiss.mjs.map +1 -0
  135. package/dist/hooks/usePopoverPosition.d.mts +50 -0
  136. package/dist/hooks/usePopoverPosition.d.ts +50 -0
  137. package/dist/hooks/usePopoverPosition.js +12 -0
  138. package/dist/hooks/usePopoverPosition.js.map +1 -0
  139. package/dist/hooks/usePopoverPosition.mjs +3 -0
  140. package/dist/hooks/usePopoverPosition.mjs.map +1 -0
  141. package/dist/index.d.mts +4 -1
  142. package/dist/index.d.ts +4 -1
  143. package/dist/index.js +95 -78
  144. package/dist/index.mjs +21 -16
  145. package/dist/styles.css +1 -1
  146. package/dist/tokens.css +1 -1
  147. package/package.json +1 -1
  148. package/dist/chunk-3UHX7ITQ.mjs.map +0 -1
  149. package/dist/chunk-5VMZMDJF.js +0 -145
  150. package/dist/chunk-5VMZMDJF.js.map +0 -1
  151. package/dist/chunk-7AKN7FDA.mjs +0 -103
  152. package/dist/chunk-7AKN7FDA.mjs.map +0 -1
  153. package/dist/chunk-AAQ7KUZH.mjs.map +0 -1
  154. package/dist/chunk-ADIKHOEG.js.map +0 -1
  155. package/dist/chunk-CVXS7IHA.js.map +0 -1
  156. package/dist/chunk-E2XOUDAH.js.map +0 -1
  157. package/dist/chunk-EJJDJJEM.js.map +0 -1
  158. package/dist/chunk-GDFYAUHT.mjs.map +0 -1
  159. package/dist/chunk-HI3JT6SI.mjs.map +0 -1
  160. package/dist/chunk-HPFJ2A24.js +0 -125
  161. package/dist/chunk-HPFJ2A24.js.map +0 -1
  162. package/dist/chunk-IIYQO6BL.js.map +0 -1
  163. package/dist/chunk-JDOXRLZW.js +0 -138
  164. package/dist/chunk-JDOXRLZW.js.map +0 -1
  165. package/dist/chunk-NLCKWF3Y.mjs +0 -88
  166. package/dist/chunk-NLCKWF3Y.mjs.map +0 -1
  167. package/dist/chunk-NUURPO3J.mjs +0 -120
  168. package/dist/chunk-NUURPO3J.mjs.map +0 -1
  169. package/dist/chunk-OCE4ODTM.mjs +0 -116
  170. package/dist/chunk-OCE4ODTM.mjs.map +0 -1
  171. package/dist/chunk-QI6TVWWF.js +0 -121
  172. package/dist/chunk-QI6TVWWF.js.map +0 -1
  173. package/dist/chunk-QSCJ2CER.mjs.map +0 -1
  174. package/dist/chunk-T4R2LSRL.js.map +0 -1
  175. package/dist/chunk-W6YOBPL5.js.map +0 -1
  176. package/dist/chunk-YBOTLQ3G.mjs +0 -99
  177. package/dist/chunk-YBOTLQ3G.mjs.map +0 -1
  178. package/dist/chunk-Z3FAKG3E.mjs.map +0 -1
@@ -0,0 +1,198 @@
1
+ 'use strict';
2
+
3
+ var chunkXMLBKK7X_js = require('./chunk-XMLBKK7X.js');
4
+ var chunkDPMUWQHL_js = require('./chunk-DPMUWQHL.js');
5
+ var chunkGLYGO7WX_js = require('./chunk-GLYGO7WX.js');
6
+ var chunkRQOTH7I7_js = require('./chunk-RQOTH7I7.js');
7
+ var chunkPASF6T4H_js = require('./chunk-PASF6T4H.js');
8
+ var React = require('react');
9
+ var jsxRuntime = require('react/jsx-runtime');
10
+
11
+ function _interopNamespace(e) {
12
+ if (e && e.__esModule) return e;
13
+ var n = Object.create(null);
14
+ if (e) {
15
+ Object.keys(e).forEach(function (k) {
16
+ if (k !== 'default') {
17
+ var d = Object.getOwnPropertyDescriptor(e, k);
18
+ Object.defineProperty(n, k, d.get ? d : {
19
+ enumerable: true,
20
+ get: function () { return e[k]; }
21
+ });
22
+ }
23
+ });
24
+ }
25
+ n.default = e;
26
+ return Object.freeze(n);
27
+ }
28
+
29
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
30
+
31
+ function NavigationMenu({ items, className, ariaLabel = "Navegaci\xF3n principal", linkAs, rootLinkAs }) {
32
+ const [openId, setOpenId] = React__namespace.useState(null);
33
+ const focusOnOpen = React__namespace.useRef(false);
34
+ const rootRef = React__namespace.useRef(null);
35
+ const panelRef = React__namespace.useRef(null);
36
+ const anchorRef = React__namespace.useRef(null);
37
+ const triggerRefs = React__namespace.useRef({});
38
+ const open = openId !== null;
39
+ const pos = chunkDPMUWQHL_js.usePopoverPosition(anchorRef, panelRef, {
40
+ open,
41
+ side: "bottom",
42
+ align: "start",
43
+ offset: 8
44
+ });
45
+ chunkXMLBKK7X_js.useDismiss({
46
+ open,
47
+ onDismiss: () => setOpenId(null),
48
+ refs: [rootRef, panelRef],
49
+ closeOnEscape: false
50
+ });
51
+ const closeAndFocusTrigger = () => {
52
+ const id = openId;
53
+ setOpenId(null);
54
+ if (id) triggerRefs.current[id]?.focus();
55
+ };
56
+ const panelLinks = () => Array.from(panelRef.current?.querySelectorAll(".nav-menu__link") ?? []);
57
+ const focusLinkAt = (index) => {
58
+ const links = panelLinks();
59
+ if (links.length === 0) return;
60
+ const wrapped = (index % links.length + links.length) % links.length;
61
+ links[wrapped]?.focus();
62
+ };
63
+ React__namespace.useEffect(() => {
64
+ if (open && focusOnOpen.current) {
65
+ focusOnOpen.current = false;
66
+ focusLinkAt(0);
67
+ }
68
+ }, [open]);
69
+ const onPanelKeyDown = (e) => {
70
+ const links = panelLinks();
71
+ const current = links.indexOf(document.activeElement);
72
+ if (e.key === "Escape") {
73
+ e.preventDefault();
74
+ closeAndFocusTrigger();
75
+ } else if (e.key === "Tab") {
76
+ setOpenId(null);
77
+ } else if (e.key === "ArrowDown") {
78
+ e.preventDefault();
79
+ focusLinkAt(current + 1);
80
+ } else if (e.key === "ArrowUp") {
81
+ e.preventDefault();
82
+ focusLinkAt(current - 1);
83
+ } else if (e.key === "Home") {
84
+ e.preventDefault();
85
+ focusLinkAt(0);
86
+ } else if (e.key === "End") {
87
+ e.preventDefault();
88
+ focusLinkAt(links.length - 1);
89
+ }
90
+ };
91
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { ref: rootRef, "aria-label": ariaLabel, className: chunkPASF6T4H_js.cx("nav-menu", className), children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "nav-menu__list", children: items.map((item) => {
92
+ const hasChildren = !!item.links?.length;
93
+ const isOpen = openId === item.id;
94
+ const triggerCls = chunkPASF6T4H_js.cx("nav-menu__trigger", isOpen && "is-open");
95
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
96
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: item.label }),
97
+ hasChildren && /* @__PURE__ */ jsxRuntime.jsx(chunkRQOTH7I7_js.ChevronDown, { size: 14, className: "nav-menu__chevron" })
98
+ ] });
99
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "nav-menu__item", children: [
100
+ hasChildren ? /* @__PURE__ */ jsxRuntime.jsx(
101
+ "button",
102
+ {
103
+ type: "button",
104
+ ref: (el) => {
105
+ triggerRefs.current[item.id] = el;
106
+ },
107
+ className: triggerCls,
108
+ "aria-expanded": isOpen,
109
+ "aria-haspopup": "menu",
110
+ onClick: (e) => {
111
+ if (isOpen) {
112
+ setOpenId(null);
113
+ return;
114
+ }
115
+ anchorRef.current = e.currentTarget;
116
+ focusOnOpen.current = false;
117
+ setOpenId(item.id);
118
+ },
119
+ onMouseEnter: (e) => {
120
+ if (!openId) return;
121
+ anchorRef.current = e.currentTarget;
122
+ focusOnOpen.current = false;
123
+ setOpenId(item.id);
124
+ },
125
+ onKeyDown: (e) => {
126
+ if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
127
+ e.preventDefault();
128
+ if (isOpen) {
129
+ focusLinkAt(0);
130
+ return;
131
+ }
132
+ anchorRef.current = e.currentTarget;
133
+ focusOnOpen.current = true;
134
+ setOpenId(item.id);
135
+ } else if (e.key === "Escape" && isOpen) {
136
+ e.preventDefault();
137
+ setOpenId(null);
138
+ }
139
+ },
140
+ children: content
141
+ }
142
+ ) : rootLinkAs && item.href ? rootLinkAs(item, content, triggerCls) : /* @__PURE__ */ jsxRuntime.jsx("a", { className: triggerCls, href: item.href, children: content }),
143
+ hasChildren && isOpen && /* @__PURE__ */ jsxRuntime.jsx(chunkGLYGO7WX_js.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
144
+ "div",
145
+ {
146
+ ref: panelRef,
147
+ className: "nav-menu__panel",
148
+ role: "menu",
149
+ "aria-label": typeof item.label === "string" ? item.label : void 0,
150
+ onKeyDown: onPanelKeyDown,
151
+ style: {
152
+ position: "absolute",
153
+ top: pos.top,
154
+ left: pos.left,
155
+ visibility: pos.ready ? "visible" : "hidden"
156
+ },
157
+ children: [
158
+ item.featured && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "nav-menu__featured", children: [
159
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: item.featured.label }),
160
+ item.featured.description && /* @__PURE__ */ jsxRuntime.jsx("p", { children: item.featured.description })
161
+ ] }),
162
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "nav-menu__sublist", children: item.links.map((link) => {
163
+ const linkCls = "nav-menu__link";
164
+ const linkContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
165
+ link.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nav-menu__link-icon", children: link.icon }),
166
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "nav-menu__link-body", children: [
167
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nav-menu__link-label", children: link.label }),
168
+ link.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "nav-menu__link-desc", children: link.description })
169
+ ] })
170
+ ] });
171
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { role: "none", children: linkAs ? linkAs(link, linkContent, linkCls) : /* @__PURE__ */ jsxRuntime.jsx(
172
+ "a",
173
+ {
174
+ role: "menuitem",
175
+ tabIndex: -1,
176
+ className: linkCls,
177
+ href: link.href,
178
+ onClick: (e) => {
179
+ if (link.onClick) {
180
+ e.preventDefault();
181
+ link.onClick();
182
+ }
183
+ closeAndFocusTrigger();
184
+ },
185
+ children: linkContent
186
+ }
187
+ ) }, link.id);
188
+ }) })
189
+ ]
190
+ }
191
+ ) })
192
+ ] }, item.id);
193
+ }) }) });
194
+ }
195
+
196
+ exports.NavigationMenu = NavigationMenu;
197
+ //# sourceMappingURL=chunk-VR4OXVKE.js.map
198
+ //# sourceMappingURL=chunk-VR4OXVKE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/NavigationMenu.tsx"],"names":["React","usePopoverPosition","useDismiss","cx","jsxs","Fragment","jsx","ChevronDown","Portal"],"mappings":"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","file":"chunk-VR4OXVKE.js","sourcesContent":["'use client';\nimport * as React from 'react';\nimport { cx } from '../utils/cx';\nimport { ChevronDown } from './Icons';\nimport { Portal } from './Portal';\nimport { usePopoverPosition } from '../hooks/usePopoverPosition';\nimport { useDismiss } from '../hooks/useDismiss';\n\nexport interface NavLink {\n id: string;\n label: React.ReactNode;\n href?: string;\n description?: React.ReactNode;\n icon?: React.ReactNode;\n onClick?: () => void;\n}\n\nexport interface NavMenuItem {\n id: string;\n label: React.ReactNode;\n href?: string;\n links?: NavLink[];\n featured?: NavLink;\n}\n\nexport interface NavigationMenuProps {\n items: NavMenuItem[];\n className?: string;\n ariaLabel?: string;\n linkAs?: (link: NavLink, content: React.ReactNode, className: string) => React.ReactNode;\n rootLinkAs?: (item: NavMenuItem, content: React.ReactNode, className: string) => React.ReactNode;\n}\n\nexport function NavigationMenu({ items, className, ariaLabel = 'Navegación principal', linkAs, rootLinkAs }: NavigationMenuProps) {\n const [openId, setOpenId] = React.useState<string | null>(null);\n // When the panel was opened by keyboard we move focus into it; pointer\n // (click/hover) opens leave focus with the user's cursor.\n const focusOnOpen = React.useRef(false);\n const rootRef = React.useRef<HTMLElement>(null);\n const panelRef = React.useRef<HTMLDivElement>(null);\n // The currently-open trigger; usePopoverPosition anchors to this and\n // focus returns here on close. One panel is open at a time, so a single\n // anchor ref is correct (see todo.md risk note).\n const anchorRef = React.useRef<HTMLElement | null>(null);\n const triggerRefs = React.useRef<Record<string, HTMLButtonElement | null>>({});\n\n const open = openId !== null;\n\n const pos = usePopoverPosition(anchorRef, panelRef, {\n open,\n side: 'bottom',\n align: 'start',\n offset: 8,\n });\n\n // Outside-click closes; Escape is handled on the panel so it can also\n // return focus to the trigger (WAI-ARIA disclosure/menu pattern).\n useDismiss({\n open,\n onDismiss: () => setOpenId(null),\n refs: [rootRef, panelRef],\n closeOnEscape: false,\n });\n\n const closeAndFocusTrigger = () => {\n const id = openId;\n setOpenId(null);\n if (id) triggerRefs.current[id]?.focus();\n };\n\n // `.nav-menu__link` is applied to every link node (default <a> and the\n // `linkAs` render-prop alike), so querying by class manages focus\n // uniformly regardless of how the consumer renders links.\n const panelLinks = (): HTMLElement[] =>\n Array.from(panelRef.current?.querySelectorAll<HTMLElement>('.nav-menu__link') ?? []);\n\n const focusLinkAt = (index: number) => {\n const links = panelLinks();\n if (links.length === 0) return;\n const wrapped = ((index % links.length) + links.length) % links.length;\n links[wrapped]?.focus();\n };\n\n React.useEffect(() => {\n if (open && focusOnOpen.current) {\n focusOnOpen.current = false;\n focusLinkAt(0);\n }\n }, [open]);\n\n const onPanelKeyDown = (e: React.KeyboardEvent) => {\n const links = panelLinks();\n const current = links.indexOf(document.activeElement as HTMLElement);\n if (e.key === 'Escape') {\n e.preventDefault();\n closeAndFocusTrigger();\n } else if (e.key === 'Tab') {\n setOpenId(null);\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n focusLinkAt(current + 1);\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n focusLinkAt(current - 1);\n } else if (e.key === 'Home') {\n e.preventDefault();\n focusLinkAt(0);\n } else if (e.key === 'End') {\n e.preventDefault();\n focusLinkAt(links.length - 1);\n }\n };\n\n return (\n <nav ref={rootRef} aria-label={ariaLabel} className={cx('nav-menu', className)}>\n <ul className=\"nav-menu__list\">\n {items.map((item) => {\n const hasChildren = !!item.links?.length;\n const isOpen = openId === item.id;\n const triggerCls = cx('nav-menu__trigger', isOpen && 'is-open');\n const content = (\n <>\n <span>{item.label}</span>\n {hasChildren && <ChevronDown size={14} className=\"nav-menu__chevron\" />}\n </>\n );\n\n return (\n <li key={item.id} className=\"nav-menu__item\">\n {hasChildren ? (\n <button\n type=\"button\"\n ref={(el) => { triggerRefs.current[item.id] = el; }}\n className={triggerCls}\n aria-expanded={isOpen}\n aria-haspopup=\"menu\"\n onClick={(e) => {\n if (isOpen) { setOpenId(null); return; }\n anchorRef.current = e.currentTarget;\n focusOnOpen.current = false;\n setOpenId(item.id);\n }}\n onMouseEnter={(e) => {\n if (!openId) return;\n anchorRef.current = e.currentTarget;\n focusOnOpen.current = false;\n setOpenId(item.id);\n }}\n onKeyDown={(e) => {\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n if (isOpen) { focusLinkAt(0); return; }\n anchorRef.current = e.currentTarget;\n focusOnOpen.current = true;\n setOpenId(item.id);\n } else if (e.key === 'Escape' && isOpen) {\n e.preventDefault();\n setOpenId(null);\n }\n }}\n >\n {content}\n </button>\n ) : rootLinkAs && item.href ? (\n rootLinkAs(item, content, triggerCls)\n ) : (\n <a className={triggerCls} href={item.href}>\n {content}\n </a>\n )}\n {hasChildren && isOpen && (\n <Portal>\n <div\n ref={panelRef}\n className=\"nav-menu__panel\"\n role=\"menu\"\n aria-label={typeof item.label === 'string' ? item.label : undefined}\n onKeyDown={onPanelKeyDown}\n style={{\n position: 'absolute',\n top: pos.top,\n left: pos.left,\n visibility: pos.ready ? 'visible' : 'hidden',\n }}\n >\n {item.featured && (\n <div className=\"nav-menu__featured\">\n <strong>{item.featured.label}</strong>\n {item.featured.description && <p>{item.featured.description}</p>}\n </div>\n )}\n <ul className=\"nav-menu__sublist\">\n {item.links!.map((link) => {\n const linkCls = 'nav-menu__link';\n const linkContent = (\n <>\n {link.icon && <span className=\"nav-menu__link-icon\">{link.icon}</span>}\n <span className=\"nav-menu__link-body\">\n <span className=\"nav-menu__link-label\">{link.label}</span>\n {link.description && <span className=\"nav-menu__link-desc\">{link.description}</span>}\n </span>\n </>\n );\n return (\n <li key={link.id} role=\"none\">\n {linkAs ? (\n linkAs(link, linkContent, linkCls)\n ) : (\n <a\n role=\"menuitem\"\n tabIndex={-1}\n className={linkCls}\n href={link.href}\n onClick={(e) => {\n if (link.onClick) {\n e.preventDefault();\n link.onClick();\n }\n closeAndFocusTrigger();\n }}\n >\n {linkContent}\n </a>\n )}\n </li>\n );\n })}\n </ul>\n </div>\n </Portal>\n )}\n </li>\n );\n })}\n </ul>\n </nav>\n );\n}\n"]}
@@ -0,0 +1,75 @@
1
+ import { usePopoverPosition } from './chunk-H3PRT76O.mjs';
2
+ import { Portal } from './chunk-QX5GGPV5.mjs';
3
+ import { cx } from './chunk-IEPCH3JB.mjs';
4
+ import * as React from 'react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ function HoverCard({
8
+ trigger,
9
+ children,
10
+ placement = "bottom",
11
+ openDelay = 250,
12
+ closeDelay = 150,
13
+ offset = 8,
14
+ className,
15
+ contentClassName
16
+ }) {
17
+ const [open, setOpen] = React.useState(false);
18
+ const triggerRef = React.useRef(null);
19
+ const contentRef = React.useRef(null);
20
+ const openTimer = React.useRef(null);
21
+ const closeTimer = React.useRef(null);
22
+ const clear = () => {
23
+ if (openTimer.current) clearTimeout(openTimer.current);
24
+ if (closeTimer.current) clearTimeout(closeTimer.current);
25
+ };
26
+ const onEnter = () => {
27
+ clear();
28
+ openTimer.current = setTimeout(() => setOpen(true), openDelay);
29
+ };
30
+ const onLeave = () => {
31
+ clear();
32
+ closeTimer.current = setTimeout(() => setOpen(false), closeDelay);
33
+ };
34
+ React.useEffect(() => () => clear(), []);
35
+ const pos = usePopoverPosition(triggerRef, contentRef, {
36
+ open,
37
+ side: placement,
38
+ align: "center",
39
+ offset
40
+ });
41
+ return /* @__PURE__ */ jsxs(
42
+ "span",
43
+ {
44
+ className: cx("hover-card", className),
45
+ onMouseEnter: onEnter,
46
+ onMouseLeave: onLeave,
47
+ onFocus: onEnter,
48
+ onBlur: onLeave,
49
+ children: [
50
+ /* @__PURE__ */ jsx("span", { ref: triggerRef, className: "hover-card__trigger", children: trigger }),
51
+ open && /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(
52
+ "div",
53
+ {
54
+ ref: contentRef,
55
+ role: "tooltip",
56
+ className: cx("hover-card__content", "is-floating", contentClassName),
57
+ style: {
58
+ position: "absolute",
59
+ top: pos.top,
60
+ left: pos.left,
61
+ visibility: pos.ready ? "visible" : "hidden"
62
+ },
63
+ onMouseEnter: onEnter,
64
+ onMouseLeave: onLeave,
65
+ children
66
+ }
67
+ ) })
68
+ ]
69
+ }
70
+ );
71
+ }
72
+
73
+ export { HoverCard };
74
+ //# sourceMappingURL=chunk-WLDQP4KD.mjs.map
75
+ //# sourceMappingURL=chunk-WLDQP4KD.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/HoverCard.tsx"],"names":[],"mappings":";;;;;;AAmBO,SAAS,SAAA,CAAU;AAAA,EACxB,OAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA,GAAY,QAAA;AAAA,EACZ,SAAA,GAAY,GAAA;AAAA,EACZ,UAAA,GAAa,GAAA;AAAA,EACb,MAAA,GAAS,CAAA;AAAA,EACT,SAAA;AAAA,EACA;AACF,CAAA,EAAmB;AACjB,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAU,eAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,UAAA,GAAmB,aAAwB,IAAI,CAAA;AACrD,EAAA,MAAM,UAAA,GAAmB,aAAuB,IAAI,CAAA;AACpD,EAAA,MAAM,SAAA,GAAkB,aAA6C,IAAI,CAAA;AACzE,EAAA,MAAM,UAAA,GAAmB,aAA6C,IAAI,CAAA;AAE1E,EAAA,MAAM,QAAQ,MAAM;AAClB,IAAA,IAAI,SAAA,CAAU,OAAA,EAAS,YAAA,CAAa,SAAA,CAAU,OAAO,CAAA;AACrD,IAAA,IAAI,UAAA,CAAW,OAAA,EAAS,YAAA,CAAa,UAAA,CAAW,OAAO,CAAA;AAAA,EACzD,CAAA;AAEA,EAAA,MAAM,UAAU,MAAM;AACpB,IAAA,KAAA,EAAM;AACN,IAAA,SAAA,CAAU,UAAU,UAAA,CAAW,MAAM,OAAA,CAAQ,IAAI,GAAG,SAAS,CAAA;AAAA,EAC/D,CAAA;AACA,EAAA,MAAM,UAAU,MAAM;AACpB,IAAA,KAAA,EAAM;AACN,IAAA,UAAA,CAAW,UAAU,UAAA,CAAW,MAAM,OAAA,CAAQ,KAAK,GAAG,UAAU,CAAA;AAAA,EAClE,CAAA;AAEA,EAAM,gBAAU,MAAM,MAAM,KAAA,EAAM,EAAG,EAAE,CAAA;AAEvC,EAAA,MAAM,GAAA,GAAM,kBAAA,CAAmB,UAAA,EAAY,UAAA,EAAY;AAAA,IACrD,IAAA;AAAA,IACA,IAAA,EAAM,SAAA;AAAA,IACN,KAAA,EAAO,QAAA;AAAA,IACP;AAAA,GACD,CAAA;AAED,EAAA,uBACE,IAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA,CAAG,YAAA,EAAc,SAAS,CAAA;AAAA,MACrC,YAAA,EAAc,OAAA;AAAA,MACd,YAAA,EAAc,OAAA;AAAA,MACd,OAAA,EAAS,OAAA;AAAA,MACT,MAAA,EAAQ,OAAA;AAAA,MAER,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAA,EAAK,UAAA,EAAY,SAAA,EAAU,uBAAuB,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,QAC/D,IAAA,wBACE,MAAA,EAAA,EACC,QAAA,kBAAA,GAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,GAAA,EAAK,UAAA;AAAA,YACL,IAAA,EAAK,SAAA;AAAA,YACL,SAAA,EAAW,EAAA,CAAG,qBAAA,EAAuB,aAAA,EAAe,gBAAgB,CAAA;AAAA,YACpE,KAAA,EAAO;AAAA,cACL,QAAA,EAAU,UAAA;AAAA,cACV,KAAK,GAAA,CAAI,GAAA;AAAA,cACT,MAAM,GAAA,CAAI,IAAA;AAAA,cACV,UAAA,EAAY,GAAA,CAAI,KAAA,GAAQ,SAAA,GAAY;AAAA,aACtC;AAAA,YACA,YAAA,EAAc,OAAA;AAAA,YACd,YAAA,EAAc,OAAA;AAAA,YAEb;AAAA;AAAA,SACH,EACF;AAAA;AAAA;AAAA,GAEJ;AAEJ","file":"chunk-WLDQP4KD.mjs","sourcesContent":["'use client';\nimport * as React from 'react';\nimport { cx } from '../utils/cx';\nimport { Portal } from './Portal';\nimport { usePopoverPosition } from '../hooks/usePopoverPosition';\n\nexport type HoverCardPlacement = 'top' | 'bottom' | 'left' | 'right';\n\nexport interface HoverCardProps {\n trigger: React.ReactNode;\n children: React.ReactNode;\n placement?: HoverCardPlacement;\n openDelay?: number;\n closeDelay?: number;\n offset?: number;\n className?: string;\n contentClassName?: string;\n}\n\nexport function HoverCard({\n trigger,\n children,\n placement = 'bottom',\n openDelay = 250,\n closeDelay = 150,\n offset = 8,\n className,\n contentClassName,\n}: HoverCardProps) {\n const [open, setOpen] = React.useState(false);\n const triggerRef = React.useRef<HTMLSpanElement>(null);\n const contentRef = React.useRef<HTMLDivElement>(null);\n const openTimer = React.useRef<ReturnType<typeof setTimeout> | null>(null);\n const closeTimer = React.useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clear = () => {\n if (openTimer.current) clearTimeout(openTimer.current);\n if (closeTimer.current) clearTimeout(closeTimer.current);\n };\n\n const onEnter = () => {\n clear();\n openTimer.current = setTimeout(() => setOpen(true), openDelay);\n };\n const onLeave = () => {\n clear();\n closeTimer.current = setTimeout(() => setOpen(false), closeDelay);\n };\n\n React.useEffect(() => () => clear(), []);\n\n const pos = usePopoverPosition(triggerRef, contentRef, {\n open,\n side: placement,\n align: 'center',\n offset,\n });\n\n return (\n <span\n className={cx('hover-card', className)}\n onMouseEnter={onEnter}\n onMouseLeave={onLeave}\n onFocus={onEnter}\n onBlur={onLeave}\n >\n <span ref={triggerRef} className=\"hover-card__trigger\">{trigger}</span>\n {open && (\n <Portal>\n <div\n ref={contentRef}\n role=\"tooltip\"\n className={cx('hover-card__content', 'is-floating', contentClassName)}\n style={{\n position: 'absolute',\n top: pos.top,\n left: pos.left,\n visibility: pos.ready ? 'visible' : 'hidden',\n }}\n onMouseEnter={onEnter}\n onMouseLeave={onLeave}\n >\n {children}\n </div>\n </Portal>\n )}\n </span>\n );\n}\n"]}
@@ -1,8 +1,9 @@
1
1
  'use strict';
2
2
 
3
+ var chunkDPMUWQHL_js = require('./chunk-DPMUWQHL.js');
4
+ var chunkGLYGO7WX_js = require('./chunk-GLYGO7WX.js');
3
5
  var chunkPASF6T4H_js = require('./chunk-PASF6T4H.js');
4
6
  var React = require('react');
5
- var reactDom = require('react-dom');
6
7
  var jsxRuntime = require('react/jsx-runtime');
7
8
 
8
9
  function _interopNamespace(e) {
@@ -36,7 +37,6 @@ function HoverCard({
36
37
  contentClassName
37
38
  }) {
38
39
  const [open, setOpen] = React__namespace.useState(false);
39
- const [coords, setCoords] = React__namespace.useState(null);
40
40
  const triggerRef = React__namespace.useRef(null);
41
41
  const contentRef = React__namespace.useRef(null);
42
42
  const openTimer = React__namespace.useRef(null);
@@ -54,41 +54,12 @@ function HoverCard({
54
54
  closeTimer.current = setTimeout(() => setOpen(false), closeDelay);
55
55
  };
56
56
  React__namespace.useEffect(() => () => clear(), []);
57
- React__namespace.useEffect(() => {
58
- if (!open || !triggerRef.current || !contentRef.current) return;
59
- const t = triggerRef.current.getBoundingClientRect();
60
- const c = contentRef.current.getBoundingClientRect();
61
- let top = 0;
62
- let left = 0;
63
- if (placement === "bottom") {
64
- top = t.bottom + offset;
65
- left = t.left + (t.width - c.width) / 2;
66
- } else if (placement === "top") {
67
- top = t.top - c.height - offset;
68
- left = t.left + (t.width - c.width) / 2;
69
- } else if (placement === "right") {
70
- left = t.right + offset;
71
- top = t.top + (t.height - c.height) / 2;
72
- } else {
73
- left = t.left - c.width - offset;
74
- top = t.top + (t.height - c.height) / 2;
75
- }
76
- left = Math.max(8, Math.min(left, window.innerWidth - c.width - 8));
77
- top = Math.max(8, Math.min(top, window.innerHeight - c.height - 8));
78
- setCoords({ top: top + window.scrollY, left: left + window.scrollX });
79
- }, [open, placement, offset]);
80
- const panel = open && /* @__PURE__ */ jsxRuntime.jsx(
81
- "div",
82
- {
83
- ref: contentRef,
84
- role: "tooltip",
85
- className: chunkPASF6T4H_js.cx("hover-card__content", contentClassName),
86
- style: coords ? { position: "absolute", top: coords.top, left: coords.left } : { position: "absolute", visibility: "hidden" },
87
- onMouseEnter: onEnter,
88
- onMouseLeave: onLeave,
89
- children
90
- }
91
- );
57
+ const pos = chunkDPMUWQHL_js.usePopoverPosition(triggerRef, contentRef, {
58
+ open,
59
+ side: placement,
60
+ align: "center",
61
+ offset
62
+ });
92
63
  return /* @__PURE__ */ jsxRuntime.jsxs(
93
64
  "span",
94
65
  {
@@ -99,12 +70,28 @@ function HoverCard({
99
70
  onBlur: onLeave,
100
71
  children: [
101
72
  /* @__PURE__ */ jsxRuntime.jsx("span", { ref: triggerRef, className: "hover-card__trigger", children: trigger }),
102
- panel && typeof document !== "undefined" && reactDom.createPortal(panel, document.body)
73
+ open && /* @__PURE__ */ jsxRuntime.jsx(chunkGLYGO7WX_js.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
74
+ "div",
75
+ {
76
+ ref: contentRef,
77
+ role: "tooltip",
78
+ className: chunkPASF6T4H_js.cx("hover-card__content", "is-floating", contentClassName),
79
+ style: {
80
+ position: "absolute",
81
+ top: pos.top,
82
+ left: pos.left,
83
+ visibility: pos.ready ? "visible" : "hidden"
84
+ },
85
+ onMouseEnter: onEnter,
86
+ onMouseLeave: onLeave,
87
+ children
88
+ }
89
+ ) })
103
90
  ]
104
91
  }
105
92
  );
106
93
  }
107
94
 
108
95
  exports.HoverCard = HoverCard;
109
- //# sourceMappingURL=chunk-W6YOBPL5.js.map
110
- //# sourceMappingURL=chunk-W6YOBPL5.js.map
96
+ //# sourceMappingURL=chunk-WVN5JJVV.js.map
97
+ //# sourceMappingURL=chunk-WVN5JJVV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/HoverCard.tsx"],"names":["React","usePopoverPosition","jsxs","cx","jsx","Portal"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmBO,SAAS,SAAA,CAAU;AAAA,EACxB,OAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA,GAAY,QAAA;AAAA,EACZ,SAAA,GAAY,GAAA;AAAA,EACZ,UAAA,GAAa,GAAA;AAAA,EACb,MAAA,GAAS,CAAA;AAAA,EACT,SAAA;AAAA,EACA;AACF,CAAA,EAAmB;AACjB,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAUA,0BAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,UAAA,GAAmBA,wBAAwB,IAAI,CAAA;AACrD,EAAA,MAAM,UAAA,GAAmBA,wBAAuB,IAAI,CAAA;AACpD,EAAA,MAAM,SAAA,GAAkBA,wBAA6C,IAAI,CAAA;AACzE,EAAA,MAAM,UAAA,GAAmBA,wBAA6C,IAAI,CAAA;AAE1E,EAAA,MAAM,QAAQ,MAAM;AAClB,IAAA,IAAI,SAAA,CAAU,OAAA,EAAS,YAAA,CAAa,SAAA,CAAU,OAAO,CAAA;AACrD,IAAA,IAAI,UAAA,CAAW,OAAA,EAAS,YAAA,CAAa,UAAA,CAAW,OAAO,CAAA;AAAA,EACzD,CAAA;AAEA,EAAA,MAAM,UAAU,MAAM;AACpB,IAAA,KAAA,EAAM;AACN,IAAA,SAAA,CAAU,UAAU,UAAA,CAAW,MAAM,OAAA,CAAQ,IAAI,GAAG,SAAS,CAAA;AAAA,EAC/D,CAAA;AACA,EAAA,MAAM,UAAU,MAAM;AACpB,IAAA,KAAA,EAAM;AACN,IAAA,UAAA,CAAW,UAAU,UAAA,CAAW,MAAM,OAAA,CAAQ,KAAK,GAAG,UAAU,CAAA;AAAA,EAClE,CAAA;AAEA,EAAMA,2BAAU,MAAM,MAAM,KAAA,EAAM,EAAG,EAAE,CAAA;AAEvC,EAAA,MAAM,GAAA,GAAMC,mCAAA,CAAmB,UAAA,EAAY,UAAA,EAAY;AAAA,IACrD,IAAA;AAAA,IACA,IAAA,EAAM,SAAA;AAAA,IACN,KAAA,EAAO,QAAA;AAAA,IACP;AAAA,GACD,CAAA;AAED,EAAA,uBACEC,eAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAWC,mBAAA,CAAG,YAAA,EAAc,SAAS,CAAA;AAAA,MACrC,YAAA,EAAc,OAAA;AAAA,MACd,YAAA,EAAc,OAAA;AAAA,MACd,OAAA,EAAS,OAAA;AAAA,MACT,MAAA,EAAQ,OAAA;AAAA,MAER,QAAA,EAAA;AAAA,wBAAAC,cAAA,CAAC,MAAA,EAAA,EAAK,GAAA,EAAK,UAAA,EAAY,SAAA,EAAU,uBAAuB,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,QAC/D,IAAA,mCACEC,uBAAA,EAAA,EACC,QAAA,kBAAAD,cAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,GAAA,EAAK,UAAA;AAAA,YACL,IAAA,EAAK,SAAA;AAAA,YACL,SAAA,EAAWD,mBAAA,CAAG,qBAAA,EAAuB,aAAA,EAAe,gBAAgB,CAAA;AAAA,YACpE,KAAA,EAAO;AAAA,cACL,QAAA,EAAU,UAAA;AAAA,cACV,KAAK,GAAA,CAAI,GAAA;AAAA,cACT,MAAM,GAAA,CAAI,IAAA;AAAA,cACV,UAAA,EAAY,GAAA,CAAI,KAAA,GAAQ,SAAA,GAAY;AAAA,aACtC;AAAA,YACA,YAAA,EAAc,OAAA;AAAA,YACd,YAAA,EAAc,OAAA;AAAA,YAEb;AAAA;AAAA,SACH,EACF;AAAA;AAAA;AAAA,GAEJ;AAEJ","file":"chunk-WVN5JJVV.js","sourcesContent":["'use client';\nimport * as React from 'react';\nimport { cx } from '../utils/cx';\nimport { Portal } from './Portal';\nimport { usePopoverPosition } from '../hooks/usePopoverPosition';\n\nexport type HoverCardPlacement = 'top' | 'bottom' | 'left' | 'right';\n\nexport interface HoverCardProps {\n trigger: React.ReactNode;\n children: React.ReactNode;\n placement?: HoverCardPlacement;\n openDelay?: number;\n closeDelay?: number;\n offset?: number;\n className?: string;\n contentClassName?: string;\n}\n\nexport function HoverCard({\n trigger,\n children,\n placement = 'bottom',\n openDelay = 250,\n closeDelay = 150,\n offset = 8,\n className,\n contentClassName,\n}: HoverCardProps) {\n const [open, setOpen] = React.useState(false);\n const triggerRef = React.useRef<HTMLSpanElement>(null);\n const contentRef = React.useRef<HTMLDivElement>(null);\n const openTimer = React.useRef<ReturnType<typeof setTimeout> | null>(null);\n const closeTimer = React.useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clear = () => {\n if (openTimer.current) clearTimeout(openTimer.current);\n if (closeTimer.current) clearTimeout(closeTimer.current);\n };\n\n const onEnter = () => {\n clear();\n openTimer.current = setTimeout(() => setOpen(true), openDelay);\n };\n const onLeave = () => {\n clear();\n closeTimer.current = setTimeout(() => setOpen(false), closeDelay);\n };\n\n React.useEffect(() => () => clear(), []);\n\n const pos = usePopoverPosition(triggerRef, contentRef, {\n open,\n side: placement,\n align: 'center',\n offset,\n });\n\n return (\n <span\n className={cx('hover-card', className)}\n onMouseEnter={onEnter}\n onMouseLeave={onLeave}\n onFocus={onEnter}\n onBlur={onLeave}\n >\n <span ref={triggerRef} className=\"hover-card__trigger\">{trigger}</span>\n {open && (\n <Portal>\n <div\n ref={contentRef}\n role=\"tooltip\"\n className={cx('hover-card__content', 'is-floating', contentClassName)}\n style={{\n position: 'absolute',\n top: pos.top,\n left: pos.left,\n visibility: pos.ready ? 'visible' : 'hidden',\n }}\n onMouseEnter={onEnter}\n onMouseLeave={onLeave}\n >\n {children}\n </div>\n </Portal>\n )}\n </span>\n );\n}\n"]}
@@ -0,0 +1,67 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+
5
+ function _interopNamespace(e) {
6
+ if (e && e.__esModule) return e;
7
+ var n = Object.create(null);
8
+ if (e) {
9
+ Object.keys(e).forEach(function (k) {
10
+ if (k !== 'default') {
11
+ var d = Object.getOwnPropertyDescriptor(e, k);
12
+ Object.defineProperty(n, k, d.get ? d : {
13
+ enumerable: true,
14
+ get: function () { return e[k]; }
15
+ });
16
+ }
17
+ });
18
+ }
19
+ n.default = e;
20
+ return Object.freeze(n);
21
+ }
22
+
23
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
24
+
25
+ // src/hooks/useDismiss.ts
26
+ function useDismiss({
27
+ open,
28
+ onDismiss,
29
+ refs,
30
+ closeOnEscape = true,
31
+ closeOnOutsideClick = true,
32
+ returnFocusRef
33
+ }) {
34
+ const onDismissRef = React__namespace.useRef(onDismiss);
35
+ onDismissRef.current = onDismiss;
36
+ const refsRef = React__namespace.useRef(refs);
37
+ refsRef.current = refs;
38
+ React__namespace.useEffect(() => {
39
+ if (!open) return;
40
+ const onPointer = (e) => {
41
+ if (!closeOnOutsideClick) return;
42
+ const target = e.target;
43
+ if (refsRef.current.some((r) => r.current?.contains(target))) return;
44
+ onDismissRef.current();
45
+ };
46
+ const onKey = (e) => {
47
+ if (closeOnEscape && e.key === "Escape") onDismissRef.current();
48
+ };
49
+ document.addEventListener("mousedown", onPointer);
50
+ document.addEventListener("keydown", onKey);
51
+ return () => {
52
+ document.removeEventListener("mousedown", onPointer);
53
+ document.removeEventListener("keydown", onKey);
54
+ };
55
+ }, [open, closeOnEscape, closeOnOutsideClick]);
56
+ const wasOpen = React__namespace.useRef(false);
57
+ React__namespace.useEffect(() => {
58
+ if (wasOpen.current && !open) {
59
+ returnFocusRef?.current?.focus();
60
+ }
61
+ wasOpen.current = open;
62
+ }, [open, returnFocusRef]);
63
+ }
64
+
65
+ exports.useDismiss = useDismiss;
66
+ //# sourceMappingURL=chunk-XMLBKK7X.js.map
67
+ //# sourceMappingURL=chunk-XMLBKK7X.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/useDismiss.ts"],"names":["React"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAqBO,SAAS,UAAA,CAAW;AAAA,EACzB,IAAA;AAAA,EACA,SAAA;AAAA,EACA,IAAA;AAAA,EACA,aAAA,GAAgB,IAAA;AAAA,EAChB,mBAAA,GAAsB,IAAA;AAAA,EACtB;AACF,CAAA,EAA4B;AAC1B,EAAA,MAAM,YAAA,GAAqBA,wBAAO,SAAS,CAAA;AAC3C,EAAA,YAAA,CAAa,OAAA,GAAU,SAAA;AACvB,EAAA,MAAM,OAAA,GAAgBA,wBAAO,IAAI,CAAA;AACjC,EAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAElB,EAAMA,2BAAU,MAAM;AACpB,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,SAAA,GAAY,CAAC,CAAA,KAAwB;AACzC,MAAA,IAAI,CAAC,mBAAA,EAAqB;AAC1B,MAAA,MAAM,SAAS,CAAA,CAAE,MAAA;AACjB,MAAA,IAAI,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,EAAE,OAAA,EAAS,QAAA,CAAS,MAAM,CAAC,CAAA,EAAG;AAC9D,MAAA,YAAA,CAAa,OAAA,EAAQ;AAAA,IACvB,CAAA;AACA,IAAA,MAAM,KAAA,GAAQ,CAAC,CAAA,KAA2B;AACxC,MAAA,IAAI,aAAA,IAAiB,CAAA,CAAE,GAAA,KAAQ,QAAA,eAAuB,OAAA,EAAQ;AAAA,IAChE,CAAA;AACA,IAAA,QAAA,CAAS,gBAAA,CAAiB,aAAa,SAAS,CAAA;AAChD,IAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,KAAK,CAAA;AAC1C,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,mBAAA,CAAoB,aAAa,SAAS,CAAA;AACnD,MAAA,QAAA,CAAS,mBAAA,CAAoB,WAAW,KAAK,CAAA;AAAA,IAC/C,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,IAAA,EAAM,aAAA,EAAe,mBAAmB,CAAC,CAAA;AAE7C,EAAA,MAAM,OAAA,GAAgBA,wBAAO,KAAK,CAAA;AAClC,EAAMA,2BAAU,MAAM;AACpB,IAAA,IAAI,OAAA,CAAQ,OAAA,IAAW,CAAC,IAAA,EAAM;AAC5B,MAAA,cAAA,EAAgB,SAAS,KAAA,EAAM;AAAA,IACjC;AACA,IAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAAA,EACpB,CAAA,EAAG,CAAC,IAAA,EAAM,cAAc,CAAC,CAAA;AAC3B","file":"chunk-XMLBKK7X.js","sourcesContent":["import * as React from 'react';\n\nexport interface UseDismissOptions {\n open: boolean;\n onDismiss: () => void;\n /** Refs whose subtree should NOT count as \"outside\" (trigger + panel). */\n refs: Array<React.RefObject<HTMLElement | null>>;\n closeOnEscape?: boolean;\n closeOnOutsideClick?: boolean;\n /** Focus returns here when the panel closes (usually the trigger). */\n returnFocusRef?: React.RefObject<HTMLElement | null>;\n}\n\n/**\n * Shared dismiss behaviour for floating panels: closes on outside\n * pointer-down and on Escape, and restores focus to the trigger when the\n * panel closes (focus hygiene for keyboard/AT users).\n *\n * `onDismiss` and `refs` are read through refs internally, so callers\n * don't need to memoize them to avoid re-subscribing listeners.\n */\nexport function useDismiss({\n open,\n onDismiss,\n refs,\n closeOnEscape = true,\n closeOnOutsideClick = true,\n returnFocusRef,\n}: UseDismissOptions): void {\n const onDismissRef = React.useRef(onDismiss);\n onDismissRef.current = onDismiss;\n const refsRef = React.useRef(refs);\n refsRef.current = refs;\n\n React.useEffect(() => {\n if (!open) return;\n const onPointer = (e: MouseEvent): void => {\n if (!closeOnOutsideClick) return;\n const target = e.target as Node;\n if (refsRef.current.some((r) => r.current?.contains(target))) return;\n onDismissRef.current();\n };\n const onKey = (e: KeyboardEvent): void => {\n if (closeOnEscape && e.key === 'Escape') onDismissRef.current();\n };\n document.addEventListener('mousedown', onPointer);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onPointer);\n document.removeEventListener('keydown', onKey);\n };\n }, [open, closeOnEscape, closeOnOutsideClick]);\n\n const wasOpen = React.useRef(false);\n React.useEffect(() => {\n if (wasOpen.current && !open) {\n returnFocusRef?.current?.focus();\n }\n wasOpen.current = open;\n }, [open, returnFocusRef]);\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import * as React from 'react';
2
+
3
+ // src/hooks/useDelayedUnmount.ts
4
+ function useDelayedUnmount(open, durationMs) {
5
+ const [mounted, setMounted] = React.useState(open);
6
+ const [closing, setClosing] = React.useState(false);
7
+ React.useEffect(() => {
8
+ if (open) {
9
+ setMounted(true);
10
+ setClosing(false);
11
+ return;
12
+ }
13
+ if (!mounted) return;
14
+ setClosing(true);
15
+ const handle = setTimeout(() => {
16
+ setMounted(false);
17
+ setClosing(false);
18
+ }, durationMs);
19
+ return () => clearTimeout(handle);
20
+ }, [open, durationMs, mounted]);
21
+ return { mounted, closing };
22
+ }
23
+
24
+ export { useDelayedUnmount };
25
+ //# sourceMappingURL=chunk-XXUSZD5I.mjs.map
26
+ //# sourceMappingURL=chunk-XXUSZD5I.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/useDelayedUnmount.ts"],"names":[],"mappings":";;;AAkBO,SAAS,iBAAA,CAAkB,MAAe,UAAA,EAAoB;AACnE,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAU,eAAS,IAAI,CAAA;AACjD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAU,eAAS,KAAK,CAAA;AAElD,EAAM,gBAAU,MAAM;AACpB,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,UAAA,CAAW,KAAK,CAAA;AAChB,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,MAAM,MAAA,GAAS,WAAW,MAAM;AAC9B,MAAA,UAAA,CAAW,KAAK,CAAA;AAChB,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA,IAClB,GAAG,UAAU,CAAA;AACb,IAAA,OAAO,MAAM,aAAa,MAAM,CAAA;AAAA,EAClC,CAAA,EAAG,CAAC,IAAA,EAAM,UAAA,EAAY,OAAO,CAAC,CAAA;AAE9B,EAAA,OAAO,EAAE,SAAS,OAAA,EAAQ;AAC5B","file":"chunk-XXUSZD5I.mjs","sourcesContent":["import * as React from 'react';\n\n/**\n * Delays unmounting of a component so an exit animation can play.\n *\n * When `open` flips to false, the hook keeps `mounted` true for `durationMs`\n * (giving CSS time to play `is-closing` keyframes) and then flips it to\n * false. The `closing` flag toggles during that window so the consumer can\n * apply a class like `is-closing` for the CSS animation.\n *\n * Usage:\n *\n * ```tsx\n * const { mounted, closing } = useDelayedUnmount(open, 200);\n * if (!mounted) return null;\n * return <div className={cx('modal', closing && 'is-closing')} />\n * ```\n */\nexport function useDelayedUnmount(open: boolean, durationMs: number) {\n const [mounted, setMounted] = React.useState(open);\n const [closing, setClosing] = React.useState(false);\n\n React.useEffect(() => {\n if (open) {\n setMounted(true);\n setClosing(false);\n return;\n }\n if (!mounted) return;\n setClosing(true);\n const handle = setTimeout(() => {\n setMounted(false);\n setClosing(false);\n }, durationMs);\n return () => clearTimeout(handle);\n }, [open, durationMs, mounted]);\n\n return { mounted, closing };\n}\n"]}
@@ -1,5 +1,8 @@
1
1
  'use strict';
2
2
 
3
+ var chunkXMLBKK7X_js = require('./chunk-XMLBKK7X.js');
4
+ var chunkDPMUWQHL_js = require('./chunk-DPMUWQHL.js');
5
+ var chunkGLYGO7WX_js = require('./chunk-GLYGO7WX.js');
3
6
  var chunkPASF6T4H_js = require('./chunk-PASF6T4H.js');
4
7
  var React = require('react');
5
8
  var jsxRuntime = require('react/jsx-runtime');
@@ -25,38 +28,25 @@ function _interopNamespace(e) {
25
28
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
26
29
 
27
30
  function ContextMenu({ items, children, className, menuClassName, ariaLabel = "Men\xFA contextual" }) {
28
- const [pos, setPos] = React__namespace.useState(null);
31
+ const [point, setPoint] = React__namespace.useState(null);
29
32
  const menuRef = React__namespace.useRef(null);
30
- const close = () => setPos(null);
33
+ const anchorRef = React__namespace.useRef(null);
34
+ const open = point !== null;
35
+ const close = () => setPoint(null);
31
36
  const onContextMenu = (e) => {
32
37
  e.preventDefault();
33
- setPos({ x: e.clientX, y: e.clientY });
38
+ const x = e.clientX;
39
+ const y = e.clientY;
40
+ anchorRef.current = { getBoundingClientRect: () => new DOMRect(x, y, 0, 0) };
41
+ setPoint({ x, y });
34
42
  };
35
- React__namespace.useEffect(() => {
36
- if (!pos) return;
37
- const onClick = (e) => {
38
- if (menuRef.current?.contains(e.target)) return;
39
- close();
40
- };
41
- const onKey = (e) => {
42
- if (e.key === "Escape") close();
43
- };
44
- document.addEventListener("mousedown", onClick);
45
- document.addEventListener("keydown", onKey);
46
- return () => {
47
- document.removeEventListener("mousedown", onClick);
48
- document.removeEventListener("keydown", onKey);
49
- };
50
- }, [pos]);
51
- React__namespace.useEffect(() => {
52
- if (!pos || !menuRef.current) return;
53
- const r = menuRef.current.getBoundingClientRect();
54
- let x = pos.x;
55
- let y = pos.y;
56
- if (x + r.width > window.innerWidth) x = window.innerWidth - r.width - 8;
57
- if (y + r.height > window.innerHeight) y = window.innerHeight - r.height - 8;
58
- if (x !== pos.x || y !== pos.y) setPos({ x, y });
59
- }, [pos]);
43
+ const pos = chunkDPMUWQHL_js.usePopoverPosition(anchorRef, menuRef, {
44
+ open,
45
+ side: "bottom",
46
+ align: "start",
47
+ offset: 2
48
+ });
49
+ chunkXMLBKK7X_js.useDismiss({ open, onDismiss: close, refs: [menuRef] });
60
50
  const handleSelect = (item) => {
61
51
  if (item.disabled || item.separator) return;
62
52
  item.onSelect?.();
@@ -64,14 +54,19 @@ function ContextMenu({ items, children, className, menuClassName, ariaLabel = "M
64
54
  };
65
55
  return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: chunkPASF6T4H_js.cx("context-menu", className), onContextMenu, children: [
66
56
  children,
67
- pos && /* @__PURE__ */ jsxRuntime.jsx(
57
+ open && /* @__PURE__ */ jsxRuntime.jsx(chunkGLYGO7WX_js.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
68
58
  "ul",
69
59
  {
70
60
  ref: menuRef,
71
61
  role: "menu",
72
62
  "aria-label": ariaLabel,
73
- className: chunkPASF6T4H_js.cx("context-menu__menu", menuClassName),
74
- style: { position: "fixed", top: pos.y, left: pos.x, zIndex: "var(--z-popover, 1300)" },
63
+ className: chunkPASF6T4H_js.cx("context-menu__menu", "is-floating", menuClassName),
64
+ style: {
65
+ position: "absolute",
66
+ top: pos.top,
67
+ left: pos.left,
68
+ visibility: pos.ready ? "visible" : "hidden"
69
+ },
75
70
  children: items.map(
76
71
  (item) => item.separator ? /* @__PURE__ */ jsxRuntime.jsx("li", { className: "context-menu__separator", role: "separator" }, item.id) : /* @__PURE__ */ jsxRuntime.jsx("li", { role: "none", children: /* @__PURE__ */ jsxRuntime.jsxs(
77
72
  "button",
@@ -89,10 +84,10 @@ function ContextMenu({ items, children, className, menuClassName, ariaLabel = "M
89
84
  ) }, item.id)
90
85
  )
91
86
  }
92
- )
87
+ ) })
93
88
  ] });
94
89
  }
95
90
 
96
91
  exports.ContextMenu = ContextMenu;
97
- //# sourceMappingURL=chunk-IIYQO6BL.js.map
98
- //# sourceMappingURL=chunk-IIYQO6BL.js.map
92
+ //# sourceMappingURL=chunk-YAORRBMU.js.map
93
+ //# sourceMappingURL=chunk-YAORRBMU.js.map