@threadlabs/looma 0.1.13 → 0.1.15
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/dist/{chunk-DQZJTDIB.js → chunk-SVINNT3E.js} +29 -27
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/looma.cjs.js +1 -1
- package/dist/cjs/ui-tree-item.cjs.entry.js +694 -0
- package/dist/cjs/ui-tree.cjs.entry.js +257 -0
- package/dist/collection/collection-manifest.json +3 -1
- package/dist/collection/components/ui-tree/ui-tree.css +11 -0
- package/dist/collection/components/ui-tree/ui-tree.js +252 -0
- package/dist/collection/components/ui-tree-item/ui-tree-item.css +213 -0
- package/dist/collection/components/ui-tree-item/ui-tree-item.js +347 -0
- package/dist/collection/utils/drag-drop.js +51 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +1 -1
- package/dist/components/ui-tree-item.d.ts +11 -0
- package/dist/components/ui-tree-item.js +13 -0
- package/dist/components/ui-tree.d.ts +11 -0
- package/dist/components/ui-tree.js +1 -0
- package/dist/esm/loader.js +1 -1
- package/dist/esm/looma.js +1 -1
- package/dist/esm/ui-tree-item.entry.js +692 -0
- package/dist/esm/ui-tree.entry.js +255 -0
- package/dist/index.cjs +687 -15
- package/dist/index.d.cts +17 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.js +44 -3
- package/dist/looma/looma.esm.js +1 -1
- package/dist/looma/p-95368dee.entry.js +1 -0
- package/dist/looma/p-ef9ca2ed.entry.js +13 -0
- package/dist/types/components/ui-tree/ui-tree.d.ts +28 -0
- package/dist/types/components/ui-tree-item/ui-tree-item.d.ts +36 -0
- package/dist/types/components.d.ts +176 -0
- package/dist/types/utils/drag-drop.d.ts +15 -0
- package/dist/{ui-affordance-scope.entry-SWTDTGGU.js → ui-affordance-scope.entry-PFP2TDKO.js} +1 -1
- package/dist/{ui-avatar-group.entry-VUYE2XOM.js → ui-avatar-group.entry-DQDP325O.js} +1 -1
- package/dist/{ui-avatar.entry-2CKHEJTS.js → ui-avatar.entry-WYIDMOFE.js} +1 -1
- package/dist/{ui-badge.entry-4SWSD3R5.js → ui-badge.entry-VGHXPEDT.js} +1 -1
- package/dist/{ui-button.entry-SS3AS32R.js → ui-button.entry-LKPLOJ22.js} +1 -1
- package/dist/{ui-checkbox.entry-V7OYTOLW.js → ui-checkbox.entry-J74HEA22.js} +1 -1
- package/dist/{ui-context-menu.entry-UCLTQESP.js → ui-context-menu.entry-MQM2FCLI.js} +1 -1
- package/dist/{ui-dialog.entry-PXIVZF7D.js → ui-dialog.entry-DQMMDO4Z.js} +1 -1
- package/dist/{ui-disclosure.entry-ZADBPM2D.js → ui-disclosure.entry-ONF7UZDC.js} +1 -1
- package/dist/{ui-floating-action-button.entry-WNBWY36T.js → ui-floating-action-button.entry-FKTGVC5T.js} +1 -1
- package/dist/{ui-form-field.entry-RZPSWN6Y.js → ui-form-field.entry-M3ISWQNU.js} +1 -1
- package/dist/{ui-icon-button.entry-ILU7RD7M.js → ui-icon-button.entry-AWFIQUHM.js} +1 -1
- package/dist/{ui-input.entry-FEIUK4EE.js → ui-input.entry-JZ6RETMT.js} +1 -1
- package/dist/{ui-menu-item.entry-UJVECPSK.js → ui-menu-item.entry-5MFR5LFL.js} +1 -1
- package/dist/{ui-menu.entry-MTCE3F5U.js → ui-menu.entry-IOEIDATQ.js} +1 -1
- package/dist/{ui-popover.entry-OAME35VB.js → ui-popover.entry-ELCMKO6Y.js} +1 -1
- package/dist/{ui-radio-group.entry-CPFX4LVA.js → ui-radio-group.entry-RJHUPPEM.js} +1 -1
- package/dist/{ui-radio.entry-44OTRYPB.js → ui-radio.entry-3VRDPOY4.js} +1 -1
- package/dist/{ui-search-result-row.entry-ZU5SL5OP.js → ui-search-result-row.entry-J34YPAV7.js} +1 -1
- package/dist/{ui-search-shell.entry-G7HG4RKU.js → ui-search-shell.entry-IJ4UUP27.js} +1 -1
- package/dist/{ui-select.entry-NAONXMFG.js → ui-select.entry-C6YD3HQ5.js} +1 -1
- package/dist/{ui-switch.entry-SE4ZTCS2.js → ui-switch.entry-UZDF5QTI.js} +1 -1
- package/dist/{ui-tabs.entry-2YG2JE3K.js → ui-tabs.entry-YRAKWOMR.js} +1 -1
- package/dist/{ui-textarea.entry-PV3APDLY.js → ui-textarea.entry-JLDKFT3K.js} +1 -1
- package/dist/{ui-toast-region.entry-WH2OL3FR.js → ui-toast-region.entry-GC7C7KXF.js} +1 -1
- package/dist/{ui-tooltip.entry-FY563DP4.js → ui-tooltip.entry-F26XDTYX.js} +1 -1
- package/dist/{ui-top-bar.entry-LJSZXFAH.js → ui-top-bar.entry-5W5UA5KV.js} +1 -1
- package/dist/ui-tree-item.entry-3LM7IXIK.js +385 -0
- package/dist/ui-tree.entry-X4FU42A6.js +244 -0
- package/editor.css +42 -0
- package/package.json +1 -1
- package/styles.css +18 -6
- package/vue/{chunk-YN4IUYVY.js → chunk-IITL6UBR.js} +7 -1
- package/vue/editor/index.d.ts +41 -3
- package/vue/editor/index.js +273 -4
- package/vue/index.d.ts +24 -1
- package/vue/index.js +5 -1
package/vue/editor/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
IconButton,
|
|
3
3
|
createAdapterComponent,
|
|
4
4
|
toHTMLElement
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-IITL6UBR.js";
|
|
6
6
|
|
|
7
7
|
// src/editor/index.ts
|
|
8
8
|
import "@threadlabs/looma/editor";
|
|
@@ -130,6 +130,188 @@ import {
|
|
|
130
130
|
getVisualViewportRect,
|
|
131
131
|
LOOMA_ICONS
|
|
132
132
|
} from "@threadlabs/looma/core";
|
|
133
|
+
|
|
134
|
+
// src/editor/image-delivery.ts
|
|
135
|
+
import { Extension } from "@tiptap/core";
|
|
136
|
+
import { Plugin, PluginKey } from "@tiptap/pm/state";
|
|
137
|
+
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
138
|
+
function optionalString(value) {
|
|
139
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
140
|
+
}
|
|
141
|
+
function normalizeImageDimension(value) {
|
|
142
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : void 0;
|
|
143
|
+
}
|
|
144
|
+
function imageDescriptorFromAttrs(attrs) {
|
|
145
|
+
const src = optionalString(attrs.src);
|
|
146
|
+
if (!src) return null;
|
|
147
|
+
const alt = typeof attrs.alt === "string" ? attrs.alt : void 0;
|
|
148
|
+
const width = normalizeImageDimension(attrs.width);
|
|
149
|
+
const height = normalizeImageDimension(attrs.height);
|
|
150
|
+
return {
|
|
151
|
+
src,
|
|
152
|
+
...alt !== void 0 ? { alt } : {},
|
|
153
|
+
...width ? { width } : {},
|
|
154
|
+
...height ? { height } : {},
|
|
155
|
+
...attrs.responsive === true ? { responsive: true } : {}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function transientAttributes(resolver, image) {
|
|
159
|
+
const attributes = {
|
|
160
|
+
"aria-label": image.alt ? `Open image: ${image.alt}` : "Open image",
|
|
161
|
+
"data-looma-image": "",
|
|
162
|
+
role: "button",
|
|
163
|
+
src: image.src,
|
|
164
|
+
tabindex: "0"
|
|
165
|
+
};
|
|
166
|
+
if (!image.responsive || !resolver) return attributes;
|
|
167
|
+
let rendition;
|
|
168
|
+
try {
|
|
169
|
+
rendition = resolver(image);
|
|
170
|
+
} catch {
|
|
171
|
+
return attributes;
|
|
172
|
+
}
|
|
173
|
+
if (!rendition) return attributes;
|
|
174
|
+
const src = optionalString(rendition.src);
|
|
175
|
+
const srcset = optionalString(rendition.srcset);
|
|
176
|
+
const sizes = optionalString(rendition.sizes);
|
|
177
|
+
if (src) attributes.src = src;
|
|
178
|
+
if (srcset) attributes.srcset = srcset;
|
|
179
|
+
if (sizes) attributes.sizes = sizes;
|
|
180
|
+
if (rendition.loading === "eager" || rendition.loading === "lazy") {
|
|
181
|
+
attributes.loading = rendition.loading;
|
|
182
|
+
}
|
|
183
|
+
if (["async", "auto", "sync"].includes(rendition.decoding ?? "")) {
|
|
184
|
+
attributes.decoding = rendition.decoding;
|
|
185
|
+
}
|
|
186
|
+
if (["auto", "high", "low"].includes(rendition.fetchPriority ?? "")) {
|
|
187
|
+
attributes.fetchpriority = rendition.fetchPriority;
|
|
188
|
+
}
|
|
189
|
+
if (src && src !== image.src || srcset) attributes["data-looma-rendition"] = "true";
|
|
190
|
+
return attributes;
|
|
191
|
+
}
|
|
192
|
+
function createDecorations(doc, resolver, failedRenditions) {
|
|
193
|
+
const decorations = [];
|
|
194
|
+
const currentSources = /* @__PURE__ */ new Set();
|
|
195
|
+
doc.descendants((node, position) => {
|
|
196
|
+
if (node.type.name !== "image") return;
|
|
197
|
+
const image = imageDescriptorFromAttrs(node.attrs);
|
|
198
|
+
if (!image) return;
|
|
199
|
+
currentSources.add(image.src);
|
|
200
|
+
decorations.push(Decoration.node(
|
|
201
|
+
position,
|
|
202
|
+
position + node.nodeSize,
|
|
203
|
+
transientAttributes(failedRenditions.has(image.src) ? void 0 : resolver, image)
|
|
204
|
+
));
|
|
205
|
+
});
|
|
206
|
+
for (const src of failedRenditions) {
|
|
207
|
+
if (!currentSources.has(src)) failedRenditions.delete(src);
|
|
208
|
+
}
|
|
209
|
+
return DecorationSet.create(doc, decorations);
|
|
210
|
+
}
|
|
211
|
+
function rangeContainsImage(doc, from, to) {
|
|
212
|
+
const start = Math.max(0, Math.min(from - 1, doc.content.size));
|
|
213
|
+
const end = Math.max(start, Math.min(to + 1, doc.content.size));
|
|
214
|
+
let found = false;
|
|
215
|
+
doc.nodesBetween(start, end, (node) => {
|
|
216
|
+
if (node.type.name !== "image") return !found;
|
|
217
|
+
found = true;
|
|
218
|
+
return false;
|
|
219
|
+
});
|
|
220
|
+
return found;
|
|
221
|
+
}
|
|
222
|
+
function transactionChangesImages(transaction) {
|
|
223
|
+
let changed = false;
|
|
224
|
+
transaction.mapping.maps.forEach((stepMap) => {
|
|
225
|
+
stepMap.forEach((oldStart, oldEnd, newStart, newEnd) => {
|
|
226
|
+
if (rangeContainsImage(transaction.before, oldStart, oldEnd) || rangeContainsImage(transaction.doc, newStart, newEnd)) changed = true;
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
return changed;
|
|
230
|
+
}
|
|
231
|
+
function createLoomaImageDeliveryController(options) {
|
|
232
|
+
const pluginKey = new PluginKey("looma-image-delivery");
|
|
233
|
+
const failedRenditions = /* @__PURE__ */ new Set();
|
|
234
|
+
const refresh = (editor) => {
|
|
235
|
+
editor.view.dispatch(editor.state.tr.setMeta(pluginKey, true));
|
|
236
|
+
};
|
|
237
|
+
const extension = Extension.create({
|
|
238
|
+
name: "loomaImageDelivery",
|
|
239
|
+
addGlobalAttributes() {
|
|
240
|
+
return [{
|
|
241
|
+
types: ["image"],
|
|
242
|
+
attributes: {
|
|
243
|
+
width: {
|
|
244
|
+
default: null,
|
|
245
|
+
parseHTML: (element) => normalizeImageDimension(Number(element.getAttribute("width"))) ?? null,
|
|
246
|
+
renderHTML: (attributes) => normalizeImageDimension(attributes.width) ? { width: normalizeImageDimension(attributes.width) } : {}
|
|
247
|
+
},
|
|
248
|
+
height: {
|
|
249
|
+
default: null,
|
|
250
|
+
parseHTML: (element) => normalizeImageDimension(Number(element.getAttribute("height"))) ?? null,
|
|
251
|
+
renderHTML: (attributes) => normalizeImageDimension(attributes.height) ? { height: normalizeImageDimension(attributes.height) } : {}
|
|
252
|
+
},
|
|
253
|
+
responsive: {
|
|
254
|
+
default: null,
|
|
255
|
+
parseHTML: (element) => element.hasAttribute("data-looma-responsive") || null,
|
|
256
|
+
renderHTML: (attributes) => attributes.responsive === true ? { "data-looma-responsive": "" } : {}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}];
|
|
260
|
+
},
|
|
261
|
+
addProseMirrorPlugins() {
|
|
262
|
+
return [new Plugin({
|
|
263
|
+
key: pluginKey,
|
|
264
|
+
state: {
|
|
265
|
+
init: (_, state) => createDecorations(
|
|
266
|
+
state.doc,
|
|
267
|
+
options.resolveAttributes(),
|
|
268
|
+
failedRenditions
|
|
269
|
+
),
|
|
270
|
+
apply: (transaction, previous) => {
|
|
271
|
+
if (!transaction.getMeta(pluginKey) && !transactionChangesImages(transaction)) {
|
|
272
|
+
return previous.map(transaction.mapping, transaction.doc);
|
|
273
|
+
}
|
|
274
|
+
return createDecorations(
|
|
275
|
+
transaction.doc,
|
|
276
|
+
options.resolveAttributes(),
|
|
277
|
+
failedRenditions
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
props: {
|
|
282
|
+
decorations: (state) => pluginKey.getState(state)
|
|
283
|
+
}
|
|
284
|
+
})];
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
return {
|
|
288
|
+
extension,
|
|
289
|
+
markRenditionFailed: (editor, src) => {
|
|
290
|
+
if (failedRenditions.has(src)) return false;
|
|
291
|
+
failedRenditions.add(src);
|
|
292
|
+
refresh(editor);
|
|
293
|
+
return true;
|
|
294
|
+
},
|
|
295
|
+
reset: (editor) => {
|
|
296
|
+
failedRenditions.clear();
|
|
297
|
+
refresh(editor);
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
function imageUploadContent(image) {
|
|
302
|
+
return {
|
|
303
|
+
type: "image",
|
|
304
|
+
attrs: {
|
|
305
|
+
src: image.src,
|
|
306
|
+
alt: image.alt,
|
|
307
|
+
...image.width ? { width: image.width } : {},
|
|
308
|
+
...image.height ? { height: image.height } : {},
|
|
309
|
+
...image.responsive === true ? { responsive: true } : {}
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// src/editor/LoomaEditor.ts
|
|
133
315
|
var EMPTY_DOCUMENT = { type: "doc", content: [] };
|
|
134
316
|
var EMPTY_CAPABILITIES = {
|
|
135
317
|
canAddRowBefore: false,
|
|
@@ -189,13 +371,19 @@ var LoomaEditor = defineComponent2({
|
|
|
189
371
|
uploadImage: {
|
|
190
372
|
type: Function,
|
|
191
373
|
default: void 0
|
|
374
|
+
},
|
|
375
|
+
resolveImageAttributes: {
|
|
376
|
+
type: Function,
|
|
377
|
+
default: void 0
|
|
192
378
|
}
|
|
193
379
|
},
|
|
194
380
|
emits: {
|
|
195
381
|
"update:modelValue": (_value) => true,
|
|
196
382
|
update: (_value) => true,
|
|
197
383
|
ready: (_editor) => true,
|
|
198
|
-
uploadError: (_error, _file) => true
|
|
384
|
+
uploadError: (_error, _file) => true,
|
|
385
|
+
imageActivate: (_detail) => true,
|
|
386
|
+
imageRenditionError: (_detail) => true
|
|
199
387
|
},
|
|
200
388
|
setup(props, { attrs, emit, expose }) {
|
|
201
389
|
const root = ref(null);
|
|
@@ -208,6 +396,7 @@ var LoomaEditor = defineComponent2({
|
|
|
208
396
|
const mobileToolbarShell = ref(null);
|
|
209
397
|
const dragOver = ref(false);
|
|
210
398
|
const uploading = ref(false);
|
|
399
|
+
const failedUpload = ref(null);
|
|
211
400
|
const tablePickerOpen = ref(false);
|
|
212
401
|
const tablePickerStyle = ref({});
|
|
213
402
|
const mobileToolbarStyle = ref({});
|
|
@@ -249,9 +438,13 @@ var LoomaEditor = defineComponent2({
|
|
|
249
438
|
Object.assign(slash, state);
|
|
250
439
|
}
|
|
251
440
|
});
|
|
441
|
+
const imageDelivery = createLoomaImageDeliveryController({
|
|
442
|
+
resolveAttributes: () => props.resolveImageAttributes
|
|
443
|
+
});
|
|
252
444
|
const editor = useEditor({
|
|
253
445
|
extensions: [
|
|
254
446
|
...getDefaultEditorExtensions({ placeholder: props.placeholder }),
|
|
447
|
+
imageDelivery.extension,
|
|
255
448
|
slashExtension,
|
|
256
449
|
...props.extensions
|
|
257
450
|
],
|
|
@@ -265,6 +458,10 @@ var LoomaEditor = defineComponent2({
|
|
|
265
458
|
}
|
|
266
459
|
});
|
|
267
460
|
watch(() => props.editable, (editable) => editor.value?.setEditable(editable));
|
|
461
|
+
watch(() => props.resolveImageAttributes, () => {
|
|
462
|
+
const instance = editor.value;
|
|
463
|
+
if (instance) imageDelivery.reset(instance);
|
|
464
|
+
});
|
|
268
465
|
watch(() => props.modelValue, (value) => {
|
|
269
466
|
const instance = editor.value;
|
|
270
467
|
if (!instance || sameDocument(instance.getJSON(), value)) return;
|
|
@@ -441,6 +638,49 @@ var LoomaEditor = defineComponent2({
|
|
|
441
638
|
nextTick(updateTableUi);
|
|
442
639
|
});
|
|
443
640
|
};
|
|
641
|
+
const imageForElement = (element) => {
|
|
642
|
+
const instance = editor.value;
|
|
643
|
+
if (!instance) return null;
|
|
644
|
+
try {
|
|
645
|
+
const position = instance.view.posAtDOM(element, 0);
|
|
646
|
+
const node = instance.state.doc.nodeAt(position);
|
|
647
|
+
return node?.type.name === "image" ? imageDescriptorFromAttrs(node.attrs) : null;
|
|
648
|
+
} catch {
|
|
649
|
+
return null;
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
const imageElementForEvent = (event) => {
|
|
653
|
+
const element = event.target instanceof Element ? event.target.closest("img[data-looma-image]") : null;
|
|
654
|
+
return element && root.value?.contains(element) ? element : null;
|
|
655
|
+
};
|
|
656
|
+
const activateImage = (element, trigger) => {
|
|
657
|
+
const image = imageForElement(element);
|
|
658
|
+
if (image) emit("imageActivate", { ...image, trigger });
|
|
659
|
+
};
|
|
660
|
+
const onImageClick = (event) => {
|
|
661
|
+
const element = imageElementForEvent(event);
|
|
662
|
+
if (element && !props.editable) activateImage(element, "pointer");
|
|
663
|
+
};
|
|
664
|
+
const onImageDoubleClick = (event) => {
|
|
665
|
+
const element = imageElementForEvent(event);
|
|
666
|
+
if (element && props.editable) activateImage(element, "pointer");
|
|
667
|
+
};
|
|
668
|
+
const onImageKeyDown = (event) => {
|
|
669
|
+
if (event.key !== "Enter" && event.key !== " ") return;
|
|
670
|
+
const element = imageElementForEvent(event);
|
|
671
|
+
if (!element) return;
|
|
672
|
+
event.preventDefault();
|
|
673
|
+
activateImage(element, "keyboard");
|
|
674
|
+
};
|
|
675
|
+
const onImageError = (event) => {
|
|
676
|
+
const element = imageElementForEvent(event);
|
|
677
|
+
if (!element || element.dataset.loomaRendition !== "true") return;
|
|
678
|
+
const image = imageForElement(element);
|
|
679
|
+
if (!image) return;
|
|
680
|
+
const instance = editor.value;
|
|
681
|
+
if (!instance || !imageDelivery.markRenditionFailed(instance, image.src)) return;
|
|
682
|
+
emit("imageRenditionError", { ...image, trigger: "programmatic" });
|
|
683
|
+
};
|
|
444
684
|
onMounted(() => {
|
|
445
685
|
updateMobileViewport();
|
|
446
686
|
window.addEventListener("resize", onViewportChange);
|
|
@@ -450,6 +690,7 @@ var LoomaEditor = defineComponent2({
|
|
|
450
690
|
document.addEventListener("pointerdown", onDocumentPointerDown, true);
|
|
451
691
|
document.addEventListener("pointerdown", onResizePointerDown, true);
|
|
452
692
|
document.addEventListener("pointerup", onResizePointerUp, true);
|
|
693
|
+
root.value?.addEventListener("error", onImageError, true);
|
|
453
694
|
});
|
|
454
695
|
onBeforeUnmount(() => {
|
|
455
696
|
window.removeEventListener("resize", onViewportChange);
|
|
@@ -459,6 +700,7 @@ var LoomaEditor = defineComponent2({
|
|
|
459
700
|
document.removeEventListener("pointerdown", onDocumentPointerDown, true);
|
|
460
701
|
document.removeEventListener("pointerdown", onResizePointerDown, true);
|
|
461
702
|
document.removeEventListener("pointerup", onResizePointerUp, true);
|
|
703
|
+
root.value?.removeEventListener("error", onImageError, true);
|
|
462
704
|
unbindEditorUi(editor.value);
|
|
463
705
|
if (dragLeaveTimer) clearTimeout(dragLeaveTimer);
|
|
464
706
|
if (tablePointerFrame !== null) cancelAnimationFrame(tablePointerFrame);
|
|
@@ -469,8 +711,18 @@ var LoomaEditor = defineComponent2({
|
|
|
469
711
|
try {
|
|
470
712
|
const result = await props.uploadImage(file);
|
|
471
713
|
const image = typeof result === "string" ? { url: result } : result;
|
|
472
|
-
|
|
714
|
+
const width = normalizeImageDimension(image.width);
|
|
715
|
+
const height = normalizeImageDimension(image.height);
|
|
716
|
+
editor.value.chain().focus().insertContent(imageUploadContent({
|
|
717
|
+
src: image.url,
|
|
718
|
+
alt: image.alt ?? file.name,
|
|
719
|
+
...width ? { width } : {},
|
|
720
|
+
...height ? { height } : {},
|
|
721
|
+
...image.responsive === true ? { responsive: true } : {}
|
|
722
|
+
})).run();
|
|
723
|
+
failedUpload.value = null;
|
|
473
724
|
} catch (error) {
|
|
725
|
+
failedUpload.value = { file };
|
|
474
726
|
emit("uploadError", error, file);
|
|
475
727
|
} finally {
|
|
476
728
|
uploading.value = false;
|
|
@@ -658,7 +910,10 @@ var LoomaEditor = defineComponent2({
|
|
|
658
910
|
dragOver.value = false;
|
|
659
911
|
}, 100);
|
|
660
912
|
},
|
|
661
|
-
onDrop
|
|
913
|
+
onDrop,
|
|
914
|
+
onClick: onImageClick,
|
|
915
|
+
onDblclick: onImageDoubleClick,
|
|
916
|
+
onKeydown: onImageKeyDown
|
|
662
917
|
}, [
|
|
663
918
|
instance && props.editable && !mobile.value ? h2(BubbleMenu, {
|
|
664
919
|
editor: instance,
|
|
@@ -703,6 +958,20 @@ var LoomaEditor = defineComponent2({
|
|
|
703
958
|
"aria-hidden": "true",
|
|
704
959
|
onChange: onFileChange
|
|
705
960
|
}),
|
|
961
|
+
failedUpload.value ? h2("div", {
|
|
962
|
+
class: "looma-editor__upload-error",
|
|
963
|
+
role: "alert"
|
|
964
|
+
}, [
|
|
965
|
+
h2("span", "Couldn\u2019t upload image."),
|
|
966
|
+
h2("button", {
|
|
967
|
+
type: "button",
|
|
968
|
+
disabled: uploading.value,
|
|
969
|
+
onClick: () => {
|
|
970
|
+
const attempt = failedUpload.value;
|
|
971
|
+
if (attempt) void insertImage(attempt.file);
|
|
972
|
+
}
|
|
973
|
+
}, uploading.value ? "Retrying\u2026" : "Retry")
|
|
974
|
+
]) : null,
|
|
706
975
|
dragOver.value ? h2("div", { class: "looma-editor__drop-overlay", "aria-hidden": "true" }, [
|
|
707
976
|
loomaIcon("image"),
|
|
708
977
|
h2("span", "Drop image to upload")
|
package/vue/index.d.ts
CHANGED
|
@@ -30,6 +30,21 @@ interface VueAdapterEventMap {
|
|
|
30
30
|
reason: string;
|
|
31
31
|
trigger: string;
|
|
32
32
|
};
|
|
33
|
+
reorder: {
|
|
34
|
+
sourceId: string;
|
|
35
|
+
targetId: string;
|
|
36
|
+
position: "before" | "inside" | "after";
|
|
37
|
+
sourceType: string;
|
|
38
|
+
targetType: string;
|
|
39
|
+
sourceScope: string;
|
|
40
|
+
targetScope: string;
|
|
41
|
+
trigger: string;
|
|
42
|
+
};
|
|
43
|
+
expand: {
|
|
44
|
+
id: string;
|
|
45
|
+
expanded: boolean;
|
|
46
|
+
trigger: string;
|
|
47
|
+
};
|
|
33
48
|
}
|
|
34
49
|
|
|
35
50
|
declare const Stack: vue.DefineComponent<{}, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
@@ -140,6 +155,12 @@ declare const SearchResultRow: vue.DefineComponent<{}, () => vue.VNode<vue.Rende
|
|
|
140
155
|
declare const TopBar: vue.DefineComponent<{}, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
141
156
|
[key: string]: any;
|
|
142
157
|
}>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
158
|
+
declare const Tree: vue.DefineComponent<{}, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
159
|
+
[key: string]: any;
|
|
160
|
+
}>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
161
|
+
declare const TreeItem: vue.DefineComponent<{}, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
162
|
+
[key: string]: any;
|
|
163
|
+
}>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
143
164
|
declare const ADAPTER_COMPONENT_TAG_MAP: {
|
|
144
165
|
readonly Stack: "ui-stack";
|
|
145
166
|
readonly Inline: "ui-inline";
|
|
@@ -177,7 +198,9 @@ declare const ADAPTER_COMPONENT_TAG_MAP: {
|
|
|
177
198
|
readonly SearchShell: "ui-search-shell";
|
|
178
199
|
readonly SearchResultRow: "ui-search-result-row";
|
|
179
200
|
readonly TopBar: "ui-top-bar";
|
|
201
|
+
readonly Tree: "ui-tree";
|
|
202
|
+
readonly TreeItem: "ui-tree-item";
|
|
180
203
|
};
|
|
181
204
|
declare const VUE_ADAPTER_NOTE = "Thin adapter only: attrs and slots pass through to custom elements and DOM events map to typed callbacks.";
|
|
182
205
|
|
|
183
|
-
export { ADAPTER_COMPONENT_TAG_MAP, AffordanceScope, Avatar, AvatarGroup, Badge, Button, Center, Checkbox, Cluster, ContextMenu, Dialog, Disclosure, FloatingActionButton, FormField, Grid, IconButton, Inline, Input, Menu, MenuItem, Popover, Radio, RadioGroup, Reel, SearchResultRow, SearchShell, Select, Separator, Sidebar, Stack, Switch, Switcher, Tabs, Textarea, ToastRegion, Tooltip, TopBar, VUE_ADAPTER_NOTE, type VueAdapterEventMap };
|
|
206
|
+
export { ADAPTER_COMPONENT_TAG_MAP, AffordanceScope, Avatar, AvatarGroup, Badge, Button, Center, Checkbox, Cluster, ContextMenu, Dialog, Disclosure, FloatingActionButton, FormField, Grid, IconButton, Inline, Input, Menu, MenuItem, Popover, Radio, RadioGroup, Reel, SearchResultRow, SearchShell, Select, Separator, Sidebar, Stack, Switch, Switcher, Tabs, Textarea, ToastRegion, Tooltip, TopBar, Tree, TreeItem, VUE_ADAPTER_NOTE, type VueAdapterEventMap };
|
package/vue/index.js
CHANGED
|
@@ -36,8 +36,10 @@ import {
|
|
|
36
36
|
ToastRegion,
|
|
37
37
|
Tooltip,
|
|
38
38
|
TopBar,
|
|
39
|
+
Tree,
|
|
40
|
+
TreeItem,
|
|
39
41
|
VUE_ADAPTER_NOTE
|
|
40
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-IITL6UBR.js";
|
|
41
43
|
export {
|
|
42
44
|
ADAPTER_COMPONENT_TAG_MAP,
|
|
43
45
|
AffordanceScope,
|
|
@@ -76,5 +78,7 @@ export {
|
|
|
76
78
|
ToastRegion,
|
|
77
79
|
Tooltip,
|
|
78
80
|
TopBar,
|
|
81
|
+
Tree,
|
|
82
|
+
TreeItem,
|
|
79
83
|
VUE_ADAPTER_NOTE
|
|
80
84
|
};
|