@dooboostore/simple-web-component 1.0.18 → 1.0.21

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 (618) hide show
  1. package/README.md +2065 -164
  2. package/dist/cjs/config/config.js +2 -0
  3. package/dist/cjs/config/config.js.map +2 -2
  4. package/dist/cjs/decorators/addEventListener.js +8 -8
  5. package/dist/cjs/decorators/addEventListener.js.map +2 -2
  6. package/dist/cjs/decorators/appendChild.js +53 -9
  7. package/dist/cjs/decorators/appendChild.js.map +2 -2
  8. package/dist/cjs/decorators/attribute.js +141 -0
  9. package/dist/cjs/decorators/attribute.js.map +7 -0
  10. package/dist/cjs/decorators/changedAttribute.js +5 -5
  11. package/dist/cjs/decorators/changedAttribute.js.map +2 -2
  12. package/dist/cjs/decorators/classList.js +104 -0
  13. package/dist/cjs/decorators/classList.js.map +7 -0
  14. package/dist/cjs/decorators/elementDefine.js +334 -425
  15. package/dist/cjs/decorators/elementDefine.js.map +3 -3
  16. package/dist/cjs/decorators/emitCustomEvent.js +65 -13
  17. package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
  18. package/dist/cjs/decorators/index.js +4 -0
  19. package/dist/cjs/decorators/index.js.map +2 -2
  20. package/dist/cjs/decorators/lifecycles.js +4 -4
  21. package/dist/cjs/decorators/lifecycles.js.map +2 -2
  22. package/dist/cjs/decorators/onConnectedInnerHtml.js +4 -4
  23. package/dist/cjs/decorators/onConnectedInnerHtml.js.map +2 -2
  24. package/dist/cjs/decorators/query.js +60 -36
  25. package/dist/cjs/decorators/query.js.map +2 -2
  26. package/dist/cjs/decorators/queryAll.js +47 -23
  27. package/dist/cjs/decorators/queryAll.js.map +2 -2
  28. package/dist/cjs/decorators/replaceChildren.js +32 -6
  29. package/dist/cjs/decorators/replaceChildren.js.map +2 -2
  30. package/dist/cjs/decorators/setAttribute.js +64 -10
  31. package/dist/cjs/decorators/setAttribute.js.map +2 -2
  32. package/dist/cjs/decorators/style.js +88 -0
  33. package/dist/cjs/decorators/style.js.map +7 -0
  34. package/dist/cjs/elements/SwcAppEngine.js +30 -15
  35. package/dist/cjs/elements/SwcAppEngine.js.map +3 -3
  36. package/dist/cjs/elements/SwcAppMixin.js +79 -0
  37. package/dist/cjs/elements/SwcAppMixin.js.map +7 -0
  38. package/dist/cjs/elements/SwcAsync.js +58 -123
  39. package/dist/cjs/elements/SwcAsync.js.map +3 -3
  40. package/dist/cjs/elements/SwcChoose.js +52 -76
  41. package/dist/cjs/elements/SwcChoose.js.map +3 -3
  42. package/dist/cjs/elements/SwcIf.js +66 -94
  43. package/dist/cjs/elements/SwcIf.js.map +3 -3
  44. package/dist/cjs/elements/SwcLoop.js +73 -174
  45. package/dist/cjs/elements/SwcLoop.js.map +3 -3
  46. package/dist/cjs/elements/SwcSubTemplates.js +12 -37
  47. package/dist/cjs/elements/SwcSubTemplates.js.map +3 -3
  48. package/dist/cjs/elements/index.js +1 -8
  49. package/dist/cjs/elements/index.js.map +2 -2
  50. package/dist/cjs/elements/register.js +831 -0
  51. package/dist/cjs/elements/register.js.map +7 -0
  52. package/dist/cjs/index.js +14 -3
  53. package/dist/cjs/index.js.map +2 -2
  54. package/dist/cjs/router/ElementRouter.js +7 -7
  55. package/dist/cjs/router/ElementRouter.js.map +2 -2
  56. package/dist/cjs/types.js.map +1 -1
  57. package/dist/cjs/utils/TemplateUtils.js +103 -0
  58. package/dist/cjs/utils/TemplateUtils.js.map +7 -0
  59. package/dist/cjs/utils/Utils.js +10 -7
  60. package/dist/cjs/utils/Utils.js.map +2 -2
  61. package/dist/esm/config/config.js +2 -0
  62. package/dist/esm/config/config.js.map +2 -2
  63. package/dist/esm/decorators/addEventListener.js +5 -5
  64. package/dist/esm/decorators/addEventListener.js.map +2 -2
  65. package/dist/esm/decorators/appendChild.js +52 -8
  66. package/dist/esm/decorators/appendChild.js.map +2 -2
  67. package/dist/esm/decorators/attribute.js +122 -0
  68. package/dist/esm/decorators/attribute.js.map +7 -0
  69. package/dist/esm/decorators/changedAttribute.js +1 -1
  70. package/dist/esm/decorators/changedAttribute.js.map +1 -1
  71. package/dist/esm/decorators/classList.js +85 -0
  72. package/dist/esm/decorators/classList.js.map +7 -0
  73. package/dist/esm/decorators/elementDefine.js +334 -425
  74. package/dist/esm/decorators/elementDefine.js.map +3 -3
  75. package/dist/esm/decorators/emitCustomEvent.js +62 -10
  76. package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
  77. package/dist/esm/decorators/index.js +4 -0
  78. package/dist/esm/decorators/index.js.map +2 -2
  79. package/dist/esm/decorators/lifecycles.js +1 -1
  80. package/dist/esm/decorators/lifecycles.js.map +1 -1
  81. package/dist/esm/decorators/onConnectedInnerHtml.js +1 -1
  82. package/dist/esm/decorators/onConnectedInnerHtml.js.map +1 -1
  83. package/dist/esm/decorators/query.js +58 -34
  84. package/dist/esm/decorators/query.js.map +2 -2
  85. package/dist/esm/decorators/queryAll.js +45 -21
  86. package/dist/esm/decorators/queryAll.js.map +2 -2
  87. package/dist/esm/decorators/replaceChildren.js +28 -2
  88. package/dist/esm/decorators/replaceChildren.js.map +2 -2
  89. package/dist/esm/decorators/setAttribute.js +62 -8
  90. package/dist/esm/decorators/setAttribute.js.map +2 -2
  91. package/dist/esm/decorators/style.js +69 -0
  92. package/dist/esm/decorators/style.js.map +7 -0
  93. package/dist/esm/elements/SwcAppEngine.js +27 -12
  94. package/dist/esm/elements/SwcAppEngine.js.map +2 -2
  95. package/dist/esm/elements/SwcAppMixin.js +60 -0
  96. package/dist/esm/elements/SwcAppMixin.js.map +7 -0
  97. package/dist/esm/elements/SwcAsync.js +58 -123
  98. package/dist/esm/elements/SwcAsync.js.map +3 -3
  99. package/dist/esm/elements/SwcChoose.js +52 -76
  100. package/dist/esm/elements/SwcChoose.js.map +3 -3
  101. package/dist/esm/elements/SwcIf.js +66 -94
  102. package/dist/esm/elements/SwcIf.js.map +3 -3
  103. package/dist/esm/elements/SwcLoop.js +72 -173
  104. package/dist/esm/elements/SwcLoop.js.map +3 -3
  105. package/dist/esm/elements/SwcSubTemplates.js +12 -37
  106. package/dist/esm/elements/SwcSubTemplates.js.map +3 -3
  107. package/dist/esm/elements/index.js +1 -8
  108. package/dist/esm/elements/index.js.map +2 -2
  109. package/dist/esm/elements/register.js +812 -0
  110. package/dist/esm/elements/register.js.map +7 -0
  111. package/dist/esm/index.js +14 -3
  112. package/dist/esm/index.js.map +2 -2
  113. package/dist/esm/router/ElementRouter.js +2 -2
  114. package/dist/esm/router/ElementRouter.js.map +1 -1
  115. package/dist/esm/types.js.map +1 -1
  116. package/dist/esm/utils/TemplateUtils.js +84 -0
  117. package/dist/esm/utils/TemplateUtils.js.map +7 -0
  118. package/dist/esm/utils/Utils.js +6 -3
  119. package/dist/esm/utils/Utils.js.map +2 -2
  120. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +4910 -7463
  121. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
  122. package/dist/types/config/config.d.ts +1 -0
  123. package/dist/types/config/config.d.ts.map +1 -1
  124. package/dist/types/decorators/addEventListener.d.ts +11 -11
  125. package/dist/types/decorators/addEventListener.d.ts.map +1 -1
  126. package/dist/types/decorators/appendChild.d.ts +1 -1
  127. package/dist/types/decorators/appendChild.d.ts.map +1 -1
  128. package/dist/types/decorators/attribute.d.ts +23 -0
  129. package/dist/types/decorators/attribute.d.ts.map +1 -0
  130. package/dist/types/decorators/classList.d.ts +34 -0
  131. package/dist/types/decorators/classList.d.ts.map +1 -0
  132. package/dist/types/decorators/elementDefine.d.ts +9 -5
  133. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  134. package/dist/types/decorators/emitCustomEvent.d.ts +7 -4
  135. package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
  136. package/dist/types/decorators/index.d.ts +4 -0
  137. package/dist/types/decorators/index.d.ts.map +1 -1
  138. package/dist/types/decorators/query.d.ts +7 -8
  139. package/dist/types/decorators/query.d.ts.map +1 -1
  140. package/dist/types/decorators/queryAll.d.ts +5 -9
  141. package/dist/types/decorators/queryAll.d.ts.map +1 -1
  142. package/dist/types/decorators/replaceChildren.d.ts.map +1 -1
  143. package/dist/types/decorators/setAttribute.d.ts +16 -3
  144. package/dist/types/decorators/setAttribute.d.ts.map +1 -1
  145. package/dist/types/decorators/style.d.ts +24 -0
  146. package/dist/types/decorators/style.d.ts.map +1 -0
  147. package/dist/types/elements/SwcAppEngine.d.ts +6 -5
  148. package/dist/types/elements/SwcAppEngine.d.ts.map +1 -1
  149. package/dist/types/elements/SwcAppMixin.d.ts +364 -0
  150. package/dist/types/elements/SwcAppMixin.d.ts.map +1 -0
  151. package/dist/types/elements/SwcAsync.d.ts +2 -6
  152. package/dist/types/elements/SwcAsync.d.ts.map +1 -1
  153. package/dist/types/elements/SwcChoose.d.ts +2 -1
  154. package/dist/types/elements/SwcChoose.d.ts.map +1 -1
  155. package/dist/types/elements/SwcIf.d.ts +5 -6
  156. package/dist/types/elements/SwcIf.d.ts.map +1 -1
  157. package/dist/types/elements/SwcLoop.d.ts +4 -10
  158. package/dist/types/elements/SwcLoop.d.ts.map +1 -1
  159. package/dist/types/elements/SwcSubTemplates.d.ts.map +1 -1
  160. package/dist/types/elements/index.d.ts +1 -8
  161. package/dist/types/elements/index.d.ts.map +1 -1
  162. package/dist/types/elements/register.d.ts +2 -0
  163. package/dist/types/elements/register.d.ts.map +1 -0
  164. package/dist/types/index.d.ts +8 -3
  165. package/dist/types/index.d.ts.map +1 -1
  166. package/dist/types/router/ElementRouter.d.ts +1 -1
  167. package/dist/types/router/ElementRouter.d.ts.map +1 -1
  168. package/dist/types/types.d.ts +8 -2
  169. package/dist/types/types.d.ts.map +1 -1
  170. package/dist/types/utils/TemplateUtils.d.ts +54 -0
  171. package/dist/types/utils/TemplateUtils.d.ts.map +1 -0
  172. package/dist/types/utils/Utils.d.ts.map +1 -1
  173. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +4910 -7463
  174. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
  175. package/package.json +11 -6
  176. package/src/config/config.ts +2 -0
  177. package/src/decorators/addEventListener.ts +13 -12
  178. package/src/decorators/appendChild.ts +53 -9
  179. package/src/decorators/attribute.ts +158 -0
  180. package/src/decorators/changedAttribute.ts +1 -1
  181. package/src/decorators/classList.ts +117 -0
  182. package/src/decorators/elementDefine.ts +371 -425
  183. package/src/decorators/emitCustomEvent.ts +77 -13
  184. package/src/decorators/index.ts +4 -0
  185. package/src/decorators/lifecycles.ts +1 -1
  186. package/src/decorators/onConnectedInnerHtml.ts +1 -1
  187. package/src/decorators/query.ts +58 -38
  188. package/src/decorators/queryAll.ts +45 -29
  189. package/src/decorators/replaceChildren.ts +31 -2
  190. package/src/decorators/setAttribute.ts +86 -12
  191. package/src/decorators/style.ts +89 -0
  192. package/src/elements/SwcAppEngine.ts +34 -18
  193. package/src/elements/SwcAppMixin.ts +65 -0
  194. package/src/elements/SwcAsync.ts +58 -128
  195. package/src/elements/SwcChoose.ts +51 -77
  196. package/src/elements/SwcIf.ts +64 -86
  197. package/src/elements/SwcLoop.ts +71 -168
  198. package/src/elements/SwcSubTemplates.ts +0 -13
  199. package/src/elements/index.ts +1 -8
  200. package/src/elements/register.ts +735 -0
  201. package/src/index.ts +17 -5
  202. package/src/router/ElementRouter.ts +2 -2
  203. package/src/types.ts +15 -6
  204. package/src/utils/TemplateUtils.ts +83 -0
  205. package/src/utils/Utils.ts +6 -3
  206. package/dist/cjs/elements/SwcApp.js +0 -55
  207. package/dist/cjs/elements/SwcApp.js.map +0 -7
  208. package/dist/cjs/elements/is/SwcAppAnchor.js +0 -55
  209. package/dist/cjs/elements/is/SwcAppAnchor.js.map +0 -7
  210. package/dist/cjs/elements/is/SwcAppArea.js +0 -55
  211. package/dist/cjs/elements/is/SwcAppArea.js.map +0 -7
  212. package/dist/cjs/elements/is/SwcAppAudio.js +0 -55
  213. package/dist/cjs/elements/is/SwcAppAudio.js.map +0 -7
  214. package/dist/cjs/elements/is/SwcAppBase.js +0 -55
  215. package/dist/cjs/elements/is/SwcAppBase.js.map +0 -7
  216. package/dist/cjs/elements/is/SwcAppBody.js +0 -55
  217. package/dist/cjs/elements/is/SwcAppBody.js.map +0 -7
  218. package/dist/cjs/elements/is/SwcAppButton.js +0 -55
  219. package/dist/cjs/elements/is/SwcAppButton.js.map +0 -7
  220. package/dist/cjs/elements/is/SwcAppCanvas.js +0 -55
  221. package/dist/cjs/elements/is/SwcAppCanvas.js.map +0 -7
  222. package/dist/cjs/elements/is/SwcAppData.js +0 -55
  223. package/dist/cjs/elements/is/SwcAppData.js.map +0 -7
  224. package/dist/cjs/elements/is/SwcAppDataList.js +0 -55
  225. package/dist/cjs/elements/is/SwcAppDataList.js.map +0 -7
  226. package/dist/cjs/elements/is/SwcAppDetails.js +0 -55
  227. package/dist/cjs/elements/is/SwcAppDetails.js.map +0 -7
  228. package/dist/cjs/elements/is/SwcAppDialog.js +0 -55
  229. package/dist/cjs/elements/is/SwcAppDialog.js.map +0 -7
  230. package/dist/cjs/elements/is/SwcAppDiv.js +0 -55
  231. package/dist/cjs/elements/is/SwcAppDiv.js.map +0 -7
  232. package/dist/cjs/elements/is/SwcAppDl.js +0 -55
  233. package/dist/cjs/elements/is/SwcAppDl.js.map +0 -7
  234. package/dist/cjs/elements/is/SwcAppEmbed.js +0 -55
  235. package/dist/cjs/elements/is/SwcAppEmbed.js.map +0 -7
  236. package/dist/cjs/elements/is/SwcAppFieldSet.js +0 -55
  237. package/dist/cjs/elements/is/SwcAppFieldSet.js.map +0 -7
  238. package/dist/cjs/elements/is/SwcAppForm.js +0 -55
  239. package/dist/cjs/elements/is/SwcAppForm.js.map +0 -7
  240. package/dist/cjs/elements/is/SwcAppHeading.js +0 -55
  241. package/dist/cjs/elements/is/SwcAppHeading.js.map +0 -7
  242. package/dist/cjs/elements/is/SwcAppHr.js +0 -55
  243. package/dist/cjs/elements/is/SwcAppHr.js.map +0 -7
  244. package/dist/cjs/elements/is/SwcAppIFrame.js +0 -55
  245. package/dist/cjs/elements/is/SwcAppIFrame.js.map +0 -7
  246. package/dist/cjs/elements/is/SwcAppImage.js +0 -55
  247. package/dist/cjs/elements/is/SwcAppImage.js.map +0 -7
  248. package/dist/cjs/elements/is/SwcAppInput.js +0 -55
  249. package/dist/cjs/elements/is/SwcAppInput.js.map +0 -7
  250. package/dist/cjs/elements/is/SwcAppLabel.js +0 -55
  251. package/dist/cjs/elements/is/SwcAppLabel.js.map +0 -7
  252. package/dist/cjs/elements/is/SwcAppLegend.js +0 -55
  253. package/dist/cjs/elements/is/SwcAppLegend.js.map +0 -7
  254. package/dist/cjs/elements/is/SwcAppLi.js +0 -55
  255. package/dist/cjs/elements/is/SwcAppLi.js.map +0 -7
  256. package/dist/cjs/elements/is/SwcAppLink.js +0 -55
  257. package/dist/cjs/elements/is/SwcAppLink.js.map +0 -7
  258. package/dist/cjs/elements/is/SwcAppMap.js +0 -55
  259. package/dist/cjs/elements/is/SwcAppMap.js.map +0 -7
  260. package/dist/cjs/elements/is/SwcAppMeta.js +0 -55
  261. package/dist/cjs/elements/is/SwcAppMeta.js.map +0 -7
  262. package/dist/cjs/elements/is/SwcAppMeter.js +0 -55
  263. package/dist/cjs/elements/is/SwcAppMeter.js.map +0 -7
  264. package/dist/cjs/elements/is/SwcAppMod.js +0 -55
  265. package/dist/cjs/elements/is/SwcAppMod.js.map +0 -7
  266. package/dist/cjs/elements/is/SwcAppObject.js +0 -55
  267. package/dist/cjs/elements/is/SwcAppObject.js.map +0 -7
  268. package/dist/cjs/elements/is/SwcAppOl.js +0 -55
  269. package/dist/cjs/elements/is/SwcAppOl.js.map +0 -7
  270. package/dist/cjs/elements/is/SwcAppOptGroup.js +0 -55
  271. package/dist/cjs/elements/is/SwcAppOptGroup.js.map +0 -7
  272. package/dist/cjs/elements/is/SwcAppOption.js +0 -55
  273. package/dist/cjs/elements/is/SwcAppOption.js.map +0 -7
  274. package/dist/cjs/elements/is/SwcAppOutput.js +0 -55
  275. package/dist/cjs/elements/is/SwcAppOutput.js.map +0 -7
  276. package/dist/cjs/elements/is/SwcAppParagraph.js +0 -55
  277. package/dist/cjs/elements/is/SwcAppParagraph.js.map +0 -7
  278. package/dist/cjs/elements/is/SwcAppParam.js +0 -55
  279. package/dist/cjs/elements/is/SwcAppParam.js.map +0 -7
  280. package/dist/cjs/elements/is/SwcAppPicture.js +0 -55
  281. package/dist/cjs/elements/is/SwcAppPicture.js.map +0 -7
  282. package/dist/cjs/elements/is/SwcAppPre.js +0 -55
  283. package/dist/cjs/elements/is/SwcAppPre.js.map +0 -7
  284. package/dist/cjs/elements/is/SwcAppProgress.js +0 -55
  285. package/dist/cjs/elements/is/SwcAppProgress.js.map +0 -7
  286. package/dist/cjs/elements/is/SwcAppQuote.js +0 -55
  287. package/dist/cjs/elements/is/SwcAppQuote.js.map +0 -7
  288. package/dist/cjs/elements/is/SwcAppScript.js +0 -55
  289. package/dist/cjs/elements/is/SwcAppScript.js.map +0 -7
  290. package/dist/cjs/elements/is/SwcAppSelect.js +0 -55
  291. package/dist/cjs/elements/is/SwcAppSelect.js.map +0 -7
  292. package/dist/cjs/elements/is/SwcAppSlot.js +0 -55
  293. package/dist/cjs/elements/is/SwcAppSlot.js.map +0 -7
  294. package/dist/cjs/elements/is/SwcAppSource.js +0 -55
  295. package/dist/cjs/elements/is/SwcAppSource.js.map +0 -7
  296. package/dist/cjs/elements/is/SwcAppSpan.js +0 -55
  297. package/dist/cjs/elements/is/SwcAppSpan.js.map +0 -7
  298. package/dist/cjs/elements/is/SwcAppStyle.js +0 -55
  299. package/dist/cjs/elements/is/SwcAppStyle.js.map +0 -7
  300. package/dist/cjs/elements/is/SwcAppTable.js +0 -55
  301. package/dist/cjs/elements/is/SwcAppTable.js.map +0 -7
  302. package/dist/cjs/elements/is/SwcAppTableCell.js +0 -55
  303. package/dist/cjs/elements/is/SwcAppTableCell.js.map +0 -7
  304. package/dist/cjs/elements/is/SwcAppTableRow.js +0 -55
  305. package/dist/cjs/elements/is/SwcAppTableRow.js.map +0 -7
  306. package/dist/cjs/elements/is/SwcAppTableSection.js +0 -55
  307. package/dist/cjs/elements/is/SwcAppTableSection.js.map +0 -7
  308. package/dist/cjs/elements/is/SwcAppTemplate.js +0 -55
  309. package/dist/cjs/elements/is/SwcAppTemplate.js.map +0 -7
  310. package/dist/cjs/elements/is/SwcAppTextArea.js +0 -55
  311. package/dist/cjs/elements/is/SwcAppTextArea.js.map +0 -7
  312. package/dist/cjs/elements/is/SwcAppTime.js +0 -55
  313. package/dist/cjs/elements/is/SwcAppTime.js.map +0 -7
  314. package/dist/cjs/elements/is/SwcAppTitle.js +0 -55
  315. package/dist/cjs/elements/is/SwcAppTitle.js.map +0 -7
  316. package/dist/cjs/elements/is/SwcAppTrack.js +0 -55
  317. package/dist/cjs/elements/is/SwcAppTrack.js.map +0 -7
  318. package/dist/cjs/elements/is/SwcAppUl.js +0 -55
  319. package/dist/cjs/elements/is/SwcAppUl.js.map +0 -7
  320. package/dist/cjs/elements/is/SwcAppVideo.js +0 -55
  321. package/dist/cjs/elements/is/SwcAppVideo.js.map +0 -7
  322. package/dist/cjs/elements/is/index.js +0 -74
  323. package/dist/cjs/elements/is/index.js.map +0 -7
  324. package/dist/esm/elements/SwcApp.js +0 -36
  325. package/dist/esm/elements/SwcApp.js.map +0 -7
  326. package/dist/esm/elements/is/SwcAppAnchor.js +0 -36
  327. package/dist/esm/elements/is/SwcAppAnchor.js.map +0 -7
  328. package/dist/esm/elements/is/SwcAppArea.js +0 -36
  329. package/dist/esm/elements/is/SwcAppArea.js.map +0 -7
  330. package/dist/esm/elements/is/SwcAppAudio.js +0 -36
  331. package/dist/esm/elements/is/SwcAppAudio.js.map +0 -7
  332. package/dist/esm/elements/is/SwcAppBase.js +0 -36
  333. package/dist/esm/elements/is/SwcAppBase.js.map +0 -7
  334. package/dist/esm/elements/is/SwcAppBody.js +0 -36
  335. package/dist/esm/elements/is/SwcAppBody.js.map +0 -7
  336. package/dist/esm/elements/is/SwcAppButton.js +0 -36
  337. package/dist/esm/elements/is/SwcAppButton.js.map +0 -7
  338. package/dist/esm/elements/is/SwcAppCanvas.js +0 -36
  339. package/dist/esm/elements/is/SwcAppCanvas.js.map +0 -7
  340. package/dist/esm/elements/is/SwcAppData.js +0 -36
  341. package/dist/esm/elements/is/SwcAppData.js.map +0 -7
  342. package/dist/esm/elements/is/SwcAppDataList.js +0 -36
  343. package/dist/esm/elements/is/SwcAppDataList.js.map +0 -7
  344. package/dist/esm/elements/is/SwcAppDetails.js +0 -36
  345. package/dist/esm/elements/is/SwcAppDetails.js.map +0 -7
  346. package/dist/esm/elements/is/SwcAppDialog.js +0 -36
  347. package/dist/esm/elements/is/SwcAppDialog.js.map +0 -7
  348. package/dist/esm/elements/is/SwcAppDiv.js +0 -36
  349. package/dist/esm/elements/is/SwcAppDiv.js.map +0 -7
  350. package/dist/esm/elements/is/SwcAppDl.js +0 -36
  351. package/dist/esm/elements/is/SwcAppDl.js.map +0 -7
  352. package/dist/esm/elements/is/SwcAppEmbed.js +0 -36
  353. package/dist/esm/elements/is/SwcAppEmbed.js.map +0 -7
  354. package/dist/esm/elements/is/SwcAppFieldSet.js +0 -36
  355. package/dist/esm/elements/is/SwcAppFieldSet.js.map +0 -7
  356. package/dist/esm/elements/is/SwcAppForm.js +0 -36
  357. package/dist/esm/elements/is/SwcAppForm.js.map +0 -7
  358. package/dist/esm/elements/is/SwcAppHeading.js +0 -36
  359. package/dist/esm/elements/is/SwcAppHeading.js.map +0 -7
  360. package/dist/esm/elements/is/SwcAppHr.js +0 -36
  361. package/dist/esm/elements/is/SwcAppHr.js.map +0 -7
  362. package/dist/esm/elements/is/SwcAppIFrame.js +0 -36
  363. package/dist/esm/elements/is/SwcAppIFrame.js.map +0 -7
  364. package/dist/esm/elements/is/SwcAppImage.js +0 -36
  365. package/dist/esm/elements/is/SwcAppImage.js.map +0 -7
  366. package/dist/esm/elements/is/SwcAppInput.js +0 -36
  367. package/dist/esm/elements/is/SwcAppInput.js.map +0 -7
  368. package/dist/esm/elements/is/SwcAppLabel.js +0 -36
  369. package/dist/esm/elements/is/SwcAppLabel.js.map +0 -7
  370. package/dist/esm/elements/is/SwcAppLegend.js +0 -36
  371. package/dist/esm/elements/is/SwcAppLegend.js.map +0 -7
  372. package/dist/esm/elements/is/SwcAppLi.js +0 -36
  373. package/dist/esm/elements/is/SwcAppLi.js.map +0 -7
  374. package/dist/esm/elements/is/SwcAppLink.js +0 -36
  375. package/dist/esm/elements/is/SwcAppLink.js.map +0 -7
  376. package/dist/esm/elements/is/SwcAppMap.js +0 -36
  377. package/dist/esm/elements/is/SwcAppMap.js.map +0 -7
  378. package/dist/esm/elements/is/SwcAppMeta.js +0 -36
  379. package/dist/esm/elements/is/SwcAppMeta.js.map +0 -7
  380. package/dist/esm/elements/is/SwcAppMeter.js +0 -36
  381. package/dist/esm/elements/is/SwcAppMeter.js.map +0 -7
  382. package/dist/esm/elements/is/SwcAppMod.js +0 -36
  383. package/dist/esm/elements/is/SwcAppMod.js.map +0 -7
  384. package/dist/esm/elements/is/SwcAppObject.js +0 -36
  385. package/dist/esm/elements/is/SwcAppObject.js.map +0 -7
  386. package/dist/esm/elements/is/SwcAppOl.js +0 -36
  387. package/dist/esm/elements/is/SwcAppOl.js.map +0 -7
  388. package/dist/esm/elements/is/SwcAppOptGroup.js +0 -36
  389. package/dist/esm/elements/is/SwcAppOptGroup.js.map +0 -7
  390. package/dist/esm/elements/is/SwcAppOption.js +0 -36
  391. package/dist/esm/elements/is/SwcAppOption.js.map +0 -7
  392. package/dist/esm/elements/is/SwcAppOutput.js +0 -36
  393. package/dist/esm/elements/is/SwcAppOutput.js.map +0 -7
  394. package/dist/esm/elements/is/SwcAppParagraph.js +0 -36
  395. package/dist/esm/elements/is/SwcAppParagraph.js.map +0 -7
  396. package/dist/esm/elements/is/SwcAppParam.js +0 -36
  397. package/dist/esm/elements/is/SwcAppParam.js.map +0 -7
  398. package/dist/esm/elements/is/SwcAppPicture.js +0 -36
  399. package/dist/esm/elements/is/SwcAppPicture.js.map +0 -7
  400. package/dist/esm/elements/is/SwcAppPre.js +0 -36
  401. package/dist/esm/elements/is/SwcAppPre.js.map +0 -7
  402. package/dist/esm/elements/is/SwcAppProgress.js +0 -36
  403. package/dist/esm/elements/is/SwcAppProgress.js.map +0 -7
  404. package/dist/esm/elements/is/SwcAppQuote.js +0 -36
  405. package/dist/esm/elements/is/SwcAppQuote.js.map +0 -7
  406. package/dist/esm/elements/is/SwcAppScript.js +0 -36
  407. package/dist/esm/elements/is/SwcAppScript.js.map +0 -7
  408. package/dist/esm/elements/is/SwcAppSelect.js +0 -36
  409. package/dist/esm/elements/is/SwcAppSelect.js.map +0 -7
  410. package/dist/esm/elements/is/SwcAppSlot.js +0 -36
  411. package/dist/esm/elements/is/SwcAppSlot.js.map +0 -7
  412. package/dist/esm/elements/is/SwcAppSource.js +0 -36
  413. package/dist/esm/elements/is/SwcAppSource.js.map +0 -7
  414. package/dist/esm/elements/is/SwcAppSpan.js +0 -36
  415. package/dist/esm/elements/is/SwcAppSpan.js.map +0 -7
  416. package/dist/esm/elements/is/SwcAppStyle.js +0 -36
  417. package/dist/esm/elements/is/SwcAppStyle.js.map +0 -7
  418. package/dist/esm/elements/is/SwcAppTable.js +0 -36
  419. package/dist/esm/elements/is/SwcAppTable.js.map +0 -7
  420. package/dist/esm/elements/is/SwcAppTableCell.js +0 -36
  421. package/dist/esm/elements/is/SwcAppTableCell.js.map +0 -7
  422. package/dist/esm/elements/is/SwcAppTableRow.js +0 -36
  423. package/dist/esm/elements/is/SwcAppTableRow.js.map +0 -7
  424. package/dist/esm/elements/is/SwcAppTableSection.js +0 -36
  425. package/dist/esm/elements/is/SwcAppTableSection.js.map +0 -7
  426. package/dist/esm/elements/is/SwcAppTemplate.js +0 -36
  427. package/dist/esm/elements/is/SwcAppTemplate.js.map +0 -7
  428. package/dist/esm/elements/is/SwcAppTextArea.js +0 -36
  429. package/dist/esm/elements/is/SwcAppTextArea.js.map +0 -7
  430. package/dist/esm/elements/is/SwcAppTime.js +0 -36
  431. package/dist/esm/elements/is/SwcAppTime.js.map +0 -7
  432. package/dist/esm/elements/is/SwcAppTitle.js +0 -36
  433. package/dist/esm/elements/is/SwcAppTitle.js.map +0 -7
  434. package/dist/esm/elements/is/SwcAppTrack.js +0 -36
  435. package/dist/esm/elements/is/SwcAppTrack.js.map +0 -7
  436. package/dist/esm/elements/is/SwcAppUl.js +0 -36
  437. package/dist/esm/elements/is/SwcAppUl.js.map +0 -7
  438. package/dist/esm/elements/is/SwcAppVideo.js +0 -36
  439. package/dist/esm/elements/is/SwcAppVideo.js.map +0 -7
  440. package/dist/esm/elements/is/index.js +0 -58
  441. package/dist/esm/elements/is/index.js.map +0 -7
  442. package/dist/types/elements/SwcApp.d.ts +0 -9
  443. package/dist/types/elements/SwcApp.d.ts.map +0 -1
  444. package/dist/types/elements/is/SwcAppAnchor.d.ts +0 -9
  445. package/dist/types/elements/is/SwcAppAnchor.d.ts.map +0 -1
  446. package/dist/types/elements/is/SwcAppArea.d.ts +0 -9
  447. package/dist/types/elements/is/SwcAppArea.d.ts.map +0 -1
  448. package/dist/types/elements/is/SwcAppAudio.d.ts +0 -9
  449. package/dist/types/elements/is/SwcAppAudio.d.ts.map +0 -1
  450. package/dist/types/elements/is/SwcAppBase.d.ts +0 -9
  451. package/dist/types/elements/is/SwcAppBase.d.ts.map +0 -1
  452. package/dist/types/elements/is/SwcAppBody.d.ts +0 -9
  453. package/dist/types/elements/is/SwcAppBody.d.ts.map +0 -1
  454. package/dist/types/elements/is/SwcAppButton.d.ts +0 -9
  455. package/dist/types/elements/is/SwcAppButton.d.ts.map +0 -1
  456. package/dist/types/elements/is/SwcAppCanvas.d.ts +0 -9
  457. package/dist/types/elements/is/SwcAppCanvas.d.ts.map +0 -1
  458. package/dist/types/elements/is/SwcAppData.d.ts +0 -9
  459. package/dist/types/elements/is/SwcAppData.d.ts.map +0 -1
  460. package/dist/types/elements/is/SwcAppDataList.d.ts +0 -9
  461. package/dist/types/elements/is/SwcAppDataList.d.ts.map +0 -1
  462. package/dist/types/elements/is/SwcAppDetails.d.ts +0 -9
  463. package/dist/types/elements/is/SwcAppDetails.d.ts.map +0 -1
  464. package/dist/types/elements/is/SwcAppDialog.d.ts +0 -9
  465. package/dist/types/elements/is/SwcAppDialog.d.ts.map +0 -1
  466. package/dist/types/elements/is/SwcAppDiv.d.ts +0 -9
  467. package/dist/types/elements/is/SwcAppDiv.d.ts.map +0 -1
  468. package/dist/types/elements/is/SwcAppDl.d.ts +0 -9
  469. package/dist/types/elements/is/SwcAppDl.d.ts.map +0 -1
  470. package/dist/types/elements/is/SwcAppEmbed.d.ts +0 -9
  471. package/dist/types/elements/is/SwcAppEmbed.d.ts.map +0 -1
  472. package/dist/types/elements/is/SwcAppFieldSet.d.ts +0 -9
  473. package/dist/types/elements/is/SwcAppFieldSet.d.ts.map +0 -1
  474. package/dist/types/elements/is/SwcAppForm.d.ts +0 -9
  475. package/dist/types/elements/is/SwcAppForm.d.ts.map +0 -1
  476. package/dist/types/elements/is/SwcAppHeading.d.ts +0 -9
  477. package/dist/types/elements/is/SwcAppHeading.d.ts.map +0 -1
  478. package/dist/types/elements/is/SwcAppHr.d.ts +0 -9
  479. package/dist/types/elements/is/SwcAppHr.d.ts.map +0 -1
  480. package/dist/types/elements/is/SwcAppIFrame.d.ts +0 -9
  481. package/dist/types/elements/is/SwcAppIFrame.d.ts.map +0 -1
  482. package/dist/types/elements/is/SwcAppImage.d.ts +0 -9
  483. package/dist/types/elements/is/SwcAppImage.d.ts.map +0 -1
  484. package/dist/types/elements/is/SwcAppInput.d.ts +0 -9
  485. package/dist/types/elements/is/SwcAppInput.d.ts.map +0 -1
  486. package/dist/types/elements/is/SwcAppLabel.d.ts +0 -9
  487. package/dist/types/elements/is/SwcAppLabel.d.ts.map +0 -1
  488. package/dist/types/elements/is/SwcAppLegend.d.ts +0 -9
  489. package/dist/types/elements/is/SwcAppLegend.d.ts.map +0 -1
  490. package/dist/types/elements/is/SwcAppLi.d.ts +0 -9
  491. package/dist/types/elements/is/SwcAppLi.d.ts.map +0 -1
  492. package/dist/types/elements/is/SwcAppLink.d.ts +0 -9
  493. package/dist/types/elements/is/SwcAppLink.d.ts.map +0 -1
  494. package/dist/types/elements/is/SwcAppMap.d.ts +0 -9
  495. package/dist/types/elements/is/SwcAppMap.d.ts.map +0 -1
  496. package/dist/types/elements/is/SwcAppMeta.d.ts +0 -9
  497. package/dist/types/elements/is/SwcAppMeta.d.ts.map +0 -1
  498. package/dist/types/elements/is/SwcAppMeter.d.ts +0 -9
  499. package/dist/types/elements/is/SwcAppMeter.d.ts.map +0 -1
  500. package/dist/types/elements/is/SwcAppMod.d.ts +0 -9
  501. package/dist/types/elements/is/SwcAppMod.d.ts.map +0 -1
  502. package/dist/types/elements/is/SwcAppObject.d.ts +0 -9
  503. package/dist/types/elements/is/SwcAppObject.d.ts.map +0 -1
  504. package/dist/types/elements/is/SwcAppOl.d.ts +0 -9
  505. package/dist/types/elements/is/SwcAppOl.d.ts.map +0 -1
  506. package/dist/types/elements/is/SwcAppOptGroup.d.ts +0 -9
  507. package/dist/types/elements/is/SwcAppOptGroup.d.ts.map +0 -1
  508. package/dist/types/elements/is/SwcAppOption.d.ts +0 -9
  509. package/dist/types/elements/is/SwcAppOption.d.ts.map +0 -1
  510. package/dist/types/elements/is/SwcAppOutput.d.ts +0 -9
  511. package/dist/types/elements/is/SwcAppOutput.d.ts.map +0 -1
  512. package/dist/types/elements/is/SwcAppParagraph.d.ts +0 -9
  513. package/dist/types/elements/is/SwcAppParagraph.d.ts.map +0 -1
  514. package/dist/types/elements/is/SwcAppParam.d.ts +0 -9
  515. package/dist/types/elements/is/SwcAppParam.d.ts.map +0 -1
  516. package/dist/types/elements/is/SwcAppPicture.d.ts +0 -9
  517. package/dist/types/elements/is/SwcAppPicture.d.ts.map +0 -1
  518. package/dist/types/elements/is/SwcAppPre.d.ts +0 -9
  519. package/dist/types/elements/is/SwcAppPre.d.ts.map +0 -1
  520. package/dist/types/elements/is/SwcAppProgress.d.ts +0 -9
  521. package/dist/types/elements/is/SwcAppProgress.d.ts.map +0 -1
  522. package/dist/types/elements/is/SwcAppQuote.d.ts +0 -9
  523. package/dist/types/elements/is/SwcAppQuote.d.ts.map +0 -1
  524. package/dist/types/elements/is/SwcAppScript.d.ts +0 -9
  525. package/dist/types/elements/is/SwcAppScript.d.ts.map +0 -1
  526. package/dist/types/elements/is/SwcAppSelect.d.ts +0 -9
  527. package/dist/types/elements/is/SwcAppSelect.d.ts.map +0 -1
  528. package/dist/types/elements/is/SwcAppSlot.d.ts +0 -9
  529. package/dist/types/elements/is/SwcAppSlot.d.ts.map +0 -1
  530. package/dist/types/elements/is/SwcAppSource.d.ts +0 -9
  531. package/dist/types/elements/is/SwcAppSource.d.ts.map +0 -1
  532. package/dist/types/elements/is/SwcAppSpan.d.ts +0 -9
  533. package/dist/types/elements/is/SwcAppSpan.d.ts.map +0 -1
  534. package/dist/types/elements/is/SwcAppStyle.d.ts +0 -9
  535. package/dist/types/elements/is/SwcAppStyle.d.ts.map +0 -1
  536. package/dist/types/elements/is/SwcAppTable.d.ts +0 -9
  537. package/dist/types/elements/is/SwcAppTable.d.ts.map +0 -1
  538. package/dist/types/elements/is/SwcAppTableCell.d.ts +0 -9
  539. package/dist/types/elements/is/SwcAppTableCell.d.ts.map +0 -1
  540. package/dist/types/elements/is/SwcAppTableRow.d.ts +0 -9
  541. package/dist/types/elements/is/SwcAppTableRow.d.ts.map +0 -1
  542. package/dist/types/elements/is/SwcAppTableSection.d.ts +0 -9
  543. package/dist/types/elements/is/SwcAppTableSection.d.ts.map +0 -1
  544. package/dist/types/elements/is/SwcAppTemplate.d.ts +0 -9
  545. package/dist/types/elements/is/SwcAppTemplate.d.ts.map +0 -1
  546. package/dist/types/elements/is/SwcAppTextArea.d.ts +0 -9
  547. package/dist/types/elements/is/SwcAppTextArea.d.ts.map +0 -1
  548. package/dist/types/elements/is/SwcAppTime.d.ts +0 -9
  549. package/dist/types/elements/is/SwcAppTime.d.ts.map +0 -1
  550. package/dist/types/elements/is/SwcAppTitle.d.ts +0 -9
  551. package/dist/types/elements/is/SwcAppTitle.d.ts.map +0 -1
  552. package/dist/types/elements/is/SwcAppTrack.d.ts +0 -9
  553. package/dist/types/elements/is/SwcAppTrack.d.ts.map +0 -1
  554. package/dist/types/elements/is/SwcAppUl.d.ts +0 -9
  555. package/dist/types/elements/is/SwcAppUl.d.ts.map +0 -1
  556. package/dist/types/elements/is/SwcAppVideo.d.ts +0 -9
  557. package/dist/types/elements/is/SwcAppVideo.d.ts.map +0 -1
  558. package/dist/types/elements/is/index.d.ts +0 -58
  559. package/dist/types/elements/is/index.d.ts.map +0 -1
  560. package/src/elements/SwcApp.ts +0 -26
  561. package/src/elements/is/SwcAppAnchor.ts +0 -26
  562. package/src/elements/is/SwcAppArea.ts +0 -26
  563. package/src/elements/is/SwcAppAudio.ts +0 -26
  564. package/src/elements/is/SwcAppBase.ts +0 -26
  565. package/src/elements/is/SwcAppBody.ts +0 -26
  566. package/src/elements/is/SwcAppButton.ts +0 -26
  567. package/src/elements/is/SwcAppCanvas.ts +0 -26
  568. package/src/elements/is/SwcAppData.ts +0 -26
  569. package/src/elements/is/SwcAppDataList.ts +0 -26
  570. package/src/elements/is/SwcAppDetails.ts +0 -26
  571. package/src/elements/is/SwcAppDialog.ts +0 -26
  572. package/src/elements/is/SwcAppDiv.ts +0 -26
  573. package/src/elements/is/SwcAppDl.ts +0 -26
  574. package/src/elements/is/SwcAppEmbed.ts +0 -26
  575. package/src/elements/is/SwcAppFieldSet.ts +0 -26
  576. package/src/elements/is/SwcAppForm.ts +0 -26
  577. package/src/elements/is/SwcAppHeading.ts +0 -26
  578. package/src/elements/is/SwcAppHr.ts +0 -26
  579. package/src/elements/is/SwcAppIFrame.ts +0 -26
  580. package/src/elements/is/SwcAppImage.ts +0 -26
  581. package/src/elements/is/SwcAppInput.ts +0 -26
  582. package/src/elements/is/SwcAppLabel.ts +0 -26
  583. package/src/elements/is/SwcAppLegend.ts +0 -26
  584. package/src/elements/is/SwcAppLi.ts +0 -26
  585. package/src/elements/is/SwcAppLink.ts +0 -26
  586. package/src/elements/is/SwcAppMap.ts +0 -26
  587. package/src/elements/is/SwcAppMeta.ts +0 -26
  588. package/src/elements/is/SwcAppMeter.ts +0 -26
  589. package/src/elements/is/SwcAppMod.ts +0 -26
  590. package/src/elements/is/SwcAppObject.ts +0 -26
  591. package/src/elements/is/SwcAppOl.ts +0 -26
  592. package/src/elements/is/SwcAppOptGroup.ts +0 -26
  593. package/src/elements/is/SwcAppOption.ts +0 -26
  594. package/src/elements/is/SwcAppOutput.ts +0 -26
  595. package/src/elements/is/SwcAppParagraph.ts +0 -26
  596. package/src/elements/is/SwcAppParam.ts +0 -26
  597. package/src/elements/is/SwcAppPicture.ts +0 -26
  598. package/src/elements/is/SwcAppPre.ts +0 -26
  599. package/src/elements/is/SwcAppProgress.ts +0 -26
  600. package/src/elements/is/SwcAppQuote.ts +0 -26
  601. package/src/elements/is/SwcAppScript.ts +0 -26
  602. package/src/elements/is/SwcAppSelect.ts +0 -26
  603. package/src/elements/is/SwcAppSlot.ts +0 -26
  604. package/src/elements/is/SwcAppSource.ts +0 -26
  605. package/src/elements/is/SwcAppSpan.ts +0 -26
  606. package/src/elements/is/SwcAppStyle.ts +0 -26
  607. package/src/elements/is/SwcAppTable.ts +0 -26
  608. package/src/elements/is/SwcAppTableCell.ts +0 -26
  609. package/src/elements/is/SwcAppTableRow.ts +0 -26
  610. package/src/elements/is/SwcAppTableSection.ts +0 -26
  611. package/src/elements/is/SwcAppTemplate.ts +0 -26
  612. package/src/elements/is/SwcAppTextArea.ts +0 -26
  613. package/src/elements/is/SwcAppTime.ts +0 -26
  614. package/src/elements/is/SwcAppTitle.ts +0 -26
  615. package/src/elements/is/SwcAppTrack.ts +0 -26
  616. package/src/elements/is/SwcAppUl.ts +0 -26
  617. package/src/elements/is/SwcAppVideo.ts +0 -26
  618. package/src/elements/is/index.ts +0 -57
