@webitel/ui-sdk 26.8.118 → 26.8.120

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 (37) hide show
  1. package/dist/{clients-DWcx-Mfk.js → clients-CwGTZ_pb.js} +1502 -170
  2. package/dist/{components-CeOlovz8.js → components-Bl2fDyms.js} +933 -948
  3. package/dist/ui-sdk.css +1 -1
  4. package/dist/ui-sdk.js +1 -1
  5. package/dist/ui-sdk.umd.cjs +2158 -2119
  6. package/dist/{wt-chat-emoji-v9gpIuHe.js → wt-chat-emoji-CQ-ZUYcm.js} +1 -1
  7. package/dist/{wt-display-chip-items-Bob7miL_.js → wt-display-chip-items-yuaxgXrU.js} +1 -1
  8. package/dist/wt-label-CiLpqe61.js +34 -0
  9. package/dist/wt-rich-text-editor-DyGnGabB.js +130 -0
  10. package/dist/{wt-send-message-popup-9O69XY0L.js → wt-send-message-popup-Ig3Uq6So.js} +2 -2
  11. package/dist/{wt-type-extension-value-input-55YmFcBp.js → wt-type-extension-value-input-B4fjVEic.js} +2 -2
  12. package/dist/{wt-vidstack-player-ETPSioGH.js → wt-vidstack-player-DitE8XQx.js} +1 -1
  13. package/package.json +3 -1
  14. package/src/components/index.js +14 -0
  15. package/src/components/on-demand/wt-rich-text-editor/__tests__/WtRichTextEditor.compat.spec.js +127 -0
  16. package/src/components/on-demand/wt-rich-text-editor/__tests__/WtRichTextEditor.spec.js +157 -0
  17. package/src/components/on-demand/wt-rich-text-editor/__tests__/loadTinyMce.spec.js +54 -0
  18. package/src/components/on-demand/wt-rich-text-editor/_internals/loadTinyMce.ts +31 -0
  19. package/src/components/on-demand/wt-rich-text-editor/_internals/wt-rich-text-editor-skeleton.vue +54 -0
  20. package/src/components/on-demand/wt-rich-text-editor/wt-rich-text-editor.vue +223 -0
  21. package/types/.tsbuildinfo +1 -1
  22. package/types/components/index.d.ts +7 -0
  23. package/types/components/on-demand/wt-call-media-action/wt-call-media-action.vue.d.ts +2 -2
  24. package/types/components/on-demand/wt-rich-text-editor/__tests__/WtRichTextEditor.compat.spec.d.ts +1 -0
  25. package/types/components/on-demand/wt-rich-text-editor/__tests__/WtRichTextEditor.spec.d.ts +1 -0
  26. package/types/components/on-demand/wt-rich-text-editor/__tests__/loadTinyMce.spec.d.ts +1 -0
  27. package/types/components/on-demand/wt-rich-text-editor/_internals/loadTinyMce.d.ts +1 -0
  28. package/types/components/on-demand/wt-rich-text-editor/_internals/wt-rich-text-editor-skeleton.vue.d.ts +3 -0
  29. package/types/components/on-demand/wt-rich-text-editor/wt-rich-text-editor.vue.d.ts +65 -0
  30. package/types/components/transitions/cases/wt-replace-transition.vue.d.ts +1 -1
  31. package/types/components/wt-datepicker/wt-datepicker.vue.d.ts +2 -2
  32. package/types/components/wt-input-text/wt-input-text.vue.d.ts +1 -1
  33. package/types/components/wt-player/wt-player.vue.d.ts +1 -1
  34. package/types/components/wt-search-bar/wt-search-bar.vue.d.ts +2 -2
  35. package/types/components/wt-table/wt-table.vue.d.ts +1 -1
  36. package/types/components/wt-textarea/wt-textarea.vue.d.ts +1 -1
  37. package/types/components/wt-time-input/wt-time-input.vue.d.ts +1 -1
