foundry-design-web-adapter 0.2.0-beta.1 → 0.2.0-beta.2
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/README.md +9 -3
- package/THIRD_PARTY_NOTICES.md +4 -18
- package/dist/adapter.js +1059 -812
- package/dist/index.d.ts.map +1 -1
- package/dist/keyline-icons.d.ts +9 -0
- package/dist/keyline-icons.d.ts.map +1 -0
- package/dist/review.d.ts +2 -0
- package/dist/review.d.ts.map +1 -1
- package/dist/workspace.d.ts +50 -0
- package/dist/workspace.d.ts.map +1 -0
- package/package.json +2 -2
package/dist/adapter.js
CHANGED
|
@@ -81,6 +81,16 @@ function reviewSelection(draft, changeId, defaultSelected) {
|
|
|
81
81
|
function reviewAfterValue(draft, changeId, fallback) {
|
|
82
82
|
return draft.afterValues[changeId] ?? String(fallback);
|
|
83
83
|
}
|
|
84
|
+
function humanizeProperty(property) {
|
|
85
|
+
return property.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[-_]+/g, " ").toLowerCase().replace(/^./, (character) => character.toUpperCase());
|
|
86
|
+
}
|
|
87
|
+
function reviewSummary(selectedCount, selectableCount, elementCount, unresolvedCount = 0) {
|
|
88
|
+
if (!selectableCount && !unresolvedCount) return "No design changes are waiting for review.";
|
|
89
|
+
const changes = `${selectedCount} ${selectedCount === 1 ? "change" : "changes"}`;
|
|
90
|
+
const elements = `${elementCount} ${elementCount === 1 ? "element" : "elements"}`;
|
|
91
|
+
const unresolved = unresolvedCount ? ` \xB7 ${unresolvedCount} ${unresolvedCount === 1 ? "change needs" : "changes need"} mapping` : "";
|
|
92
|
+
return `${changes} ready across ${elements}${unresolved}`;
|
|
93
|
+
}
|
|
84
94
|
|
|
85
95
|
// src/canvas.ts
|
|
86
96
|
function layerSelectionScore(signals) {
|
|
@@ -482,499 +492,412 @@ function baselineForContext(memory, targetId, breakpoint, theme, state) {
|
|
|
482
492
|
);
|
|
483
493
|
}
|
|
484
494
|
|
|
485
|
-
// ../../node_modules/.pnpm
|
|
486
|
-
var
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
viewBox: "0 0 24 24",
|
|
491
|
-
fill: "none",
|
|
492
|
-
stroke: "currentColor",
|
|
493
|
-
"stroke-width": 2,
|
|
494
|
-
"stroke-linecap": "round",
|
|
495
|
-
"stroke-linejoin": "round"
|
|
495
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/u/user-check.js
|
|
496
|
+
var data = {
|
|
497
|
+
"width": 24,
|
|
498
|
+
"height": 24,
|
|
499
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7L18 9.25L22 4.75M8 14H10C13.3137 14 16 16.6863 16 20C16 20.5523 15.5523 21 15 21H3C2.44772 21 2 20.5523 2 20C2 16.6863 4.68629 14 8 14ZM9 4C10.6569 4 12 5.34315 12 7C12 8.65685 10.6569 10 9 10C7.34315 10 6 8.65685 6 7C6 5.34315 7.34315 4 9 4Z"/>'
|
|
496
500
|
};
|
|
501
|
+
var user_check_default = data;
|
|
497
502
|
|
|
498
|
-
// ../../node_modules/.pnpm
|
|
499
|
-
var
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
});
|
|
504
|
-
if (children?.length) {
|
|
505
|
-
children.forEach((child) => {
|
|
506
|
-
const childElement = createSVGElement(child);
|
|
507
|
-
element.appendChild(childElement);
|
|
508
|
-
});
|
|
509
|
-
}
|
|
510
|
-
return element;
|
|
511
|
-
};
|
|
512
|
-
var createElement = (iconNode, customAttrs = {}) => {
|
|
513
|
-
const tag = "svg";
|
|
514
|
-
const attrs = {
|
|
515
|
-
...defaultAttributes,
|
|
516
|
-
...customAttrs
|
|
517
|
-
};
|
|
518
|
-
return createSVGElement([tag, attrs, iconNode]);
|
|
503
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/a/activity.js
|
|
504
|
+
var data2 = {
|
|
505
|
+
"width": 24,
|
|
506
|
+
"height": 24,
|
|
507
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2 12H5L8 4L16 20L19 12H22"/>'
|
|
519
508
|
};
|
|
509
|
+
var activity_default = data2;
|
|
520
510
|
|
|
521
|
-
// ../../node_modules/.pnpm
|
|
522
|
-
var
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
return false;
|
|
511
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/a/align-offset-left.js
|
|
512
|
+
var data3 = {
|
|
513
|
+
"width": 24,
|
|
514
|
+
"height": 24,
|
|
515
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 2V8M12 2V20M20 10V22"/>'
|
|
529
516
|
};
|
|
517
|
+
var align_offset_left_default = data3;
|
|
530
518
|
|
|
531
|
-
// ../../node_modules/.pnpm
|
|
532
|
-
var
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
// ../../node_modules/.pnpm/lucide@1.37.0/node_modules/lucide/dist/esm/shared/src/utils/toCamelCase.mjs
|
|
537
|
-
var toCamelCase = (string) => string.replace(
|
|
538
|
-
/^([A-Z])|[\s-_]+(\w)/g,
|
|
539
|
-
(match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase()
|
|
540
|
-
);
|
|
541
|
-
|
|
542
|
-
// ../../node_modules/.pnpm/lucide@1.37.0/node_modules/lucide/dist/esm/shared/src/utils/toPascalCase.mjs
|
|
543
|
-
var toPascalCase = (string) => {
|
|
544
|
-
const camelCase = toCamelCase(string);
|
|
545
|
-
return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
|
|
519
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/a/arrow-down.js
|
|
520
|
+
var data4 = {
|
|
521
|
+
"width": 24,
|
|
522
|
+
"height": 24,
|
|
523
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12.1229L11.5875 18.8261C11.8153 19.058 12.1847 19.058 12.4125 18.8261L19 12.1229M12 5V18.0587"/>'
|
|
546
524
|
};
|
|
525
|
+
var arrow_down_default = data4;
|
|
547
526
|
|
|
548
|
-
// ../../node_modules/.pnpm
|
|
549
|
-
var
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
var getClassNames = (attrs) => {
|
|
554
|
-
if (typeof attrs === "string") return attrs;
|
|
555
|
-
if (!attrs || !attrs.class) return "";
|
|
556
|
-
if (attrs.class && typeof attrs.class === "string") {
|
|
557
|
-
return attrs.class.split(" ");
|
|
558
|
-
}
|
|
559
|
-
if (attrs.class && Array.isArray(attrs.class)) {
|
|
560
|
-
return attrs.class;
|
|
561
|
-
}
|
|
562
|
-
return "";
|
|
563
|
-
};
|
|
564
|
-
var replaceElement = (element, { nameAttr, icons, attrs }) => {
|
|
565
|
-
const iconName = element.getAttribute(nameAttr);
|
|
566
|
-
if (iconName == null) return;
|
|
567
|
-
const ComponentName = toPascalCase(iconName);
|
|
568
|
-
const iconNode = icons[ComponentName];
|
|
569
|
-
if (!iconNode) {
|
|
570
|
-
return console.warn(
|
|
571
|
-
`${element.outerHTML} icon name was not found in the provided icons object.`
|
|
572
|
-
);
|
|
573
|
-
}
|
|
574
|
-
const elementAttrs = getAttrs(element);
|
|
575
|
-
const ariaProps = hasA11yProp(elementAttrs) ? {} : { "aria-hidden": "true" };
|
|
576
|
-
const iconAttrs = {
|
|
577
|
-
...defaultAttributes,
|
|
578
|
-
"data-lucide": iconName,
|
|
579
|
-
...ariaProps,
|
|
580
|
-
...attrs,
|
|
581
|
-
...elementAttrs
|
|
582
|
-
};
|
|
583
|
-
const elementClassNames = getClassNames(elementAttrs);
|
|
584
|
-
const className = getClassNames(attrs);
|
|
585
|
-
const classNames = mergeClasses(
|
|
586
|
-
"lucide",
|
|
587
|
-
`lucide-${iconName}`,
|
|
588
|
-
...elementClassNames,
|
|
589
|
-
...className
|
|
590
|
-
);
|
|
591
|
-
if (classNames) {
|
|
592
|
-
Object.assign(iconAttrs, {
|
|
593
|
-
class: classNames
|
|
594
|
-
});
|
|
595
|
-
}
|
|
596
|
-
const svgElement = createElement(iconNode, iconAttrs);
|
|
597
|
-
return element.parentNode?.replaceChild(svgElement, element);
|
|
527
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/a/arrow-left.js
|
|
528
|
+
var data5 = {
|
|
529
|
+
"width": 24,
|
|
530
|
+
"height": 24,
|
|
531
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 12H5.94129M11.8771 5L5.17385 11.5875C4.94205 11.8153 4.94205 12.1847 5.17385 12.4125L11.8771 19"/>'
|
|
598
532
|
};
|
|
533
|
+
var arrow_left_default = data5;
|
|
599
534
|
|
|
600
|
-
// ../../node_modules/.pnpm
|
|
601
|
-
var
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
];
|
|
608
|
-
|
|
609
|
-
// ../../node_modules/.pnpm/lucide@1.37.0/node_modules/lucide/dist/esm/icons/activity.mjs
|
|
610
|
-
var Activity = [
|
|
611
|
-
[
|
|
612
|
-
"path",
|
|
613
|
-
{
|
|
614
|
-
d: "M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2"
|
|
615
|
-
}
|
|
616
|
-
]
|
|
617
|
-
];
|
|
618
|
-
|
|
619
|
-
// ../../node_modules/.pnpm/lucide@1.37.0/node_modules/lucide/dist/esm/icons/align-horizontal-space-around.mjs
|
|
620
|
-
var AlignHorizontalSpaceAround = [
|
|
621
|
-
["rect", { width: "6", height: "10", x: "9", y: "7", rx: "2" }],
|
|
622
|
-
["path", { d: "M4 22V2" }],
|
|
623
|
-
["path", { d: "M20 22V2" }]
|
|
624
|
-
];
|
|
625
|
-
|
|
626
|
-
// ../../node_modules/.pnpm/lucide@1.37.0/node_modules/lucide/dist/esm/icons/arrow-down.mjs
|
|
627
|
-
var ArrowDown = [
|
|
628
|
-
["path", { d: "M12 5v14" }],
|
|
629
|
-
["path", { d: "m19 12-7 7-7-7" }]
|
|
630
|
-
];
|
|
535
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/a/arrow-up.js
|
|
536
|
+
var data6 = {
|
|
537
|
+
"width": 24,
|
|
538
|
+
"height": 24,
|
|
539
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 11.8771L11.5875 5.17385C11.8153 4.94205 12.1847 4.94205 12.4125 5.17385L19 11.8771M12 19V5.94129"/>'
|
|
540
|
+
};
|
|
541
|
+
var arrow_up_default = data6;
|
|
631
542
|
|
|
632
|
-
// ../../node_modules/.pnpm
|
|
633
|
-
var
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
543
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/b/bookmark.js
|
|
544
|
+
var data7 = {
|
|
545
|
+
"width": 24,
|
|
546
|
+
"height": 24,
|
|
547
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 5C4 3.3431 5.3431 2 7 2L17 2C18.6569 2 20 3.3431 20 5L20 20.9983C20 21.7895 19.1248 22.2673 18.4592 21.8395L12.8111 18.8514C12.317 18.5338 11.683 18.5338 11.1889 18.8514L5.5408 21.8395C4.8752 22.2673 4 21.7895 4 20.9983Z"/>'
|
|
548
|
+
};
|
|
549
|
+
var bookmark_default = data7;
|
|
637
550
|
|
|
638
|
-
// ../../node_modules/.pnpm
|
|
639
|
-
var
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
551
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/s/square.js
|
|
552
|
+
var data8 = {
|
|
553
|
+
"width": 24,
|
|
554
|
+
"height": 24,
|
|
555
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 3H18C19.6569 3 21 4.34315 21 6V18C21 19.6569 19.6569 21 18 21H6C4.34315 21 3 19.6569 3 18V6C3 4.34315 4.34315 3 6 3Z"/>'
|
|
556
|
+
};
|
|
557
|
+
var square_default = data8;
|
|
643
558
|
|
|
644
|
-
// ../../node_modules/.pnpm
|
|
645
|
-
var
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
]
|
|
652
|
-
];
|
|
559
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/c/check.js
|
|
560
|
+
var data9 = {
|
|
561
|
+
"width": 24,
|
|
562
|
+
"height": 24,
|
|
563
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12L9.66667 17L19 7"/>'
|
|
564
|
+
};
|
|
565
|
+
var check_default = data9;
|
|
653
566
|
|
|
654
|
-
// ../../node_modules/.pnpm
|
|
655
|
-
var
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
],
|
|
662
|
-
["path", { d: "m3.3 7 8.7 5 8.7-5" }],
|
|
663
|
-
["path", { d: "M12 22V12" }]
|
|
664
|
-
];
|
|
567
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/c/chevron-down.js
|
|
568
|
+
var data10 = {
|
|
569
|
+
"width": 24,
|
|
570
|
+
"height": 24,
|
|
571
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 9L12 15L18 9"/>'
|
|
572
|
+
};
|
|
573
|
+
var chevron_down_default = data10;
|
|
665
574
|
|
|
666
|
-
// ../../node_modules/.pnpm
|
|
667
|
-
var
|
|
575
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/c/chevron-right.js
|
|
576
|
+
var data11 = {
|
|
577
|
+
"width": 24,
|
|
578
|
+
"height": 24,
|
|
579
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 6L15 12L9 18"/>'
|
|
580
|
+
};
|
|
581
|
+
var chevron_right_default = data11;
|
|
668
582
|
|
|
669
|
-
// ../../node_modules/.pnpm
|
|
670
|
-
var
|
|
583
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/g/grid-3x2.js
|
|
584
|
+
var data12 = {
|
|
585
|
+
"width": 24,
|
|
586
|
+
"height": 24,
|
|
587
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 3H18C19.65685 3 21 4.34315 21 6V18C21 19.65685 19.65685 21 18 21H6C4.34315 21 3 19.65685 3 18V6C3 4.34315 4.34315 3 6 3ZM9 3V21M15 3V21M3 12H21"/>'
|
|
588
|
+
};
|
|
589
|
+
var grid_3x2_default = data12;
|
|
671
590
|
|
|
672
|
-
// ../../node_modules/.pnpm
|
|
673
|
-
var
|
|
591
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/s/square-terminal.js
|
|
592
|
+
var data13 = {
|
|
593
|
+
"width": 24,
|
|
594
|
+
"height": 24,
|
|
595
|
+
"body": '<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M6 3H18C19.6569 3 21 4.34315 21 6V18C21 19.6569 19.6569 21 18 21H6C4.34315 21 3 19.6569 3 18V6C3 4.34315 4.34315 3 6 3Z"/><path d="M7 7L11 11L7 15M13 17H17"/></g>'
|
|
596
|
+
};
|
|
597
|
+
var square_terminal_default = data13;
|
|
674
598
|
|
|
675
|
-
// ../../node_modules/.pnpm
|
|
676
|
-
var
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
599
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/s/shapes.js
|
|
600
|
+
var data14 = {
|
|
601
|
+
"width": 24,
|
|
602
|
+
"height": 24,
|
|
603
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3L10 10M10 3L3 10M17.5 3L21 10H14L17.5 3ZM10 17.5C10 19.433 8.433 21 6.5 21C4.567 21 3 19.433 3 17.5C3 15.567 4.567 14 6.5 14C8.433 14 10 15.567 10 17.5ZM16 14H19C20.1046 14 21 14.8954 21 16V19C21 20.1046 20.1046 21 19 21H16C14.8954 21 14 20.1046 14 19V16C14 14.8954 14.8954 14 16 14Z"/>'
|
|
604
|
+
};
|
|
605
|
+
var shapes_default = data14;
|
|
681
606
|
|
|
682
|
-
// ../../node_modules/.pnpm
|
|
683
|
-
var
|
|
684
|
-
|
|
685
|
-
|
|
607
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/c/circle-half.js
|
|
608
|
+
var data15 = {
|
|
609
|
+
"width": 24,
|
|
610
|
+
"height": 24,
|
|
611
|
+
"body": '<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2Z"/><path d="M12 6C15.3138 6 18 8.6862 18 12C18 15.3138 15.3138 18 12 18Z"/></g>'
|
|
612
|
+
};
|
|
613
|
+
var circle_half_default = data15;
|
|
686
614
|
|
|
687
|
-
// ../../node_modules/.pnpm
|
|
688
|
-
var
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
],
|
|
695
|
-
[
|
|
696
|
-
"path",
|
|
697
|
-
{
|
|
698
|
-
d: "M2.297 11.293a1 1 0 0 0 0 1.414l2.377 2.377a1 1 0 0 0 1.414 0l2.377-2.377a1 1 0 0 0 0-1.414L6.088 8.916a1 1 0 0 0-1.414 0z"
|
|
699
|
-
}
|
|
700
|
-
],
|
|
701
|
-
[
|
|
702
|
-
"path",
|
|
703
|
-
{
|
|
704
|
-
d: "M8.916 17.912a1 1 0 0 0 0 1.415l2.377 2.376a1 1 0 0 0 1.414 0l2.377-2.376a1 1 0 0 0 0-1.415l-2.377-2.376a1 1 0 0 0-1.414 0z"
|
|
705
|
-
}
|
|
706
|
-
],
|
|
707
|
-
[
|
|
708
|
-
"path",
|
|
709
|
-
{
|
|
710
|
-
d: "M8.916 4.674a1 1 0 0 0 0 1.414l2.377 2.376a1 1 0 0 0 1.414 0l2.377-2.376a1 1 0 0 0 0-1.414l-2.377-2.377a1 1 0 0 0-1.414 0z"
|
|
711
|
-
}
|
|
712
|
-
]
|
|
713
|
-
];
|
|
615
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/c/cursor.js
|
|
616
|
+
var data16 = {
|
|
617
|
+
"width": 24,
|
|
618
|
+
"height": 24,
|
|
619
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.3184 20.5112L3.0341 3.9139C2.8602 3.3677 3.3816 2.8558 3.9268 3.0373L20.5197 8.5617C21.1361 8.7669 21.1671 9.6243 20.5672 9.8732L13.4774 12.8146C13.3157 12.8817 13.1848 13.0065 13.1107 13.1647L9.6254 20.596C9.3541 21.174 8.5121 21.1195 8.3184 20.5112Z"/>'
|
|
620
|
+
};
|
|
621
|
+
var cursor_default = data16;
|
|
714
622
|
|
|
715
|
-
// ../../node_modules/.pnpm
|
|
716
|
-
var
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
623
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/c/cursor-click.js
|
|
624
|
+
var data17 = {
|
|
625
|
+
"width": 24,
|
|
626
|
+
"height": 24,
|
|
627
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12.1748 5.76261L13.9549 3.98724M7.88236 4.69633L6.98121 2M4.70404 7.86707L2 6.96809M5.77258 12.14803L3.99248 13.9234M9.26992 9.88622L13.0143 21.6534C13.1515 22.0847 13.7482 22.1234 13.9403 21.7136L16.4099 16.4449C16.4625 16.3328 16.5551 16.2442 16.6697 16.1967L21.6933 14.1113C22.1184 13.9348 22.0964 13.3269 21.6597 13.1814L9.90251 9.26472C9.51618 9.13602 9.14671 9.49902 9.26992 9.88622Z"/>'
|
|
628
|
+
};
|
|
629
|
+
var cursor_click_default = data17;
|
|
720
630
|
|
|
721
|
-
// ../../node_modules/.pnpm
|
|
722
|
-
var
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
],
|
|
729
|
-
["path", { d: "M14.084 14.158a3 3 0 0 1-4.242-4.242" }],
|
|
730
|
-
[
|
|
731
|
-
"path",
|
|
732
|
-
{
|
|
733
|
-
d: "M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"
|
|
734
|
-
}
|
|
735
|
-
],
|
|
736
|
-
["path", { d: "m2 2 20 20" }]
|
|
737
|
-
];
|
|
631
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/e/eye.js
|
|
632
|
+
var data18 = {
|
|
633
|
+
"width": 24,
|
|
634
|
+
"height": 24,
|
|
635
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2 12C3.0523 7.3229 7.206 4 12 4C16.794 4 20.9477 7.3229 22 12C20.9477 16.6771 16.794 20 12 20C7.206 20 3.0523 16.6771 2 12ZM15 12C15 13.6569 13.6569 15 12 15C10.3431 15 9 13.6569 9 12C9 10.3431 10.3431 9 12 9C13.6569 9 15 10.3431 15 12Z"/>'
|
|
636
|
+
};
|
|
637
|
+
var eye_default = data18;
|
|
738
638
|
|
|
739
|
-
// ../../node_modules/.pnpm
|
|
740
|
-
var
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
],
|
|
747
|
-
["circle", { cx: "12", cy: "12", r: "3" }]
|
|
748
|
-
];
|
|
639
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/e/eye-off.js
|
|
640
|
+
var data19 = {
|
|
641
|
+
"width": 24,
|
|
642
|
+
"height": 24,
|
|
643
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18.035 18.035C16.3283 19.2786 14.2337 20 12 20C7.206 20 3.0523 16.6771 2 12C2.562 9.5021 4.0086 7.3904 5.965 5.965M9.8779 4.2211C10.565 4.076 11.2752 4 12 4C16.794 4 20.9477 7.3229 22 12C21.7487 13.1169 21.3206 14.1566 20.7491 15.0922M14.1213 14.1213C13.5785 14.6642 12.8285 15 12 15C10.3431 15 9 13.6569 9 12C9 11.1716 9.3358 10.4216 9.8787 9.8787M2 2L22 22"/>'
|
|
644
|
+
};
|
|
645
|
+
var eye_off_default = data19;
|
|
749
646
|
|
|
750
|
-
// ../../node_modules/.pnpm
|
|
751
|
-
var
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
],
|
|
758
|
-
["path", { d: "M14 2v5a1 1 0 0 0 1 1h5" }],
|
|
759
|
-
["path", { d: "M10 9H8" }],
|
|
760
|
-
["path", { d: "M16 13H8" }],
|
|
761
|
-
["path", { d: "M16 17H8" }]
|
|
762
|
-
];
|
|
647
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/f/file-text.js
|
|
648
|
+
var data20 = {
|
|
649
|
+
"width": 24,
|
|
650
|
+
"height": 24,
|
|
651
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 2H8C5.79086 2 4 3.79086 4 6V18C4 20.2091 5.79086 22 8 22H16C18.2091 22 20 20.2091 20 18V8L14 2ZM14 2V5C14 6.65685 15.3431 8 17 8H20M8 13H12M8 17H16"/>'
|
|
652
|
+
};
|
|
653
|
+
var file_text_default = data20;
|
|
763
654
|
|
|
764
|
-
// ../../node_modules/.pnpm
|
|
765
|
-
var
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
],
|
|
772
|
-
["path", { d: "M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12" }],
|
|
773
|
-
["path", { d: "M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17" }]
|
|
774
|
-
];
|
|
655
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/l/layout-dashboard.js
|
|
656
|
+
var data21 = {
|
|
657
|
+
"width": 24,
|
|
658
|
+
"height": 24,
|
|
659
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 3H9C9.55228 3 10 3.44772 10 4V11C10 11.55228 9.55228 12 9 12H4C3.44772 12 3 11.55228 3 11V4C3 3.44772 3.44772 3 4 3ZM4 16H9C9.55228 16 10 16.44772 10 17V20C10 20.55228 9.55228 21 9 21H4C3.44772 21 3 20.55228 3 20V17C3 16.44772 3.44772 16 4 16ZM15 3H20C20.55228 3 21 3.44772 21 4V7C21 7.55228 20.55228 8 20 8H15C14.44772 8 14 7.55228 14 7V4C14 3.44772 14.44772 3 15 3ZM15 12H20C20.55228 12 21 12.44772 21 13V20C21 20.55228 20.55228 21 20 21H15C14.44772 21 14 20.55228 14 20V13C14 12.44772 14.44772 12 15 12Z"/>'
|
|
660
|
+
};
|
|
661
|
+
var layout_dashboard_default = data21;
|
|
775
662
|
|
|
776
|
-
// ../../node_modules/.pnpm
|
|
777
|
-
var
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
663
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/g/grid-squares.js
|
|
664
|
+
var data22 = {
|
|
665
|
+
"width": 24,
|
|
666
|
+
"height": 24,
|
|
667
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 16C3 14.8954 3.8954 14 5 14L8 14C9.1046 14 10 14.8954 10 16L10 19C10 20.1046 9.1046 21 8 21L5 21C3.8954 21 3 20.1046 3 19L3 16ZM3 5C3 3.8954 3.8954 3 5 3L8 3C9.1046 3 10 3.8954 10 5L10 8C10 9.1046 9.1046 10 8 10L5 10C3.8954 10 3 9.1046 3 8L3 5ZM14 16C14 14.8954 14.8954 14 16 14L19 14C20.1046 14 21 14.8954 21 16L21 19C21 20.1046 20.1046 21 19 21L16 21C14.8954 21 14 20.1046 14 19L14 16ZM14 5C14 3.8954 14.8954 3 16 3L19 3C20.1046 3 21 3.8954 21 5L21 8C21 9.1046 20.1046 10 19 10L16 10C14.8954 10 14 9.1046 14 8L14 5Z"/>'
|
|
668
|
+
};
|
|
669
|
+
var grid_squares_default = data22;
|
|
783
670
|
|
|
784
|
-
// ../../node_modules/.pnpm
|
|
785
|
-
var
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
671
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/l/link.js
|
|
672
|
+
var data23 = {
|
|
673
|
+
"width": 24,
|
|
674
|
+
"height": 24,
|
|
675
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17H7C4.23858 17 2 14.7614 2 12C2 9.23858 4.23858 7 7 7H9M15 7H17C19.7614 7 22 9.23858 22 12C22 14.7614 19.7614 17 17 17H15M8 12H16"/>'
|
|
676
|
+
};
|
|
677
|
+
var link_default = data23;
|
|
790
678
|
|
|
791
|
-
// ../../node_modules/.pnpm
|
|
792
|
-
var
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
679
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/l/link-off.js
|
|
680
|
+
var data24 = {
|
|
681
|
+
"width": 24,
|
|
682
|
+
"height": 24,
|
|
683
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17L7 17C4.2386 17 2 14.7614 2 12C2 9.2386 4.2386 7 7 7M15 7L17 7C19.7614 7 22 9.2386 22 12C22 13.2135 21.5677 14.326 20.8488 15.1919M17 17L15 17M8 12L12 12M2 2L22 22"/>'
|
|
684
|
+
};
|
|
685
|
+
var link_off_default = data24;
|
|
796
686
|
|
|
797
|
-
// ../../node_modules/.pnpm
|
|
798
|
-
var
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
687
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/l/lock.js
|
|
688
|
+
var data25 = {
|
|
689
|
+
"width": 24,
|
|
690
|
+
"height": 24,
|
|
691
|
+
"body": '<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M7.5 10V6.5C7.5 4.01472 9.51472 2 12 2C14.4853 2 16.5 4.01472 16.5 6.5V10M4 13V19C4 20.6569 5.34315 22 7 22H17C18.6569 22 20 20.6569 20 19V13C20 11.3431 18.6569 10 17 10H7C5.34315 10 4 11.3431 4 13Z"/><path fill="currentColor" d="M13.5 16C13.5 16.8284 12.8284 17.5 12 17.5C11.1716 17.5 10.5 16.8284 10.5 16C10.5 15.1716 11.1716 14.5 12 14.5C12.8284 14.5 13.5 15.1716 13.5 16Z" stroke="none"/></g>'
|
|
692
|
+
};
|
|
693
|
+
var lock_default = data25;
|
|
804
694
|
|
|
805
|
-
// ../../node_modules/.pnpm
|
|
806
|
-
var
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
]
|
|
813
|
-
];
|
|
695
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/m/maximize.js
|
|
696
|
+
var data26 = {
|
|
697
|
+
"width": 24,
|
|
698
|
+
"height": 24,
|
|
699
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3H6C4.34315 3 3 4.34315 3 6V9M15 3H18C19.65685 3 21 4.34315 21 6V9M21 15V18C21 19.65685 19.65685 21 18 21H15M3 15V18C3 19.65685 4.34315 21 6 21H9"/>'
|
|
700
|
+
};
|
|
701
|
+
var maximize_default = data26;
|
|
814
702
|
|
|
815
|
-
// ../../node_modules/.pnpm
|
|
816
|
-
var
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
],
|
|
823
|
-
["circle", { cx: "13.5", cy: "6.5", r: ".5", fill: "currentColor" }],
|
|
824
|
-
["circle", { cx: "17.5", cy: "10.5", r: ".5", fill: "currentColor" }],
|
|
825
|
-
["circle", { cx: "6.5", cy: "12.5", r: ".5", fill: "currentColor" }],
|
|
826
|
-
["circle", { cx: "8.5", cy: "7.5", r: ".5", fill: "currentColor" }]
|
|
827
|
-
];
|
|
703
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/f/flower.js
|
|
704
|
+
var data27 = {
|
|
705
|
+
"width": 24,
|
|
706
|
+
"height": 24,
|
|
707
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.6 5.2162C9.6 3.8907 10.6745 2.8162 12 2.8162C13.3255 2.8162 14.4 3.8907 14.4 5.2162C14.4 6.5417 13.3255 7.6162 12 7.6162C10.6745 7.6162 9.6 6.5417 9.6 5.2162ZM16.7329 10.3986C16.7329 9.0731 17.8074 7.9986 19.1329 7.9986C20.4584 7.9986 21.5329 9.0731 21.5329 10.3986C21.5329 11.7241 20.4584 12.7986 19.1329 12.7986C17.8074 12.7986 16.7329 11.7241 16.7329 10.3986ZM14.0084 18.7838C14.0084 17.4583 15.0829 16.3838 16.4084 16.3838C17.7339 16.3838 18.8084 17.4583 18.8084 18.7838C18.8084 20.1093 17.7339 21.1838 16.4084 21.1838C15.0829 21.1838 14.0084 20.1093 14.0084 18.7838ZM5.1916 18.7838C5.1916 17.4583 6.2661 16.3838 7.5916 16.3838C8.9171 16.3838 9.9916 17.4583 9.9916 18.7838C9.9916 20.1093 8.9171 21.1838 7.5916 21.1838C6.2661 21.1838 5.1916 20.1093 5.1916 18.7838ZM2.4671 10.3986C2.4671 9.0731 3.5416 7.9986 4.8671 7.9986C6.1926 7.9986 7.2671 9.0731 7.2671 10.3986C7.2671 11.7241 6.1926 12.7986 4.8671 12.7986C3.5416 12.7986 2.4671 11.7241 2.4671 10.3986Z"/>'
|
|
708
|
+
};
|
|
709
|
+
var flower_default = data27;
|
|
828
710
|
|
|
829
|
-
// ../../node_modules/.pnpm
|
|
830
|
-
var
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
711
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/p/panel-right.js
|
|
712
|
+
var data28 = {
|
|
713
|
+
"width": 24,
|
|
714
|
+
"height": 24,
|
|
715
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 3H18C19.6569 3 21 4.34315 21 6V18C21 19.6569 19.6569 21 18 21H6C4.34315 21 3 19.6569 3 18V6C3 4.34315 4.34315 3 6 3ZM15 3V21"/>'
|
|
716
|
+
};
|
|
717
|
+
var panel_right_default = data28;
|
|
835
718
|
|
|
836
|
-
// ../../node_modules/.pnpm
|
|
837
|
-
var
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
719
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/p/play.js
|
|
720
|
+
var data29 = {
|
|
721
|
+
"width": 24,
|
|
722
|
+
"height": 24,
|
|
723
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4.00351C4 2.379713 5.83285 1.432756 7.157224 2.372305L19.578612 11.184397C20.140462 11.58299 20.140462 12.41701 19.578612 12.815603L7.157224 21.627695C5.83285 22.567244 4 21.620287 4 19.99649Z"/>'
|
|
724
|
+
};
|
|
725
|
+
var play_default = data29;
|
|
843
726
|
|
|
844
|
-
// ../../node_modules/.pnpm
|
|
845
|
-
var
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
727
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/r/rotate-cw.js
|
|
728
|
+
var data30 = {
|
|
729
|
+
"width": 24,
|
|
730
|
+
"height": 24,
|
|
731
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.7883 10.0593C20.929 10.6966 21 11.3473 21 12C21 16.9706 16.9706 21 12 21C7.0294 21 3 16.9706 3 12C3 7.0294 7.0294 3 12 3C14.4831 3 16.8559 4.0259 18.5568 5.8349M19.7143 3L19.2707 6.105C19.2317 6.3784 18.9784 6.5683 18.705 6.5293L15.6 6.0857"/>'
|
|
732
|
+
};
|
|
733
|
+
var rotate_cw_default = data30;
|
|
849
734
|
|
|
850
|
-
// ../../node_modules/.pnpm
|
|
851
|
-
var
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
735
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/r/refresh-ccw.js
|
|
736
|
+
var data31 = {
|
|
737
|
+
"width": 24,
|
|
738
|
+
"height": 24,
|
|
739
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.7883 13.9407C20.929 13.3034 21 12.6527 21 12C21 7.0294 16.9706 3 12 3C9.5169 3 7.1441 4.0259 5.4432 5.8349M4.2857 3L4.7293 6.105C4.7683 6.3784 5.0216 6.5683 5.295 6.5293L8.4 6.0857M3.2117 10.0593C3.071 10.6966 3 11.3473 3 12C3 16.9706 7.0294 21 12 21C14.4831 21 16.8559 19.9741 18.5568 18.1651M19.7143 21L19.2707 17.895C19.2317 17.6216 18.9784 17.4317 18.705 17.4707L15.6 17.9143"/>'
|
|
740
|
+
};
|
|
741
|
+
var refresh_ccw_default = data31;
|
|
855
742
|
|
|
856
|
-
// ../../node_modules/.pnpm
|
|
857
|
-
var
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
],
|
|
864
|
-
["path", { d: "M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7" }],
|
|
865
|
-
["path", { d: "M7 3v4a1 1 0 0 0 1 1h7" }]
|
|
866
|
-
];
|
|
743
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/d/download.js
|
|
744
|
+
var data32 = {
|
|
745
|
+
"width": 24,
|
|
746
|
+
"height": 24,
|
|
747
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3V14M8 10L12 14L16 10M4 18V19C4 20.1046 4.89543 21 6 21H18C19.1046 21 20 20.1046 20 19V18"/>'
|
|
748
|
+
};
|
|
749
|
+
var download_default = data32;
|
|
867
750
|
|
|
868
|
-
// ../../node_modules/.pnpm
|
|
869
|
-
var
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
],
|
|
876
|
-
["path", { d: "M20 2v4" }],
|
|
877
|
-
["path", { d: "M22 4h-4" }],
|
|
878
|
-
["circle", { cx: "4", cy: "20", r: "2" }]
|
|
879
|
-
];
|
|
751
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/s/star.js
|
|
752
|
+
var data33 = {
|
|
753
|
+
"width": 24,
|
|
754
|
+
"height": 24,
|
|
755
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11.5386 2.8073C11.6164 2.6212 11.7983 2.5 12 2.5C12.2017 2.5 12.3836 2.6212 12.4614 2.8073L14.87 8.5744C14.9422 8.7473 15.1049 8.8653 15.2916 8.8802L21.5398 9.379C21.7413 9.3951 21.9133 9.531 21.9756 9.7233C22.0379 9.9157 21.9783 10.1266 21.8245 10.2578L17.0671 14.3162C16.924 14.4383 16.8615 14.6302 16.9053 14.8131L18.3593 20.8835C18.4064 21.0798 18.3307 21.2851 18.1675 21.404C18.0044 21.5229 17.7857 21.532 17.6132 21.4271L12.2598 18.1708C12.1002 18.0737 11.8998 18.0737 11.7402 18.1708L6.3868 21.4271C6.2143 21.532 5.9956 21.5229 5.8325 21.404C5.6693 21.2851 5.5936 21.0798 5.6407 20.8835L7.0947 14.8131C7.1385 14.6302 7.076 14.4383 6.9329 14.3162L2.1755 10.2578C2.0217 10.1266 1.962 9.9157 2.0244 9.7233C2.0867 9.531 2.2587 9.3951 2.4602 9.379L8.7084 8.8802C8.8951 8.8653 9.0578 8.7473 9.13 8.5744Z"/>'
|
|
756
|
+
};
|
|
757
|
+
var star_default = data33;
|
|
880
758
|
|
|
881
|
-
// ../../node_modules/.pnpm
|
|
882
|
-
var
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
759
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/t/triangle-alert.js
|
|
760
|
+
var data34 = {
|
|
761
|
+
"width": 24,
|
|
762
|
+
"height": 24,
|
|
763
|
+
"body": '<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M14.4051 4.39215C13.3181 2.53595 10.6819 2.53595 9.5949 4.39215L2.40063 16.6777C1.28536 18.5822 2.63072 21 4.80572 21H19.1943C21.3693 21 22.7146 18.5822 21.5994 16.6777L14.4051 4.39215Z"/><path d="M12 9V13"/><path fill="currentColor" d="M13 17C13 17.5523 12.5523 18 12 18C11.4477 18 11 17.5523 11 17C11 16.4477 11.4477 16 12 16C12.5523 16 13 16.4477 13 17Z" stroke="none"/></g>'
|
|
764
|
+
};
|
|
765
|
+
var triangle_alert_default = data34;
|
|
887
766
|
|
|
888
|
-
// ../../node_modules/.pnpm
|
|
889
|
-
var
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
767
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/c/cursor-text.js
|
|
768
|
+
var data35 = {
|
|
769
|
+
"width": 24,
|
|
770
|
+
"height": 24,
|
|
771
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3.5H12.9583M3 8.10055H5.98748M3 12.7011H5.98748M10.2669 10.0807L13.3776 20.1434C13.5147 20.5871 14.1112 20.627 14.3032 20.2053L16.3303 15.7538C16.3829 15.6384 16.4755 15.5473 16.5901 15.4983L20.6934 13.745C21.1183 13.5634 21.0964 12.9379 20.6598 12.7882L10.8992 9.44123C10.513 9.30882 10.1437 9.68231 10.2669 10.0807Z"/>'
|
|
772
|
+
};
|
|
773
|
+
var cursor_text_default = data35;
|
|
894
774
|
|
|
895
|
-
// ../../node_modules/.pnpm
|
|
896
|
-
var
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
775
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/r/rotate-ccw.js
|
|
776
|
+
var data36 = {
|
|
777
|
+
"width": 24,
|
|
778
|
+
"height": 24,
|
|
779
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.2117 10.0593C3.071 10.6966 3 11.3473 3 12C3 16.9706 7.0294 21 12 21C16.9706 21 21 16.9706 21 12C21 7.0294 16.9706 3 12 3C9.5169 3 7.1441 4.0259 5.4432 5.8349M4.2857 3L4.7293 6.105C4.7683 6.3784 5.0216 6.5683 5.295 6.5293L8.4 6.0857"/>'
|
|
780
|
+
};
|
|
781
|
+
var rotate_ccw_default = data36;
|
|
900
782
|
|
|
901
|
-
// ../../node_modules/.pnpm
|
|
902
|
-
var
|
|
783
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/p/pencil-ruler.js
|
|
784
|
+
var data37 = {
|
|
785
|
+
"width": 24,
|
|
786
|
+
"height": 24,
|
|
787
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.9371 21.3335C3.8326 21.3694 3.7228 21.3878 3.6122 21.3878C3.0599 21.3878 2.6122 20.9401 2.6122 20.3878C2.6122 20.2772 2.6306 20.1674 2.6665 20.0629L4.1467 15.7542C4.1961 15.6103 4.2777 15.4796 4.3853 15.372L14.7577 4.9996C15.3203 4.437 16.0834 4.121 16.879 4.121C17.6747 4.121 18.4377 4.437 19.0004 4.9996C19.563 5.5623 19.879 6.3253 19.879 7.121C19.879 7.9166 19.563 8.6797 19.0004 9.2423L8.628 19.6147C8.5204 19.7223 8.3897 19.8039 8.2458 19.8533L3.9371 21.3335ZM4.2218 15.5355L8.4645 19.7782M4.2925 2.8783C4.8551 2.3157 5.6182 1.9996 6.4139 1.9996C7.2095 1.9996 7.9726 2.3157 8.5352 2.8783L12.7071 7.0503L7.0503 12.7071L2.8783 8.5352C2.3157 7.9726 1.9996 7.2095 1.9996 6.4139C1.9996 5.6182 2.3157 4.8551 2.8783 4.2925L4.2925 2.8783ZM16.9497 11.2929L21.1217 15.4648C21.6843 16.0274 22.0004 16.7905 22.0004 17.5861C22.0004 18.3818 21.6843 19.1449 21.1217 19.7075L19.7075 21.1217C19.1449 21.6843 18.3818 22.0004 17.5861 22.0004C16.7905 22.0004 16.0274 21.6843 15.4648 21.1217L11.2929 16.9497L16.9497 11.2929ZM9.5251 3.8683L7.4038 5.9896M20.1317 14.4749L18.0104 16.5962"/>'
|
|
788
|
+
};
|
|
789
|
+
var pencil_ruler_default = data37;
|
|
903
790
|
|
|
904
|
-
// ../../node_modules/.pnpm
|
|
905
|
-
var
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
],
|
|
912
|
-
["path", { d: "m14 7 3 3" }],
|
|
913
|
-
["path", { d: "M5 6v4" }],
|
|
914
|
-
["path", { d: "M19 14v4" }],
|
|
915
|
-
["path", { d: "M10 2v2" }],
|
|
916
|
-
["path", { d: "M7 8H3" }],
|
|
917
|
-
["path", { d: "M21 16h-4" }],
|
|
918
|
-
["path", { d: "M11 3H9" }]
|
|
919
|
-
];
|
|
791
|
+
// ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/x/x.js
|
|
792
|
+
var data38 = {
|
|
793
|
+
"width": 24,
|
|
794
|
+
"height": 24,
|
|
795
|
+
"body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7L17 17M17 7L7 17"/>'
|
|
796
|
+
};
|
|
797
|
+
var x_default = data38;
|
|
920
798
|
|
|
921
|
-
//
|
|
922
|
-
var
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
799
|
+
// src/keyline-icons.ts
|
|
800
|
+
var KEYLINE_ICONS = {
|
|
801
|
+
accessibility: user_check_default,
|
|
802
|
+
activity: activity_default,
|
|
803
|
+
"align-horizontal-space-around": align_offset_left_default,
|
|
804
|
+
"arrow-down": arrow_down_default,
|
|
805
|
+
"arrow-left": arrow_left_default,
|
|
806
|
+
"arrow-up": arrow_up_default,
|
|
807
|
+
bookmark: bookmark_default,
|
|
808
|
+
box: square_default,
|
|
809
|
+
check: check_default,
|
|
810
|
+
"chevron-down": chevron_down_default,
|
|
811
|
+
"chevron-right": chevron_right_default,
|
|
812
|
+
"columns-3": grid_3x2_default,
|
|
813
|
+
command: square_terminal_default,
|
|
814
|
+
component: shapes_default,
|
|
815
|
+
contrast: circle_half_default,
|
|
816
|
+
eye: eye_default,
|
|
817
|
+
"eye-off": eye_off_default,
|
|
818
|
+
"file-text": file_text_default,
|
|
819
|
+
"layout-grid": layout_dashboard_default,
|
|
820
|
+
"layers-3": grid_squares_default,
|
|
821
|
+
"link-2": link_default,
|
|
822
|
+
lock: lock_default,
|
|
823
|
+
"maximize-2": maximize_default,
|
|
824
|
+
"mouse-pointer-2": cursor_default,
|
|
825
|
+
interact: cursor_click_default,
|
|
826
|
+
palette: flower_default,
|
|
827
|
+
"panels-top-left": panel_right_default,
|
|
828
|
+
play: play_default,
|
|
829
|
+
"redo-2": rotate_cw_default,
|
|
830
|
+
"rotate-ccw": refresh_ccw_default,
|
|
831
|
+
save: download_default,
|
|
832
|
+
sparkles: star_default,
|
|
833
|
+
"triangle-alert": triangle_alert_default,
|
|
834
|
+
type: cursor_text_default,
|
|
835
|
+
"undo-2": rotate_ccw_default,
|
|
836
|
+
"unlink-2": link_off_default,
|
|
837
|
+
"wand-sparkles": pencil_ruler_default,
|
|
838
|
+
x: x_default
|
|
839
|
+
};
|
|
840
|
+
function renderKeylineIcons(root) {
|
|
841
|
+
root.querySelectorAll("[data-foundry-icon]").forEach((placeholder) => {
|
|
842
|
+
const semanticName = placeholder.dataset.foundryIcon;
|
|
843
|
+
if (!semanticName) return;
|
|
844
|
+
const icon = KEYLINE_ICONS[semanticName];
|
|
845
|
+
if (!icon) return;
|
|
846
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
847
|
+
svg.setAttribute("viewBox", `0 0 ${icon.width ?? 24} ${icon.height ?? 24}`);
|
|
848
|
+
svg.setAttribute("aria-hidden", "true");
|
|
849
|
+
svg.setAttribute("focusable", "false");
|
|
850
|
+
svg.setAttribute("data-keyline-icon", semanticName);
|
|
851
|
+
svg.innerHTML = icon.body;
|
|
852
|
+
placeholder.replaceWith(svg);
|
|
853
|
+
});
|
|
854
|
+
}
|
|
926
855
|
|
|
927
|
-
//
|
|
928
|
-
var
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
856
|
+
// src/workspace.ts
|
|
857
|
+
var DEFAULT_WORKSPACE_STATE = {
|
|
858
|
+
layersOpen: true,
|
|
859
|
+
inspectorOpen: true,
|
|
860
|
+
utility: null,
|
|
861
|
+
tray: "hidden",
|
|
862
|
+
workbenchOpen: false,
|
|
863
|
+
comparisonOpen: false
|
|
864
|
+
};
|
|
865
|
+
function updateWorkspace(state, action) {
|
|
866
|
+
if (action.type === "toggle-layers") {
|
|
867
|
+
return { ...state, layersOpen: action.open ?? !state.layersOpen };
|
|
939
868
|
}
|
|
940
|
-
if (
|
|
941
|
-
|
|
942
|
-
}
|
|
943
|
-
const elementsToReplace = Array.from(root.querySelectorAll(`[${nameAttr}]`));
|
|
944
|
-
elementsToReplace.forEach((element) => replaceElement(element, { nameAttr, icons, attrs }));
|
|
945
|
-
if (inTemplates) {
|
|
946
|
-
const templates = Array.from(root.querySelectorAll("template"));
|
|
947
|
-
templates.forEach(
|
|
948
|
-
(template) => createIcons({
|
|
949
|
-
icons,
|
|
950
|
-
nameAttr,
|
|
951
|
-
attrs,
|
|
952
|
-
root: template.content,
|
|
953
|
-
inTemplates
|
|
954
|
-
})
|
|
955
|
-
);
|
|
869
|
+
if (action.type === "toggle-inspector") {
|
|
870
|
+
return { ...state, inspectorOpen: action.open ?? !state.inspectorOpen };
|
|
956
871
|
}
|
|
957
|
-
if (
|
|
958
|
-
|
|
959
|
-
if (deprecatedElements.length > 0) {
|
|
960
|
-
console.warn(
|
|
961
|
-
"[Lucide] Some icons were found with the now deprecated icon-name attribute. These will still be replaced for backwards compatibility, but will no longer be supported in v1.0 and you should switch to data-lucide"
|
|
962
|
-
);
|
|
963
|
-
Array.from(deprecatedElements).forEach(
|
|
964
|
-
(element) => replaceElement(element, { nameAttr: "icon-name", icons, attrs })
|
|
965
|
-
);
|
|
966
|
-
}
|
|
872
|
+
if (action.type === "open-utility") {
|
|
873
|
+
return { ...state, utility: state.utility === action.utility ? null : action.utility };
|
|
967
874
|
}
|
|
968
|
-
};
|
|
875
|
+
if (action.type === "close-utility") return { ...state, utility: null };
|
|
876
|
+
if (action.type === "set-tray") return { ...state, tray: action.tray };
|
|
877
|
+
if (action.type === "set-workbench") return { ...state, workbenchOpen: action.open };
|
|
878
|
+
return { ...state, comparisonOpen: action.open };
|
|
879
|
+
}
|
|
880
|
+
function clampUtilityRect(rect, bounds, minimum = { width: 280, height: 280 }) {
|
|
881
|
+
const availableWidth = Math.max(minimum.width, bounds.right - bounds.left);
|
|
882
|
+
const availableHeight = Math.max(minimum.height, bounds.bottom - bounds.top);
|
|
883
|
+
const width = Math.min(Math.max(rect.width, minimum.width), availableWidth);
|
|
884
|
+
const height = Math.min(Math.max(rect.height, minimum.height), availableHeight);
|
|
885
|
+
return {
|
|
886
|
+
x: Math.min(Math.max(rect.x, bounds.left), Math.max(bounds.left, bounds.right - width)),
|
|
887
|
+
y: Math.min(Math.max(rect.y, bounds.top), Math.max(bounds.top, bounds.bottom - height)),
|
|
888
|
+
width,
|
|
889
|
+
height
|
|
890
|
+
};
|
|
891
|
+
}
|
|
969
892
|
|
|
970
893
|
// src/index.ts
|
|
971
894
|
var CATEGORY_LABELS = {
|
|
972
|
-
layout: "Layout",
|
|
973
|
-
typography: "
|
|
974
|
-
color: "
|
|
895
|
+
layout: "Layout and spacing",
|
|
896
|
+
typography: "Typography",
|
|
897
|
+
color: "Fill and stroke",
|
|
975
898
|
effects: "Effects",
|
|
976
899
|
content: "Content",
|
|
977
|
-
accessibility: "
|
|
900
|
+
accessibility: "Accessibility",
|
|
978
901
|
motion: "Motion"
|
|
979
902
|
};
|
|
980
903
|
var CATEGORY_ICONS = {
|
|
@@ -986,66 +909,32 @@ var CATEGORY_ICONS = {
|
|
|
986
909
|
accessibility: "accessibility",
|
|
987
910
|
motion: "play"
|
|
988
911
|
};
|
|
989
|
-
var FOUNDRY_ICONS = {
|
|
990
|
-
Accessibility,
|
|
991
|
-
Activity,
|
|
992
|
-
AlignHorizontalSpaceAround,
|
|
993
|
-
ArrowDown,
|
|
994
|
-
ArrowLeft,
|
|
995
|
-
ArrowUp,
|
|
996
|
-
Box,
|
|
997
|
-
Bookmark,
|
|
998
|
-
ChevronDown,
|
|
999
|
-
ChevronRight,
|
|
1000
|
-
Check,
|
|
1001
|
-
Columns3,
|
|
1002
|
-
Component,
|
|
1003
|
-
Command,
|
|
1004
|
-
Contrast,
|
|
1005
|
-
Eye,
|
|
1006
|
-
EyeOff,
|
|
1007
|
-
FileText,
|
|
1008
|
-
LayoutGrid,
|
|
1009
|
-
Layers3: Layers,
|
|
1010
|
-
Link2,
|
|
1011
|
-
Lock,
|
|
1012
|
-
Maximize2,
|
|
1013
|
-
MousePointer2,
|
|
1014
|
-
Palette,
|
|
1015
|
-
PanelsTopLeft,
|
|
1016
|
-
Play,
|
|
1017
|
-
Sparkles,
|
|
1018
|
-
TriangleAlert,
|
|
1019
|
-
Type,
|
|
1020
|
-
Redo2,
|
|
1021
|
-
RotateCcw,
|
|
1022
|
-
Save,
|
|
1023
|
-
Undo2,
|
|
1024
|
-
Unlink2,
|
|
1025
|
-
WandSparkles,
|
|
1026
|
-
X
|
|
1027
|
-
};
|
|
1028
912
|
var CONTROL_SECTIONS = {
|
|
1029
913
|
layout: [
|
|
1030
914
|
{
|
|
1031
|
-
label: "
|
|
1032
|
-
properties: [
|
|
915
|
+
label: "Position and size",
|
|
916
|
+
properties: [
|
|
917
|
+
"widthMode",
|
|
918
|
+
"heightMode",
|
|
919
|
+
"width",
|
|
920
|
+
"height",
|
|
921
|
+
"minWidth",
|
|
922
|
+
"maxWidth",
|
|
923
|
+
"aspectRatio",
|
|
924
|
+
"overflow"
|
|
925
|
+
],
|
|
1033
926
|
columns: 2,
|
|
1034
927
|
prefixes: {
|
|
1035
928
|
widthMode: "W",
|
|
1036
929
|
heightMode: "H",
|
|
930
|
+
width: "W",
|
|
931
|
+
height: "H",
|
|
1037
932
|
minWidth: "Min",
|
|
1038
933
|
maxWidth: "Max",
|
|
1039
934
|
aspectRatio: "Ratio",
|
|
1040
935
|
overflow: "Clip"
|
|
1041
936
|
}
|
|
1042
937
|
},
|
|
1043
|
-
{
|
|
1044
|
-
label: "Size",
|
|
1045
|
-
properties: ["width", "height"],
|
|
1046
|
-
columns: 2,
|
|
1047
|
-
prefixes: { width: "W", height: "H" }
|
|
1048
|
-
},
|
|
1049
938
|
{
|
|
1050
939
|
label: "Flow",
|
|
1051
940
|
properties: [
|
|
@@ -1132,34 +1021,34 @@ var CONTROL_SECTIONS = {
|
|
|
1132
1021
|
]
|
|
1133
1022
|
};
|
|
1134
1023
|
var PANEL_CSS = `
|
|
1135
|
-
:host { all:initial; --fdc-ink:#
|
|
1024
|
+
:host { all:initial; color-scheme:dark; --fdc-ink:#f0f1f3; --fdc-paper:#141416; --fdc-surface:#1c1c1f; --fdc-subtle:#242428; --fdc-elevated:#29292e; --fdc-line:#303035; --fdc-signal:#3b82f6; --fdc-signal-soft:#172d50; --fdc-component:#9b87f5; --fdc-component-soft:#28233d; --fdc-muted:#9a9aa2; --fdc-font:"Geist Sans",Geist,Arial,sans-serif; font-family:var(--fdc-font); color:var(--fdc-ink); }
|
|
1136
1025
|
*,*::before,*::after { box-sizing:border-box;font-family:inherit; }
|
|
1137
1026
|
button,select,input { font:inherit; }
|
|
1138
1027
|
button:focus-visible,select:focus-visible,input:focus-visible { outline:2px solid var(--fdc-signal);outline-offset:2px; }
|
|
1139
1028
|
.outline { position:fixed;z-index:2147483645;pointer-events:none;border:1.5px solid var(--fdc-signal);box-shadow:0 0 0 1px rgb(255 255 255 / 90%),0 0 0 4px rgb(54 89 244 / 12%);transition:top 80ms linear,left 80ms linear,width 80ms linear,height 80ms linear; }
|
|
1140
1029
|
.measure { position:absolute;left:-2px;top:-28px;height:25px;display:flex;align-items:center;padding:0 9px;color:white;background:var(--fdc-signal);border-radius:5px 5px 5px 0;font:650 10px/1 var(--fdc-font);letter-spacing:.02em;white-space:nowrap;box-shadow:0 4px 14px rgb(25 43 124 / 20%); }
|
|
1141
1030
|
.cross::before,.cross::after { content:"";position:absolute;background:var(--fdc-signal); }.cross::before { width:11px;height:1px;left:-6px;top:-1px; }.cross::after { width:1px;height:11px;left:-1px;top:-6px; }
|
|
1142
|
-
.panel { position:fixed;z-index:2147483646;top:12px;right:12px;width:
|
|
1031
|
+
.panel { position:fixed;z-index:2147483646;top:12px;right:12px;width:352px;min-width:312px;max-width:min(520px,calc(100vw - 24px));max-height:calc(100vh - 24px);overflow:hidden;display:flex;flex-direction:column;color:var(--fdc-ink);background:var(--fdc-surface);border:1px solid var(--fdc-line);box-shadow:0 1px 2px rgb(0 0 0 / 5%),0 10px 28px rgb(0 0 0 / 10%);pointer-events:auto;border-radius:12px; }
|
|
1143
1032
|
.top { flex:none;background:var(--fdc-surface);border-bottom:1px solid var(--fdc-line); }
|
|
1144
1033
|
.top-identity { position:relative;min-height:44px;display:flex;align-items:center;padding:0 12px; }
|
|
1145
|
-
.brand { flex:1;display:flex;align-items:center;
|
|
1034
|
+
.brand { flex:1;display:flex;align-items:center;min-width:0; }
|
|
1146
1035
|
.brand-copy { display:flex;align-items:baseline;gap:5px; }.brand-copy b { font-size:13px;line-height:1;font-weight:550;letter-spacing:-.02em; }.brand-copy span { color:var(--fdc-muted);font:400 10px/1 var(--fdc-font); }
|
|
1147
1036
|
.session-status { flex:none;margin-left:8px;display:flex;align-items:center;gap:5px;padding:4px 7px;border:0;color:#236c59;background:#eef8f4;border-radius:999px;font:500 10px/1 var(--fdc-font);cursor:pointer; }.session-status i { width:5px;height:5px;background:#2ca67f;border-radius:50%; }.session-status.saving { color:#6b570f;background:#fff8d8; }.session-status.saving i { background:#d5a91d;animation:fdc-pulse 1s ease-in-out infinite; }.session-status.error,.session-status.offline { color:#8b4d3d;background:#faece7; }.session-status.error i,.session-status.offline i { background:#d16d51; }.session-status.saved { color:#236c59;background:#eef8f4; }.status-popover { position:absolute;z-index:2;top:39px;right:40px;width:238px;padding:10px;border:1px solid var(--fdc-line);border-radius:8px;background:white;box-shadow:0 10px 28px rgb(0 0 0 / 14%); }.status-popover[hidden] { display:none; }.status-popover strong { display:block;font-size:11px;font-weight:550; }.status-popover span,.status-popover code { display:block;margin-top:5px;overflow:hidden;text-overflow:ellipsis;color:var(--fdc-muted);font:400 9px/1.45 var(--fdc-font);white-space:nowrap; }.status-popover button { width:100%;height:28px;margin-top:8px;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:var(--fdc-ink);font-size:9px;cursor:pointer; }
|
|
1148
1037
|
.top-identity>.close { flex:none;margin-left:4px; }.top-actions { min-height:40px;display:grid;grid-template-columns:repeat(6,minmax(0,1fr));align-items:center;padding:4px 8px;border-top:1px solid var(--fdc-line);background:var(--fdc-surface); }.top-actions .icon-button { justify-self:center; }.icon-button { width:32px;height:32px;display:grid;place-items:center;border:0;border-radius:6px;background:transparent;color:var(--fdc-muted);cursor:pointer; }.icon-button:hover { background:var(--fdc-subtle);color:var(--fdc-ink); }.icon-button.active { color:#0761d1;background:#edf6ff; }.icon-button:disabled { opacity:.35;cursor:not-allowed; }.icon-button:disabled:hover { color:var(--fdc-muted);background:transparent; }
|
|
1149
|
-
.selection { padding:
|
|
1150
|
-
.scope { display:grid;grid-template-columns:1fr 1fr;gap:
|
|
1151
|
-
.tool-shelf { position:fixed;z-index:2147483646;left:50%;bottom:18px;transform:translateX(-50%);display:flex;align-items:center;gap:6px;max-width:calc(100vw - 32px);padding:6px;background:var(--fdc-surface);border:1px solid var(--fdc-line);border-radius:12px;box-shadow:0 2px 2px rgb(0 0 0 / 4%),0 8px 16px -4px rgb(0 0 0 / 14%);pointer-events:auto; }
|
|
1152
|
-
.tool-select,.tab { position:relative;flex:none;width:36px;height:36px;display:grid;place-items:center;padding:0;border:0;border-radius:6px;background:transparent;color:#4d4d4d;cursor:pointer; }.tool-select:hover,.tab:hover { color:var(--fdc-ink);background:var(--fdc-subtle); }.tool-select.active,.tab.active { color:white;background:var(--fdc-ink); }.tool-select svg,.tab svg,.icon-button svg { width:16px;height:16px;
|
|
1153
|
-
.controls { min-height:210px;overflow:auto;background:var(--fdc-surface); }.inspector-heading { position:sticky;top:0;z-index:1;height:42px;display:flex;align-items:center;gap:8px;padding:0 12px;background:rgb(255 255 255 / 96%);border-bottom:1px solid var(--fdc-line);backdrop-filter:blur(8px); }.inspector-heading svg { width:15px;height:15px;
|
|
1038
|
+
.selection { position:relative;padding:14px;background:var(--fdc-surface);border-bottom:1px solid var(--fdc-line); }.selection::before { content:"";position:absolute;top:13px;left:0;width:2px;height:0;background:var(--fdc-signal);border-radius:0 2px 2px 0;transition:height .18s ease; }.panel.has-selection .selection::before { height:24px; }.selection-heading { display:flex;align-items:center;justify-content:space-between;margin-bottom:9px; }.selection-kind { max-width:220px;overflow:hidden;text-overflow:ellipsis;padding:4px 6px;color:#4d4d4d;background:var(--fdc-subtle);border-radius:4px;font:500 10px/1 var(--fdc-font);text-transform:uppercase;letter-spacing:.025em;white-space:nowrap; }.selection-state { color:var(--fdc-muted);font:450 10px/1 var(--fdc-font); }.panel.has-selection .selection-state { color:#0761d1; }.selection strong { display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:16px;line-height:1.3;font-weight:550;letter-spacing:-.025em; }.selection code { display:block;margin-top:5px;overflow:hidden;text-overflow:ellipsis;color:var(--fdc-muted);font:400 11px/1.45 var(--fdc-font);white-space:nowrap; }.selection-hint { display:block;margin-top:9px;color:#858585;font:400 10px/1.45 var(--fdc-font); }.selection-stats { display:flex;gap:5px;margin-top:10px; }.selection-stats[hidden] { display:none; }.selection-stats span { padding:5px 7px;color:#4d4d4d;background:var(--fdc-subtle);border-radius:5px;font:400 10px/1 var(--fdc-font); }.selection-stats span:first-child { color:#0761d1;background:#edf6ff; }.selection.selected-flash strong { animation:fdc-selection-title .2s ease-out; }
|
|
1039
|
+
.scope { display:grid;grid-template-columns:1fr 1fr;gap:8px;padding:12px 14px;background:var(--fdc-surface);border-bottom:1px solid var(--fdc-line); }.scope label { display:flex;flex-direction:column;gap:6px;color:var(--fdc-muted);font:500 11px/1.2 var(--fdc-font); }.scope select { width:100%;height:34px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:6px;background:var(--fdc-surface);color:var(--fdc-ink);font:400 12px/1 var(--fdc-font);text-transform:none;letter-spacing:0;outline:none;cursor:pointer; }
|
|
1040
|
+
.tool-shelf { position:fixed;z-index:2147483646;left:50%;bottom:18px;transform:translateX(-50%);display:flex;align-items:center;gap:6px;max-width:calc(100vw - 32px);padding:6px;background:var(--fdc-surface);border:1px solid var(--fdc-line);border-radius:12px;box-shadow:0 2px 2px rgb(0 0 0 / 4%),0 8px 16px -4px rgb(0 0 0 / 14%);pointer-events:auto; }.mode-copy { min-width:96px;display:flex;flex-direction:column;gap:2px;padding:0 6px 0 1px; }.mode-copy strong { font-size:10px;font-weight:550;line-height:1.1; }.mode-copy span { color:var(--fdc-muted);font-size:9px;line-height:1.2;white-space:nowrap; }
|
|
1041
|
+
.tool-select,.tab { position:relative;flex:none;width:36px;height:36px;display:grid;place-items:center;padding:0;border:0;border-radius:6px;background:transparent;color:#4d4d4d;cursor:pointer; }.tool-select:hover,.tab:hover { color:var(--fdc-ink);background:var(--fdc-subtle); }.tool-select.active,.tab.active { color:white;background:var(--fdc-ink); }.tool-select svg,.tab svg,.icon-button svg { width:16px;height:16px;pointer-events:none; }.tool-select::after,.tab::after { content:attr(data-tooltip);position:absolute;left:50%;bottom:calc(100% + 8px);transform:translate(-50%,3px);padding:6px 8px;border-radius:5px;background:var(--fdc-ink);color:white;font:400 11px/1 var(--fdc-font);white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .12s ease,transform .12s ease; }.tool-select:hover::after,.tool-select:focus-visible::after,.tab:not(:disabled):hover::after,.tab:not(:disabled):focus-visible::after { opacity:1;transform:translate(-50%,0); }.tool-divider { width:1px;height:24px;flex:none;background:var(--fdc-line); }.tabs { display:flex;gap:2px;overflow:visible;scrollbar-width:none; }.tab:disabled { color:#a1a1a1;cursor:default; }.tab:disabled:hover { background:transparent; }
|
|
1042
|
+
.controls { min-height:210px;overflow:auto;background:var(--fdc-surface); }.inspector-heading { position:sticky;top:0;z-index:1;height:42px;display:flex;align-items:center;gap:8px;padding:0 12px;background:rgb(255 255 255 / 96%);border-bottom:1px solid var(--fdc-line);backdrop-filter:blur(8px); }.inspector-heading svg { width:15px;height:15px;color:#4d4d4d; }.inspector-heading strong { font-size:12px;font-weight:550; }.property-count { margin-left:auto;color:var(--fdc-muted);font:400 10px/1 var(--fdc-font);letter-spacing:.01em; }.property-section { padding:0;border-bottom:1px solid var(--fdc-line); }.section-head { width:100%;min-height:39px;display:flex;align-items:center;padding:0 8px 0 4px;background:white;color:#3f3f3f; }.section-head:hover { background:#fcfcfc; }.section-toggle { min-width:0;min-height:39px;flex:1;display:flex;align-items:center;gap:7px;padding:0 8px;border:0;background:transparent;color:inherit;text-align:left;cursor:pointer; }.section-toggle>svg { width:12px;height:12px;color:#858585;transition:transform .12s ease; }.property-section.collapsed .section-toggle>svg { transform:rotate(-90deg); }.section-head strong { font-size:11px;font-weight:500; }.section-grid { display:grid;gap:8px;padding:0 12px 12px; }.property-section.collapsed .section-grid { display:none; }.section-grid.two { grid-template-columns:1fr 1fr; }.section-grid.stacked .property-control { grid-template-columns:1fr;gap:6px; }.property-control { display:grid;grid-template-columns:minmax(0,1fr) 132px 24px;align-items:center;gap:7px;min-height:34px; }.property-label { overflow:hidden;text-overflow:ellipsis;color:#4d4d4d;font-size:11px;font-weight:400;white-space:nowrap; }.control-field { position:relative;display:flex;align-items:center;min-width:0;height:32px;border:1px solid var(--fdc-line);border-radius:5px;background:var(--fdc-paper);overflow:hidden;transition:border-color .12s ease,box-shadow .12s ease,background .12s ease; }.control-field:hover { background:var(--fdc-surface); }.control-field:focus-within { border-color:var(--fdc-signal);background:var(--fdc-surface);box-shadow:0 0 0 2px rgb(0 112 243 / 10%); }.control-reset { width:24px;height:24px;display:grid;place-items:center;padding:0;border:0;border-radius:4px;background:transparent;color:#8a8a8a;cursor:pointer;opacity:0; }.property-control:hover .control-reset,.compact-control:hover .control-reset,.control-reset:focus-visible { opacity:1; }.control-reset:hover { color:var(--fdc-ink);background:var(--fdc-subtle); }.control-reset svg { width:12px;height:12px; }.compact-control { min-width:0;display:grid;grid-template-columns:minmax(0,1fr) 24px;gap:5px;align-items:center; }.compact-control .control-field { width:100%; }.field-prefix { min-width:28px;padding-left:8px;color:#7a7a7a;font:400 10px/1 var(--fdc-font); }.compact-control .field-prefix.wide { min-width:40px; }.property-control input,.property-control select,.compact-control input,.compact-control select { width:100%;min-width:0;height:30px;padding:0 7px;border:0;background:transparent;color:var(--fdc-ink);font:400 11px/1 var(--fdc-font);outline:none; }.property-control input[type="number"],.compact-control input[type="number"] { appearance:textfield; }.property-control input[type="number"]::-webkit-inner-spin-button,.property-control input[type="number"]::-webkit-outer-spin-button,.compact-control input[type="number"]::-webkit-inner-spin-button,.compact-control input[type="number"]::-webkit-outer-spin-button { margin:0;appearance:none; }.property-control select { font-family:var(--fdc-font); }.control-field .unit-select { width:40px;flex:none;padding:0 3px;color:#707070;font-size:9px;cursor:pointer; }[data-scrub-for] { cursor:ew-resize;user-select:none;touch-action:none; }.property-label[data-scrub-for]:hover,.field-prefix[data-scrub-for]:hover,[data-scrub-for].scrubbing { color:var(--fdc-signal); }.color-swatch { width:17px;height:17px;flex:none;margin-left:7px;border:1px solid rgb(0 0 0 / 10%);border-radius:3px;background:var(--swatch-color); }.color-swatch.transparent { background-color:white;background-image:linear-gradient(45deg,#d9d9d9 25%,transparent 25%),linear-gradient(-45deg,#d9d9d9 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#d9d9d9 75%),linear-gradient(-45deg,transparent 75%,#d9d9d9 75%);background-size:8px 8px;background-position:0 0,0 4px,4px -4px,-4px 0; }.color-value { overflow:hidden;text-overflow:ellipsis;margin-left:7px;color:#4d4d4d;font:400 10px/1 var(--fdc-font);white-space:nowrap; }.color-picker { position:absolute;inset:0;width:100%!important;height:100%!important;opacity:0;cursor:pointer; }.unit { padding-right:7px;color:#7a7a7a;font:400 10px/1 var(--fdc-font); }.sr-only { position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0; }
|
|
1154
1043
|
.motion-list { padding:0 12px 12px; }.motion-row { padding:12px 0;border-bottom:1px solid var(--fdc-line); }.motion-title { display:flex;justify-content:space-between;gap:12px;margin-bottom:9px;font-size:12px;font-weight:550; }.motion-title code { color:var(--fdc-muted);font:400 10px/1.3 var(--fdc-font); }.motion-actions { display:grid;grid-template-columns:repeat(4,1fr);gap:4px; }.motion-actions button { min-height:30px;padding:0 5px;border:1px solid var(--fdc-line);background:var(--fdc-paper);border-radius:5px;color:var(--fdc-ink);font-size:10px;font-weight:400;cursor:pointer; }.motion-actions button:hover { border-color:#c7c7c7;background:var(--fdc-surface); }
|
|
1155
1044
|
.motion-timeline { width:100%;margin:2px 0 10px;accent-color:var(--fdc-signal); }.motion-fields { display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-bottom:8px; }.motion-fields label { display:grid;grid-template-columns:auto 1fr;align-items:center;gap:5px;color:var(--fdc-muted);font-size:9px; }.motion-fields input { width:100%;height:28px;padding:0 6px;border:1px solid var(--fdc-line);border-radius:5px;background:var(--fdc-paper);color:var(--fdc-ink);font-size:10px; }
|
|
1156
1045
|
.empty { padding:48px 28px;text-align:center;color:var(--fdc-muted);font-size:13px;line-height:1.6; }.empty::before { content:"\u2316";display:grid;place-items:center;width:38px;height:38px;margin:0 auto 13px;color:var(--fdc-signal);background:var(--fdc-signal-soft);border-radius:10px;font:18px/1 var(--fdc-font); }
|
|
1157
1046
|
.change-dock { min-height:48px;display:grid;grid-template-columns:minmax(0,1fr) 30px 68px;align-items:center;gap:6px;padding:7px 8px;border-top:1px solid var(--fdc-line);background:white; }.change-dock[hidden] { display:none; }.change-dock-copy { min-width:0;padding-left:3px; }.change-dock-copy strong,.change-dock-copy span { display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }.change-dock-copy strong { font-size:10px;font-weight:550; }.change-dock-copy span { margin-top:3px;color:var(--fdc-muted);font-size:9px; }.change-dock button { height:30px;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:var(--fdc-ink);font-size:9px;cursor:pointer; }.change-dock .dock-review { color:white;border-color:var(--fdc-ink);background:var(--fdc-ink); }.change-dock svg { width:12px;height:12px; }.footer { display:grid;grid-template-columns:82px 1fr;gap:6px;padding:8px;background:var(--fdc-surface);border-top:1px solid var(--fdc-line); }.footer:has(.review[hidden]) { grid-template-columns:1fr; }.footer button[hidden] { display:none; }.footer button { min-height:36px;border:1px solid var(--fdc-line);border-radius:6px;background:var(--fdc-surface);color:var(--fdc-ink);font-size:11px;font-weight:450;cursor:pointer; }.footer button:hover { border-color:#d0d0d0;background:var(--fdc-paper); }.footer .review { align-items:center;justify-content:center;gap:7px;color:white;background:var(--fdc-ink);border-color:var(--fdc-ink); }.footer .review:not([hidden]) { display:flex; }.footer .review:hover { background:#2f2f2f; }.change-count { min-width:18px;height:18px;display:inline-grid;place-items:center;padding:0 5px;color:var(--fdc-ink);background:white;border-radius:999px;font:500 9px/1 var(--fdc-font); }.change-count[hidden] { display:none; }
|
|
1158
1047
|
.review-view { min-height:0;flex:1;display:none;flex-direction:column;background:var(--fdc-surface); }.panel.reviewing .selection,.panel.reviewing .scope,.panel.reviewing .controls,.panel.reviewing>.footer,.panel.reviewing>.change-dock { display:none; }.panel.reviewing .review-view { display:flex; }.review-head { min-height:48px;display:flex;align-items:center;gap:8px;padding:0 10px;border-bottom:1px solid var(--fdc-line); }.review-head button { width:30px;height:30px;display:grid;place-items:center;padding:0;border:0;border-radius:5px;background:transparent;color:var(--fdc-muted);cursor:pointer; }.review-head button:hover { background:var(--fdc-subtle);color:var(--fdc-ink); }.review-head svg { width:15px;height:15px; }.review-head strong { font-size:12px;font-weight:550; }.review-head span { margin-left:auto;color:var(--fdc-muted);font-size:10px; }.review-body { min-height:160px;overflow-x:hidden;overflow-y:auto; }.review-toolbar { position:sticky;top:0;z-index:1;display:flex;gap:5px;padding:7px 8px;border-bottom:1px solid var(--fdc-line);background:rgb(255 255 255 / 96%);backdrop-filter:blur(8px); }.review-toolbar button { height:27px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:#555;font-size:9px;cursor:pointer; }.review-toolbar button:last-child { margin-left:auto; }.review-empty { padding:42px 24px;color:var(--fdc-muted);font-size:12px;line-height:1.55;text-align:center; }.review-group { border-bottom:1px solid var(--fdc-line); }.review-group-title { width:100%;min-height:36px;display:flex;align-items:center;gap:7px;padding:0 12px;border:0;background:white;color:var(--fdc-muted);font-size:10px;font-weight:500;text-align:left;cursor:pointer; }.review-group-title span { margin-left:auto;font-size:9px; }.review-group-title svg { width:11px;height:11px;transition:transform .12s ease; }.review-group.collapsed .review-group-title svg { transform:rotate(-90deg); }.review-group.collapsed .review-card { display:none; }.review-card { display:grid;grid-template-columns:18px minmax(0,1fr);gap:8px;padding:9px 12px 10px; }.review-card.rejected { opacity:.62; }.review-card+.review-card { border-top:1px solid var(--fdc-line); }.review-card input[type="checkbox"] { width:14px;height:14px;margin:2px 0 0;accent-color:var(--fdc-ink); }.review-card-main { min-width:0; }.review-card-line { display:flex;align-items:center;gap:7px; }.review-card-line strong { min-width:0;overflow:hidden;text-overflow:ellipsis;font-size:11px;font-weight:500;white-space:nowrap; }.review-card-tools { display:flex;gap:3px;margin-left:auto; }.review-card-tools button { height:23px;padding:0 6px;border:1px solid var(--fdc-line);border-radius:4px;background:white;color:#666;font-size:8px;cursor:pointer; }.confidence-pill { flex:none;padding:3px 5px;border-radius:4px;background:#edf6ff;color:#0761d1;font-size:9px;text-transform:capitalize; }.confidence-pill.unresolved { color:#984a2b;background:#fff0e8; }.review-values { display:grid;grid-template-columns:minmax(0,1fr) 12px minmax(0,1fr);align-items:center;gap:4px;margin-top:7px; }.review-before { overflow:hidden;text-overflow:ellipsis;padding:7px;color:var(--fdc-muted);background:var(--fdc-subtle);border-radius:4px;font-size:10px;white-space:nowrap; }.review-values>span { color:var(--fdc-muted);font-size:10px;text-align:center; }.review-after { width:100%;height:28px;min-width:0;padding:0 7px;border:1px solid var(--fdc-line);border-radius:4px;background:white;font-size:10px;outline:none; }.review-after:focus { border-color:var(--fdc-signal);box-shadow:0 0 0 2px rgb(0 112 243 / 10%); }.review-source { margin-top:6px;overflow-wrap:anywhere;color:var(--fdc-muted);font-size:9px;line-height:1.45; }.review-actions { display:grid;grid-template-columns:82px 1fr;gap:6px;padding:8px;border-top:1px solid var(--fdc-line); }.review-actions button { min-height:36px;border:1px solid var(--fdc-line);border-radius:6px;background:white;font-size:11px;cursor:pointer; }.review-actions .apply { color:white;background:var(--fdc-ink);border-color:var(--fdc-ink); }.review-actions button:disabled { opacity:.45;cursor:not-allowed; }.run-summary { padding:14px 12px;border-bottom:1px solid var(--fdc-line); }.run-state { display:flex;align-items:center;gap:8px; }.run-state i { width:8px;height:8px;border-radius:50%;background:#a3a3a3; }.run-state i.active { background:var(--fdc-signal);box-shadow:0 0 0 4px rgb(0 112 243 / 10%); }.run-state i.passed { background:#2ca67f; }.run-state i.attention { background:#d16d51; }.run-state strong { font-size:12px;font-weight:550;text-transform:capitalize; }.run-summary p { margin:8px 0 0;color:var(--fdc-muted);font-size:10px;line-height:1.5; }.run-steps { padding:4px 12px 10px; }.run-step { display:grid;grid-template-columns:18px minmax(0,1fr);gap:7px;padding:8px 0;border-bottom:1px solid var(--fdc-line); }.run-step:last-child { border-bottom:0; }.run-step span:first-child { color:var(--fdc-muted);font-size:10px; }.run-step strong { display:block;font-size:10px;font-weight:500;text-transform:capitalize; }.run-step p { margin:3px 0 0;color:var(--fdc-muted);font-size:9px;line-height:1.45; }.result-list { padding:0 12px 12px; }.result-row { display:flex;align-items:flex-start;justify-content:space-between;gap:8px;padding:8px 0;border-top:1px solid var(--fdc-line);font-size:10px; }.result-row span:last-child { color:var(--fdc-muted);text-align:right; }.result-row.pass span:first-child { color:#23715c; }.result-row.fail span:first-child { color:#a24d30; }.run-files { padding:0 12px 12px;color:var(--fdc-muted);font-size:9px;line-height:1.5; }.run-files code { display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
|
|
1159
1048
|
.toast { position:fixed;left:50%;bottom:76px;transform:translate(-50%,8px);padding:9px 12px;background:var(--fdc-ink);color:white;border-radius:6px;font-size:11px;font-weight:450;opacity:0;transition:.15s ease;pointer-events:none;white-space:nowrap;box-shadow:0 8px 20px rgb(0 0 0 / 16%); }.toast.show { opacity:1;transform:translate(-50%,0); }
|
|
1160
|
-
.resize-handle { position:absolute;width:9px;height:9px;border:1px solid
|
|
1049
|
+
.resize-handle { position:absolute;width:9px;height:9px;min-width:9px;min-height:9px;aspect-ratio:1;padding:0;border:1px solid #f0f1f3;border-radius:1px;background:var(--fdc-signal);box-shadow:0 1px 4px rgb(0 0 0 / 28%);appearance:none;pointer-events:auto;touch-action:none; }
|
|
1161
1050
|
.resize-handle[data-handle="n"]{top:-5px;left:calc(50% - 4px);cursor:ns-resize}.resize-handle[data-handle="s"]{bottom:-5px;left:calc(50% - 4px);cursor:ns-resize}.resize-handle[data-handle="e"]{right:-5px;top:calc(50% - 4px);cursor:ew-resize}.resize-handle[data-handle="w"]{left:-5px;top:calc(50% - 4px);cursor:ew-resize}.resize-handle[data-handle="ne"]{right:-5px;top:-5px;cursor:nesw-resize}.resize-handle[data-handle="nw"]{left:-5px;top:-5px;cursor:nwse-resize}.resize-handle[data-handle="se"]{right:-5px;bottom:-5px;cursor:nwse-resize}.resize-handle[data-handle="sw"]{left:-5px;bottom:-5px;cursor:nesw-resize}
|
|
1162
|
-
.panel-resizer { position:absolute;z-index:3;top:84px;bottom:0;left:-4px;width:8px;border:0;background:transparent;cursor:ew-resize;touch-action:none; }.panel-resizer::after { content:"";position:absolute;top:50%;left:3px;width:2px;height:28px;transform:translateY(-50%);border-radius:2px;background:#
|
|
1051
|
+
.panel-resizer { position:absolute;z-index:3;top:84px;bottom:0;left:-4px;width:8px;border:0;background:transparent;cursor:ew-resize;touch-action:none; }.panel-resizer::after { content:"";position:absolute;top:50%;left:3px;width:2px;height:28px;transform:translateY(-50%);border-radius:2px;background:#4a4a50;opacity:0;transition:opacity .12s ease; }.panel:hover .panel-resizer::after,.panel-resizer:focus-visible::after { opacity:1; }.radius-handle { position:absolute;top:7px;left:7px;width:10px;height:10px;min-width:10px;min-height:10px;aspect-ratio:1;padding:0;border:2px solid #f0f1f3;border-radius:50%;background:#ff4d8d;box-shadow:0 1px 4px rgb(0 0 0 / 28%);appearance:none;pointer-events:auto;cursor:nwse-resize;touch-action:none; }
|
|
1163
1052
|
.canvas-variant { position:fixed;z-index:2147483645;height:27px;max-width:180px;padding:0 25px 0 8px;border:1px solid #b8d5ff;border-radius:6px;background:white;color:#075fc5;font-size:9px;box-shadow:0 5px 14px rgb(0 0 0 / 10%);pointer-events:auto; }.canvas-variant[hidden] { display:none; }
|
|
1164
1053
|
.onboarding-card { position:fixed;z-index:2147483647;left:50%;bottom:78px;width:286px;transform:translateX(-50%);padding:13px;border:1px solid var(--fdc-line);border-radius:10px;background:white;box-shadow:0 12px 32px rgb(0 0 0 / 14%);pointer-events:auto; }.onboarding-card[hidden] { display:none; }.onboarding-card-head { display:flex;align-items:center;gap:8px; }.onboarding-card-head svg { width:15px;height:15px;color:var(--fdc-signal); }.onboarding-card-head strong { font-size:11px;font-weight:550; }.onboarding-card p { margin:8px 0 11px;color:var(--fdc-muted);font-size:10px;line-height:1.5; }.onboarding-steps { display:grid;grid-template-columns:repeat(3,1fr);gap:5px; }.onboarding-steps span { padding:7px 5px;border:1px solid var(--fdc-line);border-radius:6px;color:#555;font-size:9px;line-height:1.35;text-align:center; }.onboarding-actions { display:flex;justify-content:flex-end;gap:5px;margin-top:10px; }.onboarding-actions button { height:28px;padding:0 9px;border:1px solid var(--fdc-line);border-radius:5px;background:white;font-size:9px;cursor:pointer; }.onboarding-actions .onboarding-start { color:white;border-color:var(--fdc-ink);background:var(--fdc-ink); }
|
|
1165
1054
|
.review-details { margin-top:7px;color:var(--fdc-muted);font-size:9px; }.review-details summary { cursor:pointer;user-select:none; }.review-details[open] summary { margin-bottom:5px; }.review-details .review-source { display:block; }.review-details .impact-list { display:grid;gap:3px;margin-top:5px; }
|
|
@@ -1173,7 +1062,7 @@ var PANEL_CSS = `
|
|
|
1173
1062
|
.selection-path { display:flex;align-items:center;gap:4px;margin-top:9px;min-width:0; }.selection-path button { min-width:0;height:25px;display:flex;align-items:center;gap:4px;padding:0 7px;border:1px solid var(--fdc-line);border-radius:5px;background:var(--fdc-paper);color:#555;font-size:9px;cursor:pointer; }.selection-path button:hover { color:var(--fdc-ink);border-color:#d2d2d2;background:white; }.selection-path button:disabled { opacity:.4;cursor:default; }.selection-path svg { width:11px;height:11px; }.selection-path .path-name { flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
|
|
1174
1063
|
.selection-path[hidden] { display:none; }
|
|
1175
1064
|
.layers-panel { position:fixed;z-index:2147483646;top:12px;left:12px;width:252px;max-height:calc(100vh - 24px);display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--fdc-line);border-radius:10px;background:var(--fdc-surface);box-shadow:0 1px 2px rgb(0 0 0 / 5%),0 10px 28px rgb(0 0 0 / 10%);pointer-events:auto; }.layers-panel[hidden] { display:none; }.layers-head { min-height:44px;display:flex;align-items:center;gap:8px;padding:0 8px 0 12px;border-bottom:1px solid var(--fdc-line); }.layers-head svg { width:15px;height:15px; }.layers-head strong { font-size:12px;font-weight:550; }.layers-head span { color:var(--fdc-muted);font-size:9px; }.layers-head .icon-button { margin-left:auto; }.layers-search { padding:8px;border-bottom:1px solid var(--fdc-line);background:var(--fdc-paper); }.layers-search input { width:100%;height:30px;padding:0 9px;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:var(--fdc-ink);font-size:10px;outline:none; }.layers-search input:focus { border-color:var(--fdc-signal);box-shadow:0 0 0 2px rgb(0 112 243 / 10%); }.layer-tree { min-height:120px;overflow:auto;padding:5px; }.layer-row { width:100%;height:30px;display:grid;grid-template-columns:14px 14px minmax(0,1fr) auto;align-items:center;gap:4px;padding:0 7px 0 calc(7px + var(--layer-depth) * 12px);border:0;border-radius:5px;background:transparent;color:#474747;text-align:left;cursor:pointer; }.layer-row:hover { background:var(--fdc-subtle); }.layer-row.selected { color:#075fc5;background:#eaf3ff; }.layer-row .chevron,.layer-row .layer-icon { width:12px;height:12px;color:#8a8a8a; }.layer-row .layer-label { overflow:hidden;text-overflow:ellipsis;font-size:10px;white-space:nowrap; }.layer-row .layer-meta { padding:2px 4px;border-radius:3px;background:#f0f0f0;color:#747474;font-size:8px;text-transform:uppercase; }.layer-row.selected .layer-meta { color:#075fc5;background:#d8e9ff; }.layers-empty { padding:34px 18px;color:var(--fdc-muted);font-size:10px;line-height:1.5;text-align:center; }
|
|
1176
|
-
.layers-switch { display:grid;grid-template-columns:1fr 1fr;gap:3px;padding:5px;border-bottom:1px solid var(--fdc-line);background:var(--fdc-paper); }.layers-switch button { min-width:0;height:28px;display:flex;align-items:center;justify-content:center;gap:6px;padding:0 7px;border:0;border-radius:5px;background:transparent;color:var(--fdc-muted);font-size:10px;cursor:pointer; }.layers-switch button:hover { color:var(--fdc-ink);background:white; }.layers-switch button.active { color:var(--fdc-ink);background:white;box-shadow:0 0 0 1px var(--fdc-line),0 1px 2px rgb(0 0 0 / 5%); }.layers-switch button span { min-width:17px;height:17px;display:grid;place-items:center;padding:0 4px;border-radius:999px;background:var(--fdc-subtle);color:#747474;font-size:8px; }.layers-switch button[data-layer-view="components"].active { color:#5f46bf; }.layers-switch button[data-layer-view="components"].active span { color:#5f46bf;background:var(--fdc-component-soft); }.component-list { display:grid;gap:5px;padding:2px; }.component-card { overflow:hidden;border:1px solid var(--fdc-line);border-radius:7px;background:white; }.component-card:hover { border-color:#d7d0f3;box-shadow:0 2px 8px rgb(52 38 110 / 6%); }.component-card.selected { border-color:#c8bdf1;background:#fbfaff;box-shadow:0 0 0 2px rgb(114 87 217 / 8%); }.component-main { width:100%;min-height:52px;display:grid;grid-template-columns:30px minmax(0,1fr) auto;align-items:center;gap:7px;padding:7px 8px;border:0;background:transparent;color:var(--fdc-ink);text-align:left;cursor:pointer; }.component-main:disabled { cursor:default; }.component-mark { width:28px;height:28px;display:grid;place-items:center;border-radius:7px;color:var(--fdc-component);background:var(--fdc-component-soft); }.component-mark svg { width:14px;height:14px;
|
|
1065
|
+
.layers-switch { display:grid;grid-template-columns:1fr 1fr;gap:3px;padding:5px;border-bottom:1px solid var(--fdc-line);background:var(--fdc-paper); }.layers-switch button { min-width:0;height:28px;display:flex;align-items:center;justify-content:center;gap:6px;padding:0 7px;border:0;border-radius:5px;background:transparent;color:var(--fdc-muted);font-size:10px;cursor:pointer; }.layers-switch button:hover { color:var(--fdc-ink);background:white; }.layers-switch button.active { color:var(--fdc-ink);background:white;box-shadow:0 0 0 1px var(--fdc-line),0 1px 2px rgb(0 0 0 / 5%); }.layers-switch button span { min-width:17px;height:17px;display:grid;place-items:center;padding:0 4px;border-radius:999px;background:var(--fdc-subtle);color:#747474;font-size:8px; }.layers-switch button[data-layer-view="components"].active { color:#5f46bf; }.layers-switch button[data-layer-view="components"].active span { color:#5f46bf;background:var(--fdc-component-soft); }.component-list { display:grid;gap:5px;padding:2px; }.component-card { overflow:hidden;border:1px solid var(--fdc-line);border-radius:7px;background:white; }.component-card:hover { border-color:#d7d0f3;box-shadow:0 2px 8px rgb(52 38 110 / 6%); }.component-card.selected { border-color:#c8bdf1;background:#fbfaff;box-shadow:0 0 0 2px rgb(114 87 217 / 8%); }.component-main { width:100%;min-height:52px;display:grid;grid-template-columns:30px minmax(0,1fr) auto;align-items:center;gap:7px;padding:7px 8px;border:0;background:transparent;color:var(--fdc-ink);text-align:left;cursor:pointer; }.component-main:disabled { cursor:default; }.component-mark { width:28px;height:28px;display:grid;place-items:center;border-radius:7px;color:var(--fdc-component);background:var(--fdc-component-soft); }.component-mark svg { width:14px;height:14px; }.component-copy { min-width:0; }.component-copy strong,.component-copy span { display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }.component-copy strong { font-size:10px;font-weight:550; }.component-copy span { margin-top:4px;color:var(--fdc-muted);font-size:8px; }.component-status { display:flex;flex-direction:column;align-items:flex-end;gap:4px; }.component-status span { padding:2px 5px;border-radius:999px;color:#5f46bf;background:var(--fdc-component-soft);font-size:8px;white-space:nowrap; }.component-status small { color:#8b8b8b;font-size:8px;white-space:nowrap; }.component-variants { display:flex;gap:4px;overflow:hidden;padding:0 8px 8px 45px; }.component-variants span { max-width:88px;overflow:hidden;text-overflow:ellipsis;padding:3px 5px;border:1px solid #e6e1f7;border-radius:4px;color:#66598c;background:#faf9ff;font-size:8px;white-space:nowrap; }
|
|
1177
1066
|
.layer-row { grid-template-columns:16px minmax(0,1fr);gap:1px;padding-right:4px;cursor:default; }.layer-row.dragging { opacity:.45; }.layer-row.drop-target { box-shadow:inset 0 2px 0 var(--fdc-signal); }.layer-spacer { width:1px;pointer-events:none; }.layer-toggle { width:16px;height:28px;display:grid;place-items:center;padding:0;border:0;background:transparent;color:#858585;cursor:pointer; }.layer-toggle:disabled { visibility:hidden; }.layer-toggle svg { width:11px;height:11px; }.layer-select { min-width:0;height:28px;display:grid;grid-template-columns:14px minmax(0,1fr) auto;align-items:center;gap:5px;padding:0 4px;border:0;background:transparent;color:inherit;text-align:left;cursor:pointer; }
|
|
1178
1067
|
.health-panel { position:fixed;z-index:2147483646;top:12px;left:12px;width:304px;max-height:calc(100vh - 24px);display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--fdc-line);border-radius:10px;background:var(--fdc-surface);box-shadow:0 1px 2px rgb(0 0 0 / 5%),0 10px 28px rgb(0 0 0 / 10%);pointer-events:auto; }.health-panel[hidden] { display:none; }.health-head { min-height:48px;display:flex;align-items:center;gap:8px;padding:0 8px 0 12px;border-bottom:1px solid var(--fdc-line); }.health-head>svg { width:15px;height:15px; }.health-head strong { font-size:12px;font-weight:550; }.health-head .icon-button { margin-left:auto; }.health-summary { display:grid;grid-template-columns:54px minmax(0,1fr);gap:10px;padding:12px;border-bottom:1px solid var(--fdc-line); }.health-score { width:54px;height:54px;display:grid;place-items:center;border-radius:50%;background:conic-gradient(var(--score-color) calc(var(--score) * 1%),#ececec 0); }.health-score::before { content:"";grid-area:1/1;width:42px;height:42px;border-radius:50%;background:white; }.health-score strong { z-index:1;grid-area:1/1;font-size:15px;font-weight:600; }.health-summary-copy { min-width:0;align-self:center; }.health-summary-copy strong { display:block;font-size:11px;font-weight:550; }.health-summary-copy span { display:block;margin-top:4px;color:var(--fdc-muted);font-size:9px;line-height:1.4; }.health-filters { display:flex;gap:4px;padding:7px 8px;border-bottom:1px solid var(--fdc-line);background:var(--fdc-paper); }.health-filters button { min-height:27px;padding:0 8px;border:1px solid transparent;border-radius:5px;background:transparent;color:#666;font-size:9px;cursor:pointer; }.health-filters button:hover,.health-filters button.active { border-color:var(--fdc-line);background:white;color:var(--fdc-ink); }.health-list { min-height:120px;overflow:auto;padding:6px; }.health-card { padding:10px;border:1px solid var(--fdc-line);border-radius:7px;background:white; }.health-card+.health-card { margin-top:6px; }.health-card-top { display:flex;align-items:center;gap:6px; }.health-severity { width:7px;height:7px;flex:none;border-radius:50%;background:#a3a3a3; }.health-severity.high { background:#d15d43; }.health-severity.medium { background:#d69b3c; }.health-severity.low { background:#4b84cb; }.health-card-top strong { min-width:0;overflow:hidden;text-overflow:ellipsis;font-size:10px;font-weight:550;white-space:nowrap; }.health-card-top span:last-child { margin-left:auto;color:var(--fdc-muted);font-size:8px;text-transform:capitalize; }.health-card p { margin:7px 0 0;color:#5d5d5d;font-size:9px;line-height:1.45; }.health-evidence { margin-top:6px;padding:6px;border-radius:4px;background:var(--fdc-paper);color:#777;font-size:8px;line-height:1.4; }.health-actions { display:flex;gap:5px;margin-top:8px; }.health-actions button { min-height:27px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:#555;font-size:9px;cursor:pointer; }.health-actions button:hover { border-color:#c8c8c8;color:var(--fdc-ink); }.health-actions .health-fix { margin-left:auto;color:white;border-color:var(--fdc-ink);background:var(--fdc-ink); }.health-actions .health-fix.previewed { color:#23715c;border-color:#bcded2;background:#edf8f4;cursor:default; }.health-actions .health-fix:disabled { opacity:1; }.health-actions .health-ignore { padding:0 6px;color:#888;border-color:transparent; }.health-footer { display:flex;align-items:center;gap:5px;padding:8px;border-top:1px solid var(--fdc-line); }.health-footer button { min-height:30px;padding:0 9px;border:1px solid var(--fdc-line);border-radius:5px;background:white;color:#555;font-size:9px;cursor:pointer; }.health-footer .health-rescan { flex:1;color:white;border-color:var(--fdc-ink);background:var(--fdc-ink); }.health-empty { padding:36px 18px;text-align:center;color:var(--fdc-muted);font-size:10px;line-height:1.5; }.health-empty svg { display:block;width:22px;height:22px;margin:0 auto 10px;color:#2b9a76; }
|
|
1179
1068
|
.tool-select:disabled { color:#b6b6b6;cursor:default; }.tool-select:disabled:hover { background:transparent; }
|
|
@@ -1194,7 +1083,115 @@ var PANEL_CSS = `
|
|
|
1194
1083
|
.component-actions { display:flex;gap:4px;padding:0 8px 8px 45px; }.component-actions button,.component-variants button { height:24px;padding:0 6px;border:1px solid #e6e1f7;border-radius:4px;color:#66598c;background:#faf9ff;font-size:8px;cursor:pointer; }.component-actions button:hover,.component-variants button:hover { border-color:#c8bdf1;background:#f4f0ff; }
|
|
1195
1084
|
.token-provenance { grid-column:2;display:flex;align-items:center;gap:5px;margin-top:5px;color:#23715c;font-size:8px; }.token-provenance.literal { color:#985033; }.token-provenance::before { content:"";width:5px;height:5px;border-radius:50%;background:currentColor; }
|
|
1196
1085
|
.workbench-matrix[hidden] { display:none; }
|
|
1197
|
-
|
|
1086
|
+
/* Foundry dark instrument theme */
|
|
1087
|
+
.panel,.layers-panel,.health-panel,.library-panel,.tool-shelf,.onboarding-card,.compare-bar,.command-palette,.status-popover,.canvas-variant { color:var(--fdc-ink);background:var(--fdc-surface);border-color:var(--fdc-line);box-shadow:0 1px 2px rgb(0 0 0 / 24%),0 14px 36px rgb(0 0 0 / 36%); }
|
|
1088
|
+
.top,.top-actions,.selection,.scope,.controls,.property-section,.change-dock,.footer,.review-view,.review-head,.review-group,.review-group-title,.review-actions,.layers-head,.layer-tree,.health-head,.health-list,.health-footer,.library-head,.library-actions,.library-body,.memory-card,.context-tools,.native-panel { color:var(--fdc-ink);background:var(--fdc-surface);border-color:var(--fdc-line); }
|
|
1089
|
+
.inspector-heading,.review-toolbar { background:rgb(28 28 31 / 96%);border-color:var(--fdc-line); }
|
|
1090
|
+
.section-head,.section-head:hover,.onboarding-step { color:var(--fdc-ink);background:var(--fdc-surface); }
|
|
1091
|
+
.icon-button,.tool-select,.tab,.section-toggle,.review-head button,.review-group-title,.compare-bar button { color:var(--fdc-muted); }
|
|
1092
|
+
.icon-button:hover,.review-head button:hover,.section-head:hover,.layer-row:hover,.command-item:hover,.command-item.active { color:var(--fdc-ink);background:var(--fdc-subtle); }
|
|
1093
|
+
.tool-select.active,.tab.active { color:var(--fdc-ink);background:#34343a; }.tool-select.inspect.active { color:white;background:var(--fdc-signal); }
|
|
1094
|
+
.icon-button.active,.section-head .section-action.active,.context-tools button.active { color:#9ec5ff;background:var(--fdc-signal-soft);border-color:#315482; }
|
|
1095
|
+
.tool-select::after,.tab::after { color:#141416;background:#f0f1f3;border:1px solid #ffffff; }
|
|
1096
|
+
.selection-kind,.selection-stats span,.layer-badge { color:#c8c8ce;background:var(--fdc-subtle); }.selection-stats span:first-child { color:#86b7ff;background:var(--fdc-signal-soft); }
|
|
1097
|
+
.selection-path button,.control-field,.native-search,.layers-search input,.review-after,.review-toolbar button,.review-card-tools button,.review-actions button,.change-dock button,.footer button,.status-popover button,.health-actions button,.health-footer button,.context-tools button,.native-chip,.variant-button,.library-actions button,.memory-card-actions button,.empty-state-actions button,.onboarding-actions button { color:var(--fdc-ink);background:var(--fdc-elevated);border-color:var(--fdc-line); }
|
|
1098
|
+
.selection-path button:hover,.control-field:hover,.footer button:hover { color:var(--fdc-ink);background:#303036;border-color:#494950; }
|
|
1099
|
+
.scope select,.property-control input,.property-control select,.compact-control input,.compact-control select,.native-search,.command-palette input { color:var(--fdc-ink);background:var(--fdc-paper);border-color:var(--fdc-line); }
|
|
1100
|
+
.scope select option,.property-control select option,.compact-control select option { color:var(--fdc-ink);background:var(--fdc-paper); }
|
|
1101
|
+
.property-label,.section-head,.color-value,.layer-row,.command-item,.library-section-head { color:#d1d1d6; }.field-prefix,.unit,.control-field .unit-select,.section-toggle>svg,.layer-row .chevron,.layer-row .layer-icon,.command-item svg,.command-item small { color:var(--fdc-muted); }
|
|
1102
|
+
.layer-row.selected { color:#a9cbff;background:var(--fdc-signal-soft); }.layer-row.selected .layer-icon { color:#86b7ff; }
|
|
1103
|
+
.layer-row .layer-meta { color:#b5b5bc;background:var(--fdc-elevated); }.layer-row.selected .layer-meta { color:#a9cbff;background:#23416d; }
|
|
1104
|
+
.layers-search { background:var(--fdc-paper); }.layers-switch { background:var(--fdc-paper);border-color:var(--fdc-line); }.layers-switch button { color:var(--fdc-muted);background:transparent; }.layers-switch button:hover,.layers-switch button.active { color:var(--fdc-ink);background:var(--fdc-elevated); }.layers-switch button[data-layer-view="components"].active,.layers-switch button[data-layer-view="components"].active span { color:#c1b5f5;background:var(--fdc-component-soft); }
|
|
1105
|
+
.token-chip { color:#d1d1d6;background:var(--fdc-paper);border-color:var(--fdc-line); }.token-chip:hover { color:#9ec5ff;background:var(--fdc-signal-soft);border-color:#315482; }
|
|
1106
|
+
.review-summary { background:var(--fdc-paper); }.review-before { color:var(--fdc-muted);background:var(--fdc-subtle); }.review-sample { color:var(--fdc-muted);background:var(--fdc-paper);border-color:var(--fdc-line); }.review-sample::after { color:var(--fdc-muted);background:rgb(28 28 31 / 88%); }
|
|
1107
|
+
.confidence-pill { color:#9ec5ff;background:var(--fdc-signal-soft); }.confidence-pill.unresolved { color:#f2ae8f;background:#42271d; }
|
|
1108
|
+
.session-status,.session-status.saved { color:#83d8bb;background:#18352c; }.session-status.saving { color:#efd979;background:#3d3417; }.session-status.error,.session-status.offline { color:#f0a18b;background:#40251f; }
|
|
1109
|
+
.empty-state-icon { color:#9ec5ff;background:var(--fdc-signal-soft); }.onboarding-card-head span { color:#e7a68c;background:#36231d; }
|
|
1110
|
+
.change-count { color:var(--fdc-ink);background:var(--fdc-paper); }
|
|
1111
|
+
.change-dock .dock-review,.footer .review,.review-actions .apply,.onboarding-actions .onboarding-start,.health-actions .health-fix,.health-footer .health-rescan,.memory-card-actions button:first-child,.empty-state-actions button:first-child { color:#141416;background:#f0f1f3;border-color:#f0f1f3; }.change-dock .dock-review:hover,.footer .review:hover,.review-actions .apply:hover { color:#141416;background:#ffffff; }
|
|
1112
|
+
.panel-resizer::after { background:#4a4a50; }
|
|
1113
|
+
.empty-state { min-height:220px;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:36px 30px;text-align:center; }.empty-state-icon { width:38px;height:38px;display:grid;place-items:center;margin-bottom:14px;border-radius:10px; }.empty-state-icon svg { width:16px;height:16px; }.empty-state strong { font-size:13px;font-weight:550;letter-spacing:-.01em; }.empty-state p { max-width:230px;margin:7px 0 0;color:var(--fdc-muted);font-size:11px;line-height:1.55; }.empty-state-actions { display:flex;align-items:center;gap:6px;margin-top:16px; }.empty-state-actions button { height:30px;padding:0 10px;border:1px solid var(--fdc-line);border-radius:6px;font-size:10px;cursor:pointer; }.empty-state kbd { margin-top:12px;color:var(--fdc-muted);font:400 9px/1.4 var(--fdc-font); }
|
|
1114
|
+
.review-head strong { font-size:13px; }.review-summary { padding:13px 14px 12px;border-bottom:1px solid var(--fdc-line);background:#fcfcfc; }.review-summary strong { display:block;font-size:12px;font-weight:550;letter-spacing:-.01em; }.review-summary span { display:block;margin-top:4px;color:var(--fdc-muted);font-size:10px;line-height:1.45; }.review-summary.attention strong { color:#8b4d3d; }.review-toolbar button { height:28px;padding:0 9px;font-size:10px; }
|
|
1115
|
+
.onboarding-card { bottom:82px;width:340px;padding:16px;border-radius:12px;box-shadow:0 14px 38px rgb(0 0 0 / 15%); }.onboarding-card-head { gap:9px; }.onboarding-card-head span { width:26px;height:26px;display:grid;place-items:center;color:#a75031;background:#fbf1ed;border-radius:7px; }.onboarding-card-head svg { width:14px;height:14px;color:inherit; }.onboarding-card-head strong { font-size:13px;letter-spacing:-.015em; }.onboarding-card>p { margin:9px 0 14px;font-size:11px;line-height:1.55; }.onboarding-steps { display:grid;grid-template-columns:1fr;gap:1px;border:1px solid var(--fdc-line);border-radius:8px;overflow:hidden;background:var(--fdc-line); }.onboarding-step { display:grid;grid-template-columns:24px 1fr;gap:9px;padding:9px 10px;background:white;text-align:left; }.onboarding-step b { color:#8a8a8a;font-size:9px;font-weight:500;letter-spacing:.04em; }.onboarding-step strong { display:block;font-size:10px;font-weight:550; }.onboarding-step small { display:block;margin-top:2px;color:var(--fdc-muted);font-size:9px;line-height:1.35; }.onboarding-actions { gap:6px;margin-top:13px; }.onboarding-actions button { height:32px;padding:0 11px;border-radius:6px;font-size:10px; }
|
|
1116
|
+
.onboarding-card,.onboarding-step { color:var(--fdc-ink);background:var(--fdc-surface); }.onboarding-card-head span { color:#e7a68c;background:#36231d; }.onboarding-actions button { color:var(--fdc-ink);background:var(--fdc-elevated);border-color:var(--fdc-line); }.onboarding-actions .onboarding-start { color:#141416;background:#f0f1f3;border-color:#f0f1f3; }
|
|
1117
|
+
.review-summary { color:var(--fdc-ink);background:var(--fdc-paper); }.empty-state-icon { color:#9ec5ff;background:var(--fdc-signal-soft); }
|
|
1118
|
+
.component-card,.health-card { color:var(--fdc-ink);background:var(--fdc-surface);border-color:var(--fdc-line); }.component-card.selected { color:var(--fdc-ink);background:var(--fdc-component-soft);border-color:#5c4b9e;box-shadow:0 0 0 2px rgb(155 135 245 / 10%); }.component-variants span,.component-actions button,.component-variants button { color:#c1b5f5;background:var(--fdc-component-soft);border-color:#4a406f; }.health-score::before { background:var(--fdc-surface); }.health-filters button { color:var(--fdc-muted); }.health-filters button:hover,.health-filters button.active { color:var(--fdc-ink);background:var(--fdc-elevated);border-color:var(--fdc-line); }.health-card p,.health-evidence { color:var(--fdc-muted); }.mapping-chooser { color:#f0c9a8;background:#35291d;border-color:#665039; }.mapping-chooser>strong,.mapping-option,.mapping-option small { color:#e7c29f; }.review-card.locating { background:var(--fdc-signal-soft); }.baseline-badge { color:#83d8bb;background:#18352c; }
|
|
1119
|
+
/* Workspace ownership */
|
|
1120
|
+
.workspace-bar { position:fixed;z-index:2147483647;top:12px;left:50%;min-height:48px;display:flex;align-items:center;gap:5px;padding:6px;transform:translateX(-50%);color:var(--fdc-ink);background:rgb(28 28 31 / 96%);border:1px solid var(--fdc-line);border-radius:12px;box-shadow:0 2px 2px rgb(0 0 0 / 20%),0 14px 34px rgb(0 0 0 / 34%);backdrop-filter:blur(14px);pointer-events:auto; }.workspace-bar .brand { flex:none;padding:0 7px; }.workspace-bar .brand-copy b { font-size:12px; }.workspace-bar .session-status { margin:0; }.workspace-actions { display:flex;align-items:center;gap:2px; }.workspace-divider { width:1px;height:24px;background:var(--fdc-line); }.workspace-bar .icon-button { width:34px;height:34px; }.workspace-bar .icon-button.active { color:#9ec5ff;background:var(--fdc-signal-soft); }.workspace-bar .status-popover { top:44px;right:auto;left:58px; }
|
|
1121
|
+
.panel { top:72px;bottom:12px;max-height:none;overflow:clip; }.panel[hidden] { display:none; }.inspector-head { min-height:44px;display:flex;align-items:center;gap:7px;padding:0 8px 0 13px;border-bottom:1px solid var(--fdc-line);background:var(--fdc-surface); }.inspector-head strong { font-size:12px;font-weight:550; }.inspector-head span { color:var(--fdc-muted);font-size:9px; }.inspector-head .icon-button { margin-left:auto; }.controls { min-height:0;flex:1; }.inspector-baseline { padding:0 12px 8px;border-bottom:1px solid var(--fdc-line); }.inspector-category { border-bottom:1px solid var(--fdc-line); }.inspector-category>.inspector-heading { position:sticky;top:0;z-index:2;height:44px;padding:0 8px 0 4px;background:rgb(28 28 31 / 97%); }.inspector-category>.inspector-heading .section-toggle { min-height:43px; }.inspector-category>.inspector-heading .section-toggle>svg { width:15px;height:15px;color:var(--fdc-muted);transform:none; }.inspector-category.collapsed>.category-body { display:none; }.inspector-category.collapsed>.inspector-heading .section-toggle>svg { transform:rotate(-90deg); }.inspector-category .property-section { margin-left:10px;border-left:1px solid var(--fdc-line); }.inspector-category .property-section .section-head { padding-left:6px; }.inspector-category[data-category="position"]>.category-body>.property-section>.section-head { display:none; }.category-body>.context-tools,.category-body>.native-panel,.category-body>.design-health { margin-left:10px; }
|
|
1122
|
+
.inspector-scroll { min-width:0;min-height:0;flex:1;overflow-x:hidden;overflow-y:auto;background:var(--fdc-surface); }
|
|
1123
|
+
.inspector-scroll::-webkit-scrollbar { width:6px; }
|
|
1124
|
+
.inspector-scroll::-webkit-scrollbar-track { background:transparent; }
|
|
1125
|
+
.inspector-scroll::-webkit-scrollbar-thumb { background:#4a4a50;border-radius:999px; }
|
|
1126
|
+
.inspector-scroll::-webkit-scrollbar-thumb:hover { background:#626269; }
|
|
1127
|
+
.inspector-scroll>.selection,.inspector-scroll>.scope,.inspector-scroll>.controls { width:100%;box-sizing:border-box; }
|
|
1128
|
+
.inspector-scroll>.controls { min-height:0;overflow:visible;flex:none; }
|
|
1129
|
+
/* Fluid inspector controls */
|
|
1130
|
+
.inspector-category .property-section { width:100%;margin-left:0;border-left:0; }
|
|
1131
|
+
.inspector-category .property-section .section-head { padding-left:10px; }
|
|
1132
|
+
.category-body>.context-tools,.category-body>.native-panel { width:100%;margin-left:0; }
|
|
1133
|
+
.category-body>.design-health { width:auto;margin:12px 14px 0; }
|
|
1134
|
+
.section-grid { width:100%;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;padding:12px 14px 14px;box-sizing:border-box; }
|
|
1135
|
+
.section-grid.stacked { grid-template-columns:minmax(0,1fr); }
|
|
1136
|
+
.section-grid:not(.stacked)>:last-child:nth-child(odd) { grid-column:1/-1; }
|
|
1137
|
+
.property-control { min-width:0;display:flex;flex-direction:column;align-items:stretch;gap:6px; }
|
|
1138
|
+
.property-control .property-label { min-height:13px;line-height:13px; }
|
|
1139
|
+
.property-control .control-field { width:100%;height:34px; }
|
|
1140
|
+
.property-control input,.property-control select { height:32px; }
|
|
1141
|
+
.section-grid.two { grid-template-columns:repeat(2,minmax(0,1fr));gap:8px; }
|
|
1142
|
+
.section-grid.two .compact-control { position:relative;display:block; }
|
|
1143
|
+
.compact-control .field-prefix,.compact-control .field-prefix.wide { width:44px;min-width:44px;box-sizing:border-box;padding-left:10px; }
|
|
1144
|
+
.section-grid.two .control-field { width:100%;height:34px; }
|
|
1145
|
+
.section-grid.two .compact-control input,.section-grid.two .compact-control select { height:32px; }
|
|
1146
|
+
.control-field>.control-reset { position:absolute;z-index:2;top:4px;right:4px;width:24px;height:24px; }
|
|
1147
|
+
.control-field>input { padding-right:32px; }
|
|
1148
|
+
.control-field:has(>select:not(.unit-select))>.control-reset { right:30px; }
|
|
1149
|
+
.control-field:has(>select:not(.unit-select))>select:not(.unit-select) { padding-right:56px!important; }
|
|
1150
|
+
.control-field:has(>.unit-select)>.control-reset { right:49px; }
|
|
1151
|
+
.control-field:has(>.unit)>.control-reset { right:25px; }
|
|
1152
|
+
/* Consistent inset chevrons for every select input */
|
|
1153
|
+
select { -webkit-appearance:none;appearance:none;padding-right:30px!important;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='%238f8f96' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 6.5 3 3 3-3'/%3E%3C/svg%3E")!important;background-repeat:no-repeat!important;background-position:right 9px center!important;background-size:16px 16px!important; }
|
|
1154
|
+
.control-field .unit-select { width:48px;padding-right:20px!important;padding-left:3px!important;background-position:right 3px center!important;background-size:14px 14px!important; }
|
|
1155
|
+
.layers-panel { top:72px;bottom:12px;max-height:none; }.layers-panel[hidden] { display:none; }
|
|
1156
|
+
.utility-panel { z-index:2147483646;max-height:none;min-width:280px;min-height:280px;box-shadow:0 2px 2px rgb(0 0 0 / 22%),0 18px 48px rgb(0 0 0 / 42%); }.utility-panel[hidden] { display:none; }.utility-handle { cursor:grab;user-select:none;touch-action:none; }.utility-handle:active { cursor:grabbing; }.utility-resizer { position:absolute;right:2px;bottom:2px;width:18px;height:18px;padding:0;border:0;background:transparent;cursor:nwse-resize; }.utility-resizer::after { content:"";position:absolute;right:3px;bottom:3px;width:7px;height:7px;border-right:1px solid var(--fdc-muted);border-bottom:1px solid var(--fdc-muted); }.health-panel,.library-panel { right:auto;max-height:none; }.health-list,.library-body { min-height:0;flex:1; }
|
|
1157
|
+
.change-tray { position:fixed;z-index:2147483646;right:var(--fdc-canvas-right,376px);bottom:12px;left:var(--fdc-canvas-left,276px);min-height:0;display:flex;flex-direction:column;align-items:stretch;padding:0;overflow:hidden;color:var(--fdc-ink);background:var(--fdc-surface);border:1px solid var(--fdc-line);border-radius:11px;box-shadow:0 2px 2px rgb(0 0 0 / 22%),0 18px 48px rgb(0 0 0 / 36%);pointer-events:auto; }.change-tray[hidden] { display:none; }.change-tray-summary { min-height:48px;display:grid;grid-template-columns:minmax(0,1fr) auto 32px 72px;align-items:center;gap:7px;padding:6px 7px 6px 11px; }.change-tray-summary .change-count { margin-right:2px; }.change-tray-summary button { height:32px;border:1px solid var(--fdc-line);border-radius:6px;color:var(--fdc-ink);background:var(--fdc-elevated);cursor:pointer; }.change-tray-summary .tray-compare { width:32px;display:grid;place-items:center;padding:0; }.change-tray-summary .tray-compare svg { width:13px;height:13px; }.change-tray-summary button:disabled { opacity:.35;cursor:not-allowed; }.change-tray.expanded { height:min(420px,45vh); }.change-tray.expanded .change-tray-summary { border-bottom:1px solid var(--fdc-line); }.change-tray .review-view:not([hidden]) { min-width:0;min-height:0;display:flex; }.change-tray .review-body { min-height:0;flex:1;display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));align-content:start;overflow:auto; }.change-tray .review-group { min-width:0;border-right:1px solid var(--fdc-line); }.change-tray .review-actions { flex:none;grid-template-columns:100px minmax(180px,280px);justify-content:end; }.change-tray .review-head { flex:none; }.change-tray .review-head span { margin-left:auto; }
|
|
1158
|
+
/* Focused review list */
|
|
1159
|
+
.change-tray .review-body { display:block;overflow-x:hidden;overflow-y:auto; }
|
|
1160
|
+
.review-overview { position:sticky;top:0;z-index:3;display:flex;align-items:center;gap:12px;min-height:52px;padding:8px 12px;border-bottom:1px solid var(--fdc-line);background:rgb(20 20 22 / 97%);backdrop-filter:blur(10px); }
|
|
1161
|
+
.review-overview .review-summary { min-width:0;flex:1;padding:0;border:0;background:transparent; }
|
|
1162
|
+
.review-overview .review-summary strong { overflow:hidden;text-overflow:ellipsis;font-size:11px;white-space:nowrap; }
|
|
1163
|
+
.review-overview .review-summary span { overflow:hidden;text-overflow:ellipsis;margin-top:2px;font-size:9px;white-space:nowrap; }
|
|
1164
|
+
.review-overview .review-toolbar { position:static;z-index:auto;flex:none;padding:0;border:0;background:transparent;backdrop-filter:none; }
|
|
1165
|
+
.review-overview .review-toolbar button { height:28px;padding:0 8px;border-color:transparent;background:transparent;color:var(--fdc-muted);font-size:9px; }
|
|
1166
|
+
.review-overview .review-toolbar button:hover { color:var(--fdc-ink);background:var(--fdc-elevated);border-color:var(--fdc-line); }
|
|
1167
|
+
.change-tray .review-group { border-right:0;border-bottom:1px solid var(--fdc-line); }
|
|
1168
|
+
.change-tray .review-group-title { position:sticky;top:52px;z-index:2;min-height:38px;padding:0 12px;background:rgb(28 28 31 / 98%); }
|
|
1169
|
+
.review-group-title .included-count { font-size:9px; }
|
|
1170
|
+
.review-card { min-height:50px;grid-template-columns:18px minmax(0,1fr);align-items:start;gap:9px;padding:8px 12px; }
|
|
1171
|
+
.review-card input[type="checkbox"] { margin-top:7px; }
|
|
1172
|
+
.review-card-line { min-height:32px;display:grid;grid-template-columns:minmax(120px,1fr) auto minmax(220px,320px) 30px;align-items:center;gap:8px; }
|
|
1173
|
+
.review-card-line>strong { font-size:10px; }
|
|
1174
|
+
.review-values { min-width:0;display:grid;grid-template-columns:minmax(72px,1fr) 12px minmax(90px,1fr);align-items:center;gap:5px;margin:0; }
|
|
1175
|
+
.review-before { min-width:0;overflow:hidden;text-overflow:ellipsis;padding:0 8px;color:var(--fdc-muted);background:transparent;font-size:10px;text-align:right;white-space:nowrap; }
|
|
1176
|
+
.review-after { height:30px;font-size:10px; }
|
|
1177
|
+
.review-more { position:relative;justify-self:end; }
|
|
1178
|
+
.review-more>summary { width:28px;height:28px;display:grid;place-items:center;border:1px solid transparent;border-radius:5px;color:var(--fdc-muted);font:600 11px/1 var(--fdc-font);letter-spacing:1px;list-style:none;cursor:pointer; }
|
|
1179
|
+
.review-more>summary::-webkit-details-marker { display:none; }
|
|
1180
|
+
.review-more>summary:hover,.review-more[open]>summary { color:var(--fdc-ink);background:var(--fdc-elevated);border-color:var(--fdc-line); }
|
|
1181
|
+
.review-more .review-card-tools { position:absolute;z-index:5;right:0;top:32px;width:260px;display:flex;flex-direction:column;gap:2px;padding:4px;border:1px solid var(--fdc-line);border-radius:7px;background:var(--fdc-elevated);box-shadow:0 10px 24px rgb(0 0 0 / 34%); }
|
|
1182
|
+
.review-more .review-card-tools button { width:100%;height:27px;padding:0 7px;border:0;text-align:left;background:transparent; }
|
|
1183
|
+
.review-more .review-card-tools button:hover { background:var(--fdc-subtle); }
|
|
1184
|
+
.review-details { margin-top:3px;padding-top:3px;border-top:1px solid var(--fdc-line); }
|
|
1185
|
+
.review-details summary { min-height:27px;display:flex;align-items:center;padding:0 7px;color:var(--fdc-muted);font-size:8px;cursor:pointer; }
|
|
1186
|
+
.review-details[open] { padding-bottom:6px; }
|
|
1187
|
+
.review-details .review-source,.review-details .impact-list { padding-right:7px;padding-left:7px; }
|
|
1188
|
+
.review-visual { display:none; }
|
|
1189
|
+
@media (max-width:980px){.review-card-line{grid-template-columns:minmax(100px,1fr) auto minmax(190px,260px) 30px}.review-overview .review-summary span{display:none}}
|
|
1190
|
+
@media (max-width:760px){.review-card-line{grid-template-columns:minmax(0,1fr) auto 30px}.review-values{grid-column:1/-1;width:100%}.review-overview{align-items:flex-start}.review-overview .review-toolbar{margin-left:auto}.review-overview .review-toolbar button{padding:0 6px}}
|
|
1191
|
+
.tool-shelf { bottom:calc(18px + var(--fdc-tray-lift,0px)); }.tool-select[hidden],.tool-divider[hidden] { display:none; }.tool-select.interact.active { color:white;background:var(--fdc-signal); }.mode-copy { min-width:88px; }.canvas-actions-divider { margin-left:2px; }.multi-actions-divider { margin-left:2px; }
|
|
1192
|
+
.compare-bar { bottom:calc(78px + var(--fdc-tray-lift,0px)); }
|
|
1193
|
+
@keyframes fdc-selection-title { from { opacity:.45;transform:translateY(2px) } to { opacity:1;transform:none } }
|
|
1194
|
+
@media (max-width:680px){.workspace-bar{right:8px;left:8px;transform:none;overflow-x:auto}.workspace-bar .brand{padding-right:3px}.workspace-bar .brand-copy{display:none}.workspace-bar .status-popover{position:fixed;top:66px;right:8px;left:8px;width:auto}.panel{top:auto;right:8px;bottom:74px;left:8px;width:auto;max-height:56vh}.layers-panel{top:68px;right:8px;bottom:auto;left:8px;width:auto;max-height:42vh}.utility-panel{top:68px!important;right:8px!important;bottom:74px!important;left:8px!important;width:auto!important;height:auto!important;max-height:none}.utility-resizer{display:none}.scope{display:grid;grid-template-columns:1fr 1fr}.controls{min-height:170px}.change-tray{right:8px;bottom:8px;left:8px}.change-tray.expanded{height:48vh}.change-tray .review-body{grid-template-columns:1fr}.tool-shelf{right:8px;bottom:calc(8px + var(--fdc-tray-lift,0px));left:8px;transform:none;max-width:none}.mode-copy{min-width:0}.mode-copy span{display:none}.tool-select::after,.tab::after{display:none}.onboarding-card{right:12px;bottom:68px;left:12px;width:auto;transform:none}.workbench-controls select,.workbench-controls button:not(.icon-button){max-width:92px}.workbench-matrix{grid-template-columns:76px repeat(var(--matrix-columns),minmax(90px,1fr))}}
|
|
1198
1195
|
@media (prefers-reduced-motion:reduce){*{transition-duration:.01ms!important}}
|
|
1199
1196
|
`;
|
|
1200
1197
|
function numberFrom(value) {
|
|
@@ -1513,12 +1510,12 @@ function renderPropertyControl(control, index, prefix) {
|
|
|
1513
1510
|
"%"
|
|
1514
1511
|
].filter((unit) => unit !== control.unit).map((unit) => `<option>${unit}</option>`).join("")}</select>` : control.unit ? `<span class="unit">${control.unit}</span>` : "";
|
|
1515
1512
|
const field = `${renderControlInput(control, index)}${unitControl}`;
|
|
1516
|
-
const reset = `<button type="button" class="control-reset" data-reset-control="${index}" title="Reset ${escapeHtml(control.label)}" aria-label="Reset ${escapeHtml(control.label)}"><i data-
|
|
1513
|
+
const reset = `<button type="button" class="control-reset" data-reset-control="${index}" title="Reset ${escapeHtml(control.label)}" aria-label="Reset ${escapeHtml(control.label)}"><i data-foundry-icon="rotate-ccw"></i></button>`;
|
|
1517
1514
|
const scrubAttributes = control.kind === "number" ? ` data-scrub-for="${index}" title="Drag left or right to adjust ${escapeHtml(control.label)}. Hold Shift for larger steps or Option for finer steps."` : "";
|
|
1518
1515
|
if (prefix) {
|
|
1519
|
-
return `<label class="compact-control"><span class="sr-only">${escapeHtml(control.label)}</span><span class="control-field"><span class="field-prefix ${prefix.length > 2 ? "wide" : ""}"${scrubAttributes}>${escapeHtml(prefix)}</span>${field}
|
|
1516
|
+
return `<label class="compact-control"><span class="sr-only">${escapeHtml(control.label)}</span><span class="control-field"><span class="field-prefix ${prefix.length > 2 ? "wide" : ""}"${scrubAttributes}>${escapeHtml(prefix)}</span>${field}${reset}</span></label>`;
|
|
1520
1517
|
}
|
|
1521
|
-
return `<label class="property-control"><span class="property-label"${scrubAttributes}>${escapeHtml(control.label)}</span><span class="control-field">${field}
|
|
1518
|
+
return `<label class="property-control"><span class="property-label"${scrubAttributes}>${escapeHtml(control.label)}</span><span class="control-field">${field}${reset}</span></label>`;
|
|
1522
1519
|
}
|
|
1523
1520
|
function installFoundryInspector(options = {}) {
|
|
1524
1521
|
const query = new URLSearchParams(location.search);
|
|
@@ -1540,7 +1537,46 @@ function installFoundryInspector(options = {}) {
|
|
|
1540
1537
|
const host = document.createElement("div");
|
|
1541
1538
|
host.dataset.foundryOverlay = "true";
|
|
1542
1539
|
const shadow = host.attachShadow({ mode: "open" });
|
|
1543
|
-
shadow.innerHTML = `<style>${PANEL_CSS}</style
|
|
1540
|
+
shadow.innerHTML = `<style>${PANEL_CSS}</style>
|
|
1541
|
+
<div class="outline" hidden><span class="cross"></span><span class="measure"></span></div>
|
|
1542
|
+
<div class="hover-outline" hidden></div>
|
|
1543
|
+
<header class="workspace-bar" aria-label="Foundry workspace">
|
|
1544
|
+
<div class="brand"><span class="brand-copy"><b>Foundry</b></span></div>
|
|
1545
|
+
<span class="session-status"><i></i><span>Live</span></span>
|
|
1546
|
+
<span class="workspace-divider"></span>
|
|
1547
|
+
<nav class="workspace-actions" aria-label="Workspace destinations">
|
|
1548
|
+
<button class="icon-button toggle-layers" title="Toggle layers" aria-label="Toggle layers" aria-pressed="true"><i data-foundry-icon="layers-3"></i></button>
|
|
1549
|
+
<button class="icon-button toggle-inspector" title="Toggle inspector" aria-label="Toggle inspector" aria-pressed="true"><i data-foundry-icon="panels-top-left"></i></button>
|
|
1550
|
+
<button class="icon-button open-health" title="Design health" aria-label="Open design health" aria-pressed="false"><i data-foundry-icon="activity"></i></button>
|
|
1551
|
+
<button class="icon-button open-workbench" title="State workbench" aria-label="Open state workbench" aria-pressed="false"><i data-foundry-icon="play"></i></button>
|
|
1552
|
+
<button class="icon-button open-library" title="Design memory" aria-label="Open design memory" aria-pressed="false"><i data-foundry-icon="bookmark"></i></button>
|
|
1553
|
+
<button class="icon-button open-commands" title="Commands" aria-label="Open commands"><i data-foundry-icon="command"></i></button>
|
|
1554
|
+
</nav>
|
|
1555
|
+
<span class="workspace-divider"></span>
|
|
1556
|
+
<button class="icon-button close" title="Exit Foundry" aria-label="Exit Foundry"><i data-foundry-icon="x"></i></button>
|
|
1557
|
+
</header>
|
|
1558
|
+
<aside class="layers-panel" aria-label="Foundry layers" hidden>
|
|
1559
|
+
<div class="layers-head"><i data-foundry-icon="layers-3"></i><strong>Layers</strong><span data-layer-count></span><button class="icon-button close-layers" aria-label="Close layers"><i data-foundry-icon="x"></i></button></div>
|
|
1560
|
+
<div class="layers-search"><input type="search" aria-label="Search layers" placeholder="Search layers" /></div><div class="layer-tree"></div>
|
|
1561
|
+
</aside>
|
|
1562
|
+
<aside class="health-panel utility-panel" data-utility="health" aria-label="Design health" hidden>
|
|
1563
|
+
<div class="health-head utility-handle"><i data-foundry-icon="activity"></i><strong>Design health</strong><button class="icon-button close-health" aria-label="Close design health"><i data-foundry-icon="x"></i></button></div>
|
|
1564
|
+
<div class="health-summary"></div><div class="health-filters" role="group" aria-label="Filter design health issues"></div><div class="health-list"></div><div class="health-footer"><button class="health-show-ignored" hidden></button><button class="health-rescan">Scan again</button></div><button class="utility-resizer" aria-label="Resize design health"></button>
|
|
1565
|
+
</aside>
|
|
1566
|
+
<aside class="panel" aria-label="Foundry design inspector">
|
|
1567
|
+
<div class="inspector-head"><strong>Inspector</strong><span>Selection properties</span><button class="icon-button toggle-inspector inspector-collapse" aria-label="Close inspector"><i data-foundry-icon="x"></i></button></div>
|
|
1568
|
+
<div class="inspector-scroll">
|
|
1569
|
+
<div class="selection"><div class="selection-heading"><small class="selection-kind">No layer</small><span class="selection-state">Ready</span></div><strong>Nothing selected</strong><code>Click any element to inspect it</code><div class="selection-stats" hidden><span data-selection-size></span><span data-selection-confidence></span></div><div class="selection-path" hidden><button data-select-parent aria-label="Select parent layer"><i data-foundry-icon="chevron-right"></i><span>Parent</span></button><span class="path-name"></span><button data-select-child aria-label="Select first child layer"><span>Child</span><i data-foundry-icon="chevron-down"></i></button></div></div>
|
|
1570
|
+
<div class="scope"><label>Scope<select data-scope><option value="instance">Instance</option><option value="component">Component</option></select></label><label>Breakpoint<select data-breakpoint><option>current</option><option>mobile</option><option>tablet</option><option>desktop</option></select></label><label>Theme<select data-theme><option>current</option><option>light</option><option>dark</option></select></label></div>
|
|
1571
|
+
<div class="controls"><div class="empty">Select an element to inspect its measured design controls.</div></div>
|
|
1572
|
+
</div>
|
|
1573
|
+
</aside>
|
|
1574
|
+
<section class="change-dock change-tray" aria-label="Foundry changes" hidden>
|
|
1575
|
+
<div class="change-tray-summary"><div class="change-dock-copy"><strong data-dock-count>No changes</strong><span data-dock-last>Edits will appear here</span></div><span class="change-count" hidden>0</span><button class="tray-compare" title="Compare changes" aria-label="Compare changes" disabled><i data-foundry-icon="contrast"></i></button><button class="dock-review">Review</button></div>
|
|
1576
|
+
<div class="review-view" hidden><div class="review-head"><button class="review-back" aria-label="Collapse change tray"><i data-foundry-icon="chevron-down"></i></button><strong>Review and apply</strong><span class="review-count"></span></div><div class="review-body"></div><div class="review-actions"><button class="review-cancel">Collapse</button><button class="apply">Apply with agent</button></div></div>
|
|
1577
|
+
</section>
|
|
1578
|
+
<div class="tool-shelf" role="toolbar" aria-label="Canvas tools"><button class="tool-select inspect" data-tooltip="Select" title="Select: click any element" aria-label="Select mode" aria-pressed="true"><i data-foundry-icon="mouse-pointer-2"></i></button><button class="tool-select interact" data-tooltip="Interact" title="Interact with the app" aria-label="Interact mode" aria-pressed="false"><i data-foundry-icon="interact"></i></button></div>
|
|
1579
|
+
<div class="toast"></div>`;
|
|
1544
1580
|
document.body.append(host);
|
|
1545
1581
|
shadow.querySelector(".layers-search").insertAdjacentHTML(
|
|
1546
1582
|
"beforebegin",
|
|
@@ -1555,10 +1591,6 @@ function installFoundryInspector(options = {}) {
|
|
|
1555
1591
|
"afterend",
|
|
1556
1592
|
'<div class="status-popover" hidden><strong data-status-title>Session connected</strong><span data-status-detail>Changes are stored locally.</span><code data-status-project></code><code data-status-revision></code><button data-status-retry>Check connection</button></div>'
|
|
1557
1593
|
);
|
|
1558
|
-
shadow.querySelector(".footer").insertAdjacentHTML(
|
|
1559
|
-
"beforebegin",
|
|
1560
|
-
'<div class="change-dock" hidden><div class="change-dock-copy"><strong data-dock-count>No changes</strong><span data-dock-last>Edits will appear here</span></div><button class="dock-undo" title="Undo last preview" aria-label="Undo last preview"><i data-lucide="undo-2"></i></button><button class="dock-review">Review</button></div>'
|
|
1561
|
-
);
|
|
1562
1594
|
shadow.querySelector(".panel").insertAdjacentHTML(
|
|
1563
1595
|
"beforeend",
|
|
1564
1596
|
'<button class="panel-resizer" aria-label="Resize inspector panel" title="Drag to resize inspector"></button>'
|
|
@@ -1567,13 +1599,13 @@ function installFoundryInspector(options = {}) {
|
|
|
1567
1599
|
onboarding.className = "onboarding-card";
|
|
1568
1600
|
onboarding.hidden = true;
|
|
1569
1601
|
onboarding.setAttribute("aria-label", "Getting started with Foundry");
|
|
1570
|
-
onboarding.innerHTML = '<div class="onboarding-card-head"><i data-
|
|
1602
|
+
onboarding.innerHTML = '<div class="onboarding-card-head"><span><i data-foundry-icon="sparkles"></i></span><strong>Start with the interface</strong></div><p>Foundry stays in Select mode while you work. Click anything, refine measured values, then apply one reviewed batch.</p><div class="onboarding-steps"><div class="onboarding-step"><b>01</b><span><strong>Select</strong><small>Click the page or choose a layer.</small></span></div><div class="onboarding-step"><b>02</b><span><strong>Refine</strong><small>Adjust real layout, type, color, and motion.</small></span></div><div class="onboarding-step"><b>03</b><span><strong>Apply</strong><small>Review once, update source, and verify.</small></span></div></div><div class="onboarding-actions"><button class="onboarding-shortcuts">View shortcuts</button><button class="onboarding-start">Select an element</button></div>';
|
|
1571
1603
|
shadow.append(onboarding);
|
|
1572
1604
|
const compareBar = document.createElement("div");
|
|
1573
1605
|
compareBar.className = "compare-bar";
|
|
1574
1606
|
compareBar.hidden = true;
|
|
1575
1607
|
compareBar.setAttribute("aria-label", "Preview comparison");
|
|
1576
|
-
compareBar.innerHTML = `<strong>Compare</strong><button data-compare="before"><i data-
|
|
1608
|
+
compareBar.innerHTML = `<strong>Compare</strong><button data-compare="before"><i data-foundry-icon="eye-off"></i>Before</button><input data-compare-scrub type="range" min="0" max="100" value="100" aria-label="Scrub between before and after"/><button data-compare="after" class="active"><i data-foundry-icon="eye"></i>After</button><button data-compare="split"><i data-foundry-icon="columns-3"></i>Side by side</button><button data-compare="isolate"><i data-foundry-icon="contrast"></i>Isolate</button><button data-compare="reset"><i data-foundry-icon="rotate-ccw"></i>Reset element</button><button data-compare="close" aria-label="Close comparison"><i data-foundry-icon="x"></i></button>`;
|
|
1577
1609
|
shadow.append(compareBar);
|
|
1578
1610
|
const commandPalette = document.createElement("section");
|
|
1579
1611
|
commandPalette.className = "command-palette";
|
|
@@ -1582,10 +1614,11 @@ function installFoundryInspector(options = {}) {
|
|
|
1582
1614
|
commandPalette.innerHTML = `<input type="search" aria-label="Search commands" placeholder="Type a command"/><div class="command-list"></div>`;
|
|
1583
1615
|
shadow.append(commandPalette);
|
|
1584
1616
|
const libraryPanel = document.createElement("aside");
|
|
1585
|
-
libraryPanel.className = "library-panel";
|
|
1617
|
+
libraryPanel.className = "library-panel utility-panel";
|
|
1618
|
+
libraryPanel.dataset.utility = "memory";
|
|
1586
1619
|
libraryPanel.hidden = true;
|
|
1587
1620
|
libraryPanel.setAttribute("aria-label", "Foundry design memory");
|
|
1588
|
-
libraryPanel.innerHTML = `<div class="library-head"><i data-
|
|
1621
|
+
libraryPanel.innerHTML = `<div class="library-head utility-handle"><i data-foundry-icon="bookmark"></i><strong>Design memory</strong><span>Local to this project</span><button class="icon-button close-library" aria-label="Close design memory"><i data-foundry-icon="x"></i></button></div><div class="library-actions"><button data-save-recipe disabled><i data-foundry-icon="save"></i>Save treatment</button><button data-capture-baseline disabled><i data-foundry-icon="check"></i>Save baseline</button></div><div class="library-body"></div><button class="utility-resizer" aria-label="Resize design memory"></button>`;
|
|
1589
1622
|
shadow.append(libraryPanel);
|
|
1590
1623
|
shadow.querySelector(".outline").insertAdjacentHTML(
|
|
1591
1624
|
"beforeend",
|
|
@@ -1602,23 +1635,23 @@ function installFoundryInspector(options = {}) {
|
|
|
1602
1635
|
canvasVariant.hidden = true;
|
|
1603
1636
|
canvasVariant.setAttribute("aria-label", "Component variant");
|
|
1604
1637
|
shadow.append(canvasVariant);
|
|
1605
|
-
shadow.querySelector(".top-actions").insertAdjacentHTML(
|
|
1606
|
-
"afterbegin",
|
|
1607
|
-
'<button class="icon-button open-health" title="Scan design health" aria-label="Scan design health"><i data-lucide="activity"></i></button><button class="icon-button open-workbench" title="Open state workbench" aria-label="Open state workbench"><i data-lucide="panels-top-left"></i></button><button class="icon-button open-library" title="Open design memory" aria-label="Open design memory"><i data-lucide="bookmark"></i></button><button class="icon-button open-compare" title="Compare changes" aria-label="Compare changes"><i data-lucide="contrast"></i></button><button class="icon-button open-commands" title="Open commands" aria-label="Open commands"><i data-lucide="command"></i></button>'
|
|
1608
|
-
);
|
|
1609
1638
|
shadow.querySelector(".scope").insertAdjacentHTML(
|
|
1610
1639
|
"beforeend",
|
|
1611
1640
|
'<label>State<select data-state><option value="current">Current</option></select></label>'
|
|
1612
1641
|
);
|
|
1642
|
+
shadow.querySelector(".tool-shelf").querySelector(".interact").insertAdjacentHTML(
|
|
1643
|
+
"afterend",
|
|
1644
|
+
'<span class="mode-copy" aria-live="polite"><strong>Select mode</strong><span>Click any element</span></span>'
|
|
1645
|
+
);
|
|
1613
1646
|
shadow.querySelector(".tool-shelf").insertAdjacentHTML(
|
|
1614
1647
|
"beforeend",
|
|
1615
|
-
'<span class="tool-divider canvas-actions-divider"></span><button class="tool-select undo" data-tooltip="Undo" aria-label="Undo preview" disabled><i data-
|
|
1648
|
+
'<span class="tool-divider canvas-actions-divider"></span><button class="tool-select undo" data-tooltip="Undo" aria-label="Undo preview" disabled><i data-foundry-icon="undo-2"></i></button><button class="tool-select redo" data-tooltip="Redo" aria-label="Redo preview" disabled><i data-foundry-icon="redo-2"></i></button><span class="tool-divider multi-actions-divider" hidden></span><button class="tool-select align" data-tooltip="Align" aria-label="Align selected elements" hidden><i data-foundry-icon="align-horizontal-space-around"></i></button><button class="tool-select distribute" data-tooltip="Distribute" aria-label="Distribute selected elements" hidden><i data-foundry-icon="columns-3"></i></button>'
|
|
1616
1649
|
);
|
|
1617
1650
|
const workbench = document.createElement("section");
|
|
1618
1651
|
workbench.className = "workbench";
|
|
1619
1652
|
workbench.hidden = true;
|
|
1620
1653
|
workbench.setAttribute("aria-label", "Foundry state workbench");
|
|
1621
|
-
workbench.innerHTML = `<header class="workbench-head"><strong>State workbench</strong><span class="workbench-context">Live application frame</span><div class="workbench-controls"><button data-workbench-matrix>Matrix</button><select data-workbench-viewport aria-label="Viewport"></select><select data-workbench-theme aria-label="Theme"><option value="current">Current theme</option></select><button data-workbench-state="hover">Hover</button><button data-workbench-state="focus">Focus</button><button data-workbench-motion>Reduce motion</button><button class="icon-button close-workbench" aria-label="Close state workbench"><i data-
|
|
1654
|
+
workbench.innerHTML = `<header class="workbench-head"><strong>State workbench</strong><span class="workbench-context">Live application frame</span><div class="workbench-controls"><button data-workbench-matrix>Matrix</button><select data-workbench-viewport aria-label="Viewport"></select><select data-workbench-theme aria-label="Theme"><option value="current">Current theme</option></select><button data-workbench-state="hover">Hover</button><button data-workbench-state="focus">Focus</button><button data-workbench-motion>Reduce motion</button><button class="icon-button close-workbench" aria-label="Close state workbench"><i data-foundry-icon="x"></i></button></div></header><div class="workbench-stage"><div class="workbench-matrix" hidden></div><div class="frame-shell"><span class="frame-label"></span><iframe title="Foundry live state preview"></iframe></div><div class="workbench-warning" hidden></div></div>`;
|
|
1622
1655
|
workbench.querySelector("[data-workbench-motion]").insertAdjacentHTML(
|
|
1623
1656
|
"beforebegin",
|
|
1624
1657
|
'<button data-workbench-state="active">Active</button><button data-workbench-state="disabled">Disabled</button>'
|
|
@@ -1628,30 +1661,33 @@ function installFoundryInspector(options = {}) {
|
|
|
1628
1661
|
comparisonStage.className = "comparison-stage";
|
|
1629
1662
|
comparisonStage.hidden = true;
|
|
1630
1663
|
comparisonStage.setAttribute("aria-label", "Side by side comparison");
|
|
1631
|
-
comparisonStage.innerHTML = `<header><strong>Before and after</strong><span>Source baseline compared with the current Foundry preview</span><button data-close-comparison-stage aria-label="Close side by side comparison"><i data-
|
|
1664
|
+
comparisonStage.innerHTML = `<header><strong>Before and after</strong><span>Source baseline compared with the current Foundry preview</span><button data-close-comparison-stage aria-label="Close side by side comparison"><i data-foundry-icon="x"></i></button></header><div class="comparison-frames"><div class="comparison-frame"><span>Before</span><iframe data-comparison-before title="Before source preview"></iframe></div><div class="comparison-frame"><span>After</span><iframe data-comparison-after title="After Foundry preview"></iframe></div></div>`;
|
|
1632
1665
|
shadow.append(comparisonStage);
|
|
1633
1666
|
function renderIcons(root) {
|
|
1634
|
-
|
|
1635
|
-
root,
|
|
1636
|
-
icons: FOUNDRY_ICONS,
|
|
1637
|
-
attrs: {
|
|
1638
|
-
"aria-hidden": "true",
|
|
1639
|
-
focusable: "false"
|
|
1640
|
-
}
|
|
1641
|
-
});
|
|
1667
|
+
renderKeylineIcons(root);
|
|
1642
1668
|
}
|
|
1643
1669
|
renderIcons(shadow);
|
|
1644
1670
|
const outline = shadow.querySelector(".outline");
|
|
1645
1671
|
const panel = shadow.querySelector(".panel");
|
|
1646
|
-
const tabs = shadow.querySelector(".tabs");
|
|
1647
1672
|
const controlsRoot = shadow.querySelector(".controls");
|
|
1648
1673
|
const inspectButton = shadow.querySelector(".inspect");
|
|
1674
|
+
const interactButton = shadow.querySelector(".interact");
|
|
1675
|
+
const workspaceBar = shadow.querySelector(".workspace-bar");
|
|
1649
1676
|
const sessionStatus = shadow.querySelector(".session-status");
|
|
1650
1677
|
const statusPopover = shadow.querySelector(".status-popover");
|
|
1651
1678
|
const changeDock = shadow.querySelector(".change-dock");
|
|
1679
|
+
const trayCompare = shadow.querySelector(".tray-compare");
|
|
1652
1680
|
const selectionKind = shadow.querySelector(".selection-kind");
|
|
1653
1681
|
const selectionTitle = shadow.querySelector(".selection strong");
|
|
1654
1682
|
const selectionCode = shadow.querySelector(".selection code");
|
|
1683
|
+
selectionCode.insertAdjacentHTML(
|
|
1684
|
+
"afterend",
|
|
1685
|
+
'<span class="selection-hint">Select mode stays on \xB7 click anywhere to begin</span>'
|
|
1686
|
+
);
|
|
1687
|
+
const selectionHint = shadow.querySelector(".selection-hint");
|
|
1688
|
+
const selectionRoot = shadow.querySelector(".selection");
|
|
1689
|
+
const modeCopyTitle = shadow.querySelector(".mode-copy strong");
|
|
1690
|
+
const modeCopyDetail = shadow.querySelector(".mode-copy span");
|
|
1655
1691
|
const selectionState = shadow.querySelector(".selection-state");
|
|
1656
1692
|
const selectionStats = shadow.querySelector(".selection-stats");
|
|
1657
1693
|
const selectionSize = shadow.querySelector("[data-selection-size]");
|
|
@@ -1683,6 +1719,7 @@ function installFoundryInspector(options = {}) {
|
|
|
1683
1719
|
const reviewCount = shadow.querySelector(".review-count");
|
|
1684
1720
|
const applyButton = shadow.querySelector(".review-actions .apply");
|
|
1685
1721
|
const reviewCancel = shadow.querySelector(".review-cancel");
|
|
1722
|
+
let workspaceState = { ...DEFAULT_WORKSPACE_STATE };
|
|
1686
1723
|
let selected = null;
|
|
1687
1724
|
let selectedElements = [];
|
|
1688
1725
|
let layerEntries = [];
|
|
@@ -1691,7 +1728,6 @@ function installFoundryInspector(options = {}) {
|
|
|
1691
1728
|
let layerView = sessionStorage.getItem(layerViewPreferenceKey) === "components" ? "components" : "layers";
|
|
1692
1729
|
let clickCycle = { x: -1, y: -1, at: 0, index: -1, signature: "" };
|
|
1693
1730
|
let inspecting = options.startInspecting ?? true;
|
|
1694
|
-
let activeCategory = "layout";
|
|
1695
1731
|
let selectedControls = [];
|
|
1696
1732
|
let resizeObserver;
|
|
1697
1733
|
let activeReviewPayload = null;
|
|
@@ -1705,6 +1741,7 @@ function installFoundryInspector(options = {}) {
|
|
|
1705
1741
|
})();
|
|
1706
1742
|
let reviewShowRejected = false;
|
|
1707
1743
|
let reviewPoll;
|
|
1744
|
+
let lastReviewTrigger = null;
|
|
1708
1745
|
let designGraph = null;
|
|
1709
1746
|
const previewHistory = [];
|
|
1710
1747
|
let historyCursor = 0;
|
|
@@ -1716,11 +1753,11 @@ function installFoundryInspector(options = {}) {
|
|
|
1716
1753
|
let hydratedOnce = false;
|
|
1717
1754
|
const collapsedSections = /* @__PURE__ */ new Set();
|
|
1718
1755
|
try {
|
|
1719
|
-
for (const key of JSON.parse(
|
|
1756
|
+
for (const key of JSON.parse(sessionStorage.getItem("__foundry_collapsed_sections") ?? "[]")) {
|
|
1720
1757
|
if (typeof key === "string") collapsedSections.add(key);
|
|
1721
1758
|
}
|
|
1722
1759
|
} catch {
|
|
1723
|
-
|
|
1760
|
+
sessionStorage.removeItem("__foundry_collapsed_sections");
|
|
1724
1761
|
}
|
|
1725
1762
|
let comparisonActive = false;
|
|
1726
1763
|
let isolatedComparisonElement = null;
|
|
@@ -1742,6 +1779,166 @@ function installFoundryInspector(options = {}) {
|
|
|
1742
1779
|
let projectRevision = "";
|
|
1743
1780
|
let designMemory = emptyDesignMemory();
|
|
1744
1781
|
let matrixMode = false;
|
|
1782
|
+
let lastUtilityTrigger = null;
|
|
1783
|
+
const utilityRects = /* @__PURE__ */ new Map();
|
|
1784
|
+
function utilityStorageKey(utility) {
|
|
1785
|
+
return `__foundry_utility_rect:${utility}:${projectRoot}`;
|
|
1786
|
+
}
|
|
1787
|
+
function canvasBounds() {
|
|
1788
|
+
const layersRect = workspaceState.layersOpen ? layersPanel.getBoundingClientRect() : null;
|
|
1789
|
+
const inspectorRect = workspaceState.inspectorOpen ? panel.getBoundingClientRect() : null;
|
|
1790
|
+
const trayRect = !changeDock.hidden ? changeDock.getBoundingClientRect() : null;
|
|
1791
|
+
return {
|
|
1792
|
+
left: Math.round((layersRect?.right ?? 0) + 12),
|
|
1793
|
+
top: Math.round(workspaceBar.getBoundingClientRect().bottom + 12),
|
|
1794
|
+
right: Math.round((inspectorRect?.left ?? window.innerWidth) - 12),
|
|
1795
|
+
bottom: Math.round((trayRect?.top ?? window.innerHeight) - 12)
|
|
1796
|
+
};
|
|
1797
|
+
}
|
|
1798
|
+
function readUtilityRect(utility) {
|
|
1799
|
+
try {
|
|
1800
|
+
const value = JSON.parse(localStorage.getItem(utilityStorageKey(utility)) ?? "null");
|
|
1801
|
+
if (value && ["x", "y", "width", "height"].every((key) => Number.isFinite(value[key]))) {
|
|
1802
|
+
return value;
|
|
1803
|
+
}
|
|
1804
|
+
} catch {
|
|
1805
|
+
localStorage.removeItem(utilityStorageKey(utility));
|
|
1806
|
+
}
|
|
1807
|
+
return void 0;
|
|
1808
|
+
}
|
|
1809
|
+
function applyUtilityRect(utility) {
|
|
1810
|
+
const utilityPanel = utility === "health" ? healthPanel : libraryPanel;
|
|
1811
|
+
if (window.matchMedia("(max-width: 680px)").matches) {
|
|
1812
|
+
utilityPanel.style.removeProperty("left");
|
|
1813
|
+
utilityPanel.style.removeProperty("top");
|
|
1814
|
+
utilityPanel.style.removeProperty("width");
|
|
1815
|
+
utilityPanel.style.removeProperty("height");
|
|
1816
|
+
return;
|
|
1817
|
+
}
|
|
1818
|
+
const bounds = canvasBounds();
|
|
1819
|
+
const fallback = {
|
|
1820
|
+
x: bounds.left + 12,
|
|
1821
|
+
y: bounds.top + 12,
|
|
1822
|
+
width: 320,
|
|
1823
|
+
height: Math.min(560, Math.max(320, bounds.bottom - bounds.top - 24))
|
|
1824
|
+
};
|
|
1825
|
+
const rect = clampUtilityRect(
|
|
1826
|
+
utilityRects.get(utility) ?? readUtilityRect(utility) ?? fallback,
|
|
1827
|
+
bounds
|
|
1828
|
+
);
|
|
1829
|
+
utilityRects.set(utility, rect);
|
|
1830
|
+
Object.assign(utilityPanel.style, {
|
|
1831
|
+
left: `${rect.x}px`,
|
|
1832
|
+
top: `${rect.y}px`,
|
|
1833
|
+
width: `${rect.width}px`,
|
|
1834
|
+
height: `${rect.height}px`
|
|
1835
|
+
});
|
|
1836
|
+
}
|
|
1837
|
+
function positionWorkspaceSurfaces() {
|
|
1838
|
+
const bounds = canvasBounds();
|
|
1839
|
+
host.style.setProperty("--fdc-canvas-left", `${Math.max(12, bounds.left)}px`);
|
|
1840
|
+
host.style.setProperty(
|
|
1841
|
+
"--fdc-canvas-right",
|
|
1842
|
+
`${Math.max(12, window.innerWidth - bounds.right)}px`
|
|
1843
|
+
);
|
|
1844
|
+
host.style.setProperty(
|
|
1845
|
+
"--fdc-tray-lift",
|
|
1846
|
+
workspaceState.tray !== "hidden" ? `${Math.max(0, window.innerHeight - bounds.bottom)}px` : "0px"
|
|
1847
|
+
);
|
|
1848
|
+
if (workspaceState.utility) applyUtilityRect(workspaceState.utility);
|
|
1849
|
+
}
|
|
1850
|
+
function persistUtilityRect(utility, rect) {
|
|
1851
|
+
utilityRects.set(utility, rect);
|
|
1852
|
+
try {
|
|
1853
|
+
localStorage.setItem(utilityStorageKey(utility), JSON.stringify(rect));
|
|
1854
|
+
} catch {
|
|
1855
|
+
showToast("Panel position could not be saved in this browser");
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
function setUtility(utility) {
|
|
1859
|
+
const closing = utility == null;
|
|
1860
|
+
if (!closing && shadow.activeElement instanceof HTMLElement) {
|
|
1861
|
+
lastUtilityTrigger = shadow.activeElement;
|
|
1862
|
+
}
|
|
1863
|
+
workspaceState = utility ? updateWorkspace(workspaceState, { type: "open-utility", utility }) : updateWorkspace(workspaceState, { type: "close-utility" });
|
|
1864
|
+
healthPanel.hidden = workspaceState.utility !== "health";
|
|
1865
|
+
libraryPanel.hidden = workspaceState.utility !== "memory";
|
|
1866
|
+
shadow.querySelector(".open-health").classList.toggle("active", workspaceState.utility === "health");
|
|
1867
|
+
shadow.querySelector(".open-library").classList.toggle("active", workspaceState.utility === "memory");
|
|
1868
|
+
shadow.querySelector(".open-health").setAttribute("aria-pressed", String(workspaceState.utility === "health"));
|
|
1869
|
+
shadow.querySelector(".open-library").setAttribute("aria-pressed", String(workspaceState.utility === "memory"));
|
|
1870
|
+
if (workspaceState.utility === "health") scanDesignHealth();
|
|
1871
|
+
if (workspaceState.utility === "memory") renderDesignMemory();
|
|
1872
|
+
positionWorkspaceSurfaces();
|
|
1873
|
+
if (closing) lastUtilityTrigger?.focus();
|
|
1874
|
+
}
|
|
1875
|
+
function installUtilityGeometry(utilityPanel, utility) {
|
|
1876
|
+
const handle = utilityPanel.querySelector(".utility-handle");
|
|
1877
|
+
const resizer = utilityPanel.querySelector(".utility-resizer");
|
|
1878
|
+
handle.addEventListener("pointerdown", (event) => {
|
|
1879
|
+
if (event.button !== 0 || event.target.closest("button")) return;
|
|
1880
|
+
const start = utilityPanel.getBoundingClientRect();
|
|
1881
|
+
const startX = event.clientX;
|
|
1882
|
+
const startY = event.clientY;
|
|
1883
|
+
handle.setPointerCapture(event.pointerId);
|
|
1884
|
+
const move = (pointerMove) => {
|
|
1885
|
+
const rect = clampUtilityRect(
|
|
1886
|
+
{
|
|
1887
|
+
x: start.x + pointerMove.clientX - startX,
|
|
1888
|
+
y: start.y + pointerMove.clientY - startY,
|
|
1889
|
+
width: start.width,
|
|
1890
|
+
height: start.height
|
|
1891
|
+
},
|
|
1892
|
+
canvasBounds()
|
|
1893
|
+
);
|
|
1894
|
+
Object.assign(utilityPanel.style, { left: `${rect.x}px`, top: `${rect.y}px` });
|
|
1895
|
+
utilityRects.set(utility, rect);
|
|
1896
|
+
};
|
|
1897
|
+
const finish = () => {
|
|
1898
|
+
handle.removeEventListener("pointermove", move);
|
|
1899
|
+
handle.removeEventListener("pointerup", finish);
|
|
1900
|
+
handle.removeEventListener("pointercancel", finish);
|
|
1901
|
+
const rect = utilityRects.get(utility);
|
|
1902
|
+
if (rect) persistUtilityRect(utility, rect);
|
|
1903
|
+
};
|
|
1904
|
+
handle.addEventListener("pointermove", move);
|
|
1905
|
+
handle.addEventListener("pointerup", finish);
|
|
1906
|
+
handle.addEventListener("pointercancel", finish);
|
|
1907
|
+
});
|
|
1908
|
+
resizer.addEventListener("pointerdown", (event) => {
|
|
1909
|
+
if (event.button !== 0) return;
|
|
1910
|
+
const start = utilityPanel.getBoundingClientRect();
|
|
1911
|
+
const startX = event.clientX;
|
|
1912
|
+
const startY = event.clientY;
|
|
1913
|
+
resizer.setPointerCapture(event.pointerId);
|
|
1914
|
+
const move = (pointerMove) => {
|
|
1915
|
+
const rect = clampUtilityRect(
|
|
1916
|
+
{
|
|
1917
|
+
x: start.x,
|
|
1918
|
+
y: start.y,
|
|
1919
|
+
width: start.width + pointerMove.clientX - startX,
|
|
1920
|
+
height: start.height + pointerMove.clientY - startY
|
|
1921
|
+
},
|
|
1922
|
+
canvasBounds()
|
|
1923
|
+
);
|
|
1924
|
+
Object.assign(utilityPanel.style, {
|
|
1925
|
+
width: `${rect.width}px`,
|
|
1926
|
+
height: `${rect.height}px`
|
|
1927
|
+
});
|
|
1928
|
+
utilityRects.set(utility, rect);
|
|
1929
|
+
};
|
|
1930
|
+
const finish = () => {
|
|
1931
|
+
resizer.removeEventListener("pointermove", move);
|
|
1932
|
+
resizer.removeEventListener("pointerup", finish);
|
|
1933
|
+
resizer.removeEventListener("pointercancel", finish);
|
|
1934
|
+
const rect = utilityRects.get(utility);
|
|
1935
|
+
if (rect) persistUtilityRect(utility, rect);
|
|
1936
|
+
};
|
|
1937
|
+
resizer.addEventListener("pointermove", move);
|
|
1938
|
+
resizer.addEventListener("pointerup", finish);
|
|
1939
|
+
resizer.addEventListener("pointercancel", finish);
|
|
1940
|
+
});
|
|
1941
|
+
}
|
|
1745
1942
|
if (!sessionId || !token) {
|
|
1746
1943
|
setSessionStatus(
|
|
1747
1944
|
"offline",
|
|
@@ -1763,13 +1960,20 @@ function installFoundryInspector(options = {}) {
|
|
|
1763
1960
|
function updateChangeCount(count, latest) {
|
|
1764
1961
|
changeCount.textContent = String(count);
|
|
1765
1962
|
changeCount.hidden = count === 0;
|
|
1766
|
-
shadow.querySelector(".footer .review").hidden = count > 0;
|
|
1767
1963
|
changeDock.hidden = count === 0;
|
|
1964
|
+
workspaceState = updateWorkspace(workspaceState, {
|
|
1965
|
+
type: "set-tray",
|
|
1966
|
+
tray: count === 0 ? "hidden" : workspaceState.tray === "expanded" ? "expanded" : "collapsed"
|
|
1967
|
+
});
|
|
1968
|
+
if (count === 0) reviewView.hidden = true;
|
|
1969
|
+
changeDock.classList.toggle("expanded", workspaceState.tray === "expanded");
|
|
1970
|
+
trayCompare.disabled = count === 0 || historyCursor === 0;
|
|
1768
1971
|
changeDock.querySelector("[data-dock-count]").textContent = `${count} ${count === 1 ? "change" : "changes"} recorded`;
|
|
1769
1972
|
if (latest) {
|
|
1770
1973
|
lastRecordedSummary = `${latest.target?.label ?? "Element"} \xB7 ${latest.property} ${reviewValue(latest.before, latest.unit)} \u2192 ${reviewValue(latest.after, latest.unit)}`;
|
|
1771
1974
|
}
|
|
1772
1975
|
changeDock.querySelector("[data-dock-last]").textContent = lastRecordedSummary || "Ready to review";
|
|
1976
|
+
positionWorkspaceSurfaces();
|
|
1773
1977
|
}
|
|
1774
1978
|
function populateDesignContext() {
|
|
1775
1979
|
if (!designGraph) return;
|
|
@@ -1822,6 +2026,8 @@ function installFoundryInspector(options = {}) {
|
|
|
1822
2026
|
if (projectRoot !== nextProjectRoot || !hydratedOnce) {
|
|
1823
2027
|
projectRoot = nextProjectRoot;
|
|
1824
2028
|
designMemory = readDesignMemory(localStorage, projectRoot);
|
|
2029
|
+
utilityRects.clear();
|
|
2030
|
+
positionWorkspaceSurfaces();
|
|
1825
2031
|
}
|
|
1826
2032
|
projectRevision = changeSet.context.revision ?? "";
|
|
1827
2033
|
designGraph = graph;
|
|
@@ -1887,13 +2093,10 @@ function installFoundryInspector(options = {}) {
|
|
|
1887
2093
|
);
|
|
1888
2094
|
}
|
|
1889
2095
|
function openDesignMemory() {
|
|
1890
|
-
|
|
1891
|
-
shadow.querySelector(".open-library").classList.add("active");
|
|
1892
|
-
renderDesignMemory();
|
|
2096
|
+
if (workspaceState.utility !== "memory") setUtility("memory");
|
|
1893
2097
|
}
|
|
1894
2098
|
function closeDesignMemory() {
|
|
1895
|
-
|
|
1896
|
-
shadow.querySelector(".open-library").classList.remove("active");
|
|
2099
|
+
if (workspaceState.utility === "memory") setUtility(null);
|
|
1897
2100
|
}
|
|
1898
2101
|
function saveSelectedRecipe() {
|
|
1899
2102
|
if (!selected) return;
|
|
@@ -2200,7 +2403,7 @@ function installFoundryInspector(options = {}) {
|
|
|
2200
2403
|
(variant) => `<button data-component-variant="${escapeHtml(variant.id)}" data-component-owner="${index}">${escapeHtml(variant.name)}</button>`
|
|
2201
2404
|
).join("");
|
|
2202
2405
|
const remainingVariants = Math.max(0, entry.variants.length - 3);
|
|
2203
|
-
return `<article class="component-card ${selectedComponent2 ? "selected" : ""}" data-component-row="${index}"><button class="component-main" data-component-index="${index}" aria-label="${liveCount ? `Select ${escapeHtml(entry.name)} component` : `${escapeHtml(entry.name)} component is not on the canvas`}" ${liveCount ? "" : "disabled"}><span class="component-mark"><i data-
|
|
2406
|
+
return `<article class="component-card ${selectedComponent2 ? "selected" : ""}" data-component-row="${index}"><button class="component-main" data-component-index="${index}" aria-label="${liveCount ? `Select ${escapeHtml(entry.name)} component` : `${escapeHtml(entry.name)} component is not on the canvas`}" ${liveCount ? "" : "disabled"}><span class="component-mark"><i data-foundry-icon="component"></i></span><span class="component-copy"><strong>${escapeHtml(entry.name)}</strong><span>${escapeHtml(entry.namespace)}</span></span><span class="component-status"><span>${liveCount ? `${liveCount} live` : "Indexed"}</span><small>${entry.variants.length ? `${entry.variants.length} variant${entry.variants.length === 1 ? "" : "s"}` : `${entry.indexedInstances} instance${entry.indexedInstances === 1 ? "" : "s"}`}</small></span></button>${variants ? `<div class="component-variants">${variants}${remainingVariants ? `<button data-component-index="${index}">+${remainingVariants}</button>` : ""}</div>` : ""}${liveCount > 1 ? `<div class="component-actions"><button data-select-all-instances="${index}">Select all ${liveCount} instances</button></div>` : ""}</article>`;
|
|
2204
2407
|
}).join("")}</div>` : '<div class="layers-empty">No components match this search.</div>';
|
|
2205
2408
|
renderIcons(layerTree);
|
|
2206
2409
|
layerTree.querySelectorAll("[data-component-row]").forEach((row) => {
|
|
@@ -2312,7 +2515,7 @@ function installFoundryInspector(options = {}) {
|
|
|
2312
2515
|
const index = layerEntries.indexOf(entry);
|
|
2313
2516
|
const meta = entry.instrumented ? "Mapped" : entry.kind;
|
|
2314
2517
|
const collapsed = collapsedLayers.has(entry.element);
|
|
2315
|
-
return `<div class="layer-row ${selectedElements.includes(entry.element) ? "selected" : ""}" style="--layer-depth:${Math.min(entry.depth, 8)}" data-layer-row="${index}" draggable="true"><button class="layer-toggle" data-layer-toggle="${index}" aria-label="${collapsed ? "Expand" : "Collapse"} ${escapeHtml(entry.label)}" aria-expanded="${!collapsed}" ${entry.hasChildren ? "" : "disabled"}><i data-
|
|
2518
|
+
return `<div class="layer-row ${selectedElements.includes(entry.element) ? "selected" : ""}" style="--layer-depth:${Math.min(entry.depth, 8)}" data-layer-row="${index}" draggable="true"><button class="layer-toggle" data-layer-toggle="${index}" aria-label="${collapsed ? "Expand" : "Collapse"} ${escapeHtml(entry.label)}" aria-expanded="${!collapsed}" ${entry.hasChildren ? "" : "disabled"}><i data-foundry-icon="${collapsed ? "chevron-right" : "chevron-down"}"></i></button><button class="layer-select" data-layer-index="${index}" aria-label="Select ${escapeHtml(entry.label)}"><i class="layer-icon" data-foundry-icon="${entry.kind === "component" ? "component" : "box"}"></i><span class="layer-label">${escapeHtml(entry.label)}</span><span class="layer-meta">${escapeHtml(meta)}</span></button></div>`;
|
|
2316
2519
|
}).join(
|
|
2317
2520
|
""
|
|
2318
2521
|
)}${range.after ? `<div class="layer-spacer" style="height:${range.after}px"></div>` : ""}` : '<div class="layers-empty">No visible layers match this search.</div>';
|
|
@@ -2402,19 +2605,41 @@ function installFoundryInspector(options = {}) {
|
|
|
2402
2605
|
}
|
|
2403
2606
|
const layersPreferenceKey = "__foundry_layers_visibility";
|
|
2404
2607
|
function toggleLayers(force, remember = true) {
|
|
2405
|
-
|
|
2406
|
-
|
|
2608
|
+
workspaceState = updateWorkspace(workspaceState, {
|
|
2609
|
+
type: "toggle-layers",
|
|
2610
|
+
open: force
|
|
2611
|
+
});
|
|
2612
|
+
layersPanel.hidden = !workspaceState.layersOpen;
|
|
2407
2613
|
const layersButton = shadow.querySelector(".toggle-layers");
|
|
2408
|
-
const layersButtonLabel =
|
|
2614
|
+
const layersButtonLabel = workspaceState.layersOpen ? "Hide layers" : "Show layers";
|
|
2409
2615
|
layersButton.setAttribute("aria-label", layersButtonLabel);
|
|
2410
2616
|
layersButton.title = layersButtonLabel;
|
|
2411
|
-
layersButton.
|
|
2412
|
-
|
|
2617
|
+
layersButton.setAttribute("aria-pressed", String(workspaceState.layersOpen));
|
|
2618
|
+
layersButton.classList.toggle("active", workspaceState.layersOpen);
|
|
2413
2619
|
if (remember) {
|
|
2414
|
-
sessionStorage.setItem(layersPreferenceKey,
|
|
2620
|
+
sessionStorage.setItem(layersPreferenceKey, workspaceState.layersOpen ? "open" : "closed");
|
|
2415
2621
|
}
|
|
2416
|
-
if (
|
|
2622
|
+
if (workspaceState.layersOpen) renderLayers();
|
|
2417
2623
|
else previewLayer(null);
|
|
2624
|
+
positionWorkspaceSurfaces();
|
|
2625
|
+
}
|
|
2626
|
+
function toggleInspector(force) {
|
|
2627
|
+
workspaceState = updateWorkspace(workspaceState, {
|
|
2628
|
+
type: "toggle-inspector",
|
|
2629
|
+
open: force
|
|
2630
|
+
});
|
|
2631
|
+
panel.hidden = !workspaceState.inspectorOpen;
|
|
2632
|
+
shadow.querySelectorAll(".toggle-inspector").forEach((button) => {
|
|
2633
|
+
button.classList.toggle("active", workspaceState.inspectorOpen);
|
|
2634
|
+
button.setAttribute("aria-pressed", String(workspaceState.inspectorOpen));
|
|
2635
|
+
if (!button.classList.contains("inspector-collapse")) {
|
|
2636
|
+
button.setAttribute(
|
|
2637
|
+
"aria-label",
|
|
2638
|
+
workspaceState.inspectorOpen ? "Hide inspector" : "Show inspector"
|
|
2639
|
+
);
|
|
2640
|
+
}
|
|
2641
|
+
});
|
|
2642
|
+
positionWorkspaceSurfaces();
|
|
2418
2643
|
}
|
|
2419
2644
|
function selectionCandidatesAt(x, y, preferMappedTarget = false) {
|
|
2420
2645
|
const hitElements = (root) => {
|
|
@@ -2451,9 +2676,8 @@ function installFoundryInspector(options = {}) {
|
|
|
2451
2676
|
function updateHistoryActions() {
|
|
2452
2677
|
shadow.querySelector(".undo").disabled = historyCursor === 0;
|
|
2453
2678
|
shadow.querySelector(".redo").disabled = historyCursor >= previewHistory.length;
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
compare.title = historyCursor ? "Compare changes (Shift-C)" : "Make a preview change to enable comparison";
|
|
2679
|
+
trayCompare.disabled = historyCursor === 0;
|
|
2680
|
+
trayCompare.title = historyCursor ? "Compare changes (Shift-C)" : "Make a preview change to enable comparison";
|
|
2457
2681
|
}
|
|
2458
2682
|
function pushHistory(entry) {
|
|
2459
2683
|
previewHistory.splice(historyCursor);
|
|
@@ -2645,8 +2869,11 @@ function installFoundryInspector(options = {}) {
|
|
|
2645
2869
|
if (matrixMode) renderWorkbenchMatrix();
|
|
2646
2870
|
}
|
|
2647
2871
|
function openWorkbench() {
|
|
2872
|
+
workspaceState = updateWorkspace(workspaceState, { type: "set-workbench", open: true });
|
|
2648
2873
|
workbench.hidden = false;
|
|
2649
|
-
shadow.querySelector(".open-workbench")
|
|
2874
|
+
const workbenchButton = shadow.querySelector(".open-workbench");
|
|
2875
|
+
workbenchButton.classList.add("active");
|
|
2876
|
+
workbenchButton.setAttribute("aria-pressed", "true");
|
|
2650
2877
|
resizeWorkbench();
|
|
2651
2878
|
const frame = shadow.querySelector(".frame-shell iframe");
|
|
2652
2879
|
const url = new URL(location.href);
|
|
@@ -2656,8 +2883,11 @@ function installFoundryInspector(options = {}) {
|
|
|
2656
2883
|
if (matrixMode) renderWorkbenchMatrix();
|
|
2657
2884
|
}
|
|
2658
2885
|
function closeWorkbench() {
|
|
2886
|
+
workspaceState = updateWorkspace(workspaceState, { type: "set-workbench", open: false });
|
|
2659
2887
|
workbench.hidden = true;
|
|
2660
|
-
shadow.querySelector(".open-workbench")
|
|
2888
|
+
const workbenchButton = shadow.querySelector(".open-workbench");
|
|
2889
|
+
workbenchButton.classList.remove("active");
|
|
2890
|
+
workbenchButton.setAttribute("aria-pressed", "false");
|
|
2661
2891
|
}
|
|
2662
2892
|
function reviewValue(value, unit) {
|
|
2663
2893
|
const rendered = typeof value === "string" ? value : JSON.stringify(value);
|
|
@@ -2669,23 +2899,6 @@ function installFoundryInspector(options = {}) {
|
|
|
2669
2899
|
}
|
|
2670
2900
|
return change.target.locator?.selector ?? "Source mapping unavailable";
|
|
2671
2901
|
}
|
|
2672
|
-
function reviewVisual(change, afterValue) {
|
|
2673
|
-
const before = String(change.before);
|
|
2674
|
-
const after = String(afterValue);
|
|
2675
|
-
const property = String(change.property);
|
|
2676
|
-
const colorValue = (value) => /^(#|rgb|hsl|oklch|transparent)/i.test(value.trim()) ? value.trim() : "#e8e8e8";
|
|
2677
|
-
const numeric = (value) => Math.max(0, Number.parseFloat(value) || 0);
|
|
2678
|
-
const sample = (value, label) => {
|
|
2679
|
-
let style = "";
|
|
2680
|
-
if (/color|fill|background/i.test(property)) style = `--sample-color:${colorValue(value)}`;
|
|
2681
|
-
else if (/radius/i.test(property))
|
|
2682
|
-
style = `--sample-radius:${Math.min(16, numeric(value))}px`;
|
|
2683
|
-
else if (/width|height|gap|padding|margin|size/i.test(property))
|
|
2684
|
-
style = `--sample-scale:${Math.max(0.45, Math.min(1.35, numeric(value) / Math.max(numeric(before), numeric(after), 1)))}`;
|
|
2685
|
-
return `<span class="review-sample" data-label="${label}"><i style="${escapeHtml(style)}"></i></span>`;
|
|
2686
|
-
};
|
|
2687
|
-
return `<span class="review-visual">${sample(before, "Before")}${sample(after, "After")}</span>`;
|
|
2688
|
-
}
|
|
2689
2902
|
function persistReviewDraft() {
|
|
2690
2903
|
try {
|
|
2691
2904
|
sessionStorage.setItem(reviewDraftKey, JSON.stringify(reviewDraft));
|
|
@@ -2706,7 +2919,19 @@ function installFoundryInspector(options = {}) {
|
|
|
2706
2919
|
const selectableCount = reviewBody.querySelectorAll(
|
|
2707
2920
|
"[data-review-change]:not(:disabled)"
|
|
2708
2921
|
).length;
|
|
2922
|
+
const summary = reviewBody.querySelector(".review-summary");
|
|
2923
|
+
const elementCount = reviewBody.querySelectorAll(".review-group").length;
|
|
2924
|
+
const unresolvedCount = Number(summary?.dataset.unresolved ?? 0);
|
|
2709
2925
|
reviewCount.textContent = `${selectedCount} of ${selectableCount} included`;
|
|
2926
|
+
if (summary) {
|
|
2927
|
+
summary.classList.toggle("attention", unresolvedCount > 0);
|
|
2928
|
+
summary.querySelector("strong").textContent = reviewSummary(
|
|
2929
|
+
selectedCount,
|
|
2930
|
+
selectableCount,
|
|
2931
|
+
elementCount,
|
|
2932
|
+
unresolvedCount
|
|
2933
|
+
);
|
|
2934
|
+
}
|
|
2710
2935
|
reviewBody.querySelectorAll(".review-group").forEach((group) => {
|
|
2711
2936
|
const included = group.querySelectorAll(
|
|
2712
2937
|
"[data-review-change]:checked:not(:disabled)"
|
|
@@ -2726,11 +2951,14 @@ function installFoundryInspector(options = {}) {
|
|
|
2726
2951
|
const rejectedCount = activeReviewPayload?.changeSet?.changes?.filter(
|
|
2727
2952
|
(change) => change.status === "rejected" && String(change.before) !== String(change.after)
|
|
2728
2953
|
).length ?? 0;
|
|
2729
|
-
|
|
2954
|
+
const unresolvedCount = changes.filter(
|
|
2955
|
+
(change) => change.confidence === "unresolved" || change.mappingCandidates?.length > 1 && !change.selectedMappingId
|
|
2956
|
+
).length;
|
|
2957
|
+
reviewBody.innerHTML = changes.length || rejectedCount ? `<div class="review-overview"><div class="review-summary" data-unresolved="${unresolvedCount}" aria-live="polite"><strong>Preparing review\u2026</strong><span>Only included, exactly mapped changes will be sent to your agent.</span></div><div class="review-toolbar"><button data-review-approve-exact>Include all</button><button data-review-toggle-rejected>${reviewShowRejected ? "Hide removed" : rejectedCount ? `${rejectedCount} removed` : "Removed"}</button></div></div>${[
|
|
2730
2958
|
...groups.values()
|
|
2731
2959
|
].map((group) => {
|
|
2732
2960
|
const target = group[0].target;
|
|
2733
|
-
return `<section class="review-group" data-review-target="${escapeHtml(target.id)}"><button class="review-group-title" aria-expanded="true"><i data-
|
|
2961
|
+
return `<section class="review-group" data-review-target="${escapeHtml(target.id)}"><button class="review-group-title" aria-expanded="true"><i data-foundry-icon="chevron-down"></i><strong>${escapeHtml(target.label)}</strong><span class="included-count"></span><span class="group-total">${group.length}</span></button>${group.map((change) => {
|
|
2734
2962
|
const unresolved = change.confidence === "unresolved" || change.mappingCandidates?.length > 1 && !change.selectedMappingId;
|
|
2735
2963
|
const selectable = !unresolved && change.status !== "rejected";
|
|
2736
2964
|
const checked = selectable && reviewSelection(reviewDraft, change.id, true);
|
|
@@ -2752,7 +2980,7 @@ function installFoundryInspector(options = {}) {
|
|
|
2752
2980
|
componentInstances: component?.instances,
|
|
2753
2981
|
unresolved
|
|
2754
2982
|
});
|
|
2755
|
-
return `<div class="review-card ${change.status === "rejected" ? "rejected" : ""}" data-review-card="${escapeHtml(change.id)}"><input aria-label="Include ${escapeHtml(change.property)} change" type="checkbox" data-review-change="${escapeHtml(change.id)}" ${checked ? "checked" : ""} ${selectable ? "" : "disabled"}/><
|
|
2983
|
+
return `<div class="review-card ${change.status === "rejected" ? "rejected" : ""}" data-review-card="${escapeHtml(change.id)}"><input aria-label="Include ${escapeHtml(change.property)} change" type="checkbox" data-review-change="${escapeHtml(change.id)}" ${checked ? "checked" : ""} ${selectable ? "" : "disabled"}/><div class="review-card-main"><div class="review-card-line"><strong title="${escapeHtml(change.property)}">${escapeHtml(humanizeProperty(change.property))}</strong><span class="confidence-pill ${unresolved ? "unresolved" : ""}">${escapeHtml(change.status === "rejected" ? "removed" : change.confidence)}</span><span class="review-values"><span class="review-before" title="Before: ${escapeHtml(reviewValue(change.before, change.unit))}">${escapeHtml(reviewValue(change.before, change.unit))}</span><span aria-hidden="true">\u2192</span><input aria-label="New ${escapeHtml(change.property)} value" class="review-after" data-review-after="${escapeHtml(change.id)}" data-value-kind="${inputType}" type="${inputType}" value="${escapeHtml(afterValue)}" ${selectable ? "" : "disabled"}/></span><details class="review-more"><summary aria-label="More actions for ${escapeHtml(humanizeProperty(change.property))}">\u2022\u2022\u2022</summary><div class="review-card-tools"><button data-review-locate="${escapeHtml(change.id)}">Locate</button><button data-review-preview="${escapeHtml(change.id)}" title="Hold to preview before">Preview before</button><button data-review-status="${escapeHtml(change.id)}" data-next-status="${change.status === "rejected" ? "draft" : "rejected"}">${change.status === "rejected" ? "Restore" : "Remove"}</button><details class="review-details"><summary>Source and scope</summary><span class="review-source">${escapeHtml(change.property)} \xB7 ${escapeHtml(reviewSource(change))} \xB7 ${escapeHtml(change.scope)} \xB7 ${escapeHtml(change.context.breakpoint)} \xB7 ${escapeHtml(change.context.theme)}${change.token ? ` \xB7 ${escapeHtml(change.token)}` : ""}</span><span class="impact-list">${impact.map((message) => `<span class="impact-item ${unresolved || !change.token && message.includes("literal") ? "warning" : ""}">${escapeHtml(message)}</span>`).join("")}</span></details></div></details></div>${mappingChooser}</div></div>`;
|
|
2756
2984
|
}).join("")}</section>`;
|
|
2757
2985
|
}).join("")}` : '<div class="review-empty">No unresolved design edits are waiting for review.</div>';
|
|
2758
2986
|
applyButton.dataset.action = "apply";
|
|
@@ -2962,7 +3190,7 @@ function installFoundryInspector(options = {}) {
|
|
|
2962
3190
|
else renderReviewList(pending);
|
|
2963
3191
|
}
|
|
2964
3192
|
async function refreshReview() {
|
|
2965
|
-
if (
|
|
3193
|
+
if (workspaceState.tray !== "expanded" || !sessionId || !token) return;
|
|
2966
3194
|
try {
|
|
2967
3195
|
const payload = await sessionRequest();
|
|
2968
3196
|
const latestRun = payload.applyRuns?.at(-1);
|
|
@@ -2989,20 +3217,29 @@ function installFoundryInspector(options = {}) {
|
|
|
2989
3217
|
showToast("Session connection is missing");
|
|
2990
3218
|
return;
|
|
2991
3219
|
}
|
|
2992
|
-
|
|
3220
|
+
if (shadow.activeElement instanceof HTMLElement) lastReviewTrigger = shadow.activeElement;
|
|
3221
|
+
workspaceState = updateWorkspace(workspaceState, { type: "set-tray", tray: "expanded" });
|
|
3222
|
+
changeDock.classList.add("expanded");
|
|
2993
3223
|
reviewView.hidden = false;
|
|
2994
3224
|
outline.hidden = true;
|
|
3225
|
+
positionWorkspaceSurfaces();
|
|
2995
3226
|
renderReviewPayload(await sessionRequest());
|
|
2996
3227
|
clearInterval(reviewPoll);
|
|
2997
3228
|
clearInterval(healthPoll);
|
|
2998
3229
|
reviewPoll = setInterval(() => void refreshReview(), 1e3);
|
|
2999
3230
|
}
|
|
3000
3231
|
function closeReview() {
|
|
3001
|
-
|
|
3232
|
+
workspaceState = updateWorkspace(workspaceState, {
|
|
3233
|
+
type: "set-tray",
|
|
3234
|
+
tray: changeDock.hidden ? "hidden" : "collapsed"
|
|
3235
|
+
});
|
|
3236
|
+
changeDock.classList.remove("expanded");
|
|
3002
3237
|
reviewView.hidden = true;
|
|
3003
3238
|
clearInterval(reviewPoll);
|
|
3004
3239
|
reviewPoll = void 0;
|
|
3005
3240
|
updateOutline();
|
|
3241
|
+
positionWorkspaceSurfaces();
|
|
3242
|
+
lastReviewTrigger?.focus();
|
|
3006
3243
|
}
|
|
3007
3244
|
async function submitReviewedRun() {
|
|
3008
3245
|
if (!activeReviewPayload) return;
|
|
@@ -3283,27 +3520,10 @@ function installFoundryInspector(options = {}) {
|
|
|
3283
3520
|
}
|
|
3284
3521
|
}
|
|
3285
3522
|
function renderToolTabs() {
|
|
3286
|
-
const
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
"color",
|
|
3291
|
-
"effects",
|
|
3292
|
-
"content",
|
|
3293
|
-
"accessibility",
|
|
3294
|
-
...selected?.getAnimations().length ? ["motion"] : []
|
|
3295
|
-
])
|
|
3296
|
-
];
|
|
3297
|
-
tabs.innerHTML = categories.map(
|
|
3298
|
-
(category) => `<button class="tab ${selected && activeCategory === category ? "active" : ""}" data-category="${category}" data-tooltip="${CATEGORY_LABELS[category]}" title="${CATEGORY_LABELS[category]} controls" aria-label="${CATEGORY_LABELS[category]} controls" ${selected ? "" : "disabled"}><i data-lucide="${CATEGORY_ICONS[category]}"></i></button>`
|
|
3299
|
-
).join("");
|
|
3300
|
-
renderIcons(tabs);
|
|
3301
|
-
tabs.querySelectorAll("[data-category]").forEach(
|
|
3302
|
-
(button) => button.addEventListener("click", () => {
|
|
3303
|
-
activeCategory = button.dataset.category;
|
|
3304
|
-
renderControls();
|
|
3305
|
-
})
|
|
3306
|
-
);
|
|
3523
|
+
const multi = selectedElements.length > 1;
|
|
3524
|
+
shadow.querySelectorAll(".align,.distribute,.multi-actions-divider").forEach((element) => {
|
|
3525
|
+
element.hidden = !multi;
|
|
3526
|
+
});
|
|
3307
3527
|
}
|
|
3308
3528
|
function installNumberScrubbing() {
|
|
3309
3529
|
controlsRoot.querySelectorAll("[data-scrub-for]").forEach((handle) => {
|
|
@@ -3496,21 +3716,22 @@ function installFoundryInspector(options = {}) {
|
|
|
3496
3716
|
}
|
|
3497
3717
|
function renderContextPanel(category) {
|
|
3498
3718
|
if (!selected) return "";
|
|
3499
|
-
const
|
|
3719
|
+
const supportsTokens = ["layout", "typography", "color", "effects"].includes(category);
|
|
3720
|
+
const tokens = supportsTokens ? tokensForCategory(category).slice(0, 24) : [];
|
|
3500
3721
|
const component = selectedComponent();
|
|
3501
3722
|
const variants = component?.variants ?? [];
|
|
3502
3723
|
const tokenPanel = tokens.length ? `<section class="native-panel"><div class="native-panel-head"><strong>Project ${category === "typography" ? "styles" : "tokens"}</strong><span>${tokens.length}</span></div><input class="native-search" type="search" placeholder="Search project values" aria-label="Search project values"/><div class="native-grid">${tokens.map(
|
|
3503
3724
|
(token2) => `<button class="native-chip" data-native-token="${escapeHtml(token2.id)}" data-token-search="${escapeHtml(`${token2.name} ${token2.value}`.toLowerCase())}" title="${escapeHtml(token2.value)}">${category === "color" ? `<span class="swatch" style="--token-color:${escapeHtml(token2.value)}"></span>` : ""}<span>${escapeHtml(token2.name)}</span></button>`
|
|
3504
3725
|
).join("")}</div></section>` : "";
|
|
3505
3726
|
const contrast = category === "color" ? contrastRatio(getComputedStyle(selected).color, opaqueBackground(selected)) : null;
|
|
3506
|
-
const health = category === "color" && contrast != null ? `<div class="design-health ${contrast >= 4.5 ? "pass" : "fail"}"><i data-
|
|
3507
|
-
const variantPanel = variants.length ? `<section class="native-panel"><div class="native-panel-head"><strong>${escapeHtml(component.name)} variants</strong><span>${component.instances} instances</span></div><div class="variant-list">${variants.map(
|
|
3727
|
+
const health = category === "color" && contrast != null ? `<div class="design-health ${contrast >= 4.5 ? "pass" : "fail"}"><i data-foundry-icon="contrast"></i><span>${contrast}:1 contrast \xB7 ${contrast >= 4.5 ? "AA pass" : "Needs attention"}</span></div>` : "";
|
|
3728
|
+
const variantPanel = category === "content" && variants.length ? `<section class="native-panel"><div class="native-panel-head"><strong>${escapeHtml(component.name)} variants</strong><span>${component.instances} instances</span></div><div class="variant-list">${variants.map(
|
|
3508
3729
|
(variant) => `<button class="variant-button" data-variant="${escapeHtml(variant.id)}"><span>${escapeHtml(variant.name)}</span><code>${escapeHtml(
|
|
3509
3730
|
Object.entries(variant.props).map(([key, value]) => `${key}=${value}`).join(" \xB7 ")
|
|
3510
3731
|
)}</code></button>`
|
|
3511
3732
|
).join("")}</div></section>` : "";
|
|
3512
|
-
const categoryTools = category === "layout" ? `<div class="context-tools"><button data-layout-action="tidy"><i data-
|
|
3513
|
-
const tokenMode = designGraph?.tokens.length ?? 0 ? `<div class="context-tools"><button class="${tokenOnly ? "active" : ""}" data-token-only><i data-
|
|
3733
|
+
const categoryTools = category === "layout" ? `<div class="context-tools"><button data-layout-action="tidy"><i data-foundry-icon="wand-sparkles"></i>Tidy layout</button><button data-layout-action="up"><i data-foundry-icon="arrow-up"></i>Move up</button><button data-layout-action="down"><i data-foundry-icon="arrow-down"></i>Move down</button><button data-layout-action="lock"><i data-foundry-icon="lock"></i>Lock ratio</button></div>` : category === "typography" ? `<div class="context-tools"><button data-type-preset="compact">Compact</button><button data-type-preset="body">Body</button><button data-type-preset="display">Display</button></div>` : category === "color" ? `<div class="context-tools"><button data-color-action="gradient">Linear gradient</button><button data-color-action="clear">Clear fill</button></div>` : "";
|
|
3734
|
+
const tokenMode = category === "layout" && (designGraph?.tokens.length ?? 0) ? `<div class="context-tools"><button class="${tokenOnly ? "active" : ""}" data-token-only><i data-foundry-icon="${tokenOnly ? "lock" : "unlink-2"}"></i>${tokenOnly ? "Token-only on" : "Token-only off"}</button></div>` : "";
|
|
3514
3735
|
return `${categoryTools}${tokenMode}${health}${variantPanel}${tokenPanel}`;
|
|
3515
3736
|
}
|
|
3516
3737
|
async function applyControlValue(control, value, operationLabel) {
|
|
@@ -3533,21 +3754,26 @@ function installFoundryInspector(options = {}) {
|
|
|
3533
3754
|
await record(control, before, after, element, operationLabel);
|
|
3534
3755
|
}
|
|
3535
3756
|
function installContextActions(controls) {
|
|
3536
|
-
controlsRoot.
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3757
|
+
controlsRoot.querySelectorAll(".native-search").forEach(
|
|
3758
|
+
(search) => search.addEventListener("input", (event) => {
|
|
3759
|
+
const queryValue = event.currentTarget.value.toLowerCase();
|
|
3760
|
+
search.closest(".native-panel")?.querySelectorAll("[data-token-search]").forEach((chip) => {
|
|
3761
|
+
chip.hidden = !chip.dataset.tokenSearch?.includes(queryValue);
|
|
3762
|
+
});
|
|
3763
|
+
})
|
|
3764
|
+
);
|
|
3765
|
+
controlsRoot.querySelectorAll("[data-token-only]").forEach(
|
|
3766
|
+
(button) => button.addEventListener("click", () => {
|
|
3767
|
+
tokenOnly = !tokenOnly;
|
|
3768
|
+
renderControls();
|
|
3769
|
+
})
|
|
3770
|
+
);
|
|
3546
3771
|
controlsRoot.querySelectorAll("[data-native-token]").forEach((button) => {
|
|
3547
3772
|
button.addEventListener("click", () => {
|
|
3548
3773
|
const token2 = designGraph?.tokens.find((item) => item.id === button.dataset.nativeToken);
|
|
3549
3774
|
if (!token2) return;
|
|
3550
|
-
const
|
|
3775
|
+
const category = button.closest(".inspector-category")?.dataset.category ?? "layout";
|
|
3776
|
+
const candidateProperties = category === "color" ? ["color", "backgroundColor", "borderColor"] : category === "typography" ? ["fontSize", "fontWeight", "lineHeight", "letterSpacing", "fontFamily"] : category === "effects" ? ["borderRadius"] : ["gap", "paddingTop", "paddingRight", "paddingBottom", "paddingLeft"];
|
|
3551
3777
|
const control = controls.find((item) => item.property === activeControlProperty) ?? candidateProperties.map((property) => controls.find((item) => item.property === property)).find(Boolean);
|
|
3552
3778
|
if (!control) return;
|
|
3553
3779
|
const value = control.kind === "number" ? numberFrom(token2.value) : token2.value;
|
|
@@ -3703,7 +3929,8 @@ function installFoundryInspector(options = {}) {
|
|
|
3703
3929
|
return;
|
|
3704
3930
|
}
|
|
3705
3931
|
comparisonActive = true;
|
|
3706
|
-
|
|
3932
|
+
workspaceState = updateWorkspace(workspaceState, { type: "set-comparison", open: true });
|
|
3933
|
+
trayCompare.classList.add("active");
|
|
3707
3934
|
compareBar.hidden = false;
|
|
3708
3935
|
compareBar.querySelector("[data-compare-scrub]").value = mode === "before" ? "0" : "100";
|
|
3709
3936
|
compareBar.querySelectorAll("[data-compare]").forEach((button) => button.classList.toggle("active", button.dataset.compare === mode));
|
|
@@ -3804,7 +4031,8 @@ function installFoundryInspector(options = {}) {
|
|
|
3804
4031
|
if (isolatedComparisonElement) toggleComparisonIsolation();
|
|
3805
4032
|
showComparison("after");
|
|
3806
4033
|
comparisonActive = false;
|
|
3807
|
-
|
|
4034
|
+
workspaceState = updateWorkspace(workspaceState, { type: "set-comparison", open: false });
|
|
4035
|
+
trayCompare.classList.remove("active");
|
|
3808
4036
|
compareBar.hidden = true;
|
|
3809
4037
|
}
|
|
3810
4038
|
const commands = [
|
|
@@ -3846,7 +4074,7 @@ function installFoundryInspector(options = {}) {
|
|
|
3846
4074
|
const normalized = queryValue.trim().toLowerCase();
|
|
3847
4075
|
const filtered = commands.filter((command) => command.label.toLowerCase().includes(normalized));
|
|
3848
4076
|
commandPalette.querySelector(".command-list").innerHTML = filtered.length ? filtered.map(
|
|
3849
|
-
(command, index) => `<button class="command-item ${index === 0 ? "active" : ""}" data-command="${command.id}"><i data-
|
|
4077
|
+
(command, index) => `<button class="command-item ${index === 0 ? "active" : ""}" data-command="${command.id}"><i data-foundry-icon="${command.icon}"></i><span>${command.label}</span><small>${command.shortcut}</small></button>`
|
|
3850
4078
|
).join("") : '<div class="layers-empty">No commands match.</div>';
|
|
3851
4079
|
renderIcons(commandPalette);
|
|
3852
4080
|
commandPalette.querySelectorAll("[data-command]").forEach(
|
|
@@ -4001,8 +4229,8 @@ function installFoundryInspector(options = {}) {
|
|
|
4001
4229
|
return `<button class="${healthFilter === filter ? "active" : ""}" data-health-filter="${filter}" aria-pressed="${healthFilter === filter}">${label} ${count}</button>`;
|
|
4002
4230
|
}).join("");
|
|
4003
4231
|
healthList.innerHTML = filtered.length ? filtered.map(
|
|
4004
|
-
(issue) => `<article class="health-card" data-health-issue="${escapeHtml(issue.id)}"><div class="health-card-top"><span class="health-severity ${issue.severity}"></span><strong>${escapeHtml(issue.title)}</strong><span>${escapeHtml(issue.severity)}</span></div><p>${escapeHtml(issue.description)}</p><div class="health-evidence"><strong>${escapeHtml(issue.elementLabel)}</strong><br/>${escapeHtml(issue.evidence)}</div><div class="health-actions"><button data-health-select="${escapeHtml(issue.id)}">Select</button><button class="health-ignore" data-health-ignore="${escapeHtml(issue.id)}">Ignore</button>${issue.fix ? `<button class="health-fix ${issue.previewed ? "previewed" : ""}" data-health-fix="${escapeHtml(issue.id)}" ${issue.previewed ? "disabled" : ""}>${issue.previewed ? '<i data-
|
|
4005
|
-
).join("") : `<div class="health-empty"><i data-
|
|
4232
|
+
(issue) => `<article class="health-card" data-health-issue="${escapeHtml(issue.id)}"><div class="health-card-top"><span class="health-severity ${issue.severity}"></span><strong>${escapeHtml(issue.title)}</strong><span>${escapeHtml(issue.severity)}</span></div><p>${escapeHtml(issue.description)}</p><div class="health-evidence"><strong>${escapeHtml(issue.elementLabel)}</strong><br/>${escapeHtml(issue.evidence)}</div><div class="health-actions"><button data-health-select="${escapeHtml(issue.id)}">Select</button><button class="health-ignore" data-health-ignore="${escapeHtml(issue.id)}">Ignore</button>${issue.fix ? `<button class="health-fix ${issue.previewed ? "previewed" : ""}" data-health-fix="${escapeHtml(issue.id)}" ${issue.previewed ? "disabled" : ""}>${issue.previewed ? '<i data-foundry-icon="check"></i> Added to review' : escapeHtml(issue.fix.label)}</button>` : ""}</div></article>`
|
|
4233
|
+
).join("") : `<div class="health-empty"><i data-foundry-icon="${visibleIssues.length ? "triangle-alert" : "check"}"></i>${visibleIssues.length ? "No issues match this filter." : "This viewport is looking healthy."}</div>`;
|
|
4006
4234
|
const ignoredCount = healthIssues.filter((issue) => ignoredHealthIssues.has(issue.id)).length;
|
|
4007
4235
|
const ignoredButton = shadow.querySelector(".health-show-ignored");
|
|
4008
4236
|
ignoredButton.hidden = ignoredCount === 0;
|
|
@@ -4084,123 +4312,159 @@ function installFoundryInspector(options = {}) {
|
|
|
4084
4312
|
showToast("Health correction added to review");
|
|
4085
4313
|
}
|
|
4086
4314
|
function openHealth() {
|
|
4087
|
-
|
|
4088
|
-
healthPanel.hidden = false;
|
|
4089
|
-
shadow.querySelector(".open-health").classList.add("active");
|
|
4090
|
-
shadow.querySelector(".toggle-layers").classList.remove("active");
|
|
4091
|
-
scanDesignHealth();
|
|
4315
|
+
if (workspaceState.utility !== "health") setUtility("health");
|
|
4092
4316
|
}
|
|
4093
4317
|
function closeHealth() {
|
|
4094
|
-
|
|
4095
|
-
|
|
4318
|
+
if (workspaceState.utility === "health") setUtility(null);
|
|
4319
|
+
}
|
|
4320
|
+
function renderMotionControls(animations) {
|
|
4321
|
+
if (!animations.length) return "";
|
|
4322
|
+
return `<section class="inspector-category property-section ${collapsedSections.has("category:motion") ? "collapsed" : ""}" data-category="motion" data-section-key="category:motion"><div class="inspector-heading section-head"><button class="section-toggle" aria-expanded="${String(!collapsedSections.has("category:motion"))}"><i data-foundry-icon="play"></i><strong>Motion</strong></button><span class="property-count">${animations.length} active</span></div><div class="category-body motion-list">${animations.map((animation, index) => {
|
|
4323
|
+
const timing = animation.effect?.getComputedTiming();
|
|
4324
|
+
const authored = animation.effect?.getTiming();
|
|
4325
|
+
const duration = Number(timing?.duration ?? 0) || 1e3;
|
|
4326
|
+
return `<div class="motion-row" data-animation="${index}"><div class="motion-title"><span>Animation ${index + 1}</span><code>${Math.round(duration)} ms</code></div><input class="motion-timeline" data-motion-timeline type="range" min="0" max="${duration}" step="1" value="${Math.min(duration, Number(animation.currentTime ?? 0))}" aria-label="Animation timeline"/><div class="motion-fields"><label>Duration<input data-motion-duration type="number" min="0" step="10" value="${Math.round(duration)}"/></label><label>Delay<input data-motion-delay type="number" step="10" value="${Math.round(Number(authored?.delay ?? 0))}"/></label><label style="grid-column:1/-1">Easing<input data-motion-easing type="text" value="${escapeHtml(String(authored?.easing ?? "linear"))}"/></label></div><div class="motion-actions"><button data-action="toggle">${animation.playState === "paused" ? "Play" : "Pause"}</button><button data-action="slower">\xBD speed</button><button data-action="faster">2\xD7 speed</button><button data-action="restart">Restart</button></div></div>`;
|
|
4327
|
+
}).join("")}</div></section>`;
|
|
4328
|
+
}
|
|
4329
|
+
function installMotionControls(animations) {
|
|
4330
|
+
controlsRoot.querySelectorAll("[data-animation]").forEach((row) => {
|
|
4331
|
+
const animation = animations[Number(row.dataset.animation)];
|
|
4332
|
+
if (!animation) return;
|
|
4333
|
+
row.querySelector("[data-motion-timeline]").addEventListener("input", (event) => {
|
|
4334
|
+
animation.pause();
|
|
4335
|
+
animation.currentTime = Number(event.currentTarget.value);
|
|
4336
|
+
});
|
|
4337
|
+
const installTimingField = (selector, property, label) => {
|
|
4338
|
+
const field = row.querySelector(selector);
|
|
4339
|
+
field.addEventListener("change", () => {
|
|
4340
|
+
const effect = animation.effect;
|
|
4341
|
+
if (!effect) return;
|
|
4342
|
+
const before = effect.getTiming()[property];
|
|
4343
|
+
const after = property === "easing" ? field.value : Number(field.value);
|
|
4344
|
+
effect.updateTiming({ [property]: after });
|
|
4345
|
+
void record(
|
|
4346
|
+
{
|
|
4347
|
+
category: "motion",
|
|
4348
|
+
property: `animation.${row.dataset.animation}.${property}`,
|
|
4349
|
+
label,
|
|
4350
|
+
kind: property === "easing" ? "text" : "number",
|
|
4351
|
+
value: before,
|
|
4352
|
+
unit: property === "easing" ? void 0 : "ms",
|
|
4353
|
+
read: () => effect.getTiming()[property],
|
|
4354
|
+
apply: (value) => effect.updateTiming({ [property]: value })
|
|
4355
|
+
},
|
|
4356
|
+
before,
|
|
4357
|
+
after
|
|
4358
|
+
);
|
|
4359
|
+
});
|
|
4360
|
+
};
|
|
4361
|
+
installTimingField("[data-motion-duration]", "duration", "Duration");
|
|
4362
|
+
installTimingField("[data-motion-delay]", "delay", "Delay");
|
|
4363
|
+
installTimingField("[data-motion-easing]", "easing", "Easing");
|
|
4364
|
+
row.querySelectorAll("[data-action]").forEach(
|
|
4365
|
+
(button) => button.addEventListener("click", () => {
|
|
4366
|
+
const before = animation.playbackRate;
|
|
4367
|
+
if (button.dataset.action === "toggle")
|
|
4368
|
+
animation.playState === "paused" ? animation.play() : animation.pause();
|
|
4369
|
+
if (button.dataset.action === "slower") animation.playbackRate *= 0.5;
|
|
4370
|
+
if (button.dataset.action === "faster") animation.playbackRate *= 2;
|
|
4371
|
+
if (button.dataset.action === "restart") animation.currentTime = 0;
|
|
4372
|
+
void record(
|
|
4373
|
+
{
|
|
4374
|
+
category: "motion",
|
|
4375
|
+
property: `animation.${row.dataset.animation}.playbackRate`,
|
|
4376
|
+
label: "Playback rate",
|
|
4377
|
+
kind: "number",
|
|
4378
|
+
value: before,
|
|
4379
|
+
read: () => animation.playbackRate,
|
|
4380
|
+
apply: () => {
|
|
4381
|
+
}
|
|
4382
|
+
},
|
|
4383
|
+
before,
|
|
4384
|
+
animation.playbackRate
|
|
4385
|
+
);
|
|
4386
|
+
renderControls();
|
|
4387
|
+
})
|
|
4388
|
+
);
|
|
4389
|
+
});
|
|
4096
4390
|
}
|
|
4097
4391
|
function renderControls() {
|
|
4098
4392
|
renderToolTabs();
|
|
4099
|
-
if (
|
|
4100
|
-
|
|
4101
|
-
controlsRoot.innerHTML = animations.length ? `<div class="inspector-heading"><i data-lucide="play"></i><strong>Motion</strong><span class="property-count">${animations.length} active</span></div><div class="motion-list">${animations.map((animation, index) => {
|
|
4102
|
-
const timing = animation.effect?.getComputedTiming();
|
|
4103
|
-
const authored = animation.effect?.getTiming();
|
|
4104
|
-
const duration = Number(timing?.duration ?? 0) || 1e3;
|
|
4105
|
-
return `<div class="motion-row" data-animation="${index}"><div class="motion-title"><span>Animation ${index + 1}</span><code>${Math.round(duration)} ms</code></div><input class="motion-timeline" data-motion-timeline type="range" min="0" max="${duration}" step="1" value="${Math.min(duration, Number(animation.currentTime ?? 0))}" aria-label="Animation timeline"/><div class="motion-fields"><label>Duration<input data-motion-duration type="number" min="0" step="10" value="${Math.round(duration)}"/></label><label>Delay<input data-motion-delay type="number" step="10" value="${Math.round(Number(authored?.delay ?? 0))}"/></label><label style="grid-column:1/-1">Easing<input data-motion-easing type="text" value="${escapeHtml(String(authored?.easing ?? "linear"))}"/></label></div><div class="motion-actions"><button data-action="toggle">${animation.playState === "paused" ? "Play" : "Pause"}</button><button data-action="slower">\xBD speed</button><button data-action="faster">2\xD7 speed</button><button data-action="restart">Restart</button></div></div>`;
|
|
4106
|
-
}).join("")}</div>` : '<div class="empty">No CSS, transition, or Web Animation is active on this element.</div>';
|
|
4107
|
-
renderIcons(controlsRoot);
|
|
4108
|
-
controlsRoot.querySelectorAll("[data-animation]").forEach((row) => {
|
|
4109
|
-
const animation = animations[Number(row.dataset.animation)];
|
|
4110
|
-
if (!animation) return;
|
|
4111
|
-
row.querySelector("[data-motion-timeline]").addEventListener("input", (event) => {
|
|
4112
|
-
animation.pause();
|
|
4113
|
-
animation.currentTime = Number(event.currentTarget.value);
|
|
4114
|
-
});
|
|
4115
|
-
const installTimingField = (selector, property, label) => {
|
|
4116
|
-
const field = row.querySelector(selector);
|
|
4117
|
-
field.addEventListener("change", () => {
|
|
4118
|
-
const effect = animation.effect;
|
|
4119
|
-
if (!effect) return;
|
|
4120
|
-
const before = effect.getTiming()[property];
|
|
4121
|
-
const after = property === "easing" ? field.value : Number(field.value);
|
|
4122
|
-
effect.updateTiming({ [property]: after });
|
|
4123
|
-
void record(
|
|
4124
|
-
{
|
|
4125
|
-
category: "motion",
|
|
4126
|
-
property: `animation.${row.dataset.animation}.${property}`,
|
|
4127
|
-
label,
|
|
4128
|
-
kind: property === "easing" ? "text" : "number",
|
|
4129
|
-
value: before,
|
|
4130
|
-
unit: property === "easing" ? void 0 : "ms",
|
|
4131
|
-
read: () => effect.getTiming()[property],
|
|
4132
|
-
apply: (value) => effect.updateTiming({ [property]: value })
|
|
4133
|
-
},
|
|
4134
|
-
before,
|
|
4135
|
-
after
|
|
4136
|
-
);
|
|
4137
|
-
});
|
|
4138
|
-
};
|
|
4139
|
-
installTimingField("[data-motion-duration]", "duration", "Duration");
|
|
4140
|
-
installTimingField("[data-motion-delay]", "delay", "Delay");
|
|
4141
|
-
installTimingField("[data-motion-easing]", "easing", "Easing");
|
|
4142
|
-
row.querySelectorAll("[data-action]").forEach(
|
|
4143
|
-
(button) => button.addEventListener("click", () => {
|
|
4144
|
-
const before = animation.playbackRate;
|
|
4145
|
-
if (button.dataset.action === "toggle")
|
|
4146
|
-
animation.playState === "paused" ? animation.play() : animation.pause();
|
|
4147
|
-
if (button.dataset.action === "slower") animation.playbackRate *= 0.5;
|
|
4148
|
-
if (button.dataset.action === "faster") animation.playbackRate *= 2;
|
|
4149
|
-
if (button.dataset.action === "restart") animation.currentTime = 0;
|
|
4150
|
-
void record(
|
|
4151
|
-
{
|
|
4152
|
-
category: "motion",
|
|
4153
|
-
property: `animation.${row.dataset.animation}.playbackRate`,
|
|
4154
|
-
label: "Playback rate",
|
|
4155
|
-
kind: "number",
|
|
4156
|
-
value: before,
|
|
4157
|
-
read: () => animation.playbackRate,
|
|
4158
|
-
apply: () => {
|
|
4159
|
-
}
|
|
4160
|
-
},
|
|
4161
|
-
before,
|
|
4162
|
-
animation.playbackRate
|
|
4163
|
-
);
|
|
4164
|
-
renderControls();
|
|
4165
|
-
})
|
|
4166
|
-
);
|
|
4167
|
-
});
|
|
4393
|
+
if (!selected) {
|
|
4394
|
+
renderSelectionEmptyState();
|
|
4168
4395
|
return;
|
|
4169
4396
|
}
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4397
|
+
const groups = [
|
|
4398
|
+
{
|
|
4399
|
+
key: "position",
|
|
4400
|
+
category: "layout",
|
|
4401
|
+
label: "Position and size",
|
|
4402
|
+
icon: "maximize-2",
|
|
4403
|
+
sectionLabels: ["Position and size"]
|
|
4404
|
+
},
|
|
4405
|
+
{
|
|
4406
|
+
key: "layout",
|
|
4407
|
+
category: "layout",
|
|
4408
|
+
label: "Layout and spacing",
|
|
4409
|
+
icon: CATEGORY_ICONS.layout,
|
|
4410
|
+
sectionLabels: ["Flow", "Padding", "Margin"],
|
|
4411
|
+
showContext: true
|
|
4412
|
+
},
|
|
4413
|
+
...["typography", "color", "effects", "content", "accessibility"].map(
|
|
4414
|
+
(category) => ({
|
|
4415
|
+
key: category,
|
|
4416
|
+
category,
|
|
4417
|
+
label: CATEGORY_LABELS[category],
|
|
4418
|
+
icon: CATEGORY_ICONS[category],
|
|
4419
|
+
showContext: true
|
|
4420
|
+
})
|
|
4421
|
+
)
|
|
4422
|
+
];
|
|
4423
|
+
const indexedControls = selectedControls.map((control, index) => ({ control, index })).filter(
|
|
4424
|
+
({ control }) => tokenOnly ? matchingTokens(
|
|
4425
|
+
designGraph?.tokens ?? [],
|
|
4426
|
+
control.property,
|
|
4427
|
+
`${control.value}${control.unit ?? ""}`
|
|
4428
|
+
).length > 0 : true
|
|
4429
|
+
);
|
|
4430
|
+
const categoryMarkup = groups.map((group) => {
|
|
4431
|
+
const configuredCategorySections = CONTROL_SECTIONS[group.category] ?? [];
|
|
4432
|
+
const configuredSections = group.sectionLabels ? configuredCategorySections.filter(
|
|
4433
|
+
(section) => group.sectionLabels.includes(section.label)
|
|
4434
|
+
) : configuredCategorySections;
|
|
4435
|
+
const groupProperties = new Set(
|
|
4436
|
+
configuredSections.flatMap((section) => section.properties)
|
|
4178
4437
|
);
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
const
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
(
|
|
4192
|
-
).join("")
|
|
4438
|
+
const controls = indexedControls.filter(
|
|
4439
|
+
(entry) => entry.control.category === group.category && (!group.sectionLabels || groupProperties.has(entry.control.property))
|
|
4440
|
+
);
|
|
4441
|
+
if (!controls.length) return "";
|
|
4442
|
+
const renderedProperties = /* @__PURE__ */ new Set();
|
|
4443
|
+
const sections = configuredSections.map((section) => {
|
|
4444
|
+
const entries = section.properties.map((property) => controls.find((entry) => entry.control.property === property)).filter((entry) => Boolean(entry));
|
|
4445
|
+
entries.forEach(({ control }) => renderedProperties.add(control.property));
|
|
4446
|
+
if (!entries.length) return "";
|
|
4447
|
+
const sectionKey = `${group.key}:${section.label}`;
|
|
4448
|
+
return `<section class="property-section ${collapsedSections.has(sectionKey) ? "collapsed" : ""}" data-section-key="${escapeHtml(sectionKey)}"><div class="section-head"><button class="section-toggle" aria-expanded="${String(!collapsedSections.has(sectionKey))}"><i data-foundry-icon="chevron-down"></i><strong>${escapeHtml(section.label)}</strong></button>${section.label === "Padding" ? `<button class="section-action ${paddingLinked ? "active" : ""}" data-padding-link aria-label="${paddingLinked ? "Unlink padding values" : "Link padding values"}"><i data-foundry-icon="${paddingLinked ? "link-2" : "unlink-2"}"></i></button>` : ""}</div><div class="section-grid ${section.columns === 2 ? "two" : ""} ${section.stacked ? "stacked" : ""}">${entries.map(
|
|
4449
|
+
({ control, index }) => renderPropertyControl(control, index, section.prefixes?.[control.property])
|
|
4450
|
+
).join("")}</div></section>`;
|
|
4451
|
+
}).join("");
|
|
4452
|
+
const remaining = controls.filter(
|
|
4453
|
+
({ control }) => !renderedProperties.has(control.property)
|
|
4454
|
+
);
|
|
4455
|
+
const remainingSection = remaining.length ? `<section class="property-section ${collapsedSections.has(`${group.key}:Other`) ? "collapsed" : ""}" data-section-key="${escapeHtml(`${group.key}:Other`)}"><div class="section-head"><button class="section-toggle" aria-expanded="${String(!collapsedSections.has(`${group.key}:Other`))}"><i data-foundry-icon="chevron-down"></i><strong>Other</strong></button></div><div class="section-grid">${remaining.map(({ control, index }) => renderPropertyControl(control, index)).join("")}</div></section>` : "";
|
|
4456
|
+
const categoryKey = `category:${group.key}`;
|
|
4457
|
+
return `<section class="inspector-category property-section ${collapsedSections.has(categoryKey) ? "collapsed" : ""}" data-category="${group.key}" data-section-key="${categoryKey}"><div class="inspector-heading section-head"><button class="section-toggle" aria-expanded="${String(!collapsedSections.has(categoryKey))}"><i data-foundry-icon="${group.icon}"></i><strong>${group.label}</strong></button><span class="property-count">${controls.length}</span></div><div class="category-body">${group.showContext ? renderContextPanel(group.category) : ""}${sections}${remainingSection}</div></section>`;
|
|
4193
4458
|
}).join("");
|
|
4194
|
-
const
|
|
4195
|
-
const remainingSection = remaining.length ? `<section class="property-section ${collapsedSections.has(`${activeCategory}:Other`) ? "collapsed" : ""}" data-section-key="${escapeHtml(`${activeCategory}:Other`)}"><div class="section-head"><button class="section-toggle" aria-expanded="${String(!collapsedSections.has(`${activeCategory}:Other`))}"><i data-lucide="chevron-down"></i><strong>Other</strong></button></div><div class="section-grid">${remaining.map(({ control, index }) => renderPropertyControl(control, index)).join("")}</div></section>` : "";
|
|
4196
|
-
const currentBaseline = selected ? baselineForContext(
|
|
4459
|
+
const currentBaseline = baselineForContext(
|
|
4197
4460
|
designMemory,
|
|
4198
4461
|
foundryTargetId(selected),
|
|
4199
4462
|
breakpoint.value,
|
|
4200
4463
|
theme.value,
|
|
4201
4464
|
state.value
|
|
4202
|
-
)
|
|
4203
|
-
|
|
4465
|
+
);
|
|
4466
|
+
const animations = selected.getAnimations();
|
|
4467
|
+
controlsRoot.innerHTML = `${currentBaseline ? `<div class="inspector-baseline"><span class="baseline-badge">Verified baseline \xB7 ${escapeHtml(new Date(currentBaseline.verifiedAt).toLocaleDateString())}</span></div>` : ""}${categoryMarkup}${renderMotionControls(animations)}`;
|
|
4204
4468
|
renderIcons(controlsRoot);
|
|
4205
4469
|
controlsRoot.querySelectorAll(".section-toggle").forEach((button) => {
|
|
4206
4470
|
button.addEventListener("click", () => {
|
|
@@ -4212,24 +4476,26 @@ function installFoundryInspector(options = {}) {
|
|
|
4212
4476
|
button.setAttribute("aria-expanded", String(!collapsed));
|
|
4213
4477
|
if (collapsed) collapsedSections.add(key);
|
|
4214
4478
|
else collapsedSections.delete(key);
|
|
4215
|
-
|
|
4479
|
+
sessionStorage.setItem(
|
|
4216
4480
|
"__foundry_collapsed_sections",
|
|
4217
4481
|
JSON.stringify([...collapsedSections])
|
|
4218
4482
|
);
|
|
4219
4483
|
});
|
|
4220
4484
|
});
|
|
4221
|
-
controlsRoot.
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4485
|
+
controlsRoot.querySelectorAll("[data-padding-link]").forEach(
|
|
4486
|
+
(button) => button.addEventListener("click", () => {
|
|
4487
|
+
paddingLinked = !paddingLinked;
|
|
4488
|
+
renderControls();
|
|
4489
|
+
})
|
|
4490
|
+
);
|
|
4491
|
+
indexedControls.forEach(({ control, index }) => {
|
|
4226
4492
|
const matches = matchingTokens(
|
|
4227
4493
|
designGraph?.tokens ?? [],
|
|
4228
4494
|
control.property,
|
|
4229
4495
|
`${control.value}${control.unit ?? ""}`
|
|
4230
4496
|
);
|
|
4231
|
-
const tokenEligible =
|
|
4232
|
-
if (!tokenEligible || !tokensForCategory(
|
|
4497
|
+
const tokenEligible = control.category === "layout" && /gap|padding|margin/i.test(control.property) || control.category === "typography" && /font|lineHeight|letterSpacing/i.test(control.property) || control.category === "color" && /color|background|fill|stroke/i.test(control.property) || control.category === "effects" && /radius|shadow|blur/i.test(control.property);
|
|
4498
|
+
if (!tokenEligible || !tokensForCategory(control.category).length) return;
|
|
4233
4499
|
const field = controlsRoot.querySelector(`[data-control="${index}"]`);
|
|
4234
4500
|
const label = field?.closest("label");
|
|
4235
4501
|
if (!label) return;
|
|
@@ -4247,7 +4513,7 @@ function installFoundryInspector(options = {}) {
|
|
|
4247
4513
|
});
|
|
4248
4514
|
controlsRoot.querySelectorAll("[data-reset-control]").forEach((button) => {
|
|
4249
4515
|
button.addEventListener("click", () => {
|
|
4250
|
-
const control =
|
|
4516
|
+
const control = selectedControls[Number(button.dataset.resetControl)];
|
|
4251
4517
|
if (!control || !selected) return;
|
|
4252
4518
|
const entry = previewHistory.find(
|
|
4253
4519
|
(item) => item.element === selected && item.property === control.property
|
|
@@ -4276,7 +4542,7 @@ function installFoundryInspector(options = {}) {
|
|
|
4276
4542
|
controlsRoot.querySelectorAll("[data-unit-control]").forEach((unitField) => {
|
|
4277
4543
|
unitField.addEventListener("change", () => {
|
|
4278
4544
|
const index = Number(unitField.dataset.unitControl);
|
|
4279
|
-
const control =
|
|
4545
|
+
const control = selectedControls[index];
|
|
4280
4546
|
const valueField = controlsRoot.querySelector(
|
|
4281
4547
|
`input[data-control="${index}"]`
|
|
4282
4548
|
);
|
|
@@ -4321,7 +4587,8 @@ function installFoundryInspector(options = {}) {
|
|
|
4321
4587
|
});
|
|
4322
4588
|
const fieldRecorders = /* @__PURE__ */ new Map();
|
|
4323
4589
|
controlsRoot.querySelectorAll("[data-control]").forEach((field) => {
|
|
4324
|
-
const
|
|
4590
|
+
const index = Number(field.dataset.control);
|
|
4591
|
+
const control = selectedControls[index];
|
|
4325
4592
|
if (!control) return;
|
|
4326
4593
|
const editedElement = selected;
|
|
4327
4594
|
const recorder = createDebouncedChangeRecorder(180, (before, after) => {
|
|
@@ -4338,7 +4605,7 @@ function installFoundryInspector(options = {}) {
|
|
|
4338
4605
|
}
|
|
4339
4606
|
return record(control, before, after, editedElement);
|
|
4340
4607
|
});
|
|
4341
|
-
fieldRecorders.set(
|
|
4608
|
+
fieldRecorders.set(index, recorder);
|
|
4342
4609
|
field.addEventListener("focus", () => {
|
|
4343
4610
|
activeControlProperty = control.property;
|
|
4344
4611
|
});
|
|
@@ -4347,7 +4614,7 @@ function installFoundryInspector(options = {}) {
|
|
|
4347
4614
|
const value = control.kind === "number" ? Number(field.value) : field.value;
|
|
4348
4615
|
control.apply(value);
|
|
4349
4616
|
if (paddingLinked && control.property.startsWith("padding")) {
|
|
4350
|
-
|
|
4617
|
+
indexedControls.forEach(({ control: linkedControl, index: linkedIndex }) => {
|
|
4351
4618
|
if (linkedControl === control || !["paddingTop", "paddingRight", "paddingBottom", "paddingLeft"].includes(
|
|
4352
4619
|
linkedControl.property
|
|
4353
4620
|
))
|
|
@@ -4367,18 +4634,20 @@ function installFoundryInspector(options = {}) {
|
|
|
4367
4634
|
});
|
|
4368
4635
|
controlsRoot.querySelectorAll("[data-token-control]").forEach((button) => {
|
|
4369
4636
|
button.addEventListener("click", () => {
|
|
4637
|
+
const index = Number(button.dataset.tokenControl);
|
|
4370
4638
|
const field = controlsRoot.querySelector(
|
|
4371
|
-
`[data-control="${
|
|
4639
|
+
`[data-control="${index}"]`
|
|
4372
4640
|
);
|
|
4373
|
-
const control =
|
|
4641
|
+
const control = selectedControls[index];
|
|
4374
4642
|
if (!field || !control) return;
|
|
4375
4643
|
const raw = button.dataset.tokenValue ?? "";
|
|
4376
4644
|
field.value = control.kind === "number" ? String(numberFrom(raw)) : raw;
|
|
4377
4645
|
field.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
|
|
4378
4646
|
});
|
|
4379
4647
|
});
|
|
4380
|
-
installContextActions(
|
|
4648
|
+
installContextActions(selectedControls);
|
|
4381
4649
|
installNumberScrubbing();
|
|
4650
|
+
installMotionControls(animations);
|
|
4382
4651
|
}
|
|
4383
4652
|
function select(element, additive = false) {
|
|
4384
4653
|
if (element === host || host.contains(element)) return;
|
|
@@ -4398,14 +4667,16 @@ function installFoundryInspector(options = {}) {
|
|
|
4398
4667
|
selected = element;
|
|
4399
4668
|
}
|
|
4400
4669
|
selectedControls = controlsFor(element);
|
|
4401
|
-
if (activeCategory === "motion" && !element.getAnimations().length) {
|
|
4402
|
-
activeCategory = "layout";
|
|
4403
|
-
}
|
|
4404
4670
|
const target = targetFor(element);
|
|
4671
|
+
panel.classList.add("has-selection");
|
|
4672
|
+
selectionRoot.classList.remove("selected-flash");
|
|
4673
|
+
void selectionRoot.offsetWidth;
|
|
4674
|
+
selectionRoot.classList.add("selected-flash");
|
|
4405
4675
|
selectionKind.textContent = element.tagName.toLowerCase();
|
|
4406
4676
|
selectionTitle.textContent = selectedElements.length > 1 ? `${selectedElements.length} elements` : target.label;
|
|
4407
4677
|
selectionCode.textContent = element.dataset.foundrySource || foundrySelector(element);
|
|
4408
|
-
selectionState.textContent = "
|
|
4678
|
+
selectionState.textContent = selectedElements.length > 1 ? "Multi-select" : "Selected";
|
|
4679
|
+
selectionHint.textContent = selectedElements.length > 1 ? `${selectedElements.length} layers \xB7 shared controls are shown` : "Shift-click adds layers \xB7 repeat a click to cycle overlaps";
|
|
4409
4680
|
selectionConfidence.textContent = target.confidence === "instrumented" ? "Instrumented" : "Measured target";
|
|
4410
4681
|
selectionStats.hidden = false;
|
|
4411
4682
|
resizeObserver?.disconnect();
|
|
@@ -4420,6 +4691,16 @@ function installFoundryInspector(options = {}) {
|
|
|
4420
4691
|
if (!libraryPanel.hidden) renderDesignMemory();
|
|
4421
4692
|
if (matrixMode) renderWorkbenchMatrix();
|
|
4422
4693
|
}
|
|
4694
|
+
function renderSelectionEmptyState() {
|
|
4695
|
+
controlsRoot.innerHTML = '<div class="empty-state"><span class="empty-state-icon"><i data-foundry-icon="mouse-pointer-2"></i></span><strong>Select something to begin</strong><p>Click any element on the page, or use Layers for a precise structural selection.</p><span class="empty-state-actions"><button data-empty-layers>Open Layers</button><button data-empty-interact>Interact with app</button></span><kbd>Shift-click adds \xB7 Option-click selects while interacting</kbd></div>';
|
|
4696
|
+
renderIcons(controlsRoot);
|
|
4697
|
+
controlsRoot.querySelector("[data-empty-layers]")?.addEventListener("click", () => toggleLayers(true));
|
|
4698
|
+
controlsRoot.querySelector("[data-empty-interact]")?.addEventListener("click", () => {
|
|
4699
|
+
inspecting = false;
|
|
4700
|
+
updateInspectionMode();
|
|
4701
|
+
showToast("Interaction mode on \xB7 Option-click still selects");
|
|
4702
|
+
});
|
|
4703
|
+
}
|
|
4423
4704
|
function clearSelection() {
|
|
4424
4705
|
selected = null;
|
|
4425
4706
|
selectedElements = [];
|
|
@@ -4427,16 +4708,18 @@ function installFoundryInspector(options = {}) {
|
|
|
4427
4708
|
sessionStorage.removeItem("__foundry_selected_selector");
|
|
4428
4709
|
resizeObserver?.disconnect();
|
|
4429
4710
|
outline.hidden = true;
|
|
4711
|
+
panel.classList.remove("has-selection");
|
|
4430
4712
|
shadow.querySelectorAll(".multi-outline").forEach((item) => item.remove());
|
|
4431
4713
|
selectionKind.textContent = "No layer";
|
|
4432
4714
|
selectionTitle.textContent = "Nothing selected";
|
|
4433
4715
|
selectionCode.textContent = "Click any element to inspect it";
|
|
4434
4716
|
selectionState.textContent = "Ready";
|
|
4717
|
+
selectionHint.textContent = "Select mode stays on \xB7 click anywhere to begin";
|
|
4435
4718
|
selectionStats.hidden = true;
|
|
4436
4719
|
selectionPath.hidden = true;
|
|
4437
4720
|
previewLayer(null);
|
|
4438
4721
|
renderToolTabs();
|
|
4439
|
-
|
|
4722
|
+
renderSelectionEmptyState();
|
|
4440
4723
|
updateCanvasActions();
|
|
4441
4724
|
renderLayers();
|
|
4442
4725
|
if (!libraryPanel.hidden) renderDesignMemory();
|
|
@@ -4591,13 +4874,17 @@ function installFoundryInspector(options = {}) {
|
|
|
4591
4874
|
}
|
|
4592
4875
|
function updateInspectionMode() {
|
|
4593
4876
|
inspectButton.classList.toggle("active", inspecting);
|
|
4877
|
+
interactButton.classList.toggle("active", !inspecting);
|
|
4594
4878
|
inspectButton.setAttribute("aria-pressed", String(inspecting));
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
inspectButton.title =
|
|
4879
|
+
interactButton.setAttribute("aria-pressed", String(!inspecting));
|
|
4880
|
+
inspectButton.setAttribute("aria-label", "Select mode");
|
|
4881
|
+
interactButton.setAttribute("aria-label", "Interact mode");
|
|
4882
|
+
inspectButton.dataset.tooltip = "Select";
|
|
4883
|
+
interactButton.dataset.tooltip = "Interact";
|
|
4884
|
+
inspectButton.title = "Select mode: click any element";
|
|
4885
|
+
interactButton.title = "Interaction mode: use the app normally. Option-click still selects.";
|
|
4886
|
+
modeCopyTitle.textContent = inspecting ? "Select mode" : "Interact mode";
|
|
4887
|
+
modeCopyDetail.textContent = inspecting ? "Click any element" : "Option-click to select";
|
|
4601
4888
|
}
|
|
4602
4889
|
async function waitForStableGeometry(changes) {
|
|
4603
4890
|
let previous = "";
|
|
@@ -4780,7 +5067,7 @@ function installFoundryInspector(options = {}) {
|
|
|
4780
5067
|
method: "POST",
|
|
4781
5068
|
body: JSON.stringify({ runId, results })
|
|
4782
5069
|
});
|
|
4783
|
-
if (
|
|
5070
|
+
if (workspaceState.tray === "expanded") renderReviewPayload(payload);
|
|
4784
5071
|
showToast(
|
|
4785
5072
|
`${results.filter((result) => result.passed).length}/${results.length} changes verified`
|
|
4786
5073
|
);
|
|
@@ -4911,19 +5198,27 @@ function installFoundryInspector(options = {}) {
|
|
|
4911
5198
|
document.addEventListener("keydown", nudgeSelection);
|
|
4912
5199
|
document.addEventListener("keyup", commitNudge);
|
|
4913
5200
|
window.addEventListener("scroll", updateOutline, true);
|
|
4914
|
-
|
|
5201
|
+
const handleWorkspaceResize = () => {
|
|
5202
|
+
updateOutline();
|
|
5203
|
+
positionWorkspaceSurfaces();
|
|
5204
|
+
};
|
|
5205
|
+
window.addEventListener("resize", handleWorkspaceResize);
|
|
4915
5206
|
renderToolTabs();
|
|
5207
|
+
renderSelectionEmptyState();
|
|
4916
5208
|
installResizeHandles();
|
|
4917
5209
|
installRadiusHandle();
|
|
4918
5210
|
installPanelResizer();
|
|
4919
5211
|
updateHistoryActions();
|
|
4920
5212
|
updateInspectionMode();
|
|
4921
5213
|
inspectButton.addEventListener("click", () => {
|
|
4922
|
-
inspecting =
|
|
5214
|
+
inspecting = true;
|
|
4923
5215
|
updateInspectionMode();
|
|
4924
|
-
showToast(
|
|
4925
|
-
|
|
4926
|
-
|
|
5216
|
+
showToast("Select mode on \xB7 click any element");
|
|
5217
|
+
});
|
|
5218
|
+
interactButton.addEventListener("click", () => {
|
|
5219
|
+
inspecting = false;
|
|
5220
|
+
updateInspectionMode();
|
|
5221
|
+
showToast("Interaction mode on \xB7 use the app normally");
|
|
4927
5222
|
});
|
|
4928
5223
|
const toggleStatusPopover = () => {
|
|
4929
5224
|
statusPopover.hidden = !statusPopover.hidden;
|
|
@@ -4944,6 +5239,7 @@ function installFoundryInspector(options = {}) {
|
|
|
4944
5239
|
onboarding.hidden = true;
|
|
4945
5240
|
inspecting = true;
|
|
4946
5241
|
updateInspectionMode();
|
|
5242
|
+
showToast("Select mode stays on \xB7 click any element to begin");
|
|
4947
5243
|
});
|
|
4948
5244
|
onboarding.querySelector(".onboarding-shortcuts")?.addEventListener("click", () => {
|
|
4949
5245
|
localStorage.setItem("__foundry_onboarded", "1");
|
|
@@ -4974,6 +5270,8 @@ function installFoundryInspector(options = {}) {
|
|
|
4974
5270
|
shadow.querySelector(".toggle-layers")?.addEventListener("click", () => toggleLayers());
|
|
4975
5271
|
shadow.querySelector(".close-layers")?.addEventListener("click", () => toggleLayers(false));
|
|
4976
5272
|
toggleLayers(sessionStorage.getItem(layersPreferenceKey) !== "closed", false);
|
|
5273
|
+
shadow.querySelectorAll(".toggle-inspector").forEach((button) => button.addEventListener("click", () => toggleInspector()));
|
|
5274
|
+
toggleInspector(true);
|
|
4977
5275
|
layerViewButtons.forEach((button) => {
|
|
4978
5276
|
button.addEventListener("click", () => {
|
|
4979
5277
|
layerView = button.dataset.layerView === "components" ? "components" : "layers";
|
|
@@ -4983,7 +5281,10 @@ function installFoundryInspector(options = {}) {
|
|
|
4983
5281
|
renderLayers();
|
|
4984
5282
|
});
|
|
4985
5283
|
});
|
|
4986
|
-
shadow.querySelector(".open-health")?.addEventListener(
|
|
5284
|
+
shadow.querySelector(".open-health")?.addEventListener(
|
|
5285
|
+
"click",
|
|
5286
|
+
() => workspaceState.utility === "health" ? closeHealth() : openHealth()
|
|
5287
|
+
);
|
|
4987
5288
|
shadow.querySelector(".close-health")?.addEventListener("click", closeHealth);
|
|
4988
5289
|
shadow.querySelector(".health-rescan")?.addEventListener("click", scanDesignHealth);
|
|
4989
5290
|
shadow.querySelector(".health-show-ignored")?.addEventListener("click", () => {
|
|
@@ -4998,6 +5299,8 @@ function installFoundryInspector(options = {}) {
|
|
|
4998
5299
|
libraryPanel.querySelector(".close-library")?.addEventListener("click", closeDesignMemory);
|
|
4999
5300
|
libraryPanel.querySelector("[data-save-recipe]")?.addEventListener("click", saveSelectedRecipe);
|
|
5000
5301
|
libraryPanel.querySelector("[data-capture-baseline]")?.addEventListener("click", saveManualBaseline);
|
|
5302
|
+
installUtilityGeometry(healthPanel, "health");
|
|
5303
|
+
installUtilityGeometry(libraryPanel, "memory");
|
|
5001
5304
|
layerSearch.addEventListener("input", () => renderLayers());
|
|
5002
5305
|
layerTree.addEventListener("scroll", () => {
|
|
5003
5306
|
cancelAnimationFrame(layerScrollFrame);
|
|
@@ -5011,7 +5314,7 @@ function installFoundryInspector(options = {}) {
|
|
|
5011
5314
|
const child = firstLayerChild(selected);
|
|
5012
5315
|
if (child) select(child);
|
|
5013
5316
|
});
|
|
5014
|
-
|
|
5317
|
+
trayCompare.addEventListener("click", () => showComparison("after"));
|
|
5015
5318
|
shadow.querySelector(".open-commands")?.addEventListener("click", openCommands);
|
|
5016
5319
|
compareBar.querySelectorAll("[data-compare]").forEach(
|
|
5017
5320
|
(button) => button.addEventListener("click", () => {
|
|
@@ -5061,8 +5364,6 @@ function installFoundryInspector(options = {}) {
|
|
|
5061
5364
|
shadow.querySelector(".redo")?.addEventListener("click", () => void replayHistory(1));
|
|
5062
5365
|
shadow.querySelector(".align")?.addEventListener("click", () => void alignSelected());
|
|
5063
5366
|
shadow.querySelector(".distribute")?.addEventListener("click", () => void distributeSelected());
|
|
5064
|
-
shadow.querySelector(".verify")?.addEventListener("click", () => void verify());
|
|
5065
|
-
shadow.querySelector(".review")?.addEventListener("click", () => void openReview());
|
|
5066
5367
|
shadow.querySelector(".review-back")?.addEventListener("click", closeReview);
|
|
5067
5368
|
reviewCancel.addEventListener("click", () => {
|
|
5068
5369
|
if (reviewCancel.dataset.action === "cancel") void cancelRun();
|
|
@@ -5117,7 +5418,7 @@ function installFoundryInspector(options = {}) {
|
|
|
5117
5418
|
else if (!healthPanel.hidden) closeHealth();
|
|
5118
5419
|
else if (comparisonActive) closeComparison();
|
|
5119
5420
|
else if (!workbench.hidden) closeWorkbench();
|
|
5120
|
-
else if (
|
|
5421
|
+
else if (workspaceState.tray === "expanded") closeReview();
|
|
5121
5422
|
else clearSelection();
|
|
5122
5423
|
}
|
|
5123
5424
|
document.addEventListener("keydown", handleGlobalShortcuts);
|
|
@@ -5159,7 +5460,7 @@ function installFoundryInspector(options = {}) {
|
|
|
5159
5460
|
document.removeEventListener("keyup", commitNudge);
|
|
5160
5461
|
document.removeEventListener("keydown", handleGlobalShortcuts);
|
|
5161
5462
|
window.removeEventListener("scroll", updateOutline, true);
|
|
5162
|
-
window.removeEventListener("resize",
|
|
5463
|
+
window.removeEventListener("resize", handleWorkspaceResize);
|
|
5163
5464
|
cancelAnimationFrame(selectionHoverFrame);
|
|
5164
5465
|
host.remove();
|
|
5165
5466
|
}
|
|
@@ -5179,57 +5480,3 @@ function installFoundryInspector(options = {}) {
|
|
|
5179
5480
|
export {
|
|
5180
5481
|
installFoundryInspector
|
|
5181
5482
|
};
|
|
5182
|
-
/*! Bundled license information:
|
|
5183
|
-
|
|
5184
|
-
lucide/dist/esm/defaultAttributes.mjs:
|
|
5185
|
-
lucide/dist/esm/createElement.mjs:
|
|
5186
|
-
lucide/dist/esm/shared/src/utils/hasA11yProp.mjs:
|
|
5187
|
-
lucide/dist/esm/shared/src/utils/mergeClasses.mjs:
|
|
5188
|
-
lucide/dist/esm/shared/src/utils/toCamelCase.mjs:
|
|
5189
|
-
lucide/dist/esm/shared/src/utils/toPascalCase.mjs:
|
|
5190
|
-
lucide/dist/esm/replaceElement.mjs:
|
|
5191
|
-
lucide/dist/esm/icons/accessibility.mjs:
|
|
5192
|
-
lucide/dist/esm/icons/activity.mjs:
|
|
5193
|
-
lucide/dist/esm/icons/align-horizontal-space-around.mjs:
|
|
5194
|
-
lucide/dist/esm/icons/arrow-down.mjs:
|
|
5195
|
-
lucide/dist/esm/icons/arrow-left.mjs:
|
|
5196
|
-
lucide/dist/esm/icons/arrow-up.mjs:
|
|
5197
|
-
lucide/dist/esm/icons/bookmark.mjs:
|
|
5198
|
-
lucide/dist/esm/icons/box.mjs:
|
|
5199
|
-
lucide/dist/esm/icons/check.mjs:
|
|
5200
|
-
lucide/dist/esm/icons/chevron-down.mjs:
|
|
5201
|
-
lucide/dist/esm/icons/chevron-right.mjs:
|
|
5202
|
-
lucide/dist/esm/icons/columns-3.mjs:
|
|
5203
|
-
lucide/dist/esm/icons/command.mjs:
|
|
5204
|
-
lucide/dist/esm/icons/component.mjs:
|
|
5205
|
-
lucide/dist/esm/icons/contrast.mjs:
|
|
5206
|
-
lucide/dist/esm/icons/eye-off.mjs:
|
|
5207
|
-
lucide/dist/esm/icons/eye.mjs:
|
|
5208
|
-
lucide/dist/esm/icons/file-text.mjs:
|
|
5209
|
-
lucide/dist/esm/icons/layers.mjs:
|
|
5210
|
-
lucide/dist/esm/icons/layout-grid.mjs:
|
|
5211
|
-
lucide/dist/esm/icons/link-2.mjs:
|
|
5212
|
-
lucide/dist/esm/icons/lock.mjs:
|
|
5213
|
-
lucide/dist/esm/icons/maximize-2.mjs:
|
|
5214
|
-
lucide/dist/esm/icons/mouse-pointer-2.mjs:
|
|
5215
|
-
lucide/dist/esm/icons/palette.mjs:
|
|
5216
|
-
lucide/dist/esm/icons/panels-top-left.mjs:
|
|
5217
|
-
lucide/dist/esm/icons/play.mjs:
|
|
5218
|
-
lucide/dist/esm/icons/redo-2.mjs:
|
|
5219
|
-
lucide/dist/esm/icons/rotate-ccw.mjs:
|
|
5220
|
-
lucide/dist/esm/icons/save.mjs:
|
|
5221
|
-
lucide/dist/esm/icons/sparkles.mjs:
|
|
5222
|
-
lucide/dist/esm/icons/triangle-alert.mjs:
|
|
5223
|
-
lucide/dist/esm/icons/type.mjs:
|
|
5224
|
-
lucide/dist/esm/icons/undo-2.mjs:
|
|
5225
|
-
lucide/dist/esm/icons/unlink-2.mjs:
|
|
5226
|
-
lucide/dist/esm/icons/wand-sparkles.mjs:
|
|
5227
|
-
lucide/dist/esm/icons/x.mjs:
|
|
5228
|
-
lucide/dist/esm/lucide.mjs:
|
|
5229
|
-
(**
|
|
5230
|
-
* @license lucide v1.37.0 - ISC
|
|
5231
|
-
*
|
|
5232
|
-
* This source code is licensed under the ISC license.
|
|
5233
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
5234
|
-
*)
|
|
5235
|
-
*/
|