react-aria-menubutton
Advanced tools
Comparing version 0.3.0 to 0.4.0
# Changelog | ||
## 0.4.0 | ||
- Options to customize css classes' component name and namespace. | ||
- Remove the need to pass in React by distinguishing `dist-modules/` with (transpiled) CommonJS modules and `dist/` with a UMD library that expects React to be global. | ||
- Switch from browserify to webpack for JS module compilation. | ||
## 0.3.0 | ||
@@ -4,0 +9,0 @@ - Remove `classnames` dependency. |
@@ -14,2 +14,6 @@ 'use strict'; | ||
var _React = require('react'); | ||
var _React2 = _interopRequireWildcard(_React); | ||
var _import = require('./keys'); | ||
@@ -19,5 +23,5 @@ | ||
var _createMenu = require('./createMenu'); | ||
var _Menu = require('./Menu'); | ||
var _createMenu2 = _interopRequireWildcard(_createMenu); | ||
var _Menu2 = _interopRequireWildcard(_Menu); | ||
@@ -28,7 +32,11 @@ var _focusManager = require('./focusManager'); | ||
var _cssClassnamer = require('./cssClassnamer'); | ||
var _cssClassnamer2 = _interopRequireWildcard(_cssClassnamer); | ||
function createAriaMenuButton() { | ||
var React = arguments[0] === undefined ? global.React : arguments[0]; | ||
var opts = arguments[0] === undefined ? {} : arguments[0]; | ||
var Menu = _createMenu2['default'](React); | ||
var CSSTransitionGroup = React.addons ? React.addons.CSSTransitionGroup : false; | ||
var CSSTransitionGroup = opts.reactAddons ? opts.reactAddons.CSSTransitionGroup : false; | ||
_cssClassnamer2['default'].init(opts.componentName, opts.namespace); | ||
@@ -57,3 +65,3 @@ var AriaMenuButton = (function (_React$Component) { | ||
AriaMenuButton.prototype.componentDidMount = function componentDidMount() { | ||
this.focusManager.trigger = React.findDOMNode(this.refs.trigger); | ||
this.focusManager.trigger = _React2['default'].findDOMNode(this.refs.trigger); | ||
}; | ||
@@ -164,6 +172,6 @@ | ||
var outsideId = props.id ? '' + props.id + '-outside' : undefined; | ||
var triggerClasses = 'AriaMenuButton-trigger'; | ||
if (isOpen) triggerClasses += ' is-open'; | ||
var triggerClasses = [_cssClassnamer2['default'].componentPart('trigger')]; | ||
if (isOpen) triggerClasses.push(_cssClassnamer2['default'].applyNamespace('is-open')); | ||
var menu = isOpen ? React.createElement(Menu, _extends({}, props, { | ||
var menu = isOpen ? _React2['default'].createElement(_Menu2['default'], _extends({}, props, { | ||
handleSelection: this.handleSelection.bind(this), | ||
@@ -173,12 +181,12 @@ receiveFocus: this.state.innerFocus, | ||
var menuWrapper = props.transition ? React.createElement( | ||
var menuWrapper = props.transition ? _React2['default'].createElement( | ||
CSSTransitionGroup, | ||
{ transitionName: 'is', | ||
{ transitionName: _cssClassnamer2['default'].applyNamespace('is'), | ||
component: 'div', | ||
className: 'AriaMenuButton-menuWrapper AriaMenuButton-menuWrapper--trans', | ||
className: [_cssClassnamer2['default'].componentPart('menuWrapper'), _cssClassnamer2['default'].componentPart('menuWrapper--trans')].join(' '), | ||
onKeyDown: this.handleMenuKey.bind(this) }, | ||
menu | ||
) : React.createElement( | ||
) : _React2['default'].createElement( | ||
'div', | ||
{ className: 'AriaMenuButton-menuWrapper', | ||
{ className: _cssClassnamer2['default'].componentPart('menuWrapper'), | ||
onKeyDown: this.handleMenuKey.bind(this) }, | ||
@@ -200,3 +208,3 @@ menu | ||
var outsideOverlay = !isOpen ? false : React.createElement('div', { id: outsideId, | ||
var outsideOverlay = !isOpen ? false : _React2['default'].createElement('div', { id: outsideId, | ||
onClick: this.handleOverlayClick.bind(this), | ||
@@ -212,16 +220,16 @@ ref: 'overlay', | ||
return React.createElement( | ||
return _React2['default'].createElement( | ||
'div', | ||
{ id: props.id, | ||
className: 'AriaMenuButton', | ||
className: _cssClassnamer2['default'].componentPart(), | ||
onKeyDown: this.handleAnywhereKey.bind(this), | ||
onBlur: this.handleBlur.bind(this) }, | ||
outsideOverlay, | ||
React.createElement( | ||
_React2['default'].createElement( | ||
'div', | ||
{ style: innerStyle }, | ||
React.createElement( | ||
_React2['default'].createElement( | ||
'div', | ||
{ id: triggerId, | ||
className: triggerClasses, | ||
className: triggerClasses.join(' '), | ||
onClick: this.toggleMenu.bind(this), | ||
@@ -242,5 +250,6 @@ onKeyDown: this.handleTriggerKey.bind(this), | ||
return AriaMenuButton; | ||
})(React.Component); | ||
})(_React2['default'].Component); | ||
var pt = React.PropTypes; | ||
var pt = _React2['default'].PropTypes; | ||
AriaMenuButton.propTypes = { | ||
@@ -247,0 +256,0 @@ handleSelection: pt.func.isRequired, |
@@ -1,526 +0,647 @@ | ||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.createAriaMenuButton = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
(function (global){ | ||
'use strict'; | ||
(function webpackUniversalModuleDefinition(root, factory) { | ||
if(typeof exports === 'object' && typeof module === 'object') | ||
module.exports = factory(require("react")); | ||
else if(typeof define === 'function' && define.amd) | ||
define(["react"], factory); | ||
else if(typeof exports === 'object') | ||
exports["AriaMenuButton"] = factory(require("react")); | ||
else | ||
root["AriaMenuButton"] = factory(root["react"]); | ||
})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { | ||
return /******/ (function(modules) { // webpackBootstrap | ||
/******/ // The module cache | ||
/******/ var installedModules = {}; | ||
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; | ||
/******/ // The require function | ||
/******/ function __webpack_require__(moduleId) { | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; | ||
/******/ // Check if module is in cache | ||
/******/ if(installedModules[moduleId]) | ||
/******/ return installedModules[moduleId].exports; | ||
var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; | ||
/******/ // Create a new module (and put it into the cache) | ||
/******/ var module = installedModules[moduleId] = { | ||
/******/ exports: {}, | ||
/******/ id: moduleId, | ||
/******/ loaded: false | ||
/******/ }; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
/******/ // Execute the module function | ||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); | ||
exports.__esModule = true; | ||
exports['default'] = createAriaMenuButton; | ||
/******/ // Flag the module as loaded | ||
/******/ module.loaded = true; | ||
var _import = require('./keys'); | ||
/******/ // Return the exports of the module | ||
/******/ return module.exports; | ||
/******/ } | ||
var keys = _interopRequireWildcard(_import); | ||
var _createMenu = require('./createMenu'); | ||
/******/ // expose the modules object (__webpack_modules__) | ||
/******/ __webpack_require__.m = modules; | ||
var _createMenu2 = _interopRequireWildcard(_createMenu); | ||
/******/ // expose the module cache | ||
/******/ __webpack_require__.c = installedModules; | ||
var _focusManager = require('./focusManager'); | ||
/******/ // __webpack_public_path__ | ||
/******/ __webpack_require__.p = ""; | ||
var _focusManager2 = _interopRequireWildcard(_focusManager); | ||
/******/ // Load entry module and return exports | ||
/******/ return __webpack_require__(0); | ||
/******/ }) | ||
/************************************************************************/ | ||
/******/ ([ | ||
/* 0 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
function createAriaMenuButton() { | ||
var React = arguments[0] === undefined ? global.React : arguments[0]; | ||
'use strict'; | ||
var Menu = _createMenu2['default'](React); | ||
var CSSTransitionGroup = React.addons ? React.addons.CSSTransitionGroup : false; | ||
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; | ||
var AriaMenuButton = (function (_React$Component) { | ||
function AriaMenuButton(props) { | ||
_classCallCheck(this, AriaMenuButton); | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; | ||
_React$Component.call(this, props); | ||
this.state = { isOpen: !!props.startOpen }; | ||
this.focusManager = _focusManager2['default'](); | ||
} | ||
var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; | ||
_inherits(AriaMenuButton, _React$Component); | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
AriaMenuButton.prototype.shouldComponentUpdate = function shouldComponentUpdate(newProps, newState) { | ||
return this.state.isOpen !== newState.isOpen || this.props.selectedValue !== newProps.selectedValue; | ||
}; | ||
exports.__esModule = true; | ||
exports['default'] = createAriaMenuButton; | ||
AriaMenuButton.prototype.componentWillMount = function componentWillMount() { | ||
if (this.props.transition && !CSSTransitionGroup) { | ||
throw new Error('If you want to use transitions with ariaMenuButton, you need to pass it ' + 'React with addons'); | ||
} | ||
}; | ||
var _React = __webpack_require__(1); | ||
AriaMenuButton.prototype.componentDidMount = function componentDidMount() { | ||
this.focusManager.trigger = React.findDOMNode(this.refs.trigger); | ||
}; | ||
var _React2 = _interopRequireWildcard(_React); | ||
AriaMenuButton.prototype.openMenu = function openMenu() { | ||
var innerFocus = arguments[0] === undefined ? false : arguments[0]; | ||
var _import = __webpack_require__(2); | ||
this.setState({ isOpen: true, innerFocus: innerFocus }); | ||
}; | ||
var keys = _interopRequireWildcard(_import); | ||
AriaMenuButton.prototype.closeMenu = function closeMenu() { | ||
var _this = this; | ||
var _Menu = __webpack_require__(3); | ||
var focusTrigger = arguments[0] === undefined ? true : arguments[0]; | ||
var _Menu2 = _interopRequireWildcard(_Menu); | ||
this.setState({ isOpen: false, innerFocus: false }, function () { | ||
if (focusTrigger) _this.focusManager.focusTrigger(); | ||
_this.focusManager.currentFocus = -1; | ||
}); | ||
}; | ||
var _focusManager = __webpack_require__(4); | ||
AriaMenuButton.prototype.toggleMenu = function toggleMenu() { | ||
if (this.state.isOpen) this.closeMenu();else this.openMenu(); | ||
}; | ||
var _focusManager2 = _interopRequireWildcard(_focusManager); | ||
AriaMenuButton.prototype.handleAnywhereKey = function handleAnywhereKey(e) { | ||
var key = e.key; | ||
var isLetterKey = isLetterKeyEvent(e); | ||
var _cssClassnamer = __webpack_require__(5); | ||
if (key !== keys.DOWN && !isLetterKey) { | ||
return; | ||
}e.preventDefault(); | ||
var _cssClassnamer2 = _interopRequireWildcard(_cssClassnamer); | ||
if (key === keys.DOWN) { | ||
// "With focus on the button and the drop-down menu open, | ||
// pressing Down Arrow will move focus into the menu onto | ||
// the first menu item. [...]" | ||
// "With focus on the drop-down menu, the Up and Down Arrow | ||
// keys move focus within the menu items, "wrapping" at the top and bottom." | ||
if (this.state.isOpen) this.focusManager.moveDown(); | ||
function createAriaMenuButton() { | ||
var opts = arguments[0] === undefined ? {} : arguments[0]; | ||
// "With focus on the button and no drop-down menu displayed, | ||
// pressing Down Arrow will open the drop-down menu and move focus | ||
// into the menu and onto the first menu item." | ||
else this.openMenu(true); | ||
} else if (isLetterKey && this.state.isOpen) this.checkLetterKeys(e.keyCode); | ||
}; | ||
var CSSTransitionGroup = opts.reactAddons ? opts.reactAddons.CSSTransitionGroup : false; | ||
_cssClassnamer2['default'].init(opts.componentName, opts.namespace); | ||
// "With focus on the button pressing Space or Enter will toggle | ||
// the display of the drop-down menu. Focus remains on the button." | ||
var AriaMenuButton = (function (_React$Component) { | ||
function AriaMenuButton(props) { | ||
_classCallCheck(this, AriaMenuButton); | ||
AriaMenuButton.prototype.handleTriggerKey = function handleTriggerKey(e) { | ||
var key = e.key; | ||
if (key !== keys.ENTER && key !== keys.SPACE) { | ||
return; | ||
}e.preventDefault(); | ||
this.toggleMenu(); | ||
}; | ||
_React$Component.call(this, props); | ||
this.state = { isOpen: !!props.startOpen }; | ||
this.focusManager = _focusManager2['default'](); | ||
} | ||
AriaMenuButton.prototype.handleMenuKey = function handleMenuKey(e) { | ||
// "With focus on the drop-down menu, pressing Escape closes | ||
// the menu and returns focus to the button. | ||
if (e.key === keys.ESCAPE) this.closeMenu(); | ||
_inherits(AriaMenuButton, _React$Component); | ||
// "With focus on the drop-down menu, the Up and Down Arrow | ||
// keys move focus within the menu items, "wrapping" at the top and bottom." | ||
else if (e.key === keys.UP && this.state.isOpen) { | ||
e.preventDefault(); | ||
this.focusManager.moveUp(); | ||
} | ||
}; | ||
AriaMenuButton.prototype.shouldComponentUpdate = function shouldComponentUpdate(newProps, newState) { | ||
return this.state.isOpen !== newState.isOpen || this.props.selectedValue !== newProps.selectedValue; | ||
}; | ||
AriaMenuButton.prototype.checkLetterKeys = function checkLetterKeys(kc) { | ||
// "Typing a letter (printable character) key moves focus to the next | ||
// instance of a visible node whose title begins with that printable letter." | ||
this.focusManager.moveToLetter(String.fromCharCode(kc)); | ||
}; | ||
AriaMenuButton.prototype.componentWillMount = function componentWillMount() { | ||
if (this.props.transition && !CSSTransitionGroup) { | ||
throw new Error('If you want to use transitions with ariaMenuButton, you need to pass it ' + 'React with addons'); | ||
} | ||
}; | ||
AriaMenuButton.prototype.handleBlur = function handleBlur() { | ||
var _this2 = this; | ||
AriaMenuButton.prototype.componentDidMount = function componentDidMount() { | ||
this.focusManager.trigger = _React2['default'].findDOMNode(this.refs.trigger); | ||
}; | ||
this.blurTimeout = setTimeout(function () { | ||
var activeEl = document.activeElement; | ||
if (activeEl === _this2.focusManager.trigger) return; | ||
if (_this2.focusManager.focusables.some(function (f) { | ||
return f.node === activeEl; | ||
})) return; | ||
if (_this2.state.isOpen) _this2.closeMenu(false); | ||
}, 0); | ||
}; | ||
AriaMenuButton.prototype.openMenu = function openMenu() { | ||
var innerFocus = arguments[0] === undefined ? false : arguments[0]; | ||
AriaMenuButton.prototype.handleSelection = function handleSelection(v) { | ||
if (this.props.closeOnSelection) this.closeMenu(); | ||
this.props.handleSelection(v); | ||
}; | ||
this.setState({ isOpen: true, innerFocus: innerFocus }); | ||
}; | ||
AriaMenuButton.prototype.handleOverlayClick = function handleOverlayClick() { | ||
console.log('overlay click triggered'); | ||
this.closeMenu(false); | ||
}; | ||
AriaMenuButton.prototype.closeMenu = function closeMenu() { | ||
var _this = this; | ||
AriaMenuButton.prototype.render = function render() { | ||
var props = this.props; | ||
var isOpen = this.state.isOpen; | ||
var focusTrigger = arguments[0] === undefined ? true : arguments[0]; | ||
var triggerId = props.id ? '' + props.id + '-trigger' : undefined; | ||
var outsideId = props.id ? '' + props.id + '-outside' : undefined; | ||
var triggerClasses = 'AriaMenuButton-trigger'; | ||
if (isOpen) triggerClasses += ' is-open'; | ||
this.setState({ isOpen: false, innerFocus: false }, function () { | ||
if (focusTrigger) _this.focusManager.focusTrigger(); | ||
_this.focusManager.currentFocus = -1; | ||
}); | ||
}; | ||
var menu = isOpen ? React.createElement(Menu, _extends({}, props, { | ||
handleSelection: this.handleSelection.bind(this), | ||
receiveFocus: this.state.innerFocus, | ||
focusManager: this.focusManager })) : false; | ||
AriaMenuButton.prototype.toggleMenu = function toggleMenu() { | ||
if (this.state.isOpen) this.closeMenu();else this.openMenu(); | ||
}; | ||
var menuWrapper = props.transition ? React.createElement( | ||
CSSTransitionGroup, | ||
{ transitionName: 'is', | ||
component: 'div', | ||
className: 'AriaMenuButton-menuWrapper AriaMenuButton-menuWrapper--trans', | ||
onKeyDown: this.handleMenuKey.bind(this) }, | ||
menu | ||
) : React.createElement( | ||
'div', | ||
{ className: 'AriaMenuButton-menuWrapper', | ||
onKeyDown: this.handleMenuKey.bind(this) }, | ||
menu | ||
); | ||
AriaMenuButton.prototype.handleAnywhereKey = function handleAnywhereKey(e) { | ||
var key = e.key; | ||
var isLetterKey = isLetterKeyEvent(e); | ||
// The outsideOverlay and its accompanying innerStyle are here | ||
// to make the menu close when there is a click outside it | ||
// (mobile browsers will not fire the onBlur handler). | ||
// They are styled inline here because they should be the same | ||
// in every situation. | ||
if (key !== keys.DOWN && !isLetterKey) { | ||
return; | ||
}e.preventDefault(); | ||
var innerStyle = !isOpen ? {} : { | ||
display: 'inline-block', | ||
position: 'relative', | ||
zIndex: '100' | ||
}; | ||
if (key === keys.DOWN) { | ||
// "With focus on the button and the drop-down menu open, | ||
// pressing Down Arrow will move focus into the menu onto | ||
// the first menu item. [...]" | ||
// "With focus on the drop-down menu, the Up and Down Arrow | ||
// keys move focus within the menu items, "wrapping" at the top and bottom." | ||
if (this.state.isOpen) this.focusManager.moveDown(); | ||
var outsideOverlay = !isOpen ? false : React.createElement('div', { id: outsideId, | ||
onClick: this.handleOverlayClick.bind(this), | ||
ref: 'overlay', | ||
style: { | ||
cursor: 'pointer', | ||
position: 'fixed', | ||
top: 0, bottom: 0, left: 0, right: 0, | ||
zIndex: '99', | ||
WebkitTapHighlightColor: 'rgba(0,0,0,0)' | ||
} }); | ||
// "With focus on the button and no drop-down menu displayed, | ||
// pressing Down Arrow will open the drop-down menu and move focus | ||
// into the menu and onto the first menu item." | ||
else this.openMenu(true); | ||
} else if (isLetterKey && this.state.isOpen) this.checkLetterKeys(e.keyCode); | ||
}; | ||
return React.createElement( | ||
'div', | ||
{ id: props.id, | ||
className: 'AriaMenuButton', | ||
onKeyDown: this.handleAnywhereKey.bind(this), | ||
onBlur: this.handleBlur.bind(this) }, | ||
outsideOverlay, | ||
React.createElement( | ||
'div', | ||
{ style: innerStyle }, | ||
React.createElement( | ||
'div', | ||
{ id: triggerId, | ||
className: triggerClasses, | ||
onClick: this.toggleMenu.bind(this), | ||
onKeyDown: this.handleTriggerKey.bind(this), | ||
ref: 'trigger', | ||
'aria-haspopup': true, | ||
'aria-expanded': isOpen, | ||
role: 'button', | ||
tabIndex: '0' }, | ||
props.triggerContent | ||
), | ||
menuWrapper | ||
) | ||
); | ||
}; | ||
// "With focus on the button pressing Space or Enter will toggle | ||
// the display of the drop-down menu. Focus remains on the button." | ||
return AriaMenuButton; | ||
})(React.Component); | ||
AriaMenuButton.prototype.handleTriggerKey = function handleTriggerKey(e) { | ||
var key = e.key; | ||
if (key !== keys.ENTER && key !== keys.SPACE) { | ||
return; | ||
}e.preventDefault(); | ||
this.toggleMenu(); | ||
}; | ||
var pt = React.PropTypes; | ||
AriaMenuButton.propTypes = { | ||
handleSelection: pt.func.isRequired, | ||
items: pt.arrayOf(pt.object).isRequired, | ||
triggerContent: pt.oneOfType([pt.string, pt.element]).isRequired, | ||
closeOnSelection: pt.bool, | ||
flushRight: pt.bool, | ||
id: pt.string, | ||
startOpen: pt.bool, | ||
selectedValue: pt.oneOfType([pt.string, pt.number, pt.bool]), | ||
transition: pt.bool | ||
}; | ||
AriaMenuButton.prototype.handleMenuKey = function handleMenuKey(e) { | ||
// "With focus on the drop-down menu, pressing Escape closes | ||
// the menu and returns focus to the button. | ||
if (e.key === keys.ESCAPE) this.closeMenu(); | ||
return AriaMenuButton; | ||
} | ||
// "With focus on the drop-down menu, the Up and Down Arrow | ||
// keys move focus within the menu items, "wrapping" at the top and bottom." | ||
else if (e.key === keys.UP && this.state.isOpen) { | ||
e.preventDefault(); | ||
this.focusManager.moveUp(); | ||
} | ||
}; | ||
function isLetterKeyEvent(e) { | ||
return e.keyCode >= keys.LOWEST_LETTER_CODE && e.keyCode <= keys.HIGHEST_LETTER_CODE; | ||
} | ||
module.exports = exports['default']; | ||
AriaMenuButton.prototype.checkLetterKeys = function checkLetterKeys(kc) { | ||
// "Typing a letter (printable character) key moves focus to the next | ||
// instance of a visible node whose title begins with that printable letter." | ||
this.focusManager.moveToLetter(String.fromCharCode(kc)); | ||
}; | ||
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | ||
},{"./createMenu":2,"./focusManager":4,"./keys":5}],2:[function(require,module,exports){ | ||
'use strict'; | ||
AriaMenuButton.prototype.handleBlur = function handleBlur() { | ||
var _this2 = this; | ||
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; | ||
this.blurTimeout = setTimeout(function () { | ||
var activeEl = document.activeElement; | ||
if (activeEl === _this2.focusManager.trigger) return; | ||
if (_this2.focusManager.focusables.some(function (f) { | ||
return f.node === activeEl; | ||
})) return; | ||
if (_this2.state.isOpen) _this2.closeMenu(false); | ||
}, 0); | ||
}; | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; | ||
AriaMenuButton.prototype.handleSelection = function handleSelection(v) { | ||
if (this.props.closeOnSelection) this.closeMenu(); | ||
this.props.handleSelection(v); | ||
}; | ||
var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; | ||
AriaMenuButton.prototype.handleOverlayClick = function handleOverlayClick() { | ||
console.log('overlay click triggered'); | ||
this.closeMenu(false); | ||
}; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
AriaMenuButton.prototype.render = function render() { | ||
var props = this.props; | ||
var isOpen = this.state.isOpen; | ||
exports.__esModule = true; | ||
exports['default'] = createMenu; | ||
var triggerId = props.id ? '' + props.id + '-trigger' : undefined; | ||
var outsideId = props.id ? '' + props.id + '-outside' : undefined; | ||
var triggerClasses = [_cssClassnamer2['default'].componentPart('trigger')]; | ||
if (isOpen) triggerClasses.push(_cssClassnamer2['default'].applyNamespace('is-open')); | ||
var _createMenuItem = require('./createMenuItem'); | ||
var menu = isOpen ? _React2['default'].createElement(_Menu2['default'], _extends({}, props, { | ||
handleSelection: this.handleSelection.bind(this), | ||
receiveFocus: this.state.innerFocus, | ||
focusManager: this.focusManager })) : false; | ||
var _createMenuItem2 = _interopRequireWildcard(_createMenuItem); | ||
var menuWrapper = props.transition ? _React2['default'].createElement( | ||
CSSTransitionGroup, | ||
{ transitionName: _cssClassnamer2['default'].applyNamespace('is'), | ||
component: 'div', | ||
className: [_cssClassnamer2['default'].componentPart('menuWrapper'), _cssClassnamer2['default'].componentPart('menuWrapper--trans')].join(' '), | ||
onKeyDown: this.handleMenuKey.bind(this) }, | ||
menu | ||
) : _React2['default'].createElement( | ||
'div', | ||
{ className: _cssClassnamer2['default'].componentPart('menuWrapper'), | ||
onKeyDown: this.handleMenuKey.bind(this) }, | ||
menu | ||
); | ||
function createMenu(React) { | ||
// The outsideOverlay and its accompanying innerStyle are here | ||
// to make the menu close when there is a click outside it | ||
// (mobile browsers will not fire the onBlur handler). | ||
// They are styled inline here because they should be the same | ||
// in every situation. | ||
var MenuItem = _createMenuItem2['default'](React); | ||
var innerStyle = !isOpen ? {} : { | ||
display: 'inline-block', | ||
position: 'relative', | ||
zIndex: '100' | ||
}; | ||
var Menu = (function (_React$Component) { | ||
function Menu() { | ||
_classCallCheck(this, Menu); | ||
var outsideOverlay = !isOpen ? false : _React2['default'].createElement('div', { id: outsideId, | ||
onClick: this.handleOverlayClick.bind(this), | ||
ref: 'overlay', | ||
style: { | ||
cursor: 'pointer', | ||
position: 'fixed', | ||
top: 0, bottom: 0, left: 0, right: 0, | ||
zIndex: '99', | ||
WebkitTapHighlightColor: 'rgba(0,0,0,0)' | ||
} }); | ||
if (_React$Component != null) { | ||
_React$Component.apply(this, arguments); | ||
} | ||
} | ||
return _React2['default'].createElement( | ||
'div', | ||
{ id: props.id, | ||
className: _cssClassnamer2['default'].componentPart(), | ||
onKeyDown: this.handleAnywhereKey.bind(this), | ||
onBlur: this.handleBlur.bind(this) }, | ||
outsideOverlay, | ||
_React2['default'].createElement( | ||
'div', | ||
{ style: innerStyle }, | ||
_React2['default'].createElement( | ||
'div', | ||
{ id: triggerId, | ||
className: triggerClasses.join(' '), | ||
onClick: this.toggleMenu.bind(this), | ||
onKeyDown: this.handleTriggerKey.bind(this), | ||
ref: 'trigger', | ||
'aria-haspopup': true, | ||
'aria-expanded': isOpen, | ||
role: 'button', | ||
tabIndex: '0' }, | ||
props.triggerContent | ||
), | ||
menuWrapper | ||
) | ||
); | ||
}; | ||
_inherits(Menu, _React$Component); | ||
return AriaMenuButton; | ||
})(_React2['default'].Component); | ||
Menu.prototype.shouldComponentUpdate = function shouldComponentUpdate(newProps) { | ||
return this.props.selectedValue !== newProps.selectedValue; | ||
}; | ||
var pt = _React2['default'].PropTypes; | ||
Menu.prototype.componentWillMount = function componentWillMount() { | ||
this.props.focusManager.focusables = []; | ||
}; | ||
AriaMenuButton.propTypes = { | ||
handleSelection: pt.func.isRequired, | ||
items: pt.arrayOf(pt.object).isRequired, | ||
triggerContent: pt.oneOfType([pt.string, pt.element]).isRequired, | ||
closeOnSelection: pt.bool, | ||
flushRight: pt.bool, | ||
id: pt.string, | ||
startOpen: pt.bool, | ||
selectedValue: pt.oneOfType([pt.string, pt.number, pt.bool]), | ||
transition: pt.bool | ||
}; | ||
Menu.prototype.componentDidMount = function componentDidMount() { | ||
if (this.props.receiveFocus) this.props.focusManager.move(0); | ||
}; | ||
return AriaMenuButton; | ||
} | ||
Menu.prototype.render = function render() { | ||
var props = this.props; | ||
var selectedValue = props.selectedValue; | ||
function isLetterKeyEvent(e) { | ||
return e.keyCode >= keys.LOWEST_LETTER_CODE && e.keyCode <= keys.HIGHEST_LETTER_CODE; | ||
} | ||
module.exports = exports['default']; | ||
var items = props.items.map(function (item, i) { | ||
return React.createElement( | ||
'li', | ||
{ key: i, | ||
className: 'AriaMenuButton-li', | ||
role: 'presentation' }, | ||
React.createElement(MenuItem, _extends({}, item, { | ||
focusManager: props.focusManager, | ||
handleSelection: props.handleSelection, | ||
isSelected: item.value === selectedValue })) | ||
); | ||
}); | ||
/***/ }, | ||
/* 1 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
var menuClasses = 'AriaMenuButton-menu'; | ||
if (props.flushRight) menuClasses += ' AriaMenuButton-menu--flushRight'; | ||
module.exports = __WEBPACK_EXTERNAL_MODULE_1__; | ||
return React.createElement( | ||
'ol', | ||
{ className: menuClasses, | ||
role: 'menu' }, | ||
items | ||
); | ||
}; | ||
/***/ }, | ||
/* 2 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
return Menu; | ||
})(React.Component); | ||
'use strict'; | ||
var pt = React.PropTypes; | ||
Menu.propTypes = { | ||
focusManager: pt.object.isRequired, | ||
items: pt.arrayOf(pt.object).isRequired, | ||
flushRight: pt.bool, | ||
handleSelection: pt.func, | ||
receiveFocus: pt.bool, | ||
selectedValue: pt.any | ||
}; | ||
exports.__esModule = true; | ||
// Lookey here | ||
// https://github.com/facebook/react/blob/0.13-stable/src/browser/ui/dom/getEventKey.js | ||
return Menu; | ||
} | ||
var ENTER = 'Enter'; | ||
exports.ENTER = ENTER; | ||
var SPACE = ' '; | ||
exports.SPACE = SPACE; | ||
var ESCAPE = 'Escape'; | ||
exports.ESCAPE = ESCAPE; | ||
var UP = 'ArrowUp'; | ||
exports.UP = UP; | ||
var DOWN = 'ArrowDown'; | ||
exports.DOWN = DOWN; | ||
var LOWEST_LETTER_CODE = 65; | ||
exports.LOWEST_LETTER_CODE = LOWEST_LETTER_CODE; | ||
var HIGHEST_LETTER_CODE = 91; | ||
exports.HIGHEST_LETTER_CODE = HIGHEST_LETTER_CODE; | ||
module.exports = exports['default']; | ||
/***/ }, | ||
/* 3 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
},{"./createMenuItem":3}],3:[function(require,module,exports){ | ||
'use strict'; | ||
'use strict'; | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; | ||
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; | ||
var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; | ||
exports.__esModule = true; | ||
exports['default'] = createMenuItem; | ||
var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; | ||
var _ENTER$SPACE = require('./keys'); | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
function createMenuItem(React) { | ||
var MenuItem = (function (_React$Component) { | ||
function MenuItem() { | ||
_classCallCheck(this, MenuItem); | ||
exports.__esModule = true; | ||
if (_React$Component != null) { | ||
_React$Component.apply(this, arguments); | ||
} | ||
} | ||
var _React = __webpack_require__(1); | ||
_inherits(MenuItem, _React$Component); | ||
var _React2 = _interopRequireWildcard(_React); | ||
MenuItem.prototype.shouldComponentUpdate = function shouldComponentUpdate(newProps) { | ||
return this.props.isSelected !== newProps.isSelected; | ||
}; | ||
var _MenuItem = __webpack_require__(6); | ||
MenuItem.prototype.componentDidMount = function componentDidMount() { | ||
this.props.focusManager.focusables.push({ | ||
content: this.props.content, | ||
text: this.props.text, | ||
node: React.findDOMNode(this) | ||
}); | ||
}; | ||
var _MenuItem2 = _interopRequireWildcard(_MenuItem); | ||
MenuItem.prototype.handleClick = function handleClick(e) { | ||
var props = this.props; | ||
if (props.isSelected) { | ||
return; | ||
} // If there's no value, we'll send the label | ||
var v = typeof props.value !== 'undefined' ? props.value : props.content; | ||
props.handleSelection(v, e); | ||
}; | ||
var _cssClassnamer = __webpack_require__(5); | ||
MenuItem.prototype.handleKey = function handleKey(e) { | ||
if (e.key !== _ENTER$SPACE.ENTER && e.key !== _ENTER$SPACE.SPACE) { | ||
return; | ||
}e.preventDefault(); | ||
this.handleClick(e); | ||
}; | ||
var _cssClassnamer2 = _interopRequireWildcard(_cssClassnamer); | ||
MenuItem.prototype.render = function render() { | ||
var props = this.props; | ||
var itemClasses = 'AriaMenuButton-menuItem'; | ||
if (props.isSelected) itemClasses += ' is-selected'; | ||
var Menu = (function (_React$Component) { | ||
function Menu() { | ||
_classCallCheck(this, Menu); | ||
// tabindex -1 because: "With focus on the button pressing | ||
// the Tab key will take the user to the next tab focusable item on the page. | ||
// With focus on the drop-down menu, pressing the Tab key will take the user | ||
// to the next tab focusable item on the page." | ||
// "A menuitem within a menu or menubar may appear in the tab order | ||
// only if it is not within a popup menu." | ||
// ... so not in tab order, but programatically focusable | ||
return React.createElement( | ||
'div', | ||
{ id: props.id, | ||
className: itemClasses, | ||
onClick: this.handleClick.bind(this), | ||
onKeyDown: this.handleKey.bind(this), | ||
role: 'menuitem', | ||
tabIndex: '-1', | ||
'data-value': props.value }, | ||
props.content | ||
); | ||
}; | ||
if (_React$Component != null) { | ||
_React$Component.apply(this, arguments); | ||
} | ||
} | ||
return MenuItem; | ||
})(React.Component); | ||
_inherits(Menu, _React$Component); | ||
var pt = React.PropTypes; | ||
MenuItem.propTypes = { | ||
focusManager: pt.object.isRequired, | ||
handleSelection: pt.func.isRequired, | ||
content: pt.oneOfType([pt.string, pt.element]).isRequired, | ||
id: pt.string, | ||
isSelected: pt.bool, | ||
text: pt.string, | ||
value: pt.oneOfType([pt.string, pt.number, pt.bool]) | ||
}; | ||
Menu.prototype.shouldComponentUpdate = function shouldComponentUpdate(newProps) { | ||
return this.props.selectedValue !== newProps.selectedValue; | ||
}; | ||
return MenuItem; | ||
} | ||
Menu.prototype.componentWillMount = function componentWillMount() { | ||
this.props.focusManager.focusables = []; | ||
}; | ||
module.exports = exports['default']; | ||
Menu.prototype.componentDidMount = function componentDidMount() { | ||
if (this.props.receiveFocus) this.props.focusManager.move(0); | ||
}; | ||
},{"./keys":5}],4:[function(require,module,exports){ | ||
'use strict'; | ||
Menu.prototype.render = function render() { | ||
var props = this.props; | ||
var selectedValue = props.selectedValue; | ||
exports.__esModule = true; | ||
exports['default'] = focusManager; | ||
var focusManagerProto = { | ||
var items = props.items.map(function (item, i) { | ||
return _React2['default'].createElement( | ||
'li', | ||
{ key: i, | ||
className: _cssClassnamer2['default'].componentPart('li'), | ||
role: 'presentation' }, | ||
_React2['default'].createElement(_MenuItem2['default'], _extends({}, item, { | ||
focusManager: props.focusManager, | ||
handleSelection: props.handleSelection, | ||
isSelected: item.value === selectedValue })) | ||
); | ||
}); | ||
focusables: [], | ||
var menuClasses = [_cssClassnamer2['default'].componentPart('menu')]; | ||
if (props.flushRight) menuClasses.push(_cssClassnamer2['default'].componentPart('menu--flushRight')); | ||
trigger: null, | ||
return _React2['default'].createElement( | ||
'ol', | ||
{ className: menuClasses.join(' '), | ||
role: 'menu' }, | ||
items | ||
); | ||
}; | ||
currentFocus: -1, | ||
return Menu; | ||
})(_React2['default'].Component); | ||
move: function move(i) { | ||
this.focusables[i].node.focus(); | ||
this.currentFocus = i; | ||
}, | ||
exports['default'] = Menu; | ||
moveUp: function moveUp() { | ||
var next = this.currentFocus === -1 || this.currentFocus === 0 ? this.focusables.length - 1 : this.currentFocus - 1; | ||
this.move(next); | ||
}, | ||
var pt = _React2['default'].PropTypes; | ||
moveDown: function moveDown() { | ||
var next = this.currentFocus === -1 || this.currentFocus === this.focusables.length - 1 ? 0 : this.currentFocus + 1; | ||
this.move(next); | ||
}, | ||
Menu.propTypes = { | ||
focusManager: pt.object.isRequired, | ||
items: pt.arrayOf(pt.object).isRequired, | ||
flushRight: pt.bool, | ||
handleSelection: pt.func, | ||
receiveFocus: pt.bool, | ||
selectedValue: pt.any | ||
}; | ||
module.exports = exports['default']; | ||
moveToLetter: function moveToLetter(letter) { | ||
var cyclo = this.focusables.slice(this.currentFocus + 1).concat(this.focusables.slice(0, this.currentFocus + 1)); | ||
for (var i = 0, l = cyclo.length; i < l; i++) { | ||
var item = cyclo[i]; | ||
if (!item.text && !item.content.charAt) { | ||
throw new Error('AriaMenuButton items must have textual `content` or a `text` prop'); | ||
} | ||
if (item.text) { | ||
if (item.text.charAt(0).toLowerCase() !== letter.toLowerCase()) continue; | ||
} else if (item.content.charAt(0).toLowerCase() !== letter.toLowerCase()) continue; | ||
item.node.focus(); | ||
this.currentFocus = this.focusables.indexOf(item); | ||
return; | ||
} | ||
}, | ||
/***/ }, | ||
/* 4 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
focusTrigger: function focusTrigger() { | ||
this.trigger.focus(); | ||
} | ||
'use strict'; | ||
}; | ||
exports.__esModule = true; | ||
exports['default'] = focusManager; | ||
var focusManagerProto = { | ||
function focusManager() { | ||
return Object.create(focusManagerProto); | ||
} | ||
focusables: [], | ||
module.exports = exports['default']; | ||
trigger: null, | ||
},{}],5:[function(require,module,exports){ | ||
'use strict'; | ||
currentFocus: -1, | ||
exports.__esModule = true; | ||
// Lookey here | ||
// https://github.com/facebook/react/blob/0.13-stable/src/browser/ui/dom/getEventKey.js | ||
move: function move(i) { | ||
this.focusables[i].node.focus(); | ||
this.currentFocus = i; | ||
}, | ||
var ENTER = 'Enter'; | ||
exports.ENTER = ENTER; | ||
var SPACE = ' '; | ||
exports.SPACE = SPACE; | ||
var ESCAPE = 'Escape'; | ||
exports.ESCAPE = ESCAPE; | ||
var UP = 'ArrowUp'; | ||
exports.UP = UP; | ||
var DOWN = 'ArrowDown'; | ||
exports.DOWN = DOWN; | ||
var LOWEST_LETTER_CODE = 65; | ||
exports.LOWEST_LETTER_CODE = LOWEST_LETTER_CODE; | ||
var HIGHEST_LETTER_CODE = 91; | ||
exports.HIGHEST_LETTER_CODE = HIGHEST_LETTER_CODE; | ||
moveUp: function moveUp() { | ||
var next = this.currentFocus === -1 || this.currentFocus === 0 ? this.focusables.length - 1 : this.currentFocus - 1; | ||
this.move(next); | ||
}, | ||
},{}]},{},[1])(1) | ||
}); | ||
moveDown: function moveDown() { | ||
var next = this.currentFocus === -1 || this.currentFocus === this.focusables.length - 1 ? 0 : this.currentFocus + 1; | ||
this.move(next); | ||
}, | ||
moveToLetter: function moveToLetter(letter) { | ||
var cyclo = this.focusables.slice(this.currentFocus + 1).concat(this.focusables.slice(0, this.currentFocus + 1)); | ||
for (var i = 0, l = cyclo.length; i < l; i++) { | ||
var item = cyclo[i]; | ||
if (!item.text && !item.content.charAt) { | ||
throw new Error('AriaMenuButton items must have textual `content` or a `text` prop'); | ||
} | ||
if (item.text) { | ||
if (item.text.charAt(0).toLowerCase() !== letter.toLowerCase()) continue; | ||
} else if (item.content.charAt(0).toLowerCase() !== letter.toLowerCase()) continue; | ||
item.node.focus(); | ||
this.currentFocus = this.focusables.indexOf(item); | ||
return; | ||
} | ||
}, | ||
focusTrigger: function focusTrigger() { | ||
this.trigger.focus(); | ||
} | ||
}; | ||
function focusManager() { | ||
return Object.create(focusManagerProto); | ||
} | ||
module.exports = exports['default']; | ||
/***/ }, | ||
/* 5 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
'use strict'; | ||
exports.__esModule = true; | ||
exports['default'] = { | ||
init: function init(_x, namespace) { | ||
var componentName = arguments[0] === undefined ? 'AriaMenuButton' : arguments[0]; | ||
this.namespace = namespace; | ||
this.componentName = this.applyNamespace(componentName); | ||
}, | ||
componentPart: function componentPart(remainder) { | ||
if (!remainder) { | ||
return this.componentName; | ||
}return '' + this.componentName + '-' + remainder; | ||
}, | ||
applyNamespace: function applyNamespace(str) { | ||
if (!this.namespace) { | ||
return str; | ||
}return '' + this.namespace + '-' + str; | ||
} | ||
}; | ||
module.exports = exports['default']; | ||
/***/ }, | ||
/* 6 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
'use strict'; | ||
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; | ||
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; | ||
var _inherits = function (subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; | ||
exports.__esModule = true; | ||
var _React = __webpack_require__(1); | ||
var _React2 = _interopRequireWildcard(_React); | ||
var _ENTER$SPACE = __webpack_require__(2); | ||
var _cssClassnamer = __webpack_require__(5); | ||
var _cssClassnamer2 = _interopRequireWildcard(_cssClassnamer); | ||
var MenuItem = (function (_React$Component) { | ||
function MenuItem() { | ||
_classCallCheck(this, MenuItem); | ||
if (_React$Component != null) { | ||
_React$Component.apply(this, arguments); | ||
} | ||
} | ||
_inherits(MenuItem, _React$Component); | ||
MenuItem.prototype.shouldComponentUpdate = function shouldComponentUpdate(newProps) { | ||
return this.props.isSelected !== newProps.isSelected; | ||
}; | ||
MenuItem.prototype.componentDidMount = function componentDidMount() { | ||
this.props.focusManager.focusables.push({ | ||
content: this.props.content, | ||
text: this.props.text, | ||
node: _React2['default'].findDOMNode(this) | ||
}); | ||
}; | ||
MenuItem.prototype.handleClick = function handleClick(e) { | ||
var props = this.props; | ||
if (props.isSelected) { | ||
return; | ||
} // If there's no value, we'll send the label | ||
var v = typeof props.value !== 'undefined' ? props.value : props.content; | ||
props.handleSelection(v, e); | ||
}; | ||
MenuItem.prototype.handleKey = function handleKey(e) { | ||
if (e.key !== _ENTER$SPACE.ENTER && e.key !== _ENTER$SPACE.SPACE) { | ||
return; | ||
}e.preventDefault(); | ||
this.handleClick(e); | ||
}; | ||
MenuItem.prototype.render = function render() { | ||
var props = this.props; | ||
var itemClasses = [_cssClassnamer2['default'].componentPart('menuItem')]; | ||
if (props.isSelected) itemClasses.push(_cssClassnamer2['default'].applyNamespace('is-selected')); | ||
// tabindex -1 because: "With focus on the button pressing | ||
// the Tab key will take the user to the next tab focusable item on the page. | ||
// With focus on the drop-down menu, pressing the Tab key will take the user | ||
// to the next tab focusable item on the page." | ||
// "A menuitem within a menu or menubar may appear in the tab order | ||
// only if it is not within a popup menu." | ||
// ... so not in tab order, but programatically focusable | ||
return _React2['default'].createElement( | ||
'div', | ||
{ id: props.id, | ||
className: itemClasses.join(' '), | ||
onClick: this.handleClick.bind(this), | ||
onKeyDown: this.handleKey.bind(this), | ||
role: 'menuitem', | ||
tabIndex: '-1', | ||
'data-value': props.value }, | ||
props.content | ||
); | ||
}; | ||
return MenuItem; | ||
})(_React2['default'].Component); | ||
exports['default'] = MenuItem; | ||
var pt = _React2['default'].PropTypes; | ||
MenuItem.propTypes = { | ||
focusManager: pt.object.isRequired, | ||
handleSelection: pt.func.isRequired, | ||
content: pt.oneOfType([pt.string, pt.element]).isRequired, | ||
id: pt.string, | ||
isSelected: pt.bool, | ||
text: pt.string, | ||
value: pt.oneOfType([pt.string, pt.number, pt.bool]) | ||
}; | ||
module.exports = exports['default']; | ||
/***/ } | ||
/******/ ]) | ||
}); | ||
; |
@@ -1,1 +0,1 @@ | ||
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.createAriaMenuButton=e()}}(function(){return function e(t,n,o){function r(s,u){if(!n[s]){if(!t[s]){var a="function"==typeof require&&require;if(!u&&a)return a(s,!0);if(i)return i(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[s]={exports:{}};t[s][0].call(l.exports,function(e){var n=t[s][1][e];return r(n?n:e)},l,l.exports,e,t,n,o)}return n[s].exports}for(var i="function"==typeof require&&require,s=0;s<o.length;s++)r(o[s]);return r}({1:[function(e,t,n){(function(o){"use strict";function r(){var e=void 0===arguments[0]?o.React:arguments[0],t=d["default"](e),n=e.addons?e.addons.CSSTransitionGroup:!1,r=function(o){function r(e){u(this,r),o.call(this,e),this.state={isOpen:!!e.startOpen},this.focusManager=y["default"]()}return a(r,o),r.prototype.shouldComponentUpdate=function(e,t){return this.state.isOpen!==t.isOpen||this.props.selectedValue!==e.selectedValue},r.prototype.componentWillMount=function(){if(this.props.transition&&!n)throw new Error("If you want to use transitions with ariaMenuButton, you need to pass it React with addons")},r.prototype.componentDidMount=function(){this.focusManager.trigger=e.findDOMNode(this.refs.trigger)},r.prototype.openMenu=function(){var e=void 0===arguments[0]?!1:arguments[0];this.setState({isOpen:!0,innerFocus:e})},r.prototype.closeMenu=function(){var e=this,t=void 0===arguments[0]?!0:arguments[0];this.setState({isOpen:!1,innerFocus:!1},function(){t&&e.focusManager.focusTrigger(),e.focusManager.currentFocus=-1})},r.prototype.toggleMenu=function(){this.state.isOpen?this.closeMenu():this.openMenu()},r.prototype.handleAnywhereKey=function(e){var t=e.key,n=i(e);(t===p.DOWN||n)&&(e.preventDefault(),t===p.DOWN?this.state.isOpen?this.focusManager.moveDown():this.openMenu(!0):n&&this.state.isOpen&&this.checkLetterKeys(e.keyCode))},r.prototype.handleTriggerKey=function(e){var t=e.key;(t===p.ENTER||t===p.SPACE)&&(e.preventDefault(),this.toggleMenu())},r.prototype.handleMenuKey=function(e){e.key===p.ESCAPE?this.closeMenu():e.key===p.UP&&this.state.isOpen&&(e.preventDefault(),this.focusManager.moveUp())},r.prototype.checkLetterKeys=function(e){this.focusManager.moveToLetter(String.fromCharCode(e))},r.prototype.handleBlur=function(){var e=this;this.blurTimeout=setTimeout(function(){var t=document.activeElement;t!==e.focusManager.trigger&&(e.focusManager.focusables.some(function(e){return e.node===t})||e.state.isOpen&&e.closeMenu(!1))},0)},r.prototype.handleSelection=function(e){this.props.closeOnSelection&&this.closeMenu(),this.props.handleSelection(e)},r.prototype.handleOverlayClick=function(){console.log("overlay click triggered"),this.closeMenu(!1)},r.prototype.render=function(){var o=this.props,r=this.state.isOpen,i=o.id?""+o.id+"-trigger":void 0,s=o.id?""+o.id+"-outside":void 0,u="AriaMenuButton-trigger";r&&(u+=" is-open");var a=r?e.createElement(t,c({},o,{handleSelection:this.handleSelection.bind(this),receiveFocus:this.state.innerFocus,focusManager:this.focusManager})):!1,l=o.transition?e.createElement(n,{transitionName:"is",component:"div",className:"AriaMenuButton-menuWrapper AriaMenuButton-menuWrapper--trans",onKeyDown:this.handleMenuKey.bind(this)},a):e.createElement("div",{className:"AriaMenuButton-menuWrapper",onKeyDown:this.handleMenuKey.bind(this)},a),p=r?{display:"inline-block",position:"relative",zIndex:"100"}:{},f=r?e.createElement("div",{id:s,onClick:this.handleOverlayClick.bind(this),ref:"overlay",style:{cursor:"pointer",position:"fixed",top:0,bottom:0,left:0,right:0,zIndex:"99",WebkitTapHighlightColor:"rgba(0,0,0,0)"}}):!1;return e.createElement("div",{id:o.id,className:"AriaMenuButton",onKeyDown:this.handleAnywhereKey.bind(this),onBlur:this.handleBlur.bind(this)},f,e.createElement("div",{style:p},e.createElement("div",{id:i,className:u,onClick:this.toggleMenu.bind(this),onKeyDown:this.handleTriggerKey.bind(this),ref:"trigger","aria-haspopup":!0,"aria-expanded":r,role:"button",tabIndex:"0"},o.triggerContent),l))},r}(e.Component),s=e.PropTypes;return r.propTypes={handleSelection:s.func.isRequired,items:s.arrayOf(s.object).isRequired,triggerContent:s.oneOfType([s.string,s.element]).isRequired,closeOnSelection:s.bool,flushRight:s.bool,id:s.string,startOpen:s.bool,selectedValue:s.oneOfType([s.string,s.number,s.bool]),transition:s.bool},r}function i(e){return e.keyCode>=p.LOWEST_LETTER_CODE&&e.keyCode<=p.HIGHEST_LETTER_CODE}var s=function(e){return e&&e.__esModule?e:{"default":e}},u=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},a=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(e.__proto__=t)},c=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e};n.__esModule=!0,n["default"]=r;var l=e("./keys"),p=s(l),f=e("./createMenu"),d=s(f),h=e("./focusManager"),y=s(h);t.exports=n["default"]}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./createMenu":2,"./focusManager":4,"./keys":5}],2:[function(e,t,n){"use strict";function o(e){var t=c["default"](e),n=function(n){function o(){i(this,o),null!=n&&n.apply(this,arguments)}return s(o,n),o.prototype.shouldComponentUpdate=function(e){return this.props.selectedValue!==e.selectedValue},o.prototype.componentWillMount=function(){this.props.focusManager.focusables=[]},o.prototype.componentDidMount=function(){this.props.receiveFocus&&this.props.focusManager.move(0)},o.prototype.render=function(){var n=this.props,o=n.selectedValue,r=n.items.map(function(r,i){return e.createElement("li",{key:i,className:"AriaMenuButton-li",role:"presentation"},e.createElement(t,u({},r,{focusManager:n.focusManager,handleSelection:n.handleSelection,isSelected:r.value===o})))}),i="AriaMenuButton-menu";return n.flushRight&&(i+=" AriaMenuButton-menu--flushRight"),e.createElement("ol",{className:i,role:"menu"},r)},o}(e.Component),o=e.PropTypes;return n.propTypes={focusManager:o.object.isRequired,items:o.arrayOf(o.object).isRequired,flushRight:o.bool,handleSelection:o.func,receiveFocus:o.bool,selectedValue:o.any},n}var r=function(e){return e&&e.__esModule?e:{"default":e}},i=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},s=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(e.__proto__=t)},u=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e};n.__esModule=!0,n["default"]=o;var a=e("./createMenuItem"),c=r(a);t.exports=n["default"]},{"./createMenuItem":3}],3:[function(e,t,n){"use strict";function o(e){var t=function(t){function n(){r(this,n),null!=t&&t.apply(this,arguments)}return i(n,t),n.prototype.shouldComponentUpdate=function(e){return this.props.isSelected!==e.isSelected},n.prototype.componentDidMount=function(){this.props.focusManager.focusables.push({content:this.props.content,text:this.props.text,node:e.findDOMNode(this)})},n.prototype.handleClick=function(e){var t=this.props;if(!t.isSelected){var n="undefined"!=typeof t.value?t.value:t.content;t.handleSelection(n,e)}},n.prototype.handleKey=function(e){(e.key===s.ENTER||e.key===s.SPACE)&&(e.preventDefault(),this.handleClick(e))},n.prototype.render=function(){var t=this.props,n="AriaMenuButton-menuItem";return t.isSelected&&(n+=" is-selected"),e.createElement("div",{id:t.id,className:n,onClick:this.handleClick.bind(this),onKeyDown:this.handleKey.bind(this),role:"menuitem",tabIndex:"-1","data-value":t.value},t.content)},n}(e.Component),n=e.PropTypes;return t.propTypes={focusManager:n.object.isRequired,handleSelection:n.func.isRequired,content:n.oneOfType([n.string,n.element]).isRequired,id:n.string,isSelected:n.bool,text:n.string,value:n.oneOfType([n.string,n.number,n.bool])},t}var r=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},i=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(e.__proto__=t)};n.__esModule=!0,n["default"]=o;var s=e("./keys");t.exports=n["default"]},{"./keys":5}],4:[function(e,t,n){"use strict";function o(){return Object.create(r)}n.__esModule=!0,n["default"]=o;var r={focusables:[],trigger:null,currentFocus:-1,move:function(e){this.focusables[e].node.focus(),this.currentFocus=e},moveUp:function(){var e=-1===this.currentFocus||0===this.currentFocus?this.focusables.length-1:this.currentFocus-1;this.move(e)},moveDown:function(){var e=-1===this.currentFocus||this.currentFocus===this.focusables.length-1?0:this.currentFocus+1;this.move(e)},moveToLetter:function(e){for(var t=this.focusables.slice(this.currentFocus+1).concat(this.focusables.slice(0,this.currentFocus+1)),n=0,o=t.length;o>n;n++){var r=t[n];if(!r.text&&!r.content.charAt)throw new Error("AriaMenuButton items must have textual `content` or a `text` prop");if(r.text){if(r.text.charAt(0).toLowerCase()!==e.toLowerCase())continue}else if(r.content.charAt(0).toLowerCase()!==e.toLowerCase())continue;return r.node.focus(),void(this.currentFocus=this.focusables.indexOf(r))}},focusTrigger:function(){this.trigger.focus()}};t.exports=n["default"]},{}],5:[function(e,t,n){"use strict";n.__esModule=!0;var o="Enter";n.ENTER=o;var r=" ";n.SPACE=r;var i="Escape";n.ESCAPE=i;var s="ArrowUp";n.UP=s;var u="ArrowDown";n.DOWN=u;var a=65;n.LOWEST_LETTER_CODE=a;var c=91;n.HIGHEST_LETTER_CODE=c},{}]},{},[1])(1)}); | ||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports.AriaMenuButton=t(require("react")):e.AriaMenuButton=t(e.react)}(this,function(e){return function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={exports:{},id:o,loaded:!1};return e[o].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";function o(){var e=void 0===arguments[0]?{}:arguments[0],t=e.reactAddons?e.reactAddons.CSSTransitionGroup:!1;v["default"].init(e.componentName,e.namespace);var n=function(e){function n(t){s(this,n),e.call(this,t),this.state={isOpen:!!t.startOpen},this.focusManager=y["default"]()}return a(n,e),n.prototype.shouldComponentUpdate=function(e,t){return this.state.isOpen!==t.isOpen||this.props.selectedValue!==e.selectedValue},n.prototype.componentWillMount=function(){if(this.props.transition&&!t)throw new Error("If you want to use transitions with ariaMenuButton, you need to pass it React with addons")},n.prototype.componentDidMount=function(){this.focusManager.trigger=l["default"].findDOMNode(this.refs.trigger)},n.prototype.openMenu=function(){var e=void 0===arguments[0]?!1:arguments[0];this.setState({isOpen:!0,innerFocus:e})},n.prototype.closeMenu=function(){var e=this,t=void 0===arguments[0]?!0:arguments[0];this.setState({isOpen:!1,innerFocus:!1},function(){t&&e.focusManager.focusTrigger(),e.focusManager.currentFocus=-1})},n.prototype.toggleMenu=function(){this.state.isOpen?this.closeMenu():this.openMenu()},n.prototype.handleAnywhereKey=function(e){var t=e.key,n=r(e);(t===f.DOWN||n)&&(e.preventDefault(),t===f.DOWN?this.state.isOpen?this.focusManager.moveDown():this.openMenu(!0):n&&this.state.isOpen&&this.checkLetterKeys(e.keyCode))},n.prototype.handleTriggerKey=function(e){var t=e.key;(t===f.ENTER||t===f.SPACE)&&(e.preventDefault(),this.toggleMenu())},n.prototype.handleMenuKey=function(e){e.key===f.ESCAPE?this.closeMenu():e.key===f.UP&&this.state.isOpen&&(e.preventDefault(),this.focusManager.moveUp())},n.prototype.checkLetterKeys=function(e){this.focusManager.moveToLetter(String.fromCharCode(e))},n.prototype.handleBlur=function(){var e=this;this.blurTimeout=setTimeout(function(){var t=document.activeElement;t!==e.focusManager.trigger&&(e.focusManager.focusables.some(function(e){return e.node===t})||e.state.isOpen&&e.closeMenu(!1))},0)},n.prototype.handleSelection=function(e){this.props.closeOnSelection&&this.closeMenu(),this.props.handleSelection(e)},n.prototype.handleOverlayClick=function(){console.log("overlay click triggered"),this.closeMenu(!1)},n.prototype.render=function(){var e=this.props,n=this.state.isOpen,o=e.id?""+e.id+"-trigger":void 0,r=e.id?""+e.id+"-outside":void 0,i=[v["default"].componentPart("trigger")];n&&i.push(v["default"].applyNamespace("is-open"));var s=n?l["default"].createElement(h["default"],u({},e,{handleSelection:this.handleSelection.bind(this),receiveFocus:this.state.innerFocus,focusManager:this.focusManager})):!1,a=e.transition?l["default"].createElement(t,{transitionName:v["default"].applyNamespace("is"),component:"div",className:[v["default"].componentPart("menuWrapper"),v["default"].componentPart("menuWrapper--trans")].join(" "),onKeyDown:this.handleMenuKey.bind(this)},s):l["default"].createElement("div",{className:v["default"].componentPart("menuWrapper"),onKeyDown:this.handleMenuKey.bind(this)},s),c=n?{display:"inline-block",position:"relative",zIndex:"100"}:{},p=n?l["default"].createElement("div",{id:r,onClick:this.handleOverlayClick.bind(this),ref:"overlay",style:{cursor:"pointer",position:"fixed",top:0,bottom:0,left:0,right:0,zIndex:"99",WebkitTapHighlightColor:"rgba(0,0,0,0)"}}):!1;return l["default"].createElement("div",{id:e.id,className:v["default"].componentPart(),onKeyDown:this.handleAnywhereKey.bind(this),onBlur:this.handleBlur.bind(this)},p,l["default"].createElement("div",{style:c},l["default"].createElement("div",{id:o,className:i.join(" "),onClick:this.toggleMenu.bind(this),onKeyDown:this.handleTriggerKey.bind(this),ref:"trigger","aria-haspopup":!0,"aria-expanded":n,role:"button",tabIndex:"0"},e.triggerContent),a))},n}(l["default"].Component),o=l["default"].PropTypes;return n.propTypes={handleSelection:o.func.isRequired,items:o.arrayOf(o.object).isRequired,triggerContent:o.oneOfType([o.string,o.element]).isRequired,closeOnSelection:o.bool,flushRight:o.bool,id:o.string,startOpen:o.bool,selectedValue:o.oneOfType([o.string,o.number,o.bool]),transition:o.bool},n}function r(e){return e.keyCode>=f.LOWEST_LETTER_CODE&&e.keyCode<=f.HIGHEST_LETTER_CODE}var i=function(e){return e&&e.__esModule?e:{"default":e}},s=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},a=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(e.__proto__=t)},u=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e};t.__esModule=!0,t["default"]=o;var c=n(1),l=i(c),p=n(2),f=i(p),d=n(3),h=i(d),m=n(4),y=i(m),g=n(5),v=i(g);e.exports=t["default"]},function(t,n,o){t.exports=e},function(e,t,n){"use strict";t.__esModule=!0;var o="Enter";t.ENTER=o;var r=" ";t.SPACE=r;var i="Escape";t.ESCAPE=i;var s="ArrowUp";t.UP=s;var a="ArrowDown";t.DOWN=a;var u=65;t.LOWEST_LETTER_CODE=u;var c=91;t.HIGHEST_LETTER_CODE=c},function(e,t,n){"use strict";var o=function(e){return e&&e.__esModule?e:{"default":e}},r=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},i=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(e.__proto__=t)},s=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e};t.__esModule=!0;var a=n(1),u=o(a),c=n(6),l=o(c),p=n(5),f=o(p),d=function(e){function t(){r(this,t),null!=e&&e.apply(this,arguments)}return i(t,e),t.prototype.shouldComponentUpdate=function(e){return this.props.selectedValue!==e.selectedValue},t.prototype.componentWillMount=function(){this.props.focusManager.focusables=[]},t.prototype.componentDidMount=function(){this.props.receiveFocus&&this.props.focusManager.move(0)},t.prototype.render=function(){var e=this.props,t=e.selectedValue,n=e.items.map(function(n,o){return u["default"].createElement("li",{key:o,className:f["default"].componentPart("li"),role:"presentation"},u["default"].createElement(l["default"],s({},n,{focusManager:e.focusManager,handleSelection:e.handleSelection,isSelected:n.value===t})))}),o=[f["default"].componentPart("menu")];return e.flushRight&&o.push(f["default"].componentPart("menu--flushRight")),u["default"].createElement("ol",{className:o.join(" "),role:"menu"},n)},t}(u["default"].Component);t["default"]=d;var h=u["default"].PropTypes;d.propTypes={focusManager:h.object.isRequired,items:h.arrayOf(h.object).isRequired,flushRight:h.bool,handleSelection:h.func,receiveFocus:h.bool,selectedValue:h.any},e.exports=t["default"]},function(e,t,n){"use strict";function o(){return Object.create(r)}t.__esModule=!0,t["default"]=o;var r={focusables:[],trigger:null,currentFocus:-1,move:function(e){this.focusables[e].node.focus(),this.currentFocus=e},moveUp:function(){var e=-1===this.currentFocus||0===this.currentFocus?this.focusables.length-1:this.currentFocus-1;this.move(e)},moveDown:function(){var e=-1===this.currentFocus||this.currentFocus===this.focusables.length-1?0:this.currentFocus+1;this.move(e)},moveToLetter:function(e){for(var t=this.focusables.slice(this.currentFocus+1).concat(this.focusables.slice(0,this.currentFocus+1)),n=0,o=t.length;o>n;n++){var r=t[n];if(!r.text&&!r.content.charAt)throw new Error("AriaMenuButton items must have textual `content` or a `text` prop");if(r.text){if(r.text.charAt(0).toLowerCase()!==e.toLowerCase())continue}else if(r.content.charAt(0).toLowerCase()!==e.toLowerCase())continue;return r.node.focus(),void(this.currentFocus=this.focusables.indexOf(r))}},focusTrigger:function(){this.trigger.focus()}};e.exports=t["default"]},function(e,t,n){"use strict";t.__esModule=!0,t["default"]={init:function(e,t){var n=void 0===arguments[0]?"AriaMenuButton":arguments[0];this.namespace=t,this.componentName=this.applyNamespace(n)},componentPart:function(e){return e?""+this.componentName+"-"+e:this.componentName},applyNamespace:function(e){return this.namespace?""+this.namespace+"-"+e:e}},e.exports=t["default"]},function(e,t,n){"use strict";var o=function(e){return e&&e.__esModule?e:{"default":e}},r=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},i=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(e.__proto__=t)};t.__esModule=!0;var s=n(1),a=o(s),u=n(2),c=n(5),l=o(c),p=function(e){function t(){r(this,t),null!=e&&e.apply(this,arguments)}return i(t,e),t.prototype.shouldComponentUpdate=function(e){return this.props.isSelected!==e.isSelected},t.prototype.componentDidMount=function(){this.props.focusManager.focusables.push({content:this.props.content,text:this.props.text,node:a["default"].findDOMNode(this)})},t.prototype.handleClick=function(e){var t=this.props;if(!t.isSelected){var n="undefined"!=typeof t.value?t.value:t.content;t.handleSelection(n,e)}},t.prototype.handleKey=function(e){(e.key===u.ENTER||e.key===u.SPACE)&&(e.preventDefault(),this.handleClick(e))},t.prototype.render=function(){var e=this.props,t=[l["default"].componentPart("menuItem")];return e.isSelected&&t.push(l["default"].applyNamespace("is-selected")),a["default"].createElement("div",{id:e.id,className:t.join(" "),onClick:this.handleClick.bind(this),onKeyDown:this.handleKey.bind(this),role:"menuitem",tabIndex:"-1","data-value":e.value},e.content)},t}(a["default"].Component);t["default"]=p;var f=a["default"].PropTypes;p.propTypes={focusManager:f.object.isRequired,handleSelection:f.func.isRequired,content:f.oneOfType([f.string,f.element]).isRequired,id:f.string,isSelected:f.bool,text:f.string,value:f.oneOfType([f.string,f.number,f.bool])},e.exports=t["default"]}])}); |
{ | ||
"name": "react-aria-menubutton", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"description": "A fully accessible, easily themeable, React-powered menu button", | ||
@@ -24,9 +24,9 @@ "main": "index.js", | ||
"devDependencies": { | ||
"babel": "5.1.9", | ||
"babelify": "6.0.2", | ||
"browserify": "9.0.8", | ||
"babel": "5.1.10", | ||
"babel-loader": "5.0.0", | ||
"css-loader": "0.10.1", | ||
"es5-shim": "4.1.1", | ||
"eslint": "0.19.0", | ||
"eslint-plugin-react": "2.1.0", | ||
"http-server": "0.8.0", | ||
"eslint-plugin-react": "2.1.1", | ||
"imports-loader": "0.6.3", | ||
"karma": "0.12.31", | ||
@@ -37,24 +37,26 @@ "karma-cli": "0.0.4", | ||
"parallelshell": "1.1.1", | ||
"partialify": "3.1.3", | ||
"sinon": "1.14.1", | ||
"sinon": "git://github.com/cjohansen/Sinon.JS#b672042043517b9f84e14ed0fb8265126168778a", | ||
"tape": "4.0.0", | ||
"trash": "1.4.1", | ||
"uglify-js": "2.4.20", | ||
"watchify": "3.1.1" | ||
"watchify": "3.1.1", | ||
"webpack": "1.8.5", | ||
"webpack-dev-server": "1.8.0" | ||
}, | ||
"scripts": { | ||
"lint": "eslint .", | ||
"bundle-demo": "browserify -e ./demo/demo.js -o ./demo/demo-bundle.js -t [ babelify --loose ] -t partialify", | ||
"watch-demo": "watchify -d -e ./demo/demo.js -o ./demo/demo-bundle.js -v -t [ babelify --loose ] -t partialify", | ||
"demo-dev": "parallelshell 'http-server ./ -o' 'npm run watch-demo'", | ||
"bundle-test": "browserify -e ./test/index.js -t [ babelify --loose ] -o ./test/test-bundle.js", | ||
"bundle-dist": "browserify -e ./src/createAriaMenuButton.js -t [ babelify --loose ] -o ./dist/createAriaMenuButton.js --standalone createAriaMenuButton", | ||
"build-modules": "babel src --loose --out-dir dist-modules", | ||
"build-modules": "trash dist-modules/* --force && babel src --loose --out-dir dist-modules", | ||
"minify": "uglifyjs ./dist/createAriaMenuButton.js -c -m -o ./dist/createAriaMenuButton.min.js", | ||
"build": "npm run bundle-dist && npm run build-modules && npm run minify", | ||
"watch-test": "watchify -d -e ./test/index.js -t [ babelify --loose ] -o ./test/test-bundle.js -v", | ||
"bundle-demo": "webpack --config webpack.config.demo.js", | ||
"watch-demo": "webpack --config webpack.config.demo.js --watch", | ||
"demo-dev": "webpack-dev-server --config webpack.config.demo.js --watch", | ||
"watch-karma": "karma start", | ||
"bundle-test": "webpack --config webpack.config.test.js", | ||
"watch-test": "webpack --config webpack.config.test.js --watch", | ||
"test-dev": "parallelshell 'npm run watch-test' 'npm run watch-karma'", | ||
"test-single": "npm run bundle-test && karma start --single-run", | ||
"test": "npm run lint && npm run build-modules && npm run test-single" | ||
"test": "npm run lint && npm run test-single", | ||
"bundle-dist": "webpack --config webpack.config.dist.js", | ||
"build": "trash dist/* --force && npm run bundle-dist && parallelshell 'npm run build-modules' 'npm run minify'" | ||
} | ||
} |
@@ -23,9 +23,2 @@ # react-aria-menubutton [![Build Status](https://travis-ci.org/davidtheclark/react-aria-menubutton.svg?branch=master)](https://travis-ci.org/davidtheclark/react-aria-menubutton) | ||
## Dependencies | ||
- React 0.13.x | ||
If you have React exposed as a global, everything will be fine. | ||
If not (for instance, if you're using a module system), you will pass the dependency in when you call `createAriaMenuButton()`, as [documented below](#api). | ||
## Installation | ||
@@ -37,11 +30,18 @@ | ||
## Example Usage | ||
There is only one dependency: React 0.13.x. | ||
Using CommonJS: | ||
## Usage | ||
There are two ways to use this module: | ||
- with CommonJS | ||
- as a global UMD library | ||
Either way, what is exposed is the function `createAriaMenuButton([options])`, which returns the component you want, tailored with your options. | ||
Using CommonJS, for example, you can simply `require()` the module to get the factory: | ||
```js | ||
var React = require('react'); | ||
var createAriaMenuButton = require('react-aria-menubutton'); | ||
var AriaMenuButton = createAriaMenuButton(React); | ||
var AriaMenuButton = createAriaMenuButton(); | ||
@@ -59,12 +59,15 @@ React.render( | ||
Using globals: | ||
Using globals/UMD, you must do the following: | ||
- Expose React globally | ||
- Use one of the builds in the `dist/` directory | ||
For example: | ||
```html | ||
<script src="createAriaMenuButton.js"></script> | ||
<script src="react.min.js"></script> | ||
<script src="node_modules/react-aria-menu-button/dist/createAriaMenuButton.min.js"></script> | ||
<script> | ||
// Assuming React is globally available | ||
var AriaMenuButton = createAriaMenuButton(); | ||
// ... | ||
</script> | ||
``` | ||
@@ -100,2 +103,40 @@ | ||
### Customizing class names | ||
You can customize these class names in SUIT-compliant ways by passing `componentName` and `namespace` options to `createAriaMenuButton([options]). | ||
#### Specify your own component name | ||
This will replace `AriaMenuButton` in the class name with the component name of your choice. For example, if you pass `{ componentName: 'Dropdown' }`, your classes will be | ||
```css | ||
.Dropdown {} | ||
.Dropdown-trigger {} | ||
.Dropdown-trigger.is-open {} | ||
.Dropdown-menuWrapper {} | ||
/* ... and so on */ | ||
``` | ||
#### Specify your own namespace | ||
This will add you namespace to the front of every class name, including the state classes. For example, if you pass `{ namespace: 'up' }`, you classes will be | ||
```css | ||
.up-AriaMenuButton {} | ||
.up-AriaMenuButton-trigger {} | ||
.up-AriaMenuButton-trigger.up-is-open {} | ||
.up-AriaMenuButton-menuWrapper {} | ||
``` | ||
#### Specify both component name and namespace | ||
And you can, of course, specify both a component name and a namespace. Passing `{ componentName: 'Down', namespace: 'lo' }`, you'll get | ||
```css | ||
.lo-Down {} | ||
.lo-Down-trigger {} | ||
.lo-Down-trigger.lo-is-open {} | ||
.lo-Down-menuWrapper {} | ||
``` | ||
## API | ||
@@ -107,9 +148,26 @@ | ||
### createAriaMenuButton(React) | ||
### createAriaMenuButton([options]) | ||
Returns a React component, an `AriaMenuButton`, as described below. | ||
If `React` is available on the global (`window`) object, you do not have to pass them in as arguments. | ||
Otherwise, pass in the dependency to get your special button. | ||
```js | ||
/* little example */ | ||
var createAriaMenuButton = require('react-aria-menubutton'); | ||
var MySpecialButton = createAriaMenuButton({ | ||
componentName: 'MySpecialButton', | ||
namespace: 'me' | ||
}); | ||
``` | ||
#### options | ||
- **componentName**: Specify a component name for css classes. [See above](#specify-your-own-component-name). | ||
- **namespace**: Specify a namespace for css classes. [See above](#specify-your-own-namespace). | ||
- **reactAddons**: If `transition` is true — because you want to use React's CSSTransitionGroup to animate the opening and closing of the menu — you need to pass in `React.addons` here. For example, | ||
```js | ||
var React = require('react/addons'); | ||
var createAriaMenuButton = require('react-aria-menubutton'); | ||
var AriaMenuButton = createAriaMenuButton({ reactAddons: React.addons }); | ||
``` | ||
### AriaMenuButton | ||
@@ -176,2 +234,2 @@ | ||
Note this: If you want to use `transition`, the component will need access to React *with addons*, since `ReactCSSTransitionGroup` is an addon. | ||
Note this: If you want to use `transition`, the component will need access to React *with addons*, since `ReactCSSTransitionGroup` is an addon. This is done by passing `React.addons` as the option `reactAddons`, as [described above](#options). |
@@ -0,9 +1,11 @@ | ||
import React from 'react'; | ||
import * as keys from './keys'; | ||
import createMenu from './createMenu'; | ||
import Menu from './Menu'; | ||
import focusManager from './focusManager'; | ||
import cssClassnamer from './cssClassnamer'; | ||
export default function createAriaMenuButton(React=global.React) { | ||
export default function createAriaMenuButton(opts={}) { | ||
const Menu = createMenu(React); | ||
const CSSTransitionGroup = (React.addons) ? React.addons.CSSTransitionGroup : false; | ||
const CSSTransitionGroup = (opts.reactAddons) ? opts.reactAddons.CSSTransitionGroup : false; | ||
cssClassnamer.init(opts.componentName, opts.namespace); | ||
@@ -131,4 +133,4 @@ class AriaMenuButton extends React.Component { | ||
const outsideId = (props.id) ? `${props.id}-outside` : undefined; | ||
let triggerClasses = 'AriaMenuButton-trigger'; | ||
if (isOpen) triggerClasses += ' is-open'; | ||
const triggerClasses = [cssClassnamer.componentPart('trigger')]; | ||
if (isOpen) triggerClasses.push(cssClassnamer.applyNamespace('is-open')); | ||
@@ -143,5 +145,8 @@ const menu = (isOpen) ? ( | ||
const menuWrapper = (props.transition) ? ( | ||
<CSSTransitionGroup transitionName='is' | ||
<CSSTransitionGroup transitionName={cssClassnamer.applyNamespace('is')} | ||
component='div' | ||
className='AriaMenuButton-menuWrapper AriaMenuButton-menuWrapper--trans' | ||
className={[ | ||
cssClassnamer.componentPart('menuWrapper'), | ||
cssClassnamer.componentPart('menuWrapper--trans') | ||
].join(' ')} | ||
onKeyDown={this.handleMenuKey.bind(this)}> | ||
@@ -151,3 +156,3 @@ {menu} | ||
) : ( | ||
<div className='AriaMenuButton-menuWrapper' | ||
<div className={cssClassnamer.componentPart('menuWrapper')} | ||
onKeyDown={this.handleMenuKey.bind(this)}> | ||
@@ -185,3 +190,3 @@ {menu} | ||
<div id={props.id} | ||
className='AriaMenuButton' | ||
className={cssClassnamer.componentPart()} | ||
onKeyDown={this.handleAnywhereKey.bind(this)} | ||
@@ -195,3 +200,3 @@ onBlur={this.handleBlur.bind(this)}> | ||
<div id={triggerId} | ||
className={triggerClasses} | ||
className={triggerClasses.join(' ')} | ||
onClick={this.toggleMenu.bind(this)} | ||
@@ -217,2 +222,3 @@ onKeyDown={this.handleTriggerKey.bind(this)} | ||
const pt = React.PropTypes; | ||
AriaMenuButton.propTypes = { | ||
@@ -219,0 +225,0 @@ handleSelection: pt.func.isRequired, |
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
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
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
88864
27
1708
230
0
19