From 3450409c065253cf2a1f951ee47ab856fae001cb Mon Sep 17 00:00:00 2001 From: eliza Date: Thu, 7 Mar 2024 08:17:37 -0800 Subject: [PATCH 1/2] =?UTF-8?q?refactor(color-picker):=20add=C2=A0clearabl?= =?UTF-8?q?e=C2=A0property=20and=20deprecate=C2=A0allowEmpty?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calcite-components/src/components.d.ts | 14 +++++- .../components/color-picker/color-picker.tsx | 47 ++++++++++++++----- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/packages/calcite-components/src/components.d.ts b/packages/calcite-components/src/components.d.ts index 6d403dea954..bd60692b48c 100644 --- a/packages/calcite-components/src/components.d.ts +++ b/packages/calcite-components/src/components.d.ts @@ -674,7 +674,7 @@ export namespace Components { */ "disabled": boolean; /** - * Specifies the optional new name of the file after it is downloaded. + * Prompts the user to save the linked URL instead of navigating to it. Can be used with or without a value: Without a value, the browser will suggest a filename/extension See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-download. */ "download": string | boolean; /** @@ -980,6 +980,7 @@ export namespace Components { interface CalciteColorPicker { /** * When `true`, an empty color (`null`) will be allowed as a `value`. When `false`, a color value is enforced, and clearing the input or blurring will restore the last valid `value`. + * @deprecated Use `clearable` instead. */ "allowEmpty": boolean; /** @@ -990,6 +991,10 @@ export namespace Components { * When `true`, hides the RGB/HSV channel inputs. */ "channelsDisabled": boolean; + /** + * When `true`, a clear button is displayed when the component has a value. + */ + "clearable": boolean; /** * Internal prop for advanced use-cases. */ @@ -8059,7 +8064,7 @@ declare namespace LocalJSX { */ "disabled"?: boolean; /** - * Specifies the optional new name of the file after it is downloaded. + * Prompts the user to save the linked URL instead of navigating to it. Can be used with or without a value: Without a value, the browser will suggest a filename/extension See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-download. */ "download"?: string | boolean; /** @@ -8375,6 +8380,7 @@ declare namespace LocalJSX { interface CalciteColorPicker { /** * When `true`, an empty color (`null`) will be allowed as a `value`. When `false`, a color value is enforced, and clearing the input or blurring will restore the last valid `value`. + * @deprecated Use `clearable` instead. */ "allowEmpty"?: boolean; /** @@ -8385,6 +8391,10 @@ declare namespace LocalJSX { * When `true`, hides the RGB/HSV channel inputs. */ "channelsDisabled"?: boolean; + /** + * When `true`, a clear button is displayed when the component has a value. + */ + "clearable"?: boolean; /** * Internal prop for advanced use-cases. */ 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 e12d1c8c840..e55b8f79bc7 100644 --- a/packages/calcite-components/src/components/color-picker/color-picker.tsx +++ b/packages/calcite-components/src/components/color-picker/color-picker.tsx @@ -98,6 +98,8 @@ export class ColorPicker * When `true`, an empty color (`null`) will be allowed as a `value`. * * When `false`, a color value is enforced, and clearing the input or blurring will restore the last valid `value`. + * + * @deprecated Use `clearable` instead. */ @Prop({ reflect: true }) allowEmpty = false; @@ -121,6 +123,11 @@ export class ColorPicker /** When `true`, hides the RGB/HSV channel inputs. */ @Prop() channelsDisabled = false; + /** + * When `true`, a clear button is displayed when the component has a value. + */ + @Prop({ reflect: true }) clearable = false; + /** * Internal prop for advanced use-cases. * @@ -225,8 +232,8 @@ export class ColorPicker @Watch("value") handleValueChange(value: ColorValue | null, oldValue: ColorValue | null): void { - const { allowEmpty, format } = this; - const checkMode = !allowEmpty || value; + const { allowEmpty, isClearable = allowEmpty, format } = this; + const checkMode = !isClearable || value; let modeChanged = false; if (checkMode) { @@ -258,7 +265,7 @@ export class ColorPicker } const color = - allowEmpty && !value + isClearable && !value ? null : Color( value != null && typeof value === "object" && alphaCompatible(this.mode) @@ -293,6 +300,10 @@ export class ColorPicker return this.color || this.previousColor || DEFAULT_COLOR; } + get isClearable(): boolean { + return this.clearable && !!this.value; + } + private checkerPattern: HTMLCanvasElement; private colorFieldRenderingContext: CanvasRenderingContext2D; @@ -417,11 +428,11 @@ export class ColorPicker private handleHexInputChange = (event: Event): void => { event.stopPropagation(); - const { allowEmpty, color } = this; + const { allowEmpty, isClearable = allowEmpty, color } = this; const input = event.target as HTMLCalciteColorPickerHexInputElement; const hex = input.value; - if (allowEmpty && !hex) { + if (isClearable && !hex) { this.internalColorSet(null); return; } @@ -439,6 +450,8 @@ export class ColorPicker }; private handleChannelInput = (event: CustomEvent): void => { + const { allowEmpty, isClearable = allowEmpty } = this; + const input = event.currentTarget as HTMLCalciteInputNumberElement; const channelIndex = Number(input.getAttribute("data-channel-index")); const isAlphaChannel = channelIndex === 3; @@ -451,7 +464,7 @@ export class ColorPicker let inputValue: string; - if (this.allowEmpty && !input.value) { + if (isClearable && !input.value) { inputValue = ""; } else { const value = Number(input.value); @@ -504,11 +517,13 @@ export class ColorPicker } private handleChannelChange = (event: CustomEvent): void => { + const { allowEmpty, isClearable = allowEmpty } = this; + const input = event.currentTarget as HTMLCalciteInputNumberElement; const channelIndex = Number(input.getAttribute("data-channel-index")); const channels = [...this.channels] as this["channels"]; - const shouldClearChannels = this.allowEmpty && !input.value; + const shouldClearChannels = isClearable && !input.value; if (shouldClearChannels) { this.channels = [null, null, null, null]; @@ -666,9 +681,9 @@ export class ColorPicker async componentWillLoad(): Promise { setUpLoadableComponent(this); - const { allowEmpty, color, format, value } = this; + const { allowEmpty, isClearable = allowEmpty, color, format, value } = this; - const willSetNoColor = allowEmpty && !value; + const willSetNoColor = isClearable && !value; const parsedMode = parseMode(value); const valueIsCompatible = willSetNoColor || (format === "auto" && parsedMode) || format === parsedMode; @@ -723,6 +738,7 @@ export class ColorPicker render(): VNode { const { allowEmpty, + isClearable = allowEmpty, channelsDisabled, color, colorFieldScopeLeft, @@ -862,7 +878,7 @@ export class ColorPicker {noHex ? null : (
{ - const { allowEmpty, channelMode: activeChannelMode, channels, messages, alphaChannel } = this; + const { + allowEmpty, + isClearable = allowEmpty, + channelMode: activeChannelMode, + channels, + messages, + alphaChannel, + } = this; const selected = channelMode === activeChannelMode; const isRgb = channelMode === "rgb"; const channelAriaLabels = isRgb @@ -990,7 +1013,7 @@ export class ColorPicker if (isAlphaChannel) { channelValue = - allowEmpty && !channelValue ? channelValue : alphaToOpacity(channelValue); + isClearable && !channelValue ? channelValue : alphaToOpacity(channelValue); } /* the channel container is ltr, so we apply the host's direction */ From cdf76b3b402042b24b44fd7ebdc354da7216970b Mon Sep 17 00:00:00 2001 From: eliza Date: Thu, 7 Mar 2024 12:52:47 -0800 Subject: [PATCH 2/2] add clearable to color-picker-hex-input --- .../calcite-components/src/components.d.ts | 10 ++++++ .../color-picker-hex-input.tsx | 32 +++++++++++++------ .../components/color-picker/color-picker.tsx | 2 +- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/packages/calcite-components/src/components.d.ts b/packages/calcite-components/src/components.d.ts index bd60692b48c..23679eac8e4 100644 --- a/packages/calcite-components/src/components.d.ts +++ b/packages/calcite-components/src/components.d.ts @@ -1066,12 +1066,17 @@ export namespace Components { interface CalciteColorPickerHexInput { /** * When `true`, an empty color (`null`) will be allowed as a `value`. When `false`, a color value is enforced, and clearing the input or blurring will restore the last valid `value`. + * @deprecated Use `clearable` instead. */ "allowEmpty": boolean; /** * When `true`, the component will allow updates to the color's alpha value. */ "alphaChannel": boolean; + /** + * When `true`, a clear button is displayed when the component has a value. + */ + "clearable": boolean; /** * Specifies accessible label for the input field. * @deprecated use `messages` instead @@ -8470,12 +8475,17 @@ declare namespace LocalJSX { interface CalciteColorPickerHexInput { /** * When `true`, an empty color (`null`) will be allowed as a `value`. When `false`, a color value is enforced, and clearing the input or blurring will restore the last valid `value`. + * @deprecated Use `clearable` instead. */ "allowEmpty"?: boolean; /** * When `true`, the component will allow updates to the color's alpha value. */ "alphaChannel"?: boolean; + /** + * When `true`, a clear button is displayed when the component has a value. + */ + "clearable"?: boolean; /** * Specifies accessible label for the input field. * @deprecated use `messages` instead 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 446f4690e94..0c0b1bed577 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 @@ -50,7 +50,7 @@ export class ColorPickerHexInput implements LoadableComponent { //-------------------------------------------------------------------------- connectedCallback(): void { - const { allowEmpty, alphaChannel, value } = this; + const { allowEmpty, isClearable = allowEmpty, alphaChannel, value } = this; if (value) { const normalized = normalizeHex(value, alphaChannel); @@ -62,7 +62,7 @@ export class ColorPickerHexInput implements LoadableComponent { return; } - if (allowEmpty) { + if (isClearable) { this.internalSetValue(null, null, false); } } @@ -85,6 +85,8 @@ export class ColorPickerHexInput implements LoadableComponent { * When `true`, an empty color (`null`) will be allowed as a `value`. * * When `false`, a color value is enforced, and clearing the input or blurring will restore the last valid `value`. + * + * @deprecated Use `clearable` instead. */ @Prop() allowEmpty = false; @@ -93,6 +95,11 @@ export class ColorPickerHexInput implements LoadableComponent { */ @Prop() alphaChannel = false; + /** + * When `true`, a clear button is displayed when the component has a value. + */ + @Prop({ reflect: true }) clearable = false; + /** * Specifies accessible label for the input field. * @@ -142,7 +149,7 @@ export class ColorPickerHexInput implements LoadableComponent { const node = this.hexInputNode; const inputValue = node.value; const hex = `#${inputValue}`; - const { allowEmpty, internalColor } = this; + const { allowEmpty, isClearable = allowEmpty, internalColor } = this; const willClearValue = allowEmpty && !inputValue; const isLonghand = isLonghandHex(hex); @@ -155,7 +162,7 @@ export class ColorPickerHexInput implements LoadableComponent { // manipulating DOM directly since rerender doesn't update input value node.value = - allowEmpty && !internalColor + isClearable && !internalColor ? "" : this.formatHexForInternalInput( rgbToHex( @@ -168,8 +175,8 @@ export class ColorPickerHexInput implements LoadableComponent { private onOpacityInputBlur = (): void => { const node = this.opacityInputNode; const inputValue = node.value; - const { allowEmpty, internalColor } = this; - const willClearValue = allowEmpty && !inputValue; + const { allowEmpty, isClearable = allowEmpty, internalColor } = this; + const willClearValue = isClearable && !inputValue; if (willClearValue) { return; @@ -177,7 +184,7 @@ export class ColorPickerHexInput implements LoadableComponent { // manipulating DOM directly since rerender doesn't update input value node.value = - allowEmpty && !internalColor ? "" : this.formatOpacityForInternalInput(internalColor); + isClearable && !internalColor ? "" : this.formatOpacityForInternalInput(internalColor); }; private onHexInputChange = (): void => { @@ -296,6 +303,10 @@ export class ColorPickerHexInput implements LoadableComponent { private previousNonNullValue: string = this.value; + get isClearable(): boolean { + return this.clearable && this.value.length > 0; + } + //-------------------------------------------------------------------------- // // Lifecycle @@ -303,7 +314,7 @@ export class ColorPickerHexInput implements LoadableComponent { //-------------------------------------------------------------------------- render(): VNode { - const { alphaChannel, hexLabel, internalColor, messages, scale, value } = this; + const { alphaChannel, hexLabel, internalColor, isClearable, messages, scale, value } = this; const hexInputValue = this.formatHexForInternalInput(value); const opacityInputValue = this.formatOpacityForInternalInput(internalColor); const inputScale = scale === "l" ? "m" : "s"; @@ -312,6 +323,7 @@ export class ColorPickerHexInput implements LoadableComponent {