npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ngx-blockly

v14.0.2

Published

An angular wrapper for google's blockly.

Downloads

612

Readme

NGX-Blockly

An angular wrapper for google's blockly

Setup

Installation

Install from npm repository:

npm install ngx-blockly --save

Sample

Example app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { NgxBlocklyModule } from 'ngx-blockly';

import 'blockly/blocks'; // needed if you want to use the blockly default blocks

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    NgxBlocklyModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {
}

'Example app.component.ts'

import {NgxBlocklyConfig } from 'ngx-blockly';

export class AppComponent {
    
    public config: NgxBlocklyConfig = {
        toolbox: '<xml id="toolbox" style="display: none">' +
                    '<block type="controls_if"></block>' +
                    '<block type="controls_repeat_ext"></block>' +
                    '<block type="logic_compare"></block>' +
                    '<block type="math_number"></block>' +
                    '<block type="math_arithmetic"></block>' +
                    '<block type="text"></block>' +
                    '<block type="text_print"></block>' +
                 '</xml>',
        scrollbars: true,
        trashcan: true
    };
}

Example app.component.html

<ngx-blockly [config]="config"></ngx-blockly>

Styling

ngx-blockly {
  position: absolute;
  width: 100%;
  height: 100%;
}

Configuration

Default Blockly Configuration (see https://developers.google.com/blockly/guides/get-started/web#configuration)

export class NgxBlocklyConfig {
    // Allows blocks to be collapsed or expanded. Defaults to true if the toolbox has categories, false otherwise.
    collapse?: boolean;
    // Allows blocks to have comments. Defaults to true if the toolbox has categories, false otherwise.
    comments?: boolean;
    // If false, don't inject CSS (providing CSS becomes the document's responsibility). Defaults to true.
    css?: boolean;
    // If false, don't inject CSS (providing CSS becomes the document's responsibility). Defaults to true.
    disable?: boolean;
    // Grid options.
    grid?: {
        spacing: number,
        length: number,
        colour: string,
        snap: boolean
    };
    // If true toolbox is horizontal, if false toolbox is vertical. Defaults to false.
    horizontalLayout?: boolean;
    // 	Maximum number of blocks that may be created. Useful for student exercises. Defaults to Infinity.
    maxBlocks?: number;
    // Map from block types to maximum number of blocks of that type that may be created. Undeclared types default to Infinity.
    maxInstances?: object;
    // Path from page (or frame) to the Blockly media directory. Defaults to "https://blockly-demo.appspot.com/static/media/"
    media?: string;
    // If true list and string operations should index from 1, if false index from 0. Defaults to true.
    oneBasedIndex?: boolean;
    // If true, prevent the user from editing. Supresses the toolbox and trashcan. Defaults to false.
    readOnly?: boolean;
    // If true, mirror the editor (for Arabic or Hebrew locales). Defaults to false.
    rtl?: boolean;
    // Sets whether the workspace is scrollable or not. Defaults to true if the toolbox has categories, false otherwise
    scrollbars?: boolean;
    // If false, don't play sounds (e.g. click and delete). Defaults to true.
    sounds?: boolean;
    // Defaults to classic theme if no theme is provided. (https://developers.google.com/blockly/guides/configure/web/themes)
    theme?: any;
    // Tree structure of categories and blocks available to the user
    toolbox?: string;
    // If "start" toolbox is on top (if horizontal) or left (if vertical and LTR) or right (if vertical and RTL).
    // If "end" toolbox is on opposite side. Defaults to "start".
    toolboxPosition?: string;
    // Displays or hides the trashcan. Defaults to true if the toolbox has categories, false otherwise.
    trashcan?: boolean;
    // Maximum number of deleted items that will appear in the trashcan flyout. '0' disables the feature. Defaults to '32'.
    maxTrashcanContents?: number;
    // Zoom Options.
    zoom?: {
        controls: boolean,
        wheel: boolean,
        startScale: number,
        maxScale: number,
        minScale: number,
        scaleSpeed: number
    };
    // Defaults to geras renderer if no renderer is provided.
    renderer?: string;
    // Map of plugin type to name of registered plugin or plugin class.
    plugins?: any;
}

``

Code Generation

import { Component } from '@angular/core';
import { NgxBlocklyConfig, NgxBlocklyGeneratorConfig } from 'ngx-blockly';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss']
})
export class AppComponent {

    public config: NgxBlocklyConfig = {
        toolbox: '<xml id="toolbox" style="display: none">' +
            '<block type="controls_if"></block>' +
            '<block type="controls_repeat_ext"></block>' +
            '<block type="logic_compare"></block>' +
            '<block type="math_number"></block>' +
            '<block type="math_arithmetic"></block>' +
            '<block type="text"></block>' +
            '<block type="text_print"></block>' +
            '</xml>',
        scrollbars: true,
        trashcan: true,
        generators: [
            NgxBlocklyGenerator.DART,
            NgxBlocklyGenerator.LUA,
            NgxBlocklyGenerator.JAVASCRIPT,
            NgxBlocklyGenerator.PHP,
            NgxBlocklyGenerator.PYTHON,
            NgxBlocklyGenerator.XML
        ],
        defaultBlocks: true,
    };
    

    onCode(code: string) {
        console.log(code);
    }
}
<ngx-blockly [config]="config" (javascriptCode)="onCode($event)" (pythonCode)="onCode($event)"></ngx-blockly>

Import/Export Blockly Project

    @ViewChild(NgxBlocklyComponent) workspace;

    // Returns formatted xml of workspace
    this.workspace.toXml();

    // Add xml to workspace (clears previous elements)
    this.workspace.fromXml(xml);

    // Append xml to workspace
    this.workspace.appendFromXml(xml);

