@coveo/atomic-react 3.11.44 → 3.11.45

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.
@@ -8361,7 +8361,7 @@ function getWindow$1() {
8361
8361
  }
8362
8362
  function getAtomicEnvironment(headlessVersion) {
8363
8363
  return {
8364
- version: "3.61.4",
8364
+ version: "3.61.5",
8365
8365
  headlessVersion
8366
8366
  };
8367
8367
  }
@@ -18625,8 +18625,7 @@ const customRenderer = {
18625
18625
  return `<em part="answer-emphasis">${text}</em>`;
18626
18626
  },
18627
18627
  heading (text, level) {
18628
- const plainText = toInlinePlainText(text);
18629
- return `<div part="answer-heading-${level}" aria-label="${plainText}">${text}</div>`;
18628
+ return `<div part="answer-heading-${level}" role="heading" aria-level="${level}">${text}</div>`;
18630
18629
  },
18631
18630
  html (text) {
18632
18631
  return escapeHtml(text);
@@ -19285,6 +19284,37 @@ const generated_answer_tw_css = [
19285
19284
 
19286
19285
  const atomic_generated_answer_tw_css = generated_answer_tw_css;
19287
19286
 
19287
+ const SILENT = {
19288
+ message: '',
19289
+ assertive: false
19290
+ };
19291
+ const getAnswerAnnouncement = (answer, i18n)=>{
19292
+ if (!answer) return SILENT;
19293
+ if (answer.error) {
19294
+ const errorMessageKey = answer.error.isSseTurnLimitReachedError?.() ? 'generated-answer-error-turn-limit-reached' : 'generated-answer-error-generic';
19295
+ return {
19296
+ message: i18n.t(errorMessageKey),
19297
+ assertive: true
19298
+ };
19299
+ }
19300
+ if (answer.cannotAnswer) return {
19301
+ message: i18n.t('generated-answer-cannot-generate-answer'),
19302
+ assertive: true
19303
+ };
19304
+ if (answer.isStreaming || answer.isLoading) return {
19305
+ message: i18n.t('generating-answer'),
19306
+ assertive: false
19307
+ };
19308
+ if (answer.answer?.trim()) return {
19309
+ message: i18n.t('answer-generated', {
19310
+ answer: markdownToPlainText(answer.answer)
19311
+ }),
19312
+ assertive: false
19313
+ };
19314
+ return SILENT;
19315
+ };
19316
+ const isSettledAnswer = (answer)=>Boolean(answer && !answer.isStreaming && !answer.isLoading && !answer.error && !answer.cannotAnswer && answer.answer?.trim());
19317
+
19288
19318
  const styles$8 = lit.css`/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */:host{display:inline}a{color:var(--atomic-primary);text-decoration-line:none}a [part=answer-link-text]{text-decoration-line:underline}.icon-wrapper{vertical-align:text-bottom;width:1em;height:1em;display:inline-block}`;
19289
19319
  const atomic_generated_answer_inline_link_tw_css = styles$8;
19290
19320
 
@@ -19423,7 +19453,11 @@ const renderGeneratedTextContent = ({ props })=>lit.html`
19423
19453
  `;
19424
19454
 
19425
19455
  const renderGeneratedContentContainer = ({ props })=>(children)=>lit.html`
19426
- <div part="generated-container">
19456
+ <div
19457
+ part="generated-container"
19458
+ id=${ifDefined_js.ifDefined(props.id)}
19459
+ aria-busy=${props.isStreaming ? 'true' : 'false'}
19460
+ >
19427
19461
  ${'text/markdown' === props.answerContentFormat ? renderGeneratedMarkdownContent({
19428
19462
  props: {
19429
19463
  answer: props.answer,
@@ -19451,6 +19485,7 @@ const renderCopyButton = ({ props })=>{
19451
19485
  return renderButton({
19452
19486
  props: {
19453
19487
  title: props.title,
19488
+ ariaLabel: props.title,
19454
19489
  part: 'copy-button',
19455
19490
  style: 'text-transparent',
19456
19491
  class: classes.join(' '),
@@ -19458,7 +19493,7 @@ const renderCopyButton = ({ props })=>{
19458
19493
  }
19459
19494
  })(lit.html`
19460
19495
  <div class="icon-container text-neutral-dark">
19461
- <atomic-icon class="w-5" .icon=${copy}></atomic-icon>
19496
+ <atomic-icon class="w-5" .icon=${copy} aria-hidden="true"></atomic-icon>
19462
19497
  </div>
19463
19498
  `);
19464
19499
  };
@@ -19487,6 +19522,7 @@ const renderFeedbackButton = ({ props })=>{
19487
19522
  return lit.html`<button
19488
19523
  type="button"
19489
19524
  title=${props.title}
19525
+ aria-label=${props.title}
19490
19526
  part="feedback-button"
19491
19527
  class=${classNames}
19492
19528
  aria-pressed=${props.active ? 'true' : 'false'}
@@ -19495,7 +19531,7 @@ const renderFeedbackButton = ({ props })=>{
19495
19531
  })}
19496
19532
  @click=${props.onClick}
19497
19533
  >
