@threadlabs/looma 0.22.12 → 0.22.14

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 (71) hide show
  1. package/components/shared/icons.js +4 -0
  2. package/components/ui-card/ui-card.html +21 -2
  3. package/components/ui-icon/ui-icon.html +4 -0
  4. package/components/ui-input/ui-input.html +1 -0
  5. package/components/ui-input-group/ui-input-group.html +11 -0
  6. package/components/ui-popover/ui-popover.html +15 -0
  7. package/components/ui-scroll-area/ui-scroll-area.html +12 -0
  8. package/components/ui-search-result-row/ui-search-result-row.html +11 -0
  9. package/components/ui-stack/ui-stack.html +6 -3
  10. package/components/ui-text/ui-text.html +12 -0
  11. package/dist/index.js +1 -1
  12. package/editor/chunks/extensions.js +75 -6
  13. package/editor/extensions/index.d.ts +1 -0
  14. package/editor/extensions/index.js +2 -2
  15. package/editor/extensions/preset.d.ts +2 -0
  16. package/editor/extensions/relative-links.d.ts +8 -0
  17. package/editor/extensions/slash-command.d.ts +5 -3
  18. package/editor/icons.d.ts +4 -0
  19. package/editor/index.js +7 -3
  20. package/package.json +1 -1
  21. package/styles/ui-card.css +17 -0
  22. package/styles/ui-input-group.css +9 -0
  23. package/styles/ui-input.css +1 -0
  24. package/styles/ui-popover.css +13 -0
  25. package/styles/ui-scroll-area.css +10 -0
  26. package/styles/ui-search-result-row.css +9 -0
  27. package/styles/ui-stack.css +3 -0
  28. package/styles/ui-text.css +8 -0
  29. package/vanilla/UiCard.d.ts +2 -1
  30. package/vanilla/UiCard.js +1 -1
  31. package/vanilla/UiIcon.js +1 -1
  32. package/vanilla/UiInputGroup.d.ts +1 -0
  33. package/vanilla/UiInputGroup.js +1 -1
  34. package/vanilla/UiPopover.d.ts +1 -0
  35. package/vanilla/UiPopover.js +1 -1
  36. package/vanilla/UiScrollArea.d.ts +1 -0
  37. package/vanilla/UiScrollArea.js +1 -1
  38. package/vanilla/UiSearchResultRow.d.ts +1 -0
  39. package/vanilla/UiSearchResultRow.js +1 -1
  40. package/vanilla/UiStack.d.ts +1 -1
  41. package/vanilla/UiStack.js +1 -1
  42. package/vanilla/UiText.d.ts +2 -0
  43. package/vanilla/UiText.js +1 -1
  44. package/vue/UiCard.d.ts +12 -3
  45. package/vue/UiCard.vue +49 -5
  46. package/vue/UiIcon.vue +23 -0
  47. package/vue/UiInput.vue +1 -0
  48. package/vue/UiInputGroup.d.ts +9 -0
  49. package/vue/UiInputGroup.vue +33 -2
  50. package/vue/UiPopover.d.ts +9 -0
  51. package/vue/UiPopover.vue +43 -2
  52. package/vue/UiScrollArea.d.ts +9 -0
  53. package/vue/UiScrollArea.vue +35 -2
  54. package/vue/UiSearchResultRow.d.ts +9 -0
  55. package/vue/UiSearchResultRow.vue +38 -1
  56. package/vue/UiStack.d.ts +3 -3
  57. package/vue/UiStack.vue +10 -4
  58. package/vue/UiText.d.ts +18 -0
  59. package/vue/UiText.vue +70 -0
  60. package/vue/chunks/UiCard.js +39 -3
  61. package/vue/chunks/UiIcon.js +69 -1
  62. package/vue/chunks/UiInput.js +1 -1
  63. package/vue/chunks/UiInputGroup.js +59 -22
  64. package/vue/chunks/UiPopover.js +37 -5
  65. package/vue/chunks/UiScrollArea.js +66 -23
  66. package/vue/chunks/UiSearchResultRow.js +28 -2
  67. package/vue/chunks/UiStack.js +3 -2
  68. package/vue/chunks/UiText.js +92 -4
  69. package/vue/components.css +174 -297
  70. package/vue/editor/LoomaEditor.d.ts +11 -0
  71. package/vue/editor/index.js +262 -145
@@ -7,6 +7,7 @@ import { dropCursor } from "@tiptap/pm/dropcursor";
7
7
  import { gapCursor } from "@tiptap/pm/gapcursor";
8
8
  import { createLowlight } from "lowlight";
9
9
  import { DOMParser, Node as Node$2, Slice } from "@tiptap/pm/model";
10
+ import { Mapping } from "@tiptap/pm/transform";
10
11
  import MarkdownIt from "markdown-it";
11
12
  import { CellSelection, TableMap, addColumn, addColumnAfter, addColumnBefore, addRow, addRowAfter, addRowBefore, cellAround, columnResizing, deleteCellSelection, deleteColumn, deleteRow, deleteTable, fixTables, goToNextCell, mergeCells, moveTableColumn, moveTableRow, setCellAttr, splitCell, tableEditing, toggleHeader, toggleHeaderCell } from "@tiptap/pm/tables";
12
13
  //#region src/editor/extensions/active-block.ts
@@ -6198,6 +6199,57 @@ function createLoomaMentionExtension(options = {}) {
6198
6199
  });
6199
6200
  }
