@pie-element/simple-cloze 0.1.3 → 0.1.4-next.0
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/configure.js +2 -0
- package/controller.js +1 -0
- package/dist/author/index.d.ts +0 -1
- package/dist/author/index.js +14813 -20641
- package/dist/author/index.js.map +1 -1
- package/dist/controller/defaults.d.ts +0 -1
- package/dist/controller/index.d.ts +0 -1
- package/dist/controller/index.js +4 -4
- package/dist/controller/index.js.map +1 -1
- package/dist/delivery/index.d.ts +6 -1
- package/dist/delivery/index.js +577 -357
- package/dist/delivery/index.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.iife.d.ts +0 -1
- package/dist/index.iife.js +3 -3
- package/dist/index.js +577 -357
- package/dist/index.js.map +1 -1
- package/dist/print/index.d.ts +0 -1
- package/dist/print/index.js +471 -314
- package/dist/print/index.js.map +1 -1
- package/dist/runtime-support.d.ts +12 -0
- package/dist/runtime-support.js +14 -0
- package/dist/runtime-support.js.map +1 -0
- package/package.json +21 -18
- package/dist/author/index.d.ts.map +0 -1
- package/dist/controller/defaults.d.ts.map +0 -1
- package/dist/controller/index.d.ts.map +0 -1
- package/dist/delivery/index.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.iife.d.ts.map +0 -1
- package/dist/print/index.d.ts.map +0 -1
- package/src/author/Author.svelte +0 -102
- package/src/author/index.ts +0 -28
- package/src/controller/defaults.ts +0 -13
- package/src/controller/index.ts +0 -98
- package/src/delivery/SimpleCloze.svelte +0 -171
- package/src/delivery/index.ts +0 -37
- package/src/index.iife.ts +0 -7
- package/src/index.ts +0 -1
- package/src/print/Print.svelte +0 -49
- package/src/print/index.ts +0 -18
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/runtime-support.ts
|
|
2
|
+
var e = {
|
|
3
|
+
schemaVersion: 1,
|
|
4
|
+
packageName: "@pie-element/simple-cloze",
|
|
5
|
+
supports: { esm: {
|
|
6
|
+
delivery: !1,
|
|
7
|
+
author: !1,
|
|
8
|
+
print: !1
|
|
9
|
+
} }
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
export { e as default, e as runtimeSupport };
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=runtime-support.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-support.js","names":[],"sources":["../src/runtime-support.ts"],"sourcesContent":["export const runtimeSupport = {\n schemaVersion: 1,\n packageName: '@pie-element/simple-cloze',\n supports: {\n esm: {\n delivery: false,\n author: false,\n print: false,\n },\n },\n};\n\nexport default runtimeSupport;\n"],"mappings":";AAAA,IAAa,IAAiB;CAC5B,eAAe;CACf,aAAa;CACb,UAAU,EACR,KAAK;EACH,UAAU;EACV,QAAQ;EACR,OAAO;CACT,EACF;AACF"}
|
package/package.json
CHANGED
|
@@ -1,65 +1,68 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pie-element/simple-cloze",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4-next.0",
|
|
4
4
|
"description": "Simple cloze (text entry) demo/template PIE element built with Svelte 5",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"pie": {
|
|
9
|
-
"controller": "@pie-element/simple-cloze"
|
|
9
|
+
"controller": "@pie-element/simple-cloze/controller",
|
|
10
|
+
"configure": "@pie-element/simple-cloze/configure"
|
|
10
11
|
},
|
|
11
12
|
"exports": {
|
|
12
13
|
".": {
|
|
13
|
-
"development": "./src/index.ts",
|
|
14
14
|
"types": "./dist/index.d.ts",
|
|
15
15
|
"default": "./dist/index.js"
|
|
16
16
|
},
|
|
17
17
|
"./delivery": {
|
|
18
|
-
"development": "./src/delivery/index.ts",
|
|
19
18
|
"types": "./dist/delivery/index.d.ts",
|
|
20
19
|
"default": "./dist/delivery/index.js"
|
|
21
20
|
},
|
|
22
21
|
"./controller": {
|
|
23
|
-
"
|
|
22
|
+
"types": "./dist/controller/index.d.ts",
|
|
23
|
+
"default": "./dist/controller/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./controller.js": {
|
|
24
26
|
"types": "./dist/controller/index.d.ts",
|
|
25
27
|
"default": "./dist/controller/index.js"
|
|
26
28
|
},
|
|
27
29
|
"./author": {
|
|
28
|
-
"
|
|
30
|
+
"types": "./dist/author/index.d.ts",
|
|
31
|
+
"default": "./dist/author/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./configure": {
|
|
29
34
|
"types": "./dist/author/index.d.ts",
|
|
30
35
|
"default": "./dist/author/index.js"
|
|
31
36
|
},
|
|
32
37
|
"./print": {
|
|
33
|
-
"development": "./src/print/index.ts",
|
|
34
38
|
"types": "./dist/print/index.d.ts",
|
|
35
39
|
"default": "./dist/print/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./runtime-support": {
|
|
42
|
+
"types": "./dist/runtime-support.d.ts",
|
|
43
|
+
"default": "./dist/runtime-support.js"
|
|
36
44
|
}
|
|
37
45
|
},
|
|
38
46
|
"files": [
|
|
39
|
-
"
|
|
40
|
-
"
|
|
47
|
+
"configure.js",
|
|
48
|
+
"controller.js",
|
|
49
|
+
"dist"
|
|
41
50
|
],
|
|
42
51
|
"sideEffects": false,
|
|
43
52
|
"scripts": {
|
|
44
|
-
"build": "vite build && vite build --config vite.delivery.config.ts && vite build --config vite.controller.config.ts && vite build --config vite.author.config.ts && vite build --config vite.print.config.ts && vite build --config vite.config.iife.ts && tsc --emitDeclarationOnly",
|
|
53
|
+
"build": "vite build && vite build --config vite.delivery.config.ts && vite build --config vite.controller.config.ts && vite build --config vite.author.config.ts && vite build --config vite.print.config.ts && vite build --config vite.runtime-support.config.ts && vite build --config vite.config.iife.ts && tsc --emitDeclarationOnly",
|
|
45
54
|
"dev": "vite",
|
|
46
55
|
"demo": "vite --mode demo",
|
|
47
56
|
"clean": "rm -rf dist tsconfig.tsbuildinfo"
|
|
48
57
|
},
|
|
49
|
-
"
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@pie-lib/delivery-events-svelte": "0.1.0",
|
|
50
60
|
"@pie-lib/editable-html-tiptap-svelte": "0.1.2",
|
|
51
61
|
"@pie-lib/styling-svelte": "0.1.2",
|
|
52
|
-
"lodash-es": "^4.17.21"
|
|
53
|
-
},
|
|
54
|
-
"peerDependencies": {
|
|
55
|
-
"svelte": "^5.0.0"
|
|
56
|
-
},
|
|
57
|
-
"devDependencies": {
|
|
58
62
|
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
|
59
63
|
"@tiptap/core": "^3.19.0",
|
|
60
64
|
"@tiptap/pm": "^3.19.0",
|
|
61
65
|
"@tiptap/starter-kit": "^3.19.0",
|
|
62
|
-
"@types/lodash-es": "^4.17.12",
|
|
63
66
|
"svelte": "^5.54.0",
|
|
64
67
|
"typescript": "^5.9.3",
|
|
65
68
|
"vite": "^8.0.1"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/author/index.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,kBAAkB,KAAmC,CAAC;AAE5D,cAAM,iBAAkB,SAAQ,kBAAkB;IAChD,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,SAAS,CAAuC;IAExD,IAAI,KAAK,CAAC,CAAC,EAAE,GAAG,EAGf;IAED,IAAI,KAAK,IALI,GAAG,CAOf;IAED,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,EAGpC;IAED,IAAI,QAAQ,IALK,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAOpC;CACF;AAED,eAAe,iBAAiB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/controller/defaults.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,wBAYE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/controller/index.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,cAAc,GAAI,UAAU,GAAG,EAAE,SAAS,GAAG,2CAczD,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,WAAW,GAAG,EAAE,SAAS,GAAG,UAM3D,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,UAAU,GAAG,EAAE,SAAS,GAAG,EAAE,KAAK,GAAG,qBAgBzD,CAAC;AAEL,eAAO,MAAM,kBAAkB,GAAI,QAAO,GAAQ,QAAsC,CAAC;AAEzF,eAAO,MAAM,gBAAgB,GAAI,GAAG,GAAG,QAAe,CAAC;AAEvD,eAAO,MAAM,KAAK,GAAI,UAAU,GAAG,EAAE,SAAS,GAAG,EAAE,KAAK,GAAG,qBA4B1D,CAAC;AAEF,eAAO,MAAM,4BAA4B,GAAI,UAAU,GAAG,EAAE,KAAK,GAAG,qBAQnE,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,QAAO,GAAQ,EAAE,UAAS,GAAQ,QAQ1D,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/delivery/index.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,kBAAkB,KAAwC,CAAC;AAGjE,cAAM,kBAAmB,SAAQ,kBAAkB;IACjD,gBAAgB,EAAE,GAAG,CAAQ;IAG7B,IAAI,OAAO,CAAC,CAAC,EAAE,GAAG,EAIjB;IAGD,IAAI,OAAO,IAPI,GAAG,CASjB;IAGD,eAAe,GAAI,gBAAgB,GAAG,UAEpC;IAEF,iBAAiB;CAKlB;AAID,eAAe,kBAAkB,CAAC"}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/index.iife.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.iife.d.ts","sourceRoot":"","sources":["../src/index.iife.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,OAAO,MAAM,YAAY,CAAC;AAEjC,eAAe,OAAO,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/print/index.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,kBAAkB,KAAkC,CAAC;AAE3D,cAAM,gBAAiB,SAAQ,kBAAkB;IAC/C,OAAO,CAAC,MAAM,CAAa;IAE3B,IAAI,KAAK,CAAC,CAAC,EAAE,GAAG,EAGf;IAED,IAAI,KAAK,IALI,GAAG,CAOf;CACF;AAED,eAAe,gBAAgB,CAAC"}
|
package/src/author/Author.svelte
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
<svelte:options
|
|
2
|
-
customElement={{
|
|
3
|
-
shadow: 'none',
|
|
4
|
-
props: {
|
|
5
|
-
model: { type: 'Object' }
|
|
6
|
-
}
|
|
7
|
-
}}
|
|
8
|
-
/>
|
|
9
|
-
|
|
10
|
-
<script lang="ts">
|
|
11
|
-
import { EditableHtml } from '@pie-lib/editable-html-tiptap-svelte';
|
|
12
|
-
import { createEventDispatcher } from 'svelte';
|
|
13
|
-
|
|
14
|
-
const dispatch = createEventDispatcher();
|
|
15
|
-
|
|
16
|
-
let { model = $bindable(), onChange }: { model?: any; onChange?: (model: any) => void } = $props();
|
|
17
|
-
|
|
18
|
-
function emitModelUpdate(nextModel: any) {
|
|
19
|
-
// Match the expected contract used by AuthorView:
|
|
20
|
-
// detail contains { update, reset }
|
|
21
|
-
dispatch('model.updated', { update: nextModel, reset: false });
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function handlePromptChange(html: string) {
|
|
25
|
-
if (onChange && model) {
|
|
26
|
-
onChange({ ...model, prompt: html });
|
|
27
|
-
}
|
|
28
|
-
if (model) {
|
|
29
|
-
emitModelUpdate({ ...model, prompt: html });
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function handleAnswerChange(e: Event) {
|
|
34
|
-
const target = e.target as HTMLInputElement;
|
|
35
|
-
if (onChange && model) {
|
|
36
|
-
onChange({ ...model, correctAnswer: target.value });
|
|
37
|
-
}
|
|
38
|
-
if (model) {
|
|
39
|
-
emitModelUpdate({ ...model, correctAnswer: target.value });
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
</script>
|
|
43
|
-
|
|
44
|
-
<div class="simple-cloze-author">
|
|
45
|
-
<div class="input-container">
|
|
46
|
-
<span class="input-label">Prompt</span>
|
|
47
|
-
<EditableHtml
|
|
48
|
-
markup={model?.prompt || ""}
|
|
49
|
-
onChange={handlePromptChange}
|
|
50
|
-
placeholder="Enter your question here..."
|
|
51
|
-
/>
|
|
52
|
-
</div>
|
|
53
|
-
|
|
54
|
-
<div class="mb-6">
|
|
55
|
-
<label for="simple-cloze-correct-answer" class="block text-sm text-gray-600 mb-2">
|
|
56
|
-
Correct Answer
|
|
57
|
-
</label>
|
|
58
|
-
<input
|
|
59
|
-
id="simple-cloze-correct-answer"
|
|
60
|
-
type="text"
|
|
61
|
-
class="input input-bordered w-full"
|
|
62
|
-
placeholder="Enter the correct answer"
|
|
63
|
-
value={model?.correctAnswer || ""}
|
|
64
|
-
oninput={handleAnswerChange}
|
|
65
|
-
/>
|
|
66
|
-
</div>
|
|
67
|
-
</div>
|
|
68
|
-
|
|
69
|
-
<style>
|
|
70
|
-
.simple-cloze-author {
|
|
71
|
-
max-width: 56rem;
|
|
72
|
-
margin: 0 auto;
|
|
73
|
-
padding: 24px;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
.input-container {
|
|
77
|
-
position: relative;
|
|
78
|
-
padding-top: 16px;
|
|
79
|
-
margin-bottom: 24px;
|
|
80
|
-
width: 100%;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
.input-label {
|
|
84
|
-
position: absolute;
|
|
85
|
-
top: 0;
|
|
86
|
-
left: 0;
|
|
87
|
-
transform-origin: top left;
|
|
88
|
-
transform: scale(0.75) translate(0, -0.75em);
|
|
89
|
-
color: var(--pie-text, rgba(0, 0, 0, 0.6));
|
|
90
|
-
pointer-events: none;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
:global(.simple-cloze-author .editor-container) {
|
|
94
|
-
border-color: var(--pie-border-light, #ccc);
|
|
95
|
-
border-radius: 4px;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
:global(.simple-cloze-author .editor-holder) {
|
|
99
|
-
min-height: 140px;
|
|
100
|
-
}
|
|
101
|
-
</style>
|
|
102
|
-
|
package/src/author/index.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import AuthorComponent from './Author.svelte';
|
|
2
|
-
|
|
3
|
-
const SvelteElementClass = (AuthorComponent as any).element;
|
|
4
|
-
|
|
5
|
-
class SimpleClozeAuthor extends SvelteElementClass {
|
|
6
|
-
private _model: any = null;
|
|
7
|
-
private _onChange: ((model: any) => void) | null = null;
|
|
8
|
-
|
|
9
|
-
set model(m: any) {
|
|
10
|
-
this._model = m;
|
|
11
|
-
super.model = m;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
get model() {
|
|
15
|
-
return this._model;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
set onChange(fn: (model: any) => void) {
|
|
19
|
-
this._onChange = fn;
|
|
20
|
-
(this as any).onChange = fn;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
get onChange() {
|
|
24
|
-
return this._onChange || (() => {});
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export default SimpleClozeAuthor;
|
package/src/controller/index.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { isEmpty } from 'lodash-es';
|
|
2
|
-
import defaults from './defaults';
|
|
3
|
-
|
|
4
|
-
export const getCorrectness = (question: any, session: any) => {
|
|
5
|
-
if (!session || !session.response) {
|
|
6
|
-
return 'unanswered';
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const correctAnswer = question?.correctAnswer || '';
|
|
10
|
-
const userAnswer = session.response || '';
|
|
11
|
-
|
|
12
|
-
// Simple string comparison for now
|
|
13
|
-
if (userAnswer.trim().toLowerCase() === correctAnswer.trim().toLowerCase()) {
|
|
14
|
-
return 'correct';
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return 'incorrect';
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export const getPartialScore = (_question: any, session: any) => {
|
|
21
|
-
if (!session || isEmpty(session)) {
|
|
22
|
-
return 0;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return 1;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export const outcome = (question: any, session: any, env: any) =>
|
|
29
|
-
new Promise((resolve) => {
|
|
30
|
-
if (!session || isEmpty(session)) {
|
|
31
|
-
resolve({ score: 0, empty: true });
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
session = normalizeSession(session);
|
|
36
|
-
|
|
37
|
-
if (env.mode !== 'evaluate') {
|
|
38
|
-
resolve({ score: undefined, completed: undefined });
|
|
39
|
-
} else {
|
|
40
|
-
const correctness = getCorrectness(question, session);
|
|
41
|
-
const score = correctness === 'correct' ? 1 : 0;
|
|
42
|
-
resolve({ score });
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
export const createDefaultModel = (model: any = {}) => ({ ...defaults.model, ...model });
|
|
47
|
-
|
|
48
|
-
export const normalizeSession = (s: any) => ({ ...s });
|
|
49
|
-
|
|
50
|
-
export const model = (question: any, session: any, env: any) => {
|
|
51
|
-
return new Promise((resolve) => {
|
|
52
|
-
session = session || {};
|
|
53
|
-
const normalizedQuestion = createDefaultModel(question);
|
|
54
|
-
|
|
55
|
-
const out: any = {
|
|
56
|
-
prompt: normalizedQuestion.promptEnabled ? normalizedQuestion.prompt : null,
|
|
57
|
-
disabled: env.mode !== 'gather',
|
|
58
|
-
view: env.mode === 'view',
|
|
59
|
-
env,
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
if (env.mode === 'evaluate') {
|
|
63
|
-
const correctness = getCorrectness(normalizedQuestion, session);
|
|
64
|
-
out.correctness = correctness;
|
|
65
|
-
out.correctAnswer = normalizedQuestion.correctAnswer;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {
|
|
69
|
-
out.teacherInstructions = normalizedQuestion.teacherInstructionsEnabled
|
|
70
|
-
? normalizedQuestion.teacherInstructions
|
|
71
|
-
: null;
|
|
72
|
-
} else {
|
|
73
|
-
out.teacherInstructions = null;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
resolve(out);
|
|
77
|
-
});
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
export const createCorrectResponseSession = (question: any, env: any) => {
|
|
81
|
-
return new Promise((resolve) => {
|
|
82
|
-
if (env.mode !== 'evaluate' && env.role === 'instructor') {
|
|
83
|
-
resolve({ id: '1', response: question.correctAnswer || '' });
|
|
84
|
-
} else {
|
|
85
|
-
resolve(null);
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
export const validate = (model: any = {}, _config: any = {}) => {
|
|
91
|
-
const errors: any = {};
|
|
92
|
-
|
|
93
|
-
if (!model.prompt || model.prompt.trim() === '' || model.prompt === '<p></p>') {
|
|
94
|
-
errors.prompt = 'Prompt is required';
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return errors;
|
|
98
|
-
};
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
<svelte:options
|
|
2
|
-
customElement={{
|
|
3
|
-
shadow: 'none',
|
|
4
|
-
props: {
|
|
5
|
-
model: { type: 'Object' },
|
|
6
|
-
session: { type: 'Object' }
|
|
7
|
-
}
|
|
8
|
-
}}
|
|
9
|
-
/>
|
|
10
|
-
|
|
11
|
-
<script lang="ts">
|
|
12
|
-
import { onMount } from 'svelte';
|
|
13
|
-
|
|
14
|
-
// Props using $props() in Svelte 5 custom element mode
|
|
15
|
-
let props = $props<{ model?: any; session?: any }>();
|
|
16
|
-
|
|
17
|
-
let inputElement: HTMLInputElement | null = null;
|
|
18
|
-
let showCorrectAnswer = $state(false);
|
|
19
|
-
|
|
20
|
-
onMount(() => {
|
|
21
|
-
if (inputElement) {
|
|
22
|
-
// Set initial value from session
|
|
23
|
-
inputElement.value = props?.session?.response || '';
|
|
24
|
-
|
|
25
|
-
inputElement.addEventListener('input', handleInput);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return () => {
|
|
29
|
-
if (inputElement) {
|
|
30
|
-
inputElement.removeEventListener('input', handleInput);
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
// Update input value when session changes externally
|
|
36
|
-
$effect(() => {
|
|
37
|
-
if (inputElement && !showCorrectAnswer) {
|
|
38
|
-
const sessionValue = props?.session?.response || '';
|
|
39
|
-
if (inputElement.value !== sessionValue) {
|
|
40
|
-
inputElement.value = sessionValue;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
// Update input value when showing correct answer
|
|
46
|
-
$effect(() => {
|
|
47
|
-
if (inputElement) {
|
|
48
|
-
if (showCorrectAnswer && props?.model?.correctAnswer) {
|
|
49
|
-
inputElement.value = props.model.correctAnswer;
|
|
50
|
-
} else if (!showCorrectAnswer) {
|
|
51
|
-
inputElement.value = props?.session?.response || '';
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
function handleInput(event: Event) {
|
|
57
|
-
const target = event.target as HTMLInputElement;
|
|
58
|
-
const newValue = target.value;
|
|
59
|
-
|
|
60
|
-
// Create updated session
|
|
61
|
-
const updatedSession = {
|
|
62
|
-
...props.session,
|
|
63
|
-
response: newValue,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
// Find the host custom element
|
|
67
|
-
const hostElement = target.closest('simple-cloze') as any;
|
|
68
|
-
if (hostElement?._internalSession) {
|
|
69
|
-
hostElement._internalSession = updatedSession;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Dispatch custom event for web component
|
|
73
|
-
const customEvent = new CustomEvent('session-changed', {
|
|
74
|
-
bubbles: true,
|
|
75
|
-
composed: true,
|
|
76
|
-
detail: { complete: true, component: 'simple-cloze' },
|
|
77
|
-
});
|
|
78
|
-
hostElement?.dispatchEvent(customEvent);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function toggleCorrectAnswer() {
|
|
82
|
-
showCorrectAnswer = !showCorrectAnswer;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Computed values
|
|
86
|
-
const isEvaluateMode = $derived(props?.model?.env?.mode === 'evaluate');
|
|
87
|
-
const correctness = $derived(props?.model?.correctness);
|
|
88
|
-
const isCorrect = $derived(correctness === 'correct');
|
|
89
|
-
const isIncorrect = $derived(correctness === 'incorrect');
|
|
90
|
-
</script>
|
|
91
|
-
|
|
92
|
-
<div class="p-4">
|
|
93
|
-
{#if props?.model?.prompt}
|
|
94
|
-
<div class="mb-4 prose">{@html props.model.prompt}</div>
|
|
95
|
-
{/if}
|
|
96
|
-
|
|
97
|
-
{#if isEvaluateMode && isIncorrect}
|
|
98
|
-
<button
|
|
99
|
-
type="button"
|
|
100
|
-
class="mb-3 flex items-center gap-2 cursor-pointer select-none"
|
|
101
|
-
onclick={toggleCorrectAnswer}
|
|
102
|
-
aria-pressed={showCorrectAnswer}
|
|
103
|
-
>
|
|
104
|
-
{#if showCorrectAnswer}
|
|
105
|
-
<!-- Hide correct answer icon (open state) -->
|
|
106
|
-
<svg style="width: 25px; height: 25px;" preserveAspectRatio="xMinYMin meet" version="1.1" viewBox="-283 359 34 35">
|
|
107
|
-
<circle cx="-266" cy="375.9" r="14" fill="#bce2ff" />
|
|
108
|
-
<path d="M-280.5,375.9c0-8,6.5-14.5,14.5-14.5s14.5,6.5,14.5,14.5s-6.5,14.5-14.5,14.5S-280.5,383.9-280.5,375.9z M-279.5,375.9c0,7.4,6.1,13.5,13.5,13.5c7.4,0,13.5-6.1,13.5-13.5s-6.1-13.5-13.5-13.5C-273.4,362.4-279.5,368.5-279.5,375.9z" fill="#bce2ff" />
|
|
109
|
-
<polygon points="-265.4,383.1 -258.6,377.2 -261.2,374.2 -264.3,376.9 -268.9,368.7 -272.4,370.6" fill="#1a9cff" />
|
|
110
|
-
</svg>
|
|
111
|
-
{:else}
|
|
112
|
-
<!-- Show correct answer icon (closed state) -->
|
|
113
|
-
<svg style="width: 25px; height: 25px;" preserveAspectRatio="xMinYMin meet" version="1.1" viewBox="-129.5 127 34 35">
|
|
114
|
-
<path style="fill: #D0CAC5; stroke: #E6E3E0; stroke-width: 0.75; stroke-miterlimit: 10;" d="M-112.9,160.4c-8.5,0-15.5-6.9-15.5-15.5c0-8.5,6.9-15.5,15.5-15.5s15.5,6.9,15.5,15.5 C-97.4,153.5-104.3,160.4-112.9,160.4z" />
|
|
115
|
-
<path style="fill: #B3ABA4; stroke: #CDC7C2; stroke-width: 0.5; stroke-miterlimit: 10;" d="M-113.2,159c-8,0-14.5-6.5-14.5-14.5s6.5-14.5,14.5-14.5s14.5,6.5,14.5,14.5S-105.2,159-113.2,159z" />
|
|
116
|
-
<circle cx="-114.2" cy="143.5" r="14" fill="white" />
|
|
117
|
-
<path d="M-114.2,158c-8,0-14.5-6.5-14.5-14.5s6.5-14.5,14.5-14.5s14.5,6.5,14.5,14.5S-106.2,158-114.2,158z M-114.2,130c-7.4,0-13.5,6.1-13.5,13.5s6.1,13.5,13.5,13.5s13.5-6.1,13.5-13.5S-106.8,130-114.2,130z" fill="#bce2ff" />
|
|
118
|
-
<polygon points="-114.8,150.7 -121.6,144.8 -119,141.8 -115.9,144.5 -111.3,136.3 -107.8,138.2" fill="#1a9cff" />
|
|
119
|
-
</svg>
|
|
120
|
-
{/if}
|
|
121
|
-
<span class="text-sm hover:underline">
|
|
122
|
-
{showCorrectAnswer ? 'Hide' : 'Show'} correct answer
|
|
123
|
-
</span>
|
|
124
|
-
</button>
|
|
125
|
-
{/if}
|
|
126
|
-
|
|
127
|
-
<div class="relative inline-block">
|
|
128
|
-
{#if isEvaluateMode && (isCorrect || showCorrectAnswer)}
|
|
129
|
-
<span class="correctness-icon" style="background-color: #0EA449;">
|
|
130
|
-
<svg style="width: 12px; height: 12px; color: white;" fill="currentColor" viewBox="0 0 24 24">
|
|
131
|
-
<path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/>
|
|
132
|
-
</svg>
|
|
133
|
-
</span>
|
|
134
|
-
{/if}
|
|
135
|
-
{#if isEvaluateMode && isIncorrect && !showCorrectAnswer}
|
|
136
|
-
<span class="correctness-icon" style="background-color: #BF0D00;">
|
|
137
|
-
<svg style="width: 12px; height: 12px; color: white;" fill="currentColor" viewBox="0 0 24 24">
|
|
138
|
-
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/>
|
|
139
|
-
</svg>
|
|
140
|
-
</span>
|
|
141
|
-
{/if}
|
|
142
|
-
<input
|
|
143
|
-
bind:this={inputElement}
|
|
144
|
-
type="text"
|
|
145
|
-
placeholder="Enter your answer..."
|
|
146
|
-
disabled={props?.model?.disabled}
|
|
147
|
-
readonly={showCorrectAnswer}
|
|
148
|
-
class="outline-none px-3 py-2 rounded"
|
|
149
|
-
style:border={isEvaluateMode && (isCorrect || showCorrectAnswer) ? 'solid 2px #0EA449' : isEvaluateMode && isIncorrect && !showCorrectAnswer ? 'solid 2px #BF0D00' : 'solid 1px #d1d5db'}
|
|
150
|
-
style:color={isEvaluateMode && (isCorrect || isIncorrect) ? 'black' : ''}
|
|
151
|
-
/>
|
|
152
|
-
</div>
|
|
153
|
-
</div>
|
|
154
|
-
|
|
155
|
-
<style>
|
|
156
|
-
/* Custom styles for correct answer display */
|
|
157
|
-
input[readonly] {
|
|
158
|
-
font-weight: 600;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
.correctness-icon {
|
|
162
|
-
position: absolute;
|
|
163
|
-
top: -8px;
|
|
164
|
-
left: -8px;
|
|
165
|
-
border-radius: 50%;
|
|
166
|
-
display: inline-flex;
|
|
167
|
-
align-items: center;
|
|
168
|
-
justify-content: center;
|
|
169
|
-
padding: 2px;
|
|
170
|
-
}
|
|
171
|
-
</style>
|
package/src/delivery/index.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// Import the Svelte component compiled as custom element
|
|
2
|
-
import SimpleClozeComponent from './SimpleCloze.svelte';
|
|
3
|
-
|
|
4
|
-
// Get the base Svelte custom element class
|
|
5
|
-
const SvelteElementClass = (SimpleClozeComponent as any).element;
|
|
6
|
-
|
|
7
|
-
// Create a wrapper that properly handles session updates
|
|
8
|
-
class SimpleClozeElement extends SvelteElementClass {
|
|
9
|
-
_internalSession: any = null;
|
|
10
|
-
|
|
11
|
-
// Override the session setter to maintain internal state
|
|
12
|
-
set session(s: any) {
|
|
13
|
-
this._internalSession = s;
|
|
14
|
-
// Update the Svelte component's props
|
|
15
|
-
super.session = s;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Override the session getter to return internal state
|
|
19
|
-
get session() {
|
|
20
|
-
return this._internalSession;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Provide a callback for the Svelte component to update session
|
|
24
|
-
onSessionChange = (updatedSession: any) => {
|
|
25
|
-
this._internalSession = updatedSession;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
connectedCallback() {
|
|
29
|
-
super.connectedCallback();
|
|
30
|
-
// Set the callback on the Svelte component instance
|
|
31
|
-
(this as any).onSessionChange = this.onSessionChange;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Export the custom element class
|
|
36
|
-
// The demo loader will register it with customElements.define()
|
|
37
|
-
export default SimpleClozeElement;
|
package/src/index.iife.ts
DELETED
package/src/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from './delivery/index';
|
package/src/print/Print.svelte
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
<svelte:options
|
|
2
|
-
customElement={{
|
|
3
|
-
shadow: 'none',
|
|
4
|
-
props: {
|
|
5
|
-
model: { type: 'Object' }
|
|
6
|
-
}
|
|
7
|
-
}}
|
|
8
|
-
/>
|
|
9
|
-
|
|
10
|
-
<script lang="ts">
|
|
11
|
-
// Destructure props so Svelte can infer what to expose as custom element properties
|
|
12
|
-
let { model = null }: { model?: any } = $props();
|
|
13
|
-
|
|
14
|
-
let prompt = $state('');
|
|
15
|
-
$effect(() => {
|
|
16
|
-
prompt = model?.prompt || '';
|
|
17
|
-
});
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
<div class="p-4 print:p-0">
|
|
21
|
-
{#if prompt}
|
|
22
|
-
<div class="mb-4 prose prose-sm">{@html prompt}</div>
|
|
23
|
-
{/if}
|
|
24
|
-
|
|
25
|
-
<div class="inline-block">
|
|
26
|
-
<input
|
|
27
|
-
type="text"
|
|
28
|
-
placeholder="______________________"
|
|
29
|
-
class="px-3 py-2 border-b-2 border-gray-400 bg-transparent print:border-black"
|
|
30
|
-
style="border-top: none; border-left: none; border-right: none;"
|
|
31
|
-
disabled
|
|
32
|
-
/>
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
|
|
36
|
-
<style>
|
|
37
|
-
@media print {
|
|
38
|
-
input {
|
|
39
|
-
border-color: black !important;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.prose :global(p) {
|
|
44
|
-
margin: 0.5em 0;
|
|
45
|
-
}
|
|
46
|
-
.prose :global(strong) {
|
|
47
|
-
font-weight: 600;
|
|
48
|
-
}
|
|
49
|
-
</style>
|
package/src/print/index.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import PrintComponent from './Print.svelte';
|
|
2
|
-
|
|
3
|
-
const SvelteElementClass = (PrintComponent as any).element;
|
|
4
|
-
|
|
5
|
-
class SimpleClozePrint extends SvelteElementClass {
|
|
6
|
-
private _model: any = null;
|
|
7
|
-
|
|
8
|
-
set model(m: any) {
|
|
9
|
-
this._model = m;
|
|
10
|
-
super.model = m;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
get model() {
|
|
14
|
-
return this._model;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default SimpleClozePrint;
|