snice 4.10.0 → 4.12.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 (269) hide show
  1. package/adapters/react/carousel.d.ts +1 -0
  2. package/adapters/react/carousel.d.ts.map +1 -1
  3. package/adapters/react/carousel.js +1 -1
  4. package/adapters/react/carousel.js.map +1 -1
  5. package/adapters/react/carousel.tsx +2 -1
  6. package/bin/templates/CLAUDE.md +169 -113
  7. package/bin/templates/pwa/README.md +72 -94
  8. package/bin/templates/pwa/src/components/app-header.ts +218 -0
  9. package/bin/templates/pwa/src/components/notification-badge.ts +68 -0
  10. package/bin/templates/pwa/src/components/search-bar.ts +99 -0
  11. package/bin/templates/pwa/src/controllers/notification-controller.ts +42 -0
  12. package/bin/templates/pwa/src/guards/auth.ts +1 -1
  13. package/bin/templates/pwa/src/main.ts +19 -0
  14. package/bin/templates/pwa/src/pages/dashboard.ts +124 -23
  15. package/bin/templates/pwa/src/pages/data.ts +329 -0
  16. package/bin/templates/pwa/src/pages/notifications.ts +112 -30
  17. package/bin/templates/pwa/src/pages/profile.ts +86 -52
  18. package/bin/templates/pwa/src/pages/settings.ts +291 -0
  19. package/bin/templates/pwa/src/styles/global.css +12 -3
  20. package/dist/cdn/accordion/snice-accordion.js +1 -1
  21. package/dist/cdn/accordion/snice-accordion.min.js +1 -1
  22. package/dist/cdn/alert/snice-alert.js +1 -1
  23. package/dist/cdn/alert/snice-alert.min.js +1 -1
  24. package/dist/cdn/app-tiles/snice-app-tiles.js +1 -1
  25. package/dist/cdn/app-tiles/snice-app-tiles.min.js +1 -1
  26. package/dist/cdn/audio-recorder/snice-audio-recorder.js +1 -1
  27. package/dist/cdn/audio-recorder/snice-audio-recorder.min.js +1 -1
  28. package/dist/cdn/avatar/snice-avatar.js +1 -1
  29. package/dist/cdn/avatar/snice-avatar.min.js +1 -1
  30. package/dist/cdn/badge/snice-badge.js +1 -1
  31. package/dist/cdn/badge/snice-badge.min.js +1 -1
  32. package/dist/cdn/banner/snice-banner.js +1 -1
  33. package/dist/cdn/banner/snice-banner.min.js +1 -1
  34. package/dist/cdn/book/snice-book.js +1 -1
  35. package/dist/cdn/book/snice-book.min.js +1 -1
  36. package/dist/cdn/breadcrumbs/snice-breadcrumbs.js +1 -1
  37. package/dist/cdn/breadcrumbs/snice-breadcrumbs.min.js +1 -1
  38. package/dist/cdn/button/snice-button.js +1 -1
  39. package/dist/cdn/button/snice-button.min.js +1 -1
  40. package/dist/cdn/calendar/snice-calendar.js +1 -1
  41. package/dist/cdn/calendar/snice-calendar.min.js +1 -1
  42. package/dist/cdn/camera/README.md +1 -1
  43. package/dist/cdn/camera/snice-camera.js +1 -1
  44. package/dist/cdn/camera/snice-camera.min.js +1 -1
  45. package/dist/cdn/camera-annotate/snice-camera-annotate.js +1 -1
  46. package/dist/cdn/camera-annotate/snice-camera-annotate.min.js +1 -1
  47. package/dist/cdn/candlestick/snice-candlestick.js +1 -1
  48. package/dist/cdn/candlestick/snice-candlestick.min.js +1 -1
  49. package/dist/cdn/card/snice-card.js +1 -1
  50. package/dist/cdn/card/snice-card.min.js +1 -1
  51. package/dist/cdn/carousel/README.md +2 -2
  52. package/dist/cdn/carousel/snice-carousel.js +9 -3
  53. package/dist/cdn/carousel/snice-carousel.js.map +1 -1
  54. package/dist/cdn/carousel/snice-carousel.min.js +3 -3
  55. package/dist/cdn/carousel/snice-carousel.min.js.map +1 -1
  56. package/dist/cdn/chart/snice-chart.js +1 -1
  57. package/dist/cdn/chart/snice-chart.min.js +1 -1
  58. package/dist/cdn/chat/snice-chat.js +1 -1
  59. package/dist/cdn/chat/snice-chat.min.js +1 -1
  60. package/dist/cdn/checkbox/snice-checkbox.js +1 -1
  61. package/dist/cdn/checkbox/snice-checkbox.min.js +1 -1
  62. package/dist/cdn/chip/snice-chip.js +1 -1
  63. package/dist/cdn/chip/snice-chip.min.js +1 -1
  64. package/dist/cdn/code-block/snice-code-block.js +1 -1
  65. package/dist/cdn/code-block/snice-code-block.min.js +1 -1
  66. package/dist/cdn/color-display/snice-color-display.js +1 -1
  67. package/dist/cdn/color-display/snice-color-display.min.js +1 -1
  68. package/dist/cdn/color-picker/snice-color-picker.js +1 -1
  69. package/dist/cdn/color-picker/snice-color-picker.min.js +1 -1
  70. package/dist/cdn/command-palette/snice-command-palette.js +1 -1
  71. package/dist/cdn/command-palette/snice-command-palette.min.js +1 -1
  72. package/dist/cdn/comments/snice-comments.js +1 -1
  73. package/dist/cdn/comments/snice-comments.min.js +1 -1
  74. package/dist/cdn/countdown/snice-countdown.js +1 -1
  75. package/dist/cdn/countdown/snice-countdown.min.js +1 -1
  76. package/dist/cdn/cropper/snice-cropper.js +1 -1
  77. package/dist/cdn/cropper/snice-cropper.min.js +1 -1
  78. package/dist/cdn/date-picker/snice-date-picker.js +1 -1
  79. package/dist/cdn/date-picker/snice-date-picker.min.js +1 -1
  80. package/dist/cdn/diff/snice-diff.js +1 -1
  81. package/dist/cdn/diff/snice-diff.min.js +1 -1
  82. package/dist/cdn/divider/snice-divider.js +1 -1
  83. package/dist/cdn/divider/snice-divider.min.js +1 -1
  84. package/dist/cdn/doc/snice-doc.js +1 -1
  85. package/dist/cdn/doc/snice-doc.min.js +1 -1
  86. package/dist/cdn/draw/snice-draw.js +1 -1
  87. package/dist/cdn/draw/snice-draw.min.js +1 -1
  88. package/dist/cdn/drawer/snice-drawer.js +1 -1
  89. package/dist/cdn/drawer/snice-drawer.min.js +1 -1
  90. package/dist/cdn/empty-state/snice-empty-state.js +1 -1
  91. package/dist/cdn/empty-state/snice-empty-state.min.js +1 -1
  92. package/dist/cdn/file-gallery/snice-file-gallery.js +1 -1
  93. package/dist/cdn/file-gallery/snice-file-gallery.min.js +1 -1
  94. package/dist/cdn/file-upload/snice-file-upload.js +1 -1
  95. package/dist/cdn/file-upload/snice-file-upload.min.js +1 -1
  96. package/dist/cdn/flip-card/snice-flip-card.js +1 -1
  97. package/dist/cdn/flip-card/snice-flip-card.min.js +1 -1
  98. package/dist/cdn/flow/snice-flow.js +1 -1
  99. package/dist/cdn/flow/snice-flow.min.js +1 -1
  100. package/dist/cdn/funnel/snice-funnel.js +1 -1
  101. package/dist/cdn/funnel/snice-funnel.min.js +1 -1
  102. package/dist/cdn/gantt/README.md +1 -1
  103. package/dist/cdn/gantt/snice-gantt.js +1 -1
  104. package/dist/cdn/gantt/snice-gantt.min.js +1 -1
  105. package/dist/cdn/gauge/snice-gauge.js +1 -1
  106. package/dist/cdn/gauge/snice-gauge.min.js +1 -1
  107. package/dist/cdn/heatmap/snice-heatmap.js +1 -1
  108. package/dist/cdn/heatmap/snice-heatmap.min.js +1 -1
  109. package/dist/cdn/image/snice-image.js +1 -1
  110. package/dist/cdn/image/snice-image.min.js +1 -1
  111. package/dist/cdn/input/snice-input.js +1 -1
  112. package/dist/cdn/input/snice-input.min.js +1 -1
  113. package/dist/cdn/kanban/snice-kanban.js +1 -1
  114. package/dist/cdn/kanban/snice-kanban.min.js +1 -1
  115. package/dist/cdn/kpi/snice-kpi.js +1 -1
  116. package/dist/cdn/kpi/snice-kpi.min.js +1 -1
  117. package/dist/cdn/layout/snice-layout.js +1 -1
  118. package/dist/cdn/layout/snice-layout.min.js +1 -1
  119. package/dist/cdn/link/snice-link.js +1 -1
  120. package/dist/cdn/link/snice-link.min.js +1 -1
  121. package/dist/cdn/link-preview/snice-link-preview.js +1 -1
  122. package/dist/cdn/link-preview/snice-link-preview.min.js +1 -1
  123. package/dist/cdn/list/snice-list.js +1 -1
  124. package/dist/cdn/list/snice-list.min.js +1 -1
  125. package/dist/cdn/location/snice-location.js +1 -1
  126. package/dist/cdn/location/snice-location.min.js +1 -1
  127. package/dist/cdn/login/snice-login.js +1 -1
  128. package/dist/cdn/login/snice-login.min.js +1 -1
  129. package/dist/cdn/map/snice-map.js +1 -1
  130. package/dist/cdn/map/snice-map.min.js +1 -1
  131. package/dist/cdn/markdown/README.md +1 -1
  132. package/dist/cdn/markdown/snice-markdown.js +2 -2
  133. package/dist/cdn/markdown/snice-markdown.js.map +1 -1
  134. package/dist/cdn/markdown/snice-markdown.min.js +2 -2
  135. package/dist/cdn/markdown/snice-markdown.min.js.map +1 -1
  136. package/dist/cdn/masonry/snice-masonry.js +1 -1
  137. package/dist/cdn/masonry/snice-masonry.min.js +1 -1
  138. package/dist/cdn/menu/snice-menu.js +1 -1
  139. package/dist/cdn/menu/snice-menu.min.js +1 -1
  140. package/dist/cdn/modal/snice-modal.js +1 -1
  141. package/dist/cdn/modal/snice-modal.min.js +1 -1
  142. package/dist/cdn/music-player/snice-music-player.js +1 -1
  143. package/dist/cdn/music-player/snice-music-player.min.js +1 -1
  144. package/dist/cdn/nav/snice-nav.js +1 -1
  145. package/dist/cdn/nav/snice-nav.min.js +1 -1
  146. package/dist/cdn/network-graph/snice-network-graph.js +1 -1
  147. package/dist/cdn/network-graph/snice-network-graph.min.js +1 -1
  148. package/dist/cdn/notification-center/snice-notification-center.js +1 -1
  149. package/dist/cdn/notification-center/snice-notification-center.min.js +1 -1
  150. package/dist/cdn/org-chart/snice-org-chart.js +1 -1
  151. package/dist/cdn/org-chart/snice-org-chart.min.js +1 -1
  152. package/dist/cdn/pagination/snice-pagination.js +1 -1
  153. package/dist/cdn/pagination/snice-pagination.min.js +1 -1
  154. package/dist/cdn/paint/snice-paint.js +1 -1
  155. package/dist/cdn/paint/snice-paint.min.js +1 -1
  156. package/dist/cdn/pdf-viewer/README.md +2 -2
  157. package/dist/cdn/pdf-viewer/snice-pdf-viewer.js +72 -78
  158. package/dist/cdn/pdf-viewer/snice-pdf-viewer.js.map +1 -1
  159. package/dist/cdn/pdf-viewer/snice-pdf-viewer.min.js +3 -3
  160. package/dist/cdn/pdf-viewer/snice-pdf-viewer.min.js.map +1 -1
  161. package/dist/cdn/podcast-player/README.md +1 -1
  162. package/dist/cdn/podcast-player/snice-podcast-player.js +2 -2
  163. package/dist/cdn/podcast-player/snice-podcast-player.js.map +1 -1
  164. package/dist/cdn/podcast-player/snice-podcast-player.min.js +2 -2
  165. package/dist/cdn/podcast-player/snice-podcast-player.min.js.map +1 -1
  166. package/dist/cdn/pricing-table/snice-pricing-table.js +1 -1
  167. package/dist/cdn/pricing-table/snice-pricing-table.min.js +1 -1
  168. package/dist/cdn/progress/snice-progress.js +1 -1
  169. package/dist/cdn/progress/snice-progress.min.js +1 -1
  170. package/dist/cdn/qr-code/snice-qr-code.js +1 -1
  171. package/dist/cdn/qr-code/snice-qr-code.min.js +1 -1
  172. package/dist/cdn/qr-reader/snice-qr-reader.js +1 -1
  173. package/dist/cdn/qr-reader/snice-qr-reader.min.js +1 -1
  174. package/dist/cdn/radio/snice-radio.js +1 -1
  175. package/dist/cdn/radio/snice-radio.min.js +1 -1
  176. package/dist/cdn/rating/snice-rating.js +1 -1
  177. package/dist/cdn/rating/snice-rating.min.js +1 -1
  178. package/dist/cdn/recipe/snice-recipe.js +1 -1
  179. package/dist/cdn/recipe/snice-recipe.min.js +1 -1
  180. package/dist/cdn/runtime/README.md +1 -1
  181. package/dist/cdn/runtime/snice-runtime.esm.js +10 -3
  182. package/dist/cdn/runtime/snice-runtime.esm.js.map +1 -1
  183. package/dist/cdn/runtime/snice-runtime.esm.min.js +4 -4
  184. package/dist/cdn/runtime/snice-runtime.esm.min.js.map +1 -1
  185. package/dist/cdn/runtime/snice-runtime.js +10 -3
  186. package/dist/cdn/runtime/snice-runtime.js.map +1 -1
  187. package/dist/cdn/runtime/snice-runtime.min.js +4 -4
  188. package/dist/cdn/runtime/snice-runtime.min.js.map +1 -1
  189. package/dist/cdn/sankey/snice-sankey.js +1 -1
  190. package/dist/cdn/sankey/snice-sankey.min.js +1 -1
  191. package/dist/cdn/select/snice-select.js +1 -1
  192. package/dist/cdn/select/snice-select.min.js +1 -1
  193. package/dist/cdn/skeleton/snice-skeleton.js +1 -1
  194. package/dist/cdn/skeleton/snice-skeleton.min.js +1 -1
  195. package/dist/cdn/slider/snice-slider.js +1 -1
  196. package/dist/cdn/slider/snice-slider.min.js +1 -1
  197. package/dist/cdn/sortable/snice-sortable.js +1 -1
  198. package/dist/cdn/sortable/snice-sortable.min.js +1 -1
  199. package/dist/cdn/sparkline/snice-sparkline.js +1 -1
  200. package/dist/cdn/sparkline/snice-sparkline.min.js +1 -1
  201. package/dist/cdn/spinner/snice-spinner.js +1 -1
  202. package/dist/cdn/spinner/snice-spinner.min.js +1 -1
  203. package/dist/cdn/split-pane/snice-split-pane.js +1 -1
  204. package/dist/cdn/split-pane/snice-split-pane.min.js +1 -1
  205. package/dist/cdn/spotlight/snice-spotlight.js +1 -1
  206. package/dist/cdn/spotlight/snice-spotlight.min.js +1 -1
  207. package/dist/cdn/spreadsheet/snice-spreadsheet.js +1 -1
  208. package/dist/cdn/spreadsheet/snice-spreadsheet.min.js +1 -1
  209. package/dist/cdn/stepper/snice-stepper.js +1 -1
  210. package/dist/cdn/stepper/snice-stepper.min.js +1 -1
  211. package/dist/cdn/switch/snice-switch.js +1 -1
  212. package/dist/cdn/switch/snice-switch.min.js +1 -1
  213. package/dist/cdn/table/snice-table.js +1 -1
  214. package/dist/cdn/table/snice-table.min.js +1 -1
  215. package/dist/cdn/tabs/snice-tabs.js +1 -1
  216. package/dist/cdn/tabs/snice-tabs.min.js +1 -1
  217. package/dist/cdn/tag-input/snice-tag-input.js +1 -1
  218. package/dist/cdn/tag-input/snice-tag-input.min.js +1 -1
  219. package/dist/cdn/terminal/snice-terminal.js +1 -1
  220. package/dist/cdn/terminal/snice-terminal.min.js +1 -1
  221. package/dist/cdn/testimonial/snice-testimonial.js +1 -1
  222. package/dist/cdn/testimonial/snice-testimonial.min.js +1 -1
  223. package/dist/cdn/textarea/snice-textarea.js +1 -1
  224. package/dist/cdn/textarea/snice-textarea.min.js +1 -1
  225. package/dist/cdn/time-range-picker/snice-time-range-picker.js +1 -1
  226. package/dist/cdn/time-range-picker/snice-time-range-picker.min.js +1 -1
  227. package/dist/cdn/timeline/snice-timeline.js +1 -1
  228. package/dist/cdn/timeline/snice-timeline.min.js +1 -1
  229. package/dist/cdn/timer/snice-timer.js +1 -1
  230. package/dist/cdn/timer/snice-timer.min.js +1 -1
  231. package/dist/cdn/toast/snice-toast.js +1 -1
  232. package/dist/cdn/toast/snice-toast.min.js +1 -1
  233. package/dist/cdn/tooltip/snice-tooltip.js +1 -1
  234. package/dist/cdn/tooltip/snice-tooltip.min.js +1 -1
  235. package/dist/cdn/tree/snice-tree.js +1 -1
  236. package/dist/cdn/tree/snice-tree.min.js +1 -1
  237. package/dist/cdn/treemap/snice-treemap.js +1 -1
  238. package/dist/cdn/treemap/snice-treemap.min.js +1 -1
  239. package/dist/cdn/video-player/snice-video-player.js +1 -1
  240. package/dist/cdn/video-player/snice-video-player.min.js +1 -1
  241. package/dist/cdn/virtual-scroller/snice-virtual-scroller.js +1 -1
  242. package/dist/cdn/virtual-scroller/snice-virtual-scroller.min.js +1 -1
  243. package/dist/cdn/waterfall/snice-waterfall.js +1 -1
  244. package/dist/cdn/waterfall/snice-waterfall.min.js +1 -1
  245. package/dist/cdn/weather/snice-weather.js +1 -1
  246. package/dist/cdn/weather/snice-weather.min.js +1 -1
  247. package/dist/components/carousel/snice-carousel.js +8 -2
  248. package/dist/components/carousel/snice-carousel.js.map +1 -1
  249. package/dist/components/code-block/grammars/html.json +48 -0
  250. package/dist/components/markdown/snice-markdown.js +1 -1
  251. package/dist/components/markdown/snice-markdown.js.map +1 -1
  252. package/dist/components/pdf-viewer/snice-pdf-viewer.d.ts +9 -8
  253. package/dist/components/pdf-viewer/snice-pdf-viewer.js +71 -77
  254. package/dist/components/pdf-viewer/snice-pdf-viewer.js.map +1 -1
  255. package/dist/components/podcast-player/snice-podcast-player.js +1 -1
  256. package/dist/components/podcast-player/snice-podcast-player.js.map +1 -1
  257. package/dist/index.cjs +8 -1
  258. package/dist/index.cjs.map +1 -1
  259. package/dist/index.esm.js +8 -1
  260. package/dist/index.esm.js.map +1 -1
  261. package/dist/index.iife.js +8 -1
  262. package/dist/index.iife.js.map +1 -1
  263. package/dist/symbols.cjs +1 -1
  264. package/dist/symbols.esm.js +1 -1
  265. package/dist/transitions.cjs +1 -1
  266. package/dist/transitions.esm.js +1 -1
  267. package/docs/ai/patterns.md +1 -1
  268. package/docs/routing.md +2 -2
  269. package/package.json +4 -2
