Installation
Get MTxFlow up and running in your project.
CDN (Script Tag)
The fastest way to get started. Include the CSS and JS bundle directly:
<link rel="stylesheet" href="path/to/mtx-flow.bundle.css">
<script src="path/to/mtx-flow.bundle.min.js"></script>
<script>
// Everything is under window.mtx
console.log(mtx.VERSION); // "1.0.0-alpha.1"
</script>
NPM / Yarn
npm install @mtx/flow
# or
yarn add @mtx/flow
import { State, Modal, Dom, Utils, Icons } from '@mtx/flow';
const state = new State('app');
state.set('theme', 'dark');
Bundle Sizes
| File | Size | Format |
|---|
mtx-flow.bundle.min.js | ~21 KB | IIFE (window.mtx) |
mtx-flow.esm.js | ~37 KB | ES Module |
mtx-flow.bundle.css | ~10 KB | CSS |
Quick Start
A 2-minute walkthrough of the most common APIs.
1. Show an Alert
// Promise-based, no callback spaghetti
await mtx.Modal.alert('Welcome!', 'Hello World');
console.log('User clicked OK');
→ Try in Showcase2. Store Data
const state = new mtx.State('myApp');
// Typed set/get
state.set('user', { name: 'John', role: 'admin' });
const user = state.get('user'); // { name: 'John', role: 'admin' }
// Watch for changes
const unsubscribe = state.onChange('user', (newVal, oldVal) => {
console.log('User changed:', newVal);
});
// Cleanup
unsubscribe();
→ Try in Showcase3. Pick a DOM Element
const picker = new mtx.Dom.Picker({
onPick: (result) => {
console.log(result.selector); // e.g., "#main-nav .btn-login"
console.log(result.strategy); // "css" | "id" | "auto"
console.log(result.element); // HTMLElement
},
onCancel: () => console.log('Cancelled')
});
picker.start(); // Click any element to pick it
→ Try in ShowcaseArchitecture
How MTxFlow is organized internally.
Module Structure
src/
├── core/ # Foundation (always loaded)
│ ├── mtx.ts # Namespace, config, version
│ ├── mtx-state.ts # State storage manager
│ ├── mtx-utils.ts # Shared utilities
│ └── mtx-icons.ts # SVG icon bundle
├── modules/ # Feature modules (tree-shakeable)
│ ├── mtx-dom.ts # Element Picker & DOM resolver
│ └── mtx-modal.ts # Popup / Modal / Tooltip engine
├── styles/ # CSS design system
│ ├── variables.css # --mtxf-* tokens
│ ├── reset.css # Scoped reset (:where)
│ ├── modal.css # Modal component styles
│ └── animations.css # Keyframe presets
└── index.ts # Bundle entry point
Naming Conventions
| Element | Convention | Example |
|---|
| Global namespace | window.mtx | mtx.Modal.alert() |
| CSS class prefix | mtxf- | .mtxf-modal |
| CSS custom props | --mtxf-* | --mtxf-accent |
| Data attributes | data-mtxf-* | data-mtxf-id="step1" |
| Storage keys | mtxf__* | mtxf__app__theme |
Z-Index Layers
| Layer | z-index | CSS Variable |
|---|
| Tooltip | 9000 | --mtxf-z-tooltip |
| Overlay | 9050 | --mtxf-z-overlay |
| Modal | 9100 | --mtxf-z-modal |
| Tour | 9200 | --mtxf-z-tour |
| Draw | 9300 | --mtxf-z-draw |
| Controls | 9400 | --mtxf-z-controls |
| Cursor | 99999 | --mtxf-z-cursor |
mtx (Namespace)
Root namespace, configuration, and version info.
Constants
mtx.VERSION: stringLibrary version string, e.g., "1.0.0-alpha.1".
Functions
mtx.configure(opts: Partial<MtxConfig>): voidSet library-wide configuration. Call once at init.
mtx.configure({
debug: true, // Enable [MTxFlow] console logs
cssPrefix: 'mtxf-', // CSS class prefix
dataPrefix: 'data-mtxf-',
storagePrefix: 'mtxf__',
});
mtx.log(...args): voidDebug-only logger. Only outputs when config.debug = true.
mtx.State
Persistent key-value storage with typed access and change observers.
→ Try in ShowcaseConstructor
new mtx.State(storageKey: string, options?: StateOptions)| Option | Type | Default | Description |
|---|
storage | 'local' | 'session' | 'memory' | 'local' | Primary storage backend |
fallback | 'local' | 'session' | 'memory' | 'memory' | Fallback if primary is unavailable |
prefix | string | 'mtxf__' | Key prefix in storage |
Methods
.get<T>(key: string): T | nullRetrieve a value. Automatically JSON-parsed.
.set<T>(key: string, value: T): voidStore a value. Automatically JSON-serialized. Triggers onChange listeners.
.remove(key: string): voidRemove a key. Triggers onChange with null.
.clear(): voidRemove all keys belonging to this State instance.
.onChange<T>(key: string, listener): () => voidSubscribe to changes. Returns an unsubscribe function.
.snapshot(): Record<string, unknown>Dump all state as a plain object. Useful for debugging.
.restore(data: Record<string, unknown>): voidRestore state from a snapshot.
mtx.Utils
Common utility functions used across all modules.
→ Try in ShowcaseFunctions
mtx.Utils.throttle(fn, ms): FunctionLimits function calls to at most once per ms milliseconds.
mtx.Utils.debounce(fn, ms): FunctionDelays function execution until ms of inactivity.
mtx.Utils.deepMerge(target, source): ObjectRecursively merge two objects. Arrays are replaced, not merged.
mtx.Utils.generateId(prefix?): stringGenerate a unique ID, e.g., "mtxf-1-a3f8c2".
mtx.Utils.waitFor(selector, timeout?): Promise<Element>Wait for a DOM element to appear using MutationObserver.
mtx.Utils.on(el, event, handler, opts?): voidShorthand for addEventListener.
mtx.Utils.ready(fn): voidSafe DOMContentLoaded wrapper.
mtx.Utils.getScrollParent(el): Element | nullFind the nearest scrollable ancestor.
mtx.Icons
Curated SVG icon bundle: FontAwesome, Bootstrap Icons, Heroicons.
→ Try in ShowcaseIcon Sets
| Set | Icons | License |
|---|
mtx.Icons.fa.* | circleQuestion, circleCheck, circleExclamation, circleInfo, xmark, arrowRight, gear, eye | MIT / CC BY 4.0 |
mtx.Icons.bi.* | infoCircle, checkCircle, exclamationTriangle, search | MIT |
mtx.Icons.hero.* | questionMarkCircle, cursor, play, cog | MIT |
Usage
// Render into a container
mtx.Icons.render(document.getElementById('icon-slot'), mtx.Icons.fa.gear, {
size: 20,
color: '#0070f3',
class: 'my-icon'
});
// Or use the raw SVG string
element.innerHTML = mtx.Icons.fa.circleCheck;
mtx.Dom
DOM element resolver, best-selector generator, and interactive picker.
→ Try in ShowcaseResolver
mtx.Dom.resolve(descriptor: string): ResolveResult | nullResolve an element by any strategy. Tries in order: #id → [data-mtxf-id] → CSS selector → XPath.
mtx.Dom.resolve('#my-button'); // by ID
mtx.Dom.resolve('.nav .btn-primary'); // by CSS
mtx.Dom.resolve('//button[@type="submit"]'); // by XPath
mtx.Dom.resolve('step-1'); // by data-mtxf-id
mtx.Dom.getBestSelector(el: Element): stringGenerate the shortest unique CSS selector for any element.
mtx.Dom.waitFor(selector, timeout?): Promise<Element>Wait for an element to appear using MutationObserver.
Picker
new mtx.Dom.Picker(options?: PickerOptions)Interactive element picker with visual overlay.
| Option | Type | Description |
|---|
onPick | (result) => void | Called when user clicks an element |
onCancel | () => void | Called when user presses ESC |
overlayColor | string | Highlight overlay color |
borderColor | string | Highlight border color |
mtx.Modal
Promise-based modals, tooltips, and popups. No Swal or Tippy needed.
→ Try in ShowcaseQuick Methods
mtx.Modal.alert(content, title?): Promise<void>Simple alert with OK button. Returns a Promise that resolves on close.
mtx.Modal.confirm(content, title?): Promise<boolean>Confirm dialog. Returns true if confirmed, false if cancelled.
mtx.Modal.tooltip(target, content, placement?): ModalInstanceAttach a tooltip to an element. Placement: 'top' | 'bottom' | 'left' | 'right'.
Custom Modal
mtx.Modal.open(options): ModalInstanceOpen a fully customizable modal.
const modal = mtx.Modal.open({
variant: 'dialog', // 'alert'|'confirm'|'dialog'|'drawer'|'fullscreen'
title: 'My Dialog',
content: '<p>HTML content here</p>',
html: true,
theme: 'dark', // 'dark' | 'light'
draggable: true,
closable: true,
closeOnOverlay: true,
closeOnEsc: true,
buttons: [
{ text: 'Cancel', variant: 'ghost', close: true },
{ text: 'Save', variant: 'primary', value: 'saved', close: true },
],
onClose: (modal, result) => {
console.log('Closed with:', result);
},
});
// Programmatic control
modal.setContent('New content');
modal.close('custom-result');
mtx.Modal.closeAll(): voidClose all open modals.
mtx.Draw
Draw dynamic SVG shapes directly onto the DOM with coordinate or element-relative positioning.
→ Try in ShowcaseDraw Options
| Option | Type | Default | Description |
|---|
color | string | '#e63946' | Stroke/line color |
strokeWidth | number | 2 | Line width in pixels |
fill | string | 'none' | SVG fill property |
dashed | boolean | false | Draw dashed line |
opacity | number | 1 | Opacity (0..1) |
arrowHead | 'start'|'end'|'both'|'none' | 'end' | Arrow head position for lines |
arrowSize | number | 8 | Size of the arrow head marker |
padding | number | 0 | Margin around target elements |
Drawing Methods
mtx.Draw.arrow(from: PointInput, to: PointInput, opts?: DrawOptions): DrawElementDraw a single-headed arrow connecting two points/elements.
mtx.Draw.circle(target: string | Element, opts?: DrawOptions): DrawElementDraw a circle wrapping around a target element.
mtx.Draw.checkmark(target: string | Element, opts?: DrawOptions): DrawElementDraw an animated hand-drawn style checkmark ✓ on target.
mtx.Draw.spotlight(target: string | Element, opts?: DrawOptions): DrawElementCreate a spotlight overlay focusing on target, dimming the rest of the screen.
mtx.Draw.label(target: string | Element, text: string, opts?: DrawOptions): DrawElementDraw a tooltip-style label box hovering next to the target element.
DrawElement Instance API
const shape = mtx.Draw.rect('#my-element', { color: 'blue' });
shape.update({ color: 'red', strokeWidth: 4 }); // update properties
shape.refresh(); // force recalculate position
shape.remove(); // erase from DOM
DrawManager
Global manager tracking all drawn shapes. Handles automatic recalculations on scroll and resize events.
mtx.DrawManager.removeAll(): voidClears all currently active drawings from the DOM.
mtx.Anim & Timeline
High-performance RAF animation engine supporting n-degree spring easings and choreographed timelines.
→ Try in ShowcasePreset Effects
Pre-packaged visual effects targeting DOM elements or SVG drawings:
| Preset | Target Type | Description |
|---|
typewriter | Text Elements | Types out text character by character |
highlight-text | Text Elements | Creates a highlighter effect behind the text |
draw-arrow | SVG Arrow | Draws an arrow path from start to end |
pulse | HTMLElement | Gently pulses size (zoom in/out) |
shake | HTMLElement | Shakes horizontally to indicate error |
glow | HTMLElement / Viewport | Creates a pulsating neon glow border simulating camera recording or focus spotlight |
Anim Configuration
const anim = mtx.Anim.play({
effect: 'glow',
target: document.body, // document.body or viewport
duration: 3000,
loop: true,
color: '#0da84e', // Glow border & shadow color
glowSize: 20, // Shadow blur radius in pixels
glowBorderWidth: 4, // Neon frame border width in pixels
glowMinOpacity: 0.4, // Pulsing minimum opacity level
glowMaxOpacity: 1.0, // Pulsing maximum opacity level
glowBlinkSpeedMultiplier: 1.0, // Speed multiplier for blinking dot
showRecBadge: true, // Display top-right RED blinking REC badge
onComplete: () => console.log('Done!')
});
anim.pause();
anim.resume();
anim.stop();
Timeline API
Choreograph multiple sequential or parallel animation events easily.
const tl = new mtx.Timeline({
autoplay: false,
loop: false,
onComplete: () => console.log('Timeline complete')
});
tl.add({ at: 0, effect: 'typewriter', target: '#title', duration: 1000 })
.add({ at: '+=200', effect: 'highlight-text', target: '#title', duration: 500 })
.add({ at: '+=100', effect: 'draw-circle', target: '#button', duration: 800 });
tl.play();
tl.seek(1500); // Seek to 1.5s mark
mtx.Connect
Draw real-time connecting SVG paths between two elements, keeping them connected during drags and scrolls.
→ Try in ShowcaseConnect Options
| Option | Type | Default | Description |
|---|
from | string|Element | Required | Source element |
to | string|Element | Required | Target destination element |
type | 'straight'|'curved'|'elbow'|'step' | 'curved' | Line drawing algorithm style |
autoAnchor | boolean | true | Auto-select the closest pair of edges |
animated | boolean | false | Animate a glowing pulse flow along the connector |
flowSpeed | number | 1 | Flow speed factor multiplier |
label | string | '' | Floating text centered on the line |
API
const conn = new mtx.Connect({
from: '#box-a',
to: '#box-b',
type: 'elbow',
color: '#0070f3',
animated: true,
});
conn.attach(); // Add to DOM and begin observers
conn.update({ type: 'curved', color: 'red' }); // update live properties
conn.detach(); // remove from DOM and stop observers
mtx.Scene
JSON-based scene scripting and virtual human-like cursor simulation.
→ Try in ShowcaseScenePlayer Configuration
const player = new mtx.ScenePlayer(scriptJson, {
mode: 'watch', // 'watch' (simulation) | 'practice' (interactive)
autoplay: true,
speed: 1, // 0.5 to 2
loop: false,
onComplete: () => console.log('Scene finished!'),
});
player.start();
Scene Actions
| Action | Description | Example Payload |
|---|
click | Move cursor and click target | { type: 'click', target: '#btn' } |
type | Type text like a human | { type: 'type', target: '#input', text: 'Stark' } |
hover | Hover cursor over target | { type: 'hover', target: '#menu' } |
scroll | Scroll element into view | { type: 'scroll', target: '#section' } |
wait | Delay execution | { type: 'wait', duration: 1000 } |
SceneBuilder (Fluent API)
const script = new mtx.SceneBuilder('guide-id', 'Form Guide')
.scene('step-1', 'Fill Form')
.act('Enter Username')
.action({ type: 'click', target: '#user-input' })
.action({ type: 'type', target: '#user-input', text: 'ironman' })
.build();
mtx.Tour & TourHelp
Interactive step-by-step product tours and embedded help icon badges.
→ Try in ShowcaseTour Guide API
const tour = new mtx.Tour({
steps: [
{ element: '#logo', title: 'Welcome', content: 'This is the main logo.' },
{ element: '#search', title: 'Search', content: 'Search docs here.' }
],
keyboard: true, // arrow keys navigation
scrollToElement: true,
});
tour.start();
TourHelp API
const help = new mtx.TourHelp({
items: [
{
element: '#input-username',
title: 'Info',
content: 'Unique username required.',
animate: 'pulse',
}
]
});
help.show();
TourPicker API (Visual Builder)
TourPicker provides a floating, interactive admin panel allowing developers to visually pick elements, edit steps, and save presets.
const picker = new mtx.TourPicker({
onPick: (info) => console.log('Picked step:', info),
onSave: (items) => console.log('Saved custom steps:', items)
});
// Import existing steps for editing
picker.importItems([
{ element: '#logo', title: 'Welcome', content: 'This is the main logo.' },
{ element: '#search', title: 'Search Docs', content: 'Search input.' }
]);
picker.enable(); // starts picker mode
picker.disable(); // stops picker mode
mtx.Diagram
Interactive flowchart builder with draggable nodes and auto-aligning connectors.
→ Try in ShowcaseDiagram API
const diagram = new mtx.Diagram({
container: '#canvas-container',
readOnly: false
});
// Add Nodes
const n1 = diagram.addNode({ id: 'start', x: 50, y: 100, label: 'Start' });
const n2 = diagram.addNode({ id: 'end', x: 250, y: 100, label: 'End' });
// Connect Nodes
diagram.connect('start', 'end', {
type: 'curved',
color: '#0070f3',
animated: true
});
State History & Export
diagram.undo(); // Undo last drag/add
diagram.redo(); // Redo
// Export compiled standalone SVG string
const svgString = diagram.exportSVG();
mtx.Recorder
Automated interaction recorder for creating SceneScript workflows visually.
→ Try in ShowcaseRecorder Configuration
const recorder = new mtx.Recorder({
captureClick: true, // Record click events
captureType: true, // Record typing events
captureScroll: true, // Record scroll events
recordDelays: true, // Record elapsed time between events as 'wait' steps
maxDelay: 5000, // Max duration of wait steps (ms)
showPanel: true, // Show floating control panel UI
panelPosition: 'top-right', // 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'
scriptName: 'My Guide',
});
recorder.start();
Control Methods
recorder.start(); // Start recording
recorder.pause(); // Pause recording
recorder.resume(); // Resume recording
recorder.stop(); // Stop recording
recorder.undoLast(); // Pop and discard the last captured action
recorder.export(); // Get the SceneScript JSON object
recorder.exportJSON(); // Get the SceneScript formatted JSON string
recorder.exportToFile('f.json'); // Trigger download of JSON file
recorder.destroy(); // Cleanup and remove the UI panel
Adding Custom Annotations
You can programmatically inject custom steps (such as instructional tooltips or alerts) directly into the recorded script timeline:
recorder.addAnnotation({
variant: 'tooltip',
title: 'Input Step',
content: 'Please enter your account password here to proceed.',
target: '#password-input',
});
mtx.Transform
Advanced overlay controls for element selection, moving, 8-point resizing, rotating, and quick action bar (Lock, Duplicate, Delete).
→ Try in ShowcaseConstructor
new mtx.TransformManager(options: TransformManagerOptions)Initialize a new TransformManager overlay to control a DOM element.
TransformManagerOptions
| Option | Type | Default | Description |
|---|
element | HTMLElement | Required | The target DOM element to overlay control controls. |
maintainAspectRatio | boolean | false | Whether the aspect ratio is locked by default. Can be overridden temporarily by holding the Shift key during resizing. |
scale | number | 1 | The zoom or layout scale factor of the parent container. Use this to keep coordinates aligned in scaled preview containers. |
locked | boolean | false | Whether the element starts in a locked state, which disables drag, rotate, and resize interactions. |
rotation | number | 0 | Initial rotation angle of the element in degrees (0 to 360). |
tempRemoveClasses | string[] | [] | CSS classes (e.g., animations or floats) that should be temporarily removed from the element while dragging, resizing, or rotating to avoid layout conflicts. |
onTransform | (context) => void | () => {} | Callback triggered continuously during interaction. Receives { left, top, width, height, rotation } coordinates. |
onTransformStart | () => void | () => {} | Callback triggered when dragging, resizing, or rotating begins. |
onTransformEnd | (context) => void | () => {} | Callback triggered when dragging, resizing, or rotating ends. Receives final coordinates. |
onDuplicate | (el) => void | () => {} | Callback triggered when the Duplicate quick button is clicked. |
onDelete | (el) => void | () => {} | Callback triggered when the Delete quick button is clicked. |
onLockToggle | (locked) => void | () => {} | Callback triggered when the lock status is toggled via the toolbar lock button. |
Methods
.setScale(scale: number): voidUpdate the zoom/preview scale factor of the manager dynamically. Automatically re-aligns the overlay layout.
.updateOverlay(): voidForce-recalculate the coordinates and re-align the selection border and handles to match the target element's bounding rect.
.show(): voidShow the selection border overlay and action toolbar.
.hide(): voidHide the selection border overlay and action toolbar.
.destroy(): voidDeregister all event listeners, disconnect observers, and completely remove the selection overlay elements from the DOM to prevent memory leaks.
Example Usage
// Initialize transform overlay for a box
const transform = new mtx.TransformManager({
element: document.getElementById('box-1'),
maintainAspectRatio: true,
scale: 1.0,
onTransform: (coords) => {
console.log('Coordinates changed:', coords); // e.g., { left: '10.5%', top: '22.0%', ... }
},
onDuplicate: (el) => {
// Clone and place next to the original
const clone = el.cloneNode(true);
clone.style.left = '50%';
clone.style.top = '50%';
el.parentElement.appendChild(clone);
// Automatically attach a new manager to the cloned element
new mtx.TransformManager({ element: clone });
},
onDelete: (el) => {
el.remove();
}
});
// Update scale on zoom change
window.addEventListener('zoom-change', (e) => {
transform.setScale(e.detail.zoomFactor);
});