diff --git a/components/doc/accordion/theming/tailwinddoc.js b/components/doc/accordion/theming/tailwinddoc.js index 1f92bc501a..10ab21f4ad 100644 --- a/components/doc/accordion/theming/tailwinddoc.js +++ b/components/doc/accordion/theming/tailwinddoc.js @@ -34,7 +34,7 @@ const Tailwind = { 'dark:bg-gray-900 dark:border-blue-900/40 dark:text-white/80 dark:hover:bg-gray-800/80 dark:focus:shadow-[inset_0_0_0_0.2rem_rgba(147,197,253,0.5)]', // Dark mode 'hover:border-gray-300 hover:bg-gray-200 hover:text-gray-800', // Hover 'focus:outline-none focus:outline-offset-0 focus:shadow-[inset_0_0_0_0.2rem_rgba(191,219,254,1)]', // Focus - { 'rounded-br-md rounded-bl-md': !context.active, 'rounded-br-0 rounded-bl-0 text-gray-800': context.active } // Condition + { 'rounded-br-md rounded-bl-md': !context.selected, 'rounded-br-0 rounded-bl-0 text-gray-800': context.selected } // Condition ) }), headerIcon: 'inline-block mr-2', diff --git a/components/doc/common/apidoc/index.json b/components/doc/common/apidoc/index.json index 108fd7eb3e..daa1de6c7b 100644 --- a/components/doc/common/apidoc/index.json +++ b/components/doc/common/apidoc/index.json @@ -10086,19 +10086,6 @@ "returnType": "void", "description": "Callback to invoke on value change" }, - { - "name": "onClick", - "parameters": [ - { - "name": "event", - "optional": false, - "type": "CheckboxClickEvent", - "description": "Custom click event" - } - ], - "returnType": "void", - "description": "Callback to invoke on value change. Mark the event with preventDefault to prevent the option from changing." - }, { "name": "onContextMenu", "parameters": [ @@ -10161,36 +10148,6 @@ "type": "FormTarget" } ] - }, - "CheckboxClickEvent": { - "description": "Custom click event.", - "relatedProp": "onClick", - "props": [ - { - "name": "originalEvent", - "optional": true, - "readonly": false, - "type": "SyntheticEvent" - }, - { - "name": "value", - "optional": false, - "readonly": false, - "type": "any" - }, - { - "name": "checked", - "optional": true, - "readonly": false, - "type": "boolean" - }, - { - "name": "target", - "optional": false, - "readonly": false, - "type": "FormTarget" - } - ] } } }, @@ -10207,12 +10164,6 @@ "readonly": false, "type": "CheckboxProps" }, - { - "name": "state", - "optional": false, - "readonly": false, - "type": "CheckboxState" - }, { "name": "context", "optional": false, @@ -10240,6 +10191,13 @@ "type": "CheckboxPassThroughType>", "description": "Uses to pass attributes to the input's DOM element." }, + { + "name": "box", + "optional": true, + "readonly": false, + "type": "CheckboxPassThroughType>", + "description": "Used to pass attributes to the box's DOM element." + }, { "name": "icon", "optional": true, @@ -10254,20 +10212,6 @@ "type": "TooltipPassThroughOptions", "description": "Uses to pass attributes tooltip's DOM element." }, - { - "name": "hiddenInputWrapper", - "optional": true, - "readonly": false, - "type": "CheckboxPassThroughType>", - "description": "Uses to pass attributes to the hidden input wrapper's DOM element." - }, - { - "name": "hiddenInput", - "optional": true, - "readonly": false, - "type": "CheckboxPassThroughType>", - "description": "Uses to pass attributes to the hidden input's DOM element." - }, { "name": "hooks", "optional": true, @@ -10298,20 +10242,6 @@ } ], "callbacks": [] - }, - "CheckboxState": { - "description": "Defines current inline state in Checkbox component.", - "relatedProp": "", - "props": [ - { - "name": "focused", - "optional": false, - "readonly": false, - "type": "boolean", - "description": "Current focus state as a boolean." - } - ], - "callbacks": [] } } }, @@ -22714,6 +22644,22 @@ "default": "false", "description": "When present, it specifies that the component should automatically get focus on load." }, + { + "name": "autoOptionFocus", + "optional": true, + "readonly": false, + "type": "false", + "default": "false", + "description": "Whether to focus on the first visible or selected element." + }, + { + "name": "checkmark", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "false", + "description": "Whether the selected option will be shown with a check mark." + }, { "name": "children", "optional": true, @@ -22867,6 +22813,14 @@ "default": "", "description": "Reference of the focusable input element." }, + { + "name": "highlightOnSelect", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "true", + "description": "Whether the selected option will be add highlight class." + }, { "name": "id", "optional": true, @@ -23059,6 +23013,14 @@ "default": "200px", "description": "Height of the viewport in pixels, a scrollbar is defined if height of list exceeds this value." }, + { + "name": "selectOnFocus", + "optional": true, + "readonly": false, + "type": "false", + "default": "false", + "description": "When enabled, the focused tab is activated." + }, { "name": "showClear", "optional": true, @@ -23439,6 +23401,13 @@ "type": "DropdownPassThroughType>", "description": "Uses to pass attributes to the item group's DOM element." }, + { + "name": "itemGroupLabel", + "optional": true, + "readonly": false, + "type": "DropdownPassThroughType>", + "description": "Used to pass attributes to the item group label's DOM element." + }, { "name": "item", "optional": true, @@ -23446,6 +23415,27 @@ "type": "DropdownPassThroughType>", "description": "Uses to pass attributes to the item's DOM element." }, + { + "name": "itemLabel", + "optional": true, + "readonly": false, + "type": "DropdownPassThroughType>", + "description": "Used to pass attributes to the item label's DOM element." + }, + { + "name": "checkIcon", + "optional": true, + "readonly": false, + "type": "DropdownPassThroughType>", + "description": "Used to pass attributes to the check icon's DOM element." + }, + { + "name": "blankIcon", + "optional": true, + "readonly": false, + "type": "DropdownPassThroughType>", + "description": "Used to pass attributes to the bank icon's DOM element." + }, { "name": "emptyMessage", "optional": true, @@ -30790,12 +30780,6 @@ "optional": false, "readonly": false, "type": "InputSwitchProps" - }, - { - "name": "state", - "optional": false, - "readonly": false, - "type": "InputSwitchState" } ], "callbacks": [] @@ -30819,18 +30803,11 @@ "description": "Uses to pass attributes to the slider's DOM element." }, { - "name": "hiddenInputWrapper", - "optional": true, - "readonly": false, - "type": "InputSwitchPassThroughType>", - "description": "Uses to pass attributes to the hidden input wrapper's DOM element." - }, - { - "name": "hiddenInput", + "name": "input", "optional": true, "readonly": false, "type": "InputSwitchPassThroughType>", - "description": "Uses to pass attributes to the hidden input's DOM element." + "description": "Uses to pass attributes to the input's DOM element." }, { "name": "tooltip", @@ -30848,20 +30825,6 @@ } ], "callbacks": [] - }, - "InputSwitchState": { - "description": "Defines current inline state in InputSwitch component.", - "relatedProp": "", - "props": [ - { - "name": "focused", - "optional": false, - "readonly": false, - "type": "boolean", - "description": "Current focus state as a boolean." - } - ], - "callbacks": [] } } }, @@ -31595,6 +31558,14 @@ "default": "", "description": "Establishes relationships between the component and label(s) where its value should be one or more element IDs." }, + { + "name": "autoOptionFocus", + "optional": true, + "readonly": false, + "type": "false", + "default": "false", + "description": "Whether to focus on the first visible or selected element." + }, { "name": "children", "optional": true, @@ -31811,6 +31782,14 @@ "default": "", "description": "Used to configure passthrough(pt) options of the component." }, + { + "name": "selectOnFocus", + "optional": true, + "readonly": false, + "type": "false", + "default": "false", + "description": "When enabled, the focused tab is activated." + }, { "name": "tooltip", "optional": true, @@ -34911,6 +34890,14 @@ "default": "", "description": "Establishes relationships between the component and label(s) where its value should be one or more element IDs." }, + { + "name": "autoOptionFocus", + "optional": true, + "readonly": false, + "type": "false", + "default": "false", + "description": "Whether to focus on the first visible or selected element." + }, { "name": "checkboxIcon", "optional": true, @@ -35135,6 +35122,22 @@ "default": "", "description": "Function that gets the option and returns the content for it." }, + { + "name": "loading", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "false", + "description": "Displays a loader to indicate data load is in progress." + }, + { + "name": "loadingIcon", + "optional": true, + "readonly": false, + "type": "IconType", + "default": "", + "description": "The icon to show while indicating data load is in progress." + }, { "name": "maxSelectedLabels", "optional": true, @@ -35335,6 +35338,14 @@ "default": "", "description": "Number of maximum options that can be selected." }, + { + "name": "selectOnFocus", + "optional": true, + "readonly": false, + "type": "false", + "default": "false", + "description": "When enabled, the focused tab is activated." + }, { "name": "showClear", "optional": true, @@ -36604,6 +36615,14 @@ "default": "", "description": "Establishes relationships between the component and label(s) where its value should be one or more element IDs." }, + { + "name": "autoOptionFocus", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "true", + "description": "Whether to focus on the first visible or selected element." + }, { "name": "breakpoint", "optional": true, @@ -40642,6 +40661,14 @@ "props": { "description": "Defines valid properties in PickList component.", "values": [ + { + "name": "autoOptionFocus", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "true", + "description": "Whether to focus on the first visible or selected element." + }, { "name": "breakpoint", "optional": true, @@ -41937,7 +41964,7 @@ "readonly": false, "type": "boolean", "default": "false", - "description": "When present, it specifies that the element value cannot be altered." + "description": "When present, it specifies that the component should be disabled." }, { "name": "inputId", @@ -41955,6 +41982,14 @@ "default": "", "description": "Reference of the input element." }, + { + "name": "invalid", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "false", + "description": "When present, it specifies that the component should have invalid state style." + }, { "name": "name", "optional": true, @@ -41979,6 +42014,14 @@ "default": "", "description": "Used to configure passthrough(pt) options of the component." }, + { + "name": "readonly", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "", + "description": "When present, it specifies that an input field is read-only." + }, { "name": "required", "optional": true, @@ -42036,19 +42079,6 @@ ], "returnType": "void", "description": "Callback to invoke on value change" - }, - { - "name": "onClick", - "parameters": [ - { - "name": "event", - "optional": false, - "type": "RadioButtonClickEvent", - "description": "Custom click event." - } - ], - "returnType": "void", - "description": "Callback to invoke on click. Mark the event with preventDefault to prevent the option from changing." } ] } @@ -42086,36 +42116,6 @@ "type": "FormTarget" } ] - }, - "RadioButtonClickEvent": { - "description": "Custom click event.", - "relatedProp": "onClick", - "props": [ - { - "name": "originalEvent", - "optional": true, - "readonly": false, - "type": "SyntheticEvent" - }, - { - "name": "value", - "optional": false, - "readonly": false, - "type": "any" - }, - { - "name": "checked", - "optional": true, - "readonly": false, - "type": "boolean" - }, - { - "name": "target", - "optional": false, - "readonly": false, - "type": "FormTarget" - } - ] } } }, @@ -42131,12 +42131,6 @@ "optional": false, "readonly": false, "type": "RadioButtonProps" - }, - { - "name": "state", - "optional": false, - "readonly": false, - "type": "RadioButtonState" } ], "callbacks": [] @@ -42152,13 +42146,6 @@ "type": "RadioButtonPassThroughType>", "description": "Uses to pass attributes to the root's DOM element." }, - { - "name": "input", - "optional": true, - "readonly": false, - "type": "RadioButtonPassThroughType>", - "description": "Uses to pass attributes to the input's DOM element." - }, { "name": "icon", "optional": true, @@ -42167,18 +42154,18 @@ "description": "Uses to pass attributes to the icon's DOM element." }, { - "name": "hiddenInputWrapper", + "name": "input", "optional": true, "readonly": false, "type": "RadioButtonPassThroughType>", - "description": "Uses to pass attributes to the hidden accessible DOM element wrapper." + "description": "Uses to pass attributes to the input's DOM element." }, { - "name": "hiddenInput", + "name": "box", "optional": true, "readonly": false, - "type": "RadioButtonPassThroughType>", - "description": "Uses to pass attributes to the hidden accessible DOM element." + "type": "CheckboxPassThroughType>", + "description": "Used to pass attributes to the box's DOM element." }, { "name": "tooltip", @@ -42196,20 +42183,6 @@ } ], "callbacks": [] - }, - "RadioButtonState": { - "description": "Defines current inline state in RadioButton component.", - "relatedProp": "", - "props": [ - { - "name": "focused", - "optional": false, - "readonly": false, - "type": "boolean", - "description": "Current focused state as a boolean." - } - ], - "callbacks": [] } } }, @@ -43699,6 +43672,13 @@ "type": "SidebarPassThroughType>", "description": "Uses to pass attributes to the close button's DOM element." }, + { + "name": "icons", + "optional": true, + "readonly": false, + "type": "SidebarPassThroughType>", + "description": "Uses to pass attributes to the custom icons content's DOM element." + }, { "name": "closeIcon", "optional": true, @@ -43713,13 +43693,6 @@ "type": "SidebarPassThroughType>", "description": "Uses to pass attributes to the content's DOM element." }, - { - "name": "icons", - "optional": true, - "readonly": false, - "type": "SidebarPassThroughType>", - "description": "Uses to pass attributes to the custom icons content's DOM element." - }, { "name": "mask", "optional": true, @@ -45640,14 +45613,6 @@ "default": "", "description": "Size of the element relative to 100%." }, - { - "name": "step", - "optional": true, - "readonly": false, - "type": "number", - "default": "5", - "description": "Step factor to increment/decrement the size of the panels while pressing the arrow keys." - }, { "name": "style", "optional": true, @@ -45735,6 +45700,14 @@ "default": "session", "description": "Defines where a stateful splitter keeps its state, valid values are \"session\" for sessionStorage and \"local\" for localStorage." }, + { + "name": "step", + "optional": true, + "readonly": false, + "type": "number", + "default": "5", + "description": "Step factor to increment/decrement the size of the panels while pressing the arrow keys." + }, { "name": "unstyled", "optional": true, @@ -48894,6 +48867,14 @@ "default": "", "description": "Used to get the child elements of the component." }, + { + "name": "disabled", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "false", + "description": "When present, it specifies that the element should be disabled." + }, { "name": "iconPos", "optional": true, @@ -48902,6 +48883,14 @@ "default": "left", "description": "Position of the icon, valid values are \"left\" and \"right\"." }, + { + "name": "invalid", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "false", + "description": "When present, it specifies that the component should have invalid state style." + }, { "name": "offIcon", "optional": true, @@ -48950,6 +48939,14 @@ "default": "", "description": "Used to configure passthrough(pt) options of the component." }, + { + "name": "readonly", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "", + "description": "When present, it specifies that an input field is read-only." + }, { "name": "tooltip", "optional": true, @@ -49108,6 +49105,20 @@ "readonly": false, "type": "ComponentHooks", "description": "Used to manage all lifecycle hooks" + }, + { + "name": "input", + "optional": true, + "readonly": false, + "type": "ToggleButtonPassThroughType>", + "description": "Uses to pass attributes to the input's DOM element." + }, + { + "name": "box", + "optional": true, + "readonly": false, + "type": "CheckboxPassThroughType>", + "description": "Used to pass attributes to the box's DOM element." } ], "callbacks": [] @@ -49606,6 +49617,14 @@ "default": "", "description": "Target element on global tooltip option." }, + { + "name": "unstyled", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "false", + "description": "When enabled, it removes component related styles in the core." + }, { "name": "updateDelay", "optional": true, @@ -49995,6 +50014,14 @@ "type": "PassThroughOptions", "default": "", "description": "Used to configure passthrough(pt) options of the component." + }, + { + "name": "unstyled", + "optional": true, + "readonly": false, + "type": "boolean", + "default": "false", + "description": "When enabled, it removes component related styles in the core." } ] }, @@ -54526,12 +54553,6 @@ "optional": false, "readonly": false, "type": "TriStateCheckboxProps" - }, - { - "name": "state", - "optional": false, - "readonly": false, - "type": "TriStateCheckboxState" } ], "callbacks": [] @@ -54548,11 +54569,18 @@ "description": "Uses to pass attributes to the root's DOM element." }, { - "name": "checkbox", + "name": "input", "optional": true, "readonly": false, - "type": "TriStateCheckboxPassThroughType>", - "description": "Uses to pass attributes to the checkbox box's DOM element." + "type": "CheckboxPassThroughType>", + "description": "Uses to pass attributes to the input's DOM element." + }, + { + "name": "box", + "optional": true, + "readonly": false, + "type": "CheckboxPassThroughType>", + "description": "Used to pass attributes to the box's DOM element." }, { "name": "tooltip", @@ -54591,20 +54619,6 @@ } ], "callbacks": [] - }, - "TriStateCheckboxState": { - "description": "Defines current inline state in TriStateCheckbox component.", - "relatedProp": "", - "props": [ - { - "name": "focused", - "optional": false, - "readonly": false, - "type": "boolean", - "description": "Focused state as a boolean." - } - ], - "callbacks": [] } } }, @@ -54733,7 +54747,7 @@ "returnType": "void" } ], - "extendedBy": "AutoCompleteChangeEvent,CheckboxChangeEvent,CheckboxClickEvent,ChipsChangeEvent,ColorPickerChangeEvent,DropdownChangeEvent,InputMaskChangeEvent,InputNumberValueChangeEvent,RadioButtonChangeEvent,RadioButtonClickEvent,RatingChangeEvent,SelectButtonChangeEvent,TreeSelectChangeEvent,TriStateCheckboxChangeEvent" + "extendedBy": "AutoCompleteChangeEvent,CheckboxChangeEvent,ChipsChangeEvent,ColorPickerChangeEvent,DropdownChangeEvent,InputMaskChangeEvent,InputNumberValueChangeEvent,RadioButtonChangeEvent,RatingChangeEvent,SelectButtonChangeEvent,TreeSelectChangeEvent,TriStateCheckboxChangeEvent" }, "FormBooleanEvent": { "relatedProp": "", diff --git a/components/doc/datatable/scroll/frozencolumnsdoc.js b/components/doc/datatable/scroll/frozencolumnsdoc.js index 99482b6a25..83edd47f84 100644 --- a/components/doc/datatable/scroll/frozencolumnsdoc.js +++ b/components/doc/datatable/scroll/frozencolumnsdoc.js @@ -164,7 +164,7 @@ export default function FrozenColumnsDemo() { <>

- A column can be fixed during horizontal scrolling by enablng the frozen property. The location is defined with the alignFrozen that can be left or right. + A column can be fixed during horizontal scrolling by enabling the frozen property. The location is defined with the alignFrozen that can be left or right.

diff --git a/components/doc/dialog/theming/styleddoc.js b/components/doc/dialog/theming/styleddoc.js index 379242eb0e..a505b64293 100644 --- a/components/doc/dialog/theming/styleddoc.js +++ b/components/doc/dialog/theming/styleddoc.js @@ -20,7 +20,7 @@ export function StyledDoc(props) { Container element. - p-dialog-titlebar + p-dialog-header Container of header. @@ -28,13 +28,17 @@ export function StyledDoc(props) { Header element. - p-dialog-titlebar-icon + p-dialog-header-icons Icon container inside header. - p-dialog-titlebar-close + p-dialog-header-close Close icon element. + + p-dialog-header-maximize + Maximize icon element. + p-dialog-content Content element diff --git a/components/doc/dropdown/checkmarkdoc.js b/components/doc/dropdown/checkmarkdoc.js new file mode 100644 index 0000000000..0543626b24 --- /dev/null +++ b/components/doc/dropdown/checkmarkdoc.js @@ -0,0 +1,83 @@ +import { DocSectionCode } from '@/components/doc/common/docsectioncode'; +import { DocSectionText } from '@/components/doc/common/docsectiontext'; +import { Dropdown } from '@/components/lib/dropdown/Dropdown'; +import { useState } from 'react'; + +export function CheckmarkDoc(props) { + const [selectedCity, setSelectedCity] = useState(null); + const cities = [ + { name: 'New York', code: 'NY' }, + { name: 'Rome', code: 'RM' }, + { name: 'London', code: 'LDN' }, + { name: 'Istanbul', code: 'IST' }, + { name: 'Paris', code: 'PRS' } + ]; + + const code = { + basic: ` + setSelectedCity(e.value)} options={cities} optionLabel="name" + placeholder="Select a City" className="w-full md:w-14rem" checkmark={true} highlightOnSelect={false} /> + `, + javascript: ` +import React, { useState } from "react"; +import { Dropdown } from 'primereact/dropdown'; + +export default function CheckmarkDemo() { + const [selectedCity, setSelectedCity] = useState(null); + const cities = [ + { name: 'New York', code: 'NY' }, + { name: 'Rome', code: 'RM' }, + { name: 'London', code: 'LDN' }, + { name: 'Istanbul', code: 'IST' }, + { name: 'Paris', code: 'PRS' } + ]; + + return ( +
+ setSelectedCity(e.value)} options={cities} optionLabel="name" + placeholder="Select a City" className="w-full md:w-14rem" checkmark={true} highlightOnSelect={false} /> +
+ ) +} + `, + typescript: ` +import React, { useState } from "react"; +import { Dropdown, DropdownChangeEvent } from 'primereact/dropdown'; + +interface City { + name: string; + code: string; +} + +export default function CheckmarkDemo() { + const [selectedCity, setSelectedCity] = useState(null); + const cities: City[] = [ + { name: 'New York', code: 'NY' }, + { name: 'Rome', code: 'RM' }, + { name: 'London', code: 'LDN' }, + { name: 'Istanbul', code: 'IST' }, + { name: 'Paris', code: 'PRS' } + ]; + + return ( +
+ setSelectedCity(e.value)} options={cities} optionLabel="name" + placeholder="Select a City" className="w-full md:w-14rem" checkmark={true} highlightOnSelect={false} /> +
+ ) +} + ` + }; + + return ( + <> + +

An alternative way to highlight the selected option is displaying a checkmark instead.

+
+
+ setSelectedCity(e.value)} options={cities} optionLabel="name" placeholder="Select a City" className="w-full md:w-14rem" checkmark={true} highlightOnSelect={false} /> +
+ + + ); +} diff --git a/components/doc/menu/theming/tailwinddoc.js b/components/doc/menu/theming/tailwinddoc.js index fb852ed014..f4184d8ffb 100644 --- a/components/doc/menu/theming/tailwinddoc.js +++ b/components/doc/menu/theming/tailwinddoc.js @@ -23,18 +23,21 @@ const Tailwind = { menu: { className: classNames('m-0 p-0 list-none', 'outline-none') }, - content: ({ context }) => ({ + content: ({ state }) => ({ className: classNames( 'text-gray-700 dark:text-white/80 transition-shadow duration-200 rounded-none', 'hover:text-gray-700 dark:hover:text-white/80 hover:bg-gray-200 dark:hover:bg-gray-800/80', // Hover { - 'bg-gray-300 text-gray-700 dark:text-white/80 dark:bg-gray-800/90': context.focused + 'bg-gray-300 text-gray-700 dark:text-white/80 dark:bg-gray-800/90': state.focused } ) }), action: { className: classNames('text-gray-700 dark:text-white/80 py-3 px-5 select-none', 'cursor-pointer flex items-center no-underline overflow-hidden relative') }, + menuitem: { + className: classNames('hover:bg-gray-200') + }, icon: 'text-gray-600 dark:text-white/70 mr-2', submenuheader: { className: classNames('m-0 p-3 text-gray-700 dark:text-white/80 bg-white dark:bg-gray-900 font-bold rounded-tl-none rounded-tr-none') diff --git a/components/doc/organizationchart/basicdoc.js b/components/doc/organizationchart/basicdoc.js index 88c93c3b4b..086050c441 100644 --- a/components/doc/organizationchart/basicdoc.js +++ b/components/doc/organizationchart/basicdoc.js @@ -92,7 +92,7 @@ import { OrganizationChart } from 'primereact/organizationchart'; import { TreeNode } from 'primereact/treenode'; export default function BasicDoc() { - const [data] = useState([ + const [data] = useState([ { label: 'Argentina', expanded: true, diff --git a/components/doc/organizationchart/pt/ptdoc.js b/components/doc/organizationchart/pt/ptdoc.js index f6cd6ce570..3d13edc645 100644 --- a/components/doc/organizationchart/pt/ptdoc.js +++ b/components/doc/organizationchart/pt/ptdoc.js @@ -115,7 +115,7 @@ import { TreeNode } from 'primereact/treenode'; export default function PTDemo() { const [selection, setSelection] = useState([]); - const [data] = useState([ + const [data] = useState([ { label: 'Argentina', expanded: true, diff --git a/components/doc/organizationchart/templatedoc.js b/components/doc/organizationchart/templatedoc.js index 08b3b25b97..a13e629aa7 100644 --- a/components/doc/organizationchart/templatedoc.js +++ b/components/doc/organizationchart/templatedoc.js @@ -124,7 +124,7 @@ import { OrganizationChart } from 'primereact/organizationchart'; import { TreeNode } from 'primereact/treenode'; export default function TemplateDemo() { - const [data] = useState([ + const [data] = useState([ { label: 'Argentina', expanded: true, diff --git a/components/doc/panel/theming/styleddoc.js b/components/doc/panel/theming/styleddoc.js index e889852744..9cf0b7e263 100644 --- a/components/doc/panel/theming/styleddoc.js +++ b/components/doc/panel/theming/styleddoc.js @@ -20,7 +20,7 @@ export function StyledDoc(props) { Container element. - p-panel-titlebar + p-panel-header Header section. @@ -28,7 +28,7 @@ export function StyledDoc(props) { Title text of panel. - p-panel-titlebar-toggler + p-panel-toggler Toggle icon. diff --git a/components/doc/sidebar/headlessdoc.js b/components/doc/sidebar/headlessdoc.js index 56d6d9b367..70a7522f80 100644 --- a/components/doc/sidebar/headlessdoc.js +++ b/components/doc/sidebar/headlessdoc.js @@ -1,11 +1,11 @@ import { DocSectionCode } from '@/components/doc/common/docsectioncode'; import { DocSectionText } from '@/components/doc/common/docsectiontext'; -import { Button } from '@/components/lib/button/Button'; -import { Sidebar } from '@/components/lib/sidebar/Sidebar'; import { Avatar } from '@/components/lib/avatar/Avatar'; +import { Button } from '@/components/lib/button/Button'; import { Ripple } from '@/components/lib/ripple/Ripple'; -import { useState, useRef } from 'react'; +import { Sidebar } from '@/components/lib/sidebar/Sidebar'; import { StyleClass } from '@/components/lib/styleclass/StyleClass'; +import { useRef, useState } from 'react'; export function HeadlessDoc(props) { const [visible, setVisible] = useState(false); @@ -207,7 +207,6 @@ export default function HeadlessDemo() { const btnRef2 = useRef(null); const btnRef3 = useRef(null); const btnRef4 = useRef(null); - const [visible, setVisible] = useState(false); return (
diff --git a/components/doc/timeline/templatedoc.js b/components/doc/timeline/templatedoc.js index da73415bcc..963e4d95fa 100644 --- a/components/doc/timeline/templatedoc.js +++ b/components/doc/timeline/templatedoc.js @@ -95,7 +95,7 @@ interface TimelineEvent { } export default function TemplateDemo() { - const events: TimelineEvent = [ + const events: TimelineEvent[] = [ { status: 'Ordered', date: '15/10/2020 10:30', icon: 'pi pi-shopping-cart', color: '#9C27B0', image: 'game-controller.jpg' }, { status: 'Processing', date: '15/10/2020 14:00', icon: 'pi pi-cog', color: '#673AB7' }, { status: 'Shipped', date: '15/10/2020 16:15', icon: 'pi pi-shopping-cart', color: '#FF9800' }, @@ -113,7 +113,7 @@ export default function TemplateDemo() { const customizedContent = (item: TimelineEvent) => { return ( - { item.image && {item.name}} + { item.image && {item.image}}

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate neque quas!

diff --git a/components/doc/togglebutton/theming/tailwinddoc.js b/components/doc/togglebutton/theming/tailwinddoc.js index e7a56bd0e4..fcb24f40e7 100644 --- a/components/doc/togglebutton/theming/tailwinddoc.js +++ b/components/doc/togglebutton/theming/tailwinddoc.js @@ -7,14 +7,11 @@ export function TailwindDoc(props) { basic: ` const Tailwind = { togglebutton: { - root: ({ props, state }) => ({ + root: ({ props }) => ({ 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)]': 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, diff --git a/components/doc/tree/eventsdoc.js b/components/doc/tree/eventsdoc.js index 6760470ace..c4e8b9a7d4 100644 --- a/components/doc/tree/eventsdoc.js +++ b/components/doc/tree/eventsdoc.js @@ -80,8 +80,9 @@ export default function EventsDemo() { `, typescript: ` import React, { useState, useEffect, useRef } from 'react'; -import { Tree, TreeNode, TreeEventNodeEvent } from 'primereact/tree'; +import { Tree, TreeEventNodeEvent } from 'primereact/tree'; import { Toast } from 'primereact/toast'; +import { TreeNode } from "primereact/treenode"; import { NodeService } from './service/NodeService'; export default function EventsDemo() { diff --git a/components/doc/treetable/contextmenudoc.js b/components/doc/treetable/contextmenudoc.js index 08b3d02197..f39340863a 100644 --- a/components/doc/treetable/contextmenudoc.js +++ b/components/doc/treetable/contextmenudoc.js @@ -106,17 +106,17 @@ export default function ContextMenuDemo() { `, typescript: ` import React, { useState, useEffect, useRef } from 'react'; -import { TreeTable } from 'primereact/treetable'; +import { TreeTable, TreeTableExpandedKeysType } from 'primereact/treetable'; import { ContextMenu } from 'primereact/contextmenu'; import { Toast } from 'primereact/toast'; import { Column } from 'primereact/column'; -import { TreeNode } from 'primereact/column'; +import { TreeNode } from 'primereact/treenode'; import { NodeService } from './service/NodeService'; export default function ContextMenuDemo() { - const [nodes, setNodes] = useState([]); + const [nodes, setNodes] = useState([]); const [expandedKeys, setExpandedKeys] = useState(null); - const [selectedNodeKey, setSelectedNodeKey] = useState(null); + const [selectedNodeKey, setSelectedNodeKey] = useState(null); const toast = useRef(null); const cm = useRef(null); const menu = [ diff --git a/components/doc/treetable/filterdoc.js b/components/doc/treetable/filterdoc.js index 9d23d38b2d..4108534b1a 100644 --- a/components/doc/treetable/filterdoc.js +++ b/components/doc/treetable/filterdoc.js @@ -106,9 +106,9 @@ interface FilterModeOption { } export default function FilterDemo() { - const [nodes, setNodes] = useState([]); + const [nodes, setNodes] = useState([]); const [globalFilter, setGlobalFilter] = useState(''); - const [filterMode, setFilterMode] = useState('lenient'); + const [filterMode, setFilterMode] = useState<'lenient' | 'strict'>('lenient'); const [filterOptions] = useState([ { label: 'Lenient', value: 'lenient' }, { label: 'Strict', value: 'strict' } diff --git a/components/doc/treetable/scroll/frozencolumnsdoc.js b/components/doc/treetable/scroll/frozencolumnsdoc.js index 68f36c1207..f02d898bd0 100644 --- a/components/doc/treetable/scroll/frozencolumnsdoc.js +++ b/components/doc/treetable/scroll/frozencolumnsdoc.js @@ -60,7 +60,7 @@ import { TreeNode } from 'primereact/treenode'; import { NodeService } from './service/NodeService'; export default function FrozenColumnsDemo() { - const [nodes, setNodes] = useState([]); + const [nodes, setNodes] = useState([]); useEffect(() => { NodeService.getTreeTableNodes().then(data => setNodes(data)); diff --git a/components/doc/treetable/scroll/verticaldoc.js b/components/doc/treetable/scroll/verticaldoc.js index 7a45e532d0..e20e8f350b 100644 --- a/components/doc/treetable/scroll/verticaldoc.js +++ b/components/doc/treetable/scroll/verticaldoc.js @@ -52,7 +52,7 @@ import { TreeNode } from 'primereact/treenode'; import { NodeService } from './service/NodeService'; export default function VerticalScrollDemo() { - const [nodes, setNodes] = useState([]); + const [nodes, setNodes] = useState([]); useEffect(() => { NodeService.getTreeTableNodes().then(data => setNodes(data)); diff --git a/components/doc/treetable/selection/multipledoc.js b/components/doc/treetable/selection/multipledoc.js index 5575c0ddfe..b19b6924c9 100644 --- a/components/doc/treetable/selection/multipledoc.js +++ b/components/doc/treetable/selection/multipledoc.js @@ -75,7 +75,7 @@ import { InputSwitch, InputSwitchChangeEvent } from 'primereact/inputswitch'; import { NodeService } from './service/NodeService'; export default function MultipleRowsSelectionDemo() { - const [nodes, setNodes] = useState([]); + const [nodes, setNodes] = useState([]); const [selectedNodeKeys, setSelectedNodeKeys] = useState(null); const [metaKey, setMetaKey] = useState(true); diff --git a/components/doc/treetable/selection/singledoc.js b/components/doc/treetable/selection/singledoc.js index 80c63330bd..eb3878ea93 100644 --- a/components/doc/treetable/selection/singledoc.js +++ b/components/doc/treetable/selection/singledoc.js @@ -66,7 +66,7 @@ import { InputSwitch, InputSwitchChangeEvent } from 'primereact/inputswitch'; import { NodeService } from './service/NodeService'; export default function SingleRowSelectionDemo() { - const [nodes, setNodes] = useState([]); + const [nodes, setNodes] = useState([]); const [selectedNodeKey, setSelectedNodeKey] = useState(null); const [metaKey, setMetaKey] = useState(true); diff --git a/components/lib/autocomplete/autocomplete.d.ts b/components/lib/autocomplete/autocomplete.d.ts index 921db8271a..8322f651e9 100755 --- a/components/lib/autocomplete/autocomplete.d.ts +++ b/components/lib/autocomplete/autocomplete.d.ts @@ -227,7 +227,7 @@ export interface AutoCompleteContext { * Defines valid properties in AutoComplete component. In addition to these, all properties of HTMLSpanElement can be used in this component. * @group Properties */ -export interface AutoCompleteProps extends Omit, HTMLSpanElement>, 'onChange' | 'onSelect' | 'ref'> { +export interface AutoCompleteProps extends Omit, HTMLSpanElement>, 'onChange' | 'onSelect' | 'ref'> { /** * Unique identifier of the element. */ diff --git a/components/lib/checkbox/Checkbox.js b/components/lib/checkbox/Checkbox.js index cb818642b2..bbc98352d2 100644 --- a/components/lib/checkbox/Checkbox.js +++ b/components/lib/checkbox/Checkbox.js @@ -12,32 +12,30 @@ export const Checkbox = React.memo( const mergeProps = useMergeProps(); const context = React.useContext(PrimeReactContext); const props = CheckboxBase.getProps(inProps, context); - const [focusedState, setFocusedState] = React.useState(false); const { ptm, cx, isUnstyled } = CheckboxBase.setMetaData({ props, - state: { - focused: focusedState - }, context: { checked: props.checked === props.trueValue, disabled: props.disabled } }); - useHandleStyle(CheckboxBase.css.styles, isUnstyled, { name: 'checkbox', styled: true }); + useHandleStyle(CheckboxBase.css.styles, isUnstyled, { name: 'checkbox' }); + const elementRef = React.useRef(null); const inputRef = React.useRef(props.inputRef); - const onClick = (event) => { - if (props.disabled || props.readOnly) { + const isChecked = () => { + return props.checked === props.trueValue; + }; + + const onChange = (event) => { + if (props.disabled || props.readonly) { return; } - if (props.onChange || props.onClick) { + if (props.onChange) { const checked = isChecked(); - 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; const value = checked ? props.falseValue : props.trueValue; const eventData = { originalEvent: event, @@ -58,39 +56,23 @@ export const Checkbox = React.memo( } }; - props.onClick && props.onClick(eventData); + props.onChange && props.onChange(eventData); // do not continue if the user defined click wants to prevent if (event.defaultPrevented) { return; } - if (isInputToggled || isCheckboxToggled) { - props.onChange && props.onChange(eventData); - } - DomHandler.focus(inputRef.current); - event.preventDefault(); } }; const onFocus = () => { - setFocusedState(true); + props?.onFocus?.(); }; const onBlur = () => { - setFocusedState(false); - }; - - const onKeyDown = (event) => { - if (event.code === 'Space' || event.key === ' ') { - // event.key is for Android support - onClick(event); - } - }; - - const isChecked = () => { - return props.checked === props.trueValue; + props?.onBlur?.(); }; React.useImperativeHandle(ref, () => ({ @@ -117,21 +99,11 @@ export const Checkbox = React.memo( const checked = isChecked(); const hasTooltip = ObjectUtils.isNotEmpty(props.tooltip); const otherProps = CheckboxBase.getOtherProps(props); - const ariaProps = ObjectUtils.reduceKeys(otherProps, DomHandler.ARIA_PROPS); - const iconProps = mergeProps( - { - className: cx('icon') - }, - ptm('icon') - ); - const icon = checked ? props.icon || : null; - const checkboxIcon = IconUtils.getJSXIcon(icon, { ...iconProps }, { props, checked }); const rootProps = mergeProps( { id: props.id, - className: classNames(props.className, cx('root', { checked, focusedState })), + className: classNames(props.className, cx('root', { checked })), style: props.style, - onClick: (e) => onClick(e), 'data-p-highlight': checked, 'data-p-disabled': props.disabled, onContextMenu: props.onContextMenu, @@ -141,48 +113,59 @@ export const Checkbox = React.memo( ptm('root') ); - const hiddenInputWrapperProps = mergeProps( - { - className: 'p-hidden-accessible' - }, - ptm('hiddenInputWrapper') - ); - - const hiddenInputProps = mergeProps( - { - id: props.inputId, - type: 'checkbox', - name: props.name, - tabIndex: props.tabIndex, - defaultChecked: checked, - onFocus: (e) => onFocus(e), - onBlur: (e) => onBlur(e), - onKeyDown: (e) => onKeyDown(e), - disabled: props.disabled, - readOnly: props.readOnly, - required: props.required, - ...ariaProps - }, - ptm('hiddenInput') - ); + const createInputElement = () => { + const ariaProps = ObjectUtils.reduceKeys(otherProps, DomHandler.ARIA_PROPS); + const inputProps = mergeProps( + { + id: props.inputId, + type: 'checkbox', + className: cx('input'), + name: props.name, + tabIndex: props.tabIndex, + defaultChecked: checked, + onFocus: (e) => onFocus(e), + onBlur: (e) => onBlur(e), + onChange: (e) => onChange(e), + disabled: props.disabled, + readOnly: props.readOnly, + required: props.required, + 'aria-invalid': props.invalid, + checked: isChecked(), + ...ariaProps + }, + ptm('input') + ); + + return ; + }; - const inputProps = mergeProps( - { - className: cx('input', { checked, focusedState }), - 'data-p-highlight': checked, - 'data-p-disabled': props.disabled, - 'data-p-focus': focusedState - }, - ptm('input') - ); + const createBoxElement = () => { + const iconProps = mergeProps( + { + className: cx('icon') + }, + ptm('icon') + ); + const boxProps = mergeProps( + { + className: cx('box', { checked }), + 'data-p-highlight': checked, + 'data-p-disabled': props.disabled + }, + ptm('box') + ); + + const icon = checked ? props.icon || : null; + const checkboxIcon = IconUtils.getJSXIcon(icon, { ...iconProps }, { props, checked }); + + return
{checkboxIcon}
; + }; return ( <>
-
- -
-
{checkboxIcon}
+ {createInputElement()} + {createBoxElement()}
{hasTooltip && } diff --git a/components/lib/checkbox/CheckboxBase.js b/components/lib/checkbox/CheckboxBase.js index 45b5aacea5..de4a4e57cc 100644 --- a/components/lib/checkbox/CheckboxBase.js +++ b/components/lib/checkbox/CheckboxBase.js @@ -2,42 +2,18 @@ import { ComponentBase } from '../componentbase/ComponentBase'; import { classNames } from '../utils/Utils'; const classes = { - icon: 'p-checkbox-icon p-c', - input: ({ props, checked, focusedState }) => - classNames('p-checkbox-box', { + box: 'p-checkbox-box', + input: 'p-checkbox-input', + icon: 'p-checkbox-icon', + root: ({ props, checked }) => + classNames('p-checkbox p-component', { 'p-highlight': checked, 'p-disabled': props.disabled, 'p-invalid': props.invalid, - 'p-focus': focusedState - }), - root: ({ props, checked, focusedState }) => - classNames('p-checkbox p-component', { - 'p-checkbox-checked': checked, - 'p-checkbox-disabled': props.disabled, - 'p-checkbox-focused': focusedState + 'p-variant-filled': props.variant === 'filled' }) }; -const styles = ` -.p-checkbox { - display: inline-flex; - cursor: pointer; - user-select: none; - vertical-align: bottom; - position: relative; -} - -.p-checkbox.p-checkbox-disabled { - cursor: auto; -} - -.p-checkbox-box { - display: flex; - justify-content: center; - align-items: center; -} -`; - export const CheckboxBase = ComponentBase.extend({ defaultProps: { __TYPE: 'Checkbox', @@ -67,7 +43,6 @@ export const CheckboxBase = ComponentBase.extend({ children: undefined }, css: { - classes, - styles + classes } }); diff --git a/components/lib/checkbox/checkbox.d.ts b/components/lib/checkbox/checkbox.d.ts index 807039146e..077e348105 100644 --- a/components/lib/checkbox/checkbox.d.ts +++ b/components/lib/checkbox/checkbox.d.ts @@ -22,7 +22,6 @@ export declare type CheckboxPassThroughType = PassThroughType>; + /** + * Used to pass attributes to the box's DOM element. + */ + box?: CheckboxPassThroughType>; /** * Uses to pass attributes to the icon's DOM element. */ @@ -48,14 +51,6 @@ export interface CheckboxPassThroughOptions { * @type {TooltipPassThroughOptions} */ tooltip?: TooltipPassThroughOptions; - /** - * Uses to pass attributes to the hidden input wrapper's DOM element. - */ - hiddenInputWrapper?: CheckboxPassThroughType>; - /** - * Uses to pass attributes to the hidden input's DOM element. - */ - hiddenInput?: CheckboxPassThroughType>; /** * Used to manage all lifecycle hooks * @see {@link ComponentHooks} @@ -79,17 +74,6 @@ export interface CheckboxContext { disabled: boolean; } -/** - * Defines current inline state in Checkbox component. - */ -export interface CheckboxState { - /** - * Current focus state as a boolean. - * @defaultValue false - */ - focused: boolean; -} - /** * Custom change event. * @see {@link CheckboxProps.onChange} @@ -98,19 +82,11 @@ export interface CheckboxState { */ interface CheckboxChangeEvent extends FormEvent {} -/** - * Custom click event. - * @see {@link CheckboxProps.onClick} - * @extends {FormEvent } - * @event - */ -interface CheckboxClickEvent extends FormEvent {} - /** * Defines valid properties in Checkbox component. In addition to these, all properties of HTMLDivElement can be used in this component. * @group Properties */ -export interface CheckboxProps extends Omit, HTMLDivElement>, 'onChange' | 'onClick' | 'ref'> { +export interface CheckboxProps extends Omit, HTMLDivElement>, 'onChange' | 'ref'> { /** * Unique identifier of the element. */ @@ -202,11 +178,6 @@ export interface CheckboxProps extends Omit} event - Browser event diff --git a/components/lib/componentbase/ComponentBase.js b/components/lib/componentbase/ComponentBase.js index 58b07cec28..a5edf8ecf5 100644 --- a/components/lib/componentbase/ComponentBase.js +++ b/components/lib/componentbase/ComponentBase.js @@ -95,25 +95,6 @@ const buttonStyles = ` z-index: 1; } `; -const checkboxStyles = ` -.p-checkbox { - display: inline-flex; - cursor: pointer; - user-select: none; - vertical-align: bottom; - position: relative; -} - -.p-checkbox.p-checkbox-disabled { - cursor: auto; -} - -.p-checkbox-box { - display: flex; - justify-content: center; - align-items: center; -} -`; const inputTextStyles = ` .p-inputtext { margin: 0; @@ -221,34 +202,6 @@ const inputTextStyles = ` display: block; width: 100%; } -`; -const radioButtonStyles = ` -.p-radiobutton { - display: inline-flex; - cursor: pointer; - user-select: none; - vertical-align: bottom; -} - -.p-radiobutton-box { - display: flex; - justify-content: center; - align-items: center; -} - -.p-radiobutton-icon { - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - transform: translateZ(0) scale(.1); - border-radius: 50%; - visibility: hidden; -} - -.p-radiobutton-box.p-highlight .p-radiobutton-icon { - transform: translateZ(0) scale(1.0, 1.0); - visibility: visible; -} - `; const iconStyles = ` .p-icon { @@ -456,9 +409,7 @@ const commonStyle = ` } ${buttonStyles} - ${checkboxStyles} ${inputTextStyles} - ${radioButtonStyles} ${iconStyles} } `; diff --git a/components/lib/confirmdialog/ConfirmDialogBase.js b/components/lib/confirmdialog/ConfirmDialogBase.js index 747703edce..9e71b6a627 100644 --- a/components/lib/confirmdialog/ConfirmDialogBase.js +++ b/components/lib/confirmdialog/ConfirmDialogBase.js @@ -23,6 +23,7 @@ export const ConfirmDialogBase = ComponentBase.extend({ breakpoints: null, children: undefined, className: null, + content: null, defaultFocus: 'accept', footer: null, icon: null, diff --git a/components/lib/confirmpopup/ConfirmPopupBase.js b/components/lib/confirmpopup/ConfirmPopupBase.js index 5fbcd4973a..c5ad494c92 100644 --- a/components/lib/confirmpopup/ConfirmPopupBase.js +++ b/components/lib/confirmpopup/ConfirmPopupBase.js @@ -82,6 +82,7 @@ export const ConfirmPopupBase = ComponentBase.extend({ children: undefined, className: null, closeOnEscape: true, + content: null, defaultFocus: 'accept', dismissable: true, footer: null, diff --git a/components/lib/dropdown/Dropdown.js b/components/lib/dropdown/Dropdown.js index eef24d2738..e0d4c1ef61 100644 --- a/components/lib/dropdown/Dropdown.js +++ b/components/lib/dropdown/Dropdown.js @@ -726,6 +726,7 @@ export const Dropdown = React.memo( if (selectedOption !== event.option) { updateEditableLabel(event.option); const optionValue = getOptionValue(event.option); + const selectedOptionIndex = findOptionIndexInList(event.option, visibleOptions); if (props.onChange) { props.onChange({ @@ -744,6 +745,8 @@ export const Dropdown = React.memo( } }); } + + changeFocusedOptionIndex(event.originalEvent, selectedOptionIndex); } }; diff --git a/components/lib/dropdown/DropdownBase.js b/components/lib/dropdown/DropdownBase.js index cdacda02ba..498e0c4722 100644 --- a/components/lib/dropdown/DropdownBase.js +++ b/components/lib/dropdown/DropdownBase.js @@ -25,6 +25,7 @@ const classes = { classNames('p-dropdown-item-group', { 'p-dropdown-item-empty': !optionGroupLabel || optionGroupLabel.length === 0 }), + itemGroupLabel: 'p-dropdown-item-group-label', dropdownIcon: 'p-dropdown-trigger-icon p-clickable', loadingIcon: 'p-dropdown-trigger-icon p-clickable', clearIcon: 'p-dropdown-clear-icon p-clickable', @@ -38,13 +39,16 @@ const classes = { 'p-input-filled': (context && context.inputStyle === 'filled') || PrimeReact.inputStyle === 'filled', 'p-ripple-disabled': (context && context.ripple === false) || PrimeReact.ripple === false }), - item: ({ selected, disabled, label, index, focusedOptionIndex }) => + item: ({ selected, disabled, label, index, focusedOptionIndex, highlightOnSelect }) => classNames('p-dropdown-item', { - 'p-highlight': selected, + 'p-highlight': selected && highlightOnSelect, 'p-disabled': disabled, 'p-focus': index === focusedOptionIndex, 'p-dropdown-item-empty': !label || label.length === 0 }), + itemLabel: 'p-dropdown-item-label', + checkIcon: 'p-dropdown-check-icon', + blankIcon: 'p-dropdown-blank-icon', wrapper: 'p-dropdown-items-wrapper', header: 'p-dropdown-header', footer: 'p-dropdown-footer', @@ -163,6 +167,8 @@ export const DropdownBase = ComponentBase.extend({ dropdownIcon: null, editable: false, emptyFilterMessage: null, + highlightOnSelect: true, + checkmark: false, emptyMessage: null, filter: false, filterBy: null, diff --git a/components/lib/dropdown/DropdownItem.js b/components/lib/dropdown/DropdownItem.js index bdb3460750..b226609ab4 100644 --- a/components/lib/dropdown/DropdownItem.js +++ b/components/lib/dropdown/DropdownItem.js @@ -2,10 +2,12 @@ import * as React from 'react'; import { useMergeProps } from '../hooks/Hooks'; import { Ripple } from '../ripple/Ripple'; import { classNames, ObjectUtils } from '../utils/Utils'; +import { CheckIcon } from '../icons/check'; +import { BlankIcon } from '../icons/blank'; export const DropdownItem = React.memo((props) => { const mergeProps = useMergeProps(); - const { ptm, cx, selected, disabled, option, label, index, focusedOptionIndex } = props; + const { ptm, cx, selected, disabled, option, label, index, focusedOptionIndex, checkmark, highlightOnSelect } = props; const getPTOptions = (key) => { return ptm(key, { @@ -30,7 +32,7 @@ export const DropdownItem = React.memo((props) => { { role: 'option', key: props.label, - className: classNames(option.className, cx('item', { selected, disabled, label, index, focusedOptionIndex })), + className: classNames(option.className, cx('item', { selected, disabled, label, index, focusedOptionIndex, highlightOnSelect })), style: props.style, onClick: (e) => onClick(e, index), 'aria-label': label, @@ -41,10 +43,39 @@ export const DropdownItem = React.memo((props) => { }, getPTOptions('item', { selected, disabled, option, label }) ); + const itemGroupLabelProps = mergeProps( + { + className: cx('itemLabel') + }, + getPTOptions('itemLabel') + ); + + const iconRenderer = () => { + if (selected) { + const checkIconProps = mergeProps( + { + className: cx('checkIcon') + }, + getPTOptions('checIcon') + ); + + return ; + } else { + const blankIconProps = mergeProps( + { + className: cx('blankIcon') + }, + getPTOptions('blankIcon') + ); + + return ; + } + }; return (
  • - {content} + {checkmark && iconRenderer()} + {content}
  • ); diff --git a/components/lib/dropdown/DropdownPanel.js b/components/lib/dropdown/DropdownPanel.js index 0d5f8e1860..2440546c9c 100644 --- a/components/lib/dropdown/DropdownPanel.js +++ b/components/lib/dropdown/DropdownPanel.js @@ -89,10 +89,12 @@ export const DropdownPanel = React.memo( style={style} template={props.itemTemplate} selected={props.isSelected(option)} + highlightOnSelect={props.highlightOnSelect} disabled={disabled} onClick={props.onOptionClick} ptm={ptm} cx={cx} + checkmark={props.checkmark} /> ); }); @@ -128,10 +130,18 @@ export const DropdownPanel = React.memo( }, getPTOptions('itemGroup') ); + const itemGroupLabelProps = mergeProps( + { + className: cx('itemGroupLabel') + }, + getPTOptions('itemGroupLabel') + ); return ( -
  • {groupContent}
  • +
  • + {groupContent} +
  • {groupChildrenContent}
    ); @@ -150,10 +160,12 @@ export const DropdownPanel = React.memo( style={style} template={props.itemTemplate} selected={props.isSelected(option)} + highlightOnSelect={props.highlightOnSelect} disabled={disabled} onClick={props.onOptionClick} ptm={ptm} cx={cx} + checkmark={props.checkmark} /> ); } diff --git a/components/lib/dropdown/dropdown.d.ts b/components/lib/dropdown/dropdown.d.ts index d0e0ff2ab8..66e705448e 100644 --- a/components/lib/dropdown/dropdown.d.ts +++ b/components/lib/dropdown/dropdown.d.ts @@ -93,10 +93,26 @@ export interface DropdownPassThroughOptions { * Uses to pass attributes to the item group's DOM element. */ itemGroup?: DropdownPassThroughType>; + /** + * Used to pass attributes to the item group label's DOM element. + */ + itemGroupLabel?: DropdownPassThroughType>; /** * Uses to pass attributes to the item's DOM element. */ item?: DropdownPassThroughType>; + /** + * Used to pass attributes to the item label's DOM element. + */ + itemLabel?: DropdownPassThroughType>; + /** + * Used to pass attributes to the check icon's DOM element. + */ + checkIcon?: DropdownPassThroughType>; + /** + * Used to pass attributes to the bank icon's DOM element. + */ + blankIcon?: DropdownPassThroughType>; /** * Uses to pass attributes to the empty message's DOM element. */ @@ -265,6 +281,16 @@ export interface DropdownProps extends Omit { // Reduce array length, by removing undefined elements at the end of array: const lastIndex = groupToDisplayedElements[group].length - 1; - const lastOrder = groupToDisplayedElements[group].findLastIndex((el) => el !== undefined); + const lastOrder = ObjectUtils.findLastIndex(groupToDisplayedElements[group], (el) => el !== undefined); if (lastOrder !== lastIndex) groupToDisplayedElements[group].splice(lastOrder + 1); diff --git a/components/lib/inputnumber/InputNumber.js b/components/lib/inputnumber/InputNumber.js index 3bd88f7796..8ea484a107 100644 --- a/components/lib/inputnumber/InputNumber.js +++ b/components/lib/inputnumber/InputNumber.js @@ -322,6 +322,12 @@ export const InputNumber = React.memo( return; } + if (event.shiftKey || event.altKey) { + isSpecialChar.current = true; + + return; + } + if (props.onKeyDown) { props.onKeyDown(event); @@ -333,21 +339,11 @@ export const InputNumber = React.memo( lastValue.current = event.target.value; - if (event.shiftKey || event.altKey) { - isSpecialChar.current = true; - - return; - } - let selectionStart = event.target.selectionStart; let selectionEnd = event.target.selectionEnd; let inputValue = event.target.value; let newValueStr = null; - if (event.altKey) { - event.preventDefault(); - } - switch (event.code) { //up case 'ArrowUp': @@ -379,6 +375,7 @@ export const InputNumber = React.memo( //enter and tab case 'Tab': + case 'NumpadEnter': case 'Enter': newValueStr = validateValue(parseValue(inputValue)); inputRef.current.value = formatValue(newValueStr); @@ -494,37 +491,17 @@ export const InputNumber = React.memo( break; default: - break; - } - }; - - const onInputKeyUp = (event) => { - if (props.disabled || props.readOnly) { - return; - } - - if (props.onKeyUp) { - props.onKeyUp(event); - - // do not continue if the user defined event wants to prevent - if (event.defaultPrevented) { - return; - } - } - - const code = event.which || event.keyCode; + event.preventDefault(); - if (code !== 13) { - // to submit a form - event.preventDefault(); - } + let char = event.key; + const _isDecimalSign = isDecimalSign(char); + const _isMinusSign = isMinusSign(char); - const char = String.fromCharCode(code); - const _isDecimalSign = isDecimalSign(char); - const _isMinusSign = isMinusSign(char); + if (((event.code.startsWith('Digit') || event.code.startsWith('Numpad')) && Number(char) >= 0 && Number(char) <= 9) || _isMinusSign || _isDecimalSign) { + insert(event, char, { isDecimalSign: _isDecimalSign, isMinusSign: _isMinusSign }); + } - if ((48 <= code && code <= 57) || _isMinusSign || _isDecimalSign) { - insert(event, char, { isDecimalSign: _isDecimalSign, isMinusSign: _isMinusSign }); + break; } }; @@ -1137,7 +1114,6 @@ export const InputNumber = React.memo( name={props.name} autoFocus={props.autoFocus} onKeyDown={onInputKeyDown} - onKeyPress={onInputKeyUp} onInput={onInput} onClick={onInputClick} onPointerDown={onInputPointerDown} diff --git a/components/lib/inputnumber/inputnumber.d.ts b/components/lib/inputnumber/inputnumber.d.ts index 32d5775cd4..4d6bff60a4 100644 --- a/components/lib/inputnumber/inputnumber.d.ts +++ b/components/lib/inputnumber/inputnumber.d.ts @@ -317,11 +317,6 @@ export interface InputNumberProps extends Omit} event - Browser event */ onKeyDown?(event: React.KeyboardEvent): void; - /** - * Callback to invoke when the key released. - * @param {React.KeyboardEvent} event - Browser event - */ - onKeyUp?(event: React.KeyboardEvent): void; /** * Used to get the child elements of the component. * @readonly diff --git a/components/lib/inputswitch/InputSwitch.js b/components/lib/inputswitch/InputSwitch.js index b3a08239f6..fcc02ecc53 100644 --- a/components/lib/inputswitch/InputSwitch.js +++ b/components/lib/inputswitch/InputSwitch.js @@ -11,12 +11,8 @@ export const InputSwitch = React.memo( const mergeProps = useMergeProps(); const context = React.useContext(PrimeReactContext); const props = InputSwitchBase.getProps(inProps, context); - const [focusedState, setFocusedState] = React.useState(false); const { ptm, cx, isUnstyled } = InputSwitchBase.setMetaData({ - props, - state: { - focused: focusedState - } + props }); useHandleStyle(InputSwitchBase.css.styles, isUnstyled, { name: 'inputswitch' }); @@ -24,18 +20,7 @@ export const InputSwitch = React.memo( const inputRef = React.useRef(props.inputRef); const checked = props.checked === props.trueValue; - const onClick = (event) => { - if (props.disabled) { - return; - } - - toggle(event); - DomHandler.focus(inputRef.current); - - event.preventDefault(); - }; - - const toggle = (event) => { + const onChange = (event) => { if (props.onChange) { const value = checked ? props.falseValue : props.trueValue; @@ -58,13 +43,11 @@ export const InputSwitch = React.memo( }; const onFocus = (event) => { - setFocusedState(true); - props.onFocus && props.onFocus(event); + props?.onFocus?.(event); }; const onBlur = (event) => { - setFocusedState(false); - props.onBlur && props.onBlur(event); + props?.onBlur?.(event); }; React.useImperativeHandle(ref, () => ({ @@ -90,9 +73,8 @@ export const InputSwitch = React.memo( const rootProps = mergeProps( { - className: classNames(props.className, cx('root', { focusedState, checked })), + className: classNames(props.className, cx('root', { checked })), style: props.style, - onClick, role: 'checkbox', 'aria-checked': checked, 'data-p-highlight': checked, @@ -101,29 +83,24 @@ export const InputSwitch = React.memo( otherProps, ptm('root') ); - const hiddenInputWrapperProps = mergeProps( - { - className: 'p-hidden-accessible' - }, - ptm('hiddenInputWrapper') - ); - const hiddenInputProps = mergeProps( + const inputProps = mergeProps( { type: 'checkbox', id: props.inputId, name: props.name, checked: checked, - onChange: toggle, + onChange: onChange, onFocus: onFocus, onBlur: onBlur, disabled: props.disabled, role: 'switch', tabIndex: props.tabIndex, 'aria-checked': checked, + className: cx('input'), ...ariaProps }, - ptm('hiddenInput') + ptm('input') ); const sliderProps = mergeProps( @@ -136,9 +113,7 @@ export const InputSwitch = React.memo( return ( <>
    -
    - -
    +
    {hasTooltip && } diff --git a/components/lib/inputswitch/InputSwitchBase.js b/components/lib/inputswitch/InputSwitchBase.js index ca23288ac1..5432f9660a 100644 --- a/components/lib/inputswitch/InputSwitchBase.js +++ b/components/lib/inputswitch/InputSwitchBase.js @@ -2,41 +2,16 @@ import { ComponentBase } from '../componentbase/ComponentBase'; import { classNames } from '../utils/Utils'; const classes = { - root: ({ props, focusedState, checked }) => + root: ({ props, checked }) => classNames('p-inputswitch p-component', { - 'p-inputswitch-checked': checked, + 'p-highlight': checked, 'p-disabled': props.disabled, - 'p-invalid': props.invalid, - 'p-focus': focusedState + 'p-invalid': props.invalid }), + input: 'p-inputswitch-input', slider: 'p-inputswitch-slider' }; -const styles = ` -@layer primereact { - .p-inputswitch { - position: relative; - display: inline-block; - } - - .p-inputswitch-slider { - position: absolute; - cursor: pointer; - top: 0; - left: 0; - right: 0; - bottom: 0; - border: 1px solid transparent; - } - - .p-inputswitch-slider:before { - position: absolute; - content: ""; - top: 50%; - } -} -`; - export const InputSwitchBase = ComponentBase.extend({ defaultProps: { __TYPE: 'InputSwitch', @@ -61,7 +36,6 @@ export const InputSwitchBase = ComponentBase.extend({ children: undefined }, css: { - classes, - styles + classes } }); diff --git a/components/lib/inputswitch/inputswitch.d.ts b/components/lib/inputswitch/inputswitch.d.ts index d1235296cd..95c1aadd2a 100644 --- a/components/lib/inputswitch/inputswitch.d.ts +++ b/components/lib/inputswitch/inputswitch.d.ts @@ -22,7 +22,6 @@ export declare type InputSwitchPassThroughType = PassThroughType>; /** - * Uses to pass attributes to the hidden input wrapper's DOM element. + * Uses to pass attributes to the input's DOM element. */ - hiddenInputWrapper?: InputSwitchPassThroughType>; - /** - * Uses to pass attributes to the hidden input's DOM element. - */ - hiddenInput?: InputSwitchPassThroughType>; + input?: InputSwitchPassThroughType>; /** * Uses to pass attributes tooltip's DOM element. * @type {TooltipPassThroughOptions} @@ -58,17 +53,6 @@ export interface InputSwitchPassThroughOptions { hooks?: ComponentHooks; } -/** - * Defines current inline state in InputSwitch component. - */ -export interface InputSwitchState { - /** - * Current focus state as a boolean. - * @defaultValue false - */ - focused: boolean; -} - /** * Custom change event. * @see {@link InputSwitchProps.onChange} diff --git a/components/lib/inputtext/InputText.js b/components/lib/inputtext/InputText.js index 2f0735f438..8066bf1844 100644 --- a/components/lib/inputtext/InputText.js +++ b/components/lib/inputtext/InputText.js @@ -4,7 +4,7 @@ import { useHandleStyle } from '../componentbase/ComponentBase'; import { useMergeProps } from '../hooks/Hooks'; import { KeyFilter } from '../keyfilter/KeyFilter'; import { Tooltip } from '../tooltip/Tooltip'; -import { DomHandler, ObjectUtils, classNames } from '../utils/Utils'; +import { DomHandler, ObjectUtils } from '../utils/Utils'; import { InputTextBase } from './InputTextBase'; export const InputText = React.memo( @@ -71,7 +71,7 @@ export const InputText = React.memo( const rootProps = mergeProps( { - className: classNames(props.className, cx('root', { isFilled })), + className: cx('root', { isFilled }), onBeforeInput: onBeforeInput, onInput: onInput, onKeyDown: onKeyDown, diff --git a/components/lib/inputtext/__snapshots__/InputText.spec.js.snap b/components/lib/inputtext/__snapshots__/InputText.spec.js.snap index ebd3d0795b..dc881df8d3 100644 --- a/components/lib/inputtext/__snapshots__/InputText.spec.js.snap +++ b/components/lib/inputtext/__snapshots__/InputText.spec.js.snap @@ -3,7 +3,7 @@ exports[`InputText when input has className only 1 className is printed 1`] = `
    diff --git a/components/lib/listbox/ListBoxBase.js b/components/lib/listbox/ListBoxBase.js index 35f22c5ba3..8fdaf18801 100644 --- a/components/lib/listbox/ListBoxBase.js +++ b/components/lib/listbox/ListBoxBase.js @@ -96,7 +96,7 @@ export const ListBoxBase = ComponentBase.extend({ listStyle: null, metaKeySelection: false, selectOnFocus: false, - autoOptionFocus: true, + autoOptionFocus: false, multiple: false, onChange: null, onFilterValueChange: null, diff --git a/components/lib/listbox/listbox.d.ts b/components/lib/listbox/listbox.d.ts index b2e9a7be6d..2561c3e440 100755 --- a/components/lib/listbox/listbox.d.ts +++ b/components/lib/listbox/listbox.d.ts @@ -339,6 +339,16 @@ export interface ListBoxProps extends Omit - classNames('p-checkbox-box', { - 'p-highlight': props.selected - }), transition: 'p-connected-overlay' }; @@ -240,6 +236,7 @@ export const MultiSelectBase = ComponentBase.extend({ itemClassName: null, itemTemplate: null, loading: false, + loadingIcon: null, maxSelectedLabels: null, name: null, onBlur: null, diff --git a/components/lib/multiselect/MultiSelectItem.js b/components/lib/multiselect/MultiSelectItem.js index e91409ce8f..63a21dae8b 100644 --- a/components/lib/multiselect/MultiSelectItem.js +++ b/components/lib/multiselect/MultiSelectItem.js @@ -2,12 +2,13 @@ import * as React from 'react'; import { useMergeProps } from '../hooks/Hooks'; import { CheckIcon } from '../icons/check'; import { Ripple } from '../ripple/Ripple'; +import { Checkbox } from '../checkbox/Checkbox'; import { IconUtils, ObjectUtils, classNames } from '../utils/Utils'; export const MultiSelectItem = React.memo((props) => { const [focusedState, setFocusedState] = React.useState(false); const mergeProps = useMergeProps(); - const { ptm, cx } = props; + const { ptm, cx, isUnstyled } = props; const getPTOptions = (key) => { return ptm(key, { @@ -59,14 +60,6 @@ export const MultiSelectItem = React.memo((props) => { getPTOptions('checkboxContainer') ); - const checkboxProps = mergeProps( - { - className: cx('checkbox', { itemProps: props }), - 'data-p-highlight': props.selected - }, - getPTOptions('checkbox') - ); - const itemProps = mergeProps( { className: classNames(props.className, props.option.className, cx('item', { itemProps: props })), @@ -86,7 +79,7 @@ export const MultiSelectItem = React.memo((props) => { return (
  • -
    {checkboxIcon}
    +
    {content} diff --git a/components/lib/multiselect/MultiSelectPanel.js b/components/lib/multiselect/MultiSelectPanel.js index 9dd06a4e2e..f46eb9c95f 100644 --- a/components/lib/multiselect/MultiSelectPanel.js +++ b/components/lib/multiselect/MultiSelectPanel.js @@ -120,6 +120,7 @@ export const MultiSelectPanel = React.memo( disabled={disabled} className={props.itemClassName} checkboxIcon={props.checkboxIcon} + isUnstyled={isUnstyled} ptm={ptm} cx={cx} /> @@ -197,6 +198,7 @@ export const MultiSelectPanel = React.memo( disabled={disabled} className={props.itemClassName} checkboxIcon={props.checkboxIcon} + isUnstyled={isUnstyled} ptm={ptm} cx={cx} /> diff --git a/components/lib/multiselect/multiselect.d.ts b/components/lib/multiselect/multiselect.d.ts index 042fdc0f5a..bc9b4f407b 100644 --- a/components/lib/multiselect/multiselect.d.ts +++ b/components/lib/multiselect/multiselect.d.ts @@ -464,7 +464,7 @@ export interface MultiSelectProps extends Omit; + dropdownIcon?: IconType | undefined; /** * Template to display when filtering does not return any results. * @defaultValue No records found @@ -550,6 +550,15 @@ export interface MultiSelectProps extends Omit React.ReactNode); + /** + * Displays a loader to indicate data load is in progress. + * @defaultValue false + */ + loading?: boolean | undefined; + /** + * The icon to show while indicating data load is in progress. + */ + loadingIcon?: IconType | undefined; /** * Decides how many selected item labels to show at most. */ @@ -685,6 +694,16 @@ export interface MultiSelectProps extends Omit { - const listElement = getListElement(); - const selectedFirstItem = DomHandler.findSingle(listElement, '[data-p-highlight="true"]') || DomHandler.findSingle(listElement, '[data-pc-section="item"]'); - const itemList = listElement && listElement.children ? [...listElement.children] : []; + const findCurrentFocusedIndex = (listElement) => { + if (focusedOptionIndex === -1) { + const itemList = listElement && listElement.children ? [...listElement.children] : []; + let selectedOptionIndex = findFirstSelectedOptionIndex(listElement, itemList); + + if (props.autoOptionFocus && selectedOptionIndex === -1) { + selectedOptionIndex = findFirstFocusedOptionIndex(listElement, itemList); + } - if (selectedFirstItem && itemList.length > 0) { - const findIndex = ObjectUtils.findIndexInList(selectedFirstItem, itemList); + return selectedOptionIndex; + } - setFocused(true); + return -1; + }; - const index = focusedOptionIndex !== -1 ? focusedOptionIndex : selectedFirstItem ? findIndex : -1; + const findFirstSelectedOptionIndex = (listElement, itemList) => { + if (selectionState.length) { + const selectedFirstItem = DomHandler.findSingle(listElement, '[data-p-highlight="true"]'); - changeFocusedOptionIndex(index); - props.onFocus && props.onFocus(event); + return ObjectUtils.findIndexInList(selectedFirstItem, itemList); } + + return -1; + }; + + const findFirstFocusedOptionIndex = (listElement, itemList) => { + const firstFocusableItem = DomHandler.findSingle(listElement, '[data-pc-section="item"]'); + + return ObjectUtils.findIndexInList(firstFocusableItem, itemList); + }; + + const onListFocus = (event) => { + setFocused(true); + + const listElement = getListElement(); + const currentFocusedIndex = findCurrentFocusedIndex(listElement); + + changeFocusedOptionIndex(currentFocusedIndex); + + props.onFocus && props.onFocus(event); }; const onListBlur = (event) => { @@ -141,7 +166,6 @@ export const OrderList = React.memo( }; const onOptionMouseDown = (index) => { - setFocused(true); setFocusedOptionIndex(index); }; @@ -248,7 +272,15 @@ export const OrderList = React.memo( const listElement = getListElement(); const items = DomHandler.find(listElement, '[data-pc-section="item"]'); - let order = index >= items.length ? items.length - 1 : index < 0 ? 0 : index; + let order; + + if (index >= items.length) { + order = items.length - 1; + } else if (index < 0) { + return; + } else { + order = index; + } const _focusedOptionIndex = items[order] ? items[order].getAttribute('id') : -1; diff --git a/components/lib/orderlist/OrderListBase.js b/components/lib/orderlist/OrderListBase.js index 2e301a9be6..0156dcab15 100644 --- a/components/lib/orderlist/OrderListBase.js +++ b/components/lib/orderlist/OrderListBase.js @@ -99,6 +99,7 @@ export const OrderListBase = ComponentBase.extend({ moveDownIcon: null, moveBottomIcon: null, dataKey: null, + autoOptionFocus: true, breakpoint: '960px', onChange: null, itemTemplate: null, diff --git a/components/lib/orderlist/orderlist.d.ts b/components/lib/orderlist/orderlist.d.ts index 5c254a2b2a..3239f88312 100755 --- a/components/lib/orderlist/orderlist.d.ts +++ b/components/lib/orderlist/orderlist.d.ts @@ -171,6 +171,11 @@ export interface OrderListProps extends Omit ({ + root: ({ parent }) => ({ className: classNames('w-16 !h-16 !rounded-full justify-center z-10', { - 'rotate-45': state.visible + 'rotate-45': parent.state.visible }) }), label: { @@ -1157,11 +1157,11 @@ const Tailwind = { }) }) }, - dropdownButton: ({ props }) => ({ - root: { - className: classNames({ 'rounded-l-none': props.showIcon }) - } - }), + dropdownButton: { + root: ({ props }) => ({ + className: classNames({ 'rounded-l-none': props.icon }) + }) + }, panel: ({ props }) => ({ className: classNames('bg-white dark:bg-gray-900', 'min-w-full', { 'shadow-md border-0 absolute': !props.inline, @@ -1171,7 +1171,7 @@ const Tailwind = { header: { className: classNames('flex items-center justify-between', 'p-2 text-gray-700 dark:text-white/80 bg-white dark:bg-gray-900 font-semibold m-0 border-b border-gray-300 dark:border-blue-900/40 rounded-t-lg') }, - previousbutton: { + previousButton: { className: classNames( 'flex items-center justify-center cursor-pointer overflow-hidden relative', 'w-8 h-8 text-gray-600 dark:text-white/70 border-0 bg-transparent rounded-full transition-colors duration-200 ease-in-out', @@ -1185,7 +1185,7 @@ const Tailwind = { yearTitle: { className: classNames('text-gray-700 dark:text-white/80 transition duration-200 font-semibold p-2', 'hover:text-blue-500') }, - nextbutton: { + nextButton: { className: classNames( 'flex items-center justify-center cursor-pointer overflow-hidden relative', 'w-8 h-8 text-gray-600 dark:text-white/70 border-0 bg-transparent rounded-full transition-colors duration-200 ease-in-out', @@ -1195,10 +1195,10 @@ const Tailwind = { table: { className: classNames('border-collapse w-full', 'my-2') }, - tableheadercell: 'p-2', + tableHeaderCell: 'p-2', weekday: 'text-gray-600 dark:text-white/70', day: 'p-2', - daylabel: ({ context }) => ({ + dayLabel: ({ context }) => ({ className: classNames( 'w-10 h-10 rounded-full transition-shadow duration-200 border-transparent border', 'flex items-center justify-center mx-auto overflow-hidden relative', @@ -1213,7 +1213,7 @@ const Tailwind = { } ) }), - monthpicker: 'my-2', + monthPicker: 'my-2', month: ({ context }) => ({ className: classNames( 'w-1/3 inline-flex items-center justify-center cursor-pointer overflow-hidden relative', @@ -1222,7 +1222,7 @@ const Tailwind = { { 'text-gray-600 dark:text-white/70 bg-transprent hover:bg-gray-200 dark:hover:bg-gray-800/80': !context.selected && !context.disabled, 'text-blue-700 bg-blue-100 hover:bg-blue-200': context.selected && !context.disabled } ) }), - yearpicker: { + yearPicker: { className: classNames('my-2') }, year: ({ context }) => ({ @@ -1236,29 +1236,29 @@ const Tailwind = { } ) }), - timepicker: { + timePicker: { className: classNames('flex justify-center items-center', 'border-t-1 border-solid border-gray-300 p-2') }, - separatorcontainer: 'flex items-center flex-col px-2', + separatorContainer: 'flex items-center flex-col px-2', separator: 'text-xl', - hourpicker: 'flex items-center flex-col px-2', - minutepicker: 'flex items-center flex-col px-2', - ampmpicker: 'flex items-center flex-col px-2', - incrementbutton: { + hourPicker: 'flex items-center flex-col px-2', + minutePicker: 'flex items-center flex-col px-2', + ampmPicker: 'flex items-center flex-col px-2', + incrementButton: { className: classNames( 'flex items-center justify-center cursor-pointer overflow-hidden relative', 'w-8 h-8 text-gray-600 dark:text-white/70 border-0 bg-transparent rounded-full transition-colors duration-200 ease-in-out', 'hover:text-gray-700 dark:hover:text-white/80 hover:border-transparent hover:bg-gray-200 dark:hover:bg-gray-800/80 ' ) }, - decrementbutton: { + decrementButton: { className: classNames( 'flex items-center justify-center cursor-pointer overflow-hidden relative', 'w-8 h-8 text-gray-600 dark:text-white/70 border-0 bg-transparent rounded-full transition-colors duration-200 ease-in-out', 'hover:text-gray-700 dark:hover:text-white/80 hover:border-transparent hover:bg-gray-200 dark:hover:bg-gray-800/80 ' ) }, - groupcontainer: 'flex', + groupContainer: 'flex', group: { className: classNames('flex-1', 'border-l border-gray-300 pr-0.5 pl-0.5 pt-0 pb-0', 'first:pl-0 first:border-l-0') }, diff --git a/components/lib/picklist/PickList.js b/components/lib/picklist/PickList.js index 92554e1033..a74b599c5e 100644 --- a/components/lib/picklist/PickList.js +++ b/components/lib/picklist/PickList.js @@ -226,21 +226,45 @@ export const PickList = React.memo( const sourceList = getVisibleList(props.source, 'source'); const targetList = getVisibleList(props.target, 'target'); - const onListFocus = (event, type) => { - const listElement = getListElement(type); - const selectedFirstItem = DomHandler.findSingle(listElement, '[data-p-highlight="true"]') || DomHandler.findSingle(listElement, '[data-pc-section="item"]'); - const itemList = listElement && listElement.children ? [...listElement.children] : []; + const findCurrentFocusedIndex = (listElement) => { + if (focusedOptionIndex === -1) { + const itemList = listElement && listElement.children ? [...listElement.children] : []; + let selectedOptionIndex = findFirstSelectedOptionIndex(listElement, itemList); - if (selectedFirstItem) { - const findIndex = ObjectUtils.findIndexInList(selectedFirstItem, itemList); + if (props.autoOptionFocus && selectedOptionIndex === -1) { + selectedOptionIndex = findFirstFocusedOptionIndex(listElement, itemList); + } + + return selectedOptionIndex; + } - setFocused({ ...focused, [type]: true }); + return -1; + }; - const index = focusedOptionIndex !== -1 ? focusedOptionIndex : selectedFirstItem ? findIndex : -1; + const findFirstSelectedOptionIndex = (listElement, itemList) => { + if (sourceSelectionState.length || targetSelectionState.length) { + const selectedFirstItem = DomHandler.findSingle(listElement, '[data-p-highlight="true"]'); - changeFocusedOptionIndex(index, type); - props.onFocus && props.onFocus(event); + return ObjectUtils.findIndexInList(selectedFirstItem, itemList); } + + return -1; + }; + + const findFirstFocusedOptionIndex = (listElement, itemList) => { + const firstFocusableItem = DomHandler.findSingle(listElement, '[data-pc-section="item"]'); + + return ObjectUtils.findIndexInList(firstFocusableItem, itemList); + }; + + const onListFocus = (event, type) => { + setFocused({ ...focused, [type]: true }); + + const listElement = getListElement(type); + const currentFocusedIndex = findCurrentFocusedIndex(listElement); + + changeFocusedOptionIndex(currentFocusedIndex, type); + props.onFocus && props.onFocus(event); }; const onListBlur = (event, type) => { @@ -467,7 +491,15 @@ export const PickList = React.memo( const items = DomHandler.find(listElement, '[data-pc-section="item"]'); - let order = index >= items.length ? items.length - 1 : index < 0 ? 0 : index; + let order; + + if (index >= items.length) { + order = items.length - 1; + } else if (index < 0) { + return; + } else { + order = index; + } setFocusedOptionIndex(items[order].getAttribute('id')); scrollInViewWithFocus(items[order].getAttribute('id'), type); diff --git a/components/lib/picklist/PickListBase.js b/components/lib/picklist/PickListBase.js index 0be6ed9935..4d7f413234 100644 --- a/components/lib/picklist/PickListBase.js +++ b/components/lib/picklist/PickListBase.js @@ -114,6 +114,7 @@ export const PickListBase = ComponentBase.extend({ targetFilterTemplate: null, tabIndex: 0, dataKey: null, + autoOptionFocus: true, breakpoint: '960px', itemTemplate: null, sourceItemTemplate: null, diff --git a/components/lib/picklist/picklist.d.ts b/components/lib/picklist/picklist.d.ts index ada61bbb95..c4336af677 100755 --- a/components/lib/picklist/picklist.d.ts +++ b/components/lib/picklist/picklist.d.ts @@ -259,6 +259,11 @@ export interface PickListProps { * Template for the target list caption. */ targetHeader?: React.ReactNode | undefined; + /** + * Whether to focus on the first visible or selected element. + * @defaultValue true + */ + autoOptionFocus?: boolean | undefined; /** * Inline style of the element. */ diff --git a/components/lib/radiobutton/RadioButton.js b/components/lib/radiobutton/RadioButton.js index 5bba326b67..3b17e015b4 100644 --- a/components/lib/radiobutton/RadioButton.js +++ b/components/lib/radiobutton/RadioButton.js @@ -12,29 +12,25 @@ export const RadioButton = React.memo( const context = React.useContext(PrimeReactContext); const props = RadioButtonBase.getProps(inProps, context); - const [focusedState, setFocusedState] = React.useState(false); const elementRef = React.useRef(null); const inputRef = React.useRef(props.inputRef); const { ptm, cx, isUnstyled } = RadioButtonBase.setMetaData({ - props, - state: { - focused: focusedState - } + props }); - useHandleStyle(RadioButtonBase.css.styles, isUnstyled, { name: 'radiobutton', styled: true }); + useHandleStyle(RadioButtonBase.css.styles, isUnstyled, { name: 'radiobutton' }); const select = (event) => { - onClick(event); + onChange(event); }; - const onClick = (event) => { - if (props.disabled) { + const onChange = (event) => { + if (props.disabled || props.readonly) { return; } - if (props.onChange || props.onClick) { + if (props.onChange) { const checked = props.checked; const radioClicked = event.target instanceof HTMLDivElement; const inputClicked = event.target === inputRef.current; @@ -61,7 +57,7 @@ export const RadioButton = React.memo( } }; - props.onClick && props.onClick(eventData); + props?.onChange?.(eventData); // do not continue if the user defined click wants to prevent if (event.defaultPrevented) { @@ -69,7 +65,7 @@ export const RadioButton = React.memo( } if (isInputToggled || isRadioToggled) { - props.onChange && props.onChange(eventData); + props?.onChange?.(eventData); if (isRadioToggled) { inputRef.current.checked = value; @@ -77,24 +73,24 @@ export const RadioButton = React.memo( } DomHandler.focus(inputRef.current); - event.preventDefault(); } }; - const onFocus = () => { - setFocusedState(true); + const onFocus = (event) => { + props?.onFocus?.(event); }; - const onBlur = () => { - setFocusedState(false); + const onBlur = (event) => { + props?.onBlur?.(event); }; - const onKeyDown = (event) => { - if (event.code === 'Space' || event.key === ' ') { - // event.key is for Android support - onClick(event); - } - }; + React.useImperativeHandle(ref, () => ({ + props, + select, + focus: () => DomHandler.focus(inputRef.current), + getElement: () => elementRef.current, + getInput: () => inputRef.current + })); React.useEffect(() => { if (inputRef.current) { @@ -112,75 +108,71 @@ export const RadioButton = React.memo( } }); - React.useImperativeHandle(ref, () => ({ - props, - select, - focus: () => DomHandler.focus(inputRef.current), - getElement: () => elementRef.current, - getInput: () => inputRef.current - })); - const hasTooltip = ObjectUtils.isNotEmpty(props.tooltip); const otherProps = RadioButtonBase.getOtherProps(props); - const ariaProps = ObjectUtils.reduceKeys(otherProps, DomHandler.ARIA_PROPS); const rootProps = mergeProps( { - className: classNames(props.className, cx('root', { focusedState })), + id: props.id, + className: classNames(props.className, cx('root')), style: props.style, - onClick: onClick, 'data-p-checked': props.checked }, RadioButtonBase.getOtherProps(props), ptm('root') ); - const hiddenInputWrapperProps = mergeProps( - { - className: 'p-hidden-accessible' - }, - ptm('hiddenInputWrapper') - ); - - const hiddenInputProps = mergeProps( - { - type: 'radio', - name: props.name, - defaultChecked: props.checked, - onFocus: onFocus, - onBlur: onBlur, - onKeyDown: onKeyDown, - disabled: props.disabled, - required: props.required, - tabIndex: props.tabIndex, - ...ariaProps - }, - ptm('hiddenInput') - ); - - const inputProps = mergeProps( - { - className: cx('input', { focusedState }) - }, - ptm('input') - ); + const createInputElement = () => { + const ariaProps = ObjectUtils.reduceKeys(otherProps, DomHandler.ARIA_PROPS); + const inputProps = mergeProps( + { + id: props.inputId, + type: 'radio', + name: props.name, + defaultChecked: props.checked, + onFocus: onFocus, + onBlur: onBlur, + onChange: onChange, + disabled: props.disabled, + readonly: props.readonly, + required: props.required, + tabIndex: props.tabIndex, + className: cx('input'), + ...ariaProps + }, + ptm('input') + ); + + return ; + }; - const iconProps = mergeProps( - { - className: cx('icon') - }, - ptm('icon') - ); + const createBoxElement = () => { + const boxProps = mergeProps( + { + className: cx('box') + }, + ptm('box') + ); + + const iconProps = mergeProps( + { + className: cx('icon') + }, + ptm('icon') + ); + + return ( +
    +
    +
    + ); + }; return ( <> -
    -
    - -
    -
    -
    -
    +
    + {createInputElement()} + {createBoxElement()}
    {hasTooltip && } diff --git a/components/lib/radiobutton/RadioButtonBase.js b/components/lib/radiobutton/RadioButtonBase.js index 0e8bd3fe38..f1a50200bb 100644 --- a/components/lib/radiobutton/RadioButtonBase.js +++ b/components/lib/radiobutton/RadioButtonBase.js @@ -2,52 +2,17 @@ import { ComponentBase } from '../componentbase/ComponentBase'; import { classNames } from '../utils/Utils'; const classes = { - root: ({ props, focusedState }) => + root: ({ props }) => classNames('p-radiobutton p-component', { - 'p-radiobutton-checked': props.checked, - 'p-radiobutton-disabled': props.disabled, - 'p-radiobutton-focused': focusedState, - 'p-invalid': props.invalid - }), - input: ({ props, focusedState }) => - classNames('p-radiobutton-box', { 'p-highlight': props.checked, 'p-disabled': props.disabled, - 'p-focus': focusedState + 'p-invalid': props.invalid }), + box: 'p-radiobutton-box', + input: 'p-radiobutton-input', icon: 'p-radiobutton-icon' }; -const styles = ` -@layer primereact { - .p-radiobutton { - display: inline-flex; - cursor: pointer; - user-select: none; - vertical-align: bottom; - } - - .p-radiobutton-box { - display: flex; - justify-content: center; - align-items: center; - } - - .p-radiobutton-icon { - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - transform: translateZ(0) scale(.1); - border-radius: 50%; - visibility: hidden; - } - - .p-radiobutton-box.p-highlight .p-radiobutton-icon { - transform: translateZ(0) scale(1.0, 1.0); - visibility: visible; - } -} -`; - export const RadioButtonBase = ComponentBase.extend({ defaultProps: { __TYPE: 'RadioButton', @@ -71,7 +36,6 @@ export const RadioButtonBase = ComponentBase.extend({ children: undefined }, css: { - classes, - styles + classes } }); diff --git a/components/lib/radiobutton/radiobutton.d.ts b/components/lib/radiobutton/radiobutton.d.ts index adb80a3870..b2324eccb7 100644 --- a/components/lib/radiobutton/radiobutton.d.ts +++ b/components/lib/radiobutton/radiobutton.d.ts @@ -8,6 +8,7 @@ * */ import * as React from 'react'; +import { CheckboxPassThroughType } from '../checkbox/checkbox'; import { ComponentHooks } from '../componentbase/componentbase'; import { PassThroughOptions } from '../passthrough'; import { TooltipPassThroughOptions } from '../tooltip/tooltip'; @@ -22,7 +23,6 @@ export declare type RadioButtonPassThroughType = PassThroughType>; - /** - * Uses to pass attributes to the input's DOM element. - */ - input?: RadioButtonPassThroughType>; /** * Uses to pass attributes to the icon's DOM element. */ icon?: RadioButtonPassThroughType>; /** - * Uses to pass attributes to the hidden accessible DOM element wrapper. + * Uses to pass attributes to the input's DOM element. */ - hiddenInputWrapper?: RadioButtonPassThroughType>; + input?: RadioButtonPassThroughType>; /** - * Uses to pass attributes to the hidden accessible DOM element. + * Used to pass attributes to the box's DOM element. */ - hiddenInput?: RadioButtonPassThroughType>; + box?: CheckboxPassThroughType>; /** * Uses to pass attributes tooltip's DOM element. * @type {TooltipPassThroughOptions} @@ -62,17 +58,6 @@ export interface RadioButtonPassThroughOptions { hooks?: ComponentHooks; } -/** - * Defines current inline state in RadioButton component. - */ -export interface RadioButtonState { - /** - * Current focused state as a boolean. - * @defaultValue false - */ - focused: boolean; -} - /** * Custom change event. * @see {@link RadioButtonProps.onChange} @@ -81,19 +66,11 @@ export interface RadioButtonState { */ interface RadioButtonChangeEvent extends FormEvent {} -/** - * Custom click event. - * @see {@link RadioButtonProps.onClick} - * @extends {FormEvent} - * @event - */ -interface RadioButtonClickEvent extends FormEvent {} - /** * Defines valid properties in RadioButton component. In addition to these, all properties of HTMLDivElement can be used in this component. * @group Properties */ -export interface RadioButtonProps extends Omit, HTMLDivElement>, 'onChange' | 'onClick' | 'ref' | 'pt'> { +export interface RadioButtonProps extends Omit, HTMLDivElement>, 'onChange' | 'ref' | 'pt'> { /** * When present, it specifies that the component should automatically get focus on load. * @defaultValue false @@ -126,10 +103,15 @@ export interface RadioButtonProps extends Omit>; + /** + * Uses to pass attributes to the custom icons content's DOM element. + */ + icons?: SidebarPassThroughType>; /** * Uses to pass attributes to the close icon's DOM element. */ @@ -50,10 +54,6 @@ export interface SidebarPassThroughOptions { * Uses to pass attributes to the content's DOM element. */ content?: SidebarPassThroughType>; - /** - * Uses to pass attributes to the custom icons content's DOM element. - */ - icons?: SidebarPassThroughType>; /** * Uses to pass attributes to the mask's DOM element. */ diff --git a/components/lib/splitter/Splitter.js b/components/lib/splitter/Splitter.js index 1a8e091aa3..6cddd15d13 100644 --- a/components/lib/splitter/Splitter.js +++ b/components/lib/splitter/Splitter.js @@ -253,24 +253,24 @@ export const Splitter = React.memo( } case 'Home': { - resizePanel(index, 100, minSize); + resizePanel(index, 100 - minSize, minSize); event.preventDefault(); break; } case 'End': { - resizePanel(index, minSize, 100); + resizePanel(index, minSize, 100 - minSize); event.preventDefault(); break; } case 'Enter': { - if (prevSize.current > 100 - (minSize || 5)) { - resizePanel(index, minSize, 100); + if (prevSize.current >= 100 - (minSize || 5)) { + resizePanel(index, minSize, 100 - minSize); } else { - resizePanel(index, 100, minSize); + resizePanel(index, 100 - minSize, minSize); } event.preventDefault(); @@ -386,8 +386,7 @@ export const Splitter = React.memo( onTouchStart: (event) => onGutterTouchStart(event, index), onTouchMove: (event) => onGutterTouchMove(event), onTouchEnd: (event) => onGutterTouchEnd(event), - 'data-p-splitter-gutter-resizing': false, - role: 'separator' + 'data-p-splitter-gutter-resizing': false }, ptm('gutter') ); @@ -396,6 +395,7 @@ export const Splitter = React.memo( { tabIndex: getPanelProp(panel, 'tabIndex') || 0, className: cx('gutterHandler'), + role: 'separator', 'aria-orientation': horizontal ? 'vertical' : 'horizontal', 'aria-controls': panelId, 'aria-label': getPanelProp(panel, 'aria-label'), diff --git a/components/lib/splitter/__snapshots__/Splitter.spec.js.snap b/components/lib/splitter/__snapshots__/Splitter.spec.js.snap index ba089e7797..2dd53bf996 100644 --- a/components/lib/splitter/__snapshots__/Splitter.spec.js.snap +++ b/components/lib/splitter/__snapshots__/Splitter.spec.js.snap @@ -23,7 +23,6 @@ exports[`Splitter Nested 1`] = ` class="p-splitter-gutter" data-p-splitter-gutter-resizing="false" data-pc-section="gutter" - role="separator" style="width: 4px;" > @@ -66,7 +66,6 @@ exports[`Splitter Nested 1`] = ` class="p-splitter-gutter" data-p-splitter-gutter-resizing="false" data-pc-section="gutter" - role="separator" style="height: 4px;" > @@ -109,7 +109,6 @@ exports[`Splitter Nested 1`] = ` class="p-splitter-gutter" data-p-splitter-gutter-resizing="false" data-pc-section="gutter" - role="separator" style="width: 4px;" > @@ -165,7 +165,6 @@ exports[`Splitter Single Panel with size 1`] = ` class="p-splitter-gutter" data-p-splitter-gutter-resizing="false" data-pc-section="gutter" - role="separator" style="height: 4px;" > @@ -207,7 +207,6 @@ exports[`Splitter Single Panel without size 1`] = ` class="p-splitter-gutter" data-p-splitter-gutter-resizing="false" data-pc-section="gutter" - role="separator" style="height: 4px;" > @@ -249,7 +249,6 @@ exports[`Splitter Splitter requires two SplitterPanel components to wrap. 1`] = class="p-splitter-gutter" data-p-splitter-gutter-resizing="false" data-pc-section="gutter" - role="separator" style="width: 4px;" > @@ -301,7 +301,6 @@ exports[`Splitter Vertical layout 1`] = ` class="p-splitter-gutter" data-p-splitter-gutter-resizing="false" data-pc-section="gutter" - role="separator" style="height: 4px;" > diff --git a/components/lib/splitter/splitter.d.ts b/components/lib/splitter/splitter.d.ts index d69f2f45db..1c9b0e8a19 100644 --- a/components/lib/splitter/splitter.d.ts +++ b/components/lib/splitter/splitter.d.ts @@ -139,11 +139,6 @@ interface SplitterPanelProps extends Omit { - if (!props.disabled && props.onChange) { + if (!props.disabled && props.onChange && !props.readonly) { props.onChange({ originalEvent: e, value: !props.checked, @@ -56,13 +52,11 @@ export const ToggleButton = React.memo( }; const onFocus = (event) => { - setFocusedState(true); - props.onFocus && props.onFocus(event); + props?.onFocus?.(event); }; const onBlur = (event) => { - setFocusedState(false); - props.onBlur && props.onBlur(event); + props?.onBlur?.(event); }; const createIcon = () => { @@ -108,27 +102,51 @@ export const ToggleButton = React.memo( ref: elementRef, id: props.id, className: cx('root', { hasIcon, hasLabel }), + 'data-p-highlight': props.checked, + 'data-p-disabled': props.disabled + }, + ToggleButtonBase.getOtherProps(props), + ptm('root') + ); + + const inputProps = mergeProps( + { + id: props.inputId, + className: cx('input'), style: props.style, - onClick: toggle, + onChange: toggle, onFocus: onFocus, onBlur: onBlur, onKeyDown: onKeyDown, tabIndex: tabIndex, - role: 'button', + role: 'switch', + type: 'checkbox', 'aria-pressed': props.checked, - 'data-p-highlight': props.checked, - 'data-p-disabled': props.disabled + 'aria-invalid': props.invalid, + disabled: props.disabled, + readonly: props.readonly, + value: props.checked, + checked: props.checked }, - ToggleButtonBase.getOtherProps(props), - ptm('root') + ptm('input') + ); + + const boxProps = mergeProps( + { + className: cx('box', { hasIcon, hasLabel }) + }, + ptm('box') ); return ( <>
    - {iconElement} - {label} - + +
    + {iconElement} + {label} + +
    {hasTooltip && } diff --git a/components/lib/togglebutton/ToggleButtonBase.js b/components/lib/togglebutton/ToggleButtonBase.js index 35f69bd394..b2092977e8 100644 --- a/components/lib/togglebutton/ToggleButtonBase.js +++ b/components/lib/togglebutton/ToggleButtonBase.js @@ -2,23 +2,27 @@ import { ComponentBase } from '../componentbase/ComponentBase'; import { classNames } from '../utils/Utils'; const classes = { - label: 'p-button-label', - icon: ({ props, label }) => - classNames('p-button-icon p-c', { - 'p-button-icon-left': props.iconPos === 'left' && label, - 'p-button-icon-right': props.iconPos === 'right' && label - }), - root: ({ props, hasIcon, hasLabel }) => + root: ({ props }) => classNames( - 'p-button p-togglebutton p-component', + 'p-togglebutton p-component', { - 'p-button-icon-only': hasIcon && !hasLabel, - 'p-highlight': props.checked, 'p-disabled': props.disabled, + 'p-highlight': props.checked, 'p-invalid': props.invalid }, props.className - ) + ), + input: 'p-togglebutton-input', + box: ({ hasIcon, hasLabel }) => + classNames('p-button p-component', { + 'p-button-icon-only': hasIcon && !hasLabel + }), + icon: ({ props, label }) => + classNames('p-button-icon', { + 'p-button-icon-left': props.iconPos === 'left' && label, + 'p-button-icon-right': props.iconPos === 'right' && label + }), + label: 'p-button-label' }; export const ToggleButtonBase = ComponentBase.extend({ diff --git a/components/lib/togglebutton/togglebutton.d.ts b/components/lib/togglebutton/togglebutton.d.ts index e1ef006fd8..b28df7858a 100644 --- a/components/lib/togglebutton/togglebutton.d.ts +++ b/components/lib/togglebutton/togglebutton.d.ts @@ -8,6 +8,7 @@ * */ import * as React from 'react'; +import { CheckboxPassThroughType } from '../checkbox/checkbox'; import { ComponentHooks } from '../componentbase/componentbase'; import { PassThroughOptions } from '../passthrough'; import { TooltipPassThroughOptions } from '../tooltip/tooltip'; @@ -50,6 +51,14 @@ export interface ToggleButtonPassThroughOptions { * @see {@link ComponentHooks} */ hooks?: ComponentHooks; + /** + * Uses to pass attributes to the input's DOM element. + */ + input?: ToggleButtonPassThroughType>; + /** + * Used to pass attributes to the box's DOM element. + */ + box?: CheckboxPassThroughType>; } /** * Custom toggle button change target options @@ -122,6 +131,16 @@ export interface ToggleButtonProps extends Omit { - if (validateDropNode(dragState.current.path, event.path)) { + if (validateDropNode(dragState.current?.path, event.path)) { const value = cloneValue(props.value); let dragPaths = dragState.current.path.split('-'); @@ -210,7 +210,7 @@ export const Tree = React.memo( }; const validateDropPoint = (event) => { - let _validateDrop = validateDrop(dragState.current.path, event.path); + let _validateDrop = validateDrop(dragState.current?.path, event.path); if (_validateDrop) { //child dropped to next sibling's drop point diff --git a/components/lib/tree/UITreeNode.js b/components/lib/tree/UITreeNode.js index 96a580efc2..055774ab04 100644 --- a/components/lib/tree/UITreeNode.js +++ b/components/lib/tree/UITreeNode.js @@ -714,7 +714,7 @@ export const UITreeNode = React.memo((props) => { getPTOptions('nodeIcon') ); - return ; + return IconUtils.getJSXIcon(icon, { ...nodeIconProps }, { props }); } return null; diff --git a/components/lib/tristatecheckbox/TriStateCheckbox.js b/components/lib/tristatecheckbox/TriStateCheckbox.js index b4abbdb6d4..c7dc31975b 100644 --- a/components/lib/tristatecheckbox/TriStateCheckbox.js +++ b/components/lib/tristatecheckbox/TriStateCheckbox.js @@ -14,25 +14,19 @@ export const TriStateCheckbox = React.memo( const context = React.useContext(PrimeReactContext); const props = TriStateCheckboxBase.getProps(inProps, context); - const [focusedState, setFocusedState] = React.useState(false); const elementRef = React.useRef(null); const { ptm, cx, isUnstyled } = TriStateCheckboxBase.setMetaData({ - props, - state: { - focused: focusedState - } + props }); useHandleStyle(TriStateCheckboxBase.css.styles, isUnstyled, { name: 'tristatecheckbox' }); - const onClick = (event) => { - if (!props.disabled && !props.readOnly) { - toggle(event); + const onChange = (event) => { + if (props.disabled || props.readOnly) { + return; } - }; - const toggle = (event) => { let newValue; if (props.value === null || props.value === undefined) newValue = true; @@ -58,17 +52,17 @@ export const TriStateCheckbox = React.memo( } }; - const onFocus = () => { - setFocusedState(true); + const onFocus = (event) => { + props?.onFocus?.(event); }; - const onBlur = () => { - setFocusedState(false); + const onBlur = (event) => { + props?.onBlur?.(event); }; const onKeyDown = (e) => { if (e.code === 'Enter' || e.code === 'Space') { - toggle(e); + onChange(e); e.preventDefault(); } }; @@ -114,9 +108,9 @@ export const TriStateCheckbox = React.memo( const ariaValueLabel = props.value ? ariaLabel('trueLabel') : props.value === false ? ariaLabel('falseLabel') : ariaLabel('nullLabel'); const ariaChecked = props.value ? 'true' : 'false'; - const checkboxProps = mergeProps( + const boxProps = mergeProps( { - className: cx('checkbox', { focusedState }), + className: cx('box'), tabIndex: props.disabled ? '-1' : props.tabIndex, onFocus: onFocus, onBlur: onBlur, @@ -125,7 +119,7 @@ export const TriStateCheckbox = React.memo( 'aria-checked': ariaChecked, ...ariaProps }, - ptm('checkbox') + ptm('box') ); const srOnlyAriaProps = mergeProps( @@ -140,18 +134,30 @@ export const TriStateCheckbox = React.memo( { className: classNames(props.className, cx('root')), style: props.style, - onClick: onClick, 'data-p-disabled': props.disabled }, TriStateCheckboxBase.getOtherProps(props), ptm('root') ); + const inputProps = mergeProps({ + id: props.inputId, + className: cx('input'), + type: 'checkbox', + 'aria-invalid': props.invalid, + disabled: props.disabled, + readonly: props.readOnly, + value: props.value, + checked: props.value, + onChange: onChange + }); + return ( <>
    -
    {checkIcon}
    - {focusedState && {ariaValueLabel}} + + {ariaValueLabel} +
    {checkIcon}
    {hasTooltip && } diff --git a/components/lib/tristatecheckbox/TriStateCheckboxBase.js b/components/lib/tristatecheckbox/TriStateCheckboxBase.js index e9c83cc0f7..8ea8aa2a8c 100644 --- a/components/lib/tristatecheckbox/TriStateCheckboxBase.js +++ b/components/lib/tristatecheckbox/TriStateCheckboxBase.js @@ -1,16 +1,17 @@ import { ComponentBase } from '../componentbase/ComponentBase'; -import { ObjectUtils, classNames } from '../utils/Utils'; +import { classNames } from '../utils/Utils'; const classes = { - root: ({ props }) => classNames('p-tristatecheckbox p-checkbox p-component', { 'p-checkbox-disabled': props.disabled }), - checkIcon: 'p-checkbox-icon p-c', - checkbox: ({ props, focusedState }) => - classNames('p-checkbox-box', { - 'p-highlight': ObjectUtils.isNotEmpty(props.value), + root: ({ props }) => + classNames('p-tristatecheckbox p-checkbox p-component', { + 'p-highlight': props.value !== null, 'p-disabled': props.disabled, 'p-invalid': props.invalid, - 'p-focus': focusedState - }) + 'p-variant-filled': props.variant === 'filled' + }), + checkIcon: 'p-checkbox-icon p-c', + box: 'p-checkbox-box', + input: 'p-checkbox-input' }; export const TriStateCheckboxBase = ComponentBase.extend({ diff --git a/components/lib/tristatecheckbox/tristatecheckbox.d.ts b/components/lib/tristatecheckbox/tristatecheckbox.d.ts index c5558af79e..8734451ecf 100644 --- a/components/lib/tristatecheckbox/tristatecheckbox.d.ts +++ b/components/lib/tristatecheckbox/tristatecheckbox.d.ts @@ -8,6 +8,7 @@ * */ import * as React from 'react'; +import { CheckboxPassThroughType } from '../checkbox/checkbox'; import { ComponentHooks } from '../componentbase/componentbase'; import { PassThroughOptions } from '../passthrough'; import { TooltipPassThroughOptions } from '../tooltip/tooltip'; @@ -22,7 +23,6 @@ export declare type TriStateCheckboxPassThroughType = PassThroughType>; /** - * Uses to pass attributes to the checkbox box's DOM element. + * Uses to pass attributes to the input's DOM element. */ - checkbox?: TriStateCheckboxPassThroughType>; + input?: CheckboxPassThroughType>; + /** + * Used to pass attributes to the box's DOM element. + */ + box?: CheckboxPassThroughType>; /** * Uses to pass attributes tooltip's DOM element. * @type {TooltipPassThroughOptions} @@ -62,16 +66,6 @@ export interface TriStateCheckboxPassThroughOptions { hooks?: ComponentHooks; } -/** - * Defines current inline state in TriStateCheckbox component. - */ -export interface TriStateCheckboxState { - /** - * Focused state as a boolean. - */ - focused: boolean; -} - /** * Custom change event. * @see {@link TriStateCheckboxProps.onChange} diff --git a/pages/dropdown/index.js b/pages/dropdown/index.js index 34cbab0b6a..5511956c08 100644 --- a/pages/dropdown/index.js +++ b/pages/dropdown/index.js @@ -2,6 +2,7 @@ import DocApiTable from '@/components/doc/common/docapitable'; import { DocComponent } from '@/components/doc/common/doccomponent'; import { AccessibilityDoc } from '@/components/doc/dropdown/accessibilitydoc'; import { BasicDoc } from '@/components/doc/dropdown/basicdoc'; +import { CheckmarkDoc } from '@/components/doc/dropdown/checkmarkdoc'; import { ClearIconDoc } from '@/components/doc/dropdown/clearicondoc'; import { DisabledDoc } from '@/components/doc/dropdown/disableddoc'; import { EditableDoc } from '@/components/doc/dropdown/editabledoc'; @@ -33,6 +34,11 @@ const DropdownDemo = () => { label: 'Basic', component: BasicDoc }, + { + id: 'checkmark', + label: 'Checkmark', + component: CheckmarkDoc + }, { id: 'editable', label: 'Editable', diff --git a/public/themes/md-dark-indigo/theme.css b/public/themes/md-dark-indigo/theme.css index b4d8375d48..3f69ee157c 100644 --- a/public/themes/md-dark-indigo/theme.css +++ b/public/themes/md-dark-indigo/theme.css @@ -1926,19 +1926,6 @@ .p-rating.p-readonly .p-rating-item { cursor: default; } - .p-rating { - position: relative; - display: flex; - align-items: center; - } - .p-rating-item { - display: inline-flex; - align-items: center; - cursor: pointer; - } - .p-rating.p-readonly .p-rating-item { - cursor: default; - } .p-rating { gap: 0.5rem; }