@flogeez/angular-tiptap-editor 3.1.2 → 3.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +2 -2
  3. package/esm2022/flogeez-angular-tiptap-editor.mjs +5 -0
  4. package/esm2022/lib/ate-editor.provider.mjs +38 -0
  5. package/esm2022/lib/components/bubble-menus/base/ate-base-bubble-menu.mjs +207 -0
  6. package/esm2022/lib/components/bubble-menus/base/ate-base-sub-bubble-menu.mjs +137 -0
  7. package/esm2022/lib/components/bubble-menus/color/ate-color-bubble-menu.component.mjs +365 -0
  8. package/esm2022/lib/components/bubble-menus/image/ate-image-bubble-menu.component.mjs +309 -0
  9. package/esm2022/lib/components/bubble-menus/link/ate-link-bubble-menu.component.mjs +247 -0
  10. package/esm2022/lib/components/bubble-menus/table/ate-cell-bubble-menu.component.mjs +126 -0
  11. package/esm2022/lib/components/bubble-menus/table/ate-table-bubble-menu.component.mjs +271 -0
  12. package/esm2022/lib/components/bubble-menus/text/ate-bubble-menu.component.mjs +272 -0
  13. package/esm2022/lib/components/color-picker/ate-color-picker.component.mjs +123 -0
  14. package/esm2022/lib/components/edit-toggle/ate-edit-toggle.component.mjs +42 -0
  15. package/esm2022/lib/components/editor/angular-tiptap-editor.component.mjs +1031 -0
  16. package/esm2022/lib/components/editor/ate-block-controls.component.mjs +256 -0
  17. package/esm2022/lib/components/slash-commands/ate-slash-commands.component.mjs +328 -0
  18. package/esm2022/lib/components/toolbar/ate-toolbar.component.mjs +531 -0
  19. package/esm2022/lib/components/ui/ate-button.component.mjs +91 -0
  20. package/esm2022/lib/components/ui/ate-separator.component.mjs +11 -0
  21. package/esm2022/lib/config/ate-editor.config.mjs +133 -0
  22. package/esm2022/lib/config/ate-global-config.token.mjs +6 -0
  23. package/esm2022/lib/config/ate-slash-commands.config.mjs +130 -0
  24. package/esm2022/lib/directives/ate-noop-value-accessor.directive.mjs +40 -0
  25. package/esm2022/lib/directives/ate-tooltip.directive.mjs +138 -0
  26. package/esm2022/lib/extensions/ate-block-controls.extension.mjs +156 -0
  27. package/esm2022/lib/extensions/ate-link-click-behavior.extension.mjs +32 -0
  28. package/esm2022/lib/extensions/ate-resizable-image.extension.mjs +277 -0
  29. package/esm2022/lib/extensions/ate-table.extension.mjs +27 -0
  30. package/esm2022/lib/extensions/ate-tiptap-state.extension.mjs +85 -0
  31. package/esm2022/lib/extensions/ate-upload-progress.extension.mjs +195 -0
  32. package/esm2022/lib/extensions/calculators/ate-discovery.calculator.mjs +62 -0
  33. package/esm2022/lib/extensions/calculators/ate-image.calculator.mjs +8 -0
  34. package/esm2022/lib/extensions/calculators/ate-marks.calculator.mjs +75 -0
  35. package/esm2022/lib/extensions/calculators/ate-selection.calculator.mjs +35 -0
  36. package/esm2022/lib/extensions/calculators/ate-structure.calculator.mjs +34 -0
  37. package/esm2022/lib/extensions/calculators/ate-table.calculator.mjs +38 -0
  38. package/esm2022/lib/models/ate-bubble-menu.model.mjs +53 -0
  39. package/esm2022/lib/models/ate-editor-config.model.mjs +2 -0
  40. package/esm2022/lib/models/ate-editor-state.model.mjs +90 -0
  41. package/esm2022/lib/models/ate-image.model.mjs +2 -0
  42. package/esm2022/lib/models/ate-slash-command.model.mjs +2 -0
  43. package/esm2022/lib/models/ate-toolbar.model.mjs +35 -0
  44. package/esm2022/lib/node-view/ate-angular-node-view.mjs +97 -0
  45. package/esm2022/lib/node-view/ate-injector.registry.mjs +16 -0
  46. package/esm2022/lib/node-view/ate-node-view.factory.mjs +125 -0
  47. package/esm2022/lib/node-view/ate-node-view.models.mjs +2 -0
  48. package/esm2022/lib/node-view/ate-node-view.renderer.mjs +154 -0
  49. package/esm2022/lib/node-view/ate-register-angular-component.mjs +49 -0
  50. package/esm2022/lib/services/ate-color-picker.service.mjs +194 -0
  51. package/esm2022/lib/services/ate-editor-commands.service.mjs +474 -0
  52. package/esm2022/lib/services/ate-i18n.service.mjs +422 -0
  53. package/esm2022/lib/services/ate-image.service.mjs +459 -0
  54. package/esm2022/lib/services/ate-link.service.mjs +99 -0
  55. package/esm2022/lib/utils/ate-color.utils.mjs +60 -0
  56. package/esm2022/public-api.mjs +40 -0
  57. package/fesm2022/flogeez-angular-tiptap-editor.mjs +321 -354
  58. package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
  59. package/index.d.ts +3 -1734
  60. package/lib/ate-editor.provider.d.ts +21 -0
  61. package/lib/components/bubble-menus/base/ate-base-bubble-menu.d.ts +71 -0
  62. package/lib/components/bubble-menus/base/ate-base-sub-bubble-menu.d.ts +60 -0
  63. package/lib/components/bubble-menus/color/ate-color-bubble-menu.component.d.ts +77 -0
  64. package/lib/components/bubble-menus/image/ate-image-bubble-menu.component.d.ts +49 -0
  65. package/lib/components/bubble-menus/link/ate-link-bubble-menu.component.d.ts +55 -0
  66. package/lib/components/bubble-menus/table/ate-cell-bubble-menu.component.d.ts +16 -0
  67. package/lib/components/bubble-menus/table/ate-table-bubble-menu.component.d.ts +25 -0
  68. package/lib/components/bubble-menus/text/ate-bubble-menu.component.d.ts +53 -0
  69. package/lib/components/color-picker/ate-color-picker.component.d.ts +54 -0
  70. package/lib/components/edit-toggle/ate-edit-toggle.component.d.ts +13 -0
  71. package/lib/components/editor/angular-tiptap-editor.component.d.ts +242 -0
  72. package/lib/components/editor/ate-block-controls.component.d.ts +44 -0
  73. package/lib/components/slash-commands/ate-slash-commands.component.d.ts +34 -0
  74. package/lib/components/toolbar/ate-toolbar.component.d.ts +47 -0
  75. package/lib/components/ui/ate-button.component.d.ts +25 -0
  76. package/lib/components/ui/ate-separator.component.d.ts +5 -0
  77. package/lib/config/ate-editor.config.d.ts +19 -0
  78. package/lib/config/ate-global-config.token.d.ts +6 -0
  79. package/lib/config/ate-slash-commands.config.d.ts +41 -0
  80. package/lib/directives/ate-noop-value-accessor.directive.d.ts +13 -0
  81. package/lib/directives/ate-tooltip.directive.d.ts +30 -0
  82. package/lib/extensions/ate-block-controls.extension.d.ts +10 -0
  83. package/lib/extensions/ate-link-click-behavior.extension.d.ts +2 -0
  84. package/lib/extensions/ate-resizable-image.extension.d.ts +27 -0
  85. package/lib/extensions/ate-table.extension.d.ts +2 -0
  86. package/lib/extensions/ate-tiptap-state.extension.d.ts +7 -0
  87. package/lib/extensions/ate-upload-progress.extension.d.ts +7 -0
  88. package/lib/extensions/calculators/ate-discovery.calculator.d.ts +7 -0
  89. package/lib/extensions/calculators/ate-image.calculator.d.ts +2 -0
  90. package/lib/extensions/calculators/ate-marks.calculator.d.ts +2 -0
  91. package/lib/extensions/calculators/ate-selection.calculator.d.ts +2 -0
  92. package/lib/extensions/calculators/ate-structure.calculator.d.ts +2 -0
  93. package/lib/extensions/calculators/ate-table.calculator.d.ts +2 -0
  94. package/lib/models/ate-bubble-menu.model.d.ts +33 -0
  95. package/lib/models/ate-editor-config.model.d.ts +113 -0
  96. package/lib/models/ate-editor-state.model.d.ts +109 -0
  97. package/lib/models/ate-image.model.d.ts +104 -0
  98. package/lib/models/ate-slash-command.model.d.ts +17 -0
  99. package/lib/models/ate-toolbar.model.d.ts +18 -0
  100. package/lib/node-view/ate-angular-node-view.d.ts +115 -0
  101. package/lib/node-view/ate-injector.registry.d.ts +3 -0
  102. package/lib/node-view/ate-node-view.factory.d.ts +10 -0
  103. package/lib/node-view/ate-node-view.models.d.ts +138 -0
  104. package/lib/node-view/ate-node-view.renderer.d.ts +23 -0
  105. package/lib/node-view/ate-register-angular-component.d.ts +35 -0
  106. package/lib/services/ate-color-picker.service.d.ts +65 -0
  107. package/lib/services/ate-editor-commands.service.d.ts +75 -0
  108. package/lib/services/ate-i18n.service.d.ts +406 -0
  109. package/lib/services/ate-image.service.d.ts +82 -0
  110. package/lib/services/ate-link.service.d.ts +42 -0
  111. package/lib/utils/ate-color.utils.d.ts +12 -0
  112. package/package.json +3 -1
  113. package/public-api.d.ts +31 -0
