@threadlabs/looma 0.2.19 → 0.3.0

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.
Files changed (51) hide show
  1. package/dist/{chunk-A5MSXQ7Y.js → chunk-3NVMCHGR.js} +2225 -1255
  2. package/dist/chunk-XDNZIKNI.js +2721 -0
  3. package/dist/declarative-generated.cjs +93 -79
  4. package/dist/declarative-generated.d.cts +7 -1
  5. package/dist/declarative-generated.d.ts +7 -1
  6. package/dist/declarative-generated.js +91 -78
  7. package/dist/declarative.cjs +1499 -1702
  8. package/dist/declarative.d.cts +77 -3
  9. package/dist/declarative.d.ts +77 -3
  10. package/dist/declarative.js +5 -3
  11. package/dist/index.cjs +3732 -3025
  12. package/dist/index.d.cts +211 -35
  13. package/dist/index.d.ts +211 -35
  14. package/dist/index.js +6 -61
  15. package/dist/loader.cjs +3725 -2962
  16. package/dist/loader.js +2 -2
  17. package/editor/{chunk-WI7ZA44X.js → chunk-U36XNFJN.js} +111 -77
  18. package/editor/extensions/index.d.ts +272 -27
  19. package/editor/index.d.ts +1 -1
  20. package/editor/index.js +1 -1
  21. package/editor/{table-overlay-DoiLie4h.d.ts → table-overlay-DZFGHQDt.d.ts} +48 -6
  22. package/editor/ui.d.ts +15 -11
  23. package/editor/ui.js +1 -1
  24. package/layout/index.cjs +197 -340
  25. package/layout/index.d.cts +11 -0
  26. package/layout/index.d.ts +11 -0
  27. package/layout/index.js +197 -340
  28. package/layout.css +31 -134
  29. package/package.json +24 -11
  30. package/react/index.d.ts +1276 -0
  31. package/react/index.js +1526 -0
  32. package/styles.css +5 -10
  33. package/svelte/index.d.ts +204 -0
  34. package/svelte/index.js +1881 -0
  35. package/theme-dark.css +81 -2
  36. package/theme-high-contrast.css +14 -0
  37. package/theme-light.css +30 -1
  38. package/tokens.css +45 -1
  39. package/vue/chunk-UZMTYDP6.js +4355 -0
  40. package/vue/editor/index.d.ts +78 -8
  41. package/vue/editor/index.js +59 -49
  42. package/vue/index.d.ts +67 -78
  43. package/vue/index.js +3 -9
  44. package/dist/chunk-ECJQ4YGC.js +0 -2925
  45. package/dist/valibot.cjs +0 -31
  46. package/dist/valibot.d.cts +0 -10
  47. package/dist/valibot.d.ts +0 -10
  48. package/dist/valibot.js +0 -9
  49. package/dist/validation-bxcou-l-.d.cts +0 -58
  50. package/dist/validation-bxcou-l-.d.ts +0 -58
  51. package/vue/chunk-P7BZ2KJZ.js +0 -3559
@@ -1,10 +1,12 @@
1
1
  import { Node, AnyExtension, Extension, Editor, Range } from '@tiptap/core';
2
- import { d as TableContextMenuActionEventDetail, g as TableOverlayActionEventDetail } from '../table-overlay-DoiLie4h.js';
3
- export { a as TABLE_CELL_BACKGROUND_PRESETS } from '../table-overlay-DoiLie4h.js';
2
+ import { d as TableContextMenuActionEventDetail, g as TableOverlayActionEventDetail } from '../table-overlay-DZFGHQDt.js';
3
+ export { a as TABLE_CELL_BACKGROUND_PRESETS } from '../table-overlay-DZFGHQDt.js';
4
4
  import { PluginKey } from '@tiptap/pm/state';
5
5
  import { LoomaIconName } from '@threadlabs/looma/core';
6
6
 
7
+ /** Canonical tone values that may be persisted in a Looma callout node. */
7
8
  declare const LOOMA_CALLOUT_TONES: readonly ["info", "note", "warning"];
9
+ /** A serialized callout tone; unsupported input is normalized to `note`. */
8
10
  type LoomaCalloutTone = (typeof LOOMA_CALLOUT_TONES)[number];
9
11
  declare module "@tiptap/core" {
10
12
  interface Commands<ReturnType> {
@@ -14,7 +16,12 @@ declare module "@tiptap/core" {
14
16
  };
15
17
  }
16
18
  }
17
- /** A durable, themeable block container for informational editor content. */
19
+ /**
20
+ * A durable, themeable block container for informational editor content.
21
+ *
22
+ * @invariant Parsed and rendered `data-tone` values always belong to
23
+ * `LOOMA_CALLOUT_TONES`; missing or unknown values round-trip as `note`.
24
+ */
18
25
  declare const LoomaCallout: Node<any, any>;
19
26
 
20
27
  /**
@@ -22,19 +29,41 @@ declare const LoomaCallout: Node<any, any>;
22
29
  * Uses the Vanilla JS Tiptap API; apps provide @tiptap/core and Looma ships the preset extensions.
23
30
  */
24
31
 
