@mappoh/nova 0.1.16

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/dist/animation/parallax.d.ts +23 -0
  2. package/dist/animation/parallax.d.ts.map +1 -0
  3. package/dist/animation/parallax.js +96 -0
  4. package/dist/animation/parallax.js.map +1 -0
  5. package/dist/animation/scroll-animate.d.ts +30 -0
  6. package/dist/animation/scroll-animate.d.ts.map +1 -0
  7. package/dist/animation/scroll-animate.js +65 -0
  8. package/dist/animation/scroll-animate.js.map +1 -0
  9. package/dist/animation/scroll-observer.d.ts +32 -0
  10. package/dist/animation/scroll-observer.d.ts.map +1 -0
  11. package/dist/animation/scroll-observer.js +63 -0
  12. package/dist/animation/scroll-observer.js.map +1 -0
  13. package/dist/animation/smooth-scroll.d.ts +47 -0
  14. package/dist/animation/smooth-scroll.d.ts.map +1 -0
  15. package/dist/animation/smooth-scroll.js +169 -0
  16. package/dist/animation/smooth-scroll.js.map +1 -0
  17. package/dist/animation/text-reveal.d.ts +30 -0
  18. package/dist/animation/text-reveal.d.ts.map +1 -0
  19. package/dist/animation/text-reveal.js +164 -0
  20. package/dist/animation/text-reveal.js.map +1 -0
  21. package/dist/animation/ticker.d.ts +32 -0
  22. package/dist/animation/ticker.d.ts.map +1 -0
  23. package/dist/animation/ticker.js +62 -0
  24. package/dist/animation/ticker.js.map +1 -0
  25. package/dist/canvas/dot-grid.d.ts +50 -0
  26. package/dist/canvas/dot-grid.d.ts.map +1 -0
  27. package/dist/canvas/dot-grid.js +123 -0
  28. package/dist/canvas/dot-grid.js.map +1 -0
  29. package/dist/canvas/noise.d.ts +33 -0
  30. package/dist/canvas/noise.d.ts.map +1 -0
  31. package/dist/canvas/noise.js +241 -0
  32. package/dist/canvas/noise.js.map +1 -0
  33. package/dist/canvas/particles.d.ts +44 -0
  34. package/dist/canvas/particles.d.ts.map +1 -0
  35. package/dist/canvas/particles.js +138 -0
  36. package/dist/canvas/particles.js.map +1 -0
  37. package/dist/canvas/sequence.d.ts +43 -0
  38. package/dist/canvas/sequence.d.ts.map +1 -0
  39. package/dist/canvas/sequence.js +162 -0
  40. package/dist/canvas/sequence.js.map +1 -0
  41. package/dist/component/bind.d.ts +25 -0
  42. package/dist/component/bind.d.ts.map +1 -0
  43. package/dist/component/bind.js +28 -0
  44. package/dist/component/bind.js.map +1 -0
  45. package/dist/component/component.d.ts +76 -0
  46. package/dist/component/component.d.ts.map +1 -0
  47. package/dist/component/component.js +219 -0
  48. package/dist/component/component.js.map +1 -0
  49. package/dist/component/connect.d.ts +60 -0
  50. package/dist/component/connect.d.ts.map +1 -0
  51. package/dist/component/connect.js +115 -0
  52. package/dist/component/connect.js.map +1 -0
  53. package/dist/component/html.d.ts +35 -0
  54. package/dist/component/html.d.ts.map +1 -0
  55. package/dist/component/html.js +51 -0
  56. package/dist/component/html.js.map +1 -0
  57. package/dist/component/hydrate.d.ts +37 -0
  58. package/dist/component/hydrate.d.ts.map +1 -0
  59. package/dist/component/hydrate.js +242 -0
  60. package/dist/component/hydrate.js.map +1 -0
  61. package/dist/component/index.d.ts +9 -0
  62. package/dist/component/index.d.ts.map +1 -0
  63. package/dist/component/index.js +6 -0
  64. package/dist/component/index.js.map +1 -0
  65. package/dist/component/template.d.ts +30 -0
  66. package/dist/component/template.d.ts.map +1 -0
  67. package/dist/component/template.js +469 -0
  68. package/dist/component/template.js.map +1 -0
  69. package/dist/css/gradient-text.d.ts +40 -0
  70. package/dist/css/gradient-text.d.ts.map +1 -0
  71. package/dist/css/gradient-text.js +90 -0
  72. package/dist/css/gradient-text.js.map +1 -0
  73. package/dist/css/index.d.ts +3 -0
  74. package/dist/css/index.d.ts.map +1 -0
  75. package/dist/css/index.js +2 -0
  76. package/dist/css/index.js.map +1 -0
  77. package/dist/devtools/devtools.d.ts +27 -0
  78. package/dist/devtools/devtools.d.ts.map +1 -0
  79. package/dist/devtools/devtools.js +237 -0
  80. package/dist/devtools/devtools.js.map +1 -0
  81. package/dist/devtools/index.d.ts +3 -0
  82. package/dist/devtools/index.d.ts.map +1 -0
  83. package/dist/devtools/index.js +2 -0
  84. package/dist/devtools/index.js.map +1 -0
  85. package/dist/drag/drag.d.ts +38 -0
  86. package/dist/drag/drag.d.ts.map +1 -0
  87. package/dist/drag/drag.js +181 -0
  88. package/dist/drag/drag.js.map +1 -0
  89. package/dist/drag/index.d.ts +3 -0
  90. package/dist/drag/index.d.ts.map +1 -0
  91. package/dist/drag/index.js +2 -0
  92. package/dist/drag/index.js.map +1 -0
  93. package/dist/dropdown/dropdown.d.ts +55 -0
  94. package/dist/dropdown/dropdown.d.ts.map +1 -0
  95. package/dist/dropdown/dropdown.js +314 -0
  96. package/dist/dropdown/dropdown.js.map +1 -0
  97. package/dist/dropdown/group.d.ts +18 -0
  98. package/dist/dropdown/group.d.ts.map +1 -0
  99. package/dist/dropdown/group.js +119 -0
  100. package/dist/dropdown/group.js.map +1 -0
  101. package/dist/dropdown/index.d.ts +5 -0
  102. package/dist/dropdown/index.d.ts.map +1 -0
  103. package/dist/dropdown/index.js +3 -0
  104. package/dist/dropdown/index.js.map +1 -0
  105. package/dist/forms/form-engine.d.ts +91 -0
  106. package/dist/forms/form-engine.d.ts.map +1 -0
  107. package/dist/forms/form-engine.js +228 -0
  108. package/dist/forms/form-engine.js.map +1 -0
  109. package/dist/forms/index.d.ts +3 -0
  110. package/dist/forms/index.d.ts.map +1 -0
  111. package/dist/forms/index.js +2 -0
  112. package/dist/forms/index.js.map +1 -0
  113. package/dist/forms/validators.d.ts +20 -0
  114. package/dist/forms/validators.d.ts.map +1 -0
  115. package/dist/forms/validators.js +82 -0
  116. package/dist/forms/validators.js.map +1 -0
  117. package/dist/gallery/gallery.d.ts +66 -0
  118. package/dist/gallery/gallery.d.ts.map +1 -0
  119. package/dist/gallery/gallery.js +347 -0
  120. package/dist/gallery/gallery.js.map +1 -0
  121. package/dist/gallery/index.d.ts +3 -0
  122. package/dist/gallery/index.d.ts.map +1 -0
  123. package/dist/gallery/index.js +2 -0
  124. package/dist/gallery/index.js.map +1 -0
  125. package/dist/gesture/gesture.d.ts +44 -0
  126. package/dist/gesture/gesture.d.ts.map +1 -0
  127. package/dist/gesture/gesture.js +152 -0
  128. package/dist/gesture/gesture.js.map +1 -0
  129. package/dist/gesture/index.d.ts +3 -0
  130. package/dist/gesture/index.d.ts.map +1 -0
  131. package/dist/gesture/index.js +2 -0
  132. package/dist/gesture/index.js.map +1 -0
  133. package/dist/http/http.d.ts +44 -0
  134. package/dist/http/http.d.ts.map +1 -0
  135. package/dist/http/http.js +135 -0
  136. package/dist/http/http.js.map +1 -0
  137. package/dist/http/index.d.ts +3 -0
  138. package/dist/http/index.d.ts.map +1 -0
  139. package/dist/http/index.js +2 -0
  140. package/dist/http/index.js.map +1 -0
  141. package/dist/i18n/i18n.d.ts +28 -0
  142. package/dist/i18n/i18n.d.ts.map +1 -0
  143. package/dist/i18n/i18n.js +84 -0
  144. package/dist/i18n/i18n.js.map +1 -0
  145. package/dist/i18n/index.d.ts +3 -0
  146. package/dist/i18n/index.d.ts.map +1 -0
  147. package/dist/i18n/index.js +2 -0
  148. package/dist/i18n/index.js.map +1 -0
  149. package/dist/image/effects.d.ts +33 -0
  150. package/dist/image/effects.d.ts.map +1 -0
  151. package/dist/image/effects.js +236 -0
  152. package/dist/image/effects.js.map +1 -0
  153. package/dist/image/image.d.ts +83 -0
  154. package/dist/image/image.d.ts.map +1 -0
  155. package/dist/image/image.js +236 -0
  156. package/dist/image/image.js.map +1 -0
  157. package/dist/image/index.d.ts +5 -0
  158. package/dist/image/index.d.ts.map +1 -0
  159. package/dist/image/index.js +3 -0
  160. package/dist/image/index.js.map +1 -0
  161. package/dist/interaction/index.d.ts +3 -0
  162. package/dist/interaction/index.d.ts.map +1 -0
  163. package/dist/interaction/index.js +2 -0
  164. package/dist/interaction/index.js.map +1 -0
  165. package/dist/interaction/tilt.d.ts +30 -0
  166. package/dist/interaction/tilt.d.ts.map +1 -0
  167. package/dist/interaction/tilt.js +131 -0
  168. package/dist/interaction/tilt.js.map +1 -0
  169. package/dist/lazy/index.d.ts +3 -0
  170. package/dist/lazy/index.d.ts.map +1 -0
  171. package/dist/lazy/index.js +2 -0
  172. package/dist/lazy/index.js.map +1 -0
  173. package/dist/lazy/lazy.d.ts +42 -0
  174. package/dist/lazy/lazy.d.ts.map +1 -0
  175. package/dist/lazy/lazy.js +80 -0
  176. package/dist/lazy/lazy.js.map +1 -0
  177. package/dist/modal/index.d.ts +3 -0
  178. package/dist/modal/index.d.ts.map +1 -0
  179. package/dist/modal/index.js +2 -0
  180. package/dist/modal/index.js.map +1 -0
  181. package/dist/modal/modal.d.ts +39 -0
  182. package/dist/modal/modal.d.ts.map +1 -0
  183. package/dist/modal/modal.js +174 -0
  184. package/dist/modal/modal.js.map +1 -0
  185. package/dist/router/index.d.ts +3 -0
  186. package/dist/router/index.d.ts.map +1 -0
  187. package/dist/router/index.js +2 -0
  188. package/dist/router/index.js.map +1 -0
  189. package/dist/router/router.d.ts +80 -0
  190. package/dist/router/router.d.ts.map +1 -0
  191. package/dist/router/router.js +256 -0
  192. package/dist/router/router.js.map +1 -0
  193. package/dist/router/speculate.d.ts +28 -0
  194. package/dist/router/speculate.d.ts.map +1 -0
  195. package/dist/router/speculate.js +36 -0
  196. package/dist/router/speculate.js.map +1 -0
  197. package/dist/search/fuzzy.d.ts +16 -0
  198. package/dist/search/fuzzy.d.ts.map +1 -0
  199. package/dist/search/fuzzy.js +77 -0
  200. package/dist/search/fuzzy.js.map +1 -0
  201. package/dist/search/index.d.ts +5 -0
  202. package/dist/search/index.d.ts.map +1 -0
  203. package/dist/search/index.js +3 -0
  204. package/dist/search/index.js.map +1 -0
  205. package/dist/search/search.d.ts +56 -0
  206. package/dist/search/search.d.ts.map +1 -0
  207. package/dist/search/search.js +540 -0
  208. package/dist/search/search.js.map +1 -0
  209. package/dist/search/wasm.d.ts +35 -0
  210. package/dist/search/wasm.d.ts.map +1 -0
  211. package/dist/search/wasm.js +51 -0
  212. package/dist/search/wasm.js.map +1 -0
  213. package/dist/security/cors.d.ts +61 -0
  214. package/dist/security/cors.d.ts.map +1 -0
  215. package/dist/security/cors.js +174 -0
  216. package/dist/security/cors.js.map +1 -0
  217. package/dist/security/csp.d.ts +49 -0
  218. package/dist/security/csp.d.ts.map +1 -0
  219. package/dist/security/csp.js +143 -0
  220. package/dist/security/csp.js.map +1 -0
  221. package/dist/security/csrf.d.ts +47 -0
  222. package/dist/security/csrf.d.ts.map +1 -0
  223. package/dist/security/csrf.js +122 -0
  224. package/dist/security/csrf.js.map +1 -0
  225. package/dist/security/encrypt.d.ts +64 -0
  226. package/dist/security/encrypt.d.ts.map +1 -0
  227. package/dist/security/encrypt.js +129 -0
  228. package/dist/security/encrypt.js.map +1 -0
  229. package/dist/security/index.d.ts +21 -0
  230. package/dist/security/index.d.ts.map +1 -0
  231. package/dist/security/index.js +11 -0
  232. package/dist/security/index.js.map +1 -0
  233. package/dist/security/rate-limit.d.ts +57 -0
  234. package/dist/security/rate-limit.d.ts.map +1 -0
  235. package/dist/security/rate-limit.js +222 -0
  236. package/dist/security/rate-limit.js.map +1 -0
  237. package/dist/security/rbac.d.ts +84 -0
  238. package/dist/security/rbac.d.ts.map +1 -0
  239. package/dist/security/rbac.js +164 -0
  240. package/dist/security/rbac.js.map +1 -0
  241. package/dist/security/sanitize.d.ts +44 -0
  242. package/dist/security/sanitize.d.ts.map +1 -0
  243. package/dist/security/sanitize.js +230 -0
  244. package/dist/security/sanitize.js.map +1 -0
  245. package/dist/security/secure-store.d.ts +44 -0
  246. package/dist/security/secure-store.d.ts.map +1 -0
  247. package/dist/security/secure-store.js +164 -0
  248. package/dist/security/secure-store.js.map +1 -0
  249. package/dist/security/session.d.ts +76 -0
  250. package/dist/security/session.d.ts.map +1 -0
  251. package/dist/security/session.js +251 -0
  252. package/dist/security/session.js.map +1 -0
  253. package/dist/security/sri.d.ts +66 -0
  254. package/dist/security/sri.d.ts.map +1 -0
  255. package/dist/security/sri.js +159 -0
  256. package/dist/security/sri.js.map +1 -0
  257. package/dist/shortcuts/index.d.ts +3 -0
  258. package/dist/shortcuts/index.d.ts.map +1 -0
  259. package/dist/shortcuts/index.js +2 -0
  260. package/dist/shortcuts/index.js.map +1 -0
  261. package/dist/shortcuts/shortcuts.d.ts +43 -0
  262. package/dist/shortcuts/shortcuts.d.ts.map +1 -0
  263. package/dist/shortcuts/shortcuts.js +141 -0
  264. package/dist/shortcuts/shortcuts.js.map +1 -0
  265. package/dist/ssr/index.d.ts +3 -0
  266. package/dist/ssr/index.d.ts.map +1 -0
  267. package/dist/ssr/index.js +2 -0
  268. package/dist/ssr/index.js.map +1 -0
  269. package/dist/ssr/ssr.d.ts +62 -0
  270. package/dist/ssr/ssr.d.ts.map +1 -0
  271. package/dist/ssr/ssr.js +132 -0
  272. package/dist/ssr/ssr.js.map +1 -0
  273. package/dist/state/index.d.ts +5 -0
  274. package/dist/state/index.d.ts.map +1 -0
  275. package/dist/state/index.js +3 -0
  276. package/dist/state/index.js.map +1 -0
  277. package/dist/state/persistent.d.ts +31 -0
  278. package/dist/state/persistent.d.ts.map +1 -0
  279. package/dist/state/persistent.js +132 -0
  280. package/dist/state/persistent.js.map +1 -0
  281. package/dist/state/store.d.ts +31 -0
  282. package/dist/state/store.d.ts.map +1 -0
  283. package/dist/state/store.js +107 -0
  284. package/dist/state/store.js.map +1 -0
  285. package/dist/store/index.d.ts +3 -0
  286. package/dist/store/index.d.ts.map +1 -0
  287. package/dist/store/index.js +2 -0
  288. package/dist/store/index.js.map +1 -0
  289. package/dist/store/store.d.ts +36 -0
  290. package/dist/store/store.d.ts.map +1 -0
  291. package/dist/store/store.js +175 -0
  292. package/dist/store/store.js.map +1 -0
  293. package/dist/supabase/auth.d.ts +28 -0
  294. package/dist/supabase/auth.d.ts.map +1 -0
  295. package/dist/supabase/auth.js +47 -0
  296. package/dist/supabase/auth.js.map +1 -0
  297. package/dist/supabase/client.d.ts +18 -0
  298. package/dist/supabase/client.d.ts.map +1 -0
  299. package/dist/supabase/client.js +36 -0
  300. package/dist/supabase/client.js.map +1 -0
  301. package/dist/supabase/realtime.d.ts +22 -0
  302. package/dist/supabase/realtime.d.ts.map +1 -0
  303. package/dist/supabase/realtime.js +51 -0
  304. package/dist/supabase/realtime.js.map +1 -0
  305. package/dist/sw/index.d.ts +3 -0
  306. package/dist/sw/index.d.ts.map +1 -0
  307. package/dist/sw/index.js +2 -0
  308. package/dist/sw/index.js.map +1 -0
  309. package/dist/sw/sw.d.ts +49 -0
  310. package/dist/sw/sw.d.ts.map +1 -0
  311. package/dist/sw/sw.js +125 -0
  312. package/dist/sw/sw.js.map +1 -0
  313. package/dist/tabs/index.d.ts +3 -0
  314. package/dist/tabs/index.d.ts.map +1 -0
  315. package/dist/tabs/index.js +2 -0
  316. package/dist/tabs/index.js.map +1 -0
  317. package/dist/tabs/tabs.d.ts +34 -0
  318. package/dist/tabs/tabs.d.ts.map +1 -0
  319. package/dist/tabs/tabs.js +173 -0
  320. package/dist/tabs/tabs.js.map +1 -0
  321. package/dist/test/index.d.ts +3 -0
  322. package/dist/test/index.d.ts.map +1 -0
  323. package/dist/test/index.js +2 -0
  324. package/dist/test/index.js.map +1 -0
  325. package/dist/test/test.d.ts +37 -0
  326. package/dist/test/test.d.ts.map +1 -0
  327. package/dist/test/test.js +108 -0
  328. package/dist/test/test.js.map +1 -0
  329. package/dist/theme/index.d.ts +3 -0
  330. package/dist/theme/index.d.ts.map +1 -0
  331. package/dist/theme/index.js +2 -0
  332. package/dist/theme/index.js.map +1 -0
  333. package/dist/theme/theme.d.ts +40 -0
  334. package/dist/theme/theme.d.ts.map +1 -0
  335. package/dist/theme/theme.js +142 -0
  336. package/dist/theme/theme.js.map +1 -0
  337. package/dist/timeline/index.d.ts +3 -0
  338. package/dist/timeline/index.d.ts.map +1 -0
  339. package/dist/timeline/index.js +2 -0
  340. package/dist/timeline/index.js.map +1 -0
  341. package/dist/timeline/timeline.d.ts +44 -0
  342. package/dist/timeline/timeline.d.ts.map +1 -0
  343. package/dist/timeline/timeline.js +196 -0
  344. package/dist/timeline/timeline.js.map +1 -0
  345. package/dist/toast/index.d.ts +3 -0
  346. package/dist/toast/index.d.ts.map +1 -0
  347. package/dist/toast/index.js +2 -0
  348. package/dist/toast/index.js.map +1 -0
  349. package/dist/toast/toast.d.ts +31 -0
  350. package/dist/toast/toast.d.ts.map +1 -0
  351. package/dist/toast/toast.js +198 -0
  352. package/dist/toast/toast.js.map +1 -0
  353. package/dist/tooltip/index.d.ts +3 -0
  354. package/dist/tooltip/index.d.ts.map +1 -0
  355. package/dist/tooltip/index.js +2 -0
  356. package/dist/tooltip/index.js.map +1 -0
  357. package/dist/tooltip/tooltip.d.ts +27 -0
  358. package/dist/tooltip/tooltip.d.ts.map +1 -0
  359. package/dist/tooltip/tooltip.js +229 -0
  360. package/dist/tooltip/tooltip.js.map +1 -0
  361. package/dist/transition/index.d.ts +3 -0
  362. package/dist/transition/index.d.ts.map +1 -0
  363. package/dist/transition/index.js +2 -0
  364. package/dist/transition/index.js.map +1 -0
  365. package/dist/transition/transition.d.ts +31 -0
  366. package/dist/transition/transition.d.ts.map +1 -0
  367. package/dist/transition/transition.js +95 -0
  368. package/dist/transition/transition.js.map +1 -0
  369. package/dist/webgl/index.d.ts +3 -0
  370. package/dist/webgl/index.d.ts.map +1 -0
  371. package/dist/webgl/index.js +2 -0
  372. package/dist/webgl/index.js.map +1 -0
  373. package/dist/webgl/webgl.d.ts +49 -0
  374. package/dist/webgl/webgl.d.ts.map +1 -0
  375. package/dist/webgl/webgl.js +401 -0
  376. package/dist/webgl/webgl.js.map +1 -0
  377. package/package.json +269 -0
  378. package/styles/base/global.css +47 -0
  379. package/styles/base/reset.css +73 -0
  380. package/styles/tokens/colors.css +50 -0
  381. package/styles/tokens/spacing.css +46 -0
  382. package/styles/tokens/typography.css +37 -0
  383. package/styles/utilities/layout.css +46 -0
