@sequent-org/moodboard 1.4.56 → 1.4.58

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.
Files changed (30) hide show
  1. package/package.json +1 -1
  2. package/src/core/commands/PasteObjectCommand.js +7 -1
  3. package/src/core/commands/UpdateContentCommand.js +95 -0
  4. package/src/core/flows/ObjectLifecycleFlow.js +10 -1
  5. package/src/initNoBundler.js +28 -4
  6. package/src/services/text/TextBoxMetrics.js +133 -0
  7. package/src/tools/object-tools/selection/MindmapInlineEditorController.js +98 -7
  8. package/src/tools/object-tools/selection/SelectInputRouter.js +56 -3
  9. package/src/tools/object-tools/selection/TextEditorCaretService.js +113 -0
  10. package/src/tools/object-tools/selection/TextEditorDomFactory.js +37 -21
  11. package/src/tools/object-tools/selection/TextEditorInteractionController.js +111 -12
  12. package/src/tools/object-tools/selection/TextEditorPositioningService.js +19 -1
  13. package/src/tools/object-tools/selection/TextEditorSyncService.js +2 -1
  14. package/src/tools/object-tools/selection/TextInlineEditorController.js +70 -45
  15. package/src/tools/object-tools/selection/TransformInteractionController.js +7 -1
  16. package/src/ui/FramePropertiesPanel.js +7 -0
  17. package/src/ui/HtmlTextLayer.js +174 -64
  18. package/src/ui/ImagePropertiesPanel.js +7 -0
  19. package/src/ui/TextPropertiesPanel.js +305 -2
  20. package/src/ui/handles/HandlesDomRenderer.js +2 -0
  21. package/src/ui/handles/HandlesInteractionController.js +40 -0
  22. package/src/ui/styles/panels.css +240 -19
  23. package/src/ui/styles/workspace.css +94 -7
  24. package/src/ui/text-properties/TextFormatControls.js +132 -21
  25. package/src/ui/text-properties/TextLinkControl.js +255 -0
  26. package/src/ui/text-properties/TextLockMoreControls.js +173 -0
  27. package/src/ui/text-properties/TextPropertiesPanelBindings.js +45 -0
  28. package/src/ui/text-properties/TextPropertiesPanelMapper.js +52 -0
  29. package/src/ui/text-properties/TextPropertiesPanelRenderer.js +263 -26
  30. package/src/ui/text-properties/TextPropertiesPanelState.js +6 -0
@@ -206,10 +206,27 @@
206
206
  height: 36px;
207
207
  }
208
208
 
209
+ .text-properties-panel.is-locked {
210
+ min-width: 0;
211
+ padding: 0 6px;
212
+ gap: 4px;
213
+ }
214
+
209
215
  .text-properties-panel * {
210
216
  max-height: 36px;
211
217
  }
212
218
 
219
+ .text-properties-panel [id^="tpp-color-dropdown"],
220
+ .text-properties-panel [id^="tpp-color-dropdown"] *,
221
+ .text-properties-panel [id^="tpp-bgcolor-dropdown"],
222
+ .text-properties-panel [id^="tpp-bgcolor-dropdown"] *,
223
+ .text-properties-panel [id^="tpp-highlight-dropdown"],
224
+ .text-properties-panel [id^="tpp-highlight-dropdown"] *,
225
+ .text-properties-panel .tpp-more-dropdown,
226
+ .text-properties-panel .tpp-more-dropdown * {
227
+ max-height: none;
228
+ }
229
+
213
230
  /* Frame properties toolbar — mirror image toolbar look */
