snice 5.1.0 → 5.2.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 (305) hide show
  1. package/adapters/react/SniceProvider.js +1 -1
  2. package/adapters/react/SniceRouter.js +1 -1
  3. package/adapters/react/matchRoute.js +1 -1
  4. package/adapters/react/useRequestHandler.js +1 -1
  5. package/dist/cdn/accordion/snice-accordion.js +1 -1
  6. package/dist/cdn/accordion/snice-accordion.min.js +1 -1
  7. package/dist/cdn/action-bar/snice-action-bar.js +1 -1
  8. package/dist/cdn/action-bar/snice-action-bar.min.js +1 -1
  9. package/dist/cdn/activity-feed/snice-activity-feed.js +1 -1
  10. package/dist/cdn/activity-feed/snice-activity-feed.min.js +1 -1
  11. package/dist/cdn/alert/snice-alert.js +1 -1
  12. package/dist/cdn/alert/snice-alert.min.js +1 -1
  13. package/dist/cdn/app-tiles/snice-app-tiles.js +1 -1
  14. package/dist/cdn/app-tiles/snice-app-tiles.min.js +1 -1
  15. package/dist/cdn/approval-flow/snice-approval-flow.js +1 -1
  16. package/dist/cdn/approval-flow/snice-approval-flow.min.js +1 -1
  17. package/dist/cdn/audio-recorder/snice-audio-recorder.js +1 -1
  18. package/dist/cdn/audio-recorder/snice-audio-recorder.min.js +1 -1
  19. package/dist/cdn/availability/snice-availability.js +1 -1
  20. package/dist/cdn/availability/snice-availability.min.js +1 -1
  21. package/dist/cdn/avatar/snice-avatar.js +1 -1
  22. package/dist/cdn/avatar/snice-avatar.min.js +1 -1
  23. package/dist/cdn/avatar-group/snice-avatar-group.js +1 -1
  24. package/dist/cdn/avatar-group/snice-avatar-group.min.js +1 -1
  25. package/dist/cdn/badge/snice-badge.js +1 -1
  26. package/dist/cdn/badge/snice-badge.min.js +1 -1
  27. package/dist/cdn/banner/snice-banner.js +1 -1
  28. package/dist/cdn/banner/snice-banner.min.js +1 -1
  29. package/dist/cdn/binpack/snice-binpack.js +1 -1
  30. package/dist/cdn/binpack/snice-binpack.min.js +1 -1
  31. package/dist/cdn/book/snice-book.js +1 -1
  32. package/dist/cdn/book/snice-book.min.js +1 -1
  33. package/dist/cdn/booking/snice-booking.js +1 -1
  34. package/dist/cdn/booking/snice-booking.min.js +1 -1
  35. package/dist/cdn/breadcrumbs/snice-breadcrumbs.js +1 -1
  36. package/dist/cdn/breadcrumbs/snice-breadcrumbs.min.js +1 -1
  37. package/dist/cdn/button/snice-button.js +1 -1
  38. package/dist/cdn/button/snice-button.min.js +1 -1
  39. package/dist/cdn/calendar/snice-calendar.js +1 -1
  40. package/dist/cdn/calendar/snice-calendar.min.js +1 -1
  41. package/dist/cdn/camera/snice-camera.js +1 -1
  42. package/dist/cdn/camera/snice-camera.min.js +1 -1
  43. package/dist/cdn/camera-annotate/snice-camera-annotate.js +1 -1
  44. package/dist/cdn/camera-annotate/snice-camera-annotate.min.js +1 -1
  45. package/dist/cdn/candlestick/snice-candlestick.js +1 -1
  46. package/dist/cdn/candlestick/snice-candlestick.min.js +1 -1
  47. package/dist/cdn/card/snice-card.js +1 -1
  48. package/dist/cdn/card/snice-card.min.js +1 -1
  49. package/dist/cdn/carousel/snice-carousel.js +1 -1
  50. package/dist/cdn/carousel/snice-carousel.min.js +1 -1
  51. package/dist/cdn/cart/snice-cart.js +1 -1
  52. package/dist/cdn/cart/snice-cart.min.js +1 -1
  53. package/dist/cdn/chart/snice-chart.js +1 -1
  54. package/dist/cdn/chart/snice-chart.min.js +1 -1
  55. package/dist/cdn/chat/snice-chat.js +1 -1
  56. package/dist/cdn/chat/snice-chat.min.js +1 -1
  57. package/dist/cdn/checkbox/snice-checkbox.js +1 -1
  58. package/dist/cdn/checkbox/snice-checkbox.min.js +1 -1
  59. package/dist/cdn/chip/snice-chip.js +1 -1
  60. package/dist/cdn/chip/snice-chip.min.js +1 -1
  61. package/dist/cdn/code-block/snice-code-block.js +1 -1
  62. package/dist/cdn/code-block/snice-code-block.min.js +1 -1
  63. package/dist/cdn/color-display/snice-color-display.js +1 -1
  64. package/dist/cdn/color-display/snice-color-display.min.js +1 -1
  65. package/dist/cdn/color-picker/snice-color-picker.js +1 -1
  66. package/dist/cdn/color-picker/snice-color-picker.min.js +1 -1
  67. package/dist/cdn/command-palette/snice-command-palette.js +1 -1
  68. package/dist/cdn/command-palette/snice-command-palette.min.js +1 -1
  69. package/dist/cdn/comments/snice-comments.js +1 -1
  70. package/dist/cdn/comments/snice-comments.min.js +1 -1
  71. package/dist/cdn/countdown/snice-countdown.js +1 -1
  72. package/dist/cdn/countdown/snice-countdown.min.js +1 -1
  73. package/dist/cdn/cropper/snice-cropper.js +1 -1
  74. package/dist/cdn/cropper/snice-cropper.min.js +1 -1
  75. package/dist/cdn/data-card/snice-data-card.js +1 -1
  76. package/dist/cdn/data-card/snice-data-card.min.js +1 -1
  77. package/dist/cdn/date-picker/snice-date-picker.js +1 -1
  78. package/dist/cdn/date-picker/snice-date-picker.min.js +1 -1
  79. package/dist/cdn/date-range-picker/snice-date-range-picker.js +1 -1
  80. package/dist/cdn/date-range-picker/snice-date-range-picker.min.js +1 -1
  81. package/dist/cdn/date-time-picker/snice-date-time-picker.js +1 -1
  82. package/dist/cdn/date-time-picker/snice-date-time-picker.min.js +1 -1
  83. package/dist/cdn/diff/snice-diff.js +1 -1
  84. package/dist/cdn/diff/snice-diff.min.js +1 -1
  85. package/dist/cdn/divider/snice-divider.js +1 -1
  86. package/dist/cdn/divider/snice-divider.min.js +1 -1
  87. package/dist/cdn/doc/snice-doc.js +1 -1
  88. package/dist/cdn/doc/snice-doc.min.js +1 -1
  89. package/dist/cdn/draw/snice-draw.js +1 -1
  90. package/dist/cdn/draw/snice-draw.min.js +1 -1
  91. package/dist/cdn/drawer/snice-drawer.js +1 -1
  92. package/dist/cdn/drawer/snice-drawer.min.js +1 -1
  93. package/dist/cdn/empty-state/snice-empty-state.js +1 -1
  94. package/dist/cdn/empty-state/snice-empty-state.min.js +1 -1
  95. package/dist/cdn/estimate/snice-estimate.js +1 -1
  96. package/dist/cdn/estimate/snice-estimate.min.js +1 -1
  97. package/dist/cdn/file-gallery/snice-file-gallery.js +1 -1
  98. package/dist/cdn/file-gallery/snice-file-gallery.min.js +1 -1
  99. package/dist/cdn/file-upload/snice-file-upload.js +1 -1
  100. package/dist/cdn/file-upload/snice-file-upload.min.js +1 -1
  101. package/dist/cdn/flip-card/snice-flip-card.js +1 -1
  102. package/dist/cdn/flip-card/snice-flip-card.min.js +1 -1
  103. package/dist/cdn/flow/snice-flow.js +1 -1
  104. package/dist/cdn/flow/snice-flow.min.js +1 -1
  105. package/dist/cdn/form-layout/snice-form-layout.js +1 -1
  106. package/dist/cdn/form-layout/snice-form-layout.min.js +1 -1
  107. package/dist/cdn/funnel/snice-funnel.js +1 -1
  108. package/dist/cdn/funnel/snice-funnel.min.js +1 -1
  109. package/dist/cdn/gantt/snice-gantt.js +1 -1
  110. package/dist/cdn/gantt/snice-gantt.min.js +1 -1
  111. package/dist/cdn/gauge/snice-gauge.js +1 -1
  112. package/dist/cdn/gauge/snice-gauge.min.js +1 -1
  113. package/dist/cdn/grid/snice-grid.js +1 -1
  114. package/dist/cdn/grid/snice-grid.min.js +1 -1
  115. package/dist/cdn/heatmap/snice-heatmap.js +1 -1
  116. package/dist/cdn/heatmap/snice-heatmap.min.js +1 -1
  117. package/dist/cdn/image/snice-image.js +1 -1
  118. package/dist/cdn/image/snice-image.min.js +1 -1
  119. package/dist/cdn/input/snice-input.js +1 -1
  120. package/dist/cdn/input/snice-input.min.js +1 -1
  121. package/dist/cdn/invoice/snice-invoice.js +1 -1
  122. package/dist/cdn/invoice/snice-invoice.min.js +1 -1
  123. package/dist/cdn/kanban/snice-kanban.js +1 -1
  124. package/dist/cdn/kanban/snice-kanban.min.js +1 -1
  125. package/dist/cdn/key-value/snice-key-value.js +1 -1
  126. package/dist/cdn/key-value/snice-key-value.min.js +1 -1
  127. package/dist/cdn/kpi/snice-kpi.js +1 -1
  128. package/dist/cdn/kpi/snice-kpi.min.js +1 -1
  129. package/dist/cdn/layout/snice-layout.js +1 -1
  130. package/dist/cdn/layout/snice-layout.min.js +1 -1
  131. package/dist/cdn/leaderboard/snice-leaderboard.js +1 -1
  132. package/dist/cdn/leaderboard/snice-leaderboard.min.js +1 -1
  133. package/dist/cdn/link/snice-link.js +1 -1
  134. package/dist/cdn/link/snice-link.min.js +1 -1
  135. package/dist/cdn/link-preview/snice-link-preview.js +1 -1
  136. package/dist/cdn/link-preview/snice-link-preview.min.js +1 -1
  137. package/dist/cdn/list/snice-list.js +1 -1
  138. package/dist/cdn/list/snice-list.min.js +1 -1
  139. package/dist/cdn/location/snice-location.js +1 -1
  140. package/dist/cdn/location/snice-location.min.js +1 -1
  141. package/dist/cdn/login/snice-login.js +1 -1
  142. package/dist/cdn/login/snice-login.min.js +1 -1
  143. package/dist/cdn/map/snice-map.js +1 -1
  144. package/dist/cdn/map/snice-map.min.js +1 -1
  145. package/dist/cdn/markdown/snice-markdown.js +1 -1
  146. package/dist/cdn/markdown/snice-markdown.min.js +1 -1
  147. package/dist/cdn/masonry/snice-masonry.js +1 -1
  148. package/dist/cdn/masonry/snice-masonry.min.js +1 -1
  149. package/dist/cdn/menu/snice-menu.js +1 -1
  150. package/dist/cdn/menu/snice-menu.min.js +1 -1
  151. package/dist/cdn/message-strip/snice-message-strip.js +1 -1
  152. package/dist/cdn/message-strip/snice-message-strip.min.js +1 -1
  153. package/dist/cdn/metric-table/snice-metric-table.js +1 -1
  154. package/dist/cdn/metric-table/snice-metric-table.min.js +1 -1
  155. package/dist/cdn/modal/snice-modal.js +1 -1
  156. package/dist/cdn/modal/snice-modal.min.js +1 -1
  157. package/dist/cdn/music-player/snice-music-player.js +1 -1
  158. package/dist/cdn/music-player/snice-music-player.min.js +1 -1
  159. package/dist/cdn/nav/snice-nav.js +1 -1
  160. package/dist/cdn/nav/snice-nav.min.js +1 -1
  161. package/dist/cdn/network-graph/snice-network-graph.js +1 -1
  162. package/dist/cdn/network-graph/snice-network-graph.min.js +1 -1
  163. package/dist/cdn/notification-center/snice-notification-center.js +1 -1
  164. package/dist/cdn/notification-center/snice-notification-center.min.js +1 -1
  165. package/dist/cdn/order-tracker/snice-order-tracker.js +1 -1
  166. package/dist/cdn/order-tracker/snice-order-tracker.min.js +1 -1
  167. package/dist/cdn/org-chart/snice-org-chart.js +1 -1
  168. package/dist/cdn/org-chart/snice-org-chart.min.js +1 -1
  169. package/dist/cdn/pagination/snice-pagination.js +1 -1
  170. package/dist/cdn/pagination/snice-pagination.min.js +1 -1
  171. package/dist/cdn/paint/snice-paint.js +1 -1
  172. package/dist/cdn/paint/snice-paint.min.js +1 -1
  173. package/dist/cdn/pdf-viewer/snice-pdf-viewer.js +1 -1
  174. package/dist/cdn/pdf-viewer/snice-pdf-viewer.min.js +1 -1
  175. package/dist/cdn/permission-matrix/snice-permission-matrix.js +1 -1
  176. package/dist/cdn/permission-matrix/snice-permission-matrix.min.js +1 -1
  177. package/dist/cdn/podcast-player/snice-podcast-player.js +1 -1
  178. package/dist/cdn/podcast-player/snice-podcast-player.min.js +1 -1
  179. package/dist/cdn/popover/snice-popover.js +1 -1
  180. package/dist/cdn/popover/snice-popover.min.js +1 -1
  181. package/dist/cdn/pricing-table/snice-pricing-table.js +1 -1
  182. package/dist/cdn/pricing-table/snice-pricing-table.min.js +1 -1
  183. package/dist/cdn/product-card/snice-product-card.js +1 -1
  184. package/dist/cdn/product-card/snice-product-card.min.js +1 -1
  185. package/dist/cdn/progress/snice-progress.js +1 -1
  186. package/dist/cdn/progress/snice-progress.min.js +1 -1
  187. package/dist/cdn/progress-ring/snice-progress-ring.js +1 -1
  188. package/dist/cdn/progress-ring/snice-progress-ring.min.js +1 -1
  189. package/dist/cdn/qr-code/snice-qr-code.js +1 -1
  190. package/dist/cdn/qr-code/snice-qr-code.min.js +1 -1
  191. package/dist/cdn/qr-reader/snice-qr-reader.js +1 -1
  192. package/dist/cdn/qr-reader/snice-qr-reader.min.js +1 -1
  193. package/dist/cdn/radio/snice-radio.js +1 -1
  194. package/dist/cdn/radio/snice-radio.min.js +1 -1
  195. package/dist/cdn/range-slider/snice-range-slider.js +1 -1
  196. package/dist/cdn/range-slider/snice-range-slider.min.js +1 -1
  197. package/dist/cdn/rating/snice-rating.js +1 -1
  198. package/dist/cdn/rating/snice-rating.min.js +1 -1
  199. package/dist/cdn/receipt/snice-receipt.js +1 -1
  200. package/dist/cdn/receipt/snice-receipt.min.js +1 -1
  201. package/dist/cdn/recipe/snice-recipe.js +1 -1
  202. package/dist/cdn/recipe/snice-recipe.min.js +1 -1
  203. package/dist/cdn/runtime/snice-runtime.esm.js +220 -205
  204. package/dist/cdn/runtime/snice-runtime.esm.js.map +1 -1
  205. package/dist/cdn/runtime/snice-runtime.esm.min.js +8 -8
  206. package/dist/cdn/runtime/snice-runtime.esm.min.js.map +1 -1
  207. package/dist/cdn/runtime/snice-runtime.js +220 -205
  208. package/dist/cdn/runtime/snice-runtime.js.map +1 -1
  209. package/dist/cdn/runtime/snice-runtime.min.js +8 -8
  210. package/dist/cdn/runtime/snice-runtime.min.js.map +1 -1
  211. package/dist/cdn/sankey/snice-sankey.js +1 -1
  212. package/dist/cdn/sankey/snice-sankey.min.js +1 -1
  213. package/dist/cdn/segmented-control/snice-segmented-control.js +1 -1
  214. package/dist/cdn/segmented-control/snice-segmented-control.min.js +1 -1
  215. package/dist/cdn/select/snice-select.js +1 -1
  216. package/dist/cdn/select/snice-select.min.js +1 -1
  217. package/dist/cdn/skeleton/snice-skeleton.js +1 -1
  218. package/dist/cdn/skeleton/snice-skeleton.min.js +1 -1
  219. package/dist/cdn/slider/snice-slider.js +1 -1
  220. package/dist/cdn/slider/snice-slider.min.js +1 -1
  221. package/dist/cdn/sortable/snice-sortable.js +1 -1
  222. package/dist/cdn/sortable/snice-sortable.min.js +1 -1
  223. package/dist/cdn/sparkline/snice-sparkline.js +1 -1
  224. package/dist/cdn/sparkline/snice-sparkline.min.js +1 -1
  225. package/dist/cdn/spinner/snice-spinner.js +1 -1
  226. package/dist/cdn/spinner/snice-spinner.min.js +1 -1
  227. package/dist/cdn/split-button/snice-split-button.js +1 -1
  228. package/dist/cdn/split-button/snice-split-button.min.js +1 -1
  229. package/dist/cdn/split-pane/snice-split-pane.js +1 -1
  230. package/dist/cdn/split-pane/snice-split-pane.min.js +1 -1
  231. package/dist/cdn/spotlight/snice-spotlight.js +1 -1
  232. package/dist/cdn/spotlight/snice-spotlight.min.js +1 -1
  233. package/dist/cdn/stat-group/snice-stat-group.js +1 -1
  234. package/dist/cdn/stat-group/snice-stat-group.min.js +1 -1
  235. package/dist/cdn/step-input/snice-step-input.js +1 -1
  236. package/dist/cdn/step-input/snice-step-input.min.js +1 -1
  237. package/dist/cdn/stepper/snice-stepper.js +1 -1
  238. package/dist/cdn/stepper/snice-stepper.min.js +1 -1
  239. package/dist/cdn/switch/snice-switch.js +1 -1
  240. package/dist/cdn/switch/snice-switch.min.js +1 -1
  241. package/dist/cdn/table/snice-table.js +1 -1
  242. package/dist/cdn/table/snice-table.min.js +1 -1
  243. package/dist/cdn/tabs/snice-tabs.js +1 -1
  244. package/dist/cdn/tabs/snice-tabs.min.js +1 -1
  245. package/dist/cdn/tag/snice-tag.js +1 -1
  246. package/dist/cdn/tag/snice-tag.min.js +1 -1
  247. package/dist/cdn/tag-input/snice-tag-input.js +1 -1
  248. package/dist/cdn/tag-input/snice-tag-input.min.js +1 -1
  249. package/dist/cdn/terminal/snice-terminal.js +1 -1
  250. package/dist/cdn/terminal/snice-terminal.min.js +1 -1
  251. package/dist/cdn/testimonial/snice-testimonial.js +1 -1
  252. package/dist/cdn/testimonial/snice-testimonial.min.js +1 -1
  253. package/dist/cdn/textarea/snice-textarea.js +1 -1
  254. package/dist/cdn/textarea/snice-textarea.min.js +1 -1
  255. package/dist/cdn/time-picker/snice-time-picker.js +1 -1
  256. package/dist/cdn/time-picker/snice-time-picker.min.js +1 -1
  257. package/dist/cdn/time-range-picker/snice-time-range-picker.js +1 -1
  258. package/dist/cdn/time-range-picker/snice-time-range-picker.min.js +1 -1
  259. package/dist/cdn/timeline/snice-timeline.js +1 -1
  260. package/dist/cdn/timeline/snice-timeline.min.js +1 -1
  261. package/dist/cdn/timer/snice-timer.js +1 -1
  262. package/dist/cdn/timer/snice-timer.min.js +1 -1
  263. package/dist/cdn/toast/snice-toast.js +1 -1
  264. package/dist/cdn/toast/snice-toast.min.js +1 -1
  265. package/dist/cdn/tooltip/snice-tooltip.js +1 -1
  266. package/dist/cdn/tooltip/snice-tooltip.min.js +1 -1
  267. package/dist/cdn/tree/snice-tree.js +1 -1
  268. package/dist/cdn/tree/snice-tree.min.js +1 -1
  269. package/dist/cdn/treemap/snice-treemap.js +1 -1
  270. package/dist/cdn/treemap/snice-treemap.min.js +1 -1
  271. package/dist/cdn/user-card/snice-user-card.js +1 -1
  272. package/dist/cdn/user-card/snice-user-card.min.js +1 -1
  273. package/dist/cdn/video-player/snice-video-player.js +1 -1
  274. package/dist/cdn/video-player/snice-video-player.min.js +1 -1
  275. package/dist/cdn/virtual-scroller/snice-virtual-scroller.js +1 -1
  276. package/dist/cdn/virtual-scroller/snice-virtual-scroller.min.js +1 -1
  277. package/dist/cdn/waterfall/snice-waterfall.js +1 -1
  278. package/dist/cdn/waterfall/snice-waterfall.min.js +1 -1
  279. package/dist/cdn/weather/snice-weather.js +1 -1
  280. package/dist/cdn/weather/snice-weather.min.js +1 -1
  281. package/dist/cdn/work-order/snice-work-order.js +1 -1
  282. package/dist/cdn/work-order/snice-work-order.min.js +1 -1
  283. package/dist/context.d.ts +2 -2
  284. package/dist/index.cjs +217 -202
  285. package/dist/index.cjs.map +1 -1
  286. package/dist/index.esm.js +217 -202
  287. package/dist/index.esm.js.map +1 -1
  288. package/dist/index.iife.js +217 -202
  289. package/dist/index.iife.js.map +1 -1
  290. package/dist/react/SniceProvider.js +1 -1
  291. package/dist/react/SniceRouter.js +1 -1
  292. package/dist/react/index.js +1 -1
  293. package/dist/react/matchRoute.js +1 -1
  294. package/dist/react/useRequestHandler.js +1 -1
  295. package/dist/symbols.cjs +1 -1
  296. package/dist/symbols.esm.js +1 -1
  297. package/dist/transitions.cjs +1 -1
  298. package/dist/transitions.esm.js +1 -1
  299. package/docs/STORYBOOK.md +1 -1
  300. package/docs/ai/api.md +4 -5
  301. package/docs/ai/decorators.md +2 -2
  302. package/docs/components/drawer.md +1 -1
  303. package/docs/elements.md +1 -1
  304. package/docs/routing.md +1 -1
  305. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v5.0.0
