@leanix/components 0.4.959 → 0.4.961

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, Input, Component, input, computed, ChangeDetectionStrategy, HostBinding, EventEmitter, HostListener, Output, Injectable, ElementRef, ViewChild, Inject, model, Directive, signal, Optional, Pipe, inject, NgModule, output, DestroyRef, ChangeDetectorRef, effect, ContentChild, afterRenderEffect, ContentChildren, ViewChildren, forwardRef, TemplateRef, viewChild, booleanAttribute, SecurityContext, Self, Host, Injector, ApplicationRef, createComponent } from '@angular/core';
2
+ import { InjectionToken, Input, Component, input, computed, ChangeDetectionStrategy, HostBinding, EventEmitter, HostListener, Output, Injectable, ElementRef, ViewChild, Inject, model, Directive, signal, Optional, Pipe, inject, NgModule, output, DestroyRef, ChangeDetectorRef, effect, ContentChild, afterRenderEffect, ContentChildren, ViewChildren, forwardRef, TemplateRef, viewChild, booleanAttribute, Injector, ApplicationRef, createComponent, SecurityContext, Self, Host } from '@angular/core';
3
3
  import * as i1$1 from '@ngx-translate/core';
4
4
  import { TranslatePipe, TranslateModule, TranslateService } from '@ngx-translate/core';
5
5
  import * as i1 from '@leanix/components/ui5';
@@ -24,21 +24,19 @@ import { Renderer, marked } from 'marked';
24
24
  import * as i3 from '@angular/cdk/portal';
25
25
  import { ComponentPortal, PortalModule, CdkPortal } from '@angular/cdk/portal';
26
26
  import * as i1$2 from '@angular/cdk/overlay';
27
- import { CdkOverlayOrigin, CdkConnectedOverlay, OverlayModule } from '@angular/cdk/overlay';
27
+ import { CdkOverlayOrigin, CdkConnectedOverlay } from '@angular/cdk/overlay';
28
28
  import * as i2 from '@angular/cdk/a11y';
29
29
  import { ActiveDescendantKeyManager } from '@angular/cdk/a11y';
30
30
  import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
31
31
  import * as i1$3 from '@ncstate/sat-popover';
32
32
  import { SatPopoverModule, SatPopoverComponent } from '@ncstate/sat-popover';
33
- import { ClipboardModule } from '@angular/cdk/clipboard';
34
- import * as i2$2 from '@angular/forms';
35
- import { FormsModule, NG_VALUE_ACCESSOR, NG_VALIDATORS, ReactiveFormsModule, UntypedFormControl, NgForm, Validators, FormControl } from '@angular/forms';
36
33
  import * as i2$1 from 'ngx-infinite-scroll';
37
34
  import { InfiniteScrollModule } from 'ngx-infinite-scroll';
35
+ import * as i2$2 from '@angular/forms';
36
+ import { FormsModule, NG_VALUE_ACCESSOR, NG_VALIDATORS, ReactiveFormsModule, UntypedFormControl, NgForm, Validators, FormControl } from '@angular/forms';
38
37
  import * as i1$4 from '@angular/cdk/drag-drop';
39
38
  import { moveItemInArray, CdkDropList, CdkDrag, DragDropModule } from '@angular/cdk/drag-drop';
40
39
  import * as i1$5 from '@angular/cdk/bidi';
41
- import * as i1$6 from '@angular/platform-browser';
42
40
  import { Node as Node$1, mergeAttributes, Extension, getMarkRange, findParentNode, Editor, NodeView } from '@tiptap/core';
43
41
  import Bold from '@tiptap/extension-bold';
44
42
  import BulletList from '@tiptap/extension-bullet-list';
@@ -71,6 +69,7 @@ import { TableCell } from '@tiptap/extension-table-cell';
71
69
  import { TableHeader } from '@tiptap/extension-table-header';
72
70
  import { TableRow } from '@tiptap/extension-table-row';
73
71
  import { trigger, transition, style, animate } from '@angular/animations';
72
+ import * as i1$6 from '@angular/platform-browser';
74
73
  import { coerceNumberProperty } from '@angular/cdk/coercion';
75
74
 
76
75
  const DATE_FORMATS = new InjectionToken('DATE_FORMATS', {
@@ -5582,6 +5581,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
5582
5581
  type: Input
5583
5582
  }] } });
5584
5583
 
5584
+ class DatepickerConfig {
5585
+ constructor() {
5586
+ this.locale = 'en';
5587
+ this.datepickerMode = 'day';
5588
+ this.startingDay = 0;
5589
+ this.yearRange = 20;
5590
+ this.minMode = 'day';
5591
+ this.maxMode = 'year';
5592
+ this.showWeeks = true;
5593
+ this.formatDay = 'dd';
5594
+ this.formatMonth = 'MMMM';
5595
+ this.formatYear = 'yyyy';
5596
+ this.formatDayHeader = 'EE';
5597
+ this.formatDayTitle = 'MMMM yyyy';
5598
+ this.formatMonthTitle = 'yyyy';
5599
+ this.onlyCurrentMonth = false;
5600
+ this.monthColLimit = 3;
5601
+ this.yearColLimit = 5;
5602
+ this.shortcutPropagation = false;
5603
+ }
5604
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatepickerConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5605
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatepickerConfig }); }
5606
+ }
5607
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatepickerConfig, decorators: [{
5608
+ type: Injectable
5609
+ }] });
5610
+
5585
5611
  const isBs3 = () => true;
5586
5612
 
