@flogeez/angular-tiptap-editor 2.3.0 → 2.4.1

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 (105) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +132 -93
  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 +133 -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 +226 -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 +121 -0
  11. package/esm2022/lib/components/bubble-menus/table/ate-table-bubble-menu.component.mjs +266 -0
  12. package/esm2022/lib/components/bubble-menus/text/ate-bubble-menu.component.mjs +294 -0
  13. package/esm2022/lib/components/color-picker/ate-color-picker.component.mjs +122 -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 +953 -0
  16. package/esm2022/lib/components/slash-commands/ate-slash-commands.component.mjs +329 -0
  17. package/esm2022/lib/components/toolbar/ate-toolbar.component.mjs +531 -0
  18. package/esm2022/lib/components/ui/ate-button.component.mjs +90 -0
  19. package/esm2022/lib/components/ui/ate-separator.component.mjs +31 -0
  20. package/esm2022/lib/config/ate-editor.config.mjs +76 -0
  21. package/esm2022/lib/config/ate-global-config.token.mjs +6 -0
  22. package/esm2022/lib/config/ate-slash-commands.config.mjs +130 -0
  23. package/esm2022/lib/directives/ate-noop-value-accessor.directive.mjs +40 -0
  24. package/esm2022/lib/extensions/ate-link-click-behavior.extension.mjs +32 -0
  25. package/esm2022/lib/extensions/ate-resizable-image.extension.mjs +270 -0
  26. package/esm2022/lib/extensions/ate-table.extension.mjs +29 -0
  27. package/esm2022/lib/extensions/ate-tiptap-state.extension.mjs +85 -0
  28. package/esm2022/lib/extensions/ate-upload-progress.extension.mjs +195 -0
  29. package/esm2022/lib/extensions/calculators/ate-discovery.calculator.mjs +62 -0
  30. package/esm2022/lib/extensions/calculators/ate-image.calculator.mjs +8 -0
  31. package/esm2022/lib/extensions/calculators/ate-marks.calculator.mjs +75 -0
  32. package/esm2022/lib/extensions/calculators/ate-selection.calculator.mjs +35 -0
  33. package/esm2022/lib/extensions/calculators/ate-structure.calculator.mjs +34 -0
  34. package/esm2022/lib/extensions/calculators/ate-table.calculator.mjs +38 -0
  35. package/esm2022/lib/models/ate-bubble-menu.model.mjs +49 -0
  36. package/esm2022/lib/models/ate-editor-config.model.mjs +2 -0
  37. package/esm2022/lib/models/ate-editor-state.model.mjs +90 -0
  38. package/esm2022/lib/models/ate-image.model.mjs +2 -0
  39. package/esm2022/lib/models/ate-toolbar.model.mjs +35 -0
  40. package/esm2022/lib/node-view/ate-angular-node-view.mjs +97 -0
  41. package/esm2022/lib/node-view/ate-injector.registry.mjs +16 -0
  42. package/esm2022/lib/node-view/ate-node-view.factory.mjs +125 -0
  43. package/esm2022/lib/node-view/ate-node-view.models.mjs +2 -0
  44. package/esm2022/lib/node-view/ate-node-view.renderer.mjs +154 -0
  45. package/esm2022/lib/node-view/ate-register-angular-component.mjs +49 -0
  46. package/esm2022/lib/services/ate-color-picker.service.mjs +193 -0
  47. package/esm2022/lib/services/ate-editor-commands.service.mjs +465 -0
  48. package/esm2022/lib/services/ate-i18n.service.mjs +410 -0
  49. package/esm2022/lib/services/ate-image.service.mjs +368 -0
  50. package/esm2022/lib/services/ate-link.service.mjs +97 -0
  51. package/esm2022/lib/utils/ate-color.utils.mjs +60 -0
  52. package/esm2022/public-api.mjs +93 -0
  53. package/fesm2022/flogeez-angular-tiptap-editor.mjs +1178 -1100
  54. package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
  55. package/index.d.ts +3 -1562
  56. package/lib/ate-editor.provider.d.ts +21 -0
  57. package/lib/components/bubble-menus/base/ate-base-bubble-menu.d.ts +71 -0
  58. package/lib/components/bubble-menus/base/ate-base-sub-bubble-menu.d.ts +60 -0
  59. package/lib/components/bubble-menus/color/ate-color-bubble-menu.component.d.ts +77 -0
  60. package/lib/components/bubble-menus/image/ate-image-bubble-menu.component.d.ts +52 -0
  61. package/lib/components/bubble-menus/link/ate-link-bubble-menu.component.d.ts +55 -0
  62. package/lib/components/bubble-menus/table/ate-cell-bubble-menu.component.d.ts +12 -0
  63. package/lib/components/bubble-menus/table/ate-table-bubble-menu.component.d.ts +24 -0
  64. package/lib/components/bubble-menus/text/ate-bubble-menu.component.d.ts +53 -0
  65. package/lib/components/color-picker/ate-color-picker.component.d.ts +54 -0
  66. package/lib/components/edit-toggle/ate-edit-toggle.component.d.ts +13 -0
  67. package/lib/components/editor/angular-tiptap-editor.component.d.ts +235 -0
  68. package/lib/components/slash-commands/ate-slash-commands.component.d.ts +43 -0
  69. package/lib/components/toolbar/ate-toolbar.component.d.ts +47 -0
  70. package/lib/components/ui/ate-button.component.d.ts +25 -0
  71. package/lib/components/ui/ate-separator.component.d.ts +7 -0
  72. package/lib/config/ate-editor.config.d.ts +7 -0
  73. package/lib/config/ate-global-config.token.d.ts +6 -0
  74. package/lib/config/ate-slash-commands.config.d.ts +41 -0
  75. package/lib/directives/ate-noop-value-accessor.directive.d.ts +13 -0
  76. package/lib/extensions/ate-link-click-behavior.extension.d.ts +2 -0
  77. package/lib/extensions/ate-resizable-image.extension.d.ts +27 -0
  78. package/lib/extensions/ate-table.extension.d.ts +2 -0
  79. package/lib/extensions/ate-tiptap-state.extension.d.ts +7 -0
  80. package/lib/extensions/ate-upload-progress.extension.d.ts +7 -0
  81. package/lib/extensions/calculators/ate-discovery.calculator.d.ts +7 -0
  82. package/lib/extensions/calculators/ate-image.calculator.d.ts +2 -0
  83. package/lib/extensions/calculators/ate-marks.calculator.d.ts +2 -0
  84. package/lib/extensions/calculators/ate-selection.calculator.d.ts +2 -0
  85. package/lib/extensions/calculators/ate-structure.calculator.d.ts +2 -0
  86. package/lib/extensions/calculators/ate-table.calculator.d.ts +2 -0
  87. package/lib/models/ate-bubble-menu.model.d.ts +33 -0
  88. package/lib/models/ate-editor-config.model.d.ts +100 -0
  89. package/lib/models/ate-editor-state.model.d.ts +109 -0
  90. package/lib/models/ate-image.model.d.ts +104 -0
  91. package/lib/models/ate-toolbar.model.d.ts +18 -0
  92. package/lib/node-view/ate-angular-node-view.d.ts +115 -0
  93. package/lib/node-view/ate-injector.registry.d.ts +3 -0
  94. package/lib/node-view/ate-node-view.factory.d.ts +10 -0
  95. package/lib/node-view/ate-node-view.models.d.ts +138 -0
  96. package/lib/node-view/ate-node-view.renderer.d.ts +23 -0
  97. package/lib/node-view/ate-register-angular-component.d.ts +35 -0
  98. package/lib/services/ate-color-picker.service.d.ts +65 -0
  99. package/lib/services/ate-editor-commands.service.d.ts +72 -0
  100. package/lib/services/ate-i18n.service.d.ts +394 -0
  101. package/lib/services/ate-image.service.d.ts +71 -0
  102. package/lib/services/ate-link.service.d.ts +42 -0
  103. package/lib/utils/ate-color.utils.d.ts +12 -0
  104. package/package.json +3 -1
  105. package/public-api.d.ts +112 -0