2
+ * snice v5.1.0
3
3
  * A decorator-driven web component library with differential rendering, routing, controllers, and 130+ ready-made UI components. Use as much or as little as you want. Zero dependencies, works anywhere.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -2681,6 +2681,208 @@ function cleanupEventHandlers(instance) {
2681
2681
  instance[CLEANUP].events = [];
2682
2682
  }
2683
2683
 
2684
+ /**
2685
+ * @context decorator for receiving router context updates
2686
+ */
2687
+ const CONTEXT_HANDLERS = getSymbol('context-handlers');
2688
+ /**
2689
+ * @context decorator for receiving router context updates
2690
+ *
2691
+ * Works on both methods and fields:
2692
+ *
2693
+ * - **Method form**: the method is invoked with the current Context on every
2694
+ * update (and once at register time so the first render sees the context).
2695
+ * - **Field form**: the field is overwritten with the current Context on
2696
+ * every update (and once at register time). Pair with `@property` if you
2697
+ * want assignment to also schedule a re-render.
2698
+ *
2699
+ * @example
2700
+ * ```typescript
2701
+ * @element('my-layout')
2702
+ * class MyLayout extends HTMLElement {
2703
+ * // Method form
2704
+ * @context()
2705
+ * handleContext(ctx: Context) {
2706
+ * this.renderNav(ctx.navigation.placards, ctx.navigation.route);
2707
+ * }
2708
+ *
2709
+ * // Field form — the field is populated before first render
2710
+ * @context() ctx!: Context;
2711
+ *
2712
+ * // Field + @property — assignment also triggers re-render
2713
+ * @property({ attribute: false }) @context() reactiveCtx!: Context;
2714
+ * }
2715
+ * ```
2716
+ */
2717
+ function context$1(options = {}) {
2718
+ return function (value, decoratorContext) {
2719
+ const name = decoratorContext.name;
2720
+ const kind = decoratorContext.kind;
2721
+ const registerHandler = function () {
2722
+ const constructor = this.constructor;
2723
+ // De-dupe: methods identify by reference, fields identify by name.
2724
+ if (!Object.prototype.hasOwnProperty.call(constructor, CONTEXT_METHODS)) {
2725
+ constructor[CONTEXT_METHODS] = new Set();
2726
+ }
2727
+ const dedupeKey = kind === 'method' ? value : `field:${name}`;
2728
+ if (constructor[CONTEXT_METHODS].has(dedupeKey))
2729
+ return;
2730
+ constructor[CONTEXT_METHODS].add(dedupeKey);
2731
+ if (!Object.prototype.hasOwnProperty.call(constructor, CONTEXT_HANDLERS)) {
2732
+ const inherited = constructor[CONTEXT_HANDLERS];
2733
+ constructor[CONTEXT_HANDLERS] = inherited ? [...inherited] : [];
2734
+ }
2735
+ if (kind === 'method') {
2736
+ constructor[CONTEXT_HANDLERS].push({
2737
+ kind: 'method',
2738
+ methodName: name,
2739
+ method: value,
2740
+ options,
2741
+ });
2742
+ }
2743
+ else if (kind === 'field' || kind === 'accessor') {
2744
+ constructor[CONTEXT_HANDLERS].push({
2745
+ kind: 'field',
2746
+ fieldName: name,
2747
+ options,
2748
+ });
2749
+ }
2750
+ };
2751
+ if (kind === 'method') {
2752
+ decoratorContext.addInitializer(registerHandler);
2753
+ return value;
2754
+ }
2755
+ // Field decorators: do registration via the init function (fires per
2756
+ // instance during construction, with `this` bound). Returning the init
2757
+ // function is the canonical Stage 3 way for field decorators —
2758
+ // `addInitializer` for fields can be late or unreliable across runtimes.
2759
+ return function (initialValue) {
2760
+ registerHandler.call(this);
2761
+ return initialValue;
2762
+ };
2763
+ };
2764
+ }
2765
+ /**
2766
+ * Setup context handler for an element instance
2767
+ * Called automatically during element connection
2768
+ */
2769
+ // Accepts an HTMLElement OR a controller instance — both are plain objects
2770
+ // that may carry CONTEXT_HANDLER and a constructor with CONTEXT_HANDLERS.
2771
+ function setupContextHandler(element) {
2772
+ const handlers = element.constructor[CONTEXT_HANDLERS];
2773
+ if (!handlers || !Array.isArray(handlers) || handlers.length === 0) {
2774
+ return;
2775
+ }
2776
+ // Get the Context instance from the router
2777
+ const ctx = element[CONTEXT_HANDLER];
2778
+ if (!ctx) {
2779
+ return;
2780
+ }
2781
+ // Store the Context instance for cleanup
2782
+ element[NAVIGATION_CONTEXT_INSTANCE] = ctx;
2783
+ // Per-element Map of handler-name → wrapped function. Symbol-keyed so it
2784
+ // doesn't pollute the element's public surface.
2785
+ let wrapped = element[WRAPPED_CONTEXT_HANDLERS];
2786
+ if (!wrapped) {
2787
+ wrapped = new Map();
2788
+ element[WRAPPED_CONTEXT_HANDLERS] = wrapped;
2789
+ }
2790
+ // Register each handler with the Context
2791
+ for (const handler of handlers) {
2792
+ const { kind, options } = handler;
2793
+ const handlerName = kind === 'field' ? handler.fieldName : handler.methodName;
2794
+ // Create wrapped method with timing controls
2795
+ const wrappedFn = function (context) {
2796
+ // Skip if already called once
2797
+ if (options.once && element[CONTEXT_CALLED]) {
2798
+ return;
2799
+ }
2800
+ const callMethod = () => {
2801
+ if (kind === 'field') {
2802
+ element[handler.fieldName] = context;
2803
+ }
2804
+ else {
2805
+ handler.method.call(element, context);
2806
+ }
2807
+ // Handle once option
2808
+ if (options.once) {
2809
+ element[CONTEXT_CALLED] = true;
2810
+ // Unregister after first call
2811
+ const ctx = element[NAVIGATION_CONTEXT_INSTANCE];
2812
+ if (ctx && typeof ctx[CONTEXT_UNREGISTER] === 'function') {
2813
+ ctx[CONTEXT_UNREGISTER](element);
2814
+ }
2815
+ }
2816
+ };
2817
+ // Per-handler timer slot to avoid debounce/throttle handlers on the same
2818
+ // element overwriting each other's state.
2819
+ const timerSlot = element[CONTEXT_TIMER] ||
2820
+ (element[CONTEXT_TIMER] = {});
2821
+ const timerKey = handlerName;
2822
+ if (options.debounce) {
2823
+ clearTimeout(timerSlot[timerKey]?.timeout);
2824
+ timerSlot[timerKey] = {
2825
+ timeout: setTimeout(callMethod, options.debounce),
2826
+ };
2827
+ return;
2828
+ }
2829
+ if (options.throttle) {
2830
+ const now = Date.now();
2831
+ const lastCall = timerSlot[timerKey]?.lastCall || 0;
2832
+ if (now - lastCall >= options.throttle) {
2833
+ timerSlot[timerKey] = { lastCall: now };
2834
+ callMethod();
2835
+ }
2836
+ return;
2837
+ }
2838
+ callMethod();
2839
+ };
2840
+ wrapped.set(handlerName, wrappedFn);
2841
+ // Register with the Context using the handler name (lookup goes through
2842
+ // the WRAPPED_CONTEXT_HANDLERS Map on the element).
2843
+ if (typeof ctx[CONTEXT_REGISTER] === 'function') {
2844
+ ctx[CONTEXT_REGISTER](element, handlerName);
2845
+ }
2846
+ // Synchronously emit current context to the just-registered handler so
2847
+ // field/method values are populated BEFORE the first render microtask
2848
+ // flushes — eliminates the cold-render flicker where ctx is undefined.
2849
+ try {
2850
+ wrappedFn(ctx);
2851
+ }
2852
+ catch (error) {
2853
+ console.error(`Error invoking @context handler at registration:`, error);
2854
+ }
2855
+ }
2856
+ }
2857
+ /**
2858
+ * Cleanup context handler for an element instance
2859
+ * Called automatically during element disconnection
2860
+ */
2861
+ function cleanupContextHandler(element) {
2862
+ const handlers = element.constructor[CONTEXT_HANDLERS];
2863
+ if (!handlers || !Array.isArray(handlers) || handlers.length === 0) {
2864
+ return;
2865
+ }
2866
+ // Clear any pending debounce timers (per-handler slots)
2867
+ const timerSlot = element[CONTEXT_TIMER];
2868
+ if (timerSlot && typeof timerSlot === 'object') {
2869
+ for (const key of Object.keys(timerSlot)) {
2870
+ if (timerSlot[key]?.timeout)
2871
+ clearTimeout(timerSlot[key].timeout);
2872
+ }
2873
+ delete element[CONTEXT_TIMER];
2874
+ }
2875
+ // Drop the per-element wrapped-handlers Map.
2876
+ delete element[WRAPPED_CONTEXT_HANDLERS];
2877
+ // Unregister from Context if available
2878
+ const ctx = element[NAVIGATION_CONTEXT_INSTANCE];
2879
+ if (ctx && typeof ctx[CONTEXT_UNREGISTER] === 'function') {
2880
+ ctx[CONTEXT_UNREGISTER](element);
2881
+ }
2882
+ delete element[NAVIGATION_CONTEXT_INSTANCE];
2883
+ delete element[CONTEXT_CALLED];
2884
+ }
2885
+
2684
2886
  // Controller-scoped cleanup registry