5587
5613
  /**
@@ -6294,33 +6320,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
6294
6320
  `, imports: [NgClass, ButtonComponent], styles: [":host .btn-info .text-success{color:#fff!important}\n"] }]
6295
6321
  }], ctorParameters: () => [{ type: DatePickerInnerComponent }] });
6296
6322
 
6297
- class DatepickerConfig {
6298
- constructor() {
6299
- this.locale = 'en';
6300
- this.datepickerMode = 'day';
6301
- this.startingDay = 0;
6302
- this.yearRange = 20;
6303
- this.minMode = 'day';
6304
- this.maxMode = 'year';
6305
- this.showWeeks = true;
6306
- this.formatDay = 'dd';
6307
- this.formatMonth = 'MMMM';
6308
- this.formatYear = 'yyyy';
6309
- this.formatDayHeader = 'EE';
6310
- this.formatDayTitle = 'MMMM yyyy';
6311
- this.formatMonthTitle = 'yyyy';
6312
- this.onlyCurrentMonth = false;
6313
- this.monthColLimit = 3;
6314
- this.yearColLimit = 5;
6315
- this.shortcutPropagation = false;
6316
- }
6317
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatepickerConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6318
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatepickerConfig }); }
6319
- }
6320
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatepickerConfig, decorators: [{
6321
- type: Injectable
6322
- }] });
6323
-
6324
6323
  const DATEPICKER_CONTROL_VALUE_ACCESSOR = {
6325
6324
  provide: NG_VALUE_ACCESSOR,
6326
6325
  useExisting: forwardRef(() => DatePickerComponent),
@@ -6384,7 +6383,7 @@ class DatePickerComponent {
6384
6383
  this.onTouched = fn;
6385
6384
  }
6386
6385
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatePickerComponent, deps: [{ token: DatepickerConfig }], target: i0.ɵɵFactoryTarget.Component }); }
6387
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: DatePickerComponent, isStandalone: true, selector: "datepicker", inputs: { datepickerMode: "datepickerMode", initDate: "initDate", minDate: "minDate", maxDate: "maxDate", minMode: "minMode", maxMode: "maxMode", showWeeks: "showWeeks", formatDay: "formatDay", formatMonth: "formatMonth", formatYear: "formatYear", formatDayHeader: "formatDayHeader", formatDayTitle: "formatDayTitle", formatMonthTitle: "formatMonthTitle", startingDay: "startingDay", yearRange: "yearRange", onlyCurrentMonth: "onlyCurrentMonth", shortcutPropagation: "shortcutPropagation", monthColLimit: "monthColLimit", yearColLimit: "yearColLimit", customClass: "customClass", dateDisabled: "dateDisabled", dayDisabled: "dayDisabled", activeDate: "activeDate" }, outputs: { selectionDone: "selectionDone", activeDateChange: "activeDateChange" }, providers: [DATEPICKER_CONTROL_VALUE_ACCESSOR], viewQueries: [{ propertyName: "_datePicker", first: true, predicate: DatePickerInnerComponent, descendants: true, static: true }], ngImport: i0, template: `
6386
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: DatePickerComponent, isStandalone: true, selector: "datepicker", inputs: { datepickerMode: "datepickerMode", initDate: "initDate", minDate: "minDate", maxDate: "maxDate", minMode: "minMode", maxMode: "maxMode", showWeeks: "showWeeks", formatDay: "formatDay", formatMonth: "formatMonth", formatYear: "formatYear", formatDayHeader: "formatDayHeader", formatDayTitle: "formatDayTitle", formatMonthTitle: "formatMonthTitle", startingDay: "startingDay", yearRange: "yearRange", onlyCurrentMonth: "onlyCurrentMonth", shortcutPropagation: "shortcutPropagation", monthColLimit: "monthColLimit", yearColLimit: "yearColLimit", customClass: "customClass", dateDisabled: "dateDisabled", dayDisabled: "dayDisabled", activeDate: "activeDate" }, outputs: { selectionDone: "selectionDone", activeDateChange: "activeDateChange" }, providers: [DATEPICKER_CONTROL_VALUE_ACCESSOR, DatepickerConfig], viewQueries: [{ propertyName: "_datePicker", first: true, predicate: DatePickerInnerComponent, descendants: true, static: true }], ngImport: i0, template: `
6388
6387
  <datepicker-inner
6389
6388
  [activeDate]="activeDate"
6390
6389
  (update)="onUpdate($event)"
@@ -6460,7 +6459,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
6460
6459
  <yearpicker tabindex="0" />
6461
6460
  </datepicker-inner>
6462
6461
  `,
6463
- providers: [DATEPICKER_CONTROL_VALUE_ACCESSOR],
6462
+ providers: [DATEPICKER_CONTROL_VALUE_ACCESSOR, DatepickerConfig],
6464
6463
  imports: [DatePickerInnerComponent, DayPickerComponent, MonthPickerComponent, YearPickerComponent]
6465
6464
  }]
6466
6465
  }], ctorParameters: () => [{ type: DatepickerConfig }], propDecorators: { datepickerMode: [{
@@ -6957,22 +6956,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
6957
6956
  args: ['dateStringTemplate', { read: TemplateRef, static: true }]
6958
6957
  }] } });
6959
6958
 
6960
- class DatepickerUiModule {
6961
- static forRoot() {
6962
- return { ngModule: DatepickerUiModule, providers: [DatepickerConfig] };
6963
- }
6964
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatepickerUiModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
6965
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: DatepickerUiModule, imports: [DatePickerComponent], exports: [DatePickerComponent] }); }
6966
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatepickerUiModule, imports: [DatePickerComponent] }); }
6967
- }
6968
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatepickerUiModule, decorators: [{
6969
- type: NgModule,
6970
- args: [{
6971
- imports: [DatePickerComponent],
6972
- exports: [DatePickerComponent]
6973
- }]
6974
- }] });
6975
-
6976
6959
  /**
6977
6960
  * Individual item within a drag-and-drop list.
6978
6961
  *
@@ -7338,35 +7321,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
7338
7321
  args: [KeyboardSortableItemDirective]
7339
7322
  }] } });
7340
7323
 
7341
- class LxDragAndDropListModule {
7342
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: LxDragAndDropListModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
7343
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: LxDragAndDropListModule, imports: [CommonModule,
7344
- DragDropModule, i1$1.TranslateModule, KeyboardSortableItemDirective,
7345
- KeyboardSortableListDirective,
7346
- DragAndDropListComponent,
7347
- DragAndDropListItemComponent], exports: [DragAndDropListComponent, DragAndDropListItemComponent] }); }
7348
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: LxDragAndDropListModule, imports: [CommonModule,
7349
- DragDropModule,
7350
- TranslateModule.forChild(),
7351
- DragAndDropListComponent,
7352
- DragAndDropListItemComponent] }); }
7353
- }
7354
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: LxDragAndDropListModule, decorators: [{
7355
- type: NgModule,
7356
- args: [{
7357
- imports: [
7358
- CommonModule,
7359
- DragDropModule,
7360
- TranslateModule.forChild(),
7361
- KeyboardSortableItemDirective,
7362
- KeyboardSortableListDirective,
7363
- DragAndDropListComponent,
7364
- DragAndDropListItemComponent
7365
- ],
7366
- exports: [DragAndDropListComponent, DragAndDropListItemComponent]
7367
- }]
7368
- }] });
7369
-
7370
7324
  /**
7371
7325
  * Displays form validation error messages.
7372
7326
  *
@@ -10045,677 +9999,65 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
10045
9999
  type: Output
10046
10000
  }] } });
10047
10001
 
10048
- // /**
10049
- // * Converts HTML to text, preserving semantic newlines for block-level
10050
- // * elements. (Taken from https://stackoverflow.com/a/20384452/6813271)
10051
- // *
10052
- // * @param node - The HTML node to perform text extraction.
10053
- // */
10054
- // export function getNodeTextWithNewlines(node: Element, _inner = false): string {
10055
- // let result = '';
10056
- // if (node.nodeType === document.TEXT_NODE) {
10057
- // // Replace repeated spaces, newlines, and tabs with a single space.
10058
- // result = node.nodeValue.replace( /\s+/g, ' ' );
10059
- // } else {
10060
- // for (let i = 0, j = node.childNodes.length; i < j; i++ ) {
10061
- // result += this.getNodeTextWithNewlines(node.childNodes[i] as Element, true);
10062
- // }
10063
- // const d = node['currentStyle'] ?
10064
- // node['currentStyle']['display'] :
10065
- // document.defaultView.getComputedStyle(node, null).getPropertyValue('display');
10066
- // if (d.match(/^block/)) {
10067
- // result = '\n' + result + '\n';
10068
- // } else if (d.match(/list/) || d.match(/row/) || node.tagName === 'BR' || node.tagName === 'HR' ) {
10069
- // result += '\n';
10070
- // }
10071
- // }
10072
- // return _inner ? result : _.trim(result, '\n');
10073
- // }
10074
- /** Trim whitespaces from html */
10075
- function trimHtml(str) {
10076
- return str
10077
- .replace(/(<\/?(br *\/?|p)>|&nbsp;|\s)*$/i, '')
10078
- .replace(/^(<\/?(br *\/?|p)>|&nbsp;|\s)*/i, '')
10079
- .replace(/^<(div|p)>(<\/?(br *\/?|p)>|&nbsp;|\s)*<\/ *(div|p)>$/i, '');
10080
- }
10081
-
10082
- // First version based on https://stackoverflow.com/a/41253897/6813271
10083
- class ContenteditableDirective {
10084
- constructor(elRef, sanitizer) {
10085
- this.elRef = elRef;
10086
- this.sanitizer = sanitizer;
10087
- this.lxContenteditableModelChange = new EventEmitter();
10088
- /** Allow (sanitized) html */
10089
- this.lxContenteditableHtml = false;
10090
- this.lxContenteditableHtmlPaste = true;
10091
- this.emittedValue = null;
10002
+ const Caption = Node$1.create({
10003
+ name: 'caption',
10004
+ group: 'block',
10005
+ content: 'inline*',
10006
+ defining: true,
10007
+ parseHTML() {
10008
+ return [{ tag: 'p[data-type="caption"]' }];
10009
+ },
10010
+ renderHTML({ HTMLAttributes }) {
10011
+ return ['p', mergeAttributes(HTMLAttributes, { 'data-type': 'caption' }), 0];
10012
+ },
10013
+ addCommands() {
10014
+ return {
10015
+ setCaption: () => ({ commands }) => commands.setNode(this.name)
10016
+ };
10092
10017
  }
10093
- ngOnChanges(changes) {
10094
- if (changes['lxContenteditableModel']) {
10095
- // On init: if lxContenteditableModel is empty, read from DOM in case the element has content
10096
- if (changes['lxContenteditableModel'].isFirstChange() && !this.lxContenteditableModel) {
10097
- // Prevent Exp.HasChanged: Don't read and emit value from DOM during change detection
10098
- setTimeout(() => {
10099
- this.onInput(true);
10100
- });
10018
+ });
10019
+
10020
+ const highlightTermStatePluginKey = new PluginKey('highlight-term-state');
10021
+ function highlightTermState(_editor) {
10022
+ return new Plugin({
10023
+ key: highlightTermStatePluginKey,
10024
+ state: {
10025
+ init() {
10026
+ return { term: null };
10027
+ },
10028
+ apply: (tr, state) => {
10029
+ const meta = tr.getMeta(highlightTermStatePluginKey);
10030
+ return meta ? { ...state, ...meta } : state;
10101
10031
  }
10102
- this.refreshView();
10103
10032
  }
10104
- }
10105
- onInput(initialInlineData = false) {
10106
- let value = this.elRef.nativeElement[this.getProperty()];
10107
- value = this.cleanContent(value, initialInlineData);
10108
- this.emittedValue = value;
10109
- this.lxContenteditableModelChange.emit(value);
10110
- }
10111
- /**
10112
- * @param event {ClipboardEvent}
10113
- */
10114
- onPaste(event) {
10115
- const clipboardEvent = event;
10116
- this.onInput();
10117
- // For text-only contenteditable, remove pasted HTML.
10118
- if (!this.lxContenteditableHtml || !this.lxContenteditableHtmlPaste) {
10119
- let isHtml = true;
10120
- // TODO: Use beforepaste event. See https://www.lucidchart.com/techblog/2014/12/02/definitive-guide-copying-pasting-javascript/.
10121
- if (clipboardEvent.clipboardData && clipboardEvent.clipboardData.types) {
10122
- const types = [].slice.apply(clipboardEvent.clipboardData.types);
10123
- isHtml = intersection(types, ['text/html', 'com.apple.webarchive']).length > 0;
10124
- }
10125
- if (isHtml) {
10126
- // 1 tick wait is required for DOM update
10127
- setTimeout(() => {
10128
- // Cursor will be lost
10129
- // The lint disabling here should be clearified. See if and how this directive is needed.
10130
- this.elRef.nativeElement.innerHTML = this.sanitizer.sanitize(SecurityContext.HTML, this.elRef.nativeElement.innerText.replace(/\n/g, '<br />'));
10131
- });
10033
+ });
10034
+ }
10035
+
10036
+ const highlightTermPluginKey = new PluginKey('highlight-term');
10037
+ function highlightTerm(_editor, options) {
10038
+ return new Plugin({
10039
+ key: highlightTermPluginKey,
10040
+ state: {
10041
+ init(_, state) {
10042
+ const term = highlightTermStatePluginKey.getState(state)?.term ?? null;
10043
+ return createDecorations(state.doc, term ?? null, options);
10044
+ },
10045
+ apply(tr, oldDecorationSet, state) {
10046
+ const meta = tr.getMeta(highlightTermStatePluginKey);
10047
+ const oldTerm = highlightTermStatePluginKey.getState(state)?.term ?? null;
10048
+ const termChanged = meta?.term && meta.term !== oldTerm;
10049
+ if (tr.docChanged || termChanged) {
10050
+ return createDecorations(tr.doc, meta?.term || oldTerm, options);
10051
+ }
10052
+ return oldDecorationSet.map(tr.mapping, tr.doc);
10132
10053
  }
10133
- }
10134
- }
10135
- onDrop(event) {
10136
- this.onInput();
10137
- // For text-only contenteditable, don't allow drop content.
10138
- if (!this.lxContenteditableHtml || !this.lxContenteditableHtmlPaste) {
10139
- event.preventDefault();
10140
- event.stopPropagation();
10141
- return false;
10142
- }
10143
- return false;
10144
- }
10145
- cleanContent(value, initialInlineData = false) {
10146
- if (this.lxContenteditableHtml === 'trim' || (this.lxContenteditableHtml && initialInlineData)) {
10147
- value = trimHtml(value);
10148
- }
10149
- else if (initialInlineData && !this.lxContenteditableHtml && value) {
10150
- value = value.replace(/^[\n\s]+/, '');
10151
- value = value.replace(/[\n\s]+$/, '');
10152
- }
10153
- // Some browsers like Chrome insert nbsp; when using contentEditable attribute
10154
- return new NbspPipe().transform(value);
10155
- }
10156
- refreshView() {
10157
- if (!isNil(this.lxContenteditableModel)) {
10158
- const newContent = this.cleanContent(this.lxContenteditableModel);
10159
- // Only refresh if content changed to avoid cursor loss
10160
- // (as ngOnChanges can be triggered an additional time by onInput())
10161
- if (this.emittedValue === null || this.emittedValue !== newContent) {
10162
- this.elRef.nativeElement[this.getProperty()] = this.sanitize(newContent);
10054
+ },
10055
+ props: {
10056
+ decorations(state) {
10057
+ return this.getState(state);
10163
10058
  }
10164
10059
  }
10165
- }
10166
- getProperty() {
10167
- return this.lxContenteditableHtml ? 'innerHTML' : 'innerText';
10168
- }
10169
- sanitize(content) {
10170
- return this.lxContenteditableHtml ? this.sanitizer.sanitize(SecurityContext.HTML, content) : content;
10171
- }
10172
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ContenteditableDirective, deps: [{ token: i0.ElementRef }, { token: i1$6.DomSanitizer }], target: i0.ɵɵFactoryTarget.Directive }); }
10173
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: ContenteditableDirective, isStandalone: true, selector: "[lxContenteditableModel]", inputs: { lxContenteditableModel: "lxContenteditableModel", lxContenteditableHtml: "lxContenteditableHtml", lxContenteditableHtmlPaste: "lxContenteditableHtmlPaste" }, outputs: { lxContenteditableModelChange: "lxContenteditableModelChange" }, host: { listeners: { "input": "onInput()", "blur": "onInput()", "keyup": "onInput()", "paste": "onPaste($event)", "drop": "onDrop($event)" } }, usesOnChanges: true, ngImport: i0 }); }
10174
- }
10175
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ContenteditableDirective, decorators: [{
10176
- type: Directive,
10177
- args: [{
10178
- selector: '[lxContenteditableModel]'
10179
- }]
10180
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1$6.DomSanitizer }], propDecorators: { lxContenteditableModel: [{
10181
- type: Input
10182
- }], lxContenteditableModelChange: [{
10183
- type: Output
10184
- }], lxContenteditableHtml: [{
10185
- type: Input
10186
- }], lxContenteditableHtmlPaste: [{
10187
- type: Input
10188
- }], onInput: [{
10189
- type: HostListener,
10190
- args: ['input']
10191
- }, {
10192
- type: HostListener,
10193
- args: ['blur']
10194
- }, {
10195
- type: HostListener,
10196
- args: ['keyup']
10197
- }], onPaste: [{
10198
- type: HostListener,
10199
- args: ['paste', ['$event']]
10200
- }], onDrop: [{
10201
- type: HostListener,
10202
- args: ['drop', ['$event']]
10203
- }] } });
10204
-
10205
- class FormSubmitDirective {
10206
- constructor(elementRef) {
10207
- this.elementRef = elementRef;
10208
- this.submitted$ = new BehaviorSubject(false);
10209
- this.subscription = fromEvent(this.elementRef.nativeElement, 'submit')
10210
- .pipe(take(1))
10211
- .subscribe(() => this.submitted$.next(true));
10212
- }
10213
- ngOnDestroy() {
10214
- if (this.subscription) {
10215
- this.subscription.unsubscribe();
10216
- }
10217
- }
10218
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FormSubmitDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
10219
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: FormSubmitDirective, isStandalone: true, selector: "form", ngImport: i0 }); }
10220
- }
10221
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FormSubmitDirective, decorators: [{
10222
- type: Directive,
10223
- args: [{
10224
- // eslint-disable-next-line @angular-eslint/directive-selector
10225
- selector: 'form'
10226
- }]
10227
- }], ctorParameters: () => [{ type: i0.ElementRef }] });
10228
-
10229
- const FORM_CONTROL_ERROR_NAMESPACE = new InjectionToken('FORM_CONTROL_ERROR_NAMESPACE');
10230
- const FORM_CONTROL_ERROR_DISPLAY_STRATEGY = new InjectionToken('FORM_CONTROL_ERROR_DISPLAY_STRATEGY');
10231
- const provideFormControlErrorNamespace = (namespace) => ({
10232
- provide: FORM_CONTROL_ERROR_NAMESPACE,
10233
- useValue: namespace
10234
- });
10235
- const provideFormControlErrorDisplayStrategy = (fn) => ({
10236
- provide: FORM_CONTROL_ERROR_DISPLAY_STRATEGY,
10237
- useValue: fn
10238
- });
10239
- class FormErrorDirective {
10240
- get control() {
10241
- return this.ngControl?.control || this.ctrl || null;
10242
- }
10243
- get name() {
10244
- return this.ngControl?.name || this.controlName;
10245
- }
10246
- get formSubmitted() {
10247
- return this.formSubmitDirective ? this.formSubmitDirective.submitted$ : of(undefined);
10248
- }
10249
- constructor(viewContainer, componentFactoryResolver, translateService, destroyRef, ngControl, formSubmitDirective, namespace, strategy) {
10250
- this.viewContainer = viewContainer;
10251
- this.componentFactoryResolver = componentFactoryResolver;
10252
- this.translateService = translateService;
10253
- this.destroyRef = destroyRef;
10254
- this.ngControl = ngControl;
10255
- this.formSubmitDirective = formSubmitDirective;
10256
- this.namespace = namespace;
10257
- this.strategy = strategy;
10258
- }
10259
- ngOnInit() {
10260
- const control = this.control;
10261
- if (isAbstractControl(control)) {
10262
- combineLatest([control.valueChanges.pipe(startWith(control.value)), this.formSubmitted])
10263
- .pipe(map(([, submitted]) => submitted), map(resolveStrategy(this.strategy, control)), takeUntilDestroyed(this.destroyRef))
10264
- .subscribe((display) => {
10265
- const { errors } = control;
10266
- if (errors && display) {
10267
- const firstErrorKey = Object.keys(errors)[0];
10268
- const translationKey = this.buildTranslationKey(firstErrorKey);
10269
- this.setError(translationKey);
10270
- }
10271
- else if (this.ref) {
10272
- this.setError();
10273
- }
10274
- });
10275
- }
10276
- }
10277
- buildTranslationKey(errorKey) {
10278
- if (this.control) {
10279
- return `${this.namespace || 'form'}.errors.${this.name ? `${this.name}.` : ''}${errorKey}`;
10280
- }
10281
- else {
10282
- return '';
10283
- }
10284
- }
10285
- setError(key) {
10286
- if (!this.ref) {
10287
- const factory = this.componentFactoryResolver.resolveComponentFactory(ErrorMessageComponent);
10288
- this.ref = this.viewContainer.createComponent(factory);
10289
- }
10290
- if (key) {
10291
- this.translateService
10292
- .get(key)
10293
- .pipe(takeUntilDestroyed(this.destroyRef))
10294
- .subscribe((message) => {
10295
- if (this.ref) {
10296
- this.ref.instance.dynamicErrorMessage.set(message);
10297
- }
10298
- });
10299
- }
10300
- else {
10301
- this.ref.instance.dynamicErrorMessage.set('');
10302
- }
10303
- }
10304
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FormErrorDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.ComponentFactoryResolver }, { token: i1$1.TranslateService }, { token: i0.DestroyRef }, { token: i2$2.NgControl, optional: true, self: true }, { token: FormSubmitDirective, host: true, optional: true }, { token: FORM_CONTROL_ERROR_NAMESPACE, optional: true }, { token: FORM_CONTROL_ERROR_DISPLAY_STRATEGY, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
10305
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: FormErrorDirective, isStandalone: true, selector: "[lxFormError]", inputs: { ctrl: ["lxFormError", "ctrl"], controlName: "controlName" }, ngImport: i0 }); }
10306
- }
10307
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FormErrorDirective, decorators: [{
10308
- type: Directive,
10309
- args: [{
10310
- selector: '[lxFormError]'
10311
- }]
10312
- }], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: i0.ComponentFactoryResolver }, { type: i1$1.TranslateService }, { type: i0.DestroyRef }, { type: i2$2.NgControl, decorators: [{
10313
- type: Optional
10314
- }, {
10315
- type: Self
10316
- }] }, { type: FormSubmitDirective, decorators: [{
10317
- type: Optional
10318
- }, {
10319
- type: Host
10320
- }] }, { type: undefined, decorators: [{
10321
- type: Optional
10322
- }, {
10323
- type: Inject,
10324
- args: [FORM_CONTROL_ERROR_NAMESPACE]
10325
- }] }, { type: undefined, decorators: [{
10326
- type: Optional
10327
- }, {
10328
- type: Inject,
10329
- args: [FORM_CONTROL_ERROR_DISPLAY_STRATEGY]
10330
- }] }], propDecorators: { ctrl: [{
10331
- type: Input,
10332
- args: ['lxFormError']
10333
- }], controlName: [{
10334
- type: Input
10335
- }] } });
10336
- const isAbstractControl = (ctrl) => !!ctrl;
10337
- const resolveStrategy = curry((strategy, control, submitted) => strategy ? strategy({ control, submitted }) : true);
10338
-
10339
- class FilterSelectionPipe {
10340
- transform(items, selection, itemKey) {
10341
- const isArray = Array.isArray(selection);
10342
- return filter$1((item) => {
10343
- if (isArray) {
10344
- if (isObject(item)) {
10345
- return itemKey
10346
- ? !find((selectedItem) => selectedItem?.[itemKey] === item?.[itemKey], selection)
10347
- : !find(item, selection);
10348
- }
10349
- else {
10350
- return !includes(item, selection);
10351
- }
10352
- }
10353
- else {
10354
- return !isEqual$1(item, selection);
10355
- }
10356
- }, items);
10357
- }
10358
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FilterSelectionPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
10359
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: FilterSelectionPipe, isStandalone: true, name: "lxFilterBySelection" }); }
10360
- }
10361
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FilterSelectionPipe, decorators: [{
10362
- type: Pipe,
10363
- args: [{
10364
- name: 'lxFilterBySelection'
10365
- }]
10366
- }] });
10367
-
10368
- class FilterTermPipe {
10369
- transform(items, options) {
10370
- if (items === null) {
10371
- return [];
10372
- }
10373
- if (options.term) {
10374
- return filter$1((item) => {
10375
- const value = options.key ? item[options.key] : item;
10376
- return toLower(value).indexOf(toLower(options.term)) > -1;
10377
- }, items);
10378
- }
10379
- else {
10380
- return items;
10381
- }
10382
- }
10383
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FilterTermPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
10384
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: FilterTermPipe, isStandalone: true, name: "lxFilterByTerm" }); }
10385
- }
10386
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FilterTermPipe, decorators: [{
10387
- type: Pipe,
10388
- args: [{
10389
- name: 'lxFilterByTerm'
10390
- }]
10391
- }] });
10392
-
10393
- /**
10394
- * Reformats numbers into a short format.
10395
- * @example {{ 1000 | lxFormatNumber | async }} prints 1K
10396
- *
10397
- * If the parameter currency is set, a currency sign is inserted based on the value and the current locale.
10398
- * In this case, the pipe must be used with an innerHtml attribute.
10399
- * @example [innerHtml]="1000 | lxFormatNumber: 'USD' | async" prints $1K
10400
- */
10401
- class FormatNumberPipe {
10402
- constructor(getLocale) {
10403
- this.getLocale = getLocale;
10404
- }
10405
- transform(number, currency) {
10406
- const locale$ = this.getLocale();
10407
- return locale$.pipe(map((locale) => {
10408
- if (number === null || number === undefined) {
10409
- return null;
10410
- }
10411
- const options = {
10412
- notation: 'compact',
10413
- compactDisplay: 'short'
10414
- };
10415
- if (currency) {
10416
- try {
10417
- const currencyOptions = { ...options, currency, style: 'currency' };
10418
- const formatedNumberWithCurrency = new Intl.NumberFormat(locale, currencyOptions).format(number);
10419
- return this.getFormatedCurrency(formatedNumberWithCurrency, currency);
10420
- }
10421
- catch (_error) {
10422
- console.warn(`FormatNumberPipe: Invalid currency code: ${currency}`);
10423
- return new Intl.NumberFormat(locale, options).format(number);
10424
- }
10425
- }
10426
- return new Intl.NumberFormat(locale, options).format(number);
10427
- }));
10428
- }
10429
- /**
10430
- * Use custom currency symbol, when the currency in the formated number doesn't match the
10431
- * symbol in the CURRENCY_SYMBOL_MAP.
10432
- */
10433
- getFormatedCurrency(formatedNumberWitCurrency, currency) {
10434
- const currencyMapping = CURRENCY_SYMBOL_MAP[currency];
10435
- if (currencyMapping && currencyMapping !== currency && !formatedNumberWitCurrency.includes(currencyMapping)) {
10436
- return formatedNumberWitCurrency.replace(currency, currencyMapping);
10437
- }
10438
- return formatedNumberWitCurrency;
10439
- }
10440
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FormatNumberPipe, deps: [{ token: LOCALE_FN }], target: i0.ɵɵFactoryTarget.Pipe }); }
10441
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: FormatNumberPipe, isStandalone: true, name: "lxFormatNumber" }); }
10442
- }
10443
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FormatNumberPipe, decorators: [{
10444
- type: Pipe,
10445
- args: [{
10446
- name: 'lxFormatNumber'
10447
- }]
10448
- }], ctorParameters: () => [{ type: Function, decorators: [{
10449
- type: Inject,
10450
- args: [LOCALE_FN]
10451
- }] }] });
10452
-
10453
- const FORMS_MODULE_EXPORTS = [
10454
- BasicDropdownComponent,
10455
- BasicDropdownItemComponent,
10456
- BreadcrumbComponent,
10457
- CurrencyInputComponent,
10458
- CurrencySymbolComponent,
10459
- DateInputComponent,
10460
- FilterSelectionPipe,
10461
- FilterTermPipe,
10462
- FormErrorComponent,
10463
- KeyboardActionSourceDirective,
10464
- MarkInvalidDirective,
10465
- MultiSelectComponent,
10466
- OptionComponent,
10467
- OptionGroupComponent,
10468
- OptionGroupDropdownComponent,
10469
- OptionsDropdownComponent,
10470
- OptionsSubDropdownComponent,
10471
- CdkOptionsDropdownComponent,
10472
- CdkOptionsSubDropdownComponent,
10473
- PickerComponent,
10474
- PickerOptionComponent,
10475
- PickerTriggerDirective,
10476
- PillListComponent,
10477
- PillItemComponent,
10478
- ResponsiveInputComponent,
10479
- SelectableItemDirective,
10480
- SelectDropdownDirective,
10481
- SelectedOptionDirective,
10482
- SingleSelectComponent,
10483
- SwitchComponent,
10484
- SortingDropdownComponent,
10485
- SortingDropdownTriggerComponent,
10486
- FormatNumberPipe,
10487
- FormErrorDirective,
10488
- FormSubmitDirective,
10489
- ErrorMessageComponent,
10490
- LxDragAndDropListModule,
10491
- ContenteditableDirective,
10492
- InputComponent
10493
- ];
10494
- class LxFormsModule {
10495
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: LxFormsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
10496
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: LxFormsModule, imports: [CommonModule,
10497
- FormsModule,
10498
- ReactiveFormsModule, i1$1.TranslateModule, DatepickerUiModule, InfiniteScrollModule,
10499
- ClipboardModule,
10500
- OverlayModule,
10501
- LxDragAndDropListModule,
10502
- BasicDropdownComponent,
10503
- BasicDropdownItemComponent,
10504
- BreadcrumbComponent,
10505
- CurrencyInputComponent,
10506
- CurrencySymbolComponent,
10507
- DateInputComponent,
10508
- FilterSelectionPipe,
10509
- FilterTermPipe,
10510
- FormErrorComponent,
10511
- KeyboardActionSourceDirective,
10512
- MarkInvalidDirective,
10513
- MultiSelectComponent,
10514
- OptionComponent,
10515
- OptionGroupComponent,
10516
- OptionGroupDropdownComponent,
10517
- OptionsDropdownComponent,
10518
- OptionsSubDropdownComponent,
10519
- CdkOptionsDropdownComponent,
10520
- CdkOptionsSubDropdownComponent,
10521
- PickerComponent,
10522
- PickerOptionComponent,
10523
- PickerTriggerDirective,
10524
- PillListComponent,
10525
- PillItemComponent,
10526
- ResponsiveInputComponent,
10527
- SelectableItemDirective,
10528
- SelectedOptionDirective,
10529
- SelectDropdownDirective,
10530
- SingleSelectComponent,
10531
- SwitchComponent,
10532
- SortingDropdownComponent,
10533
- SortingDropdownTriggerComponent,
10534
- InputComponent,
10535
- FormatNumberPipe,
10536
- FormErrorDirective,
10537
- ErrorMessageComponent,
10538
- FormSubmitDirective,
10539
- ContenteditableDirective], exports: [BasicDropdownComponent,
10540
- BasicDropdownItemComponent,
10541
- BreadcrumbComponent,
10542
- CurrencyInputComponent,
10543
- CurrencySymbolComponent,
10544
- DateInputComponent,
10545
- FilterSelectionPipe,
10546
- FilterTermPipe,
10547
- FormErrorComponent,
10548
- KeyboardActionSourceDirective,
10549
- MarkInvalidDirective,
10550
- MultiSelectComponent,
10551
- OptionComponent,
10552
- OptionGroupComponent,
10553
- OptionGroupDropdownComponent,
10554
- OptionsDropdownComponent,
10555
- OptionsSubDropdownComponent,
10556
- CdkOptionsDropdownComponent,
10557
- CdkOptionsSubDropdownComponent,
10558
- PickerComponent,
10559
- PickerOptionComponent,
10560
- PickerTriggerDirective,
10561
- PillListComponent,
10562
- PillItemComponent,
10563
- ResponsiveInputComponent,
10564
- SelectableItemDirective,
10565
- SelectDropdownDirective,
10566
- SelectedOptionDirective,
10567
- SingleSelectComponent,
10568
- SwitchComponent,
10569
- SortingDropdownComponent,
10570
- SortingDropdownTriggerComponent,
10571
- FormatNumberPipe,
10572
- FormErrorDirective,
10573
- FormSubmitDirective,
10574
- ErrorMessageComponent,
10575
- LxDragAndDropListModule,
10576
- ContenteditableDirective,
10577
- InputComponent] }); }
10578
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: LxFormsModule, imports: [CommonModule,
10579
- FormsModule,
10580
- ReactiveFormsModule,
10581
- TranslateModule.forChild(),
10582
- DatepickerUiModule.forRoot(),
10583
- InfiniteScrollModule,
10584
- ClipboardModule,
10585
- OverlayModule,
10586
- LxDragAndDropListModule,
10587
- BasicDropdownComponent,
10588
- BreadcrumbComponent,
10589
- CurrencyInputComponent,
10590
- DateInputComponent,
10591
- FormErrorComponent,
10592
- MultiSelectComponent,
10593
- OptionComponent,
10594
- OptionGroupDropdownComponent,
10595
- PickerOptionComponent,
10596
- PillListComponent,
10597
- PillItemComponent,
10598
- ResponsiveInputComponent,
10599
- SingleSelectComponent,
10600
- SortingDropdownComponent,
10601
- SortingDropdownTriggerComponent,
10602
- InputComponent, LxDragAndDropListModule] }); }
10603
- }
10604
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: LxFormsModule, decorators: [{
10605
- type: NgModule,
10606
- args: [{
10607
- imports: [
10608
- CommonModule,
10609
- FormsModule,
10610
- ReactiveFormsModule,
10611
- TranslateModule.forChild(),
10612
- DatepickerUiModule.forRoot(),
10613
- InfiniteScrollModule,
10614
- ClipboardModule,
10615
- OverlayModule,
10616
- LxDragAndDropListModule,
10617
- BasicDropdownComponent,
10618
- BasicDropdownItemComponent,
10619
- BreadcrumbComponent,
10620
- CurrencyInputComponent,
10621
- CurrencySymbolComponent,
10622
- DateInputComponent,
10623
- FilterSelectionPipe,
10624
- FilterTermPipe,
10625
- FormErrorComponent,
10626
- KeyboardActionSourceDirective,
10627
- MarkInvalidDirective,
10628
- MultiSelectComponent,
10629
- OptionComponent,
10630
- OptionGroupComponent,
10631
- OptionGroupDropdownComponent,
10632
- OptionsDropdownComponent,
10633
- OptionsSubDropdownComponent,
10634
- CdkOptionsDropdownComponent,
10635
- CdkOptionsSubDropdownComponent,
10636
- PickerComponent,
10637
- PickerOptionComponent,
10638
- PickerTriggerDirective,
10639
- PillListComponent,
10640
- PillItemComponent,
10641
- ResponsiveInputComponent,
10642
- SelectableItemDirective,
10643
- SelectedOptionDirective,
10644
- SelectDropdownDirective,
10645
- SingleSelectComponent,
10646
- SwitchComponent,
10647
- SortingDropdownComponent,
10648
- SortingDropdownTriggerComponent,
10649
- InputComponent,
10650
- FormatNumberPipe,
10651
- FormErrorDirective,
10652
- ErrorMessageComponent,
10653
- FormSubmitDirective,
10654
- ContenteditableDirective
10655
- ],
10656
- exports: FORMS_MODULE_EXPORTS
10657
- }]
10658
- }] });
10659
-
10660
- const Caption = Node$1.create({
10661
- name: 'caption',
10662
- group: 'block',
10663
- content: 'inline*',
10664
- defining: true,
10665
- parseHTML() {
10666
- return [{ tag: 'p[data-type="caption"]' }];
10667
- },
10668
- renderHTML({ HTMLAttributes }) {
10669
- return ['p', mergeAttributes(HTMLAttributes, { 'data-type': 'caption' }), 0];
10670
- },
10671
- addCommands() {
10672
- return {
10673
- setCaption: () => ({ commands }) => commands.setNode(this.name)
10674
- };
10675
- }
10676
- });
10677
-
10678
- const highlightTermStatePluginKey = new PluginKey('highlight-term-state');
10679
- function highlightTermState(_editor) {
10680
- return new Plugin({
10681
- key: highlightTermStatePluginKey,
10682
- state: {
10683
- init() {
10684
- return { term: null };
10685
- },
10686
- apply: (tr, state) => {
10687
- const meta = tr.getMeta(highlightTermStatePluginKey);
10688
- return meta ? { ...state, ...meta } : state;
10689
- }
10690
- }
10691
- });
10692
- }
10693
-
10694
- const highlightTermPluginKey = new PluginKey('highlight-term');
10695
- function highlightTerm(_editor, options) {
10696
- return new Plugin({
10697
- key: highlightTermPluginKey,
10698
- state: {
10699
- init(_, state) {
10700
- const term = highlightTermStatePluginKey.getState(state)?.term ?? null;
10701
- return createDecorations(state.doc, term ?? null, options);
10702
- },
10703
- apply(tr, oldDecorationSet, state) {
10704
- const meta = tr.getMeta(highlightTermStatePluginKey);
10705
- const oldTerm = highlightTermStatePluginKey.getState(state)?.term ?? null;
10706
- const termChanged = meta?.term && meta.term !== oldTerm;
10707
- if (tr.docChanged || termChanged) {
10708
- return createDecorations(tr.doc, meta?.term || oldTerm, options);
10709
- }
10710
- return oldDecorationSet.map(tr.mapping, tr.doc);
10711
- }
10712
- },
10713
- props: {
10714
- decorations(state) {
10715
- return this.getState(state);
10716
- }
10717
- }
10718
- });
10060
+ });
10719
10061
  }
