@seekbuddy/dsh-ui 0.0.0-stage → 0.2.0-beta.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 (195) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/LICENSE +22 -0
  3. package/README.md +175 -2
  4. package/README.zh.md +176 -0
  5. package/THIRD_PARTY_NOTICES.md +42 -0
  6. package/UPSTREAM.md +56 -0
  7. package/dist/blocks.js +1582 -0
  8. package/dist/chunks/chunk-23KOEBWJ.js +104 -0
  9. package/dist/chunks/chunk-3HCOU44R.js +697 -0
  10. package/dist/chunks/chunk-5JXG4BHW.js +31 -0
  11. package/dist/chunks/chunk-5XDVPALS.js +61 -0
  12. package/dist/chunks/chunk-AY44MQMD.js +3052 -0
  13. package/dist/chunks/chunk-B3EEK7A2.js +408 -0
  14. package/dist/chunks/chunk-CEBTQO6W.js +24 -0
  15. package/dist/chunks/chunk-CI73NXA5.js +202 -0
  16. package/dist/chunks/chunk-CTQPGUZP.js +22 -0
  17. package/dist/chunks/chunk-F352IICS.js +57 -0
  18. package/dist/chunks/chunk-IOBKTEKP.js +144 -0
  19. package/dist/chunks/chunk-KETGFAOH.js +66 -0
  20. package/dist/chunks/chunk-LA3QDZYN.js +2777 -0
  21. package/dist/chunks/chunk-NE62SYOZ.js +89 -0
  22. package/dist/chunks/chunk-OQPH36OI.js +754 -0
  23. package/dist/chunks/chunk-QJKAQ6PO.js +155 -0
  24. package/dist/chunks/chunk-R6AUJQ3G.js +129 -0
  25. package/dist/chunks/chunk-RNVSCTW7.js +24 -0
  26. package/dist/chunks/chunk-RZOP2PFC.js +152 -0
  27. package/dist/chunks/chunk-TQU54HSM.js +112 -0
  28. package/dist/chunks/chunk-TUK6UGXM.js +36 -0
  29. package/dist/chunks/chunk-TZ7HRE6D.js +328 -0
  30. package/dist/chunks/chunk-VIH56PDF.js +57 -0
  31. package/dist/chunks/chunk-WUL523OW.js +27 -0
  32. package/dist/chunks/chunk-XX6MSZLS.js +261 -0
  33. package/dist/chunks/chunk-ZA47FP7C.js +7 -0
  34. package/dist/chunks/chunk-ZZNL5PWF.js +170 -0
  35. package/dist/icons.js +803 -0
  36. package/dist/index.js +1182 -0
  37. package/dist/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  38. package/dist/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  39. package/dist/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  40. package/dist/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  41. package/dist/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  42. package/dist/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
  43. package/dist/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  44. package/dist/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
  45. package/dist/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
  46. package/dist/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  47. package/dist/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
  48. package/dist/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  49. package/dist/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  50. package/dist/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  51. package/dist/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
  52. package/dist/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  53. package/dist/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  54. package/dist/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  55. package/dist/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  56. package/dist/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  57. package/dist/katex.css +1 -0
  58. package/dist/katex.css.d.ts +2 -0
  59. package/dist/markdown.js +148 -0
  60. package/dist/meta.json +6876 -0
  61. package/dist/root-inputs.json +67 -0
  62. package/dist/seekbuddy-card.js +7 -0
  63. package/dist/seekbuddy-empty.js +8 -0
  64. package/dist/seekbuddy-internal/DangerButton.js +7 -0
  65. package/dist/seekbuddy-internal/Mark.js +7 -0
  66. package/dist/seekbuddy-internal/Message.js +10 -0
  67. package/dist/seekbuddy-internal/Pagination.js +9 -0
  68. package/dist/seekbuddy-internal/StatusBadge.js +7 -0
  69. package/dist/seekbuddy-internal/SubtleButton.js +7 -0
  70. package/dist/seekbuddy-internal/Switch.js +7 -0
  71. package/dist/seekbuddy-internal/Upload.js +7 -0
  72. package/dist/seekbuddy-internal/date/Calendar.js +8 -0
  73. package/dist/seekbuddy-internal/date/DatePicker.js +9 -0
  74. package/dist/seekbuddy-internal/date/DateRangePicker.js +9 -0
  75. package/dist/seekbuddy-internal/date/TimePicker.js +8 -0
  76. package/dist/seekbuddy-internal/date/fields.js +16 -0
  77. package/dist/seekbuddy-internal/qr/QrCode.js +7 -0
  78. package/dist/seekbuddy-spinner.js +7 -0
  79. package/dist/seekbuddy-tabs.js +7 -0
  80. package/dist/seekbuddy-timeline.js +8 -0
  81. package/dist/seekbuddy.js +89 -0
  82. package/dist/theme-bootstrap.js +13 -0
  83. package/dist/theme.js +37 -0
  84. package/dist/tokens.css +934 -0
  85. package/dist/tokens.css.d.ts +2 -0
  86. package/dist/types/Button.d.ts +18 -0
  87. package/dist/types/Checkbox.d.ts +19 -0
  88. package/dist/types/CodeFileIcon.d.ts +11 -0
  89. package/dist/types/CodeToolbar.d.ts +29 -0
  90. package/dist/types/ConfigField.d.ts +32 -0
  91. package/dist/types/ConnectionIndicator.d.ts +25 -0
  92. package/dist/types/DiffBlock.d.ts +51 -0
  93. package/dist/types/DisclosureRow.d.ts +35 -0
  94. package/dist/types/FileTypeIcon.d.ts +42 -0
  95. package/dist/types/FoldToggle.d.ts +19 -0
  96. package/dist/types/HoverCard.d.ts +36 -0
  97. package/dist/types/ImageLightbox.d.ts +26 -0
  98. package/dist/types/ImagePreview.d.ts +11 -0
  99. package/dist/types/Input.d.ts +11 -0
  100. package/dist/types/JsonTree.d.ts +58 -0
  101. package/dist/types/LinkIcon.d.ts +33 -0
  102. package/dist/types/Menu.d.ts +142 -0
  103. package/dist/types/MenuGroup.d.ts +21 -0
  104. package/dist/types/MenuSurface.d.ts +15 -0
  105. package/dist/types/Modal.d.ts +43 -0
  106. package/dist/types/PermissionIcon.d.ts +38 -0
  107. package/dist/types/Pill.d.ts +12 -0
  108. package/dist/types/ReadBlock.d.ts +47 -0
  109. package/dist/types/ReferenceIcon.d.ts +20 -0
  110. package/dist/types/RiskConfirmation.d.ts +19 -0
  111. package/dist/types/SearchBlock.d.ts +71 -0
  112. package/dist/types/SegmentedControl.d.ts +34 -0
  113. package/dist/types/SegmentedTabs.d.ts +25 -0
  114. package/dist/types/ShortcutKeys.d.ts +10 -0
  115. package/dist/types/SiteGlyph.d.ts +24 -0
  116. package/dist/types/StateDot.d.ts +19 -0
  117. package/dist/types/Switch.d.ts +19 -0
  118. package/dist/types/Tag.d.ts +31 -0
  119. package/dist/types/TerminalBlock.d.ts +77 -0
  120. package/dist/types/TextShimmer.d.ts +22 -0
  121. package/dist/types/Toast.d.ts +48 -0
  122. package/dist/types/Tooltip.d.ts +63 -0
  123. package/dist/types/WebBlock.d.ts +60 -0
  124. package/dist/types/ansi.d.ts +16 -0
  125. package/dist/types/blocks.d.ts +19 -0
  126. package/dist/types/clipboard.d.ts +8 -0
  127. package/dist/types/code-file-icon-artwork.d.ts +53 -0
  128. package/dist/types/code-file-types.d.ts +29 -0
  129. package/dist/types/code-highlighting.d.ts +11 -0
  130. package/dist/types/css-modules.d.ts +6 -0
  131. package/dist/types/darwin-desktop.d.ts +8 -0
  132. package/dist/types/file-size.d.ts +7 -0
  133. package/dist/types/focus.d.ts +8 -0
  134. package/dist/types/guide-artwork.d.ts +14 -0
  135. package/dist/types/head-tail-cap.d.ts +22 -0
  136. package/dist/types/icons/index.d.ts +384 -0
  137. package/dist/types/icons/props.d.ts +8 -0
  138. package/dist/types/icons/shared-artwork.d.ts +42 -0
  139. package/dist/types/icons.d.ts +6 -0
  140. package/dist/types/index.d.ts +53 -0
  141. package/dist/types/input-modality.d.ts +18 -0
  142. package/dist/types/keyboard-composition.d.ts +10 -0
  143. package/dist/types/markdown/CodeBlock.d.ts +34 -0
  144. package/dist/types/markdown/JsonBlock.d.ts +7 -0
  145. package/dist/types/markdown/MarkdownDelegate.d.ts +45 -0
  146. package/dist/types/markdown/MarkdownText.d.ts +47 -0
  147. package/dist/types/markdown/cjkFriendlyStrong.d.ts +8 -0
  148. package/dist/types/markdown/file-link.d.ts +12 -0
  149. package/dist/types/markdown/highlight.d.ts +147 -0
  150. package/dist/types/markdown/incremental.d.ts +79 -0
  151. package/dist/types/markdown/katex.d.ts +18 -0
  152. package/dist/types/markdown/local-image-syntax.d.ts +9 -0
  153. package/dist/types/markdown/mathCompatibility.d.ts +10 -0
  154. package/dist/types/markdown/parse.d.ts +24 -0
  155. package/dist/types/markdown/plain-text.d.ts +21 -0
  156. package/dist/types/markdown/render.d.ts +140 -0
  157. package/dist/types/markdown/useViewportHighlighting.d.ts +10 -0
  158. package/dist/types/markdown.d.ts +9 -0
  159. package/dist/types/overlay-top-margin.d.ts +7 -0
  160. package/dist/types/plugin-artwork.d.ts +16 -0
  161. package/dist/types/pointer-grace.d.ts +21 -0
  162. package/dist/types/rank-by-name.d.ts +21 -0
  163. package/dist/types/relative-time.d.ts +22 -0
  164. package/dist/types/seekbuddy/Card.d.ts +28 -0
  165. package/dist/types/seekbuddy/DangerButton.d.ts +31 -0
  166. package/dist/types/seekbuddy/Empty.d.ts +34 -0
  167. package/dist/types/seekbuddy/Mark.d.ts +27 -0
  168. package/dist/types/seekbuddy/Message.d.ts +52 -0
  169. package/dist/types/seekbuddy/Pagination.d.ts +66 -0
  170. package/dist/types/seekbuddy/Spinner.d.ts +20 -0
  171. package/dist/types/seekbuddy/StatusBadge.d.ts +33 -0
  172. package/dist/types/seekbuddy/SubtleButton.d.ts +30 -0
  173. package/dist/types/seekbuddy/Switch.d.ts +36 -0
  174. package/dist/types/seekbuddy/Tabs.d.ts +49 -0
  175. package/dist/types/seekbuddy/Timeline.d.ts +42 -0
  176. package/dist/types/seekbuddy/Upload.d.ts +101 -0
  177. package/dist/types/seekbuddy/date/Calendar.d.ts +94 -0
  178. package/dist/types/seekbuddy/date/DatePicker.d.ts +29 -0
  179. package/dist/types/seekbuddy/date/DateRangePicker.d.ts +41 -0
  180. package/dist/types/seekbuddy/date/TimePicker.d.ts +35 -0
  181. package/dist/types/seekbuddy/date/date.d.ts +79 -0
  182. package/dist/types/seekbuddy/date/fields.d.ts +45 -0
  183. package/dist/types/seekbuddy/index.d.ts +49 -0
  184. package/dist/types/seekbuddy/qr/QrCode.d.ts +37 -0
  185. package/dist/types/seekbuddy/qr/qr.d.ts +38 -0
  186. package/dist/types/theme-bootstrap.d.ts +3 -0
  187. package/dist/types/theme-core.d.ts +14 -0
  188. package/dist/types/theme.d.ts +4 -0
  189. package/dist/types/use-copy-feedback.d.ts +13 -0
  190. package/dist/types/useAnchoredMaxHeight.d.ts +13 -0
  191. package/dist/types/useAnchoredPosition.d.ts +35 -0
  192. package/dist/types/useDismissOnOutsidePointer.d.ts +10 -0
  193. package/dist/types/useModalLayer.d.ts +26 -0
  194. package/dist/types/user-text.d.ts +36 -0
  195. package/package.json +151 -4
