@webwriter/quiz 1.0.9 → 1.0.10

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.
Files changed (112) hide show
  1. package/.env +1 -0
  2. package/LICENSE +6 -6
  3. package/custom.d.ts +175 -175
  4. package/dist/widgets/webwriter-choice-item.js +174 -29
  5. package/dist/widgets/webwriter-choice.js +174 -29
  6. package/dist/widgets/webwriter-cloze-gap.js +174 -29
  7. package/dist/widgets/webwriter-cloze.js +174 -29
  8. package/dist/widgets/webwriter-mark.js +174 -29
  9. package/dist/widgets/webwriter-order-item.js +174 -29
  10. package/dist/widgets/webwriter-order.js +174 -29
  11. package/dist/widgets/webwriter-pairing-item.js +174 -29
  12. package/dist/widgets/webwriter-pairing.js +174 -29
  13. package/dist/widgets/webwriter-quiz.js +174 -29
  14. package/dist/widgets/webwriter-speech.js +174 -29
  15. package/dist/widgets/webwriter-task-explainer.js +174 -29
  16. package/dist/widgets/webwriter-task-hint.js +174 -29
  17. package/dist/widgets/webwriter-task-prompt.js +174 -29
  18. package/dist/widgets/webwriter-task.js +176 -31
  19. package/dist/widgets/webwriter-text.js +174 -29
  20. package/lit-localize.json +14 -14
  21. package/localization/bg.xlf +69 -54
  22. package/localization/cs.xlf +69 -54
  23. package/localization/da.xlf +69 -54
  24. package/localization/de.xlf +74 -54
  25. package/localization/el.xlf +69 -54
  26. package/localization/es.xlf +69 -54
  27. package/localization/et.xlf +69 -54
  28. package/localization/fi.xlf +69 -54
  29. package/localization/fr.xlf +69 -54
  30. package/localization/generated/bg.ts +29 -24
  31. package/localization/generated/cs.ts +29 -24
  32. package/localization/generated/da.ts +29 -24
  33. package/localization/generated/de.ts +29 -24
  34. package/localization/generated/el.ts +29 -24
  35. package/localization/generated/es.ts +29 -24
  36. package/localization/generated/et.ts +29 -24
  37. package/localization/generated/fi.ts +29 -24
  38. package/localization/generated/fr.ts +29 -24
  39. package/localization/generated/hu.ts +29 -24
  40. package/localization/generated/id.ts +29 -24
  41. package/localization/generated/index.js +2 -2
  42. package/localization/generated/it.ts +29 -24
  43. package/localization/generated/ja.ts +29 -24
  44. package/localization/generated/ko.ts +29 -24
  45. package/localization/generated/locale-codes.js +79 -79
  46. package/localization/generated/lt.ts +29 -24
  47. package/localization/generated/lv.ts +29 -24
  48. package/localization/generated/nb.ts +29 -24
  49. package/localization/generated/nl.ts +29 -24
  50. package/localization/generated/pl.ts +29 -24
  51. package/localization/generated/pt-BR.ts +29 -24
  52. package/localization/generated/pt-PT.ts +29 -24
  53. package/localization/generated/ro.ts +29 -24
  54. package/localization/generated/ru.ts +29 -24
  55. package/localization/generated/sk.ts +29 -24
  56. package/localization/generated/sl.ts +29 -24
  57. package/localization/generated/sv.ts +29 -24
  58. package/localization/generated/tr.ts +29 -24
  59. package/localization/generated/uk.ts +29 -24
  60. package/localization/generated/zh-hans.ts +29 -24
  61. package/localization/hu.xlf +69 -54
  62. package/localization/id.xlf +69 -54
  63. package/localization/it.xlf +69 -54
  64. package/localization/ja.xlf +69 -54
  65. package/localization/ko.xlf +69 -54
  66. package/localization/lt.xlf +69 -54
  67. package/localization/lv.xlf +69 -54
  68. package/localization/nb.xlf +69 -54
  69. package/localization/nl.xlf +69 -54
  70. package/localization/pl.xlf +69 -54
  71. package/localization/pt-BR.xlf +69 -54
  72. package/localization/pt-PT.xlf +69 -54
  73. package/localization/ro.xlf +69 -54
  74. package/localization/ru.xlf +69 -54
  75. package/localization/sk.xlf +69 -54
  76. package/localization/sl.xlf +69 -54
  77. package/localization/sv.xlf +69 -54
  78. package/localization/tr.xlf +69 -54
  79. package/localization/uk.xlf +69 -54
  80. package/localization/zh-hans.xlf +69 -54
  81. package/package.json +2 -53
  82. package/src/lib/combobox.ts +455 -455
  83. package/src/lib/highlighter-fill.svg +5 -5
  84. package/src/snippets/Beispiel-Choice.html +57 -57
  85. package/src/snippets/Beispiel-Mark.html +13 -13
  86. package/src/snippets/Beispiel-Order.html +52 -52
  87. package/src/snippets/Beispiel-Text.html +20 -20
  88. package/src/snippets/choice.html +7 -7
  89. package/src/snippets/cloze.html +3 -3
  90. package/src/snippets/mark.html +3 -3
  91. package/src/snippets/order.html +7 -7
  92. package/src/snippets/pairing.html +9 -9
  93. package/src/snippets/speech.html +3 -3
  94. package/src/snippets/text.html +3 -3
  95. package/src/snippets/wordsearch.html +3 -3
  96. package/src/widgets/webwriter-choice-item.ts +250 -250
  97. package/src/widgets/webwriter-choice.ts +314 -314
  98. package/src/widgets/webwriter-cloze-gap.ts +215 -215
  99. package/src/widgets/webwriter-cloze.ts +135 -135
  100. package/src/widgets/webwriter-mark.ts +431 -431
  101. package/src/widgets/webwriter-order-item.ts +437 -437
  102. package/src/widgets/webwriter-order.ts +284 -284
  103. package/src/widgets/webwriter-pairing-item.ts +160 -160
  104. package/src/widgets/webwriter-pairing.ts +192 -192
  105. package/src/widgets/webwriter-quiz.ts +281 -281
  106. package/src/widgets/webwriter-speech.ts +272 -272
  107. package/src/widgets/webwriter-task-explainer.ts +42 -42
  108. package/src/widgets/webwriter-task-hint.ts +22 -22
  109. package/src/widgets/webwriter-task-prompt.ts +23 -23
  110. package/src/widgets/webwriter-task.ts +546 -546
  111. package/src/widgets/webwriter-text.ts +135 -135
  112. package/tsconfig.json +6 -6