10720
10062
  function createDecorations(doc, term, options) {
10721
10063
  const decorations = [];
@@ -12347,343 +11689,634 @@ class FocusEditorDirective {
12347
11689
  this.editor().commands.focus('start');
12348
11690
  });
12349
11691
  }
12350
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FocusEditorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
12351
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: FocusEditorDirective, isStandalone: true, selector: "lx-rich-text-editor[lxFocusEditor]", ngImport: i0 }); }
12352
- }
12353
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FocusEditorDirective, decorators: [{
12354
- type: Directive,
12355
- args: [{
12356
- selector: 'lx-rich-text-editor[lxFocusEditor]'
12357
- }]
12358
- }] });
12359
-
12360
- class HighlightTermDirective {
12361
- constructor() {
12362
- this.lxHighlightTerm = input(...(ngDevMode ? [undefined, { debugName: "lxHighlightTerm" }] : []));
12363
- this.editor = inject(TipTapEditorDirective).editor;
12364
- effect(() => {
12365
- this.editor().view.dispatch(this.editor().view.state.tr.setMeta(highlightTermStatePluginKey, {
12366
- term: this.lxHighlightTerm()
12367
- }));
12368
- });
11692
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FocusEditorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
11693
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: FocusEditorDirective, isStandalone: true, selector: "lx-rich-text-editor[lxFocusEditor]", ngImport: i0 }); }
11694
+ }
11695
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FocusEditorDirective, decorators: [{
11696
+ type: Directive,
11697
+ args: [{
11698
+ selector: 'lx-rich-text-editor[lxFocusEditor]'
11699
+ }]
11700
+ }] });
11701
+
11702
+ class HighlightTermDirective {
11703
+ constructor() {
11704
+ this.lxHighlightTerm = input(...(ngDevMode ? [undefined, { debugName: "lxHighlightTerm" }] : []));
11705
+ this.editor = inject(TipTapEditorDirective).editor;
11706
+ effect(() => {
11707
+ this.editor().view.dispatch(this.editor().view.state.tr.setMeta(highlightTermStatePluginKey, {
11708
+ term: this.lxHighlightTerm()
11709
+ }));
11710
+ });
11711
+ }
11712
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: HighlightTermDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
11713
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.18", type: HighlightTermDirective, isStandalone: true, selector: "lx-rich-text-editor[lxHighlightTerm]", inputs: { lxHighlightTerm: { classPropertyName: "lxHighlightTerm", publicName: "lxHighlightTerm", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
11714
+ }
11715
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: HighlightTermDirective, decorators: [{
11716
+ type: Directive,
11717
+ args: [{
11718
+ selector: 'lx-rich-text-editor[lxHighlightTerm]'
11719
+ }]
11720
+ }], ctorParameters: () => [], propDecorators: { lxHighlightTerm: [{ type: i0.Input, args: [{ isSignal: true, alias: "lxHighlightTerm", required: false }] }] } });
11721
+
11722
+ class PlaceholderDirective {
11723
+ constructor() {
11724
+ this.lxPlaceholder = input(...(ngDevMode ? [undefined, { debugName: "lxPlaceholder" }] : []));
11725
+ this.editor = inject(TipTapEditorDirective).editor;
11726
+ effect(() => {
11727
+ const extension = this.editor().extensionManager.extensions.find((e) => e.name === 'placeholder');
11728
+ if (extension) {
11729
+ extension.options['placeholder'] = this.lxPlaceholder() ?? '';
11730
+ this.editor().view.dispatch(this.editor().view.state.tr);
11731
+ }
11732
+ });
11733
+ }
11734
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: PlaceholderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
11735
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.18", type: PlaceholderDirective, isStandalone: true, selector: "lx-rich-text-editor[lxPlaceholder]", inputs: { lxPlaceholder: { classPropertyName: "lxPlaceholder", publicName: "lxPlaceholder", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
11736
+ }
11737
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: PlaceholderDirective, decorators: [{
11738
+ type: Directive,
11739
+ args: [{
11740
+ selector: 'lx-rich-text-editor[lxPlaceholder]'
11741
+ }]
11742
+ }], ctorParameters: () => [], propDecorators: { lxPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "lxPlaceholder", required: false }] }] } });
11743
+
11744
+ class TruncateDirective {
11745
+ constructor() {
11746
+ this.lxTruncate = input(...(ngDevMode ? [undefined, { debugName: "lxTruncate" }] : []));
11747
+ this.editor = inject(TipTapEditorDirective).editor;
11748
+ effect(() => {
11749
+ const options = this.lxTruncate();
11750
+ if (options) {
11751
+ this.editor().view.dispatch(this.editor().view.state.tr.setMeta(truncatePluginKey, options));
11752
+ }
11753
+ });
11754
+ }
11755
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TruncateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
11756
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.18", type: TruncateDirective, isStandalone: true, selector: "lx-rich-text-editor[lxTruncate]", inputs: { lxTruncate: { classPropertyName: "lxTruncate", publicName: "lxTruncate", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
11757
+ }
11758
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TruncateDirective, decorators: [{
11759
+ type: Directive,
11760
+ args: [{
11761
+ selector: 'lx-rich-text-editor[lxTruncate]'
11762
+ }]
11763
+ }], ctorParameters: () => [], propDecorators: { lxTruncate: [{ type: i0.Input, args: [{ isSignal: true, alias: "lxTruncate", required: false }] }] } });
11764
+
11765
+ /**
11766
+ * Base component for custom Tiptap node views in Angular.
11767
+ *
11768
+ * Extend this component to create custom node views for the rich text editor.
11769
+ * Provides all Tiptap NodeViewProps as required input signals.
11770
+ */
11771
+ // eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
11772
+ class AngularNodeViewComponent {
11773
+ constructor() {
11774
+ /** The Tiptap editor instance. */
11775
+ this.editor = input.required(...(ngDevMode ? [{ debugName: "editor" }] : []));
11776
+ /** The ProseMirror node being rendered. */
11777
+ this.node = input.required(...(ngDevMode ? [{ debugName: "node" }] : []));
11778
+ /** Array of decorations for this node. */
11779
+ this.decorations = input.required(...(ngDevMode ? [{ debugName: "decorations" }] : []));
11780
+ /** Whether the node is currently selected. */
11781
+ this.selected = input.required(...(ngDevMode ? [{ debugName: "selected" }] : []));
11782
+ /** The Tiptap extension that created this node. */
11783
+ this.extension = input.required(...(ngDevMode ? [{ debugName: "extension" }] : []));
11784
+ /** Function to get the node's position in the document. */
11785
+ this.getPos = input.required(...(ngDevMode ? [{ debugName: "getPos" }] : []));
11786
+ /** Function to update the node's attributes. */
11787
+ this.updateAttributes = input.required(...(ngDevMode ? [{ debugName: "updateAttributes" }] : []));
11788
+ /** Function to delete the node from the document. */
11789
+ this.deleteNode = input.required(...(ngDevMode ? [{ debugName: "deleteNode" }] : []));
11790
+ }
11791
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AngularNodeViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
11792
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.18", type: AngularNodeViewComponent, isStandalone: true, selector: "ng-component", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, decorations: { classPropertyName: "decorations", publicName: "decorations", isSignal: true, isRequired: true, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: true, transformFunction: null }, extension: { classPropertyName: "extension", publicName: "extension", isSignal: true, isRequired: true, transformFunction: null }, getPos: { classPropertyName: "getPos", publicName: "getPos", isSignal: true, isRequired: true, transformFunction: null }, updateAttributes: { classPropertyName: "updateAttributes", publicName: "updateAttributes", isSignal: true, isRequired: true, transformFunction: null }, deleteNode: { classPropertyName: "deleteNode", publicName: "deleteNode", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: '', isInline: true }); }
11793
+ }
11794
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AngularNodeViewComponent, decorators: [{
11795
+ type: Component,
11796
+ args: [{
11797
+ template: ''
11798
+ }]
11799
+ }], propDecorators: { editor: [{ type: i0.Input, args: [{ isSignal: true, alias: "editor", required: true }] }], node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: true }] }], decorations: [{ type: i0.Input, args: [{ isSignal: true, alias: "decorations", required: true }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: true }] }], extension: [{ type: i0.Input, args: [{ isSignal: true, alias: "extension", required: true }] }], getPos: [{ type: i0.Input, args: [{ isSignal: true, alias: "getPos", required: true }] }], updateAttributes: [{ type: i0.Input, args: [{ isSignal: true, alias: "updateAttributes", required: true }] }], deleteNode: [{ type: i0.Input, args: [{ isSignal: true, alias: "deleteNode", required: true }] }] } });
11800
+
11801
+ class AngularRenderer {
11802
+ constructor(ViewComponent, injector, props) {
11803
+ this.applicationRef = injector.get(ApplicationRef);
11804
+ this.componentRef = createComponent(ViewComponent, {
11805
+ environmentInjector: this.applicationRef.injector,
11806
+ elementInjector: injector
11807
+ });
11808
+ // set input props to the component
11809
+ this.updateProps(props);
11810
+ this.applicationRef.attachView(this.componentRef.hostView);
11811
+ }
11812
+ get instance() {
11813
+ return this.componentRef.instance;
11814
+ }
11815
+ get elementRef() {
11816
+ return this.componentRef.injector.get(ElementRef);
11817
+ }
11818
+ get dom() {
11819
+ return this.elementRef.nativeElement;
11820
+ }
11821
+ updateProps(props) {
11822
+ Object.entries(props).forEach(([key, value]) => {
11823
+ this.componentRef.setInput(key, value);
11824
+ });
11825
+ }
11826
+ detectChanges() {
11827
+ this.componentRef.changeDetectorRef.detectChanges();
11828
+ }
11829
+ destroy() {
11830
+ this.componentRef.destroy();
11831
+ this.applicationRef.detachView(this.componentRef.hostView);
11832
+ }
11833
+ }
11834
+
11835
+ class AngularNodeView extends NodeView {
11836
+ mount() {
11837
+ const injector = this.options.injector;
11838
+ const props = {
11839
+ editor: this.editor,
11840
+ node: this.node,
11841
+ decorations: this.decorations,
11842
+ selected: false,
11843
+ extension: this.extension,
11844
+ getPos: () => this.getPos(),
11845
+ updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
11846
+ deleteNode: () => this.deleteNode()
11847
+ };
11848
+ this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
11849
+ this.handleBlur = this.handleBlur.bind(this);
11850
+ this.editor.on('selectionUpdate', this.handleSelectionUpdate);
11851
+ this.editor.on('blur', this.handleBlur);
11852
+ // create renderer
11853
+ this.renderer = new AngularRenderer(this.component, injector, props);
11854
+ // Register drag handler
11855
+ if (this.extension.config.draggable) {
11856
+ this.renderer.elementRef.nativeElement.ondragstart = (e) => {
11857
+ this.onDragStart(e);
11858
+ };
11859
+ }
11860
+ this.contentDOMElement = this.node.isLeaf ? null : document.createElement(this.node.isInline ? 'span' : 'div');
11861
+ if (this.contentDOMElement) {
11862
+ // For some reason the whiteSpace prop is not inherited properly in Chrome and Safari
11863
+ // With this fix it seems to work fine
11864
+ // See: https://github.com/ueberdosis/tiptap/issues/1197
11865
+ this.contentDOMElement.style.whiteSpace = 'inherit';
11866
+ // Required for editable node views
11867
+ // The content won't be rendered if `editable` is set to `false`
11868
+ this.renderer.detectChanges();
11869
+ }
11870
+ this.appendContendDom();
11871
+ /**
11872
+ * Ensure the node is selected when clicked.
11873
+ *
11874
+ * ProseMirror/Tiptap sometimes does not trigger `selectionUpdate` for single-node editors
11875
+ * or when the node is already implicitly selected. By explicitly creating a NodeSelection
11876
+ * and dispatching it, we force ProseMirror to treat this node as newly selected, which
11877
+ * triggers `handleSelectionUpdate` and updates the NodeView's selected state.
11878
+ */
11879
+ this.handleMouseDown = (event) => {
11880
+ if (!this.editor.isEditable)
11881
+ return;
11882
+ const pos = this.getPos();
11883
+ const nodeSelection = NodeSelection.create(this.editor.state.doc, pos);
11884
+ const tr = this.editor.state.tr.setSelection(nodeSelection);
11885
+ this.editor.view.dispatch(tr);
11886
+ this.editor.view.focus();
11887
+ this.selectNode();
11888
+ event.stopPropagation();
11889
+ };
11890
+ const selection = this.editor.state.selection;
11891
+ if (selection instanceof NodeSelection && selection.node.type.name === 'lxDiagram') {
11892
+ this.dom.addEventListener('mousedown', this.handleMouseDown);
11893
+ }
11894
+ }
11895
+ get dom() {
11896
+ return this.renderer.dom;
11897
+ }
11898
+ get contentDOM() {
11899
+ if (this.node.isLeaf) {
11900
+ return null;
11901
+ }
11902
+ return this.contentDOMElement;
11903
+ }
11904
+ appendContendDom() {
11905
+ const contentElement = this.dom.querySelector('[data-node-view-content]');
11906
+ if (this.contentDOMElement && contentElement && !contentElement.contains(this.contentDOMElement)) {
11907
+ contentElement.appendChild(this.contentDOMElement);
11908
+ }
11909
+ }
11910
+ handleBlur() {
11911
+ this.deselectNode();
11912
+ }
11913
+ handleSelectionUpdate() {
11914
+ const { from, to } = this.editor.state.selection;
11915
+ if (from <= this.getPos() && to >= this.getPos() + this.node.nodeSize) {
11916
+ this.selectNode();
11917
+ }
11918
+ else {
11919
+ this.deselectNode();
11920
+ }
11921
+ }
11922
+ update(node, decorations, _innerDecorations) {
11923
+ const updateProps = () => {
11924
+ this.renderer.updateProps({ node, decorations: decorations });
11925
+ };
11926
+ if (this.options.update) {
11927
+ const oldNode = this.node;
11928
+ const oldDecorations = this.decorations;
11929
+ this.node = node;
11930
+ this.decorations = decorations;
11931
+ return this.options.update({
11932
+ oldNode,
11933
+ oldDecorations,
11934
+ newNode: node,
11935
+ newDecorations: decorations,
11936
+ updateProps: () => updateProps()
11937
+ });
11938
+ }
11939
+ if (node.type !== this.node.type) {
11940
+ return false;
11941
+ }
11942
+ if (node === this.node && this.decorations === decorations) {
11943
+ return true;
11944
+ }
11945
+ this.node = node;
11946
+ this.decorations = decorations;
11947
+ updateProps();
11948
+ return true;
11949
+ }
11950
+ selectNode() {
11951
+ if (!this.editor.isEditable)
11952
+ return;
11953
+ this.renderer.updateProps({ selected: true });
12369
11954
  }
12370
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: HighlightTermDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
12371
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.18", type: HighlightTermDirective, isStandalone: true, selector: "lx-rich-text-editor[lxHighlightTerm]", inputs: { lxHighlightTerm: { classPropertyName: "lxHighlightTerm", publicName: "lxHighlightTerm", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
12372
- }
12373
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: HighlightTermDirective, decorators: [{
12374
- type: Directive,
12375
- args: [{
12376
- selector: 'lx-rich-text-editor[lxHighlightTerm]'
12377
- }]
12378
- }], ctorParameters: () => [], propDecorators: { lxHighlightTerm: [{ type: i0.Input, args: [{ isSignal: true, alias: "lxHighlightTerm", required: false }] }] } });
12379
-
12380
- class PlaceholderDirective {
12381
- constructor() {
12382
- this.lxPlaceholder = input(...(ngDevMode ? [undefined, { debugName: "lxPlaceholder" }] : []));
12383
- this.editor = inject(TipTapEditorDirective).editor;
12384
- effect(() => {
12385
- const extension = this.editor().extensionManager.extensions.find((e) => e.name === 'placeholder');
12386
- if (extension) {
12387
- extension.options['placeholder'] = this.lxPlaceholder() ?? '';
12388
- this.editor().view.dispatch(this.editor().view.state.tr);
12389
- }
12390
- });
11955
+ deselectNode() {
11956
+ this.renderer.updateProps({ selected: false });
12391
11957
  }
12392
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: PlaceholderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
12393
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.18", type: PlaceholderDirective, isStandalone: true, selector: "lx-rich-text-editor[lxPlaceholder]", inputs: { lxPlaceholder: { classPropertyName: "lxPlaceholder", publicName: "lxPlaceholder", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
12394
- }
12395
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: PlaceholderDirective, decorators: [{
12396
- type: Directive,
12397
- args: [{
12398
- selector: 'lx-rich-text-editor[lxPlaceholder]'
12399
- }]
12400
- }], ctorParameters: () => [], propDecorators: { lxPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "lxPlaceholder", required: false }] }] } });
12401
-
12402
- class TruncateDirective {
12403
- constructor() {
12404
- this.lxTruncate = input(...(ngDevMode ? [undefined, { debugName: "lxTruncate" }] : []));
12405
- this.editor = inject(TipTapEditorDirective).editor;
12406
- effect(() => {
12407
- const options = this.lxTruncate();
12408
- if (options) {
12409
- this.editor().view.dispatch(this.editor().view.state.tr.setMeta(truncatePluginKey, options));
12410
- }
12411
- });
11958
+ destroy() {
11959
+ this.renderer.destroy();
11960
+ this.editor.off('selectionUpdate', this.handleSelectionUpdate);
11961
+ if (this.handleMouseDown) {
11962
+ this.dom.removeEventListener('mousedown', this.handleMouseDown);
11963
+ this.handleMouseDown = undefined;
11964
+ }
11965
+ this.contentDOMElement = null;
12412
11966
  }
12413
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TruncateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
12414
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.18", type: TruncateDirective, isStandalone: true, selector: "lx-rich-text-editor[lxTruncate]", inputs: { lxTruncate: { classPropertyName: "lxTruncate", publicName: "lxTruncate", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
12415
11967
  }
12416
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TruncateDirective, decorators: [{
12417
- type: Directive,
12418
- args: [{
12419
- selector: 'lx-rich-text-editor[lxTruncate]'
12420
- }]
12421
- }], ctorParameters: () => [], propDecorators: { lxTruncate: [{ type: i0.Input, args: [{ isSignal: true, alias: "lxTruncate", required: false }] }] } });
11968
+ const AngularNodeViewRenderer = (ViewComponent, options) => {
11969
+ return (props) => {
11970
+ return new AngularNodeView(ViewComponent, props, options);
11971
+ };
11972
+ };
12422
11973
 
