@webwriter/quiz 1.0.4 → 1.0.6

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 (128) hide show
  1. package/LICENSE +6 -6
  2. package/custom.d.ts +175 -175
  3. package/dist/widgets/webwriter-choice-item.css +1 -1
  4. package/dist/widgets/webwriter-choice-item.js +1886 -802
  5. package/dist/widgets/webwriter-choice.css +1 -1
  6. package/dist/widgets/webwriter-choice.js +1943 -846
  7. package/dist/widgets/webwriter-cloze-gap.css +1 -1
  8. package/dist/widgets/webwriter-cloze-gap.js +1988 -902
  9. package/dist/widgets/webwriter-cloze.css +1 -1
  10. package/dist/widgets/webwriter-cloze.js +1833 -748
  11. package/dist/widgets/webwriter-mark.css +1 -1
  12. package/dist/widgets/webwriter-mark.js +1848 -762
  13. package/dist/widgets/webwriter-order-item.css +1 -1
  14. package/dist/widgets/webwriter-order-item.js +1884 -799
  15. package/dist/widgets/webwriter-order.css +1 -1
  16. package/dist/widgets/webwriter-order.js +1887 -2299
  17. package/dist/widgets/webwriter-pairing-item.css +1 -1
  18. package/dist/widgets/webwriter-pairing-item.js +1718 -614
  19. package/dist/widgets/webwriter-pairing.css +1 -1
  20. package/dist/widgets/webwriter-pairing.js +1873 -781
  21. package/dist/widgets/webwriter-quiz.css +1 -1
  22. package/dist/widgets/webwriter-quiz.js +2241 -1026
  23. package/dist/widgets/webwriter-speech.css +1 -1
  24. package/dist/widgets/webwriter-speech.js +2179 -961
  25. package/dist/widgets/webwriter-task-explainer.css +1 -1
  26. package/dist/widgets/webwriter-task-explainer.js +1704 -600
  27. package/dist/widgets/webwriter-task-hint.css +1 -1
  28. package/dist/widgets/webwriter-task-hint.js +1695 -591
  29. package/dist/widgets/webwriter-task-prompt.css +1 -1
  30. package/dist/widgets/webwriter-task-prompt.js +1670 -566
  31. package/dist/widgets/webwriter-task.css +1 -1
  32. package/dist/widgets/webwriter-task.js +2361 -1143
  33. package/dist/widgets/webwriter-text.css +1 -1
  34. package/dist/widgets/webwriter-text.js +1876 -770
  35. package/icon.svg +1 -0
  36. package/lit-localize.json +15 -0
  37. package/localization/bg.xlf +54 -0
  38. package/localization/cs.xlf +54 -0
  39. package/localization/da.xlf +54 -0
  40. package/localization/de.xlf +54 -0
  41. package/localization/el.xlf +54 -0
  42. package/localization/es.xlf +54 -0
  43. package/localization/et.xlf +54 -0
  44. package/localization/fi.xlf +54 -0
  45. package/localization/fr.xlf +54 -0
  46. package/localization/generated/bg.ts +25 -0
  47. package/localization/generated/cs.ts +25 -0
  48. package/localization/generated/da.ts +25 -0
  49. package/localization/generated/de.ts +25 -0
  50. package/localization/generated/el.ts +25 -0
  51. package/localization/generated/es.ts +25 -0
  52. package/localization/generated/et.ts +25 -0
  53. package/localization/generated/fi.ts +25 -0
  54. package/localization/generated/fr.ts +25 -0
  55. package/localization/generated/hu.ts +25 -0
  56. package/localization/generated/id.ts +25 -0
  57. package/localization/generated/index.js +3 -0
  58. package/localization/generated/it.ts +25 -0
  59. package/localization/generated/ja.ts +25 -0
  60. package/localization/generated/ko.ts +25 -0
  61. package/localization/generated/locale-codes.js +79 -0
  62. package/localization/generated/lt.ts +25 -0
  63. package/localization/generated/lv.ts +25 -0
  64. package/localization/generated/nb.ts +25 -0
  65. package/localization/generated/nl.ts +25 -0
  66. package/localization/generated/pl.ts +25 -0
  67. package/localization/generated/pt-BR.ts +25 -0
  68. package/localization/generated/pt-PT.ts +25 -0
  69. package/localization/generated/ro.ts +25 -0
  70. package/localization/generated/ru.ts +25 -0
  71. package/localization/generated/sk.ts +25 -0
  72. package/localization/generated/sl.ts +25 -0
  73. package/localization/generated/sv.ts +25 -0
  74. package/localization/generated/tr.ts +25 -0
  75. package/localization/generated/uk.ts +25 -0
  76. package/localization/generated/zh-hans.ts +25 -0
  77. package/localization/hu.xlf +54 -0
  78. package/localization/id.xlf +54 -0
  79. package/localization/it.xlf +54 -0
  80. package/localization/ja.xlf +54 -0
  81. package/localization/ko.xlf +54 -0
  82. package/localization/lt.xlf +54 -0
  83. package/localization/lv.xlf +54 -0
  84. package/localization/nb.xlf +54 -0
  85. package/localization/nl.xlf +54 -0
  86. package/localization/pl.xlf +54 -0
  87. package/localization/pt-BR.xlf +54 -0
  88. package/localization/pt-PT.xlf +54 -0
  89. package/localization/ro.xlf +54 -0
  90. package/localization/ru.xlf +54 -0
  91. package/localization/sk.xlf +54 -0
  92. package/localization/sl.xlf +54 -0
  93. package/localization/sv.xlf +54 -0
  94. package/localization/tr.xlf +54 -0
  95. package/localization/uk.xlf +54 -0
  96. package/localization/zh-hans.xlf +54 -0
  97. package/package.json +206 -198
  98. package/src/lib/combobox.ts +455 -455
  99. package/src/lib/highlighter-fill.svg +5 -5
  100. package/src/snippets/Beispiel-Choice.html +57 -0
  101. package/src/snippets/Beispiel-Mark.html +14 -0
  102. package/src/snippets/Beispiel-Order.html +52 -0
  103. package/src/snippets/Beispiel-Text.html +20 -0
  104. package/src/snippets/choice.html +7 -7
  105. package/src/snippets/cloze.html +3 -3
  106. package/src/snippets/mark.html +3 -3
  107. package/src/snippets/order.html +7 -7
  108. package/src/snippets/pairing.html +9 -9
  109. package/src/snippets/speech.html +3 -3
  110. package/src/snippets/text.html +3 -3
  111. package/src/snippets/wordsearch.html +3 -3
  112. package/src/widgets/webwriter-choice-item.ts +250 -250
  113. package/src/widgets/webwriter-choice.ts +314 -309
  114. package/src/widgets/webwriter-cloze-gap.ts +215 -216
  115. package/src/widgets/webwriter-cloze.ts +135 -135
  116. package/src/widgets/webwriter-mark.ts +431 -434
  117. package/src/widgets/webwriter-order-item.ts +437 -444
  118. package/src/widgets/webwriter-order.ts +284 -272
  119. package/src/widgets/webwriter-pairing-item.ts +160 -155
  120. package/src/widgets/webwriter-pairing.ts +192 -187
  121. package/src/widgets/webwriter-quiz.ts +281 -280
  122. package/src/widgets/webwriter-speech.ts +272 -267
  123. package/src/widgets/webwriter-task-explainer.ts +42 -37
  124. package/src/widgets/webwriter-task-hint.ts +22 -16
  125. package/src/widgets/webwriter-task-prompt.ts +23 -17
  126. package/src/widgets/webwriter-task.ts +546 -543
  127. package/src/widgets/webwriter-text.ts +135 -130
  128. 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
-
17
- declare global {interface HTMLElementTagNameMap {
18
- "webwriter-choice-item": WebwriterChoiceItem;
19
- }}
20
-
21
- @customElement("webwriter-choice-item")
22
- export class WebwriterChoiceItem extends LitElementWw {
23
-
24
- static localization = {}
25
-
26
- msg = (str: string) => this.lang in WebwriterChoiceItem.localization? WebwriterChoiceItem.localization[this.lang][str] ?? str: str
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": `"${this.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
  }