From 37e2d4513265bd0913c7ddfe8509730e7b9f69f5 Mon Sep 17 00:00:00 2001 From: Melloware Date: Mon, 18 Apr 2022 13:17:58 -0400 Subject: [PATCH 01/11] Fix #2763: Calendar onMonthChange made optional (#2767) --- components/lib/calendar/Calendar.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/lib/calendar/Calendar.d.ts b/components/lib/calendar/Calendar.d.ts index 4b7fd2b2e6..8d73863954 100644 --- a/components/lib/calendar/Calendar.d.ts +++ b/components/lib/calendar/Calendar.d.ts @@ -149,7 +149,7 @@ export interface CalendarProps { onInput?(event: React.FormEvent): void; onSelect?(e: CalendarSelectParams): void; onChange?(e: CalendarChangeParams): void; - onMonthChange(e: CalendarMonthChangeParams): void + onMonthChange?(e: CalendarMonthChangeParams): void onViewDateChange?(e: CalendarViewChangeParams): void; onTodayButtonClick?(event: React.MouseEvent): void; onClearButtonClick?(event: React.MouseEvent): void; From 8cbcbecb5785465016be856a7c9a64ff35e1341b Mon Sep 17 00:00:00 2001 From: Cagatay Civici Date: Tue, 19 Apr 2022 09:09:48 +0300 Subject: [PATCH 02/11] Accessibility refactor for InputMask --- components/doc/inputmask/index.js | 19 ++++++++++++++++++- components/doc/inputtext/index.js | 2 +- components/lib/inputmask/InputMask.d.ts | 1 - components/lib/inputmask/InputMask.js | 3 +-- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/components/doc/inputmask/index.js b/components/doc/inputmask/index.js index 4ab4375256..37082e9111 100644 --- a/components/doc/inputmask/index.js +++ b/components/doc/inputmask/index.js @@ -474,7 +474,24 @@ import { InputMask } from 'primereact/inputmask';
Styling
-

Styling is same as inputtext component, for theming classes visit theming page.

+

Styling is same as inputtext component.

+ +
Accessibility
+
Screen Reader
+

InputMask component renders a native input element that implicitly includes any passed prop. Value to describe the component can either be provided via label tag combined with id prop or using aria-labelledby, aria-label props.

+ +{` + + + +Phone + + + +`} + +
Keyboard Support
+

InputMask can receive focus using the tab key.

Dependencies

None.

