snice 5.2.3 → 6.0.0

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 (653) hide show
  1. package/README.md +5 -8
  2. package/adapters/react/SniceProvider.js +1 -1
  3. package/adapters/react/SniceRouter.js +1 -1
  4. package/adapters/react/audio-recorder.d.ts +0 -4
  5. package/adapters/react/audio-recorder.d.ts.map +1 -1
  6. package/adapters/react/audio-recorder.js +1 -1
  7. package/adapters/react/audio-recorder.js.map +1 -1
  8. package/adapters/react/audio-recorder.tsx +1 -5
  9. package/adapters/react/avatar.d.ts +0 -1
  10. package/adapters/react/avatar.d.ts.map +1 -1
  11. package/adapters/react/avatar.js +1 -1
  12. package/adapters/react/avatar.js.map +1 -1
  13. package/adapters/react/avatar.tsx +1 -2
  14. package/adapters/react/breadcrumbs.d.ts +0 -1
  15. package/adapters/react/breadcrumbs.d.ts.map +1 -1
  16. package/adapters/react/breadcrumbs.js +1 -1
  17. package/adapters/react/breadcrumbs.js.map +1 -1
  18. package/adapters/react/breadcrumbs.tsx +1 -2
  19. package/adapters/react/camera-annotate.d.ts +0 -5
  20. package/adapters/react/camera-annotate.d.ts.map +1 -1
  21. package/adapters/react/camera-annotate.js +1 -1
  22. package/adapters/react/camera-annotate.js.map +1 -1
  23. package/adapters/react/camera-annotate.tsx +1 -6
  24. package/adapters/react/card.d.ts +0 -2
  25. package/adapters/react/card.d.ts.map +1 -1
  26. package/adapters/react/card.js +1 -1
  27. package/adapters/react/card.js.map +1 -1
  28. package/adapters/react/card.tsx +1 -3
  29. package/adapters/react/carousel.d.ts +0 -1
  30. package/adapters/react/carousel.d.ts.map +1 -1
  31. package/adapters/react/carousel.js +1 -1
  32. package/adapters/react/carousel.js.map +1 -1
  33. package/adapters/react/carousel.tsx +1 -2
  34. package/adapters/react/cart.d.ts +0 -1
  35. package/adapters/react/cart.d.ts.map +1 -1
  36. package/adapters/react/cart.js +1 -1
  37. package/adapters/react/cart.js.map +1 -1
  38. package/adapters/react/cart.tsx +1 -2
  39. package/adapters/react/chart.d.ts +0 -5
  40. package/adapters/react/chart.d.ts.map +1 -1
  41. package/adapters/react/chart.js +1 -1
  42. package/adapters/react/chart.js.map +1 -1
  43. package/adapters/react/chart.tsx +1 -6
  44. package/adapters/react/chat.d.ts +4 -1
  45. package/adapters/react/chat.d.ts.map +1 -1
  46. package/adapters/react/chat.js +2 -2
  47. package/adapters/react/chat.js.map +1 -1
  48. package/adapters/react/chat.tsx +6 -3
  49. package/adapters/react/chip.d.ts +0 -1
  50. package/adapters/react/chip.d.ts.map +1 -1
  51. package/adapters/react/chip.js +1 -1
  52. package/adapters/react/chip.js.map +1 -1
  53. package/adapters/react/chip.tsx +1 -2
  54. package/adapters/react/command-palette.d.ts +0 -4
  55. package/adapters/react/command-palette.d.ts.map +1 -1
  56. package/adapters/react/command-palette.js +1 -1
  57. package/adapters/react/command-palette.js.map +1 -1
  58. package/adapters/react/command-palette.tsx +1 -5
  59. package/adapters/react/comments.d.ts +0 -1
  60. package/adapters/react/comments.d.ts.map +1 -1
  61. package/adapters/react/comments.js +1 -1
  62. package/adapters/react/comments.js.map +1 -1
  63. package/adapters/react/comments.tsx +1 -2
  64. package/adapters/react/countdown.d.ts +0 -4
  65. package/adapters/react/countdown.d.ts.map +1 -1
  66. package/adapters/react/countdown.js +1 -1
  67. package/adapters/react/countdown.js.map +1 -1
  68. package/adapters/react/countdown.tsx +1 -5
  69. package/adapters/react/date-time-picker.d.ts +0 -1
  70. package/adapters/react/date-time-picker.d.ts.map +1 -1
  71. package/adapters/react/date-time-picker.js +1 -1
  72. package/adapters/react/date-time-picker.js.map +1 -1
  73. package/adapters/react/date-time-picker.tsx +1 -2
  74. package/adapters/react/file-upload.d.ts +0 -2
  75. package/adapters/react/file-upload.d.ts.map +1 -1
  76. package/adapters/react/file-upload.js +1 -1
  77. package/adapters/react/file-upload.js.map +1 -1
  78. package/adapters/react/file-upload.tsx +1 -3
  79. package/adapters/react/heatmap.d.ts +0 -4
  80. package/adapters/react/heatmap.d.ts.map +1 -1
  81. package/adapters/react/heatmap.js +1 -1
  82. package/adapters/react/heatmap.js.map +1 -1
  83. package/adapters/react/heatmap.tsx +1 -5
  84. package/adapters/react/image.d.ts +0 -2
  85. package/adapters/react/image.d.ts.map +1 -1
  86. package/adapters/react/image.js +1 -1
  87. package/adapters/react/image.js.map +1 -1
  88. package/adapters/react/image.tsx +1 -3
  89. package/adapters/react/kanban.d.ts +0 -4
  90. package/adapters/react/kanban.d.ts.map +1 -1
  91. package/adapters/react/kanban.js +1 -1
  92. package/adapters/react/kanban.js.map +1 -1
  93. package/adapters/react/kanban.tsx +1 -5
  94. package/adapters/react/key-value.d.ts +0 -2
  95. package/adapters/react/key-value.d.ts.map +1 -1
  96. package/adapters/react/key-value.js +1 -1
  97. package/adapters/react/key-value.js.map +1 -1
  98. package/adapters/react/key-value.tsx +1 -3
  99. package/adapters/react/leaderboard.d.ts +0 -1
  100. package/adapters/react/leaderboard.d.ts.map +1 -1
  101. package/adapters/react/leaderboard.js +1 -1
  102. package/adapters/react/leaderboard.js.map +1 -1
  103. package/adapters/react/leaderboard.tsx +1 -2
  104. package/adapters/react/map.d.ts +0 -3
  105. package/adapters/react/map.d.ts.map +1 -1
  106. package/adapters/react/map.js +1 -1
  107. package/adapters/react/map.js.map +1 -1
  108. package/adapters/react/map.tsx +1 -4
  109. package/adapters/react/markdown.d.ts +1 -1
  110. package/adapters/react/markdown.d.ts.map +1 -1
  111. package/adapters/react/markdown.js +1 -1
  112. package/adapters/react/markdown.js.map +1 -1
  113. package/adapters/react/markdown.tsx +2 -2
  114. package/adapters/react/matchRoute.d.ts +1 -1
  115. package/adapters/react/matchRoute.js +38 -4
  116. package/adapters/react/matchRoute.js.map +1 -1
  117. package/adapters/react/message-strip.d.ts +1 -1
  118. package/adapters/react/message-strip.js +1 -1
  119. package/adapters/react/message-strip.tsx +2 -2
  120. package/adapters/react/music-player.d.ts +0 -1
  121. package/adapters/react/music-player.d.ts.map +1 -1
  122. package/adapters/react/music-player.js +1 -1
  123. package/adapters/react/music-player.js.map +1 -1
  124. package/adapters/react/music-player.tsx +1 -2
  125. package/adapters/react/org-chart.d.ts +0 -1
  126. package/adapters/react/org-chart.d.ts.map +1 -1
  127. package/adapters/react/org-chart.js +1 -1
  128. package/adapters/react/org-chart.js.map +1 -1
  129. package/adapters/react/org-chart.tsx +1 -2
  130. package/adapters/react/paint.d.ts +0 -1
  131. package/adapters/react/paint.d.ts.map +1 -1
  132. package/adapters/react/paint.js +1 -1
  133. package/adapters/react/paint.js.map +1 -1
  134. package/adapters/react/paint.tsx +1 -2
  135. package/adapters/react/podcast-player.d.ts +0 -2
  136. package/adapters/react/podcast-player.d.ts.map +1 -1
  137. package/adapters/react/podcast-player.js +1 -1
  138. package/adapters/react/podcast-player.js.map +1 -1
  139. package/adapters/react/podcast-player.tsx +1 -3
  140. package/adapters/react/product-card.d.ts +0 -3
  141. package/adapters/react/product-card.d.ts.map +1 -1
  142. package/adapters/react/product-card.js +1 -1
  143. package/adapters/react/product-card.js.map +1 -1
  144. package/adapters/react/product-card.tsx +1 -4
  145. package/adapters/react/qr-reader.d.ts +0 -4
  146. package/adapters/react/qr-reader.d.ts.map +1 -1
  147. package/adapters/react/qr-reader.js +1 -1
  148. package/adapters/react/qr-reader.js.map +1 -1
  149. package/adapters/react/qr-reader.tsx +1 -5
  150. package/adapters/react/recipe.d.ts +0 -5
  151. package/adapters/react/recipe.d.ts.map +1 -1
  152. package/adapters/react/recipe.js +1 -1
  153. package/adapters/react/recipe.js.map +1 -1
  154. package/adapters/react/recipe.tsx +1 -6
  155. package/adapters/react/route-specificity.d.ts +1 -0
  156. package/adapters/react/spotlight.d.ts +0 -2
  157. package/adapters/react/spotlight.d.ts.map +1 -1
  158. package/adapters/react/spotlight.js +1 -1
  159. package/adapters/react/spotlight.js.map +1 -1
  160. package/adapters/react/spotlight.tsx +1 -3
  161. package/adapters/react/tag-input.d.ts +0 -4
  162. package/adapters/react/tag-input.d.ts.map +1 -1
  163. package/adapters/react/tag-input.js +1 -1
  164. package/adapters/react/tag-input.js.map +1 -1
  165. package/adapters/react/tag-input.tsx +1 -5
  166. package/adapters/react/terminal.d.ts +0 -1
  167. package/adapters/react/terminal.d.ts.map +1 -1
  168. package/adapters/react/terminal.js +1 -1
  169. package/adapters/react/terminal.js.map +1 -1
  170. package/adapters/react/terminal.tsx +1 -2
  171. package/adapters/react/time-picker.d.ts +0 -1
  172. package/adapters/react/time-picker.d.ts.map +1 -1
  173. package/adapters/react/time-picker.js +1 -1
  174. package/adapters/react/time-picker.js.map +1 -1
  175. package/adapters/react/time-picker.tsx +1 -2
  176. package/adapters/react/timer.d.ts +0 -1
  177. package/adapters/react/timer.d.ts.map +1 -1
  178. package/adapters/react/timer.js +1 -1
  179. package/adapters/react/timer.js.map +1 -1
  180. package/adapters/react/timer.tsx +1 -2
  181. package/adapters/react/useRequestHandler.js +1 -1
  182. package/adapters/react/video-player.d.ts +0 -6
  183. package/adapters/react/video-player.d.ts.map +1 -1
  184. package/adapters/react/video-player.js +1 -1
  185. package/adapters/react/video-player.js.map +1 -1
  186. package/adapters/react/video-player.tsx +1 -7
  187. package/adapters/react/virtual-scroller.d.ts +0 -1
  188. package/adapters/react/virtual-scroller.d.ts.map +1 -1
  189. package/adapters/react/virtual-scroller.js +1 -1
  190. package/adapters/react/virtual-scroller.js.map +1 -1
  191. package/adapters/react/virtual-scroller.tsx +1 -2
  192. package/bin/templates/default/tests/services/jwt.test.ts +8 -1
  193. package/bin/templates/react/tests/services/jwt.test.ts +10 -3
  194. package/dist/cdn/accordion/snice-accordion.js +1 -1
  195. package/dist/cdn/accordion/snice-accordion.min.js +1 -1
  196. package/dist/cdn/action-bar/README.md +2 -2
  197. package/dist/cdn/action-bar/snice-action-bar.js +2 -2
  198. package/dist/cdn/action-bar/snice-action-bar.js.map +1 -1
  199. package/dist/cdn/action-bar/snice-action-bar.min.js +2 -2
  200. package/dist/cdn/action-bar/snice-action-bar.min.js.map +1 -1
  201. package/dist/cdn/activity-feed/snice-activity-feed.js +1 -1
  202. package/dist/cdn/activity-feed/snice-activity-feed.min.js +1 -1
  203. package/dist/cdn/alert/snice-alert.js +1 -1
  204. package/dist/cdn/alert/snice-alert.js.map +1 -1
  205. package/dist/cdn/alert/snice-alert.min.js +1 -1
  206. package/dist/cdn/alert/snice-alert.min.js.map +1 -1
  207. package/dist/cdn/app-tiles/snice-app-tiles.js +1 -1
  208. package/dist/cdn/app-tiles/snice-app-tiles.min.js +1 -1
  209. package/dist/cdn/approval-flow/snice-approval-flow.js +1 -1
  210. package/dist/cdn/approval-flow/snice-approval-flow.js.map +1 -1
  211. package/dist/cdn/approval-flow/snice-approval-flow.min.js +1 -1
  212. package/dist/cdn/approval-flow/snice-approval-flow.min.js.map +1 -1
  213. package/dist/cdn/audio-recorder/snice-audio-recorder.js +1 -1
  214. package/dist/cdn/audio-recorder/snice-audio-recorder.min.js +1 -1
  215. package/dist/cdn/availability/snice-availability.js +1 -1
  216. package/dist/cdn/availability/snice-availability.min.js +1 -1
  217. package/dist/cdn/avatar/snice-avatar.js +1 -1
  218. package/dist/cdn/avatar/snice-avatar.min.js +1 -1
  219. package/dist/cdn/avatar-group/snice-avatar-group.js +1 -1
  220. package/dist/cdn/avatar-group/snice-avatar-group.min.js +1 -1
  221. package/dist/cdn/badge/snice-badge.js +1 -1
  222. package/dist/cdn/badge/snice-badge.js.map +1 -1
  223. package/dist/cdn/badge/snice-badge.min.js +1 -1
  224. package/dist/cdn/badge/snice-badge.min.js.map +1 -1
  225. package/dist/cdn/banner/README.md +1 -1
  226. package/dist/cdn/banner/snice-banner.js +2 -2
  227. package/dist/cdn/banner/snice-banner.js.map +1 -1
  228. package/dist/cdn/banner/snice-banner.min.js +2 -2
  229. package/dist/cdn/banner/snice-banner.min.js.map +1 -1
  230. package/dist/cdn/binpack/snice-binpack.js +1 -1
  231. package/dist/cdn/binpack/snice-binpack.min.js +1 -1
  232. package/dist/cdn/book/snice-book.js +1 -1
  233. package/dist/cdn/book/snice-book.min.js +1 -1
  234. package/dist/cdn/booking/snice-booking.js +1 -1
  235. package/dist/cdn/booking/snice-booking.min.js +1 -1
  236. package/dist/cdn/breadcrumbs/snice-breadcrumbs.js +1 -1
  237. package/dist/cdn/breadcrumbs/snice-breadcrumbs.js.map +1 -1
  238. package/dist/cdn/breadcrumbs/snice-breadcrumbs.min.js +1 -1
  239. package/dist/cdn/breadcrumbs/snice-breadcrumbs.min.js.map +1 -1
  240. package/dist/cdn/button/snice-button.js +1 -1
  241. package/dist/cdn/button/snice-button.js.map +1 -1
  242. package/dist/cdn/button/snice-button.min.js +1 -1
  243. package/dist/cdn/button/snice-button.min.js.map +1 -1
  244. package/dist/cdn/calendar/snice-calendar.js +1 -1
  245. package/dist/cdn/calendar/snice-calendar.min.js +1 -1
  246. package/dist/cdn/camera/snice-camera.js +1 -1
  247. package/dist/cdn/camera/snice-camera.min.js +1 -1
  248. package/dist/cdn/camera-annotate/snice-camera-annotate.js +1 -1
  249. package/dist/cdn/camera-annotate/snice-camera-annotate.min.js +1 -1
  250. package/dist/cdn/candlestick/snice-candlestick.js +1 -1
  251. package/dist/cdn/candlestick/snice-candlestick.min.js +1 -1
  252. package/dist/cdn/card/snice-card.js +1 -1
  253. package/dist/cdn/card/snice-card.min.js +1 -1
  254. package/dist/cdn/carousel/snice-carousel.js +1 -1
  255. package/dist/cdn/carousel/snice-carousel.min.js +1 -1
  256. package/dist/cdn/cart/snice-cart.js +1 -1
  257. package/dist/cdn/cart/snice-cart.min.js +1 -1
  258. package/dist/cdn/chart/snice-chart.js +1 -1
  259. package/dist/cdn/chart/snice-chart.js.map +1 -1
  260. package/dist/cdn/chart/snice-chart.min.js +1 -1
  261. package/dist/cdn/chart/snice-chart.min.js.map +1 -1
  262. package/dist/cdn/chat/README.md +2 -2
  263. package/dist/cdn/chat/snice-chat.js +785 -89
  264. package/dist/cdn/chat/snice-chat.js.map +1 -1
  265. package/dist/cdn/chat/snice-chat.min.js +71 -75
  266. package/dist/cdn/chat/snice-chat.min.js.map +1 -1
  267. package/dist/cdn/checkbox/snice-checkbox.js +1 -1
  268. package/dist/cdn/checkbox/snice-checkbox.min.js +1 -1
  269. package/dist/cdn/chip/snice-chip.js +1 -1
  270. package/dist/cdn/chip/snice-chip.js.map +1 -1
  271. package/dist/cdn/chip/snice-chip.min.js +1 -1
  272. package/dist/cdn/chip/snice-chip.min.js.map +1 -1
  273. package/dist/cdn/code-block/snice-code-block.js +1 -1
  274. package/dist/cdn/code-block/snice-code-block.min.js +1 -1
  275. package/dist/cdn/color-display/snice-color-display.js +1 -1
  276. package/dist/cdn/color-display/snice-color-display.min.js +1 -1
  277. package/dist/cdn/color-picker/snice-color-picker.js +1 -1
  278. package/dist/cdn/color-picker/snice-color-picker.min.js +1 -1
  279. package/dist/cdn/command-palette/README.md +1 -1
  280. package/dist/cdn/command-palette/snice-command-palette.js +2 -2
  281. package/dist/cdn/command-palette/snice-command-palette.js.map +1 -1
  282. package/dist/cdn/command-palette/snice-command-palette.min.js +2 -2
  283. package/dist/cdn/command-palette/snice-command-palette.min.js.map +1 -1
  284. package/dist/cdn/comments/snice-comments.js +1 -1
  285. package/dist/cdn/comments/snice-comments.min.js +1 -1
  286. package/dist/cdn/countdown/snice-countdown.js +1 -1
  287. package/dist/cdn/countdown/snice-countdown.min.js +1 -1
  288. package/dist/cdn/cropper/snice-cropper.js +1 -1
  289. package/dist/cdn/cropper/snice-cropper.min.js +1 -1
  290. package/dist/cdn/data-card/snice-data-card.js +1 -1
  291. package/dist/cdn/data-card/snice-data-card.js.map +1 -1
  292. package/dist/cdn/data-card/snice-data-card.min.js +1 -1
  293. package/dist/cdn/data-card/snice-data-card.min.js.map +1 -1
  294. package/dist/cdn/date-picker/snice-date-picker.js +1 -1
  295. package/dist/cdn/date-picker/snice-date-picker.min.js +1 -1
  296. package/dist/cdn/date-range-picker/snice-date-range-picker.js +1 -1
  297. package/dist/cdn/date-range-picker/snice-date-range-picker.min.js +1 -1
  298. package/dist/cdn/date-time-picker/snice-date-time-picker.js +1 -1
  299. package/dist/cdn/date-time-picker/snice-date-time-picker.min.js +1 -1
  300. package/dist/cdn/diff/snice-diff.js +1 -1
  301. package/dist/cdn/diff/snice-diff.min.js +1 -1
  302. package/dist/cdn/divider/snice-divider.js +1 -1
  303. package/dist/cdn/divider/snice-divider.min.js +1 -1
  304. package/dist/cdn/doc/snice-doc.js +1 -1
  305. package/dist/cdn/doc/snice-doc.min.js +1 -1
  306. package/dist/cdn/draw/snice-draw.js +1 -1
  307. package/dist/cdn/draw/snice-draw.min.js +1 -1
  308. package/dist/cdn/drawer/snice-drawer.js +1 -1
  309. package/dist/cdn/drawer/snice-drawer.js.map +1 -1
  310. package/dist/cdn/drawer/snice-drawer.min.js +1 -1
  311. package/dist/cdn/drawer/snice-drawer.min.js.map +1 -1
  312. package/dist/cdn/empty-state/snice-empty-state.js +1 -1
  313. package/dist/cdn/empty-state/snice-empty-state.js.map +1 -1
  314. package/dist/cdn/empty-state/snice-empty-state.min.js +1 -1
  315. package/dist/cdn/empty-state/snice-empty-state.min.js.map +1 -1
  316. package/dist/cdn/estimate/snice-estimate.js +1 -1
  317. package/dist/cdn/estimate/snice-estimate.min.js +1 -1
  318. package/dist/cdn/file-gallery/snice-file-gallery.js +1 -1
  319. package/dist/cdn/file-gallery/snice-file-gallery.min.js +1 -1
  320. package/dist/cdn/file-upload/snice-file-upload.js +1 -1
  321. package/dist/cdn/file-upload/snice-file-upload.min.js +1 -1
  322. package/dist/cdn/flip-card/snice-flip-card.js +1 -1
  323. package/dist/cdn/flip-card/snice-flip-card.min.js +1 -1
  324. package/dist/cdn/flow/snice-flow.js +1 -1
  325. package/dist/cdn/flow/snice-flow.min.js +1 -1
  326. package/dist/cdn/form-layout/snice-form-layout.js +1 -1
  327. package/dist/cdn/form-layout/snice-form-layout.min.js +1 -1
  328. package/dist/cdn/funnel/snice-funnel.js +1 -1
  329. package/dist/cdn/funnel/snice-funnel.js.map +1 -1
  330. package/dist/cdn/funnel/snice-funnel.min.js +1 -1
  331. package/dist/cdn/funnel/snice-funnel.min.js.map +1 -1
  332. package/dist/cdn/gantt/snice-gantt.js +1 -1
  333. package/dist/cdn/gantt/snice-gantt.min.js +1 -1
  334. package/dist/cdn/gauge/snice-gauge.js +1 -1
  335. package/dist/cdn/gauge/snice-gauge.min.js +1 -1
  336. package/dist/cdn/grid/snice-grid.js +1 -1
  337. package/dist/cdn/grid/snice-grid.min.js +1 -1
  338. package/dist/cdn/heatmap/snice-heatmap.js +1 -1
  339. package/dist/cdn/heatmap/snice-heatmap.min.js +1 -1
  340. package/dist/cdn/image/snice-image.js +1 -1
  341. package/dist/cdn/image/snice-image.js.map +1 -1
  342. package/dist/cdn/image/snice-image.min.js +1 -1
  343. package/dist/cdn/image/snice-image.min.js.map +1 -1
  344. package/dist/cdn/input/snice-input.js +1 -1
  345. package/dist/cdn/input/snice-input.js.map +1 -1
  346. package/dist/cdn/input/snice-input.min.js +1 -1
  347. package/dist/cdn/input/snice-input.min.js.map +1 -1
  348. package/dist/cdn/invoice/README.md +1 -1
  349. package/dist/cdn/invoice/snice-invoice.js +2 -2
  350. package/dist/cdn/invoice/snice-invoice.js.map +1 -1
  351. package/dist/cdn/invoice/snice-invoice.min.js +2 -2
  352. package/dist/cdn/invoice/snice-invoice.min.js.map +1 -1
  353. package/dist/cdn/kanban/snice-kanban.js +1 -1
  354. package/dist/cdn/kanban/snice-kanban.min.js +1 -1
  355. package/dist/cdn/key-value/snice-key-value.js +1 -1
  356. package/dist/cdn/key-value/snice-key-value.min.js +1 -1
  357. package/dist/cdn/kpi/snice-kpi.js +1 -1
  358. package/dist/cdn/kpi/snice-kpi.js.map +1 -1
  359. package/dist/cdn/kpi/snice-kpi.min.js +1 -1
  360. package/dist/cdn/kpi/snice-kpi.min.js.map +1 -1
  361. package/dist/cdn/layout/snice-layout.js +1 -1
  362. package/dist/cdn/layout/snice-layout.min.js +1 -1
  363. package/dist/cdn/leaderboard/snice-leaderboard.js +1 -1
  364. package/dist/cdn/leaderboard/snice-leaderboard.min.js +1 -1
  365. package/dist/cdn/link/snice-link.js +1 -1
  366. package/dist/cdn/link/snice-link.min.js +1 -1
  367. package/dist/cdn/link-preview/snice-link-preview.js +1 -1
  368. package/dist/cdn/link-preview/snice-link-preview.min.js +1 -1
  369. package/dist/cdn/list/snice-list.js +1 -1
  370. package/dist/cdn/list/snice-list.js.map +1 -1
  371. package/dist/cdn/list/snice-list.min.js +1 -1
  372. package/dist/cdn/list/snice-list.min.js.map +1 -1
  373. package/dist/cdn/location/snice-location.js +1 -1
  374. package/dist/cdn/location/snice-location.js.map +1 -1
  375. package/dist/cdn/location/snice-location.min.js +1 -1
  376. package/dist/cdn/location/snice-location.min.js.map +1 -1
  377. package/dist/cdn/login/snice-login.js +3 -1
  378. package/dist/cdn/login/snice-login.js.map +1 -1
  379. package/dist/cdn/login/snice-login.min.js +1 -1
  380. package/dist/cdn/login/snice-login.min.js.map +1 -1
  381. package/dist/cdn/map/snice-map.js +1 -1
  382. package/dist/cdn/map/snice-map.min.js +1 -1
  383. package/dist/cdn/markdown/README.md +2 -2
  384. package/dist/cdn/markdown/snice-markdown.js +16 -3
  385. package/dist/cdn/markdown/snice-markdown.js.map +1 -1
  386. package/dist/cdn/markdown/snice-markdown.min.js +3 -3
  387. package/dist/cdn/markdown/snice-markdown.min.js.map +1 -1
  388. package/dist/cdn/masonry/snice-masonry.js +1 -1
  389. package/dist/cdn/masonry/snice-masonry.min.js +1 -1
  390. package/dist/cdn/menu/snice-menu.js +2 -2
  391. package/dist/cdn/menu/snice-menu.js.map +1 -1
  392. package/dist/cdn/menu/snice-menu.min.js +2 -2
  393. package/dist/cdn/menu/snice-menu.min.js.map +1 -1
  394. package/dist/cdn/message-strip/snice-message-strip.js +9 -9
  395. package/dist/cdn/message-strip/snice-message-strip.js.map +1 -1
  396. package/dist/cdn/message-strip/snice-message-strip.min.js +3 -3
  397. package/dist/cdn/message-strip/snice-message-strip.min.js.map +1 -1
  398. package/dist/cdn/metric-table/snice-metric-table.js +1 -1
  399. package/dist/cdn/metric-table/snice-metric-table.min.js +1 -1
  400. package/dist/cdn/modal/snice-modal.js +1 -1
  401. package/dist/cdn/modal/snice-modal.js.map +1 -1
  402. package/dist/cdn/modal/snice-modal.min.js +1 -1
  403. package/dist/cdn/modal/snice-modal.min.js.map +1 -1
  404. package/dist/cdn/music-player/snice-music-player.js +1 -1
  405. package/dist/cdn/music-player/snice-music-player.min.js +1 -1
  406. package/dist/cdn/nav/snice-nav.js +1 -1
  407. package/dist/cdn/nav/snice-nav.min.js +1 -1
  408. package/dist/cdn/network-graph/snice-network-graph.js +1 -1
  409. package/dist/cdn/network-graph/snice-network-graph.js.map +1 -1
  410. package/dist/cdn/network-graph/snice-network-graph.min.js +1 -1
  411. package/dist/cdn/network-graph/snice-network-graph.min.js.map +1 -1
  412. package/dist/cdn/notification-center/snice-notification-center.js +1 -1
  413. package/dist/cdn/notification-center/snice-notification-center.js.map +1 -1
  414. package/dist/cdn/notification-center/snice-notification-center.min.js +1 -1
  415. package/dist/cdn/notification-center/snice-notification-center.min.js.map +1 -1
  416. package/dist/cdn/order-tracker/snice-order-tracker.js +1 -1
  417. package/dist/cdn/order-tracker/snice-order-tracker.min.js +1 -1
  418. package/dist/cdn/org-chart/snice-org-chart.js +1 -1
  419. package/dist/cdn/org-chart/snice-org-chart.min.js +1 -1
  420. package/dist/cdn/pagination/snice-pagination.js +1 -1
  421. package/dist/cdn/pagination/snice-pagination.min.js +1 -1
  422. package/dist/cdn/paint/snice-paint.js +1 -1
  423. package/dist/cdn/paint/snice-paint.min.js +1 -1
  424. package/dist/cdn/pdf-viewer/snice-pdf-viewer.js +1 -1
  425. package/dist/cdn/pdf-viewer/snice-pdf-viewer.min.js +1 -1
  426. package/dist/cdn/permission-matrix/snice-permission-matrix.js +1 -1
  427. package/dist/cdn/permission-matrix/snice-permission-matrix.min.js +1 -1
  428. package/dist/cdn/podcast-player/snice-podcast-player.js +1 -1
  429. package/dist/cdn/podcast-player/snice-podcast-player.min.js +1 -1
  430. package/dist/cdn/popover/snice-popover.js +1 -1
  431. package/dist/cdn/popover/snice-popover.min.js +1 -1
  432. package/dist/cdn/pricing-table/snice-pricing-table.js +1 -1
  433. package/dist/cdn/pricing-table/snice-pricing-table.min.js +1 -1
  434. package/dist/cdn/product-card/snice-product-card.js +3 -3
  435. package/dist/cdn/product-card/snice-product-card.js.map +1 -1
  436. package/dist/cdn/product-card/snice-product-card.min.js +3 -3
  437. package/dist/cdn/product-card/snice-product-card.min.js.map +1 -1
  438. package/dist/cdn/progress/README.md +1 -1
  439. package/dist/cdn/progress/snice-progress.js +2 -2
  440. package/dist/cdn/progress/snice-progress.js.map +1 -1
  441. package/dist/cdn/progress/snice-progress.min.js +2 -2
  442. package/dist/cdn/progress/snice-progress.min.js.map +1 -1
  443. package/dist/cdn/progress-ring/snice-progress-ring.js +2 -2
  444. package/dist/cdn/progress-ring/snice-progress-ring.js.map +1 -1
  445. package/dist/cdn/progress-ring/snice-progress-ring.min.js +2 -2
  446. package/dist/cdn/progress-ring/snice-progress-ring.min.js.map +1 -1
  447. package/dist/cdn/qr-code/snice-qr-code.js +1 -1
  448. package/dist/cdn/qr-code/snice-qr-code.min.js +1 -1
  449. package/dist/cdn/qr-reader/snice-qr-reader.js +1 -1
  450. package/dist/cdn/qr-reader/snice-qr-reader.min.js +1 -1
  451. package/dist/cdn/radio/snice-radio.js +1 -1
  452. package/dist/cdn/radio/snice-radio.min.js +1 -1
  453. package/dist/cdn/range-slider/snice-range-slider.js +1 -1
  454. package/dist/cdn/range-slider/snice-range-slider.min.js +1 -1
  455. package/dist/cdn/rating/snice-rating.js +1 -1
  456. package/dist/cdn/rating/snice-rating.min.js +1 -1
  457. package/dist/cdn/receipt/snice-receipt.js +1 -1
  458. package/dist/cdn/receipt/snice-receipt.min.js +1 -1
  459. package/dist/cdn/recipe/snice-recipe.js +1 -1
  460. package/dist/cdn/recipe/snice-recipe.min.js +1 -1
  461. package/dist/cdn/runtime/README.md +2 -2
  462. package/dist/cdn/runtime/snice-runtime.esm.js +644 -172
  463. package/dist/cdn/runtime/snice-runtime.esm.js.map +1 -1
  464. package/dist/cdn/runtime/snice-runtime.esm.min.js +8 -8
  465. package/dist/cdn/runtime/snice-runtime.esm.min.js.map +1 -1
  466. package/dist/cdn/runtime/snice-runtime.js +644 -172
  467. package/dist/cdn/runtime/snice-runtime.js.map +1 -1
  468. package/dist/cdn/runtime/snice-runtime.min.js +8 -8
  469. package/dist/cdn/runtime/snice-runtime.min.js.map +1 -1
  470. package/dist/cdn/sankey/snice-sankey.js +1 -1
  471. package/dist/cdn/sankey/snice-sankey.js.map +1 -1
  472. package/dist/cdn/sankey/snice-sankey.min.js +1 -1
  473. package/dist/cdn/sankey/snice-sankey.min.js.map +1 -1
  474. package/dist/cdn/segmented-control/snice-segmented-control.js +1 -1
  475. package/dist/cdn/segmented-control/snice-segmented-control.min.js +1 -1
  476. package/dist/cdn/select/snice-select.js +1 -1
  477. package/dist/cdn/select/snice-select.min.js +1 -1
  478. package/dist/cdn/skeleton/snice-skeleton.js +1 -1
  479. package/dist/cdn/skeleton/snice-skeleton.min.js +1 -1
  480. package/dist/cdn/slider/snice-slider.js +1 -1
  481. package/dist/cdn/slider/snice-slider.min.js +1 -1
  482. package/dist/cdn/sortable/snice-sortable.js +1 -1
  483. package/dist/cdn/sortable/snice-sortable.min.js +1 -1
  484. package/dist/cdn/sparkline/snice-sparkline.js +1 -1
  485. package/dist/cdn/sparkline/snice-sparkline.min.js +1 -1
  486. package/dist/cdn/spinner/snice-spinner.js +1 -1
  487. package/dist/cdn/spinner/snice-spinner.min.js +1 -1
  488. package/dist/cdn/split-button/snice-split-button.js +1 -1
  489. package/dist/cdn/split-button/snice-split-button.js.map +1 -1
  490. package/dist/cdn/split-button/snice-split-button.min.js +1 -1
  491. package/dist/cdn/split-button/snice-split-button.min.js.map +1 -1
  492. package/dist/cdn/split-pane/snice-split-pane.js +1 -1
  493. package/dist/cdn/split-pane/snice-split-pane.min.js +1 -1
  494. package/dist/cdn/spotlight/snice-spotlight.js +1 -1
  495. package/dist/cdn/spotlight/snice-spotlight.min.js +1 -1
  496. package/dist/cdn/stat-group/snice-stat-group.js +1 -1
  497. package/dist/cdn/stat-group/snice-stat-group.min.js +1 -1
  498. package/dist/cdn/step-input/snice-step-input.js +1 -1
  499. package/dist/cdn/step-input/snice-step-input.min.js +1 -1
  500. package/dist/cdn/stepper/snice-stepper.js +1 -1
  501. package/dist/cdn/stepper/snice-stepper.min.js +1 -1
  502. package/dist/cdn/switch/snice-switch.js +1 -1
  503. package/dist/cdn/switch/snice-switch.min.js +1 -1
  504. package/dist/cdn/table/README.md +1 -1
  505. package/dist/cdn/table/snice-table.js +14 -4
  506. package/dist/cdn/table/snice-table.js.map +1 -1
  507. package/dist/cdn/table/snice-table.min.js +14 -4
  508. package/dist/cdn/table/snice-table.min.js.map +1 -1
  509. package/dist/cdn/tabs/snice-tabs.js +1 -1
  510. package/dist/cdn/tabs/snice-tabs.min.js +1 -1
  511. package/dist/cdn/tag/snice-tag.js +1 -1
  512. package/dist/cdn/tag/snice-tag.min.js +1 -1
  513. package/dist/cdn/tag-input/snice-tag-input.js +2 -2
  514. package/dist/cdn/tag-input/snice-tag-input.js.map +1 -1
  515. package/dist/cdn/tag-input/snice-tag-input.min.js +2 -2
  516. package/dist/cdn/tag-input/snice-tag-input.min.js.map +1 -1
  517. package/dist/cdn/terminal/snice-terminal.js +1 -1
  518. package/dist/cdn/terminal/snice-terminal.min.js +1 -1
  519. package/dist/cdn/testimonial/snice-testimonial.js +1 -1
  520. package/dist/cdn/testimonial/snice-testimonial.min.js +1 -1
  521. package/dist/cdn/textarea/snice-textarea.js +1 -1
  522. package/dist/cdn/textarea/snice-textarea.min.js +1 -1
  523. package/dist/cdn/time-picker/README.md +1 -1
  524. package/dist/cdn/time-picker/snice-time-picker.js +18 -13
  525. package/dist/cdn/time-picker/snice-time-picker.js.map +1 -1
  526. package/dist/cdn/time-picker/snice-time-picker.min.js +3 -3
  527. package/dist/cdn/time-picker/snice-time-picker.min.js.map +1 -1
  528. package/dist/cdn/time-range-picker/snice-time-range-picker.js +1 -1
  529. package/dist/cdn/time-range-picker/snice-time-range-picker.min.js +1 -1
  530. package/dist/cdn/timeline/snice-timeline.js +1 -1
  531. package/dist/cdn/timeline/snice-timeline.js.map +1 -1
  532. package/dist/cdn/timeline/snice-timeline.min.js +1 -1
  533. package/dist/cdn/timeline/snice-timeline.min.js.map +1 -1
  534. package/dist/cdn/timer/snice-timer.js +1 -1
  535. package/dist/cdn/timer/snice-timer.min.js +1 -1
  536. package/dist/cdn/toast/snice-toast.js +1 -1
  537. package/dist/cdn/toast/snice-toast.js.map +1 -1
  538. package/dist/cdn/toast/snice-toast.min.js +1 -1
  539. package/dist/cdn/toast/snice-toast.min.js.map +1 -1
  540. package/dist/cdn/tooltip/snice-tooltip.js +1 -1
  541. package/dist/cdn/tooltip/snice-tooltip.min.js +1 -1
  542. package/dist/cdn/tree/snice-tree.js +1 -1
  543. package/dist/cdn/tree/snice-tree.min.js +1 -1
  544. package/dist/cdn/treemap/snice-treemap.js +1 -1
  545. package/dist/cdn/treemap/snice-treemap.js.map +1 -1
  546. package/dist/cdn/treemap/snice-treemap.min.js +1 -1
  547. package/dist/cdn/treemap/snice-treemap.min.js.map +1 -1
  548. package/dist/cdn/user-card/snice-user-card.js +1 -1
  549. package/dist/cdn/user-card/snice-user-card.min.js +1 -1
  550. package/dist/cdn/video-player/snice-video-player.js +1 -1
  551. package/dist/cdn/video-player/snice-video-player.min.js +1 -1
  552. package/dist/cdn/virtual-scroller/snice-virtual-scroller.js +1 -1
  553. package/dist/cdn/virtual-scroller/snice-virtual-scroller.min.js +1 -1
  554. package/dist/cdn/waterfall/snice-waterfall.js +1 -1
  555. package/dist/cdn/waterfall/snice-waterfall.min.js +1 -1
  556. package/dist/cdn/weather/snice-weather.js +1 -1
  557. package/dist/cdn/weather/snice-weather.min.js +1 -1
  558. package/dist/cdn/work-order/snice-work-order.js +1 -1
  559. package/dist/cdn/work-order/snice-work-order.min.js +1 -1
  560. package/dist/components/action-bar/snice-action-bar.js +1 -1
  561. package/dist/components/action-bar/snice-action-bar.js.map +1 -1
  562. package/dist/components/banner/snice-banner.js +1 -1
  563. package/dist/components/banner/snice-banner.js.map +1 -1
  564. package/dist/components/chat/snice-chat-message.d.ts +32 -0
  565. package/dist/components/chat/snice-chat-message.js +127 -0
  566. package/dist/components/chat/snice-chat-message.js.map +1 -0
  567. package/dist/components/chat/snice-chat-message.types.d.ts +30 -0
  568. package/dist/components/chat/snice-chat.d.ts +31 -4
  569. package/dist/components/chat/snice-chat.js +363 -90
  570. package/dist/components/chat/snice-chat.js.map +1 -1
  571. package/dist/components/chat/snice-chat.types.d.ts +34 -3
  572. package/dist/components/command-palette/snice-command-palette.js +1 -1
  573. package/dist/components/command-palette/snice-command-palette.js.map +1 -1
  574. package/dist/components/icons/index.d.ts +4 -0
  575. package/dist/components/icons/index.js +5 -1
  576. package/dist/components/icons/index.js.map +1 -1
  577. package/dist/components/invoice/snice-invoice.js +1 -1
  578. package/dist/components/invoice/snice-invoice.js.map +1 -1
  579. package/dist/components/login/snice-login.d.ts +2 -2
  580. package/dist/components/login/snice-login.js +2 -0
  581. package/dist/components/login/snice-login.js.map +1 -1
  582. package/dist/components/login/snice-login.types.d.ts +4 -0
  583. package/dist/components/markdown/snice-markdown.d.ts +1 -0
  584. package/dist/components/markdown/snice-markdown.js +15 -2
  585. package/dist/components/markdown/snice-markdown.js.map +1 -1
  586. package/dist/components/menu/snice-menu.js +1 -1
  587. package/dist/components/menu/snice-menu.js.map +1 -1
  588. package/dist/components/message-strip/snice-message-strip.d.ts +1 -1
  589. package/dist/components/message-strip/snice-message-strip.js +8 -8
  590. package/dist/components/message-strip/snice-message-strip.types.d.ts +1 -1
  591. package/dist/components/product-card/snice-product-card.js +2 -2
  592. package/dist/components/product-card/snice-product-card.js.map +1 -1
  593. package/dist/components/progress/snice-progress.js +1 -1
  594. package/dist/components/progress/snice-progress.js.map +1 -1
  595. package/dist/components/progress-ring/snice-progress-ring.js +1 -1
  596. package/dist/components/progress-ring/snice-progress-ring.js.map +1 -1
  597. package/dist/components/table/snice-table.js +13 -3
  598. package/dist/components/table/snice-table.js.map +1 -1
  599. package/dist/components/tag-input/snice-tag-input.js +1 -1
  600. package/dist/components/tag-input/snice-tag-input.js.map +1 -1
  601. package/dist/components/time-picker/snice-time-picker.js +17 -12
  602. package/dist/components/time-picker/snice-time-picker.js.map +1 -1
  603. package/dist/components/utils.d.ts +6 -0
  604. package/dist/components/utils.js +1 -1
  605. package/dist/components/utils.js.map +1 -1
  606. package/dist/element.d.ts +2 -1
  607. package/dist/events.d.ts +6 -0
  608. package/dist/index.cjs +641 -169
  609. package/dist/index.cjs.map +1 -1
  610. package/dist/index.esm.js +641 -169
  611. package/dist/index.esm.js.map +1 -1
  612. package/dist/index.iife.js +641 -169
  613. package/dist/index.iife.js.map +1 -1
  614. package/dist/parts.d.ts +1 -8
  615. package/dist/react/SniceProvider.js +1 -1
  616. package/dist/react/SniceRouter.js +1 -1
  617. package/dist/react/index.js +1 -1
  618. package/dist/react/matchRoute.d.ts +1 -1
  619. package/dist/react/matchRoute.js +38 -4
  620. package/dist/react/matchRoute.js.map +1 -1
  621. package/dist/react/route-specificity.d.ts +1 -0
  622. package/dist/react/useRequestHandler.js +1 -1
  623. package/dist/render.d.ts +7 -0
  624. package/dist/route-specificity.d.ts +1 -0
  625. package/dist/symbols.cjs +14 -1
  626. package/dist/symbols.cjs.map +1 -1
  627. package/dist/symbols.d.ts +3 -0
  628. package/dist/symbols.esm.js +12 -2
  629. package/dist/symbols.esm.js.map +1 -1
  630. package/dist/transitions.cjs +1 -1
  631. package/dist/transitions.esm.js +1 -1
  632. package/dist/types/context.d.ts +5 -2
  633. package/dist/types/dispatch-options.d.ts +7 -0
  634. package/dist/types/index.d.ts +1 -0
  635. package/dist/types/on-options.d.ts +14 -0
  636. package/dist/types/watch-options.d.ts +9 -0
  637. package/dist/utils.d.ts +26 -0
  638. package/docs/ai/DEVELOPMENT.md +1 -1
  639. package/docs/ai/README.md +11 -0
  640. package/docs/ai/api.md +24 -5
  641. package/docs/ai/cdn.md +31 -0
  642. package/docs/ai/components/chat.md +57 -1
  643. package/docs/ai/components/message-strip.md +3 -3
  644. package/docs/ai/decorators.md +44 -5
  645. package/docs/cdn.md +56 -0
  646. package/docs/components/chat.md +108 -2
  647. package/docs/components/message-strip.md +8 -8
  648. package/docs/elements.md +21 -0
  649. package/docs/events.md +88 -0
  650. package/docs/superpowers/specs/2026-05-26-chat-styling-design.md +155 -0
  651. package/docs/superpowers/specs/2026-05-27-chat-theming-REMAINING.md +83 -0
  652. package/docs/superpowers/specs/2026-06-09-chat-custom-content-design.md +233 -0
  653. package/package.json +1 -1
