{"id":49780883,"url":"https://github.com/textcortex/slidewise","last_synced_at":"2026-05-11T20:02:45.176Z","repository":{"id":355104530,"uuid":"1224599725","full_name":"textcortex/SlideWise","owner":"textcortex","description":"PPTX + React = ❤️","archived":false,"fork":false,"pushed_at":"2026-05-10T11:06:20.000Z","size":351,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-10T11:25:00.809Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/textcortex.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-29T12:48:00.000Z","updated_at":"2026-05-10T11:05:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/textcortex/SlideWise","commit_stats":null,"previous_names":["textcortex/slidewise"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/textcortex/SlideWise","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/textcortex%2FSlideWise","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/textcortex%2FSlideWise/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/textcortex%2FSlideWise/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/textcortex%2FSlideWise/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/textcortex","download_url":"https://codeload.github.com/textcortex/SlideWise/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/textcortex%2FSlideWise/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32910635,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-11T17:09:15.040Z","status":"ssl_error","status_checked_at":"2026-05-11T17:08:45.420Z","response_time":120,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-11T20:02:44.391Z","updated_at":"2026-05-11T20:02:45.169Z","avatar_url":"https://github.com/textcortex.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Slidewise\n\nEmbeddable React PPTX editor. PPTX import + canvas editor + PPTX export, in\none component.\n\n```bash\npnpm add @textcortex/slidewise\n```\n\nPeer dependencies: `react \u003e=19`, `react-dom \u003e=19`.\n\n## Quick start\n\n`SlidewiseFileEditor` wraps the editor with PPTX load/save plumbing — give it\nasync `loadBlob` and `saveBlob` callbacks and it handles parsing, dirty\ntracking, and serialisation.\n\n```tsx\nimport {\n  SlidewiseFileEditor,\n  type SlidewiseFileEditorApi,\n} from \"@textcortex/slidewise\";\nimport \"@textcortex/slidewise/style.css\";\nimport { useRef } from \"react\";\n\nexport function PresentationsRoute({ fileId }: { fileId: string }) {\n  const apiRef = useRef\u003cSlidewiseFileEditorApi | null\u003e(null);\n\n  return (\n    \u003cSlidewiseFileEditor\n      onEditorApiChange={(api) =\u003e (apiRef.current = api)}\n      loadBlob={async () =\u003e {\n        const res = await fetch(`/api/files/${fileId}`);\n        return res.blob();\n      }}\n      saveBlob={async (pptx) =\u003e {\n        await fetch(`/api/files/${fileId}`, { method: \"PUT\", body: pptx });\n      }}\n    /\u003e\n  );\n}\n```\n\nThe host owns transport and conflict detection; Slidewise owns parsing,\nediting, and serialisation. Call `apiRef.current.save()` to trigger a save\nfrom outside the editor's top bar; call `apiRef.current.isDirty()` to gate\n\"unsaved changes\" UI.\n\n## Lower-level entry point\n\nIf your host already has a `Deck` in memory (e.g. you're storing the JSON\nshape in your own database rather than `.pptx` blobs), mount\n`SlidewiseEditor` directly:\n\n```tsx\nimport { SlidewiseEditor, type Deck } from \"@textcortex/slidewise\";\nimport \"@textcortex/slidewise/style.css\";\n\n\u003cSlidewiseEditor\n  deck={deck}\n  onChange={(next) =\u003e setDeck(next)}\n  onSave={(next) =\u003e persist(next)}\n/\u003e;\n```\n\n## Working with decks programmatically\n\nSlidewise persists slides as a versioned JSON `Deck`. The schema is the\ncanonical contract — undo/redo, exports, AI features, and persistence all\nkey off it.\n\n```ts\nimport {\n  parsePptx,\n  serializeDeck,\n  migrate,\n  CURRENT_DECK_VERSION,\n  type Deck,\n} from \"@textcortex/slidewise\";\n\nconst deck: Deck = await parsePptx(blob); // import\nconst pptx: Blob = await serializeDeck(deck); // export\nconst safe: Deck = migrate(unknownDeckJson); // normalise an external deck\n```\n\n`migrate()` runs every external deck (PPTX import, JSON import, localStorage\nhydration, host props) through the schema migration chain so the rest of the\neditor only sees current-shape decks. It throws if the input was written by a\nnewer Slidewise than the host has installed — pin the version range you can\nsupport.\n\n## Theming\n\nSlidewise exposes its surface colors and chrome metrics as CSS custom\nproperties, all namespaced under `--slidewise-*`. Override any subset on the\n`style` prop of `\u003cSlidewise.Root\u003e` (or in a stylesheet that targets the\n`.slidewise-editor` class) to retheme without forking.\n\n```tsx\n\u003cSlidewise.Root\n  style={{\n    \"--slidewise-bg-app\": \"#0a0a0e\",\n    \"--slidewise-bg-rail\": \"#1c1c22\",\n    \"--slidewise-bg-topbar\": \"linear-gradient(180deg, #1c1c22, #14141a)\",\n    \"--slidewise-radius\": \"8px\",\n  } as React.CSSProperties}\n\u003e\n  ...\n\u003c/Slidewise.Root\u003e\n```\n\nFor the most-customized surfaces there's also a typed prop equivalent:\n\n```tsx\n\u003cSlidewise.Root\n  surfaces={{\n    app: \"#0a0a0e\",\n    rail: \"#1c1c22\",\n    canvasFrom: \"#16181c\",\n    canvasTo: \"#0f0f12\",\n    button: \"transparent\",\n    buttonHover: \"rgba(255,255,255,0.06)\",\n  }}\n\u003e\n```\n\n### Public CSS variables\n\n| Variable | What it controls | Default |\n|---|---|---|\n| `--slidewise-radius` | Primary chrome button border-radius. | `10px` |\n| `--slidewise-bar-bg` | Top-bar background (alias kept for v1.1 hosts). | `var(--app-bg)` |\n| `--slidewise-accent` | Accent color used for focus rings, the Smart pill, hover affordances. | `var(--accent)` |\n| `--slidewise-bg-app` | Outermost app shell background. | `var(--app-bg)` |\n| `--slidewise-bg-topbar` | Top bar surface. | `var(--app-bg)` |\n| `--slidewise-bg-rail` | Slide-rail container. | `var(--rail-bg)` |\n| `--slidewise-bg-rail-item` | Idle slide-rail item. | `transparent` |\n| `--slidewise-bg-rail-item-active` | Active/selected rail item. | `var(--accent-soft)` |\n| `--slidewise-bg-canvas-frame` | Frame around the canvas. | `transparent` |\n| `--slidewise-bg-canvas-from` / `--slidewise-bg-canvas-to` | Canvas gradient stops. | `var(--canvas-bg-from)` / `var(--canvas-bg-to)` |\n| `--slidewise-bg-bottom-toolbar` | Floating tool selector. | `var(--toolbar-bg)` |\n| `--slidewise-bg-right-panel` | `\u003cSlidewise.RightPanel\u003e` surface. | `var(--rail-bg)` |\n| `--slidewise-bg-menu` / `--slidewise-bg-tooltip` / `--slidewise-bg-popover` / `--slidewise-bg-dialog` | Floating UI surfaces. | `var(--menu-bg)` |\n| `--slidewise-bg-slide` | Slide paper. | `#ffffff` |\n| `--slidewise-bg-selection` | Selection overlay tint. | `var(--accent-soft)` |\n| `--slidewise-bg-hover` / `--slidewise-bg-active` | Interactive state tints. | `var(--hover)` / `var(--active)` |\n| `--slidewise-bg-input` | Form input background. | `var(--input-bg)` |\n| `--slidewise-bg-button` / `--slidewise-bg-button-hover` | Chrome button surfaces. | `transparent` / `var(--hover)` |\n| `--slidewise-bg-pill` | Smart pill background. | `var(--smart-grad)` |\n| `--slidewise-bg-unsaved-badge` | Unsaved-changes badge. | `rgba(232, 80, 76, 0.12)` |\n\nThe library also ships a smaller `--surface-*` token family for ad-hoc\ncard/panel surfaces (`--surface-bg`, `--surface-ring`, `--surface-shadow`,\nplus their `-hover` variants) and a `.slidewise-surface` utility class that\napplies all three together.\n\n## Localization\n\nEvery user-visible string in the chrome is overridable through the `labels`\nprop:\n\n```tsx\n\u003cSlidewise.Root\n  labels={{\n    save: { idle: \"Speichern\", saving: \"Wird gespeichert…\", saved: \"Gespeichert\" },\n    play: \"Wiedergabe\",\n    export: \"Exportieren\",\n    undo: \"Rückgängig\",\n    redo: \"Wiederherstellen\",\n    themeToggle: { toDark: \"Dunkler Modus\", toLight: \"Heller Modus\" },\n    smart: \"Smart\",\n    unsavedBadge: \"Nicht gespeicherte Änderungen\",\n    fileLoadError: (msg) =\u003e `Datei konnte nicht geöffnet werden: ${msg}`,\n    fileLoading: \"Wird geladen…\",\n  }}\n\u003e\n```\n\nMissing entries fall back to the English defaults (`DEFAULT_LABELS`).\n\n## Releasing\n\nVersioning and publishing run through\n[changesets](https://github.com/changesets/changesets).\n\n```bash\npnpm changeset            # describe the impact of your change\npnpm version-packages     # bump versions + update CHANGELOG (CI usually does this)\npnpm release              # build + publish (CI does this on merge)\n```\n\nCI (`.github/workflows/release.yml`) opens a \"Version Packages\" PR whenever\nthere are pending changesets and publishes to npm when that PR merges.\n\n## Repo layout\n\n- `src/SlidewiseEditor.tsx` / `src/SlidewiseFileEditor.tsx` — public entry components\n- `src/components/editor/` — top bar, slide rail, canvas, panels\n- `src/lib/pptx/` — PPTX import (`pptxToDeck`) and export (`deckToPptx`)\n- `src/lib/schema/` — `Deck` schema versioning + migrator\n- `src/lib/types.ts` — `Deck` / `Slide` / `SlideElement` shapes (the contract)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftextcortex%2Fslidewise","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftextcortex%2Fslidewise","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftextcortex%2Fslidewise/lists"}