Go to file
Astrian Zheng 3cdf0a28ef
All checks were successful
Quality Check & Publish / quality (push) Successful in 26s
Quality Check & Publish / quality-failed-webhook (push) Has been skipped
Quality Check & Publish / publish (push) Successful in 27s
Quality Check & Publish / publish-failed-webhook (push) Has been skipped
fix: type challenges gived up ˊ_>ˋ
2025-05-21 22:53:44 +10:00
.gitea/workflows ci: add actions in github platform 2025-05-21 19:34:32 +10:00
.github/workflows ci: add actions in github platform 2025-05-21 19:34:32 +10:00
src fix: type challenges gived up ˊ_>ˋ 2025-05-21 22:53:44 +10:00
.gitignore chore: ignore vim swap file 2025-05-21 13:38:35 +10:00
.npmignore Add .npmignore to exclude src/ and .gitea directories 2025-05-16 10:47:15 +10:00
biome.json chore: linting the files 2025-05-16 19:48:50 +10:00
LICENSE Add license 2025-05-15 06:34:13 +00:00
package-lock.json Add ComponentOptions type definition and update index.ts to use it 2025-05-21 13:37:31 +10:00
package.json fix: rollup compress the utils folder 2025-05-21 22:12:32 +10:00
readme.md Fix formatting in README for clarity 2025-05-16 10:25:55 +10:00
rollup.config.js fix: rollup compress the utils folder 2025-05-21 22:12:32 +10:00
tsconfig.json fix: type challenges gived up ˊ_>ˋ 2025-05-21 22:53:44 +10:00

Laterano

Lateranians love sweets, and it is said that a qualified Lateranian knows how to make at least twenty kinds of desserts.

Lateranians have even created the unique dessert “Cactus Tart,” which is loved by the Pope.

ref

Laterano is a front-end framework based on the native support of vanilla-favoured Web Component feature. It allows you to adapt modern MVVM development workflows with the features, abilities, and benefits of Shadow DOM, including native componentized support, styling management, and more.

Note: Laterano was developed for learning purposes originally and is still under active development. We do not recommend using it inside a production environment.

How to use

  1. Create a vanilla front-end project with Vite. Input npm init vite inside the terminal, then choose “Vanilla” and “TypeScript”
  2. Install Laterano through npm
  3. Define your component and use it inside your HTML
  4. Done!

Here is a sample code for a simple to-do app:

import defineComponent from 'laterano'
import './style.css'

defineComponent({
  tag: 'x-todolist',
  template: `
    <div class="container">
      <h1>Todo List</h1>
      <input type="text" placeholder="Add a new todo" %connect="todoinput" @keyup="e => this.triggerFunc('keyDownListener', e)" />

      <ul class="todo-list">
        <li %if="todos.length === 0">
          <span class="empty">
            No todos yet! Add one above.
          </span>
        </li>
        <li %for="item in todos" %key="item.time" class="todo-item">
          <button @click="this.triggerFunc('removeTodo', item.time)">
            {{ item.name }}
          </button>
        </li>
      </ul>

      
    </div>
  `,
  style: `
    div.container {
      display: flex;
      flex-direction: column;
      align-items: center;
      min-height: 100vh;
      background-color: #f0f0f0;
    }
    div.container input {
      width: 20rem;
      padding: 0.75rem;
      margin-bottom: 1.5rem;
      border: 1px solid #ccc;
      border-radius: 0.5rem;
      font-size: 1rem;
    }
    div.container input:focus {
      border-color: #007bff;
      outline: none;
    }

    div.container ul.todo-list {
      list-style-type: none;
      padding: 0;
      width: 20rem;
      border: 1px solid #ccc;
      border-radius: 0.5rem;
      overflow: hidden;
    }
    div.container ul.todo-list li {
      padding: 10px;
      border-bottom: 1px solid #ccc;
      background-color: #fff;
    }
    div.container ul.todo-list li.todo-item {
      cursor: pointer;
    }
    div.container ul.todo-list li:hover {
      background-color: #f9f9f9;
    }
    div.container ul.todo-list li:last-child {
      border-bottom: none;
    }

    div.container ul.todo-list li button {
      background: none;
      border: none;
      width: 100%;
      text-align: left;
      font-size: 1rem;
      cursor: pointer;
    }

    span.empty {
      color: #999;
      cursor: default;
    }
  `,
  states: {
    todos: [
      
    ],
    todoinput: ''
  },
  funcs: {
    keyDownListener: function (event: KeyboardEvent) {
      if(event.key !== 'Enter') return
      if ((this as any).getState('todoinput') === "") return
      this.setState("todos", [
        ...(this as any).getState('todos'),
        {
          name: (this as any).getState('todoinput'),
          time: new Date().getTime()
        }
      ])
      this.setState("todoinput", "")
    },
    removeTodo: function (time: number) {
      const todos = (this as any).getState('todos')
      let list = structuredClone(todos)
      const index = list.findIndex((item: { time: number }) => item.time === time)
      if (index !== -1) {
        list.splice(index, 1)
        this.setState('todos', list)
      }

    }
  }
})
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + TS</title>
  </head>
  <body>
    <div id="app">
      <div>
        <x-todolist></x-todolist>
      </div>
    </div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>