@@ -6,7 +6,7 @@ Inline contextual message bar within content flow. Differs from alert (card), ba
6
6
 
7
7
  ```ts
8
8
  variant: 'info'|'success'|'warning'|'danger' = 'info';
9
- dismissable: boolean = false;
9
+ dismissible: boolean = false;
10
10
  icon: string = ''; // Custom icon (set "none" to hide)
11
11
  ```
12
12
 
@@ -43,8 +43,8 @@ import 'snice/components/message-strip/snice-message-strip';
43
43
  <snice-message-strip variant="warning">Review your changes.</snice-message-strip>
44
44
  <snice-message-strip variant="danger">An error occurred.</snice-message-strip>
45
45
 
46
- <!-- Dismissable -->
47
- <snice-message-strip variant="info" dismissable>You can close this.</snice-message-strip>
46
+ <!-- Dismissible -->
47
+ <snice-message-strip variant="info" dismissible>You can close this.</snice-message-strip>
48
48
 
49
49
  <!-- Custom icon -->
50
50
  <snice-message-strip variant="info" icon="🔔">New notification.</snice-message-strip>
@@ -13,7 +13,8 @@
13
13
 
14
14
  ## Properties
15
15
  - `@property({ type?, attribute?: string|boolean, converter?, hasChanged? })` - Reactive, syncs attrs. Initial defaults NOT reflected to attrs.
