lightview 1.8.2 → 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.
- package/.agent/workflows/daisyui-component-migration.md +155 -0
- package/.codacy/cli.sh +149 -0
- package/.codacy/codacy.yaml +15 -0
- package/.github/instructions/codacy.instructions.md +72 -0
- package/.wranglerignore +21 -0
- package/README.md +1330 -19
- package/_headers +4 -0
- package/build.js +70 -0
- package/components/actions/button.js +151 -0
- package/components/actions/dropdown.js +120 -0
- package/components/actions/modal.js +146 -0
- package/components/actions/swap.js +118 -0
- package/components/daisyui.js +288 -0
- package/components/data-display/accordion.js +128 -0
- package/components/data-display/alert.js +112 -0
- package/components/data-display/avatar.js +170 -0
- package/components/data-display/badge.js +82 -0
- package/components/data-display/card.js +151 -0
- package/components/data-display/carousel.js +94 -0
- package/components/data-display/chart.js +220 -0
- package/components/data-display/chat.js +128 -0
- package/components/data-display/collapse.js +103 -0
- package/components/data-display/countdown.js +69 -0
- package/components/data-display/diff.js +111 -0
- package/components/data-display/kbd.js +65 -0
- package/components/data-display/loading.js +75 -0
- package/components/data-display/progress.js +79 -0
- package/components/data-display/radial-progress.js +88 -0
- package/components/data-display/skeleton.js +66 -0
- package/components/data-display/stats.js +159 -0
- package/components/data-display/table.js +146 -0
- package/components/data-display/timeline.js +146 -0
- package/components/data-display/toast.js +72 -0
- package/components/data-display/tooltip.js +74 -0
- package/components/data-input/checkbox.js +253 -0
- package/components/data-input/file-input.js +224 -0
- package/components/data-input/input.js +264 -0
- package/components/data-input/radio.js +338 -0
- package/components/data-input/range.js +204 -0
- package/components/data-input/rating.js +219 -0
- package/components/data-input/select.js +287 -0
- package/components/data-input/textarea.js +287 -0
- package/components/data-input/toggle.js +201 -0
- package/components/index.js +137 -0
- package/components/layout/divider.js +72 -0
- package/components/layout/drawer.js +142 -0
- package/components/layout/footer.js +100 -0
- package/components/layout/hero.js +109 -0
- package/components/layout/indicator.js +90 -0
- package/components/layout/join.js +78 -0
- package/components/layout/navbar.js +110 -0
- package/components/navigation/breadcrumbs.js +91 -0
- package/components/navigation/dock.js +103 -0
- package/components/navigation/menu.js +126 -0
- package/components/navigation/pagination.js +105 -0
- package/components/navigation/steps.js +89 -0
- package/components/navigation/tabs.css +177 -0
- package/components/navigation/tabs.js +123 -0
- package/components/theme/theme-switch.css +65 -0
- package/components/theme/theme-switch.js +177 -0
- package/docs/about.html +164 -0
- package/docs/api/computed.html +184 -0
- package/docs/api/effects.html +173 -0
- package/docs/api/elements.html +180 -0
- package/docs/api/enhance.html +225 -0
- package/docs/api/hypermedia.html +165 -0
- package/docs/api/index.html +178 -0
- package/docs/api/nav.html +18 -0
- package/docs/api/signals.html +136 -0
- package/docs/api/state.html +217 -0
- package/docs/assets/images/logo-favicon.svg +42 -0
- package/docs/assets/images/logo-static.svg +40 -0
- package/docs/assets/images/logo.svg +66 -0
- package/docs/assets/js/examplify.js +395 -0
- package/docs/assets/styles/site.css +1102 -0
- package/docs/assets/styles/themes.css +236 -0
- package/docs/components/accordion.html +439 -0
- package/docs/components/alert.html +528 -0
- package/docs/components/avatar.html +586 -0
- package/docs/components/badge.html +531 -0
- package/docs/components/breadcrumbs.html +278 -0
- package/docs/components/button.html +579 -0
- package/docs/components/card.html +561 -0
- package/docs/components/carousel.html +286 -0
- package/docs/components/chart-area.html +702 -0
- package/docs/components/chart-bar.html +782 -0
- package/docs/components/chart-column.html +735 -0
- package/docs/components/chart-line.html +794 -0
- package/docs/components/chart-pie.html +823 -0
- package/docs/components/chart.html +610 -15
- package/docs/components/chat.html +547 -0
- package/docs/components/checkbox.html +641 -0
- package/docs/components/collapse.html +536 -0
- package/docs/components/component-nav.html +53 -0
- package/docs/components/countdown.html +470 -0
- package/docs/components/diff.html +245 -0
- package/docs/components/divider.html +240 -0
- package/docs/components/dock.html +277 -0
- package/docs/components/drawer.html +515 -0
- package/docs/components/dropdown.html +479 -0
- package/docs/components/file-input.html +591 -0
- package/docs/components/footer.html +301 -0
- package/docs/components/gallery.html +504 -0
- package/docs/components/hero.html +264 -0
- package/docs/components/index.css +840 -0
- package/docs/components/index.html +735 -0
- package/docs/components/indicator.html +342 -0
- package/docs/components/input.html +644 -0
- package/docs/components/join.html +285 -0
- package/docs/components/kbd.html +322 -0
- package/docs/components/loading.html +521 -0
- package/docs/components/menu.html +461 -0
- package/docs/components/modal.html +639 -0
- package/docs/components/navbar.html +321 -0
- package/docs/components/pagination.html +279 -0
- package/docs/components/progress.html +514 -0
- package/docs/components/radial-progress.html +434 -0
- package/docs/components/radio.html +655 -0
- package/docs/components/range.html +611 -0
- package/docs/components/rating.html +642 -0
- package/docs/components/select.html +696 -0
- package/docs/components/sidebar-setup.js +93 -0
- package/docs/components/skeleton.html +447 -0
- package/docs/components/spinner.html +68 -0
- package/docs/components/stats.html +486 -0
- package/docs/components/steps.html +356 -0
- package/docs/components/swap.html +517 -0
- package/docs/components/switch.html +68 -0
- package/docs/components/table.html +668 -0
- package/docs/components/tabs.html +506 -0
- package/docs/components/text-input.html +68 -0
- package/docs/components/textarea.html +603 -0
- package/docs/components/timeline.html +485 -42
- package/docs/components/toast.html +474 -0
- package/docs/components/toggle.html +564 -0
- package/docs/components/tooltip.html +423 -0
- package/docs/examples/getting-started-example.html +40 -0
- package/docs/examples/index.html +93 -0
- package/docs/getting-started/index.html +739 -0
- package/docs/getting-started/reviews.html +23 -0
- package/docs/getting-started/reviews.odom +108 -0
- package/docs/getting-started/reviews.vdom +84 -0
- package/docs/index.html +132 -42
- package/docs/playground.html +416 -0
- package/docs/router.html +285 -0
- package/docs/styles/index.html +190 -0
- package/functions/_middleware.js +32 -0
- package/index.html +309 -0
- package/lightview-router.js +364 -0
- package/lightview-x.js +1577 -0
- package/lightview.js +659 -1200
- package/lightview.js.backup +793 -0
- package/middleware/locale.js +25 -0
- package/middleware/markdown.js +44 -0
- package/middleware/notFound.js +37 -0
- package/package.json +27 -41
- package/watch.js +92 -0
- package/wrangler.toml +12 -0
- package/.idea/lightview.iml +0 -12
- package/.idea/modules.xml +0 -8
- package/.idea/vcs.xml +0 -6
- package/LICENSE +0 -21
- package/codepen-no-tabs-embed.css +0 -2
- package/docs/CNAME +0 -1
- package/docs/api.html +0 -674
- package/docs/blank.html +0 -10
- package/docs/comparedto.html +0 -89
- package/docs/components/chart-repl.html +0 -69
- package/docs/components/components.js +0 -113
- package/docs/components/contents.html +0 -17
- package/docs/components/gantt-repl.html +0 -61
- package/docs/components/gantt.html +0 -42
- package/docs/components/gauge-repl.html +0 -66
- package/docs/components/gauge.html +0 -20
- package/docs/components/orgchart-repl.html +0 -64
- package/docs/components/orgchart.html +0 -41
- package/docs/components/repl-as-src.html +0 -17
- package/docs/components/repl-repl.html +0 -95
- package/docs/components/repl.html +0 -527
- package/docs/components/timeline-repl.html +0 -72
- package/docs/components.html +0 -14
- package/docs/css/highlightjs.min.css +0 -9
- package/docs/css/tutorial.css +0 -35
- package/docs/examples/anchor.html +0 -11
- package/docs/examples/chart.html +0 -34
- package/docs/examples/counter.html +0 -26
- package/docs/examples/counter.test.mjs +0 -47
- package/docs/examples/counter2.html +0 -26
- package/docs/examples/directives.html +0 -79
- package/docs/examples/foreign.html +0 -50
- package/docs/examples/forgeinform.html +0 -98
- package/docs/examples/form.html +0 -61
- package/docs/examples/gauge.html +0 -18
- package/docs/examples/invalid-template-literals.html +0 -44
- package/docs/examples/medium/remote.html +0 -60
- package/docs/examples/message.html +0 -18
- package/docs/examples/nested.html +0 -11
- package/docs/examples/object-bound-form.html +0 -34
- package/docs/examples/remote-server.js +0 -51
- package/docs/examples/remote.html +0 -34
- package/docs/examples/remote.json +0 -1
- package/docs/examples/scratch.html +0 -69
- package/docs/examples/sensors/index.html +0 -44
- package/docs/examples/sensors/sensor-server.js +0 -30
- package/docs/examples/shared.html +0 -41
- package/docs/examples/template.html +0 -33
- package/docs/examples/timeline.html +0 -21
- package/docs/examples/todo.html +0 -40
- package/docs/examples/top.html +0 -10
- package/docs/examples/types.html +0 -94
- package/docs/examples/xor.html +0 -62
- package/docs/examples.html +0 -25
- package/docs/javascript/codejar.min.js +0 -8
- package/docs/javascript/highlightjs.min.js +0 -1173
- package/docs/javascript/isomorphic-git.js +0 -9
- package/docs/javascript/json5.min.js +0 -1
- package/docs/javascript/lightning-fs.js +0 -1
- package/docs/javascript/lightview.js +0 -1285
- package/docs/javascript/marked.min.js +0 -6
- package/docs/javascript/peerjs.min.js +0 -70
- package/docs/javascript/turndown.js +0 -973
- package/docs/javascript/types.js +0 -606
- package/docs/javascript/utils.js +0 -45
- package/docs/lightview.html +0 -63
- package/docs/old_index.html +0 -965
- package/docs/old_index.md +0 -1132
- package/docs/slidein.html +0 -51
- package/docs/tutorial/0-getting-started.html +0 -67
- package/docs/tutorial/1-intro-to-variables.html +0 -103
- package/docs/tutorial/10-template-components.html +0 -80
- package/docs/tutorial/11-linked-components.html +0 -76
- package/docs/tutorial/12-imported-components.html +0 -67
- package/docs/tutorial/13-input-binding.html +0 -94
- package/docs/tutorial/14-automatic-variable-creation.html +0 -74
- package/docs/tutorial/15-form-binding.html +0 -110
- package/docs/tutorial/16-if-directive.html +0 -60
- package/docs/tutorial/17-loop-directives.html +0 -83
- package/docs/tutorial/18-sanitizing-and-escaping-input.html +0 -79
- package/docs/tutorial/2-imported-and-exported-variables.html +0 -80
- package/docs/tutorial/3-data-types.html +0 -89
- package/docs/tutorial/4-extended-data-types.html +0 -83
- package/docs/tutorial/5-extended-functional-types.html +0 -96
- package/docs/tutorial/5.1-extended-functional-types.html +0 -79
- package/docs/tutorial/5.2-extended-functional-types.html +0 -70
- package/docs/tutorial/6-conventional-javascript.html +0 -75
- package/docs/tutorial/7-monitoring-with-observers.html +0 -107
- package/docs/tutorial/8-event-listeners.html +0 -65
- package/docs/tutorial/9-intro-to-components.html +0 -91
- package/docs/tutorial/contents.html +0 -32
- package/docs/tutorial/my-component.html +0 -29
- package/docs/tutorial/remote-value.json +0 -4
- package/docs/websiterepl.html +0 -46
- package/jest-puppeteer.config.js +0 -5
- package/jest.config.json +0 -12
- package/lightview.min.js +0 -1
- package/lightview_good.js +0 -1267
- package/lightview_optimized.js +0 -1274
- package/repl_hold.html +0 -320
- package/test/basic.html +0 -104
- package/test/basic.test.mjs +0 -315
- package/test/extended.html +0 -29
- package/test/extended.test.mjs +0 -448
- package/types.js +0 -607
- package/unsplash.key +0 -1
package/_headers
ADDED
package/build.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
const rootDir = __dirname;
|
|
5
|
+
const distDir = path.join(rootDir, 'dist');
|
|
6
|
+
const docsDir = path.join(rootDir, 'docs');
|
|
7
|
+
const componentsDir = path.join(rootDir, 'components');
|
|
8
|
+
const middlewareDir = path.join(rootDir, 'middleware');
|
|
9
|
+
|
|
10
|
+
// Configuration
|
|
11
|
+
// Files in root that should be copied
|
|
12
|
+
const allowedExtensions = ['.html', '.js', '.css', '.txt', '.xml', '.ico', '.png', '.svg', '.jpg', '.jpeg', '.md'];
|
|
13
|
+
const includeFiles = ['_headers']; // specific files to always include
|
|
14
|
+
const excludeFiles = ['build.js', 'package.json', 'package-lock.json', 'wrangler.toml'];
|
|
15
|
+
|
|
16
|
+
console.log('Building for deployment...');
|
|
17
|
+
|
|
18
|
+
// 1. Clean/Create dist
|
|
19
|
+
if (fs.existsSync(distDir)) {
|
|
20
|
+
fs.rmSync(distDir, { recursive: true, force: true });
|
|
21
|
+
}
|
|
22
|
+
fs.mkdirSync(distDir);
|
|
23
|
+
console.log('Created dist directory.');
|
|
24
|
+
|
|
25
|
+
// 2. Copy Root Files
|
|
26
|
+
const files = fs.readdirSync(rootDir);
|
|
27
|
+
files.forEach(file => {
|
|
28
|
+
const srcPath = path.join(rootDir, file);
|
|
29
|
+
const stat = fs.statSync(srcPath);
|
|
30
|
+
|
|
31
|
+
if (stat.isFile()) {
|
|
32
|
+
const ext = path.extname(file).toLowerCase();
|
|
33
|
+
|
|
34
|
+
// Check if file should be copied
|
|
35
|
+
const isAllowedExt = allowedExtensions.includes(ext);
|
|
36
|
+
const isExplicitInclude = includeFiles.includes(file);
|
|
37
|
+
const isExcluded = excludeFiles.includes(file) || file.startsWith('.');
|
|
38
|
+
|
|
39
|
+
if ((isAllowedExt || isExplicitInclude) && !isExcluded) {
|
|
40
|
+
fs.copyFileSync(srcPath, path.join(distDir, file));
|
|
41
|
+
console.log(`Copied: ${file}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// 3. Copy Docs Directory
|
|
47
|
+
if (fs.existsSync(docsDir)) {
|
|
48
|
+
fs.cpSync(docsDir, path.join(distDir, 'docs'), { recursive: true });
|
|
49
|
+
console.log('Copied: docs directory');
|
|
50
|
+
} else {
|
|
51
|
+
console.warn('Warning: docs directory not found.');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 4. Copy Components Directory
|
|
55
|
+
if (fs.existsSync(componentsDir)) {
|
|
56
|
+
fs.cpSync(componentsDir, path.join(distDir, 'components'), { recursive: true });
|
|
57
|
+
console.log('Copied: components directory');
|
|
58
|
+
} else {
|
|
59
|
+
console.warn('Warning: components directory not found.');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 5. Copy Middleware Directory
|
|
63
|
+
if (fs.existsSync(middlewareDir)) {
|
|
64
|
+
fs.cpSync(middlewareDir, path.join(distDir, 'middleware'), { recursive: true });
|
|
65
|
+
console.log('Copied: middleware directory');
|
|
66
|
+
} else {
|
|
67
|
+
console.warn('Warning: middleware directory not found.');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.log('Build complete! Assets are ready in ./dist');
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightview Button Component (DaisyUI)
|
|
3
|
+
* @see https://daisyui.com/components/button/
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import '../daisyui.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Button Component
|
|
10
|
+
* @param {Object} props
|
|
11
|
+
* @param {string} props.color - 'primary' | 'secondary' | 'accent' | 'neutral' | 'info' | 'success' | 'warning' | 'error' | 'ghost' | 'link'
|
|
12
|
+
* @param {string} props.size - 'xs' | 'sm' | 'md' | 'lg'
|
|
13
|
+
* @param {string} props.variant - 'outline' | 'soft' | 'dash' | 'wide' | 'block' | 'square' | 'circle'
|
|
14
|
+
* @param {boolean} props.disabled - Disable the button
|
|
15
|
+
* @param {boolean} props.loading - Show loading state
|
|
16
|
+
* @param {boolean} props.active - Force active state
|
|
17
|
+
* @param {boolean} props.glass - Glass morphism effect
|
|
18
|
+
* @param {boolean} props.noAnimation - Disable click animation
|
|
19
|
+
* @param {boolean} props.useShadow - Render in Shadow DOM with isolated DaisyUI styles
|
|
20
|
+
* @param {...children} children - Button content
|
|
21
|
+
*/
|
|
22
|
+
const Button = (props = {}, ...children) => {
|
|
23
|
+
const { tags } = window.Lightview || {};
|
|
24
|
+
const LVX = window.LightviewX || {};
|
|
25
|
+
|
|
26
|
+
if (!tags) {
|
|
27
|
+
console.error('Lightview not found');
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const { button, div, span, shadowDOM } = tags;
|
|
32
|
+
|
|
33
|
+
const {
|
|
34
|
+
color,
|
|
35
|
+
size,
|
|
36
|
+
variant,
|
|
37
|
+
disabled = false,
|
|
38
|
+
loading = false,
|
|
39
|
+
active = false,
|
|
40
|
+
glass = false,
|
|
41
|
+
noAnimation = false,
|
|
42
|
+
useShadow,
|
|
43
|
+
theme, // Explicit theme override
|
|
44
|
+
class: className = '',
|
|
45
|
+
...rest
|
|
46
|
+
} = props;
|
|
47
|
+
|
|
48
|
+
const getClassList = () => {
|
|
49
|
+
const classes = ['btn'];
|
|
50
|
+
|
|
51
|
+
// Color
|
|
52
|
+
if (['primary', 'secondary', 'accent', 'neutral', 'info', 'success', 'warning', 'error', 'ghost', 'link'].includes(color)) classes.push(`btn-${color}`);
|
|
53
|
+
|
|
54
|
+
// Size
|
|
55
|
+
if (size) classes.push(`btn-${size}`);
|
|
56
|
+
|
|
57
|
+
// Variant
|
|
58
|
+
if (variant === 'outline') classes.push('btn-outline');
|
|
59
|
+
else if (variant === 'soft') classes.push('btn-soft');
|
|
60
|
+
else if (variant === 'dash') classes.push('btn-dash');
|
|
61
|
+
else if (variant === 'wide') classes.push('btn-wide');
|
|
62
|
+
else if (variant === 'block') classes.push('btn-block');
|
|
63
|
+
else if (variant === 'square') classes.push('btn-square');
|
|
64
|
+
else if (variant === 'circle') classes.push('btn-circle');
|
|
65
|
+
|
|
66
|
+
// States
|
|
67
|
+
const isDisabled = typeof disabled === 'function' ? disabled() : disabled;
|
|
68
|
+
const isLoading = typeof loading === 'function' ? loading() : loading;
|
|
69
|
+
const isActive = typeof active === 'function' ? active() : active;
|
|
70
|
+
|
|
71
|
+
if (isDisabled) classes.push('btn-disabled');
|
|
72
|
+
if (isActive) classes.push('btn-active');
|
|
73
|
+
if (glass) classes.push('glass');
|
|
74
|
+
if (noAnimation) classes.push('no-animation');
|
|
75
|
+
|
|
76
|
+
if (className) classes.push(className);
|
|
77
|
+
|
|
78
|
+
return classes.join(' ');
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const buildContent = () => {
|
|
82
|
+
const isLoading = typeof loading === 'function' ? loading() : loading;
|
|
83
|
+
if (isLoading) {
|
|
84
|
+
return [
|
|
85
|
+
tags.span({ class: 'loading loading-spinner' }),
|
|
86
|
+
...children
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
return children;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
if (color && !['primary', 'secondary', 'accent', 'neutral', 'info', 'success', 'warning', 'error', 'ghost', 'link'].includes(color)) {
|
|
93
|
+
// set the background color using style
|
|
94
|
+
rest.style = rest.style || '';
|
|
95
|
+
if (typeof rest.style === 'object') {
|
|
96
|
+
rest.style.backgroundColor = color;
|
|
97
|
+
} else {
|
|
98
|
+
rest.style += `;background-color: ${color};`;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const buttonEl = button({
|
|
102
|
+
class: typeof disabled === 'function' || typeof loading === 'function' || typeof active === 'function'
|
|
103
|
+
? () => getClassList()
|
|
104
|
+
: getClassList(),
|
|
105
|
+
disabled: typeof disabled === 'function'
|
|
106
|
+
? () => disabled() || (typeof loading === 'function' ? loading() : loading)
|
|
107
|
+
: disabled || loading,
|
|
108
|
+
...rest
|
|
109
|
+
}, ...(typeof loading === 'function' ? [() => buildContent()] : buildContent()));
|
|
110
|
+
|
|
111
|
+
// Check if we should use shadow DOM
|
|
112
|
+
let usesShadow = false;
|
|
113
|
+
if (LVX.shouldUseShadow) {
|
|
114
|
+
usesShadow = LVX.shouldUseShadow(useShadow);
|
|
115
|
+
} else {
|
|
116
|
+
usesShadow = useShadow === true;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (usesShadow) {
|
|
120
|
+
const adoptedStyleSheets = LVX.getAdoptedStyleSheets ? LVX.getAdoptedStyleSheets() : [];
|
|
121
|
+
|
|
122
|
+
// If theme is explicitly provided, wrap in a div with data-theme
|
|
123
|
+
// Otherwise, return button directly in shadow root to allow inheritance from host
|
|
124
|
+
// Use reactive theme signal if available, otherwise fallback to explicit 'theme' prop or default
|
|
125
|
+
const themeValue = theme || (LVX.themeSignal ? () => LVX.themeSignal.value : 'light');
|
|
126
|
+
|
|
127
|
+
return div({ class: 'content', style: 'display: inline-block' },
|
|
128
|
+
shadowDOM({ mode: 'open', adoptedStyleSheets },
|
|
129
|
+
div({ 'data-theme': themeValue },
|
|
130
|
+
buttonEl
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return buttonEl;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
window.Lightview.tags.Button = Button;
|
|
141
|
+
|
|
142
|
+
// Register as Custom Element
|
|
143
|
+
if (window.LightviewX?.createCustomElement) {
|
|
144
|
+
const ButtonElement = window.LightviewX.createCustomElement(Button);
|
|
145
|
+
if (!customElements.get('lv-button')) {
|
|
146
|
+
customElements.define('lv-button', ButtonElement);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
export default Button;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightview Dropdown Component (DaisyUI)
|
|
3
|
+
* @see https://daisyui.com/components/dropdown/
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import '../daisyui.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Dropdown Component
|
|
10
|
+
* @param {Object} props
|
|
11
|
+
* @param {string} props.position - 'top' | 'bottom' | 'left' | 'right' | 'end'
|
|
12
|
+
* @param {boolean} props.hover - Open on hover
|
|
13
|
+
* @param {boolean} props.open - Force open state
|
|
14
|
+
* @param {boolean} props.useShadow - Render in Shadow DOM with isolated DaisyUI styles
|
|
15
|
+
*/
|
|
16
|
+
const Dropdown = (props = {}, ...children) => {
|
|
17
|
+
const { tags } = window.Lightview || {};
|
|
18
|
+
const LVX = window.LightviewX || {};
|
|
19
|
+
|
|
20
|
+
if (!tags) return null;
|
|
21
|
+
|
|
22
|
+
const { div, shadowDOM } = tags;
|
|
23
|
+
|
|
24
|
+
const {
|
|
25
|
+
position,
|
|
26
|
+
hover = false,
|
|
27
|
+
open = false,
|
|
28
|
+
useShadow,
|
|
29
|
+
class: className = '',
|
|
30
|
+
...rest
|
|
31
|
+
} = props;
|
|
32
|
+
|
|
33
|
+
const classes = ['dropdown'];
|
|
34
|
+
if (position === 'top') classes.push('dropdown-top');
|
|
35
|
+
else if (position === 'bottom') classes.push('dropdown-bottom');
|
|
36
|
+
else if (position === 'left') classes.push('dropdown-left');
|
|
37
|
+
else if (position === 'right') classes.push('dropdown-right');
|
|
38
|
+
else if (position === 'end') classes.push('dropdown-end');
|
|
39
|
+
|
|
40
|
+
if (hover) classes.push('dropdown-hover');
|
|
41
|
+
if (open) classes.push('dropdown-open');
|
|
42
|
+
if (className) classes.push(className);
|
|
43
|
+
|
|
44
|
+
const dropdownEl = div({ class: classes.join(' '), ...rest }, ...children);
|
|
45
|
+
|
|
46
|
+
// Check if we should use shadow DOM
|
|
47
|
+
let usesShadow = false;
|
|
48
|
+
if (LVX.shouldUseShadow) {
|
|
49
|
+
usesShadow = LVX.shouldUseShadow(useShadow);
|
|
50
|
+
} else {
|
|
51
|
+
usesShadow = useShadow === true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (usesShadow) {
|
|
55
|
+
const adoptedStyleSheets = LVX.getAdoptedStyleSheets ? LVX.getAdoptedStyleSheets() : [];
|
|
56
|
+
|
|
57
|
+
const themeValue = LVX.themeSignal ? () => LVX.themeSignal.value : 'light';
|
|
58
|
+
|
|
59
|
+
return div({ class: 'contents' },
|
|
60
|
+
shadowDOM({ mode: 'open', adoptedStyleSheets },
|
|
61
|
+
div({ 'data-theme': themeValue },
|
|
62
|
+
dropdownEl
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return dropdownEl;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Dropdown Trigger - the element that toggles the dropdown
|
|
73
|
+
*/
|
|
74
|
+
Dropdown.Trigger = (props = {}, ...children) => {
|
|
75
|
+
const { tags } = window.Lightview || {};
|
|
76
|
+
if (!tags) return null;
|
|
77
|
+
|
|
78
|
+
const { class: className = '', ...rest } = props;
|
|
79
|
+
|
|
80
|
+
return tags.div({
|
|
81
|
+
tabindex: '0',
|
|
82
|
+
role: 'button',
|
|
83
|
+
class: `btn m-1 ${className}`.trim(),
|
|
84
|
+
...rest
|
|
85
|
+
}, ...children);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Dropdown Content - the menu that appears
|
|
90
|
+
*/
|
|
91
|
+
Dropdown.Content = (props = {}, ...children) => {
|
|
92
|
+
const { tags } = window.Lightview || {};
|
|
93
|
+
if (!tags) return null;
|
|
94
|
+
|
|
95
|
+
const { class: className = '', ...rest } = props;
|
|
96
|
+
|
|
97
|
+
return tags.ul({
|
|
98
|
+
tabindex: '0',
|
|
99
|
+
class: `dropdown-content menu bg-base-100 rounded-box z-1 w-52 p-2 shadow-sm ${className}`.trim(),
|
|
100
|
+
...rest
|
|
101
|
+
}, ...children);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Dropdown Item
|
|
106
|
+
*/
|
|
107
|
+
Dropdown.Item = (props = {}, ...children) => {
|
|
108
|
+
const { tags } = window.Lightview || {};
|
|
109
|
+
if (!tags) return null;
|
|
110
|
+
|
|
111
|
+
return tags.li(props, tags.a({}, ...children));
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const tags = window.Lightview.tags;
|
|
115
|
+
tags.Dropdown = Dropdown;
|
|
116
|
+
tags['Dropdown.Trigger'] = Dropdown.Trigger;
|
|
117
|
+
tags['Dropdown.Content'] = Dropdown.Content;
|
|
118
|
+
tags['Dropdown.Item'] = Dropdown.Item;
|
|
119
|
+
|
|
120
|
+
export default Dropdown;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightview Modal Component (DaisyUI)
|
|
3
|
+
* @see https://daisyui.com/components/modal/
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import '../daisyui.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Modal Component using the dialog element
|
|
10
|
+
* @param {Object} props
|
|
11
|
+
* @param {string} props.id - Required unique ID for the modal
|
|
12
|
+
* @param {boolean|function} props.open - Control open state reactively
|
|
13
|
+
* @param {string} props.position - 'top' | 'bottom' | 'middle' (default)
|
|
14
|
+
* @param {function} props.onClose - Callback when modal closes
|
|
15
|
+
* @param {boolean} props.useShadow - Render in Shadow DOM with isolated DaisyUI styles
|
|
16
|
+
*/
|
|
17
|
+
const Modal = (props = {}, ...children) => {
|
|
18
|
+
const { tags } = window.Lightview || {};
|
|
19
|
+
const LVX = window.LightviewX || {};
|
|
20
|
+
|
|
21
|
+
if (!tags) return null;
|
|
22
|
+
|
|
23
|
+
const { dialog, div, shadowDOM } = tags;
|
|
24
|
+
|
|
25
|
+
const {
|
|
26
|
+
id,
|
|
27
|
+
open = false,
|
|
28
|
+
position,
|
|
29
|
+
onClose,
|
|
30
|
+
useShadow = false,
|
|
31
|
+
class: className = '',
|
|
32
|
+
...rest
|
|
33
|
+
} = props;
|
|
34
|
+
|
|
35
|
+
const classes = ['modal'];
|
|
36
|
+
if (position === 'top') classes.push('modal-top');
|
|
37
|
+
else if (position === 'bottom') classes.push('modal-bottom');
|
|
38
|
+
else if (position === 'middle') classes.push('modal-middle');
|
|
39
|
+
if (className) classes.push(className);
|
|
40
|
+
|
|
41
|
+
const modalEl = dialog({
|
|
42
|
+
id,
|
|
43
|
+
class: classes.join(' '),
|
|
44
|
+
...rest
|
|
45
|
+
}, ...children);
|
|
46
|
+
|
|
47
|
+
// Handle reactive open state
|
|
48
|
+
if (typeof open === 'function') {
|
|
49
|
+
const checkOpen = () => {
|
|
50
|
+
if (open()) {
|
|
51
|
+
modalEl.domEl?.showModal?.();
|
|
52
|
+
} else {
|
|
53
|
+
modalEl.domEl?.close?.();
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
// Set up effect after element is in DOM
|
|
57
|
+
setTimeout(checkOpen, 0);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Check if we should use shadow DOM
|
|
61
|
+
let usesShadow = false;
|
|
62
|
+
if (LVX.shouldUseShadow) {
|
|
63
|
+
usesShadow = LVX.shouldUseShadow(useShadow);
|
|
64
|
+
} else {
|
|
65
|
+
usesShadow = useShadow === true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (usesShadow) {
|
|
69
|
+
const adoptedStyleSheets = LVX.getAdoptedStyleSheets ? LVX.getAdoptedStyleSheets() : [];
|
|
70
|
+
|
|
71
|
+
const themeValue = LVX.themeSignal ? () => LVX.themeSignal.value : 'light';
|
|
72
|
+
|
|
73
|
+
return div({ class: 'contents' },
|
|
74
|
+
shadowDOM({ mode: 'open', adoptedStyleSheets },
|
|
75
|
+
div({ 'data-theme': themeValue },
|
|
76
|
+
modalEl
|
|
77
|
+
)
|
|
78
|
+
)
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return modalEl;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Modal Box - the content container
|
|
87
|
+
*/
|
|
88
|
+
Modal.Box = (props = {}, ...children) => {
|
|
89
|
+
const { tags } = window.Lightview || {};
|
|
90
|
+
if (!tags) return null;
|
|
91
|
+
|
|
92
|
+
const { class: className = '', ...rest } = props;
|
|
93
|
+
|
|
94
|
+
return tags.div({
|
|
95
|
+
class: `modal-box ${className}`.trim(),
|
|
96
|
+
...rest
|
|
97
|
+
}, ...children);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Modal Action - container for action buttons
|
|
102
|
+
*/
|
|
103
|
+
Modal.Action = (props = {}, ...children) => {
|
|
104
|
+
const { tags } = window.Lightview || {};
|
|
105
|
+
if (!tags) return null;
|
|
106
|
+
|
|
107
|
+
const { class: className = '', ...rest } = props;
|
|
108
|
+
|
|
109
|
+
return tags.div({
|
|
110
|
+
class: `modal-action ${className}`.trim(),
|
|
111
|
+
...rest
|
|
112
|
+
}, ...children);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Modal Backdrop - click to close
|
|
117
|
+
*/
|
|
118
|
+
Modal.Backdrop = (props = {}) => {
|
|
119
|
+
const { tags } = window.Lightview || {};
|
|
120
|
+
if (!tags) return null;
|
|
121
|
+
|
|
122
|
+
return tags.form({ method: 'dialog', class: 'modal-backdrop' },
|
|
123
|
+
tags.button({}, 'close')
|
|
124
|
+
);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Open a modal by ID
|
|
129
|
+
*/
|
|
130
|
+
Modal.open = (id) => {
|
|
131
|
+
document.getElementById(id)?.showModal?.();
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Close a modal by ID
|
|
136
|
+
*/
|
|
137
|
+
Modal.close = (id) => {
|
|
138
|
+
document.getElementById(id)?.close?.();
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
window.Lightview.tags.Modal = Modal;
|
|
142
|
+
window.Lightview.tags['Modal.Box'] = Modal.Box;
|
|
143
|
+
window.Lightview.tags['Modal.Action'] = Modal.Action;
|
|
144
|
+
window.Lightview.tags['Modal.Backdrop'] = Modal.Backdrop;
|
|
145
|
+
|
|
146
|
+
export default Modal;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightview Swap Component (DaisyUI)
|
|
3
|
+
* @see https://daisyui.com/components/swap/
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import '../daisyui.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Swap Component - toggle between two elements
|
|
10
|
+
* @param {Object} props
|
|
11
|
+
* @param {boolean|function} props.active - Control swap state
|
|
12
|
+
* @param {string} props.effect - 'rotate' | 'flip'
|
|
13
|
+
* @param {boolean} props.useShadow - Render in Shadow DOM with isolated DaisyUI styles
|
|
14
|
+
*/
|
|
15
|
+
const Swap = (props = {}, ...children) => {
|
|
16
|
+
const { tags, signal } = window.Lightview || {};
|
|
17
|
+
const LVX = window.LightviewX || {};
|
|
18
|
+
|
|
19
|
+
if (!tags) return null;
|
|
20
|
+
|
|
21
|
+
const { label, input, div, shadowDOM } = tags;
|
|
22
|
+
|
|
23
|
+
const {
|
|
24
|
+
active = false,
|
|
25
|
+
effect,
|
|
26
|
+
useShadow,
|
|
27
|
+
class: className = '',
|
|
28
|
+
onChange,
|
|
29
|
+
...rest
|
|
30
|
+
} = props;
|
|
31
|
+
|
|
32
|
+
const classes = ['swap'];
|
|
33
|
+
if (effect === 'rotate') classes.push('swap-rotate');
|
|
34
|
+
else if (effect === 'flip') classes.push('swap-flip');
|
|
35
|
+
if (className) classes.push(className);
|
|
36
|
+
|
|
37
|
+
// Handle reactive active state
|
|
38
|
+
const isActive = typeof active === 'function' ? active : () => active;
|
|
39
|
+
|
|
40
|
+
const swapEl = label({
|
|
41
|
+
class: () => {
|
|
42
|
+
const base = [...classes];
|
|
43
|
+
if (isActive()) base.push('swap-active');
|
|
44
|
+
return base.join(' ');
|
|
45
|
+
},
|
|
46
|
+
...rest
|
|
47
|
+
},
|
|
48
|
+
input({
|
|
49
|
+
type: 'checkbox',
|
|
50
|
+
checked: isActive,
|
|
51
|
+
onchange: (e) => {
|
|
52
|
+
if (onChange) onChange(e.target.checked);
|
|
53
|
+
}
|
|
54
|
+
}),
|
|
55
|
+
...children
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
// Check if we should use shadow DOM
|
|
59
|
+
let usesShadow = false;
|
|
60
|
+
if (LVX.shouldUseShadow) {
|
|
61
|
+
usesShadow = LVX.shouldUseShadow(useShadow);
|
|
62
|
+
} else {
|
|
63
|
+
usesShadow = useShadow === true;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (usesShadow) {
|
|
67
|
+
const adoptedStyleSheets = LVX.getAdoptedStyleSheets ? LVX.getAdoptedStyleSheets() : [];
|
|
68
|
+
|
|
69
|
+
const themeValue = LVX.themeSignal ? () => LVX.themeSignal.value : 'light';
|
|
70
|
+
|
|
71
|
+
return div({ class: 'contents' },
|
|
72
|
+
shadowDOM({ mode: 'open', adoptedStyleSheets },
|
|
73
|
+
div({ 'data-theme': themeValue },
|
|
74
|
+
swapEl
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return swapEl;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Swap On - visible when active
|
|
85
|
+
*/
|
|
86
|
+
Swap.On = (props = {}, ...children) => {
|
|
87
|
+
const { tags } = window.Lightview || {};
|
|
88
|
+
if (!tags) return null;
|
|
89
|
+
|
|
90
|
+
const { class: className = '', ...rest } = props;
|
|
91
|
+
|
|
92
|
+
return tags.div({
|
|
93
|
+
class: `swap-on ${className}`.trim(),
|
|
94
|
+
...rest
|
|
95
|
+
}, ...children);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Swap Off - visible when inactive
|
|
100
|
+
*/
|
|
101
|
+
Swap.Off = (props = {}, ...children) => {
|
|
102
|
+
const { tags } = window.Lightview || {};
|
|
103
|
+
if (!tags) return null;
|
|
104
|
+
|
|
105
|
+
const { class: className = '', ...rest } = props;
|
|
106
|
+
|
|
107
|
+
return tags.div({
|
|
108
|
+
class: `swap-off ${className}`.trim(),
|
|
109
|
+
...rest
|
|
110
|
+
}, ...children);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const tags = window.Lightview.tags;
|
|
114
|
+
tags.Swap = Swap;
|
|
115
|
+
tags['Swap.On'] = Swap.On;
|
|
116
|
+
tags['Swap.Off'] = Swap.Off;
|
|
117
|
+
|
|
118
|
+
export default Swap;
|