@refraction-ui/react 0.19.1 → 0.20.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 (342) hide show
  1. package/dist/chunk-533MCMSU.js +2355 -0
  2. package/dist/chunk-533MCMSU.js.map +7 -0
  3. package/dist/chunk-AMK4VCBG.js +250 -0
  4. package/dist/chunk-AMK4VCBG.js.map +7 -0
  5. package/dist/chunk-BOLFYVI6.js +90 -0
  6. package/dist/chunk-BOLFYVI6.js.map +7 -0
  7. package/dist/chunk-F7B64KT3.js +187 -0
  8. package/dist/chunk-F7B64KT3.js.map +7 -0
  9. package/dist/chunk-FD37DFCC.js +77 -0
  10. package/dist/chunk-FD37DFCC.js.map +7 -0
  11. package/dist/chunk-H54FLNAF.js +132 -0
  12. package/dist/chunk-H54FLNAF.js.map +7 -0
  13. package/dist/chunk-INP46354.js +664 -0
  14. package/dist/chunk-INP46354.js.map +7 -0
  15. package/dist/chunk-ONACRMG4.js +116 -0
  16. package/dist/chunk-ONACRMG4.js.map +7 -0
  17. package/dist/chunk-SDZ3LROZ.js +7 -0
  18. package/dist/chunk-SDZ3LROZ.js.map +7 -0
  19. package/dist/chunk-TOZBR4GL.js +154 -0
  20. package/dist/chunk-TOZBR4GL.js.map +7 -0
  21. package/dist/chunk-UNEM2TRI.js +225 -0
  22. package/dist/chunk-UNEM2TRI.js.map +7 -0
  23. package/dist/chunk-VK3EQ34F.js +92 -0
  24. package/dist/chunk-VK3EQ34F.js.map +7 -0
  25. package/dist/chunk-WK2IIUFO.js +316 -0
  26. package/dist/chunk-WK2IIUFO.js.map +7 -0
  27. package/dist/chunk-WSPJTQAV.js +59 -0
  28. package/dist/chunk-WSPJTQAV.js.map +7 -0
  29. package/dist/chunk-XWP763SH.js +3 -2
  30. package/dist/chunk-XWP763SH.js.map +7 -1
  31. package/dist/chunk-Y2FNNAIL.js +80 -0
  32. package/dist/chunk-Y2FNNAIL.js.map +1 -0
  33. package/dist/{chunk-4A4BW3GR.js → chunk-ZF3OHCGV.js} +28 -5
  34. package/dist/chunk-ZF3OHCGV.js.map +7 -0
  35. package/dist/form.cjs +5 -11
  36. package/dist/form.cjs.map +1 -1
  37. package/dist/form.js +6 -12
  38. package/dist/form.js.map +1 -1
  39. package/dist/index.cjs +2879 -33936
  40. package/dist/index.cjs.map +1 -1
  41. package/dist/index.d.cts +1 -0
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.js +126 -28780
  44. package/dist/internal/react-app-shell/index.d.cts +2 -22
  45. package/dist/internal/react-app-shell/index.d.ts +2 -22
  46. package/dist/internal/react-badge/index.d.cts +5 -0
  47. package/dist/internal/react-badge/index.d.ts +5 -0
  48. package/dist/internal/react-callout/index.d.cts +4 -0
  49. package/dist/internal/react-callout/index.d.ts +4 -0
  50. package/dist/internal/react-card/index.d.cts +8 -1
  51. package/dist/internal/react-card/index.d.ts +8 -1
  52. package/dist/internal/react-collapsible/index.d.cts +0 -3
  53. package/dist/internal/react-collapsible/index.d.ts +0 -3
  54. package/dist/internal/react-combobox/index.d.cts +0 -3
  55. package/dist/internal/react-combobox/index.d.ts +0 -3
  56. package/dist/internal/react-command/index.d.cts +0 -3
  57. package/dist/internal/react-command/index.d.ts +0 -3
  58. package/dist/internal/react-data-table/index.d.cts +0 -3
  59. package/dist/internal/react-data-table/index.d.ts +0 -3
  60. package/dist/internal/react-dialog/index.d.cts +0 -3
  61. package/dist/internal/react-dialog/index.d.ts +0 -3
  62. package/dist/internal/react-dropdown-menu/index.d.cts +0 -3
  63. package/dist/internal/react-dropdown-menu/index.d.ts +0 -3
  64. package/dist/internal/react-feedback-dialog/index.d.cts +0 -3
  65. package/dist/internal/react-feedback-dialog/index.d.ts +0 -3
  66. package/dist/internal/react-form/index.d.cts +2 -21
  67. package/dist/internal/react-form/index.d.ts +2 -21
  68. package/dist/internal/react-keyboard-shortcut/index.d.cts +0 -6
  69. package/dist/internal/react-keyboard-shortcut/index.d.ts +0 -6
  70. package/dist/internal/react-link-card/index.d.cts +8 -2
  71. package/dist/internal/react-link-card/index.d.ts +8 -2
  72. package/dist/internal/react-popover/index.d.cts +0 -3
  73. package/dist/internal/react-popover/index.d.ts +0 -3
  74. package/dist/internal/react-sheet/index.d.cts +0 -3
  75. package/dist/internal/react-sheet/index.d.ts +0 -3
  76. package/dist/internal/react-slot/index.d.cts +23 -0
  77. package/dist/internal/react-slot/index.d.ts +23 -0
  78. package/dist/internal/react-toast/index.d.cts +0 -3
  79. package/dist/internal/react-toast/index.d.ts +0 -3
  80. package/dist/internal/react-tooltip/index.d.cts +0 -3
  81. package/dist/internal/react-tooltip/index.d.ts +0 -3
  82. package/dist/react-accordion.js +125 -0
  83. package/dist/react-accordion.js.map +7 -0
  84. package/dist/react-ai.js +257 -0
  85. package/dist/react-ai.js.map +7 -0
  86. package/dist/react-analytics.js +1698 -0
  87. package/dist/react-analytics.js.map +7 -0
  88. package/dist/react-animated-text.js +164 -0
  89. package/dist/react-animated-text.js.map +7 -0
  90. package/dist/react-app-shell.js +631 -0
  91. package/dist/react-app-shell.js.map +7 -0
  92. package/dist/react-audience-feature-card.js +53 -0
  93. package/dist/react-audience-feature-card.js.map +7 -0
  94. package/dist/react-audio-room.js +166 -0
  95. package/dist/react-audio-room.js.map +7 -0
  96. package/dist/react-auth.js +211 -0
  97. package/dist/react-auth.js.map +7 -0
  98. package/dist/react-avatar-group.js +154 -0
  99. package/dist/react-avatar-group.js.map +7 -0
  100. package/dist/react-avatar.js +168 -0
  101. package/dist/react-avatar.js.map +7 -0
  102. package/dist/react-badge.js +86 -0
  103. package/dist/react-badge.js.map +7 -0
  104. package/dist/react-bottom-nav.js +67 -0
  105. package/dist/react-bottom-nav.js.map +7 -0
  106. package/dist/react-brand-network-cell.js +92 -0
  107. package/dist/react-brand-network-cell.js.map +7 -0
  108. package/dist/react-breadcrumbs.js +104 -0
  109. package/dist/react-breadcrumbs.js.map +7 -0
  110. package/dist/react-browser-chrome-mock.js +89 -0
  111. package/dist/react-browser-chrome-mock.js.map +7 -0
  112. package/dist/react-button.js +13 -0
  113. package/dist/react-button.js.map +7 -0
  114. package/dist/react-calendar.js +301 -0
  115. package/dist/react-calendar.js.map +7 -0
  116. package/dist/react-call-controls.js +113 -0
  117. package/dist/react-call-controls.js.map +7 -0
  118. package/dist/react-callout.js +152 -0
  119. package/dist/react-callout.js.map +7 -0
  120. package/dist/react-card-grid.js +34 -0
  121. package/dist/react-card-grid.js.map +7 -0
  122. package/dist/react-card.js +200 -0
  123. package/dist/react-card.js.map +7 -0
  124. package/dist/react-carousel.js +132 -0
  125. package/dist/react-carousel.js.map +7 -0
  126. package/dist/react-charts.js +509 -0
  127. package/dist/react-charts.js.map +7 -0
  128. package/dist/react-checkbox.js +156 -0
  129. package/dist/react-checkbox.js.map +7 -0
  130. package/dist/react-checklist.js +168 -0
  131. package/dist/react-checklist.js.map +7 -0
  132. package/dist/react-code-block.js +78 -0
  133. package/dist/react-code-block.js.map +7 -0
  134. package/dist/react-code-editor.js +184 -0
  135. package/dist/react-code-editor.js.map +7 -0
  136. package/dist/react-collapsible.js +192 -0
  137. package/dist/react-collapsible.js.map +7 -0
  138. package/dist/react-combobox.js +609 -0
  139. package/dist/react-combobox.js.map +7 -0
  140. package/dist/react-command-input.js +202 -0
  141. package/dist/react-command-input.js.map +7 -0
  142. package/dist/react-command.js +364 -0
  143. package/dist/react-command.js.map +7 -0
  144. package/dist/react-composer.js +2036 -0
  145. package/dist/react-composer.js.map +7 -0
  146. package/dist/react-content-protection.js +133 -0
  147. package/dist/react-content-protection.js.map +7 -0
  148. package/dist/react-conversation.js +1226 -0
  149. package/dist/react-conversation.js.map +7 -0
  150. package/dist/react-cookie-consent.js +291 -0
  151. package/dist/react-cookie-consent.js.map +7 -0
  152. package/dist/react-data-table.js +310 -0
  153. package/dist/react-data-table.js.map +7 -0
  154. package/dist/react-date-picker.js +95 -0
  155. package/dist/react-date-picker.js.map +7 -0
  156. package/dist/react-device-frame.js +137 -0
  157. package/dist/react-device-frame.js.map +7 -0
  158. package/dist/react-dialog.js +218 -0
  159. package/dist/react-dialog.js.map +7 -0
  160. package/dist/react-diff-viewer.js +460 -0
  161. package/dist/react-diff-viewer.js.map +7 -0
  162. package/dist/react-dropdown-menu.js +292 -0
  163. package/dist/react-dropdown-menu.js.map +7 -0
  164. package/dist/react-editor-status-bar.js +148 -0
  165. package/dist/react-editor-status-bar.js.map +7 -0
  166. package/dist/react-editor-tabs.js +159 -0
  167. package/dist/react-editor-tabs.js.map +7 -0
  168. package/dist/react-emoji-picker.js +238 -0
  169. package/dist/react-emoji-picker.js.map +7 -0
  170. package/dist/react-empty-state.js +90 -0
  171. package/dist/react-empty-state.js.map +7 -0
  172. package/dist/react-feedback-dialog.js +275 -0
  173. package/dist/react-feedback-dialog.js.map +7 -0
  174. package/dist/react-file-tree.js +376 -0
  175. package/dist/react-file-tree.js.map +7 -0
  176. package/dist/react-file-upload.js +360 -0
  177. package/dist/react-file-upload.js.map +7 -0
  178. package/dist/react-floating-reactions.js +124 -0
  179. package/dist/react-floating-reactions.js.map +7 -0
  180. package/dist/react-flow-editor.js +198 -0
  181. package/dist/react-flow-editor.js.map +7 -0
  182. package/dist/react-footer.js +67 -0
  183. package/dist/react-footer.js.map +7 -0
  184. package/dist/react-graph-view.js +197 -0
  185. package/dist/react-graph-view.js.map +7 -0
  186. package/dist/react-icon-system.js +9 -0
  187. package/dist/react-icon-system.js.map +7 -0
  188. package/dist/react-infinite-canvas.js +8 -0
  189. package/dist/react-infinite-canvas.js.map +7 -0
  190. package/dist/react-inline-editor.js +216 -0
  191. package/dist/react-inline-editor.js.map +7 -0
  192. package/dist/react-input-group.js +150 -0
  193. package/dist/react-input-group.js.map +7 -0
  194. package/dist/react-input.js +10 -0
  195. package/dist/react-input.js.map +7 -0
  196. package/dist/react-install-prompt.js +132 -0
  197. package/dist/react-install-prompt.js.map +7 -0
  198. package/dist/react-kanban-board.js +198 -0
  199. package/dist/react-kanban-board.js.map +7 -0
  200. package/dist/react-keyboard-shortcut.js +36 -0
  201. package/dist/react-keyboard-shortcut.js.map +7 -0
  202. package/dist/react-language-selector.js +311 -0
  203. package/dist/react-language-selector.js.map +7 -0
  204. package/dist/react-link-card.js +48 -0
  205. package/dist/react-link-card.js.map +7 -0
  206. package/dist/react-live-captions.js +92 -0
  207. package/dist/react-live-captions.js.map +7 -0
  208. package/dist/react-live-cursors.js +145 -0
  209. package/dist/react-live-cursors.js.map +7 -0
  210. package/dist/react-live-transcript.js +117 -0
  211. package/dist/react-live-transcript.js.map +7 -0
  212. package/dist/react-location-selector.js +252 -0
  213. package/dist/react-location-selector.js.map +7 -0
  214. package/dist/react-logger.js +415 -0
  215. package/dist/react-logger.js.map +7 -0
  216. package/dist/react-markdown-renderer.js +12 -0
  217. package/dist/react-markdown-renderer.js.map +7 -0
  218. package/dist/react-marquee-strip.js +62 -0
  219. package/dist/react-marquee-strip.js.map +7 -0
  220. package/dist/react-mascot.js +367 -0
  221. package/dist/react-mascot.js.map +7 -0
  222. package/dist/react-mastery-bar.js +97 -0
  223. package/dist/react-mastery-bar.js.map +7 -0
  224. package/dist/react-mini-map.js +207 -0
  225. package/dist/react-mini-map.js.map +7 -0
  226. package/dist/react-mobile-nav.js +216 -0
  227. package/dist/react-mobile-nav.js.map +7 -0
  228. package/dist/react-navbar.js +96 -0
  229. package/dist/react-navbar.js.map +7 -0
  230. package/dist/react-numbered-steps.js +67 -0
  231. package/dist/react-numbered-steps.js.map +7 -0
  232. package/dist/react-otp-input.js +318 -0
  233. package/dist/react-otp-input.js.map +7 -0
  234. package/dist/react-pagination.js +199 -0
  235. package/dist/react-pagination.js.map +7 -0
  236. package/dist/react-password-input.js +104 -0
  237. package/dist/react-password-input.js.map +7 -0
  238. package/dist/react-payment.js +81 -0
  239. package/dist/react-payment.js.map +7 -0
  240. package/dist/react-popover.js +176 -0
  241. package/dist/react-popover.js.map +7 -0
  242. package/dist/react-pre-call-lobby.js +309 -0
  243. package/dist/react-pre-call-lobby.js.map +7 -0
  244. package/dist/react-presence-indicator.js +86 -0
  245. package/dist/react-presence-indicator.js.map +7 -0
  246. package/dist/react-pricing-card.js +142 -0
  247. package/dist/react-pricing-card.js.map +7 -0
  248. package/dist/react-progress-display.js +188 -0
  249. package/dist/react-progress-display.js.map +7 -0
  250. package/dist/react-radial-gauge.js +193 -0
  251. package/dist/react-radial-gauge.js.map +7 -0
  252. package/dist/react-radio.js +169 -0
  253. package/dist/react-radio.js.map +7 -0
  254. package/dist/react-rating-scale.js +171 -0
  255. package/dist/react-rating-scale.js.map +7 -0
  256. package/dist/react-reaction-bar.js +111 -0
  257. package/dist/react-reaction-bar.js.map +7 -0
  258. package/dist/react-resizable-layout.js +298 -0
  259. package/dist/react-resizable-layout.js.map +7 -0
  260. package/dist/react-rich-editor.js +1 -0
  261. package/dist/react-rich-editor.js.map +7 -0
  262. package/dist/react-search-bar.js +285 -0
  263. package/dist/react-search-bar.js.map +7 -0
  264. package/dist/react-section-head.js +65 -0
  265. package/dist/react-section-head.js.map +7 -0
  266. package/dist/react-segmented-control.js +215 -0
  267. package/dist/react-segmented-control.js.map +7 -0
  268. package/dist/react-select.js +389 -0
  269. package/dist/react-select.js.map +7 -0
  270. package/dist/react-separator.js +86 -0
  271. package/dist/react-separator.js.map +7 -0
  272. package/dist/react-sheet.js +310 -0
  273. package/dist/react-sheet.js.map +7 -0
  274. package/dist/react-sidebar.js +100 -0
  275. package/dist/react-sidebar.js.map +7 -0
  276. package/dist/react-skeleton.js +91 -0
  277. package/dist/react-skeleton.js.map +7 -0
  278. package/dist/react-skip-to-content.js +38 -0
  279. package/dist/react-skip-to-content.js.map +7 -0
  280. package/dist/react-slide-viewer.js +264 -0
  281. package/dist/react-slide-viewer.js.map +7 -0
  282. package/dist/react-slider.js +105 -0
  283. package/dist/react-slider.js.map +7 -0
  284. package/dist/react-slot-picker.js +184 -0
  285. package/dist/react-slot-picker.js.map +7 -0
  286. package/dist/react-slot.js +7 -0
  287. package/dist/react-slot.js.map +7 -0
  288. package/dist/react-social-auth-button.js +169 -0
  289. package/dist/react-social-auth-button.js.map +7 -0
  290. package/dist/react-sortable-list.js +204 -0
  291. package/dist/react-sortable-list.js.map +7 -0
  292. package/dist/react-stat-grid.js +69 -0
  293. package/dist/react-stat-grid.js.map +7 -0
  294. package/dist/react-status-indicator.js +117 -0
  295. package/dist/react-status-indicator.js.map +7 -0
  296. package/dist/react-steps.js +167 -0
  297. package/dist/react-steps.js.map +7 -0
  298. package/dist/react-sticky-note.js +131 -0
  299. package/dist/react-sticky-note.js.map +7 -0
  300. package/dist/react-switch.js +139 -0
  301. package/dist/react-switch.js.map +7 -0
  302. package/dist/react-table-of-contents.js +80 -0
  303. package/dist/react-table-of-contents.js.map +7 -0
  304. package/dist/react-tabs.js +230 -0
  305. package/dist/react-tabs.js.map +7 -0
  306. package/dist/react-terminal.js +101 -0
  307. package/dist/react-terminal.js.map +7 -0
  308. package/dist/react-test-results.js +158 -0
  309. package/dist/react-test-results.js.map +7 -0
  310. package/dist/react-textarea.js +89 -0
  311. package/dist/react-textarea.js.map +7 -0
  312. package/dist/react-thread-view.js +139 -0
  313. package/dist/react-thread-view.js.map +7 -0
  314. package/dist/react-timeline.js +153 -0
  315. package/dist/react-timeline.js.map +7 -0
  316. package/dist/react-toast.js +253 -0
  317. package/dist/react-toast.js.map +7 -0
  318. package/dist/react-tooltip.js +221 -0
  319. package/dist/react-tooltip.js.map +7 -0
  320. package/dist/react-version-selector.js +270 -0
  321. package/dist/react-version-selector.js.map +7 -0
  322. package/dist/react-video-grid.js +129 -0
  323. package/dist/react-video-grid.js.map +7 -0
  324. package/dist/react-video-player.js +206 -0
  325. package/dist/react-video-player.js.map +7 -0
  326. package/dist/react-video-tile.js +8 -0
  327. package/dist/react-video-tile.js.map +7 -0
  328. package/dist/react-voice-pill.js +314 -0
  329. package/dist/react-voice-pill.js.map +7 -0
  330. package/dist/react-waveform.js +558 -0
  331. package/dist/react-waveform.js.map +7 -0
  332. package/dist/react-wizard.js +337 -0
  333. package/dist/react-wizard.js.map +7 -0
  334. package/dist/styles.css +7 -0
  335. package/dist/theme.js +1 -1
  336. package/package.json +3 -2
  337. package/dist/applicationinsights-web-H7OBLIVJ.js +0 -23393
  338. package/dist/applicationinsights-web-H7OBLIVJ.js.map +0 -1
  339. package/dist/chunk-4A4BW3GR.js.map +0 -1
  340. package/dist/index.js.map +0 -1
  341. package/dist/module-X3HTTRQK.js +0 -6438
  342. package/dist/module-X3HTTRQK.js.map +0 -1
