@tinyweb_dev/oe-exam-sdk 0.1.32 → 0.2.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.
@@ -1,3 +1,3 @@
1
1
  import React from 'react';
2
2
  import type { MoversCrosswordPuzzleRendererProps } from '../../types';
3
- export declare function MoversCrosswordPuzzleRenderer({ partNumber, partName, questionCount, instruction, title, gridSize, clues, answers, correctAnswers, onAnswerChange, isReviewMode, caseSensitive, }: MoversCrosswordPuzzleRendererProps): React.JSX.Element;
3
+ export declare function MoversCrosswordPuzzleRenderer({ partNumber, partName, questionCount, instruction, title, gridSize, markedColumn, hiddenWord, clues, answers, correctAnswers, onAnswerChange, isReviewMode, caseSensitive, }: MoversCrosswordPuzzleRendererProps): React.JSX.Element;
@@ -4,7 +4,7 @@ import { useState, useMemo, useRef, useEffect } from 'react';
4
4
  import { Check, X } from 'lucide-react';
5
5
  import CambridgeYlePartBanner from '../../../../themes/cambridge-yle/CambridgeYlePartBanner';
6
6
  import CambridgeYleInstructionBanner from '../../../../themes/cambridge-yle/CambridgeYleInstructionBanner';
7
- export function MoversCrosswordPuzzleRenderer({ partNumber, partName, questionCount, instruction, title, gridSize, clues, answers = {}, correctAnswers = {}, onAnswerChange, isReviewMode = false, caseSensitive = false, }) {
7
+ export function MoversCrosswordPuzzleRenderer({ partNumber, partName, questionCount, instruction, title, gridSize, markedColumn, hiddenWord, clues, answers = {}, correctAnswers = {}, onAnswerChange, isReviewMode = false, caseSensitive = false, }) {
8
8
  const rows = gridSize?.rows || 12;
9
9
  const cols = gridSize?.cols || 12;
10
10
  const acrossClues = useMemo(() => clues?.across || [], [clues?.across]);
@@ -258,9 +258,31 @@ export function MoversCrosswordPuzzleRenderer({ partNumber, partName, questionCo
258
258
  const isSelected = selectedCell?.r === r && selectedCell?.c === c;
259
259
  const isWordActive = activeWordCells.some((cell) => cell.r === r && cell.c === c);
260
260
  const reviewStatus = getCellReviewStatus(r, c);
261
- const cellValue = answers[key] || '';
262
- let cellStyle = 'border-gray-400 bg-white text-gray-800';
263
- if (isReviewMode && reviewStatus) {
261
+ const isMarked = markedColumn && c === markedColumn;
262
+ const isExample = cellInfo.across?.isExample || cellInfo.down?.isExample;
263
+ // Example letter resolution
264
+ let exampleLetter = '';
265
+ if (isExample) {
266
+ if (cellInfo.across?.isExample && correctAnswers[`across-${cellInfo.across.number}`]) {
267
+ const word = correctAnswers[`across-${cellInfo.across.number}`];
268
+ exampleLetter = word[c - cellInfo.across.startCol] || '';
269
+ }
270
+ else if (cellInfo.down?.isExample && correctAnswers[`down-${cellInfo.down.number}`]) {
271
+ const word = correctAnswers[`down-${cellInfo.down.number}`];
272
+ exampleLetter = word[r - cellInfo.down.startRow] || '';
273
+ }
274
+ }
275
+ const cellValue = isExample ? exampleLetter : (answers[key] || '');
276
+ // Dynamic styles
277
+ let cellStyle = isMarked
278
+ ? 'border-gray-400 bg-gray-400 text-gray-950 shadow-sm ring-1 ring-gray-400/50'
279
+ : 'border-gray-300 bg-gray-100 text-gray-800';
280
+ if (isExample) {
281
+ cellStyle = isMarked
282
+ ? 'border-orange-400 bg-gray-400 text-orange-600 font-bold italic shadow-sm ring-1 ring-gray-400/50'
283
+ : 'border-gray-300 bg-gray-100 text-orange-600 font-bold italic';
284
+ }
285
+ else if (isReviewMode && reviewStatus) {
264
286
  if (reviewStatus.isCorrect) {
265
287
  cellStyle = 'border-green-500 bg-green-100 text-green-700 font-bold';
266
288
  }
@@ -269,17 +291,21 @@ export function MoversCrosswordPuzzleRenderer({ partNumber, partName, questionCo
269
291
  }
270
292
  }
271
293
  else if (isSelected) {
272
- cellStyle = 'border-blue-600 bg-blue-100 ring-2 ring-blue-500 text-blue-900 font-bold';
294
+ cellStyle = isMarked
295
+ ? 'border-blue-600 bg-blue-200 ring-2 ring-blue-600 text-blue-950 font-bold'
296
+ : 'border-blue-600 bg-blue-100 ring-2 ring-blue-500 text-blue-900 font-bold';
273
297
  }
274
298
  else if (isWordActive) {
275
- cellStyle = 'border-blue-400 bg-blue-50 text-blue-900';
299
+ cellStyle = isMarked
300
+ ? 'border-blue-500 bg-slate-300 text-blue-950 font-bold ring-1 ring-blue-400'
301
+ : 'border-blue-400 bg-blue-50 text-blue-900';
276
302
  }
277
303
  return (_jsxs("div", { onClick: () => handleCellClick(r, c), className: `relative flex items-center justify-center rounded-lg border-2 font-bold shadow-sm h-8 w-8 sm:h-10 sm:w-10 md:h-11 md:w-11 text-base sm:text-lg transition-all select-none cursor-pointer ${cellStyle}`, children: [clueNum && (_jsx("span", { className: "absolute top-0.5 left-1 text-[9px] sm:text-[10px] font-bold text-gray-500 leading-none", children: clueNum })), !isReviewMode ? (_jsx("input", { ref: (el) => {
278
304
  if (el)
279
305
  inputRefs.current.set(key, el);
280
306
  else
281
307
  inputRefs.current.delete(key);
282
- }, type: "text", maxLength: 1, value: cellValue, onChange: (e) => handleInputChange(e.target.value, r, c), onKeyDown: (e) => handleKeyDown(e, r, c), onFocus: () => handleCellClick(r, c), className: "w-full h-full text-center bg-transparent uppercase font-bold outline-none cursor-pointer" })) : (_jsxs("div", { className: "flex flex-col items-center justify-center", children: [_jsx("span", { children: cellValue || '—' }), reviewStatus && !reviewStatus.isCorrect && (_jsx("span", { className: "absolute -bottom-1 -right-1 text-[9px] bg-green-600 text-white font-bold px-1 rounded-full shadow", children: reviewStatus.expected }))] })), isReviewMode && reviewStatus && (_jsx("span", { className: `absolute -top-1 -right-1 rounded-full p-0.5 text-white ${reviewStatus.isCorrect ? 'bg-green-500' : 'bg-red-500'}`, children: reviewStatus.isCorrect ? (_jsx(Check, { className: "h-2.5 w-2.5" })) : (_jsx(X, { className: "h-2.5 w-2.5" })) }))] }, key));
308
+ }, type: "text", maxLength: 1, disabled: Boolean(isExample), value: cellValue, onChange: (e) => handleInputChange(e.target.value, r, c), onKeyDown: (e) => handleKeyDown(e, r, c), onFocus: () => handleCellClick(r, c), className: `w-full h-full text-center bg-transparent uppercase font-bold outline-none ${isExample ? 'cursor-default' : 'cursor-pointer'}` })) : (_jsxs("div", { className: "flex flex-col items-center justify-center", children: [_jsx("span", { children: cellValue || '—' }), reviewStatus && !reviewStatus.isCorrect && (_jsx("span", { className: "absolute -bottom-1 -right-1 text-[9px] bg-green-600 text-white font-bold px-1 rounded-full shadow", children: reviewStatus.expected }))] })), isReviewMode && reviewStatus && (_jsx("span", { className: `absolute -top-1 -right-1 rounded-full p-0.5 text-white ${reviewStatus.isCorrect ? 'bg-green-500' : 'bg-red-500'}`, children: reviewStatus.isCorrect ? (_jsx(Check, { className: "h-2.5 w-2.5" })) : (_jsx(X, { className: "h-2.5 w-2.5" })) }))] }, key));
283
309
  });