package/README.md CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  > **"Pure, Standards-Compliant, and Blazing Fast Web Components Framework."**
4
4
 
5
- `simple-web-component` (SWC) is a minimalist library designed for building high-performance Web Components and Single Page Applications (SPA). It strips away heavy "magic" features like Proxy-based reactivity and continuous `MutationObserver` scans in favor of a **Pure Architecture** that stays out of your way while offering professional-grade Dependency Injection (DI) and Routing.
5
+ `simple-web-component` (SWC) is a minimalist library designed for building high-performance Web Components and Single Page Applications (SPA). It strips away heavy "magic" features like Proxy-based reactivity and continuous `MutationObserver` scans in favor of a **Pure Architecture** that adheres strictly to browser standards.
6
6
 
7
7
  ---
8
8
 
9
9
  ## 🚀 Why SWC?
10
10
 
11
11
  - **Zero Magic**: No Proxy traps, no Virtual DOM diffing. Predictive and standard-compliant.
12
- - **Native Inheritance**: Inherit directly from `HTMLElement`, `HTMLDivElement`, etc.
12
+ - **Native Inheritance**: Inherit directly from `HTMLElement`, `HTMLDivElement`, or `HTMLTemplateElement`.
13
13
  - **Extreme Performance**: Ideal for high-load UIs (1,000+ nodes) with minimal memory overhead.
