Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
b419255
Add audio-only player example
devin-ai-integration[bot] Oct 7, 2026
3a8f62a
Add keep the control bar visible example
devin-ai-integration[bot] Oct 7, 2026
a75c7eb
Add Conviva analytics example
devin-ai-integration[bot] Oct 7, 2026
64e20dd
Add Millicast example
devin-ai-integration[bot] Oct 7, 2026
33baedc
Add THEOlive example with latency readout
devin-ai-integration[bot] Oct 7, 2026
a921513
Add Dolby Atmos, Dolby Vision and HDR detection examples
devin-ai-integration[bot] Oct 7, 2026
b00b861
Add a search bar to the examples overview
devin-ai-integration[bot] Oct 7, 2026
03c7b40
Fix audio-only example iframe height, poster and idle hiding
devin-ai-integration[bot] Oct 7, 2026
7b50bab
Move spatialRendering into the audio configuration
devin-ai-integration[bot] Oct 7, 2026
5d02f15
Probe dvh1 and dvhe codecs and fix Dolby Vision status levels
devin-ai-integration[bot] Oct 7, 2026
25f2e25
Set Conviva example source after creating the connector
devin-ai-integration[bot] Oct 7, 2026
1c85b0b
Hide the audio-only media layer and fix the player height
devin-ai-integration[bot] Oct 7, 2026
a1eb06a
Fix detection summaries and the THEOlive readout sentence
devin-ai-integration[bot] Oct 7, 2026
feb6c93
Remove the HDR example
devin-ai-integration[bot] Oct 7, 2026
5e8127b
Add credential inputs and a detailed event log to the Conviva example
devin-ai-integration[bot] Oct 7, 2026
63f67f5
Fix Conviva panel layout, event log columns and iframe scrollbars
devin-ai-integration[bot] Oct 7, 2026
cefeb14
Extract searchable doc card list logic into shared hook and component
devin-ai-integration[bot] Oct 7, 2026
a954052
Clarify Dolby Vision status wording
devin-ai-integration[bot] Oct 7, 2026
0525a73
Show remaining time in audio-only demo and use OptiView product names
devin-ai-integration[bot] Oct 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions spellcheck/dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1021,3 +1021,6 @@ yospace-connector-web
Yottabyte
Youbora
Zettabyte
HLG
HLG-compatible
UIs
109 changes: 109 additions & 0 deletions src/components/DocCardListSearch/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { Fragment, useMemo, useState, type JSX } from 'react';
import DocCardList, { type Props as DocCardListProps } from '@theme/DocCardList';
import { useDocsVersion } from '@docusaurus/plugin-content-docs/client';
import { PropSidebarItem, PropSidebarItemCategory } from '@docusaurus/plugin-content-docs';
import Heading, { type HeadingType } from '@theme/Heading';
import styles from './styles.module.css';

export interface DocCardGroup {
label?: string;
items: PropSidebarItem[];
}

export function isCategory(item: PropSidebarItem): item is PropSidebarItemCategory {
return item.type === 'category';
}

function itemText(item: PropSidebarItem, groupLabel: string, description?: string): string {
const label = item.type === 'link' || item.type === 'category' ? item.label : '';
return `${label} ${description ?? ''} ${groupLabel}`.toLowerCase();
}

// Filters groups by whitespace-separated terms (all must match) against
// item label + doc description + group label.
// Category items match on their label + group label. Empty groups are dropped.
// With an empty query, returns groups unchanged.
export function useDocCardListSearch(groups: DocCardGroup[]): {
query: string;
setQuery: (q: string) => void;
filteredGroups: DocCardGroup[];
noMatches: boolean;
} {
const { docs } = useDocsVersion();
const [query, setQuery] = useState('');

const filteredGroups = useMemo(() => {
const terms = query.trim().toLowerCase().split(/\s+/).filter(Boolean);
if (terms.length === 0) return groups;
return groups
.map((group) => ({
...group,
items: group.items.filter((item) => {
const haystack =
item.type === 'link'
? itemText(item, group.label ?? '', item.docId ? docs[item.docId]?.description : undefined)
: item.type === 'category'
? itemText(item, group.label ?? '')
: '';
return terms.every((term) => haystack.includes(term));
}),
}))
.filter((group) => group.items.length > 0);
}, [query, groups, docs]);

return { query, setQuery, filteredGroups, noMatches: query.trim() !== '' && filteredGroups.length === 0 };
}

