lightview 2.0.9 → 2.2.1
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/build-bundles.mjs +105 -0
- package/build.js +236 -46
- package/components/actions/button.js +16 -3
- package/components/actions/swap.js +26 -3
- package/components/daisyui.js +1 -1
- package/components/data-display/alert.js +13 -3
- package/components/data-display/avatar.js +25 -1
- package/components/data-display/badge.js +11 -3
- package/components/data-display/chart.js +22 -5
- package/components/data-display/countdown.js +3 -2
- package/components/data-display/kbd.js +9 -3
- package/components/data-display/loading.js +11 -3
- package/components/data-display/progress.js +11 -3
- package/components/data-display/radial-progress.js +12 -3
- package/components/data-display/tooltip.js +17 -0
- package/components/data-input/checkbox.js +23 -1
- package/components/data-input/input.js +24 -1
- package/components/data-input/radio.js +37 -2
- package/components/data-input/select.js +24 -1
- package/components/data-input/toggle.js +21 -1
- package/components/layout/divider.js +21 -1
- package/components/layout/indicator.js +14 -0
- package/components/navigation/breadcrumbs.js +42 -2
- package/components/navigation/tabs.js +291 -16
- package/docs/api/elements.html +125 -49
- package/docs/api/hypermedia.html +29 -2
- package/docs/api/index.html +6 -2
- package/docs/api/nav.html +18 -4
- package/docs/assets/js/examplify.js +1 -1
- package/docs/cdom-nav.html +55 -0
- package/docs/cdom.html +792 -0
- package/docs/components/alert.html +8 -8
- package/docs/components/avatar.html +24 -54
- package/docs/components/badge.html +69 -14
- package/docs/components/breadcrumbs.html +95 -29
- package/docs/components/button.html +78 -92
- package/docs/components/chart-area.html +3 -3
- package/docs/components/chart-bar.html +4 -181
- package/docs/components/chart-column.html +4 -189
- package/docs/components/chart-line.html +3 -3
- package/docs/components/chart-pie.html +112 -166
- package/docs/components/chart.html +11 -13
- package/docs/components/checkbox.html +48 -28
- package/docs/components/collapse.html +6 -6
- package/docs/components/component-nav.html +1 -1
- package/docs/components/countdown.html +12 -12
- package/docs/components/divider.html +65 -21
- package/docs/components/dropdown.html +1 -1
- package/docs/components/file-input.html +4 -4
- package/docs/components/footer.html +11 -11
- package/docs/components/indicator.html +85 -31
- package/docs/components/input.html +45 -29
- package/docs/components/join.html +4 -4
- package/docs/components/kbd.html +67 -28
- package/docs/components/loading.html +96 -92
- package/docs/components/pagination.html +4 -4
- package/docs/components/progress.html +50 -7
- package/docs/components/radial-progress.html +32 -12
- package/docs/components/radio.html +42 -31
- package/docs/components/select.html +48 -59
- package/docs/components/swap.html +183 -100
- package/docs/components/tabs.html +146 -278
- package/docs/components/toggle.html +44 -25
- package/docs/components/tooltip.html +71 -31
- package/docs/getting-started/index.html +8 -6
- package/docs/index.html +1 -1
- package/docs/syntax-nav.html +10 -0
- package/docs/syntax.html +8 -6
- package/index.html +2 -2
- package/jprx/LICENSE +21 -0
- package/jprx/README.md +130 -0
- package/jprx/helpers/array.js +75 -0
- package/jprx/helpers/compare.js +26 -0
- package/jprx/helpers/conditional.js +34 -0
- package/jprx/helpers/datetime.js +54 -0
- package/jprx/helpers/format.js +20 -0
- package/jprx/helpers/logic.js +24 -0
- package/jprx/helpers/lookup.js +25 -0
- package/jprx/helpers/math.js +34 -0
- package/jprx/helpers/network.js +41 -0
- package/jprx/helpers/state.js +80 -0
- package/jprx/helpers/stats.js +39 -0
- package/jprx/helpers/string.js +49 -0
- package/jprx/index.js +69 -0
- package/jprx/package.json +24 -0
- package/jprx/parser.js +1517 -0
- package/lightview-all.js +3785 -0
- package/lightview-cdom.js +2128 -0
- package/lightview-router.js +179 -208
- package/lightview-x.js +1435 -1608
- package/lightview.js +613 -766
- package/lightview.js.bak +1 -0
- package/package.json +10 -3
- package/src/lightview-all.js +10 -0
- package/src/lightview-cdom.js +457 -0
- package/src/lightview-router.js +210 -0
- package/src/lightview-x.js +1630 -0
- package/src/lightview.js +705 -0
- package/src/reactivity/signal.js +133 -0
- package/src/reactivity/state.js +217 -0
- package/{watch.js → start-dev.js} +2 -1
- package/tests/cdom/fixtures/helpers.cdomc +62 -0
- package/tests/cdom/fixtures/user.cdom +14 -0
- package/tests/cdom/fixtures/user.cdomc +12 -0
- package/tests/cdom/fixtures/user.odom +18 -0
- package/tests/cdom/fixtures/user.vdom +11 -0
- package/tests/cdom/helpers.test.js +121 -0
- package/tests/cdom/loader.test.js +125 -0
- package/tests/cdom/parser.test.js +179 -0
- package/tests/cdom/reactivity.test.js +186 -0
- package/tests/text-tag.test.js +77 -0
- package/vite.config.mjs +52 -0
- package/wrangler.toml +0 -3
- package/components/data-display/skeleton.js +0 -66
- package/docs/components/skeleton.html +0 -447
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { build } from 'vite';
|
|
2
|
+
import { resolve } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { copyFileSync, rmSync, existsSync } from 'fs';
|
|
5
|
+
|
|
6
|
+
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
7
|
+
const isWatch = process.argv.includes('--watch');
|
|
8
|
+
|
|
9
|
+
const builds = [
|
|
10
|
+
{ entry: 'src/lightview.js', name: 'lightview', globalName: 'Lightview' },
|
|
11
|
+
{ entry: 'src/lightview-x.js', name: 'lightview-x', globalName: 'LightviewX' },
|
|
12
|
+
{ entry: 'src/lightview-cdom.js', name: 'lightview-cdom', globalName: 'LightviewCDOM' },
|
|
13
|
+
{ entry: 'src/lightview-router.js', name: 'lightview-router', globalName: 'LightviewRouter' },
|
|
14
|
+
{ entry: 'src/lightview-all.js', name: 'lightview-all', globalName: 'LightviewAll' }
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
let building = false;
|
|
18
|
+
let queued = false;
|
|
19
|
+
|
|
20
|
+
async function runBuilds() {
|
|
21
|
+
if (building) {
|
|
22
|
+
queued = true;
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
building = true;
|
|
26
|
+
|
|
27
|
+
console.log(isWatch ? 'Change detected. Rebuilding bundled files...' : 'Building bundles...');
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
for (const b of builds) {
|
|
31
|
+
// console.log(`Building ${b.name}...`);
|
|
32
|
+
await build({
|
|
33
|
+
configFile: false,
|
|
34
|
+
logLevel: 'silent', // Reduce noise
|
|
35
|
+
build: {
|
|
36
|
+
lib: {
|
|
37
|
+
entry: resolve(__dirname, b.entry),
|
|
38
|
+
name: b.globalName,
|
|
39
|
+
formats: ['iife'],
|
|
40
|
+
fileName: () => `${b.name}.js`
|
|
41
|
+
},
|
|
42
|
+
outDir: 'build_tmp',
|
|
43
|
+
// Don't clean here, clean manually
|
|
44
|
+
emptyOutDir: false,
|
|
45
|
+
rollupOptions: {
|
|
46
|
+
external: (id) => id.includes('/components/') || id.includes('/docs/')
|
|
47
|
+
},
|
|
48
|
+
minify: false // No minification for easier debugging
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Copy files
|
|
54
|
+
for (const b of builds) {
|
|
55
|
+
try {
|
|
56
|
+
const src = resolve(__dirname, `build_tmp/${b.name}.js`);
|
|
57
|
+
const dest = resolve(__dirname, `${b.name}.js`);
|
|
58
|
+
if (existsSync(src)) {
|
|
59
|
+
copyFileSync(src, dest);
|
|
60
|
+
console.log(`Updated ${b.name}.js`);
|
|
61
|
+
} else {
|
|
62
|
+
console.error(`Missing built file: ${src}`);
|
|
63
|
+
}
|
|
64
|
+
} catch (e) {
|
|
65
|
+
console.error(`Failed to copy ${b.name}.js`, e);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Cleanup
|
|
70
|
+
if (existsSync(resolve(__dirname, 'build_tmp'))) {
|
|
71
|
+
rmSync(resolve(__dirname, 'build_tmp'), { recursive: true, force: true });
|
|
72
|
+
}
|
|
73
|
+
} catch (e) {
|
|
74
|
+
console.error('Build error:', e);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
building = false;
|
|
78
|
+
if (queued) {
|
|
79
|
+
queued = false;
|
|
80
|
+
runBuilds();
|
|
81
|
+
} else {
|
|
82
|
+
if (isWatch) console.log('Waiting for changes...');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Initial run
|
|
87
|
+
runBuilds();
|
|
88
|
+
|
|
89
|
+
if (isWatch) {
|
|
90
|
+
console.log('Watching src/ for changes...');
|
|
91
|
+
// Dynamic import to avoid errors if run in environment without fs (unlikely here but good practice)
|
|
92
|
+
const { watch } = await import('fs');
|
|
93
|
+
let debounceTimer;
|
|
94
|
+
|
|
95
|
+
// Watch src directory
|
|
96
|
+
// Note: recursive option for Linux requires Node 20+, Windows/macOS supported earlier.
|
|
97
|
+
watch(resolve(__dirname, 'src'), { recursive: true }, (event, filename) => {
|
|
98
|
+
if (filename && !filename.includes('~')) {
|
|
99
|
+
clearTimeout(debounceTimer);
|
|
100
|
+
debounceTimer = setTimeout(() => {
|
|
101
|
+
runBuilds();
|
|
102
|
+
}, 300); // 300ms debounce
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
package/build.js
CHANGED
|
@@ -1,70 +1,260 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const { minify } = require('terser');
|
|
4
|
+
|
|
5
|
+
// Parse command line arguments
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
const envArg = args.find(arg => arg.startsWith('--env='));
|
|
8
|
+
const env = envArg ? envArg.split('=')[1] : 'prod';
|
|
9
|
+
|
|
10
|
+
// Validate env
|
|
11
|
+
const validEnvs = ['prod', 'test', 'dev'];
|
|
12
|
+
if (!validEnvs.includes(env)) {
|
|
13
|
+
console.error(`Invalid env "${env}". Allowed values: ${validEnvs.join(', ')}`);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const shouldMinify = env === 'prod';
|
|
3
18
|
|
|
4
19
|
const rootDir = __dirname;
|
|
5
20
|
const distDir = path.join(rootDir, 'dist');
|
|
6
21
|
const docsDir = path.join(rootDir, 'docs');
|
|
7
22
|
const componentsDir = path.join(rootDir, 'components');
|
|
8
23
|
const middlewareDir = path.join(rootDir, 'middleware');
|
|
24
|
+
const jprxDir = path.join(rootDir, 'jprx');
|
|
9
25
|
|
|
10
26
|
// Configuration
|
|
11
27
|
// Files in root that should be copied
|
|
12
28
|
const allowedExtensions = ['.html', '.js', '.css', '.txt', '.xml', '.ico', '.png', '.svg', '.jpg', '.jpeg', '.md'];
|
|
13
29
|
const includeFiles = ['_headers']; // specific files to always include
|
|
14
|
-
const excludeFiles = ['build.js', 'package.json', 'package-lock.json', 'wrangler.toml'];
|
|
30
|
+
const excludeFiles = ['build.js', 'build-bundles.mjs', 'package.json', 'package-lock.json', 'wrangler.toml'];
|
|
15
31
|
|
|
16
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Minify a JavaScript file using terser
|
|
34
|
+
* @param {string} code - The JavaScript source code
|
|
35
|
+
* @returns {Promise<string>} - The minified code
|
|
36
|
+
*/
|
|
37
|
+
async function minifyJS(code) {
|
|
38
|
+
if (!shouldMinify) {
|
|
39
|
+
return code; // Skip minification in dev mode
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const result = await minify(code, {
|
|
43
|
+
module: true, // Handle ES6 module syntax
|
|
44
|
+
compress: {
|
|
45
|
+
drop_console: false
|
|
46
|
+
},
|
|
47
|
+
mangle: {
|
|
48
|
+
reserved: ['examplify', 'examplifyIdCounter'] // Preserve global function names called from HTML
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return result.code;
|
|
52
|
+
} catch (e) {
|
|
53
|
+
console.error('Minification error:', e);
|
|
54
|
+
return code; // Return original on error
|
|
55
|
+
}
|
|
56
|
+
}
|
|
17
57
|
|
|
18
|
-
|
|
19
|
-
if (
|
|
20
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Copy a file, minifying if it's a JS file (and minification is enabled)
|
|
60
|
+
* @param {string} srcPath - Source file path
|
|
61
|
+
* @param {string} destPath - Destination file path
|
|
62
|
+
*/
|
|
63
|
+
async function copyFile(srcPath, destPath) {
|
|
64
|
+
const ext = path.extname(srcPath).toLowerCase();
|
|
65
|
+
|
|
66
|
+
if (ext === '.js' && shouldMinify) {
|
|
67
|
+
// Read, minify, and write JS files
|
|
68
|
+
const code = fs.readFileSync(srcPath, 'utf8');
|
|
69
|
+
const minified = await minifyJS(code);
|
|
70
|
+
fs.writeFileSync(destPath, minified);
|
|
71
|
+
} else {
|
|
72
|
+
// Copy other files directly
|
|
73
|
+
fs.copyFileSync(srcPath, destPath);
|
|
74
|
+
}
|
|
21
75
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Recursively copy a directory, minifying JS files if enabled
|
|
79
|
+
* @param {string} srcDir - Source directory
|
|
80
|
+
* @param {string} destDir - Destination directory
|
|
81
|
+
*/
|
|
82
|
+
async function copyDirWithMinify(srcDir, destDir) {
|
|
83
|
+
if (!fs.existsSync(destDir)) {
|
|
84
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
43
85
|
}
|
|
44
|
-
});
|
|
45
86
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
87
|
+
const entries = fs.readdirSync(srcDir, { withFileTypes: true });
|
|
88
|
+
|
|
89
|
+
for (const entry of entries) {
|
|
90
|
+
const srcPath = path.join(srcDir, entry.name);
|
|
91
|
+
const destPath = path.join(destDir, entry.name);
|
|
92
|
+
|
|
93
|
+
if (entry.isDirectory()) {
|
|
94
|
+
await copyDirWithMinify(srcPath, destPath);
|
|
95
|
+
} else {
|
|
96
|
+
await copyFile(srcPath, destPath);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
52
99
|
}
|
|
53
100
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
101
|
+
async function build() {
|
|
102
|
+
console.log(`Building for deployment (env: ${env}, minify: ${shouldMinify})...`);
|
|
103
|
+
|
|
104
|
+
// 1. Clean/Create dist - continue even if deletion fails (e.g., file locks on Windows)
|
|
105
|
+
if (fs.existsSync(distDir)) {
|
|
106
|
+
try {
|
|
107
|
+
fs.rmSync(distDir, { recursive: true, force: true });
|
|
108
|
+
console.log('Cleaned dist directory.');
|
|
109
|
+
} catch (e) {
|
|
110
|
+
console.warn('Warning: Could not delete dist directory (files may be locked). Overwriting files instead.');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (!fs.existsSync(distDir)) {
|
|
115
|
+
fs.mkdirSync(distDir);
|
|
116
|
+
console.log('Created dist directory.');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// 2. Copy Root Files (with minification for JS if enabled)
|
|
120
|
+
const files = fs.readdirSync(rootDir);
|
|
121
|
+
for (const file of files) {
|
|
122
|
+
const srcPath = path.join(rootDir, file);
|
|
123
|
+
const stat = fs.statSync(srcPath);
|
|
124
|
+
|
|
125
|
+
if (stat.isFile()) {
|
|
126
|
+
const ext = path.extname(file).toLowerCase();
|
|
127
|
+
|
|
128
|
+
// Check if file should be copied
|
|
129
|
+
const isAllowedExt = allowedExtensions.includes(ext);
|
|
130
|
+
const isExplicitInclude = includeFiles.includes(file);
|
|
131
|
+
const isExcluded = excludeFiles.includes(file) || file.startsWith('.');
|
|
132
|
+
|
|
133
|
+
if ((isAllowedExt || isExplicitInclude) && !isExcluded) {
|
|
134
|
+
await copyFile(srcPath, path.join(distDir, file));
|
|
135
|
+
const suffix = ext === '.js' && shouldMinify ? ' (minified)' : '';
|
|
136
|
+
console.log(`Copied: ${file}${suffix}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 3. Copy Docs Directory
|
|
142
|
+
if (fs.existsSync(docsDir)) {
|
|
143
|
+
await copyDirWithMinify(docsDir, path.join(distDir, 'docs'));
|
|
144
|
+
console.log(`Copied: docs directory${shouldMinify ? ' (JS files minified)' : ''}`);
|
|
145
|
+
} else {
|
|
146
|
+
console.warn('Warning: docs directory not found.');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 4. Copy Components Directory
|
|
150
|
+
if (fs.existsSync(componentsDir)) {
|
|
151
|
+
await copyDirWithMinify(componentsDir, path.join(distDir, 'components'));
|
|
152
|
+
console.log(`Copied: components directory${shouldMinify ? ' (JS files minified)' : ''}`);
|
|
153
|
+
} else {
|
|
154
|
+
console.warn('Warning: components directory not found.');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// 5. Copy Middleware Directory
|
|
158
|
+
if (fs.existsSync(middlewareDir)) {
|
|
159
|
+
await copyDirWithMinify(middlewareDir, path.join(distDir, 'middleware'));
|
|
160
|
+
console.log(`Copied: middleware directory${shouldMinify ? ' (JS files minified)' : ''}`);
|
|
161
|
+
} else {
|
|
162
|
+
console.warn('Warning: middleware directory not found.');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
// 7. Copy JPRX Directory
|
|
168
|
+
if (fs.existsSync(jprxDir)) {
|
|
169
|
+
await copyDirWithMinify(jprxDir, path.join(distDir, 'jprx'));
|
|
170
|
+
console.log(`Copied: jprx directory${shouldMinify ? ' (JS files minified)' : ''}`);
|
|
171
|
+
} else {
|
|
172
|
+
console.warn('Warning: jprx directory not found.');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
console.log('Build complete! Assets are ready in ./dist');
|
|
60
176
|
}
|
|
61
177
|
|
|
62
|
-
//
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
178
|
+
// Check for --watch flag
|
|
179
|
+
const isWatch = args.includes('--watch');
|
|
180
|
+
|
|
181
|
+
if (isWatch) {
|
|
182
|
+
// Watch mode
|
|
183
|
+
const { watch } = require('fs');
|
|
184
|
+
const { execSync } = require('child_process');
|
|
185
|
+
let debounceTimer;
|
|
186
|
+
let building = false;
|
|
187
|
+
let queued = false;
|
|
188
|
+
let needsBundleRebuild = false;
|
|
189
|
+
|
|
190
|
+
const runBuildBundles = () => {
|
|
191
|
+
console.log('Rebuilding bundles...');
|
|
192
|
+
try {
|
|
193
|
+
execSync('node build-bundles.mjs', { cwd: rootDir, stdio: 'inherit' });
|
|
194
|
+
console.log('Bundles rebuilt successfully.');
|
|
195
|
+
} catch (e) {
|
|
196
|
+
console.error('Bundle rebuild failed:', e.message);
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const runBuild = async () => {
|
|
201
|
+
if (building) {
|
|
202
|
+
queued = true;
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
building = true;
|
|
206
|
+
try {
|
|
207
|
+
if (needsBundleRebuild) {
|
|
208
|
+
runBuildBundles();
|
|
209
|
+
needsBundleRebuild = false;
|
|
210
|
+
}
|
|
211
|
+
await build();
|
|
212
|
+
} catch (e) {
|
|
213
|
+
console.error('Build failed:', e);
|
|
214
|
+
}
|
|
215
|
+
building = false;
|
|
216
|
+
if (queued) {
|
|
217
|
+
queued = false;
|
|
218
|
+
runBuild();
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const watchDir = (dir, name, triggersBundleRebuild = false) => {
|
|
223
|
+
if (fs.existsSync(dir)) {
|
|
224
|
+
watch(dir, { recursive: true }, (event, filename) => {
|
|
225
|
+
if (filename && !filename.includes('~') && !filename.includes('.git')) {
|
|
226
|
+
clearTimeout(debounceTimer);
|
|
227
|
+
if (triggersBundleRebuild) {
|
|
228
|
+
needsBundleRebuild = true;
|
|
229
|
+
}
|
|
230
|
+
debounceTimer = setTimeout(() => {
|
|
231
|
+
console.log(`\nChange detected in ${name}: ${filename}`);
|
|
232
|
+
runBuild();
|
|
233
|
+
}, 300);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
console.log(`Watching: ${name}${triggersBundleRebuild ? ' (triggers bundle rebuild)' : ''}`);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
console.log('Starting watch mode...\n');
|
|
241
|
+
|
|
242
|
+
// Initial build (bundles already built by npm script)
|
|
243
|
+
runBuild().then(() => {
|
|
244
|
+
// Watch all relevant directories
|
|
245
|
+
// src/ and jprx/ trigger bundle rebuilds
|
|
246
|
+
watchDir(path.join(rootDir, 'src'), 'src/', true);
|
|
247
|
+
watchDir(jprxDir, 'jprx/', true);
|
|
248
|
+
// Other directories just get copied
|
|
249
|
+
watchDir(docsDir, 'docs/');
|
|
250
|
+
watchDir(componentsDir, 'components/');
|
|
251
|
+
watchDir(middlewareDir, 'middleware/');
|
|
252
|
+
console.log('\nWaiting for changes...');
|
|
253
|
+
});
|
|
66
254
|
} else {
|
|
67
|
-
|
|
255
|
+
// Single build
|
|
256
|
+
build().catch(e => {
|
|
257
|
+
console.error('Build failed:', e);
|
|
258
|
+
process.exit(1);
|
|
259
|
+
});
|
|
68
260
|
}
|
|
69
|
-
|
|
70
|
-
console.log('Build complete! Assets are ready in ./dist');
|
|
@@ -139,9 +139,22 @@ const Button = (props = {}, ...children) => {
|
|
|
139
139
|
|
|
140
140
|
globalThis.Lightview.tags.Button = Button;
|
|
141
141
|
|
|
142
|
-
// Register as Custom Element
|
|
143
|
-
if (globalThis.LightviewX
|
|
144
|
-
const ButtonElement = globalThis.LightviewX.
|
|
142
|
+
// Register as Custom Element using customElementWrapper
|
|
143
|
+
if (globalThis.LightviewX && typeof customElements !== 'undefined') {
|
|
144
|
+
const ButtonElement = globalThis.LightviewX.customElementWrapper(Button, {
|
|
145
|
+
attributeMap: {
|
|
146
|
+
color: String,
|
|
147
|
+
size: String,
|
|
148
|
+
variant: String,
|
|
149
|
+
disabled: Boolean,
|
|
150
|
+
loading: Boolean,
|
|
151
|
+
active: Boolean,
|
|
152
|
+
glass: Boolean,
|
|
153
|
+
noAnimation: Boolean
|
|
154
|
+
},
|
|
155
|
+
childElements: {} // No child components for Button, uses slot
|
|
156
|
+
});
|
|
157
|
+
|
|
145
158
|
if (!customElements.get('lv-button')) {
|
|
146
159
|
customElements.define('lv-button', ButtonElement);
|
|
147
160
|
}
|
|
@@ -34,8 +34,9 @@ const Swap = (props = {}, ...children) => {
|
|
|
34
34
|
else if (effect === 'flip') classes.push('swap-flip');
|
|
35
35
|
if (className) classes.push(className);
|
|
36
36
|
|
|
37
|
-
// Handle reactive
|
|
38
|
-
const
|
|
37
|
+
// Handle internal state for non-reactive/uncontrolled usage
|
|
38
|
+
const internalActive = signal(active);
|
|
39
|
+
const isActive = typeof active === 'function' ? active : () => internalActive.value;
|
|
39
40
|
|
|
40
41
|
const swapEl = label({
|
|
41
42
|
class: () => {
|
|
@@ -49,7 +50,11 @@ const Swap = (props = {}, ...children) => {
|
|
|
49
50
|
type: 'checkbox',
|
|
50
51
|
checked: isActive,
|
|
51
52
|
onchange: (e) => {
|
|
52
|
-
|
|
53
|
+
const checked = e.target.checked;
|
|
54
|
+
if (typeof active !== 'function') {
|
|
55
|
+
internalActive.value = checked;
|
|
56
|
+
}
|
|
57
|
+
if (onChange) onChange(checked);
|
|
53
58
|
}
|
|
54
59
|
}),
|
|
55
60
|
...children
|
|
@@ -115,4 +120,22 @@ tags.Swap = Swap;
|
|
|
115
120
|
tags['Swap.On'] = Swap.On;
|
|
116
121
|
tags['Swap.Off'] = Swap.Off;
|
|
117
122
|
|
|
123
|
+
// Register as Custom Element using customElementWrapper
|
|
124
|
+
if (globalThis.LightviewX && typeof customElements !== 'undefined') {
|
|
125
|
+
const SwapElement = globalThis.LightviewX.customElementWrapper(Swap, {
|
|
126
|
+
attributeMap: {
|
|
127
|
+
active: Boolean,
|
|
128
|
+
effect: String
|
|
129
|
+
},
|
|
130
|
+
childElements: {
|
|
131
|
+
'on': Swap.On,
|
|
132
|
+
'off': Swap.Off
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
if (!customElements.get('lv-swap')) {
|
|
137
|
+
customElements.define('lv-swap', SwapElement);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
118
141
|
export default Swap;
|
package/components/daisyui.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* This module ensures DaisyUI CSS is loaded and provides utilities for components
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const DAISYUI_CDN = 'https://cdn.jsdelivr.net/npm/daisyui@
|
|
6
|
+
const DAISYUI_CDN = 'https://cdn.jsdelivr.net/npm/daisyui@5.5.14/daisyui.min.css';
|
|
7
7
|
const TAILWIND_CDN = 'https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4';
|
|
8
8
|
|
|
9
9
|
let daisyLoaded = false;
|
|
@@ -101,9 +101,19 @@ function getAlertIcon(type) {
|
|
|
101
101
|
|
|
102
102
|
globalThis.Lightview.tags.Alert = Alert;
|
|
103
103
|
|
|
104
|
-
// Register as Custom Element
|
|
105
|
-
if (globalThis.LightviewX
|
|
106
|
-
const AlertElement = globalThis.LightviewX.
|
|
104
|
+
// Register as Custom Element using customElementWrapper
|
|
105
|
+
if (globalThis.LightviewX && typeof customElements !== 'undefined') {
|
|
106
|
+
const AlertElement = globalThis.LightviewX.customElementWrapper(Alert, {
|
|
107
|
+
attributeMap: {
|
|
108
|
+
color: String,
|
|
109
|
+
soft: Boolean,
|
|
110
|
+
dash: Boolean,
|
|
111
|
+
outline: Boolean,
|
|
112
|
+
icon: String
|
|
113
|
+
},
|
|
114
|
+
childElements: {} // No child components for Alert
|
|
115
|
+
});
|
|
116
|
+
|
|
107
117
|
if (!customElements.get('lv-alert')) {
|
|
108
118
|
customElements.define('lv-alert', AlertElement);
|
|
109
119
|
}
|
|
@@ -158,7 +158,31 @@ tags.Avatar = Avatar;
|
|
|
158
158
|
tags['Avatar.Group'] = Avatar.Group;
|
|
159
159
|
|
|
160
160
|
// Register as Custom Elements
|
|
161
|
-
if (globalThis.LightviewX?.
|
|
161
|
+
if (globalThis.LightviewX?.customElementWrapper) {
|
|
162
|
+
if (!customElements.get('lv-avatar')) {
|
|
163
|
+
customElements.define('lv-avatar', globalThis.LightviewX.customElementWrapper(Avatar, {
|
|
164
|
+
attributeMap: {
|
|
165
|
+
src: String,
|
|
166
|
+
alt: String,
|
|
167
|
+
placeholder: String,
|
|
168
|
+
size: String,
|
|
169
|
+
shape: String,
|
|
170
|
+
ring: Boolean,
|
|
171
|
+
ringColor: String,
|
|
172
|
+
online: Boolean,
|
|
173
|
+
offline: Boolean,
|
|
174
|
+
class: String
|
|
175
|
+
}
|
|
176
|
+
}));
|
|
177
|
+
}
|
|
178
|
+
if (!customElements.get('lv-avatar-group')) {
|
|
179
|
+
customElements.define('lv-avatar-group', globalThis.LightviewX.customElementWrapper(Avatar.Group, {
|
|
180
|
+
attributeMap: {
|
|
181
|
+
class: String
|
|
182
|
+
}
|
|
183
|
+
}));
|
|
184
|
+
}
|
|
185
|
+
} else if (globalThis.LightviewX?.createCustomElement) {
|
|
162
186
|
if (!customElements.get('lv-avatar')) {
|
|
163
187
|
customElements.define('lv-avatar', globalThis.LightviewX.createCustomElement(Avatar));
|
|
164
188
|
}
|
|
@@ -71,9 +71,17 @@ const Badge = (props = {}, ...children) => {
|
|
|
71
71
|
|
|
72
72
|
globalThis.Lightview.tags.Badge = Badge;
|
|
73
73
|
|
|
74
|
-
// Register as Custom Element
|
|
75
|
-
if (globalThis.LightviewX
|
|
76
|
-
const BadgeElement = globalThis.LightviewX.
|
|
74
|
+
// Register as Custom Element using customElementWrapper
|
|
75
|
+
if (globalThis.LightviewX && typeof customElements !== 'undefined') {
|
|
76
|
+
const BadgeElement = globalThis.LightviewX.customElementWrapper(Badge, {
|
|
77
|
+
attributeMap: {
|
|
78
|
+
color: String,
|
|
79
|
+
size: String,
|
|
80
|
+
variant: String
|
|
81
|
+
},
|
|
82
|
+
childElements: {} // No child components for Badge, uses slot
|
|
83
|
+
});
|
|
84
|
+
|
|
77
85
|
if (!customElements.get('lv-badge')) {
|
|
78
86
|
customElements.define('lv-badge', BadgeElement);
|
|
79
87
|
}
|
|
@@ -24,9 +24,22 @@ import '../daisyui.js';
|
|
|
24
24
|
*/
|
|
25
25
|
const CHARTS_CSS_URL = 'https://cdn.jsdelivr.net/npm/charts.css/dist/charts.min.css';
|
|
26
26
|
|
|
27
|
+
// Register stylesheet for Shadow DOM usage (Adopted StyleSheets)
|
|
28
|
+
// Using top-level await in module to ensure it's loaded before any component renders
|
|
29
|
+
if (globalThis.LightviewX?.registerStyleSheet) {
|
|
30
|
+
await LightviewX.registerStyleSheet(CHARTS_CSS_URL);
|
|
31
|
+
}
|
|
32
|
+
|
|
27
33
|
// Auto-load charts.css for Global/Light DOM usage
|
|
28
34
|
if (typeof document !== 'undefined') {
|
|
29
|
-
if (!document.querySelector(`link[href^="
|
|
35
|
+
if (!document.querySelector(`link[href^="${CHARTS_CSS_URL}"]`)) {
|
|
36
|
+
// Preload for better performance
|
|
37
|
+
const preload = document.createElement('link');
|
|
38
|
+
preload.rel = 'preload';
|
|
39
|
+
preload.as = 'style';
|
|
40
|
+
preload.href = CHARTS_CSS_URL;
|
|
41
|
+
document.head.appendChild(preload);
|
|
42
|
+
|
|
30
43
|
const link = document.createElement('link');
|
|
31
44
|
link.rel = 'stylesheet';
|
|
32
45
|
link.href = CHARTS_CSS_URL;
|
|
@@ -48,8 +61,8 @@ const Chart = (props = {}, ...children) => {
|
|
|
48
61
|
labels = false,
|
|
49
62
|
dataOnHover = false,
|
|
50
63
|
primaryAxis = false,
|
|
64
|
+
secondaryAxesCount,
|
|
51
65
|
secondaryAxis = false,
|
|
52
|
-
spacing,
|
|
53
66
|
reverse = false,
|
|
54
67
|
multiple = false,
|
|
55
68
|
stacked = false,
|
|
@@ -65,10 +78,14 @@ const Chart = (props = {}, ...children) => {
|
|
|
65
78
|
if (heading) classes.push('show-heading');
|
|
66
79
|
if (primaryAxis) classes.push('show-primary-axis');
|
|
67
80
|
|
|
68
|
-
if (
|
|
69
|
-
|
|
81
|
+
if (secondaryAxesCount) {
|
|
82
|
+
classes.push(`show-${secondaryAxesCount}-secondary-axes`);
|
|
83
|
+
} else if (secondaryAxis === true) {
|
|
84
|
+
classes.push('show-10-secondary-axes');
|
|
85
|
+
} else if (typeof secondaryAxis === 'string') {
|
|
86
|
+
classes.push(secondaryAxis);
|
|
87
|
+
}
|
|
70
88
|
|
|
71
|
-
if (spacing) classes.push(`data-spacing-${spacing}`);
|
|
72
89
|
if (reverse) classes.push('reverse');
|
|
73
90
|
if (multiple) classes.push('multiple');
|
|
74
91
|
if (stacked) classes.push('stacked');
|
|
@@ -30,12 +30,13 @@ const Countdown = (props = {}, ...children) => {
|
|
|
30
30
|
|
|
31
31
|
const countdownEl = span({
|
|
32
32
|
class: `countdown ${className}`.trim(),
|
|
33
|
+
style: 'line-height: 1.2em; height: 1.2em; vertical-align: middle;',
|
|
33
34
|
...rest
|
|
34
35
|
},
|
|
35
36
|
span({
|
|
36
37
|
style: typeof value === 'function'
|
|
37
|
-
? () => `--value:${getValue()};`
|
|
38
|
-
: `--value:${value};`
|
|
38
|
+
? () => `--value:${getValue()}; height: 1.2em;`
|
|
39
|
+
: `--value:${value}; height: 1.2em;`
|
|
39
40
|
})
|
|
40
41
|
);
|
|
41
42
|
|
|
@@ -54,9 +54,15 @@ const Kbd = (props = {}, ...children) => {
|
|
|
54
54
|
|
|
55
55
|
globalThis.Lightview.tags.Kbd = Kbd;
|
|
56
56
|
|
|
57
|
-
// Register as Custom Element
|
|
58
|
-
if (globalThis.LightviewX
|
|
59
|
-
const KbdElement = globalThis.LightviewX.
|
|
57
|
+
// Register as Custom Element using customElementWrapper
|
|
58
|
+
if (globalThis.LightviewX && typeof customElements !== 'undefined') {
|
|
59
|
+
const KbdElement = globalThis.LightviewX.customElementWrapper(Kbd, {
|
|
60
|
+
attributeMap: {
|
|
61
|
+
size: String
|
|
62
|
+
},
|
|
63
|
+
childElements: {} // No child components, uses slot for key text
|
|
64
|
+
});
|
|
65
|
+
|
|
60
66
|
if (!customElements.get('lv-kbd')) {
|
|
61
67
|
customElements.define('lv-kbd', KbdElement);
|
|
62
68
|
}
|