@mova-ui/react 0.4.10 → 0.4.11

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 (512) hide show
  1. package/dist/catalog/components/cards/CardTimeMachine.d.ts +7 -0
  2. package/dist/catalog/components/cards/CardTimeMachine.js +14 -11
  3. package/dist/catalog/components/dither-charts/DitherBook.d.ts +5 -2
  4. package/dist/catalog/components/dither-charts/DitherBook.js +35 -27
  5. package/dist/catalog/components/dither-charts/DitherChartsGrid.js +3 -3
  6. package/dist/catalog/components/simple-comp/DitherChartsGrid.js +3 -3
  7. package/dist/catalog/data/ditherCharts.js +3 -3
  8. package/dist/catalog/data/formElements.js +2 -2
  9. package/dist/catalog/data/installCommand.js +2 -2
  10. package/dist/catalog/data/metrics.js +2 -2
  11. package/dist/catalog/data/supportedRegistryIds.js +1 -1
  12. package/dist/catalog/data/textAnimations.js +2 -2
  13. package/dist/catalog/data/toggles.js +2 -2
  14. package/dist/catalog/data/transitions.js +2 -2
  15. package/dist/catalog-chunks/{chunk-YPZZOKH4.js → chunk-CQ7VYA46.js} +7 -0
  16. package/dist/catalog-chunks/{chunk-6NP66VN5.js → chunk-EYGZ2KK7.js} +1 -1
  17. package/dist/catalog-chunks/{chunk-WKFJSUM3.js → chunk-PMFHIVMP.js} +1 -1
  18. package/dist/index.d.ts +7 -0
  19. package/dist/index.js +2149 -143
  20. package/dist/styles.css +1 -1
  21. package/dist/ui/patterns/animated-mega-menu.d.ts +23 -0
  22. package/dist/ui/patterns/blur-carousel.d.ts +44 -0
  23. package/dist/ui/patterns/compare-slider.d.ts +15 -0
  24. package/dist/ui/patterns/fold-panel.d.ts +15 -0
  25. package/dist/ui/patterns/gesture-range-slider.d.ts +21 -0
  26. package/dist/ui/patterns/long-press-context-menu.d.ts +48 -0
  27. package/dist/ui/patterns/split-view.d.ts +17 -0
  28. package/package.json +1 -1
  29. package/registry/1.json +1 -1
  30. package/registry/10.json +1 -1
  31. package/registry/11.json +1 -1
  32. package/registry/12.json +1 -1
  33. package/registry/13.json +1 -1
  34. package/registry/14.json +1 -1
  35. package/registry/15.json +1 -1
  36. package/registry/16.json +1 -1
  37. package/registry/17.json +1 -1
  38. package/registry/18.json +1 -1
  39. package/registry/19.json +1 -1
  40. package/registry/2.json +1 -1
  41. package/registry/20.json +1 -1
  42. package/registry/21.json +1 -1
  43. package/registry/22.json +1 -1
  44. package/registry/23.json +1 -1
  45. package/registry/24.json +1 -1
  46. package/registry/25.json +1 -1
  47. package/registry/26.json +1 -1
  48. package/registry/27.json +1 -1
  49. package/registry/28.json +1 -1
  50. package/registry/29.json +1 -1
  51. package/registry/3.json +1 -1
  52. package/registry/30.json +1 -1
  53. package/registry/31.json +1 -1
  54. package/registry/32.json +1 -1
  55. package/registry/33.json +1 -1
  56. package/registry/34.json +1 -1
  57. package/registry/35.json +1 -1
  58. package/registry/36.json +1 -1
  59. package/registry/37.json +1 -1
  60. package/registry/4.json +1 -1
  61. package/registry/5.json +1 -1
  62. package/registry/6.json +1 -1
  63. package/registry/7.json +1 -1
  64. package/registry/8.json +1 -1
  65. package/registry/9.json +1 -1
  66. package/registry/LICENSE.third-party +52 -0
  67. package/registry/ab-segmented-tabs.json +1 -1
  68. package/registry/accordion-blind.json +1 -1
  69. package/registry/accordion-loader.json +1 -1
  70. package/registry/ai-approval-card.json +1 -1
  71. package/registry/ai-code-block.json +1 -1
  72. package/registry/ai-context-meter.json +1 -1
  73. package/registry/ai-fine-tune-card.json +1 -1
  74. package/registry/ai-prompt-bar.json +1 -1
  75. package/registry/ai-sidebar-nav.json +1 -1
  76. package/registry/ai-sources.json +1 -1
  77. package/registry/ai-suggestions.json +1 -1
  78. package/registry/ai-task-list.json +1 -1
  79. package/registry/ai-tool-call.json +1 -1
  80. package/registry/analyzing-image.json +1 -1
  81. package/registry/animated-mega-menu.json +21 -0
  82. package/registry/animated-sidebar.json +1 -1
  83. package/registry/animated-tags.json +1 -1
  84. package/registry/app-icon-load.json +1 -1
  85. package/registry/apple-breathe.json +1 -1
  86. package/registry/apple-equalizer.json +1 -1
  87. package/registry/apple-icon-morph.json +1 -1
  88. package/registry/apple-pulse-dots.json +1 -1
  89. package/registry/apple-scale-pulse.json +1 -1
  90. package/registry/apple-sound-wave.json +1 -1
  91. package/registry/apple-text-reveal.json +1 -1
  92. package/registry/apple-unlock.json +1 -1
  93. package/registry/arc-tracer.json +1 -1
  94. package/registry/balance-bar-chart-card.json +1 -1
  95. package/registry/bar-cascade.json +1 -1
  96. package/registry/bar-sweep.json +1 -1
  97. package/registry/blur-carousel.json +18 -0
  98. package/registry/blur-text.json +1 -1
  99. package/registry/blur-up-char.json +1 -1
  100. package/registry/blur-up-word.json +1 -1
  101. package/registry/bobbing-dots.json +1 -1
  102. package/registry/bookmark-corner-peel.json +1 -1
  103. package/registry/bookmark-save-pill.json +1 -1
  104. package/registry/bookmark-toggle.json +1 -1
  105. package/registry/border-trail-loading.json +1 -1
  106. package/registry/bounce-dots.json +1 -1
  107. package/registry/bounce-in-char.json +1 -1
  108. package/registry/bouncing-bars.json +1 -1
  109. package/registry/bouncing-dots.json +1 -1
  110. package/registry/bouncing-lines.json +1 -1
  111. package/registry/bouncing-square.json +1 -1
  112. package/registry/breathe-ring.json +1 -1
  113. package/registry/breathing-glow.json +1 -1
  114. package/registry/breathing-square.json +1 -1
  115. package/registry/btn-1.json +1 -1
  116. package/registry/btn-10.json +1 -1
  117. package/registry/btn-11.json +1 -1
  118. package/registry/btn-12.json +1 -1
  119. package/registry/btn-13.json +1 -1
  120. package/registry/btn-14.json +1 -1
  121. package/registry/btn-15.json +1 -1
  122. package/registry/btn-16.json +1 -1
  123. package/registry/btn-17.json +1 -1
  124. package/registry/btn-18.json +1 -1
  125. package/registry/btn-19.json +1 -1
  126. package/registry/btn-2.json +1 -1
  127. package/registry/btn-20.json +1 -1
  128. package/registry/btn-21.json +1 -1
  129. package/registry/btn-22.json +1 -1
  130. package/registry/btn-23.json +1 -1
  131. package/registry/btn-24.json +1 -1
  132. package/registry/btn-25.json +1 -1
  133. package/registry/btn-26.json +1 -1
  134. package/registry/btn-27.json +1 -1
  135. package/registry/btn-28.json +1 -1
  136. package/registry/btn-29.json +1 -1
  137. package/registry/btn-3.json +1 -1
  138. package/registry/btn-30.json +1 -1
  139. package/registry/btn-31.json +1 -1
  140. package/registry/btn-32.json +1 -1
  141. package/registry/btn-33.json +1 -1
  142. package/registry/btn-34.json +1 -1
  143. package/registry/btn-35.json +1 -1
  144. package/registry/btn-36.json +1 -1
  145. package/registry/btn-37.json +1 -1
  146. package/registry/btn-4.json +1 -1
  147. package/registry/btn-5.json +1 -1
  148. package/registry/btn-6.json +1 -1
  149. package/registry/btn-7.json +1 -1
  150. package/registry/btn-8.json +1 -1
  151. package/registry/btn-9.json +1 -1
  152. package/registry/button-slide-arrow.json +1 -1
  153. package/registry/cacheable-bandwidth-cost.json +1 -1
  154. package/registry/calendar-day-card.json +1 -1
  155. package/registry/card-arc-5.json +1 -1
  156. package/registry/card-arc-7.json +1 -1
  157. package/registry/card-carousel-mono.json +1 -1
  158. package/registry/card-carousel.json +1 -1
  159. package/registry/card-cascade-stagger.json +1 -1
  160. package/registry/card-corner-fan.json +1 -1
  161. package/registry/card-cover-flow-mono.json +1 -1
  162. package/registry/card-cover-flow.json +1 -1
  163. package/registry/card-deck-cascade.json +1 -1
  164. package/registry/card-glance-preview.json +1 -1
  165. package/registry/card-hover.json +1 -1
  166. package/registry/card-linear-spread.json +1 -1
  167. package/registry/card-long-arc-5.json +1 -1
  168. package/registry/card-scatter-spread.json +1 -1
  169. package/registry/card-stack-peel.json +1 -1
  170. package/registry/card-stamp-arc.json +1 -1
  171. package/registry/card-time-machine-mono.json +1 -1
  172. package/registry/card-time-machine.json +1 -1
  173. package/registry/card-wheel-fan.json +1 -1
  174. package/registry/category-select.json +1 -1
  175. package/registry/character-stagger.json +1 -1
  176. package/registry/checkbox-draw.json +1 -1
  177. package/registry/checkmark-draw.json +1 -1
  178. package/registry/circle-toggle.json +1 -1
  179. package/registry/circuit-trace-draw.json +1 -1
  180. package/registry/circular-bars.json +1 -1
  181. package/registry/circular-create-button.json +1 -1
  182. package/registry/classic-spinner.json +1 -1
  183. package/registry/classic-toggle.json +1 -1
  184. package/registry/clock-spinner.json +1 -1
  185. package/registry/comet-spinner.json +1 -1
  186. package/registry/compare-slider.json +19 -0
  187. package/registry/compass-needle-deflect.json +1 -1
  188. package/registry/concentric-pulse.json +1 -1
  189. package/registry/concentric-ring.json +1 -1
  190. package/registry/concentric-squares.json +1 -1
  191. package/registry/context-menu.json +1 -1
  192. package/registry/conveyor-loop.json +1 -1
  193. package/registry/credit-score-barcode-meter.json +1 -1
  194. package/registry/cross-spinner.json +1 -1
  195. package/registry/cube-flip-spring.json +1 -1
  196. package/registry/cursor-trail.json +1 -1
  197. package/registry/dash-ring.json +1 -1
  198. package/registry/dashed-spiral.json +1 -1
  199. package/registry/date-position-selector.json +1 -1
  200. package/registry/day-trading-order-ticket.json +1 -1
  201. package/registry/dia-text-reveal.json +1 -1
  202. package/registry/diamond-grid.json +1 -1
  203. package/registry/diamond-rotate-spring.json +1 -1
  204. package/registry/dislike-toggle.json +1 -1
  205. package/registry/dither-book.json +1 -1
  206. package/registry/domino-cascade.json +1 -1
  207. package/registry/dot-spinner.json +1 -1
  208. package/registry/dots-ring.json +1 -1
  209. package/registry/double-bounce-toggle.json +1 -1
  210. package/registry/double-ring.json +1 -1
  211. package/registry/download-icons.json +1 -1
  212. package/registry/drop-dot.json +1 -1
  213. package/registry/drop-in-char.json +1 -1
  214. package/registry/droplet-squish.json +1 -1
  215. package/registry/dual-arc.json +1 -1
  216. package/registry/dual-magnet-dipole.json +1 -1
  217. package/registry/dynamic-island.json +1 -1
  218. package/registry/elastic-bars.json +1 -1
  219. package/registry/elastic-square.json +1 -1
  220. package/registry/elastic-tag-snap.json +1 -1
  221. package/registry/error-shake.json +1 -1
  222. package/registry/expanding-cross.json +1 -1
  223. package/registry/expanding-icon-tabs.json +1 -1
  224. package/registry/face-id-scan.json +1 -1
  225. package/registry/fade-arc.json +1 -1
  226. package/registry/fade-dots.json +1 -1
  227. package/registry/fade-down.json +1 -1
  228. package/registry/fade-in-char.json +1 -1
  229. package/registry/fade-in-text.json +1 -1
  230. package/registry/fade-in-word.json +1 -1
  231. package/registry/fade-in.json +1 -1
  232. package/registry/fade-up.json +1 -1
  233. package/registry/file-upload-dropzone.json +1 -1
  234. package/registry/filter-tag-pill.json +1 -1
  235. package/registry/flip-square.json +1 -1
  236. package/registry/flip-x-char.json +1 -1
  237. package/registry/flip-y-char.json +1 -1
  238. package/registry/float-char.json +1 -1
  239. package/registry/float-word.json +1 -1
  240. package/registry/floating-diamonds.json +1 -1
  241. package/registry/floating-label-input.json +1 -1
  242. package/registry/fluid-bars.json +1 -1
  243. package/registry/fluid-diamond.json +1 -1
  244. package/registry/fluid-dot-orbit.json +1 -1
  245. package/registry/fluid-skeleton.json +1 -1
  246. package/registry/focus-blur.json +1 -1
  247. package/registry/fold-panel.json +19 -0
  248. package/registry/form-submit-button.json +1 -1
  249. package/registry/french-doors-3d.json +1 -1
  250. package/registry/gear-tooth-step.json +1 -1
  251. package/registry/gears.json +1 -1
  252. package/registry/gelatin-wobble.json +1 -1
  253. package/registry/geometric-iris-shutter.json +1 -1
  254. package/registry/gesture-range-slider.json +18 -0
  255. package/registry/glassmorphic-card.json +1 -1
  256. package/registry/glow-button.json +1 -1
  257. package/registry/glow-text.json +1 -1
  258. package/registry/gooey-popover.json +1 -1
  259. package/registry/gradient-arc.json +1 -1
  260. package/registry/gradient-shimmer.json +1 -1
  261. package/registry/grid-dots.json +1 -1
  262. package/registry/haptic-ring.json +1 -1
  263. package/registry/heartbeat.json +1 -1
  264. package/registry/hex-lattice-draw.json +1 -1
  265. package/registry/hexagon-spinner.json +1 -1
  266. package/registry/hourglass.json +1 -1
  267. package/registry/hover-lift-char.json +1 -1
  268. package/registry/hover-lift-word.json +1 -1
  269. package/registry/hover-link-card.json +1 -1
  270. package/registry/hover-scale-char.json +1 -1
  271. package/registry/hover-scale-word.json +1 -1
  272. package/registry/imessage-chat.json +1 -1
  273. package/registry/inertia-skid-stop.json +1 -1
  274. package/registry/infinity-path.json +1 -1
  275. package/registry/input-focus-glow.json +1 -1
  276. package/registry/inset-action-button.json +1 -1
  277. package/registry/inset-button.json +1 -1
  278. package/registry/intersecting-rings.json +1 -1
  279. package/registry/ios-spinner.json +1 -1
  280. package/registry/kinetic-metronome-tick.json +1 -1
  281. package/registry/kinetic-tension-capsule.json +1 -1
  282. package/registry/light-dark-morph.json +1 -1
  283. package/registry/like-toggle.json +1 -1
  284. package/registry/line-spinner.json +1 -1
  285. package/registry/liquid-dots.json +1 -1
  286. package/registry/liquid-glass-sheet.json +1 -1
  287. package/registry/long-press-context-menu.json +19 -0
  288. package/registry/mac-terminal.json +1 -1
  289. package/registry/magnetic-button.json +1 -1
  290. package/registry/magnetic-disks.json +1 -1
  291. package/registry/magnetic-dots.json +1 -1
  292. package/registry/magnetic-slide-btn.json +1 -1
  293. package/registry/manifest.json +785 -652
  294. package/registry/matrix-grid-loader.json +1 -1
  295. package/registry/minimal-triangle.json +1 -1
  296. package/registry/modular-tile-snap.json +1 -1
  297. package/registry/mono-activity-blue.json +1 -1
  298. package/registry/mono-activity-green.json +1 -1
  299. package/registry/mono-activity-purple.json +1 -1
  300. package/registry/mono-heatmap.json +1 -1
  301. package/registry/mono-rounded-area.json +1 -1
  302. package/registry/mono-rounded-bar.json +1 -1
  303. package/registry/mono-rounded-bubble.json +1 -1
  304. package/registry/mono-rounded-bullet.json +1 -1
  305. package/registry/mono-rounded-candlestick.json +1 -1
  306. package/registry/mono-rounded-composed.json +1 -1
  307. package/registry/mono-rounded-donut.json +1 -1
  308. package/registry/mono-rounded-funnel.json +1 -1
  309. package/registry/mono-rounded-gauge-arc.json +1 -1
  310. package/registry/mono-rounded-heatmap.json +1 -1
  311. package/registry/mono-rounded-kpi.json +1 -1
  312. package/registry/mono-rounded-line.json +1 -1
  313. package/registry/mono-rounded-meter.json +1 -1
  314. package/registry/mono-rounded-polar.json +1 -1
  315. package/registry/mono-rounded-pyramid.json +1 -1
  316. package/registry/mono-rounded-radar.json +1 -1
  317. package/registry/mono-rounded-radial-gauge.json +1 -1
  318. package/registry/mono-rounded-radial-group.json +1 -1
  319. package/registry/mono-rounded-range.json +1 -1
  320. package/registry/mono-rounded-sankey.json +1 -1
  321. package/registry/mono-rounded-scatter.json +1 -1
  322. package/registry/mono-rounded-sparkline.json +1 -1
  323. package/registry/mono-rounded-stacked-bar.json +1 -1
  324. package/registry/mono-rounded-step.json +1 -1
  325. package/registry/mono-rounded-stream.json +1 -1
  326. package/registry/mono-rounded-treemap.json +1 -1
  327. package/registry/mono-rounded-waterfall.json +1 -1
  328. package/registry/mono-stock.json +1 -1
  329. package/registry/morph-action-pill.json +1 -1
  330. package/registry/morph-dot-ring.json +1 -1
  331. package/registry/morph-loader.json +1 -1
  332. package/registry/morph-toggle.json +1 -1
  333. package/registry/morphing-bars.json +1 -1
  334. package/registry/morphing-infinity.json +1 -1
  335. package/registry/morphing-ring.json +1 -1
  336. package/registry/morphing-shape.json +1 -1
  337. package/registry/mouse-follow.json +1 -1
  338. package/registry/multi-select-chips.json +1 -1
  339. package/registry/multi-tab-bar.json +1 -1
  340. package/registry/neon-sign-draw.json +1 -1
  341. package/registry/nested-orbital-gimbal.json +1 -1
  342. package/registry/network-telemetry-matrix.json +1 -1
  343. package/registry/newtons-cradle.json +1 -1
  344. package/registry/noise-decibel-level.json +1 -1
  345. package/registry/obsidian-liquid-wave.json +1 -1
  346. package/registry/offset-rings.json +1 -1
  347. package/registry/orbiting-circles.json +1 -1
  348. package/registry/orbiting-dot.json +1 -1
  349. package/registry/origami-envelope-unfold.json +1 -1
  350. package/registry/origami-shape.json +1 -1
  351. package/registry/otp-input.json +1 -1
  352. package/registry/overview-bar-scrubber-card.json +1 -1
  353. package/registry/page-transition.json +1 -1
  354. package/registry/page-turn-curl.json +1 -1
  355. package/registry/password-toggle.json +1 -1
  356. package/registry/pendulum-bubble-level.json +1 -1
  357. package/registry/pendulum.json +1 -1
  358. package/registry/perspective-flip-stage.json +1 -1
  359. package/registry/perspective-flip.json +1 -1
  360. package/registry/perspective-layout-switcher.json +1 -1
  361. package/registry/physics-dock.json +1 -1
  362. package/registry/pill-tabs.json +1 -1
  363. package/registry/plus-minus-toggle.json +1 -1
  364. package/registry/presets.json +1 -1
  365. package/registry/prism-block-stack.json +1 -1
  366. package/registry/progress-indicator-piano.json +1 -1
  367. package/registry/progress-indicator.json +1 -1
  368. package/registry/progress-stepper.json +1 -1
  369. package/registry/pulsating-dots.json +1 -1
  370. package/registry/pulse-char.json +1 -1
  371. package/registry/pulse-dot.json +1 -1
  372. package/registry/pulse-dots.json +1 -1
  373. package/registry/pulse-square.json +1 -1
  374. package/registry/pulse-word.json +1 -1
  375. package/registry/pulse.json +1 -1
  376. package/registry/pumping-heart.json +1 -1
  377. package/registry/pyramid-block-build.json +1 -1
  378. package/registry/radar-sweep.json +1 -1
  379. package/registry/radial-iris-mask.json +1 -1
  380. package/registry/radial-spinner.json +1 -1
  381. package/registry/radio-scale.json +1 -1
  382. package/registry/range-slider.json +1 -1
  383. package/registry/receipt-tape-print.json +1 -1
  384. package/registry/rectangle-toggle.json +1 -1
  385. package/registry/repost-toggle.json +1 -1
  386. package/registry/reveal-text.json +1 -1
  387. package/registry/ribbon-banner-slide.json +1 -1
  388. package/registry/ring-sweep.json +1 -1
  389. package/registry/ripple-effect.json +1 -1
  390. package/registry/rise-up-word.json +1 -1
  391. package/registry/roller-blind-drop.json +1 -1
  392. package/registry/rolling-tumble.json +1 -1
  393. package/registry/rotate-in-char.json +1 -1
  394. package/registry/rotating-cross.json +1 -1
  395. package/registry/rotating-louvers.json +1 -1
  396. package/registry/rotating-triangle.json +1 -1
  397. package/registry/rudder-issue-board.json +1 -1
  398. package/registry/sales-analytics-dual-bars.json +1 -1
  399. package/registry/sales-overview-radial-dashboard.json +1 -1
  400. package/registry/sales-target-segmented-arc.json +1 -1
  401. package/registry/scale-in-char.json +1 -1
  402. package/registry/scale-in-text.json +1 -1
  403. package/registry/scale-in-word.json +1 -1
  404. package/registry/scale-in.json +1 -1
  405. package/registry/scramble-text.json +1 -1
  406. package/registry/scroll-canvas-unroll.json +1 -1
  407. package/registry/scroll-reveal.json +1 -1
  408. package/registry/search-expand.json +1 -1
  409. package/registry/segmented-arc-meter.json +1 -1
  410. package/registry/segmented-link-stretch.json +1 -1
  411. package/registry/segmented-step-bar.json +1 -1
  412. package/registry/segmented-stepper-dots.json +1 -1
  413. package/registry/select-dropdown.json +1 -1
  414. package/registry/server-performance-step-bars.json +1 -1
  415. package/registry/shape-shift-grid.json +1 -1
  416. package/registry/shimmer-line.json +1 -1
  417. package/registry/shimmer-text.json +1 -1
  418. package/registry/shutter-slide.json +1 -1
  419. package/registry/shutter-step-slices.json +1 -1
  420. package/registry/siri-wave.json +1 -1
  421. package/registry/skeleton-loader.json +1 -1
  422. package/registry/skeleton.json +1 -1
  423. package/registry/skew-x-char.json +1 -1
  424. package/registry/slide-down-char.json +1 -1
  425. package/registry/slide-down-word.json +1 -1
  426. package/registry/slide-left-char.json +1 -1
  427. package/registry/slide-left.json +1 -1
  428. package/registry/slide-right-char.json +1 -1
  429. package/registry/slide-right.json +1 -1
  430. package/registry/slide-up-char.json +1 -1
  431. package/registry/slide-up-text.json +1 -1
  432. package/registry/slide-up-word.json +1 -1
  433. package/registry/sliding-bars.json +1 -1
  434. package/registry/slinky-coil.json +1 -1
  435. package/registry/smart-card-dispenser.json +1 -1
  436. package/registry/smooth-dot-shift.json +1 -1
  437. package/registry/smooth-ring.json +1 -1
  438. package/registry/smooth-rounded-square.json +1 -1
  439. package/registry/solid-switch.json +1 -1
  440. package/registry/spatial-door-portal.json +1 -1
  441. package/registry/spinning-squares.json +1 -1
  442. package/registry/spiral-spinner.json +1 -1
  443. package/registry/split-gate-reveal.json +1 -1
  444. package/registry/split-view.json +18 -0
  445. package/registry/spotlight.json +1 -1
  446. package/registry/spring-bars.json +1 -1
  447. package/registry/spring-dot-matrix.json +1 -1
  448. package/registry/spring-hexagon.json +1 -1
  449. package/registry/spring-ring-expand.json +1 -1
  450. package/registry/spring-text-pop.json +1 -1
  451. package/registry/spring-text.json +1 -1
  452. package/registry/square-accordion.json +1 -1
  453. package/registry/square-grid.json +1 -1
  454. package/registry/square-snake.json +1 -1
  455. package/registry/square-spinner.json +1 -1
  456. package/registry/squash-sphere.json +1 -1
  457. package/registry/stacked-bar-pulse.json +1 -1
  458. package/registry/stagger-text.json +1 -1
  459. package/registry/staggered-glass-curtain.json +1 -1
  460. package/registry/sticky-note-peel.json +1 -1
  461. package/registry/sticky-reveal.json +1 -1
  462. package/registry/stretch-x-char.json +1 -1
  463. package/registry/stretch-y-char.json +1 -1
  464. package/registry/stroke-waveform.json +1 -1
  465. package/registry/submenu-flyout.json +1 -1
  466. package/registry/success-check.json +1 -1
  467. package/registry/sudden-brake.json +1 -1
  468. package/registry/swapping-dots.json +1 -1
  469. package/registry/swing-word.json +1 -1
  470. package/registry/swirling-spinner.json +1 -1
  471. package/registry/symmetric-wave.json +1 -1
  472. package/registry/terminal-loader.json +1 -1
  473. package/registry/text-blink.json +1 -1
  474. package/registry/text-dots.json +1 -1
  475. package/registry/text-morph.json +1 -1
  476. package/registry/text-reveal.json +1 -1
  477. package/registry/text-shimmer-wave.json +1 -1
  478. package/registry/text-shimmer.json +1 -1
  479. package/registry/textarea-auto-grow.json +1 -1
  480. package/registry/theme-toggle.json +1 -1
  481. package/registry/tilt-card.json +1 -1
  482. package/registry/timer-preparation-segmented.json +1 -1
  483. package/registry/tracking-in-text.json +1 -1
  484. package/registry/tracking-out-text.json +1 -1
  485. package/registry/trailing-dots.json +1 -1
  486. package/registry/triple-dot-spinner.json +1 -1
  487. package/registry/twin-orbit.json +1 -1
  488. package/registry/typewriter-text.json +1 -1
  489. package/registry/typing-indicator.json +1 -1
  490. package/registry/typing.json +1 -1
  491. package/registry/use-mouse-position.json +1 -1
  492. package/registry/use-reduced-motion.json +1 -1
  493. package/registry/use-scroll-progress.json +1 -1
  494. package/registry/use-stagger.json +1 -1
  495. package/registry/use-web-haptics.json +1 -1
  496. package/registry/users-growth-pill-progress.json +1 -1
  497. package/registry/utils.json +1 -1
  498. package/registry/vertical-wheel-counter.json +1 -1
  499. package/registry/views-hourly-wave-chart.json +1 -1
  500. package/registry/voice-assistant-card.json +1 -1
  501. package/registry/wandering-cube.json +1 -1
  502. package/registry/wandering-eyes.json +1 -1
  503. package/registry/watch-spinner.json +1 -1
  504. package/registry/wave-dots.json +1 -1
  505. package/registry/wave-physics-loader.json +1 -1
  506. package/registry/wave-reveal.json +1 -1
  507. package/registry/waveform-loader.json +1 -1
  508. package/registry/word-reveal.json +1 -1
  509. package/registry/zig-zag-pulse.json +1 -1
  510. package/registry/zoom-in-text.json +1 -1
  511. package/registry/zoom-in.json +1 -1
  512. package/registry/zoom-out-text.json +1 -1
