taleem-player 0.6.0-rc.1 β 0.7.0-rc
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 +172 -124
- package/dist/css/taleem.css +347 -0
- package/dist/css/themes/dark.css +6 -0
- package/dist/css/themes/light.css +6 -0
- package/dist/css/themes/paper.css +6 -0
- package/dist/taleem-player.esm.js +120 -11
- package/dist/taleem-player.umd.js +120 -11
- package/package.json +11 -7
package/README.md
CHANGED
|
@@ -1,215 +1,263 @@
|
|
|
1
1
|
|
|
2
|
-
#
|
|
2
|
+
# Taleem Player
|
|
3
3
|
|
|
4
|
-
**taleem-player** is a **time-driven player** for **Taleem slides**.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
<img src="https://raw.githubusercontent.com/bilza2023/taleem-player/main/docs/images/taleem.webp" alt="Taleem Player β JSON to Web Presentations" />
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
**Taleem Player** is a JavaScript library that converts **JSON slide data** into **web-based presentations**.
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
* timed presentations
|
|
12
|
-
* audio / videoβsynced slides
|
|
13
|
-
* external playback control
|
|
14
|
-
|
|
15
|
-
At its core, `taleem-player` does one thing:
|
|
16
|
-
|
|
17
|
-
> **Given a player-ready deck and a time value, render the correct Taleem slide.**
|
|
18
|
-
|
|
19
|
-
It does **not** author decks.
|
|
20
|
-
It does **not** fix data.
|
|
21
|
-
It does **not** manage time.
|
|
9
|
+
It provides multiple **modes** to display the same JSON presentation in different ways on the web.
|
|
22
10
|
|
|
23
11
|
---
|
|
12
|
+
###### Work in progress. Expect minor bugs, but no API breakages.
|
|
24
13
|
|
|
25
|
-
|
|
14
|
+
Demo and Documentation
|
|
26
15
|
|
|
27
|
-
|
|
16
|
+
See Taleem Player in action:
|
|
28
17
|
|
|
29
|
-
|
|
18
|
+
π https://bilza2023.github.io/taleem/
|
|
30
19
|
|
|
31
|
-
|
|
20
|
+
This live demo lets you explore:
|
|
32
21
|
|
|
33
|
-
|
|
34
|
-
* real visual behavior
|
|
35
|
-
* actual rendered output
|
|
36
|
-
* examples and demos
|
|
22
|
+
Browser Mode β instant, index-based slide rendering
|
|
37
23
|
|
|
38
|
-
|
|
24
|
+
Player Mode β time-driven, progressive presentations
|
|
39
25
|
|
|
40
|
-
|
|
26
|
+
Real Taleem slide JSON used in production
|
|
41
27
|
|
|
42
|
-
|
|
43
|
-
The website shows *results*.
|
|
28
|
+
Shared CSS system powering all display modes
|
|
44
29
|
|
|
30
|
+
No screenshots. No mock data.
|
|
31
|
+
What you see is the real engine running in the browser.
|
|
45
32
|
---
|
|
46
33
|
|
|
47
|
-
##
|
|
34
|
+
## What it does
|
|
35
|
+
|
|
36
|
+
* Takes **Taleem slide JSON**
|
|
37
|
+
* Renders it as a **web presentation**
|
|
38
|
+
* Supports **multiple display modes**
|
|
39
|
+
* Ships **ready-to-use CSS**
|
|
40
|
+
* Includes **utilities** for real-world usage
|
|
48
41
|
|
|
49
|
-
|
|
42
|
+
---
|
|
50
43
|
|
|
51
|
-
|
|
44
|
+
## Installation
|
|
52
45
|
|
|
53
|
-
```
|
|
54
|
-
|
|
46
|
+
```bash
|
|
47
|
+
npm install taleem-player
|
|
55
48
|
```
|
|
56
49
|
|
|
57
|
-
|
|
50
|
+
---
|
|
58
51
|
|
|
59
|
-
|
|
60
|
-
* or no slide (before or after the timeline)
|
|
52
|
+
## Display Modes
|
|
61
53
|
|
|
62
|
-
|
|
54
|
+
### 1. Browser Mode
|
|
63
55
|
|
|
64
|
-
|
|
56
|
+
**Index-based slide viewer**.
|
|
65
57
|
|
|
66
|
-
|
|
58
|
+
Use this when you want:
|
|
67
59
|
|
|
68
|
-
|
|
60
|
+
* manual navigation
|
|
61
|
+
* previews
|
|
62
|
+
* galleries
|
|
63
|
+
* syllabus / editor views
|
|
69
64
|
|
|
70
|
-
|
|
65
|
+
#### API
|
|
71
66
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
* Owns a single DOM stage
|
|
75
|
-
* Resolves which slide is active at a given time
|
|
76
|
-
* Renders slides using **taleem-slides**
|
|
77
|
-
* Exposes a **minimal API**
|
|
67
|
+
```js
|
|
68
|
+
import { createTaleemBrowser } from "taleem-player";
|
|
78
69
|
|
|
79
|
-
|
|
70
|
+
const browser = createTaleemBrowser({
|
|
71
|
+
mount: "#app",
|
|
72
|
+
deck
|
|
73
|
+
});
|
|
80
74
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
player.destroy()
|
|
75
|
+
browser.render(0); // render slide by index
|
|
76
|
+
browser.getTotal(); // total number of slides
|
|
84
77
|
```
|
|
85
78
|
|
|
86
|
-
|
|
79
|
+
Characteristics:
|
|
80
|
+
|
|
81
|
+
* slide index driven
|
|
82
|
+
* no timing
|
|
83
|
+
* deterministic rendering
|
|
84
|
+
* same slide JSON as other modes
|
|
87
85
|
|
|
88
86
|
---
|
|
89
87
|
|
|
90
|
-
|
|
88
|
+
### 2. Player Mode
|
|
91
89
|
|
|
92
|
-
|
|
90
|
+
**Time-based slide player**.
|
|
93
91
|
|
|
94
|
-
|
|
95
|
-
* auto-generate timings
|
|
96
|
-
* fix broken decks
|
|
97
|
-
* define slide layouts
|
|
98
|
-
* ship CSS
|
|
99
|
-
* manage audio or narration
|
|
100
|
-
* play / pause / autoplay
|
|
101
|
-
* own clocks or intervals
|
|
92
|
+
Use this when you want:
|
|
102
93
|
|
|
103
|
-
|
|
104
|
-
|
|
94
|
+
* narrated lessons
|
|
95
|
+
* video / audio sync
|
|
96
|
+
* timed presentations
|
|
105
97
|
|
|
106
|
-
|
|
98
|
+
#### API
|
|
99
|
+
|
|
100
|
+
```js
|
|
101
|
+
import { createTaleemPlayer } from "taleem-player";
|
|
102
|
+
|
|
103
|
+
const player = createTaleemPlayer({
|
|
104
|
+
mount: "#app",
|
|
105
|
+
deckDemo and Documentation
|
|
106
|
+
|
|
107
|
+
Live demo and documentation are available here:
|
|
108
|
+
|
|
109
|
+
π https://bilza2023.github.io/taleem/
|
|
110
|
+
|
|
111
|
+
The demo showcases:
|
|
107
112
|
|
|
108
|
-
|
|
113
|
+
browser mode rendering
|
|
109
114
|
|
|
110
|
-
|
|
115
|
+
player mode rendering
|
|
111
116
|
|
|
112
|
-
|
|
117
|
+
real Taleem slide JSON
|
|
113
118
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
+
shared CSS across modes
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
player.renderAt(12.5); // render slide at time (seconds)
|
|
123
|
+
player.destroy();
|
|
119
124
|
```
|
|
120
125
|
|
|
121
|
-
|
|
126
|
+
Characteristics:
|
|
127
|
+
|
|
128
|
+
* time driven
|
|
129
|
+
* external clock control
|
|
130
|
+
* no play / pause logic
|
|
131
|
+
* one active slide at a time
|
|
122
132
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
* no auto-injection
|
|
128
|
-
* no browser forgiveness
|
|
133
|
+
---
|
|
134
|
+
## Browser Mode vs Player Mode
|
|
135
|
+
|
|
136
|
+
Both modes render the same JSON presentation, but they serve very different purposes.
|
|
129
137
|
|
|
130
|
-
|
|
131
|
-
|
|
138
|
+
| Feature | Browser Mode | Player Mode |
|
|
139
|
+
|-------|-------------|-------------|
|
|
140
|
+
| Rendering model | Index-based | Time-based |
|
|
141
|
+
| Navigation | Manual (by slide index) | Progressive (by time) |
|
|
142
|
+
| Timing required | No | Yes (required) |
|
|
143
|
+
| Rendering behavior | One slide at a time | Slides change over time |
|
|
144
|
+
| Control source | Application-driven | External clock / media |
|
|
145
|
+
| Best suited for | Previews, galleries, editors | Narration, video, audio sync |
|
|
132
146
|
|
|
133
147
|
---
|
|
134
148
|
|
|
135
|
-
|
|
149
|
+
### Browser Mode
|
|
136
150
|
|
|
137
|
-
|
|
151
|
+
Use Browser Mode when you want direct access to slides.
|
|
138
152
|
|
|
139
|
-
|
|
153
|
+
**Characteristics**
|
|
154
|
+
- Index-based rendering
|
|
155
|
+
- No timing data required
|
|
156
|
+
- Deterministic output
|
|
140
157
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
158
|
+
**Ideal for**
|
|
159
|
+
- previews
|
|
160
|
+
- galleries
|
|
161
|
+
- editors
|
|
162
|
+
- syllabus pages
|
|
145
163
|
|
|
146
|
-
|
|
164
|
+
|
|
165
|
+
β οΈ Important:
|
|
166
|
+
In Player Mode, the user must provide valid and ordered timings (start, end).
|
|
167
|
+
The library does not auto-fix or guess timings.
|
|
147
168
|
|
|
148
169
|
---
|
|
149
170
|
|
|
150
|
-
##
|
|
171
|
+
## Utilities
|
|
151
172
|
|
|
152
|
-
|
|
173
|
+
Taleem Player includes small helper utilities for preparing decks.
|
|
153
174
|
|
|
154
|
-
###
|
|
175
|
+
### assignMockTimings
|
|
155
176
|
|
|
156
|
-
|
|
177
|
+
Convert a non-timed deck into a player-ready deck.
|
|
157
178
|
|
|
158
|
-
|
|
179
|
+
```js
|
|
180
|
+
import { assignMockTimings } from "taleem-player";
|
|
159
181
|
|
|
160
|
-
|
|
182
|
+
const timedDeck = assignMockTimings(deck, 5);
|
|
183
|
+
```
|
|
161
184
|
|
|
162
|
-
|
|
185
|
+
---
|
|
163
186
|
|
|
164
|
-
|
|
187
|
+
### resolveAssetPaths
|
|
165
188
|
|
|
166
|
-
|
|
189
|
+
Resolve image paths for deployment.
|
|
167
190
|
|
|
168
|
-
|
|
191
|
+
```js
|
|
192
|
+
import { resolveAssetPaths } from "taleem-player";
|
|
169
193
|
|
|
170
|
-
|
|
171
|
-
|
|
194
|
+
resolveAssetPaths(deck, "/images/");
|
|
195
|
+
```
|
|
172
196
|
|
|
173
197
|
---
|
|
174
198
|
|
|
175
|
-
|
|
199
|
+
### resolveBackground
|
|
200
|
+
|
|
201
|
+
Normalize and resolve background configuration.
|
|
176
202
|
|
|
177
203
|
```js
|
|
178
|
-
import {
|
|
204
|
+
import { resolveBackground } from "taleem-player";
|
|
179
205
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
deck // must be player-ready
|
|
183
|
-
});
|
|
206
|
+
resolveBackground(deck, "/images/");
|
|
207
|
+
```
|
|
184
208
|
|
|
185
|
-
|
|
186
|
-
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## CSS
|
|
212
|
+
|
|
213
|
+
Taleem Player ships with built-in styles.
|
|
214
|
+
|
|
215
|
+
### Base styles
|
|
216
|
+
|
|
217
|
+
```js
|
|
218
|
+
import "taleem-player/css";
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Themes
|
|
222
|
+
|
|
223
|
+
```js
|
|
224
|
+
import "taleem-player/css/dark";
|
|
225
|
+
import "taleem-player/css/light";
|
|
226
|
+
import "taleem-player/css/paper";
|
|
187
227
|
```
|
|
188
228
|
|
|
189
|
-
|
|
190
|
-
|
|
229
|
+
CSS controls layout, visibility, and visual behavior.
|
|
230
|
+
Modes share the same CSS.
|
|
191
231
|
|
|
192
232
|
---
|
|
193
233
|
|
|
194
|
-
##
|
|
234
|
+
## Input format
|
|
195
235
|
|
|
196
|
-
|
|
197
|
-
* Slides are deterministic
|
|
198
|
-
* Seconds are enough
|
|
199
|
-
* Libraries stay small
|
|
200
|
-
* Control lives at the top
|
|
236
|
+
Taleem Player does **not** define slide structure.
|
|
201
237
|
|
|
202
|
-
|
|
203
|
-
|
|
238
|
+
It renders JSON produced for **taleem-slides**.
|
|
239
|
+
|
|
240
|
+
* Player Mode requires slides with `start` / `end`
|
|
241
|
+
* Browser Mode only needs ordered slides
|
|
204
242
|
|
|
205
243
|
---
|
|
206
244
|
|
|
207
|
-
##
|
|
245
|
+
## What Taleem Player does NOT do
|
|
246
|
+
|
|
247
|
+
* create slides
|
|
248
|
+
* edit JSON
|
|
249
|
+
* validate schemas
|
|
250
|
+
* manage time or playback
|
|
251
|
+
* handle audio or narration
|
|
252
|
+
* provide UI controls
|
|
253
|
+
|
|
254
|
+
Those belong to the **application**, not the library.
|
|
255
|
+
|
|
256
|
+
---
|
|
208
257
|
|
|
209
|
-
|
|
258
|
+
## Status
|
|
210
259
|
|
|
211
|
-
|
|
212
|
-
No new concepts belong here.
|
|
260
|
+
**Release Candidate (API stable)**
|
|
213
261
|
|
|
214
262
|
---
|
|
215
263
|
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
|
|
2
|
+
/* =====================================================
|
|
3
|
+
TALEEM β Single Public Stylesheet
|
|
4
|
+
|
|
5
|
+
/* -------------------------------
|
|
6
|
+
Global Page Reset
|
|
7
|
+
------------------------------- */
|
|
8
|
+
|
|
9
|
+
html,body {
|
|
10
|
+
height: 100%;
|
|
11
|
+
overflow: hidden;
|
|
12
|
+
margin: 0;
|
|
13
|
+
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
|
14
|
+
background: var(--backgroundColor, #0b1220);
|
|
15
|
+
color: var(--primaryColor, #e6e9ff);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
#app {
|
|
19
|
+
position: relative;
|
|
20
|
+
width: 100vw;
|
|
21
|
+
min-height: 100vh;
|
|
22
|
+
overflow: hidden;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* -------------------------------
|
|
26
|
+
Browser / Player Layers
|
|
27
|
+
------------------------------- */
|
|
28
|
+
.taleem-browser-bg {
|
|
29
|
+
position: absolute;
|
|
30
|
+
inset: 0;
|
|
31
|
+
z-index: 0;
|
|
32
|
+
background-size: cover;
|
|
33
|
+
background-position: center;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.taleem-browser-slide {
|
|
37
|
+
position: relative;
|
|
38
|
+
z-index: 1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* -------------------------------
|
|
42
|
+
Base Slide Grammar
|
|
43
|
+
------------------------------- */
|
|
44
|
+
.slide {
|
|
45
|
+
height: 100vh;
|
|
46
|
+
box-sizing: border-box;
|
|
47
|
+
|
|
48
|
+
display: flex;
|
|
49
|
+
flex-direction: column;
|
|
50
|
+
justify-content: center;
|
|
51
|
+
align-items: center;
|
|
52
|
+
|
|
53
|
+
padding: 64px 80px;
|
|
54
|
+
gap: 32px;
|
|
55
|
+
|
|
56
|
+
overflow: hidden;
|
|
57
|
+
background: transparent;
|
|
58
|
+
color: var(--primaryColor, #e6e9ff);
|
|
59
|
+
|
|
60
|
+
font-size: 2.4rem;
|
|
61
|
+
line-height: 1.6;
|
|
62
|
+
letter-spacing: 0.01em;
|
|
63
|
+
text-align: center;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* -------------------------------
|
|
67
|
+
Global Image Safety
|
|
68
|
+
------------------------------- */
|
|
69
|
+
.slide img {
|
|
70
|
+
max-width: 100%;
|
|
71
|
+
max-height: 100%;
|
|
72
|
+
height: auto;
|
|
73
|
+
width: auto;
|
|
74
|
+
display: block;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* -------------------------------
|
|
78
|
+
Headings
|
|
79
|
+
------------------------------- */
|
|
80
|
+
.slide h1 {
|
|
81
|
+
margin: 0;
|
|
82
|
+
letter-spacing: -0.015em;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* -------------------------------
|
|
86
|
+
Slide Types
|
|
87
|
+
------------------------------- */
|
|
88
|
+
.slide.titleSlide h1 {
|
|
89
|
+
font-size: 5.6rem;
|
|
90
|
+
font-weight: 700;
|
|
91
|
+
line-height: 1.2;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.slide.titleAndSubtitle h1 {
|
|
95
|
+
font-size: 5.8rem;
|
|
96
|
+
font-weight: 700;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.slide.titleAndSubtitle h2 {
|
|
100
|
+
font-size: 3.8rem;
|
|
101
|
+
font-weight: 400;
|
|
102
|
+
opacity: 0.8;
|
|
103
|
+
margin: 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.slide.titleAndPara h1 {
|
|
107
|
+
font-size: 4.8rem;
|
|
108
|
+
font-weight: 600;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.slide.titleAndPara p {
|
|
112
|
+
font-size: 3rem;
|
|
113
|
+
max-width: 70ch;
|
|
114
|
+
opacity: 0.9;
|
|
115
|
+
margin: 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* -------------------------------
|
|
119
|
+
Bullet List
|
|
120
|
+
------------------------------- */
|
|
121
|
+
.slide.bulletList ul {
|
|
122
|
+
list-style: disc;
|
|
123
|
+
padding-left: 2rem;
|
|
124
|
+
margin: 0;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.slide.bulletList li {
|
|
128
|
+
font-size: 3.6rem;
|
|
129
|
+
margin-bottom: 1rem;
|
|
130
|
+
text-align: left;
|
|
131
|
+
font-weight: 500;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* -------------------------------
|
|
135
|
+
Image Variants
|
|
136
|
+
------------------------------- */
|
|
137
|
+
.slide.imageSlide {
|
|
138
|
+
padding: 0;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.slide.imageSlide img {
|
|
142
|
+
object-fit: contain;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.slide.imageWithTitle {
|
|
146
|
+
position: relative;
|
|
147
|
+
padding: 48px;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.slide.imageWithTitle img {
|
|
151
|
+
height: calc(100vh - 96px);
|
|
152
|
+
border-radius: 12px;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.slide.imageWithTitle h1 {
|
|
156
|
+
position: absolute;
|
|
157
|
+
bottom: 64px;
|
|
158
|
+
left: 50%;
|
|
159
|
+
transform: translateX(-50%);
|
|
160
|
+
font-size: 4.6rem;
|
|
161
|
+
background: rgba(0, 0, 0, 0.45);
|
|
162
|
+
padding: 0.4em 0.8em;
|
|
163
|
+
border-radius: 6px;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.slide.imageWithCaption {
|
|
167
|
+
display: flex;
|
|
168
|
+
flex-direction: column;
|
|
169
|
+
justify-content: center;
|
|
170
|
+
gap: 32px;
|
|
171
|
+
height: 100vh;
|
|
172
|
+
overflow: hidden;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.slide.imageWithCaption img {
|
|
176
|
+
max-height: 55vh; /* reduce slightly */
|
|
177
|
+
object-fit: contain;
|
|
178
|
+
flex-shrink: 0;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.slide.imageWithCaption p {
|
|
182
|
+
max-height: 20vh; /* hard cap text */
|
|
183
|
+
overflow: hidden;
|
|
184
|
+
text-overflow: ellipsis;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* -------------------------------
|
|
188
|
+
Two Column Text
|
|
189
|
+
------------------------------- */
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
.slide.twoColumnText {
|
|
193
|
+
flex-direction: row;
|
|
194
|
+
justify-content: center; /* center the columns block */
|
|
195
|
+
align-items: center;
|
|
196
|
+
gap: 64px;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.slide.twoColumnText > div {
|
|
200
|
+
flex: 1;
|
|
201
|
+
max-width: 520px; /* keeps columns visually centered */
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
/* QUOTE SLIDE */
|
|
206
|
+
.slide.quoteSlide {
|
|
207
|
+
display: flex;
|
|
208
|
+
flex-direction: column;
|
|
209
|
+
justify-content: center;
|
|
210
|
+
gap: 32px;
|
|
211
|
+
height: 100vh;
|
|
212
|
+
overflow: hidden;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.slide.quoteSlide blockquote {
|
|
216
|
+
max-height: 60vh;
|
|
217
|
+
overflow: hidden;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.slide.quoteSlide cite {
|
|
221
|
+
flex-shrink: 0;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* -------------------------------
|
|
225
|
+
Quote Slide
|
|
226
|
+
------------------------------- */
|
|
227
|
+
.slide.quoteSlide blockquote {
|
|
228
|
+
font-size: 3.8rem;
|
|
229
|
+
font-style: italic;
|
|
230
|
+
max-width: 60ch;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.slide.quoteSlide cite {
|
|
234
|
+
font-size: 2.4rem;
|
|
235
|
+
opacity: 0.75;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* -------------------------------
|
|
239
|
+
Big Number
|
|
240
|
+
------------------------------- */
|
|
241
|
+
.slide.bigNumber .number {
|
|
242
|
+
font-size: 9rem;
|
|
243
|
+
font-weight: 700;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/* -------------------------------
|
|
247
|
+
Fill Image (Full Bleed)
|
|
248
|
+
------------------------------- */
|
|
249
|
+
.slide.fillImage {
|
|
250
|
+
padding: 0;
|
|
251
|
+
height: 100vh;
|
|
252
|
+
display: block;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.slide.fillImage img {
|
|
256
|
+
width: 100%;
|
|
257
|
+
height: 100%;
|
|
258
|
+
object-fit: cover;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/* -------------------------------
|
|
262
|
+
Demo / Player UI (Optional)
|
|
263
|
+
------------------------------- */
|
|
264
|
+
#timebar {
|
|
265
|
+
position: fixed;
|
|
266
|
+
bottom: 0;
|
|
267
|
+
left: 0;
|
|
268
|
+
right: 0;
|
|
269
|
+
height: 32px;
|
|
270
|
+
background: rgba(0, 0, 0, 0.6);
|
|
271
|
+
backdrop-filter: blur(6px);
|
|
272
|
+
z-index: 10;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
/* ///////fixes */
|
|
278
|
+
|
|
279
|
+
/* -------------------------------
|
|
280
|
+
Image + Bullets (Side by Side)
|
|
281
|
+
------------------------------- */
|
|
282
|
+
|
|
283
|
+
.slide.imageRightBulletsLeft,
|
|
284
|
+
.slide.imageLeftBulletsRight {
|
|
285
|
+
display: flex;
|
|
286
|
+
flex-direction: row;
|
|
287
|
+
align-items: center;
|
|
288
|
+
gap: 64px;
|
|
289
|
+
text-align: left;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/* image on right */
|
|
293
|
+
.slide.imageRightBulletsLeft img {
|
|
294
|
+
order: 2;
|
|
295
|
+
}
|
|
296
|
+
/* -------------------------------
|
|
297
|
+
Table Slide
|
|
298
|
+
------------------------------- */
|
|
299
|
+
|
|
300
|
+
.slide.table {
|
|
301
|
+
display: flex;
|
|
302
|
+
justify-content: center;
|
|
303
|
+
align-items: center;
|
|
304
|
+
|
|
305
|
+
width: 100%;
|
|
306
|
+
height: 100vh;
|
|
307
|
+
|
|
308
|
+
padding: 64px 80px;
|
|
309
|
+
box-sizing: border-box;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/* actual table */
|
|
313
|
+
.slide.table table {
|
|
314
|
+
border-collapse: collapse;
|
|
315
|
+
width: 100%;
|
|
316
|
+
max-width: 1200px;
|
|
317
|
+
|
|
318
|
+
font-size: 2.8rem;
|
|
319
|
+
line-height: 1.4;
|
|
320
|
+
text-align: center;
|
|
321
|
+
|
|
322
|
+
color: var(--primaryColor, #e6e9ff);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/* header cells (title row) */
|
|
326
|
+
.slide.table thead th {
|
|
327
|
+
font-weight: 700; /* title row bold */
|
|
328
|
+
padding: 20px 24px;
|
|
329
|
+
|
|
330
|
+
border: 2px solid rgba(255, 255, 255, 0.35);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/* body cells */
|
|
334
|
+
.slide.table tbody td {
|
|
335
|
+
padding: 20px 24px;
|
|
336
|
+
|
|
337
|
+
border: 2px solid rgba(255, 255, 255, 0.25);
|
|
338
|
+
}
|
|
339
|
+
/* hide empty table header row */
|
|
340
|
+
.slide.table thead th:empty {
|
|
341
|
+
display: none;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
.slide.table thead tr:has(th:empty) {
|
|
345
|
+
display: none;
|
|
346
|
+
}
|
|
347
|
+
|
|
@@ -274,22 +274,19 @@ var ImageRightBulletsLeftSlide = {
|
|
|
274
274
|
var TableSlide = {
|
|
275
275
|
type: "table",
|
|
276
276
|
fromJSON(raw) {
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
277
|
+
const rows = raw.data;
|
|
278
|
+
if (!Array.isArray(rows) || rows.length === 0) {
|
|
279
|
+
console.warn("Empty table skipped", raw);
|
|
280
|
+
return null;
|
|
281
281
|
}
|
|
282
282
|
return Object.freeze({
|
|
283
283
|
type: "table",
|
|
284
284
|
render() {
|
|
285
285
|
return `
|
|
286
286
|
<table class="slide table">
|
|
287
|
-
<thead>
|
|
288
|
-
<tr>${headers.map((h) => `<th>${h}</th>`).join("")}</tr>
|
|
289
|
-
</thead>
|
|
290
287
|
<tbody>
|
|
291
288
|
${rows.map(
|
|
292
|
-
(
|
|
289
|
+
(row) => `<tr>${row.map((cell) => `<td>${cell}</td>`).join("")}</tr>`
|
|
293
290
|
).join("")}
|
|
294
291
|
</tbody>
|
|
295
292
|
</table>
|
|
@@ -593,7 +590,7 @@ function getSlideTemplate(type) {
|
|
|
593
590
|
return template;
|
|
594
591
|
}
|
|
595
592
|
|
|
596
|
-
// src/
|
|
593
|
+
// src/engines/player/stage.js
|
|
597
594
|
function createStage(mount) {
|
|
598
595
|
if (!mount) throw new Error("taleem-player: mount is required");
|
|
599
596
|
const root = typeof mount === "string" ? document.querySelector(mount) : mount;
|
|
@@ -618,7 +615,7 @@ function createStage(mount) {
|
|
|
618
615
|
};
|
|
619
616
|
}
|
|
620
617
|
|
|
621
|
-
// src/
|
|
618
|
+
// src/engines/player/player.js
|
|
622
619
|
function createTaleemPlayer({ mount, deck }) {
|
|
623
620
|
const stage = createStage(mount);
|
|
624
621
|
let lastSlide = null;
|
|
@@ -680,6 +677,118 @@ function createTaleemPlayer({ mount, deck }) {
|
|
|
680
677
|
destroy
|
|
681
678
|
};
|
|
682
679
|
}
|
|
680
|
+
|
|
681
|
+
// src/engines/browser/browser.js
|
|
682
|
+
function createTaleemBrowser({ mount, deck }) {
|
|
683
|
+
if (!mount) {
|
|
684
|
+
throw new Error("taleem-browser: mount is required");
|
|
685
|
+
}
|
|
686
|
+
if (!deck || !Array.isArray(deck.deck)) {
|
|
687
|
+
throw new Error("taleem-browser: valid deck-v1 required");
|
|
688
|
+
}
|
|
689
|
+
const root = typeof mount === "string" ? document.querySelector(mount) : mount;
|
|
690
|
+
if (!root) {
|
|
691
|
+
throw new Error("taleem-browser: mount not found");
|
|
692
|
+
}
|
|
693
|
+
root.innerHTML = `
|
|
694
|
+
<div class="taleem-browser-bg"></div>
|
|
695
|
+
<div class="taleem-browser-slide"></div>
|
|
696
|
+
`;
|
|
697
|
+
const bgEl = root.querySelector(".taleem-browser-bg");
|
|
698
|
+
const slideEl = root.querySelector(".taleem-browser-slide");
|
|
699
|
+
applyBackground(bgEl, deck.background);
|
|
700
|
+
const slides = deck.deck.map((slideJSON, i) => {
|
|
701
|
+
if (!slideJSON.type) {
|
|
702
|
+
throw new Error(`taleem-browser: slide ${i} missing type`);
|
|
703
|
+
}
|
|
704
|
+
const Template = getSlideTemplate(slideJSON.type);
|
|
705
|
+
if (!Template) {
|
|
706
|
+
throw new Error(`taleem-browser: unknown slide type "${slideJSON.type}"`);
|
|
707
|
+
}
|
|
708
|
+
return Template.fromJSON(slideJSON);
|
|
709
|
+
});
|
|
710
|
+
const total = slides.length;
|
|
711
|
+
function render(index, renderState = {}) {
|
|
712
|
+
if (index < 0 || index >= total) return;
|
|
713
|
+
const slide = slides[index];
|
|
714
|
+
slideEl.innerHTML = slide.render(renderState);
|
|
715
|
+
}
|
|
716
|
+
return {
|
|
717
|
+
render,
|
|
718
|
+
getTotal() {
|
|
719
|
+
return total;
|
|
720
|
+
}
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
function applyBackground(el, bg = {}) {
|
|
724
|
+
el.style.position = "absolute";
|
|
725
|
+
el.style.inset = "0";
|
|
726
|
+
el.style.zIndex = "0";
|
|
727
|
+
el.style.backgroundColor = bg.backgroundColor || "#000";
|
|
728
|
+
el.style.backgroundImage = bg.backgroundImage ? `url(${bg.backgroundImage})` : "none";
|
|
729
|
+
el.style.backgroundSize = "cover";
|
|
730
|
+
el.style.backgroundPosition = "center";
|
|
731
|
+
el.style.opacity = bg.backgroundImageOpacity !== void 0 ? bg.backgroundImageOpacity : 1;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
// src/utils/assignMockTimings.js
|
|
735
|
+
function assignMockTimings(goldenDeck, slideDuration = 5) {
|
|
736
|
+
if (!goldenDeck || !Array.isArray(goldenDeck.deck) || typeof slideDuration !== "number") {
|
|
737
|
+
throw new Error("assignMockTimings: invalid deck or slideDuration");
|
|
738
|
+
}
|
|
739
|
+
let currentTime = 0;
|
|
740
|
+
const deckWithTimings = {
|
|
741
|
+
...goldenDeck,
|
|
742
|
+
deck: goldenDeck.deck.map((slide) => {
|
|
743
|
+
const start = currentTime;
|
|
744
|
+
const end = start + slideDuration;
|
|
745
|
+
currentTime = end;
|
|
746
|
+
const data = Array.isArray(slide.data) ? slide.data.map((item) => ({
|
|
747
|
+
...item,
|
|
748
|
+
showAt: start + (typeof item.showAt === "number" ? item.showAt : 0)
|
|
749
|
+
})) : slide.data;
|
|
750
|
+
return {
|
|
751
|
+
...slide,
|
|
752
|
+
start,
|
|
753
|
+
end,
|
|
754
|
+
data
|
|
755
|
+
};
|
|
756
|
+
})
|
|
757
|
+
};
|
|
758
|
+
return deckWithTimings;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// src/utils/resolveAssetPaths.js
|
|
762
|
+
function resolveAssetPaths(deck, IMG_BASE) {
|
|
763
|
+
if (deck.background?.backgroundImage && typeof deck.background.backgroundImage === "string") {
|
|
764
|
+
deck.background.backgroundImage = IMG_BASE + deck.background.backgroundImage.split("/").pop();
|
|
765
|
+
}
|
|
766
|
+
deck.deck.forEach((slide) => {
|
|
767
|
+
slide.data?.forEach((item) => {
|
|
768
|
+
if (item.name === "image" && typeof item.content === "string") {
|
|
769
|
+
item.content = IMG_BASE + item.content.split("/").pop();
|
|
770
|
+
}
|
|
771
|
+
});
|
|
772
|
+
});
|
|
773
|
+
return deck;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// src/utils/resolveBackground.js
|
|
777
|
+
function resolveBackground2(deck, ASSET_BASE) {
|
|
778
|
+
if (!deck || !deck.background) return deck;
|
|
779
|
+
const bg = deck.background;
|
|
780
|
+
if (typeof bg.backgroundImage === "string" && bg.backgroundImage.length > 0) {
|
|
781
|
+
bg.backgroundImage = ASSET_BASE + bg.backgroundImage.split("/").pop();
|
|
782
|
+
}
|
|
783
|
+
if (bg.backgroundImageOpacity === void 0) {
|
|
784
|
+
bg.backgroundImageOpacity = 1;
|
|
785
|
+
}
|
|
786
|
+
return deck;
|
|
787
|
+
}
|
|
683
788
|
export {
|
|
684
|
-
|
|
789
|
+
assignMockTimings,
|
|
790
|
+
createTaleemBrowser,
|
|
791
|
+
createTaleemPlayer,
|
|
792
|
+
resolveAssetPaths,
|
|
793
|
+
resolveBackground2 as resolveBackground
|
|
685
794
|
};
|
|
@@ -20,7 +20,11 @@ var TaleemPlayer = (() => {
|
|
|
20
20
|
// src/index.js
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
|
|
23
|
+
assignMockTimings: () => assignMockTimings,
|
|
24
|
+
createTaleemBrowser: () => createTaleemBrowser,
|
|
25
|
+
createTaleemPlayer: () => createTaleemPlayer,
|
|
26
|
+
resolveAssetPaths: () => resolveAssetPaths,
|
|
27
|
+
resolveBackground: () => resolveBackground2
|
|
24
28
|
});
|
|
25
29
|
|
|
26
30
|
// node_modules/taleem-slides/src/slides/TitleSlide.js
|
|
@@ -299,22 +303,19 @@ var TaleemPlayer = (() => {
|
|
|
299
303
|
var TableSlide = {
|
|
300
304
|
type: "table",
|
|
301
305
|
fromJSON(raw) {
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
+
const rows = raw.data;
|
|
307
|
+
if (!Array.isArray(rows) || rows.length === 0) {
|
|
308
|
+
console.warn("Empty table skipped", raw);
|
|
309
|
+
return null;
|
|
306
310
|
}
|
|
307
311
|
return Object.freeze({
|
|
308
312
|
type: "table",
|
|
309
313
|
render() {
|
|
310
314
|
return `
|
|
311
315
|
<table class="slide table">
|
|
312
|
-
<thead>
|
|
313
|
-
<tr>${headers.map((h) => `<th>${h}</th>`).join("")}</tr>
|
|
314
|
-
</thead>
|
|
315
316
|
<tbody>
|
|
316
317
|
${rows.map(
|
|
317
|
-
(
|
|
318
|
+
(row) => `<tr>${row.map((cell) => `<td>${cell}</td>`).join("")}</tr>`
|
|
318
319
|
).join("")}
|
|
319
320
|
</tbody>
|
|
320
321
|
</table>
|
|
@@ -618,7 +619,7 @@ var TaleemPlayer = (() => {
|
|
|
618
619
|
return template;
|
|
619
620
|
}
|
|
620
621
|
|
|
621
|
-
// src/
|
|
622
|
+
// src/engines/player/stage.js
|
|
622
623
|
function createStage(mount) {
|
|
623
624
|
if (!mount) throw new Error("taleem-player: mount is required");
|
|
624
625
|
const root = typeof mount === "string" ? document.querySelector(mount) : mount;
|
|
@@ -643,7 +644,7 @@ var TaleemPlayer = (() => {
|
|
|
643
644
|
};
|
|
644
645
|
}
|
|
645
646
|
|
|
646
|
-
// src/
|
|
647
|
+
// src/engines/player/player.js
|
|
647
648
|
function createTaleemPlayer({ mount, deck }) {
|
|
648
649
|
const stage = createStage(mount);
|
|
649
650
|
let lastSlide = null;
|
|
@@ -705,5 +706,113 @@ var TaleemPlayer = (() => {
|
|
|
705
706
|
destroy
|
|
706
707
|
};
|
|
707
708
|
}
|
|
709
|
+
|
|
710
|
+
// src/engines/browser/browser.js
|
|
711
|
+
function createTaleemBrowser({ mount, deck }) {
|
|
712
|
+
if (!mount) {
|
|
713
|
+
throw new Error("taleem-browser: mount is required");
|
|
714
|
+
}
|
|
715
|
+
if (!deck || !Array.isArray(deck.deck)) {
|
|
716
|
+
throw new Error("taleem-browser: valid deck-v1 required");
|
|
717
|
+
}
|
|
718
|
+
const root = typeof mount === "string" ? document.querySelector(mount) : mount;
|
|
719
|
+
if (!root) {
|
|
720
|
+
throw new Error("taleem-browser: mount not found");
|
|
721
|
+
}
|
|
722
|
+
root.innerHTML = `
|
|
723
|
+
<div class="taleem-browser-bg"></div>
|
|
724
|
+
<div class="taleem-browser-slide"></div>
|
|
725
|
+
`;
|
|
726
|
+
const bgEl = root.querySelector(".taleem-browser-bg");
|
|
727
|
+
const slideEl = root.querySelector(".taleem-browser-slide");
|
|
728
|
+
applyBackground(bgEl, deck.background);
|
|
729
|
+
const slides = deck.deck.map((slideJSON, i) => {
|
|
730
|
+
if (!slideJSON.type) {
|
|
731
|
+
throw new Error(`taleem-browser: slide ${i} missing type`);
|
|
732
|
+
}
|
|
733
|
+
const Template = getSlideTemplate(slideJSON.type);
|
|
734
|
+
if (!Template) {
|
|
735
|
+
throw new Error(`taleem-browser: unknown slide type "${slideJSON.type}"`);
|
|
736
|
+
}
|
|
737
|
+
return Template.fromJSON(slideJSON);
|
|
738
|
+
});
|
|
739
|
+
const total = slides.length;
|
|
740
|
+
function render(index, renderState = {}) {
|
|
741
|
+
if (index < 0 || index >= total) return;
|
|
742
|
+
const slide = slides[index];
|
|
743
|
+
slideEl.innerHTML = slide.render(renderState);
|
|
744
|
+
}
|
|
745
|
+
return {
|
|
746
|
+
render,
|
|
747
|
+
getTotal() {
|
|
748
|
+
return total;
|
|
749
|
+
}
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
function applyBackground(el, bg = {}) {
|
|
753
|
+
el.style.position = "absolute";
|
|
754
|
+
el.style.inset = "0";
|
|
755
|
+
el.style.zIndex = "0";
|
|
756
|
+
el.style.backgroundColor = bg.backgroundColor || "#000";
|
|
757
|
+
el.style.backgroundImage = bg.backgroundImage ? `url(${bg.backgroundImage})` : "none";
|
|
758
|
+
el.style.backgroundSize = "cover";
|
|
759
|
+
el.style.backgroundPosition = "center";
|
|
760
|
+
el.style.opacity = bg.backgroundImageOpacity !== void 0 ? bg.backgroundImageOpacity : 1;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// src/utils/assignMockTimings.js
|
|
764
|
+
function assignMockTimings(goldenDeck, slideDuration = 5) {
|
|
765
|
+
if (!goldenDeck || !Array.isArray(goldenDeck.deck) || typeof slideDuration !== "number") {
|
|
766
|
+
throw new Error("assignMockTimings: invalid deck or slideDuration");
|
|
767
|
+
}
|
|
768
|
+
let currentTime = 0;
|
|
769
|
+
const deckWithTimings = {
|
|
770
|
+
...goldenDeck,
|
|
771
|
+
deck: goldenDeck.deck.map((slide) => {
|
|
772
|
+
const start = currentTime;
|
|
773
|
+
const end = start + slideDuration;
|
|
774
|
+
currentTime = end;
|
|
775
|
+
const data = Array.isArray(slide.data) ? slide.data.map((item) => ({
|
|
776
|
+
...item,
|
|
777
|
+
showAt: start + (typeof item.showAt === "number" ? item.showAt : 0)
|
|
778
|
+
})) : slide.data;
|
|
779
|
+
return {
|
|
780
|
+
...slide,
|
|
781
|
+
start,
|
|
782
|
+
end,
|
|
783
|
+
data
|
|
784
|
+
};
|
|
785
|
+
})
|
|
786
|
+
};
|
|
787
|
+
return deckWithTimings;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
// src/utils/resolveAssetPaths.js
|
|
791
|
+
function resolveAssetPaths(deck, IMG_BASE) {
|
|
792
|
+
if (deck.background?.backgroundImage && typeof deck.background.backgroundImage === "string") {
|
|
793
|
+
deck.background.backgroundImage = IMG_BASE + deck.background.backgroundImage.split("/").pop();
|
|
794
|
+
}
|
|
795
|
+
deck.deck.forEach((slide) => {
|
|
796
|
+
slide.data?.forEach((item) => {
|
|
797
|
+
if (item.name === "image" && typeof item.content === "string") {
|
|
798
|
+
item.content = IMG_BASE + item.content.split("/").pop();
|
|
799
|
+
}
|
|
800
|
+
});
|
|
801
|
+
});
|
|
802
|
+
return deck;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// src/utils/resolveBackground.js
|
|
806
|
+
function resolveBackground2(deck, ASSET_BASE) {
|
|
807
|
+
if (!deck || !deck.background) return deck;
|
|
808
|
+
const bg = deck.background;
|
|
809
|
+
if (typeof bg.backgroundImage === "string" && bg.backgroundImage.length > 0) {
|
|
810
|
+
bg.backgroundImage = ASSET_BASE + bg.backgroundImage.split("/").pop();
|
|
811
|
+
}
|
|
812
|
+
if (bg.backgroundImageOpacity === void 0) {
|
|
813
|
+
bg.backgroundImageOpacity = 1;
|
|
814
|
+
}
|
|
815
|
+
return deck;
|
|
816
|
+
}
|
|
708
817
|
return __toCommonJS(index_exports);
|
|
709
818
|
})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "taleem-player",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0-rc",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/taleem-player.umd.js",
|
|
6
6
|
"module": "./dist/taleem-player.esm.js",
|
|
@@ -8,22 +8,26 @@
|
|
|
8
8
|
".": {
|
|
9
9
|
"import": "./dist/taleem-player.esm.js",
|
|
10
10
|
"require": "./dist/taleem-player.umd.js"
|
|
11
|
-
}
|
|
11
|
+
},
|
|
12
|
+
"./css": "./dist/css/taleem.css",
|
|
13
|
+
"./css/dark": "./dist/css/themes/dark.css",
|
|
14
|
+
"./css/light": "./dist/css/themes/light.css",
|
|
15
|
+
"./css/paper": "./dist/css/themes/paper.css"
|
|
12
16
|
},
|
|
13
17
|
"files": [
|
|
14
18
|
"dist"
|
|
15
19
|
],
|
|
16
20
|
"scripts": {
|
|
17
21
|
"build": "node ./scripts/build.js",
|
|
18
|
-
"test": "
|
|
22
|
+
"test": "vitest run"
|
|
19
23
|
},
|
|
20
24
|
"dependencies": {
|
|
21
|
-
"taleem-core": "^1.3
|
|
22
|
-
"taleem-slides": "^0.6.
|
|
25
|
+
"taleem-core": "^1.4.3",
|
|
26
|
+
"taleem-slides": "^0.6.2-rc.6"
|
|
23
27
|
},
|
|
24
28
|
"devDependencies": {
|
|
25
29
|
"esbuild": "^0.27.2",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
30
|
+
"jsdom": "^22.1.0",
|
|
31
|
+
"vitest": "^3.2.4"
|
|
28
32
|
}
|
|
29
33
|
}
|