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,561 @@
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: 'Card' }
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">Card</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
+ Cards are used to group and display content in a way that is easily readable.
61
+ Supports images, actions, and multiple layout variants.
62
+ </p>
63
+
64
+ <!-- Basic Usage -->
65
+ <div class="card bg-base-200" style="margin-bottom: 2rem;">
66
+ <div class="card-body">
67
+ <h2 class="card-title">Basic Usage</h2>
68
+ <p class="text-sm" style="opacity: 0.7; margin-bottom: 1rem;">Card with image, title, and
69
+ action button.
70
+ </p>
71
+
72
+ <!-- Tabs -->
73
+ <script>
74
+ window.switchSyntaxTab = (tabId) => {
75
+ const tabs = ['tagged', 'vdom', 'object'];
76
+ tabs.forEach(t => {
77
+ const tabEl = document.getElementById(`tab-btn-${t}`);
78
+ const contentEl = document.getElementById(`syntax-${t}`);
79
+ if (t === tabId) {
80
+ tabEl.classList.add('syntax-tab-active');
81
+ contentEl.style.display = 'block';
82
+ } else {
83
+ tabEl.classList.remove('syntax-tab-active');
84
+ contentEl.style.display = 'none';
85
+ }
86
+ });
87
+ };
88
+ </script>
89
+ <div role="tablist" class="syntax-tabs" style="margin-bottom: 1rem;">
90
+ <button id="tab-btn-tagged" role="tab" class="syntax-tab syntax-tab-active"
91
+ onclick="switchSyntaxTab('tagged')">Tagged</button>
92
+ <button id="tab-btn-vdom" role="tab" class="syntax-tab"
93
+ onclick="switchSyntaxTab('vdom')">vDOM</button>
94
+ <button id="tab-btn-object" role="tab" class="syntax-tab"
95
+ onclick="switchSyntaxTab('object')">Object
96
+ DOM</button>
97
+ </div>
98
+
99
+ <!-- Tagged Syntax -->
100
+ <div id="syntax-tagged">
101
+ <pre><script>
102
+ examplify(document.currentScript.nextElementSibling, {
103
+ at: document.currentScript.parentElement,
104
+ scripts: ['/lightview.js', '/lightview-x.js'],
105
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
106
+ type: 'module',
107
+ minHeight: 340,
108
+ autoRun: true
109
+ });
110
+ </script><code contenteditable="true">await import('/components/data-display/card.js');
111
+ await import('/components/actions/button.js');
112
+ const { tags, $ } = Lightview;
113
+ const { p, Card, Button } = tags;
114
+
115
+ const card = Card({ style: 'width: 18rem;' },
116
+ Card.Figure({
117
+ src: 'https://images.unsplash.com/photo-1606107557195-0e29a4b5b4aa?w=400&h=200&fit=crop',
118
+ alt: 'Shoes'
119
+ }),
120
+ Card.Body({},
121
+ Card.Title({}, 'Nike Air Max'),
122
+ p({}, 'Premium comfort meets modern style.'),
123
+ Card.Actions({ justify: 'end' },
124
+ Button({ color: 'primary' }, 'Buy Now')
125
+ )
126
+ )
127
+ );
128
+
129
+ $('#example').content(card);</code></pre>
130
+ </div>
131
+
132
+ <!-- vDOM Syntax -->
133
+ <div id="syntax-vdom" style="display: none;">
134
+ <pre><script>
135
+ examplify(document.currentScript.nextElementSibling, {
136
+ at: document.currentScript.parentElement,
137
+ scripts: ['/lightview.js', '/lightview-x.js'],
138
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
139
+ type: 'module',
140
+ minHeight: 340
141
+ });
142
+ </script><code contenteditable="true">await import('/components/data-display/card.js');
143
+ await import('/components/actions/button.js');
144
+ const { $, tags } = Lightview;
145
+ const { Card, Button, p } = tags;
146
+
147
+ const card = {
148
+ tag: Card,
149
+ attributes: { style: 'width: 18rem;' },
150
+ children: [
151
+ {
152
+ tag: Card.Figure,
153
+ attributes: {
154
+ src: 'https://images.unsplash.com/photo-1606107557195-0e29a4b5b4aa?w=400&h=200&fit=crop',
155
+ alt: 'Shoes'
156
+ }
157
+ },
158
+ {
159
+ tag: Card.Body,
160
+ children: [
161
+ { tag: Card.Title, children: ['Nike Air Max'] },
162
+ { tag: p, children: ['Premium comfort meets modern style.'] },
163
+ {
164
+ tag: Card.Actions,
165
+ attributes: { justify: 'end' },
166
+ children: [
167
+ { tag: Button, attributes: { color: 'primary' }, children: ['Buy Now'] }
168
+ ]
169
+ }
170
+ ]
171
+ }
172
+ ]
173
+ };
174
+
175
+ $('#example').content(card);</code></pre>
176
+ </div>
177
+
178
+ <!-- Object DOM Syntax -->
179
+ <div id="syntax-object" style="display: none;">
180
+ <pre><script>
181
+ examplify(document.currentScript.nextElementSibling, {
182
+ at: document.currentScript.parentElement,
183
+ scripts: ['/lightview.js', '/lightview-x.js'],
184
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
185
+ type: 'module',
186
+ minHeight: 340
187
+ });
188
+ </script><code contenteditable="true">await import('/components/data-display/card.js');
189
+ await import('/components/actions/button.js');
190
+ const { $ } = Lightview;
191
+
192
+ const card = {
193
+ Card: {
194
+ style: 'width: 18rem;',
195
+ children: [
196
+ {
197
+ 'Card.Figure': {
198
+ src: 'https://images.unsplash.com/photo-1606107557195-0e29a4b5b4aa?w=400&h=200&fit=crop',
199
+ alt: 'Shoes'
200
+ }
201
+ },
202
+ {
203
+ 'Card.Body': {
204
+ children: [
205
+ { 'Card.Title': { children: ['Nike Air Max'] } },
206
+ { p: { children: ['Premium comfort meets modern style.'] } },
207
+ {
208
+ 'Card.Actions': {
209
+ justify: 'end',
210
+ children: [
211
+ { Button: { color: 'primary', children: ['Buy Now'] } }
212
+ ]
213
+ }
214
+ }
215
+ ]
216
+ }
217
+ }
218
+ ]
219
+ }
220
+ };
221
+
222
+ $('#example').content(card);</code></pre>
223
+ </div>
224
+ </div>
225
+ </div>
226
+
227
+ <!-- Reactive Example -->
228
+ <div class="card bg-base-200" style="margin-bottom: 2rem;">
229
+ <div class="card-body">
230
+ <h2 class="card-title">Product Card with Cart</h2>
231
+ <p class="text-sm" style="opacity: 0.7; margin-bottom: 1rem;">Interactive card with add to
232
+ cart
233
+ functionality.</p>
234
+
235
+ <!-- Tabs -->
236
+ <script>
237
+ window.switchReactiveSyntaxTab = (tabId) => {
238
+ const tabs = ['tagged', 'vdom', 'object'];
239
+ tabs.forEach(t => {
240
+ const tabEl = document.getElementById(`reactive-tab-btn-${t}`);
241
+ const contentEl = document.getElementById(`reactive-syntax-${t}`);
242
+ if (t === tabId) {
243
+ tabEl.classList.add('syntax-tab-active');
244
+ contentEl.style.display = 'block';
245
+ } else {
246
+ tabEl.classList.remove('syntax-tab-active');
247
+ contentEl.style.display = 'none';
248
+ }
249
+ });
250
+ };
251
+ </script>
252
+ <div role="tablist" class="syntax-tabs" style="margin-bottom: 1rem;">
253
+ <button id="reactive-tab-btn-tagged" role="tab" class="syntax-tab syntax-tab-active"
254
+ onclick="switchReactiveSyntaxTab('tagged')">Tagged</button>
255
+ <button id="reactive-tab-btn-vdom" role="tab" class="syntax-tab"
256
+ onclick="switchReactiveSyntaxTab('vdom')">vDOM</button>
257
+ <button id="reactive-tab-btn-object" role="tab" class="syntax-tab"
258
+ onclick="switchReactiveSyntaxTab('object')">Object DOM</button>
259
+ </div>
260
+
261
+ <!-- Tagged Syntax -->
262
+ <div id="reactive-syntax-tagged">
263
+ <pre><script>
264
+ examplify(document.currentScript.nextElementSibling, {
265
+ at: document.currentScript.parentElement,
266
+ scripts: ['/lightview.js', '/lightview-x.js'],
267
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
268
+ type: 'module',
269
+ minHeight: 380
270
+ });
271
+ </script><code contenteditable="true">await import('/components/data-display/card.js');
272
+ await import('/components/actions/button.js');
273
+ await import('/components/data-display/badge.js');
274
+ const { signal, tags, $ } = Lightview;
275
+ const { p, span, div, Card, Button, Badge } = tags;
276
+
277
+ const inCart = signal(false);
278
+
279
+ const card = Card({ style: 'width: 18rem;' },
280
+ Card.Figure({
281
+ src: 'https://images.unsplash.com/photo-1523275335684-37898b6baf30?w=400&h=200&fit=crop',
282
+ alt: 'Watch'
283
+ }),
284
+ Card.Body({},
285
+ div({ style: 'display: flex; justify-content: space-between; align-items: start;' },
286
+ Card.Title({}, 'Smart Watch'),
287
+ Badge({ color: 'success' }, 'New')
288
+ ),
289
+ p({ style: 'font-size: 0.875rem; opacity: 0.7;' }, 'Track your fitness goals with precision.'),
290
+ div({ style: 'font-size: 1.25rem; font-weight: 700;' }, '$299'),
291
+ Card.Actions({ justify: 'end' },
292
+ () => inCart.value
293
+ ? Button({ color: 'success', onclick: () => { inCart.value = false; } }, '✓ In Cart')
294
+ : Button({ color: 'primary', onclick: () => { inCart.value = true; } }, 'Add to Cart')
295
+ )
296
+ )
297
+ );
298
+
299
+ $('#example').content(card);</code></pre>
300
+ </div>
301
+
302
+ <!-- vDOM Syntax -->
303
+ <div id="reactive-syntax-vdom" style="display: none;">
304
+ <pre><script>
305
+ examplify(document.currentScript.nextElementSibling, {
306
+ at: document.currentScript.parentElement,
307
+ scripts: ['/lightview.js', '/lightview-x.js'],
308
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
309
+ type: 'module',
310
+ minHeight: 380
311
+ });
312
+ </script><code contenteditable="true">await import('/components/data-display/card.js');
313
+ await import('/components/actions/button.js');
314
+ await import('/components/data-display/badge.js');
315
+ const { signal, $, tags } = Lightview;
316
+ const { Card, Button, Badge, div, p } = tags;
317
+
318
+ const inCart = signal(false);
319
+
320
+ const card = {
321
+ tag: Card,
322
+ attributes: { style: 'width: 18rem;' },
323
+ children: [
324
+ {
325
+ tag: Card.Figure,
326
+ attributes: {
327
+ src: 'https://images.unsplash.com/photo-1523275335684-37898b6baf30?w=400&h=200&fit=crop',
328
+ alt: 'Watch'
329
+ }
330
+ },
331
+ {
332
+ tag: Card.Body,
333
+ children: [
334
+ {
335
+ tag: div,
336
+ attributes: { style: 'display: flex; justify-content: space-between; align-items: start;' },
337
+ children: [
338
+ { tag: Card.Title, children: ['Smart Watch'] },
339
+ { tag: Badge, attributes: { color: 'success' }, children: ['New'] }
340
+ ]
341
+ },
342
+ { tag: p, attributes: { style: 'font-size: 0.875rem; opacity: 0.7;' }, children: ['Track your fitness goals with precision.'] },
343
+ { tag: div, attributes: { style: 'font-size: 1.25rem; font-weight: 700;' }, children: ['$299'] },
344
+ {
345
+ tag: Card.Actions,
346
+ attributes: { justify: 'end' },
347
+ children: [
348
+ () => inCart.value
349
+ ? { tag: Button, attributes: { color: 'success', onclick: () => { inCart.value = false; } }, children: ['✓ In Cart'] }
350
+ : { tag: Button, attributes: { color: 'primary', onclick: () => { inCart.value = true; } }, children: ['Add to Cart'] }
351
+ ]
352
+ }
353
+ ]
354
+ }
355
+ ]
356
+ };
357
+
358
+ $('#example').content(card);</code></pre>
359
+ </div>
360
+
361
+ <!-- Object DOM Syntax -->
362
+ <div id="reactive-syntax-object" style="display: none;">
363
+ <pre><script>
364
+ examplify(document.currentScript.nextElementSibling, {
365
+ at: document.currentScript.parentElement,
366
+ scripts: ['/lightview.js', '/lightview-x.js'],
367
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
368
+ type: 'module',
369
+ minHeight: 380
370
+ });
371
+ </script><code contenteditable="true">await import('/components/data-display/card.js');
372
+ await import('/components/actions/button.js');
373
+ await import('/components/data-display/badge.js');
374
+ const { signal, $ } = Lightview;
375
+
376
+ const inCart = signal(false);
377
+
378
+ const card = {
379
+ Card: {
380
+ style: 'width: 18rem;',
381
+ children: [
382
+ {
383
+ 'Card.Figure': {
384
+ src: 'https://images.unsplash.com/photo-1523275335684-37898b6baf30?w=400&h=200&fit=crop',
385
+ alt: 'Watch'
386
+ }
387
+ },
388
+ {
389
+ 'Card.Body': {
390
+ children: [
391
+ {
392
+ div: {
393
+ style: 'display: flex; justify-content: space-between; align-items: start;',
394
+ children: [
395
+ { 'Card.Title': { children: ['Smart Watch'] } },
396
+ { Badge: { color: 'success', children: ['New'] } }
397
+ ]
398
+ }
399
+ },
400
+ { p: { style: 'font-size: 0.875rem; opacity: 0.7;', children: ['Track your fitness goals with precision.'] } },
401
+ { div: { style: 'font-size: 1.25rem; font-weight: 700;', children: ['$299'] } },
402
+ {
403
+ 'Card.Actions': {
404
+ justify: 'end',
405
+ children: [
406
+ () => inCart.value
407
+ ? { Button: { color: 'success', onclick: () => { inCart.value = false; }, children: ['✓ In Cart'] } }
408
+ : { Button: { color: 'primary', onclick: () => { inCart.value = true; }, children: ['Add to Cart'] } }
409
+ ]
410
+ }
411
+ }
412
+ ]
413
+ }
414
+ }
415
+ ]
416
+ }
417
+ };
418
+
419
+ $('#example').content(card);</code></pre>
420
+ </div>
421
+ </div>
422
+ </div>
423
+
424
+ <!-- Props Table -->
425
+ <h2 class="text-xl font-bold" style="margin-bottom: 1rem;">Props</h2>
426
+ <div style="overflow-x: auto; margin-bottom: 2rem;">
427
+ <table class="table table-zebra">
428
+ <thead>
429
+ <tr>
430
+ <th>Prop</th>
431
+ <th>Type</th>
432
+ <th>Default</th>
433
+ <th>Description</th>
434
+ </tr>
435
+ </thead>
436
+ <tbody>
437
+ <tr>
438
+ <td><code>variant</code></td>
439
+ <td>string</td>
440
+ <td>-</td>
441
+ <td>'bordered' | 'dash' | 'side' | 'compact'</td>
442
+ </tr>
443
+ <tr>
444
+ <td><code>imageFull</code></td>
445
+ <td>boolean</td>
446
+ <td>false</td>
447
+ <td>Image fills the entire card width with overlay text</td>
448
+ </tr>
449
+ <tr>
450
+ <td><code>bg</code></td>
451
+ <td>string</td>
452
+ <td>'bg-base-100'</td>
453
+ <td>Background color class</td>
454
+ </tr>
455
+ <tr>
456
+ <td><code>shadow</code></td>
457
+ <td>string</td>
458
+ <td>'shadow-sm'</td>
459
+ <td>Shadow class (shadow-sm, shadow-md, shadow-xl)</td>
460
+ </tr>
461
+ </tbody>
462
+ </table>
463
+ </div>
464
+
465
+ <!-- Sub-components -->
466
+ <h2 class="text-xl font-bold" style="margin-bottom: 1rem;">Sub-components</h2>
467
+ <div style="overflow-x: auto; margin-bottom: 2rem;">
468
+ <table class="table table-zebra">
469
+ <thead>
470
+ <tr>
471
+ <th>Component</th>
472
+ <th>Description</th>
473
+ </tr>
474
+ </thead>
475
+ <tbody>
476
+ <tr>
477
+ <td><code>Card.Body</code></td>
478
+ <td>Content container with padding</td>
479
+ </tr>
480
+ <tr>
481
+ <td><code>Card.Title</code></td>
482
+ <td>Card heading (h2)</td>
483
+ </tr>
484
+ <tr>
485
+ <td><code>Card.Actions</code></td>
486
+ <td>Container for action buttons (props: justify)</td>
487
+ </tr>
488
+ <tr>
489
+ <td><code>Card.Figure</code></td>
490
+ <td>Image container (props: src, alt)</td>
491
+ </tr>
492
+ </tbody>
493
+ </table>
494
+ </div>
495
+
496
+ <!-- Variants -->
497
+ <h2 class="text-xl font-bold" style="margin-bottom: 1rem;">Variants</h2>
498
+ <div
499
+ style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 2rem;">
500
+ <div class="card card-bordered" style="background-color: oklch(var(--b1));">
501
+ <div class="card-body">
502
+ <h2 class="card-title">Bordered</h2>
503
+ <p>Card with a border instead of shadow.</p>
504
+ </div>
505
+ </div>
506
+ <div class="card card-dash" style="background-color: oklch(var(--b1));">
507
+ <div class="card-body">
508
+ <h2 class="card-title">Dash</h2>
509
+ <p>Card with a dashed border.</p>
510
+ </div>
511
+ </div>
512
+ </div>
513
+
514
+ <!-- Side Card -->
515
+ <h2 class="text-xl font-bold" style="margin-bottom: 1rem;">Side Layout</h2>
516
+ <div class="card card-side"
517
+ style="background-color: oklch(var(--b1)); box-shadow: var(--shadow-sm); margin-bottom: 2rem;">
518
+ <figure><img
519
+ src="https://images.unsplash.com/photo-1606107557195-0e29a4b5b4aa?w=200&h=200&fit=crop"
520
+ alt="Album" /></figure>
521
+ <div class="card-body">
522
+ <h2 class="card-title">Horizontal Card</h2>
523
+ <p>Image on the side with content next to it.</p>
524
+ <div class="card-actions" style="justify-content: flex-end;">
525
+ <button class="btn btn-primary">Listen</button>
526
+ </div>
527
+ </div>
528
+ </div>
529
+
530
+ <!-- Compact -->
531
+ <h2 class="text-xl font-bold" style="margin-bottom: 1rem;">Compact</h2>
532
+ <div class="card card-compact"
533
+ style="background-color: oklch(var(--b1)); box-shadow: var(--shadow-sm); width: 16rem; margin-bottom: 2rem;">
534
+ <figure><img
535
+ src="https://images.unsplash.com/photo-1606107557195-0e29a4b5b4aa?w=300&h=150&fit=crop"
536
+ alt="Shoes" /></figure>
537
+ <div class="card-body">
538
+ <h2 class="card-title">Compact Card</h2>
539
+ <p>Less padding for a tighter layout.</p>
540
+ </div>
541
+ </div>
542
+
543
+ <!-- Image Overlay -->
544
+ <h2 class="text-xl font-bold" style="margin-bottom: 1rem;">Image Overlay</h2>
545
+ <div class="card image-full"
546
+ style="box-shadow: var(--shadow-xl); width: 24rem; margin-bottom: 2rem;">
547
+ <figure><img
548
+ src="https://images.unsplash.com/photo-1606107557195-0e29a4b5b4aa?w=500&h=300&fit=crop"
549
+ alt="Shoes" /></figure>
550
+ <div class="card-body">
551
+ <h2 class="card-title">Text Over Image</h2>
552
+ <p>Content overlay on top of the image.</p>
553
+ <div class="card-actions" style="justify-content: flex-end;">
554
+ <button class="btn btn-primary">Shop Now</button>
555
+ </div>
556
+ </div>
557
+ </div>
558
+ </div>
559
+ </div>
560
+ </div>
561
+ </div>