14
14
  - **Micro-Frontend Ready**: Independent routing and DI containers for every component scope.
15
15
  - **Standard-First**: Works directly with native Custom Elements, Shadow DOM, and Slots.
@@ -58,7 +58,13 @@ class MyEl extends HTMLElement {
58
58
  ### 3. Modern Attribute Management
59
59
  SWC uses a **Method-Based Reflection** approach. You control exactly how data flows.
60
60
 
61
- - **`@setAttribute(name?)`**: Reflects the method's **return value** to the DOM attribute.
61
+ **Attribute sync rules**
62
+ - Initial sync honors DOM-first semantics: if a markup attribute already exists (e.g., `<my-el count="11">`), the first write keeps that DOM value even when the class defines `count = 0`.
63
+ - `connectedInitialize: true` flips the direction for that property so the in-memory value is pushed to the DOM during `connectedCallback`.
64
+ - Type conversion is automatic through `convertValue` so `Boolean`, `Number`, and `String` fields always expose typed values while still storing the serialized attribute on the element.
65
+ - Getters return `null` when the resolved target exists but the attribute is absent, giving you an explicit signal that the DOM is missing that state.
66
+
67
+ - **`@setAttribute(name?, options?)`**: Reflects the method's **return value** to the DOM attribute. Supports `SwcQueryOptions` for root-aware target resolution (light DOM, shadow DOM, or auto-detect).
62
68
  - **`@changedAttribute(name?)`**: A handler triggered when the attribute changes.
63
69
 
64
70
  ```typescript
@@ -66,10 +72,14 @@ SWC uses a **Method-Based Reflection** approach. You control exactly how data fl
66
72
  class MyCounter extends HTMLElement {
67
73
  private count = 0;
68
74
  @query('#display') displayEl?: HTMLElement;
75
+ @query('#shadow-input', { root: 'shadow' }) shadowInput?: HTMLInputElement;
69
76
 
70
77
  @setAttribute('count')
71
78
  updateCount(val: number) { return val; } // Sets 'count' attribute in DOM
72
79
 
80
+ @setAttribute('shadow-value', { root: 'shadow' })
81
+ updateShadowValue(val: string) { return val; } // Sets attribute on shadow DOM element
82
+
73
83
  @changedAttribute('count')
74
84
  onCountChange(newVal: string, oldVal: string, name: string) {
75
85
  this.count = Number(newVal);
@@ -80,262 +90,2153 @@ class MyCounter extends HTMLElement {
80
90
  ```
81
91
 
82
92
  ### 4. Powerful Queries (`@query`, `@queryAll`)
83
- Inject internal elements directly into properties. Supports the **`:host`** selector and precise root control. Assigning `null` or `[]` to these properties will surgically remove the target elements from the DOM.
93
+ Inject internal elements or host instances directly into properties. Assigning `null` or `[]` to these properties will surgically remove the target elements from the DOM.
84
94
 
85
- | Root Option | Description |
86
- |---|---|
87
- | `auto` (default) | Search in `shadowRoot` if exists, otherwise `this` (Light DOM). |
88
- | `shadow` | **Strictly** search in `shadowRoot`. Returns `null/[]` if no shadow. |
89
- | `light` | **Strictly** search in Light DOM (`this`). |
90
- | `all` | Search in **both** Shadow and Light DOM. |
95
+ #### Root Options
96
+ The `root` option controls which DOM tree is searched:
97
+ - **`'auto'`** (default): Searches shadow DOM first, then light DOM
98
+ - **`'light'`**: Searches only light DOM
99
+ - **`'shadow'`**: Searches only shadow DOM
100
+ - **`'all'`**: Searches all ancestors, returning `[lightNodes, shadowNodes]` array
101
+
102
+ #### Usage with Special Targets:
103
+ Special targets (starting with `:`) navigate the hierarchy and environment.
104
+ ```typescript
105
+ @query(':host') self!: HTMLElement;
106
+ @query(':parentHost') parent!: HTMLElement;
107
+ @query(':appHost') app!: SwcAppInterface;
108
+ @query(':window') win!: Window;
109
+ @query(':document') doc!: Document;
110
+ @queryAll(':hosts') ancestors!: HTMLElement[];
111
+ ```
91
112
 
113
+ #### Usage with Selectors & Root Options:
114
+ Standard CSS selectors support precise root control.
92
115
  ```typescript
93
- @query('.title') titleEl!: HTMLElement;
116
+ // root options: 'light' | 'shadow' | 'all' | 'auto' (default)
94
117
  @query('.btn', { root: 'shadow' }) shadowBtn!: HTMLButtonElement;
95
- @query(':host') self!: HTMLElement; // References the component itself
96
118
  ```
97
119
 
98
120
  ### 5. Smart Event Binding (`@addEventListener`)
99
- Bind events declaratively with support for **Event Delegation** and special targets like `:window` and `:document`.
121
+
122
+ Bind events declaratively with built-in **Event Delegation**, **Auto-Cleanup**, and **Context Injection**. Events flow through the component hierarchy with full access to parent scopes.
123
+
124
+ #### Core Features:
125
+ - **Direct Binding**: Bind to static selectors present at initialization
126
+ - **Event Delegation**: Automatically handle dynamically added elements
127
+ - **Auto-Cleanup**: Automatically remove listeners on `disconnectedCallback`
128
+ - **Context Injection**: Receive `$host`, `$parentHost`, `$appHost` automatically
129
+ - **Special Targets**: `:window`, `:document`, `:parentHost`, `:appHost`
130
+
131
+ #### Pattern 1: Direct Binding & Static Selectors
100
132
 
101
133
  ```typescript
102
- @elementDefine('event-demo')
103
- class EventDemo extends HTMLElement {
104
- // 1. Direct binding (Pure Mode)
105
- @addEventListener('.static-btn', 'click')
106
- onStaticClick(event: MouseEvent) { ... }
134
+ @Sim
135
+ @elementDefine('form-handler')
136
+ class FormHandler extends HTMLElement {
137
+ @query('#submit-btn') submitBtn?: HTMLButtonElement;
138
+ @query('#form') form?: HTMLFormElement;
139
+
140
+ // Bind to a specific static element
141
+ @addEventListener('#submit-btn', 'click')
142
+ onSubmit(event: MouseEvent) {
143
+ event.preventDefault();
144
+ console.log('Form submitted');
145
+ this.form?.submit();
146
+ }
107
147
 
108
- // 2. Event Delegation (Handles dynamic nodes)
109
- @addEventListener('.item', 'click', { delegate: true })
110
- onItemClick(event: MouseEvent, { $host }: HostSet, target: HTMLElement) {
111
- console.log('Clicked dynamic item:', target.textContent);
148
+ // Bind to multiple elements with selector
149
+ @addEventListener('input[type="text"]', 'input')
150
+ onTextInput(event: Event) {
151
+ console.log('Input value:', (event.target as HTMLInputElement).value);
112
152
  }
113
153
 
114
- // 3. Global Events with Auto-Cleanup
115
- @addEventListener(':window', 'resize', { removeOnDisconnected: true })
116
- onResize() { ... }
154
+ @onConnectedInnerHtml
155
+ render() {
156
+ return `
157
+ <form id="form">
158
+ <input type="text" placeholder="Enter name">
159
+ <input type="email" placeholder="Enter email">
160
+ <button id="submit-btn">Submit</button>
161
+ </form>
162
+ `;
163
+ }
117
164
  }
118
165
  ```
119
166
 
120
- ### 6. `@replaceChildren(selector)`
121
- Surgically replaces the children of a target element with the method's return value (`string`, `Node`, or `Array<Node|string>`).
167
+ #### Pattern 2: Event Delegation (Dynamic Content)
168
+
169
+ Automatically handle elements added **after component initialization**.
122
170
 
123
171
  ```typescript
124
- @elementDefine('surgical-demo')
125
- class SurgicalDemo extends HTMLElement {
126
- // Replaces all children of #display-area with the new content
127
- @replaceChildren('#display-area')
128
- updateView(title: string) {
129
- return `<h2>${title}</h2><p>Updated successfully.</p>`;
172
+ @Sim
173
+ @elementDefine('todo-app')
174
+ class TodoApp extends HTMLElement {
175
+ private todos: any[] = [];
176
+
177
+ constructor(private todoService: TodoService) { super(); }
178
+
179
+ // Delegate: Handles all current AND future .todo-item elements
180
+ @addEventListener('.todo-item', 'click', { delegate: true })
181
+ onTodoClick(event: MouseEvent, hostSet: any, target: HTMLElement) {
182
+ const todoId = target.getAttribute('data-id');
183
+ console.log('Clicked todo:', todoId);
184
+ this.selectTodo(todoId);
185
+ }
186
+
187
+ // Event delegation with checkbox - even newly added items react
188
+ @addEventListener('.todo-checkbox', 'change', { delegate: true })
189
+ onTodoToggle(event: Event, hostSet: any, target: HTMLInputElement) {
190
+ const todoId = target.closest('.todo-item')?.getAttribute('data-id');
191
+ const isChecked = target.checked;
192
+ console.log(`Todo ${todoId} ${isChecked ? 'completed' : 'uncompleted'}`);
193
+ }
194
+
195
+ async addTodo(text: string) {
196
+ const newTodo = await this.todoService.create(text);
197
+ this.todos.push(newTodo);
198
+ this.render();
199
+ // New .todo-item elements automatically get event listeners!
200
+ }
201
+
202
+ selectTodo(id: string) {
203
+ const todo = this.todos.find(t => t.id === id);
204
+ console.log('Selected:', todo);
205
+ }
206
+
207
+ @onConnectedInnerHtml
208
+ render() {
209
+ return `
210
+ <div>
211
+ <input type="text" placeholder="Add todo">
212
+ <button swc-on-click="$host.addTodo(this.previousElementSibling.value)">Add</button>
213
+ <ul>
214
+ ${this.todos.map(t => `
215
+ <li class="todo-item" data-id="${t.id}">
216
+ <input type="checkbox" class="todo-checkbox" ${t.done ? 'checked' : ''}>
217
+ <span>${t.text}</span>
218
+ </li>
219
+ `).join('')}
220
+ </ul>
221
+ </div>
222
+ `;
130
223
  }
131
224
  }
132
225
  ```
133
226
 
134
- ### 7. `@appendChild(selector, options?)`
135
- Appends or inserts the method's return value relative to a target element.
136
- - **position**: `'lastChild'` (default), `'firstChild'`, `'nextSibling'`, `'previousSibling'`.
227
+ #### Pattern 3: Global Events with Context Access
137
228
 
138
229
  ```typescript
139
- @elementDefine('list-manager')
140
- class ListManager extends HTMLElement {
141
- // Prepends a new item to the top of the #my-list element
142
- @appendChild('#my-list', { position: 'firstChild' })
143
- addNewItem(text: string) {
144
- return `<li>${text}</li>`;
230
+ @Sim
231
+ @elementDefine('responsive-layout')
232
+ class ResponsiveLayout extends HTMLElement {
233
+ private isMobile = false;
234
+
235
+ // Listen to window resize with auto-cleanup on disconnect
236
+ @addEventListener(':window', 'resize', { removeOnDisconnected: true })
237
+ onWindowResize() {
238
+ this.isMobile = window.innerWidth < 768;
239
+ this.updateLayout();
240
+ }
241
+
242
+ // Listen to global scroll with host context
243
+ @addEventListener(':window', 'scroll', { removeOnDisconnected: true })
244
+ onScroll(event: Event, { $appHost }: any) {
245
+ const scrollPos = window.scrollY;
246
+ console.log('Scrolled in app:', $appHost?.tagName, 'Position:', scrollPos);
247
+ }
248
+
249
+ updateLayout() {
250
+ this.className = this.isMobile ? 'mobile-layout' : 'desktop-layout';
251
+ }
252
+
253
+ @onConnectedInnerHtml
254
+ render() {
255
+ return `<div class="${this.isMobile ? 'mobile' : 'desktop'}"><slot></slot></div>`;
145
256
  }
146
257
  }
147
258
  ```
148
259
 
260
+ ### 6. `@replaceChildren(selector)`
261
+
262
+ Surgically replaces the children of a target element. Perfect for dynamic content updates without full-page re-renders.
263
+
264
+ **Use Cases:**
265
+ - Search results updating without page reload
266
+ - Filtering product lists
267
+ - Content swaps in tabbed interfaces
268
+ - Live data refreshes
269
+
270
+ #### Pattern 1: Simple Content Replacement
271
+
149
272
  ```typescript
150
- @elementDefine('list-manager')
151
- class ListManager extends HTMLElement {
152
- // Prepends a new item to the top of the #my-list element
153
- @appendChild('#my-list', { position: 'firstChild' })
154
- addNewItem(text: string) {
155
- return `<li>${text}</li>`;
273
+ @Sim
274
+ @elementDefine('search-results')
275
+ class SearchResults extends HTMLElement {
276
+ private results: any[] = [];
277
+ private isLoading = false;
278
+
279
+ // Replace #results-container with new search results
280
+ @replaceChildren('#results-container')
281
+ async displayResults(query: string) {
282
+ this.isLoading = true;
283
+ const startTime = Date.now();
284
+
285
+ try {
286
+ this.results = await fetch(`/api/search?q=${query}`)
287
+ .then(r => r.json());
288
+
289
+ return htmlFragment`
290
+ <div class="results-header">
291
+ <p>Found ${this.results.length} results in ${Date.now() - startTime}ms</p>
292
+ </div>
293
+ <div class="results-list">
294
+ ${this.results.map(item => `
295
+ <div class="result-item" data-id="${item.id}">
296
+ <h3>${item.title}</h3>
297
+ <p>${item.description}</p>
298
+ <a href="${item.url}">View</a>
299
+ </div>
300
+ `).join('')}
301
+ </div>
302
+ `;
303
+ } catch (error) {
304
+ return htmlFragment`<p class="error">Search failed: ${error.message}</p>`;
305
+ }
306
+ }
307
+
308
+ @onConnectedInnerHtml
309
+ render() {
310
+ return `
311
+ <div>
312
+ <input type="text" class="search-input" placeholder="Search...">
313
+ <button swc-on-click="$host.search($el.previousElementSibling.value)">Search</button>
314
+ <div id="results-container">
315
+ <p>Enter search term...</p>
316
+ </div>
317
+ </div>
318
+ `;
319
+ }
320
+
321
+ search(query: string) {
322
+ if (query.trim()) {
323
+ this.displayResults(query);
324
+ }
156
325
  }
157
326
  }
158
327
  ```
159
328
 
160
- ---
329
+ #### Pattern 2: Tab Content Switching
161
330
 
162
- ## 🌐 Powerful SPA & Routing
331
+ ```typescript
332
+ @Sim
333
+ @elementDefine('tabbed-panel')
334
+ class TabbedPanel extends HTMLElement {
335
+ private activeTab = 'overview';
336
+ private tabData: any = {
337
+ overview: '<h3>Overview</h3><p>General information...</p>',
338
+ details: '<h3>Details</h3><p>Detailed specifications...</p>',
339
+ reviews: '<h3>Reviews</h3><p>Customer reviews...</p>'
340
+ };
163
341
 
164
- SWC provides a revolutionary way to build SPAs where **each component scope is an independent application**.
342
+ // Click tab and automatically replace content
343
+ @replaceChildren('.tab-content')
344
+ switchTab(tabName: string) {
345
+ this.activeTab = tabName;
165
346
 
166
- ### 1. Isolated App Scopes (Micro-Frontends)
167
- Use the `<swc-app>` tag to create an isolated universe. Each instance has its own **DI Container** and **Router**.
347
+ // Update tab buttons visual state
348
+ Array.from(this.querySelectorAll('.tab-btn')).forEach(btn => {
349
+ btn.classList.toggle('active', btn.getAttribute('data-tab') === tabName);
350
+ });
168
351
 
169
- ```html
170
- <!-- index.html -->
171
- <swc-app swc-get-application-config="myAppConfig(this)"></swc-app>
352
+ // Return new content
353
+ return htmlFragment`${this.tabData[tabName]}`;
354
+ }
172
355
 
