taleem-player 1.0.1 → 1.0.3

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 CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  # Taleem Player
3
2
 
4
3
  <img src="./docs/images/taleem.webp"
@@ -7,7 +6,7 @@
7
6
 
8
7
  **Taleem Player** converts **Taleem JSON slide data** into **web-based presentations**.
9
8
 
10
- It renders the *same taleem JSON* in multiple ways using different display modes.
9
+ It renders the _same taleem JSON_ in multiple ways using different display modes.
11
10
 
12
11
  > **Stable 1.0 — API frozen.**
13
12
  > Internal improvements may continue without breaking public contracts.
@@ -19,6 +18,7 @@ It renders the *same taleem JSON* in multiple ways using different display modes
19
18
  👉 https://bilza2023.github.io/taleem/
20
19
 
21
20
  The live demo shows:
21
+
22
22
  - Browser Mode (index-based rendering)
23
23
  - Player Mode (time-based rendering)
24
24
  - Real production Taleem JSON
@@ -33,7 +33,7 @@ What you see is the real engine running in the browser.**
33
33
 
34
34
  ```bash
35
35
  npm install taleem-player
36
- ````
36
+ ```
37
37
 
38
38
  ---
39
39
 
@@ -48,7 +48,7 @@ import { createTaleemBrowser } from "taleem-player";
48
48
 
49
49
  const browser = createTaleemBrowser({
50
50
  mount: "#app",
51
- deck
51
+ deck,
52
52
  });
53
53
 
54
54
  browser.render(0);
@@ -57,10 +57,10 @@ browser.getTotal();
57
57
 
58
58
  **Ideal for**
59
59
 
60
- * previews
61
- * galleries
62
- * editors
63
- * syllabus pages
60
+ - previews
61
+ - galleries
62
+ - editors
63
+ - syllabus pages
64
64
 
65
65
  ---
66
66
 
@@ -77,9 +77,9 @@ player.renderAt(12.5);
77
77
 
78
78
  **Ideal for**
79
79
 
80
- * narrated lessons
81
- * video / audio sync
82
- * recorded presentations
80
+ - narrated lessons
81
+ - video / audio sync
82
+ - recorded presentations
83
83
 
84
84
  ---
85
85
 
@@ -100,7 +100,6 @@ player.renderAt(12.5);
100
100
 
101
101
  ## Utilities (Runtime-safe)
102
102
 
103
-
104
103
  These **Utilities (Runtime-safe)** are exported :
105
104
 
106
105
  ```js
@@ -108,14 +107,14 @@ import {
108
107
  assignMockTimings,
109
108
  resolveAssetPaths,
110
109
  resolveBackground,
111
- getDeckEndTime
110
+ getDeckEndTime,
112
111
  } from "taleem-player";
113
112
  ```
114
113
 
115
- * `assignMockTimings(deck, seconds)`
116
- * `resolveAssetPaths(deck, basePath)`
117
- * `resolveBackground(deck, basePath)`
118
- * `getDeckEndTime(deck)`
114
+ - `assignMockTimings(deck, seconds)`
115
+ - `resolveAssetPaths(deck, basePath)`
116
+ - `resolveBackground(deck, basePath)`
117
+ - `getDeckEndTime(deck)`
119
118
 
120
119
  These helpers prepare decks for real usage and runtime playback.
121
120
 
@@ -137,11 +136,11 @@ All modes share the same styling system.
137
136
 
138
137
  ## What Taleem Player does NOT do
139
138
 
140
- * create slides
141
- * edit JSON
142
- * manage clocks or media playback
143
- * handle audio or narration
144
- * auto-validate or repair data
139
+ - create slides
140
+ - edit JSON
141
+ - manage clocks or media playback
142
+ - handle audio or narration
143
+ - auto-validate or repair data
145
144
 
146
145
  Those responsibilities belong to the **application layer**.
147
146
 
@@ -151,9 +150,13 @@ Those responsibilities belong to the **application layer**.
151
150
 
152
151
  **Stable — Version 1.0**
153
152
 
153
+ The `eq` slide type is **experimental**:
154
+ - it is implemented but intentionally limited
155
+ - it should not be relied on for production math rendering
156
+ - its behavior may evolve without breaking the core player API
157
+
154
158
  ---
155
159
 
156
160
  ## License
157
161
 
158
162
  MIT
