@cfpb/cfpb-expandables
Advanced tools
Comparing version 0.22.1 to 0.23.0
{ | ||
"name": "@cfpb/cfpb-expandables", | ||
"version": "0.22.1", | ||
"version": "0.23.0", | ||
"description": "Design System expandables", | ||
@@ -12,5 +12,5 @@ "main": "src/index.js", | ||
"dependencies": { | ||
"@cfpb/cfpb-atomic-component": "^0.22.1", | ||
"@cfpb/cfpb-core": "^0.22.0", | ||
"@cfpb/cfpb-icons": "^0.22.1" | ||
"@cfpb/cfpb-atomic-component": "^0.23.0", | ||
"@cfpb/cfpb-core": "^0.23.0", | ||
"@cfpb/cfpb-icons": "^0.23.0" | ||
}, | ||
@@ -20,4 +20,4 @@ "keywords": [ | ||
], | ||
"gitHead": "b28492d3c103be46103fc89f2666c08f8a251f21", | ||
"gitHead": "e984ffb0041a7cf9da1c1e71efa6c59e7694105a", | ||
"type": "module" | ||
} |
@@ -5,142 +5,114 @@ /* ========================================================================== | ||
import { AtomicComponent } from '@cfpb/cfpb-atomic-component/src/components/AtomicComponent.js'; | ||
import { EventObserver } from '@cfpb/cfpb-atomic-component'; | ||
import ExpandableTransition from './ExpandableTransition.js'; | ||
import { | ||
add as addDataHook, | ||
checkDom, | ||
setInitFlag, | ||
instantiateAll, | ||
MaxHeightTransition, | ||
EventObserver, | ||
FlyoutMenu, | ||
} from '@cfpb/cfpb-atomic-component'; | ||
const eventObserver = new EventObserver(); | ||
const BASE_CLASS = 'o-expandable'; | ||
/** | ||
* Event handler for when an expandable begins expanding. | ||
* Expandable | ||
* | ||
* @class | ||
* @classdesc Initializes a new Expandable molecule. | ||
* @param {HTMLElement} element - The DOM element within which to search | ||
* for the molecule. | ||
* @returns {Expandable} An instance. | ||
*/ | ||
function expandBeginHandler() { | ||
this.ui.content.classList.remove('u-hidden'); | ||
} | ||
function Expandable(element) { | ||
// Internal vars. | ||
const _dom = checkDom(element, BASE_CLASS); | ||
let _targetDom; | ||
let _contentDom; | ||
let _labelDom; | ||
/** | ||
* Event handler for when an expandable is finished collapsing. | ||
*/ | ||
function collapseEndHandler() { | ||
this.ui.content.classList.add('u-hidden'); | ||
} | ||
// Animation vars. | ||
let _transition; | ||
let _flyout; | ||
/** | ||
* Event handler for when an accordion is activated | ||
*/ | ||
function _accordionActivatedHandler() { | ||
if (this.activeAccordion) { | ||
this.transition.toggleExpandable(); | ||
this.toggleTargetState(this.ui.target); | ||
this.activeAccordion = false; | ||
} | ||
} | ||
/** | ||
* Set up and create the multiselect. | ||
* | ||
* @returns {Expandable} An instance. | ||
*/ | ||
function init() { | ||
if (!setInitFlag(_dom)) { | ||
return this; | ||
} | ||
/** | ||
* Initialize a new expandable. | ||
*/ | ||
function initialize() { | ||
const transition = new ExpandableTransition(this.ui.content); | ||
this.transition = transition.init(); | ||
this.transition.addEventListener( | ||
'expandbegin', | ||
expandBeginHandler.bind(this) | ||
); | ||
this.transition.addEventListener( | ||
'collapseend', | ||
collapseEndHandler.bind(this) | ||
); | ||
_targetDom = _dom.querySelector(`.${BASE_CLASS}_target`); | ||
_contentDom = _dom.querySelector(`.${BASE_CLASS}_content`); | ||
_labelDom = _dom.querySelector(`.${BASE_CLASS}_label`); | ||
if ( | ||
this.ui.content.classList.contains(ExpandableTransition.CLASSES.EXPANDED) | ||
) { | ||
this.ui.target.classList.add(this.classes.targetExpanded); | ||
} else { | ||
this.ui.target.classList.add(this.classes.targetCollapsed); | ||
this.ui.content.classList.add('u-hidden'); | ||
} | ||
const isExpanded = _contentDom.classList.contains( | ||
`${BASE_CLASS}_content__onload-open` | ||
); | ||
const expandableGroup = this.ui.target.closest('.' + this.classes.group); | ||
// Add behavior hooks. | ||
addDataHook(_dom, 'behavior_flyout-menu'); | ||
addDataHook(_targetDom, 'behavior_flyout-menu_trigger'); | ||
addDataHook(_contentDom, 'behavior_flyout-menu_content'); | ||
this.isAccordionGroup = | ||
expandableGroup !== null && | ||
expandableGroup.classList.contains(this.classes.groupAccordion); | ||
// If it's expanded we don't set an initial height, | ||
// as it will be calculated internally. | ||
const initialClass = isExpanded | ||
? MaxHeightTransition.CLASSES.MH_DEFAULT | ||
: MaxHeightTransition.CLASSES.MH_ZERO; | ||
_transition = new MaxHeightTransition(_contentDom).init(initialClass); | ||
if (this.isAccordionGroup) { | ||
eventObserver.addEventListener( | ||
'accordionActivated', | ||
_accordionActivatedHandler.bind(this) | ||
// Create root menu. | ||
_flyout = new FlyoutMenu(_dom); | ||
_flyout.setTransition( | ||
_transition, | ||
_transition.maxHeightZero, | ||
_transition.maxHeightDefault | ||
); | ||
} | ||
} | ||
/** | ||
* Event handler for when an expandable is clicked. | ||
*/ | ||
function expandableClickHandler() { | ||
this.transition.toggleExpandable(); | ||
this.toggleTargetState(this.ui.target); | ||
_flyout.init(isExpanded); | ||
if (this.isAccordionGroup) { | ||
if (this.activeAccordion) { | ||
this.activeAccordion = false; | ||
} else { | ||
eventObserver.dispatchEvent('accordionActivated', { target: this }); | ||
this.activeAccordion = true; | ||
} | ||
// Add events. | ||
_flyout.addEventListener('expandbegin', () => { | ||
_contentDom.classList.remove('u-hidden'); | ||
this.dispatchEvent('expandbegin', { target: this }); | ||
}); | ||
_flyout.addEventListener('collapseend', () => { | ||
_contentDom.classList.add('u-hidden'); | ||
}); | ||
return this; | ||
} | ||
} | ||
/** | ||
* Toggle an expandable to open or closed. | ||
* | ||
* @param {HTMLElement} element - The expandable target HTML DOM element. | ||
*/ | ||
function toggleTargetState(element) { | ||
if (element.classList.contains(this.classes.targetExpanded)) { | ||
this.ui.target.classList.add(this.classes.targetCollapsed); | ||
this.ui.target.classList.remove(this.classes.targetExpanded); | ||
} else { | ||
this.ui.target.classList.add(this.classes.targetExpanded); | ||
this.ui.target.classList.remove(this.classes.targetCollapsed); | ||
/** | ||
* @returns {string} The expandable label text. | ||
*/ | ||
function getLabelText() { | ||
return _labelDom.textContent.trim(); | ||
} | ||
} | ||
/** | ||
* Retrieve the label text of the expandable header. | ||
* | ||
* @returns {string} The text of the expandable's label. | ||
*/ | ||
function getLabelText() { | ||
return this.ui.label.textContent.trim(); | ||
} | ||
// Attach public events. | ||
this.init = init; | ||
this.expand = () => _flyout.expand(); | ||
this.collapse = () => _flyout.collapse(); | ||
this.isExpanded = () => _flyout.isExpanded(); | ||
this.refresh = () => _flyout.getTransition().refresh(); | ||
this.getLabelText = getLabelText; | ||
const Expandable = AtomicComponent.extend({ | ||
ui: { | ||
base: '.o-expandable', | ||
target: '.o-expandable_target', | ||
content: '.o-expandable_content', | ||
header: '.o-expandable_header', | ||
label: '.o-expandable_label', | ||
}, | ||
const eventObserver = new EventObserver(); | ||
this.addEventListener = eventObserver.addEventListener; | ||
this.removeEventListener = eventObserver.removeEventListener; | ||
this.dispatchEvent = eventObserver.dispatchEvent; | ||
classes: { | ||
targetExpanded: 'o-expandable_target__expanded', | ||
targetCollapsed: 'o-expandable_target__collapsed', | ||
group: 'o-expandable-group', | ||
groupAccordion: 'o-expandable-group__accordion', | ||
}, | ||
return this; | ||
} | ||
events: { | ||
'click .o-expandable_target': 'expandableClickHandler', | ||
}, | ||
Expandable.BASE_CLASS = BASE_CLASS; | ||
Expandable.init = (scope) => | ||
instantiateAll(`.${Expandable.BASE_CLASS}`, Expandable, scope); | ||
transition: null, | ||
isAccordionGroup: false, | ||
activeAccordion: false, | ||
initialize: initialize, | ||
expandableClickHandler: expandableClickHandler, | ||
toggleTargetState: toggleTargetState, | ||
getLabelText: getLabelText, | ||
}); | ||
export { Expandable }; |
@@ -7,2 +7,3 @@ /* ========================================================================== | ||
export { Expandable } from './Expandable.js'; | ||
export { ExpandableGroup } from './ExpandableGroup.js'; | ||
export { Summary } from './Summary.js'; |
@@ -229,4 +229,4 @@ /* eslint-disable no-use-before-define */ | ||
Summary.BASE_CLASS = BASE_CLASS; | ||
Summary.init = () => instantiateAll(`.${BASE_CLASS}`, Summary); | ||
Summary.init = (scope) => instantiateAll(`.${BASE_CLASS}`, Summary, scope); | ||
export { Summary }; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
62172
14
498
+ Added@cfpb/cfpb-atomic-component@0.23.0(transitive)
+ Added@cfpb/cfpb-core@0.23.0(transitive)
+ Added@cfpb/cfpb-icons@0.23.0(transitive)
- Removed@cfpb/cfpb-atomic-component@0.22.1(transitive)
- Removed@cfpb/cfpb-core@0.22.0(transitive)
- Removed@cfpb/cfpb-icons@0.22.1(transitive)
- Removedftdomdelegate@3.1.0(transitive)
Updated@cfpb/cfpb-core@^0.23.0
Updated@cfpb/cfpb-icons@^0.23.0