19498
- <atomic-icon class=${iconClassNames} .icon=${thumbs}></atomic-icon>
19534
+ <atomic-icon class=${iconClassNames} .icon=${thumbs} aria-hidden="true"></atomic-icon>
19499
19535
  </button>`;
19500
19536
  };
19501
19537
 
@@ -19609,6 +19645,24 @@ class AtomicGeneratedAnswerContent extends lit.LitElement {
19609
19645
  </div>
19610
19646
  `;
19611
19647
  }
19648
+ updated() {
19649
+ this.announceAnswerStatus();
19650
+ }
19651
+ announceAnswerStatus() {
19652
+ if (!this.i18n || !this.generatedAnswer) return;
19653
+ const { message, assertive } = getAnswerAnnouncement(this.generatedAnswer, this.i18n);
19654
+ if (!this.hasObservedAnswer) {
19655
+ this.hasObservedAnswer = true;
19656
+ if (isSettledAnswer(this.generatedAnswer)) {
19657
+ this.lastAnnouncedMessage = message;
19658
+ return;
19659
+ }
19660
+ }
19661
+ if (message === this.lastAnnouncedMessage) return;
19662
+ this.lastAnnouncedMessage = message;
19663
+ if (assertive) this.ariaErrorMessage.message = message;
19664
+ else this.ariaMessage.message = message;
19665
+ }
19612
19666
  renderFeedbackAndCopyButtons(answerId) {
19613
19667
  return lit.html`
19614
19668
  <div class="mt-4" part="feedback-and-copy-buttons">
@@ -19639,9 +19693,11 @@ class AtomicGeneratedAnswerContent extends lit.LitElement {
19639
19693
  try {
19640
19694
  await navigator.clipboard.writeText(answer);
19641
19695
  this.copyState = 'success';
19696
+ this.ariaCopyMessage.message = this.i18n.t('generated-answer-copied');
19642
19697
  this.onCopyToClipboard(answerId);
19643
19698
  } catch (error) {
19644
19699
  this.copyState = 'error';
19700
+ this.ariaCopyMessage.message = this.i18n.t('failed-to-copy-generated-answer');
19645
19701
  console.error(`Failed to copy to clipboard: ${error}`);
19646
19702
  }
19647
19703
  this.scheduleCopyReset();
@@ -19678,7 +19734,7 @@ class AtomicGeneratedAnswerContent extends lit.LitElement {
19678
19734
  `;
19679
19735
  }
19680
19736
  constructor(...args){
19681
- super(...args), this.answerId = '', this.renderCitations = ()=>lit.html``, this.onClickLike = ()=>{}, this.onClickDislike = ()=>{}, this.onCopyToClipboard = ()=>{}, this.copyState = 'idle';
19737
+ super(...args), this.answerId = '', this.renderCitations = ()=>lit.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;
19682
19738
  }
19683
19739
  }
19684
19740
  AtomicGeneratedAnswerContent.styles = [
@@ -20277,7 +20333,7 @@ class AtomicGeneratedAnswerThreadItem extends lit.LitElement {
20277
20333
  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-['']";
20278
20334
  return lit.html`
20279
20335
  <div class="group/title grid min-w-0 grid-cols-[10px_1fr] gap-x-3">
20280
- <div class="row-span-2 flex flex-col items-center">
20336
+ <div class="row-span-2 flex flex-col items-center" aria-hidden="true">
20281
20337
  <div class=${timelineDotToggleClasses}>
20282
20338
  ${when_js.when(this.showTimelineDot, ()=>lit.html`
20283
20339
  <span
@@ -20311,8 +20367,9 @@ class AtomicGeneratedAnswerThreadItem extends lit.LitElement {
20311
20367
  >${this.title}</span
20312
20368
  >`)}
20313
20369
  </div>
20314
- <div id=${this.contentId} class="min-w-0 pl-2 py-1.5">
20370
+ <div class="min-w-0 pl-2 py-1.5">
20315
20371
  <div
20372
+ id=${this.contentId}
20316
20373
  class="mb-2"
20317
20374
  ?hidden=${!this.isExpanded}
20318
20375
  aria-hidden=${this.isExpanded ? 'false' : 'true'}
@@ -20473,7 +20530,7 @@ class AtomicGeneratedAnswerThread extends lit.LitElement {
20473
20530
  `;
20474
20531
  return lit.html`
20475
20532
  <li class="group/title grid min-w-0 grid-cols-[10px_1fr] gap-x-3">
20476
- <div class="row-span-2 flex flex-col items-center">
20533
+ <div class="row-span-2 flex flex-col items-center" aria-hidden="true">
20477
20534
  <div class="flex justify-center items-center text-base h-[1lh] my-1.5">
20478
20535
  <span class=${timelineDotClasses}></span>
20479
20536
  </div>
@@ -22119,6 +22176,7 @@ const renderShowButton = ({ props })=>lit.html`${renderButton({
22119
22176
  part: 'answer-show-button',
22120
22177
  class: 'hidden items-center hover:bg-transparent',
22121
22178
  ariaExpanded: props.isCollapsed ? 'false' : 'true',
22179
+ ariaControls: props.controlsId,
22122
22180
  onClick: props.onClick
22123
22181
  }
22124
22182
  })(lit.html`
@@ -22149,6 +22207,7 @@ const renderGeneratingAnswerLabel = ({ props })=>{
22149
22207
  `)}`;
22150
22208
  };
22151
22209
 
22210
+ const GENERATED_CONTENT_ID = 'generated-answer-content';
22152
22211
  const renderAnswerContent = ({ props })=>{
22153
22212
  const { i18n, generatedAnswer, collapsible, renderFeedbackAndCopyButtonsSlot, renderCitationsSlot, onRetry, onClickShowButton } = props;
22154
22213
  const { answer, isStreaming, citations, answerContentFormat, expanded, error } = generatedAnswer;
@@ -22166,7 +22225,8 @@ const renderAnswerContent = ({ props })=>{
22166
22225
  props: {
22167
22226
  answer,
22168
22227
  answerContentFormat,
22169
- isStreaming: !!isStreaming
22228
+ isStreaming: !!isStreaming,
22229
+ id: collapsible ? GENERATED_CONTENT_ID : void 0
22170
22230
  }
22171
22231
  })(lit.html`
22172
22232
  ${renderSourceCitations({
@@ -22194,7 +22254,8 @@ const renderAnswerContent = ({ props })=>{
22194
22254
  props: {
22195
22255
  i18n,
22196
22256
  onClick: onClickShowButton,
22197
- isCollapsed: !expanded
22257
+ isCollapsed: !expanded,
22258
+ controlsId: GENERATED_CONTENT_ID
22198
22259
  }
22199
22260
  }) : lit.nothing}
22200
22261
  </div>
@@ -28602,6 +28663,7 @@ let AtomicGeneratedAnswer$1 = class AtomicGeneratedAnswer extends lit.LitElement
28602
28663
  'generated-answer-content-background': this.areFollowUpsEnabled,
28603
28664
  'agent-scrollable': this.areFollowUpsEnabled
28604
28665
  })}
