@ship-ui/core 0.13.2 → 0.13.3
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.
|
@@ -3027,6 +3027,7 @@ class ShipSelectComponent {
|
|
|
3027
3027
|
this.options = model([]);
|
|
3028
3028
|
this.selectedOptions = model([]);
|
|
3029
3029
|
this.cleared = output();
|
|
3030
|
+
this.#previousSelectedOptions = signal(null);
|
|
3030
3031
|
this.inlineTemplate = contentChild(TemplateRef);
|
|
3031
3032
|
this.optionsWrapRef = viewChild.required('optionsWrap');
|
|
3032
3033
|
this.inputRefInput = signal(null);
|
|
@@ -3094,6 +3095,7 @@ class ShipSelectComponent {
|
|
|
3094
3095
|
scoredOptions.sort((a, b) => b.score - a.score);
|
|
3095
3096
|
return scoredOptions.map((scoredOption) => scoredOption.item);
|
|
3096
3097
|
});
|
|
3098
|
+
this.#componentId = generateUniqueId();
|
|
3097
3099
|
this.inputRefEl = computed(() => {
|
|
3098
3100
|
const inputRefInput = this.inputRefInput();
|
|
3099
3101
|
if (inputRefInput === null)
|
|
@@ -3104,6 +3106,10 @@ class ShipSelectComponent {
|
|
|
3104
3106
|
return null;
|
|
3105
3107
|
}
|
|
3106
3108
|
input.autocomplete = 'off';
|
|
3109
|
+
input.setAttribute('role', 'combobox');
|
|
3110
|
+
input.setAttribute('id', `combobox-${this.#componentId}`);
|
|
3111
|
+
input.setAttribute('aria-haspopup', 'listbox');
|
|
3112
|
+
input.setAttribute('aria-owns', 'optionsWrapId');
|
|
3107
3113
|
this.#createCustomInputEventListener(input);
|
|
3108
3114
|
input.addEventListener('focus', () => {
|
|
3109
3115
|
if (this.readonly())
|
|
@@ -3131,11 +3137,23 @@ class ShipSelectComponent {
|
|
|
3131
3137
|
return;
|
|
3132
3138
|
}
|
|
3133
3139
|
this.setSelectedOptionsFromValue(newInputValue);
|
|
3134
|
-
this.
|
|
3140
|
+
this.setInputValueFromOptions(this.selectedOptions());
|
|
3135
3141
|
this.#setFirstSelectedOptionAsFocused();
|
|
3136
3142
|
});
|
|
3137
3143
|
return input;
|
|
3138
3144
|
});
|
|
3145
|
+
this.focusEffect = effect(() => {
|
|
3146
|
+
const input = this.inputRefEl();
|
|
3147
|
+
if (!input)
|
|
3148
|
+
return;
|
|
3149
|
+
const focusedId = this.getLabelAsSlug(this.filteredOptions()[this.focusedOptionIndex()]);
|
|
3150
|
+
if (focusedId) {
|
|
3151
|
+
input.setAttribute('aria-activedescendant', focusedId);
|
|
3152
|
+
}
|
|
3153
|
+
else {
|
|
3154
|
+
input.removeAttribute('aria-activedescendant');
|
|
3155
|
+
}
|
|
3156
|
+
});
|
|
3139
3157
|
this.openAbortController = null;
|
|
3140
3158
|
this.isOpenEffect = effect(() => {
|
|
3141
3159
|
const isOpen = this.isOpen();
|
|
@@ -3146,6 +3164,7 @@ class ShipSelectComponent {
|
|
|
3146
3164
|
const input = this.inputRefEl();
|
|
3147
3165
|
if (!input)
|
|
3148
3166
|
return;
|
|
3167
|
+
input.setAttribute('aria-expanded', this.isOpen().toString());
|
|
3149
3168
|
input.addEventListener('keydown', (e) => {
|
|
3150
3169
|
if (e.key === 'Escape' || e.key === 'Tab') {
|
|
3151
3170
|
e.preventDefault();
|
|
@@ -3173,6 +3192,7 @@ class ShipSelectComponent {
|
|
|
3173
3192
|
const input = this.inputRefEl();
|
|
3174
3193
|
if (!input)
|
|
3175
3194
|
return;
|
|
3195
|
+
input.setAttribute('aria-expanded', this.isOpen().toString());
|
|
3176
3196
|
if (this.openAbortController) {
|
|
3177
3197
|
this.openAbortController.abort();
|
|
3178
3198
|
this.openAbortController = null;
|
|
@@ -3192,7 +3212,7 @@ class ShipSelectComponent {
|
|
|
3192
3212
|
return;
|
|
3193
3213
|
this.disabled.set(input.disabled);
|
|
3194
3214
|
this.setSelectedOptionsFromValue(input.value);
|
|
3195
|
-
this.
|
|
3215
|
+
this.setInputValueFromOptions(this.selectedOptions());
|
|
3196
3216
|
});
|
|
3197
3217
|
this.selectedLabels = computed(() => {
|
|
3198
3218
|
const selected = this.selectedOptions();
|
|
@@ -3237,6 +3257,7 @@ class ShipSelectComponent {
|
|
|
3237
3257
|
});
|
|
3238
3258
|
}
|
|
3239
3259
|
#selfRef;
|
|
3260
|
+
#previousSelectedOptions;
|
|
3240
3261
|
#inputObserver;
|
|
3241
3262
|
#calculateMatchScore(option, input) {
|
|
3242
3263
|
if (!input)
|
|
@@ -3271,6 +3292,7 @@ class ShipSelectComponent {
|
|
|
3271
3292
|
score += matchCount * 20;
|
|
3272
3293
|
return score;
|
|
3273
3294
|
}
|
|
3295
|
+
#componentId;
|
|
3274
3296
|
#selectedOptionsEffect;
|
|
3275
3297
|
ngOnInit() {
|
|
3276
3298
|
this.setInitInput();
|
|
@@ -3311,15 +3333,14 @@ class ShipSelectComponent {
|
|
|
3311
3333
|
});
|
|
3312
3334
|
this.selectedOptions.set(selectMultiple ? selectedOptions : [selectedOptions[0]]);
|
|
3313
3335
|
}
|
|
3314
|
-
|
|
3315
|
-
const selectedOptions = this.selectedOptions();
|
|
3336
|
+
setInputValueFromOptions(options) {
|
|
3316
3337
|
const valueKey = this.value();
|
|
3317
|
-
if (
|
|
3338
|
+
if (options.length === 0) {
|
|
3318
3339
|
this.inputValue.set('');
|
|
3319
3340
|
this.updateInputElValue();
|
|
3320
3341
|
return;
|
|
3321
3342
|
}
|
|
3322
|
-
const inputValue =
|
|
3343
|
+
const inputValue = options
|
|
3323
3344
|
.map((option) => {
|
|
3324
3345
|
const optionValue = valueKey ? this.#getProperty(option, valueKey) : option;
|
|
3325
3346
|
return optionValue;
|
|
@@ -3334,6 +3355,12 @@ class ShipSelectComponent {
|
|
|
3334
3355
|
return option;
|
|
3335
3356
|
return this.#getProperty(option, label);
|
|
3336
3357
|
}
|
|
3358
|
+
getLabelAsSlug(option) {
|
|
3359
|
+
const label = this.getLabel(option);
|
|
3360
|
+
if (!label || typeof label !== 'string')
|
|
3361
|
+
return '';
|
|
3362
|
+
return label.replaceAll(' ', '-');
|
|
3363
|
+
}
|
|
3337
3364
|
toggleOptionByIndex(optionIndex, event) {
|
|
3338
3365
|
const option = this.filteredOptions()[optionIndex];
|
|
3339
3366
|
if ((this.asFreeText() && optionIndex === -1) || !option) {
|
|
@@ -3349,6 +3376,7 @@ class ShipSelectComponent {
|
|
|
3349
3376
|
const selectedOptionValues = this.selectedOptionValues();
|
|
3350
3377
|
const optionValue = valueKey ? this.#getProperty(option, valueKey) : option;
|
|
3351
3378
|
this.prevInputValue.set(null);
|
|
3379
|
+
this.#previousSelectedOptions.set(null);
|
|
3352
3380
|
this.selectedOptions.update((selectedOptions) => {
|
|
3353
3381
|
const index = selectedOptionValues.indexOf(optionValue);
|
|
3354
3382
|
if (index > -1) {
|
|
@@ -3372,7 +3400,7 @@ class ShipSelectComponent {
|
|
|
3372
3400
|
else {
|
|
3373
3401
|
this.isOpen.set(false);
|
|
3374
3402
|
}
|
|
3375
|
-
this.
|
|
3403
|
+
this.setInputValueFromOptions(this.selectedOptions());
|
|
3376
3404
|
if (selectMultiple && this.hasSearch()) {
|
|
3377
3405
|
this.inputValue.set('');
|
|
3378
3406
|
this.updateInputElValue();
|
|
@@ -3383,7 +3411,7 @@ class ShipSelectComponent {
|
|
|
3383
3411
|
this.selectedOptions.update((selectedOptions) => {
|
|
3384
3412
|
return [...selectedOptions.slice(0, optionRemoveIndex), ...selectedOptions.slice(optionRemoveIndex + 1)];
|
|
3385
3413
|
});
|
|
3386
|
-
this.
|
|
3414
|
+
this.setInputValueFromOptions(this.selectedOptions());
|
|
3387
3415
|
}
|
|
3388
3416
|
isSelected(optionIndex) {
|
|
3389
3417
|
const valueKey = this.value();
|
|
@@ -3400,6 +3428,9 @@ class ShipSelectComponent {
|
|
|
3400
3428
|
this.inputValue.set('');
|
|
3401
3429
|
this.updateInputElValue();
|
|
3402
3430
|
}
|
|
3431
|
+
else {
|
|
3432
|
+
this.#previousSelectedOptions.set(this.selectedOptions());
|
|
3433
|
+
}
|
|
3403
3434
|
if (!this.selectMultiple()) {
|
|
3404
3435
|
this.#setFirstSelectedOptionAsFocused();
|
|
3405
3436
|
}
|
|
@@ -3418,16 +3449,20 @@ class ShipSelectComponent {
|
|
|
3418
3449
|
close() {
|
|
3419
3450
|
this.isOpen.set(false);
|
|
3420
3451
|
const prevInputValue = this.prevInputValue();
|
|
3452
|
+
const prevSelectedOptions = this.#previousSelectedOptions();
|
|
3421
3453
|
if (this.asFreeText()) {
|
|
3422
3454
|
this.updateInputElValue();
|
|
3423
3455
|
return;
|
|
3424
3456
|
}
|
|
3425
3457
|
if (this.hasSearch() && prevInputValue) {
|
|
3426
3458
|
this.inputValue.set(prevInputValue);
|
|
3427
|
-
this.
|
|
3459
|
+
this.setInputValueFromOptions(this.selectedOptions());
|
|
3460
|
+
}
|
|
3461
|
+
if (!this.hasSearch() && prevSelectedOptions !== null) {
|
|
3462
|
+
this.setInputValueFromOptions(prevSelectedOptions);
|
|
3428
3463
|
}
|
|
3429
3464
|
if (this.selectMultiple()) {
|
|
3430
|
-
this.
|
|
3465
|
+
this.setInputValueFromOptions(this.selectedOptions());
|
|
3431
3466
|
}
|
|
3432
3467
|
}
|
|
3433
3468
|
clear($event) {
|
|
@@ -3585,11 +3620,13 @@ class ShipSelectComponent {
|
|
|
3585
3620
|
}
|
|
3586
3621
|
</sh-form-field>
|
|
3587
3622
|
|
|
3588
|
-
<div class="ship-options" #optionsWrap>
|
|
3623
|
+
<div class="ship-options" #optionsWrap id="optionsWrapId" role="listbox">
|
|
3589
3624
|
@for (option of filteredOptions(); track $index) {
|
|
3590
3625
|
<li
|
|
3591
3626
|
(click)="toggleOptionByIndex($index)"
|
|
3592
3627
|
class="option"
|
|
3628
|
+
[id]="this.getLabelAsSlug(option)"
|
|
3629
|
+
[attr.aria-selected]="isSelected($index)"
|
|
3593
3630
|
[class.selected]="isSelected($index)"
|
|
3594
3631
|
[class.focused]="$index === focusedOptionIndex()">
|
|
3595
3632
|
@if (selectMultiple()) {
|
|
@@ -3711,11 +3748,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImpor
|
|
|
3711
3748
|
}
|
|
3712
3749
|
</sh-form-field>
|
|
3713
3750
|
|
|
3714
|
-
<div class="ship-options" #optionsWrap>
|
|
3751
|
+
<div class="ship-options" #optionsWrap id="optionsWrapId" role="listbox">
|
|
3715
3752
|
@for (option of filteredOptions(); track $index) {
|
|
3716
3753
|
<li
|
|
3717
3754
|
(click)="toggleOptionByIndex($index)"
|
|
3718
3755
|
class="option"
|
|
3756
|
+
[id]="this.getLabelAsSlug(option)"
|
|
3757
|
+
[attr.aria-selected]="isSelected($index)"
|
|
3719
3758
|
[class.selected]="isSelected($index)"
|
|
3720
3759
|
[class.focused]="$index === focusedOptionIndex()">
|
|
3721
3760
|
@if (selectMultiple()) {
|