lightview 1.8.1-b → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/.agent/workflows/daisyui-component-migration.md +155 -0
  2. package/.codacy/cli.sh +149 -0
  3. package/.codacy/codacy.yaml +15 -0
  4. package/.github/instructions/codacy.instructions.md +72 -0
  5. package/.wranglerignore +21 -0
  6. package/README.md +1331 -21
  7. package/_headers +4 -0
  8. package/build.js +70 -0
  9. package/components/actions/button.js +151 -0
  10. package/components/actions/dropdown.js +120 -0
  11. package/components/actions/modal.js +146 -0
  12. package/components/actions/swap.js +118 -0
  13. package/components/daisyui.js +288 -0
  14. package/components/data-display/accordion.js +128 -0
  15. package/components/data-display/alert.js +112 -0
  16. package/components/data-display/avatar.js +170 -0
  17. package/components/data-display/badge.js +82 -0
  18. package/components/data-display/card.js +151 -0
  19. package/components/data-display/carousel.js +94 -0
  20. package/components/data-display/chart.js +220 -0
  21. package/components/data-display/chat.js +128 -0
  22. package/components/data-display/collapse.js +103 -0
  23. package/components/data-display/countdown.js +69 -0
  24. package/components/data-display/diff.js +111 -0
  25. package/components/data-display/kbd.js +65 -0
  26. package/components/data-display/loading.js +75 -0
  27. package/components/data-display/progress.js +79 -0
  28. package/components/data-display/radial-progress.js +88 -0
  29. package/components/data-display/skeleton.js +66 -0
  30. package/components/data-display/stats.js +159 -0
  31. package/components/data-display/table.js +146 -0
  32. package/components/data-display/timeline.js +146 -0
  33. package/components/data-display/toast.js +72 -0
  34. package/components/data-display/tooltip.js +74 -0
  35. package/components/data-input/checkbox.js +253 -0
  36. package/components/data-input/file-input.js +224 -0
  37. package/components/data-input/input.js +264 -0
  38. package/components/data-input/radio.js +338 -0
  39. package/components/data-input/range.js +204 -0
  40. package/components/data-input/rating.js +219 -0
  41. package/components/data-input/select.js +287 -0
  42. package/components/data-input/textarea.js +287 -0
  43. package/components/data-input/toggle.js +201 -0
  44. package/components/index.js +137 -0
  45. package/components/layout/divider.js +72 -0
  46. package/components/layout/drawer.js +142 -0
  47. package/components/layout/footer.js +100 -0
  48. package/components/layout/hero.js +109 -0
  49. package/components/layout/indicator.js +90 -0
  50. package/components/layout/join.js +78 -0
  51. package/components/layout/navbar.js +110 -0
  52. package/components/navigation/breadcrumbs.js +91 -0
  53. package/components/navigation/dock.js +103 -0
  54. package/components/navigation/menu.js +126 -0
  55. package/components/navigation/pagination.js +105 -0
  56. package/components/navigation/steps.js +89 -0
  57. package/components/navigation/tabs.css +177 -0
  58. package/components/navigation/tabs.js +123 -0
  59. package/components/theme/theme-switch.css +65 -0
  60. package/components/theme/theme-switch.js +177 -0
  61. package/docs/about.html +164 -0
  62. package/docs/api/computed.html +184 -0
  63. package/docs/api/effects.html +173 -0
  64. package/docs/api/elements.html +180 -0
  65. package/docs/api/enhance.html +225 -0
  66. package/docs/api/hypermedia.html +165 -0
  67. package/docs/api/index.html +178 -0
  68. package/docs/api/nav.html +18 -0
  69. package/docs/api/signals.html +136 -0
  70. package/docs/api/state.html +217 -0
  71. package/docs/assets/images/logo-favicon.svg +42 -0
  72. package/docs/assets/images/logo-static.svg +40 -0
  73. package/docs/assets/images/logo.svg +66 -0
  74. package/docs/assets/js/examplify.js +395 -0
  75. package/docs/assets/styles/site.css +1102 -0
  76. package/docs/assets/styles/themes.css +236 -0
  77. package/docs/components/accordion.html +439 -0
  78. package/docs/components/alert.html +528 -0
  79. package/docs/components/avatar.html +586 -0
  80. package/docs/components/badge.html +531 -0
  81. package/docs/components/breadcrumbs.html +278 -0
  82. package/docs/components/button.html +579 -0
  83. package/docs/components/card.html +561 -0
  84. package/docs/components/carousel.html +286 -0
  85. package/docs/components/chart-area.html +702 -0
  86. package/docs/components/chart-bar.html +782 -0
  87. package/docs/components/chart-column.html +735 -0
  88. package/docs/components/chart-line.html +794 -0
  89. package/docs/components/chart-pie.html +823 -0
  90. package/docs/components/chart.html +612 -0
  91. package/docs/components/chat.html +547 -0
  92. package/docs/components/checkbox.html +641 -0
  93. package/docs/components/collapse.html +536 -0
  94. package/docs/components/component-nav.html +53 -0
  95. package/docs/components/countdown.html +470 -0
  96. package/docs/components/diff.html +245 -0
  97. package/docs/components/divider.html +240 -0
  98. package/docs/components/dock.html +277 -0
  99. package/docs/components/drawer.html +515 -0
  100. package/docs/components/dropdown.html +479 -0
  101. package/docs/components/file-input.html +591 -0
  102. package/docs/components/footer.html +301 -0
  103. package/docs/components/gallery.html +504 -0
  104. package/docs/components/hero.html +264 -0
  105. package/docs/components/index.css +840 -0
  106. package/docs/components/index.html +735 -0
  107. package/docs/components/indicator.html +342 -0
  108. package/docs/components/input.html +644 -0
  109. package/docs/components/join.html +285 -0
  110. package/docs/components/kbd.html +322 -0
  111. package/docs/components/loading.html +521 -0
  112. package/docs/components/menu.html +461 -0
  113. package/docs/components/modal.html +639 -0
  114. package/docs/components/navbar.html +321 -0
  115. package/docs/components/pagination.html +279 -0
  116. package/docs/components/progress.html +514 -0
  117. package/docs/components/radial-progress.html +434 -0
  118. package/docs/components/radio.html +655 -0
  119. package/docs/components/range.html +611 -0
  120. package/docs/components/rating.html +642 -0
  121. package/docs/components/select.html +696 -0
  122. package/docs/components/sidebar-setup.js +93 -0
  123. package/docs/components/skeleton.html +447 -0
  124. package/docs/components/spinner.html +68 -0
  125. package/docs/components/stats.html +486 -0
  126. package/docs/components/steps.html +356 -0
  127. package/docs/components/swap.html +517 -0
  128. package/docs/components/switch.html +68 -0
  129. package/docs/components/table.html +668 -0
  130. package/docs/components/tabs.html +506 -0
  131. package/docs/components/text-input.html +68 -0
  132. package/docs/components/textarea.html +603 -0
  133. package/docs/components/timeline.html +487 -0
  134. package/docs/components/toast.html +474 -0
  135. package/docs/components/toggle.html +564 -0
  136. package/docs/components/tooltip.html +423 -0
  137. package/docs/examples/getting-started-example.html +40 -0
  138. package/docs/examples/index.html +93 -0
  139. package/docs/getting-started/index.html +739 -0
  140. package/docs/getting-started/reviews.html +23 -0
  141. package/docs/getting-started/reviews.odom +108 -0
  142. package/docs/getting-started/reviews.vdom +84 -0
  143. package/docs/index.html +134 -0
  144. package/docs/playground.html +416 -0
  145. package/docs/router.html +285 -0
  146. package/docs/styles/index.html +190 -0
  147. package/functions/_middleware.js +32 -0
  148. package/index.html +309 -0
  149. package/lightview-router.js +364 -0
  150. package/lightview-x.js +1577 -0
  151. package/lightview.js +658 -1109
  152. package/lightview.js.backup +793 -0
  153. package/middleware/locale.js +25 -0
  154. package/middleware/markdown.js +44 -0
  155. package/middleware/notFound.js +37 -0
  156. package/package.json +27 -41
  157. package/watch.js +92 -0
  158. package/wrangler.toml +12 -0
  159. package/.idea/lightview.iml +0 -12
  160. package/.idea/modules.xml +0 -8
  161. package/.idea/vcs.xml +0 -6
  162. package/LICENSE +0 -21
  163. package/codepen-no-tabs-embed.css +0 -2
  164. package/components/chart/chart.html +0 -17
  165. package/components/chart/example.html +0 -32
  166. package/components/chart.html +0 -83
  167. package/components/components.js +0 -113
  168. package/components/gantt/example.html +0 -22
  169. package/components/gantt/gantt.html +0 -42
  170. package/components/gauge/example.html +0 -28
  171. package/components/gauge/gauge.html +0 -20
  172. package/components/gauge.html +0 -60
  173. package/components/orgchart/example.html +0 -25
  174. package/components/orgchart/orgchart.html +0 -41
  175. package/components/repl/code-editor.html +0 -64
  176. package/components/repl/editor.html +0 -37
  177. package/components/repl/editorjs-inline-tool/index.js +0 -3
  178. package/components/repl/editorjs-inline-tool/inline-tools.js +0 -28
  179. package/components/repl/editorjs-inline-tool/tool.js +0 -175
  180. package/components/repl/repl-with-wysiwyg.html +0 -355
  181. package/components/repl/repl.html +0 -345
  182. package/components/repl/sup.js +0 -44
  183. package/components/repl/wysiwyg-repl.html +0 -258
  184. package/components/timeline/example.html +0 -33
  185. package/components/timeline/timeline.html +0 -44
  186. package/components/timeline.html +0 -81
  187. package/examples/anchor.html +0 -11
  188. package/examples/chart.html +0 -34
  189. package/examples/counter.html +0 -26
  190. package/examples/counter.test.mjs +0 -47
  191. package/examples/counter2.html +0 -26
  192. package/examples/directives.html +0 -79
  193. package/examples/foreign.html +0 -50
  194. package/examples/forgeinform.html +0 -98
  195. package/examples/form.html +0 -61
  196. package/examples/gauge.html +0 -18
  197. package/examples/invalid-template-literals.html +0 -44
  198. package/examples/medium/remote.html +0 -60
  199. package/examples/message.html +0 -18
  200. package/examples/nested.html +0 -11
  201. package/examples/object-bound-form.html +0 -34
  202. package/examples/remote-server.js +0 -51
  203. package/examples/remote.html +0 -34
  204. package/examples/remote.json +0 -1
  205. package/examples/scratch.html +0 -69
  206. package/examples/sensors/index.html +0 -30
  207. package/examples/sensors/sensor-server.js +0 -30
  208. package/examples/shared.html +0 -41
  209. package/examples/template.html +0 -33
  210. package/examples/timeline.html +0 -21
  211. package/examples/todo.html +0 -38
  212. package/examples/top.html +0 -10
  213. package/examples/types.html +0 -94
  214. package/examples/xor.html +0 -62
  215. package/jest-puppeteer.config.js +0 -5
  216. package/jest.config.json +0 -12
  217. package/sites/client.html +0 -48
  218. package/sites/index.html +0 -247
  219. package/test/basic.html +0 -93
  220. package/test/basic.test.mjs +0 -315
  221. package/test/extended.html +0 -29
  222. package/test/extended.test.mjs +0 -448
  223. package/types.js +0 -534
  224. package/unsplash.key +0 -1
