Quick Reference

Framework Methods

  • XTool.init() - Initialize framework
  • XTool.directive() - Register directive
  • XTool.registerComponent() - Register component
  • XTool.loadComponents() - Load external components

Component Context

  • this.$el - Root element
  • this.$destroy() - Destroy component
  • this.$nextTick() - Next DOM update
  • this.$mutate() - Mutate reactive data

Type Generics

  • <TData> - Component data type
  • <TMethods> - Methods type
  • <TComputed> - Computed type
  • <T> - Directive value type
Quick Start
import { XTool } from 'fynejs'; XTool.init({ debug: true });

Framework Interface

Core framework methods and configuration options for initializing and customizing FyneJS.

INTERFACE

XToolFramework

Main framework interface providing initialization, directive registration, and component management.

METHOD init
Returns: XToolFramework

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']
});
METHOD directive<T>
Returns: XToolFramework

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 }

Configuration

Framework configuration options for customizing behavior, performance, and security.

INTERFACE

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
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'
  ]
});

Component Interfaces

TypeScript interfaces for defining components with proper type safety and IntelliSense support.

INTERFACE

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
Update Lifecycle
Unmount Lifecycle
Destroy Lifecycle
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');
  }
};
INTERFACE

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 };
  }
};
INTERFACE

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
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.

INTERFACE

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);
  }
};

Type Utilities

Advanced TypeScript utilities for enhanced type safety and developer experience.

UTILITIES

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

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>
Note

Both XTool and FyneJS reference the same framework instance.

MODULES

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>
`;