@myoc/element 0.19.532 → 0.19.533
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/dev/index.js +783 -16
- package/dist/dev/index.js.map +4 -4
- package/dist/prod/index.js +15 -15
- package/dist/types/common/src/constants.d.ts +1 -0
- package/dist/types/element/src/gif.d.ts +29 -0
- package/dist/types/element/src/image.d.ts +6 -1
- package/dist/types/element/src/index.d.ts +2 -0
- package/dist/types/element/src/newElement.d.ts +1 -0
- package/dist/types/element/src/renderGif.d.ts +5 -0
- package/dist/types/element/src/types.d.ts +12 -0
- package/dist/types/excalidraw/actions/actionBoundText.d.ts +2 -2
- package/dist/types/excalidraw/actions/actionCanvas.d.ts +6 -6
- package/dist/types/excalidraw/actions/actionClipboard.d.ts +2 -2
- package/dist/types/excalidraw/actions/actionCropEditor.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +3 -3
- package/dist/types/excalidraw/actions/actionDeselect.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionElementLock.d.ts +2 -2
- package/dist/types/excalidraw/actions/actionExport.d.ts +2 -2
- package/dist/types/excalidraw/actions/actionFrame.d.ts +4 -3
- package/dist/types/excalidraw/actions/actionGroup.d.ts +2 -2
- package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +2 -1
- package/dist/types/excalidraw/actions/actionLink.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionProperties.d.ts +2 -2
- package/dist/types/excalidraw/actions/actionSelectAll.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionStyles.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleArrowBinding.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleMidpointSnapping.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleStats.d.ts +1 -1
- package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +1 -1
- package/dist/types/excalidraw/components/App.d.ts +8 -1
- package/dist/types/excalidraw/components/App.gif.d.ts +18 -0
- package/dist/types/excalidraw/components/GifPlaybackControls.d.ts +10 -0
- package/dist/types/excalidraw/components/icons.d.ts +4 -0
- package/dist/types/excalidraw/data/blob.d.ts +2 -2
- package/dist/types/excalidraw/data/json.d.ts +1 -1
- package/dist/types/excalidraw/data/restoreGif.d.ts +4 -0
- package/dist/types/excalidraw/scene/Renderer.d.ts +1 -0
- package/dist/types/excalidraw/scene/types.d.ts +2 -1
- package/dist/types/excalidraw/types.d.ts +12 -2
- package/dist/types/excalidraw/viewport.d.ts +1 -1
- package/package.json +5 -4
package/dist/dev/index.js
CHANGED
|
@@ -14535,7 +14535,11 @@ var determineCustomLinearAngle = (pivotPoint, draggedPoint) => Math.atan2(dragge
|
|
|
14535
14535
|
|
|
14536
14536
|
// src/image.ts
|
|
14537
14537
|
init_define_import_meta_env();
|
|
14538
|
-
import {
|
|
14538
|
+
import {
|
|
14539
|
+
DEFAULT_GIF_AUTO_DECODE_MAX_FILE_SIZE_BYTES,
|
|
14540
|
+
MIME_TYPES,
|
|
14541
|
+
SVG_NS
|
|
14542
|
+
} from "@excalidraw/common";
|
|
14539
14543
|
|
|
14540
14544
|
// ../../node_modules/thumbhash/thumbhash.js
|
|
14541
14545
|
init_define_import_meta_env();
|
|
@@ -14689,6 +14693,614 @@ function thumbHashToApproximateAspectRatio(hash) {
|
|
|
14689
14693
|
return lx / ly;
|
|
14690
14694
|
}
|
|
14691
14695
|
|
|
14696
|
+
// src/gif.ts
|
|
14697
|
+
init_define_import_meta_env();
|
|
14698
|
+
|
|
14699
|
+
// ../../node_modules/modern-gif/dist/index.mjs
|
|
14700
|
+
init_define_import_meta_env();
|
|
14701
|
+
var SIGNATURE = "GIF";
|
|
14702
|
+
var VERSIONS = ["87a", "89a"];
|
|
14703
|
+
var IMAGE_DESCRIPTOR = 44;
|
|
14704
|
+
var EXTENSION = 33;
|
|
14705
|
+
var EXTENSION_APPLICATION = 255;
|
|
14706
|
+
var EXTENSION_APPLICATION_BLOCK_SIZE = 11;
|
|
14707
|
+
var EXTENSION_COMMENT = 254;
|
|
14708
|
+
var EXTENSION_GRAPHIC_CONTROL = 249;
|
|
14709
|
+
var EXTENSION_GRAPHIC_CONTROL_BLOCK_SIZE = 4;
|
|
14710
|
+
var EXTENSION_PLAIN_TEXT = 1;
|
|
14711
|
+
var EXTENSION_PLAIN_TEXT_BLOCK_SIZE = 1;
|
|
14712
|
+
var TRAILER = 59;
|
|
14713
|
+
function mergeBuffers(buffers) {
|
|
14714
|
+
const container = new Uint8Array(
|
|
14715
|
+
buffers.reduce((total, array) => total + array.byteLength, 0)
|
|
14716
|
+
);
|
|
14717
|
+
buffers.reduce((offset, array) => {
|
|
14718
|
+
container.set(array, offset);
|
|
14719
|
+
return offset + array.byteLength;
|
|
14720
|
+
}, 0);
|
|
14721
|
+
return container;
|
|
14722
|
+
}
|
|
14723
|
+
function resovleSource(source, output, options) {
|
|
14724
|
+
let buffer;
|
|
14725
|
+
if (ArrayBuffer.isView(source)) {
|
|
14726
|
+
buffer = source.buffer;
|
|
14727
|
+
} else if (source instanceof ArrayBuffer) {
|
|
14728
|
+
buffer = source;
|
|
14729
|
+
} else {
|
|
14730
|
+
const canvas = document.createElement("canvas");
|
|
14731
|
+
const { width, height } = options || {};
|
|
14732
|
+
const context2d = canvas.getContext("2d");
|
|
14733
|
+
if (!context2d) {
|
|
14734
|
+
throw new Error("Failed to create canvas context2d");
|
|
14735
|
+
}
|
|
14736
|
+
canvas.width = width ?? ("width" in source ? typeof source.width === "number" ? source.width : source.width.baseVal.value : 0);
|
|
14737
|
+
canvas.height = height ?? ("height" in source ? typeof source.height === "number" ? source.height : source.height.baseVal.value : 0);
|
|
14738
|
+
context2d.drawImage(source, 0, 0, canvas.width, canvas.height);
|
|
14739
|
+
buffer = context2d.getImageData(0, 0, canvas.width, canvas.height).data.buffer;
|
|
14740
|
+
}
|
|
14741
|
+
switch (output) {
|
|
14742
|
+
case "uint8Array":
|
|
14743
|
+
return new Uint8Array(buffer);
|
|
14744
|
+
case "uint8ClampedArray":
|
|
14745
|
+
return new Uint8ClampedArray(buffer);
|
|
14746
|
+
case "dataView":
|
|
14747
|
+
return new DataView(buffer);
|
|
14748
|
+
default:
|
|
14749
|
+
throw new Error("Unsupported output format");
|
|
14750
|
+
}
|
|
14751
|
+
}
|
|
14752
|
+
var Reader = class {
|
|
14753
|
+
_view;
|
|
14754
|
+
offset = 0;
|
|
14755
|
+
constructor(source) {
|
|
14756
|
+
this._view = resovleSource(source, "dataView");
|
|
14757
|
+
}
|
|
14758
|
+
readByte() {
|
|
14759
|
+
return this._view.getUint8(this.offset++);
|
|
14760
|
+
}
|
|
14761
|
+
readBytes(length) {
|
|
14762
|
+
return Array.from({ length }).map(() => this.readByte());
|
|
14763
|
+
}
|
|
14764
|
+
readString(length) {
|
|
14765
|
+
return String.fromCharCode(...this.readBytes(length));
|
|
14766
|
+
}
|
|
14767
|
+
readUnsigned() {
|
|
14768
|
+
return [this._view.getUint16(this.offset, true), this.offset += 2][0];
|
|
14769
|
+
}
|
|
14770
|
+
readBits() {
|
|
14771
|
+
return this._view.getUint8(this.offset++).toString(2).padStart(8, "0").split("").map(Number);
|
|
14772
|
+
}
|
|
14773
|
+
readColorTable(length) {
|
|
14774
|
+
return Array.from({ length }, () => Array.from(this.readBytes(3)));
|
|
14775
|
+
}
|
|
14776
|
+
readSubBlock() {
|
|
14777
|
+
const block = [];
|
|
14778
|
+
while (true) {
|
|
14779
|
+
const val = this.readByte();
|
|
14780
|
+
if (val === 0 && this._view.getUint8(this.offset) !== 0)
|
|
14781
|
+
break;
|
|
14782
|
+
block.push(val);
|
|
14783
|
+
}
|
|
14784
|
+
return block;
|
|
14785
|
+
}
|
|
14786
|
+
};
|
|
14787
|
+
function decode(source) {
|
|
14788
|
+
const gif = {};
|
|
14789
|
+
const reader = new Reader(source);
|
|
14790
|
+
const createFrame = () => ({ index: 0, delay: 100, disposal: 0 });
|
|
14791
|
+
const signature = reader.readString(3);
|
|
14792
|
+
const version = reader.readString(3);
|
|
14793
|
+
if (signature !== SIGNATURE || !VERSIONS.includes(version)) {
|
|
14794
|
+
throw new Error("This is not a 87a/89a GIF data.");
|
|
14795
|
+
}
|
|
14796
|
+
gif.version = version;
|
|
14797
|
+
gif.width = reader.readUnsigned();
|
|
14798
|
+
gif.height = reader.readUnsigned();
|
|
14799
|
+
const bits = reader.readBits();
|
|
14800
|
+
gif.globalColorTable = Boolean(bits[0]);
|
|
14801
|
+
gif.colorResoluTion = Number.parseInt(bits.slice(1, 4).join(""), 2) + 1;
|
|
14802
|
+
gif.colorTableSorted = Boolean(bits[4]);
|
|
14803
|
+
const colorTableSize = Number.parseInt(bits.slice(5, 8).join(""), 2);
|
|
14804
|
+
gif.colorTableSize = 2 ** (colorTableSize + 1);
|
|
14805
|
+
gif.backgroundColorIndex = reader.readByte();
|
|
14806
|
+
gif.pixelAspectRatio = reader.readByte();
|
|
14807
|
+
if (gif.globalColorTable) {
|
|
14808
|
+
if (gif.colorTableSize) {
|
|
14809
|
+
gif.colorTable = reader.readColorTable(gif.colorTableSize);
|
|
14810
|
+
} else {
|
|
14811
|
+
reader.readSubBlock();
|
|
14812
|
+
}
|
|
14813
|
+
}
|
|
14814
|
+
gif.frames = [];
|
|
14815
|
+
let frame = createFrame();
|
|
14816
|
+
const flags = [];
|
|
14817
|
+
const extensionFlags = [];
|
|
14818
|
+
while (true) {
|
|
14819
|
+
const flag = reader.readByte();
|
|
14820
|
+
flags.push(flag);
|
|
14821
|
+
if (flag === IMAGE_DESCRIPTOR) {
|
|
14822
|
+
frame.left = reader.readUnsigned();
|
|
14823
|
+
frame.top = reader.readUnsigned();
|
|
14824
|
+
frame.width = reader.readUnsigned();
|
|
14825
|
+
frame.height = reader.readUnsigned();
|
|
14826
|
+
const bits2 = reader.readBits();
|
|
14827
|
+
frame.localColorTable = Boolean(bits2[0]);
|
|
14828
|
+
frame.interlaced = Boolean(bits2[1]);
|
|
14829
|
+
frame.colorTableSorted = Boolean(bits2[2]);
|
|
14830
|
+
frame.reserved = Number.parseInt(bits2.slice(3, 5).join(""), 2);
|
|
14831
|
+
const colorTableSize2 = Number.parseInt(bits2.slice(5, 8).join(""), 2);
|
|
14832
|
+
frame.colorTableSize = 2 ** (colorTableSize2 + 1);
|
|
14833
|
+
if (frame.localColorTable) {
|
|
14834
|
+
frame.colorTable = reader.readColorTable(frame.colorTableSize);
|
|
14835
|
+
}
|
|
14836
|
+
frame.lzwMinCodeSize = reader.readByte();
|
|
14837
|
+
frame.dataPositions = [];
|
|
14838
|
+
while (true) {
|
|
14839
|
+
const length = reader.readByte();
|
|
14840
|
+
if (length === 0)
|
|
14841
|
+
break;
|
|
14842
|
+
const offset = reader.offset;
|
|
14843
|
+
frame.dataPositions.push([offset, length]);
|
|
14844
|
+
reader.offset = offset + length;
|
|
14845
|
+
}
|
|
14846
|
+
gif.frames.push(frame);
|
|
14847
|
+
frame = createFrame();
|
|
14848
|
+
frame.index = gif.frames.length;
|
|
14849
|
+
continue;
|
|
14850
|
+
}
|
|
14851
|
+
if (flag === EXTENSION) {
|
|
14852
|
+
const extensionFlag = reader.readByte();
|
|
14853
|
+
extensionFlags.push(extensionFlag);
|
|
14854
|
+
if (extensionFlag === EXTENSION_APPLICATION) {
|
|
14855
|
+
if (reader.readByte() !== EXTENSION_APPLICATION_BLOCK_SIZE)
|
|
14856
|
+
continue;
|
|
14857
|
+
const application = {
|
|
14858
|
+
identifier: reader.readString(8),
|
|
14859
|
+
code: reader.readString(3),
|
|
14860
|
+
data: []
|
|
14861
|
+
};
|
|
14862
|
+
if (`${application.identifier}${application.code}` === "NETSCAPE2.0") {
|
|
14863
|
+
if (reader.readByte() === 3) {
|
|
14864
|
+
gif.looped = Boolean(reader.readByte());
|
|
14865
|
+
gif.loopCount = reader.readUnsigned();
|
|
14866
|
+
}
|
|
14867
|
+
}
|
|
14868
|
+
application.data = reader.readSubBlock();
|
|
14869
|
+
frame.application = application;
|
|
14870
|
+
continue;
|
|
14871
|
+
}
|
|
14872
|
+
if (extensionFlag === EXTENSION_COMMENT) {
|
|
14873
|
+
frame.comment = reader.readSubBlock().map((val) => String.fromCharCode(val)).join("");
|
|
14874
|
+
continue;
|
|
14875
|
+
}
|
|
14876
|
+
if (extensionFlag === EXTENSION_GRAPHIC_CONTROL) {
|
|
14877
|
+
if (reader.readByte() !== EXTENSION_GRAPHIC_CONTROL_BLOCK_SIZE)
|
|
14878
|
+
continue;
|
|
14879
|
+
const bits2 = reader.readBits();
|
|
14880
|
+
const graphicControl = {
|
|
14881
|
+
// ↓ <Packed Fields>
|
|
14882
|
+
reserved: Number.parseInt(bits2.slice(0, 3).join(""), 2),
|
|
14883
|
+
disposal: Number.parseInt(bits2.slice(3, 6).join(""), 2),
|
|
14884
|
+
userInput: Boolean(bits2[6]),
|
|
14885
|
+
transparent: Boolean(bits2[7]),
|
|
14886
|
+
// ↑ <Packed Fields>
|
|
14887
|
+
delayTime: reader.readUnsigned(),
|
|
14888
|
+
transparentIndex: reader.readByte()
|
|
14889
|
+
};
|
|
14890
|
+
reader.readSubBlock();
|
|
14891
|
+
frame.graphicControl = graphicControl;
|
|
14892
|
+
frame.disposal = graphicControl.disposal;
|
|
14893
|
+
frame.delay = (graphicControl.delayTime || 10) * 10;
|
|
14894
|
+
continue;
|
|
14895
|
+
}
|
|
14896
|
+
if (extensionFlag === EXTENSION_PLAIN_TEXT) {
|
|
14897
|
+
if (reader.readByte() !== EXTENSION_PLAIN_TEXT_BLOCK_SIZE)
|
|
14898
|
+
continue;
|
|
14899
|
+
frame.plainText = {
|
|
14900
|
+
left: reader.readUnsigned(),
|
|
14901
|
+
top: reader.readUnsigned(),
|
|
14902
|
+
width: reader.readUnsigned(),
|
|
14903
|
+
height: reader.readUnsigned(),
|
|
14904
|
+
cellWidth: reader.readByte(),
|
|
14905
|
+
cellHeight: reader.readByte(),
|
|
14906
|
+
colorIndex: reader.readByte(),
|
|
14907
|
+
backgroundColorIndex: reader.readByte(),
|
|
14908
|
+
data: reader.readSubBlock()
|
|
14909
|
+
};
|
|
14910
|
+
continue;
|
|
14911
|
+
}
|
|
14912
|
+
console.warn(
|
|
14913
|
+
`Unknown extension block: 0x${extensionFlag.toString(16)}`,
|
|
14914
|
+
flags.slice(0, flags.length - 1).map((val) => `0x${val.toString(16)}`),
|
|
14915
|
+
extensionFlags.slice(0, extensionFlags.length - 1).map((val) => `0x${val.toString(16)}`)
|
|
14916
|
+
);
|
|
14917
|
+
continue;
|
|
14918
|
+
}
|
|
14919
|
+
if (flag === TRAILER)
|
|
14920
|
+
break;
|
|
14921
|
+
console.warn(
|
|
14922
|
+
`Unknown block: 0x${flag.toString(16)}`,
|
|
14923
|
+
flags.slice(0, flags.length - 1).map((val) => `0x${val.toString(16)}`),
|
|
14924
|
+
extensionFlags.slice(0, extensionFlags.length - 1).map((val) => `0x${val.toString(16)}`)
|
|
14925
|
+
);
|
|
14926
|
+
}
|
|
14927
|
+
return gif;
|
|
14928
|
+
}
|
|
14929
|
+
function createWorker(options) {
|
|
14930
|
+
const callbacks = /* @__PURE__ */ new Map();
|
|
14931
|
+
const { workerUrl } = options;
|
|
14932
|
+
let { workerNumber = 1 } = options;
|
|
14933
|
+
const workers = [...Array.from({ length: workerUrl ? workerNumber : 0 })].map(() => {
|
|
14934
|
+
try {
|
|
14935
|
+
const worker = new Worker(workerUrl);
|
|
14936
|
+
worker.onmessage = onMessage;
|
|
14937
|
+
return worker;
|
|
14938
|
+
} catch (err) {
|
|
14939
|
+
console.warn(err);
|
|
14940
|
+
return null;
|
|
14941
|
+
}
|
|
14942
|
+
}).filter(Boolean);
|
|
14943
|
+
workerNumber = workers.length;
|
|
14944
|
+
function onMessage(event) {
|
|
14945
|
+
const { id, data } = event.data;
|
|
14946
|
+
callbacks.get(id)?.(data);
|
|
14947
|
+
callbacks.delete(id);
|
|
14948
|
+
}
|
|
14949
|
+
const getWorker = /* @__PURE__ */ function() {
|
|
14950
|
+
let id = 0;
|
|
14951
|
+
return (index) => workers[(index ?? id++) % workerNumber];
|
|
14952
|
+
}();
|
|
14953
|
+
const call = /* @__PURE__ */ function() {
|
|
14954
|
+
let id = 0;
|
|
14955
|
+
return (type, data, transfer, index) => {
|
|
14956
|
+
return new Promise((resolve) => {
|
|
14957
|
+
const worker = getWorker(index);
|
|
14958
|
+
if (!worker)
|
|
14959
|
+
return resolve(void 0);
|
|
14960
|
+
callbacks.set(id, resolve);
|
|
14961
|
+
worker.postMessage({ id: id++, type, data }, { transfer });
|
|
14962
|
+
});
|
|
14963
|
+
};
|
|
14964
|
+
}();
|
|
14965
|
+
return {
|
|
14966
|
+
call
|
|
14967
|
+
};
|
|
14968
|
+
}
|
|
14969
|
+
function deinterlace(pixels, width) {
|
|
14970
|
+
const newPixels = Array.from({ length: pixels.length });
|
|
14971
|
+
const rows = pixels.length / width;
|
|
14972
|
+
const offsets = [0, 4, 2, 1];
|
|
14973
|
+
const steps = [8, 8, 4, 2];
|
|
14974
|
+
let fromRow = 0;
|
|
14975
|
+
for (let pass = 0; pass < 4; pass++) {
|
|
14976
|
+
for (let toRow = offsets[pass]; toRow < rows; toRow += steps[pass]) {
|
|
14977
|
+
newPixels.splice.apply(
|
|
14978
|
+
newPixels,
|
|
14979
|
+
[toRow * width, width].concat(
|
|
14980
|
+
pixels.slice(fromRow * width, (fromRow + 1) * width)
|
|
14981
|
+
)
|
|
14982
|
+
);
|
|
14983
|
+
fromRow++;
|
|
14984
|
+
}
|
|
14985
|
+
}
|
|
14986
|
+
return newPixels;
|
|
14987
|
+
}
|
|
14988
|
+
function lzwDecode(minCodeSize, data, pixelCount) {
|
|
14989
|
+
const MAX_STACK_SIZE = 4096;
|
|
14990
|
+
const nullCode = -1;
|
|
14991
|
+
const npix = pixelCount;
|
|
14992
|
+
let available, codeMask, codeSize, inCode, oldCode, code, i;
|
|
14993
|
+
const dstPixels = Array.from({ length: pixelCount });
|
|
14994
|
+
const prefix = Array.from({ length: MAX_STACK_SIZE });
|
|
14995
|
+
const suffix = Array.from({ length: MAX_STACK_SIZE });
|
|
14996
|
+
const pixelStack = Array.from({ length: MAX_STACK_SIZE + 1 });
|
|
14997
|
+
const dataSize = minCodeSize;
|
|
14998
|
+
const clear = 1 << dataSize;
|
|
14999
|
+
const endOfInformation = clear + 1;
|
|
15000
|
+
available = clear + 2;
|
|
15001
|
+
oldCode = nullCode;
|
|
15002
|
+
codeSize = dataSize + 1;
|
|
15003
|
+
codeMask = (1 << codeSize) - 1;
|
|
15004
|
+
for (code = 0; code < clear; code++) {
|
|
15005
|
+
prefix[code] = 0;
|
|
15006
|
+
suffix[code] = code;
|
|
15007
|
+
}
|
|
15008
|
+
let datum, bits, first, top, pi, bi;
|
|
15009
|
+
datum = bits = first = top = pi = bi = 0;
|
|
15010
|
+
for (i = 0; i < npix; ) {
|
|
15011
|
+
if (top === 0) {
|
|
15012
|
+
if (bits < codeSize) {
|
|
15013
|
+
datum += data[bi] << bits;
|
|
15014
|
+
bits += 8;
|
|
15015
|
+
bi++;
|
|
15016
|
+
continue;
|
|
15017
|
+
}
|
|
15018
|
+
code = datum & codeMask;
|
|
15019
|
+
datum >>= codeSize;
|
|
15020
|
+
bits -= codeSize;
|
|
15021
|
+
if (code > available || code === endOfInformation) {
|
|
15022
|
+
break;
|
|
15023
|
+
}
|
|
15024
|
+
if (code === clear) {
|
|
15025
|
+
codeSize = dataSize + 1;
|
|
15026
|
+
codeMask = (1 << codeSize) - 1;
|
|
15027
|
+
available = clear + 2;
|
|
15028
|
+
oldCode = nullCode;
|
|
15029
|
+
continue;
|
|
15030
|
+
}
|
|
15031
|
+
if (oldCode === nullCode) {
|
|
15032
|
+
pixelStack[top++] = suffix[code];
|
|
15033
|
+
oldCode = code;
|
|
15034
|
+
first = code;
|
|
15035
|
+
continue;
|
|
15036
|
+
}
|
|
15037
|
+
inCode = code;
|
|
15038
|
+
if (code === available) {
|
|
15039
|
+
pixelStack[top++] = first;
|
|
15040
|
+
code = oldCode;
|
|
15041
|
+
}
|
|
15042
|
+
while (code > clear) {
|
|
15043
|
+
pixelStack[top++] = suffix[code];
|
|
15044
|
+
code = prefix[code];
|
|
15045
|
+
}
|
|
15046
|
+
first = suffix[code] & 255;
|
|
15047
|
+
pixelStack[top++] = first;
|
|
15048
|
+
if (available < MAX_STACK_SIZE) {
|
|
15049
|
+
prefix[available] = oldCode;
|
|
15050
|
+
suffix[available] = first;
|
|
15051
|
+
available++;
|
|
15052
|
+
if ((available & codeMask) === 0 && available < MAX_STACK_SIZE) {
|
|
15053
|
+
codeSize++;
|
|
15054
|
+
codeMask += available;
|
|
15055
|
+
}
|
|
15056
|
+
}
|
|
15057
|
+
oldCode = inCode;
|
|
15058
|
+
}
|
|
15059
|
+
top--;
|
|
15060
|
+
dstPixels[pi++] = pixelStack[top];
|
|
15061
|
+
i++;
|
|
15062
|
+
}
|
|
15063
|
+
for (i = pi; i < npix; i++) {
|
|
15064
|
+
dstPixels[i] = 0;
|
|
15065
|
+
}
|
|
15066
|
+
return dstPixels;
|
|
15067
|
+
}
|
|
15068
|
+
function decodeFrames(source, options) {
|
|
15069
|
+
const array = resovleSource(source, "uint8Array");
|
|
15070
|
+
if (options?.workerUrl) {
|
|
15071
|
+
return createWorker({ workerUrl: options.workerUrl }).call(
|
|
15072
|
+
"frames:decode",
|
|
15073
|
+
array,
|
|
15074
|
+
[array.buffer]
|
|
15075
|
+
);
|
|
15076
|
+
}
|
|
15077
|
+
const {
|
|
15078
|
+
gif = decode(source),
|
|
15079
|
+
range
|
|
15080
|
+
} = options ?? {};
|
|
15081
|
+
const {
|
|
15082
|
+
width: globalWidth,
|
|
15083
|
+
height: globalHeight,
|
|
15084
|
+
colorTable: globalColorTable,
|
|
15085
|
+
frames: globalFrames
|
|
15086
|
+
} = gif;
|
|
15087
|
+
const frames2 = range ? globalFrames.slice(range[0], range[1] + 1) : globalFrames;
|
|
15088
|
+
const hasDisposal3 = frames2.some((frame) => frame.disposal === 3);
|
|
15089
|
+
let pixels = new Uint8ClampedArray(globalWidth * globalHeight * 4);
|
|
15090
|
+
let previousFrame;
|
|
15091
|
+
let previousPixels = pixels.slice();
|
|
15092
|
+
return frames2.map((frame) => {
|
|
15093
|
+
const {
|
|
15094
|
+
left,
|
|
15095
|
+
top,
|
|
15096
|
+
width,
|
|
15097
|
+
height,
|
|
15098
|
+
interlaced,
|
|
15099
|
+
localColorTable,
|
|
15100
|
+
colorTable,
|
|
15101
|
+
lzwMinCodeSize,
|
|
15102
|
+
dataPositions,
|
|
15103
|
+
graphicControl,
|
|
15104
|
+
delay,
|
|
15105
|
+
disposal
|
|
15106
|
+
} = frame;
|
|
15107
|
+
const previousDisposal = previousFrame?.disposal;
|
|
15108
|
+
const bottom = top + height;
|
|
15109
|
+
const {
|
|
15110
|
+
transparent,
|
|
15111
|
+
transparentIndex: localTransparentIndex
|
|
15112
|
+
} = graphicControl ?? {};
|
|
15113
|
+
const palette2 = localColorTable ? colorTable : globalColorTable;
|
|
15114
|
+
const transparentIndex = transparent ? localTransparentIndex : -1;
|
|
15115
|
+
const compressedData = mergeBuffers(
|
|
15116
|
+
dataPositions.map(
|
|
15117
|
+
([begin, length]) => array.subarray(begin, begin + length)
|
|
15118
|
+
)
|
|
15119
|
+
);
|
|
15120
|
+
let colorIndexes = lzwDecode(lzwMinCodeSize, compressedData, width * height);
|
|
15121
|
+
if (interlaced) {
|
|
15122
|
+
colorIndexes = deinterlace(colorIndexes, width);
|
|
15123
|
+
}
|
|
15124
|
+
if (previousDisposal === 3) {
|
|
15125
|
+
pixels = previousPixels.slice();
|
|
15126
|
+
} else if (previousDisposal === 2) {
|
|
15127
|
+
const { left: left2, top: top2, width: width2, height: height2 } = previousFrame;
|
|
15128
|
+
const bottom2 = top2 + height2;
|
|
15129
|
+
for (let y = top2; y < bottom2; y++) {
|
|
15130
|
+
const globalOffset = y * globalWidth + left2;
|
|
15131
|
+
for (let x = 0; x < width2; x++) {
|
|
15132
|
+
const index = (globalOffset + x) * 4;
|
|
15133
|
+
pixels[index] = pixels[index + 1] = pixels[index + 2] = pixels[index + 3] = 0;
|
|
15134
|
+
}
|
|
15135
|
+
}
|
|
15136
|
+
}
|
|
15137
|
+
for (let y = top; y < bottom; y++) {
|
|
15138
|
+
const globalOffset = y * globalWidth + left;
|
|
15139
|
+
const localOffset = (y - top) * width;
|
|
15140
|
+
for (let x = 0; x < width; x++) {
|
|
15141
|
+
const colorIndex = colorIndexes[localOffset + x];
|
|
15142
|
+
const index = (globalOffset + x) * 4;
|
|
15143
|
+
if (colorIndex !== transparentIndex) {
|
|
15144
|
+
const [r, g, b2] = palette2?.[colorIndex] ?? [0, 0, 0];
|
|
15145
|
+
pixels[index] = r;
|
|
15146
|
+
pixels[index + 1] = g;
|
|
15147
|
+
pixels[index + 2] = b2;
|
|
15148
|
+
pixels[index + 3] = 255;
|
|
15149
|
+
}
|
|
15150
|
+
}
|
|
15151
|
+
}
|
|
15152
|
+
if (hasDisposal3 && disposal !== 1 && disposal !== 3) {
|
|
15153
|
+
previousPixels = pixels.slice();
|
|
15154
|
+
}
|
|
15155
|
+
previousFrame = frame;
|
|
15156
|
+
return {
|
|
15157
|
+
width: globalWidth,
|
|
15158
|
+
height: globalHeight,
|
|
15159
|
+
delay,
|
|
15160
|
+
data: pixels.slice()
|
|
15161
|
+
};
|
|
15162
|
+
});
|
|
15163
|
+
}
|
|
15164
|
+
var ditherKernels = {
|
|
15165
|
+
"floyd-steinberg": [
|
|
15166
|
+
[7 / 16, 1, 0],
|
|
15167
|
+
[3 / 16, -1, 1],
|
|
15168
|
+
[5 / 16, 0, 1],
|
|
15169
|
+
[1 / 16, 1, 1]
|
|
15170
|
+
],
|
|
15171
|
+
"atkinson": [
|
|
15172
|
+
[1 / 8, 1, 0],
|
|
15173
|
+
[1 / 8, 2, 0],
|
|
15174
|
+
[1 / 8, -1, 1],
|
|
15175
|
+
[1 / 8, 0, 1],
|
|
15176
|
+
[1 / 8, 1, 1],
|
|
15177
|
+
[1 / 8, 0, 2]
|
|
15178
|
+
],
|
|
15179
|
+
"stucki": [
|
|
15180
|
+
[8 / 42, 1, 0],
|
|
15181
|
+
[4 / 42, 2, 0],
|
|
15182
|
+
[2 / 42, -2, 1],
|
|
15183
|
+
[4 / 42, -1, 1],
|
|
15184
|
+
[8 / 42, 0, 1],
|
|
15185
|
+
[4 / 42, 1, 1],
|
|
15186
|
+
[2 / 42, 2, 1],
|
|
15187
|
+
[1 / 42, -2, 2],
|
|
15188
|
+
[2 / 42, -1, 2],
|
|
15189
|
+
[4 / 42, 0, 2],
|
|
15190
|
+
[2 / 42, 1, 2],
|
|
15191
|
+
[1 / 42, 2, 2]
|
|
15192
|
+
]
|
|
15193
|
+
};
|
|
15194
|
+
|
|
15195
|
+
// src/gif.ts
|
|
15196
|
+
var MAX_CONCURRENT_GIF_DECODES = 5;
|
|
15197
|
+
var gifWorkerUrl;
|
|
15198
|
+
var configureGifWorkerUrl = (workerUrl) => {
|
|
15199
|
+
gifWorkerUrl = workerUrl;
|
|
15200
|
+
};
|
|
15201
|
+
var dataURLToArrayBuffer = (dataURL) => {
|
|
15202
|
+
const dataIndexStart = dataURL.indexOf(",");
|
|
15203
|
+
const byteString = atob(dataURL.slice(dataIndexStart + 1));
|
|
15204
|
+
const buffer = new ArrayBuffer(byteString.length);
|
|
15205
|
+
const bytes = new Uint8Array(buffer);
|
|
15206
|
+
for (let index = 0; index < byteString.length; index++) {
|
|
15207
|
+
bytes[index] = byteString.charCodeAt(index);
|
|
15208
|
+
}
|
|
15209
|
+
return buffer;
|
|
15210
|
+
};
|
|
15211
|
+
var decodeGifFrames = async (dataURL) => {
|
|
15212
|
+
const buffer = dataURLToArrayBuffer(dataURL);
|
|
15213
|
+
const gif = decode(buffer);
|
|
15214
|
+
const decodedFrames = gifWorkerUrl ? await decodeFrames(buffer, { gif, workerUrl: gifWorkerUrl }) : await decodeFrames(buffer, { gif });
|
|
15215
|
+
const frames2 = decodedFrames.map((frame) => {
|
|
15216
|
+
const canvas = document.createElement("canvas");
|
|
15217
|
+
canvas.width = frame.width;
|
|
15218
|
+
canvas.height = frame.height;
|
|
15219
|
+
const context = canvas.getContext("2d");
|
|
15220
|
+
if (context) {
|
|
15221
|
+
const imageData = context.createImageData(frame.width, frame.height);
|
|
15222
|
+
imageData.data.set(frame.data);
|
|
15223
|
+
context.putImageData(imageData, 0, 0);
|
|
15224
|
+
}
|
|
15225
|
+
return canvas;
|
|
15226
|
+
});
|
|
15227
|
+
return {
|
|
15228
|
+
frames: frames2,
|
|
15229
|
+
delays: decodedFrames.map((frame) => Math.max(frame.delay, 16)),
|
|
15230
|
+
width: gif.width,
|
|
15231
|
+
height: gif.height
|
|
15232
|
+
};
|
|
15233
|
+
};
|
|
15234
|
+
var activeGifDecodeCount = 0;
|
|
15235
|
+
var gifDecodeSequence = 0;
|
|
15236
|
+
var gifDecodeSchedulePending = false;
|
|
15237
|
+
var gifDecodeQueue = [];
|
|
15238
|
+
var getDataURLByteLength = (dataURL) => {
|
|
15239
|
+
const dataIndexStart = dataURL.indexOf(",");
|
|
15240
|
+
const encoded = dataURL.slice(dataIndexStart + 1);
|
|
15241
|
+
const padding = encoded.endsWith("==") && 2 || encoded.endsWith("=") && 1 || 0;
|
|
15242
|
+
return Math.floor(encoded.length * 3 / 4) - padding;
|
|
15243
|
+
};
|
|
15244
|
+
var runGifDecodeTask = (task) => {
|
|
15245
|
+
activeGifDecodeCount++;
|
|
15246
|
+
decodeGifFrames(task.dataURL).then(task.resolve, task.reject).finally(() => {
|
|
15247
|
+
activeGifDecodeCount--;
|
|
15248
|
+
queueGifDecodeScheduler();
|
|
15249
|
+
});
|
|
15250
|
+
};
|
|
15251
|
+
var scheduleNextGifDecode = () => {
|
|
15252
|
+
gifDecodeSchedulePending = false;
|
|
15253
|
+
while (activeGifDecodeCount < MAX_CONCURRENT_GIF_DECODES && gifDecodeQueue.length) {
|
|
15254
|
+
runGifDecodeTask(gifDecodeQueue.shift());
|
|
15255
|
+
}
|
|
15256
|
+
};
|
|
15257
|
+
var queueGifDecodeScheduler = () => {
|
|
15258
|
+
if (gifDecodeSchedulePending) {
|
|
15259
|
+
return;
|
|
15260
|
+
}
|
|
15261
|
+
gifDecodeSchedulePending = true;
|
|
15262
|
+
queueMicrotask(scheduleNextGifDecode);
|
|
15263
|
+
};
|
|
15264
|
+
var decodeGifFramesQueued = (dataURL) => {
|
|
15265
|
+
return new Promise((resolve, reject) => {
|
|
15266
|
+
const task = {
|
|
15267
|
+
dataURL,
|
|
15268
|
+
priority: getDataURLByteLength(dataURL),
|
|
15269
|
+
sequence: gifDecodeSequence++,
|
|
15270
|
+
resolve,
|
|
15271
|
+
reject
|
|
15272
|
+
};
|
|
15273
|
+
const insertionIndex = gifDecodeQueue.findIndex(
|
|
15274
|
+
(queuedTask) => queuedTask.priority > task.priority || queuedTask.priority === task.priority && queuedTask.sequence > task.sequence
|
|
15275
|
+
);
|
|
15276
|
+
if (insertionIndex === -1) {
|
|
15277
|
+
gifDecodeQueue.push(task);
|
|
15278
|
+
} else {
|
|
15279
|
+
gifDecodeQueue.splice(insertionIndex, 0, task);
|
|
15280
|
+
}
|
|
15281
|
+
queueGifDecodeScheduler();
|
|
15282
|
+
});
|
|
15283
|
+
};
|
|
15284
|
+
var createGifPlaybackMetadata = (opts = {}) => ({
|
|
15285
|
+
frameIndex: 0,
|
|
15286
|
+
speed: 1,
|
|
15287
|
+
playing: opts.playing ?? false
|
|
15288
|
+
});
|
|
15289
|
+
var getGifRenderFrame = (element, cacheEntry, runtimeFrameIndex) => {
|
|
15290
|
+
const gifFrameIndex = element.gifPlayback?.playing ? runtimeFrameIndex ?? element.gifPlayback.frameIndex : element.gifPlayback?.frameIndex ?? 0;
|
|
15291
|
+
return cacheEntry?.gif?.frames[gifFrameIndex];
|
|
15292
|
+
};
|
|
15293
|
+
var hasActiveGifDecode = (visibleElements, imageCache) => visibleElements.some((element) => {
|
|
15294
|
+
if (!isInitializedImageElement(element)) {
|
|
15295
|
+
return false;
|
|
15296
|
+
}
|
|
15297
|
+
const cacheEntry = imageCache.get(element.fileId);
|
|
15298
|
+
return cacheEntry?.gifDecodeStatus === "pending" && !cacheEntry.gif?.frames.length;
|
|
15299
|
+
});
|
|
15300
|
+
var hasPlayableGif = (visibleElements, imageCache) => visibleElements.some(
|
|
15301
|
+
(element) => isInitializedImageElement(element) && element.gifPlayback?.playing && imageCache.get(element.fileId)?.gif?.frames.length
|
|
15302
|
+
);
|
|
15303
|
+
|
|
14692
15304
|
// src/image.ts
|
|
14693
15305
|
var THUMB_HASH_MAX_DIMENSION = 100;
|
|
14694
15306
|
var thumbHashCanvasCache = /* @__PURE__ */ new Map();
|
|
@@ -14774,7 +15386,10 @@ var loadHTMLImageElement = (dataURL) => {
|
|
|
14774
15386
|
var updateImageCache = async ({
|
|
14775
15387
|
fileIds,
|
|
14776
15388
|
files,
|
|
14777
|
-
imageCache
|
|
15389
|
+
imageCache,
|
|
15390
|
+
onImageCacheUpdate,
|
|
15391
|
+
gifAutoDecodeMaxFileSizeBytes = DEFAULT_GIF_AUTO_DECODE_MAX_FILE_SIZE_BYTES,
|
|
15392
|
+
forceGifDecode = false
|
|
14778
15393
|
}) => {
|
|
14779
15394
|
const updatedFiles = /* @__PURE__ */ new Map();
|
|
14780
15395
|
const erroredFiles = /* @__PURE__ */ new Map();
|
|
@@ -14793,20 +15408,72 @@ var updateImageCache = async ({
|
|
|
14793
15408
|
const imagePromise = loadHTMLImageElement(fileData.dataURL);
|
|
14794
15409
|
const data = {
|
|
14795
15410
|
image: imagePromise,
|
|
14796
|
-
mimeType: fileData.mimeType
|
|
15411
|
+
mimeType: fileData.mimeType,
|
|
15412
|
+
gifDecodeStatus: fileData.mimeType === MIME_TYPES.gif ? "pending" : void 0
|
|
14797
15413
|
};
|
|
14798
15414
|
imageCache.set(fileId, data);
|
|
14799
|
-
|
|
15415
|
+
if (data.gifDecodeStatus === "pending") {
|
|
15416
|
+
onImageCacheUpdate?.(fileId);
|
|
15417
|
+
}
|
|
15418
|
+
let image = imagePromise;
|
|
15419
|
+
let gif;
|
|
15420
|
+
let gifDecodeStatus;
|
|
15421
|
+
try {
|
|
15422
|
+
image = await imagePromise;
|
|
15423
|
+
if (fileData.mimeType === MIME_TYPES.gif) {
|
|
15424
|
+
const decodingData = {
|
|
15425
|
+
...data,
|
|
15426
|
+
image,
|
|
15427
|
+
gifDecodeStatus: "pending"
|
|
15428
|
+
};
|
|
15429
|
+
imageCache.set(fileId, decodingData);
|
|
15430
|
+
onImageCacheUpdate?.(fileId);
|
|
15431
|
+
}
|
|
15432
|
+
if (fileData.mimeType === MIME_TYPES.gif && !forceGifDecode && getDataURLByteLength(fileData.dataURL) > gifAutoDecodeMaxFileSizeBytes) {
|
|
15433
|
+
gifDecodeStatus = "deferred";
|
|
15434
|
+
} else {
|
|
15435
|
+
gif = fileData.mimeType === MIME_TYPES.gif ? await decodeGifFramesQueued(fileData.dataURL) : void 0;
|
|
15436
|
+
if (fileData.mimeType === MIME_TYPES.gif) {
|
|
15437
|
+
gifDecodeStatus = "success";
|
|
15438
|
+
}
|
|
15439
|
+
}
|
|
15440
|
+
} catch (error) {
|
|
15441
|
+
erroredFiles.set(fileId, true);
|
|
15442
|
+
if (fileData.mimeType === MIME_TYPES.gif) {
|
|
15443
|
+
gifDecodeStatus = "error";
|
|
15444
|
+
}
|
|
15445
|
+
} finally {
|
|
15446
|
+
if (fileData.mimeType === MIME_TYPES.gif) {
|
|
15447
|
+
imageCache.set(fileId, {
|
|
15448
|
+
...data,
|
|
15449
|
+
image,
|
|
15450
|
+
gif,
|
|
15451
|
+
gifDecodeStatus: gifDecodeStatus ?? "error"
|
|
15452
|
+
});
|
|
15453
|
+
onImageCacheUpdate?.(fileId);
|
|
15454
|
+
}
|
|
15455
|
+
}
|
|
15456
|
+
if (erroredFiles.has(fileId)) {
|
|
15457
|
+
return;
|
|
15458
|
+
}
|
|
14800
15459
|
if (previousCacheEntry?.isPlaceholder) {
|
|
14801
15460
|
imageCache.set(fileId, {
|
|
14802
15461
|
...data,
|
|
14803
15462
|
image,
|
|
15463
|
+
gif,
|
|
15464
|
+
gifDecodeStatus: fileData.mimeType === MIME_TYPES.gif ? gifDecodeStatus : void 0,
|
|
14804
15465
|
placeholderImage: await previousCacheEntry.image,
|
|
14805
15466
|
transitionStart: performance.now()
|
|
14806
15467
|
});
|
|
14807
15468
|
} else {
|
|
14808
|
-
imageCache.set(fileId, {
|
|
15469
|
+
imageCache.set(fileId, {
|
|
15470
|
+
...data,
|
|
15471
|
+
image,
|
|
15472
|
+
gif,
|
|
15473
|
+
gifDecodeStatus: fileData.mimeType === MIME_TYPES.gif ? gifDecodeStatus : void 0
|
|
15474
|
+
});
|
|
14809
15475
|
}
|
|
15476
|
+
onImageCacheUpdate?.(fileId);
|
|
14810
15477
|
} catch (error) {
|
|
14811
15478
|
erroredFiles.set(fileId, true);
|
|
14812
15479
|
}
|
|
@@ -14870,6 +15537,52 @@ var normalizeSVG = (SVGString) => {
|
|
|
14870
15537
|
}
|
|
14871
15538
|
};
|
|
14872
15539
|
|
|
15540
|
+
// src/renderGif.ts
|
|
15541
|
+
init_define_import_meta_env();
|
|
15542
|
+
var drawGifDecodePlaceholder = (element, context, theme, drawImagePlaceholder2) => {
|
|
15543
|
+
drawImagePlaceholder2(element, context, theme);
|
|
15544
|
+
const pulse = 0.55 + Math.sin(performance.now() / 350) * 0.25;
|
|
15545
|
+
const text = "GIF Decoding";
|
|
15546
|
+
const fontFamily = "Assistant, system-ui, BlinkMacSystemFont, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif";
|
|
15547
|
+
const textX = element.width / 2;
|
|
15548
|
+
const textY = element.height / 2;
|
|
15549
|
+
context.save();
|
|
15550
|
+
context.globalAlpha *= pulse;
|
|
15551
|
+
context.textAlign = "center";
|
|
15552
|
+
context.textBaseline = "middle";
|
|
15553
|
+
context.font = `600 100px ${fontFamily}`;
|
|
15554
|
+
const targetTextWidth = element.width * 0.6;
|
|
15555
|
+
const measuredWidth = context.measureText(text).width;
|
|
15556
|
+
const widthFitFontSize = measuredWidth ? 100 * targetTextWidth / measuredWidth : 24;
|
|
15557
|
+
const fontSize = Math.max(
|
|
15558
|
+
12,
|
|
15559
|
+
Math.min(widthFitFontSize, element.height * 0.35)
|
|
15560
|
+
);
|
|
15561
|
+
context.font = `600 ${fontSize}px ${fontFamily}`;
|
|
15562
|
+
const finalFontSize = Number.parseFloat(
|
|
15563
|
+
context.font.match(/\d+(\.\d+)?px/)?.[0] ?? `${fontSize}`
|
|
15564
|
+
);
|
|
15565
|
+
const finalMeasuredWidth = context.measureText(text).width;
|
|
15566
|
+
const paddingX = Math.max(12, finalFontSize * 0.55);
|
|
15567
|
+
const paddingY = Math.max(8, finalFontSize * 0.35);
|
|
15568
|
+
const pillWidth = finalMeasuredWidth + paddingX * 2;
|
|
15569
|
+
const pillHeight = finalFontSize + paddingY * 2;
|
|
15570
|
+
const pillX = textX - pillWidth / 2;
|
|
15571
|
+
const pillY = textY - pillHeight / 2;
|
|
15572
|
+
const radius = Math.min(pillHeight / 2, finalFontSize * 0.25);
|
|
15573
|
+
context.fillStyle = "rgba(0, 0, 0, 0.62)";
|
|
15574
|
+
context.beginPath();
|
|
15575
|
+
if (context.roundRect) {
|
|
15576
|
+
context.roundRect(pillX, pillY, pillWidth, pillHeight, radius);
|
|
15577
|
+
} else {
|
|
15578
|
+
context.rect(pillX, pillY, pillWidth, pillHeight);
|
|
15579
|
+
}
|
|
15580
|
+
context.fill();
|
|
15581
|
+
context.fillStyle = "#fff";
|
|
15582
|
+
context.fillText(text, textX, textY);
|
|
15583
|
+
context.restore();
|
|
15584
|
+
};
|
|
15585
|
+
|
|
14873
15586
|
// src/renderElement.ts
|
|
14874
15587
|
var isPendingImageElement = (element, renderConfig) => isInitializedImageElement(element) && !renderConfig.imageCache.has(element.fileId);
|
|
14875
15588
|
var getCanvasPadding = (element) => {
|
|
@@ -15039,7 +15752,14 @@ var drawElementOnCanvas = (element, rc, context, renderConfig) => {
|
|
|
15039
15752
|
context.save();
|
|
15040
15753
|
const cacheEntry = element.fileId !== null ? renderConfig.imageCache.get(element.fileId) : null;
|
|
15041
15754
|
const img = isInitializedImageElement(element) ? cacheEntry?.image : void 0;
|
|
15042
|
-
if (
|
|
15755
|
+
if (cacheEntry?.gifDecodeStatus === "pending" && !cacheEntry.gif?.frames.length) {
|
|
15756
|
+
drawGifDecodePlaceholder(
|
|
15757
|
+
element,
|
|
15758
|
+
context,
|
|
15759
|
+
renderConfig.theme,
|
|
15760
|
+
drawImagePlaceholder
|
|
15761
|
+
);
|
|
15762
|
+
} else if (img != null && !(img instanceof Promise)) {
|
|
15043
15763
|
if (element.roundness && context.roundRect) {
|
|
15044
15764
|
context.beginPath();
|
|
15045
15765
|
context.roundRect(
|
|
@@ -15080,11 +15800,17 @@ var drawElementOnCanvas = (element, rc, context, renderConfig) => {
|
|
|
15080
15800
|
delete cacheEntry.transitionStart;
|
|
15081
15801
|
}
|
|
15082
15802
|
}
|
|
15803
|
+
const gifFrame = getGifRenderFrame(
|
|
15804
|
+
element,
|
|
15805
|
+
cacheEntry,
|
|
15806
|
+
renderConfig.getGifFrameIndex?.(element)
|
|
15807
|
+
);
|
|
15808
|
+
const imageForRender = gifFrame ?? img;
|
|
15083
15809
|
const { x, y, width, height } = element.crop ? element.crop : {
|
|
15084
15810
|
x: 0,
|
|
15085
15811
|
y: 0,
|
|
15086
|
-
width:
|
|
15087
|
-
height:
|
|
15812
|
+
width: imageForRender instanceof HTMLCanvasElement ? imageForRender.width : imageForRender.naturalWidth,
|
|
15813
|
+
height: imageForRender instanceof HTMLCanvasElement ? imageForRender.height : imageForRender.naturalHeight
|
|
15088
15814
|
};
|
|
15089
15815
|
const shouldInvertImage = renderConfig.theme === THEME.DARK && cacheEntry?.mimeType === MIME_TYPES2.svg;
|
|
15090
15816
|
if (shouldInvertImage && isSafari) {
|
|
@@ -15096,7 +15822,7 @@ var drawElementOnCanvas = (element, rc, context, renderConfig) => {
|
|
|
15096
15822
|
if (tempContext) {
|
|
15097
15823
|
tempContext.scale(devicePixelRatio, devicePixelRatio);
|
|
15098
15824
|
tempContext.drawImage(
|
|
15099
|
-
|
|
15825
|
+
imageForRender,
|
|
15100
15826
|
x,
|
|
15101
15827
|
y,
|
|
15102
15828
|
width,
|
|
@@ -15136,7 +15862,7 @@ var drawElementOnCanvas = (element, rc, context, renderConfig) => {
|
|
|
15136
15862
|
context.filter = DARK_THEME_FILTER;
|
|
15137
15863
|
}
|
|
15138
15864
|
context.drawImage(
|
|
15139
|
-
|
|
15865
|
+
imageForRender,
|
|
15140
15866
|
x,
|
|
15141
15867
|
y,
|
|
15142
15868
|
width,
|
|
@@ -18496,7 +19222,8 @@ var newImageElement = (opts) => {
|
|
|
18496
19222
|
fileName: opts.fileName ?? null,
|
|
18497
19223
|
thumbHash: opts.thumbHash ?? null,
|
|
18498
19224
|
scale: opts.scale ?? [1, 1],
|
|
18499
|
-
crop: opts.crop ?? null
|
|
19225
|
+
crop: opts.crop ?? null,
|
|
19226
|
+
gifPlayback: opts.gifPlayback ?? null
|
|
18500
19227
|
};
|
|
18501
19228
|
};
|
|
18502
19229
|
|
|
@@ -22336,10 +23063,10 @@ var dragSelectedElements = (pointerDownState, _selectedElements, offset, scene,
|
|
|
22336
23063
|
const elementsToUpdate = new Set(
|
|
22337
23064
|
selectedElements
|
|
22338
23065
|
);
|
|
22339
|
-
const
|
|
22340
|
-
if (
|
|
23066
|
+
const frames2 = selectedElements.filter((e) => isFrameLikeElement(e)).map((f) => f.id);
|
|
23067
|
+
if (frames2.length > 0) {
|
|
22341
23068
|
for (const element of scene.getNonDeletedElements()) {
|
|
22342
|
-
if (element.frameId !== null &&
|
|
23069
|
+
if (element.frameId !== null && frames2.includes(element.frameId)) {
|
|
22343
23070
|
elementsToUpdate.add(element);
|
|
22344
23071
|
}
|
|
22345
23072
|
}
|
|
@@ -25521,6 +26248,10 @@ var PlusIcon = createIcon(
|
|
|
25521
26248
|
] }),
|
|
25522
26249
|
tablerIconProps
|
|
25523
26250
|
);
|
|
26251
|
+
var CirclePauseIcon = createIcon(
|
|
26252
|
+
"M320 112C434.9 112 528 205.1 528 320C528 434.9 434.9 528 320 528C205.1 528 112 434.9 112 320C112 205.1 205.1 112 320 112zM320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM288 248C288 234.7 277.3 224 264 224C250.7 224 240 234.7 240 248L240 392C240 405.3 250.7 416 264 416C277.3 416 288 405.3 288 392L288 248zM400 248C400 234.7 389.3 224 376 224C362.7 224 352 234.7 352 248L352 392C352 405.3 362.7 416 376 416C389.3 416 400 405.3 400 392L400 248z",
|
|
26253
|
+
640
|
|
26254
|
+
);
|
|
25524
26255
|
var DotsIcon = createIcon(
|
|
25525
26256
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", { strokeWidth: "1.5", children: [
|
|
25526
26257
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { stroke: "none", d: "M0 0h24v24H0z", fill: "none" }),
|
|
@@ -27364,6 +28095,33 @@ var playerStopFilledIcon = createIcon(
|
|
|
27364
28095
|
] }),
|
|
27365
28096
|
tablerIconProps
|
|
27366
28097
|
);
|
|
28098
|
+
var prevFrame = createIcon(
|
|
28099
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
28100
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M7 5v14" }),
|
|
28101
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M19 6l-9 6l9 6z" })
|
|
28102
|
+
] }),
|
|
28103
|
+
tablerIconProps
|
|
28104
|
+
);
|
|
28105
|
+
var nextFrame = createIcon(
|
|
28106
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
28107
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M17 5v14" }),
|
|
28108
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 6l9 6l-9 6z" })
|
|
28109
|
+
] }),
|
|
28110
|
+
tablerIconProps
|
|
28111
|
+
);
|
|
28112
|
+
var frames = createIcon(
|
|
28113
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", { strokeWidth: 1.25, children: [
|
|
28114
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { stroke: "none", d: "M0 0h24v24H0z", fill: "none" }),
|
|
28115
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4 6h16a1 1 0 0 1 1 1v10a1 1 0 0 1 -1 1h-16a1 1 0 0 1 -1 -1v-10a1 1 0 0 1 1 -1z" }),
|
|
28116
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M7 6v12" }),
|
|
28117
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M17 6v12" }),
|
|
28118
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 10h4" }),
|
|
28119
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 14h4" }),
|
|
28120
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M17 10h4" }),
|
|
28121
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M17 14h4" })
|
|
28122
|
+
] }),
|
|
28123
|
+
tablerIconProps
|
|
28124
|
+
);
|
|
27367
28125
|
var tablerCheckIcon = createIcon(
|
|
27368
28126
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
27369
28127
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { stroke: "none", d: "M0 0h24v24H0z", fill: "none" }),
|
|
@@ -28947,7 +29705,7 @@ var recognizeShape = (points, previousElement, zoom = 1) => {
|
|
|
28947
29705
|
const type = previousElement?.type === "arrow" && recognized !== "arrow" ? "freedraw" : recognized;
|
|
28948
29706
|
return { type, points, boundingBox };
|
|
28949
29707
|
};
|
|
28950
|
-
var convertToShape = (points, appState, elementsMap, previousElement,
|
|
29708
|
+
var convertToShape = (points, appState, elementsMap, previousElement, frames2) => {
|
|
28951
29709
|
const recognizedShape = recognizeShape(
|
|
28952
29710
|
points,
|
|
28953
29711
|
previousElement,
|
|
@@ -28955,7 +29713,7 @@ var convertToShape = (points, appState, elementsMap, previousElement, frames) =>
|
|
|
28955
29713
|
);
|
|
28956
29714
|
const boundingBox = recognizedShape.boundingBox;
|
|
28957
29715
|
const [minX, minY, maxX, maxY] = boundingBox;
|
|
28958
|
-
const frameLikeElements =
|
|
29716
|
+
const frameLikeElements = frames2 ?? getFrameLikeElements([...elementsMap.values()]);
|
|
28959
29717
|
const frameId = frameLikeElements.find((frame) => {
|
|
28960
29718
|
const [fx1, fy1, fx2, fy2] = getElementAbsoluteCoords3(frame, elementsMap);
|
|
28961
29719
|
return fx1 <= minX && fy1 <= minY && fx2 >= maxX && fy2 >= maxY;
|
|
@@ -29252,13 +30010,17 @@ export {
|
|
|
29252
30010
|
computeBoundTextPosition,
|
|
29253
30011
|
computeBucketFillPolygon,
|
|
29254
30012
|
computeContainerDimensionForBoundText,
|
|
30013
|
+
configureGifWorkerUrl,
|
|
29255
30014
|
containsCJK,
|
|
29256
30015
|
convertToExcalidrawElements,
|
|
29257
30016
|
convertToShape,
|
|
29258
30017
|
convertToShapeHandlePointerMoveFromPointerDown,
|
|
30018
|
+
createGifPlaybackMetadata,
|
|
29259
30019
|
createPlaceholderEmbeddableLabel,
|
|
29260
30020
|
createSrcDoc,
|
|
29261
30021
|
cropElement,
|
|
30022
|
+
decodeGifFrames,
|
|
30023
|
+
decodeGifFramesQueued,
|
|
29262
30024
|
deconstructDiamondElement,
|
|
29263
30025
|
deconstructLinearOrFreeDrawElement,
|
|
29264
30026
|
deconstructRectanguloidElement,
|
|
@@ -29271,6 +30033,7 @@ export {
|
|
|
29271
30033
|
dragNewElement,
|
|
29272
30034
|
dragNewTextElement,
|
|
29273
30035
|
dragSelectedElements,
|
|
30036
|
+
drawGifDecodePlaceholder,
|
|
29274
30037
|
duplicateElement,
|
|
29275
30038
|
duplicateElements,
|
|
29276
30039
|
editGroupForSelectedElement,
|
|
@@ -29321,6 +30084,7 @@ export {
|
|
|
29321
30084
|
getCornerRadius,
|
|
29322
30085
|
getCubicBezierCurveBound,
|
|
29323
30086
|
getCursorForResizingElement,
|
|
30087
|
+
getDataURLByteLength,
|
|
29324
30088
|
getDefaultFrameName,
|
|
29325
30089
|
getDefaultRoundnessTypeForElement,
|
|
29326
30090
|
getDiamondBaseCorners,
|
|
@@ -29350,6 +30114,7 @@ export {
|
|
|
29350
30114
|
getFreedrawOutlineAsSegments,
|
|
29351
30115
|
getFreedrawOutlinePoints,
|
|
29352
30116
|
getFreedrawStrokeCenterPoints,
|
|
30117
|
+
getGifRenderFrame,
|
|
29353
30118
|
getGlobalFixedPointForBindableElement,
|
|
29354
30119
|
getGlobalFixedPoints,
|
|
29355
30120
|
getHeadingForElbowArrowSnap,
|
|
@@ -29416,10 +30181,12 @@ export {
|
|
|
29416
30181
|
handleFocusPointHover,
|
|
29417
30182
|
handleFocusPointPointerDown,
|
|
29418
30183
|
handleFocusPointPointerUp,
|
|
30184
|
+
hasActiveGifDecode,
|
|
29419
30185
|
hasBackground,
|
|
29420
30186
|
hasBoundTextElement,
|
|
29421
30187
|
hasBoundingBox,
|
|
29422
30188
|
hasFreedrawMode,
|
|
30189
|
+
hasPlayableGif,
|
|
29423
30190
|
hasStrokeColor,
|
|
29424
30191
|
hasStrokeStyle,
|
|
29425
30192
|
hasStrokeWidth,
|