@sequent-org/moodboard 1.0.24 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (346) hide show
  1. package/package.json +2 -2
  2. package/src/assets/emodji//320/226/320/265/320/275/321/201/320/272/320/270/320/265 /321/215/320/274/320/276/321/206/320/270/320/270/1f645.png +0 -0
  3. package/src/assets/emodji//320/226/320/265/320/275/321/201/320/272/320/270/320/265 /321/215/320/274/320/276/321/206/320/270/320/270/1f646.png +0 -0
  4. package/src/assets/emodji//320/226/320/265/320/275/321/201/320/272/320/270/320/265 /321/215/320/274/320/276/321/206/320/270/320/270/1f64b.png +0 -0
  5. package/src/assets/emodji//320/226/320/265/320/275/321/201/320/272/320/270/320/265 /321/215/320/274/320/276/321/206/320/270/320/270/1f64d.png +0 -0
  6. package/src/assets/emodji//320/226/320/265/320/275/321/201/320/272/320/270/320/265 /321/215/320/274/320/276/321/206/320/270/320/270/1f64e.png +0 -0
  7. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/1f446.png +0 -0
  8. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/1f447.png +0 -0
  9. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/1f448.png +0 -0
  10. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/1f449.png +0 -0
  11. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/1f44a.png +0 -0
  12. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/1f44b.png +0 -0
  13. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/1f44c.png +0 -0
  14. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/1f450.png +0 -0
  15. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/1f4aa.png +0 -0
  16. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/1f590.png +0 -0
  17. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/1f596.png +0 -0
  18. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/1f64c.png +0 -0
  19. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/1f64f.png +0 -0
  20. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/261d.png +0 -0
  21. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/270a.png +0 -0
  22. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/270b.png +0 -0
  23. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/270c.png +0 -0
  24. package/src/assets/emodji//320/226/320/265/321/201/321/202/321/213/270d.png +0 -0
  25. package/src/assets/emodji//320/232/320/276/321/202/320/270/320/272/320/270/1f638.png +0 -0
  26. package/src/assets/emodji//320/232/320/276/321/202/320/270/320/272/320/270/1f639.png +0 -0
  27. package/src/assets/emodji//320/232/320/276/321/202/320/270/320/272/320/270/1f63a.png +0 -0
  28. package/src/assets/emodji//320/232/320/276/321/202/320/270/320/272/320/270/1f63b.png +0 -0
  29. package/src/assets/emodji//320/232/320/276/321/202/320/270/320/272/320/270/1f63c.png +0 -0
  30. package/src/assets/emodji//320/232/320/276/321/202/320/270/320/272/320/270/1f63d.png +0 -0
  31. package/src/assets/emodji//320/232/320/276/321/202/320/270/320/272/320/270/1f63e.png +0 -0
  32. package/src/assets/emodji//320/232/320/276/321/202/320/270/320/272/320/270/1f63f.png +0 -0
  33. package/src/assets/emodji//320/232/320/276/321/202/320/270/320/272/320/270/1f640.png +0 -0
  34. package/src/assets/emodji//320/236/320/261/320/265/320/267/321/214/321/217/320/275/320/272/320/260/1f435.png +0 -0
  35. package/src/assets/emodji//320/236/320/261/320/265/320/267/321/214/321/217/320/275/320/272/320/260/1f648.png +0 -0
  36. package/src/assets/emodji//320/236/320/261/320/265/320/267/321/214/321/217/320/275/320/272/320/260/1f649.png +0 -0
  37. package/src/assets/emodji//320/236/320/261/320/265/320/267/321/214/321/217/320/275/320/272/320/260/1f64a.png +0 -0
  38. package/src/assets/emodji//320/240/320/260/320/267/320/275/320/276/320/265/1f440.png +0 -0
  39. package/src/assets/emodji//320/240/320/260/320/267/320/275/320/276/320/265/1f441.png +0 -0
  40. package/src/assets/emodji//320/240/320/260/320/267/320/275/320/276/320/265/1f499.png +0 -0
  41. package/src/assets/emodji//320/240/320/260/320/267/320/275/320/276/320/265/1f4a1.png +0 -0
  42. package/src/assets/emodji//320/240/320/260/320/267/320/275/320/276/320/265/1f4a3.png +0 -0
  43. package/src/assets/emodji//320/240/320/260/320/267/320/275/320/276/320/265/1f4a9.png +0 -0
  44. package/src/assets/emodji//320/240/320/260/320/267/320/275/320/276/320/265/1f4ac.png +0 -0
  45. package/src/assets/emodji//320/240/320/260/320/267/320/275/320/276/320/265/1f4af.png +0 -0
  46. package/src/assets/emodji//320/240/320/260/320/267/320/275/320/276/320/265/203c.png +0 -0
  47. package/src/assets/emodji//320/240/320/260/320/267/320/275/320/276/320/265/26d4.png +0 -0
  48. package/src/assets/emodji//320/240/320/260/320/267/320/275/320/276/320/265/2764.png +0 -0
  49. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f600.png +0 -0
  50. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f601.png +0 -0
  51. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f602.png +0 -0
  52. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f603.png +0 -0
  53. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f604.png +0 -0
  54. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f605.png +0 -0
  55. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f606.png +0 -0
  56. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f607.png +0 -0
  57. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f609.png +0 -0
  58. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f60a.png +0 -0
  59. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f60b.png +0 -0
  60. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f60c.png +0 -0
  61. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f60d.png +0 -0
  62. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f60e.png +0 -0
  63. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f60f.png +0 -0
  64. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f610.png +0 -0
  65. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f611.png +0 -0
  66. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f612.png +0 -0
  67. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f613.png +0 -0
  68. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f614.png +0 -0
  69. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f615.png +0 -0
  70. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f616.png +0 -0
  71. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f617.png +0 -0
  72. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f618.png +0 -0
  73. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f619.png +0 -0
  74. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f61a.png +0 -0
  75. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f61b.png +0 -0
  76. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f61c.png +0 -0
  77. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f61d.png +0 -0
  78. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f61e.png +0 -0
  79. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f61f.png +0 -0
  80. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f620.png +0 -0
  81. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f621.png +0 -0
  82. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f622.png +0 -0
  83. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f623.png +0 -0
  84. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f624.png +0 -0
  85. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f625.png +0 -0
  86. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f626.png +0 -0
  87. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f627.png +0 -0
  88. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f628.png +0 -0
  89. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f629.png +0 -0
  90. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f62a.png +0 -0
  91. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f62b.png +0 -0
  92. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f62c.png +0 -0
  93. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f62d.png +0 -0
  94. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f62e.png +0 -0
  95. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f62f.png +0 -0
  96. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f630.png +0 -0
  97. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f631.png +0 -0
  98. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f632.png +0 -0
  99. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f633.png +0 -0
  100. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f635.png +0 -0
  101. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f636.png +0 -0
  102. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f641.png +0 -0
  103. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/1f642.png +0 -0
  104. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/2639.png +0 -0
  105. package/src/assets/emodji//320/241/320/274/320/260/320/271/320/273/320/270/320/272/320/270/263a.png +0 -0
  106. package/src/assets/fonts/amatic-sc/AmaticSC-Bold.ttf +0 -0
  107. package/src/assets/fonts/amatic-sc/AmaticSC-Regular.ttf +0 -0
  108. package/src/assets/fonts/caveat/Caveat-Bold.ttf +0 -0
  109. package/src/assets/fonts/caveat/Caveat-Medium.ttf +0 -0
  110. package/src/assets/fonts/caveat/Caveat-Regular.ttf +0 -0
  111. package/src/assets/fonts/caveat/Caveat-SemiBold.ttf +0 -0
  112. package/src/assets/fonts/caveat/Caveat-VariableFont_wght.ttf +0 -0
  113. package/src/assets/fonts/great-vibes/GreatVibes-Regular.ttf +0 -0
  114. package/src/assets/fonts/lobster/Lobster-Regular.ttf +0 -0
  115. package/src/assets/fonts/noto-serif/NotoSerif-Black.ttf +0 -0
  116. package/src/assets/fonts/noto-serif/NotoSerif-BlackItalic.ttf +0 -0
  117. package/src/assets/fonts/noto-serif/NotoSerif-Bold.ttf +0 -0
  118. package/src/assets/fonts/noto-serif/NotoSerif-BoldItalic.ttf +0 -0
  119. package/src/assets/fonts/noto-serif/NotoSerif-ExtraBold.ttf +0 -0
  120. package/src/assets/fonts/noto-serif/NotoSerif-ExtraBoldItalic.ttf +0 -0
  121. package/src/assets/fonts/noto-serif/NotoSerif-ExtraLight.ttf +0 -0
  122. package/src/assets/fonts/noto-serif/NotoSerif-ExtraLightItalic.ttf +0 -0
  123. package/src/assets/fonts/noto-serif/NotoSerif-Italic-VariableFont_wdth,wght.ttf +0 -0
  124. package/src/assets/fonts/noto-serif/NotoSerif-Italic.ttf +0 -0
  125. package/src/assets/fonts/noto-serif/NotoSerif-Light.ttf +0 -0
  126. package/src/assets/fonts/noto-serif/NotoSerif-LightItalic.ttf +0 -0
  127. package/src/assets/fonts/noto-serif/NotoSerif-Medium.ttf +0 -0
  128. package/src/assets/fonts/noto-serif/NotoSerif-MediumItalic.ttf +0 -0
  129. package/src/assets/fonts/noto-serif/NotoSerif-Regular.ttf +0 -0
  130. package/src/assets/fonts/noto-serif/NotoSerif-SemiBold.ttf +0 -0
  131. package/src/assets/fonts/noto-serif/NotoSerif-SemiBoldItalic.ttf +0 -0
  132. package/src/assets/fonts/noto-serif/NotoSerif-Thin.ttf +0 -0
  133. package/src/assets/fonts/noto-serif/NotoSerif-ThinItalic.ttf +0 -0
  134. package/src/assets/fonts/noto-serif/NotoSerif-VariableFont_wdth,wght.ttf +0 -0
  135. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-Black.ttf +0 -0
  136. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-BlackItalic.ttf +0 -0
  137. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-Bold.ttf +0 -0
  138. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-BoldItalic.ttf +0 -0
  139. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-ExtraBold.ttf +0 -0
  140. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-ExtraBoldItalic.ttf +0 -0
  141. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-ExtraLight.ttf +0 -0
  142. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-ExtraLightItalic.ttf +0 -0
  143. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-Italic.ttf +0 -0
  144. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-Light.ttf +0 -0
  145. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-LightItalic.ttf +0 -0
  146. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-Medium.ttf +0 -0
  147. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-MediumItalic.ttf +0 -0
  148. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-Regular.ttf +0 -0
  149. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-SemiBold.ttf +0 -0
  150. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-SemiBoldItalic.ttf +0 -0
  151. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-Thin.ttf +0 -0
  152. package/src/assets/fonts/noto-serif/NotoSerif_Condensed-ThinItalic.ttf +0 -0
  153. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-Black.ttf +0 -0
  154. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-BlackItalic.ttf +0 -0
  155. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-Bold.ttf +0 -0
  156. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-BoldItalic.ttf +0 -0
  157. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-ExtraBold.ttf +0 -0
  158. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-ExtraBoldItalic.ttf +0 -0
  159. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-ExtraLight.ttf +0 -0
  160. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-ExtraLightItalic.ttf +0 -0
  161. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-Italic.ttf +0 -0
  162. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-Light.ttf +0 -0
  163. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-LightItalic.ttf +0 -0
  164. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-Medium.ttf +0 -0
  165. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-MediumItalic.ttf +0 -0
  166. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-Regular.ttf +0 -0
  167. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-SemiBold.ttf +0 -0
  168. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-SemiBoldItalic.ttf +0 -0
  169. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-Thin.ttf +0 -0
  170. package/src/assets/fonts/noto-serif/NotoSerif_ExtraCondensed-ThinItalic.ttf +0 -0
  171. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-Black.ttf +0 -0
  172. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-BlackItalic.ttf +0 -0
  173. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-Bold.ttf +0 -0
  174. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-BoldItalic.ttf +0 -0
  175. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-ExtraBold.ttf +0 -0
  176. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-ExtraBoldItalic.ttf +0 -0
  177. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-ExtraLight.ttf +0 -0
  178. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-ExtraLightItalic.ttf +0 -0
  179. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-Italic.ttf +0 -0
  180. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-Light.ttf +0 -0
  181. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-LightItalic.ttf +0 -0
  182. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-Medium.ttf +0 -0
  183. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-MediumItalic.ttf +0 -0
  184. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-Regular.ttf +0 -0
  185. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-SemiBold.ttf +0 -0
  186. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-SemiBoldItalic.ttf +0 -0
  187. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-Thin.ttf +0 -0
  188. package/src/assets/fonts/noto-serif/NotoSerif_SemiCondensed-ThinItalic.ttf +0 -0
  189. package/src/assets/fonts/oswald/Oswald-Bold.ttf +0 -0
  190. package/src/assets/fonts/oswald/Oswald-ExtraLight.ttf +0 -0
  191. package/src/assets/fonts/oswald/Oswald-Light.ttf +0 -0
  192. package/src/assets/fonts/oswald/Oswald-Medium.ttf +0 -0
  193. package/src/assets/fonts/oswald/Oswald-Regular.ttf +0 -0
  194. package/src/assets/fonts/oswald/Oswald-SemiBold.ttf +0 -0
  195. package/src/assets/fonts/oswald/Oswald-VariableFont_wght.ttf +0 -0
  196. package/src/assets/fonts/pacifico/Pacifico-Regular.ttf +0 -0
  197. package/src/assets/fonts/playfair/PlayfairDisplay-Black.ttf +0 -0
  198. package/src/assets/fonts/playfair/PlayfairDisplay-BlackItalic.ttf +0 -0
  199. package/src/assets/fonts/playfair/PlayfairDisplay-Bold.ttf +0 -0
  200. package/src/assets/fonts/playfair/PlayfairDisplay-BoldItalic.ttf +0 -0
  201. package/src/assets/fonts/playfair/PlayfairDisplay-ExtraBold.ttf +0 -0
  202. package/src/assets/fonts/playfair/PlayfairDisplay-ExtraBoldItalic.ttf +0 -0
  203. package/src/assets/fonts/playfair/PlayfairDisplay-Italic-VariableFont_wght.ttf +0 -0
  204. package/src/assets/fonts/playfair/PlayfairDisplay-Italic.ttf +0 -0
  205. package/src/assets/fonts/playfair/PlayfairDisplay-Medium.ttf +0 -0
  206. package/src/assets/fonts/playfair/PlayfairDisplay-MediumItalic.ttf +0 -0
  207. package/src/assets/fonts/playfair/PlayfairDisplay-Regular.ttf +0 -0
  208. package/src/assets/fonts/playfair/PlayfairDisplay-SemiBold.ttf +0 -0
  209. package/src/assets/fonts/playfair/PlayfairDisplay-SemiBoldItalic.ttf +0 -0
  210. package/src/assets/fonts/playfair/PlayfairDisplay-VariableFont_wght.ttf +0 -0
  211. package/src/assets/fonts/poiret-one/PoiretOne-Regular.ttf +0 -0
  212. package/src/assets/fonts/roboto/Roboto-Black.ttf +0 -0
  213. package/src/assets/fonts/roboto/Roboto-BlackItalic.ttf +0 -0
  214. package/src/assets/fonts/roboto/Roboto-Bold.ttf +0 -0
  215. package/src/assets/fonts/roboto/Roboto-BoldItalic.ttf +0 -0
  216. package/src/assets/fonts/roboto/Roboto-ExtraBold.ttf +0 -0
  217. package/src/assets/fonts/roboto/Roboto-ExtraBoldItalic.ttf +0 -0
  218. package/src/assets/fonts/roboto/Roboto-ExtraLight.ttf +0 -0
  219. package/src/assets/fonts/roboto/Roboto-ExtraLightItalic.ttf +0 -0
  220. package/src/assets/fonts/roboto/Roboto-Italic-VariableFont_wdth,wght.ttf +0 -0
  221. package/src/assets/fonts/roboto/Roboto-Italic.ttf +0 -0
  222. package/src/assets/fonts/roboto/Roboto-Light.ttf +0 -0
  223. package/src/assets/fonts/roboto/Roboto-LightItalic.ttf +0 -0
  224. package/src/assets/fonts/roboto/Roboto-Medium.ttf +0 -0
  225. package/src/assets/fonts/roboto/Roboto-MediumItalic.ttf +0 -0
  226. package/src/assets/fonts/roboto/Roboto-Regular.ttf +0 -0
  227. package/src/assets/fonts/roboto/Roboto-SemiBold.ttf +0 -0
  228. package/src/assets/fonts/roboto/Roboto-SemiBoldItalic.ttf +0 -0
  229. package/src/assets/fonts/roboto/Roboto-Thin.ttf +0 -0
  230. package/src/assets/fonts/roboto/Roboto-ThinItalic.ttf +0 -0
  231. package/src/assets/fonts/roboto/Roboto-VariableFont_wdth,wght.ttf +0 -0
  232. package/src/assets/fonts/roboto/Roboto_Condensed-Black.ttf +0 -0
  233. package/src/assets/fonts/roboto/Roboto_Condensed-BlackItalic.ttf +0 -0
  234. package/src/assets/fonts/roboto/Roboto_Condensed-Bold.ttf +0 -0
  235. package/src/assets/fonts/roboto/Roboto_Condensed-BoldItalic.ttf +0 -0
  236. package/src/assets/fonts/roboto/Roboto_Condensed-ExtraBold.ttf +0 -0
  237. package/src/assets/fonts/roboto/Roboto_Condensed-ExtraBoldItalic.ttf +0 -0
  238. package/src/assets/fonts/roboto/Roboto_Condensed-ExtraLight.ttf +0 -0
  239. package/src/assets/fonts/roboto/Roboto_Condensed-ExtraLightItalic.ttf +0 -0
  240. package/src/assets/fonts/roboto/Roboto_Condensed-Italic.ttf +0 -0
  241. package/src/assets/fonts/roboto/Roboto_Condensed-Light.ttf +0 -0
  242. package/src/assets/fonts/roboto/Roboto_Condensed-LightItalic.ttf +0 -0
  243. package/src/assets/fonts/roboto/Roboto_Condensed-Medium.ttf +0 -0
  244. package/src/assets/fonts/roboto/Roboto_Condensed-MediumItalic.ttf +0 -0
  245. package/src/assets/fonts/roboto/Roboto_Condensed-Regular.ttf +0 -0
  246. package/src/assets/fonts/roboto/Roboto_Condensed-SemiBold.ttf +0 -0
  247. package/src/assets/fonts/roboto/Roboto_Condensed-SemiBoldItalic.ttf +0 -0
  248. package/src/assets/fonts/roboto/Roboto_Condensed-Thin.ttf +0 -0
  249. package/src/assets/fonts/roboto/Roboto_Condensed-ThinItalic.ttf +0 -0
  250. package/src/assets/fonts/roboto/Roboto_SemiCondensed-Black.ttf +0 -0
  251. package/src/assets/fonts/roboto/Roboto_SemiCondensed-BlackItalic.ttf +0 -0
  252. package/src/assets/fonts/roboto/Roboto_SemiCondensed-Bold.ttf +0 -0
  253. package/src/assets/fonts/roboto/Roboto_SemiCondensed-BoldItalic.ttf +0 -0
  254. package/src/assets/fonts/roboto/Roboto_SemiCondensed-ExtraBold.ttf +0 -0
  255. package/src/assets/fonts/roboto/Roboto_SemiCondensed-ExtraBoldItalic.ttf +0 -0
  256. package/src/assets/fonts/roboto/Roboto_SemiCondensed-ExtraLight.ttf +0 -0
  257. package/src/assets/fonts/roboto/Roboto_SemiCondensed-ExtraLightItalic.ttf +0 -0
  258. package/src/assets/fonts/roboto/Roboto_SemiCondensed-Italic.ttf +0 -0
  259. package/src/assets/fonts/roboto/Roboto_SemiCondensed-Light.ttf +0 -0
  260. package/src/assets/fonts/roboto/Roboto_SemiCondensed-LightItalic.ttf +0 -0
  261. package/src/assets/fonts/roboto/Roboto_SemiCondensed-Medium.ttf +0 -0
  262. package/src/assets/fonts/roboto/Roboto_SemiCondensed-MediumItalic.ttf +0 -0
  263. package/src/assets/fonts/roboto/Roboto_SemiCondensed-Regular.ttf +0 -0
  264. package/src/assets/fonts/roboto/Roboto_SemiCondensed-SemiBold.ttf +0 -0
  265. package/src/assets/fonts/roboto/Roboto_SemiCondensed-SemiBoldItalic.ttf +0 -0
  266. package/src/assets/fonts/roboto/Roboto_SemiCondensed-Thin.ttf +0 -0
  267. package/src/assets/fonts/roboto/Roboto_SemiCondensed-ThinItalic.ttf +0 -0
  268. package/src/assets/fonts/roboto-slab/RobotoSlab-Black.ttf +0 -0
  269. package/src/assets/fonts/roboto-slab/RobotoSlab-Bold.ttf +0 -0
  270. package/src/assets/fonts/roboto-slab/RobotoSlab-ExtraBold.ttf +0 -0
  271. package/src/assets/fonts/roboto-slab/RobotoSlab-ExtraLight.ttf +0 -0
  272. package/src/assets/fonts/roboto-slab/RobotoSlab-Light.ttf +0 -0
  273. package/src/assets/fonts/roboto-slab/RobotoSlab-Medium.ttf +0 -0
  274. package/src/assets/fonts/roboto-slab/RobotoSlab-Regular.ttf +0 -0
  275. package/src/assets/fonts/roboto-slab/RobotoSlab-SemiBold.ttf +0 -0
  276. package/src/assets/fonts/roboto-slab/RobotoSlab-Thin.ttf +0 -0
  277. package/src/assets/fonts/roboto-slab/RobotoSlab-VariableFont_wght.ttf +0 -0
  278. package/src/assets/fonts/rubik-mono-one/RubikMonoOne-Regular.ttf +0 -0
  279. package/src/assets/icons/arrows-up-down-left-right.svg +1 -0
  280. package/src/assets/icons/arrows-up-down.svg +1 -0
  281. package/src/assets/icons/attachments.svg +1 -3
  282. package/src/assets/icons/attachments2.svg +3 -0
  283. package/src/assets/icons/clear.svg +1 -5
  284. package/src/assets/icons/cursor-default-custom.svg +10 -0
  285. package/src/assets/icons/cursor-default.svg +1 -0
  286. package/src/assets/icons/cursor-default2.svg +1 -0
  287. package/src/assets/icons/emoji.svg +1 -6
  288. package/src/assets/icons/emoji2.svg +6 -0
  289. package/src/assets/icons/frame.svg +1 -3
  290. package/src/assets/icons/frame2.svg +3 -0
  291. package/src/assets/icons/i-cursor.svg +1 -0
  292. package/src/assets/icons/image.svg +1 -3
  293. package/src/assets/icons/image2.svg +3 -0
  294. package/src/assets/icons/note.svg +1 -3
  295. package/src/assets/icons/note2.svg +3 -0
  296. package/src/assets/icons/pencil.svg +1 -3
  297. package/src/assets/icons/pencil2.svg +3 -0
  298. package/src/assets/icons/rotate-icon.svg +3 -0
  299. package/src/assets/icons/select.svg +1 -1
  300. package/src/assets/icons/shapes.svg +1 -3
  301. package/src/assets/icons/shapes2.svg +3 -0
  302. package/src/assets/icons/text-add.svg +1 -3
  303. package/src/assets/icons/text-add2.svg +3 -0
  304. package/src/assets/icons/trash.svg +1 -0
  305. package/src/core/PixiEngine.js +32 -0
  306. package/src/core/commands/CopyObjectCommand.js +20 -9
  307. package/src/core/commands/GroupMoveCommand.js +49 -13
  308. package/src/core/commands/MoveObjectCommand.js +4 -24
  309. package/src/core/commands/PasteObjectCommand.js +26 -15
  310. package/src/core/events/Events.js +2 -0
  311. package/src/core/index.js +575 -47
  312. package/src/grid/GridFactory.js +3 -3
  313. package/src/grid/LineGrid.js +42 -20
  314. package/src/moodboard/MoodBoard.js +11 -0
  315. package/src/objects/DrawingObject.js +16 -7
  316. package/src/objects/FileObject.js +25 -11
  317. package/src/objects/FrameObject.js +38 -9
  318. package/src/objects/ImageObject.js +24 -5
  319. package/src/objects/NoteObject.js +227 -39
  320. package/src/objects/ShapeObject.js +9 -8
  321. package/src/objects/TextObject.js +2 -20
  322. package/src/services/BoardService.js +3 -3
  323. package/src/services/FrameService.js +95 -17
  324. package/src/services/ZoomPanController.js +14 -3
  325. package/src/tools/BaseTool.js +6 -1
  326. package/src/tools/ToolManager.js +24 -1
  327. package/src/tools/object-tools/DrawingTool.js +3 -1
  328. package/src/tools/object-tools/PlacementTool.js +366 -105
  329. package/src/tools/object-tools/SelectTool.js +508 -153
  330. package/src/tools/object-tools/TextTool.js +23 -2
  331. package/src/tools/object-tools/selection/BoxSelectController.js +5 -0
  332. package/src/ui/FilePropertiesPanel.js +9 -2
  333. package/src/ui/FramePropertiesPanel.js +239 -91
  334. package/src/ui/HtmlHandlesLayer.js +383 -126
  335. package/src/ui/HtmlTextLayer.js +122 -26
  336. package/src/ui/NotePropertiesPanel.js +128 -44
  337. package/src/ui/TextPropertiesPanel.js +100 -118
  338. package/src/ui/Toolbar.js +254 -65
  339. package/src/ui/Topbar.js +112 -10
  340. package/src/ui/ZoomPanel.js +8 -2
  341. package/src/ui/styles/index.css +5 -0
  342. package/src/ui/styles/panels.css +232 -0
  343. package/src/ui/styles/toolbar.css +77 -0
  344. package/src/ui/styles/topbar.css +113 -0
  345. package/src/ui/styles/workspace.css +481 -263
  346. package/src/utils/emojiResolver.js +121 -0
