@mhmo91/schmancy 0.4.92 → 0.4.93

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 (378) hide show
  1. package/ai/area.md +181 -968
  2. package/dist/ai/area.md +181 -968
  3. package/dist/{animated-text-CM1zqBki.cjs → animated-text-Dqrad7cv.cjs} +2 -2
  4. package/dist/{animated-text-CM1zqBki.cjs.map → animated-text-Dqrad7cv.cjs.map} +1 -1
  5. package/dist/{animated-text-CUFCt7Zg.js → animated-text-mNos9Gw8.js} +3 -3
  6. package/dist/{animated-text-CUFCt7Zg.js.map → animated-text-mNos9Gw8.js.map} +1 -1
  7. package/dist/animated-text.cjs +1 -1
  8. package/dist/animated-text.js +1 -1
  9. package/dist/area.cjs +1 -1
  10. package/dist/area.js +1 -1
  11. package/dist/{autocomplete-09_SfjsP.js → autocomplete-CMxXFeC_.js} +35 -35
  12. package/dist/autocomplete-CMxXFeC_.js.map +1 -0
  13. package/dist/{autocomplete-CFREt7Vm.cjs → autocomplete-CzYbBt-K.cjs} +6 -6
  14. package/dist/autocomplete-CzYbBt-K.cjs.map +1 -0
  15. package/dist/autocomplete.cjs +1 -1
  16. package/dist/autocomplete.js +1 -1
  17. package/dist/{avatar-C8PC_n9i.cjs → avatar-CGGPvamo.cjs} +21 -69
  18. package/dist/avatar-CGGPvamo.cjs.map +1 -0
  19. package/dist/{avatar-CKp3Ukk4.js → avatar-CH-EctMv.js} +152 -200
  20. package/dist/avatar-CH-EctMv.js.map +1 -0
  21. package/dist/badge.cjs +1 -1
  22. package/dist/badge.js +1 -1
  23. package/dist/{boat-Ddi4PegB.cjs → boat-feSRWu7P.cjs} +2 -2
  24. package/dist/{boat-Ddi4PegB.cjs.map → boat-feSRWu7P.cjs.map} +1 -1
  25. package/dist/{boat-DDJK4CS4.js → boat-xekVVZab.js} +2 -2
  26. package/dist/{boat-DDJK4CS4.js.map → boat-xekVVZab.js.map} +1 -1
  27. package/dist/boat.cjs +1 -1
  28. package/dist/boat.js +1 -1
  29. package/dist/busy.cjs +1 -1
  30. package/dist/busy.js +1 -1
  31. package/dist/button.cjs +1 -1
  32. package/dist/button.js +1 -1
  33. package/dist/card.cjs +1 -1
  34. package/dist/card.js +1 -1
  35. package/dist/{checkbox-BU1x0W8U.js → checkbox-DTfIF2XH.js} +2 -2
  36. package/dist/{checkbox-BU1x0W8U.js.map → checkbox-DTfIF2XH.js.map} +1 -1
  37. package/dist/{checkbox-TclkD2h5.cjs → checkbox-DwBANLb6.cjs} +2 -2
  38. package/dist/{checkbox-TclkD2h5.cjs.map → checkbox-DwBANLb6.cjs.map} +1 -1
  39. package/dist/checkbox.cjs +1 -1
  40. package/dist/checkbox.js +1 -1
  41. package/dist/{chips-Bxsoq1vm.js → chips-7TbOS1By.js} +56 -67
  42. package/dist/{chips-Bxsoq1vm.js.map → chips-7TbOS1By.js.map} +1 -1
  43. package/dist/{chips-DQBHJNSu.cjs → chips-DORDPg5b.cjs} +10 -21
  44. package/dist/{chips-DQBHJNSu.cjs.map → chips-DORDPg5b.cjs.map} +1 -1
  45. package/dist/chips.cjs +1 -1
  46. package/dist/chips.js +1 -1
  47. package/dist/code-highlight.cjs +1 -1
  48. package/dist/code-highlight.js +1 -1
  49. package/dist/{code-preview-DnUM87ZB.js → code-preview-DWDE2pUe.js} +2 -2
  50. package/dist/{code-preview-DnUM87ZB.js.map → code-preview-DWDE2pUe.js.map} +1 -1
  51. package/dist/{code-preview-C9Imx-RX.cjs → code-preview-DqFuxCjV.cjs} +2 -2
  52. package/dist/{code-preview-C9Imx-RX.cjs.map → code-preview-DqFuxCjV.cjs.map} +1 -1
  53. package/dist/components.cjs +1 -1
  54. package/dist/components.js +1 -1
  55. package/dist/content-drawer.cjs +1 -1
  56. package/dist/content-drawer.js +1 -1
  57. package/dist/{date-range-D1A1Xrmw.cjs → date-range-DwdO0vNv.cjs} +2 -2
  58. package/dist/{date-range-D1A1Xrmw.cjs.map → date-range-DwdO0vNv.cjs.map} +1 -1
  59. package/dist/{date-range-inline-CwLJLOe1.cjs → date-range-inline-B1WaAPY6.cjs} +2 -2
  60. package/dist/{date-range-inline-CwLJLOe1.cjs.map → date-range-inline-B1WaAPY6.cjs.map} +1 -1
  61. package/dist/{date-range-inline-Ca4DPfeR.js → date-range-inline-yYh4Uw-k.js} +3 -3
  62. package/dist/{date-range-inline-Ca4DPfeR.js.map → date-range-inline-yYh4Uw-k.js.map} +1 -1
  63. package/dist/date-range-inline.cjs +1 -1
  64. package/dist/date-range-inline.js +1 -1
  65. package/dist/{date-range-DF7MnRi3.js → date-range-s2EHTGQM.js} +4 -4
  66. package/dist/{date-range-DF7MnRi3.js.map → date-range-s2EHTGQM.js.map} +1 -1
  67. package/dist/date-range.cjs +1 -1
  68. package/dist/date-range.js +1 -1
  69. package/dist/{delay-hXu_bFxW.js → delay-D19Mpit_.js} +2 -2
  70. package/dist/{delay-hXu_bFxW.js.map → delay-D19Mpit_.js.map} +1 -1
  71. package/dist/{delay-DQKt6VVn.cjs → delay-l2gPaJoH.cjs} +2 -2
  72. package/dist/{delay-DQKt6VVn.cjs.map → delay-l2gPaJoH.cjs.map} +1 -1
  73. package/dist/delay.cjs +1 -1
  74. package/dist/delay.js +1 -1
  75. package/dist/{details-Ci0XXz0g.js → details-CEu4oDP7.js} +2 -2
  76. package/dist/{details-Ci0XXz0g.js.map → details-CEu4oDP7.js.map} +1 -1
  77. package/dist/{details-Ft0ivj0F.cjs → details-LNuoItTO.cjs} +2 -2
  78. package/dist/{details-Ft0ivj0F.cjs.map → details-LNuoItTO.cjs.map} +1 -1
  79. package/dist/details.cjs +1 -1
  80. package/dist/details.js +1 -1
  81. package/dist/{dialog-content-7tFlrTFn.cjs → dialog-content-6wVlm9RL.cjs} +2 -2
  82. package/dist/{dialog-content-7tFlrTFn.cjs.map → dialog-content-6wVlm9RL.cjs.map} +1 -1
  83. package/dist/{dialog-content-DXnLwUtv.js → dialog-content-CQ3Xi4_b.js} +4 -4
  84. package/dist/{dialog-content-DXnLwUtv.js.map → dialog-content-CQ3Xi4_b.js.map} +1 -1
  85. package/dist/dialog-service-CgJH8clD.cjs +2 -0
  86. package/dist/dialog-service-CgJH8clD.cjs.map +1 -0
  87. package/dist/{dialog-service-DwhuICgc.js → dialog-service-PQ9ssbsY.js} +53 -47
  88. package/dist/dialog-service-PQ9ssbsY.js.map +1 -0
  89. package/dist/dialog.cjs +1 -1
  90. package/dist/dialog.js +2 -2
  91. package/dist/directives.cjs +1 -1
  92. package/dist/directives.js +1 -1
  93. package/dist/divider-5OCZNBJ7.js +22 -0
  94. package/dist/divider-5OCZNBJ7.js.map +1 -0
  95. package/dist/divider-auzbAyaR.cjs +2 -0
  96. package/dist/divider-auzbAyaR.cjs.map +1 -0
  97. package/dist/divider.cjs +1 -1
  98. package/dist/divider.js +1 -1
  99. package/dist/{dropdown-content-CXxTjA0j.cjs → dropdown-content-BI541LSK.cjs} +5 -10
  100. package/dist/dropdown-content-BI541LSK.cjs.map +1 -0
  101. package/dist/{dropdown-content-BCk2WbXc.js → dropdown-content-BLZviV1z.js} +40 -41
  102. package/dist/dropdown-content-BLZviV1z.js.map +1 -0
  103. package/dist/dropdown.cjs +1 -1
  104. package/dist/dropdown.js +1 -1
  105. package/dist/{email-recipients-BWIYYwA8.cjs → email-recipients-DizBUcJ2.cjs} +24 -24
  106. package/dist/email-recipients-DizBUcJ2.cjs.map +1 -0
  107. package/dist/{email-recipients-BT3xPoBN.js → email-recipients-JeGKXcBj.js} +141 -144
  108. package/dist/email-recipients-JeGKXcBj.js.map +1 -0
  109. package/dist/extra.cjs +1 -1
  110. package/dist/extra.js +1 -1
  111. package/dist/{flex-DflXFgVs.cjs → flex-BN7HdoGW.cjs} +2 -2
  112. package/dist/{flex-DflXFgVs.cjs.map → flex-BN7HdoGW.cjs.map} +1 -1
  113. package/dist/{flex-DJEZ1DdQ.js → flex-ro_7y02P.js} +2 -2
  114. package/dist/{flex-DJEZ1DdQ.js.map → flex-ro_7y02P.js.map} +1 -1
  115. package/dist/{form-7OiDtJT4.js → form-BqGTSZpr.js} +11 -23
  116. package/dist/form-BqGTSZpr.js.map +1 -0
  117. package/dist/form-DT6f2KNH.cjs +2 -0
  118. package/dist/form-DT6f2KNH.cjs.map +1 -0
  119. package/dist/form.cjs +1 -1
  120. package/dist/form.js +1 -1
  121. package/dist/{formField.mixin-B1vJlhmI.cjs → formField.mixin-CSy0dZ7Q.cjs} +2 -2
  122. package/dist/{formField.mixin-B1vJlhmI.cjs.map → formField.mixin-CSy0dZ7Q.cjs.map} +1 -1
  123. package/dist/{formField.mixin-3i7VOHMH.js → formField.mixin-DtegNyKv.js} +2 -2
  124. package/dist/{formField.mixin-3i7VOHMH.js.map → formField.mixin-DtegNyKv.js.map} +1 -1
  125. package/dist/{icon-BMhWh8Ib.js → icon-CSxxuGxN.js} +2 -2
  126. package/dist/{icon-BMhWh8Ib.js.map → icon-CSxxuGxN.js.map} +1 -1
  127. package/dist/{icon-TPLdDnCq.cjs → icon-GaL2G_1M.cjs} +2 -2
  128. package/dist/{icon-TPLdDnCq.cjs.map → icon-GaL2G_1M.cjs.map} +1 -1
  129. package/dist/{icon-button-DOZuY9x8.js → icon-button-B0jLowAy.js} +5 -5
  130. package/dist/icon-button-B0jLowAy.js.map +1 -0
  131. package/dist/{icon-button-CLDy5tUS.cjs → icon-button-DkvwZOHF.cjs} +4 -4
  132. package/dist/icon-button-DkvwZOHF.cjs.map +1 -0
  133. package/dist/icons.cjs +1 -1
  134. package/dist/icons.js +1 -1
  135. package/dist/index.cjs +1 -1
  136. package/dist/index.js +49 -49
  137. package/dist/{input-Dre3bMuF.js → input-D0c-WhDi.js} +40 -44
  138. package/dist/input-D0c-WhDi.js.map +1 -0
  139. package/dist/input-fPWOjQgP.cjs +51 -0
  140. package/dist/input-fPWOjQgP.cjs.map +1 -0
  141. package/dist/input.cjs +1 -1
  142. package/dist/input.js +1 -1
  143. package/dist/layout.cjs +1 -1
  144. package/dist/layout.js +1 -1
  145. package/dist/lazy-DObpkuL6.cjs.map +1 -1
  146. package/dist/lazy-E2LCDm7n.js.map +1 -1
  147. package/dist/{list-2mBZmMCP.js → list-3Ity7MFT.js} +2 -2
  148. package/dist/{list-2mBZmMCP.js.map → list-3Ity7MFT.js.map} +1 -1
  149. package/dist/{list-DZ43cTnR.cjs → list-CbXXjBUM.cjs} +2 -2
  150. package/dist/{list-DZ43cTnR.cjs.map → list-CbXXjBUM.cjs.map} +1 -1
  151. package/dist/list.cjs +1 -1
  152. package/dist/list.js +1 -1
  153. package/dist/{litElement.mixin-CjRG_9tZ.cjs → litElement.mixin-DFG5Ckp7.cjs} +2 -2
  154. package/dist/{litElement.mixin-CjRG_9tZ.cjs.map → litElement.mixin-DFG5Ckp7.cjs.map} +1 -1
  155. package/dist/{litElement.mixin-Bj0zv3lK.js → litElement.mixin-Efwm8boA.js} +2 -2
  156. package/dist/{litElement.mixin-Bj0zv3lK.js.map → litElement.mixin-Efwm8boA.js.map} +1 -1
  157. package/dist/mailbox.cjs +1 -1
  158. package/dist/mailbox.js +1 -1
  159. package/dist/{map-sSS6ACVH.js → map-BCQwFMpm.js} +2 -2
  160. package/dist/{map-sSS6ACVH.js.map → map-BCQwFMpm.js.map} +1 -1
  161. package/dist/{map-D69SEPpf.cjs → map-DeRVVjHa.cjs} +2 -2
  162. package/dist/{map-D69SEPpf.cjs.map → map-DeRVVjHa.cjs.map} +1 -1
  163. package/dist/map.cjs +1 -1
  164. package/dist/map.js +1 -1
  165. package/dist/media-CL9LNHic.cjs +226 -0
  166. package/dist/media-CL9LNHic.cjs.map +1 -0
  167. package/dist/media-nVQjNoX7.js +307 -0
  168. package/dist/media-nVQjNoX7.js.map +1 -0
  169. package/dist/{menu-CATzB9tA.js → menu-CusvB2dY.js} +3 -3
  170. package/dist/{menu-CATzB9tA.js.map → menu-CusvB2dY.js.map} +1 -1
  171. package/dist/{menu-BOeTdvk_.cjs → menu-Delwe6al.cjs} +2 -2
  172. package/dist/{menu-BOeTdvk_.cjs.map → menu-Delwe6al.cjs.map} +1 -1
  173. package/dist/menu.cjs +1 -1
  174. package/dist/menu.js +1 -1
  175. package/dist/nav-drawer.cjs +1 -1
  176. package/dist/nav-drawer.js +1 -1
  177. package/dist/{notification-service-LnNx5EDh.cjs → notification-service-BwcUY8O5.cjs} +7 -7
  178. package/dist/notification-service-BwcUY8O5.cjs.map +1 -0
  179. package/dist/{notification-service-DrwmIgoR.js → notification-service-DiTgelcm.js} +62 -58
  180. package/dist/notification-service-DiTgelcm.js.map +1 -0
  181. package/dist/notification.cjs +1 -1
  182. package/dist/notification.js +2 -2
  183. package/dist/{notify-DQMcgjgZ.cjs → notify-C81e8flx.cjs} +2 -2
  184. package/dist/{notify-DQMcgjgZ.cjs.map → notify-C81e8flx.cjs.map} +1 -1
  185. package/dist/{notify-C41nYdUf.js → notify-JNbirYT5.js} +2 -2
  186. package/dist/{notify-C41nYdUf.js.map → notify-JNbirYT5.js.map} +1 -1
  187. package/dist/{option-BNKGfKgL.cjs → option-D4XcuvRK.cjs} +5 -5
  188. package/dist/option-D4XcuvRK.cjs.map +1 -0
  189. package/dist/{option-DbBr0StZ.js → option-dihFw6qv.js} +12 -12
  190. package/dist/option-dihFw6qv.js.map +1 -0
  191. package/dist/option.cjs +1 -1
  192. package/dist/option.js +1 -1
  193. package/dist/{payment-card-form-ByWbYHhd.cjs → payment-card-form-CIm57Nfa.cjs} +2 -2
  194. package/dist/{payment-card-form-ByWbYHhd.cjs.map → payment-card-form-CIm57Nfa.cjs.map} +1 -1
  195. package/dist/{payment-card-form-_jHodv7G.js → payment-card-form-pDuTrWgZ.js} +3 -3
  196. package/dist/{payment-card-form-_jHodv7G.js.map → payment-card-form-pDuTrWgZ.js.map} +1 -1
  197. package/dist/{progress-BY7K7Etz.cjs → progress-BETtTl0y.cjs} +2 -2
  198. package/dist/{progress-BY7K7Etz.cjs.map → progress-BETtTl0y.cjs.map} +1 -1
  199. package/dist/{progress-Cix7Mu1p.js → progress-C4o_zWvg.js} +2 -2
  200. package/dist/{progress-Cix7Mu1p.js.map → progress-C4o_zWvg.js.map} +1 -1
  201. package/dist/progress.cjs +1 -1
  202. package/dist/progress.js +1 -1
  203. package/dist/{radio-button-BNmjg-i9.js → radio-button-DaSKbB-Z.js} +27 -27
  204. package/dist/radio-button-DaSKbB-Z.js.map +1 -0
  205. package/dist/radio-button-h6y0tWJQ.cjs +41 -0
  206. package/dist/radio-button-h6y0tWJQ.cjs.map +1 -0
  207. package/dist/radio-group.cjs +1 -1
  208. package/dist/radio-group.js +1 -1
  209. package/dist/{ripple-BumgqsDT.js → ripple-Cy-nvO8W.js} +24 -22
  210. package/dist/ripple-Cy-nvO8W.js.map +1 -0
  211. package/dist/ripple-DqQrvaTe.cjs +16 -0
  212. package/dist/ripple-DqQrvaTe.cjs.map +1 -0
  213. package/dist/route.component-BaefEO15.js +320 -0
  214. package/dist/route.component-BaefEO15.js.map +1 -0
  215. package/dist/route.component-DzBfI9eE.cjs +12 -0
  216. package/dist/route.component-DzBfI9eE.cjs.map +1 -0
  217. package/dist/{schmancy-steps-container-D69TfC2I.cjs → schmancy-steps-container-DpM5Kvt3.cjs} +2 -2
  218. package/dist/{schmancy-steps-container-D69TfC2I.cjs.map → schmancy-steps-container-DpM5Kvt3.cjs.map} +1 -1
  219. package/dist/{schmancy-steps-container-BUE4fG8_.js → schmancy-steps-container-uRaJiCZE.js} +2 -2
  220. package/dist/{schmancy-steps-container-BUE4fG8_.js.map → schmancy-steps-container-uRaJiCZE.js.map} +1 -1
  221. package/dist/select-ClFVeWZA.cjs +57 -0
  222. package/dist/select-ClFVeWZA.cjs.map +1 -0
  223. package/dist/{select-Bspcrc-h.js → select-uQ5xnOKn.js} +16 -16
  224. package/dist/select-uQ5xnOKn.js.map +1 -0
  225. package/dist/select.cjs +1 -1
  226. package/dist/select.js +1 -1
  227. package/dist/{sheet-CuE9tUeo.cjs → sheet-CEcMgg-2.cjs} +2 -2
  228. package/dist/{sheet-CuE9tUeo.cjs.map → sheet-CEcMgg-2.cjs.map} +1 -1
  229. package/dist/{sheet-BxOGSGJ0.js → sheet-CvvdxIUZ.js} +3 -3
  230. package/dist/{sheet-BxOGSGJ0.js.map → sheet-CvvdxIUZ.js.map} +1 -1
  231. package/dist/sheet.cjs +1 -1
  232. package/dist/sheet.js +1 -1
  233. package/dist/{slider-ChQVbnYO.js → slider-DyxIZ-hn.js} +3 -3
  234. package/dist/{slider-ChQVbnYO.js.map → slider-DyxIZ-hn.js.map} +1 -1
  235. package/dist/{slider-DeKwZONn.cjs → slider-T8sYw1p-.cjs} +2 -2
  236. package/dist/{slider-DeKwZONn.cjs.map → slider-T8sYw1p-.cjs.map} +1 -1
  237. package/dist/slider.cjs +1 -1
  238. package/dist/slider.js +1 -1
  239. package/dist/{spinner-y1dPMTQp.js → spinner-D9fC8P3H.js} +2 -2
  240. package/dist/{spinner-y1dPMTQp.js.map → spinner-D9fC8P3H.js.map} +1 -1
  241. package/dist/{spinner-C5tMQys5.cjs → spinner-DJviKuwJ.cjs} +2 -2
  242. package/dist/{spinner-C5tMQys5.cjs.map → spinner-DJviKuwJ.cjs.map} +1 -1
  243. package/dist/steps.cjs +1 -1
  244. package/dist/steps.js +1 -1
  245. package/dist/{surface-4MzhEaru.cjs → surface-B_SGQ1f7.cjs} +2 -2
  246. package/dist/{surface-4MzhEaru.cjs.map → surface-B_SGQ1f7.cjs.map} +1 -1
  247. package/dist/{surface-BYmdH754.js → surface-CUyYCpFl.js} +2 -2
  248. package/dist/{surface-BYmdH754.js.map → surface-CUyYCpFl.js.map} +1 -1
  249. package/dist/surface.cjs +1 -1
  250. package/dist/surface.js +1 -1
  251. package/dist/{table-J5EVvpXy.cjs → table-C-sWuoAy.cjs} +2 -2
  252. package/dist/{table-J5EVvpXy.cjs.map → table-C-sWuoAy.cjs.map} +1 -1
  253. package/dist/{table-YBHaxQzQ.js → table-D7p7a-Ag.js} +2 -2
  254. package/dist/{table-YBHaxQzQ.js.map → table-D7p7a-Ag.js.map} +1 -1
  255. package/dist/table.cjs +1 -1
  256. package/dist/table.js +1 -1
  257. package/dist/{tabs-compatibility-ezB19WI8.js → tabs-compatibility-Dn8bSEvA.js} +2 -2
  258. package/dist/{tabs-compatibility-ezB19WI8.js.map → tabs-compatibility-Dn8bSEvA.js.map} +1 -1
  259. package/dist/{tabs-compatibility-JMTsaND_.cjs → tabs-compatibility-XoF2vpv5.cjs} +2 -2
  260. package/dist/{tabs-compatibility-JMTsaND_.cjs.map → tabs-compatibility-XoF2vpv5.cjs.map} +1 -1
  261. package/dist/tabs.cjs +1 -1
  262. package/dist/tabs.js +1 -1
  263. package/dist/tailwind.mixin-C13RR5x6.js +43 -0
  264. package/dist/{tailwind.mixin-Cwbr8x57.js.map → tailwind.mixin-C13RR5x6.js.map} +1 -1
  265. package/dist/tailwind.mixin-O9jmUJ7m.cjs +2 -0
  266. package/dist/{tailwind.mixin-B-VcpMHn.cjs.map → tailwind.mixin-O9jmUJ7m.cjs.map} +1 -1
  267. package/dist/teleport.cjs +1 -1
  268. package/dist/teleport.js +1 -1
  269. package/dist/{textarea-B3nWhCra.cjs → textarea-9rSwC34M.cjs} +2 -2
  270. package/dist/{textarea-B3nWhCra.cjs.map → textarea-9rSwC34M.cjs.map} +1 -1
  271. package/dist/{textarea-yn7IFbnu.js → textarea-Dsqg9ted.js} +3 -3
  272. package/dist/{textarea-yn7IFbnu.js.map → textarea-Dsqg9ted.js.map} +1 -1
  273. package/dist/textarea.cjs +1 -1
  274. package/dist/textarea.js +1 -1
  275. package/dist/{theme-button-I_c1ZWWV.cjs → theme-button-BTH2A59w.cjs} +2 -2
  276. package/dist/{theme-button-I_c1ZWWV.cjs.map → theme-button-BTH2A59w.cjs.map} +1 -1
  277. package/dist/{theme-button-CGArg1pu.js → theme-button-pfkAwkvY.js} +2 -2
  278. package/dist/{theme-button-CGArg1pu.js.map → theme-button-pfkAwkvY.js.map} +1 -1
  279. package/dist/theme-button.cjs +1 -1
  280. package/dist/theme-button.js +1 -1
  281. package/dist/theme.cjs +1 -1
  282. package/dist/{theme.component-CdSDaeU0.cjs → theme.component-BvoZuM2h.cjs} +3 -3
  283. package/dist/{theme.component-CdSDaeU0.cjs.map → theme.component-BvoZuM2h.cjs.map} +1 -1
  284. package/dist/{theme.component-B5zp-4OG.js → theme.component-C3G_OrjE.js} +168 -168
  285. package/dist/{theme.component-B5zp-4OG.js.map → theme.component-C3G_OrjE.js.map} +1 -1
  286. package/dist/theme.js +1 -1
  287. package/dist/{timezone-DRBf5biI.cjs → timezone-BKBME7Gq.cjs} +2 -2
  288. package/dist/{timezone-DRBf5biI.cjs.map → timezone-BKBME7Gq.cjs.map} +1 -1
  289. package/dist/{timezone-CepyC8kw.js → timezone-mQeoU0_O.js} +3 -3
  290. package/dist/{timezone-CepyC8kw.js.map → timezone-mQeoU0_O.js.map} +1 -1
  291. package/dist/tooltip-Bcun7m0S.cjs +7 -0
  292. package/dist/tooltip-Bcun7m0S.cjs.map +1 -0
  293. package/dist/{tooltip-C6HlAqs2.js → tooltip-Doh_evJW.js} +55 -55
  294. package/dist/tooltip-Doh_evJW.js.map +1 -0
  295. package/dist/tooltip.cjs +1 -1
  296. package/dist/tooltip.js +1 -1
  297. package/dist/{tree-CpqWMdfb.cjs → tree-DpKb9Q-1.cjs} +2 -2
  298. package/dist/{tree-CpqWMdfb.cjs.map → tree-DpKb9Q-1.cjs.map} +1 -1
  299. package/dist/{tree-CxJAr7G3.js → tree-cl3PdPTy.js} +2 -2
  300. package/dist/{tree-CxJAr7G3.js.map → tree-cl3PdPTy.js.map} +1 -1
  301. package/dist/tree.cjs +1 -1
  302. package/dist/tree.js +1 -1
  303. package/dist/{typewriter-BWg7Otk8.cjs → typewriter-QSd_xI9j.cjs} +3 -15
  304. package/dist/typewriter-QSd_xI9j.cjs.map +1 -0
  305. package/dist/{typewriter-D3QLAVdz.js → typewriter-peuqmq9f.js} +64 -76
  306. package/dist/typewriter-peuqmq9f.js.map +1 -0
  307. package/dist/typewriter.cjs +1 -1
  308. package/dist/typewriter.js +1 -1
  309. package/dist/{typography-C8NCP_rr.js → typography-BkuzOZ0g.js} +2 -2
  310. package/dist/{typography-C8NCP_rr.js.map → typography-BkuzOZ0g.js.map} +1 -1
  311. package/dist/{typography-DGOOlbC1.cjs → typography-BoI8HgTE.cjs} +2 -2
  312. package/dist/{typography-DGOOlbC1.cjs.map → typography-BoI8HgTE.cjs.map} +1 -1
  313. package/dist/typography.cjs +1 -1
  314. package/dist/typography.js +1 -1
  315. package/package.json +1 -1
  316. package/types/src/area/area.component.d.ts +8 -3
  317. package/types/src/area/area.service.d.ts +1 -0
  318. package/types/src/area/route.component.d.ts +4 -5
  319. package/types/src/area/utils.d.ts +2 -1
  320. package/types/src/card/card.d.ts +55 -3
  321. package/types/src/directives/ripple.d.ts +2 -1
  322. package/types/src/dropdown/dropdown-component.d.ts +1 -0
  323. package/types/src/form/form-v2.d.ts +0 -1
  324. package/types/src/form/form.d.ts +0 -1
  325. package/types/src/mailbox/email-editor.d.ts +1 -2
  326. package/types/src/notification/notification-audio.d.ts +9 -0
  327. package/types/src/notification/notification-container.d.ts +1 -0
  328. package/dist/autocomplete-09_SfjsP.js.map +0 -1
  329. package/dist/autocomplete-CFREt7Vm.cjs.map +0 -1
  330. package/dist/avatar-C8PC_n9i.cjs.map +0 -1
  331. package/dist/avatar-CKp3Ukk4.js.map +0 -1
  332. package/dist/dialog-service-DwhuICgc.js.map +0 -1
  333. package/dist/dialog-service-juvsgc5X.cjs +0 -2
  334. package/dist/dialog-service-juvsgc5X.cjs.map +0 -1
  335. package/dist/divider-BG9uDpUp.js +0 -103
  336. package/dist/divider-BG9uDpUp.js.map +0 -1
  337. package/dist/divider-CWnAg2p-.cjs +0 -83
  338. package/dist/divider-CWnAg2p-.cjs.map +0 -1
  339. package/dist/dropdown-content-BCk2WbXc.js.map +0 -1
  340. package/dist/dropdown-content-CXxTjA0j.cjs.map +0 -1
  341. package/dist/email-recipients-BT3xPoBN.js.map +0 -1
  342. package/dist/email-recipients-BWIYYwA8.cjs.map +0 -1
  343. package/dist/form-7OiDtJT4.js.map +0 -1
  344. package/dist/form-nHwPpyhJ.cjs +0 -14
  345. package/dist/form-nHwPpyhJ.cjs.map +0 -1
  346. package/dist/icon-button-CLDy5tUS.cjs.map +0 -1
  347. package/dist/icon-button-DOZuY9x8.js.map +0 -1
  348. package/dist/input-CqLneJhz.cjs +0 -51
  349. package/dist/input-CqLneJhz.cjs.map +0 -1
  350. package/dist/input-Dre3bMuF.js.map +0 -1
  351. package/dist/media-B-VIbSH_.js +0 -151
  352. package/dist/media-B-VIbSH_.js.map +0 -1
  353. package/dist/media-Cew1Mxkj.cjs +0 -100
  354. package/dist/media-Cew1Mxkj.cjs.map +0 -1
  355. package/dist/notification-service-DrwmIgoR.js.map +0 -1
  356. package/dist/notification-service-LnNx5EDh.cjs.map +0 -1
  357. package/dist/option-BNKGfKgL.cjs.map +0 -1
  358. package/dist/option-DbBr0StZ.js.map +0 -1
  359. package/dist/radio-button-BNmjg-i9.js.map +0 -1
  360. package/dist/radio-button-CYq6qTSb.cjs +0 -41
  361. package/dist/radio-button-CYq6qTSb.cjs.map +0 -1
  362. package/dist/ripple-BumgqsDT.js.map +0 -1
  363. package/dist/ripple-C2BHbhcS.cjs +0 -16
  364. package/dist/ripple-C2BHbhcS.cjs.map +0 -1
  365. package/dist/route.component-CzCd2fMa.cjs +0 -12
  366. package/dist/route.component-CzCd2fMa.cjs.map +0 -1
  367. package/dist/route.component-Q3rCkryr.js +0 -321
  368. package/dist/route.component-Q3rCkryr.js.map +0 -1
  369. package/dist/select-B-yc3JB7.cjs +0 -57
  370. package/dist/select-B-yc3JB7.cjs.map +0 -1
  371. package/dist/select-Bspcrc-h.js.map +0 -1
  372. package/dist/tailwind.mixin-B-VcpMHn.cjs +0 -2
  373. package/dist/tailwind.mixin-Cwbr8x57.js +0 -43
  374. package/dist/tooltip-C6HlAqs2.js.map +0 -1
  375. package/dist/tooltip-CCX8PidC.cjs +0 -7
  376. package/dist/tooltip-CCX8PidC.cjs.map +0 -1
  377. package/dist/typewriter-BWg7Otk8.cjs.map +0 -1
  378. package/dist/typewriter-D3QLAVdz.js.map +0 -1