@@ -0,0 +1,133 @@
1
+ import { Directive, input, viewChild, inject, effect, } from "@angular/core";
2
+ import tippy, { sticky } from "tippy.js";
3
+ import { AteEditorCommandsService } from "../../../services/ate-editor-commands.service";
4
+ import { AteI18nService } from "../../../services/ate-i18n.service";
5
+ import * as i0 from "@angular/core";
6
+ /**
7
+ * Base abstract class for Sub-Bubble Menus (Link, Color).
8
+ * These menus are "sub-menus" of the main bubble menu or triggered/anchored by specific UI elements.
9
+ */
10
+ export class AteBaseSubBubbleMenu {
11
+ constructor() {
12
+ this.i18nService = inject(AteI18nService);
13
+ this.editorCommands = inject(AteEditorCommandsService);
14
+ // Core Inputs
15
+ this.editor = input.required();
16
+ // Required viewChild for the menu container
17
+ this.menuRef = viewChild.required("menuRef");
18
+ // Internal State
19
+ this.tippyInstance = null;
20
+ this.updateTimeout = null;
21
+ // Reactive state alias for templates
22
+ this.state = this.editorCommands.editorState;
23
+ /**
24
+ * Core logic to decide whether to show or hide the menu.
25
+ */
26
+ this.updateMenu = () => {
27
+ if (this.updateTimeout) {
28
+ clearTimeout(this.updateTimeout);
29
+ }
30
+ this.updateTimeout = setTimeout(() => {
31
+ if (this.shouldShow()) {
32
+ this.showTippy();
33
+ }
34
+ else {
35
+ this.hideTippy();
36
+ }
37
+ }, 10);
38
+ };
39
+ // Reactive effect for menu updates (re-positioning)
40
+ effect(() => {
41
+ // Monitor editor state and specific sub-menu states
42
+ this.state();
43
+ this.onStateChange();
44
+ this.updateMenu();
45
+ }, { allowSignalWrites: true });
46
+ }
47
+ ngOnInit() {
48
+ this.initTippy();
49
+ }
50
+ ngOnDestroy() {
51
+ if (this.updateTimeout) {
52
+ clearTimeout(this.updateTimeout);
53
+ }
54
+ if (this.tippyInstance) {
55
+ this.tippyInstance.destroy();
56
+ this.tippyInstance = null;
57
+ }
58
+ }
59
+ /**
60
+ * Initializes the Tippy instance with sub-menu defaults.
61
+ */
62
+ initTippy() {
63
+ if (!this.menuRef()?.nativeElement) {
64
+ setTimeout(() => this.initTippy(), 50);
65
+ return;
66
+ }
67
+ const ed = this.editor();
68
+ if (this.tippyInstance) {
69
+ this.tippyInstance.destroy();
70
+ }
71
+ this.tippyInstance = tippy(document.body, {
72
+ content: this.menuRef().nativeElement,
73
+ trigger: "manual",
74
+ placement: "bottom-start",
75
+ appendTo: () => ed.options.element,
76
+ interactive: true,
77
+ arrow: false,
78
+ offset: [0, 8],
79
+ hideOnClick: true,
80
+ plugins: [sticky],
81
+ sticky: false,
82
+ getReferenceClientRect: () => this.getSelectionRect(),
83
+ popperOptions: {
84
+ modifiers: [
85
+ {
86
+ name: "preventOverflow",
87
+ options: { boundary: ed.options.element, padding: 8 },
88
+ },
89
+ {
90
+ name: "flip",
91
+ options: { fallbackPlacements: ["top-start", "bottom-end", "top-end"] },
92
+ },
93
+ ],
94
+ },
95
+ onShow: instance => this.onTippyShow(instance),
96
+ onHide: instance => this.onTippyHide(instance),
97
+ });
98
+ this.updateMenu();
99
+ }
100
+ /**
101
+ * Helper to show the Tippy instance with updated positioning.
102
+ */
103
+ showTippy() {
104
+ if (this.tippyInstance) {
105
+ this.tippyInstance.setProps({ getReferenceClientRect: () => this.getSelectionRect() });
106
+ this.tippyInstance.show();
107
+ }
108
+ }
109
+ /**
110
+ * Helper to hide the Tippy instance.
111
+ */
112
+ hideTippy() {
113
+ this.tippyInstance?.hide();
114
+ }
115
+ /**
116
+ * Optional hook called when Tippy is about to be shown.
117
+ */
118
+ onTippyShow(_instance) {
119
+ /* empty */
120
+ }
121
+ /**
122
+ * Optional hook called when Tippy is about to be hidden.
123
+ */
124
+ onTippyHide(_instance) {
125
+ /* empty */
126
+ }
127
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteBaseSubBubbleMenu, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
128
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "18.2.14", type: AteBaseSubBubbleMenu, inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "menuRef", first: true, predicate: ["menuRef"], descendants: true, isSignal: true }], ngImport: i0 }); }
129
+ }
130
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteBaseSubBubbleMenu, decorators: [{
131
+ type: Directive
132
+ }], ctorParameters: () => [] });
133
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRlLWJhc2Utc3ViLWJ1YmJsZS1tZW51LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhci10aXB0YXAtZWRpdG9yL3NyYy9saWIvY29tcG9uZW50cy9idWJibGUtbWVudXMvYmFzZS9hdGUtYmFzZS1zdWItYnViYmxlLW1lbnUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBQ0wsU0FBUyxFQUlULE1BQU0sRUFDTixNQUFNLEdBQ1AsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxLQUFLLEVBQUUsRUFBNkIsTUFBTSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBRXBFLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLCtDQUErQyxDQUFDO0FBQ3pGLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQzs7QUFFcEU7OztHQUdHO0FBRUgsTUFBTSxPQUFnQixvQkFBb0I7SUFpQnhDO1FBaEJtQixnQkFBVyxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNyQyxtQkFBYyxHQUFHLE1BQU0sQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBRXJFLGNBQWM7UUFDZCxXQUFNLEdBQUcsS0FBSyxDQUFDLFFBQVEsRUFBVSxDQUFDO1FBRWxDLDRDQUE0QztRQUM1QyxZQUFPLEdBQUcsU0FBUyxDQUFDLFFBQVEsQ0FBNkIsU0FBUyxDQUFDLENBQUM7UUFFcEUsaUJBQWlCO1FBQ1Asa0JBQWEsR0FBeUIsSUFBSSxDQUFDO1FBQzNDLGtCQUFhLEdBQWtCLElBQUksQ0FBQztRQUU5QyxxQ0FBcUM7UUFDNUIsVUFBSyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDO1FBd0VqRDs7V0FFRztRQUNILGVBQVUsR0FBRyxHQUFHLEVBQUU7WUFDaEIsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7Z0JBQ3ZCLFlBQVks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QztZQUM5QyxNQUFNLEVBQUUsUUFBUSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQztTQUMvQyxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQWtCRDs7T0FFRztJQUNPLFNBQVM7UUFDakIsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDdkIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsRUFBRSxzQkFBc0IsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDdkYsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM1QixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ08sU0FBUztRQUNqQixJQUFJLENBQUMsYUFBYSxFQUFFLElBQUksRUFBRSxDQUFDO0lBQzdCLENBQUM7SUFtQkQ7O09BRUc7SUFDTyxXQUFXLENBQUMsU0FBd0I7UUFDNUMsV0FBVztJQUNiLENBQUM7SUFFRDs7T0FFRztJQUNPLFdBQVcsQ0FBQyxTQUF3QjtRQUM1QyxXQUFXO0lBQ2IsQ0FBQzsrR0FySm1CLG9CQUFvQjttR0FBcEIsb0JBQW9COzs0RkFBcEIsb0JBQW9CO2tCQUR6QyxTQUFTIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgRGlyZWN0aXZlLFxuICBpbnB1dCxcbiAgdmlld0NoaWxkLFxuICBFbGVtZW50UmVmLFxuICBPbkluaXQsXG4gIE9uRGVzdHJveSxcbiAgaW5qZWN0LFxuICBlZmZlY3QsXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgdGlwcHksIHsgSW5zdGFuY2UgYXMgVGlwcHlJbnN0YW5jZSwgc3RpY2t5IH0gZnJvbSBcInRpcHB5LmpzXCI7XG5pbXBvcnQgeyBFZGl0b3IgfSBmcm9tIFwiQHRpcHRhcC9jb3JlXCI7XG5pbXBvcnQgeyBBdGVFZGl0b3JDb21tYW5kc1NlcnZpY2UgfSBmcm9tIFwiLi4vLi4vLi4vc2VydmljZXMvYXRlLWVkaXRvci1jb21tYW5kcy5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBBdGVJMThuU2VydmljZSB9IGZyb20gXCIuLi8uLi8uLi9zZXJ2aWNlcy9hdGUtaTE4bi5zZXJ2aWNlXCI7XG5cbi8qKlxuICogQmFzZSBhYnN0cmFjdCBjbGFzcyBmb3IgU3ViLUJ1YmJsZSBNZW51cyAoTGluaywgQ29sb3IpLlxuICogVGhlc2UgbWVudXMgYXJlIFwic3ViLW1lbnVzXCIgb2YgdGhlIG1haW4gYnViYmxlIG1lbnUgb3IgdHJpZ2dlcmVkL2FuY2hvcmVkIGJ5IHNwZWNpZmljIFVJIGVsZW1lbnRzLlxuICovXG5ARGlyZWN0aXZlKClcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBBdGVCYXNlU3ViQnViYmxlTWVudSBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGkxOG5TZXJ2aWNlID0gaW5qZWN0KEF0ZUkxOG5TZXJ2aWNlKTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGVkaXRvckNvbW1hbmRzID0gaW5qZWN0KEF0ZUVkaXRvckNvbW1hbmRzU2VydmljZSk7XG5cbiAgLy8gQ29yZSBJbnB1dHNcbiAgZWRpdG9yID0gaW5wdXQucmVxdWlyZWQ8RWRpdG9yPigpO1xuXG4gIC8vIFJlcXVpcmVkIHZpZXdDaGlsZCBmb3IgdGhlIG1lbnUgY29udGFpbmVyXG4gIG1lbnVSZWYgPSB2aWV3Q2hpbGQucmVxdWlyZWQ8RWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD4+KFwibWVudVJlZlwiKTtcblxuICAvLyBJbnRlcm5hbCBTdGF0ZVxuICBwcm90ZWN0ZWQgdGlwcHlJbnN0YW5jZTogVGlwcHlJbnN0YW5jZSB8IG51bGwgPSBudWxsO1xuICBwcm90ZWN0ZWQgdXBkYXRlVGltZW91dDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG5cbiAgLy8gUmVhY3RpdmUgc3RhdGUgYWxpYXMgZm9yIHRlbXBsYXRlc1xuICByZWFkb25seSBzdGF0ZSA9IHRoaXMuZWRpdG9yQ29tbWFuZHMuZWRpdG9yU3RhdGU7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgLy8gUmVhY3RpdmUgZWZmZWN0IGZvciBtZW51IHVwZGF0ZXMgKHJlLXBvc2l0aW9uaW5nKVxuICAgIGVmZmVjdCgoKSA9PiB7XG4gICAgICAvLyBNb25pdG9yIGVkaXRvciBzdGF0ZSBhbmQgc3BlY2lmaWMgc3ViLW1lbnUgc3RhdGVzXG4gICAgICB0aGlzLnN0YXRlKCk7XG4gICAgICB0aGlzLm9uU3RhdGVDaGFuZ2UoKTtcblxuICAgICAgdGhpcy51cGRhdGVNZW51KCk7XG4gICAgfSwgeyBhbGxvd1NpZ25hbFdyaXRlczogdHJ1ZSB9KTtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuaW5pdFRpcHB5KCk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICBpZiAodGhpcy51cGRhdGVUaW1lb3V0KSB7XG4gICAgICBjbGVhclRpbWVvdXQodGhpcy51cGRhdGVUaW1lb3V0KTtcbiAgICB9XG4gICAgaWYgKHRoaXMudGlwcHlJbnN0YW5jZSkge1xuICAgICAgdGhpcy50aXBweUluc3RhbmNlLmRlc3Ryb3koKTtcbiAgICAgIHRoaXMudGlwcHlJbnN0YW5jZSA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemVzIHRoZSBUaXBweSBpbnN0YW5jZSB3aXRoIHN1Yi1tZW51IGRlZmF1bHRzLlxuICAgKi9cbiAgcHJvdGVjdGVkIGluaXRUaXBweSgpIHtcbiAgICBpZiAoIXRoaXMubWVudVJlZigpPy5uYXRpdmVFbGVtZW50KSB7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMuaW5pdFRpcHB5KCksIDUwKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBlZCA9IHRoaXMuZWRpdG9yKCk7XG4gICAgaWYgKHRoaXMudGlwcHlJbnN0YW5jZSkge1xuICAgICAgdGhpcy50aXBweUluc3RhbmNlLmRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICB0aGlzLnRpcHB5SW5zdGFuY2UgPSB0aXBweShkb2N1bWVudC5ib2R5LCB7XG4gICAgICBjb250ZW50OiB0aGlzLm1lbnVSZWYoKS5uYXRpdmVFbGVtZW50LFxuICAgICAgdHJpZ2dlcjogXCJtYW51YWxcIixcbiAgICAgIHBsYWNlbWVudDogXCJib3R0b20tc3RhcnRcIixcbiAgICAgIGFwcGVuZFRvOiAoKSA9PiAoZWQub3B0aW9ucy5lbGVtZW50IGFzIEhUTUxFbGVtZW50KSxcbiAgICAgIGludGVyYWN0aXZlOiB0cnVlLFxuICAgICAgYXJyb3c6IGZhbHNlLFxuICAgICAgb2Zmc2V0OiBbMCwgOF0sXG4gICAgICBoaWRlT25DbGljazogdHJ1ZSxcbiAgICAgIHBsdWdpbnM6IFtzdGlja3ldLFxuICAgICAgc3RpY2t5OiBmYWxzZSxcbiAgICAgIGdldFJlZmVyZW5jZUNsaWVudFJlY3Q6ICgpID0+IHRoaXMuZ2V0U2VsZWN0aW9uUmVjdCgpLFxuICAgICAgcG9wcGVyT3B0aW9uczoge1xuICAgICAgICBtb2RpZmllcnM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiBcInByZXZlbnRPdmVyZmxvd1wiLFxuICAgICAgICAgICAgb3B0aW9uczogeyBib3VuZGFyeTogZWQub3B0aW9ucy5lbGVtZW50LCBwYWRkaW5nOiA4IH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiBcImZsaXBcIixcbiAgICAgICAgICAgIG9wdGlvbnM6IHsgZmFsbGJhY2tQbGFjZW1lbnRzOiBbXCJ0b3Atc3RhcnRcIiwgXCJib3R0b20tZW5kXCIsIFwidG9wLWVuZFwiXSB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgICAgb25TaG93OiBpbnN0YW5jZSA9PiB0aGlzLm9uVGlwcHlTaG93KGluc3RhbmNlKSxcbiAgICAgIG9uSGlkZTogaW5zdGFuY2UgPT4gdGhpcy5vblRpcHB5SGlkZShpbnN0YW5jZSksXG4gICAgfSk7XG5cbiAgICB0aGlzLnVwZGF0ZU1lbnUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb3JlIGxvZ2ljIHRvIGRlY2lkZSB3aGV0aGVyIHRvIHNob3cgb3IgaGlkZSB0aGUgbWVudS5cbiAgICovXG4gIHVwZGF0ZU1lbnUgPSAoKSA9PiB7XG4gICAgaWYgKHRoaXMudXBkYXRlVGltZW91dCkge1xuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMudXBkYXRlVGltZW91dCk7XG4gICAgfVxuICAgIHRoaXMudXBkYXRlVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuc2hvdWxkU2hvdygpKSB7XG4gICAgICAgIHRoaXMuc2hvd1RpcHB5KCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmhpZGVUaXBweSgpO1xuICAgICAgfVxuICAgIH0sIDEwKTtcbiAgfTtcblxuICAvKipcbiAgICogSGVscGVyIHRvIHNob3cgdGhlIFRpcHB5IGluc3RhbmNlIHdpdGggdXBkYXRlZCBwb3NpdGlvbmluZy5cbiAgICovXG4gIHByb3RlY3RlZCBzaG93VGlwcHkoKSB7XG4gICAgaWYgKHRoaXMudGlwcHlJbnN0YW5jZSkge1xuICAgICAgdGhpcy50aXBweUluc3RhbmNlLnNldFByb3BzKHsgZ2V0UmVmZXJlbmNlQ2xpZW50UmVjdDogKCkgPT4gdGhpcy5nZXRTZWxlY3Rpb25SZWN0KCkgfSk7XG4gICAgICB0aGlzLnRpcHB5SW5zdGFuY2Uuc2hvdygpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgdG8gaGlkZSB0aGUgVGlwcHkgaW5zdGFuY2UuXG4gICAqL1xuICBwcm90ZWN0ZWQgaGlkZVRpcHB5KCkge1xuICAgIHRoaXMudGlwcHlJbnN0YW5jZT8uaGlkZSgpO1xuICB9XG5cbiAgLy8gLS0tIEFic3RyYWN0IG1ldGhvZHMgJiBIb29rcyAtLS1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgUmVjdCByZXByZXNlbnRpbmcgdGhlIHRhcmdldCBmb3IgcG9zaXRpb25pbmcgdGhlIG1lbnUuXG4gICAqL1xuICBhYnN0cmFjdCBnZXRTZWxlY3Rpb25SZWN0KCk6IERPTVJlY3Q7XG5cbiAgLyoqXG4gICAqIFJldHVybnMgd2hldGhlciB0aGUgbWVudSBzaG91bGQgYmUgZGlzcGxheWVkIGJhc2VkIG9uIGN1cnJlbnQgc3RhdGUuXG4gICAqL1xuICBhYnN0cmFjdCBzaG91bGRTaG93KCk6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEhvb2sgdG8gYWRkIHJlYWN0aXZlIGRlcGVuZGVuY2llcyB0byB0aGUgdXBkYXRlIGN5Y2xlLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFic3RyYWN0IG9uU3RhdGVDaGFuZ2UoKTogdm9pZDtcblxuICAvKipcbiAgICogT3B0aW9uYWwgaG9vayBjYWxsZWQgd2hlbiBUaXBweSBpcyBhYm91dCB0byBiZSBzaG93bi5cbiAgICovXG4gIHByb3RlY3RlZCBvblRpcHB5U2hvdyhfaW5zdGFuY2U6IFRpcHB5SW5zdGFuY2UpIHtcbiAgICAvKiBlbXB0eSAqL1xuICB9XG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIGhvb2sgY2FsbGVkIHdoZW4gVGlwcHkgaXMgYWJvdXQgdG8gYmUgaGlkZGVuLlxuICAgKi9cbiAgcHJvdGVjdGVkIG9uVGlwcHlIaWRlKF9pbnN0YW5jZTogVGlwcHlJbnN0YW5jZSkge1xuICAgIC8qIGVtcHR5ICovXG4gIH1cbn1cbiJdfQ==
@@ -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", inputs: ["orientation", "size"] }], 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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QUFPO1FBQ0wsSUFBSSxDQUFDLGNBQWMsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUVELE1BQU07UUFDSixVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ2QsSUFBSSxDQUFDLGNBQWMsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDMUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ3BCLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNWLENBQUM7K0dBL01VLDJCQUEyQjttR0FBM0IsMkJBQTJCLHFPQTNMNUI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQThFVCwybURBL0VTLFlBQVksOEJBQUUsV0FBVywrQkFBRSxrQkFBa0IsNkxBQUUscUJBQXFCOzs0RkE0TG5FLDJCQUEyQjtrQkFoTXZDLFNBQVM7K0JBQ0UsdUJBQXVCLGNBQ3JCLElBQUksbUJBQ0MsdUJBQXVCLENBQUMsTUFBTSxXQUN0QyxDQUFDLFlBQVksRUFBRSxXQUFXLEVBQUUsa0JBQWtCLEVBQUUscUJBQXFCLENBQUMsWUFDckU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQThFVCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIEVsZW1lbnRSZWYsXG4gIHNpZ25hbCxcbiAgaW5qZWN0LFxuICBjb21wdXRlZCxcbiAgdmlld0NoaWxkLFxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vblwiO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcbmltcG9ydCB7IEluc3RhbmNlIGFzIFRpcHB5SW5zdGFuY2UgfSBmcm9tIFwidGlwcHkuanNcIjtcbmltcG9ydCB7IEF0ZUNvbG9yUGlja2VyU2VydmljZSB9IGZyb20gXCIuLi8uLi8uLi9zZXJ2aWNlcy9hdGUtY29sb3ItcGlja2VyLnNlcnZpY2VcIjtcbmltcG9ydCB7IEF0ZUJ1dHRvbkNvbXBvbmVudCB9IGZyb20gXCIuLi8uLi91aS9hdGUtYnV0dG9uLmNvbXBvbmVudFwiO1xuaW1wb3J0IHsgQXRlU2VwYXJhdG9yQ29tcG9uZW50IH0gZnJvbSBcIi4uLy4uL3VpL2F0ZS1zZXBhcmF0b3IuY29tcG9uZW50XCI7XG5pbXBvcnQgeyBBdGVCYXNlU3ViQnViYmxlTWVudSB9IGZyb20gXCIuLi9iYXNlL2F0ZS1iYXNlLXN1Yi1idWJibGUtbWVudVwiO1xuXG5jb25zdCBQUkVTRVRfQ09MT1JTID0gW1xuICBcIiMwMDAwMDBcIixcbiAgXCIjNjY2NjY2XCIsXG4gIFwiI0NDQ0NDQ1wiLFxuICBcIiNGRkZGRkZcIixcbiAgXCIjRjQ0MzM2XCIsXG4gIFwiI0ZGOTgwMFwiLFxuICBcIiNGRkVCM0JcIixcbiAgXCIjNENBRjUwXCIsXG4gIFwiIzAwQkNENFwiLFxuICBcIiMyMTk2RjNcIixcbiAgXCIjOUMyN0IwXCIsXG4gIFwiI0U5MUU2M1wiLFxuXTtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiBcImF0ZS1jb2xvci1idWJibGUtbWVudVwiLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgRm9ybXNNb2R1bGUsIEF0ZUJ1dHRvbkNvbXBvbmVudCwgQXRlU2VwYXJhdG9yQ29tcG9uZW50XSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2XG4gICAgICAjbWVudVJlZlxuICAgICAgY2xhc3M9XCJidWJibGUtbWVudSBjb2xvci1idWJibGUtbWVudVwiXG4gICAgICAobW91c2Vkb3duKT1cIm9uTW91c2VEb3duKCRldmVudClcIlxuICAgICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgICAoa2V5ZG93bik9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxuICAgICAgKGtleWRvd24uZXNjYXBlKT1cIm9uQXBwbHkoJGV2ZW50KVwiXG4gICAgICB0YWJpbmRleD1cIi0xXCJcbiAgICAgIHJvbGU9XCJkaWFsb2dcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJjb2xvci1waWNrZXItY29udGFpbmVyXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkcm9wZG93bi1yb3cgcHJlc2V0c1wiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2xvci1ncmlkXCI+XG4gICAgICAgICAgICBAZm9yIChjb2xvciBvZiBwcmVzZXRzOyB0cmFjayBjb2xvcikge1xuICAgICAgICAgICAgICA8YXRlLWJ1dHRvblxuICAgICAgICAgICAgICAgIGNsYXNzPVwiY29sb3Itc3dhdGNoLWJ0blwiXG4gICAgICAgICAgICAgICAgc2l6ZT1cInNtYWxsXCJcbiAgICAgICAgICAgICAgICBbdGl0bGVdPVwiY29sb3JcIlxuICAgICAgICAgICAgICAgIFthY3RpdmVdPVwiaXNDb2xvckFjdGl2ZShjb2xvcilcIlxuICAgICAgICAgICAgICAgIFtiYWNrZ3JvdW5kQ29sb3JdPVwiY29sb3JcIlxuICAgICAgICAgICAgICAgIChidXR0b25DbGljayk9XCJhcHBseUNvbG9yKGNvbG9yLCB0cnVlLCAkZXZlbnQpXCI+PC9hdGUtYnV0dG9uPlxuICAgICAgICAgICAgfVxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwiZHJvcGRvd24tcm93IGNvbnRyb2xzXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImhleC1pbnB1dC13cmFwcGVyXCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImhleC1oYXNoXCI+Izwvc3Bhbj5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAjaGV4SW5wdXRcbiAgICAgICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgICAgICBjbGFzcz1cImhleC1pbnB1dFwiXG4gICAgICAgICAgICAgIFt2YWx1ZV09XCJoZXhWYWx1ZSgpXCJcbiAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJ0KCkuY3VzdG9tQ29sb3JcIlxuICAgICAgICAgICAgICAoaW5wdXQpPVwib25IZXhJbnB1dCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgKGNoYW5nZSk9XCJvbkhleENoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgKGtleWRvd24uZW50ZXIpPVwib25BcHBseSgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgKGZvY3VzKT1cIm9uRm9jdXMoKVwiXG4gICAgICAgICAgICAgIChibHVyKT1cIm9uQmx1cigpXCJcbiAgICAgICAgICAgICAgbWF4bGVuZ3RoPVwiNlwiXG4gICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiMDAwMDAwXCIgLz5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJuYXRpdmUtdHJpZ2dlci13cmFwcGVyXCI+XG4gICAgICAgICAgICA8YXRlLWJ1dHRvblxuICAgICAgICAgICAgICBjbGFzcz1cImJ0bi1uYXRpdmUtcGlja2VyLXRyaWdnZXJcIlxuICAgICAgICAgICAgICBpY29uPVwiY29sb3JpemVcIlxuICAgICAgICAgICAgICBbdGl0bGVdPVwidCgpLmN1c3RvbUNvbG9yXCJcbiAgICAgICAgICAgICAgW2JhY2tncm91bmRDb2xvcl09XCJjdXJyZW50Q29sb3IoKVwiXG4gICAgICAgICAgICAgIChidXR0b25DbGljayk9XCJ0cmlnZ2VyTmF0aXZlUGlja2VyKCRldmVudClcIj48L2F0ZS1idXR0b24+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgI2NvbG9ySW5wdXRcbiAgICAgICAgICAgICAgdHlwZT1cImNvbG9yXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJoaWRkZW4tbmF0aXZlLWlucHV0XCJcbiAgICAgICAgICAgICAgW3ZhbHVlXT1cImN1cnJlbnRDb2xvcigpXCJcbiAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJ0KCkuY3VzdG9tQ29sb3JcIlxuICAgICAgICAgICAgICAoaW5wdXQpPVwib25OYXRpdmVJbnB1dCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgKGNoYW5nZSk9XCJvbk5hdGl2ZUNoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgKGZvY3VzKT1cIm9uRm9jdXMoKVwiXG4gICAgICAgICAgICAgIChibHVyKT1cIm9uQmx1cigpXCIgLz5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxhdGUtYnV0dG9uXG4gICAgICAgICAgICBpY29uPVwiY2hlY2tcIlxuICAgICAgICAgICAgW3RpdGxlXT1cImNvbW1vbigpLmFwcGx5XCJcbiAgICAgICAgICAgIGNvbG9yPVwidmFyKC0tYXRlLXByaW1hcnkpXCJcbiAgICAgICAgICAgIChidXR0b25DbGljayk9XCJvbkFwcGx5KCRldmVudClcIj48L2F0ZS1idXR0b24+XG5cbiAgICAgICAgICA8YXRlLXNlcGFyYXRvciAvPlxuXG4gICAgICAgICAgPGF0ZS1idXR0b25cbiAgICAgICAgICAgIGljb249XCJmb3JtYXRfY29sb3JfcmVzZXRcIlxuICAgICAgICAgICAgW3RpdGxlXT1cInQoKS5jbGVhclwiXG4gICAgICAgICAgICB2YXJpYW50PVwiZGFuZ2VyXCJcbiAgICAgICAgICAgIChidXR0b25DbGljayk9XCJvbkNsZWFyQ29sb3IoJGV2ZW50KVwiPjwvYXRlLWJ1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVzOiBbXG4gICAgYFxuICAgICAgLmNvbG9yLXBpY2tlci1jb250YWluZXIge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgICBnYXA6IDhweDtcbiAgICAgIH1cblxuICAgICAgLmRyb3Bkb3duLXJvdyB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgfVxuXG4gICAgICAuZHJvcGRvd24tcm93LnByZXNldHMge1xuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgICAgIH1cblxuICAgICAgLmRyb3Bkb3duLXJvdy5jb250cm9scyB7XG4gICAgICAgIGdhcDogOHB4O1xuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gICAgICAgIHBhZGRpbmctdG9wOiA0cHg7XG4gICAgICAgIGJvcmRlci10b3A6IDFweCBzb2xpZCB2YXIoLS1hdGUtYm9yZGVyLCAjZTJlOGYwKTtcbiAgICAgIH1cblxuICAgICAgLmNvbG9yLWdyaWQge1xuICAgICAgICBkaXNwbGF5OiBncmlkO1xuICAgICAgICBncmlkLXRlbXBsYXRlLWNvbHVtbnM6IHJlcGVhdCgxMiwgMWZyKTtcbiAgICAgICAgZ2FwOiA0cHg7XG4gICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgfVxuXG4gICAgICA6aG9zdCA6Om5nLWRlZXAgLmNvbG9yLXN3YXRjaC1idG4gLmF0ZS1idXR0b24ge1xuICAgICAgICB3aWR0aDogMTAwJTtcbiAgICAgICAgYXNwZWN0LXJhdGlvOiAxO1xuICAgICAgICBoZWlnaHQ6IGF1dG87XG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDRweDtcbiAgICAgICAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgwLCAwLCAwLCAwLjEpO1xuICAgICAgICBwYWRkaW5nOiAwO1xuICAgICAgfVxuXG4gICAgICA6aG9zdCA6Om5nLWRlZXAgLmNvbG9yLXN3YXRjaC1idG4gLmF0ZS1idXR0b24uaXMtYWN0aXZlIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB2YXIoLS1hdGUtcHJpbWFyeSwgIzNiODJmNik7XG4gICAgICAgIGJveC1zaGFkb3c6IDAgMCAwIDJweCByZ2JhKDU5LCAxMzAsIDI0NiwgMC4zKTtcbiAgICAgIH1cblxuICAgICAgOmhvc3QgOjpuZy1kZWVwIC5idG4tbmF0aXZlLXBpY2tlci10cmlnZ2VyIC5hdGUtYnV0dG9uIHtcbiAgICAgICAgY29sb3I6ICNmZmZmZmY7XG4gICAgICAgIHRleHQtc2hhZG93OiAwIDFweCAycHggcmdiYSgwLCAwLCAwLCAwLjIpO1xuICAgICAgfVxuXG4gICAgICAuZGl2aWRlci12IHtcbiAgICAgICAgd2lkdGg6IDFweDtcbiAgICAgICAgaGVpZ2h0OiAyNHB4O1xuICAgICAgICBiYWNrZ3JvdW5kOiB2YXIoLS1hdGUtYm9yZGVyLCAjZTJlOGYwKTtcbiAgICAgIH1cblxuICAgICAgLmhleC1pbnB1dC13cmFwcGVyIHtcbiAgICAgICAgZmxleDogMTtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgICAgYmFja2dyb3VuZDogdmFyKC0tYXRlLXN1cmZhY2Utc2Vjb25kYXJ5LCAjZjhmYWZjKTtcbiAgICAgICAgYm9yZGVyOiAxcHggc29saWQgdmFyKC0tYXRlLWJvcmRlciwgI2UyZThmMCk7XG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDhweDtcbiAgICAgICAgcGFkZGluZzogMCAxMHB4O1xuICAgICAgICBoZWlnaHQ6IDMycHg7XG4gICAgICAgIHRyYW5zaXRpb246IGJvcmRlci1jb2xvciAxNTBtcyBlYXNlO1xuICAgICAgfVxuXG4gICAgICAuaGV4LWlucHV0LXdyYXBwZXI6Zm9jdXMtd2l0aGluIHtcbiAgICAgICAgYm9yZGVyLWNvbG9yOiB2YXIoLS1hdGUtcHJpbWFyeSwgIzNiODJmNik7XG4gICAgICAgIGJhY2tncm91bmQ6IHZhcigtLWF0ZS1tZW51LWJnLCAjZmZmZmZmKTtcbiAgICAgIH1cblxuICAgICAgLmhleC1oYXNoIHtcbiAgICAgICAgY29sb3I6IHZhcigtLWF0ZS10ZXh0LW11dGVkLCAjOTRhM2I4KTtcbiAgICAgICAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTtcbiAgICAgICAgZm9udC1zaXplOiAwLjg3NXJlbTtcbiAgICAgIH1cblxuICAgICAgLmhleC1pbnB1dCB7XG4gICAgICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50O1xuICAgICAgICBib3JkZXI6IG5vbmU7XG4gICAgICAgIG91dGxpbmU6IG5vbmU7XG4gICAgICAgIGNvbG9yOiB2YXIoLS1hdGUtdGV4dCwgIzFlMjkzYik7XG4gICAgICAgIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7XG4gICAgICAgIGZvbnQtc2l6ZTogMC44NzVyZW07XG4gICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgICBwYWRkaW5nLWxlZnQ6IDRweDtcbiAgICAgIH1cblxuICAgICAgLm5hdGl2ZS10cmlnZ2VyLXdyYXBwZXIge1xuICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gICAgICAgIHdpZHRoOiAzMnB4O1xuICAgICAgICBoZWlnaHQ6IDMycHg7XG4gICAgICB9XG5cbiAgICAgIC5oaWRkZW4tbmF0aXZlLWlucHV0IHtcbiAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgICBpbnNldDogMDtcbiAgICAgICAgb3BhY2l0eTogMDtcbiAgICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICAgIGhlaWdodDogMTAwJTtcbiAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xuICAgICAgfVxuICAgIGAsXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIEF0ZUNvbG9yQnViYmxlTWVudUNvbXBvbmVudCBleHRlbmRzIEF0ZUJhc2VTdWJCdWJibGVNZW51IHtcbiAgcHJpdmF0ZSByZWFkb25seSBjb2xvclBpY2tlclN2YyA9IGluamVjdChBdGVDb2xvclBpY2tlclNlcnZpY2UpO1xuXG4gIHJlYWRvbmx5IHQgPSB0aGlzLmkxOG5TZXJ2aWNlLnRvb2xiYXI7XG4gIHJlYWRvbmx5IGNvbW1vbiA9IHRoaXMuaTE4blNlcnZpY2UuY29tbW9uO1xuICByZWFkb25seSBwcmVzZXRzID0gUFJFU0VUX0NPTE9SUztcblxuICBwcml2YXRlIGNvbG9ySW5wdXRSZWYgPSB2aWV3Q2hpbGQ8RWxlbWVudFJlZjxIVE1MSW5wdXRFbGVtZW50Pj4oXCJjb2xvcklucHV0XCIpO1xuXG4gIC8qKlxuICAgKiBMT0NBTCBNT0RFOiBXZSBsb2NrIHRoZSBtb2RlIHdoZW4gdGhlIG1lbnUgaXMgc2hvd24gdG8gYXZvaWQgcmFjZSBjb25kaXRpb25zXG4gICAqIHdoZXJlIHRoZSBwYXJlbnQgKGJ1YmJsZSBtZW51KSBjbGVhcnMgdGhlIGdsb2JhbCBzaWduYWwgYmVmb3JlIHdlIGFwcGx5IHRoZSBjb2xvci5cbiAgICovXG4gIGFjdGl2ZU1vZGUgPSBzaWduYWw8XCJ0ZXh0XCIgfCBcImhpZ2hsaWdodFwiPihcInRleHRcIik7XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIG9uU3RhdGVDaGFuZ2UoKSB7XG4gICAgdGhpcy5jb2xvclBpY2tlclN2Yy5lZGl0TW9kZSgpO1xuICAgIHRoaXMuY29sb3JQaWNrZXJTdmMubWVudVRyaWdnZXIoKTtcbiAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLmlzSW50ZXJhY3RpbmcoKTtcbiAgfVxuXG4gIG92ZXJyaWRlIHNob3VsZFNob3coKTogYm9vbGVhbiB7XG4gICAgY29uc3QgeyBpc0VkaXRhYmxlIH0gPSB0aGlzLnN0YXRlKCk7XG4gICAgaWYgKCFpc0VkaXRhYmxlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY29sb3JQaWNrZXJTdmMuZWRpdE1vZGUoKSAhPT0gbnVsbCB8fCB0aGlzLmNvbG9yUGlja2VyU3ZjLmlzSW50ZXJhY3RpbmcoKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgb3ZlcnJpZGUgZ2V0U2VsZWN0aW9uUmVjdCgpOiBET01SZWN0IHtcbiAgICBjb25zdCB0cmlnZ2VyID0gdGhpcy5jb2xvclBpY2tlclN2Yy5tZW51VHJpZ2dlcigpO1xuICAgIGNvbnN0IGVkID0gdGhpcy5lZGl0b3IoKTtcbiAgICBpZiAoIWVkKSB7XG4gICAgICByZXR1cm4gbmV3IERPTVJlY3QoMCwgMCwgMCwgMCk7XG4gICAgfVxuXG4gICAgLy8gMS4gSWYgd2UgaGF2ZSBhIHN0YWJsZSB0cmlnZ2VyIGZyb20gc2VydmljZSAodG9vbGJhciBvciBwYXJlbnQgbWVudSksIGFuY2hvciB0byBpdFxuICAgIGlmICh0cmlnZ2VyKSB7XG4gICAgICBjb25zdCByZWN0ID0gdHJpZ2dlci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIC8vIE9ubHkgdXNlIGlmIGl0J3Mgc3RpbGwgdmlzaWJsZS9pbiBET00gKHdpZHRoID4gMClcbiAgICAgIGlmIChyZWN0LndpZHRoID4gMCkge1xuICAgICAgICByZXR1cm4gcmVjdDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyAyLiBPdGhlcndpc2UgKGJ1YmJsZSBtZW51IC8gcmVsYXkpLCBhbmNob3IgdG8gdGV4dCBzZWxlY3Rpb25cbiAgICBjb25zdCB7IGZyb20gfSA9IGVkLnN0YXRlLnNlbGVjdGlvbjtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IG5vZGUgfSA9IGVkLnZpZXcuZG9tQXRQb3MoZnJvbSk7XG4gICAgICBjb25zdCBlbGVtZW50ID0gbm9kZSBpbnN0YW5jZW9mIEVsZW1lbnQgPyBub2RlIDogbm9kZS5wYXJlbnRFbGVtZW50O1xuICAgICAgY29uc3QgY29sb3JFbGVtZW50ID0gZWxlbWVudD8uY2xvc2VzdCgnW3N0eWxlKj1cImNvbG9yXCJdLCBbc3R5bGUqPVwiYmFja2dyb3VuZFwiXSwgbWFyaycpO1xuICAgICAgaWYgKGNvbG9yRWxlbWVudCkge1xuICAgICAgICByZXR1cm4gY29sb3JFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKF9lKSB7XG4gICAgICAvKiBpZ25vcmUgKi9cbiAgICB9XG5cbiAgICAvLyBVc2UgbmF0aXZlIHNlbGVjdGlvbiBmb3IgbXVsdGktbGluZSBhY2N1cmFjeVxuICAgIGNvbnN0IHNlbGVjdGlvbiA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICBpZiAoc2VsZWN0aW9uICYmIHNlbGVjdGlvbi5yYW5nZUNvdW50ID4gMCkge1xuICAgICAgY29uc3QgcmFuZ2UgPSBzZWxlY3Rpb24uZ2V0UmFuZ2VBdCgwKTtcbiAgICAgIGNvbnN0IHJlY3QgPSByYW5nZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIGlmIChyZWN0LndpZHRoID4gMCAmJiByZWN0LmhlaWdodCA+IDApIHtcbiAgICAgICAgcmV0dXJuIHJlY3Q7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRmluYWwgZmFsbGJhY2sgdG8gY29vcmRpbmF0ZXMgYXQgY3Vyc29yXG4gICAgY29uc3QgeyB0b3AsIGJvdHRvbSwgbGVmdCwgcmlnaHQgfSA9IGVkLnZpZXcuY29vcmRzQXRQb3MoZnJvbSk7XG4gICAgcmV0dXJuIG5ldyBET01SZWN0KGxlZnQsIHRvcCwgcmlnaHQgLSBsZWZ0LCBib3R0b20gLSB0b3ApO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIG9uVGlwcHlTaG93KF9pbnN0YW5jZTogVGlwcHlJbnN0YW5jZSkge1xuICAgIC8vIDEuIExvY2sgdGhlIG1vZGUgaW1tZWRpYXRlbHkgdG8gYmUgaW1tdW5lIHRvIGV4dGVybmFsIHNpZ25hbCBjaGFuZ2VzXG4gICAgY29uc3QgY3VycmVudE1vZGUgPSB0aGlzLmNvbG9yUGlja2VyU3ZjLmVkaXRNb2RlKCkgfHwgXCJ0ZXh0XCI7XG4gICAgdGhpcy5hY3RpdmVNb2RlLnNldChjdXJyZW50TW9kZSk7XG5cbiAgICAvLyAyLiBDYXB0dXJlIHNlbGVjdGlvbiBmb3IgdGhlIGNvbW1hbmQgZmFsbGJhY2tcbiAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLmNhcHR1cmVTZWxlY3Rpb24odGhpcy5lZGl0b3IoKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgb25UaXBweUhpZGUoX2luc3RhbmNlOiBUaXBweUluc3RhbmNlKSB7XG4gICAgLy8gQ2xlYXIgdHJpZ2dlciBvbmx5IEFGVEVSIHRoZSBtZW51IGlzIGhpZGRlbiB0byBtYWludGFpbiBhbmNob3Igc3RhYmlsaXR5IGR1cmluZyBhbmltYXRpb25cbiAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLmRvbmUoKTtcbiAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLmNsb3NlKCk7XG4gIH1cblxuICByZWFkb25seSBjdXJyZW50Q29sb3IgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgbWFya3MgPSB0aGlzLnN0YXRlKCkubWFya3M7XG4gICAgY29uc3QgY29sb3IgPSB0aGlzLmFjdGl2ZU1vZGUoKSA9PT0gXCJ0ZXh0XCIgPyBtYXJrcy5jb21wdXRlZENvbG9yIDogbWFya3MuY29tcHV0ZWRCYWNrZ3JvdW5kO1xuICAgIHJldHVybiBjb2xvciB8fCAodGhpcy5hY3RpdmVNb2RlKCkgPT09IFwidGV4dFwiID8gXCIjMDAwMDAwXCIgOiBcIiNmZmZmMDBcIik7XG4gIH0pO1xuXG4gIHJlYWRvbmx5IGhleFZhbHVlID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IGNvbG9yID0gdGhpcy5jdXJyZW50Q29sb3IoKTtcbiAgICByZXR1cm4gY29sb3IucmVwbGFjZShcIiNcIiwgXCJcIikudG9VcHBlckNhc2UoKTtcbiAgfSk7XG5cbiAgaXNDb2xvckFjdGl2ZShjb2xvcjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuY29sb3JQaWNrZXJTdmMubm9ybWFsaXplQ29sb3IodGhpcy5jdXJyZW50Q29sb3IoKSkgPT09XG4gICAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLm5vcm1hbGl6ZUNvbG9yKGNvbG9yKVxuICAgICk7XG4gIH1cblxuICBhcHBseUNvbG9yKGNvbG9yOiBzdHJpbmcsIGFkZFRvSGlzdG9yeSA9IHRydWUsIGV2ZW50PzogRXZlbnQpIHtcbiAgICBpZiAoZXZlbnQpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9XG5cbiAgICBjb25zdCBlZGl0b3IgPSB0aGlzLmVkaXRvcigpO1xuICAgIC8vIFVzZSBvdXIgTE9DS0VEIG1vZGUgaW5zdGVhZCBvZiB0aGUgZ2xvYmFsIHNpZ25hbFxuICAgIC8vIERldGVybWluZSBpZiB3ZSBzaG91bGQgZm9jdXMgYmFjayB0byB0aGUgZWRpdG9yLlxuICAgIGNvbnN0IHNob3VsZEZvY3VzID0gIXRoaXMuY29sb3JQaWNrZXJTdmMuaXNJbnRlcmFjdGluZygpO1xuXG4gICAgaWYgKHRoaXMuYWN0aXZlTW9kZSgpID09PSBcInRleHRcIikge1xuICAgICAgdGhpcy5jb2xvclBpY2tlclN2Yy5hcHBseUNvbG9yKGVkaXRvciwgY29sb3IsIGFkZFRvSGlzdG9yeSwgc2hvdWxkRm9jdXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLmFwcGx5SGlnaGxpZ2h0KGVkaXRvciwgY29sb3IsIGFkZFRvSGlzdG9yeSwgc2hvdWxkRm9jdXMpO1xuICAgIH1cbiAgfVxuXG4gIG9uQXBwbHkoZXZlbnQ/OiBFdmVudCkge1xuICAgIGlmIChldmVudCkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIH1cbiAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLmNsb3NlKCk7XG4gIH1cblxuICBvbkhleElucHV0KGV2ZW50OiBFdmVudCkge1xuICAgIGNvbnN0IGlucHV0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgbGV0IHZhbHVlID0gaW5wdXQudmFsdWUudHJpbSgpO1xuICAgIGlmICghdmFsdWUuc3RhcnRzV2l0aChcIiNcIikpIHtcbiAgICAgIHZhbHVlID0gXCIjXCIgKyB2YWx1ZTtcbiAgICB9XG4gICAgaWYgKC9eIz9bMC05QS1GYS1mXXszLDZ9JC8udGVzdCh2YWx1ZSkpIHtcbiAgICAgIHRoaXMuYXBwbHlDb2xvcih2YWx1ZSwgZmFsc2UpO1xuICAgIH1cbiAgfVxuXG4gIG9uSGV4Q2hhbmdlKGV2ZW50OiBFdmVudCkge1xuICAgIGNvbnN0IGlucHV0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgbGV0IHZhbHVlID0gaW5wdXQudmFsdWUudHJpbSgpO1xuICAgIGlmICghdmFsdWUuc3RhcnRzV2l0aChcIiNcIikpIHtcbiAgICAgIHZhbHVlID0gXCIjXCIgKyB2YWx1ZTtcbiAgICB9XG4gICAgaWYgKC9eIz9bMC05QS1GYS1mXXszLDZ9JC8udGVzdCh2YWx1ZSkpIHtcbiAgICAgIHRoaXMuYXBwbHlDb2xvcih2YWx1ZSwgdHJ1ZSwgZXZlbnQpO1xuICAgIH1cbiAgfVxuXG4gIHRyaWdnZXJOYXRpdmVQaWNrZXIoZXZlbnQ/OiBFdmVudCkge1xuICAgIGlmIChldmVudCkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIH1cbiAgICB0aGlzLmNvbG9ySW5wdXRSZWYoKT8ubmF0aXZlRWxlbWVudC5jbGljaygpO1xuICB9XG5cbiAgb25OYXRpdmVJbnB1dChldmVudDogRXZlbnQpIHtcbiAgICB0aGlzLmFwcGx5Q29sb3IoKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZSwgZmFsc2UpO1xuICB9XG5cbiAgb25OYXRpdmVDaGFuZ2UoZXZlbnQ6IEV2ZW50KSB7XG4gICAgdGhpcy5hcHBseUNvbG9yKChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkudmFsdWUsIHRydWUsIGV2ZW50KTtcbiAgfVxuXG4gIG9uQ2xlYXJDb2xvcihldmVudD86IEV2ZW50KSB7XG4gICAgaWYgKGV2ZW50KSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfVxuXG4gICAgY29uc3QgZWRpdG9yID0gdGhpcy5lZGl0b3IoKTtcbiAgICBpZiAodGhpcy5hY3RpdmVNb2RlKCkgPT09IFwidGV4dFwiKSB7XG4gICAgICB0aGlzLmNvbG9yUGlja2VyU3ZjLnVuc2V0Q29sb3IoZWRpdG9yKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5jb2xvclBpY2tlclN2Yy51bnNldEhpZ2hsaWdodChlZGl0b3IpO1xuICAgIH1cbiAgfVxuXG4gIG9uTW91c2VEb3duKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgY29uc3QgdGFyZ2V0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgIGlmICh0YXJnZXQudGFnTmFtZSAhPT0gXCJJTlBVVFwiKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbiAgfVxuXG4gIG9uRm9jdXMoKSB7XG4gICAgdGhpcy5jb2xvclBpY2tlclN2Yy5zZXRJbnRlcmFjdGluZyh0cnVlKTtcbiAgfVxuXG4gIG9uQmx1cigpIHtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMuY29sb3JQaWNrZXJTdmMuc2V0SW50ZXJhY3RpbmcoZmFsc2UpO1xuICAgICAgdGhpcy51cGRhdGVNZW51KCk7XG4gICAgfSwgMTUwKTtcbiAgfVxufVxuIl19