16
- - `@watch('propName')` - React to changes: `(oldVal, newVal, propertyName) => void`
16
+ - `@watch('propName')` - Fires once on init as `(undefined, initialValue, propertyName)`, then on every change: `(oldVal, newVal, propertyName) => void`.
17
+ - `@watch('propName', { immediate: false })` - Change-only; skips the init call (use for watchers that dispatch events). Options object is the last arg (works with multiple names).
17
18
 
18
19
  ## Lifecycle
19
20
  - `@ready()` - After first render. Fires once.
@@ -27,8 +28,37 @@
27
28
  - `@queryAll('selector', { light? })` - NodeList
28
29
 
29
30
  ## Events
30
- - `@on('event', 'selector?')` - Delegation, auto-bound
31
- - `@dispatch('event-name', options?)` - Emit CustomEvent, detail = return value. Supports async. Options: `{ debounce?, throttle?, dispatchOnUndefined? }`
31
+ - `@on('event', 'selector?', options?)` - Delegation, auto-bound. Options: `{ capture?, once?, passive?, preventDefault?, stopPropagation?, debounce?, throttle?, scope? }`
32
+ - `@dispatch('event-name', options?)` - Emit CustomEvent, detail = return value. Supports async. Options: `{ debounce?, throttle?, dispatchOnUndefined?, scope?, ...EventInit }`
33
+
34
+ ### scope (on both `@on` and `@dispatch`)
35
+
36
+ Redirects where the listener is attached / event is dispatched. Default: host element.
37
+
38
+ ```ts
39
+ scope?: 'global' | string | EventTarget | ((this: HTMLElement) => EventTarget | null)
40
+ ```
41
+
42
+ | value | resolves to |
43
+ |---|---|
44
+ | omitted | host element |
45
+ | `'global'` | `document` |
46
+ | selector string | `host.closest(selector)` — nearest ancestor |
47
+ | Element / EventTarget | that node |
48
+ | resolver fn | called with host as `this`; `null` skips |
49
+
50
+ ```ts
51
+ @on('bus:save', { scope: 'global' }) onSave(e) {}
52
+ @on('bus:cart-added', { scope: 'cart-shell' }) onAdd(e) {}
53
+ @on('go', { scope: someEl }) onGo(e) {}
54
+ @on('beep', { scope() { return this.closest('app-shell'); } }) onBeep(e) {}
55
+
56
+ @dispatch('bus:cart-added', { scope: 'global' }) add(id) { return { id }; }
57
+ @dispatch('bus:x', { scope: 'cart-shell' }) fire() { return 1; }
58
+ ```
59
+
60
+ Unresolved scope → `console.warn`, listener not attached / event not dispatched.
61
+ Resolver re-runs on reconnect — listeners track DOM moves.
32
62
 