package/dist/ai/area.md CHANGED
@@ -1,1069 +1,282 @@
1
- # Schmancy Area - Advanced Routing System
1
+ # Schmancy Area - Routing System
2
2
 
3
- Schmancy Area is a powerful, reactive routing and state management system for web components with RxJS integration. It supports nested routing, segment-based matching, navigation guards, and multiple independent router outlets.
3
+ Reactive routing system for web components using RxJS. Supports multiple outlets, guards, lazy loading, and nested routing.
4
4
 
5
- ## Core Components
6
-
7
- ### 1. `<schmancy-area>` - Router Outlet
8
- The main container that displays routed components.
5
+ ## Quick Start
9
6
 
10
7
  ```html
11
- <!-- Basic router outlet -->
12
- <schmancy-area
13
- name="main"
14
- default="home-component">
15
- </schmancy-area>
16
-
17
- <!-- With default component as element -->
18
- <schmancy-area
19
- name="sidebar"
20
- .default=${new MyDefaultComponent()}>
8
+ <!-- Define routes declaratively -->
9
+ <schmancy-area name="main" default="home-page">
10
+ <schmancy-route when="products" component="product-list"></schmancy-route>
11
+ <schmancy-route when="about" component="about-page"></schmancy-route>
12
+ <schmancy-route
13
+ when="admin"
14
+ component="admin-panel"
15
+ .guard=${authState$.asObservable()}
16
+ @redirect=${() => area.push({ component: 'login', area: 'main' })}>
17
+ </schmancy-route>
21
18
  </schmancy-area>
22
19
  ```
