Quick Reference
Framework Methods
XTool.init()- Initialize frameworkXTool.directive()- Register directiveXTool.registerComponent()- Register componentXTool.loadComponents()- Load external componentsXTool.mountComponent()- Mount programmatically
Component Context
this.$el- Root elementthis.$refs- Element referencesthis.$nextTick()- Next DOM updatethis.Signals- Emit/connect signals
Type Generics
<TData>- Component data type<TMethods>- Methods type<TComputed>- Computed type<T>- Directive value type
import { XTool } from 'fynejs'; XTool.init({ debug: true });
Framework Interface
Core framework methods and configuration options for initializing and customizing FyneJS.
XToolFramework
Main framework interface providing initialization, directive registration, and component management.
init
Syntax
init(config?: XToolConfig): XToolFramework
Description
Initialize the framework with optional configuration settings.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| config | XToolConfig | Optional | Configuration options for the framework |
Example
// Initialize with default settings
XTool.init();
// Initialize with custom configuration
XTool.init({
container: '.app',
debug: true,
staticDirectives: true,
prefix: 'x',
delegate: false,
sandboxExpressions: false,
allowGlobals: ['Math', 'Date']
});
directive<T>
Syntax
directive<T>(name: string, directive: CustomDirective<T>): XToolFramework
Description
Register a custom directive with bind, update, and unbind lifecycle hooks.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Required | Directive name (without prefix) |
| directive | CustomDirective<T> | Required | Directive definition with lifecycle hooks |
Example
XTool.directive('tooltip', {
bind(element, value, expression, component) {
element.setAttribute('title', value);
},
update(element, value) {
element.setAttribute('title', value);
},
unbind(element) {
element.removeAttribute('title');
}
});
METHOD registerComponent(definition): XToolFramework
Register a reusable component with name, template, and lifecycle hooks. Returns the framework instance for chaining.
Syntax
registerComponent(definition: RegisteredComponentDefinition): XToolFramework
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| definition | RegisteredComponentDefinition | Required | Component definition with required name and optional template |
Example
XTool.registerComponent({
name: 'counter',
template: `<div>
<span x-text="count"></span>
<button x-on:click="increment">+</button>
</div>`,
data: { count: 0 },
methods: {
increment() { this.count++; }
}
});
METHOD loadComponents(sources): Promise<ComponentLoaderResult>
Load external component definitions with different loading strategies. Returns a promise with load results.
Syntax
loadComponents(sources: Array<string | ComponentSource>): Promise<ComponentLoaderResult>
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| sources | Array<string | ComponentSource> | Required | Array of component paths or source objects with loading options |
Example
// Load components with different modes
await XTool.loadComponents([
'components/button.js', // preload (default)
{ path: 'components/modal.js', mode: 'defer' },
{ path: 'components/chart.js', mode: 'lazy', name: 'data-chart' }
]);
// Returns: { settled: 2, failed: 0 }
METHOD mountComponent(name, element, props?): ReactiveComponent | undefined
Programmatically mount a registered component on a DOM element. Returns the component instance or undefined if mounting failed.
Syntax
mountComponent(name: string, element: Element, props?: Record<string, any>): ReactiveComponent | undefined
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Required | Name of the registered component to mount |
| element | Element | Required | DOM element to mount the component on |
| props | Record<string, any> | Optional | Initial props to pass to the component |
Example
// Register a component first
XTool.registerComponent({
name: 'user-card',
template: '<div><h3 x-text="name"></h3><p x-text="role"></p></div>',
data: { name: 'Guest', role: 'Viewer' }
});
// Programmatically mount on any element
const container = document.getElementById('dynamic-container');
const component = XTool.mountComponent('user-card', container, {
name: 'John Doe',
role: 'Administrator'
});
// Access the mounted component instance
if (component) {
console.log('Component mounted successfully');
// Later: component.$destroy() to unmount
}
Use Cases
Perfect for dynamically creating components in response to user actions, integrating with third-party libraries, or building component factories.
Configuration
Framework configuration options for customizing behavior, performance, and security.
XToolConfig
Configuration interface for framework initialization with type-safe options.
Configuration Properties
| Property | Type | Default | Description |
|---|---|---|---|
container
Optional
|
string |
'body'
|
Container selector for auto-discovery of components |
debug
Optional
|
boolean |
false
|
Enable debug logging for development |
staticDirectives
Optional
|
boolean |
true
|
Enable static directive optimization for performance |
prefix
Optional
|
string |
'x'
|
Directive prefix for custom attribute names |
delegate
Optional
|
boolean |
false
|
Enable event delegation for better performance |
sandboxExpressions
Optional
|
boolean |
false
|
Restrict globals in expressions for security |
allowGlobals
Optional
|
string[] |
undefined
|
Whitelist of globals when sandboxExpressions is enabled |
router
Optional
|
RouterOptions |
undefined
|
SPA router configuration for client-side navigation |
Configuration Example
// Complete configuration example
XTool.init({
container: '.app-container', // Custom container
debug: true, // Enable debugging
staticDirectives: true, // Optimize static directives
prefix: 'data', // Use 'data-' prefix
delegate: true, // Enable event delegation
sandboxExpressions: true, // Secure expressions
allowGlobals: [ // Allowed global objects
'Math', 'Date', 'JSON', 'console'
],
router: { // SPA routing configuration
enabled: true, // Enable SPA routing
transitionName: 'route', // View transition name
prefetchOnHover: true, // Prefetch on hover
before: async (to, from, info) => {
// Navigation guard
return true; // Allow navigation
},
after: async (to, from, info) => {
// Post-navigation hook
console.log('Navigated to:', to);
}
}
});
RouterOptions
Configuration interface for SPA routing functionality with navigation hooks and transitions.
Router Properties
| Property | Type | Default | Description |
|---|---|---|---|
enabled
Optional
|
boolean |
false
|
Enable or disable SPA routing functionality |
transitionName
Optional
|
string |
'route'
|
Name for view transitions API transitions |
prefetchOnHover
Optional
|
boolean |
false
|
Prefetch pages when hovering over links |
before
Optional
|
NavigationHook |
undefined
|
Hook called before navigation (can cancel) |
after
Optional
|
NavigationHook |
undefined
|
Hook called after successful navigation |
error
Optional
|
ErrorHook |
undefined
|
Hook called when navigation fails |
Router Hook Types
// Navigation hook signature
type NavigationHook = (
to: string, // Destination URL
from: string, // Current URL
info: { // Navigation context
source: 'link' | 'popstate' | 'program';
}
) => boolean | void | Promise<boolean | void>;
// Error hook signature
type ErrorHook = (
error: unknown, // Error that occurred
to: string, // Attempted destination
from: string // Current URL
) => void;
Component Interfaces
TypeScript interfaces for defining components with proper type safety and IntelliSense support.
TransitionConfig
Configuration object for x-transition directive with class phases, timing, and end hooks.
Configuration Properties
| Property | Type | Description |
|---|---|---|
duration
Optional
|
number | Fallback transition duration in milliseconds (default: 150). Actual duration is computed from CSS transitions/animations. |
easing
Optional
|
string | CSS easing function (default: 'ease'). Used for inline fade transitions. |
enter
Optional
|
string | Classes applied during entire enter phase (e.g., 'transition ease-out duration-300'). |
enterFrom
Optional
|
string | Initial state classes for enter (e.g., 'opacity-0 scale-95'). Applied first, then removed before enterTo. |
enterTo
Optional
|
string | Target state classes for enter (e.g., 'opacity-100 scale-100'). Applied after enterFrom is removed. |
leave
Optional
|
string | Classes applied during entire leave phase (e.g., 'transition ease-in duration-200'). |
leaveFrom
Optional
|
string | Initial state classes for leave (e.g., 'opacity-100 scale-100'). |
leaveTo
Optional
|
string | Target state classes for leave (e.g., 'opacity-0 scale-95'). |
toggle
Optional
|
string | Simple class list added on show and removed on hide (e.g., 'opacity-0 transition-opacity duration-200'). |
End Hook (.after / .end modifier)
Add .after or .end modifier to run an expression when transition completes naturally (not on cancellation).
x-transition:enter.after="({ el, phase, config }) => ..."
- el: The transitioned element
- phase: 'enter' | 'leave'
- config: This config object with resolved
duration(effective ms from CSS) andeasing
ComponentDefinition<TData, TMethods, TComputed>
Base interface for defining reactive components with typed data, methods, and computed properties.
PROPERTY data?: TData
Reactive data object with typed properties that trigger UI updates when changed.
// Define typed data interface
interface UserData {
name: string;
email: string;
isActive: boolean;
}
// Use in component
const component = {
data: {
name: 'John Doe',
email: 'john@example.com',
isActive: true
} as UserData
};
PROPERTY methods?: WithThisForMethods<ComponentContext>
Component methods with proper context binding and type safety. Methods have access to component data and the full ComponentContext.
const component = {
data: { count: 0 },
methods: {
increment() {
this.count++; // 'this' is properly typed
},
setCount(value: number) {
this.count = value;
}
}
};
PROPERTY computed?: BindComputed<ComponentContext>
Computed properties with automatic caching and dependency tracking. Values are recalculated only when dependencies change. Computed functions have access to the ComponentContext.
const component = {
data: {
firstName: 'John',
lastName: 'Doe'
},
computed: {
fullName() {
return `${this.firstName} ${this.lastName}`;
},
initials() {
return `${this.firstName[0]}${this.lastName[0]}`;
}
}
};
PROPERTY propEffects?: PropEffectsMap<ComponentContext>
Reactive handlers for component prop changes with old/new value tracking. Handlers receive the new and old values and have access to the ComponentContext.
const component = {
data: { message: 'Hello' },
propEffects: {
userId(newValue, oldValue) {
console.log(`User changed: ${oldValue} → ${newValue}`);
this.loadUserData(newValue);
},
theme(newTheme) {
this.updateStyles(newTheme);
}
}
};
PROPERTY template?: string | Promise<string> | (() => string | Promise<string>)
Component template for rendering. Supports static strings, promises, or factory functions.
// Static template
const component1 = {
template: `<div>
<h1 x-text="title"></h1>
<p x-text="description"></p>
</div>`
};
// Async template
const component2 = {
template: async () => {
const response = await fetch('/templates/card.html');
return await response.text();
}
};
PROPERTY name?: string
Optional component name for registration and debugging. Required for registered components.
const component = {
name: 'user-card',
data: { user: null },
template: `<div class="card">
<h3 x-text="user?.name"></h3>
</div>`
};
LIFECYCLE Lifecycle Hooks
Component lifecycle methods with proper context typing and execution order. All lifecycle hooks have access to the full ComponentContext.
Mount Lifecycle
beforeMount?(this: ComponentContext)- Before element is attachedmounted?(this: ComponentContext)- After element is attached and reactive
Update Lifecycle
updated?(this: ComponentContext)- After reactive data changes
Unmount Lifecycle
beforeUnmount?(this: ComponentContext)- Before component cleanupunmounted?(this: ComponentContext)- After component cleanup
Destroy Lifecycle
beforeDestroy?(this: ComponentContext)- Before permanent destructiondestroyed?(this: ComponentContext)- After permanent destruction
const component = {
data: { isReady: false },
// Mount lifecycle
beforeMount() {
console.log('About to mount', this.$el);
},
mounted() {
this.isReady = true;
console.log('Component mounted', this.$el);
},
// Update lifecycle
updated() {
console.log('Component updated');
},
// Unmount lifecycle
beforeUnmount() {
this.cleanup();
},
unmounted() {
console.log('Component unmounted');
}
};
RegisteredComponentDefinition<TData, TMethods, TComputed>
Extended component definition for reusable components with required name and additional configuration options.
EXTENDS ComponentDefinition<TData, TMethods, TComputed>
Inherits all properties from ComponentDefinition plus additional required fields.
name: string Required
Unique component name used for registration and template references.
makeData?: (props: Record<string, string>) => Record<string, unknown>
Factory function to generate base data from component props/attributes.
init?: (props: Record<string, any>) => ComponentDefinition | void
Instance augmentation function to customize component per usage.
Registered Component Example
const counterComponent: RegisteredComponentDefinition = {
name: 'counter',
template: `<div>
<span x-text="count"></span>
<button x-on:click="increment">+</button>
</div>`,
data: { count: 0 },
methods: {
increment() {
this.count++;
}
},
makeData(props) {
return { count: parseInt(props.start) || 0 };
}
};
ComponentContext<TData, TMethods, TComputedVals>
Component context available in methods, computed properties, and expressions with proper type safety.
PROPERTIES Special Properties
$el- Component's root element$id- Component's unique ID$isMounted- Mount status$isDestroyed- Destruction status$isSealed- Sealed mode status$isFrozen- Frozen status$parent- Parent component$children- Child components
METHODS Utility Methods
$destroy()- Destroy component$forceUpdate()- Force re-render$addCleanupFunction()- Add cleanup$nextTick()- Next DOM update$mutate()- Mutate reactive data$seal()- Toggle sealed mode$log()- Debug logging
REFS Element References
$refs.name- Access element by x-ref name$ref(name)- Get ref by name (function form)$ref(name, value)- Register any value as a ref
Refs bubble up the component tree—child components can access parent refs.
HELPERS DOM Helpers
$attr(name, value)- Set attribute on $target element$attr({ name: value, ... })- Set multiple attributes$css(prop, value)- Set CSS property on $target element$css({ prop: value, ... })- Set multiple CSS properties
Supports glob patterns: $attr('[width,height]', 100) sets both attributes.
SIGNALS Component Messaging
Signals.emit(name, payload?)- Emit a signal that bubbles upSignals.connect(name, handler)- Listen for a signalSignals.disconnect(name, handler)- Stop listening
Signals bubble from child to parent. Call event.stopPropagation() to stop bubbling.
Component Context Usage
const component = {
data: { message: 'Hello' },
methods: {
logInfo() {
this.$log('Component ID:', this.$id);
this.$log('Element:', this.$el);
this.$log('Is mounted:', this.$isMounted);
},
scheduleUpdate() {
this.$nextTick(() => {
console.log('DOM updated');
});
},
forceChange() {
this.$mutate(() => {
this.message = 'Changed!';
});
}
}
};
Directive Interfaces
Interfaces for creating custom directives with proper lifecycle management and type safety.
CustomDirective<T>
Interface for defining custom directives with typed value handling and lifecycle management.
METHOD bind?(element, value, expression, component, ...)
Called once when directive is first bound to an element. Use for initial setup and event listeners.
const fadeDirective: CustomDirective<number> = {
bind(element, value, expression, component) {
element.style.transition = 'opacity 0.3s';
element.style.opacity = value.toString();
}
};
METHOD update?(element, value, expression, component, ...)
Called whenever reactive dependencies change. Use to update the DOM based on new values.
const fadeDirective: CustomDirective<number> = {
update(element, value) {
element.style.opacity = value.toString();
}
};
METHOD unbind?(element, component)
Called when directive is removed (cleanup). Use to remove event listeners and clean up resources.
const fadeDirective: CustomDirective<number> = {
unbind(element) {
element.style.transition = '';
element.style.opacity = '';
}
};
update?(element, value, expression, component, modifiers?, evaluator?)
Called whenever reactive dependencies change.
const fadeDirective: CustomDirective<number> = {
update(element, value) {
element.style.opacity = value.toString();
}
};
unbind?(element, component)
Called when directive is removed (cleanup).
const fadeDirective: CustomDirective<number> = {
unbind(element) {
element.style.transition = '';
element.style.opacity = '';
}
};
Complete Example
Full directive implementation with TypeScript.
interface TooltipConfig {
text: string;
position?: 'top' | 'bottom' | 'left' | 'right';
delay?: number;
}
const tooltipDirective: CustomDirective<TooltipConfig> = {
bind(element, value, expression, component, modifiers) {
const config = typeof value === 'string' ? { text: value } : value;
// Create tooltip element
const tooltip = document.createElement('div');
tooltip.className = 'tooltip';
tooltip.textContent = config.text;
// Store for cleanup
(element as any)._tooltip = tooltip;
// Add event listeners
element.addEventListener('mouseenter', showTooltip);
element.addEventListener('mouseleave', hideTooltip);
},
update(element, value) {
const tooltip = (element as any)._tooltip;
if (tooltip) {
const config = typeof value === 'string' ? { text: value } : value;
tooltip.textContent = config.text;
}
},
unbind(element) {
const tooltip = (element as any)._tooltip;
if (tooltip) {
tooltip.remove();
delete (element as any)._tooltip;
}
element.removeEventListener('mouseenter', showTooltip);
element.removeEventListener('mouseleave', hideTooltip);
}
};
Event Callback Contexts
Understanding the context and arguments passed to event handlers and directive callbacks.
Event Directive Context
Event handlers in x-on and @ directives receive both special variables and function arguments.
Special Variables
Available within event handler expressions:
$event
The native DOM event object
$target
The element that triggered the event (event.target)
<!-- Using special variables -->
<button @click="console.log($event.type, $target.tagName)">
Click me
</button>
<!-- Preventing default behavior -->
<form @submit="$event.preventDefault(); handleSubmit()">
Function Arguments
When calling methods, the element is automatically passed as an argument:
// Component method signature
methods: {
handleClick(element) {
// element is the DOM element that triggered the event
console.log('Clicked:', element.tagName);
}
}
<!-- Usage in template -->
<button @click="handleClick">Click</button>
x-intersect Callback Context
x-intersect directive callbacks receive detailed intersection information.
Callback Arguments
The callback receives a payload object with intersection details:
entry
IntersectionObserverEntry object with detailed intersection data
phase
'enter' | 'leave' - which phase triggered the callback
visible
Boolean indicating if element is currently visible
before
Boolean indicating if element was visible before this change
<!-- Using intersection payload -->
<div x-intersect:enter="handleIntersect">
Observe me!
</div>
// Component method
methods: {
handleIntersect(payload) {
console.log('Phase:', payload.phase);
console.log('Visible:', payload.visible);
console.log('Intersection ratio:', payload.entry.intersectionRatio);
}
}
Router Hook Context
Router navigation hooks receive detailed navigation context information.
Hook Arguments
All router hooks receive the same three arguments:
to
Destination URL (string)
from
Current URL (string)
info
Navigation context object with source information
// Router configuration with hooks
router: {
before(to, from, info) {
console.log('Navigating to:', to);
console.log('Coming from:', from);
console.log('Source:', info.source); // 'link', 'popstate', or 'program'
return true; // Allow navigation
}
}
info.source indicates how the navigation was triggered:
• 'link' - User clicked a link
• 'popstate' - Browser back/forward button
• 'program' - Programmatic navigation
Type Utilities
Advanced TypeScript utilities for enhanced type safety and developer experience.
Type Helpers
Advanced TypeScript utilities used internally by the framework for enhanced type safety.
TYPE DeepReadonly<T>
Deep readonly utility preventing mutations in computed getters.
// Data is DeepReadonly in computed
computed: {
summary() {
// this.users is DeepReadonly<User[]>
// Prevents: this.users.push(newUser)
return this.users.length;
}
}
TYPE ComputedValues<TComputed>
Derives computed value types from getter functions.
const computed = {
fullName(): string { /* ... */ },
age(): number { /* ... */ }
};
// ComputedValues<typeof computed> = {
// fullName: string;
// age: number;
// }
TYPE WithThisForMethods<TCtx, TMethods>
Injects proper 'this' context into method signatures.
// Original method signature
const methods = {
updateUser(id: number, data: UserData) { /* ... */ }
};
// With proper 'this' binding:
// (this: ComponentContext, id: number, data: UserData) => void
TYPE HtmlTag
Template literal type for HTML template strings.
import { html } from 'fynejs';
const template = html`
<div class="${className}">
<h1>${title}</h1>
<p>${content}</p>
</div>
`;
TYPE ComponentSource
Configuration object for component loading with path, mode, and optional name.
interface ComponentSource {
path: string; // Component file path
mode?: 'preload' | 'defer' | 'lazy'; // Loading strategy
name?: string; // Override component name
}
// Usage in loadComponents
const sources = [
'components/button.js', // string (preload mode)
{ path: 'modal.js', mode: 'defer' }, // ComponentSource
{ path: 'chart.js', mode: 'lazy', name: 'data-chart' }
];
TYPE ComponentLoaderResult
Return type from loadComponents() showing load success counts and failures.
interface ComponentLoaderResult {
settled: number; // Successfully loaded (preload + defer modes)
failed: number; // Failed immediate loads
}
// Example result
const result = await XTool.loadComponents(['a.js', 'b.js']);
console.log(`Loaded: ${result.settled}, Failed: ${result.failed}`);
Global Declarations
Global types and module declarations for both browser and bundler environments.
Browser Environment
Global declarations available in browser environments via script tags.
Global Window Objects
// Available on window object
declare global {
interface Window {
XTool: XToolFramework;
FyneJS: XToolFramework; // Alias
}
}
// Usage in browser
<script src="..."></script>
<script>
// Both are available
XTool.init();
FyneJS.init(); // Same instance
</script>
Both XTool and FyneJS reference the same framework instance.
Module Exports
ESM and CommonJS module declarations for modern bundlers and Node.js environments.
ESM ES Module Imports
// Named imports
import { XTool, FyneJS, html } from 'fynejs';
import type { ComponentDefinition, XToolConfig } from 'fynejs';
// Default import
import XTool from 'fynejs';
CJS CommonJS Requires
// Destructured require
const { XTool, FyneJS, html } = require('fynejs');
// Default require
const XTool = require('fynejs').default;
HELPER HTML Template Helper
Tagged template literal for HTML strings with syntax highlighting support in IDEs.
import { html } from 'fynejs';
// Template literal with syntax highlighting
const template = html`
<div x-data="{ count: 0 }">
<span x-text="count"></span>
<button x-on:click="count++">Increment</button>
</div>
`;