@coveo/atomic 3.61.3 → 3.61.5

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 (88) hide show
  1. package/custom-elements.json +1246 -1222
  2. package/dist/assets/ai.svg +1 -1
  3. package/dist/assets/ai_model_generative.svg +1 -0
  4. package/dist/assets/attachment.svg +1 -1
  5. package/dist/assets/audio.svg +1 -1
  6. package/dist/assets/box_notes.svg +1 -1
  7. package/dist/assets/css.svg +1 -1
  8. package/dist/assets/csv.svg +1 -1
  9. package/dist/assets/eps.svg +1 -1
  10. package/dist/assets/excel.svg +1 -1
  11. package/dist/assets/exe.svg +1 -1
  12. package/dist/assets/flash.svg +1 -1
  13. package/dist/assets/gdoc.svg +1 -1
  14. package/dist/assets/gdocs.svg +1 -1
  15. package/dist/assets/gform.svg +1 -1
  16. package/dist/assets/gpres.svg +1 -1
  17. package/dist/assets/gsheet.svg +1 -1
  18. package/dist/assets/html.svg +1 -1
  19. package/dist/assets/image.svg +1 -1
  20. package/dist/assets/in_queue_experience.svg +1 -0
  21. package/dist/assets/initiate_external_transfer.svg +1 -0
  22. package/dist/assets/keynote.svg +1 -1
  23. package/dist/assets/mp4.svg +1 -1
  24. package/dist/assets/outbound_call.svg +1 -0
  25. package/dist/assets/overlay.svg +1 -1
  26. package/dist/assets/pack.svg +1 -1
  27. package/dist/assets/pages.svg +1 -1
  28. package/dist/assets/pdf.svg +1 -1
  29. package/dist/assets/ppt.svg +1 -1
  30. package/dist/assets/psd.svg +1 -1
  31. package/dist/assets/quip_doc.svg +1 -1
  32. package/dist/assets/quip_slide.svg +1 -1
  33. package/dist/assets/rfp_record.svg +1 -0
  34. package/dist/assets/rtf.svg +1 -1
  35. package/dist/assets/slack_canvas.svg +1 -1
  36. package/dist/assets/slack_list_item.svg +1 -1
  37. package/dist/assets/slack_lists.svg +1 -1
  38. package/dist/assets/slide.svg +1 -1
  39. package/dist/assets/stypi.svg +1 -1
  40. package/dist/assets/suggested_for_you.svg +1 -0
  41. package/dist/assets/txt.svg +1 -1
  42. package/dist/assets/unknown.svg +1 -1
  43. package/dist/assets/vcf.svg +1 -0
  44. package/dist/assets/visio.svg +1 -1
  45. package/dist/assets/voicemail_drop.svg +1 -0
  46. package/dist/assets/webex.svg +1 -1
  47. package/dist/assets/word.svg +1 -1
  48. package/dist/assets/xml.svg +1 -1
  49. package/dist/assets/zip.svg +1 -1
  50. package/dist/cjs/autoloader/index.cjs +24 -6
  51. package/dist/cjs/components/common/atomic-generated-answer-content/atomic-generated-answer-content.cjs +23 -1
  52. package/dist/cjs/components/common/atomic-generated-answer-thread/atomic-generated-answer-thread.cjs +1 -1
  53. package/dist/cjs/components/common/atomic-generated-answer-thread-item/atomic-generated-answer-thread-item.cjs +3 -2
  54. package/dist/cjs/components/common/generated-answer/answer-announcement.cjs +73 -0
  55. package/dist/cjs/components/common/generated-answer/copy-button.cjs +2 -1
  56. package/dist/cjs/components/common/generated-answer/feedback-button.cjs +2 -1
  57. package/dist/cjs/components/common/generated-answer/generated-content/markdown-utils.cjs +1 -2
  58. package/dist/cjs/components/common/generated-answer/generated-content-container.cjs +6 -1
  59. package/dist/cjs/components/common/generated-answer/render-answer-content.cjs +5 -2
  60. package/dist/cjs/components/common/generated-answer/show-button.cjs +1 -0
  61. package/dist/cjs/components/insight/atomic-insight-generated-answer/atomic-insight-generated-answer.cjs +3 -1
  62. package/dist/cjs/components/search/atomic-generated-answer/atomic-generated-answer.cjs +8 -1
  63. package/dist/cjs/components/search/atomic-sort-dropdown/atomic-sort-dropdown.cjs +1 -0
  64. package/dist/cjs/global/environment.cjs +1 -1
  65. package/dist/cjs/versions.cjs +1 -1
  66. package/dist/esm/autoloader/index.js +24 -6
  67. package/dist/esm/components/common/atomic-generated-answer-content/atomic-generated-answer-content.js +23 -1
  68. package/dist/esm/components/common/atomic-generated-answer-thread/atomic-generated-answer-thread.js +1 -1
  69. package/dist/esm/components/common/atomic-generated-answer-thread-item/atomic-generated-answer-thread-item.js +3 -2
  70. package/dist/esm/components/common/generated-answer/answer-announcement.js +32 -0
  71. package/dist/esm/components/common/generated-answer/copy-button.js +2 -1
  72. package/dist/esm/components/common/generated-answer/feedback-button.js +2 -1
  73. package/dist/esm/components/common/generated-answer/generated-content/markdown-utils.js +1 -2
  74. package/dist/esm/components/common/generated-answer/generated-content-container.js +6 -1
  75. package/dist/esm/components/common/generated-answer/render-answer-content.js +5 -2
  76. package/dist/esm/components/common/generated-answer/show-button.js +1 -0
  77. package/dist/esm/components/insight/atomic-insight-generated-answer/atomic-insight-generated-answer.js +3 -1
  78. package/dist/esm/components/search/atomic-generated-answer/atomic-generated-answer.js +8 -1
  79. package/dist/esm/components/search/atomic-sort-dropdown/atomic-sort-dropdown.js +1 -0
  80. package/dist/esm/global/environment.js +1 -1
  81. package/dist/esm/versions.js +1 -1
  82. package/dist/types/components/common/atomic-generated-answer-content/atomic-generated-answer-content.d.ts +7 -0
  83. package/dist/types/components/common/generated-answer/answer-announcement.d.ts +22 -0
  84. package/dist/types/components/common/generated-answer/generated-content-container.d.ts +1 -0
  85. package/dist/types/components/common/generated-answer/show-button.d.ts +1 -0
  86. package/dist/types/components/insight/atomic-insight-generated-answer/atomic-insight-generated-answer.d.ts +1 -0
  87. package/dist/types/components/search/atomic-generated-answer/atomic-generated-answer.d.ts +2 -0
  88. package/package.json +20 -20