32
+ /**
33
+ * Deliberate policy knobs in Looma's default extension set.
34
+ * Consumers needing different schemas should compose an explicit Tiptap list
35
+ * rather than relying on undocumented mutation of the returned extensions.
36
+ */
25
37
  interface DefaultEditorExtensionsOptions {
38
+ /** Placeholder shown only for empty paragraphs, not every empty node type. */
26
39
  placeholder?: string;
40
+ /** Passed to Tiptap Link; defaults false to keep editing clicks in the editor. */
27
41
  linkOpenOnClick?: boolean;
42
+ /** Passed to Tiptap Image; block images are the default document policy. */
28
43
  imageInline?: boolean;
44
+ /** Custom mention extension, the Looma default, or false to omit mentions. */
29
45
  mention?: AnyExtension | false;
30
46
  }
31
- /** Complete Looma table support as one Tiptap extension. */
47
+ /**
48
+ * Complete Looma table schema as one Tiptap extension.
49
+ * Use this in presets that want table, row, header, and cell nodes to remain an
50
+ * atomic policy choice; use `getLoomaTableExtensions` only when ordering or
51
+ * per-extension composition must be explicit.
52
+ *
53
+ * @invariant Installs exactly one compatible table, row, header, and cell node
54
+ * set so a preset cannot accidentally split Looma's persisted table schema.
55
+ */
32
56
  declare const LoomaTableKit: AnyExtension;
33
- /** Individual table extensions for consumers that prefer an explicit extension list. */
57
+ /** Returns a fresh ordered list of the same schema extensions as `LoomaTableKit`. */
34
58
  declare function getLoomaTableExtensions(): AnyExtension[];
35
59
  /**
36
- * Returns the default Looma editor extensions (Vanilla Tiptap).
37
- * Use with new Editor({ extensions: getDefaultEditorExtensions(), ... }) or framework useEditor().
60
+ * Builds Looma's complete, ordered Tiptap extension policy.
61
+ *
62
+ * A fresh array is returned for each editor. Document nodes precede marks and
63
+ * behavior extensions; Looma's table/list policies are installed once; mention
64
+ * can be replaced without coupling UI chrome to an application directory.
65
+ * Use with `new Editor({ extensions: getDefaultEditorExtensions(), ... })` or a
66
+ * framework's Tiptap editor hook.
38
67
  */
39
68
  declare function getDefaultEditorExtensions(options?: DefaultEditorExtensionsOptions): AnyExtension[];
40
69
 