214
231
  .frame-properties-panel {
215
232
  position: absolute;
@@ -615,10 +632,10 @@
615
632
 
616
633
  .text-properties-panel .font-select {
617
634
  box-sizing: border-box;
618
- min-width: 90px;
619
- width: 90px;
635
+ min-width: 70px;
636
+ width: 70px;
620
637
  height: 38px;
621
- padding: 4px 8px;
638
+ padding: 4px 0px;
622
639
  font-size: 13px;
623
640
  background-color: #fff;
624
641
  border: none;
@@ -741,12 +758,12 @@
741
758
  border: none;
742
759
  padding: 0;
743
760
  cursor: pointer;
744
- color: #666;
761
+ color: #6B7280;
745
762
  }
746
763
 
747
764
  .text-properties-panel .font-size-stepper:hover {
748
765
  background: #f5f5f5;
749
- color: #333;
766
+ color: #111827;
750
767
  }
751
768
 
752
769
  .text-properties-panel .font-size-stepper--down {
@@ -754,11 +771,10 @@
754
771
  margin-top: -2px;
755
772
  }
756
773
 
757
- .text-properties-panel .current-color-button,
758
774
  .text-properties-panel .current-bgcolor-button {
759
- width: 28px;
760
- height: 28px;
761
- border: 1px solid #ddd;
775
+ width: 20px;
776
+ height: 20px;
777
+ border: none;
762
778
  border-radius: 50%;
763
779
  background-color: #000;
764
780
  cursor: pointer;
@@ -769,6 +785,54 @@
769
785
  position: relative;
770
786
  }
771
787
 
788
+ .text-properties-panel .current-color-button {
789
+ width: 28px;
790
+ height: 28px;
791
+ border: 1px solid transparent;
792
+ border-radius: 4px;
793
+ background-color: transparent;
794
+ cursor: pointer;
795
+ margin: 0;
796
+ padding: 0;
797
+ display: flex;
798
+ flex-direction: column;
799
+ align-items: center;
800
+ justify-content: center;
801
+ box-sizing: border-box;
802
+ position: relative;
803
+ transition: background 0.15s;
804
+ color: #6B7280;
805
+ }
806
+
807
+ .text-properties-panel .current-color-button:hover {
808
+ background: #f0f0f0;
809
+ color: #111827;
810
+ }
811
+
812
+ .text-properties-panel .current-highlight-button {
813
+ width: 28px;
814
+ height: 28px;
815
+ border: 1px solid transparent;
816
+ border-radius: 4px;
817
+ background-color: transparent;
818
+ cursor: pointer;
819
+ margin: 0;
820
+ padding: 0;
821
+ display: flex;
822
+ flex-direction: column;
823
+ align-items: center;
824
+ justify-content: center;
825
+ box-sizing: border-box;
826
+ position: relative;
827
+ transition: background 0.15s;
828
+ color: #6B7280;
829
+ }
830
+
831
+ .text-properties-panel .current-highlight-button:hover {
832
+ background: #f0f0f0;
833
+ color: #111827;
834
+ }
835
+
772
836
  .text-properties-panel .tpp-format-btn {
773
837
  height: 28px;
774
838
  min-width: 28px;
@@ -780,17 +844,29 @@
780
844
  display: inline-flex;
781
845
  align-items: center;
782
846
  justify-content: center;
783
- color: #444;
847
+ color: #6B7280;
784
848
  flex-shrink: 0;
785
- transition: background 0.15s;
849
+ transition: background 0.15s, color 0.15s;
786
850
  }
787
- .text-properties-panel .tpp-format-btn:hover { background: #f0f0f0; }
851
+ .text-properties-panel .tpp-format-btn:hover { background: #f0f0f0; color: #111827; }
788
852
  .text-properties-panel .tpp-format-btn.is-active {
789
853
  background: #e8eaff;
790
854
  border-color: #6155F5;
791
855
  color: #6155F5;
792
856
  }
793
857
 
858
+ .text-properties-panel .tpp-format-btns-wrapper {
859
+ width: 24px;
860
+ height: 24px;
861
+ }
862
+
863
+ .text-properties-panel .tpp-format-btn.tpp-format-trigger {
864
+ width: 24px;
865
+ min-width: 24px;
866
+ height: 24px;
867
+ padding: 0;
868
+ }
869
+
794
870
  .text-properties-panel .tpp-list-btns {
795
871
  display: flex;
796
872
  gap: 2px;
@@ -817,6 +893,21 @@
817
893
  z-index: 4000;
818
894
  }
819
895
 
896
+ .text-properties-panel .tpp-format-modal {
897
+ max-height: none;
898
+ position: absolute;
899
+ top: calc(100% + 4px);
900
+ left: 0;
901
+ flex-direction: row;
902
+ gap: 2px;
903
+ background: #ffffff;
904
+ border: 1px solid #E5E7EB;
905
+ border-radius: 6px;
906
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12), 0 1px 3px rgba(0, 0, 0, 0.06);
907
+ padding: 4px;
908
+ z-index: 4000;
909
+ }
910
+
820
911
  .text-properties-panel .tpp-list-modal-option {
821
912
  display: flex;
822
913
  align-items: center;
@@ -833,6 +924,26 @@
833
924
  flex-shrink: 0;
834
925
  }
835
926
 
927
+ .text-properties-panel .tpp-format-modal-option {
928
+ display: flex;
929
+ align-items: center;
930
+ justify-content: center;
931
+ width: 28px;
932
+ height: 28px;
933
+ padding: 0;
934
+ border: none;
935
+ background: transparent;
936
+ border-radius: 4px;
937
+ cursor: pointer;
938
+ color: #374151;
939
+ transition: background 0.1s;
940
+ flex-shrink: 0;
941
+ }
942
+
943
+ .text-properties-panel .tpp-format-modal-option:hover {
944
+ background: #f3f4f6;
945
+ }
946
+
836
947
  .text-properties-panel .tpp-list-modal-option:hover {
837
948
  background: #f3f4f6;
838
949
  }
@@ -887,6 +998,34 @@
887
998
  background: #f3f4f6;
888
999
  }
889
1000
 
1001
+ .text-properties-panel .tpp-lh-control {
1002
+ display: flex;
1003
+ align-items: center;
1004
+ position: relative;
1005
+ }
1006
+
1007
+ .text-properties-panel .tpp-lh-control svg {
1008
+ width: 22px;
1009
+ height: 22px;
1010
+ }
1011
+
1012
+ .text-properties-panel .tpp-lh-modal {
1013
+ max-height: none;
1014
+ position: absolute;
1015
+ top: calc(100% + 4px);
1016
+ left: 50%;
1017
+ transform: translateX(-50%);
1018
+ flex-direction: row;
1019
+ align-items: center;
1020
+ justify-content: center;
1021
+ background: #ffffff;
1022
+ border: 1px solid #E5E7EB;
1023
+ border-radius: 6px;
1024
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12), 0 1px 3px rgba(0, 0, 0, 0.06);
1025
+ padding: 8px 12px;
1026
+ z-index: 4000;
1027
+ }
1028
+
890
1029
  .text-properties-panel .tpp-lh-slider {
891
1030
  width: 68px;
892
1031
  accent-color: #6155F5;
@@ -1091,7 +1230,7 @@
1091
1230
  }
