@nrk/core-toggle
Advanced tools
Comparing version 3.0.8 to 3.0.9-0
@@ -0,1 +1,2 @@ | ||
/*! @nrk/core-toggle v3.0.9-0 - Copyright (c) 2017-2021 NRK */ | ||
'use strict'; | ||
@@ -56,3 +57,3 @@ | ||
function isNativeReflectConstruct() { | ||
function _isNativeReflectConstruct() { | ||
if (typeof Reflect === "undefined" || !Reflect.construct) return false; | ||
@@ -63,3 +64,3 @@ if (Reflect.construct.sham) return false; | ||
try { | ||
Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); | ||
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); | ||
return true; | ||
@@ -72,3 +73,3 @@ } catch (e) { | ||
function _construct(Parent, args, Class) { | ||
if (isNativeReflectConstruct()) { | ||
if (_isNativeReflectConstruct()) { | ||
_construct = Reflect.construct; | ||
@@ -143,6 +144,26 @@ } else { | ||
function _createSuper(Derived) { | ||
var hasNativeReflectConstruct = _isNativeReflectConstruct(); | ||
return function _createSuperInternal() { | ||
var Super = _getPrototypeOf(Derived), | ||
result; | ||
if (hasNativeReflectConstruct) { | ||
var NewTarget = _getPrototypeOf(this).constructor; | ||
result = Reflect.construct(Super, arguments, NewTarget); | ||
} else { | ||
result = Super.apply(this, arguments); | ||
} | ||
return _possibleConstructorReturn(this, result); | ||
}; | ||
} | ||
var IS_BROWSER = typeof window !== 'undefined'; | ||
var IS_ANDROID = IS_BROWSER && /(android)/i.test(navigator.userAgent); // Bad, but needed | ||
var IS_IOS = IS_BROWSER && /iPad|iPhone|iPod/.test(String(navigator.platform)); // Mock HTMLElement for Node | ||
var IS_IOS = IS_BROWSER && /iPad|iPhone|iPod/.test(String(navigator.platform)); | ||
// Mock HTMLElement for Node | ||
@@ -237,9 +258,13 @@ if (!IS_BROWSER && !global.HTMLElement) { | ||
var SCROLLER = IS_BROWSER && document.createElement('div'); | ||
var CoreToggle = /*#__PURE__*/function (_HTMLElement) { | ||
_inherits(CoreToggle, _HTMLElement); | ||
var _super = _createSuper(CoreToggle); | ||
function CoreToggle() { | ||
_classCallCheck(this, CoreToggle); | ||
return _possibleConstructorReturn(this, _getPrototypeOf(CoreToggle).apply(this, arguments)); | ||
return _super.apply(this, arguments); | ||
} | ||
@@ -270,2 +295,3 @@ | ||
document.removeEventListener('click', this); | ||
handleAutoposition(this, true); | ||
} | ||
@@ -283,2 +309,3 @@ }, { | ||
handleAutoposition(this, this.hidden); | ||
dispatchEvent(this, 'toggle'); | ||
@@ -291,2 +318,3 @@ } | ||
if (event.defaultPrevented) return; | ||
if (event.type === 'resize' || event.type === 'scroll') return this.updatePosition(); | ||
@@ -310,8 +338,38 @@ if (event.type === 'keydown' && event.keyCode === 27) { | ||
} | ||
/** | ||
* updatePosition Exposed for _very_ niche situations, use sparingly | ||
* @param {HTMLElement} contentEl Reference to the core-toggle element | ||
*/ | ||
}, { | ||
key: "updatePosition", | ||
value: function updatePosition() { | ||
var _this = this; | ||
if (this._skipPosition || !this.button) return; // Avoid infinite loops for mutationObserver | ||
this._skipPosition = true; | ||
this.style.position = 'fixed'; // Set viewModel before reading dimensions | ||
var triggerRect = this.button.getBoundingClientRect(); | ||
var contentRect = this.getBoundingClientRect(); | ||
var hasSpaceRight = triggerRect.left + contentRect.width < window.innerWidth; | ||
var hasSpaceUnder = triggerRect.bottom + contentRect.height < window.innerHeight; | ||
var hasSpaceOver = triggerRect.top - contentRect.height > 0; // Always place under when no hasSpaceOver, as no OS can scroll further up than window.scrollY = 0 | ||
var placeUnder = hasSpaceUnder || !hasSpaceOver; | ||
var scroll = placeUnder ? window.pageYOffset + triggerRect.bottom + contentRect.height + 30 : 0; | ||
this.style.left = "".concat(Math.round(hasSpaceRight ? triggerRect.left : triggerRect.right - contentRect.width), "px"); | ||
this.style.top = "".concat(Math.round(placeUnder ? triggerRect.bottom : triggerRect.top - contentRect.height), "px"); | ||
SCROLLER.style.cssText = "position:absolute;padding:1px;top:".concat(Math.round(scroll), "px"); | ||
setTimeout(function () { | ||
return _this._skipPosition = null; | ||
}); // Timeout to flush event queue before we can resume acting on mutations | ||
} | ||
}, { | ||
key: "button", | ||
get: function get() { | ||
if (this._button && this._button.getAttribute('for') === this.id) return this._button; // Speed up | ||
if (this._button && (this._button.getAttribute('data-for') || this._button.getAttribute('for')) === this.id) return this._button; // Speed up | ||
return (this._button = this.id && document.querySelector("[for=\"".concat(this.id, "\"]"))) || this.previousElementSibling; | ||
return (this._button = this.id && document.querySelector("[for=\"".concat(this.id, "\"],[data-for=\"").concat(this.id, "\"]"))) || this.previousElementSibling; | ||
} // aria-haspopup triggers forms mode in JAWS, therefore store as custom attr | ||
@@ -326,2 +384,10 @@ | ||
this[val === false ? 'removeAttribute' : 'setAttribute']('popup', val); | ||
} | ||
}, { | ||
key: "autoposition", | ||
get: function get() { | ||
return this.hasAttribute('autoposition'); | ||
}, | ||
set: function set(val) { | ||
toggleAttribute(this, 'autoposition', val); | ||
} // Must set attribute for IE11 | ||
@@ -336,5 +402,5 @@ | ||
toggleAttribute(this, 'hidden', val); | ||
} // Sets this.button aria-label, so visible button text can be augmentet with intension of button | ||
} // Set this.button aria-label, so that visible button text can be augmentet with intention of button | ||
// Example: Button text: "01.02.2019", aria-label: "01.02.2019, Choose date" | ||
// Does not updates aria-label if not allready set to something else than this.popup | ||
// Does not update aria-label if not already set to something else than this.popup | ||
@@ -346,4 +412,7 @@ }, { | ||
}, | ||
set: function set() { | ||
var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; | ||
set: function set(data) { | ||
if (data === void 0) { | ||
data = false; | ||
} | ||
if (!this.button || !this.popup.length) return; | ||
@@ -358,4 +427,4 @@ var button = this.button; | ||
button.value = data.value || label; | ||
target[data.innerHTML ? 'innerHTML' : 'textContent'] = data.innerHTML || label; | ||
button.setAttribute('aria-label', "".concat(button.textContent, ",").concat(this.popup)); | ||
target[data.innerHTML ? 'innerHTML' : 'textContent'] = data.innerHTML || label; | ||
} | ||
@@ -366,3 +435,3 @@ } | ||
get: function get() { | ||
return ['hidden']; | ||
return ['hidden', 'autoposition']; | ||
} | ||
@@ -374,2 +443,26 @@ }]); | ||
function handleAutoposition(self, teardown) { | ||
if (teardown) { | ||
if (self._positionObserver) self._positionObserver.disconnect(); | ||
if (SCROLLER.parentNode) SCROLLER.parentNode.removeChild(SCROLLER); | ||
self.style.position = self._positionObserver = null; | ||
window.removeEventListener('scroll', self, true); // Use capture to also listen for elements with overflow | ||
window.removeEventListener('resize', self); | ||
} else if (self.autoposition) { | ||
// Attach MutationObserver if supported | ||
if (!self._positionObserver) self._positionObserver = window.MutationObserver && new window.MutationObserver(self.updatePosition.bind(self)); | ||
if (self._positionObserver) self._positionObserver.observe(self, { | ||
childList: true, | ||
subtree: true, | ||
attributes: true | ||
}); | ||
document.body.appendChild(SCROLLER); | ||
window.addEventListener('scroll', self, true); // Use capture to also listen for elements with overflow | ||
window.addEventListener('resize', self); | ||
self.updatePosition(); // Initial trigger | ||
} | ||
} | ||
module.exports = CoreToggle; |
@@ -1,5 +0,7 @@ | ||
import { IS_ANDROID, IS_IOS, closest, dispatchEvent, getUUID, toggleAttribute } from '../utils' | ||
import { closest, dispatchEvent, getUUID, IS_ANDROID, IS_BROWSER, IS_IOS, toggleAttribute } from '../utils' | ||
// Element to ensure overflowing content can be reached by scrolling | ||
const SCROLLER = IS_BROWSER && document.createElement('div') | ||
export default class CoreToggle extends HTMLElement { | ||
static get observedAttributes () { return ['hidden'] } | ||
static get observedAttributes () { return ['hidden', 'autoposition'] } | ||
@@ -22,2 +24,3 @@ connectedCallback () { | ||
document.removeEventListener('click', this) | ||
handleAutoposition(this, true) | ||
} | ||
@@ -29,2 +32,3 @@ | ||
try { this.querySelector('[autofocus]').focus() } catch (err) {} | ||
handleAutoposition(this, this.hidden) | ||
dispatchEvent(this, 'toggle') | ||
@@ -36,2 +40,3 @@ } | ||
if (event.defaultPrevented) return | ||
if (event.type === 'resize' || event.type === 'scroll') return this.updatePosition() | ||
if (event.type === 'keydown' && event.keyCode === 27) { | ||
@@ -54,5 +59,30 @@ const isButton = event.target.getAttribute && event.target.getAttribute('aria-expanded') === 'true' | ||
/** | ||
* updatePosition Exposed for _very_ niche situations, use sparingly | ||
* @param {HTMLElement} contentEl Reference to the core-toggle element | ||
*/ | ||
updatePosition () { | ||
if (this._skipPosition || !this.button) return // Avoid infinite loops for mutationObserver | ||
this._skipPosition = true | ||
this.style.position = 'fixed' // Set viewModel before reading dimensions | ||
const triggerRect = this.button.getBoundingClientRect() | ||
const contentRect = this.getBoundingClientRect() | ||
const hasSpaceRight = triggerRect.left + contentRect.width < window.innerWidth | ||
const hasSpaceUnder = triggerRect.bottom + contentRect.height < window.innerHeight | ||
const hasSpaceOver = triggerRect.top - contentRect.height > 0 | ||
// Always place under when no hasSpaceOver, as no OS can scroll further up than window.scrollY = 0 | ||
const placeUnder = hasSpaceUnder || !hasSpaceOver | ||
const scroll = placeUnder ? window.pageYOffset + triggerRect.bottom + contentRect.height + 30 : 0 | ||
this.style.left = `${Math.round(hasSpaceRight ? triggerRect.left : triggerRect.right - contentRect.width)}px` | ||
this.style.top = `${Math.round(placeUnder ? triggerRect.bottom : triggerRect.top - contentRect.height)}px` | ||
SCROLLER.style.cssText = `position:absolute;padding:1px;top:${Math.round(scroll)}px` | ||
setTimeout(() => (this._skipPosition = null)) // Timeout to flush event queue before we can resume acting on mutations | ||
} | ||
get button () { | ||
if (this._button && this._button.getAttribute('for') === this.id) return this._button // Speed up | ||
return (this._button = this.id && document.querySelector(`[for="${this.id}"]`)) || this.previousElementSibling | ||
if (this._button && (this._button.getAttribute('data-for') || this._button.getAttribute('for')) === this.id) return this._button // Speed up | ||
return (this._button = this.id && document.querySelector(`[for="${this.id}"],[data-for="${this.id}"]`)) || this.previousElementSibling | ||
} | ||
@@ -65,2 +95,6 @@ | ||
get autoposition () { return this.hasAttribute('autoposition') } | ||
set autoposition (val) { toggleAttribute(this, 'autoposition', val) } | ||
// Must set attribute for IE11 | ||
@@ -71,5 +105,5 @@ get hidden () { return this.hasAttribute('hidden') } | ||
// Sets this.button aria-label, so visible button text can be augmentet with intension of button | ||
// Set this.button aria-label, so that visible button text can be augmentet with intention of button | ||
// Example: Button text: "01.02.2019", aria-label: "01.02.2019, Choose date" | ||
// Does not updates aria-label if not allready set to something else than this.popup | ||
// Does not update aria-label if not already set to something else than this.popup | ||
get value () { return this.button.value || this.button.textContent } | ||
@@ -86,6 +120,30 @@ | ||
button.value = data.value || label | ||
target[data.innerHTML ? 'innerHTML' : 'textContent'] = data.innerHTML || label | ||
button.setAttribute('aria-label', `${button.textContent},${this.popup}`) | ||
target[data.innerHTML ? 'innerHTML' : 'textContent'] = data.innerHTML || label | ||
} | ||
} | ||
} | ||
/** | ||
* handleAutoposition Kept external from element as it is linked to multiple lifecycles and shouldn't be accessible as an internal function | ||
* @param {HTMLElement} self core-toggle instance | ||
* @param {Boolean} teardown if true, clean up and remove | ||
*/ | ||
function handleAutoposition (self, teardown) { | ||
if (teardown) { | ||
if (self._positionObserver) self._positionObserver.disconnect() | ||
if (SCROLLER.parentNode) SCROLLER.parentNode.removeChild(SCROLLER) | ||
self.style.position = self._positionObserver = null | ||
window.removeEventListener('scroll', self, true) // Use capture to also listen for elements with overflow | ||
window.removeEventListener('resize', self) | ||
} else if (self.autoposition) { | ||
// Attach MutationObserver if supported | ||
if (!self._positionObserver) self._positionObserver = window.MutationObserver && new window.MutationObserver(self.updatePosition.bind(self)) | ||
if (self._positionObserver) self._positionObserver.observe(self, { childList: true, subtree: true, attributes: true }) | ||
document.body.appendChild(SCROLLER) | ||
window.addEventListener('scroll', self, true) // Use capture to also listen for elements with overflow | ||
window.addEventListener('resize', self) | ||
self.updatePosition() // Initial trigger | ||
} | ||
} |
@@ -6,4 +6,5 @@ import CoreToggle from './core-toggle.js' | ||
export default customElementToReact(CoreToggle, { | ||
props: ['popup'], | ||
customEvents: ['toggle', 'toggle.select'], | ||
suffix: version | ||
}) |
@@ -0,9 +1,12 @@ | ||
/*! @nrk/core-toggle v3.0.9-0 - Copyright (c) 2017-2021 NRK */ | ||
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('react')) : | ||
typeof define === 'function' && define.amd ? define(['react'], factory) : | ||
(global = global || self, global.CoreToggle = factory(global.React)); | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.CoreToggle = factory(global.React)); | ||
}(this, (function (React) { 'use strict'; | ||
React = React && React.hasOwnProperty('default') ? React['default'] : React; | ||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
var React__default = /*#__PURE__*/_interopDefaultLegacy(React); | ||
function _classCallCheck(instance, Constructor) { | ||
@@ -62,3 +65,3 @@ if (!(instance instanceof Constructor)) { | ||
function isNativeReflectConstruct() { | ||
function _isNativeReflectConstruct() { | ||
if (typeof Reflect === "undefined" || !Reflect.construct) return false; | ||
@@ -69,3 +72,3 @@ if (Reflect.construct.sham) return false; | ||
try { | ||
Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); | ||
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); | ||
return true; | ||
@@ -78,3 +81,3 @@ } catch (e) { | ||
function _construct(Parent, args, Class) { | ||
if (isNativeReflectConstruct()) { | ||
if (_isNativeReflectConstruct()) { | ||
_construct = Reflect.construct; | ||
@@ -149,6 +152,26 @@ } else { | ||
function _createSuper(Derived) { | ||
var hasNativeReflectConstruct = _isNativeReflectConstruct(); | ||
return function _createSuperInternal() { | ||
var Super = _getPrototypeOf(Derived), | ||
result; | ||
if (hasNativeReflectConstruct) { | ||
var NewTarget = _getPrototypeOf(this).constructor; | ||
result = Reflect.construct(Super, arguments, NewTarget); | ||
} else { | ||
result = Super.apply(this, arguments); | ||
} | ||
return _possibleConstructorReturn(this, result); | ||
}; | ||
} | ||
var IS_BROWSER = typeof window !== 'undefined'; | ||
var IS_ANDROID = IS_BROWSER && /(android)/i.test(navigator.userAgent); // Bad, but needed | ||
var IS_IOS = IS_BROWSER && /iPad|iPhone|iPod/.test(String(navigator.platform)); // Mock HTMLElement for Node | ||
var IS_IOS = IS_BROWSER && /iPad|iPhone|iPod/.test(String(navigator.platform)); | ||
// Mock HTMLElement for Node | ||
@@ -171,3 +194,3 @@ if (!IS_BROWSER && !global.HTMLElement) { | ||
var closest = function () { | ||
var closest$1 = function () { | ||
var proto = typeof window === 'undefined' ? {} : window.Element.prototype; | ||
@@ -244,9 +267,13 @@ var match = proto.matches || proto.msMatchesSelector || proto.webkitMatchesSelector; | ||
var SCROLLER = IS_BROWSER && document.createElement('div'); | ||
var CoreToggle = /*#__PURE__*/function (_HTMLElement) { | ||
_inherits(CoreToggle, _HTMLElement); | ||
var _super = _createSuper(CoreToggle); | ||
function CoreToggle() { | ||
_classCallCheck(this, CoreToggle); | ||
return _possibleConstructorReturn(this, _getPrototypeOf(CoreToggle).apply(this, arguments)); | ||
return _super.apply(this, arguments); | ||
} | ||
@@ -277,2 +304,3 @@ | ||
document.removeEventListener('click', this); | ||
handleAutoposition(this, true); | ||
} | ||
@@ -290,2 +318,3 @@ }, { | ||
handleAutoposition(this, this.hidden); | ||
dispatchEvent(this, 'toggle'); | ||
@@ -298,6 +327,7 @@ } | ||
if (event.defaultPrevented) return; | ||
if (event.type === 'resize' || event.type === 'scroll') return this.updatePosition(); | ||
if (event.type === 'keydown' && event.keyCode === 27) { | ||
var isButton = event.target.getAttribute && event.target.getAttribute('aria-expanded') === 'true'; | ||
var isHiding = isButton ? event.target === this.button : closest(event.target, this.nodeName) === this; | ||
var isHiding = isButton ? event.target === this.button : closest$1(event.target, this.nodeName) === this; | ||
@@ -313,12 +343,42 @@ if (isHiding) { | ||
if (event.type === 'click') { | ||
var btn = closest(event.target, 'a,button'); | ||
if (btn && !btn.hasAttribute('aria-expanded') && closest(event.target, this.nodeName) === this) dispatchEvent(this, 'toggle.select', btn);else if (btn && btn.getAttribute('aria-controls') === this.id) this.hidden = !this.hidden;else if (this.popup && !this.contains(event.target)) this.hidden = true; // Click in content or outside | ||
var btn = closest$1(event.target, 'a,button'); | ||
if (btn && !btn.hasAttribute('aria-expanded') && closest$1(event.target, this.nodeName) === this) dispatchEvent(this, 'toggle.select', btn);else if (btn && btn.getAttribute('aria-controls') === this.id) this.hidden = !this.hidden;else if (this.popup && !this.contains(event.target)) this.hidden = true; // Click in content or outside | ||
} | ||
} | ||
/** | ||
* updatePosition Exposed for _very_ niche situations, use sparingly | ||
* @param {HTMLElement} contentEl Reference to the core-toggle element | ||
*/ | ||
}, { | ||
key: "updatePosition", | ||
value: function updatePosition() { | ||
var _this = this; | ||
if (this._skipPosition || !this.button) return; // Avoid infinite loops for mutationObserver | ||
this._skipPosition = true; | ||
this.style.position = 'fixed'; // Set viewModel before reading dimensions | ||
var triggerRect = this.button.getBoundingClientRect(); | ||
var contentRect = this.getBoundingClientRect(); | ||
var hasSpaceRight = triggerRect.left + contentRect.width < window.innerWidth; | ||
var hasSpaceUnder = triggerRect.bottom + contentRect.height < window.innerHeight; | ||
var hasSpaceOver = triggerRect.top - contentRect.height > 0; // Always place under when no hasSpaceOver, as no OS can scroll further up than window.scrollY = 0 | ||
var placeUnder = hasSpaceUnder || !hasSpaceOver; | ||
var scroll = placeUnder ? window.pageYOffset + triggerRect.bottom + contentRect.height + 30 : 0; | ||
this.style.left = "".concat(Math.round(hasSpaceRight ? triggerRect.left : triggerRect.right - contentRect.width), "px"); | ||
this.style.top = "".concat(Math.round(placeUnder ? triggerRect.bottom : triggerRect.top - contentRect.height), "px"); | ||
SCROLLER.style.cssText = "position:absolute;padding:1px;top:".concat(Math.round(scroll), "px"); | ||
setTimeout(function () { | ||
return _this._skipPosition = null; | ||
}); // Timeout to flush event queue before we can resume acting on mutations | ||
} | ||
}, { | ||
key: "button", | ||
get: function get() { | ||
if (this._button && this._button.getAttribute('for') === this.id) return this._button; // Speed up | ||
if (this._button && (this._button.getAttribute('data-for') || this._button.getAttribute('for')) === this.id) return this._button; // Speed up | ||
return (this._button = this.id && document.querySelector("[for=\"".concat(this.id, "\"]"))) || this.previousElementSibling; | ||
return (this._button = this.id && document.querySelector("[for=\"".concat(this.id, "\"],[data-for=\"").concat(this.id, "\"]"))) || this.previousElementSibling; | ||
} // aria-haspopup triggers forms mode in JAWS, therefore store as custom attr | ||
@@ -333,2 +393,10 @@ | ||
this[val === false ? 'removeAttribute' : 'setAttribute']('popup', val); | ||
} | ||
}, { | ||
key: "autoposition", | ||
get: function get() { | ||
return this.hasAttribute('autoposition'); | ||
}, | ||
set: function set(val) { | ||
toggleAttribute(this, 'autoposition', val); | ||
} // Must set attribute for IE11 | ||
@@ -343,5 +411,5 @@ | ||
toggleAttribute(this, 'hidden', val); | ||
} // Sets this.button aria-label, so visible button text can be augmentet with intension of button | ||
} // Set this.button aria-label, so that visible button text can be augmentet with intention of button | ||
// Example: Button text: "01.02.2019", aria-label: "01.02.2019, Choose date" | ||
// Does not updates aria-label if not allready set to something else than this.popup | ||
// Does not update aria-label if not already set to something else than this.popup | ||
@@ -353,4 +421,7 @@ }, { | ||
}, | ||
set: function set() { | ||
var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; | ||
set: function set(data) { | ||
if (data === void 0) { | ||
data = false; | ||
} | ||
if (!this.button || !this.popup.length) return; | ||
@@ -365,4 +436,4 @@ var button = this.button; | ||
button.value = data.value || label; | ||
target[data.innerHTML ? 'innerHTML' : 'textContent'] = data.innerHTML || label; | ||
button.setAttribute('aria-label', "".concat(button.textContent, ",").concat(this.popup)); | ||
target[data.innerHTML ? 'innerHTML' : 'textContent'] = data.innerHTML || label; | ||
} | ||
@@ -373,3 +444,3 @@ } | ||
get: function get() { | ||
return ['hidden']; | ||
return ['hidden', 'autoposition']; | ||
} | ||
@@ -381,4 +452,28 @@ }]); | ||
var version = "3.0.8"; | ||
function handleAutoposition(self, teardown) { | ||
if (teardown) { | ||
if (self._positionObserver) self._positionObserver.disconnect(); | ||
if (SCROLLER.parentNode) SCROLLER.parentNode.removeChild(SCROLLER); | ||
self.style.position = self._positionObserver = null; | ||
window.removeEventListener('scroll', self, true); // Use capture to also listen for elements with overflow | ||
window.removeEventListener('resize', self); | ||
} else if (self.autoposition) { | ||
// Attach MutationObserver if supported | ||
if (!self._positionObserver) self._positionObserver = window.MutationObserver && new window.MutationObserver(self.updatePosition.bind(self)); | ||
if (self._positionObserver) self._positionObserver.observe(self, { | ||
childList: true, | ||
subtree: true, | ||
attributes: true | ||
}); | ||
document.body.appendChild(SCROLLER); | ||
window.addEventListener('scroll', self, true); // Use capture to also listen for elements with overflow | ||
window.addEventListener('resize', self); | ||
self.updatePosition(); // Initial trigger | ||
} | ||
} | ||
var version = "3.0.9-0"; | ||
/** | ||
@@ -391,3 +486,3 @@ * closest | ||
var closest$1 = function () { | ||
var closest = function () { | ||
var proto = typeof window === 'undefined' ? {} : window.Element.prototype; | ||
@@ -438,100 +533,100 @@ var match = proto.matches || proto.msMatchesSelector || proto.webkitMatchesSelector; | ||
var tagName = (dashCase + "-" + (options.suffix || 'react')).replace(/\W+/g, '-').toLowerCase(); | ||
return (/*@__PURE__*/function (superclass) { | ||
function anonymous(props) { | ||
var this$1 = this; | ||
superclass.call(this, props); // Register ref prop for accessing custom element https://reactjs.org/docs/refs-and-the-dom.html#callback-refs | ||
return function (superclass) { | ||
function anonymous(props) { | ||
var this$1$1 = this; | ||
superclass.call(this, props); // Register ref prop for accessing custom element https://reactjs.org/docs/refs-and-the-dom.html#callback-refs | ||
this.ref = function (el) { | ||
if (typeof this$1.props.forwardRef === 'function') { | ||
this$1.props.forwardRef(el); | ||
} else if (this$1.props.forwardRef) { | ||
this$1.props.forwardRef.current = el; | ||
} | ||
this.ref = function (el) { | ||
if (typeof this$1$1.props.forwardRef === 'function') { | ||
this$1$1.props.forwardRef(el); | ||
} else if (this$1$1.props.forwardRef) { | ||
this$1$1.props.forwardRef.current = el; | ||
} | ||
return this$1.el = el; | ||
}; // Register event handler on component for each custom event | ||
return this$1$1.el = el; | ||
}; // Register event handler on component for each custom event | ||
Object.keys(eventMap).forEach(function (eventName) { | ||
var onEventName = eventMap[eventName]; | ||
Object.keys(eventMap).forEach(function (eventName) { | ||
var onEventName = eventMap[eventName]; | ||
this$1[eventName] = function (event) { | ||
if (this$1.props[onEventName] && closest$1(event.target, this$1.el.nodeName) === this$1.el) { | ||
this$1.props[onEventName](event); | ||
} | ||
}; | ||
}); | ||
} | ||
this$1$1[eventName] = function (event) { | ||
if (this$1$1.props[onEventName] && closest(event.target, this$1$1.el.nodeName) === this$1$1.el) { | ||
this$1$1.props[onEventName](event); | ||
} | ||
}; | ||
}); | ||
} | ||
if (superclass) anonymous.__proto__ = superclass; | ||
anonymous.prototype = Object.create(superclass && superclass.prototype); | ||
anonymous.prototype.constructor = anonymous; | ||
if (superclass) anonymous.__proto__ = superclass; | ||
anonymous.prototype = Object.create(superclass && superclass.prototype); | ||
anonymous.prototype.constructor = anonymous; | ||
anonymous.prototype.componentDidMount = function componentDidMount() { | ||
var this$1 = this; // Run connectedCallback() after React componentDidMount() to allow React hydration to run first | ||
anonymous.prototype.componentDidMount = function componentDidMount() { | ||
var this$1$1 = this; // Run connectedCallback() after React componentDidMount() to allow React hydration to run first | ||
if (!window.customElements.get(tagName)) { | ||
window.customElements.define(tagName, elementClass); | ||
} // Populate properties on custom element | ||
if (!window.customElements.get(tagName)) { | ||
window.customElements.define(tagName, elementClass); | ||
} // Populate properties on custom element | ||
customProps.forEach(function (propName) { | ||
if (propName in this$1.props) { | ||
this$1.el[propName] = this$1.props[propName]; | ||
} | ||
}); // Register events on custom element | ||
customProps.forEach(function (propName) { | ||
if (propName in this$1$1.props) { | ||
this$1$1.el[propName] = this$1$1.props[propName]; | ||
} | ||
}); // Register events on custom element | ||
customEvents.forEach(function (eventName) { | ||
this$1.el.addEventListener(eventName, this$1[eventName]); | ||
}); | ||
}; | ||
customEvents.forEach(function (eventName) { | ||
this$1$1.el.addEventListener(eventName, this$1$1[eventName]); | ||
}); | ||
}; | ||
anonymous.prototype.componentDidUpdate = function componentDidUpdate(prev) { | ||
var this$1 = this; // Sync prop changes to custom element | ||
anonymous.prototype.componentDidUpdate = function componentDidUpdate(prev) { | ||
var this$1$1 = this; // Sync prop changes to custom element | ||
customProps.forEach(function (propName) { | ||
if (prev[propName] !== this$1.props[propName]) { | ||
this$1.el[propName] = this$1.props[propName]; | ||
} | ||
}); | ||
}; | ||
customProps.forEach(function (propName) { | ||
if (prev[propName] !== this$1$1.props[propName]) { | ||
this$1$1.el[propName] = this$1$1.props[propName]; | ||
} | ||
}); | ||
}; | ||
anonymous.prototype.componentWillUnmount = function componentWillUnmount() { | ||
var this$1 = this; // Remove event handlers on custom element on unmount | ||
anonymous.prototype.componentWillUnmount = function componentWillUnmount() { | ||
var this$1$1 = this; // Remove event handlers on custom element on unmount | ||
customEvents.forEach(function (eventName) { | ||
this$1.el.removeEventListener(eventName, this$1[eventName]); | ||
}); | ||
}; | ||
customEvents.forEach(function (eventName) { | ||
this$1$1.el.removeEventListener(eventName, this$1$1[eventName]); | ||
}); | ||
}; | ||
anonymous.prototype.render = function render() { | ||
var this$1 = this; // Convert React props to CustomElement props https://github.com/facebook/react/issues/12810 | ||
anonymous.prototype.render = function render() { | ||
var this$1$1 = this; // Convert React props to CustomElement props https://github.com/facebook/react/issues/12810 | ||
return React.createElement(tagName, Object.keys(this.props).reduce(function (thisProps, propName) { | ||
if (skipProps.indexOf(propName) === -1) { | ||
// Do not render customEvents and custom props as attributes | ||
if (propName === 'className') { | ||
thisProps["class"] = this$1.props[propName]; | ||
} // Fixes className for custom elements | ||
else if (this$1.props[propName] === true) { | ||
thisProps[propName] = ''; | ||
} // Fixes boolean attributes | ||
else if (this$1.props[propName] !== false) { | ||
thisProps[propName] = this$1.props[propName]; | ||
} // Pass only truthy, non-function props | ||
return React__default['default'].createElement(tagName, Object.keys(this.props).reduce(function (thisProps, propName) { | ||
if (skipProps.indexOf(propName) === -1) { | ||
// Do not render customEvents and custom props as attributes | ||
if (propName === 'className') { | ||
thisProps["class"] = this$1$1.props[propName]; | ||
} // Fixes className for custom elements | ||
else if (this$1$1.props[propName] === true) { | ||
thisProps[propName] = ''; | ||
} // Fixes boolean attributes | ||
else if (this$1$1.props[propName] !== false) { | ||
thisProps[propName] = this$1$1.props[propName]; | ||
} // Pass only truthy, non-function props | ||
} | ||
} | ||
return thisProps; | ||
}, { | ||
ref: this.ref | ||
})); | ||
}; | ||
return thisProps; | ||
}, { | ||
ref: this.ref | ||
})); | ||
}; | ||
return anonymous; | ||
}(React.Component) | ||
); | ||
return anonymous; | ||
}(React__default['default'].Component); | ||
} | ||
var coreToggle = customElementToReact(CoreToggle, { | ||
props: ['popup'], | ||
customEvents: ['toggle', 'toggle.select'], | ||
@@ -538,0 +633,0 @@ suffix: version |
@@ -1,3 +0,3 @@ | ||
/*! @nrk/core-toggle v3.0.8 - Copyright (c) 2017-2020 NRK */ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).coreToggle=e()}(this,function(){"use strict";function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function r(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function u(t){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}function c(t,e){return(c=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function s(t,e,n){return(s=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(t){return!1}}()?Reflect.construct:function(t,e,n){var i=[null];i.push.apply(i,e);var o=new(Function.bind.apply(t,i));return n&&c(o,n.prototype),o}).apply(null,arguments)}function a(t){var i="function"==typeof Map?new Map:void 0;return(a=function(t){if(null===t||(e=t,-1===Function.toString.call(e).indexOf("[native code]")))return t;var e;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==i){if(i.has(t))return i.get(t);i.set(t,n)}function n(){return s(t,arguments,u(this).constructor)}return n.prototype=Object.create(t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),c(n,t)})(t)}function l(t,e){return!e||"object"!=typeof e&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}var t="undefined"!=typeof window,f=t&&/(android)/i.test(navigator.userAgent),h=t&&/iPad|iPhone|iPod/.test(String(navigator.platform));t||global.HTMLElement||(global.HTMLElement=function(){return function t(){o(this,t)}}());var e,n,p=(e="undefined"==typeof window?{}:window.Element.prototype,n=e.matches||e.msMatchesSelector||e.webkitMatchesSelector,e.closest?function(t,e){return t.closest(e)}:function(t,e){for(t.correspondingUseElement&&(t=t.correspondingUseElement);t;t=t.parentElement)if(n.call(t,e))return t;return null});function d(t,e,n){var i,o=2<arguments.length&&void 0!==n?n:{},r="prevent_recursive_dispatch_maximum_callstack".concat(e);if(t[r])return!0;t[r]=!0,"function"==typeof window.CustomEvent?i=new window.CustomEvent(e,{bubbles:!0,cancelable:!0,detail:o}):(i=document.createEvent("CustomEvent")).initCustomEvent(e,!0,!0,o);var u=t.dispatchEvent(i);return t[r]=null,u}function b(){return Date.now().toString(36)+Math.random().toString(36).slice(2,5)}return function(){function t(){return o(this,t),l(this,u(t).apply(this,arguments))}var e,n,i;return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&c(t,e)}(t,a(HTMLElement)),e=t,i=[{key:"observedAttributes",get:function(){return["hidden"]}}],(n=[{key:"connectedCallback",value:function(){h&&(document.documentElement.style.cursor="pointer"),f||this.setAttribute("aria-labelledby",this.button.id=this.button.id||b()),this.value=this.button.textContent,this.setAttribute("role","group"),this.button.setAttribute("aria-expanded",this._open=!this.hidden),this.button.setAttribute("aria-controls",this.id=this.id||b()),document.addEventListener("keydown",this,!0),document.addEventListener("click",this)}},{key:"disconnectedCallback",value:function(){this._button=null,document.removeEventListener("keydown",this,!0),document.removeEventListener("click",this)}},{key:"attributeChangedCallback",value:function(){if(this._open===this.hidden){this.button.setAttribute("aria-expanded",this._open=!this.hidden);try{this.querySelector("[autofocus]").focus()}catch(t){}d(this,"toggle")}}},{key:"handleEvent",value:function(t){if(!t.defaultPrevented){if("keydown"===t.type&&27===t.keyCode)if(t.target.getAttribute&&"true"===t.target.getAttribute("aria-expanded")?t.target===this.button:p(t.target,this.nodeName)===this)return this.hidden=!0,this.button.focus(),t.preventDefault();if("click"===t.type){var e=p(t.target,"a,button");e&&!e.hasAttribute("aria-expanded")&&p(t.target,this.nodeName)===this?d(this,"toggle.select",e):e&&e.getAttribute("aria-controls")===this.id?this.hidden=!this.hidden:this.popup&&!this.contains(t.target)&&(this.hidden=!0)}}}},{key:"button",get:function(){return this._button&&this._button.getAttribute("for")===this.id?this._button:(this._button=this.id&&document.querySelector('[for="'.concat(this.id,'"]')))||this.previousElementSibling}},{key:"popup",get:function(){return"true"===this.getAttribute("popup")||this.getAttribute("popup")||this.hasAttribute("popup")},set:function(t){this[!1===t?"removeAttribute":"setAttribute"]("popup",t)}},{key:"hidden",get:function(){return this.hasAttribute("hidden")},set:function(t){!function(t,e,n){var i=2<arguments.length&&void 0!==n?n:!this.hasAttribute(e);!i===t.hasAttribute(e)&&t[i?"setAttribute":"removeAttribute"](e,"")}(this,"hidden",t)}},{key:"value",get:function(){return this.button.value||this.button.textContent},set:function(t){var e=0<arguments.length&&void 0!==t&&t;if(this.button&&this.popup.length){var n=this.button,i=(n.getAttribute("aria-label")||",".concat(this.popup)).split(",")[1],o=e.textContent||e||"";if(i===this.popup){var r=n.querySelector("span")||n;n.value=e.value||o,n.setAttribute("aria-label","".concat(n.textContent,",").concat(this.popup)),r[e.innerHTML?"innerHTML":"textContent"]=e.innerHTML||o}}}}])&&r(e.prototype,n),i&&r(e,i),t}()}),window.customElements.define("core-toggle",coreToggle); | ||
/*! @nrk/core-toggle v3.0.9-0 - Copyright (c) 2017-2021 NRK */ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).coreToggle=e()}(this,(function(){"use strict";function t(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function e(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function n(t){return(n=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}function i(t,e){return(i=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function o(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(t){return!1}}function r(t,e,n){return(r=o()?Reflect.construct:function(t,e,n){var o=[null];o.push.apply(o,e);var r=new(Function.bind.apply(t,o));return n&&i(r,n.prototype),r}).apply(null,arguments)}function u(t){var e="function"==typeof Map?new Map:void 0;return(u=function(t){if(null===t||(o=t,-1===Function.toString.call(o).indexOf("[native code]")))return t;var o;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==e){if(e.has(t))return e.get(t);e.set(t,u)}function u(){return r(t,arguments,n(this).constructor)}return u.prototype=Object.create(t.prototype,{constructor:{value:u,enumerable:!1,writable:!0,configurable:!0}}),i(u,t)})(t)}function s(t,e){return!e||"object"!=typeof e&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}var a="undefined"!=typeof window,c=a&&/(android)/i.test(navigator.userAgent),l=a&&/iPad|iPhone|iPod/.test(String(navigator.platform));a||global.HTMLElement||(global.HTMLElement=function(){return function e(){t(this,e)}}());var d,h,p=(d="undefined"==typeof window?{}:window.Element.prototype,h=d.matches||d.msMatchesSelector||d.webkitMatchesSelector,d.closest?function(t,e){return t.closest(e)}:function(t,e){for(t.correspondingUseElement&&(t=t.correspondingUseElement);t;t=t.parentElement)if(h.call(t,e))return t;return null});function f(t,e){var n,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},o="prevent_recursive_dispatch_maximum_callstack".concat(e);if(t[o])return!0;t[o]=!0,"function"==typeof window.CustomEvent?n=new window.CustomEvent(e,{bubbles:!0,cancelable:!0,detail:i}):(n=document.createEvent("CustomEvent")).initCustomEvent(e,!0,!0,i);var r=t.dispatchEvent(n);return t[o]=null,r}function b(){return Date.now().toString(36)+Math.random().toString(36).slice(2,5)}function v(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:!this.hasAttribute(e);return!n===t.hasAttribute(e)&&t[n?"setAttribute":"removeAttribute"](e,""),n}var g=a&&document.createElement("div");function y(t,e){e?(t._positionObserver&&t._positionObserver.disconnect(),g.parentNode&&g.parentNode.removeChild(g),t.style.position=t._positionObserver=null,window.removeEventListener("scroll",t,!0),window.removeEventListener("resize",t)):t.autoposition&&(t._positionObserver||(t._positionObserver=window.MutationObserver&&new window.MutationObserver(t.updatePosition.bind(t))),t._positionObserver&&t._positionObserver.observe(t,{childList:!0,subtree:!0,attributes:!0}),document.body.appendChild(g),window.addEventListener("scroll",t,!0),window.addEventListener("resize",t),t.updatePosition())}return function(r){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&i(t,e)}(_,r);var u,a,d,h,m,w=(u=_,a=o(),function(){var t,e=n(u);if(a){var i=n(this).constructor;t=Reflect.construct(e,arguments,i)}else t=e.apply(this,arguments);return s(this,t)});function _(){return t(this,_),w.apply(this,arguments)}return d=_,m=[{key:"observedAttributes",get:function(){return["hidden","autoposition"]}}],(h=[{key:"connectedCallback",value:function(){l&&(document.documentElement.style.cursor="pointer"),c||this.setAttribute("aria-labelledby",this.button.id=this.button.id||b()),this.value=this.button.textContent,this.setAttribute("role","group"),this.button.setAttribute("aria-expanded",this._open=!this.hidden),this.button.setAttribute("aria-controls",this.id=this.id||b()),document.addEventListener("keydown",this,!0),document.addEventListener("click",this)}},{key:"disconnectedCallback",value:function(){this._button=null,document.removeEventListener("keydown",this,!0),document.removeEventListener("click",this),y(this,!0)}},{key:"attributeChangedCallback",value:function(){if(this._open===this.hidden){this.button.setAttribute("aria-expanded",this._open=!this.hidden);try{this.querySelector("[autofocus]").focus()}catch(t){}y(this,this.hidden),f(this,"toggle")}}},{key:"handleEvent",value:function(t){if(!t.defaultPrevented){if("resize"===t.type||"scroll"===t.type)return this.updatePosition();if("keydown"===t.type&&27===t.keyCode&&(t.target.getAttribute&&"true"===t.target.getAttribute("aria-expanded")?t.target===this.button:p(t.target,this.nodeName)===this))return this.hidden=!0,this.button.focus(),t.preventDefault();if("click"===t.type){var e=p(t.target,"a,button");e&&!e.hasAttribute("aria-expanded")&&p(t.target,this.nodeName)===this?f(this,"toggle.select",e):e&&e.getAttribute("aria-controls")===this.id?this.hidden=!this.hidden:this.popup&&!this.contains(t.target)&&(this.hidden=!0)}}}},{key:"updatePosition",value:function(){var t=this;if(!this._skipPosition&&this.button){this._skipPosition=!0,this.style.position="fixed";var e=this.button.getBoundingClientRect(),n=this.getBoundingClientRect(),i=e.left+n.width<window.innerWidth,o=e.bottom+n.height<window.innerHeight,r=e.top-n.height>0,u=o||!r,s=u?window.pageYOffset+e.bottom+n.height+30:0;this.style.left="".concat(Math.round(i?e.left:e.right-n.width),"px"),this.style.top="".concat(Math.round(u?e.bottom:e.top-n.height),"px"),g.style.cssText="position:absolute;padding:1px;top:".concat(Math.round(s),"px"),setTimeout((function(){return t._skipPosition=null}))}}},{key:"button",get:function(){return this._button&&(this._button.getAttribute("data-for")||this._button.getAttribute("for"))===this.id?this._button:(this._button=this.id&&document.querySelector('[for="'.concat(this.id,'"],[data-for="').concat(this.id,'"]')))||this.previousElementSibling}},{key:"popup",get:function(){return"true"===this.getAttribute("popup")||this.getAttribute("popup")||this.hasAttribute("popup")},set:function(t){this[!1===t?"removeAttribute":"setAttribute"]("popup",t)}},{key:"autoposition",get:function(){return this.hasAttribute("autoposition")},set:function(t){v(this,"autoposition",t)}},{key:"hidden",get:function(){return this.hasAttribute("hidden")},set:function(t){v(this,"hidden",t)}},{key:"value",get:function(){return this.button.value||this.button.textContent},set:function(t){if(void 0===t&&(t=!1),this.button&&this.popup.length){var e=this.button,n=(e.getAttribute("aria-label")||",".concat(this.popup)).split(",")[1],i=t.textContent||t||"";if(n===this.popup){var o=e.querySelector("span")||e;e.value=t.value||i,o[t.innerHTML?"innerHTML":"textContent"]=t.innerHTML||i,e.setAttribute("aria-label","".concat(e.textContent,",").concat(this.popup))}}}}])&&e(d.prototype,h),m&&e(d,m),_}(u(HTMLElement))})),window.customElements.define("core-toggle",coreToggle); | ||
//# sourceMappingURL=core-toggle.min.js.map |
@@ -0,8 +1,12 @@ | ||
/*! @nrk/core-toggle v3.0.9-0 - Copyright (c) 2017-2021 NRK */ | ||
'use strict'; | ||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var fs = _interopDefault(require('fs')); | ||
var path = _interopDefault(require('path')); | ||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs); | ||
var path__default = /*#__PURE__*/_interopDefaultLegacy(path); | ||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { | ||
@@ -55,4 +59,4 @@ try { | ||
var coreToggle = fs.readFileSync(path.resolve(__dirname, 'core-toggle.min.js'), 'utf-8'); | ||
var customElements = fs.readFileSync(require.resolve('@webcomponents/custom-elements'), 'utf-8'); | ||
var coreToggle = fs__default['default'].readFileSync(path__default['default'].resolve(__dirname, 'core-toggle.min.js'), 'utf-8'); | ||
var customElements = fs__default['default'].readFileSync(require.resolve('@webcomponents/custom-elements'), 'utf-8'); | ||
describe('core-toggle', function () { | ||
@@ -112,10 +116,14 @@ beforeEach( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() { | ||
_context2.next = 13; | ||
return expect(prop('core-toggle', 'autoposition')).toMatch(/false/i); | ||
case 13: | ||
_context2.next = 15; | ||
return attr('button', 'id'); | ||
case 13: | ||
case 15: | ||
buttonId = _context2.sent; | ||
_context2.next = 16; | ||
_context2.next = 18; | ||
return expect(attr('core-toggle', 'aria-labelledby')).toEqual(buttonId); | ||
case 16: | ||
case 18: | ||
case "end": | ||
@@ -307,3 +315,3 @@ return _context2.stop(); | ||
}))); | ||
it('respects "for" attribute', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee7() { | ||
it('respects deprecated "for" attribute', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee7() { | ||
var toggleId; | ||
@@ -326,9 +334,17 @@ return regeneratorRuntime.wrap(function _callee7$(_context7) { | ||
_context7.next = 7; | ||
return expect(attr('button', 'for')).toEqual(toggleId); | ||
return $('button').click(); | ||
case 7: | ||
_context7.next = 9; | ||
return expect(attr('button', 'for')).toEqual(toggleId); | ||
case 9: | ||
_context7.next = 11; | ||
return expect(attr('button', 'aria-controls')).toEqual(toggleId); | ||
case 9: | ||
case 11: | ||
_context7.next = 13; | ||
return expect(prop('core-toggle', 'hidden')).toMatch(/false/i); | ||
case 13: | ||
case "end": | ||
@@ -340,4 +356,4 @@ return _context7.stop(); | ||
}))); | ||
it('respects exisiting aria-label with popup and value', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee8() { | ||
var toggleValue; | ||
it('respects "data-for" attribute', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee8() { | ||
var toggleId; | ||
return regeneratorRuntime.wrap(function _callee8$(_context8) { | ||
@@ -349,3 +365,3 @@ while (1) { | ||
return browser.executeScript(function () { | ||
document.body.innerHTML = "\n <button aria-label=\"Label\">Toggle</button>\n <core-toggle popup=\"Another label\" hidden></core-toggle>\n "; | ||
document.body.innerHTML = "\n <div><button data-for=\"content\">Toggle</button></div>\n <core-toggle id=\"content\" hidden></core-toggle>\n "; | ||
}); | ||
@@ -355,20 +371,22 @@ | ||
_context8.next = 4; | ||
return browser.executeScript(function () { | ||
return document.querySelector('core-toggle').value = 'Button text'; | ||
}); | ||
return attr('core-toggle', 'id'); | ||
case 4: | ||
_context8.next = 6; | ||
return prop('core-toggle', 'value'); | ||
toggleId = _context8.sent; | ||
_context8.next = 7; | ||
return $('button').click(); | ||
case 6: | ||
toggleValue = _context8.sent; | ||
case 7: | ||
_context8.next = 9; | ||
return expect(prop('button', 'textContent')).toEqual(toggleValue); | ||
return expect(attr('button', 'data-for')).toEqual(toggleId); | ||
case 9: | ||
_context8.next = 11; | ||
return expect(attr('button', 'aria-label')).toEqual('Label'); | ||
return expect(attr('button', 'aria-controls')).toEqual(toggleId); | ||
case 11: | ||
_context8.next = 13; | ||
return expect(prop('core-toggle', 'hidden')).toMatch(/false/i); | ||
case 13: | ||
case "end": | ||
@@ -380,3 +398,3 @@ return _context8.stop(); | ||
}))); | ||
it('sets aria-label with popup attr and value', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee9() { | ||
it('respects exisiting aria-label with popup and value', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee9() { | ||
var toggleValue; | ||
@@ -389,3 +407,3 @@ return regeneratorRuntime.wrap(function _callee9$(_context9) { | ||
return browser.executeScript(function () { | ||
document.body.innerHTML = "\n <button>Toggle</button>\n <core-toggle popup=\"Some label\" hidden></core-toggle>\n "; | ||
document.body.innerHTML = "\n <button aria-label=\"Label\">Toggle</button>\n <core-toggle popup=\"Another label\" hidden></core-toggle>\n "; | ||
}); | ||
@@ -410,3 +428,3 @@ | ||
_context9.next = 11; | ||
return expect(attr('button', 'aria-label')).toEqual('Button text,Some label'); | ||
return expect(attr('button', 'aria-label')).toEqual('Label'); | ||
@@ -420,3 +438,3 @@ case 11: | ||
}))); | ||
it('sets aria-label with popup prop and value', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee10() { | ||
it('sets aria-label with popup attr and value', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee10() { | ||
var toggleValue; | ||
@@ -429,3 +447,3 @@ return regeneratorRuntime.wrap(function _callee10$(_context10) { | ||
return browser.executeScript(function () { | ||
document.body.innerHTML = "\n <button>Toggle</button>\n <core-toggle hidden></core-toggle>\n "; | ||
document.body.innerHTML = "\n <button>Toggle</button>\n <core-toggle popup=\"Some label\" hidden></core-toggle>\n "; | ||
}); | ||
@@ -436,3 +454,3 @@ | ||
return browser.executeScript(function () { | ||
return document.querySelector('core-toggle').popup = 'Some label'; | ||
return document.querySelector('core-toggle').value = 'Button text'; | ||
}); | ||
@@ -442,3 +460,40 @@ | ||
_context10.next = 6; | ||
return prop('core-toggle', 'value'); | ||
case 6: | ||
toggleValue = _context10.sent; | ||
_context10.next = 9; | ||
return expect(prop('button', 'textContent')).toEqual(toggleValue); | ||
case 9: | ||
_context10.next = 11; | ||
return expect(attr('button', 'aria-label')).toEqual('Button text,Some label'); | ||
case 11: | ||
case "end": | ||
return _context10.stop(); | ||
} | ||
} | ||
}, _callee10); | ||
}))); | ||
it('sets aria-label with popup prop and value', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee11() { | ||
var toggleValue; | ||
return regeneratorRuntime.wrap(function _callee11$(_context11) { | ||
while (1) { | ||
switch (_context11.prev = _context11.next) { | ||
case 0: | ||
_context11.next = 2; | ||
return browser.executeScript(function () { | ||
document.body.innerHTML = "\n <button>Toggle</button>\n <core-toggle hidden></core-toggle>\n "; | ||
}); | ||
case 2: | ||
_context11.next = 4; | ||
return browser.executeScript(function () { | ||
return document.querySelector('core-toggle').popup = 'Some label'; | ||
}); | ||
case 4: | ||
_context11.next = 6; | ||
return browser.executeScript(function () { | ||
return document.querySelector('core-toggle').value = 'Button text'; | ||
@@ -448,12 +503,12 @@ }); | ||
case 6: | ||
_context10.next = 8; | ||
_context11.next = 8; | ||
return prop('core-toggle', 'value'); | ||
case 8: | ||
toggleValue = _context10.sent; | ||
_context10.next = 11; | ||
toggleValue = _context11.sent; | ||
_context11.next = 11; | ||
return expect(prop('button', 'textContent')).toEqual(toggleValue); | ||
case 11: | ||
_context10.next = 13; | ||
_context11.next = 13; | ||
return expect(attr('button', 'aria-label')).toEqual('Button text,Some label'); | ||
@@ -463,14 +518,14 @@ | ||
case "end": | ||
return _context10.stop(); | ||
return _context11.stop(); | ||
} | ||
} | ||
}, _callee10); | ||
}, _callee11); | ||
}))); | ||
it('triggers toggle event', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee11() { | ||
it('triggers toggle event', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee12() { | ||
var triggered; | ||
return regeneratorRuntime.wrap(function _callee11$(_context11) { | ||
return regeneratorRuntime.wrap(function _callee12$(_context12) { | ||
while (1) { | ||
switch (_context11.prev = _context11.next) { | ||
switch (_context12.prev = _context12.next) { | ||
case 0: | ||
_context11.next = 2; | ||
_context12.next = 2; | ||
return browser.executeScript(function () { | ||
@@ -485,3 +540,3 @@ document.body.innerHTML = "\n <button>Toggle</button>\n <core-toggle hidden></core-toggle>\n "; | ||
case 2: | ||
_context11.next = 4; | ||
_context12.next = 4; | ||
return browser.executeScript(function () { | ||
@@ -492,4 +547,4 @@ return window.triggered; | ||
case 4: | ||
triggered = _context11.sent; | ||
_context11.next = 7; | ||
triggered = _context12.sent; | ||
_context12.next = 7; | ||
return expect(triggered).toEqual(true); | ||
@@ -499,20 +554,20 @@ | ||
case "end": | ||
return _context11.stop(); | ||
return _context12.stop(); | ||
} | ||
} | ||
}, _callee11); | ||
}, _callee12); | ||
}))); | ||
it('triggers select event', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee12() { | ||
it('triggers select event', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee13() { | ||
var itemId; | ||
return regeneratorRuntime.wrap(function _callee12$(_context12) { | ||
return regeneratorRuntime.wrap(function _callee13$(_context13) { | ||
while (1) { | ||
switch (_context12.prev = _context12.next) { | ||
switch (_context13.prev = _context13.next) { | ||
case 0: | ||
_context12.next = 2; | ||
_context13.next = 2; | ||
return browser.executeScript(function () { | ||
document.body.innerHTML = "\n <button>Toggle</button>\n <core-toggle hidden>\n <button id=\"my-item\">Select me</button>\n </core-toggle>\n "; | ||
document.body.innerHTML = "\n <button id=\"toggleBtn\">Toggle</button>\n <core-toggle hidden>\n <button id=\"my-item\">Select me</button>\n </core-toggle>\n "; | ||
}); | ||
case 2: | ||
_context12.next = 4; | ||
_context13.next = 4; | ||
return browser.executeScript(function () { | ||
@@ -522,9 +577,14 @@ document.addEventListener('toggle.select', function (event) { | ||
}); | ||
var toggle = document.querySelector('core-toggle'); | ||
toggle.hidden = false; | ||
toggle.children[0].click(); | ||
}); | ||
case 4: | ||
_context12.next = 6; | ||
_context13.next = 6; | ||
return $('#toggleBtn').click(); | ||
case 6: | ||
_context13.next = 8; | ||
return $('#my-item').click(); | ||
case 8: | ||
_context13.next = 10; | ||
return browser.wait(function () { | ||
@@ -536,14 +596,79 @@ return browser.executeScript(function () { | ||
case 6: | ||
itemId = _context12.sent; | ||
_context12.next = 9; | ||
case 10: | ||
itemId = _context13.sent; | ||
_context13.next = 13; | ||
return expect(itemId).toEqual('my-item'); | ||
case 9: | ||
case 13: | ||
case "end": | ||
return _context12.stop(); | ||
return _context13.stop(); | ||
} | ||
} | ||
}, _callee12); | ||
}, _callee13); | ||
}))); | ||
it('supports attribute autoposition', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee14() { | ||
return regeneratorRuntime.wrap(function _callee14$(_context14) { | ||
while (1) { | ||
switch (_context14.prev = _context14.next) { | ||
case 0: | ||
_context14.next = 2; | ||
return browser.executeScript(function () { | ||
document.body.innerHTML = "\n <button>Toggle</button>\n <core-toggle autoposition hidden></core-toggle>\n "; | ||
}); | ||
case 2: | ||
_context14.next = 4; | ||
return expect(prop('core-toggle', 'autoposition')).toMatch(/true/i); | ||
case 4: | ||
_context14.next = 6; | ||
return $('button').click(); | ||
case 6: | ||
_context14.next = 8; | ||
return expect($('core-toggle').getCssValue('position')).toEqual('fixed'); | ||
case 8: | ||
case "end": | ||
return _context14.stop(); | ||
} | ||
} | ||
}, _callee14); | ||
}))); | ||
it('updates aria-label on select when event value is set to event detail', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee15() { | ||
return regeneratorRuntime.wrap(function _callee15$(_context15) { | ||
while (1) { | ||
switch (_context15.prev = _context15.next) { | ||
case 0: | ||
_context15.next = 2; | ||
return browser.executeScript(function () { | ||
document.body.innerHTML = "\n <button id=\"toggleBtn\">Toggle</button>\n <core-toggle hidden popup=\"Choose wisely\">\n <button id=\"my-item\">Select me</button>\n </core-toggle>\n "; | ||
document.addEventListener('toggle.select', function (event) { | ||
return event.target.value = event.detail; | ||
}); | ||
}); | ||
case 2: | ||
_context15.next = 4; | ||
return browser.wait(ExpectedConditions.presenceOf($('#toggleBtn[aria-label="Toggle,Choose wisely"]'))); | ||
case 4: | ||
_context15.next = 6; | ||
return $('#toggleBtn').click(); | ||
case 6: | ||
_context15.next = 8; | ||
return $('#my-item').click(); | ||
case 8: | ||
_context15.next = 10; | ||
return expect(attr('#toggleBtn', 'aria-label')).toEqual('Select me,Choose wisely'); | ||
case 10: | ||
case "end": | ||
return _context15.stop(); | ||
} | ||
} | ||
}, _callee15); | ||
}))); | ||
}); |
@@ -26,2 +26,3 @@ import fs from 'fs' | ||
await expect(prop('core-toggle', 'hidden')).toMatch(/true/i) | ||
await expect(prop('core-toggle', 'autoposition')).toMatch(/false/i) | ||
const buttonId = await attr('button', 'id') | ||
@@ -105,3 +106,3 @@ await expect(attr('core-toggle', 'aria-labelledby')).toEqual(buttonId) | ||
it('respects "for" attribute', async () => { | ||
it('respects deprecated "for" attribute', async () => { | ||
await browser.executeScript(() => { | ||
@@ -114,6 +115,22 @@ document.body.innerHTML = ` | ||
const toggleId = await attr('core-toggle', 'id') | ||
await $('button').click() | ||
await expect(attr('button', 'for')).toEqual(toggleId) | ||
await expect(attr('button', 'aria-controls')).toEqual(toggleId) | ||
await expect(prop('core-toggle', 'hidden')).toMatch(/false/i) | ||
}) | ||
it('respects "data-for" attribute', async () => { | ||
await browser.executeScript(() => { | ||
document.body.innerHTML = ` | ||
<div><button data-for="content">Toggle</button></div> | ||
<core-toggle id="content" hidden></core-toggle> | ||
` | ||
}) | ||
const toggleId = await attr('core-toggle', 'id') | ||
await $('button').click() | ||
await expect(attr('button', 'data-for')).toEqual(toggleId) | ||
await expect(attr('button', 'aria-controls')).toEqual(toggleId) | ||
await expect(prop('core-toggle', 'hidden')).toMatch(/false/i) | ||
}) | ||
it('respects exisiting aria-label with popup and value', async () => { | ||
@@ -175,3 +192,3 @@ await browser.executeScript(() => { | ||
document.body.innerHTML = ` | ||
<button>Toggle</button> | ||
<button id="toggleBtn">Toggle</button> | ||
<core-toggle hidden> | ||
@@ -184,9 +201,38 @@ <button id="my-item">Select me</button> | ||
document.addEventListener('toggle.select', (event) => (window.itemId = event.detail.id)) | ||
const toggle = document.querySelector('core-toggle') | ||
toggle.hidden = false | ||
toggle.children[0].click() | ||
}) | ||
await $('#toggleBtn').click() | ||
await $('#my-item').click() | ||
const itemId = await browser.wait(() => browser.executeScript(() => window.itemId)) | ||
await expect(itemId).toEqual('my-item') | ||
}) | ||
it('supports attribute autoposition', async () => { | ||
await browser.executeScript(() => { | ||
document.body.innerHTML = ` | ||
<button>Toggle</button> | ||
<core-toggle autoposition hidden></core-toggle> | ||
` | ||
}) | ||
await expect(prop('core-toggle', 'autoposition')).toMatch(/true/i) | ||
await $('button').click() | ||
await expect($('core-toggle').getCssValue('position')).toEqual('fixed') | ||
}) | ||
it('updates aria-label on select when event value is set to event detail', async () => { | ||
await browser.executeScript(() => { | ||
document.body.innerHTML = ` | ||
<button id="toggleBtn">Toggle</button> | ||
<core-toggle hidden popup="Choose wisely"> | ||
<button id="my-item">Select me</button> | ||
</core-toggle> | ||
` | ||
document.addEventListener('toggle.select', (event) => (event.target.value = event.detail)) | ||
}) | ||
await browser.wait(ExpectedConditions.presenceOf($('#toggleBtn[aria-label="Toggle,Choose wisely"]'))) | ||
await $('#toggleBtn').click() | ||
await $('#my-item').click() | ||
// aria-label always ends with popup-attribute | ||
await expect(attr('#toggleBtn', 'aria-label')).toEqual('Select me,Choose wisely') | ||
}) | ||
}) |
287
jsx.js
@@ -0,7 +1,10 @@ | ||
/*! @nrk/core-toggle v3.0.9-0 - Copyright (c) 2017-2021 NRK */ | ||
'use strict'; | ||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } | ||
var React = require('react'); | ||
var React = _interopDefault(require('react')); | ||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
var React__default = /*#__PURE__*/_interopDefaultLegacy(React); | ||
function _classCallCheck(instance, Constructor) { | ||
@@ -60,3 +63,3 @@ if (!(instance instanceof Constructor)) { | ||
function isNativeReflectConstruct() { | ||
function _isNativeReflectConstruct() { | ||
if (typeof Reflect === "undefined" || !Reflect.construct) return false; | ||
@@ -67,3 +70,3 @@ if (Reflect.construct.sham) return false; | ||
try { | ||
Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); | ||
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); | ||
return true; | ||
@@ -76,3 +79,3 @@ } catch (e) { | ||
function _construct(Parent, args, Class) { | ||
if (isNativeReflectConstruct()) { | ||
if (_isNativeReflectConstruct()) { | ||
_construct = Reflect.construct; | ||
@@ -147,6 +150,26 @@ } else { | ||
function _createSuper(Derived) { | ||
var hasNativeReflectConstruct = _isNativeReflectConstruct(); | ||
return function _createSuperInternal() { | ||
var Super = _getPrototypeOf(Derived), | ||
result; | ||
if (hasNativeReflectConstruct) { | ||
var NewTarget = _getPrototypeOf(this).constructor; | ||
result = Reflect.construct(Super, arguments, NewTarget); | ||
} else { | ||
result = Super.apply(this, arguments); | ||
} | ||
return _possibleConstructorReturn(this, result); | ||
}; | ||
} | ||
var IS_BROWSER = typeof window !== 'undefined'; | ||
var IS_ANDROID = IS_BROWSER && /(android)/i.test(navigator.userAgent); // Bad, but needed | ||
var IS_IOS = IS_BROWSER && /iPad|iPhone|iPod/.test(String(navigator.platform)); // Mock HTMLElement for Node | ||
var IS_IOS = IS_BROWSER && /iPad|iPhone|iPod/.test(String(navigator.platform)); | ||
// Mock HTMLElement for Node | ||
@@ -169,3 +192,3 @@ if (!IS_BROWSER && !global.HTMLElement) { | ||
var closest = function () { | ||
var closest$1 = function () { | ||
var proto = typeof window === 'undefined' ? {} : window.Element.prototype; | ||
@@ -242,9 +265,13 @@ var match = proto.matches || proto.msMatchesSelector || proto.webkitMatchesSelector; | ||
var SCROLLER = IS_BROWSER && document.createElement('div'); | ||
var CoreToggle = /*#__PURE__*/function (_HTMLElement) { | ||
_inherits(CoreToggle, _HTMLElement); | ||
var _super = _createSuper(CoreToggle); | ||
function CoreToggle() { | ||
_classCallCheck(this, CoreToggle); | ||
return _possibleConstructorReturn(this, _getPrototypeOf(CoreToggle).apply(this, arguments)); | ||
return _super.apply(this, arguments); | ||
} | ||
@@ -275,2 +302,3 @@ | ||
document.removeEventListener('click', this); | ||
handleAutoposition(this, true); | ||
} | ||
@@ -288,2 +316,3 @@ }, { | ||
handleAutoposition(this, this.hidden); | ||
dispatchEvent(this, 'toggle'); | ||
@@ -296,6 +325,7 @@ } | ||
if (event.defaultPrevented) return; | ||
if (event.type === 'resize' || event.type === 'scroll') return this.updatePosition(); | ||
if (event.type === 'keydown' && event.keyCode === 27) { | ||
var isButton = event.target.getAttribute && event.target.getAttribute('aria-expanded') === 'true'; | ||
var isHiding = isButton ? event.target === this.button : closest(event.target, this.nodeName) === this; | ||
var isHiding = isButton ? event.target === this.button : closest$1(event.target, this.nodeName) === this; | ||
@@ -311,12 +341,42 @@ if (isHiding) { | ||
if (event.type === 'click') { | ||
var btn = closest(event.target, 'a,button'); | ||
if (btn && !btn.hasAttribute('aria-expanded') && closest(event.target, this.nodeName) === this) dispatchEvent(this, 'toggle.select', btn);else if (btn && btn.getAttribute('aria-controls') === this.id) this.hidden = !this.hidden;else if (this.popup && !this.contains(event.target)) this.hidden = true; // Click in content or outside | ||
var btn = closest$1(event.target, 'a,button'); | ||
if (btn && !btn.hasAttribute('aria-expanded') && closest$1(event.target, this.nodeName) === this) dispatchEvent(this, 'toggle.select', btn);else if (btn && btn.getAttribute('aria-controls') === this.id) this.hidden = !this.hidden;else if (this.popup && !this.contains(event.target)) this.hidden = true; // Click in content or outside | ||
} | ||
} | ||
/** | ||
* updatePosition Exposed for _very_ niche situations, use sparingly | ||
* @param {HTMLElement} contentEl Reference to the core-toggle element | ||
*/ | ||
}, { | ||
key: "updatePosition", | ||
value: function updatePosition() { | ||
var _this = this; | ||
if (this._skipPosition || !this.button) return; // Avoid infinite loops for mutationObserver | ||
this._skipPosition = true; | ||
this.style.position = 'fixed'; // Set viewModel before reading dimensions | ||
var triggerRect = this.button.getBoundingClientRect(); | ||
var contentRect = this.getBoundingClientRect(); | ||
var hasSpaceRight = triggerRect.left + contentRect.width < window.innerWidth; | ||
var hasSpaceUnder = triggerRect.bottom + contentRect.height < window.innerHeight; | ||
var hasSpaceOver = triggerRect.top - contentRect.height > 0; // Always place under when no hasSpaceOver, as no OS can scroll further up than window.scrollY = 0 | ||
var placeUnder = hasSpaceUnder || !hasSpaceOver; | ||
var scroll = placeUnder ? window.pageYOffset + triggerRect.bottom + contentRect.height + 30 : 0; | ||
this.style.left = "".concat(Math.round(hasSpaceRight ? triggerRect.left : triggerRect.right - contentRect.width), "px"); | ||
this.style.top = "".concat(Math.round(placeUnder ? triggerRect.bottom : triggerRect.top - contentRect.height), "px"); | ||
SCROLLER.style.cssText = "position:absolute;padding:1px;top:".concat(Math.round(scroll), "px"); | ||
setTimeout(function () { | ||
return _this._skipPosition = null; | ||
}); // Timeout to flush event queue before we can resume acting on mutations | ||
} | ||
}, { | ||
key: "button", | ||
get: function get() { | ||
if (this._button && this._button.getAttribute('for') === this.id) return this._button; // Speed up | ||
if (this._button && (this._button.getAttribute('data-for') || this._button.getAttribute('for')) === this.id) return this._button; // Speed up | ||
return (this._button = this.id && document.querySelector("[for=\"".concat(this.id, "\"]"))) || this.previousElementSibling; | ||
return (this._button = this.id && document.querySelector("[for=\"".concat(this.id, "\"],[data-for=\"").concat(this.id, "\"]"))) || this.previousElementSibling; | ||
} // aria-haspopup triggers forms mode in JAWS, therefore store as custom attr | ||
@@ -331,2 +391,10 @@ | ||
this[val === false ? 'removeAttribute' : 'setAttribute']('popup', val); | ||
} | ||
}, { | ||
key: "autoposition", | ||
get: function get() { | ||
return this.hasAttribute('autoposition'); | ||
}, | ||
set: function set(val) { | ||
toggleAttribute(this, 'autoposition', val); | ||
} // Must set attribute for IE11 | ||
@@ -341,5 +409,5 @@ | ||
toggleAttribute(this, 'hidden', val); | ||
} // Sets this.button aria-label, so visible button text can be augmentet with intension of button | ||
} // Set this.button aria-label, so that visible button text can be augmentet with intention of button | ||
// Example: Button text: "01.02.2019", aria-label: "01.02.2019, Choose date" | ||
// Does not updates aria-label if not allready set to something else than this.popup | ||
// Does not update aria-label if not already set to something else than this.popup | ||
@@ -351,4 +419,7 @@ }, { | ||
}, | ||
set: function set() { | ||
var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; | ||
set: function set(data) { | ||
if (data === void 0) { | ||
data = false; | ||
} | ||
if (!this.button || !this.popup.length) return; | ||
@@ -363,4 +434,4 @@ var button = this.button; | ||
button.value = data.value || label; | ||
target[data.innerHTML ? 'innerHTML' : 'textContent'] = data.innerHTML || label; | ||
button.setAttribute('aria-label', "".concat(button.textContent, ",").concat(this.popup)); | ||
target[data.innerHTML ? 'innerHTML' : 'textContent'] = data.innerHTML || label; | ||
} | ||
@@ -371,3 +442,3 @@ } | ||
get: function get() { | ||
return ['hidden']; | ||
return ['hidden', 'autoposition']; | ||
} | ||
@@ -379,4 +450,28 @@ }]); | ||
var version = "3.0.8"; | ||
function handleAutoposition(self, teardown) { | ||
if (teardown) { | ||
if (self._positionObserver) self._positionObserver.disconnect(); | ||
if (SCROLLER.parentNode) SCROLLER.parentNode.removeChild(SCROLLER); | ||
self.style.position = self._positionObserver = null; | ||
window.removeEventListener('scroll', self, true); // Use capture to also listen for elements with overflow | ||
window.removeEventListener('resize', self); | ||
} else if (self.autoposition) { | ||
// Attach MutationObserver if supported | ||
if (!self._positionObserver) self._positionObserver = window.MutationObserver && new window.MutationObserver(self.updatePosition.bind(self)); | ||
if (self._positionObserver) self._positionObserver.observe(self, { | ||
childList: true, | ||
subtree: true, | ||
attributes: true | ||
}); | ||
document.body.appendChild(SCROLLER); | ||
window.addEventListener('scroll', self, true); // Use capture to also listen for elements with overflow | ||
window.addEventListener('resize', self); | ||
self.updatePosition(); // Initial trigger | ||
} | ||
} | ||
var version = "3.0.9-0"; | ||
/** | ||
@@ -389,3 +484,3 @@ * closest | ||
var closest$1 = function () { | ||
var closest = function () { | ||
var proto = typeof window === 'undefined' ? {} : window.Element.prototype; | ||
@@ -436,100 +531,100 @@ var match = proto.matches || proto.msMatchesSelector || proto.webkitMatchesSelector; | ||
var tagName = (dashCase + "-" + (options.suffix || 'react')).replace(/\W+/g, '-').toLowerCase(); | ||
return (/*@__PURE__*/function (superclass) { | ||
function anonymous(props) { | ||
var this$1 = this; | ||
superclass.call(this, props); // Register ref prop for accessing custom element https://reactjs.org/docs/refs-and-the-dom.html#callback-refs | ||
return function (superclass) { | ||
function anonymous(props) { | ||
var this$1$1 = this; | ||
superclass.call(this, props); // Register ref prop for accessing custom element https://reactjs.org/docs/refs-and-the-dom.html#callback-refs | ||
this.ref = function (el) { | ||
if (typeof this$1.props.forwardRef === 'function') { | ||
this$1.props.forwardRef(el); | ||
} else if (this$1.props.forwardRef) { | ||
this$1.props.forwardRef.current = el; | ||
} | ||
this.ref = function (el) { | ||
if (typeof this$1$1.props.forwardRef === 'function') { | ||
this$1$1.props.forwardRef(el); | ||
} else if (this$1$1.props.forwardRef) { | ||
this$1$1.props.forwardRef.current = el; | ||
} | ||
return this$1.el = el; | ||
}; // Register event handler on component for each custom event | ||
return this$1$1.el = el; | ||
}; // Register event handler on component for each custom event | ||
Object.keys(eventMap).forEach(function (eventName) { | ||
var onEventName = eventMap[eventName]; | ||
Object.keys(eventMap).forEach(function (eventName) { | ||
var onEventName = eventMap[eventName]; | ||
this$1[eventName] = function (event) { | ||
if (this$1.props[onEventName] && closest$1(event.target, this$1.el.nodeName) === this$1.el) { | ||
this$1.props[onEventName](event); | ||
} | ||
}; | ||
}); | ||
} | ||
this$1$1[eventName] = function (event) { | ||
if (this$1$1.props[onEventName] && closest(event.target, this$1$1.el.nodeName) === this$1$1.el) { | ||
this$1$1.props[onEventName](event); | ||
} | ||
}; | ||
}); | ||
} | ||
if (superclass) anonymous.__proto__ = superclass; | ||
anonymous.prototype = Object.create(superclass && superclass.prototype); | ||
anonymous.prototype.constructor = anonymous; | ||
if (superclass) anonymous.__proto__ = superclass; | ||
anonymous.prototype = Object.create(superclass && superclass.prototype); | ||
anonymous.prototype.constructor = anonymous; | ||
anonymous.prototype.componentDidMount = function componentDidMount() { | ||
var this$1 = this; // Run connectedCallback() after React componentDidMount() to allow React hydration to run first | ||
anonymous.prototype.componentDidMount = function componentDidMount() { | ||
var this$1$1 = this; // Run connectedCallback() after React componentDidMount() to allow React hydration to run first | ||
if (!window.customElements.get(tagName)) { | ||
window.customElements.define(tagName, elementClass); | ||
} // Populate properties on custom element | ||
if (!window.customElements.get(tagName)) { | ||
window.customElements.define(tagName, elementClass); | ||
} // Populate properties on custom element | ||
customProps.forEach(function (propName) { | ||
if (propName in this$1.props) { | ||
this$1.el[propName] = this$1.props[propName]; | ||
} | ||
}); // Register events on custom element | ||
customProps.forEach(function (propName) { | ||
if (propName in this$1$1.props) { | ||
this$1$1.el[propName] = this$1$1.props[propName]; | ||
} | ||
}); // Register events on custom element | ||
customEvents.forEach(function (eventName) { | ||
this$1.el.addEventListener(eventName, this$1[eventName]); | ||
}); | ||
}; | ||
customEvents.forEach(function (eventName) { | ||
this$1$1.el.addEventListener(eventName, this$1$1[eventName]); | ||
}); | ||
}; | ||
anonymous.prototype.componentDidUpdate = function componentDidUpdate(prev) { | ||
var this$1 = this; // Sync prop changes to custom element | ||
anonymous.prototype.componentDidUpdate = function componentDidUpdate(prev) { | ||
var this$1$1 = this; // Sync prop changes to custom element | ||
customProps.forEach(function (propName) { | ||
if (prev[propName] !== this$1.props[propName]) { | ||
this$1.el[propName] = this$1.props[propName]; | ||
} | ||
}); | ||
}; | ||
customProps.forEach(function (propName) { | ||
if (prev[propName] !== this$1$1.props[propName]) { | ||
this$1$1.el[propName] = this$1$1.props[propName]; | ||
} | ||
}); | ||
}; | ||
anonymous.prototype.componentWillUnmount = function componentWillUnmount() { | ||
var this$1 = this; // Remove event handlers on custom element on unmount | ||
anonymous.prototype.componentWillUnmount = function componentWillUnmount() { | ||
var this$1$1 = this; // Remove event handlers on custom element on unmount | ||
customEvents.forEach(function (eventName) { | ||
this$1.el.removeEventListener(eventName, this$1[eventName]); | ||
}); | ||
}; | ||
customEvents.forEach(function (eventName) { | ||
this$1$1.el.removeEventListener(eventName, this$1$1[eventName]); | ||
}); | ||
}; | ||
anonymous.prototype.render = function render() { | ||
var this$1 = this; // Convert React props to CustomElement props https://github.com/facebook/react/issues/12810 | ||
anonymous.prototype.render = function render() { | ||
var this$1$1 = this; // Convert React props to CustomElement props https://github.com/facebook/react/issues/12810 | ||
return React.createElement(tagName, Object.keys(this.props).reduce(function (thisProps, propName) { | ||
if (skipProps.indexOf(propName) === -1) { | ||
// Do not render customEvents and custom props as attributes | ||
if (propName === 'className') { | ||
thisProps["class"] = this$1.props[propName]; | ||
} // Fixes className for custom elements | ||
else if (this$1.props[propName] === true) { | ||
thisProps[propName] = ''; | ||
} // Fixes boolean attributes | ||
else if (this$1.props[propName] !== false) { | ||
thisProps[propName] = this$1.props[propName]; | ||
} // Pass only truthy, non-function props | ||
return React__default['default'].createElement(tagName, Object.keys(this.props).reduce(function (thisProps, propName) { | ||
if (skipProps.indexOf(propName) === -1) { | ||
// Do not render customEvents and custom props as attributes | ||
if (propName === 'className') { | ||
thisProps["class"] = this$1$1.props[propName]; | ||
} // Fixes className for custom elements | ||
else if (this$1$1.props[propName] === true) { | ||
thisProps[propName] = ''; | ||
} // Fixes boolean attributes | ||
else if (this$1$1.props[propName] !== false) { | ||
thisProps[propName] = this$1$1.props[propName]; | ||
} // Pass only truthy, non-function props | ||
} | ||
} | ||
return thisProps; | ||
}, { | ||
ref: this.ref | ||
})); | ||
}; | ||
return thisProps; | ||
}, { | ||
ref: this.ref | ||
})); | ||
}; | ||
return anonymous; | ||
}(React.Component) | ||
); | ||
return anonymous; | ||
}(React__default['default'].Component); | ||
} | ||
var coreToggle = customElementToReact(CoreToggle, { | ||
props: ['popup'], | ||
customEvents: ['toggle', 'toggle.select'], | ||
@@ -536,0 +631,0 @@ suffix: version |
@@ -5,3 +5,3 @@ { | ||
"author": "NRK <opensource@nrk.no> (https://www.nrk.no/)", | ||
"version": "3.0.8", | ||
"version": "3.0.9-0", | ||
"license": "MIT", | ||
@@ -8,0 +8,0 @@ "main": "core-toggle.cjs.js", |
@@ -78,3 +78,3 @@ # Core Toggle | ||
Remember to [polyfill](https://github.com/webcomponents/polyfills#custom-elements) custom elements if needed. | ||
Remember to [polyfill](https://github.com/webcomponents/polyfills/tree/master/packages/custom-elements) custom elements if needed. | ||
@@ -87,3 +87,3 @@ | ||
```html | ||
<button>Toggle VanillaJS</button> <!-- Must be <button> placed directly before <core-toggle> or use id + for attributes --> | ||
<button>Toggle VanillaJS</button> <!-- Must be <button> placed directly before <core-toggle> or use id + data-for attributes --> | ||
<core-toggle | ||
@@ -135,7 +135,7 @@ hidden <!-- Set hidden attribute to prevent FOUC --> | ||
Putting the toggle button directly before the content is highly recommended, as this fulfills all accessibility requirements by default. There might be scenarios though, where styling makes this DOM structure impractical. In such cases, give the `<button>` a `for` attribute, and the `<core-toggle>` an `id` with corresponding value. Make sure there is no text between the button and toggle content, as this will break the experience for screen reader users: | ||
Putting the toggle button directly before the content is highly recommended, as this fulfills all accessibility requirements by default. There might be scenarios though, where styling makes this DOM structure impractical. In such cases, give the `<button>` a `data-for` attribute (`for` is deprecated), and the `<core-toggle>` an `id` with corresponding value. Make sure there is no text between the button and toggle content, as this will break the experience for screen reader users: | ||
```html | ||
<div> | ||
<button for="my-toggle">Toggle</button> | ||
<button data-for="my-toggle">Toggle</button> | ||
</div> | ||
@@ -162,2 +162,21 @@ <core-toggle id="my-toggle" hidden>...</core-toggle> | ||
### Autoposition | ||
When using core-toggle near the screen edges, the `autoposition` attribute positions the toggled content where there is visual room around the button, using `position:fixed`. | ||
This enables core-toggle to be used inside scrollable areas. | ||
```html | ||
<!--demo--> | ||
<div style="overflow:auto; height:70px; width:200px; border:2px dashed #ccc;"> | ||
<button type="button">Toggle is autopositioned</button> | ||
<core-toggle class="my-dropdown" autoposition hidden> | ||
<ul> | ||
<li><a>Link</a></li> | ||
<li><a>Another link</a></li> | ||
<li><a>Linking is life</a></li> | ||
</ul> | ||
</core-toggle> | ||
<p>Scroll me to the edge!</p> | ||
</div> | ||
``` | ||
## Events | ||
@@ -228,2 +247,4 @@ | ||
`popup`-attribute is required for Select behavior | ||
Listen to the `toggle.select` event and update the button's value from the selected item | ||
@@ -230,0 +251,0 @@ to create a component that behaves like a `<select>`: |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
173551
2322
315
1
1