taleem-player 0.0.1

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.
package/README.md ADDED
@@ -0,0 +1,267 @@
1
+
2
+ # đź§  `@taleem/player`
3
+
4
+ **Version:** v1.0.0
5
+ **Status:** STABLE
6
+ **Scope:** Slide interpretation (NO UI)
7
+ **Depends on:** `deck-v1` (from `taleem-core`)
8
+ **Renders:** ❌ Nothing
9
+
10
+ ---
11
+
12
+ ## Purpose
13
+
14
+ `@taleem/player` is the **semantic interpreter** for Taleem slide decks.
15
+
16
+ It takes a validated `deck-v1` document and answers one question only:
17
+
18
+ > **“What does this slide mean?”**
19
+
20
+ It does **not** render HTML, does **not** touch the DOM, and does **not** know where or how slides will be displayed.
21
+
22
+ If you are looking for UI, CSS, animations, audio, or frameworks —
23
+ **you are in the wrong repository.**
24
+
25
+ ---
26
+
27
+ ## What this package DOES
28
+
29
+ `@taleem/player` is responsible for:
30
+
31
+ 1. Interpreting slide **types** (`titleSlide`, `eq`, `twoColumnText`, …)
32
+ 2. Grouping **flat slide data** into semantic regions
33
+ 3. Enforcing **slide meaning contracts**
34
+ 4. Producing **render-ready frames** (pure data)
35
+ 5. Failing loudly on unsupported slide types
36
+
37
+ It is the **single authority** on what a slide *means*.
38
+
39
+ ---
40
+
41
+ ## What this package does NOT do
42
+
43
+ This package intentionally does **NOT**:
44
+
45
+ * Render HTML
46
+ * Use `document`, `window`, or the DOM
47
+ * Load files or URLs
48
+ * Manage time loops or playback
49
+ * Handle user input
50
+ * Know about CSS, layouts, or screen sizes
51
+ * Store state or progress
52
+ * Perform validation (that’s `taleem-core`)
53
+
54
+ If you feel tempted to add any of the above here — stop.
55
+
56
+ ---
57
+
58
+ ## Architectural position
59
+
60
+ ```
61
+ Deck JSON (deck-v1)
62
+ ↓
63
+ taleem-core
64
+ ↓
65
+ @taleem/player
66
+ ↓
67
+ Renderer (web / pdf / video / cli)
68
+ ```
69
+
70
+ The Player **sits between content and rendering**.
71
+
72
+ * Everything above it can change.
73
+ * Everything below it can change.
74
+ * The Player must remain **pure and stable**.
75
+
76
+ ---
77
+
78
+ ## Mental model (IMPORTANT)
79
+
80
+ > **Slides are documents, not components.**
81
+ > **The Player interprets.**
82
+ > **Renderers paint.**
83
+
84
+ This repository exists because violating that boundary causes years of pain.
85
+
86
+ ---
87
+
88
+ ## Public API
89
+
90
+ ### Import
91
+
92
+ ```js
93
+ import { Player } from "@taleem/player";
94
+ ```
95
+
96
+ ---
97
+
98
+ ### Creating a Player
99
+
100
+ ```js
101
+ const player = new Player(deck);
102
+ ```
103
+
104
+ Where `deck` is a valid `deck-v1` document.
105
+
106
+ ---
107
+
108
+ ### Frame generation (index-based)
109
+
110
+ ```js
111
+ const frame = player.getFrameByIndex(0);
112
+ ```
113
+
114
+ Returns a **render instruction**:
115
+
116
+ ```js
117
+ {
118
+ type: "titleSlide",
119
+ regions: {
120
+ title: "Angles and Transversals"
121
+ },
122
+ meta: {
123
+ start: 0,
124
+ end: 10
125
+ }
126
+ }
127
+ ```
128
+
129
+ * `type` → slide semantic type
130
+ * `regions` → grouped, interpreted data
131
+ * `meta` → timing metadata (passed through, not used)
132
+
133
+ ---
134
+
135
+ ### Time-based access (future / optional)
136
+
137
+ ```js
138
+ const frame = player.getFrame(timeInSeconds);
139
+ ```
140
+
141
+ Time support exists but is **not required** for basic rendering.
142
+ Navigation and playback loops live **outside** the Player.
143
+
144
+ ---
145
+
146
+ ## Slide semantics (core responsibility)
147
+
148
+ ### Example: `twoColumnText`
149
+
150
+ Input (flat):
151
+
152
+ ```js
153
+ [
154
+ { name: "title", content: "Topic", showAt: 0 },
155
+ { name: "left", content: "Left text", showAt: 1 },
156
+ { name: "right", content: "Right text", showAt: 2 }
157
+ ]
158
+ ```
159
+
160
+ Output (interpreted):
161
+
162
+ ```js
163
+ {
164
+ title: "Topic",
165
+ left: ["Left text"],
166
+ right: ["Right text"]
167
+ }
168
+ ```
169
+
170
+ The **grouping logic lives here**, not in the renderer.
171
+
172
+ ---
173
+
174
+ ## EQ slide support (gold standard)
175
+
176
+ This Player fully supports the **flat EQ authoring model** defined in `eq.md`.
177
+
178
+ Key rules (frozen):
179
+
180
+ * EQ input is a **flat array**
181
+ * Non-`sp*` items start a new line
182
+ * All following `sp*` items attach to the last line
183
+ * Sidebars are semantic, not structural
184
+
185
+ This logic is implemented and **covered by tests**.
186
+
187
+ ---
188
+
189
+ ## Tests and trust
190
+
191
+ This package has automated tests that verify:
192
+
193
+ * Basic frame generation
194
+ * Index-based navigation
195
+ * EQ sidebar grouping behavior
196
+ * Boundary enforcement
197
+
198
+ If tests pass:
199
+
200
+ * the Player is correct
201
+ * slide meaning is stable
202
+ * future refactors are safe
203
+
204
+ ---
205
+
206
+ ## Design rules (DO NOT BREAK)
207
+
208
+ 1. No DOM access
209
+ 2. No renderer imports
210
+ 3. No CSS
211
+ 4. No framework assumptions
212
+ 5. No silent behavior changes
213
+ 6. No auto-mutation of decks
214
+ 7. New slide types require **explicit Player support**
215
+
216
+ If a new slide type appears in a deck and the Player does not support it,
217
+ **the Player must throw**.
218
+
219
+ Silent fallbacks are forbidden.
220
+
221
+ ---
222
+
223
+ ## Relationship to other packages
224
+
225
+ * **`taleem-core`**
226
+ Defines *what a deck is* and *how time maps to slides*
227
+
228
+ * **`@taleem/player`** (this repo)
229
+ Defines *what slides mean*
230
+
231
+ * **Renderers (web / pdf / video)**
232
+ Define *how slides look*
233
+
234
+ This separation is intentional and permanent.
235
+
236
+ ---
237
+
238
+ ## When to modify this repo
239
+
240
+ Only modify `@taleem/player` if:
241
+
242
+ * a new slide semantic is introduced
243
+ * an existing slide semantic is incorrect
244
+ * tests reveal a broken interpretation rule
245
+
246
+ If you are adding UI features — you are in the wrong repo.
247
+
248
+ ---
249
+
250
+ ## Final warning (read twice)
251
+
252
+ > **A previous version of this system failed because UI logic leaked into the Player.
253
+ > This repository exists to make that mistake impossible.**
254
+
255
+ Treat this README as **law**, not guidance.
256
+
257
+ ---
258
+
259
+ ## Status
260
+
261
+ âś” Boundaries enforced
262
+ âś” Tests passing
263
+ âś” Semantics stable
264
+ âś” Ready for long-term use
265
+
266
+ This is a **completed deliverable**.
267
+
@@ -0,0 +1,85 @@
1
+ {
2
+ "name": "Angles and Transversals",
3
+ "description": "Intro to angle types formed by a transversal — with memory trick",
4
+ "tags": [
5
+ "geometry",
6
+ "angles",
7
+ "class9"
8
+ ],
9
+ "status": "ready",
10
+ "createdAt": "2025-07-25T16:04:36.820Z",
11
+ "editedAt": "2025-07-25T16:04:36.820Z",
12
+ "version": "deck-v1",
13
+ "background": {
14
+ "backgroundColor": "#F3E5AB",
15
+ "backgroundImage": "/media/images/taleem.webp",
16
+ "backgroundImageOpacity": 0.1
17
+ },
18
+ "deck": [
19
+ {
20
+ "start": 0,
21
+ "end": 9.02,
22
+ "type": "titleSlide",
23
+ "data": [
24
+ {
25
+ "name": "title",
26
+ "content": "Angles and Transversals",
27
+ "showAt": 0
28
+ }
29
+ ]
30
+ },
31
+ {
32
+ "start": 9.02,
33
+ "end": 33.87,
34
+ "type": "imageSlide",
35
+ "data": [
36
+ {
37
+ "name": "image",
38
+ "content": "/media/images/traversal.webp",
39
+ "showAt": 0
40
+ }
41
+ ]
42
+ },
43
+ {
44
+ "start": 33.87,
45
+ "end": 52.85,
46
+ "type": "titleAndSubtitle",
47
+ "data": [
48
+ {
49
+ "name": "title",
50
+ "content": "Memory Line",
51
+ "showAt": 0
52
+ },
53
+ {
54
+ "name": "subtitle",
55
+ "content": "Jahan angles milay — Alternate aur Corresponding barabar, Interior mil ke 180!",
56
+ "showAt": 0
57
+ }
58
+ ]
59
+ },
60
+ {
61
+ "start": 52.85,
62
+ "end": 188.09,
63
+ "type": "imageSlide",
64
+ "data": [
65
+ {
66
+ "name": "image",
67
+ "content": "/media/images/angles.jpg",
68
+ "showAt": 0
69
+ }
70
+ ]
71
+ },
72
+ {
73
+ "start": 188.09,
74
+ "end": 196.18,
75
+ "type": "titleSlide",
76
+ "data": [
77
+ {
78
+ "name": "title",
79
+ "content": "Jahan angles milay — Alternate aur Corresponding barabar, Interior mil ke 180!",
80
+ "showAt": 0
81
+ }
82
+ ]
83
+ }
84
+ ]
85
+ }
@@ -0,0 +1,169 @@
1
+ {
2
+ "name": "congruent_triangles",
3
+ "description": "Class 9 Geometry — Congruent Triangles Summary",
4
+ "tags": [
5
+ "math",
6
+ "geometry",
7
+ "triangles"
8
+ ],
9
+ "status": "draft",
10
+ "createdAt": "2025-07-21T00:00:00Z",
11
+ "editedAt": "2025-07-21T00:00:00Z",
12
+ "version": "deck-v1",
13
+ "background": {
14
+ "backgroundColor": "#F3E5AB",
15
+ "backgroundImage": "/images/taleem.webp",
16
+ "backgroundImageOpacity": 0.07
17
+ },
18
+ "deck": [
19
+ {
20
+ "start": 0,
21
+ "end": 10,
22
+ "type": "imageWithTitle",
23
+ "data": [
24
+ {
25
+ "name": "image",
26
+ "content": "/images/congruent_triangle.webp",
27
+ "showAt": 0
28
+ },
29
+ {
30
+ "name": "title",
31
+ "content": "Congruent Triangles",
32
+ "showAt": 2
33
+ }
34
+ ]
35
+ },
36
+ {
37
+ "start": 10,
38
+ "end": 30,
39
+ "type": "imageLeftBulletsRight",
40
+ "data": [
41
+ {
42
+ "name": "image",
43
+ "content": "/images/congruent_triangle2.webp",
44
+ "showAt": 10
45
+ },
46
+ {
47
+ "name": "bullet",
48
+ "content": "Same shape and same size",
49
+ "showAt": 13
50
+ },
51
+ {
52
+ "name": "bullet",
53
+ "content": "All sides and angles are equal",
54
+ "showAt": 16
55
+ },
56
+ {
57
+ "name": "bullet",
58
+ "content": "Can fit exactly on top of each other",
59
+ "showAt": 19
60
+ }
61
+ ]
62
+ },
63
+ {
64
+ "start": 30,
65
+ "end": 35,
66
+ "type": "titleAndSubtitle",
67
+ "data": [
68
+ {
69
+ "name": "title",
70
+ "content": "4 Rules to Prove Congruence",
71
+ "showAt": 30
72
+ },
73
+ {
74
+ "name": "subtitle",
75
+ "content": "SAS, ASA, SSS, RHS",
76
+ "showAt": 32
77
+ }
78
+ ]
79
+ },
80
+ {
81
+ "start": 35,
82
+ "end": 50,
83
+ "type": "bulletList",
84
+ "data": [
85
+ {
86
+ "name": "bullet",
87
+ "content": "SAS: Side–Angle–Side",
88
+ "showAt": 36
89
+ },
90
+ {
91
+ "name": "bullet",
92
+ "content": "ASA: Angle–Side–Angle",
93
+ "showAt": 38
94
+ },
95
+ {
96
+ "name": "bullet",
97
+ "content": "SSS: Side–Side–Side",
98
+ "showAt": 41
99
+ },
100
+ {
101
+ "name": "bullet",
102
+ "content": "RHS: Right-angle–Hypotenuse–Side",
103
+ "showAt": 44
104
+ }
105
+ ]
106
+ },
107
+ {
108
+ "start": 50,
109
+ "end": 55,
110
+ "type": "titleAndSubtitle",
111
+ "data": [
112
+ {
113
+ "name": "title",
114
+ "content": "Similar vs Congruent",
115
+ "showAt": 50
116
+ },
117
+ {
118
+ "name": "subtitle",
119
+ "content": "Not all triangles that look alike are congruent",
120
+ "showAt": 52
121
+ }
122
+ ]
123
+ },
124
+ {
125
+ "start": 55,
126
+ "end": 75,
127
+ "type": "imageLeftBulletsRight",
128
+ "data": [
129
+ {
130
+ "name": "image",
131
+ "content": "/images/congruent_triangle2.webp",
132
+ "showAt": 55
133
+ },
134
+ {
135
+ "name": "bullet",
136
+ "content": "Congruent: exact match in size and shape",
137
+ "showAt": 58
138
+ },
139
+ {
140
+ "name": "bullet",
141
+ "content": "Similar: same shape, different size",
142
+ "showAt": 61
143
+ },
144
+ {
145
+ "name": "bullet",
146
+ "content": "Similar ≠ Congruent (they don’t “fit”)",
147
+ "showAt": 64
148
+ }
149
+ ]
150
+ },
151
+ {
152
+ "start": 75,
153
+ "end": 85,
154
+ "type": "quoteSlide",
155
+ "data": [
156
+ {
157
+ "name": "quoteLine",
158
+ "content": "Congruent triangles are the building blocks of geometric proof.",
159
+ "showAt": 75
160
+ },
161
+ {
162
+ "name": "author",
163
+ "content": "— Taleem.Help",
164
+ "showAt": 78
165
+ }
166
+ ]
167
+ }
168
+ ]
169
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "version": "deck-v1",
3
+ "name": "demo-minimal",
4
+ "deck": [
5
+ {
6
+ "start": 0,
7
+ "end": 10,
8
+ "type": "titleSlide",
9
+ "data": [
10
+ { "name": "title", "content": "Angles and Transversals", "showAt": 0 }
11
+ ]
12
+ },
13
+ {
14
+ "start": 10,
15
+ "end": 20,
16
+ "type": "titleSlide",
17
+ "data": [
18
+ { "name": "title", "content": "Parallel Lines and Transversals", "showAt": 0 }
19
+ ]
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "eq_long_test",
3
+ "description": "Title + 1 long eq slide with 15 lines",
4
+ "tags": ["test", "eq"],
5
+ "status": "draft",
6
+ "version": "deck-v1",
7
+ "background": {
8
+ "backgroundColor": "#F3E5AB",
9
+ "backgroundImage": "/images/taleem.webp",
10
+ "backgroundImageOpacity": 0.07
11
+ },
12
+ "deck": [
13
+ {
14
+ "type": "imageWithTitle",
15
+ "start": 0,
16
+ "end": 5,
17
+ "data": [
18
+ {
19
+ "name": "image",
20
+ "content": "/images/box.webp",
21
+ "showAt": 0
22
+ },
23
+ {
24
+ "name": "title",
25
+ "content": "Equations Test Deck",
26
+ "showAt": 0
27
+ }
28
+ ]
29
+ },
30
+ {
31
+ "type": "eq",
32
+ "start": 5,
33
+ "end": 50,
34
+ "data": [
35
+ { "name": "line", "type": "heading", "content": "Algebra & Physics Equations", "showAt": 5 },
36
+
37
+ { "name": "line", "type": "math", "content": "a^2 + b^2 = c^2", "showAt": 7, "spItems": [{ "type": "spText", "content": "Pythagoras theorem" }] },
38
+ { "name": "line", "type": "text", "content": "This relates the sides of a right triangle.", "showAt": 9 },
39
+
40
+ { "name": "line", "type": "math", "content": "F = m \\times a", "showAt": 11, "spItems": [{ "type": "spHeading", "content": "Newton's Second Law" }] },
41
+ { "name": "line", "type": "text", "content": "Force equals mass times acceleration.", "showAt": 13 },
42
+
43
+ { "name": "line", "type": "math", "content": "E = m c^2", "showAt": 15, "spItems": [{ "type": "spMath", "content": "c = speed of light" }] },
44
+ { "name": "line", "type": "text", "content": "Energy-mass equivalence from Einstein.", "showAt": 17 },
45
+
46
+ { "name": "line", "type": "math", "content": "V = I R", "showAt": 19 },
47
+ { "name": "line", "type": "text", "content": "Ohm's Law: voltage, current, resistance.", "showAt": 21 },
48
+
49
+ { "name": "line", "type": "math", "content": "p = m v", "showAt": 23 },
50
+ { "name": "line", "type": "text", "content": "Momentum equals mass times velocity.", "showAt": 25 },
51
+
52
+ { "name": "line", "type": "math", "content": "KE = 1/2 m v^2", "showAt": 27 },
53
+ { "name": "line", "type": "text", "content": "Kinetic energy formula.", "showAt": 29 },
54
+
55
+ { "name": "line", "type": "math", "content": "PE = m g h", "showAt": 31 },
56
+ { "name": "line", "type": "text", "content": "Potential energy at height h.", "showAt": 33 },
57
+
58
+ { "name": "line", "type": "math", "content": "Q = m c ΔT", "showAt": 35 },
59
+ { "name": "line", "type": "text", "content": "Heat energy gained or lost.", "showAt": 37 },
60
+
61
+ { "name": "line", "type": "math", "content": "v = d / t", "showAt": 39 },
62
+ { "name": "line", "type": "text", "content": "Velocity is distance over time.", "showAt": 41 }
63
+ ]
64
+ }
65
+ ]
66
+ }
67
+
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "goldstandard_eq_28aug25",
3
+ "description": "Title + one long EQ slide (FLAT authoring) covering all sidebar types",
4
+ "tags": ["eq", "gold-standard", "flat-authoring"],
5
+ "status": "draft",
6
+ "version": "deck-v1",
7
+ "background": {
8
+ "backgroundColor": "#0e0f14",
9
+ "backgroundImage": "/media/images/box.webp",
10
+ "backgroundImageOpacity": 0.07
11
+ },
12
+ "deck": [
13
+ {
14
+ "type": "imageWithTitle",
15
+ "start": 0,
16
+ "end": 5,
17
+ "data": [
18
+ { "name": "image", "content": "/media/images/box.webp", "showAt": 0 },
19
+ { "name": "title", "content": "EQ Sidebar Gold Standard", "showAt": 0 }
20
+ ]
21
+ },
22
+ {
23
+ "type": "eq",
24
+ "start": 5,
25
+ "end": 55,
26
+ "data": [
27
+ { "type": "heading", "content": "Test All Sidebar Types", "showAt": 5 },
28
+ { "type": "spHeading","content": "SP Heading" },
29
+ { "type": "spText", "content": "This is a sidebar comment." },
30
+ { "type": "spMath", "content": "a^2 + b^2 = c^2" },
31
+ { "type": "spImage", "content": "/media/images/box.webp" },
32
+
33
+ { "type": "math", "content": "E = mc^2", "showAt": 12 },
34
+ { "type": "spHeading","content": "Einstein's Law" },
35
+ { "type": "spText", "content": "Energy–mass equivalence" },
36
+ { "type": "spImage", "content": "/media/images/box.webp" },
37
+
38
+ { "type": "math", "content": "\\\\int_0^\\\\pi \\\\sin x \\\\,dx = 2", "showAt": 20 },
39
+ { "type": "spHeading","content": "Integral Result" },
40
+ { "type": "spText", "content": "Area under sine from 0 to π" },
41
+ { "type": "spMath", "content": "\\\\int_0^\\\\pi \\\\sin x \\\\,dx = 2" },
42
+
43
+ { "type": "math", "content": "\\\\sum_{n=1}^{\\\\infty} \\\\frac{1}{n^2} = \\\\frac{\\\\pi^2}{6}", "showAt": 28 },
44
+ { "type": "spHeading","content": "Basel Problem" },
45
+ { "type": "spText", "content": "Euler's celebrated result" },
46
+ { "type": "spImage", "content": "/media/images/box.webp" },
47
+
48
+ { "type": "text", "content": "Ohm’s Law", "showAt": 36 },
49
+ { "type": "spMath", "content": "V = I R" },
50
+ { "type": "spText", "content": "Voltage = Current Ă— Resistance" },
51
+
52
+ { "type": "math", "content": "p = m v", "showAt": 42 },
53
+ { "type": "spText", "content": "Momentum = mass Ă— velocity" },
54
+
55
+ { "type": "math", "content": "KE = \\u00BD m v^2", "showAt": 46 },
56
+ { "type": "spText", "content": "Kinetic energy formula" },
57
+
58
+ { "type": "math", "content": "PE = m g h", "showAt": 50 },
59
+ { "type": "spText", "content": "Potential energy at height h" },
60
+
61
+ { "type": "text", "content": "End of test. All sidebar types shown.", "showAt": 54 },
62
+ { "type": "spText", "content": "Thanks for testing EQ format!" }
63
+ ]
64
+ }
65
+ ]
66
+ }
67
+