@memberjunction/ng-artifacts 6.2.0-edge.0 → 6.2.0-edge.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/dist/lib/components/artifact-message-card.component.d.ts +60 -8
  2. package/dist/lib/components/artifact-message-card.component.d.ts.map +1 -1
  3. package/dist/lib/components/artifact-message-card.component.js +135 -39
  4. package/dist/lib/components/artifact-message-card.component.js.map +1 -1
  5. package/dist/lib/components/artifact-type-plugin-viewer.component.d.ts +58 -6
  6. package/dist/lib/components/artifact-type-plugin-viewer.component.d.ts.map +1 -1
  7. package/dist/lib/components/artifact-type-plugin-viewer.component.js +107 -29
  8. package/dist/lib/components/artifact-type-plugin-viewer.component.js.map +1 -1
  9. package/dist/lib/components/artifact-version-download.d.ts +5 -3
  10. package/dist/lib/components/artifact-version-download.d.ts.map +1 -1
  11. package/dist/lib/components/artifact-version-download.js +11 -7
  12. package/dist/lib/components/artifact-version-download.js.map +1 -1
  13. package/dist/lib/components/artifact-version-history.component.d.ts +74 -8
  14. package/dist/lib/components/artifact-version-history.component.d.ts.map +1 -1
  15. package/dist/lib/components/artifact-version-history.component.js +152 -34
  16. package/dist/lib/components/artifact-version-history.component.js.map +1 -1
  17. package/dist/lib/components/artifact-viewer-panel.component.d.ts +328 -35
  18. package/dist/lib/components/artifact-viewer-panel.component.d.ts.map +1 -1
  19. package/dist/lib/components/artifact-viewer-panel.component.js +701 -213
  20. package/dist/lib/components/artifact-viewer-panel.component.js.map +1 -1
  21. package/dist/lib/components/file-artifact-toolbar.component.d.ts +112 -10
  22. package/dist/lib/components/file-artifact-toolbar.component.d.ts.map +1 -1
  23. package/dist/lib/components/file-artifact-toolbar.component.js +197 -23
  24. package/dist/lib/components/file-artifact-toolbar.component.js.map +1 -1
  25. package/dist/lib/components/plugins/audio-artifact-viewer.component.d.ts +9 -1
  26. package/dist/lib/components/plugins/audio-artifact-viewer.component.d.ts.map +1 -1
  27. package/dist/lib/components/plugins/audio-artifact-viewer.component.js +20 -4
  28. package/dist/lib/components/plugins/audio-artifact-viewer.component.js.map +1 -1
  29. package/dist/lib/components/plugins/code-artifact-viewer.component.d.ts +23 -5
  30. package/dist/lib/components/plugins/code-artifact-viewer.component.d.ts.map +1 -1
  31. package/dist/lib/components/plugins/code-artifact-viewer.component.js +69 -31
  32. package/dist/lib/components/plugins/code-artifact-viewer.component.js.map +1 -1
  33. package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts +136 -18
  34. package/dist/lib/components/plugins/component-artifact-viewer.component.d.ts.map +1 -1
  35. package/dist/lib/components/plugins/component-artifact-viewer.component.js +285 -97
  36. package/dist/lib/components/plugins/component-artifact-viewer.component.js.map +1 -1
  37. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.d.ts +2 -2
  38. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js +7 -7
  39. package/dist/lib/components/plugins/component-feedback-panel/component-feedback-panel.component.js.map +1 -1
  40. package/dist/lib/components/plugins/component-permission-evaluation.d.ts +2 -0
  41. package/dist/lib/components/plugins/component-permission-evaluation.d.ts.map +1 -1
  42. package/dist/lib/components/plugins/component-permission-evaluation.js +6 -2
  43. package/dist/lib/components/plugins/component-permission-evaluation.js.map +1 -1
  44. package/dist/lib/components/plugins/data-artifact-viewer.component.d.ts +17 -6
  45. package/dist/lib/components/plugins/data-artifact-viewer.component.d.ts.map +1 -1
  46. package/dist/lib/components/plugins/data-artifact-viewer.component.js +32 -22
  47. package/dist/lib/components/plugins/data-artifact-viewer.component.js.map +1 -1
  48. package/dist/lib/components/plugins/data-requirements-viewer/data-requirements-viewer.component.d.ts +56 -4
  49. package/dist/lib/components/plugins/data-requirements-viewer/data-requirements-viewer.component.d.ts.map +1 -1
  50. package/dist/lib/components/plugins/data-requirements-viewer/data-requirements-viewer.component.js +142 -36
  51. package/dist/lib/components/plugins/data-requirements-viewer/data-requirements-viewer.component.js.map +1 -1
  52. package/dist/lib/components/plugins/docx-artifact-viewer.component.d.ts +14 -2
  53. package/dist/lib/components/plugins/docx-artifact-viewer.component.d.ts.map +1 -1
  54. package/dist/lib/components/plugins/docx-artifact-viewer.component.js +32 -8
  55. package/dist/lib/components/plugins/docx-artifact-viewer.component.js.map +1 -1
  56. package/dist/lib/components/plugins/html-artifact-viewer.component.d.ts +17 -3
  57. package/dist/lib/components/plugins/html-artifact-viewer.component.d.ts.map +1 -1
  58. package/dist/lib/components/plugins/html-artifact-viewer.component.js +36 -8
  59. package/dist/lib/components/plugins/html-artifact-viewer.component.js.map +1 -1
  60. package/dist/lib/components/plugins/image-artifact-viewer.component.d.ts +41 -5
  61. package/dist/lib/components/plugins/image-artifact-viewer.component.d.ts.map +1 -1
  62. package/dist/lib/components/plugins/image-artifact-viewer.component.js +102 -30
  63. package/dist/lib/components/plugins/image-artifact-viewer.component.js.map +1 -1
  64. package/dist/lib/components/plugins/json-artifact-viewer.component.d.ts +33 -5
  65. package/dist/lib/components/plugins/json-artifact-viewer.component.d.ts.map +1 -1
  66. package/dist/lib/components/plugins/json-artifact-viewer.component.js +89 -33
  67. package/dist/lib/components/plugins/json-artifact-viewer.component.js.map +1 -1
  68. package/dist/lib/components/plugins/markdown-artifact-viewer.component.d.ts +12 -2
  69. package/dist/lib/components/plugins/markdown-artifact-viewer.component.d.ts.map +1 -1
  70. package/dist/lib/components/plugins/markdown-artifact-viewer.component.js +28 -8
  71. package/dist/lib/components/plugins/markdown-artifact-viewer.component.js.map +1 -1
  72. package/dist/lib/components/plugins/ml-experiment-results-viewer.component.d.ts +4 -0
  73. package/dist/lib/components/plugins/ml-experiment-results-viewer.component.d.ts.map +1 -1
  74. package/dist/lib/components/plugins/ml-experiment-results-viewer.component.js +14 -6
  75. package/dist/lib/components/plugins/ml-experiment-results-viewer.component.js.map +1 -1
  76. package/dist/lib/components/plugins/pdf-artifact-viewer.component.d.ts +47 -5
  77. package/dist/lib/components/plugins/pdf-artifact-viewer.component.d.ts.map +1 -1
  78. package/dist/lib/components/plugins/pdf-artifact-viewer.component.js +129 -45
  79. package/dist/lib/components/plugins/pdf-artifact-viewer.component.js.map +1 -1
  80. package/dist/lib/components/plugins/save-query-dialog.component.d.ts +5 -1
  81. package/dist/lib/components/plugins/save-query-dialog.component.d.ts.map +1 -1
  82. package/dist/lib/components/plugins/save-query-dialog.component.js +12 -4
  83. package/dist/lib/components/plugins/save-query-dialog.component.js.map +1 -1
  84. package/dist/lib/components/plugins/svg-artifact-viewer.component.d.ts +17 -3
  85. package/dist/lib/components/plugins/svg-artifact-viewer.component.d.ts.map +1 -1
  86. package/dist/lib/components/plugins/svg-artifact-viewer.component.js +36 -8
  87. package/dist/lib/components/plugins/svg-artifact-viewer.component.js.map +1 -1
  88. package/dist/lib/components/plugins/video-artifact-viewer.component.d.ts +9 -1
  89. package/dist/lib/components/plugins/video-artifact-viewer.component.d.ts.map +1 -1
  90. package/dist/lib/components/plugins/video-artifact-viewer.component.js +20 -4
  91. package/dist/lib/components/plugins/video-artifact-viewer.component.js.map +1 -1
  92. package/dist/lib/components/plugins/xlsx-artifact-viewer.component.d.ts +28 -4
  93. package/dist/lib/components/plugins/xlsx-artifact-viewer.component.d.ts.map +1 -1
  94. package/dist/lib/components/plugins/xlsx-artifact-viewer.component.js +64 -16
  95. package/dist/lib/components/plugins/xlsx-artifact-viewer.component.js.map +1 -1
  96. package/dist/lib/components/previews/audio-artifact-preview.component.d.ts +9 -1
  97. package/dist/lib/components/previews/audio-artifact-preview.component.d.ts.map +1 -1
  98. package/dist/lib/components/previews/audio-artifact-preview.component.js +20 -4
  99. package/dist/lib/components/previews/audio-artifact-preview.component.js.map +1 -1
  100. package/dist/lib/components/previews/image-artifact-preview.component.d.ts +16 -2
  101. package/dist/lib/components/previews/image-artifact-preview.component.d.ts.map +1 -1
  102. package/dist/lib/components/previews/image-artifact-preview.component.js +35 -7
  103. package/dist/lib/components/previews/image-artifact-preview.component.js.map +1 -1
  104. package/dist/lib/components/previews/video-artifact-preview.component.d.ts +9 -1
  105. package/dist/lib/components/previews/video-artifact-preview.component.d.ts.map +1 -1
  106. package/dist/lib/components/previews/video-artifact-preview.component.js +20 -4
  107. package/dist/lib/components/previews/video-artifact-preview.component.js.map +1 -1
  108. package/dist/lib/interfaces/artifact-viewer-plugin.interface.js.map +1 -1
  109. package/dist/lib/services/artifact-file.service.d.ts +8 -0
  110. package/dist/lib/services/artifact-file.service.d.ts.map +1 -1
  111. package/dist/lib/services/artifact-file.service.js +22 -6
  112. package/dist/lib/services/artifact-file.service.js.map +1 -1
  113. package/dist/lib/services/artifact-icon.service.d.ts +2 -0
  114. package/dist/lib/services/artifact-icon.service.d.ts.map +1 -1
  115. package/dist/lib/services/artifact-icon.service.js +5 -1
  116. package/dist/lib/services/artifact-icon.service.js.map +1 -1
  117. package/dist/lib/services/artifact-preview-resolver.service.d.ts +2 -0
  118. package/dist/lib/services/artifact-preview-resolver.service.d.ts.map +1 -1
  119. package/dist/lib/services/artifact-preview-resolver.service.js +5 -1
  120. package/dist/lib/services/artifact-preview-resolver.service.js.map +1 -1
  121. package/dist/lib/snapshot-helpers.d.ts +10 -0
  122. package/dist/lib/snapshot-helpers.d.ts.map +1 -1
  123. package/dist/lib/snapshot-helpers.js +25 -5
  124. package/dist/lib/snapshot-helpers.js.map +1 -1
  125. package/package.json +21 -21
