# PeRyL

TypeScript/JavaScript library and tools for rapid server and client side web
applications development.

## HApp - PeRyL HSML App

`HApp` - HSML App, TypeScript/JavaScript Web UI framework for rapid SPA web
applications development based on Flux single directional data flow architecture.

Read [Tutorial](HApp.md) to learn how to write HApp.

See live [demo](https://peryl.gitlab.io/peryl/demo/js/hsml-app-js_demo.html)
or [demo](https://peryl.gitlab.io/peryl/demo/js/hsml-app-js-happi_demo.html).

HApp example code:

```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>PeRyL hsml app demo</title>
    <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Raleway">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>

<body>
    <div class="w3-container">
        <h1>PeRyL hsml app demo</h1>
        <div id="app"></div>
    </div>

    <script src="https://unpkg.com/peryl/dist/browser-umd/hsml-app.js"></script>
    <script>

        // Flux single directional data flow architecture actions
        const Actions = {
            title: "title",
            dec: "dec",
            inc: "inc",
            clear: "clear"
        }

        // Flux single directional data flow architecture state/store init
        function state() {
            return {
                title: "Counter",
                count: 77
            };
        }

        // Flux single directional data flow architecture view
        function view(state) {
            // HSML (Hyper Script Markup Language) HTML reprezentation
            return [
                ["h2",
                    // conditional class
                    { classes: [["w3-text-light-grey", !state.title]] },
                    state.title || "No title"
                ],
                ["p", [
                    ["label", "Title:"],
                    // Input element static classes declaration
                    ["input.w3-input.w3-border", {
                        type: "text",
                        name: "title",
                        value: new String(state.title),
                        // On click action definition
                        on: ["input", Actions.title]
                    }]
                ]],
                ["p", [
                    ["button.w3-button.w3-blue",
                        { on: ["click", Actions.clear] },
                        "Clear title"
                    ]
                ]],
                ["hr"],
                ["p", [
                    ["h2", [
                        "Count: ",
                        ["strong",
                            {
                                classes: [ // conditional classes
                                    ["w3-text-red", state.count < 77],
                                    ["w3-text-green", state.count > 77],
                                ]
                            },
                            state.count
                        ]
                    ]],
                    ["button.w3-button.w3-blue",
                        // On click action definition with attached data
                        { on: ["click", Actions.dec, 1] },
                        [["i.fa.fa-chevron-left"]]
                    ],
                    " ",
                    ["button.w3-button.w3-blue",
                        { on: ["click", Actions.inc, 2] },
                        [["i.fa.fa-chevron-right"]]
                    ]
                ]]
            ]
        };

        // Flux single directional data flow architecture dispatcher
        async function dispatcher(action, state, dispatch) {
            console.log("action:", action);

            switch (action.type) {
                // HSML App (HApp) lifecycle actions
                case HAppActions.init:
                case HAppActions.mount:
                case HAppActions.umount:
                    break;

                case Actions.title:
                    // Action data resolved automatically form input
                    state.title = action.data.value;
                    break;

                case Actions.inc:
                    state.count = state.count + action.data;
                    // async action call
                    setTimeout(() => dispatch(Actions.dec, 1), 1e3);
                    break;

                case Actions.dec:
                    state.count = state.count - action.data;
                    break;

                case Actions.clear:
                    state.title = "";
                    break;

                default:
                    console.warn("unhandled action:", action);
            }
        };

        const debug = true; // Console print engine lifecycle details

        // Run HApp application on html element with id "app"
        new HApp(state, view, dispatcher, "app", debug);

    </script>
</body>

</html>
```