package/dist/index.js CHANGED
@@ -320,7 +320,7 @@ function ApprovalCard({
320
320
  const measured = useRef(false);
321
321
  const [viewportH, setViewportH] = useState4(void 0);
322
322
  const [trackY, setTrackY] = useState4(0);
323
- const [animate, setAnimate] = useState4(false);
323
+ const [animate3, setAnimate] = useState4(false);
324
324
  const [ready, setReady] = useState4(false);
325
325
  const last = qi >= questions.length - 1;
326
326
  const selected = answers[qi] ?? [];
@@ -439,7 +439,7 @@ function ApprovalCard({
439
439
  "div",
440
440
  {
441
441
  className: "overflow-hidden",
442
- style: { height: viewportH, transition: animate ? `height ${SLIDE}` : void 0 },
442
+ style: { height: viewportH, transition: animate3 ? `height ${SLIDE}` : void 0 },
443
443
  "aria-live": "polite",
444
444
  children: /* @__PURE__ */ jsx(
445
445
  "div",
@@ -450,7 +450,7 @@ function ApprovalCard({
450
450
  flexDirection: "column",
451
451
  gap: 26,
452
452
  transform: `translate3d(0, ${-trackY}px, 0)`,
453
- transition: animate ? `transform ${SLIDE}` : void 0,
453
+ transition: animate3 ? `transform ${SLIDE}` : void 0,
454
454
  willChange: "transform"
455
455
  },
456
456
  children: questions.map((question, qIdx) => {
@@ -459,7 +459,7 @@ function ApprovalCard({
459
459
  const picked = answers[qIdx] ?? [];
460
460
  const questionStyle = {
461
461
  opacity: active ? 1 : 0,
462
- transition: animate ? `opacity ${SLIDE}` : void 0,
462
+ transition: animate3 ? `opacity ${SLIDE}` : void 0,
463
463
  pointerEvents: active ? void 0 : "none"
464
464
  };
465
465
  return /* @__PURE__ */ jsxs(
@@ -1012,14 +1012,14 @@ function ScrubField({
1012
1012
  const drag = useRef3(null);
1013
1013
  const [draft, setDraft] = useState7(String(value));
1014
1014
  useEffect6(() => setDraft(String(value)), [value]);
1015
- const clamp2 = (v) => Math.min(max, Math.max(min, Number((Math.round(v / step) * step).toFixed(8))));
1015
+ const clamp5 = (v) => Math.min(max, Math.max(min, Number((Math.round(v / step) * step).toFixed(8))));
1016
1016
  const commitDraft = () => {
1017
1017
  const parsed = draft.trim() === "" ? NaN : Number(draft);
1018
1018
  if (!Number.isFinite(parsed)) {
1019
1019
  setDraft(String(value));
1020
1020
  return;
1021
1021
  }
1022
- const next = clamp2(parsed);
1022
+ const next = clamp5(parsed);
1023
1023
  setDraft(String(next));
1024
1024
  if (next !== value) onChange(next);
1025
1025
  };
@@ -1047,7 +1047,7 @@ function ScrubField({
1047
1047
  },
1048
1048
  onPointerMove: (e) => {
1049
1049
  if (!drag.current) return;
1050
- onChange(clamp2(drag.current.v + (e.clientX - drag.current.x) / 2 * step));
1050
+ onChange(clamp5(drag.current.v + (e.clientX - drag.current.x) / 2 * step));
1051
1051
  },
1052
1052
  onPointerUp: () => drag.current = null,
1053
1053
  onPointerCancel: () => drag.current = null,
@@ -1056,10 +1056,10 @@ function ScrubField({
1056
1056
  const mult = e.shiftKey ? 10 : 1;
1057
1057
  if (e.key === "ArrowUp" || e.key === "ArrowRight") {
1058
1058
  e.preventDefault();
1059
- onChange(clamp2(value + step * mult));
1059
+ onChange(clamp5(value + step * mult));
1060
1060
  } else if (e.key === "ArrowDown" || e.key === "ArrowLeft") {
1061
1061
  e.preventDefault();
1062
- onChange(clamp2(value - step * mult));
1062
+ onChange(clamp5(value - step * mult));
1063
1063
  }
1064
1064
  },
1065
1065
  className: "flex h-full shrink-0 cursor-ew-resize touch-none items-center rounded-[4px]\n px-0.5 text-[12px] text-[var(--mova-ai-ink-muted,#858585)] select-none hover:text-[var(--mova-ai-ink-secondary,#666)] focus-visible:text-[var(--mova-ai-accent-ink,#333)]\n focus-visible:outline-none",
@@ -4264,14 +4264,14 @@ function BalanceBarChartCard({ periods = periodsDefault, defaultPeriod = "week",
4264
4264
  tip.dataset.show = "true";
4265
4265
  tip.setAttribute("aria-hidden", "false");
4266
4266
  }, [active, period, currency, locale]);
4267
- const movePill = React.useCallback((animate) => {
4267
+ const movePill = React.useCallback((animate3) => {
4268
4268
  const tab = tabs.current?.querySelector('[role=tab][aria-selected="true"]');
4269
4269
  const el = pill.current;
4270
4270
  if (!tab || !el) return;
4271
- if (!animate) el.style.transition = "none";
4271
+ if (!animate3) el.style.transition = "none";
4272
4272
  el.style.transform = `translateX(${tab.offsetLeft}px)`;
4273
4273
  el.style.width = `${tab.offsetWidth}px`;
4274
- if (!animate) {
4274
+ if (!animate3) {
4275
4275
  void el.offsetWidth;
4276
4276
  el.style.transition = "";
4277
4277
  }
@@ -10469,19 +10469,470 @@ var ZigZagPulse = () => {
10469
10469
  )) });
10470
10470
  };
10471
10471
 
10472
+ // .generated/ui/patterns/animated-mega-menu.tsx
10473
+ import {
10474
+ useCallback as useCallback4,
10475
+ useEffect as useEffect18,
10476
+ useId as useId11,
10477
+ useRef as useRef17,
10478
+ useState as useState27
10479
+ } from "react";
10480
+ import { AnimatePresence as AnimatePresence7, motion as motion155, useIsPresent, useReducedMotion as useReducedMotion9 } from "framer-motion";
10481
+ import { ChevronDown as ChevronDown3, Menu, X } from "lucide-react";
10482
+ import { Fragment as Fragment14, jsx as jsx171, jsxs as jsxs81 } from "react/jsx-runtime";
10483
+ import { createElement } from "react";
10484
+ var spring = { type: "spring", stiffness: 350, damping: 32 };
10485
+ var menuStyles = `
10486
+ .mova-mega { position:relative; container-type:inline-size; width:100%; color:var(--mova-mega-text); font:inherit; }
10487
+ .mova-mega *, .mova-mega *::before { box-sizing:border-box; }
10488
+ .mova-mega-bar { height:56px; display:flex; align-items:center; gap:24px; padding:0 32px; }
10489
+ .mova-mega-brand, .mova-mega-actions { flex-shrink:0; display:flex; align-items:center; }
10490
+ .mova-mega-actions { margin-inline-start:auto; }
10491
+ .mova-mega-nav { display:flex; gap:2px; align-items:center; min-width:0; overflow:auto; scrollbar-width:none; }
10492
+ .mova-mega-trigger, .mova-mega-toggle, .mova-mega-link {
10493
+ appearance:none; border:0; background:none; color:inherit; font:inherit; text-decoration:none;
10494
+ position:relative; cursor:pointer; border-radius:8px; -webkit-tap-highlight-color:transparent;
10495
+ }
10496
+ .mova-mega :is(.mova-mega-trigger,.mova-mega-toggle,.mova-mega-link):focus-visible {
10497
+ outline:2px solid currentColor; outline-offset:-2px;
10498
+ }
10499
+ .mova-mega-trigger {
10500
+ display:flex; flex-shrink:0; align-items:center; gap:8px; height:36px; padding:0 14px;
10501
+ font-size:14px; white-space:nowrap; color:var(--mova-mega-muted);
10502
+ }
10503
+ .mova-mega-trigger[data-active=true] { color:var(--mova-mega-text); }
10504
+ .mova-mega-trigger > span { z-index:1; display:inline-flex; }
10505
+ .mova-mega-pill, .mova-mega-row-pill {
10506
+ position:absolute; inset:0; border-radius:inherit; background:var(--mova-mega-highlight); pointer-events:none;
10507
+ }
10508
+ .mova-mega-pill { z-index:0 !important; }
10509
+ .mova-mega-bridge { position:absolute; top:100%; left:0; right:0; height:8px; }
10510
+ .mova-mega-popup {
10511
+ position:absolute; left:0; top:calc(100% + 8px); z-index:2; overflow:hidden; border:1px solid var(--mova-mega-border);
10512
+ background:var(--mova-mega-surface); border-radius:16px; transform-origin:top center; box-shadow:0 14px 32px #0003;
10513
+ }
10514
+ .mova-mega-content { position:absolute; top:0; left:0; right:0; max-height:min(65vh,420px); overflow:auto; overscroll-behavior:contain; }
10515
+ .mova-mega-grid { padding:8px; display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); column-gap:8px; }
10516
+ .mova-mega-link {
10517
+ display:flex; align-items:center; gap:10px; border-radius:12px; min-height:52px;
10518
+ padding:8px 16px; line-height:1.25; text-align:start; font-size:14px; min-width:0;
10519
+ }
10520
+ .mova-mega-link > span:not(.mova-mega-row-pill) { position:relative; min-width:0; overflow-wrap:anywhere; }
10521
+ .mova-mega-description { display:block; color:var(--mova-mega-muted); font-size:12px; margin-top:2px; }
10522
+ .mova-mega-footer { grid-column:1/-1; border-top:1px solid var(--mova-mega-border); padding-top:8px; margin-top:8px; }
10523
+ .mova-mega-toggle, .mova-mega-mobile { display:none; }
10524
+ .mova-mega-mobile { position:absolute; z-index:2; top:100%; inset-inline:0; padding:8px; max-height:min(65vh,430px);
10525
+ overflow:auto; overscroll-behavior:contain; background:var(--mova-mega-surface);
10526
+ border:1px solid var(--mova-mega-border); border-radius:16px; box-shadow:0 14px 32px #0003;
10527
+ }
10528
+ @container (max-width: 699px) {
10529
+ .mova-mega-bar { padding:0 16px; height:64px; gap:12px; }
10530
+ .mova-mega-nav, .mova-mega-popup, .mova-mega-bridge { display:none; }
10531
+ .mova-mega-toggle { display:grid; place-items:center; min-width:44px; height:44px; }
10532
+ .mova-mega-toggle:last-child { margin-inline-start:auto; }
10533
+ .mova-mega-mobile { display:block; }
10534
+ .mova-mega-mobile .mova-mega-trigger { width:100%; justify-content:space-between; min-height:44px; }
10535
+ .mova-mega-mobile .mova-mega-trigger[data-active=true] { background:var(--mova-mega-highlight); }
10536
+ }
10537
+ @container (max-width: 310px) { .mova-mega-grid { grid-template-columns:minmax(0,1fr); } }
10538
+ @container (min-width: 700px) and (max-width: 839px) {
10539
+ .mova-mega-bar { padding:0 16px; gap:12px; }
10540
+ .mova-mega-trigger { padding:0 10px; }
10541
+ }
10542
+ `;
10543
+ function PresencePanel({ as, onPresent, ...props }) {
10544
+ const present = useIsPresent();
10545
+ const Element2 = as === "nav" ? motion155.nav : motion155.div;
10546
+ const setRef = useCallback4((element) => {
10547
+ if (!element) return;
10548
+ element.inert = !present;
10549
+ if (present) onPresent?.(element);
10550
+ }, [onPresent, present]);
10551
+ return /* @__PURE__ */ jsx171(
10552
+ Element2,
10553
+ {
10554
+ ...props,
10555
+ "data-present": present,
10556
+ "aria-hidden": !present || void 0,
10557
+ style: { ...props.style, pointerEvents: present ? props.style?.pointerEvents : "none" },
10558
+ ref: setRef
10559
+ }
10560
+ );
10561
+ }
10562
+ function panelPosition(header, trigger, item) {
10563
+ const bounds = header.getBoundingClientRect();
10564
+ const triggerBounds = trigger.getBoundingClientRect();
10565
+ const hasDescriptions = item.links?.some((link) => link.description);
10566
+ const width = Math.min(hasDescriptions ? 466 : 434, bounds.width - 32);
10567
+ const center = triggerBounds.left - bounds.left + triggerBounds.width / 2;
10568
+ const x = Math.max(16, Math.min(center - width / 2, bounds.width - width - 16));
10569
+ return { x, width };
10570
+ }
10571
+ function MegaMenuLinks({ item, layoutId, close }) {
10572
+ const [highlighted, setHighlighted] = useState27(null);
10573
+ const reduced = useReducedMotion9();
10574
+ const links = item.links ?? [];
10575
+ const row = (link, index) => /* @__PURE__ */ jsxs81(
10576
+ "a",
10577
+ {
10578
+ className: "mova-mega-link",
10579
+ href: link.href,
10580
+ onPointerEnter: (event) => {
10581
+ if (event.pointerType === "mouse") setHighlighted(index);
10582
+ },
10583
+ onFocus: () => setHighlighted(index),
10584
+ onClick: close,
10585
+ children: [
10586
+ highlighted === index && /* @__PURE__ */ jsx171(
10587
+ motion155.span,
10588
+ {
10589
+ "aria-hidden": "true",
10590
+ className: "mova-mega-row-pill",
10591
+ layoutId: reduced ? void 0 : layoutId,
10592
+ transition: spring
10593
+ }
10594
+ ),
10595
+ link.icon != null && /* @__PURE__ */ jsx171("span", { "aria-hidden": "true", children: link.icon }),
10596
+ /* @__PURE__ */ jsxs81("span", { children: [
10597
+ link.label,
10598
+ link.description && /* @__PURE__ */ jsx171("span", { className: "mova-mega-description", children: link.description })
10599
+ ] })
10600
+ ]
10601
+ },
10602
+ index
10603
+ );
10604
+ return /* @__PURE__ */ jsxs81(
10605
+ "div",
10606
+ {
10607
+ className: "mova-mega-grid",
10608
+ onPointerLeave: () => setHighlighted(null),
10609
+ onBlur: (event) => {
10610
+ if (!event.currentTarget.contains(event.relatedTarget)) setHighlighted(null);
10611
+ },
10612
+ children: [
10613
+ links.map(row),
10614
+ item.footer && /* @__PURE__ */ jsx171("div", { className: "mova-mega-footer", children: row(item.footer, links.length) })
10615
+ ]
10616
+ }
10617
+ );
10618
+ }
10619
+ function AnimatedMegaMenu({
10620
+ items: items2,
10621
+ brand,
10622
+ actions,
10623
+ label = "Main navigation",
10624
+ theme = "dark",
10625
+ className,
10626
+ style
10627
+ }) {
10628
+ const id = useId11();
10629
+ const reduced = useReducedMotion9();
10630
+ const root = useRef17(null);
10631
+ const mobileToggle = useRef17(null);
10632
+ const triggers = useRef17([]);
10633
+ const closeTimer = useRef17(void 0);
10634
+ const focusOnOpen = useRef17(false);
10635
+ const [highlighted, setHighlighted] = useState27(null);
10636
+ const [active, setActive] = useState27(null);
10637
+ const [direction, setDirection] = useState27(1);
10638
+ const [mobileOpen, setMobileOpen] = useState27(false);
10639
+ const [mobileGroup, setMobileGroup] = useState27(null);
10640
+ const [currentPanel, setCurrentPanel] = useState27(null);
10641
+ const [geometry, setGeometry] = useState27({ x: 16, width: 434, height: 120 });
10642
+ const openItem = active === null ? void 0 : items2[active];
10643
+ const dark = theme === "dark";
10644
+ const transition2 = reduced ? { duration: 0 } : spring;
10645
+ function currentContent() {
10646
+ return root.current?.querySelector('.mova-mega-content[data-present="true"]');
10647
+ }
10648
+ function close() {
10649
+ window.clearTimeout(closeTimer.current);
10650
+ focusOnOpen.current = false;
10651
+ setCurrentPanel(null);
10652
+ setActive(null);
10653
+ setHighlighted(null);
10654
+ setMobileOpen(false);
10655
+ setMobileGroup(null);
10656
+ }
10657
+ function show(index, focusLinks = false) {
10658
+ window.clearTimeout(closeTimer.current);
10659
+ const item = items2[index];
10660
+ if (!item) return;
10661
+ if (active !== null && index !== active) setDirection(index > active ? 1 : -1);
10662
+ setHighlighted(index);
10663
+ if (item.links?.length || item.footer) {
10664
+ const trigger = triggers.current[index];
10665
+ if (active !== index && root.current && trigger) {
10666
+ const position = panelPosition(root.current, trigger, item);
10667
+ setGeometry((previous) => ({ ...previous, ...position }));
10668
+ }
10669
+ setActive(index);
10670
+ if (focusLinks) {
10671
+ const first = active === index ? currentContent()?.querySelector("a") : null;
10672
+ if (first) first.focus();
10673
+ else focusOnOpen.current = true;
10674
+ }
10675
+ } else {
10676
+ setActive(null);
10677
+ }
10678
+ }
10679
+ useEffect18(() => {
10680
+ if (active === null || !root.current || !currentPanel || currentPanel !== currentContent()) return;
10681
+ const header = root.current;
10682
+ const panel = currentPanel;
10683
+ const trigger = triggers.current[active];
10684
+ const item = items2[active];
10685
+ if (!trigger || !item) return;
10686
+ const measure = () => {
10687
+ if (header.clientWidth < 700) return;
10688
+ const { x, width } = panelPosition(header, trigger, item);
10689
+ const height = panel.offsetHeight + 2;
10690
+ setGeometry((old) => old.x === x && old.width === width && old.height === height ? old : { x, width, height });
10691
+ };
10692
+ measure();
10693
+ const observer = new ResizeObserver(measure);
10694
+ observer.observe(header);
10695
+ observer.observe(panel);
10696
+ observer.observe(trigger);
10697
+ if (focusOnOpen.current) {
10698
+ focusOnOpen.current = false;
10699
+ panel.querySelector("a")?.focus();
10700
+ }
10701
+ return () => observer.disconnect();
10702
+ }, [active, currentPanel, items2]);
10703
+ useEffect18(() => {
10704
+ const header = root.current;
10705
+ if (!header) return;
10706
+ let compact = header.getBoundingClientRect().width < 700;
10707
+ const observer = new ResizeObserver(() => {
10708
+ const next = header.getBoundingClientRect().width < 700;
10709
+ if (compact === next) return;
10710
+ compact = next;
10711
+ close();
10712
+ });
10713
+ observer.observe(header);
10714
+ return () => observer.disconnect();
10715
+ }, []);
10716
+ useEffect18(() => {
10717
+ if (!mobileOpen && active === null) return;
10718
+ const dismiss = (event) => {
10719
+ if (!root.current?.contains(event.target)) close();
10720
+ };
10721
+ document.addEventListener("pointerdown", dismiss);
10722
+ return () => document.removeEventListener("pointerdown", dismiss);
10723
+ }, [active, mobileOpen]);
10724
+ useEffect18(() => () => window.clearTimeout(closeTimer.current), []);
10725
+ function handleTriggerKey(event, index) {
10726
+ if (event.key === "ArrowDown" && (items2[index].links?.length || items2[index].footer)) {
10727
+ event.preventDefault();
10728
+ show(index, true);
10729
+ } else if (event.key === "ArrowRight" || event.key === "ArrowLeft") {
10730
+ const next = (index + (event.key === "ArrowRight" ? 1 : -1) + items2.length) % items2.length;
10731
+ event.preventDefault();
10732
+ triggers.current[next]?.focus();
10733
+ }
10734
+ }
10735
+ const variables = {
10736
+ "--mova-mega-text": dark ? "#ededed" : "#171717",
10737
+ "--mova-mega-muted": dark ? "#a1a1a1" : "#595959",
10738
+ "--mova-mega-highlight": dark ? "#ffffff0f" : "#0000000c",
10739
+ "--mova-mega-border": dark ? "#ffffff1a" : "#0000001a",
10740
+ "--mova-mega-surface": dark ? "#080808" : "#fff",
10741
+ ...style
10742
+ };
10743
+ return /* @__PURE__ */ jsxs81(
10744
+ "header",
10745
+ {
10746
+ ref: root,
10747
+ className: `mova-mega ${className ?? ""}`,
10748
+ style: variables,
10749
+ onPointerEnter: () => window.clearTimeout(closeTimer.current),
10750
+ onPointerLeave: (event) => {
10751
+ if (event.pointerType !== "mouse" || root.current?.contains(document.activeElement) && document.activeElement?.matches(":focus-visible")) return;
10752
+ closeTimer.current = window.setTimeout(close, 120);
10753
+ },
10754
+ onBlur: (event) => {
10755
+ if (!event.currentTarget.contains(event.relatedTarget)) close();
10756
+ },
10757
+ onKeyDown: (event) => {
10758
+ if (event.key !== "Escape" || !openItem && !mobileOpen) return;
10759
+ event.preventDefault();
10760
+ if (mobileOpen) mobileToggle.current?.focus();
10761
+ else if (active !== null) triggers.current[active]?.focus();
10762
+ close();
10763
+ },
10764
+ children: [
10765
+ /* @__PURE__ */ jsx171("style", { children: menuStyles }),
10766
+ /* @__PURE__ */ jsxs81("div", { className: "mova-mega-bar", children: [
10767
+ brand && /* @__PURE__ */ jsx171("div", { className: "mova-mega-brand", children: brand }),
10768
+ /* @__PURE__ */ jsx171("nav", { className: "mova-mega-nav", "aria-label": label, children: items2.map((item, index) => {
10769
+ const hasMenu = Boolean(item.links?.length || item.footer);
10770
+ const common = {
10771
+ className: "mova-mega-trigger",
10772
+ "data-active": highlighted === index,
10773
+ onPointerEnter: (event) => {
10774
+ if (event.pointerType === "mouse") show(index);
10775
+ },
10776
+ onFocus: () => {
10777
+ setHighlighted(index);
10778
+ if (active !== index) setActive(null);
10779
+ },
10780
+ onKeyDown: (event) => handleTriggerKey(event, index)
10781
+ };
10782
+ const children = /* @__PURE__ */ jsxs81(Fragment14, { children: [
10783
+ highlighted === index && /* @__PURE__ */ jsx171(motion155.span, { "aria-hidden": "true", className: "mova-mega-pill", layoutId: reduced ? void 0 : `${id}-nav-pill`, transition: transition2 }),
10784
+ /* @__PURE__ */ jsx171("span", { children: item.label }),
10785
+ hasMenu && /* @__PURE__ */ jsx171(motion155.span, { "aria-hidden": "true", animate: { rotate: active === index ? 180 : 0 }, transition: transition2, children: /* @__PURE__ */ jsx171(ChevronDown3, { size: 14 }) })
10786
+ ] });
10787
+ return hasMenu ? /* @__PURE__ */ createElement(
10788
+ "button",
10789
+ {
10790
+ ...common,
10791
+ key: index,
10792
+ type: "button",
10793
+ ref: (element) => {
10794
+ triggers.current[index] = element;
10795
+ },
10796
+ "aria-expanded": active === index,
10797
+ "aria-controls": active === index ? `${id}-panel` : void 0,
10798
+ onClick: () => show(index, true)
10799
+ },
10800
+ children
10801
+ ) : /* @__PURE__ */ createElement(
10802
+ "a",
10803
+ {
10804
+ ...common,
10805
+ key: index,
10806
+ href: item.href,
10807
+ ref: (element) => {
10808
+ triggers.current[index] = element;
10809
+ },
10810
+ onClick: close
10811
+ },
10812
+ children
10813
+ );
10814
+ }) }),
10815
+ actions && /* @__PURE__ */ jsx171("div", { className: "mova-mega-actions", children: actions }),
10816
+ /* @__PURE__ */ jsx171(
10817
+ "button",
10818
+ {
10819
+ className: "mova-mega-toggle",
10820
+ ref: mobileToggle,
10821
+ type: "button",
10822
+ "aria-label": mobileOpen ? "Close navigation" : "Open navigation",
10823
+ "aria-expanded": mobileOpen,
10824
+ "aria-controls": mobileOpen ? `${id}-mobile` : void 0,
10825
+ onClick: () => {
10826
+ if (mobileOpen) close();
10827
+ else setMobileOpen(true);
10828
+ },
10829
+ onKeyDown: (event) => {
10830
+ if (event.key === "ArrowDown" && mobileOpen) {
10831
+ event.preventDefault();
10832
+ root.current?.querySelector('.mova-mega-mobile[data-present="true"] :is(button,a[href])')?.focus();
10833
+ }
10834
+ },
10835
+ children: mobileOpen ? /* @__PURE__ */ jsx171(X, { size: 20 }) : /* @__PURE__ */ jsx171(Menu, { size: 20 })
10836
+ }
10837
+ )
10838
+ ] }),
10839
+ /* @__PURE__ */ jsx171(AnimatePresence7, { initial: false, children: openItem && /* @__PURE__ */ jsx171(
10840
+ PresencePanel,
10841
+ {
10842
+ id: `${id}-panel`,
10843
+ className: "mova-mega-popup",
10844
+ initial: { opacity: 0, scale: reduced ? 1 : 0.96, ...geometry },
10845
+ animate: { opacity: 1, scale: 1, ...geometry },
10846
+ exit: { opacity: 0, scale: reduced ? 1 : 0.96 },
10847
+ transition: transition2,
10848
+ children: /* @__PURE__ */ jsx171(AnimatePresence7, { initial: false, custom: direction, propagate: true, children: /* @__PURE__ */ jsx171(
10849
+ PresencePanel,
10850
+ {
10851
+ className: "mova-mega-content",
10852
+ onPresent: setCurrentPanel,
10853
+ custom: direction,
10854
+ variants: {
10855
+ entering: (side) => ({ x: reduced ? 0 : side * 24, opacity: 0 }),
10856
+ visible: { x: 0, opacity: 1 },
10857
+ exiting: (side) => ({ x: reduced ? 0 : side * -24, opacity: 0, pointerEvents: "none" })
10858
+ },
10859
+ initial: "entering",
10860
+ animate: "visible",
10861
+ exit: "exiting",
10862
+ transition: transition2,
10863
+ onKeyDown: (event) => {
10864
+ const links = Array.from(event.currentTarget.querySelectorAll("a[href]"));
10865
+ const current = links.findIndex((link) => link === document.activeElement);
10866
+ if (current === -1 || active === null) return;
10867
+ if (event.key === "Tab") {
10868
+ const next2 = event.shiftKey && current === 0 ? triggers.current[active] : !event.shiftKey && current === links.length - 1 ? triggers.current[active + 1] ?? root.current?.querySelector(".mova-mega-actions :is(button,a[href])") : null;
10869
+ if (next2) {
10870
+ event.preventDefault();
10871
+ next2.focus();
10872
+ }
10873
+ return;
10874
+ }
10875
+ if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) return;
10876
+ event.preventDefault();
10877
+ const next = event.key === "Home" ? 0 : event.key === "End" ? links.length - 1 : (current + (event.key === "ArrowDown" ? 1 : -1) + links.length) % links.length;
10878
+ links[next].focus();
10879
+ },
10880
+ children: /* @__PURE__ */ jsx171(MegaMenuLinks, { item: openItem, layoutId: `${id}-rows-${active}`, close })
10881
+ },
10882
+ active
10883
+ ) })
10884
+ },
10885
+ "panel"
10886
+ ) }),
10887
+ openItem && /* @__PURE__ */ jsx171("span", { className: "mova-mega-bridge", "aria-hidden": "true" }),
10888
+ /* @__PURE__ */ jsx171(AnimatePresence7, { initial: false, children: mobileOpen && /* @__PURE__ */ jsx171(
10889
+ PresencePanel,
10890
+ {
10891
+ as: "nav",
10892
+ id: `${id}-mobile`,
10893
+ "aria-label": label,
10894
+ className: "mova-mega-mobile",
10895
+ initial: { opacity: 0, y: reduced ? 0 : -6 },
10896
+ animate: { opacity: 1, y: 0 },
10897
+ exit: { opacity: 0, y: reduced ? 0 : -6 },
10898
+ transition: transition2,
10899
+ children: items2.map((item, index) => item.links?.length || item.footer ? /* @__PURE__ */ jsxs81("div", { children: [
10900
+ /* @__PURE__ */ jsxs81(
10901
+ "button",
10902
+ {
10903
+ className: "mova-mega-trigger",
10904
+ type: "button",
10905
+ "aria-expanded": mobileGroup === index,
10906
+ "data-active": mobileGroup === index,
10907
+ onClick: () => setMobileGroup(mobileGroup === index ? null : index),
10908
+ children: [
10909
+ item.label,
10910
+ /* @__PURE__ */ jsx171(motion155.span, { "aria-hidden": "true", animate: { rotate: mobileGroup === index ? 180 : 0 }, transition: transition2, children: /* @__PURE__ */ jsx171(ChevronDown3, { size: 14 }) })
10911
+ ]
10912
+ }
10913
+ ),
10914
+ mobileGroup === index && /* @__PURE__ */ jsx171(MegaMenuLinks, { item, layoutId: `${id}-mobile-rows`, close })
10915
+ ] }, index) : /* @__PURE__ */ jsx171("a", { className: "mova-mega-trigger", href: item.href, onClick: close, children: item.label }, index))
10916
+ }
10917
+ ) })
10918
+ ]
10919
+ }
10920
+ );
10921
+ }
10922
+
10472
10923
  // .generated/ui/patterns/animated-tags.tsx
10473
10924
  import { CircleX, Plus as Plus2 } from "lucide-react";
10474
- import { AnimatePresence as AnimatePresence7, motion as motion155, useReducedMotion as useReducedMotion9 } from "framer-motion";
10475
- import { useState as useState27 } from "react";
10476
- import { jsx as jsx171, jsxs as jsxs81 } from "react/jsx-runtime";
10925
+ import { AnimatePresence as AnimatePresence8, motion as motion156, useReducedMotion as useReducedMotion10 } from "framer-motion";
10926
+ import { useState as useState28 } from "react";
10927
+ import { jsx as jsx172, jsxs as jsxs82 } from "react/jsx-runtime";
10477
10928
  function AnimatedTags({
10478
10929
  initialTags = ["react", "tailwindcss", "javascript"],
10479
10930
  selectedTags: controlledSelectedTags,
10480
10931
  onChange,
10481
10932
  className = ""
10482
10933
  }) {
10483
- const [internalSelected, setInternalSelected] = useState27([]);
10484
- const shouldReduceMotion = useReducedMotion9();
10934
+ const [internalSelected, setInternalSelected] = useState28([]);
10935
+ const shouldReduceMotion = useReducedMotion10();
10485
10936
  const selectedTag = controlledSelectedTags ?? internalSelected;
10486
10937
  const tags = initialTags.filter((tag) => !selectedTag.includes(tag));
10487
10938
  const handleTagClick = (tag) => {
@@ -10500,11 +10951,11 @@ function AnimatedTags({
10500
10951
  setInternalSelected(newSelectedTag);
10501
10952
  }
10502
10953
  };
10503
- return /* @__PURE__ */ jsxs81("div", { className: `flex w-[300px] flex-col gap-4 p-4 ${className}`, children: [
10504
- /* @__PURE__ */ jsxs81("div", { className: "flex flex-col items-start justify-center gap-1", children: [
10505
- /* @__PURE__ */ jsx171("p", { children: "Selected Tags" }),
10506
- /* @__PURE__ */ jsx171(AnimatePresence7, { children: /* @__PURE__ */ jsx171("div", { className: "flex min-h-12 w-full flex-wrap items-center gap-1 rounded-xl border bg-background p-2", children: selectedTag?.map((tag) => /* @__PURE__ */ jsxs81(
10507
- motion155.div,
10954
+ return /* @__PURE__ */ jsxs82("div", { className: `flex w-[300px] flex-col gap-4 p-4 ${className}`, children: [
10955
+ /* @__PURE__ */ jsxs82("div", { className: "flex flex-col items-start justify-center gap-1", children: [
10956
+ /* @__PURE__ */ jsx172("p", { children: "Selected Tags" }),
10957
+ /* @__PURE__ */ jsx172(AnimatePresence8, { children: /* @__PURE__ */ jsx172("div", { className: "flex min-h-12 w-full flex-wrap items-center gap-1 rounded-xl border bg-background p-2", children: selectedTag?.map((tag) => /* @__PURE__ */ jsxs82(
10958
+ motion156.div,
10508
10959
  {
10509
10960
  animate: shouldReduceMotion ? { opacity: 1 } : {
10510
10961
  filter: "blur(0px)",
@@ -10520,7 +10971,7 @@ function AnimatedTags({
10520
10971
  children: [
10521
10972
  tag,
10522
10973
  " ",
10523
- /* @__PURE__ */ jsx171(
10974
+ /* @__PURE__ */ jsx172(
10524
10975
  CircleX,
10525
10976
  {
10526
10977
  className: "ease flex items-center justify-center rounded-full transition-all duration-200",
@@ -10532,8 +10983,8 @@ function AnimatedTags({
10532
10983
  tag
10533
10984
  )) }) })
10534
10985
  ] }),
10535
- /* @__PURE__ */ jsx171(AnimatePresence7, { children: /* @__PURE__ */ jsx171("div", { className: "flex flex-wrap items-center gap-1", children: tags.map((tag) => /* @__PURE__ */ jsxs81(
10536
- motion155.div,
10986
+ /* @__PURE__ */ jsx172(AnimatePresence8, { children: /* @__PURE__ */ jsx172("div", { className: "flex flex-wrap items-center gap-1", children: tags.map((tag) => /* @__PURE__ */ jsxs82(
10987
+ motion156.div,
10537
10988
  {
10538
10989
  animate: shouldReduceMotion ? { opacity: 1 } : {
10539
10990
  filter: "blur(0px)",
@@ -10549,7 +11000,7 @@ function AnimatedTags({
10549
11000
  children: [
10550
11001
  tag,
10551
11002
  " ",
10552
- /* @__PURE__ */ jsx171(
11003
+ /* @__PURE__ */ jsx172(
10553
11004
  Plus2,
10554
11005
  {
10555
11006
  className: "ease flex items-center justify-center rounded-full transition-all duration-200 group-hover/tag:bg-primary group-hover/tag:text-foreground",
@@ -10563,10 +11014,448 @@ function AnimatedTags({
10563
11014
  ] });
10564
11015
  }
10565
11016
 
11017
+ // .generated/ui/patterns/blur-carousel.tsx
11018
+ import { useEffect as useEffect19, useRef as useRef18, useState as useState29 } from "react";
11019
+ import { motion as motion157, useMotionValue as useMotionValue2, useReducedMotion as useReducedMotion11, useTransform as useTransform2 } from "framer-motion";
11020
+ import { jsx as jsx173, jsxs as jsxs83 } from "react/jsx-runtime";
11021
+ function CarouselSlide({ children, index, total, position, reducedMotion }) {
11022
+ const distance = useTransform2(position, (value) => Math.min(1, Math.abs(value - index)));
11023
+ const scale = useTransform2(distance, (value) => 1 - value * 0.15);
11024
+ const opacity = useTransform2(distance, (value) => 1 - value * 0.5);
11025
+ const filter = useTransform2(distance, (value) => `blur(${value * 7}px)`);
11026
+ return /* @__PURE__ */ jsx173(
11027
+ "div",
11028
+ {
11029
+ role: "group",
11030
+ "aria-roledescription": "slide",
11031
+ "aria-label": `${index + 1} of ${total}`,
11032
+ "data-mova-blur-slide": index,
11033
+ style: {
11034
+ flex: "0 0 var(--mova-blur-width)",
11035
+ minWidth: 0,
11036
+ boxSizing: "border-box",
11037
+ paddingInline: "var(--mova-blur-gap)",
11038
+ scrollSnapAlign: "start",
11039
+ display: "grid",
11040
+ alignItems: "center"
11041
+ },
11042
+ children: /* @__PURE__ */ jsx173(
11043
+ motion157.div,
11044
+ {
11045
+ style: {
11046
+ overflow: "hidden",
11047
+ minWidth: 0,
11048
+ borderRadius: 20,
11049
+ boxShadow: "0 8px 12px rgb(0 0 0 / 20%)",
11050
+ opacity,
11051
+ scale: reducedMotion ? 1 : scale
11052
+ },
11053
+ children: /* @__PURE__ */ jsx173(motion157.div, { style: { filter: reducedMotion ? "none" : filter }, children })
11054
+ }
11055
+ )
11056
+ }
11057
+ );
11058
+ }
11059
+ var carouselCss = `
11060
+ [data-mova-blur-viewport] { scroll-snap-type: x mandatory; }
11061
+ [data-mova-blur-viewport][data-dragging] { scroll-snap-type: none; }
11062
+ [data-mova-blur-viewport]::-webkit-scrollbar { display: none; }
11063
+ [data-mova-blur-viewport]:focus-visible {
11064
+ outline: 2px solid currentColor;
11065
+ outline-offset: -2px;
11066
+ }
11067
+ @media (pointer: fine) {
11068
+ [data-mova-blur-viewport][tabindex] { cursor: grab; }
11069
+ [data-mova-blur-viewport][data-dragging] { cursor: grabbing; }
11070
+ }
11071
+ `;
11072
+ function BlurCarousel({
11073
+ data,
11074
+ renderItem,
11075
+ keyExtractor,
11076
+ spacing = 20,
11077
+ itemWidth,
11078
+ horizontalSpacing,
11079
+ className,
11080
+ style,
11081
+ label = "Carousel"
11082
+ }) {
11083
+ const viewportRef = useRef18(null);
11084
+ const dragRef = useRef18(null);
11085
+ const suppressClick = useRef18(false);
11086
+ const targetIndex = useRef18(null);
11087
+ const settleTimer = useRef18(null);
11088
+ const position = useMotionValue2(0);
11089
+ const reducedMotion = useReducedMotion11() ?? false;
11090
+ const [activeIndex, setActiveIndex] = useState29(0);
11091
+ useEffect19(() => {
11092
+ const viewport = viewportRef.current;
11093
+ const firstSlide = viewport?.querySelector("[data-mova-blur-slide]");
11094
+ if (!viewport || !firstSlide) return;
11095
+ const sync = () => {
11096
+ const width2 = firstSlide.getBoundingClientRect().width;
11097
+ const current = width2 ? Math.abs(viewport.scrollLeft) / width2 : 0;
11098
+ position.set(current);
11099
+ setActiveIndex(Math.min(data.length - 1, Math.round(current)));
11100
+ };
11101
+ const observer = new ResizeObserver(sync);
11102
+ observer.observe(viewport);
11103
+ observer.observe(firstSlide);
11104
+ sync();
11105
+ return () => {
11106
+ observer.disconnect();
11107
+ if (settleTimer.current !== null) clearTimeout(settleTimer.current);
11108
+ };
11109
+ }, [data.length, itemWidth, horizontalSpacing, position]);
11110
+ const slideWidth = (viewport) => viewport.querySelector("[data-mova-blur-slide]")?.getBoundingClientRect().width ?? 0;
11111
+ const direction = (viewport) => getComputedStyle(viewport).direction === "rtl" ? -1 : 1;
11112
+ const clampIndex = (index) => Math.max(0, Math.min(data.length - 1, index));
11113
+ const scrollToSlide = (viewport, index, instant = false) => {
11114
+ const next = clampIndex(index);
11115
+ const left = direction(viewport) * next * slideWidth(viewport);
11116
+ if (Math.abs(viewport.scrollLeft - left) < 1) return;
11117
+ targetIndex.current = next;
11118
+ viewport.scrollTo({ left, behavior: instant || reducedMotion ? "instant" : "smooth" });
11119
+ };
11120
+ const handleScroll = (viewport) => {
11121
+ const width2 = slideWidth(viewport);
11122
+ if (!width2) return;
11123
+ const current = Math.abs(viewport.scrollLeft) / width2;
11124
+ position.set(current);
11125
+ if (settleTimer.current !== null) clearTimeout(settleTimer.current);
11126
+ settleTimer.current = setTimeout(() => {
11127
+ targetIndex.current = null;
11128
+ setActiveIndex(clampIndex(Math.round(position.get())));
11129
+ }, 150);
11130
+ };
11131
+ const handleKeyDown = (event) => {
11132
+ if (event.target !== event.currentTarget || data.length < 2 || event.altKey || event.ctrlKey || event.metaKey) return;
11133
+ const viewport = event.currentTarget;
11134
+ const current = targetIndex.current ?? Math.round(position.get());
11135
+ let next;
11136
+ switch (event.key) {
11137
+ case "ArrowLeft":
11138
+ next = current - direction(viewport);
11139
+ break;
11140
+ case "ArrowRight":
11141
+ next = current + direction(viewport);
11142
+ break;
11143
+ case "Home":
11144
+ next = 0;
11145
+ break;
11146
+ case "End":
11147
+ next = data.length - 1;
11148
+ break;
11149
+ default:
11150
+ return;
11151
+ }
11152
+ event.preventDefault();
11153
+ scrollToSlide(viewport, next);
11154
+ };
11155
+ const handlePointerDown = (event) => {
11156
+ suppressClick.current = false;
11157
+ targetIndex.current = null;
11158
+ if (data.length < 2 || event.pointerType !== "mouse" || event.button !== 0 || !event.isPrimary) return;
11159
+ if (event.target instanceof Element && event.target.closest("input, textarea, select, [contenteditable='true']")) return;
11160
+ dragRef.current = {
11161
+ pointerId: event.pointerId,
11162
+ startX: event.clientX,
11163
+ startLeft: event.currentTarget.scrollLeft,
11164
+ moved: false
11165
+ };
11166
+ };
11167
+ const handlePointerMove = (event) => {
11168
+ const drag = dragRef.current;
11169
+ if (!drag || drag.pointerId !== event.pointerId) return;
11170
+ const delta = event.clientX - drag.startX;
11171
+ const viewport = event.currentTarget;
11172
+ if (!drag.moved) {
11173
+ if (Math.abs(delta) < 5) return;
11174
+ drag.moved = true;
11175
+ viewport.dataset.dragging = "";
11176
+ viewport.setPointerCapture(event.pointerId);
11177
+ }
11178
+ event.preventDefault();
11179
+ viewport.scrollLeft = drag.startLeft - delta;
11180
+ };
11181
+ const finishDrag = (event) => {
11182
+ const drag = dragRef.current;
11183
+ if (!drag || drag.pointerId !== event.pointerId) return;
11184
+ dragRef.current = null;
11185
+ if (!drag.moved) return;
11186
+ const viewport = event.currentTarget;
11187
+ const width2 = slideWidth(viewport);
11188
+ suppressClick.current = true;
11189
+ delete viewport.dataset.dragging;
11190
+ if (width2) scrollToSlide(viewport, Math.round(Math.abs(viewport.scrollLeft) / width2));
11191
+ };
11192
+ if (!data.length) return null;
11193
+ const width = itemWidth === void 0 ? "75%" : `min(100%, ${Math.max(1, itemWidth)}px)`;
11194
+ const sideSpace = horizontalSpacing === void 0 ? "calc((100% - var(--mova-blur-width)) / 2)" : `min(${Math.max(0, horizontalSpacing)}px, calc(100% - var(--mova-blur-width)))`;
11195
+ const viewportStyle = {
11196
+ "--mova-blur-width": width,
11197
+ "--mova-blur-side": sideSpace,
11198
+ "--mova-blur-gap": `min(${Math.max(0, spacing)}px, calc(var(--mova-blur-width) / 4))`,
11199
+ display: "flex",
11200
+ width: "100%",
11201
+ minWidth: 0,
11202
+ overflowX: "auto",
11203
+ overscrollBehaviorX: "contain",
11204
+ scrollbarWidth: "none",
11205
+ paddingBlock: 12,
11206
+ scrollPaddingInlineStart: "var(--mova-blur-side)",
11207
+ userSelect: "none",
11208
+ WebkitUserSelect: "none"
11209
+ };
11210
+ return /* @__PURE__ */ jsxs83("section", { "aria-label": label, "aria-roledescription": "carousel", className, style, children: [
11211
+ /* @__PURE__ */ jsx173("style", { children: carouselCss }),
11212
+ /* @__PURE__ */ jsxs83(
11213
+ "div",
11214
+ {
11215
+ ref: viewportRef,
11216
+ "data-mova-blur-viewport": "",
11217
+ tabIndex: data.length > 1 ? 0 : void 0,
11218
+ "aria-label": data.length > 1 ? "Slides" : void 0,
11219
+ "aria-keyshortcuts": data.length > 1 ? "ArrowLeft ArrowRight Home End" : void 0,
11220
+ onKeyDown: handleKeyDown,
11221
+ onScroll: (event) => handleScroll(event.currentTarget),
11222
+ onWheel: () => {
11223
+ targetIndex.current = null;
11224
+ },
11225
+ onFocusCapture: (event) => {
11226
+ const slide = event.target.closest("[data-mova-blur-slide]");
11227
+ if (slide) scrollToSlide(event.currentTarget, Number(slide.dataset.movaBlurSlide), true);
11228
+ },
11229
+ onDragStart: (event) => {
11230
+ if (dragRef.current) event.preventDefault();
11231
+ },
11232
+ onPointerDown: handlePointerDown,
11233
+ onPointerMove: handlePointerMove,
11234
+ onPointerUp: finishDrag,
11235
+ onPointerCancel: finishDrag,
11236
+ onLostPointerCapture: finishDrag,
11237
+ onPointerLeave: (event) => {
11238
+ if (!dragRef.current?.moved) finishDrag(event);
11239
+ },
11240
+ onClickCapture: (event) => {
11241
+ if (!suppressClick.current || event.detail === 0) return;
11242
+ suppressClick.current = false;
11243
+ event.preventDefault();
11244
+ event.stopPropagation();
11245
+ },
11246
+ style: viewportStyle,
11247
+ children: [
11248
+ /* @__PURE__ */ jsx173("span", { "aria-hidden": "true", style: { flex: "0 0 var(--mova-blur-side)" } }),
11249
+ data.map((item, index) => /* @__PURE__ */ jsx173(
11250
+ CarouselSlide,
11251
+ {
11252
+ index,
11253
+ total: data.length,
11254
+ position,
11255
+ reducedMotion,
11256
+ children: renderItem({ item, index })
11257
+ },
11258
+ keyExtractor?.(item, index) ?? index
11259
+ )),
11260
+ /* @__PURE__ */ jsx173("span", { "aria-hidden": "true", style: { flex: "0 0 calc(100% - var(--mova-blur-width) - var(--mova-blur-side))" } })
11261
+ ]
11262
+ }
11263
+ ),
11264
+ /* @__PURE__ */ jsxs83(
11265
+ "span",
11266
+ {
11267
+ "aria-live": "polite",
11268
+ "aria-atomic": "true",
11269
+ style: { position: "absolute", width: 1, height: 1, padding: 0, overflow: "hidden", clipPath: "inset(50%)", whiteSpace: "nowrap" },
11270
+ children: [
11271
+ Math.min(activeIndex + 1, data.length),
11272
+ " of ",
11273
+ data.length
11274
+ ]
11275
+ }
11276
+ )
11277
+ ] });
11278
+ }
11279
+
11280
+ // .generated/ui/patterns/compare-slider.tsx
11281
+ import { useEffect as useEffect20, useRef as useRef19, useState as useState30 } from "react";
11282
+ import { animate, motion as motion158, useMotionValue as useMotionValue3, useReducedMotion as useReducedMotion12, useTransform as useTransform3 } from "framer-motion";
11283
+ import { ChevronsLeftRight } from "lucide-react";
11284
+ import { jsx as jsx174, jsxs as jsxs84 } from "react/jsx-runtime";
11285
+ var clamp2 = (value) => Math.max(0, Math.min(1, value));
11286
+ var smooth = { type: "spring", stiffness: 210, damping: 27, mass: 1 };
11287
+ var fullFrame = { position: "absolute", inset: 0, pointerEvents: "none" };
11288
+ function CompareSlider({
11289
+ before,
11290
+ after,
11291
+ initial = 0.5,
11292
+ beforeLabel = "Before",
11293
+ afterLabel = "After",
11294
+ aspectRatio = 4 / 3,
11295
+ hint = true,
11296
+ onPositionChange,
11297
+ accessibilityLabel,
11298
+ className,
11299
+ style
11300
+ }) {
11301
+ const [start] = useState30(() => Number.isFinite(initial) ? clamp2(initial) : 0.5);
11302
+ const [value, setValue] = useState30(start);
11303
+ const [held, setHeld] = useState30(false);
11304
+ const gesture = useRef19(null);
11305
+ const hasInteracted = useRef19(false);
11306
+ const position = useMotionValue3(start);
11307
+ const reduced = useReducedMotion12();
11308
+ const left = useTransform3(position, (p) => `${clamp2(p) * 100}%`);
11309
+ const clipPath = useTransform3(position, (p) => `inset(0 ${(1 - clamp2(p)) * 100}% 0 0)`);
11310
+ const leftTagOpacity = useTransform3(position, [0.12, 0.32], [0, 1]);
11311
+ const rightTagOpacity = useTransform3(position, [0.68, 0.88], [1, 0]);
11312
+ useEffect20(() => {
11313
+ if (!hint || reduced || hasInteracted.current) return;
11314
+ let playing = true;
11315
+ const timer = window.setTimeout(async () => {
11316
+ if (hasInteracted.current) return;
11317
+ const nudge = start > 0.8 ? start - 0.12 : Math.min(0.92, start + 0.12);
11318
+ await animate(position, nudge, { duration: 0.42, ease: "easeInOut" });
11319
+ if (playing && !hasInteracted.current) animate(position, start, smooth);
11320
+ }, 500);
11321
+ return () => {
11322
+ playing = false;
11323
+ window.clearTimeout(timer);
11324
+ position.stop();
11325
+ if (!hasInteracted.current) position.set(start);
11326
+ };
11327
+ }, [hint, reduced, position, start]);
11328
+ function report(next, spring2) {
11329
+ setValue(next);
11330
+ if (spring2 && !reduced) animate(position, next, smooth);
11331
+ else position.set(next);
11332
+ onPositionChange?.(next);
11333
+ }
11334
+ function fraction(event) {
11335
+ const rect = event.currentTarget.getBoundingClientRect();
11336
+ return rect.width > 0 ? clamp2((event.clientX - rect.left) / rect.width) : value;
11337
+ }
11338
+ function begin(event) {
11339
+ if (!event.isPrimary || event.button !== 0 || gesture.current) return;
11340
+ hasInteracted.current = true;
11341
+ position.stop();
11342
+ gesture.current = { id: event.pointerId, x: event.clientX, moved: false };
11343
+ event.currentTarget.setPointerCapture(event.pointerId);
11344
+ if (event.pointerType !== "touch") event.currentTarget.focus({ preventScroll: true });
11345
+ setHeld(true);
11346
+ }
11347
+ function move(event) {
11348
+ const active = gesture.current;
11349
+ if (!active || active.id !== event.pointerId) return;
11350
+ if (!active.moved && Math.abs(event.clientX - active.x) < 4) return;
11351
+ active.moved = true;
11352
+ position.set(fraction(event));
11353
+ }
11354
+ function finish(event, canceled = false) {
11355
+ const active = gesture.current;
11356
+ if (!active || active.id !== event.pointerId) return;
11357
+ gesture.current = null;
11358
+ setHeld(false);
11359
+ if (canceled) position.set(value);
11360
+ else report(fraction(event), !active.moved);
11361
+ }
11362
+ const tag = {
11363
+ position: "absolute",
11364
+ top: 12,
11365
+ borderRadius: 999,
11366
+ background: "rgba(0,0,0,.55)",
11367
+ color: "#ededed",
11368
+ padding: "4px 10px",
11369
+ fontSize: 12,
11370
+ lineHeight: "16px",
11371
+ fontWeight: 600,
11372
+ pointerEvents: "none",
11373
+ maxWidth: "45%",
11374
+ overflow: "hidden",
11375
+ textOverflow: "ellipsis",
11376
+ whiteSpace: "nowrap"
11377
+ };
11378
+ const percent = Math.round(value * 100);
11379
+ return /* @__PURE__ */ jsxs84(
11380
+ "div",
11381
+ {
11382
+ role: "slider",
11383
+ "aria-label": accessibilityLabel,
11384
+ "aria-valuemin": 0,
11385
+ "aria-valuemax": 100,
11386
+ "aria-valuenow": percent,
11387
+ "aria-valuetext": `${percent}% ${beforeLabel.toLowerCase()}`,
11388
+ tabIndex: 0,
11389
+ className: `focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current ${className ?? ""}`,
11390
+ onPointerDown: begin,
11391
+ onPointerMove: move,
11392
+ onPointerUp: (event) => finish(event),
11393
+ onPointerCancel: (event) => finish(event, true),
11394
+ onLostPointerCapture: (event) => finish(event, true),
11395
+ onKeyDown: (event) => {
11396
+ const steps = { ArrowLeft: -0.1, ArrowDown: -0.1, ArrowRight: 0.1, ArrowUp: 0.1 };
11397
+ if (event.key !== "Home" && event.key !== "End" && !(event.key in steps)) return;
11398
+ event.preventDefault();
11399
+ hasInteracted.current = true;
11400
+ const next = event.key === "Home" ? 0 : event.key === "End" ? 1 : clamp2(Math.round((value + steps[event.key]) * 10) / 10);
11401
+ report(next, true);
11402
+ },
11403
+ style: {
11404
+ position: "relative",
11405
+ width: "100%",
11406
+ aspectRatio,
11407
+ overflow: "hidden",
11408
+ isolation: "isolate",
11409
+ borderRadius: 28,
11410
+ background: "#050505",
11411
+ cursor: "ew-resize",
11412
+ touchAction: "pan-y pinch-zoom",
11413
+ userSelect: "none",
11414
+ ...style
11415
+ },
11416
+ children: [
11417
+ /* @__PURE__ */ jsx174("div", { style: fullFrame, "aria-hidden": "true", children: after }),
11418
+ /* @__PURE__ */ jsx174(motion158.div, { style: { ...fullFrame, clipPath }, "aria-hidden": "true", children: before }),
11419
+ beforeLabel && /* @__PURE__ */ jsx174(motion158.span, { "aria-hidden": "true", style: { ...tag, left: 12, opacity: leftTagOpacity }, children: beforeLabel }),
11420
+ afterLabel && /* @__PURE__ */ jsx174(motion158.span, { "aria-hidden": "true", style: { ...tag, right: 12, opacity: rightTagOpacity }, children: afterLabel }),
11421
+ /* @__PURE__ */ jsx174(motion158.div, { "aria-hidden": "true", style: {
11422
+ position: "absolute",
11423
+ insetBlock: 0,
11424
+ left,
11425
+ width: 2,
11426
+ x: -1,
11427
+ background: "#fff",
11428
+ display: "grid",
11429
+ placeItems: "center",
11430
+ pointerEvents: "none"
11431
+ }, children: /* @__PURE__ */ jsx174(
11432
+ motion158.div,
11433
+ {
11434
+ animate: { scale: held && !reduced ? 1.12 : 1 },
11435
+ transition: reduced ? { duration: 0 } : smooth,
11436
+ style: {
11437
+ position: "absolute",
11438
+ display: "grid",
11439
+ placeItems: "center",
11440
+ width: 40,
11441
+ height: 40,
11442
+ borderRadius: "50%",
11443
+ background: "#fff",
11444
+ color: "#000",
11445
+ boxShadow: "0 5px 14px #0005"
11446
+ },
11447
+ children: /* @__PURE__ */ jsx174(ChevronsLeftRight, { size: 24, strokeWidth: 2 })
11448
+ }
11449
+ ) })
11450
+ ]
11451
+ }
11452
+ );
11453
+ }
11454
+
10566
11455
  // .generated/ui/patterns/expanding-icon-tabs.tsx
10567
- import { useEffect as useEffect18, useRef as useRef17, useState as useState28 } from "react";
11456
+ import { useEffect as useEffect21, useRef as useRef20, useState as useState31 } from "react";
10568
11457
  import { Activity as Activity2, Compass, CreditCard, SlidersHorizontal as SlidersHorizontal2, Users } from "lucide-react";
10569
- import { jsx as jsx172, jsxs as jsxs82 } from "react/jsx-runtime";
11458
+ import { jsx as jsx175, jsxs as jsxs85 } from "react/jsx-runtime";
10570
11459
  var items = [
10571
11460
  { id: "overview", label: "Overview", icon: Compass },
10572
11461
  { id: "activity", label: "Activity", icon: Activity2 },
@@ -10576,9 +11465,9 @@ var items = [
10576
11465
  { id: "billing", label: "Billing", icon: CreditCard }
10577
11466
  ];
10578
11467
  function ExpandingIconTabs() {
10579
- const [active, setActive] = useState28(null);
10580
- const rootRef = useRef17(null);
10581
- useEffect18(() => {
11468
+ const [active, setActive] = useState31(null);
11469
+ const rootRef = useRef20(null);
11470
+ useEffect21(() => {
10582
11471
  if (!active) return;
10583
11472
  const region = rootRef.current?.parentElement;
10584
11473
  if (!region) return;
@@ -10606,7 +11495,7 @@ function ExpandingIconTabs() {
10606
11495
  setActive(null);
10607
11496
  }
10608
11497
  };
10609
- return /* @__PURE__ */ jsx172(
11498
+ return /* @__PURE__ */ jsx175(
10610
11499
  "div",
10611
11500
  {
10612
11501
  className: "flex max-w-full flex-wrap items-center gap-1 rounded-xl border border-[#2b2f36] bg-[#121418] p-1 text-[11px] text-[#dfe2e5] shadow-[inset_0_1px_0_rgba(255,255,255,.04),0_10px_24px_rgba(0,0,0,.35)]",
@@ -10615,7 +11504,7 @@ function ExpandingIconTabs() {
10615
11504
  ref: rootRef,
10616
11505
  onKeyDown: handleKeyDown,
10617
11506
  children: items.map(
10618
- (item, index) => "separator" in item ? /* @__PURE__ */ jsx172(
11507
+ (item, index) => "separator" in item ? /* @__PURE__ */ jsx175(
10619
11508
  "span",
10620
11509
  {
10621
11510
  className: "mx-[2px] h-[18px] w-px flex-none bg-[#23262c]",
@@ -10623,7 +11512,7 @@ function ExpandingIconTabs() {
10623
11512
  "aria-orientation": "vertical"
10624
11513
  },
10625
11514
  `separator-${index}`
10626
- ) : /* @__PURE__ */ jsxs82(
11515
+ ) : /* @__PURE__ */ jsxs85(
10627
11516
  "button",
10628
11517
  {
10629
11518
  type: "button",
@@ -10633,19 +11522,19 @@ function ExpandingIconTabs() {
10633
11522
  "aria-pressed": active === item.id,
10634
11523
  onClick: () => setActive(active === item.id ? null : item.id),
10635
11524
  children: [
10636
- /* @__PURE__ */ jsx172(
11525
+ /* @__PURE__ */ jsx175(
10637
11526
  "span",
10638
11527
  {
10639
11528
  className: `grid flex-none place-items-center [transition:color_.3s_ease] motion-reduce:[transition-duration:.01ms] ${active === item.id ? "text-[#f97316]" : ""}`,
10640
- children: /* @__PURE__ */ jsx172(item.icon, { size: 15, strokeWidth: 1.8, "aria-hidden": "true" })
11529
+ children: /* @__PURE__ */ jsx175(item.icon, { size: 15, strokeWidth: 1.8, "aria-hidden": "true" })
10641
11530
  }
10642
11531
  ),
10643
- /* @__PURE__ */ jsx172(
11532
+ /* @__PURE__ */ jsx175(
10644
11533
  "span",
10645
11534
  {
10646
11535
  className: `grid overflow-hidden [transition:grid-template-columns_.5s_cubic-bezier(.32,.72,0,1),opacity_.3s_ease] motion-reduce:[transition-duration:.01ms] ${active === item.id ? "grid-cols-[1fr] opacity-100" : "grid-cols-[0fr] opacity-0"}`,
10647
11536
  "aria-hidden": "true",
10648
- children: /* @__PURE__ */ jsx172("span", { className: "min-w-0 overflow-hidden whitespace-nowrap", children: item.label })
11537
+ children: /* @__PURE__ */ jsx175("span", { className: "min-w-0 overflow-hidden whitespace-nowrap", children: item.label })
10649
11538
  }
10650
11539
  )
10651
11540
  ]
@@ -10657,15 +11546,368 @@ function ExpandingIconTabs() {
10657
11546
  );
10658
11547
  }
10659
11548
 
11549
+ // .generated/ui/patterns/fold-panel.tsx
11550
+ import { useCallback as useCallback5, useEffect as useEffect22, useId as useId12, useRef as useRef21, useState as useState32 } from "react";
11551
+ import { motion as motion159, useReducedMotion as useReducedMotion13, useSpring as useSpring5, useTransform as useTransform4 } from "framer-motion";
11552
+ import { ChevronDown as ChevronDown4 } from "lucide-react";
11553
+ import { jsx as jsx176, jsxs as jsxs86 } from "react/jsx-runtime";
11554
+ var foldSpring = { stiffness: 210, damping: 27, mass: 1 };
11555
+ var focusStyle = "focus-visible:outline-2 focus-visible:outline-offset-[-3px] focus-visible:outline-current";
11556
+ function FoldPanel({
11557
+ title,
11558
+ subtitle,
11559
+ leading,
11560
+ children,
11561
+ open,
11562
+ defaultOpen = false,
11563
+ onOpenChange,
11564
+ disabled = false,
11565
+ theme = "dark",
11566
+ className,
11567
+ style
11568
+ }) {
11569
+ const [innerOpen, setInnerOpen] = useState32(defaultOpen);
11570
+ const expanded = open ?? innerOpen;
11571
+ const reduced = useReducedMotion13();
11572
+ const contentId = useId12();
11573
+ const trigger = useRef21(null);
11574
+ const progress = useSpring5(expanded ? 1 : 0, foldSpring);
11575
+ const rows = useTransform4(progress, [0, 1], ["0fr", "1fr"]);
11576
+ const opacity = useTransform4(progress, [0.3, 0.8], [0, 1]);
11577
+ const offset = useTransform4(progress, [0, 1], [-10, 0]);
11578
+ const rotate = useTransform4(progress, [0, 1], [0, 180]);
11579
+ const dark = theme === "dark";
11580
+ const backgroundColor = useTransform4(progress, [0, 1], dark ? ["#0a0a0a", "#1c1c1c"] : ["#fafafa", "#ffffff"]);
11581
+ const borderColor = useTransform4(progress, [0, 1], dark ? ["rgba(255,255,255,.08)", "rgba(255,255,255,.16)"] : ["rgba(0,0,0,.08)", "rgba(0,0,0,.16)"]);
11582
+ useEffect22(() => {
11583
+ const value = expanded ? 1 : 0;
11584
+ if (reduced) progress.jump(value);
11585
+ else progress.set(value);
11586
+ }, [expanded, progress, reduced]);
11587
+ const setContent = useCallback5((element) => {
11588
+ if (!element) return;
11589
+ if (!expanded && element.contains(document.activeElement)) trigger.current?.focus();
11590
+ element.inert = !expanded;
11591
+ }, [expanded]);
11592
+ function toggle() {
11593
+ if (open === void 0) setInnerOpen(!expanded);
11594
+ onOpenChange?.(!expanded);
11595
+ }
11596
+ return /* @__PURE__ */ jsxs86(
11597
+ motion159.div,
11598
+ {
11599
+ className,
11600
+ whileTap: disabled || reduced ? void 0 : { scale: 0.99 },
11601
+ transition: { type: "spring", stiffness: 520, damping: 38, mass: 1 },
11602
+ style: {
11603
+ width: "100%",
11604
+ border: "1px solid",
11605
+ borderRadius: 20,
11606
+ overflow: "hidden",
11607
+ opacity: disabled ? 0.5 : 1,
11608
+ color: dark ? "#ededed" : "#0a0a0a",
11609
+ backgroundColor,
11610
+ borderColor,
11611
+ ...style
11612
+ },
11613
+ children: [
11614
+ /* @__PURE__ */ jsxs86(
11615
+ "button",
11616
+ {
11617
+ ref: trigger,
11618
+ type: "button",
11619
+ className: focusStyle,
11620
+ "aria-controls": contentId,
11621
+ "aria-expanded": expanded,
11622
+ disabled,
11623
+ onClick: toggle,
11624
+ style: {
11625
+ appearance: "none",
11626
+ display: "flex",
11627
+ alignItems: "center",
11628
+ width: "100%",
11629
+ minHeight: 64,
11630
+ gap: 12,
11631
+ padding: "12px 16px",
11632
+ border: 0,
11633
+ background: "none",
11634
+ color: "inherit",
11635
+ font: "inherit",
11636
+ cursor: disabled ? "default" : "pointer",
11637
+ textAlign: "start"
11638
+ },
11639
+ children: [
11640
+ leading != null && /* @__PURE__ */ jsx176("span", { "aria-hidden": "true", style: {
11641
+ display: "grid",
11642
+ placeItems: "center",
11643
+ width: 36,
11644
+ height: 36,
11645
+ flexShrink: 0,
11646
+ borderRadius: 10,
11647
+ color: dark ? "#7ab2ff" : "#1f5fe0",
11648
+ background: dark ? "rgba(59,130,246,.16)" : "rgba(31,95,224,.1)"
11649
+ }, children: leading }),
11650
+ /* @__PURE__ */ jsxs86("span", { style: { display: "grid", flex: 1, minWidth: 0, gap: 2 }, children: [
11651
+ /* @__PURE__ */ jsx176("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontSize: 16, lineHeight: 1.2, fontWeight: 600 }, children: title }),
11652
+ subtitle && /* @__PURE__ */ jsx176("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", fontSize: 14, lineHeight: 1.3, color: dark ? "#a1a1a1" : "#555" }, children: subtitle })
11653
+ ] }),
11654
+ /* @__PURE__ */ jsx176(motion159.span, { "aria-hidden": "true", style: { display: "grid", placeItems: "center", width: 20, height: 20, flexShrink: 0, rotate, color: dark ? "#a1a1a1" : "#555" }, children: /* @__PURE__ */ jsx176(ChevronDown4, { size: 16, strokeWidth: 1.75 }) })
11655
+ ]
11656
+ }
11657
+ ),
11658
+ /* @__PURE__ */ jsx176(motion159.div, { ref: setContent, id: contentId, "aria-hidden": !expanded, style: { display: "grid", gridTemplateRows: rows }, children: /* @__PURE__ */ jsx176("div", { style: { minHeight: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx176(motion159.div, { style: { padding: "0 16px 16px", opacity, y: offset }, children }) }) })
11659
+ ]
11660
+ }
11661
+ );
11662
+ }
11663
+
11664
+ // .generated/ui/patterns/gesture-range-slider.tsx
11665
+ import { useEffect as useEffect23, useRef as useRef22, useState as useState33 } from "react";
11666
+ import { motion as motion160, useReducedMotion as useReducedMotion14, useSpring as useSpring6, useTransform as useTransform5 } from "framer-motion";
11667
+ import { jsx as jsx177, jsxs as jsxs87 } from "react/jsx-runtime";
11668
+ var TRACK_HEIGHT = 40;
11669
+ var THUMB_WIDTH = 6;
11670
+ var THUMB_HEIGHT = 20;
11671
+ var TICK_SIZE = 4;
11672
+ var TICK_INSET = 18;
11673
+ var SPRING_GLIDE = { stiffness: 700, damping: 50, mass: 0.5 };
11674
+ var SPRING_BOUNCY = { type: "spring", stiffness: 500, damping: 14, mass: 0.7 };
11675
+ var PALETTE = {
11676
+ dark: { track: "rgba(120,120,128,0.22)", fill: "rgba(255,255,255,0.16)", thumb: "#ffffff", tick: "rgba(255,255,255,0.25)", focus: "#ffffff" },
11677
+ light: { track: "rgba(120,120,128,0.20)", fill: "rgba(0,0,0,0.14)", thumb: "#171717", tick: "rgba(0,0,0,0.32)", focus: "#171717" }
11678
+ };
11679
+ function clamp3(value, min, max) {
11680
+ return Math.min(max, Math.max(min, value));
11681
+ }
11682
+ function decimalPlaces(value) {
11683
+ const [mantissa, exponent = "0"] = String(value).split("e");
11684
+ return Math.max(0, (mantissa.split(".")[1]?.length ?? 0) - Number(exponent));
11685
+ }
11686
+ function thumbPosition(fraction, extra = 0) {
11687
+ const ratio = clamp3(fraction, 0, 1);
11688
+ return `max(${extra}px, calc(${ratio * 100}% + ${extra - ratio * THUMB_WIDTH}px))`;
11689
+ }
11690
+ var centerVertically = {
11691
+ position: "absolute",
11692
+ pointerEvents: "none",
11693
+ top: "50%"
11694
+ };
11695
+ function GestureRangeSlider({
11696
+ value,
11697
+ defaultValue = 0,
11698
+ onValueChange,
11699
+ min = 0,
11700
+ max = 100,
11701
+ step = 1,
11702
+ showTicks = true,
11703
+ disabled = false,
11704
+ trackColor,
11705
+ fillColor,
11706
+ thumbColor,
11707
+ tickColor,
11708
+ style,
11709
+ accessibilityLabel = "Value",
11710
+ className,
11711
+ theme = "dark"
11712
+ }) {
11713
+ const minimum = Number.isFinite(min) ? min : 0;
11714
+ const maximum = Number.isFinite(max) ? Math.max(minimum, max) : Math.max(minimum, 100);
11715
+ const range = maximum - minimum;
11716
+ const increment = Number.isFinite(step) && step > 0 ? step : 1;
11717
+ const precision = Math.max(decimalPlaces(minimum), decimalPlaces(increment));
11718
+ const canAdjust = !disabled && range > 0 && Number.isFinite(range);
11719
+ const controlled = value !== void 0;
11720
+ const [internal, setInternal] = useState33(defaultValue);
11721
+ const [dragging, setDragging] = useState33(false);
11722
+ const pointerId = useRef22(null);
11723
+ const raw = value ?? internal;
11724
+ const current = clamp3(Number.isFinite(raw) ? raw : minimum, minimum, maximum);
11725
+ const lastValue = useRef22(current);
11726
+ const fraction = range > 0 && Number.isFinite(range) ? (current - minimum) / range : 0;
11727
+ const palette2 = PALETTE[theme];
11728
+ const reducedMotion = useReducedMotion14();
11729
+ const position = useSpring6(fraction, SPRING_GLIDE);
11730
+ const thumbLeft = useTransform5(position, (ratio) => thumbPosition(ratio));
11731
+ const fillWidth = useTransform5(position, (ratio) => thumbPosition(ratio, THUMB_WIDTH / 2));
11732
+ useEffect23(() => {
11733
+ if (controlled || pointerId.current === null) lastValue.current = current;
11734
+ if (reducedMotion) position.jump(fraction);
11735
+ else position.set(fraction);
11736
+ }, [controlled, current, fraction, position, reducedMotion]);
11737
+ function commit(next) {
11738
+ if (lastValue.current === next) return;
11739
+ lastValue.current = next;
11740
+ if (!controlled) setInternal(next);
11741
+ onValueChange?.(next);
11742
+ }
11743
+ function valueFromStep(index) {
11744
+ const stepped = minimum + index * increment;
11745
+ const rounded = precision <= 100 ? Number(stepped.toFixed(precision)) : stepped;
11746
+ return clamp3(rounded, minimum, maximum);
11747
+ }
11748
+ function updateFromPointer(event) {
11749
+ const rect = event.currentTarget.getBoundingClientRect();
11750
+ if (rect.width <= 0) return;
11751
+ const ratio = clamp3((event.clientX - rect.left) / rect.width, 0, 1);
11752
+ commit(valueFromStep(Math.round(ratio * range / increment)));
11753
+ }
11754
+ function startDrag(event) {
11755
+ if (!canAdjust || event.button !== 0 || pointerId.current !== null) return;
11756
+ pointerId.current = event.pointerId;
11757
+ lastValue.current = current;
11758
+ event.currentTarget.setPointerCapture(event.pointerId);
11759
+ setDragging(true);
11760
+ updateFromPointer(event);
11761
+ }
11762
+ function moveDrag(event) {
11763
+ if (canAdjust && pointerId.current === event.pointerId) updateFromPointer(event);
11764
+ }
11765
+ function finishDrag(event) {
11766
+ if (pointerId.current !== event.pointerId) return;
11767
+ if (canAdjust && event.type === "pointerup") updateFromPointer(event);
11768
+ pointerId.current = null;
11769
+ setDragging(false);
11770
+ }
11771
+ function handleKeyDown(event) {
11772
+ if (!canAdjust || pointerId.current !== null) return;
11773
+ const index = (current - minimum) / increment;
11774
+ const nearestIndex = Math.round(index);
11775
+ const onStep = valueFromStep(nearestIndex) === current;
11776
+ const nextIndex = onStep ? nearestIndex + 1 : Math.ceil(index);
11777
+ const previousIndex = onStep ? nearestIndex - 1 : Math.floor(index);
11778
+ let target;
11779
+ switch (event.key) {
11780
+ case "ArrowRight":
11781
+ case "ArrowUp":
11782
+ target = valueFromStep(nextIndex);
11783
+ break;
11784
+ case "ArrowLeft":
11785
+ case "ArrowDown":
11786
+ target = valueFromStep(previousIndex);
11787
+ break;
11788
+ case "PageUp":
11789
+ target = valueFromStep(nextIndex + 9);
11790
+ break;
11791
+ case "PageDown":
11792
+ target = valueFromStep(previousIndex - 9);
11793
+ break;
11794
+ case "Home":
11795
+ target = minimum;
11796
+ break;
11797
+ case "End":
11798
+ target = maximum;
11799
+ break;
11800
+ default:
11801
+ return;
11802
+ }
11803
+ event.preventDefault();
11804
+ lastValue.current = current;
11805
+ commit(target);
11806
+ }
11807
+ const tickSteps = Math.floor(range / increment);
11808
+ const showMarkers = showTicks && tickSteps > 0 && tickSteps <= 50;
11809
+ return /* @__PURE__ */ jsxs87(
11810
+ "div",
11811
+ {
11812
+ role: "slider",
11813
+ "aria-label": accessibilityLabel,
11814
+ "aria-orientation": "horizontal",
11815
+ "aria-valuemin": minimum,
11816
+ "aria-valuemax": maximum,
11817
+ "aria-valuenow": current,
11818
+ "aria-disabled": !canAdjust || void 0,
11819
+ tabIndex: canAdjust ? 0 : -1,
11820
+ "data-mova-gesture-range": "",
11821
+ className,
11822
+ onKeyDown: handleKeyDown,
11823
+ onPointerDown: startDrag,
11824
+ onPointerMove: moveDrag,
11825
+ onPointerUp: finishDrag,
11826
+ onPointerCancel: finishDrag,
11827
+ onLostPointerCapture: finishDrag,
11828
+ style: {
11829
+ position: "relative",
11830
+ width: "100%",
11831
+ height: TRACK_HEIGHT,
11832
+ boxSizing: "border-box",
11833
+ overflow: "hidden",
11834
+ borderRadius: 10,
11835
+ cursor: canAdjust ? "pointer" : "default",
11836
+ touchAction: canAdjust ? "none" : "auto",
11837
+ userSelect: "none",
11838
+ color: palette2.focus,
11839
+ backgroundColor: trackColor ?? palette2.track,
11840
+ opacity: disabled ? 0.5 : 1,
11841
+ ...style
11842
+ },
11843
+ children: [
11844
+ /* @__PURE__ */ jsx177("style", { children: `[data-mova-gesture-range]:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }` }),
11845
+ /* @__PURE__ */ jsx177(
11846
+ motion160.span,
11847
+ {
11848
+ "aria-hidden": "true",
11849
+ style: {
11850
+ position: "absolute",
11851
+ pointerEvents: "none",
11852
+ top: 0,
11853
+ bottom: 0,
11854
+ left: 0,
11855
+ width: fillWidth,
11856
+ backgroundColor: fillColor ?? palette2.fill
11857
+ }
11858
+ }
11859
+ ),
11860
+ showMarkers && Array.from({ length: tickSteps + 1 }, (_, index) => {
11861
+ const ratio = index / tickSteps;
11862
+ return /* @__PURE__ */ jsx177(
11863
+ "span",
11864
+ {
11865
+ "aria-hidden": "true",
11866
+ style: {
11867
+ ...centerVertically,
11868
+ width: TICK_SIZE,
11869
+ height: TICK_SIZE,
11870
+ marginTop: -TICK_SIZE / 2,
11871
+ left: `clamp(0px, calc(${ratio * 100}% + ${TICK_INSET * (1 - 2 * ratio) - TICK_SIZE / 2}px), 100%)`,
11872
+ borderRadius: "50%",
11873
+ backgroundColor: tickColor ?? palette2.tick
11874
+ }
11875
+ },
11876
+ index
11877
+ );
11878
+ }),
11879
+ /* @__PURE__ */ jsx177(
11880
+ motion160.span,
11881
+ {
11882
+ "aria-hidden": "true",
11883
+ initial: false,
11884
+ animate: { scaleY: dragging && canAdjust && !reducedMotion ? 1.35 : 1 },
11885
+ transition: reducedMotion ? { duration: 0 } : SPRING_BOUNCY,
11886
+ style: {
11887
+ ...centerVertically,
11888
+ left: thumbLeft,
11889
+ width: THUMB_WIDTH,
11890
+ height: THUMB_HEIGHT,
11891
+ marginTop: -THUMB_HEIGHT / 2,
11892
+ borderRadius: 3,
11893
+ backgroundColor: thumbColor ?? palette2.thumb
11894
+ }
11895
+ }
11896
+ )
11897
+ ]
11898
+ }
11899
+ );
11900
+ }
11901
+
10660
11902
  // .generated/ui/patterns/gooey-popover.tsx
10661
11903
  import gsap from "gsap";
10662
- import { useCallback as useCallback4, useEffect as useEffect19, useId as useId11, useRef as useRef18, useState as useState29 } from "react";
10663
- import { jsx as jsx173, jsxs as jsxs83 } from "react/jsx-runtime";
11904
+ import { useCallback as useCallback6, useEffect as useEffect24, useId as useId13, useRef as useRef23, useState as useState34 } from "react";
11905
+ import { jsx as jsx178, jsxs as jsxs88 } from "react/jsx-runtime";
10664
11906
  function cn2(...classes) {
10665
11907
  return classes.filter(Boolean).join(" ");
10666
11908
  }
10667
11909
  function useClickOutside(ref, handler, eventType = "mousedown") {
10668
- useEffect19(() => {
11910
+ useEffect24(() => {
10669
11911
  function callback(event) {
10670
11912
  const target = event.target;
10671
11913
  if (!target?.isConnected) return;
@@ -10700,20 +11942,20 @@ function GooeyPopover({
10700
11942
  contentClassName,
10701
11943
  className
10702
11944
  }) {
10703
- const filterId = useId11();
11945
+ const filterId = useId13();
10704
11946
  const isControlled = controlledIsOpen !== void 0;
10705
- const [internalIsOpen, setInternalIsOpen] = useState29(false);
11947
+ const [internalIsOpen, setInternalIsOpen] = useState34(false);
10706
11948
  const isOpen = isControlled ? controlledIsOpen : internalIsOpen;
10707
- const [isVisible, setIsVisible] = useState29(false);
10708
- const containerRef = useRef18(null);
10709
- const measureRef = useRef18(null);
10710
- const filteredContentRef = useRef18(null);
10711
- const unfilteredContentRef = useRef18(null);
10712
- const innerContentRef = useRef18(null);
10713
- const timelineRef = useRef18(null);
10714
- const [contentHeight, setContentHeight] = useState29(0);
10715
- const [prefersReducedMotion, setPrefersReducedMotion] = useState29(false);
10716
- useEffect19(() => {
11949
+ const [isVisible, setIsVisible] = useState34(false);
11950
+ const containerRef = useRef23(null);
11951
+ const measureRef = useRef23(null);
11952
+ const filteredContentRef = useRef23(null);
11953
+ const unfilteredContentRef = useRef23(null);
11954
+ const innerContentRef = useRef23(null);
11955
+ const timelineRef = useRef23(null);
11956
+ const [contentHeight, setContentHeight] = useState34(0);
11957
+ const [prefersReducedMotion, setPrefersReducedMotion] = useState34(false);
11958
+ useEffect24(() => {
10717
11959
  const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
10718
11960
  setPrefersReducedMotion(mq.matches);
10719
11961
  const handler = (e) => {
@@ -10722,7 +11964,7 @@ function GooeyPopover({
10722
11964
  mq.addEventListener("change", handler);
10723
11965
  return () => mq.removeEventListener("change", handler);
10724
11966
  }, []);
10725
- const setIsOpen = useCallback4(
11967
+ const setIsOpen = useCallback6(
10726
11968
  (open) => {
10727
11969
  if (!isControlled) {
10728
11970
  setInternalIsOpen(open);
@@ -10731,13 +11973,13 @@ function GooeyPopover({
10731
11973
  },
10732
11974
  [isControlled, onOpenChange]
10733
11975
  );
10734
- const handleClose = useCallback4(() => {
11976
+ const handleClose = useCallback6(() => {
10735
11977
  if (isOpen) {
10736
11978
  setIsOpen(false);
10737
11979
  }
10738
11980
  }, [isOpen, setIsOpen]);
10739
11981
  useClickOutside(containerRef, handleClose);
10740
- useEffect19(() => {
11982
+ useEffect24(() => {
10741
11983
  const handleKeyDown = (event) => {
10742
11984
  if (event.key === "Escape" && isOpen) {
10743
11985
  setIsOpen(false);
@@ -10746,7 +11988,7 @@ function GooeyPopover({
10746
11988
  window.addEventListener("keydown", handleKeyDown);
10747
11989
  return () => window.removeEventListener("keydown", handleKeyDown);
10748
11990
  }, [isOpen, setIsOpen]);
10749
- useEffect19(() => {
11991
+ useEffect24(() => {
10750
11992
  const measureHeight = () => {
10751
11993
  if (measureRef.current) {
10752
11994
  const height = measureRef.current.scrollHeight;
@@ -10768,7 +12010,7 @@ function GooeyPopover({
10768
12010
  const triggerRadius = triggerSize / 2;
10769
12011
  const translateY = side === "top" ? -(contentHeight + sideOffset) : triggerSize + sideOffset;
10770
12012
  const contentLeft = triggerRadius - contentWidth / 2;
10771
- useEffect19(() => {
12013
+ useEffect24(() => {
10772
12014
  if (contentHeight === 0) {
10773
12015
  return;
10774
12016
  }
@@ -10915,7 +12157,7 @@ function GooeyPopover({
10915
12157
  speed,
10916
12158
  prefersReducedMotion
10917
12159
  ]);
10918
- const defaultTriggerIcon = /* @__PURE__ */ jsxs83(
12160
+ const defaultTriggerIcon = /* @__PURE__ */ jsxs88(
10919
12161
  "svg",
10920
12162
  {
10921
12163
  fill: "none",
@@ -10928,20 +12170,20 @@ function GooeyPopover({
10928
12170
  width: 20,
10929
12171
  xmlns: "http://www.w3.org/2000/svg",
10930
12172
  children: [
10931
- /* @__PURE__ */ jsx173("line", { x1: "12", x2: "12", y1: "5", y2: "19" }),
10932
- /* @__PURE__ */ jsx173("line", { x1: "5", x2: "19", y1: "12", y2: "12" })
12173
+ /* @__PURE__ */ jsx178("line", { x1: "12", x2: "12", y1: "5", y2: "19" }),
12174
+ /* @__PURE__ */ jsx178("line", { x1: "5", x2: "19", y1: "12", y2: "12" })
10933
12175
  ]
10934
12176
  }
10935
12177
  );
10936
- return /* @__PURE__ */ jsxs83("div", { className: cn2("relative inline-flex", className), ref: containerRef, children: [
10937
- /* @__PURE__ */ jsx173(
12178
+ return /* @__PURE__ */ jsxs88("div", { className: cn2("relative inline-flex", className), ref: containerRef, children: [
12179
+ /* @__PURE__ */ jsx178(
10938
12180
  "svg",
10939
12181
  {
10940
12182
  "aria-hidden": "true",
10941
12183
  className: "absolute",
10942
12184
  style: { height: 0, width: 0 },
10943
- children: /* @__PURE__ */ jsx173("defs", { children: /* @__PURE__ */ jsxs83("filter", { id: filterId, children: [
10944
- /* @__PURE__ */ jsx173(
12185
+ children: /* @__PURE__ */ jsx178("defs", { children: /* @__PURE__ */ jsxs88("filter", { id: filterId, children: [
12186
+ /* @__PURE__ */ jsx178(
10945
12187
  "feGaussianBlur",
10946
12188
  {
10947
12189
  in: "SourceGraphic",
@@ -10949,7 +12191,7 @@ function GooeyPopover({
10949
12191
  stdDeviation: GOO_STD_DEVIATION
10950
12192
  }
10951
12193
  ),
10952
- /* @__PURE__ */ jsx173(
12194
+ /* @__PURE__ */ jsx178(
10953
12195
  "feColorMatrix",
10954
12196
  {
10955
12197
  in: "blur",
@@ -10958,11 +12200,11 @@ function GooeyPopover({
10958
12200
  values: `1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 ${String(GOO_MATRIX_ALPHA_MULTIPLIER)} ${String(GOO_MATRIX_ALPHA_OFFSET)}`
10959
12201
  }
10960
12202
  ),
10961
- /* @__PURE__ */ jsx173("feComposite", { in: "SourceGraphic", in2: "goo", operator: "atop" })
12203
+ /* @__PURE__ */ jsx178("feComposite", { in: "SourceGraphic", in2: "goo", operator: "atop" })
10962
12204
  ] }) })
10963
12205
  }
10964
12206
  ),
10965
- /* @__PURE__ */ jsx173(
12207
+ /* @__PURE__ */ jsx178(
10966
12208
  "div",
10967
12209
  {
10968
12210
  "aria-hidden": "true",
@@ -10975,17 +12217,17 @@ function GooeyPopover({
10975
12217
  visibility: "hidden",
10976
12218
  width: contentWidth
10977
12219
  },
10978
- children: /* @__PURE__ */ jsx173("div", { className: cn2("p-4", contentClassName), children })
12220
+ children: /* @__PURE__ */ jsx178("div", { className: cn2("p-4", contentClassName), children })
10979
12221
  }
10980
12222
  ),
10981
- !prefersReducedMotion && (isOpen || isVisible) && /* @__PURE__ */ jsxs83(
12223
+ !prefersReducedMotion && (isOpen || isVisible) && /* @__PURE__ */ jsxs88(
10982
12224
  "div",
10983
12225
  {
10984
12226
  "aria-hidden": "true",
10985
12227
  className: "pointer-events-none absolute inset-0",
10986
12228
  style: { filter: `url(#${filterId})` },
10987
12229
  children: [
10988
- /* @__PURE__ */ jsx173(
12230
+ /* @__PURE__ */ jsx178(
10989
12231
  "div",
10990
12232
  {
10991
12233
  className: cn2("absolute rounded-full", bgClassName),
@@ -10997,7 +12239,7 @@ function GooeyPopover({
10997
12239
  }
10998
12240
  }
10999
12241
  ),
11000
- /* @__PURE__ */ jsx173(
12242
+ /* @__PURE__ */ jsx178(
11001
12243
  "div",
11002
12244
  {
11003
12245
  className: cn2("absolute", bgClassName),
@@ -11015,7 +12257,7 @@ function GooeyPopover({
11015
12257
  ]
11016
12258
  }
11017
12259
  ),
11018
- /* @__PURE__ */ jsx173(
12260
+ /* @__PURE__ */ jsx178(
11019
12261
  "button",
11020
12262
  {
11021
12263
  "aria-expanded": isOpen,
@@ -11033,7 +12275,7 @@ function GooeyPopover({
11033
12275
  children: trigger ?? defaultTriggerIcon
11034
12276
  }
11035
12277
  ),
11036
- isOpen || isVisible ? /* @__PURE__ */ jsx173(
12278
+ isOpen || isVisible ? /* @__PURE__ */ jsx178(
11037
12279
  "div",
11038
12280
  {
11039
12281
  className: cn2(
@@ -11050,7 +12292,7 @@ function GooeyPopover({
11050
12292
  top: 0,
11051
12293
  width: triggerSize
11052
12294
  },
11053
- children: /* @__PURE__ */ jsx173(
12295
+ children: /* @__PURE__ */ jsx178(
11054
12296
  "div",
11055
12297
  {
11056
12298
  className: cn2("p-4", contentClassName),
@@ -11064,22 +12306,779 @@ function GooeyPopover({
11064
12306
  ] });
11065
12307
  }
11066
12308
 
12309
+ // .generated/ui/patterns/long-press-context-menu.tsx
12310
+ import { Fragment as Fragment15, useEffect as useEffect25, useId as useId14, useLayoutEffect as useLayoutEffect11, useRef as useRef24, useState as useState35 } from "react";
12311
+ import { createPortal as createPortal2 } from "react-dom";
12312
+ import { AnimatePresence as AnimatePresence9, motion as motion161, useIsPresent as useIsPresent2, useReducedMotion as useReducedMotion15 } from "framer-motion";
12313
+ import { jsx as jsx179, jsxs as jsxs89 } from "react/jsx-runtime";
12314
+ var LONG_PRESS_DURATION = 250;
12315
+ var PRESS_SCALE = 0.97;
12316
+ var PREVIEW_SCALE = 1.04;
12317
+ var MENU_WIDTH = 250;
12318
+ var MENU_GAP = 30;
12319
+ var SCREEN_PADDING = 22;
12320
+ var OPEN_SPRING = { type: "spring", damping: 12, mass: 0.5, stiffness: 120 };
12321
+ var CLOSE_TRANSITION = { duration: 0.18, ease: "easeOut" };
12322
+ var useClientLayoutEffect = typeof window === "undefined" ? useEffect25 : useLayoutEffect11;
12323
+ var palette = {
12324
+ light: {
12325
+ background: "rgb(250 250 250 / 90%)",
12326
+ text: "#111111",
12327
+ subtitle: "#54545a",
12328
+ destructive: "#b51d13",
12329
+ backdrop: "rgb(0 0 0 / 8%)",
12330
+ separator: "rgb(0 0 0 / 9%)",
12331
+ highlight: "rgb(0 0 0 / 8%)"
12332
+ },
12333
+ dark: {
12334
+ background: "rgb(37 37 37 / 84%)",
12335
+ text: "#ffffff",
12336
+ subtitle: "#b0b0b5",
12337
+ destructive: "#ff5d54",
12338
+ backdrop: "rgb(0 0 0 / 35%)",
12339
+ separator: "rgb(255 255 255 / 10%)",
12340
+ highlight: "rgb(255 255 255 / 12%)"
12341
+ }
12342
+ };
12343
+ var contextMenuCss = `
12344
+ [data-mova-context-trigger]:focus-visible {
12345
+ outline: 2px solid Highlight;
12346
+ outline-offset: 4px;
12347
+ }
12348
+ [data-mova-context-action] { background: transparent; }
12349
+ [data-mova-context-action]:enabled:focus-visible {
12350
+ outline: 2px solid Highlight;
12351
+ outline-offset: -2px;
12352
+ background: var(--mova-context-highlight);
12353
+ }
12354
+ @media (hover: hover) {
12355
+ [data-mova-context-action]:enabled:hover { background: var(--mova-context-highlight); }
12356
+ }
12357
+ [data-mova-context-action]:enabled:active { background: var(--mova-context-highlight); }
12358
+ `;
12359
+ function placeMenu(rect, height, reducedMotion) {
12360
+ const viewport = window.visualViewport;
12361
+ const width = viewport?.width ?? document.documentElement.clientWidth;
12362
+ const viewportHeight = viewport?.height ?? document.documentElement.clientHeight;
12363
+ const inset = Math.min(SCREEN_PADDING, width / 10, viewportHeight / 10);
12364
+ const left = (viewport?.offsetLeft ?? 0) + inset;
12365
+ const top = (viewport?.offsetTop ?? 0) + inset;
12366
+ const availableWidth = width - inset * 2;
12367
+ const availableHeight = viewportHeight - inset * 2;
12368
+ const bottom = top + availableHeight;
12369
+ const gap = Math.min(MENU_GAP, availableHeight / 8);
12370
+ const menuWidth = Math.min(MENU_WIDTH, availableWidth);
12371
+ const scale = Math.min(
12372
+ reducedMotion ? 1 : PREVIEW_SCALE,
12373
+ availableWidth / Math.max(1, rect.width),
12374
+ availableHeight * 0.55 / Math.max(1, rect.height)
12375
+ );
12376
+ const previewWidth = rect.width * scale;
12377
+ const previewHeight = rect.height * scale;
12378
+ const maxHeight = availableHeight - gap - previewHeight;
12379
+ const menuHeight = Math.min(height, maxHeight);
12380
+ const centeredPreviewLeft = rect.left + (rect.width - previewWidth) / 2;
12381
+ const centeredPreviewTop = rect.top + (rect.height - previewHeight) / 2;
12382
+ const previewLeft = Math.max(left, Math.min(left + availableWidth - previewWidth, centeredPreviewLeft));
12383
+ const previewCenter = previewLeft + previewWidth / 2;
12384
+ const menuLeft = Math.max(left, Math.min(left + availableWidth - menuWidth, previewCenter - menuWidth / 2));
12385
+ const spaceAbove = centeredPreviewTop - top;
12386
+ const spaceBelow = bottom - (centeredPreviewTop + previewHeight);
12387
+ const above = spaceBelow < gap + menuHeight && spaceAbove > spaceBelow;
12388
+ const totalHeight = previewHeight + gap + menuHeight;
12389
+ const proposedTop = above ? centeredPreviewTop - gap - menuHeight : centeredPreviewTop;
12390
+ const groupTop = Math.max(top, Math.min(bottom - totalHeight, proposedTop));
12391
+ const previewTop = above ? groupTop + menuHeight + gap : groupTop;
12392
+ return {
12393
+ left: menuLeft,
12394
+ top: above ? groupTop : previewTop + previewHeight + gap,
12395
+ width: menuWidth,
12396
+ maxHeight,
12397
+ origin: `${Math.max(0, Math.min(menuWidth, previewCenter - menuLeft))}px ${above ? "bottom" : "top"}`,
12398
+ shiftX: previewLeft - centeredPreviewLeft,
12399
+ shiftY: previewTop - centeredPreviewTop,
12400
+ scale
12401
+ };
12402
+ }
12403
+ function ContextMenuOverlay({
12404
+ anchor,
12405
+ triggerRef,
12406
+ id,
12407
+ label,
12408
+ children,
12409
+ items: items2,
12410
+ theme,
12411
+ reducedMotion,
12412
+ close
12413
+ }) {
12414
+ const menuRef = useRef24(null);
12415
+ const [placement, setPlacement] = useState35(null);
12416
+ const colors = palette[theme];
12417
+ const isPresent = useIsPresent2();
12418
+ const closeRef = useRef24(close);
12419
+ useClientLayoutEffect(() => {
12420
+ closeRef.current = close;
12421
+ }, [close]);
12422
+ useClientLayoutEffect(() => {
12423
+ const menu = menuRef.current;
12424
+ const trigger = triggerRef.current;
12425
+ if (!menu || !trigger) return;
12426
+ const update = () => setPlacement(placeMenu(anchor.rect, menu.scrollHeight, reducedMotion));
12427
+ const observer = new ResizeObserver(update);
12428
+ observer.observe(menu);
12429
+ if (menu.firstElementChild) observer.observe(menu.firstElementChild);
12430
+ window.addEventListener("resize", update);
12431
+ window.visualViewport?.addEventListener("resize", update);
12432
+ window.visualViewport?.addEventListener("scroll", update);
12433
+ update();
12434
+ return () => {
12435
+ observer.disconnect();
12436
+ window.removeEventListener("resize", update);
12437
+ window.visualViewport?.removeEventListener("resize", update);
12438
+ window.visualViewport?.removeEventListener("scroll", update);
12439
+ };
12440
+ }, [anchor, triggerRef, reducedMotion]);
12441
+ const ready = placement !== null;
12442
+ useClientLayoutEffect(() => {
12443
+ const menu = menuRef.current;
12444
+ if (!menu || !ready || !isPresent) return;
12445
+ const first = menu.querySelector("[data-mova-context-action]:enabled");
12446
+ (first ?? menu).focus({ preventScroll: true });
12447
+ const handleFocus = (event) => {
12448
+ if (event.target instanceof Node && !menu.contains(event.target)) closeRef.current(false);
12449
+ };
12450
+ document.addEventListener("focusin", handleFocus);
12451
+ return () => document.removeEventListener("focusin", handleFocus);
12452
+ }, [isPresent, ready]);
12453
+ const handleKeyDown = (event) => {
12454
+ if (event.key === "Tab") {
12455
+ close();
12456
+ return;
12457
+ }
12458
+ if (event.key === "Escape") {
12459
+ event.preventDefault();
12460
+ event.stopPropagation();
12461
+ close();
12462
+ return;
12463
+ }
12464
+ if (event.altKey || event.ctrlKey || event.metaKey) return;
12465
+ const buttons = Array.from(event.currentTarget.querySelectorAll("[data-mova-context-action]:enabled"));
12466
+ if (!buttons.length) return;
12467
+ const focused = buttons.indexOf(document.activeElement);
12468
+ let next;
12469
+ switch (event.key) {
12470
+ case "ArrowDown":
12471
+ next = (focused + 1) % buttons.length;
12472
+ break;
12473
+ case "ArrowUp":
12474
+ next = focused < 0 ? buttons.length - 1 : (focused - 1 + buttons.length) % buttons.length;
12475
+ break;
12476
+ case "Home":
12477
+ next = 0;
12478
+ break;
12479
+ case "End":
12480
+ next = buttons.length - 1;
12481
+ break;
12482
+ default: {
12483
+ if (event.key.length !== 1 || event.key === " ") return;
12484
+ const key = event.key.toLocaleLowerCase();
12485
+ const ordered = [...buttons.slice(focused + 1), ...buttons.slice(0, focused + 1)];
12486
+ const match = ordered.find((button) => button.dataset.movaContextAction?.toLocaleLowerCase().startsWith(key));
12487
+ if (!match) return;
12488
+ next = buttons.indexOf(match);
12489
+ }
12490
+ }
12491
+ event.preventDefault();
12492
+ event.stopPropagation();
12493
+ buttons[next].focus();
12494
+ };
12495
+ const enter = reducedMotion ? { duration: 0 } : OPEN_SPRING;
12496
+ const exit = reducedMotion ? { duration: 0 } : CLOSE_TRANSITION;
12497
+ const menuRestScale = reducedMotion ? 1 : 0.8;
12498
+ return /* @__PURE__ */ jsxs89(
12499
+ motion161.div,
12500
+ {
12501
+ style: { position: "fixed", inset: 0, zIndex: 2147483647, pointerEvents: "none" },
12502
+ onContextMenu: (event) => event.preventDefault(),
12503
+ children: [
12504
+ /* @__PURE__ */ jsx179(
12505
+ motion161.div,
12506
+ {
12507
+ "aria-hidden": "true",
12508
+ initial: { opacity: 0 },
12509
+ animate: { opacity: 1, transition: enter },
12510
+ exit: { opacity: 0, transition: exit },
12511
+ onClick: () => close(),
12512
+ style: {
12513
+ position: "absolute",
12514
+ inset: 0,
12515
+ pointerEvents: isPresent ? "auto" : "none",
12516
+ touchAction: "none",
12517
+ background: colors.backdrop,
12518
+ backdropFilter: "blur(9px)",
12519
+ WebkitBackdropFilter: "blur(9px)"
12520
+ }
12521
+ }
12522
+ ),
12523
+ /* @__PURE__ */ jsx179(
12524
+ motion161.div,
12525
+ {
12526
+ "aria-hidden": "true",
12527
+ initial: { x: 0, y: 0, scale: anchor.pressed && !reducedMotion ? PRESS_SCALE : 1 },
12528
+ animate: placement ? { x: placement.shiftX, y: placement.shiftY, scale: placement.scale, transition: enter } : void 0,
12529
+ exit: { x: 0, y: 0, scale: 1, transition: exit },
12530
+ style: {
12531
+ position: "absolute",
12532
+ left: anchor.rect.left,
12533
+ top: anchor.rect.top,
12534
+ width: anchor.rect.width,
12535
+ height: anchor.rect.height,
12536
+ font: anchor.font,
12537
+ color: anchor.color
12538
+ },
12539
+ children
12540
+ }
12541
+ ),
12542
+ /* @__PURE__ */ jsx179(
12543
+ motion161.div,
12544
+ {
12545
+ ref: menuRef,
12546
+ id,
12547
+ role: "menu",
12548
+ tabIndex: -1,
12549
+ "aria-label": label,
12550
+ "aria-hidden": !isPresent || void 0,
12551
+ onKeyDown: handleKeyDown,
12552
+ initial: { opacity: 0, scale: menuRestScale },
12553
+ animate: placement ? { opacity: 1, scale: 1, transition: enter } : void 0,
12554
+ exit: { opacity: 0, scale: menuRestScale, transition: exit },
12555
+ style: {
12556
+ "--mova-context-highlight": colors.highlight,
12557
+ boxSizing: "border-box",
12558
+ position: "absolute",
12559
+ left: placement?.left ?? 0,
12560
+ top: placement?.top ?? 0,
12561
+ width: placement?.width ?? `min(${MENU_WIDTH}px, 80vw)`,
12562
+ maxHeight: placement?.maxHeight,
12563
+ visibility: ready ? "visible" : "hidden",
12564
+ pointerEvents: isPresent ? "auto" : "none",
12565
+ transformOrigin: placement?.origin,
12566
+ background: colors.background,
12567
+ color: colors.text,
12568
+ borderRadius: 36,
12569
+ paddingBlock: 12,
12570
+ overflowY: "auto",
12571
+ overscrollBehavior: "contain",
12572
+ scrollbarWidth: "thin",
12573
+ boxShadow: "0 12px 24px rgb(0 0 0 / 20%)",
12574
+ backdropFilter: "blur(24px)",
12575
+ WebkitBackdropFilter: "blur(24px)",
12576
+ font: anchor.font
12577
+ },
12578
+ children: /* @__PURE__ */ jsx179("div", { role: "presentation", style: { paddingInline: 8 }, children: items2.map((item) => /* @__PURE__ */ jsxs89(Fragment15, { children: [
12579
+ item.separatorBefore && /* @__PURE__ */ jsx179("div", { role: "separator", style: { height: 1, margin: "4px 4px", background: colors.separator } }),
12580
+ /* @__PURE__ */ jsxs89(
12581
+ "button",
12582
+ {
12583
+ type: "button",
12584
+ role: "menuitem",
12585
+ "data-mova-context-action": item.label,
12586
+ tabIndex: -1,
12587
+ disabled: item.disabled,
12588
+ onClick: () => {
12589
+ close();
12590
+ item.onSelect?.();
12591
+ },
12592
+ style: {
12593
+ appearance: "none",
12594
+ border: 0,
12595
+ borderRadius: 18,
12596
+ width: "100%",
12597
+ minHeight: 50,
12598
+ display: "flex",
12599
+ alignItems: "center",
12600
+ padding: "8px 10px",
12601
+ gap: 16,
12602
+ color: item.destructive ? colors.destructive : "inherit",
12603
+ opacity: item.disabled ? 0.45 : 1,
12604
+ font: "inherit",
12605
+ textAlign: "start",
12606
+ cursor: item.disabled ? "default" : "pointer"
12607
+ },
12608
+ children: [
12609
+ item.icon !== void 0 && /* @__PURE__ */ jsx179("span", { "aria-hidden": "true", style: { display: "grid", placeItems: "center", flex: "0 0 26px" }, children: item.icon }),
12610
+ /* @__PURE__ */ jsxs89("span", { style: { display: "grid", gap: 1, minWidth: 0 }, children: [
12611
+ /* @__PURE__ */ jsx179("span", { style: { fontSize: 17, lineHeight: 1.2, overflowWrap: "anywhere" }, children: item.label }),
12612
+ item.subtitle && /* @__PURE__ */ jsx179("span", { style: { fontSize: 13, lineHeight: 1.25, color: colors.subtitle, overflowWrap: "anywhere" }, children: item.subtitle })
12613
+ ] })
12614
+ ]
12615
+ }
12616
+ )
12617
+ ] }, item.id)) })
12618
+ }
12619
+ )
12620
+ ]
12621
+ }
12622
+ );
12623
+ }
12624
+ function ContextMenu({
12625
+ children,
12626
+ items: items2,
12627
+ label = "Actions",
12628
+ theme = "light",
12629
+ disabled = false,
12630
+ className
12631
+ }) {
12632
+ const triggerRef = useRef24(null);
12633
+ const pressRef = useRef24(null);
12634
+ const ignoreClick = useRef24(false);
12635
+ const id = useId14();
12636
+ const reducedMotion = useReducedMotion15() ?? false;
12637
+ const [pressing, setPressing] = useState35(false);
12638
+ const [anchor, setAnchor] = useState35(null);
12639
+ const [showPreview, setShowPreview] = useState35(false);
12640
+ const unavailable = disabled || items2.length === 0;
12641
+ useEffect25(() => {
12642
+ const trigger = triggerRef.current;
12643
+ const preventLongPressClick = (event) => {
12644
+ if (ignoreClick.current && event.cancelable) event.preventDefault();
12645
+ };
12646
+ trigger?.addEventListener("touchend", preventLongPressClick, { passive: false });
12647
+ return () => {
12648
+ trigger?.removeEventListener("touchend", preventLongPressClick);
12649
+ if (pressRef.current) clearTimeout(pressRef.current.timer);
12650
+ };
12651
+ }, []);
12652
+ const cancelPress = () => {
12653
+ if (pressRef.current) clearTimeout(pressRef.current.timer);
12654
+ pressRef.current = null;
12655
+ setPressing(false);
12656
+ };
12657
+ const open = (pressed = false) => {
12658
+ const trigger = triggerRef.current;
12659
+ if (!trigger || trigger.disabled || anchor) return;
12660
+ const { font, color } = getComputedStyle(trigger);
12661
+ setAnchor({ rect: trigger.getBoundingClientRect(), font, color, pressed });
12662
+ setShowPreview(true);
12663
+ };
12664
+ const close = (restoreFocus = true) => {
12665
+ setAnchor(null);
12666
+ if (restoreFocus) triggerRef.current?.focus({ preventScroll: true });
12667
+ };
12668
+ useEffect25(() => {
12669
+ if (unavailable && anchor) {
12670
+ setAnchor(null);
12671
+ setShowPreview(false);
12672
+ }
12673
+ }, [anchor, unavailable]);
12674
+ const handlePointerDown = (event) => {
12675
+ if (!event.isPrimary || event.button !== 0 || anchor) return;
12676
+ ignoreClick.current = false;
12677
+ const timer = setTimeout(() => {
12678
+ ignoreClick.current = true;
12679
+ cancelPress();
12680
+ open(true);
12681
+ }, LONG_PRESS_DURATION);
12682
+ pressRef.current = { pointerId: event.pointerId, x: event.clientX, y: event.clientY, timer };
12683
+ setPressing(true);
12684
+ };
12685
+ const handlePointerMove = (event) => {
12686
+ const press = pressRef.current;
12687
+ if (!press || press.pointerId !== event.pointerId) return;
12688
+ if (Math.hypot(event.clientX - press.x, event.clientY - press.y) < 10) return;
12689
+ ignoreClick.current = true;
12690
+ cancelPress();
12691
+ };
12692
+ return /* @__PURE__ */ jsxs89("div", { className, style: { position: "relative", display: "inline-grid", maxWidth: "100%" }, children: [
12693
+ /* @__PURE__ */ jsx179("style", { children: contextMenuCss }),
12694
+ /* @__PURE__ */ jsx179(
12695
+ motion161.div,
12696
+ {
12697
+ animate: { scale: !reducedMotion && pressing ? PRESS_SCALE : 1 },
12698
+ transition: { duration: reducedMotion ? 0 : pressing ? 0.25 : 0.16, ease: "easeOut" },
12699
+ style: { minWidth: 0, visibility: showPreview ? "hidden" : void 0 },
12700
+ children
12701
+ }
12702
+ ),
12703
+ /* @__PURE__ */ jsx179(
12704
+ "button",
12705
+ {
12706
+ ref: triggerRef,
12707
+ type: "button",
12708
+ "data-mova-context-trigger": "",
12709
+ "aria-label": label,
12710
+ "aria-haspopup": "menu",
12711
+ "aria-expanded": anchor !== null,
12712
+ "aria-controls": anchor ? id : void 0,
12713
+ "aria-keyshortcuts": "Shift+F10 ContextMenu",
12714
+ disabled: unavailable,
12715
+ onPointerDown: handlePointerDown,
12716
+ onPointerMove: handlePointerMove,
12717
+ onPointerUp: cancelPress,
12718
+ onPointerCancel: cancelPress,
12719
+ onPointerLeave: cancelPress,
12720
+ onContextMenu: (event) => {
12721
+ if (unavailable) return;
12722
+ event.preventDefault();
12723
+ event.stopPropagation();
12724
+ cancelPress();
12725
+ open();
12726
+ },
12727
+ onKeyDown: (event) => {
12728
+ if (event.key !== "ContextMenu" && !(event.key === "F10" && event.shiftKey)) return;
12729
+ event.preventDefault();
12730
+ event.stopPropagation();
12731
+ open();
12732
+ },
12733
+ onClick: (event) => {
12734
+ if (ignoreClick.current && event.detail !== 0) {
12735
+ ignoreClick.current = false;
12736
+ return;
12737
+ }
12738
+ open();
12739
+ },
12740
+ style: {
12741
+ position: "absolute",
12742
+ inset: 0,
12743
+ width: "100%",
12744
+ height: "100%",
12745
+ appearance: "none",
12746
+ border: 0,
12747
+ padding: 0,
12748
+ borderRadius: "inherit",
12749
+ background: "transparent",
12750
+ color: "inherit",
12751
+ font: "inherit",
12752
+ cursor: unavailable ? void 0 : "context-menu",
12753
+ touchAction: "manipulation",
12754
+ WebkitTouchCallout: "none"
12755
+ }
12756
+ }
12757
+ ),
12758
+ typeof document !== "undefined" && createPortal2(
12759
+ /* @__PURE__ */ jsx179(AnimatePresence9, { onExitComplete: () => setShowPreview(false), children: anchor && /* @__PURE__ */ jsx179(
12760
+ ContextMenuOverlay,
12761
+ {
12762
+ anchor,
12763
+ triggerRef,
12764
+ id,
12765
+ label,
12766
+ items: items2,
12767
+ theme,
12768
+ reducedMotion,
12769
+ close,
12770
+ children
12771
+ },
12772
+ "menu"
12773
+ ) }),
12774
+ document.body
12775
+ )
12776
+ ] });
12777
+ }
12778
+
12779
+ // .generated/ui/patterns/split-view.tsx
12780
+ import {
12781
+ useEffect as useEffect26,
12782
+ useId as useId15,
12783
+ useRef as useRef25,
12784
+ useState as useState36
12785
+ } from "react";
12786
+ import { animate as animate2, motion as motion162, useMotionValue as useMotionValue4, useReducedMotion as useReducedMotion16, useTransform as useTransform6 } from "framer-motion";
12787
+ import { jsx as jsx180, jsxs as jsxs90 } from "react/jsx-runtime";
12788
+ var INSET = 8;
12789
+ var FADE_DISTANCE = 60;
12790
+ var FLING_THRESHOLD = 500;
12791
+ var SNAP_BIAS = 20;
12792
+ var KEYBOARD_STEP = 10;
12793
+ var SPRING = { type: "spring", damping: 12, stiffness: 150, mass: 0.5 };
12794
+ var PALETTE2 = {
12795
+ dark: { root: "#121212", pane: "#1a1a1a", handle: "rgba(255,255,255,0.35)", text: "#f2f2f5" },
12796
+ light: { root: "#eaeaea", pane: "#fafafa", handle: "rgba(0,0,0,0.35)", text: "#171717" }
12797
+ };
12798
+ function clamp4(value, min, max) {
12799
+ return Math.min(max, Math.max(min, value));
12800
+ }
12801
+ function dimension(value, fallback) {
12802
+ return Number.isFinite(value) ? Math.max(0, value) : fallback;
12803
+ }
12804
+ function previousPoint(points, before) {
12805
+ for (let index = points.length - 1; index >= 0; index--) {
12806
+ if (points[index] < before) return points[index];
12807
+ }
12808
+ return void 0;
12809
+ }
12810
+ function resolveSnap(current, velocity, points) {
12811
+ if (velocity > FLING_THRESHOLD) {
12812
+ return points.find((point) => point > current + SNAP_BIAS) ?? points[points.length - 1];
12813
+ }
12814
+ if (velocity < -FLING_THRESHOLD) {
12815
+ return previousPoint(points, current - SNAP_BIAS) ?? points[0];
12816
+ }
12817
+ return points.reduce(
12818
+ (nearest, point) => Math.abs(point - current) < Math.abs(nearest - current) ? point : nearest
12819
+ );
12820
+ }
12821
+ var paneStyle = {
12822
+ borderRadius: 22,
12823
+ minWidth: 0,
12824
+ minHeight: 0,
12825
+ overflow: "hidden"
12826
+ };
12827
+ function SplitView({
12828
+ top,
12829
+ bottom,
12830
+ initialTopHeight = 300,
12831
+ minTopHeight = 50,
12832
+ minBottomHeight = 50,
12833
+ snapPoints,
12834
+ gap = 28,
12835
+ height = 480,
12836
+ theme = "dark",
12837
+ className,
12838
+ style,
12839
+ onTopHeightChange
12840
+ }) {
12841
+ const topId = useId15();
12842
+ const rootRef = useRef25(null);
12843
+ const dragRef = useRef25(null);
12844
+ const animationRef = useRef25(null);
12845
+ const reducedMotion = useReducedMotion16();
12846
+ const palette2 = PALETTE2[theme];
12847
+ const shellHeight = dimension(height, 480);
12848
+ const [measuredHeight, setMeasuredHeight] = useState36(null);
12849
+ const [dragging, setDragging] = useState36(false);
12850
+ const [announcement, setAnnouncement] = useState36("");
12851
+ const availableHeight = measuredHeight ?? Math.max(0, shellHeight - INSET * 2);
12852
+ const handleHeight = Math.min(dimension(gap, 28), availableHeight);
12853
+ const panesHeight = availableHeight - handleHeight;
12854
+ const maxTop = Math.max(0, panesHeight - dimension(minBottomHeight, 50));
12855
+ const minTop = Math.min(dimension(minTopHeight, 50), maxTop);
12856
+ const constrained = minTop === maxTop;
12857
+ const customPoints = snapPoints?.filter(Number.isFinite).map((point) => clamp4(point, minTop, maxTop));
12858
+ const points = customPoints?.length ? [...new Set(customPoints)].sort((a, b) => a - b) : [minTop, (minTop + maxTop) / 2, maxTop];
12859
+ const initialHeight = clamp4(dimension(initialTopHeight, 300), minTop, maxTop);
12860
+ const topHeight = useMotionValue4(initialHeight);
12861
+ const [reportedHeight, setReportedHeight] = useState36(initialHeight);
12862
+ const currentHeight = clamp4(reportedHeight, minTop, maxTop);
12863
+ const topOpacity = useTransform6(topHeight, [minTop, minTop + FADE_DISTANCE], [0.2, 1]);
12864
+ const bottomOpacity = useTransform6(topHeight, [maxTop - FADE_DISTANCE, maxTop], [1, 0.2]);
12865
+ useEffect26(() => {
12866
+ const root = rootRef.current;
12867
+ if (!root) return;
12868
+ const measure = () => {
12869
+ const computed = window.getComputedStyle(root);
12870
+ const padding = parseFloat(computed.paddingTop) + parseFloat(computed.paddingBottom);
12871
+ setMeasuredHeight(Math.max(0, root.clientHeight - padding));
12872
+ };
12873
+ measure();
12874
+ if (typeof ResizeObserver !== "undefined") {
12875
+ const observer = new ResizeObserver(([entry]) => setMeasuredHeight(entry.contentRect.height));
12876
+ observer.observe(root);
12877
+ return () => observer.disconnect();
12878
+ }
12879
+ window.addEventListener("resize", measure);
12880
+ return () => window.removeEventListener("resize", measure);
12881
+ }, [shellHeight]);
12882
+ useEffect26(() => {
12883
+ animationRef.current?.stop();
12884
+ const bounded = clamp4(topHeight.get(), minTop, maxTop);
12885
+ topHeight.jump(bounded);
12886
+ setReportedHeight(bounded);
12887
+ return () => animationRef.current?.stop();
12888
+ }, [maxTop, minTop, topHeight]);
12889
+ function settle(target, announce = false) {
12890
+ const from = topHeight.get();
12891
+ animationRef.current?.stop();
12892
+ setReportedHeight(target);
12893
+ if (announce) setAnnouncement(`Top pane: ${Math.round(target)} pixels`);
12894
+ if (reducedMotion || from === target) {
12895
+ topHeight.jump(target);
12896
+ } else {
12897
+ const down = from < target;
12898
+ animationRef.current = animate2(from, target, {
12899
+ ...SPRING,
12900
+ onUpdate(latest) {
12901
+ const reached = down ? latest >= target : latest <= target;
12902
+ topHeight.set(reached ? target : latest);
12903
+ if (reached) animationRef.current?.stop();
12904
+ }
12905
+ });
12906
+ }
12907
+ onTopHeightChange?.(target);
12908
+ }
12909
+ function startDrag(event) {
12910
+ if (event.button !== 0 || dragRef.current || constrained) return;
12911
+ event.currentTarget.setPointerCapture(event.pointerId);
12912
+ dragRef.current = {
12913
+ pointerId: event.pointerId,
12914
+ originY: event.clientY,
12915
+ originHeight: topHeight.get(),
12916
+ lastY: event.clientY,
12917
+ lastTime: event.timeStamp,
12918
+ velocity: 0,
12919
+ moved: false
12920
+ };
12921
+ setAnnouncement("");
12922
+ }
12923
+ function moveDrag(event) {
12924
+ const drag = dragRef.current;
12925
+ if (drag?.pointerId !== event.pointerId) return;
12926
+ const distance = event.clientY - drag.originY;
12927
+ if (!drag.moved) {
12928
+ if (Math.abs(distance) < 2) return;
12929
+ animationRef.current?.stop();
12930
+ drag.originHeight = topHeight.get();
12931
+ drag.moved = true;
12932
+ setDragging(true);
12933
+ }
12934
+ const elapsed = event.timeStamp - drag.lastTime;
12935
+ if (elapsed > 0) {
12936
+ const velocity = 1e3 * (event.clientY - drag.lastY) / elapsed;
12937
+ drag.velocity = elapsed > 80 ? velocity : drag.velocity * 0.25 + velocity * 0.75;
12938
+ drag.lastTime = event.timeStamp;
12939
+ drag.lastY = event.clientY;
12940
+ }
12941
+ topHeight.set(clamp4(drag.originHeight + distance, minTop, maxTop));
12942
+ }
12943
+ function finishDrag(event) {
12944
+ const drag = dragRef.current;
12945
+ if (drag?.pointerId !== event.pointerId) return;
12946
+ const released = event.type === "pointerup";
12947
+ if (released && event.clientY !== drag.lastY) moveDrag(event);
12948
+ dragRef.current = null;
12949
+ if (!drag.moved) return;
12950
+ setDragging(false);
12951
+ const velocity = released && event.timeStamp - drag.lastTime < 100 ? drag.velocity : 0;
12952
+ settle(resolveSnap(topHeight.get(), velocity, points), true);
12953
+ }
12954
+ function handleKeyDown(event) {
12955
+ if (constrained || dragRef.current) return;
12956
+ const current = currentHeight;
12957
+ let target;
12958
+ switch (event.key) {
12959
+ case "ArrowUp":
12960
+ target = current - KEYBOARD_STEP;
12961
+ break;
12962
+ case "ArrowDown":
12963
+ target = current + KEYBOARD_STEP;
12964
+ break;
12965
+ case "PageUp":
12966
+ target = previousPoint(points, current) ?? minTop;
12967
+ break;
12968
+ case "PageDown":
12969
+ target = points.find((point) => point > current) ?? maxTop;
12970
+ break;
12971
+ case "Home":
12972
+ target = minTop;
12973
+ break;
12974
+ case "End":
12975
+ target = maxTop;
12976
+ break;
12977
+ default:
12978
+ return;
12979
+ }
12980
+ event.preventDefault();
12981
+ const bounded = clamp4(target, minTop, maxTop);
12982
+ if (bounded !== current) settle(bounded);
12983
+ }
12984
+ return /* @__PURE__ */ jsxs90(
12985
+ "div",
12986
+ {
12987
+ ref: rootRef,
12988
+ className,
12989
+ style: {
12990
+ position: "relative",
12991
+ display: "flex",
12992
+ flexDirection: "column",
12993
+ boxSizing: "border-box",
12994
+ width: "100%",
12995
+ height: shellHeight,
12996
+ padding: INSET,
12997
+ overflow: "hidden",
12998
+ borderRadius: 34,
12999
+ color: palette2.text,
13000
+ backgroundColor: palette2.root,
13001
+ ...style
13002
+ },
13003
+ children: [
13004
+ /* @__PURE__ */ jsx180("style", { children: `
13005
+ [data-mova-split-handle]::before { position: absolute; inset: -12px 0; content: ""; }
13006
+ [data-mova-split-handle]:focus-visible { outline: 2px solid currentColor; outline-offset: -2px; }
13007
+ ` }),
13008
+ /* @__PURE__ */ jsx180(
13009
+ motion162.div,
13010
+ {
13011
+ id: topId,
13012
+ style: { ...paneStyle, flexShrink: 0, backgroundColor: palette2.pane, height: topHeight, opacity: constrained ? 1 : topOpacity },
13013
+ children: top
13014
+ }
13015
+ ),
13016
+ /* @__PURE__ */ jsx180(
13017
+ "div",
13018
+ {
13019
+ role: "separator",
13020
+ tabIndex: constrained ? -1 : 0,
13021
+ "aria-label": "Resize top pane",
13022
+ "aria-orientation": "horizontal",
13023
+ "aria-controls": topId,
13024
+ "aria-valuemin": minTop,
13025
+ "aria-valuemax": maxTop,
13026
+ "aria-valuenow": currentHeight,
13027
+ "aria-valuetext": `${Math.round(currentHeight)} pixels`,
13028
+ "aria-disabled": constrained || void 0,
13029
+ "data-mova-split-handle": "",
13030
+ onKeyDown: handleKeyDown,
13031
+ onPointerDown: startDrag,
13032
+ onPointerMove: moveDrag,
13033
+ onPointerUp: finishDrag,
13034
+ onPointerCancel: finishDrag,
13035
+ onLostPointerCapture: finishDrag,
13036
+ style: {
13037
+ position: "relative",
13038
+ zIndex: 1,
13039
+ display: "grid",
13040
+ placeItems: "center",
13041
+ flex: `0 0 ${handleHeight}px`,
13042
+ borderRadius: 6,
13043
+ cursor: constrained ? "default" : "row-resize",
13044
+ touchAction: "none",
13045
+ userSelect: "none"
13046
+ },
13047
+ children: /* @__PURE__ */ jsx180(
13048
+ motion162.span,
13049
+ {
13050
+ "aria-hidden": "true",
13051
+ initial: false,
13052
+ animate: { scale: dragging && !reducedMotion ? 1.18 : 1 },
13053
+ transition: reducedMotion ? { duration: 0 } : SPRING,
13054
+ style: { width: 44, height: 5, borderRadius: 3, backgroundColor: palette2.handle }
13055
+ }
13056
+ )
13057
+ }
13058
+ ),
13059
+ /* @__PURE__ */ jsx180(motion162.div, { style: { ...paneStyle, flex: "1 1 0", backgroundColor: palette2.pane, opacity: constrained ? 1 : bottomOpacity }, children: bottom }),
13060
+ /* @__PURE__ */ jsx180("span", { role: "status", style: { position: "absolute", width: 1, height: 1, overflow: "hidden", clipPath: "inset(50%)" }, children: announcement })
13061
+ ]
13062
+ }
13063
+ );
13064
+ }
13065
+
11067
13066
  // .generated/ui/scroll/progress-indicator.tsx
11068
- import { motion as motion156, useScroll, useSpring as useSpring5 } from "framer-motion";
11069
- import { jsx as jsx174 } from "react/jsx-runtime";
13067
+ import { motion as motion163, useScroll, useSpring as useSpring7 } from "framer-motion";
13068
+ import { jsx as jsx181 } from "react/jsx-runtime";
11070
13069
  function ProgressIndicator({
11071
13070
  color = "bg-blue-500",
11072
13071
  height = 4,
11073
13072
  className = ""
11074
13073
  }) {
11075
13074
  const { scrollYProgress } = useScroll();
11076
- const scaleX = useSpring5(scrollYProgress, {
13075
+ const scaleX = useSpring7(scrollYProgress, {
11077
13076
  stiffness: 100,
11078
13077
  damping: 30,
11079
13078
  restDelta: 1e-3
11080
13079
  });
11081
- return /* @__PURE__ */ jsx174(
11082
- motion156.div,
13080
+ return /* @__PURE__ */ jsx181(
13081
+ motion163.div,
11083
13082
  {
11084
13083
  className: `fixed top-0 left-0 right-0 origin-left z-[9999] ${color} ${className}`,
11085
13084
  style: {
@@ -11097,8 +13096,8 @@ function ProgressIndicator({
11097
13096
  }
11098
13097
 
11099
13098
  // .generated/ui/scroll/scroll-reveal.tsx
11100
- import { motion as motion157 } from "framer-motion";
11101
- import { jsx as jsx175 } from "react/jsx-runtime";
13099
+ import { motion as motion164 } from "framer-motion";
13100
+ import { jsx as jsx182 } from "react/jsx-runtime";
11102
13101
  function ScrollReveal({
11103
13102
  children,
11104
13103
  duration = 0.6,
@@ -11107,8 +13106,8 @@ function ScrollReveal({
11107
13106
  scale = 0.95,
11108
13107
  className = ""
11109
13108
  }) {
11110
- return /* @__PURE__ */ jsx175(
11111
- motion157.div,
13109
+ return /* @__PURE__ */ jsx182(
13110
+ motion164.div,
11112
13111
  {
11113
13112
  initial: { opacity: 0, y: yOffset, x: xOffset, scale },
11114
13113
  whileInView: { opacity: 1, y: 0, x: 0, scale: 1 },
@@ -11125,15 +13124,15 @@ function ScrollReveal({
11125
13124
  }
11126
13125
 
11127
13126
  // .generated/ui/scroll/sticky-reveal.tsx
11128
- import { useRef as useRef19, useState as useState30 } from "react";
11129
- import { motion as motion158, useMotionValueEvent, useScroll as useScroll2 } from "framer-motion";
11130
- import { jsx as jsx176, jsxs as jsxs84 } from "react/jsx-runtime";
13127
+ import { useRef as useRef26, useState as useState37 } from "react";
13128
+ import { motion as motion165, useMotionValueEvent, useScroll as useScroll2 } from "framer-motion";
13129
+ import { jsx as jsx183, jsxs as jsxs91 } from "react/jsx-runtime";
11131
13130
  function StickyReveal({
11132
13131
  content,
11133
13132
  className = ""
11134
13133
  }) {
11135
- const [activeCard, setActiveCard] = useState30(0);
11136
- const ref = useRef19(null);
13134
+ const [activeCard, setActiveCard] = useState37(0);
13135
+ const ref = useRef26(null);
11137
13136
  const { scrollYProgress } = useScroll2({
11138
13137
  target: ref,
11139
13138
  offset: ["start start", "end end"]
@@ -11149,15 +13148,15 @@ function StickyReveal({
11149
13148
  }, 0);
11150
13149
  setActiveCard(closestIndex);
11151
13150
  });
11152
- return /* @__PURE__ */ jsxs84(
13151
+ return /* @__PURE__ */ jsxs91(
11153
13152
  "div",
11154
13153
  {
11155
13154
  ref,
11156
13155
  className: `relative flex justify-between gap-10 max-w-5xl mx-auto py-10 px-4 ${className}`,
11157
13156
  children: [
11158
- /* @__PURE__ */ jsx176("div", { className: "w-1/2 flex flex-col gap-32 py-10", children: content.map((item, index) => /* @__PURE__ */ jsxs84("div", { className: "min-h-[50vh] flex flex-col justify-center", children: [
11159
- /* @__PURE__ */ jsx176(
11160
- motion158.h2,
13157
+ /* @__PURE__ */ jsx183("div", { className: "w-1/2 flex flex-col gap-32 py-10", children: content.map((item, index) => /* @__PURE__ */ jsxs91("div", { className: "min-h-[50vh] flex flex-col justify-center", children: [
13158
+ /* @__PURE__ */ jsx183(
13159
+ motion165.h2,
11161
13160
  {
11162
13161
  animate: {
11163
13162
  opacity: activeCard === index ? 1 : 0.3
@@ -11166,8 +13165,8 @@ function StickyReveal({
11166
13165
  children: item.title
11167
13166
  }
11168
13167
  ),
11169
- /* @__PURE__ */ jsx176(
11170
- motion158.p,
13168
+ /* @__PURE__ */ jsx183(
13169
+ motion165.p,
11171
13170
  {
11172
13171
  animate: {
11173
13172
  opacity: activeCard === index ? 1 : 0.3
@@ -11177,8 +13176,8 @@ function StickyReveal({
11177
13176
  }
11178
13177
  )
11179
13178
  ] }, index)) }),
11180
- /* @__PURE__ */ jsx176("div", { className: "sticky top-20 h-[60vh] w-1/2 rounded-2xl bg-neutral-100 dark:bg-neutral-900 border border-neutral-200/10 overflow-hidden flex items-center justify-center", children: content.map((item, index) => /* @__PURE__ */ jsx176(
11181
- motion158.div,
13179
+ /* @__PURE__ */ jsx183("div", { className: "sticky top-20 h-[60vh] w-1/2 rounded-2xl bg-neutral-100 dark:bg-neutral-900 border border-neutral-200/10 overflow-hidden flex items-center justify-center", children: content.map((item, index) => /* @__PURE__ */ jsx183(
13180
+ motion165.div,
11182
13181
  {
11183
13182
  initial: { opacity: 0, scale: 0.9 },
11184
13183
  animate: {
@@ -11187,7 +13186,7 @@ function StickyReveal({
11187
13186
  },
11188
13187
  transition: { duration: 0.4 },
11189
13188
  className: "absolute inset-0 p-6 flex items-center justify-center",
11190
- children: item.content || /* @__PURE__ */ jsxs84("div", { className: "text-lg font-semibold text-neutral-400", children: [
13189
+ children: item.content || /* @__PURE__ */ jsxs91("div", { className: "text-lg font-semibold text-neutral-400", children: [
11191
13190
  "Card ",
11192
13191
  index + 1,
11193
13192
  " Visual"
@@ -11201,8 +13200,8 @@ function StickyReveal({
11201
13200
  }
11202
13201
 
11203
13202
  // .generated/ui/text/blur-text.tsx
11204
- import { motion as motion159 } from "framer-motion";
11205
- import { jsx as jsx177 } from "react/jsx-runtime";
13203
+ import { motion as motion166 } from "framer-motion";
13204
+ import { jsx as jsx184 } from "react/jsx-runtime";
11206
13205
  function BlurText({
11207
13206
  text,
11208
13207
  duration = 0.5,
@@ -11231,16 +13230,16 @@ function BlurText({
11231
13230
  }
11232
13231
  }
11233
13232
  };
11234
- return /* @__PURE__ */ jsx177(
11235
- motion159.div,
13233
+ return /* @__PURE__ */ jsx184(
13234
+ motion166.div,
11236
13235
  {
11237
13236
  variants: containerVariants,
11238
13237
  initial: "hidden",
11239
13238
  whileInView: "visible",
11240
13239
  viewport: { once: true, margin: "-10%" },
11241
13240
  className: `inline-block ${className}`,
11242
- children: characters.map((char, index) => /* @__PURE__ */ jsx177(
11243
- motion159.span,
13241
+ children: characters.map((char, index) => /* @__PURE__ */ jsx184(
13242
+ motion166.span,
11244
13243
  {
11245
13244
  variants: charVariants,
11246
13245
  className: "inline-block whitespace-pre",
@@ -11253,8 +13252,8 @@ function BlurText({
11253
13252
  }
11254
13253
 
11255
13254
  // .generated/ui/text/character-stagger.tsx
11256
- import { motion as motion160 } from "framer-motion";
11257
- import { jsx as jsx178 } from "react/jsx-runtime";
13255
+ import { motion as motion167 } from "framer-motion";
13256
+ import { jsx as jsx185 } from "react/jsx-runtime";
11258
13257
  function CharacterStagger({
11259
13258
  text,
11260
13259
  duration = 0.4,
@@ -11287,16 +13286,16 @@ function CharacterStagger({
11287
13286
  }
11288
13287
  }
11289
13288
  };
11290
- return /* @__PURE__ */ jsx178(
11291
- motion160.div,
13289
+ return /* @__PURE__ */ jsx185(
13290
+ motion167.div,
11292
13291
  {
11293
13292
  variants: containerVariants,
11294
13293
  initial: "hidden",
11295
13294
  whileInView: "visible",
11296
13295
  viewport: { once: true, margin: "-10%" },
11297
13296
  className: `inline-block ${className}`,
11298
- children: characters.map((char, index) => /* @__PURE__ */ jsx178(
11299
- motion160.span,
13297
+ children: characters.map((char, index) => /* @__PURE__ */ jsx185(
13298
+ motion167.span,
11300
13299
  {
11301
13300
  variants: charVariants,
11302
13301
  className: "inline-block whitespace-pre",
@@ -11309,8 +13308,8 @@ function CharacterStagger({
11309
13308
  }
11310
13309
 
11311
13310
  // .generated/ui/text/text-reveal.tsx
11312
- import { motion as motion161 } from "framer-motion";
11313
- import { jsx as jsx179 } from "react/jsx-runtime";
13311
+ import { motion as motion168 } from "framer-motion";
13312
+ import { jsx as jsx186 } from "react/jsx-runtime";
11314
13313
  function TextReveal({
11315
13314
  text,
11316
13315
  duration = 0.8,
@@ -11338,22 +13337,22 @@ function TextReveal({
11338
13337
  }
11339
13338
  }
11340
13339
  };
11341
- return /* @__PURE__ */ jsx179(
11342
- motion161.div,
13340
+ return /* @__PURE__ */ jsx186(
13341
+ motion168.div,
11343
13342
  {
11344
13343
  variants: containerVariants,
11345
13344
  initial: "hidden",
11346
13345
  whileInView: "visible",
11347
13346
  viewport: { once: true, margin: "-20%" },
11348
13347
  className: `flex flex-col ${className}`,
11349
- children: lines.map((line, index) => /* @__PURE__ */ jsx179("div", { className: "overflow-hidden py-1", children: /* @__PURE__ */ jsx179(motion161.span, { variants: itemVariants, className: "block", children: line }) }, index))
13348
+ children: lines.map((line, index) => /* @__PURE__ */ jsx186("div", { className: "overflow-hidden py-1", children: /* @__PURE__ */ jsx186(motion168.span, { variants: itemVariants, className: "block", children: line }) }, index))
11350
13349
  }
11351
13350
  );
11352
13351
  }
11353
13352
 
11354
13353
  // .generated/ui/text/word-reveal.tsx
11355
- import { motion as motion162 } from "framer-motion";
11356
- import { jsx as jsx180 } from "react/jsx-runtime";
13354
+ import { motion as motion169 } from "framer-motion";
13355
+ import { jsx as jsx187 } from "react/jsx-runtime";
11357
13356
  function WordReveal({
11358
13357
  text,
11359
13358
  duration = 0.5,
@@ -11383,16 +13382,16 @@ function WordReveal({
11383
13382
  }
11384
13383
  }
11385
13384
  };
11386
- return /* @__PURE__ */ jsx180(
11387
- motion162.div,
13385
+ return /* @__PURE__ */ jsx187(
13386
+ motion169.div,
11388
13387
  {
11389
13388
  variants: containerVariants,
11390
13389
  initial: "hidden",
11391
13390
  whileInView: "visible",
11392
13391
  viewport: { once: true, margin: "-10%" },
11393
13392
  className: `flex flex-wrap gap-x-2 gap-y-1.5 ${className}`,
11394
- children: words.map((word, index) => /* @__PURE__ */ jsx180(
11395
- motion162.span,
13393
+ children: words.map((word, index) => /* @__PURE__ */ jsx187(
13394
+ motion169.span,
11396
13395
  {
11397
13396
  variants: wordVariants,
11398
13397
  className: "inline-block",
@@ -11405,18 +13404,18 @@ function WordReveal({
11405
13404
  }
11406
13405
 
11407
13406
  // .generated/ui/toggles/classic-toggle.tsx
11408
- import { useState as useState31 } from "react";
11409
- import { motion as motion163 } from "framer-motion";
11410
- import { jsx as jsx181 } from "react/jsx-runtime";
13407
+ import { useState as useState38 } from "react";
13408
+ import { motion as motion170 } from "framer-motion";
13409
+ import { jsx as jsx188 } from "react/jsx-runtime";
11411
13410
  var ClassicToggle = () => {
11412
- const [isOn, setIsOn] = useState31(false);
11413
- return /* @__PURE__ */ jsx181(
13411
+ const [isOn, setIsOn] = useState38(false);
13412
+ return /* @__PURE__ */ jsx188(
11414
13413
  "button",
11415
13414
  {
11416
13415
  onClick: () => setIsOn(!isOn),
11417
13416
  className: `relative w-16 h-9 rounded-full p-1 transition-colors duration-300 cursor-pointer border-0 ${isOn ? "bg-emerald-500" : "bg-neutral-800"}`,
11418
- children: /* @__PURE__ */ jsx181(
11419
- motion163.div,
13417
+ children: /* @__PURE__ */ jsx188(
13418
+ motion170.div,
11420
13419
  {
11421
13420
  animate: { x: isOn ? 28 : 0 },
11422
13421
  transition: { type: "spring", stiffness: 500, damping: 30 },
@@ -11428,17 +13427,17 @@ var ClassicToggle = () => {
11428
13427
  };
11429
13428
 
11430
13429
  // .generated/ui/transitions/page-transition.tsx
11431
- import { useEffect as useEffect20, useRef as useRef20 } from "react";
11432
- import { motion as motion164 } from "framer-motion";
11433
- import { jsx as jsx182, jsxs as jsxs85 } from "react/jsx-runtime";
13430
+ import { useEffect as useEffect27, useRef as useRef27 } from "react";
13431
+ import { motion as motion171 } from "framer-motion";
13432
+ import { jsx as jsx189, jsxs as jsxs92 } from "react/jsx-runtime";
11434
13433
  var PageTransition = ({
11435
13434
  type = "double-stairs",
11436
13435
  isVisible,
11437
13436
  onComplete,
11438
13437
  className = ""
11439
13438
  }) => {
11440
- const pathRefs = useRef20([]);
11441
- useEffect20(() => {
13439
+ const pathRefs = useRef27([]);
13440
+ useEffect27(() => {
11442
13441
  if (type !== "liquid-wave" || !isVisible) return;
11443
13442
  let animId;
11444
13443
  const numPoints = 12;
@@ -11491,8 +13490,8 @@ var PageTransition = ({
11491
13490
  transition: { duration: 0.8, ease: [0.76, 0, 0.24, 1], delay: i * 0.05 }
11492
13491
  })
11493
13492
  };
11494
- return /* @__PURE__ */ jsx182(
11495
- motion164.div,
13493
+ return /* @__PURE__ */ jsx189(
13494
+ motion171.div,
11496
13495
  {
11497
13496
  className: `fixed inset-0 z-50 flex h-screen w-screen pointer-events-none ${className}`,
11498
13497
  initial: "initial",
@@ -11500,8 +13499,8 @@ var PageTransition = ({
11500
13499
  onAnimationComplete: () => {
11501
13500
  if (onComplete) onComplete();
11502
13501
  },
11503
- children: [...Array(COLUMNS)].map((_, i) => /* @__PURE__ */ jsx182(
11504
- motion164.div,
13502
+ children: [...Array(COLUMNS)].map((_, i) => /* @__PURE__ */ jsx189(
13503
+ motion171.div,
11505
13504
  {
11506
13505
  variants,
11507
13506
  custom: i,
@@ -11513,28 +13512,28 @@ var PageTransition = ({
11513
13512
  );
11514
13513
  }
11515
13514
  if (type === "liquid-wave") {
11516
- return /* @__PURE__ */ jsxs85(
13515
+ return /* @__PURE__ */ jsxs92(
11517
13516
  "svg",
11518
13517
  {
11519
13518
  className: `fixed inset-0 w-full h-full pointer-events-none z-50 ${className}`,
11520
13519
  viewBox: "0 0 100 100",
11521
13520
  preserveAspectRatio: "none",
11522
13521
  children: [
11523
- /* @__PURE__ */ jsx182("path", { ref: (el) => {
13522
+ /* @__PURE__ */ jsx189("path", { ref: (el) => {
11524
13523
  pathRefs.current[0] = el;
11525
13524
  }, fill: "#3f3f46", style: { opacity: 0.4 } }),
11526
- /* @__PURE__ */ jsx182("path", { ref: (el) => {
13525
+ /* @__PURE__ */ jsx189("path", { ref: (el) => {
11527
13526
  pathRefs.current[1] = el;
11528
13527
  }, fill: "#27272a", style: { opacity: 0.75 } }),
11529
- /* @__PURE__ */ jsx182("path", { ref: (el) => {
13528
+ /* @__PURE__ */ jsx189("path", { ref: (el) => {
11530
13529
  pathRefs.current[2] = el;
11531
13530
  }, fill: "#09090b" })
11532
13531
  ]
11533
13532
  }
11534
13533
  );
11535
13534
  }
11536
- return /* @__PURE__ */ jsx182(
11537
- motion164.div,
13535
+ return /* @__PURE__ */ jsx189(
13536
+ motion171.div,
11538
13537
  {
11539
13538
  className: `fixed inset-0 z-50 bg-neutral-900 pointer-events-none ${className}`,
11540
13539
  initial: { opacity: 0 },
@@ -11556,6 +13555,7 @@ export {
11556
13555
  ai_tool_call_default as AIToolCall,
11557
13556
  AccordionLoader,
11558
13557
  AnalyzingImage,
13558
+ AnimatedMegaMenu,
11559
13559
  AnimatedSidebar,
11560
13560
  AnimatedTags,
11561
13561
  AppIconLoad,
@@ -11571,6 +13571,7 @@ export {
11571
13571
  BalanceBarChartCard,
11572
13572
  BarCascade,
11573
13573
  BarSweep,
13574
+ BlurCarousel,
11574
13575
  BlurText,
11575
13576
  BobbingDots,
11576
13577
  BorderTrailLoading,
@@ -11590,9 +13591,11 @@ export {
11590
13591
  ClassicToggle,
11591
13592
  ClockSpinner,
11592
13593
  CometSpinner,
13594
+ CompareSlider,
11593
13595
  ConcentricPulse,
11594
13596
  ConcentricRing,
11595
13597
  ConcentricSquares,
13598
+ ContextMenu,
11596
13599
  ConveyorLoop,
11597
13600
  CrossSpinner,
11598
13601
  CubeFlipSpring,
@@ -11624,7 +13627,9 @@ export {
11624
13627
  FluidDiamond,
11625
13628
  FluidDotOrbit,
11626
13629
  FluidSkeleton,
13630
+ FoldPanel,
11627
13631
  Gears,
13632
+ GestureRangeSlider,
11628
13633
  GlassmorphicCard,
11629
13634
  GlowButton,
11630
13635
  GooeyPopover,
@@ -11688,6 +13693,7 @@ export {
11688
13693
  SmoothRoundedSquare,
11689
13694
  SpinningSquares,
11690
13695
  SpiralSpinner,
13696
+ SplitView,
11691
13697
  Spotlight,
11692
13698
  SpringBars,
11693
13699
  SpringDotMatrix,