u2ui 1.0.0 → 1.4.5

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 (591) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +36 -36
  3. package/attr/behavior/README.md +6 -4
  4. package/attr/behavior/behavior.js +265 -261
  5. package/attr/behavior/manifest.json +42 -42
  6. package/attr/confirm/README.md +8 -8
  7. package/attr/confirm/confirm.js +86 -90
  8. package/attr/confirm/manifest.json +42 -42
  9. package/attr/disableif/README.md +37 -0
  10. package/attr/disableif/disableif.js +59 -0
  11. package/attr/disableif/manifest.json +38 -0
  12. package/attr/draghandle/README.md +15 -15
  13. package/attr/draghandle/draghandle.js +24 -42
  14. package/attr/draghandle/manifest.json +30 -0
  15. package/attr/dropzone/README.md +32 -0
  16. package/attr/dropzone/dropzone.js +485 -0
  17. package/attr/dropzone/manifest.json +36 -0
  18. package/attr/focusgroup/README.md +9 -9
  19. package/attr/focusgroup/focusgroup.js +97 -100
  20. package/attr/focusgroup/manifest.json +30 -38
  21. package/attr/href/README.md +5 -5
  22. package/attr/href/href.js +50 -42
  23. package/attr/href/manifest.json +42 -42
  24. package/attr/intersect/README.md +15 -15
  25. package/attr/intersect/intersect.js +98 -98
  26. package/attr/intersect/manifest.json +44 -57
  27. package/attr/lightbox/README.md +27 -0
  28. package/attr/lightbox/lightbox.js +120 -0
  29. package/attr/lightbox/manifest.json +29 -0
  30. package/attr/movable/README.md +27 -0
  31. package/attr/movable/manifest.json +47 -0
  32. package/attr/movable/movable.js +111 -0
  33. package/attr/navigable/README.md +9 -9
  34. package/attr/navigable/TargetObserver.js +90 -91
  35. package/attr/navigable/U2TargetObserver.js +75 -75
  36. package/attr/navigable/manifest.json +34 -42
  37. package/attr/navigable/navigable.js +85 -87
  38. package/attr/parallax/README.md +10 -10
  39. package/attr/parallax/manifest.json +36 -0
  40. package/attr/parallax/parallax.js +119 -119
  41. package/attr/scrollspy/README.md +43 -0
  42. package/attr/scrollspy/manifest.json +28 -0
  43. package/attr/scrollspy/scrollspy.js +85 -0
  44. package/attr/selectable/README.md +42 -0
  45. package/attr/selectable/SelectionManager.js +171 -0
  46. package/attr/selectable/manifest.json +33 -0
  47. package/attr/selectable/selectable.js +28 -0
  48. package/attr/skin/README.md +15 -16
  49. package/attr/skin/manifest.json +40 -0
  50. package/attr/skin/skin.css +49 -50
  51. package/attr/store/README.md +41 -0
  52. package/attr/store/manifest.json +28 -0
  53. package/attr/store/store.js +62 -0
  54. package/class/badge/README.md +2 -2
  55. package/class/badge/badge.css +34 -34
  56. package/class/card/README.md +51 -0
  57. package/class/card/card.css +31 -0
  58. package/class/flex/README.md +16 -16
  59. package/class/flex/flex.css +15 -25
  60. package/class/grid/README.md +18 -18
  61. package/class/grid/grid.css +38 -40
  62. package/class/reset/README.md +6 -6
  63. package/class/reset/reset.css +8 -8
  64. package/class/table/README.md +22 -21
  65. package/class/table/table.css +125 -125
  66. package/class/unstyle/README.md +7 -5
  67. package/class/unstyle/unstyle.css +14 -12
  68. package/class/width/README.md +18 -18
  69. package/class/width/width.css +21 -22
  70. package/css/README.md +11 -0
  71. package/css/base/README.md +8 -2
  72. package/css/base/base.css +153 -127
  73. package/css/base/beta.css +34 -50
  74. package/css/base/full.css +5 -5
  75. package/css/base/nomotion.css +8 -8
  76. package/css/base/print.css +36 -36
  77. package/css/classless/README.md +10 -4
  78. package/css/classless/aria.css +51 -64
  79. package/css/classless/classless.css +118 -124
  80. package/css/classless/full.css +11 -11
  81. package/css/classless/more.css +314 -340
  82. package/css/classless/simple.css +314 -103
  83. package/css/classless/snippeds/a/icons.css +66 -12
  84. package/css/classless/snippeds/a/tests.html +118 -0
  85. package/css/classless/snippeds/blockquote/big-quotes.css +36 -0
  86. package/css/classless/snippeds/blockquote/tests.html +62 -0
  87. package/css/classless/snippeds/button/square.css +22 -0
  88. package/css/classless/snippeds/button/tests.html +53 -0
  89. package/css/classless/snippeds/experiments/aria-header-nav-dropdown.css +46 -0
  90. package/css/classless/snippeds/hr/gradient.css +2 -2
  91. package/css/classless/snippeds/hr/section_sign.css +16 -16
  92. package/css/classless/snippeds/hr/tests.html +49 -49
  93. package/css/classless/snippeds/p/indent.css +9 -0
  94. package/css/classless/snippeds/p/initial.css +9 -0
  95. package/css/classless/snippeds/p/tests.html +60 -0
  96. package/css/classless/variables.css +132 -99
  97. package/css/norm/README.md +7 -1
  98. package/css/norm/beta.css +41 -39
  99. package/css/norm/norm.css +89 -98
  100. package/css/norm/oldies.css +71 -60
  101. package/css/{classes → utils}/README.md +10 -4
  102. package/css/{classes/classes.css → utils/utils.css} +78 -78
  103. package/el/accordion/README.md +60 -59
  104. package/el/accordion/accordion.css +11 -7
  105. package/el/accordion/accordion.js +211 -258
  106. package/el/accordion/manifest.json +44 -57
  107. package/el/alert/README.md +86 -67
  108. package/el/alert/alert.css +72 -73
  109. package/el/alert/alert.js +206 -187
  110. package/el/alert/manifest.json +59 -77
  111. package/el/breadcrumb/README.md +41 -0
  112. package/el/breadcrumb/breadcrumb.css +22 -0
  113. package/el/breadcrumb/breadcrumb.js +119 -0
  114. package/el/breadcrumb/manifest.json +42 -0
  115. package/el/buttongroup/README.md +36 -36
  116. package/el/buttongroup/buttongroup.css +38 -30
  117. package/el/buttongroup/buttongroup.js +68 -56
  118. package/el/buttongroup/manifest.json +28 -0
  119. package/el/bytes/README.md +4 -4
  120. package/el/bytes/bytes.css +6 -6
  121. package/el/bytes/bytes.js +98 -97
  122. package/el/bytes/manifest.json +90 -95
  123. package/el/calendar/README.md +64 -0
  124. package/el/calendar/calendar.css +36 -0
  125. package/el/calendar/calendar.js +391 -0
  126. package/el/calendar/ext/drag.js +69 -0
  127. package/el/calendar/ext/keyNavigation.js +101 -0
  128. package/el/calendar/manifest.json +69 -0
  129. package/el/carousel/README.md +14 -14
  130. package/el/carousel/carousel.css +45 -46
  131. package/el/carousel/carousel.js +398 -371
  132. package/el/carousel/manifest.json +44 -58
  133. package/el/carousel-nav/README.md +13 -14
  134. package/el/carousel-nav/carousel-nav.js +74 -74
  135. package/el/carousel-nav/manifest.json +31 -0
  136. package/el/chart/README.md +46 -0
  137. package/el/chart/chart.css +7 -0
  138. package/el/chart/chart.js +188 -0
  139. package/el/chart/engines/apexcharts.js +103 -0
  140. package/el/chart/engines/billboard.js +79 -0
  141. package/el/chart/engines/chart.js.js +32 -0
  142. package/el/chart/engines/chartist.js +74 -0
  143. package/el/chart/engines/echarts.js +65 -0
  144. package/el/chart/engines/frappe.js +49 -0
  145. package/el/chart/engines/nvd3.js +139 -0
  146. package/el/chart/engines/plotly.js +73 -0
  147. package/el/chart/manifest.json +54 -0
  148. package/el/code/README.md +21 -21
  149. package/el/code/code.css +46 -46
  150. package/el/code/code.js +291 -289
  151. package/el/code/manifest.json +59 -66
  152. package/el/cookiebanner/README.md +70 -0
  153. package/el/cookiebanner/cookiebanner.css +42 -0
  154. package/el/cookiebanner/cookiebanner.js +161 -0
  155. package/el/cookiebanner/extensions/googleConsentMode.js +36 -0
  156. package/el/cookiebanner/knownItems.js +291 -0
  157. package/el/cookiebanner/manifest.json +85 -0
  158. package/el/cookiebanner/ui.js +426 -0
  159. package/el/copy/README.md +9 -7
  160. package/el/copy/copy.css +3 -3
  161. package/el/copy/copy.js +89 -117
  162. package/el/copy/manifest.json +37 -49
  163. package/el/counter/README.md +12 -9
  164. package/el/counter/counter.css +8 -8
  165. package/el/counter/counter.js +96 -95
  166. package/el/counter/manifest.json +50 -59
  167. package/el/drawer/README.md +35 -0
  168. package/el/drawer/drawer.css +77 -0
  169. package/el/drawer/drawer.js +166 -0
  170. package/el/drawer/manifest.json +27 -0
  171. package/el/fields/README.md +34 -0
  172. package/el/fields/fields.css +5 -0
  173. package/el/fields/fields.js +133 -0
  174. package/el/fields/manifest.json +32 -0
  175. package/el/ico/README.md +119 -118
  176. package/el/ico/debug.js +86 -0
  177. package/el/ico/font/Font Awesome.css +22 -22
  178. package/el/ico/font/LigatureSymbols.css +7 -7
  179. package/el/ico/font/Material Icons.css +6 -6
  180. package/el/ico/font/RemixFilled.css +8 -8
  181. package/el/ico/font/RemixOutlined.css +8 -8
  182. package/el/ico/font/old/anicons.css +31 -31
  183. package/el/ico/font/old/devicons.css +210 -210
  184. package/el/ico/font/old/material.all.css +36 -36
  185. package/el/ico/font/old/remix.css +15 -15
  186. package/el/ico/font/old/utf8.css +54 -54
  187. package/el/ico/ico.css +122 -110
  188. package/el/ico/ico.js +163 -189
  189. package/el/ico/manifest.json +68 -86
  190. package/el/input/README.md +41 -39
  191. package/el/input/input.css +95 -35
  192. package/el/input/input.js +682 -331
  193. package/el/input/manifest.json +54 -0
  194. package/el/maintitlebar/README.md +39 -0
  195. package/el/maintitlebar/maintitlebar.css +40 -0
  196. package/el/maintitlebar/maintitlebar.js +17 -0
  197. package/el/maintitlebar/manifest.json +32 -0
  198. package/el/masonry/README.md +19 -19
  199. package/el/masonry/manifest.json +49 -60
  200. package/el/masonry/masonry.css +27 -27
  201. package/el/masonry/masonry.js +93 -92
  202. package/el/menubutton/README.md +39 -0
  203. package/el/menubutton/manifest.json +44 -0
  204. package/el/{splitbutton/splitbutton.css → menubutton/menubutton.css} +51 -47
  205. package/el/menubutton/menubutton.js +90 -0
  206. package/el/number/README.md +9 -6
  207. package/el/number/manifest.json +162 -121
  208. package/el/number/number.css +6 -6
  209. package/el/number/number.js +67 -67
  210. package/el/out/README.md +5 -5
  211. package/el/out/manifest.json +26 -38
  212. package/el/out/out.css +2 -2
  213. package/el/out/out.js +42 -59
  214. package/el/pagination/README.md +32 -0
  215. package/el/pagination/manifest.json +47 -0
  216. package/el/pagination/pagination.css +27 -0
  217. package/el/pagination/pagination.js +147 -0
  218. package/el/parallax-bg/README.md +26 -6
  219. package/el/parallax-bg/manifest.json +32 -0
  220. package/el/parallax-bg/parallax-bg.css +13 -13
  221. package/el/parallax-bg/parallax-bg.js +197 -186
  222. package/el/qrcode/README.md +7 -7
  223. package/el/qrcode/manifest.json +32 -43
  224. package/el/qrcode/package.json +22 -22
  225. package/el/qrcode/qrcode.css +13 -13
  226. package/el/qrcode/qrcode.js +53 -45
  227. package/el/rating/README.md +9 -20
  228. package/el/rating/manifest.json +52 -65
  229. package/el/rating/rating.css +10 -10
  230. package/el/rating/rating.js +148 -139
  231. package/el/responsive/README.md +43 -0
  232. package/el/responsive/manifest.json +41 -0
  233. package/el/responsive/responsive.css +4 -0
  234. package/el/responsive/responsive.js +143 -0
  235. package/el/rte/README.md +10 -10
  236. package/el/rte/manifest.json +33 -0
  237. package/el/rte/rte.css +9 -9
  238. package/el/rte/rte.js +56 -56
  239. package/el/skeleton/README.md +3 -3
  240. package/el/skeleton/manifest.json +37 -51
  241. package/el/skeleton/skeleton.css +67 -60
  242. package/el/skeleton/skeleton.js +71 -72
  243. package/el/splitpanel/README.md +33 -13
  244. package/el/splitpanel/manifest.json +36 -49
  245. package/el/splitpanel/splitpanel.css +20 -17
  246. package/el/splitpanel/splitpanel.js +117 -116
  247. package/el/spot/README.md +36 -0
  248. package/el/spot/manifest.json +55 -0
  249. package/el/spot/spot.css +23 -0
  250. package/el/spot/spot.js +106 -0
  251. package/el/system/README.md +29 -0
  252. package/el/system/demoHtml.html +660 -0
  253. package/el/system/manifest.json +32 -0
  254. package/el/system/styler.js +661 -0
  255. package/el/system/system.js +84 -0
  256. package/el/table/README.md +80 -68
  257. package/el/table/ext/autoFormatTable.js +228 -0
  258. package/el/table/manifest.json +32 -43
  259. package/el/table/table.css +4 -59
  260. package/el/table/table.js +468 -194
  261. package/el/tabs/README.md +17 -17
  262. package/el/tabs/manifest.json +44 -59
  263. package/el/tabs/tabs.css +22 -22
  264. package/el/tabs/tabs.js +192 -210
  265. package/el/textfit/README.md +7 -7
  266. package/el/textfit/manifest.json +33 -45
  267. package/el/textfit/textfit.css +5 -5
  268. package/el/textfit/textfit.js +80 -80
  269. package/el/time/README.md +6 -5
  270. package/el/time/manifest.json +79 -118
  271. package/el/time/time.js +179 -168
  272. package/el/toc/README.md +27 -0
  273. package/el/toc/manifest.json +36 -0
  274. package/el/toc/toc.css +3 -0
  275. package/el/toc/toc.js +85 -0
  276. package/el/tooltip/README.md +13 -10
  277. package/el/tooltip/manifest.json +56 -69
  278. package/el/tooltip/tooltip.css +100 -97
  279. package/el/tooltip/tooltip.js +146 -82
  280. package/el/tree/README.md +133 -0
  281. package/el/tree/ext/dnd.js +53 -0
  282. package/el/tree/ext/item.js +35 -0
  283. package/el/tree/manifest.json +61 -0
  284. package/el/tree/tree.css +18 -0
  285. package/el/tree/tree.js +236 -0
  286. package/el/typewriter/README.md +11 -11
  287. package/el/typewriter/manifest.json +45 -66
  288. package/el/typewriter/typewriter.css +6 -6
  289. package/el/typewriter/typewriter.js +161 -166
  290. package/el/video/README.md +37 -0
  291. package/el/video/manifest.json +96 -0
  292. package/el/video/video.js +550 -0
  293. package/js/Placer/Placer.js +156 -156
  294. package/js/Placer/README.md +14 -16
  295. package/js/PointerObserver/PointerObserver-no-scroll.js +146 -0
  296. package/js/PointerObserver/PointerObserver.js +161 -130
  297. package/js/PointerObserver/README.md +6 -7
  298. package/js/SelectorObserver/README.md +9 -9
  299. package/js/SelectorObserver/SelectorObserver.js +199 -200
  300. package/js/Tour/README.md +56 -0
  301. package/js/Tour/Tour.js +156 -0
  302. package/js/contextmenu/README.md +6 -31
  303. package/js/contextmenu/contextmenu.js +338 -336
  304. package/js/dialog/README.md +8 -7
  305. package/js/dialog/dialog.js +228 -261
  306. package/js/drag/README.md +28 -0
  307. package/js/drag/drag.js +38 -0
  308. package/js/drag/indicateDrop.js +80 -0
  309. package/js/loading/README.md +24 -0
  310. package/js/loading/loading.js +139 -0
  311. package/js/navigator/README.md +26 -0
  312. package/js/navigator/navigator.js +430 -0
  313. package/js/navigator/url-change-event.js +29 -0
  314. package/js/rte/README.md +13 -14
  315. package/js/rte/old/NodeCleaner.js +315 -315
  316. package/js/rte/old/Rte/Rte.ui.mjs +154 -154
  317. package/js/rte/old/Rte/index.mjs +5 -5
  318. package/js/rte/old/Rte/main.css +189 -189
  319. package/js/rte/old/old.rte.js +131 -131
  320. package/js/rte/old/range-selection.old.js +394 -394
  321. package/js/rte/rte.js +7 -7
  322. package/js/rte/src/behavior.js +228 -228
  323. package/js/rte/src/events.js +73 -73
  324. package/js/rte/src/fixes.js +250 -250
  325. package/js/rte/src/range.js +469 -472
  326. package/js/rte/src/rte.js +71 -71
  327. package/js/rte/src/ui/items/ai.js +166 -167
  328. package/js/rte/src/ui/items/code.js +93 -93
  329. package/js/rte/src/ui/items/undo.js +183 -183
  330. package/js/rte/src/ui.items.js +6 -7
  331. package/js/rte/src/ui.js +268 -268
  332. package/js/rte/src/util/indentHtml.js +21 -15
  333. package/js/serviceWorker/README.md +17 -0
  334. package/js/serviceWorker/serviceWorker.js +84 -0
  335. package/js/serviceWorker/sw.js +221 -0
  336. package/js/shortcut/README.md +6 -6
  337. package/js/shortcut/shortcut.js +53 -89
  338. package/package.json +9 -8
  339. package/theme/brutalist/README.md +10 -0
  340. package/theme/brutalist/theme.css +98 -0
  341. package/theme/elegance/README.md +10 -0
  342. package/theme/elegance/theme.css +120 -0
  343. package/theme/luxury/README.md +10 -0
  344. package/theme/luxury/theme.css +107 -0
  345. package/theme/minimalism/README.md +10 -0
  346. package/theme/minimalism/theme.css +103 -0
  347. package/theme/natur/README.md +10 -0
  348. package/theme/natur/theme.css +101 -0
  349. package/theme/pastell/README.md +10 -0
  350. package/theme/pastell/theme.css +99 -0
  351. package/theme/pop/README.md +10 -0
  352. package/theme/pop/theme.css +101 -0
  353. package/theme/prompt.css +175 -0
  354. package/theme/retro/README.md +10 -0
  355. package/theme/retro/theme.css +99 -0
  356. package/theme/soft/README.md +10 -0
  357. package/theme/soft/theme.css +84 -0
  358. package/theme/tech/README.md +10 -0
  359. package/theme/tech/theme.css +98 -0
  360. package/theme/test/README.md +10 -0
  361. package/theme/test/theme.css +109 -0
  362. package/theme/test.html +284 -0
  363. package/theme/tmp/README.md +10 -0
  364. package/theme/tmp/theme.css +323 -0
  365. package/u2/auto.js +156 -161
  366. package/u2/auto.ui.js +82 -85
  367. package/u2/plan-scoped-refactoring.md +236 -0
  368. package/u2/projects.json +757 -467
  369. package/u2/tools/baseElement.js +217 -95
  370. package/u2/tools/baseElement.test.html +139 -119
  371. package/u2/tools/ce-inspector.js +307 -307
  372. package/u2/tools/ce-inspector.test.html +67 -65
  373. package/u2/tools/ce-manfest-from-element.js +207 -207
  374. package/u2/tools/dev-iframe.js +212 -213
  375. package/u2/tools/dev-iframe.test.html +72 -74
  376. package/u2/tools/eventsExplorer.js +102 -101
  377. package/u2/tools/logo/u1.svg +9 -9
  378. package/u2/tools/promiseElementById.js +14 -0
  379. package/u2/tools/update.repos.json.js +259 -234
  380. package/u2/tools/update.skill.js +176 -0
  381. package/u2/tools/variable-styler.js +317 -0
  382. package/u2/u2.js +30 -14
  383. package/u2/utils.js +61 -59
  384. package/.htaccess +0 -7
  385. package/attr/behavior/tests/minimal.html +0 -19
  386. package/attr/behavior/tests/test.html +0 -98
  387. package/attr/confirm/tests/minimal.html +0 -23
  388. package/attr/confirm/tests/test.html +0 -79
  389. package/attr/draghandle/tests/minimal.html +0 -44
  390. package/attr/focusgroup/tests/minimal.html +0 -27
  391. package/attr/focusgroup/tests/test.html +0 -154
  392. package/attr/href/tests/minimal.html +0 -17
  393. package/attr/href/tests/test.html +0 -70
  394. package/attr/intersect/tests/minimal.html +0 -30
  395. package/attr/intersect/tests/test.html +0 -64
  396. package/attr/navigable/tests/U1TargetObserver.html +0 -56
  397. package/attr/navigable/tests/minimal.html +0 -17
  398. package/attr/navigable/tests/targetObserver.html +0 -106
  399. package/attr/navigable/tests/test.html +0 -84
  400. package/attr/parallax/tests/minimal.html +0 -25
  401. package/attr/parallax/tests/performance.html +0 -102
  402. package/attr/parallax/tests/test.html +0 -108
  403. package/attr/skin/tests/minimal.html +0 -34
  404. package/attr/skin/tests/test.html +0 -96
  405. package/class/badge/tests/minimal.html +0 -17
  406. package/class/badge/tests/test.html +0 -112
  407. package/class/card1/README.md +0 -45
  408. package/class/card1/card1.css +0 -30
  409. package/class/card1/tests/minimal.html +0 -33
  410. package/class/card1/tests/test.html +0 -78
  411. package/class/flex/tests/minimal.html +0 -31
  412. package/class/flex/tests/test.html +0 -58
  413. package/class/grid/tests/minimal.html +0 -34
  414. package/class/grid/tests/test.html +0 -78
  415. package/class/input/README.md +0 -49
  416. package/class/input/input.css +0 -33
  417. package/class/input/tests/minimal.html +0 -39
  418. package/class/input/tests/test.html +0 -29
  419. package/class/reset/tests/minimal.html +0 -23
  420. package/class/table/tests/minimal.html +0 -40
  421. package/class/table/tests/test.html +0 -226
  422. package/class/unstyle/tests/minimal.html +0 -22
  423. package/class/unstyle/tests/test.html +0 -32
  424. package/class/width/tests/minimal.html +0 -27
  425. package/class/width/tests/test.html +0 -101
  426. package/css/base/tests/nomotion.html +0 -89
  427. package/css/base/tests/test.html +0 -539
  428. package/css/classes/tests/test.html +0 -63
  429. package/css/classless/snippeds/experiments/conventions.css +0 -41
  430. package/css/classless/tests/aria.html +0 -101
  431. package/css/classless/tests/foreign/classless-almond.css.html +0 -445
  432. package/css/classless/tests/foreign/classless-classless.css.html +0 -831
  433. package/css/classless/tests/foreign/classless-mvp.html +0 -415
  434. package/css/classless/tests/foreign/classless.sakura.html +0 -224
  435. package/css/classless/tests/foreign/stylestage.dev.html +0 -304
  436. package/css/classless/tests/foreign/test-homogenizer.html +0 -433
  437. package/css/classless/tests/foreign/test-html5-elements-tester.html +0 -956
  438. package/css/classless/tests/foreign/test-opinionated_css.html +0 -148
  439. package/css/classless/tests/list-bullet.html +0 -110
  440. package/css/classless/tests/more.html +0 -246
  441. package/css/classless/tests/oklch.experiments.html +0 -280
  442. package/css/classless/tests/test.html +0 -106
  443. package/css/classless/tests/variables.html +0 -109
  444. package/css/norm/tests/test.html +0 -434
  445. package/css/norm/tests/test.js +0 -103
  446. package/el/accordion/tests/minimal.html +0 -44
  447. package/el/accordion/tests/test.html +0 -168
  448. package/el/alert/alert copy.js +0 -224
  449. package/el/alert/tests/minimal.html +0 -36
  450. package/el/alert/tests/test.html +0 -105
  451. package/el/buttongroup/tests/minimal.html +0 -31
  452. package/el/buttongroup/tests/test.html +0 -83
  453. package/el/bytes/tests/minimal.html +0 -19
  454. package/el/bytes/tests/test.html +0 -117
  455. package/el/carousel/tests/experiments.html +0 -77
  456. package/el/carousel/tests/minimal.html +0 -31
  457. package/el/carousel/tests/nested.html +0 -54
  458. package/el/carousel/tests/test.html +0 -136
  459. package/el/carousel-nav/tests/minimal.html +0 -32
  460. package/el/carousel-nav/tests/test.html +0 -59
  461. package/el/code/tests/minimal.html +0 -35
  462. package/el/code/tests/test.html +0 -162
  463. package/el/copy/tests/minimal.html +0 -21
  464. package/el/copy/tests/test.html +0 -75
  465. package/el/counter/tests/minimal.html +0 -27
  466. package/el/counter/tests/test.html +0 -106
  467. package/el/ico/tests/combinations.html +0 -86
  468. package/el/ico/tests/emojis.html +0 -213
  469. package/el/ico/tests/fonts.html +0 -110
  470. package/el/ico/tests/ico-directory.html +0 -254
  471. package/el/ico/tests/minimal.html +0 -46
  472. package/el/ico/tests/test.html +0 -210
  473. package/el/ico/tests/util-multi.svg +0 -6
  474. package/el/ico/tests/util.css +0 -2
  475. package/el/ico/tests/util.js +0 -110
  476. package/el/input/tests/formParticipation.html +0 -113
  477. package/el/input/tests/minimal.html +0 -33
  478. package/el/input/tests/test.html +0 -258
  479. package/el/masonry/tests/minimal.html +0 -39
  480. package/el/masonry/tests/test.html +0 -42
  481. package/el/number/tests/minimal.html +0 -25
  482. package/el/number/tests/test.html +0 -138
  483. package/el/out/tests/minimal.html +0 -25
  484. package/el/out/tests/test.html +0 -37
  485. package/el/parallax-bg/tests/bg.jpg +0 -0
  486. package/el/parallax-bg/tests/bg1.jpg +0 -0
  487. package/el/parallax-bg/tests/bg2.jpg +0 -0
  488. package/el/parallax-bg/tests/demo.html +0 -88
  489. package/el/parallax-bg/tests/minimal.html +0 -30
  490. package/el/parallax-bg/tests/test.html +0 -64
  491. package/el/parallax-bg/tests/visible.html +0 -90
  492. package/el/qrcode/tests/minimal.html +0 -26
  493. package/el/qrcode/tests/test.html +0 -31
  494. package/el/rating/tests/minimal.html +0 -26
  495. package/el/rating/tests/tests.html +0 -77
  496. package/el/rte/tests/minimal.html +0 -25
  497. package/el/rte/tests/test.html +0 -37
  498. package/el/skeleton/tests/minimal.html +0 -22
  499. package/el/skeleton/tests/test.html +0 -22
  500. package/el/splitbutton/README.md +0 -39
  501. package/el/splitbutton/splitbutton.js +0 -26
  502. package/el/splitbutton/tests/minimal.html +0 -30
  503. package/el/splitbutton/tests/test.html +0 -68
  504. package/el/splitpanel/tests/minimal.html +0 -31
  505. package/el/splitpanel/tests/tests.html +0 -121
  506. package/el/table/tests/minimal.html +0 -38
  507. package/el/table/tests/test.html +0 -108
  508. package/el/tabs/tests/minimal.html +0 -35
  509. package/el/tabs/tests/test.html +0 -180
  510. package/el/textfit/tests/minimal.html +0 -25
  511. package/el/textfit/tests/test.html +0 -26
  512. package/el/time/tests/minimal.html +0 -19
  513. package/el/time/tests/test.html +0 -160
  514. package/el/time/time copy.js +0 -141
  515. package/el/time/time.old.uhtml.js +0 -129
  516. package/el/tooltip/tests/minimal.html +0 -25
  517. package/el/tooltip/tests/test.html +0 -178
  518. package/el/tree1/README.md +0 -111
  519. package/el/tree1/manifest.json +0 -78
  520. package/el/tree1/tests/animated.html +0 -134
  521. package/el/tree1/tests/custom.html +0 -51
  522. package/el/tree1/tests/minimal.html +0 -44
  523. package/el/tree1/tests/test.html +0 -260
  524. package/el/tree1/tree1.css +0 -26
  525. package/el/tree1/tree1.js +0 -265
  526. package/el/typewriter/tests/minimal.html +0 -25
  527. package/el/typewriter/tests/test.html +0 -78
  528. package/js/Placer/tests/minimal.html +0 -34
  529. package/js/Placer/tests/test.html +0 -49
  530. package/js/PointerObserver/tests/minimal.html +0 -29
  531. package/js/PointerObserver/tests/test.html +0 -35
  532. package/js/SelectorObserver/tests/minimal.html +0 -21
  533. package/js/SelectorObserver/tests/test.html +0 -57
  534. package/js/SelectorObserver/tests/tests.html +0 -161
  535. package/js/contextmenu/tests/minimal.html +0 -44
  536. package/js/contextmenu/tests/test.html +0 -131
  537. package/js/dialog/tests/minimal.html +0 -29
  538. package/js/dialog/tests/notification.mp3 +0 -0
  539. package/js/dialog/tests/test.html +0 -135
  540. package/js/rte/tests/ai.html +0 -81
  541. package/js/rte/tests/behavior.html +0 -88
  542. package/js/rte/tests/events.html +0 -69
  543. package/js/rte/tests/fixes.html +0 -95
  544. package/js/rte/tests/minimal.html +0 -34
  545. package/js/rte/tests/notes.md +0 -6
  546. package/js/rte/tests/range.html +0 -167
  547. package/js/rte/tests/selection-explorer.html +0 -222
  548. package/js/rte/tests/test.html +0 -92
  549. package/js/shortcut/tests/minimal.html +0 -23
  550. package/js/shortcut/tests/test.html +0 -68
  551. package/u2/experiments/Waiter/test.html +0 -132
  552. package/u2/experiments/getElementByIdPromise/test.html +0 -76
  553. package/u2/experiments/patchInputValue.html +0 -124
  554. package/u2/experiments/radiobutton/test.html +0 -75
  555. package/u2/experiments/tests/test.html +0 -223
  556. package/u2/experiments/u1-responsive/responsive.js +0 -62
  557. package/u2/experiments/u1-responsive/test.html +0 -65
  558. package/u2/experiments/u2Element.js +0 -139
  559. package/u2/experiments/u2Element.test.html +0 -47
  560. package/u2/old-stuff/IterableWeakMap/mod.js +0 -70
  561. package/u2/old-stuff/css/onStyleSheet/mod.js +0 -114
  562. package/u2/old-stuff/css/onStyleSheet/monkeypatches.js +0 -28
  563. package/u2/old-stuff/css/onStyleSheet/test/include.css +0 -19
  564. package/u2/old-stuff/css/onStyleSheet/test/style-has-include.css +0 -6
  565. package/u2/old-stuff/css/onStyleSheet/test/style-no-include.css +0 -3
  566. package/u2/old-stuff/css/onStyleSheet/test/test.html +0 -48
  567. package/u2/old-stuff/css/parser/mod.js +0 -182
  568. package/u2/old-stuff/css/parser/parser_old/mod.js +0 -128
  569. package/u2/old-stuff/css/parser/parser_old/test.html +0 -43
  570. package/u2/old-stuff/css/parser/parser_old/util.js +0 -22
  571. package/u2/old-stuff/css/parser/style.html +0 -52
  572. package/u2/old-stuff/css/parser/test.html +0 -38
  573. package/u2/old-stuff/el/ai-texter/README.md +0 -23
  574. package/u2/old-stuff/el/ai-texter/ai-texter.css +0 -12
  575. package/u2/old-stuff/el/ai-texter/ai-texter.js +0 -153
  576. package/u2/old-stuff/el/ai-texter/tests/minimal.html +0 -47
  577. package/u2/old-stuff/el/ai-texter/tests/test.html +0 -71
  578. package/u2/old-stuff/init.js +0 -38
  579. package/u2/old-stuff/markHashLinks.js +0 -51
  580. package/u2/old-stuff/onElement/mod.js +0 -73
  581. package/u2/old-stuff/test-helpers/mod.js +0 -36
  582. package/u2/old-stuff/test-helpers/test.html +0 -4
  583. package/u2/old-stuff/tests/init.js.html +0 -51
  584. package/u2/old-stuff/viewport.js +0 -64
  585. package/u2/tests/boilerplate.html +0 -46
  586. package/u2/tests/kacheln.html +0 -245
  587. package/u2/tests/showcase.html +0 -270
  588. package/u2/tests/showcase2.html +0 -157
  589. package/u2/tests/test-init.js +0 -35
  590. package/u2/tests/test.html +0 -355
  591. package/u2/tools/logo/u1ui.svg +0 -6