export function DocCardListSearchInput({
query,
onQueryChange,
placeholder = 'Search…',
}: {
query: string;
onQueryChange: (q: string) => void;
placeholder?: string;
}): JSX.Element {
return (
<input
type="search"
className={styles.searchInput}
placeholder={placeholder}
aria-label={placeholder}
value={query}
onChange={(event) => onQueryChange(event.target.value)}
onKeyDown={(event) => {
if (event.key === 'Escape') onQueryChange('');
}}
/>
);
}

export interface SearchableDocCardGroupsProps extends Omit<DocCardListProps, 'items'> {
groups: DocCardGroup[];
headingLevel?: HeadingType;
searchable?: boolean;
searchPlaceholder?: string;
}

export default function SearchableDocCardGroups({
groups,
headingLevel,
searchable = false,
searchPlaceholder = 'Search…',
...props
}: SearchableDocCardGroupsProps): JSX.Element {
const { query, setQuery, filteredGroups, noMatches } = useDocCardListSearch(groups);

return (
<>
{searchable && <DocCardListSearchInput query={query} onQueryChange={setQuery} placeholder={searchPlaceholder} />}
{noMatches && <p>No results match “{query.trim()}”.</p>}
{filteredGroups.map((group, index) => (
<Fragment key={group.label ?? index}>
{group.label && headingLevel && <Heading as={headingLevel}>{group.label}</Heading>}
<DocCardList items={group.items} {...props} />
</Fragment>
))}
</>
);
}
12 changes: 12 additions & 0 deletions src/components/DocCardListSearch/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.searchInput {
display: block;
width: 100%;
max-width: 32rem;
margin-bottom: 1.5rem;
padding: 0.5rem 0.75rem;
font: inherit;
color: var(--ifm-font-color-base);
background: var(--ifm-background-surface-color);
border: 1px solid var(--ifm-color-emphasis-300);
border-radius: var(--ifm-global-radius);
}
30 changes: 14 additions & 16 deletions src/components/SidebarCategoryDocCardList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
import { Fragment } from 'react';
import DocCardList, { type Props as DocCardListProps } from '@theme/DocCardList';
import type { JSX } from 'react';
import type { Props as DocCardListProps } from '@theme/DocCardList';
import { useDocsSidebar } from '@docusaurus/plugin-content-docs/client';
import { PropSidebarItem, PropSidebarItemCategory } from '@docusaurus/plugin-content-docs';
import Heading, { type HeadingType } from '@theme/Heading';
import type { HeadingType } from '@theme/Heading';
import SearchableDocCardGroups, { isCategory } from '../DocCardListSearch';

export interface Props extends Omit<DocCardListProps, 'items'> {
headingLevel?: HeadingType;
searchable?: boolean;
searchPlaceholder?: string;
}

function isCategory(item: PropSidebarItem): item is PropSidebarItemCategory {
return item.type === 'category';
}

