import { supportedBeatTypes } from 'mulmocast/browser'; /** * Editing works on the beat array directly, so a beat is `Record` here * rather than the cli's `MulmoBeat`: an in-progress edit is routinely invalid (a half-typed * url, chartData mid-keystroke), and a type that forbids that would have to be fought at * every keystroke. `beatToHtml` returns undefined for anything it cannot render, which is * the same answer it gives for a beat type it does not support, so the preview degrades * rather than breaking. */ export type EditableBeat = Record; export type BeatType = (typeof supportedBeatTypes)[number]; /** A plain object — not an array, not null. Every nested read below goes through it. */ export declare const isRecord: (value: unknown) => value is Record; /** The beat types this editor can create. Mirrors what beatToHtml renders. */ export declare const BEAT_TYPES: readonly BeatType[]; export declare const makeBeat: (type: BeatType) => EditableBeat; export declare const beatType: (beat: EditableBeat) => string; /** Read `beat.image` as a record. Returns an empty one rather than throwing on a malformed beat. */ export declare const beatImage: (beat: EditableBeat) => Record; /** A beat with one `image` field replaced. Returns a new object; nothing is mutated. */ export declare const withImageField: (beat: EditableBeat, field: string, value: unknown) => EditableBeat; /** A beat with one field replaced on `image.`, for the nested `slide` / `source` / `code` shapes. */ export declare const withNestedField: (beat: EditableBeat, parent: string, field: string, value: unknown) => EditableBeat; /** Read a string field off `image`, or off `image.` when a parent is given. */ export declare const readString: (beat: EditableBeat, field: string, parent?: string) => string; /** Move `from` to `to`, returning a new array. Out-of-range moves return the input unchanged. */ export declare const moveItem: (items: readonly T[], from: number, to: number) => T[]; /** * Where the selection lands after the beat at `removed` is deleted. `remaining` is the length * after the removal. The selection follows the beat it was on, so deleting a row above the * selected one does not silently move the user onto the next beat. */ export declare const selectionAfterRemove: (selected: number, removed: number, remaining: number) => number; /** Where the selection lands after `moveItem(items, from, to)` — same rule, same reason. */ export declare const selectionAfterMove: (selected: number, from: number, to: number, length: number) => number; /** * A beat's chartData as a key that separates every state it can be in. * * `JSON.stringify` cannot: it answers `undefined` for an absent field AND for one set to * `undefined`, and `"null"` for one set to null — three states, two answers. Each collision * lets a draft typed into one beat survive onto another, which is one bug reported three * times over three review rounds. The prefixes make the states distinct by construction * rather than by enumerating the pairs that must not collide. */ export declare const chartDataKey: (beat: EditableBeat) => string; /** * `JSON.stringify` for a value this editor did not create. A beat arrives as a prop, and a * script loaded from elsewhere can hold a cycle or a BigInt, which throw. This runs inside a * Vue watch getter and a computed, where a throw breaks the render — so it degrades to "this * chart cannot be shown" instead, which is how the rest of this editor treats a beat it * cannot handle. */ export declare const serializeChartData: (chartData: unknown, indent?: number) => string | undefined; /** Not JSON output, so no real chartData can produce it — see `chartDataKey`. */ export declare const UNSERIALIZABLE = "unserializable"; /** * Whether a chart JSON draft still belongs to the beat under it. * * The draft owns the beat exactly while the beat's `chartData` is what the draft parses to: * that is the state this textarea puts them in, and nothing else does. A half-typed draft * parses to nothing and emits nothing, so if the beat changed underneath it, the beat was * replaced. Both sides go through `chartDataKey`, so a draft can never own a beat whose * chartData is absent or `undefined` — only one that literally holds the parsed value. */ export declare const draftOwnsBeat: (draft: string, beat: EditableBeat) => boolean; /** * A list of strings out of a nested field of `beat.image`, e.g. a textSlide's bullets. * * Two editors were reading the same list with the same filter. The filter belongs next to the * other readers, not copied into each of them. */ export declare const readStringList: (beat: EditableBeat, field: string, parent: string) => string[];