Blockly Toolbox

XML-Definition

    public config: NgxBlocklyConfig = {
        toolbox: '<xml id="toolbox" style="display: none">' +
            '<block type="controls_if"></block>' +
            '<block type="controls_repeat_ext"></block>' +
            '<block type="logic_compare"></block>' +
            '<block type="math_number"></block>' +
            '<block type="math_arithmetic"></block>' +
            '<block type="text"></block>' +
            '<block type="text_print"></block>' +
            '</xml>',
        scrollbars: true,
        trashcan: true
    };

Toolbox with search

    public config: NgxBlocklyConfig = {
        toolbox: '<xml id="toolbox" style="display: none">' +
            '<block type="controls_if"></block>' +
            '<block type="controls_repeat_ext"></block>' +
            '<block type="logic_compare"></block>' +
            '<block type="math_number"></block>' +
            '<block type="math_arithmetic"></block>' +
            '<block type="text"></block>' +
            '<block type="text_print"></block>' +
            '</xml>',
        scrollbars: true,
        trashcan: true,
        plugins: {
            toolbox: NgxBlocklyToolbox
        }
    };

    // modify searchbar strings
    Blockly.Msg.SEARCH_PLACEHOLDER = 'my placeholder'
    Blockly.Msg.SEARCH_CATEGORY = 'my category name'

Toolbox Generator

import { Category } from './category';

public customBlocks: CustomBlock[] = [
    new TestBlock(),
    new DeviceBlock()
];

// https://developers.google.com/blockly/guides/configure/web/toolbox#xml_12
public buttons: Button[] = [
    new Button('NewButton', 'CallbackKey')
];

public labels: Label[] = [
    new Label('NewLabel', 'web-class')
];

public customCategory = new Category(
    'MyCategory',
    '#FF00FF',
    [...this.buttons, ...this.customBlocks, ...this.labels]
);

constructor(ngxToolboxBuilder : NgxToolboxBuilderService) {
    ngxToolboxBuilder.nodes = [
        this.customCategory,
        LOGIC_CATEGORY,
        LOOP_CATEGORY,
        MATH_CATEGORY,
        TEXT_CATEGORY,
        new Separator(), //Add Separator
        LISTS_CATEGORY,
        COLOUR_CATEGORY,
        VARIABLES_CATEGORY,
        FUNCTIONS_CATEGORY
    ];
    this.config.toolbox = ngxToolboxBuilder.build();
}
    # do not forget to add your customblocks
   <ngx-blockly [config]="config" [customBlocks]="customBlocks" (javascriptCode)="onCode($event)"></ngx-blockly>

Custom Block

declare var Blockly: any;

export class TestBlock extends CustomBlock {


    constructor() {
        // Add Mutator or further args if needed
        super('TestBlock');
        this.class = TestBlock;
    }

    defineBlock() {
        this.block.appendDummyInput()
            .appendField(this.type)
            .appendField(new Blockly.FieldImage('assets/testblock.png', 50, 50, '*'))
            .appendField(new Blockly.FieldImage(this.args[0], 50, 50, '*'));
        this.block.setOutput(true, 'Input');
        this.block.setColour(30);
        this.block.setTooltip('');
        this.block.setHelpUrl('');
    }

    toXML() {
        return '<block type="test"></block>';
    }

    toDartCode(block: CustomBlock): string | any[] {
        return 'Not implemented';
    }

    toJavaScriptCode(block: CustomBlock): string | any[] {
        return 'Not implemented';
    }

    toLuaCode(block: CustomBlock): string | any[] {
        return 'Not implemented';
    }

    toPHPCode(block: CustomBlock): string | any[] {
        return 'Not implemented';
    }

    toPythonCode(block: CustomBlock): string | any[] {
        return 'Not implemented';
    }


    onChange(changeEvent: any) {
        console.log(changeEvent);
    }
}

Theme

Customized theme can be specified in the theme option for NgxBlocklyConfig, and the format of the block style and category style is stated in the Themes.

Sample theme class (Using Google Blockly Classic theme):

export const blockStyles: BlockStyles = {
  logic_blocks: {
    colourPrimary: '210',
  },
};

export const categoryStyles: CategoryStyles = {
  logic_category: {
    colour: '210',
  },
}

export const componentStyle: ComponentStyle = {
   workspaceBackgroundColour: '#ff0000',
   toolboxBackgroundColour: '#00ff00',
   scrollbarColour: '#eeff33',
   insertionMarkerColour: '#FF0000',
   flyoutBackgroundColour: '#aaa000',
   flyoutOpacity: 1
   # See docs fore more options
}

export const exampleTheme: Theme = new Theme (
  'ThemeName',
  blockStyles,
  categoryStyles,
  componentStyle
)

When you have specified the theme used in Blockly workspace, you need to declare the corresponding block style/category style in block/category definition. Noted that once you have defined the theme option in NgxBlocklyConfig, then you need to manage color scheme of all blocks and categories.

Block Styling

{
  "type": "controls_if",
  "style": "logic_blocks", // Specify the block style to apply
}

Category Styling

<!-- Specify the category style to apply -->
<category name="Logic" categorystyle="logic_category">
</category>

Corresponding NgxBlocklyConfig

config: NgxBlocklyConfig = {
    theme: exampleTheme.createBlocklyTheme(),
  };

Eventlistener

At the moment it is possible to subscribe to workspace and toolbox change listeners.

<ngx-blockly 
    [config]="config" 
    (workspaceChange)="workspaceChange($event)"
    (toolboxChange)="toolboxChange($event)">
</ngx-blockly>