@elurjs/ionic 1.6.1

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 (388) hide show
  1. package/CHANGELOG.md +287 -0
  2. package/MIGRATION.md +221 -0
  3. package/README.md +695 -0
  4. package/dist/lib/IonRouterOutlet.d.ts +154 -0
  5. package/dist/lib/__tests__/IonRouterOutlet.test.d.ts +1 -0
  6. package/dist/lib/__tests__/bundles.test.d.ts +1 -0
  7. package/dist/lib/__tests__/cache-policy.test.d.ts +1 -0
  8. package/dist/lib/__tests__/capacitor.test.d.ts +1 -0
  9. package/dist/lib/__tests__/components.test.d.ts +1 -0
  10. package/dist/lib/__tests__/devtools.test.d.ts +1 -0
  11. package/dist/lib/__tests__/lifecycle.test.d.ts +1 -0
  12. package/dist/lib/__tests__/mocks/ionic.d.ts +61 -0
  13. package/dist/lib/__tests__/navigation.test.d.ts +1 -0
  14. package/dist/lib/__tests__/overlays.test.d.ts +1 -0
  15. package/dist/lib/__tests__/page-state.test.d.ts +1 -0
  16. package/dist/lib/__tests__/phase0-bugs.test.d.ts +1 -0
  17. package/dist/lib/__tests__/setup.d.ts +1 -0
  18. package/dist/lib/__tests__/setup.test.d.ts +1 -0
  19. package/dist/lib/__tests__/tabs.test.d.ts +1 -0
  20. package/dist/lib/__tests__/vite-plugin.test.d.ts +1 -0
  21. package/dist/lib/bundles/all.cjs +2 -0
  22. package/dist/lib/bundles/all.cjs.map +1 -0
  23. package/dist/lib/bundles/all.d.ts +16 -0
  24. package/dist/lib/bundles/all.js +21 -0
  25. package/dist/lib/bundles/all.js.map +1 -0
  26. package/dist/lib/bundles/buttons.cjs +2 -0
  27. package/dist/lib/bundles/buttons.cjs.map +1 -0
  28. package/dist/lib/bundles/buttons.d.ts +7 -0
  29. package/dist/lib/bundles/buttons.js +17 -0
  30. package/dist/lib/bundles/buttons.js.map +1 -0
  31. package/dist/lib/bundles/feedback.cjs +2 -0
  32. package/dist/lib/bundles/feedback.cjs.map +1 -0
  33. package/dist/lib/bundles/feedback.d.ts +8 -0
  34. package/dist/lib/bundles/feedback.js +19 -0
  35. package/dist/lib/bundles/feedback.js.map +1 -0
  36. package/dist/lib/bundles/forms.cjs +2 -0
  37. package/dist/lib/bundles/forms.cjs.map +1 -0
  38. package/dist/lib/bundles/forms.d.ts +11 -0
  39. package/dist/lib/bundles/forms.js +47 -0
  40. package/dist/lib/bundles/forms.js.map +1 -0
  41. package/dist/lib/bundles/layout.cjs +2 -0
  42. package/dist/lib/bundles/layout.cjs.map +1 -0
  43. package/dist/lib/bundles/layout.d.ts +9 -0
  44. package/dist/lib/bundles/layout.js +33 -0
  45. package/dist/lib/bundles/layout.js.map +1 -0
  46. package/dist/lib/bundles/lists.cjs +2 -0
  47. package/dist/lib/bundles/lists.cjs.map +1 -0
  48. package/dist/lib/bundles/lists.d.ts +15 -0
  49. package/dist/lib/bundles/lists.js +65 -0
  50. package/dist/lib/bundles/lists.js.map +1 -0
  51. package/dist/lib/bundles/navigation.cjs +2 -0
  52. package/dist/lib/bundles/navigation.cjs.map +1 -0
  53. package/dist/lib/bundles/navigation.d.ts +9 -0
  54. package/dist/lib/bundles/navigation.js +29 -0
  55. package/dist/lib/bundles/navigation.js.map +1 -0
  56. package/dist/lib/bundles/overlays.cjs +2 -0
  57. package/dist/lib/bundles/overlays.cjs.map +1 -0
  58. package/dist/lib/bundles/overlays.d.ts +9 -0
  59. package/dist/lib/bundles/overlays.js +25 -0
  60. package/dist/lib/bundles/overlays.js.map +1 -0
  61. package/dist/lib/capacitor.cjs +2 -0
  62. package/dist/lib/capacitor.cjs.map +1 -0
  63. package/dist/lib/capacitor.d.ts +217 -0
  64. package/dist/lib/capacitor.js +223 -0
  65. package/dist/lib/capacitor.js.map +1 -0
  66. package/dist/lib/components/accordion-group.cjs +1 -0
  67. package/dist/lib/components/accordion-group.d.ts +11 -0
  68. package/dist/lib/components/accordion-group.js +2 -0
  69. package/dist/lib/components/accordion.cjs +1 -0
  70. package/dist/lib/components/accordion.d.ts +11 -0
  71. package/dist/lib/components/accordion.js +2 -0
  72. package/dist/lib/components/action-sheet.cjs +1 -0
  73. package/dist/lib/components/action-sheet.d.ts +11 -0
  74. package/dist/lib/components/action-sheet.js +2 -0
  75. package/dist/lib/components/alert.cjs +1 -0
  76. package/dist/lib/components/alert.d.ts +11 -0
  77. package/dist/lib/components/alert.js +2 -0
  78. package/dist/lib/components/avatar.cjs +1 -0
  79. package/dist/lib/components/avatar.d.ts +11 -0
  80. package/dist/lib/components/avatar.js +2 -0
  81. package/dist/lib/components/backdrop.cjs +1 -0
  82. package/dist/lib/components/backdrop.d.ts +11 -0
  83. package/dist/lib/components/backdrop.js +2 -0
  84. package/dist/lib/components/badge.cjs +1 -0
  85. package/dist/lib/components/badge.d.ts +11 -0
  86. package/dist/lib/components/badge.js +2 -0
  87. package/dist/lib/components/breadcrumb.cjs +1 -0
  88. package/dist/lib/components/breadcrumb.d.ts +11 -0
  89. package/dist/lib/components/breadcrumb.js +2 -0
  90. package/dist/lib/components/breadcrumbs.cjs +1 -0
  91. package/dist/lib/components/breadcrumbs.d.ts +11 -0
  92. package/dist/lib/components/breadcrumbs.js +2 -0
  93. package/dist/lib/components/button.cjs +1 -0
  94. package/dist/lib/components/button.d.ts +11 -0
  95. package/dist/lib/components/button.js +2 -0
  96. package/dist/lib/components/buttons.cjs +1 -0
  97. package/dist/lib/components/buttons.d.ts +11 -0
  98. package/dist/lib/components/buttons.js +2 -0
  99. package/dist/lib/components/card-content.cjs +1 -0
  100. package/dist/lib/components/card-content.d.ts +11 -0
  101. package/dist/lib/components/card-content.js +2 -0
  102. package/dist/lib/components/card-header.cjs +1 -0
  103. package/dist/lib/components/card-header.d.ts +11 -0
  104. package/dist/lib/components/card-header.js +2 -0
  105. package/dist/lib/components/card-subtitle.cjs +1 -0
  106. package/dist/lib/components/card-subtitle.d.ts +11 -0
  107. package/dist/lib/components/card-subtitle.js +2 -0
  108. package/dist/lib/components/card-title.cjs +1 -0
  109. package/dist/lib/components/card-title.d.ts +11 -0
  110. package/dist/lib/components/card-title.js +2 -0
  111. package/dist/lib/components/card.cjs +1 -0
  112. package/dist/lib/components/card.d.ts +11 -0
  113. package/dist/lib/components/card.js +2 -0
  114. package/dist/lib/components/checkbox.cjs +1 -0
  115. package/dist/lib/components/checkbox.d.ts +11 -0
  116. package/dist/lib/components/checkbox.js +2 -0
  117. package/dist/lib/components/chip.cjs +1 -0
  118. package/dist/lib/components/chip.d.ts +11 -0
  119. package/dist/lib/components/chip.js +2 -0
  120. package/dist/lib/components/col.cjs +1 -0
  121. package/dist/lib/components/col.d.ts +11 -0
  122. package/dist/lib/components/col.js +2 -0
  123. package/dist/lib/components/content.cjs +1 -0
  124. package/dist/lib/components/content.d.ts +11 -0
  125. package/dist/lib/components/content.js +2 -0
  126. package/dist/lib/components/datetime-button.cjs +1 -0
  127. package/dist/lib/components/datetime-button.d.ts +11 -0
  128. package/dist/lib/components/datetime-button.js +2 -0
  129. package/dist/lib/components/datetime.cjs +1 -0
  130. package/dist/lib/components/datetime.d.ts +11 -0
  131. package/dist/lib/components/datetime.js +2 -0
  132. package/dist/lib/components/fab-button.cjs +1 -0
  133. package/dist/lib/components/fab-button.d.ts +11 -0
  134. package/dist/lib/components/fab-button.js +2 -0
  135. package/dist/lib/components/fab-list.cjs +1 -0
  136. package/dist/lib/components/fab-list.d.ts +11 -0
  137. package/dist/lib/components/fab-list.js +2 -0
  138. package/dist/lib/components/fab.cjs +1 -0
  139. package/dist/lib/components/fab.d.ts +11 -0
  140. package/dist/lib/components/fab.js +2 -0
  141. package/dist/lib/components/footer.cjs +1 -0
  142. package/dist/lib/components/footer.d.ts +11 -0
  143. package/dist/lib/components/footer.js +2 -0
  144. package/dist/lib/components/grid.cjs +1 -0
  145. package/dist/lib/components/grid.d.ts +11 -0
  146. package/dist/lib/components/grid.js +2 -0
  147. package/dist/lib/components/header.cjs +1 -0
  148. package/dist/lib/components/header.d.ts +11 -0
  149. package/dist/lib/components/header.js +2 -0
  150. package/dist/lib/components/img.cjs +1 -0
  151. package/dist/lib/components/img.d.ts +11 -0
  152. package/dist/lib/components/img.js +2 -0
  153. package/dist/lib/components/infinite-scroll-content.cjs +1 -0
  154. package/dist/lib/components/infinite-scroll-content.d.ts +11 -0
  155. package/dist/lib/components/infinite-scroll-content.js +2 -0
  156. package/dist/lib/components/infinite-scroll.cjs +1 -0
  157. package/dist/lib/components/infinite-scroll.d.ts +11 -0
  158. package/dist/lib/components/infinite-scroll.js +2 -0
  159. package/dist/lib/components/input-otp.cjs +1 -0
  160. package/dist/lib/components/input-otp.d.ts +11 -0
  161. package/dist/lib/components/input-otp.js +2 -0
  162. package/dist/lib/components/input-password-toggle.cjs +1 -0
  163. package/dist/lib/components/input-password-toggle.d.ts +11 -0
  164. package/dist/lib/components/input-password-toggle.js +2 -0
  165. package/dist/lib/components/input.cjs +1 -0
  166. package/dist/lib/components/input.d.ts +11 -0
  167. package/dist/lib/components/input.js +2 -0
  168. package/dist/lib/components/item-divider.cjs +1 -0
  169. package/dist/lib/components/item-divider.d.ts +11 -0
  170. package/dist/lib/components/item-divider.js +2 -0
  171. package/dist/lib/components/item-group.cjs +1 -0
  172. package/dist/lib/components/item-group.d.ts +11 -0
  173. package/dist/lib/components/item-group.js +2 -0
  174. package/dist/lib/components/item-option.cjs +1 -0
  175. package/dist/lib/components/item-option.d.ts +11 -0
  176. package/dist/lib/components/item-option.js +2 -0
  177. package/dist/lib/components/item-options.cjs +1 -0
  178. package/dist/lib/components/item-options.d.ts +11 -0
  179. package/dist/lib/components/item-options.js +2 -0
  180. package/dist/lib/components/item-sliding.cjs +1 -0
  181. package/dist/lib/components/item-sliding.d.ts +11 -0
  182. package/dist/lib/components/item-sliding.js +2 -0
  183. package/dist/lib/components/item.cjs +1 -0
  184. package/dist/lib/components/item.d.ts +11 -0
  185. package/dist/lib/components/item.js +2 -0
  186. package/dist/lib/components/label.cjs +1 -0
  187. package/dist/lib/components/label.d.ts +11 -0
  188. package/dist/lib/components/label.js +2 -0
  189. package/dist/lib/components/list-header.cjs +1 -0
  190. package/dist/lib/components/list-header.d.ts +11 -0
  191. package/dist/lib/components/list-header.js +2 -0
  192. package/dist/lib/components/list.cjs +1 -0
  193. package/dist/lib/components/list.d.ts +11 -0
  194. package/dist/lib/components/list.js +2 -0
  195. package/dist/lib/components/loading.cjs +1 -0
  196. package/dist/lib/components/loading.d.ts +11 -0
  197. package/dist/lib/components/loading.js +2 -0
  198. package/dist/lib/components/manifest.cjs +2 -0
  199. package/dist/lib/components/manifest.cjs.map +1 -0
  200. package/dist/lib/components/manifest.d.ts +43 -0
  201. package/dist/lib/components/manifest.js +647 -0
  202. package/dist/lib/components/manifest.js.map +1 -0
  203. package/dist/lib/components/menu-button.cjs +1 -0
  204. package/dist/lib/components/menu-button.d.ts +11 -0
  205. package/dist/lib/components/menu-button.js +2 -0
  206. package/dist/lib/components/menu-toggle.cjs +1 -0
  207. package/dist/lib/components/menu-toggle.d.ts +11 -0
  208. package/dist/lib/components/menu-toggle.js +2 -0
  209. package/dist/lib/components/menu.cjs +1 -0
  210. package/dist/lib/components/menu.d.ts +11 -0
  211. package/dist/lib/components/menu.js +2 -0
  212. package/dist/lib/components/modal.cjs +1 -0
  213. package/dist/lib/components/modal.d.ts +11 -0
  214. package/dist/lib/components/modal.js +2 -0
  215. package/dist/lib/components/nav-link.cjs +1 -0
  216. package/dist/lib/components/nav-link.d.ts +11 -0
  217. package/dist/lib/components/nav-link.js +2 -0
  218. package/dist/lib/components/nav.cjs +1 -0
  219. package/dist/lib/components/nav.d.ts +11 -0
  220. package/dist/lib/components/nav.js +2 -0
  221. package/dist/lib/components/note.cjs +1 -0
  222. package/dist/lib/components/note.d.ts +11 -0
  223. package/dist/lib/components/note.js +2 -0
  224. package/dist/lib/components/picker-column-option.cjs +1 -0
  225. package/dist/lib/components/picker-column-option.d.ts +11 -0
  226. package/dist/lib/components/picker-column-option.js +2 -0
  227. package/dist/lib/components/picker-column.cjs +1 -0
  228. package/dist/lib/components/picker-column.d.ts +11 -0
  229. package/dist/lib/components/picker-column.js +2 -0
  230. package/dist/lib/components/picker.cjs +1 -0
  231. package/dist/lib/components/picker.d.ts +11 -0
  232. package/dist/lib/components/picker.js +2 -0
  233. package/dist/lib/components/popover.cjs +1 -0
  234. package/dist/lib/components/popover.d.ts +11 -0
  235. package/dist/lib/components/popover.js +2 -0
  236. package/dist/lib/components/progress-bar.cjs +1 -0
  237. package/dist/lib/components/progress-bar.d.ts +11 -0
  238. package/dist/lib/components/progress-bar.js +2 -0
  239. package/dist/lib/components/radio-group.cjs +1 -0
  240. package/dist/lib/components/radio-group.d.ts +11 -0
  241. package/dist/lib/components/radio-group.js +2 -0
  242. package/dist/lib/components/radio.cjs +1 -0
  243. package/dist/lib/components/radio.d.ts +11 -0
  244. package/dist/lib/components/radio.js +2 -0
  245. package/dist/lib/components/range.cjs +1 -0
  246. package/dist/lib/components/range.d.ts +11 -0
  247. package/dist/lib/components/range.js +2 -0
  248. package/dist/lib/components/refresher-content.cjs +1 -0
  249. package/dist/lib/components/refresher-content.d.ts +11 -0
  250. package/dist/lib/components/refresher-content.js +2 -0
  251. package/dist/lib/components/refresher.cjs +1 -0
  252. package/dist/lib/components/refresher.d.ts +11 -0
  253. package/dist/lib/components/refresher.js +2 -0
  254. package/dist/lib/components/reorder-group.cjs +1 -0
  255. package/dist/lib/components/reorder-group.d.ts +11 -0
  256. package/dist/lib/components/reorder-group.js +2 -0
  257. package/dist/lib/components/reorder.cjs +1 -0
  258. package/dist/lib/components/reorder.d.ts +11 -0
  259. package/dist/lib/components/reorder.js +2 -0
  260. package/dist/lib/components/ripple-effect.cjs +1 -0
  261. package/dist/lib/components/ripple-effect.d.ts +11 -0
  262. package/dist/lib/components/ripple-effect.js +2 -0
  263. package/dist/lib/components/router-link.cjs +1 -0
  264. package/dist/lib/components/router-link.d.ts +11 -0
  265. package/dist/lib/components/router-link.js +2 -0
  266. package/dist/lib/components/row.cjs +1 -0
  267. package/dist/lib/components/row.d.ts +11 -0
  268. package/dist/lib/components/row.js +2 -0
  269. package/dist/lib/components/searchbar.cjs +1 -0
  270. package/dist/lib/components/searchbar.d.ts +11 -0
  271. package/dist/lib/components/searchbar.js +2 -0
  272. package/dist/lib/components/segment-button.cjs +1 -0
  273. package/dist/lib/components/segment-button.d.ts +11 -0
  274. package/dist/lib/components/segment-button.js +2 -0
  275. package/dist/lib/components/segment-content.cjs +1 -0
  276. package/dist/lib/components/segment-content.d.ts +11 -0
  277. package/dist/lib/components/segment-content.js +2 -0
  278. package/dist/lib/components/segment-view.cjs +1 -0
  279. package/dist/lib/components/segment-view.d.ts +11 -0
  280. package/dist/lib/components/segment-view.js +2 -0
  281. package/dist/lib/components/segment.cjs +1 -0
  282. package/dist/lib/components/segment.d.ts +11 -0
  283. package/dist/lib/components/segment.js +2 -0
  284. package/dist/lib/components/select-modal.cjs +1 -0
  285. package/dist/lib/components/select-modal.d.ts +11 -0
  286. package/dist/lib/components/select-modal.js +2 -0
  287. package/dist/lib/components/select-option.cjs +1 -0
  288. package/dist/lib/components/select-option.d.ts +11 -0
  289. package/dist/lib/components/select-option.js +2 -0
  290. package/dist/lib/components/select-popover.cjs +1 -0
  291. package/dist/lib/components/select-popover.d.ts +11 -0
  292. package/dist/lib/components/select-popover.js +2 -0
  293. package/dist/lib/components/select.cjs +1 -0
  294. package/dist/lib/components/select.d.ts +11 -0
  295. package/dist/lib/components/select.js +2 -0
  296. package/dist/lib/components/skeleton-text.cjs +1 -0
  297. package/dist/lib/components/skeleton-text.d.ts +11 -0
  298. package/dist/lib/components/skeleton-text.js +2 -0
  299. package/dist/lib/components/spinner.cjs +1 -0
  300. package/dist/lib/components/spinner.d.ts +11 -0
  301. package/dist/lib/components/spinner.js +2 -0
  302. package/dist/lib/components/split-pane.cjs +1 -0
  303. package/dist/lib/components/split-pane.d.ts +11 -0
  304. package/dist/lib/components/split-pane.js +2 -0
  305. package/dist/lib/components/tab-bar.cjs +1 -0
  306. package/dist/lib/components/tab-bar.d.ts +11 -0
  307. package/dist/lib/components/tab-bar.js +2 -0
  308. package/dist/lib/components/tab-button.cjs +1 -0
  309. package/dist/lib/components/tab-button.d.ts +11 -0
  310. package/dist/lib/components/tab-button.js +2 -0
  311. package/dist/lib/components/tab.cjs +1 -0
  312. package/dist/lib/components/tab.d.ts +11 -0
  313. package/dist/lib/components/tab.js +2 -0
  314. package/dist/lib/components/tabs.cjs +1 -0
  315. package/dist/lib/components/tabs.d.ts +11 -0
  316. package/dist/lib/components/tabs.js +2 -0
  317. package/dist/lib/components/text.cjs +1 -0
  318. package/dist/lib/components/text.d.ts +11 -0
  319. package/dist/lib/components/text.js +2 -0
  320. package/dist/lib/components/textarea.cjs +1 -0
  321. package/dist/lib/components/textarea.d.ts +11 -0
  322. package/dist/lib/components/textarea.js +2 -0
  323. package/dist/lib/components/thumbnail.cjs +1 -0
  324. package/dist/lib/components/thumbnail.d.ts +11 -0
  325. package/dist/lib/components/thumbnail.js +2 -0
  326. package/dist/lib/components/title.cjs +1 -0
  327. package/dist/lib/components/title.d.ts +11 -0
  328. package/dist/lib/components/title.js +2 -0
  329. package/dist/lib/components/toast.cjs +1 -0
  330. package/dist/lib/components/toast.d.ts +11 -0
  331. package/dist/lib/components/toast.js +2 -0
  332. package/dist/lib/components/toggle.cjs +1 -0
  333. package/dist/lib/components/toggle.d.ts +11 -0
  334. package/dist/lib/components/toggle.js +2 -0
  335. package/dist/lib/components/toolbar.cjs +1 -0
  336. package/dist/lib/components/toolbar.d.ts +11 -0
  337. package/dist/lib/components/toolbar.js +2 -0
  338. package/dist/lib/components.cjs +1 -0
  339. package/dist/lib/components.d.ts +110 -0
  340. package/dist/lib/components.js +94 -0
  341. package/dist/lib/definitions-CmPIrLhr.js +282 -0
  342. package/dist/lib/definitions-CmPIrLhr.js.map +1 -0
  343. package/dist/lib/definitions-CrcjkKEd.cjs +2 -0
  344. package/dist/lib/definitions-CrcjkKEd.cjs.map +1 -0
  345. package/dist/lib/devtools.cjs +2 -0
  346. package/dist/lib/devtools.cjs.map +1 -0
  347. package/dist/lib/devtools.d.ts +54 -0
  348. package/dist/lib/devtools.js +46 -0
  349. package/dist/lib/devtools.js.map +1 -0
  350. package/dist/lib/elur-ionic.cjs +1 -0
  351. package/dist/lib/elur-ionic.cjs.map +1 -0
  352. package/dist/lib/elur-ionic.js +1 -0
  353. package/dist/lib/elur-ionic.js.map +1 -0
  354. package/dist/lib/index.d.ts +47 -0
  355. package/dist/lib/lifecycle.d.ts +62 -0
  356. package/dist/lib/navigation.cjs +2 -0
  357. package/dist/lib/navigation.cjs.map +1 -0
  358. package/dist/lib/navigation.d.ts +214 -0
  359. package/dist/lib/navigation.js +205 -0
  360. package/dist/lib/navigation.js.map +1 -0
  361. package/dist/lib/overlays.cjs +2 -0
  362. package/dist/lib/overlays.cjs.map +1 -0
  363. package/dist/lib/overlays.d.ts +400 -0
  364. package/dist/lib/overlays.js +161 -0
  365. package/dist/lib/overlays.js.map +1 -0
  366. package/dist/lib/page-state.cjs +2 -0
  367. package/dist/lib/page-state.cjs.map +1 -0
  368. package/dist/lib/page-state.d.ts +160 -0
  369. package/dist/lib/page-state.js +91 -0
  370. package/dist/lib/page-state.js.map +1 -0
  371. package/dist/lib/setup.d.ts +105 -0
  372. package/dist/lib/tabs-ByPLrzax.cjs +50 -0
  373. package/dist/lib/tabs-ByPLrzax.cjs.map +1 -0
  374. package/dist/lib/tabs-DjD1_PTM.js +178 -0
  375. package/dist/lib/tabs-DjD1_PTM.js.map +1 -0
  376. package/dist/lib/tabs.cjs +1 -0
  377. package/dist/lib/tabs.d.ts +83 -0
  378. package/dist/lib/tabs.js +2 -0
  379. package/dist/lib/vite-plugin.cjs +38 -0
  380. package/dist/lib/vite-plugin.cjs.map +1 -0
  381. package/dist/lib/vite-plugin.d.ts +61 -0
  382. package/dist/lib/vite-plugin.js +25411 -0
  383. package/dist/lib/vite-plugin.js.map +1 -0
  384. package/dist/lib/web-Bnz2Zs_W.cjs +2 -0
  385. package/dist/lib/web-Bnz2Zs_W.cjs.map +1 -0
  386. package/dist/lib/web-Ce5OM4dv.js +56 -0
  387. package/dist/lib/web-Ce5OM4dv.js.map +1 -0
  388. package/package.json +216 -0
