manim-simplex 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. manim_simplex-0.2.0/.gitignore +30 -0
  2. manim_simplex-0.2.0/.pre-commit-config.yaml +66 -0
  3. manim_simplex-0.2.0/.python-version +1 -0
  4. manim_simplex-0.2.0/CHANGELOG.md +114 -0
  5. manim_simplex-0.2.0/LICENSE +21 -0
  6. manim_simplex-0.2.0/PKG-INFO +214 -0
  7. manim_simplex-0.2.0/README.md +182 -0
  8. manim_simplex-0.2.0/examples/README.md +33 -0
  9. manim_simplex-0.2.0/examples/glyph_map_demo.py +27 -0
  10. manim_simplex-0.2.0/examples/hello_slide.py +36 -0
  11. manim_simplex-0.2.0/examples/manim.cfg +3 -0
  12. manim_simplex-0.2.0/examples/outline_slide.py +28 -0
  13. manim_simplex-0.2.0/examples/theme_demo.py +25 -0
  14. manim_simplex-0.2.0/pyproject.toml +102 -0
  15. manim_simplex-0.2.0/ruff.toml +43 -0
  16. manim_simplex-0.2.0/src/simplex/engine/README.md +38 -0
  17. manim_simplex-0.2.0/src/simplex/engine/__init__.py +31 -0
  18. manim_simplex-0.2.0/src/simplex/engine/animations.py +160 -0
  19. manim_simplex-0.2.0/src/simplex/engine/code.py +442 -0
  20. manim_simplex-0.2.0/src/simplex/engine/debug.py +181 -0
  21. manim_simplex-0.2.0/src/simplex/engine/defaults.py +33 -0
  22. manim_simplex-0.2.0/src/simplex/engine/dynamics.py +100 -0
  23. manim_simplex-0.2.0/src/simplex/engine/geometry.py +247 -0
  24. manim_simplex-0.2.0/src/simplex/engine/ghost_fade.py +72 -0
  25. manim_simplex-0.2.0/src/simplex/engine/glyph_map.py +339 -0
  26. manim_simplex-0.2.0/src/simplex/engine/region.py +304 -0
  27. manim_simplex-0.2.0/src/simplex/engine/scaling.py +77 -0
  28. manim_simplex-0.2.0/src/simplex/engine/text.py +110 -0
  29. manim_simplex-0.2.0/src/simplex/manifest.py +114 -0
  30. manim_simplex-0.2.0/src/simplex/mobjects/README.md +33 -0
  31. manim_simplex-0.2.0/src/simplex/mobjects/__init__.py +13 -0
  32. manim_simplex-0.2.0/src/simplex/mobjects/array.py +408 -0
  33. manim_simplex-0.2.0/src/simplex/mobjects/graph.py +59 -0
  34. manim_simplex-0.2.0/src/simplex/mobjects/outline.py +141 -0
  35. manim_simplex-0.2.0/src/simplex/plugin.py +74 -0
  36. manim_simplex-0.2.0/src/simplex/py.typed +0 -0
  37. manim_simplex-0.2.0/src/simplex/section.py +51 -0
  38. manim_simplex-0.2.0/src/simplex/slides/README.md +43 -0
  39. manim_simplex-0.2.0/src/simplex/slides/__init__.py +12 -0
  40. manim_simplex-0.2.0/src/simplex/slides/base.py +118 -0
  41. manim_simplex-0.2.0/src/simplex/slides/chrome.py +69 -0
  42. manim_simplex-0.2.0/src/simplex/slides/outline.py +433 -0
  43. manim_simplex-0.2.0/src/simplex/theme/README.md +19 -0
  44. manim_simplex-0.2.0/src/simplex/theme/__init__.py +28 -0
  45. manim_simplex-0.2.0/src/simplex/theme/context.py +29 -0
  46. manim_simplex-0.2.0/src/simplex/theme/presets.py +87 -0
  47. manim_simplex-0.2.0/src/simplex/theme/pygments_style.py +78 -0
  48. manim_simplex-0.2.0/src/simplex/theme/tokens.py +105 -0
  49. manim_simplex-0.2.0/src/simplex/theme/web_css.py +33 -0
  50. manim_simplex-0.2.0/tests/README.md +27 -0
  51. manim_simplex-0.2.0/tests/__init__.py +0 -0
  52. manim_simplex-0.2.0/tests/engine/README.md +22 -0
  53. manim_simplex-0.2.0/tests/engine/__init__.py +0 -0
  54. manim_simplex-0.2.0/tests/engine/test_animations.py +56 -0
  55. manim_simplex-0.2.0/tests/engine/test_code.py +145 -0
  56. manim_simplex-0.2.0/tests/engine/test_debug.py +42 -0
  57. manim_simplex-0.2.0/tests/engine/test_dynamics.py +33 -0
  58. manim_simplex-0.2.0/tests/engine/test_geometry.py +83 -0
  59. manim_simplex-0.2.0/tests/engine/test_ghost_fade.py +21 -0
  60. manim_simplex-0.2.0/tests/engine/test_glyph_map.py +24 -0
  61. manim_simplex-0.2.0/tests/engine/test_region.py +222 -0
  62. manim_simplex-0.2.0/tests/engine/test_scaling.py +38 -0
  63. manim_simplex-0.2.0/tests/engine/test_text.py +67 -0
  64. manim_simplex-0.2.0/tests/mobjects/README.md +16 -0
  65. manim_simplex-0.2.0/tests/mobjects/__init__.py +0 -0
  66. manim_simplex-0.2.0/tests/mobjects/test_graph.py +35 -0
  67. manim_simplex-0.2.0/tests/mobjects/test_outline.py +64 -0
  68. manim_simplex-0.2.0/tests/slides/README.md +20 -0
  69. manim_simplex-0.2.0/tests/slides/__init__.py +0 -0
  70. manim_simplex-0.2.0/tests/slides/test_base.py +96 -0
  71. manim_simplex-0.2.0/tests/slides/test_chrome.py +55 -0
  72. manim_simplex-0.2.0/tests/slides/test_outline.py +141 -0
  73. manim_simplex-0.2.0/tests/test_manifest.py +134 -0
  74. manim_simplex-0.2.0/tests/test_section.py +75 -0
  75. manim_simplex-0.2.0/tests/theme/README.md +8 -0
  76. manim_simplex-0.2.0/tests/theme/__init__.py +0 -0
  77. manim_simplex-0.2.0/tests/theme/test_tokens.py +52 -0
  78. manim_simplex-0.2.0/tests/theme/test_web_css.py +18 -0
  79. manim_simplex-0.2.0/uv.lock +1422 -0
