good
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:
5 ? 'GT5' : ''">
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.
' + dm.count">
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:
- alpha
- beta
- gamma
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@threadsdata-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.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.