diff --git a/docs/es-modules/index.html b/docs/es-modules/index.html index f17c2455e..d0a237935 100644 --- a/docs/es-modules/index.html +++ b/docs/es-modules/index.html @@ -80,7 +80,6 @@

Code examples:

  • Video Transformations
  • VAST & VPAID Support
  • Video Details
  • -
  • Visual Search
  • VR/360 Videos

  • /all build
  • diff --git a/docs/es-modules/visual-search.html b/docs/es-modules/visual-search.html deleted file mode 100644 index 12ed83dae..000000000 --- a/docs/es-modules/visual-search.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - - Cloudinary Video Player - - - - - -
    - -

    Cloudinary Video Player

    -

    Visual Search

    - - - -

    - Full documentation -

    -
    - - - - - - - diff --git a/docs/index.html b/docs/index.html index 350d2b0cb..9e82ce059 100644 --- a/docs/index.html +++ b/docs/index.html @@ -86,7 +86,6 @@

    Some code examples:

  • Video Transformations
  • VAST & VPAID Support
  • Video Details
  • -
  • Visual Search
  • VR/360 Videos

  • Embedded (iframe) player
  • diff --git a/docs/visual-search.html b/docs/visual-search.html deleted file mode 100644 index 4fdb405f6..000000000 --- a/docs/visual-search.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - Cloudinary Video Player - Visual Search - - - - - - - - - - - - - - - - - - -
    - -

    Cloudinary Video Player

    -

    Visual Search Plugin

    - - - -
    - -

    Playlist with mixed content

    - - - -

    - Full documentation -

    - -

    Example Code:

    -
    -      
    -    <video
    -      id="player"
    -      playsinline
    -      controls
    -      class="cld-video-player cld-fluid"
    -      width="500"
    -    ></video>
    -      
    -      
    -    // Initialize player with visual search plugin
    -    const player = cloudinary.videoPlayer('player', {
    -      cloudName: 'demo',
    -      publicId: 'elephants',
    -      visualSearch: true
    -    });
    -
    -      
    -    
    -
    - - diff --git a/src/config/configSchema.json b/src/config/configSchema.json index 98144c587..3e77e6e12 100644 --- a/src/config/configSchema.json +++ b/src/config/configSchema.json @@ -342,10 +342,6 @@ ], "default": false }, - "visualSearch": { - "type": "boolean", - "default": false - }, "interactionAreas": { "type": "object", "properties": { diff --git a/src/config/defaults.js b/src/config/defaults.js index 5b9f8d20b..94687714f 100644 --- a/src/config/defaults.js +++ b/src/config/defaults.js @@ -13,7 +13,6 @@ export default { pictureInPictureToggle: false, seekThumbnails: true, aiHighlightsGraph: false, - visualSearch: false, download: false, preload: PRELOAD.METADATA, textTrackSettings: false, diff --git a/src/index.all.js b/src/index.all.js index 1d2ada3c3..8b5807cdc 100644 --- a/src/index.all.js +++ b/src/index.all.js @@ -14,7 +14,6 @@ import './plugins/colors/colors.js'; import './plugins/ima/ima.js'; import './plugins/playlist/playlist.js'; import './plugins/interaction-areas/interaction-areas.js'; -import './plugins/visual-search/visual-search.js'; import './plugins/share/share.js'; import './components/shoppable-bar/shoppable.js'; import './components/recommendations-overlay/recommendations-overlay.js'; diff --git a/src/plugins/index.js b/src/plugins/index.js index d254b833c..03d8cd045 100644 --- a/src/plugins/index.js +++ b/src/plugins/index.js @@ -18,7 +18,6 @@ import imaPlugin from './ima'; import interactionAreas from './interaction-areas'; import playlist from './playlist'; import shoppable from './shoppable-plugin'; -import visualSearch from './visual-search'; import share from './share'; import adaptiveStreaming from './adaptive-streaming'; import textTracksManager from './text-tracks-manager'; @@ -42,7 +41,6 @@ const plugins = { playlist, shoppable, interactionAreas, - visualSearch, share, adaptiveStreaming, textTracksManager, diff --git a/src/plugins/visual-search/components/SearchButton.js b/src/plugins/visual-search/components/SearchButton.js deleted file mode 100644 index 1b87197de..000000000 --- a/src/plugins/visual-search/components/SearchButton.js +++ /dev/null @@ -1,23 +0,0 @@ -import videojs from 'video.js'; - -export const SearchButton = (onClick) => { - const button = videojs.dom.createEl('button', { - className: 'vjs-control vjs-button vjs-visual-search-button', - title: 'Search video content', - ariaLabel: 'Search video content' - }); - - const searchIcon = videojs.dom.createEl('span', { - className: 'vjs-icon-search' - }); - button.appendChild(searchIcon); - - const spinnerIcon = videojs.dom.createEl('span', { - className: 'vjs-loading-spinner' - }); - button.appendChild(spinnerIcon); - - button.addEventListener('click', onClick); - - return button; -}; diff --git a/src/plugins/visual-search/components/SearchInput.js b/src/plugins/visual-search/components/SearchInput.js deleted file mode 100644 index 69db040ac..000000000 --- a/src/plugins/visual-search/components/SearchInput.js +++ /dev/null @@ -1,54 +0,0 @@ -import videojs from 'video.js'; - -export const SearchInput = (onSearch, onClose) => { - const form = videojs.dom.createEl('form', { - className: 'vjs-visual-search-form' - }); - - const input = videojs.dom.createEl('input', { - className: 'vjs-visual-search-input', - type: 'text', - ariaLabel: 'Search input', - tabIndex: -1 - }); - - const closeButton = videojs.dom.createEl('button', { - className: 'vjs-control vjs-button vjs-visual-search-close', - type: 'button', - title: 'Close search', - ariaLabel: 'Close search', - tabIndex: -1 - }); - - // Add close icon - const closeIcon = videojs.dom.createEl('span', { - className: 'vjs-icon-close' - }); - closeButton.appendChild(closeIcon); - - form.appendChild(input); - form.appendChild(closeButton); - - // Handle search submission - form.addEventListener('submit', (e) => { - e.preventDefault(); - const query = input.value.trim(); - if (query) { - onSearch(query); - } - }); - - // Handle close button - closeButton.addEventListener('click', (e) => { - e.preventDefault(); - if (onClose) { - onClose(); - } - }); - - return { - element: form, - input, - closeButton - }; -}; diff --git a/src/plugins/visual-search/components/SearchResults.js b/src/plugins/visual-search/components/SearchResults.js deleted file mode 100644 index 8247b0094..000000000 --- a/src/plugins/visual-search/components/SearchResults.js +++ /dev/null @@ -1,72 +0,0 @@ -import videojs from 'video.js'; - -export const SearchResults = player => { - const clearMarkers = () => { - player.$$('.vjs-visual-search-marker').forEach(el => el.remove()); - player.$$('.vjs-visual-search-results-wrapper').forEach(el => el.remove()); - - // Remove the class that indicates search results are displayed - player.removeClass('vjs-visual-search-results-active'); - }; - - const displayResults = results => { - // Clear existing markers - clearMarkers(); - - const total = player.duration(); - const seekBar = player.controlBar.progressControl.seekBar; - - // Create wrapper for search results - const wrapperEl = videojs.dom.createEl('div', { - className: 'vjs-visual-search-results-wrapper', - role: 'presentation' - }); - - // Add markers for each result - results.forEach(result => { - const { start_time, end_time } = result; - const position = (start_time / total) * 100; - const width = ((end_time - start_time) / total) * 100; - const time = `${Math.floor(start_time / 60)}:${Math.floor(start_time % 60) - .toString() - .padStart(2, '0')}`; - - const markerEl = videojs.dom.createEl('div', { - className: 'vjs-control vjs-visual-search-marker', - style: `left: ${position}%; width: ${width}%`, - tabIndex: 0, - role: 'button', - title: `Search result at ${time}`, - ariaLabel: `Search result at ${time}` - }); - - wrapperEl.appendChild(markerEl); - - // Add click handler to jump to this time - markerEl.addEventListener('click', () => { - player.currentTime(start_time); - }); - - // Add keyboard support - markerEl.addEventListener('keydown', e => { - if (e.key === 'Enter' || e.key === ' ') { - e.preventDefault(); - player.currentTime(start_time); - } - }); - }); - - // Add wrapper to seek bar - seekBar.el().appendChild(wrapperEl); - - // Add a class to indicate search results are displayed - if (results.length > 0) { - player.addClass('vjs-visual-search-results-active'); - } - }; - - return { - displayResults, - clearMarkers - }; -}; diff --git a/src/plugins/visual-search/index.js b/src/plugins/visual-search/index.js deleted file mode 100644 index bab095131..000000000 --- a/src/plugins/visual-search/index.js +++ /dev/null @@ -1,9 +0,0 @@ -export default async function lazyVisualSearchPlugin(options) { - const player = this; - try { - const { default: initPlugin } = await import(/* webpackChunkName: "visual-search" */ './visual-search'); - player.ready(() => initPlugin(options, player)); - } catch (error) { - console.error('Failed to load plugin:', error); - } -} diff --git a/src/plugins/visual-search/visual-search.js b/src/plugins/visual-search/visual-search.js deleted file mode 100644 index 5ff168bdd..000000000 --- a/src/plugins/visual-search/visual-search.js +++ /dev/null @@ -1,123 +0,0 @@ -import videojs from 'video.js'; -import { SearchButton } from './components/SearchButton'; -import { SearchInput } from './components/SearchInput'; -import { SearchResults } from './components/SearchResults'; - -import './visual-search.scss'; - -const visualSearch = (options, player) => { - player.addClass('vjs-visual-search'); - - let isSearchActive = false; - - const searchResults = SearchResults(player); - - const performSearch = async query => { - const searchButton = player.$('.vjs-visual-search-button'); - searchButton.classList.add('vjs-waiting'); - - try { - const source = player.cloudinary.source(); - const publicId = source.publicId(); - const transformation = Object.assign({}, source.transformation()); - - transformation.flags = transformation.flags || []; - transformation.flags.push(`getinfo:search_b64_${btoa(query)}`); - - const visualSearchSrc = source.config().url(`${publicId}`, { transformation }); - - const response = await fetch(visualSearchSrc, { - method: 'GET', - headers: { - 'Content-Type': 'application/json' - } - }); - - if (!response.ok) { - throw new Error(`Search request failed with status: ${response.status}`); - } - - const results = await response.json(); - searchResults.displayResults(results.timestamps); - - if (results && !player.hasStarted()) { - // Make sure the progress bar is visible - player.play().then(() => player.pause()); - } - } catch (error) { - console.error('Error performing visual search:', error); - } finally { - searchButton.classList.remove('vjs-waiting'); - } - }; - - const clearUI = () => { - isSearchActive = false; - searchResults.clearMarkers(); - player.$('.vjs-visual-search-wrapper')?.remove(); - }; - - const createSearchUI = () => { - clearUI(); - - const titleBar = player.$('.vjs-title-bar'); - if (titleBar) { - titleBar.classList.remove('vjs-hidden'); - } - - const searchContainer = videojs.dom.createEl('div', { - className: 'vjs-visual-search-wrapper' - }); - - // Handle the search icon click (expand or submit) - const handleSearchButtonClick = () => { - if (!isSearchActive) { - isSearchActive = true; - searchContainer.classList.add('vjs-visual-search-active'); - searchInput.input.tabIndex = 0; - searchInput.closeButton.tabIndex = 0; - searchInput.input.focus(); - } else { - const query = searchInput.input.value.trim(); - if (query) { - performSearch(query); - } - } - }; - - const closeSearch = () => { - if (isSearchActive) { - isSearchActive = false; - searchContainer.classList.remove('vjs-visual-search-active'); - searchInput.input.value = ''; - searchInput.input.tabIndex = -1; - searchInput.closeButton.tabIndex = -1; - - searchResults.clearMarkers(); - } - }; - - const searchButton = SearchButton(handleSearchButtonClick); - const searchInput = SearchInput(performSearch, closeSearch); - searchContainer.appendChild(searchButton); - searchContainer.appendChild(searchInput.element); - - titleBar.prepend(searchContainer); - - player.on('keydown', e => { - if (e.key === 'Escape' && isSearchActive) { - closeSearch(); - } - }); - }; - - createSearchUI(); - - // Public methods - player.visualSearch = { - createSearchUI, - clearUI - }; -}; - -export default visualSearch; diff --git a/src/plugins/visual-search/visual-search.scss b/src/plugins/visual-search/visual-search.scss deleted file mode 100644 index 52813afb4..000000000 --- a/src/plugins/visual-search/visual-search.scss +++ /dev/null @@ -1,183 +0,0 @@ -.vjs-visual-search { - .vjs-visual-search-wrapper { - position: absolute; - top: 1.5em; - right: 1.5em; - margin-left: auto; - display: flex; - align-items: center; - transition: all 0.3s ease; - border-radius: 1.5em; - overflow: hidden; - background-color: transparent; - pointer-events: auto; - - &.vjs-visual-search-active { - background-color: color-mix(in srgb, var(--color-base) 60%, transparent); - backdrop-filter: blur(10px); - - .vjs-visual-search-form { - width: 13.75em; - margin-right: 0.25em; - opacity: 1; - } - - .vjs-visual-search-button { - background-color: transparent; - text-shadow: none; - - &:hover { - text-shadow: 0 0 0.5em var(--color-accent); - } - } - } - - &:hover:not(.vjs-visual-search-active) { - .vjs-visual-search-button { - background-color: color-mix(in srgb, var(--color-base) 25%, transparent); - } - } - - + .vjs-title-bar-title { - padding-right: 2em; - } - } - - .vjs-visual-search-button { - background: transparent; - border: none; - color: var(--color-text); - cursor: pointer; - width: 2.75em; - height: 2.75em; - padding: 0.1em; - opacity: 0.9; - border-radius: 50%; - transition: all 0.25s ease; - z-index: 2; - flex-shrink: 0; - text-shadow: 0 0 1em var(--color-base); - - &:hover { - opacity: 1; - } - - > span:before { - font-size: 1.8em; - } - - .vjs-loading-spinner { - display: none; - width: 2.15em; - height: 2.15em; - position: absolute; - top: 0.3em; - left: 0.3em; - border-width: 0.4em; - transform: none; - } - - &.vjs-waiting { - > .vjs-icon-search { - display: none; - } - > .vjs-loading-spinner { - display: flex; - } - } - } - - .vjs-visual-search-form { - display: flex; - align-items: center; - width: 0; - opacity: 0; - transition: all 0.3s ease; - overflow: hidden; - } - - .vjs-visual-search-input { - background: transparent; - border: none; - color: var(--color-text); - font-size: 0.938em; - padding: 0; - width: 100%; - height: 2.25em; - outline: none; - - &::placeholder { - color: color-mix(in srgb, white 70%, transparent); - } - } - - .vjs-visual-search-close { - background: transparent; - border: none; - color: var(--color-text); - cursor: pointer; - width: 2em; - height: 2em; - padding: 0.25em; - opacity: 0.7; - transition: opacity 0.2s ease; - flex-shrink: 0; - text-shadow: 0 0 0.25em var(--color-base); - - &:hover { - opacity: 1; - } - - .vjs-icon-close:before { - font-size: 1em; - } - } - - .vjs-visual-search-results-wrapper { - position: absolute; - bottom: 100%; - left: 0; - width: 100%; - height: 0.75em; - z-index: 1; - $bg1: color-mix(in srgb, var(--color-accent) 15%, transparent); - $bg2: color-mix(in srgb, var(--color-base) 20%, transparent); - background: - linear-gradient(to right, $bg1, $bg1), - linear-gradient(to right, $bg2, $bg2); - } - - .vjs-visual-search-marker { - position: absolute; - height: 100%; - background-color: var(--color-accent); - opacity: 0.7; - pointer-events: auto; - cursor: pointer; - transition: opacity 0.2s ease; - - &:hover { - opacity: 0.8; - } - - &:focus { - box-shadow: inset 0 0 0 0.1em color-mix(in srgb, var(--color-text) 50%, transparent); - } - } -} - -// Push seek-thumbs/chapters/time up when search results are active -.vjs-visual-search-results-active { - .vjs-mouse-display { - translate: 0 -0.75em; - } -} - -@keyframes vjs-visual-search-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/src/utils/get-analytics-player-options.js b/src/utils/get-analytics-player-options.js index c7e5b6144..f32c00730 100644 --- a/src/utils/get-analytics-player-options.js +++ b/src/utils/get-analytics-player-options.js @@ -28,7 +28,6 @@ const getSourceOptions = (sourceOptions = {}) => ({ if (sourceOptions.chapters) return 'inline-chapters'; return undefined; })(), - visualSearch: sourceOptions.visualSearch, download: sourceOptions.download === true ? true : undefined, hdr: sourceOptions.hdr === true ? true : undefined, recommendations: sourceOptions.recommendations && sourceOptions.recommendations.length, diff --git a/src/validators/validators.js b/src/validators/validators.js index aadf01dd5..16744cdb3 100644 --- a/src/validators/validators.js +++ b/src/validators/validators.js @@ -100,7 +100,6 @@ export const sourceValidators = { resourceType: validator.isString, shoppable: validator.isPlainObject, chapters: validator.or(validator.isBoolean, validator.isPlainObject), - visualSearch: validator.or(validator.isBoolean), download: validator.isBoolean, title: validator.or(validator.isString, validator.isBoolean), description: validator.or(validator.isString, validator.isBoolean), diff --git a/src/video-player.const.js b/src/video-player.const.js index 05a4b5324..103ef217d 100644 --- a/src/video-player.const.js +++ b/src/video-player.const.js @@ -29,7 +29,6 @@ export const SOURCE_PARAMS = [ 'title', 'transformation', 'type', - 'visualSearch', 'withCredentials', 'videoSources' ]; diff --git a/src/video-player.js b/src/video-player.js index 01620efde..fab754c35 100644 --- a/src/video-player.js +++ b/src/video-player.js @@ -202,7 +202,6 @@ class VideoPlayer { this._initAnalytics(); this._initCloudinaryAnalytics(); this._initFloatingPlayer(); - this._initVisualSearch(); this._initShare(); this._initColors(); this._initTextTracks(); @@ -347,19 +346,6 @@ class VideoPlayer { }); } - _initVisualSearch() { - // Listen for source changes to apply visual search based on source config - this.videojs.on(PLAYER_EVENT.CLD_SOURCE_CHANGED, (e, { source }) => { - if (source?._visualSearch && this.videojs.visualSearch) { - isFunction(this.videojs.visualSearch) - ? this.videojs.visualSearch(source._visualSearch) - : this.videojs.visualSearch.createSearchUI(source._visualSearch); - } else if (!source?._visualSearch && this.videojs.visualSearch?.clearUI) { - this.videojs.visualSearch.clearUI(); - } - }); - } - _initShare() { // Listen for source changes to apply Share plugin based on source config this.videojs.on(PLAYER_EVENT.CLD_SOURCE_CHANGED, (e, { source }) => { diff --git a/src/video-player.utils.js b/src/video-player.utils.js index 52320b99d..70ce3486d 100644 --- a/src/video-player.utils.js +++ b/src/video-player.utils.js @@ -110,7 +110,7 @@ export const splitOptions = (flatOptions) => { delete playerOptions.cloudinaryConfig; } - // Source-level config (visualSearch, chapters, etc.) + // Source-level config (chapters, textTracks, etc.) playerOptions.sourceOptions = Utils.sliceAndUnsetProperties(playerOptions, ...SOURCE_PARAMS); // Allow explicitly passing options to videojs using the `videojs` namespace, in order diff --git a/test/e2e/specs/NonESM/visualSearchPage.spec.ts b/test/e2e/specs/NonESM/visualSearchPage.spec.ts deleted file mode 100644 index c355a71e5..000000000 --- a/test/e2e/specs/NonESM/visualSearchPage.spec.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { vpTest } from '../../fixtures/vpTest'; -import { test } from '@playwright/test'; -import { waitForPageToLoadWithTimeout } from '../../src/helpers/waitForPageToLoadWithTimeout'; -import { getLinkByName } from '../../testData/pageLinksData'; -import { ExampleLinkName } from '../../testData/ExampleLinkNames'; - -const link = getLinkByName(ExampleLinkName.VisualSearch); - -vpTest(`Test if video on visual search page is playing as expected`, async ({ page, pomPages }) => { - await test.step('Navigate to visual search page by clicking on link', async () => { - await pomPages.mainPage.clickLinkByName(link.name); - await waitForPageToLoadWithTimeout(page, 10000); - }); - - // Wait for both video elements to be ready - await test.step('Wait for video elements to be ready', async () => { - await pomPages.visualSearchPage.visualSearchVideoComponent.locator.scrollIntoViewIfNeeded(); - await pomPages.visualSearchPage.visualSearchPlaylistVideoComponent.locator.scrollIntoViewIfNeeded(); - }); - - await test.step('Click play button on visual search plugin video', async () => { - await pomPages.visualSearchPage.visualSearchVideoComponent.clickPlay(); - }); - - await test.step('Validating that visual search plugin video is playing', async () => { - await pomPages.visualSearchPage.visualSearchVideoComponent.validateVideoIsPlaying(true); - }); - - await test.step('Click play button on mixed content video', async () => { - await pomPages.visualSearchPage.visualSearchPlaylistVideoComponent.clickPlay(); - }); - - await test.step('Validating that visual mixed content video is playing', async () => { - await pomPages.visualSearchPage.visualSearchPlaylistVideoComponent.validateVideoIsPlaying(true); - }); -}); diff --git a/test/e2e/src/pom/PageManager.ts b/test/e2e/src/pom/PageManager.ts index 7f2bcea76..2bdc2fee8 100644 --- a/test/e2e/src/pom/PageManager.ts +++ b/test/e2e/src/pom/PageManager.ts @@ -30,7 +30,6 @@ import { SubtitlesAndCaptionsPage } from './subtitlesAndCaptionsPage'; import { VideoTransformationsPage } from './videoTransformationsPage'; import { VastAndVpaidPage } from './vastAndVpaidPage'; import { Vr360VideosPage } from './vr360VideosPage'; -import { VisualSearchPage } from './visualSearchPage'; import { SharePluginPage } from './sharePluginPage'; /** @@ -207,12 +206,5 @@ export class PageManager { public get vr360VideosPage(): Vr360VideosPage { return this.getPage(Vr360VideosPage); } - - /** - * Returns visual search page object - */ - public get visualSearchPage(): VisualSearchPage { - return this.getPage(VisualSearchPage); - } } export default PageManager; diff --git a/test/e2e/src/pom/visualSearchPage.ts b/test/e2e/src/pom/visualSearchPage.ts deleted file mode 100644 index 2bb506434..000000000 --- a/test/e2e/src/pom/visualSearchPage.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Page } from '@playwright/test'; -import { VideoComponent } from '../../components/videoComponent'; -import { BasePage } from './BasePage'; - -const VISUAL_SEARCH_PAGE_VIDEO_SELECTOR = '//*[@id="player_html5_api"]'; -const VISUAL_SEARCH_PLAYLIST_VIDEO_SELECTOR = '//*[@id="player-playlist_html5_api"]'; - -/** - * Video player examples visual search page object - */ -export class VisualSearchPage extends BasePage { - public visualSearchVideoComponent: VideoComponent; - public visualSearchPlaylistVideoComponent: VideoComponent; - - constructor(page: Page) { - super(page); - this.visualSearchVideoComponent = new VideoComponent(page, VISUAL_SEARCH_PAGE_VIDEO_SELECTOR); - this.visualSearchPlaylistVideoComponent = new VideoComponent(page, VISUAL_SEARCH_PLAYLIST_VIDEO_SELECTOR); - } -} diff --git a/test/e2e/testData/ExampleLinkNames.ts b/test/e2e/testData/ExampleLinkNames.ts index b4943366b..3665fab94 100644 --- a/test/e2e/testData/ExampleLinkNames.ts +++ b/test/e2e/testData/ExampleLinkNames.ts @@ -42,7 +42,6 @@ export enum ExampleLinkName { AllBuild = '/all build', ShareAndDownload = 'Share & Download', SourceSwitcher = 'Source switcher', - VisualSearch = 'Visual Search', VideoDetails = 'Video Details', EntryPoints = 'Entry Points (all exports)', LazyPlayer = 'Lazy player', diff --git a/test/e2e/testData/pageLinksData.ts b/test/e2e/testData/pageLinksData.ts index 35b57edc2..82a0bf11b 100644 --- a/test/e2e/testData/pageLinksData.ts +++ b/test/e2e/testData/pageLinksData.ts @@ -44,7 +44,6 @@ export const LINKS: ExampleLinkType[] = [ { name: ExampleLinkName.VR360Videos, endpoint: '360.html' }, { name: ExampleLinkName.EmbeddedIframePlayer, endpoint: 'embedded-iframe.html' }, { name: ExampleLinkName.ESMImports, endpoint: 'cld-vp-esm-pages.netlify.app' }, - { name: ExampleLinkName.VisualSearch, endpoint: 'visual-search.html' }, { name: ExampleLinkName.VideoDetails, endpoint: 'video-details.html' }, ];