foundry-design-web-adapter 0.2.0-beta.7 → 0.2.0-beta.8

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/dist/adapter.js CHANGED
@@ -564,237 +564,253 @@ var data9 = {
564
564
  };
565
565
  var check_default = data9;
566
566
 
567
- // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/c/chevron-down.js
567
+ // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/c/circle-dashed.js
568
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="M21.8769 10.4357C22.041 11.4721 22.041 12.5279 21.8769 13.5643M20.0902 17.8778C19.4734 18.7268 18.7268 19.4734 17.8778 20.0902M13.5643 21.8769C12.5279 22.041 11.4721 22.041 10.4357 21.8769M6.12215 20.0902C5.2732 19.4734 4.52663 18.7268 3.90983 17.8778M2.12312 13.5643C1.95896 12.5279 1.95896 11.4721 2.12312 10.4357M3.90983 6.12215C4.52663 5.2732 5.2732 4.52663 6.12215 3.90983M10.4357 2.12312C11.4721 1.95896 12.5279 1.95896 13.5643 2.12312M17.8778 3.90983C18.7268 4.52663 19.4734 5.2732 20.0902 6.12215"/>'
572
+ };
573
+ var circle_dashed_default = data10;
574
+
575
+ // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/c/chevron-down.js
576
+ var data11 = {
569
577
  "width": 24,
570
578
  "height": 24,
571
579
  "body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 9L12 15L18 9"/>'
572
580
  };
573
- var chevron_down_default = data10;
581
+ var chevron_down_default = data11;
574
582
 
