q2-tecton-elements 1.69.1 → 1.70.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/dist/bundle-report.json +2246 -355
- package/dist/cjs/click-elsewhere_3.cjs.entry.js +2 -2
- package/dist/cjs/{index-D2LFCsNP.js → index-SpDCZABA.js} +2 -2
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/q2-action-group_2.cjs.entry.js +1 -1
- package/dist/cjs/q2-action-sheet.cjs.entry.js +2 -2
- package/dist/cjs/q2-badge_2.cjs.entry.js +11 -4
- package/dist/cjs/q2-btn_2.cjs.entry.js +6 -2
- package/dist/cjs/q2-calendar.cjs.entry.js +5 -3
- package/dist/cjs/q2-card-image.cjs.entry.js +8 -6
- package/dist/cjs/q2-card.cjs.entry.js +2 -2
- package/dist/cjs/q2-carousel-pane.cjs.entry.js +1 -1
- package/dist/cjs/q2-carousel.cjs.entry.js +1 -1
- package/dist/cjs/q2-chart-area.cjs.entry.js +1 -1
- package/dist/cjs/q2-chart-bar.cjs.entry.js +1 -1
- package/dist/cjs/q2-chart-donut.cjs.entry.js +2 -2
- package/dist/cjs/q2-checkbox-group.cjs.entry.js +1 -1
- package/dist/cjs/q2-checkbox_2.cjs.entry.js +4 -3
- package/dist/cjs/q2-context.cjs.entry.js +1 -1
- package/dist/cjs/q2-currency.cjs.entry.js +1 -1
- package/dist/cjs/q2-data-table.cjs.entry.js +6 -3
- package/dist/cjs/q2-detail.cjs.entry.js +2 -2
- package/dist/cjs/q2-dropdown-item.cjs.entry.js +1 -1
- package/dist/cjs/q2-dropdown.cjs.entry.js +3 -3
- package/dist/cjs/q2-editable-field.cjs.entry.js +12 -4
- package/dist/cjs/q2-file-picker.cjs.entry.js +1 -1
- package/dist/cjs/q2-icon.cjs.entry.js +1 -1
- package/dist/cjs/q2-item.cjs.entry.js +2 -2
- package/dist/cjs/q2-legend.cjs.entry.js +1 -1
- package/dist/cjs/q2-link_2.cjs.entry.js +2 -2
- package/dist/cjs/q2-loc.cjs.entry.js +20 -2
- package/dist/cjs/q2-message.cjs.entry.js +1 -1
- package/dist/cjs/q2-meter.cjs.entry.js +2 -2
- package/dist/cjs/q2-modal.cjs.entry.js +3 -3
- package/dist/cjs/q2-month-picker.cjs.entry.js +1 -1
- package/dist/cjs/q2-optgroup.cjs.entry.js +1 -1
- package/dist/cjs/q2-option.cjs.entry.js +1 -1
- package/dist/cjs/q2-otp.cjs.entry.js +1 -1
- package/dist/cjs/q2-pagination.cjs.entry.js +1 -1
- package/dist/cjs/q2-pill.cjs.entry.js +1 -1
- package/dist/cjs/q2-radio-group.cjs.entry.js +1 -1
- package/dist/cjs/q2-radio.cjs.entry.js +1 -1
- package/dist/cjs/q2-relative-time.cjs.entry.js +1 -1
- package/dist/cjs/q2-search.cjs.entry.js +101 -12
- package/dist/cjs/q2-section.cjs.entry.js +2 -2
- package/dist/cjs/q2-select.cjs.entry.js +36 -6
- package/dist/cjs/q2-stepper-pane.cjs.entry.js +1 -1
- package/dist/cjs/q2-stepper-vertical.cjs.entry.js +24 -18
- package/dist/cjs/q2-stepper.cjs.entry.js +5 -4
- package/dist/cjs/q2-surface.cjs.entry.js +95 -0
- package/dist/cjs/q2-tab-container.cjs.entry.js +2 -2
- package/dist/cjs/q2-tab-pane.cjs.entry.js +1 -1
- package/dist/cjs/q2-tecton-elements.cjs.js +1 -1
- package/dist/cjs/q2-textarea.cjs.entry.js +1 -1
- package/dist/cjs/q2-toast.cjs.entry.js +1 -1
- package/dist/cjs/q2-tooltip.cjs.entry.js +1 -1
- package/dist/cjs/tecton-tab-pane.cjs.entry.js +2 -2
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/q2-action-sheet/q2-action-sheet.css +1 -1
- package/dist/collection/components/q2-btn/q2-btn.css +32 -17
- package/dist/collection/components/q2-btn/q2-btn.js +6 -1
- package/dist/collection/components/q2-calendar/q2-calendar.js +24 -2
- package/dist/collection/components/q2-calendar/test/q2-calendar-test.vr.js +4 -0
- package/dist/collection/components/q2-card/q2-card.css +2 -2
- package/dist/collection/components/q2-card-image/q2-card-image.css +3 -0
- package/dist/collection/components/q2-card-image/q2-card-image.js +25 -23
- package/dist/collection/components/q2-chart-area/q2-chart-area.css +4 -0
- package/dist/collection/components/q2-chart-bar/q2-chart-bar.css +4 -0
- package/dist/collection/components/q2-chart-donut/q2-chart-donut.css +1 -1
- package/dist/collection/components/q2-checkbox/q2-checkbox.js +2 -1
- package/dist/collection/components/q2-currency/q2-currency.css +1 -1
- package/dist/collection/components/q2-data-table/q2-data-table.js +5 -2
- package/dist/collection/components/q2-detail/q2-detail.css +12 -12
- package/dist/collection/components/q2-dropdown/q2-dropdown.js +2 -2
- package/dist/collection/components/q2-editable-field/q2-editable-field.js +11 -3
- package/dist/collection/components/q2-input/q2-input.css +11 -1
- package/dist/collection/components/q2-input/q2-input.js +29 -2
- package/dist/collection/components/q2-input/test/q2-input-test.vr.js +8 -0
- package/dist/collection/components/q2-item/q2-item.css +10 -5
- package/dist/collection/components/q2-item/test/q2-item-test.vr.js +132 -0
- package/dist/collection/components/q2-legend/q2-legend.css +2 -2
- package/dist/collection/components/q2-list/q2-list.css +1 -1
- package/dist/collection/components/q2-loc/q2-loc.js +42 -1
- package/dist/collection/components/q2-message/q2-message.css +4 -0
- package/dist/collection/components/q2-meter/q2-meter.css +3 -3
- package/dist/collection/components/q2-modal/q2-modal.css +1 -1
- package/dist/collection/components/q2-modal/q2-modal.js +2 -2
- package/dist/collection/components/q2-otp/q2-otp.css +33 -0
- package/dist/collection/components/q2-otp/test/q2-otp-test.vr.js +83 -0
- package/dist/collection/components/q2-popover/q2-popover.css +2 -1
- package/dist/collection/components/q2-radio/q2-radio.css +2 -0
- package/dist/collection/components/q2-search/q2-search.css +30 -0
- package/dist/collection/components/q2-search/q2-search.js +99 -10
- package/dist/collection/components/q2-search/test/q2-search-test.vr.js +145 -0
- package/dist/collection/components/q2-section/q2-section.css +1 -1
- package/dist/collection/components/q2-select/q2-select.css +4 -2
- package/dist/collection/components/q2-select/q2-select.js +54 -4
- package/dist/collection/components/q2-select/test/q2-select-test.vr.js +5 -0
- package/dist/collection/components/q2-stepper/q2-stepper.css +2 -2
- package/dist/collection/components/q2-stepper/q2-stepper.js +3 -2
- package/dist/collection/components/q2-stepper-vertical/q2-stepper-vertical.css +2 -2
- package/dist/collection/components/q2-stepper-vertical/q2-stepper-vertical.js +22 -16
- package/dist/collection/components/q2-surface/q2-surface.css +348 -0
- package/dist/collection/components/q2-surface/q2-surface.js +381 -0
- package/dist/collection/components/q2-surface/test/q2-surface-test.vr.js +108 -0
- package/dist/collection/components/q2-tab-container/q2-tab-container.js +1 -1
- package/dist/collection/components/q2-tab-pane/q2-tab-pane.js +1 -1
- package/dist/collection/components/q2-tag/q2-tag.js +1 -1
- package/dist/collection/components/q2-toast/q2-toast.js +3 -1
- package/dist/collection/components/tecton-tab-pane/tecton-tab-pane.js +2 -2
- package/dist/collection/utils/index.js +2 -2
- package/dist/components/index.js +12 -10
- package/dist/components/index2.js +3 -3
- package/dist/components/q2-action-sheet.js +1 -1
- package/dist/components/q2-btn2.js +5 -1
- package/dist/components/q2-calendar.js +294 -290
- package/dist/components/q2-card-image.js +9 -6
- package/dist/components/q2-card.js +14 -14
- package/dist/components/q2-chart-donut.js +1 -1
- package/dist/components/q2-checkbox2.js +12 -12
- package/dist/components/q2-currency.js +1 -1
- package/dist/components/q2-data-table.js +4 -4
- package/dist/components/q2-detail.js +1 -1
- package/dist/components/q2-dropdown.js +8 -8
- package/dist/components/q2-editable-field.js +15 -5
- package/dist/components/q2-input2.js +46 -26
- package/dist/components/q2-item2.js +1 -1
- package/dist/components/q2-legend2.js +51 -51
- package/dist/components/q2-list2.js +1 -1
- package/dist/components/q2-loc.js +23 -8
- package/dist/components/q2-meter.js +10 -10
- package/dist/components/q2-modal.js +54 -54
- package/dist/components/q2-popover2.js +1 -1
- package/dist/components/q2-search.js +106 -51
- package/dist/components/q2-section.js +1 -1
- package/dist/components/q2-select2.js +25 -9
- package/dist/components/q2-stepper-vertical.js +72 -63
- package/dist/components/q2-stepper.js +73 -71
- package/dist/components/q2-surface.d.ts +11 -0
- package/dist/components/q2-surface.js +109 -0
- package/dist/components/q2-tab-container.js +12 -12
- package/dist/components/q2-tab-pane.js +6 -6
- package/dist/components/q2-tag2.js +5 -5
- package/dist/components/tecton-tab-pane.js +10 -10
- package/dist/esm/click-elsewhere_3.entry.js +2 -2
- package/dist/esm/{index-Bx4m6N0g.js → index-Cps4jSQM.js} +2 -2
- package/dist/esm/loader.js +1 -1
- package/dist/esm/q2-action-group_2.entry.js +1 -1
- package/dist/esm/q2-action-sheet.entry.js +2 -2
- package/dist/esm/q2-badge_2.entry.js +11 -4
- package/dist/esm/q2-btn_2.entry.js +6 -2
- package/dist/esm/q2-calendar.entry.js +5 -3
- package/dist/esm/q2-card-image.entry.js +8 -6
- package/dist/esm/q2-card.entry.js +2 -2
- package/dist/esm/q2-carousel-pane.entry.js +1 -1
- package/dist/esm/q2-carousel.entry.js +1 -1
- package/dist/esm/q2-chart-area.entry.js +1 -1
- package/dist/esm/q2-chart-bar.entry.js +1 -1
- package/dist/esm/q2-chart-donut.entry.js +2 -2
- package/dist/esm/q2-checkbox-group.entry.js +1 -1
- package/dist/esm/q2-checkbox_2.entry.js +4 -3
- package/dist/esm/q2-context.entry.js +1 -1
- package/dist/esm/q2-currency.entry.js +1 -1
- package/dist/esm/q2-data-table.entry.js +6 -3
- package/dist/esm/q2-detail.entry.js +2 -2
- package/dist/esm/q2-dropdown-item.entry.js +1 -1
- package/dist/esm/q2-dropdown.entry.js +3 -3
- package/dist/esm/q2-editable-field.entry.js +12 -4
- package/dist/esm/q2-file-picker.entry.js +1 -1
- package/dist/esm/q2-icon.entry.js +1 -1
- package/dist/esm/q2-item.entry.js +2 -2
- package/dist/esm/q2-legend.entry.js +1 -1
- package/dist/esm/q2-link_2.entry.js +2 -2
- package/dist/esm/q2-loc.entry.js +20 -2
- package/dist/esm/q2-message.entry.js +1 -1
- package/dist/esm/q2-meter.entry.js +2 -2
- package/dist/esm/q2-modal.entry.js +3 -3
- package/dist/esm/q2-month-picker.entry.js +1 -1
- package/dist/esm/q2-optgroup.entry.js +1 -1
- package/dist/esm/q2-option.entry.js +1 -1
- package/dist/esm/q2-otp.entry.js +1 -1
- package/dist/esm/q2-pagination.entry.js +1 -1
- package/dist/esm/q2-pill.entry.js +1 -1
- package/dist/esm/q2-radio-group.entry.js +1 -1
- package/dist/esm/q2-radio.entry.js +1 -1
- package/dist/esm/q2-relative-time.entry.js +1 -1
- package/dist/esm/q2-search.entry.js +101 -12
- package/dist/esm/q2-section.entry.js +2 -2
- package/dist/esm/q2-select.entry.js +36 -6
- package/dist/esm/q2-stepper-pane.entry.js +1 -1
- package/dist/esm/q2-stepper-vertical.entry.js +24 -18
- package/dist/esm/q2-stepper.entry.js +5 -4
- package/dist/esm/q2-surface.entry.js +93 -0
- package/dist/esm/q2-tab-container.entry.js +2 -2
- package/dist/esm/q2-tab-pane.entry.js +1 -1
- package/dist/esm/q2-tecton-elements.js +1 -1
- package/dist/esm/q2-textarea.entry.js +1 -1
- package/dist/esm/q2-toast.entry.js +1 -1
- package/dist/esm/q2-tooltip.entry.js +1 -1
- package/dist/esm/tecton-tab-pane.entry.js +2 -2
- package/dist/q2-tecton-elements/click-elsewhere_3.entry.js +2 -2
- package/dist/q2-tecton-elements/{index-Bx4m6N0g.js → index-Cps4jSQM.js} +3 -3
- package/dist/q2-tecton-elements/q2-action-group_2.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-action-sheet.entry.js +2 -2
- package/dist/q2-tecton-elements/q2-badge_2.entry.js +51 -32
- package/dist/q2-tecton-elements/q2-btn_2.entry.js +6 -2
- package/dist/q2-tecton-elements/q2-calendar.entry.js +7 -4
- package/dist/q2-tecton-elements/q2-card-image.entry.js +65 -62
- package/dist/q2-tecton-elements/q2-card.entry.js +2 -2
- package/dist/q2-tecton-elements/q2-carousel-pane.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-carousel.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-chart-area.entry.js +54 -54
- package/dist/q2-tecton-elements/q2-chart-bar.entry.js +3 -3
- package/dist/q2-tecton-elements/q2-chart-donut.entry.js +7 -7
- package/dist/q2-tecton-elements/q2-checkbox-group.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-checkbox_2.entry.js +18 -18
- package/dist/q2-tecton-elements/q2-context.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-currency.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-data-table.entry.js +50 -50
- package/dist/q2-tecton-elements/q2-detail.entry.js +2 -2
- package/dist/q2-tecton-elements/q2-dropdown-item.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-dropdown.entry.js +16 -16
- package/dist/q2-tecton-elements/q2-editable-field.entry.js +15 -8
- package/dist/q2-tecton-elements/q2-file-picker.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-icon.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-item.entry.js +2 -2
- package/dist/q2-tecton-elements/q2-legend.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-link_2.entry.js +2 -2
- package/dist/q2-tecton-elements/q2-loc.entry.js +20 -6
- package/dist/q2-tecton-elements/q2-message.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-meter.entry.js +2 -2
- package/dist/q2-tecton-elements/q2-modal.entry.js +55 -55
- package/dist/q2-tecton-elements/q2-month-picker.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-optgroup.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-option.entry.js +7 -7
- package/dist/q2-tecton-elements/q2-otp.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-pagination.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-pill.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-radio-group.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-radio.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-relative-time.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-search.entry.js +108 -53
- package/dist/q2-tecton-elements/q2-section.entry.js +2 -2
- package/dist/q2-tecton-elements/q2-select.entry.js +25 -10
- package/dist/q2-tecton-elements/q2-stepper-pane.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-stepper-vertical.entry.js +75 -66
- package/dist/q2-tecton-elements/q2-stepper.entry.js +47 -45
- package/dist/q2-tecton-elements/q2-surface.entry.js +89 -0
- package/dist/q2-tecton-elements/q2-tab-container.entry.js +13 -13
- package/dist/q2-tecton-elements/q2-tab-pane.entry.js +2 -2
- package/dist/q2-tecton-elements/q2-tecton-elements.esm.js +1 -1
- package/dist/q2-tecton-elements/q2-textarea.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-toast.entry.js +5 -5
- package/dist/q2-tecton-elements/q2-tooltip.entry.js +8 -8
- package/dist/q2-tecton-elements/tecton-tab-pane.entry.js +6 -6
- package/dist/types/components/q2-calendar/q2-calendar.d.ts +2 -0
- package/dist/types/components/q2-card-image/q2-card-image.d.ts +5 -5
- package/dist/types/components/q2-editable-field/q2-editable-field.d.ts +1 -0
- package/dist/types/components/q2-input/q2-input.d.ts +3 -0
- package/dist/types/components/q2-item/test/q2-item-test.vr.d.ts +1 -0
- package/dist/types/components/q2-loc/q2-loc.d.ts +6 -0
- package/dist/types/components/q2-modal/q2-modal.d.ts +1 -1
- package/dist/types/components/q2-otp/test/q2-otp-test.vr.d.ts +1 -0
- package/dist/types/components/q2-search/q2-search.d.ts +7 -0
- package/dist/types/components/q2-search/test/q2-search-test.vr.d.ts +1 -0
- package/dist/types/components/q2-select/q2-select.d.ts +4 -0
- package/dist/types/components/q2-stepper-vertical/q2-stepper-vertical.d.ts +2 -1
- package/dist/types/components/q2-surface/q2-surface.d.ts +54 -0
- package/dist/types/components/q2-surface/test/q2-surface-test.vr.d.ts +1 -0
- package/dist/types/components/q2-toast/q2-toast.d.ts +3 -1
- package/dist/types/components.d.ts +259 -13
- package/dist/types/utils/index.d.ts +3 -1
- package/package.json +4 -3
|
@@ -83,6 +83,7 @@ export class Q2Search {
|
|
|
83
83
|
*/
|
|
84
84
|
this.showSelectedToggle = false;
|
|
85
85
|
this.clearAll = () => {
|
|
86
|
+
this.clearSelectedDisplay();
|
|
86
87
|
const { multiple } = this;
|
|
87
88
|
this.value = '';
|
|
88
89
|
this.selectedOptions = [];
|
|
@@ -101,7 +102,7 @@ export class Q2Search {
|
|
|
101
102
|
this.tctInput.emit({ query: '' });
|
|
102
103
|
};
|
|
103
104
|
this.handleSelectionChanges = (detail) => {
|
|
104
|
-
var _a, _b, _c, _d, _e
|
|
105
|
+
var _a, _b, _c, _d, _e;
|
|
105
106
|
const { multiple } = this;
|
|
106
107
|
if (multiple) {
|
|
107
108
|
const values = (_a = detail.values) !== null && _a !== void 0 ? _a : [];
|
|
@@ -123,6 +124,10 @@ export class Q2Search {
|
|
|
123
124
|
// Re-clicking the already-selected single-select option closes the popover
|
|
124
125
|
// with no state change and no `tctChange`.
|
|
125
126
|
if (value === this.value && value !== '') {
|
|
127
|
+
const reSelected = this.optionElements.find(o => o.value === value);
|
|
128
|
+
this.searchText = this.optionDisplayText(reSelected, value);
|
|
129
|
+
this.isShowingSelectionDisplay = true;
|
|
130
|
+
this.checkSelectedDisplay();
|
|
126
131
|
// Focus before close so the focus event fires while open===true, which
|
|
127
132
|
// causes onFocus to skip openDropdown (it's already open at that point).
|
|
128
133
|
(_d = this.innerInputField) === null || _d === void 0 ? void 0 : _d.focus();
|
|
@@ -131,12 +136,13 @@ export class Q2Search {
|
|
|
131
136
|
}
|
|
132
137
|
this.value = value;
|
|
133
138
|
const selected = this.optionElements.find(o => o.value === value);
|
|
134
|
-
const display =
|
|
139
|
+
const display = this.optionDisplayText(selected, value);
|
|
135
140
|
this.searchText = display;
|
|
136
141
|
this.isShowingSelectionDisplay = true;
|
|
142
|
+
this.checkSelectedDisplay();
|
|
137
143
|
// Focus before close: the focus event fires while open===true so onFocus's
|
|
138
144
|
// openDropdown call is a no-op, then closeDropdown brings us to closed+focused.
|
|
139
|
-
(
|
|
145
|
+
(_e = this.innerInputField) === null || _e === void 0 ? void 0 : _e.focus();
|
|
140
146
|
this.closeDropdown();
|
|
141
147
|
this.tctChange.emit({
|
|
142
148
|
value,
|
|
@@ -154,6 +160,8 @@ export class Q2Search {
|
|
|
154
160
|
this.inputInputHandler = (event) => {
|
|
155
161
|
event.stopPropagation();
|
|
156
162
|
const next = event.detail.value;
|
|
163
|
+
if (this.isShowingSelectionDisplay)
|
|
164
|
+
this.clearSelectedDisplay();
|
|
157
165
|
// Preserve `value` while the user types — they're searching, not deselecting.
|
|
158
166
|
// `handleSelectionChanges` updates value if they pick a different option,
|
|
159
167
|
// and `revertToSelectedDisplay` restores the display on blur.
|
|
@@ -208,6 +216,17 @@ export class Q2Search {
|
|
|
208
216
|
event.stopPropagation();
|
|
209
217
|
this.handleSelectionChanges(event.detail);
|
|
210
218
|
};
|
|
219
|
+
this.onSelectedDisplayMousedown = (event) => {
|
|
220
|
+
var _a;
|
|
221
|
+
event.preventDefault();
|
|
222
|
+
event.stopPropagation();
|
|
223
|
+
this.isShowingSelectionDisplay = false;
|
|
224
|
+
this.clearSelectedDisplay();
|
|
225
|
+
if (this.value)
|
|
226
|
+
(_a = this.innerInputField) === null || _a === void 0 ? void 0 : _a.select();
|
|
227
|
+
if (!this.open)
|
|
228
|
+
this.openDropdown();
|
|
229
|
+
};
|
|
211
230
|
this.onViewportResize = () => {
|
|
212
231
|
if (!this.open || !this.popoverAlignment)
|
|
213
232
|
return;
|
|
@@ -261,10 +280,14 @@ export class Q2Search {
|
|
|
261
280
|
if (target && ((_c = this.popoverElement) === null || _c === void 0 ? void 0 : _c.contains(target)))
|
|
262
281
|
return;
|
|
263
282
|
this.inputFocused = true;
|
|
264
|
-
|
|
283
|
+
// Only switch away from the selection display when the user actively re-engages the
|
|
284
|
+
// field (popover is closed). During the post-selection focus that closes the popover,
|
|
285
|
+
// `open` is still true — clearing here would immediately discard the rich display.
|
|
286
|
+
if (this.isShowingSelectionDisplay && !this.open) {
|
|
265
287
|
// Clear the flag before mutating searchText so the filter watcher runs against the
|
|
266
288
|
// new query, not the stale "showing a selection" guard.
|
|
267
289
|
this.isShowingSelectionDisplay = false;
|
|
290
|
+
this.clearSelectedDisplay();
|
|
268
291
|
if (this.multiple) {
|
|
269
292
|
// Multi-select always opens to a fresh search after a selection.
|
|
270
293
|
this.searchText = '';
|
|
@@ -361,6 +384,7 @@ export class Q2Search {
|
|
|
361
384
|
* Does not emit `tctChange`.
|
|
362
385
|
*/
|
|
363
386
|
async reset() {
|
|
387
|
+
this.clearSelectedDisplay();
|
|
364
388
|
this.value = '';
|
|
365
389
|
this.selectedOptions = [];
|
|
366
390
|
this.searchText = '';
|
|
@@ -477,6 +501,11 @@ export class Q2Search {
|
|
|
477
501
|
return count > 1 ? `+${count - 1}` : null;
|
|
478
502
|
return `${count}`;
|
|
479
503
|
}
|
|
504
|
+
get firstSelectedOptionElement() {
|
|
505
|
+
var _a, _b;
|
|
506
|
+
const v = this.multiple ? (_a = this.selectedOptions) === null || _a === void 0 ? void 0 : _a[0] : this.value;
|
|
507
|
+
return v ? (_b = this.optionElements.find(o => o.value === v)) !== null && _b !== void 0 ? _b : null : null;
|
|
508
|
+
}
|
|
480
509
|
get innerInputContainer() {
|
|
481
510
|
var _a, _b, _c;
|
|
482
511
|
return (_c = (_b = (_a = this.inputField) === null || _a === void 0 ? void 0 : _a.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('.input-container')) !== null && _c !== void 0 ? _c : null;
|
|
@@ -513,6 +542,9 @@ export class Q2Search {
|
|
|
513
542
|
const rowHeight = Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
514
543
|
return this.minRows * rowHeight;
|
|
515
544
|
}
|
|
545
|
+
get selectedDisplaySlot() {
|
|
546
|
+
return this.hostElement.querySelector('[slot="_selected-display"]');
|
|
547
|
+
}
|
|
516
548
|
get visibleOptionElements() {
|
|
517
549
|
return this.optionElements.filter(opt => !opt.hidden);
|
|
518
550
|
}
|
|
@@ -546,12 +578,50 @@ export class Q2Search {
|
|
|
546
578
|
const { multilineOptions } = this;
|
|
547
579
|
this.optionElements.forEach(option => (option.multiline = multilineOptions));
|
|
548
580
|
}
|
|
581
|
+
checkSelectedDisplay() {
|
|
582
|
+
var _a;
|
|
583
|
+
const { multilineOptions, isShowingSelectionDisplay, value, multiple, selectedOptions, firstSelectedOptionElement, } = this;
|
|
584
|
+
const hasNoValue = multiple ? !(selectedOptions === null || selectedOptions === void 0 ? void 0 : selectedOptions.length) : !value;
|
|
585
|
+
if (!multilineOptions || !isShowingSelectionDisplay || hasNoValue)
|
|
586
|
+
return this.clearSelectedDisplay();
|
|
587
|
+
if (!firstSelectedOptionElement || firstSelectedOptionElement.display)
|
|
588
|
+
return this.clearSelectedDisplay();
|
|
589
|
+
const child = firstSelectedOptionElement.firstElementChild;
|
|
590
|
+
if (!child)
|
|
591
|
+
return this.clearSelectedDisplay();
|
|
592
|
+
const selectionClone = child.cloneNode(true);
|
|
593
|
+
selectionClone.querySelectorAll('[hide-on-select]').forEach(el => el.remove());
|
|
594
|
+
let namedSlot = this.selectedDisplaySlot;
|
|
595
|
+
if (namedSlot) {
|
|
596
|
+
if (((_a = namedSlot.firstElementChild) === null || _a === void 0 ? void 0 : _a.outerHTML) !== selectionClone.outerHTML) {
|
|
597
|
+
namedSlot.replaceChildren(selectionClone);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
else {
|
|
601
|
+
namedSlot = document.createElement('div');
|
|
602
|
+
namedSlot.slot = '_selected-display';
|
|
603
|
+
// Prevent the non-focusable overlay from blurring the hidden input when clicked.
|
|
604
|
+
// Same pattern used by q2-input's clear button (onMouseDown preventDefault).
|
|
605
|
+
namedSlot.addEventListener('mousedown', this.onSelectedDisplayMousedown);
|
|
606
|
+
namedSlot.appendChild(selectionClone);
|
|
607
|
+
this.hostElement.appendChild(namedSlot);
|
|
608
|
+
}
|
|
609
|
+
return namedSlot;
|
|
610
|
+
}
|
|
549
611
|
checkSelectedOptions() {
|
|
550
612
|
const { multiple, selectedOptions, value } = this;
|
|
551
613
|
this.optionElements.forEach(option => {
|
|
552
614
|
option.selected = multiple ? selectedOptions.includes(option.value) : option.value === value;
|
|
553
615
|
});
|
|
554
616
|
}
|
|
617
|
+
clearSelectedDisplay() {
|
|
618
|
+
const slot = this.selectedDisplaySlot;
|
|
619
|
+
if (slot) {
|
|
620
|
+
slot.removeEventListener('mousedown', this.onSelectedDisplayMousedown);
|
|
621
|
+
slot.remove();
|
|
622
|
+
}
|
|
623
|
+
return null;
|
|
624
|
+
}
|
|
555
625
|
closeDropdown() {
|
|
556
626
|
if (!this.open)
|
|
557
627
|
return;
|
|
@@ -578,8 +648,16 @@ export class Q2Search {
|
|
|
578
648
|
this.open = true;
|
|
579
649
|
this.tctOpen.emit();
|
|
580
650
|
}
|
|
651
|
+
optionDisplayText(option, fallback = '') {
|
|
652
|
+
var _a, _b;
|
|
653
|
+
if (option === null || option === void 0 ? void 0 : option.display)
|
|
654
|
+
return loc(option.display);
|
|
655
|
+
if (this.multilineOptions)
|
|
656
|
+
return '';
|
|
657
|
+
return (_b = (_a = option === null || option === void 0 ? void 0 : option.textContent) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : fallback;
|
|
658
|
+
}
|
|
581
659
|
revertToSelectedDisplay() {
|
|
582
|
-
var _a, _b, _c
|
|
660
|
+
var _a, _b, _c;
|
|
583
661
|
if (this.multiple) {
|
|
584
662
|
// Preserve an in-progress query — user blurred without selecting and may resume.
|
|
585
663
|
if (this.searchText)
|
|
@@ -593,7 +671,7 @@ export class Q2Search {
|
|
|
593
671
|
// re-populated yet) — leave the query alone rather than blanking it.
|
|
594
672
|
if (!selected)
|
|
595
673
|
return;
|
|
596
|
-
const display =
|
|
674
|
+
const display = this.optionDisplayText(selected);
|
|
597
675
|
this.searchText = display;
|
|
598
676
|
this.isShowingSelectionDisplay = true;
|
|
599
677
|
return;
|
|
@@ -606,10 +684,16 @@ export class Q2Search {
|
|
|
606
684
|
// Same guard: don't clobber an in-progress query when the matching option isn't in the DOM.
|
|
607
685
|
if (!selected)
|
|
608
686
|
return;
|
|
609
|
-
const display = selected.display
|
|
687
|
+
const display = selected.display
|
|
688
|
+
? loc(selected.display)
|
|
689
|
+
: this.multilineOptions
|
|
690
|
+
? ''
|
|
691
|
+
: (_c = (_b = selected.textContent) === null || _b === void 0 ? void 0 : _b.trim()) !== null && _c !== void 0 ? _c : '';
|
|
610
692
|
this.isShowingSelectionDisplay = true;
|
|
611
|
-
if (this.searchText === display)
|
|
693
|
+
if (this.searchText === display) {
|
|
694
|
+
this.checkSelectedDisplay();
|
|
612
695
|
return;
|
|
696
|
+
}
|
|
613
697
|
this.searchText = display;
|
|
614
698
|
}
|
|
615
699
|
setCustomLabel() {
|
|
@@ -644,6 +728,11 @@ export class Q2Search {
|
|
|
644
728
|
}
|
|
645
729
|
// #endregion
|
|
646
730
|
// #region Render Methods
|
|
731
|
+
renderCustomDisplay() {
|
|
732
|
+
if (!this.checkSelectedDisplay())
|
|
733
|
+
return null;
|
|
734
|
+
return (h("slot", { name: "_selected-display", slot: "custom-display" }));
|
|
735
|
+
}
|
|
647
736
|
renderEmpty() {
|
|
648
737
|
if (this.hasEmptySlot) {
|
|
649
738
|
return h("slot", { name: "empty" });
|
|
@@ -673,9 +762,9 @@ export class Q2Search {
|
|
|
673
762
|
return (h("q2-popover", { ref: el => (this.popoverElement = el), controlElement: (_a = this.innerInputContainer) !== null && _a !== void 0 ? _a : undefined, open: this.open, maxHeight: this.popoverMaxHeight, minHeight: this.popoverMinHeight, align: useBlock ? undefined : this.popoverAlignment, block: useBlock }, h("div", { class: "popover-content", "data-loading": this.loading ? 'true' : 'false', "aria-busy": this.loading ? 'true' : null }, h("div", { class: "popover-top-container", hidden: !this.hasPopoverTop && !(this.multiple && this.showSelectedToggle), tabindex: "-1" }, h("slot", { name: "popover-top" }), !this.loading && this.renderMultiSelectHeader()), h("q2-option-list", { ref: el => (this.optionList = el), type: "listbox", id: this.optionListId, label: loc(this.listLabel), multiple: this.multiple, selectedOptions: this.structuredSelectedOptions, showSelected: this.showSelected, customSearch: true, hidden: this.loading, onChange: (e) => e.stopPropagation(), onTctChange: this.onOptionListChange }, h("slot", null)), showEmpty && this.renderEmpty(), h("div", { class: "popover-bottom-container", hidden: !this.hasPopoverBottom, tabindex: "-1" }, h("slot", { name: "popover-bottom" })), this.loading && (h("div", { class: "loading-overlay", "aria-hidden": "true" }, h("q2-loading", { type: "spinner" }))))));
|
|
674
763
|
}
|
|
675
764
|
render() {
|
|
676
|
-
return (h(Fragment, { key: '
|
|
765
|
+
return (h(Fragment, { key: '0686476c153375c6c3cca61cdeaf1267c5ca6b20' }, h("div", { key: 'f5ed583b8da30b2222dd4a466a37e1c10b589fa7', "aria-live": "polite", "aria-atomic": "true", role: "status", class: "sr" }, this.statusMessage), h("click-elsewhere", { key: 'f1172a06706ea799f6020d21610004450e051d9a', class: this.wrapperClasses, role: "presentation", onChange: this.onClickElsewhere }, h("q2-input", { key: '75675f105bd09279650e6aae6b869e0f3f99c270', ref: el => (this.inputField = el), class: "q2-search-input", label: (this.label && loc(this.label)) || '', value: this.searchText, iconLeft: "search", clearable: this.clearable && !this.loading && !!this.searchText, disabled: this.disabled, optional: this.optional, readonly: !!this.readonly, placeholder: this.placeholder ? loc(this.placeholder) : undefined, hideLabel: this.hideLabel, errors: (Array.isArray(this.errors) && this.errors.length > 0 && this.errors.map(e => loc(e))) ||
|
|
677
766
|
(this.invalid && ['tecton.element.search.invalid']) ||
|
|
678
|
-
[], ariaExpanded: this.isInputOnlyMode ? undefined : `${this.open}`, ariaControls: this.isInputOnlyMode ? undefined : this.optionListId, ariaHaspopup: this.isInputOnlyMode ? undefined : 'listbox', hideMessages: true, _role: this.isInputOnlyMode ? undefined : 'combobox', onTctInput: this.inputInputHandler, onInput: (e) => e.stopImmediatePropagation(), onChange: (e) => e.stopPropagation(), onTctChange: (e) => e.stopPropagation(), badgeValue: this.badgeValue }), this.renderOptionsDropdown())));
|
|
767
|
+
[], ariaExpanded: this.isInputOnlyMode ? undefined : `${this.open}`, ariaControls: this.isInputOnlyMode ? undefined : this.optionListId, ariaHaspopup: this.isInputOnlyMode ? undefined : 'listbox', hideMessages: true, _role: this.isInputOnlyMode ? undefined : 'combobox', onTctInput: this.inputInputHandler, onInput: (e) => e.stopImmediatePropagation(), onChange: (e) => e.stopPropagation(), onTctChange: (e) => e.stopPropagation(), badgeValue: this.badgeValue }, this.renderCustomDisplay()), this.renderOptionsDropdown())));
|
|
679
768
|
}
|
|
680
769
|
static get is() { return "q2-search"; }
|
|
681
770
|
static get encapsulation() { return "shadow"; }
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { expect } from "@playwright/test";
|
|
2
|
+
import { test } from "@stencil/playwright";
|
|
3
|
+
import { setupPage, THEMES } from "../../../utils/test/vr-helpers";
|
|
4
|
+
const OPTIONS = `
|
|
5
|
+
<q2-option value="1" display="Apothecary"></q2-option>
|
|
6
|
+
<q2-option value="2" display="Borant"></q2-option>
|
|
7
|
+
<q2-option value="3" display="Valtay"></q2-option>
|
|
8
|
+
`;
|
|
9
|
+
const ERRORS = ['This field is required.', 'The value entered is invalid.'];
|
|
10
|
+
const VARIANTS = [
|
|
11
|
+
{
|
|
12
|
+
name: 'default',
|
|
13
|
+
html: '<q2-search label="Search" placeholder="Type to search"></q2-search>',
|
|
14
|
+
states: ['resting', 'focus'],
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: 'clearable-with-value',
|
|
18
|
+
html: `<q2-search label="Search" clearable value="1">${OPTIONS}</q2-search>`,
|
|
19
|
+
states: ['resting'],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: 'optional',
|
|
23
|
+
html: '<q2-search label="Search" optional placeholder="Type to search"></q2-search>',
|
|
24
|
+
states: ['resting'],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'readonly',
|
|
28
|
+
html: `<q2-search label="Search" readonly value="1">${OPTIONS}</q2-search>`,
|
|
29
|
+
states: ['resting'],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'disabled',
|
|
33
|
+
html: '<q2-search label="Search" disabled placeholder="Type to search"></q2-search>',
|
|
34
|
+
states: ['resting'],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'errored',
|
|
38
|
+
html: '<q2-search label="Search" placeholder="Type to search"></q2-search>',
|
|
39
|
+
states: ['resting'],
|
|
40
|
+
setup: 'errors',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'expanded',
|
|
44
|
+
html: `<q2-search label="Search">${OPTIONS}</q2-search>`,
|
|
45
|
+
states: ['expanded', 'expanded-option-hover', 'expanded-option-focus'],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'loading',
|
|
49
|
+
html: '<q2-search label="Search" loading placeholder="Type to search"></q2-search>',
|
|
50
|
+
states: ['expanded'],
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'no-results',
|
|
54
|
+
html: '<q2-search label="Search"></q2-search>',
|
|
55
|
+
states: ['expanded'],
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'multiple',
|
|
59
|
+
html: `<q2-search label="Search" multiple filter>${OPTIONS}</q2-search>`,
|
|
60
|
+
states: ['expanded', 'expanded-option-hover', 'expanded-option-focus'],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'multiple-show-selected-toggle',
|
|
64
|
+
html: `<q2-search label="Search" multiple filter show-selected-toggle>${OPTIONS}</q2-search>`,
|
|
65
|
+
states: ['expanded'],
|
|
66
|
+
setup: 'multiple-selected',
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
const applySetup = async (page, setup) => {
|
|
70
|
+
if (!setup)
|
|
71
|
+
return;
|
|
72
|
+
await page.evaluate(({ setup, errors }) => {
|
|
73
|
+
const el = document.querySelector('q2-search');
|
|
74
|
+
if (setup === 'errors')
|
|
75
|
+
el.errors = errors;
|
|
76
|
+
if (setup === 'multiple-selected')
|
|
77
|
+
el.selectedOptions = ['1'];
|
|
78
|
+
}, { setup, errors: ERRORS });
|
|
79
|
+
};
|
|
80
|
+
const openSearch = async (page, hasOptions) => {
|
|
81
|
+
await page.evaluate(() => {
|
|
82
|
+
const el = document.querySelector('q2-search');
|
|
83
|
+
return el.openPopover();
|
|
84
|
+
});
|
|
85
|
+
if (hasOptions) {
|
|
86
|
+
await page.locator('q2-option').first().waitFor({ state: 'visible' });
|
|
87
|
+
}
|
|
88
|
+
// Wait for the popover open transition (box-shadow, opacity) to fully settle.
|
|
89
|
+
await page.waitForTimeout(300);
|
|
90
|
+
};
|
|
91
|
+
const setup = (page, variant, theme) => setupPage(page, variant.html, { theme, setupLoc: true }).then(() => applySetup(page, variant.setup));
|
|
92
|
+
const restingCase = (variant, theme) => {
|
|
93
|
+
test(`q2-search--${variant.name}--resting — ${theme}`, async ({ page }) => {
|
|
94
|
+
await setup(page, variant, theme);
|
|
95
|
+
await expect(page).toHaveScreenshot(`q2-search--${variant.name}--resting--${theme}.png`);
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
const focusCase = (variant, theme) => {
|
|
99
|
+
test(`q2-search--${variant.name}--focus — ${theme}`, async ({ page }) => {
|
|
100
|
+
await setup(page, variant, theme);
|
|
101
|
+
await page.keyboard.press('Tab');
|
|
102
|
+
await expect(page).toHaveScreenshot(`q2-search--${variant.name}--focus--${theme}.png`);
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
const expandedCase = (variant, theme) => {
|
|
106
|
+
const hasOptions = !variant.name.includes('loading') && !variant.name.includes('no-results');
|
|
107
|
+
test(`q2-search--${variant.name}--expanded — ${theme}`, async ({ page }) => {
|
|
108
|
+
await setup(page, variant, theme);
|
|
109
|
+
await openSearch(page, hasOptions);
|
|
110
|
+
await expect(page).toHaveScreenshot(`q2-search--${variant.name}--expanded--${theme}.png`);
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
const expandedOptionHoverCase = (variant, theme) => {
|
|
114
|
+
test(`q2-search--${variant.name}--expanded-option-hover — ${theme}`, async ({ page }) => {
|
|
115
|
+
await setup(page, variant, theme);
|
|
116
|
+
await openSearch(page, true);
|
|
117
|
+
await page.locator('q2-option[value="1"]').hover();
|
|
118
|
+
await expect(page).toHaveScreenshot(`q2-search--${variant.name}--expanded-option-hover--${theme}.png`);
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
// ArrowDown after open moves focus to the first option, triggering :focus-visible.
|
|
122
|
+
const expandedOptionFocusCase = (variant, theme) => {
|
|
123
|
+
test(`q2-search--${variant.name}--expanded-option-focus — ${theme}`, async ({ page }) => {
|
|
124
|
+
await setup(page, variant, theme);
|
|
125
|
+
await openSearch(page, true);
|
|
126
|
+
await page.keyboard.press('ArrowDown');
|
|
127
|
+
await expect(page).toHaveScreenshot(`q2-search--${variant.name}--expanded-option-focus--${theme}.png`);
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
const CASE_MAP = {
|
|
131
|
+
resting: restingCase,
|
|
132
|
+
focus: focusCase,
|
|
133
|
+
expanded: expandedCase,
|
|
134
|
+
'expanded-option-hover': expandedOptionHoverCase,
|
|
135
|
+
'expanded-option-focus': expandedOptionFocusCase,
|
|
136
|
+
};
|
|
137
|
+
test.describe('q2-search — variants × themes', () => {
|
|
138
|
+
for (const variant of VARIANTS) {
|
|
139
|
+
for (const theme of THEMES) {
|
|
140
|
+
for (const state of variant.states) {
|
|
141
|
+
CASE_MAP[state](variant, theme);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
});
|
|
@@ -94,7 +94,7 @@ button {
|
|
|
94
94
|
:host {
|
|
95
95
|
display: block;
|
|
96
96
|
background: var(--tct-section-background, var(--tct-section-background-color, var(--t-section-background-color, var(--tct-section-bg, var(--t-section-bg, var(--app-white, #ffffff))))));
|
|
97
|
-
color: var(--tct-section-font-color, var(--t-section-font-color,
|
|
97
|
+
color: var(--tct-section-font-color, var(--t-section-font-color, inherit));
|
|
98
98
|
border-radius: var(--tct-section-border-radius, var(--t-section-border-radius, var(--app-border-radius-1, 4px)));
|
|
99
99
|
margin: var(--tct-section-margin, var(--t-section-margin, var(--app-scale-3x, 15px)));
|
|
100
100
|
border-width: var(--tct-section-border-width, 0);
|
|
@@ -128,8 +128,8 @@ button {
|
|
|
128
128
|
* @prop --tct-select-margin: (<length-percentage>+) Controls the outer margin of the select host.
|
|
129
129
|
* @prop --tct-select-margin-top: (<length-percentage>) Controls the top margin of the select host when --tct-select-margin is not set.
|
|
130
130
|
* @prop --tct-select-margin-bottom: (<length-percentage>) Controls the bottom margin of the select host when --tct-select-margin is not set.
|
|
131
|
-
* @prop --tct-select-input-min-height?: (<length-percentage>) Controls the optional minimum height of the select input.
|
|
132
|
-
* @prop --tct-select-input-max-height?: (<length-percentage>) Controls the optional maximum height of the select input.
|
|
131
|
+
* @prop --tct-select-input-min-height?: (<length-percentage>) Controls the optional minimum height of the select input. Use this to control the height of the select in the empty state, especially when using multiline-options with tall content.
|
|
132
|
+
* @prop --tct-select-input-max-height?: (<length-percentage>) Controls the optional maximum height of the select input. Use this to constrain the height when displaying multiline selected content.
|
|
133
133
|
* @prop --tct-select-multi-select-option-background?: (<color>) Controls the optional background color of multi-select option chips in their default state.
|
|
134
134
|
* @prop --tct-select-multi-select-option-color?: (<color>) Controls the optional text color of multi-select option chips in their default state.
|
|
135
135
|
* @prop --tct-select-multi-select-option-active-background: (<color>) Controls the background color of multi-select option chips when active (checked).
|
|
@@ -161,6 +161,8 @@ button {
|
|
|
161
161
|
::slotted([slot=_selected-display]) {
|
|
162
162
|
width: 100%;
|
|
163
163
|
min-height: var(--comp-selected-display-height, 44px);
|
|
164
|
+
padding-top: var(--tct-select-selected-display-padding, var(--app-scale-2x, 10px));
|
|
165
|
+
padding-bottom: var(--tct-select-selected-display-padding, var(--app-scale-2x, 10px));
|
|
164
166
|
}
|
|
165
167
|
|
|
166
168
|
.custom-display-content {
|
|
@@ -82,6 +82,8 @@ export class Q2Select {
|
|
|
82
82
|
* This property is only relevant for `multiple` (i.e., multi-select) implementations.
|
|
83
83
|
*/
|
|
84
84
|
this.selectedOptions = [];
|
|
85
|
+
/** Determines whether to show a success state. The error state takes precedence when both are set. */
|
|
86
|
+
this.valid = false;
|
|
85
87
|
this.addTouchEventListeners = () => {
|
|
86
88
|
if (!isMobile() || !this.popoverElement)
|
|
87
89
|
return;
|
|
@@ -271,6 +273,22 @@ export class Q2Select {
|
|
|
271
273
|
return;
|
|
272
274
|
this.open = open;
|
|
273
275
|
};
|
|
276
|
+
this.onSelectedDisplayClick = (event) => {
|
|
277
|
+
// Stop click from bubbling to q2-input's onClick (which would toggle the dropdown)
|
|
278
|
+
event.stopPropagation();
|
|
279
|
+
if (this.open) {
|
|
280
|
+
this.focusInput();
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
this.prioritizeSearch = this.searchable;
|
|
284
|
+
this.clearSelectedDisplay();
|
|
285
|
+
this.openDropdownWithoutActiveElement();
|
|
286
|
+
this.focusInput();
|
|
287
|
+
};
|
|
288
|
+
this.onSelectedDisplayMousedown = (event) => {
|
|
289
|
+
// Prevent focus shift away from the hidden input
|
|
290
|
+
event.preventDefault();
|
|
291
|
+
};
|
|
274
292
|
this.removeTouchEventListeners = () => {
|
|
275
293
|
if (!isMobile() || !this.popoverElement)
|
|
276
294
|
return;
|
|
@@ -495,6 +513,8 @@ export class Q2Select {
|
|
|
495
513
|
}
|
|
496
514
|
else {
|
|
497
515
|
this.removeTouchEventListeners();
|
|
516
|
+
// Reset prioritizeSearch when dropdown closes to ensure selected display can be restored
|
|
517
|
+
this.prioritizeSearch = false;
|
|
498
518
|
}
|
|
499
519
|
this.scheduledAfterRender.push(async () => {
|
|
500
520
|
await waitForNextPaint();
|
|
@@ -657,10 +677,16 @@ export class Q2Select {
|
|
|
657
677
|
if (namedSlot.firstElementChild.outerHTML !== selectionClone.outerHTML) {
|
|
658
678
|
namedSlot.replaceChild(selectionClone, namedSlot.firstElementChild);
|
|
659
679
|
}
|
|
680
|
+
namedSlot.removeEventListener('mousedown', this.onSelectedDisplayMousedown);
|
|
681
|
+
namedSlot.addEventListener('mousedown', this.onSelectedDisplayMousedown);
|
|
682
|
+
namedSlot.removeEventListener('click', this.onSelectedDisplayClick);
|
|
683
|
+
namedSlot.addEventListener('click', this.onSelectedDisplayClick);
|
|
660
684
|
}
|
|
661
685
|
else {
|
|
662
686
|
namedSlot = document.createElement('div');
|
|
663
687
|
namedSlot.slot = '_selected-display';
|
|
688
|
+
namedSlot.addEventListener('mousedown', this.onSelectedDisplayMousedown);
|
|
689
|
+
namedSlot.addEventListener('click', this.onSelectedDisplayClick);
|
|
664
690
|
namedSlot.appendChild(selectionClone);
|
|
665
691
|
this.hostElement.appendChild(namedSlot);
|
|
666
692
|
}
|
|
@@ -690,8 +716,12 @@ export class Q2Select {
|
|
|
690
716
|
mirrorEmit(this, ['input', 'tctInput'], { query: '' });
|
|
691
717
|
}
|
|
692
718
|
clearSelectedDisplay() {
|
|
693
|
-
|
|
694
|
-
(
|
|
719
|
+
const slot = this.selectedDisplaySlot;
|
|
720
|
+
if (slot) {
|
|
721
|
+
slot.removeEventListener('mousedown', this.onSelectedDisplayMousedown);
|
|
722
|
+
slot.removeEventListener('click', this.onSelectedDisplayClick);
|
|
723
|
+
slot.remove();
|
|
724
|
+
}
|
|
695
725
|
}
|
|
696
726
|
clearValue() {
|
|
697
727
|
const { multiple } = this;
|
|
@@ -786,7 +816,7 @@ export class Q2Select {
|
|
|
786
816
|
this.errors.length > 0 &&
|
|
787
817
|
this.errors.map(error => loc(error))) ||
|
|
788
818
|
(this.invalid && ['tecton.element.select.invalid']) ||
|
|
789
|
-
[], disabled: this.disabled, optional: this.optional, readonly: !!this.readonly, placeholder: this.placeholder || undefined, hideLabel: this.hideLabel, ariaExpanded: `${this.open}`, ariaControls: "option-list", ariaHaspopup: "listbox", "test-id": "toggleDropdown", "hide-messages": true, iconRight: "chevron-down", onClick: this.inputClickHandler, onInput: e => e.stopImmediatePropagation(), onTctInput: this.inputInputHandler, onKeyDown: this.inputKeydownHandler, onFocus: this.inputFocusHandler, onBlur: this.inputBlurHandler, onChange: e => e.stopPropagation(), onTctChange: this.inputChangeHandler, badgeValue: this.badgeValue, badgeTheme: this.inputFocused ? 'primary' : undefined, _role: "combobox", _preventEntry: !this.searchable }, this.renderCustomDisplay()), h("div", { class: "custom-display-content", hidden: !this.hasCustomDisplay || !!this.searchText, onClick: this.onCustomDisplayClick }, h("slot", { name: "q2-select-display" })), this.renderOptionsDropdown()));
|
|
819
|
+
[], disabled: this.disabled, optional: this.optional, readonly: !!this.readonly, placeholder: this.placeholder || undefined, hideLabel: this.hideLabel, valid: this.valid, ariaExpanded: `${this.open}`, ariaControls: "option-list", ariaHaspopup: "listbox", "test-id": "toggleDropdown", "hide-messages": true, iconRight: "chevron-down", onClick: this.inputClickHandler, onInput: e => e.stopImmediatePropagation(), onTctInput: this.inputInputHandler, onKeyDown: this.inputKeydownHandler, onFocus: this.inputFocusHandler, onBlur: this.inputBlurHandler, onChange: e => e.stopPropagation(), onTctChange: this.inputChangeHandler, badgeValue: this.badgeValue, badgeTheme: this.inputFocused ? 'primary' : undefined, _role: "combobox", _preventEntry: !this.searchable }, this.renderCustomDisplay()), h("div", { class: "custom-display-content", hidden: !this.hasCustomDisplay || !!this.searchText, onClick: this.onCustomDisplayClick }, h("slot", { name: "q2-select-display" })), this.renderOptionsDropdown()));
|
|
790
820
|
}
|
|
791
821
|
renderVisibilityToggle() {
|
|
792
822
|
var _a, _b;
|
|
@@ -797,7 +827,7 @@ export class Q2Select {
|
|
|
797
827
|
]), checked: showSelected, "test-id": "selectedOptionsButton", onClick: this.showSelectedOptions, onKeyDown: this.visibilityToggleKeyDown }), h("label", { htmlFor: "selected" }, loc('tecton.element.select.multiHeader.selected', [selectedOptionsCount]))))));
|
|
798
828
|
}
|
|
799
829
|
render() {
|
|
800
|
-
return (h("click-elsewhere", { key: '
|
|
830
|
+
return (h("click-elsewhere", { key: 'a08e10cf8bd4e2d3f210d36003417f2a1dec4b21', class: this.wrapperClasses, role: "presentation", onChange: this.clickedElsewhere }, this.renderSelectField()));
|
|
801
831
|
}
|
|
802
832
|
static get is() { return "q2-select"; }
|
|
803
833
|
static get encapsulation() { return "shadow"; }
|
|
@@ -1227,6 +1257,26 @@ export class Q2Select {
|
|
|
1227
1257
|
"setter": false,
|
|
1228
1258
|
"defaultValue": "[]"
|
|
1229
1259
|
},
|
|
1260
|
+
"valid": {
|
|
1261
|
+
"type": "boolean",
|
|
1262
|
+
"mutable": false,
|
|
1263
|
+
"complexType": {
|
|
1264
|
+
"original": "boolean",
|
|
1265
|
+
"resolved": "boolean",
|
|
1266
|
+
"references": {}
|
|
1267
|
+
},
|
|
1268
|
+
"required": false,
|
|
1269
|
+
"optional": false,
|
|
1270
|
+
"docs": {
|
|
1271
|
+
"tags": [],
|
|
1272
|
+
"text": "Determines whether to show a success state. The error state takes precedence when both are set."
|
|
1273
|
+
},
|
|
1274
|
+
"getter": false,
|
|
1275
|
+
"setter": false,
|
|
1276
|
+
"reflect": true,
|
|
1277
|
+
"attribute": "valid",
|
|
1278
|
+
"defaultValue": "false"
|
|
1279
|
+
},
|
|
1230
1280
|
"value": {
|
|
1231
1281
|
"type": "string",
|
|
1232
1282
|
"mutable": true,
|
|
@@ -44,6 +44,11 @@ const VARIANTS = [
|
|
|
44
44
|
states: ['resting'],
|
|
45
45
|
setup: 'errors',
|
|
46
46
|
},
|
|
47
|
+
{
|
|
48
|
+
name: 'valid',
|
|
49
|
+
html: `<q2-select label="My select" placeholder="Select an option" valid value="2">${OPTIONS}</q2-select>`,
|
|
50
|
+
states: ['resting'],
|
|
51
|
+
},
|
|
47
52
|
];
|
|
48
53
|
const applySelectSetup = async (page, setup) => {
|
|
49
54
|
if (!setup)
|
|
@@ -275,7 +275,7 @@ li {
|
|
|
275
275
|
}
|
|
276
276
|
|
|
277
277
|
.step-label {
|
|
278
|
-
color: var(--tct-stepper-label-color, var(--tct-stepper-title-color, var(--t-stepper-title-color,
|
|
278
|
+
color: var(--tct-stepper-label-color, var(--tct-stepper-title-color, var(--t-stepper-title-color, inherit)));
|
|
279
279
|
font-size: var(--tct-stepper-label-font-size, var(--tct-stepper-title-font-size, var(--t-stepper-title-font-size, var(--app-font-size-small, 12px))));
|
|
280
280
|
line-height: var(--tct-stepper-label-line-height, 1.5em);
|
|
281
281
|
text-overflow: ellipsis;
|
|
@@ -290,7 +290,7 @@ li {
|
|
|
290
290
|
}
|
|
291
291
|
|
|
292
292
|
.step-description {
|
|
293
|
-
color: var(--tct-stepper-description-color, var(--t-stepper-description-color,
|
|
293
|
+
color: var(--tct-stepper-description-color, var(--t-stepper-description-color, inherit));
|
|
294
294
|
font-size: var(--tct-stepper-description-font-size, var(--t-stepper-description-font-size, var(--app-font-size-small, 12px)));
|
|
295
295
|
text-overflow: ellipsis;
|
|
296
296
|
overflow: hidden;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { h, Fragment, } from "@stencil/core";
|
|
2
2
|
import { loc, overrideFocus, isEventFromElement, createGuid } from "../../utils/index";
|
|
3
3
|
import mirrorEmit from "../../utils/mirror-emit";
|
|
4
|
+
import sanitizeHTMLString from "../../utils/sanitize-html-string";
|
|
4
5
|
/**
|
|
5
6
|
* @name Stepper
|
|
6
7
|
* @category Display
|
|
@@ -273,14 +274,14 @@ export class Q2Stepper {
|
|
|
273
274
|
if (isPaneDisabled)
|
|
274
275
|
stepClasses.push('pane-disabled');
|
|
275
276
|
const disabled = isLocked || stepNumber > lastEnabledStep;
|
|
276
|
-
return (h("li", { role: "presentation" }, h("button", { class: stepClasses.join(' '), type: "button", "aria-labelledby": labelId, "aria-describedBy": descriptionId, "aria-label": btnLabel, "aria-selected": `${isCurrentStep}`, "aria-disabled": disabled ? 'true' : undefined, role: "tab", tabIndex: isCurrentStep ? 0 : -1, onKeyDown: ev => this.onStepKeyDown(ev, stepNumber), onClick: ev => !isPaneDisabled && !disabled && this.onStepClick(ev, stepNumber) }, h(Fragment, null, statusIcon ? (h("div", { class: "step-icon" }, h("q2-icon", { type: statusIcon }))) : (h("div", { class: "step-bubble" }, stepNumber)), labelId && (h("div", { class: "step-label", id: labelId, innerHTML: label })), labelId && descriptionId && (h("div", { class: "step-description", id: descriptionId, innerHTML: description })))), stepIndex ? h("div", { class: "step-divider" }) : ''));
|
|
277
|
+
return (h("li", { role: "presentation" }, h("button", { class: stepClasses.join(' '), type: "button", "aria-labelledby": labelId, "aria-describedBy": descriptionId, "aria-label": btnLabel, "aria-selected": `${isCurrentStep}`, "aria-disabled": disabled ? 'true' : undefined, role: "tab", tabIndex: isCurrentStep ? 0 : -1, onKeyDown: ev => this.onStepKeyDown(ev, stepNumber), onClick: ev => !isPaneDisabled && !disabled && this.onStepClick(ev, stepNumber) }, h(Fragment, null, statusIcon ? (h("div", { class: "step-icon" }, h("q2-icon", { type: statusIcon }))) : (h("div", { class: "step-bubble" }, stepNumber)), labelId && (h("div", { class: "step-label", id: labelId, innerHTML: sanitizeHTMLString(label) })), labelId && descriptionId && (h("div", { class: "step-description", id: descriptionId, innerHTML: sanitizeHTMLString(description) })))), stepIndex ? h("div", { class: "step-divider" }) : ''));
|
|
277
278
|
}
|
|
278
279
|
render() {
|
|
279
280
|
const { stepCount, scrollEnabled, showScrollLeft, showScrollRight } = this;
|
|
280
281
|
const containerClasses = ['step-container'];
|
|
281
282
|
if (scrollEnabled)
|
|
282
283
|
containerClasses.push('has-scroll');
|
|
283
|
-
return (h(Fragment, { key: '
|
|
284
|
+
return (h(Fragment, { key: 'c1e21a36e0b2f684f4520b0f75f78affd73359bd' }, h("div", { key: '3791e857d27aa3fea928f663268f21270d499023', class: containerClasses.join(' ') }, scrollEnabled && (h(Fragment, { key: '19b689b2b56f52099f22f859264e33e16fd918bf' }, h("div", { key: '5b1b1e00034fa009c555924c2067fed6369740cb', class: "gradient-left", hidden: !showScrollLeft }), h("div", { key: 'b5de1b413f6c8ce006207926f26ae845594228eb', class: "gradient-right", hidden: !showScrollRight }), h("q2-btn", { key: '832a97c5619cadb1167f6e1e7ecd94ab4f5f3cb1', class: "btn-left", hideLabel: true, hidden: !this.showScrollLeft, label: loc('tecton.element.stepper.scrollLeft'), onTctClick: () => this.onScrollBtnClick('left') }, h("q2-icon", { key: '3e53b2b2f19bbba59a37016b9cdf1a302b030b63', type: "chevron-left" })), h("q2-btn", { key: 'ffacbb0d2f9c15a503221a2dbc4662ba6f3c3272', class: "btn-right", hideLabel: true, hidden: !this.showScrollRight, label: loc('tecton.element.stepper.scrollRight'), onTctClick: () => this.onScrollBtnClick('right') }, h("q2-icon", { key: '2c60dc5392c9c9eec99dd24b229bbd1fa5e9587f', type: "chevron-right" })))), h("ul", { key: '25806a72f9f0cda2e032a81dbaac9f808be385c9', onScroll: this.checkScrollState, ref: el => (this.listElement = el), role: "tablist" }, stepCount > 0 && [...Array(stepCount).keys()].map(stepIndex => this.renderStepBtn(stepIndex)))), h("div", { key: '622b3ed56e3f66adc33bf197b7874a7b9bf8667f', role: "list" }, h("slot", { key: '73c4321743596227054e317c271bcc044179363b', onSlotchange: () => this.onSlotChange() }))));
|
|
284
285
|
}
|
|
285
286
|
static get is() { return "q2-stepper"; }
|
|
286
287
|
static get encapsulation() { return "shadow"; }
|
|
@@ -134,7 +134,7 @@ button {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
.step-description {
|
|
137
|
-
color: var(--tct-stepper-vertical-description-color, var(--tct-advanced-stepper-description-color, var(--t-advanced-stepper-description-color,
|
|
137
|
+
color: var(--tct-stepper-vertical-description-color, var(--tct-advanced-stepper-description-color, var(--t-advanced-stepper-description-color, inherit)));
|
|
138
138
|
font-size: var(--tct-stepper-vertical-description-font-size, var(--tct-advanced-stepper-description-font-size, var(--t-advanced-stepper-description-font-size, var(--app-font-size-small, 12px))));
|
|
139
139
|
padding-bottom: 0.2em;
|
|
140
140
|
}
|
|
@@ -145,7 +145,7 @@ ul {
|
|
|
145
145
|
--comp-btn-icon-visibility: var(--tct-stepper-vertical-btn-icon-visibility, visible);
|
|
146
146
|
--comp-btn-content-gap: var(--tct-stepper-vertical-btn-gap, var(--tct-advanced-stepper-btn-gap, var(--t-advanced-stepper-btn-gap, var(--app-scale-3x, 15px))));
|
|
147
147
|
--comp-btn-label-font-size: var(--tct-stepper-vertical-btn-label-font-size, var(--tct-advanced-stepper-btn-label-font-size, var(--t-advanced-stepper-btn-label-font-size, 16px)));
|
|
148
|
-
--comp-btn-label-color: var(--tct-stepper-vertical-label-color, var(--tct-advanced-stepper-label-color, var(--t-advanced-stepper-label-color,
|
|
148
|
+
--comp-btn-label-color: var(--tct-stepper-vertical-label-color, var(--tct-advanced-stepper-label-color, var(--t-advanced-stepper-label-color, inherit)));
|
|
149
149
|
--comp-tween: var(--tct-stepper-vertical-tween, var(--tct-advanced-stepper-tween, var(--t-advanced-stepper-tween, var(--app-tween-1, 0.2s ease))));
|
|
150
150
|
--comp-bullet-bg: var(--tct-stepper-vertical-bullet-active-background, var(--tct-advanced-stepper-bullet-active-bg, var(--t-advanced-stepper-bullet-active-bg, var(--t-primary, #0079c1))));
|
|
151
151
|
list-style: none;
|