Full Code of Heydon/inclusive-menu-button for AI

master 218114116595 cached
10 files
21.2 KB
5.6k tokens
1 symbols
1 requests
Download .txt
Repository: Heydon/inclusive-menu-button
Branch: master
Commit: 218114116595
Files: 10
Total size: 21.2 KB

Directory structure:
gitextract_vdrgq3rv/

├── .gitignore
├── LICENSE
├── README.md
├── examples/
│   ├── basic.html
│   ├── disabled-items.html
│   ├── menuitemcheckbox.html
│   └── menuitemradio.html
├── inclusive-menu-button.css
├── inclusive-menu-button.js
└── package.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
.DS_Store
*.log
node_modules


================================================
FILE: LICENSE
================================================
This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.

In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.

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 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.

For more information, please refer to <http://unlicense.org>


================================================
FILE: README.md
================================================
# Inclusive Menu Button

A **menu button** module that implements the correct ARIA semantics and keyboard behavior.

## Installation

```
npm i inclusive-menu-button --save
```

## Expected markup

In the following example, three menu items are provided.

```html
<div data-inclusive-menu>
 <button data-inclusive-menu-opens="difficulty">
   Difficulty
   <span aria-hidden="true">&#x25be;</span>
 </button>
 <div id="difficulty" data-inclusive-menu-from="left">
   <button>Easy</button>
   <button>Medium</button>
   <button>Incredibly Hard</button>
 </div>
</div>
```

* The parent element must take `data-inclusive-menu`.
* `data-inclusive-menu-opens` takes a value that must match the menu element's `id`. In this case, it is `difficulty`.
* `data-inclusive-menu-from` defines from which side of the button the menu will grow. Any value but "right" will mean it grows from the left.
* The menu items must be sibling buttons. The script adds the `menuitem` role (as well as the `menu` role to the parent menu element).

### After initialization

Once you've initialized the menu button, this will be the resulting markup, including all of the necessary ARIA attribution:

```html
<div data-inclusive-menu>
 <button data-inclusive-menu-opens="difficulty" aria-haspopup="true" aria-expanded="false">
   Difficulty
   <span aria-hidden="true">&#x25be;</span>
 </button>
 <div id="difficulty" data-inclusive-menu-from="left" role="menu" hidden>
   <button role="menuitem" tabindex="-1">Easy</button>
   <button role="menuitem" tabindex="-1">Medium</button>
   <button role="menuitem" tabindex="-1">Incredibly Hard</button>
 </div>
</div>
```

## CSS

The following functional styling is provided for the basic layout of an archetypal "dropdown" menu appearance. You can either override and add to these styles in the cascade or remove them altogether and start from scratch.

```css
[data-inclusive-menu] {
  position: relative;
  display: inline-block;
}

[data-inclusive-menu-opens],
[data-inclusive-menu] [role^="menuitem"] {
  text-align: left;
  border: 0;
}

[data-inclusive-menu] [role="menu"] {
  position: absolute;
  left: 0;
}

[data-inclusive-menu] [data-inclusive-menu-from="right"] {
  left: auto;
  right: 0;
}

[data-inclusive-menu] [role^="menuitem"] {
  display: block;
  min-width: 100%;
  white-space: nowrap;
}

[data-inclusive-menu] [role^="menuitem"][aria-checked="true"]::before {
  content: '\2713\0020';
}
```

## Initialization

Initialize the menu button / menu like so:

```js
// get a menu button
const exampleButton = document.querySelector('[data-inclusive-menu-opens]')

// Make it a menu button
const exampleMenuButton = new MenuButton(exampleButton)
```

### Checked items

Sometimes you'd like to persist the selected menu item, using a checked state. WAI-ARIA provides `menuitemradio` (allowing the checking of just one item) and `menuitemcheckbox` (allowing the checking of multiple items). Checked items are marked with `aria-checked="true"`.

You can supply the constructor with a `checkable` value of 'none' (default), 'one', or 'many'. In the following example, 'one' is chosen, implementing `menuitemradio`. See the examples folder for working demonstrations.

```js
// Make it a menu button with menuitemradio buttons
const exampleMenuButton = new MenuButton(exampleButton, { checkable: 'one' })
```

If you want to set default checked items, just do that in the HTML:

```html
<div id="difficulty" data-inclusive-menu-from="left">
 <button>Easy</button>
 <button aria-checked="true">Medium</button>
 <button>Incredibly Hard</button>
</div>
```

The basic CSS (see above) prefixes the checked item with a check mark. This declaration can be removed safely and replaced with a different form of indication.