@@ -0,0 +1,80 @@
1
+
2
+ // HINWEIS: In attr/dropzone/dropzone.js gibt es eine eigene, reichere indicateDrop-Variante
3
+ // (horizontal/vertikal, Gap-Zentrierung, leerer Container). Bewusst noch nicht zusammengeführt —
4
+ // diese hier kann dafür into-Rahmen + content-Box-Inset. Bei Änderungen ggf. dort mitdenken.
5
+
6
+ /**
7
+ * Zeigt einen Drop-Indicator relativ zu einem Element
8
+ * @param {'before'|'after'|'into'|null} position - Position des Indicators oder null zum Verstecken
9
+ * @param {HTMLElement|null} element - Referenz-Element
10
+ * @param {object} [options]
11
+ * @param {'border'|'content'} [options.box='border'] - Bezugsbox des Elements, auf allen Seiten gleich.
12
+ * 'content' = innerhalb des Paddings (macht z.B. Einrückungen sichtbar).
13
+ */
14
+ export function indicateDrop(position, element, { box = 'border' } = {}) {
15
+ let indicator = document.getElementById('drop-indicator');
16
+
17
+ if (!indicator) {
18
+ indicator = document.createElement('div');
19
+ indicator.id = 'drop-indicator';
20
+ indicator.popover = 'manual';
21
+ indicator.innerHTML = `
22
+ <style>
23
+ #drop-indicator {
24
+ --color: var(--blue, #2563eb);
25
+ position: fixed;
26
+ margin: 0;
27
+ padding: 0;
28
+ border: none;
29
+ border:0 solid var(--color);
30
+ height: 2px;
31
+ background: var(--color);
32
+ pointer-events: none;
33
+ overflow:visible;
34
+ transition: .07s ease-out;
35
+ &::before, &::after {
36
+ content: "";
37
+ width: 9px;
38
+ height: 9px;
39
+ border-radius: 99px;
40
+ background: inherit;
41
+ position: absolute;
42
+ top: -4px;
43
+ left: -5px;
44
+ }
45
+ &::after {
46
+ right:-5px; left:auto;
47
+ }
48
+ &[data-into] { /* Rahmen statt Linie */
49
+ height:auto;
50
+ background:none;
51
+ background: color-mix(in srgb, var(--color) 10%, transparent);
52
+ border-width:2px;
53
+ &::before, &::after { xdisplay:none }
54
+ }
55
+ }
56
+ </style>
57
+ `;
58
+ document.body.appendChild(indicator);
59
+ }
60
+
61
+ if (!position || !element) {
62
+ indicator.hidePopover();
63
+ return;
64
+ }
65
+
66
+ const rect = element.getBoundingClientRect();
67
+ const s = indicator.style;
68
+ let top = rect.top, bottom = rect.bottom, left = rect.left, width = rect.width, height = rect.height;
69
+ if (box === 'content') { // echte Content-Box, alle Seiten gleich behandelt
70
+ const cs = getComputedStyle(element);
71
+ const [pt, pr, pb, pl] = ['Top', 'Right', 'Bottom', 'Left'].map(k => parseFloat(cs['padding' + k]) || 0);
72
+ top += pt; bottom -= pb; left += pl; width -= pl + pr; height -= pt + pb;
73
+ }
74
+ s.left = `${left}px`;
75
+ s.width = `${width}px`;
76
+ indicator.toggleAttribute('data-into', position === 'into');
77
+ if (position === 'into') { s.top = `${top}px`; s.height = `${height}px`; }
78
+ else { s.top = `${(position === 'before' ? top : bottom) - 1}px`; s.height = ''; }
79
+ indicator.showPopover();
80
+ }
@@ -0,0 +1,24 @@
1
+ ## loading.js
2
+
3
+ ## Usage
4
+
5
+ ```html
6
+ <button id="btn1" onclick="setTimeout(u2_loading.mark(this),2000)">load</button>
7
+ ```
8
+
9
+ ## Install
10
+
11
+ ```js
12
+ import * as module from "https://cdn.jsdelivr.net/gh/u2ui/u2@main/js/loading/loading.js"
13
+ ```
14
+
15
+ ## Demos
16
+
17
+ [test.html](http://gcdn.li/u2ui/u2@main/js/loading/tests/test.html)
18
+ [minimal.html](http://gcdn.li/u2ui/u2@main/js/loading/tests/minimal.html)
19
+
20
+ ## About
21
+
22
+ - MIT License, Copyright (c) 2022 <u2> (like all repositories in this organization) <br>
23
+ - Suggestions, ideas, finding bugs and making pull requests make us very happy. ♥
24
+
@@ -0,0 +1,139 @@
1
+
2
+ export function mark(el, opt) {
3
+ if (!el.length) return _markElement(el, opt);
4
+ const dones = Array.from(el, el=>_markElement(el, opt));
5
+ return ()=>{ for (let done of dones) done(); }
6
+ }
7
+
8
+ export function done(el) {
9
+ el.loadingTasks--;
10
+ clearTimeout(el.u2ShowLoadingTO);
11
+ if (el.loadingTasks <= 0) {
12
+ el.classList.remove('u2Loading');
13
+ el.removeAttribute('aria-busy');
14
+ //el.removeAttribute('inert');
15
+ el.style.cssText = el.u2Loading_oldCssText;
16
+ el.u2Loading_oldCssText = undefined;
17
+ }
18
+ }
19
+
20
+ function _markElement(el, {delay = 0} = {}) {
21
+
22
+ el.loadingTasks ??= 0;
23
+ el.loadingTasks++;
24
+ if (el.loadingTasks === 1) { // new, already loading
25
+
26
+ const mutationObserver = new MutationObserver(()=>{
27
+ done(el);
28
+ if (el.loadingTasks <= 0) mutationObserver.disconnect();
29
+ });
30
+ mutationObserver.observe(el,{childList:true});
31
+ if (el.tagName === 'IMG') {
32
+ const onload = e=>{
33
+ el.loadingTasks = 1;
34
+ done(el);
35
+ }
36
+ el.addEventListener('load', onload, {once:true});
37
+ el.addEventListener('error', onload, {once:true});
38
+ }
39
+
40
+
41
+ const root = el.getRootNode();
42
+ if (root.adoptedStyleSheets.indexOf(sheet) === -1) root.adoptedStyleSheets = [...root.adoptedStyleSheets, sheet];
43
+
44
+ el.u2Loading_oldCssText = el.style.cssText;
45
+ el.ariaBusy = 'true';
46
+ //el.inert = true;
47
+
48
+ clearTimeout(el.u2ShowLoadingTO);
49
+ el.u2ShowLoadingTO = setTimeout(()=>{
50
+ el.classList.add('u2Loading');
51
+ //if (el.hasAttribute('aria-life')) el.ariaBusy = 'true';
52
+
53
+ // this is bad:
54
+ //if (!el.offsetHeight) el.style.minHeight = '36px';
55
+ //if (!el.offsetWidth) el.style.minWidth = '36px';
56
+
57
+ let svg = getComputedStyle(el).getPropertyValue('--loading-svg');
58
+ svg = svg.replace('currentColor', getComputedStyle(el).color);
59
+ el.style.setProperty('background-image', svg, 'important');
60
+ },delay);
61
+ }
62
+ return ()=>done(el);
63
+ }
64
+
65
+
66
+ const xsvg = `
67
+ <svg fill="currentColor" width="64px" height="64px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" xpreserveAspectRatio="xMidYMid">
68
+ <style>
69
+ @keyframes x {
70
+ from { opacity: 1; scale:1.5; }
71
+ 100% { opacity: 0; scale:1; }
72
+ }
73
+ g > g {
74
+ transform: rotate(calc(var(--i) * 45deg)) translate(34px, 0);
75
+ }
76
+ circle {
77
+ animation: x 1.4s infinite;
78
+ will-change:opacity,transform;
79
+ animation-delay: calc(var(--i) * .17s);
80
+ }
81
+ </style>
82
+ <g transform="translate(50 50)">
83
+ <g style="--i:0"><circle cx="0" cy="0" r="8"></circle></g>
84
+ <g style="--i:1"><circle cx="0" cy="0" r="8"></circle></g>
85
+ <g style="--i:2"><circle cx="0" cy="0" r="8"></circle></g>
86
+ <g style="--i:3"><circle cx="0" cy="0" r="8"></circle></g>
87
+ <g style="--i:4"><circle cx="0" cy="0" r="8"></circle></g>
88
+ <g style="--i:5"><circle cx="0" cy="0" r="8"></circle></g>
89
+ <g style="--i:6"><circle cx="0" cy="0" r="8"></circle></g>
90
+ <g style="--i:7"><circle cx="0" cy="0" r="8"></circle></g>
91
+ </g>
92
+ </svg>`;
93
+
94
+ const svg = '<svg width="24" height="24" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_V8m1{transform-origin:center;animation:spinner_zKoa 2s linear infinite}.spinner_V8m1 circle{stroke-linecap:round;animation:spinner_YpZS 1.5s ease-in-out infinite}@keyframes spinner_zKoa{100%{transform:rotate(360deg)}}@keyframes spinner_YpZS{0%{stroke-dasharray:0 150;stroke-dashoffset:0}47.5%{stroke-dasharray:42 150;stroke-dashoffset:-16}95%,100%{stroke-dasharray:42 150;stroke-dashoffset:-59}}</style><g class="spinner_V8m1"><circle cx="12" cy="12" r="9.5" fill="none" stroke-width="3"></circle></g></svg>';
95
+
96
+
97
+ const css = `
98
+ .u2Loading {
99
+ --loading-svg: url("data:image/svg+xml;utf8,${encodeURIComponent(svg)}");
100
+ background-image: var(--loading-svg) !important;
101
+ background-repeat: no-repeat !important;
102
+ background-position: 50% !important;
103
+ background-position-y: min(50%, 10rem) !important;
104
+ background-size: 32px !important;
105
+ cursor: wait !important;
106
+ opacity:1;
107
+ pointer-events:none;
108
+ & > * {
109
+ opacity:.1;
110
+ cursor: wait !important;
111
+ }
112
+ &:is(button, span) {
113
+ background-size: 2px !important;
114
+ background-position:-100% !important;
115
+ &::after {
116
+ content:"";
117
+ display:inline-block;
118
+
119
+ line-height:inherit;
120
+ height:.8lh;
121
+ width:.8lh;
122
+ margin-bottom:.1lh;
123
+ vertical-align: bottom;
124
+
125
+ margin-left:.3em;
126
+ background-image:inherit;
127
+ background-size:contain;
128
+ background-repeat:no-repeat;
129
+ }
130
+ }
131
+ &:is(img) {
132
+ object-position: -10000px -10000px !important;
133
+ background-position-y: 50% !important;
134
+ }
135
+ }
136
+ `;
137
+
138
+ const sheet = new CSSStyleSheet();
139
+ sheet.replaceSync(css);
@@ -0,0 +1,26 @@
1
+ ## navigator.js
2
+
3
+ ## Usage
4
+
5
+ ```html
6
+
7
+ ```
8
+
9
+ ## Install
10
+
11
+ ```js
12
+ import * as module from "https://cdn.jsdelivr.net/gh/u2ui/u2@main/js/navigator/navigator.js"
13
+ ```
14
+
15
+ ## Demos
16
+
17
+ [about.html](http://gcdn.li/u2ui/u2@main/js/navigator/tests/about.html)
18
+ [contact.html](http://gcdn.li/u2ui/u2@main/js/navigator/tests/contact.html)
19
+ [minimal.html](http://gcdn.li/u2ui/u2@main/js/navigator/tests/minimal.html)
20
+ [index.html](http://gcdn.li/u2ui/u2@main/js/navigator/tests/index.html)
21
+
22
+ ## About
23
+
24
+ - MIT License, Copyright (c) 2022 <u2> (like all repositories in this organization) <br>
25
+ - Suggestions, ideas, finding bugs and making pull requests make us very happy. ♥
26
+
@@ -0,0 +1,430 @@
1
+ import './url-change-event.js';
2
+
3
+ // ==================== CONFIG ====================
4
+ const CONFIG = {
5
+ cacheSize: 50,
6
+ prefetchDelay: 100,
7
+ mouseProximity: 200,
8
+ cacheDuration: 3 * 60 * 60 * 1000, // 3 Stunden
9
+ cacheVersion: 'v1',
10
+ };
11
+
12
+ // ==================== STATE ====================
13
+ const state = {
14
+ pageCache: new Map(),
15
+ prefetchQueue: new Set(),
16
+ failedUrls: new Set(),
17
+ mouse: { x: 0, y: 0 },
18
+ isIdle: false,
19
+ idleTimer: null,
20
+ persistentCache: null,
21
+ };
22
+
23
+ // ==================== PERSISTENT STORAGE ====================
24
+ class PersistentStorage {
25
+ static async init() {
26
+ if ('caches' in globalThis) {
27
+ state.persistentCache = await caches.open(`router-cache-${CONFIG.cacheVersion}`);
28
+ return 'Cache API';
29
+ }
30
+ state.persistentCache = 'localStorage';
31
+ return 'localStorage';
32
+ }
33
+
34
+ static async get(url) {
35
+ const now = performance.now() + performance.timeOrigin;
36
+
37
+ if (state.persistentCache === 'localStorage') {
38
+ try {
39
+ const item = localStorage.getItem(`router:${url}`);
40
+ if (!item) return null;
41
+
42
+ const data = JSON.parse(item);
43
+ if (now - data.timestamp > CONFIG.cacheDuration) {
44
+ localStorage.removeItem(`router:${url}`);
45
+ return null;
46
+ }
47
+ return data.html;
48
+ } catch {
49
+ return null;
50
+ }
51
+ }
52
+
53
+ // Cache API
54
+ try {
55
+ const response = await state.persistentCache.match(url);
56
+ if (!response) return null;
57
+
58
+ const timestamp = Number(response.headers.get('X-Cached-Time') ?? '0');
59
+ if (now - timestamp > CONFIG.cacheDuration) {
60
+ await state.persistentCache.delete(url);
61
+ return null;
62
+ }
63
+
64
+ return await response.text();
65
+ } catch {
66
+ return null;
67
+ }
68
+ }
69
+
70
+ static async set(url, html) {
71
+ const now = performance.now() + performance.timeOrigin;
72
+
73
+ if (state.persistentCache === 'localStorage') {
74
+ try {
75
+ const data = { html, timestamp: now };
76
+ localStorage.setItem(`router:${url}`, JSON.stringify(data));
77
+ this.cleanup();
78
+ } catch (error) {
79
+ if (error.name === 'QuotaExceededError') {
80
+ this.cleanup(true);
81
+ }
82
+ }
83
+ return;
84
+ }
85
+
86
+ // Cache API
87
+ try {
88
+ const response = new Response(html, {
89
+ headers: {
90
+ 'Content-Type': 'text/html; charset=utf-8',
91
+ 'X-Cached-Time': String(now),
92
+ },
93
+ });
94
+ await state.persistentCache.put(url, response);
95
+ } catch (error) {
96
+ console.warn('Cache write failed:', error);
97
+ }
98
+ }
99
+
100
+ static cleanup(force = false) {
101
+ if (state.persistentCache !== 'localStorage') return;
102
+
103
+ const now = performance.now() + performance.timeOrigin;
104
+ const keys = Object.keys(localStorage).filter(k => k.startsWith('router:'));
105
+
106
+ for (const key of keys) {
107
+ try {
108
+ const item = JSON.parse(localStorage.getItem(key));
109
+ if (force || now - item.timestamp > CONFIG.cacheDuration) {
110
+ localStorage.removeItem(key);
111
+ }
112
+ } catch {
113
+ localStorage.removeItem(key);
114
+ }
115
+ }
116
+ }
117
+ }
118
+
119
+ // ==================== DOM MORPHING (IdleCallback optimiert) ====================
120
+ class Morph {
121
+ static morph(oldNode, newNode) {
122
+ if (oldNode.nodeType === Node.TEXT_NODE) {
123
+ if (oldNode.nodeValue !== newNode.nodeValue) {
124
+ oldNode.nodeValue = newNode.nodeValue;
125
+ }
126
+ return;
127
+ }
128
+ this.#morphAttributes(oldNode, newNode);
129
+ this.#morphChildren(oldNode, newNode);
130
+ }
131
+
132
+ static #morphAttributes(oldNode, newNode) {
133
+ const oldAttrs = oldNode.attributes;
134
+ const newAttrs = newNode.attributes;
135
+ if (newAttrs) { // Update/Add attributes
136
+ for (const attr of newAttrs) {
137
+ if (oldNode.getAttribute(attr.name) !== attr.value) oldNode.setAttribute(attr.name, attr.value);
138
+ }
139
+ }
140
+ if (oldAttrs) { // Remove old attributes
141
+ for (let i = oldAttrs.length - 1; i >= 0; i--) {
142
+ const attr = oldAttrs[i];
143
+ if (!newNode.hasAttribute(attr.name)) oldNode.removeAttribute(attr.name);
144
+ }
145
+ }
146
+ }
147
+ static #morphChildren(oldNode, newNode) {
148
+ const oldChildren = [...oldNode.childNodes];
149
+ const newChildren = [...newNode.childNodes];
150
+ const maxLen = Math.max(oldChildren.length, newChildren.length);
151
+
152
+ for (let i = 0; i < maxLen; i++) {
153
+ const oldChild = oldChildren[i];
154
+ const newChild = newChildren[i];
155
+
156
+ if (!oldChild && newChild) {
157
+ oldNode.append(newChild);
158
+ } else if (oldChild && !newChild) {
159
+ oldNode.removeChild(oldChild);
160
+ } else if (oldChild && newChild) {
161
+ if (this.#shouldReplace(oldChild, newChild)) {
162
+ oldNode.replaceChild(newChild, oldChild);
163
+ } else {
164
+ this.morph(oldChild, newChild);
165
+ }
166
+ }
167
+ }
168
+ }
169
+ static #shouldReplace(oldNode, newNode) {
170
+ if (oldNode.nodeType !== newNode.nodeType) return true;
171
+ if (oldNode.nodeType === Node.TEXT_NODE) return oldNode.textContent !== newNode.textContent;
172
+ return oldNode.tagName !== newNode.tagName || oldNode.id !== newNode.id;
173
+ }
174
+ }
175
+
176
+ // import morphdom from 'https://esm.sh/morphdom@2.7.4';
177
+ // morphdom(oldNode, newNode);
178
+ // import nanomorph from 'https://esm.sh/nanomorph@5.4.3';
179
+ // nanomorph(oldNode, newNode);
180
+ // import Idiomorph from 'https://esm.sh/idiomorph@0.3.0';
181
+ // Idiomorph.morph(oldNode, newNode);
182
+
183
+ import morphdom from 'https://esm.sh/morphdom@2.7.4';
184
+ function morphDocument(newDoc) {
185
+ // am liebsten würde ich ganzes dokument inklusive header morphen, aber dann kann generiertes css verloren gehen... :(
186
+ //morphdom(document.body, newDoc.body);
187
+ //morphdom(document.documentElement, newDoc.documentElement);
188
+ document.title = newDoc.title;
189
+ Morph.morph(document.body, newDoc.body);
190
+ }
191
+
192
+
193
+ // ==================== UTILITIES ====================
194
+ const Utils = {
195
+ isInternalLink(url) {
196
+ try {
197
+ const link = new URL(url, location.origin);
198
+ return link.origin === location.origin;
199
+ } catch {
200
+ return false;
201
+ }
202
+ },
203
+ getDistance(x1, y1, x2, y2) {
204
+ return Math.hypot(x2 - x1, y2 - y1);
205
+ },
206
+ idlePromise(options) {
207
+ return new Promise(resolve => {
208
+ if ('requestIdleCallback' in globalThis) {
209
+ requestIdleCallback(resolve, options);
210
+ } else {
211
+ setTimeout(resolve, 1);
212
+ }
213
+ });
214
+ },
215
+ };
216
+
217
+ // ==================== CACHE MANAGEMENT ====================
218
+ class CacheManager {
219
+ static addToCache(url, html) {
220
+ if (state.pageCache.size >= CONFIG.cacheSize) {
221
+ const firstKey = state.pageCache.keys().next().value;
222
+ state.pageCache.delete(firstKey);
223
+ }
224
+
225
+ state.pageCache.set(url, html);
226
+ PersistentStorage.set(url, html);
227
+ }
228
+
229
+ static async fetchPage(url) {
230
+ // Blacklist-Check
231
+ if (state.failedUrls.has(url)) return null;
232
+
233
+ // 1. Memory Cache
234
+ if (state.pageCache.has(url)) return state.pageCache.get(url);
235
+
236
+ // 2. Persistent Storage
237
+ const cachedHtml = await PersistentStorage.get(url);
238
+ if (cachedHtml) {
239
+ state.pageCache.set(url, cachedHtml);
240
+ return cachedHtml;
241
+ }
242
+
243
+ // 3. Network
244
+ try {
245
+ const response = await fetch(url, {
246
+ headers: { 'X-Requested-With': 'SmartRouter' },
247
+ });
248
+
249
+
250
+ if (!response.ok) {
251
+ state.failedUrls.add(url); // In Blacklist eintragen
252
+ return null;
253
+ }
254
+
255
+ const html = await response.text();
256
+ this.addToCache(url, html);
257
+ return html;
258
+ } catch (error) {
259
+ console.error('Fetch failed:', url, error);
260
+ return null;
261
+ }
262
+ }
263
+ }
264
+
265
+
266
+ // ==================== PAGE NAVIGATION ====================
267
+ async function loadPage(url, shouldUpdateHistory = true) {
268
+ const html = await CacheManager.fetchPage(url);
269
+ if (!html) {
270
+ location.href = url;
271
+ return;
272
+ }
273
+
274
+ // Parse mit DOMParser
275
+ const parser = new DOMParser();
276
+ const newDoc = parser.parseFromString(html, 'text/html');
277
+
278
+ if ('startViewTransition' in document) {
279
+ document.startViewTransition(() => morphDocument(newDoc));
280
+ } else morphDocument(newDoc);
281
+
282
+ if (shouldUpdateHistory) history.pushState({ url }, '', url);
283
+
284
+ scrollTo({ top: 0, behavior: 'instant' });
285
+
286
+ Prefetch.scheduleIdlePrefetch();
287
+ }
288
+
289
+ // ==================== PREFETCHING ====================
290
+ class Prefetch {
291
+ static getAllInternalLinks() {
292
+ const links = [];
293
+
294
+ for (const link of document.querySelectorAll('a[href]')) {
295
+ const href = link.href;
296
+ if (!href || !Utils.isInternalLink(href)) continue;
297
+
298
+ const url = new URL(href, location.origin).href;
299
+ if (state.pageCache.has(url)) continue;
300
+
301
+ const rect = link.getBoundingClientRect();
302
+ const centerX = rect.left + rect.width / 2;
303
+ const centerY = rect.top + rect.height / 2;
304
+ const distance = Utils.getDistance(state.mouse.x, state.mouse.y, centerX, centerY);
305
+
306
+ links.push({ url, distance, element: link });
307
+ }
308
+
309
+ return links;
310
+ }
311
+
312
+ static async prefetchLinks() {
313
+ if (!state.isIdle) return;
314
+
315
+ const links = this.getAllInternalLinks();
316
+ links.sort((a, b) => a.distance - b.distance);
317
+
318
+ // Priority: Links nahe der Maus
319
+ const nearbyLinks = links.filter(l => l.distance < CONFIG.mouseProximity);
320
+ const otherLinks = links.filter(l => l.distance >= CONFIG.mouseProximity);
321
+
322
+ // Prefetch
323
+ for (const link of nearbyLinks.slice(0, 3)) {
324
+ if (!state.isIdle || state.prefetchQueue.has(link.url)) continue;
325
+ await Utils.idlePromise({ timeout: 2000 });
326
+ state.prefetchQueue.add(link.url);
327
+ await CacheManager.fetchPage(link.url);
328
+ state.prefetchQueue.delete(link.url);
329
+ }
330
+
331
+ // Rest der Links (rate-limited)
332
+ for (const link of otherLinks.slice(0, 10)) {
333
+ if (!state.isIdle || state.prefetchQueue.has(link.url)) break;
334
+ await Utils.idlePromise({ timeout: 2000 });
335
+ state.prefetchQueue.add(link.url);
336
+ await CacheManager.fetchPage(link.url);
337
+ state.prefetchQueue.delete(link.url);
338
+ await new Promise(resolve => setTimeout(resolve, 100));
339
+ }
340
+ }
341
+
342
+ static scheduleIdlePrefetch() {
343
+ clearTimeout(state.idleTimer);
344
+ state.isIdle = false;
345
+
346
+ state.idleTimer = setTimeout(() => {
347
+ state.isIdle = true;
348
+ this.prefetchLinks();
349
+ }, CONFIG.prefetchDelay);
350
+ }
351
+ }
352
+
353
+ // ==================== EVENT HANDLERS ====================
354
+ class EventHandlers {
355
+ static setupLinkInterception() {
356
+ document.addEventListener('click', (e) => {
357
+ if (e.ctrlKey || e.shiftKey) return;
358
+
359
+ const link = e.target.closest('a');
360
+ const href = link?.href;
361
+
362
+ if (!href || link.target || !Utils.isInternalLink(href)) return;
363
+
364
+ const sameDoc = location.href.replace(/#.*$/, '') === href.replace(/#.*$/, '');
365
+
366
+ if (link.hash && sameDoc) return; // same document, but hash-link: don't preventDefault
367
+ e.preventDefault();
368
+ if (sameDoc) return; // same document, nothing to load, but prevent reload
369
+
370
+ loadPage(link.href);
371
+
372
+ }, { passive: false });
373
+ }
374
+
375
+ static setupHistoryNavigation() {
376
+ addEventListener('popstate', (e) => {
377
+ if (e.state === null) return; // hash-links only? ok?
378
+ if (e.state.source === 'u2-target') { // todo, make it generic
379
+ console.log('new url handled by u2-navigable');
380
+ return;
381
+ }
382
+ const url = e.state?.url ?? location.href;
383
+ // todo: from hash-link to same document without hash, it is should not load
384
+ loadPage(url, false);
385
+ });
386
+ }
387
+
388
+ static setupMouseTracking() {
389
+ document.addEventListener('mousemove', (e) => {
390
+ state.mouse.x = e.clientX;
391
+ state.mouse.y = e.clientY;
392
+ }, { passive: true });
393
+ }
394
+
395
+ static setupIdleDetection() {
396
+ for (const event of ['scroll', 'mousemove', 'keydown', 'click', 'touchstart']) {
397
+ addEventListener(event, () => Prefetch.scheduleIdlePrefetch(), {
398
+ passive: true
399
+ });
400
+ }
401
+ }
402
+ }
403
+
404
+ // ==================== INITIALIZATION ====================
405
+ async function init() {
406
+ // Persistent Storage
407
+ const storageType = await PersistentStorage.init();
408
+ //console.log(`🚀 Smart Router initialized (${storageType})`);
409
+
410
+ // Cleanup
411
+ PersistentStorage.cleanup();
412
+
413
+ // Cache current page
414
+ CacheManager.addToCache(location.href, document.documentElement.outerHTML);
415
+
416
+ // History state
417
+ history.replaceState({ url: location.href }, '', location.href);
418
+
419
+ // Event listeners
420
+ EventHandlers.setupLinkInterception();
421
+ EventHandlers.setupHistoryNavigation();
422
+ EventHandlers.setupMouseTracking();
423
+ EventHandlers.setupIdleDetection();
424
+
425
+ // Start prefetching
426
+ Prefetch.scheduleIdlePrefetch();
427
+ }
428
+
429
+ // Auto-init
430
+ init();