hzl-web 2.2.0 → 2.4.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.
Binary file
Binary file
@@ -6,6 +6,18 @@
6
6
  "start_url": "/",
7
7
  "scope": "/",
8
8
  "icons": [
9
+ {
10
+ "src": "/web-app-manifest-192x192.png",
11
+ "sizes": "192x192",
12
+ "type": "image/png",
13
+ "purpose": "any"
14
+ },
15
+ {
16
+ "src": "/web-app-manifest-512x512.png",
17
+ "sizes": "512x512",
18
+ "type": "image/png",
19
+ "purpose": "any"
20
+ },
9
21
  {
10
22
  "src": "/web-app-manifest-192x192.png",
11
23
  "sizes": "192x192",
@@ -19,6 +31,21 @@
19
31
  "purpose": "maskable"
20
32
  }
21
33
  ],
34
+ "screenshots": [
35
+ {
36
+ "src": "/screenshot-wide.png",
37
+ "sizes": "1280x720",
38
+ "type": "image/png",
39
+ "form_factor": "wide",
40
+ "label": "HZL task dashboard - desktop view"
41
+ },
42
+ {
43
+ "src": "/screenshot-mobile.png",
44
+ "sizes": "390x844",
45
+ "type": "image/png",
46
+ "label": "HZL task dashboard - mobile view"
47
+ }
48
+ ],
22
49
  "theme_color": "#1a1a1a",
23
50
  "background_color": "#1a1a1a",
24
51
  "display": "standalone"
@@ -1,9 +1,9 @@
1
- export declare const DASHBOARD_HTML: string;
2
- export declare const DASHBOARD_SITE_MANIFEST: string;
3
- export declare const DASHBOARD_SERVICE_WORKER: string;
4
- export declare const DASHBOARD_FAVICON_PNG_96: Buffer<ArrayBufferLike>;
5
- export declare const DASHBOARD_FAVICON_ICO: Buffer<ArrayBufferLike>;
6
- export declare const DASHBOARD_APPLE_TOUCH_ICON: Buffer<ArrayBufferLike>;
7
- export declare const DASHBOARD_WEB_APP_ICON_192: Buffer<ArrayBufferLike>;
8
- export declare const DASHBOARD_WEB_APP_ICON_512: Buffer<ArrayBufferLike>;
1
+ export interface EmbeddedFile {
2
+ content: Buffer;
3
+ contentType: string;
4
+ }
5
+ /** All files from dist/ui/ keyed by URL path (e.g. "/index.html", "/assets/main-abc.js") */
6
+ export declare const UI_FILES: Map<string, EmbeddedFile>;
7
+ /** Legacy dashboard HTML for the HZL_LEGACY_DASHBOARD=1 feature toggle */
8
+ export declare const LEGACY_DASHBOARD_HTML: string;
9
9
  //# sourceMappingURL=ui-embed.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ui-embed.d.ts","sourceRoot":"","sources":["../src/ui-embed.ts"],"names":[],"mappings":"AAmCA,eAAO,MAAM,cAAc,QAA2B,CAAC;AACvD,eAAO,MAAM,uBAAuB,QAAiC,CAAC;AACtE,eAAO,MAAM,wBAAwB,QAAsB,CAAC;AAC5D,eAAO,MAAM,wBAAwB,yBAAoC,CAAC;AAC1E,eAAO,MAAM,qBAAqB,yBAA8B,CAAC;AACjE,eAAO,MAAM,0BAA0B,yBAAuC,CAAC;AAC/E,eAAO,MAAM,0BAA0B,yBAA+C,CAAC;AACvF,eAAO,MAAM,0BAA0B,yBAA+C,CAAC"}