@@ -0,0 +1,697 @@
1
+ import {
2
+ ShortcutKeys,
3
+ overlayTopMargin,
4
+ usePointerGrace
5
+ } from "./chunk-OQPH36OI.js";
6
+ import {
7
+ IconCheckOutlineRegular
8
+ } from "./chunk-LA3QDZYN.js";
9
+
10
+ // src/StateDot.tsx
11
+ import clsx from "clsx";
12
+
13
+ // .build/css/StateDot.module.mjs
14
+ var id = "@seekbuddy/dsh-ui/StateDot.module.css";
15
+ if (typeof document !== "undefined" && !document.querySelector('style[data-dsh-ui-primitives="' + id + '"]')) {
16
+ const element = document.createElement("style");
17
+ element.setAttribute("data-dsh-ui-primitives", id);
18
+ element.textContent = '.vSoTLq_dot{flex:none;display:inline-block;position:relative}.vSoTLq_dot:after{content:"";corner-shape:round;background:currentColor;border-radius:50%;position:absolute;inset:20%}.vSoTLq_dot[data-state=done]{color:var(--dsw-alias-state-success-primary)}.vSoTLq_dot[data-state=warning]{color:var(--dsw-alias-state-warn-primary)}.vSoTLq_dot[data-state=error]{color:var(--dsw-alias-state-error-primary)}.vSoTLq_dot[data-state=idle]{color:var(--dsw-alias-state-idle-primary)}.vSoTLq_spinner{color:var(--dsw-alias-label-tertiary);flex:none}.vSoTLq_spinnerMotion{transform-origin:50%;animation:1.5s linear infinite vSoTLq_dsh-state-dot-spin}.vSoTLq_spinnerTrack,.vSoTLq_spinnerArc{fill:none;stroke:currentColor;stroke-width:2px;stroke-linecap:round}.vSoTLq_spinnerTrack{opacity:.25}.vSoTLq_spinnerArc{stroke-dasharray:12 150;animation:1.5s ease-in-out infinite vSoTLq_dsh-state-dot-dash}@keyframes vSoTLq_dsh-state-dot-spin{to{transform:rotate(360deg)}}@keyframes vSoTLq_dsh-state-dot-dash{0%{stroke-dasharray:12 150;stroke-dashoffset:0}50%{stroke-dasharray:24 150;stroke-dashoffset:-6px}to{stroke-dasharray:12 150;stroke-dashoffset:0}}@media (prefers-reduced-motion:reduce){.vSoTLq_spinnerMotion,.vSoTLq_spinnerArc{animation:none}.vSoTLq_spinnerArc{stroke-dasharray:18 150;stroke-dashoffset:-3px}}.vSoTLq_step{box-sizing:border-box;corner-shape:round;border:1.5px solid var(--dsw-alias-label-tertiary);color:var(--dsw-alias-label-primary-foreground);border-radius:50%;flex:none;justify-content:center;align-items:center;display:inline-flex}.vSoTLq_step[data-state=done]{border-color:var(--dsw-alias-state-success-primary);background:var(--dsw-alias-state-success-primary)}.vSoTLq_step[data-state=error]{border-color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-state-error-primary)}.vSoTLq_step[data-state=warning]{border-color:var(--dsw-alias-state-warn-primary)}';
19
+ document.head.appendChild(element);
20
+ }
21
+ var StateDot_module_default = { "dot": "vSoTLq_dot", "dsh-state-dot-dash": "vSoTLq_dsh-state-dot-dash", "spinner": "vSoTLq_spinner", "step": "vSoTLq_step", "spinnerTrack": "vSoTLq_spinnerTrack", "spinnerArc": "vSoTLq_spinnerArc", "dsh-state-dot-spin": "vSoTLq_dsh-state-dot-spin", "spinnerMotion": "vSoTLq_spinnerMotion" };
22
+
23
+ // src/StateDot.tsx
24
+ import { jsx, jsxs } from "react/jsx-runtime";
25
+ function syncSpinner(element) {
26
+ if (element === null) return;
27
+ const spinner = element;
28
+ for (const animation of spinner.getAnimations?.({ subtree: true }) ?? []) animation.startTime = 0;
29
+ }
30
+ function StateDot({
31
+ state,
32
+ size,
33
+ className,
34
+ appearance = "dot"
35
+ }) {
36
+ const edge = size ?? (state === "ongoing" ? 14 : 10);
37
+ if (state === "ongoing") {
38
+ return /* @__PURE__ */ jsx(
39
+ "svg",
40
+ {
41
+ ref: syncSpinner,
42
+ className: clsx(StateDot_module_default.spinner, className),
43
+ "data-state": "ongoing",
44
+ width: edge,
45
+ height: edge,
46
+ viewBox: "0 0 24 24",
47
+ "aria-hidden": "true",
48
+ children: /* @__PURE__ */ jsxs("g", { className: StateDot_module_default.spinnerMotion, children: [
49
+ /* @__PURE__ */ jsx("circle", { className: StateDot_module_default.spinnerTrack, cx: "12", cy: "12", r: "9.5" }),
50
+ /* @__PURE__ */ jsx("circle", { className: StateDot_module_default.spinnerArc, cx: "12", cy: "12", r: "9.5" })
51
+ ] })
52
+ }
53
+ );
54
+ }
55
+ return /* @__PURE__ */ jsx(
56
+ "span",
57
+ {
58
+ className: clsx(appearance === "step" ? StateDot_module_default.step : StateDot_module_default.dot, className),
59
+ "data-state": state,
60
+ style: { width: edge, height: edge },
61
+ "aria-hidden": "true",
62
+ children: appearance === "step" && state === "done" && /* @__PURE__ */ jsx(IconCheckOutlineRegular, { size: edge - 2 })
63
+ }
64
+ );
65
+ }
66
+
67
+ // src/Pill.tsx
68
+ import clsx2 from "clsx";
69
+
70
+ // .build/css/Pill.module.mjs
71
+ var id2 = "@seekbuddy/dsh-ui/Pill.module.css";
72
+ if (typeof document !== "undefined" && !document.querySelector('style[data-dsh-ui-primitives="' + id2 + '"]')) {
73
+ const element = document.createElement("style");
74
+ element.setAttribute("data-dsh-ui-primitives", id2);
75
+ element.textContent = ".c2tx2W_pill{corner-shape:round;height:24px;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2);border:none;border-radius:999px;align-items:center;gap:4px;padding:0 8px;font-size:12px;line-height:18px;display:inline-flex}.c2tx2W_interactive{cursor:pointer}.c2tx2W_interactive:hover{background:var(--dsw-alias-interactive-bg-hover)}.c2tx2W_active{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-button-ghost-active-fill);box-shadow:inset 0 0 0 1px var(--dsw-alias-button-ghost-active-border)}";
76
+ document.head.appendChild(element);
77
+ }
78
+ var Pill_module_default = { "pill": "c2tx2W_pill", "interactive": "c2tx2W_interactive", "active": "c2tx2W_active" };
79
+
80
+ // src/Pill.tsx
81
+ import { jsx as jsx2 } from "react/jsx-runtime";
82
+ function Pill({
83
+ active = false,
84
+ className,
85
+ children,
86
+ onClick,
87
+ ...rest
88
+ }) {
89
+ if (!onClick) {
90
+ return /* @__PURE__ */ jsx2("span", { className: clsx2(Pill_module_default.pill, active && Pill_module_default.active, className), children });
91
+ }
92
+ return /* @__PURE__ */ jsx2(
93
+ "button",
94
+ {
95
+ type: "button",
96
+ className: clsx2(Pill_module_default.pill, Pill_module_default.interactive, active && Pill_module_default.active, className),
97
+ onClick,
98
+ ...rest,
99
+ children
100
+ }
101
+ );
102
+ }
103
+
104
+ // src/keyboard-composition.ts
105
+ function observeComposition(document2) {
106
+ let composing = false;
107
+ let ended = false;
108
+ const start = () => {
109
+ composing = true;
110
+ };
111
+ const end = () => {
112
+ composing = false;
113
+ ended = true;
114
+ };
115
+ const release = () => {
116
+ ended = false;
117
+ };
118
+ const blur = () => {
119
+ composing = false;
120
+ ended = false;
121
+ };
122
+ document2.addEventListener("compositionstart", start, true);
123
+ document2.addEventListener("compositionend", end, true);
124
+ document2.addEventListener("keyup", release, true);
125
+ document2.defaultView?.addEventListener("blur", blur);
126
+ return {
127
+ guards: (event) => {
128
+ const guarded = composing || ended || event.isComposing || event.keyCode === 229;
129
+ ended = false;
130
+ return guarded;
131
+ },
132
+ dispose: () => {
133
+ document2.removeEventListener("compositionstart", start, true);
134
+ document2.removeEventListener("compositionend", end, true);
135
+ document2.removeEventListener("keyup", release, true);
136
+ document2.defaultView?.removeEventListener("blur", blur);
137
+ }
138
+ };
139
+ }
140
+
141
+ // src/focus.ts
142
+ var releases = /* @__PURE__ */ new WeakMap();
143
+ var navigationKeys = /* @__PURE__ */ new Set(["Tab", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End"]);
144
+ function focusWithoutRing(element, options) {
145
+ releases.get(element)?.();
146
+ const release = () => {
147
+ element.removeAttribute("data-dsh-automatic-focus");
148
+ element.removeEventListener("blur", release);
149
+ element.removeEventListener("keydown", navigate, true);
150
+ releases.delete(element);
151
+ };
152
+ const navigate = (event) => {
153
+ if (!event.isComposing && !event.ctrlKey && !event.altKey && !event.metaKey && navigationKeys.has(event.key))
154
+ release();
155
+ };
156
+ releases.set(element, release);
157
+ element.setAttribute("data-dsh-automatic-focus", "");
158
+ element.addEventListener("blur", release);
159
+ element.addEventListener("keydown", navigate, true);
160
+ element.focus(options);
161
+ if (!element.matches(":focus")) release();
162
+ }
163
+
164
+ // src/useModalLayer.ts
165
+ import { useLayoutEffect, useRef } from "react";
166
+ var modalSelector = '[role="dialog"][aria-modal="true"], [role="menu"]';
167
+ var layers = /* @__PURE__ */ new WeakMap();
168
+ function closeTopModal(document2) {
169
+ const top = layers.get(document2)?.at(-1);
170
+ if (top === void 0) return;
171
+ const foreground = [...document2.querySelectorAll(modalSelector)].at(-1);
172
+ if (foreground === top.element) top.close();
173
+ }
174
+ function isBehindModal(anchor) {
175
+ if (anchor === null) return false;
176
+ const top = layers.get(anchor.ownerDocument)?.at(-1);
177
+ return top !== void 0 && !top.element.contains(anchor);
178
+ }
179
+ var focusable = 'button:not(:disabled), input:not(:disabled), textarea:not(:disabled), select:not(:disabled), a[href], [tabindex="0"]';
180
+ function useModalLayer(dialog, open, onClose) {
181
+ const close = useRef(onClose);
182
+ close.current = onClose;
183
+ useLayoutEffect(() => {
184
+ const element = dialog.current;
185
+ if (!open || element === null) return;
186
+ const document2 = element.ownerDocument;
187
+ const composition = observeComposition(document2);
188
+ const previous = document2.activeElement;
189
+ const stack = layers.get(document2) ?? [];
190
+ layers.set(document2, stack);
191
+ const layer = {
192
+ element,
193
+ close: () => {
194
+ close.current();
195
+ }
196
+ };
197
+ stack.push(layer);
198
+ const initial = element.querySelector("[data-modal-autofocus]") ?? element.querySelector(focusable) ?? element;
199
+ if (!element.contains(document2.activeElement)) focusWithoutRing(initial);
200
+ const keydown = (event) => {
201
+ const composing = composition.guards(event);
202
+ if (stack.at(-1) !== layer || event.defaultPrevented || composing || event.ctrlKey || event.altKey || event.metaKey)
203
+ return;
204
+ if (event.key === "Escape" && !event.shiftKey) {
205
+ event.preventDefault();
206
+ if (!event.repeat) close.current();
207
+ }
208
+ if (event.key !== "Tab") return;
209
+ if (document2.activeElement?.closest('[role="menu"]')) return;
210
+ const items = [...element.querySelectorAll(focusable)].filter(
211
+ (item) => !item.closest("[inert], [hidden]")
212
+ );
213
+ const first = items[0] ?? element;
214
+ const last = items.at(-1) ?? element;
215
+ const atEdge = event.shiftKey ? document2.activeElement === first : document2.activeElement === last;
216
+ if (document2.activeElement === element || !element.contains(document2.activeElement) || atEdge) {
217
+ event.preventDefault();
218
+ const target = event.shiftKey ? last : first;
219
+ target.focus();
220
+ }
221
+ };
222
+ document2.addEventListener("keydown", keydown);
223
+ return () => {
224
+ composition.dispose();
225
+ const wasTop = stack.at(-1) === layer;
226
+ stack.splice(stack.indexOf(layer), 1);
227
+ document2.removeEventListener("keydown", keydown);
228
+ if (stack.length === 0) layers.delete(document2);
229
+ if (wasTop) {
230
+ const target = previous instanceof HTMLElement && previous.isConnected ? previous : stack.at(-1)?.element;
231
+ if (target !== void 0) focusWithoutRing(target);
232
+ }
233
+ };
234
+ }, [dialog, open]);
235
+ }
236
+
237
+ // src/MenuSurface.tsx
238
+ import { forwardRef, useId, useLayoutEffect as useLayoutEffect2, useRef as useRef2 } from "react";
239
+ import { createPortal } from "react-dom";
240
+ import clsx3 from "clsx";
241
+
242
+ // .build/css/MenuSurface.module.mjs
243
+ var id3 = "@seekbuddy/dsh-ui/MenuSurface.module.css";
244
+ if (typeof document !== "undefined" && !document.querySelector('style[data-dsh-ui-primitives="' + id3 + '"]')) {
245
+ const element = document.createElement("style");
246
+ element.setAttribute("data-dsh-ui-primitives", id3);
247
+ element.textContent = "._J1jQq_surface,._J1jQq_backing{border-radius:var(--dsw-radius-lg)}._J1jQq_compact{border-radius:var(--dsw-radius-md)}:where(._J1jQq_surface){position:relative}._J1jQq_surface{anchor-name:var(--dsh-menu-anchor);isolation:isolate}._J1jQq_material{z-index:-1;border-radius:inherit;background:var(--dsw-menu-surface-fill);backdrop-filter:var(--dsw-menu-backdrop-filter);pointer-events:none;position:absolute;inset:0}._J1jQq_backing{display:none}html[data-platform=darwin] ._J1jQq_backing{position-anchor:var(--dsh-menu-anchor);top:anchor(top);left:anchor(left);width:anchor-size(width, 0px);height:anchor-size(height, 0px);z-index:-1;background:var(--dsw-alias-bg-base);pointer-events:none;display:block;position:fixed}";
248
+ document.head.appendChild(element);
249
+ }
250
+ var MenuSurface_module_default = { "compact": "_J1jQq_compact", "backing": "_J1jQq_backing", "surface": "_J1jQq_surface", "material": "_J1jQq_material" };
251
+
252
+ // src/MenuSurface.tsx
253
+ import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
254
+ var MenuSurface = forwardRef(function MenuSurface2({ compact = false, className, style, children, ...props }, ref) {
255
+ const id5 = useId();
256
+ const backingRef = useRef2(null);
257
+ useLayoutEffect2(() => {
258
+ document.body.appendChild(backingRef.current);
259
+ }, []);
260
+ const anchorStyle = {
261
+ "--dsh-menu-anchor": `--dsh-menu-${id5.replaceAll(":", "")}`
262
+ };
263
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
264
+ /* @__PURE__ */ jsxs2(
265
+ "div",
266
+ {
267
+ ...props,
268
+ ref,
269
+ "data-menu-material": "translucent",
270
+ className: clsx3(MenuSurface_module_default.surface, compact && MenuSurface_module_default.compact, className),
271
+ style: { ...style, ...anchorStyle },
272
+ children: [
273
+ /* @__PURE__ */ jsx3("div", { "aria-hidden": "true", className: MenuSurface_module_default.material }),
274
+ children
275
+ ]
276
+ }
277
+ ),
278
+ createPortal(
279
+ /* @__PURE__ */ jsx3(
280
+ "div",
281
+ {
282
+ ref: backingRef,
283
+ "aria-hidden": "true",
284
+ "data-menu-backing": "",
285
+ className: clsx3(MenuSurface_module_default.backing, compact && MenuSurface_module_default.compact),
286
+ style: { ...anchorStyle, visibility: style?.visibility }
287
+ }
288
+ ),
289
+ document.body
290
+ )
291
+ ] });
292
+ });
293
+
294
+ // src/Menu.tsx
295
+ import { useEffect, useLayoutEffect as useLayoutEffect3, useRef as useRef3, useState } from "react";
296
+ import { createPortal as createPortal2 } from "react-dom";
297
+ import clsx4 from "clsx";
298
+
299
+ // .build/css/Menu.module.mjs
300
+ var id4 = "@seekbuddy/dsh-ui/Menu.module.css";
301
+ if (typeof document !== "undefined" && !document.querySelector('style[data-dsh-ui-primitives="' + id4 + '"]')) {
302
+ const element = document.createElement("style");
303
+ element.setAttribute("data-dsh-ui-primitives", id4);
304
+ element.textContent = '.or0wJW_root{display:inline-flex;position:relative}.or0wJW_list,.or0wJW_submenu{box-sizing:border-box;--dsw-elevation-stroke-color:var(--dsw-alias-border-l1);box-shadow:var(--dsw-elevation-prominent);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border:0;flex-direction:column;gap:0;padding:4px;display:flex}.or0wJW_list{z-index:100;min-width:144px;max-width:360px;position:absolute;top:calc(100% + 4px);left:0}.or0wJW_portal{z-index:1100;position:fixed;top:auto;left:auto}.or0wJW_sideTop{top:auto;bottom:calc(100% + 4px)}.or0wJW_alignEnd{left:auto;right:0}.or0wJW_scrollable{max-height:calc(100vh - 12px - max(12px, var(--dsh-frame-overlay-top,12px)))}.or0wJW_viewport{flex-direction:column;min-height:0;display:flex}.or0wJW_scrollable .or0wJW_viewport{overflow-y:auto}.or0wJW_footer{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;flex:none;margin-top:3px;padding-top:3px;display:flex}.or0wJW_itemWrap{position:relative}.or0wJW_item{border-radius:var(--dsw-radius-md);cursor:pointer;width:100%;min-height:34px;color:var(--dsw-alias-label-primary);text-align:left;background:0 0;border:none;align-items:center;gap:6px;padding:6px 8px;font-size:13px;line-height:20px;display:flex}.or0wJW_item:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.or0wJW_item:focus-visible:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);outline:none}.or0wJW_denseList .or0wJW_item{min-height:30px;padding-block:4px}.or0wJW_denseList .or0wJW_label{padding-block:3px}.or0wJW_list.or0wJW_compactList,.or0wJW_submenu.or0wJW_compactList{min-width:156px;padding:4px}.or0wJW_compactList .or0wJW_item{border-radius:var(--dsw-radius-sm);gap:5px;min-height:24px;padding:2px 6px;font-size:11px;line-height:17px}.or0wJW_compactList .or0wJW_itemIcon{width:12px;height:12px}.or0wJW_compactList .or0wJW_separator{margin:2px}.or0wJW_compactList .or0wJW_label{padding:3px 6px;font-size:10px;line-height:15px}.or0wJW_item:disabled{opacity:.4;cursor:not-allowed}.or0wJW_itemIcon{width:14px;height:14px;color:var(--dsw-alias-menu-icon);flex:none;justify-content:center;align-items:center;display:inline-flex}.or0wJW_itemIcon svg,.or0wJW_check{width:14px;height:14px}.or0wJW_compactList .or0wJW_itemIcon svg,.or0wJW_compactList .or0wJW_check{width:12px;height:12px}.or0wJW_itemLabel{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.or0wJW_shortcut{flex:none;margin-inline-start:auto}.or0wJW_shortcut .or0wJW_shortcutKeys{color:var(--dsw-alias-label-caption);font-size:11px;line-height:16px}.or0wJW_check{color:var(--dsw-alias-label-primary);flex:none}.or0wJW_selected{background:0 0}.or0wJW_selectedFill{background:var(--dsw-alias-interactive-bg-hover)}.or0wJW_danger,.or0wJW_danger .or0wJW_itemIcon{color:var(--dsw-alias-state-error-primary)}.or0wJW_danger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger)}.or0wJW_danger:focus-visible:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);outline:none}.or0wJW_label{color:var(--dsw-alias-label-tertiary);padding:6px 8px;font-size:11px;line-height:15px}.or0wJW_separator{background:var(--dsw-alias-border-l2);height:.5px;margin:3px 2px}.or0wJW_separator+.or0wJW_separator,.or0wJW_separator+.or0wJW_itemWrap>.or0wJW_separator:first-child,.or0wJW_itemWrap:first-child>.or0wJW_separator:first-child{display:none}.or0wJW_submenu{z-index:101;min-width:163px;position:absolute;top:auto;bottom:-4px;left:calc(100% + 10px)}.or0wJW_submenu:before{content:"";width:10px;position:absolute;top:0;bottom:0;left:-10px}';
305
+ document.head.appendChild(element);
306
+ }
307
+ var Menu_module_default = { "list": "or0wJW_list", "submenu": "or0wJW_submenu", "viewport": "or0wJW_viewport", "footer": "or0wJW_footer", "shortcut": "or0wJW_shortcut", "selected": "or0wJW_selected", "scrollable": "or0wJW_scrollable", "itemLabel": "or0wJW_itemLabel", "shortcutKeys": "or0wJW_shortcutKeys", "item": "or0wJW_item", "compactList": "or0wJW_compactList", "itemIcon": "or0wJW_itemIcon", "alignEnd": "or0wJW_alignEnd", "check": "or0wJW_check", "portal": "or0wJW_portal", "sideTop": "or0wJW_sideTop", "label": "or0wJW_label", "separator": "or0wJW_separator", "root": "or0wJW_root", "denseList": "or0wJW_denseList", "selectedFill": "or0wJW_selectedFill", "itemWrap": "or0wJW_itemWrap", "danger": "or0wJW_danger" };
308
+
309
+ // src/Menu.tsx
310
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
311
+ function MenuItemButton({
312
+ children,
313
+ shortcut,
314
+ icon,
315
+ disabled = false,
316
+ danger = false,
317
+ separatorBefore = false,
318
+ onSelect
319
+ }) {
320
+ return /* @__PURE__ */ jsxs3("div", { className: Menu_module_default.itemWrap, children: [
321
+ separatorBefore && /* @__PURE__ */ jsx4("div", { className: Menu_module_default.separator, role: "separator" }),
322
+ /* @__PURE__ */ jsxs3(
323
+ "button",
324
+ {
325
+ type: "button",
326
+ role: "menuitem",
327
+ className: clsx4(Menu_module_default.item, danger && Menu_module_default.danger),
328
+ disabled,
329
+ "aria-keyshortcuts": shortcut?.aria,
330
+ onClick: onSelect,
331
+ children: [
332
+ icon !== void 0 && /* @__PURE__ */ jsx4("span", { className: Menu_module_default.itemIcon, children: icon }),
333
+ /* @__PURE__ */ jsx4("span", { className: Menu_module_default.itemLabel, children }),
334
+ shortcut !== void 0 && /* @__PURE__ */ jsx4("span", { "aria-hidden": "true", className: Menu_module_default.shortcut, children: /* @__PURE__ */ jsx4(ShortcutKeys, { keys: shortcut.keys, className: Menu_module_default.shortcutKeys }) })
335
+ ]
336
+ }
337
+ )
338
+ ] });
339
+ }
340
+ function isSeparator(entry) {
341
+ return "type" in entry && entry.type === "separator";
342
+ }
343
+ function isLabel(entry) {
344
+ return "type" in entry && entry.type === "label";
345
+ }
346
+ var MEASURE_STYLE = { visibility: "hidden", left: 0, top: 0 };
347
+ function Menu({
348
+ open,
349
+ anchor,
350
+ items = [],
351
+ children,
352
+ selectedId,
353
+ selectedIds,
354
+ onSelect,
355
+ onClose,
356
+ align = "start",
357
+ side = "bottom",
358
+ portal = false,
359
+ closeOnPointerLeave = false,
360
+ dense = false,
361
+ compact = false,
362
+ autoFocus = false,
363
+ selection = "check",
364
+ getAnchorRect,
365
+ footer,
366
+ className,
367
+ listClassName
368
+ }) {
369
+ const rootRef = useRef3(null);
370
+ const listRef = useRef3(null);
371
+ const walkIndex = useRef3(null);
372
+ const triggerRef = useRef3(null);
373
+ const selectingWithTab = useRef3(false);
374
+ const refocusAnchor = (navigation = false) => {
375
+ const trigger = triggerRef.current;
376
+ const target = trigger !== null && document.contains(trigger) && !trigger.disabled ? trigger : rootRef.current?.querySelector("button:not(:disabled)");
377
+ if (target == null) return;
378
+ if (navigation) target.focus();
379
+ else focusWithoutRing(target);
380
+ };
381
+ const refocusAfterSelection = () => {
382
+ const navigation = selectingWithTab.current;
383
+ queueMicrotask(() => {
384
+ if (openRef.current) return;
385
+ const active = document.activeElement;
386
+ if (active === null || active === document.body || listRef.current?.contains(active) === true)
387
+ refocusAnchor(navigation);
388
+ });
389
+ };
390
+ const openRef = useRef3(open);
391
+ openRef.current = open;
392
+ const [openSubmenuId, setOpenSubmenuId] = useState(null);
393
+ const [fixedPos, setFixedPos] = useState(null);
394
+ const { arm: armClose, cancel: cancelClose } = usePointerGrace(onClose);
395
+ useLayoutEffect3(() => {
396
+ if (!open || !portal) {
397
+ setFixedPos(null);
398
+ return;
399
+ }
400
+ const place = () => {
401
+ let r;
402
+ if (getAnchorRect !== void 0) {
403
+ r = getAnchorRect();
404
+ } else {
405
+ r = rootRef.current?.getBoundingClientRect() ?? null;
406
+ }
407
+ if (r === null) return;
408
+ const MARGIN = 12;
409
+ const vw = window.innerWidth;
410
+ const vh = window.innerHeight;
411
+ const listEl = listRef.current;
412
+ const lw = listEl?.offsetWidth ?? 0;
413
+ const lh = listEl?.offsetHeight ?? 0;
414
+ let x;
415
+ let y;
416
+ if (side === "right") {
417
+ x = r.right + 4;
418
+ y = r.top;
419
+ } else if (align === "start") {
420
+ x = r.left;
421
+ y = side === "bottom" ? r.bottom + 4 : r.top - lh - 4;
422
+ } else {
423
+ x = r.right - lw;
424
+ y = side === "bottom" ? r.bottom + 4 : r.top - lh - 4;
425
+ }
426
+ if (lw > 0) x = Math.min(Math.max(x, MARGIN), vw - lw - MARGIN);
427
+ if (lh > 0) y = Math.min(Math.max(y, overlayTopMargin(MARGIN)), vh - lh - MARGIN);
428
+ setFixedPos((current) => current?.left === x && current.top === y ? current : { left: x, top: y });
429
+ };
430
+ place();
431
+ const track = () => {
432
+ place();
433
+ frame = requestAnimationFrame(track);
434
+ };
435
+ let frame = requestAnimationFrame(track);
436
+ window.addEventListener("scroll", place, true);
437
+ window.addEventListener("resize", place);
438
+ return () => {
439
+ cancelAnimationFrame(frame);
440
+ window.removeEventListener("scroll", place, true);
441
+ window.removeEventListener("resize", place);
442
+ };
443
+ }, [open, portal, align, side, getAnchorRect]);
444
+ useEffect(() => {
445
+ if (!open) {
446
+ triggerRef.current = null;
447
+ return;
448
+ }
449
+ const active = document.activeElement;
450
+ triggerRef.current = active instanceof HTMLElement && rootRef.current?.contains(active) === true ? active : null;
451
+ }, [open]);
452
+ useEffect(() => {
453
+ if (!open || !autoFocus) return;
454
+ const first = listRef.current?.querySelector("button:not(:disabled)");
455
+ walkIndex.current = first === void 0 || first === null ? null : 0;
456
+ if (first != null) focusWithoutRing(first);
457
+ }, [open, autoFocus]);
458
+ useEffect(() => {
459
+ if (!open) {
460
+ setOpenSubmenuId(null);
461
+ walkIndex.current = null;
462
+ return;
463
+ }
464
+ const composition = observeComposition(document);
465
+ const onPointerDown = (e) => {
466
+ if (!(e.target instanceof Node)) return;
467
+ if (rootRef.current?.contains(e.target) === true) return;
468
+ if (listRef.current?.contains(e.target) === true) return;
469
+ onClose();
470
+ };
471
+ const onKeyDown = (e) => {
472
+ if (composition.guards(e) || isBehindModal(rootRef.current) || e.defaultPrevented || e.ctrlKey || e.altKey || e.metaKey)
473
+ return;
474
+ const focused = document.activeElement;
475
+ const insideList = listRef.current?.contains(focused) === true;
476
+ const anchored = rootRef.current?.contains(focused) === true || insideList;
477
+ if (e.key === "Escape" && !e.shiftKey) {
478
+ e.preventDefault();
479
+ if (e.repeat) return;
480
+ onClose();
481
+ if (anchored || autoFocus) refocusAnchor();
482
+ }
483
+ if (e.key === "Tab") {
484
+ const list3 = listRef.current;
485
+ if (list3 === null || !anchored) return;
486
+ if (e.shiftKey) {
487
+ e.preventDefault();
488
+ onClose();
489
+ refocusAnchor(true);
490
+ return;
491
+ }
492
+ if (insideList) {
493
+ if (focused instanceof Element && focused.getAttribute("role") === "menuitem") {
494
+ e.preventDefault();
495
+ selectingWithTab.current = true;
496
+ try {
497
+ ;
498
+ focused.click();
499
+ } finally {
500
+ selectingWithTab.current = false;
501
+ }
502
+ }
503
+ return;
504
+ }
505
+ const row = list3.querySelector("button:not(:disabled)");
506
+ if (row === null) return;
507
+ e.preventDefault();
508
+ row.focus();
509
+ walkIndex.current = 0;
510
+ return;
511
+ }
512
+ if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(e.key)) return;
513
+ const list2 = listRef.current;
514
+ if (list2 === null || !anchored) return;
515
+ const buttons = Array.from(list2.querySelectorAll("button:not(:disabled)"));
516
+ if (buttons.length === 0) return;
517
+ const index = buttons.indexOf(focused);
518
+ const from = index >= 0 ? index : walkIndex.current;
519
+ const next = e.key === "Home" ? 0 : e.key === "End" ? buttons.length - 1 : from === null ? e.key === "ArrowDown" ? 0 : buttons.length - 1 : (from + (e.key === "ArrowDown" ? 1 : -1) + buttons.length) % buttons.length;
520
+ e.preventDefault();
521
+ walkIndex.current = next;
522
+ buttons[next]?.focus();
523
+ };
524
+ const onWindowBlur = () => {
525
+ if (document.activeElement instanceof HTMLIFrameElement) onClose();
526
+ };
527
+ document.addEventListener("pointerdown", onPointerDown);
528
+ const onEscape = (event) => {
529
+ if (event.key === "Escape") onKeyDown(event);
530
+ };
531
+ const onOtherKey = (event) => {
532
+ if (event.key !== "Escape") onKeyDown(event);
533
+ };
534
+ document.addEventListener("keydown", onOtherKey);
535
+ document.addEventListener("keydown", onEscape, true);
536
+ window.addEventListener("blur", onWindowBlur);
537
+ return () => {
538
+ composition.dispose();
539
+ document.removeEventListener("pointerdown", onPointerDown);
540
+ document.removeEventListener("keydown", onOtherKey);
541
+ document.removeEventListener("keydown", onEscape, true);
542
+ window.removeEventListener("blur", onWindowBlur);
543
+ };
544
+ }, [open, onClose, autoFocus]);
545
+ useEffect(() => {
546
+ if (!open) cancelClose();
547
+ }, [open, cancelClose]);
548
+ const scrollable = !items.some(
549
+ (entry) => !isSeparator(entry) && !isLabel(entry) && entry.submenu !== void 0 && entry.submenu.length > 0
550
+ );
551
+ const renderEntry = (entry) => {
552
+ if (isSeparator(entry)) {
553
+ return /* @__PURE__ */ jsx4("div", { className: Menu_module_default.separator, role: "separator" }, entry.id);
554
+ }
555
+ if (isLabel(entry)) {
556
+ return /* @__PURE__ */ jsx4("div", { className: Menu_module_default.label, role: "presentation", children: entry.text }, entry.id);
557
+ }
558
+ const hasSub = entry.submenu !== void 0 && entry.submenu.length > 0;
559
+ const subOpen = hasSub && openSubmenuId === entry.id;
560
+ const selected = entry.id === selectedId || selectedIds?.includes(entry.id) === true;
561
+ return /* @__PURE__ */ jsxs3(
562
+ "div",
563
+ {
564
+ className: Menu_module_default.itemWrap,
565
+ onMouseEnter: hasSub ? () => {
566
+ setOpenSubmenuId(entry.id);
567
+ } : void 0,
568
+ onMouseLeave: () => {
569
+ setOpenSubmenuId(null);
570
+ },
571
+ children: [
572
+ /* @__PURE__ */ jsxs3(
573
+ "button",
574
+ {
575
+ type: "button",
576
+ role: "menuitem",
577
+ className: clsx4(
578
+ Menu_module_default.item,
579
+ selected && (selection === "fill" ? Menu_module_default.selectedFill : Menu_module_default.selected),
580
+ entry.danger === true && Menu_module_default.danger
581
+ ),
582
+ disabled: entry.disabled,
583
+ "aria-keyshortcuts": entry.shortcut?.aria,
584
+ "aria-haspopup": hasSub ? "menu" : void 0,
585
+ "aria-expanded": hasSub ? subOpen : void 0,
586
+ onFocus: hasSub ? () => {
587
+ setOpenSubmenuId(entry.id);
588
+ } : void 0,
589
+ onClick: () => {
590
+ if (hasSub) {
591
+ setOpenSubmenuId(entry.id);
592
+ return;
593
+ }
594
+ onSelect?.(entry.id);
595
+ },
596
+ children: [
597
+ entry.icon !== void 0 && /* @__PURE__ */ jsx4("span", { className: Menu_module_default.itemIcon, children: entry.icon }),
598
+ /* @__PURE__ */ jsx4("span", { className: Menu_module_default.itemLabel, children: entry.label }),
599
+ entry.shortcut !== void 0 && /* @__PURE__ */ jsx4("span", { "aria-hidden": "true", className: Menu_module_default.shortcut, children: /* @__PURE__ */ jsx4(ShortcutKeys, { keys: entry.shortcut.keys, className: Menu_module_default.shortcutKeys }) }),
600
+ selected && selection === "check" && /* @__PURE__ */ jsx4(IconCheckOutlineRegular, { className: Menu_module_default.check })
601
+ ]
602
+ }
603
+ ),
604
+ subOpen && entry.submenu !== void 0 && /* @__PURE__ */ jsx4(MenuSurface, { compact, className: clsx4(Menu_module_default.submenu, compact && Menu_module_default.compactList), role: "menu", children: entry.submenu.map((sub) => /* @__PURE__ */ jsxs3(
605
+ "button",
606
+ {
607
+ type: "button",
608
+ role: "menuitem",
609
+ className: Menu_module_default.item,
610
+ disabled: sub.disabled,
611
+ "aria-keyshortcuts": sub.shortcut?.aria,
612
+ onClick: () => {
613
+ onSelect?.(sub.id);
614
+ refocusAfterSelection();
615
+ },
616
+ children: [
617
+ sub.icon !== void 0 && /* @__PURE__ */ jsx4("span", { className: Menu_module_default.itemIcon, children: sub.icon }),
618
+ /* @__PURE__ */ jsx4("span", { className: Menu_module_default.itemLabel, children: sub.label }),
619
+ sub.shortcut !== void 0 && /* @__PURE__ */ jsx4("span", { "aria-hidden": "true", className: Menu_module_default.shortcut, children: /* @__PURE__ */ jsx4(ShortcutKeys, { keys: sub.shortcut.keys, className: Menu_module_default.shortcutKeys }) })
620
+ ]
621
+ },
622
+ sub.id
623
+ )) })
624
+ ]
625
+ },
626
+ entry.id
627
+ );
628
+ };
629
+ const collapseSubmenuFrom = (e) => {
630
+ const row = e.target instanceof Element ? e.target.closest('button[role="menuitem"]') : null;
631
+ if (row === null || row.getAttribute("aria-haspopup") === "menu") return;
632
+ if (row.closest('[role="menu"]') !== e.currentTarget) return;
633
+ setOpenSubmenuId(null);
634
+ };
635
+ const list = open && /* @__PURE__ */ jsxs3(
636
+ MenuSurface,
637
+ {
638
+ compact,
639
+ ref: listRef,
640
+ className: clsx4(
641
+ Menu_module_default.list,
642
+ listClassName,
643
+ dense && Menu_module_default.denseList,
644
+ compact && Menu_module_default.compactList,
645
+ scrollable && Menu_module_default.scrollable,
646
+ portal && Menu_module_default.portal,
647
+ side === "top" && !portal && Menu_module_default.sideTop,
648
+ align === "end" && !portal && Menu_module_default.alignEnd
649
+ ),
650
+ style: portal ? fixedPos ?? MEASURE_STYLE : void 0,
651
+ role: "menu",
652
+ onClick: (e) => {
653
+ e.stopPropagation();
654
+ const row = e.target instanceof Element ? e.target.closest('button[role="menuitem"]') : null;
655
+ if (row !== null && row.getAttribute("aria-haspopup") !== "menu") refocusAfterSelection();
656
+ },
657
+ onMouseOver: collapseSubmenuFrom,
658
+ onFocus: collapseSubmenuFrom,
659
+ children: [
660
+ /* @__PURE__ */ jsxs3("div", { className: Menu_module_default.viewport, role: "presentation", children: [
661
+ items.map(renderEntry),
662
+ children
663
+ ] }),
664
+ footer !== void 0 && footer.length > 0 && /* @__PURE__ */ jsx4("div", { className: Menu_module_default.footer, role: "presentation", children: footer.map(renderEntry) })
665
+ ]
666
+ }
667
+ );
668
+ return /* @__PURE__ */ jsxs3(
669
+ "span",
670
+ {
671
+ ref: rootRef,
672
+ className: clsx4(Menu_module_default.root, className),
673
+ onPointerEnter: closeOnPointerLeave ? cancelClose : void 0,
674
+ onPointerLeave: closeOnPointerLeave ? () => {
675
+ if (open) armClose();
676
+ } : void 0,
677
+ children: [
678
+ anchor,
679
+ portal ? list !== false && createPortal2(list, document.body) : list
680
+ ]
681
+ }
682
+ );
683
+ }
684
+
685
+ export {
686
+ StateDot,
687
+ Pill,
688
+ observeComposition,
689
+ focusWithoutRing,
690
+ modalSelector,
691
+ closeTopModal,
692
+ isBehindModal,
693
+ useModalLayer,
694
+ MenuSurface,
695
+ MenuItemButton,
696
+ Menu
697
+ };