snice 1.13.2 → 1.13.4

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 (295) hide show
  1. package/bin/templates/base/README.md +1 -1
  2. package/dist/components/accordion/snice-accordion-item.d.ts +25 -0
  3. package/dist/components/accordion/snice-accordion-item.js +260 -0
  4. package/dist/components/accordion/snice-accordion-item.js.map +1 -0
  5. package/dist/components/accordion/snice-accordion.d.ts +28 -0
  6. package/dist/components/accordion/snice-accordion.js +221 -0
  7. package/dist/components/accordion/snice-accordion.js.map +1 -0
  8. package/dist/components/accordion/snice-accordion.types.d.ts +29 -0
  9. package/dist/components/accordion/snice-accordion.types.js +2 -0
  10. package/dist/components/accordion/snice-accordion.types.js.map +1 -0
  11. package/dist/components/alert/snice-alert.d.ts +26 -0
  12. package/dist/components/alert/snice-alert.js +191 -0
  13. package/dist/components/alert/snice-alert.js.map +1 -0
  14. package/dist/components/alert/snice-alert.types.d.ts +11 -0
  15. package/dist/components/alert/snice-alert.types.js +2 -0
  16. package/dist/components/alert/snice-alert.types.js.map +1 -0
  17. package/dist/components/avatar/snice-avatar.d.ts +24 -0
  18. package/dist/components/avatar/snice-avatar.js +177 -0
  19. package/dist/components/avatar/snice-avatar.js.map +1 -0
  20. package/dist/components/avatar/snice-avatar.types.d.ts +12 -0
  21. package/dist/components/avatar/snice-avatar.types.js +2 -0
  22. package/dist/components/avatar/snice-avatar.types.js.map +1 -0
  23. package/dist/components/badge/snice-badge.d.ts +25 -0
  24. package/dist/components/badge/snice-badge.js +157 -0
  25. package/dist/components/badge/snice-badge.js.map +1 -0
  26. package/dist/components/badge/snice-badge.types.d.ts +15 -0
  27. package/dist/components/badge/snice-badge.types.js +2 -0
  28. package/dist/components/badge/snice-badge.types.js.map +1 -0
  29. package/dist/components/breadcrumbs/snice-breadcrumbs.d.ts +27 -0
  30. package/dist/components/breadcrumbs/snice-breadcrumbs.js +212 -0
  31. package/dist/components/breadcrumbs/snice-breadcrumbs.js.map +1 -0
  32. package/dist/components/breadcrumbs/snice-breadcrumbs.types.d.ts +23 -0
  33. package/dist/components/breadcrumbs/snice-breadcrumbs.types.js +2 -0
  34. package/dist/components/breadcrumbs/snice-breadcrumbs.types.js.map +1 -0
  35. package/dist/components/breadcrumbs/snice-crumb.d.ts +9 -0
  36. package/dist/components/breadcrumbs/snice-crumb.js +50 -0
  37. package/dist/components/breadcrumbs/snice-crumb.js.map +1 -0
  38. package/dist/components/button/snice-button.d.ts +32 -0
  39. package/dist/components/button/snice-button.js +212 -0
  40. package/dist/components/button/snice-button.js.map +1 -0
  41. package/dist/components/button/snice-button.types.d.ts +23 -0
  42. package/dist/components/button/snice-button.types.js +2 -0
  43. package/dist/components/button/snice-button.types.js.map +1 -0
  44. package/dist/components/card/snice-card.d.ts +19 -0
  45. package/dist/components/card/snice-card.js +132 -0
  46. package/dist/components/card/snice-card.js.map +1 -0
  47. package/dist/components/card/snice-card.types.d.ts +9 -0
  48. package/dist/components/card/snice-card.types.js +2 -0
  49. package/dist/components/card/snice-card.types.js.map +1 -0
  50. package/dist/components/checkbox/snice-checkbox.d.ts +34 -0
  51. package/dist/components/checkbox/snice-checkbox.js +289 -0
  52. package/dist/components/checkbox/snice-checkbox.js.map +1 -0
  53. package/dist/components/checkbox/snice-checkbox.types.d.ts +20 -0
  54. package/dist/components/checkbox/snice-checkbox.types.js +2 -0
  55. package/dist/components/checkbox/snice-checkbox.types.js.map +1 -0
  56. package/dist/components/chip/snice-chip.d.ts +28 -0
  57. package/dist/components/chip/snice-chip.js +203 -0
  58. package/dist/components/chip/snice-chip.js.map +1 -0
  59. package/dist/components/chip/snice-chip.types.d.ts +14 -0
  60. package/dist/components/chip/snice-chip.types.js +2 -0
  61. package/dist/components/chip/snice-chip.types.js.map +1 -0
  62. package/dist/components/date-picker/snice-date-picker.d.ts +82 -0
  63. package/dist/components/date-picker/snice-date-picker.js +880 -0
  64. package/dist/components/date-picker/snice-date-picker.js.map +1 -0
  65. package/dist/components/date-picker/snice-date-picker.types.d.ts +71 -0
  66. package/dist/components/date-picker/snice-date-picker.types.js +2 -0
  67. package/dist/components/date-picker/snice-date-picker.types.js.map +1 -0
  68. package/dist/components/divider/snice-divider.d.ts +17 -0
  69. package/dist/components/divider/snice-divider.js +111 -0
  70. package/dist/components/divider/snice-divider.js.map +1 -0
  71. package/dist/components/divider/snice-divider.types.d.ts +14 -0
  72. package/dist/components/divider/snice-divider.types.js +2 -0
  73. package/dist/components/divider/snice-divider.types.js.map +1 -0
  74. package/dist/components/drawer/snice-drawer.d.ts +37 -0
  75. package/dist/components/drawer/snice-drawer.js +335 -0
  76. package/dist/components/drawer/snice-drawer.js.map +1 -0
  77. package/dist/components/drawer/snice-drawer.types.d.ts +16 -0
  78. package/dist/components/drawer/snice-drawer.types.js +2 -0
  79. package/dist/components/drawer/snice-drawer.types.js.map +1 -0
  80. package/dist/components/input/snice-input.d.ts +65 -0
  81. package/dist/components/input/snice-input.js +603 -0
  82. package/dist/components/input/snice-input.js.map +1 -0
  83. package/dist/components/input/snice-input.types.d.ts +53 -0
  84. package/dist/components/input/snice-input.types.js +2 -0
  85. package/dist/components/input/snice-input.types.js.map +1 -0
  86. package/dist/components/layout/snice-layout-blog.d.ts +4 -0
  87. package/dist/components/layout/snice-layout-blog.js +56 -0
  88. package/dist/components/layout/snice-layout-blog.js.map +1 -0
  89. package/dist/components/layout/snice-layout-card.d.ts +6 -0
  90. package/dist/components/layout/snice-layout-card.js +53 -0
  91. package/dist/components/layout/snice-layout-card.js.map +1 -0
  92. package/dist/components/layout/snice-layout-centered.d.ts +5 -0
  93. package/dist/components/layout/snice-layout-centered.js +38 -0
  94. package/dist/components/layout/snice-layout-centered.js.map +1 -0
  95. package/dist/components/layout/snice-layout-dashboard.d.ts +4 -0
  96. package/dist/components/layout/snice-layout-dashboard.js +53 -0
  97. package/dist/components/layout/snice-layout-dashboard.js.map +1 -0
  98. package/dist/components/layout/snice-layout-fullscreen.d.ts +5 -0
  99. package/dist/components/layout/snice-layout-fullscreen.js +50 -0
  100. package/dist/components/layout/snice-layout-fullscreen.js.map +1 -0
  101. package/dist/components/layout/snice-layout-landing.d.ts +4 -0
  102. package/dist/components/layout/snice-layout-landing.js +55 -0
  103. package/dist/components/layout/snice-layout-landing.js.map +1 -0
  104. package/dist/components/layout/snice-layout-minimal.d.ts +4 -0
  105. package/dist/components/layout/snice-layout-minimal.js +27 -0
  106. package/dist/components/layout/snice-layout-minimal.js.map +1 -0
  107. package/dist/components/layout/snice-layout-sidebar.d.ts +5 -0
  108. package/dist/components/layout/snice-layout-sidebar.js +64 -0
  109. package/dist/components/layout/snice-layout-sidebar.js.map +1 -0
  110. package/dist/components/layout/snice-layout-split.d.ts +6 -0
  111. package/dist/components/layout/snice-layout-split.js +47 -0
  112. package/dist/components/layout/snice-layout-split.js.map +1 -0
  113. package/dist/components/layout/snice-layout.d.ts +4 -0
  114. package/dist/components/layout/snice-layout.js +43 -0
  115. package/dist/components/layout/snice-layout.js.map +1 -0
  116. package/dist/components/layout/snice-layout.types.d.ts +3 -0
  117. package/dist/components/layout/snice-layout.types.js +2 -0
  118. package/dist/components/layout/snice-layout.types.js.map +1 -0
  119. package/dist/components/login/snice-login.d.ts +45 -0
  120. package/dist/components/login/snice-login.js +385 -0
  121. package/dist/components/login/snice-login.js.map +1 -0
  122. package/dist/components/login/snice-login.types.d.ts +31 -0
  123. package/dist/components/login/snice-login.types.js +2 -0
  124. package/dist/components/login/snice-login.types.js.map +1 -0
  125. package/dist/components/modal/snice-modal.d.ts +32 -0
  126. package/dist/components/modal/snice-modal.js +288 -0
  127. package/dist/components/modal/snice-modal.js.map +1 -0
  128. package/dist/components/modal/snice-modal.types.d.ts +18 -0
  129. package/dist/components/modal/snice-modal.types.js +2 -0
  130. package/dist/components/modal/snice-modal.types.js.map +1 -0
  131. package/dist/components/pagination/snice-pagination.d.ts +26 -0
  132. package/dist/components/pagination/snice-pagination.js +373 -0
  133. package/dist/components/pagination/snice-pagination.js.map +1 -0
  134. package/dist/components/pagination/snice-pagination.types.d.ts +18 -0
  135. package/dist/components/pagination/snice-pagination.types.js +2 -0
  136. package/dist/components/pagination/snice-pagination.types.js.map +1 -0
  137. package/dist/components/progress/snice-progress.d.ts +35 -0
  138. package/dist/components/progress/snice-progress.js +295 -0
  139. package/dist/components/progress/snice-progress.js.map +1 -0
  140. package/dist/components/progress/snice-progress.types.d.ts +18 -0
  141. package/dist/components/progress/snice-progress.types.js +2 -0
  142. package/dist/components/progress/snice-progress.types.js.map +1 -0
  143. package/dist/components/radio/snice-radio.d.ts +33 -0
  144. package/dist/components/radio/snice-radio.js +286 -0
  145. package/dist/components/radio/snice-radio.js.map +1 -0
  146. package/dist/components/radio/snice-radio.types.d.ts +19 -0
  147. package/dist/components/radio/snice-radio.types.js +2 -0
  148. package/dist/components/radio/snice-radio.types.js.map +1 -0
  149. package/dist/components/select/snice-option.d.ts +17 -0
  150. package/dist/components/select/snice-option.js +77 -0
  151. package/dist/components/select/snice-option.js.map +1 -0
  152. package/dist/components/select/snice-option.types.d.ts +14 -0
  153. package/dist/components/select/snice-option.types.js +2 -0
  154. package/dist/components/select/snice-option.types.js.map +1 -0
  155. package/dist/components/select/snice-select.d.ts +89 -0
  156. package/dist/components/select/snice-select.js +900 -0
  157. package/dist/components/select/snice-select.js.map +1 -0
  158. package/dist/components/select/snice-select.types.d.ts +49 -0
  159. package/dist/components/select/snice-select.types.js +2 -0
  160. package/dist/components/select/snice-select.types.js.map +1 -0
  161. package/dist/components/skeleton/snice-skeleton.d.ts +16 -0
  162. package/dist/components/skeleton/snice-skeleton.js +159 -0
  163. package/dist/components/skeleton/snice-skeleton.js.map +1 -0
  164. package/dist/components/skeleton/snice-skeleton.types.d.ts +10 -0
  165. package/dist/components/skeleton/snice-skeleton.types.js +2 -0
  166. package/dist/components/skeleton/snice-skeleton.types.js.map +1 -0
  167. package/dist/components/switch/snice-switch.d.ts +38 -0
  168. package/dist/components/switch/snice-switch.js +309 -0
  169. package/dist/components/switch/snice-switch.js.map +1 -0
  170. package/dist/components/switch/snice-switch.types.d.ts +21 -0
  171. package/dist/components/switch/snice-switch.types.js +2 -0
  172. package/dist/components/switch/snice-switch.types.js.map +1 -0
  173. package/dist/components/symbols.d.ts +1 -0
  174. package/dist/components/symbols.js +20 -0
  175. package/dist/components/symbols.js.map +1 -0
  176. package/dist/components/table/snice-cell-boolean.d.ts +21 -0
  177. package/dist/components/table/snice-cell-boolean.js +152 -0
  178. package/dist/components/table/snice-cell-boolean.js.map +1 -0
  179. package/dist/components/table/snice-cell-date.d.ts +24 -0
  180. package/dist/components/table/snice-cell-date.js +240 -0
  181. package/dist/components/table/snice-cell-date.js.map +1 -0
  182. package/dist/components/table/snice-cell-duration.d.ts +16 -0
  183. package/dist/components/table/snice-cell-duration.js +123 -0
  184. package/dist/components/table/snice-cell-duration.js.map +1 -0
  185. package/dist/components/table/snice-cell-filesize.d.ts +16 -0
  186. package/dist/components/table/snice-cell-filesize.js +119 -0
  187. package/dist/components/table/snice-cell-filesize.js.map +1 -0
  188. package/dist/components/table/snice-cell-number.d.ts +23 -0
  189. package/dist/components/table/snice-cell-number.js +202 -0
  190. package/dist/components/table/snice-cell-number.js.map +1 -0
  191. package/dist/components/table/snice-cell-progress.d.ts +17 -0
  192. package/dist/components/table/snice-cell-progress.js +114 -0
  193. package/dist/components/table/snice-cell-progress.js.map +1 -0
  194. package/dist/components/table/snice-cell-rating.d.ts +17 -0
  195. package/dist/components/table/snice-cell-rating.js +113 -0
  196. package/dist/components/table/snice-cell-rating.js.map +1 -0
  197. package/dist/components/table/snice-cell-sparkline.d.ts +29 -0
  198. package/dist/components/table/snice-cell-sparkline.js +290 -0
  199. package/dist/components/table/snice-cell-sparkline.js.map +1 -0
  200. package/dist/components/table/snice-cell-text.d.ts +19 -0
  201. package/dist/components/table/snice-cell-text.js +153 -0
  202. package/dist/components/table/snice-cell-text.js.map +1 -0
  203. package/dist/components/table/snice-cell.d.ts +32 -0
  204. package/dist/components/table/snice-cell.js +451 -0
  205. package/dist/components/table/snice-cell.js.map +1 -0
  206. package/dist/components/table/snice-column.d.ts +62 -0
  207. package/dist/components/table/snice-column.js +440 -0
  208. package/dist/components/table/snice-column.js.map +1 -0
  209. package/dist/components/table/snice-header.d.ts +33 -0
  210. package/dist/components/table/snice-header.js +303 -0
  211. package/dist/components/table/snice-header.js.map +1 -0
  212. package/dist/components/table/snice-progress.d.ts +10 -0
  213. package/dist/components/table/snice-progress.js +91 -0
  214. package/dist/components/table/snice-progress.js.map +1 -0
  215. package/dist/components/table/snice-rating.d.ts +9 -0
  216. package/dist/components/table/snice-rating.js +68 -0
  217. package/dist/components/table/snice-rating.js.map +1 -0
  218. package/dist/components/table/snice-row.d.ts +43 -0
  219. package/dist/components/table/snice-row.js +365 -0
  220. package/dist/components/table/snice-row.js.map +1 -0
  221. package/dist/components/table/snice-table.d.ts +69 -0
  222. package/dist/components/table/snice-table.js +814 -0
  223. package/dist/components/table/snice-table.js.map +1 -0
  224. package/dist/components/table/snice-table.types.d.ts +137 -0
  225. package/dist/components/table/snice-table.types.js +2 -0
  226. package/dist/components/table/snice-table.types.js.map +1 -0
  227. package/dist/components/tabs/snice-tab-panel.d.ts +12 -0
  228. package/dist/components/tabs/snice-tab-panel.js +78 -0
  229. package/dist/components/tabs/snice-tab-panel.js.map +1 -0
  230. package/dist/components/tabs/snice-tab.d.ts +13 -0
  231. package/dist/components/tabs/snice-tab.js +90 -0
  232. package/dist/components/tabs/snice-tab.js.map +1 -0
  233. package/dist/components/tabs/snice-tabs.d.ts +34 -0
  234. package/dist/components/tabs/snice-tabs.js +367 -0
  235. package/dist/components/tabs/snice-tabs.js.map +1 -0
  236. package/dist/components/tabs/snice-tabs.types.d.ts +23 -0
  237. package/dist/components/tabs/snice-tabs.types.js +2 -0
  238. package/dist/components/tabs/snice-tabs.types.js.map +1 -0
  239. package/dist/components/toast/snice-toast-container.d.ts +25 -0
  240. package/dist/components/toast/snice-toast-container.js +251 -0
  241. package/dist/components/toast/snice-toast-container.js.map +1 -0
  242. package/dist/components/toast/snice-toast.d.ts +23 -0
  243. package/dist/components/toast/snice-toast.js +316 -0
  244. package/dist/components/toast/snice-toast.js.map +1 -0
  245. package/dist/components/toast/snice-toast.types.d.ts +30 -0
  246. package/dist/components/toast/snice-toast.types.js +2 -0
  247. package/dist/components/toast/snice-toast.types.js.map +1 -0
  248. package/dist/components/tooltip/snice-tooltip.d.ts +50 -0
  249. package/dist/components/tooltip/snice-tooltip.js +656 -0
  250. package/dist/components/tooltip/snice-tooltip.js.map +1 -0
  251. package/dist/components/tooltip/snice-tooltip.types.d.ts +18 -0
  252. package/dist/components/tooltip/snice-tooltip.types.js +2 -0
  253. package/dist/components/tooltip/snice-tooltip.types.js.map +1 -0
  254. package/dist/components/transitions.d.ts +11 -0
  255. package/dist/components/transitions.js +69 -0
  256. package/dist/components/transitions.js.map +1 -0
  257. package/dist/src/controller.d.ts +61 -0
  258. package/dist/src/controller.js +297 -0
  259. package/dist/src/controller.js.map +1 -0
  260. package/dist/src/element.d.ts +77 -0
  261. package/dist/src/element.js +805 -0
  262. package/dist/src/element.js.map +1 -0
  263. package/dist/src/events.d.ts +37 -0
  264. package/dist/src/events.js +289 -0
  265. package/dist/src/events.js.map +1 -0
  266. package/dist/src/global.d.ts +7 -0
  267. package/dist/src/global.js +23 -0
  268. package/dist/src/global.js.map +1 -0
  269. package/{src/index.ts → dist/src/index.d.ts} +1 -1
  270. package/dist/src/index.js +8 -0
  271. package/dist/src/index.js.map +1 -0
  272. package/dist/src/observe.d.ts +26 -0
  273. package/dist/src/observe.js +329 -0
  274. package/dist/src/observe.js.map +1 -0
  275. package/dist/src/request-response.d.ts +46 -0
  276. package/dist/src/request-response.js +267 -0
  277. package/dist/src/request-response.js.map +1 -0
  278. package/dist/src/router.d.ts +87 -0
  279. package/dist/src/router.js +375 -0
  280. package/dist/src/router.js.map +1 -0
  281. package/dist/src/symbols.d.ts +29 -0
  282. package/{src/symbols.ts → dist/src/symbols.js} +2 -12
  283. package/dist/src/symbols.js.map +1 -0
  284. package/dist/src/transitions.d.ts +50 -0
  285. package/dist/src/transitions.js +199 -0
  286. package/dist/src/transitions.js.map +1 -0
  287. package/package.json +6 -8
  288. package/src/controller.ts +0 -347
  289. package/src/element.ts +0 -897
  290. package/src/events.ts +0 -349
  291. package/src/global.ts +0 -31
  292. package/src/observe.ts +0 -414
  293. package/src/request-response.ts +0 -336
  294. package/src/router.ts +0 -552
  295. package/src/transitions.ts +0 -264
