This commit is contained in:
176
node_modules/react-aria-menubutton/CHANGELOG.md
generated
vendored
Normal file
176
node_modules/react-aria-menubutton/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
# Changelog
|
||||
|
||||
## 7.0.3
|
||||
- Fixes `onSelection` doesn't update on prop change issue [#142](https://github.com/davidtheclark/react-aria-menubutton/issues/142)
|
||||
|
||||
## 7.0.2
|
||||
- Fix blur handler breaking due to unavailability of button
|
||||
|
||||
## 7.0.1
|
||||
- Added React v17+ in peer dependency
|
||||
|
||||
## 7.0.0
|
||||
- **Breaking:** Removed usage of `ReactDOM.findDOMNode` and `create-react-context`. This will no longer support older versions of React, it now requires `^16.3.0`
|
||||
|
||||
## 6.3.0
|
||||
- Removed usage of legacy React context API, the package now use `create-react-context` which uses new context API if available else fallsback to the legacy API.
|
||||
|
||||
## 6.2.0
|
||||
|
||||
- Bind `Home` key to jump to first item in the current menu.
|
||||
- Bind `End` key to jump to the last item in the current menu.
|
||||
- Removed use of deprecated React lifecycle methods.
|
||||
|
||||
## 6.1.0
|
||||
|
||||
- Add `closeOnBlur` prop.
|
||||
|
||||
## 6.0.1
|
||||
|
||||
- Chore: Use loose mode for Babel compilation.
|
||||
|
||||
## 6.0.0
|
||||
|
||||
- **Breaking:** Pass `disabled` attribute to `Button` component's inner element if it is a regular HTML element that supports `disabled`.
|
||||
Considered a potentially breaking (though positive) change because it may affect behavior and styling of your UI.
|
||||
|
||||
## 5.1.1
|
||||
|
||||
- Fix keydown behavior of link menu items, so Enter and Space open the link the same way a click does.
|
||||
- Make prop `onSelection` optional, because it's not necessary if your menu items are link.
|
||||
|
||||
## 5.1.0
|
||||
|
||||
- React 16 support.
|
||||
|
||||
## 5.0.2
|
||||
|
||||
- Satisfy React deprecation warnings.
|
||||
|
||||
## 5.0.1
|
||||
|
||||
- Clicks inside the menu that are not on a `MenuItem` move focus to the first `MenuItem`.
|
||||
- When the menu opens, focus only moves to the first menu item *if you opened with keyboard interactions*.
|
||||
With a mouse click on the trigger, for example, focus remains on the trigger.
|
||||
|
||||
## 5.0.0
|
||||
|
||||
- When the menu opens, move focus to the first item (by default).
|
||||
This represents a change to [the WAI-ARIA Menu Button Design Pattern](http://www.w3.org/TR/wai-aria-practices/#menubutton).
|
||||
|
||||
## 4.3.1
|
||||
|
||||
- Introduce `dist/`, where `src/` now compiles to, since React 15.5+ demands `class`es, so Babel-compilation.
|
||||
Which is actually a huge overhaul, though in semver it's just a patch.
|
||||
|
||||
## 4.3.0
|
||||
|
||||
- Add `onMenuToggle` prop to `Wrapper`.
|
||||
|
||||
## 4.2.0
|
||||
|
||||
- Use `ownerDocument` instead of `document.documentElement` in case this is used in an iframe.
|
||||
- Rewrite test suite using Jest.
|
||||
|
||||
## 4.1.3
|
||||
|
||||
- Fix UMD build.
|
||||
|
||||
## 4.1.2
|
||||
|
||||
- Allow React 15 as a `peerDependency`.
|
||||
|
||||
## 4.1.1
|
||||
|
||||
- Update UMD build.
|
||||
|
||||
## 4.1.0
|
||||
|
||||
- Add `openMenu()` and `closeMenu()` to API.
|
||||
- Improve (fix) UMD build.
|
||||
- Allow arbitrary props to pass through to Button, Menu, MenuItem, and Wrapper elements.
|
||||
|
||||
## 4.0.2
|
||||
|
||||
- Move `react` and `react-dom` to peer dependencies.
|
||||
|
||||
## 4.0.1
|
||||
|
||||
- Update `focus-group` due to important fix there.
|
||||
|
||||
## 4.0.0
|
||||
|
||||
- Use `focus-group` for focus management, which includes improving letter navigation.
|
||||
- Switch from `tap.js` to `teeny-tap`.
|
||||
- Move UMD build to `umd/` directory that is only distributed with the npm package (available on unpkg).
|
||||
|
||||
## 3.1.0
|
||||
|
||||
- Add `disabled` prop to `Button`.
|
||||
|
||||
## 3.0.0
|
||||
|
||||
- Upgrade to React 0.14.
|
||||
- Use React's `context` to simplify API.
|
||||
- Add `<Wrapper>` component (replacing the need for the factory function `ariaMenuButton()`).
|
||||
- Add `style` prop to all components.
|
||||
|
||||
## 2.0.4 and 2.0.5
|
||||
|
||||
- Better cleanup of Tap.js listeners.
|
||||
- Key code 91 is not a letter so I should stop treating it like one.
|
||||
|
||||
## 2.0.2 and 2.0.3
|
||||
|
||||
- Avoid presuming that `document` exists, to avoid breaking `React.renderToString()`.
|
||||
|
||||
## 2.0.1
|
||||
|
||||
- Allow for the case that selecting a menu item unmounts the menu (mostly by manager timers more intelligently).
|
||||
|
||||
## 2.0.0
|
||||
|
||||
- Ignore letter key presses if the letter is paired with `alt`, `ctrl`, or `meta` keys.
|
||||
- Use [tap.js](https://github.com/alexgibson/tap.js) to improve click-outside-closes behavior: no overlay required anymore, meaning that a click outside can *both* close the menu *and* do something else — with both mouse and touch events.
|
||||
|
||||
## 1.1.0
|
||||
|
||||
- Allow objects as MenuItem `value`s.
|
||||
|
||||
## 1.0.0
|
||||
|
||||
- Nothing really: it was just time to start the real versioning.
|
||||
|
||||
## 0.8.0
|
||||
- Overlay to enable close-when-clicking-outside for mobile.
|
||||
|
||||
## 0.7.0
|
||||
- New, more flexible API: provided components are just wrappers around whatever elements they're given.
|
||||
|
||||
## 0.6.0
|
||||
- Pass `event` to `handleSelection`.
|
||||
|
||||
## 0.5.2
|
||||
- Add keywords to `package.json`.
|
||||
|
||||
## 0.5.1
|
||||
- Update build.
|
||||
|
||||
## 0.5.0
|
||||
- Make class names a little more explicit (change `menuWrapper--trans` to `menuWrapper--transition` and `li` to `menuItemWrapper`).
|
||||
- Add `transition` option to factory and remove `transition` prop from component.
|
||||
|
||||
## 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
|
||||
- Remove `classnames` dependency.
|
||||
|
||||
## 0.2.0
|
||||
- Add `dist-modules` for modular consumption.
|
||||
- Upgrade dependencies.
|
||||
|
||||
## 0.1.0
|
||||
- Initial release.
|
||||
22
node_modules/react-aria-menubutton/CODE_OF_CONDUCT.md
generated
vendored
Normal file
22
node_modules/react-aria-menubutton/CODE_OF_CONDUCT.md
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
||||
|
||||
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery
|
||||
* Personal attacks
|
||||
* Trolling or insulting/derogatory comments
|
||||
* Public or private harassment
|
||||
* Publishing other's private information, such as physical or electronic addresses, without explicit permission
|
||||
* Other unethical or unprofessional conduct.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
|
||||
|
||||
This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
|
||||
21
node_modules/react-aria-menubutton/LICENSE
generated
vendored
Normal file
21
node_modules/react-aria-menubutton/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2016 David Clark
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
382
node_modules/react-aria-menubutton/README.md
generated
vendored
Normal file
382
node_modules/react-aria-menubutton/README.md
generated
vendored
Normal file
@@ -0,0 +1,382 @@
|
||||
# react-aria-menubutton [](https://travis-ci.org/davidtheclark/react-aria-menubutton)
|
||||
|
||||
A React component (set of components, really) that will help you build accessible menu buttons by providing keyboard interactions and ARIA attributes aligned with [the WAI-ARIA Menu Button Design Pattern](http://www.w3.org/TR/wai-aria-practices/#menubutton).
|
||||
|
||||
Please check out [the demo](https://davidtheclark.github.io/react-aria-menubutton/demo/).
|
||||
|
||||
## Project Goals
|
||||
|
||||
- Full accessibility
|
||||
- Maximum flexibility
|
||||
- Absolutely minimal styling
|
||||
- Thorough testing
|
||||
- Useful modularity
|
||||
|
||||
"Useful modularity" means that when it makes sense, chunks of lower-level code that solve specific problems are split off into vanilla JS, framework-agnostic modules that could be shared with other similar projects (e.g. a menu button for Angular or Ember).
|
||||
|
||||
For this library I was able to split off:
|
||||
|
||||
- [focus-group](//github.com/davidtheclark/focus-group)
|
||||
- [teeny-tap](//github.com/davidtheclark/teeny-tap)
|
||||
|
||||
*If you like this kind of module (accessible, flexible, unstyled, with framework-agnostic low-level modules) you should also check out these projects:*
|
||||
- [react-aria-modal](https://github.com/davidtheclark/react-aria-modal)
|
||||
- [react-aria-tabpanel](https://github.com/davidtheclark/react-aria-tabpanel)
|
||||
|
||||
### Accessibility
|
||||
|
||||
The project started as an effort to build a React component that follows every detail of [the WAI-ARIA Menu Button Design Pattern](http://www.w3.org/TR/wai-aria-practices/#menubutton) for **maximum accessibility**.
|
||||
|
||||
Just hiding and showing a menu is easy; but the required **keyboard interactions** are kind of tricky, the required **ARIA attributes** are easy to forget, and some other aspects of opening and closing the menu based on behaviors, and managing focus, proved less than pleasant.
|
||||
So I decided to try to abstract the component enough that it would be **worth sharing with others**.
|
||||
|
||||
**If you think that this component could be even more accessible, please file an issue.**
|
||||
|
||||
|
||||
### Letter Navigation
|
||||
|
||||
When focus is on the menu button or within the menu and you type a letter key, a search begins. Focus will move to the first item that starts with the letter you typed; but if you continue to type more letters, the search string extends and the focus becomes more accurate.
|
||||
|
||||
So if you type `f` focus might arrive at `farm`; but then if you keep typing until you've typed `foo`, focus will skip ahead (past `farm` and `fit` and `fog`) to `foot`. This significantly improves your ability to type your way to your intended selection.
|
||||
|
||||
This keyboard interaction (as well as the <kbd>home</kbd>, <kbd>end</kbd>, and arrow keys) is enabled by the module [focus-group](//github.com/davidtheclark/focus-group). You can read more about the way letter navigation works [in that documentation](//github.com/davidtheclark/focus-group#string-searching).
|
||||
|
||||
(In 3.x.x, when you typed a letter key focus moved to the next item in the menu (i.e. after the current focused item) that started with that letter, looping around to the front if if reached the end. This was more or less the suggested behavior from the ARIA suggestion and what I saw in jQuery UI. But I think the UX was insufficient, so when I separated out the letter navigation into the module [focus-group](//github.com/davidtheclark/focus-group), I tried to *improve letter navigation by more closely mimicking native `<select>` menus.)
|
||||
|
||||
Please file an issue if anything is unclear or doesn't work as expected.
|
||||
|
||||
### Flexibility and minimal styling
|
||||
|
||||
Instead of providing a pre-fabricated, fully styled widget, this module's goal is to provide a set of components that others can build their own stuff on top of.
|
||||
|
||||
It does not provide any classes or a stylesheet that you'll have to figure out how to include; and it does not include inline styles that would be hard to override. It **only provides "smart" components to wrap your (dumb, styled) components**. The *library's* components take care of keyboard interaction and ARIA attributes, while *your* components just do whatever you want your components to do.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
npm install react-aria-menubutton
|
||||
```
|
||||
|
||||
The modular approach of this library means you're much better off building it into your code with a module bundling system like browserify or webpack.
|
||||
|
||||
But if you need a UMD version (which will include `focus-group` and `teeny-tap` in the bundle, but of course not `React` or `ReactDOM`), you can get it via npmcdm at `https://unpkg.com/react-aria-menubutton@[version-of-choice]/umd/ReactAriaMenuButton.js`.
|
||||
If you don't know about unpkg, [read about it here](https://unpkg.com).
|
||||
|
||||
## Browser Support
|
||||
|
||||
Basically IE9+.
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const AriaMenuButton = require('react-aria-menubutton');
|
||||
|
||||
// Now use AriaMenuButton.Wrapper, AriaMenuButton.Button,
|
||||
// AriaMenuButton.Menu, and AriaMenuButton.MenuItem ...
|
||||
|
||||
// ... or with es2015
|
||||
import { Button, Wrapper, Menu, MenuItem } from 'react-aria-menubutton';
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
For details about why the examples work, read the API documentation below.
|
||||
|
||||
You can also see more examples by looking in `demo/`.
|
||||
|
||||
```js
|
||||
// Very simple ES2015 example
|
||||
|
||||
import React from 'react';
|
||||
import { Wrapper, Button, Menu, MenuItem } from 'react-aria-menubutton';
|
||||
|
||||
const menuItemWords = ['foo', 'bar', 'baz'];
|
||||
|
||||
class MyMenuButton extends React.Component {
|
||||
render() {
|
||||
const menuItems = menuItemWords.map((word, i) => {
|
||||
return (
|
||||
<li key={i}>
|
||||
<MenuItem className='MyMenuButton-menuItem'>
|
||||
{word}
|
||||
</MenuItem>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<Wrapper
|
||||
className='MyMenuButton'
|
||||
onSelection={handleSelection}
|
||||
>
|
||||
<Button className='MyMenuButton-button'>
|
||||
click me
|
||||
</Button>
|
||||
<Menu className='MyMenuButton-menu'>
|
||||
<ul>{menuItems}</ul>
|
||||
</Menu>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function handleSelection(value, event) { .. }
|
||||
```
|
||||
|
||||
```js
|
||||
// Slightly more complex, ES5 example:
|
||||
// - MenuItems have hidden values that are passed
|
||||
// to the selection handler
|
||||
// - User can navigate the MenuItems by typing the
|
||||
// first letter of a person's name, even though
|
||||
// each MenuItem's child is not simple text
|
||||
// - Menu has a function for a child
|
||||
// - React's CSSTransitionGroup is used for open-close animation
|
||||
|
||||
var React = require('react');
|
||||
var CSSTransitionGroup = require('react-transition-group/CSSTransitionGroup');
|
||||
var AriaMenuButton = require('react-aria-menubutton');
|
||||
|
||||
var people = [{
|
||||
name: 'Charles Choo-Choo',
|
||||
id: 1242
|
||||
}, {
|
||||
name: 'Mina Meowmers',
|
||||
id: 8372
|
||||
}, {
|
||||
name: 'Susan Sailor',
|
||||
id: 2435
|
||||
}];
|
||||
|
||||
var MyMenuButton = React.createClass({
|
||||
render: function() {
|
||||
var peopleMenuItems = people.map(function(person, i) {
|
||||
return (
|
||||
<AriaMenuButton.MenuItem
|
||||
key={i}
|
||||
tag='li'
|
||||
value={person.id}
|
||||
text={person.name}
|
||||
className='PeopleMenu-person'
|
||||
>
|
||||
<div className='PeopleMenu-personPhoto'>
|
||||
<img src={'/people/pictures/' + person.id + '.jpg'}/ >
|
||||
</div>
|
||||
<div className='PeopleMenu-personName'>
|
||||
{person.name}
|
||||
</div>
|
||||
</AriaMenuButton.MenuItem>
|
||||
);
|
||||
});
|
||||
|
||||
var peopleMenuInnards = function(menuState) {
|
||||
var menu = (!menuState.isOpen) ? false : (
|
||||
<div
|
||||
className='PeopleMenu-menu'
|
||||
key='menu'
|
||||
>
|
||||
{peopleMenuItems}
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<CSSTransitionGroup transitionName='people'>
|
||||
{menu}
|
||||
</CSSTransitionGroup>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<AriaMenuButton.Wrapper
|
||||
className='PeopleMenu'
|
||||
onSelection={handleSelection}
|
||||
style={{ marginTop: 20 }}
|
||||
>
|
||||
<AriaMenuButton.Button className='PeopleMenu-trigger'>
|
||||
<span className='PeopleMenu-triggerText'>
|
||||
Select a person
|
||||
</span>
|
||||
<span className='PeopleMenu-triggerIcon' />
|
||||
</AriaMenuButton.Button>
|
||||
<AriaMenuButton.Menu>
|
||||
{peopleMenuInnards}
|
||||
</AriaMenuButton.Menu>
|
||||
</AriaMenuButton.Wrapper>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
function handleSelection(value, event) { .. }
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
The module exposes four components: `Wrapper`, `Button`, `Menu`, and `MenuItem`. Each of these is documented below.
|
||||
|
||||
**`Button`, `Menu`, and `MenuItem` must always be wrapped in a `Wrapper`.**
|
||||
|
||||
### `Wrapper`
|
||||
|
||||
A simple component to group a `Button`/`Menu`/`MenuItem` set, coordinating their interactions.
|
||||
*It should wrap your entire menu button widget.*
|
||||
|
||||
All `Button`, `Menu`, and `MenuItem` components *must* be nested within a `Wrapper` component.
|
||||
|
||||
Each wrapper can contain *only one* `Button`, *only one* `Menu`, and *multiple* `MenuItem`s.
|
||||
|
||||
#### props
|
||||
|
||||
All props are optional.
|
||||
|
||||
**onSelection** { Function }: A callback to run when the user makes a selection (i.e. clicks or presses Enter or Space on a `MenuItem`). It will be passed the `value` of the selected `MenuItem` and the React SyntheticEvent. *You should definitely use this prop, unless your menu items are anchor elements.*
|
||||
|
||||
```js
|
||||
<Wrapper onSelection={handleSelection} />
|
||||
|
||||
// ...
|
||||
|
||||
function handleSelection(value, event) {
|
||||
event.stopPropagation;
|
||||
console.log(value);
|
||||
}
|
||||
```
|
||||
|
||||
**onMenuToggle** { Function }: A callback to run when the menu is opened or closed. It will be passed the the following menu-state object:
|
||||
|
||||
```js
|
||||
{
|
||||
isOpen: Boolean // whether or not the menu is open
|
||||
}
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
const Example extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
isOpen: false,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const openClass = this.state.isOpen ? 'open' : '';
|
||||
|
||||
return (
|
||||
<Wrapper
|
||||
className={`${openClass}`}
|
||||
onMenuToggle={({ isOpen }) => { this.setState({ isOpen })}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**closeOnSelection** { Boolean }: By default, it *does* automatically close. If `false`, the menu will *not* automatically close when a selection is made. Default: `true`.
|
||||
|
||||
**closeOnBlur** { Boolean }: By default, it *does* automatically close. If `false`, the menu will *not* automatically close when it blurs. Default: `true`.
|
||||
|
||||
**tag** { String }: The HTML tag for this element. Default: `'div'`.
|
||||
|
||||
### `Button`
|
||||
|
||||
A React component to wrap the content of your menu-button-pattern's button.
|
||||
|
||||
The `Button` component itself acts as a UI button (with tab-index, role, etc.), so you probably do not want to pass an HTML `<button>` element as its child.
|
||||
|
||||
Each `Button` must be wrapped in a `Wrapper`, and each `Wrapper` can wrap only one `Button`.
|
||||
|
||||
#### props
|
||||
|
||||
All props are optional.
|
||||
|
||||
**disabled** { Boolean }: If `true`, the element is disabled (`aria-disabled='true'`, not in tab order, clicking has no effect).
|
||||
|
||||
**tag** { String }: The HTML tag for this element. Default: `'span'` so styling across browsers is consistent, `button` is a good alternative if styling for that element is no issue.
|
||||
|
||||
*Any additional props (e.g. `id`, `className`, `data-whatever`) are passed directly to the HTML element.*
|
||||
|
||||
### `Menu`
|
||||
|
||||
A React component to wrap the content of your menu-button-pattern's menu.
|
||||
|
||||
A `Menu`'s child may be one of the following:
|
||||
|
||||
- a React element, which will mount when the menu is open and unmount when the menu closes
|
||||
- a function accepting the following menu-state object
|
||||
|
||||
```js
|
||||
{
|
||||
isOpen: Boolean // whether or not the menu is open
|
||||
}
|
||||
```
|
||||
|
||||
Each `Menu` must be wrapped in a `Wrapper`, and each `Wrapper` can wrap only one `Menu`.
|
||||
|
||||
#### props
|
||||
|
||||
All props are optional.
|
||||
|
||||
**tag** { String }: The HTML tag for this element. Default: `'span'`.
|
||||
|
||||
*Any additional props (e.g. `id`, `className`, `data-whatever`) are passed directly to the HTML element.*
|
||||
|
||||
### `MenuItem`
|
||||
|
||||
A React component to wrap the content of one of your menu-button-pattern's menu items.
|
||||
|
||||
Each `MenuItem` must be wrapped in a `Wrapper`, and each `Wrapper` can wrap multiple `MenuItem`s.
|
||||
|
||||
When a `MenuItem` is *selected* (by clicking or focusing and hitting Enter or Space), it calls the `onSelection` handler you passed `ariaMenuButton` when creating this set of components.
|
||||
|
||||
It passes that handler a *value* and the *event*. The value it passes is determined as follows:
|
||||
|
||||
- If the `MenuItem` has a `value` prop, that is passed.
|
||||
- If the `MenuItem` has no `value` prop, the component's child is passed (so it better be simple text!).
|
||||
|
||||
When the menu is open and the user hits a letter key, focus moves to the next `MenuItem` whose "text" starts with that letter. The `MenuItem`'s relevant "text" is determined as follows:
|
||||
|
||||
- If the `MenuItem` has a `text` prop, that is used.
|
||||
- If the `MenuItem` has no `text` prop, the component's child is used (so it better be simple text!).
|
||||
|
||||
#### props
|
||||
|
||||
All props are optional.
|
||||
|
||||
**text** { String } *Required if child is an element*: If `text` has a value, its first letter will be the letter a user can type to navigate to that item.
|
||||
|
||||
**value** { Any }: *Required if child is an element.* If `value` has a value, it will be passed to the `onSelection` handler when the `MenuItem` is selected.
|
||||
|
||||
**tag** { String }: The HTML tag for this element. Default: `'span'`.
|
||||
|
||||
*Any additional props (e.g. `id`, `className`, `data-whatever`) are passed directly to the DOM element.*
|
||||
|
||||
### openMenu(wrapperId[, openOptions])
|
||||
|
||||
Open a modal programmatically.
|
||||
|
||||
*For this to work, you must provide an `id` prop to the `Wrapper` of the menu.* That `id` should be your first argument to `openMenu()`.
|
||||
|
||||
These are the `openOptions`:
|
||||
|
||||
- **focusMenu** { Boolean }: If `true`, the menu's first item will receive focus when the menu opens. Default: `true`.
|
||||
|
||||
### closeMenu(wrapperId[, closeOptions])
|
||||
|
||||
Close a modal programmatically.
|
||||
|
||||
*For this to work, you must provide an `id` prop to the `Wrapper` of the menu.* That `id` should be your first argument to `closeMenu()`.
|
||||
|
||||
These are the `closeOptions`:
|
||||
|
||||
- **focusButton** { Boolean }: If `true`, the widget's button will receive focus when the menu closes. Default: `false`.
|
||||
|
||||
## Contributing & Development
|
||||
|
||||
Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
|
||||
|
||||
Lint with `npm run lint`.
|
||||
|
||||
Test with `npm run test-dev`. A browser should open; look at the console log for TAP output.
|
||||
140
node_modules/react-aria-menubutton/dist/Button.js
generated
vendored
Normal file
140
node_modules/react-aria-menubutton/dist/Button.js
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
'use strict';
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
||||
|
||||
function _inherits(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) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
||||
|
||||
var React = require('react');
|
||||
var PropTypes = require('prop-types');
|
||||
var ManagerContext = require('./ManagerContext');
|
||||
|
||||
var _require = require("./propTypes"),
|
||||
refType = _require.refType;
|
||||
|
||||
var specialAssign = require('./specialAssign');
|
||||
|
||||
var checkedProps = {
|
||||
ambManager: PropTypes.object.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
disabled: PropTypes.bool,
|
||||
forwardedRef: refType,
|
||||
tag: PropTypes.string
|
||||
};
|
||||
|
||||
// List retrieved from https://www.w3schools.com/tags/att_disabled.asp
|
||||
var disabledSupportedTags = function disabledSupportedTags() {
|
||||
return ['button', 'fieldset', 'input', 'optgroup', 'option', 'select', 'textarea'];
|
||||
};
|
||||
|
||||
var AriaMenuButtonButton = function (_React$Component) {
|
||||
_inherits(AriaMenuButtonButton, _React$Component);
|
||||
|
||||
function AriaMenuButtonButton() {
|
||||
var _temp, _this, _ret;
|
||||
|
||||
_classCallCheck(this, AriaMenuButtonButton);
|
||||
|
||||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
|
||||
args[_key] = arguments[_key];
|
||||
}
|
||||
|
||||
return _ret = (_temp = (_this = _possibleConstructorReturn(this, _React$Component.call.apply(_React$Component, [this].concat(args))), _this), _this.ref = React.createRef(), _this.handleKeyDown = function (event) {
|
||||
if (_this.props.disabled) return;
|
||||
|
||||
var ambManager = _this.props.ambManager;
|
||||
|
||||
switch (event.key) {
|
||||
case 'ArrowDown':
|
||||
event.preventDefault();
|
||||
if (!ambManager.isOpen) {
|
||||
ambManager.openMenu();
|
||||
} else {
|
||||
ambManager.focusItem(0);
|
||||
}
|
||||
break;
|
||||
case 'Enter':
|
||||
case ' ':
|
||||
event.preventDefault();
|
||||
ambManager.toggleMenu();
|
||||
break;
|
||||
case 'Escape':
|
||||
ambManager.handleMenuKey(event);
|
||||
break;
|
||||
default:
|
||||
// (Potential) letter keys
|
||||
ambManager.handleButtonNonArrowKey(event);
|
||||
}
|
||||
}, _this.handleClick = function () {
|
||||
if (_this.props.disabled) return;
|
||||
_this.props.ambManager.toggleMenu({}, { focusMenu: false });
|
||||
}, _this.setRef = function (instance) {
|
||||
_this.ref.current = instance;
|
||||
if (typeof _this.props.forwardedRef === "function") {
|
||||
_this.props.forwardedRef(instance);
|
||||
} else if (_this.props.forwardedRef) {
|
||||
_this.props.forwardedRef.current = instance;
|
||||
}
|
||||
}, _temp), _possibleConstructorReturn(_this, _ret);
|
||||
}
|
||||
|
||||
AriaMenuButtonButton.prototype.componentDidMount = function componentDidMount() {
|
||||
this.props.ambManager.button = this;
|
||||
};
|
||||
|
||||
AriaMenuButtonButton.prototype.componentWillUnmount = function componentWillUnmount() {
|
||||
this.props.ambManager.destroy();
|
||||
};
|
||||
|
||||
AriaMenuButtonButton.prototype.render = function render() {
|
||||
var props = this.props;
|
||||
var ambManager = this.props.ambManager;
|
||||
|
||||
var buttonProps = {
|
||||
// "The menu button itself has a role of button."
|
||||
role: 'button',
|
||||
tabIndex: props.disabled ? '' : '0',
|
||||
// "The menu button has an aria-haspopup property, set to true."
|
||||
'aria-haspopup': true,
|
||||
'aria-expanded': ambManager.isOpen,
|
||||
'aria-disabled': props.disabled,
|
||||
onKeyDown: this.handleKeyDown,
|
||||
onClick: this.handleClick
|
||||
};
|
||||
|
||||
var reserved = {};
|
||||
specialAssign(reserved, checkedProps);
|
||||
// The disabled property should be passed down to the Button element
|
||||
// if the tag has support for disabled attribute. So it needs to be removed
|
||||
// from the reserved property object
|
||||
if (disabledSupportedTags().indexOf(props.tag) >= 0) {
|
||||
delete reserved.disabled;
|
||||
}
|
||||
if (ambManager.options.closeOnBlur) {
|
||||
buttonProps.onBlur = ambManager.handleBlur;
|
||||
}
|
||||
specialAssign(buttonProps, props, reserved);
|
||||
specialAssign(buttonProps, { ref: this.setRef });
|
||||
|
||||
return React.createElement(props.tag, buttonProps, props.children);
|
||||
};
|
||||
|
||||
return AriaMenuButtonButton;
|
||||
}(React.Component);
|
||||
|
||||
AriaMenuButtonButton.propTypes = checkedProps;
|
||||
AriaMenuButtonButton.defaultProps = { tag: 'span' };
|
||||
|
||||
|
||||
module.exports = React.forwardRef(function (props, ref) {
|
||||
return React.createElement(ManagerContext.Consumer, null, function (ambManager) {
|
||||
var buttonProps = { ambManager: ambManager, forwardedRef: ref };
|
||||
specialAssign(buttonProps, props, {
|
||||
ambManager: checkedProps.ambManager,
|
||||
children: checkedProps.children,
|
||||
forwardedRef: checkedProps.forwardedRef
|
||||
});
|
||||
return React.createElement(AriaMenuButtonButton, buttonProps, props.children);
|
||||
});
|
||||
});
|
||||
7
node_modules/react-aria-menubutton/dist/ManagerContext.js
generated
vendored
Normal file
7
node_modules/react-aria-menubutton/dist/ManagerContext.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
|
||||
var AriaMenuButtonManagerContext = React.createContext();
|
||||
|
||||
module.exports = AriaMenuButtonManagerContext;
|
||||
131
node_modules/react-aria-menubutton/dist/Menu.js
generated
vendored
Normal file
131
node_modules/react-aria-menubutton/dist/Menu.js
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
'use strict';
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
||||
|
||||
function _inherits(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) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
||||
|
||||
var React = require('react');
|
||||
var PropTypes = require('prop-types');
|
||||
var createTapListener = require('teeny-tap');
|
||||
var ManagerContext = require('./ManagerContext');
|
||||
|
||||
var _require = require("./propTypes"),
|
||||
refType = _require.refType;
|
||||
|
||||
var specialAssign = require('./specialAssign');
|
||||
|
||||
var checkedProps = {
|
||||
ambManager: PropTypes.object.isRequired,
|
||||
children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired,
|
||||
forwardedRef: refType,
|
||||
tag: PropTypes.string
|
||||
};
|
||||
|
||||
var AriaMenuButtonMenu = function (_React$Component) {
|
||||
_inherits(AriaMenuButtonMenu, _React$Component);
|
||||
|
||||
function AriaMenuButtonMenu() {
|
||||
var _temp, _this, _ret;
|
||||
|
||||
_classCallCheck(this, AriaMenuButtonMenu);
|
||||
|
||||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
|
||||
args[_key] = arguments[_key];
|
||||
}
|
||||
|
||||
return _ret = (_temp = (_this = _possibleConstructorReturn(this, _React$Component.call.apply(_React$Component, [this].concat(args))), _this), _this.ref = React.createRef(), _this.addTapListener = function () {
|
||||
var el = _this.ref.current;
|
||||
if (!el) return;
|
||||
var doc = el.ownerDocument;
|
||||
if (!doc) return;
|
||||
_this.tapListener = createTapListener(doc.documentElement, _this.handleTap);
|
||||
}, _this.handleTap = function (event) {
|
||||
if (_this.ref.current.contains(event.target)) return;
|
||||
if (_this.props.ambManager.button.ref.current.contains(event.target)) return;
|
||||
_this.props.ambManager.closeMenu();
|
||||
}, _this.setRef = function (instance) {
|
||||
_this.ref.current = instance;
|
||||
if (typeof _this.props.forwardedRef === "function") {
|
||||
_this.props.forwardedRef(instance);
|
||||
} else if (_this.props.forwardedRef) {
|
||||
_this.props.forwardedRef.current = instance;
|
||||
}
|
||||
}, _temp), _possibleConstructorReturn(_this, _ret);
|
||||
}
|
||||
|
||||
AriaMenuButtonMenu.prototype.componentDidMount = function componentDidMount() {
|
||||
this.props.ambManager.menu = this;
|
||||
};
|
||||
|
||||
AriaMenuButtonMenu.prototype.componentDidUpdate = function componentDidUpdate() {
|
||||
var ambManager = this.props.ambManager;
|
||||
if (!ambManager.options.closeOnBlur) return;
|
||||
if (ambManager.isOpen && !this.tapListener) {
|
||||
this.addTapListener();
|
||||
} else if (!ambManager.isOpen && this.tapListener) {
|
||||
this.tapListener.remove();
|
||||
delete this.tapListener;
|
||||
}
|
||||
|
||||
if (!ambManager.isOpen) {
|
||||
// Clear the ambManager's items, so they
|
||||
// can be reloaded next time this menu opens
|
||||
ambManager.clearItems();
|
||||
}
|
||||
};
|
||||
|
||||
AriaMenuButtonMenu.prototype.componentWillUnmount = function componentWillUnmount() {
|
||||
if (this.tapListener) this.tapListener.remove();
|
||||
this.props.ambManager.destroy();
|
||||
};
|
||||
|
||||
AriaMenuButtonMenu.prototype.render = function render() {
|
||||
var props = this.props;
|
||||
var ambManager = this.props.ambManager;
|
||||
|
||||
var childrenToRender = function () {
|
||||
if (typeof props.children === 'function') {
|
||||
return props.children({ isOpen: ambManager.isOpen });
|
||||
}
|
||||
if (ambManager.isOpen) return props.children;
|
||||
return false;
|
||||
}();
|
||||
|
||||
if (!childrenToRender) return false;
|
||||
|
||||
var menuProps = {
|
||||
onKeyDown: ambManager.handleMenuKey,
|
||||
role: 'menu',
|
||||
tabIndex: -1
|
||||
};
|
||||
|
||||
if (ambManager.options.closeOnBlur) {
|
||||
menuProps.onBlur = ambManager.handleBlur;
|
||||
}
|
||||
|
||||
specialAssign(menuProps, props, checkedProps);
|
||||
specialAssign(menuProps, { ref: this.setRef });
|
||||
|
||||
return React.createElement(props.tag, menuProps, childrenToRender);
|
||||
};
|
||||
|
||||
return AriaMenuButtonMenu;
|
||||
}(React.Component);
|
||||
|
||||
AriaMenuButtonMenu.propTypes = checkedProps;
|
||||
AriaMenuButtonMenu.defaultProps = { tag: 'div' };
|
||||
|
||||
|
||||
module.exports = React.forwardRef(function (props, ref) {
|
||||
return React.createElement(ManagerContext.Consumer, null, function (ambManager) {
|
||||
var buttonProps = { ambManager: ambManager, forwardedRef: ref };
|
||||
specialAssign(buttonProps, props, {
|
||||
ambManager: checkedProps.ambManager,
|
||||
children: checkedProps.children,
|
||||
forwardedRef: checkedProps.forwardedRef
|
||||
});
|
||||
return React.createElement(AriaMenuButtonMenu, buttonProps, props.children);
|
||||
});
|
||||
});
|
||||
96
node_modules/react-aria-menubutton/dist/MenuItem.js
generated
vendored
Normal file
96
node_modules/react-aria-menubutton/dist/MenuItem.js
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
'use strict';
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
||||
|
||||
function _inherits(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) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
||||
|
||||
var React = require('react');
|
||||
var PropTypes = require('prop-types');
|
||||
var ManagerContext = require('./ManagerContext');
|
||||
|
||||
var _require = require("./propTypes"),
|
||||
refType = _require.refType;
|
||||
|
||||
var specialAssign = require('./specialAssign');
|
||||
|
||||
var checkedProps = {
|
||||
ambManager: PropTypes.object.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
forwardedRef: refType,
|
||||
tag: PropTypes.string,
|
||||
text: PropTypes.string,
|
||||
value: PropTypes.any
|
||||
};
|
||||
|
||||
var AriaMenuButtonMenuItem = function (_React$Component) {
|
||||
_inherits(AriaMenuButtonMenuItem, _React$Component);
|
||||
|
||||
function AriaMenuButtonMenuItem() {
|
||||
var _temp, _this, _ret;
|
||||
|
||||
_classCallCheck(this, AriaMenuButtonMenuItem);
|
||||
|
||||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
|
||||
args[_key] = arguments[_key];
|
||||
}
|
||||
|
||||
return _ret = (_temp = (_this = _possibleConstructorReturn(this, _React$Component.call.apply(_React$Component, [this].concat(args))), _this), _this.ref = React.createRef(), _this.handleKeyDown = function (event) {
|
||||
if (event.key !== 'Enter' && event.key !== ' ') return;
|
||||
if (_this.props.tag === 'a' && _this.props.href) return;
|
||||
event.preventDefault();
|
||||
_this.selectItem(event);
|
||||
}, _this.selectItem = function (event) {
|
||||
// If there's no value, we'll send the child
|
||||
var value = typeof _this.props.value !== 'undefined' ? _this.props.value : _this.props.children;
|
||||
_this.props.ambManager.handleSelection(value, event);
|
||||
}, _this.setRef = function (instance) {
|
||||
_this.ref.current = instance;
|
||||
if (typeof _this.props.forwardedRef === "function") {
|
||||
_this.props.forwardedRef(instance);
|
||||
} else if (_this.props.forwardedRef) {
|
||||
_this.props.forwardedRef.current = instance;
|
||||
}
|
||||
}, _temp), _possibleConstructorReturn(_this, _ret);
|
||||
}
|
||||
|
||||
AriaMenuButtonMenuItem.prototype.componentDidMount = function componentDidMount() {
|
||||
this.props.ambManager.addItem({
|
||||
node: this.ref.current,
|
||||
text: this.props.text
|
||||
});
|
||||
};
|
||||
|
||||
AriaMenuButtonMenuItem.prototype.render = function render() {
|
||||
var menuItemProps = {
|
||||
onClick: this.selectItem,
|
||||
onKeyDown: this.handleKeyDown,
|
||||
role: 'menuitem',
|
||||
tabIndex: '-1',
|
||||
ref: this.setRef
|
||||
};
|
||||
|
||||
specialAssign(menuItemProps, this.props, checkedProps);
|
||||
|
||||
return React.createElement(this.props.tag, menuItemProps, this.props.children);
|
||||
};
|
||||
|
||||
return AriaMenuButtonMenuItem;
|
||||
}(React.Component);
|
||||
|
||||
AriaMenuButtonMenuItem.propTypes = checkedProps;
|
||||
AriaMenuButtonMenuItem.defaultProps = { tag: 'div' };
|
||||
|
||||
|
||||
module.exports = React.forwardRef(function (props, ref) {
|
||||
return React.createElement(ManagerContext.Consumer, null, function (ambManager) {
|
||||
var buttonProps = { ambManager: ambManager, forwardedRef: ref };
|
||||
specialAssign(buttonProps, props, {
|
||||
ambManager: checkedProps.ambManager,
|
||||
children: checkedProps.children,
|
||||
forwardedRef: checkedProps.forwardedRef
|
||||
});
|
||||
return React.createElement(AriaMenuButtonMenuItem, buttonProps, props.children);
|
||||
});
|
||||
});
|
||||
74
node_modules/react-aria-menubutton/dist/Wrapper.js
generated
vendored
Normal file
74
node_modules/react-aria-menubutton/dist/Wrapper.js
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
'use strict';
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
||||
|
||||
function _inherits(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) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
||||
|
||||
var React = require('react');
|
||||
var PropTypes = require('prop-types');
|
||||
var createManager = require('./createManager');
|
||||
var ManagerContext = require('./ManagerContext');
|
||||
|
||||
var _require = require("./propTypes"),
|
||||
refType = _require.refType;
|
||||
|
||||
var specialAssign = require('./specialAssign');
|
||||
|
||||
var checkedProps = {
|
||||
children: PropTypes.node.isRequired,
|
||||
forwardedRef: refType,
|
||||
onMenuToggle: PropTypes.func,
|
||||
onSelection: PropTypes.func,
|
||||
closeOnSelection: PropTypes.bool,
|
||||
closeOnBlur: PropTypes.bool,
|
||||
tag: PropTypes.string
|
||||
};
|
||||
|
||||
var managerOptionsFromProps = function managerOptionsFromProps(props) {
|
||||
return {
|
||||
onMenuToggle: props.onMenuToggle,
|
||||
onSelection: props.onSelection,
|
||||
closeOnSelection: props.closeOnSelection,
|
||||
closeOnBlur: props.closeOnBlur,
|
||||
id: props.id
|
||||
};
|
||||
};
|
||||
|
||||
var AriaMenuButtonWrapper = function (_React$Component) {
|
||||
_inherits(AriaMenuButtonWrapper, _React$Component);
|
||||
|
||||
function AriaMenuButtonWrapper(props) {
|
||||
_classCallCheck(this, AriaMenuButtonWrapper);
|
||||
|
||||
var _this = _possibleConstructorReturn(this, _React$Component.call(this, props));
|
||||
|
||||
_this.manager = createManager(managerOptionsFromProps(props));
|
||||
return _this;
|
||||
}
|
||||
|
||||
AriaMenuButtonWrapper.prototype.componentDidUpdate = function componentDidUpdate() {
|
||||
this.manager.updateOptions(managerOptionsFromProps(this.props));
|
||||
};
|
||||
|
||||
AriaMenuButtonWrapper.prototype.render = function render() {
|
||||
var wrapperProps = {};
|
||||
specialAssign(wrapperProps, this.props, checkedProps);
|
||||
|
||||
return React.createElement(ManagerContext.Provider, { value: this.manager }, React.createElement(this.props.tag, wrapperProps, this.props.children));
|
||||
};
|
||||
|
||||
return AriaMenuButtonWrapper;
|
||||
}(React.Component);
|
||||
|
||||
AriaMenuButtonWrapper.propTypes = checkedProps;
|
||||
AriaMenuButtonWrapper.defaultProps = { tag: 'div' };
|
||||
|
||||
|
||||
module.exports = React.forwardRef(function (props, ref) {
|
||||
var wrapperProps = { forwardedRef: ref };
|
||||
specialAssign(wrapperProps, props, { children: checkedProps.children, forwardedRef: checkedProps.forwardedRef });
|
||||
specialAssign(wrapperProps, { forwardedRef: ref });
|
||||
return React.createElement(AriaMenuButtonWrapper, wrapperProps, props.children);
|
||||
});
|
||||
163
node_modules/react-aria-menubutton/dist/createManager.js
generated
vendored
Normal file
163
node_modules/react-aria-menubutton/dist/createManager.js
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
'use strict';
|
||||
|
||||
var createFocusGroup = require('focus-group');
|
||||
var externalStateControl = require('./externalStateControl');
|
||||
|
||||
var focusGroupOptions = {
|
||||
wrap: true,
|
||||
stringSearch: true
|
||||
};
|
||||
|
||||
var protoManager = {
|
||||
init: function init(options) {
|
||||
this.updateOptions(options);
|
||||
|
||||
this.handleBlur = handleBlur.bind(this);
|
||||
this.handleSelection = handleSelection.bind(this);
|
||||
this.handleMenuKey = handleMenuKey.bind(this);
|
||||
|
||||
// "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."
|
||||
// "Typing a letter (printable character) key moves focus to the next
|
||||
// instance of a visible node whose title begins with that printable letter."
|
||||
//
|
||||
// All of the above is handled by focus-group.
|
||||
this.focusGroup = createFocusGroup(focusGroupOptions);
|
||||
|
||||
// These component references are added when the relevant components mount
|
||||
this.button = null;
|
||||
this.menu = null;
|
||||
|
||||
// State trackers
|
||||
this.isOpen = false;
|
||||
},
|
||||
updateOptions: function updateOptions(options) {
|
||||
var oldOptions = this.options;
|
||||
|
||||
this.options = options || this.options || {};
|
||||
|
||||
if (typeof this.options.closeOnSelection === 'undefined') {
|
||||
this.options.closeOnSelection = true;
|
||||
}
|
||||
|
||||
if (typeof this.options.closeOnBlur === 'undefined') {
|
||||
this.options.closeOnBlur = true;
|
||||
}
|
||||
|
||||
if (this.options.id) {
|
||||
externalStateControl.registerManager(this.options.id, this);
|
||||
}
|
||||
|
||||
if (oldOptions && oldOptions.id && oldOptions.id !== this.options.id) {
|
||||
externalStateControl.unregisterManager(this.options.id, this);
|
||||
}
|
||||
},
|
||||
focusItem: function focusItem(index) {
|
||||
this.focusGroup.focusNodeAtIndex(index);
|
||||
},
|
||||
addItem: function addItem(item) {
|
||||
this.focusGroup.addMember(item);
|
||||
},
|
||||
clearItems: function clearItems() {
|
||||
this.focusGroup.clearMembers();
|
||||
},
|
||||
handleButtonNonArrowKey: function handleButtonNonArrowKey(event) {
|
||||
this.focusGroup._handleUnboundKey(event);
|
||||
},
|
||||
destroy: function destroy() {
|
||||
this.button = null;
|
||||
this.menu = null;
|
||||
this.focusGroup.deactivate();
|
||||
clearTimeout(this.blurTimer);
|
||||
clearTimeout(this.moveFocusTimer);
|
||||
},
|
||||
update: function update() {
|
||||
this.menu.setState({ isOpen: this.isOpen });
|
||||
this.button.setState({ menuOpen: this.isOpen });
|
||||
this.options.onMenuToggle && this.options.onMenuToggle({ isOpen: this.isOpen });
|
||||
},
|
||||
openMenu: function openMenu(openOptions) {
|
||||
if (this.isOpen) return;
|
||||
openOptions = openOptions || {};
|
||||
if (openOptions.focusMenu === undefined) {
|
||||
openOptions.focusMenu = true;
|
||||
}
|
||||
this.isOpen = true;
|
||||
this.update();
|
||||
this.focusGroup.activate();
|
||||
if (openOptions.focusMenu) {
|
||||
var self = this;
|
||||
this.moveFocusTimer = setTimeout(function () {
|
||||
self.focusItem(0);
|
||||
}, 0);
|
||||
}
|
||||
},
|
||||
closeMenu: function closeMenu(closeOptions) {
|
||||
if (!this.isOpen) return;
|
||||
closeOptions = closeOptions || {};
|
||||
this.isOpen = false;
|
||||
this.update();
|
||||
if (closeOptions.focusButton) {
|
||||
this.button.ref.current.focus();
|
||||
}
|
||||
},
|
||||
toggleMenu: function toggleMenu(closeOptions, openOptions) {
|
||||
closeOptions = closeOptions || {};
|
||||
openOptions = openOptions || {};
|
||||
if (this.isOpen) {
|
||||
this.closeMenu(closeOptions);
|
||||
} else {
|
||||
this.openMenu(openOptions);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function handleBlur() {
|
||||
var self = this;
|
||||
self.blurTimer = setTimeout(function () {
|
||||
if (!self.button) return;
|
||||
var buttonNode = self.button.ref.current;
|
||||
if (!buttonNode) return;
|
||||
var activeEl = buttonNode.ownerDocument.activeElement;
|
||||
if (buttonNode && activeEl === buttonNode) return;
|
||||
var menuNode = self.menu.ref.current;
|
||||
if (menuNode === activeEl) {
|
||||
self.focusItem(0);
|
||||
return;
|
||||
}
|
||||
if (menuNode && menuNode.contains(activeEl)) return;
|
||||
if (self.isOpen) self.closeMenu({ focusButton: false });
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function handleSelection(value, event) {
|
||||
if (this.options.closeOnSelection) this.closeMenu({ focusButton: true });
|
||||
if (this.options.onSelection) this.options.onSelection(value, event);
|
||||
}
|
||||
|
||||
function handleMenuKey(event) {
|
||||
if (this.isOpen) {
|
||||
switch (event.key) {
|
||||
// With focus on the drop-down menu, pressing Escape closes
|
||||
// the menu and returns focus to the button.
|
||||
case 'Escape':
|
||||
event.preventDefault();
|
||||
this.closeMenu({ focusButton: true });
|
||||
break;
|
||||
case 'Home':
|
||||
event.preventDefault();
|
||||
this.focusGroup.moveFocusToFirst();
|
||||
break;
|
||||
case 'End':
|
||||
event.preventDefault();
|
||||
this.focusGroup.moveFocusToLast();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function (options) {
|
||||
var newManager = Object.create(protoManager);
|
||||
newManager.init(options);
|
||||
return newManager;
|
||||
};
|
||||
32
node_modules/react-aria-menubutton/dist/externalStateControl.js
generated
vendored
Normal file
32
node_modules/react-aria-menubutton/dist/externalStateControl.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
var registeredManagers = {};
|
||||
|
||||
var errorCommon = 'a menu outside a mounted Wrapper with an id, or a menu that does not exist';
|
||||
|
||||
function registerManager(menuId, manager) {
|
||||
registeredManagers[menuId] = manager;
|
||||
}
|
||||
|
||||
function unregisterManager(menuId) {
|
||||
delete registeredManagers[menuId];
|
||||
}
|
||||
|
||||
function openMenu(menuId, openOptions) {
|
||||
var manager = registeredManagers[menuId];
|
||||
if (!manager) throw new Error('Cannot open ' + errorCommon);
|
||||
manager.openMenu(openOptions);
|
||||
}
|
||||
|
||||
function closeMenu(menuId, closeOptions) {
|
||||
var manager = registeredManagers[menuId];
|
||||
if (!manager) throw new Error('Cannot close ' + errorCommon);
|
||||
manager.closeMenu(closeOptions);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
registerManager: registerManager,
|
||||
unregisterManager: unregisterManager,
|
||||
openMenu: openMenu,
|
||||
closeMenu: closeMenu
|
||||
};
|
||||
12
node_modules/react-aria-menubutton/dist/index.js
generated
vendored
Normal file
12
node_modules/react-aria-menubutton/dist/index.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
var externalStateControl = require('./externalStateControl');
|
||||
|
||||
module.exports = {
|
||||
Wrapper: require('./Wrapper'),
|
||||
Button: require('./Button'),
|
||||
Menu: require('./Menu'),
|
||||
MenuItem: require('./MenuItem'),
|
||||
openMenu: externalStateControl.openMenu,
|
||||
closeMenu: externalStateControl.closeMenu
|
||||
};
|
||||
7
node_modules/react-aria-menubutton/dist/propTypes.js
generated
vendored
Normal file
7
node_modules/react-aria-menubutton/dist/propTypes.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
var PropTypes = require("prop-types");
|
||||
|
||||
module.exports = {
|
||||
refType: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.elementType })])
|
||||
};
|
||||
11
node_modules/react-aria-menubutton/dist/specialAssign.js
generated
vendored
Normal file
11
node_modules/react-aria-menubutton/dist/specialAssign.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function (a, b, reserved) {
|
||||
reserved = reserved || {};
|
||||
// This will get id, className, style, etc.
|
||||
for (var x in b) {
|
||||
if (!b.hasOwnProperty(x)) continue;
|
||||
if (reserved[x]) continue;
|
||||
a[x] = b[x];
|
||||
}
|
||||
};
|
||||
104
node_modules/react-aria-menubutton/package.json
generated
vendored
Normal file
104
node_modules/react-aria-menubutton/package.json
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"name": "react-aria-menubutton",
|
||||
"version": "7.0.3",
|
||||
"description": "A fully accessible and flexible React-powered menu button",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"demo-bundle": "webpack --mode production --config ./webpack-demo.config.js",
|
||||
"demo-watch": "webpack --mode development --config ./webpack-demo.config.js --watch",
|
||||
"start": "npm run demo-watch & http-server demo",
|
||||
"jest": "jest",
|
||||
"test": "npm run lint && npm run jest",
|
||||
"umd-unminified": "webpack --mode development --config ./webpack-umd.config.js",
|
||||
"umd-minified": "webpack --mode production --config ./webpack-umd.config.js",
|
||||
"umd": "npm run umd-unminified && npm run umd-minified",
|
||||
"format": "prettier --single-quote --write src/**/*.js demo/js/*.js",
|
||||
"build": "babel src -d dist --ignore src/__tests__",
|
||||
"prepublishOnly": "npm run umd && npm run build"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.js": "eslint"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/davidtheclark/react-aria-menubutton.git"
|
||||
},
|
||||
"author": {
|
||||
"name": "David Clark",
|
||||
"email": "david.dave.clark@gmail.com",
|
||||
"url": "http://davidtheclark.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/davidtheclark/react-aria-menubutton/issues"
|
||||
},
|
||||
"homepage": "https://github.com/davidtheclark/react-aria-menubutton",
|
||||
"keywords": [
|
||||
"react",
|
||||
"reactjs",
|
||||
"react-component",
|
||||
"aria",
|
||||
"accessibility",
|
||||
"menu",
|
||||
"dropdown",
|
||||
"widget"
|
||||
],
|
||||
"dependencies": {
|
||||
"focus-group": "^0.3.1",
|
||||
"prop-types": "^15.6.0",
|
||||
"teeny-tap": "^0.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.3.0 || ^17.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-eslint": "^8.0.3",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"enzyme": "^3.10.0",
|
||||
"enzyme-adapter-react-16": "^1.15.1",
|
||||
"enzyme-to-json": "^3.4.3",
|
||||
"eslint": "^4.13.1",
|
||||
"http-server": "^0.10.0",
|
||||
"husky": "^2.7.0",
|
||||
"jest": "^21.2.1",
|
||||
"lint-staged": "^8.2.1",
|
||||
"prettier": "^1.9.2",
|
||||
"react": "^16.11.0",
|
||||
"react-dom": "^16.11.0",
|
||||
"react-test-renderer": "^16.11.0",
|
||||
"webpack": "^4.15.1",
|
||||
"webpack-cli": "^3.0.8"
|
||||
},
|
||||
"babel": {
|
||||
"presets": [
|
||||
"react",
|
||||
[
|
||||
"env",
|
||||
{
|
||||
"loose": true
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": [
|
||||
"transform-class-properties"
|
||||
]
|
||||
},
|
||||
"jest": {
|
||||
"setupFiles": [
|
||||
"./src/__tests__/helpers/jest-setup.js"
|
||||
],
|
||||
"testRegex": "/__tests__/.*\\.test.js$",
|
||||
"clearMocks": true
|
||||
}
|
||||
}
|
||||
129
node_modules/react-aria-menubutton/src/Button.js
generated
vendored
Normal file
129
node_modules/react-aria-menubutton/src/Button.js
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const ManagerContext = require('./ManagerContext');
|
||||
const { refType } = require("./propTypes");
|
||||
const specialAssign = require('./specialAssign');
|
||||
|
||||
const checkedProps = {
|
||||
ambManager: PropTypes.object.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
disabled: PropTypes.bool,
|
||||
forwardedRef: refType,
|
||||
tag: PropTypes.string
|
||||
};
|
||||
|
||||
// List retrieved from https://www.w3schools.com/tags/att_disabled.asp
|
||||
const disabledSupportedTags = () => [
|
||||
'button',
|
||||
'fieldset',
|
||||
'input',
|
||||
'optgroup',
|
||||
'option',
|
||||
'select',
|
||||
'textarea'
|
||||
];
|
||||
|
||||
class AriaMenuButtonButton extends React.Component {
|
||||
static propTypes = checkedProps;
|
||||
|
||||
static defaultProps = { tag: 'span' };
|
||||
|
||||
ref = React.createRef();
|
||||
|
||||
componentDidMount() {
|
||||
this.props.ambManager.button = this;
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.ambManager.destroy();
|
||||
}
|
||||
|
||||
handleKeyDown = event => {
|
||||
if (this.props.disabled) return;
|
||||
|
||||
const ambManager = this.props.ambManager;
|
||||
|
||||
switch (event.key) {
|
||||
case 'ArrowDown':
|
||||
event.preventDefault();
|
||||
if (!ambManager.isOpen) {
|
||||
ambManager.openMenu();
|
||||
} else {
|
||||
ambManager.focusItem(0);
|
||||
}
|
||||
break;
|
||||
case 'Enter':
|
||||
case ' ':
|
||||
event.preventDefault();
|
||||
ambManager.toggleMenu();
|
||||
break;
|
||||
case 'Escape':
|
||||
ambManager.handleMenuKey(event);
|
||||
break;
|
||||
default:
|
||||
// (Potential) letter keys
|
||||
ambManager.handleButtonNonArrowKey(event);
|
||||
}
|
||||
};
|
||||
|
||||
handleClick = () => {
|
||||
if (this.props.disabled) return;
|
||||
this.props.ambManager.toggleMenu({}, { focusMenu: false });
|
||||
};
|
||||
|
||||
setRef = instance => {
|
||||
this.ref.current = instance;
|
||||
if (typeof this.props.forwardedRef === "function") {
|
||||
this.props.forwardedRef(instance);
|
||||
} else if (this.props.forwardedRef) {
|
||||
this.props.forwardedRef.current = instance;
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
const ambManager = this.props.ambManager;
|
||||
|
||||
const buttonProps = {
|
||||
// "The menu button itself has a role of button."
|
||||
role: 'button',
|
||||
tabIndex: props.disabled ? '' : '0',
|
||||
// "The menu button has an aria-haspopup property, set to true."
|
||||
'aria-haspopup': true,
|
||||
'aria-expanded': ambManager.isOpen,
|
||||
'aria-disabled': props.disabled,
|
||||
onKeyDown: this.handleKeyDown,
|
||||
onClick: this.handleClick
|
||||
};
|
||||
|
||||
const reserved = {};
|
||||
specialAssign(reserved, checkedProps);
|
||||
// The disabled property should be passed down to the Button element
|
||||
// if the tag has support for disabled attribute. So it needs to be removed
|
||||
// from the reserved property object
|
||||
if (disabledSupportedTags().indexOf(props.tag) >= 0) {
|
||||
delete reserved.disabled;
|
||||
}
|
||||
if (ambManager.options.closeOnBlur) {
|
||||
buttonProps.onBlur = ambManager.handleBlur;
|
||||
}
|
||||
specialAssign(buttonProps, props, reserved);
|
||||
specialAssign(buttonProps, { ref: this.setRef });
|
||||
|
||||
return React.createElement(props.tag, buttonProps, props.children);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = React.forwardRef((props, ref) => React.createElement(
|
||||
ManagerContext.Consumer,
|
||||
null,
|
||||
(ambManager) => {
|
||||
const buttonProps = { ambManager, forwardedRef: ref };
|
||||
specialAssign(buttonProps, props, {
|
||||
ambManager: checkedProps.ambManager,
|
||||
children: checkedProps.children,
|
||||
forwardedRef: checkedProps.forwardedRef
|
||||
});
|
||||
return React.createElement(AriaMenuButtonButton, buttonProps, props.children);
|
||||
}
|
||||
));
|
||||
5
node_modules/react-aria-menubutton/src/ManagerContext.js
generated
vendored
Normal file
5
node_modules/react-aria-menubutton/src/ManagerContext.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
const React = require('react');
|
||||
|
||||
const AriaMenuButtonManagerContext = React.createContext();
|
||||
|
||||
module.exports = AriaMenuButtonManagerContext;
|
||||
118
node_modules/react-aria-menubutton/src/Menu.js
generated
vendored
Normal file
118
node_modules/react-aria-menubutton/src/Menu.js
generated
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const createTapListener = require('teeny-tap');
|
||||
const ManagerContext = require('./ManagerContext');
|
||||
const { refType } = require("./propTypes");
|
||||
const specialAssign = require('./specialAssign');
|
||||
|
||||
const checkedProps = {
|
||||
ambManager: PropTypes.object.isRequired,
|
||||
children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired,
|
||||
forwardedRef: refType,
|
||||
tag: PropTypes.string
|
||||
};
|
||||
|
||||
class AriaMenuButtonMenu extends React.Component {
|
||||
static propTypes = checkedProps;
|
||||
static defaultProps = { tag: 'div' };
|
||||
|
||||
ref = React.createRef();
|
||||
|
||||
componentDidMount() {
|
||||
this.props.ambManager.menu = this;
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const ambManager = this.props.ambManager;
|
||||
if (!ambManager.options.closeOnBlur) return;
|
||||
if (ambManager.isOpen && !this.tapListener) {
|
||||
this.addTapListener();
|
||||
} else if (!ambManager.isOpen && this.tapListener) {
|
||||
this.tapListener.remove();
|
||||
delete this.tapListener;
|
||||
}
|
||||
|
||||
if (!ambManager.isOpen) {
|
||||
// Clear the ambManager's items, so they
|
||||
// can be reloaded next time this menu opens
|
||||
ambManager.clearItems();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.tapListener) this.tapListener.remove();
|
||||
this.props.ambManager.destroy();
|
||||
}
|
||||
|
||||
addTapListener = () => {
|
||||
const el = this.ref.current;
|
||||
if (!el) return;
|
||||
const doc = el.ownerDocument;
|
||||
if (!doc) return;
|
||||
this.tapListener = createTapListener(doc.documentElement, this.handleTap);
|
||||
};
|
||||
|
||||
handleTap = event => {
|
||||
if (this.ref.current.contains(event.target)) return;
|
||||
if (
|
||||
this.props.ambManager.button.ref.current.contains(
|
||||
event.target
|
||||
)
|
||||
)
|
||||
return;
|
||||
this.props.ambManager.closeMenu();
|
||||
};
|
||||
|
||||
setRef = instance => {
|
||||
this.ref.current = instance;
|
||||
if (typeof this.props.forwardedRef === "function") {
|
||||
this.props.forwardedRef(instance);
|
||||
} else if (this.props.forwardedRef) {
|
||||
this.props.forwardedRef.current = instance;
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
const ambManager = this.props.ambManager;
|
||||
|
||||
const childrenToRender = (function() {
|
||||
if (typeof props.children === 'function') {
|
||||
return props.children({ isOpen: ambManager.isOpen });
|
||||
}
|
||||
if (ambManager.isOpen) return props.children;
|
||||
return false;
|
||||
})();
|
||||
|
||||
if (!childrenToRender) return false;
|
||||
|
||||
const menuProps = {
|
||||
onKeyDown: ambManager.handleMenuKey,
|
||||
role: 'menu',
|
||||
tabIndex: -1
|
||||
};
|
||||
|
||||
if (ambManager.options.closeOnBlur) {
|
||||
menuProps.onBlur = ambManager.handleBlur;
|
||||
}
|
||||
|
||||
specialAssign(menuProps, props, checkedProps);
|
||||
specialAssign(menuProps, { ref: this.setRef });
|
||||
|
||||
return React.createElement(props.tag, menuProps, childrenToRender);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = React.forwardRef((props, ref) => React.createElement(
|
||||
ManagerContext.Consumer,
|
||||
null,
|
||||
(ambManager) => {
|
||||
const buttonProps = { ambManager, forwardedRef: ref };
|
||||
specialAssign(buttonProps, props, {
|
||||
ambManager: checkedProps.ambManager,
|
||||
children: checkedProps.children,
|
||||
forwardedRef: checkedProps.forwardedRef
|
||||
});
|
||||
return React.createElement(AriaMenuButtonMenu, buttonProps, props.children);
|
||||
}
|
||||
));
|
||||
84
node_modules/react-aria-menubutton/src/MenuItem.js
generated
vendored
Normal file
84
node_modules/react-aria-menubutton/src/MenuItem.js
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const ManagerContext = require('./ManagerContext');
|
||||
const { refType } = require("./propTypes");
|
||||
const specialAssign = require('./specialAssign');
|
||||
|
||||
const checkedProps = {
|
||||
ambManager: PropTypes.object.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
forwardedRef: refType,
|
||||
tag: PropTypes.string,
|
||||
text: PropTypes.string,
|
||||
value: PropTypes.any
|
||||
};
|
||||
|
||||
class AriaMenuButtonMenuItem extends React.Component {
|
||||
static propTypes = checkedProps;
|
||||
static defaultProps = { tag: 'div' };
|
||||
|
||||
ref = React.createRef();
|
||||
|
||||
componentDidMount() {
|
||||
this.props.ambManager.addItem({
|
||||
node: this.ref.current,
|
||||
text: this.props.text
|
||||
});
|
||||
}
|
||||
|
||||
handleKeyDown = event => {
|
||||
if (event.key !== 'Enter' && event.key !== ' ') return;
|
||||
if (this.props.tag === 'a' && this.props.href) return;
|
||||
event.preventDefault();
|
||||
this.selectItem(event);
|
||||
};
|
||||
|
||||
selectItem = event => {
|
||||
// If there's no value, we'll send the child
|
||||
const value = typeof this.props.value !== 'undefined'
|
||||
? this.props.value
|
||||
: this.props.children;
|
||||
this.props.ambManager.handleSelection(value, event);
|
||||
};
|
||||
|
||||
setRef = instance => {
|
||||
this.ref.current = instance;
|
||||
if (typeof this.props.forwardedRef === "function") {
|
||||
this.props.forwardedRef(instance);
|
||||
} else if (this.props.forwardedRef) {
|
||||
this.props.forwardedRef.current = instance;
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const menuItemProps = {
|
||||
onClick: this.selectItem,
|
||||
onKeyDown: this.handleKeyDown,
|
||||
role: 'menuitem',
|
||||
tabIndex: '-1',
|
||||
ref: this.setRef
|
||||
};
|
||||
|
||||
specialAssign(menuItemProps, this.props, checkedProps);
|
||||
|
||||
return React.createElement(
|
||||
this.props.tag,
|
||||
menuItemProps,
|
||||
this.props.children
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = React.forwardRef((props, ref) => React.createElement(
|
||||
ManagerContext.Consumer,
|
||||
null,
|
||||
(ambManager) => {
|
||||
const buttonProps = { ambManager, forwardedRef: ref };
|
||||
specialAssign(buttonProps, props, {
|
||||
ambManager: checkedProps.ambManager,
|
||||
children: checkedProps.children,
|
||||
forwardedRef: checkedProps.forwardedRef
|
||||
});
|
||||
return React.createElement(AriaMenuButtonMenuItem, buttonProps, props.children);
|
||||
}
|
||||
));
|
||||
62
node_modules/react-aria-menubutton/src/Wrapper.js
generated
vendored
Normal file
62
node_modules/react-aria-menubutton/src/Wrapper.js
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const createManager = require('./createManager');
|
||||
const ManagerContext = require('./ManagerContext');
|
||||
const { refType } = require("./propTypes");
|
||||
const specialAssign = require('./specialAssign');
|
||||
|
||||
const checkedProps = {
|
||||
children: PropTypes.node.isRequired,
|
||||
forwardedRef: refType,
|
||||
onMenuToggle: PropTypes.func,
|
||||
onSelection: PropTypes.func,
|
||||
closeOnSelection: PropTypes.bool,
|
||||
closeOnBlur: PropTypes.bool,
|
||||
tag: PropTypes.string
|
||||
};
|
||||
|
||||
const managerOptionsFromProps = (props) => {
|
||||
return {
|
||||
onMenuToggle: props.onMenuToggle,
|
||||
onSelection: props.onSelection,
|
||||
closeOnSelection: props.closeOnSelection,
|
||||
closeOnBlur: props.closeOnBlur,
|
||||
id: props.id
|
||||
}
|
||||
}
|
||||
|
||||
class AriaMenuButtonWrapper extends React.Component {
|
||||
static propTypes = checkedProps;
|
||||
static defaultProps = { tag: 'div' };
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.manager = createManager(managerOptionsFromProps(props));
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.manager.updateOptions(managerOptionsFromProps(this.props))
|
||||
}
|
||||
|
||||
render() {
|
||||
const wrapperProps = {};
|
||||
specialAssign(wrapperProps, this.props, checkedProps);
|
||||
|
||||
return React.createElement(
|
||||
ManagerContext.Provider,
|
||||
{ value: this.manager },
|
||||
React.createElement(
|
||||
this.props.tag,
|
||||
wrapperProps,
|
||||
this.props.children,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = React.forwardRef((props, ref) => {
|
||||
const wrapperProps = { forwardedRef: ref };
|
||||
specialAssign(wrapperProps, props, { children: checkedProps.children, forwardedRef: checkedProps.forwardedRef });
|
||||
specialAssign(wrapperProps, { forwardedRef: ref });
|
||||
return React.createElement(AriaMenuButtonWrapper, wrapperProps, props.children);
|
||||
});
|
||||
169
node_modules/react-aria-menubutton/src/__tests__/Button.test.js
generated
vendored
Normal file
169
node_modules/react-aria-menubutton/src/__tests__/Button.test.js
generated
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
const React = require('react');
|
||||
const ReactDOMServer = require('react-dom/server');
|
||||
const shallow = require('enzyme').shallow;
|
||||
const shallowToJson = require('enzyme-to-json').shallowToJson;
|
||||
const Button = require('../Button');
|
||||
const ManagerContext = require('../ManagerContext');
|
||||
const MockWrapper = require('./helpers/MockWrapper');
|
||||
const createMockKeyEvent = require('./helpers/createMockKeyEvent');
|
||||
const createMockManager = require('./helpers/createMockManager');
|
||||
const createManager = require('../createManager');
|
||||
|
||||
const el = React.createElement;
|
||||
|
||||
describe('<Button>', function() {
|
||||
let shallowOptions;
|
||||
let ambManager;
|
||||
let downEvent;
|
||||
let enterEvent;
|
||||
let spaceEvent;
|
||||
let escapeEvent;
|
||||
let fEvent;
|
||||
|
||||
beforeEach(function() {
|
||||
ambManager = createMockManager();
|
||||
shallowOptions = {
|
||||
wrappingComponent: ManagerContext.Provider,
|
||||
wrappingComponentProps: { value: ambManager },
|
||||
};
|
||||
downEvent = createMockKeyEvent('ArrowDown');
|
||||
enterEvent = createMockKeyEvent('Enter');
|
||||
spaceEvent = createMockKeyEvent(' ');
|
||||
escapeEvent = createMockKeyEvent('Escape');
|
||||
fEvent = createMockKeyEvent(null, 70);
|
||||
});
|
||||
|
||||
test('DOM with only required props and text child', function() {
|
||||
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
|
||||
expect(shallowToJson(wrapper)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('no onBlur prop when closeOnBlur is false', function() {
|
||||
const manager = createManager({ closeOnBlur: false });
|
||||
const shallowOptions = {
|
||||
wrappingComponent: ManagerContext.Provider,
|
||||
wrappingComponentProps: { value: manager }
|
||||
};
|
||||
const wrapper = shallow(el(Button, null, ''), shallowOptions).dive().dive();
|
||||
expect(shallowToJson(wrapper).props).not.toHaveProperty('onBlur');
|
||||
});
|
||||
|
||||
test('DOM with all possible props and element child', function() {
|
||||
const button = el(
|
||||
Button,
|
||||
{
|
||||
id: 'foo',
|
||||
className: 'bar',
|
||||
style: { top: 2 },
|
||||
tag: 'button',
|
||||
disabled: true,
|
||||
'data-something-something': 'seven' // arbitrary prop
|
||||
},
|
||||
el('span', null, 'hooha')
|
||||
);
|
||||
const wrapper = shallow(button, shallowOptions).dive().dive();
|
||||
expect(shallowToJson(wrapper)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('click', function() {
|
||||
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
|
||||
wrapper.simulate('click');
|
||||
|
||||
expect(ambManager.toggleMenu).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('click when disabled', function() {
|
||||
const wrapper = shallow(
|
||||
el(Button, { disabled: true }, 'foo'),
|
||||
shallowOptions
|
||||
).dive().dive();
|
||||
wrapper.simulate('click');
|
||||
|
||||
expect(ambManager.toggleMenu).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('element has disabled attribute when disabled property is set to true', function() {
|
||||
const wrapper = shallow(
|
||||
el(Button, { disabled: true, tag: 'button' }, 'foo'),
|
||||
shallowOptions
|
||||
).dive().dive();
|
||||
|
||||
expect(wrapper.props().disabled).toBeTruthy();
|
||||
});
|
||||
|
||||
test('down arrow when closed', function() {
|
||||
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
|
||||
wrapper.simulate('keyDown', downEvent);
|
||||
|
||||
expect(downEvent.preventDefault).toHaveBeenCalledTimes(1);
|
||||
expect(ambManager.openMenu).toHaveBeenCalledTimes(1);
|
||||
expect(ambManager.openMenu).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
test('down arrow when open', function() {
|
||||
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
|
||||
ambManager.isOpen = true;
|
||||
wrapper.simulate('keyDown', downEvent);
|
||||
|
||||
expect(downEvent.preventDefault).toHaveBeenCalledTimes(1);
|
||||
expect(ambManager.openMenu).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('enter key', function() {
|
||||
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
|
||||
wrapper.simulate('keyDown', enterEvent);
|
||||
|
||||
expect(enterEvent.preventDefault).toHaveBeenCalledTimes(1);
|
||||
expect(ambManager.toggleMenu).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('space key', function() {
|
||||
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
|
||||
wrapper.simulate('keyDown', spaceEvent);
|
||||
|
||||
expect(spaceEvent.preventDefault).toHaveBeenCalledTimes(1);
|
||||
expect(ambManager.toggleMenu).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('escape key', function() {
|
||||
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
|
||||
wrapper.simulate('keyDown', escapeEvent);
|
||||
|
||||
expect(ambManager.handleMenuKey).toHaveBeenCalledTimes(1);
|
||||
expect(ambManager.handleMenuKey.mock.calls[0][0].key).toBe('Escape');
|
||||
});
|
||||
|
||||
test('f key', function() {
|
||||
const wrapper = shallow(el(Button, null, 'foo'), shallowOptions).dive().dive();
|
||||
wrapper.simulate('keyDown', fEvent);
|
||||
|
||||
expect(ambManager.handleButtonNonArrowKey).toHaveBeenCalledTimes(1);
|
||||
expect(ambManager.handleButtonNonArrowKey.mock.calls[0][0].keyCode).toBe(
|
||||
70
|
||||
);
|
||||
});
|
||||
|
||||
test('enter key when disabled', function() {
|
||||
const wrapper = shallow(
|
||||
el(Button, { disabled: true }, 'foo'),
|
||||
shallowOptions
|
||||
).dive().dive();
|
||||
wrapper.simulate('keyDown', enterEvent);
|
||||
|
||||
expect(enterEvent.preventDefault).not.toHaveBeenCalled();
|
||||
expect(ambManager.toggleMenu).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('<Button> rendered via renderToString', function() {
|
||||
test('does not throw', function() {
|
||||
const output = ReactDOMServer.renderToString(
|
||||
el(
|
||||
MockWrapper,
|
||||
{ mockManager: createMockManager() },
|
||||
el(Button, null, 'foo')
|
||||
)
|
||||
);
|
||||
expect(output).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
130
node_modules/react-aria-menubutton/src/__tests__/Menu.test.js
generated
vendored
Normal file
130
node_modules/react-aria-menubutton/src/__tests__/Menu.test.js
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
const React = require('react');
|
||||
const ReactDOMServer = require('react-dom/server');
|
||||
const shallow = require('enzyme').shallow;
|
||||
const mount = require('enzyme').mount;
|
||||
const shallowToJson = require('enzyme-to-json').shallowToJson;
|
||||
const ManagerContext = require('../ManagerContext');
|
||||
const Menu = require('../Menu');
|
||||
const MockWrapper = require('./helpers/MockWrapper');
|
||||
const createMockManager = require('./helpers/createMockManager');
|
||||
const createManager = require('../createManager');
|
||||
|
||||
const el = React.createElement;
|
||||
|
||||
describe('<Menu>', function() {
|
||||
let shallowOptions;
|
||||
let ambManager;
|
||||
|
||||
beforeEach(function() {
|
||||
ambManager = createMockManager();
|
||||
shallowOptions = {
|
||||
wrappingComponent: ManagerContext.Provider,
|
||||
wrappingComponentProps: { value: ambManager }
|
||||
};
|
||||
});
|
||||
|
||||
test('closed Menu DOM with only required props and element child', function() {
|
||||
const menuEl = el(Menu, null, el('div', null, 'foo'));
|
||||
const wrapper = shallow(menuEl, shallowOptions).dive().dive();
|
||||
expect(shallowToJson(wrapper)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('no onBlur prop when closeOnBlur is false', function() {
|
||||
const manager = createManager({ closeOnBlur: false });
|
||||
manager.isOpen = true;
|
||||
const shallowOptions = {
|
||||
wrappingComponent: ManagerContext.Provider,
|
||||
wrappingComponentProps: { value: manager }
|
||||
};
|
||||
const menuEl = el(Menu, null, el('div', null, 'foo'));
|
||||
const wrapper = shallow(menuEl, shallowOptions).dive().dive();
|
||||
expect(shallowToJson(wrapper).props).not.toHaveProperty('onBlur');
|
||||
});
|
||||
|
||||
test('open Menu DOM with only required props and element child', function() {
|
||||
ambManager.isOpen = true;
|
||||
const menuEl = el(Menu, null, el('div', null, el('div', null, 'foo')));
|
||||
const wrapper = shallow(menuEl, shallowOptions).dive().dive();
|
||||
expect(shallowToJson(wrapper)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('closed menu DOM with all possible props and function child', function() {
|
||||
const childFunction = jest.fn().mockImplementation(function(menuState) {
|
||||
return 'isOpen = ' + menuState.isOpen;
|
||||
});
|
||||
const menuEl = el(
|
||||
Menu,
|
||||
{
|
||||
id: 'foo',
|
||||
className: 'bar',
|
||||
style: { bottom: 1 },
|
||||
tag: 'ul',
|
||||
'data-something-something': 'seven' // arbitrary prop
|
||||
},
|
||||
childFunction
|
||||
);
|
||||
const wrapper = shallow(menuEl, shallowOptions).dive().dive();
|
||||
expect(shallowToJson(wrapper)).toMatchSnapshot();
|
||||
expect(childFunction).toHaveBeenCalledTimes(1);
|
||||
expect(childFunction.mock.calls[0]).toEqual([{ isOpen: false }]);
|
||||
});
|
||||
|
||||
test('open menu DOM with all possible props and function child', function() {
|
||||
ambManager.isOpen = true;
|
||||
const childFunction = jest.fn().mockImplementation(function(menuState) {
|
||||
return 'isOpen = ' + menuState.isOpen;
|
||||
});
|
||||
const menuEl = el(
|
||||
Menu,
|
||||
{
|
||||
id: 'bar',
|
||||
className: 'foo',
|
||||
style: { left: 1 },
|
||||
tag: 'section'
|
||||
},
|
||||
childFunction
|
||||
);
|
||||
const wrapper = shallow(menuEl, shallowOptions).dive().dive();
|
||||
expect(shallowToJson(wrapper)).toMatchSnapshot();
|
||||
expect(childFunction).toHaveBeenCalledTimes(1);
|
||||
expect(childFunction.mock.calls[0]).toEqual([{ isOpen: true }]);
|
||||
});
|
||||
|
||||
test('menu updating', function() {
|
||||
ambManager.menuItems = [1, 2];
|
||||
const childFunction = jest.fn();
|
||||
|
||||
class LittleApp extends React.Component {
|
||||
state = { open: false };
|
||||
|
||||
toggleMenu = () => {
|
||||
this.setState({ open: !this.state.open });
|
||||
};
|
||||
|
||||
render() {
|
||||
return el(
|
||||
MockWrapper,
|
||||
{ mockManager: ambManager },
|
||||
el(Menu, null, childFunction)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const wrapper = mount(el(LittleApp));
|
||||
wrapper.instance().toggleMenu();
|
||||
expect(ambManager.clearItems).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('<Menu> rendered via renderToString', function() {
|
||||
test('does not throw', function() {
|
||||
const output = ReactDOMServer.renderToString(
|
||||
el(
|
||||
MockWrapper,
|
||||
{ mockManager: createMockManager() },
|
||||
el(Menu, null, el('div', null, 'foo'))
|
||||
)
|
||||
);
|
||||
expect(output).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
106
node_modules/react-aria-menubutton/src/__tests__/MenuItem.test.js
generated
vendored
Normal file
106
node_modules/react-aria-menubutton/src/__tests__/MenuItem.test.js
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
const React = require('react');
|
||||
const ReactDOMServer = require('react-dom/server');
|
||||
const shallow = require('enzyme').shallow;
|
||||
const shallowToJson = require('enzyme-to-json').shallowToJson;
|
||||
const ManagerContext = require('../ManagerContext');
|
||||
const MenuItem = require('../MenuItem');
|
||||
const MockWrapper = require('./helpers/MockWrapper');
|
||||
const createMockKeyEvent = require('./helpers/createMockKeyEvent');
|
||||
const createMockManager = require('./helpers/createMockManager');
|
||||
|
||||
const el = React.createElement;
|
||||
|
||||
describe('<MenuItem>', function() {
|
||||
let shallowOptions;
|
||||
let ambManager;
|
||||
|
||||
beforeEach(function() {
|
||||
ambManager = createMockManager();
|
||||
shallowOptions = {
|
||||
wrappingComponent: ManagerContext.Provider,
|
||||
wrappingComponentProps: { value: ambManager }
|
||||
};
|
||||
});
|
||||
|
||||
it('DOM with only required props', function() {
|
||||
const menuItem = el(MenuItem, null, 'foo');
|
||||
const wrapper = shallow(menuItem, shallowOptions).dive().dive();
|
||||
expect(shallowToJson(wrapper)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('DOM with all possible props and element child', function() {
|
||||
const menuItem = el(
|
||||
MenuItem,
|
||||
{
|
||||
className: 'foobar',
|
||||
id: 'hogwash',
|
||||
tag: 'li',
|
||||
style: { right: '1em' },
|
||||
text: 'horse',
|
||||
value: 'lamb',
|
||||
'data-something-something': 'seven' // arbitrary prop
|
||||
},
|
||||
el('a', { href: '#' }, 'foo')
|
||||
);
|
||||
const wrapper = shallow(menuItem, shallowOptions).dive().dive();
|
||||
expect(shallowToJson(wrapper)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('click without specified value prop', function() {
|
||||
const mockEvent = { bee: 'baa' };
|
||||
const menuItem = el(MenuItem, null, 'foo');
|
||||
const wrapper = shallow(menuItem, shallowOptions).dive().dive();
|
||||
wrapper.simulate('click', mockEvent);
|
||||
expect(ambManager.handleSelection).toHaveBeenCalledTimes(1);
|
||||
expect(ambManager.handleSelection.mock.calls[0]).toEqual([
|
||||
'foo',
|
||||
mockEvent
|
||||
]);
|
||||
});
|
||||
|
||||
it('click with specified value prop', function() {
|
||||
const mockEvent = { bee: 'baa' };
|
||||
const menuItem = el(MenuItem, { value: 'bar' }, 'foo');
|
||||
const wrapper = shallow(menuItem, shallowOptions).dive().dive();
|
||||
wrapper.simulate('click', mockEvent);
|
||||
expect(ambManager.handleSelection).toHaveBeenCalledTimes(1);
|
||||
expect(ambManager.handleSelection.mock.calls[0]).toEqual([
|
||||
'bar',
|
||||
mockEvent
|
||||
]);
|
||||
});
|
||||
|
||||
it('click with specified value prop', function() {
|
||||
const mockEnterEvent = createMockKeyEvent('Enter');
|
||||
const mockSpaceEvent = createMockKeyEvent(' ');
|
||||
const mockEscapeEvent = createMockKeyEvent('Escape');
|
||||
const menuItem = el(MenuItem, null, 'foo');
|
||||
const wrapper = shallow(menuItem, shallowOptions).dive().dive();
|
||||
|
||||
wrapper.simulate('keyDown', mockEnterEvent);
|
||||
wrapper.simulate('keyDown', mockSpaceEvent);
|
||||
wrapper.simulate('keyDown', mockEscapeEvent);
|
||||
expect(ambManager.handleSelection).toHaveBeenCalledTimes(2);
|
||||
expect(ambManager.handleSelection.mock.calls[0]).toEqual([
|
||||
'foo',
|
||||
mockEnterEvent
|
||||
]);
|
||||
expect(ambManager.handleSelection.mock.calls[1]).toEqual([
|
||||
'foo',
|
||||
mockSpaceEvent
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('<MenuItem> rendered via renderToString', function() {
|
||||
it('does not throw', function() {
|
||||
const output = ReactDOMServer.renderToString(
|
||||
el(
|
||||
MockWrapper,
|
||||
{ mockManager: createMockManager() },
|
||||
el(MenuItem, null, 'foo')
|
||||
)
|
||||
);
|
||||
expect(output).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
41
node_modules/react-aria-menubutton/src/__tests__/__snapshots__/Button.test.js.snap
generated
vendored
Normal file
41
node_modules/react-aria-menubutton/src/__tests__/__snapshots__/Button.test.js.snap
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<Button> DOM with all possible props and element child 1`] = `
|
||||
<button
|
||||
aria-disabled={true}
|
||||
aria-expanded={false}
|
||||
aria-haspopup={true}
|
||||
className="bar"
|
||||
data-something-something="seven"
|
||||
disabled={true}
|
||||
id="foo"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
role="button"
|
||||
style={
|
||||
Object {
|
||||
"top": 2,
|
||||
}
|
||||
}
|
||||
tabIndex=""
|
||||
>
|
||||
<span>
|
||||
hooha
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`<Button> DOM with only required props and text child 1`] = `
|
||||
<span
|
||||
aria-expanded={false}
|
||||
aria-haspopup={true}
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
role="button"
|
||||
tabIndex="0"
|
||||
>
|
||||
foo
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`<Button> rendered via renderToString does not throw 1`] = `"<div><span role=\\"button\\" tabindex=\\"0\\" aria-haspopup=\\"true\\" aria-expanded=\\"false\\">foo</span></div>"`;
|
||||
54
node_modules/react-aria-menubutton/src/__tests__/__snapshots__/Menu.test.js.snap
generated
vendored
Normal file
54
node_modules/react-aria-menubutton/src/__tests__/__snapshots__/Menu.test.js.snap
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<Menu> closed Menu DOM with only required props and element child 1`] = `""`;
|
||||
|
||||
exports[`<Menu> closed menu DOM with all possible props and function child 1`] = `
|
||||
<ul
|
||||
className="bar"
|
||||
data-something-something="seven"
|
||||
id="foo"
|
||||
onKeyDown={[Function]}
|
||||
role="menu"
|
||||
style={
|
||||
Object {
|
||||
"bottom": 1,
|
||||
}
|
||||
}
|
||||
tabIndex={-1}
|
||||
>
|
||||
isOpen = false
|
||||
</ul>
|
||||
`;
|
||||
|
||||
exports[`<Menu> open Menu DOM with only required props and element child 1`] = `
|
||||
<div
|
||||
onKeyDown={[Function]}
|
||||
role="menu"
|
||||
tabIndex={-1}
|
||||
>
|
||||
<div>
|
||||
<div>
|
||||
foo
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<Menu> open menu DOM with all possible props and function child 1`] = `
|
||||
<section
|
||||
className="foo"
|
||||
id="bar"
|
||||
onKeyDown={[Function]}
|
||||
role="menu"
|
||||
style={
|
||||
Object {
|
||||
"left": 1,
|
||||
}
|
||||
}
|
||||
tabIndex={-1}
|
||||
>
|
||||
isOpen = true
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`<Menu> rendered via renderToString does not throw 1`] = `"<div></div>"`;
|
||||
37
node_modules/react-aria-menubutton/src/__tests__/__snapshots__/MenuItem.test.js.snap
generated
vendored
Normal file
37
node_modules/react-aria-menubutton/src/__tests__/__snapshots__/MenuItem.test.js.snap
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<MenuItem> DOM with all possible props and element child 1`] = `
|
||||
<li
|
||||
className="foobar"
|
||||
data-something-something="seven"
|
||||
id="hogwash"
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
role="menuitem"
|
||||
style={
|
||||
Object {
|
||||
"right": "1em",
|
||||
}
|
||||
}
|
||||
tabIndex="-1"
|
||||
>
|
||||
<a
|
||||
href="#"
|
||||
>
|
||||
foo
|
||||
</a>
|
||||
</li>
|
||||
`;
|
||||
|
||||
exports[`<MenuItem> DOM with only required props 1`] = `
|
||||
<div
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
role="menuitem"
|
||||
tabIndex="-1"
|
||||
>
|
||||
foo
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<MenuItem> rendered via renderToString does not throw 1`] = `"<div><div role=\\"menuitem\\" tabindex=\\"-1\\">foo</div></div>"`;
|
||||
190
node_modules/react-aria-menubutton/src/__tests__/createManager.test.js
generated
vendored
Normal file
190
node_modules/react-aria-menubutton/src/__tests__/createManager.test.js
generated
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
/* globals Promise */
|
||||
|
||||
var createManager = require('../createManager');
|
||||
var createMockKeyEvent = require('./helpers/createMockKeyEvent');
|
||||
|
||||
var mockNode = document.createElement('button');
|
||||
var nodeOne = document.createElement('button');
|
||||
nodeOne.focus = jest.fn();
|
||||
var nodeTwo = document.createElement('button');
|
||||
nodeTwo.focus = jest.fn();
|
||||
document.body.appendChild(nodeOne);
|
||||
document.body.appendChild(nodeTwo);
|
||||
|
||||
function createManagerWithMockedElements(options) {
|
||||
var manager = createManager(options);
|
||||
manager.focusGroup.addMember({
|
||||
node: nodeOne,
|
||||
text: 'first'
|
||||
});
|
||||
manager.focusGroup.addMember({
|
||||
node: nodeTwo,
|
||||
text: 'second'
|
||||
});
|
||||
manager.button = {
|
||||
ref: { current: mockNode },
|
||||
setState: jest.fn()
|
||||
};
|
||||
manager.menu = {
|
||||
setState: jest.fn()
|
||||
};
|
||||
manager.focusItem = jest.fn();
|
||||
return manager;
|
||||
}
|
||||
|
||||
describe('createManager', function() {
|
||||
it('initalizes', function() {
|
||||
var manager = createManagerWithMockedElements();
|
||||
expect(manager.isOpen).toBe(false);
|
||||
expect(manager.options.closeOnSelection).toBeTruthy();
|
||||
expect(manager.options.closeOnBlur).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Manager#update', function() {
|
||||
var manager = createManagerWithMockedElements({
|
||||
onMenuToggle: jest.fn()
|
||||
});
|
||||
manager.update();
|
||||
expect(manager.menu.setState).toHaveBeenCalledTimes(1);
|
||||
expect(manager.menu.setState.mock.calls[0]).toEqual([
|
||||
{ isOpen: manager.isOpen }
|
||||
]);
|
||||
expect(manager.button.setState).toHaveBeenCalledTimes(1);
|
||||
expect(manager.button.setState.mock.calls[0]).toEqual([
|
||||
{ menuOpen: manager.isOpen }
|
||||
]);
|
||||
expect(manager.options.onMenuToggle).toHaveBeenCalledTimes(1);
|
||||
expect(manager.options.onMenuToggle.mock.calls[0]).toEqual([
|
||||
{ isOpen: manager.isOpen }
|
||||
]);
|
||||
});
|
||||
|
||||
it('Manager#openMenu without focusing in menu', function() {
|
||||
var manager = createManagerWithMockedElements();
|
||||
manager.openMenu({ focusMenu: false });
|
||||
expect(manager.isOpen).toBe(true);
|
||||
expect(manager.menu.setState).toHaveBeenCalledTimes(1);
|
||||
expect(manager.menu.setState.mock.calls[0]).toEqual([{ isOpen: true }]);
|
||||
expect(manager.button.setState).toHaveBeenCalledTimes(1);
|
||||
expect(manager.button.setState.mock.calls[0]).toEqual([{ menuOpen: true }]);
|
||||
|
||||
return new Promise(function(resolve) {
|
||||
setTimeout(function() {
|
||||
expect(manager.focusItem).toHaveBeenCalledTimes(0);
|
||||
resolve();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Manager#openMenu focusing in menu', function() {
|
||||
var manager = createManagerWithMockedElements();
|
||||
manager.openMenu();
|
||||
expect(manager.isOpen).toBe(true);
|
||||
expect(manager.menu.setState).toHaveBeenCalledTimes(1);
|
||||
expect(manager.menu.setState.mock.calls[0]).toEqual([{ isOpen: true }]);
|
||||
expect(manager.button.setState).toHaveBeenCalledTimes(1);
|
||||
expect(manager.button.setState.mock.calls[0]).toEqual([{ menuOpen: true }]);
|
||||
|
||||
return new Promise(function(resolve) {
|
||||
setTimeout(function() {
|
||||
expect(manager.focusItem).toHaveBeenCalledTimes(1);
|
||||
expect(manager.focusItem.mock.calls[0]).toEqual([0]);
|
||||
resolve();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Manager#closeMenu focusing on button', function() {
|
||||
mockNode.focus = jest.fn();
|
||||
|
||||
var manager = createManagerWithMockedElements();
|
||||
manager.isOpen = true;
|
||||
manager.closeMenu({ focusButton: true });
|
||||
|
||||
expect(manager.isOpen).toBe(false);
|
||||
expect(manager.menu.setState).toHaveBeenCalledTimes(1);
|
||||
expect(manager.menu.setState.mock.calls[0]).toEqual([{ isOpen: false }]);
|
||||
expect(manager.button.setState).toHaveBeenCalledTimes(1);
|
||||
expect(manager.button.setState.mock.calls[0]).toEqual([
|
||||
{ menuOpen: false }
|
||||
]);
|
||||
expect(mockNode.focus).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('Manager#closeMenu without focusing on button', function() {
|
||||
mockNode.focus = jest.fn();
|
||||
|
||||
var manager = createManagerWithMockedElements();
|
||||
manager.isOpen = true;
|
||||
manager.closeMenu({ focusButton: false });
|
||||
|
||||
expect(mockNode.focus).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Manager#toggleMenu when closed', function() {
|
||||
var manager = createManagerWithMockedElements();
|
||||
manager.openMenu = jest.fn();
|
||||
manager.closeMenu = jest.fn();
|
||||
manager.toggleMenu();
|
||||
expect(manager.openMenu).toHaveBeenCalledTimes(1);
|
||||
expect(manager.closeMenu).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Manager#toggleMenu when open', function() {
|
||||
var manager = createManagerWithMockedElements();
|
||||
manager.isOpen = true;
|
||||
manager.openMenu = jest.fn();
|
||||
manager.closeMenu = jest.fn();
|
||||
manager.toggleMenu();
|
||||
expect(manager.openMenu).not.toHaveBeenCalled();
|
||||
expect(manager.closeMenu).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('Manager#handleSelection A', function() {
|
||||
var mockOnSelection = jest.fn();
|
||||
var manager = createManagerWithMockedElements({
|
||||
onSelection: mockOnSelection
|
||||
});
|
||||
manager.closeMenu = jest.fn();
|
||||
manager.handleSelection('foo', { bar: 1 });
|
||||
expect(manager.closeMenu).toHaveBeenCalledTimes(1);
|
||||
expect(manager.closeMenu.mock.calls[0]).toEqual([{ focusButton: true }]);
|
||||
expect(mockOnSelection).toHaveBeenCalledTimes(1);
|
||||
expect(mockOnSelection.mock.calls[0]).toEqual(['foo', { bar: 1 }]);
|
||||
});
|
||||
|
||||
it('Manager#handleSelection B', function() {
|
||||
var mockOnSelection = jest.fn();
|
||||
var manager = createManagerWithMockedElements({
|
||||
onSelection: mockOnSelection,
|
||||
closeOnSelection: false
|
||||
});
|
||||
manager.closeMenu = jest.fn();
|
||||
manager.handleSelection('foo', { bar: 1 });
|
||||
expect(manager.closeMenu).not.toHaveBeenCalled();
|
||||
expect(mockOnSelection).toHaveBeenCalledTimes(1);
|
||||
expect(mockOnSelection.mock.calls[0]).toEqual(['foo', { bar: 1 }]);
|
||||
});
|
||||
|
||||
it('Manager#handleMenuKey on closed menu', function() {
|
||||
var escapeEvent = createMockKeyEvent('Escape');
|
||||
var manager = createManagerWithMockedElements();
|
||||
manager.closeMenu = jest.fn();
|
||||
|
||||
manager.handleMenuKey(escapeEvent);
|
||||
expect(escapeEvent.preventDefault).not.toHaveBeenCalled();
|
||||
expect(manager.closeMenu).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Manager#handleMenuKey on open menu', function() {
|
||||
var escapeEvent = createMockKeyEvent('Escape');
|
||||
var manager = createManagerWithMockedElements();
|
||||
manager.isOpen = true;
|
||||
manager.closeMenu = jest.fn();
|
||||
|
||||
manager.handleMenuKey(escapeEvent);
|
||||
expect(escapeEvent.preventDefault).toHaveBeenCalledTimes(1);
|
||||
expect(manager.closeMenu).toHaveBeenCalledTimes(1);
|
||||
expect(manager.closeMenu.mock.calls[0]).toEqual([{ focusButton: true }]);
|
||||
});
|
||||
});
|
||||
24
node_modules/react-aria-menubutton/src/__tests__/helpers/MockWrapper.js
generated
vendored
Normal file
24
node_modules/react-aria-menubutton/src/__tests__/helpers/MockWrapper.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const ManagerContext = require('../../ManagerContext');
|
||||
|
||||
class MockWrapper extends React.Component {
|
||||
static propTypes = {
|
||||
mockManager: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.manager = this.props.mockManager;
|
||||
}
|
||||
|
||||
render() {
|
||||
return React.createElement(
|
||||
ManagerContext.Provider,
|
||||
{ value: this.props.mockManager },
|
||||
React.createElement('div', null, this.props.children)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MockWrapper;
|
||||
7
node_modules/react-aria-menubutton/src/__tests__/helpers/createMockKeyEvent.js
generated
vendored
Normal file
7
node_modules/react-aria-menubutton/src/__tests__/helpers/createMockKeyEvent.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = function(key, keyCode) {
|
||||
return {
|
||||
key: key,
|
||||
keyCode: keyCode,
|
||||
preventDefault: jest.fn(),
|
||||
};
|
||||
};
|
||||
22
node_modules/react-aria-menubutton/src/__tests__/helpers/createMockManager.js
generated
vendored
Normal file
22
node_modules/react-aria-menubutton/src/__tests__/helpers/createMockManager.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
module.exports = function() {
|
||||
return {
|
||||
isOpen: false,
|
||||
toggleMenu: jest.fn(),
|
||||
handleMenuKey: jest.fn(),
|
||||
moveFocusDown: jest.fn(),
|
||||
openMenu: jest.fn(),
|
||||
handleKeyDown: jest.fn(),
|
||||
handleClick: jest.fn(),
|
||||
handleSelection: jest.fn(),
|
||||
handleButtonNonArrowKey: jest.fn(),
|
||||
focusItem: jest.fn(),
|
||||
menuItems: [1, 2],
|
||||
clearItems: jest.fn(),
|
||||
currentFocus: -1,
|
||||
addItem: jest.fn(),
|
||||
options: {
|
||||
closeOnBlur: true,
|
||||
closeOnSelection: true
|
||||
}
|
||||
};
|
||||
}
|
||||
5
node_modules/react-aria-menubutton/src/__tests__/helpers/jest-setup.js
generated
vendored
Normal file
5
node_modules/react-aria-menubutton/src/__tests__/helpers/jest-setup.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import './raf';
|
||||
import Enzyme from 'enzyme';
|
||||
import Adapter from 'enzyme-adapter-react-16';
|
||||
|
||||
Enzyme.configure({ adapter: new Adapter() });
|
||||
3
node_modules/react-aria-menubutton/src/__tests__/helpers/raf.js
generated
vendored
Normal file
3
node_modules/react-aria-menubutton/src/__tests__/helpers/raf.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
global.requestAnimationFrame = (callback) => {
|
||||
setTimeout(callback, 0);
|
||||
};
|
||||
173
node_modules/react-aria-menubutton/src/createManager.js
generated
vendored
Normal file
173
node_modules/react-aria-menubutton/src/createManager.js
generated
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
const createFocusGroup = require('focus-group');
|
||||
const externalStateControl = require('./externalStateControl');
|
||||
|
||||
const focusGroupOptions = {
|
||||
wrap: true,
|
||||
stringSearch: true
|
||||
};
|
||||
|
||||
const protoManager = {
|
||||
init(options) {
|
||||
this.updateOptions(options);
|
||||
|
||||
this.handleBlur = handleBlur.bind(this);
|
||||
this.handleSelection = handleSelection.bind(this);
|
||||
this.handleMenuKey = handleMenuKey.bind(this);
|
||||
|
||||
// "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."
|
||||
// "Typing a letter (printable character) key moves focus to the next
|
||||
// instance of a visible node whose title begins with that printable letter."
|
||||
//
|
||||
// All of the above is handled by focus-group.
|
||||
this.focusGroup = createFocusGroup(focusGroupOptions);
|
||||
|
||||
// These component references are added when the relevant components mount
|
||||
this.button = null;
|
||||
this.menu = null;
|
||||
|
||||
// State trackers
|
||||
this.isOpen = false;
|
||||
},
|
||||
|
||||
updateOptions(options) {
|
||||
const oldOptions = this.options;
|
||||
|
||||
this.options = options || this.options || {};
|
||||
|
||||
if (typeof this.options.closeOnSelection === 'undefined') {
|
||||
this.options.closeOnSelection = true;
|
||||
}
|
||||
|
||||
if (typeof this.options.closeOnBlur === 'undefined') {
|
||||
this.options.closeOnBlur = true;
|
||||
}
|
||||
|
||||
if (this.options.id) {
|
||||
externalStateControl.registerManager(this.options.id, this);
|
||||
}
|
||||
|
||||
if (oldOptions && oldOptions.id && oldOptions.id !== this.options.id) {
|
||||
externalStateControl.unregisterManager(this.options.id, this);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
focusItem(index) {
|
||||
this.focusGroup.focusNodeAtIndex(index);
|
||||
},
|
||||
|
||||
addItem(item) {
|
||||
this.focusGroup.addMember(item);
|
||||
},
|
||||
|
||||
clearItems() {
|
||||
this.focusGroup.clearMembers();
|
||||
},
|
||||
|
||||
handleButtonNonArrowKey(event) {
|
||||
this.focusGroup._handleUnboundKey(event);
|
||||
},
|
||||
|
||||
destroy() {
|
||||
this.button = null;
|
||||
this.menu = null;
|
||||
this.focusGroup.deactivate();
|
||||
clearTimeout(this.blurTimer);
|
||||
clearTimeout(this.moveFocusTimer);
|
||||
},
|
||||
|
||||
update() {
|
||||
this.menu.setState({ isOpen: this.isOpen });
|
||||
this.button.setState({ menuOpen: this.isOpen });
|
||||
this.options.onMenuToggle &&
|
||||
this.options.onMenuToggle({ isOpen: this.isOpen });
|
||||
},
|
||||
|
||||
openMenu(openOptions) {
|
||||
if (this.isOpen) return;
|
||||
openOptions = openOptions || {};
|
||||
if (openOptions.focusMenu === undefined) {
|
||||
openOptions.focusMenu = true;
|
||||
}
|
||||
this.isOpen = true;
|
||||
this.update();
|
||||
this.focusGroup.activate();
|
||||
if (openOptions.focusMenu) {
|
||||
const self = this;
|
||||
this.moveFocusTimer = setTimeout(function() {
|
||||
self.focusItem(0);
|
||||
}, 0);
|
||||
}
|
||||
},
|
||||
|
||||
closeMenu(closeOptions) {
|
||||
if (!this.isOpen) return;
|
||||
closeOptions = closeOptions || {};
|
||||
this.isOpen = false;
|
||||
this.update();
|
||||
if (closeOptions.focusButton) {
|
||||
this.button.ref.current.focus();
|
||||
}
|
||||
},
|
||||
|
||||
toggleMenu(closeOptions, openOptions) {
|
||||
closeOptions = closeOptions || {};
|
||||
openOptions = openOptions || {};
|
||||
if (this.isOpen) {
|
||||
this.closeMenu(closeOptions);
|
||||
} else {
|
||||
this.openMenu(openOptions);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function handleBlur() {
|
||||
const self = this;
|
||||
self.blurTimer = setTimeout(function() {
|
||||
if (!self.button) return;
|
||||
const buttonNode = self.button.ref.current;
|
||||
if (!buttonNode) return;
|
||||
const activeEl = buttonNode.ownerDocument.activeElement;
|
||||
if (buttonNode && activeEl === buttonNode) return;
|
||||
const menuNode = self.menu.ref.current;
|
||||
if (menuNode === activeEl) {
|
||||
self.focusItem(0);
|
||||
return;
|
||||
}
|
||||
if (menuNode && menuNode.contains(activeEl)) return;
|
||||
if (self.isOpen) self.closeMenu({ focusButton: false });
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function handleSelection(value, event) {
|
||||
if (this.options.closeOnSelection) this.closeMenu({ focusButton: true });
|
||||
if (this.options.onSelection) this.options.onSelection(value, event);
|
||||
}
|
||||
|
||||
function handleMenuKey(event) {
|
||||
if (this.isOpen) {
|
||||
switch (event.key) {
|
||||
// With focus on the drop-down menu, pressing Escape closes
|
||||
// the menu and returns focus to the button.
|
||||
case 'Escape':
|
||||
event.preventDefault();
|
||||
this.closeMenu({ focusButton: true });
|
||||
break;
|
||||
case 'Home':
|
||||
event.preventDefault();
|
||||
this.focusGroup.moveFocusToFirst();
|
||||
break;
|
||||
case 'End':
|
||||
event.preventDefault();
|
||||
this.focusGroup.moveFocusToLast();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function(options) {
|
||||
const newManager = Object.create(protoManager);
|
||||
newManager.init(options);
|
||||
return newManager;
|
||||
};
|
||||
31
node_modules/react-aria-menubutton/src/externalStateControl.js
generated
vendored
Normal file
31
node_modules/react-aria-menubutton/src/externalStateControl.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
const registeredManagers = {};
|
||||
|
||||
const errorCommon =
|
||||
'a menu outside a mounted Wrapper with an id, or a menu that does not exist';
|
||||
|
||||
function registerManager(menuId, manager) {
|
||||
registeredManagers[menuId] = manager;
|
||||
}
|
||||
|
||||
function unregisterManager(menuId) {
|
||||
delete registeredManagers[menuId];
|
||||
}
|
||||
|
||||
function openMenu(menuId, openOptions) {
|
||||
const manager = registeredManagers[menuId];
|
||||
if (!manager) throw new Error('Cannot open ' + errorCommon);
|
||||
manager.openMenu(openOptions);
|
||||
}
|
||||
|
||||
function closeMenu(menuId, closeOptions) {
|
||||
const manager = registeredManagers[menuId];
|
||||
if (!manager) throw new Error('Cannot close ' + errorCommon);
|
||||
manager.closeMenu(closeOptions);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
registerManager: registerManager,
|
||||
unregisterManager: unregisterManager,
|
||||
openMenu: openMenu,
|
||||
closeMenu: closeMenu
|
||||
};
|
||||
10
node_modules/react-aria-menubutton/src/index.js
generated
vendored
Normal file
10
node_modules/react-aria-menubutton/src/index.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
const externalStateControl = require('./externalStateControl');
|
||||
|
||||
module.exports = {
|
||||
Wrapper: require('./Wrapper'),
|
||||
Button: require('./Button'),
|
||||
Menu: require('./Menu'),
|
||||
MenuItem: require('./MenuItem'),
|
||||
openMenu: externalStateControl.openMenu,
|
||||
closeMenu: externalStateControl.closeMenu
|
||||
};
|
||||
8
node_modules/react-aria-menubutton/src/propTypes.js
generated
vendored
Normal file
8
node_modules/react-aria-menubutton/src/propTypes.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
const PropTypes = require("prop-types");
|
||||
|
||||
module.exports = {
|
||||
refType: PropTypes.oneOfType([
|
||||
PropTypes.func,
|
||||
PropTypes.shape({ current: PropTypes.elementType })
|
||||
])
|
||||
};
|
||||
9
node_modules/react-aria-menubutton/src/specialAssign.js
generated
vendored
Normal file
9
node_modules/react-aria-menubutton/src/specialAssign.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
module.exports = function(a, b, reserved) {
|
||||
reserved = reserved || {};
|
||||
// This will get id, className, style, etc.
|
||||
for (var x in b) {
|
||||
if (!b.hasOwnProperty(x)) continue;
|
||||
if (reserved[x]) continue;
|
||||
a[x] = b[x];
|
||||
}
|
||||
};
|
||||
1
node_modules/react-aria-menubutton/umd/ReactAriaMenuButton.js
generated
vendored
Normal file
1
node_modules/react-aria-menubutton/umd/ReactAriaMenuButton.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
14
node_modules/react-aria-menubutton/webpack-demo.config.js
generated
vendored
Normal file
14
node_modules/react-aria-menubutton/webpack-demo.config.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
demo: "./demo/js/index.js"
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, "demo"),
|
||||
filename: "demo-bundle.js"
|
||||
},
|
||||
module: {
|
||||
rules: [{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }]
|
||||
}
|
||||
};
|
||||
35
node_modules/react-aria-menubutton/webpack-umd.config.js
generated
vendored
Normal file
35
node_modules/react-aria-menubutton/webpack-umd.config.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
const path = require("path");
|
||||
|
||||
const filename = process.env.MINIFY
|
||||
? "ReactAriaMenuButton.min.js"
|
||||
: "ReactAriaMenuButton.js";
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
AriaMenuButton: "./src/index.js"
|
||||
},
|
||||
output: {
|
||||
library: "ReactAriaMenuButton",
|
||||
libraryTarget: "umd",
|
||||
path: path.join(__dirname, "umd"),
|
||||
filename: filename
|
||||
},
|
||||
externals: [
|
||||
{
|
||||
react: {
|
||||
root: "React",
|
||||
commonjs2: "react",
|
||||
commonjs: "react",
|
||||
amd: "react"
|
||||
}
|
||||
},
|
||||
],
|
||||
module: {
|
||||
rules: [{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }]
|
||||
},
|
||||
node: {
|
||||
Buffer: false,
|
||||
process: false,
|
||||
setImmediate: false
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user