23
20
 
24
- ### 2. `<schmancy-route>` - Declarative Routing
25
- Define routes declaratively with segment matching and guards. Routes are detected via slot change detection and are evaluated in order.
26
-
27
- ```html
28
- <!-- Simple route -->
29
- <schmancy-route
30
- when="products" <!-- Matches 'products' segment in URL -->
31
- component="product-list"
32
- exact>
33
- </schmancy-route>
34
-
35
- <!-- Component tag name matching -->
36
- <schmancy-route
37
- when="product-detail" <!-- Matches when component is 'product-detail' -->
38
- component="product-detail">
39
- </schmancy-route>
21
+ ```typescript
22
+ // Navigate programmatically
23
+ import { area } from '@schmancy/area';
40
24
 
41
- <!-- Route with guard -->
42
- <schmancy-route
43
- when="admin" <!-- Matches 'admin' segment anywhere in URL -->
44
- component="admin-panel"
45
- .guard=${() => isAuthenticated()}>
46
- </schmancy-route>
25
+ area.push({
26
+ component: 'product-detail',
27
+ area: 'main',
28
+ params: { productId: '123' },
29
+ state: { fromCart: true }
30
+ });
47
31
  ```
48
32
 
49
- ## Properties Reference
50
-
51
- ### `<schmancy-area>` Properties
52
-
53
- | Property | Type | Description |
54
- |----------|------|-------------|
55
- | `name` | `string` | **Required**. Unique identifier for this router outlet. |
56
- | `default` | `string \| Promise<NodeModule> \| CustomElementConstructor \| HTMLElement \| LazyComponent` | Default component to display when no route matches or area is empty. |
57
-
58
- ### `<schmancy-route>` Properties
59
-
60
- | Property | Type | Description |
61
- |----------|------|-------------|
62
- | `when` | `string` | **Required**. URL segment to match OR component tag name for programmatic navigation. |
63
- | `component` | `RouteComponent` | Component to render when route matches (string, constructor, element, lazy component). |
64
- | `exact` | `boolean` | Whether route should match exactly (default: false). |
65
- | `guard` | `() => GuardResult \| Promise<GuardResult>` | Navigation guard function. |
33
+ ## Core Components
66
34
 
67
- Note: `<schmancy-route>` does NOT have a `default` property - that's only available on `<schmancy-area>`.
35
+ ### `<schmancy-area>` - Router Outlet
36
+ | Property | Type | Required | Description |
37
+ |----------|------|----------|-------------|
38
+ | `name` | `string` | ✓ | Unique outlet identifier |
39
+ | `default` | `ComponentType` | | Fallback when no route matches |
68
40
 
69
- ## URL Matching Behavior
41
+ ### `<schmancy-route>` - Route Definition
42
+ | Property | Type | Required | Description |
43
+ |----------|------|----------|-------------|
44
+ | `when` | `string` | ✓ | URL segment or component tag to match |
45
+ | `component` | `RouteComponent` | ✓ | Component to render |
46
+ | `guard` | `Observable<boolean>` | | Navigation guard |
47
+ | `exact` | `boolean` | | Currently unused |
70
48
 
71
- The routing system uses multiple strategies to match routes:
49
+ ## URL Matching
72
50
 
73
- ### 1. **URL Segment Matching**
74
- The URL path is split by '/' and the `when` attribute is checked against each segment in the array:
51
+ Routes match in DOM order. First match wins.
75
52
 
76
53
  ```html