diff --git a/components/doc/inputtext/index.js b/components/doc/inputtext/index.js index fb70ec6322..dbc373ee43 100644 --- a/components/doc/inputtext/index.js +++ b/components/doc/inputtext/index.js @@ -402,7 +402,7 @@ import { InputText } from 'primereact/inputtext'; `}
Keyboard Support
-

Checkbox can receive focus using the tab key.

+

InputText can receive focus using the tab key.

Dependencies

None.

diff --git a/components/lib/inputmask/InputMask.d.ts b/components/lib/inputmask/InputMask.d.ts index 7314adf132..022a525c7d 100644 --- a/components/lib/inputmask/InputMask.d.ts +++ b/components/lib/inputmask/InputMask.d.ts @@ -41,7 +41,6 @@ export interface InputMaskProps { required?: boolean; tooltip?: string; tooltipOptions?: TooltipOptions; - ariaLabelledBy?: string; onComplete?(e: InputMaskCompleteParams): void; onChange?(e: InputMaskChangeParams): void; onFocus?(event: React.FocusEvent): void; diff --git a/components/lib/inputmask/InputMask.js b/components/lib/inputmask/InputMask.js index dfb63a837d..c821eb58a9 100644 --- a/components/lib/inputmask/InputMask.js +++ b/components/lib/inputmask/InputMask.js @@ -533,7 +533,7 @@ export const InputMask = React.memo(React.forwardRef((props, ref) => { + required={props.required} tooltip={props.tooltip} tooltipOptions={props.tooltipOptions} /> ) })); @@ -560,7 +560,6 @@ InputMask.defaultProps = { required: false, tooltip: null, tooltipOptions: null, - ariaLabelledBy: null, onComplete: null, onChange: null, onFocus: null, From f76047c02cdd9e5a511162a86435dedf8babf50c Mon Sep 17 00:00:00 2001 From: Cagatay Civici Date: Tue, 19 Apr 2022 09:14:06 +0300 Subject: [PATCH 03/11] Add doc for props --- components/doc/inputmask/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/components/doc/inputmask/index.js b/components/doc/inputmask/index.js index 37082e9111..b44c51fb2c 100644 --- a/components/doc/inputmask/index.js +++ b/components/doc/inputmask/index.js @@ -307,6 +307,7 @@ import { InputMask } from 'primereact/inputmask';
Properties
+

InputMask passes any valid attribute to the underlying React HTMLInputElement element. Extended properties are as follows;

From 7e1144e48a170bdd6369b81944e204388f60bd9c Mon Sep 17 00:00:00 2001 From: Cagatay Civici Date: Tue, 19 Apr 2022 09:25:24 +0300 Subject: [PATCH 04/11] Add styling section --- components/doc/inputmask/index.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/components/doc/inputmask/index.js b/components/doc/inputmask/index.js index b44c51fb2c..6cf31023d4 100644 --- a/components/doc/inputmask/index.js +++ b/components/doc/inputmask/index.js @@ -475,7 +475,27 @@ import { InputMask } from 'primereact/inputmask';
Styling
-

Styling is same as inputtext component.

+

Following is the list of structural style classes, for theming classes visit theming page.

+
+
+ + + + + + + + + + + + + + + + +
NameElement
p-inputtextInput element
p-inputmaskInput element
+
Accessibility
Screen Reader
From af1c664822dc888ae93ed9304e27705d337a7e58 Mon Sep 17 00:00:00 2001 From: Cagatay Civici Date: Tue, 19 Apr 2022 10:02:37 +0300 Subject: [PATCH 05/11] Accessibility for toggle button --- api-generator/components/togglebutton.js | 6 ---- components/doc/inputswitch/index.js | 8 ++--- components/doc/togglebutton/index.js | 36 +++++++++++-------- components/lib/button/Button.css | 4 --- components/lib/togglebutton/ToggleButton.d.ts | 1 - components/lib/togglebutton/ToggleButton.js | 5 ++- pages/togglebutton/index.js | 4 +-- 7 files changed, 30 insertions(+), 34 deletions(-) diff --git a/api-generator/components/togglebutton.js b/api-generator/components/togglebutton.js index e6a759fa14..dfe7b01620 100644 --- a/api-generator/components/togglebutton.js +++ b/api-generator/components/togglebutton.js @@ -70,12 +70,6 @@ const ToggleButtonProps = [ type: 'object', default: 'null', description: 'Configuration of the tooltip, refer to the tooltip documentation for more information.' - }, - { - name: 'ariaLabelledBy', - type: 'string', - default: 'null', - description: 'Establishes relationships between the component and label(s) where its value should be one or more element IDs.' } ]; diff --git a/components/doc/inputswitch/index.js b/components/doc/inputswitch/index.js index 9af720d152..1dd536790f 100644 --- a/components/doc/inputswitch/index.js +++ b/components/doc/inputswitch/index.js @@ -292,8 +292,8 @@ import { InputSwitch } from 'primereact/inputswitch';
Accessibility
-
Screen Reader
-

InputSwitch component uses a hidden native checkbox element with switch role internally that is only visible to screen readers. Value to describe the component can either be provided via label tag combined with inputId prop or using aria-labelledby, aria-label props.

+
Screen Reader
+

InputSwitch component uses a hidden native checkbox element with switch role internally that is only visible to screen readers. Value to describe the component can either be provided via label tag combined with inputId prop or using aria-labelledby, aria-label props.

{` @@ -305,8 +305,8 @@ import { InputSwitch } from 'primereact/inputswitch'; `} -
Keyboard Support
-

InputSwitch can receive focus using the tab key, while being focused space key is used to toggle the checked state.

+
Keyboard Support
+

InputSwitch can receive focus using the tab key, while being focused space key is used to toggle the checked state.

Dependencies

None.

diff --git a/components/doc/togglebutton/index.js b/components/doc/togglebutton/index.js index ab7701c0c4..d4d37f320c 100644 --- a/components/doc/togglebutton/index.js +++ b/components/doc/togglebutton/index.js @@ -29,10 +29,10 @@ export class ToggleButtonDemo extends Component {
Basic
- this.setState({checked1: e.value})} onIcon="pi pi-check" offIcon="pi pi-times" /> + this.setState({checked1: e.value})} onIcon="pi pi-check" offIcon="pi pi-times" className="w-full sm:w-10rem" aria-label="Confirmation" />
Customized
- this.setState({checked2: e.value})} onLabel="I confirm" offLabel="I reject" onIcon="pi pi-check" offIcon="pi pi-times" style={{width: '10em'}} /> + this.setState({checked2: e.value})} onLabel="I confirm" offLabel="I reject" onIcon="pi pi-check" offIcon="pi pi-times" className="w-full sm:w-10rem" aria-label="Confirmation" />
); @@ -54,10 +54,10 @@ const ToggleButtonDemo = () => {
Basic
- setChecked1(e.value)} onIcon="pi pi-check" offIcon="pi pi-times" /> + setChecked1(e.value)} onIcon="pi pi-check" offIcon="pi pi-times" aria-label="Confirmation" />
Customized
- setChecked2(e.value)} onLabel="I confirm" offLabel="I reject" onIcon="pi pi-check" offIcon="pi pi-times" style={{width: '10em'}} /> + setChecked2(e.value)} onLabel="I confirm" offLabel="I reject" onIcon="pi pi-check" offIcon="pi pi-times" style={{width: '10em'}} aria-label="Confirmation" />
); @@ -78,10 +78,10 @@ const ToggleButtonDemo = () => {
Basic
- setChecked1(e.value)} onIcon="pi pi-check" offIcon="pi pi-times" /> + setChecked1(e.value)} onIcon="pi pi-check" offIcon="pi pi-times" className="w-full sm:w-10rem" aria-label="Confirmation" />
Customized
- setChecked2(e.value)} onLabel="I confirm" offLabel="I reject" onIcon="pi pi-check" offIcon="pi pi-times" style={{width: '10em'}} /> + setChecked2(e.value)} onLabel="I confirm" offLabel="I reject" onIcon="pi pi-check" offIcon="pi pi-times" className="w-full sm:w-10rem" aria-label="Confirmation" />
); @@ -105,10 +105,10 @@ const ToggleButtonDemo = () => {
Basic
- setChecked1(e.value)} onIcon="pi pi-check" offIcon="pi pi-times" /> + setChecked1(e.value)} onIcon="pi pi-check" offIcon="pi pi-times" className="w-full sm:w-10rem" aria-label="Confirmation" />
Customized
- setChecked2(e.value)} onLabel="I confirm" offLabel="I reject" onIcon="pi pi-check" offIcon="pi pi-times" style={{width: '10em'}} /> + setChecked2(e.value)} onLabel="I confirm" offLabel="I reject" onIcon="pi pi-check" offIcon="pi pi-times" className="w-full sm:w-10rem" aria-label="Confirmation" />
); @@ -239,12 +239,6 @@ import { ToggleButton } from 'primereact/togglebutton'; null Configuration of the tooltip, refer to the tooltip documentation for more information. - - ariaLabelledBy - string - null - Establishes relationships between the component and label(s) where its value should be one or more element IDs. - @@ -306,6 +300,20 @@ import { ToggleButton } from 'primereact/togglebutton'; + +
Screen Reader
+

ToggleButton component uses an element with button role and updates aria-pressed state for screen readers. Value to describe the component can be defined with aria-labelledby or aria-label props, it is highly suggested to use + either of these props as the component changes the label displayed which will result in screen readers to read different labels when the component receives focus. To prevent this, always provide an aria label that does not change related to state.

+ +{` +Remember Me + + + +`} + +
Keyboard Support
+

ToggleButton can receive focus using the tab key, while being focused space key is used to toggle the checked state.

Dependencies

None.

diff --git a/components/lib/button/Button.css b/components/lib/button/Button.css index 53966e8f7f..de6c3a1f4e 100644 --- a/components/lib/button/Button.css +++ b/components/lib/button/Button.css @@ -66,7 +66,3 @@ position: relative; z-index: 1; } - -.p-button-label { - transition: all .2s; -} diff --git a/components/lib/togglebutton/ToggleButton.d.ts b/components/lib/togglebutton/ToggleButton.d.ts index 3c89a4cf29..6edd1210f4 100644 --- a/components/lib/togglebutton/ToggleButton.d.ts +++ b/components/lib/togglebutton/ToggleButton.d.ts @@ -31,7 +31,6 @@ export interface ToggleButtonProps extends Omit): void; onBlur?(event: React.FocusEvent): void; diff --git a/components/lib/togglebutton/ToggleButton.js b/components/lib/togglebutton/ToggleButton.js index caa36da078..292a689a5e 100644 --- a/components/lib/togglebutton/ToggleButton.js +++ b/components/lib/togglebutton/ToggleButton.js @@ -27,7 +27,7 @@ export const ToggleButton = React.memo(React.forwardRef((props, ref) => { } const onKeyDown = (event) => { - if (event.key === 'Enter') { + if (event.keyCode === 32) { toggle(event); event.preventDefault(); } @@ -60,7 +60,7 @@ export const ToggleButton = React.memo(React.forwardRef((props, ref) => { <>
+ tabIndex={tabIndex} role="button" aria-pressed={props.checked}> {iconElement} {label} @@ -85,7 +85,6 @@ ToggleButton.defaultProps = { tabIndex: 0, tooltip: null, tooltipOptions: null, - ariaLabelledBy: null, onChange: null, onFocus: null, onBlur: null diff --git a/pages/togglebutton/index.js b/pages/togglebutton/index.js index 1a1a60314d..e1acc8a67f 100644 --- a/pages/togglebutton/index.js +++ b/pages/togglebutton/index.js @@ -27,10 +27,10 @@ const ToggleButtonDemo = () => {
Basic
- setChecked1(e.value)} onIcon="pi pi-check" offIcon="pi pi-times" /> + setChecked1(e.value)} onIcon="pi pi-check" offIcon="pi pi-times" className="w-full sm:w-10rem" aria-label="Confirmation" />
Customized
- setChecked2(e.value)} onLabel="I confirm" offLabel="I reject" onIcon="pi pi-check" offIcon="pi pi-times" style={{ width: '10em' }} /> + setChecked2(e.value)} onLabel="I confirm" offLabel="I reject" onIcon="pi pi-check" offIcon="pi pi-times" className="w-full sm:w-10rem" aria-label="Confirmation" />
From 5c39b20e1a02efeab72976a3854d4c5498cc9a97 Mon Sep 17 00:00:00 2001 From: Onur Senture Date: Tue, 19 Apr 2022 23:34:22 +0300 Subject: [PATCH 06/11] Fixed #2764 - Intro section of Accessibility page is not accessible (#2765) --- pages/accessibility/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/accessibility/index.js b/pages/accessibility/index.js index 4ad4a3f3ae..3dc6bc86f3 100644 --- a/pages/accessibility/index.js +++ b/pages/accessibility/index.js @@ -22,7 +22,7 @@ const AccessibilityPage = () => {
-

Accessibility is a majorn concern of the Prime UI libraries and PrimeReact is no exception. PrimeTek teams have initiated a significant process to review and enhance the accessibility features of the components. This guide +

Accessibility is a majorn concern of the Prime UI libraries and PrimeReact is no exception. PrimeTek teams have initiated a significant process to review and enhance the accessibility features of the components. This guide documents the foundation of the general guidelines that PrimeReact will follow and each component documentation will have a separate Accessibility section that states the keyboard support, screen reader compatibility, the implementation details along with tips to achieve WCAG compliancy. This work has been initiated in Q2 2022 and planned to be completed by early Q3. PrimeReact will be the reference implementation which then will be ported to PrimeFaces, PrimeNG and PrimeVue.

From 77fc52e972db76996c0884db2cee238e30c509a6 Mon Sep 17 00:00:00 2001 From: Melloware Date: Wed, 20 Apr 2022 06:36:11 -0400 Subject: [PATCH 07/11] Fix #2232: Chips onAdd allow callback to return false (#2761) --- components/doc/chips/index.js | 2 +- components/lib/chips/Chips.js | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/components/doc/chips/index.js b/components/doc/chips/index.js index 42b1061438..6707a28d4b 100644 --- a/components/doc/chips/index.js +++ b/components/doc/chips/index.js @@ -356,7 +356,7 @@ customChip(item) { onAdd originalEvent: Browser event
value: Added item value - Callback to invoke when a chip is added. + Callback to invoke when a chip is added. Return 'false' to prevent the item from being added. onRemove diff --git a/components/lib/chips/Chips.js b/components/lib/chips/Chips.js index 563ddfb55c..e803a87da6 100644 --- a/components/lib/chips/Chips.js +++ b/components/lib/chips/Chips.js @@ -47,14 +47,17 @@ export const Chips = React.memo(React.forwardRef((props, ref) => { let values = props.value ? [...props.value] : []; if (props.allowDuplicate || values.indexOf(item) === -1) { - values.push(item); - + let allowAddition = true; if (props.onAdd) { - props.onAdd({ + allowAddition = props.onAdd({ originalEvent: event, value: item }); } + + if (allowAddition !== false) { + values.push(item); + } } updateInput(event, values, preventDefault); From 3ac191dc1bd79a1adee036c2695609eb1409ea2c Mon Sep 17 00:00:00 2001 From: mertsincan Date: Wed, 20 Apr 2022 13:39:38 +0100 Subject: [PATCH 08/11] Fixed #2769 - Carousel v8.0.0-rc.2 Data and Navigation Unusable --- components/lib/carousel/Carousel.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/lib/carousel/Carousel.js b/components/lib/carousel/Carousel.js index d74befb089..dfc2737338 100644 --- a/components/lib/carousel/Carousel.js +++ b/components/lib/carousel/Carousel.js @@ -28,7 +28,6 @@ export const Carousel = React.memo(React.forwardRef((props, ref) => { const itemsContainerRef = React.useRef(null); const remainingItems = React.useRef(0); const allowAutoplay = React.useRef(!!props.autoplayInterval); - const circular = React.useRef(props.circular || !!props.autoplayInterval); const attributeSelector = React.useRef(''); const swipeThreshold = React.useRef(20); const startPos = React.useRef(null); @@ -41,6 +40,7 @@ export const Carousel = React.memo(React.forwardRef((props, ref) => { const prevValue = usePrevious(props.value); const prevPage = usePrevious(props.page); const isVertical = props.orientation === 'vertical'; + const circular = props.circular || !!props.autoplayInterval; const isCircular = circular && props.value.length >= numVisibleState; const isAutoplay = props.autoplayInterval && allowAutoplay.current; const currentPage = props.onPageChange ? props.page : pageState; @@ -80,7 +80,7 @@ export const Carousel = React.memo(React.forwardRef((props, ref) => { } else if (isCircular && pageState === 0 && dir === 1) { totalShiftedItems = 0; - page = (totalShiftedItems - 1); + page = (totalIndicators - 1); } else if (page === (totalIndicators - 1) && remainingItems.current > 0) { totalShiftedItems += ((remainingItems.current * -1) - (numScrollState * dir)); @@ -309,7 +309,7 @@ export const Carousel = React.memo(React.forwardRef((props, ref) => { remainingItems.current = (props.value.length - numVisibleState) % numScrollState; let page = currentPage; - if (totalIndicators !== 0 && pageState >= totalIndicators) { + if (totalIndicators !== 0 && page >= totalIndicators) { page = totalIndicators - 1; if (props.onPageChange) { @@ -513,7 +513,7 @@ export const Carousel = React.memo(React.forwardRef((props, ref) => { const createIndicator = (index) => { const isActive = currentPage === index; - const key = 'p-carousel-indicator-' + index; + const key = 'carousel-indicator-' + index; const className = classNames('p-carousel-indicator', { 'p-highlight': isActive }); From 1dc89f53a6eee840858a998557a59f462b1db860 Mon Sep 17 00:00:00 2001 From: Melloware Date: Wed, 20 Apr 2022 08:41:44 -0400 Subject: [PATCH 09/11] Fix #2768: TreeSeelct onSelect/Unselect typescript defs (#2775) * Fix #2768: TreeSeelct onSelect/Unselect typescript defs * Fix #2768: TreeSeelct onSelect/Unselect typescript defs --- components/lib/treeselect/TreeSelect.d.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/components/lib/treeselect/TreeSelect.d.ts b/components/lib/treeselect/TreeSelect.d.ts index 0ecea47ca2..93a4a31afd 100644 --- a/components/lib/treeselect/TreeSelect.d.ts +++ b/components/lib/treeselect/TreeSelect.d.ts @@ -1,5 +1,6 @@ import * as React from 'react'; import TreeNode from '../treenode'; +import TreeEventNodeParams from '../tree'; import { CSSTransitionProps } from '../csstransition'; type TreeSelectSelectionModeType = 'single' | 'multiple' | 'checkbox'; @@ -54,9 +55,7 @@ interface TreeSelectCheckboxSelectionKeyType { partialChecked?: boolean; } -interface TreeSelectEventNodeParams { - originalEvent: React.SyntheticEvent; - node: TreeNode; +interface TreeSelectEventNodeParams extends TreeEventNodeParams { } interface TreeSelectFilterValueChangeParams { @@ -101,8 +100,8 @@ export interface TreeSelectProps extends Omit Date: Wed, 20 Apr 2022 08:43:27 -0400 Subject: [PATCH 10/11] Fix #2773: Add useStorage hook (#2774) --- components/lib/hooks/Hooks.d.ts | 4 ++- components/lib/hooks/Hooks.js | 3 +- components/lib/hooks/useStorage.js | 51 ++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 components/lib/hooks/useStorage.js diff --git a/components/lib/hooks/Hooks.d.ts b/components/lib/hooks/Hooks.d.ts index f04546f7d5..79e573fb2a 100644 --- a/components/lib/hooks/Hooks.d.ts +++ b/components/lib/hooks/Hooks.d.ts @@ -1,6 +1,7 @@ -import { DependencyList, EffectCallback, Ref } from 'react'; +import { Dispatch, DependencyList, EffectCallback, Ref } from 'react'; export type TargetType = 'document' | 'window' | Ref | undefined; +export type StorageType = 'local' | 'session'; interface EventOptions { target?: TargetType; @@ -31,3 +32,4 @@ export declare function useOverlayScrollListener(options: EventOptions): any[]; export declare function useResizeListener(options: ResizeEventOptions): any[]; export declare function useInterval(fn: any, delay?: number, when?: boolean): any[]; export declare function useTimeout(fn: any, delay?: number, when?: boolean): any[]; +export declare function useStorage(initialValue: S, key: string, storage?: StorageType): [S, Dispatch>]; \ No newline at end of file diff --git a/components/lib/hooks/Hooks.js b/components/lib/hooks/Hooks.js index 55ee0489ce..aa9f6bddff 100644 --- a/components/lib/hooks/Hooks.js +++ b/components/lib/hooks/Hooks.js @@ -7,6 +7,7 @@ import { useOverlayListener } from './useOverlayListener'; import { useOverlayScrollListener } from './useOverlayScrollListener'; import { useResizeListener } from './useResizeListener'; import { useInterval } from './useInterval'; +import { useStorage } from './useStorage'; import { useTimeout } from './useTimeout'; -export { usePrevious, useMountEffect, useUpdateEffect, useUnmountEffect, useEventListener, useOverlayListener, useOverlayScrollListener, useResizeListener, useInterval, useTimeout }; +export { usePrevious, useMountEffect, useUpdateEffect, useUnmountEffect, useEventListener, useOverlayListener, useOverlayScrollListener, useResizeListener, useInterval, useStorage, useTimeout }; diff --git a/components/lib/hooks/useStorage.js b/components/lib/hooks/useStorage.js new file mode 100644 index 0000000000..231452e931 --- /dev/null +++ b/components/lib/hooks/useStorage.js @@ -0,0 +1,51 @@ +/* eslint-disable */ +import * as React from 'react'; + +/** + * Hook to wrap around useState that stores the value in the browser local/session storage. + * + * @param {any} initialValue the initial value to store + * @param {string} key the key to store the value in local/session storage + * @param {string} storage either 'local' or 'session' for what type of storage + * @returns a stateful value, and a function to update it. + */ +export const useStorage = (initialValue, key, storage = 'local') => { + + // Since the local storage API isn't available in server-rendering environments, + // we check that typeof window !== 'undefined' to make SSR and SSG work properly. + const storageAvailable = typeof window !== 'undefined'; + + const [storedValue, setStoredValue] = React.useState(() => { + if (!storageAvailable) { + return initialValue; + } + try { + const item = storage === 'local' ? + window.localStorage.getItem(key) : + window.sessionStorage.getItem(key); + return item ? JSON.parse(item) : initialValue; + } catch (error) { + // If error also return initialValue + return initialValue; + } + }); + + const setValue = (value) => { + try { + // Allow value to be a function so we have same API as useState + const valueToStore = value instanceof Function ? value(storedValue) : value; + setStoredValue(valueToStore); + if (storageAvailable) { + const serializedValue = JSON.stringify(valueToStore); + storage === 'local' ? + window.localStorage.setItem(key, serializedValue) : + window.sessionStorage.setItem(key, serializedValue); + } + } catch (error) { + throw new Error(`PrimeReact useStorage: Failed to serialize the value at key: ${key}`); + } + }; + + return [storedValue, setValue]; +} +/* eslint-enable */ \ No newline at end of file From b4a788a681e75c5a0ed4345d81232615cec21dcb Mon Sep 17 00:00:00 2001 From: mertsincan Date: Wed, 20 Apr 2022 13:49:06 +0100 Subject: [PATCH 11/11] Update Hooks.d.ts --- components/lib/hooks/Hooks.d.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/components/lib/hooks/Hooks.d.ts b/components/lib/hooks/Hooks.d.ts index 79e573fb2a..3ccf79bdc3 100644 --- a/components/lib/hooks/Hooks.d.ts +++ b/components/lib/hooks/Hooks.d.ts @@ -1,6 +1,6 @@ -import { Dispatch, DependencyList, EffectCallback, Ref } from 'react'; +import * as React from 'react'; -export type TargetType = 'document' | 'window' | Ref | undefined; +export type TargetType = 'document' | 'window' | React.Ref | undefined; export type StorageType = 'local' | 'session'; interface EventOptions { @@ -23,13 +23,13 @@ interface ResizeEventOptions { } export declare function usePrevious(value: any): any; -export declare function useMountEffect(effect: EffectCallback): void; -export declare function useUpdateEffect(effect: EffectCallback, deps?: DependencyList): void; -export declare function useUnmountEffect(effect: EffectCallback): void; +export declare function useMountEffect(effect: React.EffectCallback): void; +export declare function useUpdateEffect(effect: React.EffectCallback, deps?: React.DependencyList): void; +export declare function useUnmountEffect(effect: React.EffectCallback): void; export declare function useEventListener(options: EventOptions): any[]; export declare function useOverlayListener(options: OverlayEventOptions): any[]; export declare function useOverlayScrollListener(options: EventOptions): any[]; export declare function useResizeListener(options: ResizeEventOptions): any[]; export declare function useInterval(fn: any, delay?: number, when?: boolean): any[]; export declare function useTimeout(fn: any, delay?: number, when?: boolean): any[]; -export declare function useStorage(initialValue: S, key: string, storage?: StorageType): [S, Dispatch>]; \ No newline at end of file +export declare function useStorage(initialValue: S, key: string, storage?: StorageType): [S, React.Dispatch>];