@omerdlw/base-framework 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (383) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +117 -0
  3. package/dist/atoms/button.d.ts +11 -0
  4. package/dist/atoms/button.d.ts.map +1 -0
  5. package/dist/atoms/icon.d.ts +15 -0
  6. package/dist/atoms/icon.d.ts.map +1 -0
  7. package/dist/atoms/index.d.ts +6 -0
  8. package/dist/atoms/index.d.ts.map +1 -0
  9. package/dist/atoms/index.js +169 -0
  10. package/dist/atoms/index.js.map +1 -0
  11. package/dist/atoms/spinner.d.ts +9 -0
  12. package/dist/atoms/spinner.d.ts.map +1 -0
  13. package/dist/atoms/tooltip.d.ts +18 -0
  14. package/dist/atoms/tooltip.d.ts.map +1 -0
  15. package/dist/error/boundary.d.ts +14 -0
  16. package/dist/error/boundary.d.ts.map +1 -0
  17. package/dist/error/constants.d.ts +18 -0
  18. package/dist/error/constants.d.ts.map +1 -0
  19. package/dist/error/index.d.ts +9 -0
  20. package/dist/error/index.d.ts.map +1 -0
  21. package/dist/error/index.js +688 -0
  22. package/dist/error/index.js.map +1 -0
  23. package/dist/error/listener.d.ts +2 -0
  24. package/dist/error/listener.d.ts.map +1 -0
  25. package/dist/error/reporter.d.ts +32 -0
  26. package/dist/error/reporter.d.ts.map +1 -0
  27. package/dist/error/theme.d.ts +3 -0
  28. package/dist/error/theme.d.ts.map +1 -0
  29. package/dist/error/types.d.ts +91 -0
  30. package/dist/error/types.d.ts.map +1 -0
  31. package/dist/error/utils.d.ts +21 -0
  32. package/dist/error/utils.d.ts.map +1 -0
  33. package/dist/events.d.ts +51 -0
  34. package/dist/events.d.ts.map +1 -0
  35. package/dist/events.js +88 -0
  36. package/dist/events.js.map +1 -0
  37. package/dist/hooks/index.d.ts +17 -0
  38. package/dist/hooks/index.d.ts.map +1 -0
  39. package/dist/hooks/index.js +804 -0
  40. package/dist/hooks/index.js.map +1 -0
  41. package/dist/hooks/types.d.ts +58 -0
  42. package/dist/hooks/types.d.ts.map +1 -0
  43. package/dist/hooks/use-async-action.d.ts +3 -0
  44. package/dist/hooks/use-async-action.d.ts.map +1 -0
  45. package/dist/hooks/use-click-outside.d.ts +3 -0
  46. package/dist/hooks/use-click-outside.d.ts.map +1 -0
  47. package/dist/hooks/use-controllable-state.d.ts +3 -0
  48. package/dist/hooks/use-controllable-state.d.ts.map +1 -0
  49. package/dist/hooks/use-debounce.d.ts +2 -0
  50. package/dist/hooks/use-debounce.d.ts.map +1 -0
  51. package/dist/hooks/use-fullscreen-state.d.ts +4 -0
  52. package/dist/hooks/use-fullscreen-state.d.ts.map +1 -0
  53. package/dist/hooks/use-global-event.d.ts +7 -0
  54. package/dist/hooks/use-global-event.d.ts.map +1 -0
  55. package/dist/hooks/use-hotkey.d.ts +4 -0
  56. package/dist/hooks/use-hotkey.d.ts.map +1 -0
  57. package/dist/hooks/use-intersection-observer.d.ts +4 -0
  58. package/dist/hooks/use-intersection-observer.d.ts.map +1 -0
  59. package/dist/hooks/use-isomorphic-layout-effect.d.ts +3 -0
  60. package/dist/hooks/use-isomorphic-layout-effect.d.ts.map +1 -0
  61. package/dist/hooks/use-media-query.d.ts +2 -0
  62. package/dist/hooks/use-media-query.d.ts.map +1 -0
  63. package/dist/hooks/use-mounted.d.ts +2 -0
  64. package/dist/hooks/use-mounted.d.ts.map +1 -0
  65. package/dist/hooks/use-required-context.d.ts +3 -0
  66. package/dist/hooks/use-required-context.d.ts.map +1 -0
  67. package/dist/hooks/use-server-action.d.ts +4 -0
  68. package/dist/hooks/use-server-action.d.ts.map +1 -0
  69. package/dist/hooks/use-storage-state.d.ts +5 -0
  70. package/dist/hooks/use-storage-state.d.ts.map +1 -0
  71. package/dist/hooks/use-store.d.ts +3 -0
  72. package/dist/hooks/use-store.d.ts.map +1 -0
  73. package/dist/index.d.ts +12 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +20415 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/kernel/adapters.d.ts +5 -0
  78. package/dist/kernel/adapters.d.ts.map +1 -0
  79. package/dist/kernel/compose.d.ts +15 -0
  80. package/dist/kernel/compose.d.ts.map +1 -0
  81. package/dist/kernel/constants.d.ts +12 -0
  82. package/dist/kernel/constants.d.ts.map +1 -0
  83. package/dist/kernel/context-registry.d.ts +3 -0
  84. package/dist/kernel/context-registry.d.ts.map +1 -0
  85. package/dist/kernel/handlers.d.ts +3 -0
  86. package/dist/kernel/handlers.d.ts.map +1 -0
  87. package/dist/kernel/hooks.d.ts +7 -0
  88. package/dist/kernel/hooks.d.ts.map +1 -0
  89. package/dist/kernel/index.d.ts +14 -0
  90. package/dist/kernel/index.d.ts.map +1 -0
  91. package/dist/kernel/index.js +2109 -0
  92. package/dist/kernel/index.js.map +1 -0
  93. package/dist/kernel/installed.d.ts +21 -0
  94. package/dist/kernel/installed.d.ts.map +1 -0
  95. package/dist/kernel/module.d.ts +32 -0
  96. package/dist/kernel/module.d.ts.map +1 -0
  97. package/dist/kernel/operations.d.ts +21 -0
  98. package/dist/kernel/operations.d.ts.map +1 -0
  99. package/dist/kernel/page-controller.d.ts +8 -0
  100. package/dist/kernel/page-controller.d.ts.map +1 -0
  101. package/dist/kernel/provider.d.ts +18 -0
  102. package/dist/kernel/provider.d.ts.map +1 -0
  103. package/dist/kernel/runtime.d.ts +30 -0
  104. package/dist/kernel/runtime.d.ts.map +1 -0
  105. package/dist/kernel/schema.d.ts +13 -0
  106. package/dist/kernel/schema.d.ts.map +1 -0
  107. package/dist/kernel/store.d.ts +4 -0
  108. package/dist/kernel/store.d.ts.map +1 -0
  109. package/dist/kernel/types.d.ts +233 -0
  110. package/dist/kernel/types.d.ts.map +1 -0
  111. package/dist/kernel/utils.d.ts +20 -0
  112. package/dist/kernel/utils.d.ts.map +1 -0
  113. package/dist/modules/ambient/constants.d.ts +23 -0
  114. package/dist/modules/ambient/constants.d.ts.map +1 -0
  115. package/dist/modules/ambient/context.d.ts +10 -0
  116. package/dist/modules/ambient/context.d.ts.map +1 -0
  117. package/dist/modules/ambient/index.d.ts +6 -0
  118. package/dist/modules/ambient/index.d.ts.map +1 -0
  119. package/dist/modules/ambient/index.js +896 -0
  120. package/dist/modules/ambient/index.js.map +1 -0
  121. package/dist/modules/ambient/module.d.ts +12 -0
  122. package/dist/modules/ambient/module.d.ts.map +1 -0
  123. package/dist/modules/ambient/types.d.ts +84 -0
  124. package/dist/modules/ambient/types.d.ts.map +1 -0
  125. package/dist/modules/ambient/utils.d.ts +18 -0
  126. package/dist/modules/ambient/utils.d.ts.map +1 -0
  127. package/dist/modules/background/constants.d.ts +12 -0
  128. package/dist/modules/background/constants.d.ts.map +1 -0
  129. package/dist/modules/background/context.d.ts +13 -0
  130. package/dist/modules/background/context.d.ts.map +1 -0
  131. package/dist/modules/background/hooks.d.ts +119 -0
  132. package/dist/modules/background/hooks.d.ts.map +1 -0
  133. package/dist/modules/background/index.d.ts +7 -0
  134. package/dist/modules/background/index.d.ts.map +1 -0
  135. package/dist/modules/background/index.js +3195 -0
  136. package/dist/modules/background/index.js.map +1 -0
  137. package/dist/modules/background/module.d.ts +14 -0
  138. package/dist/modules/background/module.d.ts.map +1 -0
  139. package/dist/modules/background/motion.d.ts +13 -0
  140. package/dist/modules/background/motion.d.ts.map +1 -0
  141. package/dist/modules/background/overlay.d.ts +49 -0
  142. package/dist/modules/background/overlay.d.ts.map +1 -0
  143. package/dist/modules/background/types.d.ts +153 -0
  144. package/dist/modules/background/types.d.ts.map +1 -0
  145. package/dist/modules/background/utils.d.ts +56 -0
  146. package/dist/modules/background/utils.d.ts.map +1 -0
  147. package/dist/modules/background/youtube/iframe.d.ts +52 -0
  148. package/dist/modules/background/youtube/iframe.d.ts.map +1 -0
  149. package/dist/modules/background/youtube/parse.d.ts +17 -0
  150. package/dist/modules/background/youtube/parse.d.ts.map +1 -0
  151. package/dist/modules/context-menu/constants.d.ts +8 -0
  152. package/dist/modules/context-menu/constants.d.ts.map +1 -0
  153. package/dist/modules/context-menu/context.d.ts +16 -0
  154. package/dist/modules/context-menu/context.d.ts.map +1 -0
  155. package/dist/modules/context-menu/hooks.d.ts +31 -0
  156. package/dist/modules/context-menu/hooks.d.ts.map +1 -0
  157. package/dist/modules/context-menu/index.d.ts +6 -0
  158. package/dist/modules/context-menu/index.d.ts.map +1 -0
  159. package/dist/modules/context-menu/index.js +2008 -0
  160. package/dist/modules/context-menu/index.js.map +1 -0
  161. package/dist/modules/context-menu/module.d.ts +12 -0
  162. package/dist/modules/context-menu/module.d.ts.map +1 -0
  163. package/dist/modules/context-menu/motion.d.ts +9 -0
  164. package/dist/modules/context-menu/motion.d.ts.map +1 -0
  165. package/dist/modules/context-menu/overlay.d.ts +15 -0
  166. package/dist/modules/context-menu/overlay.d.ts.map +1 -0
  167. package/dist/modules/context-menu/resolver.d.ts +7 -0
  168. package/dist/modules/context-menu/resolver.d.ts.map +1 -0
  169. package/dist/modules/context-menu/state.d.ts +4 -0
  170. package/dist/modules/context-menu/state.d.ts.map +1 -0
  171. package/dist/modules/context-menu/types.d.ts +171 -0
  172. package/dist/modules/context-menu/types.d.ts.map +1 -0
  173. package/dist/modules/context-menu/utils.d.ts +16 -0
  174. package/dist/modules/context-menu/utils.d.ts.map +1 -0
  175. package/dist/modules/controls/constants.d.ts +7 -0
  176. package/dist/modules/controls/constants.d.ts.map +1 -0
  177. package/dist/modules/controls/hooks.d.ts +15 -0
  178. package/dist/modules/controls/hooks.d.ts.map +1 -0
  179. package/dist/modules/controls/index.d.ts +6 -0
  180. package/dist/modules/controls/index.d.ts.map +1 -0
  181. package/dist/modules/controls/index.js +1242 -0
  182. package/dist/modules/controls/index.js.map +1 -0
  183. package/dist/modules/controls/module.d.ts +12 -0
  184. package/dist/modules/controls/module.d.ts.map +1 -0
  185. package/dist/modules/controls/overlay.d.ts +2 -0
  186. package/dist/modules/controls/overlay.d.ts.map +1 -0
  187. package/dist/modules/controls/types.d.ts +86 -0
  188. package/dist/modules/controls/types.d.ts.map +1 -0
  189. package/dist/modules/controls/utils.d.ts +9 -0
  190. package/dist/modules/controls/utils.d.ts.map +1 -0
  191. package/dist/modules/dock/cards.d.ts +1035 -0
  192. package/dist/modules/dock/cards.d.ts.map +1 -0
  193. package/dist/modules/dock/constants.d.ts +157 -0
  194. package/dist/modules/dock/constants.d.ts.map +1 -0
  195. package/dist/modules/dock/context.d.ts +26 -0
  196. package/dist/modules/dock/context.d.ts.map +1 -0
  197. package/dist/modules/dock/hooks.d.ts +957 -0
  198. package/dist/modules/dock/hooks.d.ts.map +1 -0
  199. package/dist/modules/dock/hud.d.ts +43 -0
  200. package/dist/modules/dock/hud.d.ts.map +1 -0
  201. package/dist/modules/dock/index.d.ts +27 -0
  202. package/dist/modules/dock/index.d.ts.map +1 -0
  203. package/dist/modules/dock/index.js +12111 -0
  204. package/dist/modules/dock/index.js.map +1 -0
  205. package/dist/modules/dock/module.d.ts +71 -0
  206. package/dist/modules/dock/module.d.ts.map +1 -0
  207. package/dist/modules/dock/motion.d.ts +986 -0
  208. package/dist/modules/dock/motion.d.ts.map +1 -0
  209. package/dist/modules/dock/overlay.d.ts +79 -0
  210. package/dist/modules/dock/overlay.d.ts.map +1 -0
  211. package/dist/modules/dock/provider.d.ts +3 -0
  212. package/dist/modules/dock/provider.d.ts.map +1 -0
  213. package/dist/modules/dock/routing/breadcrumbs.d.ts +43 -0
  214. package/dist/modules/dock/routing/breadcrumbs.d.ts.map +1 -0
  215. package/dist/modules/dock/routing/continuity.d.ts +19 -0
  216. package/dist/modules/dock/routing/continuity.d.ts.map +1 -0
  217. package/dist/modules/dock/routing/guards.d.ts +21 -0
  218. package/dist/modules/dock/routing/guards.d.ts.map +1 -0
  219. package/dist/modules/dock/routing/navigation.d.ts +37 -0
  220. package/dist/modules/dock/routing/navigation.d.ts.map +1 -0
  221. package/dist/modules/dock/routing/transactions.d.ts +21 -0
  222. package/dist/modules/dock/routing/transactions.d.ts.map +1 -0
  223. package/dist/modules/dock/runtime/commands.d.ts +18 -0
  224. package/dist/modules/dock/runtime/commands.d.ts.map +1 -0
  225. package/dist/modules/dock/runtime/display.d.ts +36 -0
  226. package/dist/modules/dock/runtime/display.d.ts.map +1 -0
  227. package/dist/modules/dock/runtime/dock.d.ts +123 -0
  228. package/dist/modules/dock/runtime/dock.d.ts.map +1 -0
  229. package/dist/modules/dock/state.d.ts +22 -0
  230. package/dist/modules/dock/state.d.ts.map +1 -0
  231. package/dist/modules/dock/status/events.d.ts +37 -0
  232. package/dist/modules/dock/status/events.d.ts.map +1 -0
  233. package/dist/modules/dock/status/hooks.d.ts +6 -0
  234. package/dist/modules/dock/status/hooks.d.ts.map +1 -0
  235. package/dist/modules/dock/status/model.d.ts +65 -0
  236. package/dist/modules/dock/status/model.d.ts.map +1 -0
  237. package/dist/modules/dock/surface/context.d.ts +43 -0
  238. package/dist/modules/dock/surface/context.d.ts.map +1 -0
  239. package/dist/modules/dock/surface/definition.d.ts +38 -0
  240. package/dist/modules/dock/surface/definition.d.ts.map +1 -0
  241. package/dist/modules/dock/surface/hooks.d.ts +123 -0
  242. package/dist/modules/dock/surface/hooks.d.ts.map +1 -0
  243. package/dist/modules/dock/surface/machine.d.ts +75 -0
  244. package/dist/modules/dock/surface/machine.d.ts.map +1 -0
  245. package/dist/modules/dock/surface/stack.d.ts +38 -0
  246. package/dist/modules/dock/surface/stack.d.ts.map +1 -0
  247. package/dist/modules/dock/surface/view-model.d.ts +3 -0
  248. package/dist/modules/dock/surface/view-model.d.ts.map +1 -0
  249. package/dist/modules/dock/types.d.ts +1158 -0
  250. package/dist/modules/dock/types.d.ts.map +1 -0
  251. package/dist/modules/dock/utils.d.ts +93 -0
  252. package/dist/modules/dock/utils.d.ts.map +1 -0
  253. package/dist/modules/index.d.ts +12 -0
  254. package/dist/modules/index.d.ts.map +1 -0
  255. package/dist/modules/index.js +18020 -0
  256. package/dist/modules/index.js.map +1 -0
  257. package/dist/modules/loading/constants.d.ts +5 -0
  258. package/dist/modules/loading/constants.d.ts.map +1 -0
  259. package/dist/modules/loading/context.d.ts +13 -0
  260. package/dist/modules/loading/context.d.ts.map +1 -0
  261. package/dist/modules/loading/hooks.d.ts +6 -0
  262. package/dist/modules/loading/hooks.d.ts.map +1 -0
  263. package/dist/modules/loading/index.d.ts +7 -0
  264. package/dist/modules/loading/index.d.ts.map +1 -0
  265. package/dist/modules/loading/index.js +1256 -0
  266. package/dist/modules/loading/index.js.map +1 -0
  267. package/dist/modules/loading/module.d.ts +14 -0
  268. package/dist/modules/loading/module.d.ts.map +1 -0
  269. package/dist/modules/loading/overlay.d.ts +2 -0
  270. package/dist/modules/loading/overlay.d.ts.map +1 -0
  271. package/dist/modules/loading/types.d.ts +47 -0
  272. package/dist/modules/loading/types.d.ts.map +1 -0
  273. package/dist/modules/loading/utils.d.ts +4 -0
  274. package/dist/modules/loading/utils.d.ts.map +1 -0
  275. package/dist/modules/media/constants.d.ts +7 -0
  276. package/dist/modules/media/constants.d.ts.map +1 -0
  277. package/dist/modules/media/context.d.ts +6 -0
  278. package/dist/modules/media/context.d.ts.map +1 -0
  279. package/dist/modules/media/hooks.d.ts +3 -0
  280. package/dist/modules/media/hooks.d.ts.map +1 -0
  281. package/dist/modules/media/index.d.ts +8 -0
  282. package/dist/modules/media/index.d.ts.map +1 -0
  283. package/dist/modules/media/index.js +728 -0
  284. package/dist/modules/media/index.js.map +1 -0
  285. package/dist/modules/media/module.d.ts +11 -0
  286. package/dist/modules/media/module.d.ts.map +1 -0
  287. package/dist/modules/media/overlay.d.ts +9 -0
  288. package/dist/modules/media/overlay.d.ts.map +1 -0
  289. package/dist/modules/media/types.d.ts +77 -0
  290. package/dist/modules/media/types.d.ts.map +1 -0
  291. package/dist/modules/media/utils.d.ts +17 -0
  292. package/dist/modules/media/utils.d.ts.map +1 -0
  293. package/dist/modules/modal/constants.d.ts +20 -0
  294. package/dist/modules/modal/constants.d.ts.map +1 -0
  295. package/dist/modules/modal/context.d.ts +20 -0
  296. package/dist/modules/modal/context.d.ts.map +1 -0
  297. package/dist/modules/modal/hooks.d.ts +41 -0
  298. package/dist/modules/modal/hooks.d.ts.map +1 -0
  299. package/dist/modules/modal/index.d.ts +7 -0
  300. package/dist/modules/modal/index.d.ts.map +1 -0
  301. package/dist/modules/modal/index.js +2672 -0
  302. package/dist/modules/modal/index.js.map +1 -0
  303. package/dist/modules/modal/module.d.ts +12 -0
  304. package/dist/modules/modal/module.d.ts.map +1 -0
  305. package/dist/modules/modal/motion.d.ts +16 -0
  306. package/dist/modules/modal/motion.d.ts.map +1 -0
  307. package/dist/modules/modal/overlay.d.ts +4 -0
  308. package/dist/modules/modal/overlay.d.ts.map +1 -0
  309. package/dist/modules/modal/state.d.ts +4 -0
  310. package/dist/modules/modal/state.d.ts.map +1 -0
  311. package/dist/modules/modal/types.d.ts +109 -0
  312. package/dist/modules/modal/types.d.ts.map +1 -0
  313. package/dist/modules/modal/utils.d.ts +31 -0
  314. package/dist/modules/modal/utils.d.ts.map +1 -0
  315. package/dist/modules/notification/constants.d.ts +9 -0
  316. package/dist/modules/notification/constants.d.ts.map +1 -0
  317. package/dist/modules/notification/context.d.ts +7 -0
  318. package/dist/modules/notification/context.d.ts.map +1 -0
  319. package/dist/modules/notification/hooks.d.ts +10 -0
  320. package/dist/modules/notification/hooks.d.ts.map +1 -0
  321. package/dist/modules/notification/index.d.ts +7 -0
  322. package/dist/modules/notification/index.d.ts.map +1 -0
  323. package/dist/modules/notification/index.js +905 -0
  324. package/dist/modules/notification/index.js.map +1 -0
  325. package/dist/modules/notification/module.d.ts +11 -0
  326. package/dist/modules/notification/module.d.ts.map +1 -0
  327. package/dist/modules/notification/motion.d.ts +15 -0
  328. package/dist/modules/notification/motion.d.ts.map +1 -0
  329. package/dist/modules/notification/overlay.d.ts +3 -0
  330. package/dist/modules/notification/overlay.d.ts.map +1 -0
  331. package/dist/modules/notification/types.d.ts +57 -0
  332. package/dist/modules/notification/types.d.ts.map +1 -0
  333. package/dist/modules/notification/utils.d.ts +9 -0
  334. package/dist/modules/notification/utils.d.ts.map +1 -0
  335. package/dist/modules/theme.d.ts +3 -0
  336. package/dist/modules/theme.d.ts.map +1 -0
  337. package/dist/provider.d.ts +23 -0
  338. package/dist/provider.d.ts.map +1 -0
  339. package/dist/provider.js +1973 -0
  340. package/dist/provider.js.map +1 -0
  341. package/dist/result.d.ts +50 -0
  342. package/dist/result.d.ts.map +1 -0
  343. package/dist/result.js +163 -0
  344. package/dist/result.js.map +1 -0
  345. package/dist/theme.d.ts +25 -0
  346. package/dist/theme.d.ts.map +1 -0
  347. package/dist/theme.js +44 -0
  348. package/dist/theme.js.map +1 -0
  349. package/dist/tokens/index.d.ts +3 -0
  350. package/dist/tokens/index.d.ts.map +1 -0
  351. package/dist/tokens/index.js +325 -0
  352. package/dist/tokens/index.js.map +1 -0
  353. package/dist/tokens/motion.d.ts +315 -0
  354. package/dist/tokens/motion.d.ts.map +1 -0
  355. package/dist/tokens/tokens.d.ts +34 -0
  356. package/dist/tokens/tokens.d.ts.map +1 -0
  357. package/dist/utils/cn.d.ts +3 -0
  358. package/dist/utils/cn.d.ts.map +1 -0
  359. package/dist/utils/dom.d.ts +5 -0
  360. package/dist/utils/dom.d.ts.map +1 -0
  361. package/dist/utils/index.d.ts +16 -0
  362. package/dist/utils/index.d.ts.map +1 -0
  363. package/dist/utils/index.js +485 -0
  364. package/dist/utils/index.js.map +1 -0
  365. package/dist/utils/json.d.ts +3 -0
  366. package/dist/utils/json.d.ts.map +1 -0
  367. package/dist/utils/number.d.ts +4 -0
  368. package/dist/utils/number.d.ts.map +1 -0
  369. package/dist/utils/object.d.ts +7 -0
  370. package/dist/utils/object.d.ts.map +1 -0
  371. package/dist/utils/report.d.ts +5 -0
  372. package/dist/utils/report.d.ts.map +1 -0
  373. package/dist/utils/scheduler.d.ts +34 -0
  374. package/dist/utils/scheduler.d.ts.map +1 -0
  375. package/dist/utils/store.d.ts +11 -0
  376. package/dist/utils/store.d.ts.map +1 -0
  377. package/dist/utils/string.d.ts +8 -0
  378. package/dist/utils/string.d.ts.map +1 -0
  379. package/dist/utils/timing.d.ts +8 -0
  380. package/dist/utils/timing.d.ts.map +1 -0
  381. package/dist/utils/user-message.d.ts +20 -0
  382. package/dist/utils/user-message.d.ts.map +1 -0
  383. package/package.json +113 -0