### API methods

You can open and close the menu programmatically.

```js
// Open
exampleMenuBtn.open()

// Close
exampleMenuBtn.close()

// Toggle
exampleMenuBtn.toggle()
```

### Event subscription

You can subscribe to emitted `open`, `close`, and `choose` events.

#### `open` and `close` examples

```js
exampleMenuButton.on('open', function () {
  // Do something when the menu gets open
})

exampleMenuButton.on('close', function () {
  // Do something when the menu gets closed
})
```

#### `choose` example

The `choose` event is passed the chosen item’s DOM node.

```js
exampleMenuButton.on('choose', function (choice) {
  // Do something with `choice` DOM node
})
```

### Unsubscribing

There is an `off` method included for terminating event listeners.

```js
exampleMenuButton.off('choose', exampleHandler)
```


================================================
FILE: examples/basic.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <link rel="stylesheet" href="../inclusive-menu-button.css" />
    <style>
    /* basic page styles */
    html {
      font-size: 150%;
      font-family: sans-serif;
      padding: 1em;
    }

    * {
      font-size: inherit;
      font-family: inherit;
    }

    /* custom theming */
    button {
      padding: 0.25rem 1rem;
      background: black;
      color: white;
    }

    button:focus {
      outline: none;
      background-color: #3737c8;
    }

    [data-inclusive-menu] [role^="menuitem"] {
      margin-top: 3px;
    }
    </style>
    <title>
      Inclusive Menu Button | Basic Example
    </title>
  </head>
  <body>
    <div data-inclusive-menu>
     <button data-inclusive-menu-opens="edit">
       Edit
       <span aria-hidden="true">&#x25be;</span>
     </button>
     <div id="edit" data-inclusive-menu-from="left">
       <button>Undo</button>
       <button>Redo</button>
       <button>Cut</button>
       <button>Copy</button>
       <button>Paste</button>
     </div>
    </div>
    <script src="../inclusive-menu-button.js"></script>
    <script>
      // Instantiation
      var exampleButton = document.querySelector('[data-inclusive-menu-opens]')
      var exampleMenuButton = new MenuButton(exampleButton)

      // Listen to choose event
      exampleMenuButton.on('choose', function(choice) {
        console.log('You chose "' + choice.textContent + '"')
      })
    </script>
  </body>
</html>


================================================
FILE: examples/disabled-items.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <link rel="stylesheet" href="../inclusive-menu-button.css" />
    <style>
    /* basic page styles */
    html {
      font-size: 150%;
      font-family: sans-serif;
      padding: 1em;
    }

    * {
      font-size: inherit;
      font-family: inherit;
    }

    /* custom theming */
    button {
      padding: 0.25rem 1rem;
      background: black;
      color: white;
    }

    button:disabled {
      color: #999;
      background: #333;
    }

    button:focus {
      outline: none;
      background-color: #3737c8;
    }

    [data-inclusive-menu] [role="menuitem"] {
      margin-top: 3px;
    }
    </style>
    <title>
      Inclusive Menu Button | Disable Items Example
    </title>
  </head>
  <body>
    <div data-inclusive-menu>
     <button data-inclusive-menu-opens="difficulty">
       Difficulty
       <span aria-hidden="true">&#x25be;</span>
     </button>
     <div id="difficulty" data-inclusive-menu-from="left">
       <button disabled>Easy</button>
       <button>Medium</button>
       <button disabled>Very Tricky</button>
       <button>Incredibly Hard</button>
       <button>Impossible</button>
     </div>
    </div>
    <script src="../inclusive-menu-button.js"></script>
    <script>
      // Instantiation
      var exampleButton = document.querySelector('[data-inclusive-menu-opens]')
      var exampleMenuButton = new MenuButton(exampleButton)

      // Listen to choose event
      exampleMenuButton.on('choose', function(choice) {
        console.log('You chose "' + choice.textContent + '"')
      })
    </script>
  </body>
</html>


