@memberjunction/ng-artifacts 5.11.0 → 5.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/artifacts.module.d.ts +2 -1
- package/dist/lib/artifacts.module.d.ts.map +1 -1
- package/dist/lib/artifacts.module.js +7 -3
- package/dist/lib/artifacts.module.js.map +1 -1
- package/dist/lib/components/artifact-message-card.component.js +2 -2
- package/dist/lib/components/artifact-message-card.component.js.map +1 -1
- package/dist/lib/components/artifact-viewer-panel.component.js +2 -2
- package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts +2 -0
- package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/component-artifact-viewer.component.js +43 -14
- package/dist/lib/components/plugins/component-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.d.ts +75 -0
- package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.d.ts.map +1 -0
- package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js +569 -0
- package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js.map +1 -0
- package/dist/lib/components/plugins/data-artifact-viewer.component.d.ts +10 -0
- package/dist/lib/components/plugins/data-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/data-artifact-viewer.component.js +44 -11
- package/dist/lib/components/plugins/data-artifact-viewer.component.js.map +1 -1
- package/dist/lib/components/plugins/data-requirements-viewer/data-requirements-viewer.component.js +2 -2
- package/dist/lib/components/plugins/json-artifact-viewer.component.d.ts.map +1 -1
- package/dist/lib/components/plugins/json-artifact-viewer.component.js +3 -3
- package/dist/lib/components/plugins/json-artifact-viewer.component.js.map +1 -1
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +1 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +15 -14
package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js
ADDED
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
import { Component, Input, Output, EventEmitter, ChangeDetectorRef, inject } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { FormsModule } from '@angular/forms';
|
|
4
|
+
import { Metadata } from '@memberjunction/core';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
import * as i1 from "@angular/forms";
|
|
7
|
+
const _c0 = () => [1, 2, 3, 4, 5];
|
|
8
|
+
const _forTrack0 = ($index, $item) => $item.spec.name;
|
|
9
|
+
function ComponentFeedbackPanelComponent_Conditional_15_For_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
10
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
11
|
+
i0.ɵɵelementStart(0, "i", 24);
|
|
12
|
+
i0.ɵɵlistener("click", function ComponentFeedbackPanelComponent_Conditional_15_For_2_Conditional_1_Template_i_click_0_listener($event) { i0.ɵɵrestoreView(_r4); const item_r2 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.ToggleNode(item_r2.spec, $event)); });
|
|
13
|
+
i0.ɵɵelementEnd();
|
|
14
|
+
} if (rf & 2) {
|
|
15
|
+
const item_r2 = i0.ɵɵnextContext().$implicit;
|
|
16
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
17
|
+
i0.ɵɵclassProp("fa-chevron-right", !ctx_r2.IsNodeExpanded(item_r2.spec))("fa-chevron-down", ctx_r2.IsNodeExpanded(item_r2.spec));
|
|
18
|
+
} }
|
|
19
|
+
function ComponentFeedbackPanelComponent_Conditional_15_For_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
20
|
+
i0.ɵɵelement(0, "span", 19);
|
|
21
|
+
} }
|
|
22
|
+
function ComponentFeedbackPanelComponent_Conditional_15_For_2_Conditional_7_Template(rf, ctx) { if (rf & 1) {
|
|
23
|
+
i0.ɵɵelementStart(0, "span", 23);
|
|
24
|
+
i0.ɵɵtext(1, "Registry");
|
|
25
|
+
i0.ɵɵelementEnd();
|
|
26
|
+
} }
|
|
27
|
+
function ComponentFeedbackPanelComponent_Conditional_15_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
28
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
29
|
+
i0.ɵɵelementStart(0, "div", 17);
|
|
30
|
+
i0.ɵɵlistener("click", function ComponentFeedbackPanelComponent_Conditional_15_For_2_Template_div_click_0_listener() { const item_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.SelectComponent(item_r2.spec)); })("mouseenter", function ComponentFeedbackPanelComponent_Conditional_15_For_2_Template_div_mouseenter_0_listener() { const item_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.HoverTreeItem(item_r2.spec)); })("mouseleave", function ComponentFeedbackPanelComponent_Conditional_15_For_2_Template_div_mouseleave_0_listener() { i0.ɵɵrestoreView(_r1); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.ClearTreeItemHover()); });
|
|
31
|
+
i0.ɵɵconditionalCreate(1, ComponentFeedbackPanelComponent_Conditional_15_For_2_Conditional_1_Template, 1, 4, "i", 18)(2, ComponentFeedbackPanelComponent_Conditional_15_For_2_Conditional_2_Template, 1, 0, "span", 19);
|
|
32
|
+
i0.ɵɵelement(3, "i", 20);
|
|
33
|
+
i0.ɵɵelementStart(4, "div", 21)(5, "span", 22);
|
|
34
|
+
i0.ɵɵtext(6);
|
|
35
|
+
i0.ɵɵelementEnd();
|
|
36
|
+
i0.ɵɵconditionalCreate(7, ComponentFeedbackPanelComponent_Conditional_15_For_2_Conditional_7_Template, 2, 0, "span", 23);
|
|
37
|
+
i0.ɵɵelementEnd()();
|
|
38
|
+
} if (rf & 2) {
|
|
39
|
+
const item_r2 = ctx.$implicit;
|
|
40
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
41
|
+
i0.ɵɵstyleProp("padding-left", ctx_r2.GetIndentation(item_r2.depth));
|
|
42
|
+
i0.ɵɵclassProp("selected", ctx_r2.IsSelected(item_r2.spec));
|
|
43
|
+
i0.ɵɵadvance();
|
|
44
|
+
i0.ɵɵconditional(item_r2.hasChildren ? 1 : 2);
|
|
45
|
+
i0.ɵɵadvance(5);
|
|
46
|
+
i0.ɵɵtextInterpolate(item_r2.spec.title || item_r2.spec.name);
|
|
47
|
+
i0.ɵɵadvance();
|
|
48
|
+
i0.ɵɵconditional(item_r2.spec.location === "registry" ? 7 : -1);
|
|
49
|
+
} }
|
|
50
|
+
function ComponentFeedbackPanelComponent_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
51
|
+
i0.ɵɵelementStart(0, "div", 11);
|
|
52
|
+
i0.ɵɵrepeaterCreate(1, ComponentFeedbackPanelComponent_Conditional_15_For_2_Template, 8, 7, "div", 16, _forTrack0);
|
|
53
|
+
i0.ɵɵelementEnd();
|
|
54
|
+
} if (rf & 2) {
|
|
55
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
56
|
+
i0.ɵɵadvance();
|
|
57
|
+
i0.ɵɵrepeater(ctx_r2.GetTreeItems());
|
|
58
|
+
} }
|
|
59
|
+
function ComponentFeedbackPanelComponent_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
60
|
+
i0.ɵɵelementStart(0, "div", 12);
|
|
61
|
+
i0.ɵɵelement(1, "i", 25);
|
|
62
|
+
i0.ɵɵelementStart(2, "span");
|
|
63
|
+
i0.ɵɵtext(3, "No component hierarchy available");
|
|
64
|
+
i0.ɵɵelementEnd()();
|
|
65
|
+
} }
|
|
66
|
+
function ComponentFeedbackPanelComponent_Conditional_18_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
67
|
+
i0.ɵɵelementStart(0, "p", 27);
|
|
68
|
+
i0.ɵɵtext(1);
|
|
69
|
+
i0.ɵɵelementEnd();
|
|
70
|
+
} if (rf & 2) {
|
|
71
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
72
|
+
i0.ɵɵadvance();
|
|
73
|
+
i0.ɵɵtextInterpolate(ctx_r2.SelectedSpec.description);
|
|
74
|
+
} }
|
|
75
|
+
function ComponentFeedbackPanelComponent_Conditional_18_For_11_Template(rf, ctx) { if (rf & 1) {
|
|
76
|
+
const _r6 = i0.ɵɵgetCurrentView();
|
|
77
|
+
i0.ɵɵelementStart(0, "i", 43);
|
|
78
|
+
i0.ɵɵlistener("click", function ComponentFeedbackPanelComponent_Conditional_18_For_11_Template_i_click_0_listener() { const star_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.SetRating(star_r7)); })("mouseenter", function ComponentFeedbackPanelComponent_Conditional_18_For_11_Template_i_mouseenter_0_listener() { const star_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.SetHoverRating(star_r7)); })("mouseleave", function ComponentFeedbackPanelComponent_Conditional_18_For_11_Template_i_mouseleave_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.ClearHoverRating()); });
|
|
79
|
+
i0.ɵɵelementEnd();
|
|
80
|
+
} if (rf & 2) {
|
|
81
|
+
const star_r7 = ctx.$implicit;
|
|
82
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
83
|
+
i0.ɵɵclassProp("fa-solid", ctx_r2.IsStarFilled(star_r7))("fa-regular", !ctx_r2.IsStarFilled(star_r7))("fa-star", true);
|
|
84
|
+
} }
|
|
85
|
+
function ComponentFeedbackPanelComponent_Conditional_18_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
86
|
+
i0.ɵɵelementStart(0, "span", 32);
|
|
87
|
+
i0.ɵɵtext(1);
|
|
88
|
+
i0.ɵɵelementEnd();
|
|
89
|
+
} if (rf & 2) {
|
|
90
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
91
|
+
i0.ɵɵadvance();
|
|
92
|
+
i0.ɵɵtextInterpolate1("", ctx_r2.StarRating, " out of 5 stars");
|
|
93
|
+
} }
|
|
94
|
+
function ComponentFeedbackPanelComponent_Conditional_18_Conditional_13_Template(rf, ctx) { if (rf & 1) {
|
|
95
|
+
i0.ɵɵelementStart(0, "span", 33);
|
|
96
|
+
i0.ɵɵtext(1, "Click to rate");
|
|
97
|
+
i0.ɵɵelementEnd();
|
|
98
|
+
} }
|
|
99
|
+
function ComponentFeedbackPanelComponent_Conditional_18_Conditional_21_Template(rf, ctx) { if (rf & 1) {
|
|
100
|
+
i0.ɵɵelementStart(0, "span", 38);
|
|
101
|
+
i0.ɵɵtext(1);
|
|
102
|
+
i0.ɵɵelementEnd();
|
|
103
|
+
} if (rf & 2) {
|
|
104
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
105
|
+
i0.ɵɵadvance();
|
|
106
|
+
i0.ɵɵtextInterpolate1("", ctx_r2.FeedbackComments.length, "/1000");
|
|
107
|
+
} }
|
|
108
|
+
function ComponentFeedbackPanelComponent_Conditional_18_Conditional_24_Template(rf, ctx) { if (rf & 1) {
|
|
109
|
+
i0.ɵɵelement(0, "i", 44);
|
|
110
|
+
i0.ɵɵelementStart(1, "span");
|
|
111
|
+
i0.ɵɵtext(2, "Submitting...");
|
|
112
|
+
i0.ɵɵelementEnd();
|
|
113
|
+
} }
|
|
114
|
+
function ComponentFeedbackPanelComponent_Conditional_18_Conditional_25_Template(rf, ctx) { if (rf & 1) {
|
|
115
|
+
i0.ɵɵelement(0, "i", 45);
|
|
116
|
+
i0.ɵɵelementStart(1, "span");
|
|
117
|
+
i0.ɵɵtext(2, "Submit Feedback");
|
|
118
|
+
i0.ɵɵelementEnd();
|
|
119
|
+
} }
|
|
120
|
+
function ComponentFeedbackPanelComponent_Conditional_18_Conditional_26_Template(rf, ctx) { if (rf & 1) {
|
|
121
|
+
i0.ɵɵelementStart(0, "div", 41);
|
|
122
|
+
i0.ɵɵelement(1, "i", 46);
|
|
123
|
+
i0.ɵɵelementStart(2, "span");
|
|
124
|
+
i0.ɵɵtext(3, "Feedback submitted successfully!");
|
|
125
|
+
i0.ɵɵelementEnd()();
|
|
126
|
+
} }
|
|
127
|
+
function ComponentFeedbackPanelComponent_Conditional_18_Conditional_27_Template(rf, ctx) { if (rf & 1) {
|
|
128
|
+
i0.ɵɵelementStart(0, "div", 42);
|
|
129
|
+
i0.ɵɵelement(1, "i", 47);
|
|
130
|
+
i0.ɵɵelementStart(2, "span");
|
|
131
|
+
i0.ɵɵtext(3);
|
|
132
|
+
i0.ɵɵelementEnd()();
|
|
133
|
+
} if (rf & 2) {
|
|
134
|
+
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
135
|
+
i0.ɵɵadvance(3);
|
|
136
|
+
i0.ɵɵtextInterpolate(ctx_r2.SubmitError);
|
|
137
|
+
} }
|
|
138
|
+
function ComponentFeedbackPanelComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
139
|
+
const _r5 = i0.ɵɵgetCurrentView();
|
|
140
|
+
i0.ɵɵelementStart(0, "div", 14)(1, "div", 9);
|
|
141
|
+
i0.ɵɵelement(2, "i", 26);
|
|
142
|
+
i0.ɵɵelementStart(3, "span");
|
|
143
|
+
i0.ɵɵtext(4);
|
|
144
|
+
i0.ɵɵelementEnd()();
|
|
145
|
+
i0.ɵɵconditionalCreate(5, ComponentFeedbackPanelComponent_Conditional_18_Conditional_5_Template, 2, 1, "p", 27);
|
|
146
|
+
i0.ɵɵelementStart(6, "div", 28)(7, "label", 29);
|
|
147
|
+
i0.ɵɵtext(8, "Your Rating");
|
|
148
|
+
i0.ɵɵelementEnd();
|
|
149
|
+
i0.ɵɵelementStart(9, "div", 30);
|
|
150
|
+
i0.ɵɵrepeaterCreate(10, ComponentFeedbackPanelComponent_Conditional_18_For_11_Template, 1, 6, "i", 31, i0.ɵɵrepeaterTrackByIdentity);
|
|
151
|
+
i0.ɵɵelementEnd();
|
|
152
|
+
i0.ɵɵconditionalCreate(12, ComponentFeedbackPanelComponent_Conditional_18_Conditional_12_Template, 2, 1, "span", 32)(13, ComponentFeedbackPanelComponent_Conditional_18_Conditional_13_Template, 2, 0, "span", 33);
|
|
153
|
+
i0.ɵɵelementEnd();
|
|
154
|
+
i0.ɵɵelementStart(14, "div", 34)(15, "label", 35);
|
|
155
|
+
i0.ɵɵtext(16, " Comments ");
|
|
156
|
+
i0.ɵɵelementStart(17, "span", 36);
|
|
157
|
+
i0.ɵɵtext(18, "(optional)");
|
|
158
|
+
i0.ɵɵelementEnd()();
|
|
159
|
+
i0.ɵɵelementStart(19, "textarea", 37);
|
|
160
|
+
i0.ɵɵtwoWayListener("ngModelChange", function ComponentFeedbackPanelComponent_Conditional_18_Template_textarea_ngModelChange_19_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r2.FeedbackComments, $event) || (ctx_r2.FeedbackComments = $event); return i0.ɵɵresetView($event); });
|
|
161
|
+
i0.ɵɵtext(20, " ");
|
|
162
|
+
i0.ɵɵelementEnd();
|
|
163
|
+
i0.ɵɵconditionalCreate(21, ComponentFeedbackPanelComponent_Conditional_18_Conditional_21_Template, 2, 1, "span", 38);
|
|
164
|
+
i0.ɵɵelementEnd();
|
|
165
|
+
i0.ɵɵelementStart(22, "div", 39)(23, "button", 40);
|
|
166
|
+
i0.ɵɵlistener("click", function ComponentFeedbackPanelComponent_Conditional_18_Template_button_click_23_listener() { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.SubmitFeedback()); });
|
|
167
|
+
i0.ɵɵconditionalCreate(24, ComponentFeedbackPanelComponent_Conditional_18_Conditional_24_Template, 3, 0)(25, ComponentFeedbackPanelComponent_Conditional_18_Conditional_25_Template, 3, 0);
|
|
168
|
+
i0.ɵɵelementEnd()();
|
|
169
|
+
i0.ɵɵconditionalCreate(26, ComponentFeedbackPanelComponent_Conditional_18_Conditional_26_Template, 4, 0, "div", 41);
|
|
170
|
+
i0.ɵɵconditionalCreate(27, ComponentFeedbackPanelComponent_Conditional_18_Conditional_27_Template, 4, 1, "div", 42);
|
|
171
|
+
i0.ɵɵelementEnd();
|
|
172
|
+
} if (rf & 2) {
|
|
173
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
174
|
+
i0.ɵɵadvance(4);
|
|
175
|
+
i0.ɵɵtextInterpolate1("Rate: ", ctx_r2.SelectedSpec.title || ctx_r2.SelectedSpec.name);
|
|
176
|
+
i0.ɵɵadvance();
|
|
177
|
+
i0.ɵɵconditional(ctx_r2.SelectedSpec.description ? 5 : -1);
|
|
178
|
+
i0.ɵɵadvance(5);
|
|
179
|
+
i0.ɵɵrepeater(i0.ɵɵpureFunction0(9, _c0));
|
|
180
|
+
i0.ɵɵadvance(2);
|
|
181
|
+
i0.ɵɵconditional(ctx_r2.StarRating > 0 ? 12 : 13);
|
|
182
|
+
i0.ɵɵadvance(7);
|
|
183
|
+
i0.ɵɵtwoWayProperty("ngModel", ctx_r2.FeedbackComments);
|
|
184
|
+
i0.ɵɵadvance(2);
|
|
185
|
+
i0.ɵɵconditional(ctx_r2.FeedbackComments.length > 0 ? 21 : -1);
|
|
186
|
+
i0.ɵɵadvance(2);
|
|
187
|
+
i0.ɵɵproperty("disabled", !ctx_r2.CanSubmit());
|
|
188
|
+
i0.ɵɵadvance();
|
|
189
|
+
i0.ɵɵconditional(ctx_r2.IsSubmitting ? 24 : 25);
|
|
190
|
+
i0.ɵɵadvance(2);
|
|
191
|
+
i0.ɵɵconditional(ctx_r2.SubmitSuccess ? 26 : -1);
|
|
192
|
+
i0.ɵɵadvance();
|
|
193
|
+
i0.ɵɵconditional(ctx_r2.SubmitError ? 27 : -1);
|
|
194
|
+
} }
|
|
195
|
+
function ComponentFeedbackPanelComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
196
|
+
i0.ɵɵelementStart(0, "div", 15);
|
|
197
|
+
i0.ɵɵelement(1, "i", 48);
|
|
198
|
+
i0.ɵɵelementStart(2, "p");
|
|
199
|
+
i0.ɵɵtext(3, "Select a component from the tree to provide feedback");
|
|
200
|
+
i0.ɵɵelementEnd()();
|
|
201
|
+
} }
|
|
202
|
+
/**
|
|
203
|
+
* Component feedback panel that displays component hierarchy tree
|
|
204
|
+
* and allows users to select components and provide star ratings with comments.
|
|
205
|
+
* Registry-agnostic: works with any component registry (Skip, MJ Central, etc.)
|
|
206
|
+
*/
|
|
207
|
+
export class ComponentFeedbackPanelComponent {
|
|
208
|
+
ComponentSpec = null;
|
|
209
|
+
ReactContainerElement = null;
|
|
210
|
+
ConversationId = null;
|
|
211
|
+
ConversationDetailId = null;
|
|
212
|
+
Closed = new EventEmitter();
|
|
213
|
+
// Feedback form state
|
|
214
|
+
SelectedSpec = null;
|
|
215
|
+
StarRating = 0;
|
|
216
|
+
HoverRating = 0;
|
|
217
|
+
FeedbackComments = '';
|
|
218
|
+
IsSubmitting = false;
|
|
219
|
+
SubmitSuccess = false;
|
|
220
|
+
SubmitError = '';
|
|
221
|
+
// Tree state
|
|
222
|
+
ExpandedNodes = new Set();
|
|
223
|
+
// Highlight overlays
|
|
224
|
+
highlightOverlay = null;
|
|
225
|
+
hoverOverlay = null;
|
|
226
|
+
resizeObserver = null;
|
|
227
|
+
containerClickHandler = null;
|
|
228
|
+
cdr = inject(ChangeDetectorRef);
|
|
229
|
+
// --- Tree Methods ---
|
|
230
|
+
GetTreeItems() {
|
|
231
|
+
if (!this.ComponentSpec)
|
|
232
|
+
return [];
|
|
233
|
+
if (!this.ExpandedNodes.has(this.ComponentSpec.name)) {
|
|
234
|
+
this.ExpandedNodes.add(this.ComponentSpec.name);
|
|
235
|
+
}
|
|
236
|
+
return this.buildTree(this.ComponentSpec, 0);
|
|
237
|
+
}
|
|
238
|
+
buildTree(spec, depth) {
|
|
239
|
+
const items = [{
|
|
240
|
+
spec,
|
|
241
|
+
depth,
|
|
242
|
+
hasChildren: !!(spec.dependencies && spec.dependencies.length > 0)
|
|
243
|
+
}];
|
|
244
|
+
if (this.ExpandedNodes.has(spec.name) && spec.dependencies) {
|
|
245
|
+
for (const child of spec.dependencies) {
|
|
246
|
+
items.push(...this.buildTree(child, depth + 1));
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return items;
|
|
250
|
+
}
|
|
251
|
+
ToggleNode(spec, event) {
|
|
252
|
+
event.stopPropagation();
|
|
253
|
+
if (this.ExpandedNodes.has(spec.name)) {
|
|
254
|
+
this.ExpandedNodes.delete(spec.name);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
this.ExpandedNodes.add(spec.name);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
IsNodeExpanded(spec) {
|
|
261
|
+
return this.ExpandedNodes.has(spec.name);
|
|
262
|
+
}
|
|
263
|
+
SelectComponent(spec) {
|
|
264
|
+
this.SelectedSpec = spec;
|
|
265
|
+
this.ResetForm();
|
|
266
|
+
this.HighlightComponent(spec.name);
|
|
267
|
+
}
|
|
268
|
+
IsSelected(spec) {
|
|
269
|
+
return this.SelectedSpec?.name === spec.name;
|
|
270
|
+
}
|
|
271
|
+
GetIndentation(depth) {
|
|
272
|
+
return `${depth * 20}px`;
|
|
273
|
+
}
|
|
274
|
+
// --- Star Rating ---
|
|
275
|
+
SetRating(stars) {
|
|
276
|
+
this.StarRating = stars;
|
|
277
|
+
}
|
|
278
|
+
SetHoverRating(stars) {
|
|
279
|
+
this.HoverRating = stars;
|
|
280
|
+
}
|
|
281
|
+
ClearHoverRating() {
|
|
282
|
+
this.HoverRating = 0;
|
|
283
|
+
}
|
|
284
|
+
GetDisplayRating() {
|
|
285
|
+
return this.HoverRating || this.StarRating;
|
|
286
|
+
}
|
|
287
|
+
IsStarFilled(index) {
|
|
288
|
+
return index <= this.GetDisplayRating();
|
|
289
|
+
}
|
|
290
|
+
// --- Form ---
|
|
291
|
+
ResetForm() {
|
|
292
|
+
this.StarRating = 0;
|
|
293
|
+
this.HoverRating = 0;
|
|
294
|
+
this.FeedbackComments = '';
|
|
295
|
+
this.SubmitSuccess = false;
|
|
296
|
+
this.SubmitError = '';
|
|
297
|
+
}
|
|
298
|
+
CanSubmit() {
|
|
299
|
+
return !!this.SelectedSpec && this.StarRating > 0 && !this.IsSubmitting;
|
|
300
|
+
}
|
|
301
|
+
async SubmitFeedback() {
|
|
302
|
+
if (!this.CanSubmit() || !this.SelectedSpec)
|
|
303
|
+
return;
|
|
304
|
+
this.IsSubmitting = true;
|
|
305
|
+
this.SubmitError = '';
|
|
306
|
+
this.SubmitSuccess = false;
|
|
307
|
+
this.cdr.detectChanges();
|
|
308
|
+
try {
|
|
309
|
+
// Dynamic import to avoid adding graphql-dataprovider as a package dependency.
|
|
310
|
+
// At runtime in the browser, Metadata.Provider is always a GraphQLDataProvider.
|
|
311
|
+
const { GraphQLComponentRegistryClient } = await import('@memberjunction/graphql-dataprovider');
|
|
312
|
+
const provider = Metadata.Provider;
|
|
313
|
+
const client = new GraphQLComponentRegistryClient(provider);
|
|
314
|
+
const response = await client.SendComponentFeedback({
|
|
315
|
+
componentName: this.SelectedSpec.name,
|
|
316
|
+
componentNamespace: this.SelectedSpec.namespace || this.SelectedSpec.registry || '',
|
|
317
|
+
componentVersion: this.SelectedSpec.version,
|
|
318
|
+
registryName: this.SelectedSpec.registry,
|
|
319
|
+
rating: this.StarRating * 20, // 0-5 -> 0-100
|
|
320
|
+
comments: this.FeedbackComments.trim() || undefined,
|
|
321
|
+
conversationID: this.ConversationId || undefined,
|
|
322
|
+
conversationDetailID: this.ConversationDetailId || undefined
|
|
323
|
+
});
|
|
324
|
+
if (response.success) {
|
|
325
|
+
this.SubmitSuccess = true;
|
|
326
|
+
setTimeout(() => {
|
|
327
|
+
this.ResetForm();
|
|
328
|
+
this.cdr.detectChanges();
|
|
329
|
+
}, 2000);
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
this.SubmitError = response.error || 'Failed to submit feedback.';
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
catch (error) {
|
|
336
|
+
this.SubmitError = 'Failed to submit feedback. Please try again.';
|
|
337
|
+
console.error('Error submitting component feedback:', error);
|
|
338
|
+
}
|
|
339
|
+
finally {
|
|
340
|
+
this.IsSubmitting = false;
|
|
341
|
+
this.cdr.detectChanges();
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
// --- Hover Highlight (light preview on tree hover) ---
|
|
345
|
+
HoverTreeItem(spec) {
|
|
346
|
+
if (!this.ReactContainerElement || this.IsSelected(spec))
|
|
347
|
+
return;
|
|
348
|
+
this.showHoverOverlay(spec.name);
|
|
349
|
+
}
|
|
350
|
+
ClearTreeItemHover() {
|
|
351
|
+
this.removeHoverOverlay();
|
|
352
|
+
}
|
|
353
|
+
showHoverOverlay(componentName) {
|
|
354
|
+
if (!this.ReactContainerElement)
|
|
355
|
+
return;
|
|
356
|
+
const targetEl = this.ReactContainerElement.querySelector(`[data-mj-component="${componentName}"]`);
|
|
357
|
+
if (!targetEl) {
|
|
358
|
+
this.removeHoverOverlay();
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
this.ensureContainerPositioned();
|
|
362
|
+
if (!this.hoverOverlay) {
|
|
363
|
+
this.hoverOverlay = document.createElement('div');
|
|
364
|
+
this.ReactContainerElement.appendChild(this.hoverOverlay);
|
|
365
|
+
}
|
|
366
|
+
this.positionOverlay(this.hoverOverlay, targetEl);
|
|
367
|
+
this.hoverOverlay.style.border = '2px dashed var(--mj-brand-primary, #3B82F6)';
|
|
368
|
+
this.hoverOverlay.style.background = 'color-mix(in srgb, var(--mj-brand-primary, #3B82F6) 5%, transparent)';
|
|
369
|
+
}
|
|
370
|
+
removeHoverOverlay() {
|
|
371
|
+
if (this.hoverOverlay?.parentNode) {
|
|
372
|
+
this.hoverOverlay.parentNode.removeChild(this.hoverOverlay);
|
|
373
|
+
}
|
|
374
|
+
this.hoverOverlay = null;
|
|
375
|
+
}
|
|
376
|
+
// --- Region Highlighting (solid selection) ---
|
|
377
|
+
HighlightComponent(componentName) {
|
|
378
|
+
if (!this.ReactContainerElement) {
|
|
379
|
+
this.ClearHighlight();
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
const targetEl = this.ReactContainerElement.querySelector(`[data-mj-component="${componentName}"]`);
|
|
383
|
+
if (!targetEl) {
|
|
384
|
+
this.ClearHighlight();
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
this.ensureContainerPositioned();
|
|
388
|
+
if (!this.highlightOverlay) {
|
|
389
|
+
this.highlightOverlay = document.createElement('div');
|
|
390
|
+
this.ReactContainerElement.appendChild(this.highlightOverlay);
|
|
391
|
+
}
|
|
392
|
+
this.positionOverlay(this.highlightOverlay, targetEl);
|
|
393
|
+
this.highlightOverlay.style.border = '2px solid var(--mj-brand-primary, #3B82F6)';
|
|
394
|
+
this.highlightOverlay.style.background = 'color-mix(in srgb, var(--mj-brand-primary, #3B82F6) 10%, transparent)';
|
|
395
|
+
// Watch for resize/layout changes
|
|
396
|
+
this.resizeObserver?.disconnect();
|
|
397
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
398
|
+
if (this.highlightOverlay) {
|
|
399
|
+
this.positionOverlay(this.highlightOverlay, targetEl);
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
this.resizeObserver.observe(targetEl);
|
|
403
|
+
this.resizeObserver.observe(this.ReactContainerElement);
|
|
404
|
+
// Set up bidirectional click selection on container
|
|
405
|
+
this.installContainerClickListener();
|
|
406
|
+
}
|
|
407
|
+
ensureContainerPositioned() {
|
|
408
|
+
if (!this.ReactContainerElement)
|
|
409
|
+
return;
|
|
410
|
+
const containerStyle = getComputedStyle(this.ReactContainerElement);
|
|
411
|
+
if (containerStyle.position === 'static') {
|
|
412
|
+
this.ReactContainerElement.style.position = 'relative';
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Gets the effective bounding rect for a component marker element.
|
|
417
|
+
* display:contents elements return zero-size rects, so we compute
|
|
418
|
+
* the union bounding box of their children instead.
|
|
419
|
+
*/
|
|
420
|
+
getEffectiveRect(el) {
|
|
421
|
+
const rect = el.getBoundingClientRect();
|
|
422
|
+
if (rect.width > 0 && rect.height > 0)
|
|
423
|
+
return rect;
|
|
424
|
+
// display:contents wrapper — union the bounding rects of all children
|
|
425
|
+
const children = el.children;
|
|
426
|
+
if (children.length === 0)
|
|
427
|
+
return rect;
|
|
428
|
+
let top = Infinity, left = Infinity, bottom = -Infinity, right = -Infinity;
|
|
429
|
+
for (let i = 0; i < children.length; i++) {
|
|
430
|
+
const childRect = children[i].getBoundingClientRect();
|
|
431
|
+
if (childRect.width === 0 && childRect.height === 0)
|
|
432
|
+
continue;
|
|
433
|
+
top = Math.min(top, childRect.top);
|
|
434
|
+
left = Math.min(left, childRect.left);
|
|
435
|
+
bottom = Math.max(bottom, childRect.bottom);
|
|
436
|
+
right = Math.max(right, childRect.right);
|
|
437
|
+
}
|
|
438
|
+
if (top === Infinity)
|
|
439
|
+
return rect; // no visible children
|
|
440
|
+
return new DOMRect(left, top, right - left, bottom - top);
|
|
441
|
+
}
|
|
442
|
+
positionOverlay(overlay, targetEl) {
|
|
443
|
+
if (!this.ReactContainerElement)
|
|
444
|
+
return;
|
|
445
|
+
const targetRect = this.getEffectiveRect(targetEl);
|
|
446
|
+
const containerRect = this.ReactContainerElement.getBoundingClientRect();
|
|
447
|
+
overlay.style.position = 'absolute';
|
|
448
|
+
overlay.style.top = `${targetRect.top - containerRect.top + this.ReactContainerElement.scrollTop}px`;
|
|
449
|
+
overlay.style.left = `${targetRect.left - containerRect.left + this.ReactContainerElement.scrollLeft}px`;
|
|
450
|
+
overlay.style.width = `${targetRect.width}px`;
|
|
451
|
+
overlay.style.height = `${targetRect.height}px`;
|
|
452
|
+
overlay.style.pointerEvents = 'none';
|
|
453
|
+
overlay.style.zIndex = '10';
|
|
454
|
+
overlay.style.borderRadius = '4px';
|
|
455
|
+
overlay.style.transition = 'all 0.2s ease';
|
|
456
|
+
}
|
|
457
|
+
// --- Bidirectional click: clicking a component region selects it in the tree ---
|
|
458
|
+
installContainerClickListener() {
|
|
459
|
+
if (this.containerClickHandler || !this.ReactContainerElement)
|
|
460
|
+
return;
|
|
461
|
+
this.containerClickHandler = (e) => {
|
|
462
|
+
const target = e.target;
|
|
463
|
+
if (!target)
|
|
464
|
+
return;
|
|
465
|
+
// Walk up from click target to find nearest [data-mj-component]
|
|
466
|
+
const componentEl = target.closest('[data-mj-component]');
|
|
467
|
+
if (!componentEl)
|
|
468
|
+
return;
|
|
469
|
+
const componentName = componentEl.getAttribute('data-mj-component');
|
|
470
|
+
if (!componentName)
|
|
471
|
+
return;
|
|
472
|
+
// Find matching spec in the tree
|
|
473
|
+
const matchingSpec = this.findSpecByName(componentName);
|
|
474
|
+
if (matchingSpec && matchingSpec.name !== this.SelectedSpec?.name) {
|
|
475
|
+
this.SelectComponent(matchingSpec);
|
|
476
|
+
this.cdr.detectChanges();
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
// Use capture phase so we observe the click without interfering with component handlers
|
|
480
|
+
this.ReactContainerElement.addEventListener('click', this.containerClickHandler, true);
|
|
481
|
+
}
|
|
482
|
+
removeContainerClickListener() {
|
|
483
|
+
if (this.containerClickHandler && this.ReactContainerElement) {
|
|
484
|
+
this.ReactContainerElement.removeEventListener('click', this.containerClickHandler, true);
|
|
485
|
+
}
|
|
486
|
+
this.containerClickHandler = null;
|
|
487
|
+
}
|
|
488
|
+
findSpecByName(name) {
|
|
489
|
+
if (!this.ComponentSpec)
|
|
490
|
+
return null;
|
|
491
|
+
return this.walkSpecTree(this.ComponentSpec, name);
|
|
492
|
+
}
|
|
493
|
+
walkSpecTree(spec, name) {
|
|
494
|
+
if (spec.name === name)
|
|
495
|
+
return spec;
|
|
496
|
+
if (spec.dependencies) {
|
|
497
|
+
for (const child of spec.dependencies) {
|
|
498
|
+
const found = this.walkSpecTree(child, name);
|
|
499
|
+
if (found)
|
|
500
|
+
return found;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return null;
|
|
504
|
+
}
|
|
505
|
+
ClearHighlight() {
|
|
506
|
+
this.resizeObserver?.disconnect();
|
|
507
|
+
this.resizeObserver = null;
|
|
508
|
+
if (this.highlightOverlay?.parentNode) {
|
|
509
|
+
this.highlightOverlay.parentNode.removeChild(this.highlightOverlay);
|
|
510
|
+
}
|
|
511
|
+
this.highlightOverlay = null;
|
|
512
|
+
this.removeHoverOverlay();
|
|
513
|
+
this.removeContainerClickListener();
|
|
514
|
+
}
|
|
515
|
+
ClosePanel() {
|
|
516
|
+
this.ClearHighlight();
|
|
517
|
+
this.Closed.emit();
|
|
518
|
+
}
|
|
519
|
+
ngOnDestroy() {
|
|
520
|
+
this.ClearHighlight();
|
|
521
|
+
}
|
|
522
|
+
static ɵfac = function ComponentFeedbackPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ComponentFeedbackPanelComponent)(); };
|
|
523
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ComponentFeedbackPanelComponent, selectors: [["mj-component-feedback-panel"]], inputs: { ComponentSpec: "ComponentSpec", ReactContainerElement: "ReactContainerElement", ConversationId: "ConversationId", ConversationDetailId: "ConversationDetailId" }, outputs: { Closed: "Closed" }, decls: 20, vars: 2, consts: [[1, "feedback-panel-overlay", 3, "click"], [1, "feedback-panel", 3, "click"], [1, "panel-header"], [1, "panel-title"], [1, "fa-solid", "fa-comment-dots"], [1, "close-button", 3, "click"], [1, "fa-solid", "fa-times"], [1, "panel-content"], [1, "tree-section"], [1, "section-header"], [1, "fa-solid", "fa-sitemap"], [1, "component-tree"], [1, "empty-state"], [1, "feedback-section"], [1, "selected-component-info"], [1, "no-selection-message"], [1, "tree-item", 3, "selected", "padding-left"], [1, "tree-item", 3, "click", "mouseenter", "mouseleave"], [1, "tree-toggle", "fa-solid", 3, "fa-chevron-right", "fa-chevron-down"], [1, "tree-spacer"], [1, "fa-solid", "fa-cube", "component-icon"], [1, "component-info"], [1, "component-name"], [1, "component-badge", "registry"], [1, "tree-toggle", "fa-solid", 3, "click"], [1, "fa-solid", "fa-info-circle"], [1, "fa-solid", "fa-star"], [1, "component-description"], [1, "star-rating-container"], [1, "rating-label"], [1, "star-rating"], [1, "star", 3, "fa-solid", "fa-regular", "fa-star"], [1, "rating-text"], [1, "rating-text", "placeholder"], [1, "comment-container"], [1, "comment-label"], [1, "optional-label"], ["placeholder", "Share your thoughts about this component...", "rows", "4", "maxlength", "1000", 1, "comment-input", 3, "ngModelChange", "ngModel"], [1, "char-count"], [1, "submit-container"], [1, "submit-button", 3, "click", "disabled"], [1, "message", "success-message"], [1, "message", "error-message"], [1, "star", 3, "click", "mouseenter", "mouseleave"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "fa-solid", "fa-paper-plane"], [1, "fa-solid", "fa-check-circle"], [1, "fa-solid", "fa-exclamation-circle"], [1, "fa-solid", "fa-hand-pointer"]], template: function ComponentFeedbackPanelComponent_Template(rf, ctx) { if (rf & 1) {
|
|
524
|
+
i0.ɵɵelementStart(0, "div", 0);
|
|
525
|
+
i0.ɵɵlistener("click", function ComponentFeedbackPanelComponent_Template_div_click_0_listener() { return ctx.ClosePanel(); });
|
|
526
|
+
i0.ɵɵelementStart(1, "div", 1);
|
|
527
|
+
i0.ɵɵlistener("click", function ComponentFeedbackPanelComponent_Template_div_click_1_listener($event) { return $event.stopPropagation(); });
|
|
528
|
+
i0.ɵɵelementStart(2, "div", 2)(3, "div", 3);
|
|
529
|
+
i0.ɵɵelement(4, "i", 4);
|
|
530
|
+
i0.ɵɵelementStart(5, "span");
|
|
531
|
+
i0.ɵɵtext(6, "Component Feedback");
|
|
532
|
+
i0.ɵɵelementEnd()();
|
|
533
|
+
i0.ɵɵelementStart(7, "button", 5);
|
|
534
|
+
i0.ɵɵlistener("click", function ComponentFeedbackPanelComponent_Template_button_click_7_listener() { return ctx.ClosePanel(); });
|
|
535
|
+
i0.ɵɵelement(8, "i", 6);
|
|
536
|
+
i0.ɵɵelementEnd()();
|
|
537
|
+
i0.ɵɵelementStart(9, "div", 7)(10, "div", 8)(11, "div", 9);
|
|
538
|
+
i0.ɵɵelement(12, "i", 10);
|
|
539
|
+
i0.ɵɵelementStart(13, "span");
|
|
540
|
+
i0.ɵɵtext(14, "Select Component");
|
|
541
|
+
i0.ɵɵelementEnd()();
|
|
542
|
+
i0.ɵɵconditionalCreate(15, ComponentFeedbackPanelComponent_Conditional_15_Template, 3, 0, "div", 11)(16, ComponentFeedbackPanelComponent_Conditional_16_Template, 4, 0, "div", 12);
|
|
543
|
+
i0.ɵɵelementEnd();
|
|
544
|
+
i0.ɵɵelementStart(17, "div", 13);
|
|
545
|
+
i0.ɵɵconditionalCreate(18, ComponentFeedbackPanelComponent_Conditional_18_Template, 28, 10, "div", 14)(19, ComponentFeedbackPanelComponent_Conditional_19_Template, 4, 0, "div", 15);
|
|
546
|
+
i0.ɵɵelementEnd()()()();
|
|
547
|
+
} if (rf & 2) {
|
|
548
|
+
i0.ɵɵadvance(15);
|
|
549
|
+
i0.ɵɵconditional(ctx.ComponentSpec ? 15 : 16);
|
|
550
|
+
i0.ɵɵadvance(3);
|
|
551
|
+
i0.ɵɵconditional(ctx.SelectedSpec ? 18 : 19);
|
|
552
|
+
} }, dependencies: [CommonModule, FormsModule, i1.DefaultValueAccessor, i1.NgControlStatus, i1.MaxLengthValidator, i1.NgModel], styles: ["\n\n.feedback-panel-overlay[_ngcontent-%COMP%] {\n position: fixed;\n top: 60px;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: var(--mj-bg-overlay, rgba(0, 0, 0, 0.4));\n z-index: 9999;\n display: flex;\n justify-content: flex-start;\n animation: _ngcontent-%COMP%_fadeIn 0.2s ease-in-out;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n\n\n.feedback-panel[_ngcontent-%COMP%] {\n width: 450px;\n height: 100%;\n background-color: var(--mj-bg-surface, #ffffff);\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n animation: _ngcontent-%COMP%_slideInFromLeft 0.3s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_slideInFromLeft {\n from { transform: translateX(-100%); }\n to { transform: translateX(0); }\n}\n\n\n\n.panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default, #e0e0e0);\n background-color: var(--mj-bg-surface-card, #f8f9fa);\n}\n\n.panel-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary, #333);\n}\n\n.panel-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary, #3B82F6);\n font-size: 20px;\n}\n\n.close-button[_ngcontent-%COMP%] {\n min-width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n background: none;\n border-radius: 4px;\n cursor: pointer;\n color: var(--mj-text-secondary, #555);\n font-size: 16px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.close-button[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-hover, #e0e0e0);\n}\n\n\n\n.panel-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 20px;\n padding: 20px;\n}\n\n\n\n.section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary, #555);\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 2px solid var(--mj-brand-primary, #3B82F6);\n}\n\n.section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary, #3B82F6);\n}\n\n\n\n.tree-section[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface-card, #f8f9fa);\n border-radius: 8px;\n padding: 16px;\n}\n\n.component-tree[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.tree-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n user-select: none;\n}\n\n.tree-item[_ngcontent-%COMP%]:hover {\n background-color: color-mix(in srgb, var(--mj-brand-primary, #3B82F6) 10%, var(--mj-bg-surface, #ffffff));\n}\n\n.tree-item.selected[_ngcontent-%COMP%] {\n background-color: var(--mj-brand-primary, #3B82F6);\n color: var(--mj-text-inverse, #ffffff);\n font-weight: 500;\n}\n\n.tree-item.selected[_ngcontent-%COMP%] .component-icon[_ngcontent-%COMP%], \n.tree-item.selected[_ngcontent-%COMP%] .tree-toggle[_ngcontent-%COMP%] {\n color: var(--mj-text-inverse, #ffffff);\n}\n\n.tree-item.selected[_ngcontent-%COMP%] .component-badge[_ngcontent-%COMP%] {\n background-color: rgba(255, 255, 255, 0.2);\n color: var(--mj-text-inverse, #ffffff);\n border-color: rgba(255, 255, 255, 0.3);\n}\n\n.tree-toggle[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-muted, #666);\n cursor: pointer;\n transition: transform 0.2s ease;\n width: 16px;\n text-align: center;\n}\n\n.tree-spacer[_ngcontent-%COMP%] {\n width: 16px;\n display: inline-block;\n}\n\n.component-icon[_ngcontent-%COMP%] {\n font-size: 16px;\n color: var(--mj-brand-primary, #3B82F6);\n}\n\n.component-info[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 8px;\n overflow: hidden;\n}\n\n.component-name[_ngcontent-%COMP%] {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 14px;\n}\n\n.component-badge[_ngcontent-%COMP%] {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 10px;\n background-color: color-mix(in srgb, var(--mj-brand-primary, #3B82F6) 10%, var(--mj-bg-surface, #ffffff));\n color: var(--mj-brand-primary, #3B82F6);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary, #3B82F6) 30%, var(--mj-bg-surface, #ffffff));\n white-space: nowrap;\n font-weight: 500;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 20px;\n color: var(--mj-text-disabled, #999);\n font-size: 14px;\n}\n\n\n\n.feedback-section[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface, #ffffff);\n border-radius: 8px;\n border: 1px solid var(--mj-border-default, #e0e0e0);\n padding: 16px;\n min-height: 300px;\n}\n\n.selected-component-info[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.component-description[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary, #666);\n line-height: 1.5;\n margin: 0;\n padding: 12px;\n background-color: var(--mj-bg-surface-card, #f8f9fa);\n border-radius: 6px;\n border-left: 3px solid var(--mj-brand-primary, #3B82F6);\n}\n\n\n\n.star-rating-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.rating-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary, #333);\n}\n\n.star-rating[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.star[_ngcontent-%COMP%] {\n font-size: 32px;\n color: #ffd700;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.star[_ngcontent-%COMP%]:hover {\n transform: scale(1.2);\n filter: brightness(1.1);\n}\n\n.star.fa-regular[_ngcontent-%COMP%] {\n color: var(--mj-border-default, #d0d0d0);\n}\n\n.rating-text[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-secondary, #666);\n margin-top: 4px;\n}\n\n.rating-text.placeholder[_ngcontent-%COMP%] {\n color: var(--mj-text-disabled, #999);\n font-style: italic;\n}\n\n\n\n.comment-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n position: relative;\n}\n\n.comment-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary, #333);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.optional-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: normal;\n color: var(--mj-text-disabled, #999);\n}\n\n.comment-input[_ngcontent-%COMP%] {\n width: 100%;\n padding: 12px;\n border: 1px solid var(--mj-border-default, #d0d0d0);\n border-radius: 6px;\n font-size: 14px;\n font-family: inherit;\n resize: vertical;\n min-height: 80px;\n transition: border-color 0.2s ease;\n background-color: var(--mj-bg-surface, #ffffff);\n color: var(--mj-text-primary, #333);\n box-sizing: border-box;\n}\n\n.comment-input[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary, #3B82F6);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary, #3B82F6) 15%, transparent);\n}\n\n.char-count[_ngcontent-%COMP%] {\n position: absolute;\n bottom: 8px;\n right: 12px;\n font-size: 11px;\n color: var(--mj-text-disabled, #999);\n background-color: var(--mj-bg-surface, #ffffff);\n padding: 2px 4px;\n}\n\n\n\n.submit-container[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-start;\n}\n\n.submit-button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n font-size: 14px;\n font-weight: 500;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n background-color: var(--mj-brand-primary, #3B82F6);\n color: var(--mj-text-inverse, #ffffff);\n transition: background-color 0.2s ease;\n}\n\n.submit-button[_ngcontent-%COMP%]:hover:not(:disabled) {\n background-color: var(--mj-brand-primary-hover, #2563EB);\n}\n\n.submit-button[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n\n\n.message[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n border-radius: 6px;\n font-size: 14px;\n animation: _ngcontent-%COMP%_slideDown 0.3s ease-out;\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from { opacity: 0; transform: translateY(-10px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.success-message[_ngcontent-%COMP%] {\n background-color: var(--mj-status-success-bg, #d4edda);\n color: var(--mj-status-success-text, #155724);\n border: 1px solid var(--mj-status-success-border, #c3e6cb);\n}\n\n.success-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-success, #28a745);\n}\n\n.error-message[_ngcontent-%COMP%] {\n background-color: var(--mj-status-error-bg, #f8d7da);\n color: var(--mj-status-error-text, #721c24);\n border: 1px solid var(--mj-status-error-border, #f5c6cb);\n}\n\n.error-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error, #dc3545);\n}\n\n\n\n.no-selection-message[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 40px 20px;\n color: var(--mj-text-disabled, #999);\n text-align: center;\n}\n\n.no-selection-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n color: var(--mj-border-default, #d0d0d0);\n}\n\n.no-selection-message[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n line-height: 1.5;\n}\n\n\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar {\n width: 8px;\n}\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar-track {\n background-color: var(--mj-bg-surface-sunken, #f1f1f1);\n}\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb {\n background-color: var(--mj-border-strong, #c0c0c0);\n border-radius: 4px;\n}\n\n.panel-content[_ngcontent-%COMP%]::-webkit-scrollbar-thumb:hover {\n background-color: var(--mj-text-disabled, #a0a0a0);\n}"] });
|
|
553
|
+
}
|
|
554
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ComponentFeedbackPanelComponent, [{
|
|
555
|
+
type: Component,
|
|
556
|
+
args: [{ selector: 'mj-component-feedback-panel', standalone: true, imports: [CommonModule, FormsModule], template: "<div class=\"feedback-panel-overlay\" (click)=\"ClosePanel()\">\n <div class=\"feedback-panel\" (click)=\"$event.stopPropagation()\">\n <!-- Header -->\n <div class=\"panel-header\">\n <div class=\"panel-title\">\n <i class=\"fa-solid fa-comment-dots\"></i>\n <span>Component Feedback</span>\n </div>\n <button class=\"close-button\" (click)=\"ClosePanel()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"panel-content\">\n <!-- Component Tree Section -->\n <div class=\"tree-section\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-sitemap\"></i>\n <span>Select Component</span>\n </div>\n\n @if (ComponentSpec) {\n <div class=\"component-tree\">\n @for (item of GetTreeItems(); track item.spec.name) {\n <div\n class=\"tree-item\"\n [class.selected]=\"IsSelected(item.spec)\"\n [style.padding-left]=\"GetIndentation(item.depth)\"\n (click)=\"SelectComponent(item.spec)\"\n (mouseenter)=\"HoverTreeItem(item.spec)\"\n (mouseleave)=\"ClearTreeItemHover()\">\n\n @if (item.hasChildren) {\n <i\n class=\"tree-toggle fa-solid\"\n [class.fa-chevron-right]=\"!IsNodeExpanded(item.spec)\"\n [class.fa-chevron-down]=\"IsNodeExpanded(item.spec)\"\n (click)=\"ToggleNode(item.spec, $event)\">\n </i>\n } @else {\n <span class=\"tree-spacer\"></span>\n }\n\n <i class=\"fa-solid fa-cube component-icon\"></i>\n\n <div class=\"component-info\">\n <span class=\"component-name\">{{ item.spec.title || item.spec.name }}</span>\n @if (item.spec.location === 'registry') {\n <span class=\"component-badge registry\">Registry</span>\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-info-circle\"></i>\n <span>No component hierarchy available</span>\n </div>\n }\n </div>\n\n <!-- Feedback Form Section -->\n <div class=\"feedback-section\">\n @if (SelectedSpec) {\n <div class=\"selected-component-info\">\n <div class=\"section-header\">\n <i class=\"fa-solid fa-star\"></i>\n <span>Rate: {{ SelectedSpec.title || SelectedSpec.name }}</span>\n </div>\n\n @if (SelectedSpec.description) {\n <p class=\"component-description\">{{ SelectedSpec.description }}</p>\n }\n\n <!-- Star Rating -->\n <div class=\"star-rating-container\">\n <label class=\"rating-label\">Your Rating</label>\n <div class=\"star-rating\">\n @for (star of [1, 2, 3, 4, 5]; track star) {\n <i\n class=\"star\"\n [class.fa-solid]=\"IsStarFilled(star)\"\n [class.fa-regular]=\"!IsStarFilled(star)\"\n [class.fa-star]=\"true\"\n (click)=\"SetRating(star)\"\n (mouseenter)=\"SetHoverRating(star)\"\n (mouseleave)=\"ClearHoverRating()\">\n </i>\n }\n </div>\n @if (StarRating > 0) {\n <span class=\"rating-text\">{{ StarRating }} out of 5 stars</span>\n } @else {\n <span class=\"rating-text placeholder\">Click to rate</span>\n }\n </div>\n\n <!-- Comment Input -->\n <div class=\"comment-container\">\n <label class=\"comment-label\">\n Comments\n <span class=\"optional-label\">(optional)</span>\n </label>\n <textarea\n class=\"comment-input\"\n [(ngModel)]=\"FeedbackComments\"\n placeholder=\"Share your thoughts about this component...\"\n rows=\"4\"\n maxlength=\"1000\">\n </textarea>\n @if (FeedbackComments.length > 0) {\n <span class=\"char-count\">{{ FeedbackComments.length }}/1000</span>\n }\n </div>\n\n <!-- Submit Button -->\n <div class=\"submit-container\">\n <button\n class=\"submit-button\"\n [disabled]=\"!CanSubmit()\"\n (click)=\"SubmitFeedback()\">\n @if (IsSubmitting) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Submitting...</span>\n } @else {\n <i class=\"fa-solid fa-paper-plane\"></i>\n <span>Submit Feedback</span>\n }\n </button>\n </div>\n\n <!-- Success/Error Messages -->\n @if (SubmitSuccess) {\n <div class=\"message success-message\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <span>Feedback submitted successfully!</span>\n </div>\n }\n @if (SubmitError) {\n <div class=\"message error-message\">\n <i class=\"fa-solid fa-exclamation-circle\"></i>\n <span>{{ SubmitError }}</span>\n </div>\n }\n </div>\n } @else {\n <div class=\"no-selection-message\">\n <i class=\"fa-solid fa-hand-pointer\"></i>\n <p>Select a component from the tree to provide feedback</p>\n </div>\n }\n </div>\n </div>\n </div>\n</div>\n", styles: ["/* Overlay */\n.feedback-panel-overlay {\n position: fixed;\n top: 60px;\n left: 0;\n right: 0;\n bottom: 0;\n background-color: var(--mj-bg-overlay, rgba(0, 0, 0, 0.4));\n z-index: 9999;\n display: flex;\n justify-content: flex-start;\n animation: fadeIn 0.2s ease-in-out;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* Panel Container */\n.feedback-panel {\n width: 450px;\n height: 100%;\n background-color: var(--mj-bg-surface, #ffffff);\n box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n animation: slideInFromLeft 0.3s ease-out;\n}\n\n@keyframes slideInFromLeft {\n from { transform: translateX(-100%); }\n to { transform: translateX(0); }\n}\n\n/* Header */\n.panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default, #e0e0e0);\n background-color: var(--mj-bg-surface-card, #f8f9fa);\n}\n\n.panel-title {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary, #333);\n}\n\n.panel-title i {\n color: var(--mj-brand-primary, #3B82F6);\n font-size: 20px;\n}\n\n.close-button {\n min-width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n background: none;\n border-radius: 4px;\n cursor: pointer;\n color: var(--mj-text-secondary, #555);\n font-size: 16px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.close-button:hover {\n background-color: var(--mj-bg-surface-hover, #e0e0e0);\n}\n\n/* Content */\n.panel-content {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 20px;\n padding: 20px;\n}\n\n/* Section Headers */\n.section-header {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary, #555);\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 2px solid var(--mj-brand-primary, #3B82F6);\n}\n\n.section-header i {\n color: var(--mj-brand-primary, #3B82F6);\n}\n\n/* Component Tree */\n.tree-section {\n background-color: var(--mj-bg-surface-card, #f8f9fa);\n border-radius: 8px;\n padding: 16px;\n}\n\n.component-tree {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.tree-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n user-select: none;\n}\n\n.tree-item:hover {\n background-color: color-mix(in srgb, var(--mj-brand-primary, #3B82F6) 10%, var(--mj-bg-surface, #ffffff));\n}\n\n.tree-item.selected {\n background-color: var(--mj-brand-primary, #3B82F6);\n color: var(--mj-text-inverse, #ffffff);\n font-weight: 500;\n}\n\n.tree-item.selected .component-icon,\n.tree-item.selected .tree-toggle {\n color: var(--mj-text-inverse, #ffffff);\n}\n\n.tree-item.selected .component-badge {\n background-color: rgba(255, 255, 255, 0.2);\n color: var(--mj-text-inverse, #ffffff);\n border-color: rgba(255, 255, 255, 0.3);\n}\n\n.tree-toggle {\n font-size: 12px;\n color: var(--mj-text-muted, #666);\n cursor: pointer;\n transition: transform 0.2s ease;\n width: 16px;\n text-align: center;\n}\n\n.tree-spacer {\n width: 16px;\n display: inline-block;\n}\n\n.component-icon {\n font-size: 16px;\n color: var(--mj-brand-primary, #3B82F6);\n}\n\n.component-info {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 8px;\n overflow: hidden;\n}\n\n.component-name {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 14px;\n}\n\n.component-badge {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 10px;\n background-color: color-mix(in srgb, var(--mj-brand-primary, #3B82F6) 10%, var(--mj-bg-surface, #ffffff));\n color: var(--mj-brand-primary, #3B82F6);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary, #3B82F6) 30%, var(--mj-bg-surface, #ffffff));\n white-space: nowrap;\n font-weight: 500;\n}\n\n.empty-state {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 20px;\n color: var(--mj-text-disabled, #999);\n font-size: 14px;\n}\n\n/* Feedback Form Section */\n.feedback-section {\n background-color: var(--mj-bg-surface, #ffffff);\n border-radius: 8px;\n border: 1px solid var(--mj-border-default, #e0e0e0);\n padding: 16px;\n min-height: 300px;\n}\n\n.selected-component-info {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.component-description {\n font-size: 13px;\n color: var(--mj-text-secondary, #666);\n line-height: 1.5;\n margin: 0;\n padding: 12px;\n background-color: var(--mj-bg-surface-card, #f8f9fa);\n border-radius: 6px;\n border-left: 3px solid var(--mj-brand-primary, #3B82F6);\n}\n\n/* Star Rating */\n.star-rating-container {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.rating-label {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary, #333);\n}\n\n.star-rating {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n.star {\n font-size: 32px;\n color: #ffd700;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.star:hover {\n transform: scale(1.2);\n filter: brightness(1.1);\n}\n\n.star.fa-regular {\n color: var(--mj-border-default, #d0d0d0);\n}\n\n.rating-text {\n font-size: 13px;\n color: var(--mj-text-secondary, #666);\n margin-top: 4px;\n}\n\n.rating-text.placeholder {\n color: var(--mj-text-disabled, #999);\n font-style: italic;\n}\n\n/* Comment Input */\n.comment-container {\n display: flex;\n flex-direction: column;\n gap: 8px;\n position: relative;\n}\n\n.comment-label {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary, #333);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.optional-label {\n font-size: 12px;\n font-weight: normal;\n color: var(--mj-text-disabled, #999);\n}\n\n.comment-input {\n width: 100%;\n padding: 12px;\n border: 1px solid var(--mj-border-default, #d0d0d0);\n border-radius: 6px;\n font-size: 14px;\n font-family: inherit;\n resize: vertical;\n min-height: 80px;\n transition: border-color 0.2s ease;\n background-color: var(--mj-bg-surface, #ffffff);\n color: var(--mj-text-primary, #333);\n box-sizing: border-box;\n}\n\n.comment-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary, #3B82F6);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary, #3B82F6) 15%, transparent);\n}\n\n.char-count {\n position: absolute;\n bottom: 8px;\n right: 12px;\n font-size: 11px;\n color: var(--mj-text-disabled, #999);\n background-color: var(--mj-bg-surface, #ffffff);\n padding: 2px 4px;\n}\n\n/* Submit Button */\n.submit-container {\n display: flex;\n justify-content: flex-start;\n}\n\n.submit-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n font-size: 14px;\n font-weight: 500;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n background-color: var(--mj-brand-primary, #3B82F6);\n color: var(--mj-text-inverse, #ffffff);\n transition: background-color 0.2s ease;\n}\n\n.submit-button:hover:not(:disabled) {\n background-color: var(--mj-brand-primary-hover, #2563EB);\n}\n\n.submit-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Messages */\n.message {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n border-radius: 6px;\n font-size: 14px;\n animation: slideDown 0.3s ease-out;\n}\n\n@keyframes slideDown {\n from { opacity: 0; transform: translateY(-10px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n.success-message {\n background-color: var(--mj-status-success-bg, #d4edda);\n color: var(--mj-status-success-text, #155724);\n border: 1px solid var(--mj-status-success-border, #c3e6cb);\n}\n\n.success-message i {\n color: var(--mj-status-success, #28a745);\n}\n\n.error-message {\n background-color: var(--mj-status-error-bg, #f8d7da);\n color: var(--mj-status-error-text, #721c24);\n border: 1px solid var(--mj-status-error-border, #f5c6cb);\n}\n\n.error-message i {\n color: var(--mj-status-error, #dc3545);\n}\n\n/* No Selection Message */\n.no-selection-message {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n padding: 40px 20px;\n color: var(--mj-text-disabled, #999);\n text-align: center;\n}\n\n.no-selection-message i {\n font-size: 48px;\n color: var(--mj-border-default, #d0d0d0);\n}\n\n.no-selection-message p {\n margin: 0;\n font-size: 14px;\n line-height: 1.5;\n}\n\n/* Scrollbar Styling */\n.panel-content::-webkit-scrollbar {\n width: 8px;\n}\n\n.panel-content::-webkit-scrollbar-track {\n background-color: var(--mj-bg-surface-sunken, #f1f1f1);\n}\n\n.panel-content::-webkit-scrollbar-thumb {\n background-color: var(--mj-border-strong, #c0c0c0);\n border-radius: 4px;\n}\n\n.panel-content::-webkit-scrollbar-thumb:hover {\n background-color: var(--mj-text-disabled, #a0a0a0);\n}\n"] }]
|
|
557
|
+
}], null, { ComponentSpec: [{
|
|
558
|
+
type: Input
|
|
559
|
+
}], ReactContainerElement: [{
|
|
560
|
+
type: Input
|
|
561
|
+
}], ConversationId: [{
|
|
562
|
+
type: Input
|
|
563
|
+
}], ConversationDetailId: [{
|
|
564
|
+
type: Input
|
|
565
|
+
}], Closed: [{
|
|
566
|
+
type: Output
|
|
567
|
+
}] }); })();
|
|
568
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ComponentFeedbackPanelComponent, { className: "ComponentFeedbackPanelComponent", filePath: "src/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.ts", lineNumber: 28 }); })();
|
|
569
|
+
//# sourceMappingURL=component-feedback-panel.component.js.map
|