q2-tecton-elements 1.71.2 → 1.72.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 +1282 -594
- package/dist/cjs/click-elsewhere_3.cjs.entry.js +10 -9
- package/dist/cjs/{index-SpDCZABA.js → index-BY3aao8R.js} +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/{q2-action-group_2.cjs.entry.js → q2-action-group.cjs.entry.js} +1 -89
- package/dist/cjs/q2-action-sheet.cjs.entry.js +1 -1
- package/dist/cjs/q2-badge_2.cjs.entry.js +113 -12
- package/dist/cjs/q2-btn_2.cjs.entry.js +2 -2
- package/dist/cjs/q2-calendar.cjs.entry.js +7 -5
- package/dist/cjs/q2-card-image.cjs.entry.js +4 -4
- package/dist/cjs/q2-card.cjs.entry.js +1 -1
- 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 +1 -1
- package/dist/cjs/q2-checkbox-group.cjs.entry.js +2 -2
- package/dist/cjs/q2-checkbox_2.cjs.entry.js +3 -3
- package/dist/cjs/q2-context.cjs.entry.js +4 -3
- package/dist/cjs/q2-data-table.cjs.entry.js +2 -2
- package/dist/cjs/q2-detail.cjs.entry.js +1 -1
- 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 +38 -37
- package/dist/cjs/q2-file-picker.cjs.entry.js +60 -4
- package/dist/cjs/q2-icon.cjs.entry.js +1 -1
- package/dist/cjs/q2-item.cjs.entry.js +2 -2
- package/dist/cjs/q2-link_2.cjs.entry.js +1 -1
- package/dist/cjs/q2-loc.cjs.entry.js +1 -1
- package/dist/cjs/q2-message.cjs.entry.js +2 -2
- package/dist/cjs/q2-meter.cjs.entry.js +1 -1
- package/dist/cjs/q2-modal.cjs.entry.js +59 -17
- 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 +2 -2
- package/dist/cjs/q2-radio-group.cjs.entry.js +22 -4
- package/dist/cjs/q2-radio.cjs.entry.js +3 -3
- package/dist/cjs/q2-relative-time.cjs.entry.js +3 -3
- package/dist/cjs/q2-resize-observer.cjs.entry.js +92 -0
- package/dist/cjs/q2-search.cjs.entry.js +2 -2
- package/dist/cjs/q2-section.cjs.entry.js +7 -7
- package/dist/cjs/q2-select.cjs.entry.js +35 -19
- package/dist/cjs/q2-stepper-pane.cjs.entry.js +2 -2
- package/dist/cjs/q2-stepper-vertical.cjs.entry.js +2 -2
- package/dist/cjs/q2-stepper.cjs.entry.js +1 -1
- package/dist/cjs/q2-surface.cjs.entry.js +1 -1
- 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 +5 -3
- package/dist/collection/components/q2-btn/q2-btn.css +79 -21
- package/dist/collection/components/q2-btn/test/q2-btn-test.vr.js +156 -3
- package/dist/collection/components/q2-calendar/q2-calendar.css +3 -0
- package/dist/collection/components/q2-calendar/q2-calendar.js +5 -3
- package/dist/collection/components/q2-calendar/test/q2-calendar-test.vr.js +23 -2
- package/dist/collection/components/q2-card/test/q2-card-test.vr.js +4 -0
- package/dist/collection/components/q2-card-image/q2-card-image.css +89 -134
- package/dist/collection/components/q2-card-image/q2-card-image.js +4 -4
- package/dist/collection/components/q2-card-image/test/q2-card-image-test.vr.js +4 -0
- package/dist/collection/components/q2-carousel/test/q2-carousel-test.vr.js +13 -0
- package/dist/collection/components/q2-checkbox/q2-checkbox.css +2 -2
- package/dist/collection/components/q2-checkbox-group/q2-checkbox-group.css +2 -0
- package/dist/collection/components/q2-context/q2-context.css +5 -0
- package/dist/collection/components/q2-context/q2-context.js +2 -1
- package/dist/collection/components/q2-context/test/q2-context-test.vr.js +11 -1
- package/dist/collection/components/q2-data-table/q2-data-table.css +3 -0
- package/dist/collection/components/q2-data-table/test/q2-data-table-test.vr.js +5 -0
- package/dist/collection/components/q2-dropdown/q2-dropdown.css +2 -0
- package/dist/collection/components/q2-dropdown/q2-dropdown.js +1 -1
- package/dist/collection/components/q2-dropdown/test/q2-dropdown-test.vr.js +30 -0
- package/dist/collection/components/q2-editable-field/q2-editable-field.css +2 -0
- package/dist/collection/components/q2-editable-field/q2-editable-field.js +38 -43
- package/dist/collection/components/q2-file-picker/q2-file-picker.css +27 -0
- package/dist/collection/components/q2-file-picker/q2-file-picker.js +98 -2
- package/dist/collection/components/q2-file-picker/test/q2-file-picker-test.vr.js +22 -0
- package/dist/collection/components/q2-input/q2-input.css +67 -1
- package/dist/collection/components/q2-input/q2-input.js +155 -13
- package/dist/collection/components/q2-input/test/q2-input-test.vr.js +35 -0
- package/dist/collection/components/q2-item/q2-item.css +3 -1
- package/dist/collection/components/q2-item/test/q2-item-test.vr.js +6 -0
- package/dist/collection/components/q2-message/q2-message.css +5 -5
- package/dist/collection/components/q2-modal/q2-modal.css +40 -3
- package/dist/collection/components/q2-modal/q2-modal.js +100 -16
- package/dist/collection/components/q2-modal/test/q2-modal-test.vr.js +25 -0
- package/dist/collection/components/q2-pill/q2-pill.css +2 -2
- package/dist/collection/components/q2-popover/q2-popover.css +3 -2
- package/dist/collection/components/q2-popover/q2-popover.js +8 -7
- package/dist/collection/components/q2-radio/q2-radio.css +158 -104
- package/dist/collection/components/q2-radio/q2-radio.js +1 -1
- package/dist/collection/components/q2-radio/test/q2-radio-test.vr.js +25 -2
- package/dist/collection/components/q2-radio-group/q2-radio-group.css +39 -2
- package/dist/collection/components/q2-radio-group/q2-radio-group.js +68 -2
- package/dist/collection/components/q2-radio-group/test/q2-radio-group-test.vr.js +43 -1
- package/dist/collection/components/q2-relative-time/q2-relative-time.js +2 -2
- package/dist/collection/components/q2-search/q2-search.css +2 -0
- package/dist/collection/components/q2-section/q2-section.css +2 -0
- package/dist/collection/components/q2-section/q2-section.js +6 -6
- package/dist/collection/components/q2-select/q2-select.css +3 -0
- package/dist/collection/components/q2-select/q2-select.js +37 -18
- package/dist/collection/components/q2-select/test/q2-select-test.vr.js +13 -0
- package/dist/collection/components/q2-stepper-pane/q2-stepper-pane.js +1 -1
- package/dist/collection/components/q2-stepper-vertical/q2-stepper-vertical.js +1 -1
- package/dist/collection/components/q2-surface/q2-surface.js +1 -1
- 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/tecton-tab-pane/tecton-tab-pane.js +5 -3
- package/dist/collection/utils/index.js +1 -1
- package/dist/collection/utils/test/vr-helpers.js +16 -2
- package/dist/components/index2.js +1 -1
- package/dist/components/q2-btn2.js +1 -1
- package/dist/components/q2-calendar.js +11 -9
- package/dist/components/q2-card-image.js +24 -24
- package/dist/components/q2-checkbox-group.js +6 -6
- package/dist/components/q2-checkbox2.js +1 -1
- package/dist/components/q2-context.js +27 -26
- package/dist/components/q2-data-table.js +1 -1
- package/dist/components/q2-dropdown.js +21 -21
- package/dist/components/q2-editable-field.js +33 -35
- package/dist/components/q2-file-picker.js +70 -10
- package/dist/components/q2-input2.js +268 -163
- package/dist/components/q2-item2.js +1 -1
- package/dist/components/q2-message2.js +24 -24
- package/dist/components/q2-modal.js +96 -78
- package/dist/components/q2-pill.js +1 -1
- package/dist/components/q2-popover2.js +29 -26
- package/dist/components/q2-radio-group.js +70 -40
- package/dist/components/q2-radio.js +40 -55
- package/dist/components/q2-relative-time.js +5 -5
- package/dist/components/q2-search.js +1 -1
- package/dist/components/q2-section.js +33 -33
- package/dist/components/q2-select2.js +46 -39
- package/dist/components/q2-stepper-pane.js +15 -11
- package/dist/components/q2-stepper-vertical.js +4 -4
- package/dist/components/q2-surface.js +3 -3
- package/dist/components/q2-tab-container.js +21 -21
- package/dist/components/q2-tab-pane.js +2 -2
- package/dist/components/q2-tag2.js +5 -5
- package/dist/components/tecton-tab-pane.js +8 -7
- package/dist/esm/click-elsewhere_3.entry.js +10 -9
- package/dist/esm/{index-Cps4jSQM.js → index-DJw6Feh0.js} +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/{q2-action-group_2.entry.js → q2-action-group.entry.js} +3 -90
- package/dist/esm/q2-action-sheet.entry.js +1 -1
- package/dist/esm/q2-badge_2.entry.js +113 -12
- package/dist/esm/q2-btn_2.entry.js +2 -2
- package/dist/esm/q2-calendar.entry.js +7 -5
- package/dist/esm/q2-card-image.entry.js +4 -4
- package/dist/esm/q2-card.entry.js +1 -1
- 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 +1 -1
- package/dist/esm/q2-checkbox-group.entry.js +2 -2
- package/dist/esm/q2-checkbox_2.entry.js +3 -3
- package/dist/esm/q2-context.entry.js +4 -3
- package/dist/esm/q2-data-table.entry.js +2 -2
- package/dist/esm/q2-detail.entry.js +1 -1
- 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 +38 -37
- package/dist/esm/q2-file-picker.entry.js +60 -4
- package/dist/esm/q2-icon.entry.js +1 -1
- package/dist/esm/q2-item.entry.js +2 -2
- package/dist/esm/q2-link_2.entry.js +1 -1
- package/dist/esm/q2-loc.entry.js +1 -1
- package/dist/esm/q2-message.entry.js +2 -2
- package/dist/esm/q2-meter.entry.js +1 -1
- package/dist/esm/q2-modal.entry.js +59 -17
- 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 +2 -2
- package/dist/esm/q2-radio-group.entry.js +22 -4
- package/dist/esm/q2-radio.entry.js +3 -3
- package/dist/esm/q2-relative-time.entry.js +3 -3
- package/dist/esm/q2-resize-observer.entry.js +90 -0
- package/dist/esm/q2-search.entry.js +2 -2
- package/dist/esm/q2-section.entry.js +7 -7
- package/dist/esm/q2-select.entry.js +35 -19
- package/dist/esm/q2-stepper-pane.entry.js +2 -2
- package/dist/esm/q2-stepper-vertical.entry.js +2 -2
- package/dist/esm/q2-stepper.entry.js +1 -1
- package/dist/esm/q2-surface.entry.js +1 -1
- 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 +5 -3
- package/dist/q2-tecton-elements/click-elsewhere_3.entry.js +32 -29
- package/dist/q2-tecton-elements/{index-Cps4jSQM.js → index-DJw6Feh0.js} +1 -1
- package/dist/q2-tecton-elements/{q2-action-group_2.entry.js → q2-action-group.entry.js} +35 -113
- package/dist/q2-tecton-elements/q2-action-sheet.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-badge_2.entry.js +240 -140
- package/dist/q2-tecton-elements/q2-btn_2.entry.js +2 -2
- package/dist/q2-tecton-elements/q2-calendar.entry.js +14 -12
- package/dist/q2-tecton-elements/q2-card-image.entry.js +9 -9
- package/dist/q2-tecton-elements/q2-card.entry.js +1 -1
- 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 +31 -31
- package/dist/q2-tecton-elements/q2-chart-bar.entry.js +16 -16
- package/dist/q2-tecton-elements/q2-chart-donut.entry.js +6 -6
- package/dist/q2-tecton-elements/q2-checkbox-group.entry.js +2 -2
- package/dist/q2-tecton-elements/q2-checkbox_2.entry.js +7 -7
- package/dist/q2-tecton-elements/q2-context.entry.js +22 -21
- package/dist/q2-tecton-elements/q2-data-table.entry.js +34 -34
- package/dist/q2-tecton-elements/q2-detail.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-dropdown-item.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-dropdown.entry.js +15 -15
- package/dist/q2-tecton-elements/q2-editable-field.entry.js +38 -40
- package/dist/q2-tecton-elements/q2-file-picker.entry.js +61 -6
- 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-link_2.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-loc.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-message.entry.js +24 -24
- package/dist/q2-tecton-elements/q2-meter.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-modal.entry.js +61 -45
- package/dist/q2-tecton-elements/q2-month-picker.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-optgroup.entry.js +11 -11
- package/dist/q2-tecton-elements/q2-option.entry.js +1 -1
- 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 +2 -2
- package/dist/q2-tecton-elements/q2-radio-group.entry.js +55 -34
- package/dist/q2-tecton-elements/q2-radio.entry.js +38 -53
- package/dist/q2-tecton-elements/q2-relative-time.entry.js +12 -12
- package/dist/q2-tecton-elements/q2-resize-observer.entry.js +81 -0
- package/dist/q2-tecton-elements/q2-search.entry.js +2 -2
- package/dist/q2-tecton-elements/q2-section.entry.js +33 -33
- package/dist/q2-tecton-elements/q2-select.entry.js +27 -20
- package/dist/q2-tecton-elements/q2-stepper-pane.entry.js +20 -16
- package/dist/q2-tecton-elements/q2-stepper-vertical.entry.js +5 -5
- package/dist/q2-tecton-elements/q2-stepper.entry.js +1 -1
- package/dist/q2-tecton-elements/q2-surface.entry.js +3 -3
- package/dist/q2-tecton-elements/q2-tab-container.entry.js +20 -20
- package/dist/q2-tecton-elements/q2-tab-pane.entry.js +4 -4
- 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 +1 -1
- package/dist/q2-tecton-elements/q2-tooltip.entry.js +1 -1
- package/dist/q2-tecton-elements/tecton-tab-pane.entry.js +8 -7
- package/dist/types/components/q2-card-image/q2-card-image.d.ts +1 -1
- package/dist/types/components/q2-dropdown/test/q2-dropdown-test.vr.d.ts +1 -0
- package/dist/types/components/q2-editable-field/q2-editable-field.d.ts +6 -1
- package/dist/types/components/q2-file-picker/q2-file-picker.d.ts +20 -0
- package/dist/types/components/q2-input/q2-input.d.ts +28 -2
- package/dist/types/components/q2-modal/q2-modal.d.ts +10 -1
- package/dist/types/components/q2-radio-group/q2-radio-group.d.ts +14 -0
- package/dist/types/components/q2-select/q2-select.d.ts +8 -2
- package/dist/types/components.d.ts +119 -11
- package/dist/types/utils/test/vr-helpers.d.ts +2 -0
- package/package.json +3 -3
|
@@ -364,7 +364,7 @@ export class Q2Dropdown {
|
|
|
364
364
|
// #region Render Methods
|
|
365
365
|
render() {
|
|
366
366
|
const btnProps = this.toggleButtonProps;
|
|
367
|
-
return (h("click-elsewhere", { key: '
|
|
367
|
+
return (h("click-elsewhere", { key: 'b71837747b991c78e7ec76cc781dc46b69f15ceb', class: this.open ? 'dropdown-open' : '', onChange: this.onClickElsewhere, "test-id": "dropdownContainer" }, h("q2-btn", { key: '82fe12ed6bc51dd731cd1ff30d315f5bd795ef45', tabIndex: 0, ref: el => (this.controlElement = el), class: btnProps.className, onClick: this.onToggleClick, onKeyDown: this.onToggleKeydown, fab: btnProps.fab, intent: btnProps.intent, onFocusout: this.handleFocusOut, active: btnProps.active, disabled: btnProps.disabled, ariaExpanded: `${!!btnProps.ariaExpanded}`, label: this.hideLabel && this.label ? loc(this.label) : undefined, hideLabel: this.hideLabel, ariaHasPopup: "menu", "test-id": "dropdownButton", block: this.block, description: loc('tecton.element.dropdown.itemCount', [this.determineDropdownItemCount]) }, this.hasCustomControl ? (h("div", { "test-id": "dropdownControl", class: btnProps.custom ? '' : 'hidden' }, h("slot", { name: "control" }))) : (h(Fragment, null, this.label && !this.hideLabel && (h("span", { class: "dropdown-button-text" }, loc(this.label))), this.icon ? h("q2-icon", { type: this.icon }) : ' '))), h("q2-popover", { key: 'b4da967caa9cd12e397b5320c055b3a62b2926ec', ref: el => (this.popoverElement = el), controlElement: this.controlElement, open: this.open, "max-height": this.popoverMaxHeight, onFocusout: this.handleFocusOut, minHeight: this.popoverMinHeight, direction: this.popoverDirection, align: this.popoverAlignment, mode: this.popoverMode || undefined, block: this.block }, h("slot", { key: 'f7a490170ad9429ead0d611adb78dd8272deaaa2', name: "popover-top" }), h("q2-option-list", { key: '87eafcc44a7b5deca4dabd6bc3a3ae04517a5917', onPopoverState: this.onPopoverState, id: "option-list", ref: el => (this.optionList = el), type: "menu", label: loc('tecton.element.optionList.label', [this.optionListLabel]), "no-select": true }, h("slot", { key: '394a44b4490f2b6aff52a8262c5ec3ecc54e9111' })), h("slot", { key: '6e84bdcae4daf64aded5fadcc185dbfab889626e', name: "popover-bottom" }))));
|
|
368
368
|
}
|
|
369
369
|
static get is() { return "q2-dropdown"; }
|
|
370
370
|
static get encapsulation() { return "shadow"; }
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { expect } from "@playwright/test";
|
|
2
|
+
import { test } from "@stencil/playwright";
|
|
3
|
+
import { setupPage, THEMES } from "../../../utils/test/vr-helpers";
|
|
4
|
+
const VARIANTS = [
|
|
5
|
+
{
|
|
6
|
+
name: 'chevron',
|
|
7
|
+
html: `<q2-dropdown type="neutral" icon="chevron-down" label="Actions">
|
|
8
|
+
<q2-option value="view">View details</q2-option>
|
|
9
|
+
</q2-dropdown>`,
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
name: 'icon',
|
|
13
|
+
html: `<q2-dropdown type="icon" icon="options" label="More actions" hide-label>
|
|
14
|
+
<q2-option value="view">View details</q2-option>
|
|
15
|
+
</q2-dropdown>`,
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
const restingCase = (variant, theme) => {
|
|
19
|
+
test(`q2-dropdown--${variant.name}--resting - ${theme}`, async ({ page }) => {
|
|
20
|
+
await setupPage(page, variant.html, { theme, setupLoc: true });
|
|
21
|
+
await expect(page).toHaveScreenshot(`q2-dropdown--${variant.name}--resting--${theme}.png`);
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
test.describe('q2-dropdown - variants x themes', () => {
|
|
25
|
+
for (const variant of VARIANTS) {
|
|
26
|
+
for (const theme of THEMES) {
|
|
27
|
+
restingCase(variant, theme);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
@@ -88,6 +88,7 @@ button {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
/**
|
|
91
|
+
* @prop --tct-editable-field-icon-size: (<length>) Controls the size of edit, confirm, and cancel icons.
|
|
91
92
|
* @prop --tct-editable-field-btn-hover-background: (<color>) Controls the background color of the editable field action buttons (begin, save, cancel) on hover.
|
|
92
93
|
* @prop --tct-editable-field-btn-icon-stroke-primary: (<color>) Controls the primary stroke color of the editable field action button icons.
|
|
93
94
|
* @prop --tct-editable-field-btn-icon-stroke-secondary: (<color>) Controls the secondary stroke color of the editable field action button icons.
|
|
@@ -101,6 +102,7 @@ button {
|
|
|
101
102
|
.q2-editable-field-wrapper .save-edit,
|
|
102
103
|
.q2-editable-field-wrapper .cancel-edit {
|
|
103
104
|
flex: 0 0 44px;
|
|
105
|
+
--tct-icon-size: var(--tct-editable-field-icon-size, var(--const-px-18, 18px));
|
|
104
106
|
--tct-btn-icon-hover-background: var(--tct-editable-field-btn-hover-background, var(--app-gray-l3, #f2f2f2));
|
|
105
107
|
--tct-icon-stroke-primary: var(--tct-editable-field-btn-icon-stroke-primary, var(--app-gray, #747474));
|
|
106
108
|
--tct-icon-stroke-secondary: var(--tct-editable-field-btn-icon-stroke-secondary, var(--app-gray, #747474));
|
|
@@ -21,15 +21,26 @@ export class Q2EditableField {
|
|
|
21
21
|
this.value = '';
|
|
22
22
|
this.cancelClick = (event) => {
|
|
23
23
|
event === null || event === void 0 ? void 0 : event.stopPropagation();
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
const emittedEvents = this.emitChangeEvents({ editing: false, name: 'cancel' });
|
|
25
|
+
queueMicrotask(() => {
|
|
26
|
+
if (this.isDefaultPrevented(emittedEvents))
|
|
27
|
+
return;
|
|
28
|
+
this.innerValue = undefined;
|
|
29
|
+
this.formattedValue = undefined;
|
|
30
|
+
this.inputElement.value = '';
|
|
31
|
+
this.inputElement.value = this.defaultValue;
|
|
32
|
+
this.inputElement.value = this.value;
|
|
33
|
+
this.editing = false;
|
|
34
|
+
});
|
|
29
35
|
};
|
|
30
36
|
this.editClick = (event) => {
|
|
31
37
|
event === null || event === void 0 ? void 0 : event.stopPropagation();
|
|
32
|
-
|
|
38
|
+
const emittedEvents = this.emitChangeEvents({ editing: true, name: 'edit' });
|
|
39
|
+
queueMicrotask(() => {
|
|
40
|
+
if (this.isDefaultPrevented(emittedEvents))
|
|
41
|
+
return;
|
|
42
|
+
this.editing = true;
|
|
43
|
+
});
|
|
33
44
|
};
|
|
34
45
|
this.inputChange = (e) => {
|
|
35
46
|
e.stopPropagation();
|
|
@@ -58,11 +69,18 @@ export class Q2EditableField {
|
|
|
58
69
|
this.saveClick = (event) => {
|
|
59
70
|
event && event.stopPropagation();
|
|
60
71
|
const valueFromInputProp = this.hostElement.shadowRoot.querySelector('q2-input').value;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
72
|
+
const value = this.innerValue || valueFromInputProp;
|
|
73
|
+
const formattedValue = this.formattedValue || valueFromInputProp;
|
|
74
|
+
const emittedEvents = this.emitChangeEvents({ editing: false, name: 'save', value, formattedValue });
|
|
75
|
+
queueMicrotask(() => {
|
|
76
|
+
if (this.isDefaultPrevented(emittedEvents))
|
|
77
|
+
return;
|
|
78
|
+
if (this.hasErrors) {
|
|
79
|
+
this.inputElement.focus();
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
this.value = value;
|
|
83
|
+
this.editing = false;
|
|
66
84
|
});
|
|
67
85
|
};
|
|
68
86
|
}
|
|
@@ -81,29 +99,6 @@ export class Q2EditableField {
|
|
|
81
99
|
}
|
|
82
100
|
// #endregion
|
|
83
101
|
// #region Listeners
|
|
84
|
-
onHostElementChange(event) {
|
|
85
|
-
if (!isEventFromElement(event, this.hostElement) || this.hostElement.onchange)
|
|
86
|
-
return;
|
|
87
|
-
queueMicrotask(() => {
|
|
88
|
-
switch (event.detail.name) {
|
|
89
|
-
case 'save':
|
|
90
|
-
if (this.hasErrors) {
|
|
91
|
-
this.inputElement.focus();
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
this.value = event.detail.value;
|
|
95
|
-
this.editing = event.detail.editing;
|
|
96
|
-
break;
|
|
97
|
-
case 'cancel':
|
|
98
|
-
this.inputElement.value = this.value;
|
|
99
|
-
this.editing = event.detail.editing;
|
|
100
|
-
break;
|
|
101
|
-
case 'edit':
|
|
102
|
-
this.editing = event.detail.editing;
|
|
103
|
-
break;
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
102
|
delegateFocus(event) {
|
|
108
103
|
if (!isEventFromElement(event, this.hostElement))
|
|
109
104
|
return;
|
|
@@ -199,6 +194,9 @@ export class Q2EditableField {
|
|
|
199
194
|
get wrapperClass() {
|
|
200
195
|
return `q2-editable-field-wrapper ${this.editing ? 'editing' : ''}`;
|
|
201
196
|
}
|
|
197
|
+
emitChangeEvents(detail) {
|
|
198
|
+
return [this.change.emit(detail), this.tctChange.emit(detail)];
|
|
199
|
+
}
|
|
202
200
|
generateEditStateDOM() {
|
|
203
201
|
return (h("div", { class: this.wrapperClass, hidden: !this.editing }, h("q2-input", { ref: el => (this.inputElement = el), label: this.locLabel, hideLabel: this.hideLabel, value: this.value, hints: this.hasHints ? this.hints : undefined, errors: this.hasErrors ? this.errors : undefined, type: this.type, disabled: this.disabled, _updateValueOnInput: false, formatModifier: this.formatModifier, maxlength: this.maxlength, "test-id": "editableInput", onChange: e => e.stopImmediatePropagation(), onInput: e => e.stopImmediatePropagation(), onTctInput: this.inputInput, onTctChange: this.inputChange, onKeyDown: this.inputKeyDown, onClick: this.inputClick }), h("q2-btn", { ref: el => (this.cancelBtnElement = el), class: "cancel-edit", label: `${loc('tecton.element.editableField.cancel')} ${this.locLabel}`, "hide-label": true, "test-id": "cancelButton", onClick: e => e.stopImmediatePropagation(), onTctClick: this.cancelClick }, h("q2-icon", { type: "close" })), h("q2-btn", { ref: el => (this.saveBtnElement = el), class: "save-edit", label: `${loc('tecton.element.editableField.save')} ${this.locLabel}`, "hide-label": true, "test-id": "saveButton", onClick: e => e.stopImmediatePropagation(), onTctClick: this.saveClick }, h("q2-icon", { type: "checkmark" }))));
|
|
204
202
|
}
|
|
@@ -208,10 +206,13 @@ export class Q2EditableField {
|
|
|
208
206
|
}
|
|
209
207
|
return (h("div", { class: this.wrapperClass, hidden: this.editing }, h("div", { class: "text-wrapper" }, this.formattedValue || this.value), h("q2-btn", { ref: el => (this.editBtnElement = el), class: "begin-edit", label: `${loc('tecton.element.editableField.edit')} ${this.locLabel}`, "hide-label": true, disabled: this.disabled, "test-id": "editButton", onClick: e => e.stopImmediatePropagation(), onTctClick: this.editClick }, h("q2-icon", { type: "edit" }))));
|
|
210
208
|
}
|
|
209
|
+
isDefaultPrevented(events) {
|
|
210
|
+
return this.hostElement.onchange != null || events.some(event => event.defaultPrevented);
|
|
211
|
+
}
|
|
211
212
|
// #endregion
|
|
212
213
|
// #region Render Methods
|
|
213
214
|
render() {
|
|
214
|
-
return (h("div", { key: '
|
|
215
|
+
return (h("div", { key: '73dfc2198007dc7366243914bb055db3f8ebda3a' }, this.generateEditStateDOM(), this.generateReadStateDOM()));
|
|
215
216
|
}
|
|
216
217
|
static get is() { return "q2-editable-field"; }
|
|
217
218
|
static get encapsulation() { return "shadow"; }
|
|
@@ -530,7 +531,7 @@ export class Q2EditableField {
|
|
|
530
531
|
"name": "deprecated",
|
|
531
532
|
"text": "Use 'tctChange' instead"
|
|
532
533
|
}],
|
|
533
|
-
"text": "Emitted when the 'Edit', 'Cancel', or 'Save' buttons are clicked.\n\nThe event detail will not include a `value` or `formattedValue` if the event name is 'edit' or 'cancel'."
|
|
534
|
+
"text": "Emitted when the 'Edit', 'Cancel', or 'Save' buttons are clicked.\n\nThe event detail will not include a `value` or `formattedValue` if the event name is 'edit' or 'cancel'.\n\nCall `event.preventDefault()` to prevent the default behavior (the component's internal `editing` and `value` updates)."
|
|
534
535
|
},
|
|
535
536
|
"complexType": {
|
|
536
537
|
"original": "{\n editing: boolean;\n name: 'edit' | 'cancel' | 'save';\n value?: string;\n formattedValue?: string;\n }",
|
|
@@ -566,7 +567,7 @@ export class Q2EditableField {
|
|
|
566
567
|
"name": "info",
|
|
567
568
|
"text": "If you are utilizing events to provide input validation, it is recommended you use the `input` event, not the `change` event."
|
|
568
569
|
}],
|
|
569
|
-
"text": "Emitted when the 'Edit', 'Cancel', or 'Save' buttons are clicked.\n\nThe event detail will not include a `value` or `formattedValue` if the event name is 'edit' or 'cancel'."
|
|
570
|
+
"text": "Emitted when the 'Edit', 'Cancel', or 'Save' buttons are clicked.\n\nThe event detail will not include a `value` or `formattedValue` if the event name is 'edit' or 'cancel'.\n\nCall `event.preventDefault()` to prevent the default behavior (the component's internal `editing` and `value` updates)."
|
|
570
571
|
},
|
|
571
572
|
"complexType": {
|
|
572
573
|
"original": "{\n editing: boolean;\n name: 'edit' | 'cancel' | 'save';\n value?: string;\n formattedValue?: string;\n }",
|
|
@@ -685,12 +686,6 @@ export class Q2EditableField {
|
|
|
685
686
|
}
|
|
686
687
|
static get listeners() {
|
|
687
688
|
return [{
|
|
688
|
-
"name": "change",
|
|
689
|
-
"method": "onHostElementChange",
|
|
690
|
-
"target": undefined,
|
|
691
|
-
"capture": false,
|
|
692
|
-
"passive": false
|
|
693
|
-
}, {
|
|
694
689
|
"name": "focus",
|
|
695
690
|
"method": "delegateFocus",
|
|
696
691
|
"target": undefined,
|
|
@@ -230,6 +230,7 @@ button {
|
|
|
230
230
|
* @prop --tct-file-picker-item-close-btn-border-radius: (<length-percentage>) Controls the corner radius of the file item close button.
|
|
231
231
|
* @prop --tct-file-picker-item-close-btn-size: (<length>) Controls the width and height of the file item close button.
|
|
232
232
|
* @prop --tct-file-picker-list-max-height: (<length-percentage>) Controls the maximum height of the file list container before scrolling.
|
|
233
|
+
* @prop --tct-file-picker-list-gradient-height: (<length-percentage>) Controls the height of the fade indicating more files are available below the visible list.
|
|
233
234
|
* @prop --tct-file-picker-scrollbar-color: (<color>) Controls the scrollbar thumb color of the file list container.
|
|
234
235
|
* @prop --tct-file-picker-loading-size: (<length>) Controls the font size driving the picker-level loading spinner.
|
|
235
236
|
* @prop --tct-file-picker-loading-file-color: (<color>) Controls the text color of the loading-file message.
|
|
@@ -357,6 +358,28 @@ button {
|
|
|
357
358
|
white-space: nowrap;
|
|
358
359
|
}
|
|
359
360
|
|
|
361
|
+
.file-name-header {
|
|
362
|
+
display: flex;
|
|
363
|
+
align-items: center;
|
|
364
|
+
min-width: 0;
|
|
365
|
+
white-space: nowrap;
|
|
366
|
+
width: 100%;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.file-name-leading {
|
|
370
|
+
flex: 0 1 auto;
|
|
371
|
+
min-width: 0;
|
|
372
|
+
overflow: hidden;
|
|
373
|
+
text-overflow: ellipsis;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.file-name-trailing {
|
|
377
|
+
direction: rtl;
|
|
378
|
+
flex: 0 0 auto;
|
|
379
|
+
max-width: 50%;
|
|
380
|
+
overflow: hidden;
|
|
381
|
+
}
|
|
382
|
+
|
|
360
383
|
.file-item-loading {
|
|
361
384
|
/* stylelint-disable-next-line tecton/require-t-px-fallback */
|
|
362
385
|
font-size: var(--tct-file-picker-file-item-loading-size, var(--app-scale-6x, 30px));
|
|
@@ -375,6 +398,10 @@ button {
|
|
|
375
398
|
scrollbar-width: thin;
|
|
376
399
|
scrollbar-color: var(--tct-file-picker-scrollbar-color, var(--t-a11y-gray-color, #949494)) transparent;
|
|
377
400
|
}
|
|
401
|
+
.file-list-container.more-files {
|
|
402
|
+
-webkit-mask-image: linear-gradient(to bottom, currentColor calc(100% - var(--tct-file-picker-list-gradient-height, var(--app-scale-12x, 60px))), transparent 100%);
|
|
403
|
+
mask-image: linear-gradient(to bottom, currentColor calc(100% - var(--tct-file-picker-list-gradient-height, var(--app-scale-12x, 60px))), transparent 100%);
|
|
404
|
+
}
|
|
378
405
|
|
|
379
406
|
.file-picker {
|
|
380
407
|
display: flex;
|
|
@@ -24,6 +24,12 @@ export class Q2FilePicker {
|
|
|
24
24
|
* The size of the browse button.
|
|
25
25
|
*/
|
|
26
26
|
this.buttonSize = 'medium';
|
|
27
|
+
/**
|
|
28
|
+
* When `false`, the file name renders as-is and may wrap. Otherwise, long
|
|
29
|
+
* file names are middle-ellipsized so the beginning and end of the name
|
|
30
|
+
* remain visible.
|
|
31
|
+
*/
|
|
32
|
+
this.ellipsizeFileName = true;
|
|
27
33
|
/**
|
|
28
34
|
* Allowed file types based on extensions (e.g., ['jpg', 'png', 'pdf'] or
|
|
29
35
|
* 'jpg, png, pdf'). When using the attribute, provide a comma-separated
|
|
@@ -39,6 +45,10 @@ export class Q2FilePicker {
|
|
|
39
45
|
* The maximum size (in bytes) of any file that can be selected.
|
|
40
46
|
*/
|
|
41
47
|
this.maxFileSize = Infinity;
|
|
48
|
+
/**
|
|
49
|
+
* Shows a gradient at the bottom of the file list when more files are available below the visible area.
|
|
50
|
+
*/
|
|
51
|
+
this.showGradient = true;
|
|
42
52
|
/**
|
|
43
53
|
* An array of `ValidFileStatus` objects representing the upload status of
|
|
44
54
|
* files. Each `ValidFileStatus` object contains the following properties:
|
|
@@ -85,14 +95,21 @@ export class Q2FilePicker {
|
|
|
85
95
|
this.disableEvent(e);
|
|
86
96
|
this.isDropZoneHighlighted = true;
|
|
87
97
|
};
|
|
98
|
+
this.updateFileListGradient = () => {
|
|
99
|
+
if (!this.fileListContainer)
|
|
100
|
+
return;
|
|
101
|
+
const { clientHeight, scrollHeight, scrollTop } = this.fileListContainer;
|
|
102
|
+
const hasMoreFiles = this.showGradient && scrollHeight > clientHeight && Math.ceil(scrollTop) + clientHeight < scrollHeight;
|
|
103
|
+
this.fileListContainer.classList.toggle('more-files', hasMoreFiles);
|
|
104
|
+
};
|
|
88
105
|
// #endregion
|
|
89
106
|
// #region Render Methods
|
|
90
107
|
this.render = () => {
|
|
91
108
|
const { disabled } = this;
|
|
92
|
-
return (h("div", { class: "file-picker" }, (this.hasLabel || this.hasDescription) && (h("div", { class: "heading" }, this.hasLabel && (h("label", { class: "label", htmlFor: "file-field", "test-id": "label" }, !!this.label ? loc(this.label) : this.hasLabelSlotContent ? h("slot", { name: "label" }) : '')), this.hasDescription && (h("div", { class: "description", id: "description", "test-id": "description" }, !!this.description ? (loc(this.description)) : this.hasDescriptionSlotContent ? (h("slot", { name: "description" })) : (''))))), (this.variant === 'browse-drop' && (h("div", { class: this.dropZoneClasses, onDragEnter: this.disableEvent, onDragLeave: this.dimDropZone, onDragOver: this.highlightDropZone, onDrop: this.grabDroppedFiles, ref: el => (this.dropZone = el !== null && el !== void 0 ? el : this.dropZone), "test-id": "drop-zone" }, (this.areFilesUploading && (h(Fragment, null, h("q2-loading", { class: "loading" }), h("p", { class: "drop-zone-text" }, loc('tecton.element.filePicker.uploadingEllipsis'))))) || (h(Fragment, null, h("q2-icon", { type: "upload" }), h("p", { class: "drop-zone-text" }, h("q2-link", { class: "browse-link", label: loc('tecton.element.filePicker.browse'), onTctClick: () => this.launchFileBrowser(), variant: "inline", "test-id": "browse-link", disabled: disabled, href: "javascript:void(0)" }), loc('tecton.element.filePicker.orDragFilesHere', [this.maxFiles]))))))) || (h("div", { class: "browse", "test-id": "browse" }, h("q2-btn", { disabled: disabled || this.areFilesUploading, intent: "workflow-primary", loading: this.areFilesUploading, onClick: () => this.launchFileBrowser(), size: this.actualButtonSize, "test-id": "browse-button" }, h("q2-icon", { type: "paperclip" }), h("span", null, loc('tecton.element.filePicker.attachFiles', [this.maxFiles]))))), h("input", { "aria-describedby": (!!this.description && 'description') || undefined, class: "sr", id: "file-field", onChange: this.grabSelectedFiles, ref: el => (this.browseButtonInput = el !== null && el !== void 0 ? el : this.browseButtonInput), type: "file", "test-id": "file-input", disabled: disabled, multiple: true, tabIndex: -1 }), h("div", { class: "file-list-container" }, h("q2-list", { class: "file-list" }, this.displayedFiles.map(file => (h("q2-item", { class: this.getFileItemClasses(file.file.name), key: file.file.name, onAnimationEnd: this.getAnimationendHandlerToRemoveFileItem(file.file.name) }, h("div", { slot: "decorator" }, file.status === 'invalid-type' ||
|
|
109
|
+
return (h("div", { class: "file-picker" }, (this.hasLabel || this.hasDescription) && (h("div", { class: "heading" }, this.hasLabel && (h("label", { class: "label", htmlFor: "file-field", "test-id": "label" }, !!this.label ? loc(this.label) : this.hasLabelSlotContent ? h("slot", { name: "label" }) : '')), this.hasDescription && (h("div", { class: "description", id: "description", "test-id": "description" }, !!this.description ? (loc(this.description)) : this.hasDescriptionSlotContent ? (h("slot", { name: "description" })) : (''))))), (this.variant === 'browse-drop' && (h("div", { class: this.dropZoneClasses, onDragEnter: this.disableEvent, onDragLeave: this.dimDropZone, onDragOver: this.highlightDropZone, onDrop: this.grabDroppedFiles, ref: el => (this.dropZone = el !== null && el !== void 0 ? el : this.dropZone), "test-id": "drop-zone" }, (this.areFilesUploading && (h(Fragment, null, h("q2-loading", { class: "loading" }), h("p", { class: "drop-zone-text" }, loc('tecton.element.filePicker.uploadingEllipsis'))))) || (h(Fragment, null, h("q2-icon", { type: "upload" }), h("p", { class: "drop-zone-text" }, h("q2-link", { class: "browse-link", label: loc('tecton.element.filePicker.browse'), onTctClick: () => this.launchFileBrowser(), variant: "inline", "test-id": "browse-link", disabled: disabled, href: "javascript:void(0)" }), loc('tecton.element.filePicker.orDragFilesHere', [this.maxFiles]))))))) || (h("div", { class: "browse", "test-id": "browse" }, h("q2-btn", { block: this.isMobileViewport, disabled: disabled || this.areFilesUploading, intent: "workflow-primary", loading: this.areFilesUploading, onClick: () => this.launchFileBrowser(), size: this.actualButtonSize, "test-id": "browse-button" }, h("q2-icon", { type: "paperclip" }), h("span", null, loc('tecton.element.filePicker.attachFiles', [this.maxFiles]))))), h("input", { "aria-describedby": (!!this.description && 'description') || undefined, class: "sr", id: "file-field", onChange: this.grabSelectedFiles, ref: el => (this.browseButtonInput = el !== null && el !== void 0 ? el : this.browseButtonInput), type: "file", "test-id": "file-input", disabled: disabled, multiple: true, tabIndex: -1 }), h("div", { class: "file-list-container", onScroll: this.updateFileListGradient, ref: el => (this.fileListContainer = el !== null && el !== void 0 ? el : this.fileListContainer) }, h("q2-list", { class: "file-list", ref: el => (this.fileList = el !== null && el !== void 0 ? el : this.fileList) }, this.displayedFiles.map(file => (h("q2-item", { class: this.getFileItemClasses(file.file.name), key: file.file.name, onAnimationEnd: this.getAnimationendHandlerToRemoveFileItem(file.file.name) }, h("div", { slot: "decorator" }, file.status === 'invalid-type' ||
|
|
93
110
|
file.status === 'over-size-limit' ||
|
|
94
111
|
file.status === 'failed' ||
|
|
95
|
-
file.status === 'over-max-files-limit' ? (h("q2-icon", { class: "icon-error", type: "error" })) : file.status === 'in-progress' ? (h("q2-loading", { class: "file-item-loading", "hide-from-screen-readers": true })) : (h("q2-icon", { class: "icon-success", type: "success" }))), h("div", { slot: "header" }, file.file.name), h("div", { class: "file-item-info", slot: "body" }, this.getFileItemStatusMessage(file)), h("div", { slot: "action" }, h("q2-btn", { class: "dismiss-button", intent: "neutral-text", "hide-label": "true", label: this.getFileItemButtonLabel(file), onClick: this.getClickHandlerToRemoveFileItem(file.file.name), disabled: disabled }, h("q2-icon", { type: "close" }))))))))));
|
|
112
|
+
file.status === 'over-max-files-limit' ? (h("q2-icon", { class: "icon-error", type: "error" })) : file.status === 'in-progress' ? (h("q2-loading", { class: "file-item-loading", "hide-from-screen-readers": true })) : (h("q2-icon", { class: "icon-success", type: "success" }))), this.ellipsizeFileName === false ? (h("div", { slot: "header" }, file.file.name)) : (h("div", { class: "file-name-header", slot: "header" }, h("span", { class: "file-name-leading" }, file.file.name.slice(0, Math.ceil(file.file.name.length / 2))), h("span", { class: "file-name-trailing" }, h("bdo", { dir: "ltr" }, file.file.name.slice(Math.ceil(file.file.name.length / 2)))))), h("div", { class: "file-item-info", slot: "body" }, this.getFileItemStatusMessage(file)), h("div", { slot: "action" }, h("q2-btn", { class: "dismiss-button", intent: "neutral-text", "hide-label": "true", label: this.getFileItemButtonLabel(file), onClick: this.getClickHandlerToRemoveFileItem(file.file.name), disabled: disabled }, h("q2-icon", { type: "close" }))))))))));
|
|
96
113
|
};
|
|
97
114
|
}
|
|
98
115
|
/**
|
|
@@ -116,7 +133,29 @@ export class Q2FilePicker {
|
|
|
116
133
|
console.error('Setting the value of this component directly is not allowed.');
|
|
117
134
|
}
|
|
118
135
|
// #endregion
|
|
136
|
+
// #region Component Lifecycle Events
|
|
137
|
+
disconnectedCallback() {
|
|
138
|
+
var _a;
|
|
139
|
+
(_a = this.fileListResizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
140
|
+
}
|
|
141
|
+
componentDidLoad() {
|
|
142
|
+
if (typeof ResizeObserver !== 'function')
|
|
143
|
+
return;
|
|
144
|
+
this.fileListResizeObserver = new ResizeObserver(this.updateFileListGradient);
|
|
145
|
+
this.observeFileListContent();
|
|
146
|
+
}
|
|
147
|
+
componentDidRender() {
|
|
148
|
+
this.observeFileListContent();
|
|
149
|
+
this.updateFileListGradient();
|
|
150
|
+
if (typeof requestAnimationFrame === 'function') {
|
|
151
|
+
requestAnimationFrame(this.updateFileListGradient);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// #endregion
|
|
119
155
|
// #region Watchers
|
|
156
|
+
updateGradientVisibility() {
|
|
157
|
+
this.updateFileListGradient();
|
|
158
|
+
}
|
|
120
159
|
updateFileList(newValue) {
|
|
121
160
|
newValue.forEach(statusItem => {
|
|
122
161
|
const matchingQueuedFileIndex = this.queuedFiles.findIndex(file => file.name === statusItem.name);
|
|
@@ -166,6 +205,11 @@ export class Q2FilePicker {
|
|
|
166
205
|
get hasLabelSlotContent() {
|
|
167
206
|
return hasSlotContent(this.el, 'label');
|
|
168
207
|
}
|
|
208
|
+
get isMobileViewport() {
|
|
209
|
+
return typeof window !== 'undefined' && window.matchMedia
|
|
210
|
+
? window.matchMedia('(max-width: 479px)').matches
|
|
211
|
+
: false;
|
|
212
|
+
}
|
|
169
213
|
buildFilesObject(filesToUpload) {
|
|
170
214
|
const invalidFiles = [];
|
|
171
215
|
invalidFiles.push(...this.extractFilesOfInvalidTypes(filesToUpload));
|
|
@@ -300,6 +344,15 @@ export class Q2FilePicker {
|
|
|
300
344
|
launchFileBrowser() {
|
|
301
345
|
this.browseButtonInput.dispatchEvent(new MouseEvent('click'));
|
|
302
346
|
}
|
|
347
|
+
observeFileListContent() {
|
|
348
|
+
if (!this.fileListResizeObserver || !this.fileList)
|
|
349
|
+
return;
|
|
350
|
+
this.fileListResizeObserver.disconnect();
|
|
351
|
+
this.fileListResizeObserver.observe(this.fileList);
|
|
352
|
+
this.fileList.querySelectorAll('q2-item').forEach(fileItem => {
|
|
353
|
+
this.fileListResizeObserver.observe(fileItem);
|
|
354
|
+
});
|
|
355
|
+
}
|
|
303
356
|
static get is() { return "q2-file-picker"; }
|
|
304
357
|
static get encapsulation() { return "shadow"; }
|
|
305
358
|
static get originalStyleUrls() {
|
|
@@ -375,6 +428,26 @@ export class Q2FilePicker {
|
|
|
375
428
|
"reflect": true,
|
|
376
429
|
"attribute": "disabled"
|
|
377
430
|
},
|
|
431
|
+
"ellipsizeFileName": {
|
|
432
|
+
"type": "boolean",
|
|
433
|
+
"mutable": false,
|
|
434
|
+
"complexType": {
|
|
435
|
+
"original": "boolean",
|
|
436
|
+
"resolved": "boolean",
|
|
437
|
+
"references": {}
|
|
438
|
+
},
|
|
439
|
+
"required": false,
|
|
440
|
+
"optional": false,
|
|
441
|
+
"docs": {
|
|
442
|
+
"tags": [],
|
|
443
|
+
"text": "When `false`, the file name renders as-is and may wrap. Otherwise, long\nfile names are middle-ellipsized so the beginning and end of the name\nremain visible."
|
|
444
|
+
},
|
|
445
|
+
"getter": false,
|
|
446
|
+
"setter": false,
|
|
447
|
+
"reflect": true,
|
|
448
|
+
"attribute": "ellipsize-file-name",
|
|
449
|
+
"defaultValue": "true"
|
|
450
|
+
},
|
|
378
451
|
"fileTypes": {
|
|
379
452
|
"type": "string",
|
|
380
453
|
"mutable": false,
|
|
@@ -457,6 +530,26 @@ export class Q2FilePicker {
|
|
|
457
530
|
"attribute": "max-file-size",
|
|
458
531
|
"defaultValue": "Infinity"
|
|
459
532
|
},
|
|
533
|
+
"showGradient": {
|
|
534
|
+
"type": "boolean",
|
|
535
|
+
"mutable": false,
|
|
536
|
+
"complexType": {
|
|
537
|
+
"original": "boolean",
|
|
538
|
+
"resolved": "boolean",
|
|
539
|
+
"references": {}
|
|
540
|
+
},
|
|
541
|
+
"required": false,
|
|
542
|
+
"optional": false,
|
|
543
|
+
"docs": {
|
|
544
|
+
"tags": [],
|
|
545
|
+
"text": "Shows a gradient at the bottom of the file list when more files are available below the visible area."
|
|
546
|
+
},
|
|
547
|
+
"getter": false,
|
|
548
|
+
"setter": false,
|
|
549
|
+
"reflect": true,
|
|
550
|
+
"attribute": "show-gradient",
|
|
551
|
+
"defaultValue": "true"
|
|
552
|
+
},
|
|
460
553
|
"status": {
|
|
461
554
|
"type": "unknown",
|
|
462
555
|
"mutable": false,
|
|
@@ -571,6 +664,9 @@ export class Q2FilePicker {
|
|
|
571
664
|
static get elementRef() { return "el"; }
|
|
572
665
|
static get watchers() {
|
|
573
666
|
return [{
|
|
667
|
+
"propName": "showGradient",
|
|
668
|
+
"methodName": "updateGradientVisibility"
|
|
669
|
+
}, {
|
|
574
670
|
"propName": "status",
|
|
575
671
|
"methodName": "updateFileList"
|
|
576
672
|
}];
|
|
@@ -102,3 +102,25 @@ test.describe(`q2-file-picker — scaled font size × themes`, () => {
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
});
|
|
105
|
+
test('q2-file-picker--scrollable-file-list--resting — default-2026', async ({ page }) => {
|
|
106
|
+
await setupPage(page, '<q2-file-picker file-types="pdf" max-files="1"></q2-file-picker>', {
|
|
107
|
+
theme: 'default-2026',
|
|
108
|
+
setupLoc: true,
|
|
109
|
+
});
|
|
110
|
+
await page.evaluate(() => {
|
|
111
|
+
const filePicker = document.querySelector('q2-file-picker');
|
|
112
|
+
const input = filePicker.shadowRoot.querySelector('[test-id="file-input"]');
|
|
113
|
+
const files = new DataTransfer();
|
|
114
|
+
for (let index = 0; index < 6; index += 1) {
|
|
115
|
+
files.items.add(new File(['content'], `file-${index}.txt`, { type: 'text/plain' }));
|
|
116
|
+
}
|
|
117
|
+
input.files = files.files;
|
|
118
|
+
input.dispatchEvent(new Event('change'));
|
|
119
|
+
});
|
|
120
|
+
await expect(page.locator('.file-list-container.more-files')).toHaveCount(1);
|
|
121
|
+
await expect(page).toHaveScreenshot('q2-file-picker--scrollable-file-list--resting--default-2026.png');
|
|
122
|
+
await page.locator('q2-file-picker').evaluate((filePicker) => {
|
|
123
|
+
filePicker.showGradient = false;
|
|
124
|
+
});
|
|
125
|
+
await expect(page.locator('.file-list-container.more-files')).toHaveCount(0);
|
|
126
|
+
});
|
|
@@ -167,6 +167,7 @@ button {
|
|
|
167
167
|
* @prop --tct-input-count-width: (<length-percentage>) Controls the width of the character-count indicator.
|
|
168
168
|
* @prop --tct-input-icon-stroke-primary: (<color>) Controls the primary stroke color of icons rendered inside the input.
|
|
169
169
|
* @prop --tct-input-icon-stroke-secondary: (<color>) Controls the secondary stroke color of icons rendered inside the input.
|
|
170
|
+
* @prop --tct-input-icon-size: (<length>) Controls the size of icons rendered inside the input.
|
|
170
171
|
* @prop --tct-input-icon-container-font-size?: (<length-percentage>) Controls the optional font size of content inside the input icon containers.
|
|
171
172
|
* @prop --tct-input-icon-container-icon-min-width: (<length>) Controls the minimum width of icon slots inside the input icon containers.
|
|
172
173
|
* @prop --tct-input-icon-container-empty-display: (<custom-ident>) Controls the display value of icon containers when empty.
|
|
@@ -194,6 +195,7 @@ button {
|
|
|
194
195
|
display: block;
|
|
195
196
|
margin: var(--tct-input-margin, var(--comp-default-input-margin));
|
|
196
197
|
font-size: var(--tct-input-font-size, var(--t-input-font-size, var(--app-font-size, inherit)));
|
|
198
|
+
letter-spacing: inherit;
|
|
197
199
|
}
|
|
198
200
|
|
|
199
201
|
:host([hidden]) {
|
|
@@ -210,7 +212,7 @@ button {
|
|
|
210
212
|
}
|
|
211
213
|
.field-container.is-small .btn-clear {
|
|
212
214
|
--tct-btn-icon-width: 20px;
|
|
213
|
-
--tct-icon-size:
|
|
215
|
+
--tct-icon-size: var(--tct-input-icon-size, var(--const-px-18, 18px));
|
|
214
216
|
}
|
|
215
217
|
|
|
216
218
|
.input-label {
|
|
@@ -344,6 +346,58 @@ button {
|
|
|
344
346
|
-webkit-text-fill-color: var(--tct-input-autofill-font-color, var(--t-text, inherit));
|
|
345
347
|
}
|
|
346
348
|
|
|
349
|
+
.standard-input-container {
|
|
350
|
+
position: relative;
|
|
351
|
+
display: flex;
|
|
352
|
+
flex: 1;
|
|
353
|
+
min-width: 0;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
.visible-last-count-value {
|
|
357
|
+
position: absolute;
|
|
358
|
+
inset: 0;
|
|
359
|
+
z-index: 0;
|
|
360
|
+
box-sizing: border-box;
|
|
361
|
+
display: flex;
|
|
362
|
+
align-items: center;
|
|
363
|
+
overflow: hidden;
|
|
364
|
+
padding: var(--tct-input-padding, 0);
|
|
365
|
+
color: var(--tct-input-font-color, var(--t-input-font-color, var(--t-text, inherit)));
|
|
366
|
+
font-weight: var(--tct-input-font-weight, var(--t-input-font-weight, 400));
|
|
367
|
+
font-family: var(--tct-input-visible-last-count-font-family, monospace);
|
|
368
|
+
letter-spacing: var(--tct-input-letter-spacing, var(--t-input-letter-spacing, inherit));
|
|
369
|
+
pointer-events: none;
|
|
370
|
+
text-overflow: ellipsis;
|
|
371
|
+
white-space: nowrap;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
.visible-last-count-content {
|
|
375
|
+
display: inline-flex;
|
|
376
|
+
align-items: center;
|
|
377
|
+
flex: 0 0 auto;
|
|
378
|
+
transform: translateX(calc(var(--tct-input-visible-last-count-scroll-left, 0px) * -1));
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.visible-last-count-character {
|
|
382
|
+
display: inline-grid;
|
|
383
|
+
flex: 0 0 auto;
|
|
384
|
+
}
|
|
385
|
+
.visible-last-count-character::before {
|
|
386
|
+
content: attr(data-character);
|
|
387
|
+
grid-area: 1/1;
|
|
388
|
+
visibility: hidden;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.visible-last-count-visible-value {
|
|
392
|
+
flex: 0 0 auto;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.visible-last-count-mask {
|
|
396
|
+
grid-area: 1/1;
|
|
397
|
+
justify-self: center;
|
|
398
|
+
transform: translateY(var(--tct-input-visible-last-count-mask-translate-y, 0));
|
|
399
|
+
}
|
|
400
|
+
|
|
347
401
|
.input-field {
|
|
348
402
|
flex: 1;
|
|
349
403
|
border: 0;
|
|
@@ -365,6 +419,14 @@ button {
|
|
|
365
419
|
/* To remove up/down arrow in number field for webkit based browser */
|
|
366
420
|
/* For Firefox */
|
|
367
421
|
}
|
|
422
|
+
.input-field.has-visible-last-count {
|
|
423
|
+
position: relative;
|
|
424
|
+
z-index: 1;
|
|
425
|
+
color: transparent;
|
|
426
|
+
caret-color: var(--tct-input-font-color, var(--t-input-font-color, var(--t-text, auto)));
|
|
427
|
+
-webkit-text-fill-color: transparent;
|
|
428
|
+
font-family: var(--tct-input-visible-last-count-font-family, monospace);
|
|
429
|
+
}
|
|
368
430
|
.input-field:focus {
|
|
369
431
|
outline: none;
|
|
370
432
|
box-shadow: none;
|
|
@@ -441,6 +503,7 @@ button {
|
|
|
441
503
|
|
|
442
504
|
.input-icons-container-left,
|
|
443
505
|
.input-icons-container-right {
|
|
506
|
+
--tct-icon-size: var(--tct-input-icon-size, var(--const-px-18, 18px));
|
|
444
507
|
--tct-btn-icon-hover-background: var(--tct-input-btn-hover-background);
|
|
445
508
|
--tct-btn-hover-background: var(--tct-input-btn-hover-background);
|
|
446
509
|
display: flex;
|
|
@@ -553,6 +616,9 @@ q2-icon {
|
|
|
553
616
|
color: var(--tct-input-messages-font-color, var(--t-input-messages-font-color, inherit));
|
|
554
617
|
border-radius: var(--tct-message-border-radius, var(--app-border-radius-1, inherit));
|
|
555
618
|
}
|
|
619
|
+
.messages-container li:only-child {
|
|
620
|
+
list-style: none;
|
|
621
|
+
}
|
|
556
622
|
|
|
557
623
|
.has-error label {
|
|
558
624
|
color: var(--tct-input-error-label-font-color, var(--t-input-error-label-font-color, var(--tct-input-label-font-color, var(--t-input-label-font-color, inherit))));
|