@@ -1,251 +1,251 @@
1
- import {css, html, PropertyValues} from "lit"
2
- import {styleMap} from "lit/directives/style-map.js"
3
- import {classMap} from "lit/directives/class-map.js"
4
- import {unsafeStatic} from "lit/static-html.js"
5
- import {LitElementWw} from "@webwriter/lit"
6
- import {customElement, property, query} from "lit/decorators.js"
7
-
8
- import SlRadio from "@shoelace-style/shoelace/dist/components/radio/radio.component.js"
9
- import SlCheckbox from "@shoelace-style/shoelace/dist/components/checkbox/checkbox.component.js"
10
- import SlIcon from "@shoelace-style/shoelace/dist/components/icon/icon.component.js"
11
- import "@shoelace-style/shoelace/dist/themes/light.css"
12
- import { keyed } from "lit/directives/keyed.js"
13
- import IconX from "bootstrap-icons/icons/x.svg"
14
- import IconCheck from "bootstrap-icons/icons/check.svg"
15
-
16
- import LOCALIZE from "../../localization/generated"
17
- import {msg} from "@lit/localize"
18
-
19
- declare global {interface HTMLElementTagNameMap {
20
- "webwriter-choice-item": WebwriterChoiceItem;
21
- }}
22
-
23
- @customElement("webwriter-choice-item")
24
- export class WebwriterChoiceItem extends LitElementWw {
25
-
26
- localize = LOCALIZE
27
-
28
- @property({type: Boolean, attribute: false})
29
- accessor active = false
30
-
31
- @property({type: Boolean, attribute: false})
32
- accessor valid: true | false | undefined
33
-
34
- // inactive + invalid/no validity -> nothing
35
- // active + no validity -> blue circle
36
- // inactive/active + valid -> green upper checkmark
37
- // active + invalid -> red upper cross
38
-
39
-
40
- @property({type: String, attribute: true, reflect: true})
41
- accessor layout: "list" | "tiles" = "list"
42
-
43
- static scopedElements = {
44
- "sl-radio": SlRadio,
45
- "sl-checkbox": SlCheckbox,
46
- "sl-icon": SlIcon
47
- }
48
-
49
- static styles = css`
50
-
51
- :host {
52
- width: 100%;
53
- position: relative;
54
- }
55
-
56
- :host(:not([contenteditable=true]):not([contenteditable=""])) .author-only {
57
- display: none;
58
- }
59
-
60
- :host(:is([contenteditable=true], [contenteditable=""])) .user-only {
61
- display: none;
62
- }
63
-
64
- :host(:is([contenteditable=true], [contenteditable=""])) sl-checkbox.valid {
65
- --webwriter-control-color-600: var(--sl-color-success-600);
66
- --webwriter-control-color-400: var(--sl-color-success-400);
67
- }
68
-
69
- sl-checkbox {
70
- display: block;
71
- width: 100%;
72
- &::part(base) {
73
- width: 100%;
74
- display: flex;
75
- flex-direction: row;
76
- align-items: center;
77
- cursor: unset;
78
- }
79
-
80
- &::part(control) {
81
- cursor: pointer;
82
- border-radius: var(--webwriter-choice-radius, 2px);
83
- border-width: 2px;
84
- }
85
-
86
- &::part(control):not(:hover){
87
- border-color: var(--sl-color-gray-500);
88
- }
89
-
90
- &::part(control):hover {
91
- border-color: var(--sl-color-gray-700);
92
- }
93
-
94
- &::part(control--checked):not(:hover) {
95
- background-color: var(--webwriter-control-color-600, var(--sl-color-primary-600));
96
- border-color: var(--sl-color-gray-500);
97
- }
98
- &::part(control--checked):hover {
99
- background-color: var(--webwriter-control-color-400, var(--sl-color-primary-400));
100
- border-color: var(--webwriter-control-color-600, var(--sl-color-primary-600));
101
- }
102
-
103
- &::part(label) {
104
- width: 100%;
105
- }
106
- }
107
-
108
- .solution {
109
- position: absolute;
110
- top: -6px;
111
- left: -6px;
112
- border: 2px solid var(--sl-color-gray-500);
113
- border-radius: var(--webwriter-choice-radius, 2px);
114
- width: 12px;
115
- height: 12px;
116
- z-index: 1;
117
- color: white;
118
-
119
- &[data-valid] {
120
- background: var(--sl-color-success-600);
121
- }
122
-
123
- &:not([data-valid]) {
124
- background: var(--sl-color-danger-600);
125
- }
126
- }
127
-
128
- :host([layout=tiles]) {
129
- position: relative;
130
- overflow: visible !important;
131
-
132
- & ::slotted(:is(picture, audio, video, img, iframe)) {
133
- height: 100%;
134
- width: 100%;
135
- }
136
-
137
- & ::slotted(:not(:is(picture, audio, video, img, iframe))) {
138
- margin: 5px !important;
139
- }
140
-
141
- sl-checkbox {
142
- display: block;
143
- &::part(base) {
144
- display: flex;
145
- flex-direction: row;
146
- align-items: center;
147
- cursor: unset;
148
- position: static;
149
- }
150
-
151
- &::part(control) {
152
- position: absolute;
153
- bottom: -10px;
154
- left: -10px;
155
- cursor: pointer;
156
- border-radius: var(--webwriter-choice-radius, 2px);
157
- z-index: 100;
158
- border-color: var(--sl-color-gray-500);
159
- }
160
-
161
- &::part(control--checked):not(:hover) {
162
- background-color: var(--webwriter-control-color-600, var(--sl-color-primary-600));
163
- border-color: var(--sl-color-gray-500);
164
- }
165
- &::part(control--checked):hover {
166
- background-color: var(--webwriter-control-color-400, var(--sl-color-primary-400));
167
- border-color: var(--webwriter-control-color-600, var(--sl-color-primary-600));
168
- }
169
-
170
- &::part(label) {
171
- aspect-ratio: 1;
172
- min-width: 125px;
173
- max-width: 350px;
174
- min-height: 125px;
175
- max-height: 350px;
176
- overflow: hidden;
177
- resize: both;
178
- margin-inline-start: 0;
179
- overflow-y: auto;
180
- scrollbar-width: thin;
181
- }
182
- }
183
- }
184
- `
185
-
186
- handleClick = (e: PointerEvent) => {
187
- const checkboxClicked = e.composedPath().some(v => (v as HTMLElement)?.classList?.contains("checkbox__control"))
188
- const editable = this.isContentEditable
189
- if(editable && !checkboxClicked) {
190
- e.preventDefault()
191
- }
192
- else {
193
- e.stopImmediatePropagation()
194
- }
195
- }
196
-
197
- handleChange = (e: CustomEvent) => {
198
- if(this.isContentEditable) {
199
- this.valid = !this.valid
200
- }
201
- else {
202
- this.active = !this.active
203
- }
204
- }
205
-
206
- @query("sl-checkbox")
207
- accessor checkbox: SlCheckbox
208
-
209
- observer: MutationObserver
210
-
211
- protected async updated(_changedProperties: PropertyValues) {
212
- await this.checkbox.updateComplete
213
- const labelEl = this.checkbox.shadowRoot.querySelector(".checkbox__label") as HTMLElement
214
-
215
- if(_changedProperties.has("layout") && this.layout === "list") {
216
- this.syncSize(true)
217
- this.observer?.disconnect()
218
- }
219
- else if(_changedProperties.has("layout") && this.layout === "tiles") {
220
- this.syncSize()
221
- this.observer = new MutationObserver(() => this.syncSize())
222
- this.observer.observe(labelEl, {attributeFilter: ["style"], attributes: true})
223
- }
224
- }
225
-
226
- syncSize(clear=false) {
227
- const labelEl = this.checkbox?.shadowRoot.querySelector(".checkbox__label") as HTMLElement
228
- if(labelEl && !clear) {
229
- this.style.width = labelEl.style.width
230
- this.style.height = labelEl.style.height
231
- }
232
- else if(labelEl && clear) {
233
- this.style.width = labelEl.style.width = null
234
- this.style.height = labelEl.style.height = null
235
- }
236
- }
237
-
238
- disconnectedCallback(): void {
239
- super.disconnectedCallback()
240
- this.observer?.disconnect()
241
- }
242
-
243
- render() {
244
- return keyed(this.layout, html`
245
- ${this.valid !== undefined && (this.active || !this.active && this.valid)? html`<sl-icon class="solution user-only" ?data-valid=${this.valid} src=${this.valid? IconCheck: IconX}></sl-icon>`: null}
246
- <sl-checkbox class=${classMap({valid: this.valid, active: this.active})} exportparts="base, control, label" @click=${this.handleClick} @sl-change=${this.handleChange} ?checked=${this.isContentEditable? this.valid: this.active}>
247
- <slot part="slot" style=${styleMap({"--ww-placeholder": `"${msg("Option")}"`})}></slot>
248
- </sl-checkbox>
249
- `)
250
- }
1
+ import {css, html, PropertyValues} from "lit"
2
+ import {styleMap} from "lit/directives/style-map.js"
3
+ import {classMap} from "lit/directives/class-map.js"
4
+ import {unsafeStatic} from "lit/static-html.js"
5
+ import {LitElementWw} from "@webwriter/lit"
6
+ import {customElement, property, query} from "lit/decorators.js"
7
+
8
+ import SlRadio from "@shoelace-style/shoelace/dist/components/radio/radio.component.js"
9
+ import SlCheckbox from "@shoelace-style/shoelace/dist/components/checkbox/checkbox.component.js"
10
+ import SlIcon from "@shoelace-style/shoelace/dist/components/icon/icon.component.js"
11
+ import "@shoelace-style/shoelace/dist/themes/light.css"
12
+ import { keyed } from "lit/directives/keyed.js"
13
+ import IconX from "bootstrap-icons/icons/x.svg"
14
+ import IconCheck from "bootstrap-icons/icons/check.svg"
15
+
16
+ import LOCALIZE from "../../localization/generated"
17
+ import {msg} from "@lit/localize"
18
+
19
+ declare global {interface HTMLElementTagNameMap {
20
+ "webwriter-choice-item": WebwriterChoiceItem;
21
+ }}
22
+
23
+ @customElement("webwriter-choice-item")
24
+ export class WebwriterChoiceItem extends LitElementWw {
25
+
26
+ localize = LOCALIZE
27
+
28
+ @property({type: Boolean, attribute: false})
29
+ accessor active = false
30
+
31
+ @property({type: Boolean, attribute: false})
32
+ accessor valid: true | false | undefined
33
+
34
+ // inactive + invalid/no validity -> nothing
35
+ // active + no validity -> blue circle
36
+ // inactive/active + valid -> green upper checkmark
37
+ // active + invalid -> red upper cross
38
+
39
+
40
+ @property({type: String, attribute: true, reflect: true})
41
+ accessor layout: "list" | "tiles" = "list"
42
+
43
+ static scopedElements = {
44
+ "sl-radio": SlRadio,
45
+ "sl-checkbox": SlCheckbox,
46
+ "sl-icon": SlIcon
47
+ }
48
+
49
+ static styles = css`
50
+
51
+ :host {
52
+ width: 100%;
53
+ position: relative;
54
+ }
55
+
56
+ :host(:not([contenteditable=true]):not([contenteditable=""])) .author-only {
57
+ display: none;
58
+ }
59
+
60
+ :host(:is([contenteditable=true], [contenteditable=""])) .user-only {
61
+ display: none;
62
+ }
63
+
64
+ :host(:is([contenteditable=true], [contenteditable=""])) sl-checkbox.valid {
65
+ --webwriter-control-color-600: var(--sl-color-success-600);
66
+ --webwriter-control-color-400: var(--sl-color-success-400);
67
+ }
68
+
69
+ sl-checkbox {
70
+ display: block;
71
+ width: 100%;
72
+ &::part(base) {
73
+ width: 100%;
74
+ display: flex;
75
+ flex-direction: row;
76
+ align-items: center;
77
+ cursor: unset;
78
+ }
79
+
80
+ &::part(control) {
81
+ cursor: pointer;
82
+ border-radius: var(--webwriter-choice-radius, 2px);
83
+ border-width: 2px;
84
+ }
85
+
86
+ &::part(control):not(:hover){
87
+ border-color: var(--sl-color-gray-500);
88
+ }
89
+
90
+ &::part(control):hover {
91
+ border-color: var(--sl-color-gray-700);
92
+ }
93
+
94
+ &::part(control--checked):not(:hover) {
95
+ background-color: var(--webwriter-control-color-600, var(--sl-color-primary-600));
96
+ border-color: var(--sl-color-gray-500);
97
+ }
98
+ &::part(control--checked):hover {
99
+ background-color: var(--webwriter-control-color-400, var(--sl-color-primary-400));
100
+ border-color: var(--webwriter-control-color-600, var(--sl-color-primary-600));
101
+ }
102
+
103
+ &::part(label) {
104
+ width: 100%;
105
+ }
106
+ }
107
+
108
+ .solution {
109
+ position: absolute;
110
+ top: -6px;
111
+ left: -6px;
112
+ border: 2px solid var(--sl-color-gray-500);
113
+ border-radius: var(--webwriter-choice-radius, 2px);
114
+ width: 12px;
115
+ height: 12px;
116
+ z-index: 1;
117
+ color: white;
118
+
119
+ &[data-valid] {
120
+ background: var(--sl-color-success-600);
121
+ }
122
+
123
+ &:not([data-valid]) {
124
+ background: var(--sl-color-danger-600);
125
+ }
126
+ }
127
+
128
+ :host([layout=tiles]) {
129
+ position: relative;
130
+ overflow: visible !important;
131
+
132
+ & ::slotted(:is(picture, audio, video, img, iframe)) {
133
+ height: 100%;
134
+ width: 100%;
135
+ }
136
+
137
+ & ::slotted(:not(:is(picture, audio, video, img, iframe))) {
138
+ margin: 5px !important;
139
+ }
140
+
141
+ sl-checkbox {
142
+ display: block;
143
+ &::part(base) {
144
+ display: flex;
145
+ flex-direction: row;
146
+ align-items: center;
147
+ cursor: unset;
148
+ position: static;
149
+ }
150
+
151
+ &::part(control) {
152
+ position: absolute;
153
+ bottom: -10px;
154
+ left: -10px;
155
+ cursor: pointer;
156
+ border-radius: var(--webwriter-choice-radius, 2px);
157
+ z-index: 100;
158
+ border-color: var(--sl-color-gray-500);
159
+ }
160
+
161
+ &::part(control--checked):not(:hover) {
162
+ background-color: var(--webwriter-control-color-600, var(--sl-color-primary-600));
163
+ border-color: var(--sl-color-gray-500);
164
+ }
165
+ &::part(control--checked):hover {
166
+ background-color: var(--webwriter-control-color-400, var(--sl-color-primary-400));
167
+ border-color: var(--webwriter-control-color-600, var(--sl-color-primary-600));
168
+ }
169
+
170
+ &::part(label) {
171
+ aspect-ratio: 1;
172
+ min-width: 125px;
173
+ max-width: 350px;
174
+ min-height: 125px;
175
+ max-height: 350px;
176
+ overflow: hidden;
177
+ resize: both;
178
+ margin-inline-start: 0;
179
+ overflow-y: auto;
180
+ scrollbar-width: thin;
181
+ }
182
+ }
183
+ }
184
+ `
185
+
186
+ handleClick = (e: PointerEvent) => {
187
+ const checkboxClicked = e.composedPath().some(v => (v as HTMLElement)?.classList?.contains("checkbox__control"))
188
+ const editable = this.isContentEditable
189
+ if(editable && !checkboxClicked) {
190
+ e.preventDefault()
191
+ }
192
+ else {
193
+ e.stopImmediatePropagation()
194
+ }
195
+ }
196
+
197
+ handleChange = (e: CustomEvent) => {
198
+ if(this.isContentEditable) {
199
+ this.valid = !this.valid
200
+ }
201
+ else {
202
+ this.active = !this.active
203
+ }
204
+ }
205
+
206
+ @query("sl-checkbox")
207
+ accessor checkbox: SlCheckbox
208
+
209
+ observer: MutationObserver
210
+
211
+ protected async updated(_changedProperties: PropertyValues) {
212
+ await this.checkbox.updateComplete
213
+ const labelEl = this.checkbox.shadowRoot.querySelector(".checkbox__label") as HTMLElement
214
+
215
+ if(_changedProperties.has("layout") && this.layout === "list") {
216
+ this.syncSize(true)
217
+ this.observer?.disconnect()
218
+ }
219
+ else if(_changedProperties.has("layout") && this.layout === "tiles") {
220
+ this.syncSize()
221
+ this.observer = new MutationObserver(() => this.syncSize())
222
+ this.observer.observe(labelEl, {attributeFilter: ["style"], attributes: true})
223
+ }
224
+ }
225
+
226
+ syncSize(clear=false) {
227
+ const labelEl = this.checkbox?.shadowRoot.querySelector(".checkbox__label") as HTMLElement
228
+ if(labelEl && !clear) {
229
+ this.style.width = labelEl.style.width
230
+ this.style.height = labelEl.style.height
231
+ }
232
+ else if(labelEl && clear) {
233
+ this.style.width = labelEl.style.width = null
234
+ this.style.height = labelEl.style.height = null
235
+ }
236
+ }
237
+
238
+ disconnectedCallback(): void {
239
+ super.disconnectedCallback()
240
+ this.observer?.disconnect()
241
+ }
242
+
243
+ render() {
244
+ return keyed(this.layout, html`
245
+ ${this.valid !== undefined && (this.active || !this.active && this.valid)? html`<sl-icon class="solution user-only" ?data-valid=${this.valid} src=${this.valid? IconCheck: IconX}></sl-icon>`: null}
246
+ <sl-checkbox class=${classMap({valid: this.valid, active: this.active})} exportparts="base, control, label" @click=${this.handleClick} @sl-change=${this.handleChange} ?checked=${this.isContentEditable? this.valid: this.active}>
247
+ <slot part="slot" style=${styleMap({"--ww-placeholder": `"${msg("Option")}"`})}></slot>
248
+ </sl-checkbox>
249
+ `)
250
+ }
251
251
  }