33
63
  ## Communication
34
64
  - `@request(channel, options?)` - Async generator request pattern
@@ -58,9 +88,18 @@ attr="${val}" - String attribute
58
88
  @event=${fn} - Event listener (auto-bound)
59
89
  ```
60
90
 
61
- ## Event Modifiers
91
+ ## Event Modifiers (keyboard only)
92
+ Template dotted/colon modifiers apply ONLY to keydown/keyup/keypress — they are
93
+ key filters, not general event options. A dot in any other event name is part of
94
+ the event name (e.g. `@app.ready`).
62
95
  ```
63
96
  @keydown:Enter=${fn} - Key filter
64
97
  @keydown.ctrl+s=${fn} - Key combo
65
- @click.once=${fn} - Fire once
98
+ @keydown.~enter=${fn} - Key, any modifiers
99
+ ```
100
+ `once` / `preventDefault` / `stopPropagation` / `capture` are NOT template
101
+ modifiers — use the `@on` decorator's options object:
102
+ ```typescript
103
+ @on('click', { once: true, preventDefault: true, stopPropagation: true })
104
+ handleClick(e: Event) {}
66
105
  ```
package/docs/cdn.md ADDED
@@ -0,0 +1,56 @@
1
+ <!-- AI: For the AI-optimized version of this doc, see docs/ai/cdn.md -->
2
+
3
+ # CDN / Standalone Usage
4
+
5
+ Use any Snice component on a plain HTML page — no bundler, no build step. Each component is a standalone `.min.js` bundle that shares one small runtime.
6
+
7
+ ## Load Order
8
+
9
+ Load the runtime **once, first**, then one bundle per component. Components load in any order *after* the runtime:
10
+
11
+ ```html
12
+ <link rel="stylesheet" href="theme.css"> <!-- optional: design tokens + dark mode -->
13
+ <script src="snice-runtime.min.js"></script> <!-- required, load first -->
14
+ <script src="snice-button.min.js"></script> <!-- one bundle per component -->
15
+ <script src="snice-card.min.js"></script>
16
+
17
+ <snice-button variant="primary">Click me</snice-button>
18
+ ```
19
+
20
+ `snice-runtime.min.js` is shared by every component. Load it before any `snice-<name>.min.js` — without it the custom elements never register and the page renders blank.
21
+
22
+ ## Bundle Families
23
+
24
+ One bundle registers its whole element family — you don't load sub-elements separately:
25
+
26
+ | Bundle | Registers |
27
+ |--------|-----------|
28
+ | `snice-tabs.min.js` | `<snice-tabs>`, `<snice-tab>`, `<snice-tab-panel>` |
29
+ | `snice-select.min.js` | `<snice-select>`, `<snice-option>` |
30
+ | `snice-toast.min.js` | `<snice-toast>`, `<snice-toast-container>` |
31
+
32
+ ## Theme and Dark Mode
33
+
34
+ Components ship with built-in light-mode token fallbacks, so they render correctly with no stylesheet. Add `theme.css` for the full design-token set and dark mode:
35
+
36
+ ```html
37
+ <link rel="stylesheet" href="theme.css">
38
+ ```
39
+
40
+ Dark mode follows the OS setting automatically. To force it, set `data-theme` on the root element:
41
+
42
+ ```html
43
+ <html data-theme="dark"> <!-- or data-theme="light" to pin light -->
44
+ ```
45
+
46
+ ## Use the `.min.js` Builds
47
+
48
+ Load the `.min.js` (IIFE) bundles in `<script src>` tags. The `.esm.min.js` builds are ES modules for bundler/`import` use, not `<script src>`.
49
+
50
+ ## Generating Bundles
51
+
52
+ Bundles are published to the CDN, or build them yourself:
53
+
54
+ ```bash
55
+ snice build-component button
56
+ ```
@@ -2,9 +2,10 @@
2
2
 
3
3
  # Chat Component
4
4
 
5
- Slack-style chat interface with messages, typing indicators, reactions, file attachments, and message threading.
5
+ Slack-style chat interface with messages, typing indicators, reactions, and file attachments.
6
6
 
7
7
  ## Table of Contents
8
+ - [Components](#components)
8
9
  - [Properties](#properties)
9
10
  - [Methods](#methods)
10
11
  - [Events](#events)
@@ -14,6 +15,13 @@ Slack-style chat interface with messages, typing indicators, reactions, file att
14
15
  - [Examples](#examples)
15
16
  - [Accessibility](#accessibility)
16
17
 
18
+ ## Components
19
+
20
+ | Element | Description |
21
+ |---------|-------------|
22
+ | `snice-chat` | The chat container — renders messages, input, typing indicators. |
23
+ | `snice-chat-message` | Declarative message authoring. Provide messages as child elements instead of (or as well as) the `messages` array; child elements render first, array entries append after. |
24
+
17
25
  ## Properties
18
26
 
19
27
  | Property | Type | Default | Description |
@@ -26,6 +34,23 @@ Slack-style chat interface with messages, typing indicators, reactions, file att
26
34
  | `showTyping` (attr: `show-typing`) | `boolean` | `true` | Show typing indicators |
27
35
  | `showAvatars` (attr: `show-avatars`) | `boolean` | `true` | Show user avatars |
28
36
  | `showTimestamps` (attr: `show-timestamps`) | `boolean` | `true` | Show message timestamps |
37
+ | `authorColors` | `Record<string, string>` | `{}` | Per-author name colors, keyed by author name (property only) |
38
+ | `colorAuthors` (attr: `color-authors`) | `boolean` | `false` | Auto-assign a stable color to each author |
39
+ | `markdown` | `boolean` | `false` | Render message content as markdown by default |
40
+ | `layout` | `'default' \| 'bubbles'` | `'default'` | Built-in message layout; `'bubbles'` aligns own messages right in colored bubbles |
41
+
42
+ ### snice-chat-message Attributes
43
+
44
+ | Attribute | Type | Default | Description |
45
+ |-----------|------|---------|-------------|
46
+ | `author` | `string` | `''` | Message author name |
47
+ | `avatar` | `string` | `''` | Author avatar URL |
48
+ | `type` | `'text' \| 'file' \| 'image' \| 'system'` | `'text'` | Message type |
49
+ | `format` | `'text' \| 'markdown'` | — | How the body is rendered; unset defers to the chat-level `markdown` flag |
50
+ | `edited` | `boolean` | `false` | Marks the message as edited |
51
+ | `author-color` | `string` | `''` | Per-message author color override |
52
+
53
+ The message body is the element's text content. Rich fields with no attribute form — `reactions`, `attachment` — can be set as JS properties on the element and are carried into the message.
29
54
 
30
55
  ### ChatMessage Interface
31
56
 
@@ -41,6 +66,8 @@ interface ChatMessage {
41
66
  reactions?: MessageReaction[];
42
67
  thread?: ChatMessage[];
43
68
  attachment?: MessageAttachment;
69
+ format?: 'text' | 'markdown'; // unset = the chat-level markdown flag applies
70
+ authorColor?: string; // per-message author color override (CSS color; values containing ; { } are rejected)
44
71
  }
45
72
 
46
73
  interface MessageAttachment {
@@ -79,10 +106,11 @@ interface MessageReaction {
79
106
  | `message-edit` | `{ messageId: string, newContent: string }` | User edits a message |
80
107
  | `message-delete` | `{ messageId: string }` | User deletes a message |
81
108
  | `message-react` | `{ messageId: string, emoji: string }` | User reacts to a message |
82
- | `message-thread` | `{ messageId: string }` | User starts a thread |
83
109
  | `typing-start` | `{}` | Current user starts typing |
84
110
  | `typing-stop` | `{}` | Current user stops typing |
85
111
 
112
+ React, edit, and delete are applied to the local `messages` model by the component itself in addition to emitting the event — your handler should persist the change to a backend, not re-apply it to `messages` (doing both double-applies). If the backend rejects a change, revert it with `updateMessage()` (or by reassigning `messages`) from your handler. Reactions work on any message (yours or another user's); edit and delete are owner-only. Delete asks for inline confirmation before removing. `message-send` is the exception: the component does not self-add the sent message, so your handler appends it.
113
+
86
114
  ## CSS Custom Properties
87
115
 
88
116
  | Property | Description |
@@ -132,6 +160,27 @@ interface MessageReaction {
132
160
  |------|-------------|
133
161
  | `base` | The chat container |
134
162
  | `messages` | The scrollable messages area |
163
+ | `message` | A message row (every message) |
164
+ | `message-own` | A message row authored by the current user |
165
+ | `message-other` | A message row authored by someone else |
166
+ | `system-message` | A system message row |
167
+ | `avatar` | A message avatar |
168
+ | `author` | A message author name |
169
+ | `timestamp` | A message timestamp |
170
+ | `edited` | The "(edited)" marker |
171
+ | `message-text` | A message body |
172
+ | `attachment` | A message attachment |
173
+ | `reactions` | A message's reactions container |
174
+ | `reaction` | A single reaction |
175
+ | `reaction-active` | A reaction the current user has added |
176
+ | `actions` | The hover action menu |
177
+ | `edit-input` | The inline edit textarea (shown while editing) |
178
+ | `edit-save` | The save button in the inline editor |
179
+ | `edit-cancel` | The cancel button in the inline editor |
180
+ | `delete-confirm` | The inline delete-confirmation row |
181
+ | `delete-confirm-yes` | The confirm (delete) button |
182
+ | `delete-confirm-no` | The cancel button in the delete confirmation |
183
+ | `typing-indicator` | A typing indicator row |
135
184
  | `input-area` | The input area wrapper |
136
185
  | `input-container` | Container holding the input and buttons |
137
186
  | `input` | The message input field |
@@ -231,6 +280,63 @@ setTimeout(() => {
231
280
  }, 2000);
232
281
  ```
