asksuite-citrus 3.16.24-beta.2 → 3.16.25

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.
@@ -2106,13 +2106,34 @@ function areObjectsEqual(obj1, obj2) {
2106
2106
 
2107
2107
  const URL_REGEX = /https?:\/\/[a-zA-Z0-9.-]+(?::\d+)?(?:\/[^\s]*)?/gi;
2108
2108
 
2109
+ const Inline = Quill.import('blots/inline');
2110
+ const EMOJI_REGEX = /(?:[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|[\u{1F900}-\u{1F9FF}]|[\u{1F018}-\u{1F270}]|[\u{238C}-\u{2454}]|[\u{20D0}-\u{20FF}]|[\u{FE0F}]|[\u{200D}]|[\u{E000}-\u{F8FF}]|[\u{1F004}]|[\u{1F0CF}]|[\u{1F170}-\u{1F251}]|[\u{1F004}-\u{1F0CF}]|[\u{1F004}]|[\u{203C}\u{2049}]|[\u{2122}\u{2139}]|[\u{2194}-\u{2199}]|[\u{21A9}-\u{21AA}]|[\u{231A}-\u{231B}]|[\u{2328}]|[\u{23CF}]|[\u{23E9}-\u{23F3}]|[\u{23F8}-\u{23FA}]|[\u{24C2}]|[\u{25AA}-\u{25AB}]|[\u{25B6}]|[\u{25C0}]|[\u{25FB}-\u{25FE}]|[\u{2934}-\u{2935}]|[\u{2B05}-\u{2B07}]|[\u{2B1B}-\u{2B1C}]|[\u{2B50}]|[\u{2B55}]|[\u{3030}]|[\u{303D}]|[\u{3297}]|[\u{3299}]|[\u{1FA70}-\u{1FAFF}]|[\u{1F7E0}-\u{1F7EB}]|[\u{1F90C}-\u{1F93A}]|[\u{1F93C}-\u{1F945}]|[\u{1F947}-\u{1F9FF}]|[\u{1F30D}-\u{1F567}]|[\u{2190}-\u{21FF}]|[\u{2200}-\u{22FF}]|[\u{2300}-\u{23FF}]|[\u{2460}-\u{24FF}]|[\u{25A0}-\u{25FF}]|[\u{2600}-\u{27EF}]|[\u{2900}-\u{297F}]|[\u{2B00}-\u{2BFF}]|[\u{4DC0}-\u{4DFF}]|[\u{A490}-\u{A4CF}]|[\u{2000}-\u{206F}]|[\u{2070}-\u{209F}]|[\u{20A0}-\u{20CF}]|[\u{2100}-\u{214F}]|[\u{2150}-\u{218F}]|[\u{2190}-\u{21FF}]|[\u{2200}-\u{22FF}]|[\u{2300}-\u{23FF}]|[\u{2400}-\u{243F}]|[\u{2440}-\u{245F}]|[\u{2460}-\u{24FF}]|[\u{2500}-\u{257F}]|[\u{2580}-\u{259F}]|[\u{25A0}-\u{25FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|[\u{27C0}-\u{27EF}]|[\u{27F0}-\u{27FF}]|[\u{2800}-\u{28FF}]|[\u{2900}-\u{297F}]|[\u{2980}-\u{29FF}]|[\u{2A00}-\u{2AFF}]|[\u{2B00}-\u{2BFF}])(?:[\u{FE0E}\u{FE0F}])?(?:\u{200D}(?:[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|[\u{1F900}-\u{1F9FF}]|[\u{1F018}-\u{1F270}]|[\u{238C}-\u{2454}]|[\u{20D0}-\u{20FF}]|[\u{FE0F}]|[\u{200D}]|[\u{E000}-\u{F8FF}]|[\u{2640}]|[\u{2642}]|[\u{2695}]|[\u{26F9}]|[\u{2708}]))?/gu;
2111
+ class EmojiBlot extends Inline {
2112
+ static { this.blotName = 'emoji'; }
2113
+ static { this.tagName = 'span'; }
2114
+ static { this.className = 'quill-emoji'; }
2115
+ static create(value) {
2116
+ if (!value)
2117
+ return super.create(false);
2118
+ const node = super.create(value);
2119
+ node.classList.add(EmojiBlot.className);
2120
+ node.style.fontSize = '20px';
2121
+ return node;
2122
+ }
2123
+ static formats(node) {
2124
+ return node;
2125
+ }
2126
+ static value(node) {
2127
+ return node;
2128
+ }
2129
+ }
2130
+
2109
2131
  class RichtextWrapper {
2110
2132
  get state() {
2111
2133
  return this.stateSub.value;
2112
2134
  }
2113
2135
  get listenTextChanges$() {
2114
- return fromEvent(this.quill, 'text-change')
2115
- .pipe(map(() => this.quill.root.innerHTML));
2136
+ return fromEvent(this.quill, 'text-change').pipe(map(() => this.quill.root.innerHTML));
2116
2137
  }
2117
2138
  get listenOnTouched$() {
2118
2139
  return fromEvent(this.quill, 'selection-change').pipe(filter(() => Boolean(this.quill.getSelection(false))), map(() => null));
@@ -2142,13 +2163,16 @@ class RichtextWrapper {
2142
2163
  justify_center: false,
2143
2164
  justify_right: false,
2144
2165
  },
2145
- disabledTools: []
2166
+ disabledTools: [],
2146
2167
  });
2147
2168
  this.esc$ = new Subject();
2148
2169
  this.enter$ = new Subject();
2149
2170
  this.maxLength = -1;
2150
2171
  this.breakOnEnter = false;
2151
2172
  this.allowImages = false;
2173
+ this.isFormatting = false;
2174
+ this.pendingFormat = false;
2175
+ this.lastKeyCombination = null;
2152
2176
  this.quillFormats = [
2153
2177
  'background',
2154
2178
  'bold',
@@ -2170,10 +2194,11 @@ class RichtextWrapper {
2170
2194
  'code-block',
2171
2195
  'formula',
2172
2196
  'image',
2173
- 'htmlPanel'
2197
+ 'htmlPanel',
2198
+ 'emoji',
2174
2199
  // 'video'
2175
2200
  ];
2176
- this.textChangeHandler = () => {
2201
+ this.textChangeHandler = (delta, oldDelta, source) => {
2177
2202
  this.update();
2178
2203
  };
2179
2204
  this.selectionChangeHandler = (value, oldRange, source) => {
@@ -2203,15 +2228,15 @@ class RichtextWrapper {
2203
2228
  handler: () => {
2204
2229
  this.esc$.next(true);
2205
2230
  return false;
2206
- }
2231
+ },
2207
2232
  },
2208
2233
  enter: {
2209
2234
  key: 'enter',
2210
2235
  handler: () => {
2211
2236
  this.enter$.next(true);
2212
2237
  return this.breakOnEnter;
2213
- }
2214
- }
2238
+ },
2239
+ },
2215
2240
  };
2216
2241
  this.state$ = this.stateSub.asObservable();
2217
2242
  const editorId = `editor-${new Date().getTime()}`;
@@ -2223,15 +2248,42 @@ class RichtextWrapper {
2223
2248
  matchers: [
2224
2249
  [Node.TEXT_NODE, this.urlMatcher.bind(this)],
2225
2250
  ['IMG', this.imageMatcher.bind(this)],
2226
- [Node.ELEMENT_NODE, this.htmlPanelMatcher.bind(this)]
2251
+ [Node.ELEMENT_NODE, this.htmlPanelMatcher.bind(this)],
2252
+ [Node.TEXT_NODE, this.emojiMatcher.bind(this)],
2227
2253
  ],
2228
2254
  },
2229
2255
  keyboard: { bindings: this.bindings },
2230
2256
  },
2231
- formats: this.quillFormats
2257
+ formats: this.quillFormats,
2232
2258
  });
2259
+ this.setupEmojiDetection();
2260
+ this.setupKeyListeners();
2233
2261
  this.listenEditorChanges();
2234
2262
  }