159
-
@@ -344,4 +344,67 @@
344
344
  .slide.table thead tr:has(th:empty) {
345
345
  display: none;
346
346
  }
347
+
348
+
349
+ /* -------------------------------
350
+ Corner Words Slide (4 Quadrants)
351
+ ------------------------------- */
352
+
353
+ .slide.cornerWordsSlide {
354
+ position: relative;
355
+ width: 100%;
356
+ height: 100vh;
357
+ padding: 0;
358
+ }
359
+
360
+ /* base card */
361
+ .cornerWordsSlide .corner-card {
362
+ position: absolute;
363
+ width: 45%;
364
+ height: 45%;
365
+
366
+ display: flex;
367
+ flex-direction: column;
368
+ justify-content: center;
369
+ align-items: center;
370
+ gap: 16px;
371
+
372
+ font-size: 4.2rem;
373
+ font-weight: 700;
374
+ letter-spacing: 0.02em;
375
+ text-align: center;
376
+ }
377
+
378
+ /* emoji / icon */
379
+ .cornerWordsSlide .corner-card .icon {
380
+ font-size: 5.2rem;
381
+ line-height: 1;
382
+ }
383
+
384
+ /* label text */
385
+ .cornerWordsSlide .corner-card .label {
386
+ font-size: 3.6rem;
387
+ font-weight: 600;
388
+ }
389
+
390
+ /* quadrants */
391
+ .cornerWordsSlide .corner-1 {
392
+ top: 0;
393
+ left: 0;
394
+ }
395
+
396
+ .cornerWordsSlide .corner-2 {
397
+ top: 0;
398
+ right: 0;
399
+ }
400
+
401
+ .cornerWordsSlide .corner-3 {
402
+ bottom: 0;
403
+ left: 0;
404
+ }
405
+
406
+ .cornerWordsSlide .corner-4 {
407
+ bottom: 0;
408
+ right: 0;
409
+ }
347
410
 