233
282
 
283
+ ### Declarative Messages
284
+
285
+ Author messages as `snice-chat-message` children instead of the `messages` array. When both are present, child elements render first and array entries (including `addMessage()` calls) append after them. Slotted messages keep their identity across DOM updates, so reactions and edits made in the UI survive re-renders.
286
+
287
+ ```html
288
+ <snice-chat current-user="Me">
289
+ <snice-chat-message slot="messages" author="Alice" timestamp="2026-05-26T09:24:00Z">Hey, deploy is green</snice-chat-message>
290
+ <snice-chat-message slot="messages" author="Me" timestamp="2026-05-26T09:25:00Z">Merging now</snice-chat-message>
291
+ </snice-chat>
292
+ ```
293
+
294
+ ### Per-User Name Colors
295
+
296
+ Set `colorAuthors` to auto-assign a stable color per author, or supply explicit colors with `authorColors`. A per-message `authorColor` overrides both.
297
+
298
+ ```html
299
+ <snice-chat color-authors></snice-chat>
300
+ ```
301
+
302
+ ```javascript
303
+ chat.authorColors = { Alice: '#e11d48', Bob: '#2563eb' };
304
+ ```
305
+
306
+ ### Markdown
307
+
308
+ Set `markdown` to render every message body as markdown, or set `format: 'markdown'` per message. A per-message `format: 'text'` opts out of the component-wide default.
309
+
310
+ ```html
311
+ <snice-chat markdown></snice-chat>
312
+ ```
313
+
314
+ ```javascript
315
+ chat.addMessage({
316
+ type: 'text', author: 'Alice', timestamp: new Date(),
317
+ format: 'markdown',
318
+ content: 'shipped **v5.3** — run `npm i snice@latest`'
319
+ });
320
+ ```
321
+
322
+ ### Bubble Layout
323
+
324
+ Set `layout="bubbles"` for a mobile-OS style: own messages right-aligned in colored bubbles, others left.
325
+
326
+ ```html
327
+ <snice-chat layout="bubbles" current-user="Me"></snice-chat>
328
+ ```
329
+
330
+ ### Custom Styling with Parts
331
+
332
+ Every message internal is exposed as a CSS part.
333
+
334
+ ```css
335
+ snice-chat::part(author) { font-family: 'Inter'; }
336
+ snice-chat::part(message-own) { background: rgba(37, 99, 235, 0.06); }
337
+ snice-chat::part(message-text) { font-size: 0.9375rem; }
338
+ ```
339
+
234
340
  ## Accessibility