2263
+ emojiMatcher(node, delta) {
2264
+ if (node.nodeType === Node.TEXT_NODE) {
2265
+ const text = node.textContent || '';
2266
+ const matches = [...text.matchAll(EMOJI_REGEX)];
2267
+ if (matches && matches.length > 0) {
2268
+ const ops = [];
2269
+ let lastIndex = 0;
2270
+ for (const match of matches) {
2271
+ const emoji = match[0];
2272
+ const index = match.index;
2273
+ if (index > lastIndex) {
2274
+ ops.push({ insert: text.substring(lastIndex, index) });
2275
+ }
2276
+ ops.push({ insert: emoji, attributes: { emoji: true } });
2277
+ lastIndex = index + emoji.length;
2278
+ }
2279
+ if (lastIndex < text.length) {
2280
+ ops.push({ insert: text.substring(lastIndex) });
2281
+ }
2282
+ return { ops };
2283
+ }
2284
+ }
2285
+ return delta;
2286
+ }
2235
2287
  setItalic() {
2236
2288
  if (this.isToolDisabled('italic'))
2237
2289
  return;
@@ -2348,16 +2400,16 @@ class RichtextWrapper {
2348
2400
  this.maxLength = length;
2349
2401
  this.maxLengthSubscription?.unsubscribe();
2350
2402
  if (this.maxLength > 0)
2351
- this.maxLengthSubscription =
2352
- fromEvent(this.quill, 'text-change')
2353
- .pipe(filter(() => this.quill.getLength() > this.maxLength))
2354
- .subscribe(() => {
2355
- this.quill.deleteText(this.maxLength - 1, this.quill.getLength());
2356
- });
2403
+ this.maxLengthSubscription = fromEvent(this.quill, 'text-change')
2404
+ .pipe(filter(() => this.quill.getLength() > this.maxLength))
2405
+ .subscribe(() => {
2406
+ this.quill.deleteText(this.maxLength - 1, this.quill.getLength());
2407
+ });
2357
2408
  }
2358
2409
  setDisabledTools(tools) {
2359
- if (JSON.stringify(tools) !== JSON.stringify(this.stateSub.value.disabledTools))
2360
- this.stateSub.next({ ...this.stateSub.value, disabledTools: tools, });
2410
+ if (JSON.stringify(tools) !==
2411
+ JSON.stringify(this.stateSub.value.disabledTools))
2412
+ this.stateSub.next({ ...this.stateSub.value, disabledTools: tools });
2361
2413
  }
2362
2414
  setEditorClass(className) {
2363
2415
  if (!className)
@@ -2444,6 +2496,14 @@ class RichtextWrapper {
2444
2496
  this.quill.on('selection-change', this.selectionChangeHandler);
2445
2497
  this.quill.on('text-change', this.textChangeHandler);
2446
2498
  }
2499
+ setupKeyListeners() {
2500
+ this.quill.root.addEventListener('keydown', (event) => {
2501
+ this.lastKeyCombination = {
2502
+ key: event.key,
2503
+ shiftKey: event.shiftKey,
2504
+ };
2505
+ });
2506
+ }
2447
2507
  update() {
2448
2508
  let bounds;
2449
2509
  let formatsArr;
@@ -2471,21 +2531,134 @@ class RichtextWrapper {
2471
2531
  hasSelection,
2472
2532
  formats,
2473
2533
  bounds,
2474
- hasFocus
2534
+ hasFocus,
2475
2535
  };
2476
2536
  this.ngZone.run(() => {
2477
2537
  this.stateSub.next(newState);
2478
2538
  this.cd.markForCheck();
2479
2539
  });
2480
2540
  }
2541
+ setupEmojiDetection() {
2542
+ this.quill.on('text-change', (_delta, _oldDelta, _source) => {
2543
+ if (_source !== 'user' || this.isFormatting) {
2544
+ if (_source === 'user')
2545
+ this.pendingFormat = true;
2546
+ return;
2547
+ }
2548
+ this.formatEmoji();
2549
+ });
2550
+ }
2551
+ formatEmoji() {
2552
+ if (this.isFormatting) {
2553
+ this.pendingFormat = true;
2554
+ return;
2555
+ }
2556
+ this.isFormatting = true;
2557
+ try {
2558
+ const selection = this.quill.getSelection();
2559
+ const contents = this.quill.getContents();
2560
+ const ops = [];
2561
+ let hasChanges = false;
2562
+ if (!contents.ops?.length) {
2563
+ this.isFormatting = false;
2564
+ return;
2565
+ }
2566
+ const processedPositions = new Set();
2567
+ contents.ops.forEach((op) => {
2568
+ if (typeof op.insert === 'string') {
2569
+ const text = op.insert;
2570
+ const matches = [...text.matchAll(EMOJI_REGEX)];
2571
+ if (matches.length > 0) {
2572
+ hasChanges = true;
2573
+ let lastIndex = 0;
2574
+ for (const match of matches) {
2575
+ const emoji = match[0];
2576
+ const index = match.index;
2577
+ if (index > lastIndex) {
2578
+ const beforeText = text.substring(lastIndex, index);
2579
+ ops.push({
2580
+ insert: beforeText,
2581
+ attributes: { ...op.attributes, emoji: false },
2582
+ });
2583
+ }
2584
+ const position = ops.reduce((acc, op) => acc + (op.insert?.length || 0), 0);
2585
+ if (!processedPositions.has(position)) {
2586
+ ops.push({
2587
+ insert: emoji,
2588
+ attributes: { ...op.attributes, emoji: true },
2589
+ });
2590
+ processedPositions.add(position);
2591
+ }
2592
+ else {
2593
+ ops.push({
2594
+ insert: emoji,
2595
+ attributes: { ...op.attributes, },
2596
+ });
2597
+ }
2598
+ lastIndex = index + emoji.length;
2599
+ }
2600
+ if (lastIndex < text.length) {
2601
+ ops.push({
2602
+ insert: text.substring(lastIndex),
2603
+ attributes: { ...op.attributes, emoji: false },
2604
+ });
2605
+ }
2606
+ }
2607
+ else {
2608
+ ops.push({
2609
+ insert: op.insert,
2610
+ attributes: { ...op.attributes, emoji: false },
2611
+ });
2612
+ }
2613
+ }
2614
+ else {
2615
+ ops.push(op);
2616
+ }
2617
+ });
2618
+ if (hasChanges) {
2619
+ this.quill.setContents(new (Quill.import('delta'))(ops), 'api');
2620
+ requestAnimationFrame(() => {
2621
+ try {
2622
+ if (selection) {
2623
+ const wasShiftEnter = this.lastKeyCombination?.key.toLocaleLowerCase() === 'enter' &&
2624
+ this.lastKeyCombination?.shiftKey;
2625
+ this.quill.setSelection(wasShiftEnter ? selection.index + 1 : selection.index, selection.length);
2626
+ }
2627
+ }
2628
+ catch (e) {
2629
+ console.warn('Erro ao restaurar seleção:', e);
2630
+ }
2631
+ finally {
2632
+ this.isFormatting = false;
2633
+ if (this.pendingFormat) {
2634
+ this.pendingFormat = false;
2635
+ setTimeout(() => {
2636
+ if (!this.isFormatting) {
2637
+ this.formatEmoji();
2638
+ }
2639
+ }, 0);
2640
+ }
2641
+ }
2642
+ });
2643
+ }
2644
+ else {
2645
+ this.isFormatting = false;
2646
+ }
2647
+ }
2648
+ catch (error) {
2649
+ console.error('Erro ao formatar emojis:', error);
2650
+ this.isFormatting = false;
2651
+ this.pendingFormat = false;
2652
+ }
2653
+ }
2481
2654
  }
2482
- //to work around testing problems
2655
+ //to work around testing problems
2483
2656
  const QuillProxy = {
2484
- Quill
2657
+ Quill,
2485
2658
  };
2486
- //to work around testing problems
2659
+ //to work around testing problems
2487
2660
  const RichtextWrapperProxy = {
2488
- RichtextWrapper
2661
+ RichtextWrapper,
2489
2662
  };
2490
2663
 
2491
2664
  const TOOL_FUNCTION_MAP = {
@@ -4262,6 +4435,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.7", ngImpor
4262
4435
  }] } });
4263
4436
 
4264
4437
  Quill.register(HTMLPanelQuillBlot);
4438
+ Quill.register(EmojiBlot);
4265
4439
  function initMyLib(myLibService) {
4266
4440
  return new StorageUtilService(myLibService);
4267
4441
  }