Skip to content

Instantly share code, notes, and snippets.

@dmsnell
Created November 21, 2018 16:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmsnell/ab38d8340296d7b826576bc5ce31b9dc to your computer and use it in GitHub Desktop.
Save dmsnell/ab38d8340296d7b826576bc5ce31b9dc to your computer and use it in GitHub Desktop.
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