6200
6201
  //#endregion
6202
+ //#region src/editor/extensions/relative-links.ts
6203
+ /** Keep other origins and non-web schemes intact; same-origin links retain path, query, and fragment. */
6204
+ function siteRelativeHref(href, baseUrl) {
6205
+ if (!/^(https?:\/\/|\/\/)/i.test(href.trim())) return href;
6206
+ try {
6207
+ const base = new URL(baseUrl);
6208
+ const url = new URL(href, base);
6209
+ if (!/^https?:$/.test(base.protocol) || url.origin !== base.origin || url.username || url.password) return href;
6210
+ return `${url.pathname}${url.search}${url.hash}`;
6211
+ } catch {
6212
+ return href;
6213
+ }
6214
+ }
6215
+ /** Normalize newly created links in the same transaction batch, including paste rules and the picker.
6216
+ * @contract Existing document links are preserved until replaced; undo/redo keeps the original editing step.
6217
+ * @ownership The editor owns normalization; callers supply a site URL rather than a host callback.
6218
+ */
6219
+ function createSiteRelativeLinks(baseUrl) {
6220
+ const key = new PluginKey("looma-site-relative-links");
6221
+ return Extension.create({
6222
+ name: "loomaSiteRelativeLinks",
6223
+ addProseMirrorPlugins() {
6224
+ const editor = this.editor;
6225
+ return [new Plugin({
6226
+ key,
6227
+ appendTransaction(transactions, oldState, newState) {
6228
+ if (!editor.isEditable || !transactions.some((transaction) => transaction.docChanged) || transactions.some((transaction) => transaction.getMeta(key))) return null;
6229
+ const mapping = new Mapping();
6230
+ for (const transaction of transactions) mapping.appendMapping(transaction.mapping);
6231
+ const inverse = mapping.invert();
6232
+ const tr = newState.tr;
6233
+ newState.doc.descendants((node, position) => {
6234
+ if (!node.isText) return;
6235
+ const mark = node.marks.find((candidate) => candidate.type.name === "link");
6236
+ if (!mark || typeof mark.attrs.href !== "string") return;
6237
+ const href = siteRelativeHref(mark.attrs.href, baseUrl);
6238
+ if (href === mark.attrs.href) return;
6239
+ const before = inverse.mapResult(position, 1);
6240
+ if ((before.deleted ? null : oldState.doc.nodeAt(before.pos)?.marks.find((candidate) => candidate.type.name === "link"))?.attrs.href === mark.attrs.href) return;
6241
+ tr.addMark(position, position + node.nodeSize, mark.type.create({
6242
+ ...mark.attrs,
6243
+ href
6244
+ }));
6245
+ });
6246
+ return tr.docChanged ? tr.setMeta(key, true) : null;
6247
+ }
6248
+ })];
6249
+ }
6250
+ });
6251
+ }
6252
+ //#endregion
6201
6253
  //#region ../../node_modules/.pnpm/dompurify@3.4.15/node_modules/dompurify/dist/purify.es.mjs
6202
6254
  /*! @license DOMPurify 3.4.15 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.15/LICENSE */
