Skip to content

Commit 96978bd

Browse files
committed
Publish as custom element
1 parent 377e94e commit 96978bd

9 files changed

+413
-261
lines changed

src/CustomElement.elm

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
port module CustomElement exposing (init, update, view, subscriptions)
2+
3+
import Html exposing (Html, div, text, h3)
4+
5+
6+
--import Html.Attributes exposing (class, classList)
7+
--import Html.Events exposing (onClick)
8+
9+
import Json.Decode exposing (Value, decodeValue)
10+
import JsonValue exposing (decoder)
11+
import Json.Form
12+
import Json.Schema.Definitions
13+
14+
15+
type alias Model =
16+
{ form : Json.Form.Model
17+
, editedValue : Maybe JsonValue.JsonValue
18+
}
19+
20+
21+
init : Value -> ( Model, Cmd Msg )
22+
init v =
23+
let
24+
schema = v
25+
|> decodeValue (Json.Decode.at [ "schema" ] Json.Schema.Definitions.decoder)
26+
|> Result.withDefault Json.Schema.Definitions.blankSchema
27+
28+
value = v
29+
|> decodeValue (Json.Decode.at [ "value" ] JsonValue.decoder)
30+
|> Result.toMaybe
31+
in
32+
{ form = Json.Form.init schema value
33+
, editedValue = value
34+
}
35+
! [ loadSnippet "traveller" ]
36+
37+
38+
type Msg
39+
= JsonFormMsg Json.Form.Msg
40+
| ChangeValue Value
41+
42+
43+
update : Msg -> Model -> ( Model, Cmd Msg )
44+
update message model =
45+
case message of
46+
ChangeValue v ->
47+
{ model | editedValue = v |> decodeValue JsonValue.decoder |> Result.toMaybe
48+
}
49+
! []
50+
51+
JsonFormMsg msg ->
52+
let
53+
( ( m, cmd ), exMsg ) =
54+
Json.Form.update msg model.form
55+
in
56+
{ model
57+
| form = m
58+
, editedValue =
59+
case exMsg of
60+
Json.Form.UpdateValue v ->
61+
v
62+
63+
_ ->
64+
model.editedValue
65+
}
66+
! [ cmd |> Cmd.map JsonFormMsg ]
67+
68+
69+
view : Model -> Html Msg
70+
view model =
71+
model.form
72+
|> Json.Form.view
73+
|> Html.map JsonFormMsg
74+
75+
76+
port loadSnippet : String -> Cmd msg
77+
78+
79+
port valueChange : (Value -> msg) -> Sub msg
80+
81+
82+
subscriptions : Model -> Sub Msg
83+
subscriptions _ =
84+
valueChange ChangeValue

src/Demo.elm

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ initialShowcase =
2727
init : ( Model, Cmd Msg )
2828
init =
2929
{ showcase = initialShowcase
30-
, form = Json.Form.init (getSnippet initialShowcase)
30+
, form = Json.Form.init (getSnippet initialShowcase) Nothing
3131
, editedValue = Nothing
3232
, expandedNodes = [ [] ]
3333
}
@@ -69,7 +69,7 @@ update message model =
6969
! []
7070

7171
SetShowcase s ->
72-
{ model | showcase = s, form = Json.Form.init (getSnippet s), editedValue = Nothing } ! []
72+
{ model | showcase = s, form = Json.Form.init (getSnippet s) Nothing, editedValue = Nothing } ! []
7373

7474

7575
view : Model -> Html Msg

src/Json/Form.elm

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ type alias Msg =
3636
Definitions.Msg
3737

3838

39-
init : Schema -> Model
39+
init : Schema -> Maybe JsonValue -> Model
4040
init =
4141
Definitions.init
4242

src/Json/Form/Definitions.elm

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ type alias Model =
1515
}
1616

1717

18-
init : Schema -> Model
19-
init s =
18+
init : Schema -> Maybe JsonValue -> Model
19+
init s v =
2020
{ schema = s
2121
, focused = Nothing
22-
, value = Nothing
22+
, value = v
2323
, errors = Dict.empty
2424
, beingEdited = []
2525
, editedNumber = ""

src/JsonFormCustomElement.elm

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module JsonFormCustomElement exposing (main)
2+
3+
import Html
4+
import CustomElement exposing (init, update, view, subscriptions)
5+
6+
7+
main =
8+
Html.programWithFlags
9+
{ init = init
10+
, update = update
11+
, view = view
12+
, subscriptions = subscriptions
13+
}

src/custom-element.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const Elm = require('./JsonFormCustomElement');
2+
const css = require('../stylesheets/standalone.css').toString();
3+
4+
5+
customElements.define('json-viewer',
6+
class extends HTMLElement {
7+
8+
static get observedAttributes() {
9+
return ['value'];
10+
}
11+
12+
constructor() {
13+
super();
14+
15+
const appRoot = document.createElement('div');
16+
const appStyles = document.createElement('style');
17+
appStyles.textContent = css;
18+
19+
const shadowRoot = this.attachShadow({mode: 'open'});
20+
shadowRoot.appendChild(appStyles);
21+
shadowRoot.appendChild(appRoot);
22+
23+
const json = this.getAttribute('value');
24+
const schema = JSON.parse(this.getAttribute('schema'));
25+
const value = JSON.parse(json);
26+
const app = Elm.Main.embed(appRoot, { schema, value });
27+
this.app = app;
28+
}
29+
30+
attributeChangedCallback(name, oldValue, newValue) {
31+
switch (name) {
32+
case 'value':
33+
this.app.ports.valueChange.send(JSON.parse(newValue));
34+
break;
35+
}
36+
}
37+
});

stylesheets/standalone.css

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import './json-form.css';

webpack.config.js

+20-2
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,42 @@ var merge = require("webpack-merge");
44
var CopyWebpackPlugin = require("copy-webpack-plugin");
55
var HTMLWebpackPlugin = require("html-webpack-plugin");
66
const CleanWebpackPlugin = require("clean-webpack-plugin");
7+
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
8+
79

810
var TARGET_ENV =
911
process.env.npm_lifecycle_event === "prod" ? "production" : "development";
1012
var filename = TARGET_ENV == "production" ? "[name]-[hash].js" : "index.js";
1113

1214
var common = {
13-
entry: "./src/index.js",
15+
entry: {
16+
'index.js': "./src/index.js",
17+
'custom-element': './src/custom-element'
18+
},
1419
output: {
1520
path: path.join(__dirname, "dist"),
1621
// webpack -p automatically adds hash when building for production
17-
filename: filename
22+
filename: '[name].js'
1823
},
1924
plugins: [
2025
new HTMLWebpackPlugin({
2126
// using .ejs prevents other loaders causing errors
2227
template: "src/index.ejs",
2328
// inject details of output file at end of body
2429
inject: "body"
30+
}),
31+
new UglifyJsPlugin({
32+
uglifyOptions: {
33+
ecma: 6,
34+
compress: {
35+
pure_funcs: "F2,F3,F4,F5,F6,F7,F8,F9",
36+
pure_getters: true,
37+
keep_fargs: false,
38+
unsafe_comps: true,
39+
unsafe_methods: true,
40+
unsafe_arrows: true
41+
}
42+
}
2543
})
2644
],
2745
resolve: {

0 commit comments

Comments
 (0)