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,655 @@
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: 'Radio' }
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">Radio</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
+ Radio buttons allow the user to select one option from a set.
61
+ Use RadioGroup for a complete set with validation support.
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 RadioGroup</h2>
68
+ <p class="text-sm" style="opacity: 0.7; margin-bottom: 1rem;">Radio group with label and
69
+ options</p>
70
+
71
+ <!-- Tabs -->
72
+ <script>
73
+ window.switchSyntaxTab = (tabId) => {
74
+ const tabs = ['tagged', 'vdom', 'object', 'html'];
75
+ tabs.forEach(t => {
76
+ const tabEl = document.getElementById(`tab-btn-${t}`);
77
+ const contentEl = document.getElementById(`syntax-${t}`);
78
+ if (t === tabId) {
79
+ tabEl.classList.add('syntax-tab-active');
80
+ contentEl.style.display = 'block';
81
+ } else {
82
+ tabEl.classList.remove('syntax-tab-active');
83
+ contentEl.style.display = 'none';
84
+ }
85
+ });
86
+ };
87
+ </script>
88
+ <div role="tablist" class="syntax-tabs" style="margin-bottom: 1rem;">
89
+ <button id="tab-btn-tagged" role="tab" class="syntax-tab syntax-tab-active"
90
+ onclick="switchSyntaxTab('tagged')">Tagged</button>
91
+ <button id="tab-btn-vdom" role="tab" class="syntax-tab"
92
+ onclick="switchSyntaxTab('vdom')">vDOM</button>
93
+ <button id="tab-btn-object" role="tab" class="syntax-tab"
94
+ onclick="switchSyntaxTab('object')">Object
95
+ DOM</button>
96
+ <button id="tab-btn-html" role="tab" class="syntax-tab"
97
+ onclick="switchSyntaxTab('html')">HTML</button>
98
+ </div>
99
+
100
+ <!-- Tagged Syntax -->
101
+ <div id="syntax-tagged">
102
+ <pre><script>
103
+ examplify(document.currentScript.nextElementSibling, {
104
+ at: document.currentScript.parentElement,
105
+ scripts: ['/lightview.js', '/lightview-x.js'],
106
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
107
+ type: 'module',
108
+ minHeight: 420,
109
+ autoRun: true
110
+ });
111
+ </script><code contenteditable="true">await import('/components/data-input/radio.js');
112
+ const { tags, $ } = Lightview;
113
+ const { div, RadioGroup } = tags;
114
+
115
+ // 1. Basic radio group
116
+ const basic = RadioGroup({
117
+ label: 'Favorite Color',
118
+ name: 'color',
119
+ options: ['Red', 'Blue', 'Green', 'Yellow'],
120
+ color: 'primary'
121
+ });
122
+
123
+ // 2. With descriptions
124
+ const withDesc = RadioGroup({
125
+ label: 'Subscription Plan',
126
+ name: 'plan',
127
+ options: [
128
+ { value: 'free', label: 'Free', description: 'Basic features, limited usage' },
129
+ { value: 'pro', label: 'Pro', description: '$9/month, all features' },
130
+ { value: 'enterprise', label: 'Enterprise', description: 'Custom pricing, priority support' }
131
+ ],
132
+ color: 'secondary'
133
+ });
134
+
135
+ // 3. Horizontal layout
136
+ const horizontal = RadioGroup({
137
+ label: 'Size',
138
+ name: 'size',
139
+ options: ['S', 'M', 'L', 'XL'],
140
+ horizontal: true,
141
+ color: 'accent'
142
+ });
143
+
144
+ // Insert all examples
145
+ $('#example').content(
146
+ div({ style: 'display: flex; flex-direction: column; gap: 1.5rem; max-width: 28rem;' }, basic, withDesc, horizontal)
147
+ );</code></pre>
148
+ </div>
149
+
150
+ <!-- vDOM Syntax -->
151
+ <div id="syntax-vdom" style="display: none;">
152
+ <pre><script>
153
+ examplify(document.currentScript.nextElementSibling, {
154
+ at: document.currentScript.parentElement,
155
+ scripts: ['/lightview.js', '/lightview-x.js'],
156
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
157
+ type: 'module',
158
+ minHeight: 420
159
+ });
160
+ </script><code contenteditable="true">await import('/components/data-input/radio.js');
161
+ const { $, tags } = Lightview;
162
+ const { RadioGroup, div } = tags;
163
+
164
+ const basic = {
165
+ tag: RadioGroup,
166
+ attributes: {
167
+ label: 'Favorite Color',
168
+ name: 'color',
169
+ options: ['Red', 'Blue', 'Green', 'Yellow'],
170
+ color: 'primary'
171
+ }
172
+ };
173
+
174
+ const withDesc = {
175
+ tag: RadioGroup,
176
+ attributes: {
177
+ label: 'Subscription Plan',
178
+ name: 'plan',
179
+ options: [
180
+ { value: 'free', label: 'Free', description: 'Basic features, limited usage' },
181
+ { value: 'pro', label: 'Pro', description: '$9/month, all features' },
182
+ { value: 'enterprise', label: 'Enterprise', description: 'Custom pricing, priority support' }
183
+ ],
184
+ color: 'secondary'
185
+ }
186
+ };
187
+
188
+ const horizontal = {
189
+ tag: RadioGroup,
190
+ attributes: {
191
+ label: 'Size',
192
+ name: 'size',
193
+ options: ['S', 'M', 'L', 'XL'],
194
+ horizontal: true,
195
+ color: 'accent'
196
+ }
197
+ };
198
+
199
+ $('#example').content({
200
+ tag: div,
201
+ attributes: { style: 'display: flex; flex-direction: column; gap: 1.5rem; max-width: 28rem;' },
202
+ children: [basic, withDesc, horizontal]
203
+ });</code></pre>
204
+ </div>
205
+
206
+ <!-- Object DOM Syntax -->
207
+ <div id="syntax-object" style="display: none;">
208
+ <pre><script>
209
+ examplify(document.currentScript.nextElementSibling, {
210
+ at: document.currentScript.parentElement,
211
+ scripts: ['/lightview.js', '/lightview-x.js'],
212
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
213
+ type: 'module',
214
+ minHeight: 420
215
+ });
216
+ </script><code contenteditable="true">await import('/components/data-input/radio.js');
217
+ const { $ } = Lightview;
218
+
219
+ $('#example').content({
220
+ div: {
221
+ style: 'display: flex; flex-direction: column; gap: 1.5rem; max-width: 28rem;',
222
+ children: [
223
+ {
224
+ RadioGroup: {
225
+ label: 'Favorite Color',
226
+ name: 'color',
227
+ options: ['Red', 'Blue', 'Green', 'Yellow'],
228
+ color: 'primary'
229
+ }
230
+ },
231
+ {
232
+ RadioGroup: {
233
+ label: 'Subscription Plan',
234
+ name: 'plan',
235
+ options: [
236
+ { value: 'free', label: 'Free', description: 'Basic features, limited usage' },
237
+ { value: 'pro', label: 'Pro', description: '$9/month, all features' },
238
+ { value: 'enterprise', label: 'Enterprise', description: 'Custom pricing, priority support' }
239
+ ],
240
+ color: 'secondary'
241
+ }
242
+ },
243
+ {
244
+ RadioGroup: {
245
+ label: 'Size',
246
+ name: 'size',
247
+ options: ['S', 'M', 'L', 'XL'],
248
+ horizontal: true,
249
+ color: 'accent'
250
+ }
251
+ }
252
+ ]
253
+ }
254
+ });</code></pre>
255
+ </div>
256
+
257
+ <!-- HTML Syntax -->
258
+ <div id="syntax-html" style="display: none;">
259
+ <pre><script>
260
+ examplify(document.currentScript.nextElementSibling, {
261
+ at: document.currentScript.parentElement,
262
+ scripts: ['/lightview.js', '/lightview-x.js'],
263
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
264
+ type: 'module',
265
+ language: 'html',
266
+ minHeight: 420
267
+ });
268
+ </script><code contenteditable="true" class="language-html">
269
+ &lt;div style="display: flex; flex-direction: column; gap: 1.5rem; max-width: 28rem;"&gt;
270
+ &lt;lv-radio-group
271
+ label="Favorite Color"
272
+ name="color-html"
273
+ options='["Red", "Blue", "Green", "Yellow"]'
274
+ color="primary"&gt;
275
+ &lt;/lv-radio-group&gt;
276
+
277
+ &lt;lv-radio-group
278
+ label="Subscription Plan"
279
+ name="plan-html"
280
+ options='[{"value":"free","label":"Free","description":"Basic features, limited usage"},{"value":"pro","label":"Pro","description":"$9/month, all features"},{"value":"enterprise","label":"Enterprise","description":"Custom pricing, priority support"}]'
281
+ color="secondary"&gt;
282
+ &lt;/lv-radio-group&gt;
283
+
284
+ &lt;lv-radio-group
285
+ label="Size"
286
+ name="size-html"
287
+ options='["S", "M", "L", "XL"]'
288
+ horizontal
289
+ color="accent"&gt;
290
+ &lt;/lv-radio-group&gt;
291
+ &lt;/div&gt;</code></pre>
292
+ </div>
293
+ </div>
294
+ </div>
295
+
296
+ <!-- Reactive Example with Examplify -->
297
+ <div
298
+ style="background-color: hsl(var(--b2)); border-radius: var(--rounded-box, 1rem); padding: 2rem; margin-bottom: 2rem;">
299
+ <h2 style="font-size: 1.5rem; font-weight: 700; margin-bottom: 1rem;">Reactive Example</h2>
300
+ <p style="font-size: 0.875rem; opacity: 0.7; margin-bottom: 1rem;">Two-way binding with signals
301
+ and
302
+ validation</p>
303
+
304
+ <!-- Tabs -->
305
+ <script>
306
+ window.switchReactiveSyntaxTab = (tabId) => {
307
+ const tabs = ['tagged', 'vdom', 'object'];
308
+ tabs.forEach(t => {
309
+ const tabEl = document.getElementById(`reactive-tab-btn-${t}`);
310
+ const contentEl = document.getElementById(`reactive-syntax-${t}`);
311
+ if (t === tabId) {
312
+ tabEl.classList.add('syntax-tab-active');
313
+ contentEl.style.display = 'block';
314
+ } else {
315
+ tabEl.classList.remove('syntax-tab-active');
316
+ contentEl.style.display = 'none';
317
+ }
318
+ });
319
+ };
320
+ </script>
321
+ <div role="tablist" class="syntax-tabs" style="margin-bottom: 1rem;">
322
+ <button id="reactive-tab-btn-tagged" role="tab" class="syntax-tab syntax-tab-active"
323
+ onclick="switchReactiveSyntaxTab('tagged')">Tagged</button>
324
+ <button id="reactive-tab-btn-vdom" role="tab" class="syntax-tab"
325
+ onclick="switchReactiveSyntaxTab('vdom')">vDOM</button>
326
+ <button id="reactive-tab-btn-object" role="tab" class="syntax-tab"
327
+ onclick="switchReactiveSyntaxTab('object')">Object DOM</button>
328
+ </div>
329
+
330
+ <!-- Tagged Syntax -->
331
+ <div id="reactive-syntax-tagged">
332
+ <pre><script>
333
+ examplify(document.currentScript.nextElementSibling, {
334
+ at: document.currentScript.parentElement,
335
+ scripts: ['/lightview.js', '/lightview-x.js'],
336
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
337
+ type: 'module',
338
+ minHeight: 260
339
+ });
340
+ </script><code contenteditable="true">await import('/components/data-input/radio.js');
341
+ const { signal, tags, $ } = Lightview;
342
+ const { div, p, span, RadioGroup } = tags;
343
+
344
+ // Signal for selected value
345
+ const selectedPriority = signal('');
346
+
347
+ // Priority descriptions
348
+ const priorityInfo = {
349
+ low: { emoji: '🟢', text: 'Can wait, no rush' },
350
+ medium: { emoji: '🟡', text: 'Should be addressed soon' },
351
+ high: { emoji: '🟠', text: 'Needs attention today' },
352
+ critical: { emoji: '🔴', text: 'Drop everything and fix now!' }
353
+ };
354
+
355
+ // Reactive radio group
356
+ const reactiveDemo = div({ style: 'display: flex; flex-direction: column; gap: 1rem; max-width: 28rem;' },
357
+ RadioGroup({
358
+ label: 'Issue Priority',
359
+ name: 'priority',
360
+ value: selectedPriority,
361
+ options: [
362
+ { value: 'low', label: 'Low' },
363
+ { value: 'medium', label: 'Medium' },
364
+ { value: 'high', label: 'High' },
365
+ { value: 'critical', label: 'Critical' }
366
+ ],
367
+ required: true,
368
+ color: 'primary'
369
+ }),
370
+ p({ style: 'font-size: 1.125rem;' },
371
+ () => {
372
+ const priority = selectedPriority.value;
373
+ if (!priority) return span({ style: 'opacity: 0.5;' }, 'Select a priority level');
374
+ const info = priorityInfo[priority];
375
+ return span({}, info.emoji, ' ', info.text);
376
+ }
377
+ )
378
+ );
379
+
380
+ $('#example').content(reactiveDemo);</code></pre>
381
+ </div>
382
+
383
+ <!-- vDOM Syntax -->
384
+ <div id="reactive-syntax-vdom" style="display: none;">
385
+ <pre><script>
386
+ examplify(document.currentScript.nextElementSibling, {
387
+ at: document.currentScript.parentElement,
388
+ scripts: ['/lightview.js', '/lightview-x.js'],
389
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
390
+ type: 'module',
391
+ minHeight: 260
392
+ });
393
+ </script><code contenteditable="true">await import('/components/data-input/radio.js');
394
+ const { signal, $, tags } = Lightview;
395
+ const { RadioGroup, div, p, span } = tags;
396
+
397
+ const selectedPriority = signal('');
398
+
399
+ const priorityInfo = {
400
+ low: { emoji: '🟢', text: 'Can wait, no rush' },
401
+ medium: { emoji: '🟡', text: 'Should be addressed soon' },
402
+ high: { emoji: '🟠', text: 'Needs attention today' },
403
+ critical: { emoji: '🔴', text: 'Drop everything and fix now!' }
404
+ };
405
+
406
+ const reactiveDemo = {
407
+ tag: div,
408
+ attributes: { style: 'display: flex; flex-direction: column; gap: 1rem; max-width: 28rem;' },
409
+ children: [
410
+ {
411
+ tag: RadioGroup,
412
+ attributes: {
413
+ label: 'Issue Priority',
414
+ name: 'priority',
415
+ value: selectedPriority,
416
+ options: [
417
+ { value: 'low', label: 'Low' },
418
+ { value: 'medium', label: 'Medium' },
419
+ { value: 'high', label: 'High' },
420
+ { value: 'critical', label: 'Critical' }
421
+ ],
422
+ required: true,
423
+ color: 'primary'
424
+ }
425
+ },
426
+ {
427
+ tag: p,
428
+ attributes: { style: 'font-size: 1.125rem;' },
429
+ children: [
430
+ () => {
431
+ const priority = selectedPriority.value;
432
+ if (!priority) return { tag: span, attributes: { style: 'opacity: 0.5;' }, children: ['Select a priority level'] };
433
+ const info = priorityInfo[priority];
434
+ return { tag: span, children: [info.emoji, ' ', info.text] };
435
+ }
436
+ ]
437
+ }
438
+ ]
439
+ };
440
+
441
+ $('#example').content(reactiveDemo);</code></pre>
442
+ </div>
443
+
444
+ <!-- Object DOM Syntax -->
445
+ <div id="reactive-syntax-object" style="display: none;">
446
+ <pre><script>
447
+ examplify(document.currentScript.nextElementSibling, {
448
+ at: document.currentScript.parentElement,
449
+ scripts: ['/lightview.js', '/lightview-x.js'],
450
+ styles: ['https://cdn.jsdelivr.net/npm/daisyui@3.9.4/dist/full.min.css'],
451
+ type: 'module',
452
+ minHeight: 260
453
+ });
454
+ </script><code contenteditable="true">await import('/components/data-input/radio.js');
455
+ const { signal, $ } = Lightview;
456
+
457
+ const selectedPriority = signal('');
458
+
459
+ const priorityInfo = {
460
+ low: { emoji: '🟢', text: 'Can wait, no rush' },
461
+ medium: { emoji: '🟡', text: 'Should be addressed soon' },
462
+ high: { emoji: '🟠', text: 'Needs attention today' },
463
+ critical: { emoji: '🔴', text: 'Drop everything and fix now!' }
464
+ };
465
+
466
+ const reactiveDemo = {
467
+ div: {
468
+ style: 'display: flex; flex-direction: column; gap: 1rem; max-width: 28rem;',
469
+ children: [
470
+ {
471
+ RadioGroup: {
472
+ label: 'Issue Priority',
473
+ name: 'priority',
474
+ value: selectedPriority,
475
+ options: [
476
+ { value: 'low', label: 'Low' },
477
+ { value: 'medium', label: 'Medium' },
478
+ { value: 'high', label: 'High' },
479
+ { value: 'critical', label: 'Critical' }
480
+ ],
481
+ required: true,
482
+ color: 'primary'
483
+ }
484
+ },
485
+ {
486
+ p: {
487
+ style: 'font-size: 1.125rem;',
488
+ children: [
489
+ () => {
490
+ const priority = selectedPriority.value;
491
+ if (!priority) return { span: { style: 'opacity: 0.5;', children: ['Select a priority level'] } };
492
+ const info = priorityInfo[priority];
493
+ return { span: { children: [info.emoji, ' ', info.text] } };
494
+ }
495
+ ]
496
+ }
497
+ }
498
+ ]
499
+ }
500
+ };
501
+
502
+ $('#example').content(reactiveDemo);</code></pre>
503
+ </div>
504
+ </div>
505
+ </div>
506
+
507
+ <!-- Props Table - RadioGroup -->
508
+ <h2 class="text-xl font-bold" style="margin-bottom: 1rem;">RadioGroup Props</h2>
509
+ <div style="overflow-x: auto; margin-bottom: 2rem;">
510
+ <table class="table table-zebra">
511
+ <thead>
512
+ <tr>
513
+ <th>Prop</th>
514
+ <th>Type</th>
515
+ <th>Default</th>
516
+ <th>Description</th>
517
+ </tr>
518
+ </thead>
519
+ <tbody>
520
+ <tr>
521
+ <td><code>options</code></td>
522
+ <td>array</td>
523
+ <td>[]</td>
524
+ <td>Array of strings or objects <code>{value, label, description, disabled}</code>
525
+ </td>
526
+ </tr>
527
+ <tr>
528
+ <td><code>value</code></td>
529
+ <td>* | signal</td>
530
+ <td>-</td>
531
+ <td>Selected value (reactive with signals)</td>
532
+ </tr>
533
+ <tr>
534
+ <td><code>defaultValue</code></td>
535
+ <td>*</td>
536
+ <td>null</td>
537
+ <td>Default value for uncontrolled mode</td>
538
+ </tr>
539
+ <tr>
540
+ <td><code>name</code></td>
541
+ <td>string</td>
542
+ <td>auto</td>
543
+ <td>Radio group name for form submission</td>
544
+ </tr>
545
+ <tr>
546
+ <td><code>label</code></td>
547
+ <td>string</td>
548
+ <td>-</td>
549
+ <td>Group label displayed above options</td>
550
+ </tr>
551
+ <tr>
552
+ <td><code>helper</code></td>
553
+ <td>string</td>
554
+ <td>-</td>
555
+ <td>Helper text displayed below options</td>
556
+ </tr>
557
+ <tr>
558
+ <td><code>error</code></td>
559
+ <td>string | function</td>
560
+ <td>-</td>
561
+ <td>Error message or reactive error function</td>
562
+ </tr>
563
+ <tr>
564
+ <td><code>validate</code></td>
565
+ <td>function</td>
566
+ <td>-</td>
567
+ <td>Validation function: <code>(value) => errorMessage | null</code></td>
568
+ </tr>
569
+ <tr>
570
+ <td><code>color</code></td>
571
+ <td>string</td>
572
+ <td>-</td>
573
+ <td>'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error'
574
+ </td>
575
+ </tr>
576
+ <tr>
577
+ <td><code>size</code></td>
578
+ <td>string</td>
579
+ <td>'md'</td>
580
+ <td>'xs' | 'sm' | 'md' | 'lg'</td>
581
+ </tr>
582
+ <tr>
583
+ <td><code>horizontal</code></td>
584
+ <td>boolean</td>
585
+ <td>false</td>
586
+ <td>Arrange options horizontally</td>
587
+ </tr>
588
+ <tr>
589
+ <td><code>disabled</code></td>
590
+ <td>boolean</td>
591
+ <td>false</td>
592
+ <td>Disable all options</td>
593
+ </tr>
594
+ <tr>
595
+ <td><code>required</code></td>
596
+ <td>boolean</td>
597
+ <td>false</td>
598
+ <td>Mark as required field</td>
599
+ </tr>
600
+ <tr>
601
+ <td><code>onChange</code></td>
602
+ <td>function</td>
603
+ <td>-</td>
604
+ <td>Callback when value changes: <code>(value) => void</code></td>
605
+ </tr>
606
+ <tr>
607
+ <td><code>useShadow</code></td>
608
+ <td>boolean</td>
609
+ <td>*</td>
610
+ <td>Render in Shadow DOM</td>
611
+ </tr>
612
+ </tbody>
613
+ </table>
614
+ </div>
615
+
616
+ <!-- Colors Example -->
617
+ <h2 class="text-xl font-bold" style="margin-bottom: 1rem;">Colors</h2>
618
+ <div style="display: flex; gap: 0.5rem; margin-bottom: 2rem;">
619
+ <input type="radio" class="radio" checked name="color-demo" />
620
+ <input type="radio" class="radio radio-primary" checked name="color-demo2" />
621
+ <input type="radio" class="radio radio-secondary" checked name="color-demo3" />
622
+ <input type="radio" class="radio radio-accent" checked name="color-demo4" />
623
+ <input type="radio" class="radio radio-success" checked name="color-demo5" />
624
+ <input type="radio" class="radio radio-warning" checked name="color-demo6" />
625
+ <input type="radio" class="radio radio-info" checked name="color-demo7" />
626
+ <input type="radio" class="radio radio-error" checked name="color-demo8" />
627
+ </div>
628
+
629
+ <!-- Sizes Example -->
630
+ <h2 class="text-xl font-bold" style="margin-bottom: 1rem;">Sizes</h2>
631
+ <div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 2rem;">
632
+ <input type="radio" class="radio radio-xs" checked name="size-demo" />
633
+ <input type="radio" class="radio radio-sm" checked name="size-demo2" />
634
+ <input type="radio" class="radio radio-md" checked name="size-demo3" />
635
+ <input type="radio" class="radio radio-lg" checked name="size-demo4" />
636
+ </div>
637
+
638
+ <!-- With Label -->
639
+ <h2 class="text-xl font-bold" style="margin-bottom: 1rem;">With Label</h2>
640
+ <div style="display: flex; flex-direction: column; width: 13rem; margin-bottom: 2rem;">
641
+ <label
642
+ style="display: flex; align-items: center; justify-content: space-between; cursor: pointer; padding: 0.5rem 0;">
643
+ <span style="font-size: 0.875rem;">Option 1</span>
644
+ <input type="radio" name="label-demo" class="radio radio-primary" checked />
645
+ </label>
646
+ <label
647
+ style="display: flex; align-items: center; justify-content: space-between; cursor: pointer; padding: 0.5rem 0;">
648
+ <span style="font-size: 0.875rem;">Option 2</span>
649
+ <input type="radio" name="label-demo" class="radio radio-primary" />
650
+ </label>
651
+ </div>
652
+ </div>
653
+ </div>
654
+ </div>
655
+ </div>