@@ -0,0 +1,275 @@
1
+ import {
2
+ createDialog
3
+ } from "./chunk-VK3EQ34F.js";
4
+ import {
5
+ cn,
6
+ cva,
7
+ generateId
8
+ } from "./chunk-ZF3OHCGV.js";
9
+
10
+ // ../react-feedback-dialog/dist/index.js
11
+ import * as React from "react";
12
+
13
+ // ../feedback-dialog/dist/index.js
14
+ function createFeedbackDialog(props = {}) {
15
+ const {
16
+ open: controlledOpen,
17
+ onOpenChange,
18
+ onSubmit,
19
+ type = "general"
20
+ } = props;
21
+ const dialog = createDialog({
22
+ open: controlledOpen,
23
+ onOpenChange,
24
+ modal: true
25
+ });
26
+ let isSubmitting = false;
27
+ let isSubmitted = false;
28
+ const formState = {
29
+ comment: "",
30
+ email: "",
31
+ honeypot: ""
32
+ };
33
+ const feedbackId = generateId("rfr-feedback");
34
+ function setField(field, value) {
35
+ formState[field] = value;
36
+ }
37
+ async function submit() {
38
+ if (formState.honeypot) {
39
+ return;
40
+ }
41
+ if (!formState.comment.trim()) {
42
+ return;
43
+ }
44
+ isSubmitting = true;
45
+ const data = {
46
+ comment: formState.comment,
47
+ type,
48
+ ...formState.email ? { email: formState.email } : {}
49
+ };
50
+ try {
51
+ await onSubmit?.(data);
52
+ isSubmitting = false;
53
+ isSubmitted = true;
54
+ } catch {
55
+ isSubmitting = false;
56
+ }
57
+ }
58
+ function reset() {
59
+ formState.comment = "";
60
+ formState.email = "";
61
+ formState.honeypot = "";
62
+ isSubmitting = false;
63
+ isSubmitted = false;
64
+ }
65
+ const ariaProps = {
66
+ role: "dialog",
67
+ "aria-modal": true,
68
+ "aria-labelledby": `${feedbackId}-title`,
69
+ "aria-describedby": `${feedbackId}-desc`,
70
+ id: feedbackId
71
+ };
72
+ return {
73
+ get state() {
74
+ return {
75
+ get open() {
76
+ return dialog.state.open;
77
+ },
78
+ get isSubmitting() {
79
+ return isSubmitting;
80
+ },
81
+ get isSubmitted() {
82
+ return isSubmitted;
83
+ }
84
+ };
85
+ },
86
+ dialogProps: dialog,
87
+ formState,
88
+ setField,
89
+ submit,
90
+ reset,
91
+ ariaProps
92
+ };
93
+ }
94
+ var feedbackDialogVariants = cva({
95
+ base: "fixed left-1/2 top-1/2 z-50 w-full max-w-md -translate-x-1/2 -translate-y-1/2 rounded-lg border bg-background p-6 shadow-lg",
96
+ variants: {
97
+ type: {
98
+ text: "max-w-md",
99
+ video: "max-w-lg",
100
+ general: "max-w-md"
101
+ }
102
+ },
103
+ defaultVariants: {
104
+ type: "general"
105
+ }
106
+ });
107
+
108
+ // ../react-feedback-dialog/dist/index.js
109
+ function FeedbackDialog({
110
+ open: controlledOpen,
111
+ defaultOpen = false,
112
+ onOpenChange,
113
+ onSubmit,
114
+ type = "general",
115
+ className,
116
+ children
117
+ }) {
118
+ const [open, setOpen] = React.useState(controlledOpen ?? defaultOpen);
119
+ const [comment, setComment] = React.useState("");
120
+ const [email, setEmail] = React.useState("");
121
+ const [honeypot, setHoneypot] = React.useState("");
122
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
123
+ const [isSubmitted, setIsSubmitted] = React.useState(false);
124
+ const isControlled = controlledOpen !== void 0;
125
+ const isOpen = isControlled ? controlledOpen : open;
126
+ const handleOpenChange = React.useCallback(
127
+ (next) => {
128
+ if (!isControlled) {
129
+ setOpen(next);
130
+ }
131
+ onOpenChange?.(next);
132
+ },
133
+ [isControlled, onOpenChange]
134
+ );
135
+ const apiRef = React.useRef(null);
136
+ if (apiRef.current === null) {
137
+ apiRef.current = createFeedbackDialog({ open: isOpen, onOpenChange: handleOpenChange, onSubmit, type });
138
+ }
139
+ const handleSubmit = React.useCallback(async () => {
140
+ if (honeypot) return;
141
+ if (!comment.trim()) return;
142
+ setIsSubmitting(true);
143
+ const data = {
144
+ comment,
145
+ type,
146
+ ...email ? { email } : {}
147
+ };
148
+ try {
149
+ await onSubmit?.(data);
150
+ setIsSubmitting(false);
151
+ setIsSubmitted(true);
152
+ } catch {
153
+ setIsSubmitting(false);
154
+ }
155
+ }, [comment, email, honeypot, type, onSubmit]);
156
+ const handleReset = React.useCallback(() => {
157
+ setComment("");
158
+ setEmail("");
159
+ setHoneypot("");
160
+ setIsSubmitting(false);
161
+ setIsSubmitted(false);
162
+ }, []);
163
+ const api = apiRef.current;
164
+ const trigger = React.isValidElement(children) ? (() => {
165
+ const child = children;
166
+ const childOnClick = child.props.onClick;
167
+ const childRef = child.ref;
168
+ return React.cloneElement(child, {
169
+ onClick: (e) => {
170
+ childOnClick?.(e);
171
+ if (!e.defaultPrevented) handleOpenChange(true);
172
+ },
173
+ ref: (node) => {
174
+ if (typeof childRef === "function") childRef(node);
175
+ else if (childRef) childRef.current = node;
176
+ }
177
+ });
178
+ })() : children;
179
+ if (isSubmitted) {
180
+ return React.createElement(
181
+ React.Fragment,
182
+ null,
183
+ trigger,
184
+ React.createElement(
185
+ "div",
186
+ {
187
+ className: cn(feedbackDialogVariants({ type }), className),
188
+ ...api.ariaProps,
189
+ "data-state": "submitted"
190
+ },
191
+ React.createElement("p", { "data-testid": "success-message" }, "Thank you for your feedback!"),
192
+ React.createElement(
193
+ "button",
194
+ {
195
+ type: "button",
196
+ onClick: () => {
197
+ handleReset();
198
+ handleOpenChange(false);
199
+ }
200
+ },
201
+ "Close"
202
+ )
203
+ )
204
+ );
205
+ }
206
+ return React.createElement(
207
+ React.Fragment,
208
+ null,
209
+ trigger,
210
+ isOpen ? React.createElement(
211
+ "div",
212
+ {
213
+ className: cn(feedbackDialogVariants({ type }), className),
214
+ ...api.ariaProps,
215
+ "data-state": "open"
216
+ },
217
+ React.createElement("h2", { id: `${api.ariaProps.id}-title` }, "Send Feedback"),
218
+ React.createElement("textarea", {
219
+ "aria-label": "Feedback comment",
220
+ value: comment,
221
+ onChange: (e) => setComment(e.target.value),
222
+ placeholder: "Your feedback...",
223
+ disabled: isSubmitting
224
+ }),
225
+ React.createElement("input", {
226
+ type: "email",
227
+ "aria-label": "Email",
228
+ value: email,
229
+ onChange: (e) => setEmail(e.target.value),
230
+ placeholder: "Email (optional)",
231
+ disabled: isSubmitting
232
+ }),
233
+ // Honeypot field — hidden from real users
234
+ React.createElement("input", {
235
+ type: "text",
236
+ "aria-hidden": true,
237
+ tabIndex: -1,
238
+ style: { position: "absolute", left: "-9999px" },
239
+ value: honeypot,
240
+ onChange: (e) => setHoneypot(e.target.value),
241
+ autoComplete: "off",
242
+ name: "website"
243
+ }),
244
+ React.createElement(
245
+ "button",
246
+ {
247
+ type: "button",
248
+ onClick: handleSubmit,
249
+ disabled: isSubmitting || !comment.trim()
250
+ },
251
+ isSubmitting ? "Submitting..." : "Submit"
252
+ )
253
+ ) : null
254
+ );
255
+ }
256
+ var FeedbackButton = React.forwardRef(
257
+ function FeedbackButton2({ children, ...props }, ref) {
258
+ return React.createElement(
259
+ "button",
260
+ {
261
+ ref,
262
+ type: "button",
263
+ "aria-label": "Send feedback",
264
+ ...props
265
+ },
266
+ children ?? "Feedback"
267
+ );
268
+ }
269
+ );
270
+ export {
271
+ FeedbackButton,
272
+ FeedbackDialog,
273
+ feedbackDialogVariants
274
+ };
275
+ //# sourceMappingURL=react-feedback-dialog.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../feedback-dialog/src/feedback-dialog.ts", "../../feedback-dialog/src/feedback-dialog.styles.ts", "../../react-feedback-dialog/src/FeedbackDialog.tsx"],
4
+ "sourcesContent": ["import type { AccessibilityProps } from '@refraction-ui/shared'\nimport { createDialog, type DialogAPI } from '@refraction-ui/dialog'\nimport { generateId } from '@refraction-ui/shared'\n\nexport type FeedbackType = 'text' | 'video' | 'general'\n\nexport interface FeedbackDialogProps {\n /** Whether the dialog is open (controlled) */\n open?: boolean\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void\n /** Callback when feedback is submitted */\n onSubmit?: (data: FeedbackData) => void | Promise<void>\n /** Feedback type */\n type?: FeedbackType\n}\n\nexport interface FeedbackData {\n comment: string\n email?: string\n type: FeedbackType\n selectedText?: string\n}\n\nexport interface FeedbackFormState {\n comment: string\n email: string\n honeypot: string\n}\n\nexport interface FeedbackDialogState {\n open: boolean\n isSubmitting: boolean\n isSubmitted: boolean\n}\n\nexport interface FeedbackDialogAPI {\n /** Current state */\n state: FeedbackDialogState\n /** Dialog props from the underlying createDialog */\n dialogProps: DialogAPI\n /** Form field values */\n formState: FeedbackFormState\n /** Set a form field value */\n setField(field: keyof FeedbackFormState, value: string): void\n /** Submit the feedback form */\n submit(): Promise<void>\n /** Reset form to initial state */\n reset(): void\n /** ARIA props for the feedback dialog */\n ariaProps: Partial<AccessibilityProps> & Record<string, unknown>\n}\n\nexport function createFeedbackDialog(props: FeedbackDialogProps = {}): FeedbackDialogAPI {\n const {\n open: controlledOpen,\n onOpenChange,\n onSubmit,\n type = 'general',\n } = props\n\n const dialog = createDialog({\n open: controlledOpen,\n onOpenChange,\n modal: true,\n })\n\n let isSubmitting = false\n let isSubmitted = false\n\n const formState: FeedbackFormState = {\n comment: '',\n email: '',\n honeypot: '',\n }\n\n const feedbackId = generateId('rfr-feedback')\n\n function setField(field: keyof FeedbackFormState, value: string): void {\n formState[field] = value\n }\n\n async function submit(): Promise<void> {\n // Honeypot check — bots fill this hidden field\n if (formState.honeypot) {\n return\n }\n\n if (!formState.comment.trim()) {\n return\n }\n\n isSubmitting = true\n\n const data: FeedbackData = {\n comment: formState.comment,\n type,\n ...(formState.email ? { email: formState.email } : {}),\n }\n\n try {\n await onSubmit?.(data)\n isSubmitting = false\n isSubmitted = true\n } catch {\n isSubmitting = false\n }\n }\n\n function reset(): void {\n formState.comment = ''\n formState.email = ''\n formState.honeypot = ''\n isSubmitting = false\n isSubmitted = false\n }\n\n const ariaProps: Partial<AccessibilityProps> & Record<string, unknown> = {\n role: 'dialog',\n 'aria-modal': true,\n 'aria-labelledby': `${feedbackId}-title`,\n 'aria-describedby': `${feedbackId}-desc`,\n id: feedbackId,\n }\n\n return {\n get state() {\n return {\n get open() {\n return dialog.state.open\n },\n get isSubmitting() {\n return isSubmitting\n },\n get isSubmitted() {\n return isSubmitted\n },\n }\n },\n dialogProps: dialog,\n formState,\n setField,\n submit,\n reset,\n ariaProps,\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\nexport const feedbackDialogVariants = cva({\n base: 'fixed left-1/2 top-1/2 z-50 w-full max-w-md -translate-x-1/2 -translate-y-1/2 rounded-lg border bg-background p-6 shadow-lg',\n variants: {\n type: {\n text: 'max-w-md',\n video: 'max-w-lg',\n general: 'max-w-md',\n },\n },\n defaultVariants: {\n type: 'general',\n },\n})\n", "import * as React from 'react'\nimport {\n createFeedbackDialog,\n feedbackDialogVariants,\n type FeedbackDialogProps as CoreProps,\n type FeedbackData,\n type FeedbackType,\n} from '@refraction-ui/feedback-dialog'\nimport { cn } from '@refraction-ui/shared'\n\n// ---------------------------------------------------------------------------\n// FeedbackDialog\n// ---------------------------------------------------------------------------\n\nexport interface FeedbackDialogProps {\n open?: boolean\n /** Initial open state for uncontrolled usage (like Radix `defaultOpen`). */\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n onSubmit?: (data: FeedbackData) => void | Promise<void>\n type?: FeedbackType\n className?: string\n children?: React.ReactNode\n}\n\nexport function FeedbackDialog({\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n onSubmit,\n type = 'general',\n className,\n children,\n}: FeedbackDialogProps) {\n const [open, setOpen] = React.useState(controlledOpen ?? defaultOpen)\n const [comment, setComment] = React.useState('')\n const [email, setEmail] = React.useState('')\n const [honeypot, setHoneypot] = React.useState('')\n const [isSubmitting, setIsSubmitting] = React.useState(false)\n const [isSubmitted, setIsSubmitted] = React.useState(false)\n\n const isControlled = controlledOpen !== undefined\n const isOpen = isControlled ? controlledOpen : open\n\n const handleOpenChange = React.useCallback(\n (next: boolean) => {\n if (!isControlled) {\n setOpen(next)\n }\n onOpenChange?.(next)\n },\n [isControlled, onOpenChange],\n )\n\n const apiRef = React.useRef<ReturnType<typeof createFeedbackDialog> | null>(null)\n if (apiRef.current === null) {\n apiRef.current = createFeedbackDialog({ open: isOpen, onOpenChange: handleOpenChange, onSubmit, type })\n }\n\n const handleSubmit = React.useCallback(async () => {\n if (honeypot) return\n if (!comment.trim()) return\n\n setIsSubmitting(true)\n const data: FeedbackData = {\n comment,\n type,\n ...(email ? { email } : {}),\n }\n\n try {\n await onSubmit?.(data)\n setIsSubmitting(false)\n setIsSubmitted(true)\n } catch {\n setIsSubmitting(false)\n }\n }, [comment, email, honeypot, type, onSubmit])\n\n const handleReset = React.useCallback(() => {\n setComment('')\n setEmail('')\n setHoneypot('')\n setIsSubmitting(false)\n setIsSubmitted(false)\n }, [])\n\n const api = apiRef.current\n\n // The trigger child stays mounted in every state and opens the dialog on\n // click (composed with the child's own onClick).\n const trigger = React.isValidElement(children)\n ? (() => {\n const child = children as React.ReactElement<Record<string, unknown>> & {\n ref?: React.Ref<HTMLButtonElement>\n }\n const childOnClick = child.props.onClick as\n | ((e: React.MouseEvent<HTMLButtonElement>) => void)\n | undefined\n const childRef = child.ref\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return React.cloneElement(child, {\n onClick: (e: React.MouseEvent<HTMLButtonElement>) => {\n childOnClick?.(e)\n if (!e.defaultPrevented) handleOpenChange(true)\n },\n ref: (node: HTMLButtonElement | null) => {\n if (typeof childRef === 'function') childRef(node)\n else if (childRef) childRef.current = node\n },\n } as any)\n })()\n : children\n\n if (isSubmitted) {\n return React.createElement(\n React.Fragment,\n null,\n trigger,\n React.createElement(\n 'div',\n {\n className: cn(feedbackDialogVariants({ type }), className),\n ...api.ariaProps,\n 'data-state': 'submitted',\n },\n React.createElement('p', { 'data-testid': 'success-message' }, 'Thank you for your feedback!'),\n React.createElement(\n 'button',\n {\n type: 'button',\n onClick: () => {\n handleReset()\n handleOpenChange(false)\n },\n },\n 'Close',\n ),\n ),\n )\n }\n\n return React.createElement(\n React.Fragment,\n null,\n trigger,\n isOpen\n ? React.createElement(\n 'div',\n {\n className: cn(feedbackDialogVariants({ type }), className),\n ...api.ariaProps,\n 'data-state': 'open',\n },\n React.createElement('h2', { id: `${api.ariaProps.id}-title` }, 'Send Feedback'),\n React.createElement('textarea', {\n 'aria-label': 'Feedback comment',\n value: comment,\n onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => setComment(e.target.value),\n placeholder: 'Your feedback...',\n disabled: isSubmitting,\n }),\n React.createElement('input', {\n type: 'email',\n 'aria-label': 'Email',\n value: email,\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => setEmail(e.target.value),\n placeholder: 'Email (optional)',\n disabled: isSubmitting,\n }),\n // Honeypot field — hidden from real users\n React.createElement('input', {\n type: 'text',\n 'aria-hidden': true,\n tabIndex: -1,\n style: { position: 'absolute', left: '-9999px' },\n value: honeypot,\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => setHoneypot(e.target.value),\n autoComplete: 'off',\n name: 'website',\n }),\n React.createElement(\n 'button',\n {\n type: 'button',\n onClick: handleSubmit,\n disabled: isSubmitting || !comment.trim(),\n },\n isSubmitting ? 'Submitting...' : 'Submit',\n ),\n )\n : null,\n )\n}\n\n// ---------------------------------------------------------------------------\n// FeedbackButton\n// ---------------------------------------------------------------------------\n\nexport interface FeedbackButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n children?: React.ReactNode\n}\n\nexport const FeedbackButton = React.forwardRef<HTMLButtonElement, FeedbackButtonProps>(\n function FeedbackButton({ children, ...props }, ref) {\n return React.createElement(\n 'button',\n {\n ref,\n type: 'button',\n 'aria-label': 'Send feedback',\n ...props,\n },\n children ?? 'Feedback',\n )\n },\n)\n"],
5
+ "mappings": "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",
6
+ "names": ["FeedbackButton"]
7
+ }
@@ -0,0 +1,376 @@
1
+ import {
2
+ cn,
3
+ cva
4
+ } from "./chunk-ZF3OHCGV.js";
5
+
6
+ // ../react-file-tree/dist/index.js
7
+ import * as React from "react";
8
+
9
+ // ../file-tree/dist/index.js
10
+ function arrayEquals(a, b) {
11
+ return a.length === b.length && a.every((v, i) => v === b[i]);
12
+ }
13
+ function createFileTree(config = {}) {
14
+ let nodes = config.nodes ?? [];
15
+ let ariaLabel = config["aria-label"] ?? "File tree";
16
+ let onExpandedChange = config.onExpandedChange;
17
+ let onSelectionChange = config.onSelectionChange;
18
+ let uncontrolledExpanded = config.defaultExpandedIds ?? [];
19
+ let controlledExpanded = config.expandedIds;
20
+ let uncontrolledSelected = config.defaultSelectedId ?? null;
21
+ let controlledSelected = config.selectedId;
22
+ let focusedId = null;
23
+ let parentById = /* @__PURE__ */ new Map();
24
+ let nodeById = /* @__PURE__ */ new Map();
25
+ function reindex() {
26
+ parentById = /* @__PURE__ */ new Map();
27
+ nodeById = /* @__PURE__ */ new Map();
28
+ const walk = (list, parentId) => {
29
+ for (const node of list) {
30
+ nodeById.set(node.id, node);
31
+ parentById.set(node.id, parentId);
32
+ if (node.children) walk(node.children, node.id);
33
+ }
34
+ };
35
+ walk(nodes, null);
36
+ }
37
+ reindex();
38
+ const listeners = /* @__PURE__ */ new Set();
39
+ let snapshot = buildSnapshot();
40
+ let visibleItems = buildVisibleItems();
41
+ function expandedIds() {
42
+ return controlledExpanded !== void 0 ? controlledExpanded : uncontrolledExpanded;
43
+ }
44
+ function selectedId() {
45
+ return controlledSelected !== void 0 ? controlledSelected : uncontrolledSelected;
46
+ }
47
+ function buildSnapshot() {
48
+ return {
49
+ nodes,
50
+ expandedIds: expandedIds(),
51
+ selectedId: selectedId(),
52
+ focusedId
53
+ };
54
+ }
55
+ function buildVisibleItems() {
56
+ const expanded = new Set(expandedIds());
57
+ const selected = selectedId();
58
+ const items = [];
59
+ const walk = (list, parentId, depth) => {
60
+ for (const node of list) {
61
+ const hasChildren = Boolean(node.children && node.children.length > 0);
62
+ const isExpanded = hasChildren && expanded.has(node.id);
63
+ items.push({
64
+ node,
65
+ parentId,
66
+ depth,
67
+ hasChildren,
68
+ isExpanded,
69
+ isSelected: node.id === selected,
70
+ isFocused: node.id === focusedId
71
+ });
72
+ if (hasChildren && isExpanded) walk(node.children, node.id, depth + 1);
73
+ }
74
+ };
75
+ walk(nodes, null, 1);
76
+ return items;
77
+ }
78
+ function emit() {
79
+ snapshot = buildSnapshot();
80
+ visibleItems = buildVisibleItems();
81
+ for (const l of listeners) l();
82
+ }
83
+ function setExpanded(ids) {
84
+ if (controlledExpanded === void 0) {
85
+ if (arrayEquals(uncontrolledExpanded, ids)) return;
86
+ uncontrolledExpanded = ids;
87
+ }
88
+ onExpandedChange?.(ids);
89
+ emit();
90
+ }
91
+ function isExpandable(id) {
92
+ const node = nodeById.get(id);
93
+ return Boolean(node && !node.disabled && node.children && node.children.length > 0);
94
+ }
95
+ const api = {
96
+ getState() {
97
+ return snapshot;
98
+ },
99
+ subscribe(listener) {
100
+ listeners.add(listener);
101
+ return () => listeners.delete(listener);
102
+ },
103
+ getVisibleItems() {
104
+ return visibleItems;
105
+ },
106
+ isExpanded(id) {
107
+ return expandedIds().includes(id);
108
+ },
109
+ toggle(id) {
110
+ if (!isExpandable(id)) return;
111
+ const current = expandedIds();
112
+ setExpanded(current.includes(id) ? current.filter((v) => v !== id) : [...current, id]);
113
+ },
114
+ expand(id) {
115
+ if (!isExpandable(id)) return;
116
+ const current = expandedIds();
117
+ if (current.includes(id)) return;
118
+ setExpanded([...current, id]);
119
+ },
120
+ collapse(id) {
121
+ const current = expandedIds();
122
+ if (!current.includes(id)) return;
123
+ setExpanded(current.filter((v) => v !== id));
124
+ },
125
+ select(id) {
126
+ if (id !== null) {
127
+ const node = nodeById.get(id);
128
+ if (!node || node.disabled) return;
129
+ }
130
+ if (controlledSelected === void 0) {
131
+ if (uncontrolledSelected === id) return;
132
+ uncontrolledSelected = id;
133
+ }
134
+ onSelectionChange?.(id);
135
+ emit();
136
+ },
137
+ focus(id) {
138
+ if (id !== null && !visibleItems.some((i) => i.node.id === id)) return;
139
+ if (focusedId === id) return;
140
+ focusedId = id;
141
+ emit();
142
+ },
143
+ handleKey(key) {
144
+ const items = visibleItems;
145
+ if (items.length === 0) return;
146
+ const currentIndex = focusedId ? items.findIndex((i) => i.node.id === focusedId) : -1;
147
+ switch (key) {
148
+ case "ArrowDown":
149
+ api.focus(items[Math.min(currentIndex + 1, items.length - 1)].node.id);
150
+ return;
151
+ case "ArrowUp":
152
+ api.focus(items[Math.max(currentIndex - 1, 0)].node.id);
153
+ return;
154
+ case "Home":
155
+ api.focus(items[0].node.id);
156
+ return;
157
+ case "End":
158
+ api.focus(items[items.length - 1].node.id);
159
+ return;
160
+ case "ArrowRight": {
161
+ const item = currentIndex === -1 ? void 0 : items[currentIndex];
162
+ if (!item) {
163
+ api.focus(items[0].node.id);
164
+ return;
165
+ }
166
+ if (!item.hasChildren) return;
167
+ if (!item.isExpanded) api.expand(item.node.id);
168
+ else api.focus(items[currentIndex + 1]?.node.id ?? item.node.id);
169
+ return;
170
+ }
171
+ case "ArrowLeft": {
172
+ const item = currentIndex === -1 ? void 0 : items[currentIndex];
173
+ if (!item) return;
174
+ if (item.hasChildren && item.isExpanded) api.collapse(item.node.id);
175
+ else if (item.parentId) api.focus(item.parentId);
176
+ return;
177
+ }
178
+ case "Enter":
179
+ case " ": {
180
+ const item = currentIndex === -1 ? void 0 : items[currentIndex];
181
+ if (item) api.select(item.node.id);
182
+ return;
183
+ }
184
+ default:
185
+ return;
186
+ }
187
+ },
188
+ setNodes(nextNodes) {
189
+ nodes = nextNodes;
190
+ reindex();
191
+ emit();
192
+ },
193
+ setExpandedIds(ids) {
194
+ if (controlledExpanded !== void 0 && arrayEquals(controlledExpanded, ids)) return;
195
+ controlledExpanded = ids;
196
+ emit();
197
+ },
198
+ setSelectedId(id) {
199
+ if (controlledSelected !== void 0 && controlledSelected === id) return;
200
+ controlledSelected = id;
201
+ emit();
202
+ },
203
+ setOptions(options) {
204
+ if (options.onExpandedChange !== void 0) onExpandedChange = options.onExpandedChange;
205
+ if (options.onSelectionChange !== void 0) onSelectionChange = options.onSelectionChange;
206
+ if (options["aria-label"] !== void 0) ariaLabel = options["aria-label"];
207
+ },
208
+ getTreeAria() {
209
+ return { role: "tree", "aria-label": ariaLabel };
210
+ },
211
+ getItemAria(item) {
212
+ const aria = {
213
+ role: "treeitem",
214
+ "aria-level": item.depth,
215
+ "aria-selected": item.isSelected
216
+ };
217
+ if (item.hasChildren) aria["aria-expanded"] = item.isExpanded;
218
+ if (item.node.disabled) aria["aria-disabled"] = true;
219
+ return aria;
220
+ }
221
+ };
222
+ return api;
223
+ }
224
+ var fileTreeVariants = cva({
225
+ base: "w-full text-sm"
226
+ });
227
+ var fileTreeItemVariants = cva({
228
+ base: [
229
+ "flex w-full cursor-pointer select-none items-center gap-1.5 rounded-md px-2 py-1",
230
+ "text-sm outline-none transition-colors",
231
+ "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background",
232
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50"
233
+ ].join(" "),
234
+ variants: {
235
+ selected: {
236
+ true: "bg-accent text-accent-foreground",
237
+ false: "text-foreground hover:bg-muted"
238
+ }
239
+ },
240
+ defaultVariants: {
241
+ selected: "false"
242
+ }
243
+ });
244
+ var fileTreeGlyphClass = "w-4 shrink-0 text-center text-muted-foreground";
245
+
246
+ // ../react-file-tree/dist/index.js
247
+ import { jsx, Fragment, jsxs } from "react/jsx-runtime";
248
+ var HANDLED_KEYS = /* @__PURE__ */ new Set([
249
+ "ArrowDown",
250
+ "ArrowUp",
251
+ "ArrowLeft",
252
+ "ArrowRight",
253
+ "Home",
254
+ "End",
255
+ "Enter",
256
+ " "
257
+ ]);
258
+ function TreeItems({ nodes, depth, api, state, firstVisibleId }) {
259
+ return /* @__PURE__ */ jsx(Fragment, { children: nodes.map((node) => {
260
+ const hasChildren = Boolean(node.children && node.children.length > 0);
261
+ const isExpanded = hasChildren && state.expandedIds.includes(node.id);
262
+ const isSelected = state.selectedId === node.id;
263
+ const item = {
264
+ node,
265
+ parentId: null,
266
+ // unused by getItemAria; the core tracks real parents
267
+ depth,
268
+ hasChildren,
269
+ isExpanded,
270
+ isSelected,
271
+ isFocused: state.focusedId === node.id
272
+ };
273
+ const tabbable = state.focusedId === node.id || state.focusedId === null && node.id === firstVisibleId;
274
+ return /* @__PURE__ */ jsxs("li", { role: "none", className: "list-none", children: [
275
+ /* @__PURE__ */ jsxs(
276
+ "div",
277
+ {
278
+ ...api.getItemAria(item),
279
+ tabIndex: tabbable ? 0 : -1,
280
+ "data-disabled": node.disabled ? "true" : void 0,
281
+ style: { paddingLeft: `${(depth - 1) * 12}px` },
282
+ className: fileTreeItemVariants({ selected: isSelected ? "true" : "false" }),
283
+ onClick: () => {
284
+ api.focus(node.id);
285
+ api.select(node.id);
286
+ if (hasChildren) api.toggle(node.id);
287
+ },
288
+ onFocus: () => api.focus(node.id),
289
+ children: [
290
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: fileTreeGlyphClass, children: hasChildren ? isExpanded ? "\u25BE" : "\u25B8" : "\xB7" }),
291
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: node.label })
292
+ ]
293
+ }
294
+ ),
295
+ hasChildren && isExpanded && /* @__PURE__ */ jsx("ul", { role: "group", className: "m-0 p-0", children: /* @__PURE__ */ jsx(
296
+ TreeItems,
297
+ {
298
+ nodes: node.children,
299
+ depth: depth + 1,
300
+ api,
301
+ state,
302
+ firstVisibleId
303
+ }
304
+ ) })
305
+ ] }, node.id);
306
+ }) });
307
+ }
308
+ var FileTree = React.forwardRef(
309
+ function FileTree2({
310
+ className,
311
+ nodes = [],
312
+ expandedIds: controlledExpandedIds,
313
+ defaultExpandedIds,
314
+ selectedId: controlledSelectedId,
315
+ defaultSelectedId,
316
+ onExpandedChange,
317
+ onSelectionChange,
318
+ "aria-label": ariaLabel,
319
+ ...props
320
+ }, ref) {
321
+ const apiRef = React.useRef(null);
322
+ if (apiRef.current === null) {
323
+ apiRef.current = createFileTree({
324
+ nodes,
325
+ expandedIds: controlledExpandedIds,
326
+ defaultExpandedIds,
327
+ selectedId: controlledSelectedId,
328
+ defaultSelectedId,
329
+ onExpandedChange,
330
+ onSelectionChange,
331
+ "aria-label": ariaLabel
332
+ });
333
+ }
334
+ const api = apiRef.current;
335
+ const state = React.useSyncExternalStore(api.subscribe, api.getState, api.getState);
336
+ React.useEffect(() => {
337
+ api.setOptions({ onExpandedChange, onSelectionChange, "aria-label": ariaLabel });
338
+ });
339
+ React.useEffect(() => {
340
+ api.setNodes(nodes);
341
+ }, [api, nodes]);
342
+ React.useEffect(() => {
343
+ if (controlledExpandedIds !== void 0) api.setExpandedIds(controlledExpandedIds);
344
+ }, [api, controlledExpandedIds]);
345
+ React.useEffect(() => {
346
+ if (controlledSelectedId !== void 0) api.setSelectedId(controlledSelectedId);
347
+ }, [api, controlledSelectedId]);
348
+ const firstVisibleId = api.getVisibleItems()[0]?.node.id;
349
+ return /* @__PURE__ */ jsx("div", { ref, className: cn(fileTreeVariants(), className), ...props, children: /* @__PURE__ */ jsx(
350
+ "ul",
351
+ {
352
+ ...api.getTreeAria(),
353
+ className: "m-0 p-0",
354
+ onKeyDown: (event) => {
355
+ if (!HANDLED_KEYS.has(event.key)) return;
356
+ event.preventDefault();
357
+ api.handleKey(event.key);
358
+ },
359
+ children: /* @__PURE__ */ jsx(
360
+ TreeItems,
361
+ {
362
+ nodes: state.nodes,
363
+ depth: 1,
364
+ api,
365
+ state,
366
+ firstVisibleId
367
+ }
368
+ )
369
+ }
370
+ ) });
371
+ }
372
+ );
373
+ export {
374
+ FileTree
375
+ };
376
+ //# sourceMappingURL=react-file-tree.js.map