Hugs › Reference
Everything a page can know or do is in @getcliqio/hug-frontend. mount_hug and
useHug are built on this API; use it directly only when they don’t fit, or through the hug they
hand you.
import { connect } from '@getcliqio/hug-frontend';
const hug = await connect<Params, Values>();
hug.theme.apply(document.documentElement);
hug.auto_resize();
connect(options?)
Resolves once with everything the page needs, after the host’s init. Rejects with HugError: not_in_runtime
(not in a Hug host — use cliq hug dev), protocol_unsupported, timeout.
| Option | |
|---|---|
timeout_ms | How long to wait for the host |
transport | For tests: mock_host().transport |
The Hug
| Property | |
|---|---|
hug | { id, name, title, summary?, status, expires_at, requester, run: { id, name } } — requester is the run’s phase that asked (e.g. review; cliq hug dev in development) |
params | What it was asked |
mode | answer or view — changes with the mode and status events |
viewer | { name, via } — who is looking, and the channels that reached them |
mine | This viewer’s latest answer, or null |
viewing | In view mode, the answer to draw: { values, summary?, responder?, responded_at? } |
draft | Unsent values the host kept for this viewer, or null |
files | Upload slots: { name, accept?, max_bytes?, required, multiple? } |
attachments | Files it may read: { artifact_id, name, size, content_type, sha256 } |
progress | The requester’s status line (“1 answer couldn’t be used; …”), or null |
theme | { scheme, tokens, apply(el) } — apply sets the --cliq-* variables |
locale | The viewer’s locale |
protocol | The bridge protocol version in use |
| Method | |
|---|---|
set_values(values, { valid, problems?, submit?, summary? }) | The current answer — the host enables Submit while valid, shows problems, labels Submit ({ label, tone? }) and sends values and summary when pressed. Last call wins |
upload(key) | The host’s file picker for an upload slot → a file reference |
read_file(ref) | A file’s bytes, as a Blob |
file_url(ref) | read_file + an object URL |
download(ref) | The host saves the file for the person |
open_link(url) | Opens an http(s) link (one not in the params is shown first) |
resize(height) | Sets the frame’s height |
auto_resize(el?) | Keeps the frame fitted to el (default the body); returns a stop function |
on(event, fn) | Listens; returns an unsubscribe function |
dispose() | Stops listening to the host |
| Event | Payload | When |
|---|---|---|
update | { progress?, expires_at? } | The open Hug changes |
status | { status, mode: 'view' } | It closes, expires or is cancelled |
mode | { mode, viewing, start } | The page switches: after Submit (view), Change answer (answer, start = their answer) |
submitted | the stored answer | Submit succeeded |
submit_failed | problems | CliqHub refused the answer |
Errors
HugError with a code:
| Code | |
|---|---|
not_in_runtime | Not in a Hug host |
protocol_unsupported | No bridge protocol both sides speak |
timeout | The host didn’t answer |
upload_cancelled, upload_failed | The person closed the picker; the upload failed |
file_too_large, file_type | The file breaks the slot’s max_bytes or accept |
not_declared | Not an upload slot of this Hug |
read_denied, read_failed | The viewer may not read the file; the read failed |
rate_limited | Too many messages, uploads or reads at once |
Other exports
problems_from_zod(error), problems_text(problems) | A ZodError’s issues as { path, message }; problems as lines (a definition’s check already returns problems) |
parse_path, set_path | The path helpers set uses (verdicts[2].note) |
default_view, view_model | The default read-only view, drawn or as data |
format_bytes, humanize | 1.2 MB; ship_date → “Ship date” |
The low level, for comparison
review-batch without mount_hug:
import { connect } from '@getcliqio/hug-frontend';
import review_batch from '../hug';
const hug = await connect();
hug.theme.apply(document.documentElement);
hug.auto_resize();
let state = hug.draft ?? hug.mine?.values ?? { verdicts: hug.params.documents.map((d) => ({ id: d.id, ok: true })) };
const change = (next) => {
state = next;
const checked = review_batch.check(state, hug.params); // { ok, value } or { ok: false, problems }
hug.set_values(state, {
valid: checked.ok,
problems: checked.ok ? [] : checked.problems,
submit: { label: state.verdicts.every((v) => v.ok) ? 'Approve all' : 'Send verdicts' },
summary: checked.ok ? review_batch.summary(checked.value, hug.params) : undefined,
});
draw();
};
const draw = () => (hug.mode === 'view' ? draw_answer(hug.viewing.values) : draw_editor(state, change));
hug.on('mode', (m) => { if (m.start) state = m.start; hug.mode === 'answer' ? change(state) : draw(); });
hug.on('status', draw);
hug.mode === 'answer' ? change(state) : draw();
// …plus draw_editor, draw_answer and uploads, by hand
low-level example.