@@ -44,29 +73,92 @@ declare function getDefaultEditorExtensions(options?: DefaultEditorExtensionsOpt
44
73
  *
45
74
  * Source-editor metadata remains authoritative for non-document languages.
46
75
  * Explicit code-block context is never reinterpreted.
76
+ *
77
+ * @contract Recognized document markup is sanitized and dispatched as one paste
78
+ * transaction; every unrecognized or code-oriented payload returns control to
79
+ * Tiptap's remaining paste handlers without changing the document.
47
80
  */
48
81
  declare const LoomaSmartPaste: Extension<any, any>;
49
82
 
83
+ /** Persistable horizontal alignments accepted by Looma table cells. */
50
84
  type TableCellAlignment = "left" | "center" | "right";
85
+ /** CSS color stored in document attrs; null removes authored cell background. */
51
86
  type TableCellBackground = string | null;
87
+ /**
88
+ * Looma's table behavior policy: resizable columns, stable minimum cell width,
89
+ * and no independently resizable trailing column. The narrow handle is also a
90
+ * Tiptap coordinate probe, so changing it affects selection as well as visuals.
91
+ *
92
+ * @invariant The 3px handle, 112px cell minimum, and fixed trailing edge are a
93
+ * coordinated selection-and-resize policy and must be changed together.
94
+ */
52
95
  declare const LoomaTable: AnyExtension;
96
+ /**
97
+ * Header node that round-trips Looma alignment and background attributes.
98
+ *
99
+ * @contract Inherits the base header schema while normalizing authored styles
100
+ * into the same persisted attributes used by body cells.
101
+ */
53
102
  declare const LoomaTableHeader: AnyExtension;
103
+ /**
104
+ * Body-cell node with the same persisted formatting contract as headers.
105
+ *
106
+ * @contract Inherits the base cell schema and shares header parsing/rendering so
107
+ * moving content between header and body cells does not change formatting data.
108
+ */
54
109
  declare const LoomaTableCell: AnyExtension;
110
+ /**
111
+ * Reads formatting from the nearest cell/header ancestor of the selection.
112
+ * Left is the canonical default and is not serialized as an inline style.
113
+ *
114
+ * @contract Returns `left` outside a table cell and for missing, invalid, or
115
+ * explicitly default alignment attributes.
116
+ */
55
117
  declare function getActiveTableCellAlignment(editor: Editor): TableCellAlignment;
118
+ /**
119
+ * Returns the nearest cell/header background, normalized so blank means absent.
120
+ *
121
+ * @contract Returns null outside a table cell and for non-string or whitespace-
122
+ * only attributes, matching the value used to clear persisted background CSS.
123
+ */
56
124
  declare function getActiveTableCellBackground(editor: Editor): TableCellBackground;
125
+ /**
126
+ * Updates the active header or body cell and returns false outside a table cell.
127
+ * Setting left stores null, keeping the document free of redundant default CSS.
128
+ *
129
+ * @contract Focuses and updates only the active header or body cell; unsupported
130
+ * selections return false without creating a transaction.
131
+ */
57
132
  declare function setActiveTableCellAlignment(editor: Editor, alignment: TableCellAlignment): boolean;
133
+ /**
134
+ * Updates the active header or body cell; blank strings normalize to null so
135
+ * clearing formatting removes persisted inline style instead of storing noise.
136
+ *
137
+ * @contract Focuses and updates only the active header or body cell; unsupported
138
+ * selections return false and blank values remove the persisted attribute.
139
+ */
58
140
  declare function setActiveTableCellBackground(editor: Editor, backgroundColor: TableCellBackground): boolean;
59
141
 
60
142
  /**
61
143
  * Table overlay action handler — maps boundaryIndex to Tiptap table commands.
62
- * Use with looma-editor-table-overlay-action: call this from the adapter's handler.
144
+ * Use with the table overlay's `action` event: call this from the adapter's handler.
63
145
  */
64
146
 
147
+ /**
148
+ * Bounded initial shape for table insertion.
149
+ * Rows and columns are clamped to 1–10 by `insertTableAtRange` so slash-command
150
+ * or custom UI input cannot create an accidentally unbounded transaction.
151
+ */
65
152
  interface InsertTableAtRangeOptions {
66
153
  rows?: number;
67
154
  cols?: number;
68
155
  withHeaderRow?: boolean;
69
156
  }
157
+ /**
158
+ * Command availability calculated from the current ProseMirror selection.
159
+ * Keeping capabilities beside UI state prevents toolbars from duplicating
160
+ * Tiptap's schema/selection rules or optimistically enabling invalid actions.
161
+ */
70
162
  interface TableActionCapabilities {
71
163
  canAddRowBefore: boolean;
72
164
  canAddRowAfter: boolean;
@@ -78,6 +170,12 @@ interface TableActionCapabilities {
78
170
  canMergeCells: boolean;
79
171
  canSplitCell: boolean;
80
172
  }
173
+ /**
174
+ * One replaceable snapshot for editor-owned table chrome.
175
+ * Consumers should discard prior capabilities whenever `active` becomes false;
176
+ * they describe the current ProseMirror transaction state, not table schema in
177
+ * general.
178
+ */
81
179
  interface ActiveTableUiState {
82
180
  active: boolean;
83
181
  showToolbar: boolean;
@@ -85,50 +183,114 @@ interface ActiveTableUiState {
85
183
  cellBackground: TableCellBackground;
86
184
  capabilities: TableActionCapabilities;
87
185
  }
88
- /** Text formatting belongs to actual text selections, not table CellSelections. */
186
+ /**
187
+ * Text formatting belongs to actual text selections, not table CellSelections.
188
+ *
189
+ * @contract Returns true only for an editable editor with a non-collapsed
190
+ * `TextSelection`; node and cell selections never activate formatting chrome.
191
+ */
89
192
  declare function shouldShowTextFormattingToolbar(editor: Editor, from?: number, to?: number): boolean;
90
- /** Returns Looma's complete interaction state for the table containing the selection. */
193
+ /**
194
+ * Returns the complete interaction state for the table containing the selection.
195
+ * Inactive defaults are concrete so UI can replace its previous snapshot and
196
+ * cannot accidentally retain enabled controls from a table that lost selection.
197
+ *
198
+ * @contract Capabilities are recalculated from `editor.can()` at call time; an
199
+ * inactive snapshot disables every action and resets authored cell formatting.
200
+ */
91
201
  declare function getActiveTableUiState(editor: Editor): ActiveTableUiState;
92
- /** Executes a toolbar/context-menu action using Looma's table behavior policy. */
202
+ /**
203
+ * Executes a toolbar/context-menu action using Looma's table behavior policy.
204
+ * The boolean is Tiptap's command result, so callers can distinguish a handled
205
+ * action from one rejected by the current schema or selection.
206
+ *
207
+ * @contract The event action becomes one focused Tiptap transaction; UI callers
208
+ * never need to reproduce selection repair or cell-format policy.
209
+ * @failure Returns false when the current selection cannot support the action.
210
+ */
93
211
  declare function handleTableAction(editor: Editor, detail: TableContextMenuActionEventDetail): boolean;
94
212
  /**
95
213
  * Deletes a slash-command range (or other inline trigger text) and inserts a table.
96
- * Use this when apps want a stable default `/table` behavior without owning table policy.
214
+ * Use this when apps want a stable default `/table` behavior without owning
215
+ * table policy. Deletion and insertion share one focused command chain, so the
216
+ * trigger text cannot remain behind if insertion succeeds.
217
+ *
218
+ * @contract Rows and columns are clamped to 1–10, then range deletion and table
219
+ * insertion succeed or fail together through a single Tiptap command chain.
97
220
  */
98
221
  declare function insertTableAtRange(editor: Editor, range: Range, options?: InsertTableAtRangeOptions): boolean;
99
222
  /**
100
- * Reconciles rendered column widths back into table-cell colwidth attrs so a resized
101
- * full-width table stays inside the editor width after resize completes.
223
+ * Reconciles rendered column widths back into table-cell `colwidth` attributes.
224
+ *
225
+ * Browser layout is the source of truth at the end of a pointer resize, but
226
+ * ProseMirror must persist integer widths in the document. The algorithm keeps
227
+ * proportions, enforces a minimum, and distributes rounding error so the final
228
+ * sum still equals the rendered table width. Spanning cells are updated once at
229
+ * their top-left map coordinate rather than once per covered grid position.
230
+ *
231
+ * @invariant Every persisted width is an integer at least `minWidth`, and each
232
+ * spanning cell receives one width per logical column from its top-left origin.
233
+ * @failure Returns false without an active table or measurable columns and does
234
+ * not dispatch when persisted widths already match the rendered geometry.
102
235
  */
103
236
  declare function normalizeActiveTableColumnWidths(editor: Editor, tableElement: HTMLTableElement, minWidth?: number): boolean;
104
237
  /**
105
- * Handles a table overlay action by selecting the target cell and running the Tiptap command.
106
- * Call this from your adapter's onTableOverlayAction handler.
238
+ * Handles a geometry-derived table-overlay intent without exposing ProseMirror
239
+ * positions to UI components.
240
+ *
241
+ * Boundary indices address the visual grid edges measured by the overlay. The
242
+ * helper maps them into the current table transaction, rejects indices that do
243
+ * not represent a legal insertion edge, dispatches once, and restores editor
244
+ * focus. `open-cell-menu` returns handled without editing because menu ownership
245
+ * remains with the application/adapter.
107
246
  *
108
- * @example
109
- * ```vue
110
- * <EditorTableOverlay
111
- * :open="tableOverlayOpen"
112
- * :rows="tableRows"
113
- * :cols="tableCols"
114
- * @looma-editor-table-overlay-action="(e) => handleTableOverlayAction(editor, e.detail)"
115
- * />
116
- * ```
247
+ * @contract A valid structural intent dispatches at most one transaction;
248
+ * `open-cell-menu` acknowledges UI ownership without mutating the document.
249
+ * @failure Missing tables, malformed payloads, and out-of-range boundaries
250
+ * return false before dispatching a transaction.
117
251
  */
118
252
  declare function handleTableOverlayAction(editor: Editor, detail: TableOverlayActionEventDetail): boolean;
119
253
 
254
+ /** Default visible candidate budget when an application does not set a limit. */
120
255
  declare const DEFAULT_MENTION_RESULT_LIMIT = 8;
256
+ /** Hard candidate ceiling shared by providers, keyboard state, and menu rendering. */
121
257
  declare const MAX_MENTION_RESULT_LIMIT = 20;
258
+ /**
259
+ * Application-owned identity and display data for one mention candidate.
260
+ * Looma persists `id` and `label` in the editor document; `detail` and
261
+ * `initials` are presentation hints and are not part of mention identity.
262
+ */
122
263
  interface LoomaMentionItem {
123
264
  id: string;
124
265
  label: string;
125
266
  detail?: string;
126
267
  initials?: string;
127
268
  }
269
+ /** Bounded result budget passed to a directory provider for the current query. */
128
270
  interface LoomaMentionProviderContext {
129
271
  limit: number;
130
272
  }
273
+ /**
274
+ * Resolves candidates for the current query.
275
+ *
276
+ * Providers may perform asynchronous directory lookup, but should return no
277
+ * more than `context.limit`. The extension also clamps and filters results so a
278
+ * provider cannot accidentally create an unbounded suggestion surface.
279
+ *
280
+ * @ownership The application owns directory access and returned item data;
281
+ * Looma owns filtering, clamping, and the suggestion state that consumes it.
282
+ */
131
283
  type LoomaMentionProvider = (query: string, context: LoomaMentionProviderContext) => readonly LoomaMentionItem[] | Promise<readonly LoomaMentionItem[]>;
284
+ /**
285
+ * Complete render state handed from the headless Tiptap extension to UI chrome.
286
+ *
287
+ * The snapshot owns selection commands only while `active` is true. Consumers
288
+ * should replace, not merge, snapshots: callbacks and rectangles are tied to a
289
+ * particular suggestion range and become stale as soon as the query changes.
290
+ *
291
+ * @lifecycle `highlight` and `select` are valid only while this snapshot remains
292
+ * active; the next query update or exit invalidates both callbacks.
293
+ */
132
294
  interface LoomaMentionMenuSnapshot {
133
295
  active: boolean;
134
296
  items: LoomaMentionItem[];
@@ -139,13 +301,33 @@ interface LoomaMentionMenuSnapshot {
139
301
  highlight: ((index: number) => void) | null;
140
302
  select: ((index: number) => void) | null;
141
303
  }
304
+ /**
305
+ * Mention policy supplied by the application.
306
+ *
307
+ * Looma owns suggestion mechanics and accessibility state; the application
308
+ * owns the directory and may render the snapshot with Looma's menu or custom
309
+ * UI. `menuId` must match that UI's listbox id so `aria-controls` and
310
+ * `aria-activedescendant` reference real elements.
311
+ *
312
+ * @ownership The application owns provider work and rendering callbacks; Looma
313
+ * owns transient selection state and restores every borrowed editor ARIA value.
314
+ */
142
315
  interface LoomaMentionOptions {
143
316
  items?: readonly LoomaMentionItem[] | LoomaMentionProvider;
144
317
  limit?: number;
145
318
  menuId?: string;
146
319
  onStateChange?: (state: LoomaMentionMenuSnapshot) => void;
147
320
  }
321
+ /** Clamps public/provider limits so keyboard navigation remains predictably bounded. */
148
322
  declare function normalizeMentionResultLimit(limit?: number): number;
323
+ /**
324
+ * Applies Looma's local fallback matching to static or provider results.
325
+ * Matching is intentionally limited to display text; stable ids and arbitrary
326
+ * metadata must not become discoverable search fields by accident.
327
+ *
328
+ * @contract Preserves source order, does not mutate the input, and returns no
329
+ * more than the normalized public result limit.
330
+ */
149
331
  declare function filterLoomaMentionItems(items: readonly LoomaMentionItem[], query: string, limit?: number): LoomaMentionItem[];
150
332
 
151
333
  interface MentionPluginState {
@@ -156,17 +338,43 @@ interface MentionPluginState {
156
338
  to: number;
157
339
  };
158
340
  }
341
+ /**
342
+ * Stable key for reading Looma's active mention query and source range.
343
+ * Consumers should treat the keyed value as transient suggestion state rather
344
+ * than document data.
345
+ */
159
346
  declare const LoomaMentionSuggestionPluginKey: PluginKey<MentionPluginState>;
160
347
  /**
161
- * Domain-neutral Tiptap mention node and suggestion lifecycle. Applications
162
- * provide either a small static list or a bounded async directory provider.
348
+ * Creates a domain-neutral Tiptap mention node and suggestion lifecycle.
349
+ *
350
+ * Applications provide either a small static list or a bounded async directory
351
+ * provider. Looma owns keyboard selection plus the temporary combobox ARIA
352
+ * attributes on the editor. Every attribute is snapshotted and restored so
353
+ * installing this extension cannot erase accessibility state owned by another
354
+ * extension or by the host application.
355
+ *
356
+ * @ownership The application owns the item provider and rendered menu. The
357
+ * extension owns suggestion state and only borrows editor ARIA attributes.
358
+ * @lifecycle Each suggestion update replaces the published snapshot; exit
359
+ * restores borrowed attributes and invalidates callbacks from the prior range.
360
+ * @failure Provider rejection degrades to an empty result set so Tiptap's
361
+ * suggestion lifecycle cannot become an unhandled promise rejection.
163
362
  */
164
363
  declare function createLoomaMentionExtension(options?: LoomaMentionOptions): AnyExtension;
165
364
 
365
+ /** Editor state a slash command may replace and then act upon. */
166
366
  interface LoomaSlashCommandContext {
167
367
  editor: Editor;
168
368
  range: Range;
169
369
  }
370
+ /**
371
+ * Ephemeral render model published to any slash-menu UI.
372
+ * Replace snapshots rather than merging them: the `select` callback closes over
373
+ * a particular Tiptap range and becomes invalid when the suggestion updates.
374
+ *
375
+ * @lifecycle `select` is valid only until the next snapshot or suggestion exit;
376
+ * retaining it can apply a command to a stale source range.
377
+ */
170
378
  interface LoomaSlashMenuSnapshot {
171
379
  active: boolean;
172
380
  items: LoomaSlashCommand[];
@@ -175,12 +383,36 @@ interface LoomaSlashMenuSnapshot {
175
383
  rect: DOMRect | null;
176
384
  select: ((index: number) => void) | null;
177
385
  }
386
+ /**
387
+ * Application-owned command inventory and integration callbacks.
388
+ * Replacing `commands` changes search and execution together; the extension
389
+ * never merges domain commands into defaults implicitly. Asset selection stays
390
+ * callback-driven because uploads and persistence are outside editor ownership.
391
+ *
392
+ * @ownership The application owns command objects and callback side effects;
393
+ * the extension only searches the inventory and publishes replacement snapshots.
394
+ */
178
395
  interface LoomaSlashCommandOptions {
179
396
  commands: LoomaSlashCommand[];
180
397
  onStateChange?: (state: LoomaSlashMenuSnapshot) => void;
181
398
  onOpenImagePicker?: () => void;
182
399
  }
400
+ /**
401
+ * Builds Looma's default command policy as fresh objects for one editor.
402
+ * The image command delegates asset selection because Looma does not own upload,
403
+ * persistence, or media-library concerns.
404
+ *
405
+ * @ownership Returned command objects belong to the caller and are recreated
406
+ * per call so one editor cannot mutate another editor's command inventory.
407
+ */
183
408
  declare function getDefaultSlashCommands(onOpenImagePicker?: () => void): LoomaSlashCommand[];
409
+ /**
410
+ * One application-extensible command.
411
+ *
412
+ * Commands own their editor mutation, including removal of `context.range`.
413
+ * Keeping that policy in the command lets custom items behave exactly like
414
+ * built-ins without coupling the headless suggestion lifecycle to Tiptap nodes.
415
+ */
184
416
  interface LoomaSlashCommand {
185
417
  title: string;
186
418
  description: string;
@@ -192,8 +424,21 @@ interface LoomaSlashCommand {
192
424
  * Framework-neutral slash-command extension used by the turnkey editor.
193
425
  * Consumers embedding Looma into their own Tiptap instance can configure the
194
426
  * same behavior and render any menu they choose from `onStateChange`.
427
+ *
428
+ * @ownership The extension owns query and keyboard-selection state; the caller
429
+ * owns the command inventory and every menu snapshot after publication.
430
+ * @lifecycle Snapshot callbacks are valid only for the suggestion range that
431
+ * produced them and are replaced on every update or exit.
195
432
  */
196
433
  declare const LoomaSlashCommand: Extension<LoomaSlashCommandOptions, any>;
434
+ /**
435
+ * Creates an independently configured extension instance.
436
+ * Prefer this factory when callbacks or commands are editor-specific; the
437
+ * exported base extension remains a convenient zero-configuration preset.
438
+ *
439
+ * @ownership The caller owns supplied commands and callbacks. The returned
440
+ * extension captures them for one configuration without mutating the inventory.
441
+ */
197
442
  declare function createLoomaSlashCommandExtension(options?: Partial<LoomaSlashCommandOptions>): Extension<LoomaSlashCommandOptions, any>;
198
443
 
199
444
  export { type ActiveTableUiState, DEFAULT_MENTION_RESULT_LIMIT, type DefaultEditorExtensionsOptions, type InsertTableAtRangeOptions, LOOMA_CALLOUT_TONES, LoomaCallout, type LoomaCalloutTone, type LoomaMentionItem, type LoomaMentionMenuSnapshot, type LoomaMentionOptions, type LoomaMentionProvider, type LoomaMentionProviderContext, LoomaMentionSuggestionPluginKey, LoomaSlashCommand, type LoomaSlashCommandContext, LoomaSlashCommand as LoomaSlashCommandItem, type LoomaSlashCommandOptions, type LoomaSlashMenuSnapshot, LoomaSmartPaste, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, MAX_MENTION_RESULT_LIMIT, type TableActionCapabilities, type TableCellAlignment, type TableCellBackground, createLoomaMentionExtension, createLoomaSlashCommandExtension, filterLoomaMentionItems, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, handleTableAction, handleTableOverlayAction, insertTableAtRange, normalizeActiveTableColumnWidths, normalizeMentionResultLimit, setActiveTableCellAlignment, setActiveTableCellBackground, shouldShowTextFormattingToolbar };
package/editor/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as ActiveCellRect, T as TABLE_CELL_BACKGROUND_OPTIONS, a as TABLE_CELL_BACKGROUND_PRESETS, b as TableCellBackgroundAction, c as TableContextMenuAction, d as TableContextMenuActionEventDetail, e as TableInsertionAction, f as TableOverlayAction, g as TableOverlayActionEventDetail, h as TableOverlayGeometry, d as TableToolbarActionEventDetail, m as measureTableOverlayGeometry, r as resolveTableCellAt } from './table-overlay-DoiLie4h.js';
1
+ export { A as ActiveCellRect, T as TABLE_CELL_BACKGROUND_OPTIONS, a as TABLE_CELL_BACKGROUND_PRESETS, b as TableCellBackgroundAction, c as TableContextMenuAction, d as TableContextMenuActionEventDetail, e as TableInsertionAction, f as TableOverlayAction, g as TableOverlayActionEventDetail, h as TableOverlayGeometry, d as TableToolbarActionEventDetail, m as measureTableOverlayGeometry, r as resolveTableCellAt } from './table-overlay-DZFGHQDt.js';
2
2
  export { InsertTableEventDetail, MentionMenuHighlightEventDetail, MentionMenuSelectEventDetail, SlashMenuAnchorRect, SlashMenuHighlightEventDetail, SlashMenuItem, SlashMenuSelectEventDetail } from './ui.js';
3
3
  export { ActiveTableUiState, DEFAULT_MENTION_RESULT_LIMIT, DefaultEditorExtensionsOptions, InsertTableAtRangeOptions, LOOMA_CALLOUT_TONES, LoomaCallout, LoomaCalloutTone, LoomaMentionItem, LoomaMentionMenuSnapshot, LoomaMentionOptions, LoomaMentionProvider, LoomaMentionProviderContext, LoomaMentionSuggestionPluginKey, LoomaSlashCommand, LoomaSlashCommandContext, LoomaSlashCommand as LoomaSlashCommandItem, LoomaSlashCommandOptions, LoomaSlashMenuSnapshot, LoomaSmartPaste, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, MAX_MENTION_RESULT_LIMIT, TableActionCapabilities, TableCellAlignment, TableCellBackground, createLoomaMentionExtension, createLoomaSlashCommandExtension, filterLoomaMentionItems, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, handleTableAction, handleTableOverlayAction, insertTableAtRange, normalizeActiveTableColumnWidths, normalizeMentionResultLimit, setActiveTableCellAlignment, setActiveTableCellBackground, shouldShowTextFormattingToolbar } from './extensions/index.js';
4
4
  import '@threadlabs/looma/core';
package/editor/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  measureTableOverlayGeometry,
3
3
  resolveTableCellAt
4
- } from "./chunk-WI7ZA44X.js";
4
+ } from "./chunk-U36XNFJN.js";
5
5
  import {
6
6
  DEFAULT_MENTION_RESULT_LIMIT,
7
7
  LOOMA_CALLOUT_TONES,
@@ -1,3 +1,4 @@
1
+ /** Canonical persisted colors shared by editor commands and table UI swatches. */
1
2
  declare const TABLE_CELL_BACKGROUND_PRESETS: {
2
3
  readonly none: null;
3
4
  readonly gray: "#f3f4f6";
@@ -6,6 +7,7 @@ declare const TABLE_CELL_BACKGROUND_PRESETS: {
6
7
  readonly green: "#dcfce7";
7
8
  readonly red: "#fee2e2";
8
9
  };
10
+ /** Ordered menu choices coupling each UI intent to its persisted color value. */
9
11
  declare const TABLE_CELL_BACKGROUND_OPTIONS: readonly [{
10
12
  readonly action: "background-none";
11
13
  readonly label: "Default";
@@ -37,15 +39,18 @@ declare const TABLE_CELL_BACKGROUND_OPTIONS: readonly [{
37
39
  readonly value: "#fee2e2";
38
40
  readonly swatch: "#fee2e2";
39
41
  }];
42
+ /** Background-only action vocabulary derived from the canonical menu choices. */
40
43
  type TableCellBackgroundAction = typeof TABLE_CELL_BACKGROUND_OPTIONS[number]["action"];
41
44
 
45
+ /** Intent contracts shared by declarative table menus and editor adapters. */
46
+
42
47
  /**
43
- * ui-editor-table-context-menu — web component for table cell context menu.
44
- * Emits custom events for each action; the adapter (Vue/React) wires Tiptap commands.
45
- * Domain-neutral: no Tiptap dependency.
48
+ * Complete intent vocabulary emitted by table chrome for an adapter to execute.
49
+ * Keeping this as data prevents the reusable menu from importing or mutating a
50
+ * particular editor implementation.
46
51
  */
47
-
48
52
  type TableContextMenuAction = "align-left" | "align-center" | "align-right" | TableCellBackgroundAction | "add-row-before" | "add-row-after" | "add-column-before" | "add-column-after" | "delete-row" | "delete-column" | "delete-table" | "clear-cells" | "merge-cells" | "split-cell";
53
+ /** Adapter-facing payload that keeps the menu independent of editor commands. */
49
54
  interface TableContextMenuActionEventDetail {
50
55
  action: TableContextMenuAction;
51
56
  }
@@ -54,8 +59,20 @@ interface TableContextMenuActionEventDetail {
54
59
  * ui-editor-table-overlay — anticipatory table affordances.
55
60
  * Domain-neutral: it emits intent while the adapter owns editor commands.
56
61
  */
62
+ /** Table-structure mutations addressed by a measured row/column boundary. */
57
63
  type TableInsertionAction = "add-row-before" | "add-row-after" | "add-column-before" | "add-column-after";
64
+ /**
65
+ * Intent vocabulary emitted by the headless table overlay.
66
+ * UI stays independent of Tiptap/ProseMirror positions; adapters translate
67
+ * these logical coordinates with `handleTableOverlayAction`.
68
+ */
58
69
  type TableOverlayAction = TableInsertionAction | "select-row" | "select-column" | "open-cell-menu";
70
+ /**
71
+ * Discriminated action payload.
72
+ * Boundary indices refer to entries in the measured boundary arrays. Cell
73
+ * indices refer to the logical grid after row/column spans are expanded. The
74
+ * menu anchor uses CSS-pixel viewport coordinates suitable for fixed surfaces.
75
+ */
59
76
  type TableOverlayActionEventDetail = {
60
77
  action: TableInsertionAction;
61
78
  boundaryIndex: number;
@@ -74,6 +91,11 @@ type TableOverlayActionEventDetail = {
74
91
  bottom: number;
75
92
  };
76
93
  };
94
+ /**
95
+ * A cell rectangle relative to the table's border box, plus logical grid
96
+ * coordinates. Width/height include spans because they come from the rendered
97
+ * cell rather than an inferred uniform grid.
98
+ */
77
99
  interface ActiveCellRect {
78
100
  left: number;
79
101
  top: number;
@@ -82,15 +104,35 @@ interface ActiveCellRect {
82
104
  rowIndex: number;
83
105
  columnIndex: number;
84
106
  }
107
+ /**
108
+ * Replaceable geometry snapshot for overlay rendering.
109
+ * Boundaries are CSS-pixel offsets relative to the table; callers should
110
+ * remeasure after editor transactions or layout changes rather than mutate the
111
+ * arrays in place.
112
+ */
85
113
  interface TableOverlayGeometry {
86
114
  rowBoundaries: number[];
87
115
  columnBoundaries: number[];
88
116
  activeCell: ActiveCellRect | null;
89
117
  hoveredCell?: ActiveCellRect | null;
90
118
  }
91
- /** Resolves a logical table coordinate, including cells that span rows or columns. */
119
+ /**
120
+ * Resolves a logical grid coordinate to its owning DOM cell.
121
+ * A spanning cell can therefore be returned for more than one coordinate; this
122
+ * is intentional and prevents overlay actions from inventing nonexistent cells.
123
+ *
124
+ * @contract Coordinates outside the expanded table grid return null; coordinates
125
+ * covered by a span resolve to the single DOM cell that owns them.
126
+ */
92
127
  declare function resolveTableCellAt(table: HTMLTableElement, rowIndex: number, columnIndex: number): HTMLTableCellElement | null;
93
- /** Measures real rendered boundaries, including non-uniform and merged cells. */
128
+ /**
129
+ * Measures rendered boundaries rather than assuming a uniform table grid.
130
+ * Returned offsets are table-relative and rounded to hundredths of a CSS pixel
131
+ * to suppress observer churn without losing subpixel layout fidelity.
132
+ *
133
+ * @contract Active and hovered rectangles are returned only for cells contained
134
+ * by the supplied table; detached or foreign cells are represented as null.
135
+ */
94
136
  declare function measureTableOverlayGeometry(table: HTMLTableElement, activeCell: HTMLTableCellElement | null, hoveredCell?: HTMLTableCellElement | null): TableOverlayGeometry;
95
137
 
96
138
  export { type ActiveCellRect as A, TABLE_CELL_BACKGROUND_OPTIONS as T, TABLE_CELL_BACKGROUND_PRESETS as a, type TableCellBackgroundAction as b, type TableContextMenuAction as c, type TableContextMenuActionEventDetail as d, type TableInsertionAction as e, type TableOverlayAction as f, type TableOverlayActionEventDetail as g, type TableOverlayGeometry as h, measureTableOverlayGeometry as m, resolveTableCellAt as r };
package/editor/ui.d.ts CHANGED
@@ -1,38 +1,41 @@
1
- export { A as ActiveCellRect, T as TABLE_CELL_BACKGROUND_OPTIONS, a as TABLE_CELL_BACKGROUND_PRESETS, b as TableCellBackgroundAction, c as TableContextMenuAction, d as TableContextMenuActionEventDetail, e as TableInsertionAction, f as TableOverlayAction, g as TableOverlayActionEventDetail, h as TableOverlayGeometry, d as TableToolbarActionEventDetail, m as measureTableOverlayGeometry, r as resolveTableCellAt } from './table-overlay-DoiLie4h.js';
1
+ export { A as ActiveCellRect, T as TABLE_CELL_BACKGROUND_OPTIONS, a as TABLE_CELL_BACKGROUND_PRESETS, b as TableCellBackgroundAction, c as TableContextMenuAction, d as TableContextMenuActionEventDetail, e as TableInsertionAction, f as TableOverlayAction, g as TableOverlayActionEventDetail, h as TableOverlayGeometry, d as TableToolbarActionEventDetail, m as measureTableOverlayGeometry, r as resolveTableCellAt } from './table-overlay-DZFGHQDt.js';
2
2
  import { LoomaIconName } from '@threadlabs/looma/core';
3
3
 
4
- /**
5
- * ui-editor-insert-table-grid — web component for picking table dimensions.
6
- * Emits looma-editor-insert-table with { rows, cols, withHeaderRow }.
7
- * Domain-neutral: no Tiptap dependency.
8
- */
4
+ /** Event contract for the declarative table-dimension picker. */
5
+ /** Confirmed table dimensions emitted after preview state has been committed. */
9
6
  interface InsertTableEventDetail {
10
7
  rows: number;
11
8
  cols: number;
12
9
  withHeaderRow: boolean;
13
10
  }
14
11
 
15
- /** ui-editor-mention-menu — bounded, accessible mention suggestions. */
12
+ /** Event contracts for the declarative mention menu. */
13
+ /** Zero-based candidate position requested by pointer-driven menu highlighting. */
16
14
  interface MentionMenuHighlightEventDetail {
17
15
  index: number;
18
16
  }
17
+ /** Zero-based candidate position the host should commit as the chosen mention. */
19
18
  interface MentionMenuSelectEventDetail {
20
19
  index: number;
21
20
  }
22
21
 
22
+ /** Public data and event contracts for the declarative slash-command menu. */
23
+
23
24
  /**
24
- * ui-editor-slash-menu — floating slash-command menu.
25
- * Apps own the command list and suggestion state; Looma owns the chrome.
25
+ * Presentation projection of a slash command.
26
+ * It intentionally omits editor callbacks: the menu emits an index and the
27
+ * headless extension executes the command from its current ephemeral snapshot.
26
28
  */
27
-
28
29
  interface SlashMenuItem {
29
30
  title: string;
30
31
  description: string;
31
32
  icon: LoomaIconName;
32
33
  }
34
+ /** Pointer-hover request; selection remains owned by the suggestion extension. */
33
35
  interface SlashMenuHighlightEventDetail {
34
36
  index: number;
35
37
  }
38
+ /** Activation request for an item in the current published snapshot. */
36
39
  interface SlashMenuSelectEventDetail {
37
40
  index: number;
38
41
  }
@@ -41,7 +44,8 @@ interface SlashMenuSelectEventDetail {
41
44
  *
42
45
  * Browser DOMRect objects satisfy both variants. Plain rectangles from Tiptap
43
46
  * and ProseMirror are also supported when they provide either edge coordinates
44
- * or an origin plus dimensions.
47
+ * or an origin plus dimensions. Values use CSS-pixel viewport coordinates; the
48
+ * menu converts them into visual-viewport-aware fixed positioning.
45
49
  */
46
50
  type SlashMenuAnchorRect = Pick<DOMRectReadOnly, "left" | "top" | "right" | "bottom"> | Pick<DOMRectReadOnly, "x" | "y" | "width" | "height">;
47
51
 
package/editor/ui.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  measureTableOverlayGeometry,
3
3
  resolveTableCellAt
4
- } from "./chunk-WI7ZA44X.js";
4
+ } from "./chunk-U36XNFJN.js";
5
5
  import {
6
6
  TABLE_CELL_BACKGROUND_OPTIONS,
7
7
  TABLE_CELL_BACKGROUND_PRESETS