1
+ {"version":3,"file":"ui-embed.d.ts","sourceRoot":"","sources":["../src/ui-embed.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAqED,4FAA4F;AAC5F,eAAO,MAAM,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAwB,CAAC;AAExE,0EAA0E;AAC1E,eAAO,MAAM,qBAAqB,EAAE,MAWhC,CAAC"}
package/dist/ui-embed.js CHANGED
@@ -1,38 +1,80 @@
1
- import { accessSync, readFileSync } from 'fs';
1
+ import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
2
2
  import { fileURLToPath } from 'url';
3
- import { dirname, join } from 'path';
3
+ import { dirname, join, extname } from 'path';
4
4
  const __filename = fileURLToPath(import.meta.url);
5
5
  const __dirname = dirname(__filename);
6
- // In development, read from source. In production, this will be the dist folder.
7
- // For dev, we try the src folder first, then fall back to the build location.
8
- function resolveUiPath(relativePath) {
9
- const paths = [
10
- join(__dirname, 'ui', relativePath), // dist/ui/* (prod)
11
- join(__dirname, '..', 'src', 'ui', relativePath), // src/ui/* (dev from dist)
6
+ const MIME_TYPES = {
7
+ '.html': 'text/html; charset=utf-8',
8
+ '.css': 'text/css; charset=utf-8',
9
+ '.js': 'application/javascript; charset=utf-8',
10
+ '.json': 'application/json; charset=utf-8',
11
+ '.webmanifest': 'application/manifest+json; charset=utf-8',
12
+ '.png': 'image/png',
13
+ '.ico': 'image/x-icon',
14
+ '.svg': 'image/svg+xml',
15
+ '.woff': 'font/woff',
16
+ '.woff2': 'font/woff2',
17
+ '.txt': 'text/plain; charset=utf-8',
18
+ };
19
+ function getMimeType(filePath) {
20
+ return MIME_TYPES[extname(filePath).toLowerCase()] ?? 'application/octet-stream';
21
+ }
22
+ /**
23
+ * Resolve the ui directory path.
24
+ * Prefers dist/ui/ (contains Vite-built React app + copied legacy.html).
25
+ * Falls back to src/ui/ when dist hasn't been built yet.
26
+ */
27
+ function resolveUiDir() {
28
+ // When running from compiled JS (dist/), __dirname is dist/ so 'ui' = dist/ui/
29
+ // When running from source (src/) via vitest, __dirname is src/ so we look up to dist/ui/
30
+ const candidates = [
31
+ join(__dirname, 'ui'), // dist/ui/ when running from dist/
32
+ join(__dirname, '..', 'dist', 'ui'), // dist/ui/ when running from src/ (vitest)
33
+ join(__dirname, '..', 'src', 'ui'), // src/ui/ fallback (dev without build)
12
34
  ];
13
- for (const p of paths) {
14
- try {
15
- accessSync(p);
16
- return p;
35
+ for (const dir of candidates) {
36
+ if (existsSync(dir))
37
+ return dir;
38
+ }
39
+ throw new Error(`Could not find ui directory - checked: ${candidates.join(', ')}`);
40
+ }
41
+ /**
42
+ * Recursively load all files from a directory into a Map keyed by URL path.
43
+ * e.g. dist/ui/index.html -> "/index.html", dist/ui/assets/main-abc.js -> "/assets/main-abc.js"
44
+ */
45
+ function loadDirectory(dir, prefix = '') {
46
+ const files = new Map();
47
+ for (const entry of readdirSync(dir)) {
48
+ const fullPath = join(dir, entry);
49
+ const urlPath = prefix + '/' + entry;
50
+ if (statSync(fullPath).isDirectory()) {
51
+ for (const [k, v] of loadDirectory(fullPath, urlPath)) {
52
+ files.set(k, v);
53
+ }
17
54
  }
18
- catch {
19
- // Try next path
55
+ else {
56
+ files.set(urlPath, {
57
+ content: readFileSync(fullPath),
58
+ contentType: getMimeType(fullPath),
59
+ });
20
60
  }
21
61
  }
22
- throw new Error(`Could not find ${relativePath} - checked: ${paths.join(', ')}`);
23
- }
24
- function loadUiText(relativePath) {
25
- return readFileSync(resolveUiPath(relativePath), 'utf-8');
62
+ return files;
26
63
  }
27
- function loadUiBinary(relativePath) {
28
- return readFileSync(resolveUiPath(relativePath));
29
- }
30
- export const DASHBOARD_HTML = loadUiText('index.html');
31
- export const DASHBOARD_SITE_MANIFEST = loadUiText('site.webmanifest');
32
- export const DASHBOARD_SERVICE_WORKER = loadUiText('sw.js');
33
- export const DASHBOARD_FAVICON_PNG_96 = loadUiBinary('favicon-96x96.png');
34
- export const DASHBOARD_FAVICON_ICO = loadUiBinary('favicon.ico');
35
- export const DASHBOARD_APPLE_TOUCH_ICON = loadUiBinary('apple-touch-icon.png');
36
- export const DASHBOARD_WEB_APP_ICON_192 = loadUiBinary('web-app-manifest-192x192.png');
37
- export const DASHBOARD_WEB_APP_ICON_512 = loadUiBinary('web-app-manifest-512x512.png');
64
+ const uiDir = resolveUiDir();
65
+ /** All files from dist/ui/ keyed by URL path (e.g. "/index.html", "/assets/main-abc.js") */
66
+ export const UI_FILES = loadDirectory(uiDir);
67
+ /** Legacy dashboard HTML for the HZL_LEGACY_DASHBOARD=1 feature toggle */
68
+ export const LEGACY_DASHBOARD_HTML = (() => {
69
+ const legacyPath = join(uiDir, 'legacy.html');
70
+ if (existsSync(legacyPath)) {
71
+ return readFileSync(legacyPath, 'utf-8');
72
+ }
73
+ // Fallback: try src/ui/legacy.html when running from dist
74
+ const srcLegacy = join(__dirname, '..', 'src', 'ui', 'legacy.html');
75
+ if (existsSync(srcLegacy)) {
76
+ return readFileSync(srcLegacy, 'utf-8');
77
+ }
78
+ return '<html><body>Legacy dashboard not found.</body></html>';
79
+ })();
38
80
  //# sourceMappingURL=ui-embed.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ui-embed.js","sourceRoot":"","sources":["../src/ui-embed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAErC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,iFAAiF;AACjF,8EAA8E;AAC9E,SAAS,aAAa,CAAC,YAAoB;IACzC,MAAM,KAAK,GAAG;QACZ,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,YAAY,CAAC,EAAE,mBAAmB;QACxD,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,CAAC,EAAE,2BAA2B;KAC9E,CAAC;IAEF,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC;YACH,UAAU,CAAC,CAAC,CAAC,CAAC;YACd,OAAO,CAAC,CAAC;QACX,CAAC;QAAC,MAAM,CAAC;YACP,gBAAgB;QAClB,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,kBAAkB,YAAY,eAAe,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACnF,CAAC;AAED,SAAS,UAAU,CAAC,YAAoB;IACtC,OAAO,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,YAAY,CAAC,YAAoB;IACxC,OAAO,YAAY,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;AACvD,MAAM,CAAC,MAAM,uBAAuB,GAAG,UAAU,CAAC,kBAAkB,CAAC,CAAC;AACtE,MAAM,CAAC,MAAM,wBAAwB,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;AAC5D,MAAM,CAAC,MAAM,wBAAwB,GAAG,YAAY,CAAC,mBAAmB,CAAC,CAAC;AAC1E,MAAM,CAAC,MAAM,qBAAqB,GAAG,YAAY,CAAC,aAAa,CAAC,CAAC;AACjE,MAAM,CAAC,MAAM,0BAA0B,GAAG,YAAY,CAAC,sBAAsB,CAAC,CAAC;AAC/E,MAAM,CAAC,MAAM,0BAA0B,GAAG,YAAY,CAAC,8BAA8B,CAAC,CAAC;AACvF,MAAM,CAAC,MAAM,0BAA0B,GAAG,YAAY,CAAC,8BAA8B,CAAC,CAAC"}
1
+ {"version":3,"file":"ui-embed.js","sourceRoot":"","sources":["../src/ui-embed.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hzl-web",
3
- "version": "2.2.0",
3
+ "version": "2.4.0",
4
4
  "description": "Web dashboard for HZL - A Kanban-style task monitoring UI.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -52,16 +52,29 @@
52
52
  "visualization"
53
53
  ],
54
54
  "dependencies": {
55
- "hzl-core": "2.2.0"
55
+ "d3": "^7.9.0",
56
+ "dompurify": "^3.3.1",
57
+ "force-graph": "^1.51.1",
58
+ "marked": "^17.0.3",
59
+ "react": "^19.1.0",
60
+ "react-dom": "^19.1.0",
61
+ "hzl-core": "2.4.0"
56
62
  },
57
63
  "devDependencies": {
64
+ "@types/d3": "^7.4.3",
65
+ "@types/dompurify": "^3.2.0",
58
66
  "@types/node": "^25.2.1",
67
+ "@types/react": "^19.1.0",
68
+ "@types/react-dom": "^19.1.0",
69
+ "@vitejs/plugin-react": "^4.5.2",
59
70
  "libsql": "^0.5.0",
60
71
  "typescript": "^5.3.0",
72
+ "vite": "^6.3.5",
61
73
  "vitest": "^4.0.18"
62
74
  },
63
75
  "scripts": {
64
- "build": "tsc -b && cp -r src/ui dist/",
76
+ "build": "vite build && tsc -b && cp src/ui/legacy.html dist/ui/legacy.html",
77
+ "dev": "vite",
65
78
  "test": "vitest run",
66
79
  "test:ci": "vitest run --coverage",
67
80
  "test:watch": "vitest"