> ## Documentation Index
> Fetch the complete documentation index at: https://velt.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Velt SDK Changelog

> Release Notes of changes added to the core Velt SDK

### Libraries

* `@veltdev/react`
* `@veltdev/client`
* `@veltdev/sdk`

<Update label="4.7.13" description="February 17, 2026">
  ### Bug Fixes

  * \[**Comments**]: Fixed sidebar comment navigation scrolling the page unexpectedly. The window scroll position is now captured and restored after `scrollIntoView()` runs, so only the sidebar panel scrolls and the page remains at its current position.
</Update>

<Update label="4.7.12" description="February 16, 2026">
  ### Bug Fixes

  * \[**Comments**]: Fixed sidebar not auto-exiting focused thread mode when the annotation is deselected. The sidebar now automatically exits focused thread mode and returns to the "all comments" view when the focused annotation is deselected.
</Update>

<Update label="4.7.11" description="February 12, 2026">
  ### New Features

  * \[**Comments**]: Added `attachmentDownloadClicked` event and methods to control automatic attachment downloads. You can now intercept download clicks to implement custom download behavior such as analytics tracking, custom URLs, or access control checks.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      import { VeltComments, useCommentUtils } from '@veltdev/react';

      // Disable automatic downloads via component prop
      <VeltComments attachmentDownload={false} />

      // Using API methods
      const commentElement = client.getCommentElement();

      // Control automatic downloads
      commentElement.disableAttachmentDownload();
      commentElement.enableAttachmentDownload();

      // Listen to download click events
      commentElement.on('attachmentDownloadClicked').subscribe((event) => {
        console.log('Attachment clicked:', event.attachment);
        console.log('Annotation ID:', event.annotationId);
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <!-- Disable automatic downloads via HTML attribute -->
      <velt-comments attachment-download="false"></velt-comments>

      <script>
      const commentElement = Velt.getCommentElement();

      // Control automatic downloads
      commentElement.disableAttachmentDownload();
      commentElement.enableAttachmentDownload();

      // Listen to download click events
      commentElement.on('attachmentDownloadClicked').subscribe((event) => {
        console.log('Attachment clicked:', event.attachment);
        console.log('Annotation ID:', event.annotationId);
      });
      </script>
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Comments**]: Moved attachment loading indicator to a parent wrapper element for better CSS targeting. Custom CSS targeting `.loading` on attachment elements should be updated to target `.velt-composer-attachment--loading` on `.velt-composer-attachment-container`.

  ### Bug Fixes

  * \[**Comments**]: Fixed unintended draft auto-save when navigating back from a focused thread view.
  * \[**Comments**]: Fixed sidebar not deselecting annotations when navigating back from a focused thread.
  * \[**Comments**]: Fixed thread card attachments not falling back to default rendering when an empty wireframe template is provided.
  * \[**Comments**]: Fixed edit composer not rendering when custom thread card wireframe omits the edit composer wireframe. The default edit composer now renders automatically.
</Update>

<Update label="4.7.10" description="February 12, 2026">
  ### Bug Fixes

  * \[**Comments**]: Fixed `ADD_COMMENT` event not firing for page comment annotations. Event listeners subscribed to `ADD_COMMENT` now receive callbacks consistently for all comment creation flows, including page comments.
</Update>

<Update label="4.7.9" description="February 4, 2026">
  ### Improvements

  * \[**Comments**]: Added a `readOnly` prop to `VeltCommentComposer` and `VeltInlineCommentsSection` components that allows disabling comment input at the component level. Developers can now create mixed read/write interfaces where some comment areas are locked while others are interactive.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      import { VeltCommentComposer, VeltInlineCommentsSection } from '@veltdev/react';

      <VeltCommentComposer readOnly={true} />

      <VeltInlineCommentsSection
        readOnly={true}
      />

      // Using API methods
      const commentElement = client.getCommentElement();
      commentElement.enableReadOnlyMode();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comment-composer read-only="true"></velt-comment-composer>

      <velt-inline-comments-section
        read-only="true">
      </velt-inline-comments-section>

      <script>
      const commentElement = Velt.getCommentElement();
      Velt.enableReadOnlyMode();
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: A new edit composer wireframe for the comment dialog lets you customize the edit composer UI within comment thread cards.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltCommentDialogWireframe.ThreadCard.EditComposer />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comment-dialog-thread-card-edit-composer-wireframe></velt-comment-dialog-thread-card-edit-composer-wireframe>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: You can associate comments created via the page mode composer with specific elements using the `targetElementId` property.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      import { useCommentUtils } from '@veltdev/react';

      const commentElement = useCommentUtils();

      commentElement.setContextInPageModeComposer({
        context: { projectId: 'abc123' },
        targetElementId: 'my-target-element'
      });

      // Using API methods
      const commentElement = client.getCommentElement();
      commentElement.setContextInPageModeComposer({
        context: { projectId: 'abc123' },
        targetElementId: 'my-target-element'
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const commentElement = Velt.getCommentElement();
      commentElement.setContextInPageModeComposer({
        context: { projectId: 'abc123' },
        targetElementId: 'my-target-element'
      });
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `CommentAnnotation.resolvedByUser` property to expose the full `User` object so you can access it without additional API calls.

  * \[**Comments**]: `setAssignToType()` now accepts an `AssignToConfig` object for consistent API patterns.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      const commentElement = useCommentUtils();
      commentElement.setAssignToType({ type: 'dropdown' });
      // or
      commentElement.setAssignToType({ type: 'checkbox' });

      // Using API methods
      const commentElement = client.getCommentElement();
      commentElement.setAssignToType({ type: 'dropdown' });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const commentElement = Velt.getCommentElement();
      commentElement.setAssignToType({ type: 'dropdown' });
      // or
      commentElement.setAssignToType({ type: 'checkbox' });
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `targetElementId` to `CommentToolClickEvent` so you can identify which element was targeted when users initiate a comment.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      const commentToolClickEvent = useCommentEventCallback('commentToolClick');

      useEffect(() => {
        if (commentToolClickEvent) {
          console.log('Context:', commentToolClickEvent.context);
          console.log('Target Element ID:', commentToolClickEvent.targetElementId);
        }
      }, [commentToolClickEvent]);

      // Using API methods
      const commentElement = client.getCommentElement();
      commentElement.on('commentToolClick').subscribe((event) => {
        console.log('Target Element ID:', event.targetElementId);
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const commentElement = Velt.getCommentElement();
      commentElement.on('commentToolClick').subscribe((event) => {
        console.log('Context:', event.context);
        console.log('Target Element ID:', event.targetElementId);
      });
      </script>
      ```
    </Tab>
  </Tabs>

  ### Bug Fixes

  * \[**Comments**]: Fixed cursor position jumping when clicking autocomplete tool buttons so that @ mention and other autocomplete triggers now insert at the correct cursor position.
  * \[**Comments**]: Fixed actions menu visibility in comment dialog so the menu on the first thread card remains visible when the assignment dropdown is opened.
  * \[**Comments**]: Added "Assign" tooltip to the assignment button in comment dialog thread cards.
  * \[**Comments**]: Added `velt-reaction-pin--no-reactions` CSS class to empty reaction pins for custom styling.
  * \[**Comments**]: Fixed autocomplete panel viewport height calculation to respect custom `itemSize` from `autoCompleteScrollConfig`.
  * \[**Comments**]: Fixed attachment upload failures by using fallback metadata values from document paths and config service.
  * \[**Comments**]: Fixed read-only state management so local `readOnly` props are no longer overridden by global read-only state changes.
</Update>

<Update label="4.7.8" description="February 3, 2026">
  ### New Features

  * \[**Comments**]: Added Thread card assign button wireframe to customize the assign button that appears on individual comment thread cards.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltCommentDialogWireframe.ThreadCard.AssignButton />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comment-dialog-thread-card-assign-button-wireframe></velt-comment-dialog-thread-card-assign-button-wireframe>
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Comments**]: Added a CSS class to indicate the selected state on the assign dropdown checkbox.

  ### Bug Fixes

  * \[**Comments**]: Fixed "Assign To" label capitalization to "Assign to" for proper sentence case.
</Update>

<Update label="4.7.7" description="February 3, 2026">
  ### New Features

  * \[**Comments**]: Added ability to set context data and focus the page mode composer programmatically using `setContextInPageModeComposer()` and `focusPageModeComposer()` methods.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      import { useCommentUtils } from '@veltdev/react';

      const commentElement = useCommentUtils();

      // Set context data for the page mode composer
      commentElement.setContextInPageModeComposer({
        documentId: 'doc-123',
        sectionId: 'section-456',
        customData: 'any-value'
      });

      // Clear the context
      commentElement.setContextInPageModeComposer(null);

      // Focus the page mode composer input
      commentElement.focusPageModeComposer();

      // Using API methods
      const commentElement = client.getCommentElement();
      commentElement.setContextInPageModeComposer({ documentId: 'doc-123' });
      commentElement.focusPageModeComposer();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const commentElement = Velt.getCommentElement();

      // Set context data for the page mode composer
      commentElement.setContextInPageModeComposer({
        documentId: 'doc-123',
        sectionId: 'section-456',
        customData: 'any-value'
      });

      // Clear the context
      commentElement.setContextInPageModeComposer(null);

      // Focus the page mode composer input
      commentElement.focusPageModeComposer();
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added a new `commentToolClick` event that fires when the comment tool button is clicked.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks

      const commentToolClickEvent = useCommentEventCallback('commentToolClick');

      useEffect(() => {
        if (commentToolClickEvent) {
          console.log('Comment tool clicked');
          console.log('Context:', commentToolClickEvent.context);
          console.log('Target Element ID:', commentToolClickEvent.targetElementId);
        }
      }, [commentToolClickEvent]);

      // Using API methods
      const commentElement = client.getCommentElement();
      commentElement.on('commentToolClick').subscribe((event) => {
        console.log('Context:', event.context);
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const commentElement = Velt.getCommentElement();

      commentElement.on('commentToolClick').subscribe((event) => {
        console.log('Comment tool clicked');
        console.log('Context:', event.context);
        console.log('Metadata:', event.metadata);
      });
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added a new `sidebarButtonClick` event that fires when the sidebar button is clicked.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      const sidebarButtonClickEvent = useCommentEventCallback('sidebarButtonClick');

      useEffect(() => {
        if (sidebarButtonClickEvent) {
          console.log('Sidebar button clicked');
        }
      }, [sidebarButtonClickEvent]);

      // Using API methods
      const commentElement = client.getCommentElement();
      commentElement.on('sidebarButtonClick').subscribe((event) => {
        console.log('Metadata:', event.metadata);
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-sidebar-button></velt-sidebar-button>

      <script>
      const commentElement = Velt.getCommentElement();

      commentElement.on('sidebarButtonClick').subscribe((event) => {
        console.log('Sidebar button clicked');
        console.log('Metadata:', event.metadata);
      });
      </script>
      ```
    </Tab>
  </Tabs>

  ### Bug Fixes

  * \[**Comments**]: Fixed `reactionId` prop on `VeltCommentDialogWireframe.ThreadCard.ReactionPin` not converting to dashed-case format when passed to the underlying HTML element.
</Update>

<Update label="4.7.6" description="February 3, 2026">
  ### New Features

  * \[**Comments**]: Added ability to configure the assign-to functionality to use either a dropdown or checkbox mode for assigning users to comments.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using component
      import { VeltComments } from '@veltdev/react';

      <VeltComments assignToType="checkbox" />

      // Using API method
      const commentElement = client.getCommentElement();
      commentElement.setAssignToType('checkbox'); // or 'dropdown'
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments assign-to-type="checkbox"></velt-comments>

      <script>
      const commentElement = Velt.getCommentElement();
      commentElement.setAssignToType('checkbox'); // or 'dropdown'
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Context in page mode composer—pass context data to the page mode composer when opening the comment sidebar via the comment tool.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using component
      import { VeltCommentTool } from '@veltdev/react';

      <VeltCommentTool
        contextInPageModeComposer={true}
        context={{ section: 'header', elementId: 'nav-menu' }}
      />

      // Using API methods
      const commentElement = client.getCommentElement();
      commentElement.enableContextInPageModeComposer();
      commentElement.disableContextInPageModeComposer();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comment-tool
        context-in-page-mode-composer="true"
        context='{"section": "header", "elementId": "nav-menu"}'>
      </velt-comment-tool>

      <script>
      const commentElement = Velt.getCommentElement();
      commentElement.enableContextInPageModeComposer();
      commentElement.disableContextInPageModeComposer();
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `clearPageModeComposerContext()` method to clear context data from page mode composer. This is useful when you are using sidebar in embed mode and have to clear the context from page mode composer manually.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      const commentElement = client.getCommentElement();
      commentElement.clearPageModeComposerContext();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const commentElement = Velt.getCommentElement();
      commentElement.clearPageModeComposerContext();
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Reaction pin component—display specific reaction pins within comment thread cards using the new `VeltCommentDialogThreadCardReactionPin` wireframe component.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      import { VeltCommentDialogWireframe } from '@veltdev/react';

      <VeltCommentDialogWireframe.ThreadCard>
        <VeltCommentDialogWireframe.ThreadCard.ReactionPin reactionId="thumbs-up" />
        <VeltCommentDialogWireframe.ThreadCard.ReactionPin reactionId="heart" />
      </VeltCommentDialogWireframe.ThreadCard>
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comment-dialog-thread-card-reaction-pin-wireframe
        reaction-id="thumbs-up">
      </velt-comment-dialog-thread-card-reaction-pin-wireframe>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Exclude reactions from thread cards—exclude specific reactions from being displayed using `excludeReactionIds` on `VeltCommentDialogThreadCardReactions` and `VeltCommentDialogThreadCardReactionTool` components.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      import { VeltCommentDialogWireframe } from '@veltdev/react';

      <VeltCommentDialogWireframe.ThreadCard.Reactions
        excludeReactionIds={['thumbs-up', 'heart']}
      />
      <VeltCommentDialogWireframe.ThreadCard.ReactionTool
        excludeReactionIds={['thumbs-up', 'heart']}
      />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comment-dialog-thread-card-reactions-wireframe
        exclude-reaction-ids='["thumbs-up", "heart"]'>
      </velt-comment-dialog-thread-card-reactions-wireframe>

      <velt-comment-dialog-thread-card-reaction-tool-wireframe
        exclude-reaction-ids='["thumbs-up", "heart"]'>
      </velt-comment-dialog-thread-card-reaction-tool-wireframe>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Assigned to me filter—filter comments assigned to the current user using the new filter option in the comment sidebar minimal filter dropdown.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      import { VeltCommentsSidebarWireframe } from '@veltdev/react';

      <VeltCommentsSidebarWireframe.MinimalFilterDropdown.Content>
        <VeltCommentsSidebarWireframe.MinimalFilterDropdown.Content.FilterAssignedToMe />
      </VeltCommentsSidebarWireframe.MinimalFilterDropdown.Content>
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments-sidebar-minimal-filter-dropdown-content-filter-assigned-to-me-wireframe>
      </velt-comments-sidebar-minimal-filter-dropdown-content-filter-assigned-to-me-wireframe>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Batched per-document comment counts—added `batchedPerDocument` and `debounceMs` properties to `CommentRequestQuery`. This feature was documented in v5.0.0-beta.10 and has been backported to v4.x.
</Update>

<Update label="4.7.5" description="January 30, 2026">
  ### Bug Fixes

  * \[**Comments**]: Fixed `COMPOSER_TEXT_CHANGE` event not triggering when content is pasted into the composer.
</Update>

<Update label="4.7.4" description="January 30, 2026">
  ### New Features

  * \[**Comments**]: Renamed `targetElementId` prop to `targetComposerElementId` on `VeltCommentComposer`.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Before
      <VeltCommentComposer targetElementId="my-composer" />

      // After
      <VeltCommentComposer targetComposerElementId="my-composer" />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <!-- Before -->
      <velt-comment-composer target-element-id="my-composer"></velt-comment-composer>

      <!-- After -->
      <velt-comment-composer target-composer-element-id="my-composer"></velt-comment-composer>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Changed `submitComment()` to accept request object instead of plain string. Update calls from `submitComment(targetElementId)` to `submitComment({ targetComposerElementId })`.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Before
      const commentElement = client.getCommentElement();
      commentElement.submitComment('my-composer');

      // After
      const commentElement = client.getCommentElement();
      commentElement.submitComment({ targetComposerElementId: 'my-composer' });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      // Before
      const commentElement = Velt.getCommentElement();
      commentElement.submitComment('my-composer');

      // After
      const commentElement = Velt.getCommentElement();
      commentElement.submitComment({ targetComposerElementId: 'my-composer' });
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `clearComposer()` method to reset composer state including text, attachments, recordings, tagged users, assignments, and custom lists.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      const commentElement = client.getCommentElement();
      commentElement.clearComposer({ targetComposerElementId: 'my-composer' });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const commentElement = Velt.getCommentElement();
      commentElement.clearComposer({ targetComposerElementId: 'my-composer' });
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `getComposerData()` method to fetch current composer state on-demand. Returns the same data structure as the `COMPOSER_TEXT_CHANGE` event.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      const commentElement = client.getCommentElement();
      const composerData = commentElement.getComposerData({
        targetComposerElementId: 'my-composer'
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const commentElement = Velt.getCommentElement();
      const composerData = commentElement.getComposerData({
        targetComposerElementId: 'my-composer'
      });
      </script>
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Comments**]: Enhanced `composerTextChange` event to include full draft `annotation` object and `targetComposerElementId`. Access attachments, recordings, tagged users, and other composer state in real-time.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      import { useCommentEventCallback } from '@veltdev/react';
      import { useEffect } from 'react';

      const composerTextChangeEvent = useCommentEventCallback('composerTextChange');

      useEffect(() => {
        if (composerTextChangeEvent) {
          console.log('Text:', composerTextChangeEvent.text);
          console.log('Annotation:', composerTextChangeEvent.annotation);
          console.log('Composer ID:', composerTextChangeEvent.targetComposerElementId);
        }
      }, [composerTextChangeEvent]);

      // Using API methods
      const commentElement = client.getCommentElement();
      commentElement.on('composerTextChange').subscribe((event) => {
        console.log('composerTextChange event:', event);
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const commentElement = Velt.getCommentElement();
      commentElement.on('composerTextChange').subscribe((event) => {
        console.log('Text:', event.text);
        console.log('Annotation:', event.annotation);
        console.log('Composer ID:', event.targetComposerElementId);
      });
      </script>
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.7.3" description="January 29, 2026">
  ### New Features

  * \[**Comments**]: Added `submitComment()` method to programmatically trigger comment submission. Trigger submission from custom buttons or keyboard shortcuts instead of relying on the built-in submit button.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      <VeltCommentComposer targetElementId="composer-1" />

      // Using API methods
      const commentElement = client.getCommentElement();
      commentElement.submitComment('composer-1');
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comment-composer target-element-id="composer-1"></velt-comment-composer>

      <button onclick="submitComment('composer-1')">Send</button>

      <script>
      function submitComment(targetElementId) {
        const commentElement = Velt.getCommentElement();
        commentElement.submitComment(targetElementId);
      }
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `placeholder` prop to comment composer. Customize placeholder text to match your application context.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltCommentComposer placeholder="Share your feedback..." />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comment-composer placeholder="Share your feedback..."></velt-comment-composer>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `composerTextChange` event to track text changes in comment composers. Track input for features like auto-save, character counters, or real-time validation.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      import { useCommentEventCallback } from '@veltdev/react';
      import { useEffect } from 'react';

      const composerTextChangeEvent = useCommentEventCallback('composerTextChange');

      useEffect(() => {
          if (composerTextChangeEvent) {
              console.log('composerTextChange: ', composerTextChangeEvent);
          }
      }, [composerTextChangeEvent]);

      // Using API methods
      const commentElement = client.getCommentElement();

      commentElement.on('composerTextChange').subscribe((event) => {
          console.log('Text changed:', event.text);
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const commentElement = Velt.getCommentElement();

      commentElement.on('composerTextChange').subscribe((event) => {
          console.log('Text changed:', event.text);
      });
      </script>
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.7.1" description="January 21, 2026">
  ### Bug Fixes

  * \[**Comments**]: Fixed context issue for manual comment pins. Ensures manual comment pins display correctly across all integrations.
</Update>

<Update label="4.7.1-beta.7" description="January 20, 2026">
  ### Bug Fixes

  * \[**Self-hosting**]: Fixed attachment metadata issue where `organizationId` was missing. Improves debugging for self-hosted attachment handling.
</Update>

<Update label="4.7.1-beta.6" description="January 20, 2026">
  ### Improvements

  * \[**Core**]: Improved mutation observer element detection logic to skip animation-related elements. Prevents performance slowdowns caused by continuous animations.

  * \[**Comments**]: Optimized read status handling to skip marking already-read comment annotations as read again.

  ### Bug Fixes

  * \[**Comments**]: Fixed bottom sheet not closing properly after deleting a comment annotation.
</Update>

<Update label="4.7.1-beta.5" description="January 16, 2026">
  ### New Features

  * \[**Self-hosting**]: Added attachment resolver support for config-based endpoints. Configure `saveConfig` and `deleteConfig` URLs for file uploads and deletions. [Learn more](/self-host-data/attachments)

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using VeltProvider
      <VeltProvider
        apiKey="YOUR_API_KEY"
        dataProviders={{
          attachment: {
            config: {
              saveConfig: {
                url: '/api/attachments/save',
                headers: {
                  'Authorization': 'Bearer <token>'
                  // Note: Content-Type is automatically set by browser
                }
              },
              deleteConfig: {
                url: '/api/attachments/delete',
                headers: {
                  'Content-Type': 'application/json'
                }
              }
            }
          }
        }}>
        {/* Your app content */}
      </VeltProvider>

      // Using API method
      const client = useVeltClient();
      client.setDataProviders({
        attachment: {
          config: {
            saveConfig: {
              url: '/api/attachments/save',
              headers: {
                'Authorization': 'Bearer <token>'
              }
            },
            deleteConfig: {
              url: '/api/attachments/delete',
              headers: {
                'Content-Type': 'application/json'
              }
            }
          }
        }
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      Velt.setDataProviders({
        attachment: {
          config: {
            saveConfig: {
              url: '/api/attachments/save',
              headers: {
                'Authorization': 'Bearer <token>'
              }
            },
            deleteConfig: {
              url: '/api/attachments/delete',
              headers: {
                'Content-Type': 'application/json'
              }
            }
          }
        }
      });
      ```
    </Tab>
  </Tabs>

  **File Upload Format:**

  When using `saveConfig`, file uploads use `multipart/form-data`:

  ```typescript theme={null}
  // Request
  Method: POST
  Content-Type: multipart/form-data (set by browser)

  // Form fields:
  {
    file: File,              // Binary file object
    request: {               // JSON string
      "attachment": {
        "attachmentId": number,
        "name": string,
        "mimeType": string
      },
      "metadata": { ... },
      "event": string         // Optional
    }
  }

  // Response format:
  {
    data: {
      url: string            // URL of uploaded attachment
    },
    success: true,
    statusCode: 200
  }
  ```

  **Backward Compatibility:**

  * Existing custom `save()` and `delete()` methods continue to work
  * If `saveConfig` or `deleteConfig` are not provided, the resolver falls back to provider methods
  * No breaking changes to existing implementations

  ### Bug Fixes

  * \[**Notifications**]: Fixed notification loading issue that affected rendering.

  * \[**Comments**]: Fixed read status not updating when comment dialog opened in bottom sheet.
</Update>

<Update label="4.7.1-beta.4" description="January 15, 2026">
  ### New Features

  * \[**CRDT**]: Added [Get CRDT Data](/api-reference/rest-apis/v2/crdt/get-crdt-data) REST API to retrieve editor data. Fetch all editors in a document or target a specific editor by ID. [Learn more](/realtime-collaboration/crdt/setup/core#backend-rest-apis)

  * \[**Self-hosting**]: New Config-Based DataProviders: We've reduced self-hosting implementation overhead by **90%**.
    * **Frontend**: Simply configure your URLs and headers; the SDK handles the requests automatically.
    * **Backend**: Use the new [**Velt Python SDK**](https://pypi.org/project/velt-py) to pass your DB and storage configs. You can now pass the raw request object directly to the SDK methods and return the resulting response object straight to the client—no manual processing required.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using VeltProvider
      <VeltProvider
        apiKey="YOUR_API_KEY"
        dataProviders={{
          comment: {
            config: {
              resolveTimeout: 20000,
              saveRetryConfig: {
                retryCount: 3,
                retryDelay: 2000
              },
              getConfig: {
                url: '/api/comments/get',
                headers: {
                  'Authorization': 'Bearer your-token'
                }
              },
              saveConfig: {
                url: '/api/comments/save',
                headers: {
                  'Authorization': 'Bearer your-token'
                }
              },
              deleteConfig: {
                url: '/api/comments/delete',
                headers: {
                  'Authorization': 'Bearer your-token'
                }
              }
            }
            // get, save, delete methods are optional when configs are provided
          }
        }}>
        {/* Your app content */}
      </VeltProvider>

      // Using API method
      const client = useVeltClient();
      client.setDataProviders({
        reaction: {
          config: {
            resolveTimeout: 2000,
            getConfig: {
              url: '/api/reactions/get',
              headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer your-token'
              }
            },
            saveConfig: {
              url: '/api/reactions/save'
              // headers default to Content-Type: application/json
            },
            deleteConfig: {
              url: '/api/reactions/delete'
            }
          }
        }
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      Velt.setDataProviders({
        comment: {
          config: {
            resolveTimeout: 20000,
            saveRetryConfig: {
              retryCount: 3,
              retryDelay: 2000
            },
            getConfig: {
              url: '/api/comments/get',
              headers: {
                'Authorization': 'Bearer your-token'
              }
            },
            saveConfig: {
              url: '/api/comments/save',
              headers: {
                'Authorization': 'Bearer your-token'
              }
            },
            deleteConfig: {
              url: '/api/comments/delete',
              headers: {
                'Authorization': 'Bearer your-token'
              }
            }
          }
          // get, save, delete methods are optional when configs are provided
        }
      });

      Velt.setDataProviders({
        user: {
          config: {
            resolveUsersConfig: {
              organization: false,
              folder: false,
              document: true
            },
            getConfig: {
              url: '/api/users/get',
              headers: {
                'Authorization': 'Bearer your-token'
              }
            }
          }
          // get method is optional when getConfig is provided
        }
      });
      ```
    </Tab>
  </Tabs>

  **Backward Compatibility:**

  * Fully backward compatible - existing implementations continue working unchanged
  * Custom `get`, `save`, `delete` methods remain supported
  * Configs are optional - if not provided, SDK uses provider methods
  * User resolver's `get` method supports both old and new response formats

  **Notes:**

  * All requests use POST method with JSON body
  * Response format automatically handled by SDK
  * Retry logic (if configured) applies to config-based requests

  ### Improvements

  * \[**Notifications**]: Added dropdown layout option for notification settings. Choose between accordion or dropdown layouts.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltNotificationsTool settingsLayout="dropdown" />
      <VeltNotificationsPanel settingsLayout="dropdown" />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-notifications-tool settings-layout="dropdown"></velt-notifications-tool>
      <velt-notifications-panel settings-layout="dropdown"></velt-notifications-panel>
      ```
    </Tab>
  </Tabs>

  **Type:**

  ```typescript theme={null}
  settingsLayout: 'accordion' | 'dropdown' // Default: 'accordion'
  ```

  ### Bug Fixes

  * \[**Comments**]: Fixed comment dialog not changing read status in bottom sheet. Dialog now updates read status when opened.
</Update>

<Update label="4.7.1-beta.2" description="January 13, 2026">
  ### Improvements

  * \[**Comments**]: Added `commentPlaceholder`, `replyPlaceholder`, and `composerPlaceholder` props to inline comments section. Customize placeholder text for different input fields.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltInlineCommentsSection
        commentPlaceholder="ABC Placeholder"
        replyPlaceholder="ABC Reply Placeholder"
        composerPlaceholder="ABC Composer Placeholder"
      />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-inline-comments-section
        comment-placeholder="ABC Placeholder"
        reply-placeholder="ABC Reply Placeholder"
        composer-placeholder="ABC Composer Placeholder"
      ></velt-inline-comments-section>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `commentPlaceholder`, `replyPlaceholder`, and `pageModePlaceholder` props to sidebar. Customize placeholder text for sidebar input fields.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltCommentsSidebar
        commentPlaceholder="XYZ Placeholder"
        replyPlaceholder="XYZ Reply Placeholder"
        pageModePlaceholder="XYZ Page Mode Placeholder"
      />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments-sidebar
        comment-placeholder="XYZ Placeholder"
        reply-placeholder="XYZ Reply Placeholder"
        page-mode-placeholder="XYZ Page Mode Placeholder"
      ></velt-comments-sidebar>
      ```
    </Tab>
  </Tabs>

  * \[**Core**]: Previous document now set on organization change. When `identify()` is called, the previous document is set unless `setDocuments()` is explicitly called.

  ### Bug Fixes

  * \[**Comments**]: Fixed sidebar opening with previously selected inline comment annotation. Sidebar now opens in fresh state.

  * \[**Notifications**]: Fixed notification messages not rendering. Messages now display correctly.
</Update>

<Update label="4.7.1-beta.1" description="January 12, 2026">
  ### New Features

  * \[**Comments**]: Added `autoCompleteScrollConfig` to customize virtual scroll behavior in autocomplete. Configure scroll parameters like item size and buffer pixels.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltComments
        autoCompleteScrollConfig={{
          itemSize: 28,
          minBufferPx: 100,
          maxBufferPx: 200,
          templateCacheSize: 20
        }}
      />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments
        autocomplete-scrollconfig='{
          "itemSize": 28,
          "minBufferPx": 100,
          "maxBufferPx": 200,
          "templateCacheSize": 20
        }'
      ></velt-comments>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `forceClose`, `sortOrder`, `sortBy`, and `defaultMinimalFilter` props to sidebar. Control sidebar behavior and default filtering options.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltCommentsSidebar
        sortOrder="asc"
        sortBy="createdAt"
        defaultMinimalFilter="reset"
        forceClose={true}
      />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments-sidebar
        sort-order="asc"
        sort-by="createdAt"
        default-minimal-filter="reset"
        force-close="true"
      ></velt-comments-sidebar>
      ```
    </Tab>
  </Tabs>

  * \[**Notifications**]: Added `pageSize` prop to control initial notification load count in NotificationPanel and NotificationTool.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltNotificationsPanel pageSize={5} />
      <VeltNotificationsTool pageSize={5} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-notifications-panel page-size="5"></velt-notifications-panel>
      <velt-notifications-tool page-size="5"></velt-notifications-tool>
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Comments**]: Added `elementId` support in `/v2/commentannotations/add` REST API. Pass `elementId` in `targetElement` to define text search boundaries for text comments.

  ```json theme={null}
  {
    "data": {
      "organizationId": "yourOrganizationId",
      "documentId": "yourDocumentId",
      "commentAnnotations": [
        {
          "targetElement": {
            "elementId": "yourElementId",
            "targetText": "Your Target Text",
            "occurrence": 1
          },
          "commentData": [
            {
              "commentText": "Sample Comment",
              "commentHtml": "<div>Sample Comment</div>",
              "from": {
                "userId": "yourUserId",
                "name": "yourUserName",
                "email": "yourUserEmail"
              }
            }
          ]
        }
      ]
    }
  }
  ```

  * \[**Comments**]: Context data now passed from sidebar and inline views to dialog. Access context in `velt-if` and `velt-data` directives.

  * \[**Notifications**]: Truncated long notification text to 3 lines to prevent layout issues.

  * \[**Notifications**]: Added `velt-confirm-dialog-overlay-pane` class to confirm dialog overlay for targeted styling.

  ### Bug Fixes

  * \[**Comments**]: Fixed script tag content being included in text search for highlighting. Text comments now ignore script content during search.

  * \[**Comments**]: Fixed tooltip visibility in sidebar due to z-index conflict.

  * \[**Comments**]: Fixed autocomplete chip height issue. Added `display: block` to prevent scroll issues in thread cards.

  * \[**Comments**]: Fixed edit mode not persisting when switching to focused thread mode. Edit state now maintained correctly.

  * \[**Notifications**]: Fixed `velt-notifications-panel-settings-wireframe` mapping that was incorrectly configured.
</Update>

<Update label="4.7.0" description="January 7, 2026">
  ### Improvements

  * \[**Access Control**]: Added `context` field in document type during `setNotifications` call in PermissionProvider. Provides additional context data for better debugging.

  * \[**CRDT**]: Added CRDT data in Velt Console Data tab. Helps with debugging and reviewing data in the CRDT store for improved developer visibility.
</Update>

<Update label="4.7.0-beta.3" description="January 6, 2026">
  ### Improvements

  * \[**Access Control**]: Added polyfill for `Promise.allSettled`. Ensures compatibility when external dependencies override native implementations.

  * \[**Access Control**]: Fixed response payload for `resourceAccessResultFromCache` in Provider. Now follows the same payload pattern as other methods for better debugging.
</Update>

<Update label="4.7.0-beta.2" description="January 5, 2026">
  ### Bug Fixes

  * \[**Comments**]: Fixed a minor bug related to adding comments in focused mode.
</Update>

<Update label="4.7.0-beta.1" description="January 5, 2026">
  ### New Features

  * \[**Comments**]: Added context, locationId, documentId, and folderId props to standalone Composer component. Pass organizational identifiers directly to the composer.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltCommentComposer context={{ key: 'value' }} />
      <VeltCommentComposer documentId='YOUR_DOCUMENT_ID' />
      <VeltCommentComposer folderId='YOUR_FOLDER_ID' />
      <VeltCommentComposer locationId='YOUR_LOCATION_ID' />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comment-composer context='{"key": "value"}'></velt-comment-composer>
      <velt-comment-composer document-id='YOUR_DOCUMENT_ID'></velt-comment-composer>
      <velt-comment-composer folder-id='YOUR_FOLDER_ID'></velt-comment-composer>
      <velt-comment-composer location-id='YOUR_LOCATION_ID'></velt-comment-composer>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `openAnnotationInFocusMode` config to open comment dialog in focus mode when `focusedThreadMode` is enabled and reply button is clicked or comment is selected via `selectCommentByAnnotationId()`. Requires `focusedThreadMode` to be enabled.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltCommentsSidebar focusedThreadMode={true} openAnnotationInFocusMode={true} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments-sidebar focused-thread-mode="true" open-annotation-in-focus-mode="true"></velt-comments-sidebar>
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Self-hosting**]: Added `moduleName` to resolver `on()` method for improved debugging. Identifies which module triggered the resolver call.

  ```typescript theme={null}
  export enum UserResolverModuleName {
    IDENTIFY = 'identify/authProvider',
    GET_TEMPORARY_USERS = 'getTemporaryUsers',
    GET_USERS = 'getUsers',
    GET_HUDDLE_USERS = 'getHuddleUsers',
    GET_SINGLE_EDITOR_USERS = 'getSingleEditorUsers',
  }

  export enum CommentResolverModuleName {
    SET_DOCUMENTS = 'setDocuments',
    GET_COMMENT_ANNOTATIONS = 'getCommentAnnotations',
    GET_NOTIFICATIONS = 'getNotifications',
  }

  export enum ReactionResolverModuleName {
    SET_DOCUMENTS = 'setDocuments',
    GET_REACTION_ANNOTATIONS = 'getReactionAnnotations',
  }
  ```

  ### Bug Fixes

  * \[**Comments**]: Fixed inline comments not marking as read when clicked.

  * \[**Comments**]: Fixed focused annotation not clearing when sidebar is closed.

  * \[**Notifications**]: Fixed empty state display issue.
</Update>

<Update label="4.6.10" description="December 25, 2025">
  ### New Features

  * \[**Comments**]: Added mark as read/unread option in comment dialog. You can now toggle read status for individual comments. [See wireframe customization →](/ui-customization/features/async/comments/comment-dialog-components#optionscontentmarkasread)

  * \[**Comments**]: Added `unread` property to annotations. You can now check if an annotation is unread by the current user. See [`CommentAnnotation` data model](/api-reference/sdk/models/data-models#commentannotation).

  * \[**Comments**]: Added Open and Reset filters to sidebar minimal filter dropdown. Filter annotations by open status or clear all active filters. [See wireframe customization →](/ui-customization/features/async/comments/comment-sidebar-components#minimalfilterdropdowncontent)

  * \[**Comments**]: Added `context` prop to comment sidebar. Pass context data to page mode composer comments.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltCommentsSidebar
        context={{ jobId: 'job-page-mode', jobStatus: 'page comment' }}
      />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments-sidebar></velt-comments-sidebar>

      <script>
      const commentSidebarElement = document.querySelector('velt-comments-sidebar');
      const context = { jobId: 'job-page-mode', jobStatus: 'page comment' };
      commentSidebarElement?.setAttribute('context', JSON.stringify(context));
      </script>
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Comments**]: Added `velt-comment-dialog--read-only` class to comment dialogs. Style read-only comment dialogs with custom CSS.

  * \[**Comments**]: Added `velt-comment-sidebar-minimal-filter-content-item--selected` class to selected filter items. Style selected filter items in sidebar minimal view.

  * \[**Comments**]: Minimal actions and filter dropdowns now close automatically when an item is selected.

  ### Bug Fixes

  * \[**Comments**]: Fixed sidebar button showing "..." instead of "0" when document has no comments. Unread count now displays correctly.
</Update>

<Update label="4.6.9" description="December 24, 2025">
  ### New Features

  * \[**CRDT**]: Added webhook support for CRDT data changes. Webhooks are disabled by default. When enabled, the default debounce time is 5 seconds. Control webhook behavior using `enableWebhook()`, `disableWebhook()`, and `setWebhookDebounceTime()` methods. [See documentation →](/realtime-collaboration/crdt/setup/core#webhooks)

  * \[**CRDT**]: Added `updateData` event subscription to listen for CRDT data changes. Subscribe using the `on()` method to receive real-time notifications when CRDT data is modified. [See documentation →](/realtime-collaboration/crdt/setup/core#on)

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      import { useCrdtUtils, useCrdtEventCallback } from "@veltdev/react";

      export function YourComponent() {
        const crdtUtils = useCrdtUtils();

        useEffect(() => {
          if (crdtUtils) {
            // Enable webhook
            crdtUtils.enableWebhook();

            // Optional: Change webhook debounce time (minimum 5 seconds)
            crdtUtils.setWebhookDebounceTime(10 * 1000); // 10 seconds
          }
        }, [crdtUtils]);

        // Subscribe to updateData event
        const crdtUpdateData = useCrdtEventCallback("updateData");

        useEffect(() => {
          console.log("[CRDT] event on data change: ", crdtUpdateData);
        }, [crdtUpdateData]);

        return <div>Your Component</div>;
      }
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const crdtElement = Velt.getCrdtElement();

      // Enable webhook
      crdtElement.enableWebhook();

      // Optional: Change webhook debounce time (minimum 5 seconds)
      crdtElement.setWebhookDebounceTime(10 * 1000); // 10 seconds

      // Subscribe to updateData event
      crdtElement.on("updateData").subscribe((eventData) => {
        console.log("[CRDT] event on data change: ", eventData);
      });
      </script>
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.6.8" description="December 23, 2025">
  ### Improvements

  * \[**Access Control**]: Added context information to permission provider requests when `setDocuments` is called. The context set during `setDocuments` is now included in resource access requests.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using API methods
      client.setDocuments([{
        documentId: 'document1',
        context: {
          access: {
            code: [1, 2]
          }
        }
      }]);

      // Permission provider will receive context in request payload
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      Velt.setDocuments([{
        documentId: 'document1',
        context: {
          access: {
            code: [1, 2]
          }
        }
      }]);

      // Permission provider will receive context in request payload
      </script>
      ```
    </Tab>
  </Tabs>

  ```json theme={null}
  {
    "event": "resourceAccessRequestFormed",
    "methodName": "setDocuments",
    "uniqueId": "qaDuR1t4qN35xZ2lHTp0",
    "timestamp": 1766506430306,
    "source": "internal",
    "payload": {
      "requests": [
        {
          "userId": "user123",
          "resource": {
            "id": "document1",
            "type": "document",
            "source": "setDocuments",
            "organizationId": "org1",
            "context": {
              "access": {
                "code": [1, 2]
              }
            }
          }
        },
        {
          "userId": "user123",
          "resource": {
            "id": "{\"code\":1}",
            "type": "context",
            "source": "setDocuments",
            "organizationId": "org1",
            "context": {
              "access": {
                "code": 1
              }
            }
          }
        },
        {
          "userId": "user123",
          "resource": {
            "id": "{\"code\":2}",
            "type": "context",
            "source": "setDocuments",
            "organizationId": "org1",
            "context": {
              "access": {
                "code": 2
              }
            }
          }
        }
      ]
    }
  }
  ```

  * \[**Access Control**]: Added context access information to `getUserPermissions` API response. Returns `accessFields` array showing which context values the user has access to.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using API methods
      const request = {
        organizationId: 'org1',
        documentIds: ['document1']
      };

      const response = await client.getUserPermissions(request);

      // Response includes context access info at the user level
      console.log(response.result.data['user_123'].context.accessFields); // ['code:1', 'code:2', 'code:3']
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const request = {
        organizationId: 'org1',
        documentIds: ['document1']
      };

      const response = await Velt.getUserPermissions(request);

      // Response includes context access info at the user level
      console.log(response.result.data['user_123'].context.accessFields); // ['code:1', 'code:2', 'code:3']
      </script>
      ```
    </Tab>
  </Tabs>

  ```json theme={null}
  {
    "result": {
      "status": "success",
      "message": "User permissions retrieved successfully.",
      "data": {
        "user_123": {
          "documents": {
            "document1": {
              "accessRole": "editor"
            }
          },
          "organization": {
            "org1": {
              "accessRole": "editor"
            }
          },
          "context": {
            "accessFields": ["code:1", "code:2", "code:3"]
          }
        }
      }
    }
  }
  ```

  ### Bug Fixes

  * \[**Core**]: Fixed document metadata not being saved during `setDocuments`. Metadata details are now correctly persisted to the database.
</Update>

<Update label="4.6.7" description="December 22, 2025">
  ### Improvements

  * \[**Comments**]: Added paginated contact list to limit user downloads. Significantly reduces data transfer for apps with thousands of users.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Props
      <VeltComments paginatedContactList={true} />

      // Using API methods
      const commentElement = client.getCommentElement();

      // Enable
      commentElement.enablePaginatedContactList();

      // Disable
      commentElement.disablePaginatedContactList();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <!-- Using HTML Attribute -->
      <velt-comments paginated-contact-list="true"></velt-comments>

      <script>
      // Using API methods
      const commentElement = Velt.getCommentElement();

      // Enable
      commentElement.enablePaginatedContactList();

      // Disable
      commentElement.disablePaginatedContactList();
      </script>
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.6.7-beta.1" description="December 19, 2025">
  ### New Features

  * \[**Live Selection**]: Added `setInactivityTime()` to configure inactivity duration before removing stale live selections. Default is 5 minutes.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      import { useLiveSelectionUtils } from '@veltdev/react';

      const selectionUtils = useLiveSelectionUtils();
      const tenMinutesInMs = 10 * 60 * 1000;
      selectionUtils.setInactivityTime(tenMinutesInMs);

      // Using API methods
      const selectionElement = client.getSelectionElement();
      const tenMinutesInMs = 10 * 60 * 1000;
      selectionElement.setInactivityTime(tenMinutesInMs);
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const selectionElement = Velt.getSelectionElement();
      const tenMinutesInMs = 10 * 60 * 1000;
      selectionElement.setInactivityTime(tenMinutesInMs);
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `commentCountType` prop to control which count displays in sidebar buttons. Choose between total or unread comment counts.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltSidebarButton commentCountType="unread" />
      <VeltSidebarButton commentCountType="total" />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-sidebar-button comment-count-type="unread"></velt-sidebar-button>
      <velt-sidebar-button comment-count-type="total"></velt-sidebar-button>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `openDialog` prop to comment bubbles. Set to `false` to prevent dialog from opening when bubble is clicked.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltCommentBubble openDialog={false} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comment-bubble open-dialog="false"></velt-comment-bubble>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `commentBubbleClickedEvent` to detect comment bubble interactions.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      import { useCommentEventCallback } from '@veltdev/react';
      import { useEffect } from 'react';

      const commentBubbleClickedEvent = useCommentEventCallback('commentBubbleClicked');

      useEffect(() => {
          if (commentBubbleClickedEvent) {
              console.log('commentBubbleClicked: ', commentBubbleClickedEvent);
          }
      }, [commentBubbleClickedEvent]);

      // Using API methods
      const commentElement = client.getCommentElement();

      commentElement.on('commentBubbleClicked').subscribe((eventData) => {
          console.log('Comment bubble clicked:', eventData);
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const commentElement = Velt.getCommentElement();

      commentElement.on('commentBubbleClicked').subscribe((eventData) => {
          console.log('Comment bubble clicked:', eventData);
      });
      </script>
      ```
    </Tab>
  </Tabs>

  ```typescript theme={null}
  export interface CommentBubbleClickedEvent {
      annotationId: string;
      commentAnnotation: CommentAnnotation;
      metadata?: VeltEventMetadata;
  }
  ```

  * \[**UI Customization**]: Added unread icon wireframes to sidebar buttons and comment bubbles. Display custom unread indicators for unread comments. [See sidebar button wireframes →](/ui-customization/features/async/comments/comment-sidebar-button#unreadicon) [See comment bubble wireframes →](/ui-customization/features/async/comments/comment-bubble#unreadicon)
</Update>

<Update label="4.6.6" description="December 18, 2025">
  ### New Features

  * \[**Core**]: Added `getCurrentUserPermissions` API to subscribe to current user permissions. Useful for debugging and developer tools integration.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Subscribe to current user permissions
      const subscription = client.getCurrentUserPermissions().subscribe((permissions) => {
        console.log('Current user permissions:', permissions);
        // permissions structure matches getUserPermissions response format
      });

      // Unsubscribe when done
      subscription.unsubscribe();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      // Subscribe to current user permissions
      const subscription = Velt.getCurrentUserPermissions().subscribe((permissions) => {
        console.log('Current user permissions:', permissions);
        // permissions structure matches getUserPermissions response format
      });

      // Unsubscribe when done
      subscription.unsubscribe();
      </script>
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Core**]: Added context access info to `getUserPermissions` and `getCurrentUserPermissions` APIs for enhanced debugging capabilities.

  * \[**Core**]: Added context field from `setDocuments` to `fetchDebugInfo` method for improved debugging support.
</Update>

<Update label="4.6.6-beta.1" description="December 17, 2025">
  ### Improvements

  * \[**Comments**]: Improved robust XPath detection logic when resolving elements through comment anchors. Anchoring now supports more scenarios for detecting target elements when adding comments.

  ### Bug Fixes

  * \[**Comments**]: Fixed shadow DOM error in Comment Player Timeline where a variable was accessing an undefined component instance.

  * \[**Comments**]: Fixed `data-velt-comment-pin-active` attribute being incorrectly removed when a dialog was still selected in the host element. The attribute now correctly reflects the active state across all annotations in the host.

  * \[**Comments**]: Fixed reset filter in multi-thread comments not showing resolved comments. The reset button now clears all filters and displays all annotations including resolved ones.
</Update>

<Update label="4.6.5" description="December 16, 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed race condition in `addContext` where user context was being overwritten. Added internal timeout to ensure user context is properly applied alongside the default access context.
</Update>

<Update label="4.6.5-beta.2" description="December 15, 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed Comment Bubble closing unexpectedly after adding the first comment. The bubble now remains open as expected.

  * \[**Comments**]: Fixed draft comment annotations not being created. Users can now add draft comment annotations again.
</Update>

<Update label="4.6.5-beta.1" description="December 14, 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed `contextId` generation in comment annotations. Context filtering now works correctly with exact matches in Comment Tool and Comment Bubble components.
</Update>

<Update label="4.6.4" description="December 12, 2025">
  ### Improvements

  * \[**Core**]: Added batching for internal service calls. Reduces network calls by 90%.
  * \[**Comments**]: Refactored `@veltdev/tiptap-velt-comments` and `@veltdev/lexical-velt-comments` to follow a common pattern and folder structure across all libraries. This enables faster development of Velt comment integrations and covers more rich text editor scenarios.
</Update>

<Update label="4.6.3" description="December 12, 2025">
  ### Improvements

  * \[**Comments**]: Added `expandOnSelection` prop to Comments Sidebar. Control whether dialogs expand when selected in the sidebar.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltCommentsSidebar expandOnSelection={false} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments-sidebar expand-on-selection="false"></velt-comments-sidebar>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added event subscription support for data providers via the `Velt.on` method. You can now monitor and debug data provider operations (get, save, delete) using the same event-based debugging pattern available for permission providers.

  ### Bug Fixes

  * \[**Comments**]: Added pin click event support for Standalone Comment Pin Component (VeltCommentPin). Click events now work consistently across all pin types.
</Update>

<Update label="4.6.2" description="December 10, 2025">
  ### Improvements

  * \[**Comments**]: Reply counts now display in read-only mode. Previously hidden, you can now see the number of replies on each comment when viewing in read-only state.

  * \[**Comments**]: Added `dialogSelection` prop to disable dialog selection in sidebar. Control whether users can select comment dialogs in the sidebar.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltCommentsSidebar dialogSelection={false} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments-sidebar dialog-selection="false"></velt-comments-sidebar>
      ```
    </Tab>
  </Tabs>

  * \[**Core**]: Added `throwError` config to `identify()` and auth provider methods. Set `throwError: true` to receive errors instead of null when authentication fails. Default is `false`.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      import { useIdentify } from '@veltdev/react';

      // Using API methods
      // Promise-based
      client.identify(user, {
        throwError: true,
      }).then((user) => {
        // user is authenticated
      }).catch((err) => {
        // handle error
      });

      // Async/await
      try {
        const user = await client.identify(user, {
          throwError: true,
        });
      } catch (err) {
        // handle error
      }

      // Using setVeltAuthProvider
      client.setVeltAuthProvider({
        user,
        options: {
          throwError: true,
        },
        onError: (err) => {
          // handle error
        }
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      // Promise-based
      Velt.identify(user, {
        throwError: true,
      }).then((user) => {
        // user is authenticated
      }).catch((err) => {
        // handle error
      });

      // Async/await
      try {
        const user = await Velt.identify(user, {
          throwError: true,
        });
      } catch (err) {
        // handle error
      }

      // Using setVeltAuthProvider
      Velt.setVeltAuthProvider({
        user,
        options: {
          throwError: true,
        },
        onError: (err) => {
          // handle error
        }
      });
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Core**]: Improved `updateContext()` logic to handle context access scenarios. Context resolution now works correctly regardless of merge settings.
</Update>

<Update label="4.6.1" description="December 9, 2025">
  ### Improvements

  * \[**Core**]: Routine package updates.
</Update>

<Update label="4.6.0" description="December 8, 2025">
  ### Improvements

  * \[**Comments**]: Added `commentPinClicked` event to detect pin interactions. You can now capture click events on comment pins to track user engagement.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      import { useCommentEventCallback } from '@veltdev/react';
      import { useEffect } from 'react';

      const commentPinClickedEvent = useCommentEventCallback('commentPinClicked');

      useEffect(() => {
          if (commentPinClickedEvent) {
              console.log('commentPinClicked: ', commentPinClickedEvent);
          }
      }, [commentPinClickedEvent]);

      // Using API methods
      const commentElement = client.getCommentElement();

      commentElement.on('commentPinClicked')
      .subscribe((eventData) => {
          console.log('Comment pin clicked:', eventData);
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const commentElement = Velt.getCommentElement();

      commentElement.on('commentPinClicked')
      .subscribe((eventData) => {
          console.log('Comment pin clicked:', eventData);
      });
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `readOnly` property to Comments Sidebar. Sidebar comment dialogs can now be set to read-only mode to prevent edits.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltCommentsSidebar readOnly={true} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments-sidebar read-only="true"></velt-comments-sidebar>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Fixed tabindex behavior in all comment components. When a component is hidden or empty, tabindex is now removed to prevent focus on invisible elements.
</Update>

<Update label="4.6.0-beta.7" description="December 5, 2025">
  ### New Features

  * \[**Core**]: Added `getCurrentUser()` method to subscribe to user object changes. You can now detect when the current user's data updates in real-time.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      import { useCurrentUser } from '@veltdev/react';
      import { useEffect } from 'react';

      export function YourComponent() {
        const veltUser = useCurrentUser();

        useEffect(() => {
          console.log("Velt user: ", veltUser);
        }, [veltUser]);
      }

      // Using API methods
      client.getCurrentUser().subscribe((veltUser: User | null) => {
        console.log("Velt user: ", veltUser);
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      Velt.getCurrentUser().subscribe((veltUser) => {
        console.log("Velt user: ", veltUser);
      });
      </script>
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.6.0-beta.6" description="December 4, 2025">
  ### Improvements

  * \[**Comments**]: Added default access context in comments feature. This ensures that all relevant comments are fetched in the query if you are using feature level permissions using access context. [Learn More](https://docs.velt.dev/key-concepts/overview#set-feature-level-permissions-using-access-context-custom-metadata)
</Update>

<Update label="4.6.0-beta.5" description="December 2, 2025">
  ### Improvements

  * \[**Comments**]: Extended private comments feature to support both admin and organization users.
</Update>

<Update label="4.6.0-beta.4" description="November 28, 2025">
  ### Improvements

  * \[**REST APIs**]: Added `verifyUserPermissions` flag to [`Add Comment Annotations`](/api-reference/rest-apis/v2/comments-feature/comment-annotations/add-comment-annotations), [`Add Comments in Comment Annotation`](/api-reference/rest-apis/v2/comments-feature/comments/add-comments), [`Add Notifications`](/api-reference/rest-apis/v2/notifications/add-notifications), and [`Update Notifications`](/api-reference/rest-apis/v2/notifications/update-notifications) REST APIs. When enabled, these operations are only performed for users who have access to the specified document, preventing unauthorized resource creation or updates.

  ### Bug Fixes

  * \[**Core**]: Added missing types and added automated reviews to prevent this in future.
</Update>

<Update label="4.6.0-beta.3" description="November 27, 2025">
  ### Bug Fixes

  * \[**Core**]: Fixed an issue preventing fetching all documents within a folder.
</Update>

<Update label="4.6.0-beta.2" description="November 26, 2025">
  ### Bug Fixes

  * \[**Core**]: Fixed TypeScript types for the Velt `on()` method to display properly in IDE suggestions.

  * \[**Core**]: Added validation in `getUserPermissions()` to check if user is set before proceeding, preventing inconsistencies when user is not present.

  * \[**Core**]: Added memoization to providers in `VeltProviders` to prevent unnecessary re-renders when input values haven't changed.

  * \[**Core**]: Fixed document creation with folder support in the SDK.
</Update>

<Update label="4.6.0-beta.1" description="November 25, 2025">
  ### Bug Fixes

  * \[**Core**]: Fixed race condition in the `identify()` method that prevented user colors from updating correctly.

  * \[**Comments**]: Fixed an issue where text comments data remained stale in case of text editors that could cause data loss when saving annotations.
</Update>

<Update label="4.5.9-beta.4" description="November 25, 2025">
  ### New Features

  * \[**Core**]: Added `getHeartbeat()` method to subscribe to user-specific heartbeat data. You can retrieve heartbeat data for the current user or specify a `userId` to get heartbeats for any user, providing better visibility into active sessions per user.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      import { useHeartbeat } from "@veltdev/react";
      import { useEffect } from "react";

      const { data: heartbeatData } = useHeartbeat();
      useEffect(() => {
        console.log("Heartbeat data: ", heartbeatData);
      }, [heartbeatData]);

      // Using API methods
      client.getHeartbeat().subscribe((heartbeatData) => {
        console.log("Heartbeat data: ", heartbeatData);
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      Velt.getHeartbeat().subscribe((heartbeatData) => {
        console.log("Heartbeat data: ", heartbeatData);
      });
      </script>
      ```
    </Tab>
  </Tabs>

  **Heartbeat Interfaces:**

  ```typescript theme={null}
  export interface HeartbeatConfig {
    userId?: string;
  }

  export interface GetHeartbeatResponse {
    data: Heartbeat[] | null;
  }
  ```

  ### Improvements

  * \[**Comments**]: Added location removal logic when video plays in Timeline Player. Comment pins are now properly removed as the video plays, ensuring accurate timeline visualization.

  * \[**Comments**]: Added change detection in Timeline Player. The timeline bar now moves correctly when hovering over the play button or timeline, ensuring responsive playback controls.

  ### Bug Fixes

  * \[**Core**]: Fixed disconnect errors in the heartbeat feature. The SDK now handles network issues at the client side without triggering server disconnect errors.

  * \[**Core**]: Fixed user color and text color persistence during auto-login. Colors passed during `identify()` now persist correctly in auto-login scenarios, ensuring consistent user identification.

  * \[**Presence**]: Fixed `multipleUsersOnline` event firing when only a single user is present. The presence feature now correctly identifies single-user scenarios, preventing unwanted analytics events.
</Update>

<Update label="4.5.9-beta.3" description="November 19, 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed race condition errors in Player Timeline by adding proper lifecycle management. The player timeline now properly handles component destruction, preventing "undefined" errors that could occur when the component was destroyed during asynchronous operations.

  * \[**Notifications**]: Fixed error handling for document notifications by adding metadata validation. The SDK now checks if notification metadata exists before processing document notifications, preventing unnecessary errors in analytics tracking when notifications are missing required data.
</Update>

<Update label="4.5.9-beta.2" description="November 18, 2025">
  ### Bug Fixes

  * \[**Core**]: Fixed user resolution for tagged and assigned users in contact lists. Users added via `updateContactList()` are now properly cached, ensuring that tagged and assigned users resolve correctly from cached data instead of failing to load.
</Update>

<Update label="4.5.9-beta.1" description="November 18, 2025">
  ### Bug Fixes

  * \[**Core**]: Improved `updateContactList()` method behavior by removing unnecessary validation checks. The method now directly applies user-provided contact list data without additional validation, giving you more control over contact list management.
</Update>

<Update label="4.5.9" description="November 15, 2025">
  ### Bug Fixes

  * \[**Recorder**]: Fixed an issue where zoom was not applied unless the zoom section in the timeline was modified directly.
</Update>

<Update label="4.5.8" description="November 14, 2025">
  ### Bug Fixes

  * \[**Recorder**]: Fixed an issue where the zoom animation in the editor preview had a curve in the transition. The editor preview now displays smooth transitions to the correct coordinates instead of curved transitions.

  * \[**Recorder**]: Fixed an issue where VeltIf was throwing an error when evaluating MediaStream object.

  * \[**Comments**]: Fixed sanitization of `target` attributes in comment HTML content. The DomPurifier now preserves `target` attributes in comment HTML fields, allowing users to include links with target specifications (such as `target="_blank"`) in their comments.
</Update>

<Update label="4.5.8-beta.7" description="November 13, 2025">
  ### Improvements

  * \[**Core**]: Optimized the initialization module and significantly reduced the SDK initialization time.
</Update>

<Update label="4.5.8-beta.6" description="November 10, 2025">
  ### New Features

  * \[**Core**]: Added `fetchDebugInfo()` and `getDebugInfo()` methods to retrieve debugging information about your Velt implementation. Use `fetchDebugInfo()` to get a one-time snapshot or `getDebugInfo()` to subscribe to real-time updates of key setup info like sdk version, apikey, user, organizationId, documentId, folderID version, locations etc. You can also get this info from [Velt’s Chrome devtools](https://chromewebstore.google.com/detail/velt-devtools/nfldoicbagllmegffdapcnohakpamlnl)

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}

      // Using API methods - One-time fetch
      await client.fetchDebugInfo();

      // Using API methods - Subscribe to updates
      client.getDebugInfo().subscribe((debugInfo) => {
        console.log("Debug info: ", debugInfo);
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      // One-time fetch
      const debugInfo = await Velt.fetchDebugInfo();

      // Subscribe to updates
      Velt.getDebugInfo().subscribe((debugInfo) => {
        console.log("Debug info: ", debugInfo);
      });
      </script>
      ```
    </Tab>
  </Tabs>

  **Debug Info Interface:**

  ```typescript theme={null}
  export interface VeltDebugInfo {
    veltVersion?: string;
    apiKey?: string;
    serverMap?: {
      organization?: OrganizationMetadata;
      documents?: DocumentMetadata[];
      locations?: Location[];
      folder?: FolderMetadata;
      user?: User;
    };
    clientMap?: {
      organization?: OrganizationMetadata;
      documents?: DocumentMetadata[];
      locations?: Location[];
      folder?: FolderMetadata;
      user?: User;
    };
  }
  ```

  ### Improvements

  * \[**Access Control**]: Prevent users from adding comments, reactions, recorders, and area comments through the SDK when `access context` is used and the user doesn’t have access to the specific context.
</Update>

<Update label="4.5.8-beta.5" description="November 5, 2025">
  ### New Features

  * \[**Comments**]: Added preliminary infra required to capture screenshots in comments.
</Update>

<Update label="4.5.8-beta.4" description="November 4, 2025">
  ### Improvements

  * \[**Access Control**]: Now you can set feature level permissions using Access Context. Access Context allows you to set granular, feature-level permissions using custom metadata. When configured, new feature data is added and existing feature data is fetched only for the access context values the current user has access to. [Learn more →](/key-concepts/overview#set-feature-level-permissions-using-access-context-custom-metadata)
</Update>

<Update label="4.5.8-beta.3" description="October 30, 2025">
  ### Improvements

  * \[**Recorder**]: Updated video editor timeline picture mode design for improved visual clarity. The unselected portion of timeline pictures now displays with a cleaner design that better distinguishes selected from unselected frames.

  * \[**Recorder**]: Fixed audio merging in screen recording to combine microphone and tab audio. When recording with both microphone and tab audio enabled, both audio sources are now properly merged into the final recording.

  ### Bug Fixes

  * \[**Comments**]: Fixed type definition for `selectCommentByAnnotationId()` and made `annotationId` parameter optional.

  * \[**Comments**]: Fixed embed mode logic in comments sidebar to support multiple embedded sidebars.
</Update>

<Update label="4.5.8-beta.2" description="October 30, 2025">
  ### New Features

  * \[**Access Control**]: Added the new Permission Provider feature. With this approach, Velt pings your defined endpoint to verify whether a user should be granted access to a resource (organization, folder, or document). This ensures that your backend is still the source of truth and you don't have to sync the permissions into Velt directly. [Learn more →](/key-concepts/overview#c-real-time-permission-provider)

  * \[**Access Control**]: Added a config to automatically revoke permissions, including revoking access to documents, folders, and optionally organizations when users log out or when documents are unset. This ensures immediate permission removal without requiring manual cleanup. [Learn more →](/key-concepts/overview#c-real-time-permission-provider)

  * \[**Access Control**]: Added various Permission Provider events to monitor the sequence of permission check events for debugging and tracking purposes. [Learn more →](/api-reference/sdk/models/data-models#permissionproviderevent)

  ### Improvements

  * \[**Access Control**]: Simplified Permission Provider implementation by removing `onResourceAccessRequired` call and signature handling from client SDK. Permission handling is now fully managed internally by the SDK. You no longer need to handle signatures or make `onResourceAccessRequired` calls. The SDK automatically handles permission caching, validation, and synchronization with the backend. [Learn more →](/api-reference/sdk/api/api-methods#setpermissionprovider)
</Update>

<Update label="4.5.8-beta.1" description="October 29, 2025">
  ### New Features

  * \[**Recorder**]: Added video editor timeline image preview to display frame snapshots in the timeline. This helps you quickly navigate to specific scenes without scrubbing through the entire video.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltRecorderNotes videoEditorTimelinePreview={true} />
      <VeltRecorderControlPanel videoEditorTimelinePreview={true} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-recorder-notes video-editor-timeline-preview="true"></velt-recorder-notes>
      <velt-recorder-control-panel video-editor-timeline-preview="true"></velt-recorder-control-panel>
      ```
    </Tab>
  </Tabs>

  <Info>The timeline preview only works when both `videoEditorTimelinePreview` and `videoEditor` are set to `true`.</Info>

  ### Improvements

  * \[**Comments**]: Enhanced `selectCommentByAnnotationId()` to close the selected comment annotation when called with no arguments or an invalid ID.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      const commentElement = useCommentUtils();

      // Close the currently selected annotation
      commentElement.selectCommentByAnnotationId();
      commentElement.selectCommentByAnnotationId('invalid-id');

      // Using API methods
      const commentElement = client.getCommentElement();

      // Close the currently selected annotation
      commentElement.selectCommentByAnnotationId();
      commentElement.selectCommentByAnnotationId('invalid-id');
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const commentElement = Velt.getCommentElement();

      // Close the currently selected annotation
      commentElement.selectCommentByAnnotationId();
      commentElement.selectCommentByAnnotationId('invalid-id');
      </script>
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.5.7" description="October 28, 2025">
  ### New Features

  * \[**Access Control**]: Added early version of feature level permissions using Access Context. Access Context allows you to set granular, feature-level permissions using custom metadata. When configured, new feature data is added and existing feature data is fetched only for the access context values the current user has access to. [Learn more →](/key-concepts/overview#set-feature-level-permissions-using-access-context-custom-metadata)
</Update>

<Update label="4.5.6" description="October 27, 2025">
  ### Improvements

  * \[**Access Control**]: Added `source` field to Permission Provider requests to identify which method triggered the request. The `source` field helps you debug and trace which SDK method initiated the permission check. [Learn more →](/key-concepts/overview#c-real-time-permission-provider)

  * \[**Access Control**]: Added various Permission Provider events to monitor the sequence of permission check events for debugging and tracking purposes. [Learn more →](/api-reference/sdk/models/data-models#permissionproviderevent)

  ### Bug Fixes

  * \[**Notifications**]: Fixed notification fetching with Permission Provider when document IDs needed mapping to client document IDs.
</Update>

<Update label="4.5.6-beta.17" description="October 17, 2025">
  ### New Features

  * \[**Comments**]: Added `markAsRead()` and `markAsUnread()` methods to mark comment annotations as read or unread for the current user.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      const commentElement = useCommentUtils();

      commentElement.markAsUnread("eUgq6G6zXxJmOT9eBXtT");
      commentElement.markAsRead("eUgq6G6zXxJmOT9eBXtT");

      // Using API methods
      const commentElement = client.getCommentElement();

      commentElement.markAsUnread("eUgq6G6zXxJmOT9eBXtT");
      commentElement.markAsRead("eUgq6G6zXxJmOT9eBXtT");
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```jsx theme={null}
      const commentElement = Velt.getCommentElement();

      commentElement.markAsUnread("eUgq6G6zXxJmOT9eBXtT");
      commentElement.markAsRead("eUgq6G6zXxJmOT9eBXtT");
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Recorder**]: Added system sound capture when recording a browser tab.

  * \[**Comments**]: You can now tag users by copy-pasting their email address. Previously, only manually typed emails worked for tagging users not on the contact list.

  * \[**Comments**]: Added `viewedBy` and `reactionAnnotations` fields to comment annotation objects returned via Get Comment Annotations frontend api methods.

    * **`viewedBy`**: An array of User objects representing who has seen and read the comment annotation. Use this to track engagement, identify which stakeholders have reviewed feedback, or build custom read receipt indicators.

    * **`reactionAnnotations`**: An array of complete ReactionAnnotation objects containing the full reaction data for each message inside the thread. Use this to render reactions data (eg: reaction counts, show who reacted with what emoji) in your own components.

  ```typescript theme={null}
  // Comment Annotation Object
  {
      ...
      comments: [
          {
              ...
              reactionAnnotations?: ReactionAnnotation[]; // Complete reaction objects with full details
          }
      ],
      viewedBy?: User[]; // Users who have seen and read this annotation
  }
  ```

  ### Bug Fixes

  * \[**Recorder**]: Fixed an issue in the video editor where the playhead position was ignored after playback ended. When seeking or dragging the playhead after video completion, playback now correctly starts from the new position instead of always starting from the beginning.
</Update>

<Update label="4.5.6-beta.16" description="October 17, 2025">
  ### Improvements

  * \[**Comments**]: Released v2 improved version of comment anchoring that makes comment positioning more dynamic and robust on more dynamic websites. This includes enhanced element detection for pin, text, and area comments, improved cursor display based on DOM element visibility, and better handling of image tag positioning with conditional relative positioning for container elements.
</Update>

<Update label="4.5.6-beta.15" description="October 16, 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where draft comments with resolvers were incorrectly submitted before being finalized, causing data inconsistencies. Draft comments with resolvers now work properly and are only saved when explicitly published.

  * \[**Access Control**]: Fixed an issue where organization access permissions were not being set correctly when using the permission provider. When users logged in, their organization-level permissions were failing to initialize properly. Organization access now gets assigned correctly during the identification process.
</Update>

<Update label="4.5.6-beta.14" description="October 15, 2025">
  ### New Features

  * \[**Notifications**]: Added `triggerNotification` flag to the [Add Comment Annotations REST API](/api-reference/rest-apis/v2/comments-feature/comment-annotations/add-comment-annotations). When enabled, adding comments via the REST API will trigger in-app notifications, email notifications to relevant users and also trigger webhooks matching the SDK’s native notification behavior.

  ### Bug Fixes

  * \[**Notifications**]: Fixed an issue where marking all notifications as read in the SDK was not working correctly.
</Update>

<Update label="4.5.6-beta.13" description="October 14, 2025">
  ### Bug Fixes

  * \[**Notifications**]: Fixed an issue where a notification API was being called twice with the same request.
</Update>

<Update label="4.5.6-beta.12" description="October 14, 2025">
  ### Improvements

  * \[**Notifications**]: In-app notifications and APIs now only create and retrieve notifications for documents the user has access to; notifications for inaccessible documents will no longer be generated or returned (including historical ones)

  * \[**REST APIs**]: Added `verifyUserPermissions` flag to [`Add Notifications`](/api-reference/rest-apis/v2/notifications/add-notifications) and [`Update Notifications`](/api-reference/rest-apis/v2/notifications/update-notifications) REST APIs.
    When enabled, notifications are only created or updated for users who have access to the specified document.
    <Info>Note: If you are using the new `PermissionProvider` then this flag will not work, you will need to do the permissions validation on your end before adding or updating the notification.</Info>
</Update>

<Update label="4.5.6-beta.11" description="October 14, 2025">
  ### Bug Fixes

  * \[**Core**]: Fixed document filtering logic that was incorrectly handling access permissions. Documents are now properly filtered based on user access rights.
</Update>

<Update label="4.5.6-beta.10" description="October 14, 2025">
  ### New Features

  * \[**Access Control**]: Introduced a new **Permission Provider** approach for simpler, centralized access control. Key details:
    * You no longer need to sync users into Velt or call the Permissions API directly.
    * Configure an endpoint that Velt will call to verify user access to resources (organization, folder, or document).
    * When a user logs in or tries to access a resource:
      * Velt sends a request to your configured endpoint with relevant access details.
      * Your endpoint evaluates access, signs the result using Velt's API, and returns the response.
      * Velt validates the signature and updates access permissions accordingly.
    * This creates a single, backend-controlled source of truth for permissions.
    * You can use this approach instead of **user sync** and **on-demand** permission strategies.
    * [Learn more](/key-concepts/overview#c-real-time-permission-provider).

  ### Improvements

  * \[**Access Control**]: Added `maxDepth` parameter to [`Get Folders` REST API](/api-reference/rest-apis/v2/folders/get-folders). You can now retrieve nested subfolders at any depth level. The response includes `ancestors` array showing parent hierarchy and `inheritAccessFromParent` field indicating whether access is inherited.

  * \[**Access Control**]: Added `inheritFromParent` parameter to the [Update Folder Access REST API](/api-reference/rest-apis/v2/folders/update-folder-access). You can now configure a folder to inherit access permissions from its parent folder.

  * \[**Access Control**]: The [Update Folder REST API](/api-reference/rest-apis/v2/folders/update-folder) now handles folder moves correctly. When a folder is moved to a different parent, its `ancestors` array and `accessType` are automatically updated, and all subfolder information is updated accordingly.

  * \[**Access Control**]: Added `accessType` parameter to the [Add Folder REST API](/api-reference/rest-apis/v2/folders/add-folder). You can now set a folder's access permissions during creation.

  * \[**Core**]: The `setDocuments` method now filters out documents the user doesn't have access to instead of failing the entire operation. Previously, if any document in the array was inaccessible, the entire request would fail.

  * \[**Access Control**]: Resources (Organizations, Folders, and Documents) follow a hierarchical permission model. By default, **each resource inherits its access type and user permissions** from its parent. If a resource defines its own access type or user permissions, those **explicit settings override the inherited values**. This precedence applies during both **permission evaluation and access enforcement**.

  * \[**Access Control**]: Folder document limit set to 50 when using `setDocuments` with the `allDocuments` flag. When fetching all documents from a folder, only the first 50 documents are retrieved, and any documents the user doesn't have access to are filtered out.
</Update>

<Update label="4.5.6-beta.9" description="October 10, 2025">
  ### Bug Fixes

  * \[**Live State Sync**]: Fixed `getLiveStateData()` so that with `listenToNewChangesOnly: true`, it now returns only new changes after subscribing—instead of including existing data.
</Update>

<Update label="4.5.6-beta.8" description="October 8, 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where tagged users who don't exist in the database were not displaying correctly in email notifications. Comments now render with the proper format in both the UI and emails.

  * \[**Comments**]: Fixed an issue where user mentions in email notifications were not resolving with correct user details. Tagged users in comments now display properly with accurate information in all email notifications.

  * \[**Comments**]: Fixed an issue where user details were not resolving when a user from a different organization added comments in an accessible document. This previously caused skeleton loading states or fallback formatting for existing organization users, but now displays correctly.
</Update>

<Update label="4.5.6-beta.7" description="October 8, 2025">
  ### New Features

  * \[**Live State Sync**]: Added `fetchLiveStateData()` method to retrieve synced state data. You can fetch all synced data or retrieve data for a specific `liveStateDataId`.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      const liveStateSyncElement = useLiveStateSyncUtils();

      /// To get all the data
      const data = await liveStateSyncElement.fetchLiveStateData();

      /// To get data for specific liveStateDataId
      const specificData = await liveStateSyncElement.fetchLiveStateData({
          liveStateDataId: "LIVE_STATE_DATA_ID"
      });

      // Using API methods
      const liveStateSyncElement = client.getLiveStateSyncElement();

      /// To get all the data
      const data = await liveStateSyncElement.fetchLiveStateData();

      /// To get data for specific liveStateDataId
      const specificData = await liveStateSyncElement.fetchLiveStateData({
          liveStateDataId: "LIVE_STATE_DATA_ID"
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```jsx theme={null}
      const liveStateSyncElement = Velt.getLiveStateSyncElement();

      // To get all the data
      const data = await liveStateSyncElement.fetchLiveStateData();

      // To get data for specific liveStateDataId
      const specificData = await liveStateSyncElement.fetchLiveStateData({
          liveStateDataId: "LIVE_STATE_DATA_ID"
      });
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.5.6-beta.6" description="October 7, 2025">
  ### Bug Fixes

  * \[**Live State Sync**]: The useServerConnectionStateChangeHandler hook was sometimes incorrectly reporting an offline state due to the behavior of our special listener in a multi-tab environment. When a browser throttled an idle tab, it would interfere with the shared network activity for this specific listener. This caused the listener in active tabs to momentarily and incorrectly return a false (disconnected) status, even though the primary database connection remained active. We added a 1.5s delay to resolve the network state before emitting the value in the hook.
</Update>

<Update label="4.5.6-beta.5" description="October 6, 2025">
  ### Improvements

  * \[**Single Editor Mode**]: Improved offline handling for Single Editor Mode controls. When you're offline and attempt to use the "Edit Here" button or accept/reject actions, these operations are now prevented and a console warning is displayed.

  * \[**Live State Sync**]: Added timestamp field to Redux action data in Live State Sync. Each action now includes a UTC timestamp for better tracking and debugging.

  ```json theme={null}
  {
      "id": "ACTION_ID",
      "action": {
          "type": "ACTION_TYPE",
          "payload": "ACTION_PAYLOAD" // optional
      },
      "timestamp": 1759745729823 // UTC timestamp in milliseconds
  }
  ```
</Update>

<Update label="4.5.6-beta.4" description="October 2, 2025">
  ### Bug Fixes

  * \[**Recorder**]: Fixed an issue where the control panel was not visible in thread mode.
</Update>

<Update label="4.5.6-beta.3" description="October 2, 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed an issue with manual comment pin selection when working with draft comment annotations.
</Update>

<Update label="4.5.6-beta.2" description="October 1, 2025">
  ### Bug Fixes

  * \[**Single Editor Mode**]: Fixed an issue related to switching editor access when heartbeat is disabled.
</Update>

<Update label="4.5.6-beta.1" description="October 1, 2025">
  ### New Features

  * \[**Live State Sync**]: Added heartbeat feature for Single Editor Mode. The heartbeat mechanism provides more reliable presence detection in single editor mode scenarios. This feature is enabled by default when single editor mode is enabled.

  <Note>
    If you want to disable heartbeat functionality, you must disable it before enabling single editor mode.
  </Note>

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Hooks
      const liveStateSyncElement = useLiveStateSyncUtils();
      liveStateSyncElement.enableHeartbeat();
      liveStateSyncElement.disableHeartbeat();

      // Using API methods
      const liveStateSyncElement = client.getLiveStateSyncElement();
      liveStateSyncElement.enableHeartbeat();
      liveStateSyncElement.disableHeartbeat();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      // Using API methods
      const liveStateSyncElement = Velt.getLiveStateSyncElement();
      liveStateSyncElement.enableHeartbeat();
      liveStateSyncElement.disableHeartbeat();
      </script>
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.5.5" description="September 30, 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where the comment dialog would auto-close after submitting the first comment in popover mode.
</Update>

<Update label="4.5.4" description="September 30, 2025">
  ### Improvements

  * \[**Comments**]: Added option to close persistent comment mode with ESC key, even when a thread is active. Use `forceCloseAllOnEsc` (prop/API).

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using props on component
      <VeltComments forceCloseAllOnEsc={true} />

      // Using API methods
      const commentElement = client.getCommentElement();
      commentElement.enableForceCloseAllOnEsc();
      commentElement.disableForceCloseAllOnEsc();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <!-- Using HTML attribute -->
      <velt-comments force-close-all-on-esc="true"></velt-comments>

      <script>
      // Using API methods
      const commentElement = Velt.getCommentElement();
      commentElement.enableForceCloseAllOnEsc();
      commentElement.disableForceCloseAllOnEsc();
      </script>
      ```
    </Tab>
  </Tabs>

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where `resolvedCommentsOnDom` was not applying to comment bubbles in the video player timeline.
</Update>

<Update label="4.5.4-beta.4" description="September 29, 2025">
  ### New Features

  * \[**Comments**]: Added attachments data support in REST API endpoints for adding and updating comments. You can programmatically include attachment metadata when creating or modifying comments through the REST API.

  The `attachments` field supports comprehensive metadata including:

  * **File identification**: `attachmentId`, `name`, `bucketPath`
  * **File properties**: `size`, `type`, `url`, `thumbnail`, `mimeType`
  * **Custom metadata**: Flexible metadata object for dimensions, timestamps, and other custom properties

  <Note>
    See the full REST API reference:

    * [Add Comments API](/api-reference/rest-apis/v2/comments-feature/comments/add-comments)
    * [Update Comments API](/api-reference/rest-apis/v2/comments-feature/comments/update-comments)
  </Note>

  ### Bug Fixes

  * \[**UI Customization**]: Fixed an issue where inline comments section filter dropdown wireframe not rendering correctly.
</Update>

<Update label="4.5.4-beta.3" description="September 27, 2025">
  ### New Features

  * \[**Notifications**]: Added ESC key support to close the notification panel.

  * \[**Comments**]: Added unread badge in CommentPlayerTimeline for annotations.

  * \[**Recorder**]: Added configuration to control playback behavior on preview click. You can now enable or disable the click-to-play/pause functionality on recording previews.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using props on component
      <VeltRecorderPlayer playbackOnPreviewClick={true} />

      // Using API methods
      const recorderElement = client.getRecorderElement();
      recorderElement.enablePlaybackOnPreviewClick();
      recorderElement.disablePlaybackOnPreviewClick();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <!-- Using HTML attribute -->
      <velt-recorder-player playback-on-preview-click="true"></velt-recorder-player>

      <script>
      // Using API methods
      const recorderElement = Velt.getRecorderElement();
      recorderElement.enablePlaybackOnPreviewClick();
      recorderElement.disablePlaybackOnPreviewClick();
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Notifications**]: Added `considerAllNotifications` configuration to the notifications tool to control the notification count and unread indicator. When enabled, the notification count and unread badge include items from all tabs; when disabled (default), they only include items from the “For You” tab.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltNotificationsTool considerAllNotifications={true} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-notifications-tool consider-all-notifications="true"></velt-notifications-tool>
      ```
    </Tab>
  </Tabs>

  * \[**Notifications**]: Added ability to filter notifications to the currently set document only. By default it shows notifications for the 15 most recently active documents accessible to the current user in the current organization.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      const notificationElement = client.getNotificationElement();
      notificationElement.enableCurrentDocumentOnly();
      notificationElement.disableCurrentDocumentOnly();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const notificationElement = Velt.getNotificationElement();
      notificationElement.enableCurrentDocumentOnly();
      notificationElement.disableCurrentDocumentOnly();
      </script>
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Notifications**]: Added ability to hide notification tabs when only one tab is enabled.

  * \[**UI Customization**]: Improved CSS variable handling in the ESC button for Persistent Comments Banner.

  * \[**UI Customization**]: Removed extra space next to the notification icon.

  ### Bug Fixes

  * \[**Recorder**]: Fixed an issue where the recording edit done event was not triggering with the correct data.

  * \[**Recorder**]: Fixed an issue where the countdown timer for the recorder was not working in Firefox.
</Update>

<Update label="4.5.4-beta.2" description="September 25, 2025">
  ### New Features

  * \[**UI Customization**]: Added hide reply button wireframe for the comment dialog. [See wireframe customization →](/ui-customization/features/async/comments/comment-dialog-components#hidereply)

  * \[**UI Customization**]: Added thread card reply button wireframe for the comment dialog to enable quick replies directly from comment thread cards. [See wireframe customization →](/ui-customization/features/async/comments/comment-dialog-components#threadcardreply)

  * \[**UI Customization**]: Added filter dropdown wireframe for the inline comments section. [See wireframe customization →](/ui-customization/features/async/comments/inline-comments-section#filterdropdown-panel)

  * \[**Comments**]: Added `allowedFileTypes` property to limit file types in comment attachments.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using props on component
      <VeltComments allowedFileTypes={['jpg', 'png']} />

      // Using API method
      const commentElement = client.getCommentElement();
      commentElement.setAllowedFileTypes(['jpg', 'png']);
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <!-- Using HTML attribute -->
      <velt-comments allowed-file-types="['jpg', 'png']"></velt-comments>

      <script>
      // Using API method
      const commentElement = Velt.getCommentElement();
      commentElement.setAllowedFileTypes(['jpg', 'png']);
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added ability to display the attachment filename in the message when a file is attached.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltComments attachmentNameInMessage={true} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments attachment-name-in-message="true"></velt-comments>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added setComposerFileAttachments() API method to programmatically add file attachments to the comment composer from your application instead of requiring users to select files from the file system.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      const commentElement = client.getCommentElement();
      commentElement.setComposerFileAttachments({
        files: [file1, file2],
        annotationId: 'annotation-123',
        targetElementId: 'element-456',
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
      const commentElement = Velt.getCommentElement();
      commentElement.setComposerFileAttachments({
        files: [file1, file2],
        annotationId: 'annotation-123',
        targetElementId: 'element-456',
      });
      </script>
      ```
    </Tab>
  </Tabs>

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where floating mode prop was being incorrectly added in React when enabling embed mode in the sidebar.
</Update>

<Update label="4.5.4-beta.1" description="September 24, 2025">
  ### New Features

  * \[**UI Customization**]: Added comment-level reply button wireframe. This button is hidden by default and can be enabled through wireframe customization.

  * \[**UI Customization**]: Added hide reply button wireframes for the comment dialog body.

  ### Bug Fixes

  * \[**Recorder**]: Fixed an issue where the Recorder control panel not being draggable.

  * \[**Access Control**]: Fixed an issue where Get User Permissions REST API was not returning `permission_denied` errors in the response

  <Note>
    See the full REST API reference: <a href="/api-reference/rest-apis/v2/auth/get-permissions">Get Permissions</a>.
  </Note>
</Update>

<Update label="4.5.3" description="September 20, 2025">
  ### New Features

  * \[**Comments**]: Added `readOnly` flag to Comment Bubble component to prevent users from replying or editing existing comments in the target bubble while still displaying them. This is useful when you want to display comments in a read-only mode where users can view but not modify or respond to comments.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using props on component
      <VeltCommentBubble readOnly={true} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <!-- Using attributes on element -->
      <velt-comment-bubble read-only="true"></velt-comment-bubble>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `disabled` flag to Comment Tool component to disable the comment tool and prevent users from adding new comments. This is helpful when you want to temporarily or conditionally restrict comment creation while still allowing users to view existing comments.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using props on component
      <VeltCommentTool disabled={true} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <!-- Using attributes on element -->
      <velt-comment-tool disabled="true"></velt-comment-tool>
      ```
    </Tab>
  </Tabs>

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where clicking on one comment bubble would unintentionally open multiple comment bubbles. Now clicking on a comment bubble correctly opens only that specific bubble.

  * \[**Comments**]: Fixed an issue where empty comments were being saved in some scenarios.
</Update>

<Update label="4.5.2" description="September 20, 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where empty comments were being saved in some scenarios.
  * \[**Core**]: Released 4.5.2 stable version.
</Update>

<Update label="4.5.2-beta.17" description="September 19, 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed a minor issue with the `fullScreen` prop in the Comments Sidebar.
</Update>

<Update label="4.5.2-beta.16" description="September 19, 2025">
  ### New Features

  * \[**Comments**]: Added full-screen mode for Comments Sidebar to maximize space for reviewing and managing comments. This is particularly useful when working with large volumes of feedback or conducting detailed comment reviews. By default, this feature is disabled and only supported in default mode (floating and embed modes are not supported).

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using props on component
      <VeltCommentsSidebar fullScreen={true} />

      // Using API methods
      const commentElement = client.getCommentElement();
      commentElement.enableFullScreenInSidebar();
      commentElement.disableFullScreenInSidebar();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <!-- Using attributes on element -->
      <velt-comments-sidebar full-screen="true"></velt-comments-sidebar>

      <script>
      // Using API methods
      const commentElement = Velt.getCommentElement();
      commentElement.enableFullScreenInSidebar();
      commentElement.disableFullScreenInSidebar();
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added fixed annotation numbers to comment pins and dialogs that persist across sessions, making it easier to reference specific comments in discussions and documentation. This replaces the previous temporary numbering system that reset on page refresh.

  * \[**Comments**]: Added search by annotation number in Comments Sidebar. You can now quickly find specific comments by typing their annotation number (e.g., `#2`) in the search field, making it faster to locate and navigate to referenced comments.

  ### UI Customization

  * \[**Comments**]: Added new wireframes to customize the appearance of comment annotation numbers and full-screen button in the Comments Sidebar. [See comment dialog wireframes →](/ui-customization/features/async/comments/comment-dialog-components#commentnumber) [See comment pin wireframes →](/ui-customization/features/async/comments/comment-pin#number) [See sidebar wireframes →](/ui-customization/features/async/comments/comment-sidebar-components#fullscreenbutton)

  ### Bug Fixes

  * \[**Recorder**]: Fixed Firefox compatibility issue that was preventing recordings from being stopped properly.

  * \[**Notifications**]: Fixed an issue where Notification Panel was not closing if Velt was not initialized.
</Update>

<Update label="4.5.2-beta.15" description="September 19, 2025">
  ### Bug Fixes

  * \[**Core**]: Fixed invalid user name validation to now accept email values in user names. Also improved URL handling by removing content after the last dot (.) to make URLs non-functional, and increased maximum character limit from 20 to 30.
</Update>

<Update label="4.5.2-beta.14" description="September 18, 2025">
  ### Improvements

  * \[**Access Control**]: Updated Get User Permissions API to remove `userIds` from the request payload and now returns structured error codes alongside permission denied messages. This provides clearer error handling and makes it easier to diagnose permission issues programmatically.

  <Tabs>
    <Tab title="React / Next.js">
      ```ts theme={null}
      // Request Payload
      interface GetUserPermissionsRequest {
        organizationId?: string;
        folderIds?: string[];
        documentIds?: string[];
      }

      // Response Payload
      interface GetUserPermissionsResponse {
        [userId: string]: {
          folders?: {
            [folderId: string]: {
              accessRole?: UserPermissionAccessRole;
              expiresAt?: number;
              error?: string;
              errorCode?: UserPermissionAccessRoleResult;
            }
          }
          organization?: {
            [organizationId: string]: {
              accessRole?: UserPermissionAccessRole;
              expiresAt?: number;
              error?: string;
              errorCode?: UserPermissionAccessRoleResult;
            }
          }
          documents?: {
            [documentId: string]: {
              accessRole?: UserPermissionAccessRole;
              expiresAt?: number;
              error?: string;
              errorCode?: UserPermissionAccessRoleResult;
            }
          }
        }
      }

      enum UserPermissionAccessRoleResult {
        DOES_NOT_EXIST = 'does_not_exist',
        PERMISSION_DENIED = 'permission_denied',
        SOMETHING_WENT_WRONG = 'something_went_wrong',
      }

      enum UserPermissionAccessRole {
        EDITOR = 'editor',
        VIEWER = 'viewer',
      }

      // Using API
      await client.getUserPermissions(request as GetUserPermissionsRequest);
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```ts theme={null}
      // Request Payload
      interface GetUserPermissionsRequest {
        organizationId?: string;
        folderIds?: string[];
        documentIds?: string[];
      }

      // Response Payload
      interface GetUserPermissionsResponse {
        [userId: string]: {
          folders?: {
            [folderId: string]: {
              accessRole?: UserPermissionAccessRole;
              expiresAt?: number;
              error?: string;
              errorCode?: UserPermissionAccessRoleResult;
            }
          }
          organization?: {
            [organizationId: string]: {
              accessRole?: UserPermissionAccessRole;
              expiresAt?: number;
              error?: string;
              errorCode?: UserPermissionAccessRoleResult;
            }
          }
          documents?: {
            [documentId: string]: {
              accessRole?: UserPermissionAccessRole;
              expiresAt?: number;
              error?: string;
              errorCode?: UserPermissionAccessRoleResult;
            }
          }
        }
      }

      enum UserPermissionAccessRoleResult {
        DOES_NOT_EXIST = 'does_not_exist',
        PERMISSION_DENIED = 'permission_denied',
        SOMETHING_WENT_WRONG = 'something_went_wrong',
      }

      enum UserPermissionAccessRole {
        EDITOR = 'editor',
        VIEWER = 'viewer',
      }

      // Using API
      await Velt.getUserPermissions(request as GetUserPermissionsRequest);
      ```
    </Tab>
  </Tabs>

  * \[**Access Control**]: Users with Viewer access can no longer add comments or update metadata through the SDK. This ensures proper permission enforcement on Velt features.

  ### Bug Fixes

  * \[**Core**]: Fixed document switch issue where comments were not properly disappearing when navigating between documents, ensuring clean state transitions.

  * \[**Core**]: Fixed local cache comment persistence issue that was causing stale comment data to remain after document changes.
</Update>

<Update label="4.5.2-beta.13" description="September 17, 2025">
  ### New Features

  * \[**Recorder**]: Added maximum recording length feature that allows you to set time limits on recordings. This helps manage storage costs and ensures recordings stay focused and relevant.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using props on components
      <VeltRecorderTool maxLength={10} />
      <VeltRecorderControlPanel maxLength={10} />

      // Using API methods
      const recorderElement = client.getRecorderElement();
      recorderElement.setMaxLength(10);
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <!-- Using attributes on elements -->
      <velt-recorder-tool max-length="10"></velt-recorder-tool>
      <velt-recorder-control-panel max-length="10"></velt-recorder-control-panel>

      <script>
      // Using API methods
      const recorderElement = Velt.getRecorderElement();
      recorderElement.setMaxLength(10);
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Recorder**]: Added Picture-in-Picture (PiP) mode for screen recordings when camera is enabled. This allows users to continue recording while multitasking, improving workflow efficiency for tutorial creation and documentation.

  <Warning>
    Picture-in-Picture is only supported in Chrome browsers and only works for screen recordings when the camera is active. This feature is disabled by default.
  </Warning>

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Enable PiP on components
      <VeltRecorderTool pictureInPicture={true} />
      <VeltRecorderControlPanel pictureInPicture={true} />

      // Control PiP via API
      const recorderElement = client.getRecorderElement();
      recorderElement.enablePictureInPicture();
      recorderElement.disablePictureInPicture();
      recorderElement.openPictureInPicture();
      recorderElement.exitPictureInPicture();

      // Custom PiP button wireframe
      <VeltRecorderControlPanelWireframe.FloatingMode.ActionBar.Pip>
          <span>Custom Pip Button</span>
      </VeltRecorderControlPanelWireframe.FloatingMode.ActionBar.Pip>
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <!-- Enable PiP on elements -->
      <velt-recorder-tool picture-in-picture="true"></velt-recorder-tool>
      <velt-recorder-control-panel picture-in-picture="true"></velt-recorder-control-panel>

      <!-- Custom PiP button wireframe -->
      <velt-wireframe style="display:none;">
          <velt-recorder-control-panel-action-bar-pip-wireframe>
              <span>Custom Pip Button</span>
          </velt-recorder-control-panel-action-bar-pip-wireframe>
      </velt-wireframe>

      <script>
      // Control PiP via API
      const recorderElement = Velt.getRecorderElement();
      recorderElement.enablePictureInPicture();
      recorderElement.disablePictureInPicture();
      recorderElement.openPictureInPicture();
      recorderElement.exitPictureInPicture();
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Recorder**]: Added screen recording preview to let users see their screen recordings preview prior to staring the recording. This helps users make make necessary adjustments before starting the recording. You programmatically ask users for permissions using the new API.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Request screen permission for preview
      const recorderElement = client.getRecorderElement();
      recorderElement.requestScreenPermission();

      // Custom screen player wireframe
      <VeltRecordingPreviewStepsDialogWireframe.Video.ScreenPlayer />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <!-- Custom screen player wireframe -->
      <velt-wireframe style="display:none;">
          <velt-recording-preview-steps-dialog-screen-player-wireframe>
          </velt-recording-preview-steps-dialog-screen-player-wireframe>
      </velt-wireframe>

      <script>
      // Request screen permission for preview
      const recorderElement = Velt.getRecorderElement();
      recorderElement.requestScreenPermission();
      </script>
      ```
    </Tab>
  </Tabs>

  ### Bug Fixes

  * \[**Single Editor Mode**]: Fixed heartbeat handling issue when external heartbeat is passed to prevent conflicts with internal presence detection mechanisms.

  * \[**UI Customization**]: Fixed Angular Material CSS scoping to prevent style conflicts by ensuring Angular Material styles are properly contained within Velt components.
</Update>

<Update label="4.5.2-beta.12" description="September 16, 2025">
  ### Bug Fixes

  * \[**Single Editor Mode**]: Fixed issue where editor assignment process wasn't reinitiated when a user regained internet connection or became active again after being offline. This ensures proper editor role management in collaborative editing scenarios.

  * \[**Single Editor Mode**]: Fixed "Edit here" functionality to properly assign editor role to users even when no existing data is available in the document.

  * \[**Core**]: Fixed React hook `setDocumentSuccess` event that wasn't triggering properly by adding flush sync method for `initUpdate` events. This ensures proper event handling and state updates in React applications.
</Update>

<Update label="4.5.2-beta.11" description="September 13, 2025">
  ### New Features

  * \[**Comments**]: Added `commentPlaceholder` and `replyPlaceholder` props on `VeltComments` so you can tailor input copy to your app’s voice and improve guidance for first-time users.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using Props on VeltComments
      <VeltComments commentPlaceholder="Ask a question or propose a change (use @ to mention teammates)" replyPlaceholder="Add context or suggest a fix (use @ to notify others)" />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments comment-placeholder="Ask a question or propose a change (use @ to mention teammates)" reply-placeholder="Add context or suggest a fix (use @ to notify others)"></velt-comments>
      ```
    </Tab>
  </Tabs>

  ### Bug Fixes

  * \[**Recorder**]: Fixed Recording Preview Dialog width issue.
</Update>

<Update label="4.5.2-beta.10" description="September 11, 2025">
  ### New Features

  * \[**Access Control**]: Added User Permissions API to fetch a user's `editor`/`viewer` access across organizations, folders, and documents, for both permanent and temporary users. This helps you enforce read-only experiences.

  <Warning>
    Users with `viewer` access are read-only; write actions like adding comments are blocked in the SDK.
  </Warning>

  <Note>
    See the [Access Control overview](/key-concepts/overview#access-control) for concepts and detailed guidance.
  </Note>

  #### REST API

  Retrieves user permissions for organizations, folders, and documents in a single API call. Supports both regular and temporary users.

  <Note>
    See the full REST API reference: <a href="/api-reference/rest-apis/v2/auth/get-permissions">Get Permissions</a>.
  </Note>

  #### SDK

  <Tabs>
    <Tab title="React / Next.js">
      ```ts theme={null}
      // Request Payload
      interface GetUserPermissionsRequest {
        organizationId?: string;
        folderIds?: string[];
        documentIds?: string[];
        userIds?: string[];
      }

      // Response Payload
      interface GetUserPermissionsResponse {
        [userId: string]: {
          folders?: {
            [folderId: string]: {
              accessRole?: UserPermissionAccessRole;
              expiresAt?: number;
              error?: string;
            }
          }
          organization?: {
            [organizationId: string]: {
              accessRole?: UserPermissionAccessRole;
              expiresAt?: number;
              error?: string;
            }
          }
          documents?: {
            [documentId: string]: {
              accessRole?: UserPermissionAccessRole;
              expiresAt?: number;
              error?: string;
            }
          }
        }
      }

      enum UserPermissionAccessRole {
        EDITOR = 'editor',
        VIEWER = 'viewer',
      }

      // Using API
      await client.getUserPermissions(request as GetUserPermissionsRequest);
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```ts theme={null}
      // Request Payload
      interface GetUserPermissionsRequest {
        organizationId?: string;
        folderIds?: string[];
        documentIds?: string[];
        userIds?: string[];
      }

      // Response Payload
      interface GetUserPermissionsResponse {
        [userId: string]: {
          folders?: {
            [folderId: string]: {
              accessRole?: UserPermissionAccessRole;
              expiresAt?: number;
              error?: string;
            }
          }
          organization?: {
            [organizationId: string]: {
              accessRole?: UserPermissionAccessRole;
              expiresAt?: number;
              error?: string;
            }
          }
          documents?: {
            [documentId: string]: {
              accessRole?: UserPermissionAccessRole;
              expiresAt?: number;
              error?: string;
            }
          }
        }
      }

      enum UserPermissionAccessRole {
        EDITOR = 'editor',
        VIEWER = 'viewer',
      }

      // Using API
      await Velt.getUserPermissions(request as GetUserPermissionsRequest);
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.5.2-beta.9" description="September 11, 2025">
  ### New Features

  * \[**Comments**]: Updated default placeholders and added props to customize placeholders for comment and reply inputs. Added wireframes to allow users to customize how it looks. [See wireframe customization →](/ui-customization/features/async/comments/comment-dialog-components#composerinput)
    * Default placeholders:
      * Comment: "Comment or add others with @"
      * Reply: "Reply or add others with @"

  * \[**Comments**]: Added hook to set and get UI state.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      const { uiState, setUiState } = useUiState();

      useEffect(() => {
        console.log('uiState: ', uiState);
      }, [uiState]);

      <button onClick={() => setUiState({ a: 1, b: 2 })}>Set Data</button>
      <button onClick={() => setUiState({ a: null, b: null })}>Set Data Null</button>
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <script>
        // UI state via API
        Velt.setUiState({ a: 1, b: 2 });
        Velt.getUiState().subscribe((data) => {
          console.log('UI State: ', data);
        });
        // Set fields back to null
        Velt.setUiState({ a: null, b: null });
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added Edited chip in comment thread: Edits are now visibly transparent at a glance, improving auditability and helping reviewers quickly spot updated messages in long discussions. See [Comment Dialog components](/ui-customization/features/async/comments/comment-dialog-components).

  **New wireframes added to customize "Edited" Chip:** [See wireframe customization →](/ui-customization/features/async/comments/comment-dialog-components#threadcardedited)

  ### Bug Fixes

  * \[**Comments**]: In `InlineCommentsSection` single-thread mode, count now reflects the number of Comments vs Comment Annotations.
  * \[**Recorder**]: Fixed an issue where longer recordings were not rendering the preview correctly in recording player and editor.
  * \[**Recorder**]: Fixed an issue where the host app was not clickable when screen recording was used in floating mode.
</Update>

<Update label="4.5.2-beta.8" description="September 10, 2025">
  ### Improvements

  * \[**Single Editor Mode**]: Added additional debugging logs for Single Editor Mode.

  ### Bug Fixes

  * \[**UI**]: Scoped `.cdk-overlay-pane` CSS into `.velt-overlay-panel` class to avoid global style leakage.
</Update>

<Update label="4.5.2-beta.7" description="September 9, 2025">
  ### New Features

  * \[**Comments**]: Added clickable links of text selection in comments and a link callback to handle link clicks programmatically.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Link callback in comments
      <VeltComments linkCallback={true} />

      // Hook
      const linkEvent = useCommentEventCallback('linkClicked');
      useEffect(() => {
        if (linkEvent) {
          // Navigate with your router here
          console.log('linkClicked', linkEvent);
        }
      }, [linkEvent]);
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <!-- Link callback in comments -->
      <velt-comments link-callback="true"></velt-comments>

      <script>
        const commentElement = Velt.getCommentElement();
        commentElement.on('linkClicked').subscribe((linkData) => {
          // Navigate with your router here
          console.log('Comment link clicked:', linkData);
        });
      </script>
      ```
    </Tab>
  </Tabs>

  * \[**Recorder**]: Added `recorderId` prop to Video Editor.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Video Editor
      <VeltVideoEditor recorderId="zK3iEAfvs1Htu3QYPy5S" />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <!-- Video Editor -->
      <velt-video-editor recorder-id="zK3iEAfvs1Htu3QYPy5S"></velt-video-editor>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Slack-style link pasting: select text and paste a link to directly convert it into a clickable hyperlink. This speeds up authoring and provides a familiar UX for users.

  ### Improvements

  * \[**Comments**]: Removed translation from group name in sidebar to allow special characters.

  ### Bug Fixes

  * \[**Recorder**]: Fixed `recorderId` change detection in video player.
  * \[**Recorder**]: Fixed thread mode UI for screen recordings.
</Update>

<Update label="4.5.2-beta.6" description="September 8, 2025">
  ### New Features

  * \[**Comments**]: Added group support for custom lists. Useful for workflows like issue trackers (e.g., group by "Priority" or "Status"), allowing users to quickly refer and insert custom entities from your app. With this feature, you can combine multiple entity types into one drop down just like Linear. See full examples in Customize Behavior → [Create custom list data on comment](/async-collaboration/comments/customize-behavior#createcustomlistdataoncomment).

  <Tabs>
    <Tab title="React / Next.js">
      ```ts theme={null}
      const customListWithGroups = {
        hotkey: "$",
        type: "custom",
        groups: [
          { id: "categories", name: "Categories" },
          { id: "priorities", name: "Priorities" }
        ],
        data: [
          // Categories group - 2 items
          {
            id: "bug_1",
            name: "Bug 1",
            description: "Bug report 1",
            groupId: "categories",
            icon: { svg: "<svg></svg>" }
          },
          {
            id: "feature_2",
            name: "Feature Request 2",
            description: "New feature 2",
            groupId: "categories",
            icon: { url: "https://random.png" }
          },
          // Priorities group - 2 items
          {
            id: "high_1",
            name: "High Priority 1",
            description: "Urgent task 1",
            groupId: "priorities",
            icon: { url: "https://random.png" }
          },
          {
            id: "medium_2",
            name: "Medium Priority 2",
            description: "Normal task 2",
            groupId: "priorities",
            icon: { svg: "<svg></svg>" }
          },
          // Ungrouped items - 2 items
          {
            id: "misc_1",
            name: "Miscellaneous 1",
            description: "Other items 1",
            icon: { url: "https://random.png" }
          },
          {
            id: "note_2",
            name: "Note 2",
            description: "General note 2",
            icon: { svg: "<svg></svg>" }
          }
        ]
      };

      const commentElement = client.getCommentElement();
      commentElement.createCustomListDataOnComment(customListWithGroups);
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      const customListWithGroups = {
        hotkey: "$",
        type: "custom",
        groups: [
          { id: "categories", name: "Categories" },
          { id: "priorities", name: "Priorities" }
        ],
        data: [
          { id: "bug_1", name: "Bug 1", description: "Bug report 1", groupId: "categories", icon: { svg: "<svg></svg>" } },
          { id: "feature_2", name: "Feature Request 2", description: "New feature 2", groupId: "categories", icon: { url: "https://random.png" } },
          { id: "high_1", name: "High Priority 1", description: "Urgent task 1", groupId: "priorities", icon: { url: "https://random.png" } },
          { id: "medium_2", name: "Medium Priority 2", description: "Normal task 2", groupId: "priorities", icon: { svg: "<svg></svg>" } },
          { id: "misc_1", name: "Miscellaneous 1", description: "Other items 1", icon: { url: "https://random.png" } },
          { id: "note_2", name: "Note 2", description: "General note 2", icon: { svg: "<svg></svg>" } }
        ]
      };

      const commentElement = Velt.getCommentElement();
      commentElement.createCustomListDataOnComment(customListWithGroups);
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.5.2-beta.5" description="September 8, 2025">
  ### Improvements

  * \[**Single Editor Mode**]: Optimized and made Single Editor Mode more robust.
</Update>

<Update label="4.5.2-beta.4" description="September 6, 2025">
  ### New Features

  * \[**Single Editor Mode**]: Added `updateUserPresence` to send heartbeat data from the host app. This helps Velt detect multi-tab activity and resolve who is the active editor when users switch tabs or devices and will use that as a fallback in rare edge cases if it fails to detect multi‑tab/device presence. Most apps don’t need this; use only if you see ambiguity in who’s the active editor.

  <Tabs>
    <Tab title="React / Next.js">
      ```ts theme={null}
      export interface LiveStateSingleEditorExternalUserPresence {
        /** True if the same user is present on a different tab. */
        sameUserPresentOnTab?: boolean;
        /** True if a different user is present on a different tab. */
        differentUserPresentOnTab?: boolean;
        /** User IDs of users present on a different tab. */
        userIds?: string[];
      }

      // API method
      const liveStateSyncElement = client.getLiveStateSyncElement();
      liveStateSyncElement.updateUserPresence({
        sameUserPresentOnTab: false,
        differentUserPresentOnTab: true,
        userIds: ['user-2']
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      // API method
      const liveStateSyncElement = Velt.getLiveStateSyncElement();
      liveStateSyncElement.updateUserPresence({
        sameUserPresentOnTab: false,
        differentUserPresentOnTab: true,
        userIds: ['user-2']
      });
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Single Editor Mode**]: Added validations in `setUserAsEditor` to set a user only if no editor is currently assigned.

  <Tabs>
    <Tab title="React / Next.js">
      ```ts theme={null}
      export interface SetUserAsEditorResponse {
        error?: ErrorEvent;
      }

      export type ErrorEvent = {
        error?: string;
        code: string;
        message?: string;
        source?: string;
      };

      // Method signature
      // public setUserAsEditor: () => Promise<SetUserAsEditorResponse | void>;

      // Usage with response handling
      const liveStateSyncElement = client.getLiveStateSyncElement();
      const result = await liveStateSyncElement.setUserAsEditor();
      if (result?.error) {
        if (result.error.code === 'same_user_editor_current_tab') {
          // Same user is already editor in current tab
        } else if (result.error.code === 'same_user_editor_different_tab') {
          // Same user is already editor in different tab
        } else if (result.error.code === 'another_user_editor') {
          // Another user is already editor
        }
      }
      ```

      ```ts theme={null}
      // Possible error values
      // For same user current tab error
      {
        code: 'same_user_editor_current_tab',
        message: 'Same user is already editor in current tab.',
        source: 'setUserAsEditor',
      }

      // For same user different tab error
      {
        code: 'same_user_editor_different_tab',
        message: 'Same user is already editor in different tab.',
        source: 'setUserAsEditor',
      }

      // For another user error
      {
        code: 'another_user_editor',
        message: 'Another user is already editor.',
        source: 'setUserAsEditor',
      }
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      // Method usage
      const liveStateSyncElement = Velt.getLiveStateSyncElement();
      const result = await liveStateSyncElement.setUserAsEditor();
      if (result && result.error) {
        if (result.error.code === 'same_user_editor_current_tab') {
          // Same user already editor in current tab
        } else if (result.error.code === 'same_user_editor_different_tab') {
          // Same user already editor in different tab
        } else if (result.error.code === 'another_user_editor') {
          // Another user already editor
        }
      }
      ```
    </Tab>
  </Tabs>

  * \[**Single Editor Mode**]: Optimized and made Single Editor Mode more robust.
</Update>

<Update label="4.5.2-beta.3" description="September 5, 2025">
  ### New Features

  * \[**Access Control**]: Added support for viewer and editor roles for permanent and temporary users.

  <Info>
    **Editor vs Viewer roles**

    * **Editor**: Full read/write access to collaboration data on the resource (create/edit/delete comments and replies, add reactions, start recordings, etc.).
    * **Viewer**: Read-only access to collaboration data (view comments and replies, presence, cursors, recordings, notifications) without the ability to modify.

    Why this matters: You can enforce read-only experiences, safely grant temporary edit windows, and align Velt features with your app’s permission model.
  </Info>

  For implementation details, see the v2 Auth APIs:

  * Generate Token: [/api-reference/rest-apis/v2/auth/generate-token](/api-reference/rest-apis/v2/auth/generate-token)
  * Add Permissions: [/api-reference/rest-apis/v2/auth/add-permissions](/api-reference/rest-apis/v2/auth/add-permissions)

  <Warning>
    `accessRole` is configurable only via the v2 Users and Auth Permissions REST APIs. Frontend SDK methods do not accept or change `accessRole`.

    Relevant endpoints:

    * [/api-reference/rest-apis/v2/users/add-users](/api-reference/rest-apis/v2/users/add-users)
    * [/api-reference/rest-apis/v2/users/update-users](/api-reference/rest-apis/v2/users/update-users)
    * [/api-reference/rest-apis/v2/auth/add-permissions](/api-reference/rest-apis/v2/auth/add-permissions)
    * [/api-reference/rest-apis/v2/auth/generate-token](/api-reference/rest-apis/v2/auth/generate-token)
  </Warning>

  <Note>
    See the [Access Control overview](/key-concepts/overview#access-control) for concepts and detailed guidance.
  </Note>

  ### Improvements

  * \[**Single Editor Mode**]: Optimized and made Single Editor Mode more robust.
</Update>

<Update label="4.5.2-beta.2" description="August 25, 2025">
  ### New Features

  * \[**Comments**]: Launched a purpose built library for adding comments to Lexical Editor. [Learn more](/async-collaboration/comments/setup/lexical).

  ### Improvements

  * \[**Comments**]: Optimized how comment read/unread state is updated internally.
</Update>

<Update label="4.5.2-beta.1" description="August 22, 2025">
  ### Bug Fixes

  * \[**UI Customization**]: Fixed an issue where `Velt Button` was not passing internal state to its children in some scenarios.
</Update>

<Update label="4.5.1" description="August 22, 2025">
  ### Bug Fixes

  * \[**Core**]: Resolved a race condition in resolving user data. Applied the same fix that was added to the `4.5.0-beta.66-patch.1` version.

  <Warning>
    Note after this update, if you plan to go back to older version of the SDK before `4.5.0-beta.43`, then please reach out to Velt Support for a graceful rollback.
  </Warning>
</Update>

<Update label="4.5.0-beta.66-patch.1" description="August 22, 2025">
  ### Bug Fixes

  * \[**Core**]: Resolved a race condition in resolving user data.
</Update>

<Update label="4.5.0" description="August 20, 2025">
  ### Improvements

  * \[**Comments**]: Updated comment annotation count subscription. It now supports getting total and unread Comment Annotations count across Organization, Folder, Document and Multiple Documents levels.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Organization level
      const commentElement = client.getCommentElement();
      commentElement.getCommentAnnotationsCount({ organizationId: 'org1' }).subscribe((data) => {
        console.log('getCommentAnnotationsCount with organizationId', data);
      });

      // Folder level
      commentElement.getCommentAnnotationsCount({ organizationId: 'org1', folderId: 'folder2', allDocuments: true }).subscribe((data) => {
        console.log('getCommentAnnotationsCount with organizationId and folderId and allDocuments', data);
      });

      // Document Level
      commentElement.getCommentAnnotationsCount().subscribe((data) => {
        console.log('getCommentAnnotationsCount', data);
      });

      // Aggregate Across Multiple Documents
      commentElement.getCommentAnnotationsCount({ aggregateDocuments: true }).subscribe((data) => {
        console.log('getCommentAnnotationsCount with aggregateDocuments', data);
      });

      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      // Organization level
      const commentElement = Velt.getCommentElement();
      commentElement.getCommentAnnotationsCount({ organizationId: 'org1' }).subscribe((data) => {
        console.log('getCommentAnnotationsCount with organizationId', data);
      });

      // Folder level
      commentElement.getCommentAnnotationsCount({ organizationId: 'org1', folderId: 'folder2', allDocuments: true }).subscribe((data) => {
        console.log('getCommentAnnotationsCount with organizationId and folderId and allDocuments', data);
      });

      // Document Level
      commentElement.getCommentAnnotationsCount().subscribe((data) => {
        console.log('getCommentAnnotationsCount', data);
      });

      // Aggregate Across Multiple Documents
      commentElement.getCommentAnnotationsCount({ aggregateDocuments: true }).subscribe((data) => {
        console.log('getCommentAnnotationsCount with aggregateDocuments', data);
      });
      ```
    </Tab>
  </Tabs>

  <Warning>
    Note after this update, if you plan to go back to older version of the SDK before `4.5.0-beta.43`, then please reach out to Velt Support for a graceful rollback.
  </Warning>
</Update>

<Update label="4.5.0-beta.66" description="August 14, 2025">
  ### New Features

  * \[**Comments**]: Added support to filter out ghost comments when retrieving comment annotations count.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      const commentElement = client.getCommentElement();
      commentElement.getCommentAnnotationsCount({ filterGhostComments: true }).subscribe((data) => {
         console.log('getCommentAnnotationsCount with filterGhostComments', data);
      });

      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement.getCommentAnnotationsCount({ filterGhostComments: true }).subscribe((data) => {
         console.log('getCommentAnnotationsCount with filterGhostComments', data);
      });

      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.5.0-beta.65" description="August 13, 2025">
  ### New Features

  * \[**Recorder**]: Added API to programmatically request audio and video permissions from the user.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      const recorderElement = useRecorderUtils();

      recorderElement.askDevicePermission({
        audio: true,
        video: true
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      const recorderElement = Velt.getRecorderElement();

      recorderElement.askDevicePermission({
        audio: true,
        video: true
      });
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.5.0-beta.64" description="August 8, 2025">
  ### Improvements

  * \[**UI Customization**]: Added an alternative approach to evaluate `Velt If` conditions. The default method could be blocked by some strict Content Security Policies (CSP) that disallow `unsafe-eval`.

  <Tabs>
    <Tab title="React / Next.js">
      ```javascript theme={null}
      client.enableSafeEval();
      client.disableSafeEval();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```javascript theme={null}
      Velt.enableSafeEval();
      Velt.disableSafeEval();
      ```
    </Tab>
  </Tabs>

  * \[**Multiplayer Editing**]: Now you can encrypt CRDT data before it’s stored in Velt by registering a custom encryption provider. For CRDT methods, input data is of type `Uint8Array | number[]`. [Learn more](/realtime-collaboration/crdt/setup/core#custom-encryption)
</Update>

<Update label="4.5.0-beta.63" description="August 7, 2025">
  ### Improvements

  * \[**Comments**]: Added `filterGhostCommentsInSidebar` config in comment sidebar to hide ghost comments from sidebar. Default: `false`

  <Tabs>
    <Tab title="React / Next.js">
      **Using Props:**

      ```jsx theme={null}
      // Use either of the following
      <VeltCommentsSidebar filterGhostCommentsInSidebar={true} />
      <VeltSidebarButton filterGhostCommentsInSidebar={true} />
      ```

      **Using APIs:**

      ```javascript theme={null}
      const commentElement = client.getCommentElement();
      commentElement.enableFilterGhostCommentsInSidebar();
      commentElement.disableFilterGhostCommentsInSidebar();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      **Using Props:**

      ```html theme={null}
      <!-- Use either of the following -->
      <velt-comments-sidebar filter-ghost-comments-in-sidebar="true"></velt-comments-sidebar>
      <velt-sidebar-button filter-ghost-comments-in-sidebar="true"></velt-sidebar-button>
      ```

      **Using APIs:**

      ```javascript theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement.enableFilterGhostCommentsInSidebar();
      commentElement.disableFilterGhostCommentsInSidebar();
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.5.0-beta.62" description="August 6, 2025">
  ### Bug Fixes

  * \[**Recorder**]: Fixed an issue where the `recordingEditDone` event was not firing correctly under certain conditions.
</Update>

<Update label="4.5.0-beta.61" description="July 24, 2025">
  ### New Features

  * \[**Notifications**]: Added wireframes to modify the title text of the Velt Notification Panel.
  * \[**Video Editor**]: Introduced the `VeltVideoEditor`, a new embeddable component for viewing and editing video recordings directly in your application. It can be initialized using a URL, blob, or recorder ID.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltVideoEditor
      	blob={blob}
        url="videourl.mp4"
        darkMode={true}
        variant="xyz"
        recorderId="123"
      />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-video-editor
        recorder-id="zK3iEAfvs1Htu3QYPy5S"
        blob="blob"
        url="videourl.mp4"
        dark-mode="true"
        variant="xyz"
      ></velt-video-editor>
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.5.0-beta.60" description="July 23, 2025">
  ### Improvements

  * \[**Auth**]: When re-authentication occurs after a token expires, `setDocuments` now automatically restores the previous set of documents to maintain session continuity.
</Update>

<Update label="4.5.0-beta.59" description="July 22, 2025">
  ### New Features

  * \[**Auth**]: Introduced `authProvider` for more robust and flexible authentication management. This includes automatic token refresh with configurable retry logic. [Learn more](/key-concepts/overview#sign-in-a-user).

  * \[**Access Control**]: Added a new permissions API to [grant](/api-reference/rest-apis/v2/auth/add-permissions) and [revoke](/api-reference/rest-apis/v2/auth/remove-permissions) user permissions dynamically on demand.
    * Grant permissions on demand vs syncing users to Velt.
    * Grant temporary time based permissions or permanent permissions to Organizations, Folders and Documents.
    * [Learn more](/key-concepts/overview#access-control).
</Update>

<Update label="4.5.0-beta.58" description="July 22, 2025">
  ### New Features

  * \[**Multiplayer Editing**]: Introduced versioning support for CRDT stores. You can now save snapshots of your collaborative data, list previously saved versions, and restore the store to a specific version. This feature is currently supported for `text` and `array` data types.
</Update>

<Update label="4.5.0-beta.57" description="July 19, 2025">
  ### Improvements

  * \[**Recorder**]: Expanded recorder functionality with a comprehensive set of lifecycle events, allowing you to build more integrated and responsive recording experiences. The following events are now available:
    * `recordingEditDone`: Triggered when the "Done" button is clicked in the recording editor. Fires after edits are saved, or immediately if no edits were made.
    * `recordingStarted`: Triggered when the recording starts.
    * `recordingPaused`: Triggered when the recording is paused.
    * `recordingCancelled`: Triggered when the recording is cancelled.
    * `recordingStopped`: Triggered when the recording is stopped.
    * `recordingResumed`: Triggered when the recording is resumed after being paused.
</Update>

<Update label="4.5.0-beta.56" description="July 19, 2025">
  ### New Features

  * \[**Auth**]: Introduced a new streamlined authentication flow to simplify user session management within Velt.
</Update>

<Update label="4.5.0-beta.55" description="July 16, 2025">
  ### New Features

  * \[**Auth**]: Added support for on-demand access control. Instead of syncing users to Velt, you can now grant permanent or temporary access to resources (organizations, folders, documents) to users on the fly.
    * If you pass `organizationId` in the `identify` method and set `requireJwtToken` to `true` (in console), you **must** also include access to the same `organizationId` in the `resources` array of your permissions. Otherwise, it will throw an error.

  <Tabs>
    <Tab title="Backend Endpoint">
      ```ts theme={null}
      const authRequest: VeltAuthTokenRequest = {
        apiKey: "API_KEY",
        userId: "USER_ID",
        userProperties: {
          isAdmin: false,
          name: "USER_NAME",
          email: "USER_EMAIL"
        },
        permissions: {
          resources: [
            {
              type: "organization",
              id: "ORGANIZATION_ID"
            },
            {
              type: "document",
              id: "DOCUMENT_ID",
              organizationId: "ORGANIZATION_ID",
              expiresAt: Math.floor(Date.now() / 1000) + 3600 // 1 hour from now
            }
          ]
        }
      };

      try {
        const response = await fetch('https://api.velt.dev/v2/auth/generate_token', {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify(authRequest),
        });

        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }

        const responseJson = await response.json();
        const token = responseJson?.result?.data?.token;
        return token;
      } catch (error) {
        console.error("Error:", error);
      }

      ```
    </Tab>

    <Tab title="Frontend">
      ```ts theme={null}
      const token = await __yourBackendEndpointToGenerateToken__();
      await client.identify(user, {
        authToken: token,
      })
      ```
    </Tab>
  </Tabs>

  * \[**Multiplayer Editing (CRDT)**]: Launched Yjs based CRDT libraries for:
    * `@veltdev/crdt`: Framework-agnostic CRDT stores (array, map, text, xml), versioning, subscriptions, and syncing via the Velt client.
    * `@veltdev/crdt-react`: React Hook wrapper for CRDT integration.
    * `@veltdev/tiptap-crdt`: Purpose built CRDT library for Tiptap Editor to enable multiplayer editing.

  ### Improvements

  * \[**REST APIs**]: Added support for `context` field on:
    * `Comment` `add` and `update` APIs: Now you can pass `context` field at the comment level.
    * `CommentAnnotation` `add` API: Now you can pass `context` field not only at the comment annotation level but also at the comment level.
</Update>

<Update label="4.5.0-beta.54" description="July 16, 2025">
  ### Bug Fixes

  * \[**Recorder**]: Fixed edge cases in Firefox where devices were not appearing in settings, video sometimes remained off during video recording, and screen recording would not start until the browser was focused.
  * \[**Recorder**]: Fixed an issue where the author was incorrectly shown for audio recordings in floating player.
  * \[**Notifications**]: Fixed an issue where the Notification Panel and Comments Sidebar would not close if the document was not set.
  * \[**Seen By**]: Fixed an issue where the "Seen by" list incorrectly included the author.
</Update>

<Update label="4.5.0-beta.53" description="July 15, 2025">
  ### Improvements

  * \[**Comments Sidebar**]: Added `sidebarButtonCountType` config to control the count shown on the sidebar button.
    * `default`: Shows the total count of comments in open and in progress states.
    * `filter`: Shows the count of filtered comments.

  <Tabs>
    <Tab title="React / Next.js">
      **Using Props:**

      ```jsx theme={null}
        <VeltCommentsSidebar sidebarButtonCountType="filter" />
        <VeltSidebarButton sidebarButtonCountType="filter" />
      ```

      **Using APIs:**

      ```jsx theme={null}
      const commentElement = useCommentUtils();
      commentElement.setSidebarButtonCountType('filter');
      ```
    </Tab>

    <Tab title="Other Frameworks">
      **Using Props:**

      ```html theme={null}
      <velt-comments-sidebar sidebar-button-count-type="filter"></velt-comments-sidebar>
      <velt-sidebar-button sidebar-button-count-type="filter"></velt-sidebar-button>
      ```

      **Using APIs:**

      ```js theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement.setSidebarButtonCountType('filter');
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.5.0-beta.52" description="July 14, 2025">
  ### Improvements

  * \[**User**]: Avatar colors are now generated consistently across frontend and backend when not set manually.
  * \[**Self-hosting**]: Now we are returning author `userId` in comment and reaction resolver APIs for more flexible querying and filtering.
</Update>

<Update label="4.5.0-beta.51" description="July 14, 2025">
  ### Improvements

  * \[**Core**]: Added internal optimzations for realtime data fetching.
</Update>

<Update label="4.5.0-beta.50" description="July 11, 2025">
  ### New Features

  * \[**Comments**]: Added "Involved" filter to the comment sidebar to easily find comments where a user is author, mentioned, or assigned.

  ### Bug Fixes

  * \[**Recorder**]: Fixed issues with audio/video capture and permission prompts in Firefox.
</Update>

<Update label="4.5.0-beta.49" description="July 10, 2025">
  ### Improvements

  * \[**Notifications**]: Added an option to filter notifications based on type in the `getNotificationsData` method.
    * Now this method/hook can accept an optional `GetNotificationsDataQuery` object, which supports a `type` property:
      * `'all'` (default): returns all notifications from the documents the user has access to.
      * `'forYou'`: returns notifications where the current user is involved.
      * `'documents'`: returns notifications for documents where the current user has access to.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      const notificationsData = useNotificationsData({ type: 'forYou' });

      useEffect(() => {
        if (notificationsData) {
          console.log(notificationsData);
        }
      }, [notificationsData]);
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      const notificationElement = Velt.getNotificationElement();
      notificationElement.getNotificationsData({ type: 'forYou' }).subscribe((notifications) => {
          console.log(notifications);
      });

      ```
    </Tab>
  </Tabs>

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue with aggregated comments dialog, where hitting the reply button would close the dialog.
  * \[**Notifications**]: Fixed empty state issue in the notification API where the data would first return an empty array before returning the actual data.
</Update>

<Update label="4.5.0-beta.48" description="July 10, 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed an issue with the comment tool in popover mode where the tool would not hide sometimes even when the comment was added.
</Update>

<Update label="4.5.0-beta.47" description="July 10, 2025">
  ### Improvements

  * \[**Video Editor**]: Added robustness for edge cases with short videos (\< 2-3s) that could cause unexpected behavior in the editor. eg: zooming, trimming, etc.
  * \[**Video Editor**]: Added robustness to playhead action buttons group and tooltip display and position logic for edge cases.
</Update>

<Update label="4.5.0-beta.46" description="July 09, 2025">
  ### Improvements

  * \[**Core**]: Added internal optimzations for realtime data fetching.
</Update>

<Update label="4.5.0-beta.45" description="July 09, 2025">
  ### Updates

  * \[**Huddle**]: Added `serverFallback` config in huddle. By default Huddle service is peer-to-peer. This will enable or disable the fallback to server-side for connectivity if peer-to-peer fails.

    Default: `true`

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltHuddle serverFallback={false} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-huddle server-fallback="false"></velt-huddle>
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Notifications**]: Updated `documentName` rendering logic in the notification panel to only render the component if the `documentName` is available. Earlier it was falling back to the `documentId`.
  * \[**Notifications**]: Added support to open and close the notification panel using APIs.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      const notificationElement = useNotificationUtils()
      notificationElement.openNotificationsPanel()
      notificationElement.closeNotificationsPanel()

      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```jsx theme={null}
      const notificationElement = Velt.getNotificationElement();
      notificationElement.openNotificationsPanel();
      notificationElement.closeNotificationsPanel();
      ```
    </Tab>
  </Tabs>

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where DOM changes detection was not working for text comments in some scenarios.
  * \[**Video Editor**]: Hide video editor tooltips and selection during playback.
  * \[**Notifications**]: Fixed an issue where notification panel was not closing when clicked on notification tool.
</Update>

<Update label="4.5.0-beta.44" description="July 07 2025">
  ### New Features

  * \[**Video Editor**]: Updated video editor with new UI design for improved UX including tooltips, floating action buttons, active/inactive states, etc.
  * \[**Video Editor**]: Added a retake button on video editor.

  <Tabs>
    <Tab title="React / Next.js">
      **Using Props (use any one of the following):**

      ```jsx theme={null}
      <VeltRecorderPlayer retakeOnVideoEditor={true} />
      <VeltRecorderControlPanel retakeOnVideoEditor={true} />
      <VeltRecorderTool retakeOnVideoEditor={true} />
      ```

      **Using APIs:**

      ```jsx theme={null}
      const recorderElement = useRecorderUtils();

      // Enable/disable retake button on video editor
      recorderElement.enableRetakeOnVideoEditor();
      recorderElement.disableRetakeOnVideoEditor();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      **Using Attributes (use any one of the following):**

      ```html theme={null}
      <velt-recorder-player retake-on-video-editor="true"></velt-recorder-player>
      <velt-recorder-control-panel retake-on-video-editor="true"></velt-recorder-control-panel>
      <velt-recorder-tool retake-on-video-editor="true"></velt-recorder-tool>
      ```

      **Using APIs:**

      ```jsx theme={null}
      const recorderElement = Velt.getRecorderElement();

      // Enable/disable retake button on video editor
      recorderElement.enableRetakeOnVideoEditor();
      recorderElement.disableRetakeOnVideoEditor();
      ```
    </Tab>
  </Tabs>

  * \[**Video Editor**]: Added onboarding tooltip for new users.

      <Tabs>
        <Tab title="React / Next.js">
          **Using APIs:**

          ```jsx theme={null}
          const recorderElement = useRecorderUtils();

          // Enable/disable onboarding tooltip
          recorderElement.enableOnboardingTooltip();
          recorderElement.disableOnboardingTooltip();
          ```
        </Tab>

        <Tab title="Other Frameworks">
          **Using APIs:**

          ```jsx theme={null}
          const recorderElement = Velt.getRecorderElement();

          // Enable/disable onboarding tooltip
          recorderElement.enableOnboardingTooltip();
          recorderElement.disableOnboardingTooltip();
          ```
        </Tab>
      </Tabs>
</Update>

<Update label="4.5.0-beta.43" description="July 07 2025">
  ### Improvements

  * \[**Core**]: Added central DB for user metadata. Going forward, if user metadata changes via REST API or via identify method, it will be reflected across all data rendered in the UI.

  <Warning>
    Note after this update, if you plan to go back to older version of the SDK before `4.5.0-beta.43`, then please reach out to Velt Support for a graceful rollback.
  </Warning>
</Update>

<Update label="4.5.0-beta.42" description="July 06 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed the issue where context was not applied to freestyle area comments.
</Update>

<Update label="4.5.0-beta.41" description="July 04 2025">
  ### New Features

  * \[**Comments**]: Added support to filter and aggregate comment annotations by `locationId` in `InlineCommentsSection`, `VeltCommentPin` and `VeltCommentBubble` components. `folderId` or `documentId` is required.

      <Tabs>
        <Tab title="React / Next.js">
          **Inline Comments Section:**

          ```jsx theme={null}
          // folderId + locationId
          <VeltInlineCommentsSection folderId="YOUR_FOLDER_ID" locationId="YOUR_LOCATION_ID" />
          // documentId + locationId
          <VeltInlineCommentsSection documentId="YOUR_DOCUMENT_ID" locationId="YOUR_LOCATION_ID" />
          ```

          **Comment Tool - Comment Bubble for popover comments:**

          ```jsx theme={null}
          // folderId + locationId
          <VeltCommentTool folderId="YOUR_FOLDER_ID" locationId="YOUR_LOCATION_ID" />
          <VeltCommentBubble folderId="YOUR_FOLDER_ID" locationId="YOUR_LOCATION_ID" />
          // documentId + locationId
          <VeltCommentTool documentId="YOUR_DOCUMENT_ID" locationId="YOUR_LOCATION_ID" />
          <VeltCommentBubble documentId="YOUR_DOCUMENT_ID" locationId="YOUR_LOCATION_ID" />
          ```

          **Comment Pin:**

          ```jsx theme={null}
          // folderId + locationId
          <VeltCommentPin folderId="YOUR_FOLDER_ID" locationId="YOUR_LOCATION_ID" />
          // documentId + locationId
          <VeltCommentPin documentId="YOUR_DOCUMENT_ID" locationId="YOUR_LOCATION_ID" />
          ```
        </Tab>

        <Tab title="Other Frameworks">
          **Inline Comments Section:**

          ```html theme={null}
          <!-- folderId + locationId -->
          <velt-inline-comments-section folder-id="YOUR_FOLDER_ID" location-id="YOUR_LOCATION_ID"></velt-inline-comments-section>
          <!-- documentId + locationId -->
          <velt-inline-comments-section document-id="YOUR_DOCUMENT_ID" location-id="YOUR_LOCATION_ID"></velt-inline-comments-section>
          ```

          **Comment Tool - Comment Bubble:**

          ```html theme={null}
          <!-- folderId + locationId -->
          <velt-comment-tool folder-id="YOUR_FOLDER_ID" location-id="YOUR_LOCATION_ID"></velt-comment-tool>
          <velt-comment-bubble folder-id="YOUR_FOLDER_ID" location-id="YOUR_LOCATION_ID"></velt-comment-bubble>
          <!-- documentId + locationId -->
          <velt-comment-tool document-id="YOUR_DOCUMENT_ID" location-id="YOUR_LOCATION_ID"></velt-comment-tool>
          <velt-comment-bubble document-id="YOUR_DOCUMENT_ID" location-id="YOUR_LOCATION_ID"></velt-comment-bubble>
          ```

          **Comment Pin:**

          ```html theme={null}
          <!-- folderId + locationId -->
          <velt-comment-pin folder-id="YOUR_FOLDER_ID" location-id="YOUR_LOCATION_ID"></velt-comment-pin>
          <!-- documentId + locationId -->
          <velt-comment-pin document-id="YOUR_DOCUMENT_ID" location-id="YOUR_LOCATION_ID"></velt-comment-pin>
          ```
        </Tab>
      </Tabs>

  * \[**Comments**]: Add ability to filter and aggregate comments by mulitple conditions: `folderId`/`documentId`/`locationId` and `context`. Only those comment annotations that satisfy all the conditions will be visible.

      <Tabs>
        <Tab title="React / Next.js">
          **Inline Comments Section:**

          ```jsx theme={null}
          <VeltInlineCommentsSection folderId="YOUR_FOLDER_ID" documentId="YOUR_DOCUMENT_ID" locationId="YOUR_LOCATION_ID" context={{ key1: "value1" }} />
          ```

          **Comment Tool - Comment Bubble:**

          ```jsx theme={null}
          <VeltCommentTool folderId="YOUR_FOLDER_ID" documentId="YOUR_DOCUMENT_ID" locationId="YOUR_LOCATION_ID" context={{ key1: "value1" }} />
          <VeltCommentBubble folderId="YOUR_FOLDER_ID" documentId="YOUR_DOCUMENT_ID" locationId="YOUR_LOCATION_ID" context={{ key1: "value1" }} />
          ```

          **Comment Pin:**

          ```jsx theme={null}
          <VeltCommentPin folderId="YOUR_FOLDER_ID" documentId="YOUR_DOCUMENT_ID" locationId="YOUR_LOCATION_ID" context={{ key1: "value1" }} />
          ```
        </Tab>

        <Tab title="Other Frameworks">
          **Inline Comments Section:**

          ```jsx theme={null}
          <velt-inline-comments-section folder-id="YOUR_FOLDER_ID" document-id="YOUR_DOCUMENT_ID" location-id="YOUR_LOCATION_ID" context='{"key1": "value1"}'></velt-inline-comments-section>
          ```

          **Comment Tool - Comment Bubble:**

          ```jsx theme={null}
          <velt-comment-tool folder-id="YOUR_FOLDER_ID" document-id="YOUR_DOCUMENT_ID" location-id="YOUR_LOCATION_ID" context='{"key1": "value1"}'></velt-comment-tool>
          <velt-comment-bubble folder-id="YOUR_FOLDER_ID" document-id="YOUR_DOCUMENT_ID" location-id="YOUR_LOCATION_ID" context='{"key1": "value1"}'></velt-comment-bubble>
          ```

          **Comment Pin:**

          ```jsx theme={null}
          <velt-comment-pin folder-id="YOUR_FOLDER_ID" document-id="YOUR_DOCUMENT_ID" location-id="YOUR_LOCATION_ID" context='{"key1": "value1"}'></velt-comment-pin>
          ```
        </Tab>
      </Tabs>

  * \[**Comments**]: Added support to add context to comment tool in freestyle mode.

  * \[**Core**]: Added window load event for Velt object after it is initialized. This is useful for developers using pure HTML/JS packages.

    ```jsx theme={null}
    window.addEventListener('onVeltLoad', (event) => {
        console.log('onVeltLoad', window.Velt);
    });
    ```

  ### Bug Fixes

  * \[**Comments**]: Fixed issue where bubble count was showing the total comments count instead of the non-terminal state comments count.
  * \[**Comments**]: Fixed issue where area comments were not respecting dom id boundaries.
</Update>

<Update label="4.5.0-beta.40" description="July 03 2025">
  ### New Features

  * \[**Notifications**]: Added support to enable self notifications. By default notifications api and components exclude notifications where the current user is the action user.

      <Tabs>
        <Tab title="React / Next.js">
          **Using props:**

          ```jsx theme={null}
          <VeltNotificationsTool selfNotifications={true} />
          <VeltNotificationsPanel selfNotifications={true} />
          ```

          **Using API:**

          ```jsx theme={null}
          const notificationElement = useNotificationUtils();
          notificationElement.enableSelfNotifications(); // Enables self notifications.
          notificationElement.disableSelfNotifications(); // Disables self notifications.
          ```
        </Tab>

        <Tab title="Other Frameworks">
          **Using attributes:**

          ```html theme={null}
          <velt-notifications-tool self-notifications="true"></velt-notifications-tool>
          <velt-notifications-panel self-notifications="true"></velt-notifications-panel>
          ```

          **Using API:**

          ```jsx theme={null}
          const notificationElement = Velt.getNotificationElement();
          notificationElement.enableSelfNotifications(); // Enables self notifications.
          notificationElement.disableSelfNotifications(); // Disables self notifications.
          ```
        </Tab>
      </Tabs>

  ### Bug Fixes

  * \[**Comments**]: Fixed issue where comment text and HTML content was not being properly stripped during deletion for self-hosted data.
</Update>

<Update label="4.5.0-beta.39" description="July 03 2025">
  ### New Features

  * \[**CRDT**]: Added Yjs based CRDT library (\`@veltdev/tiptap-crdt) for Tiptap Editor (in beta).
    * This enables live cursors and collaborative editing out of the box.
    * This is framework agnostic and can be used with any Tiptap editor.
    * [Learn more](/realtime-collaboration/crdt/setup/tiptap)

  * \[**Video Editor**]: Added zoom button in video editor with [wireframes support](/ui-customization/features/async/recorder/video-editor#addzoombutton).

  * \[**Recorder**]: Added API to turn on/off the microphone on the recorder control panel.

  <Tabs>
    <Tab title="React / Next.js">
      **Using API:**

      ```jsx theme={null}
      const recorderElement = useRecorderUtils();
      recorderElement.enableRecordingMic(); // Enables the microphone.
      recorderElement.disableRecordingMic(); // Disables the microphone.
      ```
    </Tab>

    <Tab title="Other Frameworks">
      **Using API:**

      ```jsx theme={null}
      const recorderElement = Velt.getRecorderElement();
      recorderElement.enableRecordingMic(); // Enables the microphone.
      recorderElement.disableRecordingMic(); // Disables the microphone.
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Video Editor**]: Enabled zoom options dropdown to be positioned at the center of the zoom track.
  * \[**Comments**]: Enabled standalone comment composer width to be set to 100% of the parent container.
</Update>

<Update label="4.5.0-beta.38" description="July 02 2025">
  ### New Features

  * \[**Comments**]: Added reply avatar component with [wireframes support](/ui-customization/features/async/comments/comment-dialog/subcomponents/body/subcomponents/replyavatars). This shows the avatars of unique users who have replied to a comment.

      <Tabs>
        <Tab title="React / Next.js">
          **Using props:**

          ```jsx theme={null}
          <VeltComments maxReplyAvatars={2} replyAvatars={true} />
          ```

          **Using API:**

          ```jsx theme={null}
          const commentsElement = client.getCommentElement();
          commentsElement.enableReplyAvatars(); // Enables the reply avatar component.
          commentsElement.disableReplyAvatars(); // Disables the reply avatar component.
          commentsElement.setMaxReplyAvatars(2); // Sets the maximum number of reply avatars to show.
          ```
        </Tab>

        <Tab title="Other Frameworks">
          **Using props:**

          ```html theme={null}
          <velt-comments max-reply-avatars="2" reply-avatars="true"></velt-comments>
          ```

          **Using API:**

          ```jsx theme={null}
          const commentsElement = Velt.getCommentElement();
          commentsElement.enableReplyAvatars(); // Enables the reply avatar component.
          commentsElement.disableReplyAvatars(); // Disables the reply avatar component.
          commentsElement.setMaxReplyAvatars(2); // Sets the maximum number of reply avatars to show.
          ```
        </Tab>
      </Tabs>
  * \[**Comments**]: Added template variable `totalReplies` for comment wireframes. It displays the total number of replies for a comment.

  ### Bug Fixes

  * \[**Comments**]: Fixed locationName logic to use locationId in sidebar for 'This Page' filter.
  * \[**Comments**]: Fixed "@" dropdown issue where it was not opening after user selection.
</Update>

<Update label="4.5.0-beta.37" description="June 30 2025">
  ### New Features

  * \[**Cursors**]: Added wireframes support for `Cursors` component.
</Update>

<Update label="4.5.0-beta.36" description="June 26 2025">
  ### Improvements

  * \[**Comments**]: Added sidebar filter dropdown into overlays for better handling of screen and UI edges.

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where inline comments section width was not being set correctly.
</Update>

<Update label="4.5.0-beta.35" description="June 25 2025">
  ### New Features

  * \[**Core**]: Added MCP Servers for:
    * **Velt REST APIs**: Allows you to interact with your Velt data directly from various MCP compatible clients, such as Cursor, Windsurf, Claude Desktop, etc. [Learn More](/mcp/mcp).
    * **Velt Docs**: Allows you to search and browse Velt's documentation directly within your MCP-compatible IDEs, like Cursor, Windsurf etc. This enables you to quickly find information about our SDKs, APIs, and features without having to leave your editor, streamlining your development workflow when implementing Velt. [Learn More](/mcp/mcp).

  ### Bug Fixes

  * \[**Comments**]: Minor UX fixes:
    * Fixed an issue where composer auto-scroll was not working in sidebar embed mode.
    * The composer now auto-scrolls to the text cursor when a long message is pasted.
    * Mentions are now added at the cursor's position, and the cursor is placed after the mention, not at the end of the input.

  ### Improvements

  * \[**Comments**]: Comment timestamps now show the created timestamp by default, and the last updated timestamp as fallback.
  * \[**Core**]: Added improved error messages for identify method so it's easier to debug scenarios like domain mismatch, token expired, organization mismatch, missing token etc.
  * \[**Comments**]: Added tooltips to an overlay.
</Update>

<Update label="4.5.0-beta.34" description="June 23 2025">
  ### New Features

  * \[**REST APIs**]: Extended v2 endpoints for all APIs. These come with additional schema validation.
    * The previous v1 endpoints will work as usual.

  ### Bug Fixes

  * \[**Core**]: Fixed an issue where location metadata, reset etc was not working as expected in some scenarios.
</Update>

<Update label="4.5.0-beta.33" description="June 20 2025">
  ### Bug Fixes

  * \[**Comments**]: Minor UX fixes:
    * Fixed mention dropdown opening when typing space at the very start of input.
    * Fixed mention dropdown opening when @ was added at the end of a word. Exceptions: (`,`, `;`, `:`).
    * Updated custom list dropdowns to behave like the default @ dropdown.
    * Fixed `ESC` key not closing the mentions dropdown.
    * When clicking on collapsed composer, it will bring it into view.
    * The composer will auto-scroll to the  text cursor when the inputted text is very long.
    * Comment dialog will come into view when returning from focused thread mode.
    * Fixed an issue where custom filter was getting reset on page refresh.
    * Fixed search placeholder type in React `<VeltCommentsSidebarWireframe.Search placeholder="Search Comments" />`.
    * Fixed composer collapsing when clicking away with text or attachments present - now only collapses when empty.
</Update>

<Update label="4.5.0-beta.32" description="June 19 2025">
  ### New Features

  * \[**Debugger**]: Added [Activity Logs](https://console.velt.dev/dashboard/debugger/activity-logs) to the Console.
    * Review the historical Velt events stream of your users.
    * This can help debug issues, user behaviour on Velt features, etc.
    * Currently supports the last 30 days of events.
    * There is a 24-48 hour delay in the events being shown in the console.

  ### Improvements

  * \[**Comments**]: Improved autoscroll behavior in comment sidebar for new comment additions, comment dialog clicks, and composer clicks.
  * \[**Comments**]: Added `system` type support in `filterConfig` for default filters

  ### Bug Fixes

  * \[**Comments**]: Fixed autocomplete dropdown opening while typing `@` in a word.
  * \[**Comments**]: Fixed autocomplete dropdown not closing after `@` followed by immediate space.
  * \[**Comments**]: Fixed comment sidebar filter type menu closing on outside clicks.
  * \[**Comments**]: Fixed comment sidebar filter search toggle functionality.
</Update>

<Update label="4.5.0-beta.31" description="June 19 2025">
  ### Improvements

  * \[**Comments**]: Added support to aggregate and show comment annotations by `folderId`, `documentId` and `context` in `InlineCommentSection`, `VeltCommentPin`, `VeltCommentTool` and `VeltCommentBubble` components.

    * All the comment annotations matching these props will be aggregated and shown in the component.
    * This will only work when the documents or the relevant folder are initialized first.

      <Tabs>
        <Tab title="React / Next.js">
          **Inline Comments Section:**

          ```jsx theme={null}
          // Filter by folderId
          <VeltInlineCommentsSection folderId="YOUR_FOLDER_ID" />

          // Filter by documentId
          <VeltInlineCommentsSection documentId="YOUR_DOCUMENT_ID" />

          // Filter by context
          <VeltInlineCommentsSection context={{ key1: "value1" }} contextOptions={{ partialMatch: true }} />
          ```

          **Comment Tool (Works only in popover mode). This will attach these props to the new comment annotation created by the tool.**

          ```jsx theme={null}
          // Filter by folderId
          <VeltCommentTool folderId="YOUR_FOLDER_ID" />

          // Filter by documentId
          <VeltCommentTool documentId="YOUR_DOCUMENT_ID" />

          // Filter by context
          <VeltCommentTool context={{ key1: "value1" }} contextOptions={{ partialMatch: true }} />
          ```

          **Comment Bubble:**

          ```jsx theme={null}
          // Filter by folderId
          <VeltCommentBubble folderId="YOUR_FOLDER_ID" />

          // Filter by documentId
          <VeltCommentBubble documentId="YOUR_DOCUMENT_ID" />

          // Filter by context
          <VeltCommentBubble context={{ key1: "value1" }} contextOptions={{ partialMatch: true }} />
          ```

          **Comment Pin:**

          ```jsx theme={null}
          // Filter by folderId
          <VeltCommentPin folderId="YOUR_FOLDER_ID" />

          // Filter by documentId
          <VeltCommentPin documentId="YOUR_DOCUMENT_ID" />

          // Filter by context
          <VeltCommentPin context={{ key1: "value1" }} contextOptions={{ partialMatch: true }} />
          ```
        </Tab>

        <Tab title="Other Frameworks">
          **Inline Comments Section:**

          ```html theme={null}
          <!-- Filter by folderId -->
          <velt-inline-comments-section folder-id="YOUR_FOLDER_ID"></velt-inline-comments-section>

          <!-- Filter by documentId -->
          <velt-inline-comments-section document-id="YOUR_DOCUMENT_ID"></velt-inline-comments-section>

          <!-- Filter by context -->
          <velt-inline-comments-section context='{"key1": "value1"}' context-options='{"partialMatch": true}'></velt-inline-comments-section>
          ```

          **Comment Tool:**

          ```html theme={null}
          <!-- Filter by folderId -->
          <velt-comment-tool folder-id="YOUR_FOLDER_ID"></velt-comment-tool>

          <!-- Filter by documentId -->
          <velt-comment-tool document-id="YOUR_DOCUMENT_ID"></velt-comment-tool>

          <!-- Filter by context -->
          <velt-comment-tool context='{"key1": "value1"}' context-options='{"partialMatch": true}'></velt-comment-tool>
          ```

          **Comment Bubble:**

          ```html theme={null}
          <!-- Filter by folderId -->
          <velt-comment-bubble folder-id="YOUR_FOLDER_ID"></velt-comment-bubble>

          <!-- Filter by documentId -->
          <velt-comment-bubble document-id="YOUR_DOCUMENT_ID"></velt-comment-bubble>

          <!-- Filter by context -->
          <velt-comment-bubble context='{"key1": "value1"}' context-options='{"partialMatch": true}'></velt-comment-bubble>
          ```

          **Comment Pin:**

          ```html theme={null}
          <!-- Filter by folderId -->
          <velt-comment-pin folder-id="YOUR_FOLDER_ID"></velt-comment-pin>

          <!-- Filter by documentId -->
          <velt-comment-pin document-id="YOUR_DOCUMENT_ID"></velt-comment-pin>

          <!-- Filter by context -->
          <velt-comment-pin context='{"key1": "value1"}' context-options='{"partialMatch": true}'></velt-comment-pin>
          ```
        </Tab>
      </Tabs>
</Update>

<Update label="4.5.0-beta.30" description="June 19 2025">
  ### Improvements

  * \[**Notifications**]: Modified `getSettings` in notifications from a one-time call to a subscription and added a new hook for it.

      <Tabs>
        <Tab title="React / Next.js">
          **Using Hook:**

          ```jsx theme={null}
          const { setSettingsInitialConfig, setSettings, settings } = useNotificationSettings();
          // setSettingsInitialConfig will set the default settings for the notifications.
          // setSettings will update the settings for the notifications in the server.
          // settings will return the current settings for the notifications. Initially it will be null and will be updated when the settings are fetched.
          ```

          **Using API:**

          ```jsx theme={null}
          const notificationsElement = client.getNotificationElement();
          notificationsElement.getSettings().subscribe((settings) => {
            console.log('current settings are', settings);
          });
          ```
        </Tab>

        <Tab title="Other Frameworks">
          **Using API:**

          ```jsx theme={null}
          const notificationsElement = Velt.getNotificationElement();
          notificationsElement.getSettings().subscribe((settings) => {
            console.log('current settings are', settings);
          });
          ```
        </Tab>
      </Tabs>

  * \[**Documents**]: Added support for `folderId` in `updateDocuments` method.

      <Tabs>
        <Tab title="React / Next.js">
          ```jsx theme={null}
          await client.updateDocuments({
            organizationId: 'ORGANIZATION_ID',
            folderId: 'FOLDER_ID',
            documents: [
              {
                documentId: 'DOCUMENT_ID',
              }
            ]
          });
          ```
        </Tab>

        <Tab title="Other Frameworks">
          ```jsx theme={null}
          await Velt.updateDocuments({
            organizationId: 'ORGANIZATION_ID',
            folderId: 'FOLDER_ID',
            documents: [
              {
                documentId: 'DOCUMENT_ID',
              }
            ]
          });
          ```
        </Tab>
      </Tabs>
</Update>

<Update label="4.5.0-beta.29" description="June 18 2025">
  ### Bug Fixes

  * \[**UI Customization**]: Fixed an issue where the internal state for User variable was not being cleaned up in Velt If component.
</Update>

<Update label="4.5.0-beta.28" description="June 17 2025">
  ### Improvements

  * \[**Comments**]: Added support for multiple text format selection and multiple paragraphs selection in [tiptap-velt-comments](https://www.npmjs.com/package/@veltdev/tiptap-velt-comments).

  ### Bug Fixes

  * \[**Comments**]: Reverted back sidebar filter panel default layout to checkbox from dropdown.
</Update>

<Update label="4.5.0-beta.27" description="June 17 2025">
  ### Improvements

  * \[**Comments**]: Added default value for sidebar filter search input.
  * \[**Recorder**]: Updated the video editor apply button behavior. Now it will always be enabled whether or not the user edited the video.
  * \[**Comments**]: Added ability to add custom filters via `FilterConfig`.

    1. First enable custom actions.
    2. Add custom filters in filter config.
    3. Add [custom filters wireframe](/ui-customization/features/async/comments/comments-sidebar/subcomponents/filter/subcomponents/custom) to the sidebar wireframe.
    4. Add callbacks to update sidebar data when the filters are used.

      <Tabs>
        <Tab title="React / Next.js">
          **1. Enable Custom Actions:**

          ```jsx theme={null}
          <VeltCommentsSidebar customActions={true} />
          ```

          **2. Add custom filters in filter config:**

          ```jsx expandable lines theme={null}
          const filterConfig = {
            location: {
              name: 'Pages',
              enable: true,
              multiSelection: true,
              enableGrouping: true,
              placeholder: 'Search pages',
            },
            // ... Remaining filters
            deviceType: {  // Custom Filter 1
              name: 'Device Type',
              enable: true,
              multiSelection: true,
              enableGrouping: false,
              placeholder: 'Search device type',
              id: 'deviceType',
              type: 'custom',
              options: [
                {
                  id: 'desktop',
                  name: 'Desktop',
                },
                {
                  id: 'mobile',
                  name: 'Mobile',
                },
                {
                  id: 'tablet',
                  name: 'Tablet',
                },
              ]
            },
            otherCustomFilter: { // Custom Filter 2
              name: 'Other Custom Filter',
              enable: true,
              multiSelection: false,
              enableGrouping: false,
              placeholder: 'Search any field',
              id: 'otherCustomFilter',
              type: 'custom',
              options: [
                {
                  id: 'field1',
                  name: 'Field 1',
                },
                {
                  id: 'field2',
                  name: 'Field 2',
                },
                {
                  id: 'field3',
                  name: 'Field 3',
                },
                {
                  id: 'field4',
                  name: 'Field 4',
                },
                {
                  id: 'field5',
                  name: 'Field 5',
                },
              ]
            },
          };

          <VeltCommentsSidebar 
            customActions={true}
            filterConfig={filterConfig}
          />
          ```

          **3. Add [custom filters wireframe](/ui-customization/features/async/comments/comments-sidebar/subcomponents/filter/subcomponents/custom) for each custom filter you added in filter config:**

          ```jsx theme={null}
          <VeltCommentsSidebarFilterWireframe>
            <VeltCommentsSidebarWireframe.Filter.Custom id='deviceType' />
            <VeltCommentsSidebarWireframe.Filter.Custom id='otherCustomFilter' />
            {/* ... remaining filters */}
          </VeltCommentsSidebarFilterWireframe>
          ```

          **4. Add callbacks to update sidebar data when the filters are used:**

          * The following callbacks will contain the `customFilters` field with the custom filter id and its options indicating which options are selected:
          * `commentSidebarDataUpdate`
          * `commentSidebarDataInit`
          * `veltButtonClick`

          ```jsx theme={null}
            const commentElement = client.getCommentElement();
            
            // Button click callback
            client.on('veltButtonClick').subscribe(contextData => {
              console.log('veltButtonClick', contextData);
            });

            // Sidebar data callbacks
            commentElement.on('commentSidebarDataUpdate').subscribe((contextData) => {
              console.log('commentSidebarDataUpdate', contextData);
            });

            commentElement.on('commentSidebarDataInit').subscribe((contextData) => {
              console.log('commentSidebarDataInit', contextData);
            });
          ```
        </Tab>

        <Tab title="Other Frameworks">
          **1. Enable Custom Actions:**

          ```html theme={null}
          <velt-comments-sidebar custom-actions="true"></velt-comments-sidebar>
          ```

          **2. Add Custom Filters:**

          ```javascript expandable lines theme={null}
          const filterConfig = {
            location: {
              name: 'Pages',
              enable: true,
              multiSelection: true,
              enableGrouping: true,
              placeholder: 'Search pages',
            },
            // ... other default filters
            deviceType: {  // Custom Filter 1
              name: 'Device Type',
              enable: true,
              multiSelection: true,
              enableGrouping: false,
              placeholder: 'Search device type',
              id: 'deviceType',
              type: 'custom',
              options: [
                {
                  id: 'desktop',
                  name: 'Desktop',
                },
                {
                  id: 'mobile',
                  name: 'Mobile',
                },
                {
                  id: 'tablet',
                  name: 'Tablet',
                },
              ]
            },
            anyField: { // Custom Filter 2
              name: 'Any Field',
              enable: true,
              multiSelection: false,
              enableGrouping: false,
              placeholder: 'Search any field',
              id: 'anyField',
              type: 'custom',
              options: [
                {
                  id: 'field1',
                  name: 'Field 1',
                },
                {
                  id: 'field2',
                  name: 'Field 2',
                },
                {
                  id: 'field3',
                  name: 'Field 3',
                },
                {
                  id: 'field4',
                  name: 'Field 4',
                },
                {
                  id: 'field5',
                  name: 'Field 5',
                },
              ]
            },
          };

          const commentsSidebar = document.querySelector(`velt-comments-sidebar`);
          commentsSidebar?.setAttribute("filter-config", JSON.stringify(filterConfig));
          ```

          **3. Add custom filters wireframe to the sidebar wireframe:**

          ```html theme={null}
          <velt-comments-sidebar-filter-wireframe>
            <velt-comments-sidebar-filter-custom-wireframe id="deviceType"></velt-comments-sidebar-filter-custom-wireframe>
            <velt-comments-sidebar-filter-custom-wireframe id="otherCustomFilter"></velt-comments-sidebar-filter-custom-wireframe>
            <!-- ... remaining filters -->
          </velt-comments-sidebar-filter-wireframe>
          ```

          **4. Add callbacks to update sidebar data when the filters are used:**

          ```javascript theme={null}
          const commentElement = Velt.getCommentElement();

          // Button click callback
          client.on('veltButtonClick').subscribe(contextData => {
            console.log('veltButtonClick', contextData);
          });

          // Sidebar data callbacks
          commentElement.on('commentSidebarDataUpdate').subscribe((contextData) => {
            console.log('commentSidebarDataUpdate', contextData);
          });

          commentElement.on('commentSidebarDataInit').subscribe((contextData) => {
            console.log('commentSidebarDataInit', contextData);
          });
          ```
        </Tab>
      </Tabs>
</Update>

<Update label="4.5.0-beta.26" description="June 13 2025">
  ### Improvements

  * \[**Comments**]: Renamed `groupMultipleMatch` config to `groupMatchedComments` config for grouping multiple comment annotations in Comment Bubble component when multiple annotations match the provided `context` or `targetElementId`. The old config is still supported.

    * Default: `false`

      <Tabs>
        <Tab title="React / Next.js">
          **Using Props:**

          ```jsx theme={null}
          <VeltComments groupMatchedComments={true} />
          ```

          **Using API:**

          ```jsx theme={null}
          const commentElement = client.getCommentElement();
          commentElement.enableGroupMatchedComments();
          commentElement.disableGroupMatchedComments();
          ```
        </Tab>

        <Tab title="Other Frameworks">
          **Using Props:**

          ```html theme={null}
          <velt-comments group-matched-comments="true"></velt-comments>
          ```

          **Using API:**

          ```jsx theme={null}
          const commentElement = Velt.getCommentElement();
          commentElement.enableGroupMatchedComments();
          commentElement.disableGroupMatchedComments();
          ```
        </Tab>
      </Tabs>
</Update>

<Update label="4.5.0-beta.25" description="June 13 2025">
  ### New Features

  * \[**Presence**]: Added wireframes support for `Presence` component.
</Update>

<Update label="4.5.0-beta.24" description="June 13 2025">
  ### Improvements

  * \[**Comments**]: Added support for setting custom filter placeholders through `filterConfig`. This is used when `filterOptionLayout` is set to `dropdown`.

      <Tabs>
        <Tab title="React / Next.js">
          ```jsx theme={null}
          const filterConfig = {
            location: {
              name: 'Pages',
              enable: true,
              placeholder: 'Custom Location'
            },
            document: {
              name: 'Documents',
              enable: true,
              placeholder: 'Custom Document'
            }
          };

          <VeltCommentsSidebar filterConfig={filterConfig} />
          ```
        </Tab>

        <Tab title="Other Frameworks">
          ```js theme={null}
          const filterConfig = {
            location: {
              name: 'Pages',
              enable: true,
              placeholder: 'Custom Location'
            },
            document: {
              name: 'Documents',
              enable: true,
              placeholder: 'Custom Document'
            }
          };
          const commentsSidebar = document.querySelector(`velt-comments-sidebar`);
          commentsSidebar?.setAttribute("filter-config", JSON.stringify(filterConfig));
          ```
        </Tab>
      </Tabs>

  * \[**Comments**]: Added a `filteredCommentAnnotationsCount` template variable for visible comments in sidebar when a filter is applied.

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where the assign input was not closing when clicked outside in the sidebar.
  * \[**Comments**]: Fixed an issue where the reaction panel tool was getting hidden when hovered out.
  * \[**Comments**]: Fixed an issue where users set through `updateContactList` were not visible in tagged and assigned filters.
</Update>

<Update label="4.5.0-beta.23" description="June 12 2025">
  ### New Features

  * \[**Comments**]: Added support for grouping multiple comment annotations in Comment Bubble component when multiple annotations match the provided `context` or `targetElementId`

    * Default: `false`

      <Tabs>
        <Tab title="React / Next.js">
          **Using Props:**

          ```jsx theme={null}
          <VeltComments groupMultipleMatch={true} />
          ```

          **Using API:**

          ```jsx theme={null}
          const commentElement = client.getCommentElement();
          commentElement.enableGroupMultipleMatch();
          commentElement.disableGroupMultipleMatch();
          ```
        </Tab>

        <Tab title="Other Frameworks">
          **Using Props:**

          ```html theme={null}
          <velt-comments group-multiple-match="true"></velt-comments>
          ```

          **Using API:**

          ```jsx theme={null}
          const commentElement = Velt.getCommentElement();
          commentElement.enableGroupMultipleMatch();
          commentElement.disableGroupMultipleMatch();
          ```
        </Tab>
      </Tabs>
</Update>

<Update label="4.5.0-beta.22" description="June 12 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed an issue that happened on sidebar where the recording service got into a bad state when the user cancelled the recording.
</Update>

<Update label="4.5.0-beta.21" description="June 11 2025">
  ### Improvements

  * \[**Comments**]: Added support for `filterCommentsOnDom` when custom sidebar filters are configured.
  * \[**Comments**]: Added additional testIds in following components:
    * Message input (element with class `velt-composer-input--message`)
    * Container for author (element with class `velt-thread-card--author`)
    * Confirmation dialog (element with class `velt-confirm-dialog`)
    * Velt buttons (elements with class `velt-button`)
  * \[**Comments**]: Removed quotes from the display message when `notificationSource` is `custom`.
</Update>

<Update label="4.5.0-beta.20" description="June 10 2025">
  ### Improvements

  * \[**Core**]: Added `unsetLocationsIds` method to unset locations by passing location IDs as parameters

    ```jsx theme={null}
    client.unsetLocationsIds(['location1', 'location2', 'location3'])
    ```
</Update>

<Update label="4.5.0-beta.19" description="June 9 2025">
  ### Improvements

  * \[**Core**]: Improved SDK initialization layer and added new core methods to improve developer experience:

    * Added `rootDocumentId` param in `setDocuments` method to specify which document should act as root. By default 1st document will be set as root document unless `rootDocumentId` is specified.

    ```jsx theme={null}
    client.setDocuments([{id:'doc1'},{id:'doc2'}], {rootDocumentId:'doc2'})
    ```

    * Added `setRootDocument` method to set a different document as root. If user has passed multiple documents and wants to switch the root document:

    ```jsx theme={null}
    client.setRootDocument({id:'doc2'})
    // There won't be any change in the other documents internally. They will remain as is.
    ```

    * Added `setLocations` method to add multiple locations:

    ```jsx theme={null}
    client.setLocations([
      {id:'location1', locationName:'location1'},
      {id:'location2', locationName:'location2'}
    ], {rootLocationId: 'location2'})
    // By default 1st location will be set as root location unless rootLocationId is specified.

    // If User wants to append new locations then 'appendLocation' flag needs to be passed.
    client.setLocations([
      {id:'location3', locationName:'location3'},
      {id:'location4', locationName:'location4'}
    ], {appendLocation: true})
    ```

    * Added `setRootLocation` method to set a different location as root:

    ```jsx theme={null}
    client.setRootLocation({id:'location3', locationName:'location3'})
    // There won't be any change in the other locations internally. They will remain as is.
    ```

    * Added `removeLocations` method to remove multiple locations:

    ```jsx theme={null}
    client.removeLocations(
      {id:'location3', locationName:'location3'},
      {id:'location4', locationName:'location4'}
    )
    ```

    * Most init methods now return promises:
      * `await setDocuments`
      * `await setDocument`
      * `await setDocumentId`
      * `await setRootDocument`
      * `await setLocation`
      * `await setLocations`
      * `await setRootLocation`

    * Added a listener event on `ON` method to subscribe to init changes:

    ```jsx theme={null}
    Velt.on('initUpdate').subscribe((e) => console.log('New init event', e))
    ```

    * Most Analytics events now trigger a common naming pattern:
      * `setDocumentsTriggered`
      * `setRootDocumentTriggered`
      * `unsetDocumentsTriggered`
      * `setLocationsTriggered`
      * `setRootLocationTriggered`
      * `removeLocationsTriggered`
      * `setDocumentsSuccess`
      * `unsetDocumentsSuccess`
      * `setLocationsSuccess`
      * `removeLocationsSuccess`
</Update>

<Update label="4.5.0-beta.18" description="June 9 2025">
  ### New Features

  * \[**Self-hosting**]: Added support to disable getting user resolver requests for organization, document and folder users. Helps optimize performance by avoiding unnecessary user data requests
    * Sometimes you may have a lot of users within your organization, document or folder. In such cases, you may want to disable user resolver requests for organization, document and folder users and instead use [custom autocomplete feature](/async-collaboration/comments/customize-behavior#customautocompletesearch).
    * Learn more about [user data provider](/self-host-data/users)

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx {19-29} expandable lines theme={null}
      const formatUsersToRecord = (users) => {
          // Format users array into a Record object with userId as key and user data as value
          return users.reduce((record, user) => {
              record[user.userId] = {
                  userId: user.userId,
                  name: user.name,
                  // any other fields
              };
              return record;
          }, {});
      };

      const fetchUsersFromDB = async (userIds) => {
          // Fetch users from your DB
          const usersData = await __getUsersFromYourDB__(userIds);
          return formatUsersToRecord(usersData);
      };

      const userDataProvider: UserDataProvider = {
          get: fetchUsersFromDB,
          config: {
              resolveUsersConfig: {
                  organization: false, // Disable organization user requests
                  folder: false, // Disable folder user requests
                  document: true // Enable document user requests
              }
          }
      };

      <VeltProvider 
          apiKey='YOUR_API_KEY'
          dataProviders={{
              user: userDataProvider
          }}
      >
      </VeltProvider>

      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js {19-28} expandable lines theme={null}
      const formatUsersToRecord = (users) => {
          // Format users array into a Record object with userId as key and user data as value
          return users.reduce((record, user) => {
              record[user.userId] = {
                  userId: user.userId,
                  name: user.name,
                  // any other fields
              };
              return record;
          }, {});
      };

      const fetchUsersFromDB = async (userIds) => {
          // Fetch users from your DB
          const usersData = await __getUsersFromYourDB__(userIds);
          return formatUsersToRecord(usersData);
      };

      const userDataProvider = {
          get: fetchUsersFromDB,
          config: {
              resolveUsersConfig: {
                  organization: false, // Disable organization user requests
                  folder: false, // Disable folder user requests
                  document: true // Enable document user requests
              }
          }
      };

      Velt.setDataProviders({
          user: userDataProvider
      });
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.5.0-beta.17" description="June 9 2025">
  ### New Features

  * \[**Comments**]: Added custom metadata support for comment tool and comment bubble components.
    * Works only with `popover` mode comments. Perfect for complex tables with filtering and segmentation needs.
    * Set flexible comment anchoring and filtering logic at the cell level using key-value pairs.
    * **Supports aggregate views:** Eg: comments added in day view can appear in week/month views automatically.
    * **Two new props:**
      * `context`: key-value object for metadata
      * `contextOptions`: matching behavior (default: full match, or set `partialMatch: true` for flexible matching)
    * **How Partial Match Works:**
      * A comment will match if ALL provided filter criteria exist in the comment's context
      * Extra fields in the comment's context don't prevent matching
      * Missing fields in the comment's context prevent matching
      * Example: Comment has `{ day: "01", week: "01", month: "jan", product: "cheese", location: "zurich" }`
        * Filter `{ day: "01", product: "cheese" }` → ✅ matches (both fields exist in comment)
        * Filter `{ day: "01", category: "dairy" }` → ❌ no match (category doesn't exist in comment)
    * **Partial Match Examples:**

      * Comment has `{ day: "01", week: "01", month: "jan", product: "cheese" }`
      * Filter with `{ day: "01", week: "01", month: "jan", product: "cheese" }` → matches (full)
      * Filter with `{ week: "01", month: "jan", product: "cheese" }` → matches (partial)
      * Filter with `{ day: "01", week: "01", month: "jan", product: "cheese", location: "zurich" }` → no match

        <Tabs>
          <Tab title="React / Next.js">
            ```jsx theme={null}
            <VeltCommentTool context={{ 'key1': 'value1', 'key2': 'value2' }} />
            // Full match
            <VeltCommentBubble context={{ 'key1': 'value1', 'key2': 'value2' }} />
            // Partial match
            <VeltCommentBubble context={{ 'key1': 'value1' }} contextOptions={{ partialMatch: true }} />
            ```
          </Tab>

          <Tab title="Other Frameworks">
            ```html theme={null}
            <velt-comment-tool context='{"key1": "value1", "key2": "value2"}'></velt-comment-tool>

            <!-- Full match -->
            <velt-comment-bubble context='{"key1": "value1", "key2": "value2"}'></velt-comment-bubble>
            <!-- Partial match -->
            <velt-comment-bubble context='{"key1": "value1"}' context-options='{"partialMatch": true}'></velt-comment-bubble>
            ```
          </Tab>
        </Tabs>
</Update>

<Update label="4.5.0-beta.16" description="June 5 2025">
  ### Bug Fixes

  * \[**Recorder**]: Fixed an issue where sometimes the recorder service would not update the saved file url after the processing was completed due to a race condition.
</Update>

<Update label="4.5.0-beta.15" description="June 5 2025">
  ### New Features

  * \[**Comments**]: Added ability to filter out comments in the DOM when they are filtered in the sidebar.
    * When the sidebar is closed (default mode) or unmounted (embed mode), the DOM filter will be removed.
    * Default: `false`

        <Tabs>
          <Tab title="React / Next.js">
            **Using Props:**

            ```jsx theme={null}
            <VeltComments filterCommentsOnDom={true} />
            ```

            **Using API:**

            ```javascript theme={null}
            const commentElement = client.getCommentElement();
            commentElement.enableFilterCommentsOnDom();
            commentElement.disableFilterCommentsOnDom();
            ```
          </Tab>

          <Tab title="Other Frameworks">
            **Using Props:**

            ```html theme={null}
            <velt-comments filter-comments-on-dom="true"></velt-comments>
            ```

            **Using API:**

            ```js theme={null}
            const commentElement = Velt.getCommentElement();
            commentElement.enableFilterCommentsOnDom();
            commentElement.disableFilterCommentsOnDom();
            ```
          </Tab>
        </Tabs>
</Update>

<Update label="4.5.0-beta.14" description="June 4 2025">
  ### New Features

  * \[**Notifications**]: Added notification settings feature to allow users to configure their notification preferences.
    * Enable this feature in the [Velt Console](https://console.velt.dev/dashboard/config/notification).
    * Then enable settings on the notifications tool or panel in the UI. [Learn more](/async-collaboration/notifications/customize-behavior#enablesettings)

        <Tabs>
          <Tab title="React / Next.js">
            ```jsx theme={null}
            // You can enable this on either the tool or the panel
            <VeltNotificationsTool settings={true} />
            <VeltNotificationsPanel settings={true} />
            ```
          </Tab>

          <Tab title="Other Frameworks">
            ```html theme={null}
            <!-- You can enable this on either the tool or the panel -->
            <velt-notifications-tool settings="true"></velt-notifications-tool>
            <velt-notifications-panel settings="true"></velt-notifications-panel>
            ```
          </Tab>
        </Tabs>
    * Configure default settings with `setSettingsInitialConfig()` API and extend it to add more channels where you intend to send notifications to your users. [Learn more](/async-collaboration/notifications/customize-behavior#setsettingsinitialconfig)
    * Update settings programmatically with `setSettings()` API. [Learn more](/async-collaboration/notifications/customize-behavior#setsettings)
    * Get current settings with `getSettings()` API. [Learn more](/async-collaboration/notifications/customize-behavior#getsettings)
    * Subscribe to settings updates with `settingsUpdated` event. [Learn more](/async-collaboration/notifications/customize-behavior#on)
    * Added wireframe components for notifications panel settings UI. [Learn more](/ui-customization/features/async/notifications/notifications-panel#settings)
    * Added Backend APIs to set and get notifications settings. [Learn more](/api-reference/rest-apis/v2/notifications/set-config)

  ### Improvements

  * \[**DevTools**]: Exposed more events and improved the event stream ordering. The latest version is `1.1.6`
  * \[**Recorder**]: Added `transcription` field to `RecorderDataAsset`.
    ```typescript theme={null}
    class RecorderDataAsset {
      // ...
      transcription: RecorderDataTranscription;
      // ...
    }
    ```

  ### Bug Fixes

  * \[**Recorder**]: Fixed an issue where the mini player wouldn't play or pause the video on click.
  * \[**Recorder**]: Fixed an issue where the mini player was not playing the latest edited version of the video.
  * \[**Recorder**]: Fixed the alignment of the play button in the mini player.
  * \[**Recorder**]: Fixed the responsive behavior of the expanded player.
  * \[**Comments**]: Fixed an issue in composer wireframe where clicking on attachments, recordings, avatar components inside the composer was closing the composer.
</Update>

<Update label="4.5.0-beta.13" description="May 30 2025">
  ### Bug Fixes

  * \[**Comments**]: Reopen the resolved thread if someone replies.
</Update>

<Update label="4.5.0-beta.12" description="May 29 2025">
  ### New Features

  * \[**Recorder**]: Added a feature to download the latest version of a recording.
    * It's available in the UI by default. Wireframe added.
    * Added an API method to trigger download programmatically:

        <Tabs>
          <Tab title="React / Next.js">
            ```js theme={null}
            const recorderElement = client.getRecorderElement();
            await recorderElement.downloadLatestVideo('RECORDER_ID');
            ```
          </Tab>

          <Tab title="Other Frameworks">
            ```js theme={null}
            const recorderElement = Velt.getRecorderElement();
            await recorderElement.downloadLatestVideo('RECORDER_ID');
            ```
          </Tab>
        </Tabs>

  ### Improvements

  * \[**Recorder**]: Changed the background of removed video segments to a diagonal stripe pattern to clearly indicate removal (instead of waveform/thumbnails).
  * \[**Recorder**]: Added a center focal point to the zoom selection rectangle for better UX.
  * \[**Recorder**]: Added Edit button Wireframe in the recorder player.

  ### Bug Fixes

  * \[**Recorder**]: Implemented several UX fixes for the video editor:
    * Maintained correct aspect ratio for the zoom selection rectangle during resizing.
    * Ensured the zoom selection rectangle maintains its original position while resizing with aspect ratio locked.
    * Ensured video preview displays correct content at responsive widths.
    * Prevented the zoom selection rectangle from moving outside the video content area.
    * Corrected corner dragging behavior to ensure the zoom selection stays within boundaries.
    * Fixed an issue where a small zoom selection at the boundary would go out of bounds when decreasing scale.
    * Updated `recorderTime.duration` logic to store precise millisecond values.
    * Resolved an issue where dragging the trim/scale handler during video playback affected both operations simultaneously.
    * Reduced the drag threshold for improved responsiveness of drag operations.
  * \[**Recorder**]: Fixed an issue where playback on the mini video player would not stop when the video player was expanded.
</Update>

<Update label="4.5.0-beta.11" description="May 29 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where folderId was getting unset when switching between documents too quickly.
</Update>

<Update label="4.5.0-beta.10" description="May 29 2025">
  ### Improvements

  * \[**Comments**]: Render default comment sidebar only when it is opened. Note this is not applicable for sidebar in embed mode.
  * \[**Comments**]: Added a dynamic class for unread comment annotation in comment pin component: `velt-comment-pin-unread-comment`.
</Update>

<Update label="4.5.0-beta.9" description="May 28 2025">
  ### New Features

  * \[**Presence**]: Added event to track changes in user's presence state: `online`, `offline`, `away`.

  <Tabs>
    <Tab title="React / Next.js">
      **Using Hook:**

      ```jsx theme={null}
      const userStateChangeEventData = usePresenceEventCallback('userStateChange');

      useEffect(() => {
          if (userStateChangeEventData) {
              console.log('userStateChange: ', userStateChangeEventData);
          }
      }, [userStateChangeEventData]);
      ```

      **Using API:**

      ```ts theme={null}
      const presenceElement = client.getPresenceElement();
      presenceElement.on("userStateChange").subscribe((data: PresenceUserStateChangeEvent) => {
          console.log("userStateChange", data);
      });
      ```

      ```ts theme={null}
      export interface PresenceUserStateChangeEvent {
          user: PresenceUser; // Object containing user details
          state: string;      // New state of the user, e.g., 'online', 'away', 'offline'
      };
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```ts theme={null}
      const presenceElement = Velt.getPresenceElement();
      presenceElement.on("userStateChange").subscribe((data: PresenceUserStateChangeEvent) => {
          console.log("userStateChange", data);
      });
      ```
    </Tab>
  </Tabs>

  * \[**Presence**]: Added api and hook to fetch presence data with query filters.

  <Tabs>
    <Tab title="React / Next.js">
      **Using Hook:**

      ```jsx theme={null}
      // Fetch online users
      const onlineUsersPresenceData = usePresenceData({ statuses: ['online'] });
      useEffect(() => {
          if (onlineUsersPresenceData && onlineUsersPresenceData.data) {
              console.log('Presence data (online users): ', onlineUsersPresenceData.data);
          }
      }, [onlineUsersPresenceData]);

      // Fetch all users (no query)
      const allUsersPresenceData = usePresenceData();
      useEffect(() => {
          if (allUsersPresenceData && allUsersPresenceData.data) {
              console.log('Presence data (all users): ', allUsersPresenceData.data);
          }
      }, [allUsersPresenceData]);
      ```

      **Using API:**

      ```ts theme={null}
      const presenceElement = client.getPresenceElement();
      // Fetch online users
      presenceElement.getData({ statuses: ['online'] }).subscribe((response: GetPresenceDataResponse) => {
          console.log("Presence data (online users): ", response.data);
      });

      // Fetch all users (no query)
      presenceElement.getData().subscribe((response: GetPresenceDataResponse) => {
          console.log("Presence data (all users): ", response.data);
      });
      ```

      ```ts theme={null}
      PresenceRequestQuery {
          documentId?: string;
          organizationId?: string;
          statuses?: string[]; // Filter by statuses, e.g., ['online', 'away', 'offline']
      }

      GetPresenceDataResponse {
          data: PresenceUser[] | null; // Array of PresenceUser objects or null
      }
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```ts theme={null}
      const presenceElement = Velt.getPresenceElement();
      // Fetch online users
      presenceElement.getData({ statuses: ['online'] }).subscribe((response: GetPresenceDataResponse) => {
          console.log("Presence data (online users): ", response.data);
      });

      // Fetch all users (no query)
      presenceElement.getData().subscribe((response: GetPresenceDataResponse) => {
          console.log("Presence data (all users): ", response.data);
      });
      ```

      ```ts theme={null}
      PresenceRequestQuery {
          documentId?: string;
          organizationId?: string;
          statuses?: string[]; // Filter by statuses, e.g., ['online', 'away', 'offline']
      }

      GetPresenceDataResponse {
          data: PresenceUser[] | null; // Array of PresenceUser objects or null
      }
      ```
    </Tab>
  </Tabs>

  * \[**Workspace**]: Added API to add and delete domains to the allowed domains list. [Learn more](/api-reference/rest-apis/v2/workspace/add-domain)
</Update>

<Update label="4.5.0-beta.8" description="May 27 2025">
  ### New Features

  * \[**Comments**]: Added a new `Document Filter Dropdown` component to the Comment Sidebar. This feature allows users to filter comments based on documents.
    * By default, this filter is disabled. You need to enable it in filter config.
    * This works when you are using multiple documents or folders.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
        const filterConfig = {
          document: {
            enable: true,
            name: "Documents", // Optional: Customize the display name of the filter
            enableGrouping: true, // Optional: Enable grouping of documents
            multiSelection: true, // Optional: Allow multiple documents to be selected
          }
        };

        <VeltCommentsSidebar filterConfig={filterConfig} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      const filterConfig = {
        document: {
          enable: true,
          name: "Documents", // Optional: Customize the display name of the filter
          enableGrouping: true, // Optional: Enable grouping of documents
          multiSelection: true, // Optional: Allow multiple documents to be selected
        }
      };
      const commentsSidebar = document.querySelector(`velt-comments-sidebar`);
      commentsSidebar?.setAttribute("filter-config", JSON.stringify(filterConfig));
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.5.0-beta.7" description="May 23 2025">
  ### Improvements

  * \[**Comments**]: Added support to add `context` in `Velt Comment Tool` component as well. Previously, context for comments could only be added via event callbacks or APIs. With this update, you can now predefine context directly within the `Velt Comment Tool` component itself. Currently, this feature is specific to popover comments, allowing you to, for example, assign unique context to each cell in a table.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltCommentTool targetElementId="elementId" context={{ key1: 'value1' }} />
      ```
    </Tab>

    <Tab title="HTML">
      ```html theme={null}
      <velt-comment-tool target-element-id="elementId" context='{"key1": "value1"}'></velt-comment-tool>
      ```
    </Tab>
  </Tabs>

  * \[**Recorder**]: Enhanced error handling for the recorder by introducing a new `RecordingErrorEvent` event. It will be triggered when the following errors occur:
    * `transcriptionFailed`: When transcription fails.
    * `editFailed`: When a video edit operation fails.
    * `recordingFailed`: When a recording fails.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Hook
      const recorderErrorEvent = useRecorderEventCallback('error');
      useEffect(() => {
        if (recorderErrorEvent) {
            if (recorderErrorEvent.type === 'transcriptionFailed') {
                console.error('Transcription failed:', recorderErrorEvent);
            } else if (recorderErrorEvent.type === 'editFailed') {
                console.error('Edit failed:', recorderErrorEvent);
            } else if (recorderErrorEvent.type === 'recordingFailed') {
                console.error('Recording failed:', recorderErrorEvent);
            }
        }
      }, [recorderErrorEvent]);

      // API Method
      const recorderElement = client.getRecorderElement();
      recorderElement.on('error').subscribe((event) => {
          if (event.type === 'transcriptionFailed') {
              console.error('Transcription failed:', event);
          } else if (event.type === 'editFailed') {
              console.error('Edit failed:', event);
          } else if (event.type === 'recordingFailed') {
              console.error('Recording failed:', event);
          }
      });

      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      const recorderElement = Velt.getRecorderElement();
      recorderElement.on('error').subscribe((event) => {
          if (event.type === 'transcriptionFailed') {
              console.error('Transcription failed:', event);
          } else if (event.type === 'editFailed') {
              console.error('Edit failed:', event);
          } else if (event.type === 'recordingFailed') {
              console.error('Recording failed:', event);
          }
      });
      ```
    </Tab>
  </Tabs>

  * \[**Recorder**]: Added `RecordingSaveInitiatedEvent` event. This event is dispatched before the actual save operation begins for original or edited recording.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Using the hook
      const recordingSaveInitiatedEvent = useRecorderEventCallback('recordingSaveInitiated');

      useEffect(() => {
        if (recordingSaveInitiatedEvent) {
          if (recordingSaveInitiatedEvent.type === 'edit') {
            console.log('Edited recording save initiated);
          } else {
            console.log('New recording save initiated.');
          }
        }
      }, [recordingSaveInitiatedEvent]);

      // Using the API method
      const recorderElement = client.getRecorderElement(); 

      recorderElement.on('recordingSaveInitiated').subscribe((event) => {
        if (event.type === 'edit') {
          console.log('Edited recording save initiated');
        } else {
          console.log('New recording save initiated');
        }
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      const recorderElement = Velt.getRecorderElement();

      recorderElement.on('recordingSaveInitiated').subscribe((event) => {
        if (event.type === 'edit') {
          console.log('Edited recording save initiated');
        } else {
          console.log('New recording save initiated.');
        }
      });
      ```
    </Tab>
  </Tabs>

  * \[**Recorder**]: Changed background color for video in the editor to gray when the editor is resized to a smaller size.
  * \[**Recorder**]: Video playback now stops upon reaching the end and the player state is reset.
  * \[**Recorder**]: Improved type for the legacy `onRecordedData` callback.
</Update>

<Update label="4.5.0-beta.6" description="May 22 2025">
  ### Bug Fixes

  * \[**Single Editor Mode**]: Fixed an issue where the editor sometimes lost edit access when opening the document in another tab when additional users were also present in the document.
</Update>

<Update label="4.5.0-beta.5" description="May 22 2025">
  ### Improvements

  * \[**Recorder**]: Added wireframes for Timeline and Zoom feature.
</Update>

<Update label="4.5.0-beta.4" description="May 22 2025">
  ### Features

  * \[**SDK**]: Added `apiProxyDomain` support, allowing Velt API calls to be proxied through your own domain. [Learn more](/security/proxy-server#apihost).

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltProvider
        config={{
            apiProxyDomain: 'https://api.yourdomain.com'
        }}
      ></VeltProvider>
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```jsx theme={null}
       const client = await initVelt('YOUR_API_KEY', {
         apiProxyDomain: 'https://api.yourdomain.com'
       });
      ```
    </Tab>
  </Tabs>

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where Thread Card Dropdown Options: Delete Thread and Delete Comment button wireframes text was not updated correctly.
</Update>

<Update label="4.5.0-beta.3" description="May 21 2025">
  ### Improvements

  * \[**Recorder**]: Improved the post processing speed for zoom in effect by 90%.
  * \[**Recorder**]: Added configuration API to specify [recording quality constraints](/async-collaboration/recorder/customize-behavior#setrecordingqualityconstraints) and [encoding options](/async-collaboration/recorder/customize-behavior#setrecordingencodingoptions). This provides finer control over the video and audio output of recordings.

      <Tabs>
        <Tab title="React / Next.js">
          ```jsx theme={null}
          const recorderElement = useRecorderUtils();

          recorderElement.setRecordingQualityConstraints({
              'other': {
                  'video': {
                      width: { exact: 3024  },
                      height: { exact: 1542 },
                      frameRate: { exact: 20 },
                  }
              }
          });

          recorderElement.setRecordingEncodingOptions({
              'other': {
                  videoBitsPerSecond: 2000000,
                  audioBitsPerSecond: 128000
              }
          });
          ```
        </Tab>

        <Tab title="Other Frameworks">
          ```js theme={null}
          const recorderElement = Velt.getRecorderElement();

          recorderElement.setRecordingQualityConstraints({
              'other': {
                  'video': {
                      width: { exact: 3024  },
                      height: { exact: 1542 },
                      frameRate: { exact: 20 },
                  }
              }
          });

          recorderElement.setRecordingEncodingOptions({
              'other': {
                  videoBitsPerSecond: 2000000,
                  audioBitsPerSecond: 128000
              }
          });
          ```
        </Tab>
      </Tabs>

  ### Bug Fixes

  * \[**Recorder**]: Removed loading animation in the apply button which was causing performance issues.
  * \[**Recorder**]: Fixed the issue where disabled buttons were still clickable.
</Update>

<Update label="4.5.0-beta.2" description="May 21 2025">
  ### Improvements

  * \[**Presence**]: Added ability to configure when user is considered offline after being inactive. Default value: `600000`ms (10 minutes).

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltPresence offlineInactivityTime={600000} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-presence offline-inactivity-time="600000"></velt-presence>
      ```
    </Tab>
  </Tabs>

  * \[**Presence**]: Added `isUserIdle` and `isTabAway` fields in presence user objects.
    * When a user navigates away from the current tab, their status will be marked as `away`, and the `isTabAway` field in their presence object will be set to `true`.
    * If a user remains inactive (no mouse movement) for a duration defined by `inactivityTime` (default: 5 minutes), their status will be set to `away`, and the `isUserIdle` field in their presence object will be set to `true`.

  * \[**Single Editor Mode**]: Added new events for Single Editor Mode, enabling finer-grained tracking of collaborative states and user interactions.
    The new events are:

    * `accessRequested`: When a user requests editor access.
    * `accessRequestCanceled`: When a user cancels their request for editor access.
    * `accessAccepted`: When a user's request for editor access is accepted.
    * `accessRejected`: When a user's request for editor access is rejected.
    * `editorAssigned`: When a user is assigned as the editor.
    * `viewerAssigned`: When a user is assigned as a viewer.
    * `editorOnDifferentTabDetected`: When the current editor navigates away to a different browser tab or window.

      <Tabs>
        <Tab title="React / Next.js">
          **Using Hooks:**

          ```jsx theme={null}
          // Replace "EVENT_TYPE" with an actual event string. eg: "accessRequested".
          const eventData = useLiveStateSyncEventCallback("EVENT_TYPE"); 

          useEffect(() => {
            if (eventData) { 
              console.log("EVENT_TYPE data: ", eventData);
            }
          }, [eventData]);
          ```

          **Using API:**

          ```jsx theme={null}
          const liveStateSyncElement = useLiveStateSyncUtils();
          // Replace "EVENT_TYPE" with an actual event string. eg: "accessRequested".
          liveStateSyncElement.on("EVENT_TYPE").subscribe((eventData) => {
            console.log("EVENT_TYPE data: ", eventData);
          });
          ```
        </Tab>

        <Tab title="Other Frameworks">
          ```javascript theme={null}
          const liveStateSyncElement = Velt.getLiveStateSyncElement();
          // Replace "EVENT_TYPE" with an actual event string. eg: "accessRequested".
          liveStateSyncElement.on("EVENT_TYPE").subscribe((eventData) => {
            console.log("EVENT_TYPE data: ", eventData);
          });
          ```
        </Tab>
      </Tabs>

  * \[**Comments**]: The `updateContext` method is now supported even when multiple documents are initialized.
</Update>

<Update label="4.5.0-beta.1" description="May 20 2025">
  ### New Features

  * \[**Recorder**]: Added zooming functionality. Users can now add smooth zoom in and out effects on the video scenes. Note: This is in beta and currently the processing time for zoom in effect is quite high. We are working to optimize it.

  ### Improvements

  * \[**Recorder**]: Improved wireframes for video editor elements with mouse events to remove all styles if children are provided in the wireframe. Earlier for these elements, some residual styles were required to be overridden via CSS.

  * \[**Recorder**]: Added the `recordingEditDone` event. This event fires the recording edits are done processing and the new recording file is generated.

      <Tabs>
        <Tab title="React / Next.js">
          ```jsx theme={null}
          const recordingEditDoneEvent = useRecorderEventCallback('recordingEditDone');
          useEffect(() => {
              if (recordingEditDoneEvent) {
                  console.log('recordingEditDone: ', recordingEditDoneEvent);
              }
          }, [recordingEditDoneEvent]);

          ```
        </Tab>

        <Tab title="Other Frameworks">
          ```javascript theme={null}
          const recorderelement = Velt.getRecorderElement();
          recorderelement.on('recordingEditDone').subscribe((event) => {
              console.log('recording edit done:' , event);
          });

          ```
        </Tab>
      </Tabs>

  * \[**Recorder**]: Added the `deleteRecordings` API method to delete recordings.

  <Tabs>
    <Tab title="React / Next.js">
      **Using API:**

      ```ts theme={null}
      const recorderelement = client.getRecorderElement();
      await recorderelement.deleteRecordings({
          recorderIds: ['RECORDER_ID_1']
      });

      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      const recorderelement = Velt.getRecorderElement();
      await recorderelement.deleteRecordings({
          recorderIds: ['RECORDER_ID_1']
      });
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.4.0" description="May 16 2025">
  ### Bug Fixes

  * \[**Core**]: Release 4.4.0 stable version.
</Update>

<Update label="4.4.0-beta.17" description="May 16 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where the `velt-comment-sidebar-filter-item--Added` class was not being applied correctly in the people filter.
  * \[**Notifications**]: Fixed an issue where `setNotificationAsRead` was not working as expected in some scenarios.
</Update>

<Update label="4.4.0-beta.16" description="May 15 2025">
  ### Bug Fixes

  * \[**Live State Sync**]: Fixed an issue where `serverConnectionState` value was not updating correctly in some scenarios.
</Update>

<Update label="4.4.0-beta.15" description="May 14 2025">
  ### Improvements

  * \[**Comments**]: Added support to specify whether the system filters (e.g., "me", "this page") should be combined with an "and" or "or" operator. Default is `and`.

  <Tabs>
    <Tab title="React / Next.js">
      **Using Props:**

      ```tsx theme={null}
      <VeltCommentsSidebar systemFiltersOperator='or' />
      ```

      **Using API:**

      ```ts theme={null}
      const commentElement = client.getCommentElement();
      commentElement.setSystemFiltersOperator('or');
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments-sidebar system-filters-operator="or"></velt-comments-sidebar>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Improved filters for comments author in the sidebar.
</Update>

<Update label="4.4.0-beta.14" description="May 13 2025">
  ### Bug Fixes

  * \[**SDK**]: Fixed an issue where delete notification REST API was causing some older notifications to be hidden in the frontend component.
</Update>

<Update label="4.4.0-beta.13" description="May 13 2025">
  ### Improvements

  * \[**REST APIs**]: Added support for persisting read notifications in "For You" tab through `Update Notifications` REST API. You can pass `persistReadForUsers` param as true.

  ### Bug Fixes

  * \[**SDK**]: Fixed an issue where the `setAllNotificationsAsRead` SDK API method was not working as expected.
</Update>

<Update label="4.4.0-beta.12" description="May 10 2025">
  ### Improvements

  * \[**REST APIs**]: Added realtime updates to SDK when notifications are deleted via the REST APIs.
  * \[**REST APIs**]: Added support for marking notifications as read through `Update Notifications` REST API.

  ### Bug Fixes

  * \[**Single Editor Mode**]: Fixed accept reject buttons disappearing issue when multiple users request access in single editor mode.
</Update>

<Update label="4.4.0-beta.11" description="May 08 2025">
  ### Improvements

  * \[**Live State Sync**]: Improved types in `getLiveStateData`, `setLiveStateData` methods and hooks.
  * \[**Comments Sidebar**]: Ensured that "me" and "this page" options are on the top of the comments sidebar filters.
  * \[**Notifications**]: Added missing `panelOpenMode` prop to `VeltNotificationsPanel` in React.
    ```tsx theme={null}
    <VeltNotificationsPanel panelOpenMode='sidebar'/>
    ```

  ### Bug Fixes

  * \[**Comments**]: Fixed an edge case where Tiptap comments were not being added when `commentToNearestAllowedElement` is enabled and comment mode is on.
</Update>

<Update label="4.4.0-beta.10" description="May 02 2025">
  ### New Features

  * \[**Comments**]: Added ability to attach comment pins to the closest allowed element when clicking on a non-allowed element. Default: `false`

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltComments commentToNearestAllowedElement={true} />
      ```

      **Using API:**

      ```jsx theme={null}
      const commentElement = client.getCommentElement();
      commentElement.enableCommentToNearestAllowedElement();
      commentElement.disableCommentToNearestAllowedElement();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments comment-to-nearest-allowed-element="true"></velt-comments>
      ```

      **Using API:**

      ```js theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement.enableCommentToNearestAllowedElement();
      commentElement.disableCommentToNearestAllowedElement();
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added ability to enable/disable draft mode in comments. Default: `true`

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltComments draftMode={false} />
      ```

      **Using API:**

      ```jsx theme={null}
      const commentElement = client.getCommentElement();
      commentElement.enableDraftMode();
      commentElement.disableDraftMode();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments draft-mode="false"></velt-comments>
      ```

      **Using API:**

      ```js theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement.enableDraftMode();
      commentElement.disableDraftMode();
      ```
    </Tab>
  </Tabs>

  * \[**Presence**]: Added ability to turn off shadow DOM in Presence component. Default: `true`

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltPresence shadowDom={false} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-presence shadow-dom="false"></velt-presence>
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Webhooks**]: Added `assigned: true` in comment added event when someone is assigned to the comment during creation.
  * \[**Live State Sync**]: Enhanced Redux middleware with support to dynamically update configuration options:
    * `allowedActionTypes`
    * `disabledActionTypes`
    * `allowAction`
</Update>

<Update label="4.4.0-beta.9" description="Apr 30 2025">
  ### Bug Fixes

  * \[**Core**]: Added additional compatibility for Safari v16 and older versions.
</Update>

<Update label="4.4.0-beta.8" description="Apr 29 2025">
  ### Improvements

  * \[**Recorder**]: Added ability to control whether recorded videos play in full-screen mode.
    * You can use this prop on any of the following components:
      * `Velt Recorder Notes`
      * `Velt Recorder Control Panel`
      * `Velt Recorder Player`
    * Its turned on by default for Comments feature and off by default for standalone Recorder feature.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Change behaviour globally
      <VeltRecorderNotes playVideoInFullScreen={true} />
      <VeltRecorderControlPanel playVideoInFullScreen={true} />
      // Change behaviour for specific player 
      <VeltRecorderPlayer playVideoInFullScreen={true} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-recorder-notes play-video-in-full-screen="true"></velt-recorder-notes>
      <velt-recorder-control-panel play-video-in-full-screen="true"></velt-recorder-control-panel>
      <velt-recorder-player play-video-in-full-screen="true"></velt-recorder-player>
      ```
    </Tab>
  </Tabs>

  * \[**Recorder**]: Added keyboard shortcuts in video editor for improved editing experience:
    * `s`: Split the video at the selected frame.
    * `d`, `delete`, or `backspace`: Delete the selected video section.
    * `space`: Toggle video play/pause.

  * \[**Single Editor Mode**]: Added wireframe for Single Editor Mode Panel.

  * \[**Single Editor Mode**]: Added embeddable component for Single Editor Mode Panel.

      <Tabs>
        <Tab title="React / Next.js">
          ```jsx theme={null}
          <VeltSingleEditorModePanel shadowDom={false} darkMode={true} variant="custom-ui" />
          ```
        </Tab>

        <Tab title="Other Frameworks">
          ```html theme={null}
          <velt-single-editor-mode-panel shadow-dom="false" dark-mode="true" variant="custom-ui"></velt-single-editor-mode-panel>
          ```
        </Tab>
      </Tabs>
</Update>

<Update label="4.4.0-beta.7" description="Apr 28 2025">
  ### Improvements

  * \[**UI Customization**]: Added dynamic key support and square bracket notation support in Velt If conditions for more flexible conditional logic.

  ### Bug Fixes

  * \[**Follow Mode**]: Fixed an issue where follow mode was not working as expected.
  * \[**Comments**]: Fixed "All" status filter not displaying all comments in sidebar.
</Update>

<Update label="4.4.0-beta.6" description="Apr 25 2025">
  ### New Features

  * \[**UI Customization**]: Added support of adding dynamic id on Velt Button. You can use template variables to set the id.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltButtonWireframe id="someStaticId" type="button-toggle" />
      <VeltButtonWireframe id="{annotation.annotationId}" type="button-toggle" />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-button-wireframe id="someStaticId" type="button-toggle"></velt-button-wireframe>
      <velt-button-wireframe id="{annotation.annotationId}" type="button-toggle"></velt-button-wireframe>
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Recorder**]: Improved video editor UX for trimming and splitting videos.
  * \[**Single Editor Mode**]: Return `undefined` value in `isUserEditor` when there are no current editors available in single editor mode.
  * \[**Presence**]: Added `locationId` support in presence component.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltPresence locationId={"YOUR_LOCATION_ID"} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-presence location-id="YOUR_LOCATION_ID"></velt-presence>
      ```
    </Tab>
  </Tabs>

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where comment dialog composer in sidebar was getting autofocused when `fullExpanded` mode was enabled.
</Update>

<Update label="4.4.0-beta.5" description="Apr 24 2025">
  ### New Features

  * \[**UI Customization**]: Added `resetVeltButtonState` method to reset the state of Velt Button components.

    ```ts theme={null}
    // Reset state for a specific button in a given group
    client.resetVeltButtonState({id: 'openSidebar', group: 'multi'})

    // Reset state for all buttons in a given group
    client.resetVeltButtonState({group: 'multi'})

    // Reset state for a specific button in all groups
    client.resetVeltButtonState({id: 'openSidebar'})

    // Reset state for all buttons
    client.resetVeltButtonState()
    ```

  ### Improvements

  * \[**Comments**]: Updated copy and icons for sidebar filter buttons.
  * \[**Recorder**]: Made the transition to editor smoother when `autoOpenVideoEditor` is enabled.
  * \[**Recorder**]: Improved the control panel embedded settings menu UX.
  * \[**Recorder**]: Added keyboard shortcuts for Play, Pause, Split, and Delete actions in video editor.

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where the dialog might close if the user clicked outside the dialog while a recording was in progress.
</Update>

<Update label="4.4.0-beta.4" description="Apr 23 2025">
  ### New Features

  * \[**Self Hosting**]: Added support for self-hosting file attachments in comments.

  ### Improvements

  * \[**Self Hosting**]: Added retries for GET operations.
  * \[**Analytics**]: Exposed additional events to Velt Debugger.
  * \[**Live State Sync**]: Added config to choose between merging and replacing live state data.

  <Tabs>
    <Tab title="React / Next.js">
      **Using Hooks:**

      ```ts theme={null}
      const liveStateData = {
        'yourKey': 'yourValue'
      };

      useSetLiveStateData('LIVE_STATE_DATA_KEY',liveStateData, { merge: true });
      ```

      **Using API:**

      ```ts theme={null}
      const liveStateSyncElement = useLiveStateSyncUtils();
      const liveStateData = {
        'yourKey': 'yourValue'
      };
      liveStateSyncElement.setLiveStateData('LIVE_STATE_DATA_KEY', liveStateData, {
          merge: true
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```ts theme={null}
      const liveStateSyncElement = Velt.getLiveStateSyncElement();
      const liveStateData = {
        'yourKey': 'yourValue'
      };
      liveStateSyncElement.setLiveStateData('LIVE_STATE_DATA_KEY', liveStateData, {
          merge: true
      });
      ```
    </Tab>
  </Tabs>

  ### Bug Fixes

  * \[**Live State Sync**]: Fixed an issue in the Redux Middleware where the middleware was not initializing when Velt Provider was added conditionally.
</Update>

<Update label="4.4.0-beta.3" description="Apr 23 2025">
  ### Bug Fixes

  * \[**Single Editor Mode**]: Fixed an issue where `contenteditable` div's access was not syncing properly when editor state changed.
</Update>

<Update label="4.4.0-beta.2" description="Apr 22 2025">
  ### Improvements

  * \[**Recorder**]: Added missing audio waveform visualization for screen recordings.
  * \[**Recorder**]: Made query parameter optional for `fetchRecordings` method.
  * \[**Recorder**]: Improved metadata handling to ensure clean object state.
    ```typescript theme={null}
    export class RecorderData {
      recorderId!: string;
      from?: User | null; 
      metadata?: RecorderMetadata;
      assets: RecorderDataAsset[] = [];
      transcription: RecorderDataTranscription = new RecorderDataTranscription();
    }
    ```
</Update>

<Update label="4.4.0-beta.1" description="Apr 21 2025">
  ### Improvements

  * \[**Recorder**]: Added additional props in `Recorder Control Panel` component:
    * `settingsEmbedded`: If set to true, the settings will be embedded in the control panel vs a menu. Default is `false`. Please use this together with the Control Panel Wireframes so that you can move the settings panel in a different part of the control panel UI.
    * `autoOpenVideoEditor`: If set to true, the video editor will be opened automatically when the recording is done. Default is `false`.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltRecorderControlPanel autoOpenVideoEditor={true} settingsEmbedded={true} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-recorder-control-panel auto-open-video-editor="true" settings-embedded="true"></velt-recorder-control-panel>
      ```
    </Tab>
  </Tabs>

  * \[**Recorder**]: Added wireframe for recording preview in recording control panel.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltRecorderControlPanelWireframe.FloatingMode.Screen />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-recorder-control-panel-screen-wireframe></velt-recorder-control-panel-screen-wireframe>
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.3.0" description="Apr 18 2025">
  ### New Features

  * \[**Comments**]: Added `fullExpanded` mode to control the expanded state of comments.
    * When enabled, comments will be shown in fully expanded state by default.
    * Available on all comment-related components and can be controlled via props or API methods.

  <Tabs>
    <Tab title="React / Next.js">
      Using Props:

      ```jsx theme={null}
      // Apply this change globally to all types of comments
      <VeltComments fullExpanded={true} />

      // Apply this change only in comments sidebar
      <VeltCommentsSidebar fullExpanded={true} />

      // Apply this change only in inline comments section
      <VeltInlineCommentsSection fullExpanded={true} />

      // Apply this change only in the standalone comment thread
      <VeltCommentThread fullExpanded={true} />

      ```

      Using API:

      ```js theme={null}
      const commentElement = client.getCommentElement();
      commentElement.enableFullExpanded();
      commentElement.disableFullExpanded();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      Using Props:

      ```html theme={null}
      <!-- Apply this change globally to all types of comments -->
      <velt-comments full-expanded="true"></velt-comments>

      <!-- Apply this change only in comments sidebar -->
      <velt-comments-sidebar full-expanded="true"></velt-comments-sidebar>

      <!-- Apply this change only in inline comments section -->
      <velt-inline-comments-section full-expanded="true"></velt-inline-comments-section>

      <!-- Apply this change only in the standalone comment thread -->
      <velt-comment-thread full-expanded="true"></velt-comment-thread>

      ```

      Using API:

      ```js theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement.enableFullExpanded();
      commentElement.disableFullExpanded();
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.3.0-beta.7" description="Apr 17 2025">
  ### New Features

  * \[**Dev Tools**]: Published beta version of Velt Devtools Chrome extension. It allows you to inspect and debug your Velt implementation. If you are interested in trying it out, please reach out to us.
  * \[**Console**]: Added support for viewing folders, recordings and notifications data in the console data page.
  * \[**Console**]: Added support for additional filters in the console data page: organizationId, folderId, documentId, userId.
  * \[**Comments**]: Added support for folder users in `@` mentions dropdown.
  * \[**Recorder**]: Added an API to subscribe to all recorder data in the current document.
    * Param: `RecorderRequestQuery`, optional, Gets the data for the provided query.
    * Returns: `Observable<GetRecordingsResponse>`, Subscription of the recorder data.

  <Tabs>
    <Tab title="React / Next.js">
      **Using Hook:**

      ```jsx theme={null}
      const recordings = useRecordings(); 

      useEffect(() => {
        console.log('recordings', recordings);
      }, [recordings]);
      ```

      **Using API:**

      ```js theme={null}
      const recorderElement = useRecorderUtils();
      recorderElement.getRecordings().subscribe((data) => {
          console.log('recordings', data);
      });

      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      const recorderElement = Velt.getRecorderElement();
      recorderElement.getRecordings().subscribe((data) => {
          console.log('recordings', data);
      });
      ```
    </Tab>
  </Tabs>

  * \[**Recorder**]: Extended the `on` event subscription API to include:
    * `recordingDone`: Triggered when recording is completed.
    * `deleteRecording`: Triggered when a recording is deleted.

  <Tabs>
    <Tab title="React / Next.js">
      **Using Hook:**

      ```jsx theme={null}
      const recordingDoneEvent = useRecorderEventCallback('recordingDone');
      const recordingDeleteEvent = useRecorderEventCallback('deleteRecording');

      useEffect(() => {
          console.log('recordingDoneEvent', recordingDoneEvent);
      }, [recordingDoneEvent]);

      useEffect(() => {
          console.log('recordingDeleteEvent', recordingDeleteEvent);
      }, [recordingDeleteEvent]);

      ```

      **Using API:**

      ```js theme={null}
      const recorderElement = useRecorderUtils();

      recorderElement.on('recordingDone').subscribe((data) => {
          console.log('recordingDone:' , data);
      });

      recorderElement.on('deleteRecording').subscribe((data) => {
          console.log('deleteRecording:' , data);
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      const recorderElement = Velt.getRecorderElement();

      recorderElement.on('deleteRecording').subscribe((data) => {
          console.log('deleteRecording:' , data);
      });

      recorderElement.on('recordingDone').subscribe((data) => {
          console.log('recordingDone:' , data);
      });
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**UI**]: Made custom list search case insensitive.
  * \[**Recorder**]: Make the video preview responsive in video editor.
  * \[**Recorder**]: Improved types for all APIs and Props for the recording feature.
</Update>

<Update label="4.3.0-beta.6" description="Apr 16 2025">
  ### New Features

  * \[**Core**]: Added the following events in `on` method of Velt client:
    * `userUpdate`: Triggered when the Velt user is updated.
    * `documentInit`: Triggered when the Velt document is initialized.
    * `error`: Triggered when an error occurs. Currently this is only triggered for `token_expired` error. In future, this will be extended for other relevant errors.

  <Tabs>
    <Tab title="React / Next.js">
      **Using Hook:**

      ```jsx theme={null}
      const userUpdateEvent = useVeltEventCallback('userUpdate');
      const documentInitEvent = useVeltEventCallback('documentInit');
      const errorEvent = useVeltEventCallback('error');

      useEffect(() => {
          console.log('userUpdate', userUpdateEvent);
      }, [userUpdateEvent]);

      useEffect(() => {
          console.log('documentInit', documentInitEvent);
      }, [documentInitEvent]);

      useEffect(() => {
          // for token expired, error.code = 'token_expired'
          console.log('error', errorEvent);
      }, [errorEvent]);
      ```

      **Using API:**

      ```js theme={null}
      client.on('userUpdate').subscribe((user) => {
          console.log('userUpdate', user);
      });

      client.on('documentInit').subscribe((documentInit) => {
          console.log('documentInit', documentInit);
      });

      client.on('error').subscribe((error) => {
          // for token expired, error.code = 'token_expired'
          console.log('error', error);
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      Velt.on('userUpdate').subscribe((user) => {
          console.log('userUpdate', user);
      });

      Velt.on('documentInit').subscribe((documentInit) => {
          console.log('documentInit', documentInit);
      });

      Velt.on('error').subscribe((error) => {
          // for token expired, error.code = 'token_expired'
          console.log('error', error);
      });
      ```
    </Tab>
  </Tabs>

  * \[**Recorder**]: Added ability to enable/disable video editor via props on `Velt Recorder Player` and `Velt Recorder Control Panel` components. You could use any of these.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
       <VeltRecorderPlayer videoEditor={true}  />
       <VeltRecorderControlPanel videoEditor={true}/>
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
       <velt-recorder-player video-editor="true"></velt-recorder-player>
       <velt-recorder-control-panel video-editor="true"></velt-recorder-control-panel>
      ```
    </Tab>
  </Tabs>

  * \[**Recorder**]: Added `recordingCountdown` and `recordingTranscription` props on `Velt Recorder Notes` and `Velt Recorder Control Panel` components.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
       <VeltRecorderNotes recordingTranscription={false} recordingCountdown={false} />
       <VeltRecorderControlPanel recordingTranscription={false} recordingCountdown={false} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
       <velt-recorder-notes recording-countdown="false" recording-transcription="false"></velt-recorder-notes>
       <velt-recorder-control-panel recording-countdown="false" recording-transcription="false"></velt-recorder-control-panel>
      ```
    </Tab>
  </Tabs>

  * \[**Recorder**]: Added video editor wireframes.

  ### Improvements

  * \[**Core**]: Improved types for data resolvers.
  * \[**Recorder**]: Removed drag functionality from recording control panel and player.
  * \[**Recorder**]: If a `null` value is set for `recorder Id` prop in `Velt Recorder Player` component, a warning will be thrown.

  ### Bug Fixes

  * \[**Comments**]: Added a check to prevent an error in @mentions dropdown if the user group has no users and the `expandMentionGroups` config is set to true.
</Update>

<Update label="4.3.0-beta.5" description="Apr 16 2025">
  ### New Features

  * \[**Comments**]: Added support for new filters in `fetchCommentAnnotations` method:
    * `resolvedBy`: `string`, Filter comments by user who resolved the comment
    * `userIds`: `string[]`, Filter comments by comment annotation author
    * `mentionedUserIds`: `string[]`, Filter comments if the provided users are tagged in the comment

  * \[**Contacts**]: Added API and Hook to get the list of users added to organization, document, user groups or the ones overwritten using the `updateContactList` API.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}

      export interface UserGroup {
          groupId!: string;
          groupName!: string;
          users?: User[];
      }

      export interface GetContactListResponse {
          organizationUsers?: User[];
          folderUsers?: User[];
          documentUsers?: User[];
          userGroups?: UserGroup[];
          updatedContactList?: User[];
      }


      // React Hook
      const contactList = useContactList();
      console.log(contactList); // initial value will be null

      // API method
      const contactElement = client.getContactElement();
      contactElement.getContactList().subscribe((response) => {
        console.log(response); // initial value will be null
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      export interface UserGroup {
          groupId!: string;
          groupName!: string;
          users?: User[];
      }

      export interface GetContactListResponse {
          organizationUsers?: User[];
          folderUsers?: User[];
          documentUsers?: User[];
          userGroups?: UserGroup[];
          updatedContactList?: User[];
      }

      // API method
      const contactElement = Velt.getContactElement();
      contactElement.getContactList().subscribe((response) => {
        console.log(response); // initial value will be null
      });
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.3.0-beta.4" description="Apr 14 2025">
  ### New Features

  * \[**Comments**]: Added a config to show expanded user groups inside the @mentions dropdown menu.
    * Added [new wireframes](/ui-customization/features/async/comments/comment-dialog/subcomponents/autocomplete-group-option) to customize the display of user groups.
    * Here are some props to control the display of user groups:
      * `expandMentionGroups`: Whether to expand the user groups and show individual users inside the groups in the @mentions dropdown menu.
      * `showMentionGroupsFirst`: Whether to show the user groups in the @mentions dropdown menu before the non-group users.
      * `showMentionGroupsOnly`: Whether to show only the user groups in the @mentions dropdown menu and not the non-group users.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltComments 
            expandMentionGroups={true} 
            showMentionGroupsFirst={false} 
            showMentionGroupsOnly={false} 
      />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments 
           expand-mention-groups="true" 
           show-mention-groups-first="false"
           show-mention-groups-only="true"
      ></velt-comments>
      ```
    </Tab>
  </Tabs>

  * \[**Comments Sidebar**]: Added two new default system filters and their wireframes to the sidebar:

    * `Tagged`: Filter comments by specifying the user who was tagged in the comment. ([Wireframe](/ui-customization/features/async/comments/comments-sidebar/subcomponents/filter/subcomponents/tagged))
    * `Assigned`: Filter comments by specifying the user who was assigned to the comment. ([Wireframe](/ui-customization/features/async/comments/comments-sidebar/subcomponents/filter/subcomponents/assigned))

    ```typescript theme={null}
    class CommentSidebarFilterConfig {
        // ... existing properties ...
        tagged?: FilterTypeConfig;
        assigned?: FilterTypeConfig;
        // ... existing properties ...
    }
    ```
  * \[**Comments Sidebar**]: Added another UI pattern for filters options: searchable dropdown with checklist. ([Example Wireframe](/ui-customization/features/async/comments/comments-sidebar/subcomponents/filter/subcomponents/tagged))

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltCommentsSidebar filterOptionLayout="dropdown | checkbox"/>
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments-sidebar filter-option-layout="dropdown | checkbox"></velt-comments-sidebar>
      ```
    </Tab>
  </Tabs>

  * \[**Comments Sidebar**]: Added a reset filter button. ([Wireframe](/ui-customization/features/async/comments/comments-sidebar/subcomponents/filter/subcomponents/reset-button))
  * \[**Comments Sidebar**]: Added prop to disable count calculation for sidebar filter options.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltCommentsSidebar filterCount={false}/>
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```html theme={null}
      <velt-comments-sidebar filter-count="false"></velt-comments-sidebar>
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.3.0-beta.3" description="Apr 11 2025">
  ### Improvements

  * \[**Comments**]: Updated `getCommentAnnotations()` method to now [query](/api-reference/sdk/models/data-models#commentrequestquery) and subscribe to comments data even if its not the currently set document.
  * \[**Comments**]: Improved comment dialog positioning on text comments when the text is at the bottom edge of the page.
  * \[**Notifications**]: Added support in `getNotificationsData()` for retrieving custom notifications created with `notifyAll: false`.
  * \[**REST API**]: Improved the performance of [GDPR Delete API](/api-reference/rest-apis/v2/gdpr/delete-all-user-data-gdpr) and made it 90%+ faster and more efficient.

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue with SlateJS comments where comment was not being added when the text was selected from right to left.
</Update>

<Update label="4.3.0-beta.2" description="Apr 7 2025">
  ### Improvements

  * \[**Recorder**]: Optimized the video recording performance: 50% smaller files with 90% faster uploads!
</Update>

<Update label="4.3.0-beta.1" description="Apr 7 2025">
  ### Improvements

  * \[**Core**]: Upgraded several dependency packages to new versions.
</Update>

<Update label="4.2.1-beta.11" description="Apr 4 2025">
  ### Improvements

  * \[**REST API**]: Added support to get all user data for GDPR requests. [Learn more](/api-reference/rest-apis/v2/gdpr/get-all-user-data-gdpr).
</Update>

<Update label="4.2.1-beta.11" description="Apr 3 2025">
  ### Improvements

  * \[**Localization**]: Added additional null checks for provided localization strings.
  * \[**REST API**]: Added support for special characters (`_`, `-`) while creating custom notifications.
</Update>

<Update label="4.2.1-beta.10" description="Apr 3 2025">
  ### New Features

  * \[**Localization**]: Added support for localization for all static strings visible in the SDK Components.
    * You can get the complete list of strings that can be localized [here](https://firebasestorage.googleapis.com/v0/b/snippyly.appspot.com/o/external%2Flocalization-strings-map.json?alt=media\&token=0cdd2b52-10ed-4033-a08a-5c2b622ce7df).

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Provide the localization object for the languages you want to support.
      client.setTranslations({
        'en': {
          'All comments': 'All comments',
        },
        'fr': {
          'All comments': 'Tous les commentaires',
        },
        // Add more languages as needed.
      });

      // Set one of the languages you've provided the translations for.
      client.setLanguage('en');
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      // Provide the localization object for the languages you want to support.
      Velt.setTranslations({
        'en': {
          'All comments': 'All comments',
        },
        'fr': {
          'All comments': 'Tous les commentaires',
        },
        // Add more languages as needed.
      });

      // Set one of the languages you've provided the translations for.
      Velt.setLanguage('en');
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added support for `.txt` file attachments in Comments.
</Update>

<Update label="4.2.1-beta.9" description="Apr 2 2025">
  ### New Features

  * \[**Comments, Notifications**]: Added a first-party [extension](https://www.npmjs.com/package/@veltdev/slate-velt-comments) for [SlateJS](https://www.slatejs.org/) to allow comments and notifications on text content.
</Update>

<Update label="4.2.1-beta.8" description="Apr 2 2025">
  ### Bug Fixes

  * \[**UI Customization**]: Fixed an issue where empty wireframes for repeated components were not being rendered in some scenarios.

  ### Improvements

  * \[**Comments**]: Changed default value of `pin-highlighter` to false for better initial experience.
  * \[**REST API**]: Added `deleteAll` parameter to [`/v1/organizations/usergroups/users/delete`](/api-reference/rest-apis/v2/user-groups/delete-users-from-group) remove all users from a group.
  * \[**REST API**]: Added `metadata` field on the returned comment annotation objects. It will contain documentId, organizationId, folderId, etc.
</Update>

<Update label="4.2.1-beta.7" description="Mar 31 2025">
  ### Improvements

  * \[**Recorder**]: Improved the video editor to be smoother and enabled "select and delete" feature.
  * \[**Recorder**]: Added support for audio waveform visualization in video recordings.
  * \[**Recorder**]: Reduced the size of the video recordings by 50%.
</Update>

<Update label="4.2.1-beta.6" description="Mar 28 2025">
  ### New Features

  * \[**Reactions**]: Added support for self hosting reactions data.

  ### Improvements

  * \[**Core**]: Improved signature of User Resolver (used for self hosting user PII) for better consistency with backward compatibility.
  * \[**Core**]: Extended data resolvers with an option to configure retries and optimized operation order to prioritize client-side execution. Learn more [here](/api-reference/sdk/models/data-models#resolverconfig).
  * \[**REST API**]: Added support for updating users in existing comment annotations via REST APIs. Learn more [here](/api-reference/rest-apis/v2/comments-feature/comment-annotations/update-comment-annotations#param-update-users).
</Update>

<Update label="4.2.1-beta.5" description="Mar 26 2025">
  ### Improvements

  * \[**Core**]: Added support for automatic folder creation from the frontend when folders don't exist. New documents without existing data are now automatically added to the currently set folder.
  * \[**REST API**]: Added support for user mentions via REST APIs. Learn more [here](/api-reference/rest-apis/v2/comments-feature/comment-annotations/add-comment-annotations).

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where deleting inline comments in multi-document scenarios wasn't always updating the UI state.
</Update>

<Update label="4.2.1-beta.4" description="Mar 21 2025">
  ### New Features

  * \[**Core**]: Added `updateLocations` method to update location(s) metadata. Previously this could only be done via REST APIs.

  ```js theme={null}
  client.updateLocations({
    organizationId: 'org1', 
    documentIds: ['doc1', 'doc2'], 
    locations: [{
      id: 'location1', 
      locationName: 'MyLocation'
    }]
  })

  export interface UpdateLocationsRequest<T = unknown> {
      organizationId?: string;
      documentIds?: string[];
      locations?: UpdateLocationMetadata<T>[];
  }

  export interface UpdateLocationMetadata<T = unknown> {
      id: string;
      [key: string]: T | string;
  }
  ```

  ### Improvements

  * \[**Core**]: Improved types for `updateDocuments` method.

  ```js theme={null}
  client.updateDocuments({
    organizationId: 'org1', 
    documents: [{
      documentId: 'doc1', 
      documentName: 'MyDoc'
    }]
  })

  export interface UpdateDocumentsRequest<T = unknown> {
      organizationId?: string;
      documents?: UpdateDocumentMetadata<T>[];
  }

  export interface UpdateDocumentMetadata<T = unknown> {
      documentId: string;
      [key: string]: T | string;
  }
  ```

  * \[**Core**]: Added support for location persistence by after debounced document updates.
  * \[**Core**]: Show the most updated location metadata in features like sidebar and notifications even if the features have stale data.
  * \[**Core**]: `client.getMetadata()` method now provides most updated information about organization, folders documents and locations for debugging purposes.
  * \[**Core**]: Added logs for get API methods like `fetchCommentAnnotations` if it's called without an authenticated user.
  * \[**Core**]: SDK state and location are preserved after auto-relogin when browser extensions clear indexedDb during idle periods of >1hr.
  * \[**Core**]: Enhanced `disableLogs` method with more granular control:
    * `disableLogs()`: turns off only warnings
    * `disableLogs({suppressAll: true})`: turns off all logs
    * `disableLogs({warning: false, suppressAll: true})`: Keeps the warning logs but turns off all other logs
</Update>

<Update label="4.2.1-beta.3" description="Mar 20 2025">
  ### Improvements

  * \[**Core**]: Auto-relogin user in rare scenarios where after an hour of idle time indexedDb is cleared by browser extensions.
</Update>

<Update label="4.2.1-beta.2" description="Mar 20 2025">
  ### New Features

  * \[**Comments**]: Added `svgAsImg` configuration in comments to treat SVGs as images instead layered elements. Default is `false`.

  <Tabs>
    <Tab title="React / Next.js">
      **Using Props:**

      ```jsx theme={null}
      <VeltComments svgAsImg={true} />
      ```

      **Using API:**

      ```jsx theme={null}
      const commentElement = client.getCommentElement();
      commentElement.enableSvgAsImg();
      commentElement.disableSvgAsImg();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      **Using Props:**

      ```html theme={null}
      <velt-comments svg-as-img="true"></velt-comments>
      ```

      **Using API:**

      ```jsx theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement.enableSvgAsImg();
      commentElement.disableSvgAsImg();
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Comments**]: Added `data-velt-comment-dialog-comments-priority` attribute in comment dialog if a comment priority is set. This can be used to style comments differently based on their priority.
  * \[**Notifications**]: Changed min height to 300px in Notification panel.
  * \[**Comments**]: Added ability to apply filters via API before mounting the Sidebar (in embed mode).
</Update>

<Update label="4.2.1-beta.1" description="Mar 19 2025">
  ### Improvements

  * \[**Comments**]: Now, if both inline and popover comments are used, clicking on a comment in the inline comments section will not activate comment bubble.
  * \[**Comments**]: Added additional classes to inline comments section's container divs to allow for more precise custom styling.
  * \[**Core**]: Added configuration options to aggressively suppress error messages especially on Safari related to index db and network errors.

  ```js theme={null}
  client.disableLogs({suppressAll:true})
  ```

  ### Bug Fixes

  * \[**Comments**]: Added missing type for `placeholder` field in `createCustomListDataOnAnnotation` in React.
  * \[**Comments**]: Fixed minor bugs with Custom Lists wireframes.
</Update>

<Update label="4.2.0" description="Mar 18 2025">
  ### Improvements

  * \[**Notifications**]: Added minimum height to notification panel to prevent layout shift when there is just one notification.
  * \[**Notifications**]: Removed default styling from notifications tool when Wireframe is used.
  * \[**Comments**]: Added active state support in Tiptap comments mark tags.

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue with `onCommentAdd` event that was not triggered once the comments component was unmounted and remounted during the session.
</Update>

<Update label="4.2.0-beta.5" description="Mar 13 2025">
  ### New Features

  * \[**Debugging**]: Added events for `unsetDocuments` and `unsetLocations`.
  * \[**Comments**]: Added type for `fetchCommentAnnotations` in `CommentElement` for React.
  * \[**Documents**]: Added `updateDocuments` method to update document(s) metadata.

  ```js theme={null}
  client.updateDocuments({
    organizationId: 'org1',
    documents: [
      {
        documentId: 'document-id',
        documentName: 'document-name'
      }, 
      {
        documentId: 'document-id-2',
        documentName: 'document-name-2'
      }
    ]
  });

  export interface UpdateDocumentsRequest {
      organizationId?: string;
      documents?: {documentId: string; [key: string]: any}[];
  }
  ```

  * \[**Debugging**]: Added `folderId` property in `Velt.getMetadata()` response.
</Update>

<Update label="4.2.0-beta.4" description="Mar 12 2025">
  ### Improvements

  * \[**Notifications**]: Improved the notification tool component to prevent layout shift when notification count was updated.

  ### Bug Fixes

  * \[**Comments**]: Added missing type definition for Sidebar Filter Config in React to include status property.
</Update>

<Update label="4.2.0-beta.3" description="Mar 11 2025">
  ### Improvements

  * \[**Comments**]: Improved type names for comment resolver.

  ```ts theme={null}
  // Data models
  export interface VeltDataProvider {
      comment?: CommentAnnotationDataProvider;
      user?: UserDataProvider;
  }

  export interface CommentAnnotationDataProvider {
      get: (request: GetCommentResolverRequest) => Promise<Record<string, PartialCommentAnnotation>>;
      save: (request: SaveCommentResolverRequest) => Promise<void>;
      delete: (request: DeleteCommentResolverRequest) => Promise<void>;
      resolveTimeout?: number; // optional. In milliseconds. Expected timeout to get a response from your API.
  }

  export interface GetCommentResolverRequest {
      organizationId: string;
      commentAnnotationIds?: string[];
      documentIds?: string[];
      folderId?: string;
      allDocuments?: boolean;
  }

  export interface SaveCommentResolverRequest {
      commentAnnotation: { [key: string]: PartialCommentAnnotation };
  }

  export interface PartialComment {
      commentId: string | number;
      commentHtml?: string;
      commentText?: string;
  }

  export interface PartialCommentAnnotation {
      annotationId: string;
      metadata?: VeltMetadata;
      comments: {
          [commentId: string]: PartialComment;
      };
  }
  ```
</Update>

<Update label="4.2.0-beta.2" description="Mar 7 2025">
  ### New Features

  * \[**Recorder**]: Added Video Editing feature allowing users to edit recorded videos.

  <Tabs>
    <Tab title="React / Next.js">
      **Using Props:**

      ```jsx theme={null}
      <VeltRecorderNotes videoEditor={true} />
      ```

      **Using API:**

      ```jsx theme={null}
      const recorderElement = client.getRecorderElement();
      recorderElement.enableVideoEditor();
      recorderElement.disableVideoEditor();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      **Using Props:**

      ```html theme={null}
      <velt-recorder-notes video-editor="true"></velt-recorder-notes>
      ```

      **Using API:**

      ```jsx theme={null}
      const recorderElement = Velt.getRecorderElement();
      recorderElement.enableVideoEditor();
      recorderElement.disableVideoEditor();
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Recorder**]: Improved Recorder player UX.
</Update>

<Update label="4.2.0-beta.1" description="Mar 7 2025">
  ### New Features

  * \[**Comments**]: Comments Self Hosting now available. Store and retrieve comment and notification text on your own backend while using Velt's UI components.
    * Combined with existing user PII self hosting, you can now store all sensitive data on your infrastructure.
    * Support for self-hosted attachments and recordings coming soon.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Define your comment data provider
      const commentDataProvider = {
        get: async (request) => {
          const result = await getDataFromYourServer(request);
          // Ensure the result is in the required format
          return result;
        },
        save: async (request) => {
          const result = await saveDataOnYourServer(request);
          return result;
        },
        delete: async (request) => {
          await deleteDataFromYourServer(request.commentAnnotationId);
        },
      };

      // Set the data provider
      <VeltProvider
        apiKey="YOUR_API_KEY_HERE"
        dataProviders={{ comment: commentDataProvider }}>
        {/* Your app content */}
      </VeltProvider>
      ```

      **Request Objects:**

      ```js theme={null}
      // GET Request:
      {
          organizationId: string;
          commentAnnotationIds?: string[];
          documentIds?: string[];
          folderId?: string;
          allDocuments?: boolean;
      }

      // Save Request:
      {
          commentAnnotation: { [key: string]: IStrippedCommentAnnotation };
      }

      // IStrippedCommentAnnotation:
      {
          annotationId: string;
          metadata?: any;
          comments: {
              [commentId: string]: StrippedComment;
          };
      }

      // StrippedComment:
      {
          commentId: string | number;
          commentHtml?: string;
          commentText?: string;
      }

      // Delete Request:
      {
          commentAnnotationId: string;
          metadata?: any;
      }
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      // Define your comment data provider
      const commentDataProvider = {
        get: async (request) => {
          const result = await getDataFromYourServer(request);
          // Ensure the result is in the required format
          return result;
        },
        save: async (request) => {
          const result = await saveDataOnYourServer(request);
          return result;
        },
        delete: async (request) => {
          await deleteDataFromYourServer(request.commentAnnotationId);
        },
      };

      // Set the data provider
      client.setDataProviders({
        comment: commentDataProvider,
      });
      ```

      **Request Objects:**

      ```js theme={null}
      // GET Request:
      {
          organizationId: string;
          commentAnnotationIds?: string[];
          documentIds?: string[];
          folderId?: string;
          allDocuments?: boolean;
      }

      // Save Request:
      {
          commentAnnotation: { [key: string]: IStrippedCommentAnnotation };
      }

      // IStrippedCommentAnnotation:
      {
          annotationId: string;
          metadata?: any;
          comments: {
              [commentId: string]: StrippedComment;
          };
      }

      // StrippedComment:
      {
          commentId: string | number;
          commentHtml?: string;
          commentText?: string;
      }

      // Delete Request:
      {
          commentAnnotationId: string;
          metadata?: any;
      }
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.1.1" description="Mar 5 2025">
  ### Improvements

  * \[**Comments**]: Added mobile support for inline comment section, improving the user experience on smaller screens.
  * \[**Debugging**]: Now `client.getMetadata()` method only returns the currently set documents instead of all documents used in the current session.
</Update>

<Update label="4.1.0" description="Mar 4 2025">
  ### New Features

  * \[**Comments**]: Tiptap comments marks are now persisted automatically by default. This simplifies implementation as you no longer need to store marks yourself or modify your editor's content handling.
  * \[**Comments**]: Added Sorting Dropdown Wireframe support for inline comments section. [Learn more](/ui-customization/features/async/comments/inline-comments-section/subcomponents/panel/sorting-dropdown)

  ### Improvements

  * \[**Comments**]: Made the freestyle comment pins adapt to DOM elements with complex layouts.
  * \[**Comments**]: Improved loading skeleton in inline comments section to match comment card width and adapt responsively to smaller widths.
  * \[**Comments**]: Improved the alignment of the assign to dropdown in inline comments section when the width of the section is large.
  * \[**Comments**]: Added dark mode styling for the new sorting dropdown in inline comments section.

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where the comment bubble was not keeping the dialog open when a fresh annotation was added.
</Update>

<Update label="4.0.0-beta.27" description="Feb 28 2025">
  ### New Features

  * \[**Comments**]: Added a default sorting UI component in the inline comments section. This was one of the most requested features.
  * \[**Comments**]: Added config to prevent deleting the entire thread when the first comment is deleted.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      <VeltComments deleteThreadWithFirstComment={false} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      <velt-comments delete-thread-with-first-comment="false"></velt-comments>
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Comments**]: Improved the overall UI/UX of the inline comments section based on user feedback, including: loading state, inner padding, layout shift etc.

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where inline comments sorting was not working when the prop was changed dynamically.
  * \[**Comments**]: Fixed issue in single-threaded mode where delete thread label now correctly appears on the root comment regardless of sorting order.
</Update>

<Update label="4.0.0-beta.26" description="Feb 25 2025">
  ### New Features

  * \[**Core**]: Added ability to enable or disable Velt's logs/warnings in Browser Console.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      client.enableLogs();
      client.disableLogs();
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      Velt.enableLogs();
      Velt.disableLogs();
      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Core**]: Added performance improvements for scenarios where the user accesses and switches between large number of documents at a high frequency.
</Update>

<Update label="4.0.0-beta.25" description="Feb 20 2025">
  ### Improvements

  * \[**Recorder**]: Improved [`TranscriptionDoneEvent`](/api-reference/sdk/models/data-models#transcriptiondoneevent) object.

  * \[**Comments**]: Fixed `useSetDocuments` hook to properly support `setDocuments` method in dependency array in React `useEffect`:

  ```jsx theme={null}
  const { setDocuments } = useSetDocuments();
  useEffect(() => {
      setDocuments(yourDocuments);
  }, [setDocuments]);
  ```

  * \[**Comments**]: Made small UI improvements:
    * Removed 0 from Velt bubble count.
    * Fixed Velt bubble wireframe layout shift issue.

  ### Bug Fixes

  * \[**Comments**]: Fixed small UI issues:
    * Fixed an issue where draft comments were showing up when reaction was updated.
    * Fixed an issue where selecting a comment in inline comment section was also opening the Velt Comment bubble.
    * Fixed an issue where focused thread mode scroll was not working as expected.
</Update>

<Update label="4.0.0-beta.24" description="Feb 17 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where the SeenBy dropdown wasn't opening on the first click.
  * \[**Comments**]: Fixed an issue where clicking @mention button was not opening the mention dropdown. Typing @ was working as expected.
  * \[**Comments**]: Fixed a re-rendering issue when adding reactions.
</Update>

<Update label="4.0.0-beta.23" description="Feb 15 2025">
  ### New Features

  * \[**Core**]: Added `getUser` method to get the current user.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      const user = client.getUser();
      console.log(user);
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      const user = Velt.getUser();
      console.log(user);
      ```
    </Tab>
  </Tabs>

  * \[**UI Customization**]: Simplified how UI can be customized using wireframes.
    * Conditional Component Rendering: Conditionally render any component directly without needing to specify parent or sibling wireframes.
    * Conditional CSS Classes: Classes can now be conditionally applied to components based on the data in the component.
    * Wireframe CSS Classes Support: CSS Classes added to wireframes components are automatically applied to the related rendered components.

  <Tabs>
    <Tab title="React / Next.js">
      **Conditional Component Rendering:**

      ```jsx theme={null}
      // Old
      <VeltCommentDialogWireframe.Header>
        <VeltIf condition="{annotation.status.id} === 'OPEN'" >
            <VeltCommentDialogWireframe.Status />
        </VeltIf>
      </VeltCommentDialogWireframe.Header>


      // New
      <VeltCommentDialogWireframe.Status veltIf="{annotation.status.id} === 'OPEN'" />
      ```

      **Conditional CSS Classes:**

      ```jsx theme={null}
      <VeltCommentDialogWireframe.ThreadCard.Message veltClass="'color-yellow': {annotation.status.id} === 'in_progress'" />
      ```

      **Wireframe CSS Classes Support:**

      ```jsx theme={null}
      <VeltCommentDialogWireframe.ThreadCard.Message className="color-yellow" />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      **Conditional Component Rendering:**

      ```html theme={null}
      <!-- Old -->
      <velt-comment-dialog-header-wireframe>
        <velt-if condition="{annotation.status.id} === 'OPEN'" >
            <velt-comment-dialog-status-wireframe></velt-comment-dialog-status-wireframe>
        </velt-if>
      </velt-comment-dialog-header-wireframe>


      <!-- New -->
      <velt-comment-dialog-status-wireframe velt-if="{annotation.status.id} === 'OPEN'" >
      </velt-comment-dialog-status-wireframe>
      ```

      **Conditional CSS Classes:**

      ```jsx theme={null}
      <velt-comment-dialog-thread-card-message-wireframe velt-class="'color-yellow': {annotation.status.id} === 'in_progress'" > </velt-comment-dialog-thread-card-message-wireframe>
      ```

      **Wireframe CSS Classes Support:**

      ```html theme={null}
      <velt-comment-dialog-thread-card-message-wireframe class="color-yellow"> </velt-comment-dialog-thread-card-message-wireframe>
      ```
    </Tab>
  </Tabs>

  * \[**UI Customization**]: Set and render custom state data into Velt components. This data is available in all Velt Wireframes, Velt If and Velt Data components.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Setter
      client.setUiState({
          dashboardName: 'MRR Growth',
          anyKey: 'anyValue'
      });

      // Getter
      client.getUiState().subscribe((data) => {
          console.log('UI State: ', data);
      });

      // Use it in Velt Wireframe
      <VeltCommentDialogWireframe.Header>
          <VeltData field={dashboardName} />
      </VeltCommentDialogWireframe.Header>

      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      // Setter
      Velt.setUiState({
          dashboardName: 'MRR Growth',
          anyKey: 'anyValue'
      });

      // Getter
      Velt.getUiState().subscribe((data) => {
          console.log('UI State: ', data);
      });

      // Use it in Velt Wireframe
      <velt-wireframe style="display:none;">
          <velt-comment-dialog-wireframe.header>
              <velt-data field={dashboardName}></velt-data>
          </velt-comment-dialog-wireframe.header>
      </velt-wireframe>
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added support for custom autocomplete search for contact list or [custom lists](/async-collaboration/comments/customize-behavior#createcustomlistdataoncomment). You should use this if you have a large dataset that you want to plug into the autocomplete dropdown, and search directly your own data source.

  <Tabs>
    <Tab title="React / Next.js">
      **Enable the feature:**

      ```jsx theme={null}
      // Enable via props
      <VeltComments customAutocompleteSearch={true} />


      // Or, enable via Comment Element API
      const commentElement = client.getCommentElement();
      commentElement.enableCustomAutocompleteSearch();
      commentElement.disableCustomAutocompleteSearch();
      ```

      **Set initial list:**

      ```jsx theme={null}
      // For @mentions feature
      contactElement.updateContactList(users);

      // For custom list feature
      commentElement.createCustomListDataOnComment({
          hotkey: "#",
          type: "custom",
          data: customListData,
      });
      ```

      **Handle search event:**

      ```jsx theme={null}
      commentElement.on('autocompleteSearch').subscribe(async (inputData) => {
          const searchText = inputData.searchText;

          // For @mentions feature
          if (inputData.type === 'contact') {
              const filteredUsersData = await __your_api_call__(searchText);
              contactElement.updateContactList(filteredUsersData, { merge: false });
          }

          // For custom list feature
          if (inputData.type === 'custom') {
              const filteredListData = await __your_api_call__(searchText, autocompleteData);
              commentElement.createCustomListDataOnComment({
                  hotkey: "#",
                  type: "custom",
                  data: filteredListData,
              });
          }
      });

      interface AutocompleteSearchEvent {
          event: KeyboardEvent | InputEvent | Event;
          searchText: string;
          type?: 'contact' | 'custom';
          metadata?: VeltEventMetadata;
      }

      ```
    </Tab>

    <Tab title="Other Frameworks">
      **Enable the feature:**

      ```js theme={null}
      // Enable via attribute
      <velt-comments custom-autocomplete-search="true"></velt-comments>

      // Or, enable via Comment Element API
      const commentElement = Velt.getCommentElement();
      commentElement.enableCustomAutocompleteSearch();
      commentElement.disableCustomAutocompleteSearch();
      ```

      **Set initial list:**

      ```js theme={null}
      // For @mentions feature
      contactElement.updateContactList(users);

      // For custom list feature
      commentElement.createCustomListDataOnComment({
          hotkey: "#",
          type: "custom",
          data: customListData,
      });
      ```

      **Handle search event:**

      ```js theme={null}
      commentElement.on('autocompleteSearch').subscribe(async (inputData) => {
          const searchText = inputData.searchText;

          // For @mentions feature
          if (inputData.type === 'contact') {
              const filteredUsersData = await __your_api_call__(searchText);
              contactElement.updateContactList(filteredUsersData, { merge: false });
          }

          // For custom list feature
          if (inputData.type === 'custom') {
              const filteredListData = await __your_api_call__(searchText, autocompleteData);
              commentElement.createCustomListDataOnComment({
                  hotkey: "#",
                  type: "custom",
                  data: filteredListData,
              });
          }
      });

      interface AutocompleteSearchEvent {
          event: KeyboardEvent | InputEvent | Event;
          searchText: string;
          type?: 'contact' | 'custom';
          metadata?: VeltEventMetadata;
      }

      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added `composerClicked` event to detect when comment composer is clicked.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      const composerClickEvent = useCommentEventCallback('composerClicked');
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement.on('composerClicked').subscribe((data) => {
          console.log('Composer clicked', data);
      });
      ```
    </Tab>
  </Tabs>

  ### Bug Fixes

  * \[**Comments**]: Fixed assign comment input double border CSS issue.
</Update>

<Update label="4.0.0-beta.22" description="Feb 13 2025">
  ### New Features

  * \[**Folders**]: Introducing Folders! Organize documents hierarchically with granular access control. Modeled after Google Drive's folder structure.
    * Folders can contain documents and other folders.
    * Uses same permission model as Organizations and Documents.
    * APIs:
      * **Frontend**: Subscribe to folders and query by folderId.
      * **Backend**: CRUD operations for folders and access control. [Learn More](/api-reference/rest-apis/v2/folders/add-folder)
      * Added folder support to existing relevant APIs.

  * \[**Folders**]: API to subscribe to a particular folder and all its documents at the same time.

  <Tabs>
    <Tab title="React / Next.js">
      **Using Hooks:**

      ```jsx theme={null}
      const { setDocuments } = useSetDocuments();

      {/* Subscribe to a folder and all its documents */}
      const rootDocument = [
        {
          id: 'document-1',
          metadata: {
            documentName: 'Document 1'
          }
        }
      ];

      setDocuments(
        rootDocument,
        {
          folderId: 'folder1',
          allDocuments: true
        }
      );


      {/* Subscribe to a folder and some documents */}
      const documents = [
        {
          id: 'document-1',
          metadata: {
            documentName: 'Document 1'
          }
        },
        {
          id: 'document-2',
          metadata: {
            documentName: 'Document 2'
          }
        }
      ];

      setDocuments(
        documents,
        {
          folderId: 'folder1',
        }
      );
      ```

      **Using API:**

      ```jsx theme={null}
      {/* Subscribe to a folder and all its documents */}
      client.setDocuments(
        rootDocument,
        {
          folderId: 'folder1',
          allDocuments: true
        }
      );

      {/* Subscribe to a folder and some documents */}
      client.setDocuments(
        documents,
        {
          folderId: 'folder1',
        }
      );
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      // Subscribe to a folder and all its documents
      const rootDocument = [
        {
          id: 'document-1',
          metadata: {
            documentName: 'Document 1'
          }
        }
      ];

      Velt.setDocuments(
        rootDocument,
        {
          folderId: 'folder1',
          allDocuments: true
        }
      );

      // Subscribe to a folder and some documents

      const documents = [
        {
          id: 'document-1',
          metadata: {
            documentName: 'Document 1'
          }
        },
        {
          id: 'document-2',
          metadata: {
            documentName: 'Document 2'
          }
        }
      ];

      Velt.setDocuments(
        documents,
        {
          folderId: 'folder1',
        }
      );
      ```
    </Tab>
  </Tabs>

  * \[**Folders**]: Added an API to fetch folder metadata and subfolders by organizationId, folderId with pagination.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Get all folders for a specific organization
      client.fetchFolders({
        organizationId: 'org1'
      });

      // Get a specific folder's metadata with its immediate subfolders
      client.fetchFolders({
        organizationId: 'org1',
        folderId: 'folder1'
      });

      interface FetchFoldersRequest {
        organizationId?: string;
        folderId?: string;
      }

      interface FetchFoldersResponse {
        data: Record<string, FolderMetadata> | null;
        nextPageToken: string;
      }
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      // Get all folders for a specific organization
      Velt.fetchFolders({
        organizationId: 'org1'
      });

      // Get a specific folder's metadata with its immediate subfolders
      Velt.fetchFolders({
        organizationId: 'org1',
        folderId: 'folder1'
      });

      interface FetchFoldersRequest {
        organizationId?: string;
        folderId?: string;
      }

      interface FetchFoldersResponse {
        data: Record<string, FolderMetadata> | null;
        nextPageToken: string;
      }
      ```
    </Tab>
  </Tabs>

  * \[**Documents**]: Added an API to fetch document metadata by organizationId, folderId or documentIds with pagination.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Get all documents for a specific folder
      client.fetchDocuments({
        organizationId: 'org1', 
        folderId: 'folder1',
        allDocuments: true
      });

      // Get specific documents by IDs
      client.fetchDocuments({
        organizationId: 'org1',
        documentIds: ['doc1', 'doc2']
      });

      interface FetchDocumentsRequest {
        organizationId?: string;
        documentIds?: string[];
        folderId?: string;
        allDocuments?: boolean;
      }

      interface FetchDocumentsResponse {
        data: Record<string, DocumentMetadata> | null;
        nextPageToken: string;
      }
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      // Get all documents for a specific folder
      Velt.fetchDocuments({
        organizationId: 'org1', 
        folderId: 'folder1',
        allDocuments: true
      });

      // Get specific documents by IDs
      Velt.fetchDocuments({
      docElement.fetchDocuments({
        organizationId: 'org1',
        documentIds: ['doc1', 'doc2']
      });

      interface FetchDocumentsRequest {
        organizationId?: string;
        documentIds?: string[];
        folderId?: string;
        allDocuments?: boolean;
      }

      interface FetchDocumentsResponse {
        data: Record<string, DocumentMetadata> | null;
        nextPageToken: string;
      }
      ```
    </Tab>
  </Tabs>

  * \[**Comments**]: Added a new API to fetch comment annotations by organizationId, folderId or documentIds with pagination and filtering options. This is different from the existing subscription API which susbcribes to realtime changes to the comments data.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      // Get all annotations for a specific folder
      const commentElement = client.getCommentElement();
      commentElement.fetchCommentAnnotations({
        organizationId: 'org1', 
        folderId: 'folder1',
        allDocuments: true
      });

      // Get annotations for specific documents
      const commentElement = client.getCommentElement();
      commentElement.fetchCommentAnnotations({
        organizationId: 'org1',
        documentIds: ['doc1', 'doc2']
      });

      interface FetchCommentAnnotationsRequest {
        createdAfter?: number;
        createdBefore?: number;
        updatedAfter?: number;
        updatedBefore?: number;
        statusIds?: string[];
        order?: 'asc' | 'desc';
        pageToken?: string;
        allDocuments?: boolean;
        pageSize?: number;
        organizationId?: string;
        locationId?: string;
        documentIds?: string[];
        folderId?: string;
      }

      interface FetchCommentAnnotationsResponse {
        data: Record<string, CommentAnnotation[]> | null;
        nextPageToken: string;
      }
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      // Get all annotations for a specific folder
      const commentElement = Velt.getCommentElement();
      commentElement.fetchCommentAnnotations({
        organizationId: 'org1', 
        folderId: 'folder1',
        allDocuments: true
      });

      // Get annotations for specific documents
      const commentElement = Velt.getCommentElement();
      commentElement.fetchCommentAnnotations({
        organizationId: 'org1',
        documentIds: ['doc1', 'doc2']
      });

      interface FetchCommentAnnotationsRequest {
        createdAfter?: number;
        createdBefore?: number;
        updatedAfter?: number;
        updatedBefore?: number;
        statusIds?: string[];
        order?: 'asc' | 'desc';
        pageToken?: string;
        allDocuments?: boolean;
        pageSize?: number;
        organizationId?: string;
        locationId?: string;
        documentIds?: string[];
        folderId?: string;
      }

      interface FetchCommentAnnotationsResponse {
        data: Record<string, CommentAnnotation[]> | null;
        nextPageToken: string;
      }
      ```
    </Tab>
  </Tabs>
</Update>

<Update label="4.0.0-beta.21" description="Feb 11 2025">
  ### Features

  * \[**Self-hosting**] You can now self-host your user PII metadata.
    * Send only userId instead of full user object and a client side data provider.
    * Components will automatically fetch the user details from the provider and hydrate the user object.
    * The metadata will not be sent to Velt servers.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}

      const fetchUsersFromDB = async (userIds) => {
          // Fetch users from your DB
          const usersData = await getUsersFromYourDB(userIds);
          return formatUsersToRecord(usersData);
      };

      const formatUsersToRecord = (users) => {
          // Format users array into a Record object with userId as key and user data as value
          return users.reduce((record, user) => {
              record[user.userId] = {
                  userId: user.userId,
                  name: user.name,
                  // any other fields
              };
              return record;
          }, {});
      };

      <VeltProvider 
          apiKey='YOUR_API_KEY'
          userDataProvider={{
              getUsers: fetchUsersFromDB
          }}
      >
      </VeltProvider>

      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}

      Velt.setUserDataProvider({
          getUsers: fetchUsersFromDB
      });

      function fetchUsersFromDB(userIds) {
          // Fetch users from your DB
          const usersData = getUsersFromYourDB(userIds);
          return formatUsersToRecord(usersData);
      }

      function formatUsersToRecord(users) {
          // Format users array into a Record object with userId as key and user data as value
          return users.reduce((record, user) => {
              record[user.userId] = {
                  userId: user.userId,
                  name: user.name,
                  // any other fields
              };
              return record;
          }, {});
      }

      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Core**]: Added core performance improvements throughout the SDK.
  * \[**Recorder**]: Added new API methods to get the recorded data.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      const recorderElement = client.getRecorderElement();
      await recorderElement.getRecordingData({
          recorderIds: ['RECORDER_ID']
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      const recorderElement = Velt.getRecorderElement();
      await recorderElement.getRecordingData({
          recorderIds: ['RECORDER_ID']
      });
      ```
    </Tab>
  </Tabs>

  * \[**Recorder**] Added missing props to disable shadow DOM for recorder components in React SDK.

  ```jsx theme={null}
  <VeltRecorderNotes shadowDom={false} />
  <VeltRecorderTool shadowDom={false} />
  <VeltRecorderPlayer shadowDom={false} />
  ```
</Update>

<Update label="4.0.0-beta.20" description="Feb 10 2025">
  ### Bug Fixes

  * \[**Recorder**]: Fixed Safari recording compatibility issues across some macOS versions.
</Update>

<Update label="4.0.0-beta.19" description="Jan 31 2025">
  ### Features

  * \[**Core**]: Added support for React v19 in `sdk-react` library.

  ### Improvements

  * \[**Authentication**]: Made `organizationId` mandatory in `identify` method.
  * \[**New Accounts**]: New accounts or API keys will have advanced queries turned on by default.

  ### Bug Fixes

  * \[**Notifications**]: Fixed an issue where notifications were not working when organizationId was not set.
  * \[**REST API**]: Fixed an issue where the REST API for adding or updating organizations and documents did not allow custom fields in metadata.
</Update>

<Update label="4.0.0-beta.18" description="Jan 30 2025">
  ### Improvements

  * \[**Comments**]: Improved comments performance with optimistic local-first reads and writes.
  * \[**Notifications**]: Added `documentMetadata` object in the properties that are sent to SendGrid for emails.

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where custom metadata added to a comment using `addContext` was not sent to the first notification event (`newlyAdded`).
</Update>

<Update label="4.0.0-beta.17" description="Jan 29 2025">
  ### Features

  * \[**Comments**]: Added a `transcriptionDone` event callback when recording transcription is done.

  <Tabs>
    <Tab title="React / Next.js">
      **Using Hooks:**

      ```jsx theme={null}
      const onTranscriptionDone = useRecorderEventCallback('transcriptionDone');

      useEffect(() => {
          console.log(onTranscriptionDone);
      }, [onTranscriptionDone])

      ```

      **Using API:**

      ```jsx theme={null}
      const recorderElement = client.getRecorderElement();

      recorderElement.on('transcriptionDone').subscribe((data) => {
      	console.log('transcriptionDone', data);
      });

      ```
    </Tab>

    <Tab title="Other Frameworks">
      **Using API:**

      ```js theme={null}
      const recorderElement = Velt.getRecorderElement();

      recorderElement.on('transcriptionDone').subscribe((data) => {
      	console.log('transcriptionDone', data);
      });

      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Comments**]: Disabled @here in the contacts dropdown by default. You can turn it on using [this](/async-collaboration/comments/customize-behavior#enableathere).

  ### Bug Fixes

  * \[**Comments**]: Removed virtual scroll from autocomplete panel and removed fixed height. This was causing weird UI issues. We are rewriting the autocomplete panel with virtual scroll.
  * \[**Comments**]: Fixed an issue where horizontal scroll was visible on sidebar in some scenarios.
  * \[**Comments**]: Fixed an issue where the `shadowDom` prop was not passed down to page mode composer in comment sidebar.
  * \[**Comments**]: Fixed an issue where `sortData` prop was not working in comments sidebar.
</Update>

<Update label="4.0.0-beta.16" description="Jan 28 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where comments was not working for fresh documents if the advanced queries option wasn't enabled. Note this is mandatory for all versions of v4 SDK.
  * \[**Comments**]: Fixed an issue where [updateContactList](/async-collaboration/comments/customize-behavior#updatecontactlist) was not working.
  * \[**Comments**]: Fixed an issue where in inline comments, the resolve button was visible for all messages in a thread.
</Update>

<Update label="4.0.0-beta.15" description="Jan 24 2025">
  ### Features

  * \[**Self-hosting**] You can now self-host your user PII metadata.
    * Send only userId instead of full user object and a client side data provider.
    * Components will automatically fetch the user details from the provider and hydrate the user object.
    * The metadata will not be sent to Velt servers.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}

      const fetchUsersFromDB = async (userIds) => {
          // Fetch users from your DB
          const usersData = await getUsersFromYourDB(userIds);
          return formatUsersToRecord(usersData);
      };

      const formatUsersToRecord = (users) => {
          // Format users array into a Record object with userId as key and user data as value
          return users.reduce((record, user) => {
              record[user.userId] = {
                  userId: user.userId,
                  name: user.name,
                  // any other fields
              };
              return record;
          }, {});
      };

      <VeltProvider 
          apiKey='YOUR_API_KEY'
          userDataProvider={{
              getUsers: fetchUsersFromDB
          }}
      >
      </VeltProvider>

      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}

      Velt.setUserDataProvider({
          getUsers: fetchUsersFromDB
      });

      function fetchUsersFromDB(userIds) {
          // Fetch users from your DB
          const usersData = getUsersFromYourDB(userIds);
          return formatUsersToRecord(usersData);
      }

      function formatUsersToRecord(users) {
          // Format users array into a Record object with userId as key and user data as value
          return users.reduce((record, user) => {
              record[user.userId] = {
                  userId: user.userId,
                  name: user.name,
                  // any other fields
              };
              return record;
          }, {});
      }

      ```
    </Tab>
  </Tabs>

  ### Improvements

  * \[**Core**]: Added core performance improvements throughout the SDK.
  * \[**Recorder**]: Added new API methods to get the recorded data.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      const recorderElement = client.getRecorderElement();
      await recorderElement.getRecordingData({
          recorderIds: ['RECORDER_ID']
      });
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```js theme={null}
      const recorderElement = Velt.getRecorderElement();
      await recorderElement.getRecordingData({
          recorderIds: ['RECORDER_ID']
      });
      ```
    </Tab>
  </Tabs>

  * \[**Recorder**] Added missing props to disable shadow DOM for recorder components in React SDK.

  ```jsx theme={null}
  <VeltRecorderNotes shadowDom={false} />
  <VeltRecorderTool shadowDom={false} />
  <VeltRecorderPlayer shadowDom={false} />
  ```
</Update>

<Update label="4.0.0-beta.14" description="Jan 20 2025">
  ### Bug Fixes

  * \[**Recorder**]: Fixed Safari recording compatibility issues across some macOS versions.
</Update>

<Update label="4.0.0-beta.13" description="Jan 13 2025">
  ### Features

  * \[**Core**]: Added support for React v19 in `sdk-react` library.

  ### Improvements

  * \[**Authentication**]: Made `organizationId` mandatory in `identify` method.
  * \[**New Accounts**]: New accounts or API keys will have advanced queries turned on by default.

  ### Bug Fixes

  * \[**Notifications**]: Fixed an issue where notifications were not working when organizationId was not set.
  * \[**REST API**]: Fixed an issue where the REST API for adding or updating organizations and documents did not allow custom fields in metadata.
</Update>

<Update label="4.0.0-beta.12" description="Jan 10 2025">
  ### Improvements

  * \[**Comments**]: Improved comments performance with optimistic local-first reads and writes.
  * \[**Notifications**]: Added `documentMetadata` object in the properties that are sent to SendGrid for emails.

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where custom metadata added to a comment using `addContext` was not sent to the first notification event (`newlyAdded`).
</Update>

<Update label="4.0.0-beta.11" description="Jan 6 2025">
  ### Bug Fixes

  * \[**Comments**]: Fixed an issue with `getCommentAnnotationsCount` API when filtering by specific document IDs in the query.
</Update>

<Update label="4.0.0-beta.10" description="Dec 24 2024">
  ### Improvements

  * \[**Security**]: Merged security patch in the React package

  ### Bug Fixes

  * \[**Recorder**]: Fixed an issue where the floating recording player was visible for threaded recorder notes
  * \[**Comments**]: Fixed an issue where the sidebar button border color was using light mode colors in dark mode
</Update>

<Update label="4.0.0-beta.9" description="Dec 19 2024">
  ## New APIs

  ### 1. setDocuments

  * Set multiple documents at the same time. You can specify 30 documents at a time.

  * The first document in the list will be considered as the root document.

  * For features like comments, notifications, recorder, reactions etc. you will be able to read and write to multiple documents at the same time.

  * For features like cursors, presence, huddle, live state sync etc. it will default to the root document.

  * Sidebar will automatically show data from all the documents.

  * Params:
    * `documents`: [Document\[\]](/api-reference/sdk/models/data-models#document)
    * `options?`: [SetDocumentsRequestOptions](/api-reference/sdk/models/data-models#setdocumentsrequestoptions)

  <Tabs>
    <Tab title="React / Next.js">
      **Using Hooks:**

      ```jsx theme={null}
      const documents = [
        {
          id: 'document-1',
          metadata: {
            documentName: 'Document 1'
          }
        },
        {
          id: 'document-2',
          metadata: {
            documentName: 'Document 2'
          }
        }
      ];
      const { setDocuments } = useSetDocuments();
      setDocuments(documents);
      ```

      **Using API:**

      ```jsx theme={null}
      const documents = [
        {
          id: 'document-1',
          metadata: {
            documentName: 'Document 1'
          }
        },
        {
          id: 'document-2',
          metadata: {
            documentName: 'Document 2'
          }
        }
      ];
      client.setDocuments(documents);
      ```
    </Tab>

    <Tab title="Other Frameworks">
      **Using API:**

      ```js theme={null}
      const documents = [
        {
          id: 'document-1',
          metadata: {
            documentName: 'Document 1'
          }
        },
        {
          id: 'document-2',
          metadata: {
            documentName: 'Document 2'
          }
        }
      ];
      Velt.setDocuments(documents);
      ```
    </Tab>
  </Tabs>

  ### 2. getCommentAnnotations

  * Get all the comment annotations for all the specified documents.
  * You can specify 30 documents at a time.
  * If you don't specify any query, it will return data from the documents specified in the `setDocuments` method.

  <Tabs>
    <Tab title="React / Next.js">
      **Using Hooks:**

      ```jsx theme={null}
      const { data } = useGetCommentAnnotations(query);
      // initial data value will be null while the request is in progress
      ```

      **Using API:**

      ```jsx theme={null}
      const commentElement = client.getCommentElement();
      commentElement.getCommentAnnotations(query).subscribe((response) => {
        console.log(response.data);
        // initial data value will be null while the request is in progress
      });
      ```

      ```jsx theme={null}
      CommentRequestQuery {
        documentIds!: string[],
        locationIds!: string[],
        statusIds!: string[]
      };

      GetCommentAnnotationsResponse {
        data: Record<string, CommentAnnotation[]> | null; // Key: documentId, Value: CommentAnnotation[]
      };
      ```
    </Tab>

    <Tab title="Other Frameworks">
      **Using API:**

      ```js theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement.getCommentAnnotations(query).subscribe((response) => {
        console.log(response.data);
        // initial data value will be null while the request is in progress
      });
      ```

      ```js theme={null}
      CommentRequestQuery {
        documentIds!: string[],
        locationIds!: string[],
        statusIds!: string[]
      };

      GetCommentAnnotationsResponse {
        data: Record<string, CommentAnnotation[]>; // Key: documentId, Value: CommentAnnotation[]
      };
      ```
    </Tab>
  </Tabs>

  ### 3. getCommentAnnotationsCount

  * Get the total and unread comment annotations count of all the comment annotations for all the specified documents.
  * You can specify 30 documents at a time.
  * If you don't specify any query, it will return data from the documents specified in the `setDocuments` method.

  <Tabs>
    <Tab title="React / Next.js">
      **Using Hooks:**

      ```jsx theme={null}
      const { data } = useCommentAnnotationsCount(query);
      // initial data value will be null while the request is in progress
      ```

      **Using API:**

      ```jsx theme={null}
      const commentElement = client.getCommentElement();
      commentElement.getCommentAnnotationsCount(query).subscribe((response) => {
        console.log(response.data);
        // initial data value will be null while the request is in progress
      });
      ```

      ```jsx theme={null}
      CommentRequestQuery {
        documentIds!: string[],
        locationIds!: string[],
        statusIds!: string[]
      };

      GetCommentAnnotationsCountResponse {
        data: Record<string, CommentAnnotationsCount> | null; // Key: documentId, Value: CommentAnnotationsCount
      };

      CommentAnnotationsCount {
        unread: number,
        total: number
      }

      ```
    </Tab>

    <Tab title="Other Frameworks">
      **Using API:**

      ```js theme={null}
      const commentElement = Velt.getCommentElement();
      commentElement.getCommentAnnotationsCount(query).subscribe((response) => {
        console.log(response.data);
      });
      ```

      ```js theme={null}
      CommentRequestQuery {
        documentIds!: string[],
        locationIds!: string[],
        statusIds!: string[]
      };

      GetCommentAnnotationsCountResponse {
        data: Record<string, CommentAnnotationsCount>; // Key: documentId, Value: CommentAnnotationsCount
      };

      CommentAnnotationsCount {
        unread: number,
        total: number
      }

      ```
    </Tab>
  </Tabs>

  ### 4. Read/Write data from multiple documents on the same page

  * If you want to display data (eg: comments) from multiple documents on the same page, you can add `data-velt-document-id` attribute to the container that contains the `document`.
  * It will be used to identify which part of the DOM belongs to which document.

  ```html theme={null}
  <div class="document-container" data-velt-document-id="document-1">
    ...
  </div>

  <div class="document-container" data-velt-document-id="document-2">
    ...
  </div>

  <div class="document-container" data-velt-document-id="document-3">
    ...
  </div>
  ```

  ## Other updates

  ### New Features

  * \[**Comments**]: Added support for Status Filter in Comments Sidebar's main filter menu:
    * By default, the status filter is disabled in the main filter menu.
    * Currently, it doesn't support grouping.
    * Added Wireframe support for this. [Learn more](/ui-customization/features/async/comments/comments-sidebar/subcomponents/filter/subcomponents/status).
    * If you were using wireframes before, you will add this to your wireframes.

  <Tabs>
    <Tab title="React / Next.js">
      ```jsx theme={null}
      const filterConfig = {
        status: {
          enable: true,
          name: "Status",
          multiSelection: true,
        }
      };

      <VeltCommentsSidebar filterConfig={filterConfig} />
      ```
    </Tab>

    <Tab title="Other Frameworks">
      ```jsx theme={null}
      const filterConfig = {
        status: {
          enable: true,
          name: "Status",
          multiSelection: true,
        }
      };

      const commentsSidebar = document.querySelector(`velt-comments-sidebar`);
      commentsSidebar?.setAttribute("filter-config",JSON.stringify(filterConfig));
      ```
    </Tab>
  </Tabs>

  ### Bug Fixes

  * \[**Comments**]: Fixed an issue where empty state visibility was not visible when filter is applied and grouping was disabled.
  * \[**Comments**]: Fixed an issue where users could click on the comment in the sidebar and navigate to comments when they shouldn't.
</Update>
