@kitn.ai/ui
Version:
Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. Authored in SolidJS.
121 lines (120 loc) • 6.09 kB
TypeScript
import { JSX } from 'solid-js';
import { CardEnvelope, CardHost, CardResolution } from '../primitives/card-contract';
export interface TasksTask {
id: string;
label: string;
description?: string;
checked?: boolean;
disabled?: boolean;
}
export interface TasksCardData {
/**
* `select` (default) = checkbox rows + a confirm button that emits the contract
* `submit`. `progress` = an onboarding/checklist look: a header `done / total`
* count, circular indicators, per-item title + muted description, and NO confirm
* button (checking a row is itself the terminal action). Both share the same
* selection model (toggle by id, the `max` gate, `kai-value-change`); `progress`
* is purely a presentational variant.
*/
mode?: 'select' | 'progress';
heading?: string;
tasks: TasksTask[];
selectAll?: boolean;
confirmLabel?: string;
allowEmpty?: boolean;
min?: number;
max?: number;
dismissible?: boolean;
}
export interface TasksCardResult {
selected: string[];
}
export type TasksCardEnvelope = CardEnvelope<'tasks', TasksCardData>;
export declare const TASKS_CARD_TYPE: "tasks";
/** De-dupe tasks by id (first wins). Returns the usable list + an optional error. */
export declare function normalizeTasks(tasks: unknown): {
tasks: TasksTask[];
error?: string;
};
/** The ids of the initially-checked tasks (in input order). */
export declare function initialSelected(tasks: TasksTask[]): string[];
/** The selected ids in input order (selection set ∩ tasks, preserving task order). */
export declare function selectedInOrder(tasks: TasksTask[], selected: Set<string>): string[];
/** The toggleable (non-disabled) task ids. */
export declare function toggleableIds(tasks: TasksTask[]): string[];
export type SelectAllState = 'checked' | 'unchecked' | 'indeterminate';
/** Select-all tri-state over the toggleable rows. */
export declare function selectAllState(tasks: TasksTask[], selected: Set<string>): SelectAllState;
/** Whether select-all should be shown: requested AND not blocked by `max` (since
* "all" would violate max). */
export declare function showSelectAll(data: TasksCardData, tasks: TasksTask[]): boolean;
/** Whether the card is in the onboarding-checklist `progress` look (no confirm). */
export declare function isProgressMode(data: TasksCardData): boolean;
/** The header progress count (`done` checked / `total` rows) for `progress` mode. */
export declare function progressCount(tasks: TasksTask[], selected: Set<string>): {
done: number;
total: number;
};
/** Whether confirm is enabled for the current selection count. */
export declare function canConfirm(data: TasksCardData, count: number): boolean;
/** Whether an unchecked row is blocked because `max` is reached. */
export declare function isMaxReached(data: TasksCardData, count: number): boolean;
/** The disabled-reason text for confirm (for aria-describedby), or undefined. */
export declare function confirmReason(data: TasksCardData, count: number): string | undefined;
/** Imperative handle exposed via `controllerRef` — surfaces the tasks card's latent
* selection model (set the checked ids, toggle one, confirm, focus the group,
* dismiss/reopen) so the `<kai-tasks>` facade can forward them as instance methods. */
export interface TasksCardController {
/** Set the checked ids (local-only, no emit), respecting disabled/max. No arg = select all toggleable rows. */
select(taskIds?: string[]): void;
/** Toggle one task by id, honoring the max gate. */
toggle(taskId: string, checked?: boolean): void;
/** Confirm the current selection (only when allowed) — emits `submit` + resolves. */
send(): void;
/** Focus the task group (select-all checkbox if shown, else the first row). */
focus(options?: FocusOptions): void;
/** Trigger the dismiss path (emit `dismiss` + collapse to the re-openable stub). */
dismiss(): void;
/** Re-open a dismissed card from its stub (emit `reopen`). */
reopen(): void;
}
export interface TasksCardProps {
/** The tasks definition (CardEnvelope.data). */
data?: TasksCardData;
/** The card id used to correlate every emitted CardEvent. */
cardId?: string;
/** The envelope title rendered in the card chrome. */
heading?: string;
/** Optional explicit CardHost (otherwise read from a CardProvider, otherwise the
* bubbling `kai-card` CustomEvent off `hostElement`). */
host?: CardHost;
/** The custom-element host node, for the bubbling `kai-card` fallback emit. */
hostElement?: HTMLElement;
class?: string;
/** When set, render the chromed read-only summary instead of the interactive controls. */
resolution?: CardResolution;
/** Controlled selection (task ids) — when set, this wins over internal state. */
value?: string[];
/** Uncontrolled initial selection (task ids), overlaying per-task `checked`. */
defaultValue?: string[];
/** Freeze the whole list + Confirm. */
disabled?: boolean;
/** Display-only: rows can't be toggled and show the default cursor (no pointer,
* no hover background, no focus ring). Keeps the visual content as-is — this only
* drops the interactive affordances + a11y exposure. */
readonly?: boolean;
/** Fires on every selection change with the selected ids (distinct from submit). */
onValueChange?: (payload: {
value: string[];
}) => void;
/** Receive the imperative controller once mounted. */
controllerRef?: (controller: TasksCardController) => void;
}
/**
* `TasksCard` — a selectable task/plan list (checkbox rows + optional select-all
* + a confirm button) inside `Card` chrome. Row toggling and select-all are local
* UI state; only the final confirm emits the Card contract's `submit` verb
* (`{ kind:'submit', cardId, data:{ selected } }`) with the checked ids in
* input order. Emits `ready` on mount and `error` for an unusable definition.
*/
export declare function TasksCard(props: TasksCardProps): JSX.Element;