================================================
FILE: examples/menuitemcheckbox.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <link rel="stylesheet" href="../inclusive-menu-button.css" />
    <style>
    /* basic page styles */
    html {
      font-size: 150%;
      font-family: sans-serif;
      padding: 1em;
    }

    * {
      font-size: inherit;
      font-family: inherit;
    }

    /* custom theming */
    button {
      padding: 0.25rem 1rem;
      background: black;
      color: white;
    }

    button:focus {
      outline: none;
      background-color: #3737c8;
    }

    [data-inclusive-menu] [role^="menuitem"] {
      margin-top: 3px;
    }
    </style>
    <title>
      Inclusive Menu Button | menuitemcheckbox example
    </title>
  </head>
  <body>
    <div data-inclusive-menu>
     <button data-inclusive-menu-opens="typography">
       Typography
       <span aria-hidden="true">&#x25be;</span>
     </button>
     <div id="typography" data-inclusive-menu-from="left">
       <button>Ligatures</button>
       <button>Drop caps</button>
       <button>Hyphenation</button>
     </div>
    </div>
    <script src="../inclusive-menu-button.js"></script>
    <script>
      // Instantiation
      var exampleButton = document.querySelector('[data-inclusive-menu-opens]')
      var exampleMenuButton = new MenuButton(exampleButton, { checkable: 'many' })

      // Listen to choose event
      exampleMenuButton.on('choose', function (choice) {
        console.log('You chose "' + choice.textContent + '"')
      })
    </script>
  </body>
</html>


================================================
FILE: examples/menuitemradio.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <link rel="stylesheet" href="../inclusive-menu-button.css" />
    <style>
    /* basic page styles */
    html {
      font-size: 150%;
      font-family: sans-serif;
      padding: 1em;
    }

    * {
      font-size: inherit;
      font-family: inherit;
    }

    /* custom theming */
    button {
      padding: 0.25rem 1rem;
      background: black;
      color: white;
    }

    button:focus {
      outline: none;
      background-color: #3737c8;
    }

    [data-inclusive-menu] [role^="menuitem"] {
      margin-top: 3px;
    }
    </style>
    <title>
      Inclusive Menu Button | menuitemradio example
    </title>
  </head>
  <body>
    <div data-inclusive-menu>
     <button data-inclusive-menu-opens="difficulty">
       Difficulty
       <span aria-hidden="true">&#x25be;</span>
     </button>
     <div id="difficulty" data-inclusive-menu-from="left">
       <button>Easy</button>
       <button>Medium</button>
       <button>Very Tricky</button>
       <button>Incredibly Hard</button>
       <button>Impossible</button>
     </div>
    </div>
    <script src="../inclusive-menu-button.js"></script>
    <script>
      // Instantiation
      var exampleButton = document.querySelector('[data-inclusive-menu-opens]')
      var exampleMenuButton = new MenuButton(exampleButton, { checkable: 'one' })

      // Listen to choose event
      exampleMenuButton.on('choose', function (choice) {
        console.log('You chose "' + choice.textContent + '"')
      })
    </script>
  </body>
</html>


================================================
FILE: inclusive-menu-button.css
================================================
[data-inclusive-menu] {
  position: relative;
  display: inline-block;
}

[data-inclusive-menu-opens],
[data-inclusive-menu] [role^="menuitem"] {
  text-align: left;
  border: 0;
}

[data-inclusive-menu] [role="menu"] {
  position: absolute;
  left: 0;
}

[data-inclusive-menu] [data-inclusive-menu-from="right"] {
  left: auto;
  right: 0;
}

[data-inclusive-menu] [role^="menuitem"] {
  display: block;
  min-width: 100%;
  white-space: nowrap;
}

[data-inclusive-menu] [role^="menuitem"][aria-checked="true"]::before {
  content: '\2713\0020';
}


================================================
FILE: inclusive-menu-button.js
================================================
/* global define */

