snice 4.29.0 → 4.30.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (516) hide show
  1. package/README.md +3 -10
  2. package/adapters/react/SniceProvider.d.ts +71 -0
  3. package/adapters/react/SniceProvider.js +49 -0
  4. package/adapters/react/SniceProvider.js.map +1 -0
  5. package/adapters/react/SniceRouter.d.ts +44 -0
  6. package/adapters/react/SniceRouter.js +190 -0
  7. package/adapters/react/SniceRouter.js.map +1 -0
  8. package/adapters/react/components.d.ts +2 -0
  9. package/adapters/react/components.d.ts.map +1 -1
  10. package/adapters/react/components.js +1 -0
  11. package/adapters/react/components.js.map +1 -1
  12. package/adapters/react/components.ts +2 -0
  13. package/adapters/react/grid.d.ts +36 -0
  14. package/adapters/react/grid.d.ts.map +1 -0
  15. package/adapters/react/grid.js +24 -0
  16. package/adapters/react/grid.js.map +1 -0
  17. package/adapters/react/grid.tsx +44 -0
  18. package/adapters/react/index.d.ts +5 -0
  19. package/adapters/react/index.d.ts.map +1 -1
  20. package/adapters/react/index.js +3 -2
  21. package/adapters/react/index.js.map +1 -1
  22. package/adapters/react/index.ts +6 -3
  23. package/adapters/react/matchRoute.d.ts +16 -0
  24. package/adapters/react/matchRoute.js +32 -0
  25. package/adapters/react/matchRoute.js.map +1 -0
  26. package/adapters/react/types.d.ts +1 -15
  27. package/adapters/react/types.d.ts.map +1 -1
  28. package/adapters/react/types.ts +1 -15
  29. package/adapters/react/useRequestHandler.js +1 -1
  30. package/adapters/react/useRequestHandler.js.map +1 -1
  31. package/bin/snice.js +8 -13
  32. package/bin/templates/{pwa → default}/index.html +1 -1
  33. package/bin/templates/{pwa → default}/src/components/app-header.ts +36 -18
  34. package/bin/templates/{pwa → default}/src/components/notification-badge.ts +2 -21
  35. package/bin/templates/{pwa → default}/src/components/search-bar.ts +12 -12
  36. package/bin/templates/default/src/context.ts +17 -0
  37. package/bin/templates/{pwa → default}/src/controllers/notification-controller.ts +10 -15
  38. package/bin/templates/{pwa → default}/src/daemons/notifications.ts +0 -12
  39. package/bin/templates/{pwa → default}/src/main.ts +1 -7
  40. package/bin/templates/{pwa → default}/src/middleware/error.ts +1 -8
  41. package/bin/templates/{pwa → default}/src/pages/dashboard.ts +17 -18
  42. package/bin/templates/{pwa → default}/src/pages/data.ts +24 -24
  43. package/bin/templates/{pwa → default}/src/pages/login.ts +3 -6
  44. package/bin/templates/{pwa → default}/src/pages/notifications.ts +21 -19
  45. package/bin/templates/{pwa → default}/src/pages/profile.ts +10 -12
  46. package/bin/templates/{pwa → default}/src/pages/settings.ts +22 -22
  47. package/bin/templates/default/src/router.ts +13 -0
  48. package/bin/templates/default/src/styles/global.css +16 -0
  49. package/bin/templates/{pwa → default}/tsconfig.json +2 -1
  50. package/bin/templates/react/README.md +124 -0
  51. package/bin/templates/react/global.d.ts +10 -0
  52. package/bin/templates/react/index.html +15 -0
  53. package/bin/templates/react/package.json +31 -0
  54. package/bin/templates/react/src/App.tsx +112 -0
  55. package/bin/templates/react/src/components/AppHeader.tsx +85 -0
  56. package/bin/templates/react/src/components/AppLayout.tsx +11 -0
  57. package/bin/templates/react/src/components/NotificationBadge.tsx +13 -0
  58. package/bin/templates/react/src/components/SearchBar.tsx +63 -0
  59. package/bin/templates/react/src/daemons/notifications.ts +136 -0
  60. package/bin/templates/react/src/fetcher.ts +15 -0
  61. package/bin/templates/react/src/guards/auth.ts +6 -0
  62. package/bin/templates/react/src/main.tsx +27 -0
  63. package/bin/templates/react/src/middleware/auth.ts +16 -0
  64. package/bin/templates/react/src/middleware/error.ts +29 -0
  65. package/bin/templates/react/src/middleware/retry.ts +31 -0
  66. package/bin/templates/react/src/pages/DashboardPage.tsx +111 -0
  67. package/bin/templates/react/src/pages/DataPage.tsx +119 -0
  68. package/bin/templates/react/src/pages/LoginPage.tsx +46 -0
  69. package/bin/templates/react/src/pages/NotificationsPage.tsx +119 -0
  70. package/bin/templates/react/src/pages/ProfilePage.tsx +92 -0
  71. package/bin/templates/react/src/pages/SettingsPage.tsx +165 -0
  72. package/bin/templates/react/src/services/auth.ts +48 -0
  73. package/bin/templates/react/src/services/jwt.ts +35 -0
  74. package/bin/templates/react/src/services/storage.ts +24 -0
  75. package/bin/templates/react/src/styles/global.css +382 -0
  76. package/bin/templates/react/src/types/auth.ts +21 -0
  77. package/bin/templates/react/src/types/notifications.ts +9 -0
  78. package/bin/templates/react/tests/helpers/test-utils.ts +79 -0
  79. package/bin/templates/react/tests/middleware/auth.test.ts +67 -0
  80. package/bin/templates/react/tests/middleware/error.test.ts +105 -0
  81. package/bin/templates/react/tests/middleware/retry.test.ts +103 -0
  82. package/bin/templates/react/tests/services/auth.test.ts +89 -0
  83. package/bin/templates/react/tests/services/jwt.test.ts +76 -0
  84. package/bin/templates/react/tests/services/storage.test.ts +69 -0
  85. package/bin/templates/{base → react}/tsconfig.json +4 -6
  86. package/bin/templates/react/vite.config.ts +18 -0
  87. package/bin/templates/react/vitest.config.ts +18 -0
  88. package/dist/cdn/accordion/snice-accordion.js +1 -1
  89. package/dist/cdn/accordion/snice-accordion.min.js +1 -1
  90. package/dist/cdn/action-bar/snice-action-bar.js +1 -1
  91. package/dist/cdn/action-bar/snice-action-bar.min.js +1 -1
  92. package/dist/cdn/activity-feed/snice-activity-feed.js +1 -1
  93. package/dist/cdn/activity-feed/snice-activity-feed.min.js +1 -1
  94. package/dist/cdn/alert/snice-alert.js +1 -1
  95. package/dist/cdn/alert/snice-alert.min.js +1 -1
  96. package/dist/cdn/app-tiles/snice-app-tiles.js +1 -1
  97. package/dist/cdn/app-tiles/snice-app-tiles.min.js +1 -1
  98. package/dist/cdn/approval-flow/snice-approval-flow.js +1 -1
  99. package/dist/cdn/approval-flow/snice-approval-flow.min.js +1 -1
  100. package/dist/cdn/audio-recorder/snice-audio-recorder.js +1 -1
  101. package/dist/cdn/audio-recorder/snice-audio-recorder.min.js +1 -1
  102. package/dist/cdn/availability/snice-availability.js +1 -1
  103. package/dist/cdn/availability/snice-availability.min.js +1 -1
  104. package/dist/cdn/avatar/snice-avatar.js +1 -1
  105. package/dist/cdn/avatar/snice-avatar.min.js +1 -1
  106. package/dist/cdn/avatar-group/snice-avatar-group.js +1 -1
  107. package/dist/cdn/avatar-group/snice-avatar-group.min.js +1 -1
  108. package/dist/cdn/badge/snice-badge.js +1 -1
  109. package/dist/cdn/badge/snice-badge.min.js +1 -1
  110. package/dist/cdn/banner/snice-banner.js +1 -1
  111. package/dist/cdn/banner/snice-banner.min.js +1 -1
  112. package/dist/cdn/binpack/snice-binpack.js +1 -1
  113. package/dist/cdn/binpack/snice-binpack.min.js +1 -1
  114. package/dist/cdn/book/snice-book.js +1 -1
  115. package/dist/cdn/book/snice-book.min.js +1 -1
  116. package/dist/cdn/booking/snice-booking.js +1 -1
  117. package/dist/cdn/booking/snice-booking.min.js +1 -1
  118. package/dist/cdn/breadcrumbs/snice-breadcrumbs.js +1 -1
  119. package/dist/cdn/breadcrumbs/snice-breadcrumbs.min.js +1 -1
  120. package/dist/cdn/button/snice-button.js +1 -1
  121. package/dist/cdn/button/snice-button.min.js +1 -1
  122. package/dist/cdn/calendar/snice-calendar.js +1 -1
  123. package/dist/cdn/calendar/snice-calendar.min.js +1 -1
  124. package/dist/cdn/camera/snice-camera.js +1 -1
  125. package/dist/cdn/camera/snice-camera.min.js +1 -1
  126. package/dist/cdn/camera-annotate/snice-camera-annotate.js +1 -1
  127. package/dist/cdn/camera-annotate/snice-camera-annotate.min.js +1 -1
  128. package/dist/cdn/candlestick/snice-candlestick.js +1 -1
  129. package/dist/cdn/candlestick/snice-candlestick.min.js +1 -1
  130. package/dist/cdn/card/snice-card.js +1 -1
  131. package/dist/cdn/card/snice-card.min.js +1 -1
  132. package/dist/cdn/carousel/snice-carousel.js +1 -1
  133. package/dist/cdn/carousel/snice-carousel.min.js +1 -1
  134. package/dist/cdn/cart/snice-cart.js +1 -1
  135. package/dist/cdn/cart/snice-cart.min.js +1 -1
  136. package/dist/cdn/chart/snice-chart.js +1 -1
  137. package/dist/cdn/chart/snice-chart.min.js +1 -1
  138. package/dist/cdn/chat/snice-chat.js +1 -1
  139. package/dist/cdn/chat/snice-chat.min.js +1 -1
  140. package/dist/cdn/checkbox/snice-checkbox.js +1 -1
  141. package/dist/cdn/checkbox/snice-checkbox.min.js +1 -1
  142. package/dist/cdn/chip/README.md +2 -2
  143. package/dist/cdn/chip/snice-chip.js +2 -2
  144. package/dist/cdn/chip/snice-chip.js.map +1 -1
  145. package/dist/cdn/chip/snice-chip.min.js +3 -3
  146. package/dist/cdn/chip/snice-chip.min.js.map +1 -1
  147. package/dist/cdn/code-block/snice-code-block.js +1 -1
  148. package/dist/cdn/code-block/snice-code-block.min.js +1 -1
  149. package/dist/cdn/color-display/snice-color-display.js +1 -1
  150. package/dist/cdn/color-display/snice-color-display.min.js +1 -1
  151. package/dist/cdn/color-picker/snice-color-picker.js +1 -1
  152. package/dist/cdn/color-picker/snice-color-picker.min.js +1 -1
  153. package/dist/cdn/command-palette/snice-command-palette.js +1 -1
  154. package/dist/cdn/command-palette/snice-command-palette.min.js +1 -1
  155. package/dist/cdn/comments/snice-comments.js +1 -1
  156. package/dist/cdn/comments/snice-comments.min.js +1 -1
  157. package/dist/cdn/countdown/snice-countdown.js +1 -1
  158. package/dist/cdn/countdown/snice-countdown.min.js +1 -1
  159. package/dist/cdn/cropper/snice-cropper.js +1 -1
  160. package/dist/cdn/cropper/snice-cropper.min.js +1 -1
  161. package/dist/cdn/data-card/snice-data-card.js +1 -1
  162. package/dist/cdn/data-card/snice-data-card.min.js +1 -1
  163. package/dist/cdn/date-picker/README.md +1 -1
  164. package/dist/cdn/date-picker/snice-date-picker.js +2 -2
  165. package/dist/cdn/date-picker/snice-date-picker.js.map +1 -1
  166. package/dist/cdn/date-picker/snice-date-picker.min.js +2 -2
  167. package/dist/cdn/date-picker/snice-date-picker.min.js.map +1 -1
  168. package/dist/cdn/date-range-picker/README.md +1 -1
  169. package/dist/cdn/date-range-picker/snice-date-range-picker.js +2 -2
  170. package/dist/cdn/date-range-picker/snice-date-range-picker.js.map +1 -1
  171. package/dist/cdn/date-range-picker/snice-date-range-picker.min.js +11 -11
  172. package/dist/cdn/date-range-picker/snice-date-range-picker.min.js.map +1 -1
  173. package/dist/cdn/date-time-picker/README.md +1 -1
  174. package/dist/cdn/date-time-picker/snice-date-time-picker.js +2 -2
  175. package/dist/cdn/date-time-picker/snice-date-time-picker.js.map +1 -1
  176. package/dist/cdn/date-time-picker/snice-date-time-picker.min.js +2 -2
  177. package/dist/cdn/date-time-picker/snice-date-time-picker.min.js.map +1 -1
  178. package/dist/cdn/diff/snice-diff.js +1 -1
  179. package/dist/cdn/diff/snice-diff.min.js +1 -1
  180. package/dist/cdn/divider/snice-divider.js +1 -1
  181. package/dist/cdn/divider/snice-divider.min.js +1 -1
  182. package/dist/cdn/doc/snice-doc.js +1 -1
  183. package/dist/cdn/doc/snice-doc.min.js +1 -1
  184. package/dist/cdn/draw/README.md +2 -2
  185. package/dist/cdn/draw/snice-draw.js +26 -4
  186. package/dist/cdn/draw/snice-draw.js.map +1 -1
  187. package/dist/cdn/draw/snice-draw.min.js +3 -3
  188. package/dist/cdn/draw/snice-draw.min.js.map +1 -1
  189. package/dist/cdn/drawer/snice-drawer.js +1 -1
  190. package/dist/cdn/drawer/snice-drawer.min.js +1 -1
  191. package/dist/cdn/empty-state/snice-empty-state.js +1 -1
  192. package/dist/cdn/empty-state/snice-empty-state.min.js +1 -1
  193. package/dist/cdn/estimate/snice-estimate.js +1 -1
  194. package/dist/cdn/estimate/snice-estimate.min.js +1 -1
  195. package/dist/cdn/file-gallery/snice-file-gallery.js +1 -1
  196. package/dist/cdn/file-gallery/snice-file-gallery.min.js +1 -1
  197. package/dist/cdn/file-upload/snice-file-upload.js +1 -1
  198. package/dist/cdn/file-upload/snice-file-upload.min.js +1 -1
  199. package/dist/cdn/flip-card/snice-flip-card.js +1 -1
  200. package/dist/cdn/flip-card/snice-flip-card.min.js +1 -1
  201. package/dist/cdn/flow/snice-flow.js +1 -1
  202. package/dist/cdn/flow/snice-flow.min.js +1 -1
  203. package/dist/cdn/form-layout/snice-form-layout.js +1 -1
  204. package/dist/cdn/form-layout/snice-form-layout.min.js +1 -1
  205. package/dist/cdn/funnel/snice-funnel.js +1 -1
  206. package/dist/cdn/funnel/snice-funnel.min.js +1 -1
  207. package/dist/cdn/gantt/snice-gantt.js +1 -1
  208. package/dist/cdn/gantt/snice-gantt.min.js +1 -1
  209. package/dist/cdn/gauge/snice-gauge.js +1 -1
  210. package/dist/cdn/gauge/snice-gauge.min.js +1 -1
  211. package/dist/cdn/grid/README.md +27 -0
  212. package/dist/cdn/grid/snice-grid.js +862 -0
  213. package/dist/cdn/grid/snice-grid.js.map +1 -0
  214. package/dist/cdn/grid/snice-grid.min.js +13 -0
  215. package/dist/cdn/grid/snice-grid.min.js.map +1 -0
  216. package/dist/cdn/heatmap/snice-heatmap.js +1 -1
  217. package/dist/cdn/heatmap/snice-heatmap.min.js +1 -1
  218. package/dist/cdn/image/snice-image.js +1 -1
  219. package/dist/cdn/image/snice-image.min.js +1 -1
  220. package/dist/cdn/input/snice-input.js +1 -1
  221. package/dist/cdn/input/snice-input.min.js +1 -1
  222. package/dist/cdn/invoice/snice-invoice.js +1 -1
  223. package/dist/cdn/invoice/snice-invoice.min.js +1 -1
  224. package/dist/cdn/kanban/snice-kanban.js +1 -1
  225. package/dist/cdn/kanban/snice-kanban.min.js +1 -1
  226. package/dist/cdn/key-value/snice-key-value.js +1 -1
  227. package/dist/cdn/key-value/snice-key-value.min.js +1 -1
  228. package/dist/cdn/kpi/snice-kpi.js +1 -1
  229. package/dist/cdn/kpi/snice-kpi.min.js +1 -1
  230. package/dist/cdn/layout/snice-layout.js +1 -1
  231. package/dist/cdn/layout/snice-layout.min.js +1 -1
  232. package/dist/cdn/leaderboard/snice-leaderboard.js +1 -1
  233. package/dist/cdn/leaderboard/snice-leaderboard.min.js +1 -1
  234. package/dist/cdn/link/snice-link.js +1 -1
  235. package/dist/cdn/link/snice-link.min.js +1 -1
  236. package/dist/cdn/link-preview/snice-link-preview.js +1 -1
  237. package/dist/cdn/link-preview/snice-link-preview.min.js +1 -1
  238. package/dist/cdn/list/snice-list.js +1 -1
  239. package/dist/cdn/list/snice-list.min.js +1 -1
  240. package/dist/cdn/location/snice-location.js +1 -1
  241. package/dist/cdn/location/snice-location.min.js +1 -1
  242. package/dist/cdn/login/snice-login.js +1 -1
  243. package/dist/cdn/login/snice-login.min.js +1 -1
  244. package/dist/cdn/map/snice-map.js +1 -1
  245. package/dist/cdn/map/snice-map.min.js +1 -1
  246. package/dist/cdn/markdown/snice-markdown.js +1 -1
  247. package/dist/cdn/markdown/snice-markdown.min.js +1 -1
  248. package/dist/cdn/masonry/snice-masonry.js +1 -1
  249. package/dist/cdn/masonry/snice-masonry.min.js +1 -1
  250. package/dist/cdn/menu/snice-menu.js +1 -1
  251. package/dist/cdn/menu/snice-menu.min.js +1 -1
  252. package/dist/cdn/message-strip/README.md +2 -2
  253. package/dist/cdn/message-strip/snice-message-strip.js +2 -2
  254. package/dist/cdn/message-strip/snice-message-strip.js.map +1 -1
  255. package/dist/cdn/message-strip/snice-message-strip.min.js +6 -6
  256. package/dist/cdn/message-strip/snice-message-strip.min.js.map +1 -1
  257. package/dist/cdn/metric-table/snice-metric-table.js +1 -1
  258. package/dist/cdn/metric-table/snice-metric-table.min.js +1 -1
  259. package/dist/cdn/modal/snice-modal.js +1 -1
  260. package/dist/cdn/modal/snice-modal.min.js +1 -1
  261. package/dist/cdn/music-player/snice-music-player.js +1 -1
  262. package/dist/cdn/music-player/snice-music-player.min.js +1 -1
  263. package/dist/cdn/nav/snice-nav.js +1 -1
  264. package/dist/cdn/nav/snice-nav.min.js +1 -1
  265. package/dist/cdn/network-graph/snice-network-graph.js +1 -1
  266. package/dist/cdn/network-graph/snice-network-graph.min.js +1 -1
  267. package/dist/cdn/notification-center/snice-notification-center.js +1 -1
  268. package/dist/cdn/notification-center/snice-notification-center.min.js +1 -1
  269. package/dist/cdn/order-tracker/snice-order-tracker.js +1 -1
  270. package/dist/cdn/order-tracker/snice-order-tracker.min.js +1 -1
  271. package/dist/cdn/org-chart/snice-org-chart.js +1 -1
  272. package/dist/cdn/org-chart/snice-org-chart.min.js +1 -1
  273. package/dist/cdn/pagination/snice-pagination.js +1 -1
  274. package/dist/cdn/pagination/snice-pagination.min.js +1 -1
  275. package/dist/cdn/paint/README.md +2 -2
  276. package/dist/cdn/paint/snice-paint.js +26 -3
  277. package/dist/cdn/paint/snice-paint.js.map +1 -1
  278. package/dist/cdn/paint/snice-paint.min.js +3 -3
  279. package/dist/cdn/paint/snice-paint.min.js.map +1 -1
  280. package/dist/cdn/pdf-viewer/snice-pdf-viewer.js +1 -1
  281. package/dist/cdn/pdf-viewer/snice-pdf-viewer.min.js +1 -1
  282. package/dist/cdn/permission-matrix/snice-permission-matrix.js +1 -1
  283. package/dist/cdn/permission-matrix/snice-permission-matrix.min.js +1 -1
  284. package/dist/cdn/podcast-player/snice-podcast-player.js +1 -1
  285. package/dist/cdn/podcast-player/snice-podcast-player.min.js +1 -1
  286. package/dist/cdn/pricing-table/snice-pricing-table.js +1 -1
  287. package/dist/cdn/pricing-table/snice-pricing-table.min.js +1 -1
  288. package/dist/cdn/product-card/README.md +1 -1
  289. package/dist/cdn/product-card/snice-product-card.js +1 -1
  290. package/dist/cdn/product-card/snice-product-card.min.js +1 -1
  291. package/dist/cdn/progress/snice-progress.js +1 -1
  292. package/dist/cdn/progress/snice-progress.min.js +1 -1
  293. package/dist/cdn/progress-ring/snice-progress-ring.js +1 -1
  294. package/dist/cdn/progress-ring/snice-progress-ring.min.js +1 -1
  295. package/dist/cdn/qr-code/snice-qr-code.js +1 -1
  296. package/dist/cdn/qr-code/snice-qr-code.min.js +1 -1
  297. package/dist/cdn/qr-reader/snice-qr-reader.js +1 -1
  298. package/dist/cdn/qr-reader/snice-qr-reader.min.js +1 -1
  299. package/dist/cdn/radio/snice-radio.js +1 -1
  300. package/dist/cdn/radio/snice-radio.min.js +1 -1
  301. package/dist/cdn/range-slider/snice-range-slider.js +1 -1
  302. package/dist/cdn/range-slider/snice-range-slider.min.js +1 -1
  303. package/dist/cdn/rating/snice-rating.js +1 -1
  304. package/dist/cdn/rating/snice-rating.min.js +1 -1
  305. package/dist/cdn/receipt/snice-receipt.js +1 -1
  306. package/dist/cdn/receipt/snice-receipt.min.js +1 -1
  307. package/dist/cdn/recipe/snice-recipe.js +1 -1
  308. package/dist/cdn/recipe/snice-recipe.min.js +1 -1
  309. package/dist/cdn/runtime/README.md +2 -2
  310. package/dist/cdn/runtime/snice-runtime.esm.js +40 -15
  311. package/dist/cdn/runtime/snice-runtime.esm.js.map +1 -1
  312. package/dist/cdn/runtime/snice-runtime.esm.min.js +7 -7
  313. package/dist/cdn/runtime/snice-runtime.esm.min.js.map +1 -1
  314. package/dist/cdn/runtime/snice-runtime.js +40 -15
  315. package/dist/cdn/runtime/snice-runtime.js.map +1 -1
  316. package/dist/cdn/runtime/snice-runtime.min.js +6 -6
  317. package/dist/cdn/runtime/snice-runtime.min.js.map +1 -1
  318. package/dist/cdn/sankey/snice-sankey.js +1 -1
  319. package/dist/cdn/sankey/snice-sankey.min.js +1 -1
  320. package/dist/cdn/segmented-control/snice-segmented-control.js +1 -1
  321. package/dist/cdn/segmented-control/snice-segmented-control.min.js +1 -1
  322. package/dist/cdn/select/snice-select.js +1 -1
  323. package/dist/cdn/select/snice-select.min.js +1 -1
  324. package/dist/cdn/skeleton/snice-skeleton.js +1 -1
  325. package/dist/cdn/skeleton/snice-skeleton.min.js +1 -1
  326. package/dist/cdn/slider/snice-slider.js +1 -1
  327. package/dist/cdn/slider/snice-slider.min.js +1 -1
  328. package/dist/cdn/sortable/snice-sortable.js +1 -1
  329. package/dist/cdn/sortable/snice-sortable.min.js +1 -1
  330. package/dist/cdn/sparkline/snice-sparkline.js +1 -1
  331. package/dist/cdn/sparkline/snice-sparkline.min.js +1 -1
  332. package/dist/cdn/spinner/snice-spinner.js +1 -1
  333. package/dist/cdn/spinner/snice-spinner.min.js +1 -1
  334. package/dist/cdn/split-button/snice-split-button.js +1 -1
  335. package/dist/cdn/split-button/snice-split-button.min.js +1 -1
  336. package/dist/cdn/split-pane/snice-split-pane.js +1 -1
  337. package/dist/cdn/split-pane/snice-split-pane.min.js +1 -1
  338. package/dist/cdn/spotlight/snice-spotlight.js +1 -1
  339. package/dist/cdn/spotlight/snice-spotlight.min.js +1 -1
  340. package/dist/cdn/spreadsheet/snice-spreadsheet.js +1 -1
  341. package/dist/cdn/spreadsheet/snice-spreadsheet.min.js +1 -1
  342. package/dist/cdn/stat-group/snice-stat-group.js +1 -1
  343. package/dist/cdn/stat-group/snice-stat-group.min.js +1 -1
  344. package/dist/cdn/step-input/snice-step-input.js +1 -1
  345. package/dist/cdn/step-input/snice-step-input.min.js +1 -1
  346. package/dist/cdn/stepper/snice-stepper.js +1 -1
  347. package/dist/cdn/stepper/snice-stepper.min.js +1 -1
  348. package/dist/cdn/switch/snice-switch.js +1 -1
  349. package/dist/cdn/switch/snice-switch.min.js +1 -1
  350. package/dist/cdn/table/snice-table.js +1 -1
  351. package/dist/cdn/table/snice-table.min.js +1 -1
  352. package/dist/cdn/tabs/snice-tabs.js +1 -1
  353. package/dist/cdn/tabs/snice-tabs.min.js +1 -1
  354. package/dist/cdn/tag/README.md +1 -1
  355. package/dist/cdn/tag/snice-tag.js +2 -2
  356. package/dist/cdn/tag/snice-tag.js.map +1 -1
  357. package/dist/cdn/tag/snice-tag.min.js +3 -3
  358. package/dist/cdn/tag/snice-tag.min.js.map +1 -1
  359. package/dist/cdn/tag-input/README.md +2 -2
  360. package/dist/cdn/tag-input/snice-tag-input.js +2 -2
  361. package/dist/cdn/tag-input/snice-tag-input.js.map +1 -1
  362. package/dist/cdn/tag-input/snice-tag-input.min.js +2 -2
  363. package/dist/cdn/tag-input/snice-tag-input.min.js.map +1 -1
  364. package/dist/cdn/terminal/snice-terminal.js +1 -1
  365. package/dist/cdn/terminal/snice-terminal.min.js +1 -1
  366. package/dist/cdn/testimonial/snice-testimonial.js +1 -1
  367. package/dist/cdn/testimonial/snice-testimonial.min.js +1 -1
  368. package/dist/cdn/textarea/snice-textarea.js +1 -1
  369. package/dist/cdn/textarea/snice-textarea.min.js +1 -1
  370. package/dist/cdn/time-picker/README.md +1 -1
  371. package/dist/cdn/time-picker/snice-time-picker.js +2 -2
  372. package/dist/cdn/time-picker/snice-time-picker.js.map +1 -1
  373. package/dist/cdn/time-picker/snice-time-picker.min.js +2 -2
  374. package/dist/cdn/time-picker/snice-time-picker.min.js.map +1 -1
  375. package/dist/cdn/time-range-picker/snice-time-range-picker.js +1 -1
  376. package/dist/cdn/time-range-picker/snice-time-range-picker.min.js +1 -1
  377. package/dist/cdn/timeline/snice-timeline.js +1 -1
  378. package/dist/cdn/timeline/snice-timeline.min.js +1 -1
  379. package/dist/cdn/timer/snice-timer.js +1 -1
  380. package/dist/cdn/timer/snice-timer.min.js +1 -1
  381. package/dist/cdn/toast/README.md +1 -1
  382. package/dist/cdn/toast/snice-toast.js +7 -3
  383. package/dist/cdn/toast/snice-toast.js.map +1 -1
  384. package/dist/cdn/toast/snice-toast.min.js +6 -6
  385. package/dist/cdn/toast/snice-toast.min.js.map +1 -1
  386. package/dist/cdn/tooltip/snice-tooltip.js +1 -1
  387. package/dist/cdn/tooltip/snice-tooltip.min.js +1 -1
  388. package/dist/cdn/tree/snice-tree.js +1 -1
  389. package/dist/cdn/tree/snice-tree.min.js +1 -1
  390. package/dist/cdn/treemap/snice-treemap.js +1 -1
  391. package/dist/cdn/treemap/snice-treemap.min.js +1 -1
  392. package/dist/cdn/user-card/snice-user-card.js +1 -1
  393. package/dist/cdn/user-card/snice-user-card.min.js +1 -1
  394. package/dist/cdn/video-player/snice-video-player.js +1 -1
  395. package/dist/cdn/video-player/snice-video-player.min.js +1 -1
  396. package/dist/cdn/virtual-scroller/snice-virtual-scroller.js +1 -1
  397. package/dist/cdn/virtual-scroller/snice-virtual-scroller.min.js +1 -1
  398. package/dist/cdn/waterfall/README.md +1 -1
  399. package/dist/cdn/waterfall/snice-waterfall.js +1 -1
  400. package/dist/cdn/waterfall/snice-waterfall.min.js +1 -1
  401. package/dist/cdn/weather/snice-weather.js +1 -1
  402. package/dist/cdn/weather/snice-weather.min.js +1 -1
  403. package/dist/cdn/work-order/snice-work-order.js +1 -1
  404. package/dist/cdn/work-order/snice-work-order.min.js +1 -1
  405. package/dist/components/chip/snice-chip.js +1 -1
  406. package/dist/components/chip/snice-chip.js.map +1 -1
  407. package/dist/components/date-picker/snice-date-picker.js +1 -1
  408. package/dist/components/date-picker/snice-date-picker.js.map +1 -1
  409. package/dist/components/date-range-picker/snice-date-range-picker.js +1 -1
  410. package/dist/components/date-range-picker/snice-date-range-picker.js.map +1 -1
  411. package/dist/components/date-time-picker/snice-date-time-picker.js +1 -1
  412. package/dist/components/date-time-picker/snice-date-time-picker.js.map +1 -1
  413. package/dist/components/draw/snice-draw.d.ts +2 -0
  414. package/dist/components/draw/snice-draw.js +25 -3
  415. package/dist/components/draw/snice-draw.js.map +1 -1
  416. package/dist/components/grid/snice-grid.d.ts +73 -0
  417. package/dist/components/grid/snice-grid.js +795 -0
  418. package/dist/components/grid/snice-grid.js.map +1 -0
  419. package/dist/components/grid/snice-grid.types.d.ts +41 -0
  420. package/dist/components/message-strip/snice-message-strip.js +1 -1
  421. package/dist/components/message-strip/snice-message-strip.js.map +1 -1
  422. package/dist/components/paint/snice-paint.d.ts +2 -0
  423. package/dist/components/paint/snice-paint.js +25 -2
  424. package/dist/components/paint/snice-paint.js.map +1 -1
  425. package/dist/components/tag/snice-tag.js +1 -1
  426. package/dist/components/tag/snice-tag.js.map +1 -1
  427. package/dist/components/tag-input/snice-tag-input.js +1 -1
  428. package/dist/components/tag-input/snice-tag-input.js.map +1 -1
  429. package/dist/components/theme/theme.css +15 -0
  430. package/dist/components/time-picker/snice-time-picker.js +1 -1
  431. package/dist/components/time-picker/snice-time-picker.js.map +1 -1
  432. package/dist/components/toast/snice-toast-container.js +4 -0
  433. package/dist/components/toast/snice-toast-container.js.map +1 -1
  434. package/dist/components/toast/snice-toast.js +2 -2
  435. package/dist/index.cjs +37 -12
  436. package/dist/index.cjs.map +1 -1
  437. package/dist/index.esm.js +37 -12
  438. package/dist/index.esm.js.map +1 -1
  439. package/dist/index.iife.js +37 -12
  440. package/dist/index.iife.js.map +1 -1
  441. package/dist/react/SniceProvider.d.ts +71 -0
  442. package/dist/react/SniceProvider.js +49 -0
  443. package/dist/react/SniceProvider.js.map +1 -0
  444. package/dist/react/SniceRouter.d.ts +44 -0
  445. package/dist/react/SniceRouter.js +190 -0
  446. package/dist/react/SniceRouter.js.map +1 -0
  447. package/dist/react/index.d.ts +3 -0
  448. package/dist/react/index.js +14 -0
  449. package/dist/react/index.js.map +1 -0
  450. package/dist/react/matchRoute.d.ts +16 -0
  451. package/dist/react/matchRoute.js +32 -0
  452. package/dist/react/matchRoute.js.map +1 -0
  453. package/dist/react/useRequestHandler.js +1 -1
  454. package/dist/react/useRequestHandler.js.map +1 -1
  455. package/dist/symbols.cjs +1 -1
  456. package/dist/symbols.esm.js +1 -1
  457. package/dist/transitions.cjs +1 -1
  458. package/dist/transitions.esm.js +1 -1
  459. package/dist/types/guard.d.ts +4 -11
  460. package/docs/ai/README.md +7 -7
  461. package/docs/ai/components/grid.md +116 -0
  462. package/docs/ai/patterns.md +24 -0
  463. package/docs/ai/react-integration.md +97 -0
  464. package/docs/components/grid.md +249 -0
  465. package/docs/plans/2026-03-10-grid-component-design.md +138 -0
  466. package/docs/plans/2026-03-10-grid-component-plan.md +716 -0
  467. package/docs/plans/2026-03-10-react-integration-plan.md +1178 -0
  468. package/docs/react-integration.md +508 -0
  469. package/docs/request-response.md +7 -21
  470. package/package.json +1 -1
  471. package/bin/templates/base/README.md +0 -33
  472. package/bin/templates/base/global.d.ts +0 -14
  473. package/bin/templates/base/index.html +0 -13
  474. package/bin/templates/base/package.json +0 -21
  475. package/bin/templates/base/src/components/counter-button.ts +0 -88
  476. package/bin/templates/base/src/components/counter-button.types.ts +0 -7
  477. package/bin/templates/base/src/components/feature-card.ts +0 -59
  478. package/bin/templates/base/src/components/feature-card.types.ts +0 -5
  479. package/bin/templates/base/src/controllers/counter-controller.ts +0 -24
  480. package/bin/templates/base/src/main.ts +0 -24
  481. package/bin/templates/base/src/pages/about-page.ts +0 -68
  482. package/bin/templates/base/src/pages/home-page.ts +0 -105
  483. package/bin/templates/base/src/pages/not-found-page.ts +0 -55
  484. package/bin/templates/base/src/router.ts +0 -9
  485. package/bin/templates/base/src/styles/global.css +0 -27
  486. package/bin/templates/base/src/types/api-response.ts +0 -5
  487. package/bin/templates/base/src/types/status.ts +0 -1
  488. package/bin/templates/base/src/types/theme.ts +0 -1
  489. package/bin/templates/base/src/types/user.ts +0 -5
  490. package/bin/templates/base/vite.config.ts +0 -38
  491. package/bin/templates/pwa/public/vite.svg +0 -1
  492. package/bin/templates/pwa/src/router.ts +0 -20
  493. package/bin/templates/pwa/src/styles/global.css +0 -64
  494. /package/bin/templates/{pwa → default}/README.md +0 -0
  495. /package/bin/templates/{pwa → default}/global.d.ts +0 -0
  496. /package/bin/templates/{pwa → default}/package.json +0 -0
  497. /package/bin/templates/{pwa → default}/public/icons/.gitkeep +0 -0
  498. /package/bin/templates/{base → default}/public/vite.svg +0 -0
  499. /package/bin/templates/{pwa → default}/src/fetcher.ts +0 -0
  500. /package/bin/templates/{pwa → default}/src/guards/auth.ts +0 -0
  501. /package/bin/templates/{pwa → default}/src/middleware/auth.ts +0 -0
  502. /package/bin/templates/{pwa → default}/src/middleware/retry.ts +0 -0
  503. /package/bin/templates/{pwa → default}/src/services/auth.ts +0 -0
  504. /package/bin/templates/{pwa → default}/src/services/jwt.ts +0 -0
  505. /package/bin/templates/{pwa → default}/src/services/storage.ts +0 -0
  506. /package/bin/templates/{pwa → default}/src/types/auth.ts +0 -0
  507. /package/bin/templates/{pwa → default}/src/types/notifications.ts +0 -0
  508. /package/bin/templates/{pwa → default}/tests/helpers/test-utils.ts +0 -0
  509. /package/bin/templates/{pwa → default}/tests/middleware/auth.test.ts +0 -0
  510. /package/bin/templates/{pwa → default}/tests/middleware/error.test.ts +0 -0
  511. /package/bin/templates/{pwa → default}/tests/middleware/retry.test.ts +0 -0
  512. /package/bin/templates/{pwa → default}/tests/services/auth.test.ts +0 -0
  513. /package/bin/templates/{pwa → default}/tests/services/jwt.test.ts +0 -0
  514. /package/bin/templates/{pwa → default}/tests/services/storage.test.ts +0 -0
  515. /package/bin/templates/{pwa → default}/vite.config.ts +0 -0
  516. /package/bin/templates/{pwa → default}/vitest.config.ts +0 -0
