@zipify/wysiwyg 1.0.0-dev.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 (255) hide show
  1. package/.editorconfig +18 -0
  2. package/.eslintrc.js +253 -0
  3. package/.github/actions/deploy-example/action.yaml +61 -0
  4. package/.github/actions/lint-css/action.yaml +15 -0
  5. package/.github/actions/lint-js/action.yaml +22 -0
  6. package/.github/actions/setup/action.yaml +19 -0
  7. package/.github/actions/unit-tests/action.yaml +13 -0
  8. package/.github/actions/unit-tests/jest.config.js +8 -0
  9. package/.github/dependabot.yaml +17 -0
  10. package/.github/pull_request_template.md +17 -0
  11. package/.github/workflows/frontend-ci.yaml +120 -0
  12. package/.husky/pre-commit +4 -0
  13. package/.lintstagedrc +12 -0
  14. package/.release-it.json +6 -0
  15. package/.stylelintrc +110 -0
  16. package/README.md +61 -0
  17. package/babel.config.js +15 -0
  18. package/ci/example/deploy.sh +25 -0
  19. package/config/jest/TestEnvironment.js +27 -0
  20. package/config/jest/matchers/index.js +6 -0
  21. package/config/jest/matchers/toElementHasStyle.js +27 -0
  22. package/config/jest/matchers/toVueContainComponent.js +20 -0
  23. package/config/jest/matchers/toVueContainElement.js +34 -0
  24. package/config/jest/matchers/toVueContainLazyComponent.js +19 -0
  25. package/config/jest/matchers/toVueEmpty.js +16 -0
  26. package/config/jest/matchers/toVuexActionHasBeenDispatched.js +19 -0
  27. package/config/jest/setupMatchers.js +4 -0
  28. package/config/jest/setupTests.js +32 -0
  29. package/config/jest/typing.d.ts +14 -0
  30. package/config/svgo.js +22 -0
  31. package/config/webpack/example.config.js +86 -0
  32. package/config/webpack/loaders/index.js +6 -0
  33. package/config/webpack/loaders/js-loader.js +5 -0
  34. package/config/webpack/loaders/style-loader.js +7 -0
  35. package/config/webpack/loaders/svg-loader.js +4 -0
  36. package/config/webpack/loaders/vue-loader.js +4 -0
  37. package/config/webpack/settings.js +9 -0
  38. package/example/ExampleApp.vue +136 -0
  39. package/example/example.html +17 -0
  40. package/example/example.js +19 -0
  41. package/example/fonts.js +474 -0
  42. package/example/presets.js +245 -0
  43. package/example/tooltip/Tooltip.js +241 -0
  44. package/example/tooltip/TooltipManager.js +132 -0
  45. package/example/tooltip/index.js +3 -0
  46. package/example/tooltip/modifiers/TooltipCloseOnScrollModifier.js +73 -0
  47. package/example/tooltip/modifiers/index.js +1 -0
  48. package/example/tooltip/tooltip.css +95 -0
  49. package/jest.config.js +17 -0
  50. package/lib/Wysiwyg.vue +156 -0
  51. package/lib/__mocks__/svgMock.js +1 -0
  52. package/lib/__tests__/utils/NodeFactory.js +67 -0
  53. package/lib/__tests__/utils/index.js +4 -0
  54. package/lib/__tests__/utils/setReadonlyProperty.js +9 -0
  55. package/lib/__tests__/utils/waitAsyncOperation.js +6 -0
  56. package/lib/__tests__/utils/withComponentContext.js +14 -0
  57. package/lib/assets/icons.svg +69 -0
  58. package/lib/components/base/Button.vue +117 -0
  59. package/lib/components/base/ButtonToggle.vue +40 -0
  60. package/lib/components/base/FieldLabel.vue +28 -0
  61. package/lib/components/base/Icon.vue +67 -0
  62. package/lib/components/base/Modal.vue +116 -0
  63. package/lib/components/base/NumberField.vue +242 -0
  64. package/lib/components/base/Range.vue +196 -0
  65. package/lib/components/base/ScrollView.vue +60 -0
  66. package/lib/components/base/__tests__/Button.test.js +50 -0
  67. package/lib/components/base/__tests__/Icon.test.js +56 -0
  68. package/lib/components/base/__tests__/Modal.test.js +69 -0
  69. package/lib/components/base/__tests__/Range.test.js +39 -0
  70. package/lib/components/base/colorPicker/ColorPicker.vue +93 -0
  71. package/lib/components/base/colorPicker/composables/__tests__/usePickerApi.test.js +81 -0
  72. package/lib/components/base/colorPicker/composables/index.js +2 -0
  73. package/lib/components/base/colorPicker/composables/usePickerApi.js +35 -0
  74. package/lib/components/base/colorPicker/composables/usePickerHotkeys.js +25 -0
  75. package/lib/components/base/colorPicker/index.js +1 -0
  76. package/lib/components/base/composables/__tests__/useActivatedListener.test.js +89 -0
  77. package/lib/components/base/composables/__tests__/useDeselectionLock.test.js +80 -0
  78. package/lib/components/base/composables/__tests__/useElementRef.test.js +29 -0
  79. package/lib/components/base/composables/__tests__/useModalToggler.test.js +55 -0
  80. package/lib/components/base/composables/__tests__/useNumberValue.test.js +153 -0
  81. package/lib/components/base/composables/__tests__/useScrollView.test.js +43 -0
  82. package/lib/components/base/composables/__tests__/useTempValue.test.js +38 -0
  83. package/lib/components/base/composables/index.js +7 -0
  84. package/lib/components/base/composables/useActivatedListener.js +23 -0
  85. package/lib/components/base/composables/useDeselectionLock.js +35 -0
  86. package/lib/components/base/composables/useElementRef.js +5 -0
  87. package/lib/components/base/composables/useModalToggler.js +58 -0
  88. package/lib/components/base/composables/useNumberValue.js +53 -0
  89. package/lib/components/base/composables/useScrollView.js +22 -0
  90. package/lib/components/base/composables/useTempValue.js +11 -0
  91. package/lib/components/base/dropdown/Dropdown.vue +88 -0
  92. package/lib/components/base/dropdown/DropdownActivator.vue +81 -0
  93. package/lib/components/base/dropdown/DropdownDivider.vue +21 -0
  94. package/lib/components/base/dropdown/DropdownGroup.vue +55 -0
  95. package/lib/components/base/dropdown/DropdownMenu.vue +62 -0
  96. package/lib/components/base/dropdown/DropdownOption.vue +91 -0
  97. package/lib/components/base/dropdown/__tests__/DropdownActivator.test.js +54 -0
  98. package/lib/components/base/dropdown/__tests__/DropdownMenu.test.js +67 -0
  99. package/lib/components/base/dropdown/__tests__/DropdownOption.test.js +81 -0
  100. package/lib/components/base/dropdown/composables/__tests__/useActiveOptionManager.test.js +41 -0
  101. package/lib/components/base/dropdown/composables/__tests__/useDropdownEntityTitle.test.js +24 -0
  102. package/lib/components/base/dropdown/composables/index.js +2 -0
  103. package/lib/components/base/dropdown/composables/useActiveOptionManager.js +25 -0
  104. package/lib/components/base/dropdown/composables/useDropdownEntityTitle.js +5 -0
  105. package/lib/components/base/dropdown/index.js +2 -0
  106. package/lib/components/base/dropdown/injectionTokens.js +5 -0
  107. package/lib/components/base/index.js +11 -0
  108. package/lib/components/index.js +1 -0
  109. package/lib/components/toolbar/Toolbar.vue +56 -0
  110. package/lib/components/toolbar/ToolbarDevice.vue +35 -0
  111. package/lib/components/toolbar/ToolbarDivider.vue +50 -0
  112. package/lib/components/toolbar/ToolbarFull.vue +94 -0
  113. package/lib/components/toolbar/ToolbarGroup.vue +18 -0
  114. package/lib/components/toolbar/ToolbarRow.vue +19 -0
  115. package/lib/components/toolbar/__tests__/Toolbar.test.js +33 -0
  116. package/lib/components/toolbar/__tests__/ToolbarDivider.test.js +26 -0
  117. package/lib/components/toolbar/controls/AlignmentControl.vue +72 -0
  118. package/lib/components/toolbar/controls/AlignmentDeviceControl.vue +67 -0
  119. package/lib/components/toolbar/controls/BackgroundColorControl.vue +48 -0
  120. package/lib/components/toolbar/controls/CaseStyleControl.vue +54 -0
  121. package/lib/components/toolbar/controls/FontColorControl.vue +48 -0
  122. package/lib/components/toolbar/controls/FontFamilyControl.vue +96 -0
  123. package/lib/components/toolbar/controls/FontSizeControl.vue +45 -0
  124. package/lib/components/toolbar/controls/FontWeightControl.vue +43 -0
  125. package/lib/components/toolbar/controls/ItalicControl.vue +47 -0
  126. package/lib/components/toolbar/controls/LineHeightControl.vue +102 -0
  127. package/lib/components/toolbar/controls/ListControl.vue +86 -0
  128. package/lib/components/toolbar/controls/RemoveFormatControl.vue +37 -0
  129. package/lib/components/toolbar/controls/StrikeThroughControl.vue +44 -0
  130. package/lib/components/toolbar/controls/StylePresetControl.vue +95 -0
  131. package/lib/components/toolbar/controls/SuperscriptControl.vue +44 -0
  132. package/lib/components/toolbar/controls/UnderlineControl.vue +44 -0
  133. package/lib/components/toolbar/controls/__tests__/AlignmentControl.test.js +51 -0
  134. package/lib/components/toolbar/controls/__tests__/AlignmentDeviceControl.test.js +77 -0
  135. package/lib/components/toolbar/controls/__tests__/BackgroundColorControl.test.js +59 -0
  136. package/lib/components/toolbar/controls/__tests__/CaseStyleControl.test.js +43 -0
  137. package/lib/components/toolbar/controls/__tests__/FontColorControl.test.js +59 -0
  138. package/lib/components/toolbar/controls/__tests__/FontFamilyControl.test.js +57 -0
  139. package/lib/components/toolbar/controls/__tests__/FontSizeControl.test.js +47 -0
  140. package/lib/components/toolbar/controls/__tests__/FontWeightControl.test.js +45 -0
  141. package/lib/components/toolbar/controls/__tests__/ItalicControl.test.js +63 -0
  142. package/lib/components/toolbar/controls/__tests__/LineHeightControl.test.js +120 -0
  143. package/lib/components/toolbar/controls/__tests__/ListControl.test.js +82 -0
  144. package/lib/components/toolbar/controls/__tests__/RemoveFormatControl.test.js +34 -0
  145. package/lib/components/toolbar/controls/__tests__/StrikeThroughControl.test.js +44 -0
  146. package/lib/components/toolbar/controls/__tests__/StylePresetControl.test.js +129 -0
  147. package/lib/components/toolbar/controls/__tests__/SuperscriptControl.test.js +44 -0
  148. package/lib/components/toolbar/controls/__tests__/UnderlineControl.test.js +44 -0
  149. package/lib/components/toolbar/controls/composables/__tests__/useRecentFonts.test.js +69 -0
  150. package/lib/components/toolbar/controls/composables/index.js +1 -0
  151. package/lib/components/toolbar/controls/composables/useRecentFonts.js +18 -0
  152. package/lib/components/toolbar/controls/index.js +16 -0
  153. package/lib/components/toolbar/index.js +1 -0
  154. package/lib/composables/__tests__/__snapshots__/useEditor.test.js.snap +24 -0
  155. package/lib/composables/__tests__/useEditor.test.js +67 -0
  156. package/lib/composables/__tests__/useToolbar.test.js +56 -0
  157. package/lib/composables/index.js +2 -0
  158. package/lib/composables/useEditor.js +21 -0
  159. package/lib/composables/useToolbar.js +44 -0
  160. package/lib/directives/__tests__/outClick.test.js +86 -0
  161. package/lib/directives/__tests__/tooltip.test.js +39 -0
  162. package/lib/directives/index.js +2 -0
  163. package/lib/directives/outClick.js +37 -0
  164. package/lib/directives/tooltip.js +7 -0
  165. package/lib/enums/Alignments.js +6 -0
  166. package/lib/enums/CaseStyles.js +5 -0
  167. package/lib/enums/Devices.js +15 -0
  168. package/lib/enums/ListTypes.js +23 -0
  169. package/lib/enums/NodeTypes.js +12 -0
  170. package/lib/enums/TextSettings.js +30 -0
  171. package/lib/enums/index.js +6 -0
  172. package/lib/extensions/Alignment.js +67 -0
  173. package/lib/extensions/BackgroundColor.js +28 -0
  174. package/lib/extensions/CaseStyle.js +36 -0
  175. package/lib/extensions/DeviceManager.js +16 -0
  176. package/lib/extensions/FontColor.js +36 -0
  177. package/lib/extensions/FontFamily.js +62 -0
  178. package/lib/extensions/FontSize.js +74 -0
  179. package/lib/extensions/FontStyle.js +62 -0
  180. package/lib/extensions/FontWeight.js +56 -0
  181. package/lib/extensions/LineHeight.js +60 -0
  182. package/lib/extensions/StylePreset.js +168 -0
  183. package/lib/extensions/Superscript.js +5 -0
  184. package/lib/extensions/TextDecoration.js +97 -0
  185. package/lib/extensions/__tests__/Alignment.test.js +107 -0
  186. package/lib/extensions/__tests__/BackgroundColor.test.js +75 -0
  187. package/lib/extensions/__tests__/CaseStyle.test.js +58 -0
  188. package/lib/extensions/__tests__/FontColor.test.js +85 -0
  189. package/lib/extensions/__tests__/FontFamily.test.js +171 -0
  190. package/lib/extensions/__tests__/FontSize.test.js +183 -0
  191. package/lib/extensions/__tests__/FontStyle.test.js +136 -0
  192. package/lib/extensions/__tests__/FontWeight.test.js +151 -0
  193. package/lib/extensions/__tests__/LineHeight.test.js +106 -0
  194. package/lib/extensions/__tests__/StylePreset.test.js +400 -0
  195. package/lib/extensions/__tests__/TextDecoration.test.js +258 -0
  196. package/lib/extensions/__tests__/__snapshots__/Alignment.test.js.snap +29 -0
  197. package/lib/extensions/__tests__/__snapshots__/BackgroundColor.test.js.snap +28 -0
  198. package/lib/extensions/__tests__/__snapshots__/CaseStyle.test.js.snap +69 -0
  199. package/lib/extensions/__tests__/__snapshots__/FontColor.test.js.snap +28 -0
  200. package/lib/extensions/__tests__/__snapshots__/FontFamily.test.js.snap +158 -0
  201. package/lib/extensions/__tests__/__snapshots__/FontSize.test.js.snap +140 -0
  202. package/lib/extensions/__tests__/__snapshots__/FontStyle.test.js.snap +87 -0
  203. package/lib/extensions/__tests__/__snapshots__/FontWeight.test.js.snap +140 -0
  204. package/lib/extensions/__tests__/__snapshots__/LineHeight.test.js.snap +29 -0
  205. package/lib/extensions/__tests__/__snapshots__/StylePreset.test.js.snap +310 -0
  206. package/lib/extensions/__tests__/__snapshots__/TextDecoration.test.js.snap +206 -0
  207. package/lib/extensions/core/NodeProcessor.js +32 -0
  208. package/lib/extensions/core/SelectionProcessor.js +37 -0
  209. package/lib/extensions/core/TextProcessor.js +57 -0
  210. package/lib/extensions/core/__tests__/NodeProcessor.test.js +120 -0
  211. package/lib/extensions/core/__tests__/SelectionProcessor.test.js +78 -0
  212. package/lib/extensions/core/__tests__/TextProcessor.test.js +61 -0
  213. package/lib/extensions/core/__tests__/__snapshots__/NodeProcessor.test.js.snap +93 -0
  214. package/lib/extensions/core/__tests__/__snapshots__/TextProcessor.test.js.snap +43 -0
  215. package/lib/extensions/core/index.js +17 -0
  216. package/lib/extensions/core/inputRules/closeDoubleQuote.js +6 -0
  217. package/lib/extensions/core/inputRules/closeSingleQuote.js +6 -0
  218. package/lib/extensions/core/inputRules/copyright.js +6 -0
  219. package/lib/extensions/core/inputRules/ellipsis.js +6 -0
  220. package/lib/extensions/core/inputRules/emDash.js +6 -0
  221. package/lib/extensions/core/inputRules/index.js +9 -0
  222. package/lib/extensions/core/inputRules/openDoubleQuote.js +6 -0
  223. package/lib/extensions/core/inputRules/openSingleQuote.js +6 -0
  224. package/lib/extensions/core/inputRules/registeredTrademark.js +6 -0
  225. package/lib/extensions/core/inputRules/trademark.js +6 -0
  226. package/lib/extensions/index.js +49 -0
  227. package/lib/extensions/list/List.js +81 -0
  228. package/lib/extensions/list/ListItem.js +12 -0
  229. package/lib/extensions/list/__tests__/List.test.js +130 -0
  230. package/lib/extensions/list/__tests__/__snapshots__/List.test.js.snap +212 -0
  231. package/lib/extensions/list/index.js +1 -0
  232. package/lib/index.js +1 -0
  233. package/lib/injectionTokens.js +7 -0
  234. package/lib/models/Font.js +37 -0
  235. package/lib/models/__tests__/Font.test.js +58 -0
  236. package/lib/models/index.js +1 -0
  237. package/lib/services/FavoriteColors.js +6 -0
  238. package/lib/services/JsonSerializer.js +15 -0
  239. package/lib/services/Storage.js +49 -0
  240. package/lib/services/index.js +3 -0
  241. package/lib/styles/content.css +39 -0
  242. package/lib/styles/helpers/common.css +3 -0
  243. package/lib/styles/helpers/offsets.css +3 -0
  244. package/lib/styles/helpers/text.css +6 -0
  245. package/lib/styles/main.css +5 -0
  246. package/lib/styles/variables.css +57 -0
  247. package/lib/utils/__tests__/__snapshots__/renderInlineSetting.test.js.snap +40 -0
  248. package/lib/utils/__tests__/capitalize.test.js +11 -0
  249. package/lib/utils/__tests__/renderInlineSetting.test.js +39 -0
  250. package/lib/utils/capitalize.js +3 -0
  251. package/lib/utils/createCommand.js +3 -0
  252. package/lib/utils/createKeyboardShortcut.js +6 -0
  253. package/lib/utils/index.js +4 -0
  254. package/lib/utils/renderInlineSetting.js +17 -0
  255. package/package.json +75 -0