173
- <script>
174
- window.myAppConfig = (host) => {
175
- return {
176
- rootRouter: RootRouter, // The entry point class (must be @Sim)
177
- routeType: 'element', // 'element' (in-memory history), 'hash', or 'path'
178
- path: '/users/list', // Initial route path
179
- window: window // Optional: custom window object
180
- };
181
- };
356
+ @onConnectedInnerHtml
357
+ render() {
358
+ return `
359
+ <div class="tabs">
360
+ <button class="tab-btn active" data-tab="overview"
361
+ swc-on-click="$host.switchTab('overview')">Overview</button>
362
+ <button class="tab-btn" data-tab="details"
363
+ swc-on-click="$host.switchTab('details')">Details</button>
364
+ <button class="tab-btn" data-tab="reviews"
365
+ swc-on-click="$host.switchTab('reviews')">Reviews</button>
366
+ </div>
367
+ <div class="tab-content">${this.tabData.overview}</div>
368
+ `;
369
+ }
370
+ }
371
+ ```
372
+
373
+ ### 7. `@appendChild(selector, options?)`
182
374
 
183
- // External Control
184
- function navigateFromOutside() {
185
- const app = document.querySelector('swc-app');
186
- app.routing('/users/detail/2');
375
+ Appends or inserts the method's return value relative to a target element. Perfect for dynamically building lists, stacking notifications, or adding children without replacing existing content.
376
+
377
+ **Position Options:**
378
+ - **`'lastChild'`** (default): Append to end
379
+ - **`'firstChild'`**: Prepend to beginning
380
+ - **`'nextSibling'`**: Insert after element
381
+ - **`'previousSibling'`**: Insert before element
382
+
383
+ #### Pattern 1: Dynamic List Building
384
+
385
+ ```typescript
386
+ @Sim
387
+ @elementDefine('task-list')
388
+ class TaskList extends HTMLElement {
389
+ private tasks: any[] = [];
390
+ private taskIdCounter = 0;
391
+
392
+ // Append new task to bottom of list
393
+ @appendChild('#task-list', { position: 'lastChild' })
394
+ addTask(title: string, priority: 'low' | 'medium' | 'high' = 'medium') {
395
+ const id = ++this.taskIdCounter;
396
+ const bgColor = { low: '#e8f5e9', medium: '#fff3e0', high: '#ffebee' }[priority];
397
+
398
+ return htmlFragment`
399
+ <div class="task-item" data-id="${id}" style="background: ${bgColor}; padding: 12px; margin: 8px 0; border-radius: 4px;">
400
+ <div class="task-header">
401
+ <input type="checkbox" class="task-checkbox" data-id="${id}">
402
+ <span class="task-title">${title}</span>
403
+ <span class="task-priority">${priority.toUpperCase()}</span>
404
+ </div>
405
+ <button class="task-delete" swc-on-click="$host.deleteTask(${id})">🗑️ Delete</button>
406
+ </div>
407
+ `;
187
408
  }
188
- </script>
409
+
410
+ // Prepend urgent task to top of list
411
+ @appendChild('#task-list', { position: 'firstChild' })
412
+ addUrgentTask(title: string) {
413
+ return htmlFragment`
414
+ <div class="task-item urgent" style="background: #ffcdd2; padding: 12px; border: 2px solid #f44336;">
415
+ <strong>🚨 URGENT: ${title}</strong>
416
+ <button swc-on-click="$host.deleteTask()">Close</button>
417
+ </div>
418
+ `;
419
+ }
420
+
421
+ deleteTask(id?: number) {
422
+ console.log('Delete task:', id);
423
+ }
424
+
425
+ @onConnectedInnerHtml
426
+ render() {
427
+ return `
428
+ <div>
429
+ <div class="task-input">
430
+ <input type="text" id="new-task" placeholder="Enter task...">
431
+ <select id="priority">
432
+ <option value="low">Low</option>
433
+ <option value="medium" selected>Medium</option>
434
+ <option value="high">High</option>
435
+ </select>
436
+ <button swc-on-click="
437
+ const input = document.getElementById('new-task');
438
+ const priority = document.getElementById('priority').value;
439
+ if (priority === 'high') {
440
+ $host.addUrgentTask(input.value);
441
+ } else {
442
+ $host.addTask(input.value, priority);
443
+ }
444
+ input.value = '';
445
+ input.focus();
446
+ ">Add Task</button>
447
+ </div>
448
+ <div id="task-list"></div>
449
+ </div>
450
+ `;
451
+ }
452
+ }
189
453
  ```
190
454
 
191
- ### 2. DI-Powered Routing
455
+ #### Pattern 2: Notification Stack
456
+
192
457
  ```typescript
193
458
  @Sim