@@ -0,0 +1,486 @@
1
+ <!-- SEO-friendly SPA Shim -->
2
+ <script src="/lightview-router.js"></script>
3
+ <script>
4
+ if (window.LightviewRouter) {
5
+ LightviewRouter.base('/index.html');
6
+ }
7
+ </script>
8
+
9
+ <!-- Load the page-specific stylesheet -->
10
+ <link rel="stylesheet" href="./index.css">
11
+
12
+ <!-- Gallery Structure -->
13
+ <div class="gallery-page">
14
+ <div class="gallery-layout">
15
+ <!-- Sidebar Overlay -->
16
+ <div id="sidebar-overlay" class="sidebar-overlay"></div>
17
+
18
+ <!-- Sidebar -->
19
+ <div id="gallery-sidebar" class="gallery-sidebar" style="visibility: hidden" src="./component-nav.html"></div>
20
+
21
+ <!-- Main Content -->
22
+ <div id="gallery-main" class="gallery-main">
23
+ <!-- Header Container -->
24
+ <div
25
+ style="position: sticky; top: 0; z-index: 30; background: var(--gallery-surface); border-bottom: 1px solid var(--gallery-border); backdrop-filter: blur(8px);">
26
+ <!-- Breadcrumbs Row -->
27
+ <div style="padding: 0.75rem 1.5rem 0;">
28
+ <script>
29
+ (() => {
30
+ const { Breadcrumbs } = Lightview.tags;
31
+ const breadcrumbs = Breadcrumbs({
32
+ id: 'page-breadcrumbs',
33
+ items: [
34
+ { label: 'Components', href: '/docs/components' },
35
+ { label: 'Stats' }
36
+ ]
37
+ });
38
+ document.currentScript.replaceWith(breadcrumbs.domEl);
39
+ })();
40
+ </script>
41
+ </div>
42
+ <!-- Title Row -->
43
+ <div class="gallery-header"
44
+ style="border-bottom: none; height: auto; padding-top: 0.5rem; padding-bottom: 0.75rem;">
45
+ <button id="toggle-btn" class="toggle-btn" aria-label="Toggle Sidebar">
46
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="toggle-icon"
47
+ style="stroke: currentColor; stroke-width: 2;">
48
+ <path stroke-linecap="round" stroke-linejoin="round" d="M15 19l-7-7 7-7" />
49
+ <path stroke-linecap="round" stroke-linejoin="round" d="M11 19l-7-7 7-7" />
50
+ </svg>
51
+ </button>
52
+ <h1 class="gallery-title">Stats</h1>
53
+ </div>
54
+ </div>
55
+
56
+ <!-- Content -->
57
+ <div class="gallery-content">
58
+ <div class="section-content" style="max-width: 1000px;">
59
+ <p class="text-lg" style="opacity: 0.7; margin-bottom: 1.5rem;">
60
+ Stats display numeric information with optional icons and descriptions.
61
+ Perfect for dashboards and analytics.
62
+ </p>
63
+
64
+ <!-- Basic Example with Examplify -->
65
+ <div class="card bg-base-200" style="margin-bottom: 2rem;">
66
+ <div class="card-body">
67
+ <h2 class="card-title">Basic Example</h2>
68
+ <p class="text-sm" style="opacity: 0.7; margin-bottom: 1rem;">Dashboard stats with icons</p>
69
+
70
+ <!-- Tabs -->
71
+ <script>
72
+ window.switchSyntaxTab = (tabId) => {
73
+ const tabs = ['tagged', 'vdom', 'object'];
74
+ tabs.forEach(t => {
75
+ const tabEl = document.getElementById(`tab-btn-${t}`);
76
+ const contentEl = document.getElementById(`syntax-${t}`);
77
+ if (t === tabId) {
78
+ tabEl.classList.add('syntax-tab-active');
79
+ contentEl.style.display = 'block';
80
+ } else {
81
+ tabEl.classList.remove('syntax-tab-active');
82
+ contentEl.style.display = 'none';
83
+ }
84
+ });
85
+ };
86
+ </script>
87
+ <div role="tablist" class="syntax-tabs" style="margin-bottom: 1rem;">
88
+ <button id="tab-btn-tagged" role="tab" class="syntax-tab syntax-tab-active"
89
+ onclick="switchSyntaxTab('tagged')">Tagged</button>
90
+ <button id="tab-btn-vdom" role="tab" class="syntax-tab"
91
+ onclick="switchSyntaxTab('vdom')">vDOM</button>
92
+ <button id="tab-btn-object" role="tab" class="syntax-tab"
93
+ onclick="switchSyntaxTab('object')">Object
94
+ DOM</button>
95
+ </div>
96
+
97
+ <!-- Tagged Syntax -->
98
+ <div id="syntax-tagged">
99
+ <pre><script>
100
+ examplify(document.currentScript.nextElementSibling, {
101
+ at: document.currentScript.parentElement,
102
+ scripts: ['/lightview.js', '/lightview-x.js'],
103
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
104
+ type: 'module',
105
+ minHeight: 120,
106
+ autoRun: true
107
+ });
108
+ </script><code contenteditable="true">await import('/components/data-display/stats.js');
109
+ const { tags, $ } = Lightview;
110
+ const { Stats } = tags;
111
+
112
+ const stats = Stats({ style: 'box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);' },
113
+ Stats.Stat({},
114
+ Stats.Title({}, 'Total Users'),
115
+ Stats.Value({}, '89,400'),
116
+ Stats.Desc({}, '↗︎ 21% from last month')
117
+ ),
118
+ Stats.Stat({},
119
+ Stats.Title({}, 'Page Views'),
120
+ Stats.Value({ style: 'color: oklch(var(--p));' }, '2.6M'),
121
+ Stats.Desc({}, '↗︎ 14% from last month')
122
+ ),
123
+ Stats.Stat({},
124
+ Stats.Title({}, 'Conversion'),
125
+ Stats.Value({ style: 'color: oklch(var(--s));' }, '4.2%'),
126
+ Stats.Desc({}, '↘︎ 2% from last month')
127
+ )
128
+ );
129
+
130
+ $('#example').content(stats);</code></pre>
131
+ </div>
132
+
133
+ <!-- vDOM Syntax -->
134
+ <div id="syntax-vdom" style="display: none;">
135
+ <pre><script>
136
+ examplify(document.currentScript.nextElementSibling, {
137
+ at: document.currentScript.parentElement,
138
+ scripts: ['/lightview.js', '/lightview-x.js'],
139
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
140
+ type: 'module',
141
+ minHeight: 120
142
+ });
143
+ </script><code contenteditable="true">await import('/components/data-display/stats.js');
144
+ const { $, tags } = Lightview;
145
+ const { Stats } = tags;
146
+
147
+ const stats = {
148
+ tag: Stats,
149
+ attributes: { style: 'box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);' },
150
+ children: [
151
+ {
152
+ tag: Stats.Stat,
153
+ children: [
154
+ { tag: Stats.Title, children: ['Total Users'] },
155
+ { tag: Stats.Value, children: ['89,400'] },
156
+ { tag: Stats.Desc, children: ['↗︎ 21% from last month'] }
157
+ ]
158
+ },
159
+ {
160
+ tag: Stats.Stat,
161
+ children: [
162
+ { tag: Stats.Title, children: ['Page Views'] },
163
+ { tag: Stats.Value, attributes: { style: 'color: oklch(var(--p));' }, children: ['2.6M'] },
164
+ { tag: Stats.Desc, children: ['↗︎ 14% from last month'] }
165
+ ]
166
+ },
167
+ {
168
+ tag: Stats.Stat,
169
+ children: [
170
+ { tag: Stats.Title, children: ['Conversion'] },
171
+ { tag: Stats.Value, attributes: { style: 'color: oklch(var(--s));' }, children: ['4.2%'] },
172
+ { tag: Stats.Desc, children: ['↘︎ 2% from last month'] }
173
+ ]
174
+ }
175
+ ]
176
+ };
177
+
178
+ $('#example').content(stats);</code></pre>
179
+ </div>
180
+
181
+ <!-- Object DOM Syntax -->
182
+ <div id="syntax-object" style="display: none;">
183
+ <pre><script>
184
+ examplify(document.currentScript.nextElementSibling, {
185
+ at: document.currentScript.parentElement,
186
+ scripts: ['/lightview.js', '/lightview-x.js'],
187
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
188
+ type: 'module',
189
+ minHeight: 120
190
+ });
191
+ </script><code contenteditable="true">await import('/components/data-display/stats.js');
192
+ const { $ } = Lightview;
193
+
194
+ const stats = {
195
+ Stats: {
196
+ style: 'box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);',
197
+ children: [
198
+ {
199
+ 'Stats.Stat': {
200
+ children: [
201
+ { 'Stats.Title': { children: ['Total Users'] } },
202
+ { 'Stats.Value': { children: ['89,400'] } },
203
+ { 'Stats.Desc': { children: ['↗︎ 21% from last month'] } }
204
+ ]
205
+ }
206
+ },
207
+ {
208
+ 'Stats.Stat': {
209
+ children: [
210
+ { 'Stats.Title': { children: ['Page Views'] } },
211
+ { 'Stats.Value': { style: 'color: oklch(var(--p));', children: ['2.6M'] } },
212
+ { 'Stats.Desc': { children: ['↗︎ 14% from last month'] } }
213
+ ]
214
+ }
215
+ },
216
+ {
217
+ 'Stats.Stat': {
218
+ children: [
219
+ { 'Stats.Title': { children: ['Conversion'] } },
220
+ { 'Stats.Value': { style: 'color: oklch(var(--s));', children: ['4.2%'] } },
221
+ { 'Stats.Desc': { children: ['↘︎ 2% from last month'] } }
222
+ ]
223
+ }
224
+ }
225
+ ]
226
+ }
227
+ };
228
+
229
+ $('#example').content(stats);</code></pre>
230
+ </div>
231
+ </div>
232
+ </div>
233
+
234
+ <!-- Reactive Example with Examplify -->
235
+ <div class="card bg-base-200" style="margin-bottom: 2rem;">
236
+ <div class="card-body">
237
+ <h2 class="card-title">Live Analytics</h2>
238
+ <p class="text-sm" style="opacity: 0.7; margin-bottom: 1rem;">Stats with reactive values</p>
239
+
240
+ <!-- Tabs -->
241
+ <script>
242
+ window.switchReactiveSyntaxTab = (tabId) => {
243
+ const tabs = ['tagged', 'vdom', 'object'];
244
+ tabs.forEach(t => {
245
+ const tabEl = document.getElementById(`reactive-tab-btn-${t}`);
246
+ const contentEl = document.getElementById(`reactive-syntax-${t}`);
247
+ if (t === tabId) {
248
+ tabEl.classList.add('syntax-tab-active');
249
+ contentEl.style.display = 'block';
250
+ } else {
251
+ tabEl.classList.remove('syntax-tab-active');
252
+ contentEl.style.display = 'none';
253
+ }
254
+ });
255
+ };
256
+ </script>
257
+ <div role="tablist" class="syntax-tabs" style="margin-bottom: 1rem;">
258
+ <button id="reactive-tab-btn-tagged" role="tab" class="syntax-tab syntax-tab-active"
259
+ onclick="switchReactiveSyntaxTab('tagged')">Tagged</button>
260
+ <button id="reactive-tab-btn-vdom" role="tab" class="syntax-tab"
261
+ onclick="switchReactiveSyntaxTab('vdom')">vDOM</button>
262
+ <button id="reactive-tab-btn-object" role="tab" class="syntax-tab"
263
+ onclick="switchReactiveSyntaxTab('object')">Object DOM</button>
264
+ </div>
265
+
266
+ <!-- Tagged Syntax -->
267
+ <div id="reactive-syntax-tagged">
268
+ <pre><script>
269
+ examplify(document.currentScript.nextElementSibling, {
270
+ at: document.currentScript.parentElement,
271
+ scripts: ['/lightview.js', '/lightview-x.js'],
272
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
273
+ type: 'module',
274
+ minHeight: 120
275
+ });
276
+ </script><code contenteditable="true">await import('/components/data-display/stats.js');
277
+ const { signal, tags, $ } = Lightview;
278
+ const { Stats } = tags;
279
+
280
+ const visitors = signal(1234);
281
+ const sessions = signal(567);
282
+
283
+ // Simulate live updates
284
+ setInterval(() => {
285
+ visitors.value += Math.floor(Math.random() * 10);
286
+ sessions.value += Math.floor(Math.random() * 3);
287
+ }, 2000);
288
+
289
+ const stats = Stats({ style: 'box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);' },
290
+ Stats.Stat({},
291
+ Stats.Title({}, '🟢 Live Visitors'),
292
+ Stats.Value({ style: 'color: oklch(var(--su));' }, () => visitors.value.toLocaleString()),
293
+ Stats.Desc({}, 'Currently online')
294
+ ),
295
+ Stats.Stat({},
296
+ Stats.Title({}, '📊 Active Sessions'),
297
+ Stats.Value({}, () => sessions.value.toLocaleString()),
298
+ Stats.Desc({}, 'Last 5 minutes')
299
+ )
300
+ );
301
+
302
+ $('#example').content(stats);</code></pre>
303
+ </div>
304
+
305
+ <!-- vDOM Syntax -->
306
+ <div id="reactive-syntax-vdom" style="display: none;">
307
+ <pre><script>
308
+ examplify(document.currentScript.nextElementSibling, {
309
+ at: document.currentScript.parentElement,
310
+ scripts: ['/lightview.js', '/lightview-x.js'],
311
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
312
+ type: 'module',
313
+ minHeight: 120
314
+ });
315
+ </script><code contenteditable="true">await import('/components/data-display/stats.js');
316
+ const { signal, $, tags } = Lightview;
317
+ const { Stats } = tags;
318
+
319
+ const visitors = signal(1234);
320
+ const sessions = signal(567);
321
+
322
+ // Simulate live updates
323
+ setInterval(() => {
324
+ visitors.value += Math.floor(Math.random() * 10);
325
+ sessions.value += Math.floor(Math.random() * 3);
326
+ }, 2000);
327
+
328
+ const stats = {
329
+ tag: Stats,
330
+ attributes: { style: 'box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);' },
331
+ children: [
332
+ {
333
+ tag: Stats.Stat,
334
+ children: [
335
+ { tag: Stats.Title, children: ['🟢 Live Visitors'] },
336
+ { tag: Stats.Value, attributes: { style: 'color: oklch(var(--su));' }, children: [() => visitors.value.toLocaleString()] },
337
+ { tag: Stats.Desc, children: ['Currently online'] }
338
+ ]
339
+ },
340
+ {
341
+ tag: Stats.Stat,
342
+ children: [
343
+ { tag: Stats.Title, children: ['📊 Active Sessions'] },
344
+ { tag: Stats.Value, children: [() => sessions.value.toLocaleString()] },
345
+ { tag: Stats.Desc, children: ['Last 5 minutes'] }
346
+ ]
347
+ }
348
+ ]
349
+ };
350
+
351
+ $('#example').content(stats);</code></pre>
352
+ </div>
353
+
354
+ <!-- Object DOM Syntax -->
355
+ <div id="reactive-syntax-object" style="display: none;">
356
+ <pre><script>
357
+ examplify(document.currentScript.nextElementSibling, {
358
+ at: document.currentScript.parentElement,
359
+ scripts: ['/lightview.js', '/lightview-x.js'],
360
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
361
+ type: 'module',
362
+ minHeight: 120
363
+ });
364
+ </script><code contenteditable="true">await import('/components/data-display/stats.js');
365
+ const { signal, $ } = Lightview;
366
+
367
+ const visitors = signal(1234);
368
+ const sessions = signal(567);
369
+
370
+ // Simulate live updates
371
+ setInterval(() => {
372
+ visitors.value += Math.floor(Math.random() * 10);
373
+ sessions.value += Math.floor(Math.random() * 3);
374
+ }, 2000);
375
+
376
+ const stats = {
377
+ Stats: {
378
+ style: 'box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);',
379
+ children: [
380
+ {
381
+ 'Stats.Stat': {
382
+ children: [
383
+ { 'Stats.Title': { children: ['🟢 Live Visitors'] } },
384
+ { 'Stats.Value': { style: 'color: oklch(var(--su));', children: [() => visitors.value.toLocaleString()] } },
385
+ { 'Stats.Desc': { children: ['Currently online'] } }
386
+ ]
387
+ }
388
+ },
389
+ {
390
+ 'Stats.Stat': {
391
+ children: [
392
+ { 'Stats.Title': { children: ['📊 Active Sessions'] } },
393
+ { 'Stats.Value': { children: [() => sessions.value.toLocaleString()] } },
394
+ { 'Stats.Desc': { children: ['Last 5 minutes'] } }
395
+ ]
396
+ }
397
+ }
398
+ ]
399
+ }
400
+ };
401
+
402
+ $('#example').content(stats);</code></pre>
403
+ </div>
404
+ </div>
405
+ </div>
406
+
407
+ <!-- Props Table -->
408
+ <h2 class="text-xl font-bold" style="margin-bottom: 1rem;">Props</h2>
409
+ <div style="overflow-x: auto; margin-bottom: 2rem;">
410
+ <table class="table table-zebra">
411
+ <thead>
412
+ <tr>
413
+ <th>Prop</th>
414
+ <th>Type</th>
415
+ <th>Default</th>
416
+ <th>Description</th>
417
+ </tr>
418
+ </thead>
419
+ <tbody>
420
+ <tr>
421
+ <td><code>vertical</code></td>
422
+ <td>boolean</td>
423
+ <td>false</td>
424
+ <td>Stack stats vertically</td>
425
+ </tr>
426
+ </tbody>
427
+ </table>
428
+ </div>
429
+
430
+ <!-- Sub-components -->
431
+ <h2 class="text-xl font-bold" style="margin-bottom: 1rem;">Sub-components</h2>
432
+ <div style="overflow-x: auto; margin-bottom: 2rem;">
433
+ <table class="table table-zebra">
434
+ <thead>
435
+ <tr>
436
+ <th>Component</th>
437
+ <th>Description</th>
438
+ </tr>
439
+ </thead>
440
+ <tbody>
441
+ <tr>
442
+ <td><code>Stats.Stat</code></td>
443
+ <td>Individual stat container</td>
444
+ </tr>
445
+ <tr>
446
+ <td><code>Stats.Title</code></td>
447
+ <td>Stat label</td>
448
+ </tr>
449
+ <tr>
450
+ <td><code>Stats.Value</code></td>
451
+ <td>Large numeric value</td>
452
+ </tr>
453
+ <tr>
454
+ <td><code>Stats.Desc</code></td>
455
+ <td>Description/change indicator</td>
456
+ </tr>
457
+ <tr>
458
+ <td><code>Stats.Figure</code></td>
459
+ <td>Icon/image container</td>
460
+ </tr>
461
+ </tbody>
462
+ </table>
463
+ </div>
464
+
465
+ <!-- Vertical -->
466
+ <h2 class="text-xl font-bold" style="margin-bottom: 1rem;">Vertical Layout</h2>
467
+ <div class="stats stats-vertical"
468
+ style="box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); margin-bottom: 2rem;">
469
+ <div class="stat">
470
+ <div class="stat-title">Downloads</div>
471
+ <div class="stat-value">31K</div>
472
+ <div class="stat-desc">Jan 1st - Feb 1st</div>
473
+ </div>
474
+ <div class="stat">
475
+ <div class="stat-title">New Users</div>
476
+ <div class="stat-value">4,200</div>
477
+ <div class="stat-desc">↗︎ 400 (22%)</div>
478
+ </div>
479
+ </div>
480
+ </div>
481
+ </div>
482
+ </div>
483
+ </div>
484
+ </div>
485
+ </div>
486
+ </div>