myrta-ui 17.1.3 → 17.1.5
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.
- package/esm2022/lib/components/form/editor/editor.component.mjs +50 -3
- package/esm2022/lib/components/gallery/components/gallery-item/gallery-item.component.mjs +2 -2
- package/esm2022/lib/services/save-store/auto-save.store.mjs +43 -58
- package/fesm2022/myrta-ui.mjs +92 -60
- package/fesm2022/myrta-ui.mjs.map +1 -1
- package/lib/components/form/editor/editor.component.d.ts +4 -0
- package/lib/services/save-store/auto-save.store.d.ts +8 -8
- package/package.json +1 -1
package/fesm2022/myrta-ui.mjs
CHANGED
|
@@ -35,6 +35,7 @@ import 'jodit/esm/plugins/line-height/line-height.js';
|
|
|
35
35
|
import 'jodit/esm/plugins/indent/indent.js';
|
|
36
36
|
import 'jodit/esm/plugins/video/video.js';
|
|
37
37
|
import 'jodit/esm/plugins/search/search.js';
|
|
38
|
+
import 'jodit/esm/plugins/resizer/resizer.js';
|
|
38
39
|
import * as i3 from 'ngx-jodit';
|
|
39
40
|
import { NgxJoditComponent } from 'ngx-jodit';
|
|
40
41
|
import 'ace-builds/src-min-noconflict/ace.js';
|
|
@@ -3072,59 +3073,15 @@ class MrxFormValidator {
|
|
|
3072
3073
|
}
|
|
3073
3074
|
|
|
3074
3075
|
class AutoSaveStore {
|
|
3075
|
-
// Основной сигнал для состояния
|
|
3076
3076
|
state = signal({ fields: [] });
|
|
3077
|
-
// Хранилище подписок для каждого поля
|
|
3078
3077
|
subscriptions = {};
|
|
3079
|
-
// Публичные computed сигналы для доступа к данным
|
|
3080
3078
|
fields = computed(() => this.state().fields);
|
|
3081
|
-
// Получить поле по id
|
|
3082
3079
|
getField(id) {
|
|
3083
3080
|
return computed(() => this.state().fields.find(field => field.id === id));
|
|
3084
3081
|
}
|
|
3085
|
-
// Добавить или обновить поле
|
|
3086
|
-
upsertField(field) {
|
|
3087
|
-
this.state.update(current => {
|
|
3088
|
-
const exists = current.fields.some(f => f.id === field.id);
|
|
3089
|
-
if (exists) {
|
|
3090
|
-
return {
|
|
3091
|
-
fields: current.fields.map(f => f.id === field.id ? { ...f, ...field } : f)
|
|
3092
|
-
};
|
|
3093
|
-
}
|
|
3094
|
-
return {
|
|
3095
|
-
fields: [...current.fields, field]
|
|
3096
|
-
};
|
|
3097
|
-
});
|
|
3098
|
-
}
|
|
3099
|
-
// Удалить поле
|
|
3100
|
-
removeField(id) {
|
|
3101
|
-
this.state.update(current => ({
|
|
3102
|
-
fields: current.fields.filter(field => field.id !== id)
|
|
3103
|
-
}));
|
|
3104
|
-
}
|
|
3105
|
-
// Очистить все поля
|
|
3106
|
-
clear() {
|
|
3107
|
-
this.state.set({ fields: [] });
|
|
3108
|
-
}
|
|
3109
|
-
// Очистить подписку для поля
|
|
3110
|
-
clearSubscription(id) {
|
|
3111
|
-
if (this.subscriptions[id]) {
|
|
3112
|
-
this.subscriptions[id].unsubscribe();
|
|
3113
|
-
delete this.subscriptions[id];
|
|
3114
|
-
}
|
|
3115
|
-
}
|
|
3116
|
-
// Очистить все подписки
|
|
3117
|
-
clearAllSubscriptions() {
|
|
3118
|
-
Object.keys(this.subscriptions).forEach(key => {
|
|
3119
|
-
this.subscriptions[key].unsubscribe();
|
|
3120
|
-
delete this.subscriptions[key];
|
|
3121
|
-
});
|
|
3122
|
-
}
|
|
3123
|
-
// Добавить id в массив fields
|
|
3124
3082
|
addId(id, groupId) {
|
|
3125
3083
|
this.upsertField({ id, state: 'stopped', groupId });
|
|
3126
3084
|
}
|
|
3127
|
-
// Запустить сохранение для всех полей
|
|
3128
3085
|
start() {
|
|
3129
3086
|
this.clearAllSubscriptions();
|
|
3130
3087
|
this.state.update(current => ({
|
|
@@ -3134,26 +3091,22 @@ class AutoSaveStore {
|
|
|
3134
3091
|
}))
|
|
3135
3092
|
}));
|
|
3136
3093
|
}
|
|
3137
|
-
// Запустить сохранение для определенного id
|
|
3138
3094
|
startFor(id) {
|
|
3139
3095
|
this.clearSubscription(id);
|
|
3140
3096
|
this.state.update(current => ({
|
|
3141
3097
|
fields: current.fields.map(field => field.id === id
|
|
3142
|
-
? { ...field, state:
|
|
3143
|
-
: field)
|
|
3098
|
+
? { ...field, state: 'saving' }
|
|
3099
|
+
: { ...field, state: field.state === 'saved' ? 'stopped' : field.state })
|
|
3144
3100
|
}));
|
|
3145
3101
|
}
|
|
3146
|
-
// Остановить сохранение для всех полей и очистить массив
|
|
3147
3102
|
stop() {
|
|
3148
3103
|
this.clearAllSubscriptions();
|
|
3149
3104
|
this.clear();
|
|
3150
3105
|
}
|
|
3151
|
-
// Остановить сохранение для определенного id и удалить его
|
|
3152
3106
|
stopFor(id) {
|
|
3153
3107
|
this.clearSubscription(id);
|
|
3154
3108
|
this.removeField(id);
|
|
3155
3109
|
}
|
|
3156
|
-
// Успешное сохранение для всех полей
|
|
3157
3110
|
success() {
|
|
3158
3111
|
this.clearAllSubscriptions();
|
|
3159
3112
|
this.state.update(current => ({
|
|
@@ -3161,12 +3114,10 @@ class AutoSaveStore {
|
|
|
3161
3114
|
...field, state: 'saved'
|
|
3162
3115
|
}))
|
|
3163
3116
|
}));
|
|
3164
|
-
// Создаем подписку для каждого поля
|
|
3165
3117
|
this.state().fields.forEach(field => {
|
|
3166
3118
|
this.subscriptions[field.id] = timer(3000).subscribe(() => this.stop());
|
|
3167
3119
|
});
|
|
3168
3120
|
}
|
|
3169
|
-
// Успешное сохранение для определенного id
|
|
3170
3121
|
successFor(id) {
|
|
3171
3122
|
this.clearSubscription(id);
|
|
3172
3123
|
this.state.update(current => ({
|
|
@@ -3174,27 +3125,62 @@ class AutoSaveStore {
|
|
|
3174
3125
|
}));
|
|
3175
3126
|
this.subscriptions[id] = timer(3000).subscribe(() => this.stopFor(id));
|
|
3176
3127
|
}
|
|
3177
|
-
|
|
3178
|
-
autosaveError() {
|
|
3128
|
+
error() {
|
|
3179
3129
|
this.clearAllSubscriptions();
|
|
3180
3130
|
this.state.update(current => ({
|
|
3181
3131
|
fields: current.fields.map(field => ({
|
|
3182
3132
|
...field, state: 'error'
|
|
3183
3133
|
}))
|
|
3184
3134
|
}));
|
|
3185
|
-
// Создаем подписку для каждого поля
|
|
3186
3135
|
this.state().fields.forEach(field => {
|
|
3187
3136
|
this.subscriptions[field.id] = timer(3000).subscribe(() => this.stop());
|
|
3188
3137
|
});
|
|
3189
3138
|
}
|
|
3190
|
-
|
|
3191
|
-
autosaveErrorFor(id) {
|
|
3139
|
+
errorFor(id) {
|
|
3192
3140
|
this.clearSubscription(id);
|
|
3193
3141
|
this.state.update(current => ({
|
|
3194
3142
|
fields: current.fields.map(field => field.id === id ? { ...field, state: 'error' } : field)
|
|
3195
3143
|
}));
|
|
3196
3144
|
this.subscriptions[id] = timer(3000).subscribe(() => this.stopFor(id));
|
|
3197
3145
|
}
|
|
3146
|
+
// Добавить или обновить поле
|
|
3147
|
+
upsertField(field) {
|
|
3148
|
+
this.state.update(current => {
|
|
3149
|
+
const exists = current.fields.some(f => f.id === field.id);
|
|
3150
|
+
if (exists) {
|
|
3151
|
+
return {
|
|
3152
|
+
fields: current.fields.map(f => f.id === field.id ? { ...f, ...field } : f)
|
|
3153
|
+
};
|
|
3154
|
+
}
|
|
3155
|
+
return {
|
|
3156
|
+
fields: [...current.fields, field]
|
|
3157
|
+
};
|
|
3158
|
+
});
|
|
3159
|
+
}
|
|
3160
|
+
// Удалить поле
|
|
3161
|
+
removeField(id) {
|
|
3162
|
+
this.state.update(current => ({
|
|
3163
|
+
fields: current.fields.filter(field => field.id !== id)
|
|
3164
|
+
}));
|
|
3165
|
+
}
|
|
3166
|
+
// Очистить все поля
|
|
3167
|
+
clear() {
|
|
3168
|
+
this.state.set({ fields: [] });
|
|
3169
|
+
}
|
|
3170
|
+
// Очистить подписку для поля
|
|
3171
|
+
clearSubscription(id) {
|
|
3172
|
+
if (this.subscriptions[id]) {
|
|
3173
|
+
this.subscriptions[id].unsubscribe();
|
|
3174
|
+
delete this.subscriptions[id];
|
|
3175
|
+
}
|
|
3176
|
+
}
|
|
3177
|
+
// Очистить все подписки
|
|
3178
|
+
clearAllSubscriptions() {
|
|
3179
|
+
Object.keys(this.subscriptions).forEach(key => {
|
|
3180
|
+
this.subscriptions[key].unsubscribe();
|
|
3181
|
+
delete this.subscriptions[key];
|
|
3182
|
+
});
|
|
3183
|
+
}
|
|
3198
3184
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AutoSaveStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3199
3185
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AutoSaveStore, providedIn: 'root' });
|
|
3200
3186
|
}
|
|
@@ -6045,7 +6031,7 @@ class GalleryItemComponent {
|
|
|
6045
6031
|
this._autoSaveStore.successFor(obj.id);
|
|
6046
6032
|
},
|
|
6047
6033
|
error: () => {
|
|
6048
|
-
this._autoSaveStore.
|
|
6034
|
+
this._autoSaveStore.errorFor(obj.id);
|
|
6049
6035
|
}
|
|
6050
6036
|
});
|
|
6051
6037
|
}, 1500);
|
|
@@ -7558,8 +7544,11 @@ class EditorComponent {
|
|
|
7558
7544
|
},
|
|
7559
7545
|
blur: () => {
|
|
7560
7546
|
this.changeFocused(false);
|
|
7561
|
-
}
|
|
7562
|
-
|
|
7547
|
+
},
|
|
7548
|
+
paste: (event) => {
|
|
7549
|
+
this.handlePaste(event);
|
|
7550
|
+
},
|
|
7551
|
+
},
|
|
7563
7552
|
// uploader: {
|
|
7564
7553
|
// insertImageAsBase64URI: true
|
|
7565
7554
|
// },
|
|
@@ -7665,6 +7654,49 @@ class EditorComponent {
|
|
|
7665
7654
|
this.isFocused = value;
|
|
7666
7655
|
this.changeDetection.detectChanges();
|
|
7667
7656
|
}
|
|
7657
|
+
handlePaste(event) {
|
|
7658
|
+
if (!event.clipboardData || this.hasImageButton()) {
|
|
7659
|
+
return;
|
|
7660
|
+
}
|
|
7661
|
+
const { clipboardData } = event;
|
|
7662
|
+
const htmlData = clipboardData.getData('text/html');
|
|
7663
|
+
const hasHtmlImage = htmlData?.includes('<img');
|
|
7664
|
+
const hasImage = Array.from(clipboardData.items).some(item => item.type.startsWith('image/'));
|
|
7665
|
+
if (!hasImage && !hasHtmlImage) {
|
|
7666
|
+
return;
|
|
7667
|
+
}
|
|
7668
|
+
event.preventDefault();
|
|
7669
|
+
const sanitizedHtml = this.removeImagesFromHtml(htmlData);
|
|
7670
|
+
const textData = clipboardData.getData('text/plain');
|
|
7671
|
+
const contentToInsert = sanitizedHtml || textData;
|
|
7672
|
+
if (contentToInsert) {
|
|
7673
|
+
this.editorElementRef.jodit.s.insertHTML(contentToInsert);
|
|
7674
|
+
}
|
|
7675
|
+
}
|
|
7676
|
+
removeImagesFromHtml(html) {
|
|
7677
|
+
if (!html) {
|
|
7678
|
+
return null;
|
|
7679
|
+
}
|
|
7680
|
+
const div = document.createElement('div');
|
|
7681
|
+
div.innerHTML = html;
|
|
7682
|
+
div.querySelectorAll('img').forEach(img => img.remove());
|
|
7683
|
+
return div.innerHTML;
|
|
7684
|
+
}
|
|
7685
|
+
hasImageButton() {
|
|
7686
|
+
const buttons = this.defaultConfig?.buttons;
|
|
7687
|
+
if (!buttons) {
|
|
7688
|
+
return false;
|
|
7689
|
+
}
|
|
7690
|
+
if (typeof buttons === 'string') {
|
|
7691
|
+
return buttons.includes('image');
|
|
7692
|
+
}
|
|
7693
|
+
if (Array.isArray(buttons)) {
|
|
7694
|
+
return buttons.some(item => typeof item === 'string'
|
|
7695
|
+
? item === 'image'
|
|
7696
|
+
: item?.name === 'image');
|
|
7697
|
+
}
|
|
7698
|
+
return false;
|
|
7699
|
+
}
|
|
7668
7700
|
onChange = (value) => {
|
|
7669
7701
|
};
|
|
7670
7702
|
onTouched = () => {
|