@memberjunction/ng-artifacts 5.37.0 → 5.39.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.
Files changed (44) hide show
  1. package/README.md +31 -0
  2. package/dist/__tests__/image-artifact-viewer.test.d.ts +2 -0
  3. package/dist/__tests__/image-artifact-viewer.test.d.ts.map +1 -0
  4. package/dist/__tests__/image-artifact-viewer.test.js +62 -0
  5. package/dist/__tests__/image-artifact-viewer.test.js.map +1 -0
  6. package/dist/lib/__tests__/interactive-form-apply.service.test.d.ts +2 -0
  7. package/dist/lib/__tests__/interactive-form-apply.service.test.d.ts.map +1 -0
  8. package/dist/lib/__tests__/interactive-form-apply.service.test.js +206 -0
  9. package/dist/lib/__tests__/interactive-form-apply.service.test.js.map +1 -0
  10. package/dist/lib/artifacts.module.d.ts +14 -12
  11. package/dist/lib/artifacts.module.d.ts.map +1 -1
  12. package/dist/lib/artifacts.module.js +14 -2
  13. package/dist/lib/artifacts.module.js.map +1 -1
  14. package/dist/lib/components/artifact-type-plugin-viewer.component.d.ts +11 -1
  15. package/dist/lib/components/artifact-type-plugin-viewer.component.d.ts.map +1 -1
  16. package/dist/lib/components/artifact-type-plugin-viewer.component.js +18 -1
  17. package/dist/lib/components/artifact-type-plugin-viewer.component.js.map +1 -1
  18. package/dist/lib/components/artifact-viewer-panel.component.d.ts +10 -1
  19. package/dist/lib/components/artifact-viewer-panel.component.d.ts.map +1 -1
  20. package/dist/lib/components/artifact-viewer-panel.component.js +11 -3
  21. package/dist/lib/components/artifact-viewer-panel.component.js.map +1 -1
  22. package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts +60 -2
  23. package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts.map +1 -1
  24. package/dist/lib/components/plugins/component-artifact-viewer.component.js +373 -24
  25. package/dist/lib/components/plugins/component-artifact-viewer.component.js.map +1 -1
  26. package/dist/lib/components/plugins/data-artifact-viewer.component.d.ts.map +1 -1
  27. package/dist/lib/components/plugins/data-artifact-viewer.component.js +0 -1
  28. package/dist/lib/components/plugins/data-artifact-viewer.component.js.map +1 -1
  29. package/dist/lib/components/plugins/image-artifact-viewer.component.d.ts +129 -0
  30. package/dist/lib/components/plugins/image-artifact-viewer.component.d.ts.map +1 -0
  31. package/dist/lib/components/plugins/image-artifact-viewer.component.js +413 -0
  32. package/dist/lib/components/plugins/image-artifact-viewer.component.js.map +1 -0
  33. package/dist/lib/components/plugins/save-query-dialog.component.d.ts.map +1 -1
  34. package/dist/lib/components/plugins/save-query-dialog.component.js +0 -2
  35. package/dist/lib/components/plugins/save-query-dialog.component.js.map +1 -1
  36. package/dist/lib/services/interactive-form-apply.service.d.ts +46 -0
  37. package/dist/lib/services/interactive-form-apply.service.d.ts.map +1 -0
  38. package/dist/lib/services/interactive-form-apply.service.js +219 -0
  39. package/dist/lib/services/interactive-form-apply.service.js.map +1 -0
  40. package/dist/public-api.d.ts +2 -0
  41. package/dist/public-api.d.ts.map +1 -1
  42. package/dist/public-api.js +2 -0
  43. package/dist/public-api.js.map +1 -1
  44. package/package.json +18 -16
