@webwriter/quiz 1.1.2 → 1.1.5

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/.github/workflows/publish.yml +8 -0
  2. package/LICENSE +6 -6
  3. package/custom.d.ts +175 -175
  4. package/dist/widgets/webwriter-choice-item.js +69 -205
  5. package/dist/widgets/webwriter-choice.js +99 -214
  6. package/dist/widgets/webwriter-cloze-gap.js +74 -213
  7. package/dist/widgets/webwriter-cloze.js +71 -204
  8. package/dist/widgets/webwriter-mark.js +72 -205
  9. package/dist/widgets/webwriter-order-item.js +68 -201
  10. package/dist/widgets/webwriter-order.js +99 -209
  11. package/dist/widgets/webwriter-pairing-item.js +57 -160
  12. package/dist/widgets/webwriter-pairing.js +69 -196
  13. package/dist/widgets/webwriter-quiz.js +72 -211
  14. package/dist/widgets/webwriter-speech.js +71 -204
  15. package/dist/widgets/webwriter-task-explainer.js +57 -160
  16. package/dist/widgets/webwriter-task-hint.js +55 -158
  17. package/dist/widgets/webwriter-task-prompt.js +61 -170
  18. package/dist/widgets/webwriter-task.js +80 -205
  19. package/dist/widgets/webwriter-text.js +94 -205
  20. package/lit-localize.json +14 -14
  21. package/localization/bg.xlf +72 -69
  22. package/localization/cs.xlf +72 -69
  23. package/localization/da.xlf +72 -69
  24. package/localization/de.xlf +77 -74
  25. package/localization/el.xlf +72 -69
  26. package/localization/es.xlf +72 -69
  27. package/localization/et.xlf +72 -69
  28. package/localization/fi.xlf +72 -69
  29. package/localization/fr.xlf +72 -69
  30. package/localization/generated/bg.ts +30 -29
  31. package/localization/generated/cs.ts +30 -29
  32. package/localization/generated/da.ts +30 -29
  33. package/localization/generated/de.ts +30 -29
  34. package/localization/generated/el.ts +30 -29
  35. package/localization/generated/es.ts +30 -29
  36. package/localization/generated/et.ts +30 -29
  37. package/localization/generated/fi.ts +30 -29
  38. package/localization/generated/fr.ts +30 -29
  39. package/localization/generated/hu.ts +30 -29
  40. package/localization/generated/id.ts +30 -29
  41. package/localization/generated/index.js +2 -2
  42. package/localization/generated/it.ts +30 -29
  43. package/localization/generated/ja.ts +30 -29
  44. package/localization/generated/ko.ts +30 -29
  45. package/localization/generated/locale-codes.js +79 -79
  46. package/localization/generated/lt.ts +30 -29
  47. package/localization/generated/lv.ts +30 -29
  48. package/localization/generated/nb.ts +30 -29
  49. package/localization/generated/nl.ts +30 -29
  50. package/localization/generated/pl.ts +30 -29
  51. package/localization/generated/pt-BR.ts +30 -29
  52. package/localization/generated/pt-PT.ts +30 -29
  53. package/localization/generated/ro.ts +30 -29
  54. package/localization/generated/ru.ts +30 -29
  55. package/localization/generated/sk.ts +30 -29
  56. package/localization/generated/sl.ts +30 -29
  57. package/localization/generated/sv.ts +30 -29
  58. package/localization/generated/tr.ts +30 -29
  59. package/localization/generated/uk.ts +30 -29
  60. package/localization/generated/zh-hans.ts +30 -29
  61. package/localization/hu.xlf +72 -69
  62. package/localization/id.xlf +72 -69
  63. package/localization/it.xlf +72 -69
  64. package/localization/ja.xlf +72 -69
  65. package/localization/ko.xlf +72 -69
  66. package/localization/lt.xlf +72 -69
  67. package/localization/lv.xlf +72 -69
  68. package/localization/nb.xlf +72 -69
  69. package/localization/nl.xlf +72 -69
  70. package/localization/pl.xlf +72 -69
  71. package/localization/pt-BR.xlf +72 -69
  72. package/localization/pt-PT.xlf +72 -69
  73. package/localization/ro.xlf +72 -69
  74. package/localization/ru.xlf +72 -69
  75. package/localization/sk.xlf +72 -69
  76. package/localization/sl.xlf +72 -69
  77. package/localization/sv.xlf +72 -69
  78. package/localization/tr.xlf +72 -69
  79. package/localization/uk.xlf +72 -69
  80. package/localization/zh-hans.xlf +72 -69
  81. package/package.json +4 -3
  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 +256 -253
  97. package/src/widgets/webwriter-choice.ts +352 -336
  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 +440 -440
  102. package/src/widgets/webwriter-order.ts +326 -309
  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 +554 -546
  111. package/src/widgets/webwriter-text.ts +176 -155
  112. package/tsconfig.json +6 -6
