@antscorp/antsomi-ui 2.0.84 → 2.0.86-text-editor-beta.1

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 (231) hide show
  1. package/es/assets/css/main.scss +4 -2
  2. package/es/components/index.scss +2 -0
  3. package/es/components/molecules/EmojiPopover/EmojiPopover.js +5 -1
  4. package/es/components/molecules/FontSizeInput/FontSizeInput.d.ts +3 -0
  5. package/es/components/molecules/FontSizeInput/FontSizeInput.js +128 -0
  6. package/es/components/molecules/FontSizeInput/components/FontSizeControl.d.ts +8 -0
  7. package/es/components/molecules/FontSizeInput/components/FontSizeControl.js +14 -0
  8. package/es/components/molecules/FontSizeInput/components/FontSizeDropdown.d.ts +20 -0
  9. package/es/components/molecules/FontSizeInput/components/FontSizeDropdown.js +17 -0
  10. package/es/components/molecules/FontSizeInput/constants.d.ts +2 -0
  11. package/es/components/molecules/FontSizeInput/constants.js +5 -0
  12. package/es/components/molecules/FontSizeInput/index.d.ts +2 -0
  13. package/es/components/molecules/FontSizeInput/index.js +1 -0
  14. package/es/components/molecules/FontSizeInput/styled.d.ts +3 -0
  15. package/es/components/molecules/FontSizeInput/styled.js +22 -0
  16. package/es/components/molecules/FontSizeInput/styles.scss +15 -0
  17. package/es/components/molecules/FontSizeInput/types.d.ts +24 -0
  18. package/es/components/molecules/FontSizeInput/types.js +1 -0
  19. package/es/components/molecules/FontSizeInput/utils.d.ts +7 -0
  20. package/es/components/molecules/FontSizeInput/utils.js +9 -0
  21. package/es/components/molecules/TagifyInput/TagifyInput.js +20 -14
  22. package/es/components/molecules/TagifyInput/utils.d.ts +10 -1
  23. package/es/components/molecules/TagifyInput/utils.js +64 -6
  24. package/es/components/molecules/VirtualizedMenu/VirtualizedMenu.d.ts +6 -3
  25. package/es/components/molecules/VirtualizedMenu/__mocks__/index.js +2550 -938
  26. package/es/components/molecules/VirtualizedMenu/components/Item/Item.d.ts +13 -3
  27. package/es/components/molecules/VirtualizedMenu/components/Item/Item.js +53 -25
  28. package/es/components/molecules/VirtualizedMenu/components/Item/index.d.ts +1 -1
  29. package/es/components/molecules/VirtualizedMenu/components/MenuInline/MenuInline.d.ts +8 -5
  30. package/es/components/molecules/VirtualizedMenu/components/MenuInline/MenuInline.js +289 -46
  31. package/es/components/molecules/VirtualizedMenu/components/MenuInline/index.js +1 -0
  32. package/es/components/molecules/VirtualizedMenu/styled.d.ts +1 -1
  33. package/es/components/molecules/VirtualizedMenu/styled.js +23 -4
  34. package/es/components/molecules/VirtualizedMenu/types.d.ts +6 -9
  35. package/es/components/molecules/VirtualizedMenu/utils.d.ts +8 -5
  36. package/es/components/molecules/VirtualizedMenu/utils.js +13 -18
  37. package/es/components/molecules/index.d.ts +1 -0
  38. package/es/components/molecules/index.js +1 -0
  39. package/es/components/molecules/index.scss +1 -0
  40. package/es/components/organism/ActivityTimeline/__mocks__/event_tracking.json +1290 -0
  41. package/es/components/organism/ActivityTimeline/__mocks__/timeline.json +3059 -0
  42. package/es/components/organism/TextEditor/TextEditor.d.ts +3 -0
  43. package/es/components/organism/TextEditor/TextEditor.js +251 -0
  44. package/es/components/organism/TextEditor/__mocks__/text-block.settings.json +320 -0
  45. package/es/components/organism/TextEditor/__mocks__/text-contennt.d.ts +1 -0
  46. package/es/components/organism/TextEditor/__mocks__/text-contennt.js +38 -0
  47. package/es/components/organism/TextEditor/constants.d.ts +135 -0
  48. package/es/components/organism/TextEditor/constants.js +280 -0
  49. package/es/components/organism/TextEditor/extensions/BackgroundColor.d.ts +25 -0
  50. package/es/components/organism/TextEditor/extensions/BackgroundColor.js +46 -0
  51. package/es/components/organism/TextEditor/extensions/BubbleMenu/bubble-menu-plugin.d.ts +130 -0
  52. package/es/components/organism/TextEditor/extensions/BubbleMenu/bubble-menu-plugin.js +247 -0
  53. package/es/components/organism/TextEditor/extensions/BubbleMenu/bubble-menu.d.ts +15 -0
  54. package/es/components/organism/TextEditor/extensions/BubbleMenu/bubble-menu.js +31 -0
  55. package/es/components/organism/TextEditor/extensions/BubbleMenu/index.d.ts +2 -0
  56. package/es/components/organism/TextEditor/extensions/BubbleMenu/index.js +2 -0
  57. package/es/components/organism/TextEditor/extensions/Color.d.ts +6 -0
  58. package/es/components/organism/TextEditor/extensions/Color.js +41 -0
  59. package/es/components/organism/TextEditor/extensions/Emoji.d.ts +57 -0
  60. package/es/components/organism/TextEditor/extensions/Emoji.js +184 -0
  61. package/es/components/organism/TextEditor/extensions/FontFamily.d.ts +6 -0
  62. package/es/components/organism/TextEditor/extensions/FontFamily.js +43 -0
  63. package/es/components/organism/TextEditor/extensions/FontSize.d.ts +32 -0
  64. package/es/components/organism/TextEditor/extensions/FontSize.js +47 -0
  65. package/es/components/organism/TextEditor/extensions/FontWeight.d.ts +23 -0
  66. package/es/components/organism/TextEditor/extensions/FontWeight.js +41 -0
  67. package/es/components/organism/TextEditor/extensions/Highlight.d.ts +1 -0
  68. package/es/components/organism/TextEditor/extensions/Highlight.js +14 -0
  69. package/es/components/organism/TextEditor/extensions/Indent.d.ts +28 -0
  70. package/es/components/organism/TextEditor/extensions/Indent.js +68 -0
  71. package/es/components/organism/TextEditor/extensions/LineHeight.d.ts +20 -0
  72. package/es/components/organism/TextEditor/extensions/LineHeight.js +36 -0
  73. package/es/components/organism/TextEditor/extensions/Link.d.ts +15 -0
  74. package/es/components/organism/TextEditor/extensions/Link.js +50 -0
  75. package/es/components/organism/TextEditor/extensions/ListItemMarker.d.ts +13 -0
  76. package/es/components/organism/TextEditor/extensions/ListItemMarker.js +174 -0
  77. package/es/components/organism/TextEditor/extensions/Selection.d.ts +6 -0
  78. package/es/components/organism/TextEditor/extensions/Selection.js +40 -0
  79. package/es/components/organism/TextEditor/extensions/SmartTag.d.ts +39 -0
  80. package/es/components/organism/TextEditor/extensions/SmartTag.js +167 -0
  81. package/es/components/organism/TextEditor/extensions/StyleMemory.d.ts +36 -0
  82. package/es/components/organism/TextEditor/extensions/StyleMemory.js +163 -0
  83. package/es/components/organism/TextEditor/extensions/TextTransform.d.ts +31 -0
  84. package/es/components/organism/TextEditor/extensions/TextTransform.js +37 -0
  85. package/es/components/organism/TextEditor/hooks/index.d.ts +6 -0
  86. package/es/components/organism/TextEditor/hooks/index.js +6 -0
  87. package/es/components/organism/TextEditor/hooks/useDocumentState.d.ts +18 -0
  88. package/es/components/organism/TextEditor/hooks/useDocumentState.js +42 -0
  89. package/es/components/organism/TextEditor/hooks/useLinkHandler.d.ts +10 -0
  90. package/es/components/organism/TextEditor/hooks/useLinkHandler.js +223 -0
  91. package/es/components/organism/TextEditor/hooks/useMarkTracking.d.ts +26 -0
  92. package/es/components/organism/TextEditor/hooks/useMarkTracking.js +68 -0
  93. package/es/components/organism/TextEditor/hooks/usePersistence.d.ts +31 -0
  94. package/es/components/organism/TextEditor/hooks/usePersistence.js +169 -0
  95. package/es/components/organism/TextEditor/hooks/useStyleMemory.d.ts +6 -0
  96. package/es/components/organism/TextEditor/hooks/useStyleMemory.js +42 -0
  97. package/es/components/organism/TextEditor/hooks/useStylePresets.d.ts +34 -0
  98. package/es/components/organism/TextEditor/hooks/useStylePresets.js +83 -0
  99. package/es/components/organism/TextEditor/index.d.ts +14 -0
  100. package/es/components/organism/TextEditor/index.js +6 -0
  101. package/es/components/organism/TextEditor/index.scss +61 -0
  102. package/es/components/organism/TextEditor/provider.d.ts +10 -0
  103. package/es/components/organism/TextEditor/provider.js +20 -0
  104. package/es/components/organism/TextEditor/store.d.ts +11 -0
  105. package/es/components/organism/TextEditor/store.js +12 -0
  106. package/es/components/organism/TextEditor/styled.d.ts +8 -0
  107. package/es/components/organism/TextEditor/styled.js +90 -0
  108. package/es/components/organism/TextEditor/types.d.ts +92 -0
  109. package/es/components/organism/TextEditor/types.js +1 -0
  110. package/es/components/organism/TextEditor/ui/BubbleMenu/BubbleMenu.d.ts +6 -0
  111. package/es/components/organism/TextEditor/ui/BubbleMenu/BubbleMenu.js +78 -0
  112. package/es/components/organism/TextEditor/ui/BubbleMenu/index.d.ts +1 -0
  113. package/es/components/organism/TextEditor/ui/BubbleMenu/index.js +1 -0
  114. package/es/components/organism/TextEditor/ui/ColorPicker/ColorPicker.d.ts +43 -0
  115. package/es/components/organism/TextEditor/ui/ColorPicker/ColorPicker.js +120 -0
  116. package/es/components/organism/TextEditor/ui/ColorPicker/index.d.ts +1 -0
  117. package/es/components/organism/TextEditor/ui/ColorPicker/index.js +1 -0
  118. package/es/components/organism/TextEditor/ui/Emoji/EmojiList.d.ts +11 -0
  119. package/es/components/organism/TextEditor/ui/Emoji/EmojiList.js +66 -0
  120. package/es/components/organism/TextEditor/ui/Emoji/index.d.ts +2 -0
  121. package/es/components/organism/TextEditor/ui/Emoji/index.js +2 -0
  122. package/es/components/organism/TextEditor/ui/Emoji/suggestion.d.ts +4 -0
  123. package/es/components/organism/TextEditor/ui/Emoji/suggestion.js +71 -0
  124. package/es/components/organism/TextEditor/ui/FontPopover/FontPopover.d.ts +12 -0
  125. package/es/components/organism/TextEditor/ui/FontPopover/FontPopover.js +69 -0
  126. package/es/components/organism/TextEditor/ui/FontPopover/styled.d.ts +1 -0
  127. package/es/components/organism/TextEditor/ui/FontPopover/styled.js +20 -0
  128. package/es/components/organism/TextEditor/ui/Popover/Popover.d.ts +6 -0
  129. package/es/components/organism/TextEditor/ui/Popover/Popover.js +7 -0
  130. package/es/components/organism/TextEditor/ui/Popover/index.d.ts +1 -0
  131. package/es/components/organism/TextEditor/ui/Popover/index.js +1 -0
  132. package/es/components/organism/TextEditor/ui/Select/Select.d.ts +4 -0
  133. package/es/components/organism/TextEditor/ui/Select/Select.js +7 -0
  134. package/es/components/organism/TextEditor/ui/Select/index.d.ts +1 -0
  135. package/es/components/organism/TextEditor/ui/Select/index.js +1 -0
  136. package/es/components/organism/TextEditor/ui/TextAlignSelect/TextAlignSelect.d.ts +30 -0
  137. package/es/components/organism/TextEditor/ui/TextAlignSelect/TextAlignSelect.js +49 -0
  138. package/es/components/organism/TextEditor/ui/TextAlignSelect/index.d.ts +1 -0
  139. package/es/components/organism/TextEditor/ui/TextAlignSelect/index.js +1 -0
  140. package/es/components/organism/TextEditor/ui/Toolbar/Toolbar.d.ts +14 -0
  141. package/es/components/organism/TextEditor/ui/Toolbar/Toolbar.js +42 -0
  142. package/es/components/organism/TextEditor/ui/Toolbar/actions/BoldAction.d.ts +5 -0
  143. package/es/components/organism/TextEditor/ui/Toolbar/actions/BoldAction.js +7 -0
  144. package/es/components/organism/TextEditor/ui/Toolbar/actions/BulletListAction.d.ts +5 -0
  145. package/es/components/organism/TextEditor/ui/Toolbar/actions/BulletListAction.js +7 -0
  146. package/es/components/organism/TextEditor/ui/Toolbar/actions/ClearFormattingAction.d.ts +5 -0
  147. package/es/components/organism/TextEditor/ui/Toolbar/actions/ClearFormattingAction.js +18 -0
  148. package/es/components/organism/TextEditor/ui/Toolbar/actions/EmojiAction.d.ts +4 -0
  149. package/es/components/organism/TextEditor/ui/Toolbar/actions/EmojiAction.js +13 -0
  150. package/es/components/organism/TextEditor/ui/Toolbar/actions/FontFamilyAction.d.ts +7 -0
  151. package/es/components/organism/TextEditor/ui/Toolbar/actions/FontFamilyAction.js +18 -0
  152. package/es/components/organism/TextEditor/ui/Toolbar/actions/FontSizeAction.d.ts +7 -0
  153. package/es/components/organism/TextEditor/ui/Toolbar/actions/FontSizeAction.js +37 -0
  154. package/es/components/organism/TextEditor/ui/Toolbar/actions/HighlightAction.d.ts +5 -0
  155. package/es/components/organism/TextEditor/ui/Toolbar/actions/HighlightAction.js +7 -0
  156. package/es/components/organism/TextEditor/ui/Toolbar/actions/IndentAction.d.ts +5 -0
  157. package/es/components/organism/TextEditor/ui/Toolbar/actions/IndentAction.js +7 -0
  158. package/es/components/organism/TextEditor/ui/Toolbar/actions/ItalicAction.d.ts +5 -0
  159. package/es/components/organism/TextEditor/ui/Toolbar/actions/ItalicAction.js +7 -0
  160. package/es/components/organism/TextEditor/ui/Toolbar/actions/LinkAction.d.ts +6 -0
  161. package/es/components/organism/TextEditor/ui/Toolbar/actions/LinkAction.js +4 -0
  162. package/es/components/organism/TextEditor/ui/Toolbar/actions/OrderedListAction.d.ts +5 -0
  163. package/es/components/organism/TextEditor/ui/Toolbar/actions/OrderedListAction.js +7 -0
  164. package/es/components/organism/TextEditor/ui/Toolbar/actions/OutdentAction.d.ts +5 -0
  165. package/es/components/organism/TextEditor/ui/Toolbar/actions/OutdentAction.js +7 -0
  166. package/es/components/organism/TextEditor/ui/Toolbar/actions/SmartTagAction.d.ts +7 -0
  167. package/es/components/organism/TextEditor/ui/Toolbar/actions/SmartTagAction.js +9 -0
  168. package/es/components/organism/TextEditor/ui/Toolbar/actions/SpacingAction.d.ts +9 -0
  169. package/es/components/organism/TextEditor/ui/Toolbar/actions/SpacingAction.js +22 -0
  170. package/es/components/organism/TextEditor/ui/Toolbar/actions/StrikeAction.d.ts +5 -0
  171. package/es/components/organism/TextEditor/ui/Toolbar/actions/StrikeAction.js +7 -0
  172. package/es/components/organism/TextEditor/ui/Toolbar/actions/SubscriptAction.d.ts +5 -0
  173. package/es/components/organism/TextEditor/ui/Toolbar/actions/SubscriptAction.js +13 -0
  174. package/es/components/organism/TextEditor/ui/Toolbar/actions/SuperscriptAction.d.ts +5 -0
  175. package/es/components/organism/TextEditor/ui/Toolbar/actions/SuperscriptAction.js +13 -0
  176. package/es/components/organism/TextEditor/ui/Toolbar/actions/TextAlignAction.d.ts +5 -0
  177. package/es/components/organism/TextEditor/ui/Toolbar/actions/TextAlignAction.js +3 -0
  178. package/es/components/organism/TextEditor/ui/Toolbar/actions/TextBackgroundColorAction.d.ts +7 -0
  179. package/es/components/organism/TextEditor/ui/Toolbar/actions/TextBackgroundColorAction.js +19 -0
  180. package/es/components/organism/TextEditor/ui/Toolbar/actions/TextColorAction.d.ts +15 -0
  181. package/es/components/organism/TextEditor/ui/Toolbar/actions/TextColorAction.js +14 -0
  182. package/es/components/organism/TextEditor/ui/Toolbar/actions/TextTransformAction.d.ts +5 -0
  183. package/es/components/organism/TextEditor/ui/Toolbar/actions/TextTransformAction.js +30 -0
  184. package/es/components/organism/TextEditor/ui/Toolbar/actions/UnderlineAction.d.ts +5 -0
  185. package/es/components/organism/TextEditor/ui/Toolbar/actions/UnderlineAction.js +5 -0
  186. package/es/components/organism/TextEditor/ui/Toolbar/actions/UnsetLink.d.ts +6 -0
  187. package/es/components/organism/TextEditor/ui/Toolbar/actions/UnsetLink.js +10 -0
  188. package/es/components/organism/TextEditor/ui/Toolbar/actions/index.d.ts +20 -0
  189. package/es/components/organism/TextEditor/ui/Toolbar/actions/index.js +20 -0
  190. package/es/components/organism/TextEditor/ui/Toolbar/index.d.ts +1 -0
  191. package/es/components/organism/TextEditor/ui/Toolbar/index.js +1 -0
  192. package/es/components/organism/TextEditor/utils/documentState.d.ts +57 -0
  193. package/es/components/organism/TextEditor/utils/documentState.js +100 -0
  194. package/es/components/organism/TextEditor/utils/font.d.ts +84 -0
  195. package/es/components/organism/TextEditor/utils/font.js +175 -0
  196. package/es/components/organism/TextEditor/utils/htmlProcessing.d.ts +63 -0
  197. package/es/components/organism/TextEditor/utils/htmlProcessing.js +321 -0
  198. package/es/components/organism/TextEditor/utils/index.d.ts +8 -0
  199. package/es/components/organism/TextEditor/utils/index.js +16 -0
  200. package/es/components/organism/TextEditor/utils/link.d.ts +100 -0
  201. package/es/components/organism/TextEditor/utils/link.js +149 -0
  202. package/es/components/organism/TextEditor/utils/menu.d.ts +134 -0
  203. package/es/components/organism/TextEditor/utils/menu.js +317 -0
  204. package/es/components/organism/TextEditor/utils/selection.d.ts +25 -0
  205. package/es/components/organism/TextEditor/utils/selection.js +57 -0
  206. package/es/components/organism/TextEditor/utils/smartTag.d.ts +49 -0
  207. package/es/components/organism/TextEditor/utils/smartTag.js +89 -0
  208. package/es/components/organism/TextEditor/utils/style.d.ts +78 -0
  209. package/es/components/organism/TextEditor/utils/style.js +193 -0
  210. package/es/components/organism/index.d.ts +1 -0
  211. package/es/components/organism/index.js +1 -0
  212. package/es/components/organism/index.scss +1 -0
  213. package/es/config/index.d.ts +1 -0
  214. package/es/config/index.js +1 -0
  215. package/es/constants/api.d.ts +10 -0
  216. package/es/constants/api.js +10 -0
  217. package/es/hooks/index.d.ts +1 -0
  218. package/es/hooks/index.js +1 -0
  219. package/es/hooks/useBroadcastedLocalStorage.d.ts +5 -0
  220. package/es/hooks/useBroadcastedLocalStorage.js +71 -0
  221. package/es/hooks/useElementSize.d.ts +7 -0
  222. package/es/hooks/useElementSize.js +56 -0
  223. package/es/utils/common.d.ts +6 -9
  224. package/es/utils/common.js +44 -23
  225. package/es/utils/index.d.ts +1 -0
  226. package/es/utils/index.js +1 -0
  227. package/es/utils/tree.d.ts +225 -0
  228. package/es/utils/tree.js +469 -0
  229. package/es/utils/web.d.ts +4 -0
  230. package/es/utils/web.js +25 -0
  231. package/package.json +29 -3