@@ -14,13 +14,15 @@ export class NoteObject {
14
14
  this.objectData = objectData;
15
15
 
16
16
  // Размеры записки
17
- this.width = objectData.width || objectData.properties?.width || 160;
18
- this.height = objectData.height || objectData.properties?.height || 100;
17
+ const defaultSide = 250; // квадрат 250x250
18
+ this.width = objectData.width || objectData.properties?.width || defaultSide;
19
+ this.height = objectData.height || objectData.properties?.height || defaultSide;
19
20
 
20
21
  // Свойства записки
21
22
  const props = objectData.properties || {};
22
23
  this.content = props.content || '';
23
- this.fontSize = props.fontSize || 16;
24
+ this.fontSize = props.fontSize || 32;
25
+ const fontFamily = props.fontFamily || 'Caveat, Arial, cursive';
24
26
  this.backgroundColor = (typeof props.backgroundColor === 'number') ? props.backgroundColor : 0xFFF9C4; // Светло-желтый
25
27
  this.borderColor = (typeof props.borderColor === 'number') ? props.borderColor : 0xF9A825; // Золотистый
26
28
  this.textColor = (typeof props.textColor === 'number') ? props.textColor : 0x1A1A1A; // Почти черный для лучшей контрастности
@@ -32,25 +34,74 @@ export class NoteObject {
32
34
  this.container.eventMode = 'static';
33
35
  this.container.interactiveChildren = true;
34
36
 
37
+ // Тени по бокам (как у .box::before / .box::after)
38
+ this.shadowLayer = new PIXI.Container();
39
+ this.shadowLeft = new PIXI.Graphics();
40
+ this.shadowRight = new PIXI.Graphics();
41
+ this.shadowLayer.addChild(this.shadowLeft);
42
+ this.shadowLayer.addChild(this.shadowRight);
43
+ try {
44
+ // Мягкая тень (чуть сильнее)
45
+ this.shadowLayer.filters = [new PIXI.filters.BlurFilter(12)];
46
+ } catch (_) {}
47
+ this.container.addChild(this.shadowLayer);
48
+
35
49
  // Графика фона
36
50
  this.graphics = new PIXI.Graphics();
37
51
  this.container.addChild(this.graphics);
38
52
 
53
+ // Функция согласованной высоты строки (как в HtmlTextLayer)
54
+ this._computeLineHeightPx = (fs) => {
55
+ if (fs <= 12) return Math.round(fs * 1.40);
56
+ if (fs <= 18) return Math.round(fs * 1.34);
57
+ if (fs <= 36) return Math.round(fs * 1.26);
58
+ if (fs <= 48) return Math.round(fs * 1.24);
59
+ if (fs <= 72) return Math.round(fs * 1.22);
60
+ if (fs <= 96) return Math.round(fs * 1.20);
61
+ return Math.round(fs * 1.18);
62
+ };
63
+
39
64
  // Текст записки
40
65
  this.textField = new PIXI.Text(this.content, {
41
- fontFamily: 'system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif',
66
+ fontFamily: fontFamily,
42
67
  fontSize: this.fontSize,
43
68
  fill: this.textColor,
44
69
  align: 'center',
70
+ letterSpacing: 0,
45
71
  wordWrap: true,
46
- wordWrapWidth: this.width - 16, // Отступы по 8px с каждой стороны
47
- lineHeight: this.fontSize * 1.2,
72
+ breakWords: true,
73
+ wordWrapWidth: Math.max(1, Math.min(360, (this.width - 32))),
74
+ lineHeight: this._computeLineHeightPx(this.fontSize),
75
+ padding: 3,
76
+ trim: false,
48
77
  resolution: (typeof window !== 'undefined' && window.devicePixelRatio) ? window.devicePixelRatio : 1
49
78
  });
50
79
 
80
+ // Маска для обрезки текста по границам записки
81
+ this.textMask = new PIXI.Graphics();
82
+ this.container.addChild(this.textMask);
83
+ this.textField.mask = this.textMask;
84
+
51
85
  this._redraw(); // Сначала рисуем фон
86
+ // Прячем текст до загрузки шрифта Caveat, чтобы не показывать системный
87
+ this.textField.visible = false;
52
88
  this.container.addChild(this.textField); // Затем добавляем текст поверх
53
89
  this._updateTextPosition();
90
+ // Если шрифт уже загружен — показываем сразу, иначе подождём загрузки
91
+ if (this._isFontLoaded(fontFamily, this.fontSize)) {
92
+ this.textField.visible = true;
93
+ } else {
94
+ this._ensureWebFontApplied(fontFamily, this.fontSize);
95
+ // Фолбэк на случай отсутствия Font Loading API — короткая задержка
96
+ try {
97
+ if (!(typeof document !== 'undefined' && document.fonts && typeof document.fonts.load === 'function')) {
98
+ setTimeout(() => { try { this.textField.visible = true; } catch (_) {} }, 300);
99
+ }
100
+ } catch (_) {}
101
+ }
102
+
103
+ // Гарантируем применение web-font (например, Caveat) при первом создании
104
+ this._ensureWebFontApplied(fontFamily, this.fontSize);
54
105
 
55
106
  // Отладочная информация
56
107
  console.log('NoteObject created with content:', this.content);
@@ -63,6 +114,7 @@ export class NoteObject {
63
114
  properties: {
64
115
  content: this.content,
65
116
  fontSize: this.fontSize,
117
+ fontFamily: fontFamily,
66
118
  backgroundColor: this.backgroundColor,
67
119
  borderColor: this.borderColor,
68
120
  textColor: this.textColor,
@@ -73,14 +125,71 @@ export class NoteObject {
73
125
  this._redraw();
74
126
  }
75
127
 
128
+ /**
129
+ * Возвращает видимую ширину текстового блока, согласованную с режимом редактирования
130
+ */
131
+ _getVisibleTextWidth() {
132
+ const horizontalPadding = 16;
133
+ const contentWidth = Math.max(1, this.width - (horizontalPadding * 2));
134
+ return Math.max(1, Math.min(360, contentWidth));
135
+ }
136
+
137
+ /** Проверяет, загружен ли указанный web-шрифт */
138
+ _isFontLoaded(fontFamily, fontSizePx) {
139
+ try {
140
+ if (typeof document === 'undefined' || !document.fonts || typeof document.fonts.check !== 'function') return false;
141
+ const primary = String(fontFamily || '').split(',')[0].trim().replace(/^['"]|['"]$/g, '') || 'Caveat';
142
+ const size = Math.max(1, Number(fontSizePx) || 32);
143
+ const spec = `normal ${size}px ${primary}`;
144
+ return document.fonts.check(spec);
145
+ } catch (_) {
146
+ return false;
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Подгоняет размер шрифта так, чтобы текст умещался внутри записки
152
+ */
153
+ _fitTextToBounds() {
154
+ if (!this.textField) return;
155
+ const maxWidth = this._getVisibleTextWidth();
156
+ const verticalPadding = 16;
157
+ const maxHeight = Math.max(1, this.height - (verticalPadding * 2));
158
+
159
+ // Базовые установки стиля перед измерением
160
+ this.textField.style.wordWrap = true;
161
+ this.textField.style.breakWords = true;
162
+ this.textField.style.wordWrapWidth = maxWidth;
163
+
164
+ // Начинаем с желаемого размера шрифта
165
+ let displayFontSize = Math.max(1, Number(this.fontSize) || 32);
166
+ const minFontSize = 8;
167
+ let safety = 0;
168
+ const maxIterations = 64;
169
+
170
+ while (safety < maxIterations) {
171
+ this.textField.style.fontSize = displayFontSize;
172
+ this.textField.style.lineHeight = this._computeLineHeightPx(displayFontSize);
173
+ this.textField.updateText();
174
+ const needsShrink = this.textField.height > maxHeight;
175
+ if (!needsShrink || displayFontSize <= minFontSize) break;
176
+ displayFontSize = Math.max(minFontSize, displayFontSize - 1);
177
+ safety++;
178
+ }
179
+ }
180
+
76
181
  getPixi() {
77
182
  return this.container;
78
183
  }
79
184
 
80
185
  updateSize(size) {
81
186
  if (!size) return;
82
- this.width = Math.max(80, size.width || this.width);
83
- this.height = Math.max(60, size.height || this.height);
187
+ let w = Math.max(80, size.width || this.width);
188
+ let h = Math.max(60, size.height || this.height);
189
+ // Держим квадрат
190
+ const side = Math.max(w, h);
191
+ this.width = side;
192
+ this.height = side;
84
193
 
85
194
  this._redraw();
86
195
  this._updateTextPosition();
@@ -98,8 +207,10 @@ export class NoteObject {
98
207
 
99
208
  setContent(content) {
100
209
  this.content = content || '';
210
+ if (this.textField) this.textField.visible = false;
101
211
  this.textField.text = this.content;
102
212
  this._updateTextPosition();
213
+ if (this.textField) this.textField.visible = true;
103
214
  if (this.container && this.container._mb) {
104
215
  this.container._mb.properties = {
105
216
  ...(this.container._mb.properties || {}),
@@ -139,7 +250,22 @@ export class NoteObject {
139
250
  if (typeof fontSize === 'number') {
140
251
  this.fontSize = fontSize;
141
252
  this.textField.style.fontSize = fontSize;
142
- this.textField.style.lineHeight = fontSize * 1.2;
253
+ // Согласуем с HTML-слоем
254
+ this.textField.style.lineHeight = this._computeLineHeightPx(fontSize);
255
+ this.textField.style.padding = 3;
256
+ this.textField.style.trim = false;
257
+ this.textField.style.letterSpacing = 0;
258
+ }
259
+ if (typeof arguments[0]?.fontFamily === 'string') {
260
+ const ff = arguments[0].fontFamily;
261
+ this.textField.style.fontFamily = ff;
262
+ if (this.container && this.container._mb) {
263
+ this.container._mb.properties = {
264
+ ...(this.container._mb.properties || {}),
265
+ fontFamily: ff
266
+ };
267
+ }
268
+ this._ensureWebFontApplied(ff, this.fontSize);
143
269
  }
144
270
  if (typeof backgroundColor === 'number') this.backgroundColor = backgroundColor;
145
271
  if (typeof borderColor === 'number') this.borderColor = borderColor;
@@ -162,6 +288,27 @@ export class NoteObject {
162
288
  this._updateTextPosition();
163
289
  }
164
290
 
291
+ /**
292
+ * Дожидается загрузки веб-шрифта и обновляет PIXI.Text, чтобы применились корректные метрики
293
+ */
294
+ _ensureWebFontApplied(fontFamily, fontSizePx) {
295
+ try {
296
+ if (typeof document === 'undefined' || !document.fonts || !document.fonts.load) return;
297
+ const primary = String(fontFamily || '').split(',')[0].trim().replace(/^['"]|['"]$/g, '') || 'Caveat';
298
+ const size = Math.max(1, Number(fontSizePx) || 32);
299
+ const spec = `normal ${size}px ${primary}`;
300
+ document.fonts.load(spec).then(() => {
301
+ // Обновляем текст после загрузки шрифта и сразу подгоняем без мерцания
302
+ try {
303
+ if (this.textField) this.textField.visible = false;
304
+ this.textField.style.fontFamily = fontFamily;
305
+ this._updateTextPosition();
306
+ if (this.textField) this.textField.visible = true;
307
+ } catch (_) {}
308
+ }).catch(() => {});
309
+ } catch (_) {}
310
+ }
311
+
165
312
  _redraw() {
166
313
  const g = this.graphics;
167
314
  const w = this.width;
@@ -169,29 +316,50 @@ export class NoteObject {
169
316
 
170
317
  g.clear();
171
318
 
172
- // Тень записки (эффект приподнятости)
173
- g.beginFill(0x000000, 0.1);
174
- g.drawRoundedRect(2, 2, w, h, 4);
175
- g.endFill();
176
-
177
- // Основной фон записки
178
- g.beginFill(this.backgroundColor, 1);
179
- g.lineStyle(1, this.borderColor, 1);
180
- g.drawRoundedRect(0, 0, w, h, 4);
181
- g.endFill();
319
+ // Левая и правая тень (узкие полосы снизу)
320
+ const shH = Math.max(8, Math.round(h * 0.05)); // толще тень (~5% высоты)
321
+ const shW = Math.max(24, Math.round(w * 0.45)); // шире тень (~45% ширины)
322
+ const bottom = Math.max(8, Math.round(h * 0.03)) + 10; // отступ снизу ~10
323
+
324
+ const drawShadow = (g) => {
325
+ g.clear();
326
+ g.beginFill(0x000000, 1);
327
+ g.drawRoundedRect(0, 0, shW, shH, shH / 2);
328
+ g.endFill();
329
+ };
330
+ drawShadow(this.shadowLeft);
331
+ drawShadow(this.shadowRight);
332
+
333
+ // Обновляем маску текста под новые размеры
334
+ const pad = 16;
335
+ this.textMask.clear();
336
+ this.textMask.beginFill(0x000000, 1);
337
+ this.textMask.drawRect(pad, pad, Math.max(1, w - pad * 2), Math.max(1, h - pad * 2));
338
+ this.textMask.endFill();
339
+
340
+ // Базовые позиции как в CSS: left:15px и right:15px; bottom:10px
341
+ this.shadowLeft.x = 15;
342
+ this.shadowLeft.y = h - shH - 10;
343
+ this.shadowLeft.skew = new PIXI.ObservablePoint(() => {}, null, -5 * Math.PI / 180, 0);
344
+ this.shadowLeft.rotation = -5 * Math.PI / 180;
345
+
346
+ this.shadowRight.x = w - shW - 15;
347
+ this.shadowRight.y = h - shH - 10;
348
+ this.shadowRight.skew = new PIXI.ObservablePoint(() => {}, null, 5 * Math.PI / 180, 0);
349
+ this.shadowRight.rotation = 5 * Math.PI / 180;
350
+
351
+ this.shadowLayer.alpha = 0.7; // темнее
182
352
 
183
- // Небольшая полоска сверху для эффекта стикера
184
- g.beginFill(this.borderColor, 0.3);
185
- g.drawRoundedRect(0, 0, w, 8, 4);
353
+ // Основной фон записки как .box: белый с небольшим радиусом
354
+ const boxBg = (typeof this.backgroundColor === 'number') ? this.backgroundColor : 0xFFFFFF;
355
+ g.beginFill(boxBg, 1);
356
+ g.drawRoundedRect(0, 0, w, h, 2);
186
357
  g.endFill();
187
358
 
188
- // Линии на записке (эффект бумаги)
189
- g.lineStyle(0.5, this.borderColor, 0.2);
190
- const lineSpacing = Math.max(16, this.fontSize + 4);
191
- for (let y = 24; y < h - 8; y += lineSpacing) {
192
- g.moveTo(8, y);
193
- g.lineTo(w - 8, y);
194
- }
359
+ // Линии внутри записки убраны по требованию дизайна
360
+
361
+ // pivot контейнера строго по центру, чтобы ядро корректно вычисляло левый-верх
362
+ this.container.pivot.set(w / 2, h / 2);
195
363
 
196
364
  // Устанавливаем hit area для контейнера
197
365
  this.container.hitArea = new PIXI.Rectangle(0, 0, w, h);
@@ -204,24 +372,44 @@ export class NoteObject {
204
372
  point.y >= bounds.y &&
205
373
  point.y <= bounds.y + bounds.height;
206
374
  };
375
+
376
+ // Hover-эффект: ослабляем короб тени и сдвигаем ближе к центру (как в CSS)
377
+ this.container.eventMode = 'static';
378
+ this.container.on('pointerover', () => {
379
+ this.shadowLayer.alpha = 0.55;
380
+ this.shadowLeft.x = 5;
381
+ this.shadowRight.x = w - shW - 5;
382
+ this.shadowLeft.rotation = 0;
383
+ this.shadowRight.rotation = 0;
384
+ });
385
+ this.container.on('pointerout', () => {
386
+ this.shadowLayer.alpha = 0.7;
387
+ this.shadowLeft.x = 15;
388
+ this.shadowRight.x = w - shW - 15;
389
+ this.shadowLeft.rotation = -5 * Math.PI / 180;
390
+ this.shadowRight.rotation = 5 * Math.PI / 180;
391
+ });
207
392
  }
208
393
 
209
394
  _updateTextPosition() {
210
395
  if (!this.textField) return;
211
396
 
212
- // Обновляем стиль текста
213
- this.textField.style.wordWrapWidth = this.width - 16;
214
-
215
- // Ждем, пока PIXI пересчитает размеры текста
397
+ // Обновляем стиль текста согласно ограничениям редактора
398
+ this.textField.style.wordWrapWidth = this._getVisibleTextWidth();
399
+ this.textField.style.wordWrap = true;
400
+ this.textField.style.breakWords = true;
401
+
402
+ // Подгоняем размер шрифта под доступные границы
403
+ this._fitTextToBounds();
404
+
405
+ // Обновляем текст после подгонки
216
406
  this.textField.updateText();
217
407
 
218
- // Центрируем текст по горизонтали
408
+ // Центрируем текст по центру заметки
219
409
  const centerX = this.width / 2;
220
- const topMargin = 20; // Отступ от верха (ниже полоски)
221
-
222
- // Используем anchor для центрирования
223
- this.textField.anchor.set(0.5, 0);
410
+ const centerY = this.height / 2;
411
+ this.textField.anchor.set(0.5, 0.5);
224
412
  this.textField.x = centerX;
225
- this.textField.y = topMargin;
413
+ this.textField.y = centerY;
226
414
  }
227
415
  }
@@ -58,17 +58,18 @@ export class ShapeObject {
58
58
  /** Перерисовать с сохранением трансформаций */
59
59
  _redrawPreserveTransform(width, height, color, kind, cornerRadius) {
60
60
  const g = this.graphics;
61
- const x = g.x;
62
- const y = g.y;
61
+ // Сохраняем текущий центр и поворот
62
+ const centerX = g.x;
63
+ const centerY = g.y;
63
64
  const rot = g.rotation || 0;
64
- const pivotX = g.pivot?.x || 0;
65
- const pivotY = g.pivot?.y || 0;
66
65
 
67
66
  this._draw(width, height, color, kind, cornerRadius);
68
-
69
- g.pivot.set(pivotX, pivotY);
70
- g.x = x;
71
- g.y = y;
67
+ // ВАЖНО: для согласованности с ядром (позиция — левый-верх, PIXI — центр)
68
+ // pivot должен всегда быть в центре объекта (w/2, h/2)
69
+ g.pivot.set(width / 2, height / 2);
70
+ // Восстанавливаем центр
71
+ g.x = centerX;
72
+ g.y = centerY;
72
73
  g.rotation = rot;
73
74
  }
74
75
 
@@ -91,16 +91,7 @@ export class TextObject {
91
91
  * Для TextObject фактическая логика скрытия/показа обрабатывается в HtmlTextLayer
92
92
  */
93
93
  hideText() {
94
- // Для TextObject визуализация происходит в HtmlTextLayer
95
- // Эмитим событие для скрытия текста
96
- if (this.rect && this.rect._mb && this.rect._mb.objectId) {
97
- // Используем EventBus через core, если доступен
98
- if (typeof window !== 'undefined' && window.moodboardEventBus) {
99
- window.moodboardEventBus.emit('tool:hide:object:text', {
100
- objectId: this.rect._mb.objectId
101
- });
102
- }
103
- }
94
+ // Ничего не делаем: скрытие текста обрабатывается HtmlTextLayer по событию
104
95
  }
105
96
 
106
97
  /**
@@ -108,16 +99,7 @@ export class TextObject {
108
99
  * Для TextObject фактическая логика скрытия/показа обрабатывается в HtmlTextLayer
109
100
  */
110
101
  showText() {
111
- // Для TextObject визуализация происходит в HtmlTextLayer
112
- // Эмитим событие для показа текста
113
- if (this.rect && this.rect._mb && this.rect._mb.objectId) {
114
- // Используем EventBus через core, если доступен
115
- if (typeof window !== 'undefined' && window.moodboardEventBus) {
116
- window.moodboardEventBus.emit('tool:show:object:text', {
117
- objectId: this.rect._mb.objectId
118
- });
119
- }
120
- }
102
+ // Ничего не делаем: показ текста обрабатывается HtmlTextLayer по событию
121
103
  }
122
104
  }
123
105
 
@@ -15,11 +15,11 @@ export class BoardService {
15
15
  const canvasSize = (this._getCanvasSize?.() || {});
16
16
  this.grid = GridFactory.createGrid('line', {
17
17
  enabled: true,
18
- size: 20,
18
+ size: 32,
19
19
  width: canvasSize.width || 800,
20
20
  height: canvasSize.height || 600,
21
- color: 0xE6E6E6,
22
- opacity: 0.5
21
+ color: 0x6a6aff,
22
+ opacity: 0.4
23
23
  });
24
24
  this.grid.updateVisual();
25
25
  this.pixi.setGrid(this.grid);
@@ -7,15 +7,76 @@ export class FrameService {
7
7
  this.state = state;
8
8
  }
9
9
 
10
+ _forceFramesBelow() {
11
+ const world = this.pixi?.worldLayer || this.pixi?.app?.stage;
12
+ if (world) world.sortableChildren = true;
13
+ let z = 0;
14
+ for (const o of this.state.state.objects || []) {
15
+ const pix = this.pixi.objects.get(o.id);
16
+ if (!pix) continue;
17
+ if (o.type === 'frame') {
18
+ pix.zIndex = -100000;
19
+ } else {
20
+ pix.zIndex = z++;
21
+ }
22
+ }
23
+ }
24
+
25
+ _attachIntersectingObjectsToFrame(frameId) {
26
+ const framePixi = this.pixi.objects.get(frameId);
27
+ if (!framePixi || !framePixi.getBounds) return false;
28
+ const fb = framePixi.getBounds();
29
+ const frameRect = { x: fb.x, y: fb.y, w: fb.width, h: fb.height };
30
+ let changed = false;
31
+ for (const obj of this.state.state.objects || []) {
32
+ if (!obj || obj.id === frameId) continue;
33
+ if (obj.type === 'frame') continue;
34
+ const pix = this.pixi.objects.get(obj.id);
35
+ if (!pix || !pix.getBounds) continue;
36
+ const ob = pix.getBounds();
37
+ const objRect = { x: ob.x, y: ob.y, w: ob.width, h: ob.height };
38
+ // Пересечение прямоугольников (экраные координаты PIXI)
39
+ const intersects = !(objRect.x > frameRect.x + frameRect.w ||
40
+ (objRect.x + objRect.w) < frameRect.x ||
41
+ objRect.y > frameRect.y + frameRect.h ||
42
+ (objRect.y + objRect.h) < frameRect.y);
43
+ if (intersects) {
44
+ obj.properties = obj.properties || {};
45
+ obj.properties.frameId = frameId;
46
+ changed = true;
47
+ }
48
+ }
49
+ return changed;
50
+ }
51
+
10
52
  attach() {
53
+ // Автоприкрепление объектов при создании произвольного фрейма
54
+ this.eventBus.on(Events.Object.Created, ({ objectId, objectData }) => {
55
+ try {
56
+ if (!objectData || objectData.type !== 'frame') return;
57
+ const isArbitrary = (objectData.properties && objectData.properties.lockedAspect === false)
58
+ || (objectData.properties && objectData.properties.title === 'Произвольный')
59
+ || (objectData.properties && objectData.properties.isArbitrary === true);
60
+ if (!isArbitrary) return;
61
+ // Используем фактические bounds PIXI для надёжной проверки попадания
62
+ const changed = this._attachIntersectingObjectsToFrame(objectId);
63
+ if (changed) this.state.markDirty();
64
+ // Принудительно держим фреймы под объектами
65
+ this._forceFramesBelow();
66
+ // И оповестим общий менеджер на всякий случай
67
+ this.eventBus.emit(Events.Object.Reordered, { reason: 'attach_arbitrary_frame_children' });
68
+ } catch (_) { /* no-op */ }
69
+ });
70
+
11
71
  // Визуал подсветки при drag над фреймом и перенос детей на drag
12
72
  this.eventBus.on(Events.Tool.DragStart, (data) => {
13
73
  const moved = this.state.state.objects.find(o => o.id === data.object);
14
74
  if (moved && moved.type === 'frame') {
15
75
  // Серый фон
16
76
  this.pixi.setFrameFill(moved.id, moved.width, moved.height, 0xEEEEEE);
17
- // Cнимок стартовых позиций
18
- this._frameDragFrameStart = { x: this.pixi.objects.get(moved.id)?.x || 0, y: this.pixi.objects.get(moved.id)?.y || 0 };
77
+ // Cнимок стартовых позиций по центру PIXI
78
+ const fp = this.pixi.objects.get(moved.id);
79
+ this._frameDragFrameStart = { x: fp?.x || 0, y: fp?.y || 0 };
19
80
  const attachments = this._getFrameChildren(moved.id);
20
81
  this._frameDragChildStart = new Map();
21
82
  for (const childId of attachments) {
@@ -30,17 +91,37 @@ export class FrameService {
30
91
  if (!moved) return;
31
92
  if (moved.type === 'frame') {
32
93
  const attachments = this._getFrameChildren(moved.id);
33
- const frameStart = this._frameDragFrameStart || { x: data.position.x, y: data.position.y };
34
- const dx = data.position.x - frameStart.x;
35
- const dy = data.position.y - frameStart.y;
94
+ // ВАЖНО: считаем сдвиг по центру PIXI, чтобы не смешивать центр и левый-верх
95
+ const p = this.pixi.objects.get(moved.id);
96
+ const start = this._frameDragFrameStart || { x: p?.x || 0, y: p?.y || 0 };
97
+ const dx = (p?.x || 0) - start.x;
98
+ const dy = (p?.y || 0) - start.y;
36
99
  for (const childId of attachments) {
37
- const start = this._frameDragChildStart?.get(childId);
38
- if (!start) continue;
39
- const p = this.pixi.objects.get(childId);
40
- if (p) { p.x = start.x + dx; p.y = start.y + dy; }
100
+ let startPos = this._frameDragChildStart?.get(childId);
101
+ const childPixi = this.pixi.objects.get(childId);
102
+ if (!startPos) {
103
+ // Ребёнок мог появиться после начала drag
104
+ if (childPixi) {
105
+ startPos = { x: childPixi.x - dx, y: childPixi.y - dy };
106
+ this._frameDragChildStart = this._frameDragChildStart || new Map();
107
+ this._frameDragChildStart.set(childId, startPos);
108
+ } else {
109
+ continue;
110
+ }
111
+ }
112
+ const newCenterX = startPos.x + dx;
113
+ const newCenterY = startPos.y + dy;
114
+ if (childPixi) { childPixi.x = newCenterX; childPixi.y = newCenterY; }
41
115
  const stObj = this.state.state.objects.find(o => o.id === childId);
42
- if (stObj) { stObj.position.x = start.x + dx; stObj.position.y = start.y + dy; }
116
+ if (stObj) {
117
+ const halfW = childPixi ? (childPixi.width || 0) / 2 : 0;
118
+ const halfH = childPixi ? (childPixi.height || 0) / 2 : 0;
119
+ stObj.position.x = newCenterX - halfW;
120
+ stObj.position.y = newCenterY - halfH;
121
+ }
43
122
  }
123
+ // Во время перетаскивания тоже гарантируем порядок
124
+ this._forceFramesBelow();
44
125
  } else {
45
126
  // Hover-эффект: подсветка фрейма, если центр объекта внутри
46
127
  const centerX = moved.position.x + (moved.width || 0) / 2;
@@ -59,12 +140,10 @@ export class FrameService {
59
140
  }
60
141
  }
61
142
  if (hoverId !== this._frameHoverId) {
62
- // Снять подсветку с предыдущего
63
143
  if (this._frameHoverId) {
64
144
  const prev = frames.find(fr => fr.id === this._frameHoverId);
65
145
  if (prev) this.pixi.setFrameFill(prev.id, prev.width, prev.height, 0xFFFFFF);
66
146
  }
67
- // Включить подсветку нового
68
147
  if (hoverId) {
69
148
  const cur = frames.find(fr => fr.id === hoverId);
70
149
  if (cur) this.pixi.setFrameFill(cur.id, cur.width, cur.height, 0xEEEEEE);
@@ -77,14 +156,11 @@ export class FrameService {
77
156
  this.eventBus.on(Events.Tool.DragEnd, (data) => {
78
157
  const movedObj = this.state.state.objects.find(o => o.id === data.object);
79
158
  if (!movedObj) return;
80
- // Сброс заливки
81
159
  if (movedObj.type === 'frame') {
82
160
  this.pixi.setFrameFill(movedObj.id, movedObj.width, movedObj.height, 0xFFFFFF);
83
161
  }
84
-
85
- // Автопривязка/отвязка объекта к фрейму после перемещения
86
162
  this._recomputeFrameAttachment(movedObj.id);
87
- // Сброс временных структур и hover-подсветки
163
+ this._forceFramesBelow();
88
164
  this._frameDragFrameStart = null;
89
165
  this._frameDragChildStart = null;
90
166
  if (this._frameHoverId) {
@@ -108,7 +184,7 @@ export class FrameService {
108
184
  _recomputeFrameAttachment(objectId) {
109
185
  const obj = (this.state.state.objects || []).find(o => o.id === objectId);
110
186
  if (!obj) return;
111
- if (obj.type === 'frame') return; // фрейм к фрейму не крепим
187
+ if (obj.type === 'frame') return;
112
188
  const center = {
113
189
  x: obj.position.x + (obj.width || 0) / 2,
114
190
  y: obj.position.y + (obj.height || 0) / 2
@@ -131,6 +207,8 @@ export class FrameService {
131
207
  obj.properties = obj.properties || {};
132
208
  obj.properties.frameId = newFrameId || undefined;
133
209
  this.state.markDirty();
210
+ this._forceFramesBelow();
211
+ this.eventBus.emit(Events.Object.Reordered, { reason: 'recompute_frame_attachment' });
134
212
  }
135
213
  }
136
214
  }
@@ -9,11 +9,22 @@ export class ZoomPanController {
9
9
  attach() {
10
10
  // Масштабирование колесом — глобально отрабатываем Ctrl+Wheel
11
11
  this.eventBus.on(Events.Tool.WheelZoom, ({ x, y, delta }) => {
12
- const factor = 1 + (-delta) * 0.0015;
12
+ // Дискретный шаг зума 10%
13
13
  const world = this.pixi.worldLayer || this.pixi.app.stage;
14
14
  const oldScale = world.scale.x || 1;
15
- const newScale = Math.max(0.1, Math.min(5, oldScale * factor));
16
- if (newScale === oldScale) return;
15
+ const oldPercent = Math.round(oldScale * 100);
16
+ let targetPercent;
17
+ if (delta < 0) {
18
+ // Zoom in: к ближайшему следующему кратному 10 плюс шаг
19
+ targetPercent = Math.min(500, Math.floor(oldPercent / 10) * 10 + 10);
20
+ } else if (delta > 0) {
21
+ // Zoom out: к ближайшему предыдущему кратному 10 минус шаг
22
+ targetPercent = Math.max(10, Math.ceil(oldPercent / 10) * 10 - 10);
23
+ } else {
24
+ return;
25
+ }
26
+ const newScale = Math.max(0.1, Math.min(5, targetPercent / 100));
27
+ if (Math.abs(newScale - oldScale) < 0.0001) return;
17
28
  // Вычисляем мировые координаты точки под курсором до изменения скейла
18
29
  const worldX = (x - world.x) / oldScale;
19
30
  const worldY = (y - world.y) / oldScale;
@@ -44,7 +44,12 @@ export class BaseTool {
44
44
  */
45
45
  setCursor() {
46
46
  if (typeof document !== 'undefined' && document.body) {
47
- document.body.style.cursor = this.cursor;
47
+ // Для 'default' не ставим инлайн-стиль, чтобы сработал глобальный CSS-курсор
48
+ if (!this.cursor || this.cursor === 'default') {
49
+ document.body.style.cursor = '';
50
+ } else {
51
+ document.body.style.cursor = this.cursor;
52
+ }
48
53
  }
49
54
  }
50
55