77
- <!-- Segment name matching -->
54
+ <!-- Matches URL segments -->
78
55
  <schmancy-route when="products" component="product-list"></schmancy-route>
79
- <!-- URL: /store/products/123 → segments: ['store', 'products', '123'] → MATCHES (products is in array) -->
80
- <!-- URL: /products → segments: ['products'] → MATCHES -->
81
- <!-- URL: /home → segments: ['home'] → DOES NOT MATCH -->
82
- ```
83
-
84
- ### 2. **Component Tag Name Matching**
85
- For programmatic navigation, the `when` attribute can match the component tag name:
56
+ <!-- URL: /store/products → segments: ['store', 'products'] → MATCHES -->
86
57
 
87
- ```html
58
+ <!-- Matches component tag for programmatic nav -->
88
59
  <schmancy-route when="user-profile" component="user-profile"></schmancy-route>
89
- <!-- When navigating with: area.push({ component: 'user-profile', area: 'main' }) → MATCHES -->
90
- ```
91
-
92
- ### 3. **JSON-Encoded State in URL**
93
- When pretty URLs are disabled (default), the router encodes state as JSON in the URL:
94
-
95
- ```javascript
96
- // URL: /%7B%22main%22%3A%7B%22component%22%3A%22user-profile%22%7D%7D
97
- // Decoded: {"main":{"component":"user-profile"}}
98
- // The router extracts this and matches against routes
99
- ```
100
-
101
- ### Matching Priority
102
-
103
- Routes are evaluated in the order they appear in the DOM. The first matching route wins:
104
-
105
- ```html
106
- <schmancy-area name="main">
107
- <!-- Evaluated first -->
108
- <schmancy-route when="user" component="user-detail"></schmancy-route>
109
- <!-- Evaluated second -->
110
- <schmancy-route when="users" component="user-list"></schmancy-route>
111
- <!-- Catch-all (empty when) evaluated last -->
112
- <schmancy-route when="" component="not-found"></schmancy-route>
113
- </schmancy-area>
60
+ <!-- area.push({ component: 'user-profile', area: 'main' }) → MATCHES -->
114
61
  ```
115
62
 
116
63
  ## Navigation Guards
117
64
 
118
- Guards protect routes and can redirect navigation. Guards are executed before component creation for better performance:
65
+ Guards are `Observable<boolean>` that emit true to allow, false to block navigation.
119
66
 
120
67
  ```typescript