@@ -1 +1 @@
1
- {"version":3,"file":"video-artifact-preview.component.js","sourceRoot":"","sources":["../../../../src/lib/components/previews/video-artifact-preview.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,EAAU,MAAM,eAAe,CAAC;AAE7E,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;;;;;IAiBrE,8BAAgD;IAC5C,uBAAgC;IAChC,4BAAM;IAAA,YAAkB;IAC5B,AAD4B,iBAAO,EAC7B;;;IADI,eAAkB;IAAlB,yCAAkB;;;IAG5B,gCAA8D;;;;IAE9D,0CAWC;IADG,AADA,uIAAS,wBAAwB,IAAC,6LACzB,qBAAc,KAAC;IAC3B,iBAAkB;;;IAHf,AADA,AADA,AADA,AADA,AADA,AADA,2CAAsB,yBACE,+BACM,uBACR,2BACI,2BACA,qBACN;;AA9BpC;;;;;;;;;GASG;AAwDH,MAAM,OAAO,6BAA8B,SAAQ,4BAA4B;IAC1D,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAEjD,qGAAqG;IAC9F,QAAQ,GAAG,EAAE,CAAC;IAGrB,iEAAiE;IAC1D,YAAY,GAAG,EAAE,CAAC;IAEzB;;;OAGG;IACI,WAAW,GAAiB,EAAE,CAAC;IAEtC,mGAAmG;IAC3F,WAAW,CAAC,GAAW;QAC3B,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC;QACpB,IAAI,CAAC,WAAW,GAAG,GAAG;YAClB,CAAC,CAAC;gBACI;oBACI,EAAE,EAAE,IAAI,CAAC,eAAe,EAAE,EAAE,IAAI,OAAO;oBACvC,IAAI,EAAE,OAAO;oBACb,GAAG,EAAE,GAAG;oBACR,QAAQ,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,IAAI,SAAS;iBACxD;aACJ;YACH,CAAC,CAAC,EAAE,CAAC;IACb,CAAC;IAED,KAAK,CAAC,QAAQ;QACV,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3C,IAAI,GAAG,EAAE,CAAC;gBACN,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACJ,IAAI,CAAC,YAAY,GAAG,mBAAmB,CAAC;YAC5C,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACL,IAAI,CAAC,YAAY,GAAG,uBAAuB,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAEM,YAAY;QACf,IAAI,CAAC,YAAY,GAAG,4BAA4B,CAAC;QACjD,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACrB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAED,yFAAyF;IAClF,YAAY;QACf,gEAAgE;IACpE,CAAC;iSAtDQ,6BAA6B,yBAA7B,6BAA6B;6DAA7B,6BAA6B;YA5ChC,AAFA,AALF,+FAAoB,gFAKI,qFAED;;YAPvB,kFAoBC;;;iFA+BI,6BAA6B;cAvDzC,SAAS;6BACM,KAAK,YACP,2BAA2B,YAC3B;;;;;;;;;;;;;;;;;;;;;;KAsBT;;kFA8BQ,6BAA6B","sourcesContent":["import { ChangeDetectorRef, Component, inject, OnInit } from '@angular/core';\nimport { MediaTrack } from '@memberjunction/ng-media-player';\nimport { BaseArtifactPreviewComponent } from './base-artifact-preview.component';\n\n/**\n * Inline preview for video artifacts. Embeds the generic {@link MJMediaPlayerComponent}\n * (`mj-media-player`) in a compact, thumbnail-sized configuration inside the conversation message\n * card. Click events on the player are stopped from propagating so scrubbing / play-pause does\n * NOT open the full-size viewer (the card's other regions still open it).\n *\n * Compact gating: play/pause + scrubber + time (and fullscreen, which is handy for a tiny video\n * surface) are shown. Transcript, waveform, speed, skip and volume chrome are turned OFF so the\n * player reads cleanly at preview size and doesn't crowd the card.\n */\n@Component({\n standalone: false,\n selector: 'mj-video-artifact-preview',\n template: `\n @if (errorMessage) {\n <div class=\"video-preview video-preview--error\">\n <i class=\"fa-solid fa-film\"></i>\n <span>{{ errorMessage }}</span>\n </div>\n } @else if (isLoading) {\n <mj-loading text=\"Loading video...\" size=\"small\"></mj-loading>\n } @else if (videoUrl) {\n <mj-media-player\n class=\"video-preview__player\"\n [Tracks]=\"MediaTracks\"\n [ShowTranscript]=\"false\"\n [ShowTranscriptToggle]=\"false\"\n [ShowWaveform]=\"false\"\n [ShowSpeedControl]=\"false\"\n [ShowSkipControls]=\"false\"\n [ShowVolume]=\"false\"\n (click)=\"$event.stopPropagation()\"\n (Ended)=\"onMediaEnded()\"\n ></mj-media-player>\n }\n `,\n styles: [\n `\n :host {\n display: block;\n }\n\n /* Compact thumbnail — cap the height so the video surface stays consistent with the\n image preview (140px) and neither dominates the conversation card. */\n .video-preview__player {\n display: block;\n width: 100%;\n max-width: 100%;\n max-height: 140px;\n border-radius: 6px;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n }\n\n .video-preview--error {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n color: var(--mj-text-muted);\n font-size: 13px;\n }\n `,\n ],\n})\nexport class VideoArtifactPreviewComponent extends BaseArtifactPreviewComponent implements OnInit {\n private readonly cdr = inject(ChangeDetectorRef);\n\n /** Resolved URL — data URI (inline) or pre-auth URL (file). Funneled through {@link setVideoUrl}. */\n public videoUrl = '';\n\n\n /** Non-empty hides the player and shows a compact error line. */\n public errorMessage = '';\n\n /**\n * Single-track input for the generic {@link MJMediaPlayerComponent}. Rebuilt in lockstep with\n * {@link videoUrl} via {@link setVideoUrl}; `[]` until a URL exists so the player shows its empty state.\n */\n public MediaTracks: MediaTrack[] = [];\n\n /** Set the resolved URL and recompute the single-element {@link MediaTracks} array in lockstep. */\n private setVideoUrl(url: string): void {\n this.videoUrl = url;\n this.MediaTracks = url\n ? [\n {\n Id: this.artifactVersion?.ID ?? 'video',\n Kind: 'video',\n Url: url,\n MimeType: this.artifactVersion?.MimeType ?? undefined,\n },\n ]\n : [];\n }\n\n async ngOnInit(): Promise<void> {\n try {\n const url = await this.resolveContentUrl();\n if (url) {\n this.setVideoUrl(url);\n } else {\n this.errorMessage = 'No video content.';\n }\n } catch {\n this.errorMessage = 'Could not load video.';\n }\n this.cdr.markForCheck();\n }\n\n public onMediaError(): void {\n this.errorMessage = 'Video could not be played.';\n this.setVideoUrl('');\n this.cdr.markForCheck();\n }\n\n /** Fired when the generic player reaches the end of the track. No-op affordance hook. */\n public onMediaEnded(): void {\n // Playback finished — nothing to persist for an inline preview.\n }\n}\n"]}
1
+ {"version":3,"file":"video-artifact-preview.component.js","sourceRoot":"","sources":["../../../../src/lib/components/previews/video-artifact-preview.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,EAAU,MAAM,eAAe,CAAC;AAE7E,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;;;;;IAiBrE,8BAAgD;IAC5C,uBAAgC;IAChC,4BAAM;IAAA,YAAkB;IAC5B,AAD4B,iBAAO,EAC7B;;;IADI,eAAkB;IAAlB,yCAAkB;;;IAG5B,gCAA8D;;;;IAE9D,0CAWC;IADG,AADA,uIAAS,wBAAwB,IAAC,6LACzB,qBAAc,KAAC;IAC3B,iBAAkB;;;IAHf,AADA,AADA,AADA,AADA,AADA,AADA,2CAAsB,yBACE,+BACM,uBACR,2BACI,2BACA,qBACN;;AA9BpC;;;;;;;;;GASG;AAwDH,MAAM,OAAO,6BAA8B,SAAQ,4BAA4B;IAC1D,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAEjD,qGAAqG;IAC9F,QAAQ,GAAG,EAAE,CAAC;IAErB,wCAAwC;IACxC,IAAW,QAAQ;QACf,OAAO,IAAI,CAAC,QAAQ,CAAC;IACzB,CAAC;IACD,wCAAwC;IACxC,IAAW,QAAQ,CAAC,KAAK;QACrB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IAC1B,CAAC;IAGD,iEAAiE;IAC1D,YAAY,GAAG,EAAE,CAAC;IAEzB;;;OAGG;IACI,WAAW,GAAiB,EAAE,CAAC;IAEtC,mGAAmG;IAC3F,WAAW,CAAC,GAAW;QAC3B,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC;QACpB,IAAI,CAAC,WAAW,GAAG,GAAG;YAClB,CAAC,CAAC;gBACI;oBACI,EAAE,EAAE,IAAI,CAAC,eAAe,EAAE,EAAE,IAAI,OAAO;oBACvC,IAAI,EAAE,OAAO;oBACb,GAAG,EAAE,GAAG;oBACR,QAAQ,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,IAAI,SAAS;iBACxD;aACJ;YACH,CAAC,CAAC,EAAE,CAAC;IACb,CAAC;IAED,KAAK,CAAC,QAAQ;QACV,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3C,IAAI,GAAG,EAAE,CAAC;gBACN,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACJ,IAAI,CAAC,YAAY,GAAG,mBAAmB,CAAC;YAC5C,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACL,IAAI,CAAC,YAAY,GAAG,uBAAuB,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAEM,YAAY;QACf,IAAI,CAAC,YAAY,GAAG,4BAA4B,CAAC;QACjD,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACrB,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAED,4CAA4C;IACrC,YAAY;QACf,OAAO,IAAI,CAAC,YAAY,EAAE,CAAC;IAC/B,CAAC;IAED,yFAAyF;IAClF,YAAY;QACf,gEAAgE;IACpE,CAAC;IAED,4CAA4C;IACrC,YAAY;QACf,OAAO,IAAI,CAAC,YAAY,EAAE,CAAC;IAC/B,CAAC;iSAzEQ,6BAA6B,yBAA7B,6BAA6B;6DAA7B,6BAA6B;YA5ChC,AAFA,AALF,+FAAoB,gFAKI,qFAED;;YAPvB,kFAoBC;;;iFA+BI,6BAA6B;cAvDzC,SAAS;6BACM,KAAK,YACP,2BAA2B,YAC3B;;;;;;;;;;;;;;;;;;;;;;KAsBT;;kFA8BQ,6BAA6B","sourcesContent":["import { ChangeDetectorRef, Component, inject, OnInit } from '@angular/core';\nimport { MediaTrack } from '@memberjunction/ng-media-player';\nimport { BaseArtifactPreviewComponent } from './base-artifact-preview.component';\n\n/**\n * Inline preview for video artifacts. Embeds the generic {@link MJMediaPlayerComponent}\n * (`mj-media-player`) in a compact, thumbnail-sized configuration inside the conversation message\n * card. Click events on the player are stopped from propagating so scrubbing / play-pause does\n * NOT open the full-size viewer (the card's other regions still open it).\n *\n * Compact gating: play/pause + scrubber + time (and fullscreen, which is handy for a tiny video\n * surface) are shown. Transcript, waveform, speed, skip and volume chrome are turned OFF so the\n * player reads cleanly at preview size and doesn't crowd the card.\n */\n@Component({\n standalone: false,\n selector: 'mj-video-artifact-preview',\n template: `\n @if (errorMessage) {\n <div class=\"video-preview video-preview--error\">\n <i class=\"fa-solid fa-film\"></i>\n <span>{{ errorMessage }}</span>\n </div>\n } @else if (isLoading) {\n <mj-loading text=\"Loading video...\" size=\"small\"></mj-loading>\n } @else if (videoUrl) {\n <mj-media-player\n class=\"video-preview__player\"\n [Tracks]=\"MediaTracks\"\n [ShowTranscript]=\"false\"\n [ShowTranscriptToggle]=\"false\"\n [ShowWaveform]=\"false\"\n [ShowSpeedControl]=\"false\"\n [ShowSkipControls]=\"false\"\n [ShowVolume]=\"false\"\n (click)=\"$event.stopPropagation()\"\n (Ended)=\"onMediaEnded()\"\n ></mj-media-player>\n }\n `,\n styles: [\n `\n :host {\n display: block;\n }\n\n /* Compact thumbnail — cap the height so the video surface stays consistent with the\n image preview (140px) and neither dominates the conversation card. */\n .video-preview__player {\n display: block;\n width: 100%;\n max-width: 100%;\n max-height: 140px;\n border-radius: 6px;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n }\n\n .video-preview--error {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n color: var(--mj-text-muted);\n font-size: 13px;\n }\n `,\n ],\n})\nexport class VideoArtifactPreviewComponent extends BaseArtifactPreviewComponent implements OnInit {\n private readonly cdr = inject(ChangeDetectorRef);\n\n /** Resolved URL — data URI (inline) or pre-auth URL (file). Funneled through {@link setVideoUrl}. */\n public VideoUrl = '';\n\n /** @deprecated Use {@link VideoUrl}. */\n public get videoUrl() {\n return this.VideoUrl;\n }\n /** @deprecated Use {@link VideoUrl}. */\n public set videoUrl(value) {\n this.VideoUrl = value;\n }\n\n\n /** Non-empty hides the player and shows a compact error line. */\n public errorMessage = '';\n\n /**\n * Single-track input for the generic {@link MJMediaPlayerComponent}. Rebuilt in lockstep with\n * {@link videoUrl} via {@link setVideoUrl}; `[]` until a URL exists so the player shows its empty state.\n */\n public MediaTracks: MediaTrack[] = [];\n\n /** Set the resolved URL and recompute the single-element {@link MediaTracks} array in lockstep. */\n private setVideoUrl(url: string): void {\n this.VideoUrl = url;\n this.MediaTracks = url\n ? [\n {\n Id: this.artifactVersion?.ID ?? 'video',\n Kind: 'video',\n Url: url,\n MimeType: this.artifactVersion?.MimeType ?? undefined,\n },\n ]\n : [];\n }\n\n async ngOnInit(): Promise<void> {\n try {\n const url = await this.resolveContentUrl();\n if (url) {\n this.setVideoUrl(url);\n } else {\n this.errorMessage = 'No video content.';\n }\n } catch {\n this.errorMessage = 'Could not load video.';\n }\n this.cdr.markForCheck();\n }\n\n public OnMediaError(): void {\n this.errorMessage = 'Video could not be played.';\n this.setVideoUrl('');\n this.cdr.markForCheck();\n }\n\n /** @deprecated Use {@link OnMediaError}. */\n public onMediaError(): void {\n return this.OnMediaError();\n }\n\n /** Fired when the generic player reaches the end of the track. No-op affordance hook. */\n public OnMediaEnded(): void {\n // Playback finished — nothing to persist for an inline preview.\n }\n\n /** @deprecated Use {@link OnMediaEnded}. */\n public onMediaEnded(): void {\n return this.OnMediaEnded();\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"artifact-viewer-plugin.interface.js","sourceRoot":"","sources":["../../../src/lib/interfaces/artifact-viewer-plugin.interface.ts"],"names":[],"mappings":"","sourcesContent":["import { Type } from '@angular/core';\nimport { MJArtifactVersionEntity } from '@memberjunction/core-entities';\n\n/**\n * Interface for artifact viewer plugins.\n * All artifact viewer plugins must implement this interface and be registered\n * with @RegisterClass decorator from @memberjunction/global.\n */\nexport interface IArtifactViewerPlugin {\n /**\n * The Angular component class that will be dynamically loaded to render the FULL artifact\n * (the right-side viewer panel — toolbar, tabs, feedback, etc.).\n * Must be a component type that accepts artifact input. REQUIRED.\n */\n readonly componentType: Type<IArtifactViewerComponent>;\n\n /**\n * Optional: Get display metadata for the artifact (title, icon, etc.)\n * @param artifactVersion The artifact version to get metadata for\n * @returns Display metadata object\n */\n getMetadata?(artifactVersion: MJArtifactVersionEntity): ArtifactMetadata;\n}\n\n/**\n * STATIC preview contract for an artifact-viewer plugin **class**.\n *\n * The inline-PREVIEW slot is resolved WITHOUT instantiating any plugin — the resolver reads these\n * STATIC members directly off the registered constructor. This is deliberate: plugins are Angular\n * components with DI constructors (and some use `inject()` in field initializers), so a bare\n * `new SubClass()` outside an Angular injection context throws. Reading statics sidesteps that\n * entirely.\n *\n * A plugin that wants to drive an inline preview declares both members as `static`:\n * - `static readonly PreviewComponentType` — the lightweight {@link IArtifactPreviewComponent}.\n * - `static CanHandlePreview(...)` — type/content matcher for the preview slot.\n *\n * Preview resolution is INDEPENDENT of full-viewer resolution: the inline slot is filled by the\n * highest-priority registered plugin class whose `CanHandlePreview` matches AND that exposes a\n * `PreviewComponentType`. A downstream plugin overriding the full viewer for a type but NOT\n * declaring `PreviewComponentType` therefore does not suppress a base plugin's preview. When no\n * registered class exposes a matching `PreviewComponentType`, no inline preview is rendered and the\n * card falls back to its existing info-bar box.\n */\nexport interface IArtifactViewerPluginPreviewStatics {\n /**\n * The lightweight component used to render an inline PREVIEW of the artifact directly inside a\n * conversation message card (no toolbar / feedback / tabs). Optional — plugins without a preview\n * omit it and the card falls back to its info-bar box.\n */\n readonly PreviewComponentType?: Type<IArtifactPreviewComponent>;\n\n /**\n * Determines whether this plugin's {@link PreviewComponentType} applies to a given artifact.\n * Plugins that declare a `PreviewComponentType` MUST also declare this; plugins without a preview\n * can omit it (the resolver skips them).\n *\n * @param artifactTypeName The artifact type name (e.g., 'Image', 'Video', 'Audio').\n * @param contentType The MIME type (e.g., 'image/png', 'video/mp4').\n * @returns true if this plugin's preview can render the artifact.\n */\n CanHandlePreview?(artifactTypeName: string, contentType?: string): boolean;\n}\n\n/**\n * Metadata about an artifact for display purposes\n */\nexport interface ArtifactMetadata {\n title?: string;\n icon?: string;\n description?: string;\n additionalInfo?: Record<string, any>;\n}\n\n/**\n * Base interface that all artifact viewer components must implement.\n * The component receives the artifact version as an input.\n */\nexport interface IArtifactViewerComponent {\n artifactVersion: MJArtifactVersionEntity;\n}\n\n/**\n * Base interface that all inline artifact PREVIEW components must implement.\n *\n * Previews are intentionally lightweight — they receive only the artifact version and render\n * a compact, read-only representation (e.g. a thumbnail `<img>`, a mini `<video>`/`<audio>`\n * player) suitable for embedding inside a conversation message card. Unlike full viewers,\n * previews have NO toolbar, feedback, tabs, or download chrome.\n */\nexport interface IArtifactPreviewComponent {\n artifactVersion: MJArtifactVersionEntity;\n}\n"]}
1
+ {"version":3,"file":"artifact-viewer-plugin.interface.js","sourceRoot":"","sources":["../../../src/lib/interfaces/artifact-viewer-plugin.interface.ts"],"names":[],"mappings":"","sourcesContent":["import { Type } from '@angular/core';\nimport { MJArtifactVersionEntity } from '@memberjunction/core-entities';\n\n/**\n * Interface for artifact viewer plugins.\n * All artifact viewer plugins must implement this interface and be registered\n * with @RegisterClass decorator from @memberjunction/global.\n */\nexport interface IArtifactViewerPlugin {\n /**\n * The Angular component class that will be dynamically loaded to render the FULL artifact\n * (the right-side viewer panel — toolbar, tabs, feedback, etc.).\n * Must be a component type that accepts artifact input. REQUIRED.\n */\n readonly componentType: Type<IArtifactViewerComponent>;\n\n /**\n * Optional: Get display metadata for the artifact (title, icon, etc.)\n * @param artifactVersion The artifact version to get metadata for\n * @returns Display metadata object\n */\n getMetadata?(artifactVersion: MJArtifactVersionEntity): ArtifactMetadata;\n}\n\n/**\n * STATIC preview contract for an artifact-viewer plugin **class**.\n *\n * The inline-PREVIEW slot is resolved WITHOUT instantiating any plugin — the resolver reads these\n * STATIC members directly off the registered constructor. This is deliberate: plugins are Angular\n * components with DI constructors (and some use `inject()` in field initializers), so a bare\n * `new SubClass()` outside an Angular injection context throws. Reading statics sidesteps that\n * entirely.\n *\n * A plugin that wants to drive an inline preview declares both members as `static`:\n * - `static readonly PreviewComponentType` — the lightweight {@link IArtifactPreviewComponent}.\n * - `static CanHandlePreview(...)` — type/content matcher for the preview slot.\n *\n * Preview resolution is INDEPENDENT of full-viewer resolution: the inline slot is filled by the\n * highest-priority registered plugin class whose `CanHandlePreview` matches AND that exposes a\n * `PreviewComponentType`. A downstream plugin overriding the full viewer for a type but NOT\n * declaring `PreviewComponentType` therefore does not suppress a base plugin's preview. When no\n * registered class exposes a matching `PreviewComponentType`, no inline preview is rendered and the\n * card falls back to its existing info-bar box.\n */\nexport interface IArtifactViewerPluginPreviewStatics {\n /**\n * The lightweight component used to render an inline PREVIEW of the artifact directly inside a\n * conversation message card (no toolbar / feedback / tabs). Optional — plugins without a preview\n * omit it and the card falls back to its info-bar box.\n */\n readonly PreviewComponentType?: Type<IArtifactPreviewComponent>;\n\n /**\n * Determines whether this plugin's {@link PreviewComponentType} applies to a given artifact.\n * Plugins that declare a `PreviewComponentType` MUST also declare this; plugins without a preview\n * can omit it (the resolver skips them).\n *\n * @param artifactTypeName The artifact type name (e.g., 'Image', 'Video', 'Audio').\n * @param contentType The MIME type (e.g., 'image/png', 'video/mp4').\n * @returns true if this plugin's preview can render the artifact.\n */\n CanHandlePreview?(artifactTypeName: string, contentType?: string): boolean;\n}\n\n/**\n * Metadata about an artifact for display purposes\n */\nexport interface ArtifactMetadata {\n title?: string;\n icon?: string;\n description?: string;\n additionalInfo?: Record<string, any>;\n}\n\n/**\n * Base interface that all artifact viewer components must implement.\n * The component receives the artifact version as an input.\n */\nexport interface IArtifactViewerComponent {\n artifactVersion: MJArtifactVersionEntity; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub\n}\n\n/**\n * Base interface that all inline artifact PREVIEW components must implement.\n *\n * Previews are intentionally lightweight — they receive only the artifact version and render\n * a compact, read-only representation (e.g. a thumbnail `<img>`, a mini `<video>`/`<audio>`\n * player) suitable for embedding inside a conversation message card. Unlike full viewers,\n * previews have NO toolbar, feedback, tabs, or download chrome.\n */\nexport interface IArtifactPreviewComponent {\n artifactVersion: MJArtifactVersionEntity; // case-violation-ok-legacy-back-compat: the type is named in an exported signature, so consumers build object literals against it; an interface has no runtime carrier for a stub\n}\n"]}
@@ -12,20 +12,28 @@ export declare class ArtifactFileService {
12
12
  * Returns a pre-authenticated download URL for the given artifact version.
13
13
  * Results are cached; pass `forceRefresh=true` to bypass the cache.
14
14
  */
15
+ GetDownloadUrl(artifactVersionId: string, forceRefresh?: boolean): Promise<string>;
16
+ /** @deprecated Use {@link GetDownloadUrl}. */
15
17
  getDownloadUrl(artifactVersionId: string, forceRefresh?: boolean): Promise<string>;
16
18
  /** Store a URL, evicting the oldest entry if the cache is at capacity. */
17
19
  private cacheUrl;
18
20
  /** Pre-fetch and cache a URL without awaiting in the calling context. */
21
+ Prefetch(artifactVersionId: string): void;
22
+ /** @deprecated Use {@link Prefetch}. */
19
23
  prefetch(artifactVersionId: string): void;
20
24
  /**
21
25
  * Converts a base64 data URL (data:mime;base64,...) to an ArrayBuffer.
22
26
  * Used by viewers to handle inline artifact content (ContentMode='Text').
23
27
  */
28
+ DataUrlToArrayBuffer(dataUrl: string): ArrayBuffer;
29
+ /** @deprecated Use {@link DataUrlToArrayBuffer}. */
24
30
  dataUrlToArrayBuffer(dataUrl: string): ArrayBuffer;
25
31
  /**
26
32
  * Converts a base64 data URL to an object URL suitable for download/display.
27
33
  * Used by viewers to create downloadable links for inline artifacts.
28
34
  */
35
+ DataUrlToObjectUrl(dataUrl: string, mimeType: string): string;
36
+ /** @deprecated Use {@link DataUrlToObjectUrl}. */
29
37
  dataUrlToObjectUrl(dataUrl: string, mimeType: string): string;
30
38
  static ɵfac: i0.ɵɵFactoryDeclaration<ArtifactFileService, never>;
31
39
  static ɵprov: i0.ɵɵInjectableDeclaration<ArtifactFileService>;
@@ -1 +1 @@
1
- {"version":3,"file":"artifact-file.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/artifact-file.service.ts"],"names":[],"mappings":";AAMA;;;;;GAKG;AACH,qBAGa,mBAAmB;IAE5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IAEtD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAIxC;IAEF;;;OAGG;IACU,cAAc,CAAC,iBAAiB,EAAE,MAAM,EAAE,YAAY,UAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAsB7F,0EAA0E;IAC1E,OAAO,CAAC,QAAQ;IAWhB,yEAAyE;IAClE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI;IAMhD;;;OAGG;IACI,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW;IAWzD;;;OAGG;IACI,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;yCA1E3D,mBAAmB;6CAAnB,mBAAmB;CA+E/B"}
1
+ {"version":3,"file":"artifact-file.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/artifact-file.service.ts"],"names":[],"mappings":";AAMA;;;;;GAKG;AACH,qBAGa,mBAAmB;IAE5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6B;IAEtD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAIxC;IAEF;;;OAGG;IACU,cAAc,CAAC,iBAAiB,EAAE,MAAM,EAAE,YAAY,UAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAsB7F,8CAA8C;IACjC,cAAc,CAAC,iBAAiB,EAAE,MAAM,EAAE,YAAY,UAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAI7F,0EAA0E;IAC1E,OAAO,CAAC,QAAQ;IAWhB,yEAAyE;IAClE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI;IAMhD,wCAAwC;IACjC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI;IAIhD;;;OAGG;IACI,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW;IAWzD,oDAAoD;IAC7C,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW;IAIzD;;;OAGG;IACI,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAMpE,kDAAkD;IAC3C,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;yCAhG3D,mBAAmB;6CAAnB,mBAAmB;CAmG/B"}
@@ -20,7 +20,7 @@ export class ArtifactFileService {
20
20
  * Returns a pre-authenticated download URL for the given artifact version.
21
21
  * Results are cached; pass `forceRefresh=true` to bypass the cache.
22
22
  */
23
- async getDownloadUrl(artifactVersionId, forceRefresh = false) {
23
+ async GetDownloadUrl(artifactVersionId, forceRefresh = false) {
24
24
  if (!forceRefresh) {
25
25
  const cached = this.urlCache.get(artifactVersionId);
26
26
  if (cached) {
@@ -35,6 +35,10 @@ export class ArtifactFileService {
35
35
  this.cacheUrl(artifactVersionId, url);
36
36
  return url;
37
37
  }
38
+ /** @deprecated Use {@link GetDownloadUrl}. */
39
+ async getDownloadUrl(artifactVersionId, forceRefresh = false) {
40
+ return this.GetDownloadUrl(artifactVersionId, forceRefresh);
41
+ }
38
42
  /** Store a URL, evicting the oldest entry if the cache is at capacity. */
39
43
  cacheUrl(key, url) {
40
44
  if (this.urlCache.size >= CACHE_MAX_SIZE) {
@@ -47,16 +51,20 @@ export class ArtifactFileService {
47
51
  this.urlCache.set(key, url);
48
52
  }
49
53
  /** Pre-fetch and cache a URL without awaiting in the calling context. */
50
- prefetch(artifactVersionId) {
51
- this.getDownloadUrl(artifactVersionId).catch(() => {
54
+ Prefetch(artifactVersionId) {
55
+ this.GetDownloadUrl(artifactVersionId).catch(() => {
52
56
  // Prefetch failures are silently ignored — the component will retry on display
53
57
  });
54
58
  }
59
+ /** @deprecated Use {@link Prefetch}. */
60
+ prefetch(artifactVersionId) {
61
+ return this.Prefetch(artifactVersionId);
62
+ }
55
63
  /**
56
64
  * Converts a base64 data URL (data:mime;base64,...) to an ArrayBuffer.
57
65
  * Used by viewers to handle inline artifact content (ContentMode='Text').
58
66
  */
59
- dataUrlToArrayBuffer(dataUrl) {
67
+ DataUrlToArrayBuffer(dataUrl) {
60
68
  const commaIndex = dataUrl.indexOf(',');
61
69
  const base64 = commaIndex >= 0 ? dataUrl.slice(commaIndex + 1) : dataUrl;
62
70
  const binary = atob(base64);
@@ -66,15 +74,23 @@ export class ArtifactFileService {
66
74
  }
67
75
  return bytes.buffer;
68
76
  }
77
+ /** @deprecated Use {@link DataUrlToArrayBuffer}. */
78
+ dataUrlToArrayBuffer(dataUrl) {
79
+ return this.DataUrlToArrayBuffer(dataUrl);
80
+ }
69
81
  /**
70
82
  * Converts a base64 data URL to an object URL suitable for download/display.
71
83
  * Used by viewers to create downloadable links for inline artifacts.
72
84
  */
73
- dataUrlToObjectUrl(dataUrl, mimeType) {
74
- const arrayBuffer = this.dataUrlToArrayBuffer(dataUrl);
85
+ DataUrlToObjectUrl(dataUrl, mimeType) {
86
+ const arrayBuffer = this.DataUrlToArrayBuffer(dataUrl);
75
87
  const blob = new Blob([arrayBuffer], { type: mimeType });
76
88
  return URL.createObjectURL(blob);
77
89
  }
90
+ /** @deprecated Use {@link DataUrlToObjectUrl}. */
91
+ dataUrlToObjectUrl(dataUrl, mimeType) {
92
+ return this.DataUrlToObjectUrl(dataUrl, mimeType);
93
+ }
78
94
  static ɵfac = function ArtifactFileService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ArtifactFileService)(); };
79
95
  static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: ArtifactFileService, factory: ArtifactFileService.ɵfac, providedIn: 'root' });
80
96
  }
@@ -1 +1 @@
1
- {"version":3,"file":"artifact-file.service.js","sourceRoot":"","sources":["../../../src/lib/services/artifact-file.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';\n\n/** Maximum number of URL entries to keep in the in-memory cache. */\nconst CACHE_MAX_SIZE = 20;\n\n/**\n * Service for fetching pre-authenticated download URLs for file-mode artifact versions.\n *\n * URLs are cached in a bounded LRU-style Map (evicts oldest entry once the cap is reached)\n * to avoid repeated round-trips for the same version within a session.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class ArtifactFileService {\n\n private readonly urlCache = new Map<string, string>();\n\n private static readonly DOWNLOAD_URL_QUERY = `\n query ArtifactFileDownloadUrl($artifactVersionId: String!) {\n ArtifactFileDownloadUrl(artifactVersionId: $artifactVersionId)\n }\n `;\n\n /**\n * Returns a pre-authenticated download URL for the given artifact version.\n * Results are cached; pass `forceRefresh=true` to bypass the cache.\n */\n public async getDownloadUrl(artifactVersionId: string, forceRefresh = false): Promise<string> {\n if (!forceRefresh) {\n const cached = this.urlCache.get(artifactVersionId);\n if (cached) {\n return cached;\n }\n }\n\n const result = await GraphQLDataProvider.ExecuteGQL(\n ArtifactFileService.DOWNLOAD_URL_QUERY,\n { artifactVersionId },\n ) as { ArtifactFileDownloadUrl?: string };\n\n const url = result?.ArtifactFileDownloadUrl;\n if (!url) {\n throw new Error(`Failed to get download URL for artifact version ${artifactVersionId}`);\n }\n\n this.cacheUrl(artifactVersionId, url);\n return url;\n }\n\n /** Store a URL, evicting the oldest entry if the cache is at capacity. */\n private cacheUrl(key: string, url: string): void {\n if (this.urlCache.size >= CACHE_MAX_SIZE) {\n // Map preserves insertion order; delete the first (oldest) entry\n const oldestKey = this.urlCache.keys().next().value;\n if (oldestKey !== undefined) {\n this.urlCache.delete(oldestKey);\n }\n }\n this.urlCache.set(key, url);\n }\n\n /** Pre-fetch and cache a URL without awaiting in the calling context. */\n public prefetch(artifactVersionId: string): void {\n this.getDownloadUrl(artifactVersionId).catch(() => {\n // Prefetch failures are silently ignored — the component will retry on display\n });\n }\n\n /**\n * Converts a base64 data URL (data:mime;base64,...) to an ArrayBuffer.\n * Used by viewers to handle inline artifact content (ContentMode='Text').\n */\n public dataUrlToArrayBuffer(dataUrl: string): ArrayBuffer {\n const commaIndex = dataUrl.indexOf(',');\n const base64 = commaIndex >= 0 ? dataUrl.slice(commaIndex + 1) : dataUrl;\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes.buffer;\n }\n\n /**\n * Converts a base64 data URL to an object URL suitable for download/display.\n * Used by viewers to create downloadable links for inline artifacts.\n */\n public dataUrlToObjectUrl(dataUrl: string, mimeType: string): string {\n const arrayBuffer = this.dataUrlToArrayBuffer(dataUrl);\n const blob = new Blob([arrayBuffer], { type: mimeType });\n return URL.createObjectURL(blob);\n }\n}\n"]}
1
+ {"version":3,"file":"artifact-file.service.js","sourceRoot":"","sources":["../../../src/lib/services/artifact-file.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { GraphQLDataProvider } from '@memberjunction/graphql-dataprovider';\n\n/** Maximum number of URL entries to keep in the in-memory cache. */\nconst CACHE_MAX_SIZE = 20;\n\n/**\n * Service for fetching pre-authenticated download URLs for file-mode artifact versions.\n *\n * URLs are cached in a bounded LRU-style Map (evicts oldest entry once the cap is reached)\n * to avoid repeated round-trips for the same version within a session.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class ArtifactFileService {\n\n private readonly urlCache = new Map<string, string>();\n\n private static readonly DOWNLOAD_URL_QUERY = `\n query ArtifactFileDownloadUrl($artifactVersionId: String!) {\n ArtifactFileDownloadUrl(artifactVersionId: $artifactVersionId)\n }\n `;\n\n /**\n * Returns a pre-authenticated download URL for the given artifact version.\n * Results are cached; pass `forceRefresh=true` to bypass the cache.\n */\n public async GetDownloadUrl(artifactVersionId: string, forceRefresh = false): Promise<string> {\n if (!forceRefresh) {\n const cached = this.urlCache.get(artifactVersionId);\n if (cached) {\n return cached;\n }\n }\n\n const result = await GraphQLDataProvider.ExecuteGQL(\n ArtifactFileService.DOWNLOAD_URL_QUERY,\n { artifactVersionId },\n ) as { ArtifactFileDownloadUrl?: string };\n\n const url = result?.ArtifactFileDownloadUrl;\n if (!url) {\n throw new Error(`Failed to get download URL for artifact version ${artifactVersionId}`);\n }\n\n this.cacheUrl(artifactVersionId, url);\n return url;\n }\n\n /** @deprecated Use {@link GetDownloadUrl}. */\n public async getDownloadUrl(artifactVersionId: string, forceRefresh = false): Promise<string> {\n return this.GetDownloadUrl(artifactVersionId, forceRefresh);\n }\n\n /** Store a URL, evicting the oldest entry if the cache is at capacity. */\n private cacheUrl(key: string, url: string): void {\n if (this.urlCache.size >= CACHE_MAX_SIZE) {\n // Map preserves insertion order; delete the first (oldest) entry\n const oldestKey = this.urlCache.keys().next().value;\n if (oldestKey !== undefined) {\n this.urlCache.delete(oldestKey);\n }\n }\n this.urlCache.set(key, url);\n }\n\n /** Pre-fetch and cache a URL without awaiting in the calling context. */\n public Prefetch(artifactVersionId: string): void {\n this.GetDownloadUrl(artifactVersionId).catch(() => {\n // Prefetch failures are silently ignored — the component will retry on display\n });\n }\n\n /** @deprecated Use {@link Prefetch}. */\n public prefetch(artifactVersionId: string): void {\n return this.Prefetch(artifactVersionId);\n }\n\n /**\n * Converts a base64 data URL (data:mime;base64,...) to an ArrayBuffer.\n * Used by viewers to handle inline artifact content (ContentMode='Text').\n */\n public DataUrlToArrayBuffer(dataUrl: string): ArrayBuffer {\n const commaIndex = dataUrl.indexOf(',');\n const base64 = commaIndex >= 0 ? dataUrl.slice(commaIndex + 1) : dataUrl;\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes.buffer;\n }\n\n /** @deprecated Use {@link DataUrlToArrayBuffer}. */\n public dataUrlToArrayBuffer(dataUrl: string): ArrayBuffer {\n return this.DataUrlToArrayBuffer(dataUrl);\n }\n\n /**\n * Converts a base64 data URL to an object URL suitable for download/display.\n * Used by viewers to create downloadable links for inline artifacts.\n */\n public DataUrlToObjectUrl(dataUrl: string, mimeType: string): string {\n const arrayBuffer = this.DataUrlToArrayBuffer(dataUrl);\n const blob = new Blob([arrayBuffer], { type: mimeType });\n return URL.createObjectURL(blob);\n }\n\n /** @deprecated Use {@link DataUrlToObjectUrl}. */\n public dataUrlToObjectUrl(dataUrl: string, mimeType: string): string {\n return this.DataUrlToObjectUrl(dataUrl, mimeType);\n }\n}\n"]}
@@ -14,6 +14,8 @@ export declare class ArtifactIconService {
14
14
  * @param pluginIcon Optional icon provided by a viewer plugin (highest priority)
15
15
  * @returns Font Awesome icon class (e.g., 'fa-file-code', 'fa-chart-line')
16
16
  */
17
+ GetArtifactIcon(artifact: MJConversationArtifactEntity | MJArtifactEntity, pluginIcon?: string): string;
18
+ /** @deprecated Use {@link GetArtifactIcon}. */
17
19
  getArtifactIcon(artifact: MJConversationArtifactEntity | MJArtifactEntity, pluginIcon?: string): string;
18
20
  /**
19
21
  * Attempts to retrieve icon from artifact type metadata.
@@ -1 +1 @@
1
- {"version":3,"file":"artifact-icon.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/artifact-icon.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,4BAA4B,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;;AAE/F;;;;;;GAMG;AACH,qBAGa,mBAAmB;IAC5B;;;;;OAKG;IACI,eAAe,CAAC,QAAQ,EAAE,4BAA4B,GAAG,gBAAgB,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM;IAoB9G;;OAEG;IACH,OAAO,CAAC,eAAe;IAcvB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;yCAhDf,mBAAmB;6CAAnB,mBAAmB;CAsF/B"}
1
+ {"version":3,"file":"artifact-icon.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/artifact-icon.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,4BAA4B,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;;AAE/F;;;;;;GAMG;AACH,qBAGa,mBAAmB;IAC5B;;;;;OAKG;IACI,eAAe,CAAC,QAAQ,EAAE,4BAA4B,GAAG,gBAAgB,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM;IAoB9G,+CAA+C;IACxC,eAAe,CAAC,QAAQ,EAAE,4BAA4B,GAAG,gBAAgB,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM;IAI9G;;OAEG;IACH,OAAO,CAAC,eAAe;IAcvB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;yCArDf,mBAAmB;6CAAnB,mBAAmB;CA2F/B"}
@@ -15,7 +15,7 @@ export class ArtifactIconService {
15
15
  * @param pluginIcon Optional icon provided by a viewer plugin (highest priority)
16
16
  * @returns Font Awesome icon class (e.g., 'fa-file-code', 'fa-chart-line')
17
17
  */
18
- getArtifactIcon(artifact, pluginIcon) {
18
+ GetArtifactIcon(artifact, pluginIcon) {
19
19
  if (!artifact) {
20
20
  return 'fa-file';
21
21
  }
@@ -31,6 +31,10 @@ export class ArtifactIconService {
31
31
  // Priority 3: Hardcoded type-based fallback
32
32
  return this.getHardcodedIcon(artifact);
33
33
  }
34
+ /** @deprecated Use {@link GetArtifactIcon}. */
35
+ getArtifactIcon(artifact, pluginIcon) {
36
+ return this.GetArtifactIcon(artifact, pluginIcon);
37
+ }
34
38
  /**
35
39
  * Attempts to retrieve icon from artifact type metadata.
36
40
  */
@@ -1 +1 @@
1
- {"version":3,"file":"artifact-icon.service.js","sourceRoot":"","sources":["../../../src/lib/services/artifact-icon.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;;AAGvE;;;;;;GAMG;AAIH,MAAM,OAAO,mBAAmB;IAC5B;;;;;OAKG;IACI,eAAe,CAAC,QAAyD,EAAE,UAAmB;QACjG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,OAAO,SAAS,CAAC;QACrB,CAAC;QAED,mCAAmC;QACnC,IAAI,UAAU,EAAE,CAAC;YACb,OAAO,UAAU,CAAC;QACtB,CAAC;QAED,qCAAqC;QACrC,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QACpD,IAAI,YAAY,EAAE,CAAC;YACf,OAAO,YAAY,CAAC;QACxB,CAAC;QAED,4CAA4C;QAC5C,OAAO,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,QAAyD;QAC7E,IAAI,CAAC;YACD,uFAAuF;YACvF,MAAM,QAAQ,GAAG,cAAc,IAAI,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;YACpF,MAAM,YAAY,GAAG,sBAAsB,CAAC,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAChF,IAAI,YAAY,EAAE,IAAI,EAAE,CAAC;gBACrB,OAAO,YAAY,CAAC,IAAI,CAAC;YAC7B,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,iDAAiD,EAAE,KAAK,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;OAGG;IACK,gBAAgB,CAAC,QAAyD;QAC9E,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QAChD,uFAAuF;QACvF,MAAM,QAAQ,GAAG,cAAc,IAAI,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QACpF,MAAM,IAAI,GAAG,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QAE3C,iBAAiB;QACjB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,OAAO,cAAc,CAAC;QAC1B,CAAC;QAED,mBAAmB;QACnB,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,OAAO,eAAe,CAAC;QAC3B,CAAC;QAED,sBAAsB;QACtB,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,OAAO,cAAc,CAAC;QAC1B,CAAC;QAED,qBAAqB;QACrB,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACpD,OAAO,eAAe,CAAC;QAC3B,CAAC;QAED,2BAA2B;QAC3B,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACzB,OAAO,cAAc,CAAC;QAC1B,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACzB,OAAO,cAAc,CAAC;QAC1B,CAAC;QAED,mBAAmB;QACnB,OAAO,SAAS,CAAC;IACrB,CAAC;6GArFQ,mBAAmB;gEAAnB,mBAAmB,WAAnB,mBAAmB,mBAFhB,MAAM;;iFAET,mBAAmB;cAH/B,UAAU;eAAC;gBACR,UAAU,EAAE,MAAM;aACrB","sourcesContent":["import { Injectable } from '@angular/core';\nimport { ArtifactMetadataEngine } from '@memberjunction/core-entities';\nimport { MJConversationArtifactEntity, MJArtifactEntity } from '@memberjunction/core-entities';\n\n/**\n * Service for determining which icon to display for artifacts.\n * Implements a three-tier fallback strategy:\n * 1. Plugin-provided icon (from artifact viewer plugin metadata)\n * 2. Database metadata icon (from ArtifactType.Icon field)\n * 3. Hardcoded type-based mapping (legacy fallback)\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class ArtifactIconService {\n /**\n * Gets the appropriate Font Awesome icon class for an artifact.\n * @param artifact The artifact to get an icon for (MJConversationArtifactEntity or MJArtifactEntity)\n * @param pluginIcon Optional icon provided by a viewer plugin (highest priority)\n * @returns Font Awesome icon class (e.g., 'fa-file-code', 'fa-chart-line')\n */\n public getArtifactIcon(artifact: MJConversationArtifactEntity | MJArtifactEntity, pluginIcon?: string): string {\n if (!artifact) {\n return 'fa-file';\n }\n\n // Priority 1: Plugin-provided icon\n if (pluginIcon) {\n return pluginIcon;\n }\n\n // Priority 2: Database metadata icon\n const metadataIcon = this.getMetadataIcon(artifact);\n if (metadataIcon) {\n return metadataIcon;\n }\n\n // Priority 3: Hardcoded type-based fallback\n return this.getHardcodedIcon(artifact);\n }\n\n /**\n * Attempts to retrieve icon from artifact type metadata.\n */\n private getMetadataIcon(artifact: MJConversationArtifactEntity | MJArtifactEntity): string | null {\n try {\n // MJConversationArtifactEntity has ArtifactType field, MJArtifactEntity has Type field\n const typeName = 'ArtifactType' in artifact ? artifact.ArtifactType : artifact.Type;\n const artifactType = ArtifactMetadataEngine.Instance.FindArtifactType(typeName);\n if (artifactType?.Icon) {\n return artifactType.Icon;\n }\n } catch (error) {\n console.warn('Failed to load artifact type metadata for icon:', error);\n }\n return null;\n }\n\n /**\n * Legacy hardcoded icon mapping based on artifact type and name.\n * This provides backward compatibility for artifacts without metadata icons.\n */\n private getHardcodedIcon(artifact: MJConversationArtifactEntity | MJArtifactEntity): string {\n const name = artifact.Name?.toLowerCase() || '';\n // MJConversationArtifactEntity has ArtifactType field, MJArtifactEntity has Type field\n const typeName = 'ArtifactType' in artifact ? artifact.ArtifactType : artifact.Type;\n const type = typeName?.toLowerCase() || '';\n\n // Code artifacts\n if (type.includes('code')) {\n return 'fa-file-code';\n }\n\n // Report artifacts\n if (type.includes('report')) {\n return 'fa-chart-line';\n }\n\n // Dashboard artifacts\n if (type.includes('dashboard')) {\n return 'fa-chart-bar';\n }\n\n // Document artifacts\n if (type.includes('document') || name.endsWith('.md')) {\n return 'fa-file-lines';\n }\n\n // Specific file extensions\n if (name.endsWith('.json')) {\n return 'fa-file-code';\n }\n\n if (name.endsWith('.html')) {\n return 'fa-file-code';\n }\n\n // Default fallback\n return 'fa-file';\n }\n}\n"]}
1
+ {"version":3,"file":"artifact-icon.service.js","sourceRoot":"","sources":["../../../src/lib/services/artifact-icon.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { ArtifactMetadataEngine } from '@memberjunction/core-entities';\nimport { MJConversationArtifactEntity, MJArtifactEntity } from '@memberjunction/core-entities';\n\n/**\n * Service for determining which icon to display for artifacts.\n * Implements a three-tier fallback strategy:\n * 1. Plugin-provided icon (from artifact viewer plugin metadata)\n * 2. Database metadata icon (from ArtifactType.Icon field)\n * 3. Hardcoded type-based mapping (legacy fallback)\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class ArtifactIconService {\n /**\n * Gets the appropriate Font Awesome icon class for an artifact.\n * @param artifact The artifact to get an icon for (MJConversationArtifactEntity or MJArtifactEntity)\n * @param pluginIcon Optional icon provided by a viewer plugin (highest priority)\n * @returns Font Awesome icon class (e.g., 'fa-file-code', 'fa-chart-line')\n */\n public GetArtifactIcon(artifact: MJConversationArtifactEntity | MJArtifactEntity, pluginIcon?: string): string {\n if (!artifact) {\n return 'fa-file';\n }\n\n // Priority 1: Plugin-provided icon\n if (pluginIcon) {\n return pluginIcon;\n }\n\n // Priority 2: Database metadata icon\n const metadataIcon = this.getMetadataIcon(artifact);\n if (metadataIcon) {\n return metadataIcon;\n }\n\n // Priority 3: Hardcoded type-based fallback\n return this.getHardcodedIcon(artifact);\n }\n\n /** @deprecated Use {@link GetArtifactIcon}. */\n public getArtifactIcon(artifact: MJConversationArtifactEntity | MJArtifactEntity, pluginIcon?: string): string {\n return this.GetArtifactIcon(artifact, pluginIcon);\n }\n\n /**\n * Attempts to retrieve icon from artifact type metadata.\n */\n private getMetadataIcon(artifact: MJConversationArtifactEntity | MJArtifactEntity): string | null {\n try {\n // MJConversationArtifactEntity has ArtifactType field, MJArtifactEntity has Type field\n const typeName = 'ArtifactType' in artifact ? artifact.ArtifactType : artifact.Type;\n const artifactType = ArtifactMetadataEngine.Instance.FindArtifactType(typeName);\n if (artifactType?.Icon) {\n return artifactType.Icon;\n }\n } catch (error) {\n console.warn('Failed to load artifact type metadata for icon:', error);\n }\n return null;\n }\n\n /**\n * Legacy hardcoded icon mapping based on artifact type and name.\n * This provides backward compatibility for artifacts without metadata icons.\n */\n private getHardcodedIcon(artifact: MJConversationArtifactEntity | MJArtifactEntity): string {\n const name = artifact.Name?.toLowerCase() || '';\n // MJConversationArtifactEntity has ArtifactType field, MJArtifactEntity has Type field\n const typeName = 'ArtifactType' in artifact ? artifact.ArtifactType : artifact.Type;\n const type = typeName?.toLowerCase() || '';\n\n // Code artifacts\n if (type.includes('code')) {\n return 'fa-file-code';\n }\n\n // Report artifacts\n if (type.includes('report')) {\n return 'fa-chart-line';\n }\n\n // Dashboard artifacts\n if (type.includes('dashboard')) {\n return 'fa-chart-bar';\n }\n\n // Document artifacts\n if (type.includes('document') || name.endsWith('.md')) {\n return 'fa-file-lines';\n }\n\n // Specific file extensions\n if (name.endsWith('.json')) {\n return 'fa-file-code';\n }\n\n if (name.endsWith('.html')) {\n return 'fa-file-code';\n }\n\n // Default fallback\n return 'fa-file';\n }\n}\n"]}
@@ -32,6 +32,8 @@ export declare class ArtifactPreviewResolverService {
32
32
  * @param artifactTypeName The artifact's type name (e.g. from `artifact.Type`).
33
33
  * @param contentType The version MIME type (e.g. from `artifactVersion.MimeType`).
34
34
  */
35
+ ResolvePreviewComponent(artifactTypeName: string | null | undefined, contentType: string | null | undefined): Type<IArtifactPreviewComponent> | null;
36
+ /** @deprecated Use {@link ResolvePreviewComponent}. */
35
37
  resolvePreviewComponent(artifactTypeName: string | null | undefined, contentType: string | null | undefined): Type<IArtifactPreviewComponent> | null;
36
38
  static ɵfac: i0.ɵɵFactoryDeclaration<ArtifactPreviewResolverService, never>;
37
39
  static ɵprov: i0.ɵɵInjectableDeclaration<ArtifactPreviewResolverService>;
@@ -1 +1 @@
1
- {"version":3,"file":"artifact-preview-resolver.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/artifact-preview-resolver.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,IAAI,EAAE,MAAM,eAAe,CAAC;AAGjD,OAAO,EACH,yBAAyB,EAE5B,MAAM,gDAAgD,CAAC;;AAUxD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAGa,8BAA8B;IACvC;;;;;;;OAOG;IACI,uBAAuB,CAC1B,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC3C,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACvC,IAAI,CAAC,yBAAyB,CAAC,GAAG,IAAI;yCAZhC,8BAA8B;6CAA9B,8BAA8B;CAqD1C"}
1
+ {"version":3,"file":"artifact-preview-resolver.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/artifact-preview-resolver.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,IAAI,EAAE,MAAM,eAAe,CAAC;AAGjD,OAAO,EACH,yBAAyB,EAE5B,MAAM,gDAAgD,CAAC;;AAUxD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAGa,8BAA8B;IACvC;;;;;;;OAOG;IACI,uBAAuB,CAC1B,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC3C,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACvC,IAAI,CAAC,yBAAyB,CAAC,GAAG,IAAI;IA0CzC,uDAAuD;IAChD,uBAAuB,CAC1B,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC3C,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACvC,IAAI,CAAC,yBAAyB,CAAC,GAAG,IAAI;yCA1DhC,8BAA8B;6CAA9B,8BAA8B;CA6D1C"}
@@ -33,7 +33,7 @@ export class ArtifactPreviewResolverService {
33
33
  * @param artifactTypeName The artifact's type name (e.g. from `artifact.Type`).
34
34
  * @param contentType The version MIME type (e.g. from `artifactVersion.MimeType`).
35
35
  */
36
- resolvePreviewComponent(artifactTypeName, contentType) {
36
+ ResolvePreviewComponent(artifactTypeName, contentType) {
37
37
  if (!artifactTypeName && !contentType) {
38
38
  return null;
39
39
  }
@@ -66,6 +66,10 @@ export class ArtifactPreviewResolverService {
66
66
  }
67
67
  return best?.preview ?? null;
68
68
  }
69
+ /** @deprecated Use {@link ResolvePreviewComponent}. */
70
+ resolvePreviewComponent(artifactTypeName, contentType) {
71
+ return this.ResolvePreviewComponent(artifactTypeName, contentType);
72
+ }
69
73
  static ɵfac = function ArtifactPreviewResolverService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ArtifactPreviewResolverService)(); };
70
74
  static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: ArtifactPreviewResolverService, factory: ArtifactPreviewResolverService.ɵfac, providedIn: 'root' });
71
75
  }
@@ -1 +1 @@
1
- {"version":3,"file":"artifact-preview-resolver.service.js","sourceRoot":"","sources":["../../../src/lib/services/artifact-preview-resolver.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAQ,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,iCAAiC,EAAE,MAAM,8CAA8C,CAAC;;AAcjG;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,MAAM,OAAO,8BAA8B;IACvC;;;;;;;OAOG;IACI,uBAAuB,CAC1B,gBAA2C,EAC3C,WAAsC;QAEtC,IAAI,CAAC,gBAAgB,IAAI,CAAC,WAAW,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,aAAa,GAAG,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,mBAAmB,CAAC,iCAAiC,CAAC,CAAC;QAC5G,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/C,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,2FAA2F;QAC3F,4FAA4F;QAC5F,YAAY;QACZ,MAAM,OAAO,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAE3E,IAAI,IAAI,GAA0E,IAAI,CAAC;QAEvF,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,GAAG,CAAC,QAAiD,CAAC;YAClE,IAAI,CAAC,GAAG,EAAE,CAAC;gBACP,SAAS;YACb,CAAC;YAED,mEAAmE;YACnE,MAAM,OAAO,GAAG,GAAG,CAAC,oBAAoB,CAAC;YACzC,IAAI,CAAC,OAAO,IAAI,OAAO,GAAG,CAAC,gBAAgB,KAAK,UAAU,EAAE,CAAC;gBACzD,SAAS;YACb,CAAC;YAED,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,gBAAgB,IAAI,EAAE,EAAE,WAAW,IAAI,SAAS,CAAC,EAAE,CAAC;gBAC1E,SAAS;YACb,CAAC;YAED,8EAA8E;YAC9E,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACzC,IAAI,GAAG,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;YAC/C,CAAC;QACL,CAAC;QAED,OAAO,IAAI,EAAE,OAAO,IAAI,IAAI,CAAC;IACjC,CAAC;wHApDQ,8BAA8B;gEAA9B,8BAA8B,WAA9B,8BAA8B,mBAF3B,MAAM;;iFAET,8BAA8B;cAH1C,UAAU;eAAC;gBACR,UAAU,EAAE,MAAM;aACrB","sourcesContent":["import { Injectable, Type } from '@angular/core';\nimport { MJGlobal } from '@memberjunction/global';\nimport { BaseArtifactViewerPluginComponent } from '../components/base-artifact-viewer.component';\nimport {\n IArtifactPreviewComponent,\n IArtifactViewerPluginPreviewStatics,\n} from '../interfaces/artifact-viewer-plugin.interface';\n\n/**\n * A registered artifact-viewer plugin **constructor** that MAY carry the static inline-preview\n * contract ({@link IArtifactViewerPluginPreviewStatics}). The resolver reads these statics off the\n * constructor directly — it never instantiates the plugin. Plugins that don't declare a preview\n * simply leave both members undefined.\n */\ntype PreviewCapableViewerClass = Type<BaseArtifactViewerPluginComponent> & IArtifactViewerPluginPreviewStatics;\n\n/**\n * Resolves the inline-PREVIEW component for an artifact, INDEPENDENTLY of full-viewer resolution.\n *\n * The full viewer ({@link ArtifactTypePluginViewerComponent}) resolves by the artifact type's\n * `DriverClass`. The inline preview, by contrast, is resolved by enumerating every registered\n * artifact-viewer plugin CLASS and picking the highest-priority one that BOTH:\n * 1. exposes a static `PreviewComponentType`, AND\n * 2. returns `true` from its static `CanHandlePreview(typeName, contentType)`.\n *\n * The preview contract is read STATICALLY — the resolver NEVER instantiates a plugin. Plugins are\n * Angular components with DI constructors (and some use `inject()` in field initializers), so a\n * bare `new SubClass()` outside an Angular injection context throws (\"inject() must be called from\n * an injection context\"). Reading statics off the registered constructor sidesteps that entirely.\n *\n * Why independent: a downstream plugin can override the full VIEWER for a type without supplying a\n * `PreviewComponentType` — that must NOT suppress a base plugin's preview. Conversely a broad\n * viewer can coexist with a specialized preview. By resolving the preview slot on its own, neither\n * decision constrains the other.\n *\n * Ordering mirrors {@link ClassFactory.GetRegistration}: highest `Priority` wins, and on a tie the\n * LAST-registered plugin wins (later registrations auto-increment priority, so this is rarely a tie).\n */\n@Injectable({\n providedIn: 'root',\n})\nexport class ArtifactPreviewResolverService {\n /**\n * Returns the preview component type for the given artifact type/content, or `null` when no\n * registered plugin class exposes a matching static `PreviewComponentType` (caller falls back\n * to its box).\n *\n * @param artifactTypeName The artifact's type name (e.g. from `artifact.Type`).\n * @param contentType The version MIME type (e.g. from `artifactVersion.MimeType`).\n */\n public resolvePreviewComponent(\n artifactTypeName: string | null | undefined,\n contentType: string | null | undefined,\n ): Type<IArtifactPreviewComponent> | null {\n if (!artifactTypeName && !contentType) {\n return null;\n }\n\n const registrations = MJGlobal.Instance.ClassFactory.GetAllRegistrations(BaseArtifactViewerPluginComponent);\n if (!registrations || registrations.length === 0) {\n return null;\n }\n\n // Highest priority first; on a tie, later array position (later registration) wins — so we\n // walk in ascending-priority order and let a `>=` comparison keep the LAST match at a given\n // priority.\n const ordered = [...registrations].sort((a, b) => a.Priority - b.Priority);\n\n let best: { priority: number; preview: Type<IArtifactPreviewComponent> } | null = null;\n\n for (const reg of ordered) {\n const cls = reg.SubClass as PreviewCapableViewerClass | undefined;\n if (!cls) {\n continue;\n }\n\n // Read the STATIC contract off the constructor — no instantiation.\n const preview = cls.PreviewComponentType;\n if (!preview || typeof cls.CanHandlePreview !== 'function') {\n continue;\n }\n\n if (!cls.CanHandlePreview(artifactTypeName ?? '', contentType ?? undefined)) {\n continue;\n }\n\n // `>=` so a later registration at the SAME priority overrides an earlier one.\n if (!best || reg.Priority >= best.priority) {\n best = { priority: reg.Priority, preview };\n }\n }\n\n return best?.preview ?? null;\n }\n}\n"]}
1
+ {"version":3,"file":"artifact-preview-resolver.service.js","sourceRoot":"","sources":["../../../src/lib/services/artifact-preview-resolver.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAQ,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,iCAAiC,EAAE,MAAM,8CAA8C,CAAC;;AAcjG;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,MAAM,OAAO,8BAA8B;IACvC;;;;;;;OAOG;IACI,uBAAuB,CAC1B,gBAA2C,EAC3C,WAAsC;QAEtC,IAAI,CAAC,gBAAgB,IAAI,CAAC,WAAW,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,aAAa,GAAG,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,mBAAmB,CAAC,iCAAiC,CAAC,CAAC;QAC5G,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/C,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,2FAA2F;QAC3F,4FAA4F;QAC5F,YAAY;QACZ,MAAM,OAAO,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAE3E,IAAI,IAAI,GAA0E,IAAI,CAAC;QAEvF,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,GAAG,CAAC,QAAiD,CAAC;YAClE,IAAI,CAAC,GAAG,EAAE,CAAC;gBACP,SAAS;YACb,CAAC;YAED,mEAAmE;YACnE,MAAM,OAAO,GAAG,GAAG,CAAC,oBAAoB,CAAC;YACzC,IAAI,CAAC,OAAO,IAAI,OAAO,GAAG,CAAC,gBAAgB,KAAK,UAAU,EAAE,CAAC;gBACzD,SAAS;YACb,CAAC;YAED,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,gBAAgB,IAAI,EAAE,EAAE,WAAW,IAAI,SAAS,CAAC,EAAE,CAAC;gBAC1E,SAAS;YACb,CAAC;YAED,8EAA8E;YAC9E,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACzC,IAAI,GAAG,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;YAC/C,CAAC;QACL,CAAC;QAED,OAAO,IAAI,EAAE,OAAO,IAAI,IAAI,CAAC;IACjC,CAAC;IAED,uDAAuD;IAChD,uBAAuB,CAC1B,gBAA2C,EAC3C,WAAsC;QAEtC,OAAO,IAAI,CAAC,uBAAuB,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;IACvE,CAAC;wHA5DQ,8BAA8B;gEAA9B,8BAA8B,WAA9B,8BAA8B,mBAF3B,MAAM;;iFAET,8BAA8B;cAH1C,UAAU;eAAC;gBACR,UAAU,EAAE,MAAM;aACrB","sourcesContent":["import { Injectable, Type } from '@angular/core';\nimport { MJGlobal } from '@memberjunction/global';\nimport { BaseArtifactViewerPluginComponent } from '../components/base-artifact-viewer.component';\nimport {\n IArtifactPreviewComponent,\n IArtifactViewerPluginPreviewStatics,\n} from '../interfaces/artifact-viewer-plugin.interface';\n\n/**\n * A registered artifact-viewer plugin **constructor** that MAY carry the static inline-preview\n * contract ({@link IArtifactViewerPluginPreviewStatics}). The resolver reads these statics off the\n * constructor directly — it never instantiates the plugin. Plugins that don't declare a preview\n * simply leave both members undefined.\n */\ntype PreviewCapableViewerClass = Type<BaseArtifactViewerPluginComponent> & IArtifactViewerPluginPreviewStatics;\n\n/**\n * Resolves the inline-PREVIEW component for an artifact, INDEPENDENTLY of full-viewer resolution.\n *\n * The full viewer ({@link ArtifactTypePluginViewerComponent}) resolves by the artifact type's\n * `DriverClass`. The inline preview, by contrast, is resolved by enumerating every registered\n * artifact-viewer plugin CLASS and picking the highest-priority one that BOTH:\n * 1. exposes a static `PreviewComponentType`, AND\n * 2. returns `true` from its static `CanHandlePreview(typeName, contentType)`.\n *\n * The preview contract is read STATICALLY — the resolver NEVER instantiates a plugin. Plugins are\n * Angular components with DI constructors (and some use `inject()` in field initializers), so a\n * bare `new SubClass()` outside an Angular injection context throws (\"inject() must be called from\n * an injection context\"). Reading statics off the registered constructor sidesteps that entirely.\n *\n * Why independent: a downstream plugin can override the full VIEWER for a type without supplying a\n * `PreviewComponentType` — that must NOT suppress a base plugin's preview. Conversely a broad\n * viewer can coexist with a specialized preview. By resolving the preview slot on its own, neither\n * decision constrains the other.\n *\n * Ordering mirrors {@link ClassFactory.GetRegistration}: highest `Priority` wins, and on a tie the\n * LAST-registered plugin wins (later registrations auto-increment priority, so this is rarely a tie).\n */\n@Injectable({\n providedIn: 'root',\n})\nexport class ArtifactPreviewResolverService {\n /**\n * Returns the preview component type for the given artifact type/content, or `null` when no\n * registered plugin class exposes a matching static `PreviewComponentType` (caller falls back\n * to its box).\n *\n * @param artifactTypeName The artifact's type name (e.g. from `artifact.Type`).\n * @param contentType The version MIME type (e.g. from `artifactVersion.MimeType`).\n */\n public ResolvePreviewComponent(\n artifactTypeName: string | null | undefined,\n contentType: string | null | undefined,\n ): Type<IArtifactPreviewComponent> | null {\n if (!artifactTypeName && !contentType) {\n return null;\n }\n\n const registrations = MJGlobal.Instance.ClassFactory.GetAllRegistrations(BaseArtifactViewerPluginComponent);\n if (!registrations || registrations.length === 0) {\n return null;\n }\n\n // Highest priority first; on a tie, later array position (later registration) wins — so we\n // walk in ascending-priority order and let a `>=` comparison keep the LAST match at a given\n // priority.\n const ordered = [...registrations].sort((a, b) => a.Priority - b.Priority);\n\n let best: { priority: number; preview: Type<IArtifactPreviewComponent> } | null = null;\n\n for (const reg of ordered) {\n const cls = reg.SubClass as PreviewCapableViewerClass | undefined;\n if (!cls) {\n continue;\n }\n\n // Read the STATIC contract off the constructor — no instantiation.\n const preview = cls.PreviewComponentType;\n if (!preview || typeof cls.CanHandlePreview !== 'function') {\n continue;\n }\n\n if (!cls.CanHandlePreview(artifactTypeName ?? '', contentType ?? undefined)) {\n continue;\n }\n\n // `>=` so a later registration at the SAME priority overrides an earlier one.\n if (!best || reg.Priority >= best.priority) {\n best = { priority: reg.Priority, preview };\n }\n }\n\n return best?.preview ?? null;\n }\n\n /** @deprecated Use {@link ResolvePreviewComponent}. */\n public resolvePreviewComponent(\n artifactTypeName: string | null | undefined,\n contentType: string | null | undefined,\n ): Type<IArtifactPreviewComponent> | null {\n return this.ResolvePreviewComponent(artifactTypeName, contentType);\n }\n}\n"]}
@@ -23,16 +23,22 @@ interface DataArtifactSpecLike {
23
23
  * Create a DataSnapshot from JSON artifact content.
24
24
  * Parses the JSON, counts top-level keys, and stores the parsed value in custom.
25
25
  */
26
+ export declare function CreateJsonSnapshot(content: string | null, title: string | null): DataSnapshot | null;
27
+ /** @deprecated Use {@link CreateJsonSnapshot}. */
26
28
  export declare function createJsonSnapshot(content: string | null, title: string | null): DataSnapshot | null;
27
29
  /**
28
30
  * Create a DataSnapshot from code artifact content.
29
31
  * Counts lines and stores content plus lineCount in custom.
30
32
  */
33
+ export declare function CreateCodeSnapshot(content: string | null, title: string | null): DataSnapshot | null;
34
+ /** @deprecated Use {@link CreateCodeSnapshot}. */
31
35
  export declare function createCodeSnapshot(content: string | null, title: string | null): DataSnapshot | null;
32
36
  /**
33
37
  * Create a DataSnapshot from markdown artifact content.
34
38
  * Stores the raw content in custom.
35
39
  */
40
+ export declare function CreateMarkdownSnapshot(content: string | null, title: string | null): DataSnapshot | null;
41
+ /** @deprecated Use {@link CreateMarkdownSnapshot}. */
36
42
  export declare function createMarkdownSnapshot(content: string | null, title: string | null): DataSnapshot | null;
37
43
  /**
38
44
  * Create a DataSnapshot from a DataArtifactSpec (data viewer).
@@ -42,7 +48,11 @@ export declare function createMarkdownSnapshot(content: string | null, title: st
42
48
  * Build a combined SQL string from multiple tables, each with a header comment.
43
49
  * Returns null if no tables have SQL.
44
50
  */
51
+ export declare function BuildMultiTableSql(tables: DataTable[]): string | null;
52
+ /** @deprecated Use {@link BuildMultiTableSql}. */
45
53
  export declare function buildMultiTableSql(tables: DataTable[]): string | null;
54
+ export declare function CreateDataSnapshot(spec: DataArtifactSpecLike | null): DataSnapshot | null;
55
+ /** @deprecated Use {@link CreateDataSnapshot}. */
46
56
  export declare function createDataSnapshot(spec: DataArtifactSpecLike | null): DataSnapshot | null;
47
57
  export {};
48
58
  //# sourceMappingURL=snapshot-helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot-helpers.d.ts","sourceRoot":"","sources":["../../src/lib/snapshot-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,SAAS,EAAqB,MAAM,sBAAsB,CAAC;AAElF;;;GAGG;AACH,UAAU,oBAAoB;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,CAcpG;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,CAQpG;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,CAMxG;AAED;;;GAGG;AACH;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,GAAG,IAAI,CAMrE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,oBAAoB,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,CAKzF"}
1
+ {"version":3,"file":"snapshot-helpers.d.ts","sourceRoot":"","sources":["../../src/lib/snapshot-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,SAAS,EAAqB,MAAM,sBAAsB,CAAC;AAElF;;;GAGG;AACH,UAAU,oBAAoB;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,CAcpG;AAED,kDAAkD;AAClD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,CAEpG;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,CAQpG;AAED,kDAAkD;AAClD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,CAEpG;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,CAMxG;AAED,sDAAsD;AACtD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,CAExG;AAED;;;GAGG;AACH;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,GAAG,IAAI,CAMrE;AAED,kDAAkD;AAClD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,GAAG,IAAI,CAErE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,oBAAoB,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,CAKzF;AAED,kDAAkD;AAClD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,oBAAoB,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,CAEzF"}
@@ -10,7 +10,7 @@ import { DataSnapshot, NormalizeToTables } from '@memberjunction/core';
10
10
  * Create a DataSnapshot from JSON artifact content.
11
11
  * Parses the JSON, counts top-level keys, and stores the parsed value in custom.
12
12
  */
13
- export function createJsonSnapshot(content, title) {
13
+ export function CreateJsonSnapshot(content, title) {
14
14
  if (!content)
15
15
  return null;
16
16
  try {
@@ -27,11 +27,15 @@ export function createJsonSnapshot(content, title) {
27
27
  return null;
28
28
  }
29
29
  }
30
+ /** @deprecated Use {@link CreateJsonSnapshot}. */
31
+ export function createJsonSnapshot(content, title) {
32
+ return CreateJsonSnapshot(content, title);
33
+ }
30
34
  /**
31
35
  * Create a DataSnapshot from code artifact content.
32
36
  * Counts lines and stores content plus lineCount in custom.
33
37
  */
34
- export function createCodeSnapshot(content, title) {
38
+ export function CreateCodeSnapshot(content, title) {
35
39
  if (!content)
36
40
  return null;
37
41
  const lineCount = content.split('\n').length;
@@ -41,11 +45,15 @@ export function createCodeSnapshot(content, title) {
41
45
  snap.custom = { content, lineCount };
42
46
  return snap;
43
47
  }
48
+ /** @deprecated Use {@link CreateCodeSnapshot}. */
49
+ export function createCodeSnapshot(content, title) {
50
+ return CreateCodeSnapshot(content, title);
51
+ }
44
52
  /**
45
53
  * Create a DataSnapshot from markdown artifact content.
46
54
  * Stores the raw content in custom.
47
55
  */
48
- export function createMarkdownSnapshot(content, title) {
56
+ export function CreateMarkdownSnapshot(content, title) {
49
57
  if (!content)
50
58
  return null;
51
59
  const snap = new DataSnapshot();
@@ -53,6 +61,10 @@ export function createMarkdownSnapshot(content, title) {
53
61
  snap.custom = { content };
54
62
  return snap;
55
63
  }
64
+ /** @deprecated Use {@link CreateMarkdownSnapshot}. */
65
+ export function createMarkdownSnapshot(content, title) {
66
+ return CreateMarkdownSnapshot(content, title);
67
+ }
56
68
  /**
57
69
  * Create a DataSnapshot from a DataArtifactSpec (data viewer).
58
70
  * Uses NormalizeToTables to convert the spec into a tabular snapshot.
@@ -61,7 +73,7 @@ export function createMarkdownSnapshot(content, title) {
61
73
  * Build a combined SQL string from multiple tables, each with a header comment.
62
74
  * Returns null if no tables have SQL.
63
75
  */
64
- export function buildMultiTableSql(tables) {
76
+ export function BuildMultiTableSql(tables) {
65
77
  const sqlTables = tables.filter(t => t.metadata?.sql);
66
78
  if (sqlTables.length === 0)
67
79
  return null;
@@ -69,11 +81,19 @@ export function buildMultiTableSql(tables) {
69
81
  .map(t => `-- ═══ ${t.name} ═══\n${t.metadata.sql}`)
70
82
  .join('\n\n');
71
83
  }
72
- export function createDataSnapshot(spec) {
84
+ /** @deprecated Use {@link BuildMultiTableSql}. */
85
+ export function buildMultiTableSql(tables) {
86
+ return BuildMultiTableSql(tables);
87
+ }
88
+ export function CreateDataSnapshot(spec) {
73
89
  if (!spec)
74
90
  return null;
75
91
  const tableName = spec.title || 'Results';
76
92
  const tables = NormalizeToTables(spec, tableName);
77
93
  return DataSnapshot.FromTables(tables, spec.title);
78
94
  }
95
+ /** @deprecated Use {@link CreateDataSnapshot}. */
96
+ export function createDataSnapshot(spec) {
97
+ return CreateDataSnapshot(spec);
98
+ }
79
99
  //# sourceMappingURL=snapshot-helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot-helpers.js","sourceRoot":"","sources":["../../src/lib/snapshot-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAa,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAYlF;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAsB,EAAE,KAAoB;IAC7E,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;QAC9D,MAAM,IAAI,GAAG,IAAI,YAAY,EAAE,CAAC;QAChC,IAAI,CAAC,KAAK,GAAG,KAAK,IAAI,SAAS,CAAC;QAChC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5E,IAAI,CAAC,cAAc,GAAG,sBAAsB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,kBAAkB,CAAC;QAC3F,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,MAAiC,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAsB,EAAE,KAAoB;IAC7E,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAC7C,MAAM,IAAI,GAAG,IAAI,YAAY,EAAE,CAAC;IAChC,IAAI,CAAC,KAAK,GAAG,KAAK,IAAI,SAAS,CAAC;IAChC,IAAI,CAAC,cAAc,GAAG,kBAAkB,SAAS,SAAS,CAAC;IAC3D,IAAI,CAAC,MAAM,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IACrC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAsB,EAAE,KAAoB;IACjF,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,IAAI,GAAG,IAAI,YAAY,EAAE,CAAC;IAChC,IAAI,CAAC,KAAK,GAAG,KAAK,IAAI,SAAS,CAAC;IAChC,IAAI,CAAC,MAAM,GAAG,EAAE,OAAO,EAAE,CAAC;IAC1B,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAmB;IACpD,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACtD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,OAAO,SAAS;SACb,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,QAAS,CAAC,GAAI,EAAE,CAAC;SACrD,IAAI,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAiC;IAClE,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC;IAC1C,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAA+B,EAAE,SAAS,CAAC,CAAC;IAC7E,OAAO,YAAY,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;AACrD,CAAC","sourcesContent":["/**\n * Pure helper functions for creating DataSnapshots from artifact content.\n *\n * These are extracted from Angular viewer components so the logic can be\n * unit-tested without Angular TestBed. Each viewer plugin delegates to\n * the corresponding function here.\n */\nimport { DataSnapshot, DataTable, NormalizeToTables } from '@memberjunction/core';\n\n/**\n * Shape of a DataArtifactSpec that the data viewer works with.\n * Only the fields relevant to snapshot creation are required.\n */\ninterface DataArtifactSpecLike {\n title?: string;\n columns?: { field: string; headerName?: string; sqlBaseType?: string }[];\n rows?: Record<string, unknown>[];\n}\n\n/**\n * Create a DataSnapshot from JSON artifact content.\n * Parses the JSON, counts top-level keys, and stores the parsed value in custom.\n */\nexport function createJsonSnapshot(content: string | null, title: string | null): DataSnapshot | null {\n if (!content) return null;\n try {\n const parsed = JSON.parse(content) as Record<string, unknown>;\n const snap = new DataSnapshot();\n snap.title = title ?? undefined;\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n snap.interpretation = `JSON artifact with ${Object.keys(parsed).length} top-level keys.`;\n }\n snap.custom = parsed as Record<string, unknown>;\n return snap;\n } catch {\n return null;\n }\n}\n\n/**\n * Create a DataSnapshot from code artifact content.\n * Counts lines and stores content plus lineCount in custom.\n */\nexport function createCodeSnapshot(content: string | null, title: string | null): DataSnapshot | null {\n if (!content) return null;\n const lineCount = content.split('\\n').length;\n const snap = new DataSnapshot();\n snap.title = title ?? undefined;\n snap.interpretation = `Code artifact, ${lineCount} lines.`;\n snap.custom = { content, lineCount };\n return snap;\n}\n\n/**\n * Create a DataSnapshot from markdown artifact content.\n * Stores the raw content in custom.\n */\nexport function createMarkdownSnapshot(content: string | null, title: string | null): DataSnapshot | null {\n if (!content) return null;\n const snap = new DataSnapshot();\n snap.title = title ?? undefined;\n snap.custom = { content };\n return snap;\n}\n\n/**\n * Create a DataSnapshot from a DataArtifactSpec (data viewer).\n * Uses NormalizeToTables to convert the spec into a tabular snapshot.\n */\n/**\n * Build a combined SQL string from multiple tables, each with a header comment.\n * Returns null if no tables have SQL.\n */\nexport function buildMultiTableSql(tables: DataTable[]): string | null {\n const sqlTables = tables.filter(t => t.metadata?.sql);\n if (sqlTables.length === 0) return null;\n return sqlTables\n .map(t => `-- ═══ ${t.name} ═══\\n${t.metadata!.sql!}`)\n .join('\\n\\n');\n}\n\nexport function createDataSnapshot(spec: DataArtifactSpecLike | null): DataSnapshot | null {\n if (!spec) return null;\n const tableName = spec.title || 'Results';\n const tables = NormalizeToTables(spec as Record<string, unknown>, tableName);\n return DataSnapshot.FromTables(tables, spec.title);\n}\n"]}
1
+ {"version":3,"file":"snapshot-helpers.js","sourceRoot":"","sources":["../../src/lib/snapshot-helpers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure helper functions for creating DataSnapshots from artifact content.\n *\n * These are extracted from Angular viewer components so the logic can be\n * unit-tested without Angular TestBed. Each viewer plugin delegates to\n * the corresponding function here.\n */\nimport { DataSnapshot, DataTable, NormalizeToTables } from '@memberjunction/core';\n\n/**\n * Shape of a DataArtifactSpec that the data viewer works with.\n * Only the fields relevant to snapshot creation are required.\n */\ninterface DataArtifactSpecLike {\n title?: string;\n columns?: { field: string; headerName?: string; sqlBaseType?: string }[];\n rows?: Record<string, unknown>[];\n}\n\n/**\n * Create a DataSnapshot from JSON artifact content.\n * Parses the JSON, counts top-level keys, and stores the parsed value in custom.\n */\nexport function CreateJsonSnapshot(content: string | null, title: string | null): DataSnapshot | null {\n if (!content) return null;\n try {\n const parsed = JSON.parse(content) as Record<string, unknown>;\n const snap = new DataSnapshot();\n snap.title = title ?? undefined;\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n snap.interpretation = `JSON artifact with ${Object.keys(parsed).length} top-level keys.`;\n }\n snap.custom = parsed as Record<string, unknown>;\n return snap;\n } catch {\n return null;\n }\n}\n\n/** @deprecated Use {@link CreateJsonSnapshot}. */\nexport function createJsonSnapshot(content: string | null, title: string | null): DataSnapshot | null {\n return CreateJsonSnapshot(content, title);\n}\n\n/**\n * Create a DataSnapshot from code artifact content.\n * Counts lines and stores content plus lineCount in custom.\n */\nexport function CreateCodeSnapshot(content: string | null, title: string | null): DataSnapshot | null {\n if (!content) return null;\n const lineCount = content.split('\\n').length;\n const snap = new DataSnapshot();\n snap.title = title ?? undefined;\n snap.interpretation = `Code artifact, ${lineCount} lines.`;\n snap.custom = { content, lineCount };\n return snap;\n}\n\n/** @deprecated Use {@link CreateCodeSnapshot}. */\nexport function createCodeSnapshot(content: string | null, title: string | null): DataSnapshot | null {\n return CreateCodeSnapshot(content, title);\n}\n\n/**\n * Create a DataSnapshot from markdown artifact content.\n * Stores the raw content in custom.\n */\nexport function CreateMarkdownSnapshot(content: string | null, title: string | null): DataSnapshot | null {\n if (!content) return null;\n const snap = new DataSnapshot();\n snap.title = title ?? undefined;\n snap.custom = { content };\n return snap;\n}\n\n/** @deprecated Use {@link CreateMarkdownSnapshot}. */\nexport function createMarkdownSnapshot(content: string | null, title: string | null): DataSnapshot | null {\n return CreateMarkdownSnapshot(content, title);\n}\n\n/**\n * Create a DataSnapshot from a DataArtifactSpec (data viewer).\n * Uses NormalizeToTables to convert the spec into a tabular snapshot.\n */\n/**\n * Build a combined SQL string from multiple tables, each with a header comment.\n * Returns null if no tables have SQL.\n */\nexport function BuildMultiTableSql(tables: DataTable[]): string | null {\n const sqlTables = tables.filter(t => t.metadata?.sql);\n if (sqlTables.length === 0) return null;\n return sqlTables\n .map(t => `-- ═══ ${t.name} ═══\\n${t.metadata!.sql!}`)\n .join('\\n\\n');\n}\n\n/** @deprecated Use {@link BuildMultiTableSql}. */\nexport function buildMultiTableSql(tables: DataTable[]): string | null {\n return BuildMultiTableSql(tables);\n}\n\nexport function CreateDataSnapshot(spec: DataArtifactSpecLike | null): DataSnapshot | null {\n if (!spec) return null;\n const tableName = spec.title || 'Results';\n const tables = NormalizeToTables(spec as Record<string, unknown>, tableName);\n return DataSnapshot.FromTables(tables, spec.title);\n}\n\n/** @deprecated Use {@link CreateDataSnapshot}. */\nexport function createDataSnapshot(spec: DataArtifactSpecLike | null): DataSnapshot | null {\n return CreateDataSnapshot(spec);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-artifacts",
3
- "version": "6.2.0-edge.0",
3
+ "version": "6.2.0-edge.1",
4
4
  "description": "MemberJunction: Artifact viewer plugin system for rendering different artifact types (JSON, Code, Markdown, HTML, SVG, Components)",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -13,8 +13,8 @@
13
13
  "devDependencies": {
14
14
  "@angular/compiler": "21.2.22",
15
15
  "@angular/compiler-cli": "21.2.22",
16
- "@memberjunction/core": "6.2.0-edge.0",
17
- "@memberjunction/ng-test-utils": "6.2.0-edge.0",
16
+ "@memberjunction/core": "6.2.0-edge.1",
17
+ "@memberjunction/ng-test-utils": "6.2.0-edge.1",
18
18
  "sass": "^1.97.3",
19
19
  "vitest": "^4.0.18"
20
20
  },
@@ -29,24 +29,24 @@
29
29
  "ag-grid-community": "^35.0.1"
30
30
  },
31
31
  "dependencies": {
32
- "@memberjunction/core": "6.2.0-edge.0",
33
- "@memberjunction/core-entities": "6.2.0-edge.0",
34
- "@memberjunction/global": "6.2.0-edge.0",
35
- "@memberjunction/graphql-dataprovider": "6.2.0-edge.0",
36
- "@memberjunction/interactive-component-types": "6.2.0-edge.0",
37
- "@memberjunction/ng-base-forms": "6.2.0-edge.0",
38
- "@memberjunction/ng-base-types": "6.2.0-edge.0",
39
- "@memberjunction/ng-code-editor": "6.2.0-edge.0",
40
- "@memberjunction/ng-export-service": "6.2.0-edge.0",
41
- "@memberjunction/ng-markdown": "6.2.0-edge.0",
42
- "@memberjunction/ng-media-player": "6.2.0-edge.0",
43
- "@memberjunction/ng-notifications": "6.2.0-edge.0",
44
- "@memberjunction/ng-pagination": "6.2.0-edge.0",
45
- "@memberjunction/ng-query-viewer": "6.2.0-edge.0",
46
- "@memberjunction/ng-react": "6.2.0-edge.0",
47
- "@memberjunction/ng-shared-generic": "6.2.0-edge.0",
48
- "@memberjunction/ng-trees": "6.2.0-edge.0",
49
- "@memberjunction/ng-ui-components": "6.2.0-edge.0",
32
+ "@memberjunction/core": "6.2.0-edge.1",
33
+ "@memberjunction/core-entities": "6.2.0-edge.1",
34
+ "@memberjunction/global": "6.2.0-edge.1",
35
+ "@memberjunction/graphql-dataprovider": "6.2.0-edge.1",
36
+ "@memberjunction/interactive-component-types": "6.2.0-edge.1",
37
+ "@memberjunction/ng-base-forms": "6.2.0-edge.1",
38
+ "@memberjunction/ng-base-types": "6.2.0-edge.1",
39
+ "@memberjunction/ng-code-editor": "6.2.0-edge.1",
40
+ "@memberjunction/ng-export-service": "6.2.0-edge.1",
41
+ "@memberjunction/ng-markdown": "6.2.0-edge.1",
42
+ "@memberjunction/ng-media-player": "6.2.0-edge.1",
43
+ "@memberjunction/ng-notifications": "6.2.0-edge.1",
44
+ "@memberjunction/ng-pagination": "6.2.0-edge.1",
45
+ "@memberjunction/ng-query-viewer": "6.2.0-edge.1",
46
+ "@memberjunction/ng-react": "6.2.0-edge.1",
47
+ "@memberjunction/ng-shared-generic": "6.2.0-edge.1",
48
+ "@memberjunction/ng-trees": "6.2.0-edge.1",
49
+ "@memberjunction/ng-ui-components": "6.2.0-edge.1",
50
50
  "mammoth": "^1.8.0",
51
51
  "pdfjs-dist": "^4.10.38",
52
52
  "rxjs": "^7.8.2",