@@ -0,0 +1,160 @@
1
+ /**
2
+ * @elurjs/ionic / page-state.ts
3
+ *
4
+ * Opt-in page-state persistence protocol. Allows pages to save and restore
5
+ * serializable state across navigation, cache eviction, and app reloads.
6
+ *
7
+ * Key design rules:
8
+ * - **Only serializable data** — JSON.stringify is used; DOM nodes, functions,
9
+ * symbols, class instances with methods are rejected.
10
+ * - **Never persist DOM/view instances** — the protocol validates values
11
+ * before storage and throws on non-serializable content.
12
+ * - **Opt-in** — pages must explicitly call `save()` to persist state.
13
+ * - **Per cache key** — state is keyed by route path + params + query,
14
+ * matching the IonRouterOutlet cache key logic.
15
+ * - **Storage choice** — `sessionStorage` (default, cleared on tab close)
16
+ * or `localStorage` (persists across sessions).
17
+ *
18
+ * @example Basic usage in a page component
19
+ * ```ts
20
+ * import { signal, html } from "@elurjs/core";
21
+ * import { createPageState, IonPage } from "@elurjs/ionic";
22
+ *
23
+ * class SearchPage extends IonPage {
24
+ * private query = signal("");
25
+ * private results = signal<string[]>([]);
26
+ * private pageState = createPageState("search", {
27
+ * // Declare which signals are persistable
28
+ * query: this.query,
29
+ * results: this.results,
30
+ * });
31
+ *
32
+ * override onMount() {
33
+ * // Restore saved state on mount
34
+ * this.pageState.restore();
35
+ * }
36
+ *
37
+ * override onUnmount() {
38
+ * // Save state before leaving
39
+ * this.pageState.save();
40
+ * }
41
+ *
42
+ * override render() {
43
+ * return html`
44
+ * <ion-content>
45
+ * <ion-searchbar value=${() => this.query.value} @input=${(e: any) => {
46
+ * this.query.value = e.target.value;
47
+ * this.pageState.save(); // save on change
48
+ * }}></ion-searchbar>
49
+ * <ion-list>
50
+ * ${() => this.results.value.map(r => html`<ion-item>${r}</ion-item>`)}
51
+ * </ion-list>
52
+ * </ion-content>
53
+ * `;
54
+ * }
55
+ * }
56
+ * ```
57
+ *
58
+ * @example With localStorage (persists across app restarts)
59
+ * ```ts
60
+ * const pageState = createPageState("cart", {
61
+ * items: cartItems,
62
+ * total: cartTotal,
63
+ * }, { storage: "local" });
64
+ * ```
65
+ */
66
+ /** Storage backend selection. */
67
+ export type StorageBackend = "session" | "local";
68
+ /** Options for page-state persistence. */
69
+ export interface PageStateOptions {
70
+ /**
71
+ * Storage backend: `"session"` (sessionStorage, cleared on tab close)
72
+ * or `"local"` (localStorage, persists across sessions).
73
+ * @default "session"
74
+ */
75
+ storage?: StorageBackend;
76
+ /**
77
+ * Namespace prefix for storage keys. Defaults to "elur-ionic".
78
+ * Useful for multi-app scenarios on the same origin.
79
+ */
80
+ namespace?: string;
81
+ /**
82
+ * Additional key suffix (e.g. user ID) to isolate state between users.
83
+ */
84
+ keySuffix?: string;
85
+ }
86
+ /**
87
+ * A map of signal names to signals. Each signal's value must be serializable.
88
+ */
89
+ export type SignalMap = Record<string, {
90
+ value: unknown;
91
+ }>;
92
+ /**
93
+ * Page-state persistence controller. Created per page instance.
94
+ */
95
+ export interface PageState {
96
+ /**
97
+ * Save the current state of all declared signals to storage.
98
+ * Only serializable values are stored; non-serializable values are
99
+ * silently skipped (with a console.warn in dev).
100
+ */
101
+ save(): void;
102
+ /**
103
+ * Restore saved state from storage into the declared signals.
104
+ * Returns true if state was found and restored, false otherwise.
105
+ */
106
+ restore(): boolean;
107
+ /**
108
+ * Clear saved state for this page's key.
109
+ */
110
+ clear(): void;
111
+ /**
112
+ * Get the storage key that would be used (for debugging).
113
+ */
114
+ readonly key: string;
115
+ }
116
+ /**
117
+ * Check if a value is serializable (can survive JSON.stringify + parse).
118
+ * Returns true for: primitives, plain arrays, plain objects.
119
+ * Returns false for: functions, symbols, DOM nodes, class instances,
120
+ * undefined, circular references.
121
+ */
122
+ declare function isSerializable(value: unknown): boolean;
123
+ /**
124
+ * Create a page-state persistence controller.
125
+ *
126
+ * @param pageId Unique identifier for the page (e.g. route path).
127
+ * @param signals Map of signal names to signals whose values should be persisted.
128
+ * @param options Persistence options.
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * const state = createPageState("search", {
133
+ * query: searchQuery,
134
+ * filters: filterSignal,
135
+ * }, { storage: "local" });
136
+ *
137
+ * // On page mount:
138
+ * state.restore();
139
+ *
140
+ * // On page leave or data change:
141
+ * state.save();
142
+ * ```
143
+ */
144
+ export declare function createPageState(pageId: string, signals: SignalMap, options?: PageStateOptions): PageState;
145
+ /**
146
+ * Clear all elur-ionic page-state entries from a storage backend.
147
+ * Useful for logout flows.
148
+ *
149
+ * @example
150
+ * ```ts
151
+ * import { clearAllPageState } from "@elurjs/ionic";
152
+ *
153
+ * function logout() {
154
+ * clearAllPageState(); // sessionStorage
155
+ * clearAllPageState("local"); // localStorage
156
+ * }
157
+ * ```
158
+ */
159
+ export declare function clearAllPageState(backend?: StorageBackend, namespace?: string): void;
160
+ export { isSerializable };
@@ -0,0 +1,91 @@
1
+ //#region src/page-state.ts
2
+ function e(t) {
3
+ if (t === void 0) return !1;
4
+ if (t === null) return !0;
5
+ if (typeof t == "function" || typeof t == "symbol" || typeof t == "bigint" || typeof window < "u" && t instanceof Node || typeof window < "u" && t instanceof Element || typeof window < "u" && t instanceof DocumentFragment) return !1;
6
+ if (typeof t != "object") return !0;
7
+ if (Array.isArray(t)) return t.every(e);
8
+ let n = Object.getPrototypeOf(t);
9
+ if (n !== null && n !== Object.prototype) return !1;
10
+ try {
11
+ return JSON.stringify(t), !0;
12
+ } catch {
13
+ return !1;
14
+ }
15
+ }
16
+ function t(e) {
17
+ return typeof window > "u" ? null : e === "local" ? window.localStorage : window.sessionStorage;
18
+ }
19
+ function n(n, r, i = {}) {
20
+ let { storage: a = "session", namespace: o = "elur-ionic", keySuffix: s = "" } = i, c = `${o}:${n}${s ? ":" + s : ""}`;
21
+ function l() {
22
+ let i = t(a);
23
+ if (!i) return;
24
+ let o = {}, s = !1;
25
+ for (let [t, i] of Object.entries(r)) {
26
+ let r = i.value;
27
+ if (!e(r)) {
28
+ typeof console < "u" && console.warn && console.warn(`[elur-ionic] PageState: skipping non-serializable value for "${t}" on page "${n}". Only serializable data (primitives, plain arrays, plain objects) can be persisted. DOM nodes, functions, and class instances are not allowed.`);
29
+ continue;
30
+ }
31
+ o[t] = r, s = !0;
32
+ }
33
+ if (s) try {
34
+ i.setItem(c, JSON.stringify(o));
35
+ } catch {
36
+ typeof console < "u" && console.warn && console.warn(`[elur-ionic] PageState: failed to save state for page "${n}" (storage quota exceeded or storage disabled).`);
37
+ }
38
+ }
39
+ function u() {
40
+ let e = t(a);
41
+ if (!e) return !1;
42
+ let n = null;
43
+ try {
44
+ n = e.getItem(c);
45
+ } catch {
46
+ return !1;
47
+ }
48
+ if (!n) return !1;
49
+ let i;
50
+ try {
51
+ i = JSON.parse(n);
52
+ } catch {
53
+ try {
54
+ e.removeItem(c);
55
+ } catch {}
56
+ return !1;
57
+ }
58
+ for (let [e, t] of Object.entries(r)) e in i && (t.value = i[e]);
59
+ return !0;
60
+ }
61
+ function d() {
62
+ let e = t(a);
63
+ if (e) try {
64
+ e.removeItem(c);
65
+ } catch {}
66
+ }
67
+ return {
68
+ save: l,
69
+ restore: u,
70
+ clear: d,
71
+ get key() {
72
+ return c;
73
+ }
74
+ };
75
+ }
76
+ function r(e = "session", n = "elur-ionic") {
77
+ let r = t(e);
78
+ if (!r) return;
79
+ let i = `${n}:`, a = [];
80
+ try {
81
+ for (let e = 0; e < r.length; e++) {
82
+ let t = r.key(e);
83
+ t && t.startsWith(i) && a.push(t);
84
+ }
85
+ for (let e of a) r.removeItem(e);
86
+ } catch {}
87
+ }
88
+ //#endregion
89
+ export { r as clearAllPageState, n as createPageState, e as isSerializable };
90
+
91
+ //# sourceMappingURL=page-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-state.js","names":[],"sources":["../../src/page-state.ts"],"sourcesContent":["/**\n * @elurjs/ionic / page-state.ts\n *\n * Opt-in page-state persistence protocol. Allows pages to save and restore\n * serializable state across navigation, cache eviction, and app reloads.\n *\n * Key design rules:\n * - **Only serializable data** — JSON.stringify is used; DOM nodes, functions,\n * symbols, class instances with methods are rejected.\n * - **Never persist DOM/view instances** — the protocol validates values\n * before storage and throws on non-serializable content.\n * - **Opt-in** — pages must explicitly call `save()` to persist state.\n * - **Per cache key** — state is keyed by route path + params + query,\n * matching the IonRouterOutlet cache key logic.\n * - **Storage choice** — `sessionStorage` (default, cleared on tab close)\n * or `localStorage` (persists across sessions).\n *\n * @example Basic usage in a page component\n * ```ts\n * import { signal, html } from \"@elurjs/core\";\n * import { createPageState, IonPage } from \"@elurjs/ionic\";\n *\n * class SearchPage extends IonPage {\n * private query = signal(\"\");\n * private results = signal<string[]>([]);\n * private pageState = createPageState(\"search\", {\n * // Declare which signals are persistable\n * query: this.query,\n * results: this.results,\n * });\n *\n * override onMount() {\n * // Restore saved state on mount\n * this.pageState.restore();\n * }\n *\n * override onUnmount() {\n * // Save state before leaving\n * this.pageState.save();\n * }\n *\n * override render() {\n * return html`\n * <ion-content>\n * <ion-searchbar value=${() => this.query.value} @input=${(e: any) => {\n * this.query.value = e.target.value;\n * this.pageState.save(); // save on change\n * }}></ion-searchbar>\n * <ion-list>\n * ${() => this.results.value.map(r => html`<ion-item>${r}</ion-item>`)}\n * </ion-list>\n * </ion-content>\n * `;\n * }\n * }\n * ```\n *\n * @example With localStorage (persists across app restarts)\n * ```ts\n * const pageState = createPageState(\"cart\", {\n * items: cartItems,\n * total: cartTotal,\n * }, { storage: \"local\" });\n * ```\n */\n\n// --- Types ---\n\n/** Storage backend selection. */\nexport type StorageBackend = \"session\" | \"local\";\n\n/** Options for page-state persistence. */\nexport interface PageStateOptions {\n /**\n * Storage backend: `\"session\"` (sessionStorage, cleared on tab close)\n * or `\"local\"` (localStorage, persists across sessions).\n * @default \"session\"\n */\n storage?: StorageBackend;\n /**\n * Namespace prefix for storage keys. Defaults to \"elur-ionic\".\n * Useful for multi-app scenarios on the same origin.\n */\n namespace?: string;\n /**\n * Additional key suffix (e.g. user ID) to isolate state between users.\n */\n keySuffix?: string;\n}\n\n/**\n * A map of signal names to signals. Each signal's value must be serializable.\n */\nexport type SignalMap = Record<string, { value: unknown }>;\n\n/**\n * Page-state persistence controller. Created per page instance.\n */\nexport interface PageState {\n /**\n * Save the current state of all declared signals to storage.\n * Only serializable values are stored; non-serializable values are\n * silently skipped (with a console.warn in dev).\n */\n save(): void;\n /**\n * Restore saved state from storage into the declared signals.\n * Returns true if state was found and restored, false otherwise.\n */\n restore(): boolean;\n /**\n * Clear saved state for this page's key.\n */\n clear(): void;\n /**\n * Get the storage key that would be used (for debugging).\n */\n readonly key: string;\n}\n\n// --- Serialization validation ---\n\n/**\n * Check if a value is serializable (can survive JSON.stringify + parse).\n * Returns true for: primitives, plain arrays, plain objects.\n * Returns false for: functions, symbols, DOM nodes, class instances,\n * undefined, circular references.\n */\nfunction isSerializable(value: unknown): boolean {\n if (value === undefined) return false;\n if (value === null) return true;\n if (typeof value === \"function\") return false;\n if (typeof value === \"symbol\") return false;\n if (typeof value === \"bigint\") return false; // JSON.stringify throws on bigint\n\n // DOM nodes and elements\n if (typeof window !== \"undefined\" && value instanceof Node) return false;\n if (typeof window !== \"undefined\" && value instanceof Element) return false;\n if (typeof window !== \"undefined\" && value instanceof DocumentFragment) return false;\n\n // Primitives\n if (typeof value !== \"object\") return true;\n\n // Arrays — check each element\n if (Array.isArray(value)) {\n return value.every(isSerializable);\n }\n\n // Plain objects — check constructor and each value\n const proto = Object.getPrototypeOf(value);\n if (proto !== null && proto !== Object.prototype) {\n // Class instances (has non-trivial prototype) — reject\n return false;\n }\n\n try {\n // Final check: can it survive a round-trip?\n JSON.stringify(value);\n return true;\n } catch {\n return false; // circular reference or other stringify error\n }\n}\n\n// --- Storage abstraction ---\n\nfunction getStorage(backend: StorageBackend): Storage | null {\n if (typeof window === \"undefined\") return null;\n return backend === \"local\" ? window.localStorage : window.sessionStorage;\n}\n\n// --- Factory ---\n\n/**\n * Create a page-state persistence controller.\n *\n * @param pageId Unique identifier for the page (e.g. route path).\n * @param signals Map of signal names to signals whose values should be persisted.\n * @param options Persistence options.\n *\n * @example\n * ```ts\n * const state = createPageState(\"search\", {\n * query: searchQuery,\n * filters: filterSignal,\n * }, { storage: \"local\" });\n *\n * // On page mount:\n * state.restore();\n *\n * // On page leave or data change:\n * state.save();\n * ```\n */\nexport function createPageState(\n pageId: string,\n signals: SignalMap,\n options: PageStateOptions = {},\n): PageState {\n const {\n storage: backend = \"session\",\n namespace = \"elur-ionic\",\n keySuffix = \"\",\n } = options;\n\n const baseKey = `${namespace}:${pageId}${keySuffix ? \":\" + keySuffix : \"\"}`;\n\n function save(): void {\n const storage = getStorage(backend);\n if (!storage) return;\n\n const data: Record<string, unknown> = {};\n let hasData = false;\n\n for (const [name, sig] of Object.entries(signals)) {\n const value = sig.value;\n if (!isSerializable(value)) {\n if (typeof console !== \"undefined\" && console.warn) {\n console.warn(\n `[elur-ionic] PageState: skipping non-serializable value for \"${name}\" ` +\n `on page \"${pageId}\". Only serializable data (primitives, plain arrays, ` +\n `plain objects) can be persisted. DOM nodes, functions, and class ` +\n `instances are not allowed.`,\n );\n }\n continue;\n }\n data[name] = value;\n hasData = true;\n }\n\n if (hasData) {\n try {\n storage.setItem(baseKey, JSON.stringify(data));\n } catch {\n // Quota exceeded or storage disabled — fail silently\n if (typeof console !== \"undefined\" && console.warn) {\n console.warn(\n `[elur-ionic] PageState: failed to save state for page \"${pageId}\" ` +\n `(storage quota exceeded or storage disabled).`,\n );\n }\n }\n }\n }\n\n function restore(): boolean {\n const storage = getStorage(backend);\n if (!storage) return false;\n\n let raw: string | null = null;\n try {\n raw = storage.getItem(baseKey);\n } catch {\n return false; // storage access denied\n }\n\n if (!raw) return false;\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(raw);\n } catch {\n // Corrupted data — clear it\n try { storage.removeItem(baseKey); } catch { /* ignore */ }\n return false;\n }\n\n for (const [name, sig] of Object.entries(signals)) {\n if (name in data) {\n sig.value = data[name];\n }\n }\n\n return true;\n }\n\n function clear(): void {\n const storage = getStorage(backend);\n if (!storage) return;\n try {\n storage.removeItem(baseKey);\n } catch { /* ignore */ }\n }\n\n return {\n save,\n restore,\n clear,\n get key() { return baseKey; },\n };\n}\n\n// --- Batch helpers ---\n\n/**\n * Clear all elur-ionic page-state entries from a storage backend.\n * Useful for logout flows.\n *\n * @example\n * ```ts\n * import { clearAllPageState } from \"@elurjs/ionic\";\n *\n * function logout() {\n * clearAllPageState(); // sessionStorage\n * clearAllPageState(\"local\"); // localStorage\n * }\n * ```\n */\nexport function clearAllPageState(backend: StorageBackend = \"session\", namespace = \"elur-ionic\"): void {\n const storage = getStorage(backend);\n if (!storage) return;\n\n const prefix = `${namespace}:`;\n const keysToRemove: string[] = [];\n\n try {\n for (let i = 0; i < storage.length; i++) {\n const key = storage.key(i);\n if (key && key.startsWith(prefix)) {\n keysToRemove.push(key);\n }\n }\n for (const key of keysToRemove) {\n storage.removeItem(key);\n }\n } catch { /* ignore */ }\n}\n\n// --- Serialization utilities (exported for testing) ---\n\nexport { isSerializable };\n"],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @elurjs/ionic / setup.ts — v2 modular setup
3
+ *
4
+ * Architecture (Elur Ionic 2):
5
+ *
6
+ * initializeElurIonic(options) — configures Ionic Core once; returns a
7
+ * handle with status/diagnostics. Safe to
8
+ * call again (no-op after first init, but
9
+ * validates incompatible config changes).
10
+ *
11
+ * registerIonicComponents(...definers) — incremental & idempotent. Always
12
+ * registers new definers, skips already-
13
+ * registered custom elements. Works for
14
+ * lazy route loading.
15
+ *
16
+ * registerIonicons(map) — incremental with collision diagnostics.
17
+ * Merges new icons into the global set;
18
+ * warns on name collisions.
19
+ *
20
+ * setupElurIonic(options) — backward-compatible facade that calls all
21
+ * three. Existing apps work unchanged.
22
+ *
23
+ * Key changes vs v1.x:
24
+ * - No more `isInitialized` blocking: `registerIonicComponents` and
25
+ * `registerIonicons` are always incremental.
26
+ * - No `unpkg@latest` default asset path: uses official `setAssetPath` from
27
+ * ionicons. CDN is opt-in only.
28
+ * - SSR-safe: no `window` access at module load; guards in each function.
29
+ * - Returns a handle with diagnostics from `initializeElurIonic`.
30
+ */
31
+ import { addIcons, setAssetPath } from "ionicons";
32
+ export type ComponentDefiner = () => void;
33
+ export type IconDefinitionMap = Record<string, string>;
34
+ export interface SetupElurIonicOptions {
35
+ /** @deprecated Use `icons` mode in `initializeElurIonic` instead. */
36
+ iconAssetPath?: string;
37
+ components?: ComponentDefiner[];
38
+ icons?: IconDefinitionMap;
39
+ }
40
+ export interface InitializeOptions {
41
+ /**
42
+ * Icon asset strategy:
43
+ * - "inline" (default): icons are inlined via addIcons; no remote fetch.
44
+ * - "assets": use setAssetPath to a local URL; icons fetched on demand.
45
+ * - object with `mode: "assets"` and `path` for explicit local path.
46
+ */
47
+ icons?: "inline" | "assets" | {
48
+ mode: "assets";
49
+ path: string;
50
+ };
51
+ /** Ionic mode override: "ios" | "md" | undefined (auto-detect). */
52
+ mode?: "ios" | "md";
53
+ }
54
+ export interface SetupHandle {
55
+ /** True if this call performed the initialization; false if already init. */
56
+ readonly initialized: boolean;
57
+ /** Diagnostics collected during initialization. */
58
+ readonly diagnostics: string[];
59
+ }
60
+ /**
61
+ * Initialize Ionic Core for Elur. Configures the runtime once.
62
+ *
63
+ * Subsequent calls are no-ops for the core init, but `registerIonicComponents`
64
+ * and `registerIonicons` remain incremental regardless.
65
+ *
66
+ * Returns a handle with diagnostics.
67
+ */
68
+ export declare function initializeElurIonic(options?: InitializeOptions): SetupHandle;
69
+ /**
70
+ * Register additional Ionic custom element definers. Incremental and
71
+ * idempotent — always processes new definers, safe to call from lazy routes.
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * // In a lazy route module:
76
+ * import { defineCustomElement as defineIonDatetime } from "@ionic/core/components/ion-datetime.js";
77
+ * registerIonicComponents(defineIonDatetime);
78
+ * ```
79
+ */
80
+ export declare function registerIonicComponents(...definers: ComponentDefiner[]): void;
81
+ /**
82
+ * Register additional Ionicons by name → SVG string mapping. Incremental
83
+ * with collision diagnostics.
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * import { registerIonicons } from "@elurjs/ionic";
88
+ * import { home, homeOutline } from "ionicons/icons";
89
+ *
90
+ * registerIonicons({ home, "home-outline": homeOutline });
91
+ * ```
92
+ */
93
+ export declare function registerIonicons(map: IconDefinitionMap): void;
94
+ /**
95
+ * Backward-compatible facade. Calls `initializeElurIonic`, then registers
96
+ * any extra components and icons passed via options.
97
+ *
98
+ * Existing v1.x apps work unchanged. New apps should prefer the granular
99
+ * functions (`initializeElurIonic` + `registerIonicComponents` + `registerIonicons`)
100
+ * for lazy loading and HMR support.
101
+ *
102
+ * @deprecated Prefer `initializeElurIonic` + `registerIonicComponents` + `registerIonicons` for new code.
103
+ */
104
+ export declare function setupElurIonic(options?: SetupElurIonicOptions): void;
105
+ export { addIcons, setAssetPath };
@@ -0,0 +1,50 @@
1
+ let e=require("@elurjs/core"),t=require("@ionic/core/components"),n=require("@ionic/core/components/ion-app.js"),r=require("@ionic/core/components/ion-router-outlet.js"),i=require("@ionic/core/components/ion-back-button.js"),a=require("@ionic/core/components/ion-buttons.js"),o=require("ionicons/components/ion-icon.js"),s=require("ionicons"),c=require("ionicons/icons");var l=[n.defineCustomElement,r.defineCustomElement,i.defineCustomElement,a.defineCustomElement,o.defineCustomElement],u={"arrow-back":c.arrowBack,"arrow-back-sharp":c.arrowBackSharp,"chevron-back":c.chevronBack,"chevron-back-sharp":c.chevronBackSharp},d=!1,f=new Set;function p(){return typeof window<`u`}function m(){return typeof customElements<`u`}function h(e={}){let n=[];if(!p())return{initialized:!1,diagnostics:[`SSR: window unavailable, skipping init`]};if(d)return e.mode&&n.push(`mode cannot be changed after initialization; ignoring`),{initialized:!1,diagnostics:n};let r=e.icons??`inline`;if(r===`inline`)(0,s.setAssetPath)(``);else if(typeof r==`object`&&r.mode===`assets`)(0,s.setAssetPath)(r.path);else if(r===`assets`){let e=document.baseURI||`/`;(0,s.setAssetPath)(new URL(`assets/icons/`,e).href)}(0,t.initialize)();for(let e of l)e();(0,s.addIcons)(u);for(let e of Object.keys(u))f.add(e);return d=!0,{initialized:!0,diagnostics:n}}function g(...e){if(!m()){p()&&console.warn(`[elur-ionic] customElements unavailable; cannot register components`);return}for(let t of e)try{t()}catch(e){e instanceof Error&&!e.message.includes(`already been registered`)&&console.warn(`[elur-ionic] Component registration error: ${e.message}`)}}function _(e){if(!p())return;let t={};for(let[n,r]of Object.entries(e))f.has(n)&&console.warn(`[elur-ionic] Icon "${n}" already registered; overwriting.`),t[n]=r,f.add(n);Object.keys(t).length>0&&(0,s.addIcons)(t)}function v(e={}){if(!p())return;let t={};e.iconAssetPath&&(t.icons={mode:`assets`,path:e.iconAssetPath}),h(t),e.components&&g(...e.components),e.icons&&_(e.icons)}function y(e){return!e||e===`/`?`/`:e.endsWith(`/`)?e.slice(0,-1):e}function b(e,t){let n=y(t),r=y(e.path);return e.exact?n===r:r===`/`?n===`/`:n===r||n.startsWith(`${r}/`)}function x(e,t){if(!t?.length)return!1;let n=y(e);return t.some(e=>{let t=y(e);if(t.endsWith(`/*`)){let e=t.slice(0,-2);return n===e||n.startsWith(`${e}/`)}return n===t})}function S(e){return e?Object.entries(e).map(([e,t])=>`${e}: ${t}`).join(`; `):``}function C(t,n={}){let r=(0,e.elurRouter)(),i=n.slot??`bottom`,a=n.className??`elur-ion-tab-bar`,o=n.navigationDirection??`none`,c=n.layout??`icon-top`,l=n.cssVars;n.icons&&(0,s.addIcons)(n.icons);let u=(0,e.ref)(),d=!1;return(0,e.effect)(()=>{let n=r.current.value,i=u.el;if(!i){d||(0,e.nextTick)(()=>{d=!0;let e=u.el;e&&e.querySelectorAll(`ion-tab-button`).forEach((e,n)=>{let i=t[n];i&&(e.selected=b(i,r.current.value))})});return}i.querySelectorAll(`ion-tab-button`).forEach((e,r)=>{let i=t[r];i&&(e.selected=b(i,n))})}),e.html`
2
+ <ion-tab-bar
3
+ slot=${i}
4
+ class=${a}
5
+ ref=${u}
6
+ style=${()=>{let e=r.current.value,t=n.hideWhen?n.hideWhen(e):x(e,n.hiddenPaths);return[S(l),t?`display:none`:``].filter(Boolean).join(`; `)}}
7
+ >
8
+ ${t.map(t=>{let n=t.path===`/`?`root`:y(t.path).replace(/^\//,``).replace(/\//g,`-`),i=t.tabId??n;return e.html`
9
+ <ion-tab-button
10
+ tab=${i}
11
+ layout=${c}
12
+ @click.prevent.stop=${()=>{b(t,r.current.value)?r.replace(t.path,{direction:`none`}):r.navigate(t.path,{direction:o})}}
13
+ >
14
+ ${t.icon?e.html`
15
+ <ion-icon
16
+ name=${()=>b(t,r.current.value)&&t.activeIcon?t.activeIcon:t.icon}
17
+ ></ion-icon>
18
+ `:``}
19
+ <ion-label>${t.label}</ion-label>
20
+ ${t.badge==null?``:e.html`<ion-badge color=${t.badgeColor??`danger`}>${t.badge}</ion-badge>`}
21
+ </ion-tab-button>
22
+ `})}
23
+ </ion-tab-bar>
24
+ `}function w(t,n){E();let r=t instanceof e.ElurComponent?t.render():t;return e.html`
25
+ <ion-tabs>
26
+ ${r}
27
+ ${n}
28
+ </ion-tabs>
29
+ `}var T=!1;function E(){if(T||typeof document>`u`)return;T=!0;let e=document.createElement(`style`);e.id=`elur-ionic-tabs-layout`,e.textContent=`
30
+ ion-tabs {
31
+ display: flex !important;
32
+ flex-direction: column !important;
33
+ height: 100% !important;
34
+ width: 100% !important;
35
+ position: relative !important;
36
+ }
37
+ ion-tabs > ion-router-outlet {
38
+ flex: 1 1 0 !important;
39
+ min-height: 0 !important;
40
+ position: relative !important;
41
+ top: auto !important;
42
+ bottom: auto !important;
43
+ left: auto !important;
44
+ right: auto !important;
45
+ }
46
+ ion-tabs > ion-tab-bar {
47
+ flex-shrink: 0 !important;
48
+ }
49
+ `,document.head.appendChild(e)}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return C}});
50
+ //# sourceMappingURL=tabs-ByPLrzax.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabs-ByPLrzax.cjs","names":[],"sources":["../../src/setup.ts","../../src/tabs.ts"],"sourcesContent":["/**\n * @elurjs/ionic / setup.ts — v2 modular setup\n *\n * Architecture (Elur Ionic 2):\n *\n * initializeElurIonic(options) — configures Ionic Core once; returns a\n * handle with status/diagnostics. Safe to\n * call again (no-op after first init, but\n * validates incompatible config changes).\n *\n * registerIonicComponents(...definers) — incremental & idempotent. Always\n * registers new definers, skips already-\n * registered custom elements. Works for\n * lazy route loading.\n *\n * registerIonicons(map) — incremental with collision diagnostics.\n * Merges new icons into the global set;\n * warns on name collisions.\n *\n * setupElurIonic(options) — backward-compatible facade that calls all\n * three. Existing apps work unchanged.\n *\n * Key changes vs v1.x:\n * - No more `isInitialized` blocking: `registerIonicComponents` and\n * `registerIonicons` are always incremental.\n * - No `unpkg@latest` default asset path: uses official `setAssetPath` from\n * ionicons. CDN is opt-in only.\n * - SSR-safe: no `window` access at module load; guards in each function.\n * - Returns a handle with diagnostics from `initializeElurIonic`.\n */\n\nimport { initialize } from \"@ionic/core/components\";\n\n// Minimal core components — the bare minimum any elur-ionic app needs.\nimport { defineCustomElement as defineIonApp } from \"@ionic/core/components/ion-app.js\";\nimport { defineCustomElement as defineIonRouterOutlet } from \"@ionic/core/components/ion-router-outlet.js\";\nimport { defineCustomElement as defineIonBackButton } from \"@ionic/core/components/ion-back-button.js\";\nimport { defineCustomElement as defineIonButtons } from \"@ionic/core/components/ion-buttons.js\";\n\n// Icons\nimport { defineCustomElement as defineIonIcon } from \"ionicons/components/ion-icon.js\";\nimport { addIcons, setAssetPath } from \"ionicons\";\nimport { arrowBack, arrowBackSharp, chevronBack, chevronBackSharp } from \"ionicons/icons\";\n\nexport type ComponentDefiner = () => void;\nexport type IconDefinitionMap = Record<string, string>;\n\nexport interface SetupElurIonicOptions {\n /** @deprecated Use `icons` mode in `initializeElurIonic` instead. */\n iconAssetPath?: string;\n components?: ComponentDefiner[];\n icons?: IconDefinitionMap;\n}\n\nexport interface InitializeOptions {\n /**\n * Icon asset strategy:\n * - \"inline\" (default): icons are inlined via addIcons; no remote fetch.\n * - \"assets\": use setAssetPath to a local URL; icons fetched on demand.\n * - object with `mode: \"assets\"` and `path` for explicit local path.\n */\n icons?: \"inline\" | \"assets\" | { mode: \"assets\"; path: string };\n /** Ionic mode override: \"ios\" | \"md\" | undefined (auto-detect). */\n mode?: \"ios\" | \"md\";\n}\n\nexport interface SetupHandle {\n /** True if this call performed the initialization; false if already init. */\n readonly initialized: boolean;\n /** Diagnostics collected during initialization. */\n readonly diagnostics: string[];\n}\n\n// --- Internal registry state ---\n\nconst _coreDefiners: ComponentDefiner[] = [\n defineIonApp,\n defineIonRouterOutlet,\n defineIonBackButton,\n defineIonButtons,\n defineIonIcon,\n];\n\nconst _defaultIcons: IconDefinitionMap = {\n \"arrow-back\": arrowBack,\n \"arrow-back-sharp\": arrowBackSharp,\n \"chevron-back\": chevronBack,\n \"chevron-back-sharp\": chevronBackSharp,\n};\n\nlet _initialized = false;\nconst _registeredIconNames = new Set<string>();\n\nfunction _hasWindow(): boolean {\n return typeof window !== \"undefined\";\n}\n\nfunction _hasCustomElements(): boolean {\n return typeof customElements !== \"undefined\";\n}\n\n/**\n * Initialize Ionic Core for Elur. Configures the runtime once.\n *\n * Subsequent calls are no-ops for the core init, but `registerIonicComponents`\n * and `registerIonicons` remain incremental regardless.\n *\n * Returns a handle with diagnostics.\n */\nexport function initializeElurIonic(options: InitializeOptions = {}): SetupHandle {\n const diagnostics: string[] = [];\n\n if (!_hasWindow()) {\n // SSR/prerender: do not touch DOM. Module is import-safe.\n return { initialized: false, diagnostics: [\"SSR: window unavailable, skipping init\"] };\n }\n\n if (_initialized) {\n // Validate incompatible config changes after init.\n if (options.mode) {\n diagnostics.push(\"mode cannot be changed after initialization; ignoring\");\n }\n return { initialized: false, diagnostics };\n }\n\n // Icon asset strategy\n const iconsCfg = options.icons ?? \"inline\";\n if (iconsCfg === \"inline\") {\n // Default: no remote asset path. Icons are inlined via addIcons.\n // setAssetPath to empty string prevents any CDN fetch.\n setAssetPath(\"\");\n } else if (typeof iconsCfg === \"object\" && iconsCfg.mode === \"assets\") {\n setAssetPath(iconsCfg.path);\n } else if (iconsCfg === \"assets\") {\n // \"assets\" mode without explicit path — use a sensible default\n // relative to the document base.\n const base = document.baseURI || \"/\";\n setAssetPath(new URL(\"assets/icons/\", base).href);\n }\n\n // Initialize Ionic Core\n initialize();\n\n // Register minimal core components\n for (const definer of _coreDefiners) {\n definer();\n }\n\n // Register default back icons (used by IonBackButton)\n addIcons(_defaultIcons);\n for (const name of Object.keys(_defaultIcons)) {\n _registeredIconNames.add(name);\n }\n\n _initialized = true;\n\n return { initialized: true, diagnostics };\n}\n\n/**\n * Register additional Ionic custom element definers. Incremental and\n * idempotent — always processes new definers, safe to call from lazy routes.\n *\n * @example\n * ```ts\n * // In a lazy route module:\n * import { defineCustomElement as defineIonDatetime } from \"@ionic/core/components/ion-datetime.js\";\n * registerIonicComponents(defineIonDatetime);\n * ```\n */\nexport function registerIonicComponents(...definers: ComponentDefiner[]): void {\n if (!_hasCustomElements()) {\n if (_hasWindow()) {\n console.warn(\"[elur-ionic] customElements unavailable; cannot register components\");\n }\n return;\n }\n\n for (const definer of definers) {\n try {\n definer();\n } catch (e) {\n // Ionic definers internally guard against double-registration,\n // but we catch just in case.\n if (e instanceof Error && !e.message.includes(\"already been registered\")) {\n console.warn(`[elur-ionic] Component registration error: ${e.message}`);\n }\n }\n }\n}\n\n/**\n * Register additional Ionicons by name → SVG string mapping. Incremental\n * with collision diagnostics.\n *\n * @example\n * ```ts\n * import { registerIonicons } from \"@elurjs/ionic\";\n * import { home, homeOutline } from \"ionicons/icons\";\n *\n * registerIonicons({ home, \"home-outline\": homeOutline });\n * ```\n */\nexport function registerIonicons(map: IconDefinitionMap): void {\n if (!_hasWindow()) {\n return;\n }\n\n const toAdd: IconDefinitionMap = {};\n for (const [name, svg] of Object.entries(map)) {\n if (_registeredIconNames.has(name)) {\n // Overwriting is allowed (addIcons merges), but warn in dev.\n console.warn(`[elur-ionic] Icon \"${name}\" already registered; overwriting.`);\n }\n toAdd[name] = svg;\n _registeredIconNames.add(name);\n }\n\n if (Object.keys(toAdd).length > 0) {\n addIcons(toAdd);\n }\n}\n\n/**\n * Backward-compatible facade. Calls `initializeElurIonic`, then registers\n * any extra components and icons passed via options.\n *\n * Existing v1.x apps work unchanged. New apps should prefer the granular\n * functions (`initializeElurIonic` + `registerIonicComponents` + `registerIonicons`)\n * for lazy loading and HMR support.\n *\n * @deprecated Prefer `initializeElurIonic` + `registerIonicComponents` + `registerIonicons` for new code.\n */\nexport function setupElurIonic(options: SetupElurIonicOptions = {}): void {\n if (!_hasWindow()) return;\n\n // Map old options to new init\n const initOpts: InitializeOptions = {};\n if (options.iconAssetPath) {\n initOpts.icons = { mode: \"assets\", path: options.iconAssetPath };\n }\n\n const handle = initializeElurIonic(initOpts);\n\n // Register extra components (always incremental, even after init)\n if (options.components) {\n registerIonicComponents(...options.components);\n }\n\n // Register extra icons (always incremental, even after init)\n if (options.icons) {\n registerIonicons(options.icons);\n }\n\n void handle;\n}\n\nexport { addIcons, setAssetPath };\n","/**\n * @elurjs/ionic / tabs.ts — v2\n *\n * Bottom tab bar that drives navigation through the core router. The visual\n * \"active\" state is computed from `elurRouter().current` directly.\n *\n * Tab switches are intentionally direction:\"none\" — Ionic's convention is no\n * animation between tabs. Per-tab stacks (configured on IonRouterOutlet via\n * `tabs: [...]`) preserve each tab's deep view across switches.\n */\n\nimport { html, ElurComponent, effect, ref, nextTick } from \"@elurjs/core\";\nimport type { ElurTemplate } from \"@elurjs/core\";\nimport { elurRouter, type NavigationDirection } from \"@elurjs/core\";\nimport { addIcons, type IconDefinitionMap } from \"./setup.js\";\n\n/** Layout of icon and label inside each tab button. */\nexport type TabButtonLayout =\n | \"icon-top\"\n | \"icon-start\"\n | \"icon-end\"\n | \"icon-bottom\"\n | \"icon-hide\"\n | \"label-hide\";\n\nexport interface BottomTabItem {\n path: string;\n label: string;\n icon?: string;\n activeIcon?: string;\n exact?: boolean;\n tabId?: string;\n /** Badge text or number (e.g. notification count). */\n badge?: string | number;\n /** Badge color (Ionic color name). Default: \"danger\". */\n badgeColor?: string;\n}\n\nexport interface BottomTabBarOptions {\n slot?: \"top\" | \"bottom\";\n className?: string;\n hiddenPaths?: string[];\n /**\n * Direction passed to the router on tab change.\n * Default `\"none\"` — no animation, native Ionic feel.\n */\n navigationDirection?: NavigationDirection;\n hideWhen?: (path: string) => boolean;\n /**\n * Icon SVG data to register for the tab bar icons.\n *\n * The Vite plugin can only detect static `name=\"icon-name\"` in html``\n * templates. Tab bar icons are dynamic, so pass the data here.\n */\n icons?: IconDefinitionMap;\n /**\n * Layout of icon and label inside each tab button.\n * Default: `\"icon-top\"`.\n */\n layout?: TabButtonLayout;\n /**\n * CSS custom properties to set on the `ion-tab-bar` element.\n * Useful for theming: `--background`, `--color`, `--color-selected`, etc.\n *\n * @example\n * ```ts\n * createBottomTabBar(tabs, {\n * cssVars: {\n * \"--background\": \"#1a1a2e\",\n * \"--color-selected\": \"#00ff88\",\n * },\n * });\n * ```\n */\n cssVars?: Record<string, string>;\n}\n\nfunction _normalizePath(p: string): string {\n if (!p || p === \"/\") return \"/\";\n return p.endsWith(\"/\") ? p.slice(0, -1) : p;\n}\n\nfunction _isActive(tab: BottomTabItem, currentPath: string): boolean {\n const cur = _normalizePath(currentPath);\n const tgt = _normalizePath(tab.path);\n if (tab.exact) return cur === tgt;\n if (tgt === \"/\") return cur === \"/\";\n return cur === tgt || cur.startsWith(`${tgt}/`);\n}\n\nfunction _isHidden(path: string, patterns?: string[]): boolean {\n if (!patterns?.length) return false;\n const cur = _normalizePath(path);\n return patterns.some((pat) => {\n const norm = _normalizePath(pat);\n if (norm.endsWith(\"/*\")) {\n const base = norm.slice(0, -2);\n return cur === base || cur.startsWith(`${base}/`);\n }\n return cur === norm;\n });\n}\n\n/** Convert a cssVars record to a CSS string for the style attribute. */\nfunction _cssVarsToString(vars: Record<string, string> | undefined): string {\n if (!vars) return \"\";\n return Object.entries(vars)\n .map(([k, v]) => `${k}: ${v}`)\n .join(\"; \");\n}\n\nexport function createBottomTabBar(\n tabs: BottomTabItem[],\n options: BottomTabBarOptions = {},\n): ElurTemplate {\n const router = elurRouter();\n const slot = options.slot ?? \"bottom\";\n const className = options.className ?? \"elur-ion-tab-bar\";\n const direction: NavigationDirection = options.navigationDirection ?? \"none\";\n const layout: TabButtonLayout = options.layout ?? \"icon-top\";\n const cssVars = options.cssVars;\n\n // Register icons if provided.\n if (options.icons) {\n addIcons(options.icons);\n }\n\n // Stencil boolean props (like `selected`) cannot be set via HTML\n // attributes with Elur. We use an effect to set the JS property\n // directly on each ion-tab-button after it's in the DOM, and\n // re-sync whenever the route changes.\n const tabBarRef = ref<HTMLElement>();\n let synced = false;\n effect(() => {\n const currentPath = router.current.value;\n const tabBarEl = tabBarRef.el;\n if (!tabBarEl) {\n if (!synced) {\n nextTick(() => {\n synced = true;\n const el = tabBarRef.el;\n if (!el) return;\n const btns = el.querySelectorAll(\"ion-tab-button\");\n btns.forEach((btn, i) => {\n const tab = tabs[i];\n if (!tab) return;\n (btn as any).selected = _isActive(tab, router.current.value);\n });\n });\n }\n return;\n }\n const buttons = tabBarEl.querySelectorAll(\"ion-tab-button\");\n buttons.forEach((btn, i) => {\n const tab = tabs[i];\n if (!tab) return;\n const isActive = _isActive(tab, currentPath);\n (btn as any).selected = isActive;\n });\n });\n\n return html`\n <ion-tab-bar\n slot=${slot}\n class=${className}\n ref=${tabBarRef}\n style=${() => {\n const path = router.current.value;\n const hidden = options.hideWhen\n ? options.hideWhen(path)\n : _isHidden(path, options.hiddenPaths);\n const vars = _cssVarsToString(cssVars);\n const display = hidden ? \"display:none\" : \"\";\n return [vars, display].filter(Boolean).join(\"; \");\n }}\n >\n ${tabs.map((tab) => {\n const computedTabId = tab.path === \"/\"\n ? \"root\"\n : _normalizePath(tab.path).replace(/^\\//, \"\").replace(/\\//g, \"-\");\n const tabId = tab.tabId ?? computedTabId;\n\n return html`\n <ion-tab-button\n tab=${tabId}\n layout=${layout}\n @click.prevent.stop=${() => {\n // .prevent.stop prevents Ionic's internal tab selection\n // (which looks for <ion-tab> children we don't have).\n // We drive navigation through the Elur router instead.\n if (_isActive(tab, router.current.value)) {\n router.replace(tab.path, { direction: \"none\" });\n } else {\n router.navigate(tab.path, { direction });\n }\n }}\n >\n ${tab.icon\n ? html`\n <ion-icon\n name=${() => {\n const active = _isActive(tab, router.current.value);\n return active && tab.activeIcon ? tab.activeIcon : tab.icon;\n }}\n ></ion-icon>\n `\n : \"\"}\n <ion-label>${tab.label}</ion-label>\n ${tab.badge != null\n ? html`<ion-badge color=${tab.badgeColor ?? \"danger\"}>${tab.badge}</ion-badge>`\n : \"\"}\n </ion-tab-button>\n `;\n })}\n </ion-tab-bar>\n `;\n}\n\n/**\n * Wraps an IonRouterOutlet and a tab bar in <ion-tabs>.\n *\n * <ion-tabs> provides the correct CSS layout context: the outlet fills\n * the available space and the tab bar sits at the bottom (or top).\n *\n * We use <ion-tabs> for layout only — navigation is driven by the\n * Elur router via the @click handler on each <ion-tab-button>, not\n * by Ionic's internal tab selection. The tab buttons have `tab` IDs\n * so Ionic doesn't warn, but there are no <ion-tab> children.\n *\n * A small CSS snippet is injected to ensure <ion-tabs> fills its\n * parent and the absolutely-positioned <ion-router-outlet> doesn't\n * collapse the layout.\n */\nexport function createTabsLayout(\n outlet: ElurTemplate | ElurComponent,\n tabBar: ElurTemplate,\n): ElurTemplate {\n _injectTabsLayoutStyles();\n const outletTemplate = outlet instanceof ElurComponent ? outlet.render() : outlet;\n return html`\n <ion-tabs>\n ${outletTemplate}\n ${tabBar}\n </ion-tabs>\n `;\n}\n\n/** Inject the tabs layout CSS once (idempotent). */\nlet _tabsStylesInjected = false;\nfunction _injectTabsLayoutStyles(): void {\n if (_tabsStylesInjected) return;\n if (typeof document === \"undefined\") return;\n _tabsStylesInjected = true;\n const style = document.createElement(\"style\");\n style.id = \"elur-ionic-tabs-layout\";\n // ion-tabs defaults to display:block with no explicit height, which\n // collapses to the tab bar's height because ion-router-outlet is\n // position:absolute. Force ion-tabs to fill its parent and use flexbox\n // so the outlet takes the remaining space above the tab bar.\n style.textContent = `\nion-tabs {\n display: flex !important;\n flex-direction: column !important;\n height: 100% !important;\n width: 100% !important;\n position: relative !important;\n}\nion-tabs > ion-router-outlet {\n flex: 1 1 0 !important;\n min-height: 0 !important;\n position: relative !important;\n top: auto !important;\n bottom: auto !important;\n left: auto !important;\n right: auto !important;\n}\nion-tabs > ion-tab-bar {\n flex-shrink: 0 !important;\n}\n`;\n document.head.appendChild(style);\n}\n"],"mappings":"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"}