@@ -0,0 +1,54 @@
1
+ <template>
2
+ <!-- shown while the editor chunk (TinyMCE) downloads -->
3
+ <div
4
+ aria-busy="true"
5
+ class="wt-rich-text-editor-skeleton"
6
+ >
7
+ <div class="wt-rich-text-editor-skeleton__toolbar" />
8
+ <div class="wt-rich-text-editor-skeleton__body">
9
+ <div class="wt-rich-text-editor-skeleton__line" />
10
+ <div class="wt-rich-text-editor-skeleton__line" />
11
+ <div class="wt-rich-text-editor-skeleton__line wt-rich-text-editor-skeleton__line--short" />
12
+ </div>
13
+ </div>
14
+ </template>
15
+
16
+ <style scoped>
17
+ .wt-rich-text-editor-skeleton {
18
+ display: flex;
19
+ flex-direction: column;
20
+ height: 200px;
21
+ cursor: progress;
22
+ border-radius: var(--border-radius);
23
+ box-shadow: var(--elevation-4);
24
+ }
25
+
26
+ .wt-rich-text-editor-skeleton__toolbar {
27
+ height: 40px;
28
+ box-shadow: var(--elevation-2);
29
+ }
30
+
31
+ .wt-rich-text-editor-skeleton__body {
32
+ display: flex;
33
+ flex-direction: column;
34
+ gap: var(--spacing-xs);
35
+ padding: var(--spacing-sm);
36
+ }
37
+
38
+ .wt-rich-text-editor-skeleton__line {
39
+ height: 12px;
40
+ border-radius: var(--border-radius);
41
+ background: var(--skeleton-color, var(--dp-20-surface-color));
42
+ animation: wt-rich-text-editor-skeleton-pulse 1.2s ease-in-out infinite;
43
+ }
44
+
45
+ .wt-rich-text-editor-skeleton__line--short {
46
+ width: 60%;
47
+ }
48
+
49
+ @keyframes wt-rich-text-editor-skeleton-pulse {
50
+ 50% {
51
+ opacity: 0.5;
52
+ }
53
+ }
54
+ </style>
@@ -0,0 +1,223 @@
1
+ <template>
2
+ <div class="wt-rich-text-editor">
3
+ <wt-label
4
+ v-if="label || $slots.label"
5
+ :disabled="disabled"
6
+ :for="editorId"
7
+ v-bind="labelProps"
8
+ >
9
+ <!-- @slot Custom editor label -->
10
+ <slot
11
+ name="label"
12
+ v-bind="{ label }"
13
+ >
14
+ {{ label }}
15
+ </slot>
16
+ </wt-label>
17
+ <!-- tinymce-vue falls back to Tiny's cloud CDN when window.tinymce is
18
+ missing, so the editor only mounts once the self-hosted copy is in -->
19
+ <tiny-mce-editor
20
+ v-if="isTinyMceLoaded"
21
+ :id="editorId"
22
+ v-model="model"
23
+ :disabled="disabled"
24
+ :init="init"
25
+ :output-format="output"
26
+ :plugins="editorPlugins"
27
+ :toolbar="editorToolbar"
28
+ license-key="gpl"
29
+ @init="handleInit"
30
+ />
31
+ <wt-rich-text-editor-skeleton v-else />
32
+ </div>
33
+ </template>
34
+
35
+ <script setup lang="ts">
36
+ /**
37
+ * TinyMCE, self-hosted, loads with this component only: `components/index.js`
38
+ * registers it through `defineAsyncComponent`, and TinyMCE itself is loaded
39
+ * by `loadTinyMce` (in order) once the component is created.
40
+ */
41
+ import TinyMceVueEditor from '@tinymce/tinymce-vue';
42
+ import type { Editor as TinyMceInstance } from 'tinymce';
43
+ import { computed, onBeforeUnmount, ref, useId } from 'vue';
44
+
45
+ import WtLabel from '../../wt-label/wt-label.vue';
46
+ import { loadTinyMce } from './_internals/loadTinyMce';
47
+ import WtRichTextEditorSkeleton from './_internals/wt-rich-text-editor-skeleton.vue';
48
+
49
+ /**
50
+ * tinymce-vue binds the model only when it finds `onUpdate:modelValue` in its
51
+ * attrs. Apps on the @vue/compat runtime (cc-workspaces) rewrite `v-model` on
52
+ * any component not marked as Vue 3 into the Vue 2 `value` / `input` pair, so
53
+ * the listener never arrives and edits are lost (WTEL-4477). Marking the
54
+ * editor as Vue 3 keeps `v-model` intact; plain Vue 3 ignores the option.
55
+ */
56
+ // A copy rather than `extends`: `extends` does not carry `setup()`, which is
57
+ // all tinymce-vue's Editor is.
58
+ const TinyMceEditor = {
59
+ ...TinyMceVueEditor,
60
+ name: 'TinyMceEditor',
61
+ compatConfig: {
62
+ MODE: 3,
63
+ },
64
+ } as typeof TinyMceVueEditor;
65
+
66
+ type RichTextOutput = 'html' | 'text';
67
+
68
+ interface Props {
69
+ /**
70
+ * Editor label
71
+ */
72
+ label?: string;
73
+ /**
74
+ * Object with props, passed down to wt-label as props
75
+ */
76
+ labelProps?: Record<string, unknown>;
77
+ /**
78
+ * `html` keeps the formatting toolbar; `text` edits (and emits) plain text
79
+ * @values html, text
80
+ */
81
+ output?: RichTextOutput;
82
+ /**
83
+ * Editor height, in px
84
+ */
85
+ height?: number | string;
86
+ disabled?: boolean;
87
+ /**
88
+ * Placeholder shown while the editor is empty
89
+ */
90
+ placeholder?: string;
91
+ /**
92
+ * TinyMCE toolbar, replacing the default for `output`
93
+ */
94
+ toolbar?: string;
95
+ /**
96
+ * TinyMCE plugins, replacing the default for `output`. A plugin outside
97
+ * the bundled set (advlist, emoticons, fullscreen, image, link, lists,
98
+ * table) must be imported by the app.
99
+ */
100
+ plugins?: string[];
101
+ }
102
+
103
+ // Vue 3 semantics on the @vue/compat runtime too (cc-workspaces): otherwise
104
+ // compat rewrites this component's own `v-model` to `value` / `input` and
105
+ // defineModel below never sees it.
106
+ defineOptions({
107
+ compatConfig: {
108
+ MODE: 3,
109
+ },
110
+ });
111
+
112
+ const props = withDefaults(defineProps<Props>(), {
113
+ output: 'html',
114
+ height: 300,
115
+ });
116
+
117
+ /**
118
+ * @model modelValue — the content, as `output` formats it
119
+ */
120
+ const model = defineModel<string>();
121
+
122
+ const editorId = useId();
123
+
124
+ const isTinyMceLoaded = ref(false);
125
+ loadTinyMce().then(() => {
126
+ isTinyMceLoaded.value = true;
127
+ });
128
+
129
+ const HTML_PLUGINS = [
130
+ 'advlist',
131
+ 'emoticons',
132
+ 'fullscreen',
133
+ 'image',
134
+ 'link',
135
+ 'lists',
136
+ 'table',
137
+ ];
138
+
139
+ const HTML_TOOLBAR = [
140
+ 'undo redo',
141
+ 'bold italic underline strikethrough',
142
+ 'fullscreen',
143
+ 'fontfamily fontsize',
144
+ 'alignleft aligncenter alignright alignjustify',
145
+ 'numlist bullist',
146
+ 'forecolor backcolor removeformat',
147
+ 'emoticons image link table',
148
+ ].join(' | ');
149
+
150
+ const isHtml = computed(() => props.output === 'html');
151
+
152
+ const editorPlugins = computed(
153
+ () => props.plugins ?? (isHtml.value ? HTML_PLUGINS : []),
154
+ );
155
+ const editorToolbar = computed(
156
+ () => props.toolbar ?? (isHtml.value ? HTML_TOOLBAR : 'undo redo'),
157
+ );
158
+
159
+ // The editable area lives in an iframe, out of reach of the app's CSS
160
+ // variables, so its colours are read from the page and handed over.
161
+ function readColors() {
162
+ const styles = getComputedStyle(document.documentElement);
163
+ return {
164
+ backgroundColor: styles.getPropertyValue('--content-wrapper-color').trim(),
165
+ color: styles.getPropertyValue('--wt-text-field-text-color').trim(),
166
+ };
167
+ }
168
+
169
+ const init = computed(() => {
170
+ const { backgroundColor, color } = readColors();
171
+ return {
172
+ height: Number(props.height),
173
+ menubar: false,
174
+ statusbar: isHtml.value,
175
+ toolbar_mode: 'sliding' as const,
176
+ toolbar_sticky: true,
177
+ placeholder: props.placeholder,
178
+ // the skin CSS is imported above; content styles are set here
179
+ skin: false,
180
+ content_css: false,
181
+ content_style: `body { background-color: ${backgroundColor}; color: ${color}; }`,
182
+ };
183
+ });
184
+
185
+ let editor: TinyMceInstance | null = null;
186
+
187
+ // The app switches themes by toggling `theme--dark` on <html>; follow it.
188
+ const themeObserver = new MutationObserver(() => {
189
+ if (!editor?.getBody()) return;
190
+ editor.dom.setStyles(editor.getBody(), readColors());
191
+ });
192
+
193
+ function handleInit(_event: unknown, initialized: TinyMceInstance) {
194
+ editor = initialized;
195
+ themeObserver.observe(document.documentElement, {
196
+ attributes: true,
197
+ attributeFilter: [
198
+ 'class',
199
+ ],
200
+ });
201
+ }
202
+
203
+ onBeforeUnmount(() => {
204
+ themeObserver.disconnect();
205
+ editor = null;
206
+ });
207
+ </script>
208
+
209
+ <style scoped>
210
+ .wt-rich-text-editor :deep(.tox-toolbar__primary),
211
+ .wt-rich-text-editor :deep(.tox-editor-header) {
212
+ background-color: var(--content-wrapper-color);
213
+ }
214
+
215
+ .wt-rich-text-editor :deep(.tox-tbtn svg) {
216
+ fill: var(--icon-active-color);
217
+ }
218
+
219
+ .wt-rich-text-editor :deep(.tox-tbtn--disabled svg),
220
+ .wt-rich-text-editor :deep(.tox-tbtn--disabled:hover svg) {
221
+ fill: var(--icon-color);
222
+ }
223
+ </style>