package/README.md CHANGED
@@ -178,6 +178,37 @@ getIcon() {
178
178
  - `@angular/core` ^21.x
179
179
  - `@angular/platform-browser` ^21.x
180
180
 
181
+ ## Form-aware artifact viewer (interactive forms)
182
+
183
+ When an artifact's spec declares `componentRole: 'form'`, the
184
+ `ComponentArtifactViewerComponent` switches to its form-aware branch:
185
+
186
+ - Resolves the entity from `spec.entityName` (or `spec.dataRequirements.entities[0].name`)
187
+ - Loads `TOP 1` record (ordered by `NameField` then `__mj_CreatedAt`) and
188
+ mounts via `<mj-interactive-form>` bound to that real record
189
+ - Falls back to a fresh `NewRecord()` when the entity has no rows
190
+ - Exposes a search-as-you-type record picker so users can swap the bound record
191
+ - Bubbles a top-level **`applyFormRequested`** `@Output` carrying
192
+ `{ spec, entityName }` when the user clicks "Apply to my form"
193
+
194
+ The `InteractiveFormApplyService` (exported from this package) consumes
195
+ that event end-to-end: confirms with the user via `MJDialogService`,
196
+ calls `Get Active Form For Entity` to detect existing state, then
197
+ routes to `Create Interactive Form` (net-new) or
198
+ `Modify Interactive Form` (refinement → new Pending version).
199
+
200
+ Consumers wire one line in their template:
201
+ ```html
202
+ <mj-artifact-viewer-panel
203
+ ...
204
+ (applyFormRequested)="onApplyFormRequested($event)">
205
+ </mj-artifact-viewer-panel>
206
+ ```
207
+ …and inject `InteractiveFormApplyService` in the handler.
208
+
209
+ Wired in `ConversationChatAreaComponent` (live chat) and `ArtifactResource`
210
+ (standalone artifact viewing in Explorer).
211
+
181
212
  ## Build
182
213
 
183
214
  ```bash
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=image-artifact-viewer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-artifact-viewer.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/image-artifact-viewer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,62 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { IMAGE_MIME_EXTENSION_MAP, buildImageDownloadFileName, } from '../lib/components/plugins/image-artifact-viewer.component';
3
+ /**
4
+ * Unit tests for the pure helpers exported from the image-artifact viewer
5
+ * plugin. The plugin's Angular component itself can't be rendered under the
6
+ * package's `node`-environment vitest config (no DOM, no TestBed), so the
7
+ * tests focus on the deterministic, side-effect-free logic that the component
8
+ * delegates to — exactly the boundary that has historically caused user-visible
9
+ * bugs (filename sanitization, MIME → extension mapping).
10
+ */
11
+ describe('IMAGE_MIME_EXTENSION_MAP', () => {
12
+ it('covers the MIMEs that the seed Image artifact type advertises', () => {
13
+ // The metadata seed declares ContentType "image/*". These are the
14
+ // common raster MIMEs that Generate Image and uploaded files produce.
15
+ const required = ['image/png', 'image/jpeg', 'image/gif', 'image/webp'];
16
+ for (const mime of required) {
17
+ expect(IMAGE_MIME_EXTENSION_MAP[mime]).toBeTruthy();
18
+ }
19
+ });
20
+ it('returns the canonical short extension for JPEG (jpg, not jpeg)', () => {
21
+ expect(IMAGE_MIME_EXTENSION_MAP['image/jpeg']).toBe('jpg');
22
+ });
23
+ it('is frozen (read-only) so callers cannot mutate the shared map', () => {
24
+ // Object.freeze guarantees runtime immutability — if a future refactor
25
+ // removes the freeze this test will catch it.
26
+ expect(Object.isFrozen(IMAGE_MIME_EXTENSION_MAP)).toBe(true);
27
+ });
28
+ });
29
+ describe('buildImageDownloadFileName', () => {
30
+ it('combines a clean name and the right extension', () => {
31
+ expect(buildImageDownloadFileName('mountain', 'image/png')).toBe('mountain.png');
32
+ });
33
+ it('uses jpg for jpeg even when input is uppercase', () => {
34
+ expect(buildImageDownloadFileName('photo', 'IMAGE/JPEG')).toBe('photo.jpg');
35
+ });
36
+ it('strips characters that are unsafe on common filesystems', () => {
37
+ // Spaces, slashes, colons, and emoji should all be normalized to underscores.
38
+ expect(buildImageDownloadFileName('Generated image 1', 'image/jpeg')).toBe('Generated_image_1.jpg');
39
+ expect(buildImageDownloadFileName('a/b:c\\d', 'image/png')).toBe('a_b_c_d.png');
40
+ });
41
+ it('preserves dots, dashes, and underscores (filesystem-safe)', () => {
42
+ expect(buildImageDownloadFileName('snapshot_v2-final.draft', 'image/png')).toBe('snapshot_v2-final.draft.png');
43
+ });
44
+ it('falls back to "image" when no name is supplied', () => {
45
+ expect(buildImageDownloadFileName(null, 'image/png')).toBe('image.png');
46
+ expect(buildImageDownloadFileName(undefined, 'image/webp')).toBe('image.webp');
47
+ expect(buildImageDownloadFileName('', 'image/gif')).toBe('image.gif');
48
+ });
49
+ it('falls back to "img" extension when the MIME type is missing or unknown', () => {
50
+ expect(buildImageDownloadFileName('thing', null)).toBe('thing.img');
51
+ expect(buildImageDownloadFileName('thing', undefined)).toBe('thing.img');
52
+ expect(buildImageDownloadFileName('thing', '')).toBe('thing.img');
53
+ expect(buildImageDownloadFileName('thing', 'application/json')).toBe('thing.img');
54
+ });
55
+ it('does not double-append the extension when the name already has it', () => {
56
+ // The agent sometimes hands us labels like "Generated image 1.png" — we
57
+ // shouldn't end up with "Generated_image_1.png.png" in the user's downloads.
58
+ expect(buildImageDownloadFileName('photo.png', 'image/png')).toBe('photo.png');
59
+ expect(buildImageDownloadFileName('shot.JPG', 'image/jpeg')).toBe('shot.JPG');
60
+ });
61
+ });
62
+ //# sourceMappingURL=image-artifact-viewer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-artifact-viewer.test.js","sourceRoot":"","sources":["../../src/__tests__/image-artifact-viewer.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, expect } from 'vitest';\nimport {\n IMAGE_MIME_EXTENSION_MAP,\n buildImageDownloadFileName,\n} from '../lib/components/plugins/image-artifact-viewer.component';\n\n/**\n * Unit tests for the pure helpers exported from the image-artifact viewer\n * plugin. The plugin's Angular component itself can't be rendered under the\n * package's `node`-environment vitest config (no DOM, no TestBed), so the\n * tests focus on the deterministic, side-effect-free logic that the component\n * delegates to — exactly the boundary that has historically caused user-visible\n * bugs (filename sanitization, MIME → extension mapping).\n */\n\ndescribe('IMAGE_MIME_EXTENSION_MAP', () => {\n it('covers the MIMEs that the seed Image artifact type advertises', () => {\n // The metadata seed declares ContentType \"image/*\". These are the\n // common raster MIMEs that Generate Image and uploaded files produce.\n const required = ['image/png', 'image/jpeg', 'image/gif', 'image/webp'];\n for (const mime of required) {\n expect(IMAGE_MIME_EXTENSION_MAP[mime]).toBeTruthy();\n }\n });\n\n it('returns the canonical short extension for JPEG (jpg, not jpeg)', () => {\n expect(IMAGE_MIME_EXTENSION_MAP['image/jpeg']).toBe('jpg');\n });\n\n it('is frozen (read-only) so callers cannot mutate the shared map', () => {\n // Object.freeze guarantees runtime immutability — if a future refactor\n // removes the freeze this test will catch it.\n expect(Object.isFrozen(IMAGE_MIME_EXTENSION_MAP)).toBe(true);\n });\n});\n\ndescribe('buildImageDownloadFileName', () => {\n it('combines a clean name and the right extension', () => {\n expect(buildImageDownloadFileName('mountain', 'image/png')).toBe('mountain.png');\n });\n\n it('uses jpg for jpeg even when input is uppercase', () => {\n expect(buildImageDownloadFileName('photo', 'IMAGE/JPEG')).toBe('photo.jpg');\n });\n\n it('strips characters that are unsafe on common filesystems', () => {\n // Spaces, slashes, colons, and emoji should all be normalized to underscores.\n expect(buildImageDownloadFileName('Generated image 1', 'image/jpeg')).toBe('Generated_image_1.jpg');\n expect(buildImageDownloadFileName('a/b:c\\\\d', 'image/png')).toBe('a_b_c_d.png');\n });\n\n it('preserves dots, dashes, and underscores (filesystem-safe)', () => {\n expect(buildImageDownloadFileName('snapshot_v2-final.draft', 'image/png')).toBe(\n 'snapshot_v2-final.draft.png',\n );\n });\n\n it('falls back to \"image\" when no name is supplied', () => {\n expect(buildImageDownloadFileName(null, 'image/png')).toBe('image.png');\n expect(buildImageDownloadFileName(undefined, 'image/webp')).toBe('image.webp');\n expect(buildImageDownloadFileName('', 'image/gif')).toBe('image.gif');\n });\n\n it('falls back to \"img\" extension when the MIME type is missing or unknown', () => {\n expect(buildImageDownloadFileName('thing', null)).toBe('thing.img');\n expect(buildImageDownloadFileName('thing', undefined)).toBe('thing.img');\n expect(buildImageDownloadFileName('thing', '')).toBe('thing.img');\n expect(buildImageDownloadFileName('thing', 'application/json')).toBe('thing.img');\n });\n\n it('does not double-append the extension when the name already has it', () => {\n // The agent sometimes hands us labels like \"Generated image 1.png\" — we\n // shouldn't end up with \"Generated_image_1.png.png\" in the user's downloads.\n expect(buildImageDownloadFileName('photo.png', 'image/png')).toBe('photo.png');\n expect(buildImageDownloadFileName('shot.JPG', 'image/jpeg')).toBe('shot.JPG');\n });\n});\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=interactive-form-apply.service.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactive-form-apply.service.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/interactive-form-apply.service.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,206 @@
1
+ /**
2
+ * End-to-end-ish coverage for the Apply-to-my-form flow.
3
+ *
4
+ * The service is the join point that closes the chat-artifact → action loop:
5
+ * form-aware artifact viewer → applyFormRequested →
6
+ * conversation-chat-area / artifact-resource → ConfirmAndApply →
7
+ * Get Active Form For Entity (action) → Create or Modify (action)
8
+ *
9
+ * These tests mock the dialog, notifications, and the GraphQL action
10
+ * client so we can drive both branches (no-existing → Create; existing →
11
+ * Modify) and the cancellation path, plus the failure surfaces. Without
12
+ * this suite the original "Apply button is wired to nothing" bug would
13
+ * regress silently — the unit tests on the actions wouldn't notice.
14
+ */
15
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
16
+ // ─── Hoisted state buckets the mocks read/write ──────────────────────────
17
+ const hoisted = vi.hoisted(() => ({
18
+ dialogResult: 'apply',
19
+ actionResponses: new Map(),
20
+ actionCalls: [],
21
+ runViewResponses: [],
22
+ notifications: [],
23
+ }));
24
+ // ─── Module mocks ────────────────────────────────────────────────────────
25
+ vi.mock('@angular/core', () => ({
26
+ Injectable: () => (target) => target,
27
+ inject: (token) => {
28
+ // Return the mock singletons by class identity.
29
+ const name = token.name ?? '';
30
+ if (name === 'MJDialogService')
31
+ return mockDialog;
32
+ if (name === 'MJNotificationService')
33
+ return mockNotifications;
34
+ return {};
35
+ },
36
+ }));
37
+ const mockDialog = {
38
+ Open: () => ({
39
+ Result: {
40
+ subscribe: (cb) => {
41
+ cb({ result: hoisted.dialogResult });
42
+ },
43
+ },
44
+ }),
45
+ };
46
+ const mockNotifications = {
47
+ CreateSimpleNotification: (message, type) => {
48
+ hoisted.notifications.push({ message, type });
49
+ },
50
+ };
51
+ vi.mock('@memberjunction/ng-ui-components', () => ({ MJDialogService: class MJDialogService {
52
+ } }));
53
+ vi.mock('@memberjunction/ng-notifications', () => ({ MJNotificationService: class MJNotificationService {
54
+ } }));
55
+ vi.mock('@memberjunction/graphql-dataprovider', () => ({
56
+ GraphQLActionClient: class {
57
+ async RunAction(actionId, params) {
58
+ hoisted.actionCalls.push({ id: actionId, params });
59
+ return hoisted.actionResponses.get(actionId) ?? { Success: false, Message: 'mock: no response set' };
60
+ }
61
+ },
62
+ GraphQLDataProvider: class {
63
+ },
64
+ }));
65
+ vi.mock('@memberjunction/core', async () => {
66
+ const actual = await vi.importActual('@memberjunction/core');
67
+ return {
68
+ ...actual,
69
+ Metadata: { Provider: null },
70
+ LogError: vi.fn(),
71
+ RunView: class {
72
+ async RunView() {
73
+ return hoisted.runViewResponses.shift() ?? { Success: true, Results: [] };
74
+ }
75
+ },
76
+ };
77
+ });
78
+ // ─── Test setup ──────────────────────────────────────────────────────────
79
+ import { InteractiveFormApplyService } from '../services/interactive-form-apply.service';
80
+ function mockProvider(overrides = {}) {
81
+ return {
82
+ EntityByName: () => ({ ID: 'ENT-1', Name: 'MJ: Apps' }),
83
+ CurrentUser: { ID: 'U1', Name: 'Test' },
84
+ ExecuteGQL: () => Promise.resolve({}), // marks it as a GraphQL provider
85
+ ...overrides,
86
+ };
87
+ }
88
+ function spec(over = {}) {
89
+ return { name: 'Form', componentRole: 'form', location: 'embedded', code: '() => null', ...over };
90
+ }
91
+ beforeEach(() => {
92
+ hoisted.dialogResult = 'apply';
93
+ hoisted.actionResponses.clear();
94
+ hoisted.actionCalls.length = 0;
95
+ hoisted.runViewResponses.length = 0;
96
+ hoisted.notifications.length = 0;
97
+ });
98
+ describe('InteractiveFormApplyService', () => {
99
+ it('returns failure when no metadata provider is available', async () => {
100
+ const svc = new InteractiveFormApplyService();
101
+ // No provider — neither passed nor on Metadata.Provider.
102
+ const result = await svc.ConfirmAndApply(spec(), 'MJ: Apps');
103
+ expect(result.Success).toBe(false);
104
+ expect(result.Message).toMatch(/No metadata provider/);
105
+ });
106
+ it('returns failure when the declared entity is not registered', async () => {
107
+ const svc = new InteractiveFormApplyService();
108
+ const provider = mockProvider({ EntityByName: () => undefined });
109
+ const result = await svc.ConfirmAndApply(spec(), 'MJ: NotAnEntity', provider);
110
+ expect(result.Success).toBe(false);
111
+ expect(result.Message).toMatch(/not registered/);
112
+ });
113
+ it('cancellation by user yields a friendly failure result, no action invoked', async () => {
114
+ hoisted.dialogResult = 'cancel';
115
+ // Seed action-id lookup so the path past dialog is reachable in case the
116
+ // implementation order changes; with dialog returning 'cancel' the
117
+ // Create action should never be called.
118
+ hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-GET-ACTIVE' }] });
119
+ hoisted.actionResponses.set('ACT-GET-ACTIVE', {
120
+ Success: true,
121
+ Message: JSON.stringify({ Active: null, Variants: [] }),
122
+ });
123
+ const svc = new InteractiveFormApplyService();
124
+ const result = await svc.ConfirmAndApply(spec(), 'MJ: Apps', mockProvider());
125
+ expect(result.Success).toBe(false);
126
+ expect(result.Message).toMatch(/Cancelled/);
127
+ // Only Get Active Form should have been called (to populate dialog text);
128
+ // Create / Modify should NOT have been called.
129
+ const calls = hoisted.actionCalls.map(c => c.id);
130
+ expect(calls.filter(id => id !== 'ACT-GET-ACTIVE')).toEqual([]);
131
+ });
132
+ it('no existing override → calls Create Interactive Form', async () => {
133
+ // RunView lookups: each call resolves the next action ID.
134
+ hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-GET-ACTIVE' }] });
135
+ hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-CREATE' }] });
136
+ hoisted.actionResponses.set('ACT-GET-ACTIVE', {
137
+ Success: true,
138
+ Message: JSON.stringify({ Active: null, Variants: [] }),
139
+ });
140
+ hoisted.actionResponses.set('ACT-CREATE', {
141
+ Success: true,
142
+ Message: JSON.stringify({ ComponentID: 'NEW-COMP', OverrideID: 'NEW-OVER', Version: '1.0.0' }),
143
+ });
144
+ const svc = new InteractiveFormApplyService();
145
+ const result = await svc.ConfirmAndApply(spec({ name: 'CompactForm' }), 'MJ: Apps', mockProvider());
146
+ expect(result.Success).toBe(true);
147
+ expect(result.Mode).toBe('create');
148
+ expect(result.OverrideID).toBe('NEW-OVER');
149
+ expect(result.Version).toBe('1.0.0');
150
+ const calls = hoisted.actionCalls.map(c => c.id);
151
+ expect(calls).toEqual(['ACT-GET-ACTIVE', 'ACT-CREATE']);
152
+ // Success notification surfaced.
153
+ expect(hoisted.notifications.some(n => n.type === 'success')).toBe(true);
154
+ });
155
+ it('existing Active override → calls Modify Interactive Form (Pending sibling produced)', async () => {
156
+ hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-GET-ACTIVE' }] });
157
+ hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-MODIFY' }] });
158
+ hoisted.actionResponses.set('ACT-GET-ACTIVE', {
159
+ Success: true,
160
+ Message: JSON.stringify({
161
+ Active: { OverrideID: 'OVER-EXISTING', ComponentID: 'COMP-EXISTING', ComponentVersion: '1.0.0' },
162
+ Variants: [],
163
+ }),
164
+ });
165
+ hoisted.actionResponses.set('ACT-MODIFY', {
166
+ Success: true,
167
+ Message: JSON.stringify({ Mode: 'new-version', ComponentID: 'NEW-COMP', OverrideID: 'NEW-OVER', Version: '1.1.0' }),
168
+ });
169
+ const svc = new InteractiveFormApplyService();
170
+ const result = await svc.ConfirmAndApply(spec(), 'MJ: Apps', mockProvider());
171
+ expect(result.Success).toBe(true);
172
+ expect(result.Mode).toBe('modify-new-version');
173
+ expect(result.Version).toBe('1.1.0');
174
+ const calls = hoisted.actionCalls.map(c => c.id);
175
+ expect(calls).toEqual(['ACT-GET-ACTIVE', 'ACT-MODIFY']);
176
+ });
177
+ it('Get Active failure short-circuits with an error', async () => {
178
+ hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-GET-ACTIVE' }] });
179
+ hoisted.actionResponses.set('ACT-GET-ACTIVE', {
180
+ Success: false,
181
+ Message: 'DB unavailable',
182
+ });
183
+ const svc = new InteractiveFormApplyService();
184
+ const result = await svc.ConfirmAndApply(spec(), 'MJ: Apps', mockProvider());
185
+ expect(result.Success).toBe(false);
186
+ expect(result.Message).toMatch(/Could not check for existing override/);
187
+ });
188
+ it('failure on the Create action surfaces the error notification', async () => {
189
+ hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-GET-ACTIVE' }] });
190
+ hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-CREATE' }] });
191
+ hoisted.actionResponses.set('ACT-GET-ACTIVE', {
192
+ Success: true,
193
+ Message: JSON.stringify({ Active: null, Variants: [] }),
194
+ });
195
+ hoisted.actionResponses.set('ACT-CREATE', {
196
+ Success: false,
197
+ ResultCode: 'LINT_FAILED',
198
+ Message: 'Spec failed linting.',
199
+ });
200
+ const svc = new InteractiveFormApplyService();
201
+ const result = await svc.ConfirmAndApply(spec(), 'MJ: Apps', mockProvider());
202
+ expect(result.Success).toBe(false);
203
+ expect(hoisted.notifications.some(n => n.type === 'error')).toBe(true);
204
+ });
205
+ });
206
+ //# sourceMappingURL=interactive-form-apply.service.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactive-form-apply.service.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/interactive-form-apply.service.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * End-to-end-ish coverage for the Apply-to-my-form flow.\n *\n * The service is the join point that closes the chat-artifact → action loop:\n * form-aware artifact viewer → applyFormRequested →\n * conversation-chat-area / artifact-resource → ConfirmAndApply →\n * Get Active Form For Entity (action) → Create or Modify (action)\n *\n * These tests mock the dialog, notifications, and the GraphQL action\n * client so we can drive both branches (no-existing → Create; existing →\n * Modify) and the cancellation path, plus the failure surfaces. Without\n * this suite the original \"Apply button is wired to nothing\" bug would\n * regress silently — the unit tests on the actions wouldn't notice.\n */\nimport { describe, it, expect, vi, beforeEach } from 'vitest';\nimport type { ComponentSpec } from '@memberjunction/interactive-component-types';\n\n// ─── Hoisted state buckets the mocks read/write ──────────────────────────\n\nconst hoisted = vi.hoisted(() => ({\n dialogResult: 'apply' as 'apply' | 'cancel',\n actionResponses: new Map<string, { Success: boolean; Message?: string; ResultCode?: string }>(),\n actionCalls: [] as Array<{ id: string; params: unknown }>,\n runViewResponses: [] as Array<{ Success: boolean; Results: Array<{ ID: string }>; ErrorMessage?: string }>,\n notifications: [] as Array<{ message: string; type: string }>,\n}));\n\n// ─── Module mocks ────────────────────────────────────────────────────────\n\nvi.mock('@angular/core', () => ({\n Injectable: () => (target: Function) => target,\n inject: (token: { Instance?: unknown } | typeof Object) => {\n // Return the mock singletons by class identity.\n const name = (token as { name?: string }).name ?? '';\n if (name === 'MJDialogService') return mockDialog;\n if (name === 'MJNotificationService') return mockNotifications;\n return {};\n },\n}));\n\nconst mockDialog = {\n Open: () => ({\n Result: {\n subscribe: (cb: (r: { result: string }) => void) => {\n cb({ result: hoisted.dialogResult });\n },\n },\n }),\n};\n\nconst mockNotifications = {\n CreateSimpleNotification: (message: string, type: string) => {\n hoisted.notifications.push({ message, type });\n },\n};\n\nvi.mock('@memberjunction/ng-ui-components', () => ({ MJDialogService: class MJDialogService {} }));\nvi.mock('@memberjunction/ng-notifications', () => ({ MJNotificationService: class MJNotificationService {} }));\n\nvi.mock('@memberjunction/graphql-dataprovider', () => ({\n GraphQLActionClient: class {\n async RunAction(actionId: string, params: unknown) {\n hoisted.actionCalls.push({ id: actionId, params });\n return hoisted.actionResponses.get(actionId) ?? { Success: false, Message: 'mock: no response set' };\n }\n },\n GraphQLDataProvider: class {},\n}));\n\nvi.mock('@memberjunction/core', async () => {\n const actual = await vi.importActual<Record<string, unknown>>('@memberjunction/core');\n return {\n ...actual,\n Metadata: { Provider: null },\n LogError: vi.fn(),\n RunView: class {\n async RunView() {\n return hoisted.runViewResponses.shift() ?? { Success: true, Results: [] };\n }\n },\n };\n});\n\n// ─── Test setup ──────────────────────────────────────────────────────────\n\nimport { InteractiveFormApplyService } from '../services/interactive-form-apply.service';\n\nfunction mockProvider(overrides: Partial<{ EntityByName: () => unknown; CurrentUser: unknown }> = {}) {\n return {\n EntityByName: () => ({ ID: 'ENT-1', Name: 'MJ: Apps' }),\n CurrentUser: { ID: 'U1', Name: 'Test' },\n ExecuteGQL: () => Promise.resolve({}), // marks it as a GraphQL provider\n ...overrides,\n } as unknown as Parameters<InteractiveFormApplyService['ConfirmAndApply']>[2];\n}\n\nfunction spec(over: Partial<ComponentSpec> = {}): ComponentSpec {\n return { name: 'Form', componentRole: 'form', location: 'embedded', code: '() => null', ...over } as ComponentSpec;\n}\n\nbeforeEach(() => {\n hoisted.dialogResult = 'apply';\n hoisted.actionResponses.clear();\n hoisted.actionCalls.length = 0;\n hoisted.runViewResponses.length = 0;\n hoisted.notifications.length = 0;\n});\n\ndescribe('InteractiveFormApplyService', () => {\n\n it('returns failure when no metadata provider is available', async () => {\n const svc = new InteractiveFormApplyService();\n // No provider — neither passed nor on Metadata.Provider.\n const result = await svc.ConfirmAndApply(spec(), 'MJ: Apps');\n expect(result.Success).toBe(false);\n expect(result.Message).toMatch(/No metadata provider/);\n });\n\n it('returns failure when the declared entity is not registered', async () => {\n const svc = new InteractiveFormApplyService();\n const provider = mockProvider({ EntityByName: () => undefined });\n const result = await svc.ConfirmAndApply(spec(), 'MJ: NotAnEntity', provider);\n expect(result.Success).toBe(false);\n expect(result.Message).toMatch(/not registered/);\n });\n\n it('cancellation by user yields a friendly failure result, no action invoked', async () => {\n hoisted.dialogResult = 'cancel';\n // Seed action-id lookup so the path past dialog is reachable in case the\n // implementation order changes; with dialog returning 'cancel' the\n // Create action should never be called.\n hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-GET-ACTIVE' }] });\n hoisted.actionResponses.set('ACT-GET-ACTIVE', {\n Success: true,\n Message: JSON.stringify({ Active: null, Variants: [] }),\n });\n\n const svc = new InteractiveFormApplyService();\n const result = await svc.ConfirmAndApply(spec(), 'MJ: Apps', mockProvider());\n expect(result.Success).toBe(false);\n expect(result.Message).toMatch(/Cancelled/);\n // Only Get Active Form should have been called (to populate dialog text);\n // Create / Modify should NOT have been called.\n const calls = hoisted.actionCalls.map(c => c.id);\n expect(calls.filter(id => id !== 'ACT-GET-ACTIVE')).toEqual([]);\n });\n\n it('no existing override → calls Create Interactive Form', async () => {\n // RunView lookups: each call resolves the next action ID.\n hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-GET-ACTIVE' }] });\n hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-CREATE' }] });\n hoisted.actionResponses.set('ACT-GET-ACTIVE', {\n Success: true,\n Message: JSON.stringify({ Active: null, Variants: [] }),\n });\n hoisted.actionResponses.set('ACT-CREATE', {\n Success: true,\n Message: JSON.stringify({ ComponentID: 'NEW-COMP', OverrideID: 'NEW-OVER', Version: '1.0.0' }),\n });\n\n const svc = new InteractiveFormApplyService();\n const result = await svc.ConfirmAndApply(spec({ name: 'CompactForm' }), 'MJ: Apps', mockProvider());\n\n expect(result.Success).toBe(true);\n expect(result.Mode).toBe('create');\n expect(result.OverrideID).toBe('NEW-OVER');\n expect(result.Version).toBe('1.0.0');\n const calls = hoisted.actionCalls.map(c => c.id);\n expect(calls).toEqual(['ACT-GET-ACTIVE', 'ACT-CREATE']);\n // Success notification surfaced.\n expect(hoisted.notifications.some(n => n.type === 'success')).toBe(true);\n });\n\n it('existing Active override → calls Modify Interactive Form (Pending sibling produced)', async () => {\n hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-GET-ACTIVE' }] });\n hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-MODIFY' }] });\n hoisted.actionResponses.set('ACT-GET-ACTIVE', {\n Success: true,\n Message: JSON.stringify({\n Active: { OverrideID: 'OVER-EXISTING', ComponentID: 'COMP-EXISTING', ComponentVersion: '1.0.0' },\n Variants: [],\n }),\n });\n hoisted.actionResponses.set('ACT-MODIFY', {\n Success: true,\n Message: JSON.stringify({ Mode: 'new-version', ComponentID: 'NEW-COMP', OverrideID: 'NEW-OVER', Version: '1.1.0' }),\n });\n\n const svc = new InteractiveFormApplyService();\n const result = await svc.ConfirmAndApply(spec(), 'MJ: Apps', mockProvider());\n\n expect(result.Success).toBe(true);\n expect(result.Mode).toBe('modify-new-version');\n expect(result.Version).toBe('1.1.0');\n const calls = hoisted.actionCalls.map(c => c.id);\n expect(calls).toEqual(['ACT-GET-ACTIVE', 'ACT-MODIFY']);\n });\n\n it('Get Active failure short-circuits with an error', async () => {\n hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-GET-ACTIVE' }] });\n hoisted.actionResponses.set('ACT-GET-ACTIVE', {\n Success: false,\n Message: 'DB unavailable',\n });\n\n const svc = new InteractiveFormApplyService();\n const result = await svc.ConfirmAndApply(spec(), 'MJ: Apps', mockProvider());\n expect(result.Success).toBe(false);\n expect(result.Message).toMatch(/Could not check for existing override/);\n });\n\n it('failure on the Create action surfaces the error notification', async () => {\n hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-GET-ACTIVE' }] });\n hoisted.runViewResponses.push({ Success: true, Results: [{ ID: 'ACT-CREATE' }] });\n hoisted.actionResponses.set('ACT-GET-ACTIVE', {\n Success: true,\n Message: JSON.stringify({ Active: null, Variants: [] }),\n });\n hoisted.actionResponses.set('ACT-CREATE', {\n Success: false,\n ResultCode: 'LINT_FAILED',\n Message: 'Spec failed linting.',\n });\n\n const svc = new InteractiveFormApplyService();\n const result = await svc.ConfirmAndApply(spec(), 'MJ: Apps', mockProvider());\n expect(result.Success).toBe(false);\n expect(hoisted.notifications.some(n => n.type === 'error')).toBe(true);\n });\n});\n"]}
@@ -17,17 +17,19 @@ import * as i14 from "./components/file-artifact-toolbar.component";
17
17
  import * as i15 from "./components/plugins/pdf-artifact-viewer.component";
18
18
  import * as i16 from "./components/plugins/xlsx-artifact-viewer.component";
19
19
  import * as i17 from "./components/plugins/docx-artifact-viewer.component";
20
- import * as i18 from "@angular/common";
21
- import * as i19 from "@angular/forms";
22
- import * as i20 from "@memberjunction/ng-markdown";
23
- import * as i21 from "@memberjunction/ng-code-editor";
24
- import * as i22 from "@memberjunction/ng-react";
25
- import * as i23 from "@memberjunction/ng-notifications";
26
- import * as i24 from "@memberjunction/ng-query-viewer";
27
- import * as i25 from "@memberjunction/ng-shared-generic";
28
- import * as i26 from "@memberjunction/ng-trees";
29
- import * as i27 from "./components/plugins/component-feedback-panel/component-feedback-panel.component";
30
- import * as i28 from "ag-grid-angular";
20
+ import * as i18 from "./components/plugins/image-artifact-viewer.component";
21
+ import * as i19 from "@angular/common";
22
+ import * as i20 from "@angular/forms";
23
+ import * as i21 from "@memberjunction/ng-markdown";
24
+ import * as i22 from "@memberjunction/ng-code-editor";
25
+ import * as i23 from "@memberjunction/ng-react";
26
+ import * as i24 from "@memberjunction/ng-notifications";
27
+ import * as i25 from "@memberjunction/ng-query-viewer";
28
+ import * as i26 from "@memberjunction/ng-shared-generic";
29
+ import * as i27 from "@memberjunction/ng-trees";
30
+ import * as i28 from "@memberjunction/ng-base-forms";
31
+ import * as i29 from "./components/plugins/component-feedback-panel/component-feedback-panel.component";
32
+ import * as i30 from "ag-grid-angular";
31
33
  /**
32
34
  * Module for artifact viewer plugin system.
33
35
  * Provides components for viewing different types of artifacts (JSON, Code, Markdown, HTML, SVG, Components).
@@ -39,7 +41,7 @@ export declare class ArtifactsModule {
39
41
  private adapter;
40
42
  constructor(adapter: AngularAdapterService);
41
43
  static ɵfac: i0.ɵɵFactoryDeclaration<ArtifactsModule, never>;
42
- static ɵmod: i0.ɵɵNgModuleDeclaration<ArtifactsModule, [typeof i1.ArtifactTypePluginViewerComponent, typeof i2.ArtifactViewerPanelComponent, typeof i3.ArtifactVersionHistoryComponent, typeof i4.ArtifactMessageCardComponent, typeof i5.JsonArtifactViewerComponent, typeof i6.CodeArtifactViewerComponent, typeof i7.MarkdownArtifactViewerComponent, typeof i8.HtmlArtifactViewerComponent, typeof i9.SvgArtifactViewerComponent, typeof i10.ComponentArtifactViewerComponent, typeof i11.DataArtifactViewerComponent, typeof i12.SaveQueryPanelComponent, typeof i13.DataRequirementsViewerComponent, typeof i14.FileArtifactToolbarComponent, typeof i15.PdfArtifactViewerComponent, typeof i16.XlsxArtifactViewerComponent, typeof i17.DocxArtifactViewerComponent], [typeof i18.CommonModule, typeof i19.FormsModule, typeof i20.MarkdownModule, typeof i21.CodeEditorModule, typeof i22.MJReactModule, typeof i23.MJNotificationsModule, typeof i24.QueryViewerModule, typeof i25.SharedGenericModule, typeof i26.NgTreesModule, typeof i27.ComponentFeedbackPanelComponent, typeof i28.AgGridModule], [typeof i1.ArtifactTypePluginViewerComponent, typeof i2.ArtifactViewerPanelComponent, typeof i3.ArtifactVersionHistoryComponent, typeof i4.ArtifactMessageCardComponent, typeof i5.JsonArtifactViewerComponent, typeof i6.CodeArtifactViewerComponent, typeof i7.MarkdownArtifactViewerComponent, typeof i8.HtmlArtifactViewerComponent, typeof i9.SvgArtifactViewerComponent, typeof i10.ComponentArtifactViewerComponent, typeof i11.DataArtifactViewerComponent, typeof i14.FileArtifactToolbarComponent, typeof i15.PdfArtifactViewerComponent, typeof i16.XlsxArtifactViewerComponent, typeof i17.DocxArtifactViewerComponent]>;
44
+ static ɵmod: i0.ɵɵNgModuleDeclaration<ArtifactsModule, [typeof i1.ArtifactTypePluginViewerComponent, typeof i2.ArtifactViewerPanelComponent, typeof i3.ArtifactVersionHistoryComponent, typeof i4.ArtifactMessageCardComponent, typeof i5.JsonArtifactViewerComponent, typeof i6.CodeArtifactViewerComponent, typeof i7.MarkdownArtifactViewerComponent, typeof i8.HtmlArtifactViewerComponent, typeof i9.SvgArtifactViewerComponent, typeof i10.ComponentArtifactViewerComponent, typeof i11.DataArtifactViewerComponent, typeof i12.SaveQueryPanelComponent, typeof i13.DataRequirementsViewerComponent, typeof i14.FileArtifactToolbarComponent, typeof i15.PdfArtifactViewerComponent, typeof i16.XlsxArtifactViewerComponent, typeof i17.DocxArtifactViewerComponent, typeof i18.ImageArtifactViewerComponent], [typeof i19.CommonModule, typeof i20.FormsModule, typeof i21.MarkdownModule, typeof i22.CodeEditorModule, typeof i23.MJReactModule, typeof i24.MJNotificationsModule, typeof i25.QueryViewerModule, typeof i26.SharedGenericModule, typeof i27.NgTreesModule, typeof i28.BaseFormsModule, typeof i29.ComponentFeedbackPanelComponent, typeof i30.AgGridModule], [typeof i1.ArtifactTypePluginViewerComponent, typeof i2.ArtifactViewerPanelComponent, typeof i3.ArtifactVersionHistoryComponent, typeof i4.ArtifactMessageCardComponent, typeof i5.JsonArtifactViewerComponent, typeof i6.CodeArtifactViewerComponent, typeof i7.MarkdownArtifactViewerComponent, typeof i8.HtmlArtifactViewerComponent, typeof i9.SvgArtifactViewerComponent, typeof i10.ComponentArtifactViewerComponent, typeof i11.DataArtifactViewerComponent, typeof i14.FileArtifactToolbarComponent, typeof i15.PdfArtifactViewerComponent, typeof i16.XlsxArtifactViewerComponent, typeof i17.DocxArtifactViewerComponent, typeof i18.ImageArtifactViewerComponent]>;
43
45
  static ɵinj: i0.ɵɵInjectorDeclaration<ArtifactsModule>;
44
46
  }
45
47
  //# sourceMappingURL=artifacts.module.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"artifacts.module.d.ts","sourceRoot":"","sources":["../../src/lib/artifacts.module.ts"],"names":[],"mappings":"AAQA,OAAO,EAAiB,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BhF;;;;;;GAMG;AACH,qBAsEa,eAAe;IACd,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,qBAAqB;yCADvC,eAAe;0CAAf,eAAe;0CAAf,eAAe;CAsB3B"}
1
+ {"version":3,"file":"artifacts.module.d.ts","sourceRoot":"","sources":["../../src/lib/artifacts.module.ts"],"names":[],"mappings":"AAQA,OAAO,EAAiB,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkChF;;;;;;GAMG;AACH,qBAyEa,eAAe;IACd,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,qBAAqB;yCADvC,eAAe;0CAAf,eAAe;0CAAf,eAAe;CAuB3B"}
@@ -10,6 +10,9 @@ import { MJNotificationsModule } from '@memberjunction/ng-notifications';
10
10
  import { QueryViewerModule } from '@memberjunction/ng-query-viewer';
11
11
  import { SharedGenericModule } from '@memberjunction/ng-shared-generic';
12
12
  import { NgTreesModule } from '@memberjunction/ng-trees';
13
+ // BaseFormsModule supplies `<mj-interactive-form>` for the form-aware
14
+ // component-artifact viewer branch (componentRole === 'form').
15
+ import { BaseFormsModule } from '@memberjunction/ng-base-forms';
13
16
  // Import plugin components (note: base component is abstract and NOT declared)
14
17
  import { JsonArtifactViewerComponent } from './components/plugins/json-artifact-viewer.component';
15
18
  import { CodeArtifactViewerComponent } from './components/plugins/code-artifact-viewer.component';
@@ -26,6 +29,7 @@ import { FileArtifactToolbarComponent } from './components/file-artifact-toolbar
26
29
  import { PdfArtifactViewerComponent } from './components/plugins/pdf-artifact-viewer.component';
27
30
  import { XlsxArtifactViewerComponent } from './components/plugins/xlsx-artifact-viewer.component';
28
31
  import { DocxArtifactViewerComponent } from './components/plugins/docx-artifact-viewer.component';
32
+ import { ImageArtifactViewerComponent } from './components/plugins/image-artifact-viewer.component';
29
33
  // Import artifact type plugin viewer component
30
34
  import { ArtifactTypePluginViewerComponent } from './components/artifact-type-plugin-viewer.component';
31
35
  import { ArtifactVersionHistoryComponent } from './components/artifact-version-history.component';
@@ -57,6 +61,7 @@ export class ArtifactsModule {
57
61
  PdfArtifactViewerComponent,
58
62
  XlsxArtifactViewerComponent,
59
63
  DocxArtifactViewerComponent,
64
+ ImageArtifactViewerComponent,
60
65
  ];
61
66
  // PERF: Eagerly start downloading React, ReactDOM, and Babel from CDN in the background.
62
67
  // By the time a user opens an interactive component artifact, the scripts will already
@@ -74,6 +79,7 @@ export class ArtifactsModule {
74
79
  QueryViewerModule,
75
80
  SharedGenericModule,
76
81
  NgTreesModule,
82
+ BaseFormsModule,
77
83
  ComponentFeedbackPanelComponent,
78
84
  AgGridModule] });
79
85
  }
@@ -103,6 +109,7 @@ export class ArtifactsModule {
103
109
  PdfArtifactViewerComponent,
104
110
  XlsxArtifactViewerComponent,
105
111
  DocxArtifactViewerComponent,
112
+ ImageArtifactViewerComponent,
106
113
  ],
107
114
  imports: [
108
115
  CommonModule,
@@ -114,6 +121,7 @@ export class ArtifactsModule {
114
121
  QueryViewerModule,
115
122
  SharedGenericModule,
116
123
  NgTreesModule,
124
+ BaseFormsModule,
117
125
  ComponentFeedbackPanelComponent,
118
126
  AgGridModule,
119
127
  ],
@@ -137,6 +145,7 @@ export class ArtifactsModule {
137
145
  PdfArtifactViewerComponent,
138
146
  XlsxArtifactViewerComponent,
139
147
  DocxArtifactViewerComponent,
148
+ ImageArtifactViewerComponent,
140
149
  ],
141
150
  providers: [
142
151
  // Plugins are registered via @RegisterClass decorator on component classes, no providers needed
@@ -165,7 +174,8 @@ export class ArtifactsModule {
165
174
  FileArtifactToolbarComponent,
166
175
  PdfArtifactViewerComponent,
167
176
  XlsxArtifactViewerComponent,
168
- DocxArtifactViewerComponent], imports: [CommonModule,
177
+ DocxArtifactViewerComponent,
178
+ ImageArtifactViewerComponent], imports: [CommonModule,
169
179
  FormsModule,
170
180
  MarkdownModule,
171
181
  CodeEditorModule,
@@ -174,6 +184,7 @@ export class ArtifactsModule {
174
184
  QueryViewerModule,
175
185
  SharedGenericModule,
176
186
  NgTreesModule,
187
+ BaseFormsModule,
177
188
  ComponentFeedbackPanelComponent,
178
189
  AgGridModule], exports: [
179
190
  // Export artifact type plugin viewer
@@ -194,5 +205,6 @@ export class ArtifactsModule {
194
205
  FileArtifactToolbarComponent,
195
206
  PdfArtifactViewerComponent,
196
207
  XlsxArtifactViewerComponent,
197
- DocxArtifactViewerComponent] }); })();
208
+ DocxArtifactViewerComponent,
209
+ ImageArtifactViewerComponent] }); })();
198
210
  //# sourceMappingURL=artifacts.module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"artifacts.module.js","sourceRoot":"","sources":["../../src/lib/artifacts.module.ts"],"names":[],"mappings":"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","sourcesContent":["import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { MarkdownModule } from '@memberjunction/ng-markdown';\nimport { AgGridModule } from 'ag-grid-angular';\n\n// Import MJ modules\nimport { CodeEditorModule } from '@memberjunction/ng-code-editor';\nimport { MJReactModule, AngularAdapterService } from '@memberjunction/ng-react';\nimport { MJNotificationsModule } from '@memberjunction/ng-notifications';\nimport { QueryViewerModule } from '@memberjunction/ng-query-viewer';\nimport { SharedGenericModule } from '@memberjunction/ng-shared-generic';\nimport { NgTreesModule } from '@memberjunction/ng-trees';\n\n// Import plugin components (note: base component is abstract and NOT declared)\nimport { JsonArtifactViewerComponent } from './components/plugins/json-artifact-viewer.component';\nimport { CodeArtifactViewerComponent } from './components/plugins/code-artifact-viewer.component';\nimport { MarkdownArtifactViewerComponent } from './components/plugins/markdown-artifact-viewer.component';\nimport { HtmlArtifactViewerComponent } from './components/plugins/html-artifact-viewer.component';\nimport { SvgArtifactViewerComponent } from './components/plugins/svg-artifact-viewer.component';\nimport { ComponentArtifactViewerComponent } from './components/plugins/component-artifact-viewer.component';\nimport { DataArtifactViewerComponent } from './components/plugins/data-artifact-viewer.component';\nimport { SaveQueryPanelComponent } from './components/plugins/save-query-dialog.component';\nimport { DataRequirementsViewerComponent } from './components/plugins/data-requirements-viewer/data-requirements-viewer.component';\nimport { ComponentFeedbackPanelComponent } from './components/plugins/component-feedback-panel/component-feedback-panel.component';\n\n// File viewer plugins\nimport { FileArtifactToolbarComponent } from './components/file-artifact-toolbar.component';\nimport { PdfArtifactViewerComponent } from './components/plugins/pdf-artifact-viewer.component';\nimport { XlsxArtifactViewerComponent } from './components/plugins/xlsx-artifact-viewer.component';\nimport { DocxArtifactViewerComponent } from './components/plugins/docx-artifact-viewer.component';\n\n// Import artifact type plugin viewer component\nimport { ArtifactTypePluginViewerComponent } from './components/artifact-type-plugin-viewer.component';\nimport { ArtifactVersionHistoryComponent } from './components/artifact-version-history.component';\nimport { ArtifactViewerPanelComponent } from './components/artifact-viewer-panel.component';\nimport { ArtifactMessageCardComponent } from './components/artifact-message-card.component';\n\n/**\n * Module for artifact viewer plugin system.\n * Provides components for viewing different types of artifacts (JSON, Code, Markdown, HTML, SVG, Components).\n *\n * Plugins are automatically registered via @RegisterClass decorator and can be instantiated\n * using MJGlobal.Instance.ClassFactory.CreateInstance('PluginClassName').\n */\n@NgModule({\n declarations: [\n // Artifact type plugin viewer (loads appropriate plugin based on DriverClass)\n ArtifactTypePluginViewerComponent,\n\n // Artifact viewer UI components\n ArtifactViewerPanelComponent,\n ArtifactVersionHistoryComponent,\n ArtifactMessageCardComponent,\n\n // Plugin components\n JsonArtifactViewerComponent,\n CodeArtifactViewerComponent,\n MarkdownArtifactViewerComponent,\n HtmlArtifactViewerComponent,\n SvgArtifactViewerComponent,\n ComponentArtifactViewerComponent,\n DataArtifactViewerComponent,\n SaveQueryPanelComponent,\n\n // Custom tab components (used by plugins via dynamic component tabs)\n DataRequirementsViewerComponent,\n\n // File viewer toolbar and plugins\n FileArtifactToolbarComponent,\n PdfArtifactViewerComponent,\n XlsxArtifactViewerComponent,\n DocxArtifactViewerComponent,\n ],\n imports: [\n CommonModule,\n FormsModule,\n MarkdownModule,\n CodeEditorModule,\n MJReactModule,\n MJNotificationsModule,\n QueryViewerModule,\n SharedGenericModule,\n NgTreesModule,\n ComponentFeedbackPanelComponent,\n AgGridModule,\n ],\n exports: [\n // Export artifact type plugin viewer\n ArtifactTypePluginViewerComponent,\n\n // Export artifact viewer UI components\n ArtifactViewerPanelComponent,\n ArtifactVersionHistoryComponent,\n ArtifactMessageCardComponent,\n\n // Export plugin components\n JsonArtifactViewerComponent,\n CodeArtifactViewerComponent,\n MarkdownArtifactViewerComponent,\n HtmlArtifactViewerComponent,\n SvgArtifactViewerComponent,\n ComponentArtifactViewerComponent,\n DataArtifactViewerComponent,\n\n // File viewer toolbar and plugins\n FileArtifactToolbarComponent,\n PdfArtifactViewerComponent,\n XlsxArtifactViewerComponent,\n DocxArtifactViewerComponent,\n ],\n providers: [\n // Plugins are registered via @RegisterClass decorator on component classes, no providers needed\n ]\n})\nexport class ArtifactsModule {\n constructor(private adapter: AngularAdapterService) {\n // Ensure plugin components are registered on module load by referencing their classes\n // The @RegisterClass decorator on each component handles the actual registration with MJGlobal\n [\n JsonArtifactViewerComponent,\n CodeArtifactViewerComponent,\n MarkdownArtifactViewerComponent,\n HtmlArtifactViewerComponent,\n SvgArtifactViewerComponent,\n ComponentArtifactViewerComponent,\n DataArtifactViewerComponent,\n PdfArtifactViewerComponent,\n XlsxArtifactViewerComponent,\n DocxArtifactViewerComponent,\n ];\n\n // PERF: Eagerly start downloading React, ReactDOM, and Babel from CDN in the background.\n // By the time a user opens an interactive component artifact, the scripts will already\n // be cached. The adapter.preload() is non-blocking and deduplicates with initialize().\n this.adapter.preload();\n }\n}\n"]}
1
+ {"version":3,"file":"artifacts.module.js","sourceRoot":"","sources":["../../src/lib/artifacts.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,oBAAoB;AACpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,aAAa,EAAyB,MAAM,0BAA0B,CAAC;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,sEAAsE;AACtE,+DAA+D;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,+EAA+E;AAC/E,OAAO,EAAE,2BAA2B,EAAE,MAAM,qDAAqD,CAAC;AAClG,OAAO,EAAE,2BAA2B,EAAE,MAAM,qDAAqD,CAAC;AAClG,OAAO,EAAE,+BAA+B,EAAE,MAAM,yDAAyD,CAAC;AAC1G,OAAO,EAAE,2BAA2B,EAAE,MAAM,qDAAqD,CAAC;AAClG,OAAO,EAAE,0BAA0B,EAAE,MAAM,oDAAoD,CAAC;AAChG,OAAO,EAAE,gCAAgC,EAAE,MAAM,0DAA0D,CAAC;AAC5G,OAAO,EAAE,2BAA2B,EAAE,MAAM,qDAAqD,CAAC;AAClG,OAAO,EAAE,uBAAuB,EAAE,MAAM,kDAAkD,CAAC;AAC3F,OAAO,EAAE,+BAA+B,EAAE,MAAM,kFAAkF,CAAC;AACnI,OAAO,EAAE,+BAA+B,EAAE,MAAM,kFAAkF,CAAC;AAEnI,sBAAsB;AACtB,OAAO,EAAE,4BAA4B,EAAE,MAAM,8CAA8C,CAAC;AAC5F,OAAO,EAAE,0BAA0B,EAAE,MAAM,oDAAoD,CAAC;AAChG,OAAO,EAAE,2BAA2B,EAAE,MAAM,qDAAqD,CAAC;AAClG,OAAO,EAAE,2BAA2B,EAAE,MAAM,qDAAqD,CAAC;AAClG,OAAO,EAAE,4BAA4B,EAAE,MAAM,sDAAsD,CAAC;AAEpG,+CAA+C;AAC/C,OAAO,EAAE,iCAAiC,EAAE,MAAM,oDAAoD,CAAC;AACvG,OAAO,EAAE,+BAA+B,EAAE,MAAM,iDAAiD,CAAC;AAClG,OAAO,EAAE,4BAA4B,EAAE,MAAM,8CAA8C,CAAC;AAC5F,OAAO,EAAE,4BAA4B,EAAE,MAAM,8CAA8C,CAAC;;;AAE5F;;;;;;GAMG;AA0EH,MAAM,OAAO,eAAe;IACN;IAApB,YAAoB,OAA8B;QAA9B,YAAO,GAAP,OAAO,CAAuB;QAChD,sFAAsF;QACtF,+FAA+F;QAC/F;YACE,2BAA2B;YAC3B,2BAA2B;YAC3B,+BAA+B;YAC/B,2BAA2B;YAC3B,0BAA0B;YAC1B,gCAAgC;YAChC,2BAA2B;YAC3B,0BAA0B;YAC1B,2BAA2B;YAC3B,2BAA2B;YAC3B,4BAA4B;SAC7B,CAAC;QAEF,yFAAyF;QACzF,uFAAuF;QACvF,uFAAuF;QACvF,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;yGAtBU,eAAe;4DAAf,eAAe;gEA1CxB,YAAY;YACZ,WAAW;YACX,cAAc;YACd,gBAAgB;YAChB,aAAa;YACb,qBAAqB;YACrB,iBAAiB;YACjB,mBAAmB;YACnB,aAAa;YACb,eAAe;YACf,+BAA+B;YAC/B,YAAY;;iFA+BH,eAAe;cAzE3B,QAAQ;eAAC;gBACR,YAAY,EAAE;oBACZ,8EAA8E;oBAC9E,iCAAiC;oBAEjC,gCAAgC;oBAChC,4BAA4B;oBAC5B,+BAA+B;oBAC/B,4BAA4B;oBAE5B,oBAAoB;oBACpB,2BAA2B;oBAC3B,2BAA2B;oBAC3B,+BAA+B;oBAC/B,2BAA2B;oBAC3B,0BAA0B;oBAC1B,gCAAgC;oBAChC,2BAA2B;oBAC3B,uBAAuB;oBAEvB,qEAAqE;oBACrE,+BAA+B;oBAE/B,kCAAkC;oBAClC,4BAA4B;oBAC5B,0BAA0B;oBAC1B,2BAA2B;oBAC3B,2BAA2B;oBAC3B,4BAA4B;iBAC7B;gBACD,OAAO,EAAE;oBACP,YAAY;oBACZ,WAAW;oBACX,cAAc;oBACd,gBAAgB;oBAChB,aAAa;oBACb,qBAAqB;oBACrB,iBAAiB;oBACjB,mBAAmB;oBACnB,aAAa;oBACb,eAAe;oBACf,+BAA+B;oBAC/B,YAAY;iBACb;gBACD,OAAO,EAAE;oBACP,qCAAqC;oBACrC,iCAAiC;oBAEjC,uCAAuC;oBACvC,4BAA4B;oBAC5B,+BAA+B;oBAC/B,4BAA4B;oBAE5B,2BAA2B;oBAC3B,2BAA2B;oBAC3B,2BAA2B;oBAC3B,+BAA+B;oBAC/B,2BAA2B;oBAC3B,0BAA0B;oBAC1B,gCAAgC;oBAChC,2BAA2B;oBAE3B,kCAAkC;oBAClC,4BAA4B;oBAC5B,0BAA0B;oBAC1B,2BAA2B;oBAC3B,2BAA2B;oBAC3B,4BAA4B;iBAC7B;gBACD,SAAS,EAAE;gBACT,gGAAgG;iBACjG;aACF;;wFACY,eAAe;QAvExB,8EAA8E;QAC9E,iCAAiC;QAEjC,gCAAgC;QAChC,4BAA4B;QAC5B,+BAA+B;QAC/B,4BAA4B;QAE5B,oBAAoB;QACpB,2BAA2B;QAC3B,2BAA2B;QAC3B,+BAA+B;QAC/B,2BAA2B;QAC3B,0BAA0B;QAC1B,gCAAgC;QAChC,2BAA2B;QAC3B,uBAAuB;QAEvB,qEAAqE;QACrE,+BAA+B;QAE/B,kCAAkC;QAClC,4BAA4B;QAC5B,0BAA0B;QAC1B,2BAA2B;QAC3B,2BAA2B;QAC3B,4BAA4B,aAG5B,YAAY;QACZ,WAAW;QACX,cAAc;QACd,gBAAgB;QAChB,aAAa;QACb,qBAAqB;QACrB,iBAAiB;QACjB,mBAAmB;QACnB,aAAa;QACb,eAAe;QACf,+BAA+B;QAC/B,YAAY;QAGZ,qCAAqC;QACrC,iCAAiC;QAEjC,uCAAuC;QACvC,4BAA4B;QAC5B,+BAA+B;QAC/B,4BAA4B;QAE5B,2BAA2B;QAC3B,2BAA2B;QAC3B,2BAA2B;QAC3B,+BAA+B;QAC/B,2BAA2B;QAC3B,0BAA0B;QAC1B,gCAAgC;QAChC,2BAA2B;QAE3B,kCAAkC;QAClC,4BAA4B;QAC5B,0BAA0B;QAC1B,2BAA2B;QAC3B,2BAA2B;QAC3B,4BAA4B","sourcesContent":["import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { MarkdownModule } from '@memberjunction/ng-markdown';\nimport { AgGridModule } from 'ag-grid-angular';\n\n// Import MJ modules\nimport { CodeEditorModule } from '@memberjunction/ng-code-editor';\nimport { MJReactModule, AngularAdapterService } from '@memberjunction/ng-react';\nimport { MJNotificationsModule } from '@memberjunction/ng-notifications';\nimport { QueryViewerModule } from '@memberjunction/ng-query-viewer';\nimport { SharedGenericModule } from '@memberjunction/ng-shared-generic';\nimport { NgTreesModule } from '@memberjunction/ng-trees';\n// BaseFormsModule supplies `<mj-interactive-form>` for the form-aware\n// component-artifact viewer branch (componentRole === 'form').\nimport { BaseFormsModule } from '@memberjunction/ng-base-forms';\n\n// Import plugin components (note: base component is abstract and NOT declared)\nimport { JsonArtifactViewerComponent } from './components/plugins/json-artifact-viewer.component';\nimport { CodeArtifactViewerComponent } from './components/plugins/code-artifact-viewer.component';\nimport { MarkdownArtifactViewerComponent } from './components/plugins/markdown-artifact-viewer.component';\nimport { HtmlArtifactViewerComponent } from './components/plugins/html-artifact-viewer.component';\nimport { SvgArtifactViewerComponent } from './components/plugins/svg-artifact-viewer.component';\nimport { ComponentArtifactViewerComponent } from './components/plugins/component-artifact-viewer.component';\nimport { DataArtifactViewerComponent } from './components/plugins/data-artifact-viewer.component';\nimport { SaveQueryPanelComponent } from './components/plugins/save-query-dialog.component';\nimport { DataRequirementsViewerComponent } from './components/plugins/data-requirements-viewer/data-requirements-viewer.component';\nimport { ComponentFeedbackPanelComponent } from './components/plugins/component-feedback-panel/component-feedback-panel.component';\n\n// File viewer plugins\nimport { FileArtifactToolbarComponent } from './components/file-artifact-toolbar.component';\nimport { PdfArtifactViewerComponent } from './components/plugins/pdf-artifact-viewer.component';\nimport { XlsxArtifactViewerComponent } from './components/plugins/xlsx-artifact-viewer.component';\nimport { DocxArtifactViewerComponent } from './components/plugins/docx-artifact-viewer.component';\nimport { ImageArtifactViewerComponent } from './components/plugins/image-artifact-viewer.component';\n\n// Import artifact type plugin viewer component\nimport { ArtifactTypePluginViewerComponent } from './components/artifact-type-plugin-viewer.component';\nimport { ArtifactVersionHistoryComponent } from './components/artifact-version-history.component';\nimport { ArtifactViewerPanelComponent } from './components/artifact-viewer-panel.component';\nimport { ArtifactMessageCardComponent } from './components/artifact-message-card.component';\n\n/**\n * Module for artifact viewer plugin system.\n * Provides components for viewing different types of artifacts (JSON, Code, Markdown, HTML, SVG, Components).\n *\n * Plugins are automatically registered via @RegisterClass decorator and can be instantiated\n * using MJGlobal.Instance.ClassFactory.CreateInstance('PluginClassName').\n */\n@NgModule({\n declarations: [\n // Artifact type plugin viewer (loads appropriate plugin based on DriverClass)\n ArtifactTypePluginViewerComponent,\n\n // Artifact viewer UI components\n ArtifactViewerPanelComponent,\n ArtifactVersionHistoryComponent,\n ArtifactMessageCardComponent,\n\n // Plugin components\n JsonArtifactViewerComponent,\n CodeArtifactViewerComponent,\n MarkdownArtifactViewerComponent,\n HtmlArtifactViewerComponent,\n SvgArtifactViewerComponent,\n ComponentArtifactViewerComponent,\n DataArtifactViewerComponent,\n SaveQueryPanelComponent,\n\n // Custom tab components (used by plugins via dynamic component tabs)\n DataRequirementsViewerComponent,\n\n // File viewer toolbar and plugins\n FileArtifactToolbarComponent,\n PdfArtifactViewerComponent,\n XlsxArtifactViewerComponent,\n DocxArtifactViewerComponent,\n ImageArtifactViewerComponent,\n ],\n imports: [\n CommonModule,\n FormsModule,\n MarkdownModule,\n CodeEditorModule,\n MJReactModule,\n MJNotificationsModule,\n QueryViewerModule,\n SharedGenericModule,\n NgTreesModule,\n BaseFormsModule,\n ComponentFeedbackPanelComponent,\n AgGridModule,\n ],\n exports: [\n // Export artifact type plugin viewer\n ArtifactTypePluginViewerComponent,\n\n // Export artifact viewer UI components\n ArtifactViewerPanelComponent,\n ArtifactVersionHistoryComponent,\n ArtifactMessageCardComponent,\n\n // Export plugin components\n JsonArtifactViewerComponent,\n CodeArtifactViewerComponent,\n MarkdownArtifactViewerComponent,\n HtmlArtifactViewerComponent,\n SvgArtifactViewerComponent,\n ComponentArtifactViewerComponent,\n DataArtifactViewerComponent,\n\n // File viewer toolbar and plugins\n FileArtifactToolbarComponent,\n PdfArtifactViewerComponent,\n XlsxArtifactViewerComponent,\n DocxArtifactViewerComponent,\n ImageArtifactViewerComponent,\n ],\n providers: [\n // Plugins are registered via @RegisterClass decorator on component classes, no providers needed\n ]\n})\nexport class ArtifactsModule {\n constructor(private adapter: AngularAdapterService) {\n // Ensure plugin components are registered on module load by referencing their classes\n // The @RegisterClass decorator on each component handles the actual registration with MJGlobal\n [\n JsonArtifactViewerComponent,\n CodeArtifactViewerComponent,\n MarkdownArtifactViewerComponent,\n HtmlArtifactViewerComponent,\n SvgArtifactViewerComponent,\n ComponentArtifactViewerComponent,\n DataArtifactViewerComponent,\n PdfArtifactViewerComponent,\n XlsxArtifactViewerComponent,\n DocxArtifactViewerComponent,\n ImageArtifactViewerComponent,\n ];\n\n // PERF: Eagerly start downloading React, ReactDOM, and Babel from CDN in the background.\n // By the time a user opens an interactive component artifact, the scripts will already\n // be cached. The adapter.preload() is non-blocking and deduplicates with initialize().\n this.adapter.preload();\n }\n}\n"]}
@@ -22,6 +22,16 @@ export declare class ArtifactTypePluginViewerComponent extends BaseAngularCompon
22
22
  navigationRequest: EventEmitter<NavigationRequest>;
23
23
  pluginLoaded: EventEmitter<void>;
24
24
  tabsChanged: EventEmitter<void>;
25
+ /**
26
+ * Bubbled up from the component-artifact-viewer's form-aware branch when
27
+ * the user clicks "Apply to my form". Carries the spec + entity so the
28
+ * consumer (chat message card, conversation host) can invoke the
29
+ * Create-or-Modify Interactive Form action behind a confirmation dialog.
30
+ */
31
+ applyFormRequested: EventEmitter<{
32
+ spec: unknown;
33
+ entityName: string;
34
+ }>;
25
35
  viewerContainer: ViewContainerRef;
26
36
  isLoading: boolean;
27
37
  error: string | null;
@@ -78,6 +88,6 @@ export declare class ArtifactTypePluginViewerComponent extends BaseAngularCompon
78
88
  */
79
89
  private destroyCurrentViewer;
80
90
  static ɵfac: i0.ɵɵFactoryDeclaration<ArtifactTypePluginViewerComponent, never>;
81
- static ɵcmp: i0.ɵɵComponentDeclaration<ArtifactTypePluginViewerComponent, "mj-artifact-type-plugin-viewer", never, { "artifactVersion": { "alias": "artifactVersion"; "required": false; }; "artifactTypeName": { "alias": "artifactTypeName"; "required": false; }; "contentType": { "alias": "contentType"; "required": false; }; "height": { "alias": "height"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "cssClass": { "alias": "cssClass"; "required": false; }; }, { "openEntityRecord": "openEntityRecord"; "navigationRequest": "navigationRequest"; "pluginLoaded": "pluginLoaded"; "tabsChanged": "tabsChanged"; }, never, never, false, never>;
91
+ static ɵcmp: i0.ɵɵComponentDeclaration<ArtifactTypePluginViewerComponent, "mj-artifact-type-plugin-viewer", never, { "artifactVersion": { "alias": "artifactVersion"; "required": false; }; "artifactTypeName": { "alias": "artifactTypeName"; "required": false; }; "contentType": { "alias": "contentType"; "required": false; }; "height": { "alias": "height"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "cssClass": { "alias": "cssClass"; "required": false; }; }, { "openEntityRecord": "openEntityRecord"; "navigationRequest": "navigationRequest"; "pluginLoaded": "pluginLoaded"; "tabsChanged": "tabsChanged"; "applyFormRequested": "applyFormRequested"; }, never, never, false, never>;
82
92
  }
83
93
  //# sourceMappingURL=artifact-type-plugin-viewer.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"artifact-type-plugin-viewer.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/artifact-type-plugin-viewer.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,YAAY,EACZ,MAAM,EACN,SAAS,EACT,aAAa,EAEb,gBAAgB,EAGjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,uBAAuB,EAAgD,MAAM,+BAA+B,CAAC;AACtH,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAA+B,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGjF,OAAO,EAAE,iCAAiC,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;;AAExG;;;GAGG;AACH,qBA2Fa,iCAAkC,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;IAC7F,eAAe,EAAG,uBAAuB,CAAC;IAC1C,gBAAgB,EAAG,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAQ;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAEjB,gBAAgB;oBAAiC,MAAM;sBAAgB,YAAY;OAAK;IACxF,iBAAiB,kCAAyC;IAC1D,YAAY,qBAA4B;IACxC,WAAW,qBAA4B;IAGjD,eAAe,EAAG,gBAAgB,CAAC;IAE5B,SAAS,UAAQ;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAQ;IACnC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAExC,OAAO,CAAC,YAAY,CAAkC;IAEtD;;OAEG;IACH,IAAW,cAAc,IAAI,iCAAiC,GAAG,IAAI,CAEpE;IAED;;;OAGG;IACH,IAAW,gBAAgB,IAAI,OAAO,CAErC;IAED;;;OAGG;IACI,kBAAkB,IAAI,IAAI;IAI3B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxD,WAAW,IAAI,IAAI;IAInB;;OAEG;YACW,UAAU;IAyIxB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAMhB;;OAEG;YACW,eAAe;IAW7B;;;;;;OAMG;YACW,kBAAkB;IAyBhC;;OAEG;YACW,mBAAmB;IAiBjC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAiBzB;;OAEG;IACH,OAAO,CAAC,oBAAoB;yCA3SjB,iCAAiC;2CAAjC,iCAAiC;CAkT7C"}
1
+ {"version":3,"file":"artifact-type-plugin-viewer.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/artifact-type-plugin-viewer.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,YAAY,EACZ,MAAM,EACN,SAAS,EACT,aAAa,EAEb,gBAAgB,EAGjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,uBAAuB,EAAgD,MAAM,+BAA+B,CAAC;AACtH,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAA+B,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGjF,OAAO,EAAE,iCAAiC,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;;AAExG;;;GAGG;AACH,qBA2Fa,iCAAkC,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;IAC7F,eAAe,EAAG,uBAAuB,CAAC;IAC1C,gBAAgB,EAAG,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAQ;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAEjB,gBAAgB;oBAAiC,MAAM;sBAAgB,YAAY;OAAK;IACxF,iBAAiB,kCAAyC;IAC1D,YAAY,qBAA4B;IACxC,WAAW,qBAA4B;IACjD;;;;;OAKG;IACO,kBAAkB;cAA4B,OAAO;oBAAc,MAAM;OAAM;IAGzF,eAAe,EAAG,gBAAgB,CAAC;IAE5B,SAAS,UAAQ;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAQ;IACnC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAExC,OAAO,CAAC,YAAY,CAAkC;IAEtD;;OAEG;IACH,IAAW,cAAc,IAAI,iCAAiC,GAAG,IAAI,CAEpE;IAED;;;OAGG;IACH,IAAW,gBAAgB,IAAI,OAAO,CAErC;IAED;;;OAGG;IACI,kBAAkB,IAAI,IAAI;IAI3B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxD,WAAW,IAAI,IAAI;IAInB;;OAEG;YACW,UAAU;IAoJxB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAMhB;;OAEG;YACW,eAAe;IAW7B;;;;;;OAMG;YACW,kBAAkB;IAyBhC;;OAEG;YACW,mBAAmB;IAiBjC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAiBzB;;OAEG;IACH,OAAO,CAAC,oBAAoB;yCA7TjB,iCAAiC;2CAAjC,iCAAiC;CAoU7C"}