235
341
 
236
342
  - Keyboard navigation for messages and controls
@@ -3,7 +3,7 @@
3
3
  # Message Strip
4
4
  `<snice-message-strip>`
5
5
 
6
- An inline contextual message bar for displaying status messages within content flow. Unlike alerts (dismissable card), banners (full-width top), and toasts (floating), message strips are designed to sit inline within your content.
6
+ An inline contextual message bar for displaying status messages within content flow. Unlike alerts (dismissible card), banners (full-width top), and toasts (floating), message strips are designed to sit inline within your content.
7
7
 
8
8
  ## Table of Contents
9
9
  - [Properties](#properties)
@@ -20,7 +20,7 @@ An inline contextual message bar for displaying status messages within content f
20
20
  | Property | Type | Default | Description |
21
21
  |----------|------|---------|-------------|
22
22
  | `variant` | `'info' \| 'success' \| 'warning' \| 'danger'` | `'info'` | Message type / color |
23
- | `dismissable` | `boolean` | `false` | Show dismiss button |
23
+ | `dismissible` | `boolean` | `false` | Show dismiss button |
24
24
  | `icon` | `string` | `''` | Custom icon (set "none" to hide default icon) |
25
25
 
26
26
  ## Methods
@@ -86,12 +86,12 @@ Use the `variant` attribute to indicate the message type.
86
86
  <snice-message-strip variant="danger">An error occurred while saving.</snice-message-strip>
87
87
  ```
88
88
 
89
- ### Dismissable
89
+ ### Dismissible
90
90
 
91
- Set the `dismissable` attribute to allow users to close the message.
91
+ Set the `dismissible` attribute to allow users to close the message.
92
92
 
93
93
  ```html
94
- <snice-message-strip variant="info" dismissable>
94
+ <snice-message-strip variant="info" dismissible>
95
95
  You can dismiss this message.
96
96
  </snice-message-strip>
97
97
  ```
@@ -142,7 +142,7 @@ messageStrip.show();
142
142
 
143
143
  ```html
144
144
  <form>
145
- <snice-message-strip variant="danger" dismissable style="display: none;">
145
+ <snice-message-strip variant="danger" dismissible style="display: none;">
146
146
  Please fill in all required fields.
147
147
  </snice-message-strip>
148
148
 
@@ -155,10 +155,10 @@ messageStrip.show();
155
155
 
156
156
  ```html
157
157
  <div style="display: flex; flex-direction: column; gap: 8px;">
158
- <snice-message-strip variant="danger" dismissable>
158
+ <snice-message-strip variant="danger" dismissible>
159
159
  Server connection lost.
160
160
  </snice-message-strip>
161
- <snice-message-strip variant="warning" dismissable>
161
+ <snice-message-strip variant="warning" dismissible>
162
162
  Your session will expire in 5 minutes.
163
163
  </snice-message-strip>
164
164
  <snice-message-strip variant="info">
package/docs/elements.md CHANGED
@@ -995,6 +995,27 @@ class ReactiveComponent extends HTMLElement {
995
995
  }
996
996
  ```
997
997
 
998
+ **Initial values.** By default a watcher fires once during initialization with the element's starting value — from markup (`<reactive-component user-name="Ada">`) or the field default — with `oldValue` undefined, then again on every later change:
999
+
1000
+ ```typescript
1001
+ @watch('userName')
1002
+ onUserNameChange(oldVal: string | undefined, newVal: string) {
1003
+ // Init: (undefined, 'Ada')
1004
+ // Change: ('Ada', 'Grace')
1005
+ }
1006
+ ```
1007
+
1008
+ Pass `{ immediate: false }` as the last argument for a change-only watcher — one that must not run on mount, such as a watcher that dispatches an event:
1009
+
1010
+ ```typescript
1011
+ @watch('value', { immediate: false })
1012
+ onValueChange(oldVal: string, newVal: string) {
1013
+ this.dispatchChange(); // only on real changes, never on mount
1014
+ }
1015
+ ```
1016
+
1017
+ The options object always comes after the property names, so it works with multiple watched properties too: `@watch('width', 'height', { immediate: false })`.
1018
+
998
1019
  ### @context() Decorator
999
1020
 
1000
1021
  Receive router context updates. The decorated method is called whenever the router context changes (navigation, app context update, etc.):
package/docs/events.md CHANGED
@@ -385,9 +385,56 @@ interface OnOptions {
385
385
 
386
386
  // Shadow DOM delegation
387
387
  target?: string; // CSS selector to target specific elements within shadow root
388
+
389
+ // Where to attach the listener (see scope section below)
390
+ scope?: 'global' | string | EventTarget | ((this: HTMLElement) => EventTarget | null);
388
391
  }
389
392
  ```
390
393
 
394
+ #### scope — controlling the listener target
395
+
396
+ By default, `@on` attaches the listener to the host element. The `scope` option redirects
397
+ that attachment to another target, which is how Snice expresses cross-cutting events.
398
+
399
+ | `scope` value | Listener attaches to |
400
+ |---|---|
401
+ | omitted | host element (default) |
402
+ | `'global'` | `document` |
403
+ | selector string | `host.closest(selector)` — nearest matching ancestor |
404
+ | `Element` / `EventTarget` | that node directly |
405
+ | `(this) => EventTarget \| null` | called at connect; `null` skips |
406
+
407
+ The resolver function is called with the host element as `this` and re-resolves each time
408
+ the component reconnects to the DOM, so listeners follow the host when it moves.
409
+
410
+ ```typescript
411
+ // Cross-cutting global event (document)
412
+ @on('bus:save', { scope: 'global' })
413
+ onSave(e: CustomEvent) { /* ... */ }
414
+
415
+ // Scoped to nearest ancestor matching the selector
416
+ @on('bus:cart-added', { scope: 'cart-shell' })
417
+ onCartAdded(e: CustomEvent) { /* ... */ }
418
+
419
+ // Explicit EventTarget
420
+ @on('go', { scope: someElement })
421
+ onGo() { /* ... */ }
422
+
423
+ // Resolver — full control, re-runs on reconnect
424
+ @on('beep', { scope() { return this.closest('app-shell'); } })
425
+ onBeep() { /* ... */ }
426
+ ```
427
+
428
+ If `scope` cannot resolve (selector matches no ancestor, resolver returns `null` or throws),
429
+ the listener is **not attached** and a `console.warn` is emitted. The component still
430
+ mounts; only the listener is skipped.
431
+
432
+ Disconnect removes the listener from whichever target it was attached to. Reconnect
433
+ re-resolves and re-attaches, so resolver-based scopes track DOM moves correctly.
434
+
435
+ `scope` is compatible with the delegation selector — the listener attaches on the
436
+ scoped target and still matches the selector when an event fires within it.
437
+
391
438
  #### Throttling
392
439
 
393
440
  ```typescript
@@ -534,9 +581,50 @@ interface DispatchOptions extends EventInit {
534
581
  dispatchOnUndefined?: boolean; // Skip dispatch when return is undefined (default: true)
535
582
  debounce?: number; // Debounce dispatch by ms
536
583
  throttle?: number; // Throttle dispatch by ms
584
+ // Where to dispatch the event (see scope section below)
585
+ scope?: 'global' | string | EventTarget | ((this: HTMLElement) => EventTarget | null);
586
+ }
587
+ ```
588
+
589
+ #### scope — controlling the dispatch target
590
+
591
+ By default, `@dispatch` calls `this.dispatchEvent(event)` — the event originates from
592
+ the host element. The `scope` option redirects the dispatch to another target so the
593
+ event behaves as if it originated there. Use this with `@on({ scope })` to express
594
+ cross-cutting events without going through bubbling.
595
+
596
+ | `scope` value | Event dispatched on |
597
+ |---|---|
598
+ | omitted | host element (default) |
599
+ | `'global'` | `document` |
600
+ | selector string | `host.closest(selector)` — nearest matching ancestor |
601
+ | `Element` / `EventTarget` | that node directly |
602
+ | `(this) => EventTarget \| null` | called per dispatch; `null` skips |
603
+
604
+ ```typescript
605
+ // Global cart-add bus
606
+ @element('add-to-cart-button')
607
+ class AddToCartButton extends HTMLElement {
608
+ @on('click', 'button')
609
+ click() { this.add(this.productId); }
610
+
611
+ @dispatch('bus:cart-added', { scope: 'global' })
612
+ add(id: string) { return { id }; }
613
+ }
614
+
615
+ // Listener on any other element
616
+ @element('cart-counter')
617
+ class CartCounter extends HTMLElement {
618
+ @on('bus:cart-added', { scope: 'global' })
619
+ bump() { this.count++; }
537
620
  }
538
621
  ```
539
622
 
623
+ If `scope` cannot resolve (selector matches no ancestor, resolver returns `null`),
624
+ the event is **not dispatched** and a `console.warn` is emitted. The method's return
625
+ value still flows through `dispatchOnUndefined` / `debounce` / `throttle` semantics
626
+ before the scope check.
627
+
540
628
  ### Debounce/Throttle
541
629
 
542
630
  ```typescript
@@ -0,0 +1,155 @@
1
+ # snice-chat: full theming surface + declarative messages + markdown
2
+
3
+ **Date:** 2026-05-26
4
+ **Status:** Approved design, pre-implementation
5
+
6
+ ## Problem
7
+
8
+ `snice-chat` is barely styleable. It exposes only 5 CSS parts (`base`, `messages`,
9
+ `input-area`, `input-container`, `input`) and theme tokens. None of the per-message
10
+ pieces — author name, avatar, timestamp, bubble, reactions — are reachable from
11
+ outside the shadow DOM. There is no per-user color, no own-vs-other distinction
12
+ (the component computes `isCurrentUser` but never writes it to the DOM), no
13
+ markdown, and no declarative authoring API (it is imperative-only via `messages[]`).
14
+
15
+ ## Goals
16
+
17
+ Deliver five capabilities, all **opt-in** and **purely additive** — the default
18
+ render must be byte-for-byte identical to today:
19
+
20
+ - **A · Per-user name colors** — each author's name colored, Slack/Discord style.
21
+ - **B · Own vs other** — style "my" messages differently; ship an opt-in bubble layout.
22
+ - **C · Bubble / message-type theming** — restyle bubble, system message, reactions, timestamps.
23
+ - **D · Full part surface** — every internal element exposed as a CSS `::part`.
24
+ - **E · Markdown** — render message content as markdown, opt-in.
25
+
26
+ Plus the architectural change the user approved:
27
+
28
+ - **Declarative `<snice-chat-message>` sub-element** giving `snice-chat` the dual API
29
+ (imperative array **or** slotted children) required of collection components.
30
+
31
+ ## Non-Goals (explicitly out of scope)
32
+
33
+ - **CDN bundling of the new sub-element.** The known table/`snice-column` CDN
34
+ gotcha is not solved here. Do not touch the CDN build for this work.
35
+ - Inline message editing UX (stays the existing `prompt()` behavior).
36
+ - Threads / reaction pickers / any new interaction.
37
+
38
+ ## Architecture
39
+
40
+ Follows the existing **table / `snice-column` pattern**: the sub-element is a
41
+ declarative *config carrier*, not a self-rendering element. The parent keeps
42
+ ownership of all rendering, so the styling part surface stays flat — no nested
43
+ shadow DOM, no `exportparts` chaining.
44
+
45
+ ```
46
+ <snice-chat> parent — owns rendering, owns the part surface
47
+ ├─ messages[] (imperative API) ┐
48
+ │ ├─ merged → renders message rows in its shadow DOM
49
+ └─ <snice-chat-message slot> ──┘ (slot wins when present)
50
+ (declarative config carrier, render() = <slot></slot>, renders nothing)
51
+ ```
52
+
53
+ Ingestion mirrors the table:
54
+
55
+ ```
56
+ await customElements.whenDefined('snice-chat-message');
57
+ const els = Array.from(this.querySelectorAll('snice-chat-message[slot="messages"]'));
58
+ this.messages = els.map(el => el.getMessageDefinition());
59
+ // re-read on bubbling 'message-changed'
60
+ ```
61
+
62
+ ## New element: `<snice-chat-message>`
63
+
64
+ Files: `components/chat/snice-chat-message.ts`, `snice-chat-message.types.ts`, `snice-chat-message.css` (minimal).
65
+
66
+ - `@element('snice-chat-message')`, `@render()` → `html\`<slot></slot>\``.
67
+ - Attributes: `author`, `avatar`, `timestamp`, `type`, `format` (`text` | `markdown`),
68
+ `edited` (boolean), `author-color`.
69
+ - Message body = default slot text content.
70
+ - `getMessageDefinition(): ChatMessage` — serializes props to a `ChatMessage`.
71
+ - Bubbles `message-changed` (`{ message: ChatMessage }`) on any prop change, so the
72
+ parent re-reads (same as `snice-column`'s `column-changed`).
73
+
74
+ ## `<snice-chat>` additions — all additive
75
+
76
+ ### 1. Dual API
77
+ Keep `messages[]`, `addMessage`, `updateMessage`, `deleteMessage`, `clear`. Also
78
+ ingest slotted `<snice-chat-message slot="messages">` via the table pattern above.
79
+ Slot children win when present.
80
+
81
+ ### 2. Per-user name colors (A)
82
+ - New property `authorColors: Record<string, string>` (override map).
83
+ - New boolean attribute `color-authors` — opt-in to automatic coloring.
84
+ - Resolution per message, computed inside the component instance (no global
85
+ registry, no singleton):
86
+ 1. `authorColors[author]` if set, else
87
+ 2. auto: stable hash of author name → fixed accent palette **only when `color-authors` is present**, else
88
+ 3. unset → falls through to the current default color.
89
+ - Implementation: author element gets `style="--snice-chat-author-color:${resolved}"`
90
+ when a color resolves; CSS reads `color: var(--snice-chat-author-color, <current default token>)`.
91
+ Inline-CSS-var injection is the established snice idiom (`--c`, `--bar-delay`,
92
+ `--volume-percent`, `--form-columns`). **No `data-*` styling hooks.**
93
+
94
+ ### 3. Own vs other (B)
95
+ - Each message row gets space-separated part names: `part="message message-own"`
96
+ or `part="message message-other"` (the established stateful-variant idiom —
97
+ cf. `part="button first-button"`). Default CSS for these adds nothing visual.
98
+ - Opt-in `layout="bubbles"` attribute ships the aligned colored-bubble look via
99
+ `:host([layout="bubbles"])` rules. Absent attribute = today's look.
100
+
101
+ ### 4. Bubble / type theming (C) + full part surface (D)
102
+ Add `part=` to: `avatar`, `author`, `timestamp`, `edited`, `message-text`,
103
+ `attachment`, `reactions`, `reaction`, `message-actions`, `system-message`,
104
+ `typing-indicator`. (Generic role names; stateful variants via space-separated
105
+ second names where applicable.)
106
+
107
+ ### 5. Markdown (E)
108
+ - Add `format?: 'text' | 'markdown'` to `ChatMessage`.
109
+ - New boolean attribute `markdown` — component-wide default.
110
+ - A message renders as markdown when `message.format === 'markdown'`, or when the
111
+ `markdown` attribute is set and `message.format !== 'text'` (per-message `'text'`
112
+ overrides the component default).
113
+ - Markdown rendered through the existing `<snice-markdown>` component; import follows
114
+ the existing `import '../empty-state/snice-empty-state'` precedent. Off by default.
115
+
116
+ ### Types
117
+ - `ChatMessage` gains `format?: 'text' | 'markdown'`.
118
+ - New `SniceChatMessageElement` interface + `SniceChatMessageEventMap`.
119
+ - `snice-chat` gains `authorColors`, `markdown`, `colorAuthors`, `layout` on its element interface.
120
+
121
+ ## Deliverables
122
+
123
+ - Source: the new element (3 files) + additive edits to `snice-chat.ts`, `.types.ts`, `.css`.
124
+ - React adapter: metadata for `snice-chat` (new props) and new `snice-chat-message` in
125
+ `scripts/generate-react-adapters.js`; regenerate adapters + tests.
126
+ - Tests: unit tests for both elements (see Verification).
127
+ - Docs: `docs/components/chat.md` and `docs/ai/components/chat.md` updated to mirror —
128
+ new properties, attributes, parts, the sub-element, markdown, layout. Behavior + API
129
+ only; no internal symbol names or framework plumbing in the prose.
130
+ - Showcase: update `public/showcases/chat.html` to demo the new capabilities.
131
+
132
+ ## Verification (required before calling done)
133
+
134
+ - **Tests for everything authored.** Cover: dual-API ingestion (array, slot, both →
135
+ slot wins), boundary cases (no messages, one, many), author-color resolution
136
+ (map / auto / default / `color-authors` off), own/other part names, markdown
137
+ on/off and per-message override, all new parts present, default render unchanged.
138
+ - **Full suite:** `npm test` — the whole vitest suite, not a filtered path. Every
139
+ failure is in scope to fix; no "pre-existing" excuses.
140
+ - **Visual confirmation of all authored code** — exercise the live component in the
141
+ browser (showcase/demo), in **both dark and light** (Snice defaults to dark). Confirm:
142
+ default render unchanged, per-user colors, bubble layout, markdown, system messages,
143
+ reactions. Visual defects are bugs, not "polish later".
144
+
145
+ ## Key design decisions
146
+
147
+ 1. **Sub-element is a config carrier, not self-rendering** — mirrors `snice-column`.
148
+ Keeps the part surface on the parent's shadow DOM (flat `::part`, no `exportparts`).
149
+ 2. **Auto-coloring is opt-in (`color-authors`), not on by default** — preserves the
150
+ byte-for-byte-unchanged default render. `authorColors` map always wins over auto.
151
+ 3. **Per-author color via inline `--snice-chat-author-color`, not `data-*`** — matches
152
+ the snice dynamic-per-item idiom; `data-*` in snice are behavioral/JS hooks only.
153
+ 4. **Own/other via space-separated part names**, matching `part="button first-button"`.
154
+ 5. **Markdown reuses `<snice-markdown>`**, imported like the existing empty-state import.
155
+ 6. **CDN bundling of the sub-element is out of scope** by explicit instruction.