(function (global) {
  'use strict'

  // Constructor
  function MenuButton(button, options) {
    options = options || {}

    // The default settings
    this.settings = {
      checkable: 'none'
    }

    // Overwrite defaults where they are provided in options
    for (var setting in options) {
      if (options.hasOwnProperty(setting)) {
        this.settings[setting] = options[setting]
      }
    }

    // Save a reference to the element
    this.button = button

    // Add (initial) button semantics
    this.button.setAttribute('aria-haspopup', true)
    this.button.setAttribute('aria-expanded', false)

    // Get the menu
    this.menuId = this.button.getAttribute('data-inclusive-menu-opens')
    this.menu = document.getElementById(this.menuId)

    // If the menu doesn't exist
    // exit with an error referencing the missing
    // menu's id
    if (!this.menu) {
      throw new Error('Element `#' + this.menuId + '` not found.')
    }

    // Add menu semantics
    this.menu.setAttribute('role', 'menu')

    // Hide menu initially
    this.menu.hidden = true

    // Get the menu item buttons
    this.menuItems = this.menu.querySelectorAll('button')

    if (this.menuItems.length < 1) {
      throw new Error('The #' + this.menuId + ' menu has no menu items')
    }

    this.firstItem = this.menuItems[0]
    this.lastItem = this.menuItems[this.menuItems.length - 1]

    var focusNext = function (currentItem, startItem) {
      // Determine which item is the startItem (first or last)
      var goingDown = startItem === this.firstItem

      // helper function for getting next legitimate element
      function move(elem) {
        return (goingDown ? elem.nextElementSibling : elem.previousElementSibling) || startItem
      }

      // make first move
      var nextItem = move(currentItem)

      // if the menuitem is disabled move on
      while (nextItem.disabled) {
        nextItem = move(nextItem)
      }

      // focus the first one that's not disabled
      nextItem.focus()
    }.bind(this)

    Array.prototype.forEach.call(this.menuItems, function (menuItem) {
      // Disable menu button if all menu items are disabled
      var active = Array.prototype.filter.call(this.menuItems, function (item) {
        return !item.disabled
      })
      if (active.length < 1) {
        this.button.disabled = true
        return
      }

      // Add menu item semantics
      if (this.settings.checkable === 'one') {
        menuItem.setAttribute('role', 'menuitemradio')
      } else if (this.settings.checkable === 'many') {
        menuItem.setAttribute('role', 'menuitemcheckbox')
      } else {
        menuItem.setAttribute('role', 'menuitem')
      }

      // Prevent tab focus on menu items
      menuItem.setAttribute('tabindex', '-1')

      // Handle key presses for menuItem
      menuItem.addEventListener('keydown', function (e) {
        // Go to next/previous item if it exists
        // or loop around

        if (e.keyCode === 40) {
          e.preventDefault()
          focusNext(menuItem, this.firstItem)
        }

        if (e.keyCode === 38) {
          e.preventDefault()
          focusNext(menuItem, this.lastItem)
        }

        // Close on escape or tab
        if (e.keyCode === 27 || e.keyCode === 9) {
          this.toggle()
        }

        // If escape, refocus menu button
        if (e.keyCode === 27) {
          e.preventDefault()
          this.button.focus()
        }
      }.bind(this))

      menuItem.addEventListener('click', function (e) {
        // pass menu item node to select method
        this.choose(menuItem)

        // close menu and focus menu button
        this.close()
        this.button.focus()
      }.bind(this))
    }.bind(this))

    // Handle button click
    this.button.addEventListener('click', this.toggle.bind(this))

    // Also toggle on down arrow
    this.button.addEventListener('keydown', function (e) {
      if (e.keyCode === 40) {
        if (this.menu.hidden) {
          this.open()
        } else {
          this.menu.querySelector(':not([disabled])').focus()
        }
      }

      // close menu on up arrow
      if (e.keyCode === 38) {
        this.close()
      }
    }.bind(this))

    // initiate listeners object for public events
    this._listeners = {}
  }

  // Open method
  MenuButton.prototype.open = function () {
    this.button.setAttribute('aria-expanded', true)
    this.menu.hidden = false

    if (this.settings.checkable === 'one') {
      var checked = this.menu.querySelector('[aria-checked="true"]')
    }
    // Check the checked item if using menuitemradio
    if (checked) {
      checked.focus()
    } else {
      this.menu.querySelector('[role^="menuitem"]:not([disabled])').focus()
    }

    this.outsideClick = function (e) {
      if (!this.menu.contains(e.target) && !this.button.contains(e.target)) {
        this.close()
        document.removeEventListener('click', this.outsideClick.bind(this))
      }
    }.bind(this)

    document.addEventListener('click', this.outsideClick.bind(this))

    // fire open event
    this._fire('open')

    return this
  }

  // Close method
  MenuButton.prototype.close = function () {
    this.button.setAttribute('aria-expanded', false)
    this.menu.hidden = true

    // fire open event
    this._fire('close')

    return this
  }

  // Toggle method
  MenuButton.prototype.toggle = function () {
    var expanded = this.button.getAttribute('aria-expanded') === 'true'
    return expanded ? this.close() : this.open()
  }

  MenuButton.prototype.choose = function (choice) {
    if (this.settings.checkable === 'one') {
      // Remove aria-checked from whichever item it's on
      Array.prototype.forEach.call(this.menuItems, function (menuItem) {
        menuItem.removeAttribute('aria-checked');
      })

      // Set aria-checked="true" on the chosen item
      choice.setAttribute('aria-checked', 'true')
    }

    if (this.settings.checkable === 'many') {
      // check or uncheck item
      var checked = choice.getAttribute('aria-checked') === 'true' || false
      choice.setAttribute('aria-checked', !checked)
    }

    // fire open event
    this._fire('choose', choice)

    return this
  }

  MenuButton.prototype._fire = function (type, data) {
    var listeners = this._listeners[type] || []

    listeners.forEach(function (listener) {
      listener(data)
    })
  }

  MenuButton.prototype.on = function (type, handler) {
    if (typeof this._listeners[type] === 'undefined') {
      this._listeners[type] = []
    }

    this._listeners[type].push(handler)

    return this
  }

  MenuButton.prototype.off = function (type, handler) {
    var index = this._listeners[type].indexOf(handler)

    if (index > -1) {
      this._listeners[type].splice(index, 1)
    }

    return this
  }

  // Export MenuButton
  if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports = MenuButton
  } else if (typeof define === 'function' && define.amd) {
    define('MenuButton', [], function () {
      return MenuButton
    })
  } else if (typeof global === 'object') {
    // attach to window
    global.MenuButton = MenuButton
  }
}(this))


