import { defineConfig, transform } from '@videojs/compiler'; import { tailwind } from '@videojs/compiler/tailwind'; const CORE_COMPONENTS_SOURCE = '@videojs/core/components'; const ICON_COMPONENTS_SOURCE = '@videojs/icons/components'; const SOURCE_TAILWIND_SOURCE = './tailwind/video.tailwind'; const GENERATED_TAILWIND_SOURCE = '@videojs/skins/default/tailwind/video.tailwind'; export default defineConfig({ input: { 'default-video': '../skins/src/default/video.skin.tsx', }, output: { dir: 'src/presets/video', entryFileNames: '[name].generated.tailwind.tsx', banner: '// Generated by @videojs/compiler. Do not edit.\n', }, plugins: [ transform((code) => { // Types const BaseVideoSkinProps = code.import('./src/presets/types', 'BaseVideoSkinProps', { type: true }); const ReactNode = code.import('react', 'ReactNode', { type: true }); // Utils const cn = code.import('@videojs/utils/style', 'cn'); const isString = code.import('@videojs/utils/predicate', 'isString'); const isRenderProp = code.import('@/utils/use-render', 'isRenderProp'); // Components const Poster = code.import('@/ui/poster', 'Poster'); return [ code.imports({ [CORE_COMPONENTS_SOURCE]: coreComponentImport, [ICON_COMPONENTS_SOURCE]: '@/icons', [SOURCE_TAILWIND_SOURCE]: GENERATED_TAILWIND_SOURCE, }), tailwind({ mode: 'preserve' }), code .interface(/Props$/) .property('children') .setType(() => code.type.union(code.type.named(ReactNode), code.type.undefined())), code.interface('DefaultVideoSkinProps').extends(BaseVideoSkinProps), code.jsx.element(/^(Tooltip|Popover)\.Trigger$/).childToProp('render'), code.jsx.element('Controls.Root').addProp('data-controls', ''), code.jsx.element('Container').spreadProps('rest'), code.jsx.element('Text').replace('span'), code.jsx.element('Poster').replace(() => code.jsx.if( 'poster', code.jsx.create(Poster, { src: code.value.when('poster', isString), render: code.value.when('poster', isRenderProp), }) ) ), code.jsx .props('className') .where(code.value.isArray()) .replace(({ value }) => code.value.call(cn, code.value.arrayItems(value))), code.function('DefaultVideoSkin').addProps(['poster', { name: 'rest', spread: true }]), ]; }), ], }); function coreComponentImport(name: string): { source: string; name: string } { return { source: name === 'Container' ? '@/player/context' : `@/ui/${componentModuleName(name)}`, name, }; } function componentModuleName(name: string): string { return name .replace(/^AirPlay/, 'Airplay') .replace(/^PiP/, 'Pip') .replace(/([a-z0-9])([A-Z])/g, '$1-$2') .toLowerCase(); }