1660396565
Hidden Drawer Menu
Hidden Drawer Menu is a library for adding a beautiful drawer mode menu feature with perspective animation.
You can use a pre-defined menu or make a fully customized menu.
Use with default menu
import 'package:hidden_drawer_menu/model/hidden_drawer_menu.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<ScreenHiddenDrawer> itens = new List();
@override
void initState() {
itens.add(new ScreenHiddenDrawer(
new ItemHiddenMenu(
name: "Screen 1",
baseStyle: TextStyle( color: Colors.white.withOpacity(0.8), fontSize: 28.0 ),
colorLineSelected: Colors.teal,
),
FirstSreen()));
itens.add(new ScreenHiddenDrawer(
new ItemHiddenMenu(
name: "Screen 2",
baseStyle: TextStyle( color: Colors.white.withOpacity(0.8), fontSize: 28.0 ),
colorLineSelected: Colors.orange,
),
SecondSreen()));
super.initState();
}
@override
Widget build(BuildContext context) {
return HiddenDrawerMenu(
backgroundColorMenu: Colors.blueGrey,
backgroundColorAppBar: Colors.cyan,
screens: itens,
// typeOpen: TypeOpen.FROM_RIGHT,
// disableAppBarDefault: false,
// enableScaleAnimin: true,
// enableCornerAnimin: true,
// slidePercent: 80.0,
// verticalScalePercent: 80.0,
// contentCornerRadius: 10.0,
// iconMenuAppBar: Icon(Icons.menu),
// backgroundContent: DecorationImage((image: ExactAssetImage('assets/bg_news.jpg'),fit: BoxFit.cover),
// whithAutoTittleName: true,
// styleAutoTittleName: TextStyle(color: Colors.red),
// actionsAppBar: <Widget>[],
// backgroundColorContent: Colors.blue,
// elevationAppBar: 4.0,
// tittleAppBar: Center(child: Icon(Icons.ac_unit),),
// enableShadowItensMenu: true,
// backgroundMenu: DecorationImage(image: ExactAssetImage('assets/bg_news.jpg'),fit: BoxFit.cover),
);
}
}
Use with full customization menu
import 'package:hidden_drawer_menu/model/hidden_drawer_menu.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SimpleHiddenDrawer(
menu: Menu(),
screenSelectedBuilder: (position,controller) {
Widget screenCurrent;
switch(position){
case 0 : screenCurrent = Screen1(); break;
case 1 : screenCurrent = Screen2(); break;
case 2 : screenCurrent = Screen3(); break;
}
return Scaffold(
backgroundColor: backgroundColorContent,
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.menu),
onPressed: () {
controller.toggle();
}),
),
body: screenCurrent,
);
},
),
);
}
}
class Menu extends StatefulWidget {
@override
_SecondSreenState createState() => _MenuState();
}
class _MenuState extends State<SecondSreen> {
SimpleHiddenDrawerController controller;
@override
void didChangeDependencies() {
controller = SimpleHiddenDrawerController.of(context);
super.didChangeDependencies();
}
@override
Widget build(BuildContext context) {
return Container(
width: double.maxFinite,
height: double.maxFinite,
color: Colors.cyan,
padding: const EdgeInsets.all(8.0),
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
RaisedButton(
onPressed: () {
controller.setSelectedMenuPosition(0);
},
child: Text("Menu 1"),
),
RaisedButton(
onPressed: () {
controller.setSelectedMenuPosition(1);
},
child: Text("Menu 2"),
)
],
),
),
);
}
}
Actions
This actions is only accessible by the children of HiddenDrawerMenu or SimpleHiddenDrawer.
SimpleHiddenDrawerController.of(context).setSelectedMenuPosition(0);
SimpleHiddenDrawerController.of(context).toggle();
SimpleHiddenDrawerController.of(context).open();
SimpleHiddenDrawerController.of(context).close();
final controller = SimpleHiddenDrawerController.of(context);
controller.addListener((){
print(controller.position);
});
final controller = SimpleHiddenDrawerController.of(context);
controller.addListener((){
print(controller.state);
});
AnimatedDrawerController controller = AnimatedDrawerController(
vsync: this,
animationCurve:Curves.decelerate,
duration:const Duration(milliseconds: 350,
);
return AnimatedDrawerContent(
controller: controller,
whithPaddingTop: false, //(optional) default = false // Add padding top in de gesture equals Heigth of the AppBar
whithShadow: false, //(optional) default = false
isDraggable: true, //(optional) default = true
child: Screen(),
);
You can control actions by controller such as:
controller.toggle() // Open or Close
controller.open()
controller.close()
controller.move(percent) // moves to a specific position from 0 to 1 (0 = fully enclosed, 1 = fully opened)
Available settings
Run this command:
With Flutter:
$ flutter pub add hidden_drawer_menu
This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get
):
dependencies:
hidden_drawer_menu: ^3.0.1
Alternatively, your editor might support flutter pub get
. Check the docs for your editor to learn more.
Now in your Dart code, you can use:
import 'package:hidden_drawer_menu/hidden_drawer_menu.dart';
import 'package:flutter/material.dart';
import 'package:hidden_drawer_menu_demo/custom/example_custom_menu.dart';
import 'package:hidden_drawer_menu_demo/simple/example_hidden_drawer.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
width: 200.0,
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.blue),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(
20.0,
),
),
),
),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ExampleHiddenDrawer(),
),
);
},
child: Text(
"Default Example",
style: TextStyle(color: Colors.white),
),
),
),
SizedBox(
width: 200.0,
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.orange),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(
20.0,
),
),
),
),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ExampleCustomMenu()),
);
},
child: Text(
"Custom Menu Drawer",
style: TextStyle(color: Colors.white),
),
),
)
],
),
),
);
}
}
Download Details:
Author: RafaelBarbosatec
Source Code: https://github.com/RafaelBarbosatec/hidden_drawer_menu
1658920920
Context menu for electron input elements.
Installation
npm install --save electron-input-menu
Usage
This module expose a middleware for electron-contextmenu-middleware.
To use input context menu, you have to require this module and electron-contextmenu-middleware
in renderer
process and then mount this module as a middleware.
const inputMenu = require('electron-input-menu');
const context = require('electron-contextmenu-middleware');
context.use(inputMenu);
context.activate();
Keyboard shortcuts
electron-input-menu
can also register shortcuts on DOM document
object to handle copy, paste, cut, selectAll, undo and redo action. This is useful if your app doesn't provide an "Edit" menu that can handle this shortcuts.
To activate the shortcuts, call the registerShortcuts
method in renderer process.
const inputMenu = require('electron-input-menu');
inputMenu.registerShortcuts();
Related projects
electron-contextmenu-middleware - Build electron
context menus composing multiple middlewares functions.
debug-menu - Chrome-like "inspect element" context-menu.
Author: Parro-it
Source Code: https://github.com/parro-it/electron-input-menu
License: MIT license
1658849460
Provides a default menu for your electron applications, with convenience functions for multiplatform use and i18n.
Install using npm install electron-create-menu
.
Instead of importing Menu from electron
, import it from electron-create-menu
:
import Menu from "electron-create-menu";
// or
const Menu = require("electron-create-menu");
To get a default menu with platform-appropriate menu items and submenus, call Menu like so:
Menu();
Note: This API has to be called after the ready
event of app
module.
Menu always returns the menu object that Menu.buildFromTemplate
creates, so you can access instance methods on it.
Menu has two optional functions you can pass it
callback
function, where you can further edit (or replace) the generated menu.i18n
function where you can supply a function to use for translating the menu items.Menu(callback, i18n);
callback
receives two arguments:
{type: 'separator'}
for convenience.It expects you to return a menu-like object, either the edited default menu or a new menu.
To append a menu item to the menu, push an object onto menu and return it:
Menu((defaultMenu, separator) => {
defaultMenu.push({
label: "My custom menu!",
submenu: [
{ label: "my first item" },
separator(),
{ label: "my second item" }
]
});
return defaultMenu;
});
The i18n function is applied to the labels of the default menu. There are two things worth mentioning:
const i18next = require('i18next');
i18next.init({
/* assumed setup of i18next here */
}).then(function(t) {
Menu(
menu => {
menu.push({
label: i18next.t('My custom menu!'),
submenu: [
{label: i18next.t('my first item')},
{label: i18next.t('my second item')},
],
}),
return menu;
},
// This function is used to translate the default labels
i18next.t
);
});
Each item in your menu can have two new properties, showOn
and hideOn
. These accept a string or an array of strings that correspond to process.platform
values such as 'darwin' or 'win32'.
// this shows the menu item only on macOs
{
showOn: "darwin";
}
// this hides the menu item on windows and macOs
{
hideOn: ["win32", "darwin"];
}
With these, you can adapt your menu to multiple platforms without having to maintain multiple menu templates. See the default template for an example of a consolidated template.
You can also add a string or an array of strings as an argument to the separator function: separator('darwin')
. The given value is interpreted as the value for showOn
.
Menu((defaultMenu, separator) => {
defaultMenu.push({
label: "My custom menu!",
submenu: [
{
label: 'This is only shown on macOs',
showOn: 'darwin',
},
separator('darwin'), // this is shown only macOs
{label:
'This is hidden on windows'
hideOn: ['win32']
},
],
});
return defaultMenu;
});
Author: Kilian
Source Code: https://github.com/kilian/electron-create-menu
License: ISC license
1658755800
This is a Laravel 4-8 package for working with trees in relational databases.
Nested sets or Nested Set Model is a way to effectively store hierarchical data in a relational table. From wikipedia:
The nested set model is to number the nodes according to a tree traversal, which visits each node twice, assigning numbers in the order of visiting, and at both visits. This leaves two numbers for each node, which are stored as two attributes. Querying becomes inexpensive: hierarchy membership can be tested by comparing these numbers. Updating requires renumbering and is therefore expensive.
NSM shows good performance when tree is updated rarely. It is tuned to be fast for getting related nodes. It'is ideally suited for building multi-depth menu or categories for shop.
Suppose that we have a model Category
; a $node
variable is an instance of that model and the node that we are manipulating. It can be a fresh model or one from database.
Node has following relationships that are fully functional and can be eagerly loaded:
parent
children
ancestors
descendants
Moving and inserting nodes includes several database queries, so it is highly recommended to use transactions.
IMPORTANT! As of v4.2.0 transaction is not automatically started
Another important note is that structural manipulations are deferred until you hit save
on model (some methods implicitly call save
and return boolean result of the operation).
If model is successfully saved it doesn't mean that node was moved. If your application depends on whether the node has actually changed its position, use hasMoved
method:
if ($node->save()) {
$moved = $node->hasMoved();
}
When you simply creating a node, it will be appended to the end of the tree:
Category::create($attributes); // Saved as root
$node = new Category($attributes);
$node->save(); // Saved as root
In this case the node is considered a root which means that it doesn't have a parent.
// #1 Implicit save
$node->saveAsRoot();
// #2 Explicit save
$node->makeRoot()->save();
The node will be appended to the end of the tree.
If you want to make node a child of other node, you can make it last or first child.
In following examples, $parent
is some existing node.
There are few ways to append a node:
// #1 Using deferred insert
$node->appendToNode($parent)->save();
// #2 Using parent node
$parent->appendNode($node);
// #3 Using parent's children relationship
$parent->children()->create($attributes);
// #5 Using node's parent relationship
$node->parent()->associate($parent)->save();
// #6 Using the parent attribute
$node->parent_id = $parent->id;
$node->save();
// #7 Using static method
Category::create($attributes, $parent);
And only a couple ways to prepend:
// #1
$node->prependToNode($parent)->save();
// #2
$parent->prependNode($node);
You can make $node
to be a neighbor of the $neighbor
node using following methods:
$neighbor
must exists, target node can be fresh. If target node exists, it will be moved to the new position and parent will be changed if it's required.
# Explicit save
$node->afterNode($neighbor)->save();
$node->beforeNode($neighbor)->save();
# Implicit save
$node->insertAfterNode($neighbor);
$node->insertBeforeNode($neighbor);
When using static method create
on node, it checks whether attributes contains children
key. If it does, it creates more nodes recursively.
$node = Category::create([
'name' => 'Foo',
'children' => [
[
'name' => 'Bar',
'children' => [
[ 'name' => 'Baz' ],
],
],
],
]);
$node->children
now contains a list of created child nodes.
You can easily rebuild a tree. This is useful for mass-changing the structure of the tree.
Category::rebuildTree($data, $delete);
$data
is an array of nodes:
$data = [
[ 'id' => 1, 'name' => 'foo', 'children' => [ ... ] ],
[ 'name' => 'bar' ],
];
There is an id specified for node with the name of foo
which means that existing node will be filled and saved. If node is not exists ModelNotFoundException
is thrown. Also, this node has children
specified which is also an array of nodes; they will be processed in the same manner and saved as children of node foo
.
Node bar
has no primary key specified, so it will be created.
$delete
shows whether to delete nodes that are already exists but not present in $data
. By default, nodes aren't deleted.
Rebuilding a subtree
As of 4.2.8 you can rebuild a subtree:
Category::rebuildSubtree($root, $data);
This constraints tree rebuilding to descendants of $root
node.
In some cases we will use an $id
variable which is an id of the target node.
Ancestors make a chain of parents to the node. Helpful for displaying breadcrumbs to the current category.
Descendants are all nodes in a sub tree, i.e. children of node, children of children, etc.
Both ancestors and descendants can be eagerly loaded.
// Accessing ancestors
$node->ancestors;
// Accessing descendants
$node->descendants;
It is possible to load ancestors and descendants using custom query:
$result = Category::ancestorsOf($id);
$result = Category::ancestorsAndSelf($id);
$result = Category::descendantsOf($id);
$result = Category::descendantsAndSelf($id);
In most cases, you need your ancestors to be ordered by the level:
$result = Category::defaultOrder()->ancestorsOf($id);
A collection of ancestors can be eagerly loaded:
$categories = Category::with('ancestors')->paginate(30);
// in view for breadcrumbs:
@foreach($categories as $i => $category)
<small>{{ $category->ancestors->count() ? implode(' > ', $category->ancestors->pluck('name')->toArray()) : 'Top Level' }}</small><br>
{{ $category->name }}
@endforeach
Siblings are nodes that have same parent.
$result = $node->getSiblings();
$result = $node->siblings()->get();
To get only next siblings:
// Get a sibling that is immediately after the node
$result = $node->getNextSibling();
// Get all siblings that are after the node
$result = $node->getNextSiblings();
// Get all siblings using a query
$result = $node->nextSiblings()->get();
To get previous siblings:
// Get a sibling that is immediately before the node
$result = $node->getPrevSibling();
// Get all siblings that are before the node
$result = $node->getPrevSiblings();
// Get all siblings using a query
$result = $node->prevSiblings()->get();
Imagine that each category has many
goods. I.e. HasMany
relationship is established. How can you get all goods of $category
and every its descendant? Easy!
// Get ids of descendants
$categories = $category->descendants()->pluck('id');
// Include the id of category itself
$categories[] = $category->getKey();
// Get goods
$goods = Goods::whereIn('category_id', $categories)->get();
If you need to know at which level the node is:
$result = Category::withDepth()->find($id);
$depth = $result->depth;
Root node will be at level 0. Children of root nodes will have a level of 1, etc.
To get nodes of specified level, you can apply having
constraint:
$result = Category::withDepth()->having('depth', '=', 1)->get();
IMPORTANT! This will not work in database strict mode
All nodes are strictly organized internally. By default, no order is applied, so nodes may appear in random order and this doesn't affect displaying a tree. You can order nodes by alphabet or other index.
But in some cases hierarchical order is essential. It is required for retrieving ancestors and can be used to order menu items.
To apply tree order defaultOrder
method is used:
$result = Category::defaultOrder()->get();
You can get nodes in reversed order:
$result = Category::reversed()->get();
To shift node up or down inside parent to affect default order:
$bool = $node->down();
$bool = $node->up();
// Shift node by 3 siblings
$bool = $node->down(3);
The result of the operation is boolean value of whether the node has changed its position.
Various constraints that can be applied to the query builder:
Descendants constraints:
$result = Category::whereDescendantOf($node)->get();
$result = Category::whereNotDescendantOf($node)->get();
$result = Category::orWhereDescendantOf($node)->get();
$result = Category::orWhereNotDescendantOf($node)->get();
$result = Category::whereDescendantAndSelf($id)->get();
// Include target node into result set
$result = Category::whereDescendantOrSelf($node)->get();
Ancestor constraints:
$result = Category::whereAncestorOf($node)->get();
$result = Category::whereAncestorOrSelf($id)->get();
$node
can be either a primary key of the model or model instance.
After getting a set of nodes, you can convert it to tree. For example:
$tree = Category::get()->toTree();
This will fill parent
and children
relationships on every node in the set and you can render a tree using recursive algorithm:
$nodes = Category::get()->toTree();
$traverse = function ($categories, $prefix = '-') use (&$traverse) {
foreach ($categories as $category) {
echo PHP_EOL.$prefix.' '.$category->name;
$traverse($category->children, $prefix.'-');
}
};
$traverse($nodes);
This will output something like this:
- Root
-- Child 1
--- Sub child 1
-- Child 2
- Another root
Building flat tree
Also, you can build a flat tree: a list of nodes where child nodes are immediately after parent node. This is helpful when you get nodes with custom order (i.e. alphabetically) and don't want to use recursion to iterate over your nodes.
$nodes = Category::get()->toFlatTree();
Previous example will output:
Root
Child 1
Sub child 1
Child 2
Another root
Getting a subtree
Sometimes you don't need whole tree to be loaded and just some subtree of specific node. It is show in following example:
$root = Category::descendantsAndSelf($rootId)->toTree()->first();
In a single query we are getting a root of a subtree and all of its descendants that are accessible via children
relation.
If you don't need $root
node itself, do following instead:
$tree = Category::descendantsOf($rootId)->toTree($rootId);
To delete a node:
$node->delete();
IMPORTANT! Any descendant that node has will also be deleted!
IMPORTANT! Nodes are required to be deleted as models, don't try do delete them using a query like so:
Category::where('id', '=', $id)->delete();
This will break the tree!
SoftDeletes
trait is supported, also on model level.
To check if node is a descendant of other node:
$bool = $node->isDescendantOf($parent);
To check whether the node is a root:
$bool = $node->isRoot();
Other checks:
$node->isChildOf($other);
$node->isAncestorOf($other);
$node->isSiblingOf($other);
$node->isLeaf()
You can check whether a tree is broken (i.e. has some structural errors):
$bool = Category::isBroken();
It is possible to get error statistics:
$data = Category::countErrors();
It will return an array with following keys:
oddness
-- the number of nodes that have wrong set of lft
and rgt
valuesduplicates
-- the number of nodes that have same lft
or rgt
valueswrong_parent
-- the number of nodes that have invalid parent_id
value that doesn't correspond to lft
and rgt
valuesmissing_parent
-- the number of nodes that have parent_id
pointing to node that doesn't existsSince v3.1 tree can now be fixed. Using inheritance info from parent_id
column, proper _lft
and _rgt
values are set for every node.
Node::fixTree();
Imagine you have Menu
model and MenuItems
. There is a one-to-many relationship set up between these models. MenuItem
has menu_id
attribute for joining models together. MenuItem
incorporates nested sets. It is obvious that you would want to process each tree separately based on menu_id
attribute. In order to do so, you need to specify this attribute as scope attribute:
protected function getScopeAttributes()
{
return [ 'menu_id' ];
}
But now, in order to execute some custom query, you need to provide attributes that are used for scoping:
MenuItem::scoped([ 'menu_id' => 5 ])->withDepth()->get(); // OK
MenuItem::descendantsOf($id)->get(); // WRONG: returns nodes from other scope
MenuItem::scoped([ 'menu_id' => 5 ])->fixTree(); // OK
When requesting nodes using model instance, scopes applied automatically based on the attributes of that model:
$node = MenuItem::findOrFail($id);
$node->siblings()->withDepth()->get(); // OK
To get scoped query builder using instance:
$node->newScopedQuery();
Always use scoped query when eager loading:
MenuItem::scoped([ 'menu_id' => 5])->with('descendants')->findOrFail($id); // OK
MenuItem::with('descendants')->findOrFail($id); // WRONG
It is highly suggested to use database that supports transactions (like MySql's InnoDb) to secure a tree from possible corruption.
To install the package, in terminal:
composer require kalnoy/nestedset
For Laravel 5.5 and above users:
Schema::create('table', function (Blueprint $table) {
...
$table->nestedSet();
});
// To drop columns
Schema::table('table', function (Blueprint $table) {
$table->dropNestedSet();
});
For prior Laravel versions:
...
use Kalnoy\Nestedset\NestedSet;
Schema::create('table', function (Blueprint $table) {
...
NestedSet::columns($table);
});
To drop columns:
...
use Kalnoy\Nestedset\NestedSet;
Schema::table('table', function (Blueprint $table) {
NestedSet::dropColumns($table);
});
Your model should use Kalnoy\Nestedset\NodeTrait
trait to enable nested sets:
use Kalnoy\Nestedset\NodeTrait;
class Foo extends Model {
use NodeTrait;
}
If your previous extension used different set of columns, you just need to override following methods on your model class:
public function getLftName()
{
return 'left';
}
public function getRgtName()
{
return 'right';
}
public function getParentIdName()
{
return 'parent';
}
// Specify parent id attribute mutator
public function setParentAttribute($value)
{
$this->setParentIdAttribute($value);
}
If your tree contains parent_id
info, you need to add two columns to your schema:
$table->unsignedInteger('_lft');
$table->unsignedInteger('_rgt');
After setting up your model you only need to fix the tree to fill _lft
and _rgt
columns:
MyModel::fixTree();
Although this project is completely free for use, I appreciate any support!
Author: lazychaser
Source Code: https://github.com/lazychaser/laravel-nestedset
License:
1658599020
Context menu for your Electron app
Electron doesn't have a built-in context menu. You're supposed to handle that yourself. But it's both tedious and hard to get right. This module gives you a nice extensible context menu with spellchecking and items like Cut
/Copy
/Paste
for text, Save Image
for images, and Copy Link
for links. It also adds an Inspect Element
menu item when in development to quickly view items in the inspector like in Chrome.
This package can only be used in the main process.
$ npm install electron-context-menu
Requires Electron 10 or later.
const {app, BrowserWindow} = require('electron');
const contextMenu = require('electron-context-menu');
contextMenu({
showSaveImageAs: true
});
let mainWindow;
(async () => {
await app.whenReady();
mainWindow = new BrowserWindow({
webPreferences: {
spellcheck: true
}
});
})();
Advanced example:
const {app, BrowserWindow} = require('electron');
const contextMenu = require('electron-context-menu');
contextMenu({
prepend: (defaultActions, parameters, browserWindow) => [
{
label: 'Rainbow',
// Only show it when right-clicking images
visible: parameters.mediaType === 'image'
},
{
label: 'Search Google for “{selection}”',
// Only show it when right-clicking text
visible: parameters.selectionText.trim().length > 0,
click: () => {
shell.openExternal(`https://google.com/search?q=${encodeURIComponent(parameters.selectionText)}`);
}
}
]
});
let mainWindow;
(async () => {
await app.whenReady();
mainWindow = new BrowserWindow({
webPreferences: {
spellcheck: true
}
});
})();
The return value of contextMenu()
is a function that disposes of the created event listeners:
const dispose = contextMenu(); dispose();
Creates a context menu and returns a dispose function.
Type: object
Type: BrowserWindow | BrowserView | WebViewTag | WebContents
Window or WebView to add the context menu to.
When not specified, the context menu will be added to all existing and new windows.
Type: Function
Should return an array of MenuItem's to be prepended to the context menu.
The first argument is an array of default actions that can be used. The second argument is this parameters
object. The third argument is the BrowserWindow the context menu was requested for. The fourth argument is the context menu event.
MenuItem
labels may contain the placeholder {selection}
which will be replaced by the currently selected text as described in options.labels
.
Type: Function
Should return an array of MenuItem's to be appended to the context menu.
The first argument is an array of default actions that can be used. The second argument is this parameters
object. The third argument is the BrowserWindow the context menu was requested for. The fourth argument is the context menu event.
MenuItem
labels may contain the placeholder {selection}
which will be replaced by the currently selected text as described in options.labels
.
Type: boolean
Default: true
Show the Learn Spelling {selection}
menu item when right-clicking text.
Even if true
, the spellcheck
preference in browser window must still be enabled. It will also only show when right-clicking misspelled words.
Type: boolean
Default: true
Show the Look Up {selection}
menu item when right-clicking text.
Type: boolean
Default: true
Show the Search with Google
menu item when right-clicking text.
Type: boolean
Default: true
Show the Copy Image
menu item when right-clicking on an image.
Type: boolean
Default: false
Show the Copy Image Address
menu item when right-clicking on an image.
Type: boolean
Default: false
Show the Save Image
menu item when right-clicking on an image.
Type: boolean
Default: false
Show the Save Image As…
menu item when right-clicking on an image.
Type: boolean
Default: false
Show the Save Link As…
menu item when right-clicking on a link.
Type: boolean
Default: Only in development
Force enable or disable the Inspect Element
menu item.
Type: boolean
Default: false
Show the system Services
submenu when right-clicking text on macOS.
Note: Due to a bug in the Electron implementation, this menu is not identical to the "Services" submenu in the context menus of native apps. Instead, it looks the same as the "Services" menu in the main App Menu. For this reason, it is currently disabled by default.
Type: object
Default: {}
Override labels for the default menu items. Useful for i18n.
The placeholder {selection}
may be used in any label, and will be replaced by the currently selected text, trimmed to a maximum of 25 characters length. This is useful when localizing the Look Up “{selection}”
menu item, but can also be used in custom menu items, for example, to implement a Search Google for “{selection}”
menu item. If there is no selection, the {selection}
placeholder will be replaced by an empty string. Normally this placeholder is only useful for menu items which will only be shown when there is text selected. This can be checked using visible: parameters.selectionText.trim().length > 0
when implementing a custom menu item, as shown in the usage example above.
Format:
{
labels: {
copy: 'Copiar',
saveImageAs: 'Guardar imagen como…',
lookUpSelection: 'Consultar “{selection}”'
}
}
Type: Function
Determines whether or not to show the menu. Can be useful if you for example have other code presenting a context menu in some contexts.
The second argument is this parameters
object.
Example:
{
// Doesn't show the menu if the element is editable
shouldShowMenu: (event, parameters) => !parameters.isEditable
}
Type: Function
This option lets you manually pick what menu items to include. It's meant for advanced needs. The default menu with the other options should be enough for most use-cases, and it ensures correct behavior, for example, correct order of menu items. So prefer the append
and prepend
option instead of menu
whenever possible.
The function passed to this option is expected to return MenuItem[]
. The first argument the function receives is an array of default actions that can be used. These actions are functions that can take an object with a transform property (except for separator
and inspect
). The transform function will be passed the content of the action and can modify it if needed. If you use transform
on cut
, copy
, or paste
, they will convert rich text to plain text. The second argument is this parameters
object. The third argument is the BrowserWindow the context menu was requested for. The fourth argument is an Array of menu items for dictionary suggestions. This should be used if you wish to implement spellcheck in your custom menu. The last argument is the context menu event.
Even though you include an action, it will still only be shown/enabled when appropriate. For example, the saveImage
action is only shown when right-clicking an image.
MenuItem
labels may contain the placeholder {selection}
which will be replaced by the currently selected text as described in options.labels
.
To get spellchecking, “Correct Automatically”, and “Learn Spelling” in the menu, please enable the spellcheck
preference in browser window: new BrowserWindow({webPreferences: {spellcheck: true}})
The following options are ignored when menu
is used:
showLookUpSelection
showCopyImage
showCopyImageAddress
showSaveImageAs
showSaveLinkAs
showInspectElement
showServices
showSearchWithGoogle
Default actions:
spellCheck
learnSpelling
separator
lookUpSelection
searchWithGoogle
cut
copy
paste
saveImage
saveImageAs
copyImage
copyImageAddress
copyLink
saveLinkAs
inspect
services
Example for actions:
{
menu: (actions, props, browserWindow, dictionarySuggestions) => [
...dictionarySuggestions,
actions.separator(),
actions.copyLink({
transform: content => `modified_link_${content}`
}),
actions.separator(),
{
label: 'Unicorn'
},
actions.separator(),
actions.copy({
transform: content => `modified_copy_${content}`
}),
{
label: 'Invisible',
visible: false
},
actions.paste({
transform: content => `modified_paste_${content}`
})
]
}
Type: Function
Called when the context menu is shown.
The function receives an Event
object.
Type: Function
Called when the context menu is closed.
The function receives an Event
object.
Author: Sindresorhus
Source Code: https://github.com/sindresorhus/electron-context-menu
License: MIT license
1658417820
debug-menu
Chrome-like "inspect element" context-menu for Electron
This module was extracted from electron-debug to keep it focused on its main features.
Context menu items
Inspect the clicked HTML element. It shows DevTools if it's not already opened.
Install
$ npm install --save-dev debug-menu
Usage
When you use this module in renderer process code, BrowserWindow
instance need to be opened with node integration enabled.
We usually load this module only if the DEBUG
environment variable is defined, to avoid end users of the app inadvertently opening DevTools.
const debugMenu = require('debug-menu');
debugMenu.install(); // activate context menu
// later, if needed
debugMenu.uninstall(); // deactivate context menu
API
Activate context menu. This method add a listener on window
DOM object contextmenu
event.
Expose a middleware context menu that can be mounted with electron-contextmenu-middleware. See related example
Deactivate context menu. This method remove the listener on window
object.
The debug Menu object template. You can use it to integrate with your own app context or BrowserWindow
menu.
BrowserWindow
instance to use for this Menu.
Type: BrowserWindow
Default: the currently focused BrowserWindow
.
Example
// ... require electron module
const debugMenu = require('debug-menu');
const win = new BrowserWindow();
const menu = Menu.buildFromTemplate([{
label: 'Debug',
submenu: debugMenu.windowDebugMenu(win)
}]);
if (process.platform !== 'darwin') {
win.setMenu(menu);
} else {
electron.Menu.setApplicationMenu(menu);
}
// ... show window
Middleware example
const debugMenu = require('debug-menu').middleware;
const context = require('electron-contextmenu-middleware');
context.use(debugMenu);
context.activate();
Related projects
electron-contextmenu-middleware - Build electron
context menus composing multiple middlewares functions.
electron-input-menu - Context menu for electron input elements.
Author: Parro-it
Source Code: https://github.com/parro-it/debug-menu
License: MIT license
1658343240
This is the Laravel version of our menu package adds some extras like convenience methods for generating URLs and macros.
Upgrading from version 1? There's a guide for that!
Menu::macro('main', function () {
return Menu::new()
->action('HomeController@index', 'Home')
->action('AboutController@index', 'About')
->action('ContactController@index', 'Contact')
->setActiveFromRequest();
});
<nav class="navigation">
{!! Menu::main() !!}
</nav>
Spatie is a webdesign agency based in Antwerp, Belgium. You'll find an overview of all our open source projects on our website.
You can install the package via composer:
composer require spatie/laravel-menu
Documentation is available at https://spatie.be/docs/menu.
Please see CHANGELOG for more information what has changed recently.
$ phpunit
Please see CONTRIBUTING for details.
If you've found a bug regarding security please mail security@spatie.be instead of using the issue tracker.
We invest a lot of resources into creating best in class open source packages. You can support us by buying one of our paid products.
We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on our contact page. We publish all received postcards on our virtual postcard wall.
Author: Spatie
Source Code: https://github.com/spatie/laravel-menu
License: MIT license
1657747560
High level way to create menubar desktop applications with Electron.
This module provides boilerplate for setting up a menubar application using Electron. All you have to do is point it at your index.html
and menubar
will handle the rest.
✅ Only one dependency, and one peer-dependency.
✅ Works on macOS, Windows and most Linuxes. See details.
✅ 💥 3.6kB minified + gzipped 💥
![]() | ![]() | ![]() |
---|---|---|
macOS Mojave 10.14 | Windows 10 | Ubuntu 18.04 |
yarn add menubar
Starting with your own new project, run these commands:
$ yarn add menubar
$ touch myApp.js
$ touch index.html
Fill index.html
with some HTML, and myApp.js
like this:
const { menubar } = require('menubar');
const mb = menubar();
mb.on('ready', () => {
console.log('app is ready');
// your app code here
});
Then use electron
to run the app:
$ electron myApp.js
Alternatively, see examples/hello-world
folder for a simple working example.
Menubar
ClassThe return value of menubar()
is a Menubar
class instance, which has these properties:
app
: the Electron App instance,window
: the Electron Browser Window instance,tray
: the Electron Tray instance,positioner
: the Electron Positioner instance,setOption(option, value)
: change an option after menubar is created,getOption(option)
: get an menubar option,showWindow()
: show the menubar window,hideWindow()
: hide the menubar windowSee the reference API docs.
menubar()
OptionsYou can pass an optional options object into the menubar({ ... })
function:
dir
(default process.cwd()
) - the app source directoryindex
(default file:// + opts.dir + index.html
) - The URL to load the menubar's browserWindow with. The url can be a remote address (e.g. http://
) or a path to a local HTML file using the file://
protocol.browserWindow
- BrowserWindow options to be passed to the BrowserWindow constructor, see Electron docs. Some interesting fields to passed down are:x
(default undefined
) - the x position of the windowy
(default undefined
) - the y position of the windowwidth
(default 400) - window widthheight
(default 400) - window heightalwaysOnTop
(default false) - if true, the window will not hide on bluricon
(default opts.dir + IconTemplate.png
) - the png icon to use for the menubar. A good size to start with is 20x20. To support retina, supply a 2x sized image (e.g. 40x40) with @2x
added to the end of the name, so icon.png
and icon@2x.png
and Electron will automatically use your @2x
version on retina screens.tooltip
(default empty) - menubar tray icon tooltip texttray
(default created on-the-fly) - an electron Tray
instance. if provided opts.icon
will be ignoredpreloadWindow
(default false) - Create BrowserWindow instance before it is used -- increasing resource usage, but making the click on the menubar load faster.loadUrlOptions
- (default undefined) The options passed when loading the index URL in the menubar's browserWindow. Everything browserWindow.loadURL supports is supported; this object is simply passed onto browserWindow.loadURLshowOnAllWorkspaces
(default true) - Makes the window available on all OS X workspaces.windowPosition
(default trayCenter and trayBottomCenter on Windows) - Sets the window position (x and y will still override this), check positioner docs for valid values.showDockIcon
(default false) - Configure the visibility of the application dock icon.showOnRightClick
(default false) - Show the window on 'right-click' event instead of regular 'click'See the reference API docs.
The Menubar
class is an event emitter:
ready
- when menubar
's tray icon has been created and initialized, i.e. when menubar
is ready to be used. Note: this is different than Electron app's ready
event, which happens much earlier in the processcreate-window
- the line before new BrowserWindow()
is calledbefore-load
- after create window, before loadUrl (can be used for require("@electron/remote/main").enable(webContents)
)after-create-window
- the line after all window init code is done and url was loadedshow
- the line before window.show()
is calledafter-show
- the line after window.show()
is calledhide
- the line before window.hide()
is called (on window blur)after-hide
- the line after window.hide()
is calledafter-close
- after the .window
(BrowserWindow) property has been deletedfocus-lost
- emitted if always-on-top option is set and the user clicks awaymenubar | Electron | Notes |
---|---|---|
9.x.x | 9.x.x | 10.x.x | 11.x.x | 12.x.x | 13.x.x | 14.x.x | 15.x.x | 16.x.x | 17.x.x | 18.x.x | 19.x.x | |
8.x.x | 8.x.x | |
7.x.x | 7.x.x | |
6.x.x | 4.x.x | 5.x.x | 6.x.x | Not recommended for security reasons |
<= 5.x.x | <= 3.x.x | Please, please don't use these old versions |
See the reference API docs.
mb.on('after-create-window', callback)
to run things after your app has loaded. For example you could run mb.window.openDevTools()
to open the developer tools for debugging, or load a different URL with mb.window.loadURL()
mb.on('focus-lost')
if you would like to perform some operation when using the option browserWindow.alwaysOnTop: true
mb.on('after-hide', () => { mb.app.hide() } )
or similartray.setContextMenu(contextMenu)
, and pass this custom tray to menubar: const mb = menubar({ tray });
. See this example for more information.mb.app.commandLine.appendSwitch('disable-backgrounding-occluded-windows', 'true');
Author: Maxogden
Source Code: https://github.com/maxogden/menubar
License: BSD-2-Clause license
1657549980
Menubar app for JIRA
Minira is built on top of Electron, Menubar and Angular 2. It is not a replacement for JIRA:s web interface, the goal is to list a number of important issues for the moment and have easy access to edit them.
Jira is coming from the Japanese word for Godzilla
, Gojira
. Minira
is the Japanese word for Minilla, Godzillas adopted son. 🎆
Clone this repo and:
npm install
Build:
webpack
Build the .app:
npm run build
Author: jenslind
Source Code: https://github.com/jenslind/minira
License: MIT
1657418400
Shows an icon in the menu bar with the status of docker and a simple menu to start/stop containers.
Why?
I often forget if docker is running and this gives a quick visual.
Running (can make a connection)
Not running (or at least cannot connect to one)
It can take a few seconds to update the status if connecting to a docker machine instance
Started container list (shows on top)
Stopped container list
A dmg
is provided in the releases
. Otherwise, in the source directory start with npm start
.
In version 0.1.0
a .docker-indicator.yaml
file in your home directory is optional. If no file is found, the default socket at /var/run/docker.sock
is used.
If connecting to a docker machine instance not available via a socket.
docker:
protocol: https
ip: 192.168.99.100
port: 2376
ca: /Users/user/.docker/machine/machines/default/ca.pem
cert: /Users/user/.docker/machine/machines/default/cert.pem
key: /Users/user/.docker/machine/machines/default/key.pem
Whale by Aditya Dipankar from the Noun Project
0.3.0
0.2.1
0.2.0
0.1.0
0.0.4
0.0.3
0.0.2
0.0.1
Author: khornberg
Source Code: https://github.com/khornberg/docker-indicator
License: Apache-2.0 license
1657354579
Monu is an open source process monitoring menu bar application for Mac OS. You can configure Monu to launch programs, and when Monu starts up it will start them. Additionally, it will monitor the processes and restart them if they crash.
Monu is a portmanteau of 'monitor' and 'menu'. It has two C/C++ dependencies, Electron (which includes iojs) and the mon process monitor.
Monu is currently ALPHA STATUS and is intended for developers/early adopters.
To download the latest version visit the releases page
How to use Monu
To configure Monu, click 'Open Config Folder' and open 'config.json' in a text editor. When you save and return to Monu your new configuration will be automatically loaded.
Be sure your JSON syntax is valid when editing the configuration. Here are supported options. These should be added as top level key/value pairs to 'config.json':
Adding Processes
In the 'config.json' file add processes to the 'processes' key. The key must be a name (lowercase letters and hypens) and the value must be the launch command. For example:
{
"logs": "./logs",
"pids": "./pids",
"processes": {
"web-1": "http-server . -p 8081",
"web-2": "http-server . -p 8082",
"web-3": "http-server . -p 8083"
}
}
Launch on Startup
When you open Monu.app, it will start all configured processes.
If you would like Monu.app to start when your Mac starts up, got to System Preferences > Users and Groups and add Monu.app to Login Items for your User.
Developing
npm install # installs electron and all the deps needed for monu npm start # runs the app in the electron wrapper npm run build # builds the mac app
Publishing
Before publishing, make sure that your repo is clean, and that you've created a tag for the latest commit. npm version [major|minor|patch]
will do this for you, increasing the package.json version, creating a commit and adding a tag.
You should see something like this:
🐈 make publish
rm -rf Monu.app Monu.zip # prevent duplicates in the final bundle
npm run build
> monu@1.0.4 build /Users/maxogden/src/js/monu
> electron-packager . Monu --platform=darwin --arch=x64 --version=0.26.0 --ignore=node_modules/electron
Wrote new app to /Users/maxogden/src/js/monu/Monu.app
ditto -c -k --sequesterRsrc --keepParent Monu.app Monu.zip
npm run publish
> monu@1.0.4 publish /Users/maxogden/src/js/monu
> publish-release --template notes.md --assets Monu.zip
? Git Tag: v1.0.4
? Github repository owner: maxogden
? Github repository name: monu
? Release Name: Monu v1.0.4 Alpha
Uploading Monu.zip
[=================================================>] 100.0% (1.17 MB/s)
Done! Published at: https://github.com/maxogden/monu/releases/tag/v1.0.4
Author: Maxogden
Source Code: https://github.com/maxogden/monu
License: BSD-2-Clause license
1657282620
Run Grunt tasks from OS X menubar.
Select your source dir and then run Grunt tasks from the menubar.
Download and extract.
npm run build
npm test
Author: jenslind
Source Code: https://github.com/jenslind/piglet
License: MIT license
1657277220
A tiny app that shows iTunes current playing song on Mac menu bar.
To download the latest version, visit the releases page.
npm install
npm start
to launch the appnpm run package
to package the appnpm run zip
to zip the app packageThe music note icon is made by Freepik from www.flaticon.com and licensed by CC BY 3.0.
Author: Cheeaun
Source Code: https://github.com/cheeaun/kyoku
License: MIT
1657275240
a tiny OS X menubar app to display the upcoming events and recently updated repos from webuild.sg
Applications
folder.npm i
run the app from command line without building it
npm start
build the app to create WeBuildSG.app.zip
npm run build
Author: Webuildsg
Source Code: https://github.com/webuildsg/osx
License: MIT license
1657224720
A SoundCloud player that lives in your menubar.
Installing
Download the latest release for OSX.
IntelliJ users be warned: This app hijacks the ⌘+Alt+L shortcurt used by IntelliJ to reformat code. See 40 and 77.
Developing
npm install
npm install -g electron
grunt
or grunt build
NODE_ENV=development electron .
$env:NODE_ENV="development"; electron .
set "NODE_ENV=development" & electron .
Author: gillesdemey
Source Code: https://github.com/gillesdemey/Cumulus
License: MIT license