@@ -0,0 +1,116 @@
1
+ # snice-grid
2
+
3
+ Grid-coordinate layout component. Items placed at explicit (col, row) positions with optional spanning. Collision resolution: swap-first, fallback push-right-then-down. Animated transitions, drag-and-drop with snap-to-grid.
4
+
5
+ ## Properties
6
+
7
+ ```typescript
8
+ gap: string = '1rem'; // spacing between cells
9
+ columnWidth: number = 80; // column width in px -- attr: column-width
10
+ rowHeight: number = 80; // row height in px -- attr: row-height
11
+ columns: number = 0; // fixed column count (0 = auto) -- attr: columns
12
+ rows: number = 0; // fixed row count (0 = auto) -- attr: rows
13
+ originLeft: boolean = true; // false = right-to-left -- attr: origin-left
14
+ originTop: boolean = true; // false = bottom-to-top -- attr: origin-top
15
+ transitionDuration: string = '0.4s'; // CSS transition duration -- attr: transition-duration
16
+ stagger: number = 0; // ms delay between each item transition
17
+ resize: boolean = true; // auto re-layout on container resize
18
+ draggable: boolean = false; // enable drag-to-reorder with snap-to-grid
19
+ dragThrottle: number = 120; // ms throttle for drag layout updates -- attr: drag-throttle
20
+ ```
21
+
22
+ ## Item Attributes
23
+
24
+ Set on child elements:
25
+
26
+ - `grid-col` (number, default 0) -- column position (0-based)
27
+ - `grid-row` (number, default 0) -- row position (0-based)
28
+ - `grid-colspan` (number, default 1) -- columns to span
29
+ - `grid-rowspan` (number, default 1) -- rows to span
30
+ - `name` (string) -- identifier for getLayout/setLayout persistence
31
+ - `hidden` -- hides item from layout
32
+
33
+ ## Methods
34
+
35
+ - `layout()` - Full re-layout
36
+ - `fit(element, col?, row?)` - Position specific item at grid coordinates, reflow others
37
+ - `reloadItems()` - Re-collect items from DOM
38
+ - `getItemElements()` - Get all layout items
39
+ - `getLayout()` - Returns `GridLayout` (Record<string, GridLayoutEntry>) with positions/spans/order
40
+ - `setLayout(layout)` - Apply saved layout (reorder, reposition, hide/show)
41
+
42
+ ## Events
43
+
44
+ - `grid-layout-complete` -> `{ items: HTMLElement[] }`
45
+ - `grid-drag-item-positioned` -> `{ item: HTMLElement, col: number, row: number }`
46
+
47
+ ## Slots
48
+
49
+ - `(default)` - Items to place on grid (use grid-col/grid-row/grid-colspan/grid-rowspan attributes)
50
+
51
+ ## CSS Custom Properties
52
+
53
+ - `--grid-gap` - Gap between cells (set via `gap` property)
54
+ - `--grid-transition-duration` - Transition duration (set via `transition-duration` property)
55
+
56
+ ## CSS Parts
57
+
58
+ - `base` - The inner container element
59
+
60
+ ## Types
61
+
62
+ ```typescript
63
+ interface GridLayoutEntry {
64
+ col: number;
65
+ row: number;
66
+ colspan?: number;
67
+ rowspan?: number;
68
+ order: number;
69
+ hidden?: boolean;
70
+ }
71
+
72
+ type GridLayout = Record<string, GridLayoutEntry>;
73
+ ```
74
+
75
+ ## Basic Usage
76
+
77
+ ```html
78
+ <snice-grid column-width="100" row-height="100" gap="8px">
79
+ <div grid-col="0" grid-row="0">A</div>
80
+ <div grid-col="1" grid-row="0">B</div>
81
+ <div grid-col="0" grid-row="1" grid-colspan="2">Wide</div>
82
+ </snice-grid>
83
+
84
+ <!-- Draggable dashboard -->
85
+ <snice-grid draggable column-width="80" row-height="80" gap="8px" columns="4">
86
+ <div grid-col="0" grid-row="0" name="a">A</div>
87
+ <div grid-col="1" grid-row="0" name="b">B</div>
88
+ <div grid-col="0" grid-row="1" name="c" grid-colspan="2">C</div>
89
+ </snice-grid>
90
+
91
+ <!-- Fixed grid -->
92
+ <snice-grid column-width="80" row-height="80" columns="4" rows="3">
93
+ <div grid-col="0" grid-row="0">A</div>
94
+ </snice-grid>
95
+ ```
96
+
97
+ ## Collision Resolution
98
+
99
+ 1. **Swap** -- single occupant in target area swaps positions with incoming item
100
+ 2. **Push-right-then-down** -- fallback if swap fails (multiple occupants or occupant doesn't fit at swap position)
101
+ 3. Column clamping: if `col + colspan > columns`, col is clamped to `columns - colspan`
102
+
103
+ ## Drag CSS Classes
104
+
105
+ - `.grid-dragging` -- during drag (no transition, z-index: 100, opacity: 0.9, cursor: grabbing)
106
+ - `.grid-positioning` -- animating to final position after drop (z-index: 99)
107
+
108
+ ## Notes
109
+
110
+ - Items sized automatically from columnWidth/rowHeight + colspan/rowspan
111
+ - Container uses `position: relative`, items get `position: absolute` + `transform`
112
+ - Uses ResizeObserver on container for auto re-layout
113
+ - FOUC prevented via `[ready]` attribute gating transitions
114
+ - `contain: layout style` on `:host`
115
+ - Inner container has `role="list"`
116
+ - Dashed drop-placeholder shown during drag
@@ -467,3 +467,27 @@ class SearchBox extends HTMLElement {
467
467
  }
468
468
  }