121
- // Boolean guard - simple allow/deny
122
- <schmancy-route
123
- when="admin"
124
- component="admin-panel"
125
- .guard=${() => user.isAdmin}>
126
- </schmancy-route>
127
-
128
- // String guard - redirect to path
129
- <schmancy-route
130
- when="profile"
131
- component="user-profile"
132
- .guard=${() => isAuthenticated() || '/login'}>
133
- </schmancy-route>
68
+ // Simple guard
69
+ const authState$ = new BehaviorSubject(false);
134
70
 
135
- // Object guard - redirect with explicit syntax
136
71
  <schmancy-route
137
- when="settings"
138
- component="settings-page"
139
- .guard=${() => {
140
- if (!isAuthenticated()) {
141
- return { redirect: '/login' };
142
- }
143
- if (!hasPermission('settings')) {
144
- return { redirect: '/unauthorized' };
145
- }
146
- return true;
147
- }}>
148
- </schmancy-route>
149
-
150
- // Async guard - check with backend
151
- <schmancy-route
152
- when="premium"
153
- component="premium-content"
154
- .guard=${async () => {
155
- const subscription = await checkSubscription();
156
- return subscription.isActive || { redirect: '/upgrade' };
72
+ when="protected"
73
+ component="protected-page"
74
+ .guard=${authState$.asObservable()}
75
+ @redirect=${(e) => {
76
+ // e.detail contains: blockedRoute, area, params, state
77
+ $notify.error('Access denied');
78
+ area.push({ component: 'login', area: 'main' });
157
79
  }}>
158
80
  </schmancy-route>
159
- ```
160
-
161
- ### Guard Return Types
162
81
 
163
- | Return Value | Behavior |
164
- |--------------|----------|
165
- | `true` | Allow navigation to proceed |
166
- | `false` | Block navigation silently, falls back to default if specified |
167
- | `"/path"` (string) | Redirect to the specified path segment |
168
- | `{redirect: "/path"}` | Explicit redirect object |
169
- | `Promise<...>` | Async guard, resolved before navigation |
170
-
171
- **Note**: Guard failures (`false` return) will fall back to the area's `default` component if specified. Redirects trigger a new route lookup based on the redirect path segment.
172
-
173
- ## Nested Routing
174
-
175
- Create complex nested routing structures:
176
-
177
- ```html
178
- <!-- Parent component with nested routes -->
179
- <schmancy-route
180
- when="app" <!-- Matches 'app' segment in URL -->
181
- component="app-layout"
182
- default="app-dashboard">
183
-
184
- <!-- app-layout.ts -->
185
- <div class="app-container">
186
- <nav>...</nav>
187
- <schmancy-area name="app-content">
188
- <!-- Nested routes also use segment matching -->
189
- <schmancy-route when="dashboard" component="app-dashboard"></schmancy-route>
190
- <schmancy-route when="users" component="user-list"></schmancy-route>
191
- <schmancy-route when="user-detail" component="user-detail"></schmancy-route>
192
- <schmancy-route when="settings" component="settings-layout">
193
- <!-- Even deeper nesting in settings-layout -->
194
- </schmancy-route>
195
- </schmancy-area>
196
- </div>
197
- </schmancy-route>
82
+ // Complex guard with multiple conditions
83
+ const canAccess$ = combineLatest([authState$, roleState$]).pipe(
84
+ map(([auth, role]) => auth && role === 'admin')
85
+ );
198
86
  ```
199
87
 
200
- ### Multi-level Nesting Example
201
-
202
- ```html
203
- <!-- Root level -->
204
- <schmancy-area name="root">
205
- <schmancy-route when="" component="app-shell" default="home-page"> <!-- Empty when = catch-all -->
206
-
207
- <!-- Inside app-shell -->
208
- <schmancy-area name="main">
209
- <schmancy-route when="products" component="product-layout">
210
-
211
- <!-- Inside product-layout -->
212
- <schmancy-area name="product-content">
213
- <schmancy-route when="product-list" component="product-list"></schmancy-route>
214
- <schmancy-route when="product-detail" component="product-detail"></schmancy-route>
215
- <schmancy-route when="reviews" component="product-reviews"></schmancy-route>
216
- </schmancy-area>
217
-
218
- </schmancy-route>
219
- </schmancy-area>
220
-
221
- </schmancy-route>
222
- </schmancy-area>
223
- ```
88
+ **Important**: Guards return `Observable<boolean>` only. No strings, objects, or redirect paths.
89
+ Handle redirects via `@redirect` event.
224
90
 
225
91
  ## Service API
226
92
 
227
93
  ```typescript
228
- // Import the area service
229
- import { area } from '@schmancy/index';
230
- // Or specific import: import { area } from '@schmancy/area';
94
+ import { area } from '@schmancy/area';
231
95
 
232
- // Navigation methods
96
+ // Navigation
233
97
  area.push({
234
- component: 'user-profile', // Component constructor, string tag name, element instance, or lazy component
235
- area: 'main', // Target area name (required)
236
- state?: { view: 'profile' }, // Optional state object (stored in history)
237
- params?: { id: '123' }, // Optional query parameters (NOT URL query params - these are component params)
238
- props?: { userId: '123' }, // Optional component properties (alias for params, applied to component)
239
- historyStrategy?: 'push', // 'push' | 'replace' | 'pop' | 'silent' (default: 'push')
240
- clearQueryParams?: ['sort'] // Clear specific URL query params
98
+ component: string | Constructor | HTMLElement | LazyComponent,
99
+ area: string, // Required
100
+ state?: any, // Stored in history
101
+ params?: any, // Applied to component
102
+ props?: any, // Alias for params
103
+ historyStrategy?: 'push' | 'replace' | 'silent',
104
+ clearQueryParams?: string[] | boolean
241
105
  });
242
106
 
243
- // Remove/clear an area - sends clearing signal to area
244
- area.pop('sidebar'); // Clears the area content and updates history
107
+ // Clear area
108
+ area.pop('sidebar');
245
109
 
246
- // Subscription methods (return RxJS Observables)
247
- area.on(areaName, skipCurrent?) // Subscribe to an area's route changes
248
- area.all(skipCurrent?) // Subscribe to all areas
249
- area.getState<T>(areaName) // Get typed state from an area
250
- area.params<T>(areaName) // Get typed params from an area
251
- area.param<T>(areaName, key) // Get a specific param value
252
- area.props<T>(areaName) // Get typed props from an area
253
- area.prop<T>(areaName, key) // Get a specific prop value
254
-
255
- // Utility methods
256
- area.hasArea(areaName) // Check if an area exists
257
- area.getActiveAreas() // Get array of active area names
258
- area.getRoute(areaName) // Get route synchronously (returns ActiveRoute | undefined)
110
+ // Subscriptions (return Observables)
111
+ area.on(areaName) // Subscribe to route changes
112
+ area.getState<T>(areaName) // Get typed state
113
+ area.params<T>(areaName) // Get typed params
259
114
 
260
115
  // Configuration
261
- area.prettyURL = false // Enable pretty URLs (default: false uses JSON encoding)
262
- area.mode = 'HISTORY' // 'HISTORY' | 'SILENT' (default: 'HISTORY')
263
- area.enableHistoryMode = true // Enable browser history management (default: true)
116
+ area.prettyURL = false // JSON-encoded URLs (default)
117
+ area.enableHistoryMode = true // Browser history (default)
264
118
  ```
265
119
 
266
- ### Important Distinctions:
267
- - **`params`**: Component-level parameters that are passed as properties to the component instance
268
- - **`props`**: Alias for params - both are applied directly to the component element
269
- - **`state`**: Arbitrary data stored in browser history, accessible via subscriptions
270
- - **URL Query Parameters**: Managed separately via `clearQueryParams` option
271
-
272
- ## Common Patterns
273
-
274
- ### Basic Navigation
120
+ ## Lazy Loading
275
121
 
276
122
  ```typescript
277
- // Navigate to a component
278
- area.push({
279
- component: 'home-page',
280
- area: 'main'
281
- });
282
-
283
- // Navigate with parameters and state
284
- area.push({
285
- component: ProductDetailComponent,
286
- area: 'main',
287
- params: { productId: '12345' }, // Query parameters
288
- state: { showReviews: true },
289
- historyStrategy: 'push'
290
- });
291
-
292
- // Navigate with component properties
293
- area.push({
294
- component: 'my-component',
295
- area: 'main',
296
- props: {
297
- title: 'Hello World',
298
- data: { id: 123, name: 'Test' },
299
- onClick: () => console.log('Clicked!')
300
- }
301
- });
302
- ```
303
-
304
- ### Declarative Routing with Guards
305
-
306
- ```html
307
- <schmancy-area name="main">
308
- <!-- Public routes -->
309
- <schmancy-route when="home" component="home-page"></schmancy-route>
310
- <schmancy-route when="about" component="about-page"></schmancy-route>
311
-
312
- <!-- Protected routes -->
313
- <schmancy-route
314
- when="dashboard"
315
- component="dashboard-layout"
316
- .guard=${() => isAuthenticated() || '/login'}>
317
- </schmancy-route>
318
-
319
- <!-- Admin only -->
320
- <schmancy-route
321
- when="admin"
322
- component="admin-panel"
323
- .guard=${() => hasRole('admin') || { redirect: '/unauthorized' }}>
324
- </schmancy-route>
325
-
326
- <!-- Catch-all route (should be last) -->
327
- <!-- Note: Empty 'when' will match any route not matched above -->
328
- <schmancy-route when="" component="not-found-page"></schmancy-route>
329
- </schmancy-area>
330
- ```
331
-
332
- ### Clearing Areas with area.pop()
333
-
334
- ```typescript
335
- // Open a modal or sidebar
336
- area.push({
337
- component: 'user-settings',
338
- area: 'modal',
339
- props: { userId: '123' }
340
- });
341
-
342
- // Clear the modal - sends clearing signal to area component
343
- area.pop('modal'); // Component receives null signal and clears content
344
-
345
- // Clear multiple areas
346
- ['modal', 'sidebar', 'overlay'].forEach(name => area.pop(name));
347
-
348
- // Note: area.pop() now properly sends a clearing signal through the RxJS pipeline
349
- // The area component will receive a route with null component and remove its content
350
- ```
351
-
352
- ### Reactive Subscriptions
353
-
354
- ```typescript
355
- // Subscribe to area changes
356
- area.on('main').subscribe(route => {
357
- console.log(`Component: ${route.component}`);
358
- console.log(`Params:`, route.params); // Query parameters
359
- console.log(`Props:`, route.props); // Component properties
360
- });
123
+ import { lazy } from '@schmancy/area';
361
124
 
362
- // Type-safe state and params
363
- interface UserState { name: string; role: string; }
364
- interface UserParams { id: string; tab?: string; }
125
+ // Define lazy components
126
+ const LazyDashboard = lazy(() => import('./dashboard'));
365
127
 
366
- area.getState<UserState>('user').subscribe(state => {
367
- updateUserInfo(state.name, state.role);
368
- });
128
+ // Use in routes
129
+ <schmancy-route
130
+ when="dashboard"
131
+ .component=${LazyDashboard}>
132
+ </schmancy-route>
369
133
 
370
- area.params<UserParams>('user').subscribe(params => {
371
- fetchUser(params.id);
372
- setActiveTab(params.tab || 'profile');
134
+ // Preload on hover
135
+ button.addEventListener('mouseenter', () => {
136
+ LazyDashboard.preload();
373
137
  });
374
- ```
375
138
 
376
- ### Default Components
377
-
378
- Default components provide fallback UI when no route matches:
379
-
380
- ```html
381
- <!-- Area-level default -->
382
- <schmancy-area name="main" default="welcome-page">
383
- <schmancy-route when="products" component="product-list"></schmancy-route>
384
- <!-- Shows welcome-page when no route matches -->
385
- </schmancy-area>
386
-
387
- <!-- Route-level default for nested routing -->
388
- <schmancy-route
389
- when="app"
390
- component="app-layout"
391
- default="app-dashboard">
392
- <!-- Shows app-dashboard as default content inside app-layout -->
393
- </schmancy-route>
139
+ // Navigate
140
+ area.push({ component: LazyDashboard, area: 'main' });
394
141
  ```
395
142
 
396
- ## Best Practices
397
-
398
- ### 1. Route Organization
143
+ ## Nested Routing
399
144
 
400
145
  ```html
401
- <!-- Order routes from most specific to least specific -->
402
146
  <schmancy-area name="main">
403
- <!-- More specific component names first -->
404
- <schmancy-route when="product-create" component="product-create"></schmancy-route>
405
- <schmancy-route when="product-edit" component="product-edit"></schmancy-route>
406
- <schmancy-route when="product-detail" component="product-detail"></schmancy-route>
407
-
408
- <!-- General segment names -->
409
- <schmancy-route when="products" component="product-list"></schmancy-route>
410
-
411
- <!-- Catch-all (empty when) last -->
412
- <schmancy-route when="" component="not-found"></schmancy-route>
147
+ <schmancy-route when="app" component="app-layout">
148
+ <!-- Inside app-layout component -->
149
+ <schmancy-area name="app-content">
150
+ <schmancy-route when="users" component="user-list"></schmancy-route>
151
+ <schmancy-route when="settings" component="settings"></schmancy-route>
152
+ </schmancy-area>
153
+ </schmancy-route>
413
154
  </schmancy-area>
414
155
  ```
415
156
 
416
- ### 2. Guard Composition
417
-
418
- ```typescript
419
- // Compose multiple guard conditions
420
- const requireAuth = () => isAuthenticated() || '/login';
421
- const requireAdmin = () => hasRole('admin') || '/unauthorized';
422
- const requireSubscription = () => hasActiveSubscription() || '/upgrade';
423
-
424
- // Combine guards
425
- const premiumAdminGuard = () => {
426
- if (!isAuthenticated()) return '/login';
427
- if (!hasRole('admin')) return '/unauthorized';
428
- if (!hasActiveSubscription()) return '/upgrade';
429
- return true;
430
- };
431
-
432
- <schmancy-route
433
- when="premium-admin"
434
- component="premium-admin-panel"
435
- .guard=${premiumAdminGuard}>
436
- </schmancy-route>
437
- ```
438
-
439
- ### 3. Nested Area Management
440
-
441
- ```typescript
442
- // Parent component manages child areas
443
- class AppLayout extends LitElement {
444
- render() {
445
- return html`
446
- <div class="layout">
447
- <nav>
448
- <a @click=${() => this.navigate('/app/dashboard')}>Dashboard</a>
449
- <a @click=${() => this.navigate('/app/users')}>Users</a>
450
- </nav>
451
-
452
- <schmancy-area name="app-content">
453
- <schmancy-route when="dashboard" component="dashboard"></schmancy-route>
454
- <schmancy-route when="users" component="users-module"></schmancy-route>
455
- </schmancy-area>
456
- </div>
457
- `;
458
- }
459
-
460
- navigate(path: string) {
461
- window.history.pushState(null, '', path);
462
- window.dispatchEvent(new PopStateEvent('popstate'));
463
- }
464
- }
465
- ```
466
-
467
- ### 4. Dynamic Route Loading & Lazy Components
468
-
469
- #### Using the `lazy()` helper function
470
-
471
- Schmancy Area provides a powerful `lazy()` function similar to React.lazy() for optimal code splitting. Lazy components are resolved to constructors before element creation for better performance:
472
-
473
- ```typescript
474
- import { lazy } from '@schmancy/area';
475
-
476
- // Create lazy-loaded components with default exports
477
- const LazyDashboard = lazy(() => import('./components/dashboard'));
478
- const LazyAnalytics = lazy(() => import('./components/analytics'));
479
- const LazyReports = lazy(() => import('./components/reports'));
480
-
481
- // Use with area.push()
482
- area.push({
483
- component: LazyDashboard,
484
- area: 'main'
485
- });
486
-
487
- // Use with declarative routes
488
- <schmancy-route
489
- when="analytics"
490
- .component=${LazyAnalytics}
491
- .guard=${() => hasFeature('analytics') || '/upgrade'}>
492
- </schmancy-route>
493
-
494
- // Set as default for an area
495
- <schmancy-area name="main" .default=${LazyDashboard}></schmancy-area>
496
- ```
497
-
498
- #### Preloading Components
499
-
500
- Lazy components support preloading for better perceived performance. The lazy() function caches both the loading promise and the loaded module:
501
-
502
- ```typescript
503
- const LazyProfile = lazy(() => import('./profile'));
504
-
505
- // Preload on hover for instant navigation
506
- button.addEventListener('mouseenter', () => {
507
- LazyProfile.preload(); // Starts loading and caches the promise
508
- });
509
-
510
- // The component will be instantly available when navigated to
511
- area.push({ component: LazyProfile, area: 'main' }); // Uses cached module
512
-
513
- // Preload critical routes after initial page load
514
- window.addEventListener('load', () => {
515
- setTimeout(() => {
516
- LazyProfile.preload(); // Caches for future use
517
- LazySettings.preload();
518
- }, 2000);
519
- });
520
- ```
157
+ ## Common Patterns
521
158
 
522
- #### Complete Example: Lazy-Loaded Navigation
159
+ ### Protected Routes with Authentication
523
160
 
524
161
  ```typescript
525
- import { $LitElement } from '@mixins/index';
526
- import { area, lazy } from '@schmancy/area';
527
- import { html } from 'lit';
528
- import { customElement, state } from 'lit/decorators.js';
529
-
530
- // Define lazy components with default exports
531
- const routes = {
532
- dashboard: lazy(() => import('./lazy-components/dashboard')),
533
- users: lazy(() => import('./lazy-components/users')),
534
- products: lazy(() => import('./lazy-components/products')),
535
- reports: lazy(() => import('./lazy-components/reports')),
536
- settings: lazy(() => import('./lazy-components/settings'))
537
- };
538
-
539
162
  @customElement('app-shell')
540
163
  export class AppShell extends $LitElement() {
541
- @state() private currentRoute = 'dashboard';
542
-
543
- private navigate(route: string, component: any) {
544
- this.currentRoute = route;
545
- area.push({
546
- area: 'main',
547
- component: component
548
- });
549
- }
550
-
551
- render() {
552
- return html`
553
- <div class="grid grid-cols-[auto_1fr]">
554
- <!-- Sidebar Navigation -->
555
- <schmancy-list>
556
- <schmancy-list-item
557
- ?selected=${this.currentRoute === 'dashboard'}
558
- @click=${() => this.navigate('dashboard', routes.dashboard)}
559
- @mouseenter=${() => routes.dashboard.preload()}>
560
- <schmancy-icon slot="start">dashboard</schmancy-icon>
561
- Dashboard
562
- </schmancy-list-item>
563
-
564
- <schmancy-list-item
565
- ?selected=${this.currentRoute === 'users'}
566
- @click=${() => this.navigate('users', routes.users)}
567
- @mouseenter=${() => routes.users.preload()}>
568
- <schmancy-icon slot="start">group</schmancy-icon>
569
- Users
570
- </schmancy-list-item>
571
-
572
- <schmancy-list-item
573
- ?selected=${this.currentRoute === 'products'}
574
- @click=${() => this.navigate('products', routes.products)}
575
- @mouseenter=${() => routes.products.preload()}>
576
- <schmancy-icon slot="start">inventory_2</schmancy-icon>
577
- Products
578
- </schmancy-list-item>
579
- </schmancy-list>
580
-
581
- <!-- Main Content Area -->
582
- <schmancy-area
583
- name="main"
584
- .default=${routes.dashboard}>
585
- </schmancy-area>
586
- </div>
587
- `;
588
- }
589
- }
590
- ```
591
-
592
- #### Lazy Component Structure
593
-
594
- Each lazy-loaded component should use default export:
164
+ private authState$ = new BehaviorSubject(false);
595
165
 
596
- ```typescript
597
- // lazy-components/dashboard.ts
598
- import { html, css } from 'lit';
599
- import { customElement } from 'lit/decorators.js';
600
- import { $LitElement } from '@mixins/index';
601
-
602
- @customElement('lazy-dashboard')
603
- export default class LazyDashboard extends $LitElement(css`
604
- :host {
605
- display: block;
606
- padding: 24px;
607
- }
608
- `) {
609
166
  render() {
610
167
  return html`
611
- <schmancy-surface type="container" rounded="all">
612
- <schmancy-typography type="headline">Dashboard</schmancy-typography>
613
- <!-- Dashboard content -->
614
- </schmancy-surface>
168
+ <schmancy-area name="main">
169
+ <schmancy-route when="home" component="home-page"></schmancy-route>
170
+
171
+ <schmancy-route
172
+ when="dashboard"
173
+ component="dashboard"
174
+ .guard=${this.authState$.asObservable()}
175
+ @redirect=${() => {
176
+ area.push({ component: 'login', area: 'main' });
177
+ }}>
178
+ </schmancy-route>
179
+ </schmancy-area>
615
180
  `;
616
181
  }
617
182
  }
618
183
  ```
619
184
 
620
- #### Benefits of Lazy Loading
621
-
622
- 1. **Reduced Initial Bundle Size**: Components are loaded only when needed
623
- 2. **Faster Initial Page Load**: Critical path includes only essential code
624
- 3. **Automatic Code Splitting**: Each lazy import creates a separate chunk
625
- 4. **Memory Efficiency**: Components not in use aren't loaded in memory
626
- 5. **Better Perceived Performance**: Preloading on hover makes navigation feel instant
627
-
628
- #### Performance Best Practices
629
-
630
- ```typescript
631
- // 1. Group related components in the same chunk
632
- const LazyAdminComponents = lazy(() => import('./admin/index'));
633
-
634
- // 2. Preload critical routes after initial render
635
- connectedCallback() {
636
- super.connectedCallback();
637
-
638
- // Preload common routes after a delay
639
- setTimeout(() => {
640
- routes.dashboard.preload();
641
- routes.users.preload();
642
- }, 3000);
643
- }
644
-
645
- // 3. Use intersection observer for preloading visible links
646
- const observer = new IntersectionObserver((entries) => {
647
- entries.forEach(entry => {
648
- if (entry.isIntersecting) {
649
- const route = entry.target.dataset.route;
650
- routes[route]?.preload();
651
- }
652
- });
653
- });
654
-
655
- // 4. Handle loading errors gracefully
656
- const LazyFeature = lazy(() =>
657
- import('./feature').catch(() =>
658
- // Fallback to simpler version on error
659
- import('./feature-lite')
660
- )
661
- );
662
- ```
663
-
664
- #### Legacy Method (Still Supported)
665
-
666
- The traditional dynamic import method is still supported:
667
-
668
- ```typescript
669
- // Direct dynamic import (without lazy helper)
670
- <schmancy-route
671
- when="analytics"
672
- .component=${() => import('./analytics-dashboard.js').then(m => m.AnalyticsDashboard)}
673
- .guard=${() => hasFeature('analytics') || '/upgrade'}>
674
- </schmancy-route>
675
- ```
676
-
677
- ### 5. Error Boundaries
678
-
679
- ```typescript
680
- // Wrap routes in error boundaries
681
- class ErrorBoundary extends LitElement {
682
- @state() hasError = false;
683
-
684
- constructor() {
685
- super();
686
- window.addEventListener('error', () => {
687
- this.hasError = true;
688
- });
689
- }
690
-
691
- render() {
692
- if (this.hasError) {
693
- return html`<error-page></error-page>`;
694
- }
695
- return html`<slot></slot>`;
696
- }
697
- }
698
-
699
- // Use in template
700
- html`
701
- <error-boundary>
702
- <schmancy-area name="main">
703
- <!-- routes -->
704
- </schmancy-area>
705
- </error-boundary>
706
- `;
707
- ```
708
-
709
- ## History Management
710
-
711
- The router manages browser history automatically, storing state in `history.state.schmancyAreas`:
712
-
713
- ### Browser State Structure
714
- ```javascript
715
- // Browser history.state structure:
716
- {
717
- schmancyAreas: {
718
- main: {
719
- component: 'user-profile',
720
- state: { view: 'edit' },
721
- params: { userId: '123' },
722
- area: 'main'
723
- },
724
- sidebar: {
725
- component: 'nav-menu',
726
- area: 'sidebar'
727
- }
728
- }
729
- }
730
- ```
731
-
732
- ### URL Encoding Modes
185
+ ### Multi-Area Application
733
186
 
734
- #### 1. **JSON Encoding (Default)**
735
- When `area.prettyURL = false` (default), state is encoded as JSON in the URL:
736
- ```javascript
737
- // URL: /%7B%22main%22%3A%7B%22component%22%3A%22user-profile%22%7D%7D
738
- // Decoded: {"main":{"component":"user-profile"}}
739
- ```
740
-
741
- #### 2. **Pretty URLs**
742
- When `area.prettyURL = true`, creates cleaner URLs:
743
- ```javascript
744
- area.prettyURL = true;
745
- // URL: /user-profile?userId=123
746
- // Component and simple params are included in the URL
747
- ```
748
-
749
- ### History Strategies
750
-
751
- ```typescript
752
- area.push({
753
- component: 'page',
754
- area: 'main',
755
- historyStrategy: 'push' // Options: 'push' | 'replace' | 'pop' | 'silent'
756
- });
757
-
758
- // 'push': Adds new entry to history (default)
759
- // 'replace': Replaces current history entry
760
- // 'pop': Updates during back/forward navigation
761
- // 'silent': No history update
762
- ```
763
-
764
- ## Internal Behaviors
765
-
766
- ### Component Lifecycle
767
-
768
- 1. **Route Resolution Pipeline**:
769
- - Route request received (programmatic, URL, or browser navigation)
770
- - Lazy components resolved to constructors (if applicable)
771
- - Component identifier extracted for deduplication
772
- - Route deduplicated using `distinctUntilChanged`
773
- - HTMLElement created and properties applied
774
- - Component swapped with animation
775
-
776
- 2. **Component Swapping Animation**:
777
- - Old component fades out (150ms)
778
- - Old component removed from DOM
779
- - New component added to shadow DOM
780
- - New component fades in (150ms)
781
-
782
- 3. **Deduplication Strategy**:
783
- Components are deduplicated based on:
784
- - Component identifier (tag name or constructor name)
785
- - JSON stringified params
786
- - JSON stringified state
787
-
788
- This prevents unnecessary re-renders when navigating to the same route.
789
-
790
- ### RxJS Pipeline Architecture
791
-
792
- The area component uses a sophisticated RxJS pipeline:
793
-
794
- ```typescript
795
- // Three navigation sources merged into one stream:
796
- merge(
797
- area.request, // Programmatic navigation
798
- of(location.pathname), // Initial load
799
- fromEvent('popstate') // Browser back/forward
800
- )
801
- .pipe(
802
- // Resolve lazy components
803
- switchMap(/* ... */),
804
-
805
- // Deduplicate identical routes
806
- distinctUntilChanged(/* ... */),
807
-
808
- // Share single subscription
809
- shareReplay(1),
810
-
811
- // Handle errors gracefully
812
- catchError(/* ... */),
813
-
814
- // Cleanup on disconnect
815
- takeUntil(this.disconnecting)
816
- )
817
- ```
818
-
819
- ### Error Handling
820
-
821
- - **Lazy Load Failures**: Logged to console, component set to null
822
- - **Component Creation Failures**: Logged to console, gracefully skipped
823
- - **Guard Errors**: Caught and fall back to default component
824
- - **Navigation Errors**: Logged and return EMPTY observable
825
-
826
- ## Migration Guide
827
-
828
- ### From Direct area.push() to Declarative Routes
829
-
830
- **Before:**
831
- ```typescript
832
- // Old imperative approach
833
- if (path === '/products') {
834
- area.push({ component: 'product-list', area: 'main' });
835
- } else if (path.startsWith('/products/')) {
836
- const id = path.split('/')[2];
837
- area.push({
838
- component: 'product-detail',
839
- area: 'main',
840
- params: { id }
841
- });
842
- }
843
- ```
844
-
845
- **After:**
846
187
  ```html
847
- <!-- New declarative approach -->
848
- <schmancy-area name="main">
849
- <schmancy-route when="products" component="product-list"></schmancy-route>
850
- <schmancy-route when="product-detail" component="product-detail"></schmancy-route>
851
- </schmancy-area>
188
+ <!-- Multiple independent outlets -->
189
+ <div class="layout">
190
+ <schmancy-area name="sidebar" default="nav-menu"></schmancy-area>
191
+ <schmancy-area name="main" default="home"></schmancy-area>
192
+ <schmancy-area name="modal"></schmancy-area>
193
+ </div>
852
194
  ```
853
195
 
854
- ### Updating Guard Logic
855
-
856
- **Before:**
857
196
  ```typescript
858
- // Manual guard checks
859
- area.on('protected-area').pipe(
860
- switchMap(route => {
861
- if (!isAuthenticated()) {
862
- area.push({ component: 'login-page', area: 'main' });
863
- return EMPTY;
864
- }
865
- return of(route);
866
- })
867
- ).subscribe();
868
- ```
869
-
870
- **After:**
871
- ```html
872
- <!-- Built-in guard support -->
873
- <schmancy-route
874
- when="protected"
875
- component="protected-content"
876
- .guard=${() => isAuthenticated() || '/login'}>
877
- </schmancy-route>
878
- ```
879
-
880
- ## Advanced Examples
197
+ // Navigate different areas independently
198
+ area.push({ component: 'user-list', area: 'main' });
199
+ area.push({ component: 'quick-stats', area: 'sidebar' });
200
+ area.push({ component: 'edit-dialog', area: 'modal' });
881
201
 
882
- ### Multi-tenant Application
883
-
884
- ```html
885
- <schmancy-area name="root">
886
- <!-- Tenant detection route -->
887
- <schmancy-route
888
- when="tenant-app" <!-- Matches based on component tag name -->
889
- component="tenant-app"
890
- .guard=${async (params) => {
891
- const tenant = params.tenant;
892
- const isValid = await validateTenant(tenant);
893
- return isValid || { redirect: '/invalid-tenant' };
894
- }}>
895
-
896
- <!-- Inside tenant-app -->
897
- <schmancy-area name="tenant-content">
898
- <schmancy-route when="dashboard" component="tenant-dashboard"></schmancy-route>
899
- <schmancy-route when="users" component="tenant-users"></schmancy-route>
900
- <schmancy-route when="settings" component="tenant-settings"></schmancy-route>
901
- </schmancy-area>
902
-
903
- </schmancy-route>
904
- </schmancy-area>
905
- ```
906
-
907
- ### Wizard/Step Navigation
908
-
909
- ```html
910
- <schmancy-route when="onboarding" component="onboarding-wizard">
911
- <!-- Inside onboarding-wizard -->
912
- <schmancy-area name="wizard-step">
913
- <schmancy-route
914
- when="profile"
915
- component="step-profile"
916
- .guard=${() => hasCompletedStep(0) || '/onboarding/welcome'}>
917
- </schmancy-route>
918
-
919
- <schmancy-route
920
- when="preferences"
921
- component="step-preferences"
922
- .guard=${() => hasCompletedStep(1) || '/onboarding/profile'}>
923
- </schmancy-route>
924
-
925
- <schmancy-route
926
- when="complete"
927
- component="step-complete"
928
- .guard=${() => hasCompletedStep(2) || '/onboarding/preferences'}>
929
- </schmancy-route>
930
- </schmancy-area>
931
- </schmancy-route>
202
+ // Clear modal
203
+ area.pop('modal');
932
204
  ```
933
205
 
934
- ## Troubleshooting
935
-
936
- ### Common Issues and Solutions
937
-
938
- 1. **Routes not matching**
939
- - Check route order (specific before general)
940
- - Verify URL segments match exactly
941
- - Ensure wildcards are used correctly
942
-
943
- 2. **Guards not redirecting**
944
- - Return string path or `{redirect: path}` object
945
- - Check async guards are returning promises
946
- - Verify guard function is bound correctly with `.guard=${}`
947
-
948
- 3. **Nested routes not working**
949
- - Parent route must use wildcard `/*` to allow nested paths
950
- - Child area must have unique name
951
- - Check component hierarchy is rendering child areas
952
-
953
- 4. **area.pop() not clearing content**
954
- - Update to latest version (fixed in recent update)
955
- - Ensure area name is correct
956
- - Check no other navigation is immediately refilling area
957
-
958
- 5. **Default components not showing**
959
- - Verify default is set on correct element (area or route)
960
- - Check no matching routes are preventing default
961
- - Ensure component name/reference is valid
962
-
963
206
  ## Type Definitions
964
207
 
965
208
  ```typescript
966
- // Route Action - used for navigation
209
+ // Navigation request
967
210
  interface RouteAction {
968
- component: CustomElementConstructor | string | HTMLElement | (() => Promise<{ default: CustomElementConstructor }>);
969
- area: string; // Required
970
- state?: Record<string, unknown>; // State stored in history
971
- params?: Record<string, unknown>; // Component properties
972
- props?: Record<string, unknown>; // Alias for params
973
- historyStrategy?: 'push' | 'replace' | 'pop' | 'silent';
974
- clearQueryParams?: string[] | boolean | null; // Clear URL query params
975
- _source?: 'programmatic' | 'browser' | 'initial'; // Internal use only
976
- }
977
-
978
- // Active Route - current state of an area
979
- interface ActiveRoute {
980
- component: string; // Always resolved to tag name
211
+ component: ComponentType;
981
212
  area: string;
982
- state?: Record<string, unknown>;
983
- params?: Record<string, unknown>; // Component properties
984
- props?: Record<string, unknown>; // Component properties
213
+ state?: Record<string, any>;
214
+ params?: Record<string, any>;
215
+ props?: Record<string, any>; // Alias for params
216
+ historyStrategy?: 'push' | 'replace' | 'silent';
217
+ clearQueryParams?: string[] | boolean;
985
218
  }
986
219
 
987
- // Guard function signatures
988
- export type GuardResult = boolean | string | { redirect: string };
989
- type GuardFunction = () => GuardResult | Promise<GuardResult>;
220
+ // Guard type
221
+ type ObservableGuardResult = Observable<boolean>;
990
222
 
991
- // Route Component Types
992
- export type RouteComponent =
993
- | string // Tag name
994
- | CustomElementConstructor // Constructor function
995
- | HTMLElement // Existing element
996
- | TemplateResult<1> // Lit template
997
- | (() => Promise<{ default: CustomElementConstructor }>) // Lazy loader
998
- | Promise<{ default: CustomElementConstructor }>; // Dynamic import
223
+ // Component types
224
+ type RouteComponent =
225
+ | string // Tag name
226
+ | CustomElementConstructor // Class
227
+ | HTMLElement // Instance
228
+ | (() => Promise<{ default: Constructor }>) // Lazy
999
229
 
1000
- // Route configuration (from route.component.ts)
1001
- interface RouteConfig {
1002
- when: string; // URL segment to match
1003
- component: RouteComponent;
1004
- exact?: boolean; // Not actively used in current implementation
1005
- guard?: () => GuardResult | Promise<GuardResult>;
230
+ // Redirect event detail
231
+ interface RedirectEventDetail {
232
+ blockedRoute: string;
233
+ area: string;
234
+ params: Record<string, any>;
235
+ state: Record<string, any>;
1006
236
  }
237
+ ```
1007
238
 
1008
- // LazyComponent interface with preload capability
1009
- interface LazyComponent<T extends CustomElementConstructor = CustomElementConstructor> {
1010
- (): Promise<{ default: T }>;
1011
- preload(): Promise<void>;
1012
- _promise?: Promise<{ default: T }>; // Cached loading promise
1013
- _module?: { default: T }; // Cached loaded module
1014
- }
239
+ ## Internal Behavior
1015
240
 
1016
- // Browser History State Structure
1017
- interface SchmancyHistoryState {
1018
- schmancyAreas: Record<string, ActiveRoute>;
1019
- [key: string]: any; // Allow other apps to store additional state
1020
- }
241
+ ### Route Resolution Pipeline
242
+ 1. Receives navigation request (programmatic, URL, or browser)
243
+ 2. Resolves lazy components to constructors
244
+ 3. Deduplicates identical routes
245
+ 4. Evaluates guard Observable
246
+ 5. Creates element and applies properties
247
+ 6. Swaps components with 150ms fade animation
1021
248
 
1022
- // History Strategy Enum
1023
- enum HISTORY_STRATEGY {
1024
- push = 'push',
1025
- replace = 'replace',
1026
- pop = 'pop',
1027
- silent = 'silent'
1028
- }
1029
- ```
249
+ ### Route Evaluation Order
250
+ - Routes evaluated in DOM order
251
+ - First matching route wins
252
+ - Empty `when=""` acts as catch-all
1030
253
 
1031
- ## Related Components
254
+ ### History Management
255
+ - JSON-encoded URLs by default: `/%7B%22main%22%3A%7B%22component%22%3A%22home%22%7D%7D`
256
+ - Pretty URLs optional: `/products?id=123`
257
+ - State stored in `history.state.schmancyAreas`
1032
258
 
1033
- - **[Store](./store.md)** - For complex state management
1034
- - **[Layout](./layout.md)** - For responsive layouts
1035
- - **[Teleport](./teleport.md)** - For advanced component transportation
1036
- - **[Sheet](./sheet.md)** - For modal overlays
259
+ ## Troubleshooting
1037
260
 
1038
- ## Performance Tips
261
+ **Routes not matching**
262
+ - Check route order (specific before general)
263
+ - Verify `when` matches URL segment or component tag
1039
264
 
1040
- 1. **Use the `lazy()` function** for automatic code splitting and optimal loading
1041
- 2. **Implement preloading on hover** for instant perceived navigation
1042
- 3. **Handle loading errors** with catch blocks in import statements
1043
- 4. **Group related components** in the same lazy chunk when appropriate
1044
- 5. **Cache guard results** when checking expensive operations
1045
- 6. **Use `historyStrategy: 'silent'`** for non-navigational updates
1046
- 7. **Debounce rapid navigation** in user-triggered events
1047
- 8. **Preload critical routes** after initial render using `component.preload()`
1048
- 9. **Leverage default exports** in lazy-loaded components for cleaner imports
1049
- 10. **Monitor bundle sizes** to ensure effective code splitting
265
+ **Guards not working**
266
+ - Must be `Observable<boolean>`, not functions
267
+ - Use `.asObservable()` on BehaviorSubjects
268
+ - Handle redirects in `@redirect` event
1050
269
 
1051
- ## Summary
270
+ **Nested routes failing**
271
+ - Each area needs unique name
272
+ - Parent must render child `<schmancy-area>`
1052
273
 
1053
- Schmancy Area provides a complete routing solution with:
1054
- - **Declarative routing** with `<schmancy-route>` using slot detection
1055
- - **URL segment matching** - splits paths and checks for segment presence
1056
- - ✅ **Navigation guards** with boolean, string, and object return types
1057
- - **Nested routing** support for complex applications
1058
- - ✅ **Default components** for fallback UI (area-level only)
1059
- - ✅ **Reactive subscriptions** with RxJS observables
1060
- - ✅ **Type-safe** API with TypeScript support
1061
- - ✅ **Multiple router outlets** for complex layouts
1062
- - ✅ **Proper area.pop()** sends clearing signals through RxJS pipeline
1063
- - ✅ **Lazy loading** with caching and preload support
1064
- - ✅ **History management** with JSON encoding or pretty URLs
1065
- - ✅ **Animation transitions** during component swapping (150ms fade)
1066
- - ✅ **Deduplication** prevents unnecessary re-renders
1067
- - ✅ **Error handling** with graceful fallbacks
274
+ **area.pop() not clearing**
275
+ - Verify area name is correct
276
+ - Check no immediate re-navigation
277
+
278
+ ## Related Components
1068
279
 
1069
- The combination of declarative routes and programmatic navigation provides maximum flexibility for building modern web applications.
280
+ - **[Store](./store.md)** - State management
281
+ - **[Sheet](./sheet.md)** - Modal overlays
282
+ - **[Layout](./layout.md)** - Responsive layouts