@webwriter/quiz 1.0.10 → 1.1.2

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