MMOframework
Why AI Playground Libraries Documentation Search Agency
FR EN

mmo.client

.jhs elements and reactive views, compiled in PHP, no node and no bundler.

What it is
The front-end half of the framework: .jhs custom elements and views bound to a reactive template runtime, served by the theme and its Sass, SimpleCSS and JavaScript compilers; pages with display levels (simple, standard, expert), guided tours (MMO.guide, a page's {page}.tour.json), long jobs followed live (<mmo-job>) and the developer console.
Depends on
mmo.core
Used by
mmo.edms, mmo.editor
From an AI agent
search_documentation {"query": "…", "package": "mmo.client"}

One file, three languages

The replay on the home page is one .jhs file of this site: its markup, its class and its style. mmo.client compiles it in PHP into the bundle this page loads: no node, no bundler, no watcher.

src/customElements/mmo-replay.jhs
<mmo-replay> <div id="frame" part="frame"> <div id="head" part="head"><slot name="title"></slot><span id="counter"></span></div> <div id="steps" part="steps"><slot></slot></div> <div id="done" part="done"><slot name="done"></slot></div> <div id="controls" part="controls"><slot name="controls"></slot></div> </div> <script> /** * Replays a recorded session one step at a time: an agent's tool calls, a deployment's log. * * The steps are the element's own children, written by the page (so they are text the page escaped, and * translated where the page is): the first `step` show, the next ones appear as the reader goes on. What * follows the last step goes in the `done` slot. The controls are the page's buttons too, in the `controls` * slot, each saying what it does with `data-replay`: `next`, `all` or `reset`. * * @attr step - how many steps show at first (1 by default) * @slot - the steps, in order * @slot title - what is replayed, above the steps * @slot done - shown once every step is * @slot controls - the buttons, each with `data-replay="next|all|reset"` * @part frame - the box around it all * @example <mmo-replay step="2"><span slot="title">session</span><p>one</p><p>two</p><p>three</p><button slot="controls" data-replay="next">Next</button></mmo-replay> */ class Replay { init() { super.init(); this.step = Math.max(1, parseInt(this.getAttribute('step') || '1', 10) || 1); //the buttons are the page's: a click on one reaches the host this.addEventListener('click', (e) => { const button = e.target.closest('[data-replay]'); if (!button) {return;} const action = button.getAttribute('data-replay'); if (action === 'next') {this.next();} else if (action === 'all') {this.show(this.steps.length);} else if (action === 'reset') {this.show(1);} }); //the steps may be written after the element is upgraded this.queryShadow('#steps slot').addEventListener('slotchange', () => this.show(this.step)); this.show(this.step); } /** @return {HTMLElement[]} the steps: the children in no named slot */ get steps() { return [...this.children].filter((child) => !child.slot); } /** Show one more step. */ next() { this.show(this.step + 1); } /** * Show the first `count` steps, and the `done` slot when they are all shown. * @param {number} count - between 1 and the number of steps */ show(count) { const steps = this.steps; //no step written yet (the element is upgraded before its children): keep what was asked for them if (!steps.length) {this.step = Math.max(1, count); return;} this.step = Math.min(Math.max(1, count), steps.length); steps.forEach((step, i) => {step.hidden = i >= this.step;}); this.toggleAttribute('done', this.step >= steps.length); this.queryShadow('#counter').textContent = this.step + ' / ' + steps.length; for (const button of this.querySelectorAll('[data-replay="next"], [data-replay="all"]')) {button.disabled = this.step >= steps.length;} } } </script> <style> :host {display: block;} #frame {background: $color.surface-2; border: 1px solid $color.line;} #head {display: flex; justify-content: space-between; gap: $space.md; padding: $space.sm $space.lg; border-bottom: 1px solid $color.line; font-family: $font.mono; font-size: $text.xs; color: $color.text-3;} #counter {white-space: nowrap;} #steps {padding: $space.lg; min-height: 260px; font-family: $font.mono; font-size: $text.sm; line-height: 1.9;} #done {display: none; padding: 0 $space.lg $space.lg;} :host([done]) #done {display: block;} #controls {display: flex; flex-wrap: wrap; gap: $space.sm; padding: $space.md $space.lg; border-top: 1px solid $color.line;} ::slotted([hidden]) {display: none;} </style> </mmo-replay>
the element it compiles to

1The steps are the page's own children.

2The element shows them one at a time.

3Its style is Simple CSS, on the design tokens.

Elements that ship with the framework

Change their attributes: they are the elements of the framework, running in this page.

  • PHP · 95 pages
  • JavaScript · 134 pages

Every class, function and element