@fiscozen/checkbox 0.1.6 → 0.2.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/.eslintrc.cjs +19 -0
- package/.prettierrc.js +6 -0
- package/README.md +514 -0
- package/coverage/clover.xml +789 -215
- package/coverage/coverage-final.json +6 -6
- package/coverage/index.html +32 -32
- package/coverage/src/FzCheckbox.vue.html +1099 -151
- package/coverage/src/FzCheckboxGroup.vue.html +444 -81
- package/coverage/src/common.ts.html +79 -19
- package/coverage/src/components/ErrorAlert.vue.html +268 -0
- package/coverage/src/components/FzCheckboxGroupOption.vue.html +343 -70
- package/coverage/src/components/index.html +22 -22
- package/coverage/src/index.html +45 -45
- package/coverage/src/utils.ts.html +265 -0
- package/package.json +13 -11
- package/src/FzCheckbox.vue +411 -95
- package/src/FzCheckboxGroup.vue +179 -58
- package/src/__test__/FzCheckbox.test.ts +91 -19
- package/src/__test__/FzCheckboxGroup.test.ts +167 -4
- package/src/common.ts +20 -0
- package/src/components/ErrorAlert.vue +61 -0
- package/src/components/FzCheckboxGroupOption.vue +137 -46
- package/src/index.ts +1 -0
- package/src/types.ts +166 -23
- package/src/utils.ts +60 -0
- package/tsconfig.json +1 -1
- package/coverage/.tmp/coverage-0.json +0 -1
- package/coverage/.tmp/coverage-1.json +0 -1
- package/coverage/src/components/FzCheckboxErrorText.vue.html +0 -145
- package/coverage/src/types.ts.html +0 -310
- package/dist/checkbox.js +0 -301
- package/dist/checkbox.umd.cjs +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/src/FzCheckbox.vue.d.ts +0 -95
- package/dist/src/FzCheckboxGroup.vue.d.ts +0 -70
- package/dist/src/__test__/FzCheckbox.test.d.ts +0 -1
- package/dist/src/__test__/FzCheckboxGroup.test.d.ts +0 -1
- package/dist/src/common.d.ts +0 -4
- package/dist/src/components/FzCheckboxErrorText.vue.d.ts +0 -24
- package/dist/src/components/FzCheckboxGroupOption.vue.d.ts +0 -82
- package/dist/src/index.d.ts +0 -3
- package/dist/src/types.d.ts +0 -76
- package/dist/style.css +0 -1
- package/src/components/FzCheckboxErrorText.vue +0 -20
|
@@ -23,30 +23,30 @@
|
|
|
23
23
|
<div class='clearfix'>
|
|
24
24
|
|
|
25
25
|
<div class='fl pad1y space-right2'>
|
|
26
|
-
<span class="strong">
|
|
26
|
+
<span class="strong">79.89% </span>
|
|
27
27
|
<span class="quiet">Statements</span>
|
|
28
|
-
<span class='fraction'>
|
|
28
|
+
<span class='fraction'>151/189</span>
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
<div class='fl pad1y space-right2'>
|
|
33
|
-
<span class="strong">
|
|
33
|
+
<span class="strong">86.66% </span>
|
|
34
34
|
<span class="quiet">Branches</span>
|
|
35
|
-
<span class='fraction'>
|
|
35
|
+
<span class='fraction'>13/15</span>
|
|
36
36
|
</div>
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
<div class='fl pad1y space-right2'>
|
|
40
40
|
<span class="strong">0% </span>
|
|
41
41
|
<span class="quiet">Functions</span>
|
|
42
|
-
<span class='fraction'>0/
|
|
42
|
+
<span class='fraction'>0/4</span>
|
|
43
43
|
</div>
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
<div class='fl pad1y space-right2'>
|
|
47
|
-
<span class="strong">
|
|
47
|
+
<span class="strong">79.89% </span>
|
|
48
48
|
<span class="quiet">Lines</span>
|
|
49
|
-
<span class='fraction'>
|
|
49
|
+
<span class='fraction'>151/189</span>
|
|
50
50
|
</div>
|
|
51
51
|
|
|
52
52
|
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
<template id="filterTemplate">
|
|
58
58
|
<div class="quiet">
|
|
59
59
|
Filter:
|
|
60
|
-
<input
|
|
60
|
+
<input type="search" id="fileSearch">
|
|
61
61
|
</div>
|
|
62
62
|
</template>
|
|
63
63
|
</div>
|
|
@@ -161,7 +161,98 @@
|
|
|
161
161
|
<a name='L96'></a><a href='#L96'>96</a>
|
|
162
162
|
<a name='L97'></a><a href='#L97'>97</a>
|
|
163
163
|
<a name='L98'></a><a href='#L98'>98</a>
|
|
164
|
-
<a name='L99'></a><a href='#L99'>99</a
|
|
164
|
+
<a name='L99'></a><a href='#L99'>99</a>
|
|
165
|
+
<a name='L100'></a><a href='#L100'>100</a>
|
|
166
|
+
<a name='L101'></a><a href='#L101'>101</a>
|
|
167
|
+
<a name='L102'></a><a href='#L102'>102</a>
|
|
168
|
+
<a name='L103'></a><a href='#L103'>103</a>
|
|
169
|
+
<a name='L104'></a><a href='#L104'>104</a>
|
|
170
|
+
<a name='L105'></a><a href='#L105'>105</a>
|
|
171
|
+
<a name='L106'></a><a href='#L106'>106</a>
|
|
172
|
+
<a name='L107'></a><a href='#L107'>107</a>
|
|
173
|
+
<a name='L108'></a><a href='#L108'>108</a>
|
|
174
|
+
<a name='L109'></a><a href='#L109'>109</a>
|
|
175
|
+
<a name='L110'></a><a href='#L110'>110</a>
|
|
176
|
+
<a name='L111'></a><a href='#L111'>111</a>
|
|
177
|
+
<a name='L112'></a><a href='#L112'>112</a>
|
|
178
|
+
<a name='L113'></a><a href='#L113'>113</a>
|
|
179
|
+
<a name='L114'></a><a href='#L114'>114</a>
|
|
180
|
+
<a name='L115'></a><a href='#L115'>115</a>
|
|
181
|
+
<a name='L116'></a><a href='#L116'>116</a>
|
|
182
|
+
<a name='L117'></a><a href='#L117'>117</a>
|
|
183
|
+
<a name='L118'></a><a href='#L118'>118</a>
|
|
184
|
+
<a name='L119'></a><a href='#L119'>119</a>
|
|
185
|
+
<a name='L120'></a><a href='#L120'>120</a>
|
|
186
|
+
<a name='L121'></a><a href='#L121'>121</a>
|
|
187
|
+
<a name='L122'></a><a href='#L122'>122</a>
|
|
188
|
+
<a name='L123'></a><a href='#L123'>123</a>
|
|
189
|
+
<a name='L124'></a><a href='#L124'>124</a>
|
|
190
|
+
<a name='L125'></a><a href='#L125'>125</a>
|
|
191
|
+
<a name='L126'></a><a href='#L126'>126</a>
|
|
192
|
+
<a name='L127'></a><a href='#L127'>127</a>
|
|
193
|
+
<a name='L128'></a><a href='#L128'>128</a>
|
|
194
|
+
<a name='L129'></a><a href='#L129'>129</a>
|
|
195
|
+
<a name='L130'></a><a href='#L130'>130</a>
|
|
196
|
+
<a name='L131'></a><a href='#L131'>131</a>
|
|
197
|
+
<a name='L132'></a><a href='#L132'>132</a>
|
|
198
|
+
<a name='L133'></a><a href='#L133'>133</a>
|
|
199
|
+
<a name='L134'></a><a href='#L134'>134</a>
|
|
200
|
+
<a name='L135'></a><a href='#L135'>135</a>
|
|
201
|
+
<a name='L136'></a><a href='#L136'>136</a>
|
|
202
|
+
<a name='L137'></a><a href='#L137'>137</a>
|
|
203
|
+
<a name='L138'></a><a href='#L138'>138</a>
|
|
204
|
+
<a name='L139'></a><a href='#L139'>139</a>
|
|
205
|
+
<a name='L140'></a><a href='#L140'>140</a>
|
|
206
|
+
<a name='L141'></a><a href='#L141'>141</a>
|
|
207
|
+
<a name='L142'></a><a href='#L142'>142</a>
|
|
208
|
+
<a name='L143'></a><a href='#L143'>143</a>
|
|
209
|
+
<a name='L144'></a><a href='#L144'>144</a>
|
|
210
|
+
<a name='L145'></a><a href='#L145'>145</a>
|
|
211
|
+
<a name='L146'></a><a href='#L146'>146</a>
|
|
212
|
+
<a name='L147'></a><a href='#L147'>147</a>
|
|
213
|
+
<a name='L148'></a><a href='#L148'>148</a>
|
|
214
|
+
<a name='L149'></a><a href='#L149'>149</a>
|
|
215
|
+
<a name='L150'></a><a href='#L150'>150</a>
|
|
216
|
+
<a name='L151'></a><a href='#L151'>151</a>
|
|
217
|
+
<a name='L152'></a><a href='#L152'>152</a>
|
|
218
|
+
<a name='L153'></a><a href='#L153'>153</a>
|
|
219
|
+
<a name='L154'></a><a href='#L154'>154</a>
|
|
220
|
+
<a name='L155'></a><a href='#L155'>155</a>
|
|
221
|
+
<a name='L156'></a><a href='#L156'>156</a>
|
|
222
|
+
<a name='L157'></a><a href='#L157'>157</a>
|
|
223
|
+
<a name='L158'></a><a href='#L158'>158</a>
|
|
224
|
+
<a name='L159'></a><a href='#L159'>159</a>
|
|
225
|
+
<a name='L160'></a><a href='#L160'>160</a>
|
|
226
|
+
<a name='L161'></a><a href='#L161'>161</a>
|
|
227
|
+
<a name='L162'></a><a href='#L162'>162</a>
|
|
228
|
+
<a name='L163'></a><a href='#L163'>163</a>
|
|
229
|
+
<a name='L164'></a><a href='#L164'>164</a>
|
|
230
|
+
<a name='L165'></a><a href='#L165'>165</a>
|
|
231
|
+
<a name='L166'></a><a href='#L166'>166</a>
|
|
232
|
+
<a name='L167'></a><a href='#L167'>167</a>
|
|
233
|
+
<a name='L168'></a><a href='#L168'>168</a>
|
|
234
|
+
<a name='L169'></a><a href='#L169'>169</a>
|
|
235
|
+
<a name='L170'></a><a href='#L170'>170</a>
|
|
236
|
+
<a name='L171'></a><a href='#L171'>171</a>
|
|
237
|
+
<a name='L172'></a><a href='#L172'>172</a>
|
|
238
|
+
<a name='L173'></a><a href='#L173'>173</a>
|
|
239
|
+
<a name='L174'></a><a href='#L174'>174</a>
|
|
240
|
+
<a name='L175'></a><a href='#L175'>175</a>
|
|
241
|
+
<a name='L176'></a><a href='#L176'>176</a>
|
|
242
|
+
<a name='L177'></a><a href='#L177'>177</a>
|
|
243
|
+
<a name='L178'></a><a href='#L178'>178</a>
|
|
244
|
+
<a name='L179'></a><a href='#L179'>179</a>
|
|
245
|
+
<a name='L180'></a><a href='#L180'>180</a>
|
|
246
|
+
<a name='L181'></a><a href='#L181'>181</a>
|
|
247
|
+
<a name='L182'></a><a href='#L182'>182</a>
|
|
248
|
+
<a name='L183'></a><a href='#L183'>183</a>
|
|
249
|
+
<a name='L184'></a><a href='#L184'>184</a>
|
|
250
|
+
<a name='L185'></a><a href='#L185'>185</a>
|
|
251
|
+
<a name='L186'></a><a href='#L186'>186</a>
|
|
252
|
+
<a name='L187'></a><a href='#L187'>187</a>
|
|
253
|
+
<a name='L188'></a><a href='#L188'>188</a>
|
|
254
|
+
<a name='L189'></a><a href='#L189'>189</a>
|
|
255
|
+
<a name='L190'></a><a href='#L190'>190</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">18x</span>
|
|
165
256
|
<span class="cline-any cline-yes">1x</span>
|
|
166
257
|
<span class="cline-any cline-yes">1x</span>
|
|
167
258
|
<span class="cline-any cline-yes">1x</span>
|
|
@@ -209,19 +300,53 @@
|
|
|
209
300
|
<span class="cline-any cline-yes">1x</span>
|
|
210
301
|
<span class="cline-any cline-yes">1x</span>
|
|
211
302
|
<span class="cline-any cline-yes">1x</span>
|
|
212
|
-
<span class="cline-any cline-no"> </span>
|
|
213
|
-
<span class="cline-any cline-no"> </span>
|
|
214
303
|
<span class="cline-any cline-yes">1x</span>
|
|
215
304
|
<span class="cline-any cline-yes">1x</span>
|
|
216
305
|
<span class="cline-any cline-yes">1x</span>
|
|
217
|
-
<span class="cline-any cline-yes">
|
|
218
|
-
<span class="cline-any cline-
|
|
219
|
-
<span class="cline-any cline-
|
|
306
|
+
<span class="cline-any cline-yes">1x</span>
|
|
307
|
+
<span class="cline-any cline-yes">1x</span>
|
|
308
|
+
<span class="cline-any cline-yes">1x</span>
|
|
309
|
+
<span class="cline-any cline-yes">1x</span>
|
|
310
|
+
<span class="cline-any cline-yes">1x</span>
|
|
311
|
+
<span class="cline-any cline-yes">1x</span>
|
|
312
|
+
<span class="cline-any cline-yes">1x</span>
|
|
313
|
+
<span class="cline-any cline-yes">1x</span>
|
|
314
|
+
<span class="cline-any cline-yes">1x</span>
|
|
315
|
+
<span class="cline-any cline-yes">1x</span>
|
|
316
|
+
<span class="cline-any cline-yes">1x</span>
|
|
317
|
+
<span class="cline-any cline-yes">1x</span>
|
|
318
|
+
<span class="cline-any cline-yes">1x</span>
|
|
319
|
+
<span class="cline-any cline-yes">1x</span>
|
|
320
|
+
<span class="cline-any cline-yes">1x</span>
|
|
321
|
+
<span class="cline-any cline-yes">1x</span>
|
|
322
|
+
<span class="cline-any cline-yes">1x</span>
|
|
323
|
+
<span class="cline-any cline-yes">1x</span>
|
|
324
|
+
<span class="cline-any cline-yes">1x</span>
|
|
325
|
+
<span class="cline-any cline-yes">1x</span>
|
|
326
|
+
<span class="cline-any cline-yes">1x</span>
|
|
327
|
+
<span class="cline-any cline-yes">1x</span>
|
|
328
|
+
<span class="cline-any cline-yes">1x</span>
|
|
329
|
+
<span class="cline-any cline-yes">19x</span>
|
|
330
|
+
<span class="cline-any cline-yes">1x</span>
|
|
331
|
+
<span class="cline-any cline-yes">1x</span>
|
|
332
|
+
<span class="cline-any cline-yes">2x</span>
|
|
333
|
+
<span class="cline-any cline-yes">1x</span>
|
|
334
|
+
<span class="cline-any cline-yes">19x</span>
|
|
335
|
+
<span class="cline-any cline-yes">1x</span>
|
|
336
|
+
<span class="cline-any cline-yes">1x</span>
|
|
337
|
+
<span class="cline-any cline-yes">1x</span>
|
|
338
|
+
<span class="cline-any cline-yes">1x</span>
|
|
339
|
+
<span class="cline-any cline-yes">1x</span>
|
|
340
|
+
<span class="cline-any cline-yes">1x</span>
|
|
341
|
+
<span class="cline-any cline-yes">1x</span>
|
|
342
|
+
<span class="cline-any cline-yes">1x</span>
|
|
343
|
+
<span class="cline-any cline-yes">1x</span>
|
|
344
|
+
<span class="cline-any cline-yes">1x</span>
|
|
345
|
+
<span class="cline-any cline-yes">1x</span>
|
|
346
|
+
<span class="cline-any cline-yes">1x</span>
|
|
220
347
|
<span class="cline-any cline-no"> </span>
|
|
221
348
|
<span class="cline-any cline-no"> </span>
|
|
222
349
|
<span class="cline-any cline-no"> </span>
|
|
223
|
-
<span class="cline-any cline-yes">1x</span>
|
|
224
|
-
<span class="cline-any cline-yes">1x</span>
|
|
225
350
|
<span class="cline-any cline-no"> </span>
|
|
226
351
|
<span class="cline-any cline-no"> </span>
|
|
227
352
|
<span class="cline-any cline-no"> </span>
|
|
@@ -238,6 +363,17 @@
|
|
|
238
363
|
<span class="cline-any cline-no"> </span>
|
|
239
364
|
<span class="cline-any cline-no"> </span>
|
|
240
365
|
<span class="cline-any cline-yes">1x</span>
|
|
366
|
+
<span class="cline-any cline-yes">1x</span>
|
|
367
|
+
<span class="cline-any cline-yes">1x</span>
|
|
368
|
+
<span class="cline-any cline-yes">1x</span>
|
|
369
|
+
<span class="cline-any cline-yes">1x</span>
|
|
370
|
+
<span class="cline-any cline-yes">1x</span>
|
|
371
|
+
<span class="cline-any cline-yes">1x</span>
|
|
372
|
+
<span class="cline-any cline-yes">1x</span>
|
|
373
|
+
<span class="cline-any cline-yes">1x</span>
|
|
374
|
+
<span class="cline-any cline-yes">1x</span>
|
|
375
|
+
<span class="cline-any cline-yes">1x</span>
|
|
376
|
+
<span class="cline-any cline-no"> </span>
|
|
241
377
|
<span class="cline-any cline-no"> </span>
|
|
242
378
|
<span class="cline-any cline-no"> </span>
|
|
243
379
|
<span class="cline-any cline-no"> </span>
|
|
@@ -259,94 +395,185 @@
|
|
|
259
395
|
<span class="cline-any cline-no"> </span>
|
|
260
396
|
<span class="cline-any cline-yes">1x</span>
|
|
261
397
|
<span class="cline-any cline-yes">1x</span>
|
|
262
|
-
<span class="cline-any cline-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
398
|
+
<span class="cline-any cline-yes">1x</span>
|
|
399
|
+
<span class="cline-any cline-yes">1x</span>
|
|
400
|
+
<span class="cline-any cline-yes">1x</span>
|
|
401
|
+
<span class="cline-any cline-yes">1x</span>
|
|
402
|
+
<span class="cline-any cline-yes">1x</span>
|
|
403
|
+
<span class="cline-any cline-yes">1x</span>
|
|
404
|
+
<span class="cline-any cline-yes">1x</span>
|
|
405
|
+
<span class="cline-any cline-yes">1x</span>
|
|
406
|
+
<span class="cline-any cline-yes">1x</span>
|
|
407
|
+
<span class="cline-any cline-yes">1x</span>
|
|
408
|
+
<span class="cline-any cline-yes">1x</span>
|
|
409
|
+
<span class="cline-any cline-yes">1x</span>
|
|
410
|
+
<span class="cline-any cline-yes">1x</span>
|
|
411
|
+
<span class="cline-any cline-yes">1x</span>
|
|
412
|
+
<span class="cline-any cline-yes">1x</span>
|
|
413
|
+
<span class="cline-any cline-yes">1x</span>
|
|
414
|
+
<span class="cline-any cline-yes">1x</span>
|
|
415
|
+
<span class="cline-any cline-yes">1x</span>
|
|
416
|
+
<span class="cline-any cline-yes">1x</span>
|
|
417
|
+
<span class="cline-any cline-yes">1x</span>
|
|
418
|
+
<span class="cline-any cline-yes">1x</span>
|
|
419
|
+
<span class="cline-any cline-yes">1x</span>
|
|
420
|
+
<span class="cline-any cline-yes">1x</span>
|
|
421
|
+
<span class="cline-any cline-yes">1x</span>
|
|
422
|
+
<span class="cline-any cline-yes">1x</span>
|
|
423
|
+
<span class="cline-any cline-yes">1x</span>
|
|
424
|
+
<span class="cline-any cline-yes">1x</span>
|
|
425
|
+
<span class="cline-any cline-yes">1x</span>
|
|
426
|
+
<span class="cline-any cline-yes">1x</span>
|
|
427
|
+
<span class="cline-any cline-yes">1x</span>
|
|
428
|
+
<span class="cline-any cline-yes">1x</span>
|
|
429
|
+
<span class="cline-any cline-yes">1x</span>
|
|
430
|
+
<span class="cline-any cline-yes">1x</span>
|
|
431
|
+
<span class="cline-any cline-yes">1x</span>
|
|
432
|
+
<span class="cline-any cline-yes">1x</span>
|
|
433
|
+
<span class="cline-any cline-yes">1x</span>
|
|
434
|
+
<span class="cline-any cline-yes">1x</span>
|
|
435
|
+
<span class="cline-any cline-yes">1x</span>
|
|
436
|
+
<span class="cline-any cline-yes">1x</span>
|
|
437
|
+
<span class="cline-any cline-yes">1x</span>
|
|
438
|
+
<span class="cline-any cline-yes">1x</span>
|
|
439
|
+
<span class="cline-any cline-yes">1x</span>
|
|
440
|
+
<span class="cline-any cline-yes">1x</span>
|
|
441
|
+
<span class="cline-any cline-yes">1x</span>
|
|
442
|
+
<span class="cline-any cline-yes">1x</span>
|
|
443
|
+
<span class="cline-any cline-yes">1x</span>
|
|
444
|
+
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js"><script setup lang="ts">
|
|
445
|
+
/**
|
|
446
|
+
* FzCheckboxGroupOption Component
|
|
447
|
+
*
|
|
448
|
+
* Renders a single checkbox option within a checkbox group, with support for
|
|
449
|
+
* hierarchical parent-child relationships. When children are present, the parent
|
|
450
|
+
* checkbox displays an indeterminate state when partially selected.
|
|
451
|
+
*
|
|
452
|
+
* Key features:
|
|
453
|
+
* - Automatic indeterminate state management for parent checkboxes
|
|
454
|
+
* - Bi-directional sync: parent controls children, children update parent
|
|
455
|
+
* - ARIA relationships via aria-owns for accessibility
|
|
456
|
+
* - Deterministic IDs for proper ARIA associations
|
|
457
|
+
*
|
|
458
|
+
* @component
|
|
459
|
+
* @internal Used internally by FzCheckboxGroup, not intended for direct use
|
|
460
|
+
*/
|
|
292
461
|
import { computed } from "vue";
|
|
293
462
|
import FzCheckbox from "../FzCheckbox.vue";
|
|
294
463
|
import { ParentCheckbox } from "../types";
|
|
464
|
+
import { generateCheckboxId } from "../utils";
|
|
295
465
|
|
|
296
|
-
|
|
297
|
-
MODE: 3,
|
|
298
|
-
};
|
|
466
|
+
const props = defineProps<ParentCheckbox>();
|
|
299
467
|
|
|
300
|
-
|
|
301
|
-
const currentValue = computed
|
|
468
|
+
/** The actual value used for this checkbox (falls back to label if no value provided) */
|
|
469
|
+
const currentValue = computed<string | number | boolean>(
|
|
470
|
+
() => props.value ?? props.label,
|
|
471
|
+
);
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Two-way binding for selected values.
|
|
475
|
+
* Shared with parent component and all sibling checkboxes.
|
|
476
|
+
*/
|
|
302
477
|
const model = defineModel<(string | number | boolean)[]>({
|
|
303
478
|
required: true,
|
|
304
479
|
default: [],
|
|
305
480
|
});
|
|
306
481
|
|
|
307
|
-
|
|
482
|
+
/**
|
|
483
|
+
* Unique identifier for this parent checkbox.
|
|
484
|
+
* Used as a prefix for child checkbox IDs to establish ARIA relationships.
|
|
485
|
+
*/
|
|
486
|
+
const parentId: string = generateCheckboxId();
|
|
308
487
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
488
|
+
/**
|
|
489
|
+
* Computes space-separated list of child checkbox IDs.
|
|
490
|
+
* Used for aria-owns attribute to establish semantic parent-child relationship.
|
|
491
|
+
*
|
|
492
|
+
* @returns Space-separated string of child IDs, or undefined if no children
|
|
493
|
+
*/
|
|
494
|
+
const childrenIds = computed<string | undefined>(() =>
|
|
495
|
+
props.children?.map((child, index) => `${parentId}-child-${index}`).join(" "),
|
|
496
|
+
);
|
|
313
497
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
498
|
+
/** Base layout classes for the children container (indented and vertical) */
|
|
499
|
+
const staticChildContainerClass: string =
|
|
500
|
+
"flex flex-col justify-center gap-8 pl-24";
|
|
501
|
+
|
|
502
|
+
/** Size-specific spacing for child checkboxes */
|
|
503
|
+
const computedChildContainerClasses = computed<string[]>(() => []);
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Determines if parent checkbox should be in indeterminate state.
|
|
507
|
+
* Indeterminate means some, but not all, children are checked.
|
|
508
|
+
*
|
|
509
|
+
* States:
|
|
510
|
+
* - No children: false (not indeterminate)
|
|
511
|
+
* - No children checked: false (unchecked)
|
|
512
|
+
* - All children checked: false (fully checked)
|
|
513
|
+
* - Some children checked: true (indeterminate/partial)
|
|
514
|
+
*
|
|
515
|
+
* @returns true if parent should display indeterminate state
|
|
516
|
+
*/
|
|
517
|
+
const isIndeterminate = computed<boolean>(() => {
|
|
518
|
+
if (!props.children) return false;
|
|
519
|
+
|
|
520
|
+
const numChecked = props.children.filter((child) =>
|
|
521
|
+
model.value.includes(child.<span class="branch-0 cbranch-no" title="branch not covered" >value ?? child.label)</span>,
|
|
522
|
+
).length;
|
|
523
|
+
return numChecked > <span class="branch-0 cbranch-no" title="branch not covered" >0 && numChecked < props.children.length;</span>
|
|
321
524
|
});
|
|
322
525
|
|
|
526
|
+
/**
|
|
527
|
+
* Handles child checkbox changes to update parent state.
|
|
528
|
+
* Called when a child checkbox is toggled.
|
|
529
|
+
*
|
|
530
|
+
* Logic:
|
|
531
|
+
* - If ALL children are now checked → add parent to selection
|
|
532
|
+
* - If ANY child is unchecked → remove parent from selection
|
|
533
|
+
*
|
|
534
|
+
* Note: Uses concat() instead of push() to ensure Vue reactivity triggers.
|
|
535
|
+
*/
|
|
323
536
|
<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function handleCheckboxParentChange() {</span></span>
|
|
324
537
|
<span class="cstat-no" title="statement not covered" > if (!props.children) return;</span>
|
|
538
|
+
<span class="cstat-no" title="statement not covered" ></span>
|
|
325
539
|
<span class="cstat-no" title="statement not covered" > const numChecked = props.children.filter((child) =></span>
|
|
326
540
|
<span class="cstat-no" title="statement not covered" > model.value.includes(child.value ?? child.label),</span>
|
|
327
541
|
<span class="cstat-no" title="statement not covered" > ).length;</span>
|
|
328
542
|
<span class="cstat-no" title="statement not covered" ></span>
|
|
329
543
|
<span class="cstat-no" title="statement not covered" > if (numChecked === props.children.length) {</span>
|
|
330
|
-
<span class="cstat-no" title="statement not covered" > //
|
|
331
|
-
<span class="cstat-no" title="statement not covered" >
|
|
544
|
+
<span class="cstat-no" title="statement not covered" > // All children checked: add parent value to model if not already present</span>
|
|
545
|
+
<span class="cstat-no" title="statement not covered" > if (!model.value.includes(currentValue.value)) {</span>
|
|
546
|
+
<span class="cstat-no" title="statement not covered" > model.value = model.value.concat(currentValue.value);</span>
|
|
547
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
332
548
|
<span class="cstat-no" title="statement not covered" > } else {</span>
|
|
333
|
-
<span class="cstat-no" title="statement not covered" > // remove parent value
|
|
549
|
+
<span class="cstat-no" title="statement not covered" > // Not all children checked: remove parent value if present</span>
|
|
334
550
|
<span class="cstat-no" title="statement not covered" > if (model.value.includes(currentValue.value))</span>
|
|
335
551
|
<span class="cstat-no" title="statement not covered" > model.value = model.value.filter((value) => value !== currentValue.value);</span>
|
|
336
552
|
<span class="cstat-no" title="statement not covered" > }</span>
|
|
337
553
|
<span class="cstat-no" title="statement not covered" >}</span>
|
|
338
554
|
|
|
555
|
+
/**
|
|
556
|
+
* Handles parent checkbox changes to cascade to children.
|
|
557
|
+
* Called when the parent checkbox is clicked.
|
|
558
|
+
*
|
|
559
|
+
* Cascade behavior:
|
|
560
|
+
* - Parent checked → check all children
|
|
561
|
+
* - Parent unchecked → uncheck all children
|
|
562
|
+
*
|
|
563
|
+
* Only modifies children that need changes (doesn't re-add already selected children).
|
|
564
|
+
*/
|
|
339
565
|
<span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function onCheckboxParentChange() {</span></span>
|
|
340
566
|
<span class="cstat-no" title="statement not covered" > if (!props.children) return;</span>
|
|
567
|
+
<span class="cstat-no" title="statement not covered" ></span>
|
|
341
568
|
<span class="cstat-no" title="statement not covered" > if (model.value.includes(currentValue.value)) {</span>
|
|
342
|
-
<span class="cstat-no" title="statement not covered" > //
|
|
569
|
+
<span class="cstat-no" title="statement not covered" > // Parent is checked: add all unchecked children to model</span>
|
|
343
570
|
<span class="cstat-no" title="statement not covered" > model.value = model.value.concat(</span>
|
|
344
571
|
<span class="cstat-no" title="statement not covered" > props.children</span>
|
|
345
572
|
<span class="cstat-no" title="statement not covered" > ?.map((child) => child.value ?? child.label)</span>
|
|
346
573
|
<span class="cstat-no" title="statement not covered" > .filter((value) => !model.value.includes(value)),</span>
|
|
347
574
|
<span class="cstat-no" title="statement not covered" > );</span>
|
|
348
575
|
<span class="cstat-no" title="statement not covered" > } else {</span>
|
|
349
|
-
<span class="cstat-no" title="statement not covered" > // remove all children
|
|
576
|
+
<span class="cstat-no" title="statement not covered" > // Parent is unchecked: remove all children from model</span>
|
|
350
577
|
<span class="cstat-no" title="statement not covered" > model.value = model.value.filter(</span>
|
|
351
578
|
<span class="cstat-no" title="statement not covered" > (value) =></span>
|
|
352
579
|
<span class="cstat-no" title="statement not covered" > !props.children</span>
|
|
@@ -356,7 +583,53 @@ const isIndeterminate = computed(() => {
|
|
|
356
583
|
<span class="cstat-no" title="statement not covered" > }</span>
|
|
357
584
|
<span class="cstat-no" title="statement not covered" >}</span>
|
|
358
585
|
</script>
|
|
359
|
-
&
|
|
586
|
+
|
|
587
|
+
<template>
|
|
588
|
+
<!--
|
|
589
|
+
Parent checkbox
|
|
590
|
+
- Displays indeterminate state when children are partially selected
|
|
591
|
+
- aria-owns links to child checkboxes for screen reader navigation
|
|
592
|
+
- Change event cascades selection to all children
|
|
593
|
+
-->
|
|
594
|
+
<FzCheckbox
|
|
595
|
+
v-model="<span class="fstat-no" title="function not covered" >model"</span>
|
|
596
|
+
:value="props.value"
|
|
597
|
+
:label="props.label"
|
|
598
|
+
:disabled="disabled"
|
|
599
|
+
:emphasis="emphasis"
|
|
600
|
+
:error="error"
|
|
601
|
+
:indeterminate="isIndeterminate"
|
|
602
|
+
:aria-owns="children?.length ? childrenIds : undefined"
|
|
603
|
+
@change="onCheckboxParentChange"
|
|
604
|
+
>
|
|
605
|
+
<!--
|
|
606
|
+
Children slot: renders nested child checkboxes
|
|
607
|
+
Only rendered if children array has items
|
|
608
|
+
-->
|
|
609
|
+
<template #children v-if="children?.length">
|
|
610
|
+
<!-- Indented container for visual hierarchy -->
|
|
611
|
+
<div :class="[staticChildContainerClass, computedChildContainerClasses]">
|
|
612
|
+
<!--
|
|
613
|
+
Child checkboxes
|
|
614
|
+
- Assigned deterministic IDs matching those in parent's aria-owns
|
|
615
|
+
- Change events update parent's indeterminate state
|
|
616
|
+
- Share same v-model array with parent and siblings
|
|
617
|
+
-->
|
|
618
|
+
<FzCheckbox
|
|
619
|
+
v-for="(child, index) in children"
|
|
620
|
+
:key="child.value ? child.value.toString() : child.label"
|
|
621
|
+
v-model="<span class="fstat-no" title="function not covered" >model"</span>
|
|
622
|
+
:disabled="disabled"
|
|
623
|
+
v-bind="child"
|
|
624
|
+
:emphasis="emphasis"
|
|
625
|
+
:error="error"
|
|
626
|
+
:checkbox-id="`${parentId}-child-${index}`"
|
|
627
|
+
@change="handleCheckboxParentChange"
|
|
628
|
+
/>
|
|
629
|
+
</div>
|
|
630
|
+
</template>
|
|
631
|
+
</FzCheckbox>
|
|
632
|
+
</template>
|
|
360
633
|
</pre></td></tr></table></pre>
|
|
361
634
|
|
|
362
635
|
<div class='push'></div><!-- for sticky footer -->
|
|
@@ -364,7 +637,7 @@ const isIndeterminate = computed(() => {
|
|
|
364
637
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
365
638
|
Code coverage generated by
|
|
366
639
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
367
|
-
at
|
|
640
|
+
at 2025-10-30T09:58:41.772Z
|
|
368
641
|
</div>
|
|
369
642
|
<script src="../../prettify.js"></script>
|
|
370
643
|
<script>
|