@@ -0,0 +1,2008 @@
1
+ "use client";
2
+ import { createContext, useState, useRef, useInsertionEffect, useMemo, useEffect, useCallback, useSyncExternalStore, use, useId, isValidElement, useLayoutEffect, cloneElement, Children, useContext } from 'react';
3
+ import { usePathname } from 'next/navigation';
4
+ import 'clsx';
5
+ import 'tailwind-merge';
6
+ import { jsx, jsxs } from 'react/jsx-runtime';
7
+ import { AnimatePresence, motion } from 'motion/react';
8
+ import { Icon as Icon$1 } from '@iconify-icon/react';
9
+ import '@radix-ui/react-tooltip';
10
+ import { createPortal } from 'react-dom';
11
+
12
+ function useRequiredContext(context, hookName, providerName) {
13
+ const value = use(context);
14
+ if (value === null) {
15
+ throw new Error(`${hookName} must be used within ${providerName}`);
16
+ }
17
+ return value;
18
+ }
19
+ function useStore(store, selector = (state) => state, isEqual = Object.is) {
20
+ const cacheRef = useRef({
21
+ isEqual: null,
22
+ selected: void 0,
23
+ selector: null,
24
+ snapshot: null
25
+ });
26
+ const getSelectedSnapshot = useCallback(() => {
27
+ const snapshot = store.getSnapshot();
28
+ const cache = cacheRef.current;
29
+ if (cache.snapshot === snapshot && cache.selector === selector && cache.isEqual === isEqual) {
30
+ return cache.selected;
31
+ }
32
+ const selected = selector(snapshot);
33
+ if (cache.snapshot !== null && cache.isEqual === isEqual && isEqual(cache.selected, selected)) {
34
+ cache.snapshot = snapshot;
35
+ cache.selector = selector;
36
+ return cache.selected;
37
+ }
38
+ cacheRef.current = {
39
+ isEqual,
40
+ selected,
41
+ selector,
42
+ snapshot
43
+ };
44
+ return selected;
45
+ }, [isEqual, selector, store]);
46
+ return useSyncExternalStore(
47
+ store.subscribe,
48
+ getSelectedSnapshot,
49
+ getSelectedSnapshot
50
+ );
51
+ }
52
+
53
+ // src/utils/string.ts
54
+ function trimToNull(value) {
55
+ if (value === null || value === void 0) return null;
56
+ const trimmed = String(value).trim();
57
+ return trimmed.length > 0 ? trimmed : null;
58
+ }
59
+ function isImageIconSource(icon) {
60
+ return typeof icon === "string" && (icon.startsWith("http://") || icon.startsWith("https://") || icon.startsWith("/") || icon.startsWith("data:image/"));
61
+ }
62
+
63
+ // src/utils/dom.ts
64
+ var isBrowser = typeof window !== "undefined";
65
+
66
+ // src/utils/number.ts
67
+ function toFiniteNumber(value, fallback = 0) {
68
+ const parsed = Number(value);
69
+ return Number.isFinite(parsed) ? parsed : fallback;
70
+ }
71
+
72
+ // src/utils/object.ts
73
+ function isObject(value) {
74
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
75
+ }
76
+ function toArray(value) {
77
+ if (value === null || value === void 0) return [];
78
+ return Array.isArray(value) ? value : [value];
79
+ }
80
+ function report(scope, error, level = "error") {
81
+ if (process.env.NODE_ENV === "production" && typeof window !== "undefined") {
82
+ return;
83
+ }
84
+ console[level](`[${scope}]`, error);
85
+ }
86
+
87
+ // src/utils/store.ts
88
+ function freezeStoreSnapshot(state) {
89
+ if (process.env.NODE_ENV === "production" || !state || typeof state !== "object") {
90
+ return state;
91
+ }
92
+ const seen = /* @__PURE__ */ new WeakSet();
93
+ const freeze = (value) => {
94
+ if (seen.has(value) || Object.isFrozen(value)) return;
95
+ seen.add(value);
96
+ const prototype = Object.getPrototypeOf(value);
97
+ if (Array.isArray(value) || prototype === Object.prototype || prototype === null) {
98
+ for (const key of Reflect.ownKeys(value)) {
99
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
100
+ if (descriptor && "value" in descriptor && descriptor.value !== null) {
101
+ if (typeof descriptor.value === "object") freeze(descriptor.value);
102
+ }
103
+ }
104
+ }
105
+ Object.freeze(value);
106
+ };
107
+ freeze(state);
108
+ return state;
109
+ }
110
+ function createStore(initialState, { freezeSnapshots = true } = {}) {
111
+ const listeners = /* @__PURE__ */ new Set();
112
+ const prepare = freezeSnapshots ? freezeStoreSnapshot : (state) => state;
113
+ let snapshot = prepare(initialState);
114
+ const publish = (nextStateOrUpdater) => {
115
+ const nextState = typeof nextStateOrUpdater === "function" ? nextStateOrUpdater(snapshot) : nextStateOrUpdater;
116
+ if (Object.is(snapshot, nextState)) return false;
117
+ snapshot = prepare(nextState);
118
+ for (const listener of listeners) {
119
+ try {
120
+ listener();
121
+ } catch (error) {
122
+ report("CoreStore subscriber", error, "warn");
123
+ }
124
+ }
125
+ return true;
126
+ };
127
+ const setState = (updater) => {
128
+ if (typeof updater === "function") {
129
+ return publish(updater);
130
+ }
131
+ if (snapshot && typeof snapshot === "object" && updater && typeof updater === "object") {
132
+ return publish({ ...snapshot, ...updater });
133
+ }
134
+ return publish(updater);
135
+ };
136
+ return Object.freeze({
137
+ getSnapshot() {
138
+ return snapshot;
139
+ },
140
+ publish,
141
+ setState,
142
+ subscribe(listener) {
143
+ if (typeof listener !== "function") return () => {
144
+ };
145
+ listeners.add(listener);
146
+ return () => listeners.delete(listener);
147
+ }
148
+ });
149
+ }
150
+
151
+ // src/hooks/use-isomorphic-layout-effect.ts
152
+ var useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect;
153
+ var EventEmitter = class {
154
+ events = /* @__PURE__ */ new Map();
155
+ debounceTimers = /* @__PURE__ */ new Map();
156
+ subscribe(event, callback) {
157
+ if (typeof event !== "string" || !event || typeof callback !== "function") {
158
+ return () => {
159
+ };
160
+ }
161
+ const listeners = this.events.get(event) || /* @__PURE__ */ new Set();
162
+ listeners.add(callback);
163
+ this.events.set(event, listeners);
164
+ return () => {
165
+ listeners.delete(callback);
166
+ if (listeners.size === 0) this.events.delete(event);
167
+ };
168
+ }
169
+ emit(event, payload) {
170
+ const listeners = this.events.get(event);
171
+ if (!listeners || listeners.size === 0) return;
172
+ const snapshot = Array.from(listeners);
173
+ for (const callback of snapshot) {
174
+ try {
175
+ callback(payload);
176
+ } catch (error) {
177
+ report(`Event listener (${String(event)})`, error);
178
+ }
179
+ }
180
+ }
181
+ emitDebounced(event, payload, waitMs = 100) {
182
+ const existing = this.debounceTimers.get(event);
183
+ if (existing) clearTimeout(existing);
184
+ const timer = setTimeout(() => {
185
+ this.debounceTimers.delete(event);
186
+ this.emit(event, payload);
187
+ }, waitMs);
188
+ this.debounceTimers.set(event, timer);
189
+ }
190
+ cancelDebounced(event) {
191
+ if (event) {
192
+ const timer = this.debounceTimers.get(event);
193
+ if (timer) {
194
+ clearTimeout(timer);
195
+ this.debounceTimers.delete(event);
196
+ }
197
+ } else {
198
+ for (const timer of this.debounceTimers.values()) {
199
+ clearTimeout(timer);
200
+ }
201
+ this.debounceTimers.clear();
202
+ }
203
+ }
204
+ unsubscribeAll(event) {
205
+ this.cancelDebounced(event);
206
+ if (event) this.events.delete(event);
207
+ else this.events.clear();
208
+ }
209
+ hasListeners(event) {
210
+ return Boolean(this.events.get(event)?.size);
211
+ }
212
+ getListenerCount(event) {
213
+ return this.events.get(event)?.size || 0;
214
+ }
215
+ getAllEvents() {
216
+ return [...this.events.keys()];
217
+ }
218
+ };
219
+ var GLOBAL_EVENTS_KEY = /* @__PURE__ */ Symbol.for("__base_framework_global_events__");
220
+ var _global = globalThis;
221
+ _global[GLOBAL_EVENTS_KEY] ?? (_global[GLOBAL_EVENTS_KEY] = new EventEmitter());
222
+
223
+ // src/kernel/constants.ts
224
+ var DEFAULT_SOURCE = "dynamic";
225
+ var REGISTRY_SOURCES = Object.freeze({
226
+ STATIC: "static",
227
+ DYNAMIC: "dynamic",
228
+ USER: "user"
229
+ });
230
+ var REGISTRY_LIFECYCLES = Object.freeze({
231
+ IMMEDIATE: "immediate",
232
+ GRACEFUL: "graceful",
233
+ PERSISTENT: "persistent",
234
+ ROUTE: "route"
235
+ });
236
+ var REGISTRY_VALIDATION_MODES = Object.freeze({
237
+ WARN: "warn",
238
+ STRICT: "strict"
239
+ });
240
+ var REGISTRY_METADATA_KEYS = Object.freeze([
241
+ "cleanup",
242
+ "cleanupDelayMs",
243
+ "instanceId",
244
+ "lifecycle",
245
+ "priority",
246
+ "source",
247
+ "scope",
248
+ "validation"
249
+ ]);
250
+ Object.freeze({
251
+ [REGISTRY_SOURCES.STATIC]: 100,
252
+ [REGISTRY_SOURCES.DYNAMIC]: 200,
253
+ [REGISTRY_SOURCES.USER]: 300
254
+ });
255
+ Object.freeze({
256
+ [REGISTRY_SOURCES.STATIC]: 10,
257
+ [REGISTRY_SOURCES.DYNAMIC]: 20,
258
+ [REGISTRY_SOURCES.USER]: 30
259
+ });
260
+ var REGISTRY_LIFECYCLE_VALUES = new Set(
261
+ Object.values(REGISTRY_LIFECYCLES)
262
+ );
263
+ var REGISTRY_METADATA_KEY_SET = new Set(
264
+ REGISTRY_METADATA_KEYS
265
+ );
266
+ var REGISTRY_SCOPE_KINDS = Object.freeze({
267
+ APP: "app",
268
+ SESSION: "session",
269
+ ROUTE: "route",
270
+ INSTANCE: "instance",
271
+ WORKSPACE: "workspace"
272
+ });
273
+ REGISTRY_SCOPE_KINDS.APP;
274
+
275
+ // src/kernel/utils.ts
276
+ function parseFiniteNumber(value) {
277
+ const parsed = Number(value);
278
+ return Number.isFinite(parsed) ? parsed : null;
279
+ }
280
+ function getValidString(value, fallback = null) {
281
+ return trimToNull(value) ?? fallback;
282
+ }
283
+
284
+ // src/kernel/schema.ts
285
+ function resolveLifecycle(metadata, fallback) {
286
+ const lifecycle = metadata?.lifecycle ?? metadata?.cleanup;
287
+ return lifecycle && REGISTRY_LIFECYCLE_VALUES.has(lifecycle) ? lifecycle : fallback;
288
+ }
289
+ function validateRegistryMetadata(metadata) {
290
+ if (metadata === void 0 || metadata === null)
291
+ return { issues: [], valid: true };
292
+ if (!isObject(metadata))
293
+ return { issues: ["registry metadata must be an object"], valid: false };
294
+ const issues = [];
295
+ Object.keys(metadata).forEach((key) => {
296
+ if (!REGISTRY_METADATA_KEY_SET.has(key))
297
+ issues.push(`unknown registry metadata field: ${key}`);
298
+ });
299
+ if (metadata.source !== void 0 && !getValidString(metadata.source))
300
+ issues.push("source must be a non-empty string");
301
+ if (metadata.instanceId !== void 0 && !getValidString(metadata.instanceId))
302
+ issues.push("instanceId must be a non-empty string");
303
+ if (metadata.scope !== void 0 && !getValidString(metadata.scope))
304
+ issues.push("scope must be a non-empty string");
305
+ if (metadata.priority !== void 0 && parseFiniteNumber(metadata.priority) === null)
306
+ issues.push("priority must be a finite number");
307
+ if (metadata.cleanupDelayMs !== void 0) {
308
+ const delay = parseFiniteNumber(metadata.cleanupDelayMs);
309
+ if (delay === null || delay < 0)
310
+ issues.push("cleanupDelayMs must be a non-negative finite number");
311
+ }
312
+ const lifecycle = metadata.lifecycle ?? metadata.cleanup;
313
+ if (lifecycle !== void 0 && !REGISTRY_LIFECYCLE_VALUES.has(String(lifecycle))) {
314
+ issues.push(
315
+ `lifecycle must be one of: ${[...REGISTRY_LIFECYCLE_VALUES].join(", ")}`
316
+ );
317
+ }
318
+ if (metadata.validation !== void 0 && !Object.values(REGISTRY_VALIDATION_MODES).includes(
319
+ metadata.validation
320
+ )) {
321
+ issues.push(
322
+ `validation must be one of: ${Object.values(REGISTRY_VALIDATION_MODES).join(", ")}`
323
+ );
324
+ }
325
+ return { issues, valid: issues.length === 0 };
326
+ }
327
+ function normalizeRegistryMetadata(metadata, {
328
+ defaultCleanupDelayMs = null,
329
+ defaultLifecycle = null,
330
+ defaultSource = DEFAULT_SOURCE
331
+ } = {}) {
332
+ const registryMeta = isObject(metadata) ? metadata : {};
333
+ const normalizedDefaultDelay = parseFiniteNumber(defaultCleanupDelayMs);
334
+ const fallbackCleanupDelayMs = normalizedDefaultDelay !== null && normalizedDefaultDelay >= 0 ? normalizedDefaultDelay : null;
335
+ const fallbackLifecycle = defaultLifecycle && REGISTRY_LIFECYCLE_VALUES.has(defaultLifecycle) ? defaultLifecycle : null;
336
+ const source = getValidString(registryMeta.source) || getValidString(defaultSource, DEFAULT_SOURCE) || DEFAULT_SOURCE;
337
+ const scope = getValidString(registryMeta.scope);
338
+ const priority = parseFiniteNumber(registryMeta.priority);
339
+ const lifecycle = resolveLifecycle(registryMeta, fallbackLifecycle);
340
+ const validation = isValidationMode(registryMeta.validation) ? registryMeta.validation : null;
341
+ const cleanupDelayCandidate = parseFiniteNumber(registryMeta.cleanupDelayMs);
342
+ let cleanupDelayMs = cleanupDelayCandidate !== null && cleanupDelayCandidate >= 0 ? cleanupDelayCandidate : fallbackCleanupDelayMs;
343
+ if (lifecycle === REGISTRY_LIFECYCLES.IMMEDIATE) {
344
+ cleanupDelayMs = 0;
345
+ } else if ((lifecycle === REGISTRY_LIFECYCLES.GRACEFUL || lifecycle === REGISTRY_LIFECYCLES.ROUTE) && cleanupDelayMs === null) {
346
+ cleanupDelayMs = fallbackCleanupDelayMs;
347
+ }
348
+ return {
349
+ cleanupDelayMs,
350
+ lifecycle,
351
+ priority,
352
+ registerOptions: {
353
+ ...priority !== null && { priority },
354
+ ...validation === REGISTRY_VALIDATION_MODES.STRICT && { validation },
355
+ ...scope && { scope }
356
+ },
357
+ source,
358
+ ...scope && { scope },
359
+ ...validation && { validation }
360
+ };
361
+ }
362
+ function isValidationMode(value) {
363
+ return Object.values(REGISTRY_VALIDATION_MODES).includes(value);
364
+ }
365
+ function pickRegistryMetadata(options) {
366
+ if (!isObject(options)) return {};
367
+ return Object.fromEntries(
368
+ REGISTRY_METADATA_KEYS.filter((key) => options[key] !== void 0).map(
369
+ (key) => [key, options[key]]
370
+ )
371
+ );
372
+ }
373
+ function createNoopHandle(status = "rejected", reason = "unknown") {
374
+ const handle = Object.assign(() => false, {
375
+ active: false,
376
+ dispose: () => false,
377
+ instanceId: null,
378
+ key: "",
379
+ priority: 0,
380
+ reason,
381
+ source: "",
382
+ status,
383
+ type: "",
384
+ update: () => handle,
385
+ updatedAt: 0,
386
+ validation: "warn"
387
+ });
388
+ return handle;
389
+ }
390
+ createNoopHandle();
391
+ function getOrCreateGlobalContext(name, defaultValue) {
392
+ const sym = /* @__PURE__ */ Symbol.for(`@omerdlw/base-framework/context/${name}`);
393
+ const store = globalThis;
394
+ if (!store[sym]) {
395
+ store[sym] = createContext(defaultValue);
396
+ }
397
+ return store[sym];
398
+ }
399
+ var RegistryContext = getOrCreateGlobalContext(
400
+ "RegistryContext",
401
+ null
402
+ );
403
+ function useRegistryActions() {
404
+ return useRequiredContext(
405
+ RegistryContext,
406
+ "useRegistryActions",
407
+ "RegistryProvider"
408
+ ).actions;
409
+ }
410
+ function useRegistrySubscription() {
411
+ return useRequiredContext(
412
+ RegistryContext,
413
+ "useRegistrySubscription",
414
+ "RegistryProvider"
415
+ ).subscription;
416
+ }
417
+ function useRegistryEntries(type) {
418
+ const { getEntriesSnapshot, subscribe } = useRegistrySubscription();
419
+ const subscribeToType = useCallback(
420
+ (listener) => subscribe(type, null, listener),
421
+ [subscribe, type]
422
+ );
423
+ const getEntries = useCallback(
424
+ () => getEntriesSnapshot(type),
425
+ [getEntriesSnapshot, type]
426
+ );
427
+ return useSyncExternalStore(subscribeToType, getEntries, getEntries);
428
+ }
429
+ var EMPTY_MODULES = Object.freeze([]);
430
+ var ModuleHostContext = getOrCreateGlobalContext("ModuleHostContext", null);
431
+ function selectModuleSlice(coreModule, config) {
432
+ const slice = coreModule.page?.select ? coreModule.page.select(config) : config[coreModule.id];
433
+ return slice ?? null;
434
+ }
435
+ function createModulePayload(modules, config, metadata = {}) {
436
+ const payload = {};
437
+ let hasSlices = false;
438
+ for (const coreModule of modules) {
439
+ if (!coreModule.page?.entries) continue;
440
+ const slice = selectModuleSlice(coreModule, config);
441
+ if (slice === null) continue;
442
+ payload[coreModule.id] = slice;
443
+ hasSlices = true;
444
+ }
445
+ if (!hasSlices) return null;
446
+ return {
447
+ ...payload,
448
+ registry: {
449
+ ...metadata,
450
+ ...isObject(config.registry) ? config.registry : {}
451
+ }
452
+ };
453
+ }
454
+ function useInstalledModules() {
455
+ return use(ModuleHostContext)?.modules ?? EMPTY_MODULES;
456
+ }
457
+
458
+ // src/kernel/handlers.ts
459
+ function isPersistentLifecycle(lifecycle) {
460
+ return lifecycle === REGISTRY_LIFECYCLES.PERSISTENT;
461
+ }
462
+ function runRegistrationBatch(context, executor) {
463
+ return typeof context.batch === "function" ? context.batch(executor) : executor(context);
464
+ }
465
+ function createEntryCleanupKey(type, key, source, instanceId, scope) {
466
+ return JSON.stringify([
467
+ "entry",
468
+ type,
469
+ key,
470
+ scope ?? null,
471
+ source,
472
+ instanceId
473
+ ]);
474
+ }
475
+ function getCleanupScope(context) {
476
+ return context?.cleanupScope || /* @__PURE__ */ new Map();
477
+ }
478
+ function clearCleanupTimer(scope, cleanupKey) {
479
+ const lifecycle = scope.get(cleanupKey);
480
+ if (!lifecycle) return;
481
+ lifecycle.cancelled = true;
482
+ if (lifecycle.timerId !== null) clearTimeout(lifecycle.timerId);
483
+ scope.delete(cleanupKey);
484
+ }
485
+ function scheduleCleanup(scope, cleanupKey, callback, delayMs) {
486
+ clearCleanupTimer(scope, cleanupKey);
487
+ const lifecycle = {
488
+ cancelled: false,
489
+ timerId: null
490
+ };
491
+ lifecycle.timerId = setTimeout(() => {
492
+ if (lifecycle.cancelled || scope.get(cleanupKey) !== lifecycle) return;
493
+ scope.delete(cleanupKey);
494
+ callback();
495
+ }, delayMs);
496
+ scope.set(cleanupKey, lifecycle);
497
+ }
498
+ function collectModuleRegistrations(coreModule, slice, pageMetadata, context) {
499
+ const definition = coreModule.registry;
500
+ const toEntries = coreModule.page?.entries;
501
+ if (!definition || !toEntries || slice == null || slice === false) return [];
502
+ const type = coreModule.id;
503
+ const items = Array.isArray(slice) ? slice : [slice];
504
+ const registrations = [];
505
+ for (const item of items) {
506
+ if (item == null || item === false) continue;
507
+ const itemMetadata = isObject(item) && isObject(item.registry) ? item.registry : {};
508
+ const metadata = { ...pageMetadata, ...itemMetadata };
509
+ if (metadata.validation === "strict" && !validateRegistryMetadata(metadata).valid) {
510
+ continue;
511
+ }
512
+ const payload = isObject(item) ? Object.fromEntries(
513
+ Object.entries(item).filter(([key]) => key !== "registry")
514
+ ) : item;
515
+ const { cleanupDelayMs, lifecycle, registerOptions, scope, source } = normalizeRegistryMetadata(metadata, {
516
+ defaultCleanupDelayMs: definition.cleanupDelayMs ?? null,
517
+ defaultLifecycle: definition.lifecycle,
518
+ defaultSource: DEFAULT_SOURCE
519
+ });
520
+ for (const { key, value } of toEntries(payload, context) ?? []) {
521
+ const validation = definition.validate?.(value);
522
+ if (validation && !validation.valid) {
523
+ report(`Registry ${type} config is invalid`, validation.issues, "warn");
524
+ continue;
525
+ }
526
+ registrations.push({
527
+ cleanupDelayMs,
528
+ cleanupKey: createEntryCleanupKey(
529
+ type,
530
+ key,
531
+ source,
532
+ context.instanceId,
533
+ scope
534
+ ),
535
+ key,
536
+ lifecycle,
537
+ registerOptions,
538
+ scope,
539
+ source,
540
+ type,
541
+ value
542
+ });
543
+ }
544
+ }
545
+ return registrations;
546
+ }
547
+ var NO_CLEANUP = () => {
548
+ };
549
+ function applyRegistryConfig(config, context) {
550
+ const modules = context.modules ?? [];
551
+ if (!config || modules.length === 0) return NO_CLEANUP;
552
+ const pageMetadata = isObject(config.registry) ? config.registry : {};
553
+ const slices = config;
554
+ const registrations = modules.flatMap((coreModule) => {
555
+ try {
556
+ return collectModuleRegistrations(
557
+ coreModule,
558
+ slices[coreModule.id],
559
+ pageMetadata,
560
+ context
561
+ );
562
+ } catch (error) {
563
+ report(`Registry apply (${coreModule.id})`, error);
564
+ return [];
565
+ }
566
+ });
567
+ if (registrations.length === 0) return NO_CLEANUP;
568
+ const cleanupScope = getCleanupScope(context);
569
+ const owner = (registration) => ({
570
+ instanceId: context.instanceId,
571
+ scope: registration.scope,
572
+ source: registration.source
573
+ });
574
+ runRegistrationBatch(context, (queue) => {
575
+ registrations.forEach(
576
+ ({ cleanupKey, key, registerOptions, source, type, value }) => {
577
+ clearCleanupTimer(cleanupScope, cleanupKey);
578
+ queue.register(type, key, value, source, registerOptions);
579
+ }
580
+ );
581
+ });
582
+ return () => {
583
+ const immediate = [];
584
+ registrations.forEach((registration) => {
585
+ if (isPersistentLifecycle(registration.lifecycle)) return;
586
+ const { cleanupDelayMs, cleanupKey, key, type } = registration;
587
+ if (typeof cleanupDelayMs === "number" && cleanupDelayMs > 0) {
588
+ scheduleCleanup(
589
+ cleanupScope,
590
+ cleanupKey,
591
+ () => context.unregister(type, key, owner(registration)),
592
+ cleanupDelayMs
593
+ );
594
+ } else {
595
+ immediate.push(registration);
596
+ }
597
+ });
598
+ if (immediate.length === 0) return;
599
+ runRegistrationBatch(context, (queue) => {
600
+ immediate.forEach(
601
+ (registration) => queue.unregister(
602
+ registration.type,
603
+ registration.key,
604
+ owner(registration)
605
+ )
606
+ );
607
+ });
608
+ };
609
+ }
610
+
611
+ // src/kernel/hooks.ts
612
+ function withInstanceId(instanceId, sourceOrOptions, optionsArg) {
613
+ if (typeof sourceOrOptions === "string") {
614
+ return {
615
+ optionsArg: { ...isObject(optionsArg) ? optionsArg : {}, instanceId },
616
+ sourceOrOptions
617
+ };
618
+ }
619
+ if (isObject(sourceOrOptions)) {
620
+ return {
621
+ optionsArg,
622
+ sourceOrOptions: { ...sourceOrOptions, instanceId }
623
+ };
624
+ }
625
+ return {
626
+ optionsArg: void 0,
627
+ sourceOrOptions: {
628
+ ...isObject(optionsArg) ? optionsArg : {},
629
+ instanceId
630
+ }
631
+ };
632
+ }
633
+ function withInstanceIdForUnregister(instanceId, sourceOrOptions) {
634
+ if (typeof sourceOrOptions === "string") {
635
+ return { instanceId, source: sourceOrOptions };
636
+ }
637
+ if (isObject(sourceOrOptions)) {
638
+ return { ...sourceOrOptions, instanceId };
639
+ }
640
+ return { instanceId };
641
+ }
642
+ function resolveRegisterArgsWithInstance(instanceId, sourceOrOptions, optionsArg) {
643
+ const input = withInstanceId(instanceId, sourceOrOptions, optionsArg);
644
+ return [input.sourceOrOptions, input.optionsArg];
645
+ }
646
+ var MAX_STABILIZATION_DEPTH = 64;
647
+ function createStableFunctionEntry(fn) {
648
+ const entry = {
649
+ current: fn,
650
+ stable(...args) {
651
+ return entry.current?.apply(this, args);
652
+ }
653
+ };
654
+ return entry;
655
+ }
656
+ function isDirectRegistryComponentPath(path, componentSlices) {
657
+ const match = /^config\.([^.[]+)\.[^.[]+$/.exec(path);
658
+ return Boolean(match && componentSlices.has(match[1]));
659
+ }
660
+ function isReactNodeLike(value) {
661
+ return value === null || value === void 0 || typeof value === "boolean" || typeof value === "string" || typeof value === "number" || isValidElement(value);
662
+ }
663
+ function isStabilizableObject(value) {
664
+ return typeof value === "object" && value !== null && !Array.isArray(value) && !isValidElement(value);
665
+ }
666
+ function hasSameObjectKeys(previousValue, nextValue) {
667
+ if (!isStabilizableObject(previousValue) || !isStabilizableObject(nextValue)) {
668
+ return false;
669
+ }
670
+ const previousKeys = Object.keys(previousValue);
671
+ const nextKeys = Object.keys(nextValue);
672
+ if (previousKeys.length !== nextKeys.length) return false;
673
+ return nextKeys.every(
674
+ (key) => Object.prototype.hasOwnProperty.call(previousValue, key)
675
+ );
676
+ }
677
+ function stabilizeRegistryValue(value, path, scope, previousValue, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
678
+ if (depth > MAX_STABILIZATION_DEPTH) return value;
679
+ if (typeof value === "function") {
680
+ const isComponent = value.name && /^[A-Z]/.test(value.name);
681
+ if (isComponent || isDirectRegistryComponentPath(path, scope.componentSlices)) {
682
+ return value;
683
+ }
684
+ scope.usedPaths.add(path);
685
+ let entry = scope.functionEntries.get(path);
686
+ if (!entry) {
687
+ entry = createStableFunctionEntry(value);
688
+ scope.functionEntries.set(path, entry);
689
+ } else {
690
+ entry.current = value;
691
+ }
692
+ return entry.stable;
693
+ }
694
+ if (value && typeof value === "object") {
695
+ if (seen.has(value)) return value;
696
+ seen.add(value);
697
+ }
698
+ if (isValidElement(value)) {
699
+ const nextProps = stabilizeRegistryValue(
700
+ value.props,
701
+ `${path}.props`,
702
+ scope,
703
+ isValidElement(previousValue) ? previousValue.props : void 0,
704
+ seen,
705
+ depth + 1
706
+ );
707
+ if (isValidElement(previousValue) && previousValue.type === value.type && previousValue.key === value.key && previousValue.props === nextProps) {
708
+ return previousValue;
709
+ }
710
+ return cloneElement(value, nextProps);
711
+ }
712
+ if (Array.isArray(value)) {
713
+ const nextValue = value.every(isReactNodeLike) ? Children.toArray(value) : value;
714
+ const previousArray = Array.isArray(previousValue) ? previousValue : null;
715
+ let hasChanged2 = !previousArray || previousArray.length !== nextValue.length;
716
+ const stabilizedValue2 = nextValue.map((item, index) => {
717
+ const nextItem = stabilizeRegistryValue(
718
+ item,
719
+ `${path}[${index}]`,
720
+ scope,
721
+ previousArray?.[index],
722
+ seen,
723
+ depth + 1
724
+ );
725
+ if (!previousArray || nextItem !== previousArray[index]) {
726
+ hasChanged2 = true;
727
+ }
728
+ return nextItem;
729
+ });
730
+ return !hasChanged2 ? previousArray : stabilizedValue2;
731
+ }
732
+ if (typeof value !== "object" || value === null) {
733
+ return value;
734
+ }
735
+ const source = value;
736
+ const previousRecord = previousValue;
737
+ const stabilizedValue = {};
738
+ const canReusePrevious = hasSameObjectKeys(previousValue, value);
739
+ let hasChanged = !canReusePrevious;
740
+ Object.keys(source).forEach((key) => {
741
+ const nextValue = stabilizeRegistryValue(
742
+ source[key],
743
+ `${path}.${key}`,
744
+ scope,
745
+ previousRecord?.[key],
746
+ seen,
747
+ depth + 1
748
+ );
749
+ stabilizedValue[key] = nextValue;
750
+ if (!canReusePrevious || nextValue !== previousRecord?.[key]) {
751
+ hasChanged = true;
752
+ }
753
+ });
754
+ return !hasChanged ? previousValue : stabilizedValue;
755
+ }
756
+ function useAppliedRegistryConfig(payload, context, componentSlices) {
757
+ const functionEntriesRef = useRef(/* @__PURE__ */ new Map());
758
+ const appliedRef = useRef(null);
759
+ useIsomorphicLayoutEffect(() => {
760
+ const previous = appliedRef.current;
761
+ if (previous && previous.payload === payload && previous.context === context) {
762
+ return;
763
+ }
764
+ const functionEntries = functionEntriesRef.current;
765
+ const usedPaths = /* @__PURE__ */ new Set();
766
+ const config = stabilizeRegistryValue(
767
+ payload,
768
+ "config",
769
+ { componentSlices, functionEntries, usedPaths },
770
+ previous?.config
771
+ );
772
+ functionEntries.forEach((_entry, path) => {
773
+ if (!usedPaths.has(path)) functionEntries.delete(path);
774
+ });
775
+ if (previous && previous.config === config && previous.context === context) {
776
+ previous.payload = payload;
777
+ return;
778
+ }
779
+ previous?.cleanup();
780
+ appliedRef.current = {
781
+ cleanup: applyRegistryConfig(config, context),
782
+ config,
783
+ context,
784
+ payload
785
+ };
786
+ });
787
+ useIsomorphicLayoutEffect(
788
+ () => () => {
789
+ appliedRef.current?.cleanup();
790
+ appliedRef.current = null;
791
+ },
792
+ []
793
+ );
794
+ }
795
+ function createRegistryApplyContext(actions, {
796
+ cleanupScope = /* @__PURE__ */ new Map(),
797
+ instanceId,
798
+ modules = [],
799
+ pathname
800
+ }) {
801
+ const stamp = (queue) => ({
802
+ register: (type, key, item, sourceOrOptions, optionsArg) => queue.register(
803
+ type,
804
+ key,
805
+ item,
806
+ ...resolveRegisterArgsWithInstance(
807
+ instanceId,
808
+ sourceOrOptions,
809
+ optionsArg
810
+ )
811
+ ),
812
+ unregister: (type, key, sourceOrOptions) => queue.unregister(
813
+ type,
814
+ key,
815
+ withInstanceIdForUnregister(instanceId, sourceOrOptions)
816
+ )
817
+ });
818
+ return {
819
+ ...stamp(actions),
820
+ batch: (executor) => typeof executor === "function" ? actions.batch((queue) => executor(stamp(queue))) : 0,
821
+ cleanupScope,
822
+ instanceId,
823
+ modules,
824
+ pathname
825
+ };
826
+ }
827
+ function useRegistry(config, metadata) {
828
+ const { batch, register, unregister } = useRegistryActions();
829
+ const pathname = usePathname();
830
+ const modules = useInstalledModules();
831
+ const instanceId = `registry-instance-${useId()}`;
832
+ const [cleanupScope] = useState(
833
+ () => /* @__PURE__ */ new Map()
834
+ );
835
+ const context = useMemo(
836
+ () => createRegistryApplyContext(
837
+ { batch, register, unregister },
838
+ {
839
+ cleanupScope,
840
+ instanceId,
841
+ modules,
842
+ pathname
843
+ }
844
+ ),
845
+ [batch, cleanupScope, instanceId, modules, pathname, register, unregister]
846
+ );
847
+ const payload = useMemo(
848
+ () => config ? createModulePayload(modules, config, metadata) : null,
849
+ [config, metadata, modules]
850
+ );
851
+ const componentSlices = useMemo(
852
+ () => new Set(
853
+ modules.filter(
854
+ (coreModule) => coreModule.registry?.valueKind === "component"
855
+ ).map((coreModule) => coreModule.id)
856
+ ),
857
+ [modules]
858
+ );
859
+ useAppliedRegistryConfig(payload, context, componentSlices);
860
+ }
861
+ function createPageControllerStore() {
862
+ const listeners = /* @__PURE__ */ new Set();
863
+ let stack = [];
864
+ const notify = () => {
865
+ listeners.forEach((listener) => {
866
+ try {
867
+ listener();
868
+ } catch (error) {
869
+ report("Page controller listener", error);
870
+ }
871
+ });
872
+ };
873
+ return {
874
+ getSnapshot() {
875
+ const top = stack[stack.length - 1];
876
+ return top?.controllerRef?.current || null;
877
+ },
878
+ notify,
879
+ register(id, controllerRef) {
880
+ stack = stack.filter((item) => item.id !== id);
881
+ stack.push({ controllerRef, id });
882
+ notify();
883
+ },
884
+ subscribe(listener) {
885
+ listeners.add(listener);
886
+ return () => {
887
+ listeners.delete(listener);
888
+ };
889
+ },
890
+ unregister(id) {
891
+ stack = stack.filter((item) => item.id !== id);
892
+ notify();
893
+ }
894
+ };
895
+ }
896
+ var fallbackStandaloneStore = createPageControllerStore();
897
+ getOrCreateGlobalContext(
898
+ "PageControllerContext",
899
+ null
900
+ );
901
+ getOrCreateGlobalContext(
902
+ "PageControllerStoreContext",
903
+ fallbackStandaloneStore
904
+ );
905
+ function defineModule(coreModule) {
906
+ return Object.freeze({ ...coreModule });
907
+ }
908
+ function useModule(id) {
909
+ const coreModule = use(ModuleHostContext)?.byId.get(id);
910
+ return coreModule?.context ? use(coreModule.context) ?? null : null;
911
+ }
912
+ var NO_MODULE_STORE = createStore(void 0);
913
+ function useModuleState(id, selector, fallback, isEqual = Object.is) {
914
+ const runtime = useModule(id);
915
+ return useStore(
916
+ runtime?.store ?? NO_MODULE_STORE,
917
+ (state) => runtime ? selector(state) : fallback,
918
+ isEqual
919
+ );
920
+ }
921
+
922
+ // src/kernel/adapters.tsx
923
+ function useModuleRegistration(id, value, options) {
924
+ const coreModule = useInstalledModules().find(
925
+ (candidate) => candidate.id === id
926
+ );
927
+ const config = coreModule && options?.enabled !== false && value != null ? { [id]: value } : null;
928
+ useRegistry(config, pickRegistryMetadata(options));
929
+ }
930
+ function defineThemeSpec(id) {
931
+ return Object.freeze({ id });
932
+ }
933
+ var EMPTY = /* @__PURE__ */ new Map();
934
+ var ThemeContext = getOrCreateGlobalContext("ThemeContext", EMPTY);
935
+ function useTheme(spec) {
936
+ const config = useContext(ThemeContext).get(spec.id);
937
+ if (!config) {
938
+ throw new Error(
939
+ `Theme "${spec.id}" is missing. Add its theme file to src/config/ and list it in src/config/index.ts.`
940
+ );
941
+ }
942
+ return {
943
+ slots: config.slots,
944
+ styles: config.styles ?? {}
945
+ };
946
+ }
947
+
948
+ // src/modules/context-menu/constants.ts
949
+ var contextMenuTheme = defineThemeSpec("context-menu");
950
+ var CURRENT_PAGE_KEY = "current-page";
951
+ var GLOBAL_MENU_KEY = "*";
952
+ var MENU_SCREEN_MARGIN = 10;
953
+ var CONTEXT_MENU_VISIBILITY_EVENT = "context-menu:visibility";
954
+ var INITIAL_POSITION = Object.freeze({
955
+ x: 0,
956
+ y: 0
957
+ });
958
+ function joinClassNames(...classes) {
959
+ return classes.filter(Boolean).join(" ");
960
+ }
961
+ var SCROLL_LOCK_KEYS = /* @__PURE__ */ new Set([
962
+ "ArrowDown",
963
+ "ArrowUp",
964
+ "End",
965
+ "Home",
966
+ "PageDown",
967
+ "PageUp",
968
+ " ",
969
+ "Spacebar"
970
+ ]);
971
+ function isScrollLockKey(event) {
972
+ return SCROLL_LOCK_KEYS.has(event.key);
973
+ }
974
+ function extractNodeText(value) {
975
+ if (typeof value === "string") return value;
976
+ if (typeof value === "number" || typeof value === "boolean") {
977
+ return String(value);
978
+ }
979
+ if (Array.isArray(value)) {
980
+ return value.map(extractNodeText).filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
981
+ }
982
+ if (isValidElement(value))
983
+ return extractNodeText(value.props?.children);
984
+ return "";
985
+ }
986
+ function resolveAsBoolean(value, context, defaultValue = true) {
987
+ if (typeof value === "function") {
988
+ try {
989
+ return Boolean(value(context));
990
+ } catch {
991
+ return false;
992
+ }
993
+ }
994
+ if (value === void 0) {
995
+ return defaultValue;
996
+ }
997
+ return Boolean(value);
998
+ }
999
+ function resolveAsValue(value, context, fallback) {
1000
+ if (typeof value === "function") {
1001
+ try {
1002
+ const resolved = value(context);
1003
+ return resolved === void 0 ? fallback : resolved;
1004
+ } catch {
1005
+ return fallback;
1006
+ }
1007
+ }
1008
+ return value === void 0 ? fallback : value;
1009
+ }
1010
+ function emitContextMenuVisibility(isOpen) {
1011
+ if (!isBrowser) return;
1012
+ window.dispatchEvent(
1013
+ new CustomEvent(CONTEXT_MENU_VISIBILITY_EVENT, {
1014
+ detail: { isOpen: Boolean(isOpen) }
1015
+ })
1016
+ );
1017
+ }
1018
+ function safeInvoke(handler, ...args) {
1019
+ if (typeof handler !== "function") return void 0;
1020
+ try {
1021
+ const result = handler(...args);
1022
+ if (result && typeof result.then === "function") {
1023
+ result.catch(
1024
+ (err2) => report("Context menu async callback", err2)
1025
+ );
1026
+ }
1027
+ return result;
1028
+ } catch (error) {
1029
+ report("Context menu callback", error);
1030
+ return void 0;
1031
+ }
1032
+ }
1033
+ function resolveContextMenuPageMeta(dockItem, pathname = "") {
1034
+ if (!isObject(dockItem)) return null;
1035
+ const title = dockItem.contextMenuTitle ?? dockItem.title ?? null;
1036
+ const description = dockItem.contextMenuDescription ?? dockItem.description ?? null;
1037
+ const eyebrow = dockItem.contextMenuEyebrow ?? dockItem.eyebrow ?? null;
1038
+ const icon = dockItem.contextMenuIcon ?? dockItem.icon ?? null;
1039
+ if (!title && !description && !icon && !eyebrow) return null;
1040
+ return {
1041
+ description,
1042
+ descriptionText: extractNodeText(description),
1043
+ eyebrow,
1044
+ icon,
1045
+ path: typeof dockItem.path === "string" && dockItem.path ? dockItem.path : pathname,
1046
+ title,
1047
+ titleText: extractNodeText(title) || (typeof dockItem.name === "string" ? dockItem.name : "") || ""
1048
+ };
1049
+ }
1050
+ function positionMenu(menuElement, position) {
1051
+ if (!menuElement) return;
1052
+ const { height, width } = menuElement.getBoundingClientRect();
1053
+ const maxX = window.innerWidth - width - MENU_SCREEN_MARGIN;
1054
+ const maxY = window.innerHeight - height - MENU_SCREEN_MARGIN;
1055
+ const x = Math.min(Number(position?.x) || 0, maxX);
1056
+ const y = Math.min(Number(position?.y) || 0, maxY);
1057
+ menuElement.style.left = `${Math.round(Math.max(MENU_SCREEN_MARGIN, x))}px`;
1058
+ menuElement.style.top = `${Math.round(Math.max(MENU_SCREEN_MARGIN, y))}px`;
1059
+ }
1060
+ function resolveItem(item, index, context) {
1061
+ if (!item) return null;
1062
+ if (item === "separator" || item.type === "separator") {
1063
+ return {
1064
+ key: item !== "separator" && item.key || `separator-${index}`,
1065
+ type: "separator"
1066
+ };
1067
+ }
1068
+ if (resolveAsBoolean(item.hidden, context, false) || !resolveAsBoolean(item.visible, context, true)) {
1069
+ return null;
1070
+ }
1071
+ const label = resolveAsValue(item.label, context, "");
1072
+ if (typeof label !== "string" && typeof label !== "number" || !String(label).trim()) {
1073
+ return null;
1074
+ }
1075
+ const handler = item.onSelect ?? item.onClick ?? null;
1076
+ const shortcut = resolveAsValue(item.shortcut, context, null);
1077
+ return {
1078
+ ...item,
1079
+ className: resolveAsValue(item.className, context, "") || "",
1080
+ closeOnSelect: item.closeOnSelect !== false,
1081
+ danger: resolveAsBoolean(item.danger, context, false),
1082
+ disabled: resolveAsBoolean(item.disabled, context, false),
1083
+ icon: resolveAsValue(item.icon, context, null) || null,
1084
+ itemIconClassName: resolveAsValue(item.itemIconClassName, context, "") || "",
1085
+ key: item.key || `item-${index}`,
1086
+ label: String(label),
1087
+ onClick: handler,
1088
+ onSelect: handler,
1089
+ shortcut: typeof shortcut === "string" ? shortcut : null,
1090
+ type: "action"
1091
+ };
1092
+ }
1093
+ function resolveMenuItems(config, context) {
1094
+ const rawItems = resolveAsValue(config?.items, context, []);
1095
+ const items = [];
1096
+ toArray(rawItems).forEach((raw, index) => {
1097
+ const item = resolveItem(raw, index, context);
1098
+ if (!item) return;
1099
+ const previous = items[items.length - 1];
1100
+ if (item.type === "separator" && (!previous || previous.type === "separator")) {
1101
+ return;
1102
+ }
1103
+ items.push(item);
1104
+ });
1105
+ if (items[items.length - 1]?.type === "separator") items.pop();
1106
+ return items;
1107
+ }
1108
+ function resolveMenuHeader(config, context) {
1109
+ if (config?.header === false || config?.showPageHeader === false) return null;
1110
+ const configured = resolveAsValue(config?.header, context, null);
1111
+ const source = isObject(configured) ? configured : isObject(context.page) ? context.page : null;
1112
+ if (!source) return null;
1113
+ const title = resolveAsValue(source.title, context, null);
1114
+ const description = resolveAsValue(source.description, context, null);
1115
+ const icon = resolveAsValue(source.icon, context, null);
1116
+ const eyebrow = resolveAsValue(source.eyebrow, context, null);
1117
+ if (!title && !description && !icon && !eyebrow) return null;
1118
+ return {
1119
+ description,
1120
+ descriptionText: extractNodeText(description),
1121
+ eyebrow,
1122
+ icon,
1123
+ title,
1124
+ titleText: extractNodeText(title)
1125
+ };
1126
+ }
1127
+ function getNextActiveIndex(items, current, direction) {
1128
+ const count = items.length;
1129
+ const start = current < 0 ? direction === 1 ? 0 : count - 1 : current + direction;
1130
+ for (let step = 0; step < count; step++) {
1131
+ const index = ((start + step * direction) % count + count) % count;
1132
+ if (items[index].type === "action" && !items[index].disabled) return index;
1133
+ }
1134
+ return current;
1135
+ }
1136
+
1137
+ // src/modules/context-menu/resolver.ts
1138
+ function normalizeMenuCandidates(registryMenus) {
1139
+ const candidates = [];
1140
+ for (const [registryKey, rawConfig] of Object.entries(registryMenus || {})) {
1141
+ if (!isObject(rawConfig)) continue;
1142
+ const { menus, ...sharedConfig } = rawConfig;
1143
+ const nestedMenus = toArray(menus);
1144
+ const hasSharedItems = Array.isArray(sharedConfig.items) || typeof sharedConfig.items === "function";
1145
+ if (hasSharedItems || nestedMenus.length === 0) {
1146
+ candidates.push({
1147
+ config: sharedConfig,
1148
+ order: candidates.length,
1149
+ registryKey
1150
+ });
1151
+ }
1152
+ for (const menu of nestedMenus) {
1153
+ candidates.push({
1154
+ config: {
1155
+ ...sharedConfig,
1156
+ ...menu,
1157
+ classNames: { ...sharedConfig.classNames, ...menu.classNames }
1158
+ },
1159
+ order: candidates.length,
1160
+ registryKey
1161
+ });
1162
+ }
1163
+ }
1164
+ return candidates;
1165
+ }
1166
+ function isPathAllowed(config, registryKey, pathname) {
1167
+ if (!pathname) return true;
1168
+ if (config.path === pathname) return true;
1169
+ const explicitPaths = toArray(config.paths).filter(Boolean);
1170
+ if (explicitPaths.length > 0) return explicitPaths.includes(pathname);
1171
+ if (typeof config.pathMatcher === "function") {
1172
+ try {
1173
+ return Boolean(config.pathMatcher(pathname));
1174
+ } catch {
1175
+ return false;
1176
+ }
1177
+ }
1178
+ return registryKey === pathname || registryKey === CURRENT_PAGE_KEY || registryKey === GLOBAL_MENU_KEY;
1179
+ }
1180
+ function getElementDepth(from, ancestor) {
1181
+ let depth = 0;
1182
+ for (let node = from; node && node !== ancestor; node = node.parentElement) {
1183
+ depth += 1;
1184
+ }
1185
+ return depth;
1186
+ }
1187
+ function getTargetScore(config, targetElement) {
1188
+ const selectors = toArray(config.target).filter(
1189
+ (selector) => typeof selector === "string" && selector.trim()
1190
+ );
1191
+ if (selectors.length === 0) return 0;
1192
+ if (!targetElement) return null;
1193
+ let minDepth = Infinity;
1194
+ for (const selector of selectors) {
1195
+ try {
1196
+ const matched = targetElement.closest(selector);
1197
+ if (matched) {
1198
+ minDepth = Math.min(minDepth, getElementDepth(targetElement, matched));
1199
+ }
1200
+ } catch {
1201
+ }
1202
+ }
1203
+ return minDepth === Infinity ? null : Math.max(0, 100 - minDepth);
1204
+ }
1205
+ function getRouteScore(config, registryKey, pathname) {
1206
+ if (!pathname) return 0;
1207
+ if (config.path === pathname || toArray(config.paths).includes(pathname) || registryKey === pathname) {
1208
+ return 100;
1209
+ }
1210
+ if (registryKey === CURRENT_PAGE_KEY) return 70;
1211
+ if (registryKey === GLOBAL_MENU_KEY) return 40;
1212
+ return 10;
1213
+ }
1214
+ function buildMenuContext(config, event, pathname, targetElement) {
1215
+ let context = {
1216
+ currentTarget: event.currentTarget ?? null,
1217
+ event,
1218
+ pathname: pathname || "",
1219
+ point: { x: Number(event.clientX) || 0, y: Number(event.clientY) || 0 },
1220
+ target: targetElement
1221
+ };
1222
+ if (config.payload !== void 0) context.payload = config.payload;
1223
+ try {
1224
+ const payload = config.resolvePayload?.(event, context);
1225
+ if (payload !== void 0) context.payload = payload;
1226
+ } catch {
1227
+ }
1228
+ try {
1229
+ const extra = config.resolveContext?.(event, context);
1230
+ if (isObject(extra)) context = { ...context, ...extra };
1231
+ } catch {
1232
+ }
1233
+ return context;
1234
+ }
1235
+ function isMenuOverlayTarget(element) {
1236
+ return Boolean(
1237
+ element?.closest?.(
1238
+ '[data-context-menu-ignore], [data-context-menu-overlay], [role="menu"]'
1239
+ ) || element?.classList?.contains("context-menu-overlay")
1240
+ );
1241
+ }
1242
+ function resolveEventTarget(event) {
1243
+ const initialTarget = event.target instanceof Element ? event.target : null;
1244
+ if (initialTarget && !isMenuOverlayTarget(initialTarget)) {
1245
+ return initialTarget;
1246
+ }
1247
+ if (!Number.isFinite(event.clientX) || !Number.isFinite(event.clientY)) {
1248
+ return initialTarget;
1249
+ }
1250
+ try {
1251
+ const underneath = document.elementsFromPoint(event.clientX, event.clientY).find((element) => !isMenuOverlayTarget(element));
1252
+ return underneath || initialTarget;
1253
+ } catch {
1254
+ return initialTarget;
1255
+ }
1256
+ }
1257
+ function passesWhen(config, event, info) {
1258
+ if (typeof config.when !== "function") return config.when !== false;
1259
+ try {
1260
+ return Boolean(config.when(event, info));
1261
+ } catch {
1262
+ return false;
1263
+ }
1264
+ }
1265
+ function resolveContextMenu(registryMenus, pathname, event) {
1266
+ const targetElement = resolveEventTarget(event);
1267
+ let winner = null;
1268
+ for (const { config, order, registryKey } of normalizeMenuCandidates(
1269
+ registryMenus
1270
+ )) {
1271
+ if (!isPathAllowed(config, registryKey, pathname)) continue;
1272
+ const context = buildMenuContext(config, event, pathname, targetElement);
1273
+ if (!resolveAsBoolean(config.enabled, context, true)) continue;
1274
+ if (!passesWhen(config, event, {
1275
+ context,
1276
+ pathname: pathname || "",
1277
+ target: targetElement
1278
+ })) {
1279
+ continue;
1280
+ }
1281
+ const items = resolveMenuItems(config, context);
1282
+ if (!items.length) continue;
1283
+ const targetScore = getTargetScore(config, targetElement);
1284
+ if (targetScore === null) continue;
1285
+ const priority = Number(config.priority);
1286
+ const score = (Number.isFinite(priority) ? priority : 0) * 1e4 + getRouteScore(config, registryKey, pathname) * 100 + targetScore;
1287
+ if (!winner || score > winner.score) {
1288
+ winner = { config, context, items, order, score };
1289
+ }
1290
+ }
1291
+ return winner;
1292
+ }
1293
+ function prepareMenu(config, context, event) {
1294
+ const onOpenResult = safeInvoke(config.onOpen, event, context);
1295
+ if (onOpenResult === false) return null;
1296
+ const nextContext = isObject(onOpenResult) ? { ...context, ...onOpenResult } : context;
1297
+ const items = resolveMenuItems(config, nextContext);
1298
+ return items.length ? { context: nextContext, items } : null;
1299
+ }
1300
+
1301
+ // src/modules/context-menu/state.ts
1302
+ function createInitialMenuState() {
1303
+ return {
1304
+ position: INITIAL_POSITION,
1305
+ context: null,
1306
+ isOpen: false,
1307
+ config: null,
1308
+ items: []
1309
+ };
1310
+ }
1311
+ function resolveNextOpenState({
1312
+ config,
1313
+ context,
1314
+ items,
1315
+ position
1316
+ }) {
1317
+ if (!config) return null;
1318
+ return {
1319
+ config,
1320
+ context: context ?? null,
1321
+ isOpen: true,
1322
+ items: items ?? [],
1323
+ position: {
1324
+ x: Math.round(toFiniteNumber(position?.x, 0)),
1325
+ y: Math.round(toFiniteNumber(position?.y, 0))
1326
+ }
1327
+ };
1328
+ }
1329
+ var ContextMenuContext = getOrCreateGlobalContext(
1330
+ "ContextMenuContext",
1331
+ null
1332
+ );
1333
+ function selectIsOpen(state) {
1334
+ return state.isOpen;
1335
+ }
1336
+ function ContextMenuProvider({ children }) {
1337
+ const pathname = usePathname();
1338
+ const [store] = useState(
1339
+ () => createStore(createInitialMenuState(), {
1340
+ freezeSnapshots: false
1341
+ })
1342
+ );
1343
+ const isOpen = useStore(store, selectIsOpen);
1344
+ const pathnameRef = useRef(pathname);
1345
+ useInsertionEffect(() => {
1346
+ pathnameRef.current = pathname;
1347
+ }, [pathname]);
1348
+ const actions = useMemo(() => {
1349
+ const openMenu = (input) => {
1350
+ const nextState = resolveNextOpenState(input);
1351
+ if (nextState) store.publish(nextState);
1352
+ };
1353
+ const closeMenu = () => {
1354
+ const current = store.getSnapshot();
1355
+ if (!current.isOpen) return;
1356
+ store.publish(createInitialMenuState());
1357
+ safeInvoke(current.config?.onClose, current.context);
1358
+ };
1359
+ const bind = (payload, configOverride) => ({
1360
+ onContextMenu: (event) => {
1361
+ const config = configOverride || store.getSnapshot().config;
1362
+ if (!config) return;
1363
+ event.preventDefault?.();
1364
+ event.stopPropagation?.();
1365
+ const point = {
1366
+ x: Number(event.clientX ?? 0),
1367
+ y: Number(event.clientY ?? 0)
1368
+ };
1369
+ const context = {
1370
+ currentTarget: event.currentTarget ?? null,
1371
+ event,
1372
+ pathname: pathnameRef.current || "",
1373
+ payload,
1374
+ point,
1375
+ target: event.target ?? null
1376
+ };
1377
+ const prepared = prepareMenu(config, context, event);
1378
+ if (!prepared) return;
1379
+ openMenu({
1380
+ config,
1381
+ context: prepared.context,
1382
+ items: prepared.items,
1383
+ position: point
1384
+ });
1385
+ }
1386
+ });
1387
+ return { bind, closeMenu, openMenu };
1388
+ }, [store]);
1389
+ const contextValue = useMemo(
1390
+ () => ({ actions, store }),
1391
+ [actions, store]
1392
+ );
1393
+ useEffect(() => emitContextMenuVisibility(isOpen), [isOpen]);
1394
+ return /* @__PURE__ */ jsx(ContextMenuContext, { value: contextValue, children });
1395
+ }
1396
+ function useContextMenuRegistration(config, options) {
1397
+ useModuleRegistration("contextMenu", config, options);
1398
+ }
1399
+ function useContextMenu(config, options) {
1400
+ useContextMenuRegistration(config || null, options);
1401
+ const { actions, store } = useRequiredContext(
1402
+ ContextMenuContext,
1403
+ "useContextMenu",
1404
+ "ContextMenuProvider"
1405
+ );
1406
+ const state = useStore(store);
1407
+ const ctx = useMemo(
1408
+ () => ({ ...state, ...actions }),
1409
+ [actions, state]
1410
+ );
1411
+ return useMemo(() => {
1412
+ if (!config) return ctx;
1413
+ return {
1414
+ ...ctx,
1415
+ bind: (payload, configOverride) => ctx.bind(payload, { ...config, ...configOverride })
1416
+ };
1417
+ }, [config, ctx]);
1418
+ }
1419
+ function useContextMenuActions() {
1420
+ return useRequiredContext(
1421
+ ContextMenuContext,
1422
+ "useContextMenuActions",
1423
+ "ContextMenuProvider"
1424
+ ).actions;
1425
+ }
1426
+ function useContextMenuState() {
1427
+ const { store } = useRequiredContext(
1428
+ ContextMenuContext,
1429
+ "useContextMenuState",
1430
+ "ContextMenuProvider"
1431
+ );
1432
+ return useStore(store);
1433
+ }
1434
+ function selectDockPageCard(dock) {
1435
+ const card = dock.activeItem;
1436
+ return card && !card.isSurface ? card : null;
1437
+ }
1438
+ function useContextMenuListener() {
1439
+ const menus = useRegistryEntries(
1440
+ "contextMenu"
1441
+ );
1442
+ const dockCard = useModuleState("dock", selectDockPageCard, null);
1443
+ const { openMenu } = useContextMenuActions();
1444
+ const pathname = usePathname();
1445
+ useEffect(() => {
1446
+ const handleContextMenu = (event) => {
1447
+ const match = resolveContextMenu(menus, pathname || void 0, event);
1448
+ if (!match) return;
1449
+ event.preventDefault();
1450
+ event.stopPropagation();
1451
+ const page = resolveContextMenuPageMeta(dockCard, pathname || "");
1452
+ const prepared = prepareMenu(
1453
+ match.config,
1454
+ page ? { ...match.context, page } : match.context,
1455
+ event
1456
+ );
1457
+ if (!prepared) return;
1458
+ openMenu({
1459
+ config: match.config,
1460
+ context: prepared.context,
1461
+ items: prepared.items,
1462
+ position: { x: event.clientX, y: event.clientY }
1463
+ });
1464
+ };
1465
+ document.addEventListener("contextmenu", handleContextMenu, true);
1466
+ return () => document.removeEventListener("contextmenu", handleContextMenu, true);
1467
+ }, [dockCard, menus, openMenu, pathname]);
1468
+ }
1469
+ function useMenuDismissal(menuRef, onClose) {
1470
+ useEffect(() => {
1471
+ const preventScroll = (event) => event.preventDefault();
1472
+ const listenerOptions = { capture: true, passive: false };
1473
+ const handleInteraction = (event) => {
1474
+ const isInside = menuRef.current?.contains(event.target);
1475
+ if (event.type === "keydown") {
1476
+ if (event.key === "Escape") onClose();
1477
+ if (!isInside && isScrollLockKey(event)) {
1478
+ event.preventDefault();
1479
+ }
1480
+ } else if (!isInside) {
1481
+ onClose();
1482
+ }
1483
+ };
1484
+ document.addEventListener("mousedown", handleInteraction, true);
1485
+ document.addEventListener("keydown", handleInteraction, true);
1486
+ window.addEventListener("wheel", preventScroll, listenerOptions);
1487
+ window.addEventListener("touchmove", preventScroll, listenerOptions);
1488
+ return () => {
1489
+ document.removeEventListener("mousedown", handleInteraction, true);
1490
+ document.removeEventListener("keydown", handleInteraction, true);
1491
+ window.removeEventListener("wheel", preventScroll, true);
1492
+ window.removeEventListener("touchmove", preventScroll, true);
1493
+ };
1494
+ }, [menuRef, onClose]);
1495
+ }
1496
+ var emptySubscribe = () => () => {
1497
+ };
1498
+ function useContextMenuContentModel({
1499
+ config,
1500
+ items,
1501
+ menuContext,
1502
+ onClose,
1503
+ position
1504
+ }) {
1505
+ const menuRef = useRef(null);
1506
+ const itemRefs = useRef([]);
1507
+ const theme = useTheme(contextMenuTheme);
1508
+ const classes = useMemo(() => {
1509
+ const overrides = config.classNames ?? {};
1510
+ const merged = { ...theme.slots };
1511
+ for (const slot of Object.keys(merged)) {
1512
+ merged[slot] = joinClassNames(theme.slots[slot], overrides[slot]);
1513
+ }
1514
+ return merged;
1515
+ }, [config.classNames, theme.slots]);
1516
+ const header = useMemo(
1517
+ () => resolveMenuHeader(config, menuContext),
1518
+ [config, menuContext]
1519
+ );
1520
+ const [activeIndex, setActiveIndex] = useState(-1);
1521
+ const [prevItems, setPrevItems] = useState(items);
1522
+ if (items !== prevItems) {
1523
+ setPrevItems(items);
1524
+ setActiveIndex(-1);
1525
+ }
1526
+ useLayoutEffect(() => {
1527
+ itemRefs.current = [];
1528
+ positionMenu(menuRef.current, position);
1529
+ }, [header, items, position]);
1530
+ useEffect(() => {
1531
+ const target = activeIndex < 0 ? menuRef.current : itemRefs.current[activeIndex];
1532
+ target?.focus({ preventScroll: true });
1533
+ }, [activeIndex]);
1534
+ useMenuDismissal(menuRef, onClose);
1535
+ const handleItemSelect = useCallback(
1536
+ (item, event) => {
1537
+ event.preventDefault();
1538
+ event.stopPropagation();
1539
+ if (item.disabled) return;
1540
+ safeInvoke(item.onSelect || item.onClick, event, menuContext);
1541
+ if (item.closeOnSelect !== false) onClose();
1542
+ },
1543
+ [menuContext, onClose]
1544
+ );
1545
+ const handleMenuKeyDown = (event) => {
1546
+ if (event.key === "Escape") {
1547
+ event.preventDefault();
1548
+ onClose();
1549
+ } else if (event.key === "ArrowDown" || event.key === "ArrowUp") {
1550
+ event.preventDefault();
1551
+ const direction = event.key === "ArrowDown" ? 1 : -1;
1552
+ setActiveIndex(
1553
+ (current) => getNextActiveIndex(items, current, direction)
1554
+ );
1555
+ } else if ((event.key === "Enter" || event.key === " ") && items[activeIndex]) {
1556
+ event.preventDefault();
1557
+ handleItemSelect(items[activeIndex], event);
1558
+ }
1559
+ };
1560
+ return {
1561
+ menuRef,
1562
+ itemRefs,
1563
+ classes,
1564
+ styles: theme.styles,
1565
+ header,
1566
+ activeIndex,
1567
+ setActiveIndex,
1568
+ handleItemSelect,
1569
+ handleMenuKeyDown
1570
+ };
1571
+ }
1572
+ function useContextMenuRendererModel() {
1573
+ const { closeMenu, config, context, isOpen, items, position } = useContextMenu();
1574
+ const isMounted = useSyncExternalStore(
1575
+ emptySubscribe,
1576
+ () => true,
1577
+ () => false
1578
+ );
1579
+ return { closeMenu, config, context, isOpen, items, position, isMounted };
1580
+ }
1581
+ function Icon({
1582
+ className = "center",
1583
+ color,
1584
+ icon,
1585
+ onClick,
1586
+ size = 20,
1587
+ style,
1588
+ ...props
1589
+ }) {
1590
+ return /* @__PURE__ */ jsx(
1591
+ Icon$1,
1592
+ {
1593
+ className,
1594
+ height: size,
1595
+ icon,
1596
+ onClick,
1597
+ style: { color, ...style },
1598
+ width: size,
1599
+ ...props
1600
+ }
1601
+ );
1602
+ }
1603
+ Icon.displayName = "Icon";
1604
+
1605
+ // src/tokens/motion.ts
1606
+ var DURATION_TOKENS = Object.freeze({
1607
+ INSTANT: 0.08,
1608
+ MICRO: 0.18,
1609
+ FAST: 0.28,
1610
+ BASE: 0.36,
1611
+ MODERATE: 0.44,
1612
+ SLOW: 0.58,
1613
+ CINEMATIC: 0.86
1614
+ });
1615
+ var EASING_CURVES = Object.freeze({
1616
+ OUT_EXPO: [0.16, 1, 0.3, 1],
1617
+ OUT_QUART: [0.25, 1, 0.5, 1],
1618
+ OUT_QUINT: [0.22, 1, 0.36, 1],
1619
+ IN_OUT_CUBIC: [0.65, 0, 0.35, 1],
1620
+ IN_CUBIC: [0.5, 0, 1, 1],
1621
+ OUT_BACK: [0.34, 1.56, 0.64, 1]
1622
+ });
1623
+ var MOTION_EASINGS = Object.freeze({
1624
+ ENTER: EASING_CURVES.OUT_QUART,
1625
+ ENTER_EMPHASIZED: EASING_CURVES.OUT_EXPO,
1626
+ EXIT: EASING_CURVES.IN_CUBIC
1627
+ });
1628
+ Object.freeze({
1629
+ MICRO: Object.freeze({
1630
+ distance: 4,
1631
+ duration: DURATION_TOKENS.MICRO,
1632
+ ease: MOTION_EASINGS.ENTER_EMPHASIZED,
1633
+ scaleDelta: 8e-3
1634
+ }),
1635
+ FAST: Object.freeze({
1636
+ distance: 9,
1637
+ duration: DURATION_TOKENS.FAST,
1638
+ ease: MOTION_EASINGS.ENTER_EMPHASIZED,
1639
+ scaleDelta: 0.012
1640
+ }),
1641
+ STANDARD: Object.freeze({
1642
+ distance: 18,
1643
+ duration: DURATION_TOKENS.MODERATE,
1644
+ ease: MOTION_EASINGS.ENTER,
1645
+ scaleDelta: 0.018
1646
+ }),
1647
+ SURFACE: Object.freeze({
1648
+ distance: 28,
1649
+ duration: DURATION_TOKENS.SLOW,
1650
+ ease: MOTION_EASINGS.ENTER_EMPHASIZED,
1651
+ scaleDelta: 0.024
1652
+ })
1653
+ });
1654
+ Object.freeze({
1655
+ duration: DURATION_TOKENS.INSTANT,
1656
+ ease: "linear"
1657
+ });
1658
+
1659
+ // src/modules/context-menu/motion.ts
1660
+ var CONTEXT_MENU_EASINGS = Object.freeze({
1661
+ EMPHASIZED: EASING_CURVES.OUT_EXPO,
1662
+ SOFT: EASING_CURVES.OUT_QUINT,
1663
+ EXIT: EASING_CURVES.IN_CUBIC
1664
+ });
1665
+ var CONTEXT_MENU_TIERS = Object.freeze({
1666
+ MICRO: {
1667
+ duration: DURATION_TOKENS.FAST,
1668
+ distance: 4,
1669
+ scaleDelta: 8e-3,
1670
+ ease: CONTEXT_MENU_EASINGS.EMPHASIZED
1671
+ }
1672
+ });
1673
+ function toGpuTransform({
1674
+ x = 0,
1675
+ y = 0,
1676
+ scale = 1
1677
+ } = {}) {
1678
+ return `translate3d(${x}px, ${y}px, 0) scale(${scale})`;
1679
+ }
1680
+ var CONTEXT_MENU_MICRO_SPRING = Object.freeze({
1681
+ type: "spring",
1682
+ stiffness: 520,
1683
+ damping: 30,
1684
+ mass: 0.28
1685
+ });
1686
+ var CONTEXT_MENU_ITEM_TAP = Object.freeze({
1687
+ transform: toGpuTransform({
1688
+ scale: 0.97
1689
+ })
1690
+ });
1691
+ var menuContentVariants = Object.freeze({
1692
+ hidden: {
1693
+ opacity: 0
1694
+ },
1695
+ visible: {
1696
+ opacity: 1,
1697
+ transition: {
1698
+ duration: CONTEXT_MENU_TIERS.MICRO.duration,
1699
+ ease: CONTEXT_MENU_EASINGS.SOFT,
1700
+ delay: 0.04
1701
+ }
1702
+ },
1703
+ exit: {
1704
+ opacity: 0,
1705
+ transition: {
1706
+ duration: DURATION_TOKENS.MICRO,
1707
+ ease: CONTEXT_MENU_EASINGS.EXIT
1708
+ }
1709
+ }
1710
+ });
1711
+ var menuItemVariants = Object.freeze({
1712
+ hidden: {
1713
+ opacity: 0,
1714
+ transform: toGpuTransform({
1715
+ y: CONTEXT_MENU_TIERS.MICRO.distance,
1716
+ scale: 0.992
1717
+ })
1718
+ },
1719
+ visible: (index = 0) => ({
1720
+ opacity: 1,
1721
+ transform: toGpuTransform(),
1722
+ transition: {
1723
+ duration: CONTEXT_MENU_TIERS.MICRO.duration,
1724
+ ease: CONTEXT_MENU_EASINGS.EMPHASIZED,
1725
+ delay: 0.04 + Math.min(Math.max(Number(index) || 0, 0) * 0.042, 0.21)
1726
+ }
1727
+ }),
1728
+ exit: {
1729
+ opacity: 0,
1730
+ transform: toGpuTransform({
1731
+ y: -3,
1732
+ scale: 0.994
1733
+ }),
1734
+ transition: {
1735
+ duration: DURATION_TOKENS.MICRO,
1736
+ ease: CONTEXT_MENU_EASINGS.EXIT
1737
+ }
1738
+ }
1739
+ });
1740
+ var menuPopVariants = Object.freeze({
1741
+ hidden: {
1742
+ opacity: 0,
1743
+ transform: toGpuTransform({
1744
+ scale: 0.96
1745
+ }),
1746
+ transformOrigin: "top left"
1747
+ },
1748
+ visible: {
1749
+ opacity: 1,
1750
+ transform: toGpuTransform(),
1751
+ transformOrigin: "top left",
1752
+ transition: {
1753
+ duration: CONTEXT_MENU_TIERS.MICRO.duration,
1754
+ ease: CONTEXT_MENU_EASINGS.EMPHASIZED
1755
+ }
1756
+ },
1757
+ exit: {
1758
+ opacity: 0,
1759
+ transform: toGpuTransform({
1760
+ scale: 0.98
1761
+ }),
1762
+ transformOrigin: "top left",
1763
+ transition: {
1764
+ duration: DURATION_TOKENS.MICRO,
1765
+ ease: CONTEXT_MENU_EASINGS.EXIT
1766
+ }
1767
+ }
1768
+ });
1769
+ function ContextMenuHeaderIcon({
1770
+ classes,
1771
+ icon
1772
+ }) {
1773
+ const iconClassName = classes.headerIcon;
1774
+ if (isImageIconSource(icon)) {
1775
+ return /* @__PURE__ */ jsx(
1776
+ "div",
1777
+ {
1778
+ className: iconClassName,
1779
+ style: { backgroundImage: `url(${icon})` }
1780
+ }
1781
+ );
1782
+ }
1783
+ return /* @__PURE__ */ jsx("div", { className: iconClassName, children: typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { icon, size: 20 }) : icon });
1784
+ }
1785
+ function ContextMenuHeader({
1786
+ classes,
1787
+ header
1788
+ }) {
1789
+ if (!header) return null;
1790
+ return /* @__PURE__ */ jsxs("div", { className: classes.header, children: [
1791
+ header.icon && /* @__PURE__ */ jsx(ContextMenuHeaderIcon, { classes, icon: header.icon }),
1792
+ /* @__PURE__ */ jsxs("div", { className: classes.headerText, children: [
1793
+ header.eyebrow && /* @__PURE__ */ jsx("div", { className: classes.headerEyebrow, children: header.eyebrow }),
1794
+ header.title && /* @__PURE__ */ jsx("div", { className: classes.headerTitle, children: header.title }),
1795
+ header.description && /* @__PURE__ */ jsx("div", { className: classes.headerDescription, children: header.description })
1796
+ ] })
1797
+ ] });
1798
+ }
1799
+ function ContextMenuItem({
1800
+ classes,
1801
+ isActive,
1802
+ item,
1803
+ onHover,
1804
+ onSelect,
1805
+ setButtonRef
1806
+ }) {
1807
+ if (item.type === "separator") {
1808
+ return /* @__PURE__ */ jsx("div", { className: classes.separator, role: "separator" });
1809
+ }
1810
+ const itemClassName = joinClassNames(classes.item, item.className);
1811
+ const itemIconClassName = joinClassNames(
1812
+ classes.itemIcon,
1813
+ item.itemIconClassName
1814
+ );
1815
+ return /* @__PURE__ */ jsxs(
1816
+ motion.button,
1817
+ {
1818
+ ref: setButtonRef,
1819
+ className: itemClassName,
1820
+ "data-active": isActive ? "true" : void 0,
1821
+ "aria-disabled": item.disabled,
1822
+ disabled: item.disabled,
1823
+ role: "menuitem",
1824
+ type: "button",
1825
+ whileTap: CONTEXT_MENU_ITEM_TAP,
1826
+ transition: CONTEXT_MENU_MICRO_SPRING,
1827
+ onMouseEnter: onHover,
1828
+ onClick: (event) => onSelect(item, event),
1829
+ children: [
1830
+ item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { icon: item.icon, className: itemIconClassName, size: 18 }) : item.icon),
1831
+ /* @__PURE__ */ jsx("span", { className: classes.itemLabel, children: item.label }),
1832
+ item.shortcut && /* @__PURE__ */ jsx("span", { className: classes.itemShortcut, children: item.shortcut })
1833
+ ]
1834
+ }
1835
+ );
1836
+ }
1837
+ var EMPTY_MENU_CONTEXT = Object.freeze({
1838
+ pathname: "",
1839
+ point: { x: 0, y: 0 }
1840
+ });
1841
+ function ContextMenuContent({
1842
+ config,
1843
+ items,
1844
+ menuContext,
1845
+ onClose,
1846
+ position
1847
+ }) {
1848
+ const {
1849
+ menuRef,
1850
+ itemRefs,
1851
+ classes,
1852
+ styles,
1853
+ header,
1854
+ activeIndex,
1855
+ setActiveIndex,
1856
+ handleItemSelect,
1857
+ handleMenuKeyDown
1858
+ } = useContextMenuContentModel({
1859
+ config,
1860
+ items,
1861
+ menuContext,
1862
+ onClose,
1863
+ position
1864
+ });
1865
+ return /* @__PURE__ */ jsxs("div", { children: [
1866
+ /* @__PURE__ */ jsx(
1867
+ "div",
1868
+ {
1869
+ "data-context-menu-overlay": true,
1870
+ className: classes.backdrop,
1871
+ onMouseDown: onClose,
1872
+ style: styles.backdrop
1873
+ }
1874
+ ),
1875
+ /* @__PURE__ */ jsxs(
1876
+ motion.div,
1877
+ {
1878
+ ref: menuRef,
1879
+ "data-context-menu-ignore": true,
1880
+ variants: menuPopVariants,
1881
+ initial: "hidden",
1882
+ animate: "visible",
1883
+ exit: "exit",
1884
+ className: classes.menu,
1885
+ role: "menu",
1886
+ tabIndex: -1,
1887
+ style: {
1888
+ ...styles.menu,
1889
+ left: position.x || 0,
1890
+ top: position.y || 0,
1891
+ position: "fixed"
1892
+ },
1893
+ onMouseLeave: () => setActiveIndex(-1),
1894
+ onKeyDown: handleMenuKeyDown,
1895
+ children: [
1896
+ /* @__PURE__ */ jsx(
1897
+ motion.div,
1898
+ {
1899
+ variants: menuContentVariants,
1900
+ initial: "hidden",
1901
+ animate: "visible",
1902
+ children: /* @__PURE__ */ jsx(ContextMenuHeader, { classes, header })
1903
+ }
1904
+ ),
1905
+ items.map((item, index) => /* @__PURE__ */ jsx(
1906
+ motion.div,
1907
+ {
1908
+ variants: menuItemVariants,
1909
+ custom: index,
1910
+ initial: "hidden",
1911
+ animate: "visible",
1912
+ children: /* @__PURE__ */ jsx(
1913
+ ContextMenuItem,
1914
+ {
1915
+ item,
1916
+ classes,
1917
+ isActive: index === activeIndex,
1918
+ onHover: () => {
1919
+ if (item.type === "action" && !item.disabled) {
1920
+ setActiveIndex(index);
1921
+ }
1922
+ },
1923
+ setButtonRef: (node) => {
1924
+ itemRefs.current[index] = node;
1925
+ },
1926
+ onSelect: handleItemSelect
1927
+ }
1928
+ )
1929
+ },
1930
+ item.key || `menu-item-${index}`
1931
+ ))
1932
+ ]
1933
+ }
1934
+ )
1935
+ ] });
1936
+ }
1937
+ function ContextMenuRenderer() {
1938
+ const { closeMenu, config, context, isOpen, items, position, isMounted } = useContextMenuRendererModel();
1939
+ if (!isMounted) return null;
1940
+ const menuContext = context ?? EMPTY_MENU_CONTEXT;
1941
+ const resolvedItems = items.length ? items : resolveMenuItems(config, menuContext);
1942
+ return createPortal(
1943
+ /* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && config && resolvedItems.length > 0 && /* @__PURE__ */ jsx(
1944
+ ContextMenuContent,
1945
+ {
1946
+ config,
1947
+ items: resolvedItems,
1948
+ menuContext,
1949
+ position,
1950
+ onClose: closeMenu
1951
+ },
1952
+ "context-menu-content"
1953
+ ) }),
1954
+ document.body
1955
+ );
1956
+ }
1957
+ function ContextMenuGlobal() {
1958
+ useContextMenuListener();
1959
+ return /* @__PURE__ */ jsx(ContextMenuRenderer, {});
1960
+ }
1961
+
1962
+ // src/modules/context-menu/module.tsx
1963
+ function selectPageContextMenu(config) {
1964
+ return config.contextMenu ?? null;
1965
+ }
1966
+ function useContextMenuPage(_slice, page) {
1967
+ const actions = useContextMenuActions();
1968
+ return useMemo(
1969
+ () => ({
1970
+ ...actions,
1971
+ set: (contextMenu) => page.set({ contextMenu })
1972
+ }),
1973
+ [actions, page]
1974
+ );
1975
+ }
1976
+ var contextMenuModule = defineModule({
1977
+ id: "contextMenu",
1978
+ context: ContextMenuContext,
1979
+ Provider: ContextMenuProvider,
1980
+ uses: ["dock"],
1981
+ Overlay: ContextMenuGlobal,
1982
+ registry: {
1983
+ cleanupDelayMs: 600,
1984
+ keyPolicy: "route",
1985
+ lifecycle: "immediate",
1986
+ reservedKeys: [CURRENT_PAGE_KEY, GLOBAL_MENU_KEY]
1987
+ },
1988
+ page: {
1989
+ select: selectPageContextMenu,
1990
+ entries: (slice, { pathname }) => [
1991
+ { key: pathname || CURRENT_PAGE_KEY, value: slice }
1992
+ ],
1993
+ use: useContextMenuPage
1994
+ }
1995
+ });
1996
+ function defineContextMenu(definition = {}) {
1997
+ return Object.freeze({
1998
+ config: definition,
1999
+ id: definition.id ?? "context-menu",
2000
+ use: function useDefinedContextMenu(options = {}) {
2001
+ return useContextMenu({ ...definition, ...options });
2002
+ }
2003
+ });
2004
+ }
2005
+
2006
+ export { CONTEXT_MENU_VISIBILITY_EVENT, ContextMenuContext, ContextMenuProvider, contextMenuModule, contextMenuTheme, defineContextMenu, useContextMenu, useContextMenuActions, useContextMenuListener, useContextMenuRegistration, useContextMenuState };
2007
+ //# sourceMappingURL=index.js.map
2008
+ //# sourceMappingURL=index.js.map