12423
11974
  /**
12424
- * Base component for custom Tiptap node views in Angular.
11975
+ * Removes markdown syntax from text.
11976
+ * e.g '### This is a heading' will become 'This is a heading'
12425
11977
  *
12426
- * Extend this component to create custom node views for the rich text editor.
12427
- * Provides all Tiptap NodeViewProps as required input signals.
11978
+ * It does not remove links. Links can be post processed by LxLinkifyPipe or LxUnLinkifyPipe
12428
11979
  */
12429
- // eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
12430
- class AngularNodeViewComponent {
12431
- constructor() {
12432
- /** The Tiptap editor instance. */
12433
- this.editor = input.required(...(ngDevMode ? [{ debugName: "editor" }] : []));
12434
- /** The ProseMirror node being rendered. */
12435
- this.node = input.required(...(ngDevMode ? [{ debugName: "node" }] : []));
12436
- /** Array of decorations for this node. */
12437
- this.decorations = input.required(...(ngDevMode ? [{ debugName: "decorations" }] : []));
12438
- /** Whether the node is currently selected. */
12439
- this.selected = input.required(...(ngDevMode ? [{ debugName: "selected" }] : []));
12440
- /** The Tiptap extension that created this node. */
12441
- this.extension = input.required(...(ngDevMode ? [{ debugName: "extension" }] : []));
12442
- /** Function to get the node's position in the document. */
12443
- this.getPos = input.required(...(ngDevMode ? [{ debugName: "getPos" }] : []));
12444
- /** Function to update the node's attributes. */
12445
- this.updateAttributes = input.required(...(ngDevMode ? [{ debugName: "updateAttributes" }] : []));
12446
- /** Function to delete the node from the document. */
12447
- this.deleteNode = input.required(...(ngDevMode ? [{ debugName: "deleteNode" }] : []));
11980
+ class RemoveMarkdownPipe {
11981
+ transform(markdown) {
11982
+ return markdownToText(markdown);
12448
11983
  }
12449
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AngularNodeViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
12450
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.18", type: AngularNodeViewComponent, isStandalone: true, selector: "ng-component", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, decorations: { classPropertyName: "decorations", publicName: "decorations", isSignal: true, isRequired: true, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: true, transformFunction: null }, extension: { classPropertyName: "extension", publicName: "extension", isSignal: true, isRequired: true, transformFunction: null }, getPos: { classPropertyName: "getPos", publicName: "getPos", isSignal: true, isRequired: true, transformFunction: null }, updateAttributes: { classPropertyName: "updateAttributes", publicName: "updateAttributes", isSignal: true, isRequired: true, transformFunction: null }, deleteNode: { classPropertyName: "deleteNode", publicName: "deleteNode", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: '', isInline: true }); }
11984
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: RemoveMarkdownPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
11985
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: RemoveMarkdownPipe, isStandalone: true, name: "lxRemoveMarkdown" }); }
12451
11986
  }
