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,91 @@
1
+ /**
2
+ * Lightview Breadcrumbs Component (DaisyUI)
3
+ * @see https://daisyui.com/components/breadcrumbs/
4
+ */
5
+
6
+ import '../daisyui.js';
7
+
8
+ /**
9
+ * Breadcrumbs Component
10
+ * @param {Object} props
11
+ * @param {Array} props.items - Array of {label, href} objects
12
+ * @param {boolean} props.useShadow - Render in Shadow DOM with isolated DaisyUI styles
13
+ */
14
+ const Breadcrumbs = (props = {}, ...children) => {
15
+ const { tags } = window.Lightview || {};
16
+ const LVX = window.LightviewX || {};
17
+
18
+ if (!tags) return null;
19
+
20
+ const { div, ul, li, a, shadowDOM } = tags;
21
+
22
+ const {
23
+ items = [],
24
+ useShadow,
25
+ class: className = '',
26
+ ...rest
27
+ } = props;
28
+
29
+ const breadcrumbItems = items.map((item, index) => {
30
+ if (index === items.length - 1) {
31
+ // Last item - no link
32
+ return li({}, item.label);
33
+ }
34
+ return li({}, a({ href: item.href }, item.label));
35
+ });
36
+
37
+ const breadcrumbsEl = div({
38
+ class: `breadcrumbs text-sm ${className}`.trim(),
39
+ ...rest
40
+ },
41
+ ul({}, ...breadcrumbItems, ...children)
42
+ );
43
+
44
+ // Check if we should use shadow DOM
45
+ let usesShadow = false;
46
+ if (LVX.shouldUseShadow) {
47
+ usesShadow = LVX.shouldUseShadow(useShadow);
48
+ } else {
49
+ usesShadow = useShadow === true;
50
+ }
51
+
52
+ if (usesShadow) {
53
+ const adoptedStyleSheets = LVX.getAdoptedStyleSheets ? LVX.getAdoptedStyleSheets() : [];
54
+
55
+ const themeValue = LVX.themeSignal ? () => LVX.themeSignal.value : 'light';
56
+
57
+ return div({ class: 'contents', style: 'display: inline-block' },
58
+ shadowDOM({ mode: 'open', adoptedStyleSheets },
59
+ div({ 'data-theme': themeValue },
60
+ breadcrumbsEl
61
+ )
62
+ )
63
+ );
64
+ }
65
+
66
+ return breadcrumbsEl;
67
+ };
68
+
69
+ /**
70
+ * Breadcrumbs Item
71
+ */
72
+ Breadcrumbs.Item = (props = {}, ...children) => {
73
+ const { tags } = window.Lightview || {};
74
+ if (!tags) return null;
75
+
76
+ const { href, class: className = '', ...rest } = props;
77
+
78
+ if (href) {
79
+ return tags.li({ class: className, ...rest },
80
+ tags.a({ href }, ...children)
81
+ );
82
+ }
83
+
84
+ return tags.li({ class: className, ...rest }, ...children);
85
+ };
86
+
87
+
88
+ const tags = window.Lightview.tags;
89
+ tags.Breadcrumbs = Breadcrumbs;
90
+ tags['Breadcrumbs.Item'] = Breadcrumbs.Item;
91
+ export default Breadcrumbs;
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Lightview Dock Component (DaisyUI)
3
+ * @see https://daisyui.com/components/dock/
4
+ */
5
+
6
+ import '../daisyui.js';
7
+
8
+ /**
9
+ * Dock Component - bottom navigation bar
10
+ * @param {Object} props
11
+ * @param {string} props.size - 'xs' | 'sm' | 'md' | 'lg'
12
+ * @param {boolean} props.useShadow - Render in Shadow DOM with isolated DaisyUI styles
13
+ */
14
+ const Dock = (props = {}, ...children) => {
15
+ const { tags } = window.Lightview || {};
16
+ const LVX = window.LightviewX || {};
17
+
18
+ if (!tags) return null;
19
+
20
+ const { div, shadowDOM } = tags;
21
+
22
+ const {
23
+ size,
24
+ useShadow,
25
+ class: className = '',
26
+ ...rest
27
+ } = props;
28
+
29
+ const classes = ['dock'];
30
+ if (size) classes.push(`dock-${size}`);
31
+ if (className) classes.push(className);
32
+
33
+ const dockEl = div({ class: classes.join(' '), ...rest }, ...children);
34
+
35
+ // Check if we should use shadow DOM
36
+ let usesShadow = false;
37
+ if (LVX.shouldUseShadow) {
38
+ usesShadow = LVX.shouldUseShadow(useShadow);
39
+ } else {
40
+ usesShadow = useShadow === true;
41
+ }
42
+
43
+ if (usesShadow) {
44
+ const adoptedStyleSheets = LVX.getAdoptedStyleSheets ? LVX.getAdoptedStyleSheets() : [];
45
+
46
+ const themeValue = LVX.themeSignal ? () => LVX.themeSignal.value : 'light';
47
+
48
+ return div({ class: 'contents' },
49
+ shadowDOM({ mode: 'open', adoptedStyleSheets },
50
+ div({ 'data-theme': themeValue },
51
+ dockEl
52
+ )
53
+ )
54
+ );
55
+ }
56
+
57
+ return dockEl;
58
+ };
59
+
60
+ /**
61
+ * Dock Item
62
+ */
63
+ Dock.Item = (props = {}, ...children) => {
64
+ const { tags } = window.Lightview || {};
65
+ if (!tags) return null;
66
+
67
+ const {
68
+ active = false,
69
+ class: className = '',
70
+ ...rest
71
+ } = props;
72
+
73
+ const classes = [];
74
+ if (active) classes.push('dock-active');
75
+ if (className) classes.push(className);
76
+
77
+ return tags.button({
78
+ class: classes.join(' ') || undefined,
79
+ ...rest
80
+ }, ...children);
81
+ };
82
+
83
+ /**
84
+ * Dock Label
85
+ */
86
+ Dock.Label = (props = {}, ...children) => {
87
+ const { tags } = window.Lightview || {};
88
+ if (!tags) return null;
89
+
90
+ const { class: className = '', ...rest } = props;
91
+
92
+ return tags.span({
93
+ class: `dock-label ${className}`.trim(),
94
+ ...rest
95
+ }, ...children);
96
+ };
97
+
98
+ const tags = window.Lightview.tags;
99
+ tags.Dock = Dock;
100
+ tags['Dock.Item'] = Dock.Item;
101
+ tags['Dock.Label'] = Dock.Label;
102
+
103
+ export default Dock;
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Lightview Menu Component (DaisyUI)
3
+ * @see https://daisyui.com/components/menu/
4
+ */
5
+
6
+ import '../daisyui.js';
7
+
8
+ /**
9
+ * Menu Component
10
+ * @param {Object} props
11
+ * @param {boolean} props.horizontal - Horizontal layout
12
+ * @param {string} props.size - 'xs' | 'sm' | 'md' | 'lg'
13
+ * @param {string} props.bg - Background class
14
+ * @param {boolean} props.useShadow - Render in Shadow DOM with isolated DaisyUI styles
15
+ */
16
+ const Menu = (props = {}, ...children) => {
17
+ const { tags } = window.Lightview || {};
18
+ const LVX = window.LightviewX || {};
19
+
20
+ if (!tags) return null;
21
+
22
+ const { ul, div, shadowDOM } = tags;
23
+
24
+ const {
25
+ horizontal = false,
26
+ size,
27
+ bg = 'bg-base-200',
28
+ useShadow,
29
+ class: className = '',
30
+ ...rest
31
+ } = props;
32
+
33
+ const classes = ['menu', bg, 'rounded-box'];
34
+ if (horizontal) classes.push('menu-horizontal');
35
+ if (size) classes.push(`menu-${size}`);
36
+ if (className) classes.push(className);
37
+
38
+ const menuEl = ul({ class: classes.join(' '), ...rest }, ...children);
39
+
40
+ // Check if we should use shadow DOM
41
+ let usesShadow = false;
42
+ if (LVX.shouldUseShadow) {
43
+ usesShadow = LVX.shouldUseShadow(useShadow);
44
+ } else {
45
+ usesShadow = useShadow === true;
46
+ }
47
+
48
+ if (usesShadow) {
49
+ const adoptedStyleSheets = LVX.getAdoptedStyleSheets ? LVX.getAdoptedStyleSheets() : [];
50
+
51
+ const themeValue = LVX.themeSignal ? () => LVX.themeSignal.value : 'light';
52
+
53
+ return div({ class: 'contents' },
54
+ shadowDOM({ mode: 'open', adoptedStyleSheets },
55
+ div({ 'data-theme': themeValue },
56
+ menuEl
57
+ )
58
+ )
59
+ );
60
+ }
61
+
62
+ return menuEl;
63
+ };
64
+
65
+ /**
66
+ * Menu Item
67
+ */
68
+ Menu.Item = (props = {}, ...children) => {
69
+ const { tags } = window.Lightview || {};
70
+ if (!tags) return null;
71
+
72
+ const {
73
+ disabled = false,
74
+ active = false,
75
+ class: className = '',
76
+ ...rest
77
+ } = props;
78
+
79
+ const classes = [];
80
+ if (disabled) classes.push('disabled');
81
+ if (className) classes.push(className);
82
+
83
+ const innerClasses = [];
84
+ if (active) innerClasses.push('active');
85
+
86
+ return tags.li({ class: classes.join(' ') || undefined, ...rest },
87
+ tags.a({ class: innerClasses.join(' ') || undefined }, ...children)
88
+ );
89
+ };
90
+
91
+ /**
92
+ * Menu Title
93
+ */
94
+ Menu.Title = (props = {}, ...children) => {
95
+ const { tags } = window.Lightview || {};
96
+ if (!tags) return null;
97
+
98
+ const { class: className = '', ...rest } = props;
99
+
100
+ return tags.li({ class: `menu-title ${className}`.trim(), ...rest }, ...children);
101
+ };
102
+
103
+ /**
104
+ * Menu Dropdown (submenu)
105
+ */
106
+ Menu.Dropdown = (props = {}, ...children) => {
107
+ const { tags } = window.Lightview || {};
108
+ if (!tags) return null;
109
+
110
+ const { label, open = false, class: className = '', ...rest } = props;
111
+
112
+ const details = tags.details({ open, ...rest },
113
+ tags.summary({}, label),
114
+ tags.ul({}, ...children)
115
+ );
116
+
117
+ return tags.li({}, details);
118
+ };
119
+
120
+ const tags = window.Lightview.tags;
121
+ tags.Menu = Menu;
122
+ tags['Menu.Item'] = Menu.Item;
123
+ tags['Menu.Title'] = Menu.Title;
124
+ tags['Menu.Dropdown'] = Menu.Dropdown;
125
+
126
+ export default Menu;
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Lightview Pagination Component (DaisyUI)
3
+ * @see https://daisyui.com/components/pagination/
4
+ */
5
+
6
+ import '../daisyui.js';
7
+
8
+ /**
9
+ * Pagination Component
10
+ * @param {Object} props
11
+ * @param {number} props.currentPage - Current page number
12
+ * @param {number} props.totalPages - Total number of pages
13
+ * @param {function} props.onPageChange - Callback when page changes
14
+ * @param {string} props.size - 'xs' | 'sm' | 'md' | 'lg'
15
+ * @param {boolean} props.useShadow - Render in Shadow DOM with isolated DaisyUI styles
16
+ */
17
+ const Pagination = (props = {}, ...children) => {
18
+ const { tags } = window.Lightview || {};
19
+ const LVX = window.LightviewX || {};
20
+
21
+ if (!tags) return null;
22
+
23
+ const { div, button, shadowDOM } = tags;
24
+
25
+ const {
26
+ currentPage = 1,
27
+ totalPages = 1,
28
+ onPageChange,
29
+ size,
30
+ useShadow,
31
+ class: className = '',
32
+ ...rest
33
+ } = props;
34
+
35
+ const classes = ['join'];
36
+ if (className) classes.push(className);
37
+
38
+ const getCurrent = () => typeof currentPage === 'function' ? currentPage() : currentPage;
39
+
40
+ const buttons = [];
41
+
42
+ // Previous button
43
+ buttons.push(
44
+ button({
45
+ class: `join-item btn ${size ? `btn-${size}` : ''}`.trim(),
46
+ onclick: () => {
47
+ const current = getCurrent();
48
+ if (current > 1 && onPageChange) onPageChange(current - 1);
49
+ },
50
+ disabled: () => getCurrent() <= 1
51
+ }, '«')
52
+ );
53
+
54
+ // Page numbers
55
+ for (let i = 1; i <= totalPages; i++) {
56
+ buttons.push(
57
+ button({
58
+ class: () => `join-item btn ${size ? `btn-${size}` : ''} ${getCurrent() === i ? 'btn-active' : ''}`.trim(),
59
+ onclick: () => onPageChange && onPageChange(i)
60
+ }, String(i))
61
+ );
62
+ }
63
+
64
+ // Next button
65
+ buttons.push(
66
+ button({
67
+ class: `join-item btn ${size ? `btn-${size}` : ''}`.trim(),
68
+ onclick: () => {
69
+ const current = getCurrent();
70
+ if (current < totalPages && onPageChange) onPageChange(current + 1);
71
+ },
72
+ disabled: () => getCurrent() >= totalPages
73
+ }, '»')
74
+ );
75
+
76
+ const paginationEl = div({ class: classes.join(' '), ...rest }, ...buttons, ...children);
77
+
78
+ // Check if we should use shadow DOM
79
+ let usesShadow = false;
80
+ if (LVX.shouldUseShadow) {
81
+ usesShadow = LVX.shouldUseShadow(useShadow);
82
+ } else {
83
+ usesShadow = useShadow === true;
84
+ }
85
+
86
+ if (usesShadow) {
87
+ const adoptedStyleSheets = LVX.getAdoptedStyleSheets ? LVX.getAdoptedStyleSheets() : [];
88
+
89
+ const themeValue = LVX.themeSignal ? () => LVX.themeSignal.value : 'light';
90
+
91
+ return div({ class: 'contents' },
92
+ shadowDOM({ mode: 'open', adoptedStyleSheets },
93
+ div({ 'data-theme': themeValue },
94
+ paginationEl
95
+ )
96
+ )
97
+ );
98
+ }
99
+
100
+ return paginationEl;
101
+ };
102
+
103
+ window.Lightview.tags.Pagination = Pagination;
104
+
105
+ export default Pagination;
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Lightview Steps Component (DaisyUI)
3
+ * @see https://daisyui.com/components/steps/
4
+ */
5
+
6
+ import '../daisyui.js';
7
+
8
+ /**
9
+ * Steps Component
10
+ * @param {Object} props
11
+ * @param {boolean} props.vertical - Vertical layout
12
+ * @param {boolean} props.useShadow - Render in Shadow DOM with isolated DaisyUI styles
13
+ */
14
+ const Steps = (props = {}, ...children) => {
15
+ const { tags } = window.Lightview || {};
16
+ const LVX = window.LightviewX || {};
17
+
18
+ if (!tags) return null;
19
+
20
+ const { ul, div, shadowDOM } = tags;
21
+
22
+ const {
23
+ vertical = false,
24
+ useShadow,
25
+ class: className = '',
26
+ ...rest
27
+ } = props;
28
+
29
+ const classes = ['steps'];
30
+ if (vertical) classes.push('steps-vertical');
31
+ if (className) classes.push(className);
32
+
33
+ const stepsEl = ul({ class: classes.join(' '), ...rest }, ...children);
34
+
35
+ // Check if we should use shadow DOM
36
+ let usesShadow = false;
37
+ if (LVX.shouldUseShadow) {
38
+ usesShadow = LVX.shouldUseShadow(useShadow);
39
+ } else {
40
+ usesShadow = useShadow === true;
41
+ }
42
+
43
+ if (usesShadow) {
44
+ const adoptedStyleSheets = LVX.getAdoptedStyleSheets ? LVX.getAdoptedStyleSheets() : [];
45
+
46
+ const themeValue = LVX.themeSignal ? () => LVX.themeSignal.value : 'light';
47
+
48
+ return div({ class: 'contents' },
49
+ shadowDOM({ mode: 'open', adoptedStyleSheets },
50
+ div({ 'data-theme': themeValue },
51
+ stepsEl
52
+ )
53
+ )
54
+ );
55
+ }
56
+
57
+ return stepsEl;
58
+ };
59
+
60
+ /**
61
+ * Steps Item
62
+ */
63
+ Steps.Item = (props = {}, ...children) => {
64
+ const { tags } = window.Lightview || {};
65
+ if (!tags) return null;
66
+
67
+ const {
68
+ color,
69
+ content,
70
+ class: className = '',
71
+ ...rest
72
+ } = props;
73
+
74
+ const classes = ['step'];
75
+ if (color) classes.push(`step-${color}`);
76
+ if (className) classes.push(className);
77
+
78
+ return tags.li({
79
+ class: classes.join(' '),
80
+ 'data-content': content,
81
+ ...rest
82
+ }, ...children);
83
+ };
84
+
85
+ const tags = window.Lightview.tags;
86
+ tags.Steps = Steps;
87
+ tags['Steps.Item'] = Steps.Item;
88
+
89
+ export default Steps;
@@ -0,0 +1,177 @@
1
+ .lv-tabs {
2
+ display: flex;
3
+ flex-direction: column;
4
+ font-family: var(--lv-font-family);
5
+ }
6
+
7
+ /* Tab List */
8
+ .lv-tabs__list {
9
+ display: flex;
10
+ gap: 0;
11
+ border-bottom: 1px solid var(--lv-color-border);
12
+ margin: 0;
13
+ padding: 0;
14
+ list-style: none;
15
+ overflow-x: auto;
16
+ scrollbar-width: thin;
17
+ }
18
+
19
+ .lv-tabs__list::-webkit-scrollbar {
20
+ height: 4px;
21
+ }
22
+
23
+ .lv-tabs__list::-webkit-scrollbar-thumb {
24
+ background-color: var(--lv-color-border);
25
+ border-radius: var(--lv-radius-full);
26
+ }
27
+
28
+ /* Variants */
29
+ .lv-tabs[data-variant="underline"] .lv-tabs__list {
30
+ gap: var(--lv-spacing-md);
31
+ }
32
+
33
+ .lv-tabs[data-variant="pills"] .lv-tabs__list {
34
+ gap: var(--lv-spacing-xs);
35
+ border-bottom: none;
36
+ padding: var(--lv-spacing-xs);
37
+ background-color: var(--lv-color-neutral-light);
38
+ border-radius: var(--lv-radius-lg);
39
+ }
40
+
41
+ .lv-tabs[data-variant="enclosed"] .lv-tabs__list {
42
+ gap: 0;
43
+ }
44
+
45
+ /* Tab Button */
46
+ .lv-tabs__tab {
47
+ position: relative;
48
+ display: flex;
49
+ align-items: center;
50
+ justify-content: center;
51
+ gap: var(--lv-spacing-xs);
52
+ padding: var(--lv-spacing-sm) var(--lv-spacing-md);
53
+ background: none;
54
+ border: none;
55
+ font-family: inherit;
56
+ font-size: var(--lv-font-size-md);
57
+ font-weight: var(--lv-font-weight-medium);
58
+ color: var(--lv-color-text-secondary);
59
+ cursor: pointer;
60
+ white-space: nowrap;
61
+ transition: all var(--lv-transition-fast);
62
+ }
63
+
64
+ .lv-tabs__tab:hover {
65
+ color: var(--lv-color-text);
66
+ }
67
+
68
+ .lv-tabs__tab:focus-visible {
69
+ outline: 2px solid var(--lv-color-primary);
70
+ outline-offset: -2px;
71
+ border-radius: var(--lv-radius-sm);
72
+ }
73
+
74
+ .lv-tabs__tab:disabled {
75
+ opacity: 0.5;
76
+ cursor: not-allowed;
77
+ }
78
+
79
+ .lv-tabs__tab[aria-selected="true"] {
80
+ color: var(--lv-color-primary);
81
+ }
82
+
83
+ /* Underline variant styling */
84
+ .lv-tabs[data-variant="underline"] .lv-tabs__tab {
85
+ padding-bottom: calc(var(--lv-spacing-sm) + 2px);
86
+ margin-bottom: -1px;
87
+ }
88
+
89
+ .lv-tabs[data-variant="underline"] .lv-tabs__tab[aria-selected="true"]::after {
90
+ content: '';
91
+ position: absolute;
92
+ bottom: 0;
93
+ left: 0;
94
+ right: 0;
95
+ height: 2px;
96
+ background-color: var(--lv-color-primary);
97
+ border-radius: var(--lv-radius-full) var(--lv-radius-full) 0 0;
98
+ }
99
+
100
+ /* Pills variant styling */
101
+ .lv-tabs[data-variant="pills"] .lv-tabs__tab {
102
+ border-radius: var(--lv-radius-md);
103
+ }
104
+
105
+ .lv-tabs[data-variant="pills"] .lv-tabs__tab[aria-selected="true"] {
106
+ background-color: var(--lv-color-surface);
107
+ color: var(--lv-color-text);
108
+ box-shadow: var(--lv-shadow-sm);
109
+ }
110
+
111
+ /* Enclosed variant styling */
112
+ .lv-tabs[data-variant="enclosed"] .lv-tabs__tab {
113
+ border: 1px solid transparent;
114
+ border-bottom: none;
115
+ border-radius: var(--lv-radius-md) var(--lv-radius-md) 0 0;
116
+ margin-bottom: -1px;
117
+ }
118
+
119
+ .lv-tabs[data-variant="enclosed"] .lv-tabs__tab[aria-selected="true"] {
120
+ background-color: var(--lv-color-surface);
121
+ border-color: var(--lv-color-border);
122
+ color: var(--lv-color-text);
123
+ }
124
+
125
+ /* Tab Panel */
126
+ .lv-tabs__panel {
127
+ padding: var(--lv-spacing-md) 0;
128
+ }
129
+
130
+ .lv-tabs__panel[hidden] {
131
+ display: none;
132
+ }
133
+
134
+ /* Sizes */
135
+ .lv-tabs[data-size="sm"] .lv-tabs__tab {
136
+ padding: var(--lv-spacing-xs) var(--lv-spacing-sm);
137
+ font-size: var(--lv-font-size-sm);
138
+ }
139
+
140
+ .lv-tabs[data-size="lg"] .lv-tabs__tab {
141
+ padding: var(--lv-spacing-md) var(--lv-spacing-lg);
142
+ font-size: var(--lv-font-size-lg);
143
+ }
144
+
145
+ /* Full width tabs */
146
+ .lv-tabs[data-width="full"] .lv-tabs__list {
147
+ width: 100%;
148
+ }
149
+
150
+ .lv-tabs[data-width="full"] .lv-tabs__tab {
151
+ flex: 1;
152
+ }
153
+
154
+ /* Icon in tab */
155
+ .lv-tabs__tab .lv-icon {
156
+ flex-shrink: 0;
157
+ }
158
+
159
+ /* Badge/count in tab */
160
+ .lv-tabs__badge {
161
+ display: inline-flex;
162
+ align-items: center;
163
+ justify-content: center;
164
+ min-width: 1.25rem;
165
+ height: 1.25rem;
166
+ padding: 0 0.375rem;
167
+ font-size: var(--lv-font-size-xs);
168
+ font-weight: var(--lv-font-weight-semibold);
169
+ background-color: var(--lv-color-neutral-light);
170
+ color: var(--lv-color-text-secondary);
171
+ border-radius: var(--lv-radius-full);
172
+ }
173
+
174
+ .lv-tabs__tab[aria-selected="true"] .lv-tabs__badge {
175
+ background-color: var(--lv-color-primary-light);
176
+ color: var(--lv-color-primary);
177
+ }