@khanacademy/wonder-blocks-accordion 3.1.72 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/components/accordion.d.ts +65 -40
- package/dist/es/index.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-accordion
|
|
2
2
|
|
|
3
|
+
## 3.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 1f8807a: Accordion: add controlled mode via the `expandedIndices` and `onToggle` props, and fix the `id` prop so it is set on the accordion itself instead of being duplicated onto every list item
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [8ac496e]
|
|
12
|
+
- @khanacademy/wonder-blocks-clickable@8.3.0
|
|
13
|
+
|
|
3
14
|
## 3.1.72
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
|
@@ -1,53 +1,40 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import type { StyleType } from "@khanacademy/wonder-blocks-core";
|
|
2
|
+
import type { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
|
|
3
3
|
import AccordionSection from "./accordion-section";
|
|
4
4
|
export type AccordionCornerKindType = "square" | "rounded" | "rounded-per-section";
|
|
5
|
-
|
|
6
|
-
* An accordion displays a vertically stacked list of sections, each of which
|
|
7
|
-
* contains content that can be shown or hidden by clicking its header.
|
|
8
|
-
*
|
|
9
|
-
* The Wonder Blocks Accordion component is a styled wrapper for a list of
|
|
10
|
-
* AccordionSection components. It also wraps the AccordionSection
|
|
11
|
-
* components in list items.
|
|
12
|
-
*
|
|
13
|
-
* ### Usage
|
|
14
|
-
*
|
|
15
|
-
* ```jsx
|
|
16
|
-
* import {
|
|
17
|
-
* Accordion,
|
|
18
|
-
* AccordionSection
|
|
19
|
-
* } from "@khanacademy/wonder-blocks-accordion";
|
|
20
|
-
*
|
|
21
|
-
* <Accordion>
|
|
22
|
-
* <AccordionSection header="First section">
|
|
23
|
-
* This is the information present in the first section
|
|
24
|
-
* </AccordionSection>
|
|
25
|
-
* <AccordionSection header="Second section">
|
|
26
|
-
* This is the information present in the second section
|
|
27
|
-
* </AccordionSection>
|
|
28
|
-
* <AccordionSection header="Third section">
|
|
29
|
-
* This is the information present in the third section
|
|
30
|
-
* </AccordionSection>
|
|
31
|
-
* </Accordion>
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
|
-
declare const Accordion: React.ForwardRefExoticComponent<Readonly<import("@khanacademy/wonder-blocks-core").AriaAttributes> & Readonly<{
|
|
35
|
-
role?: import("@khanacademy/wonder-blocks-core").AriaRole;
|
|
36
|
-
}> & {
|
|
5
|
+
type ControlledProps = {
|
|
37
6
|
/**
|
|
38
|
-
* The
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
*
|
|
7
|
+
* The indices of the AccordionSections that are currently expanded.
|
|
8
|
+
*
|
|
9
|
+
* Passing this prop puts the Accordion into controlled mode: the parent
|
|
10
|
+
* owns the expanded state, and the Accordion only reports changes via
|
|
11
|
+
* `onToggle`. Use `initialExpandedIndex` instead if you want the
|
|
12
|
+
* Accordion to manage the expanded state itself.
|
|
43
13
|
*/
|
|
44
|
-
|
|
14
|
+
expandedIndices: ReadonlyArray<number>;
|
|
15
|
+
initialExpandedIndex?: never;
|
|
16
|
+
};
|
|
17
|
+
type UncontrolledProps = {
|
|
45
18
|
/**
|
|
46
19
|
* The index of the AccordionSection that should be expanded when the
|
|
47
20
|
* Accordion is first rendered. If not specified, no AccordionSections
|
|
48
21
|
* will be expanded when the Accordion is first rendered.
|
|
22
|
+
*
|
|
23
|
+
* This is only read on the first render. Use `expandedIndices` if you
|
|
24
|
+
* need to control the expanded state after that.
|
|
49
25
|
*/
|
|
50
26
|
initialExpandedIndex?: number;
|
|
27
|
+
expandedIndices?: never;
|
|
28
|
+
};
|
|
29
|
+
type Props = AriaProps & {
|
|
30
|
+
/**
|
|
31
|
+
* The unique identifier for the accordion.
|
|
32
|
+
*/
|
|
33
|
+
id?: string;
|
|
34
|
+
/**
|
|
35
|
+
* The AccordionSection components to display within this Accordion.
|
|
36
|
+
*/
|
|
37
|
+
children: Array<React.ReactElement<React.ComponentProps<typeof AccordionSection>>>;
|
|
51
38
|
/**
|
|
52
39
|
* Whether multiple AccordionSections can be expanded at the same time.
|
|
53
40
|
* If not specified, multiple AccordionSections can be expanded at a time.
|
|
@@ -91,5 +78,43 @@ declare const Accordion: React.ForwardRefExoticComponent<Readonly<import("@khana
|
|
|
91
78
|
* Custom styles for the overall accordion container.
|
|
92
79
|
*/
|
|
93
80
|
style?: StyleType;
|
|
94
|
-
|
|
81
|
+
/**
|
|
82
|
+
* Called when a section is toggled. It is passed the index of the section
|
|
83
|
+
* that was toggled, along with the indices of every section that is
|
|
84
|
+
* expanded as a result of the toggle. In controlled mode, the second
|
|
85
|
+
* argument is the value that should be passed back in as
|
|
86
|
+
* `expandedIndices`.
|
|
87
|
+
*/
|
|
88
|
+
onToggle?: (toggledIndex: number, allExpandedIndices: Array<number>) => unknown;
|
|
89
|
+
} & (ControlledProps | UncontrolledProps);
|
|
90
|
+
/**
|
|
91
|
+
* An accordion displays a vertically stacked list of sections, each of which
|
|
92
|
+
* contains content that can be shown or hidden by clicking its header.
|
|
93
|
+
*
|
|
94
|
+
* The Wonder Blocks Accordion component is a styled wrapper for a list of
|
|
95
|
+
* AccordionSection components. It also wraps the AccordionSection
|
|
96
|
+
* components in list items.
|
|
97
|
+
*
|
|
98
|
+
* ### Usage
|
|
99
|
+
*
|
|
100
|
+
* ```jsx
|
|
101
|
+
* import {
|
|
102
|
+
* Accordion,
|
|
103
|
+
* AccordionSection
|
|
104
|
+
* } from "@khanacademy/wonder-blocks-accordion";
|
|
105
|
+
*
|
|
106
|
+
* <Accordion>
|
|
107
|
+
* <AccordionSection header="First section">
|
|
108
|
+
* This is the information present in the first section
|
|
109
|
+
* </AccordionSection>
|
|
110
|
+
* <AccordionSection header="Second section">
|
|
111
|
+
* This is the information present in the second section
|
|
112
|
+
* </AccordionSection>
|
|
113
|
+
* <AccordionSection header="Third section">
|
|
114
|
+
* This is the information present in the third section
|
|
115
|
+
* </AccordionSection>
|
|
116
|
+
* </Accordion>
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
declare const Accordion: React.ForwardRefExoticComponent<Props & React.RefAttributes<HTMLUListElement>>;
|
|
95
120
|
export default Accordion;
|
package/dist/es/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import caretDown from '@phosphor-icons/core/bold/caret-down-bold.svg';
|
|
|
9
9
|
import Clickable from '@khanacademy/wonder-blocks-clickable';
|
|
10
10
|
import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
|
|
11
11
|
|
|
12
|
-
const StyledUl=addStyle("ul");const LANDMARK_PROLIFERATION_THRESHOLD=6;const Accordion=React.forwardRef(function Accordion(props,ref){const{children,id,
|
|
12
|
+
const StyledUl=addStyle("ul");const LANDMARK_PROLIFERATION_THRESHOLD=6;const Accordion=React.forwardRef(function Accordion(props,ref){const{children,id,allowMultipleExpanded=true,caretPosition,cornerKind="rounded",animated,style,onToggle,expandedIndices,initialExpandedIndex,...ariaProps}=props;const isControlled=expandedIndices!==undefined;const[internalSectionsOpened,setInternalSectionsOpened]=React.useState(()=>{const startingArray=Array(children.length).fill(false);if(initialExpandedIndex!==undefined){startingArray[initialExpandedIndex]=true;}return startingArray});const controlledSectionsOpened=React.useMemo(()=>{if(expandedIndices===undefined){return null}const openedArray=Array(children.length).fill(false);for(const index of expandedIndices){openedArray[index]=true;}return openedArray},[children.length,expandedIndices]);const sectionsOpened=controlledSectionsOpened??internalSectionsOpened;const childRefs=Array(children.length).fill(null);const sectionsAreRegions=children.length<=LANDMARK_PROLIFERATION_THRESHOLD;const handleSectionClick=(index,childOnToggle)=>{const newSectionsOpened=allowMultipleExpanded?[...sectionsOpened]:Array(children.length).fill(false);const newOpenedValueAtIndex=!sectionsOpened[index];newSectionsOpened[index]=newOpenedValueAtIndex;if(!isControlled){setInternalSectionsOpened(newSectionsOpened);}childOnToggle?.(newOpenedValueAtIndex);onToggle?.(index,newSectionsOpened.flatMap((isOpened,sectionIndex)=>isOpened?[sectionIndex]:[]));};const handleKeyDown=event=>{const currentlyFocusedHeaderIndex=childRefs.findIndex(ref=>ref.current===document.activeElement);if(currentlyFocusedHeaderIndex===-1){return}switch(event.key){case"ArrowUp":event.preventDefault();const previousSectionIndex=(currentlyFocusedHeaderIndex+children.length-1)%children.length;const previousChildRef=childRefs[previousSectionIndex];previousChildRef.current?.focus();break;case"ArrowDown":event.preventDefault();const nextSectionIndex=(currentlyFocusedHeaderIndex+1)%children.length;const nextChildRef=childRefs[nextSectionIndex];nextChildRef.current?.focus();break;case"Home":event.preventDefault();const firstChildRef=childRefs[0];firstChildRef.current?.focus();break;case"End":event.preventDefault();const lastChildRef=childRefs[children.length-1];lastChildRef.current?.focus();break}};return jsx(StyledUl,{id:id,style:[styles$2.wrapper,style],onKeyDown:handleKeyDown,...ariaProps,ref:ref,children:children.map((child,index)=>{const{caretPosition:childCaretPosition,cornerKind:childCornerKind,onToggle:childOnToggle,animated:childAnimated}=child.props;const childRef=React.createRef();childRefs[index]=childRef;const isFirstChild=index===0;const isLastChild=index===children.length-1;return jsx("li",{id:id?`${id}-section-${index}`:undefined,children:React.cloneElement(child,{animated:childAnimated??animated,caretPosition:childCaretPosition??caretPosition,cornerKind:childCornerKind??cornerKind,expanded:sectionsOpened[index]??false,onToggle:()=>handleSectionClick(index,childOnToggle),isFirstSection:isFirstChild,isLastSection:isLastChild,isRegion:sectionsAreRegions,ref:childRef})},index)})})});const styles$2=StyleSheet.create({wrapper:{boxSizing:"border-box",listStyle:"none",padding:0,width:"100%"}});
|
|
13
13
|
|
|
14
14
|
function getRoundedValuesForHeader(cornerKind,isFirstSection,isLastSection,expanded){switch(cornerKind){case"rounded-per-section":return {roundedTop:true,roundedBottom:!expanded};case"rounded":return {roundedTop:isFirstSection,roundedBottom:isLastSection&&!expanded};default:return {roundedTop:false,roundedBottom:false}}}
|
|
15
15
|
|
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
|
36
36
|
var caretDown__default = /*#__PURE__*/_interopDefaultLegacy(caretDown);
|
|
37
37
|
var Clickable__default = /*#__PURE__*/_interopDefaultLegacy(Clickable);
|
|
38
38
|
|
|
39
|
-
const StyledUl=wonderBlocksCore.addStyle("ul");const LANDMARK_PROLIFERATION_THRESHOLD=6;const Accordion=React__namespace.forwardRef(function Accordion(props,ref){const{children,id,
|
|
39
|
+
const StyledUl=wonderBlocksCore.addStyle("ul");const LANDMARK_PROLIFERATION_THRESHOLD=6;const Accordion=React__namespace.forwardRef(function Accordion(props,ref){const{children,id,allowMultipleExpanded=true,caretPosition,cornerKind="rounded",animated,style,onToggle,expandedIndices,initialExpandedIndex,...ariaProps}=props;const isControlled=expandedIndices!==undefined;const[internalSectionsOpened,setInternalSectionsOpened]=React__namespace.useState(()=>{const startingArray=Array(children.length).fill(false);if(initialExpandedIndex!==undefined){startingArray[initialExpandedIndex]=true;}return startingArray});const controlledSectionsOpened=React__namespace.useMemo(()=>{if(expandedIndices===undefined){return null}const openedArray=Array(children.length).fill(false);for(const index of expandedIndices){openedArray[index]=true;}return openedArray},[children.length,expandedIndices]);const sectionsOpened=controlledSectionsOpened??internalSectionsOpened;const childRefs=Array(children.length).fill(null);const sectionsAreRegions=children.length<=LANDMARK_PROLIFERATION_THRESHOLD;const handleSectionClick=(index,childOnToggle)=>{const newSectionsOpened=allowMultipleExpanded?[...sectionsOpened]:Array(children.length).fill(false);const newOpenedValueAtIndex=!sectionsOpened[index];newSectionsOpened[index]=newOpenedValueAtIndex;if(!isControlled){setInternalSectionsOpened(newSectionsOpened);}childOnToggle?.(newOpenedValueAtIndex);onToggle?.(index,newSectionsOpened.flatMap((isOpened,sectionIndex)=>isOpened?[sectionIndex]:[]));};const handleKeyDown=event=>{const currentlyFocusedHeaderIndex=childRefs.findIndex(ref=>ref.current===document.activeElement);if(currentlyFocusedHeaderIndex===-1){return}switch(event.key){case"ArrowUp":event.preventDefault();const previousSectionIndex=(currentlyFocusedHeaderIndex+children.length-1)%children.length;const previousChildRef=childRefs[previousSectionIndex];previousChildRef.current?.focus();break;case"ArrowDown":event.preventDefault();const nextSectionIndex=(currentlyFocusedHeaderIndex+1)%children.length;const nextChildRef=childRefs[nextSectionIndex];nextChildRef.current?.focus();break;case"Home":event.preventDefault();const firstChildRef=childRefs[0];firstChildRef.current?.focus();break;case"End":event.preventDefault();const lastChildRef=childRefs[children.length-1];lastChildRef.current?.focus();break}};return jsxRuntime.jsx(StyledUl,{id:id,style:[styles$2.wrapper,style],onKeyDown:handleKeyDown,...ariaProps,ref:ref,children:children.map((child,index)=>{const{caretPosition:childCaretPosition,cornerKind:childCornerKind,onToggle:childOnToggle,animated:childAnimated}=child.props;const childRef=React__namespace.createRef();childRefs[index]=childRef;const isFirstChild=index===0;const isLastChild=index===children.length-1;return jsxRuntime.jsx("li",{id:id?`${id}-section-${index}`:undefined,children:React__namespace.cloneElement(child,{animated:childAnimated??animated,caretPosition:childCaretPosition??caretPosition,cornerKind:childCornerKind??cornerKind,expanded:sectionsOpened[index]??false,onToggle:()=>handleSectionClick(index,childOnToggle),isFirstSection:isFirstChild,isLastSection:isLastChild,isRegion:sectionsAreRegions,ref:childRef})},index)})})});const styles$2=aphrodite.StyleSheet.create({wrapper:{boxSizing:"border-box",listStyle:"none",padding:0,width:"100%"}});
|
|
40
40
|
|
|
41
41
|
function getRoundedValuesForHeader(cornerKind,isFirstSection,isLastSection,expanded){switch(cornerKind){case"rounded-per-section":return {roundedTop:true,roundedBottom:!expanded};case"rounded":return {roundedTop:isFirstSection,roundedBottom:isLastSection&&!expanded};default:return {roundedTop:false,roundedBottom:false}}}
|
|
42
42
|
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Accordion components for Wonder Blocks.",
|
|
4
4
|
"author": "Khan Academy",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "3.
|
|
6
|
+
"version": "3.2.0",
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"types": "dist/index.d.ts",
|
|
22
22
|
"source": "src/index.js",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@khanacademy/wonder-blocks-clickable": "8.
|
|
24
|
+
"@khanacademy/wonder-blocks-clickable": "8.3.0",
|
|
25
25
|
"@khanacademy/wonder-blocks-core": "12.5.0",
|
|
26
26
|
"@khanacademy/wonder-blocks-icon": "6.0.2",
|
|
27
27
|
"@khanacademy/wonder-blocks-tokens": "18.0.0",
|