469
469
  ```
470
+
471
+ ## React Router
472
+
473
+ ```tsx
474
+ import { SniceRouter, Route, useSniceContext } from 'snice/react';
475
+
476
+ function App() {
477
+ return (
478
+ <SniceRouter mode="hash" context={{ user, theme: 'dark' }} layout={AppShell}>
479
+ <Route path="/" page={HomePage} />
480
+ <Route path="/settings" page={SettingsPage} guard={authGuard} guardRedirect="/login" />
481
+ <Route path="/legacy" page="legacy-dashboard" />
482
+ <Route path="/login" page={LoginPage} layout={false} />
483
+ </SniceRouter>
484
+ );
485
+ }
486
+
487
+ function AppShell({ children }) {
488
+ const ctx = useSniceContext();
489
+ return <div className="shell"><nav>...</nav><main>{children}</main></div>;
490
+ }
491
+
492
+ const authGuard = (ctx, params) => !!ctx.user;
493
+ ```
@@ -0,0 +1,97 @@
1
+ # React Integration
2
+
3
+ Source: `src/react/` → Build: `dist/react/` → Published: `adapters/react/`
4
+ Import: `import { SniceRouter, Route, useSniceContext } from 'snice/react'`
5
+ Deep import: `import { useRequestHandler } from 'snice/react/useRequestHandler'`
6
+
7
+ ## Components
8
+
9
+ | Export | Type | Purpose |
10
+ |---|---|---|
11
+ | `<SniceRouter>` | Component | Root provider. URL state, route matching, guards, layouts, context. |
12
+ | `<Route>` | Component | Route definition. Child of `<SniceRouter>`. |
13
+ | `<SniceProvider>` | Component | Context provider (standalone, no router needed). |
14
+
15
+ ## Hooks
16
+
17
+ | Export | Returns | Purpose |
18
+ |---|---|---|
19
+ | `useSniceContext()` | `SniceReactContext` | Full merged context: `{ application, navigation: {route, params, placards}, navigate, fetch? }` |
20
+ | `useNavigate()` | `(path) => void` | Programmatic navigation |
21
+ | `useParams()` | `Record<string, string>` | Current route params (shortcut for `ctx.navigation.params`) |
22
+ | `useRoute()` | `string` | Current matched route pattern (shortcut for `ctx.navigation.route`) |
23
+ | `useRequestHandler(ref, routes, options?)` | `void` | Handle @request channels from Snice elements |
24
+
25
+ ## SniceRouter Props
26
+
27
+ - `mode`: `"hash"` | `"history"` — URL strategy (required)
28
+ - `context`: `object` — App context passed to guards, available via `useSniceContext()` (default `{}`)
29
+ - `layout`: `Component | string` — Default layout wrapping all pages
30
+ - `loading`: `Component | string | JSX` — Shown during async guards (default: centered spinner)
31
+ - `fallback`: `Component | string | JSX` — No route match (default: "404" text)
32
+
33
+ ## Route Props
34
+
35
+ - `path`: Route pattern (e.g., `/users/:id`)
36
+ - `page`: React component (receives params as props) OR Snice tag name string (params set as attributes)
37
+ - `guard`: `(ctx, params) => boolean | Promise<boolean>`
38
+ - `guards`: Array of guard functions (AND logic, sequential, short-circuit)
39
+ - `guardRedirect`: Redirect path on guard failure (without it: renders nothing)
40
+ - `layout`: Override layout. `false` = no layout
41
+ - `placard`: `Placard` — page metadata for layouts
42
+
43
+ ## Guards
44
+
45
+ Same signature for both Snice and React:
46
+ `(context: Record<string, any>, params: Record<string, string>) => boolean | Promise<boolean>`
47
+
48
+ - Sync guards resolve immediately
49
+ - Async guards show `loading` component until resolved
50
+ - Guard error (throw) treated as rejection
51
+ - Guards run on navigation only, NOT on context change
52
+
53
+ ## useRequestHandler
54
+
55
+ ```tsx
56
+ useRequestHandler(ref, routes, options?)
57
+ ```
58
+
59
+ - `ref`: React ref to DOM element, or `null` for document-level
60
+ - `routes`: `Record<string, (payload) => any | Promise<any>>`
61
+ - `options.passive`: `boolean` (default false) — don't stop propagation
62
+ - Callbacks are ref-stable — no `useCallback` needed
63
+ - Re-subscribes only when channel names change
64
+ - Auto-cleanup on unmount
65
+
66
+ ## Context Shape
67
+
68
+ ```typescript
69
+ interface SniceReactContext {
70
+ application: Record<string, any>; // your context object
71
+ navigation: { route: string; params: Record<string, string>; placards: Placard[] };
72
+ navigate: (path: string) => void;
73
+ fetch?: typeof globalThis.fetch; // if provided to SniceProvider
74
+ }
75
+ ```
76
+
77
+ ## SniceProvider Props (standalone use)
78
+
79
+ - `context`, `navigate`, `route`, `params`, `placards`, `fetch` — all optional
80
+ - When inside `<SniceRouter>`, these are set automatically
81
+
82
+ ## Mixed Pages
83
+
84
+ `page` accepts React component OR string (Snice tag name).
85
+ Same for `layout`, `loading`, `fallback`.
86
+
87
+ ```tsx
88
+ <SniceRouter mode="hash" context={{ user }}>
89
+ <Route path="/" page={HomePage} />
90
+ <Route path="/legacy" page="legacy-dashboard" />
91
+ </SniceRouter>
92
+ ```
93
+
94
+ ## Type Exports
95
+
96
+ `SniceReactContext`, `SniceRouterProps`, `RouteProps`, `SniceProviderProps`, `Placard`,
97
+ `UseRequestRoute`, `UseRequestRouteMap`, `UseRequestHandlerOptions`
@@ -0,0 +1,249 @@
1
+ <!-- AI: For the AI-optimized version of this doc, see docs/ai/components/grid.md -->
2
+
3
+ # Grid Component
4
+ `<snice-grid>`
5
+
6
+ A grid-coordinate layout component. Items are placed at explicit grid positions using `grid-col` and `grid-row` attributes, and can span multiple cells with `grid-colspan` and `grid-rowspan`. Collision resolution uses swap-first with push-right-then-down fallback. Supports animated transitions and drag-and-drop with snap-to-grid.
7
+
8
+ ## Table of Contents
9
+ - [Properties](#properties)
10
+ - [Methods](#methods)
11
+ - [Events](#events)
12
+ - [Slots](#slots)
13
+ - [CSS Custom Properties](#css-custom-properties)
14
+ - [CSS Parts](#css-parts)
15
+ - [Basic Usage](#basic-usage)
16
+ - [Examples](#examples)
17
+ - [Accessibility](#accessibility)
18
+
19
+ ## Properties
20
+
21
+ | Property | Attribute | Type | Default | Description |
22
+ |----------|-----------|------|---------|-------------|
23
+ | `gap` | `gap` | `string` | `'1rem'` | Spacing between cells |
24
+ | `columnWidth` | `column-width` | `number` | `80` | Width of each grid column in pixels |
25
+ | `rowHeight` | `row-height` | `number` | `80` | Height of each grid row in pixels |
26
+ | `columns` | `columns` | `number` | `0` | Fixed number of columns (0 = auto from content) |
27
+ | `rows` | `rows` | `number` | `0` | Fixed number of rows (0 = auto from content) |
28
+ | `originLeft` | `origin-left` | `boolean` | `true` | `false` = right-to-left |
29
+ | `originTop` | `origin-top` | `boolean` | `true` | `false` = bottom-to-top |
30
+ | `transitionDuration` | `transition-duration` | `string` | `'0.4s'` | CSS transition duration for item movement |
31
+ | `stagger` | `stagger` | `number` | `0` | Delay in ms between each item's transition |
32
+ | `resize` | `resize` | `boolean` | `true` | Auto re-layout on container resize |
33
+ | `draggable` | `draggable` | `boolean` | `false` | Enable drag-to-reorder with snap-to-grid |
34
+ | `dragThrottle` | `drag-throttle` | `number` | `120` | Throttle interval (ms) for drag layout updates |
35
+
36
+ ## Methods
37
+
38
+ | Method | Arguments | Description |
39
+ |--------|-----------|-------------|
40
+ | `layout()` | -- | Perform a full re-layout |
41
+ | `fit()` | `element: HTMLElement, col?: number, row?: number` | Position specific item at grid coordinates, reflow others |
42
+ | `reloadItems()` | -- | Re-collect items from DOM |
43
+ | `getItemElements()` | -- | Returns array of all layout items |
44
+ | `getLayout()` | -- | Returns `GridLayout` object with item positions, spans, and order |
45
+ | `setLayout()` | `layout: GridLayout` | Apply a saved layout (reorder, reposition, hide/show items) |
46
+
47
+ ## Events
48
+
49
+ | Event | Detail | Description |
50
+ |-------|--------|-------------|
51
+ | `grid-layout-complete` | `{ items: HTMLElement[] }` | Fired after layout completes |
52
+ | `grid-drag-item-positioned` | `{ item: HTMLElement, col: number, row: number }` | Fired after a dragged item settles into its new grid position |
53
+
54
+ ## Slots
55
+
56
+ | Name | Description |
57
+ |------|-------------|
58
+ | (default) | Items to place on the grid. Use `grid-col`, `grid-row`, `grid-colspan`, `grid-rowspan` attributes on each item to control placement. |
59
+
60
+ ### Item Attributes
61
+
62
+ These attributes are set on child elements (not on `<snice-grid>` itself):
63
+
64
+ | Attribute | Type | Default | Description |
65
+ |-----------|------|---------|-------------|
66
+ | `grid-col` | `number` | `0` | Column position (0-based) |
67
+ | `grid-row` | `number` | `0` | Row position (0-based) |
68
+ | `grid-colspan` | `number` | `1` | Number of columns to span |
69
+ | `grid-rowspan` | `number` | `1` | Number of rows to span |
70
+ | `name` | `string` | -- | Identifier used by `getLayout()`/`setLayout()` for persistence |
71
+ | `hidden` | `boolean` | -- | Hides the item from layout |
72
+
73
+ ## CSS Custom Properties
74
+
75
+ | Property | Description | Default |
76
+ |----------|-------------|---------|
77
+ | `--grid-gap` | Gap between cells (set via `gap` property) | `1rem` |
78
+ | `--grid-transition-duration` | Transition duration for item movement (set via `transition-duration` property) | `0.4s` |
79
+
80
+ ## CSS Parts
81
+
82
+ | Part | Description |
83
+ |------|-------------|
84
+ | `base` | The inner container element |
85
+
86
+ ## Basic Usage
87
+
88
+ ```typescript
89
+ import 'snice/components/grid/snice-grid';
90
+ ```
91
+
92
+ ```html
93
+ <snice-grid column-width="100" row-height="100" gap="8px">
94
+ <div grid-col="0" grid-row="0">A</div>
95
+ <div grid-col="1" grid-row="0">B</div>
96
+ <div grid-col="0" grid-row="1">C</div>
97
+ </snice-grid>
98
+ ```
99
+
100
+ Items are sized automatically based on `columnWidth`, `rowHeight`, and their `grid-colspan`/`grid-rowspan` values.
101
+
102
+ ## Examples
103
+
104
+ ### Spanning Multiple Cells
105
+
106
+ Use `grid-colspan` and `grid-rowspan` to make items span multiple columns or rows.
107
+
108
+ ```html
109
+ <snice-grid column-width="80" row-height="80" gap="8px">
110
+ <div grid-col="0" grid-row="0" grid-colspan="2" grid-rowspan="2">Large</div>
111
+ <div grid-col="2" grid-row="0">Small A</div>
112
+ <div grid-col="2" grid-row="1">Small B</div>
113
+ <div grid-col="0" grid-row="2" grid-colspan="3">Wide</div>
114
+ </snice-grid>
115
+ ```
116
+
117
+ ### Collision Resolution
118
+
119
+ When two items request the same grid position, the component resolves collisions automatically:
120
+
121
+ 1. **Swap** -- If the target cell has a single occupant, the two items swap positions.
122
+ 2. **Push-right-then-down** -- If swap fails (multiple occupants or the swapped item doesn't fit), the incoming item is pushed to the next free cell scanning right, then down.
123
+
124
+ ```html
125
+ <snice-grid column-width="80" row-height="80" gap="8px">
126
+ <!-- Both request (0,0): the second item will be pushed to (1,0) -->
127
+ <div grid-col="0" grid-row="0">First</div>
128
+ <div grid-col="0" grid-row="0">Second</div>
129
+ </snice-grid>
130
+ ```
131
+
132
+ ### Fixed Grid Size
133
+
134
+ Set `columns` and/or `rows` to constrain the grid. Items that exceed the column limit are wrapped to the next row.
135
+
136
+ ```html
137
+ <snice-grid column-width="100" row-height="100" gap="8px" columns="4" rows="3">
138
+ <div grid-col="0" grid-row="0">A</div>
139
+ <div grid-col="3" grid-row="0" grid-colspan="2">B (clamped to fit)</div>
140
+ </snice-grid>
141
+ ```
142
+
143
+ When an item's `col + colspan` exceeds the column count, its column position is clamped to `columns - colspan`.
144
+
145
+ ### Draggable with Snap-to-Grid
146
+
147
+ Enable `draggable` to let users drag items. Items snap to the nearest grid cell during and after drag.
148
+
149
+ ```html
150
+ <snice-grid draggable column-width="80" row-height="80" gap="8px" columns="4">
151
+ <div grid-col="0" grid-row="0" name="widget-a">Widget A</div>
152
+ <div grid-col="1" grid-row="0" name="widget-b">Widget B</div>
153
+ <div grid-col="0" grid-row="1" name="widget-c" grid-colspan="2">Widget C</div>
154
+ </snice-grid>
155
+ ```
156
+
157
+ A dashed drop-placeholder shows the target cell during drag. CSS classes applied during drag:
158
+
159
+ - `.grid-dragging` -- applied during drag (no transition, z-index: 100, opacity: 0.9, cursor: grabbing)
160
+ - `.grid-positioning` -- applied while animating to final position after drop (z-index: 99)
161
+
162
+ ```javascript
163
+ const grid = document.querySelector('snice-grid');
164
+ grid.addEventListener('grid-drag-item-positioned', (e) => {
165
+ const { item, col, row } = e.detail;
166
+ console.log(`${item.getAttribute('name')} dropped at col=${col} row=${row}`);
167
+ });
168
+ ```
169
+
170
+ ### Staggered Transitions
171
+
172
+ Use `stagger` to add incremental delay between each item's transition.
173
+
174
+ ```html
175
+ <snice-grid column-width="80" row-height="80" transition-duration="0.6s" stagger="40">
176
+ <div grid-col="0" grid-row="0">A</div>
177
+ <div grid-col="1" grid-row="0">B</div>
178
+ <div grid-col="2" grid-row="0">C</div>
179
+ </snice-grid>
180
+ ```
181
+
182
+ ### Right-to-Left / Bottom-to-Top
183
+
184
+ Set `origin-left="false"` or `origin-top="false"` to change the coordinate origin.
185
+
186
+ ```html
187
+ <snice-grid column-width="80" row-height="80" origin-left="false">
188
+ <div grid-col="0" grid-row="0">Aligned right</div>
189
+ </snice-grid>
190
+ ```
191
+
192
+ ### Save and Restore Layout
193
+
194
+ Use `getLayout()` and `setLayout()` to persist item arrangement. Items must have a `name` attribute.
195
+
196
+ ```javascript
197
+ const grid = document.querySelector('snice-grid');
198
+
199
+ // Save
200
+ const layout = grid.getLayout();
201
+ localStorage.setItem('dashboard', JSON.stringify(layout));
202
+
203
+ // Restore
204
+ const saved = JSON.parse(localStorage.getItem('dashboard'));
205
+ grid.setLayout(saved);
206
+ ```
207
+
208
+ The `GridLayout` object is a `Record<string, GridLayoutEntry>` keyed by item name:
209
+
210
+ ```typescript
211
+ interface GridLayoutEntry {
212
+ col: number;
213
+ row: number;
214
+ colspan?: number;
215
+ rowspan?: number;
216
+ order: number;
217
+ hidden?: boolean;
218
+ }
219
+ ```
220
+
221
+ ### Dynamic Items
222
+
223
+ Items can be added or removed dynamically. The layout automatically updates via slot change detection.
224
+
225
+ ```javascript
226
+ const grid = document.querySelector('snice-grid');
227
+
228
+ // Add an item
229
+ const item = document.createElement('div');
230
+ item.setAttribute('grid-col', '2');
231
+ item.setAttribute('grid-row', '0');
232
+ grid.appendChild(item);
233
+
234
+ // Remove an item
235
+ grid.lastElementChild.remove();
236
+ ```
237
+
238
+ ## Accessibility
239
+
240
+ - The inner container has `role="list"` for screen reader navigation.
241
+ - When `draggable` is enabled, items show `cursor: grab` (and `cursor: grabbing` during drag).
242
+
243
+ ### Notes
244
+
245
+ - Items are absolutely positioned using `transform` for smooth transitions.
246
+ - Item width/height is computed automatically from `columnWidth`, `rowHeight`, `colspan`, and `rowspan`.
247
+ - Uses `ResizeObserver` on the container for automatic re-layout when `resize` is `true`.
248
+ - FOUC is prevented by gating transitions behind the `[ready]` attribute.
249
+ - Uses `contain: layout style` on `:host`.
@@ -0,0 +1,138 @@
1
+ # snice-grid Component Design
2
+
3
+ ## Concept
4
+ Explicit grid-coordinate placement with animated transitions and drag-and-drop. Items declare their position in grid units (col, row); the component translates to pixel positions. Collision resolution via push-right-then-down.
5
+
6
+ ## Properties
7
+
8
+ | Property | Type | Default | Description |
9
+ |---|---|---|---|
10
+ | `gap` | string | `"1rem"` | Gap between cells (CSS value) |
11
+ | `column-width` | number | `80` | Cell width in px |
12
+ | `row-height` | number | `80` | Cell height in px |
13
+ | `columns` | number | `0` | Max columns (0 = auto-grow) |
14
+ | `rows` | number | `0` | Max rows (0 = auto-grow) |
15
+ | `origin-left` | boolean | `true` | RTL support |
16
+ | `origin-top` | boolean | `true` | Bottom-origin support |
17
+ | `transition-duration` | string | `"0.4s"` | Animation speed |
18
+ | `stagger` | number | `0` | Cascade delay (ms) per item |
19
+ | `resize` | boolean | `true` | ResizeObserver relayout |
20
+ | `draggable` | boolean | `false` | Enable drag-and-drop |
21
+ | `drag-throttle` | number | `100` | Drag relayout throttle (ms) |
22
+
23
+ ## Item Attributes (on slotted children)
24
+
25
+ | Attribute | Default | Description |
26
+ |---|---|---|
27
+ | `name` | required | Unique item identifier |
28
+ | `grid-col` | `0` | Column position |
29
+ | `grid-row` | `0` | Row position |
30
+ | `grid-colspan` | `1` | Columns spanned |
31
+ | `grid-rowspan` | `1` | Rows spanned |
32
+ | `hidden` | — | Hides item from layout |
33
+
34
+ ## Pixel Calculation
35
+
36
+ ```
37
+ x = col × (columnWidth + gap)
38
+ y = row × (rowHeight + gap)
39
+ width = colspan × columnWidth + (colspan - 1) × gap
40
+ height = rowspan × rowHeight + (rowspan - 1) × gap
41
+ ```
42
+
43
+ Items are auto-sized to their grid cell dimensions.
44
+
45
+ ## Collision Resolution
46
+
47
+ **Push-right-then-down**: When item A is placed at an occupied cell, the existing item shifts right to the next open cell that fits it (accounting for colspan/rowspan). If no room remains in that row, wraps to column 0 of the next row. Cascading — if the displaced item lands on another occupied area, that item pushes too.
48
+
49
+ When `columns` is set, "no room in row" means hitting the column limit. When `rows` is also set and the grid is completely full, the last displaced item goes out of bounds (clipped by `overflow: hidden`).
50
+
51
+ ## Drag Behavior
52
+
53
+ Same as binpack: free drag during gesture, on release snap to nearest grid cell. If that cell is occupied, push-right-then-down resolution kicks in. Dashed placeholder outline shows target cell during drag.
54
+
55
+ ## Container Sizing
56
+
57
+ - `columns`/`rows` unset (0): container grows to fit furthest item edge
58
+ - `columns` and/or `rows` set: fixed size with `overflow: hidden`
59
+ - Individual items can be hidden via `hidden` attribute (same as binpack)
60
+
61
+ ## Public API
62
+
63
+ ```ts
64
+ interface SniceGridElement extends HTMLElement {
65
+ gap: string;
66
+ columnWidth: number;
67
+ rowHeight: number;
68
+ columns: number;
69
+ rows: number;
70
+ horizontal: boolean;
71
+ originLeft: boolean;
72
+ originTop: boolean;
73
+ transitionDuration: string;
74
+ stagger: number;
75
+ resize: boolean;
76
+ draggable: boolean;
77
+ dragThrottle: number;
78
+
79
+ layout(): void;
80
+ fit(element: HTMLElement, col?: number, row?: number): void;
81
+ reloadItems(): void;
82
+ getItemElements(): HTMLElement[];
83
+ getLayout(): GridLayout;
84
+ setLayout(layout: GridLayout): void;
85
+ }
86
+ ```
87
+
88
+ ## Types
89
+
90
+ ```ts
91
+ interface GridLayoutEntry {
92
+ col: number;
93
+ row: number;
94
+ colspan?: number; // default 1
95
+ rowspan?: number; // default 1
96
+ order: number;
97
+ hidden?: boolean;
98
+ }
99
+
100
+ type GridLayout = Record<string, GridLayoutEntry>;
101
+
102
+ interface GridLayoutCompleteDetail {
103
+ items: HTMLElement[];
104
+ }
105
+
106
+ interface GridDragItemPositionedDetail {
107
+ item: HTMLElement;
108
+ col: number;
109
+ row: number;
110
+ }
111
+
112
+ interface GridEventMap {
113
+ 'grid-layout-complete': CustomEvent<GridLayoutCompleteDetail>;
114
+ 'grid-drag-item-positioned': CustomEvent<GridDragItemPositionedDetail>;
115
+ }
116
+ ```
117
+
118
+ ## CSS Custom Properties
119
+
120
+ - `--grid-gap` (maps to gap property)
121
+ - `--grid-transition-duration` (maps to transitionDuration property)
122
+
123
+ ## CSS Structure
124
+
125
+ - `:host` — `display: block; position: relative; overflow: hidden` (when columns/rows set)
126
+ - `::slotted(*)` — `position: absolute; box-sizing: border-box`
127
+ - `:host([ready]) ::slotted(*)` — transition on transform (FOUC gate)
128
+ - Dragging/placeholder styles identical to binpack pattern
129
+
130
+ ## Shared Patterns with Binpack
131
+
132
+ - `[ready]` attribute for FOUC prevention
133
+ - `name` attribute for item identification
134
+ - `getLayout()`/`setLayout()` for persistence
135
+ - Stagger animation delay
136
+ - ResizeObserver relayout
137
+ - Drag placeholder with dashed outline
138
+ - Same event naming convention