575
583
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/c/chevron-right.js
576
- var data11 = {
584
+ var data12 = {
577
585
  "width": 24,
578
586
  "height": 24,
579
587
  "body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 6L15 12L9 18"/>'
580
588
  };
581
- var chevron_right_default = data11;
589
+ var chevron_right_default = data12;
582
590
 
583
591
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/g/grid-3x2.js
584
- var data12 = {
592
+ var data13 = {
585
593
  "width": 24,
586
594
  "height": 24,
587
595
  "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
596
  };
589
- var grid_3x2_default = data12;
597
+ var grid_3x2_default = data13;
590
598
 
591
599
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/s/square-terminal.js
592
- var data13 = {
600
+ var data14 = {
593
601
  "width": 24,
594
602
  "height": 24,
595
603
  "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
604
  };
597
- var square_terminal_default = data13;
605
+ var square_terminal_default = data14;
598
606
 
599
607
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/s/shapes.js
600
- var data14 = {
608
+ var data15 = {
601
609
  "width": 24,
602
610
  "height": 24,
603
611
  "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
612
  };
605
- var shapes_default = data14;
613
+ var shapes_default = data15;
606
614
 
607
615
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/c/circle-half.js
608
- var data15 = {
616
+ var data16 = {
609
617
  "width": 24,
610
618
  "height": 24,
611
619
  "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
620
  };
613
- var circle_half_default = data15;
621
+ var circle_half_default = data16;
614
622
 
615
623
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/c/cursor.js
616
- var data16 = {
624
+ var data17 = {
617
625
  "width": 24,
618
626
  "height": 24,
619
627
  "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
628
  };
621
- var cursor_default = data16;
629
+ var cursor_default = data17;
622
630
 
623
631
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/c/cursor-click.js
624
- var data17 = {
632
+ var data18 = {
625
633
  "width": 24,
626
634
  "height": 24,
627
635
  "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
636
  };
629
- var cursor_click_default = data17;
637
+ var cursor_click_default = data18;
630
638
 
631
639
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/e/eye.js
632
- var data18 = {
640
+ var data19 = {
633
641
  "width": 24,
634
642
  "height": 24,
635
643
  "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
644
  };
637
- var eye_default = data18;
645
+ var eye_default = data19;
638
646
 
639
647
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/e/eye-off.js
640
- var data19 = {
648
+ var data20 = {
641
649
  "width": 24,
642
650
  "height": 24,
643
651
  "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
652
  };
645
- var eye_off_default = data19;
653
+ var eye_off_default = data20;
646
654
 
647
655
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/f/file-text.js
648
- var data20 = {
656
+ var data21 = {
649
657
  "width": 24,
650
658
  "height": 24,
651
659
  "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
660
  };
653
- var file_text_default = data20;
661
+ var file_text_default = data21;
654
662
 
655
663
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/l/layout-dashboard.js
656
- var data21 = {
664
+ var data22 = {
657
665
  "width": 24,
658
666
  "height": 24,
659
667
  "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
668
  };
661
- var layout_dashboard_default = data21;
669
+ var layout_dashboard_default = data22;
662
670
 
663
671
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/g/grid-squares.js
664
- var data22 = {
672
+ var data23 = {
665
673
  "width": 24,
666
674
  "height": 24,
667
675
  "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
676
  };
669
- var grid_squares_default = data22;
677
+ var grid_squares_default = data23;
670
678
 
671
679
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/l/link.js
672
- var data23 = {
680
+ var data24 = {
673
681
  "width": 24,
674
682
  "height": 24,
675
683
  "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
684
  };
677
- var link_default = data23;
685
+ var link_default = data24;
678
686
 
679
687
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/l/link-off.js
680
- var data24 = {
688
+ var data25 = {
681
689
  "width": 24,
682
690
  "height": 24,
683
691
  "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
692
  };
685
- var link_off_default = data24;
693
+ var link_off_default = data25;
686
694
 
687
695
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/l/lock.js
688
- var data25 = {
696
+ var data26 = {
689
697
  "width": 24,
690
698
  "height": 24,
691
699
  "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
700
  };
693
- var lock_default = data25;
701
+ var lock_default = data26;
694
702
 
695
703
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/m/maximize.js
696
- var data26 = {
704
+ var data27 = {
697
705
  "width": 24,
698
706
  "height": 24,
699
707
  "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
708
  };
701
- var maximize_default = data26;
709
+ var maximize_default = data27;
702
710
 
703
711
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/f/flower.js
704
- var data27 = {
712
+ var data28 = {
705
713
  "width": 24,
706
714
  "height": 24,
707
715
  "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
716
  };
709
- var flower_default = data27;
717
+ var flower_default = data28;
710
718
 
711
719
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/p/panel-right.js
712
- var data28 = {
720
+ var data29 = {
713
721
  "width": 24,
714
722
  "height": 24,
715
723
  "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
724
  };
717
- var panel_right_default = data28;
725
+ var panel_right_default = data29;
718
726
 
719
727
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/p/play.js
720
- var data29 = {
728
+ var data30 = {
721
729
  "width": 24,
722
730
  "height": 24,
723
731
  "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
732
  };
725
- var play_default = data29;
733
+ var play_default = data30;
734
+
735
+ // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/p/plus.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="M5 12H19M11.995 19.005V5.005"/>'
740
+ };
741
+ var plus_default = data31;
726
742
 
727
743
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/r/rotate-cw.js
728
- var data30 = {
744
+ var data32 = {
729
745
  "width": 24,
730
746
  "height": 24,
731
747
  "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
748
  };
733
- var rotate_cw_default = data30;
749
+ var rotate_cw_default = data32;
734
750
 
735
751
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/r/refresh-ccw.js
736
- var data31 = {
752
+ var data33 = {
737
753
  "width": 24,
738
754
  "height": 24,
739
755
  "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
756
  };
741
- var refresh_ccw_default = data31;
757
+ var refresh_ccw_default = data33;
742
758
 
743
759
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/d/download.js
744
- var data32 = {
760
+ var data34 = {
745
761
  "width": 24,
746
762
  "height": 24,
747
763
  "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
764
  };
749
- var download_default = data32;
765
+ var download_default = data34;
750
766
 
751
767
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/s/star.js
752
- var data33 = {
768
+ var data35 = {
753
769
  "width": 24,
754
770
  "height": 24,
755
771
  "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
772
  };
757
- var star_default = data33;
773
+ var star_default = data35;
758
774
 
759
775
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/t/triangle-alert.js
760
- var data34 = {
776
+ var data36 = {
761
777
  "width": 24,
762
778
  "height": 24,
763
779
  "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
780
  };
765
- var triangle_alert_default = data34;
781
+ var triangle_alert_default = data36;
766
782
 
767
783
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/c/cursor-text.js
768
- var data35 = {
784
+ var data37 = {
769
785
  "width": 24,
770
786
  "height": 24,
771
787
  "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
788
  };
773
- var cursor_text_default = data35;
789
+ var cursor_text_default = data37;
774
790
 
775
791
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/r/rotate-ccw.js
776
- var data36 = {
792
+ var data38 = {
777
793
  "width": 24,
778
794
  "height": 24,
779
795
  "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
796
  };
781
- var rotate_ccw_default = data36;
797
+ var rotate_ccw_default = data38;
782
798
 
783
799
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/p/pencil-ruler.js
784
- var data37 = {
800
+ var data39 = {
785
801
  "width": 24,
786
802
  "height": 24,
787
803
  "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
804
  };
789
- var pencil_ruler_default = data37;
805
+ var pencil_ruler_default = data39;
790
806
 
791
807
  // ../../node_modules/.pnpm/@iconify-icons+keyline-icons@2.0.0/node_modules/@iconify-icons/keyline-icons/data/x/x.js
792
- var data38 = {
808
+ var data40 = {
793
809
  "width": 24,
794
810
  "height": 24,
795
811
  "body": '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7L17 17M17 7L7 17"/>'
796
812
  };
797
- var x_default = data38;
813
+ var x_default = data40;
798
814
 
799
815
  // src/keyline-icons.ts
800
816
  function normalizeKeylineIcon(icon) {
@@ -814,6 +830,7 @@ var RAW_KEYLINE_ICONS = {
814
830
  "arrow-up": arrow_up_default,
815
831
  bookmark: bookmark_default,
816
832
  box: square_default,
833
+ blur: circle_dashed_default,
817
834
  check: check_default,
818
835
  "chevron-down": chevron_down_default,
819
836
  "chevron-right": chevron_right_default,
@@ -834,6 +851,7 @@ var RAW_KEYLINE_ICONS = {
834
851
  palette: flower_default,
835
852
  "panels-top-left": panel_right_default,
836
853
  play: play_default,
854
+ plus: plus_default,
837
855
  "redo-2": rotate_cw_default,
838
856
  "rotate-ccw": refresh_ccw_default,
839
857
  save: download_default,
@@ -872,6 +890,12 @@ function renderKeylineIcons(root) {
872
890
  // src/ui-foundations.ts
873
891
  var FOUNDRY_UI_FOUNDATION_CSS = `
874
892
  :host {
893
+ --fdc-font-sans:"Foundry Inter",Inter,ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
894
+ --fdc-font-mono:"Foundry JetBrains Mono","JetBrains Mono",ui-monospace,SFMono-Regular,Consolas,monospace;
895
+ --fdc-canvas-accent:#2f6fed;
896
+ --fdc-positive:#138a63;
897
+ --fdc-warning:#b7791f;
898
+ --fdc-negative:#cf3f4f;
875
899
  --fdc-space-1:4px;
876
900
  --fdc-space-2:8px;
877
901
  --fdc-space-3:12px;
@@ -963,6 +987,87 @@ function clampUtilityRect(rect, bounds, minimum = { width: 280, height: 280 }) {
963
987
  };
964
988
  }
965
989
 
990
+ // src/effects.ts
991
+ function clamp(value, minimum, maximum) {
992
+ return Math.min(maximum, Math.max(minimum, value));
993
+ }
994
+ function hexChannel(value) {
995
+ return clamp(Math.round(value), 0, 255).toString(16).padStart(2, "0");
996
+ }
997
+ function rgbColor(value) {
998
+ const match = value.match(
999
+ /rgba?\(\s*([\d.]+)(?:\s+|\s*,\s*)([\d.]+)(?:\s+|\s*,\s*)([\d.]+)(?:\s*(?:\/|,)\s*([\d.]+)%?)?\s*\)/i
1000
+ );
1001
+ if (!match) return void 0;
1002
+ const rawAlpha = match[4] == null ? 1 : Number(match[4]);
1003
+ const percentAlpha = match[0].includes("%") ? rawAlpha / 100 : rawAlpha;
1004
+ return {
1005
+ color: `#${hexChannel(Number(match[1]))}${hexChannel(Number(match[2]))}${hexChannel(Number(match[3]))}`,
1006
+ opacity: clamp(percentAlpha, 0, 1)
1007
+ };
1008
+ }
1009
+ function splitCssList(value) {
1010
+ const entries = [];
1011
+ let depth = 0;
1012
+ let start = 0;
1013
+ for (let index = 0; index < value.length; index += 1) {
1014
+ const character = value[index];
1015
+ if (character === "(") depth += 1;
1016
+ if (character === ")") depth = Math.max(0, depth - 1);
1017
+ if (character === "," && depth === 0) {
1018
+ entries.push(value.slice(start, index).trim());
1019
+ start = index + 1;
1020
+ }
1021
+ }
1022
+ entries.push(value.slice(start).trim());
1023
+ return entries.filter(Boolean);
1024
+ }
1025
+ function parseShadowEffects(value) {
1026
+ if (!value || value.trim().toLowerCase() === "none") return [];
1027
+ return splitCssList(value).map((entry) => {
1028
+ const rgb = rgbColor(entry);
1029
+ const hex = entry.match(/#[\da-f]{6,8}/i)?.[0];
1030
+ const color = rgb?.color ?? (hex ? hex.slice(0, 7) : "#000000");
1031
+ const opacity = rgb?.opacity ?? (hex?.length === 9 ? Number.parseInt(hex.slice(7), 16) / 255 : 1);
1032
+ const withoutColor = entry.replace(/rgba?\([^)]*\)/i, "").replace(/#[\da-f]{3,8}/i, "").replace(/\binset\b/i, "").trim();
1033
+ const values = [...withoutColor.matchAll(/-?[\d.]+(?:px)?/g)].map(
1034
+ (match) => Number(match[0].replace("px", ""))
1035
+ );
1036
+ return {
1037
+ kind: /\binset\b/i.test(entry) ? "inner-shadow" : "drop-shadow",
1038
+ x: values[0] ?? 0,
1039
+ y: values[1] ?? 4,
1040
+ blur: Math.max(0, values[2] ?? 8),
1041
+ spread: values[3] ?? 0,
1042
+ color,
1043
+ opacity: clamp(opacity, 0, 1)
1044
+ };
1045
+ });
1046
+ }
1047
+ function composeShadowEffects(effects) {
1048
+ if (!effects.length) return "none";
1049
+ return effects.map((effect) => {
1050
+ const hex = effect.color.replace("#", "").padEnd(6, "0").slice(0, 6);
1051
+ const red = Number.parseInt(hex.slice(0, 2), 16) || 0;
1052
+ const green = Number.parseInt(hex.slice(2, 4), 16) || 0;
1053
+ const blue = Number.parseInt(hex.slice(4, 6), 16) || 0;
1054
+ const alpha = Math.round(clamp(effect.opacity, 0, 1) * 100);
1055
+ return `${effect.kind === "inner-shadow" ? "inset " : ""}${effect.x}px ${effect.y}px ${Math.max(0, effect.blur)}px ${effect.spread}px rgb(${red} ${green} ${blue} / ${alpha}%)`;
1056
+ }).join(", ");
1057
+ }
1058
+ function blurAmount(value) {
1059
+ const match = value.match(/\bblur\(\s*([\d.]+)px\s*\)/i);
1060
+ return match ? Number(match[1]) : null;
1061
+ }
1062
+ function replaceBlur(value, amount) {
1063
+ const normalized = !value || value.trim().toLowerCase() === "none" ? "" : value.trim();
1064
+ const withoutBlur = normalized.replace(/\bblur\(\s*[\d.]+px\s*\)/gi, "").trim();
1065
+ const parts = [amount == null ? "" : `blur(${Math.max(0, amount)}px)`, withoutBlur].filter(
1066
+ Boolean
1067
+ );
1068
+ return parts.join(" ") || "none";
1069
+ }
1070
+
966
1071
  // src/index.ts
967
1072
  var CATEGORY_LABELS = {
968
1073
  layout: "Layout and spacing",
@@ -1096,7 +1201,7 @@ var CONTROL_SECTIONS = {
1096
1201
  { label: "Stroke", properties: ["borderWidth", "borderColor"] },
1097
1202
  {
1098
1203
  label: "Effects",
1099
- properties: ["boxShadow", "filter"],
1204
+ properties: ["boxShadow", "filter", "backdropFilter"],
1100
1205
  stacked: true
1101
1206
  }
1102
1207
  ],
@@ -1117,7 +1222,9 @@ var CONTROL_SECTIONS = {
1117
1222
  };
1118
1223
  var PANEL_CSS = `
1119
1224
  ${FOUNDRY_UI_FOUNDATION_CSS}
1120
- :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); }
1225
+ @font-face { font-family:"Foundry Inter";src:url("http://127.0.0.1:4387/fonts/inter.woff2") format("woff2");font-style:normal;font-weight:100 900;font-display:swap; }
1226
+ @font-face { font-family:"Foundry JetBrains Mono";src:url("http://127.0.0.1:4387/fonts/jetbrains-mono.woff2") format("woff2");font-style:normal;font-weight:100 800;font-display:swap; }
1227
+ :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:var(--fdc-canvas-accent); --fdc-signal-soft:#172d50; --fdc-component:#9b87f5; --fdc-component-soft:#28233d; --fdc-muted:#9a9aa2; --fdc-font:var(--fdc-font-sans); font-family:var(--fdc-font); color:var(--fdc-ink); }
1121
1228
  *,*::before,*::after { box-sizing:border-box;font-family:inherit; }
1122
1229
  button,select,input { font:inherit; }
1123
1230
  button:focus-visible,select:focus-visible,input:focus-visible { outline:4px solid var(--fdc-signal);outline-offset:4px; }
@@ -1133,10 +1240,11 @@ var PANEL_CSS = `
1133
1240
  .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:8px;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; }
1134
1241
  .selection { position:relative;padding:16px;background:var(--fdc-surface);border-bottom:1px solid var(--fdc-line); }.selection::before { content:"";position:absolute;top:12px;left:0;width:4px;height:0;background:var(--fdc-signal);border-radius:0 4px 4px 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:8px; }.selection-kind { max-width:220px;overflow:hidden;text-overflow:ellipsis;padding:4px 8px;color:#4d4d4d;background:var(--fdc-subtle);border-radius:4px;font:500 12px/1 var(--fdc-font);text-transform:uppercase;letter-spacing:.025em;white-space:nowrap; }.selection-state { color:var(--fdc-muted);font:450 12px/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:4px;overflow:hidden;text-overflow:ellipsis;color:var(--fdc-muted);font:400 12px/1.45 var(--fdc-font);white-space:nowrap; }.selection-hint { display:block;margin-top:8px;color:#858585;font:400 12px/1.45 var(--fdc-font); }.selection-stats { display:flex;gap:4px;margin-top:12px; }.selection-stats[hidden] { display:none; }.selection-stats span { padding:4px 8px;color:#4d4d4d;background:var(--fdc-subtle);border-radius:4px;font:400 12px/1 var(--fdc-font); }.selection-stats span:first-child { color:#0761d1;background:#edf6ff; }.selection.selected-flash strong { animation:fdc-selection-title .2s ease-out; }
1135
1242
  .scope { display:grid;grid-template-columns:1fr 1fr;gap:8px;padding:12px 16px;background:var(--fdc-surface);border-bottom:1px solid var(--fdc-line); }.scope label { display:flex;flex-direction:column;gap:8px;color:var(--fdc-muted);font:500 12px/1.2 var(--fdc-font); }.scope select { width:100%;height:36px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:8px;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; }
1243
+ .fdc-select { position:relative;min-width:0;min-height:32px;display:flex;flex:1;align-self:stretch; }.fdc-select[hidden] { display:none; }.fdc-select>select { position:absolute!important;width:1px!important;height:1px!important;margin:-1px!important;padding:0!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;opacity:0!important;pointer-events:none!important; }.fdc-select-trigger { width:100%;min-width:0;height:36px;display:grid;grid-template-columns:minmax(0,1fr) 12px;align-items:center;gap:8px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:8px;color:var(--fdc-ink);background:var(--fdc-paper);font:400 12px/1 var(--fdc-font-mono);text-align:left;cursor:pointer; }.fdc-select-trigger:hover { border-color:var(--fdc-line-strong);background:var(--fdc-subtle); }.fdc-select-trigger[aria-expanded="true"],.fdc-select-trigger:focus-visible { border-color:var(--fdc-signal);box-shadow:0 0 0 4px color-mix(in srgb,var(--fdc-signal) 18%,transparent);outline:0; }.fdc-select-trigger:disabled { opacity:.4;cursor:not-allowed; }.fdc-select-value { overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }.fdc-select-trigger svg { width:12px;height:12px;color:var(--fdc-muted); }.fdc-select-menu { position:fixed;z-index:2147483647;overflow-x:hidden;overflow-y:auto;padding:4px;border:1px solid var(--fdc-line);border-radius:8px;color:var(--fdc-ink);background:rgb(28 28 31 / 98%);box-shadow:0 16px 36px rgb(0 0 0 / 34%);backdrop-filter:blur(16px);pointer-events:auto; }.fdc-select-menu button { width:100%;min-height:36px;display:grid;grid-template-columns:minmax(0,1fr) 12px;align-items:center;gap:8px;padding:0 8px;border:0;border-radius:4px;color:var(--fdc-muted);background:transparent;font:400 12px/1 var(--fdc-font-mono);text-align:left;cursor:pointer; }.fdc-select-menu button:hover,.fdc-select-menu button:focus-visible { color:var(--fdc-ink);background:var(--fdc-subtle);outline:0; }.fdc-select-menu button[aria-selected="true"] { color:#9ec5ff;background:var(--fdc-signal-soft); }.fdc-select-menu button svg { width:12px;height:12px; }.control-field .fdc-select { min-height:32px; }.control-field .fdc-select-trigger { height:32px;border:0;border-radius:4px;background:transparent;box-shadow:none; }.effect-card-head .fdc-select { min-height:32px; }.effect-card-head .fdc-select-trigger { height:32px;padding-left:0;border:0;background:transparent;box-shadow:none;font-family:var(--fdc-font); }.workbench-controls .fdc-select { width:112px;flex:none;align-self:center; }.workbench-controls .fdc-select-trigger { height:32px; }.fdc-canvas-variant { position:fixed;z-index:2147483645;width:180px;min-height:32px;pointer-events:auto; }.fdc-canvas-variant .fdc-select-trigger { height:32px;color:#9ec5ff;background:var(--fdc-signal-soft);border-color:var(--fdc-signal); }
1136
1244
  .tool-shelf { position:fixed;z-index:2147483646;left:50%;bottom:20px;transform:translateX(-50%);display:flex;align-items:center;gap:8px;max-width:calc(100vw - 32px);padding:8px;background:var(--fdc-surface);border:1px solid var(--fdc-line);border-radius:12px;box-shadow:0 4px 4px 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:4px;padding:0 8px 0 1px; }.mode-copy strong { font-size:12px;font-weight:550;line-height:1.1; }.mode-copy span { color:var(--fdc-muted);font-size:8px;line-height:1.2;white-space:nowrap; }
1137
1245
  .tool-select,.tab { position:relative;flex:none;width:36px;height:36px;display:grid;place-items:center;padding:0;border:0;border-radius:8px;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,.icon-button svg { width:20px;height:20px;pointer-events:none; }.tab 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%,4px);padding:8px 8px;border-radius:4px;background:var(--fdc-ink);color:white;font:400 12px/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:4px;overflow:visible;scrollbar-width:none; }.tab:disabled { color:#a1a1a1;cursor:default; }.tab:disabled:hover { background:transparent; }
1138
1246
  .controls { min-height:212px;overflow:auto;background:var(--fdc-surface); }.inspector-heading { position:sticky;top:0;z-index:1;height:44px;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:16px;height:16px;color:#4d4d4d; }.inspector-heading strong { font-size:12px;font-weight:550; }.property-count { margin-left:auto;color:var(--fdc-muted);font:400 12px/1 var(--fdc-font);letter-spacing:.01em; }.property-section { padding:0;border-bottom:1px solid var(--fdc-line); }.section-head { width:100%;min-height:40px;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:40px;flex:1;display:flex;align-items:center;gap:8px;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:12px;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:8px; }.property-control { display:grid;grid-template-columns:minmax(0,1fr) 132px 24px;align-items:center;gap:8px;min-height:36px; }.property-label { overflow:hidden;text-overflow:ellipsis;color:#4d4d4d;font-size:12px;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:4px;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 4px 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:4px;align-items:center; }.compact-control .control-field { width:100%; }.field-prefix { min-width:28px;padding-left:8px;color:#7a7a7a;font:400 12px/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:32px;padding:0 8px;border:0;background:transparent;color:var(--fdc-ink);font:400 12px/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 4px;color:#707070;font-size:8px;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:16px;height:16px;flex:none;margin-left:8px;border:1px solid rgb(0 0 0 / 10%);border-radius:4px;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:8px;color:#4d4d4d;font:400 12px/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:8px;color:#7a7a7a;font:400 12px/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; }
1139
- .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:8px;font-size:12px;font-weight:550; }.motion-title code { color:var(--fdc-muted);font:400 12px/1.3 var(--fdc-font); }.motion-actions { display:grid;grid-template-columns:repeat(4,1fr);gap:4px; }.motion-actions button { min-height:32px;padding:0 4px;border:1px solid var(--fdc-line);background:var(--fdc-paper);border-radius:4px;color:var(--fdc-ink);font-size:12px;font-weight:400;cursor:pointer; }.motion-actions button:hover { border-color:#c7c7c7;background:var(--fdc-surface); }
1247
+ .effect-section { display:block;padding:0 12px 12px; }.effects-editor,.effect-stack { display:grid;gap:8px; }.effect-empty { margin:0;padding:16px 12px;border:1px dashed var(--fdc-line);border-radius:8px;color:var(--fdc-muted);font-size:12px;text-align:center; }.effect-card { overflow:hidden;border:1px solid var(--fdc-line);border-radius:8px;background:var(--fdc-paper); }.effect-card-head { min-height:36px;display:flex;align-items:center;gap:8px;padding:0 4px 0 8px;border-bottom:1px solid var(--fdc-line); }.effect-card-head strong,.effect-card-head select { min-width:0;flex:1;height:32px;border:0;background:transparent;color:var(--fdc-ink);font:500 12px/1 var(--fdc-font);outline:none; }.effect-symbol { width:20px;height:20px;display:grid;place-items:center;color:var(--fdc-muted); }.effect-symbol svg,.effect-remove svg,.effect-add summary svg,.effect-menu svg { width:16px;height:16px; }.effect-remove { width:28px;height:28px;display:grid;place-items:center;padding:0;border:0;border-radius:4px;background:transparent;color:var(--fdc-muted);cursor:pointer; }.effect-remove:hover { color:var(--fdc-ink);background:var(--fdc-subtle); }.effect-fields { display:grid;gap:8px;padding:8px; }.effect-shadow-fields { grid-template-columns:1fr 1fr; }.effect-value { min-width:0;height:32px;display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;overflow:hidden;border:1px solid var(--fdc-line);border-radius:4px;background:var(--fdc-surface); }.effect-value>span { min-width:28px;padding:0 8px;color:var(--fdc-muted);font:500 12px/1 var(--fdc-font); }.effect-value input { width:100%;height:100%;min-width:0;padding:0 8px;border:0;background:transparent;color:var(--fdc-ink);font:400 12px/1 var(--fdc-font-mono);outline:none; }.effect-color,.effect-blur { display:grid;grid-template-columns:52px minmax(0,1fr);align-items:center;gap:8px;color:var(--fdc-muted);font-size:12px; }.effect-color { grid-column:1/-1; }.effect-color-control { height:32px;display:grid;grid-template-columns:40px minmax(0,1fr) 24px;align-items:center;overflow:hidden;border:1px solid var(--fdc-line);border-radius:4px;background:var(--fdc-surface); }.effect-color-control input[type="color"] { width:40px;height:100%;padding:4px;border:0;background:transparent; }.effect-color-control input[type="color"]::-webkit-color-swatch-wrapper { padding:0; }.effect-color-control input[type="color"]::-webkit-color-swatch { border:0;border-radius:4px; }.effect-color-control input[type="number"] { width:100%;height:100%;min-width:0;padding:0 8px;border:0;border-left:1px solid var(--fdc-line);background:transparent;color:var(--fdc-ink);font:400 12px/1 var(--fdc-font-mono);outline:none; }.effect-color-control>span { color:var(--fdc-muted);font:400 12px/1 var(--fdc-font); }.effect-add { position:relative; }.effect-add summary { min-height:32px;display:flex;align-items:center;justify-content:center;gap:8px;border:1px solid var(--fdc-line);border-radius:8px;background:var(--fdc-paper);color:var(--fdc-ink);font-size:12px;cursor:pointer;list-style:none; }.effect-add summary::-webkit-details-marker { display:none; }.effect-add summary:hover { background:var(--fdc-subtle); }.effect-menu { position:absolute;z-index:8;right:0;bottom:calc(100% + 4px);width:220px;padding:4px;border:1px solid var(--fdc-line);border-radius:8px;background:var(--fdc-elevated);box-shadow:0 12px 28px rgb(0 0 0 / 24%); }.effect-menu button { width:100%;height:32px;display:grid;grid-template-columns:20px minmax(0,1fr) auto;align-items:center;gap:8px;padding:0 8px;border:0;border-radius:4px;background:transparent;color:var(--fdc-ink);font-size:12px;text-align:left;cursor:pointer; }.effect-menu button:hover:not(:disabled) { background:var(--fdc-subtle); }.effect-menu button:disabled { color:var(--fdc-muted);cursor:not-allowed; }.effect-menu small { font:500 8px/1 var(--fdc-font-mono); }.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:8px;font-size:12px;font-weight:550; }.motion-title code { color:var(--fdc-muted);font:400 12px/1.3 var(--fdc-font); }.motion-actions { display:grid;grid-template-columns:repeat(4,1fr);gap:4px; }.motion-actions button { min-height:32px;padding:0 4px;border:1px solid var(--fdc-line);background:var(--fdc-paper);border-radius:4px;color:var(--fdc-ink);font-size:12px;font-weight:400;cursor:pointer; }.motion-actions button:hover { border-color:#c7c7c7;background:var(--fdc-surface); }
1140
1248
  .motion-timeline { width:100%;margin:4px 0 12px;accent-color:var(--fdc-signal); }.motion-fields { display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:8px; }.motion-fields label { display:grid;grid-template-columns:auto 1fr;align-items:center;gap:4px;color:var(--fdc-muted);font-size:8px; }.motion-fields input { width:100%;height:28px;padding:0 8px;border:1px solid var(--fdc-line);border-radius:4px;background:var(--fdc-paper);color:var(--fdc-ink);font-size:12px; }
1141
1249
  .empty { padding:48px 28px;text-align:center;color:var(--fdc-muted);font-size:12px;line-height:1.6; }.empty::before { content:"\u2316";display:grid;place-items:center;width:40px;height:40px;margin:0 auto 12px;color:var(--fdc-signal);background:var(--fdc-signal-soft);border-radius:12px;font:20px/1 var(--fdc-font); }
1142
1250
  .change-dock { min-height:48px;display:grid;grid-template-columns:minmax(0,1fr) 32px 68px;align-items:center;gap:8px;padding:8px 8px;border-top:1px solid var(--fdc-line);background:white; }.change-dock[hidden] { display:none; }.change-dock-copy { min-width:0;padding-left:4px; }.change-dock-copy strong,.change-dock-copy span { display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }.change-dock-copy strong { font-size:12px;font-weight:550; }.change-dock-copy span { margin-top:4px;color:var(--fdc-muted);font-size:8px; }.change-dock button { height:32px;border:1px solid var(--fdc-line);border-radius:4px;background:white;color:var(--fdc-ink);font-size:8px;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:84px 1fr;gap:8px;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:8px;background:var(--fdc-surface);color:var(--fdc-ink);font-size:12px;font-weight:450;cursor:pointer; }.footer button:hover { border-color:#d0d0d0;background:var(--fdc-paper); }.footer .review { align-items:center;justify-content:center;gap:8px;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:20px;height:20px;display:inline-grid;place-items:center;padding:0 4px;color:var(--fdc-ink);background:white;border-radius:1000px;font:500 8px/1 var(--fdc-font); }.change-count[hidden] { display:none; }
@@ -1375,6 +1483,7 @@ var PANEL_CSS = `
1375
1483
  .interface-theme-menu button:not([aria-checked="true"]) svg { visibility:hidden; }
1376
1484
  :host([data-interface-theme="light"]) { color-scheme:light;--fdc-ink:#141416;--fdc-paper:#f0f1f3;--fdc-surface:#ffffff;--fdc-subtle:#f0f1f3;--fdc-elevated:#f7f7f8;--fdc-line:#dedfe2;--fdc-signal:#2563eb;--fdc-signal-soft:#e8f0ff;--fdc-component:#7259d6;--fdc-component-soft:#f0edff;--fdc-muted:#666870; }
1377
1485
  :host([data-interface-theme="light"]) .panel,:host([data-interface-theme="light"]) .layers-panel,:host([data-interface-theme="light"]) .health-panel,:host([data-interface-theme="light"]) .library-panel,:host([data-interface-theme="light"]) .tool-shelf,:host([data-interface-theme="light"]) .onboarding-card,:host([data-interface-theme="light"]) .compare-bar,:host([data-interface-theme="light"]) .command-palette,:host([data-interface-theme="light"]) .status-popover,:host([data-interface-theme="light"]) .canvas-variant,:host([data-interface-theme="light"]) .workspace-bar,:host([data-interface-theme="light"]) .change-tray,:host([data-interface-theme="light"]) .review-modal { color:var(--fdc-ink);background:rgb(255 255 255 / 97%);border-color:var(--fdc-line);box-shadow:0 1px 4px rgb(0 0 0 / 8%),0 16px 36px rgb(0 0 0 / 14%); }
1486
+ :host([data-interface-theme="light"]) .fdc-select-menu { color:var(--fdc-ink);background:rgb(255 255 255 / 98%);border-color:var(--fdc-line);box-shadow:0 1px 4px rgb(0 0 0 / 8%),0 16px 36px rgb(0 0 0 / 14%); }
1378
1487
  :host([data-interface-theme="light"]) .top,:host([data-interface-theme="light"]) .top-actions,:host([data-interface-theme="light"]) .selection,:host([data-interface-theme="light"]) .scope,:host([data-interface-theme="light"]) .controls,:host([data-interface-theme="light"]) .property-section,:host([data-interface-theme="light"]) .change-dock,:host([data-interface-theme="light"]) .footer,:host([data-interface-theme="light"]) .review-view,:host([data-interface-theme="light"]) .review-head,:host([data-interface-theme="light"]) .review-group,:host([data-interface-theme="light"]) .review-group-title,:host([data-interface-theme="light"]) .review-actions,:host([data-interface-theme="light"]) .layers-head,:host([data-interface-theme="light"]) .layer-tree,:host([data-interface-theme="light"]) .health-head,:host([data-interface-theme="light"]) .health-list,:host([data-interface-theme="light"]) .health-footer,:host([data-interface-theme="light"]) .library-head,:host([data-interface-theme="light"]) .library-actions,:host([data-interface-theme="light"]) .library-body,:host([data-interface-theme="light"]) .memory-card,:host([data-interface-theme="light"]) .context-tools,:host([data-interface-theme="light"]) .native-panel,:host([data-interface-theme="light"]) .section-head,:host([data-interface-theme="light"]) .onboarding-step { color:var(--fdc-ink);background:var(--fdc-surface);border-color:var(--fdc-line); }
1379
1488
  :host([data-interface-theme="light"]) .inspector-heading,:host([data-interface-theme="light"]) .review-toolbar,:host([data-interface-theme="light"]) .review-overview,:host([data-interface-theme="light"]) .review-modal .review-actions { color:var(--fdc-ink);background:rgb(255 255 255 / 97%);border-color:var(--fdc-line); }
1380
1489
  :host([data-interface-theme="light"]) .review-modal .review-group-title { background:rgb(247 247 248 / 98%); }
@@ -1401,6 +1510,23 @@ var PANEL_CSS = `
1401
1510
  .section-grid { gap:8px;padding:0 16px 16px; }
1402
1511
  .inspector-category[data-category="position"]>.category-body>.property-section>.section-grid { padding-top:12px; }
1403
1512
  @media (max-width:680px){.panel,.layers-panel{width:auto}.panel-resizer{display:none}.change-tray{right:8px;bottom:8px;left:auto;width:calc(100vw - 16px)}.review-takeover{padding:8px}.review-modal{width:calc(100vw - 16px);height:calc(100vh - 16px);border-radius:12px}.review-modal .review-actions{grid-template-columns:84px 1fr}.panel.change-summary-visible .inspector-scroll{padding-bottom:60px}}
1513
+ :host([data-embedded="true"]) .workspace-bar,
1514
+ :host([data-embedded="true"]) .interface-theme-menu,
1515
+ :host([data-embedded="true"]) .status-popover,
1516
+ :host([data-embedded="true"]) .layers-panel,
1517
+ :host([data-embedded="true"]) .health-panel,
1518
+ :host([data-embedded="true"]) .panel,
1519
+ :host([data-embedded="true"]) .change-tray,
1520
+ :host([data-embedded="true"]) .review-takeover,
1521
+ :host([data-embedded="true"]) .tool-shelf,
1522
+ :host([data-embedded="true"]) .onboarding-card,
1523
+ :host([data-embedded="true"]) .compare-bar,
1524
+ :host([data-embedded="true"]) .command-palette,
1525
+ :host([data-embedded="true"]) .color-popover,
1526
+ :host([data-embedded="true"]) .library-panel,
1527
+ :host([data-embedded="true"]) .workbench,
1528
+ :host([data-embedded="true"]) .comparison-stage,
1529
+ :host([data-embedded="true"]) .canvas-variant { display:none!important; }
1404
1530
  @media (prefers-reduced-motion:reduce){*{transition-duration:.01ms!important}.layer-row.entering,.layer-branch{animation:none!important}}
1405
1531
  `;
1406
1532
  function numberFrom(value) {
@@ -1440,6 +1566,16 @@ function styleControl(element, computed, category, property, label, kind = "text
1440
1566
  )
1441
1567
  };
1442
1568
  }
1569
+ function effectStyleControl(element, computed, property, label) {
1570
+ const control = styleControl(element, computed, "effects", property, label);
1571
+ if (property === "backdropFilter") {
1572
+ control.apply = (value) => {
1573
+ element.style.setProperty("backdrop-filter", String(value));
1574
+ element.style.setProperty("-webkit-backdrop-filter", String(value));
1575
+ };
1576
+ }
1577
+ return control;
1578
+ }
1443
1579
  function numberStyleControl(element, computed, category, property, label, min, max, step) {
1444
1580
  return {
1445
1581
  category,
@@ -1621,8 +1757,9 @@ function controlsFor(element) {
1621
1757
  pxControl(element, computed, "effects", "borderBottomRightRadius", "Bottom right radius", 200),
1622
1758
  pxControl(element, computed, "effects", "borderWidth", "Border width", 32),
1623
1759
  styleControl(element, computed, "effects", "borderColor", "Border color", "color"),
1624
- styleControl(element, computed, "effects", "boxShadow", "Shadow"),
1625
- styleControl(element, computed, "effects", "filter", "Filter"),
1760
+ effectStyleControl(element, computed, "boxShadow", "Shadow"),
1761
+ effectStyleControl(element, computed, "filter", "Layer effects"),
1762
+ effectStyleControl(element, computed, "backdropFilter", "Background effects"),
1626
1763
  {
1627
1764
  category: "content",
1628
1765
  property: "textContent",
@@ -1793,6 +1930,38 @@ function displayValue(control) {
1793
1930
  if (typeof control.value !== "number") return control.value;
1794
1931
  return String(Math.round(control.value * 100) / 100);
1795
1932
  }
1933
+ function controlOptionLabel(control, option) {
1934
+ return option;
1935
+ }
1936
+ function renderShadowEffect(effect, effectIndex, controlIndex) {
1937
+ const label = effect.kind === "inner-shadow" ? "Inner shadow" : "Drop shadow";
1938
+ const numberField = (part, prefix, value) => `<label class="effect-value"><span>${prefix}</span><input type="number" step="1" value="${value}" data-shadow-control="${controlIndex}" data-shadow-index="${effectIndex}" data-shadow-part="${part}" aria-label="${escapeHtml(`${label} ${part}`)}"/></label>`;
1939
+ return `<article class="effect-card" data-effect-card="${effect.kind}"><header class="effect-card-head"><span class="effect-symbol"><i data-foundry-icon="box"></i></span><select data-shadow-kind="${effectIndex}" data-shadow-control="${controlIndex}" aria-label="Shadow type"><option value="drop-shadow" ${effect.kind === "drop-shadow" ? "selected" : ""}>Drop shadow</option><option value="inner-shadow" ${effect.kind === "inner-shadow" ? "selected" : ""}>Inner shadow</option></select><button type="button" class="effect-remove" data-remove-shadow="${effectIndex}" data-shadow-control="${controlIndex}" aria-label="Remove ${label}"><i data-foundry-icon="x"></i></button></header><div class="effect-fields effect-shadow-fields">${numberField("x", "X", effect.x)}${numberField("y", "Y", effect.y)}${numberField("blur", "Blur", effect.blur)}${numberField("spread", "Spread", effect.spread)}<label class="effect-color"><span>Color</span><span class="effect-color-control"><input type="color" value="${escapeHtml(effect.color)}" data-shadow-control="${controlIndex}" data-shadow-index="${effectIndex}" data-shadow-part="color" aria-label="${label} color"/><input type="number" min="0" max="100" step="1" value="${Math.round(effect.opacity * 100)}" data-shadow-control="${controlIndex}" data-shadow-index="${effectIndex}" data-shadow-part="opacity" aria-label="${label} opacity"/><span>%</span></span></label></div></article>`;
1940
+ }
1941
+ function renderBlurEffect(label, kind, amount, controlIndex) {
1942
+ return `<article class="effect-card" data-effect-card="${kind}"><header class="effect-card-head"><span class="effect-symbol"><i data-foundry-icon="blur"></i></span><strong>${label}</strong><button type="button" class="effect-remove" data-remove-blur="${kind}" data-blur-control="${controlIndex}" aria-label="Remove ${label}"><i data-foundry-icon="x"></i></button></header><div class="effect-fields"><label class="effect-blur"><span>Blur</span><span class="effect-value"><span>R</span><input type="number" min="0" max="200" step="1" value="${amount}" data-blur-control="${controlIndex}" aria-label="${label} amount"/></span></label></div></article>`;
1943
+ }
1944
+ function renderEffectsEditor(entries) {
1945
+ const shadowEntry = entries.find(({ control }) => control.property === "boxShadow");
1946
+ const filterEntry = entries.find(({ control }) => control.property === "filter");
1947
+ const backdropEntry = entries.find(({ control }) => control.property === "backdropFilter");
1948
+ const shadows = shadowEntry ? parseShadowEffects(String(shadowEntry.control.value)) : [];
1949
+ const layerBlur = filterEntry ? blurAmount(String(filterEntry.control.value)) : null;
1950
+ const backgroundBlur = backdropEntry ? blurAmount(String(backdropEntry.control.value)) : null;
1951
+ const active = [
1952
+ ...shadowEntry ? shadows.map((effect, index) => renderShadowEffect(effect, index, shadowEntry.index)) : [],
1953
+ ...filterEntry && layerBlur != null ? [renderBlurEffect("Layer blur", "layer-blur", layerBlur, filterEntry.index)] : [],
1954
+ ...backdropEntry && backgroundBlur != null ? [
1955
+ renderBlurEffect(
1956
+ "Background blur",
1957
+ "background-blur",
1958
+ backgroundBlur,
1959
+ backdropEntry.index
1960
+ )
1961
+ ] : []
1962
+ ].join("");
1963
+ return `<div class="effects-editor"><div class="effect-stack">${active || '<p class="effect-empty">No effects applied</p>'}</div><details class="effect-add"><summary><i data-foundry-icon="plus"></i>Add effect</summary><div class="effect-menu" role="menu"><button type="button" data-add-effect="drop-shadow" data-effect-control="${shadowEntry?.index ?? ""}" role="menuitem"><i data-foundry-icon="box"></i><span>Drop shadow</span></button><button type="button" data-add-effect="inner-shadow" data-effect-control="${shadowEntry?.index ?? ""}" role="menuitem"><i data-foundry-icon="box"></i><span>Inner shadow</span></button><button type="button" data-add-effect="layer-blur" data-effect-control="${filterEntry?.index ?? ""}" role="menuitem" ${layerBlur != null ? "disabled" : ""}><i data-foundry-icon="blur"></i><span>Layer blur</span></button><button type="button" data-add-effect="background-blur" data-effect-control="${backdropEntry?.index ?? ""}" role="menuitem" ${backgroundBlur != null ? "disabled" : ""}><i data-foundry-icon="blur"></i><span>Background blur</span></button><button type="button" role="menuitem" disabled title="Available when the project exposes a mapped effect recipe"><i data-foundry-icon="sparkles"></i><span>Noise</span><small>Recipe</small></button><button type="button" role="menuitem" disabled title="Available when the project exposes a mapped effect recipe"><i data-foundry-icon="layout-grid"></i><span>Texture</span><small>Recipe</small></button></div></details></div>`;
1964
+ }
1796
1965
  function isTransparentColor(value) {
1797
1966
  const normalized = value.trim().toLowerCase();
1798
1967
  return normalized === "transparent" || /^rgba\([^)]*,\s*0(?:\.0+)?\s*\)$/.test(normalized) || /^rgb\([^)]*\/\s*0%?\s*\)$/.test(normalized);
@@ -1801,7 +1970,7 @@ function renderControlInput(control, index) {
1801
1970
  const id = `fdc-${index}`;
1802
1971
  if (control.kind === "select") {
1803
1972
  return `<select id="${id}" data-control="${index}" aria-label="${escapeHtml(control.label)}">${control.options?.map(
1804
- (option) => `<option ${String(control.value) === option ? "selected" : ""}>${escapeHtml(option)}</option>`
1973
+ (option) => `<option value="${escapeHtml(option)}" ${String(control.value) === option ? "selected" : ""}>${escapeHtml(controlOptionLabel(control, option))}</option>`
1805
1974
  ).join("")}</select>`;
1806
1975
  }
1807
1976
  if (control.kind === "color") {
@@ -1847,6 +2016,8 @@ function installFoundryInspector(options = {}) {
1847
2016
  const runtimeUrl = (options.runtimeUrl ?? "http://127.0.0.1:4387").replace(/\/$/, "");
1848
2017
  const sessionId = options.sessionId ?? query.get("__foundry_session") ?? "";
1849
2018
  const token = options.token ?? query.get("__foundry_token") ?? "";
2019
+ const embeddedWorkspace = query.get("__foundry_embedded") === "1" && window.parent !== window;
2020
+ const runtimeOrigin = new URL(runtimeUrl).origin;
1850
2021
  const host = document.createElement("div");
1851
2022
  const interfaceThemeKey = "__foundry_interface_theme";
1852
2023
  const systemDarkTheme = window.matchMedia("(prefers-color-scheme: dark)");
@@ -1854,6 +2025,7 @@ function installFoundryInspector(options = {}) {
1854
2025
  let interfaceThemePreference = storedInterfaceTheme === "light" || storedInterfaceTheme === "dark" ? storedInterfaceTheme : "system";
1855
2026
  const resolvedInterfaceTheme = () => resolveInterfaceTheme(interfaceThemePreference, systemDarkTheme.matches);
1856
2027
  host.dataset.foundryOverlay = "true";
2028
+ host.dataset.embedded = String(embeddedWorkspace);
1857
2029
  host.dataset.interfaceTheme = resolvedInterfaceTheme();
1858
2030
  host.dataset.interfaceThemePreference = interfaceThemePreference;
1859
2031
  const shadow = host.attachShadow({ mode: "open" });
@@ -1997,7 +2169,220 @@ function installFoundryInspector(options = {}) {
1997
2169
  function renderIcons(root) {
1998
2170
  renderKeylineIcons(root);
1999
2171
  }
2172
+ let openFdcSelect;
2173
+ let fdcSelectId = 0;
2174
+ let ignoreFdcSelectScrollUntil = 0;
2175
+ function closeFdcSelect(restoreFocus = true) {
2176
+ if (!openFdcSelect) return false;
2177
+ const { trigger, menu, typeaheadTimer } = openFdcSelect;
2178
+ if (typeaheadTimer) clearTimeout(typeaheadTimer);
2179
+ trigger.setAttribute("aria-expanded", "false");
2180
+ menu.remove();
2181
+ openFdcSelect = void 0;
2182
+ if (restoreFocus && trigger.isConnected) trigger.focus();
2183
+ return true;
2184
+ }
2185
+ function syncFdcSelect(select2) {
2186
+ const wrapper = select2.parentElement;
2187
+ const trigger = wrapper?.querySelector(".fdc-select-trigger");
2188
+ if (!wrapper || !trigger) return;
2189
+ if (wrapper.hidden !== select2.hidden) wrapper.hidden = select2.hidden;
2190
+ if (select2.classList.contains("canvas-variant")) {
2191
+ wrapper.style.left = select2.style.left;
2192
+ wrapper.style.top = select2.style.top;
2193
+ }
2194
+ const label = select2.selectedOptions[0]?.textContent ?? select2.options[0]?.textContent ?? "";
2195
+ const value = trigger.querySelector(".fdc-select-value");
2196
+ if (value && value.textContent !== label) value.textContent = label;
2197
+ if (trigger.disabled !== select2.disabled) trigger.disabled = select2.disabled;
2198
+ trigger.setAttribute("aria-disabled", String(select2.disabled));
2199
+ }
2200
+ function positionFdcSelect(trigger, menu) {
2201
+ const rect = trigger.getBoundingClientRect();
2202
+ const margin = 8;
2203
+ const maxHeight = Math.min(240, window.innerHeight - margin * 2);
2204
+ menu.style.minWidth = `${Math.max(160, rect.width)}px`;
2205
+ menu.style.maxWidth = `${Math.max(160, window.innerWidth - margin * 2)}px`;
2206
+ menu.style.maxHeight = `${maxHeight}px`;
2207
+ const left = Math.max(
2208
+ margin,
2209
+ Math.min(rect.left, window.innerWidth - menu.offsetWidth - margin)
2210
+ );
2211
+ menu.style.left = `${left}px`;
2212
+ const menuHeight = Math.min(menu.scrollHeight, maxHeight);
2213
+ const roomBelow = window.innerHeight - rect.bottom - margin;
2214
+ const openAbove = roomBelow < menuHeight && rect.top > roomBelow;
2215
+ menu.style.top = `${Math.max(
2216
+ margin,
2217
+ openAbove ? rect.top - menuHeight - 4 : Math.min(rect.bottom + 4, window.innerHeight - menuHeight - margin)
2218
+ )}px`;
2219
+ }
2220
+ function moveFdcSelectFocus(menu, direction) {
2221
+ const options2 = [...menu.querySelectorAll("button:not(:disabled)")];
2222
+ if (!options2.length) return;
2223
+ const current = options2.indexOf(shadow.activeElement);
2224
+ const next = direction === "first" ? 0 : direction === "last" ? options2.length - 1 : (current + direction + options2.length) % options2.length;
2225
+ options2[next]?.focus({ preventScroll: true });
2226
+ options2[next]?.scrollIntoView({ block: "nearest" });
2227
+ }
2228
+ function openFdcSelectMenu(select2, trigger) {
2229
+ if (openFdcSelect?.select === select2) {
2230
+ closeFdcSelect();
2231
+ return;
2232
+ }
2233
+ closeFdcSelect(false);
2234
+ ignoreFdcSelectScrollUntil = performance.now() + 250;
2235
+ const menu = document.createElement("div");
2236
+ menu.className = "fdc-select-menu";
2237
+ menu.id = `${select2.id}-listbox`;
2238
+ menu.setAttribute("role", "listbox");
2239
+ menu.setAttribute("aria-label", trigger.getAttribute("aria-label") ?? "Options");
2240
+ menu.innerHTML = [...select2.options].map(
2241
+ (option, index) => `<button type="button" role="option" data-fdc-option="${index}" aria-selected="${option.selected}" ${option.disabled ? "disabled" : ""}><span>${escapeHtml(option.textContent)}</span>${option.selected ? '<i data-foundry-icon="check"></i>' : ""}</button>`
2242
+ ).join("");
2243
+ shadow.append(menu);
2244
+ renderIcons(menu);
2245
+ trigger.setAttribute("aria-controls", menu.id);
2246
+ trigger.setAttribute("aria-expanded", "true");
2247
+ positionFdcSelect(trigger, menu);
2248
+ const selected2 = menu.querySelector('[aria-selected="true"]');
2249
+ (selected2 ?? menu.querySelector("button:not(:disabled)"))?.focus({
2250
+ preventScroll: true
2251
+ });
2252
+ openFdcSelect = { select: select2, trigger, menu, typeahead: "" };
2253
+ menu.addEventListener("click", (event) => {
2254
+ const option = event.target.closest("[data-fdc-option]");
2255
+ if (!option || option.disabled) return;
2256
+ select2.selectedIndex = Number(option.dataset.fdcOption);
2257
+ select2.dispatchEvent(new Event("change", { bubbles: true }));
2258
+ syncFdcSelect(select2);
2259
+ closeFdcSelect();
2260
+ });
2261
+ }
2262
+ function selectAccessibleLabel(select2) {
2263
+ const explicit = select2.getAttribute("aria-label");
2264
+ if (explicit) return explicit;
2265
+ const wrappingLabel = select2.closest("label");
2266
+ const textLabel = [...wrappingLabel?.childNodes ?? []].filter((node) => node.nodeType === Node.TEXT_NODE).map((node) => node.textContent?.trim()).filter(Boolean).join(" ");
2267
+ if (textLabel) return textLabel;
2268
+ const visibleLabel = wrappingLabel?.querySelector(
2269
+ ":scope > span:not(.foundry-select):not(.fdc-select), :scope > strong, :scope > small"
2270
+ );
2271
+ return visibleLabel?.textContent?.trim() || "Choose an option";
2272
+ }
2273
+ function upgradeFdcSelect(select2) {
2274
+ if (select2.dataset.foundrySelect === "true") {
2275
+ syncFdcSelect(select2);
2276
+ return;
2277
+ }
2278
+ select2.dataset.foundrySelect = "true";
2279
+ if (!select2.id) select2.id = `foundry-overlay-select-${++fdcSelectId}`;
2280
+ const wrapper = document.createElement("span");
2281
+ wrapper.className = select2.classList.contains("canvas-variant") ? "fdc-select fdc-canvas-variant" : "fdc-select";
2282
+ select2.before(wrapper);
2283
+ wrapper.append(select2);
2284
+ const trigger = document.createElement("button");
2285
+ trigger.type = "button";
2286
+ trigger.className = "fdc-select-trigger";
2287
+ trigger.setAttribute("role", "combobox");
2288
+ trigger.setAttribute("aria-haspopup", "listbox");
2289
+ trigger.setAttribute("aria-expanded", "false");
2290
+ const accessibleLabel = selectAccessibleLabel(select2);
2291
+ select2.setAttribute("aria-hidden", "true");
2292
+ select2.tabIndex = -1;
2293
+ trigger.setAttribute("aria-label", accessibleLabel);
2294
+ trigger.innerHTML = '<span class="fdc-select-value"></span><i data-foundry-icon="chevron-down"></i>';
2295
+ wrapper.append(trigger);
2296
+ renderIcons(trigger);
2297
+ trigger.addEventListener("click", () => openFdcSelectMenu(select2, trigger));
2298
+ trigger.addEventListener("keydown", (event) => {
2299
+ if (!["ArrowDown", "ArrowUp", "Home", "End", "Enter", " "].includes(event.key)) return;
2300
+ event.preventDefault();
2301
+ event.stopPropagation();
2302
+ if (!openFdcSelect || openFdcSelect.select !== select2) openFdcSelectMenu(select2, trigger);
2303
+ if (!openFdcSelect) return;
2304
+ if (event.key === "ArrowUp") moveFdcSelectFocus(openFdcSelect.menu, -1);
2305
+ if (event.key === "Home") moveFdcSelectFocus(openFdcSelect.menu, "first");
2306
+ if (event.key === "End") moveFdcSelectFocus(openFdcSelect.menu, "last");
2307
+ });
2308
+ select2.addEventListener("focus", () => trigger.focus());
2309
+ select2.addEventListener("change", () => syncFdcSelect(select2));
2310
+ syncFdcSelect(select2);
2311
+ }
2312
+ function upgradeFdcSelects(root = shadow) {
2313
+ root.querySelectorAll("select").forEach(upgradeFdcSelect);
2314
+ }
2315
+ const fdcSelectObserver = new MutationObserver(() => upgradeFdcSelects());
2316
+ function handleFdcSelectKeydown(event) {
2317
+ if (!(event instanceof KeyboardEvent)) return;
2318
+ if (!openFdcSelect) return;
2319
+ const { menu } = openFdcSelect;
2320
+ if (event.key === "Escape") {
2321
+ event.preventDefault();
2322
+ event.stopPropagation();
2323
+ closeFdcSelect();
2324
+ return;
2325
+ }
2326
+ if (event.key === "Tab") {
2327
+ closeFdcSelect(false);
2328
+ return;
2329
+ }
2330
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
2331
+ event.preventDefault();
2332
+ moveFdcSelectFocus(menu, event.key === "ArrowDown" ? 1 : -1);
2333
+ return;
2334
+ }
2335
+ if (event.key === "Home" || event.key === "End") {
2336
+ event.preventDefault();
2337
+ moveFdcSelectFocus(menu, event.key === "Home" ? "first" : "last");
2338
+ return;
2339
+ }
2340
+ if (event.key === "Enter" || event.key === " ") {
2341
+ const option = shadow.activeElement?.closest(
2342
+ "[data-fdc-option]"
2343
+ );
2344
+ if (option) {
2345
+ event.preventDefault();
2346
+ option.click();
2347
+ }
2348
+ return;
2349
+ }
2350
+ if (event.key.length === 1 && /\S/.test(event.key)) {
2351
+ if (openFdcSelect.typeaheadTimer) clearTimeout(openFdcSelect.typeaheadTimer);
2352
+ openFdcSelect.typeahead += event.key.toLowerCase();
2353
+ const match = [...menu.querySelectorAll("button:not(:disabled)")].find(
2354
+ (button) => button.textContent?.trim().toLowerCase().startsWith(openFdcSelect?.typeahead ?? "")
2355
+ );
2356
+ match?.focus({ preventScroll: true });
2357
+ openFdcSelect.typeaheadTimer = setTimeout(() => {
2358
+ if (openFdcSelect) openFdcSelect.typeahead = "";
2359
+ }, 500);
2360
+ }
2361
+ }
2362
+ function handleFdcSelectDismiss(event) {
2363
+ if (!openFdcSelect) return;
2364
+ const path = event.composedPath();
2365
+ if (!path.includes(openFdcSelect.menu) && !path.includes(openFdcSelect.trigger))
2366
+ closeFdcSelect(false);
2367
+ }
2368
+ function closeFdcSelectForViewportChange(event) {
2369
+ if (event?.type === "scroll" && performance.now() < ignoreFdcSelectScrollUntil) return;
2370
+ if (event?.type === "scroll" && event.target instanceof Node && openFdcSelect?.menu.contains(event.target))
2371
+ return;
2372
+ closeFdcSelect(false);
2373
+ }
2000
2374
  renderIcons(shadow);
2375
+ upgradeFdcSelects();
2376
+ fdcSelectObserver.observe(shadow, {
2377
+ childList: true,
2378
+ subtree: true,
2379
+ attributes: true,
2380
+ attributeFilter: ["disabled", "hidden"]
2381
+ });
2382
+ shadow.addEventListener("keydown", handleFdcSelectKeydown);
2383
+ document.addEventListener("pointerdown", handleFdcSelectDismiss, true);
2384
+ window.addEventListener("resize", closeFdcSelectForViewportChange);
2385
+ window.addEventListener("scroll", closeFdcSelectForViewportChange, true);
2001
2386
  const outline = shadow.querySelector(".outline");
2002
2387
  const panel = shadow.querySelector(".panel");
2003
2388
  const controlsRoot = shadow.querySelector(".controls");
@@ -2182,7 +2567,229 @@ function installFoundryInspector(options = {}) {
2182
2567
  let designMemory = emptyDesignMemory();
2183
2568
  let matrixMode = false;
2184
2569
  let lastUtilityTrigger = null;
2570
+ let workspaceCanvasTool = inspecting ? "select" : "interact";
2571
+ let embeddedSpaceHeld = false;
2572
+ let embeddedPanActive = false;
2573
+ let embeddedPanPointer = null;
2185
2574
  const utilityRects = /* @__PURE__ */ new Map();
2575
+ let workspacePublishFrame = 0;
2576
+ function workspaceSnapshot() {
2577
+ if (!layerEntries.length) discoverLayers();
2578
+ const rect = selected?.getBoundingClientRect();
2579
+ return {
2580
+ version: 1,
2581
+ mode: inspecting ? "select" : "interact",
2582
+ interfaceTheme: resolvedInterfaceTheme(),
2583
+ context: {
2584
+ scope: scope.value,
2585
+ breakpoint: breakpoint.value,
2586
+ theme: theme.value,
2587
+ state: state.value
2588
+ },
2589
+ selection: selected ? {
2590
+ id: foundryTargetId(selected),
2591
+ selector: foundrySelector(selected),
2592
+ label: targetFor(selected).label,
2593
+ kind: selected.tagName.toLowerCase(),
2594
+ source: selected.dataset.foundrySource ?? foundrySelector(selected),
2595
+ confidence: targetFor(selected).confidence,
2596
+ width: rect ? Math.round(rect.width * 100) / 100 : 0,
2597
+ height: rect ? Math.round(rect.height * 100) / 100 : 0,
2598
+ count: selectedElements.length
2599
+ } : null,
2600
+ layers: layerEntries.slice(0, 500).map((entry) => ({
2601
+ id: foundryTargetId(entry.element),
2602
+ selector: foundrySelector(entry.element),
2603
+ label: entry.label,
2604
+ kind: entry.kind,
2605
+ depth: entry.depth,
2606
+ instrumented: entry.instrumented,
2607
+ hasChildren: entry.hasChildren,
2608
+ selected: selectedElements.includes(entry.element)
2609
+ })),
2610
+ controls: selectedControls.map((control, index) => ({
2611
+ index,
2612
+ category: control.category,
2613
+ property: control.property,
2614
+ label: control.label,
2615
+ kind: control.kind,
2616
+ value: control.read(),
2617
+ unit: control.unit,
2618
+ min: control.min,
2619
+ max: control.max,
2620
+ step: control.step,
2621
+ options: control.options
2622
+ })),
2623
+ history: { canUndo: historyCursor > 0, canRedo: historyCursor < previewHistory.length },
2624
+ project: {
2625
+ tokens: designGraph?.tokens ?? [],
2626
+ components: designGraph?.components ?? [],
2627
+ breakpoints: designGraph?.breakpoints ?? [],
2628
+ themes: designGraph?.themes ?? [],
2629
+ states: designGraph?.states ?? []
2630
+ },
2631
+ health: healthIssues.map((issue) => ({
2632
+ id: issue.id,
2633
+ kind: issue.category,
2634
+ title: issue.title,
2635
+ detail: `${issue.elementLabel}: ${issue.description}`,
2636
+ severity: issue.severity
2637
+ })),
2638
+ memory: designMemory
2639
+ };
2640
+ }
2641
+ function publishWorkspaceState() {
2642
+ if (!embeddedWorkspace) return;
2643
+ cancelAnimationFrame(workspacePublishFrame);
2644
+ workspacePublishFrame = requestAnimationFrame(() => {
2645
+ window.parent.postMessage(
2646
+ { type: "foundry:workspace-state", sessionId, payload: workspaceSnapshot() },
2647
+ runtimeOrigin
2648
+ );
2649
+ });
2650
+ }
2651
+ function publishCanvasInput(action, payload = {}) {
2652
+ if (!embeddedWorkspace) return;
2653
+ window.parent.postMessage(
2654
+ { type: "foundry:canvas-input", sessionId, payload: { action, ...payload } },
2655
+ runtimeOrigin
2656
+ );
2657
+ }
2658
+ function handleWorkspaceMessage(event) {
2659
+ if (!embeddedWorkspace || event.source !== window.parent || event.origin !== runtimeOrigin)
2660
+ return;
2661
+ const message = event.data;
2662
+ if (message.type !== "foundry:workspace-command" || message.sessionId !== sessionId) return;
2663
+ const payload = message.payload ?? {};
2664
+ if (message.command === "request-state") publishWorkspaceState();
2665
+ if (message.command === "set-mode") {
2666
+ workspaceCanvasTool = payload.mode === "pan" ? "pan" : payload.mode === "interact" ? "interact" : "select";
2667
+ inspecting = workspaceCanvasTool === "select";
2668
+ document.documentElement.style.cursor = workspaceCanvasTool === "pan" ? "grab" : "";
2669
+ updateInspectionMode();
2670
+ publishWorkspaceState();
2671
+ }
2672
+ if (message.command === "select") {
2673
+ const element = resolveFoundrySelector(document, String(payload.selector ?? ""));
2674
+ if (element) select(element, Boolean(payload.additive));
2675
+ }
2676
+ if (message.command === "set-control") {
2677
+ const control = selectedControls[Number(payload.index)] ?? selectedControls.find((item) => item.property === payload.property);
2678
+ if (control) {
2679
+ void applyControlValue(
2680
+ control,
2681
+ payload.value,
2682
+ `Adjust ${control.label}`
2683
+ ).then(() => {
2684
+ if (selected) selectedControls = controlsFor(selected);
2685
+ renderControls();
2686
+ publishWorkspaceState();
2687
+ });
2688
+ }
2689
+ }
2690
+ if (message.command === "set-context") {
2691
+ const fields = { scope, breakpoint, theme, state };
2692
+ const key = String(payload.key);
2693
+ const field = fields[key];
2694
+ if (field) {
2695
+ field.value = String(payload.value ?? "current");
2696
+ field.dispatchEvent(new Event("change", { bubbles: true }));
2697
+ publishWorkspaceState();
2698
+ }
2699
+ }
2700
+ if (message.command === "undo") void replayHistory(-1).then(publishWorkspaceState);
2701
+ if (message.command === "redo") void replayHistory(1).then(publishWorkspaceState);
2702
+ if (message.command === "compare") {
2703
+ const mode = payload.mode === "before" ? "before" : "after";
2704
+ showComparison(mode);
2705
+ publishWorkspaceState();
2706
+ }
2707
+ if (message.command === "interface-theme") {
2708
+ const preference = String(payload.value);
2709
+ if (preference === "system" || preference === "light" || preference === "dark") {
2710
+ applyInterfaceTheme(preference);
2711
+ publishWorkspaceState();
2712
+ }
2713
+ }
2714
+ if (message.command === "scan-health") {
2715
+ scanDesignHealth();
2716
+ window.setTimeout(publishWorkspaceState, 0);
2717
+ }
2718
+ }
2719
+ function handleEmbeddedCanvasKeyDown(event) {
2720
+ if (!embeddedWorkspace || event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement || event.target instanceof HTMLSelectElement || event.target instanceof HTMLElement && event.target.isContentEditable)
2721
+ return;
2722
+ if (event.code === "Space") {
2723
+ event.preventDefault();
2724
+ embeddedSpaceHeld = true;
2725
+ publishCanvasInput("space", { pressed: true });
2726
+ return;
2727
+ }
2728
+ const key = event.key.toLowerCase();
2729
+ if (key === "h" || key === "v") {
2730
+ event.preventDefault();
2731
+ event.stopImmediatePropagation();
2732
+ publishCanvasInput("shortcut", { key });
2733
+ }
2734
+ }
2735
+ function handleEmbeddedCanvasKeyUp(event) {
2736
+ if (!embeddedWorkspace || event.code !== "Space") return;
2737
+ embeddedSpaceHeld = false;
2738
+ publishCanvasInput("space", { pressed: false });
2739
+ }
2740
+ function handleEmbeddedCanvasPointerDown(event) {
2741
+ if (!embeddedWorkspace) return;
2742
+ const shouldPan = workspaceCanvasTool === "pan" || embeddedSpaceHeld || event.button === 1;
2743
+ if (!shouldPan || event.composedPath().includes(host)) return;
2744
+ event.preventDefault();
2745
+ event.stopImmediatePropagation();
2746
+ embeddedPanActive = true;
2747
+ embeddedPanPointer = event.target instanceof Element ? event.target : null;
2748
+ if (embeddedPanPointer instanceof HTMLElement)
2749
+ embeddedPanPointer.setPointerCapture(event.pointerId);
2750
+ document.documentElement.style.cursor = "grabbing";
2751
+ publishCanvasInput("pan-start", { screenX: event.screenX, screenY: event.screenY });
2752
+ }
2753
+ function handleEmbeddedCanvasPointerMove(event) {
2754
+ if (!embeddedPanActive) return;
2755
+ event.preventDefault();
2756
+ event.stopImmediatePropagation();
2757
+ publishCanvasInput("pan-move", { screenX: event.screenX, screenY: event.screenY });
2758
+ }
2759
+ function handleEmbeddedCanvasPointerUp(event) {
2760
+ if (!embeddedPanActive) return;
2761
+ event.preventDefault();
2762
+ event.stopImmediatePropagation();
2763
+ embeddedPanActive = false;
2764
+ if (embeddedPanPointer instanceof HTMLElement && embeddedPanPointer.hasPointerCapture(event.pointerId))
2765
+ embeddedPanPointer.releasePointerCapture(event.pointerId);
2766
+ embeddedPanPointer = null;
2767
+ document.documentElement.style.cursor = workspaceCanvasTool === "pan" ? "grab" : "";
2768
+ publishCanvasInput("pan-end");
2769
+ }
2770
+ function handleEmbeddedCanvasWheel(event) {
2771
+ if (!embeddedWorkspace || event.composedPath().includes(host)) return;
2772
+ if (event.ctrlKey || event.metaKey) {
2773
+ event.preventDefault();
2774
+ publishCanvasInput("zoom-wheel", {
2775
+ deltaY: event.deltaY,
2776
+ clientX: event.clientX,
2777
+ clientY: event.clientY
2778
+ });
2779
+ return;
2780
+ }
2781
+ if (workspaceCanvasTool === "interact") return;
2782
+ event.preventDefault();
2783
+ publishCanvasInput("pan-wheel", { deltaX: event.deltaX, deltaY: event.deltaY });
2784
+ }
2785
+ window.addEventListener("message", handleWorkspaceMessage);
2786
+ document.addEventListener("keydown", handleEmbeddedCanvasKeyDown, true);
2787
+ document.addEventListener("keyup", handleEmbeddedCanvasKeyUp, true);
2788
+ document.addEventListener("pointerdown", handleEmbeddedCanvasPointerDown, true);
2789
+ document.addEventListener("pointermove", handleEmbeddedCanvasPointerMove, true);
2790
+ document.addEventListener("pointerup", handleEmbeddedCanvasPointerUp, true);
2791
+ document.addEventListener("pointercancel", handleEmbeddedCanvasPointerUp, true);
2792
+ document.addEventListener("wheel", handleEmbeddedCanvasWheel, { capture: true, passive: false });
2186
2793
  const onboardingSteps = [
2187
2794
  {
2188
2795
  id: "setup",
@@ -2448,6 +3055,13 @@ function installFoundryInspector(options = {}) {
2448
3055
  }
2449
3056
  function populateDesignContext() {
2450
3057
  if (!designGraph) return;
3058
+ const selectedBreakpoint = breakpoint.value || "current";
3059
+ const selectedTheme = theme.value || "current";
3060
+ const selectedState = state.value || "current";
3061
+ const workbenchViewport = shadow.querySelector("[data-workbench-viewport]");
3062
+ const selectedWorkbenchViewport = workbenchViewport.value;
3063
+ const workbenchTheme = shadow.querySelector("[data-workbench-theme]");
3064
+ const selectedWorkbenchTheme = workbenchTheme.value || "current";
2451
3065
  breakpoint.innerHTML = [
2452
3066
  '<option value="current">Current</option>',
2453
3067
  ...designGraph.breakpoints.map(
@@ -2471,17 +3085,25 @@ function installFoundryInspector(options = {}) {
2471
3085
  '<option value="disabled">Disabled</option>',
2472
3086
  '<option value="reduced-motion">Reduced motion</option>'
2473
3087
  ].join("");
2474
- const workbenchViewport = shadow.querySelector("[data-workbench-viewport]");
2475
3088
  workbenchViewport.innerHTML = designGraph.breakpoints.map(
2476
3089
  (item) => `<option value="${escapeHtml(item.id)}">${escapeHtml(item.label)} \xB7 ${item.width}px</option>`
2477
3090
  ).join("");
2478
- const workbenchTheme = shadow.querySelector("[data-workbench-theme]");
2479
3091
  workbenchTheme.innerHTML = [
2480
3092
  '<option value="current">Current theme</option>',
2481
3093
  ...designGraph.themes.map(
2482
3094
  (item) => `<option value="${escapeHtml(item.id)}">${escapeHtml(item.label)}</option>`
2483
3095
  )
2484
3096
  ].join("");
3097
+ const restoreValue = (field, value, fallback) => {
3098
+ const available = [...field.options].some((option) => option.value === value);
3099
+ field.value = available ? value : fallback ?? field.options[0]?.value ?? "";
3100
+ syncFdcSelect(field);
3101
+ };
3102
+ restoreValue(breakpoint, selectedBreakpoint, "current");
3103
+ restoreValue(theme, selectedTheme, "current");
3104
+ restoreValue(state, selectedState, "current");
3105
+ restoreValue(workbenchViewport, selectedWorkbenchViewport);
3106
+ restoreValue(workbenchTheme, selectedWorkbenchTheme, "current");
2485
3107
  }
2486
3108
  async function hydrateSession() {
2487
3109
  if (!sessionId || !token) return;
@@ -2709,12 +3331,18 @@ function installFoundryInspector(options = {}) {
2709
3331
  return selector;
2710
3332
  }
2711
3333
  function resolveFoundrySelector(root, selector) {
3334
+ if (!selector.trim()) return null;
2712
3335
  const parts = selector.split(">>>").map((part) => part.trim());
2713
3336
  let currentRoot = root;
2714
3337
  for (let index = 0; index < parts.length; index += 1) {
2715
3338
  const part = parts[index];
2716
3339
  if (!part) return null;
2717
- const element = currentRoot.querySelector(part);
3340
+ let element;
3341
+ try {
3342
+ element = currentRoot.querySelector(part);
3343
+ } catch {
3344
+ return null;
3345
+ }
2718
3346
  if (!element) return null;
2719
3347
  if (index === parts.length - 1) return element;
2720
3348
  if (!element.shadowRoot) return null;
@@ -4184,6 +4812,7 @@ function installFoundryInspector(options = {}) {
4184
4812
  } catch (error) {
4185
4813
  showToast(error instanceof Error ? error.message : "Could not record change");
4186
4814
  }
4815
+ publishWorkspaceState();
4187
4816
  }
4188
4817
  function renderToolTabs() {
4189
4818
  const multi = selectedElements.length > 1;
@@ -4355,6 +4984,7 @@ function installFoundryInspector(options = {}) {
4355
4984
  const component = selectedComponent();
4356
4985
  if (!rect || !component?.variants.length) {
4357
4986
  canvasVariant.hidden = true;
4987
+ syncFdcSelect(canvasVariant);
4358
4988
  return;
4359
4989
  }
4360
4990
  const signature = component.variants.map((variant) => variant.id).join("|");
@@ -4370,6 +5000,7 @@ function installFoundryInspector(options = {}) {
4370
5000
  canvasVariant.style.left = `${Math.max(8, Math.min(window.innerWidth - 188, rect.left))}px`;
4371
5001
  canvasVariant.style.top = `${Math.max(8, rect.bottom + 8)}px`;
4372
5002
  canvasVariant.hidden = false;
5003
+ syncFdcSelect(canvasVariant);
4373
5004
  }
4374
5005
  function opaqueBackground(element) {
4375
5006
  let current = element;
@@ -4412,6 +5043,90 @@ function installFoundryInspector(options = {}) {
4412
5043
  updateOutline();
4413
5044
  await record(control, before, after, element, operationLabel);
4414
5045
  }
5046
+ function installEffectEditor() {
5047
+ const finish = async (control, value, label) => {
5048
+ await applyControlValue(control, value, label);
5049
+ if (selected) selectedControls = controlsFor(selected);
5050
+ renderControls();
5051
+ publishWorkspaceState();
5052
+ };
5053
+ controlsRoot.querySelectorAll("[data-shadow-part]").forEach((field) => {
5054
+ field.addEventListener("change", () => {
5055
+ const control = selectedControls[Number(field.dataset.shadowControl)];
5056
+ const effectIndex = Number(field.dataset.shadowIndex);
5057
+ const part = field.dataset.shadowPart;
5058
+ if (!control || !part) return;
5059
+ const effects = parseShadowEffects(String(control.read()));
5060
+ const effect = effects[effectIndex];
5061
+ if (!effect) return;
5062
+ if (part === "color") effect.color = field.value;
5063
+ else if (part === "opacity") effect.opacity = Number(field.value) / 100;
5064
+ else if (part !== "kind") effect[part] = Number(field.value);
5065
+ void finish(control, composeShadowEffects(effects), `Adjust ${effect.kind}`);
5066
+ });
5067
+ });
5068
+ controlsRoot.querySelectorAll("[data-shadow-kind]").forEach((field) => {
5069
+ field.addEventListener("change", () => {
5070
+ const control = selectedControls[Number(field.dataset.shadowControl)];
5071
+ const effectIndex = Number(field.dataset.shadowKind);
5072
+ if (!control) return;
5073
+ const effects = parseShadowEffects(String(control.read()));
5074
+ const effect = effects[effectIndex];
5075
+ if (!effect) return;
5076
+ effect.kind = field.value === "inner-shadow" ? "inner-shadow" : "drop-shadow";
5077
+ void finish(control, composeShadowEffects(effects), `Change to ${field.value}`);
5078
+ });
5079
+ });
5080
+ controlsRoot.querySelectorAll("[data-remove-shadow]").forEach((button) => {
5081
+ button.addEventListener("click", () => {
5082
+ const control = selectedControls[Number(button.dataset.shadowControl)];
5083
+ if (!control) return;
5084
+ const effects = parseShadowEffects(String(control.read()));
5085
+ effects.splice(Number(button.dataset.removeShadow), 1);
5086
+ void finish(control, composeShadowEffects(effects), "Remove shadow");
5087
+ });
5088
+ });
5089
+ controlsRoot.querySelectorAll("[data-blur-control]").forEach((field) => {
5090
+ field.addEventListener("change", () => {
5091
+ const control = selectedControls[Number(field.dataset.blurControl)];
5092
+ if (!control) return;
5093
+ void finish(
5094
+ control,
5095
+ replaceBlur(String(control.read()), Number(field.value)),
5096
+ `Adjust ${control.label}`
5097
+ );
5098
+ });
5099
+ });
5100
+ controlsRoot.querySelectorAll("[data-remove-blur]").forEach((button) => {
5101
+ button.addEventListener("click", () => {
5102
+ const control = selectedControls[Number(button.dataset.blurControl)];
5103
+ if (!control) return;
5104
+ void finish(control, replaceBlur(String(control.read()), null), `Remove ${control.label}`);
5105
+ });
5106
+ });
5107
+ controlsRoot.querySelectorAll("[data-add-effect]").forEach((button) => {
5108
+ button.addEventListener("click", () => {
5109
+ const control = selectedControls[Number(button.dataset.effectControl)];
5110
+ const type = button.dataset.addEffect;
5111
+ if (!control || !type) return;
5112
+ if (type === "drop-shadow" || type === "inner-shadow") {
5113
+ const effects = parseShadowEffects(String(control.read()));
5114
+ effects.push({
5115
+ kind: type,
5116
+ x: 0,
5117
+ y: 4,
5118
+ blur: 8,
5119
+ spread: 0,
5120
+ color: "#000000",
5121
+ opacity: 0.12
5122
+ });
5123
+ void finish(control, composeShadowEffects(effects), `Add ${type}`);
5124
+ return;
5125
+ }
5126
+ void finish(control, replaceBlur(String(control.read()), 4), `Add ${type}`);
5127
+ });
5128
+ });
5129
+ }
4415
5130
  function installContextActions(controls) {
4416
5131
  controlsRoot.querySelectorAll(".native-search").forEach(
4417
5132
  (search) => search.addEventListener("input", (event) => {
@@ -5332,6 +6047,9 @@ function installFoundryInspector(options = {}) {
5332
6047
  entries.forEach(({ control }) => renderedProperties.add(control.property));
5333
6048
  if (!entries.length) return "";
5334
6049
  const sectionKey = `${group.key}:${section.label}`;
6050
+ if (section.label === "Effects") {
6051
+ 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>Effects</strong></button></div><div class="section-grid effect-section">${renderEffectsEditor(entries)}</div></section>`;
6052
+ }
5335
6053
  const sectionActions = section.label === "Position and size" ? '<span class="section-actions"><button class="section-action" data-layout-action="lock" aria-label="Lock aspect ratio" title="Lock aspect ratio"><i data-foundry-icon="lock"></i></button></span>' : section.label === "Padding" ? `<span class="section-actions"><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></span>` : section.label === "Typeface" ? '<span class="section-actions type-presets"><button data-type-preset="compact">S</button><button data-type-preset="body">M</button><button data-type-preset="display">L</button></span>' : section.label === "Fill" ? '<span class="section-actions"><button class="section-action" data-color-action="gradient" aria-label="Add linear gradient" title="Add gradient"><i data-foundry-icon="sparkles"></i></button><button class="section-action" data-color-action="clear" aria-label="Clear fill" title="Clear fill"><i data-foundry-icon="x"></i></button></span>' : section.label === "Corners" ? `<span class="section-actions"><button class="section-action ${radiusLinked ? "active" : ""}" data-radius-link aria-label="${radiusLinked ? "Edit corner radii independently" : "Link corner radii"}"><i data-foundry-icon="${radiusLinked ? "link-2" : "unlink-2"}"></i></button></span>` : "";
5336
6054
  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>${sectionActions}</div><div class="section-grid ${section.columns === 2 ? "two" : ""} ${section.stacked ? "stacked" : ""}">${entries.map(
5337
6055
  ({ control, index }) => renderPropertyControl(control, index, section.prefixes?.[control.property])
@@ -5591,6 +6309,7 @@ function installFoundryInspector(options = {}) {
5591
6309
  field.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
5592
6310
  });
5593
6311
  });
6312
+ installEffectEditor();
5594
6313
  installContextActions(selectedControls);
5595
6314
  installNumberScrubbing();
5596
6315
  installMotionControls(animations);
@@ -5673,6 +6392,7 @@ function installFoundryInspector(options = {}) {
5673
6392
  if (!workbench.hidden) applyWorkbenchState();
5674
6393
  if (!libraryPanel.hidden) renderDesignMemory();
5675
6394
  if (matrixMode) renderWorkbenchMatrix();
6395
+ publishWorkspaceState();
5676
6396
  }
5677
6397
  function renderSelectionEmptyState() {
5678
6398
  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>';
@@ -5709,6 +6429,7 @@ function installFoundryInspector(options = {}) {
5709
6429
  renderLayers();
5710
6430
  if (!libraryPanel.hidden) renderDesignMemory();
5711
6431
  if (matrixMode) renderWorkbenchMatrix();
6432
+ publishWorkspaceState();
5712
6433
  }
5713
6434
  function simpleStyleControl(element, property, label, category = "layout", unit) {
5714
6435
  return {
@@ -6514,13 +7235,31 @@ function installFoundryInspector(options = {}) {
6514
7235
  sessionStorage.removeItem("__foundry_selected_selector");
6515
7236
  }
6516
7237
  }
7238
+ if (embeddedWorkspace) {
7239
+ discoverLayers();
7240
+ publishWorkspaceState();
7241
+ }
6517
7242
  function destroyInspector() {
6518
7243
  resizeObserver?.disconnect();
7244
+ fdcSelectObserver.disconnect();
7245
+ closeFdcSelect(false);
6519
7246
  cancelAnimationFrame(layerScrollFrame);
6520
7247
  cancelAnimationFrame(mutationFrame);
6521
7248
  layerMutationObserver.disconnect();
6522
7249
  systemDarkTheme.removeEventListener("change", handleSystemThemeChange);
7250
+ window.removeEventListener("message", handleWorkspaceMessage);
7251
+ document.removeEventListener("keydown", handleEmbeddedCanvasKeyDown, true);
7252
+ document.removeEventListener("keyup", handleEmbeddedCanvasKeyUp, true);
7253
+ document.removeEventListener("pointerdown", handleEmbeddedCanvasPointerDown, true);
7254
+ document.removeEventListener("pointermove", handleEmbeddedCanvasPointerMove, true);
7255
+ document.removeEventListener("pointerup", handleEmbeddedCanvasPointerUp, true);
7256
+ document.removeEventListener("pointercancel", handleEmbeddedCanvasPointerUp, true);
7257
+ document.removeEventListener("wheel", handleEmbeddedCanvasWheel, true);
6523
7258
  document.removeEventListener("pointerdown", handleInterfaceThemeDismiss, true);
7259
+ document.removeEventListener("pointerdown", handleFdcSelectDismiss, true);
7260
+ shadow.removeEventListener("keydown", handleFdcSelectKeydown);
7261
+ window.removeEventListener("resize", closeFdcSelectForViewportChange);
7262
+ window.removeEventListener("scroll", closeFdcSelectForViewportChange, true);
6524
7263
  clearInterval(reviewPoll);
6525
7264
  clearInterval(sessionPoll);
6526
7265
  document.removeEventListener("click", handlePointer, true);
@@ -6532,6 +7271,7 @@ function installFoundryInspector(options = {}) {
6532
7271
  window.removeEventListener("scroll", updateOutline, true);
6533
7272
  window.removeEventListener("resize", handleWorkspaceResize);
6534
7273
  cancelAnimationFrame(selectionHoverFrame);
7274
+ cancelAnimationFrame(workspacePublishFrame);
6535
7275
  host.remove();
6536
7276
  }
6537
7277
  return {