improve docs

This commit is contained in:
2026-03-22 16:20:26 +01:00
parent 11a6c97cc5
commit e60c1f69b4
9 changed files with 833 additions and 123 deletions

387
sigpro/sigpro.d.ts vendored Normal file
View File

@@ -0,0 +1,387 @@
/**
* SigPro - Atomic Unified Reactive Engine
* A lightweight, fine-grained reactivity system with built-in routing and plugin support.
*
* @example
* ```typescript
* // Create a reactive signal
* const count = $(0);
*
* // Create a computed value
* const double = $(() => count() * 2);
*
* // Create reactive HTML
* const app = div({ $class: () => count() > 5 ? 'high' : 'low' }, [
* h1("Counter Demo"),
* p("Count: ", () => count()),
* p("Double: ", () => double()),
* button({ onclick: () => count(count() + 1) }, "Increment")
* ]);
*
* // Mount to DOM
* $.mount(app);
* ```
*/
declare global {
interface Window {
/** Main SigPro instance */
$: SigPro;
/** HTML element creators (auto-generated from tags list) */
div: typeof html;
span: typeof html;
p: typeof html;
button: typeof html;
h1: typeof html;
h2: typeof html;
h3: typeof html;
ul: typeof html;
ol: typeof html;
li: typeof html;
a: typeof html;
label: typeof html;
section: typeof html;
nav: typeof html;
main: typeof html;
header: typeof html;
footer: typeof html;
input: typeof html;
form: typeof html;
img: typeof html;
select: typeof html;
option: typeof html;
table: typeof html;
thead: typeof html;
tbody: typeof html;
tr: typeof html;
th: typeof html;
td: typeof html;
canvas: typeof html;
video: typeof html;
audio: typeof html;
}
/**
* Reactive Signal - A reactive state container
* @template T Type of the stored value
*/
interface Signal<T> {
/** Get the current value */
(): T;
/** Set a new value */
(value: T): T;
/** Update value based on previous value */
(updater: (prev: T) => T): T;
}
/**
* Computed Signal - A reactive derived value
* @template T Type of the computed value
*/
interface Computed<T> {
/** Get the current computed value */
(): T;
}
/**
* Reactive Effect - A function that re-runs when dependencies change
*/
type Effect = () => void;
/**
* HTML Content Types
*/
type HtmlContent =
| string
| number
| boolean
| null
| undefined
| Node
| HtmlContent[]
| (() => string | number | Node | null | undefined);
/**
* HTML Attributes and Event Handlers
*/
interface HtmlProps extends Record<string, any> {
/** Two-way binding for input values */
$value?: Signal<any> | ((val: any) => void);
/** Two-way binding for checkbox/radio checked state */
$checked?: Signal<boolean> | ((val: boolean) => void);
/** Reactive class binding */
$class?: string | (() => string);
/** Reactive style binding */
$style?: string | object | (() => string | object);
/** Reactive attribute binding (any attribute can be prefixed with $) */
[key: `$${string}`]: any;
/** Standard event handlers */
onclick?: (event: MouseEvent) => void;
oninput?: (event: Event) => void;
onchange?: (event: Event) => void;
onsubmit?: (event: Event) => void;
onkeydown?: (event: KeyboardEvent) => void;
onkeyup?: (event: KeyboardEvent) => void;
onfocus?: (event: FocusEvent) => void;
onblur?: (event: FocusEvent) => void;
onmouseover?: (event: MouseEvent) => void;
onmouseout?: (event: MouseEvent) => void;
[key: `on${string}`]: ((event: any) => void) | undefined;
}
/**
* Route Configuration
*/
interface Route {
/** URL path pattern (supports :params and * wildcard) */
path: string;
/** Component to render (can be sync, async, or Promise) */
component: ((params: Record<string, string>) => HTMLElement | Promise<HTMLElement>) | Promise<any> | HTMLElement;
}
/**
* Router Instance
*/
interface Router {
/** Router container element */
(routes: Route[]): HTMLElement;
/** Programmatic navigation */
go: (path: string) => void;
}
/**
* Plugin System
*/
interface Plugin {
/**
* Extend SigPro with custom functionality or load external scripts
* @param source - Plugin function, script URL, or array of URLs
* @returns SigPro instance (sync) or Promise (async loading)
*/
(source: ((sigpro: SigPro) => void) | string | string[]): SigPro | Promise<SigPro>;
}
/**
* Main SigPro Interface
*/
interface SigPro {
/**
* Create a reactive Signal or Computed value
* @template T Type of the value
* @param initial - Initial value or computed function
* @param key - Optional localStorage key for persistence
* @returns Reactive signal or computed function
*
* @example
* ```typescript
* // Signal with localStorage persistence
* const count = $(0, 'app.count');
*
* // Computed value
* const double = $(() => count() * 2);
*
* // Reactive effect (runs automatically)
* $(() => console.log('Count changed:', count()));
* ```
*/
<T>(initial: T, key?: string): Signal<T>;
<T>(computed: () => T, key?: string): Computed<T>;
/**
* Create reactive HTML elements with hyperscript syntax
* @param tag - HTML tag name
* @param props - Attributes, events, and reactive bindings
* @param content - Child nodes or content
* @returns Live DOM element with reactivity
*
* @example
* ```typescript
* const name = $('World');
*
* const element = $.html('div',
* { class: 'greeting', $class: () => name().length > 5 ? 'long' : '' },
* [
* $.html('h1', 'Hello'),
* $.html('p', () => `Hello, ${name()}!`),
* $.html('input', {
* $value: name,
* placeholder: 'Enter your name'
* })
* ]
* );
* ```
*/
html: typeof html;
/**
* Mount a component to the DOM
* @param node - Component or element to mount
* @param target - Target element or CSS selector (default: document.body)
*
* @example
* ```typescript
* // Mount to body
* $.mount(app);
*
* // Mount to specific element
* $.mount(app, '#app');
*
* // Mount with component function
* $.mount(() => div("Dynamic component"));
* ```
*/
mount: typeof mount;
/**
* Initialize a hash-based router
* @param routes - Array of route configurations
* @returns Router container element
*
* @example
* ```typescript
* const routes = [
* { path: '/', component: Home },
* { path: '/user/:id', component: UserProfile },
* { path: '*', component: NotFound }
* ];
*
* const router = $.router(routes);
* $.mount(router);
*
* // Navigate programmatically
* $.router.go('/user/42');
* ```
*/
router: Router;
/**
* Extend SigPro with plugins or load external scripts
* @param source - Plugin function, script URL, or array of URLs
* @returns SigPro instance or Promise
*
* @example
* ```typescript
* // Load external library
* await $.plugin('https://cdn.jsdelivr.net/npm/lodash/lodash.min.js');
*
* // Register plugin
* $.plugin(($) => {
* $.customMethod = () => console.log('Custom method');
* });
*
* // Load multiple scripts
* await $.plugin(['lib1.js', 'lib2.js']);
* ```
*/
plugin: Plugin;
}
/**
* Creates a reactive HTML element
* @param tag - HTML tag name
* @param props - Attributes and event handlers
* @param content - Child content
* @returns Live DOM element
*/
function html(tag: string, props?: HtmlProps | HtmlContent, content?: HtmlContent): HTMLElement;
/**
* Mount a component to the DOM
* @param node - Component or element to mount
* @param target - Target element or CSS selector
*/
function mount(node: HTMLElement | (() => HTMLElement), target?: HTMLElement | string): void;
/**
* Type-safe HTML element creators for common tags
*
* @example
* ```typescript
* // Using tag functions directly
* const myDiv = div({ class: 'container' }, [
* h1("Title"),
* p("Paragraph text"),
* button({ onclick: () => alert('Clicked!') }, "Click me")
* ]);
* ```
*/
interface HtmlTagCreator {
/**
* Create HTML element with props and content
* @param props - HTML attributes and event handlers
* @param content - Child nodes or content
* @returns HTMLElement
*/
(props?: HtmlProps | HtmlContent, content?: HtmlContent): HTMLElement;
}
// Type-safe tag creators
const div: HtmlTagCreator;
const span: HtmlTagCreator;
const p: HtmlTagCreator;
const button: HtmlTagCreator;
const h1: HtmlTagCreator;
const h2: HtmlTagCreator;
const h3: HtmlTagCreator;
const ul: HtmlTagCreator;
const ol: HtmlTagCreator;
const li: HtmlTagCreator;
const a: HtmlTagCreator;
const label: HtmlTagCreator;
const section: HtmlTagCreator;
const nav: HtmlTagCreator;
const main: HtmlTagCreator;
const header: HtmlTagCreator;
const footer: HtmlTagCreator;
const input: HtmlTagCreator;
const form: HtmlTagCreator;
const img: HtmlTagCreator;
const select: HtmlTagCreator;
const option: HtmlTagCreator;
const table: HtmlTagCreator;
const thead: HtmlTagCreator;
const tbody: HtmlTagCreator;
const tr: HtmlTagCreator;
const th: HtmlTagCreator;
const td: HtmlTagCreator;
const canvas: HtmlTagCreator;
const video: HtmlTagCreator;
const audio: HtmlTagCreator;
}
/**
* Helper types for common use cases
*/
export namespace SigProTypes {
/**
* Extract the value type from a Signal
*/
type SignalValue<T> = T extends Signal<infer U> ? U : never;
/**
* Extract the return type from a Computed
*/
type ComputedValue<T> = T extends Computed<infer U> ? U : never;
/**
* Props for a component function
*/
interface ComponentProps {
children?: HtmlContent;
[key: string]: any;
}
/**
* Component function type
*/
type Component<P extends ComponentProps = ComponentProps> = (props: P) => HTMLElement;
/**
* Async component type (for lazy loading)
*/
type AsyncComponent = () => Promise<{ default: Component }>;
}
export {};
// Make sure $ is available globally
declare const $: SigPro;

