Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@nrk/core-toggle

Package Overview
Dependencies
Maintainers
113
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@nrk/core-toggle - npm Package Compare versions

Comparing version 1.2.2 to 2.0.0

81

core-toggle.cjs.js
'use strict';
var name = "@nrk/core-toggle";
var version = "1.2.1";
var version = "1.2.2";

@@ -90,25 +90,28 @@ var IS_BROWSER = typeof window !== 'undefined';

var OPEN = 'aria-expanded';
var POPS = 'data-haspopup'; // aria-haspopup triggers forms mode in JAWS, therefore data-
var POPUP = 'data-haspopup'; // aria-haspopup triggers forms mode in JAWS, therefore data-
var KEYS = { ESC: 27 };
function toggle (buttons, open) {
function toggle (toggles, open) {
var options = typeof open === 'object' ? open : { open: open };
if (IS_IOS) { document.documentElement.style.cursor = 'pointer'; } // Fix iOS events for closing {popup: true} https://stackoverflow.com/questions/14795944/jquery-click-events-not-working-in-ios#16006333
if (IS_IOS) { document.documentElement.style.cursor = 'pointer'; } // Fix iOS events for closing popups (https://stackoverflow.com/a/16006333/8819615)
return queryAll(buttons).map(function (button) {
var open = typeof options.open === 'boolean' ? options.open : button.getAttribute(OPEN) === 'true';
var pops = typeof options.popup === 'boolean' ? options.popup : button.getAttribute(POPS) === 'true';
var content = getContentElement(button);
return queryAll(toggles).map(function (toggle) {
var isOpen = toggle.getAttribute(OPEN) === 'true';
var open = typeof options.open === 'boolean' ? options.open : (options.open === 'toggle' ? !isOpen : isOpen);
var popup = typeof options.popup === 'string' ? options.popup : toggle.getAttribute(POPUP);
var content = getContentElement(toggle);
button.setAttribute(UUID, '');
button.setAttribute(POPS, pops);
button.setAttribute('aria-controls', content.id = content.id || getUUID());
content.setAttribute((ARIA + "-labelledby"), button.id = button.id || getUUID());
setOpen(button, open);
return button
toggle.setAttribute(UUID, '');
toggle[popup ? 'setAttribute' : 'removeAttribute'](POPUP, popup);
toggle.setAttribute('aria-controls', content.id = content.id || getUUID());
content.setAttribute((ARIA + "-labelledby"), toggle.id = toggle.id || getUUID());
setOpen(toggle, open);
if (options.value) { toggle.innerHTML = options.value; }
if (popup) { toggle.setAttribute('aria-label', ((toggle.textContent) + ", " + popup)); }
return toggle
})
}
function getContentElement (button) {
return document.getElementById(button.getAttribute('aria-controls')) || button.nextElementSibling
function getContentElement (toggle) {
return document.getElementById(toggle.getAttribute('aria-controls')) || toggle.nextElementSibling
}

@@ -119,8 +122,8 @@

for (var el = event.target; el; el = el.parentElement) {
var button = (el.id && document.querySelector(("[aria-controls=\"" + (el.id) + "\"]"))) || el;
var toggle = (el.id && document.querySelector(("[aria-controls=\"" + (el.id) + "\"]"))) || el;
if (button.hasAttribute(UUID) && button.getAttribute(POPS) === 'true' && button.getAttribute(OPEN) === 'true') {
if (toggle.hasAttribute(UUID) && toggle.hasAttribute(POPUP) && toggle.getAttribute(OPEN) === 'true') {
event.preventDefault(); // Prevent leaving maximized window in Safari
button.focus();
return setOpen(button, false)
toggle.focus();
return setOpen(toggle, false)
}

@@ -135,18 +138,32 @@ }

if (defaultPrevented) { return false } // Do not toggle if someone run event.preventDefault()
queryAll(("[" + UUID + "]")).forEach(function (el) {
var open = el.getAttribute(OPEN) === 'true';
var pops = el.getAttribute(POPS) === 'true';
var content = getContentElement(el);
if (el.contains(target)) { setOpen(el, !open); } // Click on toggle
else if (pops && open) { setOpen(el, content.contains(target)); } // Click in content or outside
for (var el = target, item = (void 0); el; el = el.parentElement) {
var toggle = item && el.id && document.querySelector(("[" + UUID + "][aria-controls=\"" + (el.id) + "\"]"));
if ((el.nodeName === 'BUTTON' || el.nodeName === 'A') && !el.hasAttribute(UUID)) { item = el; } // interactive element clicked
if (toggle) {
dispatchEvent(toggle, 'toggle.select', {
relatedTarget: getContentElement(toggle),
currentTarget: item,
value: item.textContent.trim()
});
break
}
}
queryAll(("[" + UUID + "]")).forEach(function (toggle) {
var open = toggle.getAttribute(OPEN) === 'true';
var popup = toggle.hasAttribute(POPUP);
var content = getContentElement(toggle);
if (toggle.contains(target)) { setOpen(toggle, !open); } // Click on toggle
else if (popup && open) { setOpen(toggle, content.contains(target)); } // Click in content or outside
});
});
function setOpen (button, open) {
var content = getContentElement(button);
var isOpen = button.getAttribute(OPEN) === 'true';
function setOpen (toggle, open) {
var content = getContentElement(toggle);
var isOpen = toggle.getAttribute(OPEN) === 'true';
var willOpen = typeof open === 'boolean' ? open : (open === 'toggle' ? !isOpen : isOpen);
var isUpdate = isOpen === willOpen || dispatchEvent(button, 'toggle', { relatedTarget: content, isOpen: isOpen, willOpen: willOpen });
var nextOpen = isUpdate ? willOpen : button.getAttribute(OPEN) === 'true'; // dispatchEvent can change attributes
var isUpdate = isOpen === willOpen || dispatchEvent(toggle, 'toggle', { relatedTarget: content, isOpen: isOpen, willOpen: willOpen });
var nextOpen = isUpdate ? willOpen : toggle.getAttribute(OPEN) === 'true'; // dispatchEvent can change attributes
var focus = !isOpen && nextOpen && content.querySelector('[autofocus]');

@@ -156,3 +173,3 @@

button.setAttribute(OPEN, nextOpen);
toggle.setAttribute(OPEN, nextOpen);
content[nextOpen ? 'removeAttribute' : 'setAttribute']('hidden', '');

@@ -159,0 +176,0 @@ }

@@ -7,25 +7,28 @@ import { name, version } from './package.json'

const OPEN = 'aria-expanded'
const POPS = 'data-haspopup' // aria-haspopup triggers forms mode in JAWS, therefore data-
const POPUP = 'data-haspopup' // aria-haspopup triggers forms mode in JAWS, therefore data-
const KEYS = { ESC: 27 }
export default function toggle (buttons, open) {
export default function toggle (toggles, open) {
const options = typeof open === 'object' ? open : { open }
if (IS_IOS) document.documentElement.style.cursor = 'pointer' // Fix iOS events for closing {popup: true} https://stackoverflow.com/questions/14795944/jquery-click-events-not-working-in-ios#16006333
if (IS_IOS) document.documentElement.style.cursor = 'pointer' // Fix iOS events for closing popups (https://stackoverflow.com/a/16006333/8819615)
return queryAll(buttons).map((button) => {
const open = typeof options.open === 'boolean' ? options.open : button.getAttribute(OPEN) === 'true'
const pops = typeof options.popup === 'boolean' ? options.popup : button.getAttribute(POPS) === 'true'
const content = getContentElement(button)
return queryAll(toggles).map((toggle) => {
const isOpen = toggle.getAttribute(OPEN) === 'true'
const open = typeof options.open === 'boolean' ? options.open : (options.open === 'toggle' ? !isOpen : isOpen)
const popup = typeof options.popup === 'string' ? options.popup : toggle.getAttribute(POPUP)
const content = getContentElement(toggle)
button.setAttribute(UUID, '')
button.setAttribute(POPS, pops)
button.setAttribute('aria-controls', content.id = content.id || getUUID())
content.setAttribute(`${ARIA}-labelledby`, button.id = button.id || getUUID())
setOpen(button, open)
return button
toggle.setAttribute(UUID, '')
toggle[popup ? 'setAttribute' : 'removeAttribute'](POPUP, popup)
toggle.setAttribute('aria-controls', content.id = content.id || getUUID())
content.setAttribute(`${ARIA}-labelledby`, toggle.id = toggle.id || getUUID())
setOpen(toggle, open)
if (options.value) toggle.innerHTML = options.value
if (popup) toggle.setAttribute('aria-label', `${toggle.textContent}, ${popup}`)
return toggle
})
}
function getContentElement (button) {
return document.getElementById(button.getAttribute('aria-controls')) || button.nextElementSibling
function getContentElement (toggle) {
return document.getElementById(toggle.getAttribute('aria-controls')) || toggle.nextElementSibling
}

@@ -36,8 +39,8 @@

for (let el = event.target; el; el = el.parentElement) {
const button = (el.id && document.querySelector(`[aria-controls="${el.id}"]`)) || el
const toggle = (el.id && document.querySelector(`[aria-controls="${el.id}"]`)) || el
if (button.hasAttribute(UUID) && button.getAttribute(POPS) === 'true' && button.getAttribute(OPEN) === 'true') {
if (toggle.hasAttribute(UUID) && toggle.hasAttribute(POPUP) && toggle.getAttribute(OPEN) === 'true') {
event.preventDefault() // Prevent leaving maximized window in Safari
button.focus()
return setOpen(button, false)
toggle.focus()
return setOpen(toggle, false)
}

@@ -49,18 +52,32 @@ }

if (defaultPrevented) return false // Do not toggle if someone run event.preventDefault()
queryAll(`[${UUID}]`).forEach((el) => {
const open = el.getAttribute(OPEN) === 'true'
const pops = el.getAttribute(POPS) === 'true'
const content = getContentElement(el)
if (el.contains(target)) setOpen(el, !open) // Click on toggle
else if (pops && open) setOpen(el, content.contains(target)) // Click in content or outside
for (let el = target, item; el; el = el.parentElement) {
const toggle = item && el.id && document.querySelector(`[${UUID}][aria-controls="${el.id}"]`)
if ((el.nodeName === 'BUTTON' || el.nodeName === 'A') && !el.hasAttribute(UUID)) item = el // interactive element clicked
if (toggle) {
dispatchEvent(toggle, 'toggle.select', {
relatedTarget: getContentElement(toggle),
currentTarget: item,
value: item.textContent.trim()
})
break
}
}
queryAll(`[${UUID}]`).forEach((toggle) => {
const open = toggle.getAttribute(OPEN) === 'true'
const popup = toggle.hasAttribute(POPUP)
const content = getContentElement(toggle)
if (toggle.contains(target)) setOpen(toggle, !open) // Click on toggle
else if (popup && open) setOpen(toggle, content.contains(target)) // Click in content or outside
})
})
function setOpen (button, open) {
const content = getContentElement(button)
const isOpen = button.getAttribute(OPEN) === 'true'
function setOpen (toggle, open) {
const content = getContentElement(toggle)
const isOpen = toggle.getAttribute(OPEN) === 'true'
const willOpen = typeof open === 'boolean' ? open : (open === 'toggle' ? !isOpen : isOpen)
const isUpdate = isOpen === willOpen || dispatchEvent(button, 'toggle', { relatedTarget: content, isOpen, willOpen })
const nextOpen = isUpdate ? willOpen : button.getAttribute(OPEN) === 'true' // dispatchEvent can change attributes
const isUpdate = isOpen === willOpen || dispatchEvent(toggle, 'toggle', { relatedTarget: content, isOpen, willOpen })
const nextOpen = isUpdate ? willOpen : toggle.getAttribute(OPEN) === 'true' // dispatchEvent can change attributes
const focus = !isOpen && nextOpen && content.querySelector('[autofocus]')

@@ -70,4 +87,4 @@

button.setAttribute(OPEN, nextOpen)
toggle.setAttribute(OPEN, nextOpen)
content[nextOpen ? 'removeAttribute' : 'setAttribute']('hidden', '')
}

@@ -25,3 +25,3 @@ import React from 'react'

'aria-expanded': String(Boolean(this.props.open)),
'data-haspopup': String(Boolean(this.props.popup))
'data-haspopup': this.props.popup
})

@@ -38,4 +38,4 @@ }

open: PropTypes.bool,
popup: PropTypes.bool,
popup: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
onToggle: PropTypes.func
}

@@ -1,3 +0,3 @@

/*! @nrk/core-toggle v1.2.1 - Copyright (c) 2017-2018 NRK */
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("react"),require("prop-types")):"function"==typeof define&&define.amd?define(["react","prop-types"],e):t.CoreToggle=e(t.React,t.PropTypes)}(this,function(u,t){"use strict";u=u&&u.hasOwnProperty("default")?u.default:u,t=t&&t.hasOwnProperty("default")?t.default:t;var e="undefined"!=typeof window,n=e&&/(android)/i.test(navigator.userAgent),o=e&&/iPad|iPhone|iPod/.test(String(navigator.platform)),r=function(t){void 0===t&&(t=!1);try{window.addEventListener("test",null,{get passive(){t=!0}})}catch(t){}return t}();function i(t,e,n,o){(void 0===o&&(o=!1),"undefined"==typeof window||window[t=t+"-"+e])||(r||"object"!=typeof o||(o=Boolean(o.capture)),("resize"===e||"load"===e?window:document).addEventListener(window[t]=e,n,o))}var p="prevent_recursive_dispatch_maximum_callstack";function a(t){return Date.now().toString(36)+Math.random().toString(36).slice(2,5)}function l(t,e){if(void 0===e&&(e=document),t){if(t.nodeType)return[t];if("string"==typeof t)return[].slice.call(e.querySelectorAll(t));if(t.length)return[].slice.call(t)}return[]}var c="data-@nrk/core-toggle-1.2.1".replace(/\W+/g,"-"),d=n?"data":"aria",s="aria-expanded",f="data-haspopup",g=27;function v(t,e){var r="object"==typeof e?e:{open:e};return o&&(document.documentElement.style.cursor="pointer"),l(t).map(function(t){var e="boolean"==typeof r.open?r.open:"true"===t.getAttribute(s),n="boolean"==typeof r.popup?r.popup:"true"===t.getAttribute(f),o=m(t);return t.setAttribute(c,""),t.setAttribute(f,n),t.setAttribute("aria-controls",o.id=o.id||a()),o.setAttribute(d+"-labelledby",t.id=t.id||a()),b(t,e),t})}function m(t){return document.getElementById(t.getAttribute("aria-controls"))||t.nextElementSibling}function b(t,e){var n=m(t),o="true"===t.getAttribute(s),r="boolean"==typeof e?e:"toggle"===e?!o:o,i=o===r||function(t,e,n){void 0===n&&(n={});var o,r=""+p+e;if(t[r])return!0;t[r]=!0,"function"==typeof window.CustomEvent?o=new window.CustomEvent(e,{bubbles:!0,cancelable:!0,detail:n}):(o=document.createEvent("CustomEvent")).initCustomEvent(e,!0,!0,n);var i=t.dispatchEvent(o);return t[r]=null,i}(t,"toggle",{relatedTarget:n,isOpen:o,willOpen:r})?r:"true"===t.getAttribute(s),u=!o&&i&&n.querySelector("[autofocus]");u&&setTimeout(function(){return u&&u.focus()}),t.setAttribute(s,i),n[i?"removeAttribute":"setAttribute"]("hidden","")}i(c,"keydown",function(t){if(t.keyCode===g)for(var e=t.target;e;e=e.parentElement){var n=e.id&&document.querySelector('[aria-controls="'+e.id+'"]')||e;if(n.hasAttribute(c)&&"true"===n.getAttribute(f)&&"true"===n.getAttribute(s))return t.preventDefault(),n.focus(),b(n,!1)}},!0),i(c,"click",function(t){var r=t.target;if(t.defaultPrevented)return!1;l("["+c+"]").forEach(function(t){var e="true"===t.getAttribute(s),n="true"===t.getAttribute(f),o=m(t);t.contains(r)?b(t,!e):n&&e&&b(t,o.contains(r))})});var y=function(e){function i(t){e.call(this,t),this.onToggle=this.onToggle.bind(this)}e&&(i.__proto__=e),(i.prototype=Object.create(e&&e.prototype)).constructor=i;var t={defaultProps:{configurable:!0}};return t.defaultProps.get=function(){return{open:null,popup:null,onToggle:null}},i.prototype.componentDidMount=function(){v(this.el.firstElementChild),this.el.addEventListener("toggle",this.onToggle)},i.prototype.componentDidUpdate=function(){v(this.el.firstElementChild)},i.prototype.componentWillUnmount=function(){this.el.removeEventListener("toggle",this.onToggle)},i.prototype.onToggle=function(t){this.props.onToggle&&this.props.onToggle(t)},i.prototype.render=function(){var n,o,t,r=this;return u.createElement("div",(n=this.props,o=i.defaultProps,void 0===(t={ref:function(t){return r.el=t}})&&(t={}),Object.keys(n).reduce(function(t,e){return o.hasOwnProperty(e)||(t[e]=n[e]),t},t)),u.Children.map(this.props.children,function(t,e){return 0===e?u.cloneElement(t,{"aria-expanded":String(Boolean(r.props.open)),"data-haspopup":String(Boolean(r.props.popup))}):1===e?u.cloneElement(t,{hidden:!r.props.open}):t}))},Object.defineProperties(i,t),i}(u.Component);return y.propTypes={open:t.bool,popup:t.bool,onToggle:t.func},y});
/*! @nrk/core-toggle v1.2.2 - Copyright (c) 2017-2018 NRK */
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("react"),require("prop-types")):"function"==typeof define&&define.amd?define(["react","prop-types"],t):e.CoreToggle=t(e.React,e.PropTypes)}("undefined"!=typeof self?self:this,function(u,e){"use strict";u=u&&u.hasOwnProperty("default")?u.default:u,e=e&&e.hasOwnProperty("default")?e.default:e;var t="undefined"!=typeof window,n=t&&/(android)/i.test(navigator.userAgent),o=t&&/iPad|iPhone|iPod/.test(String(navigator.platform)),r=function(e){void 0===e&&(e=!1);try{window.addEventListener("test",null,{get passive(){e=!0}})}catch(e){}return e}();function i(e,t,n,o){(void 0===o&&(o=!1),"undefined"==typeof window||window[e=e+"-"+t])||(r||"object"!=typeof o||(o=Boolean(o.capture)),("resize"===t||"load"===t?window:document).addEventListener(window[e]=t,n,o))}var a="prevent_recursive_dispatch_maximum_callstack";function l(e,t,n){void 0===n&&(n={});var o,r=""+a+t;if(e[r])return!0;e[r]=!0,"function"==typeof window.CustomEvent?o=new window.CustomEvent(t,{bubbles:!0,cancelable:!0,detail:n}):(o=document.createEvent("CustomEvent")).initCustomEvent(t,!0,!0,n);var i=e.dispatchEvent(o);return e[r]=null,i}function p(e){return Date.now().toString(36)+Math.random().toString(36).slice(2,5)}function d(e,t){if(void 0===t&&(t=document),e){if(e.nodeType)return[e];if("string"==typeof e)return[].slice.call(t.querySelectorAll(e));if(e.length)return[].slice.call(e)}return[]}var c="data-@nrk/core-toggle-1.2.2".replace(/\W+/g,"-"),s=n?"data":"aria",f="aria-expanded",g="data-haspopup",v=27;function m(e,t){var i="object"==typeof t?t:{open:t};return o&&(document.documentElement.style.cursor="pointer"),d(e).map(function(e){var t="true"===e.getAttribute(f),n="boolean"==typeof i.open?i.open:"toggle"===i.open?!t:t,o="string"==typeof i.popup?i.popup:e.getAttribute(g),r=b(e);return e.setAttribute(c,""),e[o?"setAttribute":"removeAttribute"](g,o),e.setAttribute("aria-controls",r.id=r.id||p()),r.setAttribute(s+"-labelledby",e.id=e.id||p()),y(e,n),i.value&&(e.innerHTML=i.value),o&&e.setAttribute("aria-label",e.textContent+", "+o),e})}function b(e){return document.getElementById(e.getAttribute("aria-controls"))||e.nextElementSibling}function y(e,t){var n=b(e),o="true"===e.getAttribute(f),r="boolean"==typeof t?t:"toggle"===t?!o:o,i=o===r||l(e,"toggle",{relatedTarget:n,isOpen:o,willOpen:r})?r:"true"===e.getAttribute(f),u=!o&&i&&n.querySelector("[autofocus]");u&&setTimeout(function(){return u&&u.focus()}),e.setAttribute(f,i),n[i?"removeAttribute":"setAttribute"]("hidden","")}i(c,"keydown",function(e){if(e.keyCode===v)for(var t=e.target;t;t=t.parentElement){var n=t.id&&document.querySelector('[aria-controls="'+t.id+'"]')||t;if(n.hasAttribute(c)&&n.hasAttribute(g)&&"true"===n.getAttribute(f))return e.preventDefault(),n.focus(),y(n,!1)}},!0),i(c,"click",function(e){var r=e.target;if(e.defaultPrevented)return!1;for(var t=r,n=void 0;t;t=t.parentElement){var o=n&&t.id&&document.querySelector("["+c+'][aria-controls="'+t.id+'"]');if("BUTTON"!==t.nodeName&&"A"!==t.nodeName||t.hasAttribute(c)||(n=t),o){l(o,"toggle.select",{relatedTarget:b(o),currentTarget:n,value:n.textContent.trim()});break}}d("["+c+"]").forEach(function(e){var t="true"===e.getAttribute(f),n=e.hasAttribute(g),o=b(e);e.contains(r)?y(e,!t):n&&t&&y(e,o.contains(r))})});var h=function(t){function i(e){t.call(this,e),this.onToggle=this.onToggle.bind(this)}t&&(i.__proto__=t),(i.prototype=Object.create(t&&t.prototype)).constructor=i;var e={defaultProps:{configurable:!0}};return e.defaultProps.get=function(){return{open:null,popup:null,onToggle:null}},i.prototype.componentDidMount=function(){m(this.el.firstElementChild),this.el.addEventListener("toggle",this.onToggle)},i.prototype.componentDidUpdate=function(){m(this.el.firstElementChild)},i.prototype.componentWillUnmount=function(){this.el.removeEventListener("toggle",this.onToggle)},i.prototype.onToggle=function(e){this.props.onToggle&&this.props.onToggle(e)},i.prototype.render=function(){var n,o,e,r=this;return u.createElement("div",(n=this.props,o=i.defaultProps,void 0===(e={ref:function(e){return r.el=e}})&&(e={}),Object.keys(n).reduce(function(e,t){return o.hasOwnProperty(t)||(e[t]=n[t]),e},e)),u.Children.map(this.props.children,function(e,t){return 0===t?u.cloneElement(e,{"aria-expanded":String(Boolean(r.props.open)),"data-haspopup":r.props.popup}):1===t?u.cloneElement(e,{hidden:!r.props.open}):e}))},Object.defineProperties(i,e),i}(u.Component);return h.propTypes={open:e.bool,popup:e.oneOfType([e.bool,e.string]),onToggle:e.func},h});
//# sourceMappingURL=core-toggle.jsx.js.map

@@ -1,3 +0,3 @@

/*! @nrk/core-toggle v1.2.1 - Copyright (c) 2017-2018 NRK */
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.coreToggle=e()}(this,function(){"use strict";var t="undefined"!=typeof window,e=t&&/(android)/i.test(navigator.userAgent),n=t&&/iPad|iPhone|iPod/.test(String(navigator.platform)),o=function(t){void 0===t&&(t=!1);try{window.addEventListener("test",null,{get passive(){t=!0}})}catch(t){}return t}();function r(t,e,n,r){(void 0===r&&(r=!1),"undefined"==typeof window||window[t=t+"-"+e])||(o||"object"!=typeof r||(r=Boolean(r.capture)),("resize"===e||"load"===e?window:document).addEventListener(window[t]=e,n,r))}var a="prevent_recursive_dispatch_maximum_callstack";function i(t){return Date.now().toString(36)+Math.random().toString(36).slice(2,5)}function u(t,e){if(void 0===e&&(e=document),t){if(t.nodeType)return[t];if("string"==typeof t)return[].slice.call(e.querySelectorAll(t));if(t.length)return[].slice.call(t)}return[]}var d="data-@nrk/core-toggle-1.2.1".replace(/\W+/g,"-"),c=e?"data":"aria",l="aria-expanded",f="data-haspopup",s=27;function p(t){return document.getElementById(t.getAttribute("aria-controls"))||t.nextElementSibling}function g(t,e){var n=p(t),r="true"===t.getAttribute(l),o="boolean"==typeof e?e:"toggle"===e?!r:r,i=r===o||function(t,e,n){void 0===n&&(n={});var r,o=""+a+e;if(t[o])return!0;t[o]=!0,"function"==typeof window.CustomEvent?r=new window.CustomEvent(e,{bubbles:!0,cancelable:!0,detail:n}):(r=document.createEvent("CustomEvent")).initCustomEvent(e,!0,!0,n);var i=t.dispatchEvent(r);return t[o]=null,i}(t,"toggle",{relatedTarget:n,isOpen:r,willOpen:o})?o:"true"===t.getAttribute(l),u=!r&&i&&n.querySelector("[autofocus]");u&&setTimeout(function(){return u&&u.focus()}),t.setAttribute(l,i),n[i?"removeAttribute":"setAttribute"]("hidden","")}return r(d,"keydown",function(t){if(t.keyCode===s)for(var e=t.target;e;e=e.parentElement){var n=e.id&&document.querySelector('[aria-controls="'+e.id+'"]')||e;if(n.hasAttribute(d)&&"true"===n.getAttribute(f)&&"true"===n.getAttribute(l))return t.preventDefault(),n.focus(),g(n,!1)}},!0),r(d,"click",function(t){var o=t.target;if(t.defaultPrevented)return!1;u("["+d+"]").forEach(function(t){var e="true"===t.getAttribute(l),n="true"===t.getAttribute(f),r=p(t);t.contains(o)?g(t,!e):n&&e&&g(t,r.contains(o))})}),function(t,e){var o="object"==typeof e?e:{open:e};return n&&(document.documentElement.style.cursor="pointer"),u(t).map(function(t){var e="boolean"==typeof o.open?o.open:"true"===t.getAttribute(l),n="boolean"==typeof o.popup?o.popup:"true"===t.getAttribute(f),r=p(t);return t.setAttribute(d,""),t.setAttribute(f,n),t.setAttribute("aria-controls",r.id=r.id||i()),r.setAttribute(c+"-labelledby",t.id=t.id||i()),g(t,e),t})}});
/*! @nrk/core-toggle v1.2.2 - Copyright (c) 2017-2018 NRK */
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.coreToggle=e()}("undefined"!=typeof self?self:this,function(){"use strict";var t="undefined"!=typeof window,e=t&&/(android)/i.test(navigator.userAgent),n=t&&/iPad|iPhone|iPod/.test(String(navigator.platform)),o=function(t){void 0===t&&(t=!1);try{window.addEventListener("test",null,{get passive(){t=!0}})}catch(t){}return t}();function r(t,e,n,r){(void 0===r&&(r=!1),"undefined"==typeof window||window[t=t+"-"+e])||(o||"object"!=typeof r||(r=Boolean(r.capture)),("resize"===e||"load"===e?window:document).addEventListener(window[t]=e,n,r))}var u="prevent_recursive_dispatch_maximum_callstack";function a(t,e,n){void 0===n&&(n={});var r,o=""+u+e;if(t[o])return!0;t[o]=!0,"function"==typeof window.CustomEvent?r=new window.CustomEvent(e,{bubbles:!0,cancelable:!0,detail:n}):(r=document.createEvent("CustomEvent")).initCustomEvent(e,!0,!0,n);var i=t.dispatchEvent(r);return t[o]=null,i}function d(t){return Date.now().toString(36)+Math.random().toString(36).slice(2,5)}function c(t,e){if(void 0===e&&(e=document),t){if(t.nodeType)return[t];if("string"==typeof t)return[].slice.call(e.querySelectorAll(t));if(t.length)return[].slice.call(t)}return[]}var l="data-@nrk/core-toggle-1.2.2".replace(/\W+/g,"-"),f=e?"data":"aria",s="aria-expanded",p="data-haspopup",i=27;function v(t){return document.getElementById(t.getAttribute("aria-controls"))||t.nextElementSibling}function g(t,e){var n=v(t),r="true"===t.getAttribute(s),o="boolean"==typeof e?e:"toggle"===e?!r:r,i=r===o||a(t,"toggle",{relatedTarget:n,isOpen:r,willOpen:o})?o:"true"===t.getAttribute(s),u=!r&&i&&n.querySelector("[autofocus]");u&&setTimeout(function(){return u&&u.focus()}),t.setAttribute(s,i),n[i?"removeAttribute":"setAttribute"]("hidden","")}return r(l,"keydown",function(t){if(t.keyCode===i)for(var e=t.target;e;e=e.parentElement){var n=e.id&&document.querySelector('[aria-controls="'+e.id+'"]')||e;if(n.hasAttribute(l)&&n.hasAttribute(p)&&"true"===n.getAttribute(s))return t.preventDefault(),n.focus(),g(n,!1)}},!0),r(l,"click",function(t){var o=t.target;if(t.defaultPrevented)return!1;for(var e=o,n=void 0;e;e=e.parentElement){var r=n&&e.id&&document.querySelector("["+l+'][aria-controls="'+e.id+'"]');if("BUTTON"!==e.nodeName&&"A"!==e.nodeName||e.hasAttribute(l)||(n=e),r){a(r,"toggle.select",{relatedTarget:v(r),currentTarget:n,value:n.textContent.trim()});break}}c("["+l+"]").forEach(function(t){var e="true"===t.getAttribute(s),n=t.hasAttribute(p),r=v(t);t.contains(o)?g(t,!e):n&&e&&g(t,r.contains(o))})}),function(t,e){var i="object"==typeof e?e:{open:e};return n&&(document.documentElement.style.cursor="pointer"),c(t).map(function(t){var e="true"===t.getAttribute(s),n="boolean"==typeof i.open?i.open:"toggle"===i.open?!e:e,r="string"==typeof i.popup?i.popup:t.getAttribute(p),o=v(t);return t.setAttribute(l,""),t[r?"setAttribute":"removeAttribute"](p,r),t.setAttribute("aria-controls",o.id=o.id||d()),o.setAttribute(f+"-labelledby",t.id=t.id||d()),g(t,n),i.value&&(t.innerHTML=i.value),r&&t.setAttribute("aria-label",t.textContent+", "+r),t})}});
//# sourceMappingURL=core-toggle.min.js.map

@@ -0,39 +1,5 @@

/* global expect, describe, it */
const coreToggle = require('./core-toggle.min')
function expectClosedAttributes (button, container) {
expect(button.getAttribute('aria-expanded')).toEqual('false')
expect(button.getAttribute('aria-controls')).toEqual(container.id)
expect(container.hasAttribute('hidden')).toBeTruthy()
expect(container.getAttribute('aria-labelledby')).toEqual(button.id)
}
function expectOpenAttributes (button, container) {
expect(button.getAttribute('aria-expanded')).toEqual('true')
expect(button.getAttribute('aria-controls')).toEqual(container.id)
expect(container.hasAttribute('hidden')).toBeFalsy()
expect(container.getAttribute('aria-labelledby')).toEqual(button.id)
}
function expectOpened (button, container) {
expect(button.getAttribute('data-haspopup')).toEqual('false')
expectOpenAttributes(button, container)
}
function expectClosed (button, container) {
expect(button.getAttribute('data-haspopup')).toEqual('false')
expectClosedAttributes(button, container)
}
function expectPopupOpened (button, container) {
expect(button.getAttribute('data-haspopup')).toEqual('true')
expectOpenAttributes(button, container)
}
function expectPopupClosed (button, container) {
expect(button.getAttribute('data-haspopup')).toEqual('true')
expectClosedAttributes(button, container)
}
const standardHTML = `

@@ -49,92 +15,71 @@ <button class="my-toggle">Toggle VanillaJS</button>

it('should initialize button and container with props when core-toggle is called', () => {
it('should initialize button and container', () => {
document.body.innerHTML = standardHTML
const button = document.querySelector('.my-toggle')
const container = document.querySelector('.my-toggle + *')
coreToggle(button)
expectClosed(button, container)
expect(button.hasAttribute('data-haspopup')).toEqual(false)
expect(button.getAttribute('aria-expanded')).toEqual('false')
expect(button.getAttribute('aria-controls')).toEqual(container.id)
expect(container.hasAttribute('hidden')).toEqual(true)
expect(container.getAttribute('aria-labelledby')).toEqual(button.id)
})
it('should open when calling coreToggle with open attribute set to true', () => {
it('should open with open attribute', () => {
document.body.innerHTML = standardHTML
const button = document.querySelector('.my-toggle')
const container = document.querySelector('.my-toggle + *')
coreToggle(button, { open: true })
expectOpened(button, container)
expect(container.hasAttribute('hidden')).toEqual(false)
expect(button.getAttribute('aria-expanded')).toEqual('true')
})
it('should close an open container when calling coreToggle with open attribute set to false', () => {
it('should close an opened toggle', () => {
document.body.innerHTML = standardHTML
const button = document.querySelector('.my-toggle')
const container = document.querySelector('.my-toggle + *')
coreToggle(button, { open: true })
coreToggle(button, { open: false })
expectClosed(button, container)
expect(container.hasAttribute('hidden')).toEqual(true)
})
it('should set popup attributes when initialized as a popup', () => {
it('should initialize as popup', () => {
document.body.innerHTML = standardHTML
const button = document.querySelector('.my-toggle')
const container = document.querySelector('.my-toggle + *')
coreToggle(button, { popup: true })
expectPopupClosed(button, container)
coreToggle(button, { popup: 'Test' })
expect(button.hasAttribute('data-haspopup')).toEqual(true)
})
it('should open popup when calling coreToggle with open attribute set to true', () => {
it('should open popup with open', () => {
document.body.innerHTML = standardHTML
const button = document.querySelector('.my-toggle')
const container = document.querySelector('.my-toggle + *')
coreToggle(button, { popup: true, open: true })
expectPopupOpened(button, container)
coreToggle(button, { popup: 'Tekst', open: true })
expect(button.getAttribute('data-haspopup')).toEqual('Tekst')
expect(container.hasAttribute('hidden')).toEqual(false)
})
it('should close popup when calling coreToggle with open attribute set to false', () => {
it('should close popup', () => {
document.body.innerHTML = standardHTML
const button = document.querySelector('.my-toggle')
const container = document.querySelector('.my-toggle + *')
coreToggle(button, { popup: true, open: true })
coreToggle(button, { popup: true, open: false })
expectPopupClosed(button, container)
coreToggle(button, { popup: 'Tekst', open: true })
coreToggle(button, { open: false })
expect(container.hasAttribute('hidden')).toEqual(true)
})
it('should respect existing aria-controls attribute if target is found', () => {
it('should respect existing aria-controls', () => {
document.body.innerHTML = `
<div><button class="my-toggle" aria-controls="content">Toggle VanillaJS</button></div>
<div id="content" hidden>Content</div>`
const button = document.querySelector('.my-toggle')
const container = document.querySelector('#content')
coreToggle(button, { open: false })
expect(button.getAttribute('aria-controls')).toEqual('content')
expectClosedAttributes(button, container)
expect(container.hasAttribute('hidden')).toEqual(true)
coreToggle(button, { open: true })
expectOpenAttributes(button, container)
expect(container.hasAttribute('hidden')).toEqual(false)
expect(button.getAttribute('aria-expanded')).toEqual('true')
expect(button.getAttribute('aria-controls')).toEqual(container.id)
expect(container.getAttribute('aria-labelledby')).toEqual(button.id)
})
})
module.exports = {
expectOpened,
expectClosed,
expectPopupOpened,
expectPopupClosed
}

@@ -0,1 +1,3 @@

/* global expect, describe, it */
const React = require('react')

@@ -5,3 +7,2 @@ const ReactDOM = require('react-dom')

const { name, version } = require('./package.json')
const { expectOpened, expectClosed, expectPopupOpened, expectPopupClosed } = require('./core-toggle.test.js')

@@ -26,28 +27,36 @@ const UUID = `data-${name}-${version}`.replace(/\W+/g, '-')

const container = document.querySelector(`[${UUID}] + *`)
expect(wrapper.props.open).toBeNull()
expect(wrapper.props.popup).toBeNull()
expectClosed(button, container)
expect(container.hasAttribute('hidden')).toEqual(true)
expect(button.hasAttribute('data-haspopup')).toEqual(false)
expect(button.getAttribute('aria-expanded')).toEqual('false')
expect(button.getAttribute('aria-controls')).toEqual(container.id)
expect(container.getAttribute('aria-labelledby')).toEqual(button.id)
})
it('should show content when open prop is set to true', () => {
it('should open with open attribute', () => {
mount({ open: true })
const button = document.querySelector(`[${UUID}]`)
const container = document.querySelector(`[${UUID}] + *`)
expectOpened(button, container)
expect(container.hasAttribute('hidden')).toEqual(false)
expect(button.getAttribute('aria-expanded')).toEqual('true')
})
it('should initialize as popup when popup prop is set to true', () => {
mount({ popup: true })
it('should initialize as popup', () => {
mount({ popup: 'Tekst' })
const button = document.querySelector(`[${UUID}]`)
const container = document.querySelector(`[${UUID}] + *`)
expectPopupClosed(button, container)
expect(container.hasAttribute('hidden')).toEqual(true)
expect(button.getAttribute('data-haspopup')).toEqual('Tekst')
expect(button.getAttribute('aria-expanded')).toEqual('false')
})
it('should open as a popup when popup and open prop is set to true', () => {
mount({ open: true, popup: true })
it('should open popup with open', () => {
mount({ open: true, popup: 'Tekst' })
const button = document.querySelector(`[${UUID}]`)
const container = document.querySelector(`[${UUID}] + *`)
expectPopupOpened(button, container)
expect(container.hasAttribute('hidden')).toEqual(false)
expect(button.getAttribute('data-haspopup')).toEqual('Tekst')
expect(button.getAttribute('aria-expanded')).toEqual('true')
})
})

@@ -9,3 +9,3 @@ 'use strict';

var name = "@nrk/core-toggle";
var version = "1.2.1";
var version = "1.2.2";

@@ -111,25 +111,28 @@ var IS_BROWSER = typeof window !== 'undefined';

var OPEN = 'aria-expanded';
var POPS = 'data-haspopup'; // aria-haspopup triggers forms mode in JAWS, therefore data-
var POPUP = 'data-haspopup'; // aria-haspopup triggers forms mode in JAWS, therefore data-
var KEYS = { ESC: 27 };
function toggle (buttons, open) {
function toggle (toggles, open) {
var options = typeof open === 'object' ? open : { open: open };
if (IS_IOS) { document.documentElement.style.cursor = 'pointer'; } // Fix iOS events for closing {popup: true} https://stackoverflow.com/questions/14795944/jquery-click-events-not-working-in-ios#16006333
if (IS_IOS) { document.documentElement.style.cursor = 'pointer'; } // Fix iOS events for closing popups (https://stackoverflow.com/a/16006333/8819615)
return queryAll(buttons).map(function (button) {
var open = typeof options.open === 'boolean' ? options.open : button.getAttribute(OPEN) === 'true';
var pops = typeof options.popup === 'boolean' ? options.popup : button.getAttribute(POPS) === 'true';
var content = getContentElement(button);
return queryAll(toggles).map(function (toggle) {
var isOpen = toggle.getAttribute(OPEN) === 'true';
var open = typeof options.open === 'boolean' ? options.open : (options.open === 'toggle' ? !isOpen : isOpen);
var popup = typeof options.popup === 'string' ? options.popup : toggle.getAttribute(POPUP);
var content = getContentElement(toggle);
button.setAttribute(UUID, '');
button.setAttribute(POPS, pops);
button.setAttribute('aria-controls', content.id = content.id || getUUID());
content.setAttribute((ARIA + "-labelledby"), button.id = button.id || getUUID());
setOpen(button, open);
return button
toggle.setAttribute(UUID, '');
toggle[popup ? 'setAttribute' : 'removeAttribute'](POPUP, popup);
toggle.setAttribute('aria-controls', content.id = content.id || getUUID());
content.setAttribute((ARIA + "-labelledby"), toggle.id = toggle.id || getUUID());
setOpen(toggle, open);
if (options.value) { toggle.innerHTML = options.value; }
if (popup) { toggle.setAttribute('aria-label', ((toggle.textContent) + ", " + popup)); }
return toggle
})
}
function getContentElement (button) {
return document.getElementById(button.getAttribute('aria-controls')) || button.nextElementSibling
function getContentElement (toggle) {
return document.getElementById(toggle.getAttribute('aria-controls')) || toggle.nextElementSibling
}

@@ -140,8 +143,8 @@

for (var el = event.target; el; el = el.parentElement) {
var button = (el.id && document.querySelector(("[aria-controls=\"" + (el.id) + "\"]"))) || el;
var toggle = (el.id && document.querySelector(("[aria-controls=\"" + (el.id) + "\"]"))) || el;
if (button.hasAttribute(UUID) && button.getAttribute(POPS) === 'true' && button.getAttribute(OPEN) === 'true') {
if (toggle.hasAttribute(UUID) && toggle.hasAttribute(POPUP) && toggle.getAttribute(OPEN) === 'true') {
event.preventDefault(); // Prevent leaving maximized window in Safari
button.focus();
return setOpen(button, false)
toggle.focus();
return setOpen(toggle, false)
}

@@ -156,18 +159,32 @@ }

if (defaultPrevented) { return false } // Do not toggle if someone run event.preventDefault()
queryAll(("[" + UUID + "]")).forEach(function (el) {
var open = el.getAttribute(OPEN) === 'true';
var pops = el.getAttribute(POPS) === 'true';
var content = getContentElement(el);
if (el.contains(target)) { setOpen(el, !open); } // Click on toggle
else if (pops && open) { setOpen(el, content.contains(target)); } // Click in content or outside
for (var el = target, item = (void 0); el; el = el.parentElement) {
var toggle = item && el.id && document.querySelector(("[" + UUID + "][aria-controls=\"" + (el.id) + "\"]"));
if ((el.nodeName === 'BUTTON' || el.nodeName === 'A') && !el.hasAttribute(UUID)) { item = el; } // interactive element clicked
if (toggle) {
dispatchEvent(toggle, 'toggle.select', {
relatedTarget: getContentElement(toggle),
currentTarget: item,
value: item.textContent.trim()
});
break
}
}
queryAll(("[" + UUID + "]")).forEach(function (toggle) {
var open = toggle.getAttribute(OPEN) === 'true';
var popup = toggle.hasAttribute(POPUP);
var content = getContentElement(toggle);
if (toggle.contains(target)) { setOpen(toggle, !open); } // Click on toggle
else if (popup && open) { setOpen(toggle, content.contains(target)); } // Click in content or outside
});
});
function setOpen (button, open) {
var content = getContentElement(button);
var isOpen = button.getAttribute(OPEN) === 'true';
function setOpen (toggle, open) {
var content = getContentElement(toggle);
var isOpen = toggle.getAttribute(OPEN) === 'true';
var willOpen = typeof open === 'boolean' ? open : (open === 'toggle' ? !isOpen : isOpen);
var isUpdate = isOpen === willOpen || dispatchEvent(button, 'toggle', { relatedTarget: content, isOpen: isOpen, willOpen: willOpen });
var nextOpen = isUpdate ? willOpen : button.getAttribute(OPEN) === 'true'; // dispatchEvent can change attributes
var isUpdate = isOpen === willOpen || dispatchEvent(toggle, 'toggle', { relatedTarget: content, isOpen: isOpen, willOpen: willOpen });
var nextOpen = isUpdate ? willOpen : toggle.getAttribute(OPEN) === 'true'; // dispatchEvent can change attributes
var focus = !isOpen && nextOpen && content.querySelector('[autofocus]');

@@ -177,7 +194,7 @@

button.setAttribute(OPEN, nextOpen);
toggle.setAttribute(OPEN, nextOpen);
content[nextOpen ? 'removeAttribute' : 'setAttribute']('hidden', '');
}
var Toggle = (function (superclass) {
var Toggle = /*@__PURE__*/(function (superclass) {
function Toggle (props) {

@@ -210,3 +227,3 @@ superclass.call(this, props);

'aria-expanded': String(Boolean(this$1.props.open)),
'data-haspopup': String(Boolean(this$1.props.popup))
'data-haspopup': this$1.props.popup
})

@@ -227,3 +244,3 @@ }

open: PropTypes.bool,
popup: PropTypes.bool,
popup: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
onToggle: PropTypes.func

@@ -230,0 +247,0 @@ };

@@ -5,3 +5,3 @@ {

"author": "NRK <opensource@nrk.no> (https://www.nrk.no/)",
"version": "1.2.2",
"version": "2.0.0",
"license": "MIT",

@@ -8,0 +8,0 @@ "main": "core-toggle.cjs.js",

# Core Toggle
## `@nrk/core-toggle` simply makes a `<button>` toggle the visibility of next element sibling. Toggles can be nested and easily extended with custom animations or behavior through the [toggle event](#events). It has two modes:
> `@nrk/core-toggle` simply makes a `<button>` toggle the visibility of next element sibling. Toggles can be nested and easily extended with custom animations or behavior through the [toggle event](#events). It has two modes:
---
## Installation

@@ -17,14 +17,11 @@

---
## Demo
## Demo: Default
<!--demo
<script src="core-toggle/core-toggle.min.js"></script>
<script src="core-toggle/core-toggle.jsx.js"></script>
<div class="nrk-grid">
<div class="nrk-xs-12of12 nrk-md-6of12" style="padding-right:30px"><h3>Default toggle</h3>
Content is only toggled when clicking <code>button</code>. Great for accordions and expand/collapse panels.
demo-->
Content is only toggled when clicking `button`. Great for accordions and expand/collapse panels.

@@ -51,6 +48,6 @@ ```html

</div>
<div class="nrk-xs-12of12 nrk-md-6of12"><h3>Popup toggle</h3>
Content is toggled when clicking <code>button</code>, and closed when clicking outside content. Great for dropdowns and tooltips.
## Demo: Popup
Content is toggled when clicking `button`, and closed when clicking outside content. Great for dropdowns and tooltips.
```html

@@ -60,13 +57,8 @@ <!--demo-->

<ul class="my-dropdown" hidden>
<li><a href="#">Link</a></li>
<li><a>Link</a></li>
<li>
<button class="my-popup">Can also be nested</button>
<ul class="my-dropdown" hidden>
<li><a href="#">Sub-link</a></li>
<li>
<label>
<span class="nrk-sr">Skriv her</span>
<input type="text" autofocus>
</label>
</li>
<li><a>Sub-link</a></li>
<li><input type="text" autofocus aria-label="Skriv her"></li>
</ul>

@@ -76,3 +68,3 @@ </li>

<script>
coreToggle('.my-popup', {popup: true})
coreToggle('.my-popup', { popup: 'Example picker' })
</script>

@@ -85,3 +77,3 @@ ```

<script type="text/jsx">
ReactDOM.render(<CoreToggle popup>
ReactDOM.render(<CoreToggle popup='Example picker'>
<button>Popup JSX</button>

@@ -91,3 +83,3 @@ <ul className='my-dropdown'>

<li>
<CoreToggle popup>
<CoreToggle popup='Example picker'>
<button>Can also be nested</button>

@@ -104,7 +96,25 @@ <ul className='my-dropdown'>

</div>
</div>
---
## Demo: Select
Listen to the `toggle.select` event and update the button's value from the selected item
to create a component that behaves like a `<select>`:
```html
<!--demo-->
<button class="my-popup-value">Select number</button>
<ul class="my-dropdown" hidden>
<li><button>One</button></li>
<li><button>Two</button></li>
<li><button>Three</button></li>
</ul>
<script>
document.addEventListener('toggle.select', (event) => {
if (event.target.className !== 'my-popup-value') return
coreToggle(event.target, { value: event.detail.value, open: false })
})
coreToggle('.my-popup-value', { popup: 'Number picker'})
</script>
```
## Usage

@@ -124,3 +134,4 @@

open: null, // Defaults to value of aria-expanded or false. Use true|false to force open state
popup: false // Defaults to false. Use true to enable click-outside-to-close
popup: false|String // Defaults to false. Use string to enable popup (click-outside-to-close)
value: undefined|String // Defaults to existing markup value. Pass string to change the button's innerHTML.
})

@@ -144,4 +155,4 @@ ```

---
## Markup

@@ -164,8 +175,11 @@

---
## Events
Before a `@nrk/core-toggle` changes open state, a [toggle event](https://www.w3schools.com/jsref/event_ontoggle.asp) is fired (both for VanillaJS and React/Preact components). The toggle event is cancelable, meaning you can use [`event.preventDefault()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault) to cancel toggling. The event also [bubbles](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture), and can therefore be detected both from button element itself, or any parent element (read [event delegation](https://stackoverflow.com/questions/1687296/what-is-dom-event-delegation)):
### toggle
Before a `@nrk/core-toggle` changes open state, a [toggle event](https://www.w3schools.com/jsref/event_ontoggle.asp) is fired (both for VanillaJS and React/Preact components). The toggle event is cancelable, meaning you can use [`event.preventDefault()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault) to cancel toggling. The event also [bubbles](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture), and can therefore be detected both from the button element itself, or any parent element (read [event delegation](https://stackoverflow.com/questions/1687296/what-is-dom-event-delegation)):
```js

@@ -180,4 +194,18 @@ document.addEventListener('toggle', (event) => {

---
### toggle.select
The `toggle.select` event is fired whenever an item is selected inside a toggle with the `popup` option enabled.
Useful for setting the value of the toggle button with the selected value.
```js
document.addEventListener('toggle.select', (event) => {
event.target // The buttom element triggering the event
event.detail.relatedTarget // The content element controlled by button
event.detail.currentTarget // The item element selected
event.detail.value // The selected item's value
})
```
## Styling

@@ -197,4 +225,4 @@

---
## FAQ

@@ -201,0 +229,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc