-
Notifications
You must be signed in to change notification settings - Fork 467
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* refactor(kit): `Range` use `Slider` inside * fix(kit): `Slider` improve directive `readonly` * chore(demo): `Range` extend example with ticks labels * chore(demo): `Range` extend example with ticks labels * fix(kit): `Range` prevent cursor's blinking during dragging of the thumb * chore(kit): `Range` review comments * chore(kit): `Slider` replace Array by Set * chore(kit): `Range` add not-chromium Edge support (16-18) Co-authored-by: nsbarsukov <nsbarsukov@users.noreply.github.com>
- Loading branch information
1 parent
9cdbde9
commit 245c8d5
Showing
36 changed files
with
1,238 additions
and
185 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
239 changes: 239 additions & 0 deletions
239
projects/demo-integrations/cypress/tests/kit/range/range.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
import {RANGE_PAGE_URL} from '../../../support/shared.entities'; | ||
|
||
const initializeBaseAliases = (exampleId: string) => { | ||
cy.get(`${exampleId} tui-range`).should('be.visible').as('range'); | ||
cy.get(`${exampleId} tui-range input[type=range]:first-child`) | ||
.should('be.visible') | ||
.as('leftSlider'); | ||
cy.get(`${exampleId} tui-range input[type=range]:last-child`) | ||
.should('be.visible') | ||
.as('rightSlider'); | ||
}; | ||
|
||
describe('Range', () => { | ||
beforeEach(() => { | ||
cy.viewport('macbook-13'); | ||
}); | ||
|
||
describe('examples page', () => { | ||
beforeEach(() => { | ||
cy.goToDemoPage(RANGE_PAGE_URL); | ||
cy.hideHeader(); | ||
cy.hideNavigation(); | ||
}); | ||
|
||
describe('change selected range on click', () => { | ||
const EXAMPLE_ID = '#base'; | ||
|
||
beforeEach(() => { | ||
initializeBaseAliases(EXAMPLE_ID); | ||
|
||
cy.get(EXAMPLE_ID).scrollIntoView(); | ||
}); | ||
|
||
it('click on the beginning of the track changes only nearest (left) slider', () => { | ||
cy.get('@range').click('left'); | ||
cy.get('@leftSlider').should('have.value', 0); | ||
cy.get('@rightSlider').should('have.value', 6); | ||
|
||
cy.get(EXAMPLE_ID).matchImageSnapshot('01-range-click-checks-0-6'); | ||
}); | ||
|
||
it('click on the end of the track changes only nearest (right) slider', () => { | ||
cy.get('@range').click('right'); | ||
cy.get('@leftSlider').should('have.value', 4); | ||
cy.get('@rightSlider').should('have.value', 10); | ||
|
||
cy.get(EXAMPLE_ID).matchImageSnapshot('02-range-click-checks-4-10'); | ||
}); | ||
|
||
it('click between two thumbs triggers only nearest thumb', () => { | ||
cy.get('@range').click(100, 0); | ||
cy.get('@range').click('right'); | ||
|
||
cy.get('@leftSlider').should('have.value', 1); | ||
cy.get('@rightSlider').should('have.value', 10); | ||
cy.get(EXAMPLE_ID).matchImageSnapshot('03-range-click-checks-1-10'); | ||
|
||
cy.get('@range').click('center'); | ||
cy.get('@leftSlider').should('have.value', 5); | ||
cy.get('@rightSlider').should('have.value', 10); | ||
cy.get(EXAMPLE_ID).matchImageSnapshot('03-range-click-checks-5-10'); | ||
}); | ||
}); | ||
|
||
describe('keyboard interactions', () => { | ||
describe('basic range (from 0 to 1000 with 250 steps). Initial value [0, 250]', () => { | ||
const EXAMPLE_ID = '#segments'; | ||
|
||
beforeEach(() => { | ||
initializeBaseAliases(EXAMPLE_ID); | ||
|
||
cy.get(EXAMPLE_ID).scrollIntoView(); | ||
}); | ||
|
||
const checkValuesAfterPressing = ( | ||
key: string, | ||
[leftSliderValue, rightSliderValue]: [number, number], | ||
) => { | ||
cy.get('body').type(`{${key}}`); | ||
cy.get('@leftSlider').should('have.value', leftSliderValue); | ||
cy.get('@rightSlider').should('have.value', rightSliderValue); | ||
cy.get(`${EXAMPLE_ID} output`) | ||
.invoke('text') | ||
.should( | ||
'match', | ||
new RegExp( | ||
`\\s${leftSliderValue},.+${rightSliderValue}\\s`, | ||
'gs', | ||
), | ||
); | ||
}; | ||
|
||
it('pressing of Arrow Right increases by one step (after focus on right slider)', () => { | ||
cy.get('@leftSlider').should('have.value', 0); | ||
cy.get('@rightSlider').should('have.value', 250); | ||
cy.get('@rightSlider').focus(); | ||
|
||
checkValuesAfterPressing('rightarrow', [0, 500]); | ||
checkValuesAfterPressing('rightarrow', [0, 750]); | ||
checkValuesAfterPressing('rightarrow', [0, 1000]); | ||
}); | ||
|
||
it('pressing of Arrow Right increases by one step (after focus on left slider)', () => { | ||
cy.get('@range').click('right'); | ||
cy.get('@leftSlider').should('have.value', 0); | ||
cy.get('@rightSlider').should('have.value', 1000); | ||
cy.get('@leftSlider').focus(); | ||
|
||
checkValuesAfterPressing('rightarrow', [250, 1000]); | ||
checkValuesAfterPressing('rightarrow', [500, 1000]); | ||
checkValuesAfterPressing('rightarrow', [750, 1000]); | ||
checkValuesAfterPressing('rightarrow', [1000, 1000]); | ||
}); | ||
|
||
it('pressing of Arrow Left decreases by one step (after setting right thumb active via click)', () => { | ||
cy.get('@range').click('right'); | ||
cy.get('@leftSlider').should('have.value', 0); | ||
cy.get('@rightSlider').should('have.value', 1000); | ||
|
||
checkValuesAfterPressing('leftarrow', [0, 750]); | ||
checkValuesAfterPressing('leftarrow', [0, 500]); | ||
checkValuesAfterPressing('leftarrow', [0, 250]); | ||
checkValuesAfterPressing('leftarrow', [0, 0]); | ||
}); | ||
|
||
it('cannot set left thumb more than right thumb (by Arrow Right)', () => { | ||
cy.get('@leftSlider').should('have.value', 0); | ||
cy.get('@rightSlider').should('have.value', 250); | ||
cy.get('@leftSlider').focus(); | ||
|
||
checkValuesAfterPressing('rightarrow', [250, 250]); | ||
checkValuesAfterPressing('rightarrow', [250, 250]); | ||
checkValuesAfterPressing('rightarrow', [250, 250]); | ||
}); | ||
|
||
it('cannot set right thumb less than left thumb (by ArrowLeft)', () => { | ||
cy.get('@range').click('right'); | ||
cy.get('@leftSlider').focus(); | ||
|
||
cy.get('body').type('{rightarrow}{rightarrow}'); | ||
cy.get('@leftSlider').should('have.value', 500); | ||
cy.get('@rightSlider').should('have.value', 1000); | ||
|
||
cy.get('@rightSlider').focus(); | ||
cy.get('body').type( | ||
'{leftarrow}{leftarrow}{leftarrow}{leftarrow}{leftarrow}', | ||
); | ||
|
||
cy.get('@leftSlider').should('have.value', 500); | ||
cy.get('@rightSlider').should('have.value', 500); | ||
|
||
cy.get('@rightSlider').focus(); | ||
cy.get('body').type( | ||
'{leftarrow}{leftarrow}{leftarrow}{leftarrow}{leftarrow}', | ||
); | ||
|
||
cy.get('@leftSlider').focus(); | ||
cy.get('body').type( | ||
'{rightarrow}{rightarrow}{rightarrow}{rightarrow}{rightarrow}', | ||
); | ||
|
||
cy.get('@leftSlider').should('have.value', 500); | ||
cy.get('@rightSlider').should('have.value', 500); | ||
}); | ||
}); | ||
|
||
describe('range with keySteps (from 0 to 1M) with 8 steps. Initial value [0, 100_000]', () => { | ||
const EXAMPLE_ID = '#key-steps'; | ||
|
||
beforeEach(() => { | ||
initializeBaseAliases(EXAMPLE_ID); | ||
|
||
cy.get(EXAMPLE_ID).scrollIntoView(); | ||
}); | ||
|
||
const checkValuesAfterPressing = ( | ||
key: string, | ||
[leftSliderValue, rightSliderValue]: [number, number], | ||
) => { | ||
cy.get('body').type(`{${key}}`); | ||
cy.get(`${EXAMPLE_ID} output`) | ||
.invoke('text') | ||
.should( | ||
'match', | ||
new RegExp( | ||
`\\s${leftSliderValue},.+${rightSliderValue}\\s`, | ||
'gs', | ||
), | ||
); | ||
}; | ||
|
||
it('ArrowUp increases value of the focused slider', () => { | ||
cy.get('@rightSlider').focus(); | ||
|
||
checkValuesAfterPressing('uparrow', [0, 300_000]); | ||
checkValuesAfterPressing('uparrow', [0, 500_000]); | ||
checkValuesAfterPressing('uparrow', [0, 750_000]); | ||
checkValuesAfterPressing('uparrow', [0, 1_000_000]); | ||
|
||
cy.get('@leftSlider').focus(); | ||
|
||
checkValuesAfterPressing('uparrow', [5_000, 1_000_000]); | ||
checkValuesAfterPressing('uparrow', [10_000, 1_000_000]); | ||
checkValuesAfterPressing('uparrow', [55_000, 1_000_000]); | ||
checkValuesAfterPressing('uparrow', [100_000, 1_000_000]); | ||
}); | ||
|
||
it('ArrowDown decreases value of the focused slider', () => { | ||
cy.get('@rightSlider').focus(); | ||
|
||
checkValuesAfterPressing('downarrow', [0, 55_000]); | ||
checkValuesAfterPressing('downarrow', [0, 10_000]); | ||
checkValuesAfterPressing('downarrow', [0, 5_000]); | ||
}); | ||
|
||
it('cannot set position of the LEFT slider MORE THAN position of the RIGHT slider (by ArrowUp)', () => { | ||
cy.get('@leftSlider').focus(); | ||
cy.get('body').type('{uparrow}{uparrow}{uparrow}{uparrow}'); | ||
|
||
checkValuesAfterPressing('uparrow', [100_000, 100_000]); | ||
checkValuesAfterPressing('uparrow', [100_000, 100_000]); | ||
checkValuesAfterPressing('uparrow', [100_000, 100_000]); | ||
}); | ||
|
||
it('cannot set position of the RIGHT slider LESS THAN position of the LEFT slider (by ArrowDown)', () => { | ||
cy.get('@leftSlider').focus(); | ||
cy.get('body').type('{uparrow}'); | ||
|
||
cy.get('@rightSlider').focus(); | ||
cy.get('body').type('{downarrow}{downarrow}{downarrow}'); | ||
|
||
checkValuesAfterPressing('downarrow', [5_000, 5_000]); | ||
checkValuesAfterPressing('downarrow', [5_000, 5_000]); | ||
checkValuesAfterPressing('downarrow', [5_000, 5_000]); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
1 change: 1 addition & 0 deletions
1
projects/demo/src/modules/components/range/examples/1/index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
<tui-range | ||
[formControl]="control" | ||
[max]="10" | ||
[quantum]="1" | ||
></tui-range> |
37 changes: 37 additions & 0 deletions
37
projects/demo/src/modules/components/range/examples/2/index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<tui-island class="island"> | ||
<h3 class="tui-island__title">S-size</h3> | ||
|
||
<tui-range | ||
id="s-size-range" | ||
size="s" | ||
class="range" | ||
[max]="100" | ||
[(ngModel)]="smallRangeValue" | ||
></tui-range> | ||
|
||
<p class="tui-island__paragraph"> | ||
Control value: | ||
<output for="s-size-range"> | ||
<code>{{smallRangeValue | json}}</code> | ||
</output> | ||
</p> | ||
</tui-island> | ||
|
||
<tui-island class="island"> | ||
<h3 class="tui-island__title">M-size</h3> | ||
|
||
<tui-range | ||
id="m-size-range" | ||
size="m" | ||
class="range" | ||
[formControl]="bigRangeControl" | ||
[max]="100" | ||
></tui-range> | ||
|
||
<p class="tui-island__paragraph"> | ||
Control value: | ||
<output for="m-size-range"> | ||
<code>{{bigRangeControl.value | json}}</code> | ||
</output> | ||
</p> | ||
</tui-island> |
21 changes: 21 additions & 0 deletions
21
projects/demo/src/modules/components/range/examples/2/index.less
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
@import 'taiga-ui-local'; | ||
|
||
:host { | ||
display: flex; | ||
justify-content: space-between; | ||
flex-wrap: wrap; | ||
row-gap: 1rem; | ||
} | ||
|
||
.island { | ||
box-sizing: border-box; | ||
width: 49%; | ||
|
||
@media @mobile { | ||
width: 100%; | ||
} | ||
} | ||
|
||
.range { | ||
margin: 2rem 0; | ||
} |
17 changes: 17 additions & 0 deletions
17
projects/demo/src/modules/components/range/examples/2/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import {Component} from '@angular/core'; | ||
import {FormControl} from '@angular/forms'; | ||
import {changeDetection} from '@demo/emulate/change-detection'; | ||
import {encapsulation} from '@demo/emulate/encapsulation'; | ||
|
||
@Component({ | ||
selector: 'tui-range-example-2', | ||
templateUrl: './index.html', | ||
styleUrls: ['./index.less'], | ||
changeDetection, | ||
encapsulation, | ||
}) | ||
export class TuiRangeExample2 { | ||
smallRangeValue = [0, 40]; | ||
|
||
readonly bigRangeControl = new FormControl([40, 60]); | ||
} |
31 changes: 31 additions & 0 deletions
31
projects/demo/src/modules/components/range/examples/3/index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<tui-range | ||
id="range-with-segments" | ||
new | ||
size="m" | ||
class="range" | ||
[min]="min" | ||
[max]="max" | ||
[quantum]="quantum" | ||
[segments]="segments" | ||
[(ngModel)]="value" | ||
></tui-range> | ||
|
||
<div class="ticks-labels"> | ||
<div *ngFor="let label of labels"> | ||
<ng-container *ngIf="label !== 750; else labelWithIcon"> | ||
{{label | i18nPlural: pluralMap}} | ||
</ng-container> | ||
</div> | ||
|
||
<ng-template #labelWithIcon> | ||
<tui-svg src="tuiIconArrowUp"></tui-svg> | ||
<div>3/4</div> | ||
</ng-template> | ||
</div> | ||
|
||
<p class="tui-space_top-12 tui-space_bottom-0"> | ||
Control value: | ||
<output for="range-with-segments"> | ||
<code>{{value | json}}</code> | ||
</output> | ||
</p> |
Oops, something went wrong.