28666
+ tabindex=${this.areFollowUpsEnabled ? '0' : lit.nothing}
28605
28667
  >
28606
28668
  <article>${this.renderAnswerContent()}</article>
28607
28669
  </div>
@@ -28626,6 +28688,9 @@ let AtomicGeneratedAnswer$1 = class AtomicGeneratedAnswer extends lit.LitElement
28626
28688
  </div>
28627
28689
  `;
28628
28690
  }
28691
+ get shouldAnnounceAnswerStatus() {
28692
+ return !this.areFollowUpsEnabled;
28693
+ }
28629
28694
  get hasNoAnswerGenerated() {
28630
28695
  return this.controller.hasNoAnswerGenerated;
28631
28696
  }
@@ -28650,11 +28715,13 @@ let AtomicGeneratedAnswer$1 = class AtomicGeneratedAnswer extends lit.LitElement
28650
28715
  async copyToClipboard(answer) {
28651
28716
  await this.controller.copyToClipboard(answer, ()=>{
28652
28717
  this.copied = true;
28718
+ this.ariaCopyMessage.message = this.bindings.i18n.t('generated-answer-copied');
28653
28719
  setTimeout(()=>{
28654
28720
  this.copied = false;
28655
28721
  }, 2000);
28656
28722
  }, ()=>{
28657
28723
  this.copyError = true;
28724
+ this.ariaCopyMessage.message = this.bindings.i18n.t('failed-to-copy-generated-answer');
28658
28725
  setTimeout(()=>{
28659
28726
  this.copyError = false;
28660
28727
  }, 2000);
@@ -28849,7 +28916,7 @@ let AtomicGeneratedAnswer$1 = class AtomicGeneratedAnswer extends lit.LitElement
28849
28916
  constructor(){
28850
28917
  super(), this.DEFAULT_COLLAPSED_HEIGHT = 16, this.MAX_COLLAPSED_HEIGHT = 32, this.MIN_COLLAPSED_HEIGHT = 9, this.REQUIRED_FIELDS_TO_INCLUDE_IN_CITATIONS = [
28851
28918
  'filetype'
28852
- ], 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 AriaLiveRegionController(this, 'generated-answer', false, true), this.ariaErrorMessage = new AriaLiveRegionController(this, 'generated-answer-error', true), this.onGeneratedAnswerStateUpdate = ()=>{
28919
+ ], 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 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.onGeneratedAnswerStateUpdate = ()=>{
28853
28920
  if (this.generatedAnswerState.isVisible !== this.controller.data.isVisible) {
28854
28921
  this.controller.data = {
28855
28922
  ...this.controller.data,
@@ -28857,6 +28924,7 @@ let AtomicGeneratedAnswer$1 = class AtomicGeneratedAnswer extends lit.LitElement
28857
28924
  };
28858
28925
  this.controller.writeStoredData(this.controller.data);
28859
28926
  }
28927
+ if (!this.shouldAnnounceAnswerStatus) return;
28860
28928
  const status = this.controller.getGeneratedAnswerStatus();
28861
28929
  if (this.controller.isStatusAssertive()) {
28862
28930
  this.ariaMessage.message = '';