watch-selector
Version:
Runs a function when a selector is added to dom
1,136 lines • 36.3 kB
TypeScript
/**
* State Management with Sync Generators
*
* This module provides state management functions that work with sync generators
* and the yield* pattern for better type safety and consistency.
*/
import type { Workflow } from "../types";
/**
* Set state value for the current element.
*
* Stores a value in the element's state map with type safety. Each element
* maintains its own isolated state that persists across DOM mutations.
*
* @template T - Type of the value being stored
* @param key - State key identifier (string)
* @param value - Value to store in state
* @returns Workflow<void> - Generator workflow for yield*
*
* @example Basic state setting
* ```typescript
* watch('.counter', function* () {
* yield* setState('count', 0);
* yield* setState('user', { name: 'John', age: 30 });
* });
* ```
*
* @example With type safety
* ```typescript
* interface UserData {
* name: string;
* age: number;
* email: string;
* }
*
* watch('.profile', function* () {
* const userData: UserData = {
* name: 'Jane',
* age: 25,
* email: 'jane@example.com'
* };
* yield* setState<UserData>('user', userData);
* });
* ```
*
* @example Setting multiple states
* ```typescript
* watch('.form', function* () {
* yield* setState('isValid', false);
* yield* setState('errors', []);
* yield* setState('submitCount', 0);
* yield* setState('lastSubmit', new Date());
* });
* ```
*/
export declare function setState<T>(key: string, value: T): Workflow<void>;
export declare namespace setState {
var gen: <T>(key: string, value: T) => Workflow<void>;
}
/**
* Get state value for the current element with optional default value.
*
* Retrieves a value from the element's state map with type safety.
* Returns the default value if the key doesn't exist or state is uninitialized.
*
* @template T - Expected type of the stored value
* @param key - State key identifier to retrieve
* @param defaultValue - Optional default value if key doesn't exist
* @returns Workflow<T | undefined> - The stored value, default value, or undefined
*
* @example Basic state retrieval
* ```typescript
* watch('.counter', function* () {
* const count = yield* getState<number>('count', 0);
* yield* text(`Count: ${count}`);
* });
* ```
*
* @example With complex types
* ```typescript
* interface Settings {
* theme: 'light' | 'dark';
* notifications: boolean;
* language: string;
* }
*
* watch('.settings-panel', function* () {
* const settings = yield* getState<Settings>('userSettings', {
* theme: 'light',
* notifications: true,
* language: 'en'
* });
*
* yield* toggleClass('dark-theme', settings.theme === 'dark');
* });
* ```
*
* @example Conditional logic based on state
* ```typescript
* watch('.widget', function* () {
* const isInitialized = yield* getState<boolean>('initialized');
*
* if (!isInitialized) {
* yield* addClass('loading');
* yield* initializeWidget();
* yield* setState('initialized', true);
* yield* removeClass('loading');
* }
* });
* ```
*/
export declare function getState<T>(key: string, defaultValue?: T): Workflow<T | undefined>;
export declare namespace getState {
var gen: <T>(key: string, defaultValue?: T) => Workflow<T | undefined>;
}
/**
* Update state value using an updater function with atomic operation.
*
* Safely updates state by passing the current value to an updater function
* and storing the result. This ensures consistent state updates even with
* complex transformations.
*
* @template T - Type of the state value being updated
* @param key - State key identifier to update
* @param updater - Function that receives current value and returns new value
* @returns Workflow<void> - Generator workflow for yield*
*
* @example Counter increment
* ```typescript
* watch('.counter', function* () {
* yield* click(function* () {
* yield* updateState<number>('count', (current = 0) => current + 1);
* const newCount = yield* getState<number>('count', 0);
* yield* text(`Count: ${newCount}`);
* });
* });
* ```
*
* @example Array manipulation
* ```typescript
* watch('.todo-list', function* () {
* yield* click('.add-item', function* () {
* const newItem = yield* value<string>('.new-item-input');
*
* yield* updateState<string[]>('items', (items = []) => [
* ...items,
* newItem
* ]);
*
* yield* value('.new-item-input', ''); // Clear input
* });
* });
* ```
*
* @example Object updates with spread
* ```typescript
* watch('.user-form', function* () {
* yield* input('.name-field', function* (e) {
* const name = e.target.value;
*
* yield* updateState<User>('user', (user = {}) => ({
* ...user,
* name,
* lastUpdated: new Date()
* }));
* });
* });
* ```
*
* @example Complex state transformation
* ```typescript
* watch('.game-board', function* () {
* yield* click('.cell', function* (e) {
* const cellIndex = parseInt(e.target.dataset.index || '0');
*
* yield* updateState<GameState>('gameState', (state = defaultGameState) => {
* if (state.board[cellIndex] !== null || state.gameOver) {
* return state; // Invalid move
* }
*
* const newBoard = [...state.board];
* newBoard[cellIndex] = state.currentPlayer;
*
* return {
* ...state,
* board: newBoard,
* currentPlayer: state.currentPlayer === 'X' ? 'O' : 'X',
* moveCount: state.moveCount + 1
* };
* });
* });
* });
* ```
*/
export declare function updateState<T>(key: string, updater: (value: T | undefined) => T): Workflow<void>;
export declare namespace updateState {
var gen: <T>(key: string, updater: (value: T | undefined) => T) => Workflow<void>;
}
/**
* Check if a state key exists for the current element.
*
* Returns true if the specified key exists in the element's state map,
* false otherwise. Useful for conditional logic based on state presence.
*
* @param key - State key identifier to check
* @returns Workflow<boolean> - true if key exists, false otherwise
*
* @example Conditional initialization
* ```typescript
* watch('.widget', function* () {
* const isInitialized = yield* hasState('initialized');
*
* if (!isInitialized) {
* yield* setState('config', defaultConfig);
* yield* setState('initialized', true);
* yield* addClass('ready');
* }
* });
* ```
*
* @example State validation
* ```typescript
* watch('.form', function* () {
* const hasErrors = yield* hasState('validationErrors');
* const hasData = yield* hasState('formData');
*
* yield* toggleClass('has-errors', hasErrors);
* yield* toggleClass('has-data', hasData);
*
* if (hasData && !hasErrors) {
* yield* removeClass('submit-btn', 'disabled');
* }
* });
* ```
*
* @example Cache management
* ```typescript
* watch('.data-display', function* () {
* const hasCachedData = yield* hasState('cachedResults');
*
* if (hasCachedData) {
* const data = yield* getState('cachedResults');
* yield* renderData(data);
* } else {
* yield* addClass('loading');
* const freshData = yield* fetchData();
* yield* setState('cachedResults', freshData);
* yield* renderData(freshData);
* yield* removeClass('loading');
* }
* });
* ```
*/
export declare function hasState(key: string): Workflow<boolean>;
export declare namespace hasState {
var gen: (key: string) => Workflow<boolean>;
}
/**
* Delete a state key from the current element's state.
*
* Removes the specified key and its value from the element's state map.
* Returns true if the key existed and was deleted, false otherwise.
*
* @param key - State key identifier to delete
* @returns Workflow<boolean> - true if key was deleted, false if it didn't exist
*
* @example Cleanup temporary state
* ```typescript
* watch('.modal', function* () {
* yield* click('.close', function* () {
* yield* deleteState('temporaryData');
* yield* deleteState('userInput');
* yield* deleteState('validationErrors');
* yield* addClass('closed');
* });
* });
* ```
*
* @example Conditional cleanup
* ```typescript
* watch('.cache-manager', function* () {
* yield* click('.clear-expired', function* () {
* const expiredKeys = yield* getState<string[]>('expiredKeys', []);
*
* for (const key of expiredKeys) {
* const wasDeleted = yield* deleteState(key);
* if (wasDeleted) {
* console.log(`Cleared expired cache: ${key}`);
* }
* }
*
* yield* deleteState('expiredKeys');
* });
* });
* ```
*
* @example State lifecycle management
* ```typescript
* watch('.session-manager', function* () {
* yield* onUnmount(function* () {
* // Clean up sensitive data on component unmount
* yield* deleteState('authToken');
* yield* deleteState('userData');
* yield* deleteState('sessionId');
* });
* });
* ```
*/
export declare function deleteState(key: string): Workflow<boolean>;
export declare namespace deleteState {
var gen: (key: string) => Workflow<boolean>;
}
/**
* Clear all state for the current element.
*
* Removes all key-value pairs from the element's state map, effectively
* resetting the element to have no stored state.
*
* @returns Workflow<void> - Generator workflow for yield*
*
* @example Reset component state
* ```typescript
* watch('.game-board', function* () {
* yield* click('.reset-game', function* () {
* yield* clearState();
* yield* removeClass('game-over');
* yield* addClass('ready-to-play');
* yield* text('.status', 'Game reset - click to start!');
* });
* });
* ```
*
* @example Form reset with state cleanup
* ```typescript
* watch('.contact-form', function* () {
* yield* click('.reset-form', function* () {
* // Clear all form state
* yield* clearState();
*
* // Reset form UI
* yield* removeClass('has-errors');
* yield* removeClass('submitted');
* yield* text('.error-messages', '');
*
* // Reset form fields
* yield* value('input', '');
* yield* value('textarea', '');
* });
* });
* ```
*
* @example Session cleanup
* ```typescript
* watch('.user-session', function* () {
* yield* click('.logout', function* () {
* // Clear all session state
* yield* clearState();
*
* // Update UI to logged-out state
* yield* addClass('logged-out');
* yield* removeClass('authenticated');
* yield* text('.username', 'Guest');
* });
* });
* ```
*/
export declare function clearState(): Workflow<void>;
export declare namespace clearState {
var gen: () => Workflow<void>;
}
/**
* Get all state keys for the current element.
*
* Returns an array of all state key names stored in the element's state map.
* Useful for debugging, state inspection, or bulk state operations.
*
* @returns Workflow<string[]> - Array of all state key names
*
* @example State debugging
* ```typescript
* watch('.debug-panel', function* () {
* yield* click('.show-state', function* () {
* const keys = yield* getStateKeys();
* yield* text('.state-keys', `State keys: ${keys.join(', ')}`);
*
* if (keys.length === 0) {
* yield* addClass('no-state');
* yield* text('.state-info', 'No state data found');
* }
* });
* });
* ```
*
* @example State validation
* ```typescript
* watch('.form-validator', function* () {
* yield* click('.validate', function* () {
* const keys = yield* getStateKeys();
* const requiredKeys = ['username', 'email', 'password'];
*
* const missingKeys = requiredKeys.filter(key => !keys.includes(key));
*
* if (missingKeys.length > 0) {
* yield* addClass('incomplete');
* yield* text('.errors', `Missing: ${missingKeys.join(', ')}`);
* } else {
* yield* removeClass('incomplete');
* yield* addClass('valid');
* }
* });
* });
* ```
*
* @example State export functionality
* ```typescript
* watch('.data-export', function* () {
* yield* click('.export-state', function* () {
* const keys = yield* getStateKeys();
* const stateData: Record<string, any> = {};
*
* for (const key of keys) {
* stateData[key] = yield* getState(key);
* }
*
* yield* attr('.export-link', 'href',
* `data:application/json,${encodeURIComponent(JSON.stringify(stateData))}`
* );
* yield* removeClass('.export-link', 'hidden');
* });
* });
* ```
*/
export declare function getStateKeys(): Workflow<string[]>;
export declare namespace getStateKeys {
var gen: () => Workflow<string[]>;
}
/**
* Get all state entries as key-value pairs for the current element.
*
* Returns an array of [key, value] tuples representing all state data
* stored in the element's state map. Useful for state inspection,
* serialization, or bulk operations.
*
* @template T - Expected type of state values (defaults to any)
* @returns Workflow<Array<[string, T]>> - Array of [key, value] tuples
*
* @example State inspection
* ```typescript
* watch('.state-viewer', function* () {
* yield* click('.show-all-state', function* () {
* const entries = yield* getStateEntries<any>();
*
* if (entries.length === 0) {
* yield* text('.state-display', 'No state data found');
* } else {
* const stateHtml = entries
* .map(([key, value]) => `<div><strong>${key}:</strong> ${JSON.stringify(value)}</div>`)
* .join('');
* yield* html('.state-display', stateHtml);
* }
* });
* });
* ```
*
* @example State serialization
* ```typescript
* watch('.export-manager', function* () {
* yield* click('.export-data', function* () {
* const entries = yield* getStateEntries<any>();
* const stateObject = Object.fromEntries(entries);
*
* yield* attr('.download-link', 'href',
* `data:application/json,${encodeURIComponent(JSON.stringify(stateObject))}`
* );
* yield* attr('.download-link', 'download', 'state-export.json');
* });
* });
* ```
*
* @example State comparison
* ```typescript
* watch('.state-diff', function* () {
* yield* click('.compare-state', function* () {
* const currentEntries = yield* getStateEntries<any>();
* const previousEntries = yield* getState<Array<[string, any]>>('previousState', []);
*
* const changes = currentEntries.filter(([key, value]) => {
* const prev = previousEntries.find(([prevKey]) => prevKey === key);
* return !prev || prev[1] !== value;
* });
*
* yield* setState('previousState', currentEntries);
* yield* text('.changes-count', `${changes.length} changes detected`);
* });
* });
* ```
*/
export declare function getStateEntries<T = any>(): Workflow<Array<[string, T]>>;
export declare namespace getStateEntries {
var gen: <T = any>() => Workflow<Array<[string, T]>>;
}
/**
* Get the number of state entries for the current element.
*
* Returns the count of key-value pairs stored in the element's state map.
* Useful for state monitoring, debugging, and conditional logic.
*
* @returns Workflow<number> - Number of state entries
*
* @example State monitoring
* ```typescript
* watch('.state-monitor', function* () {
* yield* input('.data-input', function* () {
* const size = yield* getStateSize();
* yield* text('.state-count', `${size} items in state`);
*
* if (size > 10) {
* yield* addClass('state-warning');
* yield* text('.warning', 'Large state detected - consider cleanup');
* }
* });
* });
* ```
*
* @example Conditional cleanup
* ```typescript
* watch('.memory-manager', function* () {
* yield* setInterval(function* () {
* const size = yield* getStateSize();
*
* if (size > 50) {
* // Trigger cleanup for large state
* const keys = yield* getStateKeys();
* const tempKeys = keys.filter(key => key.startsWith('temp_'));
*
* for (const key of tempKeys) {
* yield* deleteState(key);
* }
* }
* }, 30000); // Check every 30 seconds
* });
* ```
*
* @example State validation
* ```typescript
* watch('.form-validator', function* () {
* yield* click('.validate-completeness', function* () {
* const size = yield* getStateSize();
* const requiredFieldCount = 5;
*
* if (size < requiredFieldCount) {
* yield* addClass('incomplete-form');
* yield* text('.validation-error',
* `Missing ${requiredFieldCount - size} required fields`
* );
* } else {
* yield* removeClass('incomplete-form');
* yield* addClass('form-complete');
* }
* });
* });
* ```
*/
export declare function getStateSize(): Workflow<number>;
export declare namespace getStateSize {
var gen: () => Workflow<number>;
}
/**
* Merge state with an object, adding multiple key-value pairs at once.
*
* Takes an object and adds all its properties to the element's state map.
* Existing state values with the same keys will be overwritten.
*
* @param stateObject - Object containing key-value pairs to merge into state
* @returns Workflow<void> - Generator workflow for yield*
*
* @example Bulk state initialization
* ```typescript
* watch('.user-profile', function* () {
* const userData = {
* name: 'John Doe',
* email: 'john@example.com',
* preferences: { theme: 'dark', lang: 'en' },
* lastLogin: new Date(),
* isActive: true
* };
*
* yield* mergeState(userData);
*
* // Now all properties are available in state
* const name = yield* getState<string>('name');
* yield* text('.user-name', name);
* });
* ```
*
* @example Form data collection
* ```typescript
* watch('.contact-form', function* () {
* yield* submit(function* (event) {
* event.preventDefault();
*
* const formData = new FormData(event.target);
* const formObject = Object.fromEntries(formData.entries());
*
* // Merge all form data into state
* yield* mergeState(formObject);
*
* // Add metadata
* yield* mergeState({
* submittedAt: new Date(),
* isValid: true,
* attempts: (yield* getState<number>('attempts', 0)) + 1
* });
* });
* });
* ```
*
* @example Configuration merging
* ```typescript
* watch('.config-panel', function* () {
* const defaultConfig = {
* autoSave: true,
* theme: 'light',
* language: 'en',
* notifications: true
* };
*
* const userConfig = yield* loadUserConfig();
*
* // Merge default config first, then user overrides
* yield* mergeState(defaultConfig);
* yield* mergeState(userConfig);
* });
* ```
*/
export declare function mergeState(stateObject: Record<string, any>): Workflow<void>;
export declare namespace mergeState {
var gen: (stateObject: Record<string, any>) => Workflow<void>;
}
/**
* Get all state as a plain object with type safety.
*
* Converts the element's state map into a plain JavaScript object,
* making it easy to serialize, inspect, or pass to other functions.
*
* @template T - Expected type of the returned object (defaults to Record<string, any>)
* @returns Workflow<T> - Object containing all state key-value pairs
*
* @example State serialization
* ```typescript
* watch('.data-exporter', function* () {
* yield* click('.export', function* () {
* const stateObj = yield* getStateObject<UserState>();
*
* yield* attr('.download-link', 'href',
* `data:application/json,${encodeURIComponent(JSON.stringify(stateObj))}`
* );
* yield* attr('.download-link', 'download', 'user-state.json');
* });
* });
* ```
*
* @example State debugging
* ```typescript
* watch('.debug-panel', function* () {
* yield* click('.dump-state', function* () {
* const state = yield* getStateObject();
*
* console.log('Current state:', state);
* yield* text('.debug-output', JSON.stringify(state, null, 2));
* });
* });
* ```
*
* @example State validation with types
* ```typescript
* interface FormState {
* name: string;
* email: string;
* age: number;
* preferences: UserPreferences;
* }
*
* watch('.form-validator', function* () {
* yield* click('.validate-state', function* () {
* const formState = yield* getStateObject<FormState>();
*
* const isValid = validateFormState(formState);
* yield* toggleClass('valid-form', isValid);
*
* if (!isValid) {
* yield* text('.errors', 'Please complete all required fields');
* }
* });
* });
* ```
*/
export declare function getStateObject<T extends Record<string, any> = Record<string, any>>(): Workflow<T>;
export declare namespace getStateObject {
var gen: <T extends Record<string, any> = Record<string, any>>() => Workflow<T>;
}
/**
* Watch for changes to a specific state key with reactive callbacks.
*
* Sets up a reactive observer that triggers a callback whenever the specified
* state key is modified. The callback receives both the new and old values
* and can be either a regular function or a generator function.
*
* @template T - Type of the state value being watched
* @param key - State key to watch for changes
* @param callback - Function called when state changes (old value, new value)
* @returns Workflow<() => void> - Cleanup function to stop watching
*
* @example Basic state watching
* ```typescript
* watch('.counter', function* () {
* yield* setState('count', 0);
*
* const stopWatching = yield* watchState<number>('count', function* (newVal, oldVal) {
* yield* text('.display', `Count changed from ${oldVal} to ${newVal}`);
*
* if (newVal > 10) {
* yield* addClass('high-count');
* }
* });
*
* // Stop watching when component unmounts
* yield* onUnmount(() => stopWatching());
* });
* ```
*
* @example Form validation with state watching
* ```typescript
* watch('.form-field', function* () {
* yield* watchState<string>('value', function* (newValue, oldValue) {
* // Validate on every change
* const isValid = yield* validateField(newValue);
*
* yield* toggleClass('valid', isValid);
* yield* toggleClass('invalid', !isValid);
*
* if (!isValid) {
* yield* text('.error-message', 'This field is required');
* } else {
* yield* text('.error-message', '');
* }
* });
* });
* ```
*
* @example Complex state dependency tracking
* ```typescript
* watch('.shopping-cart', function* () {
* yield* watchState<CartItem[]>('items', function* (newItems, oldItems) {
* const total = newItems.reduce((sum, item) => sum + item.price * item.quantity, 0);
* yield* setState('total', total);
*
* yield* text('.item-count', `${newItems.length} items`);
* yield* text('.total-price', `$${total.toFixed(2)}`);
*
* // Update localStorage
* yield* persistState('items');
* });
* });
* ```
*/
export declare function watchState<T>(key: string, callback: (newValue: T | undefined, oldValue: T | undefined) => void | Generator<any, void, any>): Workflow<() => void>;
export declare namespace watchState {
var gen: <T>(key: string, callback: (newValue: T | undefined, oldValue: T | undefined) => void | Generator<any, void, any>) => Workflow<() => void>;
}
/**
* Create a computed state value that automatically updates based on dependencies.
*
* Creates a derived state value that is automatically computed from other state values.
* When any dependency changes, the computed value is recalculated and cached.
*
* @template T - Type of the computed value
* @param key - Key where the computed value will be cached
* @param dependencies - Array of state keys that this computation depends on
* @param compute - Function that computes the value from dependency values
* @returns Workflow<T> - The computed value
*
* @example Shopping cart total
* ```typescript
* watch('.shopping-cart', function* () {
* yield* setState('items', [
* { name: 'Widget', price: 10, quantity: 2 },
* { name: 'Gadget', price: 15, quantity: 1 }
* ]);
* yield* setState('taxRate', 0.08);
*
* // Computed subtotal
* const subtotal = yield* computedState<number>('subtotal', ['items'], (items) => {
* return items.reduce((sum, item) => sum + (item.price * item.quantity), 0);
* });
*
* // Computed total with tax
* const total = yield* computedState<number>('total', ['subtotal', 'taxRate'], (subtotal, taxRate) => {
* return subtotal * (1 + taxRate);
* });
*
* yield* text('.subtotal', `Subtotal: $${subtotal.toFixed(2)}`);
* yield* text('.total', `Total: $${total.toFixed(2)}`);
* });
* ```
*
* @example Form validation status
* ```typescript
* watch('.registration-form', function* () {
* const isValid = yield* computedState<boolean>('formValid',
* ['name', 'email', 'password'],
* (name, email, password) => {
* return name && name.length >= 2 &&
* email && email.includes('@') &&
* password && password.length >= 8;
* }
* );
*
* yield* toggleClass('form-valid', isValid);
* yield* attr('.submit-btn', 'disabled', !isValid ? 'true' : null);
* });
* ```
*
* @example User display name
* ```typescript
* watch('.user-profile', function* () {
* yield* setState('firstName', 'John');
* yield* setState('lastName', 'Doe');
* yield* setState('username', 'johndoe123');
*
* const displayName = yield* computedState<string>('displayName',
* ['firstName', 'lastName', 'username'],
* (firstName, lastName, username) => {
* if (firstName && lastName) {
* return `${firstName} ${lastName}`;
* }
* return username || 'Anonymous';
* }
* );
*
* yield* text('.user-name', displayName);
* });
* ```
*/
export declare function computedState<T>(key: string, dependencies: string[], compute: (...deps: any[]) => T): Workflow<T>;
export declare namespace computedState {
var gen: <T>(key: string, dependencies: string[], compute: (...deps: any[]) => T) => Workflow<T>;
}
/**
* Persist a state value to localStorage for persistence across sessions.
*
* Saves the specified state value to localStorage using JSON serialization.
* The value will be available even after page refreshes or browser restarts.
*
* @param key - State key to persist
* @param storageKey - Optional custom localStorage key (defaults to watch_state_{key})
* @returns Workflow<void> - Generator workflow for yield*
*
* @example User preferences persistence
* ```typescript
* watch('.settings-panel', function* () {
* yield* change('.theme-selector', function* (e) {
* const theme = e.target.value;
* yield* setState('theme', theme);
* yield* persistState('theme', 'user_theme_preference');
*
* yield* addClass('theme-' + theme);
* });
* });
* ```
*
* @example Form draft saving
* ```typescript
* watch('.blog-editor', function* () {
* yield* input('.content-textarea', function* (e) {
* const content = e.target.value;
* yield* setState('draftContent', content);
*
* // Auto-save draft every few seconds
* yield* persistState('draftContent', 'blog_draft');
* }, { debounce: 2000 });
* });
* ```
*
* @example Shopping cart persistence
* ```typescript
* watch('.shopping-cart', function* () {
* yield* watchState<CartItem[]>('items', function* (newItems) {
* // Persist cart whenever items change
* yield* persistState('items', 'shopping_cart_items');
* yield* text('.save-status', 'Cart saved');
* });
* });
* ```
*/
export declare function persistState(key: string, storageKey?: string): Workflow<void>;
export declare namespace persistState {
var gen: (key: string, storageKey?: string) => Workflow<void>;
}
/**
* Restore a state value from localStorage with fallback defaults.
*
* Attempts to load and parse a value from localStorage and set it in state.
* If the value doesn't exist or parsing fails, uses the provided default value.
*
* @template T - Type of the value being restored
* @param key - State key to restore the value to
* @param storageKey - Optional custom localStorage key (defaults to watch_state_{key})
* @param defaultValue - Fallback value if localStorage doesn't contain the key
* @returns Workflow<T | undefined> - The restored value or undefined
*
* @example User preferences restoration
* ```typescript
* watch('.app-container', function* () {
* // Restore theme preference on app start
* const theme = yield* restoreState<string>('theme', 'user_theme_preference', 'light');
* yield* addClass('theme-' + theme);
*
* // Restore language preference
* const language = yield* restoreState<string>('language', 'user_language', 'en');
* yield* attr('html', 'lang', language);
* });
* ```
*
* @example Form draft restoration
* ```typescript
* watch('.blog-editor', function* () {
* // Restore draft content when editor loads
* const draftContent = yield* restoreState<string>('draftContent', 'blog_draft', '');
*
* if (draftContent) {
* yield* value('.content-textarea', draftContent);
* yield* addClass('has-draft');
* yield* text('.draft-indicator', 'Draft restored');
* }
* });
* ```
*
* @example Shopping cart restoration
* ```typescript
* watch('.shopping-cart', function* () {
* const savedItems = yield* restoreState<CartItem[]>('items', 'shopping_cart_items', []);
*
* if (savedItems.length > 0) {
* yield* renderCartItems(savedItems);
* yield* text('.cart-count', String(savedItems.length));
* }
* });
* ```
*/
export declare function restoreState<T>(key: string, storageKey?: string, defaultValue?: T): Workflow<T | undefined>;
export declare namespace restoreState {
var gen: <T>(key: string, storageKey?: string, defaultValue?: T) => Workflow<T | undefined>;
}
/**
* Increment a numeric state value by a specified amount.
*
* Safely increments a numeric state value, treating undefined/missing values as 0.
* Perfect for counters, scores, and other numeric tracking.
*
* @param key - State key containing numeric value
* @param amount - Amount to increment by (defaults to 1)
* @returns Workflow<number> - The new incremented value
*
* @example Click counter
* ```typescript
* watch('.counter-button', function* () {
* yield* click(function* () {
* const newCount = yield* incrementState('clicks', 1);
* yield* text('.count-display', `Clicked ${newCount} times`);
*
* if (newCount === 10) {
* yield* addClass('milestone-reached');
* }
* });
* });
* ```
*
* @example Score tracking
* ```typescript
* watch('.game-board', function* () {
* yield* click('.score-point', function* () {
* const score = yield* incrementState('score', 10);
* yield* text('.score', `Score: ${score}`);
*
* if (score >= 100) {
* yield* addClass('high-score');
* yield* text('.status', 'High score achieved!');
* }
* });
* });
* ```
*/
export declare function incrementState(key: string, amount?: number): Workflow<number>;
export declare namespace incrementState {
var gen: (key: string, amount?: number) => Workflow<number>;
}
/**
* Decrement a numeric state value by a specified amount.
*
* Safely decrements a numeric state value, treating undefined/missing values as 0.
* Perfect for countdown timers, inventory tracking, and other numeric decreasing.
*
* @param key - State key containing numeric value
* @param amount - Amount to decrement by (defaults to 1)
* @returns Workflow<number> - The new decremented value
*
* @example Countdown timer
* ```typescript
* watch('.countdown', function* () {
* yield* setState('timeLeft', 60);
*
* const timer = setInterval(function* () {
* const timeLeft = yield* decrementState('timeLeft', 1);
* yield* text('.timer-display', `${timeLeft}s remaining`);
*
* if (timeLeft <= 0) {
* clearInterval(timer);
* yield* addClass('time-up');
* yield* text('.status', 'Time\'s up!');
* }
* }, 1000);
* });
* ```
*/
export declare function decrementState(key: string, amount?: number): Workflow<number>;
export declare namespace decrementState {
var gen: (key: string, amount?: number) => Workflow<number>;
}
/**
* Toggle a boolean state value between true and false.
*
* Flips a boolean state value, treating undefined/missing values as false.
* Perfect for toggle switches, visibility states, and other binary conditions.
*
* @param key - State key containing boolean value
* @returns Workflow<boolean> - The new toggled value
*
* @example Toggle visibility
* ```typescript
* watch('.toggle-button', function* () {
* yield* click(function* () {
* const isVisible = yield* toggleState('panelVisible');
* yield* toggleClass('.panel', 'hidden', !isVisible);
* yield* text('.toggle-text', isVisible ? 'Hide Panel' : 'Show Panel');
* });
* });
* ```
*/
export declare function toggleState(key: string): Workflow<boolean>;
export declare namespace toggleState {
var gen: (key: string) => Workflow<boolean>;
}
/**
* Append an item to an array state value.
*
* Adds an item to the end of an array stored in state, creating a new array if none exists.
* Perfect for lists, collections, and append-only data structures.
*
* @template T - Type of array items
* @param key - State key containing array
* @param item - Item to append to the array
* @returns Workflow<T[]> - The new array with item appended
*
* @example Todo list
* ```typescript
* watch('.todo-form', function* () {
* yield* submit(function* (e) {
* e.preventDefault();
* const newTodo = yield* value<string>('.todo-input');
*
* const todos = yield* appendToState<string>('todos', newTodo);
* yield* renderTodoList(todos);
* yield* value('.todo-input', ''); // Clear input
* });
* });
* ```
*/
export declare function appendToState<T>(key: string, item: T): Workflow<T[]>;
export declare namespace appendToState {
var gen: <T>(key: string, item: T) => Workflow<T[]>;
}
/**
* Prepend an item to the beginning of an array state value.
*
* Adds an item to the start of an array stored in state, creating a new array if none exists.
* Perfect for recent items lists, history tracking, and LIFO data structures.
*
* @template T - Type of array items
* @param key - State key containing array
* @param item - Item to prepend to the array
* @returns Workflow<T[]> - The new array with item prepended
*/
export declare function prependToState<T>(key: string, item: T): Workflow<T[]>;
export declare namespace prependToState {
var gen: <T>(key: string, item: T) => Workflow<T[]>;
}
/**
* Remove an item from an array state value.
*
* Removes the first occurrence of an item from an array stored in state.
* Returns the new array without the removed item.
*
* @template T - Type of array items
* @param key - State key containing array
* @param item - Item to remove from the array
* @returns Workflow<T[]> - The new array with item removed
*/
export declare function removeFromState<T>(key: string, item: T): Workflow<T[]>;
export declare namespace removeFromState {
var gen: <T>(key: string, item: T) => Workflow<T[]>;
}
declare const _default: {
setState: typeof setState;
getState: typeof getState;
updateState: typeof updateState;
hasState: typeof hasState;
deleteState: typeof deleteState;
clearState: typeof clearState;
getStateKeys: typeof getStateKeys;
getStateEntries: typeof getStateEntries;
getStateSize: typeof getStateSize;
mergeState: typeof mergeState;
getStateObject: typeof getStateObject;
watchState: typeof watchState;
computedState: typeof computedState;
persistState: typeof persistState;
restoreState: typeof restoreState;
incrementState: typeof incrementState;
decrementState: typeof decrementState;
toggleState: typeof toggleState;
appendToState: typeof appendToState;
prependToState: typeof prependToState;
removeFromState: typeof removeFromState;
};
export default _default;
//# sourceMappingURL=state-sync.d.ts.map