@@ -0,0 +1,175 @@
1
+ import { isMacOS } from '@tiptap/core';
2
+ /**
3
+ * Gets the appropriate bold font weight for a given font family
4
+ * @param currentFontFamily The font family to find bold weight for
5
+ * @param fonts Array of available font configurations
6
+ * @param minBoldWeight Minimum weight considered bold (default 700)
7
+ * @returns The first available bold weight for the font family, or minBoldWeight if none found
8
+ */
9
+ export const getBoldFontWeight = (currentFontFamily, fonts, minBoldWeight = 700) => {
10
+ if (!currentFontFamily || !fonts?.length)
11
+ return minBoldWeight;
12
+ const fontConfig = fonts.find(font => font.fontFamily.name === currentFontFamily);
13
+ return fontConfig?.fontWeight.find(weight => weight >= minBoldWeight) ?? minBoldWeight;
14
+ };
15
+ /**
16
+ * Gets the modifier key based on the platform
17
+ * @returns Platform-appropriate modifier key
18
+ */
19
+ export const getModifierKey = () => (isMacOS() ? '⌘' : 'Ctrl');
20
+ /**
21
+ * Formats a hotkey string with the appropriate modifier
22
+ * @param key The key to format
23
+ * @returns Formatted hotkey string
24
+ */
25
+ export const formatHotkey = (key) => {
26
+ const modifier = getModifierKey();
27
+ return `${modifier}+${key}`;
28
+ };
29
+ /**
30
+ * Validates if a font family name is a generic CSS font
31
+ * @param fontFamily Font family name to check
32
+ * @returns true if it's a generic font family
33
+ */
34
+ export function isGenericFontFamily(fontFamily) {
35
+ const genericFamilies = new Set([
36
+ 'serif',
37
+ 'sans-serif',
38
+ 'monospace',
39
+ 'cursive',
40
+ 'fantasy',
41
+ 'system-ui',
42
+ 'ui-serif',
43
+ 'ui-sans-serif',
44
+ 'ui-monospace',
45
+ 'ui-rounded',
46
+ 'math',
47
+ 'emoji',
48
+ 'fangsong',
49
+ ]);
50
+ return genericFamilies.has(fontFamily.toLowerCase().trim());
51
+ }
52
+ /**
53
+ * Extracts the primary font from a font-family string
54
+ * @param fontFamily Font family string (may contain fallbacks)
55
+ * @returns Primary font name
56
+ */
57
+ export function getPrimaryFontFamily(fontFamily) {
58
+ if (!fontFamily)
59
+ return '';
60
+ const fonts = fontFamily.split(',');
61
+ const primaryFont = fonts[0].trim();
62
+ // Remove quotes if present
63
+ return primaryFont.replace(/^["']|["']$/g, '');
64
+ }
65
+ /**
66
+ * Checks if a font weight is considered bold
67
+ * @param weight Font weight to check
68
+ * @param threshold Bold threshold (default 600)
69
+ * @returns true if weight is bold
70
+ */
71
+ export function isBoldWeight(weight, threshold = 600) {
72
+ const numericWeight = typeof weight === 'string' ? parseInt(weight, 10) : weight;
73
+ return !isNaN(numericWeight) && numericWeight >= threshold;
74
+ }
75
+ /**
76
+ * Gets all available font weights for a font family
77
+ * @param fontFamily Font family name
78
+ * @param fonts Array of font configurations
79
+ * @returns Array of available weights
80
+ */
81
+ export function getFontWeights(fontFamily, fonts) {
82
+ const fontConfig = fonts.find(font => font.fontFamily.name === fontFamily);
83
+ return fontConfig?.fontWeight || [400];
84
+ }
85
+ /**
86
+ * Finds the closest available font weight
87
+ * @param targetWeight Desired font weight
88
+ * @param availableWeights Array of available weights
89
+ * @returns Closest available weight
90
+ */
91
+ export function getClosestFontWeight(targetWeight, availableWeights) {
92
+ if (availableWeights.includes(targetWeight)) {
93
+ return targetWeight;
94
+ }
95
+ return availableWeights.reduce((closest, weight) => Math.abs(weight - targetWeight) < Math.abs(closest - targetWeight) ? weight : closest);
96
+ }
97
+ /**
98
+ * Validates font configuration
99
+ * @param fontConfig Font configuration to validate
100
+ * @returns true if configuration is valid
101
+ */
102
+ export function isValidFontConfig(fontConfig) {
103
+ return !!(fontConfig.fontFamily?.name &&
104
+ fontConfig.fontWeight &&
105
+ Array.isArray(fontConfig.fontWeight) &&
106
+ fontConfig.fontWeight.length > 0 &&
107
+ fontConfig.fontWeight.every(weight => typeof weight === 'number' && weight > 0));
108
+ }
109
+ /**
110
+ * Sorts font configurations alphabetically by name
111
+ * @param fonts Array of font configurations
112
+ * @returns Sorted array of font configurations
113
+ */
114
+ export function sortFontsByName(fonts) {
115
+ return [...fonts].sort((a, b) => a.fontFamily.name.localeCompare(b.fontFamily.name));
116
+ }
117
+ /**
118
+ * Groups fonts by category (if category property exists)
119
+ * @param fonts Array of font configurations
120
+ * @returns Object with fonts grouped by category
121
+ */
122
+ export function groupFontsByCategory(fonts) {
123
+ const grouped = {};
124
+ fonts.forEach(font => {
125
+ const category = font.category || 'Other';
126
+ if (!grouped[category]) {
127
+ grouped[category] = [];
128
+ }
129
+ grouped[category].push(font);
130
+ });
131
+ return grouped;
132
+ }
133
+ /**
134
+ * Checks if a font is web safe
135
+ * @param fontFamily Font family name
136
+ * @returns true if font is web safe
137
+ */
138
+ export function isWebSafeFont(fontFamily) {
139
+ const webSafeFonts = new Set([
140
+ 'arial',
141
+ 'helvetica',
142
+ 'times new roman',
143
+ 'times',
144
+ 'courier new',
145
+ 'courier',
146
+ 'verdana',
147
+ 'georgia',
148
+ 'palatino',
149
+ 'garamond',
150
+ 'bookman',
151
+ 'comic sans ms',
152
+ 'trebuchet ms',
153
+ 'arial black',
154
+ 'impact',
155
+ 'lucida sans unicode',
156
+ 'tahoma',
157
+ 'lucida console',
158
+ ]);
159
+ return webSafeFonts.has(fontFamily.toLowerCase().trim());
160
+ }
161
+ /**
162
+ * Creates a font stack with appropriate fallbacks
163
+ * @param primaryFont Primary font family
164
+ * @param category Font category for fallback selection
165
+ * @returns Complete font stack string
166
+ */
167
+ export function createFontStack(primaryFont, category = 'sans-serif') {
168
+ const fallbacks = {
169
+ serif: ['Georgia', 'Times New Roman', 'Times', 'serif'],
170
+ 'sans-serif': ['Arial', 'Helvetica', 'sans-serif'],
171
+ monospace: ['Courier New', 'Courier', 'monospace'],
172
+ };
173
+ const stack = [primaryFont, ...fallbacks[category]];
174
+ return stack.join(', ');
175
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Restructures dynamic tags from Froala editor format to be compatible with Tiptap editor.
3
+ * This function preserves styling and attributes of dynamic tags while cleaning up their structure.
4
+ *
5
+ * @param html - The HTML string containing dynamic tags
6
+ * @param options - Configuration options for the restructuring process
7
+ * @returns The restructured HTML string
8
+ */
9
+ export declare function restructureDynamicTagsWithOptions(html: string, options?: {
10
+ attributesToClone: string[];
11
+ }): string;
12
+ /**
13
+ * Safely parses and processes HTML content for editor use
14
+ * @param html - HTML string to process
15
+ * @returns Processed HTML string
16
+ */
17
+ export declare function safeParseHTMLContent(html: string): string;
18
+ /**
19
+ * Sanitizes HTML by removing potentially dangerous elements and attributes
20
+ * @param html - HTML string to sanitize
21
+ * @returns Sanitized HTML string
22
+ */
23
+ export declare function sanitizeHTML(html: string): string;
24
+ /**
25
+ * Extracts text content from HTML
26
+ * @param html - HTML string
27
+ * @returns Plain text content
28
+ */
29
+ export declare function extractTextFromHTML(html: string): string;
30
+ /**
31
+ * Counts words in HTML content
32
+ * @param html - HTML string
33
+ * @returns Word count
34
+ */
35
+ export declare function countWordsInHTML(html: string): number;
36
+ /**
37
+ * Counts characters in HTML content
38
+ * @param html - HTML string
39
+ * @param includeSpaces - Whether to include spaces in count
40
+ * @returns Character count
41
+ */
42
+ export declare function countCharactersInHTML(html: string, includeSpaces?: boolean): number;
43
+ /**
44
+ * Wraps text nodes with specified tag
45
+ * @param html - HTML string
46
+ * @param tagName - Tag name to wrap with
47
+ * @param className - Optional class name for wrapper
48
+ * @returns HTML with wrapped text nodes
49
+ */
50
+ export declare function wrapTextNodes(html: string, tagName?: string, className?: string): string;
51
+ /**
52
+ * Removes empty elements from HTML
53
+ * @param html - HTML string
54
+ * @returns HTML with empty elements removed
55
+ */
56
+ export declare function removeEmptyElements(html: string): string;
57
+ /**
58
+ * Normalizes whitespace in HTML
59
+ * @param html - HTML string
60
+ * @returns HTML with normalized whitespace
61
+ */
62
+ export declare function normalizeWhitespace(html: string): string;
63
+ export declare const htmlMinifyForEmail: (htmlEditorContent: string) => string;
@@ -0,0 +1,321 @@
1
+ import { HTML_DOM } from '../__mocks__/text-contennt';
2
+ import { SMART_TAG_HIGHLIGHT_BG } from '../constants';
3
+ import { textStyleFromElStyle, appendTextStyleToEl } from './style';
4
+ import tinycolor from 'tinycolor2';
5
+ /**
6
+ * Creates a clean span element for a dynamic tag with only the essential attributes
7
+ *
8
+ * @param doc - The document used to create the new element
9
+ * @param originalSpan - The original dynamic tag span element
10
+ * @param attributesToPreserve - List of attribute names to copy from the original span
11
+ * @returns A new span element with preserved attributes
12
+ */
13
+ function createCleanDynamicSpan(doc, originalSpan, attributesToPreserve) {
14
+ const cleanSpan = doc.createElement('span');
15
+ // Preserve only the specified attributes
16
+ for (const attrName of attributesToPreserve) {
17
+ if (originalSpan.hasAttribute(attrName)) {
18
+ cleanSpan.setAttribute(attrName, originalSpan.getAttribute(attrName));
19
+ }
20
+ }
21
+ // Preserve the text content
22
+ cleanSpan.textContent = originalSpan.textContent?.trim() || '';
23
+ return cleanSpan;
24
+ }
25
+ /**
26
+ * Extracts style wrapper elements that need to be preserved from the original dynamic tag
27
+ *
28
+ * @param doc - The document containing the dynamic tag
29
+ * @param html - The original HTML string
30
+ * @param dynamicSpan - The original dynamic tag span element
31
+ * @returns Array of wrapper elements that provide styling
32
+ */
33
+ function extractStyleWrappers(doc, html, dynamicSpan) {
34
+ const styleWrappers = [];
35
+ // Create a temporary container for style computation
36
+ const tempStyleContainer = document.createElement('div');
37
+ tempStyleContainer.style.display = 'none';
38
+ document.body.appendChild(tempStyleContainer);
39
+ try {
40
+ // Extract computed styles from the original element
41
+ if (doc.body.firstElementChild) {
42
+ const tempDoc = new DOMParser().parseFromString(html, 'text/html');
43
+ if (tempDoc.body.firstElementChild) {
44
+ tempStyleContainer.appendChild(tempDoc.body.firstElementChild);
45
+ const originalDynamicElement = tempStyleContainer.querySelector(`span[data-dynamic-id="${dynamicSpan.dataset.dynamicId}"]`);
46
+ if (originalDynamicElement) {
47
+ // Create a span with the computed text styles
48
+ const computedTextStyle = textStyleFromElStyle(window.getComputedStyle(originalDynamicElement));
49
+ // Remove background color if it matches the highlight color
50
+ if (tinycolor.equals(computedTextStyle.backgroundColor, SMART_TAG_HIGHLIGHT_BG)) {
51
+ computedTextStyle.backgroundColor = '';
52
+ }
53
+ const textStyleWrapper = document.createElement('span');
54
+ appendTextStyleToEl(textStyleWrapper, computedTextStyle);
55
+ styleWrappers.push(textStyleWrapper);
56
+ }
57
+ }
58
+ }
59
+ // Extract nested style wrappers
60
+ let nestedElement = dynamicSpan.firstElementChild;
61
+ while (nestedElement && nestedElement.children.length <= 1) {
62
+ styleWrappers.push(nestedElement);
63
+ nestedElement = nestedElement.firstElementChild || null;
64
+ }
65
+ return styleWrappers;
66
+ }
67
+ finally {
68
+ // Clean up the temporary container
69
+ document.body.removeChild(tempStyleContainer);
70
+ }
71
+ }
72
+ /**
73
+ * Reconstructs the dynamic tag element hierarchy with preserved style wrappers
74
+ *
75
+ * @param doc - The document used to create new elements
76
+ * @param baseSpan - The clean base span element for the dynamic tag
77
+ * @param styleWrappers - Array of style wrapper elements to apply
78
+ * @returns The reconstructed dynamic tag with preserved styling
79
+ */
80
+ function reconstructDynamicTagHierarchy(doc, baseSpan, styleWrappers) {
81
+ let resultNode = baseSpan;
82
+ // Apply style wrappers from innermost to outermost
83
+ styleWrappers.reverse().forEach(originalWrapper => {
84
+ const wrapperClone = doc.createElement(originalWrapper.tagName.toLowerCase());
85
+ // Clone all attributes from the original wrapper
86
+ for (let i = 0; i < originalWrapper.attributes.length; i++) {
87
+ const { name, value } = originalWrapper.attributes[i];
88
+ wrapperClone.setAttribute(name, value);
89
+ }
90
+ wrapperClone.appendChild(resultNode);
91
+ resultNode = wrapperClone;
92
+ });
93
+ return resultNode;
94
+ }
95
+ /**
96
+ * Restructures dynamic tags from Froala editor format to be compatible with Tiptap editor.
97
+ * This function preserves styling and attributes of dynamic tags while cleaning up their structure.
98
+ *
99
+ * @param html - The HTML string containing dynamic tags
100
+ * @param options - Configuration options for the restructuring process
101
+ * @returns The restructured HTML string
102
+ */
103
+ export function restructureDynamicTagsWithOptions(html, options = {
104
+ attributesToClone: [
105
+ 'class',
106
+ 'id',
107
+ 'style',
108
+ 'data-dynamic',
109
+ 'data-dynamic-id',
110
+ 'direction',
111
+ 'unicode-bidi',
112
+ 'text-align',
113
+ 'background-color',
114
+ 'color',
115
+ ],
116
+ }) {
117
+ // Parse the HTML string into a DOM
118
+ const parser = new DOMParser();
119
+ const parsedDoc = parser.parseFromString(html, 'text/html');
120
+ // Find all dynamic tag spans
121
+ const dynamicTagSpans = parsedDoc.querySelectorAll('span[data-dynamic]');
122
+ // Process each dynamic span
123
+ dynamicTagSpans.forEach(originalDynamicSpan => {
124
+ // Step 1: Create a new clean span with essential attributes
125
+ const cleanDynamicSpan = createCleanDynamicSpan(parsedDoc, originalDynamicSpan, options.attributesToClone);
126
+ // Step 2: Extract style wrappers that need to be preserved
127
+ const styleWrappers = extractStyleWrappers(parsedDoc, html, originalDynamicSpan);
128
+ // Step 3: Reconstruct the element hierarchy with preserved styles
129
+ const restructuredDynamicTag = reconstructDynamicTagHierarchy(parsedDoc, cleanDynamicSpan, styleWrappers);
130
+ // Step 4: Replace the original span with the restructured node
131
+ originalDynamicSpan.replaceWith(restructuredDynamicTag);
132
+ });
133
+ return parsedDoc.body.innerHTML;
134
+ }
135
+ /**
136
+ * Converts inherited text styles to computed styles for span elements in HTML content.
137
+ * This function processes span elements to ensure text styles are explicitly set rather than inherited.
138
+ *
139
+ * @param html - The HTML string to process
140
+ * @returns The processed HTML string with computed styles applied
141
+ */
142
+ const inheritStyleToComputedStyle = (html) => {
143
+ try {
144
+ // Create a new DOM parser and parse the HTML
145
+ const parser = new DOMParser();
146
+ const doc = parser.parseFromString(html, 'text/html');
147
+ if (!doc.body) {
148
+ // eslint-disable-next-line no-console
149
+ console.warn('Failed to parse HTML: body not found');
150
+ return html;
151
+ }
152
+ // Create a hidden container
153
+ const container = document.createElement('div');
154
+ container.style.visibility = 'hidden';
155
+ container.innerHTML = doc.body.innerHTML;
156
+ // Add container to DOM temporarily to compute styles
157
+ document.body.appendChild(container);
158
+ // Process all span elements
159
+ const spanElements = container.querySelectorAll('span');
160
+ spanElements.forEach(span => {
161
+ const textStyle = textStyleFromElStyle(span.style);
162
+ const computedStyle = window.getComputedStyle(span);
163
+ // Only update styles if there are inherited values
164
+ const shouldUpdateStyle = Object.values(textStyle).some(value => value === 'inherit');
165
+ if (!shouldUpdateStyle) {
166
+ return;
167
+ }
168
+ // Update inherited styles with computed values
169
+ Object.entries(textStyle).forEach(([key, value]) => {
170
+ if (value === 'inherit' && key in span.style) {
171
+ span.style[key] = computedStyle[key];
172
+ }
173
+ });
174
+ });
175
+ const resultHTML = container.innerHTML;
176
+ // Clean up
177
+ container.remove();
178
+ return resultHTML;
179
+ }
180
+ catch (error) {
181
+ // eslint-disable-next-line no-console
182
+ console.error('Error processing styles:', error);
183
+ return html; // Return original HTML in case of error
184
+ }
185
+ };
186
+ /**
187
+ * Safely parses and processes HTML content for editor use
188
+ * @param html - HTML string to process
189
+ * @returns Processed HTML string
190
+ */
191
+ export function safeParseHTMLContent(html) {
192
+ let resultHTML = html;
193
+ const isFroala = html.includes('fr-box');
194
+ if (isFroala) {
195
+ // console.log('safeParseHTMLContent', html);
196
+ resultHTML = inheritStyleToComputedStyle(html);
197
+ // console.log('after inheritStyleToComputedStyle', resultHTML);
198
+ resultHTML = restructureDynamicTagsWithOptions(resultHTML);
199
+ // console.log('after restructureDynamicTagsWithOptions', resultHTML);
200
+ }
201
+ return resultHTML;
202
+ }
203
+ /**
204
+ * Sanitizes HTML by removing potentially dangerous elements and attributes
205
+ * @param html - HTML string to sanitize
206
+ * @returns Sanitized HTML string
207
+ */
208
+ export function sanitizeHTML(html) {
209
+ const parser = new DOMParser();
210
+ const doc = parser.parseFromString(html, 'text/html');
211
+ // Remove script tags
212
+ const scripts = doc.querySelectorAll('script');
213
+ scripts.forEach(script => script.remove());
214
+ // Remove on* event attributes
215
+ const allElements = doc.querySelectorAll('*');
216
+ allElements.forEach(element => {
217
+ Array.from(element.attributes).forEach(attr => {
218
+ if (attr.name.startsWith('on')) {
219
+ element.removeAttribute(attr.name);
220
+ }
221
+ });
222
+ });
223
+ return doc.body.innerHTML;
224
+ }
225
+ /**
226
+ * Extracts text content from HTML
227
+ * @param html - HTML string
228
+ * @returns Plain text content
229
+ */
230
+ export function extractTextFromHTML(html) {
231
+ const parser = new DOMParser();
232
+ const doc = parser.parseFromString(html, 'text/html');
233
+ return doc.body.textContent || '';
234
+ }
235
+ /**
236
+ * Counts words in HTML content
237
+ * @param html - HTML string
238
+ * @returns Word count
239
+ */
240
+ export function countWordsInHTML(html) {
241
+ const text = extractTextFromHTML(html);
242
+ return text
243
+ .trim()
244
+ .split(/\s+/)
245
+ .filter(word => word.length > 0).length;
246
+ }
247
+ /**
248
+ * Counts characters in HTML content
249
+ * @param html - HTML string
250
+ * @param includeSpaces - Whether to include spaces in count
251
+ * @returns Character count
252
+ */
253
+ export function countCharactersInHTML(html, includeSpaces = true) {
254
+ const text = extractTextFromHTML(html);
255
+ return includeSpaces ? text.length : text.replace(/\s/g, '').length;
256
+ }
257
+ /**
258
+ * Wraps text nodes with specified tag
259
+ * @param html - HTML string
260
+ * @param tagName - Tag name to wrap with
261
+ * @param className - Optional class name for wrapper
262
+ * @returns HTML with wrapped text nodes
263
+ */
264
+ export function wrapTextNodes(html, tagName = 'span', className) {
265
+ const parser = new DOMParser();
266
+ const doc = parser.parseFromString(html, 'text/html');
267
+ function wrapTextNodesRecursive(node) {
268
+ if (node.nodeType === Node.TEXT_NODE && node.textContent?.trim()) {
269
+ const wrapper = doc.createElement(tagName);
270
+ if (className) {
271
+ wrapper.className = className;
272
+ }
273
+ wrapper.textContent = node.textContent;
274
+ node.parentNode?.replaceChild(wrapper, node);
275
+ }
276
+ else {
277
+ Array.from(node.childNodes).forEach(wrapTextNodesRecursive);
278
+ }
279
+ }
280
+ wrapTextNodesRecursive(doc.body);
281
+ return doc.body.innerHTML;
282
+ }
283
+ /**
284
+ * Removes empty elements from HTML
285
+ * @param html - HTML string
286
+ * @returns HTML with empty elements removed
287
+ */
288
+ export function removeEmptyElements(html) {
289
+ const parser = new DOMParser();
290
+ const doc = parser.parseFromString(html, 'text/html');
291
+ function removeEmptyRecursive(node) {
292
+ Array.from(node.children).forEach(child => {
293
+ removeEmptyRecursive(child);
294
+ if (!child.textContent?.trim() && child.children.length === 0) {
295
+ child.remove();
296
+ }
297
+ });
298
+ }
299
+ removeEmptyRecursive(doc.body);
300
+ return doc.body.innerHTML;
301
+ }
302
+ /**
303
+ * Normalizes whitespace in HTML
304
+ * @param html - HTML string
305
+ * @returns HTML with normalized whitespace
306
+ */
307
+ export function normalizeWhitespace(html) {
308
+ return html.replace(/\s+/g, ' ').replace(/>\s+</g, '><').trim();
309
+ }
310
+ export const htmlMinifyForEmail = (htmlEditorContent) => {
311
+ const parser = new DOMParser();
312
+ const doc = parser.parseFromString(htmlEditorContent, 'text/html');
313
+ const allElements = doc.body.querySelectorAll('*');
314
+ allElements.forEach(element => {
315
+ element.removeAttribute('spellcheck');
316
+ element.removeAttribute('class');
317
+ element.removeAttribute('contenteditable');
318
+ });
319
+ return doc.body.innerHTML;
320
+ };
321
+ htmlMinifyForEmail(HTML_DOM);
@@ -0,0 +1,8 @@
1
+ export * from './selection';
2
+ export * from './link';
3
+ export * from './smartTag';
4
+ export * from './style';
5
+ export * from './font';
6
+ export * from './htmlProcessing';
7
+ export * from './menu';
8
+ export * from './documentState';
@@ -0,0 +1,16 @@
1
+ // Selection utilities
2
+ export * from './selection';
3
+ // Link utilities
4
+ export * from './link';
5
+ // Smart tag utilities
6
+ export * from './smartTag';
7
+ // Style utilities
8
+ export * from './style';
9
+ // Font utilities
10
+ export * from './font';
11
+ // HTML processing utilities
12
+ export * from './htmlProcessing';
13
+ // Menu utilities
14
+ export * from './menu';
15
+ // Document state utilities
16
+ export * from './documentState';
@@ -0,0 +1,100 @@
1
+ import { EditorState } from '@tiptap/pm/state';
2
+ import { MarkRange } from '@tiptap/core';
3
+ import { EditorView } from '@tiptap/pm/view';
4
+ import { LinkHandler } from '../types';
5
+ /**
6
+ * Kiểm tra xem cursor có đang nằm trong một đoạn text có mark là link hay không
7
+ * @param state EditorState của Tiptap/ProseMirror
8
+ * @returns true nếu cursor đang nằm trong link, false nếu không
9
+ */
10
+ export declare const isCursorInLink: (state: EditorState) => boolean;
11
+ /**
12
+ * Gets all link mark ranges within a specified range
13
+ * @param params Object containing state, from and to positions
14
+ * @returns Array of MarkRange objects for links
15
+ */
16
+ export declare const getLinkMarkRanges: (params: {
17
+ state: EditorState;
18
+ from: number;
19
+ to: number;
20
+ }) => MarkRange[];
21
+ /**
22
+ * Gets the range of a link mark at a specific position
23
+ * @param params Object containing state and optional position
24
+ * @returns Link mark range or undefined
25
+ */
26
+ export declare const getLinkRange: (params: {
27
+ state: EditorState;
28
+ pos?: number;
29
+ }) => void | import("@tiptap/core").Range;
30
+ /**
31
+ * Gets the first link mark in a range
32
+ * @param params Object containing state, optional from and to positions
33
+ * @returns Link mark or undefined
34
+ */
35
+ export declare const getLinkMark: (params: {
36
+ state: EditorState;
37
+ from?: number;
38
+ to?: number;
39
+ }) => import("prosemirror-model").Mark | undefined;
40
+ /**
41
+ * Gets all link marks in a range
42
+ * @param params Object containing state, from and to positions
43
+ * @returns Array of link marks
44
+ */
45
+ export declare const getLinkMarks: (params: {
46
+ state: EditorState;
47
+ from: number;
48
+ to: number;
49
+ }) => import("prosemirror-model").Mark[];
50
+ /**
51
+ * Gets all link IDs from a range
52
+ * @param params Object containing state, optional from and to positions
53
+ * @returns Array of link IDs
54
+ */
55
+ export declare const getLinkIdsFromRange: (params: {
56
+ state: EditorState;
57
+ from?: number;
58
+ to?: number;
59
+ }) => string[];
60
+ /**
61
+ * Gets the active link ID and inactive links from a range
62
+ * @param params Object containing state, optional from and to positions
63
+ * @returns Object with activeId and inactiveLinks or undefined
64
+ */
65
+ export declare const getActiveLinkIdFromRange: (params: {
66
+ state: EditorState;
67
+ from?: number;
68
+ to?: number;
69
+ }) => {
70
+ activeId: string;
71
+ inactiveLinks: string[];
72
+ } | undefined;
73
+ /**
74
+ * Extends selection to include full link marks
75
+ * @param state EditorState
76
+ * @param from Start position
77
+ * @param to End position
78
+ * @returns Object with extended from, to positions and linkId
79
+ */
80
+ export declare const extendSelectionToFullLinks: (state: EditorState, from: number, to: number) => {
81
+ from: number;
82
+ to: number;
83
+ linkId?: undefined;
84
+ } | {
85
+ from: number;
86
+ to: number;
87
+ linkId: string;
88
+ };
89
+ /**
90
+ * Handles link actions (create or edit)
91
+ * @param view EditorView instance
92
+ * @param linkHandler Link handler callbacks
93
+ */
94
+ export declare function handleLinkAction(view: EditorView, linkHandler: LinkHandler | undefined): void;
95
+ /**
96
+ * Checks if the link menu should be shown
97
+ * @param state EditorState
98
+ * @returns true if link menu should be shown
99
+ */
100
+ export declare const isShowLinkMenu: (state: EditorState) => boolean;