package/src/router.ts DELETED
@@ -1,552 +0,0 @@
1
- import Route from 'route-parser';
2
- import { applyElementFunctionality } from './element';
3
- import { ROUTER_CONTEXT, CONTEXT_REQUEST_HANDLER, PAGE_TRANSITION, CREATED_AT } from './symbols';
4
- import { Transition, performTransition as performTransitionUtil } from './transitions';
5
-
6
- /**
7
- * Route parameters extracted from the URL
8
- */
9
- export type RouteParams = Record<string, string>;
10
-
11
- /**
12
- * Possible outcomes from route resolution
13
- */
14
- enum RouteResult {
15
- SUCCESS = 'success',
16
- GUARDS_FAILED = 'guards-failed',
17
- NOT_FOUND = 'not-found'
18
- }
19
-
20
- /**
21
- * Guard function that determines if navigation is allowed
22
- * @param context The application context
23
- * @param params The URL parameters from the route
24
- */
25
- export type Guard<T = any> = (context: T, params: RouteParams) => boolean | Promise<boolean>;
26
-
27
- export interface RouterOptions {
28
- /**
29
- * The target element selector where the page element will be instantiated.
30
- * The router will use this selector to find the target element, clear it, and append the page element to it.
31
- */
32
- target: string;
33
-
34
- /**
35
- * Whether to use hash routing or push state routing.
36
- */
37
- type: 'hash' | 'pushstate';
38
-
39
- /**
40
- * Override for the window object to use for routing, defaults to global.
41
- */
42
- window?: Window;
43
-
44
- /**
45
- * Override for the document object to use for routing, defaults to global.
46
- */
47
- document?: Document;
48
-
49
- /**
50
- * Global transition configuration for all pages
51
- */
52
- transition?: Transition;
53
-
54
- /**
55
- * Optional context object passed to guard functions
56
- */
57
- context?: any;
58
-
59
- /**
60
- * Default layout element tag name for all pages
61
- */
62
- layout?: string;
63
- }
64
-
65
- export interface PageOptions {
66
- /**
67
- * The tag name of the custom element.
68
- * @example { tag: 'login-page' }
69
- * // for <login-page></login-page>
70
- */
71
- tag: string;
72
-
73
- /**
74
- * The routes that will trigger the page element.
75
- * @example { routes: ['/login', '/login/:id'] }
76
- */
77
- routes: string[];
78
-
79
- /**
80
- * Optional per-page transition override
81
- */
82
- transition?: Transition;
83
-
84
- /**
85
- * Guard functions that must pass for navigation to proceed.
86
- * Can be a single guard or an array of guards (all must pass).
87
- */
88
- guards?: Guard<any> | Guard<any>[];
89
-
90
- /**
91
- * Layout element tag name for this page.
92
- * Use false to explicitly disable layout for this page.
93
- */
94
- layout?: string | false;
95
- }
96
-
97
- /**
98
- * Router return type
99
- */
100
- export interface RouterInstance {
101
- page: (pageOptions: PageOptions) => <C extends { new(...args: any[]): HTMLElement }>(constructor: C) => void;
102
- initialize: () => void;
103
- navigate: (path: string) => Promise<void>;
104
- register: (route: string, tag: string, transition?: Transition, guards?: Guard<any> | Guard<any>[]) => void;
105
- context: any;
106
- }
107
-
108
- /**
109
- * Creates a new router instance.
110
- * @param {RouterOptions} options - The router configuration options.
111
- * @returns An object containing the router's API methods.
112
- */
113
- export function Router(options: RouterOptions): RouterInstance {
114
- const routes: { route: Route, tag: string, transition?: Transition, guards?: Guard<any> | Guard<any>[], layout?: string | false }[] = [];
115
- let is_sorted = false;
116
-
117
- let _404: string; // the 404 page
118
- let _403: string; // the 403 forbidden page
119
- let home: string; // the home page
120
- let currentLayoutName: string | null = null; // Track current layout name
121
- let currentLayoutTimestamp: number | null = null; // Track current layout timestamp
122
- const context = options.context || {}; // Store context for guards
123
-
124
- function getCurrentLayoutElement(target: Element): HTMLElement | null {
125
- const noCurrentLayout = !currentLayoutName || !currentLayoutTimestamp;
126
- if (noCurrentLayout) {
127
- return null;
128
- }
129
-
130
- const layoutElements = target.querySelectorAll(currentLayoutName!) as NodeListOf<HTMLElement>;
131
-
132
- for (const element of layoutElements) {
133
- const hasTimestamp = (element as any)[CREATED_AT] === currentLayoutTimestamp;
134
- if (hasTimestamp) {
135
- return element;
136
- }
137
- }
138
-
139
- return null;
140
- }
141
-
142
- /**
143
- * Decorator function for defining a page with associated routes.
144
- * @param {PageOptions} pageOptions - The page configuration options.
145
- * @returns A decorator function to apply to a custom element class.
146
- */
147
- function page(pageOptions: PageOptions) {
148
- return function <C extends { new(...args: any[]): HTMLElement }>(constructor: C) {
149
- // Apply all element functionality (properties, queries, watchers, controllers, etc.)
150
- applyElementFunctionality(constructor);
151
-
152
- // Store transition config on constructor for later use
153
- (constructor as any)[PAGE_TRANSITION] = pageOptions.transition;
154
-
155
- // Extend the connectedCallback to add router-specific functionality
156
- const elementConnectedCallback = constructor.prototype.connectedCallback;
157
- constructor.prototype.connectedCallback = function() {
158
- // Call the element's connectedCallback first
159
- elementConnectedCallback?.call(this);
160
-
161
- // Setup context request handler for nested elements
162
- const contextRequestHandler = (event: any) => {
163
- // Only respond if this element has context
164
- if (this[ROUTER_CONTEXT] !== undefined) {
165
- event.detail.context = this[ROUTER_CONTEXT];
166
- event.stopPropagation(); // Stop bubbling once context is provided
167
- }
168
- };
169
- this.addEventListener('@context/request', contextRequestHandler);
170
-
171
- // Store handler for cleanup
172
- (this as any)[CONTEXT_REQUEST_HANDLER] = contextRequestHandler;
173
- };
174
-
175
- // Extend the disconnectedCallback to clean up router-specific stuff
176
- const elementDisconnectedCallback = constructor.prototype.disconnectedCallback;
177
- constructor.prototype.disconnectedCallback = function() {
178
- // Call element's disconnectedCallback first
179
- elementDisconnectedCallback?.call(this);
180
-
181
- // Clean up context request handler
182
- const handler = (this as any)[CONTEXT_REQUEST_HANDLER];
183
- if (handler) {
184
- this.removeEventListener('@context/request', handler);
185
- delete (this as any)[CONTEXT_REQUEST_HANDLER];
186
- }
187
-
188
- // Clean up context reference
189
- delete (this as any)[ROUTER_CONTEXT];
190
- };
191
-
192
- // Define the custom element
193
- customElements.define(pageOptions.tag, constructor);
194
-
195
- // Register the routes with guards and layout
196
- pageOptions.routes.forEach(route => register(route, pageOptions.tag, pageOptions.transition, pageOptions.guards, pageOptions.layout));
197
- }
198
- }
199
-
200
- /**
201
- * Registers a new route with the router.
202
- * @param {string} route - The route path.
203
- * @param {string} tag - The custom element tag associated with the route.
204
- * @example
205
- * register('/custom-route', 'custom-element');
206
- */
207
- function register(route: string, tag: string, transition?: Transition, guards?: Guard<any> | Guard<any>[], layout?: string | false): void {
208
- routes.push({ route: new Route(route), tag, transition, guards, layout });
209
- is_sorted = false;
210
-
211
- if (route === '/404') {
212
- _404 = tag;
213
- }
214
-
215
- if (route === '/403') {
216
- _403 = tag;
217
- }
218
-
219
- if (route === '/') {
220
- home = tag;
221
- }
222
- }
223
-
224
- function setupEventListeners(): void {
225
- const isHashType = options.type === 'hash';
226
- const isPushStateType = options.type === 'pushstate';
227
-
228
- if (isHashType) {
229
- window.addEventListener('hashchange', () => {
230
- const targetExists = !!document.querySelector(options.target);
231
- if (!targetExists) {
232
- return;
233
- }
234
-
235
- const path = getPath();
236
- navigate(path);
237
- });
238
- }
239
-
240
- if (isPushStateType) {
241
- window.addEventListener('popstate', () => {
242
- const targetExists = !!document.querySelector(options.target);
243
- if (!targetExists) {
244
- return;
245
- }
246
-
247
- const path = getPath();
248
- navigate(path);
249
- });
250
- }
251
- }
252
-
253
- /**
254
- * Initializes the router and sets up navigation event listeners.
255
- * @example
256
- * initialize();
257
- */
258
- function initialize(): void {
259
- const targetExists = !!document.querySelector(options.target);
260
- if (!targetExists) {
261
- throw new Error(`Target element not found: ${options.target}`);
262
- }
263
-
264
- const needsSorting = !is_sorted;
265
- if (needsSorting) {
266
- routes.sort((a: any, b: any) => b.route.spec.length - a.route.spec.length);
267
- is_sorted = true;
268
- }
269
-
270
- setupEventListeners();
271
-
272
- const path = getPath();
273
- navigate(path);
274
- }
275
-
276
- function getPath(): string {
277
- switch (options.type) {
278
- case 'hash':
279
- return window.location.hash.slice(1);
280
- case 'pushstate':
281
- return window.location.pathname;
282
- }
283
- }
284
-
285
- async function renderForbiddenPage(target: Element): Promise<void> {
286
- let newPageElement: HTMLElement;
287
- const has403Page = !!_403;
288
-
289
- if (has403Page) {
290
- newPageElement = document.createElement(_403);
291
- (newPageElement as any)[ROUTER_CONTEXT] = context;
292
- }
293
- if (!has403Page) {
294
- const div = document.createElement('div');
295
- div.className = 'default-403';
296
- div.innerHTML = /*html*/`<h1>403</h1><p>Unauthorized</p>`;
297
- newPageElement = div;
298
- }
299
-
300
- target.innerHTML = '';
301
- target.appendChild(newPageElement!);
302
- currentLayoutName = null;
303
- currentLayoutTimestamp = null;
304
- }
305
-
306
- async function checkGuards(guards: Guard<any> | Guard<any>[] | undefined, params: RouteParams, target: Element): Promise<boolean> {
307
- const hasGuards = !!guards;
308
- if (!hasGuards) {
309
- return true;
310
- }
311
-
312
- const guardsArray = Array.isArray(guards) ? guards : [guards];
313
- for (const guard of guardsArray) {
314
- const allowed = await guard(context, params);
315
- if (!allowed) {
316
- await renderForbiddenPage(target);
317
- return false;
318
- }
319
- }
320
- return true;
321
- }
322
-
323
- function createHomeElement(): { element: HTMLElement; transition?: Transition; layout?: string | false } {
324
- const newPageElement = document.createElement(home);
325
- (newPageElement as any)[ROUTER_CONTEXT] = context;
326
- const constructor = customElements.get(home);
327
- const transition = (constructor as any)?.[PAGE_TRANSITION];
328
-
329
- const homeRoute = routes.find(r => r.route.match('/'));
330
- return { element: newPageElement, transition, layout: homeRoute?.layout };
331
- }
332
-
333
- function create404Element(): { element: HTMLElement; transition?: Transition; layout?: string | false } {
334
- const has404Page = !!_404;
335
-
336
- if (has404Page) {
337
- const newPageElement = document.createElement(_404);
338
- (newPageElement as any)[ROUTER_CONTEXT] = context;
339
- const constructor = customElements.get(_404);
340
- const transition = (constructor as any)?.[PAGE_TRANSITION];
341
- return { element: newPageElement, transition, layout: undefined };
342
- }
343
-
344
- const div = document.createElement('div');
345
- div.className = 'default-404';
346
- div.innerHTML = /*html*/`<h1>404</h1><p>Page not found</p>`;
347
- return { element: div, transition: undefined, layout: undefined };
348
- }
349
-
350
- async function resolveRoute(path: string, target: Element): Promise<{ result: RouteResult; element?: HTMLElement; transition?: Transition; layout?: string | false }> {
351
- for (const route of routes) {
352
- const params = route.route.match(path);
353
- const isMatch = params !== false;
354
- if (!isMatch) {
355
- continue;
356
- }
357
-
358
- const guardsAllowed = await checkGuards(route.guards, params as RouteParams, target);
359
- if (!guardsAllowed) {
360
- return { result: RouteResult.GUARDS_FAILED };
361
- }
362
-
363
- const newPageElement = document.createElement(route.tag);
364
- (newPageElement as any)[ROUTER_CONTEXT] = context;
365
- const routeParams = params as RouteParams;
366
- Object.keys(routeParams).forEach(key => newPageElement.setAttribute(key, routeParams[key]));
367
-
368
- return { result: RouteResult.SUCCESS, element: newPageElement, transition: route.transition, layout: route.layout };
369
- }
370
-
371
- return { result: RouteResult.NOT_FOUND };
372
- }
373
-
374
- function determineLayout(pageLayout: string | false | undefined): string | null {
375
- const isExplicitlyNoLayout = pageLayout === false;
376
- if (isExplicitlyNoLayout) {
377
- return null;
378
- }
379
-
380
- const hasPageLayout = !!pageLayout;
381
- if (hasPageLayout) {
382
- return pageLayout;
383
- }
384
-
385
- const hasRouterLayout = !!options.layout;
386
- if (hasRouterLayout) {
387
- return options.layout!;
388
- }
389
-
390
- return null;
391
- }
392
-
393
- function setupLayout(layoutToUse: string | null): { element: HTMLElement | null; needsNewLayout: boolean } {
394
- const needsNewLayout = layoutToUse !== currentLayoutName;
395
- if (!needsNewLayout) {
396
- return { element: null, needsNewLayout: false };
397
- }
398
-
399
- currentLayoutName = layoutToUse;
400
-
401
- const shouldCreateLayout = !!layoutToUse;
402
- if (shouldCreateLayout) {
403
- const timestamp = Date.now();
404
- currentLayoutTimestamp = timestamp;
405
-
406
- const layoutElement = document.createElement(layoutToUse);
407
- (layoutElement as any)[ROUTER_CONTEXT] = context;
408
- (layoutElement as any)[CREATED_AT] = timestamp;
409
-
410
- return { element: layoutElement, needsNewLayout: true };
411
- }
412
-
413
- currentLayoutTimestamp = null;
414
- return { element: null, needsNewLayout: true };
415
- }
416
-
417
- async function renderWithLayout(target: Element, pageElement: HTMLElement, transition: Transition | undefined, layoutElement: HTMLElement | null, needsNewLayout: boolean): Promise<void> {
418
- const currentLayout = layoutElement || getCurrentLayoutElement(target);
419
- if (!currentLayout) {
420
- return;
421
- }
422
-
423
- const oldPageInLayout = currentLayout.querySelector('[slot="page"]') as HTMLElement | null;
424
- const shouldTransition = !!(transition && oldPageInLayout);
425
-
426
- if (shouldTransition) {
427
- pageElement.setAttribute('slot', 'page');
428
- await performTransition(currentLayout, oldPageInLayout!, pageElement, transition!);
429
- if (needsNewLayout) {
430
- target.innerHTML = '';
431
- target.appendChild(currentLayout);
432
- }
433
- return;
434
- }
435
-
436
- const existingPages = currentLayout.querySelectorAll('[slot="page"]');
437
- existingPages.forEach(page => page.remove());
438
- pageElement.setAttribute('slot', 'page');
439
- currentLayout.appendChild(pageElement);
440
-
441
- if (needsNewLayout) {
442
- target.innerHTML = '';
443
- target.appendChild(currentLayout);
444
- }
445
- }
446
-
447
- async function renderDirect(target: Element, pageElement: HTMLElement, transition: Transition | undefined): Promise<void> {
448
- const currentElementInTarget = target.children[0] as HTMLElement | null;
449
- const shouldTransition = !!(transition && currentElementInTarget);
450
-
451
- if (shouldTransition) {
452
- await performTransition(target, currentElementInTarget!, pageElement, transition!);
453
- return;
454
- }
455
-
456
- target.innerHTML = '';
457
- target.appendChild(pageElement);
458
- }
459
-
460
- /**
461
- * Navigates to the specified path.
462
- * @param {string} path - The path to navigate to.
463
- * @example
464
- * navigate('/login');
465
- */
466
- async function navigate(path: string): Promise<void> {
467
- const target = document.querySelector(options.target);
468
- if (!target) {
469
- throw new Error(`Target element not found: ${options.target}`);
470
- }
471
-
472
- window.scrollTo(0, 0);
473
-
474
- const isHomePath = (path.trim() === '' || path === '/') && !!home;
475
-
476
- if (isHomePath) {
477
- const homeRoute = routes.find(r => r.route.match('/'));
478
- const guardsAllowed = await checkGuards(homeRoute?.guards, {}, target);
479
- if (!guardsAllowed) {
480
- return;
481
- }
482
-
483
- const { element, transition, layout } = createHomeElement();
484
- const layoutToUse = determineLayout(layout);
485
- const { element: layoutElement, needsNewLayout } = setupLayout(layoutToUse);
486
- const finalTransition = transition || options.transition;
487
-
488
- const hasLayout = layoutElement !== null || getCurrentLayoutElement(target) !== null;
489
- if (hasLayout) {
490
- await renderWithLayout(target, element, finalTransition, layoutElement, needsNewLayout);
491
- return;
492
- }
493
-
494
- await renderDirect(target, element, finalTransition);
495
- return;
496
- }
497
-
498
- const routeResult = await resolveRoute(path, target);
499
-
500
- const isGuardsFailed = routeResult.result === RouteResult.GUARDS_FAILED;
501
- if (isGuardsFailed) {
502
- return;
503
- }
504
-
505
- const isSuccess = routeResult.result === RouteResult.SUCCESS;
506
- if (isSuccess) {
507
- const { element, transition, layout } = routeResult;
508
- const layoutToUse = determineLayout(layout);
509
- const { element: layoutElement, needsNewLayout } = setupLayout(layoutToUse);
510
- const finalTransition = transition || options.transition;
511
-
512
- const hasLayout = layoutElement !== null || getCurrentLayoutElement(target) !== null;
513
- if (hasLayout) {
514
- await renderWithLayout(target, element!, finalTransition, layoutElement, needsNewLayout);
515
- return;
516
- }
517
-
518
- await renderDirect(target, element!, finalTransition);
519
- return;
520
- }
521
-
522
- const { element, transition, layout } = create404Element();
523
- const layoutToUse = determineLayout(layout);
524
- const { element: layoutElement, needsNewLayout } = setupLayout(layoutToUse);
525
- const finalTransition = transition || options.transition;
526
-
527
- const hasLayout = layoutElement !== null || getCurrentLayoutElement(target) !== null;
528
- if (hasLayout) {
529
- await renderWithLayout(target, element, finalTransition, layoutElement, needsNewLayout);
530
- return;
531
- }
532
-
533
- await renderDirect(target, element, finalTransition);
534
- }
535
-
536
- async function performTransition(
537
- container: Element,
538
- oldElement: HTMLElement,
539
- newElement: HTMLElement,
540
- transition: Transition
541
- ): Promise<void> {
542
- return performTransitionUtil(container, oldElement, newElement, transition);
543
- }
544
-
545
- return {
546
- page,
547
- initialize,
548
- navigate,
549
- register,
550
- context,
551
- };
552
- }