From 6591424c1db1ce56e00ce2a882b2f58972e54b56 Mon Sep 17 00:00:00 2001 From: aPreciado88 Date: Tue, 11 Jun 2024 13:12:12 -0700 Subject: [PATCH 01/13] fix(color-picker-hex-input): fix color not auto updating --- .../color-picker-hex-input.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx index 6c671dd74ea..ceaa482c728 100644 --- a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx +++ b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx @@ -268,12 +268,23 @@ export class ColorPickerHexInput implements LoadableComponent { } }; + private onInputKeyUp = (): void => { + const hexInputValue = `#${this.hexInputNode.value}`; + const oldValue = this.value; + console.log("value", hexInputValue); + + if (isValidHex(hexInputValue) && isLonghandHex(hexInputValue)) { + this.internalSetValue(hexInputValue, oldValue); + } + }; + private onHexInputPaste = (event: ClipboardEvent): void => { const hex = event.clipboardData.getData("text"); if (isValidHex(hex)) { event.preventDefault(); this.hexInputNode.value = hex.slice(1); + this.internalSetValue(hex, this.value); } }; @@ -317,6 +328,7 @@ export class ColorPickerHexInput implements LoadableComponent { onCalciteInputTextChange={this.onHexInputChange} onCalciteInternalInputTextBlur={this.onHexInputBlur} onKeyDown={this.onInputKeyDown} + onKeyUp={this.onInputKeyUp} onPaste={this.onHexInputPaste} prefixText="#" ref={this.storeHexInputRef} From 54cd63e91fbde24b56867b9ea2a508d425686685 Mon Sep 17 00:00:00 2001 From: aPreciado88 Date: Wed, 12 Jun 2024 08:30:15 -0700 Subject: [PATCH 02/13] fix(color-picker-hex-input): fix color not auto updating --- .../components/color-picker-hex-input/color-picker-hex-input.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx index ceaa482c728..50046cb30c7 100644 --- a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx +++ b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx @@ -271,7 +271,6 @@ export class ColorPickerHexInput implements LoadableComponent { private onInputKeyUp = (): void => { const hexInputValue = `#${this.hexInputNode.value}`; const oldValue = this.value; - console.log("value", hexInputValue); if (isValidHex(hexInputValue) && isLonghandHex(hexInputValue)) { this.internalSetValue(hexInputValue, oldValue); From 69b82eb3d55749b720905968cfb5b28f987de962 Mon Sep 17 00:00:00 2001 From: aPreciado88 Date: Wed, 12 Jun 2024 13:36:10 -0700 Subject: [PATCH 03/13] fix(color-picker-hex-input): fix color not auto updating --- .../src/components/color-picker/color-picker.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/calcite-components/src/components/color-picker/color-picker.tsx b/packages/calcite-components/src/components/color-picker/color-picker.tsx index 8a8f186e787..a3eff9f345e 100644 --- a/packages/calcite-components/src/components/color-picker/color-picker.tsx +++ b/packages/calcite-components/src/components/color-picker/color-picker.tsx @@ -1034,6 +1034,7 @@ export class ColorPicker numberingSystem={this.numberingSystem} onCalciteInputNumberChange={this.handleChannelChange} onCalciteInputNumberInput={this.handleChannelInput} + onInput={this.handleChannelInputChange} onKeyDown={this.handleKeyDown} scale={this.scale === "l" ? "m" : "s"} // workaround to ensure input borders overlap as desired @@ -1055,6 +1056,11 @@ export class ColorPicker // //-------------------------------------------------------------------------- + handleChannelInputChange = (event: Event): void => { + const customEvent = event as CustomEvent; + this.handleChannelChange(customEvent); + }; + handleKeyDown(event: KeyboardEvent): void { if (event.key === "Enter") { event.preventDefault(); From 3336d894d7e31c43cc558ec77d091e87396d1253 Mon Sep 17 00:00:00 2001 From: aPreciado88 Date: Wed, 12 Jun 2024 13:54:07 -0700 Subject: [PATCH 04/13] fix(color-picker-hex-input): fix color not auto updating --- .../color-picker-hex-input/color-picker-hex-input.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx index 50046cb30c7..2f9554e976e 100644 --- a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx +++ b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx @@ -268,7 +268,7 @@ export class ColorPickerHexInput implements LoadableComponent { } }; - private onInputKeyUp = (): void => { + private onInputChange = (): void => { const hexInputValue = `#${this.hexInputNode.value}`; const oldValue = this.value; @@ -326,8 +326,8 @@ export class ColorPickerHexInput implements LoadableComponent { maxLength={6} onCalciteInputTextChange={this.onHexInputChange} onCalciteInternalInputTextBlur={this.onHexInputBlur} + onInput={this.onInputChange} onKeyDown={this.onInputKeyDown} - onKeyUp={this.onInputKeyUp} onPaste={this.onHexInputPaste} prefixText="#" ref={this.storeHexInputRef} From d53e0b23b9bd21487d8f982341cb132b1e8fd291 Mon Sep 17 00:00:00 2001 From: aPreciado88 Date: Wed, 12 Jun 2024 16:45:24 -0700 Subject: [PATCH 05/13] fix(color-picker-hex-input): fix color not auto updating --- .../color-picker-hex-input.tsx | 23 +++++++++++-------- .../components/color-picker/color-picker.tsx | 6 +++++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx index 2f9554e976e..71e9e954b5b 100644 --- a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx +++ b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx @@ -210,6 +210,19 @@ export class ColorPickerHexInput implements LoadableComponent { this.internalSetValue(value, this.value); }; + private onInputFocus = (): void => { + this.hexInputNode.selectText(); + }; + + private onInputChange = (): void => { + const hexInputValue = `#${this.hexInputNode.value}`; + const oldValue = this.value; + + if (isValidHex(hexInputValue) && isLonghandHex(hexInputValue)) { + this.internalSetValue(hexInputValue, oldValue); + } + }; + protected onInputKeyDown = (event: KeyboardEvent): void => { const { altKey, ctrlKey, metaKey, shiftKey } = event; const { alphaChannel, hexInputNode, internalColor, value } = this; @@ -268,15 +281,6 @@ export class ColorPickerHexInput implements LoadableComponent { } }; - private onInputChange = (): void => { - const hexInputValue = `#${this.hexInputNode.value}`; - const oldValue = this.value; - - if (isValidHex(hexInputValue) && isLonghandHex(hexInputValue)) { - this.internalSetValue(hexInputValue, oldValue); - } - }; - private onHexInputPaste = (event: ClipboardEvent): void => { const hex = event.clipboardData.getData("text"); @@ -326,6 +330,7 @@ export class ColorPickerHexInput implements LoadableComponent { maxLength={6} onCalciteInputTextChange={this.onHexInputChange} onCalciteInternalInputTextBlur={this.onHexInputBlur} + onFocus={this.onInputFocus} onInput={this.onInputChange} onKeyDown={this.onInputKeyDown} onPaste={this.onHexInputPaste} diff --git a/packages/calcite-components/src/components/color-picker/color-picker.tsx b/packages/calcite-components/src/components/color-picker/color-picker.tsx index a3eff9f345e..a82177c20f2 100644 --- a/packages/calcite-components/src/components/color-picker/color-picker.tsx +++ b/packages/calcite-components/src/components/color-picker/color-picker.tsx @@ -1034,6 +1034,7 @@ export class ColorPicker numberingSystem={this.numberingSystem} onCalciteInputNumberChange={this.handleChannelChange} onCalciteInputNumberInput={this.handleChannelInput} + onFocus={this.handleInputFocus} onInput={this.handleChannelInputChange} onKeyDown={this.handleKeyDown} scale={this.scale === "l" ? "m" : "s"} @@ -1067,6 +1068,11 @@ export class ColorPicker } } + handleInputFocus = (event: Event): void => { + const input = event.currentTarget as HTMLCalciteInputNumberElement; + input.selectText(); + }; + private showIncompatibleColorWarning(value: ColorValue, format: Format): void { console.warn( `ignoring color value (${value}) as it is not compatible with the current format (${format})`, From 2ceb3235c0848f91e11cdc3d8651e9683c3b817a Mon Sep 17 00:00:00 2001 From: aPreciado88 Date: Mon, 17 Jun 2024 14:27:43 -0700 Subject: [PATCH 06/13] fix(color-picker-hex-input): fix color not auto updating --- .../color-picker-hex-input.tsx | 41 ++++++++++++++----- .../components/color-picker/color-picker.tsx | 36 +++++++++------- 2 files changed, 53 insertions(+), 24 deletions(-) diff --git a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx index 71e9e954b5b..deef1ea08cc 100644 --- a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx +++ b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx @@ -146,8 +146,17 @@ export class ColorPickerHexInput implements LoadableComponent { const willClearValue = allowEmpty && !inputValue; const isLonghand = isLonghandHex(hex); - // ensure modified pasted hex values are committed since we prevent default to remove the # char. - this.onHexInputChange(); + /* + if alphaChannel is enabled, commit valid 4 digit hex codes. + if alphaChannel is disabled, commit valid 3 digit hex codes. + */ + if ( + (this.alphaChannel && inputValue.length === 4) || + (!this.alphaChannel && inputValue.length === 3) + ) { + // ensure modified pasted hex values are committed since we prevent default to remove the # char. + this.onHexInputChange(); + } if (willClearValue || (isValidHex(hex) && isLonghand)) { return; @@ -180,6 +189,14 @@ export class ColorPickerHexInput implements LoadableComponent { allowEmpty && !internalColor ? "" : this.formatOpacityForInternalInput(internalColor); }; + private onOpacityInputFocus = (): void => { + this.opacityInputNode.selectText(); + }; + + private onOpacityInput = (): void => { + this.onOpacityInputChange(); + }; + private onHexInputChange = (): void => { const nodeValue = this.hexInputNode.value; let value = nodeValue; @@ -210,15 +227,18 @@ export class ColorPickerHexInput implements LoadableComponent { this.internalSetValue(value, this.value); }; - private onInputFocus = (): void => { + private onHexInputFocus = (): void => { this.hexInputNode.selectText(); }; - private onInputChange = (): void => { + private onHexInput = (): void => { const hexInputValue = `#${this.hexInputNode.value}`; const oldValue = this.value; - if (isValidHex(hexInputValue) && isLonghandHex(hexInputValue)) { + if ( + isValidHex(hexInputValue, this.alphaChannel) && + isLonghandHex(hexInputValue, this.alphaChannel) + ) { this.internalSetValue(hexInputValue, oldValue); } }; @@ -284,7 +304,7 @@ export class ColorPickerHexInput implements LoadableComponent { private onHexInputPaste = (event: ClipboardEvent): void => { const hex = event.clipboardData.getData("text"); - if (isValidHex(hex)) { + if (isValidHex(hex, this.alphaChannel) && isLonghandHex(hex, this.alphaChannel)) { event.preventDefault(); this.hexInputNode.value = hex.slice(1); this.internalSetValue(hex, this.value); @@ -327,11 +347,11 @@ export class ColorPickerHexInput implements LoadableComponent { { + const input = event.currentTarget as HTMLCalciteInputNumberElement; + const channelIndex = Number(input.getAttribute("data-channel-index")); + const channels = [...this.channels] as this["channels"]; + + // restore original value when input field is left blank + if (!input.value && !this.isClearable) { + input.value = channels[channelIndex].toString(); + } + }; + + handleChannelFocus = (event: Event): void => { + const input = event.currentTarget as HTMLCalciteInputNumberElement; + input.selectText(); + }; + // using @Listen as a workaround for VDOM listener not firing @Listen("keydown", { capture: true }) @Listen("keyup", { capture: true }) @@ -532,7 +550,7 @@ export class ColorPicker } const isAlphaChannel = channelIndex === 3; - const value = Number(input.value); + const value = input.value ? Number(input.value) : channels[channelIndex]; channels[channelIndex] = isAlphaChannel ? opacityToAlpha(value) : value; this.updateColorFromChannels(channels); @@ -1034,8 +1052,8 @@ export class ColorPicker numberingSystem={this.numberingSystem} onCalciteInputNumberChange={this.handleChannelChange} onCalciteInputNumberInput={this.handleChannelInput} - onFocus={this.handleInputFocus} - onInput={this.handleChannelInputChange} + onCalciteInternalInputNumberBlur={this.handleChannelBlur} + onCalciteInternalInputNumberFocus={this.handleChannelFocus} onKeyDown={this.handleKeyDown} scale={this.scale === "l" ? "m" : "s"} // workaround to ensure input borders overlap as desired @@ -1057,22 +1075,12 @@ export class ColorPicker // //-------------------------------------------------------------------------- - handleChannelInputChange = (event: Event): void => { - const customEvent = event as CustomEvent; - this.handleChannelChange(customEvent); - }; - handleKeyDown(event: KeyboardEvent): void { if (event.key === "Enter") { event.preventDefault(); } } - handleInputFocus = (event: Event): void => { - const input = event.currentTarget as HTMLCalciteInputNumberElement; - input.selectText(); - }; - private showIncompatibleColorWarning(value: ColorValue, format: Format): void { console.warn( `ignoring color value (${value}) as it is not compatible with the current format (${format})`, From c7e73dc22724618099d2e3ae793e97d0254fc201 Mon Sep 17 00:00:00 2001 From: aPreciado88 Date: Wed, 26 Jun 2024 11:05:59 -0700 Subject: [PATCH 07/13] feat(color-picker,color-picker-hex-input): add component enhancements --- .../color-picker-hex-input.e2e.ts | 5 +- .../color-picker-hex-input.tsx | 29 +- .../color-picker/color-picker.e2e.ts | 17 +- .../components/color-picker/color-picker.tsx | 347 ++++++++++-------- 4 files changed, 219 insertions(+), 179 deletions(-) diff --git a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.e2e.ts b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.e2e.ts index 2466e3e2538..6aff1f4866e 100644 --- a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.e2e.ts +++ b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.e2e.ts @@ -272,11 +272,10 @@ describe("calcite-color-picker-hex-input", () => { await selectText(input); const longhandHexWithExtraChars = "bbbbbbbbc"; await page.keyboard.type(longhandHexWithExtraChars); - await page.keyboard.press("Enter"); await page.waitForChanges(); - const hexWithPreviousAlphaCharsPreserved = "#bbbbbbdd"; - expect(await input.getProperty("value")).toBe(hexWithPreviousAlphaCharsPreserved); + const hexWithAlphaCharsPreserved = "#bbbbbbbb"; + expect(await input.getProperty("value")).toBe(hexWithAlphaCharsPreserved); }); describe("keyboard interaction", () => { diff --git a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx index deef1ea08cc..54a2e3fbc83 100644 --- a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx +++ b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx @@ -146,14 +146,7 @@ export class ColorPickerHexInput implements LoadableComponent { const willClearValue = allowEmpty && !inputValue; const isLonghand = isLonghandHex(hex); - /* - if alphaChannel is enabled, commit valid 4 digit hex codes. - if alphaChannel is disabled, commit valid 3 digit hex codes. - */ - if ( - (this.alphaChannel && inputValue.length === 4) || - (!this.alphaChannel && inputValue.length === 3) - ) { + if (this.validateShortHandValue(inputValue)) { // ensure modified pasted hex values are committed since we prevent default to remove the # char. this.onHexInputChange(); } @@ -193,7 +186,7 @@ export class ColorPickerHexInput implements LoadableComponent { this.opacityInputNode.selectText(); }; - private onOpacityInput = (): void => { + private onOpacityInputInput = (): void => { this.onOpacityInputChange(); }; @@ -231,7 +224,7 @@ export class ColorPickerHexInput implements LoadableComponent { this.hexInputNode.selectText(); }; - private onHexInput = (): void => { + private onHexInputInput = (): void => { const hexInputValue = `#${this.hexInputNode.value}`; const oldValue = this.value; @@ -249,7 +242,7 @@ export class ColorPickerHexInput implements LoadableComponent { const { key } = event; const composedPath = event.composedPath(); - if (key === "Tab" || key === "Enter") { + if ((key === "Tab" && this.validateShortHandValue(value)) || key === "Enter") { if (composedPath.includes(hexInputNode)) { this.onHexInputChange(); } else { @@ -349,7 +342,7 @@ export class ColorPickerHexInput implements LoadableComponent { label={messages?.hex || hexLabel} maxLength={this.alphaChannel ? 8 : 6} onCalciteInputTextChange={this.onHexInputChange} - onCalciteInputTextInput={this.onHexInput} + onCalciteInputTextInput={this.onHexInputInput} onCalciteInternalInputTextBlur={this.onHexInputBlur} onCalciteInternalInputTextFocus={this.onHexInputFocus} onKeyDown={this.onInputKeyDown} @@ -369,7 +362,7 @@ export class ColorPickerHexInput implements LoadableComponent { min={OPACITY_LIMITS.min} numberButtonType="none" numberingSystem={this.numberingSystem} - onCalciteInputNumberInput={this.onOpacityInput} + onCalciteInputNumberInput={this.onOpacityInputInput} onCalciteInternalInputNumberBlur={this.onOpacityInputBlur} onCalciteInternalInputNumberFocus={this.onOpacityInputFocus} onKeyDown={this.onInputKeyDown} @@ -475,4 +468,14 @@ export class ColorPickerHexInput implements LoadableComponent { return Color(nudgedChannels); } + + /* + if alphaChannel is enabled, commit valid 4 digit hex codes. + if alphaChannel is disabled, commit valid 3 digit hex codes. + */ + private validateShortHandValue = (value: string): boolean => { + return ( + (this.alphaChannel && value?.length === 4) || (!this.alphaChannel && value?.length === 3) + ); + }; } diff --git a/packages/calcite-components/src/components/color-picker/color-picker.e2e.ts b/packages/calcite-components/src/components/color-picker/color-picker.e2e.ts index 2c6536ade0f..0ead2590485 100644 --- a/packages/calcite-components/src/components/color-picker/color-picker.e2e.ts +++ b/packages/calcite-components/src/components/color-picker/color-picker.e2e.ts @@ -196,15 +196,14 @@ describe("calcite-color-picker", () => { const channelInput = await page.find(`calcite-color-picker >>> .${CSS.channel}`); await selectText(channelInput); await channelInput.type("254"); - await channelInput.press("Enter"); await page.waitForChanges(); - expect(changeSpy).toHaveReceivedEventTimes(4); - expect(inputSpy).toHaveReceivedEventTimes(4); + expect(changeSpy).toHaveReceivedEventTimes(6); + expect(inputSpy).toHaveReceivedEventTimes(6); // change by clicking stored color await (await page.find(`calcite-color-picker >>> .${CSS.savedColor}`)).click(); - expect(changeSpy).toHaveReceivedEventTimes(5); - expect(inputSpy).toHaveReceivedEventTimes(5); + expect(changeSpy).toHaveReceivedEventTimes(7); + expect(inputSpy).toHaveReceivedEventTimes(7); // change by dragging color field thumb const mouseDragSteps = 10; @@ -222,8 +221,8 @@ describe("calcite-color-picker", () => { await page.mouse.up(); await page.waitForChanges(); - expect(changeSpy).toHaveReceivedEventTimes(6); - expect(inputSpy.length).toBeGreaterThan(6); // input event fires more than once + expect(changeSpy).toHaveReceivedEventTimes(8); + expect(inputSpy.length).toBeGreaterThan(8); // input event fires more than once // change by dragging hue slider thumb [hueScopeX, hueScopeY] = await getElementXY(page, "calcite-color-picker", `.${CSS.hueScope}`); @@ -235,7 +234,7 @@ describe("calcite-color-picker", () => { await page.mouse.up(); await page.waitForChanges(); - expect(changeSpy).toHaveReceivedEventTimes(7); + expect(changeSpy).toHaveReceivedEventTimes(9); expect(inputSpy.length).toBeGreaterThan(previousInputEventLength + 1); // input event fires more than once previousInputEventLength = inputSpy.length; @@ -246,7 +245,7 @@ describe("calcite-color-picker", () => { picker.setProperty("value", "#fff"); await page.waitForChanges(); - expect(changeSpy).toHaveReceivedEventTimes(7); + expect(changeSpy).toHaveReceivedEventTimes(9); expect(inputSpy.length).toBe(previousInputEventLength); }); diff --git a/packages/calcite-components/src/components/color-picker/color-picker.tsx b/packages/calcite-components/src/components/color-picker/color-picker.tsx index 9492b498a66..11980b8be07 100644 --- a/packages/calcite-components/src/components/color-picker/color-picker.tsx +++ b/packages/calcite-components/src/components/color-picker/color-picker.tsx @@ -4,6 +4,7 @@ import { Event, EventEmitter, h, + Host, Listen, Method, Prop, @@ -340,6 +341,10 @@ export class ColorPicker private shiftKeyChannelAdjustment = 0; + private arrowUpOrDownTracker = ""; + + private channelInputClear = false; + @State() channelMode: ColorMode = "rgb"; @State() channels: Channels = this.toChannels(DEFAULT_COLOR); @@ -478,6 +483,9 @@ export class ColorPicker if (!input.value) { inputValue = ""; + this.channelInputClear = true; + // reset this to allow typing in new value when channel input is empty + this.arrowUpOrDownTracker = ""; } else { const value = Number(input.value); const adjustedValue = value + this.shiftKeyChannelAdjustment; @@ -503,7 +511,7 @@ export class ColorPicker // restore original value when input field is left blank if (!input.value && !this.isClearable) { - input.value = channels[channelIndex].toString(); + input.value = channels[channelIndex]?.toString(); } }; @@ -544,6 +552,19 @@ export class ColorPicker : key === "ArrowDown" && shiftKey ? -complementaryBump : 0; + + if (key === "ArrowUp") { + this.arrowUpOrDownTracker = "arrowUp"; + } + if (key === "ArrowDown") { + this.arrowUpOrDownTracker = "arrowDown"; + } + } + + private getChannelInputLimit(channelIndex: number): number { + return this.channelMode === "rgb" + ? RGB_LIMITS[Object.keys(RGB_LIMITS)[channelIndex]] + : HSV_LIMITS[Object.keys(HSV_LIMITS)[channelIndex]]; } private handleChannelChange = (event: CustomEvent): void => { @@ -560,6 +581,18 @@ export class ColorPicker } const isAlphaChannel = channelIndex === 3; + + if (this.channelInputClear && this.arrowUpOrDownTracker !== "") { + input.value = + this.arrowUpOrDownTracker === "arrowUp" + ? (channels[channelIndex] + 1 <= this.getChannelInputLimit(channelIndex) + ? channels[channelIndex] + 1 + : this.getChannelInputLimit(channelIndex) + ).toString() + : (channels[channelIndex] - 1 >= 0 ? channels[channelIndex] - 1 : 0).toString(); + this.channelInputClear = false; + this.arrowUpOrDownTracker = ""; + } const value = input.value ? Number(input.value) : channels[channelIndex]; channels[channelIndex] = isAlphaChannel ? opacityToAlpha(value) : value; @@ -814,176 +847,178 @@ export class ColorPicker ); return ( - -
-
- -
-
-
- -
-
- -
-
- {alphaChannel ? ( + + +
+
+ +
+
+
+ +
- ) : null} -
-
- {noHex && noChannels ? null : ( -
-
- {noHex ? null : ( -
- + +
- )} - {noChannels ? null : ( - - - {this.renderChannelsTabTitle("rgb")} - {this.renderChannelsTabTitle("hsv")} - - {this.renderChannelsTab("rgb")} - {this.renderChannelsTab("hsv")} - - )} + ) : null}
- )} - {noSaved ? null : ( -
-
- -
- - -
-
- {savedColors.length > 0 ? ( -
- {[ - ...savedColors.map((color) => ( - +
+ {noHex ? null : ( +
+ - )), - ]} +
+ )} + {noChannels ? null : ( + + + {this.renderChannelsTabTitle("rgb")} + {this.renderChannelsTabTitle("hsv")} + + {this.renderChannelsTab("rgb")} + {this.renderChannelsTab("hsv")} + + )}
- ) : null} -
- )} -
- +
+ )} + {noSaved ? null : ( +
+
+ +
+ + +
+
+ {savedColors.length > 0 ? ( +
+ {[ + ...savedColors.map((color) => ( + + )), + ]} +
+ ) : null} +
+ )} +
+ + ); } @@ -1704,4 +1739,8 @@ export class ColorPicker private getAdjustedScopePosition(left: number, top: number): [number, number] { return [left - SCOPE_SIZE / 2, top - SCOPE_SIZE / 2]; } + + private handleColorPickerBlur = (): void => { + this.el.blur(); + }; } From 6b16caa4425b3ea1624d121b1f494f73d8858589 Mon Sep 17 00:00:00 2001 From: aPreciado88 Date: Wed, 26 Jun 2024 13:39:40 -0700 Subject: [PATCH 08/13] feat(color-picker,color-picker-hex-input): update click handler logic --- .../components/color-picker/color-picker.tsx | 316 +++++++++--------- 1 file changed, 160 insertions(+), 156 deletions(-) diff --git a/packages/calcite-components/src/components/color-picker/color-picker.tsx b/packages/calcite-components/src/components/color-picker/color-picker.tsx index 11980b8be07..f78a6d421cd 100644 --- a/packages/calcite-components/src/components/color-picker/color-picker.tsx +++ b/packages/calcite-components/src/components/color-picker/color-picker.tsx @@ -4,7 +4,6 @@ import { Event, EventEmitter, h, - Host, Listen, Method, Prop, @@ -847,178 +846,176 @@ export class ColorPicker ); return ( - - -
-
- -
-
-
- -
+ +
+
+ +
+
+
+ +
+
+ +
+
+ {alphaChannel ? (
- {alphaChannel ? ( -
- -
+
+ {noHex && noChannels ? null : ( +
+
+ {noHex ? null : ( +
+
- ) : null} + )} + {noChannels ? null : ( + + + {this.renderChannelsTabTitle("rgb")} + {this.renderChannelsTabTitle("hsv")} + + {this.renderChannelsTab("rgb")} + {this.renderChannelsTab("hsv")} + + )}
- {noHex && noChannels ? null : ( -
-
- {noHex ? null : ( -
- -
- )} - {noChannels ? null : ( - - - {this.renderChannelsTabTitle("rgb")} - {this.renderChannelsTabTitle("hsv")} - - {this.renderChannelsTab("rgb")} - {this.renderChannelsTab("hsv")} - - )} + )} + {noSaved ? null : ( +
+
+ +
+ +
- )} - {noSaved ? null : ( -
-
- -
- - -
+ {savedColors.length > 0 ? ( +
+ {[ + ...savedColors.map((color) => ( + + )), + ]}
- {savedColors.length > 0 ? ( -
- {[ - ...savedColors.map((color) => ( - - )), - ]} -
- ) : null} -
- )} -
- - + ) : null} +
+ )} +
+ ); } @@ -1743,4 +1740,11 @@ export class ColorPicker private handleColorPickerBlur = (): void => { this.el.blur(); }; + + private clickHandler = (): void => { + if (this.disabled) { + return; + } + this.handleColorPickerBlur(); + }; } From 23e4bb7d31e0e7efaee8dece77dfccbc0060d3b7 Mon Sep 17 00:00:00 2001 From: aPreciado88 Date: Fri, 28 Jun 2024 17:19:06 -0700 Subject: [PATCH 09/13] feat(color-picker,color-picker-hex-input): update input blur logic --- .../color-picker-hex-input.tsx | 3 +- .../components/color-picker/color-picker.tsx | 55 +++++++++++++++---- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx index 54a2e3fbc83..aef3fa538fc 100644 --- a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx +++ b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx @@ -18,6 +18,7 @@ import { hexChar, hexify, isLonghandHex, + isShorthandHex, isValidHex, normalizeHex, opacityToAlpha, @@ -146,7 +147,7 @@ export class ColorPickerHexInput implements LoadableComponent { const willClearValue = allowEmpty && !inputValue; const isLonghand = isLonghandHex(hex); - if (this.validateShortHandValue(inputValue)) { + if (isShorthandHex(hex, this.alphaChannel)) { // ensure modified pasted hex values are committed since we prevent default to remove the # char. this.onHexInputChange(); } diff --git a/packages/calcite-components/src/components/color-picker/color-picker.tsx b/packages/calcite-components/src/components/color-picker/color-picker.tsx index f78a6d421cd..0f652af5cd3 100644 --- a/packages/calcite-components/src/components/color-picker/color-picker.tsx +++ b/packages/calcite-components/src/components/color-picker/color-picker.tsx @@ -344,6 +344,12 @@ export class ColorPicker private channelInputClear = false; + private hexInputRef: HTMLCalciteColorPickerHexInputElement; + + private tabsRef: HTMLCalciteTabsElement; + + private focusedInput: boolean = false; + @State() channelMode: ColorMode = "rgb"; @State() channels: Channels = this.toChannels(DEFAULT_COLOR); @@ -462,6 +468,10 @@ export class ColorPicker } }; + private setFocusedInput = (): void => { + this.focusedInput = true; + }; + private handleSavedColorSelect = (event: Event): void => { const swatch = event.currentTarget as HTMLCalciteColorPickerSwatchElement; this.internalColorSet(Color(swatch.color)); @@ -517,6 +527,7 @@ export class ColorPicker handleChannelFocus = (event: Event): void => { const input = event.currentTarget as HTMLCalciteInputNumberElement; input.selectText(); + this.setFocusedInput(); }; // using @Listen as a workaround for VDOM listener not firing @@ -847,7 +858,7 @@ export class ColorPicker return ( -
+
-
+
{noHex ? null : ( @@ -942,6 +954,8 @@ export class ColorPicker messages={messages} numberingSystem={this.numberingSystem} onCalciteColorPickerHexInputChange={this.handleHexInputChange} + onFocus={this.setFocusedInput} + ref={this.setHexInputRef} scale={scale} value={selectedColorInHex} /> @@ -953,6 +967,7 @@ export class ColorPicker [CSS.colorModeContainer]: true, [CSS.splitSection]: true, }} + ref={this.setTabsRef} scale={scale === "l" ? "m" : "s"} > @@ -967,7 +982,10 @@ export class ColorPicker
)} {noSaved ? null : ( -
+
@@ -1689,6 +1707,14 @@ export class ColorPicker this.opacityScopeNode = node; }; + private setHexInputRef = (el: HTMLCalciteColorPickerHexInputElement): void => { + this.hexInputRef = el; + }; + + private setTabsRef = (el: HTMLCalciteTabsElement): void => { + this.tabsRef = el; + }; + private handleOpacityScopeKeyDown = (event: KeyboardEvent): void => { const modifier = event.shiftKey ? 10 : 1; const { key } = event; @@ -1737,14 +1763,23 @@ export class ColorPicker return [left - SCOPE_SIZE / 2, top - SCOPE_SIZE / 2]; } - private handleColorPickerBlur = (): void => { - this.el.blur(); - }; - - private clickHandler = (): void => { - if (this.disabled) { + private handleOnClick = (event: PointerEvent): void => { + const clickedElement = event.composedPath()[0] as HTMLCalciteInputElement; + if (!this.focusedInput || clickedElement.tagName === "INPUT") { return; } - this.handleColorPickerBlur(); + + this.focusedInput = false; + + const channelInputs = Array.from(this.tabsRef.querySelectorAll(".channel")); + channelInputs.forEach((element: HTMLCalciteInputNumberElement) => element?.blur()); + + const hexInput: HTMLCalciteInputTextElement = + this.hexInputRef.shadowRoot.querySelector(".hex-input"); + hexInput?.blur(); + + const opacityInput: HTMLCalciteInputNumberElement = + this.hexInputRef.shadowRoot.querySelector(".opacity-input"); + opacityInput?.blur(); }; } From a425167624ccd162a45f0e5c197bb7511572ca78 Mon Sep 17 00:00:00 2001 From: aPreciado88 Date: Fri, 28 Jun 2024 17:23:41 -0700 Subject: [PATCH 10/13] feat(color-picker,color-picker-hex-input): update input blur function name --- .../src/components/color-picker/color-picker.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/calcite-components/src/components/color-picker/color-picker.tsx b/packages/calcite-components/src/components/color-picker/color-picker.tsx index 0f652af5cd3..b51ca46a767 100644 --- a/packages/calcite-components/src/components/color-picker/color-picker.tsx +++ b/packages/calcite-components/src/components/color-picker/color-picker.tsx @@ -881,7 +881,7 @@ export class ColorPicker tabindex="0" />
-
+
{noHex ? null : ( @@ -984,7 +984,7 @@ export class ColorPicker {noSaved ? null : (
@@ -1763,7 +1763,7 @@ export class ColorPicker return [left - SCOPE_SIZE / 2, top - SCOPE_SIZE / 2]; } - private handleOnClick = (event: PointerEvent): void => { + private blurInputFields = (event: PointerEvent): void => { const clickedElement = event.composedPath()[0] as HTMLCalciteInputElement; if (!this.focusedInput || clickedElement.tagName === "INPUT") { return; From 301910180f1cd0e28bb204c43b0e81547e7aabc5 Mon Sep 17 00:00:00 2001 From: aPreciado88 Date: Tue, 2 Jul 2024 16:06:04 -0700 Subject: [PATCH 11/13] feat(color-picker,color-picker-hex-input): update end to end tests --- .../calcite-components/src/components.d.ts | 98 ++++++++++++++++ .../color-picker-hex-input.e2e.ts | 60 ++++++++++ .../color-picker/color-picker.e2e.ts | 109 ++++++++++++++++++ .../components/color-picker/color-picker.tsx | 22 ++-- 4 files changed, 278 insertions(+), 11 deletions(-) diff --git a/packages/calcite-components/src/components.d.ts b/packages/calcite-components/src/components.d.ts index c5ada57ac20..3a76eb679f5 100644 --- a/packages/calcite-components/src/components.d.ts +++ b/packages/calcite-components/src/components.d.ts @@ -8,86 +8,184 @@ import { HTMLStencilElement, JSXBase } from "@stencil/core/internal"; import { Alignment, Appearance, CollapseDirection, FlipContext, IconType, Kind, Layout, LogicalFlowPosition, Position, Scale, SelectionAppearance as SelectionAppearance1, SelectionMode, Status, Width } from "./components/interfaces"; import { RequestedItem } from "./components/accordion/interfaces"; import { RequestedItem as RequestedItem1 } from "./components/accordion-item/interfaces"; +import { ActionMessages } from "./components/action/assets/action/t9n"; import { FlipPlacement, LogicalPlacement, MenuPlacement, OverlayPositioning, ReferenceElement } from "./utils/floating-ui"; +import { ActionBarMessages } from "./components/action-bar/assets/action-bar/t9n"; import { Columns } from "./components/action-group/interfaces"; +import { ActionGroupMessages } from "./components/action-group/assets/action-group/t9n"; +import { ActionPadMessages } from "./components/action-pad/assets/action-pad/t9n"; import { AlertDuration, Sync } from "./components/alert/interfaces"; import { NumberingSystem } from "./utils/locale"; +import { AlertMessages } from "./components/alert/assets/alert/t9n"; import { HeadingLevel } from "./components/functional/Heading"; +import { BlockMessages } from "./components/block/assets/block/t9n"; import { BlockSectionToggleDisplay } from "./components/block-section/interfaces"; +import { BlockSectionMessages } from "./components/block-section/assets/block-section/t9n"; import { ButtonAlignment, DropdownIconType } from "./components/button/interfaces"; +import { ButtonMessages } from "./components/button/assets/button/t9n"; +import { CardMessages } from "./components/card/assets/card/t9n"; import { ArrowType, AutoplayType } from "./components/carousel/interfaces"; +import { CarouselMessages } from "./components/carousel/assets/carousel/t9n"; import { MutableValidityState } from "./utils/form"; +import { ChipMessages } from "./components/chip/assets/chip/t9n"; import { ColorValue, InternalColor } from "./components/color-picker/interfaces"; import { Format } from "./components/color-picker/utils"; +import { ColorPickerMessages } from "./components/color-picker/assets/color-picker/t9n"; import { ComboboxChildElement, SelectionDisplay } from "./components/combobox/interfaces"; +import { ComboboxMessages } from "./components/combobox/assets/combobox/t9n"; +import { DatePickerMessages } from "./components/date-picker/assets/date-picker/t9n"; import { DateLocaleData } from "./components/date-picker/utils"; import { HoverRange } from "./utils/date"; import { RequestedItem as RequestedItem2 } from "./components/dropdown-group/interfaces"; import { ItemKeyboardEvent } from "./components/dropdown/interfaces"; +import { FilterMessages } from "./components/filter/assets/filter/t9n"; import { FlowItemLikeElement } from "./components/flow/interfaces"; +import { FlowItemMessages } from "./components/flow-item/assets/flow-item/t9n"; import { ColorStop, DataSeries } from "./components/graph/interfaces"; +import { HandleMessages } from "./components/handle/assets/handle/t9n"; import { HandleChange, HandleNudge } from "./components/handle/interfaces"; +import { InlineEditableMessages } from "./components/inline-editable/assets/inline-editable/t9n"; import { InputPlacement } from "./components/input/interfaces"; +import { InputMessages } from "./components/input/assets/input/t9n"; +import { InputDatePickerMessages } from "./components/input-date-picker/assets/input-date-picker/t9n"; +import { InputNumberMessages } from "./components/input-number/assets/input-number/t9n"; +import { InputTextMessages } from "./components/input-text/assets/input-text/t9n"; +import { InputTimePickerMessages } from "./components/input-time-picker/assets/input-time-picker/t9n"; +import { TimePickerMessages } from "./components/time-picker/assets/time-picker/t9n"; +import { InputTimeZoneMessages } from "./components/input-time-zone/assets/input-time-zone/t9n"; import { OffsetStyle, TimeZoneMode } from "./components/input-time-zone/interfaces"; import { ListDragDetail } from "./components/list/interfaces"; import { ItemData } from "./components/list-item/interfaces"; +import { ListMessages } from "./components/list/assets/list/t9n"; import { SelectionAppearance } from "./components/list/resources"; +import { ListItemMessages } from "./components/list-item/assets/list-item/t9n"; +import { MenuMessages } from "./components/menu/assets/menu/t9n"; +import { MenuItemMessages } from "./components/menu-item/assets/menu-item/t9n"; import { MenuItemCustomEvent } from "./components/menu-item/interfaces"; import { MeterFillType, MeterLabelType } from "./components/meter/interfaces"; +import { ModalMessages } from "./components/modal/assets/modal/t9n"; +import { NoticeMessages } from "./components/notice/assets/notice/t9n"; +import { PaginationMessages } from "./components/pagination/assets/pagination/t9n"; +import { PanelMessages } from "./components/panel/assets/panel/t9n"; import { ItemData as ItemData1, ListFocusId } from "./components/pick-list/shared-list-logic"; import { ICON_TYPES } from "./components/pick-list/resources"; +import { PickListItemMessages } from "./components/pick-list-item/assets/pick-list-item/t9n"; +import { PopoverMessages } from "./components/popover/assets/popover/t9n"; +import { RatingMessages } from "./components/rating/assets/rating/t9n"; +import { ScrimMessages } from "./components/scrim/assets/scrim/t9n"; import { DisplayMode } from "./components/sheet/interfaces"; import { DisplayMode as DisplayMode1 } from "./components/shell-panel/interfaces"; +import { ShellPanelMessages } from "./components/shell-panel/assets/shell-panel/t9n"; import { DragDetail } from "./utils/sortableComponent"; import { StepperItemChangeEventDetail, StepperItemEventDetail, StepperItemKeyEventDetail, StepperLayout } from "./components/stepper/interfaces"; +import { StepperMessages } from "./components/stepper/assets/stepper/t9n"; +import { StepperItemMessages } from "./components/stepper-item/assets/stepper-item/t9n"; import { TabID, TabLayout, TabPosition } from "./components/tabs/interfaces"; +import { TabNavMessages } from "./components/tab-nav/assets/tab-nav/t9n"; import { TabChangeEventDetail, TabCloseEventDetail } from "./components/tab/interfaces"; +import { TabTitleMessages } from "./components/tab-title/assets/tab-title/t9n"; import { RowType, TableInteractionMode, TableLayout, TableRowFocusEvent, TableSelectionDisplay } from "./components/table/interfaces"; +import { TableMessages } from "./components/table/assets/table/t9n"; +import { TableCellMessages } from "./components/table-cell/assets/table-cell/t9n"; +import { TableHeaderMessages } from "./components/table-header/assets/table-header/t9n"; +import { TextAreaMessages } from "./components/text-area/assets/text-area/t9n"; import { TileSelectType } from "./components/tile-select/interfaces"; import { TileSelectGroupLayout } from "./components/tile-select-group/interfaces"; +import { TipMessages } from "./components/tip/assets/tip/t9n"; +import { TipManagerMessages } from "./components/tip-manager/assets/tip-manager/t9n"; import { TreeItemSelectDetail } from "./components/tree-item/interfaces"; +import { ValueListMessages } from "./components/value-list/assets/value-list/t9n"; import { ListItemAndHandle } from "./components/value-list-item/interfaces"; export { Alignment, Appearance, CollapseDirection, FlipContext, IconType, Kind, Layout, LogicalFlowPosition, Position, Scale, SelectionAppearance as SelectionAppearance1, SelectionMode, Status, Width } from "./components/interfaces"; export { RequestedItem } from "./components/accordion/interfaces"; export { RequestedItem as RequestedItem1 } from "./components/accordion-item/interfaces"; +export { ActionMessages } from "./components/action/assets/action/t9n"; export { FlipPlacement, LogicalPlacement, MenuPlacement, OverlayPositioning, ReferenceElement } from "./utils/floating-ui"; +export { ActionBarMessages } from "./components/action-bar/assets/action-bar/t9n"; export { Columns } from "./components/action-group/interfaces"; +export { ActionGroupMessages } from "./components/action-group/assets/action-group/t9n"; +export { ActionPadMessages } from "./components/action-pad/assets/action-pad/t9n"; export { AlertDuration, Sync } from "./components/alert/interfaces"; export { NumberingSystem } from "./utils/locale"; +export { AlertMessages } from "./components/alert/assets/alert/t9n"; export { HeadingLevel } from "./components/functional/Heading"; +export { BlockMessages } from "./components/block/assets/block/t9n"; export { BlockSectionToggleDisplay } from "./components/block-section/interfaces"; +export { BlockSectionMessages } from "./components/block-section/assets/block-section/t9n"; export { ButtonAlignment, DropdownIconType } from "./components/button/interfaces"; +export { ButtonMessages } from "./components/button/assets/button/t9n"; +export { CardMessages } from "./components/card/assets/card/t9n"; export { ArrowType, AutoplayType } from "./components/carousel/interfaces"; +export { CarouselMessages } from "./components/carousel/assets/carousel/t9n"; export { MutableValidityState } from "./utils/form"; +export { ChipMessages } from "./components/chip/assets/chip/t9n"; export { ColorValue, InternalColor } from "./components/color-picker/interfaces"; export { Format } from "./components/color-picker/utils"; +export { ColorPickerMessages } from "./components/color-picker/assets/color-picker/t9n"; export { ComboboxChildElement, SelectionDisplay } from "./components/combobox/interfaces"; +export { ComboboxMessages } from "./components/combobox/assets/combobox/t9n"; +export { DatePickerMessages } from "./components/date-picker/assets/date-picker/t9n"; export { DateLocaleData } from "./components/date-picker/utils"; export { HoverRange } from "./utils/date"; export { RequestedItem as RequestedItem2 } from "./components/dropdown-group/interfaces"; export { ItemKeyboardEvent } from "./components/dropdown/interfaces"; +export { FilterMessages } from "./components/filter/assets/filter/t9n"; export { FlowItemLikeElement } from "./components/flow/interfaces"; +export { FlowItemMessages } from "./components/flow-item/assets/flow-item/t9n"; export { ColorStop, DataSeries } from "./components/graph/interfaces"; +export { HandleMessages } from "./components/handle/assets/handle/t9n"; export { HandleChange, HandleNudge } from "./components/handle/interfaces"; +export { InlineEditableMessages } from "./components/inline-editable/assets/inline-editable/t9n"; export { InputPlacement } from "./components/input/interfaces"; +export { InputMessages } from "./components/input/assets/input/t9n"; +export { InputDatePickerMessages } from "./components/input-date-picker/assets/input-date-picker/t9n"; +export { InputNumberMessages } from "./components/input-number/assets/input-number/t9n"; +export { InputTextMessages } from "./components/input-text/assets/input-text/t9n"; +export { InputTimePickerMessages } from "./components/input-time-picker/assets/input-time-picker/t9n"; +export { TimePickerMessages } from "./components/time-picker/assets/time-picker/t9n"; +export { InputTimeZoneMessages } from "./components/input-time-zone/assets/input-time-zone/t9n"; export { OffsetStyle, TimeZoneMode } from "./components/input-time-zone/interfaces"; export { ListDragDetail } from "./components/list/interfaces"; export { ItemData } from "./components/list-item/interfaces"; +export { ListMessages } from "./components/list/assets/list/t9n"; export { SelectionAppearance } from "./components/list/resources"; +export { ListItemMessages } from "./components/list-item/assets/list-item/t9n"; +export { MenuMessages } from "./components/menu/assets/menu/t9n"; +export { MenuItemMessages } from "./components/menu-item/assets/menu-item/t9n"; export { MenuItemCustomEvent } from "./components/menu-item/interfaces"; export { MeterFillType, MeterLabelType } from "./components/meter/interfaces"; +export { ModalMessages } from "./components/modal/assets/modal/t9n"; +export { NoticeMessages } from "./components/notice/assets/notice/t9n"; +export { PaginationMessages } from "./components/pagination/assets/pagination/t9n"; +export { PanelMessages } from "./components/panel/assets/panel/t9n"; export { ItemData as ItemData1, ListFocusId } from "./components/pick-list/shared-list-logic"; export { ICON_TYPES } from "./components/pick-list/resources"; +export { PickListItemMessages } from "./components/pick-list-item/assets/pick-list-item/t9n"; +export { PopoverMessages } from "./components/popover/assets/popover/t9n"; +export { RatingMessages } from "./components/rating/assets/rating/t9n"; +export { ScrimMessages } from "./components/scrim/assets/scrim/t9n"; export { DisplayMode } from "./components/sheet/interfaces"; export { DisplayMode as DisplayMode1 } from "./components/shell-panel/interfaces"; +export { ShellPanelMessages } from "./components/shell-panel/assets/shell-panel/t9n"; export { DragDetail } from "./utils/sortableComponent"; export { StepperItemChangeEventDetail, StepperItemEventDetail, StepperItemKeyEventDetail, StepperLayout } from "./components/stepper/interfaces"; +export { StepperMessages } from "./components/stepper/assets/stepper/t9n"; +export { StepperItemMessages } from "./components/stepper-item/assets/stepper-item/t9n"; export { TabID, TabLayout, TabPosition } from "./components/tabs/interfaces"; +export { TabNavMessages } from "./components/tab-nav/assets/tab-nav/t9n"; export { TabChangeEventDetail, TabCloseEventDetail } from "./components/tab/interfaces"; +export { TabTitleMessages } from "./components/tab-title/assets/tab-title/t9n"; export { RowType, TableInteractionMode, TableLayout, TableRowFocusEvent, TableSelectionDisplay } from "./components/table/interfaces"; +export { TableMessages } from "./components/table/assets/table/t9n"; +export { TableCellMessages } from "./components/table-cell/assets/table-cell/t9n"; +export { TableHeaderMessages } from "./components/table-header/assets/table-header/t9n"; +export { TextAreaMessages } from "./components/text-area/assets/text-area/t9n"; export { TileSelectType } from "./components/tile-select/interfaces"; export { TileSelectGroupLayout } from "./components/tile-select-group/interfaces"; +export { TipMessages } from "./components/tip/assets/tip/t9n"; +export { TipManagerMessages } from "./components/tip-manager/assets/tip-manager/t9n"; export { TreeItemSelectDetail } from "./components/tree-item/interfaces"; +export { ValueListMessages } from "./components/value-list/assets/value-list/t9n"; export { ListItemAndHandle } from "./components/value-list-item/interfaces"; export namespace Components { interface CalciteAccordion { diff --git a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.e2e.ts b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.e2e.ts index 6aff1f4866e..1d27deacd88 100644 --- a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.e2e.ts +++ b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.e2e.ts @@ -108,6 +108,66 @@ describe("calcite-color-picker-hex-input", () => { expect(await input.getProperty("value")).toBe("#fafafafa"); }); + it("commits shorthand hex on blur", async () => { + const defaultHex = "#b33f33"; + const editedHex = "#aabbcc"; + const page = await newE2EPage(); + await page.setContent(``); + + const input = await page.find(`calcite-color-picker-hex-input`); + await selectText(input); + await page.keyboard.type("ab"); + await page.keyboard.press("Tab"); + await page.waitForChanges(); + + expect(await input.getProperty("value")).toBe(defaultHex); + + await selectText(input); + await page.keyboard.type("abc"); + await page.keyboard.press("Tab"); + await page.waitForChanges(); + + expect(await input.getProperty("value")).toBe(editedHex); + + await selectText(input); + await page.keyboard.type("abcd"); + await page.keyboard.press("Tab"); + await page.waitForChanges(); + + expect(await input.getProperty("value")).toBe(editedHex); + }); + + it("commits shorthand hexa on blur", async () => { + const defaultHexa = "#b33f33ff"; + const editedHexa = "#aabbccdd"; + const page = await newE2EPage(); + await page.setContent( + ``, + ); + + const input = await page.find(`calcite-color-picker-hex-input`); + await selectText(input); + await page.keyboard.type("abc"); + await page.keyboard.press("Tab"); + await page.waitForChanges(); + + expect(await input.getProperty("value")).toBe(defaultHexa); + + await selectText(input); + await page.keyboard.type("abcd"); + await page.keyboard.press("Tab"); + await page.waitForChanges(); + + expect(await input.getProperty("value")).toBe(editedHexa); + + await selectText(input); + await page.keyboard.type("abcde"); + await page.keyboard.press("Tab"); + await page.waitForChanges(); + + expect(await input.getProperty("value")).toBe(editedHexa); + }); + it("normalizes value when initialized", async () => { const page = await newE2EPage(); await page.setContent(""); diff --git a/packages/calcite-components/src/components/color-picker/color-picker.e2e.ts b/packages/calcite-components/src/components/color-picker/color-picker.e2e.ts index 0ead2590485..cf7acfe2860 100644 --- a/packages/calcite-components/src/components/color-picker/color-picker.e2e.ts +++ b/packages/calcite-components/src/components/color-picker/color-picker.e2e.ts @@ -249,6 +249,115 @@ describe("calcite-color-picker", () => { expect(inputSpy.length).toBe(previousInputEventLength); }); + // same should apply for other channel inputs + it("increments channel's value by 1 when clearing input and pressing ArrowUp", async () => { + const page = await newE2EPage(); + await page.setContent(""); + const channelInput = await page.find(`calcite-color-picker >>> .${CSS.channel}`); + const currentValue = await channelInput.getProperty("value"); + + await selectText(channelInput); + await page.keyboard.press("Backspace"); + await page.keyboard.press("ArrowUp"); + await page.waitForChanges(); + + expect(await channelInput.getProperty("value")).toBe(`${Number(currentValue) + 1}`); + }); + + // same should apply for other channel inputs + it("decrements channel's value by 1 when clearing input and pressing ArrowDown", async () => { + const page = await newE2EPage(); + await page.setContent(""); + const channelInput = await page.find(`calcite-color-picker >>> .${CSS.channel}`); + const currentValue = await channelInput.getProperty("value"); + + await selectText(channelInput); + await page.keyboard.press("Backspace"); + await page.keyboard.press("ArrowDown"); + await page.waitForChanges(); + + expect(await channelInput.getProperty("value")).toBe(`${Number(currentValue) - 1}`); + }); + + // same should apply for other channel inputs + it("prevents channel's value from going over its limit when clearing input and pressing ArrowUp", async () => { + const page = await newE2EPage(); + await page.setContent(""); + const channelInput = await page.find(`calcite-color-picker >>> .${CSS.channel}`); + + await selectText(channelInput); + await page.keyboard.press("Backspace"); + await page.keyboard.press("ArrowUp"); + await page.waitForChanges(); + + expect(await channelInput.getProperty("value")).toBe("255"); + }); + + // same should apply for other channel inputs + it("prevents channel's value from being less than 0 when clearing input and pressing ArrowDown", async () => { + const page = await newE2EPage(); + await page.setContent(""); + const channelInput = await page.find(`calcite-color-picker >>> .${CSS.channel}`); + + await selectText(channelInput); + await page.keyboard.press("Backspace"); + await page.keyboard.press("ArrowDown"); + await page.waitForChanges(); + + expect(await channelInput.getProperty("value")).toBe("0"); + }); + + // same should apply for other channel inputs + it("restores original channel value when input is cleared and blur is triggered", async () => { + const page = await newE2EPage(); + await page.setContent(""); + const channelInput = await page.find(`calcite-color-picker >>> .${CSS.channel}`); + const currentValue = await channelInput.getProperty("value"); + + await selectText(channelInput); + await page.keyboard.press("Backspace"); + await page.keyboard.press("Tab"); + await page.waitForChanges(); + + expect(await channelInput.getProperty("value")).toBe(currentValue); + }); + + // same should apply for other channel inputs + it("auto commits channel value when typing", async () => { + const page = await newE2EPage(); + await page.setContent(""); + + const channelInput = await page.find(`calcite-color-picker >>> .${CSS.channel}`); + const picker = await page.find("calcite-color-picker"); + const changeSpy = await picker.spyOnEvent("calciteColorPickerChange"); + + await selectText(channelInput); + await page.keyboard.type("123"); + await page.waitForChanges(); + + expect(changeSpy).toHaveReceivedEventTimes(3); + expect(await channelInput.getProperty("value")).toBe("123"); + }); + + // it should apply to all inputs + it("blurs focused input when clicking anywhere within the component", async () => { + const page = await newE2EPage(); + await page.setContent(""); + + const channelInput = await page.find(`calcite-color-picker >>> .${CSS.channel}`); + const currentValue = await channelInput.getProperty("value"); + const picker = await page.find("calcite-color-picker"); + const blurSpy = await picker.spyOnEvent("calciteInternalInputNumberBlur"); + + await selectText(channelInput); + await page.keyboard.press("Backspace"); + await page.mouse.click(0, 0); + await page.waitForChanges(); + + expect(blurSpy).toHaveReceivedEventTimes(1); + expect(await channelInput.getProperty("value")).toBe(currentValue); + }); + it("does not emit on initialization", async () => { const page = await newProgrammaticE2EPage(); diff --git a/packages/calcite-components/src/components/color-picker/color-picker.tsx b/packages/calcite-components/src/components/color-picker/color-picker.tsx index b51ca46a767..22ad188559a 100644 --- a/packages/calcite-components/src/components/color-picker/color-picker.tsx +++ b/packages/calcite-components/src/components/color-picker/color-picker.tsx @@ -340,9 +340,9 @@ export class ColorPicker private shiftKeyChannelAdjustment = 0; - private arrowUpOrDownTracker = ""; + private arrowKeyTracker: "up" | "down" | null = null; - private channelInputClear = false; + private isChannelInputEmpty: boolean = false; private hexInputRef: HTMLCalciteColorPickerHexInputElement; @@ -492,9 +492,9 @@ export class ColorPicker if (!input.value) { inputValue = ""; - this.channelInputClear = true; - // reset this to allow typing in new value when channel input is empty - this.arrowUpOrDownTracker = ""; + this.isChannelInputEmpty = true; + // reset this to allow typing in new value, when channel input is cleared after ArrowUp or ArrowDown have been pressed + this.arrowKeyTracker = null; } else { const value = Number(input.value); const adjustedValue = value + this.shiftKeyChannelAdjustment; @@ -564,10 +564,10 @@ export class ColorPicker : 0; if (key === "ArrowUp") { - this.arrowUpOrDownTracker = "arrowUp"; + this.arrowKeyTracker = "up"; } if (key === "ArrowDown") { - this.arrowUpOrDownTracker = "arrowDown"; + this.arrowKeyTracker = "down"; } } @@ -592,16 +592,16 @@ export class ColorPicker const isAlphaChannel = channelIndex === 3; - if (this.channelInputClear && this.arrowUpOrDownTracker !== "") { + if (this.isChannelInputEmpty && this.arrowKeyTracker) { input.value = - this.arrowUpOrDownTracker === "arrowUp" + this.arrowKeyTracker === "up" ? (channels[channelIndex] + 1 <= this.getChannelInputLimit(channelIndex) ? channels[channelIndex] + 1 : this.getChannelInputLimit(channelIndex) ).toString() : (channels[channelIndex] - 1 >= 0 ? channels[channelIndex] - 1 : 0).toString(); - this.channelInputClear = false; - this.arrowUpOrDownTracker = ""; + this.isChannelInputEmpty = false; + this.arrowKeyTracker = null; } const value = input.value ? Number(input.value) : channels[channelIndex]; From fcf027c84d9d295807ce11a3cbb8b7b7d3f47eda Mon Sep 17 00:00:00 2001 From: aPreciado88 Date: Fri, 5 Jul 2024 16:46:27 -0700 Subject: [PATCH 12/13] fix(tile): update input blur logic and code clean up --- .../color-picker-hex-input.tsx | 12 +-- .../color-picker/color-picker.e2e.ts | 21 ++-- .../components/color-picker/color-picker.tsx | 100 ++++++------------ 3 files changed, 40 insertions(+), 93 deletions(-) diff --git a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx index aef3fa538fc..c6e81c434e5 100644 --- a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx +++ b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx @@ -243,7 +243,7 @@ export class ColorPickerHexInput implements LoadableComponent { const { key } = event; const composedPath = event.composedPath(); - if ((key === "Tab" && this.validateShortHandValue(value)) || key === "Enter") { + if ((key === "Tab" && isShorthandHex(value, this.alphaChannel)) || key === "Enter") { if (composedPath.includes(hexInputNode)) { this.onHexInputChange(); } else { @@ -469,14 +469,4 @@ export class ColorPickerHexInput implements LoadableComponent { return Color(nudgedChannels); } - - /* - if alphaChannel is enabled, commit valid 4 digit hex codes. - if alphaChannel is disabled, commit valid 3 digit hex codes. - */ - private validateShortHandValue = (value: string): boolean => { - return ( - (this.alphaChannel && value?.length === 4) || (!this.alphaChannel && value?.length === 3) - ); - }; } diff --git a/packages/calcite-components/src/components/color-picker/color-picker.e2e.ts b/packages/calcite-components/src/components/color-picker/color-picker.e2e.ts index cf7acfe2860..a9cabcd7117 100644 --- a/packages/calcite-components/src/components/color-picker/color-picker.e2e.ts +++ b/packages/calcite-components/src/components/color-picker/color-picker.e2e.ts @@ -249,8 +249,7 @@ describe("calcite-color-picker", () => { expect(inputSpy.length).toBe(previousInputEventLength); }); - // same should apply for other channel inputs - it("increments channel's value by 1 when clearing input and pressing ArrowUp", async () => { + it("increments channel's value by 1 when clearing input and pressing ArrowUp. Same should apply to other channel inputs", async () => { const page = await newE2EPage(); await page.setContent(""); const channelInput = await page.find(`calcite-color-picker >>> .${CSS.channel}`); @@ -264,8 +263,7 @@ describe("calcite-color-picker", () => { expect(await channelInput.getProperty("value")).toBe(`${Number(currentValue) + 1}`); }); - // same should apply for other channel inputs - it("decrements channel's value by 1 when clearing input and pressing ArrowDown", async () => { + it("decrements channel's value by 1 when clearing input and pressing ArrowDown. Same should apply to other channel inputs", async () => { const page = await newE2EPage(); await page.setContent(""); const channelInput = await page.find(`calcite-color-picker >>> .${CSS.channel}`); @@ -279,8 +277,7 @@ describe("calcite-color-picker", () => { expect(await channelInput.getProperty("value")).toBe(`${Number(currentValue) - 1}`); }); - // same should apply for other channel inputs - it("prevents channel's value from going over its limit when clearing input and pressing ArrowUp", async () => { + it("prevents channel's value from going over its limit when clearing input and pressing ArrowUp. Same should apply to other channel inputs", async () => { const page = await newE2EPage(); await page.setContent(""); const channelInput = await page.find(`calcite-color-picker >>> .${CSS.channel}`); @@ -293,8 +290,7 @@ describe("calcite-color-picker", () => { expect(await channelInput.getProperty("value")).toBe("255"); }); - // same should apply for other channel inputs - it("prevents channel's value from being less than 0 when clearing input and pressing ArrowDown", async () => { + it("prevents channel's value from being less than 0 when clearing input and pressing ArrowDown. Same should apply to other channel inputs", async () => { const page = await newE2EPage(); await page.setContent(""); const channelInput = await page.find(`calcite-color-picker >>> .${CSS.channel}`); @@ -307,8 +303,7 @@ describe("calcite-color-picker", () => { expect(await channelInput.getProperty("value")).toBe("0"); }); - // same should apply for other channel inputs - it("restores original channel value when input is cleared and blur is triggered", async () => { + it("restores original channel value when input is cleared and blur is triggered. Same should apply to other channel inputs", async () => { const page = await newE2EPage(); await page.setContent(""); const channelInput = await page.find(`calcite-color-picker >>> .${CSS.channel}`); @@ -322,8 +317,7 @@ describe("calcite-color-picker", () => { expect(await channelInput.getProperty("value")).toBe(currentValue); }); - // same should apply for other channel inputs - it("auto commits channel value when typing", async () => { + it("auto commits channel value when typing. Same should apply to other channel inputs", async () => { const page = await newE2EPage(); await page.setContent(""); @@ -339,8 +333,7 @@ describe("calcite-color-picker", () => { expect(await channelInput.getProperty("value")).toBe("123"); }); - // it should apply to all inputs - it("blurs focused input when clicking anywhere within the component", async () => { + it("blurs focused input when clicking anywhere within the component. It should apply to all inputs", async () => { const page = await newE2EPage(); await page.setContent(""); diff --git a/packages/calcite-components/src/components/color-picker/color-picker.tsx b/packages/calcite-components/src/components/color-picker/color-picker.tsx index 22ad188559a..310f4928295 100644 --- a/packages/calcite-components/src/components/color-picker/color-picker.tsx +++ b/packages/calcite-components/src/components/color-picker/color-picker.tsx @@ -13,7 +13,12 @@ import { } from "@stencil/core"; import Color from "color"; import { throttle } from "lodash-es"; -import { Direction, getElementDir, isPrimaryPointerButton } from "../../utils/dom"; +import { + Direction, + focusFirstTabbable, + getElementDir, + isPrimaryPointerButton, +} from "../../utils/dom"; import { Scale } from "../interfaces"; import { connectInteractive, @@ -79,9 +84,7 @@ const throttleFor60FpsInMs = 16; @Component({ tag: "calcite-color-picker", styleUrl: "color-picker.scss", - shadow: { - delegatesFocus: true, - }, + shadow: {}, assetsDirs: ["assets"], }) export class ColorPicker @@ -340,15 +343,9 @@ export class ColorPicker private shiftKeyChannelAdjustment = 0; - private arrowKeyTracker: "up" | "down" | null = null; - - private isChannelInputEmpty: boolean = false; - - private hexInputRef: HTMLCalciteColorPickerHexInputElement; - - private tabsRef: HTMLCalciteTabsElement; + private upOrDownArrowKeyTracker: "down" | null | "up" = null; - private focusedInput: boolean = false; + private isActiveChannelInputEmpty: boolean = false; @State() channelMode: ColorMode = "rgb"; @@ -468,10 +465,6 @@ export class ColorPicker } }; - private setFocusedInput = (): void => { - this.focusedInput = true; - }; - private handleSavedColorSelect = (event: Event): void => { const swatch = event.currentTarget as HTMLCalciteColorPickerSwatchElement; this.internalColorSet(Color(swatch.color)); @@ -492,9 +485,9 @@ export class ColorPicker if (!input.value) { inputValue = ""; - this.isChannelInputEmpty = true; + this.isActiveChannelInputEmpty = true; // reset this to allow typing in new value, when channel input is cleared after ArrowUp or ArrowDown have been pressed - this.arrowKeyTracker = null; + this.upOrDownArrowKeyTracker = null; } else { const value = Number(input.value); const adjustedValue = value + this.shiftKeyChannelAdjustment; @@ -517,9 +510,9 @@ export class ColorPicker const input = event.currentTarget as HTMLCalciteInputNumberElement; const channelIndex = Number(input.getAttribute("data-channel-index")); const channels = [...this.channels] as this["channels"]; + const restoreValueDueToEmptyInput = !input.value && !this.isClearable; - // restore original value when input field is left blank - if (!input.value && !this.isClearable) { + if (restoreValueDueToEmptyInput) { input.value = channels[channelIndex]?.toString(); } }; @@ -527,7 +520,6 @@ export class ColorPicker handleChannelFocus = (event: Event): void => { const input = event.currentTarget as HTMLCalciteInputNumberElement; input.selectText(); - this.setFocusedInput(); }; // using @Listen as a workaround for VDOM listener not firing @@ -564,10 +556,10 @@ export class ColorPicker : 0; if (key === "ArrowUp") { - this.arrowKeyTracker = "up"; + this.upOrDownArrowKeyTracker = "up"; } if (key === "ArrowDown") { - this.arrowKeyTracker = "down"; + this.upOrDownArrowKeyTracker = "down"; } } @@ -592,16 +584,16 @@ export class ColorPicker const isAlphaChannel = channelIndex === 3; - if (this.isChannelInputEmpty && this.arrowKeyTracker) { + if (this.isActiveChannelInputEmpty && this.upOrDownArrowKeyTracker) { input.value = - this.arrowKeyTracker === "up" + this.upOrDownArrowKeyTracker === "up" ? (channels[channelIndex] + 1 <= this.getChannelInputLimit(channelIndex) ? channels[channelIndex] + 1 : this.getChannelInputLimit(channelIndex) ).toString() : (channels[channelIndex] - 1 >= 0 ? channels[channelIndex] - 1 : 0).toString(); - this.isChannelInputEmpty = false; - this.arrowKeyTracker = null; + this.isActiveChannelInputEmpty = false; + this.upOrDownArrowKeyTracker = null; } const value = input.value ? Number(input.value) : channels[channelIndex]; @@ -631,9 +623,15 @@ export class ColorPicker bounds: this.colorFieldRenderingContext.canvas.getBoundingClientRect(), }; this.captureColorFieldColor(offsetX, offsetY); - this.colorFieldScopeNode.focus(); + this.focusScope(this.colorFieldScopeNode); }; + private focusScope(focusEl: HTMLElement): void { + requestAnimationFrame(() => { + focusEl.focus(); + }); + } + private handleHueSliderPointerDown = (event: PointerEvent): void => { if (!isPrimaryPointerButton(event)) { return; @@ -649,7 +647,7 @@ export class ColorPicker bounds: this.hueSliderRenderingContext.canvas.getBoundingClientRect(), }; this.captureHueSliderColor(offsetX); - this.hueScopeNode.focus(); + this.focusScope(this.hueScopeNode); }; private handleOpacitySliderPointerDown = (event: PointerEvent): void => { @@ -667,7 +665,7 @@ export class ColorPicker bounds: this.opacitySliderRenderingContext.canvas.getBoundingClientRect(), }; this.captureOpacitySliderValue(offsetX); - this.opacityScopeNode.focus(); + this.focusScope(this.opacityScopeNode); }; private globalPointerUpHandler = (event: PointerEvent): void => { @@ -740,7 +738,8 @@ export class ColorPicker @Method() async setFocus(): Promise { await componentFocusable(this); - this.el.focus(); + + focusFirstTabbable(this.el); } //-------------------------------------------------------------------------- @@ -881,7 +880,7 @@ export class ColorPicker tabindex="0" />
-
+
{noHex ? null : ( @@ -954,8 +952,6 @@ export class ColorPicker messages={messages} numberingSystem={this.numberingSystem} onCalciteColorPickerHexInputChange={this.handleHexInputChange} - onFocus={this.setFocusedInput} - ref={this.setHexInputRef} scale={scale} value={selectedColorInHex} /> @@ -967,7 +963,6 @@ export class ColorPicker [CSS.colorModeContainer]: true, [CSS.splitSection]: true, }} - ref={this.setTabsRef} scale={scale === "l" ? "m" : "s"} > @@ -982,10 +977,7 @@ export class ColorPicker
)} {noSaved ? null : ( -
+
@@ -1707,14 +1699,6 @@ export class ColorPicker this.opacityScopeNode = node; }; - private setHexInputRef = (el: HTMLCalciteColorPickerHexInputElement): void => { - this.hexInputRef = el; - }; - - private setTabsRef = (el: HTMLCalciteTabsElement): void => { - this.tabsRef = el; - }; - private handleOpacityScopeKeyDown = (event: KeyboardEvent): void => { const modifier = event.shiftKey ? 10 : 1; const { key } = event; @@ -1762,24 +1746,4 @@ export class ColorPicker private getAdjustedScopePosition(left: number, top: number): [number, number] { return [left - SCOPE_SIZE / 2, top - SCOPE_SIZE / 2]; } - - private blurInputFields = (event: PointerEvent): void => { - const clickedElement = event.composedPath()[0] as HTMLCalciteInputElement; - if (!this.focusedInput || clickedElement.tagName === "INPUT") { - return; - } - - this.focusedInput = false; - - const channelInputs = Array.from(this.tabsRef.querySelectorAll(".channel")); - channelInputs.forEach((element: HTMLCalciteInputNumberElement) => element?.blur()); - - const hexInput: HTMLCalciteInputTextElement = - this.hexInputRef.shadowRoot.querySelector(".hex-input"); - hexInput?.blur(); - - const opacityInput: HTMLCalciteInputNumberElement = - this.hexInputRef.shadowRoot.querySelector(".opacity-input"); - opacityInput?.blur(); - }; } From 15f4822268b7b7012afcab496e2f398545b41cb8 Mon Sep 17 00:00:00 2001 From: aPreciado88 Date: Fri, 19 Jul 2024 15:54:56 -0700 Subject: [PATCH 13/13] feat(color-picker, color-picker-hex-input): code clean up --- .../color-picker-hex-input.tsx | 14 ++++++-------- .../src/components/color-picker/color-picker.tsx | 8 ++++---- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx index c6e81c434e5..a2090909e2f 100644 --- a/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx +++ b/packages/calcite-components/src/components/color-picker-hex-input/color-picker-hex-input.tsx @@ -183,10 +183,6 @@ export class ColorPickerHexInput implements LoadableComponent { allowEmpty && !internalColor ? "" : this.formatOpacityForInternalInput(internalColor); }; - private onOpacityInputFocus = (): void => { - this.opacityInputNode.selectText(); - }; - private onOpacityInputInput = (): void => { this.onOpacityInputChange(); }; @@ -221,8 +217,10 @@ export class ColorPickerHexInput implements LoadableComponent { this.internalSetValue(value, this.value); }; - private onHexInputFocus = (): void => { - this.hexInputNode.selectText(); + private onInputFocus = (event: Event): void => { + event.type === "calciteInternalInputTextFocus" + ? this.hexInputNode.selectText() + : this.opacityInputNode.selectText(); }; private onHexInputInput = (): void => { @@ -345,7 +343,7 @@ export class ColorPickerHexInput implements LoadableComponent { onCalciteInputTextChange={this.onHexInputChange} onCalciteInputTextInput={this.onHexInputInput} onCalciteInternalInputTextBlur={this.onHexInputBlur} - onCalciteInternalInputTextFocus={this.onHexInputFocus} + onCalciteInternalInputTextFocus={this.onInputFocus} onKeyDown={this.onInputKeyDown} onPaste={this.onHexInputPaste} prefixText="#" @@ -365,7 +363,7 @@ export class ColorPickerHexInput implements LoadableComponent { numberingSystem={this.numberingSystem} onCalciteInputNumberInput={this.onOpacityInputInput} onCalciteInternalInputNumberBlur={this.onOpacityInputBlur} - onCalciteInternalInputNumberFocus={this.onOpacityInputFocus} + onCalciteInternalInputNumberFocus={this.onInputFocus} onKeyDown={this.onInputKeyDown} ref={this.storeOpacityInputRef} scale={inputScale} diff --git a/packages/calcite-components/src/components/color-picker/color-picker.tsx b/packages/calcite-components/src/components/color-picker/color-picker.tsx index 310f4928295..53de0c34a36 100644 --- a/packages/calcite-components/src/components/color-picker/color-picker.tsx +++ b/packages/calcite-components/src/components/color-picker/color-picker.tsx @@ -84,7 +84,7 @@ const throttleFor60FpsInMs = 16; @Component({ tag: "calcite-color-picker", styleUrl: "color-picker.scss", - shadow: {}, + shadow: true, assetsDirs: ["assets"], }) export class ColorPicker @@ -331,6 +331,8 @@ export class ColorPicker private internalColorUpdateContext: "internal" | "initial" | "user-interaction" | null = null; + private isActiveChannelInputEmpty: boolean = false; + private isClearable: boolean; private mode: SupportedMode = CSSColorMode.HEX; @@ -343,9 +345,7 @@ export class ColorPicker private shiftKeyChannelAdjustment = 0; - private upOrDownArrowKeyTracker: "down" | null | "up" = null; - - private isActiveChannelInputEmpty: boolean = false; + private upOrDownArrowKeyTracker: "down" | "up" | null = null; @State() channelMode: ColorMode = "rgb";