@libs-ui/utils 0.2.304 → 0.2.306
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/dom.d.ts +21 -3
- package/esm2022/dom.mjs +124 -6
- package/esm2022/helpers.mjs +2 -2
- package/fesm2022/libs-ui-utils.mjs +125 -7
- package/fesm2022/libs-ui-utils.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { fromEvent, tap, takeUntil, mergeMap, startWith, finalize, Subject, filter, Observable } from 'rxjs';
|
|
2
|
-
import Quill from 'quill';
|
|
3
1
|
import DeviceDetector from 'device-detector-js';
|
|
2
|
+
import Quill from 'quill';
|
|
3
|
+
import { fromEvent, tap, takeUntil, mergeMap, startWith, finalize, lastValueFrom, timer, Subject, filter, Observable } from 'rxjs';
|
|
4
4
|
import CryptoES from 'crypto-es';
|
|
5
5
|
import { HttpParams } from '@angular/common/http';
|
|
6
6
|
import { isSignal, TemplateRef, ElementRef, signal, InjectionToken } from '@angular/core';
|
|
@@ -352,18 +352,136 @@ const getDragEventByElement = (config) => {
|
|
|
352
352
|
? mousemove.pipe(startWith(e))
|
|
353
353
|
: mousemove), takeUntil(config.onDestroy), finalize(removeClass));
|
|
354
354
|
};
|
|
355
|
-
const getHTMLFromQuill = (
|
|
355
|
+
const getHTMLFromQuill = async (data, options) => {
|
|
356
|
+
const { replaceNewLineTo = '<br>', replaceTagBRTo, replaceTags, replaceBrToDiv } = options || {};
|
|
357
|
+
const delta = (typeof data === 'string') ? await getDeltaFromHTML(data) : data;
|
|
358
|
+
if (options?.functionReplaceDelta) {
|
|
359
|
+
options.functionReplaceDelta(delta);
|
|
360
|
+
}
|
|
356
361
|
delta.ops.forEach((op) => {
|
|
357
362
|
if (op.insert) {
|
|
358
363
|
if (typeof op.insert === 'string') {
|
|
359
|
-
|
|
364
|
+
if (replaceNewLineTo) {
|
|
365
|
+
op.insert = op.insert.replace(/\n/g, replaceNewLineTo);
|
|
366
|
+
}
|
|
367
|
+
if (replaceTagBRTo) {
|
|
368
|
+
op.insert = op.insert.replace(/<br>/g, replaceTagBRTo);
|
|
369
|
+
}
|
|
370
|
+
if (replaceTags?.length) {
|
|
371
|
+
for (const tag of replaceTags) {
|
|
372
|
+
op.insert = op.insert.replace(new RegExp(`<${tag.tag}>`, 'g'), `<${tag.replaceTo}>`);
|
|
373
|
+
op.insert = op.insert.replace(new RegExp(`</${tag.tag}>`, 'g'), `</${tag.replaceTo}>`);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
360
376
|
}
|
|
361
377
|
}
|
|
362
378
|
});
|
|
363
379
|
quill.setContents(delta);
|
|
364
|
-
|
|
380
|
+
let htmlText = options?.getRootHtml ? quill.root.innerHTML : quill.root.firstElementChild?.innerHTML;
|
|
381
|
+
if (replaceBrToDiv) {
|
|
382
|
+
htmlText = convertHtmlToDivBlocks(htmlText || '');
|
|
383
|
+
}
|
|
365
384
|
return decodeEscapeHtml(htmlText || '');
|
|
366
385
|
};
|
|
386
|
+
const convertHtmlToDivBlocks = (html) => {
|
|
387
|
+
const BREAK_TOKEN = '<<<BREAK>>>';
|
|
388
|
+
// Bước 1: thay <br> thành token tạm
|
|
389
|
+
const normalizedHtml = html.replace(/<br\s*\/?>/gi, BREAK_TOKEN);
|
|
390
|
+
// Bước 2: tách theo token
|
|
391
|
+
const parts = normalizedHtml.split(BREAK_TOKEN);
|
|
392
|
+
const parser = new DOMParser();
|
|
393
|
+
const divs = [];
|
|
394
|
+
for (const raw of parts) {
|
|
395
|
+
const trimmed = raw.trim();
|
|
396
|
+
if (!trimmed)
|
|
397
|
+
continue;
|
|
398
|
+
// parse mỗi phần nhỏ như một document riêng
|
|
399
|
+
const doc = parser.parseFromString(trimmed, 'text/html');
|
|
400
|
+
const body = doc.body;
|
|
401
|
+
// Lấy lại nội dung bên trong body
|
|
402
|
+
divs.push(`<div>${body.innerHTML}</div>`);
|
|
403
|
+
}
|
|
404
|
+
return divs.join('');
|
|
405
|
+
};
|
|
406
|
+
const getDeltaFromHTML = async (html) => {
|
|
407
|
+
quill.root.innerHTML = html;
|
|
408
|
+
setTimeout(() => {
|
|
409
|
+
console.log(quill.getContents());
|
|
410
|
+
}, 1000);
|
|
411
|
+
await lastValueFrom(timer(1000));
|
|
412
|
+
return quill.getContents();
|
|
413
|
+
};
|
|
414
|
+
const processPasteData = async (e, config) => {
|
|
415
|
+
const element = config.element;
|
|
416
|
+
const files = e.clipboardData?.files;
|
|
417
|
+
if (files?.length) {
|
|
418
|
+
e.preventDefault();
|
|
419
|
+
config.handlerPasteFile?.(files);
|
|
420
|
+
config.callBack?.('file');
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
// Lưu selection TRƯỚC khi prevent default
|
|
424
|
+
const selection = window.getSelection();
|
|
425
|
+
let savedRange = null;
|
|
426
|
+
if (selection && selection.rangeCount > 0) {
|
|
427
|
+
const range = selection.getRangeAt(0);
|
|
428
|
+
// Chỉ lưu nếu range nằm trong contentText element
|
|
429
|
+
const container = range.commonAncestorContainer;
|
|
430
|
+
const isInContentElement = element.contains(container.nodeType === Node.TEXT_NODE ? container.parentNode : container);
|
|
431
|
+
if (isInContentElement) {
|
|
432
|
+
savedRange = range.cloneRange();
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
// Prevent default để tự xử lý paste
|
|
436
|
+
e.preventDefault();
|
|
437
|
+
// Sử dụng Quill để clean HTML content
|
|
438
|
+
const htmlContent = e.clipboardData?.getData('text/html') || '';
|
|
439
|
+
const plainText = e.clipboardData?.getData('text/plain') || '';
|
|
440
|
+
let contentToInsert = (plainText || '').replace(/\n/g, '<br>');
|
|
441
|
+
if (htmlContent) {
|
|
442
|
+
contentToInsert = await getHTMLFromQuill(htmlContent);
|
|
443
|
+
}
|
|
444
|
+
if (!contentToInsert) {
|
|
445
|
+
config.callBack?.('no-content');
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
if (savedRange) {
|
|
449
|
+
insertContentWithRange(contentToInsert, savedRange, element);
|
|
450
|
+
config.callBack?.('range');
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
element.innerHTML += contentToInsert;
|
|
454
|
+
config.callBack?.('content');
|
|
455
|
+
};
|
|
456
|
+
const insertContentWithRange = (content, savedRange, element) => {
|
|
457
|
+
const selection = window.getSelection();
|
|
458
|
+
if (!selection) {
|
|
459
|
+
// Fallback: append vào cuối
|
|
460
|
+
element.innerHTML += content;
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
// Restore selection
|
|
464
|
+
selection.removeAllRanges();
|
|
465
|
+
selection.addRange(savedRange);
|
|
466
|
+
// Xóa nội dung đã select (nếu có)
|
|
467
|
+
savedRange.deleteContents();
|
|
468
|
+
// Tạo document fragment từ HTML content
|
|
469
|
+
const tempDiv = document.createElement('div');
|
|
470
|
+
tempDiv.innerHTML = content;
|
|
471
|
+
const fragment = document.createDocumentFragment();
|
|
472
|
+
while (tempDiv.firstChild) {
|
|
473
|
+
fragment.appendChild(tempDiv.firstChild);
|
|
474
|
+
}
|
|
475
|
+
// Insert fragment tại vị trí range
|
|
476
|
+
savedRange.insertNode(fragment);
|
|
477
|
+
// Di chuyển cursor đến cuối nội dung vừa insert
|
|
478
|
+
if (fragment.lastChild) {
|
|
479
|
+
savedRange.setStartAfter(fragment.lastChild);
|
|
480
|
+
}
|
|
481
|
+
savedRange.collapse(true);
|
|
482
|
+
selection.removeAllRanges();
|
|
483
|
+
selection.addRange(savedRange);
|
|
484
|
+
};
|
|
367
485
|
|
|
368
486
|
class UtilsUrlSearchParams {
|
|
369
487
|
static instance;
|
|
@@ -1551,7 +1669,7 @@ const get = (obj, path, defaultValue = undefined, keepLastValueIfSignal) => {
|
|
|
1551
1669
|
return obj;
|
|
1552
1670
|
}
|
|
1553
1671
|
if (obj instanceof HttpParams) {
|
|
1554
|
-
return obj.get(`${path}`);
|
|
1672
|
+
return (obj.get(`${path}`) ?? defaultValue);
|
|
1555
1673
|
}
|
|
1556
1674
|
if (obj instanceof DOMRect) {
|
|
1557
1675
|
return obj[path];
|
|
@@ -2778,5 +2896,5 @@ const createUniqueRandomIntGenerator = (min, max) => {
|
|
|
2778
2896
|
* Generated bundle index. Do not edit.
|
|
2779
2897
|
*/
|
|
2780
2898
|
|
|
2781
|
-
export { AudioExtList, CHARACTER_DATA_EMPTY, COMMUNICATE_MICRO_KEY_GET_ALL_MESSAGE, COMMUNICATE_MICRO_PREFIX_TYPE, DEFAULT_START_PAGE_0, DocumentExtList, ENCODE_URI_PATTERN, ERROR_MESSAGE_EMPTY_VALID, ERROR_MESSAGE_MAX_LENGTH, ERROR_MESSAGE_MAX_VALID, ERROR_MESSAGE_MIN_LENGTH, ERROR_MESSAGE_MIN_VALID, ERROR_MESSAGE_PATTEN_VALID, ExcelExtList, ImageExtList, LINK_IMAGE_ERROR_TOKEN_INJECT, PROCESS_BAR_STANDARD_CONFIG_DEFAULT_TOKEN_INJECT, PROCESS_BAR_STEPS_CONFIG_DEFAULT_TOKEN_INJECT, UtilsCache, UtilsCommunicateMicro, UtilsCommunicateMicroKeyGlobal, UtilsHttpParamsRequest, UtilsHttpParamsRequestInstance, UtilsKeyCodeConstant, UtilsLanguageConstants, UtilsUrlSearchParams, VideoExtList, base64Decode, base64Encode, capitalize, checkMouseOverInContainer, checkViewInScreen, cloneDeep, cloneIBoundingClientRect, colorContrastFromOrigin, colorStepContrastFromOrigin, convertBase64ToBlob, convertBlobToFile, convertFileToBase64, convertFileToBase64_ObjectUrl, convertObjectToSignal, convertSignalToObject, convertUrlToFile, createUniqueRandomIntGenerator, decodeEscapeHtml, decodeURI, decrypt, decrypt3rd, deleteUnicode, downloadFileByUrl, downloadFileByUrlUseXmlRequest, downloadImageFromELement, encodeURI, encrypt, encrypt3rd, endCodeUrl, escapeHtml, firstLetterToUpperCase, formatDate, formatNumber, formatTextCompare, fullNameFormat, generateInterface, get, getColorById, getDayjs, getDeviceInfo, getDocumentByString, getDragEventByElement, getEventNameHandleClick, getFileExtension, getHTMLFromQuill, getKeyCacheByArrayObject, getLabelBySizeFile, getPlatFromBrowser, getSmartAxisScale, getViewport, groupBy, highlightByKeyword, isDifferenceDay, isDifferenceMonth, isDifferenceYear, isEmbedFrame, isEmpty, isEqual, isIncludeAudioExtList, isIncludeDocumentExtList, isIncludeImageExtList, isIncludeVideoExtList, isNil, isTypeAudio, isTypeFile, isTypeImage, isTypeVideo, keyBy, listColorDefine, md5, omitBy, patternAccount, patternDomain, patternEmail, patternEmoji, patternEncodeUri, patternGetFieldByRuleFieldReplace, patternHostUrl, patternKey, patternMobilePhone, patternName, patternNameProfile, patternNameSpecial, patternNameUtf8, patternNumber, patternPem, patternPhone, patternPhoneNormal, patternRuleFieldReplace, patternTax, patternUrl, protectString, range, removeEmoji, revealString, rgbToHex, set, setCaretPosition, setDefaultTimeZone, setKeyCrypto, setKeyCrypto3rd, setStylesElement, uniqBy, updateFunctionCheckEmbedFrame, updateFunctionFormatDate, updateFunctionXssFilter, uppercaseByPosition, uuid, viewDataNumberByLanguage, xssFilter };
|
|
2899
|
+
export { AudioExtList, CHARACTER_DATA_EMPTY, COMMUNICATE_MICRO_KEY_GET_ALL_MESSAGE, COMMUNICATE_MICRO_PREFIX_TYPE, DEFAULT_START_PAGE_0, DocumentExtList, ENCODE_URI_PATTERN, ERROR_MESSAGE_EMPTY_VALID, ERROR_MESSAGE_MAX_LENGTH, ERROR_MESSAGE_MAX_VALID, ERROR_MESSAGE_MIN_LENGTH, ERROR_MESSAGE_MIN_VALID, ERROR_MESSAGE_PATTEN_VALID, ExcelExtList, ImageExtList, LINK_IMAGE_ERROR_TOKEN_INJECT, PROCESS_BAR_STANDARD_CONFIG_DEFAULT_TOKEN_INJECT, PROCESS_BAR_STEPS_CONFIG_DEFAULT_TOKEN_INJECT, UtilsCache, UtilsCommunicateMicro, UtilsCommunicateMicroKeyGlobal, UtilsHttpParamsRequest, UtilsHttpParamsRequestInstance, UtilsKeyCodeConstant, UtilsLanguageConstants, UtilsUrlSearchParams, VideoExtList, base64Decode, base64Encode, capitalize, checkMouseOverInContainer, checkViewInScreen, cloneDeep, cloneIBoundingClientRect, colorContrastFromOrigin, colorStepContrastFromOrigin, convertBase64ToBlob, convertBlobToFile, convertFileToBase64, convertFileToBase64_ObjectUrl, convertHtmlToDivBlocks, convertObjectToSignal, convertSignalToObject, convertUrlToFile, createUniqueRandomIntGenerator, decodeEscapeHtml, decodeURI, decrypt, decrypt3rd, deleteUnicode, downloadFileByUrl, downloadFileByUrlUseXmlRequest, downloadImageFromELement, encodeURI, encrypt, encrypt3rd, endCodeUrl, escapeHtml, firstLetterToUpperCase, formatDate, formatNumber, formatTextCompare, fullNameFormat, generateInterface, get, getColorById, getDayjs, getDeltaFromHTML, getDeviceInfo, getDocumentByString, getDragEventByElement, getEventNameHandleClick, getFileExtension, getHTMLFromQuill, getKeyCacheByArrayObject, getLabelBySizeFile, getPlatFromBrowser, getSmartAxisScale, getViewport, groupBy, highlightByKeyword, insertContentWithRange, isDifferenceDay, isDifferenceMonth, isDifferenceYear, isEmbedFrame, isEmpty, isEqual, isIncludeAudioExtList, isIncludeDocumentExtList, isIncludeImageExtList, isIncludeVideoExtList, isNil, isTypeAudio, isTypeFile, isTypeImage, isTypeVideo, keyBy, listColorDefine, md5, omitBy, patternAccount, patternDomain, patternEmail, patternEmoji, patternEncodeUri, patternGetFieldByRuleFieldReplace, patternHostUrl, patternKey, patternMobilePhone, patternName, patternNameProfile, patternNameSpecial, patternNameUtf8, patternNumber, patternPem, patternPhone, patternPhoneNormal, patternRuleFieldReplace, patternTax, patternUrl, processPasteData, protectString, range, removeEmoji, revealString, rgbToHex, set, setCaretPosition, setDefaultTimeZone, setKeyCrypto, setKeyCrypto3rd, setStylesElement, uniqBy, updateFunctionCheckEmbedFrame, updateFunctionFormatDate, updateFunctionXssFilter, uppercaseByPosition, uuid, viewDataNumberByLanguage, xssFilter };
|
|
2782
2900
|
//# sourceMappingURL=libs-ui-utils.mjs.map
|