@@ -0,0 +1,245 @@
1
+ export const PRESETS = [
2
+ {
3
+ 'id': 'h1',
4
+ 'name': 'H1',
5
+ 'node': {
6
+ 'type': 'heading',
7
+ 'level': 1
8
+ },
9
+ 'desktop': {
10
+ 'alignment': 'left',
11
+ 'line_height': '1.2',
12
+ 'font_size': '40px'
13
+ },
14
+ 'common': {
15
+ 'font_family': 'Lato',
16
+ 'font_weight': '700',
17
+ 'color': '#262626',
18
+ 'font_style': 'normal',
19
+ 'text_decoration': 'none'
20
+ },
21
+ 'tablet': {
22
+ 'alignment': 'left',
23
+ 'line_height': '1.2',
24
+ 'font_size': '40px'
25
+ },
26
+ 'mobile': {
27
+ 'alignment': 'left',
28
+ 'line_height': '1.2',
29
+ 'font_size': '28px'
30
+ }
31
+ },
32
+ {
33
+ 'id': 'h2',
34
+ 'name': 'H2',
35
+ 'node': {
36
+ 'type': 'heading',
37
+ 'level': 2
38
+ },
39
+ 'desktop': {
40
+ 'alignment': 'left',
41
+ 'line_height': '1.2',
42
+ 'font_size': '32px'
43
+ },
44
+ 'common': {
45
+ 'font_family': 'Lato',
46
+ 'font_weight': '700',
47
+ 'color': '#262626',
48
+ 'font_style': 'normal',
49
+ 'text_decoration': 'none'
50
+ },
51
+ 'tablet': {
52
+ 'alignment': 'left',
53
+ 'line_height': '1.2',
54
+ 'font_size': '32px'
55
+ },
56
+ 'mobile': {
57
+ 'alignment': 'left',
58
+ 'line_height': '1.2',
59
+ 'font_size': '24px'
60
+ }
61
+ },
62
+ {
63
+ 'id': 'h3',
64
+ 'name': 'H3',
65
+ 'node': {
66
+ 'type': 'heading',
67
+ 'level': 3
68
+ },
69
+ 'desktop': {
70
+ 'alignment': 'left',
71
+ 'line_height': '1.2',
72
+ 'font_size': '28px'
73
+ },
74
+ 'common': {
75
+ 'font_family': 'Lato',
76
+ 'font_weight': '700',
77
+ 'color': '#262626',
78
+ 'font_style': 'normal',
79
+ 'text_decoration': 'none'
80
+ },
81
+ 'tablet': {
82
+ 'alignment': 'left',
83
+ 'line_height': '1.2',
84
+ 'font_size': '28px'
85
+ },
86
+ 'mobile': {
87
+ 'alignment': 'left',
88
+ 'line_height': '1.2',
89
+ 'font_size': '20px'
90
+ }
91
+ },
92
+ {
93
+ 'id': 'h4',
94
+ 'name': 'H4',
95
+ 'node': {
96
+ 'type': 'heading',
97
+ 'level': 4
98
+ },
99
+ 'desktop': {
100
+ 'alignment': 'left',
101
+ 'line_height': '1.2',
102
+ 'font_size': '24px'
103
+ },
104
+ 'common': {
105
+ 'font_family': 'Lato',
106
+ 'font_weight': '700',
107
+ 'color': '#262626',
108
+ 'font_style': 'normal',
109
+ 'text_decoration': 'none'
110
+ },
111
+ 'tablet': {
112
+ 'alignment': 'left',
113
+ 'line_height': '1.2',
114
+ 'font_size': '24px'
115
+ },
116
+ 'mobile': {
117
+ 'alignment': 'left',
118
+ 'line_height': '1.2',
119
+ 'font_size': '18px'
120
+ }
121
+ },
122
+ {
123
+ 'id': 'link',
124
+ 'name': 'Link',
125
+ 'hidden': true,
126
+ 'desktop': {
127
+ 'alignment': 'left',
128
+ 'line_height': 'inherit',
129
+ 'font_size': 'inherit'
130
+ },
131
+ 'common': {
132
+ 'font_family': 'inherit',
133
+ 'font_weight': 'inherit',
134
+ 'color': '',
135
+ 'font_style': 'normal',
136
+ 'text_decoration': 'underline'
137
+ },
138
+ 'tablet': {
139
+ 'alignment': 'left',
140
+ 'line_height': 'inherit',
141
+ 'font_size': 'inherit'
142
+ },
143
+ 'mobile': {
144
+ 'alignment': 'left',
145
+ 'line_height': 'inherit',
146
+ 'font_size': 'inherit'
147
+ }
148
+ },
149
+ {
150
+ 'id': 'regular-1',
151
+ 'name': 'Regular',
152
+ 'desktop': {
153
+ 'alignment': 'left',
154
+ 'line_height': '1.43',
155
+ 'font_size': '18px'
156
+ },
157
+ 'common': {
158
+ 'font_family': 'Lato',
159
+ 'font_weight': '400',
160
+ 'color': '#262626',
161
+ 'font_style': 'normal',
162
+ 'text_decoration': 'none'
163
+ },
164
+ 'tablet': {
165
+ 'alignment': 'left',
166
+ 'line_height': '1.43',
167
+ 'font_size': '18px'
168
+ },
169
+ 'mobile': {
170
+ 'alignment': 'left',
171
+ 'line_height': '1.43',
172
+ 'font_size': '18px'
173
+ }
174
+ },
175
+ {
176
+ 'id': 'regular-2',
177
+ 'name': 'Regular 2',
178
+ 'desktop': {
179
+ 'alignment': 'left',
180
+ 'line_height': '1.43',
181
+ 'font_size': '16px'
182
+ },
183
+ 'common': {
184
+ 'font_family': 'Lato',
185
+ 'font_weight': '400',
186
+ 'color': '#262626',
187
+ 'font_style': 'normal',
188
+ 'text_decoration': 'none'
189
+ },
190
+ 'tablet': {
191
+ 'alignment': 'left',
192
+ 'line_height': '1.43',
193
+ 'font_size': '16px'
194
+ },
195
+ 'mobile': {
196
+ 'alignment': 'left',
197
+ 'line_height': '1.43',
198
+ 'font_size': '16px'
199
+ }
200
+ },
201
+ {
202
+ 'id': 'regular-3',
203
+ 'name': 'Regular 3',
204
+ 'desktop': {
205
+ 'alignment': 'left',
206
+ 'line_height': '1.43',
207
+ 'font_size': '12px'
208
+ },
209
+ 'common': {
210
+ 'font_family': 'Lato',
211
+ 'font_weight': '400',
212
+ 'color': '#262626',
213
+ 'font_style': 'normal',
214
+ 'text_decoration': 'none'
215
+ },
216
+ 'tablet': {
217
+ 'alignment': 'left',
218
+ 'line_height': '1.43',
219
+ 'font_size': '12px'
220
+ },
221
+ 'mobile': {
222
+ 'alignment': 'left',
223
+ 'line_height': '1.43',
224
+ 'font_size': '12px'
225
+ }
226
+ }
227
+ ];
228
+
229
+ export function renderPresetVariable({ device, preset, property }) {
230
+ const formattedProperty = property.replace(/_/i, '-');
231
+
232
+ return `--${device}-${preset.id}-${formattedProperty}`;
233
+ }
234
+
235
+ export function renderPresets() {
236
+ for (const preset of PRESETS) {
237
+ for (const device of ['common', 'mobile', 'tablet', 'desktop']) {
238
+ for (const [property, value] of Object.entries(preset[device])) {
239
+ const variable = renderPresetVariable({ device, preset, property });
240
+
241
+ document.body.style.setProperty(variable, value);
242
+ }
243
+ }
244
+ }
245
+ }
@@ -0,0 +1,241 @@
1
+ import './tooltip.css';
2
+
3
+ import { popperGenerator, defaultModifiers } from '@popperjs/core/lib/popper-lite';
4
+ import arrow from '@popperjs/core/lib/modifiers/arrow';
5
+ import flip from '@popperjs/core/lib/modifiers/flip';
6
+ import offset from '@popperjs/core/lib/modifiers/offset';
7
+ import preventOverflow from '@popperjs/core/lib/modifiers/preventOverflow';
8
+ import { TooltipCloseOnScrollModifier } from './modifiers';
9
+
10
+ export class Tooltip {
11
+ static get defaultOptions() {
12
+ return {
13
+ placement: 'top',
14
+ size: 'md'
15
+ };
16
+ }
17
+
18
+ static get animationOptions() {
19
+ return {
20
+ enterDuration: 150,
21
+ leaveDuration: 200
22
+ };
23
+ }
24
+
25
+ static get popperStyles() {
26
+ return {
27
+ willChange: 'transform',
28
+ zIndex: 10001
29
+ };
30
+ }
31
+
32
+ /** @type {HTMLElement} tooltip's target element */
33
+ triggerEl = null;
34
+
35
+ /** @type {string} tooltip's content */
36
+ message = '';
37
+
38
+ /** @type {object} options for Popper.js instance */
39
+ popperOptions = {};
40
+
41
+ /** @type {object} styles for tooltip's wrapper element */
42
+ popperStyles = {};
43
+
44
+ /** @type {{ enterDuration: number, leaveDuration: number }} tooltip's fade in / fade out durations */
45
+ animationOptions = {};
46
+
47
+ /** @type {object | null} created Popper.js instance */
48
+ popperInstance = null;
49
+
50
+ /** @type {{ tooltip: HTMLElement, container: HTMLElement, contentEl: HTMLElement, arrow: HTMLElement }} elements of tooltip */
51
+ elements = {};
52
+
53
+ /**
54
+ * Create custom tooltip for given element with given content and options
55
+ * @param params {object}
56
+ * @param params.triggerEl {HTMLElement}
57
+ * @param params.message {string}
58
+ * @param [params.popperOptions] {{ placement: string, size: string }}
59
+ * @param [params.popperStyles] {object}
60
+ * @param [params.animationOptions] {{ enterDuration: number, leaveDuration: number }}
61
+ */
62
+ constructor({ triggerEl, message, popperOptions, popperStyles, animationOptions }) {
63
+ this.triggerEl = triggerEl;
64
+ this.message = message;
65
+
66
+ this.popperOptions = Object.assign({}, Tooltip.defaultOptions, popperOptions);
67
+ this.popperStyles = Object.assign({}, Tooltip.popperStyles, popperStyles);
68
+ this.animationOptions = Object.assign({}, Tooltip.animationOptions, animationOptions);
69
+
70
+ this._isMacOS = window.navigator.userAgent.toLowerCase().includes('mac os');
71
+
72
+ this._initialize();
73
+ }
74
+
75
+ _initialize() {
76
+ let tooltip = this._createTooltip();
77
+
78
+ this.elements = {
79
+ tooltip,
80
+ container: tooltip.querySelector('[data-container]'),
81
+ contentEl: tooltip.querySelector('[data-content]'),
82
+ arrow: tooltip.querySelector('[data-arrow]')
83
+ };
84
+ }
85
+
86
+ _createTooltip() {
87
+ let element = document.createElement('div');
88
+
89
+ Object.keys(this.popperStyles).forEach((style) => (element.style[style] = this.popperStyles[style]));
90
+
91
+ element.innerHTML = `
92
+ <div class="zpa-tooltip zpa-tooltip--${this.popperOptions.size}" data-container>
93
+ <div class="zpa-tooltip__content" data-content></div>
94
+ <div class="zpa-tooltip__arrow" data-arrow></div>
95
+ </div>`;
96
+
97
+ return element;
98
+ }
99
+
100
+ _renderContent(message) {
101
+ // Do not use .innerHTML, it will break tooltips in Scripts section!
102
+ this.elements.contentEl.textContent = message;
103
+
104
+ this.elements.hotkey?.remove();
105
+ this._renderHotkeyTip();
106
+ }
107
+
108
+ _renderHotkeyTip() {
109
+ const raw = this.triggerEl.dataset.tooltipHotkey;
110
+
111
+ if (!raw) return;
112
+
113
+ const parts = raw.split(' ').map(this._formatHotkeyPart.bind(this));
114
+ const tipEl = document.createElement('span');
115
+
116
+ tipEl.classList.add('zpa-tooltip__hotkey');
117
+ tipEl.innerText = this._isMacOS ? parts.join('') : parts.join(' ');
118
+
119
+ this.elements.contentEl.append(tipEl);
120
+ }
121
+
122
+ _formatHotkeyPart(part) {
123
+ switch (part.toLowerCase()) {
124
+ case 'mod':
125
+ return this._isMacOS ? '⌘' : 'Ctrl';
126
+
127
+ case 'shift':
128
+ return this._isMacOS ? '⇧' : 'Shift';
129
+
130
+ default: return part;
131
+ }
132
+ }
133
+
134
+ _getModifiers() {
135
+ return [
136
+ {
137
+ name: 'arrow',
138
+ options: {
139
+ element: '[data-arrow]'
140
+ }
141
+ },
142
+ {
143
+ name: 'offset',
144
+ options: {
145
+ offset: [0, 8]
146
+ }
147
+ },
148
+ {
149
+ name: 'preventOverflow',
150
+ options: {
151
+ padding: {
152
+ top: 4,
153
+ bottom: 4,
154
+ left: 8,
155
+ right: 8
156
+ }
157
+ }
158
+ },
159
+ {
160
+ name: 'customAttributes',
161
+ enabled: true,
162
+ phase: 'beforeWrite',
163
+ requires: ['computeStyles'],
164
+ fn: ({ state }) => {
165
+ this.elements.arrow.classList.add(`zpa-tooltip__arrow--${state.placement}`);
166
+ state.attributes.popper = {};
167
+ }
168
+ },
169
+ TooltipCloseOnScrollModifier.init({ tooltip: this })
170
+ ];
171
+ }
172
+
173
+ _setTooltipDuration(duration = 0) {
174
+ this.elements.container.style.transitionDuration = `${duration}ms`;
175
+ }
176
+
177
+ _renderPopper() {
178
+ const modifiers = this._getModifiers();
179
+
180
+ const createPopper = popperGenerator({
181
+ defaultModifiers: [...defaultModifiers, arrow, flip, offset, preventOverflow]
182
+ });
183
+
184
+ this.popperInstance = createPopper(this.triggerEl, this.elements.tooltip, {
185
+ placement: this.popperOptions.placement,
186
+ modifiers
187
+ });
188
+
189
+ return this.popperInstance;
190
+ }
191
+
192
+ _toggle(makeVisible) {
193
+ const { enterDuration, leaveDuration } = this.animationOptions;
194
+
195
+ this._setTooltipDuration(makeVisible ? enterDuration : leaveDuration);
196
+ this.elements.container.classList.toggle('zpa-tooltip--open', makeVisible);
197
+ }
198
+
199
+ open() {
200
+ if (this.popperInstance) {
201
+ return;
202
+ }
203
+
204
+ document.body.appendChild(this.elements.tooltip);
205
+ this.popperInstance = this._renderPopper();
206
+
207
+ this._renderContent(this.message);
208
+ this._toggle(true);
209
+ }
210
+
211
+ close() {
212
+ if (!this.popperInstance) {
213
+ return;
214
+ }
215
+
216
+ this._toggle(false);
217
+
218
+ return setTimeout(() => {
219
+ this.destroy();
220
+ }, this.animationOptions.leaveDuration);
221
+ }
222
+
223
+ update() {
224
+ this.popperInstance?.update();
225
+ }
226
+
227
+ updateContent(content) {
228
+ this.message = content;
229
+ this._renderContent(this.message);
230
+ this.update();
231
+ }
232
+
233
+ destroy() {
234
+ this.elements.tooltip.remove();
235
+
236
+ if (this.popperInstance) {
237
+ this.popperInstance.destroy();
238
+ this.popperInstance = null;
239
+ }
240
+ }
241
+ }
@@ -0,0 +1,132 @@
1
+ import { Tooltip } from './Tooltip';
2
+
3
+ const DEBOUNCE_TIMEOUT = 150;
4
+ const OPEN_TOOLTIP_DELAY = 450;
5
+
6
+ export class TooltipManager {
7
+ /** @type {Tooltip} active tooltip instance */
8
+ activeTooltip = null;
9
+
10
+ /** @type {HTMLElement} target element of active tooltip instance */
11
+ activeTooltipTargetEl = null;
12
+
13
+ /** @type {number} tooltip opening timeout id */
14
+ timeoutId = 0;
15
+
16
+ /** @type {MutationObserver} */
17
+ tooltipContentObserver = null;
18
+
19
+ constructor() {
20
+ this._onDebouncedMouseOver = window._.debounce(this._onMouseOver.bind(this), DEBOUNCE_TIMEOUT);
21
+ this.tooltipContentObserver = new MutationObserver(this._updateActiveTooltipContent.bind(this));
22
+ this.closeActiveTooltip = this.closeActiveTooltip.bind(this);
23
+ }
24
+
25
+ init() {
26
+ this.listenEvents();
27
+ }
28
+
29
+ listenEvents() {
30
+ /**
31
+ * Capture option have to be true for correct work tooltips of static elements
32
+ * because _triggerHover method of ElementSelectionManager.js has stopPropagation.
33
+ */
34
+ document.addEventListener('mouseover', this._onDebouncedMouseOver, { capture: true });
35
+ }
36
+
37
+ _onMouseOver({ target }) {
38
+ const tooltipTargetEl = target.closest('[data-tooltip]');
39
+
40
+ target.addEventListener('click', this.closeActiveTooltip);
41
+
42
+ if (this.activeTooltipTargetEl && tooltipTargetEl === this.activeTooltipTargetEl) {
43
+ return;
44
+ }
45
+
46
+ this.closeActiveTooltip();
47
+
48
+ if (!tooltipTargetEl) {
49
+ return;
50
+ }
51
+
52
+ const tooltipContent = this._getTooltipContent(tooltipTargetEl);
53
+
54
+ if (!tooltipContent) {
55
+ return;
56
+ }
57
+
58
+ this.timeoutId = setTimeout(() => {
59
+ if (!document.body.contains(tooltipTargetEl)) {
60
+ return;
61
+ }
62
+
63
+ this.activeTooltip = new Tooltip({
64
+ message: tooltipContent,
65
+ triggerEl: tooltipTargetEl,
66
+ popperOptions: this._getTooltipOptions(tooltipTargetEl)
67
+ });
68
+
69
+ this.activeTooltip.open();
70
+ this.activeTooltipTargetEl = tooltipTargetEl;
71
+
72
+ this._listenTooltipChanges();
73
+ }, OPEN_TOOLTIP_DELAY);
74
+ }
75
+
76
+ _getTooltipContent(tooltipTargetEl) {
77
+ const tooltipContent = tooltipTargetEl.dataset.tooltip || '';
78
+
79
+ return tooltipContent.trim();
80
+ }
81
+
82
+ _getTooltipOptions(tooltipTargetEl) {
83
+ const tooltipOptions = {};
84
+ const { tooltipPosition, tooltipSize } = tooltipTargetEl.dataset;
85
+
86
+ if (tooltipPosition) {
87
+ tooltipOptions.placement = tooltipPosition;
88
+ }
89
+
90
+ if (tooltipSize) {
91
+ tooltipOptions.size = tooltipSize;
92
+ }
93
+
94
+ return tooltipOptions;
95
+ }
96
+
97
+ _listenTooltipChanges() {
98
+ this.tooltipContentObserver.observe(this.activeTooltipTargetEl, {
99
+ attributes: true,
100
+ attributeFilter: ['data-tooltip']
101
+ });
102
+ }
103
+
104
+ _updateActiveTooltipContent() {
105
+ this.activeTooltip?.updateContent(this._getTooltipContent(this.activeTooltipTargetEl));
106
+ }
107
+
108
+ /**
109
+ * Update position of active tooltip. It сan be useful when dragging or dynamically resizing a target element
110
+ */
111
+ updateActiveTooltip() {
112
+ this.activeTooltip?.update();
113
+ }
114
+
115
+ /**
116
+ * Destroy active tooltip after hiding animation is complete
117
+ */
118
+ closeActiveTooltip() {
119
+ clearTimeout(this.timeoutId);
120
+
121
+ if (!this.activeTooltip) {
122
+ return;
123
+ }
124
+
125
+ this.tooltipContentObserver.disconnect();
126
+ this.activeTooltip.close();
127
+ this.activeTooltipTargetEl.removeEventListener('click', this.closeActiveTooltip);
128
+
129
+ this.activeTooltip = null;
130
+ this.activeTooltipTargetEl = null;
131
+ }
132
+ }
@@ -0,0 +1,3 @@
1
+ import { TooltipManager } from './TooltipManager';
2
+
3
+ export const tooltipManager = new TooltipManager();
@@ -0,0 +1,73 @@
1
+ export class TooltipCloseOnScrollModifier {
2
+ /**
3
+ * @type {Tooltip} - tooltip element
4
+ * */
5
+ _tooltip = null;
6
+
7
+ /**
8
+ * @description
9
+ * Tooltip emits an event after it was created
10
+ * To close it on scroll, we need to compare last and current
11
+ *
12
+ * @type {DOMRect | null}
13
+ * */
14
+ _elementPreviousPosition = null;
15
+
16
+ /**
17
+ * @type {boolean}
18
+ * */
19
+ isClosed = false;
20
+
21
+ /**
22
+ * @param {Tooltip} tooltip - tooltip element
23
+ *
24
+ * @return {Partial<Modifier<any, any>>} - Popper modifier
25
+ * */
26
+ static init({ tooltip }) {
27
+ const modifier = new TooltipCloseOnScrollModifier(tooltip);
28
+
29
+ return {
30
+ name: 'closeOnScroll',
31
+ enabled: true,
32
+ phase: 'main',
33
+ fn: () => modifier.closeOnScroll()
34
+ };
35
+ }
36
+
37
+ /**
38
+ * @param {Tooltip} tooltip - tooltip element
39
+ * */
40
+ constructor(tooltip) {
41
+ this._tooltip = tooltip;
42
+ }
43
+
44
+ /**
45
+ * To check is tooltip scrolled, we need to check target element position
46
+ * */
47
+ get isScrolled() {
48
+ if (!this._elementPreviousPosition) {
49
+ return false;
50
+ }
51
+
52
+ const isScrolledY = this._elementPreviousPosition.y !== this._elementCurrentPosition.y;
53
+ const isScrolledX = this._elementPreviousPosition.x !== this._elementCurrentPosition.x;
54
+
55
+ return isScrolledY || isScrolledX;
56
+ }
57
+
58
+ closeOnScroll() {
59
+ if (this.isClosed) return;
60
+
61
+ this._elementCurrentPosition = this._tooltip.triggerEl.getBoundingClientRect();
62
+ this.isScrolled ? this._close() : this._storeElementPosition();
63
+ }
64
+
65
+ _close() {
66
+ this.isClosed = true;
67
+ this._tooltip.close();
68
+ }
69
+
70
+ _storeElementPosition() {
71
+ this._elementPreviousPosition = this._elementCurrentPosition;
72
+ }
73
+ }
@@ -0,0 +1 @@
1
+ export * from './TooltipCloseOnScrollModifier';