@@ -532,23 +532,47 @@ var EqSlide = {
532
532
  type: "eq",
533
533
  fromJSON(raw) {
534
534
  const lines = raw.data?.filter((d) => d.name === "line").map((d) => ({
535
- type: d.type,
536
- content: d.content
535
+ content: d.content,
536
+ spItems: Array.isArray(d.spItems) ? d.spItems : []
537
537
  }));
538
538
  if (!lines || lines.length === 0) {
539
539
  throw new Error("eq: requires at least one line");
540
540
  }
541
+ const WINDOW_SIZE = 4;
541
542
  return Object.freeze({
542
543
  type: "eq",
543
544
  lines,
544
- render({ visibleCount = lines.length, activeIndex = null } = {}) {
545
+ render({ visibleCount = lines.length, activeIndex = -1 } = {}) {
546
+ const end = Math.min(visibleCount, lines.length);
547
+ const start = Math.max(0, end - WINDOW_SIZE);
548
+ const windowed = lines.slice(start, end);
549
+ const localActive = activeIndex >= start && activeIndex < end ? activeIndex - start : -1;
550
+ const activeSpItems = activeIndex >= 0 && activeIndex < lines.length ? lines[activeIndex].spItems : [];
545
551
  return `
546
552
  <section class="slide eq">
547
- ${lines.map((l, i) => {
548
- if (i >= visibleCount) return "";
549
- const cls = i === activeIndex ? "is-active" : activeIndex !== null && i < activeIndex ? "is-dim" : "";
550
- return `<div class="eq-line ${cls}">${l.content}</div>`;
551
- }).join("")}
553
+ <div class="eq-layout">
554
+
555
+ <div class="eq-left">
556
+ ${windowed.map(
557
+ (l, i) => `
558
+ <div class="eq-line ${i === localActive ? "is-active" : ""}">
559
+ ${l.content}
560
+ </div>
561
+ `
562
+ ).join("")}
563
+ </div>
564
+
565
+ <div class="eq-right">
566
+ ${activeSpItems.map(
567
+ (sp) => `
568
+ <div class="eq-sp-item eq-${sp.type || "item"}">
569
+ ${sp.content}
570
+ </div>
571
+ `
572
+ ).join("")}
573
+ </div>
574
+
575
+ </div>
552
576
  </section>
553
577
  `;
554
578
  }
@@ -591,7 +615,7 @@ function getSlideTemplate(type) {
591
615
  }
592
616
 
593
617
  // src/engines/player/stage.js
594
- function createStage(mount) {
618
+ function createStage(mount, background = {}) {
595
619
  if (!mount) throw new Error("taleem-player: mount is required");
596
620
  const root = typeof mount === "string" ? document.querySelector(mount) : mount;
597
621
  if (!root) throw new Error("taleem-player: mount element not found");
@@ -601,15 +625,41 @@ function createStage(mount) {
601
625
  stage.style.position = "relative";
602
626
  stage.style.width = "100%";
603
627
  stage.style.height = "100%";
628
+ stage.style.overflow = "hidden";
629
+ const bgLayer = document.createElement("div");
630
+ bgLayer.className = "taleem-player-bg";
631
+ bgLayer.style.position = "absolute";
632
+ bgLayer.style.inset = "0";
633
+ bgLayer.style.zIndex = "0";
634
+ bgLayer.style.backgroundRepeat = "no-repeat";
635
+ bgLayer.style.backgroundSize = "cover";
636
+ bgLayer.style.backgroundPosition = "center";
637
+ if (background.backgroundColor) {
638
+ bgLayer.style.backgroundColor = background.backgroundColor;
639
+ }
640
+ if (background.backgroundImage) {
641
+ bgLayer.style.backgroundImage = `url("${background.backgroundImage}")`;
642
+ }
643
+ if (typeof background.backgroundImageOpacity === "number" && background.backgroundImageOpacity < 1) {
644
+ bgLayer.style.opacity = String(background.backgroundImageOpacity);
645
+ }
646
+ const slideLayer = document.createElement("div");
647
+ slideLayer.className = "taleem-player-slides";
648
+ slideLayer.style.position = "relative";
649
+ slideLayer.style.zIndex = "1";
650
+ slideLayer.style.width = "100%";
651
+ slideLayer.style.height = "100%";
652
+ stage.appendChild(bgLayer);
653
+ stage.appendChild(slideLayer);
604
654
  root.appendChild(stage);
605
655
  function clear() {
606
- stage.innerHTML = "";
656
+ slideLayer.innerHTML = "";
607
657
  }
608
658
  function destroy() {
609
659
  root.innerHTML = "";
610
660
  }
611
661
  return {
612
- el: stage,
662
+ el: slideLayer,
613
663
  clear,
614
664
  destroy
615
665
  };
@@ -617,7 +667,7 @@ function createStage(mount) {
617
667
 
618
668
  // src/engines/player/player.js
619
669
  function createTaleemPlayer({ mount, deck }) {
620
- const stage = createStage(mount);
670
+ const stage = createStage(mount, deck.background);
621
671
  let lastSlide = null;
622
672
  let lastRenderedKey = null;
623
673
  function getSlideAtTime(deck2, time) {
@@ -562,23 +562,47 @@ var TaleemPlayer = (() => {
562
562
  type: "eq",
563
563
  fromJSON(raw) {
564
564
  const lines = raw.data?.filter((d) => d.name === "line").map((d) => ({
565
- type: d.type,
566
- content: d.content
565
+ content: d.content,
566
+ spItems: Array.isArray(d.spItems) ? d.spItems : []
567
567
  }));
568
568
  if (!lines || lines.length === 0) {
569
569
  throw new Error("eq: requires at least one line");
570
570
  }
571
+ const WINDOW_SIZE = 4;
571
572
  return Object.freeze({
572
573
  type: "eq",
573
574
  lines,
574
- render({ visibleCount = lines.length, activeIndex = null } = {}) {
575
+ render({ visibleCount = lines.length, activeIndex = -1 } = {}) {
576
+ const end = Math.min(visibleCount, lines.length);
577
+ const start = Math.max(0, end - WINDOW_SIZE);
578
+ const windowed = lines.slice(start, end);
579
+ const localActive = activeIndex >= start && activeIndex < end ? activeIndex - start : -1;
580
+ const activeSpItems = activeIndex >= 0 && activeIndex < lines.length ? lines[activeIndex].spItems : [];
575
581
  return `
576
582
  <section class="slide eq">
577
- ${lines.map((l, i) => {
578
- if (i >= visibleCount) return "";
579
- const cls = i === activeIndex ? "is-active" : activeIndex !== null && i < activeIndex ? "is-dim" : "";
580
- return `<div class="eq-line ${cls}">${l.content}</div>`;
581
- }).join("")}
583
+ <div class="eq-layout">
584
+
585
+ <div class="eq-left">
586
+ ${windowed.map(
587
+ (l, i) => `
588
+ <div class="eq-line ${i === localActive ? "is-active" : ""}">
589
+ ${l.content}
590
+ </div>
591
+ `
592
+ ).join("")}
593
+ </div>
594
+
595
+ <div class="eq-right">
596
+ ${activeSpItems.map(
597
+ (sp) => `
598
+ <div class="eq-sp-item eq-${sp.type || "item"}">
599
+ ${sp.content}
600
+ </div>
601
+ `
602
+ ).join("")}
603
+ </div>
604
+
605
+ </div>
582
606
  </section>
583
607
  `;
584
608
  }
@@ -621,7 +645,7 @@ var TaleemPlayer = (() => {
621
645
  }
622
646
 
623
647
  // src/engines/player/stage.js
624
- function createStage(mount) {
648
+ function createStage(mount, background = {}) {
625
649
  if (!mount) throw new Error("taleem-player: mount is required");
626
650
  const root = typeof mount === "string" ? document.querySelector(mount) : mount;
627
651
  if (!root) throw new Error("taleem-player: mount element not found");
@@ -631,15 +655,41 @@ var TaleemPlayer = (() => {
631
655
  stage.style.position = "relative";
632
656
  stage.style.width = "100%";
633
657
  stage.style.height = "100%";
658
+ stage.style.overflow = "hidden";
659
+ const bgLayer = document.createElement("div");
660
+ bgLayer.className = "taleem-player-bg";
661
+ bgLayer.style.position = "absolute";
662
+ bgLayer.style.inset = "0";
663
+ bgLayer.style.zIndex = "0";
664
+ bgLayer.style.backgroundRepeat = "no-repeat";
665
+ bgLayer.style.backgroundSize = "cover";
666
+ bgLayer.style.backgroundPosition = "center";
667
+ if (background.backgroundColor) {
668
+ bgLayer.style.backgroundColor = background.backgroundColor;
669
+ }
670
+ if (background.backgroundImage) {
671
+ bgLayer.style.backgroundImage = `url("${background.backgroundImage}")`;
672
+ }
673
+ if (typeof background.backgroundImageOpacity === "number" && background.backgroundImageOpacity < 1) {
674
+ bgLayer.style.opacity = String(background.backgroundImageOpacity);
675
+ }
676
+ const slideLayer = document.createElement("div");
677
+ slideLayer.className = "taleem-player-slides";
678
+ slideLayer.style.position = "relative";
679
+ slideLayer.style.zIndex = "1";
680
+ slideLayer.style.width = "100%";
681
+ slideLayer.style.height = "100%";
682
+ stage.appendChild(bgLayer);
683
+ stage.appendChild(slideLayer);
634
684
  root.appendChild(stage);
635
685
  function clear() {
636
- stage.innerHTML = "";
686
+ slideLayer.innerHTML = "";
637
687
  }
638
688
  function destroy() {
639
689
  root.innerHTML = "";
640
690
  }
641
691
  return {
642
- el: stage,
692
+ el: slideLayer,
643
693
  clear,
644
694
  destroy
645
695
  };
@@ -647,7 +697,7 @@ var TaleemPlayer = (() => {
647
697
 
648
698
  // src/engines/player/player.js
649
699
  function createTaleemPlayer({ mount, deck }) {
650
- const stage = createStage(mount);
700
+ const stage = createStage(mount, deck.background);
651
701
  let lastSlide = null;
652
702
  let lastRenderedKey = null;
653
703
  function getSlideAtTime(deck2, time) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taleem-player",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "type": "module",
5
5
  "main": "./dist/taleem-player.umd.js",
6
6
  "module": "./dist/taleem-player.esm.js",
@@ -28,12 +28,13 @@
28
28
  "test": "vitest run"
29
29
  },
30
30
  "dependencies": {
31
- "taleem-core": "^1.4.3",
32
- "taleem-slides": "^0.6.2-rc.6"
31
+ "taleem-slides": "^1.0.1"
33
32
  },
34
33
  "devDependencies": {
35
34
  "esbuild": "^0.27.2",
36
35
  "jsdom": "^22.1.0",
37
- "vitest": "^3.2.4"
36
+ "taleem-core": "^1.5.1",
37
+ "vitest": "^3.2.4",
38
+ "zod": "^4.3.6"
38
39
  }
39
40
  }