export default function SidebarCategoryDocCardList({ headingLevel, ...props }: Props) {
export default function SidebarCategoryDocCardList({ headingLevel = 'h2', searchable = false, searchPlaceholder, ...props }: Props): JSX.Element {
const sidebar = useDocsSidebar();
const categories = sidebar?.items.filter(isCategory) ?? [];
return categories.map((category) => (
<Fragment key={category.label}>
<Heading as={headingLevel ?? 'h2'}>{category.label}</Heading>
<DocCardList items={category.items} {...props} />
</Fragment>
));
const groups = (sidebar?.items.filter(isCategory) ?? []).map((category) => ({
label: category.label,
items: category.items,
}));
return (
<SearchableDocCardGroups groups={groups} headingLevel={headingLevel} searchable={searchable} searchPlaceholder={searchPlaceholder} {...props} />
);
}
30 changes: 11 additions & 19 deletions src/components/SidebarDocCardList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,23 @@
import { Fragment } from 'react';
import type { JSX } from 'react';
import { useDoc, useDocsSidebar } from '@docusaurus/plugin-content-docs/client';
import DocCardList, { type Props as DocCardListProps } from '@theme/DocCardList';
import { PropSidebarItem, PropSidebarItemCategory } from '@docusaurus/plugin-content-docs';
import Heading, { type HeadingType } from '@theme/Heading';
import type { Props as DocCardListProps } from '@theme/DocCardList';
import type { HeadingType } from '@theme/Heading';
import SearchableDocCardGroups, { isCategory } from '../DocCardListSearch';

export interface Props extends Omit<DocCardListProps, 'items'> {
headingLevel?: HeadingType;
searchable?: boolean;
searchPlaceholder?: string;
}

function isCategory(item: PropSidebarItem): item is PropSidebarItemCategory {
return item.type === 'category';
}

export default function SidebarDocCardList({ headingLevel, ...props }: Props) {
export default function SidebarDocCardList({ headingLevel, searchable = false, searchPlaceholder, ...props }: Props): JSX.Element {
const doc = useDoc();
const sidebar = useDocsSidebar();
const items = (sidebar?.items ?? [])
// Hide the current doc page from list
.filter((item) => !(item.type === 'link' && item.docId === doc.metadata.id));
if (headingLevel) {
const subcategories = items.filter(isCategory);
return subcategories.map((subcategory) => (
<Fragment key={subcategory.label}>
<Heading as={headingLevel}>{subcategory.label}</Heading>
<DocCardList items={subcategory.items} {...props} />
</Fragment>
));
}
return <DocCardList items={items} {...props} />;
const groups = headingLevel ? items.filter(isCategory).map((subcategory) => ({ label: subcategory.label, items: subcategory.items })) : [{ items }];
return (
<SearchableDocCardGroups groups={groups} headingLevel={headingLevel} searchable={searchable} searchPlaceholder={searchPlaceholder} {...props} />
);
}
30 changes: 14 additions & 16 deletions src/components/SubcategoryDocCardList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
import { Fragment } from 'react';
import DocCardList, { type Props as DocCardListProps } from '@theme/DocCardList';
import type { JSX } from 'react';
import type { Props as DocCardListProps } from '@theme/DocCardList';
import { useCurrentSidebarCategory } from '@docusaurus/plugin-content-docs/client';
import { PropSidebarItem, PropSidebarItemCategory } from '@docusaurus/plugin-content-docs';
import Heading, { type HeadingType } from '@theme/Heading';
import type { HeadingType } from '@theme/Heading';
import SearchableDocCardGroups, { isCategory } from '../DocCardListSearch';

export interface Props extends Omit<DocCardListProps, 'items'> {
headingLevel?: HeadingType;
searchable?: boolean;
searchPlaceholder?: string;
}

function isCategory(item: PropSidebarItem): item is PropSidebarItemCategory {
return item.type === 'category';
}

export default function SubcategoryDocCardList({ headingLevel, ...props }: Props) {
export default function SubcategoryDocCardList({ headingLevel = 'h2', searchable = false, searchPlaceholder, ...props }: Props): JSX.Element {
const category = useCurrentSidebarCategory();
const subcategories = category.items.filter(isCategory);
return subcategories.map((subcategory) => (
<Fragment key={subcategory.label}>
<Heading as={headingLevel ?? 'h2'}>{subcategory.label}</Heading>
<DocCardList items={subcategory.items} {...props} />
</Fragment>
));
const groups = category.items.filter(isCategory).map((subcategory) => ({
label: subcategory.label,
items: subcategory.items,
}));
return (
<SearchableDocCardGroups groups={groups} headingLevel={headingLevel} searchable={searchable} searchPlaceholder={searchPlaceholder} {...props} />
);
}
Loading
Loading