@dangl/angular-material-shared 2.9.0-beta0037 → 2.9.0-beta0040

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 (175) hide show
  1. package/fesm2022/dangl-angular-material-shared-tiny-mce.mjs +29 -35
  2. package/fesm2022/dangl-angular-material-shared-tiny-mce.mjs.map +1 -1
  3. package/fesm2022/dangl-angular-material-shared.mjs +36 -51
  4. package/fesm2022/dangl-angular-material-shared.mjs.map +1 -1
  5. package/package.json +11 -10
  6. package/styles/material-theme.scss +1 -1
  7. package/styles/material-variables.scss +5 -5
  8. package/tinymce-assets/icons/default/icons.js +46 -9
  9. package/tinymce-assets/icons/default/icons.min.js +1 -1
  10. package/tinymce-assets/models/dom/model.js +8198 -7244
  11. package/tinymce-assets/models/dom/model.min.js +1 -4
  12. package/tinymce-assets/plugins/accordion/plugin.js +1174 -879
  13. package/tinymce-assets/plugins/accordion/plugin.min.js +1 -4
  14. package/tinymce-assets/plugins/advlist/plugin.js +412 -200
  15. package/tinymce-assets/plugins/advlist/plugin.min.js +1 -4
  16. package/tinymce-assets/plugins/anchor/plugin.js +189 -166
  17. package/tinymce-assets/plugins/anchor/plugin.min.js +1 -4
  18. package/tinymce-assets/plugins/autolink/plugin.js +310 -220
  19. package/tinymce-assets/plugins/autolink/plugin.min.js +1 -4
  20. package/tinymce-assets/plugins/autoresize/plugin.js +180 -149
  21. package/tinymce-assets/plugins/autoresize/plugin.min.js +1 -4
  22. package/tinymce-assets/plugins/autosave/plugin.js +208 -189
  23. package/tinymce-assets/plugins/autosave/plugin.min.js +1 -4
  24. package/tinymce-assets/plugins/charmap/plugin.js +905 -1566
  25. package/tinymce-assets/plugins/charmap/plugin.min.js +1 -4
  26. package/tinymce-assets/plugins/code/plugin.js +73 -61
  27. package/tinymce-assets/plugins/code/plugin.min.js +0 -3
  28. package/tinymce-assets/plugins/codesample/plugin.js +3593 -2402
  29. package/tinymce-assets/plugins/codesample/plugin.min.js +8 -3
  30. package/tinymce-assets/plugins/directionality/plugin.js +545 -304
  31. package/tinymce-assets/plugins/directionality/plugin.min.js +1 -4
  32. package/tinymce-assets/plugins/emoticons/js/emojiimages.min.js +0 -2
  33. package/tinymce-assets/plugins/emoticons/js/emojis.min.js +0 -1
  34. package/tinymce-assets/plugins/emoticons/plugin.js +702 -488
  35. package/tinymce-assets/plugins/emoticons/plugin.min.js +1 -4
  36. package/tinymce-assets/plugins/fullscreen/plugin.js +1409 -1049
  37. package/tinymce-assets/plugins/fullscreen/plugin.min.js +1 -4
  38. package/tinymce-assets/plugins/help/js/i18n/keynav/ar.js +4 -1
  39. package/tinymce-assets/plugins/help/js/i18n/keynav/bg_BG.js +4 -1
  40. package/tinymce-assets/plugins/help/js/i18n/keynav/ca.js +4 -1
  41. package/tinymce-assets/plugins/help/js/i18n/keynav/cs.js +4 -1
  42. package/tinymce-assets/plugins/help/js/i18n/keynav/da.js +4 -1
  43. package/tinymce-assets/plugins/help/js/i18n/keynav/de.js +4 -1
  44. package/tinymce-assets/plugins/help/js/i18n/keynav/el.js +4 -1
  45. package/tinymce-assets/plugins/help/js/i18n/keynav/en.js +4 -1
  46. package/tinymce-assets/plugins/help/js/i18n/keynav/es.js +4 -1
  47. package/tinymce-assets/plugins/help/js/i18n/keynav/eu.js +4 -1
  48. package/tinymce-assets/plugins/help/js/i18n/keynav/fa.js +4 -1
  49. package/tinymce-assets/plugins/help/js/i18n/keynav/fi.js +4 -1
  50. package/tinymce-assets/plugins/help/js/i18n/keynav/fr_FR.js +4 -1
  51. package/tinymce-assets/plugins/help/js/i18n/keynav/he_IL.js +4 -1
  52. package/tinymce-assets/plugins/help/js/i18n/keynav/hi.js +4 -1
  53. package/tinymce-assets/plugins/help/js/i18n/keynav/hr.js +4 -1
  54. package/tinymce-assets/plugins/help/js/i18n/keynav/hu_HU.js +4 -1
  55. package/tinymce-assets/plugins/help/js/i18n/keynav/id.js +4 -1
  56. package/tinymce-assets/plugins/help/js/i18n/keynav/it.js +4 -1
  57. package/tinymce-assets/plugins/help/js/i18n/keynav/ja.js +4 -1
  58. package/tinymce-assets/plugins/help/js/i18n/keynav/kk.js +4 -1
  59. package/tinymce-assets/plugins/help/js/i18n/keynav/ko_KR.js +4 -1
  60. package/tinymce-assets/plugins/help/js/i18n/keynav/ms.js +4 -1
  61. package/tinymce-assets/plugins/help/js/i18n/keynav/nb_NO.js +4 -1
  62. package/tinymce-assets/plugins/help/js/i18n/keynav/nl.js +4 -1
  63. package/tinymce-assets/plugins/help/js/i18n/keynav/pl.js +4 -1
  64. package/tinymce-assets/plugins/help/js/i18n/keynav/pt_BR.js +4 -1
  65. package/tinymce-assets/plugins/help/js/i18n/keynav/pt_PT.js +4 -1
  66. package/tinymce-assets/plugins/help/js/i18n/keynav/ro.js +4 -1
  67. package/tinymce-assets/plugins/help/js/i18n/keynav/ru.js +4 -1
  68. package/tinymce-assets/plugins/help/js/i18n/keynav/sk.js +4 -1
  69. package/tinymce-assets/plugins/help/js/i18n/keynav/sl_SI.js +5 -2
  70. package/tinymce-assets/plugins/help/js/i18n/keynav/sv_SE.js +4 -1
  71. package/tinymce-assets/plugins/help/js/i18n/keynav/th_TH.js +4 -1
  72. package/tinymce-assets/plugins/help/js/i18n/keynav/tr.js +4 -1
  73. package/tinymce-assets/plugins/help/js/i18n/keynav/uk.js +4 -1
  74. package/tinymce-assets/plugins/help/js/i18n/keynav/vi.js +4 -1
  75. package/tinymce-assets/plugins/help/js/i18n/keynav/zh_CN.js +8 -5
  76. package/tinymce-assets/plugins/help/js/i18n/keynav/zh_TW.js +4 -1
  77. package/tinymce-assets/plugins/help/plugin.js +739 -809
  78. package/tinymce-assets/plugins/help/plugin.min.js +1 -4
  79. package/tinymce-assets/plugins/image/plugin.js +1475 -1291
  80. package/tinymce-assets/plugins/image/plugin.min.js +1 -4
  81. package/tinymce-assets/plugins/importcss/plugin.js +328 -269
  82. package/tinymce-assets/plugins/importcss/plugin.min.js +1 -4
  83. package/tinymce-assets/plugins/insertdatetime/plugin.js +140 -141
  84. package/tinymce-assets/plugins/insertdatetime/plugin.min.js +1 -4
  85. package/tinymce-assets/plugins/link/plugin.js +1419 -1084
  86. package/tinymce-assets/plugins/link/plugin.min.js +1 -4
  87. package/tinymce-assets/plugins/lists/plugin.js +2177 -1805
  88. package/tinymce-assets/plugins/lists/plugin.min.js +1 -4
  89. package/tinymce-assets/plugins/media/plugin.js +1305 -1047
  90. package/tinymce-assets/plugins/media/plugin.min.js +1 -4
  91. package/tinymce-assets/plugins/nonbreaking/plugin.js +93 -88
  92. package/tinymce-assets/plugins/nonbreaking/plugin.min.js +0 -3
  93. package/tinymce-assets/plugins/pagebreak/plugin.js +91 -85
  94. package/tinymce-assets/plugins/pagebreak/plugin.min.js +0 -3
  95. package/tinymce-assets/plugins/preview/plugin.js +742 -74
  96. package/tinymce-assets/plugins/preview/plugin.min.js +1 -4
  97. package/tinymce-assets/plugins/quickbars/plugin.js +582 -375
  98. package/tinymce-assets/plugins/quickbars/plugin.min.js +1 -4
  99. package/tinymce-assets/plugins/save/plugin.js +100 -82
  100. package/tinymce-assets/plugins/save/plugin.min.js +1 -4
  101. package/tinymce-assets/plugins/searchreplace/plugin.js +1183 -906
  102. package/tinymce-assets/plugins/searchreplace/plugin.min.js +1 -4
  103. package/tinymce-assets/plugins/table/plugin.js +3651 -3094
  104. package/tinymce-assets/plugins/table/plugin.min.js +1 -4
  105. package/tinymce-assets/plugins/visualblocks/plugin.js +71 -63
  106. package/tinymce-assets/plugins/visualblocks/plugin.min.js +1 -4
  107. package/tinymce-assets/plugins/visualchars/plugin.js +685 -436
  108. package/tinymce-assets/plugins/visualchars/plugin.min.js +1 -4
  109. package/tinymce-assets/plugins/wordcount/plugin.js +382 -307
  110. package/tinymce-assets/plugins/wordcount/plugin.min.js +1 -4
  111. package/tinymce-assets/skins/content/dark/content.css +9 -0
  112. package/tinymce-assets/skins/content/dark/content.js +10 -2
  113. package/tinymce-assets/skins/content/dark/content.min.css +9 -0
  114. package/tinymce-assets/skins/content/default/content.css +9 -0
  115. package/tinymce-assets/skins/content/default/content.js +10 -2
  116. package/tinymce-assets/skins/content/default/content.min.css +9 -0
  117. package/tinymce-assets/skins/content/document/content.css +9 -0
  118. package/tinymce-assets/skins/content/document/content.js +10 -2
  119. package/tinymce-assets/skins/content/document/content.min.css +9 -0
  120. package/tinymce-assets/skins/content/tinymce-5/content.css +9 -0
  121. package/tinymce-assets/skins/content/tinymce-5/content.js +10 -2
  122. package/tinymce-assets/skins/content/tinymce-5/content.min.css +9 -0
  123. package/tinymce-assets/skins/content/tinymce-5-dark/content.css +9 -0
  124. package/tinymce-assets/skins/content/tinymce-5-dark/content.js +10 -2
  125. package/tinymce-assets/skins/content/tinymce-5-dark/content.min.css +9 -0
  126. package/tinymce-assets/skins/content/writer/content.css +9 -0
  127. package/tinymce-assets/skins/content/writer/content.js +10 -2
  128. package/tinymce-assets/skins/content/writer/content.min.css +9 -0
  129. package/tinymce-assets/skins/ui/oxide/content.css +157 -49
  130. package/tinymce-assets/skins/ui/oxide/content.inline.css +157 -49
  131. package/tinymce-assets/skins/ui/oxide/content.inline.js +10 -2
  132. package/tinymce-assets/skins/ui/oxide/content.inline.min.css +10 -1
  133. package/tinymce-assets/skins/ui/oxide/content.js +10 -2
  134. package/tinymce-assets/skins/ui/oxide/content.min.css +10 -1
  135. package/tinymce-assets/skins/ui/oxide/skin.css +1592 -214
  136. package/tinymce-assets/skins/ui/oxide/skin.js +1 -2
  137. package/tinymce-assets/skins/ui/oxide/skin.min.css +1 -1
  138. package/tinymce-assets/skins/ui/oxide/skin.shadowdom.js +1 -2
  139. package/tinymce-assets/skins/ui/oxide-dark/content.css +157 -42
  140. package/tinymce-assets/skins/ui/oxide-dark/content.inline.css +157 -49
  141. package/tinymce-assets/skins/ui/oxide-dark/content.inline.js +10 -2
  142. package/tinymce-assets/skins/ui/oxide-dark/content.inline.min.css +10 -1
  143. package/tinymce-assets/skins/ui/oxide-dark/content.js +10 -2
  144. package/tinymce-assets/skins/ui/oxide-dark/content.min.css +10 -1
  145. package/tinymce-assets/skins/ui/oxide-dark/skin.css +1595 -217
  146. package/tinymce-assets/skins/ui/oxide-dark/skin.js +1 -2
  147. package/tinymce-assets/skins/ui/oxide-dark/skin.min.css +1 -1
  148. package/tinymce-assets/skins/ui/oxide-dark/skin.shadowdom.js +1 -2
  149. package/tinymce-assets/skins/ui/tinymce-5/content.css +157 -49
  150. package/tinymce-assets/skins/ui/tinymce-5/content.inline.css +157 -49
  151. package/tinymce-assets/skins/ui/tinymce-5/content.inline.js +10 -2
  152. package/tinymce-assets/skins/ui/tinymce-5/content.inline.min.css +10 -1
  153. package/tinymce-assets/skins/ui/tinymce-5/content.js +10 -2
  154. package/tinymce-assets/skins/ui/tinymce-5/content.min.css +10 -1
  155. package/tinymce-assets/skins/ui/tinymce-5/skin.css +1606 -203
  156. package/tinymce-assets/skins/ui/tinymce-5/skin.js +1 -2
  157. package/tinymce-assets/skins/ui/tinymce-5/skin.min.css +1 -1
  158. package/tinymce-assets/skins/ui/tinymce-5/skin.shadowdom.js +1 -2
  159. package/tinymce-assets/skins/ui/tinymce-5-dark/content.css +157 -42
  160. package/tinymce-assets/skins/ui/tinymce-5-dark/content.inline.css +157 -49
  161. package/tinymce-assets/skins/ui/tinymce-5-dark/content.inline.js +10 -2
  162. package/tinymce-assets/skins/ui/tinymce-5-dark/content.inline.min.css +10 -1
  163. package/tinymce-assets/skins/ui/tinymce-5-dark/content.js +10 -2
  164. package/tinymce-assets/skins/ui/tinymce-5-dark/content.min.css +10 -1
  165. package/tinymce-assets/skins/ui/tinymce-5-dark/skin.css +1607 -204
  166. package/tinymce-assets/skins/ui/tinymce-5-dark/skin.js +1 -2
  167. package/tinymce-assets/skins/ui/tinymce-5-dark/skin.min.css +1 -1
  168. package/tinymce-assets/skins/ui/tinymce-5-dark/skin.shadowdom.js +1 -2
  169. package/tinymce-assets/themes/silver/theme.js +32786 -28738
  170. package/tinymce-assets/themes/silver/theme.min.js +1 -4
  171. package/types/dangl-angular-material-shared-tiny-mce.d.ts +12 -13
  172. package/types/dangl-angular-material-shared.d.ts +26 -26
  173. package/tinymce-assets/plugins/template/index.js +0 -7
  174. package/tinymce-assets/plugins/template/plugin.js +0 -567
  175. package/tinymce-assets/plugins/template/plugin.min.js +0 -4