12452
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: AngularNodeViewComponent, decorators: [{
12453
- type: Component,
11987
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: RemoveMarkdownPipe, decorators: [{
11988
+ type: Pipe,
12454
11989
  args: [{
12455
- template: ''
11990
+ name: 'lxRemoveMarkdown'
12456
11991
  }]
12457
- }], propDecorators: { editor: [{ type: i0.Input, args: [{ isSignal: true, alias: "editor", required: true }] }], node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: true }] }], decorations: [{ type: i0.Input, args: [{ isSignal: true, alias: "decorations", required: true }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: true }] }], extension: [{ type: i0.Input, args: [{ isSignal: true, alias: "extension", required: true }] }], getPos: [{ type: i0.Input, args: [{ isSignal: true, alias: "getPos", required: true }] }], updateAttributes: [{ type: i0.Input, args: [{ isSignal: true, alias: "updateAttributes", required: true }] }], deleteNode: [{ type: i0.Input, args: [{ isSignal: true, alias: "deleteNode", required: true }] }] } });
11992
+ }] });
11993
+ function markdownToText(md) {
11994
+ let output = md || '';
11995
+ try {
11996
+ output = output
11997
+ // Remove horizontal rules (stripListHeaders conflict with this rule, which is why it has been moved to the top)
11998
+ .replace(/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/gm, '')
11999
+ // stripListLeaders
12000
+ .replace(/^([\s\t]*)([\*\-\+]|\d+\.)\s+/gm, '$1')
12001
+ // Strikethrough
12002
+ .replace(/~~/g, '')
12003
+ // Fenced codeblocks with backticks
12004
+ .replace(/```(?:.*)\n([\s\S]*?)```/g, (_, code) => code.trim())
12005
+ // Remove HTML tags
12006
+ .replace(/<[^>]*>/g, '')
12007
+ // Remove images
12008
+ .replace(/\!\[(.*?)\][\[\(].*?[\]\)]/g, '$1')
12009
+ // Remove blockquotes
12010
+ .replace(/^(\n)?\s{0,3}>\s?/gm, '$1')
12011
+ // Remove atx-style headers
12012
+ .replace(/^(\n)?\s{0,}#{1,6}\s*( (.+))? +#+$|^(\n)?\s{0,}#{1,6}\s*( (.+))?$/gm, '$1$3$4$6')
12013
+ // Remove * emphasis
12014
+ .replace(/([\*]+)(\S)(.*?\S)??\1/g, '$2$3')
12015
+ // Remove _ emphasis. Unlike *, _ emphasis gets rendered only if
12016
+ // 1. Either there is a whitespace character before opening _ and after closing _.
12017
+ // 2. Or _ is at the start/end of the string.
12018
+ .replace(/(^|\W)([_]+)(\S)(.*?\S)??\2($|\W)/g, '$1$3$4$5')
12019
+ // Remove single-line code blocks (already handled multiline above )
12020
+ .replace(/(`{3,})(.*?)\1/gm, '$2')
12021
+ // Remove inline code
12022
+ .replace(/`(.+?)`/g, '$1');
12023
+ }
12024
+ catch (e) {
12025
+ return md;
12026
+ }
12027
+ return output;
12028
+ }
12458
12029
 
12459
- class AngularRenderer {
12460
- constructor(ViewComponent, injector, props) {
12461
- this.applicationRef = injector.get(ApplicationRef);
12462
- this.componentRef = createComponent(ViewComponent, {
12463
- environmentInjector: this.applicationRef.injector,
12464
- elementInjector: injector
12465
- });
12466
- // set input props to the component
12467
- this.updateProps(props);
12468
- this.applicationRef.attachView(this.componentRef.hostView);
12030
+ // /**
12031
+ // * Converts HTML to text, preserving semantic newlines for block-level
12032
+ // * elements. (Taken from https://stackoverflow.com/a/20384452/6813271)
12033
+ // *
12034
+ // * @param node - The HTML node to perform text extraction.
12035
+ // */
12036
+ // export function getNodeTextWithNewlines(node: Element, _inner = false): string {
12037
+ // let result = '';
12038
+ // if (node.nodeType === document.TEXT_NODE) {
12039
+ // // Replace repeated spaces, newlines, and tabs with a single space.
12040
+ // result = node.nodeValue.replace( /\s+/g, ' ' );
12041
+ // } else {
12042
+ // for (let i = 0, j = node.childNodes.length; i < j; i++ ) {
12043
+ // result += this.getNodeTextWithNewlines(node.childNodes[i] as Element, true);
12044
+ // }
12045
+ // const d = node['currentStyle'] ?
12046
+ // node['currentStyle']['display'] :
12047
+ // document.defaultView.getComputedStyle(node, null).getPropertyValue('display');
12048
+ // if (d.match(/^block/)) {
12049
+ // result = '\n' + result + '\n';
12050
+ // } else if (d.match(/list/) || d.match(/row/) || node.tagName === 'BR' || node.tagName === 'HR' ) {
12051
+ // result += '\n';
12052
+ // }
12053
+ // }
12054
+ // return _inner ? result : _.trim(result, '\n');
12055
+ // }
12056
+ /** Trim whitespaces from html */
12057
+ function trimHtml(str) {
12058
+ return str
12059
+ .replace(/(<\/?(br *\/?|p)>|&nbsp;|\s)*$/i, '')
12060
+ .replace(/^(<\/?(br *\/?|p)>|&nbsp;|\s)*/i, '')
12061
+ .replace(/^<(div|p)>(<\/?(br *\/?|p)>|&nbsp;|\s)*<\/ *(div|p)>$/i, '');
12062
+ }
12063
+
12064
+ // First version based on https://stackoverflow.com/a/41253897/6813271
12065
+ class ContenteditableDirective {
12066
+ constructor(elRef, sanitizer) {
12067
+ this.elRef = elRef;
12068
+ this.sanitizer = sanitizer;
12069
+ this.lxContenteditableModelChange = new EventEmitter();
12070
+ /** Allow (sanitized) html */
12071
+ this.lxContenteditableHtml = false;
12072
+ this.lxContenteditableHtmlPaste = true;
12073
+ this.emittedValue = null;
12074
+ }
12075
+ ngOnChanges(changes) {
12076
+ if (changes['lxContenteditableModel']) {
12077
+ // On init: if lxContenteditableModel is empty, read from DOM in case the element has content
12078
+ if (changes['lxContenteditableModel'].isFirstChange() && !this.lxContenteditableModel) {
12079
+ // Prevent Exp.HasChanged: Don't read and emit value from DOM during change detection
12080
+ setTimeout(() => {
12081
+ this.onInput(true);
12082
+ });
12083
+ }
12084
+ this.refreshView();
12085
+ }
12086
+ }
12087
+ onInput(initialInlineData = false) {
12088
+ let value = this.elRef.nativeElement[this.getProperty()];
12089
+ value = this.cleanContent(value, initialInlineData);
12090
+ this.emittedValue = value;
12091
+ this.lxContenteditableModelChange.emit(value);
12469
12092
  }
12470
- get instance() {
12471
- return this.componentRef.instance;
12093
+ /**
12094
+ * @param event {ClipboardEvent}
12095
+ */
12096
+ onPaste(event) {
12097
+ const clipboardEvent = event;
12098
+ this.onInput();
12099
+ // For text-only contenteditable, remove pasted HTML.
12100
+ if (!this.lxContenteditableHtml || !this.lxContenteditableHtmlPaste) {
12101
+ let isHtml = true;
12102
+ // TODO: Use beforepaste event. See https://www.lucidchart.com/techblog/2014/12/02/definitive-guide-copying-pasting-javascript/.
12103
+ if (clipboardEvent.clipboardData && clipboardEvent.clipboardData.types) {
12104
+ const types = [].slice.apply(clipboardEvent.clipboardData.types);
12105
+ isHtml = intersection(types, ['text/html', 'com.apple.webarchive']).length > 0;
12106
+ }
12107
+ if (isHtml) {
12108
+ // 1 tick wait is required for DOM update
12109
+ setTimeout(() => {
12110
+ // Cursor will be lost
12111
+ // The lint disabling here should be clearified. See if and how this directive is needed.
12112
+ this.elRef.nativeElement.innerHTML = this.sanitizer.sanitize(SecurityContext.HTML, this.elRef.nativeElement.innerText.replace(/\n/g, '<br />'));
12113
+ });
12114
+ }
12115
+ }
12472
12116
  }
12473
- get elementRef() {
12474
- return this.componentRef.injector.get(ElementRef);
12117
+ onDrop(event) {
12118
+ this.onInput();
12119
+ // For text-only contenteditable, don't allow drop content.
12120
+ if (!this.lxContenteditableHtml || !this.lxContenteditableHtmlPaste) {
12121
+ event.preventDefault();
12122
+ event.stopPropagation();
12123
+ return false;
12124
+ }
12125
+ return false;
12475
12126
  }
12476
- get dom() {
12477
- return this.elementRef.nativeElement;
12127
+ cleanContent(value, initialInlineData = false) {
12128
+ if (this.lxContenteditableHtml === 'trim' || (this.lxContenteditableHtml && initialInlineData)) {
12129
+ value = trimHtml(value);
12130
+ }
12131
+ else if (initialInlineData && !this.lxContenteditableHtml && value) {
12132
+ value = value.replace(/^[\n\s]+/, '');
12133
+ value = value.replace(/[\n\s]+$/, '');
12134
+ }
12135
+ // Some browsers like Chrome insert nbsp; when using contentEditable attribute
12136
+ return new NbspPipe().transform(value);
12478
12137
  }
12479
- updateProps(props) {
12480
- Object.entries(props).forEach(([key, value]) => {
12481
- this.componentRef.setInput(key, value);
12482
- });
12138
+ refreshView() {
12139
+ if (!isNil(this.lxContenteditableModel)) {
12140
+ const newContent = this.cleanContent(this.lxContenteditableModel);
12141
+ // Only refresh if content changed to avoid cursor loss
12142
+ // (as ngOnChanges can be triggered an additional time by onInput())
12143
+ if (this.emittedValue === null || this.emittedValue !== newContent) {
12144
+ this.elRef.nativeElement[this.getProperty()] = this.sanitize(newContent);
12145
+ }
12146
+ }
12483
12147
  }
12484
- detectChanges() {
12485
- this.componentRef.changeDetectorRef.detectChanges();
12148
+ getProperty() {
12149
+ return this.lxContenteditableHtml ? 'innerHTML' : 'innerText';
12486
12150
  }
12487
- destroy() {
12488
- this.componentRef.destroy();
12489
- this.applicationRef.detachView(this.componentRef.hostView);
12151
+ sanitize(content) {
12152
+ return this.lxContenteditableHtml ? this.sanitizer.sanitize(SecurityContext.HTML, content) : content;
12490
12153
  }
12154
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ContenteditableDirective, deps: [{ token: i0.ElementRef }, { token: i1$6.DomSanitizer }], target: i0.ɵɵFactoryTarget.Directive }); }
12155
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: ContenteditableDirective, isStandalone: true, selector: "[lxContenteditableModel]", inputs: { lxContenteditableModel: "lxContenteditableModel", lxContenteditableHtml: "lxContenteditableHtml", lxContenteditableHtmlPaste: "lxContenteditableHtmlPaste" }, outputs: { lxContenteditableModelChange: "lxContenteditableModelChange" }, host: { listeners: { "input": "onInput()", "blur": "onInput()", "keyup": "onInput()", "paste": "onPaste($event)", "drop": "onDrop($event)" } }, usesOnChanges: true, ngImport: i0 }); }
12491
12156
  }
12157
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ContenteditableDirective, decorators: [{
12158
+ type: Directive,
12159
+ args: [{
12160
+ selector: '[lxContenteditableModel]'
12161
+ }]
12162
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1$6.DomSanitizer }], propDecorators: { lxContenteditableModel: [{
12163
+ type: Input
12164
+ }], lxContenteditableModelChange: [{
12165
+ type: Output
12166
+ }], lxContenteditableHtml: [{
12167
+ type: Input
12168
+ }], lxContenteditableHtmlPaste: [{
12169
+ type: Input
12170
+ }], onInput: [{
12171
+ type: HostListener,
12172
+ args: ['input']
12173
+ }, {
12174
+ type: HostListener,
12175
+ args: ['blur']
12176
+ }, {
12177
+ type: HostListener,
12178
+ args: ['keyup']
12179
+ }], onPaste: [{
12180
+ type: HostListener,
12181
+ args: ['paste', ['$event']]
12182
+ }], onDrop: [{
12183
+ type: HostListener,
12184
+ args: ['drop', ['$event']]
12185
+ }] } });
12492
12186
 
12493
- class AngularNodeView extends NodeView {
12494
- mount() {
12495
- const injector = this.options.injector;
12496
- const props = {
12497
- editor: this.editor,
12498
- node: this.node,
12499
- decorations: this.decorations,
12500
- selected: false,
12501
- extension: this.extension,
12502
- getPos: () => this.getPos(),
12503
- updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
12504
- deleteNode: () => this.deleteNode()
12505
- };
12506
- this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
12507
- this.handleBlur = this.handleBlur.bind(this);
12508
- this.editor.on('selectionUpdate', this.handleSelectionUpdate);
12509
- this.editor.on('blur', this.handleBlur);
12510
- // create renderer
12511
- this.renderer = new AngularRenderer(this.component, injector, props);
12512
- // Register drag handler
12513
- if (this.extension.config.draggable) {
12514
- this.renderer.elementRef.nativeElement.ondragstart = (e) => {
12515
- this.onDragStart(e);
12516
- };
12517
- }
12518
- this.contentDOMElement = this.node.isLeaf ? null : document.createElement(this.node.isInline ? 'span' : 'div');
12519
- if (this.contentDOMElement) {
12520
- // For some reason the whiteSpace prop is not inherited properly in Chrome and Safari
12521
- // With this fix it seems to work fine
12522
- // See: https://github.com/ueberdosis/tiptap/issues/1197
12523
- this.contentDOMElement.style.whiteSpace = 'inherit';
12524
- // Required for editable node views
12525
- // The content won't be rendered if `editable` is set to `false`
12526
- this.renderer.detectChanges();
12527
- }
12528
- this.appendContendDom();
12529
- /**
12530
- * Ensure the node is selected when clicked.
12531
- *
12532
- * ProseMirror/Tiptap sometimes does not trigger `selectionUpdate` for single-node editors
12533
- * or when the node is already implicitly selected. By explicitly creating a NodeSelection
12534
- * and dispatching it, we force ProseMirror to treat this node as newly selected, which
12535
- * triggers `handleSelectionUpdate` and updates the NodeView's selected state.
12536
- */
12537
- this.handleMouseDown = (event) => {
12538
- if (!this.editor.isEditable)
12539
- return;
12540
- const pos = this.getPos();
12541
- const nodeSelection = NodeSelection.create(this.editor.state.doc, pos);
12542
- const tr = this.editor.state.tr.setSelection(nodeSelection);
12543
- this.editor.view.dispatch(tr);
12544
- this.editor.view.focus();
12545
- this.selectNode();
12546
- event.stopPropagation();
12547
- };
12548
- const selection = this.editor.state.selection;
12549
- if (selection instanceof NodeSelection && selection.node.type.name === 'lxDiagram') {
12550
- this.dom.addEventListener('mousedown', this.handleMouseDown);
12551
- }
12552
- }
12553
- get dom() {
12554
- return this.renderer.dom;
12187
+ class FormSubmitDirective {
12188
+ constructor(elementRef) {
12189
+ this.elementRef = elementRef;
12190
+ this.submitted$ = new BehaviorSubject(false);
12191
+ this.subscription = fromEvent(this.elementRef.nativeElement, 'submit')
12192
+ .pipe(take(1))
12193
+ .subscribe(() => this.submitted$.next(true));
12555
12194
  }
12556
- get contentDOM() {
12557
- if (this.node.isLeaf) {
12558
- return null;
12195
+ ngOnDestroy() {
12196
+ if (this.subscription) {
12197
+ this.subscription.unsubscribe();
12559
12198
  }
12560
- return this.contentDOMElement;
12561
12199
  }
12562
- appendContendDom() {
12563
- const contentElement = this.dom.querySelector('[data-node-view-content]');
12564
- if (this.contentDOMElement && contentElement && !contentElement.contains(this.contentDOMElement)) {
12565
- contentElement.appendChild(this.contentDOMElement);
12566
- }
12200
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FormSubmitDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
12201
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: FormSubmitDirective, isStandalone: true, selector: "form", ngImport: i0 }); }
12202
+ }
12203
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FormSubmitDirective, decorators: [{
12204
+ type: Directive,
12205
+ args: [{
12206
+ // eslint-disable-next-line @angular-eslint/directive-selector
12207
+ selector: 'form'
12208
+ }]
12209
+ }], ctorParameters: () => [{ type: i0.ElementRef }] });
12210
+
12211
+ const FORM_CONTROL_ERROR_NAMESPACE = new InjectionToken('FORM_CONTROL_ERROR_NAMESPACE');
12212
+ const FORM_CONTROL_ERROR_DISPLAY_STRATEGY = new InjectionToken('FORM_CONTROL_ERROR_DISPLAY_STRATEGY');
12213
+ const provideFormControlErrorNamespace = (namespace) => ({
12214
+ provide: FORM_CONTROL_ERROR_NAMESPACE,
12215
+ useValue: namespace
12216
+ });
12217
+ const provideFormControlErrorDisplayStrategy = (fn) => ({
12218
+ provide: FORM_CONTROL_ERROR_DISPLAY_STRATEGY,
12219
+ useValue: fn
12220
+ });
12221
+ class FormErrorDirective {
12222
+ get control() {
12223
+ return this.ngControl?.control || this.ctrl || null;
12567
12224
  }
12568
- handleBlur() {
12569
- this.deselectNode();
12225
+ get name() {
12226
+ return this.ngControl?.name || this.controlName;
12570
12227
  }
12571
- handleSelectionUpdate() {
12572
- const { from, to } = this.editor.state.selection;
12573
- if (from <= this.getPos() && to >= this.getPos() + this.node.nodeSize) {
12574
- this.selectNode();
12575
- }
12576
- else {
12577
- this.deselectNode();
12578
- }
12228
+ get formSubmitted() {
12229
+ return this.formSubmitDirective ? this.formSubmitDirective.submitted$ : of(undefined);
12579
12230
  }
12580
- update(node, decorations, _innerDecorations) {
12581
- const updateProps = () => {
12582
- this.renderer.updateProps({ node, decorations: decorations });
12583
- };
12584
- if (this.options.update) {
12585
- const oldNode = this.node;
12586
- const oldDecorations = this.decorations;
12587
- this.node = node;
12588
- this.decorations = decorations;
12589
- return this.options.update({
12590
- oldNode,
12591
- oldDecorations,
12592
- newNode: node,
12593
- newDecorations: decorations,
12594
- updateProps: () => updateProps()
12231
+ constructor(viewContainer, componentFactoryResolver, translateService, destroyRef, ngControl, formSubmitDirective, namespace, strategy) {
12232
+ this.viewContainer = viewContainer;
12233
+ this.componentFactoryResolver = componentFactoryResolver;
12234
+ this.translateService = translateService;
12235
+ this.destroyRef = destroyRef;
12236
+ this.ngControl = ngControl;
12237
+ this.formSubmitDirective = formSubmitDirective;
12238
+ this.namespace = namespace;
12239
+ this.strategy = strategy;
12240
+ }
12241
+ ngOnInit() {
12242
+ const control = this.control;
12243
+ if (isAbstractControl(control)) {
12244
+ combineLatest([control.valueChanges.pipe(startWith(control.value)), this.formSubmitted])
12245
+ .pipe(map(([, submitted]) => submitted), map(resolveStrategy(this.strategy, control)), takeUntilDestroyed(this.destroyRef))
12246
+ .subscribe((display) => {
12247
+ const { errors } = control;
12248
+ if (errors && display) {
12249
+ const firstErrorKey = Object.keys(errors)[0];
12250
+ const translationKey = this.buildTranslationKey(firstErrorKey);
12251
+ this.setError(translationKey);
12252
+ }
12253
+ else if (this.ref) {
12254
+ this.setError();
12255
+ }
12595
12256
  });
12596
12257
  }
12597
- if (node.type !== this.node.type) {
12598
- return false;
12258
+ }
12259
+ buildTranslationKey(errorKey) {
12260
+ if (this.control) {
12261
+ return `${this.namespace || 'form'}.errors.${this.name ? `${this.name}.` : ''}${errorKey}`;
12599
12262
  }
12600
- if (node === this.node && this.decorations === decorations) {
12601
- return true;
12263
+ else {
12264
+ return '';
12602
12265
  }
12603
- this.node = node;
12604
- this.decorations = decorations;
12605
- updateProps();
12606
- return true;
12607
- }
12608
- selectNode() {
12609
- if (!this.editor.isEditable)
12610
- return;
12611
- this.renderer.updateProps({ selected: true });
12612
- }
12613
- deselectNode() {
12614
- this.renderer.updateProps({ selected: false });
12615
12266
  }
12616
- destroy() {
12617
- this.renderer.destroy();
12618
- this.editor.off('selectionUpdate', this.handleSelectionUpdate);
12619
- if (this.handleMouseDown) {
12620
- this.dom.removeEventListener('mousedown', this.handleMouseDown);
12621
- this.handleMouseDown = undefined;
12267
+ setError(key) {
12268
+ if (!this.ref) {
12269
+ const factory = this.componentFactoryResolver.resolveComponentFactory(ErrorMessageComponent);
12270
+ this.ref = this.viewContainer.createComponent(factory);
12271
+ }
12272
+ if (key) {
12273
+ this.translateService
12274
+ .get(key)
12275
+ .pipe(takeUntilDestroyed(this.destroyRef))
12276
+ .subscribe((message) => {
12277
+ if (this.ref) {
12278
+ this.ref.instance.dynamicErrorMessage.set(message);
12279
+ }
12280
+ });
12281
+ }
12282
+ else {
12283
+ this.ref.instance.dynamicErrorMessage.set('');
12622
12284
  }
12623
- this.contentDOMElement = null;
12624
- }
12625
- }
12626
- const AngularNodeViewRenderer = (ViewComponent, options) => {
12627
- return (props) => {
12628
- return new AngularNodeView(ViewComponent, props, options);
12629
- };
12630
- };
12631
-
12632
- /**
12633
- * Removes markdown syntax from text.
12634
- * e.g '### This is a heading' will become 'This is a heading'
12635
- *
12636
- * It does not remove links. Links can be post processed by LxLinkifyPipe or LxUnLinkifyPipe
12637
- */
12638
- class RemoveMarkdownPipe {
12639
- transform(markdown) {
12640
- return markdownToText(markdown);
12641
12285
  }
12642
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: RemoveMarkdownPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
12643
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: RemoveMarkdownPipe, isStandalone: true, name: "lxRemoveMarkdown" }); }
12286
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FormErrorDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.ComponentFactoryResolver }, { token: i1$1.TranslateService }, { token: i0.DestroyRef }, { token: i2$2.NgControl, optional: true, self: true }, { token: FormSubmitDirective, host: true, optional: true }, { token: FORM_CONTROL_ERROR_NAMESPACE, optional: true }, { token: FORM_CONTROL_ERROR_DISPLAY_STRATEGY, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
12287
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: FormErrorDirective, isStandalone: true, selector: "[lxFormError]", inputs: { ctrl: ["lxFormError", "ctrl"], controlName: "controlName" }, ngImport: i0 }); }
12644
12288
  }
12645
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: RemoveMarkdownPipe, decorators: [{
12646
- type: Pipe,
12289
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FormErrorDirective, decorators: [{
12290
+ type: Directive,
12647
12291
  args: [{
12648
- name: 'lxRemoveMarkdown'
12292
+ selector: '[lxFormError]'
12649
12293
  }]
12650
- }] });
12651
- function markdownToText(md) {
12652
- let output = md || '';
12653
- try {
12654
- output = output
12655
- // Remove horizontal rules (stripListHeaders conflict with this rule, which is why it has been moved to the top)
12656
- .replace(/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/gm, '')
12657
- // stripListLeaders
12658
- .replace(/^([\s\t]*)([\*\-\+]|\d+\.)\s+/gm, '$1')
12659
- // Strikethrough
12660
- .replace(/~~/g, '')
12661
- // Fenced codeblocks with backticks
12662
- .replace(/```(?:.*)\n([\s\S]*?)```/g, (_, code) => code.trim())
12663
- // Remove HTML tags
12664
- .replace(/<[^>]*>/g, '')
12665
- // Remove images
12666
- .replace(/\!\[(.*?)\][\[\(].*?[\]\)]/g, '$1')
12667
- // Remove blockquotes
12668
- .replace(/^(\n)?\s{0,3}>\s?/gm, '$1')
12669
- // Remove atx-style headers
12670
- .replace(/^(\n)?\s{0,}#{1,6}\s*( (.+))? +#+$|^(\n)?\s{0,}#{1,6}\s*( (.+))?$/gm, '$1$3$4$6')
12671
- // Remove * emphasis
12672
- .replace(/([\*]+)(\S)(.*?\S)??\1/g, '$2$3')
12673
- // Remove _ emphasis. Unlike *, _ emphasis gets rendered only if
12674
- // 1. Either there is a whitespace character before opening _ and after closing _.
12675
- // 2. Or _ is at the start/end of the string.
12676
- .replace(/(^|\W)([_]+)(\S)(.*?\S)??\2($|\W)/g, '$1$3$4$5')
12677
- // Remove single-line code blocks (already handled multiline above )
12678
- .replace(/(`{3,})(.*?)\1/gm, '$2')
12679
- // Remove inline code
12680
- .replace(/`(.+?)`/g, '$1');
12681
- }
12682
- catch (e) {
12683
- return md;
12684
- }
12685
- return output;
12686
- }
12294
+ }], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: i0.ComponentFactoryResolver }, { type: i1$1.TranslateService }, { type: i0.DestroyRef }, { type: i2$2.NgControl, decorators: [{
12295
+ type: Optional
12296
+ }, {
12297
+ type: Self
12298
+ }] }, { type: FormSubmitDirective, decorators: [{
12299
+ type: Optional
12300
+ }, {
12301
+ type: Host
12302
+ }] }, { type: undefined, decorators: [{
12303
+ type: Optional
12304
+ }, {
12305
+ type: Inject,
12306
+ args: [FORM_CONTROL_ERROR_NAMESPACE]
12307
+ }] }, { type: undefined, decorators: [{
12308
+ type: Optional
12309
+ }, {
12310
+ type: Inject,
12311
+ args: [FORM_CONTROL_ERROR_DISPLAY_STRATEGY]
12312
+ }] }], propDecorators: { ctrl: [{
12313
+ type: Input,
12314
+ args: ['lxFormError']
12315
+ }], controlName: [{
12316
+ type: Input
12317
+ }] } });
12318
+ const isAbstractControl = (ctrl) => !!ctrl;
12319
+ const resolveStrategy = curry((strategy, control, submitted) => strategy ? strategy({ control, submitted }) : true);
12687
12320
 