================================================
FILE: package.json
================================================
{
  "name": "inclusive-menu-button",
  "version": "0.1.4",
  "description": "A menu button module that implements the correct ARIA semantics and keyboard behavior.",
  "main": "inclusive-menu-button.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "lint": "standard ./inclusive-menu-button.js",
    "uglify": "uglifyjs inclusive-menu-button.js -o inclusive-menu-button.min.js",
    "extract-version": "cat package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[\",]//g' | tr -d '[[:space:]]'",
    "add-version": "echo \"/*! inclusive-menu-button $(npm run extract-version --silent) — © Heydon Pickering */\n$(cat inclusive-menu-button.min.js)\" > inclusive-menu-button.min.js",
    "build": "npm run uglify && npm run add-version",
    "precommit": "npm run build"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/Heydon/inclusive-menu-button.git"
  },
  "keywords": [
    "menu",
    "button",
    "ARIA",
    "accessibility",
    "dropdown"
  ],
  "author": "Heydon Pickering",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/Heydon/inclusive-menu-button/issues"
  },
  "homepage": "https://github.com/Heydon/inclusive-menu-button#readme",
  "devDependencies": {
    "husky": "^0.13.3",
    "standard": "^10.0.2",
    "uglify-js": "^2.8.22"
  }
}
Download .txt
gitextract_vdrgq3rv/

├── .gitignore
├── LICENSE
├── README.md
├── examples/
│   ├── basic.html
│   ├── disabled-items.html
│   ├── menuitemcheckbox.html
│   └── menuitemradio.html
├── inclusive-menu-button.css
├── inclusive-menu-button.js
└── package.json
Download .txt
SYMBOL INDEX (1 symbols across 1 files)

FILE: inclusive-menu-button.js
  function MenuButton (line 7) | function MenuButton(button, options) {
Condensed preview — 10 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (23K chars).
[
  {
    "path": ".gitignore",
    "chars": 29,
    "preview": ".DS_Store\n*.log\nnode_modules\n"
  },
  {
    "path": "LICENSE",
    "chars": 1210,
    "preview": "This is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, c"
  },
  {
    "path": "README.md",
    "chars": 4576,
    "preview": "# Inclusive Menu Button\n\nA **menu button** module that implements the correct ARIA semantics and keyboard behavior.\n\n## "
  },
  {
    "path": "examples/basic.html",
    "chars": 1642,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-wid"
  },
  {
    "path": "examples/disabled-items.html",
    "chars": 1783,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-wid"
  },
  {
    "path": "examples/menuitemcheckbox.html",
    "chars": 1654,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-wid"
  },
  {
    "path": "examples/menuitemradio.html",
    "chars": 1717,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-wid"
  },
  {
    "path": "inclusive-menu-button.css",
    "chars": 549,
    "preview": "[data-inclusive-menu] {\n  position: relative;\n  display: inline-block;\n}\n\n[data-inclusive-menu-opens],\n[data-inclusive-m"
  },
  {
    "path": "inclusive-menu-button.js",
    "chars": 7240,
    "preview": "/* global define */\n\n(function (global) {\n  'use strict'\n\n  // Constructor\n  function MenuButton(button, options) {\n    "
  },
  {
    "path": "package.json",
    "chars": 1344,
    "preview": "{\n  \"name\": \"inclusive-menu-button\",\n  \"version\": \"0.1.4\",\n  \"description\": \"A menu button module that implements the co"
  }
]

About this extraction

This page contains the full source code of the Heydon/inclusive-menu-button GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 10 files (21.2 KB), approximately 5.6k tokens, and a symbol index with 1 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!