194
- @Router({
195
- path: '/users',
196
- route: { '/list': UserList, '/detail/:id': UserDetail }
197
- })
198
- @elementDefine('user-router')
199
- class UserRouter extends HTMLElement implements RouterAction.CanActivate {
200
- @onConnectedInnerHtml({ useShadow: true })
201
- render() {
202
- return `<header>User System</header><main><slot></slot></main>`;
459
+ @elementDefine('notification-stack')
460
+ class NotificationStack extends HTMLElement {
461
+ private notificationId = 0;
462
+
463
+ // Append notifications to stack (they auto-dismiss)
464
+ @appendChild('.notifications', { position: 'lastChild' })
465
+ notify(message: string, type: 'info' | 'success' | 'warning' | 'error' = 'info', duration = 5000) {
466
+ const id = ++this.notificationId;
467
+ const bgColor = { info: '#e3f2fd', success: '#e8f5e9', warning: '#fff3e0', error: '#ffebee' }[type];
468
+ const borderColor = { info: '#2196f3', success: '#4caf50', warning: '#ff9800', error: '#f44336' }[type];
469
+
470
+ // Auto-remove after duration
471
+ setTimeout(() => {
472
+ const el = document.querySelector(`[data-notify-id="${id}"]`);
473
+ if (el) el.remove();
474
+ }, duration);
475
+
476
+ return htmlFragment`
477
+ <div class="notification" data-notify-id="${id}"
478
+ style="background: ${bgColor}; border-left: 4px solid ${borderColor}; padding: 16px; margin: 8px 0; border-radius: 4px; display: flex; justify-content: space-between;">
479
+ <span>${message}</span>
480
+ <button swc-on-click="this.closest('[data-notify-id]').remove()"
481
+ style="background: none; border: none; cursor: pointer; font-size: 18px;">×</button>
482
+ </div>
483
+ `;
203
484
  }
204
485
 
205
- async canActivate(url: RoutingDataSet, data?: any) {
206
- if (data instanceof Node) this.replaceChildren(data);
486
+ @onConnectedInnerHtml
487
+ render() {
488
+ return `
489
+ <div class="notifications" style="position: fixed; top: 20px; right: 20px; width: 300px; z-index: 1000;"></div>
490
+ `;
207
491
  }
208
492
  }
209
493
 
494
+ // Usage
495
+ const notifier = document.querySelector('notification-stack');
496
+ notifier.notify('Operation successful!', 'success');
497
+ notifier.notify('Something went wrong', 'error');
498
+ ```
499
+
500
+ ---
501
+
502
+ ## 🛠 Template Utilities
503
+
504
+ SWC provides powerful utilities to create DOM nodes using **Tagged Template Literals**. These are perfect for use with surgical decorators like `@replaceChildren`, `@appendChild`, and `@replaceChildren`.
505
+
506
+ ### Complete Factory List
507
+
508
+ SWC provides element factories for **all common HTML tags**:
509
+
510
+ ```typescript
511
+ import {
512
+ htmlFragment, textNode,
513
+ htmlDivElement, htmlSpanElement, htmlButtonElement,
514
+ htmlInputElement, htmlFormElement,
515
+ htmlTableElement, htmlTrElement, htmlTdElement,
516
+ htmlUlElement, htmlLiElement,
517
+ htmlHeadingElement, htmlImageElement,
518
+ // ... 50+ more factories
519
+ } from '@dooboostore/simple-web-component';
520
+ ```
521
+
522
+ ### 1. `htmlFragment` - DOM Fragments
523
+
524
+ Returns a `DocumentFragment` from an HTML string. Perfect for multi-element insertion.
525
+
526
+ ```typescript
210
527
  @Sim
211
- class UserService {
212
- async getProfile(id: string) { return { id, name: 'Standard User' }; }
528
+ @elementDefine('fragment-demo')
529
+ class FragmentDemo extends HTMLElement {
530
+ @replaceChildren('#container')
531
+ renderMultipleElements() {
532
+ // All elements wrapped in one fragment for efficient insertion
533
+ return htmlFragment`
534
+ <h2>Title</h2>
535
+ <p>First paragraph</p>
536
+ <p>Second paragraph</p>
537
+ <ul>
538
+ <li>Item 1</li>
539
+ <li>Item 2</li>
540
+ </ul>
541
+ `;
542
+ }
543
+
544
+ @onConnectedInnerHtml
545
+ render() {
546
+ return `<div id="container"></div>`;
547
+ }
213
548
  }
549
+ ```
214
550
 
551
+ ### 2. `textNode` - Pure Text Nodes
552
+
553
+ Create raw text nodes (useful for escaping HTML or building text content).
554
+
555
+ ```typescript
215
556
  @Sim
216
- @elementDefine('user-list')
217
- class UserList extends HTMLElement {
218
- constructor(private router: Router, private userService: UserService) { super(); }
557
+ @elementDefine('text-renderer')
558
+ class TextRenderer extends HTMLElement {
559
+ @appendChild('.text-list', { position: 'lastChild' })
560
+ addPlainText(userInput: string) {
561
+ // Create pure text node - prevents XSS
562
+ return textNode`User wrote: ${userInput}`;
563
+ }
219
564
 
220
565
  @onConnectedInnerHtml
221
- render() {
566
+ render() {
222
567
  return `
223
- <ul><li>User A</li><li>User B</li></ul>
224
- <button swc-on-click="$host.router.go('/users/detail/1')">Go to Detail</button>
225
- `;
568
+ <input type="text" id="user-input" placeholder="Enter text...">
569
+ <button swc-on-click="
570
+ const input = document.getElementById('user-input');
571
+ $host.addPlainText(input.value);
572
+ input.value = '';
573
+ ">Add Text</button>
574
+ <div class="text-list"></div>
575
+ `;
226
576
  }
227
577
  }
578
+ ```
579
+
580
+ ### 3. Element Factories (`html***Element`)
581
+
582
+ Specific factories for common tags. Each returns a **typed element instance**.
228
583
 
584
+ ```typescript
229
585
  @Sim
230
- @elementDefine('user-detail')
231
- class UserDetail extends HTMLElement {
232
- constructor(private router: Router, private userService: UserService) { super(); }
586
+ @elementDefine('element-factory-demo')
587
+ class ElementFactoryDemo extends HTMLElement {
588
+ // htmlDivElement returns HTMLDivElement (typed)
589
+ @appendChild('#container')
590
+ addCard(title: string, description: string) {
591
+ return htmlDivElement`
592
+ <div class="card">
593
+ <h3>${title}</h3>
594
+ <p>${description}</p>
595
+ <button class="card-btn">Learn More</button>
596
+ </div>
597
+ `;
598
+ }
233
599
 
234
- @onConnected
235
- async init() {
236
- const id = this.router.getIntent()?.params?.id;
237
- const profile = await this.userService.getProfile(id);
238
- console.log('Viewing User:', profile.name);
600
+ // htmlTableElement for building tables
601
+ @replaceChildren('#table-container')
602
+ buildTable(data: Array<{ name: string; age: number; role: string }>) {
603
+ const headerRow = htmlTrElement`
604
+ <tr style="background: #f0f0f0; font-weight: bold;">
605
+ <td>Name</td>
606
+ <td>Age</td>
607
+ <td>Role</td>
608
+ </tr>
609
+ `;
610
+
611
+ const rows = data.map(item =>
612
+ htmlTrElement`
613
+ <tr>
614
+ <td>${item.name}</td>
615
+ <td>${item.age}</td>
616
+ <td>${item.role}</td>
617
+ </tr>
618
+ `
619
+ );
620
+
621
+ return htmlTableElement`
622
+ ${headerRow}
623
+ ${rows}
624
+ `;
625
+ }
626
+
627
+ // htmlUlElement for lists
628
+ @appendChild('.sidebar')
629
+ addMenuList(items: string[]) {
630
+ const listItems = items.map(item =>
631
+ htmlLiElement`<li><a href="#">${item}</a></li>`
632
+ );
633
+
634
+ return htmlUlElement`
635
+ <ul class="menu">
636
+ ${listItems}
637
+ </ul>
638
+ `;
239
639
  }
240
640
 
241
641
  @onConnectedInnerHtml
242
- render() { return `<div>User Detail View <button swc-on-click="$host.router.back()">Back</button></div>`; }
642
+ render() {
643
+ return `
644
+ <div id="container"></div>
645
+ <div id="table-container"></div>
646
+ <div class="sidebar"></div>
647
+ `;
648
+ }
243
649
  }
244
650
  ```
245
651
 
246
- ### 3. Lifecycle @Inject
247
- ```typescript
248
- import { Inject } from '@dooboostore/simple-boot/decorators/inject/Inject';
249
- import { InjectSituationType, onConnected, HostSet } from '@dooboostore/simple-web-component';
652
+ ---
250
653
 
251
- @elementDefine('profile-page')
252
- class ProfilePage extends HTMLElement {
253
- @onConnected
254
- async init(
255
- @Inject({ situationType: InjectSituationType.HOST_SET }) hostSet: HostSet,
256
- @Inject({ type: Router }) router: Router,
257
- @Inject({ type: UserService }) api: UserService
258
- ) {
259
- console.log('App scope:', hostSet.$appHost);
260
- const user = await api.getProfile();
261
- if (!user) router.go('/login');
654
+ ## ⚡ Quick Start
655
+
656
+ ```ts
657
+ import 'reflect-metadata';
658
+ import swcRegister, { elementDefine, onConnectedInnerHtml } from '@dooboostore/simple-web-component';
659
+
660
+ swcRegister(window);
661
+
662
+ @elementDefine('hello-swc')
663
+ class HelloSwc extends HTMLElement {
664
+ @onConnectedInnerHtml({ useShadow: true })
665
+ render() {
666
+ return `<style>:host{display:block;padding:12px;background:#111;color:#fefefe}</style><slot>Hello SWC</slot>`;
262
667
  }
263
668
  }
669
+
670
+ // <hello-swc> contents render automatically once the element is connected.
264
671
  ```
265
672
 
673
+ - Call `swcRegister(window)` once per window to register structural elements (`swc-if`, `swc-loop`, etc.) globally.
674
+ - Decorators rely on `reflect-metadata`, so make sure it is imported before defining elements.
675
+
266
676
  ---
267
677
 
268
- ## 🏰 Host Hierarchy & Context
269
- SWC automatically traverses the DOM to provide meaningful context to your scripts and listeners:
678
+ ## 🧪 Interactive Test Cases
679
+
680
+ Every decorator and directive ships with runnable playgrounds under [test/case/src](test/case/src). They double as living documentation.
270
681
 
271
- - **`$host`**: The current component Handling the event (**Self**).
272
- - **`$parentHost`**: The direct parent SWC component.
273
- - **`$appHost`**: The nearest parent `<swc-app>` (the SPA boundary).
274
- - **`$hosts`**: Array of all SWC ancestors `[Root, ..., Parent, Self]`.
682
+ 1. Install dependencies at the repo root: `pnpm install`.
683
+ 2. Start the playground server:
684
+ ```bash
685
+ cd packages/@dooboostore/simple-web-component/test/case
686
+ pnpm run dev
687
+ ```
688
+ 3. Open `http://localhost:3005` and pick a scenario from the menu.
689
+
690
+ | Scenario | Folder | Highlights |
691
+ | --- | --- | --- |
692
+ | Lifecycle hooks | `lifecycle/` | All pre/post connect, disconnect, adopt hooks with parent-child ordering. |
693
+ | Attribute flow | `attr/` and `attribute-test/` | DOM-first attribute sync, `@setAttribute`, `@changedAttribute`, `connectedInitialize` edge cases. |
694
+ | Events | `event/` and `event-attribute/` | Direct binding, delegation, special selectors, `swc-on-*`, custom event emission. |
695
+ | Queries | `query/` | `@query`, `@queryAll`, special selectors like `:appHost`, element injection safety. |
696
+ | Structural directives | `swc-loop/`, `swc-if/`, `swc-choose/`, `swc-async/` | Surgical list handling, portal rendering, async template states. |
697
+ | SPA & DI | `spa/` | Multiple `<swc-app>` instances, DI containers, nested routers. |
698
+ | Performance | `load-test/` | 1,000+ node stress tests showcasing zero MutationObserver overhead. |
699
+
700
+ Each folder contains an `index.ts` that demonstrates the decorator usage and an `index.html` you can load standalone if needed.
275
701
 
276
702
  ---
277
703
 
278
- ## 🛠 Lifecycle Hooks
279
- Executed in **Parent -> Child** order.
280
- - `@onBeforeConnected` / `@onAfterConnected` (alias: `@onConnected`)
281
- - `@onBeforeDisconnected` / `@onAfterDisconnected` (alias: `@onDisconnected`)
282
- - `@onBeforeAdopted` / `@onAfterAdopted` (alias: `@onAdopted`)
283
- - `@onAddEventListener`
704
+ ## 🧱 Project Layout
705
+
706
+ - [src/](src) holds the production TypeScript sources (decorators, structural elements, router, utilities).
707
+ - [test/case/src](test/case/src) aggregates example applications used in documentation and regression checks.
708
+ - [test/case/src/README.md](test/case/src/README.md) provides an overview of every scenario along with the architectural ideas they validate.
284
709
 
285
710
  ---
286
711
 
287
- ## 🔄 Structural Directives (Advanced)
712
+ ## 🛠 Developer Scripts
288
713
 
289
- SWC provides 4 core templates: `swc-loop`, `swc-if`, `swc-choose`, and `swc-async`.
714
+ Inside [package.json](package.json) you will find task shortcuts:
290
715
 
291
- ### Common Attributes:
292
- - **`on-get-value`**: Script to fetch data.
293
- - **`on-clone-nodes`**: Callback after a group of nodes is cloned.
294
- - **`on-clone-node`**: Callback for each individual node.
295
- - **`on-get-portal`**: Script that returns an `Element` or selector for portal rendering.
716
+ - `pnpm run build` – produce ESM, CJS, and bundle artifacts (`dist/`).
717
+ - `pnpm run watch` – rebuild all targets on file changes.
718
+ - `pnpm run build:esm` / `build:cjs` – individual module formats when you only care about one output.
719
+ - `pnpm run test:bundle` – launches the bundle regression playground (`@dooboostore/simple-web-component-bundle-test`).
720
+ - `pnpm run typecheck` – validate TypeScript types without emitting output.
296
721
 
297
- ### 1. `swc-if` (Conditional Rendering)
298
- ```html
299
- <template is="swc-if" on-get-value="isAdmin">
300
- <template is="swc-default"><p>Please login.</p></template>
301
- <div class="admin-panel">Welcome!</div>
302
- </template>
303
- ```
722
+ Publishing uses `publish:npm`, which runs a clean build, packs artifacts, and pushes them with the correct metadata.
304
723
 
305
- ### 2. `swc-loop` (High-Performance Iteration)
306
- ```html
307
- <template is="swc-loop" on-get-value="users"
308
- on-clone-node="if($isElement) $node.querySelector('.name').textContent = $item.name">
309
- <template is="swc-default"><p>No users found.</p></template>
310
- <div class="user-row"><span class="name"></span></div>
311
- </template>
724
+ ---
725
+
726
+ ## 🌐 Server-Side Rendering (SSR) & Hydration
727
+
728
+ SWC provides seamless SSR support with automatic tag-name preservation and client-side hydration strategies.
729
+
730
+ ### SSR Features
731
+ - **Tag Name Preservation**: Custom element tags (e.g., `<user-route>`, `<index-router>`) are preserved through the SSR virtual DOM layer.
732
+ - **Metadata-Based Registration**: The `CustomElementRegistry` stores tagname metadata during `define()`, allowing `HTMLElementBase` to auto-infer correct tag names during construction.
733
+ - **Virtual Window Support**: Pass a custom window object to `@elementDefine()` for SSR rendering environments.
734
+
735
+ ### Hydration Modes
736
+ When connecting a server-rendered app to the client, choose a connection strategy via the `connectMode` config:
737
+
738
+ ```typescript
739
+ const config = {
740
+ rootRouter: RootRouter,
741
+ routeType: 'element',
742
+ connectMode: 'swap' // or 'direct' (default)
743
+ };
744
+
745
+ app.connect(config);
312
746
  ```
313
747
 
314
- ### 3. `swc-choose` (Switch-Case Logic)
748
+ #### Mode Behaviors:
749
+ - **`'direct'`** (default): Directly connects the existing rendered DOM tree.
750
+ - **`'swap'`**: Creates a clone of the rendered app, connects it, and smoothly replaces the original DOM (Zero FOUC - Flash of Unstyled Content).
751
+
752
+ The swap mode is ideal for SSR workflows where you want to:
753
+ 1. Render components on the server with proper tag names
754
+ 2. Send minimal HTML to the client
755
+ 3. Clone and connect on the client side without visible DOM flashing
756
+
757
+ ---
758
+
759
+ ## 🌐 Revolutionary SPA Architecture
760
+
761
+ SWC introduces a **paradigm shift** in SPA design: **Each component scope is an independent, self-contained application** with its own DI container, router, and lifecycle. This enables true micro-frontend architectures without iframe overhead while maintaining perfect encapsulation.
762
+
763
+ ### Core Philosophy: Multi-App Composition
764
+ Unlike traditional SPAs that force a global router and monolithic state tree, SWC allows:
765
+ - **Nested Independent Apps**: Multiple `<swc-app>` instances on the same page, each with zero cross-contamination
766
+ - **Autonomous Routing**: Each app handles its own navigation, history, and component lifecycle independently
767
+ - **Decentralized DI**: Service dependencies are resolved within app scope, enabling natural code splitting and lazy loading
768
+ - **Island Architecture**: Apps boot only when needed, reducing initial JavaScript payload
769
+
770
+ ---
771
+
772
+ ### 1. Isolated App Scopes & Micro-Frontend Pattern
773
+
774
+ Create a self-contained universe with `<swc-app>`. The tag acts as a **boundary** where routing, DI, and state are completely isolated from sibling apps.
775
+
315
776
  ```html
316
- <template is="swc-choose" on-get-value="user.role">
317
- <template is="swc-default">Select a role.</template>
318
- <template is="swc-when" value="admin">Admin Dashboard</template>
319
- <template is="swc-otherwise">Access Denied</template>
320
- </template>
777
+ <!-- Example: Multi-tenant dashboard with independent feature modules -->
778
+ <div class="dashboard">
779
+ <!-- User Management Module -->
780
+ <swc-app swc-get-application-config="createUserModule()"></swc-app>
781
+
782
+ <!-- Reports Module -->
783
+ <swc-app swc-get-application-config="createReportsModule()"></swc-app>
784
+
785
+ <!-- Settings Module -->
786
+ <swc-app swc-get-application-config="createSettingsModule()"></swc-app>
787
+ </div>
788
+
789
+ <script>
790
+ // Each module is bootstrapped independently
791
+ window.createUserModule = (host) => ({
792
+ rootRouter: UserManagementRouter, // Entry point router
793
+ routeType: 'element', // 'element' (in-memory), 'hash', or 'path'
794
+ path: '/dashboard', // Initial route
795
+ window: window // Optional: SSR virtual window
796
+ });
797
+
798
+ window.createReportsModule = (host) => ({
799
+ rootRouter: ReportsRouter,
800
+ routeType: 'element',
801
+ path: '/overview',
802
+ window: window
803
+ });
804
+
805
+ // External programmatic navigation (from parent scope)
806
+ function switchUserModule(userId) {
807
+ const userApp = document.querySelectorAll('swc-app')[0];
808
+ userApp.routing(`/user/${userId}`); // Navigate within the isolated app
809
+ }
810
+
811
+ // Inter-app communication (if needed)
812
+ function notifyModules(eventName, data) {
813
+ document.querySelectorAll('swc-app').forEach(app => {
814
+ app.dispatchEvent(new CustomEvent(eventName, { detail: data }));
815
+ });
816
+ }
817
+ </script>
321
818
  ```
322
819
 
323
- ### 4. `swc-async` (Declarative Promises)
324
- ```html
325
- <template is="swc-async" on-get-value="fetchData()"
326
- on-clone-node="if($isElement && $node.className === 'content') $node.textContent = $value?.title || $error?.message">
327
- <template is="swc-loading">🌀 Loading...</template>
328
- <template is="swc-error"><div class="content"></div></template>
329
- <template is="swc-success"><div class="content"></div></template>
330
- </template>
820
+ **Key Insights:**
821
+ - Each `<swc-app>` is **completely isolated**: one app's router state doesn't affect another
822
+ - No global namespace pollution: services, routes, and components live within app scope
823
+ - Perfect for **dashboard layouts, plugin architectures, and federated frontends**
824
+
825
+ ---
826
+
827
+ ### 2. Advanced DI-Powered Routing with Lifecycle Hooks
828
+
829
+ SWC routing leverages **Dependency Injection** to inject services directly into components, enabling dynamic route guards, permission checks, and data preloading.
830
+
831
+ ```typescript
832
+ // ============================================
833
+ // 1. SERVICE LAYER (Shared by all routes)
834
+ // ============================================
835
+ @Sim
836
+ class AuthService {
837
+ private user: { id: string; role: 'admin' | 'user' } | null = null;
838
+
839
+ async login(credentials: { username: string; password: string }) {
840
+ // Simulate API call
841
+ this.user = { id: 'user123', role: 'admin' };
842
+ return this.user;
843
+ }
844
+
845
+ async logout() {
846
+ this.user = null;
847
+ }
848
+
849
+ getCurrentUser() {
850
+ return this.user;
851
+ }
852
+
853
+ hasRole(role: string) {
854
+ return this.user?.role === role;
855
+ }
856
+ }
857
+
858
+ @Sim
859
+ class UserService {
860
+ constructor(private auth: AuthService) {}
861
+
862
+ async getUsers() {
863
+ if (!this.auth.hasRole('admin')) {
864
+ throw new Error('Unauthorized');
865
+ }
866
+ return [
867
+ { id: '1', name: 'John Doe', email: 'john@example.com' },
868
+ { id: '2', name: 'Jane Smith', email: 'jane@example.com' }
869
+ ];
870
+ }
871
+
872
+ async getUserById(id: string) {
873
+ return { id, name: 'User ' + id, email: `user${id}@example.com` };
874
+ }
875
+ }
876
+
877
+ // ============================================
878
+ // 2. ROUTE COMPONENTS (Nested routing)
879
+ // ============================================
880
+ @Sim
881
+ @Router({
882
+ path: '/admin',
883
+ route: {
884
+ '/users': UserListPage,
885
+ '/users/:id': UserDetailPage,
886
+ '/settings': SettingsPage
887
+ }
888
+ })
889
+ @elementDefine('admin-router')
890
+ class AdminRouter extends HTMLElement implements RouterAction.CanActivate {
891
+ constructor(private auth: AuthService) { super(); }
892
+
893
+ @onConnectedInnerHtml({ useShadow: true })
894
+ render() {
895
+ return `
896
+ <style>
897
+ :host { display: flex; height: 100vh; }
898
+ .sidebar { width: 200px; background: #333; color: white; padding: 20px; }
899
+ .sidebar nav a { display: block; margin: 10px 0; color: #0066cc; cursor: pointer; }
900
+ .content { flex: 1; padding: 20px; }
901
+ </style>
902
+ <div class="sidebar">
903
+ <h3>Admin Panel</h3>
904
+ <nav>
905
+ <a swc-on-click="$host.router.go('/admin/users')">Users</a>
906
+ <a swc-on-click="$host.router.go('/admin/settings')">Settings</a>
907
+ </nav>
908
+ </div>
909
+ <div class="content">
910
+ <slot></slot>
911
+ </div>
912
+ `;
913
+ }
914
+
915
+ // Lifecycle hook: Called BEFORE route transition
916
+ // Used for permission checks, data preloading, etc.
917
+ async canActivate(url: RoutingDataSet, data?: any) {
918
+ // Only admin can enter this route
919
+ if (!this.auth.hasRole('admin')) {
920
+ console.warn('Access Denied: Admin role required');
921
+ return false;
922
+ }
923
+
924
+ // If data is a rendered component (Node), inject it into DOM
925
+ if (data instanceof Node) {
926
+ this.replaceChildren(data);
927
+ }
928
+
929
+ return true;
930
+ }
931
+ }
932
+
933
+ // ============================================
934
+ // 3. PAGE COMPONENTS (Leaf routes)
935
+ // ============================================
936
+ @Sim
937
+ @elementDefine('user-list-page')
938
+ class UserListPage extends HTMLElement {
939
+ private users: any[] = [];
940
+
941
+ constructor(
942
+ private userService: UserService,
943
+ private router: Router,
944
+ private auth: AuthService
945
+ ) {
946
+ super();
947
+ }
948
+
949
+ @onConnected
950
+ async loadUsers() {
951
+ try {
952
+ this.users = await this.userService.getUsers();
953
+ this.render();
954
+ } catch (error) {
955
+ console.error('Failed to load users:', error);
956
+ this.innerHTML = '<p style="color: red;">Failed to load users</p>';
957
+ }
958
+ }
959
+
960
+ @classList('active')
961
+ isActive = false;
962
+
963
+ @onConnectedInnerHtml
964
+ render() {
965
+ return `
966
+ <style>
967
+ .user-table { width: 100%; border-collapse: collapse; }
968
+ .user-table th, .user-table td { padding: 10px; text-align: left; border-bottom: 1px solid #ddd; }
969
+ .user-table tr:hover { background: #f5f5f5; }
970
+ </style>
971
+ <h2>Users</h2>
972
+ <table class="user-table">
973
+ <thead>
974
+ <tr><th>Name</th><th>Email</th><th>Actions</th></tr>
975
+ </thead>
976
+ <tbody>
977
+ ${this.users.map(u => `
978
+ <tr>
979
+ <td>${u.name}</td>
980
+ <td>${u.email}</td>
981
+ <td>
982
+ <button swc-on-click="$host.router.go('/admin/users/${u.id}')">View</button>
983
+ <button swc-on-click="$host.deleteUser('${u.id}')">Delete</button>
984
+ </td>
985
+ </tr>
986
+ `).join('')}
987
+ </tbody>
988
+ </table>
989
+ `;
990
+ }
991
+
992
+ deleteUser(id: string) {
993
+ if (confirm('Delete this user?')) {
994
+ this.users = this.users.filter(u => u.id !== id);
995
+ this.render();
996
+ }
997
+ }
998
+ }
999
+
1000
+ @Sim
1001
+ @elementDefine('user-detail-page')
1002
+ class UserDetailPage extends HTMLElement {
1003
+ private user: any = null;
1004
+
1005
+ constructor(
1006
+ private userService: UserService,
1007
+ private router: Router
1008
+ ) {
1009
+ super();
1010
+ }
1011
+
1012
+ @onConnected
1013
+ async loadUser() {
1014
+ // Extract route parameter (:id)
1015
+ const id = this.router.getIntent()?.params?.id;
1016
+ if (id) {
1017
+ this.user = await this.userService.getUserById(id);
1018
+ this.render();
1019
+ }
1020
+ }
1021
+
1022
+ @onConnectedInnerHtml
1023
+ render() {
1024
+ if (!this.user) return '<p>Loading...</p>';
1025
+
1026
+ return `
1027
+ <style>
1028
+ .detail { max-width: 600px; background: #f9f9f9; padding: 20px; border-radius: 8px; }
1029
+ .detail-row { margin: 10px 0; }
1030
+ .detail-label { font-weight: bold; color: #333; }
1031
+ </style>
1032
+ <h2>User Details</h2>
1033
+ <div class="detail">
1034
+ <div class="detail-row">
1035
+ <span class="detail-label">ID:</span> ${this.user.id}
1036
+ </div>
1037
+ <div class="detail-row">
1038
+ <span class="detail-label">Name:</span> ${this.user.name}
1039
+ </div>
1040
+ <div class="detail-row">
1041
+ <span class="detail-label">Email:</span> ${this.user.email}
1042
+ </div>
1043
+ </div>
1044
+ <button swc-on-click="$host.router.back()">Back</button>
1045
+ `;
1046
+ }
1047
+ }
1048
+
1049
+ // ============================================
1050
+ // 4. ROOT ROUTER (Entry point)
1051
+ // ============================================
1052
+ @Sim
1053
+ @Router({
1054
+ path: '/',
1055
+ route: {
1056
+ '/': HomePage,
1057
+ '/login': LoginPage,
1058
+ '/admin': AdminRouter
1059
+ }
1060
+ })
1061
+ @elementDefine('app-router')
1062
+ class RootRouter extends HTMLElement implements RouterAction.CanActivate {
1063
+ constructor(private auth: AuthService) { super(); }
1064
+
1065
+ @onConnectedInnerHtml({ useShadow: true })
1066
+ render() {
1067
+ const user = this.auth.getCurrentUser();
1068
+ return `
1069
+ <style>
1070
+ :host { display: block; font-family: Arial, sans-serif; }
1071
+ header { background: #222; color: white; padding: 15px; }
1072
+ header .user-info { float: right; font-size: 12px; }
1073
+ </style>
1074
+ <header>
1075
+ <h1>SWC App</h1>
1076
+ <div class="user-info">
1077
+ ${user ? `Logged in as: ${user.id} (${user.role})` : 'Not logged in'}
1078
+ </div>
1079
+ </header>
1080
+ <main><slot></slot></main>
1081
+ `;
1082
+ }
1083
+
1084
+ async canActivate(url: RoutingDataSet, data?: any) {
1085
+ if (data instanceof Node) {
1086
+ this.replaceChildren(data);
1087
+ }
1088
+ return true;
1089
+ }
1090
+ }
1091
+ ```
1092
+
1093
+ ---
1094
+
1095
+ ### 3. Route Lifecycle & Guard Patterns
1096
+
1097
+ **The `canActivate` lifecycle hook** is called **before** entering a route. Use it for:
1098
+ - **Permission Checks**: Verify user roles and access rights
1099
+ - **Data Preloading**: Fetch required data before rendering
1100
+ - **Route Interception**: Redirect to login or error pages
1101
+ - **Analytics**: Track user navigation
1102
+
1103
+ ```typescript
1104
+ @Router({ path: '/protected', route: { '/data': ProtectedDataPage } })
1105
+ @elementDefine('protected-router')
1106
+ class ProtectedRouter extends HTMLElement implements RouterAction.CanActivate {
1107
+ constructor(private auth: AuthService) { super(); }
1108
+
1109
+ async canActivate(url: RoutingDataSet, data?: any) {
1110
+ // Guard: Redirect if not authenticated
1111
+ if (!this.auth.getCurrentUser()) {
1112
+ console.log('Redirecting to login...');
1113
+ this.parentElement?.querySelector('app-router')?.routing('/login');
1114
+ return false;
1115
+ }
1116
+
1117
+ // Data injection: Component receives pre-fetched data
1118
+ if (data instanceof Node) {
1119
+ this.replaceChildren(data);
1120
+ }
1121
+
1122
+ return true;
1123
+ }
1124
+ }
1125
+ ```
1126
+
1127
+ ---
1128
+
1129
+ ### 4. Advanced Patterns: Nested Routers & State Management
1130
+
1131
+ ```typescript
1132
+ // Real-world: Multi-level nested routing with shared state
1133
+ @Sim
1134
+ class GridStateService {
1135
+ private sortBy = 'name';
1136
+ private filterRole = '';
1137
+
1138
+ setSortBy(field: string) { this.sortBy = field; }
1139
+ setFilterRole(role: string) { this.filterRole = role; }
1140
+ getSortBy() { return this.sortBy; }
1141
+ getFilterRole() { return this.filterRole; }
1142
+ }
1143
+
1144
+ @Sim
1145
+ @Router({
1146
+ path: '/crm',
1147
+ route: {
1148
+ '/contacts': ContactsRouter,
1149
+ '/accounts': AccountsRouter
1150
+ }
1151
+ })
1152
+ @elementDefine('crm-app')
1153
+ class CRMApp extends HTMLElement implements RouterAction.CanActivate {
1154
+ async canActivate(url: RoutingDataSet, data?: any) {
1155
+ if (data instanceof Node) this.replaceChildren(data);
1156
+ return true;
1157
+ }
1158
+
1159
+ @onConnectedInnerHtml
1160
+ render() {
1161
+ return `<div><slot></slot></div>`;
1162
+ }
1163
+ }
1164
+ ```
1165
+
1166
+ ---
1167
+
1168
+ ## ✉️ Declarative & Scoped Messaging System
1169
+
1170
+ SWC provides a **hierarchical messaging architecture** using native browser events with intelligent scoping. No external event bus or state manager needed—messages flow naturally through the DOM hierarchy.
1171
+
1172
+ ### Message Scope Hierarchy
1173
+
1174
+ Messages can target different scopes using **Special Selectors**:
1175
+
1176
+ | Selector | Scope | Use Case |
1177
+ |----------|-------|----------|
1178
+ | **`:appHost`** | Same `<swc-app>` instance | Module-to-module communication (confined) |
1179
+ | **`:parentHost`** | Direct parent SWC component | Parent-child coordination |
1180
+ | **`:window` / `:document`** | Entire page | Global broadcasts (Cross-app signals) |
1181
+ | **`:firstHost` / `:firstAppHost`** | Root of hierarchy | Communication with top-level container |
1182
+ | **`selector`** (CSS) | Direct query result | Point-to-point messaging |
1183
+
1184
+ ### Pattern 1: App-Scoped Communication
1185
+
1186
+ Communicate within a micro-app without affecting siblings.
1187
+
1188
+ ```typescript
1189
+ // ========== SENDER COMPONENT ==========
1190
+ @Sim
1191
+ @elementDefine('auth-panel')
1192
+ class AuthPanel extends HTMLElement {
1193
+ constructor(private auth: AuthService) { super(); }
1194
+
1195
+ @onConnectedInnerHtml
1196
+ render() {
1197
+ return `
1198
+ <div style="padding: 10px; background: #f0f0f0; border-radius: 4px;">
1199
+ <button swc-on-click="$host.onLogin()">Login</button>
1200
+ <button swc-on-click="$host.onLogout()">Logout</button>
1201
+ </div>
1202
+ `;
1203
+ }
1204
+
1205
+ // Emit event to the nearest parent <swc-app>
1206
+ @emitCustomEvent(':appHost', 'auth-changed')
1207
+ async onLogin() {
1208
+ await this.auth.login({ username: 'demo', password: 'demo' });
1209
+ return { user: this.auth.getCurrentUser(), timestamp: Date.now() };
1210
+ }
1211
+
1212
+ @emitCustomEvent(':appHost', 'auth-changed')
1213
+ async onLogout() {
1214
+ await this.auth.logout();
1215
+ return { user: null, timestamp: Date.now() };
1216
+ }
1217
+ }
1218
+
1219
+ // ========== RECEIVER COMPONENT (SAME APP) ==========
1220
+ @Sim
1221
+ @elementDefine('user-widget')
1222
+ class UserWidget extends HTMLElement {
1223
+ private user: any = null;
1224
+
1225
+ @onConnectedInnerHtml
1226
+ render() {
1227
+ return `
1228
+ <div style="padding: 10px; background: #e8f4f8; border-radius: 4px;">
1229
+ ${this.user ? `<p>Welcome, ${this.user.name}!</p>` : '<p>Not logged in</p>'}
1230
+ </div>
1231
+ `;
1232
+ }
1233
+
1234
+ // Listen for auth changes within the same app
1235
+ @addEventListener(':appHost', 'auth-changed')
1236
+ onAuthChanged(event: CustomEvent) {
1237
+ const { detail } = event;
1238
+ this.user = detail.user;
1239
+ this.render();
1240
+ console.log('Auth state changed at:', new Date(detail.timestamp).toLocaleTimeString());
1241
+ }
1242
+ }
1243
+
1244
+ // HTML
1245
+ <swc-app swc-get-application-config="dashboardConfig()">
1246
+ <auth-panel></auth-panel>
1247
+ <user-widget></user-widget> <!-- Reacts to auth-changed event -->
1248
+ </swc-app>
1249
+ ```
1250
+
1251
+ **Result**: When user clicks "Login" in `<auth-panel>`, `<user-widget>` is notified and updates automatically. No explicit imperative connection needed.
1252
+
1253
+ ---
1254
+
1255
+ ### Pattern 2: Cross-Module (Global) Broadcasting
1256
+
1257
+ Send a signal that reaches all apps on the page.
1258
+
1259
+ ```typescript
1260
+ // ========== SENDER (In Module A) ==========
1261
+ @Sim
1262
+ @elementDefine('notification-sender')
1263
+ class NotificationSender extends HTMLElement {
1264
+ @emitCustomEvent(':window', 'system-notification')
1265
+ announceSystemMaintenance() {
1266
+ return {
1267
+ title: 'System Maintenance',
1268
+ message: 'Server will be down for 2 hours',
1269
+ severity: 'warning',
1270
+ timestamp: new Date().toISOString()
1271
+ };
1272
+ }
1273
+
1274
+ @onConnectedInnerHtml
1275
+ render() {
1276
+ return `
1277
+ <button swc-on-click="$host.announceSystemMaintenance()">
1278
+ 📢 Broadcast Maintenance Alert
1279
+ </button>
1280
+ `;
1281
+ }
1282
+ }
1283
+
1284
+ // ========== RECEIVER (In Module B, Different App) ==========
1285
+ @Sim
1286
+ @elementDefine('notification-display')
1287
+ class NotificationDisplay extends HTMLElement {
1288
+ private notifications: any[] = [];
1289
+
1290
+ @addEventListener(':window', 'system-notification')
1291
+ onSystemNotification(event: CustomEvent) {
1292
+ this.notifications.push(event.detail);
1293
+ this.render();
1294
+ }
1295
+
1296
+ @onConnectedInnerHtml
1297
+ render() {
1298
+ return `
1299
+ <div style="position: fixed; top: 10px; right: 10px; font-size: 12px;">
1300
+ ${this.notifications.map(n => `
1301
+ <div style="background: ${n.severity === 'warning' ? '#fff3cd' : '#fff'};
1302
+ border: 1px solid #ffc107; padding: 10px; margin: 5px 0;
1303
+ border-radius: 4px; max-width: 300px;">
1304
+ <strong>${n.title}</strong><br>
1305
+ ${n.message}
1306
+ </div>
1307
+ `).join('')}
1308
+ </div>
1309
+ `;
1310
+ }
1311
+ }
1312
+
1313
+ <!-- Two independent apps receiving the same broadcast -->
1314
+ <swc-app swc-get-application-config="moduleAConfig()">
1315
+ <notification-sender></notification-sender>
1316
+ </swc-app>
1317
+
1318
+ <swc-app swc-get-application-config="moduleBConfig()">
1319
+ <notification-display></notification-display>
1320
+ </swc-app>
1321
+ ```
1322
+
1323
+ **Result**: Clicking the button in Module A instantly triggers the notification in Module B, even though they're in separate `<swc-app>` instances.
1324
+
1325
+ ---
1326
+
1327
+ ### Pattern 3: Hierarchical Parent-Child Messaging
1328
+
1329
+ Communicate up and down the component tree with `$parentHost` and `:hosts` selector.
1330
+
1331
+ ```typescript
1332
+ // ========== PARENT CONTAINER ==========
1333
+ @Sim
1334
+ @elementDefine('modal-container')
1335
+ class ModalContainer extends HTMLElement {
1336
+ private modals: any[] = [];
1337
+
1338
+ @onConnectedInnerHtml
1339
+ render() {
1340
+ return `
1341
+ <div style="position: relative;">
1342
+ <slot></slot>
1343
+ ${this.modals.map(m => `
1344
+ <div style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
1345
+ background: white; border: 2px solid #333; padding: 20px;
1346
+ border-radius: 8px; z-index: 1000;">
1347
+ ${m.content}
1348
+ <button swc-on-click="$host.closeModal()">Close</button>
1349
+ </div>
1350
+ `).join('')}
1351
+ </div>
1352
+ `;
1353
+ }
1354
+
1355
+ // Listen for child components requesting to open a modal
1356
+ @addEventListener(':hosts', 'request-modal')
1357
+ onModalRequest(event: CustomEvent) {
1358
+ this.modals.push({ id: Date.now(), content: event.detail.html });
1359
+ this.render();
1360
+ event.stopPropagation();
1361
+ }
1362
+
1363
+ closeModal() {
1364
+ this.modals.pop();
1365
+ this.render();
1366
+ }
1367
+ }
1368
+
1369
+ // ========== CHILD COMPONENT ==========
1370
+ @Sim
1371
+ @elementDefine('form-with-modal')
1372
+ class FormWithModal extends HTMLElement {
1373
+ @emitCustomEvent(':parentHost', 'request-modal')
1374
+ showHelpModal() {
1375
+ return {
1376
+ html: '<h3>Help</h3><p>Fill in all required fields and click Submit.</p>'
1377
+ };
1378
+ }
1379
+
1380
+ @onConnectedInnerHtml
1381
+ render() {
1382
+ return `
1383
+ <form>
1384
+ <input type="text" placeholder="Full Name" required>
1385
+ <button type="button" swc-on-click="$host.showHelpModal()">?</button>
1386
+ <button type="submit">Submit</button>
1387
+ </form>
1388
+ `;
1389
+ }
1390
+ }
1391
+
1392
+ <!-- Structure -->
1393
+ <modal-container>
1394
+ <form-with-modal></form-with-modal>
1395
+ </modal-container>
1396
+ ```
1397
+
1398
+ **Result**: Clicking "?" in the child form opens a modal managed by the parent container.
1399
+
1400
+ ---
1401
+
1402
+ ### Pattern 4: Event Detail Payloads
1403
+
1404
+ Send rich data structures through events.
1405
+
1406
+ ```typescript
1407
+ @Sim
1408
+ @elementDefine('data-grid')
1409
+ class DataGrid extends HTMLElement {
1410
+ private rows: any[] = [];
1411
+
1412
+ @onConnected
1413
+ loadData() {
1414
+ this.rows = [
1415
+ { id: 1, name: 'Alice', age: 28, department: 'Engineering' },
1416
+ { id: 2, name: 'Bob', age: 34, department: 'Sales' }
1417
+ ];
1418
+ this.render();
1419
+ }
1420
+
1421
+ // Emit complex payload when row is clicked
1422
+ @emitCustomEvent(':appHost', 'row-selected', false) // 3rd arg: whether to bubble
1423
+ selectRow(rowId: number) {
1424
+ const row = this.rows.find(r => r.id === rowId);
1425
+ return {
1426
+ rowId,
1427
+ rowData: row,
1428
+ timestamp: Date.now(),
1429
+ gridId: this.id,
1430
+ userAgent: navigator.userAgent
1431
+ };
1432
+ }
1433
+
1434
+ @onConnectedInnerHtml
1435
+ render() {
1436
+ return `
1437
+ <table>
1438
+ <tbody>
1439
+ ${this.rows.map(row => `
1440
+ <tr swc-on-click="$host.selectRow(${row.id})">
1441
+ <td>${row.name}</td>
1442
+ <td>${row.age}</td>
1443
+ <td>${row.department}</td>
1444
+ </tr>
1445
+ `).join('')}
1446
+ </tbody>
1447
+ </table>
1448
+ `;
1449
+ }
1450
+ }
1451
+
1452
+ // Listener receives all payload details
1453
+ @Sim
1454
+ @elementDefine('detail-panel')
1455
+ class DetailPanel extends HTMLElement {
1456
+ private selectedData: any = null;
1457
+
1458
+ @addEventListener(':appHost', 'row-selected')
1459
+ onRowSelect(event: CustomEvent) {
1460
+ const { rowData, timestamp } = event.detail;
1461
+ this.selectedData = rowData;
1462
+ console.log(`Selected at ${new Date(timestamp).toLocaleTimeString()}`);
1463
+ this.render();
1464
+ }
1465
+
1466
+ @onConnectedInnerHtml
1467
+ render() {
1468
+ if (!this.selectedData) return '<p>No selection</p>';
1469
+ return `
1470
+ <div>
1471
+ <h3>${this.selectedData.name}</h3>
1472
+ <p>Age: ${this.selectedData.age}</p>
1473
+ <p>Department: ${this.selectedData.department}</p>
1474
+ </div>
1475
+ `;
1476
+ }
1477
+ }
1478
+ ```
1479
+
1480
+ ---
1481
+
1482
+ ## 🏰 Host Hierarchy, Context Propagation & Template Events
1483
+
1484
+ SWC automatically traverses the component tree to provide meaningful **context** to scripts and event handlers. This eliminates the need for prop drilling and global state managers.
1485
+
1486
+ ### Context Variables (In Templates & Event Handlers)
1487
+
1488
+ When you use `swc-on-*` inline events or callback functions, these variables are automatically injected:
1489
+
1490
+ | Variable | Type | Description |
1491
+ |----------|------|-------------|
1492
+ | **`$host`** | `HTMLElement` | The component that owns the event handler (the element itself) |
1493
+ | **`$parentHost`** | `HTMLElement` | The direct parent SWC component |
1494
+ | **`$appHost`** | `SwcAppInterface` | The nearest parent `<swc-app>` boundary |
1495
+ | **`$hosts`** | `HTMLElement[]` | Array of ALL SWC ancestors: `[Root, Parent, ..., Self]` |
1496
+ | **`$el`** | `HTMLElement` | The actual DOM element that triggered the event |
1497
+ | **`$item`** | `any` | (In `swc-loop`) Current iteration item |
1498
+ | **`$index`** | `number` | (In `swc-loop`) Current iteration index |
1499
+
1500
+ ### Pattern 1: Declarative Inline Events (`swc-on-*`)
1501
+
1502
+ Bind events directly in HTML templates. The context is automatically available.
1503
+
1504
+ ```typescript
1505
+ @Sim
1506
+ @elementDefine('todo-item')
1507
+ class TodoItem extends HTMLElement {
1508
+ private title = '';
1509
+ private done = false;
1510
+
1511
+ constructor(private todoService: TodoService) { super(); }
1512
+
1513
+ @onConnectedInnerHtml
1514
+ render() {
1515
+ return `
1516
+ <style>
1517
+ .completed { text-decoration: line-through; color: #ccc; }
1518
+ button { margin-left: 10px; padding: 2px 8px; cursor: pointer; }
1519
+ </style>
1520
+ <li class="${this.done ? 'completed' : ''}">
1521
+ <!-- Access $host (self), $appHost (parent app), and $item -->
1522
+ <span>${this.title}</span>
1523
+
1524
+ <!-- Inline script with full context -->
1525
+ <button swc-on-click="
1526
+ $host.toggleDone();
1527
+ console.log('Current item:', $item);
1528
+ console.log('App instance:', $appHost);
1529
+ ">
1530
+ ${this.done ? '✓ Done' : '○ Pending'}
1531
+ </button>
1532
+
1533
+ <button swc-on-click="$host.deleteTodo($index)">
1534
+ 🗑️ Delete
1535
+ </button>
1536
+
1537
+ <!-- Access element coordinates -->
1538
+ <button swc-on-click="
1539
+ console.log('Clicked at:', $el.getBoundingClientRect());
1540
+ ">
1541
+ Info
1542
+ </button>
1543
+ </li>
1544
+ `;
1545
+ }
1546
+
1547
+ toggleDone() {
1548
+ this.done = !this.done;
1549
+ this.render();
1550
+ }
1551
+
1552
+ deleteTodo(index: number) {
1553
+ console.log('Deleting todo at index:', index);
1554
+ }
1555
+ }
1556
+ ```
1557
+
1558
+ ### Pattern 2: Loop Iteration Context
1559
+
1560
+ `swc-loop` provides special iteration variables you can access in inline events.
1561
+
1562
+ ```typescript
1563
+ @Sim
1564
+ @elementDefine('todo-list')
1565
+ class TodoList extends HTMLElement {
1566
+ private todos = [
1567
+ { id: 1, title: 'Learn SWC', done: false },
1568
+ { id: 2, title: 'Build an app', done: false }
1569
+ ];
1570
+
1571
+ @onConnectedInnerHtml
1572
+ render() {
1573
+ return `
1574
+ <ul>
1575
+ <template is="swc-loop" on-get-value="todos"
1576
+ on-clone-node="
1577
+ if ($isElement) {
1578
+ console.log('Cloning item:', $item, 'at index:', $index);
1579
+ $node.querySelector('.index').textContent = $index + 1;
1580
+ }
1581
+ ">
1582
+ <li class="todo-item">
1583
+ <span class="index">0</span>.
1584
+ <span class="title">${'${item.title}'}</span>
1585
+ <!-- Callback receives full context -->
1586
+ <button swc-on-click="
1587
+ $host.editTodo($item.id, $index, $el);
1588
+ console.log('Hosts hierarchy:', $hosts.map(h => h.tagName));
1589
+ ">
1590
+ Edit
1591
+ </button>
1592
+ </li>
1593
+ </template>
1594
+ </ul>
1595
+ `;
1596
+ }
1597
+
1598
+ editTodo(id: number, index: number, element: HTMLElement) {
1599
+ console.log(`Editing todo #${id} (index: ${index}):`, element);
1600
+ }
1601
+ }
1602
+ ```
1603
+
1604
+ ### Pattern 3: Accessing Ancestor Services via Context
1605
+
1606
+ Use `$appHost` to access services from the parent app's DI container.
1607
+
1608
+ ```typescript
1609
+ @Sim
1610
+ @elementDefine('child-component')
1611
+ class ChildComponent extends HTMLElement {
1612
+ @onConnectedInnerHtml
1613
+ render() {
1614
+ return `
1615
+ <div>
1616
+ <!-- Access parent app's router to navigate -->
1617
+ <button swc-on-click="$appHost.routing('/dashboard')">
1618
+ Go to Dashboard
1619
+ </button>
1620
+
1621
+ <!-- Access other components in the app -->
1622
+ <button swc-on-click="
1623
+ const sibling = document.querySelector('other-component');
1624
+ sibling.triggerUpdate();
1625
+ ">
1626
+ Notify Sibling
1627
+ </button>
1628
+
1629
+ <!-- Emit event up the tree to parent app -->
1630
+ <button swc-on-click="
1631
+ $appHost.dispatchEvent(new CustomEvent('child-ready', {
1632
+ detail: { child: $host, timestamp: Date.now() }
1633
+ }));
1634
+ ">
1635
+ Notify Parent App
1636
+ </button>
1637
+ </div>
1638
+ `;
1639
+ }
1640
+ }
1641
+ ```
1642
+
1643
+ ### Pattern 4: Host Hierarchy Traversal
1644
+
1645
+ Manually traverse the component tree to find ancestors or siblings.
1646
+
1647
+ ```typescript
1648
+ @Sim
1649
+ @elementDefine('deep-child')
1650
+ class DeepChild extends HTMLElement {
1651
+ findRootApp() {
1652
+ // Traverse up until you find <swc-app> or root
1653
+ let current = this.parentElement as any;
1654
+ while (current && current.tagName !== 'SWC-APP') {
1655
+ current = current.parentElement;
1656
+ }
1657
+ return current;
1658
+ }
1659
+
1660
+ getSiblingCount() {
1661
+ // Count siblings at same level
1662
+ return this.parentElement?.querySelectorAll(':scope > *').length || 0;
1663
+ }
1664
+
1665
+ @onConnectedInnerHtml
1666
+ render() {
1667
+ return `
1668
+ <div>
1669
+ <p>Root app: ${this.findRootApp()?.getAttribute('id')}</p>
1670
+ <p>Sibling count: ${this.getSiblingCount()}</p>
1671
+ </div>
1672
+ `;
1673
+ }
1674
+ }
1675
+ ```
1676
+
1677
+ ### Real-World Example: Multi-Level Navigation with Context
1678
+
1679
+ ```typescript
1680
+ // ============ ROOT ROUTER ============
1681
+ @Sim
1682
+ @Router({ path: '/', route: { '/dashboard': Dashboard, '/profile': Profile } })
1683
+ @elementDefine('app-root')
1684
+ class AppRoot extends HTMLElement {
1685
+ private breadcrumbs: string[] = [];
1686
+
1687
+ @onConnectedInnerHtml
1688
+ render() {
1689
+ return `
1690
+ <div>
1691
+ <header>
1692
+ <h1>My App</h1>
1693
+ <nav>
1694
+ <button swc-on-click="$host.router.go('/dashboard')">Dashboard</button>
1695
+ <button swc-on-click="$host.router.go('/profile')">Profile</button>
1696
+ </nav>
1697
+ <p>Breadcrumbs: ${this.breadcrumbs.join(' > ')}</p>
1698
+ </header>
1699
+ <main><slot></slot></main>
1700
+ </div>
1701
+ `;
1702
+ }
1703
+ }
1704
+
1705
+ // ============ CHILD ROUTE ============
1706
+ @Sim
1707
+ @elementDefine('dashboard-page')
1708
+ class DashboardPage extends HTMLElement {
1709
+ @onConnectedInnerHtml
1710
+ render() {
1711
+ return `
1712
+ <div>
1713
+ <h2>Dashboard</h2>
1714
+ <button swc-on-click="
1715
+ console.log('App router:', $appHost.routing);
1716
+ console.log('My tag:', $host.tagName);
1717
+ console.log('All ancestors:', $hosts.map(h => h.tagName).join(' -> '));
1718
+ ">
1719
+ Debug Context
1720
+ </button>
1721
+ </div>
1722
+ `;
1723
+ }
1724
+ }
1725
+ ```
1726
+
1727
+ ---
1728
+
1729
+ ## 🏰 Advanced Host Context: Query & Portal Patterns
1730
+
1731
+ ### Custom Query with Root Options
1732
+
1733
+ Combine `@query/@queryAll` with the `root` option from host methods to precision-target elements.
1734
+
1735
+ ```typescript
1736
+ @Sim
1737
+ @elementDefine('form-validator')
1738
+ class FormValidator extends HTMLElement {
1739
+ @query('form', { root: 'light' }) lightForm?: HTMLFormElement;
1740
+ @query('.hidden-form', { root: 'shadow' }) shadowForm?: HTMLFormElement;
1741
+ @queryAll('input', { root: 'all' }) allInputs?: HTMLInputElement[];
1742
+
1743
+ @onConnectedInnerHtml({ useShadow: true })
1744
+ render() {
1745
+ return `
1746
+ <form class="shadow-form">
1747
+ <input type="text" placeholder="Shadow DOM input">
1748
+ </form>
1749
+ <slot></slot>
1750
+ `;
1751
+ }
1752
+
1753
+ validateAllForms() {
1754
+ // Validate both light and shadow DOM forms
1755
+ const allInputs = Array.from(this.allInputs || []);
1756
+ return allInputs.every(input => input.value.trim() !== '');
1757
+ }
1758
+ }
1759
+ ```
1760
+
1761
+ ### Portal Pattern: Render Content Anywhere
1762
+
1763
+ Use `on-get-portal` to render content at a completely different location in the DOM.
1764
+
1765
+ ```typescript
1766
+ @Sim
1767
+ @elementDefine('tooltip-manager')
1768
+ class TooltipManager extends HTMLElement {
1769
+ private tooltips: any[] = [];
1770
+
1771
+ @onConnectedInnerHtml
1772
+ render() {
1773
+ return `
1774
+ <style>
1775
+ .tooltip { position: fixed; background: #222; color: white;
1776
+ padding: 8px 12px; border-radius: 4px; font-size: 12px; }
1777
+ </style>
1778
+ <template is="swc-loop" on-get-value="tooltips"
1779
+ on-get-portal="document.body">
1780
+ <div class="tooltip" style="left: ${'${item.x}px'}; top: ${'${item.y}px'}">
1781
+ ${'${item.text}'}
1782
+ </div>
1783
+ </template>
1784
+ `;
1785
+ }
1786
+
1787
+ addTooltip(text: string, x: number, y: number) {
1788
+ this.tooltips.push({ text, x, y });
1789
+ this.render();
1790
+ }
1791
+ }
1792
+
1793
+ // Usage: Tooltip renders outside component hierarchy
1794
+ const tooltipMgr = document.querySelector('tooltip-manager');
1795
+ tooltipMgr.addTooltip('Hover info', 100, 50);
1796
+ ```
1797
+
1798
+
1799
+
1800
+ ## 🔄 Structural Directives (Advanced)
1801
+
1802
+ SWC provides 4 core templates that empower your HTML without wrapper elements: `swc-loop`, `swc-if`, `swc-choose`, and `swc-async`. They all share a consistent, high-performance API with **zero wrapper elements** and **surgical DOM updates**.
1803
+
1804
+ ### Common Attributes:
1805
+ - **`on-get-value`**: Script to fetch data (evaluated in component context).
1806
+ - **`on-clone-node`**: Callback fired for **each individual node clone** (Args: `$node`, `$item`, `$index`, `$isElement`, etc.).
1807
+ - **`on-clone-nodes`**: Callback fired **once after all nodes cloned** (Args: `$nodes`, `$elements`, `$state`, etc.).
1808
+ - **`on-get-portal`**: Render nodes at a different DOM location using a selector.
1809
+ - **`on-state-changed`**: Track rendering state changes.
1810
+
1811
+ ### 1. `swc-if` - Binary Conditional Rendering
1812
+
1813
+ Show/hide content based on a boolean expression. No DOM wrapper.
1814
+
1815
+ ```typescript
1816
+ @Sim
1817
+ @elementDefine('access-control')
1818
+ class AccessControl extends HTMLElement {
1819
+ private user: any = null;
1820
+ private isLoading = false;
1821
+
1822
+ @onConnectedInnerHtml
1823
+ render() {
1824
+ return `
1825
+ <div class="access-panel">
1826
+ <!-- Show ONLY if loading (no wrapper) -->
1827
+ <template is="swc-if" on-get-value="isLoading">
1828
+ <div class="loading-spinner">
1829
+ <spinner-component></spinner-component>
1830
+ <p>Verifying access...</p>
1831
+ </div>
1832
+ </template>
1833
+
1834
+ <!-- Show ONLY if user is authenticated -->
1835
+ <template is="swc-if" on-get-value="user">
1836
+ <template is="swc-default">
1837
+ <p class="not-authorized">⛔ You are not authorized to view this content.</p>
1838
+ </template>
1839
+ <div class="admin-content">
1840
+ <h2>Welcome, \${user?.name}! 🎉</h2>
1841
+ <p>VIP Access Level: \${user?.role}</p>
1842
+ </div>
1843
+ </template>
1844
+ </div>
1845
+ `;
1846
+ }
1847
+ }
1848
+ ```
1849
+
1850
+ ### 2. `swc-loop` - High-Performance List Rendering
1851
+
1852
+ Iterate over arrays with **index-preserving stability** and zero virtual DOM overhead.
1853
+
1854
+ ```typescript
1855
+ @Sim
1856
+ @elementDefine('product-grid')
1857
+ class ProductGrid extends HTMLElement {
1858
+ private products = [
1859
+ { id: 1, name: 'Laptop', price: 999 },
1860
+ { id: 2, name: 'Mouse', price: 29 }
1861
+ ];
1862
+
1863
+ @onConnectedInnerHtml
1864
+ render() {
1865
+ return `
1866
+ <template is="swc-loop" on-get-value="products"
1867
+ on-clone-node="
1868
+ if ($isElement) {
1869
+ $node.querySelector('.price').textContent = '$' + $item.price;
1870
+ }
1871
+ ">
1872
+ <div class="product-card">
1873
+ <h3>\${item.name}</h3>
1874
+ <p class="price">$\${item.price}</p>
1875
+ </div>
1876
+ </template>
1877
+ `;
1878
+ }
1879
+ }
1880
+ ```
1881
+
1882
+ ### 3. `swc-choose` - Multi-Branch Conditional
1883
+
1884
+ Switch-like behavior for multiple conditions.
1885
+
1886
+ ```typescript
1887
+ @templateIsSim
1888
+ @elementDefine('order-status')
1889
+ class OrderStatus extends HTMLElement {
1890
+ private order = { status: 'shipped' };
1891
+
1892
+ @onConnectedInnerHtml
1893
+ render() {
1894
+ return `
1895
+ <template is="swc-choose" on-get-value="order.status">
1896
+ <template is="swc-when" on-get-value="'pending'">
1897
+ <p>⏳ Your order is being prepared...</p>
1898
+ </template>
1899
+ <template is="swc-when" on-get-value="'shipped'">
1900
+ <p>📦 Your order has shipped!</p>
1901
+ </template>
1902
+ <template is="swc-default">
1903
+ <p>❌ Order status unknown</p>
1904
+ </template>
1905
+ </template>
1906
+ `;
1907
+ }
1908
+ }
1909
+ ```
1910
+
1911
+ ### 4. `swc-async` - Async Content Loading
1912
+
1913
+ Automatically handle Promise rendering states.
1914
+
1915
+ ```typescript
1916
+ @Sim
1917
+ @elementDefine('async-data')
1918
+ class AsyncData extends HTMLElement {
1919
+ async fetchUserData(userId: string) {
1920
+ const response = await fetch(`/api/users/\${userId}`);
1921
+ return response.json();
1922
+ }
1923
+
1924
+ @onConnectedInnerHtml
1925
+ render() {
1926
+ return `
1927
+ <template is="swc-async" on-get-value="fetchUserData('user123')">
1928
+ <template is="swc-pending">
1929
+ <p>Loading...</p>
1930
+ </template>
1931
+ <template is="swc-fulfilled">
1932
+ <h2>\${data.name}</h2>
1933
+ <p>Email: \${data.email}</p>
1934
+ </template>
1935
+ <template is="swc-rejected">
1936
+ <p>❌ Error: \${error.message}</p>
1937
+ </template>
1938
+ </template>
1939
+ `;
1940
+ }
1941
+ }
1942
+ ```
1943
+
1944
+ ---
1945
+
1946
+ ## 🚀 Server-Side Rendering (SSR) Project Example
1947
+
1948
+ SWC integrates seamlessly with `@dooboostore/simple-boot-http-server-ssr` to provide **full-stack SSR** applications with automatic tag-name preservation, hydration, and isomorphic routing.
1949
+
1950
+ ### Project Structure
1951
+
1952
+ ```
1953
+ ssr-project/
1954
+ ├── back-end/ # Express/HTTP server with SSR
1955
+ │ └── index.ts # SSR entry point
1956
+ ├── front-end/ # Client-side app
1957
+ │ └── index.ts # Client bootstrap
1958
+ ├── src/
1959
+ │ ├── bootfactory.ts # Universal app configuration
1960
+ │ ├── components/ # Shared components
1961
+ │ └── pages/ # Route components (routers + pages)
1962
+ ```
1963
+
1964
+ ### 1. Backend SSR Setup
1965
+
1966
+ The backend renders components on the server and sends HTML to the client:
1967
+
1968
+ ```typescript
1969
+ // back-end/index.ts
1970
+ import { SimpleBootHttpSSRServer } from '@dooboostore/simple-boot-http-server-ssr';
1971
+ import { SSRSimpleWebComponentFilter } from '@dooboostore/simple-boot-http-server-ssr';
1972
+ import swcRegister from '@dooboostore/simple-web-component';
1973
+ import bootfactory from '@swc-src/bootfactory';
1974
+
1975
+ const swcFilter = new SSRSimpleWebComponentFilter({
1976
+ frontDistPath: path.resolve(__dirname, '../dist-front-end'),
1977
+ frontDistIndexFileName: 'index.html',
1978
+ registerComponents: async (window: any) => {
1979
+ // 1. Register core SWC elements (swc-if, swc-loop, etc.)
1980
+ swcRegister(window);
1981
+
1982
+ // 2. Register and bootstrap your app with routing
1983
+ const urlPath = window.location.pathname;
1984
+ bootfactory(window, urlPath);
1985
+
1986
+ console.log('✅ Components registered for SSR');
1987
+ }
1988
+ });
1989
+
1990
+ const server = new SimpleBootHttpSSRServer({
1991
+ listen: { port: 8080 },
1992
+ filters: [swcFilter]
1993
+ });
1994
+
1995
+ server.listen();
1996
+ console.log('🚀 SSR Server running on http://localhost:8080');
1997
+ ```
1998
+
1999
+ ### 2. Universal Bootfactory
2000
+
2001
+ The bootfactory runs on **both server and client** with different connection modes:
2002
+
2003
+ ```typescript
2004
+ // src/bootfactory.ts
2005
+ import register from '@dooboostore/simple-web-component';
2006
+ import { IndexRouter } from './pages/index.router';
2007
+
2008
+ export default (window: Window, initialPath?: string) => {
2009
+ // Register all components globally
2010
+ register(window, [...componentFactories, ...pageFactories]);
2011
+
2012
+ const app = window.document.querySelector('#app') as any;
2013
+
2014
+ const config = {
2015
+ rootRouter: IndexRouter.SYMBOL,
2016
+ routeType: 'path', // Use browser path: /users, /pages/about
2017
+ path: initialPath ?? '/',
2018
+ window: window
2019
+ };
2020
+
2021
+ // Detect client vs server environment
2022
+ const isClientWindow = typeof window !== 'undefined' && window === globalThis.window;
2023
+
2024
+ if (isClientWindow) {
2025
+ // CLIENT: Use 'swap' mode for zero FOUC hydration
2026
+ app.connect({
2027
+ ...config,
2028
+ connectMode: 'swap' // Clone → Connect → Replace original
2029
+ });
2030
+ } else {
2031
+ // SERVER: Use 'direct' mode (no swap needed)
2032
+ app.connect(config);
2033
+ }
2034
+
2035
+ return app;
2036
+ };
2037
+ ```
2038
+
2039
+ ### 3. Isomorphic Router & Pages
2040
+
2041
+ Define routers that work the same way on server and client:
2042
+
2043
+ ```typescript
2044
+ // src/pages/index.router.ts
2045
+ import { Sim } from '@dooboostore/simple-boot';
2046
+ import { Router } from '@dooboostore/simple-boot';
2047
+ import { elementDefine, onConnectedInnerHtml, setAttribute } from '@dooboostore/simple-web-component';
2048
+ import { RouterAction } from '@dooboostore/simple-boot';
2049
+
2050
+ @Sim
2051
+ @Router({
2052
+ path: '',
2053
+ route: {
2054
+ '/': HomePage.SYMBOL,
2055
+ '/user': UserPage.SYMBOL
2056
+ }
2057
+ })
2058
+ @elementDefine('index-router')
2059
+ class IndexRouter extends HTMLElement implements RouterAction.CanActivate {
2060
+ constructor(private router: Router) {
2061
+ super();
2062
+ }
2063
+
2064
+ // Lifecycle hook: Called BEFORE entering route
2065
+ async canActivate(url: RoutingDataSet, data?: any) {
2066
+ // Inject rendered page component
2067
+ if (data instanceof Node) {
2068
+ console.log(`✅ Rendering: \${data.nodeName}`);
2069
+ this.replaceChildren(data);
2070
+ }
2071
+ }
2072
+
2073
+ @onConnectedInnerHtml({ useShadow: true })
2074
+ render() {
2075
+ return `
2076
+ <style>
2077
+ :host { display: block; }
2078
+ header { background: #222; color: white; padding: 20px; }
2079
+ nav button { margin: 5px; padding: 10px 15px; cursor: pointer; }
2080
+ section { padding: 20px; }
2081
+ </style>
2082
+ <header>
2083
+ <h1>SWC + SSR App</h1>
2084
+ <nav>
2085
+ <button swc-on-click="$host.router.go('/')">🏠 Home</button>
2086
+ <button swc-on-click="$host.router.go('/user')">👤 Users</button>
2087
+ </nav>
2088
+ </header>
2089
+ <section><slot></slot></section>
2090
+ `;
2091
+ }
2092
+ }
2093
+ ```
2094
+
2095
+ ### 4. Page Components
2096
+
2097
+ ```typescript
2098
+ // src/pages/home.page.ts - Leaf route (no children)
2099
+ @Sim
2100
+ @elementDefine('home-page')
2101
+ class HomePage extends HTMLElement {
2102
+ @onConnectedInnerHtml
2103
+ render() {
2104
+ return `
2105
+ <h2>Welcome! 👋</h2>
2106
+ <p>This page was rendered on the server and hydrated on the client.</p>
2107
+ <template is="swc-loop" on-get-value="[1,2,3]">
2108
+ <div style="padding: 10px; background: #f5f5f5; margin: 5px;">
2109
+ Item \${item}
2110
+ </div>
2111
+ </template>
2112
+ `;
2113
+ }
2114
+ }
2115
+
2116
+ // src/pages/user.router.ts - Nested router with sub-routes
2117
+ @Sim
2118
+ @Router({
2119
+ path: '/user',
2120
+ route: {
2121
+ '': UserListPage.SYMBOL,
2122
+ '/:id': UserDetailPage.SYMBOL
2123
+ }
2124
+ })
2125
+ @elementDefine('user-router')
2126
+ class UserRouter extends HTMLElement implements RouterAction.CanActivate {
2127
+ async canActivate(url: RoutingDataSet, data?: any) {
2128
+ if (data instanceof Node) {
2129
+ this.replaceChildren(data);
2130
+ }
2131
+ }
2132
+
2133
+ @onConnectedInnerHtml({ useShadow: true })
2134
+ render() {
2135
+ return `
2136
+ <div style="margin-left: 20px;">
2137
+ <h2>User Management</h2>
2138
+ <slot></slot>
2139
+ </div>
2140
+ `;
2141
+ }
2142
+ }
2143
+ ```
2144
+
2145
+ ### 5. Client Entry Point
2146
+
2147
+ The client reuses the same bootfactory:
2148
+
2149
+ ```typescript
2150
+ // front-end/index.ts
2151
+ import bootfactory from '@swc-src/bootfactory';
2152
+ import { UrlUtils } from '@dooboostore/core/url';
2153
+
2154
+ console.log('🚀 Client-side app initializing...');
2155
+
2156
+ // Get current URL path from browser
2157
+ const currentPath = UrlUtils.getUrlPath(window.location);
2158
+
2159
+ // Bootstrap with swap mode (zero FOUC)
2160
+ bootfactory(window, currentPath);
2161
+
2162
+ console.log('✅ Client app hydrated');
2163
+ ```
2164
+
2165
+ ### 6. Flow Diagram
2166
+
2167
+ ```
2168
+ ┌─────────────────────────────────────────────────────────┐
2169
+ │ User Request │
2170
+ │ GET /user/123 │
2171
+ └──────────────────────┬──────────────────────────────────┘
2172
+ │
2173
+ ┌──────────────▼──────────────┐
2174
+ │ Backend SSR Renderer │
2175
+ ├─────────────────────────────┤
2176
+ │ 1. bootfactory(virtualWin) │
2177
+ │ 2. IndexRouter routes │
2178
+ │ 3. UserRouter renders │
2179
+ │ 4. UserDetailPage → HTML │
2180
+ └──────────────┬──────────────┘
2181
+ │
2182
+ ┌──────────────▼──────────────┐
2183
+ │ Sent to Client as HTML │
2184
+ │ <swc-app> │
2185
+ │ <index-router> │
2186
+ │ <user-router> │
2187
+ │ <user-detail-page> │
2188
+ │ </user-detail-page> │
2189
+ │ </user-router> │
2190
+ │ </index-router> │
2191
+ │ </swc-app> │
2192
+ └──────────────┬──────────────┘
2193
+ │
2194
+ ┌──────────────▼──────────────┐
2195
+ │ Client Hydration Swap │
2196
+ ├─────────────────────────────┤
2197
+ │ 1. Clone SSR HTML │
2198
+ │ 2. Connect listeners │
2199
+ │ 3. Replace original DOM │
2200
+ │ 4. Fully interactive │
2201
+ └─────────────────────────────┘
2202
+ ```
2203
+
2204
+ ### 7. Key Benefits
2205
+
2206
+ | Aspect | Benefit |
2207
+ |--------|---------|
2208
+ | **SEO** | Server renders initial HTML (searchable) |
2209
+ | **Performance** | Faster First Contentful Paint (FCP) |
2210
+ | **Tag Preservation** | Custom element tags survive SSR → client |
2211
+ | **Zero FOUC** | Swap mode clones & replaces seamlessly |
2212
+ | **Code Sharing** | Same router code on server & client |
2213
+ | **Island Architecture** | Multiple independent `<swc-app>` instances |
2214
+ | **Progressive Enhancement** | Works without JavaScript (graceful fallback) |
2215
+
2216
+ ### 8. Build & Run
2217
+
2218
+ ```bash
2219
+ # Build backend (Node.js server)
2220
+ cd back-end && npm run build
2221
+
2222
+ # Build frontend (browser bundle)
2223
+ cd front-end && npm run build
2224
+
2225
+ # Run SSR server on http://localhost:8080
2226
+ npm start
2227
+
2228
+ # Visit http://localhost:8080/user/123
2229
+ # Server renders UserDetailPage → Client hydrates with swap mode
331
2230
  ```
332
2231
 
333
2232
  ---
334
2233
 
335
- ## ⚡ Performance
336
- - **Zero "Deep Scan"**: Listeners are only bound to specific selectors.
2234
+ ## ⚡ Performance Features
2235
+ - **Zero "Deep Scan"**: Listeners and queries are only bound to specific selectors.
337
2236
  - **Surgical Updates**: Manipulate DOM directly in `@changedAttribute` instead of full re-renders.
2237
+ - **Zero Background Overhead**: No polling, no background observers.
338
2238
  - **Smart Delegation**: Host-level delegation with `__swc_handled` duplicate protection.
2239
+ - **Index-Preserving Removal**: `SwcLoop` maintains stable indices during item removal for maximum UI consistency.
339
2240
 
340
2241
  ---
341
2242