@tinyweb_dev/oe-exam-sdk 0.1.23 → 0.1.26
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 +4 -5
- package/dist/components/exams/take/components/question-renderers/MoversWordFillStructuredFormRenderer.js +1 -1
- package/dist/components/exams/take/utils/question-transformers.d.ts +3 -1
- package/dist/components/exams/take/utils/question-transformers.js +1 -1
- package/dist/components/questions/_shared/types/word-fill-structured-form.type.d.ts +18 -9
- package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerClient.js +1 -1
- package/dist/components/questions/types/choose-the-correct-answer/transform.js +1 -1
- package/dist/components/questions/types/word-fill-structured-form/WfsfWordBankEditor.d.ts +14 -0
- package/dist/components/questions/types/word-fill-structured-form/WfsfWordBankEditor.js +1 -0
- package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.d.ts +1 -1
- package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.js +1 -1
- package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.d.ts +1 -1
- package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormCreator.js +1 -1
- package/dist/components/questions/types/word-fill-structured-form/register.js +1 -1
- package/dist/components/questions/types/word-fill-structured-form/transform.d.ts +5 -2
- package/dist/components/questions/types/word-fill-structured-form/transform.js +1 -1
- package/dist/components/questions/types/word-fill-structured-form/wfsf-word-bank.utils.d.ts +24 -0
- package/dist/components/questions/types/word-fill-structured-form/wfsf-word-bank.utils.js +1 -0
- package/dist/components/themes/english-certification/EcWordFillStructuredForm.js +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +1 -1
- package/dist/shared/lib/i18n/messages/en/admin.d.ts +0 -3
- package/dist/shared/lib/i18n/messages/en/admin.js +1 -1
- package/dist/shared/lib/i18n/messages/en.d.ts +0 -3
- package/dist/shared/lib/i18n/messages/vi/admin.d.ts +0 -3
- package/dist/shared/lib/i18n/messages/vi/admin.js +1 -1
- package/dist/shared/lib/i18n/messages/vi.d.ts +0 -3
- package/package.json +169 -163
- package/dist/mcp/config.d.ts +0 -12
- package/dist/mcp/config.js +0 -1
- package/dist/mcp/http-client.d.ts +0 -6
- package/dist/mcp/http-client.js +0 -1
- package/dist/mcp/index.d.ts +0 -6
- package/dist/mcp/index.js +0 -2
- package/dist/mcp/tools/_helpers.d.ts +0 -4
- package/dist/mcp/tools/_helpers.js +0 -1
- package/dist/mcp/tools/exams.d.ts +0 -2
- package/dist/mcp/tools/exams.js +0 -1
- package/dist/mcp/tools/index.d.ts +0 -2
- package/dist/mcp/tools/index.js +0 -1
- package/dist/mcp/tools/results.d.ts +0 -2
- package/dist/mcp/tools/results.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
export const transformWordFillStructuredForm=e=>{const
|
|
1
|
+
export const transformWordFillStructuredForm=e=>{const r=e.answer;if(!r?.content||!r?.answers)return{apiContent:{},apiCorrectAnswer:{}};const t=!!(r.groupTitle||r.groupSubtitle||r.groupContent||r.groupImageUrl),n={title:r.title||"",imageUrl:r.imageUrl||"",content:r.content};r.blankStyle&&(n.blankStyle=r.blankStyle),r.viewMode&&(n.viewMode=r.viewMode),Array.isArray(r.wordBank)&&r.wordBank.length>0&&(n.wordBank=r.wordBank),"letter"!==r.blankStyle&&"word"!==r.blankStyle&&"phrase"!==r.blankStyle||(n.blankStyle=r.blankStyle),"WITH_OPTIONS"!==r.viewMode&&"WITH_WORD_BANK"!==r.viewMode||(n.viewMode=r.viewMode),Array.isArray(r.wordBank)&&(n.wordBank=r.wordBank);return{apiContent:n,apiCorrectAnswer:{answers:r.answers,caseSensitive:r.caseSensitive??!1},basicGroupData:t?{title:r.groupTitle||"",subtitle:r.groupSubtitle||"",content:r.groupContent||"",imageUrl:r.groupImageUrl||""}:void 0,groupNumber:r.groupNumber||1}};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { WfsfOptionsWordBankEntry, WfsfSharedWordBankEntry, WfsfViewMode, WfsfWordBankEntry } from '../../_shared/types/word-fill-structured-form.type';
|
|
2
|
+
export type WfsfBankMode = 'FREE_TYPE' | WfsfViewMode;
|
|
3
|
+
export declare function isSharedWordEntry(entry: unknown): entry is WfsfSharedWordBankEntry;
|
|
4
|
+
export declare function isOptionsWordEntry(entry: unknown): entry is {
|
|
5
|
+
options: string[];
|
|
6
|
+
};
|
|
7
|
+
/** Detect mode from explicit viewMode and/or wordBank shape. */
|
|
8
|
+
export declare function detectWfsfBankMode(viewMode: unknown, wordBank: unknown): WfsfBankMode;
|
|
9
|
+
export declare function normalizeSharedWordBank(wordBank: unknown): WfsfSharedWordBankEntry[];
|
|
10
|
+
/**
|
|
11
|
+
* Align options bank length to blank count (numeric keys preferred).
|
|
12
|
+
* Non-numeric blank keys still get sequential slots by sorted order.
|
|
13
|
+
*/
|
|
14
|
+
export declare function normalizeOptionsWordBank(wordBank: unknown, blankKeys: string[]): WfsfOptionsWordBankEntry[];
|
|
15
|
+
export declare function emptyOptionsBank(blankCount: number): WfsfOptionsWordBankEntry[];
|
|
16
|
+
export declare function emptySharedBank(): WfsfSharedWordBankEntry[];
|
|
17
|
+
/**
|
|
18
|
+
* Payload slice for save / onChange.
|
|
19
|
+
* FREE_TYPE sets viewMode: null so host can clear preserved bank fields.
|
|
20
|
+
*/
|
|
21
|
+
export declare function bankPayloadForMode(mode: WfsfBankMode, sharedBank: WfsfSharedWordBankEntry[], optionsBank: WfsfOptionsWordBankEntry[]): {
|
|
22
|
+
viewMode: WfsfViewMode | null;
|
|
23
|
+
wordBank?: WfsfWordBankEntry[];
|
|
24
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function isSharedWordEntry(r){return!!r&&"object"==typeof r&&!Array.isArray(r)&&"word"in r&&!("options"in r)}export function isOptionsWordEntry(r){return!!r&&"object"==typeof r&&!Array.isArray(r)&&Array.isArray(r.options)}export function detectWfsfBankMode(r,n){if("WITH_OPTIONS"===r)return"WITH_OPTIONS";if("WITH_WORD_BANK"===r)return"WITH_WORD_BANK";if(!Array.isArray(n)||0===n.length)return"FREE_TYPE";const t=n.find(r=>null!=r);return isOptionsWordEntry(t)?"WITH_OPTIONS":isSharedWordEntry(t)?"WITH_WORD_BANK":n.some(r=>isOptionsWordEntry(r))?"WITH_OPTIONS":"FREE_TYPE"}export function normalizeSharedWordBank(r){return Array.isArray(r)?r.filter(isSharedWordEntry).map(r=>({word:String(r.word??""),...r.isExample?{isExample:!0}:{}})):[]}export function normalizeOptionsWordBank(r,n){const t=Array.isArray(r)?r:[],o=n.length,e=[];for(let r=0;r<o;r+=1){const o=n[r],i=parseInt(o,10),a=t[Number.isNaN(i)?r:i]??t[r]??null;null!=a?isOptionsWordEntry(a)&&a.options.length>=1?e.push({options:a.options.map(r=>String(r??""))}):e.push(null):e.push(null)}return e}export function emptyOptionsBank(r){return Array.from({length:r},()=>({options:["",""]}))}export function emptySharedBank(){return[{word:""}]}export function bankPayloadForMode(r,n,t){if("WITH_WORD_BANK"===r){return{viewMode:"WITH_WORD_BANK",wordBank:n.map(r=>({word:r.word.trim(),...r.isExample?{isExample:!0}:{}})).filter(r=>r.word.length>0)}}if("WITH_OPTIONS"===r){return{viewMode:"WITH_OPTIONS",wordBank:t.map(r=>{if(null==r)return null;const n=r.options.map(r=>r.trim()).filter(Boolean);return n.length<2?null:{options:n}})}}return{viewMode:null}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useRef as r,useEffect as n,useMemo as s,useCallback as o,memo as l}from"react";import{ResolvedImage as a}from"../../../components/common/ResolvedImage";import{cn as i}from"../../../shared/lib/utils";import{transformWordFillStructuredForm as d}from"../../../components/exams/take/exam-taking.utils";import{englishCertQuestionDomId as c}from"./english-cert-scroll";function b(e){const t=Number(e);return Number.isFinite(t)?String(t+1):e}function
|
|
1
|
+
"use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useRef as r,useEffect as n,useMemo as s,useCallback as o,memo as l}from"react";import{ResolvedImage as a}from"../../../components/common/ResolvedImage";import{cn as i}from"../../../shared/lib/utils";import{transformWordFillStructuredForm as d}from"../../../components/exams/take/exam-taking.utils";import{englishCertQuestionDomId as c}from"./english-cert-scroll";function b(e){const t=Number(e);return Number.isFinite(t)?String(t+1):e}function m(e,t){const r=e.trim();return t?r:r.toLowerCase()}function u(e,t){const r=Object.keys(e).map(e=>Number(e)).filter(e=>Number.isFinite(e)).sort((e,t)=>e-t);if(0===r.length)return`Question ${t}`;const n=r[0]+1,s=r[r.length-1]+1;return n===s?`Question ${n}`:`Questions ${n}–${s}`}const p={},f=l(function({question:o,initialAnswers:l,onBlankChange:d,isReviewMode:c}){const u=r(null),p=r(d);p.current=d;const f=r(!1),x=r(l),h=s(()=>o.content.replace(/\{([\w\d]+)\}/g,(e,t)=>`\n <span class="ec-blank-wrapper" data-blank-wrapper="${t}">\n <span class="ec-blank-number" data-blank-number="${t}">${b(t)}</span>\n <input type="text" data-blank-key="${t}" class="ec-blank-input" />\n </span>\n `),[o.content]);return n(()=>{const e=u.current;if(!e)return;f.current||(e.innerHTML=h,f.current=!0);const t=e.querySelectorAll("input.ec-blank-input"),r=[];return t.forEach(t=>{const n=t.getAttribute("data-blank-key")||"",s=e.querySelector(`[data-blank-wrapper="${n}"]`),l=x.current[n]||"",a=o.answers[n]||"",d=l.trim().length>0,u=d&&m(l,o.caseSensitive)===m(a,o.caseSensitive),f=c&&!u&&a.trim().length>0;t.value=f?`${d?l:"(empty)"} → ${a}`:l,t.disabled=c;const h=o.blankStyle||"word",g="letter"===h,w="phrase"===h;g&&(t.maxLength=Math.max(1,(a||" ").trim().length||1)),t.className=i("ec-blank-input inline-block bg-blue-50/30 text-base font-semibold leading-tight text-[#0f1730] align-baseline outline-none transition-all hover:bg-blue-50/60 focus:bg-blue-50/80",g?"h-8 w-8 rounded border-2 border-[#1167e8] px-0 text-center uppercase":w?"min-w-[9rem] max-w-[18rem] w-[14ch] rounded-t border-0 border-b-2 border-dashed border-[#1167e8] px-2 py-0.5 text-center focus:border-solid focus:border-[#0b57d0]":"min-w-[4.5rem] max-w-[7.5rem] w-[8ch] rounded-t border-0 border-b-2 border-dashed border-[#1167e8] px-1 py-0.5 text-center focus:border-solid focus:border-[#0b57d0]",c?u?"border-solid border-[#22c55e] bg-emerald-50 text-[#15803d]":d?"border-solid border-[#ef4444] bg-rose-50 text-red-700":"border-solid border-[#f97316] bg-amber-50 text-[#c2410c]":""),g||(t.size=w?18:10),g&&(t.style.display="inline-block",t.style.width="1.75rem",t.style.height="1.75rem",t.style.minWidth="1.75rem",t.style.maxWidth="1.75rem",t.style.padding="0",t.style.margin="0 2px",t.style.borderWidth="2px",t.style.borderStyle="solid",t.style.borderRadius="4px",t.style.textAlign="center",t.style.fontWeight="700",t.style.textTransform="uppercase",t.style.boxSizing="border-box");const y=e.querySelector(`[data-blank-number="${n}"]`);y&&(y.textContent=b(n),y.className=i("ec-blank-number mr-1 inline-flex h-5 min-w-5 items-center justify-center rounded-full px-1.5 text-[11px] font-bold leading-none text-white align-baseline shadow-xs",c?u?"bg-[#22c55e]":d?"bg-[#ef4444]":"bg-[#f97316]":"bg-[#0b57d0]")),s&&(s.className=i("ec-blank-wrapper inline-flex items-baseline whitespace-nowrap align-baseline",c?"mx-1":"mx-0.5"));const k=e=>{const t=e.target;p.current(n,t.value)};t.addEventListener("input",k),r.push({el:t,handler:k})}),()=>{r.forEach(({el:e,handler:t})=>{e.removeEventListener("input",t)})}},[h,c]),t("div",{className:"space-y-3",children:[o.title&&e("h3",{className:"text-base font-semibold text-[#0f1730]",children:o.title}),o.imageUrl&&e("div",{className:"flex justify-center",children:e("div",{className:"overflow-hidden rounded-lg border border-[#d9e4f2]",children:e(a,{src:o.imageUrl,alt:o.title||"Question image",className:"max-h-56 w-auto object-contain"})})}),e("div",{ref:u,className:"ec-structured-content w-full overflow-x-auto rounded-xl border border-[#d9e4f2] bg-[#f4f9ff] p-5 text-base leading-relaxed text-[#0f1730] [&_table]:w-full [&_table]:border-collapse [&_td]:border [&_td]:border-[#d9e4f2] [&_td]:px-4 [&_td]:py-3 [&_td]:align-top [&_th]:border [&_th]:border-[#d9e4f2] [&_th]:bg-[#e9f3ff] [&_th]:px-4 [&_th]:py-3 [&_th]:text-left [&_th]:font-semibold"}),c&&Object.keys(o.answers).length>0&&t("div",{className:"rounded-xl border border-[#d9e4f2] bg-white/70 p-3",children:[e("span",{className:"text-[10px] font-semibold uppercase tracking-wider text-[#64748b]",children:"Correct answers"}),e("div",{className:"mt-1 flex flex-wrap gap-1.5",children:Object.entries(o.answers).map(([e,r])=>t("span",{className:"rounded border border-[#b9edc8] bg-[#ddf8e7] px-2 py-0.5 text-xs font-semibold text-[#15803d]",children:[e,": ",r]},e))})]})]})});export function EcWordFillStructuredForm({part:n,answers:l,onAnswerChange:i,isReviewMode:b=!1}){const{questions:m,instruction:x,groupTitle:h,groupContent:g,groupImageUrl:w}=s(()=>d(n.questions),[n.questions]),y=r(l);y.current=l;const k=r(i);k.current=i;const N=o((e,t,r)=>{const n=y.current[e]||{};k.current(e,{...n,[t]:r})},[]),v=s(()=>{const e={};return m.forEach(t=>{e[t.id]=(e,r)=>N(t.id,e,r)}),e},[m,N]);return t("div",{className:"flex flex-col gap-4",children:[x&&e("div",{className:"rounded-xl border border-[#d9e4f2] bg-[#e9f3ff] px-4 py-2.5 text-sm font-semibold uppercase tracking-wide text-[#0b57d0]",children:x}),h&&e("h2",{className:"text-center text-lg font-bold uppercase text-[#0b57d0]",children:h}),w&&e("div",{className:"flex items-center justify-center",children:e(a,{src:w,alt:h||"Group image",className:"max-h-[300px] rounded-lg object-contain shadow-md"})}),e("div",{className:"flex flex-col gap-4",children:m.map(r=>t("div",{id:c(r.id),className:"scroll-mt-24 rounded-2xl border border-[#d9e4f2] bg-white/90 p-4 shadow-[0_14px_35px_rgba(13,71,161,0.10)] backdrop-blur-md",children:[e("div",{className:"mb-2 flex items-center gap-2",children:e("span",{className:"inline-flex items-center rounded-full bg-gradient-to-b from-[#1f7cff] to-[#0b57d0] px-3 py-1 text-xs font-bold text-white shadow-sm",children:u(r.answers,r.questionNumber)})}),e(f,{question:r,initialAnswers:l[r.id]||p,onBlankChange:v[r.id],isReviewMode:b})]},r.id))})]})}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export*as Api from"./api";export*as Components from"./components";export*as
|
|
1
|
+
export*as Api from"./api";export*as Components from"./components";export*as Exams from"./components/exams";export*as Questions from"./components/questions";export*as Results from"./components/results";export*as Themes from"./components/themes";export*as Shared from"./shared";export{buildExamTemplatePayload,createContestRoomsApi,createExamCreateApi,createExamEntryApi,createExamQuestionsApi,createExamQuestionsFetchApi,createExamTakingApi,createMockContestRoomsApi,createMockCreateExamApi,createMockExamEntryApi,createMockExamQuestionsApi,createMockExamTakingApi,createMockResultReviewApi,createResultReviewApi}from"./api";export{CreateExamPageContainer,ExamPreviewDialog,ExamQuestionsPageContainer,ExamTakingPageContainer,ExamViewDialog,StudentContestRoomsPageContainer,StudentExamEntryPageContainer}from"./components/exams";export{ResultReviewPageContainer}from"./components/results";export{QuestionCreator}from"./components/questions/creator/QuestionCreator";export{QuestionGroupCreator}from"./components/questions/creator/QuestionGroupCreator";export{DifficultyLevel,EditQuestionBankDialog,QuestionBankEditorType,QuestionEditorRenderer}from"./components/questions/question-bank";export{renderDedicatedComponent}from"./components/questions/creator/dedicated-component-router";export{questionTypeRegistry}from"./components/questions/creator/question-type-registry";export{QUESTION_TYPE_CONFIG,QUESTION_TYPES_WITH_DEDICATED_COMPONENTS}from"./components/questions/_shared/config/question-types.config";export{validateQuestion}from"./components/questions/_shared/utils/question-validation";export{buildAnswerPayload}from"./components/questions/_shared/utils/answer-builder";export*from"./components/questions/_shared/types";
|
|
@@ -1393,9 +1393,6 @@ declare const admin: {
|
|
|
1393
1393
|
readonly 'admin.exams.shuffle.info3': "Questions within the same Part are randomly shuffled";
|
|
1394
1394
|
readonly 'admin.exams.shuffle.info4': "Variants are linked to the parent exam for management";
|
|
1395
1395
|
readonly 'admin.exams.shuffle.countLabel': "Number of variants to create";
|
|
1396
|
-
readonly 'admin.exams.shuffle.strategyLabel': "Existing exam handling option";
|
|
1397
|
-
readonly 'admin.exams.shuffle.keepOld': "Keep existing exams and add new ones";
|
|
1398
|
-
readonly 'admin.exams.shuffle.replaceAll': "Create a completely new set";
|
|
1399
1396
|
readonly 'admin.exams.shuffle.existingVariants': "Existing exams ({count})";
|
|
1400
1397
|
readonly 'admin.exams.shuffle.deleteAll': "Delete all ({count})";
|
|
1401
1398
|
readonly 'admin.exams.shuffle.loading': "Loading...";
|