{"id":15711267,"url":"https://github.com/extend-chrome/menus","last_synced_at":"2025-05-12T14:12:29.527Z","repository":{"id":62375834,"uuid":"203826826","full_name":"extend-chrome/menus","owner":"extend-chrome","description":"A powerful context menu API to take your Chrome extension to the next level.","archived":false,"fork":false,"pushed_at":"2023-10-16T17:32:00.000Z","size":578,"stargazers_count":14,"open_issues_count":6,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-12T14:12:15.536Z","etag":null,"topics":["alpha","chrome-extension","context-menu","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/extend-chrome.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"ko_fi":"jacksteam"}},"created_at":"2019-08-22T15:50:58.000Z","updated_at":"2024-11-13T11:18:29.000Z","dependencies_parsed_at":"2024-10-24T09:30:42.025Z","dependency_job_id":"127f441c-aed7-4073-a55f-79b737e52deb","html_url":"https://github.com/extend-chrome/menus","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extend-chrome%2Fmenus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extend-chrome%2Fmenus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extend-chrome%2Fmenus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/extend-chrome%2Fmenus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/extend-chrome","download_url":"https://codeload.github.com/extend-chrome/menus/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253754220,"owners_count":21958842,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alpha","chrome-extension","context-menu","typescript"],"created_at":"2024-10-03T21:12:21.104Z","updated_at":"2025-05-12T14:12:29.440Z","avatar_url":"https://github.com/extend-chrome.png","language":"TypeScript","funding_links":["https://ko-fi.com/jacksteam"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/extend-chrome/menus\" rel=\"noopener\"\u003e\n  \u003cimg width=200px height=200px src=\"https://i.imgur.com/TzC1KEy.png\" alt=\"@extend-chrome/menus logo\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003ch3 align=\"center\"\u003e@extend-chrome/menus\u003c/h3\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[![npm (scoped)](https://img.shields.io/npm/v/@extend-chrome/menus.svg)](https://www.npmjs.com/package/@extend-chrome/menus)\n[![GitHub last commit](https://img.shields.io/github/last-commit/extend-chrome/menus.svg)](https://github.com/extend-chrome/menus)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/extend-chrome/menus/blob/master/LICENSE)\n[![TypeScript Declarations Included](https://img.shields.io/badge/types-TypeScript-informational)](#typescript)\n\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[![Chrome Extension Tutorials on YouTube](https://img.shields.io/badge/Chrome%20Extension%20Tutorials-YouTube-c4302b.svg)](https://www.youtube.com/channel/UCVj3dGw75v8aHFYD6CL1tFg)\n[![ko-fi](https://img.shields.io/badge/Buy%20us%20a%20tea-ko--fi-29ABE0)](https://ko-fi.com/jacksteam)\n\n\u003c/div\u003e\n\n---\n\nA powerful context menu API to take your Chrome extension to the next level.\n\n\u003e This library is in alpha until further notice. Things may not work. The API may change between minor versions.\n\n## Table of Contents\n\n- [Getting Started](#getting_started)\n- [Usage](#usage)\n- [Features](#features)\n- [API](#options-api)\n\n## Getting started \u003ca name = \"getting_started\"\u003e\u003c/a\u003e\n\nYou will need to use a bundler like [Rollup](https://rollupjs.org/guide/en/), Parcel, or Webpack to include this library in the build of Chrome extension.\n\nSee [`rollup-plugin-chrome-extension`](https://github.com/extend-chrome/rollup-plugin-chrome-extension) for an easy way use Rollup to build your Chrome extension!\n\n### Installation\n\n```sh\n$ npm i @extend-chrome/menus\n```\n\n## Usage \u003ca name = \"usage\"\u003e\u003c/a\u003e\n\n```js\n// background.js\nimport { menus } from '@extend-chrome/menus'\n\nconst id = 'my-menu'\n\n// Create a menu\nmenus.create({ id, title: 'My Menu' })\n\n// Use the included Observable of menu item clicks\nmenus.clickStream.subscribe(([clickData, tab]) =\u003e {\n  console.log('They clicked', clickData.id)\n  console.log('In tab', tab.id)\n\n  menus.update({ id, title: 'Another Title' })\n})\n```\n\n## Features \u003ca name = \"features\"\u003e\u003c/a\u003e\n\n### Dynamic Context Menus\n\nA dynamic context menu is only available on HTML elements that match the CSS selector defined in its options.\n\n```js\nimport { menus } from '@extend-chrome/menus'\n\nmenus.create({\n  id: 'my-dynamic-menu',\n  title: 'I only show on H1 tags',\n  selector: 'h1',\n})\n```\n\nThis feature uses `chrome.tabs.executeScript` under the hood, so it only works on pages found in the manifest `permissions` field.\n\n```jsonp\n// manifest.json\n{\n  ...\n  permissions: ['https://www.youtube.com/*']\n  ...\n}\n```\n\n### RxJs Observables\n\nChrome extensions and RxJs are a match made in heaven. Take advantage of ready-made Observables of menu item clicks, creations, updates, and removals.\n\n```js\nimport { menus } from '@extend-chrome/menus'\n\nmenus.clickStream.subscribe(([clickData, tab]) =\u003e {\n  console.log('Menu Item Id', clickData.id)\n  console.log('Tab Id', tab.id)\n})\n```\n\n### Convenience Function `useMenu`\n\nThe function `useMenu` creates a menu item and returns a tuple array of an updater function and an Observable of clicks for that menu item.\n\n```js\nimport { useMenu } from '@extend-chrome/menus'\n\nconst menuOptions = {\n  id: 'menu1',\n  title: 'Menu Item One',\n  type: 'checkbox',\n  checked: false,\n}\n\nconst [\n  // Updates only this menu item\n  updateMenu,\n  // Emits only clicks for this menu item\n  menuClickStream,\n] = useMenu(menuOptions)\n\nmenuClickStream.subscribe(([clickData, tab]) =\u003e {\n  // No need to include menu id\n  // Toggle menu item checkbox\n  updateMenu({ checked: !clickData.checked })\n})\n```\n\n### Full TypeScript Support\n\n`@extend-chrome/menus` is written in TypeScript and includes type definitions. Functions and Observables are fully typed, so Intellisense works well.\n\n```typescript\nimport { useMenu, ContextMenuOptions } from '@extend-chrome/menus'\n\nconst menuOptions: ContextMenuOptions = {\n  id: 'menu1',\n  title: 'Menu Item One',\n}\n\nconst [updateMenu, menuClickStream]: [\n  (options: Partial\u003cContextMenuOptions\u003e) =\u003e void\n  Observable\u003c[ContextMenuClickData, chrome.tabs.Tab]\u003e\n] = useMenu(menuOptions)\n```\n\n## Options API \u003ca name = \"options-api\"\u003e\u003c/a\u003e\n\nFull documentation coming soon!\n\nThere's great TypeScript support however, so Intellisense is your friend in the meantime.\n\n![Intellisense is your friend](https://media.giphy.com/media/l0MYHEI0xktKCVjri/giphy.gif)\n\n\u003c!-- ### `useMenu(options)`\n\n### `menus.create(options)`\n### `menus.createStream`\n\n### `menus.update(options)`\n### `menus.updateStream`\n\n### `menus.remove(id)`\n### `menus.removeStream` --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fextend-chrome%2Fmenus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fextend-chrome%2Fmenus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fextend-chrome%2Fmenus/lists"}