/*!
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/
import { Signal, Expression } from './rvx.js';

/**
 * Create a derived signal for debouncing user input updates.
 *
 * + If the source signal is updated, scheduled updates from the input are aborted.
 * + If the input signal is updated, a source update is scheduled with the specified delay and any previously scheduled update is aborted.
 * + Updates are processed until the current lifecycle is disposed.
 *
 * @param source The source signal.
 * @param delay The delay in milliseconds.
 * @returns The derived input signal.
 *
 * @example
 * ```tsx
 * import { debounce } from "rvx/convert";
 *
 * <TextInput value={someSignal.pipe(debounce, 300)} />
 * ```
 */
declare function debounce<T>(source: Signal<T>, delay: number): Signal<T>;

/**
 * Map expression values to strings except `null` or `undefined`.
 *
 * See {@link map}.
 *
 * @example
 * ```tsx
 * import { optionalString } from "rvx";
 *
 * <div some-value={optionalString(false)} />; // <div some-value="false" />
 * <div some-value={optionalString(null)} />; // <div />
 * <div some-value={optionalString(undefined)} />; // <div />
 * ```
 */
declare function optionalString<T>(input: Expression<T>): Expression<string | Exclude<T, Exclude<T, null | undefined>>>;

/**
 * Map an expression to join array elements using the specified separator.
 *
 * See {@link map}.
 *
 * @param separator The separator to use. Default is a space.
 *
 * @example
 * ```tsx
 * import { separated } from "rvx";
 *
 * <div aria-owns={separated(["a", "b", ...])} />
 * ```
 */
declare function separated(input: Expression<unknown[]>, separator?: string): Expression<string>;
declare function separated<T>(input: Expression<T>, separator?: string): Expression<T extends any[] ? (Exclude<T, any[]> | string) : T>;

/**
 * Map expression values to strings.
 *
 * See {@link map}.
 *
 * @example
 * ```tsx
 * import { string } from "rvx/convert";
 *
 * <div some-value={string(true)} />; // <div some-value="true" />
 * <div some-value={string(false)} />; // <div some-value="false" />
 * <div some-value={string(null)} />; // <div some-value="null" />
 * ```
 */
declare function string(input: Expression<unknown>): Expression<string>;

/**
 * Create a derived signal for trimming user input.
 *
 * + The source signal contains the trimmed value.
 * + The input signal contains the un-trimmed value.
 * + Updates are processed until the current lifecycle is disposed.
 *
 * @param source The source signal.
 * @returns The derived input signal.
 *
 * @example
 * ```tsx
 * import { trim } from "rvx/convert";
 *
 * <TextInput value={someSignal.pipe(trim)} />
 * ```
 */
declare function trim(source: Signal<string>): Signal<string>;

export { debounce, optionalString, separated, string, trim };