@@ -50,11 +50,18 @@ function registerAutoloader(roots) {
50
50
  roots
51
51
  ];
52
52
  const visitedNodes = new WeakSet();
53
+ const reportRegistrationError = (tagName, error)=>{
54
+ console.error(`[Atomic] Failed to register the "${tagName}" component. The component will not be displayed. This can happen when its code fails to load (e.g. network error, CDN issue, content security policy, proxy, or ad blocker).`, error);
55
+ };
53
56
  const observeStencilElementHydration = (atomicElement)=>{
54
57
  const attributeObserver = new MutationObserver(async ()=>{
55
58
  if (atomicElement.classList.contains('hydrated') && 'shadowRoot' in atomicElement && atomicElement.shadowRoot && !visitedNodes.has(atomicElement.shadowRoot)) {
56
59
  attributeObserver.disconnect();
57
- await discover(atomicElement.shadowRoot);
60
+ try {
61
+ await discover(atomicElement.shadowRoot);
62
+ } catch (error) {
63
+ reportRegistrationError(atomicElement.tagName.toLowerCase(), error);
64
+ }
58
65
  observer.observe(atomicElement.shadowRoot, {
59
66
  subtree: true,
60
67
  childList: true
@@ -109,16 +116,27 @@ function registerAutoloader(roots) {
109
116
  await Promise.allSettled(litRegistrationPromises);
110
117
  customElements.upgrade(root);
111
118
  };
112
- const register = (tagName)=>{
113
- if (customElements.get(tagName)) return Promise.resolve();
114
- return lazy_index_cjs_default()[tagName]?.();
119
+ const register = async (tagName)=>{
120
+ if (customElements.get(tagName)) return;
121
+ try {
122
+ await lazy_index_cjs_default()[tagName]?.();
123
+ } catch (error) {
124
+ reportRegistrationError(tagName, error);
125
+ }
115
126
  };
116
127
  const observer = new MutationObserver(async (mutations)=>{
117
- for (const { addedNodes } of mutations)for (const node of addedNodes)if (node.nodeType === Node.ELEMENT_NODE) await discover(node);
128
+ for (const { addedNodes } of mutations)for (const node of addedNodes)if (node.nodeType === Node.ELEMENT_NODE) try {
129
+ await discover(node);
130
+ } catch (error) {
131
+ reportRegistrationError(node.tagName.toLowerCase(), error);
132
+ }
118
133
  });
119
134
  const initializeDiscovery = ()=>{
120
135
  for (const root of roots){
121
- discover(root);
136
+ discover(root).catch((error)=>{
137
+ const tagName = root instanceof Element ? root.tagName.toLowerCase() : 'root';
138
+ reportRegistrationError(tagName, error);
139
+ });
122
140
  observer.observe(root, {
123
141
  subtree: true,
124
142
  childList: true
@@ -46,7 +46,9 @@ const when_js_namespaceObject = require("lit/directives/when.js");
46
46
  const atomic_generated_answer_tw_css_cjs_namespaceObject = require("../../search/atomic-generated-answer/atomic-generated-answer.tw.css.cjs");
47
47
  var atomic_generated_answer_tw_css_cjs_default = /*#__PURE__*/ __webpack_require__.n(atomic_generated_answer_tw_css_cjs_namespaceObject);
48
48
  const with_tailwind_styles_cjs_namespaceObject = require("../../../decorators/with-tailwind-styles.cjs");
49
+ const accessibility_utils_cjs_namespaceObject = require("../../../utils/accessibility-utils.cjs");
49
50
  require("../atomic-agent-stream-of-thought/atomic-agent-stream-of-thought.cjs");
51
+ const answer_announcement_cjs_namespaceObject = require("../generated-answer/answer-announcement.cjs");
50
52
  const generated_content_container_cjs_namespaceObject = require("../generated-answer/generated-content-container.cjs");
51
53
  const render_feedback_and_copy_buttons_cjs_namespaceObject = require("../generated-answer/render-feedback-and-copy-buttons.cjs");
52
54
  const source_citations_cjs_namespaceObject = require("../generated-answer/source-citations.cjs");
@@ -100,6 +102,24 @@ class AtomicGeneratedAnswerContent extends external_lit_namespaceObject.LitEleme
100
102
  </div>
101
103
  `;
102
104
  }
105
+ updated() {
106
+ this.announceAnswerStatus();
107
+ }
108
+ announceAnswerStatus() {
109
+ if (!this.i18n || !this.generatedAnswer) return;
110
+ const { message, assertive } = (0, answer_announcement_cjs_namespaceObject.getAnswerAnnouncement)(this.generatedAnswer, this.i18n);
111
+ if (!this.hasObservedAnswer) {
112
+ this.hasObservedAnswer = true;
113
+ if ((0, answer_announcement_cjs_namespaceObject.isSettledAnswer)(this.generatedAnswer)) {
114
+ this.lastAnnouncedMessage = message;
115
+ return;
116
+ }
117
+ }
118
+ if (message === this.lastAnnouncedMessage) return;
119
+ this.lastAnnouncedMessage = message;
120
+ if (assertive) this.ariaErrorMessage.message = message;
121
+ else this.ariaMessage.message = message;
122
+ }
103
123
  renderFeedbackAndCopyButtons(answerId) {
104
124
  return (0, external_lit_namespaceObject.html)`
105
125
  <div class="mt-4" part="feedback-and-copy-buttons">
@@ -130,9 +150,11 @@ class AtomicGeneratedAnswerContent extends external_lit_namespaceObject.LitEleme
130
150
  try {
131
151
  await navigator.clipboard.writeText(answer);
132
152
  this.copyState = 'success';
153
+ this.ariaCopyMessage.message = this.i18n.t('generated-answer-copied');
133
154
  this.onCopyToClipboard(answerId);
134
155
  } catch (error) {
135
156
  this.copyState = 'error';
157
+ this.ariaCopyMessage.message = this.i18n.t('failed-to-copy-generated-answer');
136
158
  console.error(`Failed to copy to clipboard: ${error}`);
137
159
  }
138
160
  this.scheduleCopyReset();
@@ -169,7 +191,7 @@ class AtomicGeneratedAnswerContent extends external_lit_namespaceObject.LitEleme
169
191
  `;
170
192
  }
171
193
  constructor(...args){
172
- super(...args), this.answerId = '', this.renderCitations = ()=>(0, external_lit_namespaceObject.html)``, this.onClickLike = ()=>{}, this.onClickDislike = ()=>{}, this.onCopyToClipboard = ()=>{}, this.copyState = 'idle';
194
+ super(...args), this.answerId = '', this.renderCitations = ()=>(0, external_lit_namespaceObject.html)``, this.onClickLike = ()=>{}, this.onClickDislike = ()=>{}, this.onCopyToClipboard = ()=>{}, this.copyState = 'idle', this.ariaMessage = new accessibility_utils_cjs_namespaceObject.AriaLiveRegionController(this, 'generated-answer', false, true), this.ariaErrorMessage = new accessibility_utils_cjs_namespaceObject.AriaLiveRegionController(this, 'generated-answer-error', true), this.ariaCopyMessage = new accessibility_utils_cjs_namespaceObject.AriaLiveRegionController(this, 'generated-answer-copy', true), this.hasObservedAnswer = false;
173
195
  }
174
196
  }
175
197
  AtomicGeneratedAnswerContent.styles = [
@@ -138,7 +138,7 @@ class AtomicGeneratedAnswerThread extends external_lit_namespaceObject.LitElemen
138
138
  `;
139
139
  return (0, external_lit_namespaceObject.html)`
140
140
  <li class="group/title grid min-w-0 grid-cols-[10px_1fr] gap-x-3">
141
- <div class="row-span-2 flex flex-col items-center">
141
+ <div class="row-span-2 flex flex-col items-center" aria-hidden="true">
142
142
  <div class="flex justify-center items-center text-base h-[1lh] my-1.5">
143
143
  <span class=${timelineDotClasses}></span>
144
144
  </div>
@@ -121,7 +121,7 @@ class AtomicGeneratedAnswerThreadItem extends external_lit_namespaceObject.LitEl
121
121
  const timelineConnectorClasses = "relative h-full w-px bg-neutral transition-colors duration-150 group-hover:bg-neutral-dark before:absolute before:left-0 before:top-[-8px] before:h-[8px] before:w-px before:bg-neutral before:transition-colors before:duration-150 group-hover:before:bg-neutral-dark before:content-[''] after:absolute after:bottom-[-8px] after:left-0 after:h-[8px] after:w-px after:bg-neutral after:transition-colors after:duration-150 group-hover:after:bg-neutral-dark after:content-['']";
122
122
  return (0, external_lit_namespaceObject.html)`
123
123
  <div class="group/title grid min-w-0 grid-cols-[10px_1fr] gap-x-3">
124
- <div class="row-span-2 flex flex-col items-center">
124
+ <div class="row-span-2 flex flex-col items-center" aria-hidden="true">
125
125
  <div class=${timelineDotToggleClasses}>
126
126
  ${(0, when_js_namespaceObject.when)(this.showTimelineDot, ()=>(0, external_lit_namespaceObject.html)`
127
127
  <span
@@ -155,8 +155,9 @@ class AtomicGeneratedAnswerThreadItem extends external_lit_namespaceObject.LitEl
155
155
  >${this.title}</span
156
156
  >`)}
157
157
  </div>
158
- <div id=${this.contentId} class="min-w-0 pl-2 py-1.5">
158
+ <div class="min-w-0 pl-2 py-1.5">
159
159
  <div
160
+ id=${this.contentId}
160
161
  class="mb-2"
161
162
  ?hidden=${!this.isExpanded}
162
163
  aria-hidden=${this.isExpanded ? 'false' : 'true'}
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, getters, values)=>{
5
+ var define = (defs, kind)=>{
6
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
+ enumerable: true,
8
+ [kind]: defs[key]
9
+ });
10
+ };
11
+ define(getters, "get");
12
+ define(values, "value");
13
+ };
14
+ })();
15
+ (()=>{
16
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
+ })();
18
+ (()=>{
19
+ __webpack_require__.r = (exports1)=>{
20
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
+ value: 'Module'
22
+ });
23
+ Object.defineProperty(exports1, '__esModule', {
24
+ value: true
25
+ });
26
+ };
27
+ })();
28
+ var __webpack_exports__ = {};
29
+ __webpack_require__.r(__webpack_exports__);
30
+ __webpack_require__.d(__webpack_exports__, {
31
+ getAnswerAnnouncement: ()=>getAnswerAnnouncement,
32
+ isSettledAnswer: ()=>isSettledAnswer
33
+ });
34
+ const markdown_utils_cjs_namespaceObject = require("./generated-content/markdown-utils.cjs");
35
+ const SILENT = {
36
+ message: '',
37
+ assertive: false
38
+ };
39
+ const getAnswerAnnouncement = (answer, i18n)=>{
40
+ if (!answer) return SILENT;
41
+ if (answer.error) {
42
+ const errorMessageKey = answer.error.isSseTurnLimitReachedError?.() ? 'generated-answer-error-turn-limit-reached' : 'generated-answer-error-generic';
43
+ return {
44
+ message: i18n.t(errorMessageKey),
45
+ assertive: true
46
+ };
47
+ }
48
+ if (answer.cannotAnswer) return {
49
+ message: i18n.t('generated-answer-cannot-generate-answer'),
50
+ assertive: true
51
+ };
52
+ if (answer.isStreaming || answer.isLoading) return {
53
+ message: i18n.t('generating-answer'),
54
+ assertive: false
55
+ };
56
+ if (answer.answer?.trim()) return {
57
+ message: i18n.t('answer-generated', {
58
+ answer: (0, markdown_utils_cjs_namespaceObject.markdownToPlainText)(answer.answer)
59
+ }),
60
+ assertive: false
61
+ };
62
+ return SILENT;
63
+ };
64
+ const isSettledAnswer = (answer)=>Boolean(answer && !answer.isStreaming && !answer.isLoading && !answer.error && !answer.cannotAnswer && answer.answer?.trim());
65
+ exports.getAnswerAnnouncement = __webpack_exports__.getAnswerAnnouncement;
66
+ exports.isSettledAnswer = __webpack_exports__.isSettledAnswer;
67
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
68
+ "getAnswerAnnouncement",
69
+ "isSettledAnswer"
70
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
71
+ Object.defineProperty(exports, '__esModule', {
72
+ value: true
73
+ });
@@ -54,6 +54,7 @@ const renderCopyButton = ({ props })=>{
54
54
  return (0, external_button_cjs_namespaceObject.renderButton)({
55
55
  props: {
56
56
  title: props.title,
57
+ ariaLabel: props.title,
57
58
  part: 'copy-button',
58
59
  style: 'text-transparent',
59
60
  class: classes.join(' '),
@@ -61,7 +62,7 @@ const renderCopyButton = ({ props })=>{
61
62
  }
62
63
  })((0, external_lit_namespaceObject.html)`
63
64
  <div class="icon-container text-neutral-dark">
64
- <atomic-icon class="w-5" .icon=${copy_cjs_default()}></atomic-icon>
65
+ <atomic-icon class="w-5" .icon=${copy_cjs_default()} aria-hidden="true"></atomic-icon>
65
66
  </div>
66
67
  `);
67
68
  };
@@ -68,6 +68,7 @@ const renderFeedbackButton = ({ props })=>{
68
68
  return (0, external_lit_namespaceObject.html)`<button
69
69
  type="button"
70
70
  title=${props.title}
71
+ aria-label=${props.title}
71
72
  part="feedback-button"
72
73
  class=${classNames}
73
74
  aria-pressed=${props.active ? 'true' : 'false'}
@@ -76,7 +77,7 @@ const renderFeedbackButton = ({ props })=>{
76
77
  })}
77
78
  @click=${props.onClick}
78
79
  >
79
- <atomic-icon class=${iconClassNames} .icon=${thumbs_cjs_default()}></atomic-icon>
80
+ <atomic-icon class=${iconClassNames} .icon=${thumbs_cjs_default()} aria-hidden="true"></atomic-icon>
80
81
  </button>`;
81
82
  };
82
83
  exports.renderFeedbackButton = __webpack_exports__.renderFeedbackButton;
@@ -69,8 +69,7 @@ const customRenderer = {
69
69
  return `<em part="answer-emphasis">${text}</em>`;
70
70
  },
71
71
  heading (text, level) {
72
- const plainText = toInlinePlainText(text);
73
- return `<div part="answer-heading-${level}" aria-label="${plainText}">${text}</div>`;
72
+ return `<div part="answer-heading-${level}" role="heading" aria-level="${level}">${text}</div>`;
74
73
  },
75
74
  html (text) {
76
75
  return escapeHtml(text);
@@ -31,10 +31,15 @@ __webpack_require__.d(__webpack_exports__, {
31
31
  renderGeneratedContentContainer: ()=>renderGeneratedContentContainer
32
32
  });
33
33
  const external_lit_namespaceObject = require("lit");
34
+ const if_defined_js_namespaceObject = require("lit/directives/if-defined.js");
34
35
  const generated_markdown_content_cjs_namespaceObject = require("./generated-content/generated-markdown-content.cjs");
35
36
  const generated_text_content_cjs_namespaceObject = require("./generated-content/generated-text-content.cjs");
36
37
  const renderGeneratedContentContainer = ({ props })=>(children)=>(0, external_lit_namespaceObject.html)`
37
- <div part="generated-container">
38
+ <div
39
+ part="generated-container"
40
+ id=${(0, if_defined_js_namespaceObject.ifDefined)(props.id)}
41
+ aria-busy=${props.isStreaming ? 'true' : 'false'}
42
+ >
38
43
  ${'text/markdown' === props.answerContentFormat ? (0, generated_markdown_content_cjs_namespaceObject.renderGeneratedMarkdownContent)({
39
44
  props: {
40
45
  answer: props.answer,
@@ -38,6 +38,7 @@ const external_show_button_cjs_namespaceObject = require("./show-button.cjs");
38
38
  const external_source_citations_cjs_namespaceObject = require("./source-citations.cjs");
39
39
  const external_render_generating_answer_label_cjs_namespaceObject = require("./render-generating-answer-label.cjs");
40
40
  require("../atomic-icon/atomic-icon.cjs");
41
+ const GENERATED_CONTENT_ID = 'generated-answer-content';
41
42
  const renderAnswerContent = ({ props })=>{
42
43
  const { i18n, generatedAnswer, collapsible, renderFeedbackAndCopyButtonsSlot, renderCitationsSlot, onRetry, onClickShowButton } = props;
43
44
  const { answer, isStreaming, citations, answerContentFormat, expanded, error } = generatedAnswer;
@@ -55,7 +56,8 @@ const renderAnswerContent = ({ props })=>{
55
56
  props: {
56
57
  answer,
57
58
  answerContentFormat,
58
- isStreaming: !!isStreaming
59
+ isStreaming: !!isStreaming,
60
+ id: collapsible ? GENERATED_CONTENT_ID : void 0
59
61
  }
60
62
  })((0, external_lit_namespaceObject.html)`
61
63
  ${(0, external_source_citations_cjs_namespaceObject.renderSourceCitations)({
@@ -83,7 +85,8 @@ const renderAnswerContent = ({ props })=>{
83
85
  props: {
84
86
  i18n,
85
87
  onClick: onClickShowButton,
86
- isCollapsed: !expanded
88
+ isCollapsed: !expanded,
89
+ controlsId: GENERATED_CONTENT_ID
87
90
  }
88
91
  }) : external_lit_namespaceObject.nothing}
89
92
  </div>
@@ -53,6 +53,7 @@ const renderShowButton = ({ props })=>(0, external_lit_namespaceObject.html)`${(
53
53
  part: 'answer-show-button',
54
54
  class: 'hidden items-center hover:bg-transparent',
55
55
  ariaExpanded: props.isCollapsed ? 'false' : 'true',
56
+ ariaControls: props.controlsId,
56
57
  onClick: props.onClick
57
58
  }
58
59
  })((0, external_lit_namespaceObject.html)`
@@ -177,11 +177,13 @@ class AtomicInsightGeneratedAnswer extends external_lit_namespaceObject.LitEleme
177
177
  async copyToClipboard(answer) {
178
178
  await this.controller.copyToClipboard(answer, ()=>{
179
179
  this.copied = true;
180
+ this.ariaCopyMessage.message = this.bindings.i18n.t('generated-answer-copied');
180
181
  setTimeout(()=>{
181
182
  this.copied = false;
182
183
  }, 2000);
183
184
  }, ()=>{
184
185
  this.copyError = true;
186
+ this.ariaCopyMessage.message = this.bindings.i18n.t('failed-to-copy-generated-answer');
185
187
  setTimeout(()=>{
186
188
  this.copyError = false;
187
189
  }, 2000);
@@ -318,7 +320,7 @@ class AtomicInsightGeneratedAnswer extends external_lit_namespaceObject.LitEleme
318
320
  constructor(){
319
321
  super(), this.DEFAULT_COLLAPSED_HEIGHT = 16, this.MAX_COLLAPSED_HEIGHT = 32, this.MIN_COLLAPSED_HEIGHT = 9, this.REQUIRED_FIELDS_TO_INCLUDE_IN_CITATIONS = [
320
322
  'filetype'
321
- ], this.withToggle = false, this.collapsible = false, this.maxCollapsedHeight = this.DEFAULT_COLLAPSED_HEIGHT, this.disableCitationAnchoring = false, this.copied = false, this.copyError = false, this.ariaMessage = new accessibility_utils_cjs_namespaceObject.AriaLiveRegionController(this, 'generated-answer', false, true), this.ariaErrorMessage = new accessibility_utils_cjs_namespaceObject.AriaLiveRegionController(this, 'generated-answer-error', true), this.onGeneratedAnswerStateUpdate = ()=>{
323
+ ], this.withToggle = false, this.collapsible = false, this.maxCollapsedHeight = this.DEFAULT_COLLAPSED_HEIGHT, this.disableCitationAnchoring = false, this.copied = false, this.copyError = false, this.ariaMessage = new accessibility_utils_cjs_namespaceObject.AriaLiveRegionController(this, 'generated-answer', false, true), this.ariaErrorMessage = new accessibility_utils_cjs_namespaceObject.AriaLiveRegionController(this, 'generated-answer-error', true), this.ariaCopyMessage = new accessibility_utils_cjs_namespaceObject.AriaLiveRegionController(this, 'generated-answer-copy', true), this.onGeneratedAnswerStateUpdate = ()=>{
322
324
  if (this.generatedAnswerState.isVisible !== this.controller.data.isVisible) {
323
325
  this.controller.data = {
324
326
  ...this.controller.data,
@@ -174,6 +174,7 @@ class AtomicGeneratedAnswer extends external_lit_namespaceObject.LitElement {
174
174
  'generated-answer-content-background': this.areFollowUpsEnabled,
175
175
  'agent-scrollable': this.areFollowUpsEnabled
176
176
  })}
177
+ tabindex=${this.areFollowUpsEnabled ? '0' : external_lit_namespaceObject.nothing}
177
178
  >
178
179
  <article>${this.renderAnswerContent()}</article>
179
180
  </div>
@@ -198,6 +199,9 @@ class AtomicGeneratedAnswer extends external_lit_namespaceObject.LitElement {
198
199
  </div>
199
200
  `;
200
201
  }
202
+ get shouldAnnounceAnswerStatus() {
203
+ return !this.areFollowUpsEnabled;
204
+ }
201
205
  get hasNoAnswerGenerated() {
202
206
  return this.controller.hasNoAnswerGenerated;
203
207
  }
@@ -222,11 +226,13 @@ class AtomicGeneratedAnswer extends external_lit_namespaceObject.LitElement {
222
226
  async copyToClipboard(answer) {
223
227
  await this.controller.copyToClipboard(answer, ()=>{
224
228
  this.copied = true;
229
+ this.ariaCopyMessage.message = this.bindings.i18n.t('generated-answer-copied');
225
230
  setTimeout(()=>{
226
231
  this.copied = false;
227
232
  }, 2000);
228
233
  }, ()=>{
229
234
  this.copyError = true;
235
+ this.ariaCopyMessage.message = this.bindings.i18n.t('failed-to-copy-generated-answer');
230
236
  setTimeout(()=>{
231
237
  this.copyError = false;
232
238
  }, 2000);
@@ -421,7 +427,7 @@ class AtomicGeneratedAnswer extends external_lit_namespaceObject.LitElement {
421
427
  constructor(){
422
428
  super(), this.DEFAULT_COLLAPSED_HEIGHT = 16, this.MAX_COLLAPSED_HEIGHT = 32, this.MIN_COLLAPSED_HEIGHT = 9, this.REQUIRED_FIELDS_TO_INCLUDE_IN_CITATIONS = [
423
429
  'filetype'
424
- ], this.withToggle = false, this.collapsible = false, this.maxCollapsedHeight = this.DEFAULT_COLLAPSED_HEIGHT, this.disableCitationAnchoring = false, this.tabsIncluded = [], this.tabsExcluded = [], this.copied = false, this.copyError = false, this.ariaMessage = new accessibility_utils_cjs_namespaceObject.AriaLiveRegionController(this, 'generated-answer', false, true), this.ariaErrorMessage = new accessibility_utils_cjs_namespaceObject.AriaLiveRegionController(this, 'generated-answer-error', true), this.onGeneratedAnswerStateUpdate = ()=>{
430
+ ], this.withToggle = false, this.collapsible = false, this.maxCollapsedHeight = this.DEFAULT_COLLAPSED_HEIGHT, this.disableCitationAnchoring = false, this.tabsIncluded = [], this.tabsExcluded = [], this.copied = false, this.copyError = false, this.ariaMessage = new accessibility_utils_cjs_namespaceObject.AriaLiveRegionController(this, 'generated-answer', false, true), this.ariaErrorMessage = new accessibility_utils_cjs_namespaceObject.AriaLiveRegionController(this, 'generated-answer-error', true), this.ariaCopyMessage = new accessibility_utils_cjs_namespaceObject.AriaLiveRegionController(this, 'generated-answer-copy', true), this.onGeneratedAnswerStateUpdate = ()=>{
425
431
  if (this.generatedAnswerState.isVisible !== this.controller.data.isVisible) {
426
432
  this.controller.data = {
427
433
  ...this.controller.data,
@@ -429,6 +435,7 @@ class AtomicGeneratedAnswer extends external_lit_namespaceObject.LitElement {
429
435
  };
430
436
  this.controller.writeStoredData(this.controller.data);
431
437
  }
438
+ if (!this.shouldAnnounceAnswerStatus) return;
432
439
  const status = this.controller.getGeneratedAnswerStatus();
433
440
  if (this.controller.isStatusAssertive()) {
434
441
  this.ariaMessage.message = '';
@@ -144,6 +144,7 @@ class AtomicSortDropdown extends external_lit_namespaceObject.LitElement {
144
144
  })))}`);
145
145
  }
146
146
  render() {
147
+ if (!this.options.length) return (0, external_lit_namespaceObject.html)`<slot></slot>`;
147
148
  const { hasError, hasResults, firstSearchExecuted, isLoading } = this.searchStatusState;
148
149
  return (0, external_lit_namespaceObject.html)`
149
150
  ${(0, sort_guard_cjs_namespaceObject.sortGuard)({
@@ -32,7 +32,7 @@ function getWindow() {
32
32
  }
33
33
  function getAtomicEnvironment(headlessVersion) {
34
34
  return {
35
- version: "3.61.3",
35
+ version: "3.61.5",
36
36
  headlessVersion
37
37
  };
38
38
  }
@@ -32,7 +32,7 @@ __webpack_require__.d(__webpack_exports__, {
32
32
  headlessVersion: ()=>package_json_namespaceObject.version
33
33
  });
34
34
  const package_json_namespaceObject = require("@coveo/headless/package.json");
35
- const atomicVersion = "3.61.3";
35
+ const atomicVersion = "3.61.5";
36
36
  exports.atomicVersion = __webpack_exports__.atomicVersion;
37
37
  exports.headlessVersion = __webpack_exports__.headlessVersion;
38
38
  for(var __rspack_i in __webpack_exports__)if (-1 === [
@@ -8,11 +8,18 @@ function registerAutoloader(roots) {
8
8
  roots
9
9
  ];
10
10
  const visitedNodes = new WeakSet();
11
+ const reportRegistrationError = (tagName, error)=>{
12
+ console.error(`[Atomic] Failed to register the "${tagName}" component. The component will not be displayed. This can happen when its code fails to load (e.g. network error, CDN issue, content security policy, proxy, or ad blocker).`, error);
13
+ };
11
14
  const observeStencilElementHydration = (atomicElement)=>{
12
15
  const attributeObserver = new MutationObserver(async ()=>{
13
16
  if (atomicElement.classList.contains('hydrated') && 'shadowRoot' in atomicElement && atomicElement.shadowRoot && !visitedNodes.has(atomicElement.shadowRoot)) {
14
17
  attributeObserver.disconnect();
15
- await discover(atomicElement.shadowRoot);
18
+ try {
19
+ await discover(atomicElement.shadowRoot);
20
+ } catch (error) {
21
+ reportRegistrationError(atomicElement.tagName.toLowerCase(), error);
22
+ }
16
23
  observer.observe(atomicElement.shadowRoot, {
17
24
  subtree: true,
18
25
  childList: true
@@ -67,16 +74,27 @@ function registerAutoloader(roots) {
67
74
  await Promise.allSettled(litRegistrationPromises);
68
75
  customElements.upgrade(root);
69
76
  };
70
- const register = (tagName)=>{
71
- if (customElements.get(tagName)) return Promise.resolve();
72
- return lazy_index[tagName]?.();
77
+ const register = async (tagName)=>{
78
+ if (customElements.get(tagName)) return;
79
+ try {
80
+ await lazy_index[tagName]?.();
81
+ } catch (error) {
82
+ reportRegistrationError(tagName, error);
83
+ }
73
84
  };
74
85
  const observer = new MutationObserver(async (mutations)=>{
75
- for (const { addedNodes } of mutations)for (const node of addedNodes)if (node.nodeType === Node.ELEMENT_NODE) await discover(node);
86
+ for (const { addedNodes } of mutations)for (const node of addedNodes)if (node.nodeType === Node.ELEMENT_NODE) try {
87
+ await discover(node);
88
+ } catch (error) {
89
+ reportRegistrationError(node.tagName.toLowerCase(), error);
90
+ }
76
91
  });
77
92
  const initializeDiscovery = ()=>{
78
93
  for (const root of roots){
79
- discover(root);
94
+ discover(root).catch((error)=>{
95
+ const tagName = root instanceof Element ? root.tagName.toLowerCase() : 'root';
96
+ reportRegistrationError(tagName, error);
97
+ });
80
98
  observer.observe(root, {
81
99
  subtree: true,
82
100
  childList: true
@@ -4,7 +4,9 @@ import { customElement, property, state } from "lit/decorators.js";
4
4
  import { when } from "lit/directives/when.js";
5
5
  import atomic_generated_answer_tw_css from "../../search/atomic-generated-answer/atomic-generated-answer.tw.css.js";
6
6
  import { withTailwindStyles } from "../../../decorators/with-tailwind-styles.js";
7
+ import { AriaLiveRegionController } from "../../../utils/accessibility-utils.js";
7
8
  import "../atomic-agent-stream-of-thought/atomic-agent-stream-of-thought.js";
9
+ import { getAnswerAnnouncement, isSettledAnswer } from "../generated-answer/answer-announcement.js";
8
10
  import { renderGeneratedContentContainer } from "../generated-answer/generated-content-container.js";
9
11
  import { renderFeedbackAndCopyButtons } from "../generated-answer/render-feedback-and-copy-buttons.js";
10
12
  import { renderSourceCitations } from "../generated-answer/source-citations.js";
@@ -58,6 +60,24 @@ class AtomicGeneratedAnswerContent extends LitElement {
58
60
  </div>
59
61
  `;
60
62
  }
63
+ updated() {
64
+ this.announceAnswerStatus();
65
+ }
66
+ announceAnswerStatus() {
67
+ if (!this.i18n || !this.generatedAnswer) return;
68
+ const { message, assertive } = getAnswerAnnouncement(this.generatedAnswer, this.i18n);
69
+ if (!this.hasObservedAnswer) {
70
+ this.hasObservedAnswer = true;
71
+ if (isSettledAnswer(this.generatedAnswer)) {
72
+ this.lastAnnouncedMessage = message;
73
+ return;
74
+ }
75
+ }
76
+ if (message === this.lastAnnouncedMessage) return;
77
+ this.lastAnnouncedMessage = message;
78
+ if (assertive) this.ariaErrorMessage.message = message;
79
+ else this.ariaMessage.message = message;
80
+ }
61
81
  renderFeedbackAndCopyButtons(answerId) {
62
82
  return html`
63
83
  <div class="mt-4" part="feedback-and-copy-buttons">
@@ -88,9 +108,11 @@ class AtomicGeneratedAnswerContent extends LitElement {
88
108
  try {
89
109
  await navigator.clipboard.writeText(answer);
90
110
  this.copyState = 'success';
111
+ this.ariaCopyMessage.message = this.i18n.t('generated-answer-copied');
91
112
  this.onCopyToClipboard(answerId);
92
113
  } catch (error) {
93
114
  this.copyState = 'error';
115
+ this.ariaCopyMessage.message = this.i18n.t('failed-to-copy-generated-answer');
94
116
  console.error(`Failed to copy to clipboard: ${error}`);
95
117
  }
96
118
  this.scheduleCopyReset();
@@ -127,7 +149,7 @@ class AtomicGeneratedAnswerContent extends LitElement {
127
149
  `;
128
150
  }
129
151
  constructor(...args){
130
- super(...args), this.answerId = '', this.renderCitations = ()=>html``, this.onClickLike = ()=>{}, this.onClickDislike = ()=>{}, this.onCopyToClipboard = ()=>{}, this.copyState = 'idle';
152
+ super(...args), this.answerId = '', this.renderCitations = ()=>html``, this.onClickLike = ()=>{}, this.onClickDislike = ()=>{}, this.onCopyToClipboard = ()=>{}, this.copyState = 'idle', this.ariaMessage = new AriaLiveRegionController(this, 'generated-answer', false, true), this.ariaErrorMessage = new AriaLiveRegionController(this, 'generated-answer-error', true), this.ariaCopyMessage = new AriaLiveRegionController(this, 'generated-answer-copy', true), this.hasObservedAnswer = false;
131
153
  }
132
154
  }
133
155
  AtomicGeneratedAnswerContent.styles = [
@@ -106,7 +106,7 @@ class AtomicGeneratedAnswerThread extends LitElement {
106
106
  `;
107
107
  return html`
108
108
  <li class="group/title grid min-w-0 grid-cols-[10px_1fr] gap-x-3">
109
- <div class="row-span-2 flex flex-col items-center">
109
+ <div class="row-span-2 flex flex-col items-center" aria-hidden="true">
110
110
  <div class="flex justify-center items-center text-base h-[1lh] my-1.5">
111
111
  <span class=${timelineDotClasses}></span>
112
112
  </div>
@@ -89,7 +89,7 @@ class AtomicGeneratedAnswerThreadItem extends LitElement {
89
89
  const timelineConnectorClasses = "relative h-full w-px bg-neutral transition-colors duration-150 group-hover:bg-neutral-dark before:absolute before:left-0 before:top-[-8px] before:h-[8px] before:w-px before:bg-neutral before:transition-colors before:duration-150 group-hover:before:bg-neutral-dark before:content-[''] after:absolute after:bottom-[-8px] after:left-0 after:h-[8px] after:w-px after:bg-neutral after:transition-colors after:duration-150 group-hover:after:bg-neutral-dark after:content-['']";
90
90
  return html`
91
91
  <div class="group/title grid min-w-0 grid-cols-[10px_1fr] gap-x-3">
92
- <div class="row-span-2 flex flex-col items-center">
92
+ <div class="row-span-2 flex flex-col items-center" aria-hidden="true">
93
93
  <div class=${timelineDotToggleClasses}>
94
94
  ${when(this.showTimelineDot, ()=>html`
95
95
  <span
@@ -123,8 +123,9 @@ class AtomicGeneratedAnswerThreadItem extends LitElement {
123
123
  >${this.title}</span
124
124
  >`)}
125
125
  </div>
126
- <div id=${this.contentId} class="min-w-0 pl-2 py-1.5">
126
+ <div class="min-w-0 pl-2 py-1.5">
127
127
  <div
128
+ id=${this.contentId}
128
129
  class="mb-2"
129
130
  ?hidden=${!this.isExpanded}
130
131
  aria-hidden=${this.isExpanded ? 'false' : 'true'}
@@ -0,0 +1,32 @@
1
+ import { markdownToPlainText } from "./generated-content/markdown-utils.js";
2
+ const SILENT = {
3
+ message: '',
4
+ assertive: false
5
+ };
6
+ const getAnswerAnnouncement = (answer, i18n)=>{
7
+ if (!answer) return SILENT;
8
+ if (answer.error) {
9
+ const errorMessageKey = answer.error.isSseTurnLimitReachedError?.() ? 'generated-answer-error-turn-limit-reached' : 'generated-answer-error-generic';
10
+ return {
11
+ message: i18n.t(errorMessageKey),
12
+ assertive: true
13
+ };
14
+ }
15
+ if (answer.cannotAnswer) return {
16
+ message: i18n.t('generated-answer-cannot-generate-answer'),
17
+ assertive: true
18
+ };
19
+ if (answer.isStreaming || answer.isLoading) return {
20
+ message: i18n.t('generating-answer'),
21
+ assertive: false
22
+ };
23
+ if (answer.answer?.trim()) return {
24
+ message: i18n.t('answer-generated', {
25
+ answer: markdownToPlainText(answer.answer)
26
+ }),
27
+ assertive: false
28
+ };
29
+ return SILENT;
30
+ };
31
+ const isSettledAnswer = (answer)=>Boolean(answer && !answer.isStreaming && !answer.isLoading && !answer.error && !answer.cannotAnswer && answer.answer?.trim());
32
+ export { getAnswerAnnouncement, isSettledAnswer };
@@ -12,6 +12,7 @@ const renderCopyButton = ({ props })=>{
12
12
  return renderButton({
13
13
  props: {
14
14
  title: props.title,
15
+ ariaLabel: props.title,
15
16
  part: 'copy-button',
16
17
  style: 'text-transparent',
17
18
  class: classes.join(' '),
@@ -19,7 +20,7 @@ const renderCopyButton = ({ props })=>{
19
20
  }
20
21
  })(html`
21
22
  <div class="icon-container text-neutral-dark">
22
- <atomic-icon class="w-5" .icon=${copy}></atomic-icon>
23
+ <atomic-icon class="w-5" .icon=${copy} aria-hidden="true"></atomic-icon>
23
24
  </div>
24
25
  `);
25
26
  };
@@ -26,6 +26,7 @@ const renderFeedbackButton = ({ props })=>{
26
26
  return html`<button
27
27
  type="button"
28
28
  title=${props.title}
29
+ aria-label=${props.title}
29
30
  part="feedback-button"
30
31
  class=${classNames}
31
32
  aria-pressed=${props.active ? 'true' : 'false'}
@@ -34,7 +35,7 @@ const renderFeedbackButton = ({ props })=>{
34
35
  })}
35
36
  @click=${props.onClick}
36
37
  >
37
- <atomic-icon class=${iconClassNames} .icon=${thumbs}></atomic-icon>
38
+ <atomic-icon class=${iconClassNames} .icon=${thumbs} aria-hidden="true"></atomic-icon>
38
39
  </button>`;
39
40
  };
40
41
  export { renderFeedbackButton };
@@ -36,8 +36,7 @@ const customRenderer = {
36
36
  return `<em part="answer-emphasis">${text}</em>`;
37
37
  },
38
38
  heading (text, level) {
39
- const plainText = toInlinePlainText(text);
40
- return `<div part="answer-heading-${level}" aria-label="${plainText}">${text}</div>`;
39
+ return `<div part="answer-heading-${level}" role="heading" aria-level="${level}">${text}</div>`;
41
40
  },
42
41
  html (text) {
43
42
  return escapeHtml(text);