View File

@@ -2,28 +2,19 @@
* SigPro - Atomic Unified Reactive Engine
* A lightweight, fine-grained reactivity system with built-in routing and plugin support.
* @author Gemini & User
*
* Type definitions available in sigpro.d.ts
*/
(() => {
/** @type {Function|null} Internal tracker for the currently executing reactive effect. */
let activeEffect = null;
/**
* @typedef {Object} SigPro
* @property {function(any|function, string=): Function} $ - Creates a Signal or Computed. Optional key for localStorage.
* @property {function(string, Object=, any=): HTMLElement} html - Creates a reactive HTML element.
* @property {function((HTMLElement|function), (HTMLElement|string)=): void} mount - Mounts a component to the DOM.
* @property {function(Array<Object>): HTMLElement} router - Initializes a hash-based router.
* @property {function(string): void} router.go - Programmatic navigation to a hash path.
* @property {function((function|string|Array<string>)): (Promise<SigPro>|SigPro)} plugin - Extends SigPro or loads external scripts.
*/
/**
* Creates a Signal (state) or a Computed/Effect (reaction).
* Supports optional persistence in localStorage.
* * @param {any|function} initial - Initial value or a function for computed logic.
* @param {string} [key] - Optional localStorage key for automatic state persistence.
* @returns {Function} A reactive accessor/mutator function.
*/
* Creates a reactive Signal or Computed value
* @param {any|Function} initial - Initial value or computed function
* @param {string} [key] - Optional localStorage key for persistence
* @returns {Function} Reactive accessor/mutator function
*/
const $ = (initial, key) => {
const subs = new Set();
@@ -69,11 +60,11 @@
};
/**
* Hyperscript engine to render reactive HTML nodes.
* @param {string} tag - The HTML tag name (e.g., 'div', 'button').
* @param {Object} [props] - Attributes, events (onclick), or reactive props ($value, $class).
* @param {any} [content] - String, Node, Array of nodes, or reactive function.
* @returns {HTMLElement} A live DOM element linked to SigPro signals.
* Creates reactive HTML elements
* @param {string} tag - HTML tag name
* @param {Object} [props] - Attributes and event handlers
* @param {any} [content] - Child content
* @returns {HTMLElement}
*/
$.html = (tag, props = {}, content = []) => {
const el = document.createElement(tag);
@@ -87,12 +78,10 @@
el.addEventListener(key.toLowerCase().slice(2), val);
} else if (key.startsWith('$')) {
const attr = key.slice(1);
// Two-way binding for inputs
if ((attr === 'value' || attr === 'checked') && typeof val === 'function') {
const ev = attr === 'checked' ? 'change' : 'input';
el.addEventListener(ev, e => val(attr === 'checked' ? e.target.checked : e.target.value));
}
// Reactive attribute update
$(() => {
const v = typeof val === 'function' ? val() : val;
if (attr === 'value' || attr === 'checked') el[attr] = v;
@@ -126,9 +115,9 @@
tags.forEach(t => window[t] = (p, c) => $.html(t, p, c));
/**
* Application mounter.
* @param {HTMLElement|function} node - Root component or element to mount.
* @param {HTMLElement|string} [target=document.body] - Target element or CSS selector.
* Mounts a component to the DOM
* @param {HTMLElement|Function} node - Component or element to mount
* @param {HTMLElement|string} [target=document.body] - Target element or selector
*/
$.mount = (node, target = document.body) => {
const el = typeof target === 'string' ? document.querySelector(target) : target;
@@ -139,11 +128,10 @@
};
/**
* Initializes a reactive hash-based router.
* Maps URL hash changes to component rendering and supports Vite's dynamic imports.
* * @param {Array<{path: string, component: Function|Promise|HTMLElement}>} routes - Array of route objects.
* @returns {HTMLElement} A reactive div container that swaps content based on the current hash.
*/
* Initializes a hash-based router
* @param {Array<{path: string, component: Function|Promise|HTMLElement}>} routes
* @returns {HTMLElement}
*/
$.router = (routes) => {
const sPath = $(window.location.hash.replace(/^#/, "") || "/");
window.addEventListener("hashchange", () => sPath(window.location.hash.replace(/^#/, "") || "/"));
@@ -185,20 +173,17 @@
};
/**
* Programmatically navigates to a specific path using the hash.
* * @param {string} path - The destination path (e.g., '/home' or 'settings').
* @example
* $.router.go('/profile/42');
* Programmatic navigation
* @param {string} path - Destination path
*/
$.router.go = (path) => {
window.location.hash = path.startsWith('/') ? path : `/${path}`;
};
/**
* Polymorphic Plugin System.
* Registers internal functions or loads external .js files as plugins.
* @param {function|string|Array<string>} source - Plugin function or URL(s).
* @returns {Promise<SigPro>|SigPro} Resolves with the $ instance after loading or registering.
* Plugin system - extends SigPro or loads external scripts
* @param {Function|string|string[]} source - Plugin or script URL(s)
* @returns {Promise<SigPro>|SigPro}
*/
$.plugin = (source) => {
if (typeof source === 'function') {