@@ -0,0 +1,291 @@
1
+ import { page } from '../router';
2
+ import { render, styles, context, dispatch, on, html, css } from 'snice';
3
+ import type { Placard, Context } from 'snice';
4
+ import { isAuthenticated } from '../guards/auth';
5
+ import type { Principal } from '../types/auth';
6
+
7
+ const placard: Placard = {
8
+ name: 'settings',
9
+ title: 'Settings',
10
+ icon: '\u2699\ufe0f',
11
+ show: true,
12
+ order: 4
13
+ };
14
+
15
+ @page({ tag: 'settings-page', routes: ['/settings'], guards: [isAuthenticated], placard })
16
+ export class SettingsPage extends HTMLElement {
17
+ private ctx?: Context;
18
+ displayName = '';
19
+ email = '';
20
+ theme: 'light' | 'dark' | 'system' = 'system';
21
+ notificationsEnabled = true;
22
+ saved = false;
23
+
24
+ @context()
25
+ handleContext(ctx: Context) {
26
+ this.ctx = ctx;
27
+ const principal = ctx.application.principal as Principal | undefined;
28
+ const user = principal?.user;
29
+ this.displayName = user?.name || '';
30
+ this.email = user?.email || '';
31
+
32
+ const storedTheme = localStorage.getItem('app-theme') as 'light' | 'dark' | 'system' | null;
33
+ this.theme = storedTheme || 'system';
34
+
35
+ this.notificationsEnabled = localStorage.getItem('notifications-enabled') !== 'false';
36
+ }
37
+
38
+ handleNameInput(e: Event) {
39
+ this.displayName = (e.target as HTMLInputElement).value;
40
+ }
41
+
42
+ handleEmailInput(e: Event) {
43
+ this.email = (e.target as HTMLInputElement).value;
44
+ }
45
+
46
+ setTheme(theme: 'light' | 'dark' | 'system') {
47
+ this.theme = theme;
48
+ localStorage.setItem('app-theme', theme);
49
+ this.applyTheme(theme);
50
+ }
51
+
52
+ toggleNotifications() {
53
+ this.notificationsEnabled = !this.notificationsEnabled;
54
+ localStorage.setItem('notifications-enabled', String(this.notificationsEnabled));
55
+ }
56
+
57
+ private applyTheme(theme: string) {
58
+ if (theme === 'dark') {
59
+ document.documentElement.style.colorScheme = 'dark';
60
+ } else if (theme === 'light') {
61
+ document.documentElement.style.colorScheme = 'light';
62
+ } else {
63
+ document.documentElement.style.colorScheme = '';
64
+ }
65
+ }
66
+
67
+ @on('keydown:ctrl+s')
68
+ preventDefaultSave(e: Event) {
69
+ e.preventDefault();
70
+ this.saveSettings();
71
+ }
72
+
73
+ @dispatch('settings-saved')
74
+ saveSettings() {
75
+ if (this.ctx) {
76
+ const principal = this.ctx.application.principal as Principal;
77
+ if (principal.user) {
78
+ principal.user.name = this.displayName;
79
+ principal.user.email = this.email;
80
+ }
81
+ this.ctx.update();
82
+ }
83
+
84
+ this.saved = true;
85
+ setTimeout(() => { this.saved = false; }, 2000);
86
+
87
+ return { displayName: this.displayName, email: this.email, theme: this.theme };
88
+ }
89
+
90
+ @render()
91
+ renderContent() {
92
+ return html`
93
+ <div class="container">
94
+ <h1>Settings</h1>
95
+ <p class="hint">Press Ctrl+S to save</p>
96
+
97
+ <if ${this.saved}>
98
+ <snice-alert variant="success" dismissible>
99
+ Settings saved successfully!
100
+ </snice-alert>
101
+ </if>
102
+
103
+ <snice-card class="section">
104
+ <h3>Profile</h3>
105
+ <div class="form-group">
106
+ <label>Display Name</label>
107
+ <snice-input
108
+ .value=${this.displayName}
109
+ @input=${this.handleNameInput}
110
+ placeholder="Your name"
111
+ ></snice-input>
112
+ </div>
113
+ <div class="form-group">
114
+ <label>Email</label>
115
+ <snice-input
116
+ .value=${this.email}
117
+ @input=${this.handleEmailInput}
118
+ placeholder="your@email.com"
119
+ ></snice-input>
120
+ </div>
121
+ </snice-card>
122
+
123
+ <snice-card class="section">
124
+ <h3>Appearance</h3>
125
+ <div class="theme-options">
126
+ <button
127
+ class="theme-btn ${this.theme === 'light' ? 'active' : ''}"
128
+ @click=${() => this.setTheme('light')}
129
+ >
130
+ <span class="theme-icon">&#9728;&#65039;</span>
131
+ Light
132
+ </button>
133
+ <button
134
+ class="theme-btn ${this.theme === 'dark' ? 'active' : ''}"
135
+ @click=${() => this.setTheme('dark')}
136
+ >
137
+ <span class="theme-icon">&#127769;</span>
138
+ Dark
139
+ </button>
140
+ <button
141
+ class="theme-btn ${this.theme === 'system' ? 'active' : ''}"
142
+ @click=${() => this.setTheme('system')}
143
+ >
144
+ <span class="theme-icon">&#128187;</span>
145
+ System
146
+ </button>
147
+ </div>
148
+ </snice-card>
149
+
150
+ <snice-card class="section">
151
+ <h3>Notifications</h3>
152
+ <div class="toggle-row">
153
+ <div>
154
+ <p class="toggle-label">Push Notifications</p>
155
+ <p class="toggle-desc">Receive real-time notification alerts</p>
156
+ </div>
157
+ <snice-switch
158
+ ?checked=${this.notificationsEnabled}
159
+ @change=${this.toggleNotifications}
160
+ ></snice-switch>
161
+ </div>
162
+ </snice-card>
163
+
164
+ <div class="actions">
165
+ <snice-button variant="primary" @click=${this.saveSettings}>
166
+ Save Settings
167
+ </snice-button>
168
+ </div>
169
+ </div>
170
+ `;
171
+ }
172
+
173
+ @styles()
174
+ componentStyles() {
175
+ return css`
176
+ .container {
177
+ padding: 2rem;
178
+ max-width: 800px;
179
+ margin: 0 auto;
180
+ }
181
+
182
+ h1 {
183
+ margin: 0 0 0.25rem 0;
184
+ color: var(--primary-color);
185
+ }
186
+
187
+ .hint {
188
+ margin: 0 0 2rem 0;
189
+ font-size: 0.8125rem;
190
+ color: var(--text-light);
191
+ }
192
+
193
+ .section {
194
+ padding: 1.5rem;
195
+ margin-bottom: 1.5rem;
196
+ }
197
+
198
+ h3 {
199
+ margin: 0 0 1.25rem 0;
200
+ color: var(--primary-color);
201
+ }
202
+
203
+ .form-group {
204
+ margin-bottom: 1rem;
205
+ }
206
+
207
+ .form-group:last-child {
208
+ margin-bottom: 0;
209
+ }
210
+
211
+ label {
212
+ display: block;
213
+ margin-bottom: 0.375rem;
214
+ font-size: 0.875rem;
215
+ font-weight: 500;
216
+ color: var(--text-color);
217
+ }
218
+
219
+ snice-input {
220
+ width: 100%;
221
+ }
222
+
223
+ .theme-options {
224
+ display: flex;
225
+ gap: 0.75rem;
226
+ }
227
+
228
+ .theme-btn {
229
+ flex: 1;
230
+ display: flex;
231
+ flex-direction: column;
232
+ align-items: center;
233
+ gap: 0.5rem;
234
+ padding: 1rem;
235
+ background: var(--bg-secondary);
236
+ border: 2px solid var(--border-color);
237
+ border-radius: var(--radius-md);
238
+ cursor: pointer;
239
+ color: var(--text-color);
240
+ font-size: 0.875rem;
241
+ transition: border-color 0.2s;
242
+ }
243
+
244
+ .theme-btn:hover {
245
+ border-color: var(--primary-color);
246
+ }
247
+
248
+ .theme-btn.active {
249
+ border-color: var(--primary-color);
250
+ background: color-mix(in srgb, var(--primary-color) 10%, transparent);
251
+ }
252
+
253
+ .theme-icon {
254
+ font-size: 1.5rem;
255
+ }
256
+
257
+ .toggle-row {
258
+ display: flex;
259
+ align-items: center;
260
+ justify-content: space-between;
261
+ }
262
+
263
+ .toggle-label {
264
+ margin: 0;
265
+ font-weight: 500;
266
+ color: var(--text-color);
267
+ }
268
+
269
+ .toggle-desc {
270
+ margin: 0.25rem 0 0 0;
271
+ font-size: 0.8125rem;
272
+ color: var(--text-light);
273
+ }
274
+
275
+ .actions {
276
+ display: flex;
277
+ justify-content: flex-end;
278
+ }
279
+
280
+ snice-alert {
281
+ margin-bottom: 1.5rem;
282
+ }
283
+
284
+ @media (max-width: 640px) {
285
+ .theme-options {
286
+ flex-direction: column;
287
+ }
288
+ }
289
+ `;
290
+ }
291
+ }
@@ -25,7 +25,7 @@
25
25
  sans-serif;