12688
12321
  class MaxLengthCounterDirective {
12689
12322
  constructor(el, renderer, ngControl) {
@@ -12816,6 +12449,120 @@ class Sorting {
12816
12449
  }
12817
12450
  }
12818
12451
 
12452
+ class FilterSelectionPipe {
12453
+ transform(items, selection, itemKey) {
12454
+ const isArray = Array.isArray(selection);
12455
+ return filter$1((item) => {
12456
+ if (isArray) {
12457
+ if (isObject(item)) {
12458
+ return itemKey
12459
+ ? !find((selectedItem) => selectedItem?.[itemKey] === item?.[itemKey], selection)
12460
+ : !find(item, selection);
12461
+ }
12462
+ else {
12463
+ return !includes(item, selection);
12464
+ }
12465
+ }
12466
+ else {
12467
+ return !isEqual$1(item, selection);
12468
+ }
12469
+ }, items);
12470
+ }
12471
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FilterSelectionPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
12472
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: FilterSelectionPipe, isStandalone: true, name: "lxFilterBySelection" }); }
12473
+ }
12474
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FilterSelectionPipe, decorators: [{
12475
+ type: Pipe,
12476
+ args: [{
12477
+ name: 'lxFilterBySelection'
12478
+ }]
12479
+ }] });
12480
+
12481
+ class FilterTermPipe {
12482
+ transform(items, options) {
12483
+ if (items === null) {
12484
+ return [];
12485
+ }
12486
+ if (options.term) {
12487
+ return filter$1((item) => {
12488
+ const value = options.key ? item[options.key] : item;
12489
+ return toLower(value).indexOf(toLower(options.term)) > -1;
12490
+ }, items);
12491
+ }
12492
+ else {
12493
+ return items;
12494
+ }
12495
+ }
12496
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FilterTermPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
12497
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: FilterTermPipe, isStandalone: true, name: "lxFilterByTerm" }); }
12498
+ }
12499
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FilterTermPipe, decorators: [{
12500
+ type: Pipe,
12501
+ args: [{
12502
+ name: 'lxFilterByTerm'
12503
+ }]
12504
+ }] });
12505
+
12506
+ /**
12507
+ * Reformats numbers into a short format.
12508
+ * @example {{ 1000 | lxFormatNumber | async }} prints 1K
12509
+ *
12510
+ * If the parameter currency is set, a currency sign is inserted based on the value and the current locale.
12511
+ * In this case, the pipe must be used with an innerHtml attribute.
12512
+ * @example [innerHtml]="1000 | lxFormatNumber: 'USD' | async" prints $1K
12513
+ */
12514
+ class FormatNumberPipe {
12515
+ constructor(getLocale) {
12516
+ this.getLocale = getLocale;
12517
+ }
12518
+ transform(number, currency) {
12519
+ const locale$ = this.getLocale();
12520
+ return locale$.pipe(map((locale) => {
12521
+ if (number === null || number === undefined) {
12522
+ return null;
12523
+ }
12524
+ const options = {
12525
+ notation: 'compact',
12526
+ compactDisplay: 'short'
12527
+ };
12528
+ if (currency) {
12529
+ try {
12530
+ const currencyOptions = { ...options, currency, style: 'currency' };
12531
+ const formatedNumberWithCurrency = new Intl.NumberFormat(locale, currencyOptions).format(number);
12532
+ return this.getFormatedCurrency(formatedNumberWithCurrency, currency);
12533
+ }
12534
+ catch (_error) {
12535
+ console.warn(`FormatNumberPipe: Invalid currency code: ${currency}`);
12536
+ return new Intl.NumberFormat(locale, options).format(number);
12537
+ }
12538
+ }
12539
+ return new Intl.NumberFormat(locale, options).format(number);
12540
+ }));
12541
+ }
12542
+ /**
12543
+ * Use custom currency symbol, when the currency in the formated number doesn't match the
12544
+ * symbol in the CURRENCY_SYMBOL_MAP.
12545
+ */
12546
+ getFormatedCurrency(formatedNumberWitCurrency, currency) {
12547
+ const currencyMapping = CURRENCY_SYMBOL_MAP[currency];
12548
+ if (currencyMapping && currencyMapping !== currency && !formatedNumberWitCurrency.includes(currencyMapping)) {
12549
+ return formatedNumberWitCurrency.replace(currency, currencyMapping);
12550
+ }
12551
+ return formatedNumberWitCurrency;
12552
+ }
12553
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FormatNumberPipe, deps: [{ token: LOCALE_FN }], target: i0.ɵɵFactoryTarget.Pipe }); }
12554
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: FormatNumberPipe, isStandalone: true, name: "lxFormatNumber" }); }
12555
+ }
12556
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: FormatNumberPipe, decorators: [{
12557
+ type: Pipe,
12558
+ args: [{
12559
+ name: 'lxFormatNumber'
12560
+ }]
12561
+ }], ctorParameters: () => [{ type: Function, decorators: [{
12562
+ type: Inject,
12563
+ args: [LOCALE_FN]
12564
+ }] }] });
12565
+
12819
12566
  /**
12820
12567
  * Due to limitations of the native html datepicker this validator is needed:
12821
12568
  * In the datepicker the min and max values only apply if the date is altered e.g. via scrolling.
@@ -13680,5 +13427,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
13680
13427
  * Generated bundle index. Do not edit.
13681
13428
  */
