diff --git a/src/app/components/accordion/accordion.spec.ts b/src/app/components/accordion/accordion.spec.ts index 58652aaa707..63dec232e57 100755 --- a/src/app/components/accordion/accordion.spec.ts +++ b/src/app/components/accordion/accordion.spec.ts @@ -3,7 +3,7 @@ import { By } from '@angular/platform-browser'; import { Accordion } from './accordion'; import { AccordionTab } from './accordion'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { Component, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; +import { Component, NO_ERRORS_SCHEMA } from '@angular/core'; @Component({ template: ` @@ -175,15 +175,61 @@ describe('Accordion', () => { expect(secondAccordionTabHeaderEl.className).toContain('p-highlight'); }); - it('should be closed', () => { - fixture.detectChanges(); - - const secondAccordionTabOpenEl = fixture.debugElement.children[0].children[0].children[1].query(By.css('a')).nativeElement; - let spaceEvent = { which: 32, preventDefault() {} }; - secondAccordionTab.onKeydown(spaceEvent as KeyboardEvent); + it('should be toggle on space and enter keydown event', () => { fixture.detectChanges(); const secondAccordionTabHeaderEl = fixture.debugElement.children[0].children[0].children[1].query(By.css('.p-accordion-header')).nativeElement; + expect(secondAccordionTabHeaderEl.className).not.toContain('p-highlight'); + + //toggle when enter is pressed + const spaceEvent = new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter' }); + secondAccordionTab.onKeydown(spaceEvent); + expect(secondAccordionTabHeaderEl.className).toContain('p-highlight'); + + //toggle when space is pressed + const keyDownEvent = new KeyboardEvent('keydown', { key: 'Space', code: 'Space' }); + secondAccordionTab.onKeydown(keyDownEvent); + fixture.detectChanges(); + + expect(secondAccordionTabHeaderEl.className).not.toContain('p-highlight'); + }); + + describe('onKeydown', () => { + let firstAccordionTabEl; + let secondAccordionTabEl; + + beforeEach(() => { + firstAccordionTabEl = fixture.debugElement.children[0].children[0].children[0].query(By.css('a')).nativeElement; + secondAccordionTabEl = fixture.debugElement.children[0].children[0].children[1].query(By.css('a')).nativeElement; + }); + + const testKeyBoardEvent = (keyCode, eventTarget, activeTab) => { + fixture.detectChanges(); + + const keyDownEvent = new KeyboardEvent('keydown', { code: keyCode }); + spyOnProperty(keyDownEvent, 'target', 'get').and.returnValue(eventTarget); + + accordion.onKeydown(keyDownEvent); + fixture.detectChanges(); + + expect(document.activeElement).toEqual(activeTab); + }; + + it('ArrowDown should focus on the next tab', () => { + testKeyBoardEvent('ArrowDown', firstAccordionTabEl, secondAccordionTabEl); + }); + + it('ArrowUp should focus on the next tab', () => { + testKeyBoardEvent('ArrowUp', secondAccordionTabEl, firstAccordionTabEl); + }); + + it('Home should focus on the first tab', () => { + testKeyBoardEvent('Home', secondAccordionTabEl, firstAccordionTabEl); + }); + + it('End should focus on the last tab', () => { + testKeyBoardEvent('End', firstAccordionTabEl, secondAccordionTabEl); + }); }); }); diff --git a/src/app/components/dialog/dialog.spec.ts b/src/app/components/dialog/dialog.spec.ts index 099d2af2da6..f55d375ba73 100755 --- a/src/app/components/dialog/dialog.spec.ts +++ b/src/app/components/dialog/dialog.spec.ts @@ -332,11 +332,7 @@ describe('Dialog', () => { fixture.detectChanges(); tick(300); - const escapeEvent: any = document.createEvent('CustomEvent'); - escapeEvent.which = 27; - escapeEvent.initEvent('keydown', true, true); - document.dispatchEvent(escapeEvent); - document.dispatchEvent(escapeEvent as KeyboardEvent); + document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' })); fixture.detectChanges(); expect(closeSpy).toHaveBeenCalled(); diff --git a/src/app/components/fileupload/fileupload.ts b/src/app/components/fileupload/fileupload.ts index 41a361de907..2582bce2b90 100755 --- a/src/app/components/fileupload/fileupload.ts +++ b/src/app/components/fileupload/fileupload.ts @@ -140,7 +140,7 @@ import { FileBeforeUploadEvent, FileProgressEvent, FileRemoveEvent, FileSelectEv
diff --git a/src/app/components/rating/rating.spec.ts b/src/app/components/rating/rating.spec.ts index cf51231a69e..344abc8adab 100755 --- a/src/app/components/rating/rating.spec.ts +++ b/src/app/components/rating/rating.spec.ts @@ -62,8 +62,8 @@ describe('Rating', () => { fixture.detectChanges(); const starElements = fixture.debugElement.queryAll(By.css('span')); - expect(starElements[0].nativeElement.className).toContain('Primeng Rocks!'); - expect(starElements[0].nativeElement.style.height).toEqual('300px'); + expect(starElements[1].nativeElement.className).toContain('Primeng Rocks!'); + expect(starElements[1].nativeElement.style.height).toEqual('300px'); }); it('should value 3', () => { @@ -86,11 +86,18 @@ describe('Rating', () => { rating.onRate.subscribe((value) => (onRateValue = value)); rating.onCancel.subscribe((value) => (onCancelRate = value)); thirdStarEl.parentElement.click(); - cancelEl.parentElement.click(); fixture.detectChanges(); expect(onRateValue.value).toEqual(3); - expect(onCancelRate).toBeTruthy(); + + const cancelspy = spyOn(rating.onCancel, 'emit').and.callThrough(); + const onModelChangeSpy = spyOn(rating, 'onModelChange').and.callThrough(); + cancelEl.parentElement.click(); + fixture.detectChanges(); + + expect(onModelChangeSpy).toHaveBeenCalled(); + expect(rating.value).toEqual(null); + expect(cancelspy).toHaveBeenCalled(); }); it('should clear value', () => { diff --git a/src/app/components/skeleton/skeleton.ts b/src/app/components/skeleton/skeleton.ts index 2435fe0f458..7d2aca9b13c 100755 --- a/src/app/components/skeleton/skeleton.ts +++ b/src/app/components/skeleton/skeleton.ts @@ -44,7 +44,7 @@ export class Skeleton { * Size of the skeleton. * @group Props */ - @Input() size: 'circle' | 'square' | undefined; + @Input() size: string | undefined; /** * Width of the element. * @group Props diff --git a/src/app/components/tree/tree.ts b/src/app/components/tree/tree.ts index ca127a74986..74a14461437 100755 --- a/src/app/components/tree/tree.ts +++ b/src/app/components/tree/tree.ts @@ -1271,7 +1271,10 @@ export class Tree implements OnInit, AfterContentInit, OnChanges, OnDestroy, Blo return; } else if (this.selectionMode) { if (node.selectable === false) { + node.style = '--p-focus-ring-color: none;'; return; + } else { + node.style = '--p-focus-ring-color: var(--primary-color)'; } if (this.hasFilteredNodes()) { diff --git a/src/app/components/treeselect/treeselect.ts b/src/app/components/treeselect/treeselect.ts index f6fd4e6521d..282fb372005 100755 --- a/src/app/components/treeselect/treeselect.ts +++ b/src/app/components/treeselect/treeselect.ts @@ -53,8 +53,8 @@ export const TREESELECT_VALUE_ACCESSOR: any = { [attr.id]="inputId" readonly [disabled]="disabled" - (focus)="onFocus()" - (blur)="onBlur()" + (focus)="onInputFocus($event)" + (blur)="onInputBlur($event)" (keydown)="onKeyDown($event)" [attr.tabindex]="!disabled ? tabindex : -1" [attr.aria-controls]="overlayVisible ? listId : null" @@ -437,6 +437,7 @@ export class TreeSelect implements AfterContentInit { * @group Emits */ @Output() onNodeCollapse: EventEmitter = new EventEmitter(); + /** * Callback to invoke when the overlay is shown. * @param {Event} event - Browser event. @@ -459,6 +460,18 @@ export class TreeSelect implements AfterContentInit { * @group Emits */ @Output() onFilter: EventEmitter = new EventEmitter(); + /** + * Callback to invoke when treeselect gets focus. + * @param {Event} event - Browser event. + * @group Emits + */ + @Output() onFocus: EventEmitter = new EventEmitter(); + /** + * Callback to invoke when treeselect loses focus. + * @param {Event} event - Browser event. + * @group Emits + */ + @Output() onBlur: EventEmitter = new EventEmitter(); /** * Callback to invoke when a node is unselected. * @param {TreeNodeUnSelectEvent} event - node unselect event. @@ -908,7 +921,7 @@ export class TreeSelect implements AfterContentInit { this.onNodeSelect.emit(event); if (this.selectionMode === 'single') { - // this.hide(); + this.hide(); this.focusInput?.nativeElement.focus(); } } @@ -917,12 +930,20 @@ export class TreeSelect implements AfterContentInit { this.onNodeUnselect.emit(event); } - onFocus() { + onInputFocus(event: Event) { + if (this.disabled) { + // For ScreenReaders + return; + } + this.focused = true; + this.onFocus.emit(event); } - onBlur() { + onInputBlur(event: Event) { this.focused = false; + this.onBlur.emit(event); + this.onModelTouched(); } writeValue(value: any): void { diff --git a/src/app/showcase/doc/apidoc/index.json b/src/app/showcase/doc/apidoc/index.json index 4c1b4563b4e..0779ac4e76d 100644 --- a/src/app/showcase/doc/apidoc/index.json +++ b/src/app/showcase/doc/apidoc/index.json @@ -12084,7 +12084,7 @@ "type": "{\n \t $implicit: any, // File list.\n \t uploadedFiles: any, // Uploaded files list.\n \t chooseCallback: VoidFunction, // Callback to invoke on choose button click.\n \t clearCallback: VoidFunction, // Callback to invoke on clear button click.\n \t uploadCallback: VoidFunction, // Callback to invoke on upload.\n }" } ], - "description": "Custom template of file." + "description": "Custom template of header." }, { "parent": "fileupload", diff --git a/src/app/showcase/doc/calendar/calendardoc.module.ts b/src/app/showcase/doc/calendar/calendardoc.module.ts index 5d5bbca09be..7327b0a0b60 100644 --- a/src/app/showcase/doc/calendar/calendardoc.module.ts +++ b/src/app/showcase/doc/calendar/calendardoc.module.ts @@ -22,7 +22,6 @@ import { TemplateDoc } from './templatedoc'; import { InlineDoc } from './inlinedoc'; import { TouchUIDoc } from './touchuidoc'; import { DateTemplateDoc } from './datetemplatedoc'; -import { PropsDoc } from './propsdoc'; import { StyleDoc } from './styledoc'; import { EventsDoc } from './eventsdoc'; import { MethodsDoc } from './methodsdoc'; @@ -56,7 +55,6 @@ import { FloatLabelModule } from 'primeng/floatlabel'; InlineDoc, TouchUIDoc, DateTemplateDoc, - PropsDoc, StyleDoc, EventsDoc, MethodsDoc, diff --git a/src/app/showcase/doc/calendar/propsdoc.ts b/src/app/showcase/doc/calendar/propsdoc.ts deleted file mode 100644 index 4bd310b0470..00000000000 --- a/src/app/showcase/doc/calendar/propsdoc.ts +++ /dev/null @@ -1,413 +0,0 @@ -import { Component, Input } from '@angular/core'; - -@Component({ - selector: 'props-doc', - template: `
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
defaultDateDatenullSet the date to highlight on first opening if the field is blank.
selectionModestringsingleDefines the quantity of the selection, valid values are "single", "multiple" and "range".
stylestringnullInline style of the component.
styleClassstringnullStyle class of the component.
inputStylestringnullInline style of the input field.
inputStyleClassstringnullStyle class of the input field.
inputIdstringnullIdentifier of the focus input to match a label defined for the component.
namestringnullName of the input element.
placeholderstringnullPlaceholder text for the input.
disabledbooleanfalseWhen specified, disables the component.
dateFormatstringmm/dd/yyFormat of the date which can also be defined at locale settings.
inlinebooleanfalseWhen enabled, displays the calendar as inline. Default is false for popup mode.
showOtherMonthsbooleantrueWhether to display dates in other months (non-selectable) at the start or end of the current month. To make these days selectable use the selectOtherMonths option.
selectOtherMonthsbooleanfalseWhether days in other months shown before or after the current month are selectable. This only applies if the showOtherMonths option is set to true.
showIconbooleanfalseWhen enabled, displays a button with icon next to input.
showOnFocusbooleantrueWhen disabled, datepicker will not be visible with input focus.
showWeekbooleanfalseWhen enabled, calendar will show week numbers.
iconstringnullIcon of the calendar button.
appendToanynull - Target element to attach the overlay, valid values are "body" or a local ng-template variable of another element (note: use binding with brackets for template variables, e.g. [appendTo]="mydiv" for a div element having - #mydiv as variable name). -
readonlyInputbooleannullWhen specified, prevents entering the date manually with keyboard.
shortYearCutoffstring+10The cutoff year for determining the century for a date.
minDateDatenullThe minimum selectable date.
maxDateDatenullThe maximum selectable date.
disabledDatesArray<Date>nullArray with dates that should be disabled (not selectable).
disabledDaysArray<number>nullArray with weekday numbers that should be disabled (not selectable).
monthNavigatorbooleanfalse - Whether the month should be rendered as a dropdown instead of text.
-
- Deprecated: Navigator is always on -
yearNavigatorbooleanfalse - Whether the year should be rendered as a dropdown instead of text.
-
- Deprecated: Navigator is always on. -
yearRangestringnull - The range of years displayed in the year drop-down in (nnnn:nnnn) format such as (2000:2020).

- Deprecated: Years are based on decades by default. -
showTimebooleanfalseWhether to display timepicker.
hourFormatstring24Specifies 12 or 24 hour format.
timeOnlybooleanfalseWhether to display timepicker only.
timeSeparatorstring:Separator of time selector.
dataTypestringdateType of the value to write back to ngModel, default is date and alternative is string.
requiredbooleanfalseWhen present, it specifies that an input field must be filled out before submitting the form.
tabindexnumbernullIndex of the element in tabbing order.
ariaLabelledBystringnullEstablishes relationships between the component and label(s) where its value should be one or more element IDs.
iconAriaLabelstringnullDefines a string that labels the icon button for accessibility.
showSecondsbooleanfalseWhether to show the seconds in time picker.
stepHournumber1Hours to change per step.
stepMinutenumber1Minutes to change per step.
stepSecondnumber1Seconds to change per step.
maxDateCountnumbernullMaximum number of selectable dates in multiple mode.
showButtonBarbooleanfalseWhether to display today and clear buttons at the footer
todayButtonStyleClassstringp-secondary-buttonStyle class of the today button.
clearButtonStyleClassstringp-secondary-buttonStyle class of the clear button.
autofocusbooleanfalseWhen present, it specifies that the component should automatically get focus on load.
baseZIndexnumber0Base zIndex value to use in layering.
autoZIndexbooleantrueWhether to automatically manage layering.
panelStyleClassstringnullStyle class of the datetimepicker container element.
panelStyleobjectnullInline style of the datetimepicker container element.
keepInvalidbooleanfalseKeep invalid value when input blur.
hideOnDateTimeSelectbooleantrueWhether to hide the overlay on date selection.
numberOfMonthsnumber1Number of months to display.
view'date' | 'month' | 'year'dateType of view to display, valid values are "date" for datepicker and "month" for month picker.
multipleSeparatorstring,Separator for multiple selection mode.
rangeSeparatorstring-Separator for joining start and end dates on range selection mode.
touchUIbooleanfalseWhen enabled, calendar overlay is displayed as optimized for touch devices.
focusTrapbooleantrueWhen enabled, can only focus on elements inside the calendar.
showTransitionOptionsstring.12s cubic-bezier(0, 0, 0.2, 1)Transition options of the show animation.
hideTransitionOptionsstring.1s linearTransition options of the hide animation.
firstDayOfWeeknumber0Defines the first of the week for various date calculations.
showClearbooleanfalseWhen enabled, a clear icon is displayed to clear the value.
-
-
` -}) -export class PropsDoc { - @Input() id: string; - - @Input() title: string; -}