@threadlabs/looma 0.28.6 → 0.28.8
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/components/ui-editor-block-actions/ui-editor-block-actions.html +20 -0
- package/components/ui-editor-block-actions/ui-editor-block-actions.js +14 -0
- package/components/ui-editor-image-toolbar/ui-editor-image-toolbar.html +7 -6
- package/components/ui-editor-image-toolbar/ui-editor-image-toolbar.js +2 -1
- package/components/ui-editor-link-card/ui-editor-link-card.html +57 -0
- package/components/ui-editor-link-card/ui-editor-link-card.js +27 -0
- package/components/ui-editor-link-form/ui-editor-link-form.html +118 -0
- package/components/ui-editor-link-form/ui-editor-link-form.js +71 -0
- package/dist/index.js +37 -34
- package/package.json +1 -1
- package/styles/ui-editor-block-actions.css +1 -0
- package/styles/ui-editor-link-card.css +1 -0
- package/styles/ui-editor-link-form.css +1 -0
- package/vanilla/UiEditorBlockActions.d.ts +16 -0
- package/vanilla/UiEditorBlockActions.js +41 -0
- package/vanilla/UiEditorImageToolbar.js +1 -1
- package/vanilla/UiEditorLinkCard.d.ts +20 -0
- package/vanilla/UiEditorLinkCard.js +153 -0
- package/vanilla/UiEditorLinkForm.d.ts +32 -0
- package/vanilla/UiEditorLinkForm.js +354 -0
- package/vanilla/index.js +3 -0
- package/vue/UiEditorBlockActions.d.ts +33 -0
- package/vue/UiEditorBlockActions.js +2 -0
- package/vue/UiEditorBlockActions.vue +125 -0
- package/vue/UiEditorImageToolbar.vue +5 -6
- package/vue/UiEditorLinkCard.d.ts +58 -0
- package/vue/UiEditorLinkCard.js +2 -0
- package/vue/UiEditorLinkCard.vue +319 -0
- package/vue/UiEditorLinkForm.d.ts +165 -0
- package/vue/UiEditorLinkForm.js +2 -0
- package/vue/UiEditorLinkForm.vue +557 -0
- package/vue/chunks/UiAffordanceScope.js +1 -1
- package/vue/chunks/UiAvatar.js +1 -1
- package/vue/chunks/UiAvatarGroup.js +1 -1
- package/vue/chunks/UiBadge.js +1 -1
- package/vue/chunks/UiBreadcrumbItem.js +1 -1
- package/vue/chunks/UiBreadcrumbs.js +1 -1
- package/vue/chunks/UiButton.js +1 -1
- package/vue/chunks/UiCallout.js +1 -1
- package/vue/chunks/UiCard.js +1 -1
- package/vue/chunks/UiCheckbox.js +1 -1
- package/vue/chunks/UiCluster.js +1 -1
- package/vue/chunks/UiCombobox.js +1 -1
- package/vue/chunks/UiContainer.js +1 -1
- package/vue/chunks/UiContextMenu.js +1 -1
- package/vue/chunks/UiCover.js +1 -1
- package/vue/chunks/UiDescriptionItem.js +1 -1
- package/vue/chunks/UiDescriptionList.js +1 -1
- package/vue/chunks/UiDialog.js +1 -1
- package/vue/chunks/UiDisclosure.js +1 -1
- package/vue/chunks/UiEditable.js +1 -1
- package/vue/chunks/UiEditorBlockActions.js +127 -0
- package/vue/chunks/UiEditorImageToolbar.js +7 -25
- package/vue/chunks/UiEditorInsertTableGrid.js +1 -1
- package/vue/chunks/UiEditorLinkCard.js +356 -0
- package/vue/chunks/UiEditorLinkForm.js +669 -0
- package/vue/chunks/UiEditorMentionMenu.js +1 -1
- package/vue/chunks/UiEditorMentionMenuItem.js +1 -1
- package/vue/chunks/UiEditorSlashMenu.js +1 -1
- package/vue/chunks/UiEditorSlashMenuGroup.js +1 -1
- package/vue/chunks/UiEditorSlashMenuItem.js +1 -1
- package/vue/chunks/UiEditorSurface.js +1 -1
- package/vue/chunks/UiEditorTableContextMenu.js +1 -1
- package/vue/chunks/UiEditorTableOverlay.js +1 -1
- package/vue/chunks/UiEditorTableToolbar.js +1 -1
- package/vue/chunks/UiEditorToolbar.js +1 -1
- package/vue/chunks/UiFloatingActionButton.js +1 -1
- package/vue/chunks/UiFormField.js +1 -1
- package/vue/chunks/UiGrid.js +1 -1
- package/vue/chunks/UiIcon.js +1 -1
- package/vue/chunks/UiIconButton.js +1 -1
- package/vue/chunks/UiImage.js +1 -1
- package/vue/chunks/UiInput.js +1 -1
- package/vue/chunks/UiInputGroup.js +1 -1
- package/vue/chunks/UiList.js +1 -1
- package/vue/chunks/UiListItem.js +1 -1
- package/vue/chunks/UiListbox.js +1 -1
- package/vue/chunks/UiMenu.js +1 -1
- package/vue/chunks/UiMenuGroup.js +1 -1
- package/vue/chunks/UiMenuItem.js +1 -1
- package/vue/chunks/UiMeter.js +1 -1
- package/vue/chunks/UiNavItem.js +1 -1
- package/vue/chunks/UiPageHeader.js +1 -1
- package/vue/chunks/UiPopover.js +1 -1
- package/vue/chunks/UiRadio.js +1 -1
- package/vue/chunks/UiRadioGroup.js +1 -1
- package/vue/chunks/UiReel.js +1 -1
- package/vue/chunks/UiScrollArea.js +1 -1
- package/vue/chunks/UiSearchResultRow.js +1 -1
- package/vue/chunks/UiSearchShell.js +1 -1
- package/vue/chunks/UiSection.js +1 -1
- package/vue/chunks/UiSelect.js +1 -1
- package/vue/chunks/UiSeparator.js +1 -1
- package/vue/chunks/UiSidebar.js +1 -1
- package/vue/chunks/UiSpinner.js +1 -1
- package/vue/chunks/UiStack.js +1 -1
- package/vue/chunks/UiStatusMessage.js +1 -1
- package/vue/chunks/UiSwitch.js +1 -1
- package/vue/chunks/UiSwitcher.js +1 -1
- package/vue/chunks/UiTable.js +1 -1
- package/vue/chunks/UiTabs.js +1 -1
- package/vue/chunks/UiText.js +1 -1
- package/vue/chunks/UiTextarea.js +1 -1
- package/vue/chunks/UiToast.js +1 -1
- package/vue/chunks/UiToastRegion.js +1 -1
- package/vue/chunks/UiTooltip.js +1 -1
- package/vue/chunks/UiTree.js +1 -1
- package/vue/chunks/UiTreeItem.js +1 -1
- package/vue/chunks/_plugin-vue_export-helper.js +1 -1
- package/vue/components.css +2886 -2886
- package/vue/editor/index.js +98 -250
- package/vue/editor/primitives.d.ts +24 -2
- package/vue/index.d.ts +3 -0
- package/vue/index.js +8 -5
package/vue/editor/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { computed, createApp, defineComponent, h, nextTick, onBeforeUnmount, onMounted, reactive, ref, shallowRef, useId, watch } from "vue";
|
|
2
2
|
import { DEFAULT_MENTION_RESULT_LIMIT, LOOMA_CHIP_COLORS, LOOMA_ICONS, createLoomaMentionExtension, createLoomaSlashCommandExtension, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getTableOfContentsEntries, getVisualViewportRect, handleTableAction, handleTableOverlayAction, measureTableOverlayGeometry, normalizeActiveTableColumnWidths, normalizeLoomaChipColor, normalizeTableOfContentsConfig, resolveTableCellAt, siteRelativeHref } from "@threadlabs/looma/editor";
|
|
3
|
-
import { Button, Callout, Card, Checkbox, Cluster, Combobox, Disclosure, EditorImageToolbar, EditorInsertTableGrid, EditorMentionMenu, EditorMentionMenuItem, EditorSlashMenu, EditorSlashMenuGroup, EditorSlashMenuItem, EditorSurface, EditorTableContextMenu, EditorTableOverlay, EditorTableToolbar, EditorToolbar, FormField, Icon, IconButton, Image, Input,
|
|
3
|
+
import { Button, Callout, Card, Checkbox, Cluster, Combobox, Disclosure, EditorBlockActions, EditorImageToolbar, EditorInsertTableGrid, EditorLinkCard, EditorLinkForm, EditorMentionMenu, EditorMentionMenuItem, EditorSlashMenu, EditorSlashMenuGroup, EditorSlashMenuItem, EditorSurface, EditorTableContextMenu, EditorTableOverlay, EditorTableToolbar, EditorToolbar, FormField, Icon, IconButton, Image, Input, List, Menu, MenuItem, Popover, Separator, Stack, Text, Tooltip } from "@threadlabs/looma/vue";
|
|
4
4
|
import { Editor, Extension, Node as Node$1, getText, getTextSerializersFromSchema, isNodeSelection, mergeAttributes, nodeInputRule, posToDOMRect } from "@tiptap/core";
|
|
5
5
|
import { Editor as Editor$1 } from "@tiptap/vue-3";
|
|
6
6
|
import { closeHistory } from "@tiptap/pm/history";
|
|
@@ -22,7 +22,10 @@ var EDITOR_ADAPTER_COMPONENT_TAG_MAP = {
|
|
|
22
22
|
EditorTableToolbar: "ui-editor-table-toolbar",
|
|
23
23
|
EditorInsertTableGrid: "ui-editor-insert-table-grid",
|
|
24
24
|
EditorTableOverlay: "ui-editor-table-overlay",
|
|
25
|
-
EditorImageToolbar: "ui-editor-image-toolbar"
|
|
25
|
+
EditorImageToolbar: "ui-editor-image-toolbar",
|
|
26
|
+
EditorLinkCard: "ui-editor-link-card",
|
|
27
|
+
EditorLinkForm: "ui-editor-link-form",
|
|
28
|
+
EditorBlockActions: "ui-editor-block-actions"
|
|
26
29
|
};
|
|
27
30
|
//#endregion
|
|
28
31
|
//#region src/components/shared/overlay.js
|
|
@@ -2481,11 +2484,14 @@ var LoomaEditor = defineComponent({
|
|
|
2481
2484
|
const fileInput = ref(null);
|
|
2482
2485
|
const tablePickerAnchorId = `looma-editor-table-picker-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
2483
2486
|
const blockActionAnchorId = `ui-block-tools-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
2484
|
-
let blockActionTarget = null;
|
|
2485
2487
|
const linkAnchorId = `looma-editor-link-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
2486
2488
|
const linkPopoverAnchorId = ref(linkAnchorId);
|
|
2487
2489
|
const linkDestinationInput = () => linkFormRoot.value?.querySelector("[data-link-destination]");
|
|
2488
2490
|
const linkFormRoot = ref(null);
|
|
2491
|
+
const setLinkFormRoot = (instance) => {
|
|
2492
|
+
const element = instance?.$el;
|
|
2493
|
+
linkFormRoot.value = element instanceof HTMLElement ? element : null;
|
|
2494
|
+
};
|
|
2489
2495
|
const linkOpen = ref(false);
|
|
2490
2496
|
const linkContextEditing = ref(false);
|
|
2491
2497
|
const linkHref = ref("");
|
|
@@ -2839,17 +2845,6 @@ var LoomaEditor = defineComponent({
|
|
|
2839
2845
|
if (linkTextEditable.value && !linkText.value.trim()) linkText.value = target.label;
|
|
2840
2846
|
applyLink();
|
|
2841
2847
|
};
|
|
2842
|
-
const moveLinkResultFocus = (event, offset) => {
|
|
2843
|
-
const buttons = [...linkFormRoot.value?.querySelectorAll("[data-link-result]") ?? []];
|
|
2844
|
-
const next = buttons[buttons.indexOf(event.target) + offset];
|
|
2845
|
-
if (next) {
|
|
2846
|
-
event.preventDefault();
|
|
2847
|
-
next.focus();
|
|
2848
|
-
} else if (offset < 0) {
|
|
2849
|
-
event.preventDefault();
|
|
2850
|
-
linkFormRoot.value?.querySelector("[data-link-search]")?.focus();
|
|
2851
|
-
}
|
|
2852
|
-
};
|
|
2853
2848
|
const openLinkEditor = (context = false) => {
|
|
2854
2849
|
const instance = editor.value;
|
|
2855
2850
|
if (!instance || !props.editable) return;
|
|
@@ -2962,244 +2957,102 @@ var LoomaEditor = defineComponent({
|
|
|
2962
2957
|
linkPopup?.hide();
|
|
2963
2958
|
formattingPopup?.hide();
|
|
2964
2959
|
};
|
|
2965
|
-
const
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2960
|
+
const linkStatus = () => {
|
|
2961
|
+
if (linkSearching.value) return "Searching…";
|
|
2962
|
+
if (linkSelectedTarget.value) return "";
|
|
2963
|
+
if (linkQuery.value.trim().length < 2) return "Type at least two letters to search.";
|
|
2964
|
+
return linkResults.value.length || linkError.value ? "" : "No results found.";
|
|
2965
|
+
};
|
|
2966
|
+
const renderLinkForm = () => {
|
|
2967
|
+
const shown = linkSelectedTarget.value ? [linkSelectedTarget.value] : linkResults.value;
|
|
2968
|
+
return h(EditorLinkForm, {
|
|
2969
|
+
ref: setLinkFormRoot,
|
|
2970
|
+
class: "looma-editor__link-form",
|
|
2971
|
+
existing: Boolean(linkSelection?.existing),
|
|
2972
|
+
searchable: Boolean(props.linkSearch),
|
|
2973
|
+
mode: linkMode.value,
|
|
2974
|
+
value: props.linkSearch ? linkQuery.value : linkHref.value,
|
|
2975
|
+
placeholder: props.linkSearch ? `Search ${props.linkTargetLabel.toLowerCase()}s or paste a URL…` : "https://example.com",
|
|
2976
|
+
newTab: linkNewTab.value,
|
|
2977
|
+
textEditable: linkTextEditable.value,
|
|
2978
|
+
text: linkText.value,
|
|
2979
|
+
error: linkError.value,
|
|
2980
|
+
status: linkStatus(),
|
|
2981
|
+
results: shown.map(({ id, label, detail }) => detail ? {
|
|
2982
|
+
id,
|
|
2983
|
+
label,
|
|
2984
|
+
detail
|
|
2985
|
+
} : {
|
|
2986
|
+
id,
|
|
2987
|
+
label
|
|
2988
|
+
}),
|
|
2989
|
+
selected: linkSelectedTarget.value?.id ?? "",
|
|
2990
|
+
onDestination: (event) => {
|
|
2991
|
+
const { value } = event.detail;
|
|
2992
|
+
if (props.linkSearch) {
|
|
2993
|
+
linkQuery.value = value;
|
|
2994
|
+
linkMode.value = /^(https?:\/\/|mailto:|tel:)/i.test(value.trim()) || linkSelection?.existing && /^(\/|\.\.?\/|#|\?)/.test(value.trim()) ? "url" : "target";
|
|
2995
|
+
linkSelectedTarget.value = null;
|
|
2996
2996
|
}
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
tone: "secondary",
|
|
3023
|
-
role: "status"
|
|
3024
|
-
}, () => "Searching…") : null,
|
|
3025
|
-
!linkSearching.value && !linkSelectedTarget.value && linkQuery.value.trim().length < 2 ? h(Text, {
|
|
3026
|
-
size: "sm",
|
|
3027
|
-
tone: "secondary"
|
|
3028
|
-
}, () => "Type at least two letters to search.") : null,
|
|
3029
|
-
!linkSearching.value && !linkSelectedTarget.value && linkQuery.value.trim().length >= 2 && !linkResults.value.length && !linkError.value ? h(Text, {
|
|
3030
|
-
size: "sm",
|
|
3031
|
-
tone: "secondary"
|
|
3032
|
-
}, () => "No results found.") : null,
|
|
3033
|
-
...(linkSelectedTarget.value ? [linkSelectedTarget.value] : linkResults.value).map((target) => h(SearchResultRow, {
|
|
3034
|
-
key: target.id,
|
|
3035
|
-
density: "compact",
|
|
3036
|
-
selected: target.id === linkSelectedTarget.value?.id,
|
|
3037
|
-
"data-link-result": "",
|
|
3038
|
-
onClick: () => selectLinkTarget(target),
|
|
3039
|
-
onKeydown: (event) => {
|
|
3040
|
-
if (event.key === "ArrowDown") moveLinkResultFocus(event, 1);
|
|
3041
|
-
if (event.key === "ArrowUp") moveLinkResultFocus(event, -1);
|
|
3042
|
-
}
|
|
3043
|
-
}, {
|
|
3044
|
-
leading: () => loomaIcon("file-text"),
|
|
3045
|
-
title: () => h(Text, {
|
|
3046
|
-
as: "strong",
|
|
3047
|
-
size: "sm",
|
|
3048
|
-
weight: "medium",
|
|
3049
|
-
truncate: true,
|
|
3050
|
-
title: target.label
|
|
3051
|
-
}, () => target.label),
|
|
3052
|
-
meta: () => target.detail ? h(Text, {
|
|
3053
|
-
as: "span",
|
|
3054
|
-
size: "xs",
|
|
3055
|
-
tone: "secondary",
|
|
3056
|
-
truncate: true,
|
|
3057
|
-
title: target.detail
|
|
3058
|
-
}, () => target.detail) : null,
|
|
3059
|
-
trailing: () => target.id === linkSelectedTarget.value?.id ? loomaIcon("check") : null
|
|
3060
|
-
}))
|
|
3061
|
-
]) : h(Checkbox, {
|
|
3062
|
-
size: "sm",
|
|
3063
|
-
checked: linkNewTab.value,
|
|
3064
|
-
onChange: (event) => {
|
|
3065
|
-
linkNewTab.value = event.detail.checked;
|
|
3066
|
-
applyLink();
|
|
3067
|
-
}
|
|
3068
|
-
}, () => "Open in new tab")];
|
|
3069
|
-
const renderLinkForm = () => h("form", {
|
|
3070
|
-
ref: linkFormRoot,
|
|
3071
|
-
class: "looma-editor__link-form",
|
|
3072
|
-
"aria-label": "Edit link",
|
|
3073
|
-
onSubmit: (event) => {
|
|
3074
|
-
event.preventDefault();
|
|
3075
|
-
if (applyLink(true)) dismissLink();
|
|
3076
|
-
},
|
|
3077
|
-
onKeydown: (event) => {
|
|
3078
|
-
if (event.key === "Escape") {
|
|
3079
|
-
event.preventDefault();
|
|
3080
|
-
event.stopPropagation();
|
|
3081
|
-
dismissLink();
|
|
3082
|
-
} else if (event.key === "Enter" && event.target instanceof HTMLInputElement) {
|
|
3083
|
-
event.preventDefault();
|
|
3084
|
-
event.stopPropagation();
|
|
2997
|
+
linkHref.value = value;
|
|
2998
|
+
linkError.value = "";
|
|
2999
|
+
applyLink();
|
|
3000
|
+
},
|
|
3001
|
+
onClear: () => {
|
|
3002
|
+
linkQuery.value = "";
|
|
3003
|
+
linkHref.value = "";
|
|
3004
|
+
linkMode.value = "target";
|
|
3005
|
+
linkSelectedTarget.value = null;
|
|
3006
|
+
linkError.value = "";
|
|
3007
|
+
},
|
|
3008
|
+
onChoose: (event) => {
|
|
3009
|
+
const target = shown.find(({ id }) => id === event.detail.id);
|
|
3010
|
+
if (target) selectLinkTarget(target);
|
|
3011
|
+
},
|
|
3012
|
+
onNewTab: (event) => {
|
|
3013
|
+
linkNewTab.value = event.detail.newTab;
|
|
3014
|
+
applyLink();
|
|
3015
|
+
},
|
|
3016
|
+
onText: (event) => {
|
|
3017
|
+
linkText.value = event.detail.text;
|
|
3018
|
+
linkError.value = "";
|
|
3019
|
+
applyLink();
|
|
3020
|
+
},
|
|
3021
|
+
onSave: () => {
|
|
3085
3022
|
if (applyLink(true)) dismissLink();
|
|
3086
|
-
}
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
h(Stack, { gap: "s" }, () => renderLinkDestination(linkMode.value)),
|
|
3095
|
-
linkTextEditable.value ? h(FormField, {}, {
|
|
3096
|
-
label: () => h("label", "Text"),
|
|
3097
|
-
default: () => h(Input, {
|
|
3098
|
-
size: "sm",
|
|
3099
|
-
value: linkText.value,
|
|
3100
|
-
onInput: (event) => {
|
|
3101
|
-
linkText.value = event.target.value;
|
|
3102
|
-
linkError.value = "";
|
|
3103
|
-
applyLink();
|
|
3104
|
-
}
|
|
3105
|
-
})
|
|
3106
|
-
}) : null,
|
|
3107
|
-
linkError.value ? h(Text, {
|
|
3023
|
+
},
|
|
3024
|
+
onDismiss: () => dismissLink()
|
|
3025
|
+
});
|
|
3026
|
+
};
|
|
3027
|
+
const renderLinkContextCard = (instance) => {
|
|
3028
|
+
if (linkContextEditing.value) return h(Card, {
|
|
3029
|
+
variant: "elevated",
|
|
3030
|
+
padding: "sm",
|
|
3108
3031
|
size: "sm",
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
}, () => linkError.value) : null
|
|
3112
|
-
])]);
|
|
3113
|
-
const renderLinkContext = (instance) => {
|
|
3114
|
-
if (linkContextEditing.value) return renderLinkForm();
|
|
3032
|
+
class: "looma-editor__link-context"
|
|
3033
|
+
}, () => [renderLinkForm()]);
|
|
3115
3034
|
const rawHref = instance.getAttributes("link").href;
|
|
3116
3035
|
const href = typeof rawHref === "string" ? rawHref : "";
|
|
3117
|
-
const safeHref = validLinkHref(href);
|
|
3118
|
-
const editId = `${toolbarScope}-link-edit`;
|
|
3119
|
-
const removeId = `${toolbarScope}-link-remove`;
|
|
3120
|
-
const openId = `${toolbarScope}-link-open`;
|
|
3121
3036
|
const target = linkContextTarget.value;
|
|
3122
|
-
return h(
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
"aria-label": `${target ? props.linkTargetLabel : "URL"}: ${target?.label ?? href}`
|
|
3133
|
-
}, () => [h(Text, {
|
|
3134
|
-
as: "strong",
|
|
3135
|
-
size: "sm",
|
|
3136
|
-
weight: "medium",
|
|
3137
|
-
font: "sans",
|
|
3138
|
-
wrap: "anywhere"
|
|
3139
|
-
}, () => target?.label ?? href), target?.detail ? h(Text, {
|
|
3140
|
-
as: "small",
|
|
3141
|
-
size: "xs",
|
|
3142
|
-
tone: "secondary",
|
|
3143
|
-
font: "sans"
|
|
3144
|
-
}, () => target.detail) : null]),
|
|
3145
|
-
safeHref ? h(Button, {
|
|
3146
|
-
id: openId,
|
|
3147
|
-
as: "a",
|
|
3148
|
-
variant: "ghost",
|
|
3149
|
-
tone: "neutral",
|
|
3150
|
-
size: "sm",
|
|
3151
|
-
href: safeHref,
|
|
3152
|
-
target: "_blank",
|
|
3153
|
-
rel: "noopener noreferrer",
|
|
3154
|
-
"aria-label": "Open link"
|
|
3155
|
-
}, () => h(Cluster, {
|
|
3156
|
-
gap: "xs",
|
|
3157
|
-
wrap: "nowrap"
|
|
3158
|
-
}, () => [loomaIcon("external-link"), "Open link"])) : null,
|
|
3159
|
-
safeHref ? h(Tooltip, { for: openId }, () => "Open link") : null,
|
|
3160
|
-
h(IconButton, {
|
|
3161
|
-
id: editId,
|
|
3162
|
-
label: "Edit link",
|
|
3163
|
-
variant: "ghost",
|
|
3164
|
-
size: "sm",
|
|
3165
|
-
onPointerdown: (event) => event.preventDefault(),
|
|
3166
|
-
onClick: () => openLinkEditor(true)
|
|
3167
|
-
}, () => loomaIcon("pencil")),
|
|
3168
|
-
h(Tooltip, { for: editId }, () => "Edit link"),
|
|
3169
|
-
h(IconButton, {
|
|
3170
|
-
id: removeId,
|
|
3171
|
-
label: "Remove link",
|
|
3172
|
-
variant: "ghost",
|
|
3173
|
-
size: "sm",
|
|
3174
|
-
onPointerdown: (event) => event.preventDefault(),
|
|
3175
|
-
onClick: removeCurrentLink
|
|
3176
|
-
}, () => loomaIcon("unlink")),
|
|
3177
|
-
h(Tooltip, { for: removeId }, () => "Remove link")
|
|
3178
|
-
]);
|
|
3179
|
-
};
|
|
3180
|
-
const renderLinkContextCard = (instance) => h(Card, {
|
|
3181
|
-
variant: "elevated",
|
|
3182
|
-
padding: linkContextEditing.value ? "sm" : "xs",
|
|
3183
|
-
size: linkContextEditing.value ? "sm" : "content",
|
|
3184
|
-
class: ["looma-editor__link-context", { "looma-editor__link-context--editing": linkContextEditing.value }]
|
|
3185
|
-
}, () => [renderLinkContext(instance)]);
|
|
3186
|
-
const captureBlockAction = () => {
|
|
3187
|
-
const instance = editor.value;
|
|
3188
|
-
const head = instance?.state.selection.$head;
|
|
3189
|
-
const position = head && head.depth > 0 ? head.before(1) : null;
|
|
3190
|
-
blockActionTarget = position === null ? null : {
|
|
3191
|
-
position,
|
|
3192
|
-
node: instance?.state.doc.nodeAt(position) ?? null
|
|
3193
|
-
};
|
|
3037
|
+
return h(EditorLinkCard, {
|
|
3038
|
+
class: "looma-editor__link-context",
|
|
3039
|
+
href,
|
|
3040
|
+
openHref: validLinkHref(href) ?? "",
|
|
3041
|
+
label: target?.label ?? "",
|
|
3042
|
+
detail: target?.detail ?? "",
|
|
3043
|
+
targetLabel: props.linkTargetLabel,
|
|
3044
|
+
onEdit: () => openLinkEditor(true),
|
|
3045
|
+
onRemove: removeCurrentLink
|
|
3046
|
+
});
|
|
3194
3047
|
};
|
|
3195
3048
|
const runBlockAction = (value) => {
|
|
3196
3049
|
const instance = editor.value;
|
|
3197
|
-
const
|
|
3198
|
-
if (!instance || !
|
|
3050
|
+
const head = instance?.state.selection.$head;
|
|
3051
|
+
if (!instance || !head || head.depth === 0 || !props.editable) return;
|
|
3199
3052
|
const { state } = instance;
|
|
3200
|
-
const
|
|
3053
|
+
const position = head.before(1);
|
|
3201
3054
|
const block = state.doc.nodeAt(position);
|
|
3202
|
-
if (!block
|
|
3055
|
+
if (!block) return;
|
|
3203
3056
|
const end = position + block.nodeSize;
|
|
3204
3057
|
const transaction = state.tr;
|
|
3205
3058
|
let focusAt = end + 1;
|
|
@@ -4323,16 +4176,11 @@ var LoomaEditor = defineComponent({
|
|
|
4323
4176
|
formatOpen.value = false;
|
|
4324
4177
|
}
|
|
4325
4178
|
}, () => instance ? renderToolbar(instance, true, false, true) : null) : null,
|
|
4326
|
-
h(
|
|
4179
|
+
h(EditorBlockActions, {
|
|
4327
4180
|
for: blockActionAnchorId,
|
|
4328
4181
|
placement: mobile.value ? "top-start" : "bottom-start",
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
}, () => [
|
|
4332
|
-
h(MenuItem, { value: "insert-below" }, () => "Insert paragraph below"),
|
|
4333
|
-
h(MenuItem, { value: "duplicate" }, () => "Duplicate block"),
|
|
4334
|
-
h(MenuItem, { value: "delete" }, () => "Delete block")
|
|
4335
|
-
]),
|
|
4182
|
+
onAction: (event) => runBlockAction(event.detail.action)
|
|
4183
|
+
}),
|
|
4336
4184
|
h(Popover, {
|
|
4337
4185
|
class: "looma-editor__table-picker-popover",
|
|
4338
4186
|
open: tablePickerOpen.value,
|
|
@@ -4462,4 +4310,4 @@ var LoomaEditor = defineComponent({
|
|
|
4462
4310
|
}
|
|
4463
4311
|
});
|
|
4464
4312
|
//#endregion
|
|
4465
|
-
export { EDITOR_ADAPTER_COMPONENT_TAG_MAP, EditorImageToolbar, EditorInsertTableGrid, EditorMentionMenu, EditorMentionMenuItem, EditorSlashMenu, EditorSlashMenuGroup, EditorSlashMenuItem, EditorTableContextMenu, EditorTableOverlay, EditorTableToolbar, EditorToolbar, LoomaEditor };
|
|
4313
|
+
export { EDITOR_ADAPTER_COMPONENT_TAG_MAP, EditorBlockActions, EditorImageToolbar, EditorInsertTableGrid, EditorLinkCard, EditorLinkForm, EditorMentionMenu, EditorMentionMenuItem, EditorSlashMenu, EditorSlashMenuGroup, EditorSlashMenuItem, EditorTableContextMenu, EditorTableOverlay, EditorTableToolbar, EditorToolbar, LoomaEditor };
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
* `@threadlabs/looma/vue`, re-exported beside the editor that composes them.
|
|
4
4
|
*/
|
|
5
5
|
import type { InsertTableEventDetail, MentionMenuHighlightEventDetail, MentionMenuSelectEventDetail, SlashMenuHighlightEventDetail, SlashMenuSelectEventDetail, TableContextMenuActionEventDetail } from "@threadlabs/looma/editor";
|
|
6
|
-
export { EditorImageToolbar, EditorInsertTableGrid, EditorMentionMenu, EditorMentionMenuItem, EditorSlashMenu, EditorSlashMenuGroup, EditorSlashMenuItem, EditorTableContextMenu, EditorTableOverlay, EditorTableToolbar, EditorToolbar, } from "@threadlabs/looma/vue";
|
|
6
|
+
export { EditorBlockActions, EditorImageToolbar, EditorInsertTableGrid, EditorLinkCard, EditorLinkForm, EditorMentionMenu, EditorMentionMenuItem, EditorSlashMenu, EditorSlashMenuGroup, EditorSlashMenuItem, EditorTableContextMenu, EditorTableOverlay, EditorTableToolbar, EditorToolbar, } from "@threadlabs/looma/vue";
|
|
7
7
|
/** The editor components' event details, by event name. */
|
|
8
8
|
export interface VueEditorAdapterEventMap {
|
|
9
9
|
highlight: MentionMenuHighlightEventDetail | SlashMenuHighlightEventDetail;
|
|
10
10
|
select: MentionMenuSelectEventDetail | SlashMenuSelectEventDetail;
|
|
11
|
-
action: TableContextMenuActionEventDetail
|
|
11
|
+
action: TableContextMenuActionEventDetail | {
|
|
12
|
+
action: "insert-below" | "duplicate" | "delete";
|
|
13
|
+
};
|
|
12
14
|
insert: InsertTableEventDetail;
|
|
13
15
|
placement: {
|
|
14
16
|
placement: "block" | "center" | "wrap-left" | "wrap-right";
|
|
@@ -17,6 +19,23 @@ export interface VueEditorAdapterEventMap {
|
|
|
17
19
|
alt: string;
|
|
18
20
|
};
|
|
19
21
|
delete: Record<string, never>;
|
|
22
|
+
edit: Record<string, never>;
|
|
23
|
+
remove: Record<string, never>;
|
|
24
|
+
destination: {
|
|
25
|
+
value: string;
|
|
26
|
+
};
|
|
27
|
+
text: {
|
|
28
|
+
text: string;
|
|
29
|
+
};
|
|
30
|
+
"new-tab": {
|
|
31
|
+
newTab: boolean;
|
|
32
|
+
};
|
|
33
|
+
choose: {
|
|
34
|
+
id: string;
|
|
35
|
+
};
|
|
36
|
+
clear: Record<string, never>;
|
|
37
|
+
save: Record<string, never>;
|
|
38
|
+
dismiss: Record<string, never>;
|
|
20
39
|
"add-row-before": {
|
|
21
40
|
boundaryIndex: number;
|
|
22
41
|
};
|
|
@@ -81,4 +100,7 @@ export declare const EDITOR_ADAPTER_COMPONENT_TAG_MAP: {
|
|
|
81
100
|
readonly EditorInsertTableGrid: "ui-editor-insert-table-grid";
|
|
82
101
|
readonly EditorTableOverlay: "ui-editor-table-overlay";
|
|
83
102
|
readonly EditorImageToolbar: "ui-editor-image-toolbar";
|
|
103
|
+
readonly EditorLinkCard: "ui-editor-link-card";
|
|
104
|
+
readonly EditorLinkForm: "ui-editor-link-form";
|
|
105
|
+
readonly EditorBlockActions: "ui-editor-block-actions";
|
|
84
106
|
};
|
package/vue/index.d.ts
CHANGED
|
@@ -19,8 +19,11 @@ export { default as DescriptionList } from "./UiDescriptionList.js";
|
|
|
19
19
|
export { default as Dialog } from "./UiDialog.js";
|
|
20
20
|
export { default as Disclosure } from "./UiDisclosure.js";
|
|
21
21
|
export { default as Editable } from "./UiEditable.js";
|
|
22
|
+
export { default as EditorBlockActions } from "./UiEditorBlockActions.js";
|
|
22
23
|
export { default as EditorImageToolbar } from "./UiEditorImageToolbar.js";
|
|
23
24
|
export { default as EditorInsertTableGrid } from "./UiEditorInsertTableGrid.js";
|
|
25
|
+
export { default as EditorLinkCard } from "./UiEditorLinkCard.js";
|
|
26
|
+
export { default as EditorLinkForm } from "./UiEditorLinkForm.js";
|
|
24
27
|
export { default as EditorMentionMenu } from "./UiEditorMentionMenu.js";
|
|
25
28
|
export { default as EditorMentionMenuItem } from "./UiEditorMentionMenuItem.js";
|
|
26
29
|
export { default as EditorSlashMenu } from "./UiEditorSlashMenu.js";
|
package/vue/index.js
CHANGED
|
@@ -23,6 +23,9 @@ import { t as UiScrollArea_default } from "./chunks/UiScrollArea.js";
|
|
|
23
23
|
import { t as UiDialog_default } from "./chunks/UiDialog.js";
|
|
24
24
|
import { t as UiDisclosure_default } from "./chunks/UiDisclosure.js";
|
|
25
25
|
import { t as UiEditable_default } from "./chunks/UiEditable.js";
|
|
26
|
+
import { t as UiMenu_default } from "./chunks/UiMenu.js";
|
|
27
|
+
import { t as UiMenuItem_default } from "./chunks/UiMenuItem.js";
|
|
28
|
+
import { t as UiEditorBlockActions_default } from "./chunks/UiEditorBlockActions.js";
|
|
26
29
|
import { t as UiEditorToolbar_default } from "./chunks/UiEditorToolbar.js";
|
|
27
30
|
import { t as UiFormField_default } from "./chunks/UiFormField.js";
|
|
28
31
|
import { t as UiIconButton_default } from "./chunks/UiIconButton.js";
|
|
@@ -32,6 +35,10 @@ import { t as UiStack_default } from "./chunks/UiStack.js";
|
|
|
32
35
|
import { t as UiText_default } from "./chunks/UiText.js";
|
|
33
36
|
import { t as UiEditorImageToolbar_default } from "./chunks/UiEditorImageToolbar.js";
|
|
34
37
|
import { t as UiEditorInsertTableGrid_default } from "./chunks/UiEditorInsertTableGrid.js";
|
|
38
|
+
import { t as UiEditorLinkCard_default } from "./chunks/UiEditorLinkCard.js";
|
|
39
|
+
import { t as UiInputGroup_default } from "./chunks/UiInputGroup.js";
|
|
40
|
+
import { t as UiSearchResultRow_default } from "./chunks/UiSearchResultRow.js";
|
|
41
|
+
import { t as UiEditorLinkForm_default } from "./chunks/UiEditorLinkForm.js";
|
|
35
42
|
import { t as UiEditorMentionMenu_default } from "./chunks/UiEditorMentionMenu.js";
|
|
36
43
|
import { t as UiEditorMentionMenuItem_default } from "./chunks/UiEditorMentionMenuItem.js";
|
|
37
44
|
import { t as UiEditorSlashMenu_default } from "./chunks/UiEditorSlashMenu.js";
|
|
@@ -44,20 +51,16 @@ import { t as UiEditorTableToolbar_default } from "./chunks/UiEditorTableToolbar
|
|
|
44
51
|
import { t as UiFloatingActionButton_default } from "./chunks/UiFloatingActionButton.js";
|
|
45
52
|
import { t as UiGrid_default } from "./chunks/UiGrid.js";
|
|
46
53
|
import { t as UiImage_default } from "./chunks/UiImage.js";
|
|
47
|
-
import { t as UiInputGroup_default } from "./chunks/UiInputGroup.js";
|
|
48
54
|
import { t as UiList_default } from "./chunks/UiList.js";
|
|
49
55
|
import { t as UiListItem_default } from "./chunks/UiListItem.js";
|
|
50
56
|
import { t as UiListbox_default } from "./chunks/UiListbox.js";
|
|
51
|
-
import { t as UiMenu_default } from "./chunks/UiMenu.js";
|
|
52
57
|
import { t as UiMenuGroup_default } from "./chunks/UiMenuGroup.js";
|
|
53
|
-
import { t as UiMenuItem_default } from "./chunks/UiMenuItem.js";
|
|
54
58
|
import { t as UiMeter_default } from "./chunks/UiMeter.js";
|
|
55
59
|
import { t as UiNavItem_default } from "./chunks/UiNavItem.js";
|
|
56
60
|
import { t as UiPageHeader_default } from "./chunks/UiPageHeader.js";
|
|
57
61
|
import { t as UiRadio_default } from "./chunks/UiRadio.js";
|
|
58
62
|
import { t as UiRadioGroup_default } from "./chunks/UiRadioGroup.js";
|
|
59
63
|
import { t as UiReel_default } from "./chunks/UiReel.js";
|
|
60
|
-
import { t as UiSearchResultRow_default } from "./chunks/UiSearchResultRow.js";
|
|
61
64
|
import { t as UiSearchShell_default } from "./chunks/UiSearchShell.js";
|
|
62
65
|
import { t as UiSection_default } from "./chunks/UiSection.js";
|
|
63
66
|
import { t as UiSelect_default } from "./chunks/UiSelect.js";
|
|
@@ -75,4 +78,4 @@ import { t as UiTopBar_default } from "./chunks/UiTopBar.js";
|
|
|
75
78
|
import { t as UiTree_default } from "./chunks/UiTree.js";
|
|
76
79
|
import { t as UiTreeItem_default } from "./chunks/UiTreeItem.js";
|
|
77
80
|
import { trackInputModality } from "@threadlabs/looma/components/shared/input-modality.js";
|
|
78
|
-
export { UiActionBar_default as ActionBar, UiAffordanceScope_default as AffordanceScope, UiAvatar_default as Avatar, UiAvatarGroup_default as AvatarGroup, UiBadge_default as Badge, UiBreadcrumbItem_default as BreadcrumbItem, UiBreadcrumbs_default as Breadcrumbs, UiButton_default as Button, UiCallout_default as Callout, UiCard_default as Card, UiCheckbox_default as Checkbox, UiCluster_default as Cluster, UiCombobox_default as Combobox, UiContainer_default as Container, UiContextMenu_default as ContextMenu, UiCover_default as Cover, UiDescriptionItem_default as DescriptionItem, UiDescriptionList_default as DescriptionList, UiDialog_default as Dialog, UiDisclosure_default as Disclosure, UiEditable_default as Editable, UiEditorImageToolbar_default as EditorImageToolbar, UiEditorInsertTableGrid_default as EditorInsertTableGrid, UiEditorMentionMenu_default as EditorMentionMenu, UiEditorMentionMenuItem_default as EditorMentionMenuItem, UiEditorSlashMenu_default as EditorSlashMenu, UiEditorSlashMenuGroup_default as EditorSlashMenuGroup, UiEditorSlashMenuItem_default as EditorSlashMenuItem, UiEditorSurface_default as EditorSurface, UiEditorTableContextMenu_default as EditorTableContextMenu, UiEditorTableOverlay_default as EditorTableOverlay, UiEditorTableToolbar_default as EditorTableToolbar, UiEditorToolbar_default as EditorToolbar, UiFloatingActionButton_default as FloatingActionButton, UiFormField_default as FormField, UiGrid_default as Grid, UiIcon_default as Icon, UiIconButton_default as IconButton, UiImage_default as Image, UiInput_default as Input, UiInputGroup_default as InputGroup, UiList_default as List, UiListItem_default as ListItem, UiListbox_default as Listbox, UiMenu_default as Menu, UiMenuGroup_default as MenuGroup, UiMenuItem_default as MenuItem, UiMeter_default as Meter, UiNavItem_default as NavItem, UiPageHeader_default as PageHeader, UiPopover_default as Popover, UiRadio_default as Radio, UiRadioGroup_default as RadioGroup, UiReel_default as Reel, UiScrollArea_default as ScrollArea, UiSearchResultRow_default as SearchResultRow, UiSearchShell_default as SearchShell, UiSection_default as Section, UiSelect_default as Select, UiSeparator_default as Separator, UiSidebar_default as Sidebar, UiSpinner_default as Spinner, UiStack_default as Stack, UiStatusMessage_default as StatusMessage, UiSwitch_default as Switch, UiSwitcher_default as Switcher, UiTable_default as Table, UiTabs_default as Tabs, UiText_default as Text, UiTextarea_default as Textarea, UiToast_default as Toast, UiToastRegion_default as ToastRegion, UiTooltip_default as Tooltip, UiTopBar_default as TopBar, UiTree_default as Tree, UiTreeItem_default as TreeItem, trackInputModality };
|
|
81
|
+
export { UiActionBar_default as ActionBar, UiAffordanceScope_default as AffordanceScope, UiAvatar_default as Avatar, UiAvatarGroup_default as AvatarGroup, UiBadge_default as Badge, UiBreadcrumbItem_default as BreadcrumbItem, UiBreadcrumbs_default as Breadcrumbs, UiButton_default as Button, UiCallout_default as Callout, UiCard_default as Card, UiCheckbox_default as Checkbox, UiCluster_default as Cluster, UiCombobox_default as Combobox, UiContainer_default as Container, UiContextMenu_default as ContextMenu, UiCover_default as Cover, UiDescriptionItem_default as DescriptionItem, UiDescriptionList_default as DescriptionList, UiDialog_default as Dialog, UiDisclosure_default as Disclosure, UiEditable_default as Editable, UiEditorBlockActions_default as EditorBlockActions, UiEditorImageToolbar_default as EditorImageToolbar, UiEditorInsertTableGrid_default as EditorInsertTableGrid, UiEditorLinkCard_default as EditorLinkCard, UiEditorLinkForm_default as EditorLinkForm, UiEditorMentionMenu_default as EditorMentionMenu, UiEditorMentionMenuItem_default as EditorMentionMenuItem, UiEditorSlashMenu_default as EditorSlashMenu, UiEditorSlashMenuGroup_default as EditorSlashMenuGroup, UiEditorSlashMenuItem_default as EditorSlashMenuItem, UiEditorSurface_default as EditorSurface, UiEditorTableContextMenu_default as EditorTableContextMenu, UiEditorTableOverlay_default as EditorTableOverlay, UiEditorTableToolbar_default as EditorTableToolbar, UiEditorToolbar_default as EditorToolbar, UiFloatingActionButton_default as FloatingActionButton, UiFormField_default as FormField, UiGrid_default as Grid, UiIcon_default as Icon, UiIconButton_default as IconButton, UiImage_default as Image, UiInput_default as Input, UiInputGroup_default as InputGroup, UiList_default as List, UiListItem_default as ListItem, UiListbox_default as Listbox, UiMenu_default as Menu, UiMenuGroup_default as MenuGroup, UiMenuItem_default as MenuItem, UiMeter_default as Meter, UiNavItem_default as NavItem, UiPageHeader_default as PageHeader, UiPopover_default as Popover, UiRadio_default as Radio, UiRadioGroup_default as RadioGroup, UiReel_default as Reel, UiScrollArea_default as ScrollArea, UiSearchResultRow_default as SearchResultRow, UiSearchShell_default as SearchShell, UiSection_default as Section, UiSelect_default as Select, UiSeparator_default as Separator, UiSidebar_default as Sidebar, UiSpinner_default as Spinner, UiStack_default as Stack, UiStatusMessage_default as StatusMessage, UiSwitch_default as Switch, UiSwitcher_default as Switcher, UiTable_default as Table, UiTabs_default as Tabs, UiText_default as Text, UiTextarea_default as Textarea, UiToast_default as Toast, UiToastRegion_default as ToastRegion, UiTooltip_default as Tooltip, UiTopBar_default as TopBar, UiTree_default as Tree, UiTreeItem_default as TreeItem, trackInputModality };
|