@ship-ui/core 0.13.16 → 0.13.17
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/fesm2022/ship-ui-core.mjs +92 -5
- package/fesm2022/ship-ui-core.mjs.map +1 -1
- package/index.d.ts +6 -1
- package/package.json +1 -1
|
@@ -3015,6 +3015,7 @@ class ShipSelectComponent {
|
|
|
3015
3015
|
this.value = input();
|
|
3016
3016
|
this.label = input();
|
|
3017
3017
|
this.asFreeText = input(false);
|
|
3018
|
+
this.validateFreeText = input();
|
|
3018
3019
|
this.placeholder = input();
|
|
3019
3020
|
this.readonly = model(false);
|
|
3020
3021
|
this.disabled = model(false);
|
|
@@ -3026,11 +3027,21 @@ class ShipSelectComponent {
|
|
|
3026
3027
|
this.optionTemplate = input(null);
|
|
3027
3028
|
this.selectedOptionTemplate = input(null);
|
|
3028
3029
|
this.placeholderTemplate = input(null);
|
|
3030
|
+
this.freeTextOptionTemplate = input(null);
|
|
3029
3031
|
this.isOpen = model(false);
|
|
3030
3032
|
this.isLoading = model(false);
|
|
3031
3033
|
this.options = model([]);
|
|
3032
3034
|
this.selectedOptions = model([]);
|
|
3033
3035
|
this.cleared = output();
|
|
3036
|
+
this.computedFreeTextOption = computed(() => {
|
|
3037
|
+
const inputValue = this.inputValue();
|
|
3038
|
+
const valueKey = this.value();
|
|
3039
|
+
const newOption = valueKey ? {} : inputValue;
|
|
3040
|
+
if (valueKey && typeof newOption === 'object') {
|
|
3041
|
+
newOption[valueKey] = inputValue;
|
|
3042
|
+
}
|
|
3043
|
+
return newOption;
|
|
3044
|
+
});
|
|
3034
3045
|
this.#previousSelectedOptions = signal(null);
|
|
3035
3046
|
this.inlineTemplate = contentChild(TemplateRef);
|
|
3036
3047
|
this.optionsWrapRef = viewChild.required('optionsWrap');
|
|
@@ -3166,6 +3177,8 @@ class ShipSelectComponent {
|
|
|
3166
3177
|
this.openAbortController = new AbortController();
|
|
3167
3178
|
}
|
|
3168
3179
|
const input = this.inputRefEl();
|
|
3180
|
+
const asFreeText = this.asFreeText();
|
|
3181
|
+
const baseIndex = asFreeText ? -1 : 0;
|
|
3169
3182
|
if (!input)
|
|
3170
3183
|
return;
|
|
3171
3184
|
input.setAttribute('aria-expanded', this.isOpen().toString());
|
|
@@ -3181,12 +3194,12 @@ class ShipSelectComponent {
|
|
|
3181
3194
|
if (e.key === 'ArrowDown') {
|
|
3182
3195
|
e.preventDefault();
|
|
3183
3196
|
const newIndex = this.focusedOptionIndex() + 1;
|
|
3184
|
-
this.focusedOptionIndex.set(newIndex > this.filteredOptions().length - 1 ?
|
|
3197
|
+
this.focusedOptionIndex.set(newIndex > this.filteredOptions().length - 1 ? baseIndex : newIndex);
|
|
3185
3198
|
}
|
|
3186
3199
|
if (e.key === 'ArrowUp') {
|
|
3187
3200
|
e.preventDefault();
|
|
3188
3201
|
const newIndex = this.focusedOptionIndex() - 1;
|
|
3189
|
-
this.focusedOptionIndex.set(newIndex <
|
|
3202
|
+
this.focusedOptionIndex.set(newIndex < baseIndex ? this.filteredOptions().length - 1 : newIndex);
|
|
3190
3203
|
}
|
|
3191
3204
|
}, {
|
|
3192
3205
|
signal: this.openAbortController?.signal,
|
|
@@ -3355,6 +3368,12 @@ class ShipSelectComponent {
|
|
|
3355
3368
|
this.inputValue.set(newInputValue);
|
|
3356
3369
|
this.updateInputElValue();
|
|
3357
3370
|
}
|
|
3371
|
+
getValue(option) {
|
|
3372
|
+
const valueKey = this.value();
|
|
3373
|
+
if (!valueKey)
|
|
3374
|
+
return option;
|
|
3375
|
+
return this.#getProperty(option, valueKey);
|
|
3376
|
+
}
|
|
3358
3377
|
getLabel(option) {
|
|
3359
3378
|
const label = this.label();
|
|
3360
3379
|
if (!label)
|
|
@@ -3368,8 +3387,24 @@ class ShipSelectComponent {
|
|
|
3368
3387
|
return label.replaceAll(' ', '-');
|
|
3369
3388
|
}
|
|
3370
3389
|
toggleOptionByIndex(optionIndex, event) {
|
|
3371
|
-
|
|
3372
|
-
if (
|
|
3390
|
+
let option = this.filteredOptions()[optionIndex];
|
|
3391
|
+
if (this.asFreeText() && optionIndex === -1) {
|
|
3392
|
+
const newOption = this.computedFreeTextOption();
|
|
3393
|
+
const newOptionValue = this.getValue(newOption);
|
|
3394
|
+
const validateFreeTextFunc = this.validateFreeText() ?? ((val) => true);
|
|
3395
|
+
const isValid = validateFreeTextFunc(newOptionValue);
|
|
3396
|
+
if (!isValid)
|
|
3397
|
+
return;
|
|
3398
|
+
this.options.update((options) => {
|
|
3399
|
+
const index = options.findIndex((option) => this.getValue(option) === newOptionValue);
|
|
3400
|
+
if (index > -1)
|
|
3401
|
+
return options;
|
|
3402
|
+
return [newOption, ...options];
|
|
3403
|
+
});
|
|
3404
|
+
optionIndex = 0;
|
|
3405
|
+
option = newOption;
|
|
3406
|
+
}
|
|
3407
|
+
else if (!option) {
|
|
3373
3408
|
this.close();
|
|
3374
3409
|
return;
|
|
3375
3410
|
}
|
|
@@ -3535,9 +3570,10 @@ class ShipSelectComponent {
|
|
|
3535
3570
|
}
|
|
3536
3571
|
}
|
|
3537
3572
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: ShipSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3538
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.4", type: ShipSelectComponent, isStandalone: true, selector: "sh-select", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, asFreeText: { classPropertyName: "asFreeText", publicName: "asFreeText", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, lazySearch: { classPropertyName: "lazySearch", publicName: "lazySearch", isSignal: true, isRequired: false, transformFunction: null }, inlineSearch: { classPropertyName: "inlineSearch", publicName: "inlineSearch", isSignal: true, isRequired: false, transformFunction: null }, asText: { classPropertyName: "asText", publicName: "asText", isSignal: true, isRequired: false, transformFunction: null }, isClearable: { classPropertyName: "isClearable", publicName: "isClearable", isSignal: true, isRequired: false, transformFunction: null }, selectMultiple: { classPropertyName: "selectMultiple", publicName: "selectMultiple", isSignal: true, isRequired: false, transformFunction: null }, optionTemplate: { classPropertyName: "optionTemplate", publicName: "optionTemplate", isSignal: true, isRequired: false, transformFunction: null }, selectedOptionTemplate: { classPropertyName: "selectedOptionTemplate", publicName: "selectedOptionTemplate", isSignal: true, isRequired: false, transformFunction: null }, placeholderTemplate: { classPropertyName: "placeholderTemplate", publicName: "placeholderTemplate", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, selectedOptions: { classPropertyName: "selectedOptions", publicName: "selectedOptions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { readonly: "readonlyChange", disabled: "disabledChange", isOpen: "isOpenChange", isLoading: "isLoadingChange", options: "optionsChange", selectedOptions: "selectedOptionsChange", cleared: "cleared" }, host: { properties: { "class.multiple": "selectMultiple()" } }, queries: [{ propertyName: "inlineTemplate", first: true, predicate: TemplateRef, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "optionsWrapRef", first: true, predicate: ["optionsWrap"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
3573
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.4", type: ShipSelectComponent, isStandalone: true, selector: "sh-select", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, asFreeText: { classPropertyName: "asFreeText", publicName: "asFreeText", isSignal: true, isRequired: false, transformFunction: null }, validateFreeText: { classPropertyName: "validateFreeText", publicName: "validateFreeText", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, lazySearch: { classPropertyName: "lazySearch", publicName: "lazySearch", isSignal: true, isRequired: false, transformFunction: null }, inlineSearch: { classPropertyName: "inlineSearch", publicName: "inlineSearch", isSignal: true, isRequired: false, transformFunction: null }, asText: { classPropertyName: "asText", publicName: "asText", isSignal: true, isRequired: false, transformFunction: null }, isClearable: { classPropertyName: "isClearable", publicName: "isClearable", isSignal: true, isRequired: false, transformFunction: null }, selectMultiple: { classPropertyName: "selectMultiple", publicName: "selectMultiple", isSignal: true, isRequired: false, transformFunction: null }, optionTemplate: { classPropertyName: "optionTemplate", publicName: "optionTemplate", isSignal: true, isRequired: false, transformFunction: null }, selectedOptionTemplate: { classPropertyName: "selectedOptionTemplate", publicName: "selectedOptionTemplate", isSignal: true, isRequired: false, transformFunction: null }, placeholderTemplate: { classPropertyName: "placeholderTemplate", publicName: "placeholderTemplate", isSignal: true, isRequired: false, transformFunction: null }, freeTextOptionTemplate: { classPropertyName: "freeTextOptionTemplate", publicName: "freeTextOptionTemplate", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, selectedOptions: { classPropertyName: "selectedOptions", publicName: "selectedOptions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { readonly: "readonlyChange", disabled: "disabledChange", isOpen: "isOpenChange", isLoading: "isLoadingChange", options: "optionsChange", selectedOptions: "selectedOptionsChange", cleared: "cleared" }, host: { properties: { "class.multiple": "selectMultiple()" } }, queries: [{ propertyName: "inlineTemplate", first: true, predicate: TemplateRef, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "optionsWrapRef", first: true, predicate: ["optionsWrap"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
3539
3574
|
@let _placeholderTemplate = placeholderTemplate();
|
|
3540
3575
|
@let _optionTemplate = optionTemplate();
|
|
3576
|
+
@let _freeTextOptionTemplate = freeTextOptionTemplate();
|
|
3541
3577
|
@let _selectedOptionTemplate = selectedOptionTemplate();
|
|
3542
3578
|
@let _inlineTemplate = inlineTemplate();
|
|
3543
3579
|
@let _selectedOptions = selectedOptions();
|
|
@@ -3629,6 +3665,31 @@ class ShipSelectComponent {
|
|
|
3629
3665
|
</sh-form-field>
|
|
3630
3666
|
|
|
3631
3667
|
<div class="ship-options" #optionsWrap id="optionsWrapId" role="listbox">
|
|
3668
|
+
@if (asFreeText()) {
|
|
3669
|
+
@let freeTextOption = computedFreeTextOption();
|
|
3670
|
+
@let freeTextOptionValue = getValue(freeTextOption);
|
|
3671
|
+
|
|
3672
|
+
@if ($any(freeTextOptionValue).length > 0) {
|
|
3673
|
+
<li
|
|
3674
|
+
(click)="toggleOptionByIndex(-1)"
|
|
3675
|
+
class="option"
|
|
3676
|
+
[id]="this.getLabelAsSlug(freeTextOption)"
|
|
3677
|
+
[attr.aria-selected]="isSelected(-1)"
|
|
3678
|
+
[class.selected]="isSelected(-1)"
|
|
3679
|
+
[class.focused]="-1 === focusedOptionIndex()">
|
|
3680
|
+
@if (_freeTextOptionTemplate) {
|
|
3681
|
+
<ng-container
|
|
3682
|
+
*ngTemplateOutlet="_freeTextOptionTemplate; context: { $implicit: { option: freeTextOption } }" />
|
|
3683
|
+
} @else if (_listOptionTemplate) {
|
|
3684
|
+
<ng-container
|
|
3685
|
+
*ngTemplateOutlet="_listOptionTemplate; context: { $implicit: { option: freeTextOption } }" />
|
|
3686
|
+
} @else {
|
|
3687
|
+
{{ freeTextOptionValue }}
|
|
3688
|
+
}
|
|
3689
|
+
</li>
|
|
3690
|
+
}
|
|
3691
|
+
}
|
|
3692
|
+
|
|
3632
3693
|
@for (option of filteredOptions(); track $index) {
|
|
3633
3694
|
<li
|
|
3634
3695
|
(click)="toggleOptionByIndex($index)"
|
|
@@ -3668,6 +3729,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImpor
|
|
|
3668
3729
|
template: `
|
|
3669
3730
|
@let _placeholderTemplate = placeholderTemplate();
|
|
3670
3731
|
@let _optionTemplate = optionTemplate();
|
|
3732
|
+
@let _freeTextOptionTemplate = freeTextOptionTemplate();
|
|
3671
3733
|
@let _selectedOptionTemplate = selectedOptionTemplate();
|
|
3672
3734
|
@let _inlineTemplate = inlineTemplate();
|
|
3673
3735
|
@let _selectedOptions = selectedOptions();
|
|
@@ -3759,6 +3821,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImpor
|
|
|
3759
3821
|
</sh-form-field>
|
|
3760
3822
|
|
|
3761
3823
|
<div class="ship-options" #optionsWrap id="optionsWrapId" role="listbox">
|
|
3824
|
+
@if (asFreeText()) {
|
|
3825
|
+
@let freeTextOption = computedFreeTextOption();
|
|
3826
|
+
@let freeTextOptionValue = getValue(freeTextOption);
|
|
3827
|
+
|
|
3828
|
+
@if ($any(freeTextOptionValue).length > 0) {
|
|
3829
|
+
<li
|
|
3830
|
+
(click)="toggleOptionByIndex(-1)"
|
|
3831
|
+
class="option"
|
|
3832
|
+
[id]="this.getLabelAsSlug(freeTextOption)"
|
|
3833
|
+
[attr.aria-selected]="isSelected(-1)"
|
|
3834
|
+
[class.selected]="isSelected(-1)"
|
|
3835
|
+
[class.focused]="-1 === focusedOptionIndex()">
|
|
3836
|
+
@if (_freeTextOptionTemplate) {
|
|
3837
|
+
<ng-container
|
|
3838
|
+
*ngTemplateOutlet="_freeTextOptionTemplate; context: { $implicit: { option: freeTextOption } }" />
|
|
3839
|
+
} @else if (_listOptionTemplate) {
|
|
3840
|
+
<ng-container
|
|
3841
|
+
*ngTemplateOutlet="_listOptionTemplate; context: { $implicit: { option: freeTextOption } }" />
|
|
3842
|
+
} @else {
|
|
3843
|
+
{{ freeTextOptionValue }}
|
|
3844
|
+
}
|
|
3845
|
+
</li>
|
|
3846
|
+
}
|
|
3847
|
+
}
|
|
3848
|
+
|
|
3762
3849
|
@for (option of filteredOptions(); track $index) {
|
|
3763
3850
|
<li
|
|
3764
3851
|
(click)="toggleOptionByIndex($index)"
|