@@ -1,216 +1,216 @@
1
- import {LitElement, html, css, RenderOptions} from "lit"
2
- import {LitElementWw} from "@webwriter/lit"
3
- import {customElement, query} from "lit/decorators.js"
4
-
5
- import SlIconButton from "@shoelace-style/shoelace/dist/components/icon-button/icon-button.component.js"
6
- import SlOption from "@shoelace-style/shoelace/dist/components/option/option.component.js"
7
- import IconPlus from "bootstrap-icons/icons/plus.svg"
8
- import IconSlashCircle from "bootstrap-icons/icons/slash-circle.svg"
9
- import IconCheckCircle from "bootstrap-icons/icons/check-circle.svg"
10
- import IconX from "bootstrap-icons/icons/x.svg"
11
-
12
- import { Combobox } from "../lib/combobox"
13
- import { property } from "lit/decorators/property.js"
14
- import { queryAsync } from "lit/decorators/query-async.js"
15
- import "@shoelace-style/shoelace/dist/themes/light.css"
16
-
17
- import LOCALIZE from "../../localization/generated"
18
- import {msg} from "@lit/localize"
19
-
20
- declare global {interface HTMLElementTagNameMap {
21
- "webwriter-cloze-gap": WebwriterClozeGap;
22
- }}
23
-
24
- @customElement("webwriter-cloze-gap")
25
- export class WebwriterClozeGap extends LitElementWw {
26
-
27
- localize = LOCALIZE
28
-
29
- @property({type: Array, attribute: true, reflect: true})
30
- accessor solution: string[]
31
-
32
- @property({type: String, attribute: true, reflect: true})
33
- accessor value: string
34
-
35
- @property({type: Array, attribute: true, reflect: true})
36
- accessor distraction: string[] = []
37
-
38
- @property({type: Boolean, attribute: true, reflect: true})
39
- accessor showOptions = false
40
-
41
- static scopedElements = {
42
- "ww-combobox": Combobox,
43
- "sl-icon-button": SlIconButton,
44
- "sl-option": SlOption
45
- }
46
-
47
- static styles = css`
48
- :host {
49
- display: inline-block !important;
50
- vertical-align: top;
51
- margin: 0 1ch;
52
- max-width: calc(100% - 2ch);
53
- max-height: 1lh;
54
- }
55
-
56
- :host(::after) {
57
- content: " ";
58
- display: block;
59
- }
60
-
61
- sl-icon-button[data-hidden] {
62
- visibility: hidden;
63
- }
64
-
65
- sl-icon-button::part(base) {
66
- padding: 0;
67
- }
68
-
69
- :host(:not(:focus-within)) #add {
70
- visibility: hidden;
71
- }
72
-
73
- sl-icon-button {
74
- overflow: visible;
75
- margin-right: 0;
76
- }
77
-
78
- ww-combobox::part(base) {
79
- min-height: unset;
80
- padding: 2px 2px;
81
- }
82
-
83
- :host(:is([contenteditable=true], [contenteditable=""])) ww-combobox::part(input) {
84
- color: var(--sl-color-success-700);
85
- }
86
-
87
- sl-option::part(base) {
88
- padding: 0;
89
- font-size: var(--sl-input-font-size-small);
90
- }
91
-
92
- sl-option::part(label) {
93
- padding: var(--sl-spacing-2x-small) 0;
94
- }
95
-
96
- sl-option::part(label):hover {
97
- color: var(--sl-color-primary-600);
98
- }
99
-
100
- sl-option::part(checked-icon) {
101
- display: none;
102
- }
103
-
104
- .remove::part(base):hover {
105
- color: var(--sl-color-danger-600) !important;
106
- }
107
-
108
- .remove::part(base):active {
109
- color: var(--sl-color-danger-800) !important;
110
- }
111
-
112
- :is(.toggle, .remove)::part(base) {
113
- padding: var(--sl-spacing-2x-small);
114
- }
115
-
116
- .solution::part(base) {
117
- color: var(--sl-color-success-700);
118
- }
119
-
120
- .toggle {
121
- color: inherit;
122
- }
123
-
124
-
125
- `
126
- @query("ww-combobox")
127
- accessor input: Combobox
128
-
129
- async focus() {
130
- (await this.input).focus()
131
- }
132
-
133
- handleChange = (e: CustomEvent) => {
134
- e.preventDefault()
135
- if(!this.isContentEditable) {
136
- this.value = this.input.value as string
137
- }
138
- }
139
-
140
- addSolution(value: string) {
141
- this.solution = Array.from(new Set([...(this.solution ?? []), value]))
142
- }
143
-
144
- toggleOptionType(value: string) {
145
- if(this.solution.includes(value)) {
146
- this.solution = this.solution.filter(v => v !== value)
147
- this.distraction = Array.from(new Set([...(this.distraction ?? []), value]))
148
- }
149
- else if(this.distraction.includes(value)) {
150
- this.distraction = this.distraction.filter(v => v !== value)
151
- this.solution = Array.from(new Set([...(this.solution ?? []), value]))
152
- }
153
- }
154
-
155
- removeOption(value: string) {
156
- this.solution = this.solution.filter(v => v !== value)
157
- this.distraction = this.distraction.filter(v => v !== value)
158
- if(this.allOptions.length === 0) {
159
- this.isAdding = false
160
- }
161
- }
162
-
163
- handleAddClick = (e: MouseEvent) => {
164
- e.stopImmediatePropagation()
165
- e.preventDefault()
166
- this.addSolution(this.input.value as string)
167
- this.isAdding = true
168
- this.input.value = ""
169
- this.input.open = true
170
- }
171
-
172
- handleToggleClick = (e: MouseEvent, value: string) => {
173
- e.stopImmediatePropagation()
174
- e.preventDefault()
175
- this.toggleOptionType(value)
176
- }
177
-
178
- handleRemoveClick = (e: MouseEvent, value: string) => {
179
- e.stopImmediatePropagation()
180
- e.preventDefault()
181
- this.removeOption(value)
182
- }
183
-
184
- handleKeydown = (e: KeyboardEvent) => {
185
- if(e.key === "Enter") {
186
- this.handleAddClick(e as any)
187
- }
188
- }
189
-
190
- handleBlur = (e: FocusEvent) => {
191
- this.isAdding = false
192
- if(this.solution.length === 1) {
193
- this.input.value = this.solution[0]
194
- }
195
- }
196
-
197
- get allOptions() {
198
- return [...(this.solution ?? []), ...this.distraction]
199
- }
200
-
201
- @property({type: Boolean, attribute: false})
202
- accessor isAdding = false
203
-
204
- render() {
205
- return html`<ww-combobox @blur=${this.handleBlur} ?suggestions=${this.allOptions.length > 1 || this.isAdding || this.distraction.length > 0} size="small" autosize .value=${this.value} @sl-change=${this.handleChange} @sl-input=${() => this.requestUpdate()} @keydown=${this.handleKeydown} >
206
- <sl-icon-button id="add" title="Add another solution" ?disabled=${this.allOptions.includes(this.input?.value as string)} ?data-hidden=${!this.input?.value} src=${IconPlus} size="small" slot="prefix" @click=${this.handleAddClick} @mousedown=${(e: Event) => {e.stopPropagation(); e.preventDefault()}} @focus=${e => e.stopPropagation()} ></sl-icon-button>
207
- ${this.allOptions.sort().map(value => html`
208
- <sl-option size="small" value=${value} class=${this.solution.includes(value)? "solution": "distraction"} >
209
- <sl-icon-button title=${this.solution.includes(value)? "Change to a distraction": "Change to a solution"} class="toggle" slot="prefix" src=${this.solution.includes(value)? IconCheckCircle: IconSlashCircle} @click=${(e: any) => this.handleToggleClick(e, value)} @mousedown=${(e: Event) => {e.stopPropagation(); e.preventDefault()}}></sl-icon-button>
210
- <span title=${this.solution.includes(value)? "Solution": "Distraction"}>${value}</span>
211
- <sl-icon-button title="Remove" class="remove" slot="suffix" src=${IconX} @click=${(e: any) => this.handleRemoveClick(e, value)} @mousedown=${(e: Event) => {e.stopPropagation(); e.preventDefault()}}></sl-icon-button>
212
- </sl-option>
213
- `)}
214
- </ww-combobox>`
215
- }
1
+ import {LitElement, html, css, RenderOptions} from "lit"
2
+ import {LitElementWw} from "@webwriter/lit"
3
+ import {customElement, query} from "lit/decorators.js"
4
+
5
+ import SlIconButton from "@shoelace-style/shoelace/dist/components/icon-button/icon-button.component.js"
6
+ import SlOption from "@shoelace-style/shoelace/dist/components/option/option.component.js"
7
+ import IconPlus from "bootstrap-icons/icons/plus.svg"
8
+ import IconSlashCircle from "bootstrap-icons/icons/slash-circle.svg"
9
+ import IconCheckCircle from "bootstrap-icons/icons/check-circle.svg"
10
+ import IconX from "bootstrap-icons/icons/x.svg"
11
+
12
+ import { Combobox } from "../lib/combobox"
13
+ import { property } from "lit/decorators/property.js"
14
+ import { queryAsync } from "lit/decorators/query-async.js"
15
+ import "@shoelace-style/shoelace/dist/themes/light.css"
16
+
17
+ import LOCALIZE from "../../localization/generated"
18
+ import {msg} from "@lit/localize"
19
+
20
+ declare global {interface HTMLElementTagNameMap {
21
+ "webwriter-cloze-gap": WebwriterClozeGap;
22
+ }}
23
+
24
+ @customElement("webwriter-cloze-gap")
25
+ export class WebwriterClozeGap extends LitElementWw {
26
+
27
+ localize = LOCALIZE
28
+
29
+ @property({type: Array, attribute: true, reflect: true})
30
+ accessor solution: string[]
31
+
32
+ @property({type: String, attribute: true, reflect: true})
33
+ accessor value: string
34
+
35
+ @property({type: Array, attribute: true, reflect: true})
36
+ accessor distraction: string[] = []
37
+
38
+ @property({type: Boolean, attribute: true, reflect: true})
39
+ accessor showOptions = false
40
+
41
+ static scopedElements = {
42
+ "ww-combobox": Combobox,
43
+ "sl-icon-button": SlIconButton,
44
+ "sl-option": SlOption
45
+ }
46
+
47
+ static styles = css`
48
+ :host {
49
+ display: inline-block !important;
50
+ vertical-align: top;
51
+ margin: 0 1ch;
52
+ max-width: calc(100% - 2ch);
53
+ max-height: 1lh;
54
+ }
55
+
56
+ :host(::after) {
57
+ content: " ";
58
+ display: block;
59
+ }
60
+
61
+ sl-icon-button[data-hidden] {
62
+ visibility: hidden;
63
+ }
64
+
65
+ sl-icon-button::part(base) {
66
+ padding: 0;
67
+ }
68
+
69
+ :host(:not(:focus-within)) #add {
70
+ visibility: hidden;
71
+ }
72
+
73
+ sl-icon-button {
74
+ overflow: visible;
75
+ margin-right: 0;
76
+ }
77
+
78
+ ww-combobox::part(base) {
79
+ min-height: unset;
80
+ padding: 2px 2px;
81
+ }
82
+
83
+ :host(:is([contenteditable=true], [contenteditable=""])) ww-combobox::part(input) {
84
+ color: var(--sl-color-success-700);
85
+ }
86
+
87
+ sl-option::part(base) {
88
+ padding: 0;
89
+ font-size: var(--sl-input-font-size-small);
90
+ }
91
+
92
+ sl-option::part(label) {
93
+ padding: var(--sl-spacing-2x-small) 0;
94
+ }
95
+
96
+ sl-option::part(label):hover {
97
+ color: var(--sl-color-primary-600);
98
+ }
99
+
100
+ sl-option::part(checked-icon) {
101
+ display: none;
102
+ }
103
+
104
+ .remove::part(base):hover {
105
+ color: var(--sl-color-danger-600) !important;
106
+ }
107
+
108
+ .remove::part(base):active {
109
+ color: var(--sl-color-danger-800) !important;
110
+ }
111
+
112
+ :is(.toggle, .remove)::part(base) {
113
+ padding: var(--sl-spacing-2x-small);
114
+ }
115
+
116
+ .solution::part(base) {
117
+ color: var(--sl-color-success-700);
118
+ }
119
+
120
+ .toggle {
121
+ color: inherit;
122
+ }
123
+
124
+
125
+ `
126
+ @query("ww-combobox")
127
+ accessor input: Combobox
128
+
129
+ async focus() {
130
+ (await this.input).focus()
131
+ }
132
+
133
+ handleChange = (e: CustomEvent) => {
134
+ e.preventDefault()
135
+ if(!this.isContentEditable) {
136
+ this.value = this.input.value as string
137
+ }
138
+ }
139
+
140
+ addSolution(value: string) {
141
+ this.solution = Array.from(new Set([...(this.solution ?? []), value]))
142
+ }
143
+
144
+ toggleOptionType(value: string) {
145
+ if(this.solution.includes(value)) {
146
+ this.solution = this.solution.filter(v => v !== value)
147
+ this.distraction = Array.from(new Set([...(this.distraction ?? []), value]))
148
+ }
149
+ else if(this.distraction.includes(value)) {
150
+ this.distraction = this.distraction.filter(v => v !== value)
151
+ this.solution = Array.from(new Set([...(this.solution ?? []), value]))
152
+ }
153
+ }
154
+
155
+ removeOption(value: string) {
156
+ this.solution = this.solution.filter(v => v !== value)
157
+ this.distraction = this.distraction.filter(v => v !== value)
158
+ if(this.allOptions.length === 0) {
159
+ this.isAdding = false
160
+ }
161
+ }
162
+
163
+ handleAddClick = (e: MouseEvent) => {
164
+ e.stopImmediatePropagation()
165
+ e.preventDefault()
166
+ this.addSolution(this.input.value as string)
167
+ this.isAdding = true
168
+ this.input.value = ""
169
+ this.input.open = true
170
+ }
171
+
172
+ handleToggleClick = (e: MouseEvent, value: string) => {
173
+ e.stopImmediatePropagation()
174
+ e.preventDefault()
175
+ this.toggleOptionType(value)
176
+ }
177
+
178
+ handleRemoveClick = (e: MouseEvent, value: string) => {
179
+ e.stopImmediatePropagation()
180
+ e.preventDefault()
181
+ this.removeOption(value)
182
+ }
183
+
184
+ handleKeydown = (e: KeyboardEvent) => {
185
+ if(e.key === "Enter") {
186
+ this.handleAddClick(e as any)
187
+ }
188
+ }
189
+
190
+ handleBlur = (e: FocusEvent) => {
191
+ this.isAdding = false
192
+ if(this.solution.length === 1) {
193
+ this.input.value = this.solution[0]
194
+ }
195
+ }
196
+
197
+ get allOptions() {
198
+ return [...(this.solution ?? []), ...this.distraction]
199
+ }
200
+
201
+ @property({type: Boolean, attribute: false})
202
+ accessor isAdding = false
203
+
204
+ render() {
205
+ return html`<ww-combobox @blur=${this.handleBlur} ?suggestions=${this.allOptions.length > 1 || this.isAdding || this.distraction.length > 0} size="small" autosize .value=${this.value} @sl-change=${this.handleChange} @sl-input=${() => this.requestUpdate()} @keydown=${this.handleKeydown} >
206
+ <sl-icon-button id="add" title="Add another solution" ?disabled=${this.allOptions.includes(this.input?.value as string)} ?data-hidden=${!this.input?.value} src=${IconPlus} size="small" slot="prefix" @click=${this.handleAddClick} @mousedown=${(e: Event) => {e.stopPropagation(); e.preventDefault()}} @focus=${e => e.stopPropagation()} ></sl-icon-button>
207
+ ${this.allOptions.sort().map(value => html`
208
+ <sl-option size="small" value=${value} class=${this.solution.includes(value)? "solution": "distraction"} >
209
+ <sl-icon-button title=${this.solution.includes(value)? "Change to a distraction": "Change to a solution"} class="toggle" slot="prefix" src=${this.solution.includes(value)? IconCheckCircle: IconSlashCircle} @click=${(e: any) => this.handleToggleClick(e, value)} @mousedown=${(e: Event) => {e.stopPropagation(); e.preventDefault()}}></sl-icon-button>
210
+ <span title=${this.solution.includes(value)? "Solution": "Distraction"}>${value}</span>
211
+ <sl-icon-button title="Remove" class="remove" slot="suffix" src=${IconX} @click=${(e: any) => this.handleRemoveClick(e, value)} @mousedown=${(e: Event) => {e.stopPropagation(); e.preventDefault()}}></sl-icon-button>
212
+ </sl-option>
213
+ `)}
214
+ </ww-combobox>`
215
+ }
216
216
  }