1092
1231
 
1093
1232
  /* More Dropdown */
1094
- .ipp-more-dropdown {
1233
+ .ipp-more-dropdown, .tpp-more-dropdown {
1095
1234
  position: absolute;
1096
1235
  top: calc(100% + 6px);
1097
1236
  right: 0;
@@ -1106,11 +1245,15 @@
1106
1245
  z-index: 1001;
1107
1246
  }
1108
1247
 
1109
- .ipp-more-dropdown.is-open {
1248
+ .ipp-more-dropdown.is-open, .tpp-more-dropdown.is-open {
1110
1249
  display: flex;
1250
+ position: fixed;
1251
+ min-width: 0;
1252
+ max-width: 214px;
1253
+ width: 214px;
1111
1254
  }
1112
1255
 
1113
- .ipp-dropdown-item {
1256
+ .ipp-dropdown-item, .tpp-dropdown-item {
1114
1257
  display: flex;
1115
1258
  align-items: center;
1116
1259
  padding: 6px 8px;
@@ -1127,7 +1270,7 @@
1127
1270
  width: 100%;
1128
1271
  }
1129
1272
 
1130
- .ipp-dropdown-item:hover {
1273
+ .ipp-dropdown-item:hover, .tpp-dropdown-item:hover {
1131
1274
  background: #F3F4F6;
1132
1275
  }
1133
1276
 
@@ -1137,19 +1280,19 @@
1137
1280
  font-size: 12px;
1138
1281
  }
1139
1282
 
1140
- .ipp-dropdown-item-shortcut {
1283
+ .ipp-dropdown-item-shortcut, .tpp-dropdown-item-shortcut {
1141
1284
  margin-left: auto;
1142
1285
  color: #9CA3AF;
1143
1286
  font-size: 12px;
1144
1287
  }
1145
1288
 
1146
- .ipp-dropdown-divider {
1289
+ .ipp-dropdown-divider, .tpp-dropdown-divider {
1147
1290
  height: 1px;
1148
1291
  background: #E5E7EB;
1149
1292
  margin: 4px 2px;
1150
1293
  }
1151
1294
 
1152
- .ipp-dropdown-icon {
1295
+ .ipp-dropdown-icon, .tpp-dropdown-icon {
1153
1296
  width: 16px;
1154
1297
  height: 16px;
1155
1298
  display: inline-flex;
@@ -1585,3 +1728,81 @@
1585
1728
  opacity: 1;
1586
1729
  }
1587
1730
 
1731
+ /* ── Кнопка «Ссылка» в панели свойств текста ────────────────── */
1732
+ .tpp-link-btn:disabled,
1733
+ .tpp-link-btn--disabled {
1734
+ opacity: 0.35;
1735
+ cursor: not-allowed;
1736
+ pointer-events: none;
1737
+ }
1738
+
1739
+ /* ── Форма ввода URL ─────────────────────────────────────────── */
1740
+ .tpp-link-form {
1741
+ position: fixed;
1742
+ z-index: 10010;
1743
+ display: flex;
1744
+ flex-direction: column;
1745
+ gap: 6px;
1746
+ background: #ffffff;
1747
+ border: 1px solid #E5E7EB;
1748
+ border-radius: 10px;
1749
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.07);
1750
+ padding: 10px 12px;
1751
+ min-width: 260px;
1752
+ max-width: 340px;
1753
+ }
1754
+
1755
+ .tpp-link-form-label {
1756
+ font-size: 11px;
1757
+ color: #6B7280;
1758
+ white-space: nowrap;
1759
+ overflow: hidden;
1760
+ text-overflow: ellipsis;
1761
+ max-width: 100%;
1762
+ }
1763
+
1764
+ .tpp-link-form-row {
1765
+ display: flex;
1766
+ gap: 6px;
1767
+ align-items: center;
1768
+ }
1769
+
1770
+ .tpp-link-input {
1771
+ flex: 1;
1772
+ height: 30px;
1773
+ padding: 0 8px;
1774
+ border: 1px solid #D1D5DB;
1775
+ border-radius: 6px;
1776
+ font-size: 13px;
1777
+ font-family: inherit;
1778
+ outline: none;
1779
+ color: #111827;
1780
+ transition: border-color 0.15s;
1781
+ }
1782
+
1783
+ .tpp-link-input:focus {
1784
+ border-color: #6366F1;
1785
+ }
1786
+
1787
+ .tpp-link-input--error {
1788
+ border-color: #EF4444;
1789
+ }
1790
+
1791
+ .tpp-link-form-ok {
1792
+ height: 30px;
1793
+ padding: 0 12px;
1794
+ background: #6366F1;
1795
+ color: #ffffff;
1796
+ border: none;
1797
+ border-radius: 6px;
1798
+ font-size: 13px;
1799
+ font-family: inherit;
1800
+ cursor: pointer;
1801
+ flex-shrink: 0;
1802
+ transition: background 0.15s;
1803
+ }
1804
+
1805
+ .tpp-link-form-ok:hover {
1806
+ background: #4F46E5;
1807
+ }
1808
+
@@ -288,7 +288,7 @@
288
288
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
289
289
  font-size: 13px;
290
290
  font-family: 'Roboto', Arial, sans-serif;
291
- min-width: 320px;
291
+ min-width: auto;
292
292
  height: 36px;
293
293
  }
294
294
 
@@ -321,6 +321,21 @@
321
321
  letter-spacing: normal;
322
322
  }
323
323
 
324
+ /* Веб-ссылка внутри текстового объекта. pointer-events: auto переопределяет
325
+ pointer-events: none у родительского .mb-text и .moodboard-html-layer,
326
+ чтобы по ссылке можно было реально перейти. */
327
+ .mb-text-link {
328
+ color: #2563EB;
329
+ text-decoration: underline;
330
+ text-underline-offset: 2px;
331
+ pointer-events: auto;
332
+ cursor: pointer;
333
+ }
334
+
335
+ .mb-text-link:hover {
336
+ color: #1D4ED8;
337
+ }
338
+
324
339
  /* Markdown-режим текстового объекта: блочный рендер, перенос по словам */
325
340
  .mb-text--md {
326
341
  white-space: normal;
@@ -650,14 +665,45 @@
650
665
  z-index: 10000;
651
666
  }
652
667
 
668
+ .mb-custom-caret {
669
+ position: absolute;
670
+ background-color: #111;
671
+ width: 2px;
672
+ pointer-events: none;
673
+ z-index: 10001;
674
+ animation: mb-caret-blink 1s step-end infinite;
675
+ display: none;
676
+ border-radius: 1px;
677
+ }
678
+
679
+ @keyframes mb-caret-blink {
680
+ 0%, 100% { opacity: 1; }
681
+ 50% { opacity: 0; }
682
+ }
683
+
684
+ /* Панель свойств текста и её дропдауны — выше inline-редактора */
685
+ .text-properties-layer {
686
+ z-index: 10050;
687
+ }
688
+
689
+ .moodboard-text-input::selection {
690
+ background: rgba(33, 150, 243, 0.28);
691
+ }
692
+
693
+ .moodboard-text-input::-moz-selection {
694
+ background: rgba(33, 150, 243, 0.28);
695
+ }
696
+
653
697
  .moodboard-text-input {
698
+ caret-color: transparent;
654
699
  position: relative;
700
+ z-index: 2;
655
701
  left: 0;
656
702
  top: 0;
657
703
  border: none;
658
704
  padding: 0;
659
705
  font-family: Caveat, Arial, cursive;
660
- color: #111;
706
+ color: transparent;
661
707
  background: transparent;
662
708
  outline: none;
663
709
  resize: none;
@@ -670,7 +716,34 @@
670
716
  padding-bottom: 0; /* без нижнего отступа */
671
717
  letter-spacing: 0px;
672
718
  font-kerning: normal;
719
+ text-rendering: optimizeLegibility;
720
+ margin: 0;
721
+ }
722
+
723
+ .moodboard-text-backdrop {
724
+ position: absolute;
725
+ z-index: 1;
726
+ left: 0;
727
+ top: 0;
728
+ width: 100%;
729
+ height: 100%;
730
+ border: none;
731
+ padding: 0;
732
+ font-family: Caveat, Arial, cursive;
733
+ color: #111;
734
+ background: transparent;
735
+ box-sizing: content-box;
736
+ overflow: hidden;
737
+ -webkit-font-smoothing: antialiased;
738
+ -moz-osx-font-smoothing: grayscale;
739
+ white-space: pre-wrap;
740
+ word-break: break-word;
741
+ padding-bottom: 0;
742
+ letter-spacing: 0px;
743
+ font-kerning: normal;
744
+ text-rendering: optimizeLegibility;
673
745
  margin: 0;
746
+ pointer-events: none;
674
747
  }
675
748
 
676
749
  .text-properties-panel .font-select,
@@ -688,9 +761,6 @@
688
761
 
689
762
  .text-properties-panel .current-color-button,
690
763
  .text-properties-panel .current-bgcolor-button {
691
- width: 28px;
692
- height: 20px;
693
- border: 1px solid #ddd;
694
764
  border-radius: 4px;
695
765
  background-color: #000;
696
766
  cursor: pointer;
@@ -700,6 +770,18 @@
700
770
  box-sizing: border-box;
701
771
  position: relative;
702
772
  }
773
+
774
+ .text-properties-panel .current-color-button {
775
+ width: 20px;
776
+ height: 20px;
777
+ border: 1px solid #ddd;
778
+ }
779
+
780
+ .text-properties-panel .current-bgcolor-button {
781
+ width: 20px;
782
+ height: 20px;
783
+ border: none;
784
+ }
703
785
  /* MoodBoard Workspace Styles */
704
786
 
705
787
  /* Основные контейнеры */
@@ -1548,8 +1630,13 @@
1548
1630
  transition: all 0.2s ease;
1549
1631
  outline: none;
1550
1632
  outline-offset: 0;
1551
- padding-top: 5px;
1552
- padding-bottom: 5px;
1633
+ padding-top: 1px;
1634
+ padding-bottom: 1px;
1635
+ }
1636
+
1637
+ .moodboard-text-backdrop {
1638
+ padding-top: 1px;
1639
+ padding-bottom: 1px;
1553
1640
  }
1554
1641
 
1555
1642
  .moodboard-text-input:focus {