@bagelink/vue 0.0.1119 → 0.0.1121
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/components/Image.vue.d.ts +8 -8
- package/dist/components/Image.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText/components/EditorToolbar.vue.d.ts.map +1 -1
- package/dist/index.cjs +74 -45
- package/dist/index.mjs +74 -45
- package/dist/style.css +5 -2
- package/package.json +1 -1
- package/src/components/Image.vue +103 -53
- package/src/components/form/inputs/RichText/components/EditorToolbar.vue +1 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
interface Window {
|
|
3
|
-
heic2any: any;
|
|
4
|
-
}
|
|
5
|
-
}
|
|
6
|
-
type __VLS_Props = {
|
|
1
|
+
interface ImageProps {
|
|
7
2
|
src?: string;
|
|
8
3
|
pathKey?: string;
|
|
9
4
|
alt?: string;
|
|
10
5
|
width?: string | number;
|
|
11
6
|
height?: string | number;
|
|
12
7
|
caption?: string;
|
|
13
|
-
}
|
|
14
|
-
declare
|
|
8
|
+
}
|
|
9
|
+
declare global {
|
|
10
|
+
interface Window {
|
|
11
|
+
heic2any: any;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
declare const _default: import('vue').DefineComponent<ImageProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<ImageProps> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
15
15
|
export default _default;
|
|
16
16
|
//# sourceMappingURL=Image.vue.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Image.vue.d.ts","sourceRoot":"","sources":["../../src/components/Image.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Image.vue.d.ts","sourceRoot":"","sources":["../../src/components/Image.vue"],"names":[],"mappings":"AA+JA,UAAU,UAAU;IACnB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACxB,OAAO,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,MAAM;QACf,QAAQ,EAAE,GAAG,CAAA;KACb;CACD;;AAkMD,wBAMG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorToolbar.vue.d.ts","sourceRoot":"","sources":["../../../../../../src/components/form/inputs/RichText/components/EditorToolbar.vue"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"EditorToolbar.vue.d.ts","sourceRoot":"","sources":["../../../../../../src/components/form/inputs/RichText/components/EditorToolbar.vue"],"names":[],"mappings":"AAAA,OAuDO,KAAK,EAAE,aAAa,EAAsC,MAAM,kBAAkB,CAAA;AAKzF,KAAK,WAAW,GAAG;IAClB,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAC3B,CAAC;;;;;;AAqJF,wBAQG"}
|
package/dist/index.cjs
CHANGED
|
@@ -21127,6 +21127,7 @@ const _sfc_main$z = /* @__PURE__ */ vue.defineComponent({
|
|
|
21127
21127
|
flat: "",
|
|
21128
21128
|
"aria-label": action.name,
|
|
21129
21129
|
class: vue.normalizeClass([[action.class, { active: _ctx.selectedStyles.has(action.name) }], ""]),
|
|
21130
|
+
tabindex: "-1",
|
|
21130
21131
|
onClick: ($event) => runAction(action.name)
|
|
21131
21132
|
}, null, 8, ["icon", "aria-label", "class", "onClick"])), [
|
|
21132
21133
|
[_directive_tooltip, action.label]
|
|
@@ -21140,7 +21141,7 @@ const _sfc_main$z = /* @__PURE__ */ vue.defineComponent({
|
|
|
21140
21141
|
};
|
|
21141
21142
|
}
|
|
21142
21143
|
});
|
|
21143
|
-
const EditorToolbar = /* @__PURE__ */ _export_sfc(_sfc_main$z, [["__scopeId", "data-v-
|
|
21144
|
+
const EditorToolbar = /* @__PURE__ */ _export_sfc(_sfc_main$z, [["__scopeId", "data-v-bcd681b9"]]);
|
|
21144
21145
|
function createCommandExecutor(state2, commands) {
|
|
21145
21146
|
return {
|
|
21146
21147
|
execute(command, value) {
|
|
@@ -31400,65 +31401,82 @@ const _sfc_main$p = /* @__PURE__ */ vue.defineComponent({
|
|
|
31400
31401
|
props: {
|
|
31401
31402
|
src: {},
|
|
31402
31403
|
pathKey: {},
|
|
31403
|
-
alt: {
|
|
31404
|
+
alt: {},
|
|
31404
31405
|
width: {},
|
|
31405
31406
|
height: {},
|
|
31406
31407
|
caption: {}
|
|
31407
31408
|
},
|
|
31408
31409
|
setup(__props) {
|
|
31410
|
+
const props2 = __props;
|
|
31409
31411
|
let imageSrc = vue.ref(null);
|
|
31410
|
-
|
|
31411
|
-
|
|
31412
|
+
let loadingError = vue.ref(false);
|
|
31413
|
+
const fileBaseUrl = vue.computed(() => "https://files.bagel.design");
|
|
31414
|
+
function getImageUrl() {
|
|
31412
31415
|
var _a2;
|
|
31413
|
-
if (
|
|
31414
|
-
return
|
|
31416
|
+
if (!props2.src && !props2.pathKey) return null;
|
|
31417
|
+
if (props2.src) return props2.src;
|
|
31418
|
+
if ((_a2 = props2.pathKey) == null ? void 0 : _a2.startsWith("static/")) {
|
|
31419
|
+
return `${void 0}/${props2.pathKey}`;
|
|
31420
|
+
}
|
|
31421
|
+
return `${fileBaseUrl.value}/${props2.pathKey}`;
|
|
31422
|
+
}
|
|
31423
|
+
async function getCachedImage(url) {
|
|
31424
|
+
if (!("caches" in window)) return null;
|
|
31425
|
+
try {
|
|
31426
|
+
const imgCache = await window.caches.open("img-cache");
|
|
31427
|
+
const cachedResponse = await imgCache.match(url);
|
|
31428
|
+
if (cachedResponse) {
|
|
31429
|
+
return URL.createObjectURL(await cachedResponse.blob());
|
|
31430
|
+
}
|
|
31431
|
+
} catch (error) {
|
|
31432
|
+
console.warn("Cache access error:", error);
|
|
31433
|
+
}
|
|
31434
|
+
return null;
|
|
31435
|
+
}
|
|
31436
|
+
async function cacheImage(url, blob) {
|
|
31437
|
+
if (!("caches" in window)) return;
|
|
31438
|
+
try {
|
|
31439
|
+
const imgCache = await window.caches.open("img-cache");
|
|
31440
|
+
await imgCache.put(url, new Response(blob));
|
|
31441
|
+
} catch (error) {
|
|
31442
|
+
console.warn("Cache write error:", error);
|
|
31443
|
+
}
|
|
31444
|
+
}
|
|
31445
|
+
async function convertHeicImage(url) {
|
|
31446
|
+
await appendScript("https://cdnjs.cloudflare.com/ajax/libs/heic2any/0.0.1/index.min.js");
|
|
31447
|
+
const response = await fetch(normalizeURL(url));
|
|
31448
|
+
const blob = await response.blob();
|
|
31449
|
+
const convertedBlob = await window.heic2any({ blob });
|
|
31450
|
+
await cacheImage(url, convertedBlob);
|
|
31451
|
+
return URL.createObjectURL(convertedBlob);
|
|
31415
31452
|
}
|
|
31416
31453
|
async function loadImage() {
|
|
31417
31454
|
var _a2;
|
|
31418
|
-
|
|
31419
|
-
|
|
31455
|
+
loadingError.value = false;
|
|
31456
|
+
const url = getImageUrl();
|
|
31420
31457
|
if (!url) {
|
|
31421
31458
|
imageSrc.value = null;
|
|
31422
31459
|
return;
|
|
31423
31460
|
}
|
|
31424
|
-
|
|
31425
|
-
|
|
31426
|
-
if (
|
|
31427
|
-
|
|
31428
|
-
|
|
31429
|
-
|
|
31430
|
-
|
|
31431
|
-
const cachedResponse = await imgCache.match(url);
|
|
31432
|
-
if (cachedResponse) {
|
|
31433
|
-
imageSrc.value = URL.createObjectURL(await cachedResponse.blob());
|
|
31434
|
-
return;
|
|
31435
|
-
}
|
|
31436
|
-
} catch (error) {
|
|
31437
|
-
console.warn("Error accessing cache:", error);
|
|
31438
|
-
}
|
|
31439
|
-
}
|
|
31440
|
-
try {
|
|
31441
|
-
await appendScript("https://cdnjs.cloudflare.com/ajax/libs/heic2any/0.0.1/index.min.js");
|
|
31442
|
-
const response = await fetch(normalizeURL(url));
|
|
31443
|
-
const blob = await response.blob();
|
|
31444
|
-
const convertedBlob = await window.heic2any({ blob });
|
|
31445
|
-
imageSrc.value = URL.createObjectURL(convertedBlob);
|
|
31446
|
-
if ("caches" in window) {
|
|
31447
|
-
try {
|
|
31448
|
-
const imgCache = await window.caches.open("img-cache");
|
|
31449
|
-
imgCache.put(url, new Response(convertedBlob));
|
|
31450
|
-
} catch (cacheError) {
|
|
31451
|
-
console.warn("Failed to cache the image:", cacheError);
|
|
31452
|
-
}
|
|
31461
|
+
try {
|
|
31462
|
+
const ext = (_a2 = url.split(".").pop()) == null ? void 0 : _a2.toLowerCase().split("?")[0];
|
|
31463
|
+
if (ext === "heic") {
|
|
31464
|
+
const cachedSrc = await getCachedImage(url);
|
|
31465
|
+
if (cachedSrc) {
|
|
31466
|
+
imageSrc.value = cachedSrc;
|
|
31467
|
+
return;
|
|
31453
31468
|
}
|
|
31454
|
-
|
|
31455
|
-
|
|
31469
|
+
imageSrc.value = await convertHeicImage(url);
|
|
31470
|
+
} else {
|
|
31471
|
+
imageSrc.value = url;
|
|
31456
31472
|
}
|
|
31457
|
-
}
|
|
31458
|
-
|
|
31473
|
+
} catch (error) {
|
|
31474
|
+
console.error("Image loading error:", error);
|
|
31475
|
+
loadingError.value = true;
|
|
31476
|
+
imageSrc.value = null;
|
|
31459
31477
|
}
|
|
31460
31478
|
}
|
|
31461
|
-
vue.watch(() => [
|
|
31479
|
+
vue.watch(() => [props2.src, props2.pathKey], loadImage, { immediate: true });
|
|
31462
31480
|
return (_ctx, _cache) => {
|
|
31463
31481
|
return _ctx.caption ? (vue.openBlock(), vue.createElementBlock("figcaption", _hoisted_1$h, [
|
|
31464
31482
|
vue.unref(imageSrc) ? (vue.openBlock(), vue.createElementBlock("img", vue.mergeProps({
|
|
@@ -31481,8 +31499,17 @@ const _sfc_main$p = /* @__PURE__ */ vue.defineComponent({
|
|
|
31481
31499
|
alt: _ctx.alt,
|
|
31482
31500
|
width: vue.unref(normalizeDimension)(_ctx.width),
|
|
31483
31501
|
height: vue.unref(normalizeDimension)(_ctx.height)
|
|
31484
|
-
}), null, 16, _hoisted_3$7)) : (vue.openBlock(), vue.
|
|
31502
|
+
}), null, 16, _hoisted_3$7)) : vue.unref(loadingError) ? (vue.openBlock(), vue.createElementBlock("div", {
|
|
31485
31503
|
key: 2,
|
|
31504
|
+
class: "flex-center error-image",
|
|
31505
|
+
style: vue.normalizeStyle({
|
|
31506
|
+
width: vue.unref(normalizeDimension)(_ctx.width),
|
|
31507
|
+
height: vue.unref(normalizeDimension)(_ctx.height)
|
|
31508
|
+
})
|
|
31509
|
+
}, [
|
|
31510
|
+
vue.createVNode(vue.unref(_sfc_main$d), { name: "broken_image" })
|
|
31511
|
+
], 4)) : (vue.openBlock(), vue.createBlock(vue.unref(Skeleton), {
|
|
31512
|
+
key: 3,
|
|
31486
31513
|
class: "img-web-kit",
|
|
31487
31514
|
width: vue.unref(normalizeDimension)(_ctx.width),
|
|
31488
31515
|
height: vue.unref(normalizeDimension)(_ctx.height)
|
|
@@ -31490,7 +31517,7 @@ const _sfc_main$p = /* @__PURE__ */ vue.defineComponent({
|
|
|
31490
31517
|
};
|
|
31491
31518
|
}
|
|
31492
31519
|
});
|
|
31493
|
-
const Image$1 = /* @__PURE__ */ _export_sfc(_sfc_main$p, [["__scopeId", "data-v-
|
|
31520
|
+
const Image$1 = /* @__PURE__ */ _export_sfc(_sfc_main$p, [["__scopeId", "data-v-6f277b5b"]]);
|
|
31494
31521
|
const _hoisted_1$g = { class: "m-0 pb-025 txt14 line-height-1 w60 menu-text" };
|
|
31495
31522
|
const _sfc_main$o = /* @__PURE__ */ vue.defineComponent({
|
|
31496
31523
|
__name: "BottomMenu",
|
|
@@ -32644,6 +32671,7 @@ function debounceFilter(ms, options = {}) {
|
|
|
32644
32671
|
lastRejector();
|
|
32645
32672
|
lastRejector = noop;
|
|
32646
32673
|
};
|
|
32674
|
+
let lastInvoker;
|
|
32647
32675
|
const filter3 = (invoke) => {
|
|
32648
32676
|
const duration = vue.toValue(ms);
|
|
32649
32677
|
const maxDuration = vue.toValue(options.maxWait);
|
|
@@ -32658,12 +32686,13 @@ function debounceFilter(ms, options = {}) {
|
|
|
32658
32686
|
}
|
|
32659
32687
|
return new Promise((resolve, reject3) => {
|
|
32660
32688
|
lastRejector = options.rejectOnCancel ? reject3 : resolve;
|
|
32689
|
+
lastInvoker = invoke;
|
|
32661
32690
|
if (maxDuration && !maxTimer) {
|
|
32662
32691
|
maxTimer = setTimeout(() => {
|
|
32663
32692
|
if (timer)
|
|
32664
32693
|
_clearTimeout(timer);
|
|
32665
32694
|
maxTimer = null;
|
|
32666
|
-
resolve(
|
|
32695
|
+
resolve(lastInvoker());
|
|
32667
32696
|
}, maxDuration);
|
|
32668
32697
|
}
|
|
32669
32698
|
timer = setTimeout(() => {
|
package/dist/index.mjs
CHANGED
|
@@ -21125,6 +21125,7 @@ const _sfc_main$z = /* @__PURE__ */ defineComponent({
|
|
|
21125
21125
|
flat: "",
|
|
21126
21126
|
"aria-label": action.name,
|
|
21127
21127
|
class: normalizeClass([[action.class, { active: _ctx.selectedStyles.has(action.name) }], ""]),
|
|
21128
|
+
tabindex: "-1",
|
|
21128
21129
|
onClick: ($event) => runAction(action.name)
|
|
21129
21130
|
}, null, 8, ["icon", "aria-label", "class", "onClick"])), [
|
|
21130
21131
|
[_directive_tooltip, action.label]
|
|
@@ -21138,7 +21139,7 @@ const _sfc_main$z = /* @__PURE__ */ defineComponent({
|
|
|
21138
21139
|
};
|
|
21139
21140
|
}
|
|
21140
21141
|
});
|
|
21141
|
-
const EditorToolbar = /* @__PURE__ */ _export_sfc(_sfc_main$z, [["__scopeId", "data-v-
|
|
21142
|
+
const EditorToolbar = /* @__PURE__ */ _export_sfc(_sfc_main$z, [["__scopeId", "data-v-bcd681b9"]]);
|
|
21142
21143
|
function createCommandExecutor(state2, commands) {
|
|
21143
21144
|
return {
|
|
21144
21145
|
execute(command, value) {
|
|
@@ -31398,65 +31399,82 @@ const _sfc_main$p = /* @__PURE__ */ defineComponent({
|
|
|
31398
31399
|
props: {
|
|
31399
31400
|
src: {},
|
|
31400
31401
|
pathKey: {},
|
|
31401
|
-
alt: {
|
|
31402
|
+
alt: {},
|
|
31402
31403
|
width: {},
|
|
31403
31404
|
height: {},
|
|
31404
31405
|
caption: {}
|
|
31405
31406
|
},
|
|
31406
31407
|
setup(__props) {
|
|
31408
|
+
const props2 = __props;
|
|
31407
31409
|
let imageSrc = ref(null);
|
|
31408
|
-
|
|
31409
|
-
|
|
31410
|
+
let loadingError = ref(false);
|
|
31411
|
+
const fileBaseUrl = computed(() => "https://files.bagel.design");
|
|
31412
|
+
function getImageUrl() {
|
|
31410
31413
|
var _a2;
|
|
31411
|
-
if (
|
|
31412
|
-
return
|
|
31414
|
+
if (!props2.src && !props2.pathKey) return null;
|
|
31415
|
+
if (props2.src) return props2.src;
|
|
31416
|
+
if ((_a2 = props2.pathKey) == null ? void 0 : _a2.startsWith("static/")) {
|
|
31417
|
+
return `${void 0}/${props2.pathKey}`;
|
|
31418
|
+
}
|
|
31419
|
+
return `${fileBaseUrl.value}/${props2.pathKey}`;
|
|
31420
|
+
}
|
|
31421
|
+
async function getCachedImage(url) {
|
|
31422
|
+
if (!("caches" in window)) return null;
|
|
31423
|
+
try {
|
|
31424
|
+
const imgCache = await window.caches.open("img-cache");
|
|
31425
|
+
const cachedResponse = await imgCache.match(url);
|
|
31426
|
+
if (cachedResponse) {
|
|
31427
|
+
return URL.createObjectURL(await cachedResponse.blob());
|
|
31428
|
+
}
|
|
31429
|
+
} catch (error) {
|
|
31430
|
+
console.warn("Cache access error:", error);
|
|
31431
|
+
}
|
|
31432
|
+
return null;
|
|
31433
|
+
}
|
|
31434
|
+
async function cacheImage(url, blob) {
|
|
31435
|
+
if (!("caches" in window)) return;
|
|
31436
|
+
try {
|
|
31437
|
+
const imgCache = await window.caches.open("img-cache");
|
|
31438
|
+
await imgCache.put(url, new Response(blob));
|
|
31439
|
+
} catch (error) {
|
|
31440
|
+
console.warn("Cache write error:", error);
|
|
31441
|
+
}
|
|
31442
|
+
}
|
|
31443
|
+
async function convertHeicImage(url) {
|
|
31444
|
+
await appendScript("https://cdnjs.cloudflare.com/ajax/libs/heic2any/0.0.1/index.min.js");
|
|
31445
|
+
const response = await fetch(normalizeURL(url));
|
|
31446
|
+
const blob = await response.blob();
|
|
31447
|
+
const convertedBlob = await window.heic2any({ blob });
|
|
31448
|
+
await cacheImage(url, convertedBlob);
|
|
31449
|
+
return URL.createObjectURL(convertedBlob);
|
|
31413
31450
|
}
|
|
31414
31451
|
async function loadImage() {
|
|
31415
31452
|
var _a2;
|
|
31416
|
-
|
|
31417
|
-
|
|
31453
|
+
loadingError.value = false;
|
|
31454
|
+
const url = getImageUrl();
|
|
31418
31455
|
if (!url) {
|
|
31419
31456
|
imageSrc.value = null;
|
|
31420
31457
|
return;
|
|
31421
31458
|
}
|
|
31422
|
-
|
|
31423
|
-
|
|
31424
|
-
if (
|
|
31425
|
-
|
|
31426
|
-
|
|
31427
|
-
|
|
31428
|
-
|
|
31429
|
-
const cachedResponse = await imgCache.match(url);
|
|
31430
|
-
if (cachedResponse) {
|
|
31431
|
-
imageSrc.value = URL.createObjectURL(await cachedResponse.blob());
|
|
31432
|
-
return;
|
|
31433
|
-
}
|
|
31434
|
-
} catch (error) {
|
|
31435
|
-
console.warn("Error accessing cache:", error);
|
|
31436
|
-
}
|
|
31437
|
-
}
|
|
31438
|
-
try {
|
|
31439
|
-
await appendScript("https://cdnjs.cloudflare.com/ajax/libs/heic2any/0.0.1/index.min.js");
|
|
31440
|
-
const response = await fetch(normalizeURL(url));
|
|
31441
|
-
const blob = await response.blob();
|
|
31442
|
-
const convertedBlob = await window.heic2any({ blob });
|
|
31443
|
-
imageSrc.value = URL.createObjectURL(convertedBlob);
|
|
31444
|
-
if ("caches" in window) {
|
|
31445
|
-
try {
|
|
31446
|
-
const imgCache = await window.caches.open("img-cache");
|
|
31447
|
-
imgCache.put(url, new Response(convertedBlob));
|
|
31448
|
-
} catch (cacheError) {
|
|
31449
|
-
console.warn("Failed to cache the image:", cacheError);
|
|
31450
|
-
}
|
|
31459
|
+
try {
|
|
31460
|
+
const ext = (_a2 = url.split(".").pop()) == null ? void 0 : _a2.toLowerCase().split("?")[0];
|
|
31461
|
+
if (ext === "heic") {
|
|
31462
|
+
const cachedSrc = await getCachedImage(url);
|
|
31463
|
+
if (cachedSrc) {
|
|
31464
|
+
imageSrc.value = cachedSrc;
|
|
31465
|
+
return;
|
|
31451
31466
|
}
|
|
31452
|
-
|
|
31453
|
-
|
|
31467
|
+
imageSrc.value = await convertHeicImage(url);
|
|
31468
|
+
} else {
|
|
31469
|
+
imageSrc.value = url;
|
|
31454
31470
|
}
|
|
31455
|
-
}
|
|
31456
|
-
|
|
31471
|
+
} catch (error) {
|
|
31472
|
+
console.error("Image loading error:", error);
|
|
31473
|
+
loadingError.value = true;
|
|
31474
|
+
imageSrc.value = null;
|
|
31457
31475
|
}
|
|
31458
31476
|
}
|
|
31459
|
-
watch(() => [
|
|
31477
|
+
watch(() => [props2.src, props2.pathKey], loadImage, { immediate: true });
|
|
31460
31478
|
return (_ctx, _cache) => {
|
|
31461
31479
|
return _ctx.caption ? (openBlock(), createElementBlock("figcaption", _hoisted_1$h, [
|
|
31462
31480
|
unref(imageSrc) ? (openBlock(), createElementBlock("img", mergeProps({
|
|
@@ -31479,8 +31497,17 @@ const _sfc_main$p = /* @__PURE__ */ defineComponent({
|
|
|
31479
31497
|
alt: _ctx.alt,
|
|
31480
31498
|
width: unref(normalizeDimension)(_ctx.width),
|
|
31481
31499
|
height: unref(normalizeDimension)(_ctx.height)
|
|
31482
|
-
}), null, 16, _hoisted_3$7)) : (openBlock(),
|
|
31500
|
+
}), null, 16, _hoisted_3$7)) : unref(loadingError) ? (openBlock(), createElementBlock("div", {
|
|
31483
31501
|
key: 2,
|
|
31502
|
+
class: "flex-center error-image",
|
|
31503
|
+
style: normalizeStyle({
|
|
31504
|
+
width: unref(normalizeDimension)(_ctx.width),
|
|
31505
|
+
height: unref(normalizeDimension)(_ctx.height)
|
|
31506
|
+
})
|
|
31507
|
+
}, [
|
|
31508
|
+
createVNode(unref(_sfc_main$d), { name: "broken_image" })
|
|
31509
|
+
], 4)) : (openBlock(), createBlock(unref(Skeleton), {
|
|
31510
|
+
key: 3,
|
|
31484
31511
|
class: "img-web-kit",
|
|
31485
31512
|
width: unref(normalizeDimension)(_ctx.width),
|
|
31486
31513
|
height: unref(normalizeDimension)(_ctx.height)
|
|
@@ -31488,7 +31515,7 @@ const _sfc_main$p = /* @__PURE__ */ defineComponent({
|
|
|
31488
31515
|
};
|
|
31489
31516
|
}
|
|
31490
31517
|
});
|
|
31491
|
-
const Image$1 = /* @__PURE__ */ _export_sfc(_sfc_main$p, [["__scopeId", "data-v-
|
|
31518
|
+
const Image$1 = /* @__PURE__ */ _export_sfc(_sfc_main$p, [["__scopeId", "data-v-6f277b5b"]]);
|
|
31492
31519
|
const _hoisted_1$g = { class: "m-0 pb-025 txt14 line-height-1 w60 menu-text" };
|
|
31493
31520
|
const _sfc_main$o = /* @__PURE__ */ defineComponent({
|
|
31494
31521
|
__name: "BottomMenu",
|
|
@@ -32642,6 +32669,7 @@ function debounceFilter(ms, options = {}) {
|
|
|
32642
32669
|
lastRejector();
|
|
32643
32670
|
lastRejector = noop;
|
|
32644
32671
|
};
|
|
32672
|
+
let lastInvoker;
|
|
32645
32673
|
const filter3 = (invoke) => {
|
|
32646
32674
|
const duration = toValue(ms);
|
|
32647
32675
|
const maxDuration = toValue(options.maxWait);
|
|
@@ -32656,12 +32684,13 @@ function debounceFilter(ms, options = {}) {
|
|
|
32656
32684
|
}
|
|
32657
32685
|
return new Promise((resolve, reject3) => {
|
|
32658
32686
|
lastRejector = options.rejectOnCancel ? reject3 : resolve;
|
|
32687
|
+
lastInvoker = invoke;
|
|
32659
32688
|
if (maxDuration && !maxTimer) {
|
|
32660
32689
|
maxTimer = setTimeout(() => {
|
|
32661
32690
|
if (timer)
|
|
32662
32691
|
_clearTimeout(timer);
|
|
32663
32692
|
maxTimer = null;
|
|
32664
|
-
resolve(
|
|
32693
|
+
resolve(lastInvoker());
|
|
32665
32694
|
}, maxDuration);
|
|
32666
32695
|
}
|
|
32667
32696
|
timer = setTimeout(() => {
|
package/dist/style.css
CHANGED
|
@@ -1435,7 +1435,7 @@ input[type="range"][data-v-25d991e5]:active::-webkit-slider-thumb {
|
|
|
1435
1435
|
background: var(--bgl-primary-light);
|
|
1436
1436
|
}
|
|
1437
1437
|
|
|
1438
|
-
.toolbar[data-v-
|
|
1438
|
+
.toolbar[data-v-bcd681b9] .active {
|
|
1439
1439
|
background: var(--bgl-primary);
|
|
1440
1440
|
color: white;
|
|
1441
1441
|
}
|
|
@@ -2123,12 +2123,15 @@ line-height: 1.65;
|
|
|
2123
2123
|
color: var(--bgl-green);
|
|
2124
2124
|
}
|
|
2125
2125
|
|
|
2126
|
-
.img-web-kit[data-v-
|
|
2126
|
+
.img-web-kit[data-v-6f277b5b] {
|
|
2127
2127
|
max-width: 100%;
|
|
2128
2128
|
vertical-align: middle;
|
|
2129
2129
|
border: 0;
|
|
2130
2130
|
width: 100%;
|
|
2131
2131
|
}
|
|
2132
|
+
.error-image[data-v-6f277b5b] {
|
|
2133
|
+
background-color: var(--skeleton-bg);
|
|
2134
|
+
}
|
|
2132
2135
|
|
|
2133
2136
|
.bgl_bottombar .bgl_btn-flex{
|
|
2134
2137
|
flex-direction: column;
|
package/package.json
CHANGED
package/src/components/Image.vue
CHANGED
|
@@ -1,83 +1,112 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { Skeleton, normalizeDimension, appendScript, normalizeURL } from '@bagelink/vue'
|
|
3
|
-
import { watch } from 'vue'
|
|
2
|
+
import { Skeleton, normalizeDimension, appendScript, normalizeURL, Icon } from '@bagelink/vue'
|
|
3
|
+
import { watch, computed } from 'vue'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
interface Window {
|
|
7
|
-
heic2any: any
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const { height, width, alt = '', src, pathKey } = defineProps<{
|
|
5
|
+
interface ImageProps {
|
|
12
6
|
src?: string
|
|
13
7
|
pathKey?: string
|
|
14
8
|
alt?: string
|
|
15
9
|
width?: string | number
|
|
16
10
|
height?: string | number
|
|
17
11
|
caption?: string
|
|
18
|
-
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
declare global {
|
|
15
|
+
interface Window {
|
|
16
|
+
heic2any: any
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const props = defineProps<ImageProps>()
|
|
19
21
|
|
|
20
22
|
let imageSrc = $ref<string | null>(null)
|
|
23
|
+
let loadingError = $ref(false)
|
|
21
24
|
|
|
22
|
-
const fileBaseUrl =
|
|
23
|
-
function pathToUrl() {
|
|
24
|
-
if (pathKey?.startsWith('static/')) return `${import.meta.env.VITE_BAGEL_BASE_URL}/${pathKey}`
|
|
25
|
+
const fileBaseUrl = computed(() => 'https://files.bagel.design')
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
function getImageUrl(): string | null {
|
|
28
|
+
if (!props.src && !props.pathKey) return null
|
|
29
|
+
if (props.src) return props.src
|
|
30
|
+
if (props.pathKey?.startsWith('static/')) {
|
|
31
|
+
return `${import.meta.env.VITE_BAGEL_BASE_URL}/${props.pathKey}`
|
|
32
|
+
}
|
|
33
|
+
return `${fileBaseUrl.value}/${props.pathKey}`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function getCachedImage(url: string): Promise<string | null> {
|
|
37
|
+
if (!('caches' in window)) return null
|
|
38
|
+
try {
|
|
39
|
+
const imgCache = await window.caches.open('img-cache')
|
|
40
|
+
const cachedResponse = await imgCache.match(url)
|
|
41
|
+
if (cachedResponse) {
|
|
42
|
+
return URL.createObjectURL(await cachedResponse.blob())
|
|
43
|
+
}
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.warn('Cache access error:', error)
|
|
46
|
+
}
|
|
47
|
+
return null
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function cacheImage(url: string, blob: Blob) {
|
|
51
|
+
if (!('caches' in window)) return
|
|
52
|
+
try {
|
|
53
|
+
const imgCache = await window.caches.open('img-cache')
|
|
54
|
+
await imgCache.put(url, new Response(blob))
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.warn('Cache write error:', error)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function convertHeicImage(url: string): Promise<string> {
|
|
61
|
+
await appendScript('https://cdnjs.cloudflare.com/ajax/libs/heic2any/0.0.1/index.min.js')
|
|
62
|
+
const response = await fetch(normalizeURL(url))
|
|
63
|
+
const blob = await response.blob()
|
|
64
|
+
const convertedBlob = await window.heic2any({ blob }) as Blob
|
|
65
|
+
await cacheImage(url, convertedBlob)
|
|
66
|
+
return URL.createObjectURL(convertedBlob)
|
|
27
67
|
}
|
|
28
68
|
|
|
29
69
|
async function loadImage() {
|
|
30
|
-
|
|
31
|
-
|
|
70
|
+
loadingError = false
|
|
71
|
+
const url = getImageUrl()
|
|
32
72
|
if (!url) {
|
|
33
73
|
imageSrc = null
|
|
34
74
|
return
|
|
35
75
|
}
|
|
36
|
-
const ext = url.split('.').pop()?.toLowerCase().split('?').shift()
|
|
37
76
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
imageSrc = URL.createObjectURL(await cachedResponse.blob())
|
|
47
|
-
return
|
|
48
|
-
}
|
|
49
|
-
} catch (error) {
|
|
50
|
-
console.warn('Error accessing cache:', error)
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
try {
|
|
54
|
-
await appendScript('https://cdnjs.cloudflare.com/ajax/libs/heic2any/0.0.1/index.min.js')
|
|
55
|
-
const response = await fetch(normalizeURL(url))
|
|
56
|
-
const blob = await response.blob()
|
|
57
|
-
const convertedBlob = await window.heic2any({ blob }) as Blob
|
|
58
|
-
imageSrc = URL.createObjectURL(convertedBlob)
|
|
59
|
-
// Only attempt to cache if the cache API is available
|
|
60
|
-
if ('caches' in window) {
|
|
61
|
-
try {
|
|
62
|
-
const imgCache = await window.caches.open('img-cache')
|
|
63
|
-
imgCache.put(url, new Response(convertedBlob))
|
|
64
|
-
} catch (cacheError) {
|
|
65
|
-
console.warn('Failed to cache the image:', cacheError)
|
|
66
|
-
}
|
|
77
|
+
try {
|
|
78
|
+
const ext = url.split('.').pop()?.toLowerCase().split('?')[0]
|
|
79
|
+
|
|
80
|
+
if (ext === 'heic') {
|
|
81
|
+
const cachedSrc = await getCachedImage(url)
|
|
82
|
+
if (cachedSrc) {
|
|
83
|
+
imageSrc = cachedSrc
|
|
84
|
+
return
|
|
67
85
|
}
|
|
68
|
-
|
|
69
|
-
|
|
86
|
+
imageSrc = await convertHeicImage(url)
|
|
87
|
+
} else {
|
|
88
|
+
imageSrc = url
|
|
70
89
|
}
|
|
71
|
-
}
|
|
72
|
-
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error('Image loading error:', error)
|
|
92
|
+
loadingError = true
|
|
93
|
+
imageSrc = null
|
|
73
94
|
}
|
|
74
95
|
}
|
|
75
|
-
|
|
96
|
+
|
|
97
|
+
watch(() => [props.src, props.pathKey], loadImage, { immediate: true })
|
|
76
98
|
</script>
|
|
77
99
|
|
|
78
100
|
<template>
|
|
79
101
|
<figcaption v-if="caption">
|
|
80
|
-
<img
|
|
102
|
+
<img
|
|
103
|
+
v-if="imageSrc"
|
|
104
|
+
:src="imageSrc"
|
|
105
|
+
v-bind="$attrs"
|
|
106
|
+
:alt="alt"
|
|
107
|
+
:width="normalizeDimension(width)"
|
|
108
|
+
:height="normalizeDimension(height)"
|
|
109
|
+
>
|
|
81
110
|
<Skeleton
|
|
82
111
|
v-else
|
|
83
112
|
class="img-web-kit"
|
|
@@ -85,7 +114,25 @@ watch(() => [src, pathKey], loadImage, { immediate: true })
|
|
|
85
114
|
:height="normalizeDimension(height)"
|
|
86
115
|
/>
|
|
87
116
|
</figcaption>
|
|
88
|
-
|
|
117
|
+
|
|
118
|
+
<img
|
|
119
|
+
v-else-if="imageSrc"
|
|
120
|
+
:src="imageSrc"
|
|
121
|
+
v-bind="$attrs"
|
|
122
|
+
:alt="alt"
|
|
123
|
+
:width="normalizeDimension(width)"
|
|
124
|
+
:height="normalizeDimension(height)"
|
|
125
|
+
>
|
|
126
|
+
<div
|
|
127
|
+
v-else-if="loadingError"
|
|
128
|
+
class="flex-center error-image"
|
|
129
|
+
:style="{
|
|
130
|
+
width: normalizeDimension(width),
|
|
131
|
+
height: normalizeDimension(height),
|
|
132
|
+
}"
|
|
133
|
+
>
|
|
134
|
+
<Icon name="broken_image" />
|
|
135
|
+
</div>
|
|
89
136
|
<Skeleton
|
|
90
137
|
v-else
|
|
91
138
|
class="img-web-kit"
|
|
@@ -101,4 +148,7 @@ watch(() => [src, pathKey], loadImage, { immediate: true })
|
|
|
101
148
|
border: 0;
|
|
102
149
|
width: 100%;
|
|
103
150
|
}
|
|
151
|
+
.error-image {
|
|
152
|
+
background-color: var(--skeleton-bg);
|
|
153
|
+
}
|
|
104
154
|
</style>
|
|
@@ -35,6 +35,7 @@ function runAction(name: ToolbarConfigOption, value?: string) {
|
|
|
35
35
|
v-else-if="action.name !== 'separator'" v-tooltip="action.label" :icon="action.icon" thin flat
|
|
36
36
|
:aria-label="action.name" :class="[action.class, { active: selectedStyles.has(action.name) }]"
|
|
37
37
|
class=""
|
|
38
|
+
tabindex="-1"
|
|
38
39
|
@click="runAction(action.name)"
|
|
39
40
|
/>
|
|
40
41
|
<span v-else-if="action.name === 'separator'" :key="`separator-${index}`" class="opacity-2 mb-025">|</span>
|