Products

Play with some of the Features

const { state } = lemonade;

export default function Counter() {
    let count = state(0);

    const update = () => {
        count.value++;
    };
    
    /**
    * Count is instance of state, so count == 1 or count.value === 1
    */
    return render => render`
        <div>
            <h1>Total ${count}</h1>
            <button onclick=${update} class="button">
                Clicked ${count} ${count == 1 ? 'time' : 'times'}
            </button>
        </div>
    `
}
const { state } = lemonade;

export default function Count() {
    let color = state('white');

    const update = () => {
        color.value = color.value === 'yellow' ? 'white' : 'yellow';
    };

    return render => render`
        <div>
            <svg xmlns="http://www.w3.org/2000/svg"
                viewBox="0 -960 960 960"
                height="60px"
                width="60px"
                fill="#A7C4E5">
                <path d="M400-240q-33 0-56.5-23.5T320-320v-50q-57-39-88.5-100T200-600q0-117 81.5-198.5T480-880q117 0 198.5 81.5T760-600q0 69-31.5 129.5T640-370v50q0 33-23.5 56.5T560-240H400Zm0 160q-17 0-28.5-11.5T360-120q0-17 11.5-28.5T400-160h160q17 0 28.5 11.5T600-120q0 17-11.5 28.5T560-80H400Z"
                stroke="black" stroke-width="30" fill=${color} />
            </svg>
            <p><input type="button" value="Update" onClick=${update} /></p>
        </div>
    `
}
export default function Welcome() {
    this.status = true;

    const toggle = () => {
        this.status = ! this.status;
    };
    
    return render => render `<div>
        <Switch value="${this.status}" />
        <p><input type="button" value="Toogle" onclick="${toggle}" /></p>
    </div>`
}
export default function Tables() {

    this.rows = [
        { title:'Google', description: 'The google search engine...' },
        { title:'Bing', description: 'The microsoft search engine...' },
        { title:'Duckduckgo', description: 'Privacy in the first place...' },
    ];

    return render => render`
        <table>
            <thead>
               <tr>
                    <th>Title</th>
                    <th>Description</th>
                </tr>
            </thead>
            <tbody :loop=${this.rows}>
                <tr>
                    <td>{{this.title}}</td>
                    <td>{{this.description}}</td>
                </tr>
            </tbody>
        </table>
    `
}
let { onchange } = lemonade; 

export default function Persistence() {
    this.language = localStorage.getItem('language');

    onchange(() => {
        localStorage.setItem('language', this.language);
    });
    
    this.options = [
        { value: '', text: 'Choose one' },
        { value: 'en_GB', text: 'English' },
        { value: 'pt_BR', text: 'Portuguese' },
    ]

    // Loop will first load all options,
    // than binding the language to the select value 
    return render => render`
        <select :loop="this.options" :bind="this.language">
            <option value="{{this.value}}">{{this.text}}</option>
        </select>
    `
}
export default function Component() {
    const add = () => {
        this.data.push({ title: this.text });
        // Update the data property in the view
        this.refresh('data');
        // Reset label
        this.text = '';
    }

    const del = (e, itemOfTheArray) => {
        this.data.splice(this.data.indexOf(itemOfTheArray), 1);
        // Update the view
        this.refresh('data');
    }

    this.data = [
        { title: 'Create a presentation' },
        { title: 'Send the report' },
        { title: 'Return the call to Jorge' },
    ];

    return render => render`<div>
        <ul :loop="${this.data}">
            <li>
                <i>{{self.title}}</i>
                <span onclick="${del}"
                    style="cursor: pointer;"> (x)</span>
            </li>
        </ul>
        <input type="text" :bind="this.text" />
        <input type="button" value="Add" onclick="${add}" />
    </div>`;
}
export default function ColorChanger() {
    const rand = function() {
        return parseInt(Math.random() * 255);
    };

    const applyColor = (e) => {
        let color = [ rand(), rand(), rand() ];
        e.target.style.backgroundColor = 'rgb(' + color + ')';
        e.target.innerText = color;
    };

    // Color changer template.
    return render => render`
        <div class="grid">
            <div onmousemove=${applyColor}></div>
            <div onmousemove=${applyColor}></div>
            <div onmousemove=${applyColor}></div>
        </div>
    `
}
let { onchange } = lemonade; 

