Skip to content

Instantly share code, notes, and snippets.

@dmsnell
Created Nov 21, 2018
Embed
What would you like to do?
Gutenberg blocks written in Elm
port module Main exposing (Flags, Model, Msg(..), init, main, subscriptions, update, view)
import Browser
import Html exposing (Html, button, div, input, text)
import Html.Attributes exposing (type_)
import Html.Events exposing (onClick, onInput)
port setAttributes : Flags -> Cmd msg
port getAttributes : (Flags -> msg) -> Sub msg
subscriptions model = getAttributes (\flags -> GetAttributes flags)
main =
Browser.element
{ init = init
, update = update
, view = view
, subscriptions = subscriptions
}
type alias Flags =
{ count : Int
}
type Msg
= Increment
| Decrement
| GetAttributes Flags
type alias Model =
Int
init : Flags -> ( Model, Cmd msg )
init flags =
( flags.count, Cmd.none )
update msg model =
let
next =
case msg of
Increment ->
model + 1
Decrement ->
model - 1
GetAttributes flags ->
Debug.log "Count" flags.count
in
( next, setAttributes { count = next } )
view model =
div []
[ button [ onClick Decrement ] [ text "-" ]
, div [] [ text (String.fromInt model) ]
, button [ onClick Increment ] [ text "+" ]
]
/**
* External dependencies
*/
import React from "react";
/**
* WordPress dependencies
*/
import { Component } from "@wordpress/element";
export const name = "core/elm";
let hasLoaded = false;
class ElmC extends Component {
constructor(...args) {
super(...args);
this.node = React.createRef();
if ( ! hasLoaded ) {
hasLoaded = true;
const script = document.createElement('script');
script.setAttribute('src', '/public/path/to/elm-block.js');
document.getElementsByTagName('body')[0].appendChild(script);
}
}
componentDidMount() {
const loader = () => {
if ( ! ( window.Elm && this.node && this.node.current ) ) {
return setTimeout( loader, 200 );
}
this.app = window.Elm.Main.init( {
node: this.node.current,
flags: this.props.attributes,
} );
this.app.ports.setAttributes.subscribe( data => this.props.setAttributes( data ) );
};
loader();
}
componentDidUpdate( prevProps ) {
if ( this.props.attributes !== prevProps.attributes && this.app && this.app.ports && this.app.ports.getAttributes ) {
this.app.ports.getAttributes.send( this.props.attributes );
}
}
render() {
return <div ref={this.node}>Loading…</div>;
}
}
export const settings = {
title: "Elm Block",
description: "Wraps an Elm component",
category: "common",
attributes: {
count: {
type: 'number',
default: 0,
}
},
edit: ElmC,
save: () => <div>Elm Block!</div>
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment