dmax m-ex-cel Tests 0: Passed 0, Failed 0

Live runtime examples

0. uPlot host props and events

Edit the title or width and the chart should update immediately. Click Step data / Add point / Toggle points to change the first chart. Click Duplicate chart to create a second live instance. Click any point to inspect the emitted payload below.

This uses the in-page WC style: data-m-wc defines the host and normal data-m-ex drives host props/events. The same host could also be registered from JS with dmWc(...); see m-ex-cel for the separate-file style.


      

1. Deep Nested Signal Sync

<input type="text" data-m-ex@.^rw@user.name> · <input type="text" data-m-ex:user.name@.input> · <input type="number" data-m-ex@.^rw^num@user.age> · <input type="number" data-m-ex:user.age@.input^num> Type in the inputs and look for the greeting and age text to update while you type.

Hello, !

Age: years old

1.a data-m-ex Direction Examples

<span data-m-ex:.@user.name> · <input type="text" data-m-ex:user.name@.input> · <input type="text" data-m-ex@.^rw@user.name> Compare one-way signal->element, one-way element->signal, and two-way sync side by side.
Signal preview:

2. Style & Boolean Deep Sync

<input type="color" data-m-ex@.^rw@user.ui.theme-color> · <input type="color" data-m-ex:user.ui.theme-color@.input> · <div data-m-ex:.style.color@user.ui.theme-color> · <input type="range" data-m-ex@.^rw^num@user.ui.font-size> · <input type="range" data-m-ex:user.ui.font-size@.input^num> · <p data-m-ex:.style.font-size@user.ui.font-size="val + 'px'"> · <input type="checkbox" data-m-ex@.^rw@user.ui.is-active> Change the color, drag the font slider, and toggle the checkbox; style changes should apply immediately.
Color sync

Resizable text

Status:

3. Multiple Triggers & Targets

<button data-m-ex:count^inc@.> · <button data-m-ex:count^dec@.> · <button data-m-ex:count@.="0">
<strong data-m-ex:.@count> · <span data-m-ex:.:doubled@count="dm.count * 2"> · <button data-m-ex:.@.="`${el.id || ''} ${detail && detail.type ? detail.type : 'click'}`">
<button data-m-ex^once:once-test^inc@.> · <button data-m-ex^once:always-test^inc@.^always> · <button data-m-ex:guard-val^inc@.> Click the buttons and look for count, doubled value, trigger probe, once-only behavior, and guard labels to change.

Count:

Doubled:

4. Side Effects & Multiple Triggers

data-m-ex:.@count@#btn1@#btn2="console.log('Triggered!', dm.count) || '✓ Check console'" · data-m-ex:.@count@#btn1@#btn2="({ btn1: 'Button 1', btn2: 'Button 2' }[(trig && trig.root) || ''] || 'count') + ' -> ' + dm.count" Click either button and look for both console side effects and visible trigger-source text.

5. Cross-Element Property Sync

<input data-m-ex@.^rw@message> · <input data-m-ex:message@.input> · <p data-m-ex:.@#src.input> · <input readonly data-m-ex:.value@#src.input> Type in the source input and look for both the text preview and readonly mirror to track it while you type.

6. Window Events & Intervals

data-m-ex:.@_window.resize="window.innerWidth + 'px'" · data-m-ex:.@_interval.1000="new Date().toLocaleTimeString()" · data-m-ex:.@_timeout.1500="(detail && detail.ms) ? ('timeout ' + detail.ms) : ''" · data-m-ex:.@_viewed^once="'✓ Viewed (ratio: ' + (detail && detail.ratio != null ? detail.ratio.toFixed(2) : '?') + ')'" · data-m-ex:.@_init="'✓ Initialized (detail.type: ' + (detail && detail.type) + ')'" Resize the window, wait for the timer labels, and scroll the viewed line into view to see each special trigger fire.

Window width:

Current time:

Scroll into view:

On init:

6.a URL, history, WC defaults, and ^sel-all

data-m-ex:_history.push-state@. · data-m-ex:.@_window.hashchange^.location.hash · data-m-ex:.@wc-step · data-m-ex:wc-picked@.step-picked^ev · data-m-ex:.@_init^sel-all..sel-all-demo-item Push/replace the hash, watch the current hash react, then compare default WC prop/event behavior and selector-query reads.

Current hash:

WC default value prop:

WC custom event detail:

QSA count:

7. Default Props & Events

<input data-m-ex:.@#inp1.input> · <button data-m-ex:.@#btn3="'Clicked!'"> Type in the input and click the button; the labels below should mirror the default prop/event behavior.

7.a `^` / `^si` trigger picks

<input data-m-ex:val-prop-picked@.input^.data-foo-bar^num> · <strong data-m-ex:.@val-source^si.bar> · <strong data-m-ex:.@val-source^si.bar="val + 1"> Type in the input and click the increment button; compare the picked property value with the picked signal child value.
Typed text:
Picked data-foo-bar:
Signal child via ^si.bar:
Expression on picked child:

8. Classes & Display

<input type="checkbox" data-m-ex@.^rw@user.ui.is-active> · <div data-m-cl+active+!inactive@user.ui.is-active> · <p data-m-sh:.@user.ui.is-active> · <p data-m-sh:.@!user.ui.is-active> Toggle the checkbox and look for classes plus positive/negative visibility changes.
Status Box

Visible only when active

Visible only when NOT active

9. List Rendering (data-m-it)

data-m-it+#tpl-post@posts · data-m-cl+zebra-even+!zebra-odd@posts="$ix % 2 === 0" · data-m-it@posts · data-m-it+#tpl-thread@threads
data-m-ex:posts@. · data-m-ex:posts@. · data-m-ex:posts@. · data-m-ex:posts@. · data-m-ex:threads@. Use the list buttons and look for append/update/remove behavior plus stable zebra striping and nested thread refresh.

10. Modifiers demo

data-m-ex:mod-once^inc@.^once · data-m-ex:mod-deb^inc@.^debounce.120 · data-m-ex:mod-thr^inc@.^throttle.120 · data-m-ex:mod-and^inc@.^and.gate Click repeatedly and compare once-only, debounced, throttled, and gated behavior.

10.a Content vs Shape

data-m-ex:demo-parent@.="{ ...(dm.demoParent || {}), child: ((dm.demoParent && dm.demoParent.child) || 0) + 1 }"
data-m-ex:demo-parent@.="{ ...(dm.demoParent || {}), addedAt: 'shape' }" · data-m-ex:demo-parent@.="(({ addedAt, ...o }) => o)(dm.demoParent || {})" Compare content-only updates with shape changes; the shape subscriber should stay quiet until keys are added or removed.
Parent signal preview:

        
Content subscriber:
Shape subscriber:

10.b Constant Index Signals

<strong data-m-ex:.@post-objs[0].title> · <strong data-m-ex:.@post-objs[1].title> · <button data-m-ex:post-objs[0].title@.="'NewP0Title'"> · <button data-m-ex:post-objs[1].title@.="'NewP1Title'"> Click each setter and check that only the targeted indexed value changes.
Post 0:
Post 1:

State Tree (Live Debug)


        

11. Actions demo + OOB HTML morph

data-m-get^stat.req:post-result@.="'https://dummyjson.com/posts/1'" Run the request and look for grouped status fields plus the JSON payload below.
Busy: | Error: | Code:

      
data-m-get^stat.post-state:post-result-custom@.="'https://dummyjson.com/posts/1'" Same request, but read grouped custom status fields instead of the default ones.
Loading…
Error: | Code:

      
data-m-ex:draftPost@.="({ title: dmEl('new-title').value, body: dmEl('new-body').value, userId: +dmEl('new-user-id').value||0 })"
data-m-post^json^stat.req:created-post@.+draftPost^spread="'https://dummyjson.com/posts/add'" Edit the fields and submit; the created-post JSON should echo the sent body with response data.

      
data-m-ex:.dataset.payload@created-post^jsos.2 writes JSON text into a data-* attribute without spelling out a manual stringify expression.

      
data-m-get^html^stat.req@.="'/mock/oob'" Run it and watch the target block morph without a full replace.
Initial target content
data-m-get^sse^stat.sse-meta:sse-events@.="'/mock/dmax-sse'" Replays one short mocked SSE response through dmax's real SSE path, then closes. It updates signals and morphs the target once so the behavior is easy to inspect.
Message: | Count:
SSE status:
Initial SSE target

      

Asserts

Output is mirrored from console.log/error. The sticky top summary updates live.