quoin-editor 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -8
- package/dist/headless.cjs +21 -11
- package/dist/headless.cjs.map +1 -1
- package/dist/headless.d.cts +1 -1
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +21 -11
- package/dist/headless.js.map +1 -1
- package/dist/index.cjs +301 -172
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -18
- package/dist/index.d.ts +35 -18
- package/dist/index.js +303 -174
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +23 -6
package/dist/index.d.cts
CHANGED
|
@@ -109,17 +109,17 @@ declare function paletteBlocks(definitions: AnyBlockDefinition[]): AnyBlockDefin
|
|
|
109
109
|
type BlockCanvasProps = {
|
|
110
110
|
/**
|
|
111
111
|
* The document. Update it synchronously from `onChange`, as with a controlled `<input value onChange>`.
|
|
112
|
-
* Applying the edit late is tolerated
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* behind the canvas's own state and reads as a foreign document. That does not revert the edit cleanly: the
|
|
116
|
-
* characters the copy predates are dropped and the ones typed after them are kept.
|
|
112
|
+
* Applying the edit late is tolerated: the canvas recognises an array it emitted however late it comes back, and
|
|
113
|
+
* a structural copy of one within 64 edits, so a transition, a debounced setter or a store that clones the
|
|
114
|
+
* document on the way through is safe.
|
|
117
115
|
* A new array that differs from the last one you supplied replaces what the canvas shows, which is how a host
|
|
118
116
|
* loads, undoes or merges. An array structurally equal to the last one you supplied is ignored, so a "discard
|
|
119
|
-
* changes" button that hands back the original document does nothing
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* block
|
|
117
|
+
* changes" button that hands back the original document does nothing. A host that does not echo `onChange` back
|
|
118
|
+
* meets the same when it restores a copy of a state from the last 64 edits, which reads as a late echo. Remount
|
|
119
|
+
* the canvas with a React `key` to force a reset in either case. The comparison is shallow over each block's
|
|
120
|
+
* `data`: a host whose block `data` holds nested objects rebuilt on every render, and which does not echo
|
|
121
|
+
* `onChange` back, can still lose an edit. The core block types all have flat data, so this only affects custom
|
|
122
|
+
* blocks.
|
|
123
123
|
*/
|
|
124
124
|
blocks: QuoinBlock[];
|
|
125
125
|
onChange: (blocks: QuoinBlock[]) => void;
|
|
@@ -209,8 +209,8 @@ type UploadFieldProps = {
|
|
|
209
209
|
label: string;
|
|
210
210
|
/** An `accept` attribute for the file input, such as `'image/*'` or `'.pdf'`. */
|
|
211
211
|
accept?: string;
|
|
212
|
-
/** Called once the upload resolves.
|
|
213
|
-
onUploaded: (result: UploadResult) => void
|
|
212
|
+
/** Called once the upload resolves. The field stays busy until a returned promise settles, and throwing or rejecting is reported through the canvas `onError`. */
|
|
213
|
+
onUploaded: (result: UploadResult) => void | Promise<void>;
|
|
214
214
|
};
|
|
215
215
|
/** A file picker wired to the canvas `upload` function, with its own busy state and inline error. */
|
|
216
216
|
declare function UploadField({ category, label, accept, onUploaded }: UploadFieldProps): React.JSX.Element;
|
|
@@ -267,7 +267,7 @@ type BlockList = {
|
|
|
267
267
|
declare function useBlockList(initial: QuoinBlock[]): BlockList;
|
|
268
268
|
|
|
269
269
|
/** Where a debounced save stands, for a "Saving..." or "Saved" indicator. */
|
|
270
|
-
type AutosaveStatus = 'idle' | 'saving' | 'saved' | 'retrying';
|
|
270
|
+
type AutosaveStatus = 'idle' | 'saving' | 'saved' | 'retrying' | 'failed';
|
|
271
271
|
/** What `useAutosave` tracks, how to build the payload, and how to persist it. */
|
|
272
272
|
type UseAutosaveInput<T> = {
|
|
273
273
|
/** The tracked fields. An edit to any of them marks dirty and restarts the debounce. */
|
|
@@ -280,24 +280,41 @@ type UseAutosaveInput<T> = {
|
|
|
280
280
|
save: (payload: T) => unknown;
|
|
281
281
|
debounceMs?: number;
|
|
282
282
|
maxBackoffMs?: number;
|
|
283
|
+
/** Retries after a failed save before giving up with status `failed`. Defaults to 8. */
|
|
284
|
+
maxRetries?: number;
|
|
285
|
+
/**
|
|
286
|
+
* Whether a failed save is worth retrying. Receives the rejection, or the resolved
|
|
287
|
+
* `{ ok: false }` value. Return false for a permanent failure. Defaults to always.
|
|
288
|
+
*/
|
|
289
|
+
isRetryable?: (error: unknown) => boolean;
|
|
290
|
+
/** Save a pending edit when the page is hidden or closed. Defaults to true. */
|
|
291
|
+
flushOnHide?: boolean;
|
|
283
292
|
};
|
|
284
|
-
/** The current save status
|
|
293
|
+
/** The current save status, the last failure, and ways to save immediately. */
|
|
285
294
|
type UseAutosaveResult = {
|
|
286
295
|
status: AutosaveStatus;
|
|
296
|
+
/** The last failure, kept while a retry is pending and cleared by the next success. */
|
|
297
|
+
error: unknown;
|
|
298
|
+
/** Saves now, even when nothing is pending, and starts the retries over. */
|
|
287
299
|
retry: () => void;
|
|
300
|
+
/** Saves a pending edit now and starts the retries over. A no-op when nothing is pending. */
|
|
301
|
+
flush: () => void;
|
|
288
302
|
};
|
|
289
303
|
/**
|
|
290
|
-
* Debounced last-write-wins autosave. Nothing fires on mount, only after the first
|
|
291
|
-
*
|
|
292
|
-
*
|
|
304
|
+
* Debounced last-write-wins autosave. Nothing fires on mount, only after the first real
|
|
305
|
+
* edit. One save runs at a time: edits made while it runs are saved once it settles, as one
|
|
306
|
+
* save of the newest payload. A failed save backs off exponentially until it lands, stops
|
|
307
|
+
* being retryable or runs out of retries. An edit still waiting for its debounce is saved
|
|
308
|
+
* on unmount and when the page is hidden. `save` and `build` are read at fire time, so
|
|
309
|
+
* passing fresh closures each render is safe.
|
|
293
310
|
*/
|
|
294
|
-
declare function useAutosave<T>({ deps, build, save, debounceMs, maxBackoffMs, }: UseAutosaveInput<T>): UseAutosaveResult;
|
|
311
|
+
declare function useAutosave<T>({ deps, build, save, debounceMs, maxBackoffMs, maxRetries, isRetryable, flushOnHide, }: UseAutosaveInput<T>): UseAutosaveResult;
|
|
295
312
|
|
|
296
313
|
/** Height follows the content, and is recomputed when the box gets narrower or
|
|
297
314
|
* wider, because a re-wrap changes the line count without changing the value.
|
|
298
315
|
* Only a width change refits: reacting to the height this hook just set would
|
|
299
316
|
* feed the observer its own output. */
|
|
300
|
-
declare function useAutoGrow<T extends HTMLTextAreaElement>(value: string): React.RefObject<T
|
|
317
|
+
declare function useAutoGrow<T extends HTMLTextAreaElement>(value: string): React.RefObject<T>;
|
|
301
318
|
|
|
302
319
|
/** A slash-palette entry: how it is shown and searched, and the markdown it inserts. */
|
|
303
320
|
type TextCommand = {
|
package/dist/index.d.ts
CHANGED
|
@@ -109,17 +109,17 @@ declare function paletteBlocks(definitions: AnyBlockDefinition[]): AnyBlockDefin
|
|
|
109
109
|
type BlockCanvasProps = {
|
|
110
110
|
/**
|
|
111
111
|
* The document. Update it synchronously from `onChange`, as with a controlled `<input value onChange>`.
|
|
112
|
-
* Applying the edit late is tolerated
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* behind the canvas's own state and reads as a foreign document. That does not revert the edit cleanly: the
|
|
116
|
-
* characters the copy predates are dropped and the ones typed after them are kept.
|
|
112
|
+
* Applying the edit late is tolerated: the canvas recognises an array it emitted however late it comes back, and
|
|
113
|
+
* a structural copy of one within 64 edits, so a transition, a debounced setter or a store that clones the
|
|
114
|
+
* document on the way through is safe.
|
|
117
115
|
* A new array that differs from the last one you supplied replaces what the canvas shows, which is how a host
|
|
118
116
|
* loads, undoes or merges. An array structurally equal to the last one you supplied is ignored, so a "discard
|
|
119
|
-
* changes" button that hands back the original document does nothing
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* block
|
|
117
|
+
* changes" button that hands back the original document does nothing. A host that does not echo `onChange` back
|
|
118
|
+
* meets the same when it restores a copy of a state from the last 64 edits, which reads as a late echo. Remount
|
|
119
|
+
* the canvas with a React `key` to force a reset in either case. The comparison is shallow over each block's
|
|
120
|
+
* `data`: a host whose block `data` holds nested objects rebuilt on every render, and which does not echo
|
|
121
|
+
* `onChange` back, can still lose an edit. The core block types all have flat data, so this only affects custom
|
|
122
|
+
* blocks.
|
|
123
123
|
*/
|
|
124
124
|
blocks: QuoinBlock[];
|
|
125
125
|
onChange: (blocks: QuoinBlock[]) => void;
|
|
@@ -209,8 +209,8 @@ type UploadFieldProps = {
|
|
|
209
209
|
label: string;
|
|
210
210
|
/** An `accept` attribute for the file input, such as `'image/*'` or `'.pdf'`. */
|
|
211
211
|
accept?: string;
|
|
212
|
-
/** Called once the upload resolves.
|
|
213
|
-
onUploaded: (result: UploadResult) => void
|
|
212
|
+
/** Called once the upload resolves. The field stays busy until a returned promise settles, and throwing or rejecting is reported through the canvas `onError`. */
|
|
213
|
+
onUploaded: (result: UploadResult) => void | Promise<void>;
|
|
214
214
|
};
|
|
215
215
|
/** A file picker wired to the canvas `upload` function, with its own busy state and inline error. */
|
|
216
216
|
declare function UploadField({ category, label, accept, onUploaded }: UploadFieldProps): React.JSX.Element;
|
|
@@ -267,7 +267,7 @@ type BlockList = {
|
|
|
267
267
|
declare function useBlockList(initial: QuoinBlock[]): BlockList;
|
|
268
268
|
|
|
269
269
|
/** Where a debounced save stands, for a "Saving..." or "Saved" indicator. */
|
|
270
|
-
type AutosaveStatus = 'idle' | 'saving' | 'saved' | 'retrying';
|
|
270
|
+
type AutosaveStatus = 'idle' | 'saving' | 'saved' | 'retrying' | 'failed';
|
|
271
271
|
/** What `useAutosave` tracks, how to build the payload, and how to persist it. */
|
|
272
272
|
type UseAutosaveInput<T> = {
|
|
273
273
|
/** The tracked fields. An edit to any of them marks dirty and restarts the debounce. */
|
|
@@ -280,24 +280,41 @@ type UseAutosaveInput<T> = {
|
|
|
280
280
|
save: (payload: T) => unknown;
|
|
281
281
|
debounceMs?: number;
|
|
282
282
|
maxBackoffMs?: number;
|
|
283
|
+
/** Retries after a failed save before giving up with status `failed`. Defaults to 8. */
|
|
284
|
+
maxRetries?: number;
|
|
285
|
+
/**
|
|
286
|
+
* Whether a failed save is worth retrying. Receives the rejection, or the resolved
|
|
287
|
+
* `{ ok: false }` value. Return false for a permanent failure. Defaults to always.
|
|
288
|
+
*/
|
|
289
|
+
isRetryable?: (error: unknown) => boolean;
|
|
290
|
+
/** Save a pending edit when the page is hidden or closed. Defaults to true. */
|
|
291
|
+
flushOnHide?: boolean;
|
|
283
292
|
};
|
|
284
|
-
/** The current save status
|
|
293
|
+
/** The current save status, the last failure, and ways to save immediately. */
|
|
285
294
|
type UseAutosaveResult = {
|
|
286
295
|
status: AutosaveStatus;
|
|
296
|
+
/** The last failure, kept while a retry is pending and cleared by the next success. */
|
|
297
|
+
error: unknown;
|
|
298
|
+
/** Saves now, even when nothing is pending, and starts the retries over. */
|
|
287
299
|
retry: () => void;
|
|
300
|
+
/** Saves a pending edit now and starts the retries over. A no-op when nothing is pending. */
|
|
301
|
+
flush: () => void;
|
|
288
302
|
};
|
|
289
303
|
/**
|
|
290
|
-
* Debounced last-write-wins autosave. Nothing fires on mount, only after the first
|
|
291
|
-
*
|
|
292
|
-
*
|
|
304
|
+
* Debounced last-write-wins autosave. Nothing fires on mount, only after the first real
|
|
305
|
+
* edit. One save runs at a time: edits made while it runs are saved once it settles, as one
|
|
306
|
+
* save of the newest payload. A failed save backs off exponentially until it lands, stops
|
|
307
|
+
* being retryable or runs out of retries. An edit still waiting for its debounce is saved
|
|
308
|
+
* on unmount and when the page is hidden. `save` and `build` are read at fire time, so
|
|
309
|
+
* passing fresh closures each render is safe.
|
|
293
310
|
*/
|
|
294
|
-
declare function useAutosave<T>({ deps, build, save, debounceMs, maxBackoffMs, }: UseAutosaveInput<T>): UseAutosaveResult;
|
|
311
|
+
declare function useAutosave<T>({ deps, build, save, debounceMs, maxBackoffMs, maxRetries, isRetryable, flushOnHide, }: UseAutosaveInput<T>): UseAutosaveResult;
|
|
295
312
|
|
|
296
313
|
/** Height follows the content, and is recomputed when the box gets narrower or
|
|
297
314
|
* wider, because a re-wrap changes the line count without changing the value.
|
|
298
315
|
* Only a width change refits: reacting to the height this hook just set would
|
|
299
316
|
* feed the observer its own output. */
|
|
300
|
-
declare function useAutoGrow<T extends HTMLTextAreaElement>(value: string): React.RefObject<T
|
|
317
|
+
declare function useAutoGrow<T extends HTMLTextAreaElement>(value: string): React.RefObject<T>;
|
|
301
318
|
|
|
302
319
|
/** A slash-palette entry: how it is shown and searched, and the markdown it inserts. */
|
|
303
320
|
type TextCommand = {
|