From 98c5b0d623d3f376e0284e9eb57185ca738e0817 Mon Sep 17 00:00:00 2001
From: Melloware <mellowaredev@gmail.com>
Date: Tue, 9 Jan 2024 14:49:28 -0500
Subject: [PATCH] Port fixes5 (#5713)

* Fix #5485: Messages restore close animation

* Fix #5490: useDebounce fixed

* Fix #5492: Listbox passthrough fixes

* Fix #5493: Multiselect passthrough fixes

* Fix #5485: Messages restore close animation

* Fix #5499: Autocomplete/Chips PT fixes

* Fix #5479: CascadeSelect PT fixes

* Fix #5509: Button loadingIcon Tailwind fix

* Fix #5512: Dropdown add tabindex for Tailwind

* Support roundingMode for InputNumber

* Fix #5523: BlockUI return activeElement focus

* Fix #5530: Chip onRemove event pass value

* DataTable:converted to data- lookups instead of className lookups

* Fix #5543: OverlayPanel Tailwind close icon

* Fix #5546: prop type error in console

* Fix #5555: BodyCell frozen issue

* Fix #5561: Inplace respect active prop

* Fix #5568: MultiSelect filterInput PT

* Fix #5572: Multselect selectAllLabel was being added to DOM

* Tooltip fix Tailwind CSS

* Dialog Breakpoints

* Calendar disabled date handling

* Fix #5609: ToggleButton focusedState

* Fix #5610: Radio/Checkbox always fire onClick

* fix: #5613, TreeSelect: TreeSelect component is not supporting tooltips and is an issue in multiple select mode

* Fix #5623 - Otherprops not working for InputSwitch

* fix:Calendar not showing correctly in Table

* fix:Image preview zoom in bug

* Fix #5637: Sidebar aria-label close

* Accept array as PT value

* Datatable breakpoints

* fix:ConfirmDialog: acceptButton's pt don't respect button
---
 components/lib/accordion/Accordion.js         |   2 +-
 .../lib/autocomplete/AutoCompletePanel.js     |   5 +-
 components/lib/autocomplete/autocomplete.d.ts |   5 +
 components/lib/blockui/BlockUI.js             |  14 ++-
 components/lib/calendar/Calendar.js           |  62 ++++++----
 components/lib/calendar/Calendar.spec.js      |  93 +++++++++++++++
 components/lib/calendar/CalendarBase.js       |   4 +-
 components/lib/cascadeselect/CascadeSelect.js |   9 +-
 .../lib/cascadeselect/CascadeSelectBase.js    |   6 +-
 .../lib/cascadeselect/CascadeSelectSub.js     |  15 ++-
 .../lib/cascadeselect/cascadeselect.d.ts      |  24 +++-
 components/lib/checkbox/Checkbox.js           |  53 +++++----
 components/lib/chip/Chip.js                   |   5 +-
 components/lib/chip/chip.d.ts                 |  19 ++-
 components/lib/componentbase/ComponentBase.js |  11 +-
 components/lib/confirmdialog/ConfirmDialog.js |   1 +
 components/lib/datatable/BodyCell.js          |   7 +-
 components/lib/datatable/DataTable.js         |  31 ++---
 components/lib/datatable/TableBody.js         |   4 +-
 components/lib/dialog/Dialog.js               |  17 ++-
 components/lib/dropdown/Dropdown.js           |   8 +-
 components/lib/hooks/useDebounce.js           |  29 +++--
 components/lib/image/Image.js                 |  16 ++-
 components/lib/inplace/Inplace.js             |   9 ++
 components/lib/inputnumber/InputNumber.js     |   9 +-
 components/lib/inputnumber/InputNumberBase.js |   1 +
 components/lib/inputnumber/inputnumber.d.ts   |   7 ++
 components/lib/inputswitch/InputSwitch.js     |   5 +-
 components/lib/listbox/ListBoxItem.js         |  14 ++-
 components/lib/listbox/listbox.d.ts           |  11 +-
 components/lib/messages/Messages.js           |   2 +-
 components/lib/multiselect/MultiSelectBase.js |   1 +
 .../lib/multiselect/MultiSelectHeader.js      |  11 +-
 components/lib/multiselect/MultiSelectItem.js |  17 ++-
 components/lib/multiselect/multiselect.d.ts   |   4 +
 components/lib/passthrough/tailwind/index.js  | 110 ++++++++++--------
 components/lib/radiobutton/RadioButton.js     |  56 ++++-----
 components/lib/sidebar/Sidebar.js             |   2 +-
 components/lib/togglebutton/ToggleButton.js   |  22 +++-
 components/lib/treeselect/TreeSelect.js       |   3 +
 components/lib/treeselect/treeselect.d.ts     |  15 +++
 41 files changed, 527 insertions(+), 212 deletions(-)
 create mode 100644 components/lib/calendar/Calendar.spec.js

diff --git a/components/lib/accordion/Accordion.js b/components/lib/accordion/Accordion.js
index 55d57311e2..6572df2596 100644
--- a/components/lib/accordion/Accordion.js
+++ b/components/lib/accordion/Accordion.js
@@ -176,7 +176,7 @@ export const Accordion = React.forwardRef((inProps, ref) => {
     };
 
     const isSelected = (index) => {
-        return props.multiple ? activeIndex && activeIndex.some((i) => i === index) : activeIndex === index;
+        return props.multiple && Array.isArray(activeIndex) ? activeIndex && activeIndex.some((i) => i === index) : activeIndex === index;
     };
 
     React.useImperativeHandle(ref, () => ({
diff --git a/components/lib/autocomplete/AutoCompletePanel.js b/components/lib/autocomplete/AutoCompletePanel.js
index 4bdf8653c9..d7b9170895 100644
--- a/components/lib/autocomplete/AutoCompletePanel.js
+++ b/components/lib/autocomplete/AutoCompletePanel.js
@@ -21,7 +21,8 @@ export const AutoCompletePanel = React.memo(
         const getPTOptions = (item, key) => {
             return _ptm(key, {
                 context: {
-                    selected: props.selectedItem.current === item
+                    selected: props.selectedItem.current === item,
+                    disabled: item.disabled
                 }
             });
         };
@@ -107,7 +108,7 @@ export const AutoCompletePanel = React.memo(
                         className: cx('item', { suggestion }),
                         style,
                         onClick: (e) => props.onItemClick(e, suggestion),
-                        'aria-selected': props.selectedItem === suggestion,
+                        'aria-selected': props.selectedItem.current === suggestion,
                         'data-p-disabled': suggestion.disabled
                     },
                     getPTOptions(suggestion, 'item')
diff --git a/components/lib/autocomplete/autocomplete.d.ts b/components/lib/autocomplete/autocomplete.d.ts
index 14c87ff681..1e6502869d 100755
--- a/components/lib/autocomplete/autocomplete.d.ts
+++ b/components/lib/autocomplete/autocomplete.d.ts
@@ -216,6 +216,11 @@ export interface AutoCompleteContext {
      * @defaultValue false
      */
     selected: boolean;
+    /**
+     * Current disabled state of the item as a boolean.
+     * @defaultValue false
+     */
+    disabled: boolean;
 }
 
 /**
diff --git a/components/lib/blockui/BlockUI.js b/components/lib/blockui/BlockUI.js
index 31ad966689..589157e4f8 100644
--- a/components/lib/blockui/BlockUI.js
+++ b/components/lib/blockui/BlockUI.js
@@ -13,6 +13,7 @@ export const BlockUI = React.forwardRef((inProps, ref) => {
     const [visibleState, setVisibleState] = React.useState(props.blocked);
     const elementRef = React.useRef(null);
     const maskRef = React.useRef(null);
+    const activeElementRef = React.useRef(null);
 
     const { ptm, cx, isUnstyled } = BlockUIBase.setMetaData({
         props
@@ -22,13 +23,18 @@ export const BlockUI = React.forwardRef((inProps, ref) => {
 
     const block = () => {
         setVisibleState(true);
+        activeElementRef.current = document.activeElement;
     };
 
     const unblock = () => {
         const callback = () => {
             setVisibleState(false);
 
-            props.fullScreen && DomHandler.unblockBodyScroll();
+            if (props.fullScreen) {
+                DomHandler.unblockBodyScroll();
+                activeElementRef.current && activeElementRef.current.focus();
+            }
+
             props.onUnblocked && props.onUnblocked();
         };
 
@@ -46,7 +52,7 @@ export const BlockUI = React.forwardRef((inProps, ref) => {
     const onPortalMounted = () => {
         if (props.fullScreen) {
             DomHandler.blockBodyScroll();
-            document.activeElement.blur();
+            activeElementRef.current && activeElementRef.current.blur();
         }
 
         if (props.autoZIndex) {
@@ -67,9 +73,7 @@ export const BlockUI = React.forwardRef((inProps, ref) => {
     }, [props.blocked]);
 
     useUnmountEffect(() => {
-        if (props.fullScreen) {
-            DomHandler.unblockBodyScroll();
-        }
+        props.fullScreen && DomHandler.unblockBodyScroll();
 
         ZIndexUtils.clear(maskRef.current);
     });
diff --git a/components/lib/calendar/Calendar.js b/components/lib/calendar/Calendar.js
index 46257d143b..74d95d2ba0 100644
--- a/components/lib/calendar/Calendar.js
+++ b/components/lib/calendar/Calendar.js
@@ -1839,11 +1839,7 @@ export const Calendar = React.memo(
                 }
             }
 
-            if (props.disabledDates || props.enabledDates) {
-                validDate = !isDateDisabled(day, month, year);
-            }
-
-            if (props.disabledDays && currentView === 'date') {
+            if (props.disabledDates || props.enabledDates || props.disabledDays) {
                 validDay = !isDayDisabled(day, month, year);
             }
 
@@ -1993,27 +1989,46 @@ export const Calendar = React.memo(
             return today.getDate() === day && today.getMonth() === month && today.getFullYear() === year;
         };
 
-        const isDateDisabled = (day, month, year) => {
+        const isDayDisabled = (day, month, year) => {
             if (props.disabledDates) {
-                return props.disabledDates.some((d) => d.getFullYear() === year && d.getMonth() === month && d.getDate() === day);
+                if (props.disabledDates.some((d) => d.getFullYear() === year && d.getMonth() === month && d.getDate() === day)) {
+                    return true;
+                }
+            } else if (props.enabledDates) {
+                if (!props.enabledDates.some((d) => d.getFullYear() === year && d.getMonth() === month && d.getDate() === day)) {
+                    return true;
+                }
             }
 
-            if (props.enabledDates) {
-                return !props.enabledDates.some((d) => d.getFullYear() === year && d.getMonth() === month && d.getDate() === day);
+            if (props.disabledDays && currentView === 'date') {
+                let weekday = new Date(year, month, day);
+                let weekdayNumber = weekday.getDay();
+
+                if (props.disabledDays.indexOf(weekdayNumber) !== -1) {
+                    return true;
+                }
             }
 
             return false;
         };
 
-        const isDayDisabled = (day, month, year) => {
-            if (props.disabledDays) {
-                let weekday = new Date(year, month, day);
-                let weekdayNumber = weekday.getDay();
+        const isMonthYearDisabled = (month, year) => {
+            const daysCountInAllMonth = month === -1 ? new Array(12).fill(0).map((_, i) => getDaysCountInMonth(i, year)) : [getDaysCountInMonth(month, year)];
+
+            for (let i = 0; i < daysCountInAllMonth.length; i++) {
+                const monthDays = daysCountInAllMonth[i];
+                const _month = month === -1 ? i : month;
+
+                for (let day = 1; day <= monthDays; day++) {
+                    let isDateSelectable = isSelectable(day, _month, year);
 
-                return props.disabledDays.indexOf(weekdayNumber) !== -1;
+                    if (isDateSelectable) {
+                        return false;
+                    }
+                }
             }
 
-            return false;
+            return true;
         };
 
         const updateInputfield = (value) => {
@@ -2582,7 +2597,10 @@ export const Calendar = React.memo(
 
         useUpdateEffect(() => {
             if (overlayVisibleState || props.visible) {
-                alignOverlay();
+                // Github #5529
+                setTimeout(() => {
+                    alignOverlay();
+                });
             }
         }, [currentView, overlayVisibleState, props.visible]);
 
@@ -3654,10 +3672,10 @@ export const Calendar = React.memo(
                         {monthPickerValues().map((m, i) => {
                             const monthProps = mergeProps(
                                 {
-                                    className: cx('month', { isMonthSelected, isSelectable, i, currentYear }),
+                                    className: cx('month', { isMonthSelected, isMonthYearDisabled, i, currentYear }),
                                     onClick: (event) => onMonthSelect(event, i),
                                     onKeyDown: (event) => onMonthCellKeydown(event, i),
-                                    'data-p-disabled': !m.selectable,
+                                    'data-p-disabled': isMonthYearDisabled(i, currentYear),
                                     'data-p-highlight': isMonthSelected(i)
                                 },
                                 ptm('month', {
@@ -3665,7 +3683,7 @@ export const Calendar = React.memo(
                                         month: m,
                                         monthIndex: i,
                                         selected: isMonthSelected(i),
-                                        disabled: !m.selectable
+                                        disabled: isMonthYearDisabled(i, currentYear)
                                     }
                                 })
                             );
@@ -3697,17 +3715,17 @@ export const Calendar = React.memo(
                         {yearPickerValues().map((y, i) => {
                             const yearProps = mergeProps(
                                 {
-                                    className: cx('year', { isYearSelected, isSelectable, y }),
+                                    className: cx('year', { isYearSelected, isMonthYearDisabled, y }),
                                     onClick: (event) => onYearSelect(event, y),
                                     'data-p-highlight': isYearSelected(y),
-                                    'data-p-disabled': !isSelectable(0, -1, y)
+                                    'data-p-disabled': isMonthYearDisabled(-1, y)
                                 },
                                 ptm('year', {
                                     context: {
                                         year: y,
                                         yearIndex: i,
                                         selected: isYearSelected(i),
-                                        disabled: !y.selectable
+                                        disabled: isMonthYearDisabled(-1, y)
                                     }
                                 })
                             );
diff --git a/components/lib/calendar/Calendar.spec.js b/components/lib/calendar/Calendar.spec.js
new file mode 100644
index 0000000000..e38ff1eef1
--- /dev/null
+++ b/components/lib/calendar/Calendar.spec.js
@@ -0,0 +1,93 @@
+import '@testing-library/jest-dom';
+import { render } from '@testing-library/react';
+import { PrimeReactProvider } from '../api/Api';
+import { Calendar } from './Calendar';
+
+describe('Calendar', () => {
+    function getAllDatesOfYear(year) {
+        let startDate = new Date(year, 0, 1);
+        let endDate = new Date(year, 11, 31);
+
+        let dates = [];
+        let currentDate = startDate;
+
+        while (currentDate <= endDate) {
+            dates.push(new Date(currentDate));
+            currentDate.setDate(currentDate.getDate() + 1);
+        }
+
+        return dates;
+    }
+
+    test('When the days of the year are disabled, then the years and month should be disabled', async () => {
+        const { container } = render(
+            <PrimeReactProvider>
+                <Calendar value={new Date(2023, 11, 15)} inline view="year" disabledDates={getAllDatesOfYear(2023)} />
+            </PrimeReactProvider>
+        );
+
+        const years = container.querySelectorAll('.p-yearpicker-year');
+
+        for (const year of years) {
+            if (year.innerHTML === '2023') {
+                expect(year).toHaveAttribute('data-p-disabled', 'true');
+                expect(year).toHaveClass('p-disabled');
+            } else {
+                expect(year).toHaveAttribute('data-p-disabled', 'false');
+                expect(year).not.toHaveClass('p-disabled');
+            }
+        }
+
+        const { container: monthContainer } = render(
+            <PrimeReactProvider>
+                <Calendar value={new Date(2023, 11, 15)} inline view="month" disabledDates={getAllDatesOfYear(2023)} />
+            </PrimeReactProvider>
+        );
+
+        const months = monthContainer.querySelectorAll('.p-monthpicker-month');
+
+        for (const month of months) {
+            expect(month).toHaveAttribute('data-p-disabled', 'true');
+            expect(month).toHaveClass('p-disabled');
+        }
+    });
+
+    test('If any day of the month is not disabled, then both the year and month can be selected', async () => {
+        const disabledDates = getAllDatesOfYear(2023);
+
+        // January and December are not disabled.
+        disabledDates.shift();
+        disabledDates.pop();
+
+        const { container: yearContainer } = render(
+            <PrimeReactProvider>
+                <Calendar value={new Date(2023, 11, 15)} inline view="year" disabledDates={disabledDates} />
+            </PrimeReactProvider>
+        );
+        const years = yearContainer.querySelectorAll('.p-yearpicker-year');
+
+        for (const year of years) {
+            expect(year).toHaveAttribute('data-p-disabled', 'false');
+            expect(year).not.toHaveClass('p-disabled');
+        }
+
+        // month
+        const { container: monthContainer } = render(
+            <PrimeReactProvider>
+                <Calendar value={new Date(2023, 11, 15)} inline view="month" disabledDates={disabledDates} />
+            </PrimeReactProvider>
+        );
+
+        const months = monthContainer.querySelectorAll('.p-monthpicker-month');
+
+        Array.from(months).forEach((month, index) => {
+            if (index === 0 || index === 11) {
+                expect(month).toHaveAttribute('data-p-disabled', 'false');
+                expect(month).not.toHaveClass('p-disabled');
+            } else {
+                expect(month).toHaveAttribute('data-p-disabled', 'true');
+                expect(month).toHaveClass('p-disabled');
+            }
+        });
+    });
+});
diff --git a/components/lib/calendar/CalendarBase.js b/components/lib/calendar/CalendarBase.js
index 4dbcc117c5..f1ec418550 100644
--- a/components/lib/calendar/CalendarBase.js
+++ b/components/lib/calendar/CalendarBase.js
@@ -190,9 +190,9 @@ const classes = {
     clearButton: 'p-button-text',
     footer: 'p-datepicker-footer',
     yearPicker: 'p-yearpicker',
-    year: ({ isYearSelected, isSelectable, y }) => classNames('p-yearpicker-year', { 'p-highlight': isYearSelected(y), 'p-disabled': !isSelectable(0, -1, y) }),
+    year: ({ isYearSelected, y, isMonthYearDisabled }) => classNames('p-yearpicker-year', { 'p-highlight': isYearSelected(y), 'p-disabled': isMonthYearDisabled(-1, y) }),
     monthPicker: 'p-monthpicker',
-    month: ({ isMonthSelected, isSelectable, i, currentYear }) => classNames('p-monthpicker-month', { 'p-highlight': isMonthSelected(i), 'p-disabled': !isSelectable(0, i, currentYear) }),
+    month: ({ isMonthSelected, isMonthYearDisabled, i, currentYear }) => classNames('p-monthpicker-month', { 'p-highlight': isMonthSelected(i), 'p-disabled': isMonthYearDisabled(i, currentYear) }),
     hourPicker: 'p-hour-picker',
     secondPicker: 'p-second-picker',
     minutePicker: 'p-minute-picker',
diff --git a/components/lib/cascadeselect/CascadeSelect.js b/components/lib/cascadeselect/CascadeSelect.js
index 37663fd207..2137ca206b 100644
--- a/components/lib/cascadeselect/CascadeSelect.js
+++ b/components/lib/cascadeselect/CascadeSelect.js
@@ -24,11 +24,14 @@ export const CascadeSelect = React.memo(
                 focused: focusedState,
                 overlayVisible: overlayVisibleState,
                 attributeSelector: attributeSelectorState
+            },
+            context: {
+                ...context
             }
         });
 
         useHandleStyle(CascadeSelectBase.css.styles, isUnstyled, { name: 'cascadeselect' });
-        useOnEscapeKey(overlayRef, overlayVisibleState, () => hide());
+
         const elementRef = React.useRef(null);
         const overlayRef = React.useRef(null);
         const inputRef = React.useRef(null);
@@ -46,6 +49,8 @@ export const CascadeSelect = React.memo(
             when: overlayVisibleState
         });
 
+        useOnEscapeKey(overlayRef, overlayVisibleState, () => hide());
+
         const onOptionSelect = (event) => {
             if (props.onChange) {
                 props.onChange({
@@ -330,7 +335,7 @@ export const CascadeSelect = React.memo(
                     ref: labelRef,
                     className: cx('label', { label })
                 },
-                ptm('label')
+                ptm('label', { context: { label, ...context } })
             );
 
             return <span {...labelProps}>{label}</span>;
diff --git a/components/lib/cascadeselect/CascadeSelectBase.js b/components/lib/cascadeselect/CascadeSelectBase.js
index afe53059bd..c23d22c390 100644
--- a/components/lib/cascadeselect/CascadeSelectBase.js
+++ b/components/lib/cascadeselect/CascadeSelectBase.js
@@ -25,10 +25,10 @@ const classes = {
             'p-ripple-disabled': (context && context.ripple === false) || PrimeReact.ripple === false
         }),
     sublist: 'p-cascadeselect-panel p-cascadeselect-items p-cascadeselect-sublist',
-    item: ({ option, isOptionGroup, activeOptionState }) =>
+    item: ({ option, isGroup, isSelected }) =>
         classNames('p-cascadeselect-item', {
-            'p-cascadeselect-item-group': isOptionGroup(option),
-            'p-cascadeselect-item-active p-highlight': activeOptionState === option
+            'p-cascadeselect-item-group': isGroup,
+            'p-cascadeselect-item-active p-highlight': isSelected
         }),
     dropdownIcon: 'p-cascadeselect-trigger-icon',
     loadingIcon: 'p-cascadeselect-trigger-icon',
diff --git a/components/lib/cascadeselect/CascadeSelectSub.js b/components/lib/cascadeselect/CascadeSelectSub.js
index 1dd9bf87fa..7dc45c32b6 100644
--- a/components/lib/cascadeselect/CascadeSelectSub.js
+++ b/components/lib/cascadeselect/CascadeSelectSub.js
@@ -10,9 +10,10 @@ export const CascadeSelectSub = React.memo((props) => {
     const context = React.useContext(PrimeReactContext);
     const { ptm, cx } = props;
 
-    const getPTOptions = (key) => {
+    const getPTOptions = (key, options) => {
         return ptm(key, {
-            hostName: props.hostName
+            hostName: props.hostName,
+            state: { ...options }
         });
     };
 
@@ -238,15 +239,17 @@ export const CascadeSelectSub = React.memo((props) => {
             getPTOptions('content')
         );
 
+        const isSelected = activeOptionState === option;
+        const isGroup = isOptionGroup(option);
         const itemProps = mergeProps(
             {
-                className: classNames(option.className, cx('item', { option, isOptionGroup, activeOptionState })),
+                className: classNames(option.className, cx('item', { option, isGroup, isSelected })),
                 style: option.style,
                 role: 'none',
-                'data-p-item-group': isOptionGroup(option),
-                'data-p-highlight': activeOptionState === option
+                'data-p-item-group': isGroup,
+                'data-p-highlight': isSelected
             },
-            getPTOptions('item')
+            getPTOptions('item', { selected: isSelected, group: isGroup })
         );
 
         return (
diff --git a/components/lib/cascadeselect/cascadeselect.d.ts b/components/lib/cascadeselect/cascadeselect.d.ts
index a935b82688..5024cb8002 100644
--- a/components/lib/cascadeselect/cascadeselect.d.ts
+++ b/components/lib/cascadeselect/cascadeselect.d.ts
@@ -24,6 +24,7 @@ export declare type CascadeSelectPassThroughTransitionType = ReactCSSTransitionP
 export interface CascadeSelectPassThroughMethodOptions {
     props: CascadeSelectProps;
     state: CascadeSelectState;
+    context: CascadeSelectContext;
 }
 
 /**
@@ -34,18 +35,35 @@ export interface CascadeSelectState {
      * Current focused state as a boolean.
      * @defaultValue false
      */
-    focused: boolean;
+    focused?: boolean;
     /**
      * Current overlay visible state as a boolean.
      * @defaultValue false
      */
-    overlayVisible: boolean;
+    overlayVisible?: boolean;
     /**
      * Current overlay attributeSelector state as a string.
      */
-    attributeSelector: string;
+    attributeSelector?: string;
+    /**
+     * For items, this is the state of the item.
+     */
+    selected?: boolean;
+    /**
+     * For items, this is whether it is a group item or not.
+     */
+    grouped?: boolean;
 }
 
+/**
+ * Defines current inline context in CascadeSelect component.
+ */
+export interface CascadeSelectContext extends APIOptions {
+    /**
+     * Label of the currently selected item
+     */
+    label?: string;
+}
 /**
  * Custom passthrough(pt) options.
  * @see {@link CascadeSelectProps.pt}
diff --git a/components/lib/checkbox/Checkbox.js b/components/lib/checkbox/Checkbox.js
index e15b0f122a..dfee79bf72 100644
--- a/components/lib/checkbox/Checkbox.js
+++ b/components/lib/checkbox/Checkbox.js
@@ -1,11 +1,11 @@
 import * as React from 'react';
 import { PrimeReactContext } from '../api/Api';
+import { useHandleStyle } from '../componentbase/ComponentBase';
 import { useMountEffect, useUpdateEffect } from '../hooks/Hooks';
 import { CheckIcon } from '../icons/check';
 import { Tooltip } from '../tooltip/Tooltip';
 import { DomHandler, IconUtils, ObjectUtils, classNames, mergeProps } from '../utils/Utils';
 import { CheckboxBase } from './CheckboxBase';
-import { useHandleStyle } from '../componentbase/ComponentBase';
 
 export const Checkbox = React.memo(
     React.forwardRef((inProps, ref) => {
@@ -37,35 +37,34 @@ export const Checkbox = React.memo(
                 const checkboxClicked = event.target instanceof HTMLDivElement || event.target instanceof HTMLSpanElement || event.target instanceof Object;
                 const isInputToggled = event.target === inputRef.current;
                 const isCheckboxToggled = checkboxClicked && event.target.checked !== checked;
-
-                if (isInputToggled || isCheckboxToggled) {
-                    const value = checked ? props.falseValue : props.trueValue;
-                    const eventData = {
-                        originalEvent: event,
+                const value = checked ? props.falseValue : props.trueValue;
+                const eventData = {
+                    originalEvent: event,
+                    value: props.value,
+                    checked: value,
+                    stopPropagation: () => {
+                        event.stopPropagation();
+                    },
+                    preventDefault: () => {
+                        event.preventDefault();
+                    },
+                    target: {
+                        type: 'checkbox',
+                        name: props.name,
+                        id: props.id,
                         value: props.value,
-                        checked: value,
-                        stopPropagation: () => {
-                            event.stopPropagation();
-                        },
-                        preventDefault: () => {
-                            event.preventDefault();
-                        },
-                        target: {
-                            type: 'checkbox',
-                            name: props.name,
-                            id: props.id,
-                            value: props.value,
-                            checked: value
-                        }
-                    };
-
-                    props.onClick && props.onClick(eventData);
-
-                    // do not continue if the user defined click wants to prevent
-                    if (event.defaultPrevented) {
-                        return;
+                        checked: value
                     }
+                };
 
+                props.onClick && props.onClick(eventData);
+
+                // do not continue if the user defined click wants to prevent
+                if (event.defaultPrevented) {
+                    return;
+                }
+
+                if (isInputToggled || isCheckboxToggled) {
                     props.onChange && props.onChange(eventData);
                 }
 
diff --git a/components/lib/chip/Chip.js b/components/lib/chip/Chip.js
index d7c0e935e6..29fb9af7a1 100644
--- a/components/lib/chip/Chip.js
+++ b/components/lib/chip/Chip.js
@@ -27,7 +27,10 @@ export const Chip = React.memo(
             setVisibleState(false);
 
             if (props.onRemove) {
-                props.onRemove(event);
+                props.onRemove({
+                    originalEvent: event,
+                    value: props.label || props.image || props.icon
+                });
             }
         };
 
diff --git a/components/lib/chip/chip.d.ts b/components/lib/chip/chip.d.ts
index f541f42b31..4aa2816bec 100644
--- a/components/lib/chip/chip.d.ts
+++ b/components/lib/chip/chip.d.ts
@@ -65,6 +65,21 @@ export interface ChipState {
     visible: boolean;
 }
 
+/**
+ * Custom remove event
+ * @event
+ */
+interface ChipRemoveEvent {
+    /**
+     * Browser event
+     */
+    originalEvent: React.SyntheticEvent;
+    /**
+     * Removed item value
+     */
+    value: string;
+}
+
 /**
  * Defines valid properties in Chip component. In addition to these, all properties of HTMLDivElement can be used in this component.
  * @group Properties
@@ -106,9 +121,9 @@ export interface ChipProps extends Omit<React.DetailedHTMLProps<React.HTMLAttrib
     onImageError?(event: React.SyntheticEvent): void;
     /**
      * Callback to invoke when a chip is removed.
-     * @param {React.MouseEvent}  event - Browser event.
+     * * @param {ChipRemoveEvent} event - Custom remove event
      */
-    onRemove?(event: React.MouseEvent<HTMLElement>): void;
+    onRemove?(event: ChipRemoveEvent): void;
     /**
      * Used to get the child elements of the component.
      * @readonly
diff --git a/components/lib/componentbase/ComponentBase.js b/components/lib/componentbase/ComponentBase.js
index 6c1d309154..aeb24e2ed6 100644
--- a/components/lib/componentbase/ComponentBase.js
+++ b/components/lib/componentbase/ComponentBase.js
@@ -1,7 +1,7 @@
 import PrimeReact from '../api/Api';
 import { useMountEffect, useStyle, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks';
 import { mergeProps } from '../utils/MergeProps';
-import { ObjectUtils } from '../utils/Utils';
+import { ObjectUtils, classNames } from '../utils/Utils';
 
 const baseStyle = `
 .p-hidden-accessible {
@@ -520,7 +520,14 @@ export const ComponentBase = {
             const getPTClassValue = (...args) => {
                 const value = getOptionValue(...args);
 
-                return ObjectUtils.isString(value) ? { className: value } : value;
+                if (Array.isArray(value)) return { className: classNames(...value) };
+                if (ObjectUtils.isString(value)) return { className: value };
+
+                if (value?.hasOwnProperty('className') && Array.isArray(value.className)) {
+                    return { className: classNames(...value.className) };
+                }
+
+                return value;
             };
 
             const globalPT = searchInDefaultPT ? (isNestedParam ? _useGlobalPT(getPTClassValue, originalkey, params) : _useDefaultPT(getPTClassValue, originalkey, params)) : undefined;
diff --git a/components/lib/confirmdialog/ConfirmDialog.js b/components/lib/confirmdialog/ConfirmDialog.js
index 918624bfc2..101a64ae0e 100644
--- a/components/lib/confirmdialog/ConfirmDialog.js
+++ b/components/lib/confirmdialog/ConfirmDialog.js
@@ -160,6 +160,7 @@ export const ConfirmDialog = React.memo(
                     icon: getPropValue('acceptIcon'),
                     className: classNames(getPropValue('acceptClassName'), cx('acceptButton')),
                     onClick: accept,
+                    pt: ptm('acceptButton'),
                     unstyled: props.unstyled,
                     __parentMetadata: {
                         parent: metaData
diff --git a/components/lib/datatable/BodyCell.js b/components/lib/datatable/BodyCell.js
index 0b3f3ca351..47be72ff03 100644
--- a/components/lib/datatable/BodyCell.js
+++ b/components/lib/datatable/BodyCell.js
@@ -27,11 +27,10 @@ export const BodyCell = React.memo((props) => {
     const { ptm, ptmo, cx } = props.ptCallbacks;
 
     const getColumnProp = (name) => ColumnBase.getCProp(props.column, name);
-    const getColumnProps = (column) => ColumnBase.getCProps(column);
+    const getColumnProps = () => ColumnBase.getCProps(props.column);
 
     const getColumnPTOptions = (key) => {
-        const cProps = getColumnProps(props.column);
-
+        const cProps = getColumnProps();
         const columnMetaData = {
             props: cProps,
             parent: props.metaData,
@@ -228,7 +227,7 @@ export const BodyCell = React.memo((props) => {
         clearTimeout(tabindexTimeout.current);
         tabindexTimeout.current = setTimeout(() => {
             if (editingState) {
-                const focusableEl = props.editMode === 'cell' ? DomHandler.getFirstFocusableElement(elementRef.current, ':not(.p-cell-editor-key-helper)') : DomHandler.findSingle(elementRef.current, '[data-p-row-editor-save="true"]');
+                const focusableEl = props.editMode === 'cell' ? DomHandler.getFirstFocusableElement(elementRef.current, ':not([data-pc-section="editorkeyhelperlabel"])') : DomHandler.findSingle(elementRef.current, '[data-p-row-editor-save="true"]');
 
                 focusableEl && focusableEl.focus();
             }
diff --git a/components/lib/datatable/DataTable.js b/components/lib/datatable/DataTable.js
index d760c99fd0..97b40c4b25 100644
--- a/components/lib/datatable/DataTable.js
+++ b/components/lib/datatable/DataTable.js
@@ -371,7 +371,7 @@ export const DataTable = React.forwardRef((inProps, ref) => {
 
     const saveColumnWidths = (state) => {
         let widths = [];
-        let headers = DomHandler.find(elementRef.current, '.p-datatable-thead > tr > th');
+        let headers = DomHandler.find(elementRef.current, '[data-pc-section="thead"] > tr > th');
 
         headers.forEach((header) => widths.push(DomHandler.getOuterWidth(header)));
         state.columnWidths = widths.join(',');
@@ -384,15 +384,15 @@ export const DataTable = React.forwardRef((inProps, ref) => {
     const addColumnWidthStyles = (widths) => {
         createStyleElement();
         let innerHTML = '';
-        let selector = `.p-datatable[${attributeSelector.current}] > .p-datatable-wrapper ${isVirtualScrollerDisabled() ? '' : '> .p-virtualscroller'} > .p-datatable-table`;
+        let selector = `[data-pc-name="datatable"][${attributeSelector.current}] > [data-pc-section="wrapper"] ${isVirtualScrollerDisabled() ? '' : '> [data-pc-name="virtualscroller"]'} > [data-pc-section="table"]`;
 
         widths.forEach((width, index) => {
             let style = `width: ${width}px !important; max-width: ${width}px !important`;
 
             innerHTML += `
-                ${selector} > .p-datatable-thead > tr > th:nth-child(${index + 1}),
-                ${selector} > .p-datatable-tbody > tr > td:nth-child(${index + 1}),
-                ${selector} > .p-datatable-tfoot > tr > td:nth-child(${index + 1}) {
+                ${selector} > [data-pc-section="thead"] > tr > th:nth-child(${index + 1}),
+                ${selector} > [data-pc-section="tbody"] > tr > td:nth-child(${index + 1}),
+                ${selector} > [data-pc-section="tfoot"] > tr > td:nth-child(${index + 1}) {
                     ${style}
                 }
             `;
@@ -557,7 +557,7 @@ export const DataTable = React.forwardRef((inProps, ref) => {
                     updateTableWidth(frozenBodyRef.current);
 
                     if (wrapperRef.current) {
-                        updateTableWidth(DomHandler.findSingle(wrapperRef.current, '.p-virtualscroller-content'));
+                        updateTableWidth(DomHandler.findSingle(wrapperRef.current, '[data-pc-name="virtualscroller"] > table > tbody'));
                     }
                 }
             }
@@ -587,7 +587,7 @@ export const DataTable = React.forwardRef((inProps, ref) => {
     const resizeTableCells = (newColumnWidth, nextColumnWidth) => {
         let widths = [];
         let colIndex = DomHandler.index(resizeColumnElement.current);
-        let headers = DomHandler.find(tableRef.current, '.p-datatable-thead > tr > th');
+        let headers = DomHandler.find(tableRef.current, '[data-pc-section="thead"] > tr > th');
 
         headers.forEach((header) => widths.push(DomHandler.getOuterWidth(header)));
 
@@ -595,16 +595,16 @@ export const DataTable = React.forwardRef((inProps, ref) => {
         createStyleElement();
 
         let innerHTML = '';
-        let selector = `.p-datatable[${attributeSelector.current}] > .p-datatable-wrapper ${isVirtualScrollerDisabled() ? '' : '> .p-virtualscroller'} > .p-datatable-table`;
+        let selector = `[data-pc-name="datatable"][${attributeSelector.current}] > [data-pc-section="wrapper"] ${isVirtualScrollerDisabled() ? '' : '> [data-pc-name="virtualscroller"]'} > [data-pc-section="table"]`;
 
         widths.forEach((width, index) => {
             let colWidth = index === colIndex ? newColumnWidth : nextColumnWidth && index === colIndex + 1 ? nextColumnWidth : width;
             let style = `width: ${colWidth}px !important; max-width: ${colWidth}px !important`;
 
             innerHTML += `
-                ${selector} > .p-datatable-thead > tr > th:nth-child(${index + 1}),
-                ${selector} > .p-datatable-tbody > tr > td:nth-child(${index + 1}),
-                ${selector} > .p-datatable-tfoot > tr > td:nth-child(${index + 1}) {
+                 ${selector} > [data-pc-section="thead"] > tr > th:nth-child(${index + 1}),
+                ${selector} > [data-pc-section="tbody"] > tr > td:nth-child(${index + 1}),
+                ${selector} > [data-pc-section="tfoot"] > tr > td:nth-child(${index + 1}) {
                     ${style}
                 }
             `;
@@ -744,7 +744,7 @@ export const DataTable = React.forwardRef((inProps, ref) => {
                 let dragColIndex = columns.findIndex((child) => isSameColumn(child, draggedColumn.current));
                 let dropColIndex = columns.findIndex((child) => isSameColumn(child, column));
                 let widths = [];
-                let headers = DomHandler.find(tableRef.current, '.p-datatable-thead > tr > th');
+                let headers = DomHandler.find(tableRef.current, '[data-pc-section="thead"] > tr > th');
 
                 headers.forEach((header) => widths.push(DomHandler.getOuterWidth(header)));
                 const movedItem = widths.find((items, index) => index === dragColIndex);
@@ -1252,7 +1252,7 @@ export const DataTable = React.forwardRef((inProps, ref) => {
 
     const resetScroll = () => {
         if (wrapperRef.current) {
-            const scrollableContainer = !isVirtualScrollerDisabled() ? DomHandler.findSingle(wrapperRef.current, '.p-virtualscroller') : wrapperRef.current;
+            const scrollableContainer = !isVirtualScrollerDisabled() ? DomHandler.findSingle(wrapperRef.current, '[data-pc-name="virtualscroller"]') : wrapperRef.current;
 
             scrollableContainer.scrollTo(0, 0);
         }
@@ -1342,7 +1342,7 @@ export const DataTable = React.forwardRef((inProps, ref) => {
     };
 
     const closeEditingRows = () => {
-        DomHandler.find(document.body, '.p-row-editor-cancel').forEach((button, index) => {
+        DomHandler.find(document.body, '[data-pc-section="roweditorcancelbuttonprops"]').forEach((button, index) => {
             setTimeout(() => {
                 button.click();
             }, index * 5);
@@ -1966,7 +1966,8 @@ export const DataTable = React.forwardRef((inProps, ref) => {
             id: props.id,
             className: classNames(props.className, ptCallbacks.cx('root', { selectable })),
             style: props.style,
-            'data-scrollselectors': '.p-datatable-wrapper'
+            'data-scrollselectors': '.p-datatable-wrapper',
+            'data-showgridlines': props.showGridlines
         },
         DataTableBase.getOtherProps(props),
         ptCallbacks.ptm('root')
diff --git a/components/lib/datatable/TableBody.js b/components/lib/datatable/TableBody.js
index 079013ea10..0a43916d7a 100644
--- a/components/lib/datatable/TableBody.js
+++ b/components/lib/datatable/TableBody.js
@@ -442,11 +442,11 @@ export const TableBody = React.memo(
 
             if (!allowCellSelection() && props.selectionAutoFocus) {
                 if (isCheckboxSelectionModeInColumn) {
-                    const checkbox = DomHandler.findSingle(target, 'td.p-selection-column .p-checkbox-box');
+                    const checkbox = DomHandler.findSingle(target, 'td[data-p-selection-column="true"] [data-pc-section="checkbox"]');
 
                     checkbox && checkbox.focus();
                 } else if (isRadioSelectionModeInColumn) {
-                    const radio = DomHandler.findSingle(target, 'td.p-selection-column input[type="radio"]');
+                    const radio = DomHandler.findSingle(target, 'td[data-p-selection-column="true"] input[type="radio"]');
 
                     radio && radio.focus();
                 }
diff --git a/components/lib/dialog/Dialog.js b/components/lib/dialog/Dialog.js
index 593748f237..cfb02ed60f 100644
--- a/components/lib/dialog/Dialog.js
+++ b/components/lib/dialog/Dialog.js
@@ -396,8 +396,8 @@ export const Dialog = React.forwardRef((inProps, ref) => {
         for (let breakpoint in props.breakpoints) {
             innerHTML += `
                 @media screen and (max-width: ${breakpoint}) {
-                    .p-dialog[${attributeSelector.current}] {
-                        width: ${props.breakpoints[breakpoint]};
+                     [data-pc-name="dialog"][${attributeSelector.current}] {
+                        width: ${props.breakpoints[breakpoint]} !important;
                     }
                 }
             `;
@@ -406,15 +406,26 @@ export const Dialog = React.forwardRef((inProps, ref) => {
         styleElement.current.innerHTML = innerHTML;
     };
 
+    const destroyStyle = () => {
+        styleElement.current = DomHandler.removeInlineStyle(styleElement.current);
+    };
+
     useMountEffect(() => {
         if (props.visible) {
             setMaskVisibleState(true);
         }
+    });
 
+    React.useEffect(() => {
         if (props.breakpoints) {
             createStyle();
         }
-    });
+
+        return () => {
+            destroyStyle();
+        };
+        // eslint-disable-next-line react-hooks/exhaustive-deps
+    }, [props.breakpoints]);
 
     useUpdateEffect(() => {
         if (props.visible && !maskVisibleState) {
diff --git a/components/lib/dropdown/Dropdown.js b/components/lib/dropdown/Dropdown.js
index 5865b438ac..9be0ed8be8 100644
--- a/components/lib/dropdown/Dropdown.js
+++ b/components/lib/dropdown/Dropdown.js
@@ -3,13 +3,13 @@ import PrimeReact, { FilterService, PrimeReactContext } from '../api/Api';
 import { useHandleStyle } from '../componentbase/ComponentBase';
 import { useMountEffect, useOverlayListener, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks';
 import { ChevronDownIcon } from '../icons/chevrondown';
+import { SpinnerIcon } from '../icons/spinner';
 import { TimesIcon } from '../icons/times';
 import { OverlayService } from '../overlayservice/OverlayService';
 import { Tooltip } from '../tooltip/Tooltip';
 import { DomHandler, IconUtils, ObjectUtils, ZIndexUtils, classNames, mergeProps } from '../utils/Utils';
 import { DropdownBase } from './DropdownBase';
 import { DropdownPanel } from './DropdownPanel';
-import { SpinnerIcon } from '../icons/spinner';
 
 export const Dropdown = React.memo(
     React.forwardRef((inProps, ref) => {
@@ -741,7 +741,7 @@ export const Dropdown = React.memo(
                     onBlur: onInputBlur,
                     onKeyDown: onInputKeyDown,
                     disabled: props.disabled,
-                    tabIndex: props.tabIndex,
+                    tabIndex: props.tabIndex || 0,
                     ...ariaProps
                 },
                 ptm('input')
@@ -771,6 +771,7 @@ export const Dropdown = React.memo(
                         onInput: onEditableInputChange,
                         onFocus: onEditableInputFocus,
                         onBlur: onInputBlur,
+                        tabIndex: props.tabIndex || 0,
                         'aria-haspopup': 'listbox',
                         ...ariaProps
                     },
@@ -783,7 +784,8 @@ export const Dropdown = React.memo(
                 const inputProps = mergeProps(
                     {
                         ref: inputRef,
-                        className: cx('input', { label })
+                        className: cx('input', { label }),
+                        tabIndex: '-1'
                     },
                     ptm('input')
                 );
diff --git a/components/lib/hooks/useDebounce.js b/components/lib/hooks/useDebounce.js
index 29ba443edc..1233441ec9 100644
--- a/components/lib/hooks/useDebounce.js
+++ b/components/lib/hooks/useDebounce.js
@@ -1,16 +1,31 @@
 import * as React from 'react';
-import { useTimeout } from './useTimeout';
+import { useMountEffect, useUnmountEffect } from './Hooks';
 
 export const useDebounce = (initialValue, delay) => {
     const [inputValue, setInputValue] = React.useState(initialValue);
     const [debouncedValue, setDebouncedValue] = React.useState(initialValue);
-    const timeout = useTimeout(
-        () => {
+    const mountedRef = React.useRef(false);
+    const timeoutRef = React.useRef(null);
+    const cancelTimer = () => window.clearTimeout(timeoutRef.current);
+
+    useMountEffect(() => {
+        mountedRef.current = true;
+    });
+
+    useUnmountEffect(() => {
+        cancelTimer();
+    });
+
+    React.useEffect(() => {
+        if (!mountedRef.current) {
+            return;
+        }
+
+        cancelTimer();
+        timeoutRef.current = window.setTimeout(() => {
             setDebouncedValue(inputValue);
-        },
-        delay,
-        inputValue !== debouncedValue
-    );
+        }, delay);
+    }, [inputValue, delay]);
 
     return [inputValue, debouncedValue, setInputValue];
 };
diff --git a/components/lib/image/Image.js b/components/lib/image/Image.js
index 811a44f314..61cc1365c8 100644
--- a/components/lib/image/Image.js
+++ b/components/lib/image/Image.js
@@ -30,6 +30,8 @@ export const Image = React.memo(
         const previewRef = React.useRef(null);
         const previewClick = React.useRef(false);
         const previewButton = React.useRef(null);
+        const zoomOutDisabled = scaleState <= 0.5;
+        const zoomInDisabled = scaleState >= 1.5;
 
         useOnEscapeKey(maskRef, props.closeOnEscape, () => {
             hide();
@@ -122,12 +124,20 @@ export const Image = React.memo(
         };
 
         const zoomIn = () => {
-            setScaleState((prevScale) => prevScale + 0.1);
+            setScaleState((prevScale) => {
+                if (zoomInDisabled) return prevScale;
+
+                return prevScale + 0.1;
+            });
             previewClick.current = true;
         };
 
         const zoomOut = () => {
-            setScaleState((prevScale) => prevScale - 0.1);
+            setScaleState((prevScale) => {
+                if (zoomOutDisabled) return prevScale;
+
+                return prevScale - 0.1;
+            });
             previewClick.current = true;
         };
 
@@ -179,8 +189,6 @@ export const Image = React.memo(
 
         const createElement = () => {
             const { downloadable, alt, crossOrigin, referrerPolicy, useMap, loading } = props;
-            const zoomOutDisabled = scaleState <= 0.5;
-            const zoomInDisabled = scaleState >= 1.5;
             const downloadIconProps = mergeProps(ptm('downloadIcon'));
             const rotateRightIconProps = mergeProps(ptm('rotateRightIcon'));
             const rotateLeftIconProps = mergeProps(ptm('rotateLeftIcon'));
diff --git a/components/lib/inplace/Inplace.js b/components/lib/inplace/Inplace.js
index a14b1b517d..27739e3b2e 100644
--- a/components/lib/inplace/Inplace.js
+++ b/components/lib/inplace/Inplace.js
@@ -2,6 +2,7 @@ import * as React from 'react';
 import { localeOption, PrimeReactContext } from '../api/Api';
 import { Button } from '../button/Button';
 import { useHandleStyle } from '../componentbase/ComponentBase';
+import { useUpdateEffect } from '../hooks/Hooks';
 import { TimesIcon } from '../icons/times';
 import { classNames, IconUtils, mergeProps, ObjectUtils } from '../utils/Utils';
 import { InplaceBase } from './InplaceBase';
@@ -44,6 +45,10 @@ export const Inplace = React.forwardRef((inProps, ref) => {
     };
 
     const close = (event) => {
+        if (props.disabled) {
+            return;
+        }
+
         props.onClose && props.onClose(event);
 
         if (props.onToggle) {
@@ -138,6 +143,10 @@ export const Inplace = React.forwardRef((inProps, ref) => {
         getElement: () => elementRef.current
     }));
 
+    useUpdateEffect(() => {
+        props.active ? open(null) : close(null);
+    }, [props.active]);
+
     const children = createChildren();
 
     const rootProps = mergeProps(
diff --git a/components/lib/inputnumber/InputNumber.js b/components/lib/inputnumber/InputNumber.js
index e73cc328a7..0c60ae2aa4 100644
--- a/components/lib/inputnumber/InputNumber.js
+++ b/components/lib/inputnumber/InputNumber.js
@@ -58,7 +58,8 @@ export const InputNumber = React.memo(
                 currencyDisplay: props.currencyDisplay,
                 useGrouping: props.useGrouping,
                 minimumFractionDigits: props.minFractionDigits,
-                maximumFractionDigits: props.maxFractionDigits
+                maximumFractionDigits: props.maxFractionDigits,
+                roundingMode: props.roundingMode
             };
         };
 
@@ -108,7 +109,8 @@ export const InputNumber = React.memo(
                     currency: props.currency,
                     currencyDisplay: props.currencyDisplay,
                     minimumFractionDigits: 0,
-                    maximumFractionDigits: 0
+                    maximumFractionDigits: 0,
+                    roundingMode: props.roundingMode
                 });
 
                 return new RegExp(`[${formatter.format(1).replace(/\s/g, '').replace(_numeral.current, '').replace(_group.current, '')}]`, 'g');
@@ -138,7 +140,8 @@ export const InputNumber = React.memo(
                     currency: props.currency,
                     currencyDisplay: props.currencyDisplay,
                     minimumFractionDigits: 0,
-                    maximumFractionDigits: 0
+                    maximumFractionDigits: 0,
+                    roundingMode: props.roundingMode
                 });
 
                 suffixChar.current = formatter.format(1).split('1')[1];
diff --git a/components/lib/inputnumber/InputNumberBase.js b/components/lib/inputnumber/InputNumberBase.js
index c4e17d0dbc..b2d50d3b28 100644
--- a/components/lib/inputnumber/InputNumberBase.js
+++ b/components/lib/inputnumber/InputNumberBase.js
@@ -171,6 +171,7 @@ export const InputNumberBase = ComponentBase.extend({
         prefix: null,
         readOnly: false,
         required: false,
+        roundingMode: undefined,
         showButtons: false,
         size: null,
         step: 1,
diff --git a/components/lib/inputnumber/inputnumber.d.ts b/components/lib/inputnumber/inputnumber.d.ts
index 4497b2c80f..ef19e8b7a8 100644
--- a/components/lib/inputnumber/inputnumber.d.ts
+++ b/components/lib/inputnumber/inputnumber.d.ts
@@ -16,6 +16,8 @@ import { TooltipOptions } from '../tooltip/tooltipoptions';
 import { FormEvent } from '../ts-helpers';
 import { IconType, PassThroughType } from '../utils/utils';
 
+export declare type RoundingMode = 'ceil' | 'floor' | 'expand' | 'trunc' | 'halfCeil' | 'halfFloor' | 'halfExpand' | 'halfTrunc' | 'halfEven';
+
 export declare type InputNumberPassThroughType<T> = PassThroughType<T, InputNumberPassThroughMethodOptions>;
 
 /**
@@ -190,6 +192,11 @@ export interface InputNumberProps extends Omit<React.DetailedHTMLProps<React.HTM
      * the default for currency formatting is the larger of minimumFractionDigits and the number of minor unit digits provided by the [ISO 4217 currency code list](https://www.six-group.com/en/products-services/financial-information/data-standards.html#scrollTo=maintenance-agency) (2 if the list doesn't provide that information).
      */
     maxFractionDigits?: number | undefined;
+    /**
+     * How decimals should be rounded. [further information](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#roundingmode).
+     * @defaultValue halfExpand
+     */
+    roundingMode?: RoundingMode;
     /**
      * Name of the input element.
      */
diff --git a/components/lib/inputswitch/InputSwitch.js b/components/lib/inputswitch/InputSwitch.js
index 85cc44a969..9aa8849354 100644
--- a/components/lib/inputswitch/InputSwitch.js
+++ b/components/lib/inputswitch/InputSwitch.js
@@ -1,10 +1,10 @@
 import * as React from 'react';
+import { PrimeReactContext } from '../api/Api';
+import { useHandleStyle } from '../componentbase/ComponentBase';
 import { useMountEffect } from '../hooks/Hooks';
 import { Tooltip } from '../tooltip/Tooltip';
 import { classNames, DomHandler, mergeProps, ObjectUtils } from '../utils/Utils';
 import { InputSwitchBase } from './InputSwitchBase';
-import { PrimeReactContext } from '../api/Api';
-import { useHandleStyle } from '../componentbase/ComponentBase';
 
 export const InputSwitch = React.memo(
     React.forwardRef((inProps, ref) => {
@@ -95,6 +95,7 @@ export const InputSwitch = React.memo(
                 role: 'checkbox',
                 'aria-checked': checked
             },
+            otherProps,
             ptm('root')
         );
         const hiddenInputWrapperProps = mergeProps(
diff --git a/components/lib/listbox/ListBoxItem.js b/components/lib/listbox/ListBoxItem.js
index da2f667340..e5a5b34eff 100644
--- a/components/lib/listbox/ListBoxItem.js
+++ b/components/lib/listbox/ListBoxItem.js
@@ -3,6 +3,7 @@ import { Ripple } from '../ripple/Ripple';
 import { DomHandler, mergeProps, ObjectUtils } from '../utils/Utils';
 
 export const ListBoxItem = React.memo((props) => {
+    const [focusedState, setFocusedState] = React.useState(false);
     const {
         ptCallbacks: { ptm, cx }
     } = props;
@@ -12,11 +13,20 @@ export const ListBoxItem = React.memo((props) => {
             hostName: props.hostName,
             context: {
                 selected: props.selected,
-                disabled: props.disabled
+                disabled: props.disabled,
+                focused: focusedState
             }
         });
     };
 
+    const onFocus = (event) => {
+        setFocusedState(true);
+    };
+
+    const onBlur = (event) => {
+        setFocusedState(false);
+    };
+
     const onClick = (event) => {
         if (props.onClick) {
             props.onClick({
@@ -91,6 +101,8 @@ export const ListBoxItem = React.memo((props) => {
             onClick: onClick,
             onTouchEnd: onTouchEnd,
             onKeyDown: onKeyDown,
+            onFocus: onFocus,
+            onBlur: onBlur,
             tabIndex: '-1',
             'aria-label': props.label,
             key: props.label,
diff --git a/components/lib/listbox/listbox.d.ts b/components/lib/listbox/listbox.d.ts
index ed1d16e4dd..bdc0e0010c 100755
--- a/components/lib/listbox/listbox.d.ts
+++ b/components/lib/listbox/listbox.d.ts
@@ -8,14 +8,14 @@
  *
  */
 import * as React from 'react';
+import { ComponentHooks } from '../componentbase/componentbase';
+import { InputTextPassThroughOptions } from '../inputtext/inputtext';
+import { PassThroughOptions } from '../passthrough';
 import { SelectItemOptionsType } from '../selectitem/selectitem';
 import { TooltipPassThroughOptions } from '../tooltip/tooltip';
 import { TooltipOptions } from '../tooltip/tooltipoptions';
 import { IconType, PassThroughType } from '../utils/utils';
 import { VirtualScroller, VirtualScrollerPassThroughOptions, VirtualScrollerProps } from '../virtualscroller';
-import { InputTextPassThroughOptions } from '../inputtext/inputtext';
-import { PassThroughOptions } from '../passthrough';
-import { ComponentHooks } from '../componentbase/componentbase';
 
 export declare type ListBoxPassThroughType<T> = PassThroughType<T, ListBoxPassThroughMethodOptions>;
 
@@ -109,6 +109,11 @@ export interface ListBoxContext {
      * @defaultValue false
      */
     selected: boolean;
+    /**
+     * Current focused state of the item as a boolean.
+     * @defaultValue false
+     */
+    focused: boolean;
     /**
      * Current disabled state of the item as a boolean.
      * @defaultValue false
diff --git a/components/lib/messages/Messages.js b/components/lib/messages/Messages.js
index 41e4874357..7cc046c078 100644
--- a/components/lib/messages/Messages.js
+++ b/components/lib/messages/Messages.js
@@ -103,7 +103,7 @@ export const Messages = React.memo(
 
         const transitionProps = mergeProps(
             {
-                classNames: ptCallbacks.cx('transition'),
+                classNames: ptCallbacks.cx('uimessage.transition'),
                 unmountOnExit: true,
                 timeout: { enter: 300, exit: 300 },
                 options: props.transitionOptions
diff --git a/components/lib/multiselect/MultiSelectBase.js b/components/lib/multiselect/MultiSelectBase.js
index 2e5397fded..2746e9eff3 100644
--- a/components/lib/multiselect/MultiSelectBase.js
+++ b/components/lib/multiselect/MultiSelectBase.js
@@ -260,6 +260,7 @@ export const MultiSelectBase = ComponentBase.extend({
         resetFilterOnHide: false,
         scrollHeight: '200px',
         selectAll: false,
+        selectAllLabel: null,
         selectedItemTemplate: null,
         selectedItemsLabel: '{0} items selected',
         selectionLimit: null,
diff --git a/components/lib/multiselect/MultiSelectHeader.js b/components/lib/multiselect/MultiSelectHeader.js
index 3921b27679..9145c7738f 100644
--- a/components/lib/multiselect/MultiSelectHeader.js
+++ b/components/lib/multiselect/MultiSelectHeader.js
@@ -116,12 +116,19 @@ export const MultiSelectHeader = React.memo((props) => {
         getPTOptions('headerCheckboxIcon')
     );
 
+    const headerCheckboxContainerProps = mergeProps(
+        {
+            className: cx('headerCheckboxContainer')
+        },
+        getPTOptions('headerCheckboxContainer')
+    );
+
     const checkedIcon = props.itemCheckboxIcon || <CheckIcon {...headerCheckboxIconProps} />;
     const itemCheckboxIcon = IconUtils.getJSXIcon(checkedIcon, { ...headerCheckboxIconProps }, { selected: props.selected });
 
     const checkboxElement = props.showSelectAll && (
-        <div className="p-multiselect-select-all">
-            <Checkbox id={selectAllId} checked={props.selectAll} onChange={onSelectAll} role="checkbox" aria-checked={props.selectAll} icon={itemCheckboxIcon} pt={ptm('headercheckbox')} unstyled={isUnstyled()} />
+        <div {...headerCheckboxContainerProps}>
+            <Checkbox id={selectAllId} checked={props.selectAll} onChange={onSelectAll} role="checkbox" aria-checked={props.selectAll} icon={itemCheckboxIcon} pt={ptm('headerCheckbox')} unstyled={isUnstyled()} />
             {!props.filter && <label {...headerSelectAllLabelProps}>{props.selectAllLabel}</label>}
         </div>
     );
diff --git a/components/lib/multiselect/MultiSelectItem.js b/components/lib/multiselect/MultiSelectItem.js
index 9339c8694b..1ee1abe6f2 100644
--- a/components/lib/multiselect/MultiSelectItem.js
+++ b/components/lib/multiselect/MultiSelectItem.js
@@ -4,17 +4,28 @@ import { Ripple } from '../ripple/Ripple';
 import { IconUtils, ObjectUtils, classNames, mergeProps } from '../utils/Utils';
 
 export const MultiSelectItem = React.memo((props) => {
+    const [focusedState, setFocusedState] = React.useState(false);
     const { ptm, cx } = props;
 
     const getPTOptions = (key) => {
         return ptm(key, {
             hostName: props.hostName,
             context: {
-                selected: props.selected
+                selected: props.selected,
+                disabled: props.disabled,
+                focused: focusedState
             }
         });
     };
 
+    const onFocus = (event) => {
+        setFocusedState(true);
+    };
+
+    const onBlur = (event) => {
+        setFocusedState(false);
+    };
+
     const onClick = (event) => {
         if (props.onClick) {
             props.onClick({
@@ -69,8 +80,10 @@ export const MultiSelectItem = React.memo((props) => {
             className: classNames(props.className, props.option.className, cx('item', { itemProps: props })),
             style: props.style,
             onClick: onClick,
-            tabIndex: tabIndex,
             onKeyDown: onKeyDown,
+            onFocus: onFocus,
+            onBlur: onBlur,
+            tabIndex: tabIndex,
             role: 'option',
             'aria-selected': props.selected,
             'data-p-highlight': props.selected,
diff --git a/components/lib/multiselect/multiselect.d.ts b/components/lib/multiselect/multiselect.d.ts
index 273b31037e..6280c61553 100644
--- a/components/lib/multiselect/multiselect.d.ts
+++ b/components/lib/multiselect/multiselect.d.ts
@@ -92,6 +92,10 @@ export interface MultiSelectPassThroughOptions {
      * Uses to pass attributes to the header checkbox's DOM element.
      */
     headerCheckbox?: CheckboxPassThroughOptions;
+    /**
+     * Uses to pass attributes to the header checkbox's container DOM element.
+     */
+    headerCheckboxContainer?: MultiSelectPassThroughType<React.HTMLAttributes<HTMLDivElement>>;
     /**
      * Uses to pass attributes to the header checkbox icon's DOM element.
      */
diff --git a/components/lib/passthrough/tailwind/index.js b/components/lib/passthrough/tailwind/index.js
index f8c4179374..8676c40446 100644
--- a/components/lib/passthrough/tailwind/index.js
+++ b/components/lib/passthrough/tailwind/index.js
@@ -396,6 +396,7 @@ const Tailwind = {
                 'dark:border dark:border-blue-900/40 dark:bg-gray-900  dark:text-white/80'
             )
         },
+        closeButton: 'flex items-center justify-center overflow-hidden absolute top-0 right-0 w-6 h-6',
         content: 'p-5 items-center flex',
         transition: TRANSITIONS.overlay
     },
@@ -492,10 +493,10 @@ const Tailwind = {
         },
         arrow: ({ context }) => ({
             className: classNames('absolute w-0 h-0 border-transparent border-solid', {
-                '-m-t-1 border-y-[0.25rem] border-r-[0.25rem] border-l-0 border-r-gray-600': context.right,
-                '-m-t-1 border-y-[0.25rem] border-l-[0.25rem] border-r-0 border-l-gray-600': context.left,
-                '-m-l-1 border-x-[0.25rem] border-t-[0.25rem] border-b-0 border-t-gray-600': context.top,
-                '-m-l-1 border-x-[0.25rem] border-b-[0.25rem] border-t-0 border-b-gray-600': context.bottom
+                '-mt-1 border-y-[0.25rem] border-r-[0.25rem] border-l-0 border-r-gray-600': context.right,
+                '-mt-1 border-y-[0.25rem] border-l-[0.25rem] border-r-0 border-l-gray-600': context.left,
+                '-ml-1 border-x-[0.25rem] border-t-[0.25rem] border-b-0 border-t-gray-600': context.top,
+                '-ml-1 border-x-[0.25rem] border-b-[0.25rem] border-t-0 border-b-gray-600': context.bottom
             })
         }),
         text: {
@@ -697,6 +698,14 @@ const Tailwind = {
                 'mt-2 order-2': props.iconPos == 'bottom' && props.label != null
             })
         }),
+        loadingIcon: ({ props }) => ({
+            className: classNames('mx-0', {
+                'mr-2': props.loading && props.iconPos == 'left' && props.label != null,
+                'ml-2 order-1': props.loading && props.iconPos == 'right' && props.label != null,
+                'mb-2': props.loading && props.iconPos == 'top' && props.label != null,
+                'mt-2 order-2': props.loading && props.iconPos == 'bottom' && props.label != null
+            })
+        }),
         badge: ({ props }) => ({
             className: classNames({ 'ml-2 w-4 h-4 leading-none flex items-center justify-center': props.badge })
         })
@@ -845,13 +854,12 @@ const Tailwind = {
         sublist: {
             className: classNames('block absolute left-full top-0', 'min-w-full z-10', 'py-3 bg-white dark:bg-gray-900 border-0 shadow-md')
         },
-        item: {
-            className: classNames(
-                'cursor-pointer font-normal whitespace-nowrap',
-                'm-0 border-0 bg-transparent transition-shadow rounded-none',
-                'text-gray-700 dark:text-white/80 hover:text-gray-700 dark:hover:text-white/80 hover:bg-gray-200 dark:hover:bg-gray-800/80'
-            )
-        },
+        item: ({ state }) => ({
+            className: classNames('cursor-pointer font-normal whitespace-nowrap', 'm-0 border-0 bg-transparent transition-shadow rounded-none', {
+                'text-gray-700 hover:text-gray-700 hover:bg-gray-200 dark:text-white/80 dark:hover:text-white/80 dark:hover:bg-gray-800/80': !state.selected,
+                'bg-blue-50 text-blue-700 dark:bg-blue-300 dark:text-white/80': state.selected
+            })
+        }),
         content: {
             className: classNames('flex items-center overflow-hidden relative', 'py-3 px-5')
         },
@@ -974,14 +982,14 @@ const Tailwind = {
         transition: TRANSITIONS.overlay
     },
     togglebutton: {
-        root: ({ props, context }) => ({
+        root: ({ props, state }) => ({
             className: classNames(
                 'inline-flex cursor-pointer select-none items-center align-bottom text-center overflow-hidden relative',
                 'px-4 py-3 rounded-md text-base w-36',
                 'border transition duration-200 ease-in-out',
-                // {
-                //     'outline-none outline-offset-0 shadow-[0_0_0_0.2rem_rgba(191,219,254,1)] dark:shadow-[0_0_0_0.2rem_rgba(147,197,253,0.5)]': context.focused
-                // },
+                {
+                    'outline-none outline-offset-0 shadow-[0_0_0_0.2rem_rgba(191,219,254,1)] dark:shadow-[0_0_0_0.2rem_rgba(147,197,253,0.5)]': state.focused
+                },
                 {
                     'bg-white dark:bg-gray-900 border-gray-300 dark:border-blue-900/40 text-gray-700 dark:text-white/80 hover:bg-gray-100 dark:hover:bg-gray-800/80 hover:border-gray-300 dark:hover:bg-gray-800/70 hover:text-gray-700 dark:hover:text-white/80':
                         !props.checked,
@@ -1254,14 +1262,14 @@ const Tailwind = {
                 'bg-blue-50 text-blue-700 dark:bg-blue-300 dark:text-white/80': !context.focused && context.selected
             })
         }),
-        itemgroup: {
+        itemGroup: {
             className: classNames('m-0 p-3 text-gray-800 bg-white font-bold', 'dark:bg-gray-900 dark:text-white/80', 'cursor-auto')
         },
         header: {
             className: classNames('p-3 border-b border-gray-300 text-gray-700 bg-gray-100 mt-0 rounded-tl-lg rounded-tr-lg', 'dark:bg-gray-800 dark:text-white/80 dark:border-blue-900/40')
         },
-        filtercontainer: 'relative',
-        filterinput: {
+        filterContainer: 'relative',
+        filterInput: {
             root: {
                 className: classNames(
                     'pr-7 -mr-7',
@@ -1272,7 +1280,7 @@ const Tailwind = {
                 )
             }
         },
-        filtericon: '-mt-2 absolute top-1/2'
+        filterIcon: '-mt-2 absolute top-1/2'
     },
     mention: {
         root: 'relative',
@@ -1310,18 +1318,20 @@ const Tailwind = {
         headerCheckboxContainer: {
             className: classNames('inline-flex cursor-pointer select-none align-bottom relative', 'mr-2', 'w-6 h-6')
         },
-        headerCheckbox: ({ context }) => ({
-            className: classNames(
-                'flex items-center justify-center',
-                'border-2 w-6 h-6 text-gray-600 dark:text-white/70 rounded-lg transition-colors duration-200',
-                'hover:border-blue-500 focus:outline-none focus:outline-offset-0 focus:shadow-[0_0_0_0.2rem_rgba(191,219,254,1)] dark:focus:shadow-[0_0_0_0.2rem_rgba(147,197,253,0.5)]',
-                {
-                    'border-gray-300 dark:border-blue-900/40 bg-white dark:bg-gray-900': !context?.selected,
-                    'border-blue-500 bg-blue-500': context?.selected
-                }
-            )
-        }),
-        headercheckboxicon: 'w-4 h-4 transition-all duration-200 text-white text-base',
+        headerCheckbox: {
+            root: ({ props }) => ({
+                className: classNames(
+                    'flex items-center justify-center',
+                    'border-2 w-6 h-6 text-gray-600 dark:text-white/70 rounded-lg transition-colors duration-200',
+                    'hover:border-blue-500 focus:outline-none focus:outline-offset-0 focus:shadow-[0_0_0_0.2rem_rgba(191,219,254,1)] dark:focus:shadow-[0_0_0_0.2rem_rgba(147,197,253,0.5)]',
+                    {
+                        'border-gray-300 dark:border-blue-900/40 bg-white dark:bg-gray-900': !props?.checked,
+                        'border-blue-500 bg-blue-500': props?.checked
+                    }
+                )
+            })
+        },
+        headerCheckboxIcon: 'w-4 h-4 transition-all duration-200 text-white text-base',
         closeButton: {
             className: classNames(
                 'flex items-center justify-center overflow-hidden relative',
@@ -1357,22 +1367,24 @@ const Tailwind = {
                 }
             )
         }),
-        checkboxicon: 'w-4 h-4 transition-all duration-200 text-white text-base',
-        itemgroup: {
+        checkboxIcon: 'w-4 h-4 transition-all duration-200 text-white text-base',
+        itemGroup: {
             className: classNames('m-0 p-3 text-gray-800 bg-white font-bold', 'dark:bg-gray-900 dark:text-white/80', 'cursor-auto')
         },
-        filtercontainer: 'relative',
-        filterinput: {
-            className: classNames(
-                'pr-7 -mr-7',
-                'w-full',
-                'font-sans text-base text-gray-700 bg-white py-3 px-3 border border-gray-300 transition duration-200 rounded-lg appearance-none',
-                'dark:bg-gray-900 dark:border-blue-900/40 dark:hover:border-blue-300 dark:text-white/80',
-                'hover:border-blue-500 focus:outline-none focus:outline-offset-0 focus:shadow-[0_0_0_0.2rem_rgba(191,219,254,1)] dark:focus:shadow-[0_0_0_0.2rem_rgba(147,197,253,0.5)]'
-            )
+        filterContainer: 'relative',
+        filterInput: {
+            root: {
+                className: classNames(
+                    'pr-7 -mr-7',
+                    'w-full',
+                    'font-sans text-base text-gray-700 bg-white py-3 px-3 border border-gray-300 transition duration-200 rounded-lg appearance-none',
+                    'dark:bg-gray-900 dark:border-blue-900/40 dark:hover:border-blue-300 dark:text-white/80',
+                    'hover:border-blue-500 focus:outline-none focus:outline-offset-0 focus:shadow-[0_0_0_0.2rem_rgba(191,219,254,1)] dark:focus:shadow-[0_0_0_0.2rem_rgba(147,197,253,0.5)]'
+                )
+            }
         },
-        filtericon: '-mt-2 absolute top-1/2',
-        clearicon: 'text-gray-500 right-12 -mt-2 absolute top-1/2',
+        filterIcon: '-mt-2 absolute top-1/2',
+        clearIcon: 'text-gray-500 right-12 -mt-2 absolute top-1/2',
         transition: TRANSITIONS.overlay
     },
     multistatecheckbox: {
@@ -1451,7 +1463,7 @@ const Tailwind = {
                 'focus:outline-offset-0 focus:shadow-[0_0_0_0.2rem_rgba(191,219,254,1)] hover:border-blue-500 focus:outline-none dark:focus:shadow-[0_0_0_0.2rem_rgba(147,197,253,0.5)]'
             )
         },
-        inputtoken: {
+        inputToken: {
             className: classNames('py-0.375rem px-0', 'flex-1 inline-flex')
         },
         input: ({ props }) => ({
@@ -1486,7 +1498,7 @@ const Tailwind = {
                 'bg-blue-50 text-blue-700 dark:bg-blue-300 dark:text-white/80': !context.focused && context.selected
             })
         }),
-        itemgroup: {
+        itemGroup: {
             className: classNames('m-0 p-3 text-gray-800 bg-white font-bold', 'dark:bg-gray-900 dark:text-white/80', 'cursor-auto')
         },
         transition: TRANSITIONS.overlay
@@ -1506,7 +1518,7 @@ const Tailwind = {
             )
         },
 
-        inputtoken: {
+        inputToken: {
             className: classNames('py-1.5 px-0', 'flex flex-1 inline-flex')
         },
         input: {
@@ -3152,7 +3164,7 @@ const Tailwind = {
                     context.sorted ? 'bg-blue-50 text-blue-700' : 'bg-slate-50 text-slate-700', // Sort
                     context.sorted ? 'dark:text-white/80 dark:bg-blue-300' : 'dark:text-white/80 dark:bg-gray-900', // Dark Mode
                     {
-                        'sticky z-[1]': props.frozen || props.frozen === '', // Frozen Columns
+                        'sticky z-[1]': props && (props.frozen || props.frozen === ''), // Frozen Columns
                         'border-x border-y': context?.showGridlines,
                         'overflow-hidden space-nowrap border-y relative bg-clip-padding': context.resizable // Resizable
                     }
@@ -3165,7 +3177,7 @@ const Tailwind = {
                     context?.size === 'small' ? 'p-2' : context?.size === 'large' ? 'p-5' : 'p-4', // Size
                     'dark:text-white/80 dark:border-blue-900/40', // Dark Mode
                     {
-                        'sticky bg-inherit': props?.frozen || props?.frozen === '', // Frozen Columns
+                        'sticky bg-inherit': props && (props.frozen || props.frozen === ''), // Frozen Columns
                         'border-x border-y': context.showGridlines
                     }
                 )
diff --git a/components/lib/radiobutton/RadioButton.js b/components/lib/radiobutton/RadioButton.js
index 8b065e2ed2..db8b1c0da7 100644
--- a/components/lib/radiobutton/RadioButton.js
+++ b/components/lib/radiobutton/RadioButton.js
@@ -1,10 +1,10 @@
 import * as React from 'react';
 import { PrimeReactContext } from '../api/Api';
+import { useHandleStyle } from '../componentbase/ComponentBase';
 import { useMountEffect } from '../hooks/Hooks';
 import { Tooltip } from '../tooltip/Tooltip';
 import { DomHandler, ObjectUtils, classNames, mergeProps } from '../utils/Utils';
 import { RadioButtonBase } from './RadioButtonBase';
-import { useHandleStyle } from '../componentbase/ComponentBase';
 
 export const RadioButton = React.memo(
     React.forwardRef((inProps, ref) => {
@@ -38,36 +38,36 @@ export const RadioButton = React.memo(
                 const radioClicked = event.target instanceof HTMLDivElement;
                 const inputClicked = event.target === inputRef.current;
                 const isInputToggled = inputClicked && event.target.checked !== checked;
-                const isRadioToggled = radioClicked && (DomHandler.isAttributeEquals(elementRef.current, 'data-p-checked', true) === checked ? !checked : false);
-
-                if (isInputToggled || isRadioToggled) {
-                    const value = !checked;
-                    const eventData = {
-                        originalEvent: event,
+                const isRadioToggled = radioClicked && (DomHandler.hasClass(elementRef.current, 'p-radiobutton-checked') === checked ? !checked : false);
+                const value = !checked;
+
+                const eventData = {
+                    originalEvent: event,
+                    value: props.value,
+                    checked: value,
+                    stopPropagation: () => {
+                        event.stopPropagation();
+                    },
+                    preventDefault: () => {
+                        event.preventDefault();
+                    },
+                    target: {
+                        type: 'radio',
+                        name: props.name,
+                        id: props.id,
                         value: props.value,
-                        checked: value,
-                        stopPropagation: () => {
-                            event.stopPropagation();
-                        },
-                        preventDefault: () => {
-                            event.preventDefault();
-                        },
-                        target: {
-                            type: 'radio',
-                            name: props.name,
-                            id: props.id,
-                            value: props.value,
-                            checked: value
-                        }
-                    };
-
-                    props.onClick && props.onClick(eventData);
-
-                    // do not continue if the user defined click wants to prevent
-                    if (event.defaultPrevented) {
-                        return;
+                        checked: value
                     }
+                };
 
+                props.onClick && props.onClick(eventData);
+
+                // do not continue if the user defined click wants to prevent
+                if (event.defaultPrevented) {
+                    return;
+                }
+
+                if (isInputToggled || isRadioToggled) {
                     props.onChange && props.onChange(eventData);
 
                     if (isRadioToggled) {
diff --git a/components/lib/sidebar/Sidebar.js b/components/lib/sidebar/Sidebar.js
index f0832785b9..a547a6d898 100644
--- a/components/lib/sidebar/Sidebar.js
+++ b/components/lib/sidebar/Sidebar.js
@@ -156,6 +156,7 @@ export const Sidebar = React.forwardRef((inProps, ref) => {
     });
 
     const createCloseIcon = () => {
+        const ariaLabel = props.ariaCloseLabel || localeOption('close');
         const closeButtonProps = mergeProps(
             {
                 type: 'button',
@@ -176,7 +177,6 @@ export const Sidebar = React.forwardRef((inProps, ref) => {
 
         const icon = props.closeIcon || <TimesIcon {...closeIconProps} />;
         const closeIcon = IconUtils.getJSXIcon(icon, { ...closeIconProps }, { props });
-        const ariaLabel = props.ariaCloseLabel || localeOption('close');
 
         if (props.showCloseIcon) {
             return (
diff --git a/components/lib/togglebutton/ToggleButton.js b/components/lib/togglebutton/ToggleButton.js
index 9b48bc3b04..b1e18a2645 100644
--- a/components/lib/togglebutton/ToggleButton.js
+++ b/components/lib/togglebutton/ToggleButton.js
@@ -1,19 +1,23 @@
 import * as React from 'react';
 import { PrimeReactContext } from '../api/Api';
+import { useHandleStyle } from '../componentbase/ComponentBase';
 import { useMountEffect } from '../hooks/Hooks';
 import { Ripple } from '../ripple/Ripple';
 import { Tooltip } from '../tooltip/Tooltip';
 import { DomHandler, IconUtils, ObjectUtils, mergeProps } from '../utils/Utils';
 import { ToggleButtonBase } from './ToggleButtonBase';
-import { useHandleStyle } from '../componentbase/ComponentBase';
 
 export const ToggleButton = React.memo(
     React.forwardRef((inProps, ref) => {
+        const [focusedState, setFocusedState] = React.useState(false);
         const context = React.useContext(PrimeReactContext);
         const props = ToggleButtonBase.getProps(inProps, context);
         const elementRef = React.useRef(null);
         const { ptm, cx, isUnstyled } = ToggleButtonBase.setMetaData({
-            props
+            props,
+            state: {
+                focused: focusedState
+            }
         });
 
         useHandleStyle(ToggleButtonBase.css.styles, isUnstyled, { name: 'togglebutton' });
@@ -43,6 +47,16 @@ export const ToggleButton = React.memo(
             }
         };
 
+        const onFocus = (event) => {
+            setFocusedState(true);
+            props.onFocus && props.onFocus(event);
+        };
+
+        const onBlur = (event) => {
+            setFocusedState(false);
+            props.onBlur && props.onBlur(event);
+        };
+
         const onKeyDown = (event) => {
             if (event.keyCode === 32) {
                 toggle(event);
@@ -95,8 +109,8 @@ export const ToggleButton = React.memo(
                 className: cx('root', { hasIcon, hasLabel }),
                 style: props.style,
                 onClick: toggle,
-                onFocus: props.onFocus,
-                onBlur: props.onBlur,
+                onFocus: onFocus,
+                onBlur: onBlur,
                 onKeyDown: onKeyDown,
                 tabIndex: tabIndex,
                 role: 'button',
diff --git a/components/lib/treeselect/TreeSelect.js b/components/lib/treeselect/TreeSelect.js
index 23900bc2b5..b2f4b594d4 100644
--- a/components/lib/treeselect/TreeSelect.js
+++ b/components/lib/treeselect/TreeSelect.js
@@ -7,6 +7,7 @@ import { SearchIcon } from '../icons/search';
 import { TimesIcon } from '../icons/times';
 import { OverlayService } from '../overlayservice/OverlayService';
 import { Ripple } from '../ripple/Ripple';
+import { Tooltip } from '../tooltip/Tooltip';
 import { Tree } from '../tree/Tree';
 import { DomHandler, IconUtils, ObjectUtils, ZIndexUtils, mergeProps } from '../utils/Utils';
 import { TreeSelectBase } from './TreeSelectBase';
@@ -33,6 +34,7 @@ export const TreeSelect = React.memo(
         const hasNoOptions = ObjectUtils.isEmpty(props.options);
         const isSingleSelectionMode = props.selectionMode === 'single';
         const isCheckboxSelectionMode = props.selectionMode === 'checkbox';
+        const hasTooltip = ObjectUtils.isNotEmpty(props.tooltip);
 
         const metaData = {
             props,
@@ -744,6 +746,7 @@ export const TreeSelect = React.memo(
                 >
                     {content}
                 </TreeSelectPanel>
+                {hasTooltip && <Tooltip target={elementRef} content={props.tooltip} {...props.tooltipOptions} pt={ptm('tooltip')} />}
             </div>
         );
     })
diff --git a/components/lib/treeselect/treeselect.d.ts b/components/lib/treeselect/treeselect.d.ts
index 10a30ec2c4..fbb888d9ee 100644
--- a/components/lib/treeselect/treeselect.d.ts
+++ b/components/lib/treeselect/treeselect.d.ts
@@ -12,6 +12,8 @@ import { CSSTransitionProps as ReactCSSTransitionProps } from 'react-transition-
 import { ComponentHooks } from '../componentbase/componentbase';
 import { CSSTransitionProps } from '../csstransition';
 import { PassThroughOptions } from '../passthrough';
+import { TooltipPassThroughOptions } from '../tooltip/tooltip';
+import { TooltipOptions } from '../tooltip/tooltipoptions';
 import { TreeNodeTemplateOptions, TreePassThroughOptions, TreeTogglerTemplateOptions } from '../tree/tree';
 import { TreeNode } from '../treenode';
 import { FormEvent } from '../ts-helpers';
@@ -123,6 +125,11 @@ export interface TreeSelectPassThroughOptions {
      * Used to control React Transition API.
      */
     transition?: TreeSelectPassThroughTransitionType;
+    /**
+     * Uses to pass attributes to the Tooltip component.
+     * @see {@link TooltipPassThroughOptions}
+     */
+    tooltip?: TooltipPassThroughOptions;
 }
 
 /**
@@ -524,6 +531,14 @@ export interface TreeSelectProps extends Omit<React.DetailedHTMLProps<React.Inpu
      * Defines the selection mode, valid values "single", "multiple", and "checkbox".
      */
     selectionMode?: 'single' | 'multiple' | 'checkbox' | undefined;
+    /**
+     * Content of the tooltip.
+     */
+    tooltip?: string | undefined;
+    /**
+     * Configuration of the tooltip, refer to the tooltip documentation for more information.
+     */
+    tooltipOptions?: TooltipOptions | undefined;
     /**
      * The properties of CSSTransition can be customized, except for "nodeRef" and "in" properties.
      */