@@ -1,5 +1,5 @@
1
1
  /**
2
- * TinyMCE version 6.8.3 (2024-02-08)
2
+ * TinyMCE version 7.9.3 (2026-05-19)
3
3
  */
4
4
 
5
5
  (function () {
@@ -7,294 +7,476 @@
7
7
 
8
8
  var global$1 = tinymce.util.Tools.resolve('tinymce.PluginManager');
9
9
 
10
- const eq = t => a => t === a;
10
+ /* eslint-disable @typescript-eslint/no-wrapper-object-types */
11
+ const isSimpleType = (type) => (value) => typeof value === type;
12
+ const eq = (t) => (a) => t === a;
11
13
  const isNull = eq(null);
12
14
  const isUndefined = eq(undefined);
13
- const isNullable = a => a === null || a === undefined;
14
- const isNonNullable = a => !isNullable(a);
15
+ const isNullable = (a) => a === null || a === undefined;
16
+ const isNonNullable = (a) => !isNullable(a);
17
+ const isFunction = isSimpleType('function');
15
18
 
16
- const noop = () => {
17
- };
18
- const constant = value => {
19
- return () => {
20
- return value;
21
- };
19
+ const noop = () => { };
20
+ const constant = (value) => {
21
+ return () => {
22
+ return value;
23
+ };
22
24
  };
23
25
  const never = constant(false);
24
26
 
27
+ /**
28
+ * The `Optional` type represents a value (of any type) that potentially does
29
+ * not exist. Any `Optional<T>` can either be a `Some<T>` (in which case the
30
+ * value does exist) or a `None` (in which case the value does not exist). This
31
+ * module defines a whole lot of FP-inspired utility functions for dealing with
32
+ * `Optional` objects.
33
+ *
34
+ * Comparison with null or undefined:
35
+ * - We don't get fancy null coalescing operators with `Optional`
36
+ * - We do get fancy helper functions with `Optional`
37
+ * - `Optional` support nesting, and allow for the type to still be nullable (or
38
+ * another `Optional`)
39
+ * - There is no option to turn off strict-optional-checks like there is for
40
+ * strict-null-checks
41
+ */
25
42
  class Optional {
26
- constructor(tag, value) {
27
- this.tag = tag;
28
- this.value = value;
29
- }
30
- static some(value) {
31
- return new Optional(true, value);
32
- }
33
- static none() {
34
- return Optional.singletonNone;
35
- }
36
- fold(onNone, onSome) {
37
- if (this.tag) {
38
- return onSome(this.value);
39
- } else {
40
- return onNone();
43
+ // The internal representation has a `tag` and a `value`, but both are
44
+ // private: able to be console.logged, but not able to be accessed by code
45
+ constructor(tag, value) {
46
+ this.tag = tag;
47
+ this.value = value;
48
+ }
49
+ // --- Identities ---
50
+ /**
51
+ * Creates a new `Optional<T>` that **does** contain a value.
52
+ */
53
+ static some(value) {
54
+ return new Optional(true, value);
55
+ }
56
+ /**
57
+ * Create a new `Optional<T>` that **does not** contain a value. `T` can be
58
+ * any type because we don't actually have a `T`.
59
+ */
60
+ static none() {
61
+ return Optional.singletonNone;
62
+ }
63
+ /**
64
+ * Perform a transform on an `Optional` type. Regardless of whether this
65
+ * `Optional` contains a value or not, `fold` will return a value of type `U`.
66
+ * If this `Optional` does not contain a value, the `U` will be created by
67
+ * calling `onNone`. If this `Optional` does contain a value, the `U` will be
68
+ * created by calling `onSome`.
69
+ *
70
+ * For the FP enthusiasts in the room, this function:
71
+ * 1. Could be used to implement all of the functions below
72
+ * 2. Forms a catamorphism
73
+ */
74
+ fold(onNone, onSome) {
75
+ if (this.tag) {
76
+ return onSome(this.value);
77
+ }
78
+ else {
79
+ return onNone();
80
+ }
81
+ }
82
+ /**
83
+ * Determine if this `Optional` object contains a value.
84
+ */
85
+ isSome() {
86
+ return this.tag;
87
+ }
88
+ /**
89
+ * Determine if this `Optional` object **does not** contain a value.
90
+ */
91
+ isNone() {
92
+ return !this.tag;
93
+ }
94
+ // --- Functor (name stolen from Haskell / maths) ---
95
+ /**
96
+ * Perform a transform on an `Optional` object, **if** there is a value. If
97
+ * you provide a function to turn a T into a U, this is the function you use
98
+ * to turn an `Optional<T>` into an `Optional<U>`. If this **does** contain
99
+ * a value then the output will also contain a value (that value being the
100
+ * output of `mapper(this.value)`), and if this **does not** contain a value
101
+ * then neither will the output.
102
+ */
103
+ map(mapper) {
104
+ if (this.tag) {
105
+ return Optional.some(mapper(this.value));
106
+ }
107
+ else {
108
+ return Optional.none();
109
+ }
110
+ }
111
+ // --- Monad (name stolen from Haskell / maths) ---
112
+ /**
113
+ * Perform a transform on an `Optional` object, **if** there is a value.
114
+ * Unlike `map`, here the transform itself also returns an `Optional`.
115
+ */
116
+ bind(binder) {
117
+ if (this.tag) {
118
+ return binder(this.value);
119
+ }
120
+ else {
121
+ return Optional.none();
122
+ }
123
+ }
124
+ // --- Traversable (name stolen from Haskell / maths) ---
125
+ /**
126
+ * For a given predicate, this function finds out if there **exists** a value
127
+ * inside this `Optional` object that meets the predicate. In practice, this
128
+ * means that for `Optional`s that do not contain a value it returns false (as
129
+ * no predicate-meeting value exists).
130
+ */
131
+ exists(predicate) {
132
+ return this.tag && predicate(this.value);
133
+ }
134
+ /**
135
+ * For a given predicate, this function finds out if **all** the values inside
136
+ * this `Optional` object meet the predicate. In practice, this means that
137
+ * for `Optional`s that do not contain a value it returns true (as all 0
138
+ * objects do meet the predicate).
139
+ */
140
+ forall(predicate) {
141
+ return !this.tag || predicate(this.value);
142
+ }
143
+ filter(predicate) {
144
+ if (!this.tag || predicate(this.value)) {
145
+ return this;
146
+ }
147
+ else {
148
+ return Optional.none();
149
+ }
150
+ }
151
+ // --- Getters ---
152
+ /**
153
+ * Get the value out of the inside of the `Optional` object, using a default
154
+ * `replacement` value if the provided `Optional` object does not contain a
155
+ * value.
156
+ */
157
+ getOr(replacement) {
158
+ return this.tag ? this.value : replacement;
159
+ }
160
+ /**
161
+ * Get the value out of the inside of the `Optional` object, using a default
162
+ * `replacement` value if the provided `Optional` object does not contain a
163
+ * value. Unlike `getOr`, in this method the `replacement` object is also
164
+ * `Optional` - meaning that this method will always return an `Optional`.
165
+ */
166
+ or(replacement) {
167
+ return this.tag ? this : replacement;
168
+ }
169
+ /**
170
+ * Get the value out of the inside of the `Optional` object, using a default
171
+ * `replacement` value if the provided `Optional` object does not contain a
172
+ * value. Unlike `getOr`, in this method the `replacement` value is
173
+ * "thunked" - that is to say that you don't pass a value to `getOrThunk`, you
174
+ * pass a function which (if called) will **return** the `value` you want to
175
+ * use.
176
+ */
177
+ getOrThunk(thunk) {
178
+ return this.tag ? this.value : thunk();
179
+ }
180
+ /**
181
+ * Get the value out of the inside of the `Optional` object, using a default
182
+ * `replacement` value if the provided Optional object does not contain a
183
+ * value.
184
+ *
185
+ * Unlike `or`, in this method the `replacement` value is "thunked" - that is
186
+ * to say that you don't pass a value to `orThunk`, you pass a function which
187
+ * (if called) will **return** the `value` you want to use.
188
+ *
189
+ * Unlike `getOrThunk`, in this method the `replacement` value is also
190
+ * `Optional`, meaning that this method will always return an `Optional`.
191
+ */
192
+ orThunk(thunk) {
193
+ return this.tag ? this : thunk();
194
+ }
195
+ /**
196
+ * Get the value out of the inside of the `Optional` object, throwing an
197
+ * exception if the provided `Optional` object does not contain a value.
198
+ *
199
+ * WARNING:
200
+ * You should only be using this function if you know that the `Optional`
201
+ * object **is not** empty (otherwise you're throwing exceptions in production
202
+ * code, which is bad).
203
+ *
204
+ * In tests this is more acceptable.
205
+ *
206
+ * Prefer other methods to this, such as `.each`.
207
+ */
208
+ getOrDie(message) {
209
+ if (!this.tag) {
210
+ throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
211
+ }
212
+ else {
213
+ return this.value;
214
+ }
215
+ }
216
+ // --- Interop with null and undefined ---
217
+ /**
218
+ * Creates an `Optional` value from a nullable (or undefined-able) input.
219
+ * Null, or undefined, is converted to `None`, and anything else is converted
220
+ * to `Some`.
221
+ */
222
+ static from(value) {
223
+ return isNonNullable(value) ? Optional.some(value) : Optional.none();
41
224
  }
42
- }
43
- isSome() {
44
- return this.tag;
45
- }
46
- isNone() {
47
- return !this.tag;
48
- }
49
- map(mapper) {
50
- if (this.tag) {
51
- return Optional.some(mapper(this.value));
52
- } else {
53
- return Optional.none();
225
+ /**
226
+ * Converts an `Optional` to a nullable type, by getting the value if it
227
+ * exists, or returning `null` if it does not.
228
+ */
229
+ getOrNull() {
230
+ return this.tag ? this.value : null;
54
231
  }
55
- }
56
- bind(binder) {
57
- if (this.tag) {
58
- return binder(this.value);
59
- } else {
60
- return Optional.none();
232
+ /**
233
+ * Converts an `Optional` to an undefined-able type, by getting the value if
234
+ * it exists, or returning `undefined` if it does not.
235
+ */
236
+ getOrUndefined() {
237
+ return this.value;
61
238
  }
62
- }
63
- exists(predicate) {
64
- return this.tag && predicate(this.value);
65
- }
66
- forall(predicate) {
67
- return !this.tag || predicate(this.value);
68
- }
69
- filter(predicate) {
70
- if (!this.tag || predicate(this.value)) {
71
- return this;
72
- } else {
73
- return Optional.none();
239
+ // --- Utilities ---
240
+ /**
241
+ * If the `Optional` contains a value, perform an action on that value.
242
+ * Unlike the rest of the methods on this type, `.each` has side-effects. If
243
+ * you want to transform an `Optional<T>` **into** something, then this is not
244
+ * the method for you. If you want to use an `Optional<T>` to **do**
245
+ * something, then this is the method for you - provided you're okay with not
246
+ * doing anything in the case where the `Optional` doesn't have a value inside
247
+ * it. If you're not sure whether your use-case fits into transforming
248
+ * **into** something or **doing** something, check whether it has a return
249
+ * value. If it does, you should be performing a transform.
250
+ */
251
+ each(worker) {
252
+ if (this.tag) {
253
+ worker(this.value);
254
+ }
74
255
  }
75
- }
76
- getOr(replacement) {
77
- return this.tag ? this.value : replacement;
78
- }
79
- or(replacement) {
80
- return this.tag ? this : replacement;
81
- }
82
- getOrThunk(thunk) {
83
- return this.tag ? this.value : thunk();
84
- }
85
- orThunk(thunk) {
86
- return this.tag ? this : thunk();
87
- }
88
- getOrDie(message) {
89
- if (!this.tag) {
90
- throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
91
- } else {
92
- return this.value;
256
+ /**
257
+ * Turn the `Optional` object into an array that contains all of the values
258
+ * stored inside the `Optional`. In practice, this means the output will have
259
+ * either 0 or 1 elements.
260
+ */
261
+ toArray() {
262
+ return this.tag ? [this.value] : [];
93
263
  }
94
- }
95
- static from(value) {
96
- return isNonNullable(value) ? Optional.some(value) : Optional.none();
97
- }
98
- getOrNull() {
99
- return this.tag ? this.value : null;
100
- }
101
- getOrUndefined() {
102
- return this.value;
103
- }
104
- each(worker) {
105
- if (this.tag) {
106
- worker(this.value);
264
+ /**
265
+ * Turn the `Optional` object into a string for debugging or printing. Not
266
+ * recommended for production code, but good for debugging. Also note that
267
+ * these days an `Optional` object can be logged to the console directly, and
268
+ * its inner value (if it exists) will be visible.
269
+ */
270
+ toString() {
271
+ return this.tag ? `some(${this.value})` : 'none()';
107
272
  }
108
- }
109
- toArray() {
110
- return this.tag ? [this.value] : [];
111
- }
112
- toString() {
113
- return this.tag ? `some(${ this.value })` : 'none()';
114
- }
115
273
  }
274
+ // Sneaky optimisation: every instance of Optional.none is identical, so just
275
+ // reuse the same object
116
276
  Optional.singletonNone = new Optional(false);
117
277
 
278
+ /* eslint-disable @typescript-eslint/unbound-method */
279
+ const nativeSlice = Array.prototype.slice;
118
280
  const exists = (xs, pred) => {
119
- for (let i = 0, len = xs.length; i < len; i++) {
120
- const x = xs[i];
121
- if (pred(x, i)) {
122
- return true;
281
+ for (let i = 0, len = xs.length; i < len; i++) {
282
+ const x = xs[i];
283
+ if (pred(x, i)) {
284
+ return true;
285
+ }
123
286
  }
124
- }
125
- return false;
287
+ return false;
126
288
  };
127
289
  const map$1 = (xs, f) => {
128
- const len = xs.length;
129
- const r = new Array(len);
130
- for (let i = 0; i < len; i++) {
131
- const x = xs[i];
132
- r[i] = f(x, i);
133
- }
134
- return r;
290
+ // pre-allocating array size when it's guaranteed to be known
291
+ // http://jsperf.com/push-allocated-vs-dynamic/22
292
+ const len = xs.length;
293
+ const r = new Array(len);
294
+ for (let i = 0; i < len; i++) {
295
+ const x = xs[i];
296
+ r[i] = f(x, i);
297
+ }
298
+ return r;
135
299
  };
300
+ // Unwound implementing other functions in terms of each.
301
+ // The code size is roughly the same, and it should allow for better optimisation.
302
+ // const each = function<T, U>(xs: T[], f: (x: T, i?: number, xs?: T[]) => void): void {
136
303
  const each$1 = (xs, f) => {
137
- for (let i = 0, len = xs.length; i < len; i++) {
138
- const x = xs[i];
139
- f(x, i);
140
- }
141
- };
142
-
143
- const Cell = initial => {
144
- let value = initial;
145
- const get = () => {
146
- return value;
147
- };
148
- const set = v => {
149
- value = v;
150
- };
151
- return {
152
- get,
153
- set
154
- };
155
- };
156
-
157
- const last = (fn, rate) => {
158
- let timer = null;
159
- const cancel = () => {
160
- if (!isNull(timer)) {
161
- clearTimeout(timer);
162
- timer = null;
304
+ for (let i = 0, len = xs.length; i < len; i++) {
305
+ const x = xs[i];
306
+ f(x, i);
163
307
  }
164
- };
165
- const throttle = (...args) => {
166
- cancel();
167
- timer = setTimeout(() => {
168
- timer = null;
169
- fn.apply(null, args);
170
- }, rate);
171
- };
172
- return {
173
- cancel,
174
- throttle
175
- };
176
- };
177
-
178
- const insertEmoticon = (editor, ch) => {
179
- editor.insertContent(ch);
180
308
  };
309
+ isFunction(Array.from) ? Array.from : (x) => nativeSlice.call(x);
181
310
 
311
+ // There are many variations of Object iteration that are faster than the 'for-in' style:
312
+ // http://jsperf.com/object-keys-iteration/107
313
+ //
314
+ // Use the native keys if it is available (IE9+), otherwise fall back to manually filtering
182
315
  const keys = Object.keys;
316
+ // eslint-disable-next-line @typescript-eslint/unbound-method
183
317
  const hasOwnProperty = Object.hasOwnProperty;
184
318
  const each = (obj, f) => {
185
- const props = keys(obj);
186
- for (let k = 0, len = props.length; k < len; k++) {
187
- const i = props[k];
188
- const x = obj[i];
189
- f(x, i);
190
- }
319
+ const props = keys(obj);
320
+ for (let k = 0, len = props.length; k < len; k++) {
321
+ const i = props[k];
322
+ const x = obj[i];
323
+ f(x, i);
324
+ }
191
325
  };
192
326
  const map = (obj, f) => {
193
- return tupleMap(obj, (x, i) => ({
194
- k: i,
195
- v: f(x, i)
196
- }));
327
+ return tupleMap(obj, (x, i) => ({
328
+ k: i,
329
+ v: f(x, i)
330
+ }));
197
331
  };
198
332
  const tupleMap = (obj, f) => {
199
- const r = {};
200
- each(obj, (x, i) => {
201
- const tuple = f(x, i);
202
- r[tuple.k] = tuple.v;
203
- });
204
- return r;
333
+ const r = {};
334
+ each(obj, (x, i) => {
335
+ const tuple = f(x, i);
336
+ r[tuple.k] = tuple.v;
337
+ });
338
+ return r;
205
339
  };
206
340
  const has = (obj, key) => hasOwnProperty.call(obj, key);
207
341
 
342
+ const Cell = (initial) => {
343
+ let value = initial;
344
+ const get = () => {
345
+ return value;
346
+ };
347
+ const set = (v) => {
348
+ value = v;
349
+ };
350
+ return {
351
+ get,
352
+ set
353
+ };
354
+ };
355
+
208
356
  const shallow = (old, nu) => {
209
- return nu;
357
+ return nu;
210
358
  };
211
- const baseMerge = merger => {
212
- return (...objects) => {
213
- if (objects.length === 0) {
214
- throw new Error(`Can't merge zero objects`);
215
- }
216
- const ret = {};
217
- for (let j = 0; j < objects.length; j++) {
218
- const curObject = objects[j];
219
- for (const key in curObject) {
220
- if (has(curObject, key)) {
221
- ret[key] = merger(ret[key], curObject[key]);
359
+ const baseMerge = (merger) => {
360
+ return (...objects) => {
361
+ if (objects.length === 0) {
362
+ throw new Error(`Can't merge zero objects`);
222
363
  }
223
- }
224
- }
225
- return ret;
226
- };
364
+ const ret = {};
365
+ for (let j = 0; j < objects.length; j++) {
366
+ const curObject = objects[j];
367
+ for (const key in curObject) {
368
+ if (has(curObject, key)) {
369
+ ret[key] = merger(ret[key], curObject[key]);
370
+ }
371
+ }
372
+ }
373
+ return ret;
374
+ };
227
375
  };
228
376
  const merge = baseMerge(shallow);
229
377
 
230
- const singleton = doRevoke => {
231
- const subject = Cell(Optional.none());
232
- const revoke = () => subject.get().each(doRevoke);
233
- const clear = () => {
234
- revoke();
235
- subject.set(Optional.none());
236
- };
237
- const isSet = () => subject.get().isSome();
238
- const get = () => subject.get();
239
- const set = s => {
240
- revoke();
241
- subject.set(Optional.some(s));
242
- };
243
- return {
244
- clear,
245
- isSet,
246
- get,
247
- set
248
- };
378
+ const singleton = (doRevoke) => {
379
+ const subject = Cell(Optional.none());
380
+ const revoke = () => subject.get().each(doRevoke);
381
+ const clear = () => {
382
+ revoke();
383
+ subject.set(Optional.none());
384
+ };
385
+ const isSet = () => subject.get().isSome();
386
+ const get = () => subject.get();
387
+ const set = (s) => {
388
+ revoke();
389
+ subject.set(Optional.some(s));
390
+ };
391
+ return {
392
+ clear,
393
+ isSet,
394
+ get,
395
+ set
396
+ };
249
397
  };
250
398
  const value = () => {
251
- const subject = singleton(noop);
252
- const on = f => subject.get().each(f);
253
- return {
254
- ...subject,
255
- on
256
- };
399
+ const subject = singleton(noop);
400
+ const on = (f) => subject.get().each(f);
401
+ return {
402
+ ...subject,
403
+ on
404
+ };
257
405
  };
258
406
 
259
407
  const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
260
408
  const contains = (str, substr, start = 0, end) => {
261
- const idx = str.indexOf(substr, start);
262
- if (idx !== -1) {
263
- return isUndefined(end) ? true : idx + substr.length <= end;
264
- } else {
265
- return false;
266
- }
409
+ const idx = str.indexOf(substr, start);
410
+ if (idx !== -1) {
411
+ return isUndefined(end) ? true : idx + substr.length <= end;
412
+ }
413
+ else {
414
+ return false;
415
+ }
267
416
  };
417
+ /** Does 'str' start with 'prefix'?
418
+ * Note: all strings start with the empty string.
419
+ * More formally, for all strings x, startsWith(x, "").
420
+ * This is so that for all strings x and y, startsWith(y + x, y)
421
+ */
268
422
  const startsWith = (str, prefix) => {
269
- return checkRange(str, prefix, 0);
423
+ return checkRange(str, prefix, 0);
424
+ };
425
+
426
+ // Run a function fn after rate ms. If another invocation occurs
427
+ // during the time it is waiting, reschedule the function again
428
+ // with the new arguments.
429
+ const last = (fn, rate) => {
430
+ let timer = null;
431
+ const cancel = () => {
432
+ if (!isNull(timer)) {
433
+ clearTimeout(timer);
434
+ timer = null;
435
+ }
436
+ };
437
+ const throttle = (...args) => {
438
+ cancel();
439
+ timer = setTimeout(() => {
440
+ timer = null;
441
+ fn.apply(null, args);
442
+ }, rate);
443
+ };
444
+ return {
445
+ cancel,
446
+ throttle
447
+ };
448
+ };
449
+
450
+ const insertEmoticon = (editor, ch) => {
451
+ editor.insertContent(ch);
270
452
  };
271
453
 
272
454
  var global = tinymce.util.Tools.resolve('tinymce.Resource');
273
455
 
274
456
  const DEFAULT_ID = 'tinymce.plugins.emoticons';
275
- const option = name => editor => editor.options.get(name);
457
+ const option = (name) => (editor) => editor.options.get(name);
276
458
  const register$2 = (editor, pluginUrl) => {
277
- const registerOption = editor.options.register;
278
- registerOption('emoticons_database', {
279
- processor: 'string',
280
- default: 'emojis'
281
- });
282
- registerOption('emoticons_database_url', {
283
- processor: 'string',
284
- default: `${ pluginUrl }/js/${ getEmojiDatabase(editor) }${ editor.suffix }.js`
285
- });
286
- registerOption('emoticons_database_id', {
287
- processor: 'string',
288
- default: DEFAULT_ID
289
- });
290
- registerOption('emoticons_append', {
291
- processor: 'object',
292
- default: {}
293
- });
294
- registerOption('emoticons_images_url', {
295
- processor: 'string',
296
- default: 'https://twemoji.maxcdn.com/v/13.0.1/72x72/'
297
- });
459
+ const registerOption = editor.options.register;
460
+ registerOption('emoticons_database', {
461
+ processor: 'string',
462
+ default: 'emojis'
463
+ });
464
+ registerOption('emoticons_database_url', {
465
+ processor: 'string',
466
+ default: `${pluginUrl}/js/${getEmojiDatabase(editor)}${editor.suffix}.js`
467
+ });
468
+ registerOption('emoticons_database_id', {
469
+ processor: 'string',
470
+ default: DEFAULT_ID
471
+ });
472
+ registerOption('emoticons_append', {
473
+ processor: 'object',
474
+ default: {}
475
+ });
476
+ registerOption('emoticons_images_url', {
477
+ processor: 'string',
478
+ default: 'https://cdnjs.cloudflare.com/ajax/libs/twemoji/15.1.0/72x72/'
479
+ });
298
480
  };
299
481
  const getEmojiDatabase = option('emoticons_database');
300
482
  const getEmojiDatabaseUrl = option('emoticons_database_url');
@@ -304,292 +486,324 @@
304
486
 
305
487
  const ALL_CATEGORY = 'All';
306
488
  const categoryNameMap = {
307
- symbols: 'Symbols',
308
- people: 'People',
309
- animals_and_nature: 'Animals and Nature',
310
- food_and_drink: 'Food and Drink',
311
- activity: 'Activity',
312
- travel_and_places: 'Travel and Places',
313
- objects: 'Objects',
314
- flags: 'Flags',
315
- user: 'User Defined'
489
+ symbols: 'Symbols',
490
+ people: 'People',
491
+ animals_and_nature: 'Animals and Nature',
492
+ food_and_drink: 'Food and Drink',
493
+ activity: 'Activity',
494
+ travel_and_places: 'Travel and Places',
495
+ objects: 'Objects',
496
+ flags: 'Flags',
497
+ user: 'User Defined'
316
498
  };
317
499
  const translateCategory = (categories, name) => has(categories, name) ? categories[name] : name;
318
- const getUserDefinedEmoji = editor => {
319
- const userDefinedEmoticons = getAppendedEmoji(editor);
320
- return map(userDefinedEmoticons, value => ({
321
- keywords: [],
322
- category: 'user',
323
- ...value
324
- }));
500
+ const getUserDefinedEmoji = (editor) => {
501
+ const userDefinedEmoticons = getAppendedEmoji(editor);
502
+ return map(userDefinedEmoticons, (value) =>
503
+ // Set some sane defaults for the custom emoji entry
504
+ ({ keywords: [], category: 'user', ...value }));
325
505
  };
506
+ // TODO: Consider how to share this loading across different editors
326
507
  const initDatabase = (editor, databaseUrl, databaseId) => {
327
- const categories = value();
328
- const all = value();
329
- const emojiImagesUrl = getEmojiImageUrl(editor);
330
- const getEmoji = lib => {
331
- if (startsWith(lib.char, '<img')) {
332
- return lib.char.replace(/src="([^"]+)"/, (match, url) => `src="${ emojiImagesUrl }${ url }"`);
333
- } else {
334
- return lib.char;
335
- }
336
- };
337
- const processEmojis = emojis => {
338
- const cats = {};
339
- const everything = [];
340
- each(emojis, (lib, title) => {
341
- const entry = {
342
- title,
343
- keywords: lib.keywords,
344
- char: getEmoji(lib),
345
- category: translateCategory(categoryNameMap, lib.category)
346
- };
347
- const current = cats[entry.category] !== undefined ? cats[entry.category] : [];
348
- cats[entry.category] = current.concat([entry]);
349
- everything.push(entry);
350
- });
351
- categories.set(cats);
352
- all.set(everything);
353
- };
354
- editor.on('init', () => {
355
- global.load(databaseId, databaseUrl).then(emojis => {
356
- const userEmojis = getUserDefinedEmoji(editor);
357
- processEmojis(merge(emojis, userEmojis));
358
- }, err => {
359
- console.log(`Failed to load emojis: ${ err }`);
360
- categories.set({});
361
- all.set([]);
508
+ const categories = value();
509
+ const all = value();
510
+ const emojiImagesUrl = getEmojiImageUrl(editor);
511
+ const getEmoji = (lib) => {
512
+ // Note: This is a little hacky, but the database doesn't provide a way for us to tell what sort of database is being used
513
+ if (startsWith(lib.char, '<img')) {
514
+ return lib.char.replace(/src="([^"]+)"/, (match, url) => `src="${emojiImagesUrl}${url}"`);
515
+ }
516
+ else {
517
+ return lib.char;
518
+ }
519
+ };
520
+ const processEmojis = (emojis) => {
521
+ const cats = {};
522
+ const everything = [];
523
+ each(emojis, (lib, title) => {
524
+ const entry = {
525
+ // Omitting fitzpatrick_scale
526
+ title,
527
+ keywords: lib.keywords,
528
+ char: getEmoji(lib),
529
+ category: translateCategory(categoryNameMap, lib.category)
530
+ };
531
+ const current = cats[entry.category] !== undefined ? cats[entry.category] : [];
532
+ cats[entry.category] = current.concat([entry]);
533
+ everything.push(entry);
534
+ });
535
+ categories.set(cats);
536
+ all.set(everything);
537
+ };
538
+ editor.on('init', () => {
539
+ global.load(databaseId, databaseUrl).then((emojis) => {
540
+ const userEmojis = getUserDefinedEmoji(editor);
541
+ processEmojis(merge(emojis, userEmojis));
542
+ }, (err) => {
543
+ // eslint-disable-next-line no-console
544
+ console.log(`Failed to load emojis: ${err}`);
545
+ categories.set({});
546
+ all.set([]);
547
+ });
362
548
  });
363
- });
364
- const listCategory = category => {
365
- if (category === ALL_CATEGORY) {
366
- return listAll();
367
- }
368
- return categories.get().bind(cats => Optional.from(cats[category])).getOr([]);
369
- };
370
- const listAll = () => all.get().getOr([]);
371
- const listCategories = () => [ALL_CATEGORY].concat(keys(categories.get().getOr({})));
372
- const waitForLoad = () => {
373
- if (hasLoaded()) {
374
- return Promise.resolve(true);
375
- } else {
376
- return new Promise((resolve, reject) => {
377
- let numRetries = 15;
378
- const interval = setInterval(() => {
379
- if (hasLoaded()) {
380
- clearInterval(interval);
381
- resolve(true);
382
- } else {
383
- numRetries--;
384
- if (numRetries < 0) {
385
- console.log('Could not load emojis from url: ' + databaseUrl);
386
- clearInterval(interval);
387
- reject(false);
388
- }
389
- }
390
- }, 100);
391
- });
392
- }
393
- };
394
- const hasLoaded = () => categories.isSet() && all.isSet();
395
- return {
396
- listCategories,
397
- hasLoaded,
398
- waitForLoad,
399
- listAll,
400
- listCategory
401
- };
549
+ const listCategory = (category) => {
550
+ if (category === ALL_CATEGORY) {
551
+ return listAll();
552
+ }
553
+ return categories.get().bind((cats) => Optional.from(cats[category])).getOr([]);
554
+ };
555
+ const listAll = () => all.get().getOr([]);
556
+ const listCategories = () =>
557
+ // TODO: Category key order should be adjusted to match the standard
558
+ [ALL_CATEGORY].concat(keys(categories.get().getOr({})));
559
+ const waitForLoad = () => {
560
+ if (hasLoaded()) {
561
+ return Promise.resolve(true);
562
+ }
563
+ else {
564
+ return new Promise((resolve, reject) => {
565
+ let numRetries = 15;
566
+ const interval = setInterval(() => {
567
+ if (hasLoaded()) {
568
+ clearInterval(interval);
569
+ resolve(true);
570
+ }
571
+ else {
572
+ numRetries--;
573
+ if (numRetries < 0) {
574
+ // eslint-disable-next-line no-console
575
+ console.log('Could not load emojis from url: ' + databaseUrl);
576
+ clearInterval(interval);
577
+ reject(false);
578
+ }
579
+ }
580
+ }, 100);
581
+ });
582
+ }
583
+ };
584
+ const hasLoaded = () => categories.isSet() && all.isSet();
585
+ return {
586
+ listCategories,
587
+ hasLoaded,
588
+ waitForLoad,
589
+ listAll,
590
+ listCategory
591
+ };
402
592
  };
403
593
 
404
- const emojiMatches = (emoji, lowerCasePattern) => contains(emoji.title.toLowerCase(), lowerCasePattern) || exists(emoji.keywords, k => contains(k.toLowerCase(), lowerCasePattern));
594
+ const emojiMatches = (emoji, lowerCasePattern) => contains(emoji.title.toLowerCase(), lowerCasePattern) ||
595
+ exists(emoji.keywords, (k) => contains(k.toLowerCase(), lowerCasePattern));
405
596
  const emojisFrom = (list, pattern, maxResults) => {
406
- const matches = [];
407
- const lowerCasePattern = pattern.toLowerCase();
408
- const reachedLimit = maxResults.fold(() => never, max => size => size >= max);
409
- for (let i = 0; i < list.length; i++) {
410
- if (pattern.length === 0 || emojiMatches(list[i], lowerCasePattern)) {
411
- matches.push({
412
- value: list[i].char,
413
- text: list[i].title,
414
- icon: list[i].char
415
- });
416
- if (reachedLimit(matches.length)) {
417
- break;
418
- }
597
+ const matches = [];
598
+ const lowerCasePattern = pattern.toLowerCase();
599
+ const reachedLimit = maxResults.fold(() => never, (max) => (size) => size >= max);
600
+ for (let i = 0; i < list.length; i++) {
601
+ // TODO: more intelligent search by showing title matches at the top, keyword matches after that (use two arrays and concat at the end)
602
+ if (pattern.length === 0 || emojiMatches(list[i], lowerCasePattern)) {
603
+ matches.push({
604
+ value: list[i].char,
605
+ text: list[i].title,
606
+ icon: list[i].char
607
+ });
608
+ if (reachedLimit(matches.length)) {
609
+ break;
610
+ }
611
+ }
419
612
  }
420
- }
421
- return matches;
613
+ return matches;
422
614
  };
423
615
 
424
616
  const patternName = 'pattern';
425
617
  const open = (editor, database) => {
426
- const initialState = {
427
- pattern: '',
428
- results: emojisFrom(database.listAll(), '', Optional.some(300))
429
- };
430
- const currentTab = Cell(ALL_CATEGORY);
431
- const scan = dialogApi => {
432
- const dialogData = dialogApi.getData();
433
- const category = currentTab.get();
434
- const candidates = database.listCategory(category);
435
- const results = emojisFrom(candidates, dialogData[patternName], category === ALL_CATEGORY ? Optional.some(300) : Optional.none());
436
- dialogApi.setData({ results });
437
- };
438
- const updateFilter = last(dialogApi => {
439
- scan(dialogApi);
440
- }, 200);
441
- const searchField = {
442
- label: 'Search',
443
- type: 'input',
444
- name: patternName
445
- };
446
- const resultsField = {
447
- type: 'collection',
448
- name: 'results'
449
- };
450
- const getInitialState = () => {
451
- const body = {
452
- type: 'tabpanel',
453
- tabs: map$1(database.listCategories(), cat => ({
454
- title: cat,
455
- name: cat,
456
- items: [
457
- searchField,
458
- resultsField
459
- ]
460
- }))
618
+ const initialState = {
619
+ pattern: '',
620
+ results: emojisFrom(database.listAll(), '', Optional.some(300))
461
621
  };
462
- return {
463
- title: 'Emojis',
464
- size: 'normal',
465
- body,
466
- initialData: initialState,
467
- onTabChange: (dialogApi, details) => {
468
- currentTab.set(details.newTabName);
469
- updateFilter.throttle(dialogApi);
470
- },
471
- onChange: updateFilter.throttle,
472
- onAction: (dialogApi, actionData) => {
473
- if (actionData.name === 'results') {
474
- insertEmoticon(editor, actionData.value);
475
- dialogApi.close();
476
- }
477
- },
478
- buttons: [{
479
- type: 'cancel',
480
- text: 'Close',
481
- primary: true
482
- }]
622
+ const currentTab = Cell(ALL_CATEGORY);
623
+ const scan = (dialogApi) => {
624
+ const dialogData = dialogApi.getData();
625
+ const category = currentTab.get();
626
+ const candidates = database.listCategory(category);
627
+ const results = emojisFrom(candidates, dialogData[patternName], category === ALL_CATEGORY ? Optional.some(300) : Optional.none());
628
+ dialogApi.setData({
629
+ results
630
+ });
483
631
  };
484
- };
485
- const dialogApi = editor.windowManager.open(getInitialState());
486
- dialogApi.focus(patternName);
487
- if (!database.hasLoaded()) {
488
- dialogApi.block('Loading emojis...');
489
- database.waitForLoad().then(() => {
490
- dialogApi.redial(getInitialState());
491
- updateFilter.throttle(dialogApi);
492
- dialogApi.focus(patternName);
493
- dialogApi.unblock();
494
- }).catch(_err => {
495
- dialogApi.redial({
496
- title: 'Emojis',
497
- body: {
498
- type: 'panel',
499
- items: [{
500
- type: 'alertbanner',
501
- level: 'error',
502
- icon: 'warning',
503
- text: 'Could not load emojis'
504
- }]
505
- },
506
- buttons: [{
507
- type: 'cancel',
508
- text: 'Close',
509
- primary: true
510
- }],
511
- initialData: {
512
- pattern: '',
513
- results: []
514
- }
515
- });
516
- dialogApi.focus(patternName);
517
- dialogApi.unblock();
518
- });
519
- }
632
+ const updateFilter = last((dialogApi) => {
633
+ scan(dialogApi);
634
+ }, 200);
635
+ const searchField = {
636
+ label: 'Search',
637
+ type: 'input',
638
+ name: patternName
639
+ };
640
+ const resultsField = {
641
+ type: 'collection',
642
+ name: 'results'
643
+ // TODO TINY-3229 implement collection columns properly
644
+ // columns: 'auto'
645
+ };
646
+ const getInitialState = () => {
647
+ const body = {
648
+ type: 'tabpanel',
649
+ // All tabs have the same fields.
650
+ tabs: map$1(database.listCategories(), (cat) => ({
651
+ title: cat,
652
+ name: cat,
653
+ items: [searchField, resultsField]
654
+ }))
655
+ };
656
+ return {
657
+ title: 'Emojis',
658
+ size: 'normal',
659
+ body,
660
+ initialData: initialState,
661
+ onTabChange: (dialogApi, details) => {
662
+ currentTab.set(details.newTabName);
663
+ updateFilter.throttle(dialogApi);
664
+ },
665
+ onChange: updateFilter.throttle,
666
+ onAction: (dialogApi, actionData) => {
667
+ if (actionData.name === 'results') {
668
+ insertEmoticon(editor, actionData.value);
669
+ dialogApi.close();
670
+ }
671
+ },
672
+ buttons: [
673
+ {
674
+ type: 'cancel',
675
+ text: 'Close',
676
+ primary: true
677
+ }
678
+ ]
679
+ };
680
+ };
681
+ const dialogApi = editor.windowManager.open(getInitialState());
682
+ dialogApi.focus(patternName);
683
+ if (!database.hasLoaded()) {
684
+ dialogApi.block('Loading emojis...');
685
+ database.waitForLoad().then(() => {
686
+ dialogApi.redial(getInitialState());
687
+ updateFilter.throttle(dialogApi);
688
+ dialogApi.focus(patternName);
689
+ dialogApi.unblock();
690
+ }).catch((_err) => {
691
+ dialogApi.redial({
692
+ title: 'Emojis',
693
+ body: {
694
+ type: 'panel',
695
+ items: [
696
+ {
697
+ type: 'alertbanner',
698
+ level: 'error',
699
+ icon: 'warning',
700
+ text: 'Could not load emojis'
701
+ }
702
+ ]
703
+ },
704
+ buttons: [
705
+ {
706
+ type: 'cancel',
707
+ text: 'Close',
708
+ primary: true
709
+ }
710
+ ],
711
+ initialData: {
712
+ pattern: '',
713
+ results: []
714
+ }
715
+ });
716
+ dialogApi.focus(patternName);
717
+ dialogApi.unblock();
718
+ });
719
+ }
520
720
  };
521
721
 
522
722
  const register$1 = (editor, database) => {
523
- editor.addCommand('mceEmoticons', () => open(editor, database));
723
+ editor.addCommand('mceEmoticons', () => open(editor, database));
524
724
  };
525
725
 
526
- const setup = editor => {
527
- editor.on('PreInit', () => {
528
- editor.parser.addAttributeFilter('data-emoticon', nodes => {
529
- each$1(nodes, node => {
530
- node.attr('data-mce-resize', 'false');
531
- node.attr('data-mce-placeholder', '1');
532
- });
726
+ const setup = (editor) => {
727
+ editor.on('PreInit', () => {
728
+ editor.parser.addAttributeFilter('data-emoticon', (nodes) => {
729
+ each$1(nodes, (node) => {
730
+ node.attr('data-mce-resize', 'false');
731
+ node.attr('data-mce-placeholder', '1');
732
+ });
733
+ });
533
734
  });
534
- });
535
735
  };
536
736
 
537
737
  const init = (editor, database) => {
538
- editor.ui.registry.addAutocompleter('emoticons', {
539
- trigger: ':',
540
- columns: 'auto',
541
- minChars: 2,
542
- fetch: (pattern, maxResults) => database.waitForLoad().then(() => {
543
- const candidates = database.listAll();
544
- return emojisFrom(candidates, pattern, Optional.some(maxResults));
545
- }),
546
- onAction: (autocompleteApi, rng, value) => {
547
- editor.selection.setRng(rng);
548
- editor.insertContent(value);
549
- autocompleteApi.hide();
550
- }
551
- });
738
+ editor.ui.registry.addAutocompleter('emoticons', {
739
+ trigger: ':',
740
+ columns: 'auto',
741
+ minChars: 2,
742
+ fetch: (pattern, maxResults) => database.waitForLoad().then(() => {
743
+ const candidates = database.listAll();
744
+ return emojisFrom(candidates, pattern, Optional.some(maxResults));
745
+ }),
746
+ onAction: (autocompleteApi, rng, value) => {
747
+ editor.selection.setRng(rng);
748
+ editor.insertContent(value);
749
+ autocompleteApi.hide();
750
+ }
751
+ });
552
752
  };
553
753
 
554
- const onSetupEditable = editor => api => {
555
- const nodeChanged = () => {
556
- api.setEnabled(editor.selection.isEditable());
557
- };
558
- editor.on('NodeChange', nodeChanged);
559
- nodeChanged();
560
- return () => {
561
- editor.off('NodeChange', nodeChanged);
562
- };
754
+ const onSetupEditable = (editor) => (api) => {
755
+ const nodeChanged = () => {
756
+ api.setEnabled(editor.selection.isEditable());
757
+ };
758
+ editor.on('NodeChange', nodeChanged);
759
+ nodeChanged();
760
+ return () => {
761
+ editor.off('NodeChange', nodeChanged);
762
+ };
563
763
  };
564
- const register = editor => {
565
- const onAction = () => editor.execCommand('mceEmoticons');
566
- editor.ui.registry.addButton('emoticons', {
567
- tooltip: 'Emojis',
568
- icon: 'emoji',
569
- onAction,
570
- onSetup: onSetupEditable(editor)
571
- });
572
- editor.ui.registry.addMenuItem('emoticons', {
573
- text: 'Emojis...',
574
- icon: 'emoji',
575
- onAction,
576
- onSetup: onSetupEditable(editor)
577
- });
764
+ const register = (editor) => {
765
+ const onAction = () => editor.execCommand('mceEmoticons');
766
+ editor.ui.registry.addButton('emoticons', {
767
+ tooltip: 'Emojis',
768
+ icon: 'emoji',
769
+ onAction,
770
+ onSetup: onSetupEditable(editor)
771
+ });
772
+ editor.ui.registry.addMenuItem('emoticons', {
773
+ text: 'Emojis...',
774
+ icon: 'emoji',
775
+ onAction,
776
+ onSetup: onSetupEditable(editor)
777
+ });
578
778
  };
579
779
 
780
+ /**
781
+ * This class contains all core logic for the emoticons plugin.
782
+ *
783
+ * @class tinymce.emoticons.Plugin
784
+ * @private
785
+ */
580
786
  var Plugin = () => {
581
- global$1.add('emoticons', (editor, pluginUrl) => {
582
- register$2(editor, pluginUrl);
583
- const databaseUrl = getEmojiDatabaseUrl(editor);
584
- const databaseId = getEmojiDatabaseId(editor);
585
- const database = initDatabase(editor, databaseUrl, databaseId);
586
- register$1(editor, database);
587
- register(editor);
588
- init(editor, database);
589
- setup(editor);
590
- });
787
+ global$1.add('emoticons', (editor, pluginUrl) => {
788
+ register$2(editor, pluginUrl);
789
+ const databaseUrl = getEmojiDatabaseUrl(editor);
790
+ const databaseId = getEmojiDatabaseId(editor);
791
+ const database = initDatabase(editor, databaseUrl, databaseId);
792
+ register$1(editor, database);
793
+ register(editor);
794
+ init(editor, database);
795
+ setup(editor);
796
+ return {
797
+ getAllEmojis: () => database.waitForLoad().then(() => database.listAll())
798
+ };
799
+ });
591
800
  };
592
801
 
593
802
  Plugin();
803
+ /** *****
804
+ * DO NOT EXPORT ANYTHING
805
+ *
806
+ * IF YOU DO ROLLUP WILL LEAVE A GLOBAL ON THE PAGE
807
+ *******/
594
808
 
595
809
  })();