@threadlabs/looma 0.22.11 → 0.22.12
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/package.json +1 -1
- package/vue/components.css +63 -4
- package/vue/editor/LoomaEditor.d.ts +48 -0
- package/vue/editor/index.d.ts +1 -1
- package/vue/editor/index.js +165 -7
package/package.json
CHANGED
package/vue/components.css
CHANGED
|
@@ -9070,18 +9070,26 @@ html[data-ui-input-modality="touch"]
|
|
|
9070
9070
|
|
|
9071
9071
|
.looma-editor__link-context-actions {
|
|
9072
9072
|
display: flex;
|
|
9073
|
+
flex-wrap: wrap;
|
|
9073
9074
|
align-items: center;
|
|
9074
9075
|
gap: var(--ui-space-1);
|
|
9075
9076
|
}
|
|
9076
9077
|
|
|
9077
9078
|
.looma-editor__link-context-url {
|
|
9078
9079
|
min-width: 0;
|
|
9079
|
-
|
|
9080
|
-
overflow: hidden;
|
|
9080
|
+
flex: 1 1 100%;
|
|
9081
9081
|
padding-inline: var(--ui-space-2);
|
|
9082
9082
|
color: var(--ui-text-secondary);
|
|
9083
|
-
|
|
9084
|
-
|
|
9083
|
+
overflow-wrap: anywhere;
|
|
9084
|
+
font-size: var(--ui-font-size-sm);
|
|
9085
|
+
}
|
|
9086
|
+
|
|
9087
|
+
.looma-editor__link-context-url :is(strong, small) {
|
|
9088
|
+
display: block;
|
|
9089
|
+
}
|
|
9090
|
+
|
|
9091
|
+
.looma-editor__link-context-url strong {
|
|
9092
|
+
color: var(--ui-text-primary);
|
|
9085
9093
|
}
|
|
9086
9094
|
|
|
9087
9095
|
.looma-editor__link-context-actions :is(button, a) {
|
|
@@ -9198,6 +9206,57 @@ html[data-ui-input-modality="touch"]
|
|
|
9198
9206
|
align-items: center;
|
|
9199
9207
|
}
|
|
9200
9208
|
|
|
9209
|
+
.looma-editor__link-modes {
|
|
9210
|
+
display: flex;
|
|
9211
|
+
gap: var(--ui-space-1);
|
|
9212
|
+
}
|
|
9213
|
+
|
|
9214
|
+
.looma-editor__link-modes button,
|
|
9215
|
+
.looma-editor__link-results button {
|
|
9216
|
+
min-height: var(--ui-control-min-block-size);
|
|
9217
|
+
padding: var(--ui-space-2);
|
|
9218
|
+
border: 1px solid var(--ui-control-border);
|
|
9219
|
+
border-radius: var(--ui-field-radius, var(--ui-radius-md));
|
|
9220
|
+
background: var(--ui-control-surface);
|
|
9221
|
+
color: var(--ui-text-primary);
|
|
9222
|
+
font: inherit;
|
|
9223
|
+
text-align: left;
|
|
9224
|
+
cursor: pointer;
|
|
9225
|
+
}
|
|
9226
|
+
|
|
9227
|
+
.looma-editor__link-modes button[aria-pressed="true"] {
|
|
9228
|
+
border-color: var(--ui-accent);
|
|
9229
|
+
color: var(--ui-accent);
|
|
9230
|
+
}
|
|
9231
|
+
|
|
9232
|
+
.looma-editor__link-results {
|
|
9233
|
+
display: flex;
|
|
9234
|
+
flex-direction: column;
|
|
9235
|
+
gap: var(--ui-space-1);
|
|
9236
|
+
max-height: 15rem;
|
|
9237
|
+
overflow-y: auto;
|
|
9238
|
+
}
|
|
9239
|
+
|
|
9240
|
+
.looma-editor__link-results p {
|
|
9241
|
+
margin: 0;
|
|
9242
|
+
color: var(--ui-text-secondary);
|
|
9243
|
+
font-size: var(--ui-font-size-sm);
|
|
9244
|
+
}
|
|
9245
|
+
|
|
9246
|
+
.looma-editor__link-results button {
|
|
9247
|
+
display: flex;
|
|
9248
|
+
flex-direction: column;
|
|
9249
|
+
width: 100%;
|
|
9250
|
+
}
|
|
9251
|
+
|
|
9252
|
+
.looma-editor__link-results button:is(:hover, :focus-visible) {
|
|
9253
|
+
background: var(--ui-surface-subtle);
|
|
9254
|
+
}
|
|
9255
|
+
|
|
9256
|
+
.looma-editor__link-results button small {
|
|
9257
|
+
color: var(--ui-text-secondary);
|
|
9258
|
+
}
|
|
9259
|
+
|
|
9201
9260
|
.looma-editor__link-error {
|
|
9202
9261
|
margin: 0;
|
|
9203
9262
|
color: var(--ui-field-danger, var(--ui-danger));
|
|
@@ -26,6 +26,25 @@ export type LoomaImageUploader = (file: File) => Promise<string | LoomaImageUplo
|
|
|
26
26
|
* bubble for selections); it does not alter document commands or stored content.
|
|
27
27
|
*/
|
|
28
28
|
export type LoomaEditorToolbarMode = "bubble" | "sticky" | "popover";
|
|
29
|
+
/** A destination supplied by the host application, such as a page or record. */
|
|
30
|
+
export interface LoomaLinkTarget {
|
|
31
|
+
id: string;
|
|
32
|
+
label: string;
|
|
33
|
+
detail?: string;
|
|
34
|
+
href: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Finds host records for a link without teaching the editor how they are stored.
|
|
38
|
+
* @ownership The host checks access and returns durable, openable href values.
|
|
39
|
+
* @failure A rejection leaves the existing document untouched and shows a retryable search error.
|
|
40
|
+
*/
|
|
41
|
+
export type LoomaLinkSearch = (query: string) => Promise<LoomaLinkTarget[]>;
|
|
42
|
+
/**
|
|
43
|
+
* Describes a saved host link so a renamed record can show its current label.
|
|
44
|
+
* @ownership The host resolves identity and access; Looma keeps the saved href as is.
|
|
45
|
+
* @failure A rejection leaves the original href visible and editable.
|
|
46
|
+
*/
|
|
47
|
+
export type LoomaLinkResolve = (href: string) => Promise<LoomaLinkTarget | null>;
|
|
29
48
|
/**
|
|
30
49
|
* Turnkey Vue editor that composes Looma's framework-neutral Tiptap extensions
|
|
31
50
|
* with declarative menus, image delivery, and table interaction chrome.
|
|
@@ -88,6 +107,19 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
|
|
|
88
107
|
type: NumberConstructor;
|
|
89
108
|
default: number;
|
|
90
109
|
};
|
|
110
|
+
/** Host-owned search and identity lookup for links to application records. */
|
|
111
|
+
linkSearch: {
|
|
112
|
+
type: PropType<LoomaLinkSearch | undefined>;
|
|
113
|
+
default: undefined;
|
|
114
|
+
};
|
|
115
|
+
linkResolve: {
|
|
116
|
+
type: PropType<LoomaLinkResolve | undefined>;
|
|
117
|
+
default: undefined;
|
|
118
|
+
};
|
|
119
|
+
linkTargetLabel: {
|
|
120
|
+
type: StringConstructor;
|
|
121
|
+
default: string;
|
|
122
|
+
};
|
|
91
123
|
uploadImage: {
|
|
92
124
|
type: PropType<LoomaImageUploader | undefined>;
|
|
93
125
|
default: undefined;
|
|
@@ -181,6 +213,19 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
|
|
|
181
213
|
type: NumberConstructor;
|
|
182
214
|
default: number;
|
|
183
215
|
};
|
|
216
|
+
/** Host-owned search and identity lookup for links to application records. */
|
|
217
|
+
linkSearch: {
|
|
218
|
+
type: PropType<LoomaLinkSearch | undefined>;
|
|
219
|
+
default: undefined;
|
|
220
|
+
};
|
|
221
|
+
linkResolve: {
|
|
222
|
+
type: PropType<LoomaLinkResolve | undefined>;
|
|
223
|
+
default: undefined;
|
|
224
|
+
};
|
|
225
|
+
linkTargetLabel: {
|
|
226
|
+
type: StringConstructor;
|
|
227
|
+
default: string;
|
|
228
|
+
};
|
|
184
229
|
uploadImage: {
|
|
185
230
|
type: PropType<LoomaImageUploader | undefined>;
|
|
186
231
|
default: undefined;
|
|
@@ -233,6 +278,9 @@ export declare const LoomaEditor: import("vue").DefineComponent<import("vue").Ex
|
|
|
233
278
|
mentionItems: LoomaMentionItem[];
|
|
234
279
|
mentionProvider: LoomaMentionProvider | undefined;
|
|
235
280
|
mentionLimit: number;
|
|
281
|
+
linkSearch: LoomaLinkSearch | undefined;
|
|
282
|
+
linkResolve: LoomaLinkResolve | undefined;
|
|
283
|
+
linkTargetLabel: string;
|
|
236
284
|
uploadImage: LoomaImageUploader | undefined;
|
|
237
285
|
resolveImageAttributes: LoomaImageAttributeResolver | undefined;
|
|
238
286
|
toolbarMode: LoomaEditorToolbarMode;
|
package/vue/editor/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * from "@threadlabs/looma/editor";
|
|
2
2
|
export * from "./primitives.js";
|
|
3
|
-
export { LoomaEditor, type LoomaEditorToolbarMode, type LoomaImageUploader, type LoomaImageUploadResult, } from "./LoomaEditor.js";
|
|
3
|
+
export { LoomaEditor, type LoomaEditorToolbarMode, type LoomaLinkTarget, type LoomaLinkSearch, type LoomaLinkResolve, type LoomaImageUploader, type LoomaImageUploadResult, } from "./LoomaEditor.js";
|
|
4
4
|
export type { LoomaImageActivationDetail, LoomaImageActivationTrigger, LoomaImageAttributeResolver, LoomaImageDescriptor, LoomaImageRenditionErrorDetail, LoomaImageRenditionAttributes, } from "./image-delivery.js";
|
package/vue/editor/index.js
CHANGED
|
@@ -562,6 +562,19 @@ var LoomaEditor = defineComponent({
|
|
|
562
562
|
type: Number,
|
|
563
563
|
default: DEFAULT_MENTION_RESULT_LIMIT
|
|
564
564
|
},
|
|
565
|
+
/** Host-owned search and identity lookup for links to application records. */
|
|
566
|
+
linkSearch: {
|
|
567
|
+
type: Function,
|
|
568
|
+
default: void 0
|
|
569
|
+
},
|
|
570
|
+
linkResolve: {
|
|
571
|
+
type: Function,
|
|
572
|
+
default: void 0
|
|
573
|
+
},
|
|
574
|
+
linkTargetLabel: {
|
|
575
|
+
type: String,
|
|
576
|
+
default: "Item"
|
|
577
|
+
},
|
|
565
578
|
uploadImage: {
|
|
566
579
|
type: Function,
|
|
567
580
|
default: void 0
|
|
@@ -613,12 +626,22 @@ var LoomaEditor = defineComponent({
|
|
|
613
626
|
let blockActionTarget = null;
|
|
614
627
|
const linkAnchorId = `looma-editor-link-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
615
628
|
const linkUrlInput = ref(null);
|
|
629
|
+
const linkFormRoot = ref(null);
|
|
616
630
|
const linkOpen = ref(false);
|
|
617
631
|
const linkContextEditing = ref(false);
|
|
618
632
|
const linkHref = ref("");
|
|
619
633
|
const linkText = ref("");
|
|
620
634
|
const linkNewTab = ref(true);
|
|
621
635
|
const linkError = ref("");
|
|
636
|
+
const linkMode = ref("url");
|
|
637
|
+
const linkQuery = ref("");
|
|
638
|
+
const linkResults = ref([]);
|
|
639
|
+
const linkSearching = ref(false);
|
|
640
|
+
const linkSelectedTarget = ref(null);
|
|
641
|
+
const linkContextTarget = ref(null);
|
|
642
|
+
const linkTargetCache = /* @__PURE__ */ new Map();
|
|
643
|
+
let linkSearchSequence = 0;
|
|
644
|
+
let linkResolveSequence = 0;
|
|
622
645
|
const chipAnchorId = `looma-editor-chip-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
623
646
|
const chipInput = ref(null);
|
|
624
647
|
const chipOpen = ref(false);
|
|
@@ -862,6 +885,63 @@ var LoomaEditor = defineComponent({
|
|
|
862
885
|
emit("update", value);
|
|
863
886
|
}
|
|
864
887
|
});
|
|
888
|
+
watch(() => {
|
|
889
|
+
editorStateVersion.value;
|
|
890
|
+
return editor.value?.isActive("link") ? editor.value.getAttributes("link").href : null;
|
|
891
|
+
}, async (href) => {
|
|
892
|
+
const sequence = ++linkResolveSequence;
|
|
893
|
+
linkContextTarget.value = null;
|
|
894
|
+
if (!href || !props.linkResolve) return;
|
|
895
|
+
if (linkTargetCache.has(href)) {
|
|
896
|
+
linkContextTarget.value = linkTargetCache.get(href) ?? null;
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
try {
|
|
900
|
+
const target = await props.linkResolve(href);
|
|
901
|
+
linkTargetCache.set(href, target);
|
|
902
|
+
if (sequence === linkResolveSequence) linkContextTarget.value = target;
|
|
903
|
+
} catch {}
|
|
904
|
+
});
|
|
905
|
+
watch([
|
|
906
|
+
linkQuery,
|
|
907
|
+
linkMode,
|
|
908
|
+
linkOpen,
|
|
909
|
+
linkContextEditing
|
|
910
|
+
], async ([query, mode, open, contextEditing]) => {
|
|
911
|
+
const sequence = ++linkSearchSequence;
|
|
912
|
+
linkResults.value = [];
|
|
913
|
+
linkSearching.value = false;
|
|
914
|
+
if (!props.linkSearch || mode !== "target" || !open && !contextEditing || query.trim().length < 2 || linkSelectedTarget.value && query === linkSelectedTarget.value.label) return;
|
|
915
|
+
linkSearching.value = true;
|
|
916
|
+
try {
|
|
917
|
+
const results = await props.linkSearch(query.trim());
|
|
918
|
+
if (sequence === linkSearchSequence) linkResults.value = results.filter((target) => validLinkHref(target.href));
|
|
919
|
+
} catch {
|
|
920
|
+
if (sequence === linkSearchSequence) linkError.value = "Search is unavailable. Try again.";
|
|
921
|
+
} finally {
|
|
922
|
+
if (sequence === linkSearchSequence) linkSearching.value = false;
|
|
923
|
+
}
|
|
924
|
+
});
|
|
925
|
+
const selectLinkTarget = (target) => {
|
|
926
|
+
linkSelectedTarget.value = target;
|
|
927
|
+
linkTargetCache.set(target.href, target);
|
|
928
|
+
linkHref.value = target.href;
|
|
929
|
+
linkQuery.value = target.label;
|
|
930
|
+
linkResults.value = [];
|
|
931
|
+
linkNewTab.value = false;
|
|
932
|
+
linkError.value = "";
|
|
933
|
+
};
|
|
934
|
+
const moveLinkResultFocus = (event, offset) => {
|
|
935
|
+
const buttons = [...linkFormRoot.value?.querySelectorAll("[data-link-result]") ?? []];
|
|
936
|
+
const next = buttons[buttons.indexOf(event.target) + offset];
|
|
937
|
+
if (next) {
|
|
938
|
+
event.preventDefault();
|
|
939
|
+
next.focus();
|
|
940
|
+
} else if (offset < 0) {
|
|
941
|
+
event.preventDefault();
|
|
942
|
+
linkFormRoot.value?.querySelector("[data-link-search]")?.focus();
|
|
943
|
+
}
|
|
944
|
+
};
|
|
865
945
|
const openLinkEditor = (context = false) => {
|
|
866
946
|
const instance = editor.value;
|
|
867
947
|
if (!instance || !props.editable) return;
|
|
@@ -883,17 +963,36 @@ var LoomaEditor = defineComponent({
|
|
|
883
963
|
linkNewTab.value = attrs.target !== "_self";
|
|
884
964
|
linkText.value = empty && !existing ? "" : instance.state.doc.textBetween(from, to);
|
|
885
965
|
linkError.value = "";
|
|
966
|
+
linkSelectedTarget.value = linkTargetCache.get(linkHref.value) ?? null;
|
|
967
|
+
linkMode.value = props.linkSearch && (!existing || linkSelectedTarget.value) ? "target" : "url";
|
|
968
|
+
linkQuery.value = linkSelectedTarget.value?.label ?? "";
|
|
886
969
|
linkContextEditing.value = context;
|
|
887
970
|
linkOpen.value = !context;
|
|
888
|
-
|
|
971
|
+
if (existing && props.linkResolve && !linkTargetCache.has(linkHref.value)) {
|
|
972
|
+
const href = linkHref.value;
|
|
973
|
+
props.linkResolve(href).then((target) => {
|
|
974
|
+
linkTargetCache.set(href, target);
|
|
975
|
+
if (linkHref.value === href && target) {
|
|
976
|
+
linkSelectedTarget.value = target;
|
|
977
|
+
linkMode.value = "target";
|
|
978
|
+
linkQuery.value = target.label;
|
|
979
|
+
}
|
|
980
|
+
}).catch(() => {});
|
|
981
|
+
}
|
|
982
|
+
nextTick(() => (linkMode.value === "url" ? linkUrlInput.value : linkFormRoot.value?.querySelector("[data-link-search]"))?.focus());
|
|
889
983
|
};
|
|
890
984
|
const saveLink = () => {
|
|
891
985
|
const instance = editor.value;
|
|
892
986
|
const selection = linkSelection;
|
|
893
987
|
if (!instance || !selection) return;
|
|
894
|
-
const href = validLinkHref(linkHref.value);
|
|
988
|
+
const href = linkMode.value === "target" ? validLinkHref(linkSelectedTarget.value?.href ?? "") : validLinkHref(linkHref.value);
|
|
895
989
|
if (!href) {
|
|
896
|
-
linkError.value = "Enter an http, https, mailto, tel, or relative URL.";
|
|
990
|
+
linkError.value = linkMode.value === "target" ? "Choose a destination from the results." : "Enter an http, https, mailto, tel, or relative URL.";
|
|
991
|
+
(linkMode.value === "url" ? linkUrlInput.value : linkFormRoot.value?.querySelector("[data-link-search]"))?.focus();
|
|
992
|
+
return;
|
|
993
|
+
}
|
|
994
|
+
if (linkMode.value === "url" && props.linkSearch && !selection.existing && !/^(https?:|mailto:|tel:)/i.test(href)) {
|
|
995
|
+
linkError.value = "Enter a full website, email, or phone URL, or choose a destination.";
|
|
897
996
|
linkUrlInput.value?.focus();
|
|
898
997
|
return;
|
|
899
998
|
}
|
|
@@ -945,6 +1044,7 @@ var LoomaEditor = defineComponent({
|
|
|
945
1044
|
linkContextEditing.value = false;
|
|
946
1045
|
};
|
|
947
1046
|
const renderLinkForm = () => h("form", {
|
|
1047
|
+
ref: linkFormRoot,
|
|
948
1048
|
class: "looma-editor__link-form",
|
|
949
1049
|
"aria-label": "Edit link",
|
|
950
1050
|
onSubmit: (event) => {
|
|
@@ -959,7 +1059,47 @@ var LoomaEditor = defineComponent({
|
|
|
959
1059
|
linkError.value = "";
|
|
960
1060
|
}
|
|
961
1061
|
})]) : null,
|
|
962
|
-
|
|
1062
|
+
props.linkSearch ? h("div", {
|
|
1063
|
+
class: "looma-editor__link-modes",
|
|
1064
|
+
role: "group",
|
|
1065
|
+
"aria-label": "Link destination"
|
|
1066
|
+
}, [h("button", {
|
|
1067
|
+
type: "button",
|
|
1068
|
+
"aria-pressed": linkMode.value === "target",
|
|
1069
|
+
onClick: () => {
|
|
1070
|
+
linkMode.value = "target";
|
|
1071
|
+
linkHref.value = "";
|
|
1072
|
+
linkSelectedTarget.value = null;
|
|
1073
|
+
linkQuery.value = "";
|
|
1074
|
+
linkError.value = "";
|
|
1075
|
+
nextTick(() => linkFormRoot.value?.querySelector("[data-link-search]")?.focus());
|
|
1076
|
+
}
|
|
1077
|
+
}, props.linkTargetLabel), h("button", {
|
|
1078
|
+
type: "button",
|
|
1079
|
+
"aria-pressed": linkMode.value === "url",
|
|
1080
|
+
onClick: () => {
|
|
1081
|
+
linkMode.value = "url";
|
|
1082
|
+
linkHref.value = "";
|
|
1083
|
+
linkSelectedTarget.value = null;
|
|
1084
|
+
linkError.value = "";
|
|
1085
|
+
nextTick(() => linkUrlInput.value?.focus());
|
|
1086
|
+
}
|
|
1087
|
+
}, "URL")]) : null,
|
|
1088
|
+
linkMode.value === "target" && props.linkSearch ? h("label", [h("span", `Find a ${props.linkTargetLabel.toLowerCase()}`), h("input", {
|
|
1089
|
+
"data-link-search": "",
|
|
1090
|
+
type: "search",
|
|
1091
|
+
value: linkQuery.value,
|
|
1092
|
+
autocomplete: "off",
|
|
1093
|
+
"aria-invalid": linkError.value ? "true" : void 0,
|
|
1094
|
+
onInput: (event) => {
|
|
1095
|
+
linkQuery.value = event.target.value;
|
|
1096
|
+
linkSelectedTarget.value = null;
|
|
1097
|
+
linkError.value = "";
|
|
1098
|
+
},
|
|
1099
|
+
onKeydown: (event) => {
|
|
1100
|
+
if (event.key === "ArrowDown") moveLinkResultFocus(event, 1);
|
|
1101
|
+
}
|
|
1102
|
+
})]) : h("label", [h("span", "URL"), h("input", {
|
|
963
1103
|
ref: linkUrlInput,
|
|
964
1104
|
type: "text",
|
|
965
1105
|
inputmode: "url",
|
|
@@ -970,7 +1110,25 @@ var LoomaEditor = defineComponent({
|
|
|
970
1110
|
linkError.value = "";
|
|
971
1111
|
}
|
|
972
1112
|
})]),
|
|
973
|
-
|
|
1113
|
+
linkMode.value === "target" && props.linkSearch ? h("div", {
|
|
1114
|
+
class: "looma-editor__link-results",
|
|
1115
|
+
"aria-label": "Destination search results"
|
|
1116
|
+
}, [
|
|
1117
|
+
linkSearching.value ? h("p", { role: "status" }, "Searching…") : null,
|
|
1118
|
+
linkSelectedTarget.value ? h("p", { class: "looma-editor__link-selected" }, `Selected: ${linkSelectedTarget.value.label}${linkSelectedTarget.value.detail ? ` · ${linkSelectedTarget.value.detail}` : ""}`) : null,
|
|
1119
|
+
!linkSearching.value && !linkSelectedTarget.value && linkQuery.value.trim().length < 2 ? h("p", "Type at least two letters to search.") : null,
|
|
1120
|
+
!linkSearching.value && !linkSelectedTarget.value && linkQuery.value.trim().length >= 2 && !linkResults.value.length && !linkError.value ? h("p", "No results found.") : null,
|
|
1121
|
+
...linkResults.value.map((target) => h("button", {
|
|
1122
|
+
key: target.id,
|
|
1123
|
+
type: "button",
|
|
1124
|
+
"data-link-result": "",
|
|
1125
|
+
onClick: () => selectLinkTarget(target),
|
|
1126
|
+
onKeydown: (event) => {
|
|
1127
|
+
if (event.key === "ArrowDown") moveLinkResultFocus(event, 1);
|
|
1128
|
+
if (event.key === "ArrowUp") moveLinkResultFocus(event, -1);
|
|
1129
|
+
}
|
|
1130
|
+
}, [h("strong", target.label), target.detail ? h("small", target.detail) : null]))
|
|
1131
|
+
]) : h("label", { class: "looma-editor__link-new-tab" }, [h("input", {
|
|
974
1132
|
type: "checkbox",
|
|
975
1133
|
checked: linkNewTab.value,
|
|
976
1134
|
onChange: (event) => {
|
|
@@ -981,7 +1139,7 @@ var LoomaEditor = defineComponent({
|
|
|
981
1139
|
class: "looma-editor__link-error",
|
|
982
1140
|
role: "alert"
|
|
983
1141
|
}, linkError.value) : null,
|
|
984
|
-
validLinkHref(linkHref.value) ? h("a", {
|
|
1142
|
+
linkMode.value === "url" && validLinkHref(linkHref.value) ? h("a", {
|
|
985
1143
|
class: "looma-editor__link-preview",
|
|
986
1144
|
href: validLinkHref(linkHref.value),
|
|
987
1145
|
target: "_blank",
|
|
@@ -1005,7 +1163,7 @@ var LoomaEditor = defineComponent({
|
|
|
1005
1163
|
h("span", {
|
|
1006
1164
|
class: "looma-editor__link-context-url",
|
|
1007
1165
|
title: href
|
|
1008
|
-
}, href),
|
|
1166
|
+
}, linkContextTarget.value ? [h("strong", linkContextTarget.value.label), linkContextTarget.value.detail ? h("small", linkContextTarget.value.detail) : null] : href),
|
|
1009
1167
|
h("button", {
|
|
1010
1168
|
type: "button",
|
|
1011
1169
|
onPointerdown: (event) => event.preventDefault(),
|