@@ -0,0 +1,30 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.so
5
+
6
+ # Build artifacts
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ .eggs/
11
+
12
+ # uv
13
+ .venv/
14
+
15
+ # Tool caches
16
+ .ruff_cache/
17
+ .pytest_cache/
18
+ .basedpyright/
19
+ .mypy_cache/
20
+
21
+ # Manim output
22
+ media/
23
+ # manim-slides output (rooted, so tests/slides/ stays tracked)
24
+ /slides/
25
+
26
+ # Editors
27
+ .idea/
28
+ .vscode/
29
+ *.swp
30
+ .DS_Store
@@ -0,0 +1,66 @@
1
+ ci:
2
+ autofix_commit_msg: |
3
+ chore(fmt): auto fixes from pre-commit.com hooks
4
+
5
+ for more information, see https://pre-commit.ci
6
+ autoupdate_commit_msg: 'chore(deps): pre-commit autoupdate'
7
+
8
+ default_stages:
9
+ - pre-commit
10
+ - pre-push
11
+
12
+ repos:
13
+ - repo: https://github.com/pre-commit/pre-commit-hooks
14
+ rev: v6.0.0
15
+ hooks:
16
+ - id: check-yaml
17
+ - id: check-toml
18
+ - id: end-of-file-fixer
19
+ - id: trailing-whitespace
20
+ - id: check-merge-conflict
21
+ - id: check-added-large-files
22
+ args: [--maxkb=512]
23
+ - id: mixed-line-ending
24
+ args: [--fix=lf]
25
+
26
+ - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
27
+ rev: v2.16.0
28
+ hooks:
29
+ - id: pretty-format-yaml
30
+ args: [--autofix]
31
+ - id: pretty-format-toml
32
+ exclude: ^(uv\.lock|poetry\.lock)$
33
+ args: [--autofix, --trailing-commas]
34
+
35
+ - repo: https://github.com/astral-sh/ruff-pre-commit
36
+ rev: v0.15.12
37
+ hooks:
38
+ - id: ruff
39
+ args: [--fix]
40
+ - id: ruff-format
41
+
42
+ - repo: https://github.com/pre-commit/mirrors-mypy
43
+ rev: v1.20.2
44
+ hooks:
45
+ - id: mypy
46
+ additional_dependencies: [types-requests, types-setuptools]
47
+ args: [--ignore-missing-imports]
48
+ files: ^src/
49
+
50
+ - repo: https://github.com/codespell-project/codespell
51
+ rev: v2.4.2
52
+ hooks:
53
+ - id: codespell
54
+ additional_dependencies:
55
+ - tomli
56
+ args: [--ignore-words-list=manim, mobjects, mobject]
57
+ exclude: ^(uv\.lock|.*\.svg)$
58
+
59
+ - repo: local
60
+ hooks:
61
+ - id: github-issues
62
+ name: GitHub issues link check
63
+ description: Check issues (and PR) links are matching number.
64
+ entry: python .github/scripts/check_github_issues.py
65
+ language: system
66
+ types: [markdown]
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,114 @@
1
+ # Changelog
2
+
3
+ All notable changes to `manim-simplex` are documented here.
4
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
5
+ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.2.0] - 2026-05-24
10
+
11
+ ### Added
12
+
13
+ - `TexPage` mobject — fixed-width minipage helper. Width is configurable
14
+ via the ``width_cm`` kwarg (default 20.0) or by overriding the class
15
+ attribute on a subclass. Replaces the old ``Definition`` mobject; the
16
+ hardcoded minipage literal no longer appears in presets or
17
+ tests.
18
+ - `Region.split(axis, k)` — divide a region into ``k`` sub-regions
19
+ along a cardinal direction. Each piece keeps the perpendicular extent
20
+ and gets ``1/k`` of the axis extent; pieces are returned in the
21
+ direction of ``axis``. Their union equals the original region.
22
+ - `Spacing.header_buff` / `Spacing.footer_buff` — chrome gap distances
23
+ exposed on the theme so they can be tuned deck-wide without editing
24
+ ``make_chrome``.
25
+ - `simplex.manifest` module — Pydantic models (`DeckManifest`, `MainSlide`,
26
+ `Subsection`) that define the cross-package contract between the plugin
27
+ and the `simplex` web builder. The web builder now imports the schema
28
+ from the plugin rather than redefining it locally.
29
+ - `simplex.section` module — `SimplexSectionType` enum promoted to the
30
+ package root (previously `simplex.engine.section_types`). Manim-free so
31
+ the web builder and CLI can use it without paying for a Manim import.
32
+ - `simplex.mobjects` subpackage — `Node`, `Edge`, `ArrayMob`, `ArrayEntry`,
33
+ `ArrayPointer` promoted from `simplex.slides.components` to a top-level
34
+ mobjects package, matching Manim's own `manim.mobject.*` convention.
35
+ - `simplex.slides.Chrome` NamedTuple — pure factory return type combining
36
+ the canvas mobjects dict and the body region.
37
+ - `simplex.engine.HighlightResult` dataclass — typed return for
38
+ `highlight_code_lines`, iterable so the existing `self.play(*result)`
39
+ pattern still works.
40
+ - `py.typed` marker — downstream `pyright`/`mypy` users now get type
41
+ information for the `simplex` namespace.
42
+ - `examples/` directory — runnable demo scenes (`hello_slide.py`,
43
+ `theme_demo.py`, `glyph_map_demo.py`) used as documentation and CI
44
+ fixtures.
45
+ - `.pre-commit-config.yaml` — ruff, ruff-format, codespell, and standard
46
+ whitespace/yaml/toml hygiene hooks.
47
+ - CHANGELOG.md.
48
+ - CI: `manim plugins -l` discovery smoke test alongside the existing
49
+ import smoke.
50
+
51
+ ### Changed
52
+
53
+ - **BREAKING:** ``Region.place`` now takes a Manim **direction vector**
54
+ (``UP``, ``DR``, ``ORIGIN``, …) instead of a string anchor name. The
55
+ same applies to the ``_anchor_point`` helper. Migrate
56
+ ``region.place(mob, "top", buff=…)`` → ``region.place(mob, UP, buff=…)``.
57
+ - **BREAKING:** ``make_chrome`` no longer accepts a ``page=`` parameter.
58
+ Slide numbering is presentation chrome and is now driven by the
59
+ RevealJS template (toggle via ``[web]`` overrides in ``deck.toml``)
60
+ so it survives without being baked into each frame.
61
+ - **BREAKING:** ``BodyText`` is removed. Plain ``manim.Tex`` carries the
62
+ theme's body font size through ``apply_theme_defaults`` — call sites
63
+ rewrite ``BodyText(...)`` to ``Tex(...)``.
64
+ - **BREAKING:** ``Definition`` is renamed to ``TexPage`` (and no longer
65
+ reads ``theme.latex.environments["definition"]``).
66
+ - ``BaseSlide`` auto-promotion now pretty-prints the class name into a
67
+ space-separated label (``DFSLecture`` → ``"DFS Lecture"``,
68
+ ``ImplementBFSSlide`` → ``"Implement BFS Slide"``). The class name
69
+ itself is unchanged.
70
+ - **BREAKING:** Python floor raised to **3.13** (was a transitional 3.14
71
+ in the Phase 3 split commit). 3.13 is a long-term-supportable floor
72
+ with much wider availability for lecture authors.
73
+ - **BREAKING:** `simplex.engine.section_types` → `simplex.section`.
74
+ - **BREAKING:** `simplex.slides.components.{graph, array}` →
75
+ `simplex.mobjects.{graph, array}`.
76
+ - **BREAKING:** `simplex.engine.transforms` is split into
77
+ `simplex.engine.glyph_map` (`TransformByGlyphMap`) and
78
+ `simplex.engine.ghost_fade` (`GhostSlideFade`). The combined module is
79
+ removed.
80
+ - `BaseSlide.next_slide()` still auto-promotes the first bare call to
81
+ a main slide (named after the scene class), but no longer emits a
82
+ `UserWarning`. Passing `name=` on the first call still works and only
83
+ changes the slide's name; the section type is `MAIN` either way.
84
+ - **BREAKING:** `make_chrome` no longer mutates its `Region` argument.
85
+ It returns a `Chrome(mobjects, body_region)` NamedTuple. Callers do
86
+ `chrome = make_chrome(...); self.add_to_canvas(**chrome.mobjects);
87
+ self.region = chrome.body_region` (or destructure).
88
+ - **BREAKING:** `highlight_code_lines` returns `HighlightResult` (a
89
+ frozen dataclass with `.fade` and `.indicate`) instead of the prior
90
+ tuple-or-AnimationGroup union. `*result` unpacks back into the
91
+ previous tuple form for callers that prefer it.
92
+ - Exit animation overrides are now stored in a `WeakKeyDictionary`
93
+ registry rather than monkey-patched onto the `Mobject` as a
94
+ `_simplex_exit` attribute. The public API (`set_exit_animation`,
95
+ `exit_for`, `Remove`) is unchanged.
96
+ - The exit-defaults registry is now wrapped in a singleton with
97
+ threading.Lock-guarded lazy init, removing the module-level mutable
98
+ global.
99
+
100
+ ### Removed
101
+
102
+ - ``BodyText`` mobject. Use ``manim.Tex`` (body size + color come from
103
+ ``apply_theme_defaults``) or ``Caption`` for smaller annotations.
104
+ - ``Definition`` mobject. Replaced by ``TexPage`` (see Added/Changed).
105
+ - ``make_chrome(..., page=…)`` parameter and the corresponding ``page``
106
+ entry in ``Chrome.mobjects``. Slide numbering moves to the web layer.
107
+ - ``LatexProfile.environments["definition"]`` entries from
108
+ ``DASTIMATOR_DARK`` and ``ACADEMIC_LIGHT``: ``TexPage`` is now the
109
+ single owner of the ``{minipage}{<width>cm}`` literal.
110
+ - `simplex.engine.section_types` module (replaced by `simplex.section`).
111
+ - `simplex.slides.components` subpackage (replaced by `simplex.mobjects`).
112
+ - `simplex.engine.transforms` module (split — see Changed).
113
+ - `UserWarning` on the first bare `BaseSlide.next_slide()` call. Auto-
114
+ promotion stays (named after the class), just silently.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shlomi Perles
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,214 @@
1
+ Metadata-Version: 2.4
2
+ Name: manim-simplex
3
+ Version: 0.2.0
4
+ Summary: Manim plugin: theme tokens, mobjects, slide hierarchy, deck manifest schema.
5
+ Project-URL: Changelog, https://github.com/shlomi-perles/manim-simplex/blob/main/CHANGELOG.md
6
+ Project-URL: Homepage, https://github.com/shlomi-perles/manim-simplex
7
+ Project-URL: Issues, https://github.com/shlomi-perles/manim-simplex/issues
8
+ Project-URL: Repository, https://github.com/shlomi-perles/manim-simplex
9
+ Author: Shlomi Perles
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: animation,computer-science,education,lecture,manim,manim-slides,math,presentation
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Education
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Education
22
+ Classifier: Topic :: Multimedia :: Graphics
23
+ Classifier: Topic :: Multimedia :: Video
24
+ Classifier: Topic :: Scientific/Engineering :: Visualization
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.13
27
+ Requires-Dist: manim-slides>=5.1.7
28
+ Requires-Dist: manim>=0.20.1
29
+ Requires-Dist: pydantic>=2.7
30
+ Requires-Dist: pygments>=2.18
31
+ Description-Content-Type: text/markdown
32
+
33
+ # manim-simplex
34
+
35
+ [![PyPI version](https://img.shields.io/pypi/v/manim-simplex.svg)](https://pypi.org/project/manim-simplex/)
36
+ [![Python](https://img.shields.io/pypi/pyversions/manim-simplex.svg)](https://pypi.org/project/manim-simplex/)
37
+ [![License](https://img.shields.io/pypi/l/manim-simplex.svg)](https://github.com/shlomi-perles/manim-simplex/blob/main/LICENSE)
38
+
39
+ The Manim plugin half of [Simplex](https://github.com/shlomi-perles/simplex):
40
+ theme tokens, reusable mobjects, slide hierarchy, deck manifest schema,
41
+ and the `manim.plugins` entry-point. Distributed on PyPI as
42
+ `manim-simplex`.
43
+
44
+ The lecture-portal platform (CLI, deck discovery, render orchestration,
45
+ web builder) lives in the sibling [`simplex`](https://github.com/shlomi-perles/simplex)
46
+ package; both contribute modules to the shared PEP 420 `simplex/`
47
+ namespace.
48
+
49
+ ## What ships here
50
+
51
+ | Module | Contents |
52
+ |---|---|
53
+ | `simplex.plugin` | `activate()` -- the `manim.plugins` entry-point. Applies the active theme to `manim.config`. |
54
+ | `simplex.section` | `SimplexSectionType` enum -- the slide-hierarchy strings written into Manim's sections JSON. Manim-free. |
55
+ | `simplex.manifest` | `DeckManifest`, `MainSlide`, `Subsection` Pydantic models -- the cross-package contract consumed by the `simplex` web builder. Manim-free. |
56
+ | `simplex.theme` | `Theme`, `Palette`, `Typography`, `Spacing`, `Motion`, `LatexProfile`, `WebPalette`, `active_theme`, `get_active_theme`, `presets`, `render_web_css`. |
57
+ | `simplex.engine` | Animation primitives -- `Region`, `Remove`, `clear_scene`, `exit_for`, `register_exit`, `set_exit_animation`, `HighlightResult`, `apply_theme_defaults`, plus the `glyph_map`, `ghost_fade`, `dynamics`, `geometry`, `code`, `text`, `scaling`, `debug` submodules. |
58
+ | `simplex.mobjects` | `Node`, `Edge`, `ArrayMob`, `ArrayEntry`, `ArrayPointer`, `OutlineProgressBar`. |
59
+ | `simplex.slides` | `BaseSlide`, `OutlineScene`, `OutlinePart`, `Chrome`, `make_chrome`. |
60
+
61
+ ## Install
62
+
63
+ ```bash
64
+ uv add manim-simplex
65
+ # or
66
+ pip install manim-simplex
67
+ ```
68
+
69
+ System dependencies (texlive, ffmpeg, cairo, pango) are the same as
70
+ Manim's -- see the [Manim install guide](https://docs.manim.community/en/stable/installation.html).
71
+
72
+ ## Quick start
73
+
74
+ ```ini
75
+ # decks/<your-deck>/manim.cfg
76
+ [CLI]
77
+ plugins = simplex
78
+ save_sections = True
79
+ ```
80
+
81
+ ```python
82
+ from manim import MathTex
83
+ from simplex.slides import BaseSlide, make_chrome
84
+ from simplex.theme import presets
85
+
86
+ class Hello(BaseSlide):
87
+ def setup(self) -> None:
88
+ super().setup()
89
+ chrome = make_chrome(presets.DASTIMATOR_DARK, self.region, header="Hello")
90
+ self.add_to_canvas(**chrome.mobjects)
91
+ self.region = chrome.body_region
92
+
93
+ def construct(self) -> None:
94
+ from manim import ORIGIN, Write
95
+ eq = MathTex(r"e^{i\pi} + 1 = 0")
96
+ self.region.place(eq, ORIGIN)
97
+ self.play(Write(eq))
98
+ self.next_slide(name="Hello")
99
+ ```
100
+
101
+ ```bash
102
+ uv run manim-slides render path/to/your_deck/scene.py Hello
103
+ ```
104
+
105
+ ## Slide hierarchy
106
+
107
+ `BaseSlide.next_slide` writes a `SimplexSectionType` value into Manim's
108
+ native section JSON. The web builder reconciles that with manim-slides'
109
+ `PresentationConfig` to build a main/sub tree.
110
+
111
+ - `self.next_slide(name="Title")` -> **MAIN** slide named `"Title"`.
112
+ - `self.next_slide()` as the *first* call -> **MAIN** slide
113
+ auto-named after the scene class with PascalCase boundaries spaced
114
+ out (``DFSLecture`` → ``"DFS Lecture"``; no warning).
115
+ - `self.next_slide()` after a named main -> **SUB** slide.
116
+ - `self.next_slide(..., loop=True)` -> the `LOOP` variant.
117
+ - `self.next_slide(..., section_type="simplex.main.skip")` -> explicit
118
+ override always wins.
119
+
120
+ ## Outline slides
121
+
122
+ `OutlineScene` composes typed `OutlinePart` objects into an animated
123
+ `BaseSlide` outline. Each part owns already-built Manim mobjects for its
124
+ feature title, compact label, and optional visual. Progress dots are
125
+ positioned with `self.region.linspace(RIGHT, n)` defaults, so edge
126
+ margins and inter-dot gaps are equal.
127
+
128
+ ```python
129
+ from manim import Circle, Square, Tex
130
+ from simplex.engine.text import Caption
131
+ from simplex.slides import OutlinePart, OutlineScene
132
+
133
+ class Outline(OutlineScene):
134
+ def __init__(self, **kwargs):
135
+ super().__init__(
136
+ parts=[
137
+ OutlinePart(Tex("Research Question"), Caption("Question"), Circle()),
138
+ OutlinePart(Tex("Algorithms"), Caption("Algorithms"), Square()),
139
+ ],
140
+ **kwargs,
141
+ )
142
+ ```
143
+
144
+ ## Theme
145
+
146
+ Themes are frozen Pydantic models -- the same instance produces:
147
+
148
+ 1. Manim defaults (via `apply_theme_defaults`, called by the plugin).
149
+ 2. A `TexTemplate` (via `LatexProfile.as_tex_template`).
150
+ 3. CSS variables for the web portal + RevealJS HTML (via
151
+ `render_web_css(theme.web_palette)`).
152
+ 4. The `darcula` Pygments style (registered by the plugin).
153
+
154
+ Switch themes per-scope with `active_theme`:
155
+
156
+ ```python
157
+ from simplex.theme import presets
158
+ from simplex.theme.context import active_theme
159
+
160
+ from manim import Tex
161
+
162
+ with active_theme(presets.ACADEMIC_LIGHT):
163
+ label = Tex("This Tex picks up the academic light palette.")
164
+ ```
165
+
166
+ ## Cross-package contract
167
+
168
+ `manim-simplex` owns the manifest schema; `simplex` imports it:
169
+
170
+ ```python
171
+ from simplex.manifest import DeckManifest, MainSlide, Subsection
172
+ ```
173
+
174
+ When the schema bumps `schema_version`, the web builder hard-fails on
175
+ unknown versions with a pointer at the `manim-simplex` upgrade. This
176
+ keeps the two repos honest about their contract.
177
+
178
+ ## Why a separate distribution?
179
+
180
+ The plugin surface (mobjects + theme + entry-point + manifest schema)
181
+ is reusable independently of the lecture-portal pipeline. Splitting
182
+ them lets the plugin be a thin dependency for users who want to render
183
+ slides without pulling in Typer, watchfiles, Jinja, and the web
184
+ builder stack.
185
+
186
+ Python's PEP 420 implicit namespace packages merge the two distributions
187
+ at import time. Neither wheel ships `src/simplex/__init__.py`, so
188
+ `from simplex.engine import Remove` resolves regardless of which wheel
189
+ contributed the module.
190
+
191
+ ## Development
192
+
193
+ Requires Python 3.13+ and [uv](https://docs.astral.sh/uv/).
194
+
195
+ ```bash
196
+ git clone https://github.com/shlomi-perles/manim-simplex.git
197
+ cd manim-simplex
198
+ uv sync --all-extras
199
+ uv run pre-commit install
200
+ uv run pytest -q
201
+ uv run ruff check .
202
+ uv run basedpyright
203
+ ```
204
+
205
+ Examples under `examples/` are runnable demo scenes; they double as
206
+ documentation and CI smoke tests:
207
+
208
+ ```bash
209
+ uv run manim -pql examples/hello_slide.py HelloSlide
210
+ ```
211
+
212
+ ## License
213
+
214
+ MIT.
@@ -0,0 +1,182 @@
1
+ # manim-simplex
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/manim-simplex.svg)](https://pypi.org/project/manim-simplex/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/manim-simplex.svg)](https://pypi.org/project/manim-simplex/)
5
+ [![License](https://img.shields.io/pypi/l/manim-simplex.svg)](https://github.com/shlomi-perles/manim-simplex/blob/main/LICENSE)
6
+
7
+ The Manim plugin half of [Simplex](https://github.com/shlomi-perles/simplex):
8
+ theme tokens, reusable mobjects, slide hierarchy, deck manifest schema,
9
+ and the `manim.plugins` entry-point. Distributed on PyPI as
10
+ `manim-simplex`.
11
+
12
+ The lecture-portal platform (CLI, deck discovery, render orchestration,
13
+ web builder) lives in the sibling [`simplex`](https://github.com/shlomi-perles/simplex)
14
+ package; both contribute modules to the shared PEP 420 `simplex/`
15
+ namespace.
16
+
17
+ ## What ships here
18
+
19
+ | Module | Contents |
20
+ |---|---|
21
+ | `simplex.plugin` | `activate()` -- the `manim.plugins` entry-point. Applies the active theme to `manim.config`. |
22
+ | `simplex.section` | `SimplexSectionType` enum -- the slide-hierarchy strings written into Manim's sections JSON. Manim-free. |
23
+ | `simplex.manifest` | `DeckManifest`, `MainSlide`, `Subsection` Pydantic models -- the cross-package contract consumed by the `simplex` web builder. Manim-free. |
24
+ | `simplex.theme` | `Theme`, `Palette`, `Typography`, `Spacing`, `Motion`, `LatexProfile`, `WebPalette`, `active_theme`, `get_active_theme`, `presets`, `render_web_css`. |
25
+ | `simplex.engine` | Animation primitives -- `Region`, `Remove`, `clear_scene`, `exit_for`, `register_exit`, `set_exit_animation`, `HighlightResult`, `apply_theme_defaults`, plus the `glyph_map`, `ghost_fade`, `dynamics`, `geometry`, `code`, `text`, `scaling`, `debug` submodules. |
26
+ | `simplex.mobjects` | `Node`, `Edge`, `ArrayMob`, `ArrayEntry`, `ArrayPointer`, `OutlineProgressBar`. |
27
+ | `simplex.slides` | `BaseSlide`, `OutlineScene`, `OutlinePart`, `Chrome`, `make_chrome`. |
28
+
29
+ ## Install
30
+
31
+ ```bash
32
+ uv add manim-simplex
33
+ # or
34
+ pip install manim-simplex
35
+ ```
36
+
37
+ System dependencies (texlive, ffmpeg, cairo, pango) are the same as
38
+ Manim's -- see the [Manim install guide](https://docs.manim.community/en/stable/installation.html).
39
+
40
+ ## Quick start
41
+
42
+ ```ini
43
+ # decks/<your-deck>/manim.cfg
44
+ [CLI]
45
+ plugins = simplex
46
+ save_sections = True
47
+ ```
48
+
49
+ ```python
50
+ from manim import MathTex
51
+ from simplex.slides import BaseSlide, make_chrome
52
+ from simplex.theme import presets
53
+
54
+ class Hello(BaseSlide):
55
+ def setup(self) -> None:
56
+ super().setup()
57
+ chrome = make_chrome(presets.DASTIMATOR_DARK, self.region, header="Hello")
58
+ self.add_to_canvas(**chrome.mobjects)
59
+ self.region = chrome.body_region
60
+
61
+ def construct(self) -> None:
62
+ from manim import ORIGIN, Write
63
+ eq = MathTex(r"e^{i\pi} + 1 = 0")
64
+ self.region.place(eq, ORIGIN)
65
+ self.play(Write(eq))
66
+ self.next_slide(name="Hello")
67
+ ```
68
+
69
+ ```bash
70
+ uv run manim-slides render path/to/your_deck/scene.py Hello
71
+ ```
72
+
73
+ ## Slide hierarchy
74
+
75
+ `BaseSlide.next_slide` writes a `SimplexSectionType` value into Manim's
76
+ native section JSON. The web builder reconciles that with manim-slides'
77
+ `PresentationConfig` to build a main/sub tree.
78
+
79
+ - `self.next_slide(name="Title")` -> **MAIN** slide named `"Title"`.
80
+ - `self.next_slide()` as the *first* call -> **MAIN** slide
81
+ auto-named after the scene class with PascalCase boundaries spaced
82
+ out (``DFSLecture`` → ``"DFS Lecture"``; no warning).
83
+ - `self.next_slide()` after a named main -> **SUB** slide.
84
+ - `self.next_slide(..., loop=True)` -> the `LOOP` variant.
85
+ - `self.next_slide(..., section_type="simplex.main.skip")` -> explicit
86
+ override always wins.
87
+
88
+ ## Outline slides
89
+
90
+ `OutlineScene` composes typed `OutlinePart` objects into an animated
91
+ `BaseSlide` outline. Each part owns already-built Manim mobjects for its
92
+ feature title, compact label, and optional visual. Progress dots are
93
+ positioned with `self.region.linspace(RIGHT, n)` defaults, so edge
94
+ margins and inter-dot gaps are equal.
95
+
96
+ ```python
97
+ from manim import Circle, Square, Tex
98
+ from simplex.engine.text import Caption
99
+ from simplex.slides import OutlinePart, OutlineScene
100
+
101
+ class Outline(OutlineScene):
102
+ def __init__(self, **kwargs):
103
+ super().__init__(
104
+ parts=[
105
+ OutlinePart(Tex("Research Question"), Caption("Question"), Circle()),
106
+ OutlinePart(Tex("Algorithms"), Caption("Algorithms"), Square()),
107
+ ],
108
+ **kwargs,
109
+ )
110
+ ```
111
+
112
+ ## Theme
113
+
114
+ Themes are frozen Pydantic models -- the same instance produces:
115
+
116
+ 1. Manim defaults (via `apply_theme_defaults`, called by the plugin).
117
+ 2. A `TexTemplate` (via `LatexProfile.as_tex_template`).
118
+ 3. CSS variables for the web portal + RevealJS HTML (via
119
+ `render_web_css(theme.web_palette)`).
120
+ 4. The `darcula` Pygments style (registered by the plugin).
121
+
122
+ Switch themes per-scope with `active_theme`:
123
+
124
+ ```python
125
+ from simplex.theme import presets
126
+ from simplex.theme.context import active_theme
127
+
128
+ from manim import Tex
129
+
130
+ with active_theme(presets.ACADEMIC_LIGHT):
131
+ label = Tex("This Tex picks up the academic light palette.")
132
+ ```
133
+
134
+ ## Cross-package contract
135
+
136
+ `manim-simplex` owns the manifest schema; `simplex` imports it:
137
+
138
+ ```python
139
+ from simplex.manifest import DeckManifest, MainSlide, Subsection
140
+ ```
141
+
142
+ When the schema bumps `schema_version`, the web builder hard-fails on
143
+ unknown versions with a pointer at the `manim-simplex` upgrade. This
144
+ keeps the two repos honest about their contract.
145
+
146
+ ## Why a separate distribution?
147
+
148
+ The plugin surface (mobjects + theme + entry-point + manifest schema)
149
+ is reusable independently of the lecture-portal pipeline. Splitting
150
+ them lets the plugin be a thin dependency for users who want to render
151
+ slides without pulling in Typer, watchfiles, Jinja, and the web
152
+ builder stack.
153
+
154
+ Python's PEP 420 implicit namespace packages merge the two distributions
155
+ at import time. Neither wheel ships `src/simplex/__init__.py`, so
156
+ `from simplex.engine import Remove` resolves regardless of which wheel
157
+ contributed the module.
158
+
159
+ ## Development
160
+
161
+ Requires Python 3.13+ and [uv](https://docs.astral.sh/uv/).
162
+
163
+ ```bash
164
+ git clone https://github.com/shlomi-perles/manim-simplex.git
165
+ cd manim-simplex
166
+ uv sync --all-extras
167
+ uv run pre-commit install
168
+ uv run pytest -q
169
+ uv run ruff check .
170
+ uv run basedpyright
171
+ ```
172
+
173
+ Examples under `examples/` are runnable demo scenes; they double as
174
+ documentation and CI smoke tests:
175
+
176
+ ```bash
177
+ uv run manim -pql examples/hello_slide.py HelloSlide
178
+ ```
179
+
180
+ ## License
181
+
182
+ MIT.
@@ -0,0 +1,33 @@
1
+ # Examples
2
+
3
+ Runnable demo scenes that double as integration smoke tests.
4
+
5
+ Each scene is intentionally small (single concept, ~30 LOC) and uses the
6
+ `manim-simplex` public API as a downstream user would.
7
+
8
+ ## Running
9
+
10
+ From the repo root with the dev environment synced:
11
+
12
+ ```bash
13
+ uv run manim -pql examples/hello_slide.py HelloSlide
14
+ uv run manim -pql examples/theme_demo.py ThemeDemo
15
+ uv run manim -pql examples/glyph_map_demo.py GlyphMapDemo
16
+ ```
17
+
18
+ The `-pql` flag previews at low quality. Use `-pqh` for 1080p, `-qk` for
19
+ 4K render-only.
20
+
21
+ ## With manim-slides
22
+
23
+ To render as a slide deck (uses the `Slide` base class):
24
+
25
+ ```bash
26
+ uv run manim-slides render examples/hello_slide.py HelloSlide
27
+ uv run manim-slides present HelloSlide
28
+ ```
29
+
30
+ The plugin auto-activates via the `manim.plugins` entry-point as long as
31
+ the deck's `manim.cfg` declares `plugins = simplex`. For these examples
32
+ we keep a tiny `manim.cfg` next to them so they render with the Simplex
33
+ theme out of the box.