2685
2887
  class ControllerScope {
2686
2888
  constructor() {
@@ -2786,6 +2988,14 @@ async function attachController(element, controllerName) {
2786
2988
  if (routerContext !== undefined) {
2787
2989
  controllerInstance[ROUTER_CONTEXT] = routerContext;
2788
2990
  }
2991
+ // Mirror the element's CONTEXT_HANDLER onto the controller so
2992
+ // setupContextHandler can wire @context() handlers declared on the
2993
+ // controller class. This makes @context() work identically on elements
2994
+ // and controllers.
2995
+ const ctxHandler = element[CONTEXT_HANDLER];
2996
+ if (ctxHandler !== undefined) {
2997
+ controllerInstance[CONTEXT_HANDLER] = ctxHandler;
2998
+ }
2789
2999
  // Store references
2790
3000
  element[CONTROLLER_KEY] = controllerInstance;
2791
3001
  element[CONTROLLER_NAME_KEY] = controllerName;
@@ -2824,6 +3034,8 @@ async function attachController(element, controllerName) {
2824
3034
  setupResponseHandlers(controllerInstance, element);
2825
3035
  // Setup @on event handlers for controller
2826
3036
  setupEventHandlers(controllerInstance, element);
3037
+ // Setup @context() handlers for controller (fires sync emit at register)
3038
+ setupContextHandler(controllerInstance);
2827
3039
  element.dispatchEvent(new CustomEvent('controller-attached', {
2828
3040
  detail: { name: controllerName, controller: controllerInstance }
2829
3041
  }));
@@ -2860,12 +3072,15 @@ async function detachController(element) {
2860
3072
  cleanupResponseHandlers(controllerInstance);
2861
3073
  // Cleanup @on event handlers for controller
2862
3074
  cleanupEventHandlers(controllerInstance);
3075
+ // Cleanup @context() handlers for controller
3076
+ cleanupContextHandler(controllerInstance);
2863
3077
  // Cleanup the controller scope
2864
3078
  if (scope) {
2865
3079
  await scope.cleanup();
2866
3080
  }
2867
- // Clean up router context reference
3081
+ // Clean up router/context references
2868
3082
  delete controllerInstance[ROUTER_CONTEXT];
3083
+ delete controllerInstance[CONTEXT_HANDLER];
2869
3084
  delete element[CONTROLLER_KEY];
2870
3085
  delete element[CONTROLLER_NAME_KEY];
2871
3086
  delete element[CONTROLLER_OPERATIONS];
@@ -2960,206 +3175,6 @@ function useNativeElementControllers() {
2960
3175
  globalThis.sniceNativeControllerObserver = observer;
2961
3176
  }
2962
3177
 
2963
- /**
2964
- * @context decorator for receiving router context updates
2965
- */
2966
- const CONTEXT_HANDLERS = getSymbol('context-handlers');
2967
- /**
2968
- * @context decorator for receiving router context updates
2969
- *
2970
- * Works on both methods and fields:
2971
- *
2972
- * - **Method form**: the method is invoked with the current Context on every
2973
- * update (and once at register time so the first render sees the context).
2974
- * - **Field form**: the field is overwritten with the current Context on
2975
- * every update (and once at register time). Pair with `@property` if you
2976
- * want assignment to also schedule a re-render.
2977
- *
2978
- * @example
2979
- * ```typescript
2980
- * @element('my-layout')
2981
- * class MyLayout extends HTMLElement {
2982
- * // Method form
2983
- * @context()
2984
- * handleContext(ctx: Context) {
2985
- * this.renderNav(ctx.navigation.placards, ctx.navigation.route);
2986
- * }
2987
- *
2988
- * // Field form — the field is populated before first render
2989
- * @context() ctx!: Context;
2990
- *
2991
- * // Field + @property — assignment also triggers re-render
2992
- * @property({ attribute: false }) @context() reactiveCtx!: Context;
2993
- * }
2994
- * ```
2995
- */
2996
- function context$1(options = {}) {
2997
- return function (value, decoratorContext) {
2998
- const name = decoratorContext.name;
2999
- const kind = decoratorContext.kind;
3000
- const registerHandler = function () {
3001
- const constructor = this.constructor;
3002
- // De-dupe: methods identify by reference, fields identify by name.
3003
- if (!Object.prototype.hasOwnProperty.call(constructor, CONTEXT_METHODS)) {
3004
- constructor[CONTEXT_METHODS] = new Set();
3005
- }
3006
- const dedupeKey = kind === 'method' ? value : `field:${name}`;
3007
- if (constructor[CONTEXT_METHODS].has(dedupeKey))
3008
- return;
3009
- constructor[CONTEXT_METHODS].add(dedupeKey);
3010
- if (!Object.prototype.hasOwnProperty.call(constructor, CONTEXT_HANDLERS)) {
3011
- const inherited = constructor[CONTEXT_HANDLERS];
3012
- constructor[CONTEXT_HANDLERS] = inherited ? [...inherited] : [];
3013
- }
3014
- if (kind === 'method') {
3015
- constructor[CONTEXT_HANDLERS].push({
3016
- kind: 'method',
3017
- methodName: name,
3018
- method: value,
3019
- options,
3020
- });
3021
- }
3022
- else if (kind === 'field' || kind === 'accessor') {
3023
- constructor[CONTEXT_HANDLERS].push({
3024
- kind: 'field',
3025
- fieldName: name,
3026
- options,
3027
- });
3028
- }
3029
- };
3030
- if (kind === 'method') {
3031
- decoratorContext.addInitializer(registerHandler);
3032
- return value;
3033
- }
3034
- // Field decorators: do registration via the init function (fires per
3035
- // instance during construction, with `this` bound). Returning the init
3036
- // function is the canonical Stage 3 way for field decorators —
3037
- // `addInitializer` for fields can be late or unreliable across runtimes.
3038
- return function (initialValue) {
3039
- registerHandler.call(this);
3040
- return initialValue;
3041
- };
3042
- };
3043
- }
3044
- /**
3045
- * Setup context handler for an element instance
3046
- * Called automatically during element connection
3047
- */
3048
- function setupContextHandler(element) {
3049
- const handlers = element.constructor[CONTEXT_HANDLERS];
3050
- if (!handlers || !Array.isArray(handlers) || handlers.length === 0) {
3051
- return;
3052
- }
3053
- // Get the Context instance from the router
3054
- const ctx = element[CONTEXT_HANDLER];
3055
- if (!ctx) {
3056
- return;
3057
- }
3058
- // Store the Context instance for cleanup
3059
- element[NAVIGATION_CONTEXT_INSTANCE] = ctx;
3060
- // Per-element Map of handler-name → wrapped function. Symbol-keyed so it
3061
- // doesn't pollute the element's public surface.
3062
- let wrapped = element[WRAPPED_CONTEXT_HANDLERS];
3063
- if (!wrapped) {
3064
- wrapped = new Map();
3065
- element[WRAPPED_CONTEXT_HANDLERS] = wrapped;
3066
- }
3067
- // Register each handler with the Context
3068
- for (const handler of handlers) {
3069
- const { kind, options } = handler;
3070
- const handlerName = kind === 'field' ? handler.fieldName : handler.methodName;
3071
- // Create wrapped method with timing controls
3072
- const wrappedFn = function (context) {
3073
- // Skip if already called once
3074
- if (options.once && element[CONTEXT_CALLED]) {
3075
- return;
3076
- }
3077
- const callMethod = () => {
3078
- if (kind === 'field') {
3079
- element[handler.fieldName] = context;
3080
- }
3081
- else {
3082
- handler.method.call(element, context);
3083
- }
3084
- // Handle once option
3085
- if (options.once) {
3086
- element[CONTEXT_CALLED] = true;
3087
- // Unregister after first call
3088
- const ctx = element[NAVIGATION_CONTEXT_INSTANCE];
3089
- if (ctx && typeof ctx[CONTEXT_UNREGISTER] === 'function') {
3090
- ctx[CONTEXT_UNREGISTER](element);
3091
- }
3092
- }
3093
- };
3094
- // Per-handler timer slot to avoid debounce/throttle handlers on the same
3095
- // element overwriting each other's state.
3096
- const timerSlot = element[CONTEXT_TIMER] ||
3097
- (element[CONTEXT_TIMER] = {});
3098
- const timerKey = handlerName;
3099
- if (options.debounce) {
3100
- clearTimeout(timerSlot[timerKey]?.timeout);
3101
- timerSlot[timerKey] = {
3102
- timeout: setTimeout(callMethod, options.debounce),
3103
- };
3104
- return;
3105
- }
3106
- if (options.throttle) {
3107
- const now = Date.now();
3108
- const lastCall = timerSlot[timerKey]?.lastCall || 0;
3109
- if (now - lastCall >= options.throttle) {
3110
- timerSlot[timerKey] = { lastCall: now };
3111
- callMethod();
3112
- }
3113
- return;
3114
- }
3115
- callMethod();
3116
- };
3117
- wrapped.set(handlerName, wrappedFn);
3118
- // Register with the Context using the handler name (lookup goes through
3119
- // the WRAPPED_CONTEXT_HANDLERS Map on the element).
3120
- if (typeof ctx[CONTEXT_REGISTER] === 'function') {
3121
- ctx[CONTEXT_REGISTER](element, handlerName);
3122
- }
3123
- // Synchronously emit current context to the just-registered handler so
3124
- // field/method values are populated BEFORE the first render microtask
3125
- // flushes — eliminates the cold-render flicker where ctx is undefined.
3126
- try {
3127
- wrappedFn(ctx);
3128
- }
3129
- catch (error) {
3130
- console.error(`Error invoking @context handler at registration:`, error);
3131
- }
3132
- }
3133
- }
3134
- /**
3135
- * Cleanup context handler for an element instance
3136
- * Called automatically during element disconnection
3137
- */
3138
- function cleanupContextHandler(element) {
3139
- const handlers = element.constructor[CONTEXT_HANDLERS];
3140
- if (!handlers || !Array.isArray(handlers) || handlers.length === 0) {
3141
- return;
3142
- }
3143
- // Clear any pending debounce timers (per-handler slots)
3144
- const timerSlot = element[CONTEXT_TIMER];
3145
- if (timerSlot && typeof timerSlot === 'object') {
3146
- for (const key of Object.keys(timerSlot)) {
3147
- if (timerSlot[key]?.timeout)
3148
- clearTimeout(timerSlot[key].timeout);
3149
- }
3150
- delete element[CONTEXT_TIMER];
3151
- }
3152
- // Drop the per-element wrapped-handlers Map.
3153
- delete element[WRAPPED_CONTEXT_HANDLERS];
3154
- // Unregister from Context if available
3155
- const ctx = element[NAVIGATION_CONTEXT_INSTANCE];
3156
- if (ctx && typeof ctx[CONTEXT_UNREGISTER] === 'function') {
3157
- ctx[CONTEXT_UNREGISTER](element);
3158
- }
3159
- delete element[NAVIGATION_CONTEXT_INSTANCE];
3160
- delete element[CONTEXT_CALLED];
3161
- }
3162
-
3163
3178
  /**
3164
3179
  * @render and @styles decorators for Snice v3.0.0
3165
3180
  * Provides automatic differential rendering on property changes