@0m0g1/griot 0.1.16 → 0.1.19

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0m0g1/griot",
3
- "version": "0.1.16",
3
+ "version": "0.1.19",
4
4
  "description": "A self-contained block-based rich text editor and renderer built for historical document authoring.",
5
5
  "type": "module",
6
6
  "main": "./src/Griot.js",
@@ -476,148 +476,6 @@ function _renderQuiz(block, opts) {
476
476
  return container;
477
477
  }
478
478
 
479
- function _renderQuiz(block, opts) {
480
- const { meta = {} } = block;
481
- const title = meta.title || '';
482
- const questions = Array.isArray(meta.questions) ? meta.questions : [];
483
- const answers = meta._submittedAnswers || {}; // optional: store last answers
484
-
485
- const container = document.createElement('div');
486
- container.className = 'griot-block griot-quiz';
487
-
488
- if (title) {
489
- const titleEl = document.createElement('h4');
490
- titleEl.className = 'griot-quiz__title';
491
- titleEl.textContent = title;
492
- container.appendChild(titleEl);
493
- }
494
-
495
- if (questions.length === 0) {
496
- const empty = document.createElement('p');
497
- empty.className = 'griot-quiz__empty';
498
- empty.textContent = 'No questions yet.';
499
- container.appendChild(empty);
500
- return container;
501
- }
502
-
503
- const form = document.createElement('form');
504
- form.className = 'griot-quiz__form';
505
-
506
- let totalScore = 0;
507
- let userScore = 0;
508
-
509
- questions.forEach((q, idx) => {
510
- const qid = q.id || `q${idx}`;
511
- const text = q.text || `Question ${idx + 1}`;
512
- const options = Array.isArray(q.options) ? q.options : [];
513
- const correctIdx = q.correctOption; // 0‑based index
514
- const explanation = q.explanation || '';
515
- const userChoice = answers[qid] !== undefined ? answers[qid] : null;
516
-
517
- const fieldset = document.createElement('fieldset');
518
- fieldset.className = 'griot-quiz__question';
519
- fieldset.dataset.index = idx;
520
-
521
- const legend = document.createElement('legend');
522
- legend.className = 'griot-quiz__question-text';
523
- legend.innerHTML = `<span class="griot-quiz__q-num">${idx + 1}.</span> ${escapeHtml(text)}`;
524
- fieldset.appendChild(legend);
525
-
526
- const optionsContainer = document.createElement('div');
527
- optionsContainer.className = 'griot-quiz__options';
528
-
529
- options.forEach((opt, optIdx) => {
530
- const label = document.createElement('label');
531
- label.className = 'griot-quiz__option';
532
-
533
- const radio = document.createElement('input');
534
- radio.type = 'radio';
535
- radio.name = `quiz_${block.id}_${qid}`;
536
- radio.value = optIdx;
537
- if (userChoice === optIdx) radio.checked = true;
538
- radio.addEventListener('change', () => {
539
- // Update stored answers in meta (optional – allows preserving after submit)
540
- const newAnswers = { ...(block.meta._submittedAnswers || {}), [qid]: optIdx };
541
- // We'll trigger an external callback later – for now just store in meta
542
- // But meta updates must go through the editor, not viewer. So we only calculate on‑the‑fly.
543
- // Instead, we call a user callback when the quiz is submitted.
544
- });
545
-
546
- const span = document.createElement('span');
547
- span.textContent = `${String.fromCharCode(65 + optIdx)}. ${escapeHtml(opt)}`;
548
-
549
- label.appendChild(radio);
550
- label.appendChild(span);
551
- optionsContainer.appendChild(label);
552
- });
553
-
554
- fieldset.appendChild(optionsContainer);
555
-
556
- // Show correct / wrong feedback after evaluation
557
- const feedback = document.createElement('div');
558
- feedback.className = 'griot-quiz__feedback';
559
- fieldset.appendChild(feedback);
560
-
561
- form.appendChild(fieldset);
562
- });
563
-
564
- const submitBtn = document.createElement('button');
565
- submitBtn.type = 'button';
566
- submitBtn.className = 'griot-quiz__submit';
567
- submitBtn.textContent = 'Check answers';
568
- submitBtn.addEventListener('click', () => {
569
- let score = 0;
570
- const newAnswers = {};
571
- questions.forEach((q, idx) => {
572
- const qid = q.id || `q${idx}`;
573
- const radios = form.querySelectorAll(`input[name="quiz_${block.id}_${qid}"]`);
574
- let selected = null;
575
- radios.forEach((r, i) => { if (r.checked) selected = i; });
576
- newAnswers[qid] = selected;
577
- const isCorrect = (selected !== null && selected === q.correctOption);
578
- if (isCorrect) score++;
579
-
580
- // Show feedback per question
581
- const feedbackDiv = form.querySelector(`fieldset[data-index="${idx}"] .griot-quiz__feedback`);
582
- if (feedbackDiv) {
583
- if (selected === null) {
584
- feedbackDiv.textContent = '❓ No answer selected.';
585
- feedbackDiv.className = 'griot-quiz__feedback griot-quiz__feedback--missing';
586
- } else if (isCorrect) {
587
- feedbackDiv.textContent = '✓ Correct!';
588
- feedbackDiv.className = 'griot-quiz__feedback griot-quiz__feedback--correct';
589
- } else {
590
- const correctAnswerText = q.options[q.correctOption];
591
- feedbackDiv.innerHTML = `✗ Incorrect. Correct answer: ${escapeHtml(correctAnswerText)}. ${escapeHtml(q.explanation || '')}`;
592
- feedbackDiv.className = 'griot-quiz__feedback griot-quiz__feedback--wrong';
593
- }
594
- if (q.explanation && selected !== null && !isCorrect) {
595
- // Already added above
596
- }
597
- }
598
- });
599
- totalScore = questions.length;
600
- userScore = score;
601
-
602
- // Display overall score
603
- const existingScore = container.querySelector('.griot-quiz__score');
604
- if (existingScore) existingScore.remove();
605
- const scoreDiv = document.createElement('div');
606
- scoreDiv.className = 'griot-quiz__score';
607
- scoreDiv.textContent = `You scored ${score} out of ${totalScore}.`;
608
- container.appendChild(scoreDiv);
609
-
610
- // Fire user callback if provided
611
- if (typeof opts.onQuizSubmit === 'function') {
612
- opts.onQuizSubmit(block.id, score, totalScore, newAnswers);
613
- }
614
- });
615
-
616
- form.appendChild(submitBtn);
617
- container.appendChild(form);
618
- return container;
619
- }
620
-
621
479
  // ─── Embed URL helpers ────────────────────────────────────────────────────────
622
480
 
623
481
  function _ytEmbed(src) {