6203
6255
  function _arrayLikeToArray(r, a) {
@@ -9290,7 +9342,7 @@ function getLoomaTableExtensions() {
9290
9342
  * the code and explicit language stay in the document schema.
9291
9343
  */
9292
9344
  function getDefaultEditorExtensions(options = {}) {
9293
- const { placeholder = "Type “/” for commands, or start writing…", linkOpenOnClick = false, imageInline = false, mention = createLoomaMentionExtension(), disableHighlight = false, codeLanguages, codeLowlight, codeBlockNodeView } = options;
9345
+ const { placeholder = "Type “/” for commands, or start writing…", linkOpenOnClick = false, linkBaseUrl, imageInline = false, mention = createLoomaMentionExtension(), disableHighlight = false, codeLanguages, codeLowlight, codeBlockNodeView } = options;
9294
9346
  const codeBlock = LoomaCodeBlock.configure({ lowlight: codeLowlight ?? createLowlight(codeLanguages) });
9295
9347
  return [
9296
9348
  Document,
@@ -9325,6 +9377,7 @@ function getDefaultEditorExtensions(options = {}) {
9325
9377
  target: "_blank"
9326
9378
  }
9327
9379
  }),
9380
+ ...linkBaseUrl ? [createSiteRelativeLinks(linkBaseUrl)] : [],
9328
9381
  Image.configure({ inline: imageInline }),
9329
9382
  (disableHighlight ? StoredOnlyHighlight : Highlight).configure({ multicolor: false }),
9330
9383
  Code,
@@ -9778,13 +9831,14 @@ var CALLOUT_COMMANDS = [
9778
9831
  ];
9779
9832
  /**
9780
9833
  * Builds Looma's default command policy as fresh objects for one editor.
9781
- * The image command delegates asset selection because Looma does not own upload,
9782
- * persistence, or media-library concerns.
9834
+ * Image and link commands delegate their picker because Looma does not own
9835
+ * upload, persistence, or destination search. Link appears only when a picker
9836
+ * callback is supplied, so a headless default inventory has no dead action.
9783
9837
  *
9784
9838
  * @ownership Returned command objects belong to the caller and are recreated
9785
9839
  * per call so one editor cannot mutate another editor's command inventory.
9786
9840
  */
9787
- function getDefaultSlashCommands(onOpenImagePicker, onOpenChipEditor) {
9841
+ function getDefaultSlashCommands(onOpenImagePicker, onOpenChipEditor, onOpenLinkEditor) {
9788
9842
  return [
9789
9843
  {
9790
9844
  title: "Text",
@@ -9950,6 +10004,20 @@ function getDefaultSlashCommands(onOpenImagePicker, onOpenChipEditor) {
9950
10004
  editor.chain().focus().deleteRange(range).setHorizontalRule().run();
9951
10005
  }
9952
10006
  },
10007
+ ...onOpenLinkEditor ? [{
10008
+ title: "Link",
10009
+ description: "Link to a destination or URL",
10010
+ icon: "link",
10011
+ keywords: [
10012
+ "link",
10013
+ "url",
10014
+ "website"
10015
+ ],
10016
+ command: ({ editor, range }) => {
10017
+ editor.chain().focus().deleteRange(range).run();
10018
+ onOpenLinkEditor();
10019
+ }
10020
+ }] : [],
9953
10021
  {
9954
10022
  title: "Image",
9955
10023
  description: "Upload an image",
@@ -10081,10 +10149,11 @@ var LoomaSlashCommand = Extension.create({
10081
10149
  function createLoomaSlashCommandExtension(options = {}) {
10082
10150
  const onOpenImagePicker = options.onOpenImagePicker;
10083
10151
  const onOpenChipEditor = options.onOpenChipEditor;
10152
+ const onOpenLinkEditor = options.onOpenLinkEditor;
10084
10153
  return LoomaSlashCommand.configure({
10085
10154
  ...options,
10086
- commands: options.commands ?? getDefaultSlashCommands(onOpenImagePicker, onOpenChipEditor)
10155
+ commands: options.commands ?? getDefaultSlashCommands(onOpenImagePicker, onOpenChipEditor, onOpenLinkEditor)
10087
10156
  });
10088
10157
  }
10089
10158
  //#endregion
10090
- export { LOOMA_CALLOUT_TONES as A, DEFAULT_MENTION_RESULT_LIMIT as C, LOOMA_CHIP_COLORS as D, normalizeMentionResultLimit as E, LoomaActiveBlock as F, LoomaActiveBlockPluginKey as I, LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS as M, LOOMA_ACTIVE_BLOCK_CLASS as N, LoomaChip as O, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS as P, createLoomaMentionExtension as S, filterLoomaMentionItems as T, getActiveTableCellBackground as _, handleTableAction as a, LoomaSmartPaste as b, normalizeActiveTableColumnWidths as c, getDefaultEditorExtensions as d, getLoomaTableExtensions as f, getActiveTableCellAlignment as g, LoomaTableHeader as h, getActiveTableUiState as i, LoomaCallout as j, normalizeLoomaChipColor as k, shouldShowTextFormattingToolbar as l, LoomaTableCell as m, createLoomaSlashCommandExtension as n, handleTableOverlayAction as o, LoomaTable as p, getDefaultSlashCommands as r, insertTableAtRange as s, LoomaSlashCommand as t, LoomaTableKit as u, setActiveTableCellAlignment as v, MAX_MENTION_RESULT_LIMIT as w, LoomaMentionSuggestionPluginKey as x, setActiveTableCellBackground as y };
10159
+ export { LoomaChip as A, LoomaMentionSuggestionPluginKey as C, filterLoomaMentionItems as D, MAX_MENTION_RESULT_LIMIT as E, LOOMA_ACTIVE_BLOCK_CLASS as F, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS as I, LoomaActiveBlock as L, LOOMA_CALLOUT_TONES as M, LoomaCallout as N, normalizeMentionResultLimit as O, LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS as P, LoomaActiveBlockPluginKey as R, siteRelativeHref as S, DEFAULT_MENTION_RESULT_LIMIT as T, getActiveTableCellBackground as _, handleTableAction as a, LoomaSmartPaste as b, normalizeActiveTableColumnWidths as c, getDefaultEditorExtensions as d, getLoomaTableExtensions as f, getActiveTableCellAlignment as g, LoomaTableHeader as h, getActiveTableUiState as i, normalizeLoomaChipColor as j, LOOMA_CHIP_COLORS as k, shouldShowTextFormattingToolbar as l, LoomaTableCell as m, createLoomaSlashCommandExtension as n, handleTableOverlayAction as o, LoomaTable as p, getDefaultSlashCommands as r, insertTableAtRange as s, LoomaSlashCommand as t, LoomaTableKit as u, setActiveTableCellAlignment as v, createLoomaMentionExtension as w, createSiteRelativeLinks as x, setActiveTableCellBackground as y };
@@ -15,3 +15,4 @@ export { getActiveTableUiState, handleTableAction, handleTableOverlayAction, ins
15
15
  export { LoomaTable, getActiveTableCellAlignment, getActiveTableCellBackground, LoomaTableCell, LoomaTableHeader, setActiveTableCellAlignment, setActiveTableCellBackground, TABLE_CELL_BACKGROUND_PRESETS, type TableCellAlignment, type TableCellBackground, } from "./table-formatting.js";
16
16
  export { createLoomaMentionExtension, DEFAULT_MENTION_RESULT_LIMIT, filterLoomaMentionItems, LoomaMentionSuggestionPluginKey, MAX_MENTION_RESULT_LIMIT, normalizeMentionResultLimit, type LoomaMentionItem, type LoomaMentionMenuSnapshot, type LoomaMentionOptions, type LoomaMentionProvider, type LoomaMentionProviderContext, } from "./mention.js";
17
17
  export { createLoomaSlashCommandExtension, getDefaultSlashCommands, LoomaSlashCommand, type LoomaSlashCommand as LoomaSlashCommandItem, type LoomaSlashCommandContext, type LoomaSlashCommandOptions, type LoomaSlashMenuSnapshot, } from "./slash-command.js";
18
+ export { siteRelativeHref, createSiteRelativeLinks } from "./relative-links.js";
@@ -1,3 +1,3 @@
1
1
  import { n as TABLE_CELL_BACKGROUND_PRESETS } from "../chunks/table-backgrounds.js";
2
- import { A as LOOMA_CALLOUT_TONES, C as DEFAULT_MENTION_RESULT_LIMIT, D as LOOMA_CHIP_COLORS, E as normalizeMentionResultLimit, F as LoomaActiveBlock, I as LoomaActiveBlockPluginKey, M as LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, N as LOOMA_ACTIVE_BLOCK_CLASS, O as LoomaChip, P as LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, S as createLoomaMentionExtension, T as filterLoomaMentionItems, _ as getActiveTableCellBackground, a as handleTableAction, b as LoomaSmartPaste, c as normalizeActiveTableColumnWidths, d as getDefaultEditorExtensions, f as getLoomaTableExtensions, g as getActiveTableCellAlignment, h as LoomaTableHeader, i as getActiveTableUiState, j as LoomaCallout, k as normalizeLoomaChipColor, l as shouldShowTextFormattingToolbar, m as LoomaTableCell, n as createLoomaSlashCommandExtension, o as handleTableOverlayAction, p as LoomaTable, r as getDefaultSlashCommands, s as insertTableAtRange, t as LoomaSlashCommand, u as LoomaTableKit, v as setActiveTableCellAlignment, w as MAX_MENTION_RESULT_LIMIT, x as LoomaMentionSuggestionPluginKey, y as setActiveTableCellBackground } from "../chunks/extensions.js";
3
- export { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, LOOMA_ACTIVE_BLOCK_CLASS, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, LOOMA_CALLOUT_TONES, LOOMA_CHIP_COLORS, LoomaActiveBlock, LoomaActiveBlockPluginKey, LoomaCallout, LoomaChip, LoomaMentionSuggestionPluginKey, LoomaSlashCommand, LoomaSmartPaste, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, MAX_MENTION_RESULT_LIMIT, TABLE_CELL_BACKGROUND_PRESETS, createLoomaMentionExtension, createLoomaSlashCommandExtension, filterLoomaMentionItems, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, handleTableAction, handleTableOverlayAction, insertTableAtRange, normalizeActiveTableColumnWidths, normalizeLoomaChipColor, normalizeMentionResultLimit, setActiveTableCellAlignment, setActiveTableCellBackground, shouldShowTextFormattingToolbar };
2
+ import { A as LoomaChip, C as LoomaMentionSuggestionPluginKey, D as filterLoomaMentionItems, E as MAX_MENTION_RESULT_LIMIT, F as LOOMA_ACTIVE_BLOCK_CLASS, I as LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, L as LoomaActiveBlock, M as LOOMA_CALLOUT_TONES, N as LoomaCallout, O as normalizeMentionResultLimit, P as LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, R as LoomaActiveBlockPluginKey, S as siteRelativeHref, T as DEFAULT_MENTION_RESULT_LIMIT, _ as getActiveTableCellBackground, a as handleTableAction, b as LoomaSmartPaste, c as normalizeActiveTableColumnWidths, d as getDefaultEditorExtensions, f as getLoomaTableExtensions, g as getActiveTableCellAlignment, h as LoomaTableHeader, i as getActiveTableUiState, j as normalizeLoomaChipColor, k as LOOMA_CHIP_COLORS, l as shouldShowTextFormattingToolbar, m as LoomaTableCell, n as createLoomaSlashCommandExtension, o as handleTableOverlayAction, p as LoomaTable, r as getDefaultSlashCommands, s as insertTableAtRange, t as LoomaSlashCommand, u as LoomaTableKit, v as setActiveTableCellAlignment, w as createLoomaMentionExtension, x as createSiteRelativeLinks, y as setActiveTableCellBackground } from "../chunks/extensions.js";
3
+ export { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, LOOMA_ACTIVE_BLOCK_CLASS, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, LOOMA_CALLOUT_TONES, LOOMA_CHIP_COLORS, LoomaActiveBlock, LoomaActiveBlockPluginKey, LoomaCallout, LoomaChip, LoomaMentionSuggestionPluginKey, LoomaSlashCommand, LoomaSmartPaste, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, MAX_MENTION_RESULT_LIMIT, TABLE_CELL_BACKGROUND_PRESETS, createLoomaMentionExtension, createLoomaSlashCommandExtension, createSiteRelativeLinks, filterLoomaMentionItems, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, handleTableAction, handleTableOverlayAction, insertTableAtRange, normalizeActiveTableColumnWidths, normalizeLoomaChipColor, normalizeMentionResultLimit, setActiveTableCellAlignment, setActiveTableCellBackground, shouldShowTextFormattingToolbar, siteRelativeHref };
@@ -16,6 +16,8 @@ export interface DefaultEditorExtensionsOptions {
16
16
  placeholder?: string;
17
17
  /** Passed to Tiptap Link; defaults false to keep editing clicks in the editor. */
18
18
  linkOpenOnClick?: boolean;
19
+ /** Site origin whose newly inserted links become relative, across paste and editor commands. */
20
+ linkBaseUrl?: string;
19
21
  /** Passed to Tiptap Image; block images are the default document policy. */
20
22
  imageInline?: boolean;
21
23
  /** Custom mention extension, the Looma default, or false to omit mentions. */
@@ -0,0 +1,8 @@
1
+ import { Extension } from '@tiptap/core';
2
+ /** Keep other origins and non-web schemes intact; same-origin links retain path, query, and fragment. */
3
+ export declare function siteRelativeHref(href: string, baseUrl: string): string;
4
+ /** Normalize newly created links in the same transaction batch, including paste rules and the picker.
5
+ * @contract Existing document links are preserved until replaced; undo/redo keeps the original editing step.
6
+ * @ownership The editor owns normalization; callers supply a site URL rather than a host callback.
7
+ */
8
+ export declare function createSiteRelativeLinks(baseUrl: string): Extension<any, any>;
@@ -49,16 +49,18 @@ export interface LoomaSlashCommandOptions {
49
49
  onStateChange?: (state: LoomaSlashMenuSnapshot) => void;
50
50
  onOpenImagePicker?: () => void;
51
51
  onOpenChipEditor?: (editor: Editor, position: number) => void;
52
+ onOpenLinkEditor?: () => void;
52
53
  }
53
54
  /**
54
55
  * Builds Looma's default command policy as fresh objects for one editor.
55
- * The image command delegates asset selection because Looma does not own upload,
56
- * persistence, or media-library concerns.
56
+ * Image and link commands delegate their picker because Looma does not own
57
+ * upload, persistence, or destination search. Link appears only when a picker
58
+ * callback is supplied, so a headless default inventory has no dead action.
57
59
  *
58
60
  * @ownership Returned command objects belong to the caller and are recreated
59
61
  * per call so one editor cannot mutate another editor's command inventory.
60
62
  */
61
- export declare function getDefaultSlashCommands(onOpenImagePicker?: () => void, onOpenChipEditor?: (editor: Editor, position: number) => void): LoomaSlashCommand[];
63
+ export declare function getDefaultSlashCommands(onOpenImagePicker?: () => void, onOpenChipEditor?: (editor: Editor, position: number) => void, onOpenLinkEditor?: () => void): LoomaSlashCommand[];
62
64
  /**
63
65
  * Framework-neutral slash-command extension used by the turnkey editor.
64
66
  * Consumers embedding Looma into their own Tiptap instance can configure the
package/editor/icons.d.ts CHANGED
@@ -7,6 +7,10 @@ export declare const LOOMA_ICONS: {
7
7
  'arrow-left': IconNode;
8
8
  bold: IconNode;
9
9
  'book-user': IconNode;
10
+ search: IconNode;
11
+ 'external-link': IconNode;
12
+ pencil: IconNode;
13
+ unlink: IconNode;
10
14
  braces: IconNode;
11
15
  calculator: IconNode;
12
16
  check: IconNode;
package/editor/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { n as TABLE_CELL_BACKGROUND_PRESETS, t as TABLE_CELL_BACKGROUND_OPTIONS } from "./chunks/table-backgrounds.js";
2
2
  import { n as resolveTableCellAt, t as measureTableOverlayGeometry } from "./chunks/ui.js";
3
- import { A as LOOMA_CALLOUT_TONES, C as DEFAULT_MENTION_RESULT_LIMIT, D as LOOMA_CHIP_COLORS, E as normalizeMentionResultLimit, F as LoomaActiveBlock, I as LoomaActiveBlockPluginKey, M as LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, N as LOOMA_ACTIVE_BLOCK_CLASS, O as LoomaChip, P as LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, S as createLoomaMentionExtension, T as filterLoomaMentionItems, _ as getActiveTableCellBackground, a as handleTableAction, b as LoomaSmartPaste, c as normalizeActiveTableColumnWidths, d as getDefaultEditorExtensions, f as getLoomaTableExtensions, g as getActiveTableCellAlignment, h as LoomaTableHeader, i as getActiveTableUiState, j as LoomaCallout, k as normalizeLoomaChipColor, l as shouldShowTextFormattingToolbar, m as LoomaTableCell, n as createLoomaSlashCommandExtension, o as handleTableOverlayAction, p as LoomaTable, r as getDefaultSlashCommands, s as insertTableAtRange, t as LoomaSlashCommand, u as LoomaTableKit, v as setActiveTableCellAlignment, w as MAX_MENTION_RESULT_LIMIT, x as LoomaMentionSuggestionPluginKey, y as setActiveTableCellBackground } from "./chunks/extensions.js";
4
- import { AlignCenter, AlignLeft, AlignRight, ArrowLeft, Bold, BookUser, Braces, Calculator, Check, ChevronDown, ChevronLeft, ChevronRight, CircleCheck, CircleDot, CircleQuestionMark, CircleX, CodeXml, Columns3, CreditCard, Ellipsis, Eraser, FileText, Folder, GripHorizontal, GripVertical, Heading1, Heading2, Heading3, Highlighter, Image, Info, Italic, LayoutDashboard, Link, List, ListOrdered, ListTodo, LoaderCircle, Merge, Minus, NotebookPen, PaintBucket, PanelBottom, PanelLeft, PanelRight, PanelTop, Pilcrow, Plus, Quote, Receipt, Redo2, Rows3, Settings, Split, Strikethrough, Table2, Tag, Trash2, TriangleAlert, Truck, Underline, Undo2, UserRound, Users, X } from "lucide";
3
+ import { A as LoomaChip, C as LoomaMentionSuggestionPluginKey, D as filterLoomaMentionItems, E as MAX_MENTION_RESULT_LIMIT, F as LOOMA_ACTIVE_BLOCK_CLASS, I as LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, L as LoomaActiveBlock, M as LOOMA_CALLOUT_TONES, N as LoomaCallout, O as normalizeMentionResultLimit, P as LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, R as LoomaActiveBlockPluginKey, S as siteRelativeHref, T as DEFAULT_MENTION_RESULT_LIMIT, _ as getActiveTableCellBackground, a as handleTableAction, b as LoomaSmartPaste, c as normalizeActiveTableColumnWidths, d as getDefaultEditorExtensions, f as getLoomaTableExtensions, g as getActiveTableCellAlignment, h as LoomaTableHeader, i as getActiveTableUiState, j as normalizeLoomaChipColor, k as LOOMA_CHIP_COLORS, l as shouldShowTextFormattingToolbar, m as LoomaTableCell, n as createLoomaSlashCommandExtension, o as handleTableOverlayAction, p as LoomaTable, r as getDefaultSlashCommands, s as insertTableAtRange, t as LoomaSlashCommand, u as LoomaTableKit, v as setActiveTableCellAlignment, w as createLoomaMentionExtension, x as createSiteRelativeLinks, y as setActiveTableCellBackground } from "./chunks/extensions.js";
4
+ import { AlignCenter, AlignLeft, AlignRight, ArrowLeft, Bold, BookUser, Braces, Calculator, Check, ChevronDown, ChevronLeft, ChevronRight, CircleCheck, CircleDot, CircleQuestionMark, CircleX, CodeXml, Columns3, CreditCard, Ellipsis, Eraser, ExternalLink, FileText, Folder, GripHorizontal, GripVertical, Heading1, Heading2, Heading3, Highlighter, Image, Info, Italic, LayoutDashboard, Link, List, ListOrdered, ListTodo, LoaderCircle, Merge, Minus, NotebookPen, PaintBucket, PanelBottom, PanelLeft, PanelRight, PanelTop, Pencil, Pilcrow, Plus, Quote, Receipt, Redo2, Rows3, Search, Settings, Split, Strikethrough, Table2, Tag, Trash2, TriangleAlert, Truck, Underline, Undo2, Unlink, UserRound, Users, X } from "lucide";
5
5
  //#region src/editor/icons.ts
6
6
  /** The opinionated Lucide set used by Looma's shipped interaction surfaces. */
7
7
  var LOOMA_ICONS = {
@@ -11,6 +11,10 @@ var LOOMA_ICONS = {
11
11
  "arrow-left": ArrowLeft,
12
12
  bold: Bold,
13
13
  "book-user": BookUser,
14
+ "search": Search,
15
+ "external-link": ExternalLink,
16
+ "pencil": Pencil,
17
+ "unlink": Unlink,
14
18
  braces: Braces,
15
19
  calculator: Calculator,
16
20
  check: Check,
@@ -114,4 +118,4 @@ function getVisualViewportRect(owner = window) {
114
118
  };
115
119
  }
116
120
  //#endregion
117
- export { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, LOOMA_ACTIVE_BLOCK_CLASS, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, LOOMA_CALLOUT_TONES, LOOMA_CHIP_COLORS, LOOMA_ICONS, LoomaActiveBlock, LoomaActiveBlockPluginKey, LoomaCallout, LoomaChip, LoomaMentionSuggestionPluginKey, LoomaSlashCommand, LoomaSmartPaste, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, MAX_MENTION_RESULT_LIMIT, TABLE_CELL_BACKGROUND_OPTIONS, TABLE_CELL_BACKGROUND_PRESETS, createLoomaMentionExtension, createLoomaSlashCommandExtension, filterLoomaMentionItems, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, getVisualViewportRect, handleTableAction, handleTableOverlayAction, insertTableAtRange, loomaIconMarkup, measureTableOverlayGeometry, normalizeActiveTableColumnWidths, normalizeLoomaChipColor, normalizeMentionResultLimit, resolveTableCellAt, setActiveTableCellAlignment, setActiveTableCellBackground, shouldShowTextFormattingToolbar };
121
+ export { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS, LOOMA_ACTIVE_BLOCK_CLASS, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS, LOOMA_CALLOUT_TONES, LOOMA_CHIP_COLORS, LOOMA_ICONS, LoomaActiveBlock, LoomaActiveBlockPluginKey, LoomaCallout, LoomaChip, LoomaMentionSuggestionPluginKey, LoomaSlashCommand, LoomaSmartPaste, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, MAX_MENTION_RESULT_LIMIT, TABLE_CELL_BACKGROUND_OPTIONS, TABLE_CELL_BACKGROUND_PRESETS, createLoomaMentionExtension, createLoomaSlashCommandExtension, createSiteRelativeLinks, filterLoomaMentionItems, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, getVisualViewportRect, handleTableAction, handleTableOverlayAction, insertTableAtRange, loomaIconMarkup, measureTableOverlayGeometry, normalizeActiveTableColumnWidths, normalizeLoomaChipColor, normalizeMentionResultLimit, resolveTableCellAt, setActiveTableCellAlignment, setActiveTableCellBackground, shouldShowTextFormattingToolbar, siteRelativeHref };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threadlabs/looma",
3
- "version": "0.22.12",
3
+ "version": "0.22.14",
4
4
  "type": "module",
5
5
  "description": "Looma components as HTML, Vue, and plain DOM, with design tokens.",
6
6
  "license": "MIT",
@@ -15,6 +15,10 @@
15
15
  color: var(--ui-text-primary);
16
16
  }
17
17
 
18
+ :scope[data-ui-card-state~="padding=xs"] {
19
+ gap: var(--ui-space-1);
20
+ padding: var(--ui-space-2);
21
+ }
18
22
  :scope[data-ui-card-state~="padding=sm"] {
19
23
  gap: var(--ui-space-2);
20
24
  padding: var(--ui-space-3);
@@ -40,6 +44,19 @@
40
44
  background: var(--ui-danger-soft);
41
45
  }
42
46
 
47
+ :scope[data-ui-card-state~="size=sm"] {
48
+ inline-size: min(22rem, calc(100vw - var(--ui-space-2) * 2));
49
+ max-inline-size: min(22rem, calc(100vw - var(--ui-space-2) * 2));
50
+ }
51
+ :scope[data-ui-card-state~="size=md"] {
52
+ inline-size: min(28rem, calc(100vw - var(--ui-space-2) * 2));
53
+ max-inline-size: min(28rem, calc(100vw - var(--ui-space-2) * 2));
54
+ }
55
+ :scope[data-ui-card-state~="size=lg"] {
56
+ inline-size: min(36rem, calc(100vw - var(--ui-space-2) * 2));
57
+ max-inline-size: min(36rem, calc(100vw - var(--ui-space-2) * 2));
58
+ }
59
+
43
60
  /* A component that sets its display still honours the hidden attribute on its root. */
44
61
  :scope[hidden] {
45
62
  display: none;
@@ -139,6 +139,15 @@
139
139
  border-inline-start: 1px solid var(--ui-border-divider);
140
140
  }
141
141
 
142
+ :scope[data-ui-input-group-state~="prefixKind=icon"] {
143
+ --_ui-default-input-padding-inline-start: var(--ui-space-2);
144
+ }
145
+ :scope[data-ui-input-group-state~="prefixKind=icon"] .affix:first-child {
146
+ padding-inline-end: 0;
147
+ border-inline-end: 0;
148
+ background: transparent;
149
+ }
150
+
142
151
  /* Centred rather than padded above and below: the group is exactly a lone Input's height, so a
143
152
  small button sits inside it with the difference split evenly, and the field keeps its height. */
144
153
  .action {
@@ -64,6 +64,7 @@
64
64
  margin: 0;
65
65
  padding: var(--ui-space-2) var(--ui-space-3);
66
66
  appearance: none;
67
+ padding-inline-start: var(--_ui-default-input-padding-inline-start, var(--ui-space-3));
67
68
  border: var(--ui-input-border-width, var(--_ui-default-input-border-width, 1px)) solid
68
69
  var(--ui-input-border, var(--_ui-default-input-border, var(--ui-control-border, var(--ui-border-strong))));
69
70
  border-radius: var(--ui-input-radius, var(--_ui-default-input-radius, var(--ui-field-radius, var(--ui-radius-md))));
@@ -92,6 +92,19 @@
92
92
  }
93
93
  }
94
94
 
95
+ :scope[data-ui-popover-state~="size=sm"] {
96
+ inline-size: min(22rem, calc(100vw - var(--ui-space-2) * 2));
97
+ max-inline-size: min(22rem, calc(100vw - var(--ui-space-2) * 2));
98
+ }
99
+ :scope[data-ui-popover-state~="size=md"] {
100
+ inline-size: min(28rem, calc(100vw - var(--ui-space-2) * 2));
101
+ max-inline-size: min(28rem, calc(100vw - var(--ui-space-2) * 2));
102
+ }
103
+ :scope[data-ui-popover-state~="size=lg"] {
104
+ inline-size: min(36rem, calc(100vw - var(--ui-space-2) * 2));
105
+ max-inline-size: min(36rem, calc(100vw - var(--ui-space-2) * 2));
106
+ }
107
+
95
108
  :scope[hidden] {
96
109
  display: none;
97
110
  }
@@ -37,6 +37,16 @@
37
37
  --_ui-scroll-fade-inline: to left;
38
38
  }
39
39
 
40
+ :scope[data-ui-scroll-area-state~="size=sm"] {
41
+ max-block-size: 9.375rem;
42
+ }
43
+ :scope[data-ui-scroll-area-state~="size=md"] {
44
+ max-block-size: 20rem;
45
+ }
46
+ :scope[data-ui-scroll-area-state~="size=lg"] {
47
+ max-block-size: 30rem;
48
+ }
49
+
40
50
  /* A component that sets its display still honours the hidden attribute on its root. */
41
51
  :scope[hidden] {
42
52
  display: none;
@@ -53,6 +53,15 @@
53
53
  transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);
54
54
  }
55
55
 
56
+ :scope[data-ui-search-result-row-state~="density=compact"] {
57
+ min-block-size: var(--ui-search-result-row-min-height, 3.125rem);
58
+ padding-block: var(--ui-search-result-row-padding-block, var(--ui-space-1));
59
+ padding-inline: var(--ui-search-result-row-padding-inline, var(--ui-space-2));
60
+ gap: var(--ui-search-result-row-gap, var(--ui-space-2));
61
+ align-items: center;
62
+ font-family: var(--ui-font-family-sans, sans-serif);
63
+ }
64
+
56
65
  :scope:hover:enabled {
57
66
  background: var(--ui-search-result-row-hover-surface, color-mix(in srgb, var(--ui-surface) 85%, black 3%));
58
67
  }
@@ -17,6 +17,9 @@
17
17
  margin: 0;
18
18
  }
19
19
 
20
+ :scope[data-ui-stack-state~="gap=none"] {
21
+ --_layout-gap: 0px;
22
+ }
20
23
  :scope[data-ui-stack-state~="gap=xs"] {
21
24
  --_layout-gap: var(--ui-space-2);
22
25
  }
@@ -91,6 +91,14 @@
91
91
  text-align: center;
92
92
  }
93
93
 
94
+ :scope[data-ui-text-state~="font=sans"] {
95
+ font-family: var(--ui-font-family-sans, sans-serif);
96
+ }
97
+
98
+ :scope[data-ui-text-state~="wrap=anywhere"] {
99
+ overflow-wrap: anywhere;
100
+ }
101
+
94
102
  /* A component that sets its display still honours the hidden attribute on its root. */
95
103
  :scope[hidden] {
96
104
  display: none;
@@ -7,7 +7,8 @@ export interface UiCardElement extends HTMLElement {
7
7
  }
8
8
  export interface UiCardProps {
9
9
  as?: "div" | "section" | "article" | "aside" | null;
10
- padding?: "sm" | "md" | "lg" | null;
10
+ padding?: "xs" | "sm" | "md" | "lg" | null;
11
+ size?: "content" | "sm" | "md" | "lg" | null;
11
12
  tone?: "neutral" | "danger" | null;
12
13
  variant?: "outlined" | "subtle" | "elevated" | null;
13
14
  attributes?: Readonly<Record<string, string | number | boolean | null | undefined>>;
package/vanilla/UiCard.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { componentRootIndex, manageComponentLifecycle } from "@nextwebwg/html-next/runtime";
3
3
  import "../styles/ui-card.css";
4
4
 
5
- const definition = {...{"contract":{"tag":"ui-card","props":{"as":{"type":{"kind":"terminal","name":"keyword"},"values":["div","section","article","aside"],"required":false,"target":{"attribute":"as"},"default":"div"},"padding":{"type":{"kind":"terminal","name":"keyword"},"values":["sm","md","lg"],"required":false,"target":{"attribute":"padding"},"default":"md"},"tone":{"type":{"kind":"terminal","name":"keyword"},"values":["neutral","danger"],"required":false,"target":{"attribute":"tone"},"default":"neutral"},"variant":{"type":{"kind":"terminal","name":"keyword"},"values":["outlined","subtle","elevated"],"required":false,"target":{"attribute":"variant"},"default":"outlined"}}},"template":{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"section","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'section'","testPlan":{"source":"as = 'section'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"section"}},"dependencies":["as"]}}},{"kind":"element","name":"article","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'article'","testPlan":{"source":"as = 'article'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"article"}},"dependencies":["as"]}}},{"kind":"element","name":"aside","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'aside'","testPlan":{"source":"as = 'aside'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"aside"}},"dependencies":["as"]}}},{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"else"}}],"flow":{"kind":"match"}},"declarations":[],"root":{"kind":"native","element":"div","choices":["section","article","aside","div"]}},source:{file:import.meta.url},css:""};
5
+ const definition = {...{"contract":{"tag":"ui-card","props":{"as":{"type":{"kind":"terminal","name":"keyword"},"values":["div","section","article","aside"],"required":false,"target":{"attribute":"as"},"default":"div"},"padding":{"type":{"kind":"terminal","name":"keyword"},"values":["xs","sm","md","lg"],"required":false,"target":{"attribute":"padding"},"default":"md"},"size":{"type":{"kind":"terminal","name":"keyword"},"values":["content","sm","md","lg"],"required":false,"target":{"attribute":"size"},"default":"content"},"tone":{"type":{"kind":"terminal","name":"keyword"},"values":["neutral","danger"],"required":false,"target":{"attribute":"tone"},"default":"neutral"},"variant":{"type":{"kind":"terminal","name":"keyword"},"values":["outlined","subtle","elevated"],"required":false,"target":{"attribute":"variant"},"default":"outlined"}}},"template":{"kind":"element","name":"template","attributes":[],"children":[{"kind":"element","name":"section","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'section'","testPlan":{"source":"as = 'section'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"section"}},"dependencies":["as"]}}},{"kind":"element","name":"article","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'article'","testPlan":{"source":"as = 'article'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"article"}},"dependencies":["as"]}}},{"kind":"element","name":"aside","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"when","test":"as = 'aside'","testPlan":{"source":"as = 'aside'","ast":{"kind":"binary","op":"=","left":{"kind":"id","name":"as"},"right":{"kind":"literal","value":"aside"}},"dependencies":["as"]}}},{"kind":"element","name":"div","attributes":[],"children":[{"kind":"slot"}],"flow":{"kind":"else"}}],"flow":{"kind":"match"}},"declarations":[],"root":{"kind":"native","element":"div","choices":["section","article","aside","div"]}},source:{file:import.meta.url},css:""};
6
6
 
7
7
  export function createUiCard(options = {}) {
8
8
  const { attributes = {}, children = [], slots = {}, ...componentProps } = options;