@vpxa/aikit 0.1.266 → 0.1.268
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/package.json
CHANGED
|
@@ -657,23 +657,6 @@
|
|
|
657
657
|
line-height: 1.6;
|
|
658
658
|
}
|
|
659
659
|
|
|
660
|
-
.task-plan__export-error {
|
|
661
|
-
position: fixed;
|
|
662
|
-
left: 50%;
|
|
663
|
-
bottom: 24px;
|
|
664
|
-
z-index: 20;
|
|
665
|
-
transform: translateX(-50%);
|
|
666
|
-
max-width: min(92vw, 560px);
|
|
667
|
-
padding: 12px 16px;
|
|
668
|
-
border: 1px solid var(--viewer-toast-border);
|
|
669
|
-
border-radius: var(--radius-pill);
|
|
670
|
-
background: var(--viewer-toast-bg);
|
|
671
|
-
color: var(--viewer-text);
|
|
672
|
-
font-size: 13px;
|
|
673
|
-
line-height: 1.4;
|
|
674
|
-
box-shadow: 0 18px 32px rgba(15, 23, 42, 0.22);
|
|
675
|
-
}
|
|
676
|
-
|
|
677
660
|
.viewer-badge {
|
|
678
661
|
position: fixed;
|
|
679
662
|
right: 16px;
|
|
@@ -794,8 +777,6 @@
|
|
|
794
777
|
</div>
|
|
795
778
|
<div class="viewer-actions" role="toolbar" aria-label="Task plan viewer actions">
|
|
796
779
|
<button id="theme-button" type="button">Theme: Auto</button>
|
|
797
|
-
<button id="export-png-button" type="button">Export PNG</button>
|
|
798
|
-
<button id="export-svg-button" type="button">Export SVG</button>
|
|
799
780
|
</div>
|
|
800
781
|
</header>
|
|
801
782
|
|
|
@@ -818,7 +799,6 @@
|
|
|
818
799
|
</div>
|
|
819
800
|
|
|
820
801
|
<div class="viewer-badge"><span class="viewer-badge__mark"></span>AI Kit static viewer</div>
|
|
821
|
-
<div class="task-plan__export-error" id="export-error" role="status" aria-live="polite" hidden></div>
|
|
822
802
|
|
|
823
803
|
<script type="application/json" id="diagram-data">{}</script>
|
|
824
804
|
<script>
|
|
@@ -830,13 +810,10 @@
|
|
|
830
810
|
const summaryEl = document.getElementById('summary');
|
|
831
811
|
const legendEl = document.getElementById('legend');
|
|
832
812
|
const emptyStateEl = document.getElementById('empty-state');
|
|
833
|
-
const exportErrorEl = document.getElementById('export-error');
|
|
834
813
|
const surfaceEl = document.getElementById('pipeline-surface');
|
|
835
814
|
const viewerTitleEl = document.getElementById('viewer-title');
|
|
836
815
|
const viewerDescriptionEl = document.getElementById('viewer-description');
|
|
837
816
|
const themeButton = document.getElementById('theme-button');
|
|
838
|
-
const exportPngButton = document.getElementById('export-png-button');
|
|
839
|
-
const exportSvgButton = document.getElementById('export-svg-button');
|
|
840
817
|
const styleTag = document.getElementById('viewer-style');
|
|
841
818
|
|
|
842
819
|
const themes = ['auto', 'dark', 'light'];
|
|
@@ -1092,28 +1069,6 @@
|
|
|
1092
1069
|
updateThemeButton();
|
|
1093
1070
|
}
|
|
1094
1071
|
|
|
1095
|
-
let exportErrorTimer = null;
|
|
1096
|
-
|
|
1097
|
-
function showExportError(message) {
|
|
1098
|
-
exportErrorEl.textContent = message;
|
|
1099
|
-
exportErrorEl.hidden = false;
|
|
1100
|
-
if (exportErrorTimer) {
|
|
1101
|
-
window.clearTimeout(exportErrorTimer);
|
|
1102
|
-
}
|
|
1103
|
-
exportErrorTimer = window.setTimeout(() => {
|
|
1104
|
-
exportErrorEl.hidden = true;
|
|
1105
|
-
}, 4500);
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
function clearExportError() {
|
|
1109
|
-
exportErrorEl.hidden = true;
|
|
1110
|
-
exportErrorEl.textContent = '';
|
|
1111
|
-
if (exportErrorTimer) {
|
|
1112
|
-
window.clearTimeout(exportErrorTimer);
|
|
1113
|
-
exportErrorTimer = null;
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
|
|
1117
1072
|
function showEmpty(title, message) {
|
|
1118
1073
|
clearElement(pipelineEl);
|
|
1119
1074
|
clearElement(summaryEl);
|
|
@@ -1307,112 +1262,12 @@
|
|
|
1307
1262
|
document.title = 'AI Kit - ' + title;
|
|
1308
1263
|
}
|
|
1309
1264
|
|
|
1310
|
-
function buildExportSvgMarkup() {
|
|
1311
|
-
const resolvedTheme = getResolvedTheme();
|
|
1312
|
-
const exportClone = surfaceEl.cloneNode(true);
|
|
1313
|
-
const padding = 24;
|
|
1314
|
-
const contentWidth = Math.ceil(surfaceEl.scrollWidth);
|
|
1315
|
-
const contentHeight = Math.ceil(surfaceEl.scrollHeight);
|
|
1316
|
-
const width = contentWidth + padding * 2;
|
|
1317
|
-
const height = contentHeight + padding * 2;
|
|
1318
|
-
|
|
1319
|
-
exportClone.removeAttribute('id');
|
|
1320
|
-
exportClone.style.width = contentWidth + 'px';
|
|
1321
|
-
exportClone.style.minHeight = '0';
|
|
1322
|
-
exportClone.style.boxShadow = 'none';
|
|
1323
|
-
|
|
1324
|
-
let stylesheet = styleTag && styleTag.textContent ? styleTag.textContent : '';
|
|
1325
|
-
stylesheet = stylesheet.replace(/:root\b/g, '.tp-export-root');
|
|
1326
|
-
stylesheet = stylesheet.replace(/\]\]>/g, ']]>');
|
|
1327
|
-
stylesheet += '\n.tp-export-root{width:' + contentWidth + 'px;padding:' + padding + 'px;background:transparent;font-family:var(--font-sans);color:var(--viewer-text);}\n';
|
|
1328
|
-
stylesheet += '.tp-export-root .task-plan__surface{min-height:0;box-shadow:none;}\n';
|
|
1329
|
-
|
|
1330
|
-
const serializedSurface = exportClone.outerHTML;
|
|
1331
|
-
const svg = [
|
|
1332
|
-
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
1333
|
-
'<svg xmlns="http://www.w3.org/2000/svg" width="' + width + '" height="' + height + '" viewBox="0 0 ' + width + ' ' + height + '">',
|
|
1334
|
-
'<foreignObject width="100%" height="100%">',
|
|
1335
|
-
'<div xmlns="http://www.w3.org/1999/xhtml" class="tp-export-root" data-theme="' + resolvedTheme + '">',
|
|
1336
|
-
'<style><![CDATA[' + stylesheet + ']]></style>',
|
|
1337
|
-
serializedSurface,
|
|
1338
|
-
'</div>',
|
|
1339
|
-
'</foreignObject>',
|
|
1340
|
-
'</svg>'
|
|
1341
|
-
].join('');
|
|
1342
|
-
|
|
1343
|
-
return { markup: svg, width, height };
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
|
-
function downloadBlob(blob, filename) {
|
|
1347
|
-
const url = URL.createObjectURL(blob);
|
|
1348
|
-
const anchor = document.createElement('a');
|
|
1349
|
-
anchor.href = url;
|
|
1350
|
-
anchor.download = filename;
|
|
1351
|
-
document.body.appendChild(anchor);
|
|
1352
|
-
anchor.click();
|
|
1353
|
-
anchor.remove();
|
|
1354
|
-
window.setTimeout(() => URL.revokeObjectURL(url), 1000);
|
|
1355
|
-
}
|
|
1356
|
-
|
|
1357
|
-
async function exportSvg() {
|
|
1358
|
-
clearExportError();
|
|
1359
|
-
try {
|
|
1360
|
-
const exported = buildExportSvgMarkup();
|
|
1361
|
-
const blob = new Blob([exported.markup], { type: 'image/svg+xml;charset=utf-8' });
|
|
1362
|
-
downloadBlob(blob, 'task-plan.svg');
|
|
1363
|
-
} catch (error) {
|
|
1364
|
-
showExportError(error instanceof Error ? error.message : 'SVG export failed.');
|
|
1365
|
-
}
|
|
1366
|
-
}
|
|
1367
|
-
|
|
1368
|
-
async function exportPng() {
|
|
1369
|
-
clearExportError();
|
|
1370
|
-
try {
|
|
1371
|
-
const exported = buildExportSvgMarkup();
|
|
1372
|
-
const blob = new Blob([exported.markup], { type: 'image/svg+xml;charset=utf-8' });
|
|
1373
|
-
const url = URL.createObjectURL(blob);
|
|
1374
|
-
const image = new Image();
|
|
1375
|
-
const scale = Math.max(window.devicePixelRatio || 1, 2);
|
|
1376
|
-
|
|
1377
|
-
await new Promise((resolve, reject) => {
|
|
1378
|
-
image.onload = resolve;
|
|
1379
|
-
image.onerror = () => reject(new Error('PNG export is unavailable in this browser. Use SVG export instead.'));
|
|
1380
|
-
image.src = url;
|
|
1381
|
-
});
|
|
1382
|
-
|
|
1383
|
-
const canvas = document.createElement('canvas');
|
|
1384
|
-
canvas.width = Math.ceil(exported.width * scale);
|
|
1385
|
-
canvas.height = Math.ceil(exported.height * scale);
|
|
1386
|
-
|
|
1387
|
-
const context = canvas.getContext('2d');
|
|
1388
|
-
if (!context) {
|
|
1389
|
-
URL.revokeObjectURL(url);
|
|
1390
|
-
throw new Error('Canvas export is unavailable in this browser.');
|
|
1391
|
-
}
|
|
1392
|
-
|
|
1393
|
-
context.scale(scale, scale);
|
|
1394
|
-
context.drawImage(image, 0, 0, exported.width, exported.height);
|
|
1395
|
-
|
|
1396
|
-
const pngBlob = await new Promise((resolve) => canvas.toBlob(resolve, 'image/png'));
|
|
1397
|
-
URL.revokeObjectURL(url);
|
|
1398
|
-
|
|
1399
|
-
if (!pngBlob) {
|
|
1400
|
-
throw new Error('PNG export failed.');
|
|
1401
|
-
}
|
|
1402
|
-
|
|
1403
|
-
downloadBlob(pngBlob, 'task-plan.png');
|
|
1404
|
-
} catch (error) {
|
|
1405
|
-
showExportError(error instanceof Error ? error.message : 'PNG export failed.');
|
|
1406
|
-
}
|
|
1407
|
-
}
|
|
1408
|
-
|
|
1409
1265
|
function render() {
|
|
1410
1266
|
const plan = readData();
|
|
1411
1267
|
if (!plan) {
|
|
1412
1268
|
return;
|
|
1413
1269
|
}
|
|
1414
1270
|
|
|
1415
|
-
clearExportError();
|
|
1416
1271
|
updateHeader(plan);
|
|
1417
1272
|
|
|
1418
1273
|
const tasks = getTasks(plan);
|
|
@@ -1428,20 +1283,6 @@
|
|
|
1428
1283
|
}
|
|
1429
1284
|
|
|
1430
1285
|
themeButton.addEventListener('click', cycleTheme);
|
|
1431
|
-
exportSvgButton.addEventListener('click', () => {
|
|
1432
|
-
void exportSvg();
|
|
1433
|
-
});
|
|
1434
|
-
exportPngButton.addEventListener('click', () => {
|
|
1435
|
-
void exportPng();
|
|
1436
|
-
});
|
|
1437
|
-
|
|
1438
|
-
if (colorSchemeQuery && typeof colorSchemeQuery.addEventListener === 'function') {
|
|
1439
|
-
colorSchemeQuery.addEventListener('change', () => {
|
|
1440
|
-
if (getThemeMode() === 'auto') {
|
|
1441
|
-
clearExportError();
|
|
1442
|
-
}
|
|
1443
|
-
});
|
|
1444
|
-
}
|
|
1445
1286
|
|
|
1446
1287
|
updateThemeButton();
|
|
1447
1288
|
render();
|