26
26
  line-height: 1.5;
27
27
  font-weight: 400;
28
- color-scheme: light;
28
+ color-scheme: light dark;
29
29
  }
30
30
 
31
31
  * {
@@ -43,13 +43,22 @@ body {
43
43
  min-height: 100vh;
44
44
  }
45
45
 
46
+ /* Dark theme via color-scheme or prefers-color-scheme */
46
47
  @media (prefers-color-scheme: dark) {
47
- :root {
48
+ :root:not([style*="color-scheme: light"]) {
48
49
  --bg-primary: #1f2937;
49
50
  --bg-secondary: #111827;
50
51
  --text-color: #f9fafb;
51
52
  --text-light: #9ca3af;
52
53
  --border-color: #374151;
53
- color-scheme: dark;
54
54
  }
55
55
  }
56
+
57
+ /* Forced dark via settings page */
58
+ :root[style*="color-scheme: dark"] {
59
+ --bg-primary: #1f2937;
60
+ --bg-secondary: #111827;
61
+ --text-color: #f9fafb;
62
+ --text-light: #9ca3af;
63
+ --border-color: #374151;
64
+ }
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -11,7 +11,7 @@ CDN build of the Snice camera component. Requires the Snice runtime (`snice-runt
11
11
  ```
12
12
 
13
13
  ## Size
14
- - Minified: 14.5 KB
14
+ - Minified: 14.6 KB
15
15
  - Gzipped: 4.3 KB
16
16
 
17
17
  ## Theme
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -11,8 +11,8 @@ CDN build of the Snice carousel component. Requires the Snice runtime (`snice-ru
11
11
  ```
12
12
 
13
13
  ## Size
14
- - Minified: 10.9 KB
15
- - Gzipped: 3.3 KB
14
+ - Minified: 11.1 KB
15
+ - Gzipped: 3.4 KB
16
16
 
17
17
  ## Theme
18
18
  For proper styling, link the Snice theme CSS:
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v4.9.0
2
+ * snice v4.11.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -106,6 +106,9 @@ var SniceCarousel = (function (exports, snice) {
106
106
  let _slotElement_decorators;
107
107
  let _slotElement_initializers = [];
108
108
  let _slotElement_extraInitializers = [];
109
+ let _slideCount_decorators;
110
+ let _slideCount_initializers = [];
111
+ let _slideCount_extraInitializers = [];
109
112
  let _init_decorators;
110
113
  let _handleSlotChange_decorators;
111
114
  let _cleanup_decorators;
@@ -129,7 +132,8 @@ var SniceCarousel = (function (exports, snice) {
129
132
  this.spaceBetween = (__runInitializers(this, _slidesPerView_extraInitializers), __runInitializers(this, _spaceBetween_initializers, 0));
130
133
  this.container = (__runInitializers(this, _spaceBetween_extraInitializers), __runInitializers(this, _container_initializers, void 0));
131
134
  this.slotElement = (__runInitializers(this, _container_extraInitializers), __runInitializers(this, _slotElement_initializers, void 0));
132
- this.slideCount = (__runInitializers(this, _slotElement_extraInitializers), 0);
135
+ this.slideCount = (__runInitializers(this, _slotElement_extraInitializers), __runInitializers(this, _slideCount_initializers, 0));
136
+ this.autoplayTimer = __runInitializers(this, _slideCount_extraInitializers);
133
137
  this.previousIndex = 0;
134
138
  }
135
139
  static {
@@ -145,6 +149,7 @@ var SniceCarousel = (function (exports, snice) {
145
149
  _spaceBetween_decorators = [snice.property({ type: Number, attribute: 'space-between' })];
146
150
  _container_decorators = [snice.query('.carousel__container')];
147
151
  _slotElement_decorators = [snice.query('slot')];
152
+ _slideCount_decorators = [snice.property({ type: Number })];
148
153
  _init_decorators = [snice.ready()];
149
154
  _handleSlotChange_decorators = [snice.on('slotchange', { target: 'slot' })];
150
155
  _cleanup_decorators = [snice.dispose()];
@@ -172,6 +177,7 @@ var SniceCarousel = (function (exports, snice) {
172
177
  __esDecorate(null, null, _spaceBetween_decorators, { kind: "field", name: "spaceBetween", static: false, private: false, access: { has: obj => "spaceBetween" in obj, get: obj => obj.spaceBetween, set: (obj, value) => { obj.spaceBetween = value; } }, metadata: _metadata }, _spaceBetween_initializers, _spaceBetween_extraInitializers);
173
178
  __esDecorate(null, null, _container_decorators, { kind: "field", name: "container", static: false, private: false, access: { has: obj => "container" in obj, get: obj => obj.container, set: (obj, value) => { obj.container = value; } }, metadata: _metadata }, _container_initializers, _container_extraInitializers);
174
179
  __esDecorate(null, null, _slotElement_decorators, { kind: "field", name: "slotElement", static: false, private: false, access: { has: obj => "slotElement" in obj, get: obj => obj.slotElement, set: (obj, value) => { obj.slotElement = value; } }, metadata: _metadata }, _slotElement_initializers, _slotElement_extraInitializers);
180
+ __esDecorate(null, null, _slideCount_decorators, { kind: "field", name: "slideCount", static: false, private: false, access: { has: obj => "slideCount" in obj, get: obj => obj.slideCount, set: (obj, value) => { obj.slideCount = value; } }, metadata: _metadata }, _slideCount_initializers, _slideCount_extraInitializers);
175
181
  __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
176
182
  _classThis = _classDescriptor.value;
177
183
  if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
@@ -253,7 +259,7 @@ var SniceCarousel = (function (exports, snice) {
253
259
 
254
260
  <if ${this.showIndicators}>
255
261
  <div class="carousel__indicators" part="indicators">
256
- ${Array.from({ length: this.slideCount - this.slidesPerView + 1 }).map((_, index) => {
262
+ ${Array.from({ length: Math.max(0, this.slideCount - this.slidesPerView + 1) }).map((_, index) => {
257
263
  const indicatorClasses = [
258
264
  'carousel__indicator',
259
265
  index === this.activeIndex ? 'carousel__indicator--active' : ''