mirror of
https://github.com/zoriya/v10.git
synced 2026-08-09 23:58:06 +00:00
221 lines
8.7 KiB
Plaintext
221 lines
8.7 KiB
Plaintext
---
|
||
import { getCollection } from 'astro:content';
|
||
import ContentWidth from '@/components/frames/ContentWidth.astro';
|
||
import MarkdownCode from '@/components/typography/MarkdownCode.astro';
|
||
import Table from '@/components/typography/Table.astro';
|
||
import Tbody from '@/components/typography/Tbody.astro';
|
||
import Td from '@/components/typography/Td.astro';
|
||
import Th from '@/components/typography/Th.astro';
|
||
import Thead from '@/components/typography/Thead.astro';
|
||
import Tr from '@/components/typography/Tr.astro';
|
||
import { isValidFramework } from '@/types/docs';
|
||
import type { PresetReference as PresetReferenceType } from '@/types/preset-reference';
|
||
import DocsLink from '../DocsLink.astro';
|
||
import FrameworkCase from '../FrameworkCase.astro';
|
||
import InlineMarkdown from './InlineMarkdown.astro';
|
||
|
||
const entries = await getCollection('presetReference');
|
||
const PINNED_PRESETS = ['video', 'audio'];
|
||
const presets: PresetReferenceType[] = entries
|
||
.map((e) => e.data)
|
||
.sort((a, b) => {
|
||
const aPin = PINNED_PRESETS.indexOf(a.name);
|
||
const bPin = PINNED_PRESETS.indexOf(b.name);
|
||
if (aPin !== -1 && bPin !== -1) return aPin - bPin;
|
||
if (aPin !== -1) return -1;
|
||
if (bPin !== -1) return 1;
|
||
return a.name.localeCompare(b.name);
|
||
});
|
||
|
||
const { framework } = Astro.params;
|
||
const pkg = framework && isValidFramework(framework) ? `@videojs/${framework}` : '@videojs/html';
|
||
|
||
/**
|
||
* Native media elements used by presets that don't have a custom element.
|
||
* The pipeline can't detect these since they're not classes with `static tagName`.
|
||
*/
|
||
const NATIVE_MEDIA_ELEMENTS: Record<string, string> = {
|
||
video: 'video',
|
||
audio: 'audio',
|
||
};
|
||
|
||
function htmlMediaElement(preset: PresetReferenceType): string | undefined {
|
||
return preset.html.mediaElement ?? NATIVE_MEDIA_ELEMENTS[preset.name];
|
||
}
|
||
|
||
const listFormat = new Intl.ListFormat('en', { style: 'long', type: 'unit' });
|
||
---
|
||
|
||
<ContentWidth>
|
||
<Table maxWidth={false} outerClass="my-6">
|
||
<Thead>
|
||
<Tr>
|
||
<Th>Import</Th>
|
||
<Th>Description</Th>
|
||
<Th><span class="sr-only">Details</span></Th>
|
||
</Tr>
|
||
</Thead>
|
||
<Tbody>
|
||
{
|
||
presets.map((preset) => {
|
||
const id = `preset-${preset.name}`;
|
||
const htmlMedia = htmlMediaElement(preset);
|
||
return (
|
||
<>
|
||
<Tr
|
||
id={id}
|
||
data-preset-row
|
||
class="group cursor-pointer data-expanded:border-transparent dark:data-expanded:border-transparent intent:bg-manila-75 dark:intent:bg-soot"
|
||
>
|
||
<Td class="align-top">
|
||
<MarkdownCode>{`${pkg}/${preset.name}`}</MarkdownCode>
|
||
</Td>
|
||
<Td class="align-top">
|
||
{preset.description && (
|
||
<InlineMarkdown content={preset.description} />
|
||
)}
|
||
</Td>
|
||
<Td class="align-top">
|
||
<button
|
||
aria-expanded="false"
|
||
aria-controls={`${id}-detail`}
|
||
aria-label={`Details for ${preset.name} preset`}
|
||
data-preset-toggle
|
||
>
|
||
<span
|
||
aria-hidden="true"
|
||
class="inline-block group-data-expanded:rotate-90"
|
||
>
|
||
▸
|
||
</span>
|
||
</button>
|
||
</Td>
|
||
</Tr>
|
||
<Tr id={`${id}-detail`} hidden>
|
||
<Td colspan="3" class="p-0">
|
||
<div class="px-6 py-4">
|
||
<dl
|
||
class="grid grid-cols-(--grid-cols) gap-x-6 gap-y-3"
|
||
style="--grid-cols: auto 1fr"
|
||
>
|
||
<dt class="font-bold">Feature bundle</dt>
|
||
<dd>
|
||
<MarkdownCode>{preset.featureBundle}</MarkdownCode>
|
||
</dd>
|
||
|
||
<dt class="font-bold">Features</dt>
|
||
<dd>
|
||
{preset.features.length > 0
|
||
? listFormat
|
||
.formatToParts(preset.features.map((f) => f.name))
|
||
.map((part) => {
|
||
if (part.type !== "element") {
|
||
return <span>{part.value}</span>;
|
||
}
|
||
const feature = preset.features.find(
|
||
(f) => f.name === part.value,
|
||
)!;
|
||
return feature.hasReference ? (
|
||
<DocsLink
|
||
class="inline-block whitespace-nowrap"
|
||
slug={feature.slug}
|
||
>
|
||
{feature.name}
|
||
</DocsLink>
|
||
) : (
|
||
<span class="inline-block whitespace-nowrap">
|
||
{feature.name}
|
||
</span>
|
||
);
|
||
})
|
||
: "–"}
|
||
</dd>
|
||
|
||
<dt class="font-bold">Skins</dt>
|
||
<dd>
|
||
<FrameworkCase frameworks={["react"]}>
|
||
{preset.react.skins.length > 0
|
||
? preset.react.skins.map((skin) => (
|
||
<div class="mb-2 last:mb-0">
|
||
<MarkdownCode class="inline-block whitespace-nowrap">{`<${skin.name}>`}</MarkdownCode>
|
||
{skin.cssImport && (
|
||
<div class="mt-0.5">
|
||
<MarkdownCode class="inline-block text-code whitespace-nowrap">{`import '${skin.cssImport}';`}</MarkdownCode>
|
||
</div>
|
||
)}
|
||
</div>
|
||
))
|
||
: "–"}
|
||
</FrameworkCase>
|
||
<FrameworkCase frameworks={["html"]}>
|
||
{preset.html.skins.length > 0
|
||
? listFormat
|
||
.formatToParts(
|
||
preset.html.skins.map(
|
||
(s) => s.tagName ?? s.name,
|
||
),
|
||
)
|
||
.map((part) =>
|
||
part.type === "element" ? (
|
||
<MarkdownCode class="inline-block whitespace-nowrap">{`<${part.value}>`}</MarkdownCode>
|
||
) : (
|
||
<span>{part.value}</span>
|
||
),
|
||
)
|
||
: "–"}
|
||
</FrameworkCase>
|
||
</dd>
|
||
|
||
<dt class="font-bold">Default media element</dt>
|
||
<dd>
|
||
<FrameworkCase frameworks={["react"]}>
|
||
<MarkdownCode>{`<${preset.react.mediaElement}>`}</MarkdownCode>
|
||
</FrameworkCase>
|
||
<FrameworkCase frameworks={["html"]}>
|
||
{htmlMedia ? (
|
||
<MarkdownCode>{`<${htmlMedia}>`}</MarkdownCode>
|
||
) : (
|
||
"–"
|
||
)}
|
||
</FrameworkCase>
|
||
</dd>
|
||
</dl>
|
||
</div>
|
||
</Td>
|
||
</Tr>
|
||
</>
|
||
);
|
||
})
|
||
}
|
||
</Tbody>
|
||
</Table>
|
||
</ContentWidth>
|
||
|
||
<script>
|
||
document
|
||
.querySelectorAll<HTMLButtonElement>("[data-preset-toggle]")
|
||
.forEach((button) => {
|
||
button.addEventListener("click", () => {
|
||
const expanded = button.getAttribute("aria-expanded") === "true";
|
||
button.setAttribute("aria-expanded", String(!expanded));
|
||
|
||
const row = button.closest<HTMLTableRowElement>("[data-preset-row]");
|
||
if (row) row.toggleAttribute("data-expanded", !expanded);
|
||
|
||
const detail = document.getElementById(
|
||
button.getAttribute("aria-controls")!,
|
||
);
|
||
if (detail) detail.hidden = expanded;
|
||
});
|
||
});
|
||
|
||
document
|
||
.querySelectorAll<HTMLTableRowElement>("[data-preset-row]")
|
||
.forEach((row) => {
|
||
row.addEventListener("click", (e) => {
|
||
if ((e.target as Element).closest("a, button")) return;
|
||
row.querySelector<HTMLButtonElement>("[data-preset-toggle]")?.click();
|
||
});
|
||
});
|
||
</script>
|