13682
13429
 
13683
- export { ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, AVATAR_COLORS, AVATAR_SIZE_MAPPING, AfterViewInitDirective, AngularNodeViewComponent, AngularNodeViewRenderer, AutocloseDirective, AutocloseGroupService, AutofocusDirective, AvatarComponent, AvatarGroupComponent, BACKSPACE, BadgeComponent, BannerComponent, BaseSelectDirective, BasicDropdownComponent, BasicDropdownItemComponent, BrPipe, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CORE_MODULE_EXPORTS, CURRENCY_SYMBOL_MAP, CardComponent, CdkOptionsDropdownComponent, CdkOptionsSubDropdownComponent, CollapsibleComponent, ContenteditableDirective, ContrastColorPipe, CounterComponent, CurrencyInputComponent, CurrencySymbolComponent, CustomDatePipe, DATEPICKER_CONTROL_VALUE_ACCESSOR, DATE_FN_LOCALE, DATE_FORMATS, DEFAULT_IMAGE_ID, DateFormatter, DateInputComponent, DatePickerComponent, DatepickerConfig, DatepickerUiModule, DragAndDropListComponent, DragAndDropListItemComponent, END, ENTER, ESCAPE, EllipsisComponent, EmptyStateComponent, ErrorMessageComponent, FORMS_MODULE_EXPORTS, FORM_CONTROL_ERROR_DISPLAY_STRATEGY, FORM_CONTROL_ERROR_NAMESPACE, FaToSapIconPipe, FilterSelectionPipe, FilterTermPipe, FocusEditorDirective, FormErrorComponent, FormErrorDirective, FormSubmitDirective, FormatNumberPipe, GLOBAL_TRANSLATION_OPTIONS, HOME, HighlightRangePipe, HighlightTermDirective, HighlightTermPipe, ICON_MAP, IMAGE_READER, InputComponent, KeyboardActionSourceDirective, KeyboardSelectAction, KeyboardSelectDirective, KeyboardSortableItemDirective, KeyboardSortableListDirective, LOCALE_FN, LX_ELLIPSIS_DEBOUNCE_ON_RESIZE, LxCoreUiModule, LxDragAndDropListModule, LxFormsModule, LxIsUuidPipe, LxLinkifyPipe, LxTimeAgo, LxTranslatePipe, LxUnlinkifyPipe, MODAL_CLOSE, MarkInvalidDirective, MarkdownPipe, MaxLengthCounterDirective, ModalCloseClickLocation, ModalComponent, ModalContentDirective, ModalFooterComponent, ModalHeaderComponent, MultiSelectComponent, NbspPipe, OptionComponent, OptionGroupComponent, OptionGroupDropdownComponent, OptionsDropdownComponent, OptionsSubDropdownComponent, PageHeaderComponent, PickerComponent, PickerOptionComponent, PickerTriggerDirective, PillItemComponent, PillListComponent, PlaceholderDirective, PopoverClickDirective, PopoverComponent, PopoverContentDirective, PopoverHoverDirective, RELEVANCE_SORTING_KEY, RemoveMarkdownPipe, ResizeObserverService, ResponsiveInputComponent, RichTextEditorComponent, SPACE, SelectDropdownDirective, SelectableItemDirective, SelectedOptionDirective, SingleSelectComponent, SkeletonComponent, SortPipe, Sorting, SortingDropdownComponent, SortingDropdownTriggerComponent, SpinnerComponent, StepperComponent, SwitchComponent, TAB, TabComponent, TabGroupComponent, TableComponent, TableHeaderComponent, TipTapEditorDirective, TokenComponent, TokenizerComponent, TokenizerOverflowPopoverComponent, TooltipComponent, TooltipDirective, TrackingDirective, TranslationAfterPipe, TranslationBeforePipe, TranslationBetweenPipe, TruncateDirective, UnescapeCurlyBracesPipe, ValidateDateInForeseeableFuture, ValidateStringNotInArray, ValidateStringNotInArrayAsync, argsToInterpolatedTemplate, getContrastColor, getInitialsUrl, getKeyboardNavigationEvents, getSapIcon, getTranslationParts, highlightText, isValidHexColor, isValidX, isValidY, markdownToText, provideFormControlErrorDisplayStrategy, provideFormControlErrorNamespace, shorthandHexHandle, stopKeyboardEventPropagation };
13430
+ export { ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, AVATAR_COLORS, AVATAR_SIZE_MAPPING, AfterViewInitDirective, AngularNodeViewComponent, AngularNodeViewRenderer, AutocloseDirective, AutocloseGroupService, AutofocusDirective, AvatarComponent, AvatarGroupComponent, BACKSPACE, BadgeComponent, BannerComponent, BaseSelectDirective, BasicDropdownComponent, BasicDropdownItemComponent, BrPipe, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CORE_MODULE_EXPORTS, CURRENCY_SYMBOL_MAP, CardComponent, CdkOptionsDropdownComponent, CdkOptionsSubDropdownComponent, CollapsibleComponent, ContenteditableDirective, ContrastColorPipe, CounterComponent, CurrencyInputComponent, CurrencySymbolComponent, CustomDatePipe, DATEPICKER_CONTROL_VALUE_ACCESSOR, DATE_FN_LOCALE, DATE_FORMATS, DEFAULT_IMAGE_ID, DateFormatter, DateInputComponent, DatePickerComponent, DatepickerConfig, DragAndDropListComponent, DragAndDropListItemComponent, END, ENTER, ESCAPE, EllipsisComponent, EmptyStateComponent, ErrorMessageComponent, FORM_CONTROL_ERROR_DISPLAY_STRATEGY, FORM_CONTROL_ERROR_NAMESPACE, FaToSapIconPipe, FilterSelectionPipe, FilterTermPipe, FocusEditorDirective, FormErrorComponent, FormErrorDirective, FormSubmitDirective, FormatNumberPipe, GLOBAL_TRANSLATION_OPTIONS, HOME, HighlightRangePipe, HighlightTermDirective, HighlightTermPipe, ICON_MAP, IMAGE_READER, InputComponent, KeyboardActionSourceDirective, KeyboardSelectAction, KeyboardSelectDirective, KeyboardSortableItemDirective, KeyboardSortableListDirective, LOCALE_FN, LX_ELLIPSIS_DEBOUNCE_ON_RESIZE, LxCoreUiModule, LxIsUuidPipe, LxLinkifyPipe, LxTimeAgo, LxTranslatePipe, LxUnlinkifyPipe, MODAL_CLOSE, MarkInvalidDirective, MarkdownPipe, MaxLengthCounterDirective, ModalCloseClickLocation, ModalComponent, ModalContentDirective, ModalFooterComponent, ModalHeaderComponent, MultiSelectComponent, NbspPipe, OptionComponent, OptionGroupComponent, OptionGroupDropdownComponent, OptionsDropdownComponent, OptionsSubDropdownComponent, PageHeaderComponent, PickerComponent, PickerOptionComponent, PickerTriggerDirective, PillItemComponent, PillListComponent, PlaceholderDirective, PopoverClickDirective, PopoverComponent, PopoverContentDirective, PopoverHoverDirective, RELEVANCE_SORTING_KEY, RemoveMarkdownPipe, ResizeObserverService, ResponsiveInputComponent, RichTextEditorComponent, SPACE, SelectDropdownDirective, SelectableItemDirective, SelectedOptionDirective, SingleSelectComponent, SkeletonComponent, SortPipe, Sorting, SortingDropdownComponent, SortingDropdownTriggerComponent, SpinnerComponent, StepperComponent, SwitchComponent, TAB, TabComponent, TabGroupComponent, TableComponent, TableHeaderComponent, TipTapEditorDirective, TokenComponent, TokenizerComponent, TokenizerOverflowPopoverComponent, TooltipComponent, TooltipDirective, TrackingDirective, TranslationAfterPipe, TranslationBeforePipe, TranslationBetweenPipe, TruncateDirective, UnescapeCurlyBracesPipe, ValidateDateInForeseeableFuture, ValidateStringNotInArray, ValidateStringNotInArrayAsync, argsToInterpolatedTemplate, getContrastColor, getInitialsUrl, getKeyboardNavigationEvents, getSapIcon, getTranslationParts, highlightText, isValidHexColor, isValidX, isValidY, markdownToText, provideFormControlErrorDisplayStrategy, provideFormControlErrorNamespace, shorthandHexHandle, stopKeyboardEventPropagation };
13684
13431
  //# sourceMappingURL=leanix-components.mjs.map