export default function Data() {
    this.size = 100;

    onchange(() => {
        this.grid.style.width = this.size + 'px';
        this.grid.style.height = this.size + 'px';
    });

    return render => render`
        <div>
            <label>
                <input type="range" :bind="this.size" min="0" max="200" />
            </label>
            <br/>
            <div class="square" :ref=${this.grid}>${this.size}</div>
        </div>
    `
}
export default function Tictactoe() {
    let text = [
        'can start the game',
        'turn to play',
        'won the game',
    ];

    // Check the board to see if there is a winner
    const isWinner = () => {
        return [
            [0,1,2], [3,4,5], [6,7,8], // Rows
            [0,3,6], [1,4,7], [2,5,8], // Columns
            [0,4,8], [2,4,6]           // Diagonals
        ].some(([a,b,c]) =>
            this.board[a].player &&
            this.board[a].player === this.board[b].player &&
            this.board[b].player === this.board[c].player
        );
    }

    /**
     * Click event handler
     * @param {MouseEvent} e
     */
    const click = (e) => {
        // Valid item to be clicked - only SPAN
        if (e.target.tagName === 'SPAN') {
            if (this.winner) {
                alert(this.title.textContent);
            } else {
                // No one picked the position yet
                if (! e.target.textContent) {
                    // Get the position of the element clicked
                    let index = Array.prototype.indexOf.call(e.target.parentNode.children, e.target);
                    // Selected the board
                    this.board[index].player = this.player;
                    // Switch the text element to refers the player's turn.
                    this.text = text[1];
                    if (isWinner()) {
                        // Switch the text element to refers the winner.
                        this.text = text[2];
                        this.winner = true;
                        // We have a winner
                        alert(this.title.textContent);
                    } else {
                        // Switch player's turn.
                        this.player = this.player === 'o' ? 'x' : 'o';
                    }
                }
            }
        }
    }

    /**
     * Reset the game variables
     */
    const reset = () => {
        // Player 0 (o) and Player 1 (x)
        this.player = 'o';
        // Update the instruction to the user
        this.text = text[0];
        // Property to define if already reached a winner.
        this.winner = false;
        // Reset the board with the 9 positions
        this.board = [{},{},{},{},{},{},{},{},{}];
    }

    // Start the game
    reset();

    // Game template
    return render => render`<div class="tictactoe">
        <h4 :ref="this.title">${this.player} ${this.text}</h4>
        <div lm-loop="${this.board}" class="board" onclick=${click}>
            <span>{{this.player}}</span>
        </div><br/>
        <input type="button" onclick=${reset} value="Reset the game" />
    </div>`
}
export default function Clock() {
    // Update clock hands
    const updateClock = () => {
        // Current time
        const now = new Date();
        // 360° / 60 = 6° per second
        this.second = now.getSeconds() * 6;
        // 360° / 60 = 6° per minute + smooth movement
        this.minute = now.getMinutes() * 6 + now.getSeconds() * 0.1;
        // 360° / 12 = 30° per hour + smooth movement
        this.hour = now.getHours() * 30 + now.getMinutes() * 0.5;
    }

    // Create marks
    let marks = [];
    for (let i = 0; i < 12; i++) {
        marks.push({ index: i*30 });
    }
    this.marks = marks;

    // Start counting
    setInterval(updateClock, 1000);

    // Initial configuration
    updateClock();

    return render => render`<div class="clock">
        <div class="face">
            <div class="marks" :loop="${this.marks}">
                <div class="mark" style="transform: rotate({{this.index}}deg)"></div>
            </div>
            <div class="hand hour" style="transform: rotate({{this.hour}}deg)"></div>
            <div class="hand minute" style="transform: rotate({{this.minute}}deg)"></div>
            <div class="hand second" style="transform: rotate({{this.second}}deg)"></div>
        </div>
    </div>`;
}