From 3e2bc1ead72d671c2f5a071d5ee801cb03aab3c6 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Fri, 15 Dec 2023 20:01:44 +0530 Subject: [PATCH 01/22] chore(slider): added filled offset variant --- packages/slider/README.md | 22 ++++++++++ packages/slider/src/Slider.ts | 51 +++++++++++++++++++++-- packages/slider/src/spectrum-config.js | 3 +- packages/slider/src/spectrum-slider.css | 12 +++--- packages/slider/stories/slider.stories.ts | 40 ++++++++++++++++++ 5 files changed, 118 insertions(+), 10 deletions(-) diff --git a/packages/slider/README.md b/packages/slider/README.md index 7d41b44687..33ce00874a 100644 --- a/packages/slider/README.md +++ b/packages/slider/README.md @@ -91,6 +91,28 @@ import { Slider } from '@spectrum-web-components/slider'; > ``` +### Filled Offset + +```html + + +``` + ### Tick ```html diff --git a/packages/slider/src/Slider.ts b/packages/slider/src/Slider.ts index bef7ab7b50..54a284ac88 100644 --- a/packages/slider/src/Slider.ts +++ b/packages/slider/src/Slider.ts @@ -38,7 +38,7 @@ import { SliderHandle } from './SliderHandle.js'; import { streamingListener } from '@spectrum-web-components/base/src/streaming-listener.js'; import type { NumberFormatter } from '@internationalized/number'; -export const variants = ['filled', 'ramp', 'range', 'tick']; +export const variants = ['filled', 'offset', 'ramp', 'range', 'tick']; /** * @element sp-slider @@ -91,6 +91,9 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { @property() public type = ''; + @property({ reflect: true }) + public override dir!: 'ltr' | 'rtl'; + @property({ type: String }) public set variant(variant: string) { const oldVariant = this.variant; @@ -181,6 +184,9 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { @query('#track') public track!: HTMLDivElement; + private rangeLength = this.max - this.min; + private centerPoint = this.rangeLength / 2 + this.min; + public override get numberFormat(): NumberFormatter { return this.getNumberFormat(); } @@ -348,6 +354,40 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { `; } + private getOffsetWidth(start: number, end: number): number { + const distance = end > start ? end - start : start - end; + return (distance / this.rangeLength) * 100; + } + + private getOffsetPosition(v: number): number { + const val = ((v - this.min) / this.rangeLength) * 100; + return val; + } + + private renderFillOffset(): TemplateResult { + if (this.variant !== 'offset') { + return html``; + } + return html` +
this.centerPoint) ? 'offset' : '' + }`} + style=${styleMap({ + [this.dir === 'rtl' ? 'right' : 'left']: `${ + this.value * 100 > this.centerPoint + ? this.getOffsetPosition(this.centerPoint) + : this.getOffsetPosition(this.value * 100) + }%`, + width: `${this.getOffsetWidth( + this.value * 100, + this.centerPoint + )}%`, + })} + >
+ `; + } + private renderTrack(): TemplateResult { const segments = this.handleController.trackSegments(); const handleItems = [ @@ -360,6 +400,7 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { id: `track${index + 1}`, html: this.renderTrackSegment(start, end), })), + { id: 'fill', html: this.renderFillOffset() }, ]; return html` @@ -438,8 +479,12 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { const size = end - start; const styles: StyleInfo = { width: `${size * 100}%`, - '--spectrum-slider-track-background-size': `${(1 / size) * 100}%`, - '--spectrum-slider-track-segment-position': `${start * 100}%`, + ...(this.handleController.size > 1 && { + '--spectrum-slider-track-background-size': `${ + (1 / size) * 100 + }%`, + '--spectrum-slider-track-segment-position': `${start * 100}%`, + }), }; return styles; } diff --git a/packages/slider/src/spectrum-config.js b/packages/slider/src/spectrum-config.js index 2f2bba16fd..d7968b7c47 100644 --- a/packages/slider/src/spectrum-config.js +++ b/packages/slider/src/spectrum-config.js @@ -99,7 +99,6 @@ const config = { }, converter.classToId('spectrum-Slider-buffer', 'buffer'), converter.classToId('spectrum-Slider-controls', 'controls'), - converter.classToId('spectrum-Slider-fill', 'fill'), converter.classToId('spectrum-Slider-label', 'label'), converter.classToId( 'spectrum-Slider-labelContainer', @@ -110,6 +109,8 @@ const config = { converter.classToClass('spectrum-Slider-handle', 'handle'), converter.classToClass('spectrum-Slider-input', 'input'), converter.classToClass('spectrum-Slider-tick', 'tick'), + converter.classToClass('spectrum-Slider-fill--right', 'offset'), + converter.classToClass('spectrum-Slider-fill', 'fill'), converter.classToClass( 'spectrum-Slider-tickLabel', 'tickLabel' diff --git a/packages/slider/src/spectrum-slider.css b/packages/slider/src/spectrum-slider.css index a58452911d..e1befe80da 100644 --- a/packages/slider/src/spectrum-slider.css +++ b/packages/slider/src/spectrum-slider.css @@ -207,7 +207,7 @@ governing permissions and limitations under the License. var(--spectrum-slider-control-height) ); } -#fill, +.fill, .track { block-size: var( --mod-slider-track-fill-thickness, @@ -237,7 +237,7 @@ governing permissions and limitations under the License. position: absolute; z-index: 1; } -#fill:before, +.fill:before, .track:before { block-size: 100%; border-end-end-radius: 0; @@ -303,7 +303,7 @@ governing permissions and limitations under the License. var(--spectrum-slider-track-middle-handleoffset) ); } -#fill { +.fill { margin-inline-start: 0; padding-block: 0; padding-inline-end: 0; @@ -315,7 +315,7 @@ governing permissions and limitations under the License. var(--spectrum-slider-handle-gap, var(--spectrum-slider-handle-gap)) ); } -.spectrum-Slider-fill--right { +.offset { padding-block: 0; padding-inline-end: calc( var( @@ -751,7 +751,7 @@ governing permissions and limitations under the License. ) ); } -#fill:before { +.fill:before { background: var( --highcontrast-slider-track-fill-color, var( @@ -939,7 +939,7 @@ governing permissions and limitations under the License. ) ); } -:host([disabled]) #fill:before { +:host([disabled]) .fill:before { background: var( --highcontrast-slider-track-fill-color-disabled, var( diff --git a/packages/slider/stories/slider.stories.ts b/packages/slider/stories/slider.stories.ts index ee594df89a..c5c5df3de5 100644 --- a/packages/slider/stories/slider.stories.ts +++ b/packages/slider/stories/slider.stories.ts @@ -132,6 +132,46 @@ export const Default = (args: StoryArgs = {}): TemplateResult => { `; }; +export const Filled = (args: StoryArgs = {}): TemplateResult => { + return html` +
+ + Slider Label + +
+ `; +}; + +export const FilledOffset = (args: StoryArgs = {}): TemplateResult => { + return html` +
+ + Slider label + +
+ `; +}; + export const autofocus = (args: StoryArgs = {}): TemplateResult => { return html`
From c067b7042bcc9f5dfa4ae3ac06df8da1d1b93921 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Fri, 15 Dec 2023 21:14:35 +0530 Subject: [PATCH 02/22] chore(slider): updated slider to take fill-start as a property --- packages/slider/src/Slider.ts | 37 +++++++++++++++-------- packages/slider/stories/slider.stories.ts | 2 +- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/packages/slider/src/Slider.ts b/packages/slider/src/Slider.ts index 54a284ac88..e51862332c 100644 --- a/packages/slider/src/Slider.ts +++ b/packages/slider/src/Slider.ts @@ -14,6 +14,7 @@ import { CSSResultArray, html, nothing, + PropertyValues, SizedMixin, TemplateResult, } from '@spectrum-web-components/base'; @@ -38,7 +39,7 @@ import { SliderHandle } from './SliderHandle.js'; import { streamingListener } from '@spectrum-web-components/base/src/streaming-listener.js'; import type { NumberFormatter } from '@internationalized/number'; -export const variants = ['filled', 'offset', 'ramp', 'range', 'tick']; +export const variants = ['filled', 'ramp', 'range', 'tick']; /** * @element sp-slider @@ -163,6 +164,9 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { @property({ type: Boolean, reflect: true }) public override disabled = false; + @property({ type: Boolean, reflect: true, attribute: 'fill-start' }) + public fillStart = false; + /** * Applies `quiet` to the underlying `sp-number-field` when `editable === true`. */ @@ -184,9 +188,6 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { @query('#track') public track!: HTMLDivElement; - private rangeLength = this.max - this.min; - private centerPoint = this.rangeLength / 2 + this.min; - public override get numberFormat(): NumberFormatter { return this.getNumberFormat(); } @@ -354,34 +355,37 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { `; } + private rangeLength = this.max - this.min; + private _startingPoint: number | undefined; + private getOffsetWidth(start: number, end: number): number { - const distance = end > start ? end - start : start - end; + const distance = (end > start ? end - start : start - end) * 100; return (distance / this.rangeLength) * 100; } private getOffsetPosition(v: number): number { - const val = ((v - this.min) / this.rangeLength) * 100; + const val = ((v * 100 - this.min) / this.rangeLength) * 100; return val; } private renderFillOffset(): TemplateResult { - if (this.variant !== 'offset') { + if (!this.fillStart) { return html``; } return html`
this.centerPoint) ? 'offset' : '' + !!(this.value > this._startingPoint) ? 'offset' : '' }`} style=${styleMap({ [this.dir === 'rtl' ? 'right' : 'left']: `${ - this.value * 100 > this.centerPoint - ? this.getOffsetPosition(this.centerPoint) - : this.getOffsetPosition(this.value * 100) + this.value > this._startingPoint + ? this.getOffsetPosition(this._startingPoint) + : this.getOffsetPosition(this.value) }%`, width: `${this.getOffsetWidth( - this.value * 100, - this.centerPoint + this._startingPoint, + this.value )}%`, })} >
@@ -500,4 +504,11 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { await this.handleController.handleUpdatesComplete(); return complete; } + + protected override updated(changes: PropertyValues): void { + super.updated(changes); + if (changes.has('value') && changes.has('fillStart')) { + this._startingPoint = Number(this.value) + Number(this.min); + } + } } diff --git a/packages/slider/stories/slider.stories.ts b/packages/slider/stories/slider.stories.ts index c5c5df3de5..977bab089d 100644 --- a/packages/slider/stories/slider.stories.ts +++ b/packages/slider/stories/slider.stories.ts @@ -157,7 +157,7 @@ export const FilledOffset = (args: StoryArgs = {}): TemplateResult => {
Date: Mon, 18 Dec 2023 13:17:26 +0530 Subject: [PATCH 03/22] chore(slider): added check on starting point variable for truthy value --- packages/slider/src/Slider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/slider/src/Slider.ts b/packages/slider/src/Slider.ts index e51862332c..56b181cb2e 100644 --- a/packages/slider/src/Slider.ts +++ b/packages/slider/src/Slider.ts @@ -369,7 +369,7 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { } private renderFillOffset(): TemplateResult { - if (!this.fillStart) { + if (!this.fillStart || !this._startingPoint) { return html``; } return html` From 2e74cbb6229026bbc77e484b056bc626f9be6957 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Mon, 18 Dec 2023 13:35:13 +0530 Subject: [PATCH 04/22] chore(slider): updated golden image cache --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8c2163f27c..a703676b1b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ executors: parameters: current_golden_images_hash: type: string - default: 0214646d25bd039099827dde1d6b00663e084836 + default: 0023dec6f648b4d33bcab051f91784d059fff858 wireit_cache_name: type: string default: wireit From cc80656fa427b6f4c5709165eaf400f1047fdd12 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Mon, 18 Dec 2023 14:28:52 +0530 Subject: [PATCH 05/22] chore(slider): updated tests --- packages/slider/test/slider.test.ts | 47 +++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/packages/slider/test/slider.test.ts b/packages/slider/test/slider.test.ts index ed61064976..3580b4d431 100644 --- a/packages/slider/test/slider.test.ts +++ b/packages/slider/test/slider.test.ts @@ -844,6 +844,53 @@ describe('Slider', () => { expect(el.variant).to.equal('tick'); expect(el.getAttribute('variant')).to.equal('tick'); }); + it('renders div[class="fill"] when fill-start', async () => { + const el = await fixture( + html` + + ` + ); + + await elementUpdated(el); + await nextFrame(); + await nextFrame(); + expect(el.values).to.deep.equal({ value: 10 }); + + const handle = el.shadowRoot.querySelector('.handle') as HTMLDivElement; + const handleBoundingRect = handle.getBoundingClientRect(); + const position: [number, number] = [ + handleBoundingRect.x + handleBoundingRect.width / 2, + handleBoundingRect.y + handleBoundingRect.height / 2, + ]; + await sendMouse({ + steps: [ + { + type: 'move', + position, + }, + { + type: 'down', + }, + ], + }); + + await elementUpdated(el); + await sendMouse({ + steps: [ + { + type: 'move', + position: [ + 200, + handleBoundingRect.y + handleBoundingRect.height + 100, + ], + }, + ], + }); + await nextFrame(); + + expect(el.value).to.equal(24); + expect(el.shadowRoot.querySelector('.fill') as HTMLDivElement).to.exist; + }); it('has a `focusElement`', async () => { const el = await fixture( html` From 752e8efa9a372719cf32c985ca89c3c0e03b4274 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Tue, 2 Jan 2024 13:47:50 +0530 Subject: [PATCH 06/22] chore(slider): updated golden image cache --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d0719c443e..aac58f8368 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ executors: parameters: current_golden_images_hash: type: string - default: c5848624f4b2ed25d56ab4e378d829f6e8ce3805 + default: 81f363750d1ae9b2749b383b412049f8f582a0e9 wireit_cache_name: type: string default: wireit From 0558aad485a0c452a8cf9d8b8cfb6784f2dd7e35 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Sat, 6 Jan 2024 12:30:30 +0530 Subject: [PATCH 07/22] chore(slider): slider with fill center and fill start value --- packages/slider/src/Slider.ts | 52 +++++++++++++++++------ packages/slider/stories/slider.stories.ts | 25 ++++++++++- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/packages/slider/src/Slider.ts b/packages/slider/src/Slider.ts index 56b181cb2e..5aa1d337b6 100644 --- a/packages/slider/src/Slider.ts +++ b/packages/slider/src/Slider.ts @@ -167,6 +167,8 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { @property({ type: Boolean, reflect: true, attribute: 'fill-start' }) public fillStart = false; + @property({ type: Number }) + public fillStartPoint: number | undefined; /** * Applies `quiet` to the underlying `sp-number-field` when `editable === true`. */ @@ -355,37 +357,54 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { `; } - private rangeLength = this.max - this.min; - private _startingPoint: number | undefined; + private _cachedValue: number | undefined; - private getOffsetWidth(start: number, end: number): number { - const distance = (end > start ? end - start : start - end) * 100; - return (distance / this.rangeLength) * 100; + /** + * @description calculates the fill width + * @param fillStartValue + * @param currentValue + * @param cachedValue + * @returns + */ + private getOffsetWidth( + fillStartValue: number, + currentValue: number, + cachedValue: number + ): number { + const distance = + fillStartValue === cachedValue + ? Math.abs(currentValue - fillStartValue) + : Math.abs( + Math.min(currentValue, cachedValue) - fillStartValue + ); + + return (distance / (this.max - this.min)) * 100; } private getOffsetPosition(v: number): number { - const val = ((v * 100 - this.min) / this.rangeLength) * 100; + const val = ((v - this.min) / (this.max - this.min)) * 100; return val; } private renderFillOffset(): TemplateResult { - if (!this.fillStart || !this._startingPoint) { + if (!this.fillStart || !this.fillStartPoint || !this._cachedValue) { return html``; } return html`
this._startingPoint) ? 'offset' : '' + !!(this.value > this.fillStartPoint) ? 'offset' : '' }`} style=${styleMap({ [this.dir === 'rtl' ? 'right' : 'left']: `${ - this.value > this._startingPoint - ? this.getOffsetPosition(this._startingPoint) + this.value > this.fillStartPoint + ? this.getOffsetPosition(this.fillStartPoint) : this.getOffsetPosition(this.value) }%`, width: `${this.getOffsetWidth( - this._startingPoint, - this.value + this.fillStartPoint, + this.value, + this._cachedValue )}%`, })} >
@@ -508,7 +527,14 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { protected override updated(changes: PropertyValues): void { super.updated(changes); if (changes.has('value') && changes.has('fillStart')) { - this._startingPoint = Number(this.value) + Number(this.min); + this._cachedValue = Number(this.value); + if (typeof this.fillStart === 'number') { + this.fillStartPoint = this.fillStart; + } else { + this.fillStartPoint = + (Number(this.max) - Number(this.min)) / 2 + + Number(this.min); + } } } } diff --git a/packages/slider/stories/slider.stories.ts b/packages/slider/stories/slider.stories.ts index 977bab089d..87da5c6ae5 100644 --- a/packages/slider/stories/slider.stories.ts +++ b/packages/slider/stories/slider.stories.ts @@ -152,7 +152,7 @@ export const Filled = (args: StoryArgs = {}): TemplateResult => { `; }; -export const FilledOffset = (args: StoryArgs = {}): TemplateResult => { +export const withOnlyFillStart = (args: StoryArgs = {}): TemplateResult => { return html`
{ `; }; +export const withFillStartValue = (args: StoryArgs = {}): TemplateResult => { + return html` +
+ + Slider label + +
+ `; +}; + +withFillStartValue.args = { + fillStart: 0.3, +}; + export const autofocus = (args: StoryArgs = {}): TemplateResult => { return html`
From b8192f030cfc955f1e3a8082e8139e71be6b9c03 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Sat, 6 Jan 2024 19:30:38 +0530 Subject: [PATCH 08/22] chore(slider): updated README --- packages/slider/README.md | 63 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/packages/slider/README.md b/packages/slider/README.md index 33ce00874a..d194af2be3 100644 --- a/packages/slider/README.md +++ b/packages/slider/README.md @@ -83,21 +83,32 @@ import { Slider } from '@spectrum-web-components/slider'; ### Filled ```html - + ``` -### Filled Offset +### Filled Offset with only fill-start ```html ``` +### Filled Offset with fill-start value + +```html-live + + + +``` + + + ### Tick ```html From 7a4521d082d5e8bf52b1e591aa1f63c5f020439b Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Sat, 6 Jan 2024 19:45:39 +0530 Subject: [PATCH 09/22] chore(slider): updated golden image cache --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d66268d884..771422cd2b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ executors: parameters: current_golden_images_hash: type: string - default: 399010224101760a8f5247862ef7f3eb900b2382 + default: b8192f030cfc955f1e3a8082e8139e71be6b9c03 wireit_cache_name: type: string default: wireit From 5a2992d312bc53a927341e6b886a7470e891e2c9 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Wed, 10 Jan 2024 15:12:38 +0530 Subject: [PATCH 10/22] chore(slider): updated golden image cache --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5200e93142..476052a022 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ executors: parameters: current_golden_images_hash: type: string - default: e8720ac5d0ee0d076e61309294041334afe2c160 + default: 4efe2e33f04f30cd4965e4d8e252edc0f3b6cf76 wireit_cache_name: type: string default: wireit From 524493dc379150ad5fecace2c5de5b4939d8123f Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Thu, 11 Jan 2024 15:27:25 +0530 Subject: [PATCH 11/22] chore(slider): code optimizations --- packages/slider/README.md | 27 ++--------- packages/slider/src/Slider.ts | 59 +++++++++++++---------- packages/slider/stories/slider.stories.ts | 5 +- packages/slider/test/slider.test.ts | 2 + 4 files changed, 39 insertions(+), 54 deletions(-) diff --git a/packages/slider/README.md b/packages/slider/README.md index d194af2be3..03942f9b84 100644 --- a/packages/slider/README.md +++ b/packages/slider/README.md @@ -126,7 +126,7 @@ import { Slider } from '@spectrum-web-components/slider'; ### Filled Offset with fill-start value -```html-live +```html - ``` - - ### Tick ```html diff --git a/packages/slider/src/Slider.ts b/packages/slider/src/Slider.ts index 5aa1d337b6..5ad688ac42 100644 --- a/packages/slider/src/Slider.ts +++ b/packages/slider/src/Slider.ts @@ -164,11 +164,9 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { @property({ type: Boolean, reflect: true }) public override disabled = false; - @property({ type: Boolean, reflect: true, attribute: 'fill-start' }) - public fillStart = false; + @property({ type: Number, reflect: true, attribute: 'fill-start' }) + public fillStart?: number | boolean; - @property({ type: Number }) - public fillStartPoint: number | undefined; /** * Applies `quiet` to the underlying `sp-number-field` when `editable === true`. */ @@ -386,27 +384,35 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { return val; } + private fillStyles(cachedValue: number): StyleInfo { + const position = this.dir === 'rtl' ? 'right' : 'left'; + const offsetPosition = + this.value > this.fillStartPoint + ? this.getOffsetPosition(this.fillStartPoint) + : this.getOffsetPosition(this.value); + const offsetWidth = this.getOffsetWidth( + this.fillStartPoint, + this.value, + cachedValue + ); + const styles: StyleInfo = { + [position]: `${offsetPosition}%`, + width: `${offsetWidth}%`, + }; + return styles; + } + private renderFillOffset(): TemplateResult { - if (!this.fillStart || !this.fillStartPoint || !this._cachedValue) { + if (!this._cachedValue) { return html``; } return html`
this.fillStartPoint) ? 'offset' : '' - }`} - style=${styleMap({ - [this.dir === 'rtl' ? 'right' : 'left']: `${ - this.value > this.fillStartPoint - ? this.getOffsetPosition(this.fillStartPoint) - : this.getOffsetPosition(this.value) - }%`, - width: `${this.getOffsetWidth( - this.fillStartPoint, - this.value, - this._cachedValue - )}%`, + class=${classMap({ + fill: true, + offset: this.value > this.fillStartPoint, })} + style=${styleMap(this.fillStyles(this._cachedValue))} >
`; } @@ -524,17 +530,18 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { return complete; } + private get fillStartPoint(): number { + if (this.fillStart) { + return Number(this.fillStart); + } else { + return (Number(this.max) - Number(this.min)) / 2 + Number(this.min); + } + } + protected override updated(changes: PropertyValues): void { super.updated(changes); if (changes.has('value') && changes.has('fillStart')) { this._cachedValue = Number(this.value); - if (typeof this.fillStart === 'number') { - this.fillStartPoint = this.fillStart; - } else { - this.fillStartPoint = - (Number(this.max) - Number(this.min)) / 2 + - Number(this.min); - } } } } diff --git a/packages/slider/stories/slider.stories.ts b/packages/slider/stories/slider.stories.ts index 87da5c6ae5..98d54a2ef0 100644 --- a/packages/slider/stories/slider.stories.ts +++ b/packages/slider/stories/slider.stories.ts @@ -180,6 +180,7 @@ export const withFillStartValue = (args: StoryArgs = {}): TemplateResult => { min="0" value=".7" step="0.1" + fill-start="0.3" @input=${handleEvent(args)} @change=${handleEvent(args)} .formatOptions=${{ style: 'percent' }} @@ -191,10 +192,6 @@ export const withFillStartValue = (args: StoryArgs = {}): TemplateResult => { `; }; -withFillStartValue.args = { - fillStart: 0.3, -}; - export const autofocus = (args: StoryArgs = {}): TemplateResult => { return html`
diff --git a/packages/slider/test/slider.test.ts b/packages/slider/test/slider.test.ts index 3580b4d431..b49bec6c0f 100644 --- a/packages/slider/test/slider.test.ts +++ b/packages/slider/test/slider.test.ts @@ -854,6 +854,8 @@ describe('Slider', () => { await elementUpdated(el); await nextFrame(); await nextFrame(); + expect(el.shadowRoot.querySelector('.fill') as HTMLDivElement).to.not + .exist; expect(el.values).to.deep.equal({ value: 10 }); const handle = el.shadowRoot.querySelector('.handle') as HTMLDivElement; From e3176f20b93a5d8ec16ef7513614baa319175fc3 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Thu, 11 Jan 2024 16:10:38 +0530 Subject: [PATCH 12/22] chore(slider): updated fill on first load in willUpdate --- packages/slider/src/Slider.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/slider/src/Slider.ts b/packages/slider/src/Slider.ts index 5ad688ac42..b40da93da0 100644 --- a/packages/slider/src/Slider.ts +++ b/packages/slider/src/Slider.ts @@ -537,10 +537,8 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { return (Number(this.max) - Number(this.min)) / 2 + Number(this.min); } } - - protected override updated(changes: PropertyValues): void { - super.updated(changes); - if (changes.has('value') && changes.has('fillStart')) { + protected override willUpdate(changed: PropertyValues): void { + if (changed.has('value') && changed.has('fillStart')) { this._cachedValue = Number(this.value); } } From 09583f878c14d86aadde356e59b16e773d3a15b6 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Thu, 11 Jan 2024 17:24:08 +0530 Subject: [PATCH 13/22] chore(slider): updated tests --- packages/slider/test/slider.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/slider/test/slider.test.ts b/packages/slider/test/slider.test.ts index b49bec6c0f..3580b4d431 100644 --- a/packages/slider/test/slider.test.ts +++ b/packages/slider/test/slider.test.ts @@ -854,8 +854,6 @@ describe('Slider', () => { await elementUpdated(el); await nextFrame(); await nextFrame(); - expect(el.shadowRoot.querySelector('.fill') as HTMLDivElement).to.not - .exist; expect(el.values).to.deep.equal({ value: 10 }); const handle = el.shadowRoot.querySelector('.handle') as HTMLDivElement; From e279f8a9a07d569bc2fc7375aaa98d510c90e2f0 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Fri, 12 Jan 2024 15:59:56 +0530 Subject: [PATCH 14/22] chore(slider): updated filled offset slider storybook and docs --- packages/slider/README.md | 11 +++++- packages/slider/src/Slider.ts | 47 ++++++++++++++++------- packages/slider/stories/slider.stories.ts | 17 +++++++- 3 files changed, 59 insertions(+), 16 deletions(-) diff --git a/packages/slider/README.md b/packages/slider/README.md index 03942f9b84..23381353e7 100644 --- a/packages/slider/README.md +++ b/packages/slider/README.md @@ -129,7 +129,16 @@ import { Slider } from '@spectrum-web-components/slider'; ```html + cachedValue) { + offsetValue = + this.value > fillStartValue + ? fillStartValue + : Math.max(currentValue, cachedValue); + } else { + offsetValue = + this.value > fillStartValue ? fillStartValue : this.value; + } + return ((offsetValue - this.min) / (this.max - this.min)) * 100; } private fillStyles(cachedValue: number): StyleInfo { const position = this.dir === 'rtl' ? 'right' : 'left'; - const offsetPosition = - this.value > this.fillStartPoint - ? this.getOffsetPosition(this.fillStartPoint) - : this.getOffsetPosition(this.value); + const offsetPosition = this.getOffsetPosition( + this.fillStartPoint, + this.value, + cachedValue + ); const offsetWidth = this.getOffsetWidth( this.fillStartPoint, this.value, diff --git a/packages/slider/stories/slider.stories.ts b/packages/slider/stories/slider.stories.ts index 98d54a2ef0..7bd3f1634d 100644 --- a/packages/slider/stories/slider.stories.ts +++ b/packages/slider/stories/slider.stories.ts @@ -186,7 +186,22 @@ export const withFillStartValue = (args: StoryArgs = {}): TemplateResult => { .formatOptions=${{ style: 'percent' }} ...=${spreadProps(args)} > - Slider label + Value Greater than Fill Start + +
+
+ + Value Less than Fill Start
`; From 986bd3c03f6752c26080f5e5fa1ff25a860e7d0c Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Fri, 12 Jan 2024 16:37:49 +0530 Subject: [PATCH 15/22] chore(slider): updated golden image cache --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 476052a022..033fb00263 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ executors: parameters: current_golden_images_hash: type: string - default: 4efe2e33f04f30cd4965e4d8e252edc0f3b6cf76 + default: e279f8a9a07d569bc2fc7375aaa98d510c90e2f0 wireit_cache_name: type: string default: wireit From 3b3227517a844b16fa0f09c1f84655abf56eab14 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Tue, 16 Jan 2024 22:41:00 +0530 Subject: [PATCH 16/22] chore(slider): updated logic for fill start with value --- packages/slider/src/Slider.ts | 39 +++++++---------------- packages/slider/stories/slider.stories.ts | 4 +-- 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/packages/slider/src/Slider.ts b/packages/slider/src/Slider.ts index 511c60275a..ef187e0837 100644 --- a/packages/slider/src/Slider.ts +++ b/packages/slider/src/Slider.ts @@ -372,43 +372,26 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { let distance: number; if (fillStartValue === cachedValue) { distance = Math.abs(currentValue - fillStartValue); - } else if (fillStartValue < cachedValue) { - distance = Math.abs( - Math.min(currentValue, cachedValue) - fillStartValue - ); } else { - distance = Math.abs( - Math.max(currentValue, cachedValue) - fillStartValue - ); + distance = Math.abs(currentValue - fillStartValue); } return (distance / (this.max - this.min)) * 100; } - private getOffsetPosition( - fillStartValue: number, - currentValue: number, - cachedValue: number - ): number { - let offsetValue: number; - if (fillStartValue > cachedValue) { - offsetValue = - this.value > fillStartValue - ? fillStartValue - : Math.max(currentValue, cachedValue); - } else { - offsetValue = - this.value > fillStartValue ? fillStartValue : this.value; - } - return ((offsetValue - this.min) / (this.max - this.min)) * 100; + /** + * @description calculates the fill width starting point to fill width + * @param value + */ + private getOffsetPosition(value: number): number { + return ((value - this.min) / (this.max - this.min)) * 100; } private fillStyles(cachedValue: number): StyleInfo { const position = this.dir === 'rtl' ? 'right' : 'left'; - const offsetPosition = this.getOffsetPosition( - this.fillStartPoint, - this.value, - cachedValue - ); + const offsetPosition = + this.value > this.fillStartPoint + ? this.getOffsetPosition(this.fillStartPoint) + : this.getOffsetPosition(this.value); const offsetWidth = this.getOffsetWidth( this.fillStartPoint, this.value, diff --git a/packages/slider/stories/slider.stories.ts b/packages/slider/stories/slider.stories.ts index 7bd3f1634d..3e07ac2279 100644 --- a/packages/slider/stories/slider.stories.ts +++ b/packages/slider/stories/slider.stories.ts @@ -152,7 +152,7 @@ export const Filled = (args: StoryArgs = {}): TemplateResult => { `; }; -export const withOnlyFillStart = (args: StoryArgs = {}): TemplateResult => { +export const FillStart = (args: StoryArgs = {}): TemplateResult => { return html`
{ `; }; -export const withFillStartValue = (args: StoryArgs = {}): TemplateResult => { +export const FillStartWithValue = (args: StoryArgs = {}): TemplateResult => { return html`
Date: Tue, 16 Jan 2024 22:55:52 +0530 Subject: [PATCH 17/22] chore(slider): updated golden image cache --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 033fb00263..6744d541d1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ executors: parameters: current_golden_images_hash: type: string - default: e279f8a9a07d569bc2fc7375aaa98d510c90e2f0 + default: 3b3227517a844b16fa0f09c1f84655abf56eab14 wireit_cache_name: type: string default: wireit From 35b181666ea5ca39f33703454f7c910e0d40cc1c Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Wed, 17 Jan 2024 11:35:27 +0530 Subject: [PATCH 18/22] chore(slider): code clean up --- packages/slider/src/Slider.ts | 17 +++++------------ packages/slider/stories/slider.stories.ts | 2 +- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/packages/slider/src/Slider.ts b/packages/slider/src/Slider.ts index ef187e0837..a91143745d 100644 --- a/packages/slider/src/Slider.ts +++ b/packages/slider/src/Slider.ts @@ -366,15 +366,9 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { */ private getOffsetWidth( fillStartValue: number, - currentValue: number, - cachedValue: number + currentValue: number ): number { - let distance: number; - if (fillStartValue === cachedValue) { - distance = Math.abs(currentValue - fillStartValue); - } else { - distance = Math.abs(currentValue - fillStartValue); - } + const distance = Math.abs(currentValue - fillStartValue); return (distance / (this.max - this.min)) * 100; } @@ -386,7 +380,7 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { return ((value - this.min) / (this.max - this.min)) * 100; } - private fillStyles(cachedValue: number): StyleInfo { + private fillStyles(): StyleInfo { const position = this.dir === 'rtl' ? 'right' : 'left'; const offsetPosition = this.value > this.fillStartPoint @@ -394,8 +388,7 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { : this.getOffsetPosition(this.value); const offsetWidth = this.getOffsetWidth( this.fillStartPoint, - this.value, - cachedValue + this.value ); const styles: StyleInfo = { [position]: `${offsetPosition}%`, @@ -414,7 +407,7 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { fill: true, offset: this.value > this.fillStartPoint, })} - style=${styleMap(this.fillStyles(this._cachedValue))} + style=${styleMap(this.fillStyles())} >
`; } diff --git a/packages/slider/stories/slider.stories.ts b/packages/slider/stories/slider.stories.ts index 3e07ac2279..65f86ae8b1 100644 --- a/packages/slider/stories/slider.stories.ts +++ b/packages/slider/stories/slider.stories.ts @@ -139,7 +139,7 @@ export const Filled = (args: StoryArgs = {}): TemplateResult => { max="1" variant="filled" min="0" - value=".5" + value=".7" step="0.01" @input=${handleEvent(args)} @change=${handleEvent(args)} From 9af3468ab729acdd5cbc14a330226adcf6ec8a9e Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Wed, 17 Jan 2024 13:44:21 +0530 Subject: [PATCH 19/22] chore(slider): updated tests --- packages/slider/src/Slider.ts | 32 +++++++++++----------- packages/slider/test/slider.test.ts | 42 ++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/packages/slider/src/Slider.ts b/packages/slider/src/Slider.ts index a91143745d..1e5de918d3 100644 --- a/packages/slider/src/Slider.ts +++ b/packages/slider/src/Slider.ts @@ -356,6 +356,7 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { } private _cachedValue: number | undefined; + private centerPoint: number | undefined; /** * @description calculates the fill width @@ -380,16 +381,13 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { return ((value - this.min) / (this.max - this.min)) * 100; } - private fillStyles(): StyleInfo { + private fillStyles(centerPoint: number): StyleInfo { const position = this.dir === 'rtl' ? 'right' : 'left'; const offsetPosition = - this.value > this.fillStartPoint - ? this.getOffsetPosition(this.fillStartPoint) + this.value > centerPoint + ? this.getOffsetPosition(centerPoint) : this.getOffsetPosition(this.value); - const offsetWidth = this.getOffsetWidth( - this.fillStartPoint, - this.value - ); + const offsetWidth = this.getOffsetWidth(centerPoint, this.value); const styles: StyleInfo = { [position]: `${offsetPosition}%`, width: `${offsetWidth}%`, @@ -398,16 +396,16 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { } private renderFillOffset(): TemplateResult { - if (!this._cachedValue) { + if (!this._cachedValue || !this.centerPoint) { return html``; } return html`
this.fillStartPoint, + offset: this.value > this.centerPoint, })} - style=${styleMap(this.fillStyles())} + style=${styleMap(this.fillStyles(this.centerPoint))} >
`; } @@ -525,16 +523,16 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), { return complete; } - private get fillStartPoint(): number { - if (this.fillStart) { - return Number(this.fillStart); - } else { - return (Number(this.max) - Number(this.min)) / 2 + Number(this.min); - } - } protected override willUpdate(changed: PropertyValues): void { if (changed.has('value') && changed.has('fillStart')) { this._cachedValue = Number(this.value); + if (this.fillStart) { + this.centerPoint = Number(this.fillStart); + } else { + this.centerPoint = + (Number(this.max) - Number(this.min)) / 2 + + Number(this.min); + } } } } diff --git a/packages/slider/test/slider.test.ts b/packages/slider/test/slider.test.ts index 3580b4d431..68139c2248 100644 --- a/packages/slider/test/slider.test.ts +++ b/packages/slider/test/slider.test.ts @@ -844,16 +844,53 @@ describe('Slider', () => { expect(el.variant).to.equal('tick'); expect(el.getAttribute('variant')).to.equal('tick'); }); - it('renders div[class="fill"] when fill-start', async () => { + it('renders fill from the centerPoint of the track when fill-start has no value', async () => { const el = await fixture( html` - + + ` + ); + + await elementUpdated(el); + await nextFrame(); + await nextFrame(); + const fillElement = el.shadowRoot.querySelector( + '.fill' + ) as HTMLDivElement; + + expect(fillElement).to.exist; + expect(fillElement.style.left).to.equal('50%'); + expect(fillElement.style.width).to.equal('0%'); + expect(el.values).to.deep.equal({ value: 10 }); + }); + it('renders fill from fill-start point', async () => { + const el = await fixture( + html` + ` ); await elementUpdated(el); await nextFrame(); await nextFrame(); + const fillElement = el.shadowRoot.querySelector( + '.fill' + ) as HTMLDivElement; + + expect(fillElement).to.exist; + expect(fillElement.style.left).to.equal('10%'); + expect(fillElement.style.width).to.equal('5%'); expect(el.values).to.deep.equal({ value: 10 }); const handle = el.shadowRoot.querySelector('.handle') as HTMLDivElement; @@ -889,7 +926,6 @@ describe('Slider', () => { await nextFrame(); expect(el.value).to.equal(24); - expect(el.shadowRoot.querySelector('.fill') as HTMLDivElement).to.exist; }); it('has a `focusElement`', async () => { const el = await fixture( From 095fd7d6db0504a2b89ad4ef3286d4b64e5129b9 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Wed, 17 Jan 2024 13:55:17 +0530 Subject: [PATCH 20/22] chore(slider): updated golden image cache --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6744d541d1..a32f117575 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ executors: parameters: current_golden_images_hash: type: string - default: 3b3227517a844b16fa0f09c1f84655abf56eab14 + default: 9af3468ab729acdd5cbc14a330226adcf6ec8a9e wireit_cache_name: type: string default: wireit From c9b480126af6dccfec997ef6f684fd019db6b7b0 Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Wed, 17 Jan 2024 18:49:31 +0530 Subject: [PATCH 21/22] chore(slider): updated story --- packages/slider/stories/slider.stories.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/slider/stories/slider.stories.ts b/packages/slider/stories/slider.stories.ts index 65f86ae8b1..1d04cfe788 100644 --- a/packages/slider/stories/slider.stories.ts +++ b/packages/slider/stories/slider.stories.ts @@ -159,7 +159,7 @@ export const FillStart = (args: StoryArgs = {}): TemplateResult => { max="1" fill-start min="0" - value=".5" + value=".7" step="0.01" @input=${handleEvent(args)} @change=${handleEvent(args)} From 1b802da3f10304d3c79c2c6724bca855955c3a7f Mon Sep 17 00:00:00 2001 From: Rajdeep Chandra Date: Wed, 17 Jan 2024 19:11:10 +0530 Subject: [PATCH 22/22] chore(slider): updated golden image cache --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a32f117575..125054fa0c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ executors: parameters: current_golden_images_hash: type: string - default: 9af3468ab729acdd5cbc14a330226adcf6ec8a9e + default: c9b480126af6dccfec997ef6f684fd019db6b7b0 wireit_cache_name: type: string default: wireit