openreader/tailwind.config.ts
Richard Roberson 42665884d7 feat(audiobook): add chapter-based export with UI and API
Introduce end-to-end chapterized audiobook generation with persistent
storage, resumable workflows, and MP3/M4B support.

API:
- add /api/audio/convert/chapter (GET/DELETE) for per-chapter ops
- add /api/audio/convert/chapters (GET/DELETE) for listing/reset
- enhance /api/audio/convert:
  - accept mp3|m4b, stream combined file, cache complete output
  - robust chapter indexing, docstore persistence, list concat
  - AbortSignal-aware ffmpeg/ffprobe, 499 on cancel

UI/UX:
- add AudiobookExportModal with progress, resume, regenerate, download
- add ProgressCard, enhance ProgressPopup (click-to-focus, richer info)
- add Header, ZoomControl; move TTSPlayer to sticky bottom bar
- redesign EPUB/HTML/PDF pages for full-height layout and controls
- add HomeContent; compact uploader variant; document list polish

TTS/Contexts:
- EPUB/PDF contexts now generate per-chapter to disk, return bookId
- support chapter regeneration; progress/cancel propagation
- pass provider/model/instructions; standardize MP3 TTS output
- HTML context updates for model/instructions

Styling:
- globals: overlay-dim, scrollbar styles, prism gradient utilities
- theme vars: secondary-accent, prism-gradient; tailwind color addition

Misc:
- fix PDF scale calc to use container height
- EPUB theme reader area fills height
- time estimation update cadence stab
- audio util passes format to combine endpoint
2025-11-11 13:32:30 -07:00

72 lines
2.3 KiB
TypeScript

import type { Config } from "tailwindcss";
import typography from "@tailwindcss/typography";
export default {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
darkMode: 'class',
theme: {
extend: {
colors: {
background: "var(--background)",
foreground: "var(--foreground)",
base: "var(--base)",
offbase: "var(--offbase)",
accent: "var(--accent)",
"secondary-accent": "var(--secondary-accent)",
muted: "var(--muted)",
},
animation: {
'spin-slow': 'spin 2s linear infinite',
'fade-in': 'fadeIn 200ms ease-in',
'fade-out': 'fadeOut 200ms ease-out',
'scale-in': 'scaleIn 200ms ease-in',
'scale-out': 'scaleOut 200ms ease-out',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
fadeOut: {
'0%': { opacity: '1' },
'100%': { opacity: '0' },
},
scaleIn: {
'0%': { transform: 'scale(0.95)', opacity: '0' },
'100%': { transform: 'scale(1)', opacity: '1' },
},
scaleOut: {
'0%': { transform: 'scale(1)', opacity: '1' },
'100%': { transform: 'scale(0.95)', opacity: '0' },
},
},
typography: {
DEFAULT: {
css: {
'--tw-prose-body': 'var(--foreground)',
'--tw-prose-headings': 'var(--foreground)',
'--tw-prose-lead': 'var(--muted)',
'--tw-prose-links': 'var(--accent)',
'--tw-prose-bold': 'var(--foreground)',
'--tw-prose-counters': 'var(--muted)',
'--tw-prose-bullets': 'var(--muted)',
'--tw-prose-hr': 'var(--offbase)',
'--tw-prose-quotes': 'var(--foreground)',
'--tw-prose-quote-borders': 'var(--offbase)',
'--tw-prose-captions': 'var(--muted)',
'--tw-prose-code': 'var(--foreground)',
'--tw-prose-pre-code': 'var(--foreground)',
'--tw-prose-pre-bg': 'var(--base)',
'--tw-prose-th-borders': 'var(--offbase)',
'--tw-prose-td-borders': 'var(--offbase)',
},
},
},
},
},
plugins: [typography],
} satisfies Config;