@@ -0,0 +1,314 @@
1
+ /**
2
+ * Nova Engine — Dropdown
3
+ *
4
+ * Positioned dropdown panels with hover bridge, keyboard navigation,
5
+ * viewport-aware flip/shift, and smooth show/hide transitions.
6
+ */
7
+ /* ---- Injected styles ---- */
8
+ const STYLE_ID = 'nova-dropdown-styles';
9
+ function injectStyles() {
10
+ if (document.getElementById(STYLE_ID))
11
+ return;
12
+ const s = document.createElement('style');
13
+ s.id = STYLE_ID;
14
+ s.textContent = `
15
+ .nova-dropdown {
16
+ position: absolute;
17
+ z-index: 99997;
18
+ opacity: 0;
19
+ transform: translateY(-4px);
20
+ transition: opacity 150ms ease-out, transform 150ms ease-out;
21
+ pointer-events: none;
22
+ }
23
+ .nova-dropdown--visible {
24
+ opacity: 1;
25
+ transform: translateY(0);
26
+ pointer-events: auto;
27
+ }
28
+ .nova-dropdown__bridge {
29
+ position: absolute;
30
+ pointer-events: auto;
31
+ }
32
+ @media (prefers-reduced-motion: reduce) {
33
+ .nova-dropdown { transition: none; }
34
+ }`;
35
+ document.head.appendChild(s);
36
+ }
37
+ function parsePlacement(p) {
38
+ const parts = p.split('-');
39
+ return [parts[0], parts[1] ?? 'center'];
40
+ }
41
+ function oppositeSide(s) {
42
+ const map = { top: 'bottom', bottom: 'top', left: 'right', right: 'left' };
43
+ return map[s];
44
+ }
45
+ function computePosition(anchor, panel, side, align, offset) {
46
+ let x = 0, y = 0;
47
+ const sx = window.scrollX, sy = window.scrollY;
48
+ if (side === 'top') {
49
+ x = anchor.left + sx + anchor.width / 2 - panel.width / 2;
50
+ y = anchor.top + sy - panel.height - offset;
51
+ }
52
+ else if (side === 'bottom') {
53
+ x = anchor.left + sx + anchor.width / 2 - panel.width / 2;
54
+ y = anchor.bottom + sy + offset;
55
+ }
56
+ else if (side === 'left') {
57
+ x = anchor.left + sx - panel.width - offset;
58
+ y = anchor.top + sy + anchor.height / 2 - panel.height / 2;
59
+ }
60
+ else {
61
+ x = anchor.right + sx + offset;
62
+ y = anchor.top + sy + anchor.height / 2 - panel.height / 2;
63
+ }
64
+ if ((side === 'top' || side === 'bottom') && align === 'start')
65
+ x = anchor.left + sx;
66
+ if ((side === 'top' || side === 'bottom') && align === 'end')
67
+ x = anchor.right + sx - panel.width;
68
+ if ((side === 'left' || side === 'right') && align === 'start')
69
+ y = anchor.top + sy;
70
+ if ((side === 'left' || side === 'right') && align === 'end')
71
+ y = anchor.bottom + sy - panel.height;
72
+ return { x, y };
73
+ }
74
+ function shouldFlip(pos, panel, side) {
75
+ const vw = window.innerWidth, vh = window.innerHeight;
76
+ const sx = window.scrollX, sy = window.scrollY;
77
+ if (side === 'top')
78
+ return pos.y - sy < 0;
79
+ if (side === 'bottom')
80
+ return pos.y - sy + panel.height > vh;
81
+ if (side === 'left')
82
+ return pos.x - sx < 0;
83
+ return pos.x - sx + panel.width > vw;
84
+ }
85
+ function shiftIntoView(pos, panel) {
86
+ const sx = window.scrollX, sy = window.scrollY;
87
+ const vw = window.innerWidth, vh = window.innerHeight;
88
+ let { x, y } = pos;
89
+ if (x - sx < 4)
90
+ x = sx + 4;
91
+ if (x - sx + panel.width > vw - 4)
92
+ x = sx + vw - panel.width - 4;
93
+ if (y - sy < 4)
94
+ y = sy + 4;
95
+ if (y - sy + panel.height > vh - 4)
96
+ y = sy + vh - panel.height - 4;
97
+ return { x, y };
98
+ }
99
+ /* ---- Focusable helpers ---- */
100
+ const FOCUSABLE = 'a[href],button:not([disabled]),input:not([disabled]),textarea:not([disabled]),select:not([disabled]),[tabindex]:not([tabindex="-1"])';
101
+ function getFocusables(el) {
102
+ return Array.from(el.querySelectorAll(FOCUSABLE));
103
+ }
104
+ /* ---- Factory ---- */
105
+ /** Attach a dropdown panel to a trigger element. */
106
+ export function dropdown(trigger, options) {
107
+ const { content, placement = 'bottom-start', offset = 8, delay = 120, hideDelay = 200, trigger: mode = 'hover', flip = true, shift = true, matchWidth = false, class: extraClass, onShow, onHide, } = options;
108
+ injectStyles();
109
+ // Panel wrapper
110
+ const panel = document.createElement('div');
111
+ panel.className = 'nova-dropdown' + (extraClass ? ` ${extraClass}` : '');
112
+ panel.setAttribute('role', 'menu');
113
+ panel.appendChild(content);
114
+ // Bridge element — invisible hover area between trigger and panel
115
+ const bridge = document.createElement('div');
116
+ bridge.className = 'nova-dropdown__bridge';
117
+ panel.appendChild(bridge);
118
+ let showTimer;
119
+ let hideTimer;
120
+ let isVisible = false;
121
+ let destroyed = false;
122
+ let rafId = null;
123
+ // Listener bookkeeping
124
+ const listeners = [];
125
+ function on(target, evt, fn) {
126
+ target.addEventListener(evt, fn);
127
+ listeners.push([target, evt, fn]);
128
+ }
129
+ function position() {
130
+ const anchorRect = trigger.getBoundingClientRect();
131
+ const panelRect = panel.getBoundingClientRect();
132
+ let [side, align] = parsePlacement(placement);
133
+ if (matchWidth) {
134
+ panel.style.width = `${anchorRect.width}px`;
135
+ }
136
+ let pos = computePosition(anchorRect, panelRect, side, align, offset);
137
+ if (flip && shouldFlip(pos, panelRect, side)) {
138
+ side = oppositeSide(side);
139
+ pos = computePosition(anchorRect, panelRect, side, align, offset);
140
+ }
141
+ if (shift)
142
+ pos = shiftIntoView(pos, panelRect);
143
+ panel.style.left = `${pos.x}px`;
144
+ panel.style.top = `${pos.y}px`;
145
+ // Position the bridge between trigger and panel
146
+ positionBridge(side, anchorRect, offset);
147
+ }
148
+ function positionBridge(side, anchorRect, gap) {
149
+ // Reset
150
+ bridge.style.top = '';
151
+ bridge.style.bottom = '';
152
+ bridge.style.left = '';
153
+ bridge.style.right = '';
154
+ bridge.style.width = '';
155
+ bridge.style.height = '';
156
+ if (side === 'bottom') {
157
+ bridge.style.bottom = '100%';
158
+ bridge.style.left = '0';
159
+ bridge.style.width = `${Math.max(anchorRect.width, panel.offsetWidth)}px`;
160
+ bridge.style.height = `${gap}px`;
161
+ }
162
+ else if (side === 'top') {
163
+ bridge.style.top = '100%';
164
+ bridge.style.left = '0';
165
+ bridge.style.width = `${Math.max(anchorRect.width, panel.offsetWidth)}px`;
166
+ bridge.style.height = `${gap}px`;
167
+ }
168
+ else if (side === 'right') {
169
+ bridge.style.right = '100%';
170
+ bridge.style.top = '0';
171
+ bridge.style.width = `${gap}px`;
172
+ bridge.style.height = '100%';
173
+ }
174
+ else {
175
+ bridge.style.left = '100%';
176
+ bridge.style.top = '0';
177
+ bridge.style.width = `${gap}px`;
178
+ bridge.style.height = '100%';
179
+ }
180
+ }
181
+ function show() {
182
+ if (isVisible || destroyed)
183
+ return;
184
+ clearTimeout(hideTimer);
185
+ onShow?.();
186
+ document.body.appendChild(panel);
187
+ // Force layout before adding visible class
188
+ requestAnimationFrame(() => {
189
+ position();
190
+ panel.classList.add('nova-dropdown--visible');
191
+ });
192
+ isVisible = true;
193
+ }
194
+ function hide() {
195
+ if (!isVisible || destroyed)
196
+ return;
197
+ panel.classList.remove('nova-dropdown--visible');
198
+ const remove = () => {
199
+ if (panel.parentNode)
200
+ panel.remove();
201
+ };
202
+ panel.addEventListener('transitionend', remove, { once: true });
203
+ // Fallback in case transitionend doesn't fire
204
+ setTimeout(remove, 200);
205
+ isVisible = false;
206
+ onHide?.();
207
+ }
208
+ function scheduleShow() {
209
+ clearTimeout(hideTimer);
210
+ showTimer = setTimeout(show, delay);
211
+ }
212
+ function scheduleHide() {
213
+ clearTimeout(showTimer);
214
+ hideTimer = setTimeout(hide, hideDelay);
215
+ }
216
+ // --- Keyboard handler ---
217
+ function onKeyDown(e) {
218
+ if (!isVisible)
219
+ return;
220
+ if (e.key === 'Escape') {
221
+ e.preventDefault();
222
+ hide();
223
+ trigger.focus();
224
+ return;
225
+ }
226
+ const focusables = getFocusables(panel);
227
+ if (focusables.length === 0)
228
+ return;
229
+ const idx = focusables.indexOf(document.activeElement);
230
+ if (e.key === 'ArrowDown') {
231
+ e.preventDefault();
232
+ const next = idx < focusables.length - 1 ? idx + 1 : 0;
233
+ focusables[next].focus();
234
+ }
235
+ else if (e.key === 'ArrowUp') {
236
+ e.preventDefault();
237
+ const prev = idx > 0 ? idx - 1 : focusables.length - 1;
238
+ focusables[prev].focus();
239
+ }
240
+ else if (e.key === 'Tab') {
241
+ // Let natural tab behavior happen, but hide if focus leaves panel
242
+ requestAnimationFrame(() => {
243
+ if (!panel.contains(document.activeElement) && document.activeElement !== trigger) {
244
+ hide();
245
+ }
246
+ });
247
+ }
248
+ }
249
+ // --- Scroll/resize repositioning ---
250
+ function onScrollResize() {
251
+ if (!isVisible)
252
+ return;
253
+ if (rafId !== null)
254
+ return;
255
+ rafId = requestAnimationFrame(() => {
256
+ rafId = null;
257
+ if (isVisible)
258
+ position();
259
+ });
260
+ }
261
+ // --- Bind trigger events ---
262
+ if (mode === 'hover') {
263
+ on(trigger, 'mouseenter', scheduleShow);
264
+ on(trigger, 'mouseleave', scheduleHide);
265
+ on(panel, 'mouseenter', () => { clearTimeout(hideTimer); });
266
+ on(panel, 'mouseleave', scheduleHide);
267
+ // Also support focus for accessibility
268
+ on(trigger, 'focus', () => show());
269
+ on(trigger, 'blur', () => {
270
+ requestAnimationFrame(() => {
271
+ if (!panel.contains(document.activeElement))
272
+ hide();
273
+ });
274
+ });
275
+ }
276
+ else if (mode === 'click') {
277
+ on(trigger, 'click', (e) => {
278
+ e.stopPropagation();
279
+ if (isVisible)
280
+ hide();
281
+ else
282
+ show();
283
+ });
284
+ on(document, 'click', (e) => {
285
+ if (isVisible && !panel.contains(e.target) && !trigger.contains(e.target)) {
286
+ hide();
287
+ }
288
+ });
289
+ }
290
+ on(document, 'keydown', onKeyDown);
291
+ on(window, 'scroll', onScrollResize);
292
+ on(window, 'resize', onScrollResize);
293
+ const instance = {
294
+ show,
295
+ hide,
296
+ update: position,
297
+ get visible() { return isVisible; },
298
+ destroy() {
299
+ if (destroyed)
300
+ return;
301
+ destroyed = true;
302
+ clearTimeout(showTimer);
303
+ clearTimeout(hideTimer);
304
+ if (rafId !== null)
305
+ cancelAnimationFrame(rafId);
306
+ if (panel.parentNode)
307
+ panel.remove();
308
+ for (const [t, e, fn] of listeners)
309
+ t.removeEventListener(e, fn);
310
+ },
311
+ };
312
+ return instance;
313
+ }
314
+ //# sourceMappingURL=dropdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dropdown.js","sourceRoot":"","sources":["../../src/dropdown/dropdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Nova Engine — Dropdown Group
3
+ *
4
+ * Coordinates multiple dropdown triggers (e.g. nav bar items)
5
+ * so that moving between them cross-fades content smoothly
6
+ * without close/reopen flicker — matching Linear's behavior.
7
+ */
8
+ import type { DropdownGroupOptions } from './dropdown';
9
+ export interface DropdownGroupInstance {
10
+ /** Destroy all dropdowns and listeners */
11
+ destroy(): void;
12
+ }
13
+ /**
14
+ * Group multiple dropdown triggers so switching between them
15
+ * cross-fades panels smoothly with no close/reopen gap.
16
+ */
17
+ export declare function dropdownGroup(options: DropdownGroupOptions): DropdownGroupInstance;
18
+ //# sourceMappingURL=group.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group.d.ts","sourceRoot":"","sources":["../../src/dropdown/group.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAoB,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,WAAW,qBAAqB;IACpC,0CAA0C;IAC1C,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,qBAAqB,CA2HlF"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Nova Engine — Dropdown Group
3
+ *
4
+ * Coordinates multiple dropdown triggers (e.g. nav bar items)
5
+ * so that moving between them cross-fades content smoothly
6
+ * without close/reopen flicker — matching Linear's behavior.
7
+ */
8
+ import { dropdown } from './dropdown';
9
+ /**
10
+ * Group multiple dropdown triggers so switching between them
11
+ * cross-fades panels smoothly with no close/reopen gap.
12
+ */
13
+ export function dropdownGroup(options) {
14
+ const { items, placement = 'bottom-start', offset = 8, delay = 100, hideDelay = 250, class: extraClass, } = options;
15
+ let activeIndex = -1;
16
+ let groupHideTimer;
17
+ let destroyed = false;
18
+ const instances = [];
19
+ const listeners = [];
20
+ function on(target, evt, fn) {
21
+ target.addEventListener(evt, fn);
22
+ listeners.push([target, evt, fn]);
23
+ }
24
+ function showItem(index) {
25
+ if (destroyed || index === activeIndex)
26
+ return;
27
+ clearTimeout(groupHideTimer);
28
+ // Hide previous
29
+ if (activeIndex >= 0 && activeIndex < instances.length) {
30
+ instances[activeIndex].hide();
31
+ }
32
+ activeIndex = index;
33
+ instances[index].show();
34
+ }
35
+ function scheduleHideAll() {
36
+ clearTimeout(groupHideTimer);
37
+ groupHideTimer = setTimeout(() => {
38
+ if (activeIndex >= 0 && activeIndex < instances.length) {
39
+ instances[activeIndex].hide();
40
+ }
41
+ activeIndex = -1;
42
+ }, hideDelay);
43
+ }
44
+ function cancelHide() {
45
+ clearTimeout(groupHideTimer);
46
+ }
47
+ // Create a dropdown instance for each item, using manual trigger mode
48
+ // so we can coordinate show/hide ourselves
49
+ for (let i = 0; i < items.length; i++) {
50
+ const { trigger, content } = items[i];
51
+ const inst = dropdown(trigger, {
52
+ content,
53
+ placement,
54
+ offset,
55
+ delay: 0, // No individual delay — group controls timing
56
+ hideDelay: 0, // No individual hide delay
57
+ trigger: 'manual', // We handle show/hide coordination
58
+ class: extraClass,
59
+ });
60
+ instances.push(inst);
61
+ // Trigger hover listeners
62
+ let showTimer;
63
+ on(trigger, 'mouseenter', () => {
64
+ cancelHide();
65
+ // If another panel is already open, switch immediately (no delay)
66
+ if (activeIndex >= 0 && activeIndex !== i) {
67
+ showItem(i);
68
+ }
69
+ else {
70
+ clearTimeout(showTimer);
71
+ showTimer = setTimeout(() => showItem(i), delay);
72
+ }
73
+ });
74
+ on(trigger, 'mouseleave', () => {
75
+ clearTimeout(showTimer);
76
+ scheduleHideAll();
77
+ });
78
+ // Keep panel open when hovering over its content
79
+ // We listen on the content element directly since it's inside the panel wrapper
80
+ on(content, 'mouseenter', () => {
81
+ cancelHide();
82
+ });
83
+ on(content, 'mouseleave', () => {
84
+ scheduleHideAll();
85
+ });
86
+ // Keyboard: allow trigger focus to open
87
+ on(trigger, 'focus', () => {
88
+ cancelHide();
89
+ showItem(i);
90
+ });
91
+ on(trigger, 'blur', () => {
92
+ // Check after a tick if focus moved to the panel content or another trigger
93
+ requestAnimationFrame(() => {
94
+ const active = document.activeElement;
95
+ if (!active) {
96
+ scheduleHideAll();
97
+ return;
98
+ }
99
+ // Check if focus went to another trigger in the group
100
+ const inGroup = items.some((item) => item.trigger.contains(active) || item.content.contains(active));
101
+ if (!inGroup)
102
+ scheduleHideAll();
103
+ });
104
+ });
105
+ }
106
+ return {
107
+ destroy() {
108
+ if (destroyed)
109
+ return;
110
+ destroyed = true;
111
+ clearTimeout(groupHideTimer);
112
+ for (const inst of instances)
113
+ inst.destroy();
114
+ for (const [t, e, fn] of listeners)
115
+ t.removeEventListener(e, fn);
116
+ },
117
+ };
118
+ }
119
+ //# sourceMappingURL=group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group.js","sourceRoot":"","sources":["../../src/dropdown/group.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { dropdown } from './dropdown';
2
+ export { dropdownGroup } from './group';
3
+ export type { DropdownOptions, DropdownInstance, DropdownGroupOptions, Placement } from './dropdown';
4
+ export type { DropdownGroupInstance } from './group';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dropdown/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACrG,YAAY,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { dropdown } from './dropdown';
2
+ export { dropdownGroup } from './group';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dropdown/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Nova Engine — Form Engine
3
+ *
4
+ * Schema-driven forms with validation, multi-step support,
5
+ * dirty/touched tracking, and async submission.
6
+ */
7
+ import type { Validator, AsyncValidator } from './validators';
8
+ export interface FieldSchema {
9
+ type?: 'text' | 'email' | 'password' | 'number' | 'textarea' | 'select' | 'checkbox';
10
+ label?: string;
11
+ placeholder?: string;
12
+ required?: boolean;
13
+ defaultValue?: unknown;
14
+ validators?: Validator[];
15
+ asyncValidators?: AsyncValidator[];
16
+ options?: {
17
+ label: string;
18
+ value: string;
19
+ }[];
20
+ }
21
+ export interface StepSchema {
22
+ title?: string;
23
+ fields: Record<string, FieldSchema>;
24
+ }
25
+ export interface FormSchema {
26
+ steps: StepSchema[];
27
+ onSubmit: (data: Record<string, unknown>) => Promise<void>;
28
+ }
29
+ export interface FieldState {
30
+ value: unknown;
31
+ error: string | null;
32
+ touched: boolean;
33
+ dirty: boolean;
34
+ validating: boolean;
35
+ }
36
+ export interface FormState {
37
+ fields: Record<string, FieldState>;
38
+ currentStep: number;
39
+ totalSteps: number;
40
+ submitting: boolean;
41
+ submitError: string | null;
42
+ valid: boolean;
43
+ }
44
+ type FormListener = (state: FormState) => void;
45
+ export declare class NovaForm {
46
+ private schema;
47
+ private fieldStates;
48
+ private currentStep;
49
+ private submitting;
50
+ private submitError;
51
+ private listeners;
52
+ constructor(schema: FormSchema);
53
+ /** Initialize field states from schema */
54
+ private initFields;
55
+ /** Get current form state snapshot */
56
+ get state(): FormState;
57
+ /** Get the current step schema */
58
+ get step(): StepSchema;
59
+ /** Update a field value */
60
+ setValue(name: string, value: unknown): void;
61
+ /** Mark a field as touched (blurred) */
62
+ touch(name: string): void;
63
+ /** Validate a single field */
64
+ validateField(name: string): string | null;
65
+ /** Validate all fields in the current step */
66
+ validateStep(): boolean;
67
+ /** Validate all fields across all steps */
68
+ validateAll(): boolean;
69
+ /** Check if form is valid (no errors) */
70
+ isValid(): boolean;
71
+ /** Go to next step (validates current step first) */
72
+ nextStep(): boolean;
73
+ /** Go to previous step */
74
+ prevStep(): boolean;
75
+ /** Go to specific step */
76
+ goToStep(index: number): void;
77
+ /** Submit the form */
78
+ submit(): Promise<boolean>;
79
+ /** Get all form data */
80
+ getData(): Record<string, unknown>;
81
+ /** Reset form to initial state */
82
+ reset(): void;
83
+ /** Subscribe to state changes */
84
+ subscribe(listener: FormListener): () => void;
85
+ private notify;
86
+ private getFieldSchema;
87
+ }
88
+ /** Create a form instance from a schema */
89
+ export declare function createForm(schema: FormSchema): NovaForm;
90
+ export {};
91
+ //# sourceMappingURL=form-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-engine.d.ts","sourceRoot":"","sources":["../../src/forms/form-engine.ts"],"names":[],"mappings":"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"}