284
310
  }) }) })] })] })] }));
285
311
  }
@@ -50,20 +50,35 @@ export function CrosswordPuzzleClient({ content, correctAnswer, isReviewMode = f
50
50
  if (!cellInfo) {
51
51
  return (_jsx("div", { className: "h-8 w-8 sm:h-9 sm:w-9 md:h-10 md:w-10 bg-transparent" }, key));
52
52
  }
53
+ const isMarked = content?.markedColumn && c === content.markedColumn;
54
+ const isExample = Boolean(cellInfo.across?.isExample || cellInfo.down?.isExample);
55
+ // If in review mode or cell is an example, display correct answer letter
53
56
  let previewLetter = '';
54
- if (correctAnswer?.answers) {
55
- if (cellInfo.across) {
57
+ if (isReviewMode || isExample) {
58
+ if (cellInfo.across && correctAnswer?.answers) {
56
59
  const word = correctAnswer.answers[`across-${cellInfo.across.number}`] || '';
57
60
  const offset = c - cellInfo.across.startCol;
58
61
  previewLetter = word[offset] || '';
59
62
  }
60
- else if (cellInfo.down) {
63
+ else if (cellInfo.down && correctAnswer?.answers) {
61
64
  const word = correctAnswer.answers[`down-${cellInfo.down.number}`] || '';
62
65
  const offset = r - cellInfo.down.startRow;
63
66
  previewLetter = word[offset] || '';
64
67
  }
65
68
  }
66
- return (_jsxs("div", { className: "relative flex items-center justify-center rounded border-2 border-gray-400 bg-white font-bold text-gray-800 shadow-sm h-8 w-8 sm:h-9 sm:w-9 md:h-10 md:w-10 text-sm sm:text-base md:text-lg", children: [clueNum && (_jsx("span", { className: "absolute top-0.5 left-1 text-[9px] font-bold text-gray-500 leading-none", children: clueNum })), _jsx("span", { children: previewLetter })] }, key));
69
+ else if (userAnswers?.[key]) {
70
+ previewLetter = userAnswers[key];
71
+ }
72
+ let cellBg = isMarked ? 'bg-gray-400 border-gray-400 shadow-sm ring-1 ring-gray-400/50' : 'bg-gray-100 border-gray-300';
73
+ let textColor = isExample
74
+ ? 'text-orange-600 font-bold italic'
75
+ : isMarked
76
+ ? 'text-gray-950 font-bold'
77
+ : 'text-gray-800 font-bold';
78
+ if (isReviewMode && previewLetter && !isExample) {
79
+ textColor = 'text-green-700 font-extrabold';
80
+ }
81
+ return (_jsxs("div", { className: `relative flex items-center justify-center rounded border-2 font-bold shadow-sm h-8 w-8 sm:h-9 sm:w-9 md:h-10 md:w-10 text-sm sm:text-base md:text-lg ${cellBg} ${textColor}`, children: [clueNum && (_jsx("span", { className: "absolute top-0.5 left-1 text-[9px] font-bold text-gray-500 leading-none", children: clueNum })), _jsx("span", { children: previewLetter })] }, key));
67
82
  });
68
83
  }) }) })] })] }));
69
84
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinyweb_dev/oe-exam-sdk",
3
- "version": "0.1.32",
3
+ "version": "0.2.1",
4
4
  "description": "Reusable OceanEdu question components.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",