@@ -0,0 +1,365 @@
1
+ import { Component, ChangeDetectionStrategy, signal, inject, computed, viewChild, } from "@angular/core";
2
+ import { CommonModule } from "@angular/common";
3
+ import { FormsModule } from "@angular/forms";
4
+ import { AteColorPickerService } from "../../../services/ate-color-picker.service";
5
+ import { AteButtonComponent } from "../../ui/ate-button.component";
6
+ import { AteSeparatorComponent } from "../../ui/ate-separator.component";
7
+ import { AteBaseSubBubbleMenu } from "../base/ate-base-sub-bubble-menu";
8
+ import * as i0 from "@angular/core";
9
+ const PRESET_COLORS = [
10
+ "#000000",
11
+ "#666666",
12
+ "#CCCCCC",
13
+ "#FFFFFF",
14
+ "#F44336",
15
+ "#FF9800",
16
+ "#FFEB3B",
17
+ "#4CAF50",
18
+ "#00BCD4",
19
+ "#2196F3",
20
+ "#9C27B0",
21
+ "#E91E63",
22
+ ];
23
+ export class AteColorBubbleMenuComponent extends AteBaseSubBubbleMenu {
24
+ constructor() {
25
+ super(...arguments);
26
+ this.colorPickerSvc = inject(AteColorPickerService);
27
+ this.t = this.i18nService.toolbar;
28
+ this.common = this.i18nService.common;
29
+ this.presets = PRESET_COLORS;
30
+ this.colorInputRef = viewChild("colorInput");
31
+ /**
32
+ * LOCAL MODE: We lock the mode when the menu is shown to avoid race conditions
33
+ * where the parent (bubble menu) clears the global signal before we apply the color.
34
+ */
35
+ this.activeMode = signal("text");
36
+ this.currentColor = computed(() => {
37
+ const marks = this.state().marks;
38
+ const color = this.activeMode() === "text" ? marks.computedColor : marks.computedBackground;
39
+ return color || (this.activeMode() === "text" ? "#000000" : "#ffff00");
40
+ });
41
+ this.hexValue = computed(() => {
42
+ const color = this.currentColor();
43
+ return color.replace("#", "").toUpperCase();
44
+ });
45
+ }
46
+ onStateChange() {
47
+ this.colorPickerSvc.editMode();
48
+ this.colorPickerSvc.menuTrigger();
49
+ this.colorPickerSvc.isInteracting();
50
+ }
51
+ shouldShow() {
52
+ const { isEditable } = this.state();
53
+ if (!isEditable) {
54
+ return false;
55
+ }
56
+ if (this.colorPickerSvc.editMode() !== null || this.colorPickerSvc.isInteracting()) {
57
+ return true;
58
+ }
59
+ return false;
60
+ }
61
+ getSelectionRect() {
62
+ const trigger = this.colorPickerSvc.menuTrigger();
63
+ const ed = this.editor();
64
+ if (!ed) {
65
+ return new DOMRect(0, 0, 0, 0);
66
+ }
67
+ // 1. If we have a stable trigger from service (toolbar or parent menu), anchor to it
68
+ if (trigger) {
69
+ const rect = trigger.getBoundingClientRect();
70
+ // Only use if it's still visible/in DOM (width > 0)
71
+ if (rect.width > 0) {
72
+ return rect;
73
+ }
74
+ }
75
+ // 2. Otherwise (bubble menu / relay), anchor to text selection
76
+ const { from } = ed.state.selection;
77
+ try {
78
+ const { node } = ed.view.domAtPos(from);
79
+ const element = node instanceof Element ? node : node.parentElement;
80
+ const colorElement = element?.closest('[style*="color"], [style*="background"], mark');
81
+ if (colorElement) {
82
+ return colorElement.getBoundingClientRect();
83
+ }
84
+ }
85
+ catch (_e) {
86
+ /* ignore */
87
+ }
88
+ // Use native selection for multi-line accuracy
89
+ const selection = window.getSelection();
90
+ if (selection && selection.rangeCount > 0) {
91
+ const range = selection.getRangeAt(0);
92
+ const rect = range.getBoundingClientRect();
93
+ if (rect.width > 0 && rect.height > 0) {
94
+ return rect;
95
+ }
96
+ }
97
+ // Final fallback to coordinates at cursor
98
+ const { top, bottom, left, right } = ed.view.coordsAtPos(from);
99
+ return new DOMRect(left, top, right - left, bottom - top);
100
+ }
101
+ onTippyShow(_instance) {
102
+ // 1. Lock the mode immediately to be immune to external signal changes
103
+ const currentMode = this.colorPickerSvc.editMode() || "text";
104
+ this.activeMode.set(currentMode);
105
+ // 2. Capture selection for the command fallback
106
+ this.colorPickerSvc.captureSelection(this.editor());
107
+ }
108
+ onTippyHide(_instance) {
109
+ // Clear trigger only AFTER the menu is hidden to maintain anchor stability during animation
110
+ this.colorPickerSvc.done();
111
+ this.colorPickerSvc.close();
112
+ }
113
+ isColorActive(color) {
114
+ return (this.colorPickerSvc.normalizeColor(this.currentColor()) ===
115
+ this.colorPickerSvc.normalizeColor(color));
116
+ }
117
+ applyColor(color, addToHistory = true, event) {
118
+ if (event) {
119
+ event.preventDefault();
120
+ event.stopPropagation();
121
+ }
122
+ const editor = this.editor();
123
+ // Use our LOCKED mode instead of the global signal
124
+ // Determine if we should focus back to the editor.
125
+ const shouldFocus = !this.colorPickerSvc.isInteracting();
126
+ if (this.activeMode() === "text") {
127
+ this.colorPickerSvc.applyColor(editor, color, addToHistory, shouldFocus);
128
+ }
129
+ else {
130
+ this.colorPickerSvc.applyHighlight(editor, color, addToHistory, shouldFocus);
131
+ }
132
+ }
133
+ onApply(event) {
134
+ if (event) {
135
+ event.preventDefault();
136
+ event.stopPropagation();
137
+ }
138
+ this.colorPickerSvc.close();
139
+ }
140
+ onHexInput(event) {
141
+ const input = event.target;
142
+ let value = input.value.trim();
143
+ if (!value.startsWith("#")) {
144
+ value = "#" + value;
145
+ }
146
+ if (/^#?[0-9A-Fa-f]{3,6}$/.test(value)) {
147
+ this.applyColor(value, false);
148
+ }
149
+ }
150
+ onHexChange(event) {
151
+ const input = event.target;
152
+ let value = input.value.trim();
153
+ if (!value.startsWith("#")) {
154
+ value = "#" + value;
155
+ }
156
+ if (/^#?[0-9A-Fa-f]{3,6}$/.test(value)) {
157
+ this.applyColor(value, true, event);
158
+ }
159
+ }
160
+ triggerNativePicker(event) {
161
+ if (event) {
162
+ event.preventDefault();
163
+ event.stopPropagation();
164
+ }
165
+ this.colorInputRef()?.nativeElement.click();
166
+ }
167
+ onNativeInput(event) {
168
+ this.applyColor(event.target.value, false);
169
+ }
170
+ onNativeChange(event) {
171
+ this.applyColor(event.target.value, true, event);
172
+ }
173
+ onClearColor(event) {
174
+ if (event) {
175
+ event.preventDefault();
176
+ event.stopPropagation();
177
+ }
178
+ const editor = this.editor();
179
+ if (this.activeMode() === "text") {
180
+ this.colorPickerSvc.unsetColor(editor);
181
+ }
182
+ else {
183
+ this.colorPickerSvc.unsetHighlight(editor);
184
+ }
185
+ }
186
+ onMouseDown(event) {
187
+ event.stopPropagation();
188
+ const target = event.target;
189
+ if (target.tagName !== "INPUT") {
190
+ event.preventDefault();
191
+ }
192
+ }
193
+ onFocus() {
194
+ this.colorPickerSvc.setInteracting(true);
195
+ }
196
+ onBlur() {
197
+ setTimeout(() => {
198
+ this.colorPickerSvc.setInteracting(false);
199
+ this.updateMenu();
200
+ }, 150);
201
+ }
202
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteColorBubbleMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
203
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AteColorBubbleMenuComponent, isStandalone: true, selector: "ate-color-bubble-menu", viewQueries: [{ propertyName: "colorInputRef", first: true, predicate: ["colorInput"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
204
+ <div
205
+ #menuRef
206
+ class="bubble-menu color-bubble-menu"
207
+ (mousedown)="onMouseDown($event)"
208
+ (click)="$event.stopPropagation()"
209
+ (keydown)="$event.stopPropagation()"
210
+ (keydown.escape)="onApply($event)"
211
+ tabindex="-1"
212
+ role="dialog">
213
+ <div class="color-picker-container">
214
+ <div class="dropdown-row presets">
215
+ <div class="color-grid">
216
+ @for (color of presets; track color) {
217
+ <ate-button
218
+ class="color-swatch-btn"
219
+ size="small"
220
+ [title]="color"
221
+ [active]="isColorActive(color)"
222
+ [backgroundColor]="color"
223
+ (buttonClick)="applyColor(color, true, $event)"></ate-button>
224
+ }
225
+ </div>
226
+ </div>
227
+
228
+ <div class="dropdown-row controls">
229
+ <div class="hex-input-wrapper">
230
+ <span class="hex-hash">#</span>
231
+ <input
232
+ #hexInput
233
+ type="text"
234
+ class="hex-input"
235
+ [value]="hexValue()"
236
+ [attr.aria-label]="t().customColor"
237
+ (input)="onHexInput($event)"
238
+ (change)="onHexChange($event)"
239
+ (keydown.enter)="onApply($event)"
240
+ (focus)="onFocus()"
241
+ (blur)="onBlur()"
242
+ maxlength="6"
243
+ placeholder="000000" />
244
+ </div>
245
+
246
+ <div class="native-trigger-wrapper">
247
+ <ate-button
248
+ class="btn-native-picker-trigger"
249
+ icon="colorize"
250
+ [title]="t().customColor"
251
+ [backgroundColor]="currentColor()"
252
+ (buttonClick)="triggerNativePicker($event)"></ate-button>
253
+ <input
254
+ #colorInput
255
+ type="color"
256
+ class="hidden-native-input"
257
+ [value]="currentColor()"
258
+ [attr.aria-label]="t().customColor"
259
+ (input)="onNativeInput($event)"
260
+ (change)="onNativeChange($event)"
261
+ (focus)="onFocus()"
262
+ (blur)="onBlur()" />
263
+ </div>
264
+
265
+ <ate-button
266
+ icon="check"
267
+ [title]="common().apply"
268
+ color="var(--ate-primary)"
269
+ (buttonClick)="onApply($event)"></ate-button>
270
+
271
+ <ate-separator />
272
+
273
+ <ate-button
274
+ icon="format_color_reset"
275
+ [title]="t().clear"
276
+ variant="danger"
277
+ (buttonClick)="onClearColor($event)"></ate-button>
278
+ </div>
279
+ </div>
280
+ </div>
281
+ `, isInline: true, styles: [".color-picker-container{display:flex;flex-direction:column;gap:8px}.dropdown-row{display:flex;align-items:center;width:100%}.dropdown-row.presets{justify-content:center}.dropdown-row.controls{gap:8px;justify-content:space-between;padding-top:4px;border-top:1px solid var(--ate-border, #e2e8f0)}.color-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:4px;width:100%}:host ::ng-deep .color-swatch-btn .ate-button{width:100%;aspect-ratio:1;height:auto;border-radius:4px;border:1px solid rgba(0,0,0,.1);padding:0}:host ::ng-deep .color-swatch-btn .ate-button.is-active{border-color:var(--ate-primary, #3b82f6);box-shadow:0 0 0 2px #3b82f64d}:host ::ng-deep .btn-native-picker-trigger .ate-button{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.2)}.divider-v{width:1px;height:24px;background:var(--ate-border, #e2e8f0)}.hex-input-wrapper{flex:1;display:flex;align-items:center;background:var(--ate-surface-secondary, #f8fafc);border:1px solid var(--ate-border, #e2e8f0);border-radius:8px;padding:0 10px;height:32px;transition:border-color .15s ease}.hex-input-wrapper:focus-within{border-color:var(--ate-primary, #3b82f6);background:var(--ate-menu-bg, #ffffff)}.hex-hash{color:var(--ate-text-muted, #94a3b8);font-family:monospace;font-size:.875rem}.hex-input{background:transparent;border:none;outline:none;color:var(--ate-text, #1e293b);font-family:monospace;font-size:.875rem;width:100%;padding-left:4px}.native-trigger-wrapper{position:relative;width:32px;height:32px}.hidden-native-input{position:absolute;inset:0;opacity:0;width:100%;height:100%;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: AteButtonComponent, selector: "ate-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["buttonClick"] }, { kind: "component", type: AteSeparatorComponent, selector: "ate-separator" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
282
+ }
283
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteColorBubbleMenuComponent, decorators: [{
284
+ type: Component,
285
+ args: [{ selector: "ate-color-bubble-menu", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, FormsModule, AteButtonComponent, AteSeparatorComponent], template: `
286
+ <div
287
+ #menuRef
288
+ class="bubble-menu color-bubble-menu"
289
+ (mousedown)="onMouseDown($event)"
290
+ (click)="$event.stopPropagation()"
291
+ (keydown)="$event.stopPropagation()"
292
+ (keydown.escape)="onApply($event)"
293
+ tabindex="-1"
294
+ role="dialog">
295
+ <div class="color-picker-container">
296
+ <div class="dropdown-row presets">
297
+ <div class="color-grid">
298
+ @for (color of presets; track color) {
299
+ <ate-button
300
+ class="color-swatch-btn"
301
+ size="small"
302
+ [title]="color"
303
+ [active]="isColorActive(color)"
304
+ [backgroundColor]="color"
305
+ (buttonClick)="applyColor(color, true, $event)"></ate-button>
306
+ }
307
+ </div>
308
+ </div>
309
+
310
+ <div class="dropdown-row controls">
311
+ <div class="hex-input-wrapper">
312
+ <span class="hex-hash">#</span>
313
+ <input
314
+ #hexInput
315
+ type="text"
316
+ class="hex-input"
317
+ [value]="hexValue()"
318
+ [attr.aria-label]="t().customColor"
319
+ (input)="onHexInput($event)"
320
+ (change)="onHexChange($event)"
321
+ (keydown.enter)="onApply($event)"
322
+ (focus)="onFocus()"
323
+ (blur)="onBlur()"
324
+ maxlength="6"
325
+ placeholder="000000" />
326
+ </div>
327
+
328
+ <div class="native-trigger-wrapper">
329
+ <ate-button
330
+ class="btn-native-picker-trigger"
331
+ icon="colorize"
332
+ [title]="t().customColor"
333
+ [backgroundColor]="currentColor()"
334
+ (buttonClick)="triggerNativePicker($event)"></ate-button>
335
+ <input
336
+ #colorInput
337
+ type="color"
338
+ class="hidden-native-input"
339
+ [value]="currentColor()"
340
+ [attr.aria-label]="t().customColor"
341
+ (input)="onNativeInput($event)"
342
+ (change)="onNativeChange($event)"
343
+ (focus)="onFocus()"
344
+ (blur)="onBlur()" />
345
+ </div>
346
+
347
+ <ate-button
348
+ icon="check"
349
+ [title]="common().apply"
350
+ color="var(--ate-primary)"
351
+ (buttonClick)="onApply($event)"></ate-button>
352
+
353
+ <ate-separator />
354
+
355
+ <ate-button
356
+ icon="format_color_reset"
357
+ [title]="t().clear"
358
+ variant="danger"
359
+ (buttonClick)="onClearColor($event)"></ate-button>
360
+ </div>
361
+ </div>
362
+ </div>
363
+ `, styles: [".color-picker-container{display:flex;flex-direction:column;gap:8px}.dropdown-row{display:flex;align-items:center;width:100%}.dropdown-row.presets{justify-content:center}.dropdown-row.controls{gap:8px;justify-content:space-between;padding-top:4px;border-top:1px solid var(--ate-border, #e2e8f0)}.color-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:4px;width:100%}:host ::ng-deep .color-swatch-btn .ate-button{width:100%;aspect-ratio:1;height:auto;border-radius:4px;border:1px solid rgba(0,0,0,.1);padding:0}:host ::ng-deep .color-swatch-btn .ate-button.is-active{border-color:var(--ate-primary, #3b82f6);box-shadow:0 0 0 2px #3b82f64d}:host ::ng-deep .btn-native-picker-trigger .ate-button{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.2)}.divider-v{width:1px;height:24px;background:var(--ate-border, #e2e8f0)}.hex-input-wrapper{flex:1;display:flex;align-items:center;background:var(--ate-surface-secondary, #f8fafc);border:1px solid var(--ate-border, #e2e8f0);border-radius:8px;padding:0 10px;height:32px;transition:border-color .15s ease}.hex-input-wrapper:focus-within{border-color:var(--ate-primary, #3b82f6);background:var(--ate-menu-bg, #ffffff)}.hex-hash{color:var(--ate-text-muted, #94a3b8);font-family:monospace;font-size:.875rem}.hex-input{background:transparent;border:none;outline:none;color:var(--ate-text, #1e293b);font-family:monospace;font-size:.875rem;width:100%;padding-left:4px}.native-trigger-wrapper{position:relative;width:32px;height:32px}.hidden-native-input{position:absolute;inset:0;opacity:0;width:100%;height:100%;cursor:pointer}\n"] }]
364
+ }] });
365
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRlLWNvbG9yLWJ1YmJsZS1tZW51LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItdGlwdGFwLWVkaXRvci9zcmMvbGliL2NvbXBvbmVudHMvYnViYmxlLW1lbnVzL2NvbG9yL2F0ZS1jb2xvci1idWJibGUtbWVudS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCx1QkFBdUIsRUFFdkIsTUFBTSxFQUNOLE1BQU0sRUFDTixRQUFRLEVBQ1IsU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFN0MsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFDbkYsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDbkUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDekUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7O0FBRXhFLE1BQU0sYUFBYSxHQUFHO0lBQ3BCLFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztDQUNWLENBQUM7QUFrTUYsTUFBTSxPQUFPLDJCQUE0QixTQUFRLG9CQUFvQjtJQWhNckU7O1FBaU1tQixtQkFBYyxHQUFHLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1FBRXZELE1BQUMsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQztRQUM3QixXQUFNLEdBQUcsSUFB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LE9BQU87UUFDTCxJQUFJLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBRUQsTUFBTTtRQUNKLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZCxJQUFJLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUMxQyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDcEIsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ1YsQ0FBQzsrR0FqTlUsMkJBQTJCO21HQUEzQiwyQkFBMkIscU9BM0w1Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBOEVULDJtREEvRVMsWUFBWSw4QkFBRSxXQUFXLCtCQUFFLGtCQUFrQiw2TEFBRSxxQkFBcUI7OzRGQTRMbkUsMkJBQTJCO2tCQWhNdkMsU0FBUzsrQkFDRSx1QkFBdUIsY0FDckIsSUFBSSxtQkFDQyx1QkFBdUIsQ0FBQyxNQUFNLFdBQ3RDLENBQUMsWUFBWSxFQUFFLFdBQVcsRUFBRSxrQkFBa0IsRUFBRSxxQkFBcUIsQ0FBQyxZQUNyRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBOEVUIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgRWxlbWVudFJlZixcbiAgc2lnbmFsLFxuICBpbmplY3QsXG4gIGNvbXB1dGVkLFxuICB2aWV3Q2hpbGQsXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uXCI7XG5pbXBvcnQgeyBGb3Jtc01vZHVsZSB9IGZyb20gXCJAYW5ndWxhci9mb3Jtc1wiO1xuaW1wb3J0IHsgSW5zdGFuY2UgYXMgVGlwcHlJbnN0YW5jZSB9IGZyb20gXCJ0aXBweS5qc1wiO1xuaW1wb3J0IHsgQXRlQ29sb3JQaWNrZXJTZXJ2aWNlIH0gZnJvbSBcIi4uLy4uLy4uL3NlcnZpY2VzL2F0ZS1jb2xvci1waWNrZXIuc2VydmljZVwiO1xuaW1wb3J0IHsgQXRlQnV0dG9uQ29tcG9uZW50IH0gZnJvbSBcIi4uLy4uL3VpL2F0ZS1idXR0b24uY29tcG9uZW50XCI7XG5pbXBvcnQgeyBBdGVTZXBhcmF0b3JDb21wb25lbnQgfSBmcm9tIFwiLi4vLi4vdWkvYXRlLXNlcGFyYXRvci5jb21wb25lbnRcIjtcbmltcG9ydCB7IEF0ZUJhc2VTdWJCdWJibGVNZW51IH0gZnJvbSBcIi4uL2Jhc2UvYXRlLWJhc2Utc3ViLWJ1YmJsZS1tZW51XCI7XG5cbmNvbnN0IFBSRVNFVF9DT0xPUlMgPSBbXG4gIFwiIzAwMDAwMFwiLFxuICBcIiM2NjY2NjZcIixcbiAgXCIjQ0NDQ0NDXCIsXG4gIFwiI0ZGRkZGRlwiLFxuICBcIiNGNDQzMzZcIixcbiAgXCIjRkY5ODAwXCIsXG4gIFwiI0ZGRUIzQlwiLFxuICBcIiM0Q0FGNTBcIixcbiAgXCIjMDBCQ0Q0XCIsXG4gIFwiIzIxOTZGM1wiLFxuICBcIiM5QzI3QjBcIixcbiAgXCIjRTkxRTYzXCIsXG5dO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6IFwiYXRlLWNvbG9yLWJ1YmJsZS1tZW51XCIsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBGb3Jtc01vZHVsZSwgQXRlQnV0dG9uQ29tcG9uZW50LCBBdGVTZXBhcmF0b3JDb21wb25lbnRdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXZcbiAgICAgICNtZW51UmVmXG4gICAgICBjbGFzcz1cImJ1YmJsZS1tZW51IGNvbG9yLWJ1YmJsZS1tZW51XCJcbiAgICAgIChtb3VzZWRvd24pPVwib25Nb3VzZURvd24oJGV2ZW50KVwiXG4gICAgICAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcbiAgICAgIChrZXlkb3duKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgICAoa2V5ZG93bi5lc2NhcGUpPVwib25BcHBseSgkZXZlbnQpXCJcbiAgICAgIHRhYmluZGV4PVwiLTFcIlxuICAgICAgcm9sZT1cImRpYWxvZ1wiPlxuICAgICAgPGRpdiBjbGFzcz1cImNvbG9yLXBpY2tlci1jb250YWluZXJcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImRyb3Bkb3duLXJvdyBwcmVzZXRzXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNvbG9yLWdyaWRcIj5cbiAgICAgICAgICAgIEBmb3IgKGNvbG9yIG9mIHByZXNldHM7IHRyYWNrIGNvbG9yKSB7XG4gICAgICAgICAgICAgIDxhdGUtYnV0dG9uXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJjb2xvci1zd2F0Y2gtYnRuXCJcbiAgICAgICAgICAgICAgICBzaXplPVwic21hbGxcIlxuICAgICAgICAgICAgICAgIFt0aXRsZV09XCJjb2xvclwiXG4gICAgICAgICAgICAgICAgW2FjdGl2ZV09XCJpc0NvbG9yQWN0aXZlKGNvbG9yKVwiXG4gICAgICAgICAgICAgICAgW2JhY2tncm91bmRDb2xvcl09XCJjb2xvclwiXG4gICAgICAgICAgICAgICAgKGJ1dHRvbkNsaWNrKT1cImFwcGx5Q29sb3IoY29sb3IsIHRydWUsICRldmVudClcIj48L2F0ZS1idXR0b24+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJkcm9wZG93bi1yb3cgY29udHJvbHNcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiaGV4LWlucHV0LXdyYXBwZXJcIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiaGV4LWhhc2hcIj4jPC9zcGFuPlxuICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICNoZXhJbnB1dFxuICAgICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICAgIGNsYXNzPVwiaGV4LWlucHV0XCJcbiAgICAgICAgICAgICAgW3ZhbHVlXT1cImhleFZhbHVlKClcIlxuICAgICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cInQoKS5jdXN0b21Db2xvclwiXG4gICAgICAgICAgICAgIChpbnB1dCk9XCJvbkhleElucHV0KCRldmVudClcIlxuICAgICAgICAgICAgICAoY2hhbmdlKT1cIm9uSGV4Q2hhbmdlKCRldmVudClcIlxuICAgICAgICAgICAgICAoa2V5ZG93bi5lbnRlcik9XCJvbkFwcGx5KCRldmVudClcIlxuICAgICAgICAgICAgICAoZm9jdXMpPVwib25Gb2N1cygpXCJcbiAgICAgICAgICAgICAgKGJsdXIpPVwib25CbHVyKClcIlxuICAgICAgICAgICAgICBtYXhsZW5ndGg9XCI2XCJcbiAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCIwMDAwMDBcIiAvPlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPGRpdiBjbGFzcz1cIm5hdGl2ZS10cmlnZ2VyLXdyYXBwZXJcIj5cbiAgICAgICAgICAgIDxhdGUtYnV0dG9uXG4gICAgICAgICAgICAgIGNsYXNzPVwiYnRuLW5hdGl2ZS1waWNrZXItdHJpZ2dlclwiXG4gICAgICAgICAgICAgIGljb249XCJjb2xvcml6ZVwiXG4gICAgICAgICAgICAgIFt0aXRsZV09XCJ0KCkuY3VzdG9tQ29sb3JcIlxuICAgICAgICAgICAgICBbYmFja2dyb3VuZENvbG9yXT1cImN1cnJlbnRDb2xvcigpXCJcbiAgICAgICAgICAgICAgKGJ1dHRvbkNsaWNrKT1cInRyaWdnZXJOYXRpdmVQaWNrZXIoJGV2ZW50KVwiPjwvYXRlLWJ1dHRvbj5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAjY29sb3JJbnB1dFxuICAgICAgICAgICAgICB0eXBlPVwiY29sb3JcIlxuICAgICAgICAgICAgICBjbGFzcz1cImhpZGRlbi1uYXRpdmUtaW5wdXRcIlxuICAgICAgICAgICAgICBbdmFsdWVdPVwiY3VycmVudENvbG9yKClcIlxuICAgICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cInQoKS5jdXN0b21Db2xvclwiXG4gICAgICAgICAgICAgIChpbnB1dCk9XCJvbk5hdGl2ZUlucHV0KCRldmVudClcIlxuICAgICAgICAgICAgICAoY2hhbmdlKT1cIm9uTmF0aXZlQ2hhbmdlKCRldmVudClcIlxuICAgICAgICAgICAgICAoZm9jdXMpPVwib25Gb2N1cygpXCJcbiAgICAgICAgICAgICAgKGJsdXIpPVwib25CbHVyKClcIiAvPlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPGF0ZS1idXR0b25cbiAgICAgICAgICAgIGljb249XCJjaGVja1wiXG4gICAgICAgICAgICBbdGl0bGVdPVwiY29tbW9uKCkuYXBwbHlcIlxuICAgICAgICAgICAgY29sb3I9XCJ2YXIoLS1hdGUtcHJpbWFyeSlcIlxuICAgICAgICAgICAgKGJ1dHRvbkNsaWNrKT1cIm9uQXBwbHkoJGV2ZW50KVwiPjwvYXRlLWJ1dHRvbj5cblxuICAgICAgICAgIDxhdGUtc2VwYXJhdG9yIC8+XG5cbiAgICAgICAgICA8YXRlLWJ1dHRvblxuICAgICAgICAgICAgaWNvbj1cImZvcm1hdF9jb2xvcl9yZXNldFwiXG4gICAgICAgICAgICBbdGl0bGVdPVwidCgpLmNsZWFyXCJcbiAgICAgICAgICAgIHZhcmlhbnQ9XCJkYW5nZXJcIlxuICAgICAgICAgICAgKGJ1dHRvbkNsaWNrKT1cIm9uQ2xlYXJDb2xvcigkZXZlbnQpXCI+PC9hdGUtYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICBgLFxuICBzdHlsZXM6IFtcbiAgICBgXG4gICAgICAuY29sb3ItcGlja2VyLWNvbnRhaW5lciB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgICAgIGdhcDogOHB4O1xuICAgICAgfVxuXG4gICAgICAuZHJvcGRvd24tcm93IHtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICB9XG5cbiAgICAgIC5kcm9wZG93bi1yb3cucHJlc2V0cyB7XG4gICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICAgICAgfVxuXG4gICAgICAuZHJvcGRvd24tcm93LmNvbnRyb2xzIHtcbiAgICAgICAgZ2FwOiA4cHg7XG4gICAgICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcbiAgICAgICAgcGFkZGluZy10b3A6IDRweDtcbiAgICAgICAgYm9yZGVyLXRvcDogMXB4IHNvbGlkIHZhcigtLWF0ZS1ib3JkZXIsICNlMmU4ZjApO1xuICAgICAgfVxuXG4gICAgICAuY29sb3ItZ3JpZCB7XG4gICAgICAgIGRpc3BsYXk6IGdyaWQ7XG4gICAgICAgIGdyaWQtdGVtcGxhdGUtY29sdW1uczogcmVwZWF0KDEyLCAxZnIpO1xuICAgICAgICBnYXA6IDRweDtcbiAgICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICB9XG5cbiAgICAgIDpob3N0IDo6bmctZGVlcCAuY29sb3Itc3dhdGNoLWJ0biAuYXRlLWJ1dHRvbiB7XG4gICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgICBhc3BlY3QtcmF0aW86IDE7XG4gICAgICAgIGhlaWdodDogYXV0bztcbiAgICAgICAgYm9yZGVyLXJhZGl1czogNHB4O1xuICAgICAgICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDAsIDAsIDAsIDAuMSk7XG4gICAgICAgIHBhZGRpbmc6IDA7XG4gICAgICB9XG5cbiAgICAgIDpob3N0IDo6bmctZGVlcCAuY29sb3Itc3dhdGNoLWJ0biAuYXRlLWJ1dHRvbi5pcy1hY3RpdmUge1xuICAgICAgICBib3JkZXItY29sb3I6IHZhcigtLWF0ZS1wcmltYXJ5LCAjM2I4MmY2KTtcbiAgICAgICAgYm94LXNoYWRvdzogMCAwIDAgMnB4IHJnYmEoNTksIDEzMCwgMjQ2LCAwLjMpO1xuICAgICAgfVxuXG4gICAgICA6aG9zdCA6Om5nLWRlZXAgLmJ0bi1uYXRpdmUtcGlja2VyLXRyaWdnZXIgLmF0ZS1idXR0b24ge1xuICAgICAgICBjb2xvcjogI2ZmZmZmZjtcbiAgICAgICAgdGV4dC1zaGFkb3c6IDAgMXB4IDJweCByZ2JhKDAsIDAsIDAsIDAuMik7XG4gICAgICB9XG5cbiAgICAgIC5kaXZpZGVyLXYge1xuICAgICAgICB3aWR0aDogMXB4O1xuICAgICAgICBoZWlnaHQ6IDI0cHg7XG4gICAgICAgIGJhY2tncm91bmQ6IHZhcigtLWF0ZS1ib3JkZXIsICNlMmU4ZjApO1xuICAgICAgfVxuXG4gICAgICAuaGV4LWlucHV0LXdyYXBwZXIge1xuICAgICAgICBmbGV4OiAxO1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICBiYWNrZ3JvdW5kOiB2YXIoLS1hdGUtc3VyZmFjZS1zZWNvbmRhcnksICNmOGZhZmMpO1xuICAgICAgICBib3JkZXI6IDFweCBzb2xpZCB2YXIoLS1hdGUtYm9yZGVyLCAjZTJlOGYwKTtcbiAgICAgICAgYm9yZGVyLXJhZGl1czogOHB4O1xuICAgICAgICBwYWRkaW5nOiAwIDEwcHg7XG4gICAgICAgIGhlaWdodDogMzJweDtcbiAgICAgICAgdHJhbnNpdGlvbjogYm9yZGVyLWNvbG9yIDE1MG1zIGVhc2U7XG4gICAgICB9XG5cbiAgICAgIC5oZXgtaW5wdXQtd3JhcHBlcjpmb2N1cy13aXRoaW4ge1xuICAgICAgICBib3JkZXItY29sb3I6IHZhcigtLWF0ZS1wcmltYXJ5LCAjM2I4MmY2KTtcbiAgICAgICAgYmFja2dyb3VuZDogdmFyKC0tYXRlLW1lbnUtYmcsICNmZmZmZmYpO1xuICAgICAgfVxuXG4gICAgICAuaGV4LWhhc2gge1xuICAgICAgICBjb2xvcjogdmFyKC0tYXRlLXRleHQtbXV0ZWQsICM5NGEzYjgpO1xuICAgICAgICBmb250LWZhbWlseTogbW9ub3NwYWNlO1xuICAgICAgICBmb250LXNpemU6IDAuODc1cmVtO1xuICAgICAgfVxuXG4gICAgICAuaGV4LWlucHV0IHtcbiAgICAgICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XG4gICAgICAgIGJvcmRlcjogbm9uZTtcbiAgICAgICAgb3V0bGluZTogbm9uZTtcbiAgICAgICAgY29sb3I6IHZhcigtLWF0ZS10ZXh0LCAjMWUyOTNiKTtcbiAgICAgICAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTtcbiAgICAgICAgZm9udC1zaXplOiAwLjg3NXJlbTtcbiAgICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICAgIHBhZGRpbmctbGVmdDogNHB4O1xuICAgICAgfVxuXG4gICAgICAubmF0aXZlLXRyaWdnZXItd3JhcHBlciB7XG4gICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICAgICAgd2lkdGg6IDMycHg7XG4gICAgICAgIGhlaWdodDogMzJweDtcbiAgICAgIH1cblxuICAgICAgLmhpZGRlbi1uYXRpdmUtaW5wdXQge1xuICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgICAgIGluc2V0OiAwO1xuICAgICAgICBvcGFjaXR5OiAwO1xuICAgICAgICB3aWR0aDogMTAwJTtcbiAgICAgICAgaGVpZ2h0OiAxMDAlO1xuICAgICAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgICB9XG4gICAgYCxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgQXRlQ29sb3JCdWJibGVNZW51Q29tcG9uZW50IGV4dGVuZHMgQXRlQmFzZVN1YkJ1YmJsZU1lbnUge1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbG9yUGlja2VyU3ZjID0gaW5qZWN0KEF0ZUNvbG9yUGlja2VyU2VydmljZSk7XG5cbiAgcmVhZG9ubHkgdCA9IHRoaXMuaTE4blNlcnZpY2UudG9vbGJhcjtcbiAgcmVhZG9ubHkgY29tbW9uID0gdGhpcy5pMThuU2VydmljZS5jb21tb247XG4gIHJlYWRvbmx5IHByZXNldHMgPSBQUkVTRVRfQ09MT1JTO1xuXG4gIHByaXZhdGUgY29sb3JJbnB1dFJlZiA9IHZpZXdDaGlsZDxFbGVtZW50UmVmPEhUTUxJbnB1dEVsZW1lbnQ+PihcImNvbG9ySW5wdXRcIik7XG5cbiAgLyoqXG4gICAqIExPQ0FMIE1PREU6IFdlIGxvY2sgdGhlIG1vZGUgd2hlbiB0aGUgbWVudSBpcyBzaG93biB0byBhdm9pZCByYWNlIGNvbmRpdGlvbnNcbiAgICogd2hlcmUgdGhlIHBhcmVudCAoYnViYmxlIG1lbnUpIGNsZWFycyB0aGUgZ2xvYmFsIHNpZ25hbCBiZWZvcmUgd2UgYXBwbHkgdGhlIGNvbG9yLlxuICAgKi9cbiAgYWN0aXZlTW9kZSA9IHNpZ25hbDxcInRleHRcIiB8IFwiaGlnaGxpZ2h0XCI+KFwidGV4dFwiKTtcblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgb25TdGF0ZUNoYW5nZSgpIHtcbiAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLmVkaXRNb2RlKCk7XG4gICAgdGhpcy5jb2xvclBpY2tlclN2Yy5tZW51VHJpZ2dlcigpO1xuICAgIHRoaXMuY29sb3JQaWNrZXJTdmMuaXNJbnRlcmFjdGluZygpO1xuICB9XG5cbiAgb3ZlcnJpZGUgc2hvdWxkU2hvdygpOiBib29sZWFuIHtcbiAgICBjb25zdCB7IGlzRWRpdGFibGUgfSA9IHRoaXMuc3RhdGUoKTtcbiAgICBpZiAoIWlzRWRpdGFibGUpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5jb2xvclBpY2tlclN2Yy5lZGl0TW9kZSgpICE9PSBudWxsIHx8IHRoaXMuY29sb3JQaWNrZXJTdmMuaXNJbnRlcmFjdGluZygpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBvdmVycmlkZSBnZXRTZWxlY3Rpb25SZWN0KCk6IERPTVJlY3Qge1xuICAgIGNvbnN0IHRyaWdnZXIgPSB0aGlzLmNvbG9yUGlja2VyU3ZjLm1lbnVUcmlnZ2VyKCk7XG4gICAgY29uc3QgZWQgPSB0aGlzLmVkaXRvcigpO1xuICAgIGlmICghZWQpIHtcbiAgICAgIHJldHVybiBuZXcgRE9NUmVjdCgwLCAwLCAwLCAwKTtcbiAgICB9XG5cbiAgICAvLyAxLiBJZiB3ZSBoYXZlIGEgc3RhYmxlIHRyaWdnZXIgZnJvbSBzZXJ2aWNlICh0b29sYmFyIG9yIHBhcmVudCBtZW51KSwgYW5jaG9yIHRvIGl0XG4gICAgaWYgKHRyaWdnZXIpIHtcbiAgICAgIGNvbnN0IHJlY3QgPSB0cmlnZ2VyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgLy8gT25seSB1c2UgaWYgaXQncyBzdGlsbCB2aXNpYmxlL2luIERPTSAod2lkdGggPiAwKVxuICAgICAgaWYgKHJlY3Qud2lkdGggPiAwKSB7XG4gICAgICAgIHJldHVybiByZWN0O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIDIuIE90aGVyd2lzZSAoYnViYmxlIG1lbnUgLyByZWxheSksIGFuY2hvciB0byB0ZXh0IHNlbGVjdGlvblxuICAgIGNvbnN0IHsgZnJvbSB9ID0gZWQuc3RhdGUuc2VsZWN0aW9uO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgbm9kZSB9ID0gZWQudmlldy5kb21BdFBvcyhmcm9tKTtcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSBub2RlIGluc3RhbmNlb2YgRWxlbWVudCA/IG5vZGUgOiBub2RlLnBhcmVudEVsZW1lbnQ7XG4gICAgICBjb25zdCBjb2xvckVsZW1lbnQgPSAoZWxlbWVudCBhcyBFbGVtZW50KT8uY2xvc2VzdChcbiAgICAgICAgJ1tzdHlsZSo9XCJjb2xvclwiXSwgW3N0eWxlKj1cImJhY2tncm91bmRcIl0sIG1hcmsnXG4gICAgICApO1xuICAgICAgaWYgKGNvbG9yRWxlbWVudCkge1xuICAgICAgICByZXR1cm4gY29sb3JFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKF9lKSB7XG4gICAgICAvKiBpZ25vcmUgKi9cbiAgICB9XG5cbiAgICAvLyBVc2UgbmF0aXZlIHNlbGVjdGlvbiBmb3IgbXVsdGktbGluZSBhY2N1cmFjeVxuICAgIGNvbnN0IHNlbGVjdGlvbiA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICBpZiAoc2VsZWN0aW9uICYmIHNlbGVjdGlvbi5yYW5nZUNvdW50ID4gMCkge1xuICAgICAgY29uc3QgcmFuZ2UgPSBzZWxlY3Rpb24uZ2V0UmFuZ2VBdCgwKTtcbiAgICAgIGNvbnN0IHJlY3QgPSByYW5nZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIGlmIChyZWN0LndpZHRoID4gMCAmJiByZWN0LmhlaWdodCA+IDApIHtcbiAgICAgICAgcmV0dXJuIHJlY3Q7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRmluYWwgZmFsbGJhY2sgdG8gY29vcmRpbmF0ZXMgYXQgY3Vyc29yXG4gICAgY29uc3QgeyB0b3AsIGJvdHRvbSwgbGVmdCwgcmlnaHQgfSA9IGVkLnZpZXcuY29vcmRzQXRQb3MoZnJvbSk7XG4gICAgcmV0dXJuIG5ldyBET01SZWN0KGxlZnQsIHRvcCwgcmlnaHQgLSBsZWZ0LCBib3R0b20gLSB0b3ApO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIG9uVGlwcHlTaG93KF9pbnN0YW5jZTogVGlwcHlJbnN0YW5jZSkge1xuICAgIC8vIDEuIExvY2sgdGhlIG1vZGUgaW1tZWRpYXRlbHkgdG8gYmUgaW1tdW5lIHRvIGV4dGVybmFsIHNpZ25hbCBjaGFuZ2VzXG4gICAgY29uc3QgY3VycmVudE1vZGUgPSB0aGlzLmNvbG9yUGlja2VyU3ZjLmVkaXRNb2RlKCkgfHwgXCJ0ZXh0XCI7XG4gICAgdGhpcy5hY3RpdmVNb2RlLnNldChjdXJyZW50TW9kZSk7XG5cbiAgICAvLyAyLiBDYXB0dXJlIHNlbGVjdGlvbiBmb3IgdGhlIGNvbW1hbmQgZmFsbGJhY2tcbiAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLmNhcHR1cmVTZWxlY3Rpb24odGhpcy5lZGl0b3IoKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgb25UaXBweUhpZGUoX2luc3RhbmNlOiBUaXBweUluc3RhbmNlKSB7XG4gICAgLy8gQ2xlYXIgdHJpZ2dlciBvbmx5IEFGVEVSIHRoZSBtZW51IGlzIGhpZGRlbiB0byBtYWludGFpbiBhbmNob3Igc3RhYmlsaXR5IGR1cmluZyBhbmltYXRpb25cbiAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLmRvbmUoKTtcbiAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLmNsb3NlKCk7XG4gIH1cblxuICByZWFkb25seSBjdXJyZW50Q29sb3IgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgbWFya3MgPSB0aGlzLnN0YXRlKCkubWFya3M7XG4gICAgY29uc3QgY29sb3IgPSB0aGlzLmFjdGl2ZU1vZGUoKSA9PT0gXCJ0ZXh0XCIgPyBtYXJrcy5jb21wdXRlZENvbG9yIDogbWFya3MuY29tcHV0ZWRCYWNrZ3JvdW5kO1xuICAgIHJldHVybiBjb2xvciB8fCAodGhpcy5hY3RpdmVNb2RlKCkgPT09IFwidGV4dFwiID8gXCIjMDAwMDAwXCIgOiBcIiNmZmZmMDBcIik7XG4gIH0pO1xuXG4gIHJlYWRvbmx5IGhleFZhbHVlID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IGNvbG9yID0gdGhpcy5jdXJyZW50Q29sb3IoKTtcbiAgICByZXR1cm4gY29sb3IucmVwbGFjZShcIiNcIiwgXCJcIikudG9VcHBlckNhc2UoKTtcbiAgfSk7XG5cbiAgaXNDb2xvckFjdGl2ZShjb2xvcjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuY29sb3JQaWNrZXJTdmMubm9ybWFsaXplQ29sb3IodGhpcy5jdXJyZW50Q29sb3IoKSkgPT09XG4gICAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLm5vcm1hbGl6ZUNvbG9yKGNvbG9yKVxuICAgICk7XG4gIH1cblxuICBhcHBseUNvbG9yKGNvbG9yOiBzdHJpbmcsIGFkZFRvSGlzdG9yeSA9IHRydWUsIGV2ZW50PzogRXZlbnQpIHtcbiAgICBpZiAoZXZlbnQpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9XG5cbiAgICBjb25zdCBlZGl0b3IgPSB0aGlzLmVkaXRvcigpO1xuICAgIC8vIFVzZSBvdXIgTE9DS0VEIG1vZGUgaW5zdGVhZCBvZiB0aGUgZ2xvYmFsIHNpZ25hbFxuICAgIC8vIERldGVybWluZSBpZiB3ZSBzaG91bGQgZm9jdXMgYmFjayB0byB0aGUgZWRpdG9yLlxuICAgIGNvbnN0IHNob3VsZEZvY3VzID0gIXRoaXMuY29sb3JQaWNrZXJTdmMuaXNJbnRlcmFjdGluZygpO1xuXG4gICAgaWYgKHRoaXMuYWN0aXZlTW9kZSgpID09PSBcInRleHRcIikge1xuICAgICAgdGhpcy5jb2xvclBpY2tlclN2Yy5hcHBseUNvbG9yKGVkaXRvciwgY29sb3IsIGFkZFRvSGlzdG9yeSwgc2hvdWxkRm9jdXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLmFwcGx5SGlnaGxpZ2h0KGVkaXRvciwgY29sb3IsIGFkZFRvSGlzdG9yeSwgc2hvdWxkRm9jdXMpO1xuICAgIH1cbiAgfVxuXG4gIG9uQXBwbHkoZXZlbnQ/OiBFdmVudCkge1xuICAgIGlmIChldmVudCkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIH1cbiAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLmNsb3NlKCk7XG4gIH1cblxuICBvbkhleElucHV0KGV2ZW50OiBFdmVudCkge1xuICAgIGNvbnN0IGlucHV0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgbGV0IHZhbHVlID0gaW5wdXQudmFsdWUudHJpbSgpO1xuICAgIGlmICghdmFsdWUuc3RhcnRzV2l0aChcIiNcIikpIHtcbiAgICAgIHZhbHVlID0gXCIjXCIgKyB2YWx1ZTtcbiAgICB9XG4gICAgaWYgKC9eIz9bMC05QS1GYS1mXXszLDZ9JC8udGVzdCh2YWx1ZSkpIHtcbiAgICAgIHRoaXMuYXBwbHlDb2xvcih2YWx1ZSwgZmFsc2UpO1xuICAgIH1cbiAgfVxuXG4gIG9uSGV4Q2hhbmdlKGV2ZW50OiBFdmVudCkge1xuICAgIGNvbnN0IGlucHV0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgbGV0IHZhbHVlID0gaW5wdXQudmFsdWUudHJpbSgpO1xuICAgIGlmICghdmFsdWUuc3RhcnRzV2l0aChcIiNcIikpIHtcbiAgICAgIHZhbHVlID0gXCIjXCIgKyB2YWx1ZTtcbiAgICB9XG4gICAgaWYgKC9eIz9bMC05QS1GYS1mXXszLDZ9JC8udGVzdCh2YWx1ZSkpIHtcbiAgICAgIHRoaXMuYXBwbHlDb2xvcih2YWx1ZSwgdHJ1ZSwgZXZlbnQpO1xuICAgIH1cbiAgfVxuXG4gIHRyaWdnZXJOYXRpdmVQaWNrZXIoZXZlbnQ/OiBFdmVudCkge1xuICAgIGlmIChldmVudCkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIH1cbiAgICB0aGlzLmNvbG9ySW5wdXRSZWYoKT8ubmF0aXZlRWxlbWVudC5jbGljaygpO1xuICB9XG5cbiAgb25OYXRpdmVJbnB1dChldmVudDogRXZlbnQpIHtcbiAgICB0aGlzLmFwcGx5Q29sb3IoKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZSwgZmFsc2UpO1xuICB9XG5cbiAgb25OYXRpdmVDaGFuZ2UoZXZlbnQ6IEV2ZW50KSB7XG4gICAgdGhpcy5hcHBseUNvbG9yKChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkudmFsdWUsIHRydWUsIGV2ZW50KTtcbiAgfVxuXG4gIG9uQ2xlYXJDb2xvcihldmVudD86IEV2ZW50KSB7XG4gICAgaWYgKGV2ZW50KSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfVxuXG4gICAgY29uc3QgZWRpdG9yID0gdGhpcy5lZGl0b3IoKTtcbiAgICBpZiAodGhpcy5hY3RpdmVNb2RlKCkgPT09IFwidGV4dFwiKSB7XG4gICAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLnVuc2V0Q29sb3IoZWRpdG9yKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5jb2xvclBpY2tlclN2Yy51bnNldEhpZ2hsaWdodChlZGl0b3IpO1xuICAgIH1cbiAgfVxuXG4gIG9uTW91c2VEb3duKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgY29uc3QgdGFyZ2V0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgIGlmICh0YXJnZXQudGFnTmFtZSAhPT0gXCJJTlBVVFwiKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbiAgfVxuXG4gIG9uRm9jdXMoKSB7XG4gICAgdGhpcy5jb2xvclBpY2tlclN2Yy5zZXRJbnRlcmFjdGluZyh0cnVlKTtcbiAgfVxuXG4gIG9uQmx1cigpIHtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMuY29sb3JQaWNrZXJTdmMuc2V0SW50ZXJhY3RpbmcoZmFsc2UpO1xuICAgICAgdGhpcy51cGRhdGVNZW51KCk7XG4gICAgfSwgMTUwKTtcbiAgfVxufVxuIl19