@ibodr/utils 0.1.1 → 0.1.4
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/index.d.ts +4 -19
- package/dist/index.mjs +2 -142
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/version.ts","../src/lib/array.ts","../src/lib/function.ts","../src/lib/control.ts","../src/lib/bind.ts","../src/lib/cache.ts","../src/lib/debounce.ts","../src/lib/error.ts","../src/lib/ExecutionQueue.ts","../src/lib/network.ts","../src/lib/file.ts","../src/lib/hash.ts","../src/lib/id.ts","../src/lib/iterable.ts","../src/lib/LruCache.ts","../src/lib/media/apng.ts","../src/lib/media/avif.ts","../src/lib/media/gif.ts","../src/lib/media/png.ts","../src/lib/media/webp.ts","../src/lib/media/media.ts","../src/lib/number.ts","../src/lib/object.ts","../src/lib/perf.ts","../src/lib/PerformanceTracker.ts","../src/lib/reordering.ts","../src/lib/retry.ts","../src/lib/sort.ts","../src/lib/storage.tsx","../src/lib/stringEnum.ts","../src/lib/throttle.ts","../src/lib/timers.ts","../src/lib/url.ts","../src/lib/value.ts","../src/lib/warn.ts","../src/index.ts"],"names":["entry","crc"],"mappings":";;;;;;;;AAYA,IAAM,wBAAA,GAA2B,6BAAA;AAOjC,SAAS,kBAAA,GAA6C;AACrD,EAAA,IAAI,UAAA,CAAW,wBAAwB,CAAA,EAAG;AACzC,IAAA,OAAO,WAAW,wBAAwB,CAAA;AAAA,EAC3C;AAEA,EAAA,MAAM,IAAA,GAA+B;AAAA,IACpC,UAAU,EAAC;AAAA,IACX,OAAA,EAAS,KAAA;AAAA,IACT,eAAA,EAAiB;AAAA,GAClB;AAEA,EAAA,MAAA,CAAO,cAAA,CAAe,YAAY,wBAAA,EAA0B;AAAA,IAC3D,KAAA,EAAO,IAAA;AAAA,IACP,QAAA,EAAU,KAAA;AAAA,IACV,YAAA,EAAc,KAAA;AAAA,IACd,UAAA,EAAY;AAAA,GACZ,CAAA;AAED,EAAA,OAAO,IAAA;AACR;AAgDO,SAAS,0BAAA,CAA2B,IAAA,EAAe,OAAA,EAAkB,OAAA,EAAkB;AAC7F,EAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,OAAA,IAAW,CAAC,OAAA,EAAS;AAClC,IAA+C;AAC9C,MAAA,MAAM,IAAI,MAAM,uEAAuE,CAAA;AAAA,IACxF;AACA,EACD;AAEA,EAAA,MAAM,OAAO,kBAAA,EAAmB;AAKhC,EAAA,IAAI,aAAY,EAAG;AAClB,IAAA,MAAM,WAAA,GAAc,KAAK,QAAA,CAAS,IAAA;AAAA,MACjC,CAAC,MAAM,CAAA,CAAE,IAAA,KAAS,QAAQ,CAAA,CAAE,OAAA,KAAY,OAAA,IAAW,CAAA,CAAE,OAAA,KAAY;AAAA,KAClE;AACA,IAAA,IAAI,WAAA,EAAa;AAAA,EAClB;AAEA,EAAA,IAAA,CAAK,SAAS,IAAA,CAAK,EAAE,IAAA,EAAM,OAAA,EAAS,SAAS,CAAA;AAE7C,EAAA,IAAI,CAAC,KAAK,eAAA,EAAiB;AAC1B,IAAA,IAAI;AAEH,MAAA,IAAA,CAAK,eAAA,GAAkB,WAAW,MAAM;AACvC,QAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AACvB,QAAA,oBAAA,CAAqB,IAAI,CAAA;AAAA,MAC1B,GAAG,GAAG,CAAA;AAAA,IACP,CAAA,CAAA,MAAQ;AAGP,MAAA,oBAAA,CAAqB,IAAI,CAAA;AAAA,IAC1B;AAAA,EACD;AACD;AAEA,SAAS,qBAAqB,IAAA,EAA8B;AAC3D,EAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,MAAA,EAAQ;AAC3B,EAAA,IAAI,KAAK,OAAA,EAAS;AAElB,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,eAAA,CAAgB,CAAA,CAAE,OAAA,EAAS,CAAA,CAAE,OAAO,CAAC,CAAA;AACjF,EAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAC,CAAA,CAAE,OAAA;AAEhD,EAAA,MAAM,gBAAA,uBAAuB,GAAA,EAAY;AACzC,EAAA,MAAM,mBAAA,uBAA0B,GAAA,EAAyB;AACzD,EAAA,KAAA,MAAW,OAAO,MAAA,EAAQ;AACzB,IAAA,IAAI,mBAAA,CAAoB,GAAA,CAAI,GAAA,CAAI,IAAI,CAAA,EAAG;AACtC,MAAA,gBAAA,CAAiB,MAAA,CAAO,IAAI,IAAI,CAAA;AAChC,MAAA,KAAA,CAAM,mBAAA,EAAqB,IAAI,IAAA,kBAAM,IAAI,KAAK,CAAA,CAAE,GAAA,CAAI,GAAA,CAAI,OAAO,CAAA;AAC/D,MAAA;AAAA,IACD;AAEA,IAAA,IAAI,GAAA,CAAI,YAAY,aAAA,EAAe;AAClC,MAAA,gBAAA,CAAiB,GAAA,CAAI,IAAI,IAAI,CAAA;AAAA,IAC9B,CAAA,MAAO;AACN,MAAA,gBAAA,CAAiB,MAAA,CAAO,IAAI,IAAI,CAAA;AAChC,MAAA,KAAA,CAAM,mBAAA,EAAqB,IAAI,IAAA,kBAAM,IAAI,KAAK,CAAA,CAAE,GAAA,CAAI,GAAA,CAAI,OAAO,CAAA;AAAA,IAChE;AAAA,EACD;AAEA,EAAA,IAAI,mBAAA,CAAoB,OAAO,CAAA,EAAG;AACjC,IAAA,MAAM,OAAA,GAAU;AAAA,MACf,GAAG,MAAA,CAAO,UAAA,EAAY,CAAC,MAAA,EAAQ,SAAS,WAAW,CAAC,CAAC,CAAA,CAAA,EAAI,OAAO,0GAAA,EAA4G,CAAC,SAAA,EAAW,MAAM,CAAC,CAAC,CAAA,CAAA;AAAA,MAChM,EAAA;AAAA,MACA,CAAA,yCAAA,EAA4C,OAAO,CAAA,CAAA,EAAI,aAAa,IAAI,CAAC,MAAA,EAAQ,UAAU,CAAC,CAAC,CAAA,oDAAA,CAAA;AAAA,MAC7F,GAAG,KAAA,CAAM,IAAA,CAAK,gBAAA,EAAkB,CAAC,IAAA,KAAS,CAAA,gBAAA,EAAS,MAAA,CAAO,IAAA,EAAM,CAAC,MAAM,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,MAC3E,EAAA;AAAA,MACA,CAAA,2FAAA,CAAA;AAAA,MACA,GAAG,MAAM,IAAA,CAAK,mBAAA,EAAqB,CAAC,CAAC,IAAA,EAAM,QAAQ,CAAA,KAAM;AACxD,QAAA,MAAM,cAAA,GAAiB,MAAM,IAAA,CAAK,QAAQ,EACxC,IAAA,CAAK,eAAe,CAAA,CACpB,GAAA,CAAI,CAAC,CAAA,KAAM,OAAO,CAAA,CAAA,EAAI,CAAC,CAAA,CAAA,EAAI,CAAA,KAAM,aAAA,GAAgB,CAAC,WAAW,CAAA,GAAI,CAAC,SAAS,CAAC,CAAC,CAAA;AAC/E,QAAA,OAAO,CAAA,gBAAA,EAAS,MAAA,CAAO,IAAA,EAAM,CAAC,MAAM,CAAC,CAAC,CAAA,EAAA,EAAK,cAAA,CAAe,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,MACrE,CAAC;AAAA,KACF;AAGA,IAAA,OAAA,CAAQ,GAAA,CAAI,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAC,CAAA;AAC9B,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA;AAAA,EACD;AAGA,EAAA,MAAM,mBAAA,uBAA0B,GAAA,EAAoD;AACpF,EAAA,KAAA,MAAW,OAAO,MAAA,EAAQ;AACzB,IAAA,KAAA,CAAM,mBAAA,EAAqB,GAAA,CAAI,IAAA,EAAM,EAAE,OAAA,EAAS,GAAA,CAAI,OAAA,EAAS,OAAA,EAAS,EAAC,EAAG,CAAA,CAAE,OAAA,CAAQ,IAAA;AAAA,MACnF,GAAA,CAAI;AAAA,KACL;AAAA,EACD;AAEA,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAoD;AAC3E,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,GAAG,CAAA,IAAK,mBAAA,EAAqB;AAC9C,IAAA,IAAI,IAAI,OAAA,CAAQ,MAAA,GAAS,GAAG,UAAA,CAAW,GAAA,CAAI,MAAM,GAAG,CAAA;AAAA,EACrD;AAEA,EAAA,IAAI,UAAA,CAAW,OAAO,CAAA,EAAG;AACxB,IAAA,MAAM,OAAA,GAAU;AAAA,MACf,GAAG,MAAA,CAAO,UAAA,EAAY,CAAC,MAAA,EAAQ,SAAS,WAAW,CAAC,CAAC,CAAA,CAAA,EAAI,OAAO,8GAAA,EAAgH,CAAC,SAAA,EAAW,MAAM,CAAC,CAAC,CAAA,CAAA;AAAA,MACpM,EAAA;AAAA,MACA,wKAAA;AAAA,MACA,EAAA;AAAA,MACA,4DAAA;AAAA,MACA,GAAG,MAAM,IAAA,CAAK,UAAA,EAAY,CAAC,CAAC,IAAA,EAAM,GAAG,CAAA,KAAM;AAC1C,QAAA,MAAM,UAAU,GAAA,CAAI,OAAA,CAClB,IAAI,CAAC,CAAA,EAAG,MAAO,CAAA,KAAM,KAAA,GAAQ,SAAS,CAAA,GAAI,CAAC,iBAAiB,CAAA,MAAA,EAAS,CAAA,GAAI,CAAC,CAAA,UAAA,CAAa,CAAA,CACvF,KAAK,IAAI,CAAA;AACX,QAAA,OAAO,CAAA,gBAAA,EAAS,OAAO,IAAA,EAAM,CAAC,MAAM,CAAC,CAAC,CAAA,EAAA,EAAK,GAAA,CAAI,OAAO,CAAA;AAAA,EAAO,OAAO,CAAA,CAAA;AAAA,MACrE,CAAC,CAAA;AAAA,MACD,EAAA;AAAA,MACA;AAAA,KACD;AAGA,IAAA,OAAA,CAAQ,GAAA,CAAI,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAC,CAAA;AAC9B,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA;AAAA,EACD;AACD;AAEA,SAAS,eAAA,CAAgB,GAAW,CAAA,EAAW;AAC9C,EAAA,MAAM,MAAA,GAAS,CAAA,CAAE,KAAA,CAAM,kCAAkC,CAAA;AACzD,EAAA,MAAM,MAAA,GAAS,CAAA,CAAE,KAAA,CAAM,kCAAkC,CAAA;AAEzD,EAAA,IAAI,CAAC,MAAA,IAAU,CAAC,QAAQ,OAAO,CAAA,CAAE,cAAc,CAAC,CAAA;AAChD,EAAA,IAAI,MAAA,CAAO,CAAC,CAAA,KAAM,MAAA,CAAO,CAAC,CAAA,EAAG,OAAO,MAAA,CAAO,MAAA,CAAO,CAAC,CAAC,CAAA,GAAI,MAAA,CAAO,MAAA,CAAO,CAAC,CAAC,CAAA;AACxE,EAAA,IAAI,MAAA,CAAO,CAAC,CAAA,KAAM,MAAA,CAAO,CAAC,CAAA,EAAG,OAAO,MAAA,CAAO,MAAA,CAAO,CAAC,CAAC,CAAA,GAAI,MAAA,CAAO,MAAA,CAAO,CAAC,CAAC,CAAA;AACxE,EAAA,IAAI,MAAA,CAAO,CAAC,CAAA,KAAM,MAAA,CAAO,CAAC,CAAA,EAAG,OAAO,MAAA,CAAO,MAAA,CAAO,CAAC,CAAC,CAAA,GAAI,MAAA,CAAO,MAAA,CAAO,CAAC,CAAC,CAAA;AACxE,EAAA,IAAI,MAAA,CAAO,CAAC,CAAA,IAAK,MAAA,CAAO,CAAC,CAAA,EAAG,OAAO,MAAA,CAAO,CAAC,CAAA,CAAE,aAAA,CAAc,MAAA,CAAO,CAAC,CAAC,CAAA;AACpE,EAAA,IAAI,MAAA,CAAO,CAAC,CAAA,EAAG,OAAO,CAAA;AACtB,EAAA,IAAI,MAAA,CAAO,CAAC,CAAA,EAAG,OAAO,EAAA;AACtB,EAAA,OAAO,CAAA;AACR;AAEA,IAAM,OAAA,GAAU;AAAA,EACf,IAAA,EAAM,GAAA;AAAA,EACN,QAAA,EAAU,IAAA;AAAA,EACV,OAAA,EAAS,IAAA;AAAA,EACT,SAAA,EAAW,IAAA;AAAA,EACX,KAAA,EAAO,IAAA;AAAA,EACP,SAAA,EAAW;AACZ,CAAA;AACA,SAAS,MAAA,CAAO,KAAA,EAAe,UAAA,GAAuC,EAAC,EAAG;AACzE,EAAA,OAAO,CAAA,KAAA,EAAQ,UAAA,CAAW,GAAA,CAAI,CAAC,CAAA,KAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,IAAI,KAAK,CAAA,MAAA,CAAA;AACpE;AAEA,SAAS,WAAA,GAAuB;AAC/B,EAAA,IAAI;AACH,IAAA,OAAiD,eAAA,IAAmB,UAAA;AAAA,EACrE,CAAA,CAAA,MAAQ;AACP,IAAA,OAAO,KAAA;AAAA,EACR;AACD;AAEA,SAAS,KAAA,CAAY,GAAA,EAAgB,GAAA,EAAQ,YAAA,EAAoB;AAChE,EAAA,IAAI,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA,EAAG;AACjB,IAAA,OAAO,GAAA,CAAI,IAAI,GAAG,CAAA;AAAA,EACnB;AACA,EAAA,GAAA,CAAI,GAAA,CAAI,KAAK,YAAY,CAAA;AACzB,EAAA,OAAO,YAAA;AACR;;;ACnOO,SAAS,WAAA,CAAe,KAAU,MAAA,EAAqB;AAC7D,EAAA,IAAI,GAAA,CAAI,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AAI9B,EAAA,MAAM,gBAAA,GAAA,CAAqB,KAAK,GAAA,CAAI,MAAM,IAAI,GAAA,CAAI,MAAA,GAAU,GAAA,CAAI,MAAA,IAAU,GAAA,CAAI,MAAA;AAG9E,EAAA,OAAO,CAAC,GAAG,GAAA,CAAI,KAAA,CAAM,gBAAgB,CAAA,EAAG,GAAG,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,gBAAgB,CAAC,CAAA;AAC1E;AAuBO,SAAS,MAAA,CAAU,OAAY,MAAA,EAA2C;AAChF,EAAA,MAAM,SAAc,EAAC;AACrB,EAAA,QAAA,EAAU,KAAA,MAAW,QAAQ,KAAA,EAAO;AACnC,IAAA,KAAA,MAAW,YAAY,MAAA,EAAQ;AAC9B,MAAA,IAAI,SAAS,MAAA,CAAO,IAAA,EAAM,QAAQ,CAAA,GAAI,SAAS,QAAA,EAAU;AACxD,QAAA,SAAS,QAAA;AAAA,MACV;AAAA,IACD;AACA,IAAA,MAAA,CAAO,KAAK,IAAI,CAAA;AAAA,EACjB;AACA,EAAA,OAAO,MAAA;AACR;AAkBO,SAAS,QAAW,GAAA,EAA4B;AACtD,EAAA,OAAO,IAAI,MAAA,CAAO,CAAC,MAAM,CAAA,KAAM,MAAA,IAAa,MAAM,IAAI,CAAA;AACvD;AAmBO,SAAS,KAAQ,GAAA,EAAkC;AACzD,EAAA,OAAO,GAAA,CAAI,GAAA,CAAI,MAAA,GAAS,CAAC,CAAA;AAC1B;AAsBO,SAAS,KAAA,CAAS,KAAmB,EAAA,EAAwC;AACnF,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI,MAAA,GAAS,QAAA;AACb,EAAA,KAAA,MAAW,QAAQ,GAAA,EAAK;AACvB,IAAA,MAAM,GAAA,GAAM,GAAG,IAAI,CAAA;AACnB,IAAA,IAAI,MAAM,MAAA,EAAQ;AACjB,MAAA,GAAA,GAAM,IAAA;AACN,MAAA,MAAA,GAAS,GAAA;AAAA,IACV;AAAA,EACD;AACA,EAAA,OAAO,GAAA;AACR;AAsBO,SAAS,KAAA,CAAS,KAAmB,EAAA,EAAwC;AACnF,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI,MAAA,GAAiB,CAAA,QAAA;AACrB,EAAA,KAAA,MAAW,QAAQ,GAAA,EAAK;AACvB,IAAA,MAAM,GAAA,GAAM,GAAG,IAAI,CAAA;AACnB,IAAA,IAAI,MAAM,MAAA,EAAQ;AACjB,MAAA,GAAA,GAAM,IAAA;AACN,MAAA,MAAA,GAAS,GAAA;AAAA,IACV;AAAA,EACD;AACA,EAAA,OAAO,GAAA;AACR;AAyBO,SAAS,SAAA,CAAa,KAAU,SAAA,EAA6C;AACnF,EAAA,MAAM,YAAiB,EAAC;AACxB,EAAA,MAAM,iBAAsB,EAAC;AAC7B,EAAA,KAAA,MAAW,QAAQ,GAAA,EAAK;AACvB,IAAA,IAAI,SAAA,CAAU,IAAI,CAAA,EAAG;AACpB,MAAA,SAAA,CAAU,KAAK,IAAI,CAAA;AAAA,IACpB,CAAA,MAAO;AACN,MAAA,cAAA,CAAe,KAAK,IAAI,CAAA;AAAA,IACzB;AAAA,EACD;AACA,EAAA,OAAO,CAAC,WAAW,cAAc,CAAA;AAClC;AA0BO,SAAS,qBAAA,CAAyB,MAAoB,IAAA,EAA6B;AACzF,EAAA,IAAI,IAAA,KAAS,MAAM,OAAO,IAAA;AAC1B,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,IAAA,CAAK,MAAA,EAAQ,OAAO,KAAA;AACxC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,IAAI,CAAC,OAAO,EAAA,CAAG,IAAA,CAAK,CAAC,CAAA,EAAG,IAAA,CAAK,CAAC,CAAC,CAAA,EAAG;AACjC,MAAA,OAAO,KAAA;AAAA,IACR;AAAA,EACD;AACA,EAAA,OAAO,IAAA;AACR;AA8BO,SAAS,6BAAA,CAGd,GAAA,EAAU,aAAA,EAA6B,QAAA,EAAwB;AAChE,EAAA,MAAM,aAAA,GAAgB,IAAI,GAAA,CAAI,aAAA,CAAc,GAAA,CAAI,CAACA,MAAAA,KAAUA,MAAAA,CAAM,GAAG,CAAC,CAAC,CAAA;AAEtE,EAAA,MAAM,SAAS,EAAC;AAChB,EAAA,KAAA,MAAW,gBAAgB,QAAA,EAAU;AACpC,IAAA,IAAI,aAAA,CAAc,GAAA,CAAI,YAAA,CAAa,GAAG,CAAC,CAAA,EAAG;AAC1C,IAAA,MAAA,CAAO,KAAK,YAAY,CAAA;AAAA,EACzB;AAEA,EAAA,KAAA,MAAW,eAAe,aAAA,EAAe;AACxC,IAAA,MAAA,CAAO,KAAK,WAAW,CAAA;AAAA,EACxB;AAEA,EAAA,OAAO,MAAA;AACR;;;AC1QO,SAAS,mBACf,EAAA,EAC4B;AAC5B,EAAA,MAAM,SAAA,GAAY,IAAI,IAAA,KAAe;AACpC,IAAA,IAAI;AACH,MAAA,OAAO,EAAA,CAAG,GAAG,IAAI,CAAA;AAAA,IAClB,SAAS,KAAA,EAAO;AACf,MAAA,IAAI,KAAA,YAAiB,KAAA,IAAS,KAAA,CAAM,iBAAA,EAAmB;AACtD,QAAA,KAAA,CAAM,iBAAA,CAAkB,OAAO,SAAS,CAAA;AAAA,MACzC;AACA,MAAA,MAAM,KAAA;AAAA,IACP;AAAA,EACD,CAAA;AAEA,EAAA,OAAO,SAAA;AACR;AAMO,IAAM,OAAmB,MAAM;AAAC;;;AC2ChC,IAAM,MAAA,GAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrB,GAAM,KAAA,EAAuB;AAC5B,IAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,KAAA,EAAM;AAAA,EAC1B,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAO,KAAA,EAA0B;AAChC,IAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAM;AAAA,EAC3B,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,IAAO,OAAA,EAA6C;AACnD,IAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,CAAC,MAAA,KAAW,MAAA,CAAO,EAAE,CAAA,GACvC,MAAA,CAAO,EAAA,CAAG,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW,MAAA,CAAO,KAAK,CAAC,CAAA,GAC/C,MAAA,CAAO,GAAA,CAAI,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAA,KAAW,CAAC,MAAA,CAAO,EAAE,CAAA,EAAG,KAAK,CAAA;AAAA,EAC1D;AACD;AA4BO,SAAS,qBAAA,CAAsB,OAAc,QAAA,EAA0B;AAC7E,EAAA,MAAM,UAAA,GACL,QAAA,IAAY,KAAA,IAAS,OAAO,KAAA,KAAU,YAAY,QAAA,IAAY,KAAA,GAAQ,KAAA,CAAM,QAAQ,CAAA,GAAI,KAAA;AACzF,EAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oBAAA,EAAuB,UAAU,CAAA,CAAE,CAAA;AACpD;AAqBO,IAAM,MAAA,GAA8D,kBAAA;AAAA,EAC1E,CAAC,OAAO,OAAA,KAAY;AACnB,IAAA,IAAI,CAAC,KAAA,EAAO;AACX,MAAA,MAAM,IAAI,KAAA,CAAM,OAAA,IAAW,iBAAiB,CAAA;AAAA,IAC7C;AAAA,EACD;AACD;AAqBO,IAAM,YAAA,GAAe,kBAAA,CAAmB,CAAI,KAAA,EAAU,OAAA,KAAqC;AAEjG,EAAA,IAAI,SAAS,IAAA,EAAM;AAClB,IAAA,MAAM,IAAI,KAAA,CAAM,OAAA,IAAW,uBAAuB,CAAA;AAAA,EACnD;AACA,EAAA,OAAO,KAAA;AACR,CAAC;AA0BM,SAAS,kBAAA,GAGd;AACD,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,MAAA;AACJ,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAW,CAAC,KAAK,GAAA,KAAQ;AAC5C,IAAA,OAAA,GAAU,GAAA;AACV,IAAA,MAAA,GAAS,GAAA;AAAA,EACV,CAAC,CAAA;AACD,EAAA,OAAO,MAAA,CAAO,OAAO,OAAA,EAAS;AAAA,IAC7B,OAAA;AAAA,IACA;AAAA,GACA,CAAA;AACF;AA2BO,SAAS,MAAM,EAAA,EAA2B;AAEhD,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACxD;;;ACnLO,SAAS,QACZ,IAAA,EAIyB;AAC5B,EAAA,IAAI,IAAA,CAAK,WAAW,CAAA,EAAG;AACtB,IAAA,MAAM,CAAC,cAAA,EAAgB,OAAO,CAAA,GAAI,IAAA;AAClC,IAAA,OAAA,CAAQ,cAAA,CAAe,SAAS,gBAAA,GAA4B;AAC3D,MAAA,MAAA,CAAO,OAAA,CAAQ,YAAA,CAAa,IAAI,CAAA,EAAG,wCAAwC,CAAA;AAC3E,MAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,IAAA,CAAK,IAAI,CAAA;AACtC,MAAA,MAAM,EAAA,GAAK,OAAA,CAAQ,cAAA,CAAe,IAAA,EAAM,QAAQ,IAAA,EAAM;AAAA,QACrD,KAAA;AAAA,QACA,QAAA,EAAU,IAAA;AAAA,QACV,YAAA,EAAc;AAAA,OACd,CAAA;AACD,MAAA,MAAA,CAAO,IAAI,8CAA8C,CAAA;AAAA,IAC1D,CAAC,CAAA;AAAA,EACF,CAAA,MAAO;AACN,IAAA,MAAM,CAAC,OAAA,EAAS,WAAA,EAAa,UAAU,CAAA,GAAI,IAAA;AAC3C,IAAA,IAAI,CAAC,UAAA,IAAc,OAAO,UAAA,CAAW,UAAU,UAAA,EAAY;AAC1D,MAAA,MAAM,IAAI,SAAA;AAAA,QACT,8CAA8C,WAAW,CAAA,kBAAA;AAAA,OAC1D;AAAA,IACD;AAEA,IAAA,OAAO;AAAA,MACN,YAAA,EAAc,IAAA;AAAA,MACd,GAAA,GAAoB;AACnB,QAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,KAAA,CAAO,IAAA,CAAK,IAAI,CAAA;AAEzC,QAAA,MAAA,CAAO,cAAA,CAAe,MAAM,WAAA,EAAa;AAAA,UACxC,KAAA,EAAO,KAAA;AAAA,UACP,YAAA,EAAc,IAAA;AAAA,UACd,QAAA,EAAU;AAAA,SACV,CAAA;AACD,QAAA,OAAO,KAAA;AAAA,MACR;AAAA,KACD;AAAA,EACD;AACD;;;AChHO,IAAM,YAAN,MAAqC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM3C,KAAA,uBAAY,OAAA,EAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA2B1B,GAAA,CAAiB,MAAS,EAAA,EAAoB;AAC7C,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA,EAAG;AAC1B,MAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,IAAA,EAAM,EAAA,CAAG,IAAI,CAAC,CAAA;AAAA,IAC9B;AAEA,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA;AAAA,EAC3B;AACD;;;ACxBO,SAAS,QAAA,CACf,UACA,IAAA,EACC;AACD,EAAA,IAAI,KAAA,GASG,MAAA;AAEP,EAAA,MAAM,EAAA,GAAK,IAAI,IAAA,KAAwB;AACtC,IAAA,IAAI,CAAC,KAAA,EAAO;AACX,MAAA,KAAA,GAAQ,EAAC;AACT,MAAA,KAAA,CAAO,OAAA,GAAU,IAAI,OAAA,CAAQ,CAAC,SAAS,MAAA,KAAW;AACjD,QAAA,KAAA,CAAO,OAAA,GAAU,OAAA;AACjB,QAAA,KAAA,CAAO,MAAA,GAAS,MAAA;AAAA,MACjB,CAAC,CAAA;AAAA,IACF;AACA,IAAA,YAAA,CAAa,MAAO,OAAO,CAAA;AAC3B,IAAA,KAAA,CAAO,UAAA,GAAa,IAAA;AAGpB,IAAA,KAAA,CAAO,OAAA,GAAU,WAAW,MAAM;AACjC,MAAA,MAAM,CAAA,GAAI,KAAA;AACV,MAAA,KAAA,GAAQ,MAAA;AACR,MAAA,IAAI;AACH,QAAA,CAAA,CAAE,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,CAAE,UAAU,CAAC,CAAA;AAAA,MACpC,SAAS,CAAA,EAAG;AACX,QAAA,CAAA,CAAE,OAAO,CAAC,CAAA;AAAA,MACX;AAAA,IACD,GAAG,IAAI,CAAA;AAEP,IAAA,OAAO,KAAA,CAAO,OAAA;AAAA,EACf,CAAA;AACA,EAAA,EAAA,CAAG,SAAS,MAAM;AACjB,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,YAAA,CAAa,MAAM,OAAO,CAAA;AAC1B,IAAA,KAAA,GAAQ,MAAA;AAAA,EACT,CAAA;AACA,EAAA,OAAO,EAAA;AACR;;;AC9EA,IAAM,kBAAA,uBAAyB,OAAA,EAAkC;AAoB1D,SAAS,aAAA,CAAc,OAAgB,WAAA,EAAwC;AACrF,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA,EAAM;AAEjD,EAAA,IAAI,kBAAA,GAAqB,kBAAA,CAAmB,GAAA,CAAI,KAAK,CAAA;AACrD,EAAA,IAAI,CAAC,kBAAA,EAAoB;AACxB,IAAA,kBAAA,GAAqB,EAAE,IAAA,EAAM,EAAC,EAAG,MAAA,EAAQ,EAAC,EAAE;AAC5C,IAAA,kBAAA,CAAmB,GAAA,CAAI,OAAO,kBAAkB,CAAA;AAAA,EACjD;AAEA,EAAA,IAAI,YAAY,IAAA,EAAM;AACrB,IAAA,kBAAA,CAAmB,IAAA,GAAO;AAAA,MACzB,GAAG,kBAAA,CAAmB,IAAA;AAAA,MACtB,GAAG,WAAA,CAAY;AAAA,KAChB;AAAA,EACD;AACA,EAAA,IAAI,YAAY,MAAA,EAAQ;AACvB,IAAA,kBAAA,CAAmB,MAAA,GAAS;AAAA,MAC3B,GAAG,kBAAA,CAAmB,MAAA;AAAA,MACtB,GAAG,WAAA,CAAY;AAAA,KAChB;AAAA,EACD;AACD;AAiBO,SAAS,oBAAoB,KAAA,EAAgC;AACnE,EAAA,OAAO,kBAAA,CAAmB,GAAA,CAAI,KAAK,CAAA,IAAK,EAAE,MAAM,EAAC,EAAG,MAAA,EAAQ,EAAC,EAAE;AAChE;;;AClCO,IAAM,iBAAN,MAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqB3B,YAA6B,OAAA,EAAkB;AAAlB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EAAmB;AAAA,EAAnB,OAAA;AAAA,EApBrB,QAAgC,EAAC;AAAA,EACjC,OAAA,GAAU,KAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsClB,OAAA,GAAU;AACT,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,MAAA,KAAW,CAAA,IAAK,CAAC,IAAA,CAAK,OAAA;AAAA,EACzC;AAAA,EAEA,MAAc,GAAA,GAAM;AACnB,IAAA,IAAI,KAAK,OAAA,EAAS;AAClB,IAAA,IAAI;AACH,MAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,MAAA,OAAO,IAAA,CAAK,MAAM,MAAA,EAAQ;AACzB,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,KAAA,EAAM;AAC9B,QAAA,MAAM,IAAA,EAAK;AACX,QAAA,IAAI,KAAK,OAAA,EAAS;AACjB,UAAA,MAAM,KAAA,CAAM,KAAK,OAAO,CAAA;AAAA,QACzB;AAAA,MACD;AAAA,IACD,CAAA,SAAE;AAID,MAAA,IAAA,CAAK,OAAA,GAAU,KAAA;AAAA,IAChB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBA,MAAM,KAAQ,IAAA,EAAoC;AACjD,IAAA,OAAO,IAAI,OAAA,CAAoB,CAAC,OAAA,EAAS,MAAA,KAAW;AACnD,MAAA,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,MAAM,OAAA,CAAQ,OAAA,CAAQ,IAAA,EAAM,CAAA,CAAE,IAAA,CAAK,OAAO,CAAA,CAAE,KAAA,CAAM,MAAM,CAAC,CAAA;AACzE,MAAA,IAAA,CAAK,GAAA,EAAI;AAAA,IACV,CAAC,CAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBA,KAAA,GAAQ;AACP,IAAA,IAAA,CAAK,QAAQ,EAAC;AAAA,EACf;AACD;;;AC9IA,eAAsB,KAAA,CAAM,OAA0B,IAAA,EAAuC;AAE5F,EAAA,OAAO,MAAA,CAAO,MAAM,KAAA,EAAO;AAAA;AAAA,IAE1B,cAAA,EAAgB,iCAAA;AAAA,IAChB,GAAG;AAAA,GACH,CAAA;AACF;AAWO,IAAM,KAAA,GAAQ,CAAC,KAAA,EAAgB,MAAA,KAAoB;AAEzD,EAAA,MAAM,GAAA,GAAM,IAAI,MAAA,CAAO,KAAA,CAAM,OAAO,MAAM,CAAA;AAC1C,EAAA,GAAA,CAAI,cAAA,GAAiB,iCAAA;AACrB,EAAA,OAAO,GAAA;AACR;;;ACRO,IAAM,WAAA,GAAN,MAAM,YAAA,CAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBxB,aAAa,iBAAiB,GAAA,EAAa;AAC1C,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAG,CAAA;AAChC,IAAA,OAAO,MAAM,SAAS,WAAA,EAAY;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,aAAa,UAAU,GAAA,EAAa;AACnC,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAG,CAAA;AAChC,IAAA,OAAO,MAAM,SAAS,IAAA,EAAK;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,aAAa,aAAa,GAAA,EAAa;AACtC,IAAA,IAAI,GAAA,CAAI,UAAA,CAAW,OAAO,CAAA,EAAG,OAAO,GAAA;AACpC,IAAA,MAAM,IAAA,GAAO,MAAM,YAAA,CAAY,SAAA,CAAU,GAAG,CAAA;AAC5C,IAAA,OAAO,MAAM,YAAA,CAAY,aAAA,CAAc,IAAI,CAAA;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,aAAa,cAAc,IAAA,EAA6B;AACvD,IAAA,OAAO,MAAM,IAAI,OAAA,CAAQ,CAAC,SAAS,MAAA,KAAW;AAC7C,MAAA,IAAI,IAAA,EAAM;AACT,QAAA,MAAM,MAAA,GAAS,IAAI,UAAA,EAAW;AAC9B,QAAA,MAAA,CAAO,MAAA,GAAS,MAAM,OAAA,CAAQ,MAAA,CAAO,MAAgB,CAAA;AACrD,QAAA,MAAA,CAAO,OAAA,GAAU,CAAC,KAAA,KAAU,MAAA,CAAO,KAAK,CAAA;AACxC,QAAA,MAAA,CAAO,OAAA,GAAU,CAAC,KAAA,KAAU,MAAA,CAAO,KAAK,CAAA;AACxC,QAAA,MAAA,CAAO,cAAc,IAAI,CAAA;AAAA,MAC1B;AAAA,IACD,CAAC,CAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,aAAa,WAAW,IAAA,EAA6B;AACpD,IAAA,OAAO,MAAM,IAAI,OAAA,CAAQ,CAAC,SAAS,MAAA,KAAW;AAC7C,MAAA,IAAI,IAAA,EAAM;AACT,QAAA,MAAM,MAAA,GAAS,IAAI,UAAA,EAAW;AAC9B,QAAA,MAAA,CAAO,MAAA,GAAS,MAAM,OAAA,CAAQ,MAAA,CAAO,MAAgB,CAAA;AACrD,QAAA,MAAA,CAAO,OAAA,GAAU,CAAC,KAAA,KAAU,MAAA,CAAO,KAAK,CAAA;AACxC,QAAA,MAAA,CAAO,OAAA,GAAU,CAAC,KAAA,KAAU,MAAA,CAAO,KAAK,CAAA;AACxC,QAAA,MAAA,CAAO,WAAW,IAAI,CAAA;AAAA,MACvB;AAAA,IACD,CAAC,CAAA;AAAA,EACF;AAAA,EA4BA,OAAO,eAAA,CAAgB,IAAA,EAAmB,WAAA,EAAkC;AAC3E,IAAA,IAAI,IAAA,CAAK,IAAA,KAAS,WAAA,EAAa,OAAO,IAAA;AACtC,IAAA,IAAI,gBAAgB,IAAA,EAAM;AACzB,MAAA,OAAO,IAAI,IAAA,CAAK,CAAC,IAAI,CAAA,EAAG,KAAK,IAAA,EAAM,EAAE,IAAA,EAAM,WAAA,EAAa,CAAA;AAAA,IACzD;AACA,IAAA,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,IAAA,EAAM,aAAa,CAAA;AAAA,EAC9C;AACD;;;ACxKO,SAAS,iBAAiB,MAAA,EAAgB;AAChD,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACvC,IAAA,IAAA,GAAA,CAAQ,IAAA,IAAQ,CAAA,IAAK,IAAA,GAAO,MAAA,CAAO,WAAW,CAAC,CAAA;AAC/C,IAAA,IAAA,IAAQ,CAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAA,GAAO,EAAA;AACf;AAuBO,SAAS,iBAAiB,GAAA,EAAU;AAC1C,EAAA,OAAO,gBAAA,CAAiB,IAAA,CAAK,SAAA,CAAU,GAAG,CAAC,CAAA;AAC5C;AAyBO,SAAS,iBAAiB,MAAA,EAAqB;AACrD,EAAA,MAAM,IAAA,GAAO,IAAI,QAAA,CAAS,MAAM,CAAA;AAChC,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,YAAY,CAAA,EAAA,EAAK;AACzC,IAAA,IAAA,GAAA,CAAQ,IAAA,IAAQ,CAAA,IAAK,IAAA,GAAO,IAAA,CAAK,SAAS,CAAC,CAAA;AAC3C,IAAA,IAAA,IAAQ,CAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAA,GAAO,EAAA;AACf;AAsBO,SAAS,IAAI,GAAA,EAAa;AAChC,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA;AAC3B,EAAA,MAAA,CAAO,IAAA,CAAK,GAAG,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,MAAA,GAAS,CAAC,CAAC,CAAC,CAAA;AAC9D,EAAA,MAAA,CAAO,IAAA,CAAK,GAAG,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,MAAA,GAAS,CAAC,CAAC,CAAC,CAAA;AAC9D,EAAA,MAAA,CAAO,IAAA,CAAK,GAAG,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,MAAA,GAAS,CAAC,CAAC,CAAC,CAAA;AAC9D,EAAA,MAAA,CAAO,IAAA,CAAK,GAAG,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,MAAA,GAAS,CAAC,CAAC,CAAC,CAAA;AAC9D,EAAA,OAAO,MAAA,CACL,OAAA,EAAQ,CACR,GAAA,CAAI,CAAC,MAAO,CAAC,CAAA,GAAK,CAAC,CAAA,GAAI,CAAA,GAAI,CAAA,GAAI,CAAC,CAAA,GAAI,CAAC,CAAA,GAAI,CAAA,GAAI,CAAC,CAAA,GAAI,IAAI,CAAA,GAAK,CAAE,CAAA,CAC7D,IAAA,CAAK,EAAE,CAAA;AACV;;;ACvGA,IAAM,SAAS,UAAA,CAAW,MAAA;AAK1B,IAAM,WAAA,GAAc,kEAAA;AAOpB,IAAM,oBAAA,GAAuB,GAAA;AAC7B,IAAI,IAAA;AAAJ,IAAsB,UAAA;AAEtB,SAAS,SAAS,KAAA,EAAe;AAChC,EAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,MAAA,GAAS,KAAA,EAAO;AACjC,IAAA,IAAA,GAAO,IAAI,UAAA,CAAW,KAAA,GAAQ,oBAAoB,CAAA;AAClD,IAAA,MAAA,CAAO,gBAAgB,IAAI,CAAA;AAC3B,IAAA,UAAA,GAAa,CAAA;AAAA,EACd,CAAA,MAAA,IAAW,UAAA,GAAa,KAAA,GAAQ,IAAA,CAAK,MAAA,EAAQ;AAC5C,IAAA,MAAA,CAAO,gBAAgB,IAAI,CAAA;AAC3B,IAAA,UAAA,GAAa,CAAA;AAAA,EACd;AACA,EAAA,UAAA,IAAc,KAAA;AACf;AAEA,SAAS,MAAA,CAAO,OAAO,EAAA,EAAI;AAE1B,EAAA,QAAA,CAAU,QAAQ,CAAE,CAAA;AACpB,EAAA,IAAI,EAAA,GAAK,EAAA;AAET,EAAA,KAAA,IAAS,CAAA,GAAI,UAAA,GAAa,IAAA,EAAM,CAAA,GAAI,YAAY,CAAA,EAAA,EAAK;AAMpD,IAAA,EAAA,IAAM,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,GAAI,EAAE,CAAA;AAAA,EAC/B;AACA,EAAA,OAAO,EAAA;AACR;AAEA,IAAI,IAAA,GAAO,MAAA;AAoBJ,SAAS,aAAa,EAAA,EAA+B;AAC3D,EAAA,IAAA,GAAO,EAAA;AACR;AAmBO,SAAS,eAAA,GAAkB;AACjC,EAAA,IAAA,GAAO,MAAA;AACR;AA2BO,SAAS,SAAS,IAAA,EAAuB;AAC/C,EAAA,OAAO,KAAK,IAAI,CAAA;AACjB;;;AC/GO,SAAS,qBAAkC,GAAA,EAA8B;AAC/E,EAAA,OAAO,GAAA,CAAI,MAAA,EAAO,CAAE,IAAA,EAAK,CAAE,KAAA;AAC5B;;;AClBO,IAAM,WAAN,MAAqB;AAAA,EAE3B,YAAoB,OAAA,EAAiB;AAAjB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EAAkB;AAAA,EAAlB,OAAA;AAAA,EADZ,GAAA,uBAAU,GAAA,EAAU;AAAA,EAG5B,IAAI,GAAA,EAAuB;AAC1B,IAAA,IAAI,CAAC,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAG,GAAG,OAAO,MAAA;AAC/B,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AAE9B,IAAA,IAAA,CAAK,GAAA,CAAI,OAAO,GAAG,CAAA;AACnB,IAAA,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AACvB,IAAA,OAAO,KAAA;AAAA,EACR;AAAA,EAEA,GAAA,CAAI,KAAQ,KAAA,EAAgB;AAC3B,IAAA,IAAI,IAAA,CAAK,IAAI,GAAA,CAAI,GAAG,GAAG,IAAA,CAAK,GAAA,CAAI,OAAO,GAAG,CAAA;AAC1C,IAAA,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AACvB,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,IAAA,GAAO,IAAA,CAAK,OAAA,EAAS;AAEjC,MAAA,IAAA,CAAK,GAAA,CAAI,OAAO,IAAA,CAAK,GAAA,CAAI,MAAK,CAAE,IAAA,GAAO,KAAM,CAAA;AAAA,IAC9C;AAAA,EACD;AAAA,EAEA,IAAI,GAAA,EAAiB;AACpB,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AAAA,EACxB;AAAA;AAAA,EAGA,IAAI,IAAA,GAAe;AAClB,IAAA,OAAO,KAAK,GAAA,CAAI,IAAA;AAAA,EACjB;AACD;;;ACGO,SAAS,eAAe,MAAA,EAA8B;AAC5D,EAAA,MAAM,IAAA,GAAO,IAAI,UAAA,CAAW,MAAM,CAAA;AAElC,EAAA,IACC,CAAC,IAAA,IACD,EAAG,OAAO,WAAW,WAAA,IAAe,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA,IAAM,IAAA,YAAgB,UAAA,CAAA,IAC9E,IAAA,CAAK,SAAS,EAAA,EACb;AACD,IAAA,OAAO,KAAA;AAAA,EACR;AAEA,EAAA,MAAM,KAAA,GACL,IAAA,CAAK,CAAC,CAAA,KAAM,GAAA,IACZ,IAAA,CAAK,CAAC,CAAA,KAAM,EAAA,IACZ,IAAA,CAAK,CAAC,CAAA,KAAM,MACZ,IAAA,CAAK,CAAC,CAAA,KAAM,EAAA,IACZ,IAAA,CAAK,CAAC,CAAA,KAAM,EAAA,IACZ,KAAK,CAAC,CAAA,KAAM,EAAA,IACZ,IAAA,CAAK,CAAC,CAAA,KAAM,EAAA,IACZ,IAAA,CAAK,CAAC,CAAA,KAAM,EAAA;AAEb,EAAA,IAAI,CAAC,KAAA,EAAO;AACX,IAAA,OAAO,KAAA;AAAA,EACR;AAeA,EAAA,SAAS,iBACR,QAAA,EACA,MAAA,EACA,SAAA,EACA,SAAA,EACA,YAAY,IAAA,EACX;AAKD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACZ,MAAA,OAAO,EAAA;AAAA,IACR;AACA,IAAA,MAAA,GAAS,IAAI,MAAA,CAAO,MAAA,EAAQ,GAAG,CAAA;AAK/B,IAAA,MAAM,aAAA,GAAgB,OAAO,MAAA,CAAO,MAAA;AACpC,IAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAIhC,IAAA,MAAM,uBAAuB,QAAA,CAAS,MAAA;AACtC,IAAA,IAAI,OAAO,cAAc,WAAA,EAAa;AACrC,MAAA,SAAA,GAAY,oBAAA;AAAA,IACb;AACA,IAAA,IAAI,SAAA,IAAa,oBAAA,IAAwB,SAAA,IAAa,CAAA,IAAK,aAAa,SAAA,EAAW;AAClF,MAAA,OAAO,EAAA;AAAA,IACR;AACA,IAAA,QAAA,GAAW,QAAA,CAAS,QAAA,CAAS,SAAA,EAAW,SAAS,CAAA;AAEjD,IAAA,IAAI,QAAA,GAAW,EAAA;AACf,IAAA,IAAI,aAAA,GAAgB,CAAA;AACpB,IAAA,IAAI,WAAA,GAAc,CAAA;AAClB,IAAA,IAAI,aAAA,GAAgB,EAAA;AAEpB,IAAA,KAAA,EAAO,OAAO,aAAA,GAAgB,QAAA,CAAS,MAAA,EAAQ;AAC9C,MAAA,MAAM,aAAa,aAAA,GAAgB,SAAA;AAEnC,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,QAAA,CAAS,aAAA,EAAe,UAAU,CAAA;AACzD,MAAA,MAAM,UAAU,OAAA,CAAQ,MAAA,CAAO,OAAO,EAAE,MAAA,EAAQ,MAAM,CAAA;AAEtD,MAAA,MAAM,OAAO,aAAA,GAAgB,OAAA;AAE7B,MAAA,IAAI,KAAA;AACJ,MAAA,IAAI,UAAA,GAAa,EAAA;AACjB,MAAA,OAAA,CAAQ,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,IAAI,OAAO,IAAA,EAAM;AAC5C,QAAA,UAAA,GAAa,KAAA,CAAM,QAAQ,aAAA,CAAc,MAAA;AACzC,QAAA,QAAA,GAAW,WAAA,GAAc,UAAA;AACzB,QAAA,MAAM,KAAA;AAAA,MACP;AAEA,MAAA,aAAA,GAAgB,UAAA;AAChB,MAAA,WAAA,IAAe,OAAA,CAAQ,MAAA;AAIvB,MAAA,MAAM,eACL,UAAA,GAAa,EAAA,GAAK,UAAA,GAAa,aAAA,GAAgB,QAAQ,MAAA,GAAS,aAAA;AACjE,MAAA,aAAA,GAAgB,OAAA,CAAQ,MAAM,YAAY,CAAA;AAAA,IAC3C;AAGA,IAAA,IAAI,YAAY,CAAA,EAAG;AAClB,MAAA,QAAA,IAAY,SAAA,IAAa,CAAA,GAAI,SAAA,GAAY,oBAAA,GAAuB,SAAA;AAAA,IACjE;AAEA,IAAA,OAAO,QAAA;AAAA,EACR;AAIA,EAAA,MAAM,OAAA,GAAU,gBAAA,CAAiB,IAAA,EAAM,MAAA,EAAQ,EAAE,CAAA;AACjD,EAAA,IAAI,WAAW,EAAA,EAAI;AAClB,IAAA,MAAM,OAAA,GAAU,gBAAA,CAAiB,IAAA,EAAM,MAAA,EAAQ,GAAG,OAAO,CAAA;AACzD,IAAA,OAAO,OAAA,IAAW,CAAA;AAAA,EACnB;AAEA,EAAA,OAAO,KAAA;AACR;;;ACvHO,IAAM,cAAA,GAAiB,CAAC,MAAA,KAAwB;AACtD,EAAA,MAAM,IAAA,GAAO,IAAI,UAAA,CAAW,MAAM,CAAA;AAClC,EAAA,OAAO,IAAA,CAAK,CAAC,CAAA,KAAM,EAAA;AACpB,CAAA;;;AC9BA,SAAS,mBAAA,CAAoB,QAAoB,MAAA,EAAwB;AACxE,EAAA,IAAI,MAAA,GAAS,CAAA;AAEb,EAAA,OAAO,MAAA,CAAO,MAAA,GAAS,MAAM,CAAA,EAAG;AAC/B,IAAA,MAAA,IAAU,MAAA,CAAO,MAAA,GAAS,MAAM,CAAA,GAAI,CAAA;AAAA,EACrC;AAEA,EAAA,OAAO,MAAA,GAAS,CAAA;AACjB;AAiBO,SAAS,MAAM,MAAA,EAA8B;AACnD,EAAA,MAAM,GAAA,GAAM,IAAI,WAAA,CAAY,OAAO,CAAA;AACnC,EAAA,MAAM,SAAS,GAAA,CAAI,MAAA,CAAO,OAAO,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA;AAC5C,EAAA,OAAO,MAAA,KAAW,KAAA;AACnB;AAoBO,SAAS,cAAc,MAAA,EAA8B;AAC3D,EAAA,MAAM,IAAA,GAAO,IAAI,UAAA,CAAW,MAAM,CAAA;AAClC,EAAA,IAAI,aAAA,EAAe,cAAA;AACnB,EAAA,IAAI,MAAA,GAAS,CAAA;AACb,EAAA,IAAI,WAAA,GAAc,CAAA;AAIlB,EAAA,IAAI,CAAC,KAAA,CAAM,MAAM,CAAA,EAAG;AACnB,IAAA,OAAO,KAAA;AAAA,EACR;AAIA,EAAA,aAAA,GAAgB,IAAA,CAAK,EAAE,CAAA,GAAI,GAAA;AAC3B,EAAA,cAAA,GAAiB,IAAA,CAAK,EAAE,CAAA,GAAI,CAAA;AAE5B,EAAA,MAAA,IAAU,CAAA;AACV,EAAA,MAAA,IAAU,CAAA;AACV,EAAA,MAAA,IAAU,gBAAgB,CAAA,GAAI,IAAA,CAAK,IAAI,CAAA,EAAG,cAAA,GAAiB,CAAC,CAAA,GAAI,CAAA;AAIhE,EAAA,OAAO,WAAA,GAAc,CAAA,IAAK,MAAA,GAAS,IAAA,CAAK,MAAA,EAAQ;AAC/C,IAAA,QAAQ,IAAA,CAAK,MAAM,CAAA;AAAG;AAAA;AAAA;AAAA;AAAA,MAKrB,KAAK,EAAA;AACJ,QAAA,WAAA,IAAe,CAAA;AAEf,QAAA,aAAA,GAAgB,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA,GAAI,GAAA;AACnC,QAAA,cAAA,GAAiB,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA,GAAI,CAAA;AAEpC,QAAA,MAAA,IAAU,EAAA;AACV,QAAA,MAAA,IAAU,gBAAgB,CAAA,GAAI,IAAA,CAAK,IAAI,CAAA,EAAG,cAAA,GAAiB,CAAC,CAAA,GAAI,CAAA;AAChE,QAAA,MAAA,IAAU,mBAAA,CAAoB,IAAA,EAAM,MAAA,GAAS,CAAC,CAAA,GAAI,CAAA;AAElD,QAAA;AAAA;AAAA;AAAA,MAID,KAAK,EAAA;AACJ,QAAA,MAAA,IAAU,CAAA;AACV,QAAA,MAAA,IAAU,mBAAA,CAAoB,MAAM,MAAM,CAAA;AAE1C,QAAA;AAAA;AAAA;AAAA,MAID,KAAK,EAAA;AACJ,QAAA,MAAA,GAAS,IAAA,CAAK,MAAA;AACd,QAAA;AAAA;AAAA,MAGD;AAEC,QAAA,MAAA,GAAS,IAAA,CAAK,MAAA;AACd,QAAA;AAAA;AACF,EACD;AAEA,EAAA,OAAO,WAAA,GAAc,CAAA;AACtB;;;AC5GA,IAAI,KAAA,GAAoC;AAAA,EACvC,CAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,QAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,QAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,QAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,QAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,QAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAA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","file":"index.mjs","sourcesContent":["interface DrawLibraryVersion {\n\tname: string\n\tversion: string\n\tmodules: string\n}\n\ninterface DrawLibraryVersionInfo {\n\tversions: DrawLibraryVersion[]\n\tdidWarn: boolean\n\tscheduledNotice: number | NodeJS.Timeout | null\n}\n\nconst DRAW_LIBRARY_VERSION_KEY = '__TLDRAW_LIBRARY_VERSIONS__' as const\n\n// eslint-disable-next-line @typescript-eslint/prefer-namespace-keyword, @typescript-eslint/no-namespace, no-shadow-restricted-names\ndeclare module globalThis {\n\texport const __TLDRAW_LIBRARY_VERSIONS__: DrawLibraryVersionInfo\n}\n\nfunction getLibraryVersions(): DrawLibraryVersionInfo {\n\tif (globalThis[DRAW_LIBRARY_VERSION_KEY]) {\n\t\treturn globalThis[DRAW_LIBRARY_VERSION_KEY]\n\t}\n\n\tconst info: DrawLibraryVersionInfo = {\n\t\tversions: [],\n\t\tdidWarn: false,\n\t\tscheduledNotice: null,\n\t}\n\n\tObject.defineProperty(globalThis, DRAW_LIBRARY_VERSION_KEY, {\n\t\tvalue: info,\n\t\twritable: false,\n\t\tconfigurable: false,\n\t\tenumerable: false,\n\t})\n\n\treturn info\n}\n\n/**\n * Clears all registered library versions and resets warning state.\n * This function is intended for testing purposes only to reset the global version tracking state.\n * @returns void\n * @example\n * ```ts\n * // In a test setup\n * beforeEach(() => {\n * clearRegisteredVersionsForTests()\n * })\n *\n * // Now version tracking starts fresh for each test\n * registerDrawLibraryVersion('@ibodr/editor', '2.0.0', 'esm')\n * ```\n * @internal\n */\nexport function clearRegisteredVersionsForTests() {\n\tconst info = getLibraryVersions()\n\tinfo.versions = []\n\tinfo.didWarn = false\n\tif (info.scheduledNotice) {\n\t\tclearTimeout(info.scheduledNotice)\n\t\tinfo.scheduledNotice = null\n\t}\n}\n\n/**\n * Registers a tldraw library version for conflict detection.\n * This function tracks different tldraw library versions to warn about potential conflicts\n * when multiple versions are loaded simultaneously.\n * @param name - The name of the tldraw library package (e.g., '\\@ibodr/editor').\n * @param version - The semantic version string (e.g., '2.0.0').\n * @param modules - The module system being used ('esm' or 'cjs').\n * @returns void\n * @example\n * ```ts\n * // Register a library version during package initialization\n * registerDrawLibraryVersion('@ibodr/editor', '2.0.0', 'esm')\n * registerDrawLibraryVersion('@ibodr/tldraw', '2.0.0', 'esm')\n *\n * // If conflicting versions are detected, warnings will be logged:\n * registerDrawLibraryVersion('@ibodr/editor', '1.9.0', 'cjs')\n * // Console warning about version mismatch will appear\n * ```\n * @internal\n */\nexport function registerDrawLibraryVersion(name?: string, version?: string, modules?: string) {\n\tif (!name || !version || !modules) {\n\t\tif ((globalThis as any).DRAW_LIBRARY_IS_BUILD) {\n\t\t\tthrow new Error('Missing name/version/module system in built version of tldraw library')\n\t\t}\n\t\treturn\n\t}\n\n\tconst info = getLibraryVersions()\n\n\t// In Next.js dev mode, Fast Refresh re-executes module-level code which causes\n\t// the same library to register multiple times, producing a false positive warning.\n\t// We skip exact duplicates only in Next.js dev to avoid hiding genuine issues.\n\tif (isNextjsDev()) {\n\t\tconst isDuplicate = info.versions.some(\n\t\t\t(v) => v.name === name && v.version === version && v.modules === modules\n\t\t)\n\t\tif (isDuplicate) return\n\t}\n\n\tinfo.versions.push({ name, version, modules })\n\n\tif (!info.scheduledNotice) {\n\t\ttry {\n\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\tinfo.scheduledNotice = setTimeout(() => {\n\t\t\t\tinfo.scheduledNotice = null\n\t\t\t\tcheckLibraryVersions(info)\n\t\t\t}, 100)\n\t\t} catch {\n\t\t\t// some environments (e.g. cloudflare workers) don't support setTimeout immediately, only in a handler.\n\t\t\t// in this case, we'll just check immediately.\n\t\t\tcheckLibraryVersions(info)\n\t\t}\n\t}\n}\n\nfunction checkLibraryVersions(info: DrawLibraryVersionInfo) {\n\tif (!info.versions.length) return\n\tif (info.didWarn) return\n\n\tconst sorted = info.versions.sort((a, b) => compareVersions(a.version, b.version))\n\tconst latestVersion = sorted[sorted.length - 1].version\n\n\tconst matchingVersions = new Set<string>()\n\tconst nonMatchingVersions = new Map<string, Set<string>>()\n\tfor (const lib of sorted) {\n\t\tif (nonMatchingVersions.has(lib.name)) {\n\t\t\tmatchingVersions.delete(lib.name)\n\t\t\tentry(nonMatchingVersions, lib.name, new Set()).add(lib.version)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (lib.version === latestVersion) {\n\t\t\tmatchingVersions.add(lib.name)\n\t\t} else {\n\t\t\tmatchingVersions.delete(lib.name)\n\t\t\tentry(nonMatchingVersions, lib.name, new Set()).add(lib.version)\n\t\t}\n\t}\n\n\tif (nonMatchingVersions.size > 0) {\n\t\tconst message = [\n\t\t\t`${format('[tldraw]', ['bold', 'bgRed', 'textWhite'])} ${format('You have multiple versions of tldraw libraries installed. This can lead to bugs and unexpected behavior.', ['textRed', 'bold'])}`,\n\t\t\t'',\n\t\t\t`The latest version you have installed is ${format(`v${latestVersion}`, ['bold', 'textBlue'])}. The following libraries are on the latest version:`,\n\t\t\t...Array.from(matchingVersions, (name) => ` • ✅ ${format(name, ['bold'])}`),\n\t\t\t'',\n\t\t\t`The following libraries are not on the latest version, or have multiple versions installed:`,\n\t\t\t...Array.from(nonMatchingVersions, ([name, versions]) => {\n\t\t\t\tconst sortedVersions = Array.from(versions)\n\t\t\t\t\t.sort(compareVersions)\n\t\t\t\t\t.map((v) => format(`v${v}`, v === latestVersion ? ['textGreen'] : ['textRed']))\n\t\t\t\treturn ` • ❌ ${format(name, ['bold'])} (${sortedVersions.join(', ')})`\n\t\t\t}),\n\t\t]\n\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(message.join('\\n'))\n\t\tinfo.didWarn = true\n\t\treturn\n\t}\n\n\t// at this point, we know that everything has the same version. there may still be duplicates though!\n\tconst potentialDuplicates = new Map<string, { version: string; modules: string[] }>()\n\tfor (const lib of sorted) {\n\t\tentry(potentialDuplicates, lib.name, { version: lib.version, modules: [] }).modules.push(\n\t\t\tlib.modules\n\t\t)\n\t}\n\n\tconst duplicates = new Map<string, { version: string; modules: string[] }>()\n\tfor (const [name, lib] of potentialDuplicates) {\n\t\tif (lib.modules.length > 1) duplicates.set(name, lib)\n\t}\n\n\tif (duplicates.size > 0) {\n\t\tconst message = [\n\t\t\t`${format('[tldraw]', ['bold', 'bgRed', 'textWhite'])} ${format('You have multiple instances of some tldraw libraries active. This can lead to bugs and unexpected behavior. ', ['textRed', 'bold'])}`,\n\t\t\t'',\n\t\t\t'This usually means that your bundler is misconfigured, and is importing the same library multiple times - usually once as an ES Module, and once as a CommonJS module.',\n\t\t\t'',\n\t\t\t'The following libraries have been imported multiple times:',\n\t\t\t...Array.from(duplicates, ([name, lib]) => {\n\t\t\t\tconst modules = lib.modules\n\t\t\t\t\t.map((m, i) => (m === 'esm' ? ` ${i + 1}. ES Modules` : ` ${i + 1}. CommonJS`))\n\t\t\t\t\t.join('\\n')\n\t\t\t\treturn ` • ❌ ${format(name, ['bold'])} v${lib.version}: \\n${modules}`\n\t\t\t}),\n\t\t\t'',\n\t\t\t'You should configure your bundler to only import one version of each library.',\n\t\t]\n\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(message.join('\\n'))\n\t\tinfo.didWarn = true\n\t\treturn\n\t}\n}\n\nfunction compareVersions(a: string, b: string) {\n\tconst aMatch = a.match(/^(\\d+)\\.(\\d+)\\.(\\d+)(?:-(\\w+))?$/)\n\tconst bMatch = b.match(/^(\\d+)\\.(\\d+)\\.(\\d+)(?:-(\\w+))?$/)\n\n\tif (!aMatch || !bMatch) return a.localeCompare(b)\n\tif (aMatch[1] !== bMatch[1]) return Number(aMatch[1]) - Number(bMatch[1])\n\tif (aMatch[2] !== bMatch[2]) return Number(aMatch[2]) - Number(bMatch[2])\n\tif (aMatch[3] !== bMatch[3]) return Number(aMatch[3]) - Number(bMatch[3])\n\tif (aMatch[4] && bMatch[4]) return aMatch[4].localeCompare(bMatch[4])\n\tif (aMatch[4]) return 1\n\tif (bMatch[4]) return -1\n\treturn 0\n}\n\nconst formats = {\n\tbold: '1',\n\ttextBlue: '94',\n\ttextRed: '31',\n\ttextGreen: '32',\n\tbgRed: '41',\n\ttextWhite: '97',\n} as const\nfunction format(value: string, formatters: (keyof typeof formats)[] = []) {\n\treturn `\\x1B[${formatters.map((f) => formats[f]).join(';')}m${value}\\x1B[m`\n}\n\nfunction isNextjsDev(): boolean {\n\ttry {\n\t\treturn process.env.NODE_ENV === 'development' && '__NEXT_DATA__' in globalThis\n\t} catch {\n\t\treturn false\n\t}\n}\n\nfunction entry<K, V>(map: Map<K, V>, key: K, defaultValue: V): V {\n\tif (map.has(key)) {\n\t\treturn map.get(key)!\n\t}\n\tmap.set(key, defaultValue)\n\treturn defaultValue\n}\n","/**\n * Rotate the contents of an array by a specified offset.\n *\n * Creates a new array with elements shifted to the left by the specified number of positions.\n * Both positive and negative offsets result in left shifts (elements move left, with elements\n * from the front wrapping to the back).\n *\n * @param arr - The array to rotate\n * @param offset - The number of positions to shift left (both positive and negative values shift left)\n * @returns A new array with elements shifted left by the specified offset\n *\n * @example\n * ```ts\n * rotateArray([1, 2, 3, 4], 1) // [2, 3, 4, 1]\n * rotateArray([1, 2, 3, 4], -1) // [2, 3, 4, 1]\n * rotateArray(['a', 'b', 'c'], 2) // ['c', 'a', 'b']\n * ```\n * @public\n */\nexport function rotateArray<T>(arr: T[], offset: number): T[] {\n\tif (arr.length === 0) return []\n\n\t// Based on the test expectations, both positive and negative offsets\n\t// should rotate left (shift elements to the left)\n\tconst normalizedOffset = ((Math.abs(offset) % arr.length) + arr.length) % arr.length\n\n\t// Slice the array at the offset point and concatenate\n\treturn [...arr.slice(normalizedOffset), ...arr.slice(0, normalizedOffset)]\n}\n\n/**\n * Remove duplicate items from an array.\n *\n * Creates a new array with duplicate items removed. Uses strict equality by default,\n * or a custom equality function if provided. Order of first occurrence is preserved.\n *\n * @param input - The array to deduplicate\n * @param equals - Optional custom equality function to compare items (defaults to strict equality)\n * @returns A new array with duplicate items removed\n *\n * @example\n * ```ts\n * dedupe([1, 2, 2, 3, 1]) // [1, 2, 3]\n * dedupe(['a', 'b', 'a', 'c']) // ['a', 'b', 'c']\n *\n * // With custom equality function\n * const objects = [{id: 1}, {id: 2}, {id: 1}]\n * dedupe(objects, (a, b) => a.id === b.id) // [{id: 1}, {id: 2}]\n * ```\n * @public\n */\nexport function dedupe<T>(input: T[], equals?: (a: any, b: any) => boolean): T[] {\n\tconst result: T[] = []\n\tmainLoop: for (const item of input) {\n\t\tfor (const existing of result) {\n\t\t\tif (equals ? equals(item, existing) : item === existing) {\n\t\t\t\tcontinue mainLoop\n\t\t\t}\n\t\t}\n\t\tresult.push(item)\n\t}\n\treturn result\n}\n\n/**\n * Remove null and undefined values from an array.\n *\n * Creates a new array with all null and undefined values filtered out.\n * The resulting array has a refined type that excludes null and undefined.\n *\n * @param arr - The array to compact\n * @returns A new array with null and undefined values removed\n *\n * @example\n * ```ts\n * compact([1, null, 2, undefined, 3]) // [1, 2, 3]\n * compact(['a', null, 'b', undefined]) // ['a', 'b']\n * ```\n * @internal\n */\nexport function compact<T>(arr: T[]): NonNullable<T>[] {\n\treturn arr.filter((i) => i !== undefined && i !== null) as any\n}\n\n/**\n * Get the last element of an array.\n *\n * Returns the last element of an array, or undefined if the array is empty.\n * Works with readonly arrays and preserves the element type.\n *\n * @param arr - The array to get the last element from\n * @returns The last element of the array, or undefined if the array is empty\n *\n * @example\n * ```ts\n * last([1, 2, 3]) // 3\n * last(['a', 'b', 'c']) // 'c'\n * last([]) // undefined\n * ```\n * @internal\n */\nexport function last<T>(arr: readonly T[]): T | undefined {\n\treturn arr[arr.length - 1]\n}\n\n/**\n * Find the item in an array with the minimum value according to a function.\n *\n * Finds the array item that produces the smallest value when passed through\n * the provided function. Returns undefined for empty arrays.\n *\n * @param arr - The array to search\n * @param fn - Function to compute the comparison value for each item\n * @returns The item with the minimum value, or undefined if the array is empty\n *\n * @example\n * ```ts\n * const people = [{name: 'Alice', age: 30}, {name: 'Bob', age: 25}]\n * minBy(people, p => p.age) // {name: 'Bob', age: 25}\n *\n * minBy([3, 1, 4, 1, 5], x => x) // 1\n * minBy([], x => x) // undefined\n * ```\n * @internal\n */\nexport function minBy<T>(arr: readonly T[], fn: (item: T) => number): T | undefined {\n\tlet min: T | undefined\n\tlet minVal = Infinity\n\tfor (const item of arr) {\n\t\tconst val = fn(item)\n\t\tif (val < minVal) {\n\t\t\tmin = item\n\t\t\tminVal = val\n\t\t}\n\t}\n\treturn min\n}\n\n/**\n * Find the item in an array with the maximum value according to a function.\n *\n * Finds the array item that produces the largest value when passed through\n * the provided function. Returns undefined for empty arrays.\n *\n * @param arr - The array to search\n * @param fn - Function to compute the comparison value for each item\n * @returns The item with the maximum value, or undefined if the array is empty\n *\n * @example\n * ```ts\n * const people = [{name: 'Alice', age: 30}, {name: 'Bob', age: 25}]\n * maxBy(people, p => p.age) // {name: 'Alice', age: 30}\n *\n * maxBy([3, 1, 4, 1, 5], x => x) // 5\n * maxBy([], x => x) // undefined\n * ```\n * @internal\n */\nexport function maxBy<T>(arr: readonly T[], fn: (item: T) => number): T | undefined {\n\tlet max: T | undefined\n\tlet maxVal: number = -Infinity\n\tfor (const item of arr) {\n\t\tconst val = fn(item)\n\t\tif (val > maxVal) {\n\t\t\tmax = item\n\t\t\tmaxVal = val\n\t\t}\n\t}\n\treturn max\n}\n\n/**\n * Split an array into two arrays based on a predicate function.\n *\n * Partitions an array into two arrays: one containing items that satisfy\n * the predicate, and another containing items that do not. The original array order is preserved.\n *\n * @param arr - The array to partition\n * @param predicate - The predicate function to test each item\n * @returns A tuple of two arrays: [satisfying items, non-satisfying items]\n *\n * @example\n * ```ts\n * const [evens, odds] = partition([1, 2, 3, 4, 5], x => x % 2 === 0)\n * // evens: [2, 4], odds: [1, 3, 5]\n *\n * const [adults, minors] = partition(\n * [{name: 'Alice', age: 30}, {name: 'Bob', age: 17}],\n * person => person.age >= 18\n * )\n * // adults: [{name: 'Alice', age: 30}], minors: [{name: 'Bob', age: 17}]\n * ```\n * @internal\n */\nexport function partition<T>(arr: T[], predicate: (item: T) => boolean): [T[], T[]] {\n\tconst satisfies: T[] = []\n\tconst doesNotSatisfy: T[] = []\n\tfor (const item of arr) {\n\t\tif (predicate(item)) {\n\t\t\tsatisfies.push(item)\n\t\t} else {\n\t\t\tdoesNotSatisfy.push(item)\n\t\t}\n\t}\n\treturn [satisfies, doesNotSatisfy]\n}\n\n/**\n * Check if two arrays are shallow equal.\n *\n * Compares two arrays for shallow equality by checking if they have the same length\n * and the same elements at each index using Object.is comparison. Returns true if arrays are\n * the same reference, have different lengths, or any elements differ.\n *\n * @param arr1 - First array to compare\n * @param arr2 - Second array to compare\n * @returns True if arrays are shallow equal, false otherwise\n *\n * @example\n * ```ts\n * areArraysShallowEqual([1, 2, 3], [1, 2, 3]) // true\n * areArraysShallowEqual([1, 2, 3], [1, 2, 4]) // false\n * areArraysShallowEqual(['a', 'b'], ['a', 'b']) // true\n * areArraysShallowEqual([1, 2], [1, 2, 3]) // false\n *\n * const obj = {x: 1}\n * areArraysShallowEqual([obj], [obj]) // true (same reference)\n * areArraysShallowEqual([{x: 1}], [{x: 1}]) // false (different objects)\n * ```\n * @internal\n */\nexport function areArraysShallowEqual<T>(arr1: readonly T[], arr2: readonly T[]): boolean {\n\tif (arr1 === arr2) return true\n\tif (arr1.length !== arr2.length) return false\n\tfor (let i = 0; i < arr1.length; i++) {\n\t\tif (!Object.is(arr1[i], arr2[i])) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n/**\n * Merge custom entries with defaults, replacing defaults that have matching keys.\n *\n * Combines two arrays by keeping all custom entries and only the default entries\n * that don't have a matching key in the custom entries. Custom entries always override defaults.\n * The result contains remaining defaults first, followed by all custom entries.\n *\n * @param key - The property name to use as the unique identifier\n * @param customEntries - Array of custom entries that will override defaults\n * @param defaults - Array of default entries\n * @returns A new array with defaults filtered out where custom entries exist, plus all custom entries\n *\n * @example\n * ```ts\n * const defaults = [{type: 'text', value: 'default'}, {type: 'number', value: 0}]\n * const custom = [{type: 'text', value: 'custom'}]\n *\n * mergeArraysAndReplaceDefaults('type', custom, defaults)\n * // Result: [{type: 'number', value: 0}, {type: 'text', value: 'custom'}]\n *\n * const tools = [{id: 'select', name: 'Select'}, {id: 'draw', name: 'Draw'}]\n * const customTools = [{id: 'select', name: 'Custom Select'}]\n *\n * mergeArraysAndReplaceDefaults('id', customTools, tools)\n * // Result: [{id: 'draw', name: 'Draw'}, {id: 'select', name: 'Custom Select'}]\n * ```\n * @internal\n */\nexport function mergeArraysAndReplaceDefaults<\n\tconst Key extends string,\n\tT extends { [K in Key]: string },\n>(key: Key, customEntries: readonly T[], defaults: readonly T[]) {\n\tconst overrideTypes = new Set(customEntries.map((entry) => entry[key]))\n\n\tconst result = []\n\tfor (const defaultEntry of defaults) {\n\t\tif (overrideTypes.has(defaultEntry[key])) continue\n\t\tresult.push(defaultEntry)\n\t}\n\n\tfor (const customEntry of customEntries) {\n\t\tresult.push(customEntry)\n\t}\n\n\treturn result\n}\n","/**\n * When a function is wrapped in `omitFromStackTrace`, if it throws an error the stack trace won't\n * include the function itself or any stack frames above it. Useful for assertion-style function\n * where the error will ideally originate from the call-site rather than within the implementation\n * of the assert fn.\n *\n * Only works in platforms that support `Error.captureStackTrace` (ie v8).\n *\n * @param fn - The function to wrap and exclude from stack traces\n * @returns A wrapped version of the function that omits itself from error stack traces\n * @example\n * ```ts\n * const assertPositive = omitFromStackTrace((value: number) => {\n * if (value <= 0) throw new Error('Value must be positive')\n * return value\n * })\n *\n * assertPositive(-1) // Error stack trace will point to this line, not inside assertPositive\n * ```\n * @internal\n */\nexport function omitFromStackTrace<Args extends Array<unknown>, Return>(\n\tfn: (...args: Args) => Return\n): (...args: Args) => Return {\n\tconst wrappedFn = (...args: Args) => {\n\t\ttry {\n\t\t\treturn fn(...args)\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && Error.captureStackTrace) {\n\t\t\t\tError.captureStackTrace(error, wrappedFn)\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\treturn wrappedFn\n}\n\n/**\n * Does nothing, but it's really really good at it.\n * @internal\n */\nexport const noop: () => void = () => {}\n","import { omitFromStackTrace } from './function'\n\n/**\n * Represents a successful result containing a value.\n *\n * Interface for the success case of a Result type, containing the computed value.\n * Used in conjunction with ErrorResult to create a discriminated union for error handling.\n *\n * @example\n * ```ts\n * const success: OkResult<string> = { ok: true, value: 'Hello World' }\n * if (success.ok) {\n * console.log(success.value) // 'Hello World'\n * }\n * ```\n * @public\n */\nexport interface OkResult<T> {\n\treadonly ok: true\n\treadonly value: T\n}\n/**\n * Represents a failed result containing an error.\n *\n * Interface for the error case of a Result type, containing the error information.\n * Used in conjunction with OkResult to create a discriminated union for error handling.\n *\n * @example\n * ```ts\n * const failure: ErrorResult<string> = { ok: false, error: 'Something went wrong' }\n * if (!failure.ok) {\n * console.error(failure.error) // 'Something went wrong'\n * }\n * ```\n * @public\n */\nexport interface ErrorResult<E> {\n\treadonly ok: false\n\treadonly error: E\n}\n/**\n * A discriminated union type for handling success and error cases.\n *\n * Represents either a successful result with a value or a failed result with an error.\n * This pattern provides type-safe error handling without throwing exceptions. The 'ok' property\n * serves as the discriminant for type narrowing.\n *\n * @example\n * ```ts\n * function divide(a: number, b: number): Result<number, string> {\n * if (b === 0) {\n * return Result.err('Division by zero')\n * }\n * return Result.ok(a / b)\n * }\n *\n * const result = divide(10, 2)\n * if (result.ok) {\n * console.log(`Result: ${result.value}`) // Result: 5\n * } else {\n * console.error(`Error: ${result.error}`)\n * }\n * ```\n * @public\n */\nexport type Result<T, E> = OkResult<T> | ErrorResult<E>\n\n/**\n * Utility object for creating Result instances.\n *\n * Provides factory methods for creating OkResult and ErrorResult instances.\n * This is the preferred way to construct Result values for consistent structure.\n *\n * @example\n * ```ts\n * // Create success result\n * const success = Result.ok(42)\n * // success: OkResult<number> = { ok: true, value: 42 }\n *\n * // Create error result\n * const failure = Result.err('Invalid input')\n * // failure: ErrorResult<string> = { ok: false, error: 'Invalid input' }\n * ```\n * @public\n */\nexport const Result = {\n\t/**\n\t * Create a successful result containing a value.\n\t *\n\t * @param value - The success value to wrap\n\t * @returns An OkResult containing the value\n\t */\n\tok<T>(value: T): OkResult<T> {\n\t\treturn { ok: true, value }\n\t},\n\t/**\n\t * Create a failed result containing an error.\n\t *\n\t * @param error - The error value to wrap\n\t * @returns An ErrorResult containing the error\n\t */\n\terr<E>(error: E): ErrorResult<E> {\n\t\treturn { ok: false, error }\n\t},\n\n\t/**\n\t * Create a successful result containing an array of values.\n\t *\n\t * If any of the results are errors, the returned result will be an error containing the first error.\n\t *\n\t * @param results - The array of results to wrap\n\t * @returns An OkResult containing the array of values\n\t */\n\tall<T>(results: Result<T, any>[]): Result<T[], any> {\n\t\treturn results.every((result) => result.ok)\n\t\t\t? Result.ok(results.map((result) => result.value))\n\t\t\t: Result.err(results.find((result) => !result.ok)?.error)\n\t},\n}\n\n/**\n * Throws an error for unhandled switch cases in exhaustive switch statements.\n *\n * Utility function to ensure exhaustive handling of discriminated unions in switch\n * statements. When called, it indicates a programming error where a case was not handled.\n * The TypeScript 'never' type ensures this function is only reachable if all cases aren't covered.\n *\n * @param value - The unhandled value (typed as 'never' for exhaustiveness checking)\n * @param property - Optional property name to extract from the value for better error messages\n * @returns Never returns (always throws)\n *\n * @example\n * ```ts\n * type Shape = 'circle' | 'square' | 'triangle'\n *\n * function getArea(shape: Shape): number {\n * switch (shape) {\n * case 'circle': return Math.PI * 5 * 5\n * case 'square': return 10 * 10\n * case 'triangle': return 0.5 * 10 * 8\n * default: return exhaustiveSwitchError(shape)\n * }\n * }\n * ```\n * @internal\n */\nexport function exhaustiveSwitchError(value: never, property?: string): never {\n\tconst debugValue =\n\t\tproperty && value && typeof value === 'object' && property in value ? value[property] : value\n\tthrow new Error(`Unknown switch case ${debugValue}`)\n}\n\n/**\n * Assert that a value is truthy, throwing an error if it's not.\n *\n * TypeScript assertion function that throws an error if the provided value is falsy.\n * After this function executes successfully, TypeScript narrows the type to exclude falsy values.\n * Stack trace is omitted from the error for cleaner debugging.\n *\n * @param value - The value to assert as truthy\n * @param message - Optional custom error message\n *\n * @example\n * ```ts\n * const user = getUser() // User | null\n * assert(user, 'User must be logged in')\n * // TypeScript now knows user is non-null\n * console.log(user.name) // Safe to access properties\n * ```\n * @internal\n */\nexport const assert: (value: unknown, message?: string) => asserts value = omitFromStackTrace(\n\t(value, message) => {\n\t\tif (!value) {\n\t\t\tthrow new Error(message || 'Assertion Error')\n\t\t}\n\t}\n)\n\n/**\n * Assert that a value is not null or undefined.\n *\n * Throws an error if the value is null or undefined, otherwise returns the value\n * with a refined type that excludes null and undefined. Stack trace is omitted for cleaner debugging.\n *\n * @param value - The value to check for null/undefined\n * @param message - Optional custom error message\n * @returns The value with null and undefined excluded from the type\n *\n * @example\n * ```ts\n * const element = document.getElementById('my-id') // HTMLElement | null\n * const safeElement = assertExists(element, 'Element not found')\n * // TypeScript now knows safeElement is HTMLElement (not null)\n * safeElement.addEventListener('click', handler) // Safe to call methods\n * ```\n * @internal\n */\nexport const assertExists = omitFromStackTrace(<T>(value: T, message?: string): NonNullable<T> => {\n\t// note that value == null is equivalent to value === null || value === undefined\n\tif (value == null) {\n\t\tthrow new Error(message ?? 'value must be defined')\n\t}\n\treturn value as NonNullable<T>\n})\n\n/**\n * Create a Promise with externally accessible resolve and reject functions.\n *\n * Creates a Promise along with its resolve and reject functions exposed as\n * properties on the returned object. This allows external code to control when the\n * Promise resolves or rejects, useful for coordination between async operations.\n *\n * @returns A Promise object with additional resolve and reject methods\n *\n * @example\n * ```ts\n * const deferred = promiseWithResolve<string>()\n *\n * // Set up the promise consumer\n * deferred.then(value => console.log(`Resolved: ${value}`))\n * deferred.catch(error => console.error(`Rejected: ${error}`))\n *\n * // Later, resolve from external code\n * setTimeout(() => {\n * deferred.resolve('Hello World')\n * }, 1000)\n * ```\n * @internal\n */\nexport function promiseWithResolve<T>(): Promise<T> & {\n\tresolve(value: T): void\n\treject(reason?: any): void\n} {\n\tlet resolve: (value: T) => void\n\tlet reject: (reason?: any) => void\n\tconst promise = new Promise<T>((res, rej) => {\n\t\tresolve = res\n\t\treject = rej\n\t})\n\treturn Object.assign(promise, {\n\t\tresolve: resolve!,\n\t\treject: reject!,\n\t})\n}\n\n/**\n * Create a Promise that resolves after a specified delay.\n *\n * Utility function for introducing delays in async code. Returns a Promise\n * that resolves with undefined after the specified number of milliseconds. Useful for\n * implementing timeouts, rate limiting, or adding delays in testing scenarios.\n *\n * @param ms - The delay in milliseconds\n * @returns A Promise that resolves after the specified delay\n *\n * @example\n * ```ts\n * async function delayedOperation() {\n * console.log('Starting...')\n * await sleep(1000) // Wait 1 second\n * console.log('Done!')\n * }\n *\n * // Can also be used with .then()\n * sleep(500).then(() => {\n * console.log('Half second has passed')\n * })\n * ```\n * @internal\n */\nexport function sleep(ms: number): Promise<void> {\n\t// eslint-disable-next-line no-restricted-globals\n\treturn new Promise((resolve) => setTimeout(resolve, ms))\n}\n","/*!\n * MIT License: https://github.com/NoHomey/bind-decorator/blob/master/License\n * Copyright (c) 2016 Ivo Stratev\n */\n\nimport { assert } from './control'\n\n/**\n * Decorator that binds a method to its class instance (legacy stage-2 TypeScript decorators).\n * When applied to a class method, ensures `this` always refers to the class instance,\n * even when the method is called as a callback or event handler.\n *\n * @param target - The prototype of the class being decorated\n * @param propertyKey - The name of the method being decorated\n * @param descriptor - The property descriptor for the method being decorated\n * @returns The modified property descriptor with bound method access\n * @example\n * ```typescript\n * class MyClass {\n * name = 'example';\n *\n * @bind\n * getName() {\n * return this.name;\n * }\n * }\n *\n * const instance = new MyClass();\n * const callback = instance.getName;\n * console.log(callback()); // 'example' (this is properly bound)\n * ```\n * @public\n */\nexport function bind<T extends (...args: any[]) => any>(\n\ttarget: object,\n\tpropertyKey: string,\n\tdescriptor: TypedPropertyDescriptor<T>\n): TypedPropertyDescriptor<T>\n\n/**\n * Decorator that binds a method to its class instance (TC39 decorators standard).\n * When applied to a class method, ensures `this` always refers to the class instance,\n * even when the method is called as a callback or event handler.\n *\n * @param originalMethod - The original method being decorated\n * @param context - The decorator context containing metadata about the method\n * @example\n * ```typescript\n * class EventHandler {\n * message = 'Hello World';\n *\n * @bind\n * handleClick() {\n * console.log(this.message);\n * }\n * }\n *\n * const handler = new EventHandler();\n * document.addEventListener('click', handler.handleClick); // 'this' is properly bound\n * ```\n * @public\n */\nexport function bind<This extends object, T extends (...args: any[]) => any>(\n\toriginalMethod: T,\n\tcontext: ClassMethodDecoratorContext<This, T>\n): void\n\n/**\n * Universal decorator implementation that handles both legacy stage-2 and TC39 decorator formats.\n * Automatically detects the decorator format based on the number of arguments and binds the\n * decorated method to the class instance, preventing common `this` context issues.\n *\n * @param args - Either legacy decorator arguments (target, propertyKey, descriptor) or TC39 decorator arguments (originalMethod, context)\n * @returns Property descriptor for legacy decorators, or void for TC39 decorators\n * @example\n * ```typescript\n * // Works with both decorator formats\n * class Calculator {\n * multiplier = 2;\n *\n * @bind\n * multiply(value: number) {\n * return value * this.multiplier;\n * }\n * }\n *\n * const calc = new Calculator();\n * const multiplyFn = calc.multiply;\n * console.log(multiplyFn(5)); // 10 (this.multiplier is accessible)\n *\n * // Useful for event handlers and callbacks\n * setTimeout(calc.multiply, 100, 3); // 6\n * ```\n * @public\n */\nexport function bind(\n\t...args: // legacy stage-2 typescript decorators\n\t\t| [_target: object, propertyKey: string, descriptor: PropertyDescriptor]\n\t\t// TC39 decorators\n\t\t| [originalMethod: (...args: any[]) => any, context: ClassMemberDecoratorContext]\n): PropertyDescriptor | void {\n\tif (args.length === 2) {\n\t\tconst [originalMethod, context] = args\n\t\tcontext.addInitializer(function initializeMethod(this: any) {\n\t\t\tassert(Reflect.isExtensible(this), 'Cannot bind to a non-extensible class.')\n\t\t\tconst value = originalMethod.bind(this)\n\t\t\tconst ok = Reflect.defineProperty(this, context.name, {\n\t\t\t\tvalue,\n\t\t\t\twritable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t})\n\t\t\tassert(ok, 'Cannot bind a non-configurable class method.')\n\t\t})\n\t} else {\n\t\tconst [_target, propertyKey, descriptor] = args\n\t\tif (!descriptor || typeof descriptor.value !== 'function') {\n\t\t\tthrow new TypeError(\n\t\t\t\t`Only methods can be decorated with @bind. <${propertyKey}> is not a method!`\n\t\t\t)\n\t\t}\n\n\t\treturn {\n\t\t\tconfigurable: true,\n\t\t\tget(this: any): any {\n\t\t\t\tconst bound = descriptor.value!.bind(this)\n\t\t\t\t// Credits to https://github.com/andreypopp/autobind-decorator for memoizing the result of bind against a symbol on the instance.\n\t\t\t\tObject.defineProperty(this, propertyKey, {\n\t\t\t\t\tvalue: bound,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t})\n\t\t\t\treturn bound\n\t\t\t},\n\t\t}\n\t}\n}\n","/**\n * A lightweight cache implementation using WeakMap for storing key-value pairs.\n *\n * A micro cache that stores computed values associated with object keys.\n * Uses WeakMap internally, which means keys can be garbage collected when no other\n * references exist, and only object keys are supported. Provides lazy computation\n * with memoization.\n *\n * @example\n * ```ts\n * const cache = new WeakCache<User, string>()\n * const user = { id: 1, name: 'Alice' }\n *\n * // Get cached value, computing it if not present\n * const displayName = cache.get(user, (u) => `${u.name} (#${u.id})`)\n * // Returns 'Alice (#1)'\n *\n * // Subsequent calls return cached value\n * const sameName = cache.get(user, (u) => `${u.name} (#${u.id})`)\n * // Returns 'Alice (#1)' without recomputing\n * ```\n * @public\n */\nexport class WeakCache<K extends object, V> {\n\t/**\n\t * The internal WeakMap storage for cached key-value pairs.\n\t *\n\t * @public\n\t */\n\titems = new WeakMap<K, V>()\n\n\t/**\n\t * Get the cached value for a given key, computing it if not already cached.\n\t *\n\t * Retrieves the cached value associated with the given key. If no cached\n\t * value exists, calls the provided callback function to compute the value, stores it\n\t * in the cache, and returns it. Subsequent calls with the same key will return the\n\t * cached value without recomputation.\n\t *\n\t * @param item - The object key to retrieve the cached value for\n\t * @param cb - Callback function that computes the value when not already cached\n\t * @returns The cached value if it exists, otherwise the newly computed value from the callback\n\t *\n\t * @example\n\t * ```ts\n\t * const cache = new WeakCache<HTMLElement, DOMRect>()\n\t * const element = document.getElementById('my-element')!\n\t *\n\t * // First call computes and caches the bounding rect\n\t * const rect1 = cache.get(element, (el) => el.getBoundingClientRect())\n\t *\n\t * // Second call returns cached value\n\t * const rect2 = cache.get(element, (el) => el.getBoundingClientRect())\n\t * // rect1 and rect2 are the same object\n\t * ```\n\t */\n\tget<P extends K>(item: P, cb: (item: P) => V) {\n\t\tif (!this.items.has(item)) {\n\t\t\tthis.items.set(item, cb(item))\n\t\t}\n\n\t\treturn this.items.get(item)!\n\t}\n}\n","import type { Awaitable } from './types'\n\n/**\n * Create a debounced version of a function that delays execution until after a specified wait time.\n *\n * Debouncing ensures that a function is only executed once after a specified delay,\n * even if called multiple times in rapid succession. Each new call resets the timer. The debounced\n * function returns a Promise that resolves with the result of the original function. Includes a\n * cancel method to prevent execution if needed.\n *\n * @param callback - The function to debounce (can be sync or async)\n * @param wait - The delay in milliseconds before executing the function\n * @returns A debounced function that returns a Promise and includes a cancel method\n *\n * @example\n * ```ts\n * // Debounce a search function\n * const searchAPI = (query: string) => fetch(`/search?q=${query}`)\n * const debouncedSearch = debounce(searchAPI, 300)\n *\n * // Multiple rapid calls will only execute the last one after 300ms\n * debouncedSearch('react').then(result => console.log(result))\n * debouncedSearch('react hooks') // This cancels the previous call\n * debouncedSearch('react typescript') // Only this will execute\n *\n * // Cancel pending execution\n * debouncedSearch.cancel()\n *\n * // With async/await\n * const saveData = debounce(async (data: any) => {\n * return await api.save(data)\n * }, 1000)\n *\n * const result = await saveData({name: 'John'})\n * ```\n *\n * @public\n * @see source - https://gist.github.com/ca0v/73a31f57b397606c9813472f7493a940\n */\nexport function debounce<T extends unknown[], U>(\n\tcallback: (...args: T) => Awaitable<U>,\n\twait: number\n) {\n\tlet state:\n\t\t| undefined\n\t\t| {\n\t\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\t\ttimeout: ReturnType<typeof setTimeout>\n\t\t\t\tpromise: Promise<U>\n\t\t\t\tresolve(value: U | PromiseLike<U>): void\n\t\t\t\treject(value: any): void\n\t\t\t\tlatestArgs: T\n\t\t } = undefined\n\n\tconst fn = (...args: T): Promise<U> => {\n\t\tif (!state) {\n\t\t\tstate = {} as any\n\t\t\tstate!.promise = new Promise((resolve, reject) => {\n\t\t\t\tstate!.resolve = resolve\n\t\t\t\tstate!.reject = reject\n\t\t\t})\n\t\t}\n\t\tclearTimeout(state!.timeout)\n\t\tstate!.latestArgs = args\n\t\t// It's up to the consumer of debounce to call `cancel`\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tstate!.timeout = setTimeout(() => {\n\t\t\tconst s = state!\n\t\t\tstate = undefined\n\t\t\ttry {\n\t\t\t\ts.resolve(callback(...s.latestArgs))\n\t\t\t} catch (e) {\n\t\t\t\ts.reject(e)\n\t\t\t}\n\t\t}, wait)\n\n\t\treturn state!.promise\n\t}\n\tfn.cancel = () => {\n\t\tif (!state) return\n\t\tclearTimeout(state.timeout)\n\t\tstate = undefined\n\t}\n\treturn fn\n}\n","/** @public */\nexport interface ErrorAnnotations {\n\ttags: Record<string, number | string | boolean | bigint | symbol | null | undefined>\n\textras: Record<string, unknown>\n}\n\nconst annotationsByError = new WeakMap<object, ErrorAnnotations>()\n\n/**\n * Annotate an error with tags and additional data. Annotations won't overwrite existing ones.\n * Retrieve them with `getErrorAnnotations`.\n *\n * @param error - The error object to annotate\n * @param annotations - Partial annotations to add (tags and/or extras)\n * @returns void\n * @example\n * ```ts\n * const error = new Error('Something went wrong')\n * annotateError(error, {\n * tags: { userId: '123', operation: 'save' },\n * extras: { timestamp: Date.now() }\n * })\n * ```\n *\n * @internal\n */\nexport function annotateError(error: unknown, annotations: Partial<ErrorAnnotations>) {\n\tif (typeof error !== 'object' || error === null) return\n\n\tlet currentAnnotations = annotationsByError.get(error)\n\tif (!currentAnnotations) {\n\t\tcurrentAnnotations = { tags: {}, extras: {} }\n\t\tannotationsByError.set(error, currentAnnotations)\n\t}\n\n\tif (annotations.tags) {\n\t\tcurrentAnnotations.tags = {\n\t\t\t...currentAnnotations.tags,\n\t\t\t...annotations.tags,\n\t\t}\n\t}\n\tif (annotations.extras) {\n\t\tcurrentAnnotations.extras = {\n\t\t\t...currentAnnotations.extras,\n\t\t\t...annotations.extras,\n\t\t}\n\t}\n}\n\n/**\n * Retrieve annotations that have been added to an error object.\n *\n * @param error - The error object to get annotations from\n * @returns The error annotations (tags and extras) or empty objects if none exist\n * @example\n * ```ts\n * const error = new Error('Something went wrong')\n * annotateError(error, { tags: { userId: '123' } })\n * const annotations = getErrorAnnotations(error)\n * console.log(annotations.tags.userId) // '123'\n * ```\n *\n * @internal\n */\nexport function getErrorAnnotations(error: Error): ErrorAnnotations {\n\treturn annotationsByError.get(error) ?? { tags: {}, extras: {} }\n}\n","import { sleep } from './control'\n\n/**\n * A queue that executes tasks sequentially with optional delay between tasks.\n *\n * ExecutionQueue ensures that tasks are executed one at a time in the order they were added,\n * with an optional timeout delay between each task execution. This is useful for rate limiting,\n * preventing race conditions, or controlling the flow of asynchronous operations.\n *\n * @example\n * ```ts\n * // Create a queue with 100ms delay between tasks\n * const queue = new ExecutionQueue(100)\n *\n * // Add tasks to the queue\n * const result1 = await queue.push(() => fetch('/api/data'))\n * const result2 = await queue.push(async () => {\n * const data = await processData()\n * return data\n * })\n *\n * // Check if queue is empty\n * if (queue.isEmpty()) {\n * console.log('All tasks completed')\n * }\n *\n * // Clean up\n * queue.close()\n * ```\n *\n * @internal\n */\nexport class ExecutionQueue {\n\tprivate queue: (() => Promise<any>)[] = []\n\tprivate running = false\n\n\t/**\n\t * Creates a new ExecutionQueue.\n\t *\n\t * Creates a new execution queue that will process tasks sequentially.\n\t * If a timeout is provided, there will be a delay between each task execution,\n\t * which is useful for rate limiting or controlling execution flow.\n\t *\n\t * timeout - Optional delay in milliseconds between task executions\n\t * @example\n\t * ```ts\n\t * // Create queue without delay\n\t * const fastQueue = new ExecutionQueue()\n\t *\n\t * // Create queue with 500ms delay between tasks\n\t * const slowQueue = new ExecutionQueue(500)\n\t * ```\n\t */\n\tconstructor(private readonly timeout?: number) {}\n\n\t/**\n\t * Checks if the queue is empty and not currently running a task.\n\t *\n\t * Determines whether the execution queue has completed all tasks and is idle.\n\t * Returns true only when there are no pending tasks in the queue AND no task is currently being executed.\n\t *\n\t * @returns True if the queue has no pending tasks and is not currently executing\n\t * @example\n\t * ```ts\n\t * const queue = new ExecutionQueue()\n\t *\n\t * console.log(queue.isEmpty()) // true - queue is empty\n\t *\n\t * queue.push(() => console.log('task'))\n\t * console.log(queue.isEmpty()) // false - task is running/pending\n\t * ```\n\t */\n\tisEmpty() {\n\t\treturn this.queue.length === 0 && !this.running\n\t}\n\n\tprivate async run() {\n\t\tif (this.running) return\n\t\ttry {\n\t\t\tthis.running = true\n\t\t\twhile (this.queue.length) {\n\t\t\t\tconst task = this.queue.shift()!\n\t\t\t\tawait task()\n\t\t\t\tif (this.timeout) {\n\t\t\t\t\tawait sleep(this.timeout)\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\t// this try/finally should not be needed because the tasks don't throw\n\t\t\t// but better safe than sorry\n\t\t\t// console.log('\\n\\n\\nrunning false\\n\\n\\n')\n\t\t\tthis.running = false\n\t\t}\n\t}\n\n\t/**\n\t * Adds a task to the queue and returns a promise that resolves with the task's result.\n\t *\n\t * Enqueues a task for sequential execution. The task will be executed after all\n\t * previously queued tasks have completed. If a timeout was specified in the constructor,\n\t * there will be a delay between this task and the next one.\n\t *\n\t * @param task - The function to execute (can be sync or async)\n\t * @returns Promise that resolves with the task's return value\n\t * @example\n\t * ```ts\n\t * const queue = new ExecutionQueue(100)\n\t *\n\t * // Add async task\n\t * const result = await queue.push(async () => {\n\t * const response = await fetch('/api/data')\n\t * return response.json()\n\t * })\n\t *\n\t * // Add sync task\n\t * const number = await queue.push(() => 42)\n\t * ```\n\t */\n\tasync push<T>(task: () => T): Promise<Awaited<T>> {\n\t\treturn new Promise<Awaited<T>>((resolve, reject) => {\n\t\t\tthis.queue.push(() => Promise.resolve(task()).then(resolve).catch(reject))\n\t\t\tthis.run()\n\t\t})\n\t}\n\n\t/**\n\t * Clears all pending tasks from the queue.\n\t *\n\t * Immediately removes all pending tasks from the queue. Any currently\n\t * running task will complete normally, but no additional tasks will be executed.\n\t * This method does not wait for the current task to finish.\n\t *\n\t * @returns void\n\t * @example\n\t * ```ts\n\t * const queue = new ExecutionQueue()\n\t *\n\t * // Add several tasks\n\t * queue.push(() => console.log('task 1'))\n\t * queue.push(() => console.log('task 2'))\n\t * queue.push(() => console.log('task 3'))\n\t *\n\t * // Clear all pending tasks\n\t * queue.close()\n\t * // Only 'task 1' will execute if it was already running\n\t * ```\n\t */\n\tclose() {\n\t\tthis.queue = []\n\t}\n}\n","/**\n * Just a wrapper around `window.fetch` that sets the `referrerPolicy` to `strict-origin-when-cross-origin`.\n *\n * @param input - A Request object or string containing the URL to fetch\n * @param init - Optional request initialization options\n * @returns Promise that resolves to the Response object\n * @internal\n */\nexport async function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n\t// eslint-disable-next-line tldraw/no-restricted-properties\n\treturn window.fetch(input, {\n\t\t// We want to make sure that the referrer is not sent to other domains.\n\t\treferrerPolicy: 'strict-origin-when-cross-origin',\n\t\t...init,\n\t})\n}\n\n/**\n * Just a wrapper around `new Image`, and yeah, it's a bit strange that it's in the network.ts file\n * but the main concern here is the referrerPolicy and setting it correctly.\n *\n * @param width - Optional width for the image element\n * @param height - Optional height for the image element\n * @returns HTMLImageElement with referrerPolicy set to 'strict-origin-when-cross-origin'\n * @internal\n */\nexport const Image = (width?: number, height?: number) => {\n\t// eslint-disable-next-line tldraw/no-restricted-properties\n\tconst img = new window.Image(width, height)\n\timg.referrerPolicy = 'strict-origin-when-cross-origin'\n\treturn img\n}\n","import { fetch } from './network'\n\n/**\n * Utility class providing helper methods for file and blob operations.\n *\n * FileHelpers contains static methods for common file operations including\n * URL fetching, format conversion, and MIME type manipulation. All methods work with\n * web APIs like fetch, FileReader, and Blob/File objects.\n *\n * @example\n * ```ts\n * // Fetch and convert a remote image to data URL\n * const dataUrl = await FileHelpers.urlToDataUrl('https://example.com/image.png')\n *\n * // Convert user-selected file to text\n * const text = await FileHelpers.blobToText(userFile)\n *\n * // Change file MIME type\n * const newFile = FileHelpers.rewriteMimeType(originalFile, 'application/json')\n * ```\n *\n * @public\n */\nexport class FileHelpers {\n\t/**\n\t * Converts a URL to an ArrayBuffer by fetching the resource.\n\t *\n\t * Fetches the resource at the given URL and returns its content as an ArrayBuffer.\n\t * This is useful for loading binary data like images, videos, or other file types.\n\t *\n\t * @param url - The URL of the file to fetch\n\t * @returns Promise that resolves to the file content as an ArrayBuffer\n\t * @example\n\t * ```ts\n\t * const buffer = await FileHelpers.urlToArrayBuffer('https://example.com/image.png')\n\t * console.log(buffer.byteLength) // Size of the file in bytes\n\t * ```\n\t * @public\n\t */\n\tstatic async urlToArrayBuffer(url: string) {\n\t\tconst response = await fetch(url)\n\t\treturn await response.arrayBuffer()\n\t}\n\n\t/**\n\t * Converts a URL to a Blob by fetching the resource.\n\t *\n\t * Fetches the resource at the given URL and returns its content as a Blob object.\n\t * Blobs are useful for handling file data in web applications.\n\t *\n\t * @param url - The URL of the file to fetch\n\t * @returns Promise that resolves to the file content as a Blob\n\t * @example\n\t * ```ts\n\t * const blob = await FileHelpers.urlToBlob('https://example.com/document.pdf')\n\t * console.log(blob.type) // 'application/pdf'\n\t * console.log(blob.size) // Size in bytes\n\t * ```\n\t * @public\n\t */\n\tstatic async urlToBlob(url: string) {\n\t\tconst response = await fetch(url)\n\t\treturn await response.blob()\n\t}\n\n\t/**\n\t * Converts a URL to a data URL by fetching the resource.\n\t *\n\t * Fetches the resource at the given URL and converts it to a base64-encoded data URL.\n\t * If the URL is already a data URL, it returns the URL unchanged. This is useful for embedding\n\t * resources directly in HTML or CSS.\n\t *\n\t * @param url - The URL of the file to convert, or an existing data URL\n\t * @returns Promise that resolves to a data URL string\n\t * @example\n\t * ```ts\n\t * const dataUrl = await FileHelpers.urlToDataUrl('https://example.com/image.jpg')\n\t * // Returns: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEA...'\n\t *\n\t * const existing = await FileHelpers.urlToDataUrl('data:text/plain;base64,SGVsbG8=')\n\t * // Returns the same data URL unchanged\n\t * ```\n\t * @public\n\t */\n\tstatic async urlToDataUrl(url: string) {\n\t\tif (url.startsWith('data:')) return url\n\t\tconst blob = await FileHelpers.urlToBlob(url)\n\t\treturn await FileHelpers.blobToDataUrl(blob)\n\t}\n\n\t/**\n\t * Convert a Blob to a base64 encoded data URL.\n\t *\n\t * Converts a Blob object to a base64-encoded data URL using the FileReader API.\n\t * This is useful for displaying images or embedding file content directly in HTML.\n\t *\n\t * @param file - The Blob object to convert\n\t * @returns Promise that resolves to a base64-encoded data URL string\n\t * @example\n\t * ```ts\n\t * const blob = new Blob(['Hello World'], { type: 'text/plain' })\n\t * const dataUrl = await FileHelpers.blobToDataUrl(blob)\n\t * // Returns: 'data:text/plain;base64,SGVsbG8gV29ybGQ='\n\t *\n\t * // With an image file\n\t * const imageDataUrl = await FileHelpers.blobToDataUrl(myImageFile)\n\t * // Can be used directly in img src attribute\n\t * ```\n\t * @public\n\t */\n\tstatic async blobToDataUrl(file: Blob): Promise<string> {\n\t\treturn await new Promise((resolve, reject) => {\n\t\t\tif (file) {\n\t\t\t\tconst reader = new FileReader()\n\t\t\t\treader.onload = () => resolve(reader.result as string)\n\t\t\t\treader.onerror = (error) => reject(error)\n\t\t\t\treader.onabort = (error) => reject(error)\n\t\t\t\treader.readAsDataURL(file)\n\t\t\t}\n\t\t})\n\t}\n\n\t/**\n\t * Convert a Blob to a unicode text string.\n\t *\n\t * Reads the content of a Blob object as a UTF-8 text string using the FileReader API.\n\t * This is useful for reading text files or extracting text content from blobs.\n\t *\n\t * @param file - The Blob object to convert to text\n\t * @returns Promise that resolves to the text content as a string\n\t * @example\n\t * ```ts\n\t * const textBlob = new Blob(['Hello World'], { type: 'text/plain' })\n\t * const text = await FileHelpers.blobToText(textBlob)\n\t * console.log(text) // 'Hello World'\n\t *\n\t * // With a text file from user input\n\t * const content = await FileHelpers.blobToText(myTextFile)\n\t * console.log(content) // File content as string\n\t * ```\n\t * @public\n\t */\n\tstatic async blobToText(file: Blob): Promise<string> {\n\t\treturn await new Promise((resolve, reject) => {\n\t\t\tif (file) {\n\t\t\t\tconst reader = new FileReader()\n\t\t\t\treader.onload = () => resolve(reader.result as string)\n\t\t\t\treader.onerror = (error) => reject(error)\n\t\t\t\treader.onabort = (error) => reject(error)\n\t\t\t\treader.readAsText(file)\n\t\t\t}\n\t\t})\n\t}\n\n\t/**\n\t * Creates a new Blob or File with a different MIME type.\n\t *\n\t * Creates a copy of the given Blob or File with a new MIME type while preserving\n\t * all other properties. If the current MIME type already matches the new one, returns the\n\t * original object unchanged. For File objects, preserves the filename.\n\t *\n\t * @param blob - The Blob or File object to modify\n\t * @param newMimeType - The new MIME type to assign\n\t * @returns A new Blob or File with the updated MIME type\n\t * @example\n\t * ```ts\n\t * // Change a generic blob to a specific image type\n\t * const blob = new Blob([imageData])\n\t * const imageBlob = FileHelpers.rewriteMimeType(blob, 'image/png')\n\t *\n\t * // Change a file's MIME type while preserving filename\n\t * const file = new File([data], 'document.txt', { type: 'text/plain' })\n\t * const jsonFile = FileHelpers.rewriteMimeType(file, 'application/json')\n\t * console.log(jsonFile.name) // 'document.txt' (preserved)\n\t * console.log(jsonFile.type) // 'application/json' (updated)\n\t * ```\n\t * @public\n\t */\n\tstatic rewriteMimeType(blob: Blob, newMimeType: string): Blob\n\tstatic rewriteMimeType(blob: File, newMimeType: string): File\n\tstatic rewriteMimeType(blob: Blob | File, newMimeType: string): Blob | File {\n\t\tif (blob.type === newMimeType) return blob\n\t\tif (blob instanceof File) {\n\t\t\treturn new File([blob], blob.name, { type: newMimeType })\n\t\t}\n\t\treturn new Blob([blob], { type: newMimeType })\n\t}\n}\n","/**\n * Hash a string using the FNV-1a algorithm.\n *\n * Generates a deterministic hash value for a given string using a variant of the FNV-1a\n * (Fowler-Noll-Vo) algorithm. The hash is returned as a string representation of a 32-bit integer.\n *\n * @param string - The input string to hash\n * @returns A string representation of the 32-bit hash value\n * @example\n * ```ts\n * const hash = getHashForString('hello world')\n * console.log(hash) // '-862545276'\n *\n * // Same input always produces same hash\n * const hash2 = getHashForString('hello world')\n * console.log(hash === hash2) // true\n * ```\n * @public\n */\nexport function getHashForString(string: string) {\n\tlet hash = 0\n\tfor (let i = 0; i < string.length; i++) {\n\t\thash = (hash << 5) - hash + string.charCodeAt(i)\n\t\thash |= 0 // Convert to 32bit integer\n\t}\n\treturn hash + ''\n}\n\n/**\n * Hash an object by converting it to JSON and then hashing the resulting string.\n *\n * Converts the object to a JSON string using JSON.stringify and then applies the same\n * hashing algorithm as getHashForString. Useful for creating consistent hash values\n * for objects, though the hash depends on JSON serialization order.\n *\n * @param obj - The object to hash (any JSON-serializable value)\n * @returns A string representation of the 32-bit hash value\n * @example\n * ```ts\n * const hash1 = getHashForObject({ name: 'John', age: 30 })\n * const hash2 = getHashForObject({ name: 'John', age: 30 })\n * console.log(hash1 === hash2) // true\n *\n * // Arrays work too\n * const arrayHash = getHashForObject([1, 2, 3, 'hello'])\n * console.log(arrayHash) // '-123456789'\n * ```\n * @public\n */\nexport function getHashForObject(obj: any) {\n\treturn getHashForString(JSON.stringify(obj))\n}\n\n/**\n * Hash an ArrayBuffer using the FNV-1a algorithm.\n *\n * Generates a deterministic hash value for binary data stored in an ArrayBuffer.\n * Processes the buffer byte by byte using the same hashing algorithm as getHashForString.\n * Useful for creating consistent identifiers for binary data like images or files.\n *\n * @param buffer - The ArrayBuffer containing binary data to hash\n * @returns A string representation of the 32-bit hash value\n * @example\n * ```ts\n * // Hash some binary data\n * const data = new Uint8Array([1, 2, 3, 4, 5])\n * const hash = getHashForBuffer(data.buffer)\n * console.log(hash) // '123456789'\n *\n * // Hash image file data\n * const fileBuffer = await file.arrayBuffer()\n * const fileHash = getHashForBuffer(fileBuffer)\n * console.log(fileHash) // Unique hash for the file\n * ```\n * @public\n */\nexport function getHashForBuffer(buffer: ArrayBuffer) {\n\tconst view = new DataView(buffer)\n\tlet hash = 0\n\tfor (let i = 0; i < view.byteLength; i++) {\n\t\thash = (hash << 5) - hash + view.getUint8(i)\n\t\thash |= 0 // Convert to 32bit integer\n\t}\n\treturn hash + ''\n}\n\n/**\n * Applies a string transformation algorithm that rearranges and modifies characters.\n *\n * Performs a series of character manipulations on the input string including\n * character repositioning through splicing operations and numeric character transformations.\n * This appears to be a custom encoding/obfuscation function.\n *\n * @param str - The input string to transform\n * @returns The transformed string after applying all manipulations\n * @example\n * ```ts\n * const result = lns('hello123')\n * console.log(result) // Transformed string (exact output depends on algorithm)\n *\n * // Can be used for simple string obfuscation\n * const obfuscated = lns('sensitive-data')\n * console.log(obfuscated) // Obfuscated version\n * ```\n * @public\n */\nexport function lns(str: string) {\n\tconst result = str.split('')\n\tresult.push(...result.splice(0, Math.round(result.length / 5)))\n\tresult.push(...result.splice(0, Math.round(result.length / 4)))\n\tresult.push(...result.splice(0, Math.round(result.length / 3)))\n\tresult.push(...result.splice(0, Math.round(result.length / 2)))\n\treturn result\n\t\t.reverse()\n\t\t.map((n) => (+n ? (+n < 5 ? 5 + +n : +n > 5 ? +n - 5 : n) : n))\n\t\t.join('')\n}\n","/*!\n * MIT License: https://github.com/ai/nanoid/blob/main/LICENSE\n * Modified code originally from <https://github.com/ai/nanoid>\n * Copyright 2017 Andrey Sitnik <andrey@sitnik.ru>\n *\n * `nanoid` is currently only distributed as an ES module. Some tools (jest, playwright) don't\n * properly support ESM-only code yet, and tldraw itself is distributed as both an ES module and a\n * CommonJS module. By including nanoid here, we can make sure it works well in every environment\n * where tldraw is used. We can also remove some unused features like custom alphabets.\n */\n\n// all environments that tldraw runs in (browser, workers, recent node versions) have global\n// `crypto`\nconst crypto = globalThis.crypto\n\n// This alphabet uses `A-Za-z0-9_-` symbols.\n// The order of characters is optimized for better gzip and brotli compression.\n// Same as in non-secure/index.js\nconst urlAlphabet = 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\n\n// It is best to make fewer, larger requests to the crypto module to\n// avoid system call overhead. So, random numbers are generated in a\n// pool. The pool is a Buffer that is larger than the initial random\n// request size by this multiplier. The pool is enlarged if subsequent\n// requests exceed the maximum buffer size.\nconst POOL_SIZE_MULTIPLIER = 128\nlet pool: Uint8Array, poolOffset: number\n\nfunction fillPool(bytes: number) {\n\tif (!pool || pool.length < bytes) {\n\t\tpool = new Uint8Array(bytes * POOL_SIZE_MULTIPLIER)\n\t\tcrypto.getRandomValues(pool)\n\t\tpoolOffset = 0\n\t} else if (poolOffset + bytes > pool.length) {\n\t\tcrypto.getRandomValues(pool)\n\t\tpoolOffset = 0\n\t}\n\tpoolOffset += bytes\n}\n\nfunction nanoid(size = 21) {\n\t// `-=` convert `size` to number to prevent `valueOf` abusing\n\tfillPool((size -= 0))\n\tlet id = ''\n\t// We are reading directly from the random pool to avoid creating new array\n\tfor (let i = poolOffset - size; i < poolOffset; i++) {\n\t\t// It is incorrect to use bytes exceeding the alphabet size.\n\t\t// The following mask reduces the random byte in the 0-255 value\n\t\t// range to the 0-63 value range. Therefore, adding hacks, such\n\t\t// as empty string fallback or magic numbers, is unnecessary because\n\t\t// the bitmask trims bytes down to the alphabet size.\n\t\tid += urlAlphabet[pool[i] & 63]\n\t}\n\treturn id\n}\n\nlet impl = nanoid\n/**\n * Mock the unique ID generator with a custom implementation for testing.\n *\n * Replaces the internal ID generation function with a custom one. This is useful\n * for testing scenarios where you need predictable or deterministic IDs.\n *\n * @param fn - The mock function that should return a string ID. Takes optional size parameter.\n * @example\n * ```ts\n * // Mock with predictable IDs for testing\n * mockUniqueId((size = 21) => 'test-id-' + size)\n * console.log(uniqueId()) // 'test-id-21'\n * console.log(uniqueId(10)) // 'test-id-10'\n *\n * // Restore original implementation when done\n * restoreUniqueId()\n * ```\n * @internal\n */\nexport function mockUniqueId(fn: (size?: number) => string) {\n\timpl = fn\n}\n\n/**\n * Restore the original unique ID generator after mocking.\n *\n * Resets the ID generation function back to the original nanoid implementation.\n * This should be called after testing to restore normal ID generation behavior.\n *\n * @example\n * ```ts\n * // After mocking for tests\n * mockUniqueId(() => 'mock-id')\n *\n * // Restore original behavior\n * restoreUniqueId()\n * console.log(uniqueId()) // Now generates real random IDs again\n * ```\n * @internal\n */\nexport function restoreUniqueId() {\n\timpl = nanoid\n}\n\n/**\n * Generate a unique ID using a modified nanoid algorithm.\n *\n * Generates a cryptographically secure random string ID using URL-safe characters.\n * The default size is 21 characters, which provides a good balance of uniqueness\n * and brevity. Uses the global crypto API for secure random number generation.\n *\n * @param size - Optional length of the generated ID (defaults to 21 characters)\n * @returns A unique string identifier\n * @example\n * ```ts\n * // Generate default 21-character ID\n * const id = uniqueId()\n * console.log(id) // 'V1StGXR8_Z5jdHi6B-myT'\n *\n * // Generate shorter ID\n * const shortId = uniqueId(10)\n * console.log(shortId) // 'V1StGXR8_Z'\n *\n * // Generate longer ID\n * const longId = uniqueId(32)\n * console.log(longId) // 'V1StGXR8_Z5jdHi6B-myTVKahvjdx...'\n * ```\n * @public\n */\nexport function uniqueId(size?: number): string {\n\treturn impl(size)\n}\n","/**\n * Get the first item from an iterable Set or Map.\n *\n * @param value - The iterable Set or Map to get the first item from\n * @returns The first value from the Set or Map\n * @example\n * ```ts\n * const A = getFirstFromIterable(new Set([1, 2, 3])) // 1\n * const B = getFirstFromIterable(\n * \tnew Map([\n * \t\t['a', 1],\n * \t\t['b', 2],\n * \t])\n * ) // 1\n * ```\n * @public\n */\nexport function getFirstFromIterable<T = unknown>(set: Set<T> | Map<any, T>): T {\n\treturn set.values().next().value!\n}\n","/** Simple LRU cache backed by a Map's insertion-order iteration. @public */\nexport class LruCache<K, V> {\n\tprivate map = new Map<K, V>()\n\tconstructor(private maxSize: number) {}\n\n\tget(key: K): V | undefined {\n\t\tif (!this.map.has(key)) return undefined\n\t\tconst value = this.map.get(key)!\n\t\t// Move to most-recent position\n\t\tthis.map.delete(key)\n\t\tthis.map.set(key, value)\n\t\treturn value\n\t}\n\n\tset(key: K, value: V): void {\n\t\tif (this.map.has(key)) this.map.delete(key)\n\t\tthis.map.set(key, value)\n\t\tif (this.map.size > this.maxSize) {\n\t\t\t// Evict oldest entry\n\t\t\tthis.map.delete(this.map.keys().next().value!)\n\t\t}\n\t}\n\n\thas(key: K): boolean {\n\t\treturn this.map.has(key)\n\t}\n\n\t// eslint-disable-next-line tldraw/no-setter-getter\n\tget size(): number {\n\t\treturn this.map.size\n\t}\n}\n","/*!\n * MIT License: https://github.com/vHeemstra/is-apng/blob/main/license\n * Copyright (c) Philip van Heemstra\n */\n\n/**\n * Determines whether an ArrayBuffer contains an animated PNG (APNG) image.\n *\n * This function checks if the provided buffer contains a valid PNG file with animation\n * control chunks (acTL) that precede the image data chunks (IDAT), which indicates\n * it's an animated PNG rather than a static PNG.\n *\n * @param buffer - The ArrayBuffer containing the image data to analyze\n * @returns True if the buffer contains an animated PNG, false otherwise\n *\n * @example\n * ```typescript\n * // Check if an uploaded file contains an animated PNG\n * if (file.type === 'image/apng') {\n * const isAnimated = isApngAnimated(await file.arrayBuffer())\n * console.log(isAnimated ? 'Animated PNG' : 'Static PNG')\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Use with fetch to check remote images\n * const response = await fetch('image.png')\n * const buffer = await response.arrayBuffer()\n * const hasAnimation = isApngAnimated(buffer)\n * ```\n *\n * @public\n */\nexport function isApngAnimated(buffer: ArrayBuffer): boolean {\n\tconst view = new Uint8Array(buffer)\n\n\tif (\n\t\t!view ||\n\t\t!((typeof Buffer !== 'undefined' && Buffer.isBuffer(view)) || view instanceof Uint8Array) ||\n\t\tview.length < 16\n\t) {\n\t\treturn false\n\t}\n\n\tconst isPNG =\n\t\tview[0] === 0x89 &&\n\t\tview[1] === 0x50 &&\n\t\tview[2] === 0x4e &&\n\t\tview[3] === 0x47 &&\n\t\tview[4] === 0x0d &&\n\t\tview[5] === 0x0a &&\n\t\tview[6] === 0x1a &&\n\t\tview[7] === 0x0a\n\n\tif (!isPNG) {\n\t\treturn false\n\t}\n\n\t/**\n\t * Returns the index of the first occurrence of a string pattern in a Uint8Array, or -1 if not found.\n\t *\n\t * Searches for a string pattern by decoding chunks of the byte array to UTF-8 text and using\n\t * regular expression matching. Handles cases where the pattern might be split across chunk boundaries.\n\t *\n\t * @param haystack - The Uint8Array to search in\n\t * @param needle - The string or RegExp pattern to locate\n\t * @param fromIndex - The array index at which to begin the search\n\t * @param upToIndex - The array index up to which to search (optional, defaults to array end)\n\t * @param chunksize - Size of the chunks used when searching (default 1024 bytes)\n\t * @returns The index position of the first match, or -1 if not found\n\t */\n\tfunction indexOfSubstring(\n\t\thaystack: Uint8Array,\n\t\tneedle: string | RegExp,\n\t\tfromIndex: number,\n\t\tupToIndex?: number,\n\t\tchunksize = 1024 /* Bytes */\n\t) {\n\t\t/**\n\t\t * Adopted from: https://stackoverflow.com/a/67771214/2142071\n\t\t */\n\n\t\tif (!needle) {\n\t\t\treturn -1\n\t\t}\n\t\tneedle = new RegExp(needle, 'g')\n\n\t\t// The needle could get split over two chunks.\n\t\t// So, at every chunk we prepend the last few characters\n\t\t// of the last chunk.\n\t\tconst needle_length = needle.source.length\n\t\tconst decoder = new TextDecoder()\n\n\t\t// Handle search offset in line with\n\t\t// `Array.prototype.indexOf()` and `TypedArray.prototype.subarray()`.\n\t\tconst full_haystack_length = haystack.length\n\t\tif (typeof upToIndex === 'undefined') {\n\t\t\tupToIndex = full_haystack_length\n\t\t}\n\t\tif (fromIndex >= full_haystack_length || upToIndex <= 0 || fromIndex >= upToIndex) {\n\t\t\treturn -1\n\t\t}\n\t\thaystack = haystack.subarray(fromIndex, upToIndex)\n\n\t\tlet position = -1\n\t\tlet current_index = 0\n\t\tlet full_length = 0\n\t\tlet needle_buffer = ''\n\n\t\touter: while (current_index < haystack.length) {\n\t\t\tconst next_index = current_index + chunksize\n\t\t\t// subarray doesn't copy\n\t\t\tconst chunk = haystack.subarray(current_index, next_index)\n\t\t\tconst decoded = decoder.decode(chunk, { stream: true })\n\n\t\t\tconst text = needle_buffer + decoded\n\n\t\t\tlet match: RegExpExecArray | null\n\t\t\tlet last_index = -1\n\t\t\twhile ((match = needle.exec(text)) !== null) {\n\t\t\t\tlast_index = match.index - needle_buffer.length\n\t\t\t\tposition = full_length + last_index\n\t\t\t\tbreak outer\n\t\t\t}\n\n\t\t\tcurrent_index = next_index\n\t\t\tfull_length += decoded.length\n\n\t\t\t// Check that the buffer doesn't itself include the needle\n\t\t\t// this would cause duplicate finds (we could also use a Set to avoid that).\n\t\t\tconst needle_index =\n\t\t\t\tlast_index > -1 ? last_index + needle_length : decoded.length - needle_length\n\t\t\tneedle_buffer = decoded.slice(needle_index)\n\t\t}\n\n\t\t// Correct for search offset.\n\t\tif (position >= 0) {\n\t\t\tposition += fromIndex >= 0 ? fromIndex : full_haystack_length + fromIndex\n\t\t}\n\n\t\treturn position\n\t}\n\n\t// APNGs have an animation control chunk ('acTL') preceding the IDATs.\n\t// See: https://en.wikipedia.org/wiki/APNG#File_format\n\tconst idatIdx = indexOfSubstring(view, 'IDAT', 12)\n\tif (idatIdx >= 12) {\n\t\tconst actlIdx = indexOfSubstring(view, 'acTL', 8, idatIdx)\n\t\treturn actlIdx >= 8\n\t}\n\n\treturn false\n}\n\n// globalThis.isApng = isApng\n\n// (new TextEncoder()).encode('IDAT')\n// Decimal: [73, 68, 65, 84]\n// Hex: [0x49, 0x44, 0x41, 0x54]\n\n// (new TextEncoder()).encode('acTL')\n// Decimal: [97, 99, 84, 76]\n// Hex: [0x61, 0x63, 0x54, 0x4C]\n\n// const idatIdx = buffer.indexOf('IDAT')\n// const actlIdx = buffer.indexOf('acTL')\n","/**\n * Determines whether an ArrayBuffer contains an animated AVIF image.\n *\n * This function performs a simple check by examining the 4th byte of the buffer.\n * AVIF animation is indicated when the byte at index 3 equals 44.\n *\n * @param buffer - The ArrayBuffer containing the AVIF image data to analyze\n * @returns True if the buffer contains an animated AVIF, false otherwise\n *\n * @example\n * ```typescript\n * // Check if an AVIF file is animated\n * const response = await fetch('image.avif')\n * const buffer = await response.arrayBuffer()\n * const isAnimated = isAvifAnimated(buffer)\n * if (isAnimated) {\n * console.log('This AVIF contains animation!')\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Use with file input\n * const fileInput = document.querySelector('input[type=\"file\"]')\n * fileInput.addEventListener('change', async (event) => {\n * const file = event.target.files[0]\n * const buffer = await file.arrayBuffer()\n * const hasAnimation = isAvifAnimated(buffer)\n * console.log(hasAnimation ? 'Animated AVIF' : 'Static AVIF')\n * })\n * ```\n *\n * @public\n */\nexport const isAvifAnimated = (buffer: ArrayBuffer) => {\n\tconst view = new Uint8Array(buffer)\n\treturn view[3] === 44\n}\n","/*!\n * MIT License\n * Modified code originally from <https://github.com/qzb/is-animated>\n * Copyright (c) 2016 Józef Sokołowski <j.k.sokolowski@gmail.com>\n */\n\n/** Returns total length of data blocks sequence */\nfunction getDataBlocksLength(buffer: Uint8Array, offset: number): number {\n\tlet length = 0\n\n\twhile (buffer[offset + length]) {\n\t\tlength += buffer[offset + length] + 1\n\t}\n\n\treturn length + 1\n}\n\n/**\n * Checks if buffer contains GIF image by examining the file header.\n *\n * @param buffer - The ArrayBuffer containing the image data to check\n * @returns True if the buffer contains a GIF image, false otherwise\n * @example\n * ```ts\n * // Check a file from user input\n * const file = event.target.files[0]\n * const buffer = await file.arrayBuffer()\n * const isGif = isGIF(buffer)\n * console.log(isGif ? 'GIF image' : 'Not a GIF')\n * ```\n * @public\n */\nexport function isGIF(buffer: ArrayBuffer): boolean {\n\tconst enc = new TextDecoder('ascii')\n\tconst header = enc.decode(buffer.slice(0, 3))\n\treturn header === 'GIF'\n}\n\n/**\n * Checks if buffer contains animated GIF image by parsing the GIF structure and counting image descriptors.\n * A GIF is considered animated if it contains more than one image descriptor block.\n *\n * @param buffer - The ArrayBuffer containing the GIF image data\n * @returns True if the GIF is animated (contains multiple frames), false otherwise\n * @example\n * ```ts\n * // Check if a GIF file is animated\n * const file = event.target.files[0]\n * if (file.type === 'image/gif') {\n * const buffer = await file.arrayBuffer()\n * const animated = isGifAnimated(buffer)\n * console.log(animated ? 'Animated GIF' : 'Static GIF')\n * }\n * ```\n * @public\n */\nexport function isGifAnimated(buffer: ArrayBuffer): boolean {\n\tconst view = new Uint8Array(buffer)\n\tlet hasColorTable, colorTableSize\n\tlet offset = 0\n\tlet imagesCount = 0\n\n\t// Check if this is this image has valid GIF header.\n\t// If not return false. Chrome, FF and IE doesn't handle GIFs with invalid version.\n\tif (!isGIF(buffer)) {\n\t\treturn false\n\t}\n\n\t// Skip header, logical screen descriptor and global color table\n\n\thasColorTable = view[10] & 0x80 // 0b10000000\n\tcolorTableSize = view[10] & 0x07 // 0b00000111\n\n\toffset += 6 // skip header\n\toffset += 7 // skip logical screen descriptor\n\toffset += hasColorTable ? 3 * Math.pow(2, colorTableSize + 1) : 0 // skip global color table\n\n\t// Find if there is more than one image descriptor\n\n\twhile (imagesCount < 2 && offset < view.length) {\n\t\tswitch (view[offset]) {\n\t\t\t// Image descriptor block. According to specification there could be any\n\t\t\t// number of these blocks (even zero). When there is more than one image\n\t\t\t// descriptor browsers will display animation (they shouldn't when there\n\t\t\t// is no delays defined, but they do it anyway).\n\t\t\tcase 0x2c:\n\t\t\t\timagesCount += 1\n\n\t\t\t\thasColorTable = view[offset + 9] & 0x80 // 0b10000000\n\t\t\t\tcolorTableSize = view[offset + 9] & 0x07 // 0b00000111\n\n\t\t\t\toffset += 10 // skip image descriptor\n\t\t\t\toffset += hasColorTable ? 3 * Math.pow(2, colorTableSize + 1) : 0 // skip local color table\n\t\t\t\toffset += getDataBlocksLength(view, offset + 1) + 1 // skip image data\n\n\t\t\t\tbreak\n\n\t\t\t// Skip all extension blocks. In theory this \"plain text extension\" blocks\n\t\t\t// could be frames of animation, but no browser renders them.\n\t\t\tcase 0x21:\n\t\t\t\toffset += 2 // skip introducer and label\n\t\t\t\toffset += getDataBlocksLength(view, offset) // skip this block and following data blocks\n\n\t\t\t\tbreak\n\n\t\t\t// Stop processing on trailer block,\n\t\t\t// all data after this point will is ignored by decoders\n\t\t\tcase 0x3b:\n\t\t\t\toffset = view.length // fast forward to end of buffer\n\t\t\t\tbreak\n\n\t\t\t// Oops! This GIF seems to be invalid\n\t\t\tdefault:\n\t\t\t\t// fast forward to end of buffer\n\t\t\t\toffset = view.length\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\treturn imagesCount > 1\n}\n","/*!\n * MIT License: https://github.com/alexgorbatchev/crc/blob/master/LICENSE\n * Copyright: 2014 Alex Gorbatchev\n * Code: crc32, https://github.com/alexgorbatchev/crc/blob/master/src/calculators/crc32.ts\n */\n\ntype BufferInput = string | ArrayBuffer | Buffer\n\ninterface CRCCalculator<T = BufferInput | Uint8Array> {\n\t(value: T, previous?: number): number\n}\n\nlet TABLE: Array<number> | Int32Array = [\n\t0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,\n\t0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,\n\t0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,\n\t0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,\n\t0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,\n\t0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,\n\t0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,\n\t0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,\n\t0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,\n\t0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,\n\t0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,\n\t0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,\n\t0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,\n\t0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,\n\t0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\n\t0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,\n\t0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,\n\t0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,\n\t0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,\n\t0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,\n\t0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,\n\t0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,\n\t0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,\n\t0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,\n\t0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,\n\t0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,\n\t0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,\n\t0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,\n\t0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,\n\t0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\n\t0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,\n\t0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,\n]\n\nif (typeof Int32Array !== 'undefined') {\n\tTABLE = new Int32Array(TABLE)\n}\n\nconst crc: CRCCalculator<Uint8Array> = (current, previous) => {\n\tlet crc = previous === 0 ? 0 : ~~previous! ^ -1\n\n\tfor (let index = 0; index < current.length; index++) {\n\t\tcrc = TABLE[(crc ^ current[index]) & 0xff] ^ (crc >>> 8)\n\t}\n\n\treturn crc ^ -1\n}\n\nconst LEN_SIZE = 4\nconst CRC_SIZE = 4\n\n/**\n * Utility class for reading and manipulating PNG image files.\n * Provides methods for parsing PNG chunks, validating PNG format, and modifying PNG metadata.\n *\n * @example\n * ```ts\n * // Validate PNG file from blob\n * const blob = new Blob([pngData], { type: 'image/png' })\n * const view = new DataView(await blob.arrayBuffer())\n * const isPng = PngHelpers.isPng(view, 0)\n *\n * // Parse PNG metadata for image processing\n * const chunks = PngHelpers.readChunks(view)\n * const physChunk = PngHelpers.findChunk(view, 'pHYs')\n *\n * // Create high-DPI PNG for export\n * const highDpiBlob = PngHelpers.setPhysChunk(view, 2, { type: 'image/png' })\n * ```\n *\n * @public\n */\nexport class PngHelpers {\n\t/**\n\t * Checks if binary data at the specified offset contains a valid PNG file signature.\n\t * Validates the 8-byte PNG signature: 89 50 4E 47 0D 0A 1A 0A.\n\t *\n\t * @param view - DataView containing the binary data to check\n\t * @param offset - Byte offset where the PNG signature should start\n\t * @returns True if the data contains a valid PNG signature, false otherwise\n\t *\n\t * @example\n\t * ```ts\n\t * // Validate PNG from file upload\n\t * const file = event.target.files[0]\n\t * const buffer = await file.arrayBuffer()\n\t * const view = new DataView(buffer)\n\t *\n\t * if (PngHelpers.isPng(view, 0)) {\n\t * console.log('Valid PNG file detected')\n\t * // Process PNG file...\n\t * } else {\n\t * console.error('Not a valid PNG file')\n\t * }\n\t * ```\n\t */\n\tstatic isPng(view: DataView, offset: number) {\n\t\tif (\n\t\t\tview.getUint8(offset + 0) === 0x89 &&\n\t\t\tview.getUint8(offset + 1) === 0x50 &&\n\t\t\tview.getUint8(offset + 2) === 0x4e &&\n\t\t\tview.getUint8(offset + 3) === 0x47 &&\n\t\t\tview.getUint8(offset + 4) === 0x0d &&\n\t\t\tview.getUint8(offset + 5) === 0x0a &&\n\t\t\tview.getUint8(offset + 6) === 0x1a &&\n\t\t\tview.getUint8(offset + 7) === 0x0a\n\t\t) {\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\t}\n\n\t/**\n\t * Reads the 4-character chunk type identifier from a PNG chunk header.\n\t *\n\t * @param view - DataView containing the PNG data\n\t * @param offset - Byte offset of the chunk type field (after length field)\n\t * @returns 4-character string representing the chunk type (e.g., 'IHDR', 'IDAT', 'IEND')\n\t *\n\t * @example\n\t * ```ts\n\t * // Read chunk type from PNG header (after 8-byte signature)\n\t * const chunkType = PngHelpers.getChunkType(dataView, 8)\n\t * console.log(chunkType) // 'IHDR' (Image Header)\n\t *\n\t * // Read chunk type at a specific position during parsing\n\t * let offset = 8 // Skip PNG signature\n\t * const chunkLength = dataView.getUint32(offset)\n\t * const type = PngHelpers.getChunkType(dataView, offset + 4)\n\t * ```\n\t */\n\tstatic getChunkType(view: DataView, offset: number) {\n\t\treturn [\n\t\t\tString.fromCharCode(view.getUint8(offset)),\n\t\t\tString.fromCharCode(view.getUint8(offset + 1)),\n\t\t\tString.fromCharCode(view.getUint8(offset + 2)),\n\t\t\tString.fromCharCode(view.getUint8(offset + 3)),\n\t\t].join('')\n\t}\n\n\t/**\n\t * Parses all chunks in a PNG file and returns their metadata.\n\t * Skips duplicate IDAT chunks but includes all other chunk types.\n\t *\n\t * @param view - DataView containing the complete PNG file data\n\t * @param offset - Starting byte offset (defaults to 0)\n\t * @returns Record mapping chunk types to their metadata (start position, data offset, and size)\n\t * @throws Error if the data is not a valid PNG file\n\t *\n\t * @example\n\t * ```ts\n\t * // Parse PNG structure for metadata extraction\n\t * const view = new DataView(await blob.arrayBuffer())\n\t * const chunks = PngHelpers.readChunks(view)\n\t *\n\t * // Check for specific chunks\n\t * const ihdrChunk = chunks['IHDR']\n\t * const physChunk = chunks['pHYs']\n\t *\n\t * if (physChunk) {\n\t * console.log(`Found pixel density info at byte ${physChunk.start}`)\n\t * } else {\n\t * console.log('No pixel density information found')\n\t * }\n\t * ```\n\t */\n\tstatic readChunks(view: DataView, offset = 0) {\n\t\tconst chunks: Record<string, { dataOffset: number; size: number; start: number }> = {}\n\t\tif (!PngHelpers.isPng(view, offset)) {\n\t\t\tthrow new Error('Not a PNG')\n\t\t}\n\t\toffset += 8\n\n\t\twhile (offset <= view.buffer.byteLength) {\n\t\t\tconst start = offset\n\t\t\tconst len = view.getInt32(offset)\n\t\t\toffset += 4\n\t\t\tconst chunkType = PngHelpers.getChunkType(view, offset)\n\n\t\t\tif (chunkType === 'IDAT' && chunks[chunkType]) {\n\t\t\t\toffset += len + LEN_SIZE + CRC_SIZE\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (chunkType === 'IEND') {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tchunks[chunkType] = {\n\t\t\t\tstart,\n\t\t\t\tdataOffset: offset + 4,\n\t\t\t\tsize: len,\n\t\t\t}\n\t\t\toffset += len + LEN_SIZE + CRC_SIZE\n\t\t}\n\n\t\treturn chunks\n\t}\n\n\t/**\n\t * Parses the pHYs (physical pixel dimensions) chunk data.\n\t * Reads pixels per unit for X and Y axes, and the unit specifier.\n\t *\n\t * @param view - DataView containing the PNG data\n\t * @param offset - Byte offset of the pHYs chunk data\n\t * @returns Object with ppux (pixels per unit X), ppuy (pixels per unit Y), and unit specifier\n\t *\n\t * @example\n\t * ```ts\n\t * // Extract pixel density information for DPI calculation\n\t * const physChunk = PngHelpers.findChunk(dataView, 'pHYs')\n\t * if (physChunk) {\n\t * const physData = PngHelpers.parsePhys(dataView, physChunk.dataOffset)\n\t *\n\t * if (physData.unit === 1) { // meters\n\t * const dpiX = Math.round(physData.ppux * 0.0254)\n\t * const dpiY = Math.round(physData.ppuy * 0.0254)\n\t * console.log(`DPI: ${dpiX} x ${dpiY}`)\n\t * }\n\t * }\n\t * ```\n\t */\n\tstatic parsePhys(view: DataView, offset: number) {\n\t\treturn {\n\t\t\tppux: view.getUint32(offset),\n\t\t\tppuy: view.getUint32(offset + 4),\n\t\t\tunit: view.getUint8(offset + 8),\n\t\t}\n\t}\n\n\t/**\n\t * Finds a specific chunk type in the PNG file and returns its metadata.\n\t *\n\t * @param view - DataView containing the PNG file data\n\t * @param type - 4-character chunk type to search for (e.g., 'pHYs', 'IDAT')\n\t * @returns Chunk metadata object if found, undefined otherwise\n\t *\n\t * @example\n\t * ```ts\n\t * // Look for pixel density information in PNG\n\t * const physChunk = PngHelpers.findChunk(dataView, 'pHYs')\n\t * if (physChunk) {\n\t * const physData = PngHelpers.parsePhys(dataView, physChunk.dataOffset)\n\t * console.log(`Found pHYs chunk with ${physData.ppux} x ${physData.ppuy} pixels per unit`)\n\t * }\n\t *\n\t * // Check for text metadata\n\t * const textChunk = PngHelpers.findChunk(dataView, 'tEXt')\n\t * if (textChunk) {\n\t * console.log(`Found text metadata at byte ${textChunk.start}`)\n\t * }\n\t * ```\n\t */\n\tstatic findChunk(view: DataView, type: string) {\n\t\tconst chunks = PngHelpers.readChunks(view)\n\t\treturn chunks[type]\n\t}\n\n\t/**\n\t * Adds or replaces a pHYs chunk in a PNG file to set pixel density for high-DPI displays.\n\t * The method determines insertion point by prioritizing IDAT chunk position over existing pHYs,\n\t * creates a properly formatted pHYs chunk with CRC validation, and returns a new Blob.\n\t *\n\t * @param view - DataView containing the original PNG file data\n\t * @param dpr - Device pixel ratio multiplier (defaults to 1)\n\t * @param options - Optional Blob constructor options for MIME type and other properties\n\t * @returns New Blob containing the PNG with updated pixel density information\n\t *\n\t * @example\n\t * ```ts\n\t * // Export PNG with proper pixel density for high-DPI displays\n\t * const canvas = document.createElement('canvas')\n\t * const ctx = canvas.getContext('2d')\n\t * // ... draw content to canvas ...\n\t *\n\t * canvas.toBlob(async (blob) => {\n\t * if (blob) {\n\t * const view = new DataView(await blob.arrayBuffer())\n\t * // Create 2x DPI version for Retina displays\n\t * const highDpiBlob = PngHelpers.setPhysChunk(view, 2, { type: 'image/png' })\n\t * // Download or use the blob...\n\t * }\n\t * }, 'image/png')\n\t * ```\n\t */\n\tstatic setPhysChunk(view: DataView, dpr = 1, options?: BlobPropertyBag) {\n\t\tlet offset = 46\n\t\tlet size = 0\n\t\tconst res1 = PngHelpers.findChunk(view, 'pHYs')\n\t\tif (res1) {\n\t\t\toffset = res1.start\n\t\t\tsize = res1.size\n\t\t}\n\n\t\tconst res2 = PngHelpers.findChunk(view, 'IDAT')\n\t\tif (res2) {\n\t\t\toffset = res2.start\n\t\t\tsize = 0\n\t\t}\n\n\t\tconst pHYsData = new ArrayBuffer(21)\n\t\tconst pHYsDataView = new DataView(pHYsData)\n\n\t\tpHYsDataView.setUint32(0, 9)\n\n\t\tpHYsDataView.setUint8(4, 'p'.charCodeAt(0))\n\t\tpHYsDataView.setUint8(5, 'H'.charCodeAt(0))\n\t\tpHYsDataView.setUint8(6, 'Y'.charCodeAt(0))\n\t\tpHYsDataView.setUint8(7, 's'.charCodeAt(0))\n\n\t\tconst DPI_72 = 2835.5\n\n\t\tpHYsDataView.setInt32(8, DPI_72 * dpr)\n\t\tpHYsDataView.setInt32(12, DPI_72 * dpr)\n\t\tpHYsDataView.setInt8(16, 1)\n\n\t\tconst crcBit = new Uint8Array(pHYsData.slice(4, 17))\n\t\tpHYsDataView.setInt32(17, crc(crcBit))\n\n\t\tconst startBuf = view.buffer.slice(0, offset)\n\t\tconst endBuf = view.buffer.slice(offset + size)\n\n\t\treturn new Blob([startBuf as ArrayBuffer, pHYsData, endBuf as ArrayBuffer], options)\n\t}\n}\n","/*!\n * MIT License: https://github.com/sindresorhus/is-webp/blob/main/license\n * Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n */\n\n/**\n * Determines whether a byte array represents a WebP image by checking the WebP file signature.\n *\n * @param view - The Uint8Array containing the potential WebP image data\n * @returns True if the byte array is a valid WebP image, false otherwise\n * @example\n * ```ts\n * // Check if file data is WebP format\n * const file = new File([...], 'image.webp', { type: 'image/webp' })\n * const buffer = await file.arrayBuffer()\n * const view = new Uint8Array(buffer)\n * const isWebPImage = isWebp(view)\n * console.log(isWebPImage ? 'Valid WebP' : 'Not WebP')\n * ```\n * @internal\n */\nexport function isWebp(view: Uint8Array) {\n\tif (!view || view.length < 12) {\n\t\treturn false\n\t}\n\n\treturn view[8] === 87 && view[9] === 69 && view[10] === 66 && view[11] === 80\n}\n\n/**\n * Determines whether a WebP image file contains animation data by checking the animation flag in the WebP VP8X chunk.\n *\n * @param buffer - The ArrayBuffer containing the WebP image data\n * @returns True if the WebP image is animated, false otherwise\n * @example\n * ```ts\n * // Check if a WebP file from user input is animated\n * const file = new File([...], 'image.webp', { type: 'image/webp' })\n * const buffer = await file.arrayBuffer()\n * const animated = isWebpAnimated(buffer)\n * console.log(animated ? 'Animated WebP' : 'Static WebP')\n * ```\n * @public\n */\nexport function isWebpAnimated(buffer: ArrayBuffer) {\n\tconst view = new Uint8Array(buffer)\n\n\tif (!isWebp(view)) {\n\t\treturn false\n\t}\n\n\tif (!view || view.length < 21) {\n\t\treturn false\n\t}\n\n\treturn ((view[20] >> 1) & 1) === 1\n}\n","import { promiseWithResolve } from '../control'\nimport { Image } from '../network'\nimport { isApngAnimated } from './apng'\nimport { isAvifAnimated } from './avif'\nimport { isGifAnimated } from './gif'\nimport { PngHelpers } from './png'\nimport { isWebpAnimated } from './webp'\n\n/**\n * Array of supported vector image MIME types.\n *\n * @example\n * ```ts\n * import { DEFAULT_SUPPORTED_VECTOR_IMAGE_TYPES } from '@ibodr/utils'\n *\n * const isSvg = DEFAULT_SUPPORTED_VECTOR_IMAGE_TYPES.includes('image/svg+xml')\n * console.log(isSvg) // true\n * ```\n * @public\n */\nexport const DEFAULT_SUPPORTED_VECTOR_IMAGE_TYPES = Object.freeze(['image/svg+xml' as const])\n/**\n * Array of supported static (non-animated) image MIME types.\n *\n * @example\n * ```ts\n * import { DEFAULT_SUPPORTED_STATIC_IMAGE_TYPES } from '@ibodr/utils'\n *\n * const isStatic = DEFAULT_SUPPORTED_STATIC_IMAGE_TYPES.includes('image/jpeg')\n * console.log(isStatic) // true\n * ```\n * @public\n */\nexport const DEFAULT_SUPPORTED_STATIC_IMAGE_TYPES = Object.freeze([\n\t'image/jpeg' as const,\n\t'image/png' as const,\n\t'image/webp' as const,\n])\n/**\n * Array of supported animated image MIME types.\n *\n * @example\n * ```ts\n * import { DEFAULT_SUPPORTED_ANIMATED_IMAGE_TYPES } from '@ibodr/utils'\n *\n * const isAnimated = DEFAULT_SUPPORTED_ANIMATED_IMAGE_TYPES.includes('image/gif')\n * console.log(isAnimated) // true\n * ```\n * @public\n */\nexport const DEFAULT_SUPPORTED_ANIMATED_IMAGE_TYPES = Object.freeze([\n\t'image/gif' as const,\n\t'image/apng' as const,\n\t'image/avif' as const,\n])\n/**\n * Array of all supported image MIME types, combining static, vector, and animated types.\n *\n * @example\n * ```ts\n * import { DEFAULT_SUPPORTED_IMAGE_TYPES } from '@ibodr/utils'\n *\n * const isSupported = DEFAULT_SUPPORTED_IMAGE_TYPES.includes('image/png')\n * console.log(isSupported) // true\n * ```\n * @public\n */\nexport const DEFAULT_SUPPORTED_IMAGE_TYPES = Object.freeze([\n\t...DEFAULT_SUPPORTED_STATIC_IMAGE_TYPES,\n\t...DEFAULT_SUPPORTED_VECTOR_IMAGE_TYPES,\n\t...DEFAULT_SUPPORTED_ANIMATED_IMAGE_TYPES,\n])\n/**\n * Array of supported video MIME types.\n *\n * @example\n * ```ts\n * import { DEFAULT_SUPPORT_VIDEO_TYPES } from '@ibodr/utils'\n *\n * const isVideo = DEFAULT_SUPPORT_VIDEO_TYPES.includes('video/mp4')\n * console.log(isVideo) // true\n * ```\n * @public\n */\nexport const DEFAULT_SUPPORT_VIDEO_TYPES = Object.freeze([\n\t'video/mp4' as const,\n\t'video/webm' as const,\n\t'video/quicktime' as const,\n])\n/**\n * Array of all supported media MIME types, combining images and videos.\n *\n * @example\n * ```ts\n * import { DEFAULT_SUPPORTED_MEDIA_TYPES } from '@ibodr/utils'\n *\n * const isMediaFile = DEFAULT_SUPPORTED_MEDIA_TYPES.includes('video/mp4')\n * console.log(isMediaFile) // true\n * ```\n * @public\n */\nexport const DEFAULT_SUPPORTED_MEDIA_TYPES = Object.freeze([\n\t...DEFAULT_SUPPORTED_IMAGE_TYPES,\n\t...DEFAULT_SUPPORT_VIDEO_TYPES,\n])\n/**\n * Comma-separated string of all supported media MIME types, useful for HTML file input accept attributes.\n *\n * @example\n * ```ts\n * import { DEFAULT_SUPPORTED_MEDIA_TYPE_LIST } from '@ibodr/utils'\n *\n * // Use in HTML file input for media uploads\n * const input = document.createElement('input')\n * input.type = 'file'\n * input.accept = DEFAULT_SUPPORTED_MEDIA_TYPE_LIST\n * input.addEventListener('change', (e) => {\n * const files = (e.target as HTMLInputElement).files\n * if (files) console.log(`Selected ${files.length} file(s)`)\n * })\n * ```\n * @public\n */\nexport const DEFAULT_SUPPORTED_MEDIA_TYPE_LIST = DEFAULT_SUPPORTED_MEDIA_TYPES.join(',')\n\n/**\n * Helpers for media\n *\n * @public\n */\nexport class MediaHelpers {\n\t/**\n\t * Load a video element from a URL with cross-origin support.\n\t *\n\t * @param src - The URL of the video to load\n\t * @param doc - Optional document to create the video element in\n\t * @returns Promise that resolves to the loaded HTMLVideoElement\n\t * @example\n\t * ```ts\n\t * const video = await MediaHelpers.loadVideo('https://example.com/video.mp4')\n\t * console.log(`Video dimensions: ${video.videoWidth}x${video.videoHeight}`)\n\t * ```\n\t * @public\n\t */\n\tstatic loadVideo(src: string, doc?: Document): Promise<HTMLVideoElement> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\tconst video = (doc ?? document).createElement('video')\n\t\t\tvideo.onloadeddata = () => resolve(video)\n\t\t\tvideo.onerror = (e) => {\n\t\t\t\tconsole.error(e)\n\t\t\t\treject(new Error('Could not load video'))\n\t\t\t}\n\t\t\tvideo.crossOrigin = 'anonymous'\n\t\t\tvideo.src = src\n\t\t})\n\t}\n\n\t/**\n\t * Extract a frame from a video element as a data URL.\n\t *\n\t * @param video - The HTMLVideoElement to extract frame from\n\t * @param time - The time in seconds to extract the frame from (default: 0)\n\t * @returns Promise that resolves to a data URL of the video frame\n\t * @example\n\t * ```ts\n\t * const video = await MediaHelpers.loadVideo('https://example.com/video.mp4')\n\t * const frameDataUrl = await MediaHelpers.getVideoFrameAsDataUrl(video, 5.0)\n\t * // Use frameDataUrl as image thumbnail\n\t * const img = document.createElement('img')\n\t * img.src = frameDataUrl\n\t * ```\n\t * @public\n\t */\n\tstatic async getVideoFrameAsDataUrl(video: HTMLVideoElement, time = 0): Promise<string> {\n\t\tconst promise = promiseWithResolve<string>()\n\t\tlet didSetTime = false\n\n\t\tconst onReadyStateChanged = () => {\n\t\t\tif (!didSetTime) {\n\t\t\t\tif (video.readyState >= video.HAVE_METADATA) {\n\t\t\t\t\tdidSetTime = true\n\t\t\t\t\tvideo.currentTime = time\n\t\t\t\t} else {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (video.readyState >= video.HAVE_CURRENT_DATA) {\n\t\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\t\tconst canvas = (video.ownerDocument ?? document).createElement('canvas')\n\t\t\t\tcanvas.width = video.videoWidth\n\t\t\t\tcanvas.height = video.videoHeight\n\t\t\t\tconst ctx = canvas.getContext('2d')\n\t\t\t\tif (!ctx) {\n\t\t\t\t\tthrow new Error('Could not get 2d context')\n\t\t\t\t}\n\t\t\t\tctx.drawImage(video, 0, 0)\n\t\t\t\tpromise.resolve(canvas.toDataURL())\n\t\t\t}\n\t\t}\n\t\tconst onError = (e: Event) => {\n\t\t\tconsole.error(e)\n\t\t\tpromise.reject(new Error('Could not get video frame'))\n\t\t}\n\n\t\tvideo.addEventListener('loadedmetadata', onReadyStateChanged)\n\t\tvideo.addEventListener('loadeddata', onReadyStateChanged)\n\t\tvideo.addEventListener('canplay', onReadyStateChanged)\n\t\tvideo.addEventListener('seeked', onReadyStateChanged)\n\n\t\tvideo.addEventListener('error', onError)\n\t\tvideo.addEventListener('stalled', onError)\n\n\t\tonReadyStateChanged()\n\n\t\ttry {\n\t\t\treturn await promise\n\t\t} finally {\n\t\t\tvideo.removeEventListener('loadedmetadata', onReadyStateChanged)\n\t\t\tvideo.removeEventListener('loadeddata', onReadyStateChanged)\n\t\t\tvideo.removeEventListener('canplay', onReadyStateChanged)\n\t\t\tvideo.removeEventListener('seeked', onReadyStateChanged)\n\n\t\t\tvideo.removeEventListener('error', onError)\n\t\t\tvideo.removeEventListener('stalled', onError)\n\t\t}\n\t}\n\n\t/**\n\t * Load an image from a URL and get its dimensions along with the image element.\n\t *\n\t * @param src - The URL of the image to load\n\t * @param doc - Optional document to use for DOM operations (e.g. measuring SVG dimensions)\n\t * @returns Promise that resolves to an object with width, height, and the image element\n\t * @example\n\t * ```ts\n\t * const { w, h, image } = await MediaHelpers.getImageAndDimensions('https://example.com/image.png')\n\t * console.log(`Image size: ${w}x${h}`)\n\t * // Image is ready to use\n\t * document.body.appendChild(image)\n\t * ```\n\t * @public\n\t */\n\tstatic getImageAndDimensions(\n\t\tsrc: string,\n\t\tdoc?: Document\n\t): Promise<{ w: number; h: number; image: HTMLImageElement }> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst img = Image()\n\t\t\timg.onload = () => {\n\t\t\t\tlet dimensions\n\t\t\t\tif (img.naturalWidth) {\n\t\t\t\t\tdimensions = {\n\t\t\t\t\t\tw: img.naturalWidth,\n\t\t\t\t\t\th: img.naturalHeight,\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Sigh, Firefox doesn't have naturalWidth or naturalHeight for SVGs. :-/\n\t\t\t\t\t// We have to attach to dom and use clientWidth/clientHeight.\n\t\t\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\t\t\tconst body = (doc ?? document).body\n\t\t\t\t\tbody.appendChild(img)\n\t\t\t\t\tdimensions = {\n\t\t\t\t\t\tw: img.clientWidth,\n\t\t\t\t\t\th: img.clientHeight,\n\t\t\t\t\t}\n\t\t\t\t\tbody.removeChild(img)\n\t\t\t\t}\n\t\t\t\tresolve({ ...dimensions, image: img })\n\t\t\t}\n\t\t\timg.onerror = (e) => {\n\t\t\t\tconsole.error(e)\n\t\t\t\treject(new Error('Could not load image'))\n\t\t\t}\n\t\t\timg.crossOrigin = 'anonymous'\n\t\t\timg.referrerPolicy = 'strict-origin-when-cross-origin'\n\t\t\timg.style.visibility = 'hidden'\n\t\t\timg.style.position = 'absolute'\n\t\t\timg.style.opacity = '0'\n\t\t\timg.style.zIndex = '-9999'\n\t\t\timg.src = src\n\t\t})\n\t}\n\n\t/**\n\t * Get the size of a video blob\n\t *\n\t * @param blob - A Blob containing the video\n\t * @param doc - Optional document to create elements in\n\t * @returns Promise that resolves to an object with width and height properties\n\t * @example\n\t * ```ts\n\t * const file = new File([...], 'video.mp4', { type: 'video/mp4' })\n\t * const { w, h } = await MediaHelpers.getVideoSize(file)\n\t * console.log(`Video dimensions: ${w}x${h}`)\n\t * ```\n\t * @public\n\t */\n\tstatic async getVideoSize(blob: Blob, doc?: Document): Promise<{ w: number; h: number }> {\n\t\treturn MediaHelpers.usingObjectURL(blob, async (url) => {\n\t\t\tconst video = await MediaHelpers.loadVideo(url, doc)\n\t\t\treturn { w: video.videoWidth, h: video.videoHeight }\n\t\t})\n\t}\n\n\t/**\n\t * Get the size of an image blob\n\t *\n\t * @param blob - A Blob containing the image\n\t * @param doc - Optional document to use for DOM operations\n\t * @returns Promise that resolves to an object with width and height properties\n\t * @example\n\t * ```ts\n\t * const file = new File([...], 'image.png', { type: 'image/png' })\n\t * const { w, h } = await MediaHelpers.getImageSize(file)\n\t * console.log(`Image dimensions: ${w}x${h}`)\n\t * ```\n\t * @public\n\t */\n\tstatic async getImageSize(\n\t\tblob: Blob,\n\t\tdoc?: Document\n\t): Promise<{ w: number; h: number; pixelRatio: number }> {\n\t\tconst { w, h } = await MediaHelpers.usingObjectURL(blob, (url) =>\n\t\t\tMediaHelpers.getImageAndDimensions(url, doc)\n\t\t)\n\n\t\ttry {\n\t\t\tif (blob.type === 'image/png') {\n\t\t\t\tconst view = new DataView(await blob.arrayBuffer())\n\t\t\t\tif (PngHelpers.isPng(view, 0)) {\n\t\t\t\t\tconst physChunk = PngHelpers.findChunk(view, 'pHYs')\n\t\t\t\t\tif (physChunk) {\n\t\t\t\t\t\tconst physData = PngHelpers.parsePhys(view, physChunk.dataOffset)\n\t\t\t\t\t\tif (physData.unit === 1 && physData.ppux === physData.ppuy) {\n\t\t\t\t\t\t\tconst dpi = Math.round(physData.ppux * 0.0254)\n\t\t\t\t\t\t\t// Try both standard baselines: Windows/web = 96, macOS = 72.\n\t\t\t\t\t\t\t// Pick whichever yields a clean integer ratio > 1.\n\t\t\t\t\t\t\tconst r96 = dpi / 96\n\t\t\t\t\t\t\tconst r72 = dpi / 72\n\t\t\t\t\t\t\tlet pixelRatio = 1\n\t\t\t\t\t\t\tif (Number.isInteger(r96) && r96 > 1) {\n\t\t\t\t\t\t\t\tpixelRatio = r96\n\t\t\t\t\t\t\t} else if (Number.isInteger(r72) && r72 > 1) {\n\t\t\t\t\t\t\t\tpixelRatio = r72\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (pixelRatio > 1) {\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tw: Math.ceil(w / pixelRatio),\n\t\t\t\t\t\t\t\t\th: Math.ceil(h / pixelRatio),\n\t\t\t\t\t\t\t\t\tpixelRatio,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconsole.error(err)\n\t\t\treturn { w, h, pixelRatio: 1 }\n\t\t}\n\t\treturn { w, h, pixelRatio: 1 }\n\t}\n\n\t/**\n\t * Check if a media file blob contains animation data.\n\t *\n\t * @param file - The Blob to check for animation\n\t * @returns Promise that resolves to true if the file is animated, false otherwise\n\t * @example\n\t * ```ts\n\t * const file = new File([...], 'animation.gif', { type: 'image/gif' })\n\t * const animated = await MediaHelpers.isAnimated(file)\n\t * console.log(animated ? 'Animated' : 'Static')\n\t * ```\n\t * @public\n\t */\n\tstatic async isAnimated(file: Blob): Promise<boolean> {\n\t\tif (file.type === 'image/gif') {\n\t\t\treturn isGifAnimated(await file.arrayBuffer())\n\t\t}\n\n\t\tif (file.type === 'image/avif') {\n\t\t\treturn isAvifAnimated(await file.arrayBuffer())\n\t\t}\n\n\t\tif (file.type === 'image/webp') {\n\t\t\treturn isWebpAnimated(await file.arrayBuffer())\n\t\t}\n\n\t\tif (file.type === 'image/apng') {\n\t\t\treturn isApngAnimated(await file.arrayBuffer())\n\t\t}\n\n\t\treturn false\n\t}\n\n\t/**\n\t * Check if a MIME type represents an animated image format.\n\t *\n\t * @param mimeType - The MIME type to check\n\t * @returns True if the MIME type is an animated image format, false otherwise\n\t * @example\n\t * ```ts\n\t * const isAnimated = MediaHelpers.isAnimatedImageType('image/gif')\n\t * console.log(isAnimated) // true\n\t * ```\n\t * @public\n\t */\n\tstatic isAnimatedImageType(mimeType: string | null): boolean {\n\t\treturn DEFAULT_SUPPORTED_ANIMATED_IMAGE_TYPES.includes((mimeType as any) || '')\n\t}\n\n\t/**\n\t * Check if a MIME type represents a static (non-animated) image format.\n\t *\n\t * @param mimeType - The MIME type to check\n\t * @returns True if the MIME type is a static image format, false otherwise\n\t * @example\n\t * ```ts\n\t * const isStatic = MediaHelpers.isStaticImageType('image/jpeg')\n\t * console.log(isStatic) // true\n\t * ```\n\t * @public\n\t */\n\tstatic isStaticImageType(mimeType: string | null): boolean {\n\t\treturn DEFAULT_SUPPORTED_STATIC_IMAGE_TYPES.includes((mimeType as any) || '')\n\t}\n\n\t/**\n\t * Check if a MIME type represents a vector image format.\n\t *\n\t * @param mimeType - The MIME type to check\n\t * @returns True if the MIME type is a vector image format, false otherwise\n\t * @example\n\t * ```ts\n\t * const isVector = MediaHelpers.isVectorImageType('image/svg+xml')\n\t * console.log(isVector) // true\n\t * ```\n\t * @public\n\t */\n\tstatic isVectorImageType(mimeType: string | null): boolean {\n\t\treturn DEFAULT_SUPPORTED_VECTOR_IMAGE_TYPES.includes((mimeType as any) || '')\n\t}\n\n\t/**\n\t * Check if a MIME type represents any supported image format (static, animated, or vector).\n\t *\n\t * @param mimeType - The MIME type to check\n\t * @returns True if the MIME type is a supported image format, false otherwise\n\t * @example\n\t * ```ts\n\t * const isImage = MediaHelpers.isImageType('image/png')\n\t * console.log(isImage) // true\n\t * ```\n\t * @public\n\t */\n\tstatic isImageType(mimeType: string): boolean {\n\t\treturn DEFAULT_SUPPORTED_IMAGE_TYPES.includes((mimeType as any) || '')\n\t}\n\n\t/**\n\t * Utility function to create an object URL from a blob, execute a function with it, and automatically clean it up.\n\t *\n\t * @param blob - The Blob to create an object URL for\n\t * @param fn - Function to execute with the object URL\n\t * @returns Promise that resolves to the result of the function\n\t * @example\n\t * ```ts\n\t * const result = await MediaHelpers.usingObjectURL(imageBlob, async (url) => {\n\t * const { w, h } = await MediaHelpers.getImageAndDimensions(url)\n\t * return { width: w, height: h }\n\t * })\n\t * // Object URL is automatically revoked after function completes\n\t * console.log(`Image dimensions: ${result.width}x${result.height}`)\n\t * ```\n\t * @public\n\t */\n\tstatic async usingObjectURL<T>(blob: Blob, fn: (url: string) => Promise<T>): Promise<T> {\n\t\tconst url = URL.createObjectURL(blob)\n\t\ttry {\n\t\t\treturn await fn(url)\n\t\t} finally {\n\t\t\tURL.revokeObjectURL(url)\n\t\t}\n\t}\n}\n","/**\n * Linear interpolate between two values.\n *\n * @param a - The start value\n * @param b - The end value\n * @param t - The interpolation factor (0-1)\n * @returns The interpolated value\n * @example\n * ```ts\n * const halfway = lerp(0, 100, 0.5) // 50\n * const quarter = lerp(10, 20, 0.25) // 12.5\n * ```\n * @public\n */\nexport function lerp(a: number, b: number, t: number) {\n\treturn a + (b - a) * t\n}\n\n/**\n * Inverse lerp between two values. Given a value `t` in the range [a, b], returns a number between\n * 0 and 1.\n *\n * @param a - The start value of the range\n * @param b - The end value of the range\n * @param t - The value within the range [a, b]\n * @returns The normalized position (0-1) of t within the range [a, b]\n * @example\n * ```ts\n * const position = invLerp(0, 100, 25) // 0.25\n * const normalized = invLerp(10, 20, 15) // 0.5\n * ```\n * @public\n */\nexport function invLerp(a: number, b: number, t: number) {\n\treturn (t - a) / (b - a)\n}\n\n/**\n * Seeded random number generator, using [xorshift](https://en.wikipedia.org/wiki/Xorshift). The\n * result will always be between -1 and 1.\n *\n * Adapted from [seedrandom](https://github.com/davidbau/seedrandom).\n *\n * @param seed - The seed string for deterministic random generation (defaults to empty string)\n * @returns A function that will return a random number between -1 and 1 each time it is called\n * @example\n * ```ts\n * const random = rng('my-seed')\n * const num1 = random() // Always the same for this seed\n * const num2 = random() // Next number in sequence\n *\n * // Different seed produces different sequence\n * const otherRandom = rng('other-seed')\n * const different = otherRandom() // Different value\n * ```\n * @public\n */\nexport function rng(seed = '') {\n\tlet x = 0\n\tlet y = 0\n\tlet z = 0\n\tlet w = 0\n\n\tfunction next() {\n\t\tconst t = x ^ (x << 11)\n\t\tx = y\n\t\ty = z\n\t\tz = w\n\t\tw ^= ((w >>> 19) ^ t ^ (t >>> 8)) >>> 0\n\t\treturn (w / 0x100000000) * 2\n\t}\n\n\tfor (let k = 0; k < seed.length + 64; k++) {\n\t\tx ^= seed.charCodeAt(k) | 0\n\t\tnext()\n\t}\n\n\treturn next\n}\n\n/**\n * Modulate a value between two ranges.\n *\n * @example\n *\n * ```ts\n * const A = modulate(0, [0, 1], [0, 100]) // 0\n * const B = modulate(0.5, [0, 1], [0, 100]) // 50\n * const C = modulate(1, [0, 1], [0, 100]) // 100\n * ```\n *\n * @param value - The interpolation value.\n * @param rangeA - From [low, high]\n * @param rangeB - To [low, high]\n * @param clamp - Whether to clamp the the result to [low, high]\n * @public\n */\nexport function modulate(value: number, rangeA: number[], rangeB: number[], clamp = false): number {\n\tconst [fromLow, fromHigh] = rangeA\n\tconst [v0, v1] = rangeB\n\tconst result = v0 + ((value - fromLow) / (fromHigh - fromLow)) * (v1 - v0)\n\n\treturn clamp\n\t\t? v0 < v1\n\t\t\t? Math.max(Math.min(result, v1), v0)\n\t\t\t: Math.max(Math.min(result, v0), v1)\n\t\t: result\n}\n","import isEqualWith from 'lodash.isequalwith'\n\n/**\n * Safely checks if an object has a specific property as its own property (not inherited).\n * Uses Object.prototype.hasOwnProperty.call to avoid issues with objects that have null prototype\n * or have overridden the hasOwnProperty method.\n *\n * @param obj - The object to check\n * @param key - The property key to check for\n * @returns True if the object has the property as its own property, false otherwise\n * @example\n * ```ts\n * const obj = { name: 'Alice', age: 30 }\n * hasOwnProperty(obj, 'name') // true\n * hasOwnProperty(obj, 'toString') // false (inherited)\n * hasOwnProperty(obj, 'unknown') // false\n * ```\n * @internal\n */\nexport function hasOwnProperty(obj: object, key: string): boolean {\n\treturn Object.prototype.hasOwnProperty.call(obj, key)\n}\n\n/**\n * Safely gets an object's own property value (not inherited). Returns undefined if the property\n * doesn't exist as an own property. Provides type-safe access with proper TypeScript inference.\n *\n * @param obj - The object to get the property from\n * @param key - The property key to retrieve\n * @returns The property value if it exists as an own property, undefined otherwise\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const name = getOwnProperty(user, 'name') // 'Alice'\n * const missing = getOwnProperty(user, 'unknown') // undefined\n * const inherited = getOwnProperty(user, 'toString') // undefined (inherited)\n * ```\n * @internal\n */\nexport function getOwnProperty<K extends string, V>(\n\tobj: Partial<Record<K, V>>,\n\tkey: K\n): V | undefined\n/** @internal */\nexport function getOwnProperty<O extends object>(obj: O, key: string): O[keyof O] | undefined\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown {\n\tif (!hasOwnProperty(obj, key)) {\n\t\treturn undefined\n\t}\n\t// @ts-expect-error we know the property exists\n\treturn obj[key]\n}\n\n/**\n * An alias for `Object.keys` that treats the object as a map and so preserves the type of the keys.\n * Unlike standard Object.keys which returns string[], this maintains the specific string literal types.\n *\n * @param object - The object to get keys from\n * @returns Array of keys with preserved string literal types\n * @example\n * ```ts\n * const config = { theme: 'dark', lang: 'en' } as const\n * const keys = objectMapKeys(config)\n * // keys is Array<'theme' | 'lang'> instead of string[]\n * ```\n * @internal\n */\nexport function objectMapKeys<Key extends string>(object: {\n\treadonly [K in Key]: unknown\n}): Array<Key> {\n\treturn Object.keys(object) as Key[]\n}\n\n/**\n * An alias for `Object.values` that treats the object as a map and so preserves the type of the\n * values. Unlike standard Object.values which returns unknown[], this maintains the specific value types.\n *\n * @param object - The object to get values from\n * @returns Array of values with preserved types\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const values = objectMapValues(scores)\n * // values is Array<number> instead of unknown[]\n * ```\n * @internal\n */\nexport function objectMapValues<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): Array<Value> {\n\treturn Object.values(object) as Value[]\n}\n\n/**\n * An alias for `Object.entries` that treats the object as a map and so preserves the type of the\n * keys and values. Unlike standard Object.entries which returns `Array<[string, unknown]>`, this maintains specific types.\n *\n * @param object - The object to get entries from\n * @returns Array of key-value pairs with preserved types\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const entries = objectMapEntries(user)\n * // entries is Array<['name' | 'age', string | number]>\n * ```\n * @internal\n */\nexport function objectMapEntries<Obj extends object>(\n\tobject: Obj\n): Array<[keyof Obj, Obj[keyof Obj]]> {\n\treturn Object.entries(object) as [keyof Obj, Obj[keyof Obj]][]\n}\n\n/**\n * Returns the entries of an object as an iterable iterator.\n * Useful when working with large collections, to avoid allocating an array.\n * Only yields own properties (not inherited ones).\n *\n * @param object - The object to iterate over\n * @returns Iterator yielding key-value pairs with preserved types\n * @example\n * ```ts\n * const largeMap = { a: 1, b: 2, c: 3 } // Imagine thousands of entries\n * for (const [key, value] of objectMapEntriesIterable(largeMap)) {\n * // Process entries one at a time without creating a large array\n * console.log(key, value)\n * }\n * ```\n * @internal\n */\nexport function* objectMapEntriesIterable<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): IterableIterator<[Key, Value]> {\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tyield [key, object[key]]\n\t}\n}\n\n/**\n * An alias for `Object.fromEntries` that treats the object as a map and so preserves the type of the\n * keys and values. Creates an object from key-value pairs with proper TypeScript typing.\n *\n * @param entries - Array of key-value pairs to convert to an object\n * @returns Object with preserved key and value types\n * @example\n * ```ts\n * const pairs: Array<['name' | 'age', string | number]> = [['name', 'Alice'], ['age', 30]]\n * const obj = objectMapFromEntries(pairs)\n * // obj is { name: string | number, age: string | number }\n * ```\n * @internal\n */\nexport function objectMapFromEntries<Key extends string, Value>(\n\tentries: ReadonlyArray<readonly [Key, Value]>\n): { [K in Key]: Value } {\n\treturn Object.fromEntries(entries) as { [K in Key]: Value }\n}\n\n/**\n * Filters an object using a predicate function, returning a new object with only the entries\n * that pass the predicate. Optimized to return the original object if no changes are needed.\n *\n * @param object - The object to filter\n * @param predicate - Function that tests each key-value pair\n * @returns A new object with only the entries that pass the predicate, or the original object if unchanged\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const passing = filterEntries(scores, (name, score) => score >= 80)\n * // { alice: 85, bob: 92 }\n * ```\n * @internal\n */\nexport function filterEntries<Key extends string, Value>(\n\tobject: { [K in Key]: Value },\n\tpredicate: (key: Key, value: Value) => boolean\n): { [K in Key]: Value } {\n\tconst result: { [K in Key]?: Value } = {}\n\tlet didChange = false\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tconst value = object[key]\n\t\tif (predicate(key, value)) {\n\t\t\tresult[key] = value\n\t\t} else {\n\t\t\tdidChange = true\n\t\t}\n\t}\n\treturn didChange ? (result as { [K in Key]: Value }) : object\n}\n\n/**\n * Maps the values of an object to new values using a mapper function, preserving keys.\n * The mapper function receives both the key and value for each entry.\n *\n * @param object - The object whose values to transform\n * @param mapper - Function that transforms each value (receives key and value)\n * @returns A new object with the same keys but transformed values\n * @example\n * ```ts\n * const prices = { apple: 1.50, banana: 0.75, orange: 2.00 }\n * const withTax = mapObjectMapValues(prices, (fruit, price) => price * 1.08)\n * // { apple: 1.62, banana: 0.81, orange: 2.16 }\n * ```\n * @internal\n */\nexport function mapObjectMapValues<Key extends string, ValueBefore, ValueAfter>(\n\tobject: { readonly [K in Key]: ValueBefore },\n\tmapper: (key: Key, value: ValueBefore) => ValueAfter\n): { [K in Key]: ValueAfter } {\n\tconst result = {} as { [K in Key]: ValueAfter }\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tresult[key] = mapper(key, object[key])\n\t}\n\treturn result\n}\n\n/**\n * Performs a shallow equality check between two objects. Compares all enumerable own properties\n * using Object.is for value comparison. Returns true if both objects have the same keys and values.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @returns True if objects are shallow equal, false otherwise\n * @example\n * ```ts\n * const a = { x: 1, y: 2 }\n * const b = { x: 1, y: 2 }\n * const c = { x: 1, y: 3 }\n * areObjectsShallowEqual(a, b) // true\n * areObjectsShallowEqual(a, c) // false\n * areObjectsShallowEqual(a, a) // true (same reference)\n * ```\n * @internal\n */\nexport function areObjectsShallowEqual<T extends object>(obj1: T, obj2: T): boolean {\n\tif (obj1 === obj2) return true\n\tconst keys1 = Object.keys(obj1)\n\tif (keys1.length !== Object.keys(obj2).length) return false\n\tfor (const key of keys1) {\n\t\tif (!hasOwnProperty(obj2, key)) return false\n\t\tif (!Object.is((obj1 as any)[key], (obj2 as any)[key])) return false\n\t}\n\treturn true\n}\n\n/**\n * Groups an array of values into a record by a key extracted from each value.\n * The key selector function is called for each element to determine the grouping key.\n *\n * @param array - The array to group\n * @param keySelector - Function that extracts the grouping key from each value\n * @returns A record where keys are the extracted keys and values are arrays of grouped items\n * @example\n * ```ts\n * const people = [\n * { name: 'Alice', age: 25 },\n * { name: 'Bob', age: 30 },\n * { name: 'Charlie', age: 25 }\n * ]\n * const byAge = groupBy(people, person => `age-${person.age}`)\n * // { 'age-25': [Alice, Charlie], 'age-30': [Bob] }\n * ```\n * @internal\n */\nexport function groupBy<K extends string, V>(\n\tarray: ReadonlyArray<V>,\n\tkeySelector: (value: V) => K\n): Record<K, V[]> {\n\tconst result: Record<K, V[]> = {} as any\n\tfor (const value of array) {\n\t\tconst key = keySelector(value)\n\t\tif (!result[key]) result[key] = []\n\t\tresult[key].push(value)\n\t}\n\treturn result\n}\n\n/**\n * Creates a new object with specified keys omitted from the original object.\n * Uses shallow copying and then deletes the unwanted keys.\n *\n * @param obj - The source object\n * @param keys - Array of key names to omit from the result\n * @returns A new object without the specified keys\n * @example\n * ```ts\n * const user = { id: '123', name: 'Alice', password: 'secret', email: 'alice@example.com' }\n * const publicUser = omit(user, ['password'])\n * // { id: '123', name: 'Alice', email: 'alice@example.com' }\n * ```\n * @internal\n */\nexport function omit(\n\tobj: Record<string, unknown>,\n\tkeys: ReadonlyArray<string>\n): Record<string, unknown> {\n\tconst result = { ...obj }\n\tfor (const key of keys) {\n\t\tdelete result[key]\n\t}\n\treturn result\n}\n\n/**\n * Compares two objects and returns an array of keys where the values differ.\n * Uses Object.is for comparison, which handles NaN and -0/+0 correctly.\n * Only checks keys present in the first object.\n *\n * @param obj1 - The first object (keys to check come from this object)\n * @param obj2 - The second object to compare against\n * @returns Array of keys where values differ between the objects\n * @example\n * ```ts\n * const before = { name: 'Alice', age: 25, city: 'NYC' }\n * const after = { name: 'Alice', age: 26, city: 'NYC' }\n * const changed = getChangedKeys(before, after)\n * // ['age']\n * ```\n * @internal\n */\nexport function getChangedKeys<T extends object>(obj1: T, obj2: T): (keyof T)[] {\n\tconst result: (keyof T)[] = []\n\tfor (const key in obj1) {\n\t\tif (!Object.is(obj1[key], obj2[key])) {\n\t\t\tresult.push(key)\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Deep equality comparison that allows for floating-point precision errors.\n * Numbers are considered equal if they differ by less than the threshold.\n * Uses lodash.isequalwith internally for the deep comparison logic.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @param threshold - Maximum difference allowed between numbers (default: 0.000001)\n * @returns True if objects are deeply equal with floating-point tolerance\n * @example\n * ```ts\n * const a = { x: 0.1 + 0.2 } // 0.30000000000000004\n * const b = { x: 0.3 }\n * isEqualAllowingForFloatingPointErrors(a, b) // true\n *\n * const c = { coords: [1.0000001, 2.0000001] }\n * const d = { coords: [1.0000002, 2.0000002] }\n * isEqualAllowingForFloatingPointErrors(c, d) // true\n * ```\n * @internal\n */\nexport function isEqualAllowingForFloatingPointErrors(\n\tobj1: object,\n\tobj2: object,\n\tthreshold = 0.000001\n): boolean {\n\treturn isEqualWith(obj1, obj2, (value1, value2) => {\n\t\tif (typeof value1 === 'number' && typeof value2 === 'number') {\n\t\t\treturn Math.abs(value1 - value2) < threshold\n\t\t}\n\t\treturn undefined\n\t})\n}\n","/**\n * Color scheme for performance indicators.\n * Provides consistent colors for performance measurement displays.\n *\n * @public\n */\nexport const PERFORMANCE_COLORS = {\n\tGood: '#40C057',\n\tMid: '#FFC078',\n\tPoor: '#E03131',\n}\n\n/**\n * Default color for performance measurement log prefixes.\n * Uses the 'Good' performance color for console output styling.\n *\n * @public\n */\nexport const PERFORMANCE_PREFIX_COLOR = PERFORMANCE_COLORS.Good\n\n/**\n * Measures and logs the execution time of a callback function.\n * Executes the provided callback and logs the duration to the console with styled output.\n *\n * @param name - Descriptive name for the operation being measured\n * @param cb - Callback function to execute and measure\n * @returns The return value of the callback function\n *\n * @example\n * ```ts\n * const result = measureCbDuration('data processing', () => {\n * return processLargeDataSet(data)\n * })\n * // Console output: \"Perf data processing took 42.5ms\"\n * ```\n *\n * @internal\n */\nexport function measureCbDuration(name: string, cb: () => any) {\n\tconst start = performance.now()\n\tconst result = cb()\n\t// eslint-disable-next-line no-console\n\tconsole.debug(\n\t\t`%cPerf%c ${name} took ${performance.now() - start}ms`,\n\t\t`color: white; background: ${PERFORMANCE_PREFIX_COLOR};padding: 2px;border-radius: 3px;`,\n\t\t'font-weight: normal'\n\t)\n\treturn result\n}\n\n/**\n * Decorator that measures and logs the execution time of class methods.\n * Wraps the decorated method to automatically log its execution duration.\n *\n * @param _target - The class prototype (unused)\n * @param propertyKey - Name of the method being decorated\n * @param descriptor - Property descriptor of the method\n * @returns Modified property descriptor with timing measurement\n *\n * @example\n * ```ts\n * class DataProcessor {\n * @measureDuration\n * processData(data: unknown[]) {\n * return data.map(item => transform(item))\n * }\n * }\n * // When processData is called, logs: \"Perf processData took: 15.2ms\"\n * ```\n *\n * @internal\n */\nexport function measureDuration(_target: any, propertyKey: string, descriptor: PropertyDescriptor) {\n\tconst originalMethod = descriptor.value\n\tdescriptor.value = function (...args: any[]) {\n\t\tconst start = performance.now()\n\t\tconst result = originalMethod.apply(this, args)\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.debug(\n\t\t\t`%cPerf%c ${propertyKey} took: ${performance.now() - start}ms`,\n\t\t\t`color: white; background: ${PERFORMANCE_PREFIX_COLOR};padding: 2px;border-radius: 3px;`,\n\t\t\t'font-weight: normal'\n\t\t)\n\t\treturn result\n\t}\n\treturn descriptor\n}\n\nconst averages = new Map<any, { total: number; count: number }>()\n\n/**\n * Decorator that measures method execution time and tracks running averages.\n * Wraps the decorated method to log both current execution time and running average.\n * Maintains a running total and count for each decorated method to calculate averages.\n *\n * @param _target - The class prototype (unused)\n * @param propertyKey - Name of the method being decorated\n * @param descriptor - Property descriptor of the method\n * @returns Modified property descriptor with timing measurement and averaging\n *\n * @example\n * ```ts\n * class RenderEngine {\n * @measureAverageDuration\n * renderFrame() {\n * // Rendering logic here\n * }\n * }\n * // After multiple calls, logs: \"Perf renderFrame took 16.67ms | average 15.83ms\"\n * ```\n *\n * @internal\n */\nexport function measureAverageDuration(\n\t_target: any,\n\tpropertyKey: string,\n\tdescriptor: PropertyDescriptor\n) {\n\tconst originalMethod = descriptor.value\n\tdescriptor.value = function (...args: any[]) {\n\t\tconst start = performance.now()\n\t\tconst result = originalMethod.apply(this, args)\n\t\tconst end = performance.now()\n\t\tconst length = end - start\n\t\tif (length !== 0) {\n\t\t\tconst value = averages.get(descriptor.value)!\n\t\t\tconst total = value.total + length\n\t\t\tconst count = value.count + 1\n\t\t\taverages.set(descriptor.value, { total, count })\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.debug(\n\t\t\t\t`%cPerf%c ${propertyKey} took ${(end - start).toFixed(2)}ms | average ${(total / count).toFixed(2)}ms`,\n\t\t\t\t`color: white; background: ${PERFORMANCE_PREFIX_COLOR};padding: 2px;border-radius: 3px;`,\n\t\t\t\t'font-weight: normal'\n\t\t\t)\n\t\t}\n\t\treturn result\n\t}\n\taverages.set(descriptor.value, { total: 0, count: 0 })\n\treturn descriptor\n}\n","import { PERFORMANCE_COLORS, PERFORMANCE_PREFIX_COLOR } from './perf'\n\n/**\n * A utility class for measuring and tracking frame rate performance during operations.\n * Provides visual feedback in the browser console with color-coded FPS indicators.\n *\n * @example\n * ```ts\n * const tracker = new PerformanceTracker()\n *\n * tracker.start('render')\n * renderShapes()\n * tracker.stop() // Logs performance info to console\n *\n * // Check if tracking is active\n * if (tracker.isStarted()) {\n * console.log('Still tracking performance')\n * }\n * ```\n *\n * @public\n */\nexport class PerformanceTracker {\n\tprivate startTime = 0\n\tprivate name = ''\n\tprivate frames = 0\n\tprivate started = false\n\tprivate frame: number | null = null\n\n\t/**\n\t * Records animation frames to calculate frame rate.\n\t * Called automatically during performance tracking.\n\t */\n\t// eslint-disable-next-line tldraw/prefer-class-methods\n\trecordFrame = () => {\n\t\tthis.frames++\n\t\tif (!this.started) return\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tthis.frame = requestAnimationFrame(this.recordFrame)\n\t}\n\n\t/**\n\t * Starts performance tracking for a named operation.\n\t *\n\t * @param name - A descriptive name for the operation being tracked\n\t *\n\t * @example\n\t * ```ts\n\t * tracker.start('canvas-render')\n\t * // ... perform rendering operations\n\t * tracker.stop()\n\t * ```\n\t */\n\tstart(name: string) {\n\t\tthis.name = name\n\t\tthis.frames = 0\n\t\tthis.started = true\n\t\tif (this.frame !== null) cancelAnimationFrame(this.frame)\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tthis.frame = requestAnimationFrame(this.recordFrame)\n\t\tthis.startTime = performance.now()\n\t}\n\n\t/**\n\t * Stops performance tracking and logs results to the console.\n\t *\n\t * Displays the operation name, frame rate, and uses color coding:\n\t * - Green background: \\> 55 FPS (good performance)\n\t * - Yellow background: 30-55 FPS (moderate performance)\n\t * - Red background: \\< 30 FPS (poor performance)\n\t *\n\t * @example\n\t * ```ts\n\t * tracker.start('interaction')\n\t * handleUserInteraction()\n\t * tracker.stop() // Logs: \"Perf Interaction 60 fps\"\n\t * ```\n\t */\n\tstop() {\n\t\tthis.started = false\n\t\tif (this.frame !== null) cancelAnimationFrame(this.frame)\n\t\tconst duration = (performance.now() - this.startTime) / 1000\n\t\tconst fps = duration === 0 ? 0 : Math.floor(this.frames / duration)\n\t\tconst background =\n\t\t\tfps > 55\n\t\t\t\t? PERFORMANCE_COLORS.Good\n\t\t\t\t: fps > 30\n\t\t\t\t\t? PERFORMANCE_COLORS.Mid\n\t\t\t\t\t: PERFORMANCE_COLORS.Poor\n\t\tconst color = background === PERFORMANCE_COLORS.Mid ? 'black' : 'white'\n\t\tconst capitalized = this.name[0].toUpperCase() + this.name.slice(1)\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.debug(\n\t\t\t`%cPerf%c ${capitalized} %c${fps}%c fps`,\n\t\t\t`color: white; background: ${PERFORMANCE_PREFIX_COLOR};padding: 2px;border-radius: 3px;`,\n\t\t\t'font-weight: normal',\n\t\t\t`font-weight: bold; padding: 2px; background: ${background};color: ${color};`,\n\t\t\t'font-weight: normal'\n\t\t)\n\t}\n\n\t/**\n\t * Checks whether performance tracking is currently active.\n\t *\n\t * @returns True if tracking is in progress, false otherwise\n\t *\n\t * @example\n\t * ```ts\n\t * if (!tracker.isStarted()) {\n\t * tracker.start('new-operation')\n\t * }\n\t * ```\n\t */\n\tisStarted() {\n\t\treturn this.started\n\t}\n}\n","import { generateKeyBetween, generateNKeysBetween } from 'jittered-fractional-indexing'\n\nconst generateNKeysBetweenWithNoJitter = (a: string | null, b: string | null, n: number) => {\n\treturn generateNKeysBetween(a, b, n, { jitterBits: 0 })\n}\n\nconst generateKeysFn =\n\tprocess.env.NODE_ENV === 'test' ? generateNKeysBetweenWithNoJitter : generateNKeysBetween\n\n/**\n * A string made up of an integer part followed by a fraction part. The fraction point consists of\n * zero or more digits with no trailing zeros. Based on\n * {@link https://observablehq.com/@dgreensp/implementing-fractional-indexing}.\n *\n * @public\n */\nexport type IndexKey = string & { __brand: 'indexKey' }\n\n/**\n * The index key for the first index - 'a0'.\n * @public\n */\nexport const ZERO_INDEX_KEY = 'a0' as IndexKey\n\n/**\n * Validates that a string is a valid IndexKey.\n * @param index - The string to validate.\n * @throws Error if the index is invalid.\n * @internal\n */\nexport function validateIndexKey(index: string): asserts index is IndexKey {\n\ttry {\n\t\tgenerateKeyBetween(index, null)\n\t} catch {\n\t\tthrow new Error('invalid index: ' + index)\n\t}\n}\n\n/**\n * Get a number of indices between two indices.\n * @param below - The index below.\n * @param above - The index above.\n * @param n - The number of indices to get.\n * @returns An array of n IndexKey values between below and above.\n * @example\n * ```ts\n * const indices = getIndicesBetween('a0' as IndexKey, 'a2' as IndexKey, 2)\n * console.log(indices) // ['a0V', 'a1']\n * ```\n * @public\n */\nexport function getIndicesBetween(\n\tbelow: IndexKey | null | undefined,\n\tabove: IndexKey | null | undefined,\n\tn: number\n) {\n\treturn generateKeysFn(below ?? null, above ?? null, n) as IndexKey[]\n}\n\n/**\n * Get a number of indices above an index.\n * @param below - The index below.\n * @param n - The number of indices to get.\n * @returns An array of n IndexKey values above the given index.\n * @example\n * ```ts\n * const indices = getIndicesAbove('a0' as IndexKey, 3)\n * console.log(indices) // ['a1', 'a2', 'a3']\n * ```\n * @public\n */\nexport function getIndicesAbove(below: IndexKey | null | undefined, n: number) {\n\treturn generateKeysFn(below ?? null, null, n) as IndexKey[]\n}\n\n/**\n * Get a number of indices below an index.\n * @param above - The index above.\n * @param n - The number of indices to get.\n * @returns An array of n IndexKey values below the given index.\n * @example\n * ```ts\n * const indices = getIndicesBelow('a2' as IndexKey, 2)\n * console.log(indices) // ['a1', 'a0V']\n * ```\n * @public\n */\nexport function getIndicesBelow(above: IndexKey | null | undefined, n: number) {\n\treturn generateKeysFn(null, above ?? null, n) as IndexKey[]\n}\n\n/**\n * Get the index between two indices.\n * @param below - The index below.\n * @param above - The index above.\n * @returns A single IndexKey value between below and above.\n * @example\n * ```ts\n * const index = getIndexBetween('a0' as IndexKey, 'a2' as IndexKey)\n * console.log(index) // 'a1'\n * ```\n * @public\n */\nexport function getIndexBetween(\n\tbelow: IndexKey | null | undefined,\n\tabove: IndexKey | null | undefined\n) {\n\treturn generateKeysFn(below ?? null, above ?? null, 1)[0] as IndexKey\n}\n\n/**\n * Get the index above a given index.\n * @param below - The index below.\n * @returns An IndexKey value above the given index.\n * @example\n * ```ts\n * const index = getIndexAbove('a0' as IndexKey)\n * console.log(index) // 'a1'\n * ```\n * @public\n */\nexport function getIndexAbove(below: IndexKey | null | undefined = null) {\n\treturn generateKeysFn(below, null, 1)[0] as IndexKey\n}\n\n/**\n * Get the index below a given index.\n * @param above - The index above.\n * @returns An IndexKey value below the given index.\n * @example\n * ```ts\n * const index = getIndexBelow('a2' as IndexKey)\n * console.log(index) // 'a1'\n * ```\n * @public\n */\nexport function getIndexBelow(above: IndexKey | null | undefined = null) {\n\treturn generateKeysFn(null, above, 1)[0] as IndexKey\n}\n\n/**\n * Get n number of indices, starting at an index.\n * @param n - The number of indices to get.\n * @param start - The index to start at.\n * @returns An array containing the start index plus n additional IndexKey values.\n * @example\n * ```ts\n * const indices = getIndices(3, 'a1' as IndexKey)\n * console.log(indices) // ['a1', 'a2', 'a3', 'a4']\n * ```\n * @public\n */\nexport function getIndices(n: number, start = 'a1' as IndexKey) {\n\treturn [start, ...generateKeysFn(start, null, n)] as IndexKey[]\n}\n\n/**\n * Sort by index.\n * @param a - An object with an index property.\n * @param b - An object with an index property.\n * @returns A number indicating sort order (-1, 0, or 1).\n * @example\n * ```ts\n * const shapes = [\n * { id: 'b', index: 'a2' as IndexKey },\n * { id: 'a', index: 'a1' as IndexKey }\n * ]\n * const sorted = shapes.sort(sortByIndex)\n * console.log(sorted) // [{ id: 'a', index: 'a1' }, { id: 'b', index: 'a2' }]\n * ```\n * @public\n */\nexport function sortByIndex<T extends { index: IndexKey }>(a: T, b: T) {\n\tif (a.index < b.index) {\n\t\treturn -1\n\t} else if (a.index > b.index) {\n\t\treturn 1\n\t}\n\treturn 0\n}\n\n/**\n * Sort by index, or null.\n * @param a - An object with an index property.\n * @param b - An object with an index property.\n * @public\n */\nexport function sortByMaybeIndex<T extends { index?: IndexKey | null }>(a: T, b: T) {\n\tif (a.index && b.index) {\n\t\treturn a.index < b.index ? -1 : 1\n\t}\n\tif (a.index && b.index == null) {\n\t\treturn -1\n\t}\n\tif (a.index == null && b.index == null) {\n\t\treturn 0\n\t}\n\treturn 1\n}\n","import { sleep } from './control'\n\n/**\n * Retries an async operation with configurable attempt count, wait duration, and error filtering.\n * Executes the provided async function repeatedly until it succeeds or the maximum number of attempts is reached.\n * Includes support for abort signals and custom error matching to determine which errors should trigger retries.\n *\n * @param fn - The async function to retry on failure\n * @param options - Configuration options for retry behavior:\n * - `attempts`: Maximum number of retry attempts (default: 3)\n * - `waitDuration`: Milliseconds to wait between retry attempts (default: 1000)\n * - `abortSignal`: Optional AbortSignal to cancel the retry operation\n * - `matchError`: Optional function to determine if an error should trigger a retry\n * @returns Promise that resolves with the function's return value on success\n *\n * @example\n * ```ts\n * // Basic retry with default settings (3 attempts, 1 second wait)\n * const data = await retry(async () => {\n * const response = await fetch('/api/data')\n * if (!response.ok) throw new Error('Network error')\n * return response.json()\n * })\n *\n * // Custom retry configuration\n * const result = await retry(\n * async () => unreliableApiCall(),\n * {\n * attempts: 5,\n * waitDuration: 2000,\n * matchError: (error) => error instanceof NetworkError\n * }\n * )\n *\n * // With abort signal for cancellation\n * const controller = new AbortController()\n * setTimeout(() => controller.abort(), 10000) // Cancel after 10 seconds\n *\n * const data = await retry(\n * async () => fetchData(),\n * {\n * attempts: 10,\n * abortSignal: controller.signal\n * }\n * )\n * ```\n *\n * @internal\n */\nexport async function retry<T>(\n\tfn: (args: { attempt: number; remaining: number; total: number }) => Promise<T>,\n\t{\n\t\tattempts = 3,\n\t\twaitDuration = 1000,\n\t\tabortSignal,\n\t\tmatchError,\n\t}: {\n\t\tattempts?: number\n\t\twaitDuration?: number\n\t\tabortSignal?: AbortSignal\n\t\tmatchError?(error: unknown): boolean\n\t} = {}\n): Promise<T> {\n\tlet error: unknown = null\n\tfor (let i = 0; i < attempts; i++) {\n\t\tif (abortSignal?.aborted) throw new Error('aborted')\n\t\ttry {\n\t\t\treturn await fn({ attempt: i, remaining: attempts - i, total: attempts })\n\t\t} catch (e) {\n\t\t\tif (matchError && !matchError(e)) throw e\n\t\t\terror = e\n\t\t\tawait sleep(waitDuration)\n\t\t}\n\t}\n\t// eslint-disable-next-line no-throw-literal\n\tthrow error\n}\n","/**\n * Compares two objects by their id property for use with Array.sort().\n * Sorts objects in ascending order based on their id values.\n *\n * @param a - First object to compare\n * @param b - Second object to compare\n * @returns 1 if a.id \\> b.id, -1 if a.id \\<= b.id\n *\n * @example\n * ```ts\n * const items = [\n * { id: 'c', name: 'Charlie' },\n * { id: 'a', name: 'Alice' },\n * { id: 'b', name: 'Bob' },\n * ]\n *\n * const sorted = items.sort(sortById)\n * // [{ id: 'a', name: 'Alice' }, { id: 'b', name: 'Bob' }, { id: 'c', name: 'Charlie' }]\n * ```\n *\n * @public\n */\nexport function sortById<T extends { id: any }>(a: T, b: T) {\n\treturn a.id > b.id ? 1 : -1\n}\n","/* eslint-disable tldraw/no-direct-storage */\n\n/**\n * Get a value from local storage.\n *\n * @param key - The key to get.\n * @returns The stored value as a string, or null if not found or storage is unavailable.\n * @example\n * ```ts\n * const userTheme = getFromLocalStorage('user-theme')\n * if (userTheme) {\n * console.log('Stored theme:', userTheme)\n * }\n * ```\n * @internal\n */\nexport function getFromLocalStorage(key: string) {\n\ttry {\n\t\treturn localStorage.getItem(key)\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Set a value in local storage. Will not throw an error if localStorage is not available.\n *\n * @param key - The key to set.\n * @param value - The value to set.\n * @returns void\n * @example\n * ```ts\n * const preferences = { theme: 'dark', language: 'en' }\n * setInLocalStorage('user-preferences', JSON.stringify(preferences))\n * ```\n * @internal\n */\nexport function setInLocalStorage(key: string, value: string) {\n\ttry {\n\t\tlocalStorage.setItem(key, value)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Remove a value from local storage. Will not throw an error if localStorage is not available.\n *\n * @param key - The key to remove.\n * @returns void\n * @example\n * ```ts\n * deleteFromLocalStorage('user-preferences')\n * // Value is now removed from localStorage\n * ```\n * @internal\n */\nexport function deleteFromLocalStorage(key: string) {\n\ttry {\n\t\tlocalStorage.removeItem(key)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Clear all values from local storage. Will not throw an error if localStorage is not available.\n *\n * @returns void\n * @example\n * ```ts\n * clearLocalStorage()\n * // All localStorage data is now cleared\n * ```\n * @internal\n */\nexport function clearLocalStorage() {\n\ttry {\n\t\tlocalStorage.clear()\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Get a value from session storage.\n *\n * @param key - The key to get.\n * @returns The stored value as a string, or null if not found or storage is unavailable.\n * @example\n * ```ts\n * const currentTool = getFromSessionStorage('current-tool')\n * if (currentTool) {\n * console.log('Active tool:', currentTool)\n * }\n * ```\n * @internal\n */\nexport function getFromSessionStorage(key: string) {\n\ttry {\n\t\treturn sessionStorage.getItem(key)\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Set a value in session storage. Will not throw an error if sessionStorage is not available.\n *\n * @param key - The key to set.\n * @param value - The value to set.\n * @returns void\n * @example\n * ```ts\n * setInSessionStorage('current-tool', 'select')\n * setInSessionStorage('temp-data', JSON.stringify({ x: 100, y: 200 }))\n * ```\n * @internal\n */\nexport function setInSessionStorage(key: string, value: string) {\n\ttry {\n\t\tsessionStorage.setItem(key, value)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Remove a value from session storage. Will not throw an error if sessionStorage is not available.\n *\n * @param key - The key to remove.\n * @returns void\n * @example\n * ```ts\n * deleteFromSessionStorage('temp-data')\n * // Value is now removed from sessionStorage\n * ```\n * @internal\n */\nexport function deleteFromSessionStorage(key: string) {\n\ttry {\n\t\tsessionStorage.removeItem(key)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Clear all values from session storage. Will not throw an error if sessionStorage is not available.\n *\n * @returns void\n * @example\n * ```ts\n * clearSessionStorage()\n * // All sessionStorage data is now cleared\n * ```\n * @internal\n */\nexport function clearSessionStorage() {\n\ttry {\n\t\tsessionStorage.clear()\n\t} catch {\n\t\t// noop\n\t}\n}\n","/**\n * Creates an enum-like object from string values where each key maps to itself.\n * Useful for creating string constant objects with type safety and autocompletion.\n * @param values - The string values to create the enum from.\n * @returns An object where each provided string is both the key and value.\n * @example\n * ```ts\n * const Colors = stringEnum('red', 'green', 'blue')\n * // Results in: { red: 'red', green: 'green', blue: 'blue' }\n *\n * // Type-safe usage\n * function setColor(color: keyof typeof Colors) {\n * console.log(`Setting color to ${Colors[color]}`)\n * }\n *\n * setColor('red') // ✓ Valid\n * setColor('yellow') // ✗ TypeScript error\n * ```\n * @internal\n */\nexport function stringEnum<T extends string>(...values: T[]): { [K in T]: K } {\n\tconst obj = {} as { [K in T]: K }\n\tfor (const value of values) {\n\t\tobj[value] = value\n\t}\n\treturn obj\n}\n","const isTest = () =>\n\ttypeof process !== 'undefined' &&\n\tprocess.env.NODE_ENV === 'test' &&\n\t// @ts-expect-error\n\t!globalThis.__FORCE_RAF_IN_TESTS__\n\n// Browsers aren't precise with frame timing - this factor prevents skipping frames unnecessarily\n// by aiming slightly below the theoretical frame duration (e.g., ~7.5ms instead of 8.33ms for 120fps)\nconst timingVarianceFactor = 0.9\nconst getTargetTimePerFrame = (targetFps: number) =>\n\tMath.floor(1000 / targetFps) * timingVarianceFactor\n\n/**\n * A scheduler class that manages a queue of functions to be executed at a target frame rate.\n * Each instance maintains its own queue and state, allowing for separate throttling contexts\n * (e.g., UI operations vs network sync operations).\n *\n * @public\n */\nexport class FpsScheduler {\n\tprivate targetFps: number\n\tprivate targetTimePerFrame: number\n\tprivate fpsQueue: Array<() => void> = []\n\tprivate frameRaf: undefined | number\n\tprivate flushRaf: undefined | number\n\tprivate lastFlushTime: number\n\n\tconstructor(targetFps: number = 120) {\n\t\tthis.targetFps = targetFps\n\t\tthis.targetTimePerFrame = getTargetTimePerFrame(targetFps)\n\t\tthis.lastFlushTime = -this.targetTimePerFrame\n\t}\n\n\tupdateTargetFps(targetFps: number) {\n\t\tif (targetFps === this.targetFps) return\n\t\tthis.targetFps = targetFps\n\t\tthis.targetTimePerFrame = getTargetTimePerFrame(targetFps)\n\t\tthis.lastFlushTime = -this.targetTimePerFrame\n\t}\n\n\tprivate flush() {\n\t\tconst queue = this.fpsQueue.splice(0, this.fpsQueue.length)\n\t\tfor (const fn of queue) {\n\t\t\tfn()\n\t\t}\n\t}\n\n\tprivate tick(isOnNextFrame = false) {\n\t\tif (this.frameRaf) return\n\n\t\tconst now = Date.now()\n\t\tconst elapsed = now - this.lastFlushTime\n\n\t\tif (elapsed < this.targetTimePerFrame) {\n\t\t\t// If we're too early to flush, we need to wait until the next frame to try and flush again.\n\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\tthis.frameRaf = requestAnimationFrame(() => {\n\t\t\t\tthis.frameRaf = undefined\n\t\t\t\tthis.tick(true)\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tif (isOnNextFrame) {\n\t\t\t// If we've already waited for the next frame to run the tick, then we can flush immediately\n\t\t\tif (this.flushRaf) return // ...though if there's a flush raf, that means we'll be flushing on this frame already, so we can do nothing here.\n\t\t\tthis.lastFlushTime = now\n\t\t\tthis.flush()\n\t\t} else {\n\t\t\t// If we haven't already waited for the next frame to run the tick, we need to wait until the next frame to flush.\n\t\t\tif (this.flushRaf) return // ...though if there's a flush raf, that means we'll be flushing on the next frame already, so we can do nothing here.\n\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\tthis.flushRaf = requestAnimationFrame(() => {\n\t\t\t\tthis.flushRaf = undefined\n\t\t\t\tthis.lastFlushTime = Date.now()\n\t\t\t\tthis.flush()\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Creates a throttled version of a function that executes at most once per frame.\n\t * The default target frame rate is set by the FpsScheduler instance.\n\t * Subsequent calls within the same frame are ignored, ensuring smooth performance\n\t * for high-frequency events like mouse movements or scroll events.\n\t *\n\t * @param fn - The function to throttle, optionally with a cancel method\n\t * @returns A throttled function with an optional cancel method to remove pending calls\n\t *\n\t * @public\n\t */\n\tfpsThrottle(fn: { (): void; cancel?(): void }): {\n\t\t(): void\n\t\tcancel?(): void\n\t} {\n\t\tif (isTest()) {\n\t\t\tfn.cancel = () => {\n\t\t\t\tif (this.frameRaf) {\n\t\t\t\t\tcancelAnimationFrame(this.frameRaf)\n\t\t\t\t\tthis.frameRaf = undefined\n\t\t\t\t}\n\t\t\t\tif (this.flushRaf) {\n\t\t\t\t\tcancelAnimationFrame(this.flushRaf)\n\t\t\t\t\tthis.flushRaf = undefined\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fn\n\t\t}\n\n\t\tconst throttledFn = () => {\n\t\t\tif (this.fpsQueue.includes(fn)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.fpsQueue.push(fn)\n\t\t\tthis.tick()\n\t\t}\n\t\tthrottledFn.cancel = () => {\n\t\t\tconst index = this.fpsQueue.indexOf(fn)\n\t\t\tif (index > -1) {\n\t\t\t\tthis.fpsQueue.splice(index, 1)\n\t\t\t}\n\t\t}\n\t\treturn throttledFn\n\t}\n\n\t/**\n\t * Schedules a function to execute on the next animation frame.\n\t * If the same function is passed multiple times before the frame executes,\n\t * it will only be called once, effectively batching multiple calls.\n\t *\n\t * @param fn - The function to execute on the next frame\n\t * @returns A cancel function that can prevent execution if called before the next frame\n\t *\n\t * @public\n\t */\n\tthrottleToNextFrame(fn: () => void): () => void {\n\t\tif (isTest()) {\n\t\t\tfn()\n\t\t\treturn () => void null // noop\n\t\t}\n\n\t\tif (!this.fpsQueue.includes(fn)) {\n\t\t\tthis.fpsQueue.push(fn)\n\t\t\tthis.tick()\n\t\t}\n\n\t\treturn () => {\n\t\t\tconst index = this.fpsQueue.indexOf(fn)\n\t\t\tif (index > -1) {\n\t\t\t\tthis.fpsQueue.splice(index, 1)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Default instance for UI operations\nconst defaultScheduler = new FpsScheduler(120)\n\n/**\n * Creates a throttled version of a function that executes at most once per frame.\n * The default target frame rate is 120fps, but can be customized per function.\n * Subsequent calls within the same frame are ignored, ensuring smooth performance\n * for high-frequency events like mouse movements or scroll events.\n *\n * Uses the default throttle instance for UI operations. If you need a separate\n * throttling queue (e.g., for network operations), create your own Throttle instance.\n *\n * @param fn - The function to throttle, optionally with a cancel method\n * @returns A throttled function with an optional cancel method to remove pending calls\n *\n * @example\n * ```ts\n * // Default 120fps throttling\n * const updateCanvas = fpsThrottle(() => {\n * // This will run at most once per frame (~8.33ms)\n * redrawCanvas()\n * })\n *\n * // Call as often as you want - automatically throttled to 120fps\n * document.addEventListener('mousemove', updateCanvas)\n *\n * // Cancel pending calls if needed\n * updateCanvas.cancel?.()\n * ```\n *\n * @internal\n */\nexport function fpsThrottle(fn: { (): void; cancel?(): void }): {\n\t(): void\n\tcancel?(): void\n} {\n\treturn defaultScheduler.fpsThrottle(fn)\n}\n\n/**\n * Schedules a function to execute on the next animation frame, targeting 120fps.\n * If the same function is passed multiple times before the frame executes,\n * it will only be called once, effectively batching multiple calls.\n *\n * Uses the default throttle instance for UI operations.\n *\n * @param fn - The function to execute on the next frame\n * @returns A cancel function that can prevent execution if called before the next frame\n *\n * @example\n * ```ts\n * const updateUI = throttleToNextFrame(() => {\n * // Batches multiple calls into the next animation frame\n * updateStatusBar()\n * refreshToolbar()\n * })\n *\n * // Multiple calls within the same frame are batched\n * updateUI() // Will execute\n * updateUI() // Ignored (same function already queued)\n * updateUI() // Ignored (same function already queued)\n *\n * // Get cancel function to prevent execution\n * const cancel = updateUI()\n * cancel() // Prevents execution if called before next frame\n * ```\n *\n * @internal\n */\nexport function throttleToNextFrame(fn: () => void): () => void {\n\treturn defaultScheduler.throttleToNextFrame(fn)\n}\n","/* eslint-disable tldraw/no-restricted-properties */\n\n/**\n * A utility class for managing timeouts, intervals, and animation frames with context-based organization and automatic cleanup.\n * Helps prevent memory leaks by organizing timers into named contexts that can be cleared together.\n * @example\n * ```ts\n * const timers = new Timers()\n *\n * // Set timers with context organization\n * timers.setTimeout('ui', () => console.log('Auto save'), 5000)\n * timers.setInterval('ui', () => console.log('Refresh'), 1000)\n * timers.requestAnimationFrame('ui', () => console.log('Render'))\n *\n * // Clear all timers for a context\n * timers.dispose('ui')\n *\n * // Or get context-bound functions\n * const uiTimers = timers.forContext('ui')\n * uiTimers.setTimeout(() => console.log('Contextual timeout'), 1000)\n * ```\n * @public\n */\nexport class Timers {\n\tprivate timeouts = new Map<string, number[]>()\n\tprivate intervals = new Map<string, number[]>()\n\tprivate rafs = new Map<string, number[]>()\n\n\t/**\n\t * Creates a new Timers instance with bound methods for safe callback usage.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * // Methods are pre-bound, safe to use as callbacks\n\t * element.addEventListener('click', timers.dispose)\n\t * ```\n\t */\n\tconstructor() {\n\t\tthis.setTimeout = this.setTimeout.bind(this)\n\t\tthis.setInterval = this.setInterval.bind(this)\n\t\tthis.requestAnimationFrame = this.requestAnimationFrame.bind(this)\n\t\tthis.dispose = this.dispose.bind(this)\n\t}\n\n\t/**\n\t * Creates a timeout that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this timer under.\n\t * @param handler - The function to execute when the timeout expires.\n\t * @param timeout - The delay in milliseconds (default: 0).\n\t * @param args - Additional arguments to pass to the handler.\n\t * @returns The timer ID that can be used with clearTimeout.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.setTimeout('autosave', () => save(), 5000)\n\t * // Timer will be automatically cleared when 'autosave' context is disposed\n\t * ```\n\t * @public\n\t */\n\tsetTimeout(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number {\n\t\tconst id = window.setTimeout(handler, timeout, args)\n\t\tconst current = this.timeouts.get(contextId) ?? []\n\t\tthis.timeouts.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Creates an interval that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this timer under.\n\t * @param handler - The function to execute repeatedly.\n\t * @param timeout - The delay in milliseconds between executions (default: 0).\n\t * @param args - Additional arguments to pass to the handler.\n\t * @returns The interval ID that can be used with clearInterval.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.setInterval('refresh', () => updateData(), 1000)\n\t * // Interval will be automatically cleared when 'refresh' context is disposed\n\t * ```\n\t * @public\n\t */\n\tsetInterval(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number {\n\t\tconst id = window.setInterval(handler, timeout, args)\n\t\tconst current = this.intervals.get(contextId) ?? []\n\t\tthis.intervals.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Requests an animation frame that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this animation frame under.\n\t * @param callback - The function to execute on the next animation frame.\n\t * @returns The request ID that can be used with cancelAnimationFrame.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.requestAnimationFrame('render', () => draw())\n\t * // Animation frame will be automatically cancelled when 'render' context is disposed\n\t * ```\n\t * @public\n\t */\n\trequestAnimationFrame(contextId: string, callback: FrameRequestCallback): number {\n\t\tconst id = window.requestAnimationFrame(callback)\n\t\tconst current = this.rafs.get(contextId) ?? []\n\t\tthis.rafs.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Disposes of all timers associated with the specified context.\n\t * Clears all timeouts, intervals, and animation frames for the given context ID.\n\t * @param contextId - The context identifier whose timers should be cleared.\n\t * @returns void\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * timers.setTimeout('ui', () => console.log('timeout'), 1000)\n\t * timers.setInterval('ui', () => console.log('interval'), 500)\n\t *\n\t * // Clear all 'ui' context timers\n\t * timers.dispose('ui')\n\t * ```\n\t * @public\n\t */\n\tdispose(contextId: string) {\n\t\tthis.timeouts.get(contextId)?.forEach((id) => clearTimeout(id))\n\t\tthis.intervals.get(contextId)?.forEach((id) => clearInterval(id))\n\t\tthis.rafs.get(contextId)?.forEach((id) => cancelAnimationFrame(id))\n\n\t\tthis.timeouts.delete(contextId)\n\t\tthis.intervals.delete(contextId)\n\t\tthis.rafs.delete(contextId)\n\t}\n\n\t/**\n\t * Disposes of all timers across all contexts.\n\t * Clears every timeout, interval, and animation frame managed by this instance.\n\t * @returns void\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * timers.setTimeout('ui', () => console.log('ui'), 1000)\n\t * timers.setTimeout('background', () => console.log('bg'), 2000)\n\t *\n\t * // Clear everything\n\t * timers.disposeAll()\n\t * ```\n\t * @public\n\t */\n\tdisposeAll() {\n\t\tfor (const contextId of this.timeouts.keys()) {\n\t\t\tthis.dispose(contextId)\n\t\t}\n\t}\n\n\t/**\n\t * Returns an object with timer methods bound to a specific context.\n\t * Convenient for getting context-specific timer functions without repeatedly passing the contextId.\n\t * @param contextId - The context identifier to bind the returned methods to.\n\t * @returns An object with setTimeout, setInterval, requestAnimationFrame, and dispose methods bound to the context.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const uiTimers = timers.forContext('ui')\n\t *\n\t * // These are equivalent to calling timers.setTimeout('ui', ...)\n\t * uiTimers.setTimeout(() => console.log('timeout'), 1000)\n\t * uiTimers.setInterval(() => console.log('interval'), 500)\n\t * uiTimers.requestAnimationFrame(() => console.log('frame'))\n\t *\n\t * // Dispose only this context\n\t * uiTimers.dispose()\n\t * ```\n\t * @public\n\t */\n\tforContext(contextId: string) {\n\t\treturn {\n\t\t\tsetTimeout: (handler: TimerHandler, timeout?: number, ...args: any[]) =>\n\t\t\t\tthis.setTimeout(contextId, handler, timeout, args),\n\t\t\tsetInterval: (handler: TimerHandler, timeout?: number, ...args: any[]) =>\n\t\t\t\tthis.setInterval(contextId, handler, timeout, args),\n\t\t\trequestAnimationFrame: (callback: FrameRequestCallback) =>\n\t\t\t\tthis.requestAnimationFrame(contextId, callback),\n\t\t\tdispose: () => this.dispose(contextId),\n\t\t}\n\t}\n}\n","/**\n * Safely parses a URL string without throwing exceptions on invalid input.\n * Returns a URL object for valid URLs or undefined for invalid ones.\n *\n * @param url - The URL string to parse\n * @param baseUrl - Optional base URL to resolve relative URLs against\n * @returns A URL object if parsing succeeds, undefined if it fails\n *\n * @example\n * ```ts\n * // Valid absolute URL\n * const url1 = safeParseUrl('https://example.com')\n * if (url1) {\n * console.log(`Valid URL: ${url1.href}`) // \"Valid URL: https://example.com/\"\n * }\n *\n * // Invalid URL\n * const url2 = safeParseUrl('not-a-url')\n * console.log(url2) // undefined\n *\n * // Relative URL with base\n * const url3 = safeParseUrl('/path', 'https://example.com')\n * if (url3) {\n * console.log(url3.href) // \"https://example.com/path\"\n * }\n *\n * // Error handling\n * function handleUserUrl(input: string) {\n * const url = safeParseUrl(input)\n * if (url) {\n * return url\n * } else {\n * console.log('Invalid URL provided')\n * return null\n * }\n * }\n * ```\n *\n * @public\n */\nexport const safeParseUrl = (url: string, baseUrl?: string | URL) => {\n\ttry {\n\t\treturn new URL(url, baseUrl)\n\t} catch {\n\t\treturn\n\t}\n}\n","/**\n * Get whether a value is not undefined.\n *\n * @param value - The value to check.\n * @returns True if the value is not undefined, with proper type narrowing.\n * @example\n * ```ts\n * const maybeString: string | undefined = getValue()\n *\n * if (isDefined(maybeString)) {\n * // TypeScript knows maybeString is string, not undefined\n * console.log(maybeString.toUpperCase())\n * }\n *\n * // Filter undefined values from arrays\n * const values = [1, undefined, 2, undefined, 3]\n * const definedValues = values.filter(isDefined) // [1, 2, 3]\n * ```\n * @public\n */\nexport function isDefined<T>(value: T): value is typeof value extends undefined ? never : T {\n\treturn value !== undefined\n}\n\n/**\n * Get whether a value is not null.\n *\n * @param value - The value to check.\n * @returns True if the value is not null, with proper type narrowing.\n * @example\n * ```ts\n * const maybeString: string | null = getValue()\n *\n * if (isNonNull(maybeString)) {\n * // TypeScript knows maybeString is string, not null\n * console.log(maybeString.length)\n * }\n *\n * // Filter null values from arrays\n * const values = [\"a\", null, \"b\", null, \"c\"]\n * const nonNullValues = values.filter(isNonNull) // [\"a\", \"b\", \"c\"]\n * ```\n * @public\n */\nexport function isNonNull<T>(value: T): value is typeof value extends null ? never : T {\n\treturn value !== null\n}\n\n/**\n * Get whether a value is not nullish (not null and not undefined).\n *\n * @param value - The value to check.\n * @returns True if the value is neither null nor undefined, with proper type narrowing.\n * @example\n * ```ts\n * const maybeString: string | null | undefined = getValue()\n *\n * if (isNonNullish(maybeString)) {\n * // TypeScript knows maybeString is string, not null or undefined\n * console.log(maybeString.charAt(0))\n * }\n *\n * // Filter nullish values from arrays\n * const values = [\"hello\", null, \"world\", undefined, \"!\"]\n * const cleanValues = values.filter(isNonNullish) // [\"hello\", \"world\", \"!\"]\n * ```\n * @public\n */\nexport function isNonNullish<T>(\n\tvalue: T\n): value is typeof value extends undefined ? never : typeof value extends null ? never : T {\n\treturn value !== null && value !== undefined\n}\n\nfunction getStructuredClone(): [<T>(i: T) => T, boolean] {\n\tif (typeof globalThis !== 'undefined' && (globalThis as any).structuredClone) {\n\t\treturn [globalThis.structuredClone as <T>(i: T) => T, true]\n\t}\n\n\tif (typeof global !== 'undefined' && (global as any).structuredClone) {\n\t\treturn [global.structuredClone as <T>(i: T) => T, true]\n\t}\n\n\tif (typeof window !== 'undefined' && (window as any).structuredClone) {\n\t\treturn [window.structuredClone as <T>(i: T) => T, true]\n\t}\n\n\treturn [<T>(i: T): T => (i ? JSON.parse(JSON.stringify(i)) : i), false]\n}\n\nconst _structuredClone = getStructuredClone()\n\n/**\n * Create a deep copy of a value. Uses the structuredClone API if available, otherwise uses JSON.parse(JSON.stringify()).\n *\n * @param i - The value to clone.\n * @returns A deep copy of the input value.\n * @example\n * ```ts\n * const original = { a: 1, b: { c: 2 } }\n * const copy = structuredClone(original)\n *\n * copy.b.c = 3\n * console.log(original.b.c) // 2 (unchanged)\n * console.log(copy.b.c) // 3\n *\n * // Works with complex objects\n * const complexObject = {\n * date: new Date(),\n * array: [1, 2, 3],\n * nested: { deep: { value: \"test\" } }\n * }\n * const cloned = structuredClone(complexObject)\n * ```\n * @public\n */\nexport const structuredClone = _structuredClone[0]\n\n/**\n * Whether the current environment has native structuredClone support.\n * @returns True if using native structuredClone, false if using JSON fallback.\n * @internal\n */\nexport const isNativeStructuredClone = _structuredClone[1]\n\n/**\n * The prototype object used by structuredClone for cloned objects.\n * When we patch structuredClone in jsdom for testing (see https://github.com/jsdom/jsdom/issues/3363),\n * the Object that is used as a prototype for the cloned object is not the same as the Object in\n * the code under test (that comes from jsdom's fake global context). This constant is used in\n * our code to work around this case.\n *\n * This is also the case for Array prototype, but that problem can be worked around with an\n * Array.isArray() check.\n * @internal\n */\nexport const STRUCTURED_CLONE_OBJECT_PROTOTYPE = Object.getPrototypeOf(structuredClone({}))\n","const usedWarnings = new Set<string>()\n\n/**\n * Issues a deprecation warning for deprecated getter properties, advising users to use\n * the equivalent getter method instead. The warning is shown only once per property name.\n *\n * @param name - The name of the deprecated property (e.g., 'viewport')\n *\n * @example\n * ```ts\n * // Inside a class with deprecated property access\n * get viewport() {\n * warnDeprecatedGetter('viewport')\n * return this.getViewport()\n * }\n *\n * // Usage will show: \"[tldraw] Using 'viewport' is deprecated and will be removed...\"\n * // But only the first time it's accessed\n * ```\n *\n * @internal\n */\nexport function warnDeprecatedGetter(name: string) {\n\twarnOnce(\n\t\t`Using '${name}' is deprecated and will be removed in the near future. Please refactor to use 'get${name[0].toLocaleUpperCase()}${name.slice(\n\t\t\t1\n\t\t)}' instead.`\n\t)\n}\n\n/**\n * Issues a warning message to the console, but only once per unique message.\n * Subsequent calls with the same message are ignored, preventing console spam.\n * All messages are prefixed with \"[tldraw]\".\n *\n * @param message - The warning message to display\n *\n * @example\n * ```ts\n * // Warn about deprecated usage\n * function oldFunction() {\n * warnOnce('oldFunction is deprecated, use newFunction instead')\n * // Continue with implementation...\n * }\n *\n * // First call logs: \"[tldraw] oldFunction is deprecated, use newFunction instead\"\n * oldFunction() // Shows warning\n * oldFunction() // No warning (already shown)\n * oldFunction() // No warning (already shown)\n * ```\n *\n * @internal\n */\nexport function warnOnce(message: string) {\n\tif (usedWarnings.has(message)) return\n\n\tusedWarnings.add(message)\n\tconsole.warn(`[tldraw] ${message}`)\n}\n","import { registerDrawLibraryVersion } from './lib/version'\n\nexport { default as isEqual } from 'lodash.isequal'\nexport { default as isEqualWith } from 'lodash.isequalwith'\nexport { default as throttle } from 'lodash.throttle'\nexport { default as uniq } from 'lodash.uniq'\nexport {\n\tareArraysShallowEqual,\n\tcompact,\n\tdedupe,\n\tlast,\n\tmaxBy,\n\tmergeArraysAndReplaceDefaults,\n\tminBy,\n\tpartition,\n\trotateArray,\n} from './lib/array'\nexport { bind } from './lib/bind'\nexport { WeakCache } from './lib/cache'\nexport {\n\tassert,\n\tassertExists,\n\texhaustiveSwitchError,\n\tpromiseWithResolve,\n\tResult,\n\tsleep,\n\ttype ErrorResult,\n\ttype OkResult,\n} from './lib/control'\nexport { debounce } from './lib/debounce'\nexport { annotateError, getErrorAnnotations, type ErrorAnnotations } from './lib/error'\nexport { ExecutionQueue } from './lib/ExecutionQueue'\nexport { FileHelpers } from './lib/file'\nexport { noop, omitFromStackTrace } from './lib/function'\nexport { getHashForBuffer, getHashForObject, getHashForString, lns } from './lib/hash'\nexport { mockUniqueId, restoreUniqueId, uniqueId } from './lib/id'\nexport { getFirstFromIterable } from './lib/iterable'\nexport { LruCache } from './lib/LruCache'\nexport type { JsonArray, JsonObject, JsonPrimitive, JsonValue } from './lib/json-value'\nexport {\n\tDEFAULT_SUPPORT_VIDEO_TYPES,\n\tDEFAULT_SUPPORTED_IMAGE_TYPES,\n\tDEFAULT_SUPPORTED_MEDIA_TYPE_LIST,\n\tDEFAULT_SUPPORTED_MEDIA_TYPES,\n\tMediaHelpers,\n} from './lib/media/media'\nexport { PngHelpers } from './lib/media/png'\nexport { fetch, Image } from './lib/network'\nexport { invLerp, lerp, modulate, rng } from './lib/number'\nexport {\n\tareObjectsShallowEqual,\n\tfilterEntries,\n\tgetChangedKeys,\n\tgetOwnProperty,\n\tgroupBy,\n\thasOwnProperty,\n\tisEqualAllowingForFloatingPointErrors,\n\tmapObjectMapValues,\n\tobjectMapEntries,\n\tobjectMapEntriesIterable,\n\tobjectMapFromEntries,\n\tobjectMapKeys,\n\tobjectMapValues,\n\tomit,\n} from './lib/object'\nexport { measureAverageDuration, measureCbDuration, measureDuration } from './lib/perf'\nexport { PerformanceTracker } from './lib/PerformanceTracker'\nexport {\n\tgetIndexAbove,\n\tgetIndexBelow,\n\tgetIndexBetween,\n\tgetIndices,\n\tgetIndicesAbove,\n\tgetIndicesBelow,\n\tgetIndicesBetween,\n\tsortByIndex,\n\tsortByMaybeIndex,\n\tvalidateIndexKey,\n\tZERO_INDEX_KEY,\n\ttype IndexKey,\n} from './lib/reordering'\nexport { retry } from './lib/retry'\nexport { sortById } from './lib/sort'\nexport {\n\tclearLocalStorage,\n\tclearSessionStorage,\n\tdeleteFromLocalStorage,\n\tdeleteFromSessionStorage,\n\tgetFromLocalStorage,\n\tgetFromSessionStorage,\n\tsetInLocalStorage,\n\tsetInSessionStorage,\n} from './lib/storage'\nexport { stringEnum } from './lib/stringEnum'\nexport { FpsScheduler, fpsThrottle, throttleToNextFrame } from './lib/throttle'\nexport { Timers } from './lib/timers'\nexport {\n\ttype Awaitable,\n\ttype Expand,\n\ttype MakeUndefinedOptional,\n\ttype RecursivePartial,\n\ttype Required,\n} from './lib/types'\nexport { safeParseUrl } from './lib/url'\nexport {\n\tisDefined,\n\tisNativeStructuredClone,\n\tisNonNull,\n\tisNonNullish,\n\tSTRUCTURED_CLONE_OBJECT_PROTOTYPE,\n\tstructuredClone,\n} from './lib/value'\nexport { registerDrawLibraryVersion } from './lib/version'\nexport { warnDeprecatedGetter, warnOnce } from './lib/warn'\n\nregisterDrawLibraryVersion(\n\t(globalThis as any).DRAW_LIBRARY_NAME,\n\t(globalThis as any).DRAW_LIBRARY_VERSION,\n\t(globalThis as any).DRAW_LIBRARY_MODULES\n)\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/version.ts","../src/lib/array.ts","../src/lib/function.ts","../src/lib/control.ts","../src/lib/bind.ts","../src/lib/cache.ts","../src/lib/debounce.ts","../src/lib/error.ts","../src/lib/ExecutionQueue.ts","../src/lib/network.ts","../src/lib/file.ts","../src/lib/hash.ts","../src/lib/id.ts","../src/lib/iterable.ts","../src/lib/LruCache.ts","../src/lib/media/apng.ts","../src/lib/media/avif.ts","../src/lib/media/gif.ts","../src/lib/media/png.ts","../src/lib/media/webp.ts","../src/lib/media/media.ts","../src/lib/number.ts","../src/lib/object.ts","../src/lib/perf.ts","../src/lib/PerformanceTracker.ts","../src/lib/reordering.ts","../src/lib/retry.ts","../src/lib/sort.ts","../src/lib/storage.tsx","../src/lib/stringEnum.ts","../src/lib/throttle.ts","../src/lib/timers.ts","../src/lib/url.ts","../src/lib/value.ts","../src/lib/warn.ts","../src/index.ts"],"names":["crc"],"mappings":"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AAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,QAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,QAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,QAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,QAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,QAAA;AAAA,EACpF,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,SAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,UAAA;AAAA,EA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","file":"index.mjs","sourcesContent":["/**\n * Registers a draw library version.\n * Kept for package entry-point compatibility; version conflict warnings are disabled.\n * @internal\n */\nexport function registerDrawLibraryVersion(name?: string, version?: string, modules?: string) {\n\tif (!name || !version || !modules) {\n\t\tif ((globalThis as any).DRAW_LIBRARY_IS_BUILD) {\n\t\t\tthrow new Error('Missing name/version/module system in built version of tldraw library')\n\t\t}\n\t}\n}\n\n/** @internal */\nexport function clearRegisteredVersionsForTests() {}\n","/**\n * Rotate the contents of an array by a specified offset.\n *\n * Creates a new array with elements shifted to the left by the specified number of positions.\n * Both positive and negative offsets result in left shifts (elements move left, with elements\n * from the front wrapping to the back).\n *\n * @param arr - The array to rotate\n * @param offset - The number of positions to shift left (both positive and negative values shift left)\n * @returns A new array with elements shifted left by the specified offset\n *\n * @example\n * ```ts\n * rotateArray([1, 2, 3, 4], 1) // [2, 3, 4, 1]\n * rotateArray([1, 2, 3, 4], -1) // [2, 3, 4, 1]\n * rotateArray(['a', 'b', 'c'], 2) // ['c', 'a', 'b']\n * ```\n * @public\n */\nexport function rotateArray<T>(arr: T[], offset: number): T[] {\n\tif (arr.length === 0) return []\n\n\t// Based on the test expectations, both positive and negative offsets\n\t// should rotate left (shift elements to the left)\n\tconst normalizedOffset = ((Math.abs(offset) % arr.length) + arr.length) % arr.length\n\n\t// Slice the array at the offset point and concatenate\n\treturn [...arr.slice(normalizedOffset), ...arr.slice(0, normalizedOffset)]\n}\n\n/**\n * Remove duplicate items from an array.\n *\n * Creates a new array with duplicate items removed. Uses strict equality by default,\n * or a custom equality function if provided. Order of first occurrence is preserved.\n *\n * @param input - The array to deduplicate\n * @param equals - Optional custom equality function to compare items (defaults to strict equality)\n * @returns A new array with duplicate items removed\n *\n * @example\n * ```ts\n * dedupe([1, 2, 2, 3, 1]) // [1, 2, 3]\n * dedupe(['a', 'b', 'a', 'c']) // ['a', 'b', 'c']\n *\n * // With custom equality function\n * const objects = [{id: 1}, {id: 2}, {id: 1}]\n * dedupe(objects, (a, b) => a.id === b.id) // [{id: 1}, {id: 2}]\n * ```\n * @public\n */\nexport function dedupe<T>(input: T[], equals?: (a: any, b: any) => boolean): T[] {\n\tconst result: T[] = []\n\tmainLoop: for (const item of input) {\n\t\tfor (const existing of result) {\n\t\t\tif (equals ? equals(item, existing) : item === existing) {\n\t\t\t\tcontinue mainLoop\n\t\t\t}\n\t\t}\n\t\tresult.push(item)\n\t}\n\treturn result\n}\n\n/**\n * Remove null and undefined values from an array.\n *\n * Creates a new array with all null and undefined values filtered out.\n * The resulting array has a refined type that excludes null and undefined.\n *\n * @param arr - The array to compact\n * @returns A new array with null and undefined values removed\n *\n * @example\n * ```ts\n * compact([1, null, 2, undefined, 3]) // [1, 2, 3]\n * compact(['a', null, 'b', undefined]) // ['a', 'b']\n * ```\n * @internal\n */\nexport function compact<T>(arr: T[]): NonNullable<T>[] {\n\treturn arr.filter((i) => i !== undefined && i !== null) as any\n}\n\n/**\n * Get the last element of an array.\n *\n * Returns the last element of an array, or undefined if the array is empty.\n * Works with readonly arrays and preserves the element type.\n *\n * @param arr - The array to get the last element from\n * @returns The last element of the array, or undefined if the array is empty\n *\n * @example\n * ```ts\n * last([1, 2, 3]) // 3\n * last(['a', 'b', 'c']) // 'c'\n * last([]) // undefined\n * ```\n * @internal\n */\nexport function last<T>(arr: readonly T[]): T | undefined {\n\treturn arr[arr.length - 1]\n}\n\n/**\n * Find the item in an array with the minimum value according to a function.\n *\n * Finds the array item that produces the smallest value when passed through\n * the provided function. Returns undefined for empty arrays.\n *\n * @param arr - The array to search\n * @param fn - Function to compute the comparison value for each item\n * @returns The item with the minimum value, or undefined if the array is empty\n *\n * @example\n * ```ts\n * const people = [{name: 'Alice', age: 30}, {name: 'Bob', age: 25}]\n * minBy(people, p => p.age) // {name: 'Bob', age: 25}\n *\n * minBy([3, 1, 4, 1, 5], x => x) // 1\n * minBy([], x => x) // undefined\n * ```\n * @internal\n */\nexport function minBy<T>(arr: readonly T[], fn: (item: T) => number): T | undefined {\n\tlet min: T | undefined\n\tlet minVal = Infinity\n\tfor (const item of arr) {\n\t\tconst val = fn(item)\n\t\tif (val < minVal) {\n\t\t\tmin = item\n\t\t\tminVal = val\n\t\t}\n\t}\n\treturn min\n}\n\n/**\n * Find the item in an array with the maximum value according to a function.\n *\n * Finds the array item that produces the largest value when passed through\n * the provided function. Returns undefined for empty arrays.\n *\n * @param arr - The array to search\n * @param fn - Function to compute the comparison value for each item\n * @returns The item with the maximum value, or undefined if the array is empty\n *\n * @example\n * ```ts\n * const people = [{name: 'Alice', age: 30}, {name: 'Bob', age: 25}]\n * maxBy(people, p => p.age) // {name: 'Alice', age: 30}\n *\n * maxBy([3, 1, 4, 1, 5], x => x) // 5\n * maxBy([], x => x) // undefined\n * ```\n * @internal\n */\nexport function maxBy<T>(arr: readonly T[], fn: (item: T) => number): T | undefined {\n\tlet max: T | undefined\n\tlet maxVal: number = -Infinity\n\tfor (const item of arr) {\n\t\tconst val = fn(item)\n\t\tif (val > maxVal) {\n\t\t\tmax = item\n\t\t\tmaxVal = val\n\t\t}\n\t}\n\treturn max\n}\n\n/**\n * Split an array into two arrays based on a predicate function.\n *\n * Partitions an array into two arrays: one containing items that satisfy\n * the predicate, and another containing items that do not. The original array order is preserved.\n *\n * @param arr - The array to partition\n * @param predicate - The predicate function to test each item\n * @returns A tuple of two arrays: [satisfying items, non-satisfying items]\n *\n * @example\n * ```ts\n * const [evens, odds] = partition([1, 2, 3, 4, 5], x => x % 2 === 0)\n * // evens: [2, 4], odds: [1, 3, 5]\n *\n * const [adults, minors] = partition(\n * [{name: 'Alice', age: 30}, {name: 'Bob', age: 17}],\n * person => person.age >= 18\n * )\n * // adults: [{name: 'Alice', age: 30}], minors: [{name: 'Bob', age: 17}]\n * ```\n * @internal\n */\nexport function partition<T>(arr: T[], predicate: (item: T) => boolean): [T[], T[]] {\n\tconst satisfies: T[] = []\n\tconst doesNotSatisfy: T[] = []\n\tfor (const item of arr) {\n\t\tif (predicate(item)) {\n\t\t\tsatisfies.push(item)\n\t\t} else {\n\t\t\tdoesNotSatisfy.push(item)\n\t\t}\n\t}\n\treturn [satisfies, doesNotSatisfy]\n}\n\n/**\n * Check if two arrays are shallow equal.\n *\n * Compares two arrays for shallow equality by checking if they have the same length\n * and the same elements at each index using Object.is comparison. Returns true if arrays are\n * the same reference, have different lengths, or any elements differ.\n *\n * @param arr1 - First array to compare\n * @param arr2 - Second array to compare\n * @returns True if arrays are shallow equal, false otherwise\n *\n * @example\n * ```ts\n * areArraysShallowEqual([1, 2, 3], [1, 2, 3]) // true\n * areArraysShallowEqual([1, 2, 3], [1, 2, 4]) // false\n * areArraysShallowEqual(['a', 'b'], ['a', 'b']) // true\n * areArraysShallowEqual([1, 2], [1, 2, 3]) // false\n *\n * const obj = {x: 1}\n * areArraysShallowEqual([obj], [obj]) // true (same reference)\n * areArraysShallowEqual([{x: 1}], [{x: 1}]) // false (different objects)\n * ```\n * @internal\n */\nexport function areArraysShallowEqual<T>(arr1: readonly T[], arr2: readonly T[]): boolean {\n\tif (arr1 === arr2) return true\n\tif (arr1.length !== arr2.length) return false\n\tfor (let i = 0; i < arr1.length; i++) {\n\t\tif (!Object.is(arr1[i], arr2[i])) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n/**\n * Merge custom entries with defaults, replacing defaults that have matching keys.\n *\n * Combines two arrays by keeping all custom entries and only the default entries\n * that don't have a matching key in the custom entries. Custom entries always override defaults.\n * The result contains remaining defaults first, followed by all custom entries.\n *\n * @param key - The property name to use as the unique identifier\n * @param customEntries - Array of custom entries that will override defaults\n * @param defaults - Array of default entries\n * @returns A new array with defaults filtered out where custom entries exist, plus all custom entries\n *\n * @example\n * ```ts\n * const defaults = [{type: 'text', value: 'default'}, {type: 'number', value: 0}]\n * const custom = [{type: 'text', value: 'custom'}]\n *\n * mergeArraysAndReplaceDefaults('type', custom, defaults)\n * // Result: [{type: 'number', value: 0}, {type: 'text', value: 'custom'}]\n *\n * const tools = [{id: 'select', name: 'Select'}, {id: 'draw', name: 'Draw'}]\n * const customTools = [{id: 'select', name: 'Custom Select'}]\n *\n * mergeArraysAndReplaceDefaults('id', customTools, tools)\n * // Result: [{id: 'draw', name: 'Draw'}, {id: 'select', name: 'Custom Select'}]\n * ```\n * @internal\n */\nexport function mergeArraysAndReplaceDefaults<\n\tconst Key extends string,\n\tT extends { [K in Key]: string },\n>(key: Key, customEntries: readonly T[], defaults: readonly T[]) {\n\tconst overrideTypes = new Set(customEntries.map((entry) => entry[key]))\n\n\tconst result = []\n\tfor (const defaultEntry of defaults) {\n\t\tif (overrideTypes.has(defaultEntry[key])) continue\n\t\tresult.push(defaultEntry)\n\t}\n\n\tfor (const customEntry of customEntries) {\n\t\tresult.push(customEntry)\n\t}\n\n\treturn result\n}\n","/**\n * When a function is wrapped in `omitFromStackTrace`, if it throws an error the stack trace won't\n * include the function itself or any stack frames above it. Useful for assertion-style function\n * where the error will ideally originate from the call-site rather than within the implementation\n * of the assert fn.\n *\n * Only works in platforms that support `Error.captureStackTrace` (ie v8).\n *\n * @param fn - The function to wrap and exclude from stack traces\n * @returns A wrapped version of the function that omits itself from error stack traces\n * @example\n * ```ts\n * const assertPositive = omitFromStackTrace((value: number) => {\n * if (value <= 0) throw new Error('Value must be positive')\n * return value\n * })\n *\n * assertPositive(-1) // Error stack trace will point to this line, not inside assertPositive\n * ```\n * @internal\n */\nexport function omitFromStackTrace<Args extends Array<unknown>, Return>(\n\tfn: (...args: Args) => Return\n): (...args: Args) => Return {\n\tconst wrappedFn = (...args: Args) => {\n\t\ttry {\n\t\t\treturn fn(...args)\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && Error.captureStackTrace) {\n\t\t\t\tError.captureStackTrace(error, wrappedFn)\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\treturn wrappedFn\n}\n\n/**\n * Does nothing, but it's really really good at it.\n * @internal\n */\nexport const noop: () => void = () => {}\n","import { omitFromStackTrace } from './function'\n\n/**\n * Represents a successful result containing a value.\n *\n * Interface for the success case of a Result type, containing the computed value.\n * Used in conjunction with ErrorResult to create a discriminated union for error handling.\n *\n * @example\n * ```ts\n * const success: OkResult<string> = { ok: true, value: 'Hello World' }\n * if (success.ok) {\n * console.log(success.value) // 'Hello World'\n * }\n * ```\n * @public\n */\nexport interface OkResult<T> {\n\treadonly ok: true\n\treadonly value: T\n}\n/**\n * Represents a failed result containing an error.\n *\n * Interface for the error case of a Result type, containing the error information.\n * Used in conjunction with OkResult to create a discriminated union for error handling.\n *\n * @example\n * ```ts\n * const failure: ErrorResult<string> = { ok: false, error: 'Something went wrong' }\n * if (!failure.ok) {\n * console.error(failure.error) // 'Something went wrong'\n * }\n * ```\n * @public\n */\nexport interface ErrorResult<E> {\n\treadonly ok: false\n\treadonly error: E\n}\n/**\n * A discriminated union type for handling success and error cases.\n *\n * Represents either a successful result with a value or a failed result with an error.\n * This pattern provides type-safe error handling without throwing exceptions. The 'ok' property\n * serves as the discriminant for type narrowing.\n *\n * @example\n * ```ts\n * function divide(a: number, b: number): Result<number, string> {\n * if (b === 0) {\n * return Result.err('Division by zero')\n * }\n * return Result.ok(a / b)\n * }\n *\n * const result = divide(10, 2)\n * if (result.ok) {\n * console.log(`Result: ${result.value}`) // Result: 5\n * } else {\n * console.error(`Error: ${result.error}`)\n * }\n * ```\n * @public\n */\nexport type Result<T, E> = OkResult<T> | ErrorResult<E>\n\n/**\n * Utility object for creating Result instances.\n *\n * Provides factory methods for creating OkResult and ErrorResult instances.\n * This is the preferred way to construct Result values for consistent structure.\n *\n * @example\n * ```ts\n * // Create success result\n * const success = Result.ok(42)\n * // success: OkResult<number> = { ok: true, value: 42 }\n *\n * // Create error result\n * const failure = Result.err('Invalid input')\n * // failure: ErrorResult<string> = { ok: false, error: 'Invalid input' }\n * ```\n * @public\n */\nexport const Result = {\n\t/**\n\t * Create a successful result containing a value.\n\t *\n\t * @param value - The success value to wrap\n\t * @returns An OkResult containing the value\n\t */\n\tok<T>(value: T): OkResult<T> {\n\t\treturn { ok: true, value }\n\t},\n\t/**\n\t * Create a failed result containing an error.\n\t *\n\t * @param error - The error value to wrap\n\t * @returns An ErrorResult containing the error\n\t */\n\terr<E>(error: E): ErrorResult<E> {\n\t\treturn { ok: false, error }\n\t},\n\n\t/**\n\t * Create a successful result containing an array of values.\n\t *\n\t * If any of the results are errors, the returned result will be an error containing the first error.\n\t *\n\t * @param results - The array of results to wrap\n\t * @returns An OkResult containing the array of values\n\t */\n\tall<T>(results: Result<T, any>[]): Result<T[], any> {\n\t\treturn results.every((result) => result.ok)\n\t\t\t? Result.ok(results.map((result) => result.value))\n\t\t\t: Result.err(results.find((result) => !result.ok)?.error)\n\t},\n}\n\n/**\n * Throws an error for unhandled switch cases in exhaustive switch statements.\n *\n * Utility function to ensure exhaustive handling of discriminated unions in switch\n * statements. When called, it indicates a programming error where a case was not handled.\n * The TypeScript 'never' type ensures this function is only reachable if all cases aren't covered.\n *\n * @param value - The unhandled value (typed as 'never' for exhaustiveness checking)\n * @param property - Optional property name to extract from the value for better error messages\n * @returns Never returns (always throws)\n *\n * @example\n * ```ts\n * type Shape = 'circle' | 'square' | 'triangle'\n *\n * function getArea(shape: Shape): number {\n * switch (shape) {\n * case 'circle': return Math.PI * 5 * 5\n * case 'square': return 10 * 10\n * case 'triangle': return 0.5 * 10 * 8\n * default: return exhaustiveSwitchError(shape)\n * }\n * }\n * ```\n * @internal\n */\nexport function exhaustiveSwitchError(value: never, property?: string): never {\n\tconst debugValue =\n\t\tproperty && value && typeof value === 'object' && property in value ? value[property] : value\n\tthrow new Error(`Unknown switch case ${debugValue}`)\n}\n\n/**\n * Assert that a value is truthy, throwing an error if it's not.\n *\n * TypeScript assertion function that throws an error if the provided value is falsy.\n * After this function executes successfully, TypeScript narrows the type to exclude falsy values.\n * Stack trace is omitted from the error for cleaner debugging.\n *\n * @param value - The value to assert as truthy\n * @param message - Optional custom error message\n *\n * @example\n * ```ts\n * const user = getUser() // User | null\n * assert(user, 'User must be logged in')\n * // TypeScript now knows user is non-null\n * console.log(user.name) // Safe to access properties\n * ```\n * @internal\n */\nexport const assert: (value: unknown, message?: string) => asserts value = omitFromStackTrace(\n\t(value, message) => {\n\t\tif (!value) {\n\t\t\tthrow new Error(message || 'Assertion Error')\n\t\t}\n\t}\n)\n\n/**\n * Assert that a value is not null or undefined.\n *\n * Throws an error if the value is null or undefined, otherwise returns the value\n * with a refined type that excludes null and undefined. Stack trace is omitted for cleaner debugging.\n *\n * @param value - The value to check for null/undefined\n * @param message - Optional custom error message\n * @returns The value with null and undefined excluded from the type\n *\n * @example\n * ```ts\n * const element = document.getElementById('my-id') // HTMLElement | null\n * const safeElement = assertExists(element, 'Element not found')\n * // TypeScript now knows safeElement is HTMLElement (not null)\n * safeElement.addEventListener('click', handler) // Safe to call methods\n * ```\n * @internal\n */\nexport const assertExists = omitFromStackTrace(<T>(value: T, message?: string): NonNullable<T> => {\n\t// note that value == null is equivalent to value === null || value === undefined\n\tif (value == null) {\n\t\tthrow new Error(message ?? 'value must be defined')\n\t}\n\treturn value as NonNullable<T>\n})\n\n/**\n * Create a Promise with externally accessible resolve and reject functions.\n *\n * Creates a Promise along with its resolve and reject functions exposed as\n * properties on the returned object. This allows external code to control when the\n * Promise resolves or rejects, useful for coordination between async operations.\n *\n * @returns A Promise object with additional resolve and reject methods\n *\n * @example\n * ```ts\n * const deferred = promiseWithResolve<string>()\n *\n * // Set up the promise consumer\n * deferred.then(value => console.log(`Resolved: ${value}`))\n * deferred.catch(error => console.error(`Rejected: ${error}`))\n *\n * // Later, resolve from external code\n * setTimeout(() => {\n * deferred.resolve('Hello World')\n * }, 1000)\n * ```\n * @internal\n */\nexport function promiseWithResolve<T>(): Promise<T> & {\n\tresolve(value: T): void\n\treject(reason?: any): void\n} {\n\tlet resolve: (value: T) => void\n\tlet reject: (reason?: any) => void\n\tconst promise = new Promise<T>((res, rej) => {\n\t\tresolve = res\n\t\treject = rej\n\t})\n\treturn Object.assign(promise, {\n\t\tresolve: resolve!,\n\t\treject: reject!,\n\t})\n}\n\n/**\n * Create a Promise that resolves after a specified delay.\n *\n * Utility function for introducing delays in async code. Returns a Promise\n * that resolves with undefined after the specified number of milliseconds. Useful for\n * implementing timeouts, rate limiting, or adding delays in testing scenarios.\n *\n * @param ms - The delay in milliseconds\n * @returns A Promise that resolves after the specified delay\n *\n * @example\n * ```ts\n * async function delayedOperation() {\n * console.log('Starting...')\n * await sleep(1000) // Wait 1 second\n * console.log('Done!')\n * }\n *\n * // Can also be used with .then()\n * sleep(500).then(() => {\n * console.log('Half second has passed')\n * })\n * ```\n * @internal\n */\nexport function sleep(ms: number): Promise<void> {\n\t// eslint-disable-next-line no-restricted-globals\n\treturn new Promise((resolve) => setTimeout(resolve, ms))\n}\n","/*!\n * MIT License: https://github.com/NoHomey/bind-decorator/blob/master/License\n * Copyright (c) 2016 Ivo Stratev\n */\n\nimport { assert } from './control'\n\n/**\n * Decorator that binds a method to its class instance (legacy stage-2 TypeScript decorators).\n * When applied to a class method, ensures `this` always refers to the class instance,\n * even when the method is called as a callback or event handler.\n *\n * @param target - The prototype of the class being decorated\n * @param propertyKey - The name of the method being decorated\n * @param descriptor - The property descriptor for the method being decorated\n * @returns The modified property descriptor with bound method access\n * @example\n * ```typescript\n * class MyClass {\n * name = 'example';\n *\n * @bind\n * getName() {\n * return this.name;\n * }\n * }\n *\n * const instance = new MyClass();\n * const callback = instance.getName;\n * console.log(callback()); // 'example' (this is properly bound)\n * ```\n * @public\n */\nexport function bind<T extends (...args: any[]) => any>(\n\ttarget: object,\n\tpropertyKey: string,\n\tdescriptor: TypedPropertyDescriptor<T>\n): TypedPropertyDescriptor<T>\n\n/**\n * Decorator that binds a method to its class instance (TC39 decorators standard).\n * When applied to a class method, ensures `this` always refers to the class instance,\n * even when the method is called as a callback or event handler.\n *\n * @param originalMethod - The original method being decorated\n * @param context - The decorator context containing metadata about the method\n * @example\n * ```typescript\n * class EventHandler {\n * message = 'Hello World';\n *\n * @bind\n * handleClick() {\n * console.log(this.message);\n * }\n * }\n *\n * const handler = new EventHandler();\n * document.addEventListener('click', handler.handleClick); // 'this' is properly bound\n * ```\n * @public\n */\nexport function bind<This extends object, T extends (...args: any[]) => any>(\n\toriginalMethod: T,\n\tcontext: ClassMethodDecoratorContext<This, T>\n): void\n\n/**\n * Universal decorator implementation that handles both legacy stage-2 and TC39 decorator formats.\n * Automatically detects the decorator format based on the number of arguments and binds the\n * decorated method to the class instance, preventing common `this` context issues.\n *\n * @param args - Either legacy decorator arguments (target, propertyKey, descriptor) or TC39 decorator arguments (originalMethod, context)\n * @returns Property descriptor for legacy decorators, or void for TC39 decorators\n * @example\n * ```typescript\n * // Works with both decorator formats\n * class Calculator {\n * multiplier = 2;\n *\n * @bind\n * multiply(value: number) {\n * return value * this.multiplier;\n * }\n * }\n *\n * const calc = new Calculator();\n * const multiplyFn = calc.multiply;\n * console.log(multiplyFn(5)); // 10 (this.multiplier is accessible)\n *\n * // Useful for event handlers and callbacks\n * setTimeout(calc.multiply, 100, 3); // 6\n * ```\n * @public\n */\nexport function bind(\n\t...args: // legacy stage-2 typescript decorators\n\t\t| [_target: object, propertyKey: string, descriptor: PropertyDescriptor]\n\t\t// TC39 decorators\n\t\t| [originalMethod: (...args: any[]) => any, context: ClassMemberDecoratorContext]\n): PropertyDescriptor | void {\n\tif (args.length === 2) {\n\t\tconst [originalMethod, context] = args\n\t\tcontext.addInitializer(function initializeMethod(this: any) {\n\t\t\tassert(Reflect.isExtensible(this), 'Cannot bind to a non-extensible class.')\n\t\t\tconst value = originalMethod.bind(this)\n\t\t\tconst ok = Reflect.defineProperty(this, context.name, {\n\t\t\t\tvalue,\n\t\t\t\twritable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t})\n\t\t\tassert(ok, 'Cannot bind a non-configurable class method.')\n\t\t})\n\t} else {\n\t\tconst [_target, propertyKey, descriptor] = args\n\t\tif (!descriptor || typeof descriptor.value !== 'function') {\n\t\t\tthrow new TypeError(\n\t\t\t\t`Only methods can be decorated with @bind. <${propertyKey}> is not a method!`\n\t\t\t)\n\t\t}\n\n\t\treturn {\n\t\t\tconfigurable: true,\n\t\t\tget(this: any): any {\n\t\t\t\tconst bound = descriptor.value!.bind(this)\n\t\t\t\t// Credits to https://github.com/andreypopp/autobind-decorator for memoizing the result of bind against a symbol on the instance.\n\t\t\t\tObject.defineProperty(this, propertyKey, {\n\t\t\t\t\tvalue: bound,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t})\n\t\t\t\treturn bound\n\t\t\t},\n\t\t}\n\t}\n}\n","/**\n * A lightweight cache implementation using WeakMap for storing key-value pairs.\n *\n * A micro cache that stores computed values associated with object keys.\n * Uses WeakMap internally, which means keys can be garbage collected when no other\n * references exist, and only object keys are supported. Provides lazy computation\n * with memoization.\n *\n * @example\n * ```ts\n * const cache = new WeakCache<User, string>()\n * const user = { id: 1, name: 'Alice' }\n *\n * // Get cached value, computing it if not present\n * const displayName = cache.get(user, (u) => `${u.name} (#${u.id})`)\n * // Returns 'Alice (#1)'\n *\n * // Subsequent calls return cached value\n * const sameName = cache.get(user, (u) => `${u.name} (#${u.id})`)\n * // Returns 'Alice (#1)' without recomputing\n * ```\n * @public\n */\nexport class WeakCache<K extends object, V> {\n\t/**\n\t * The internal WeakMap storage for cached key-value pairs.\n\t *\n\t * @public\n\t */\n\titems = new WeakMap<K, V>()\n\n\t/**\n\t * Get the cached value for a given key, computing it if not already cached.\n\t *\n\t * Retrieves the cached value associated with the given key. If no cached\n\t * value exists, calls the provided callback function to compute the value, stores it\n\t * in the cache, and returns it. Subsequent calls with the same key will return the\n\t * cached value without recomputation.\n\t *\n\t * @param item - The object key to retrieve the cached value for\n\t * @param cb - Callback function that computes the value when not already cached\n\t * @returns The cached value if it exists, otherwise the newly computed value from the callback\n\t *\n\t * @example\n\t * ```ts\n\t * const cache = new WeakCache<HTMLElement, DOMRect>()\n\t * const element = document.getElementById('my-element')!\n\t *\n\t * // First call computes and caches the bounding rect\n\t * const rect1 = cache.get(element, (el) => el.getBoundingClientRect())\n\t *\n\t * // Second call returns cached value\n\t * const rect2 = cache.get(element, (el) => el.getBoundingClientRect())\n\t * // rect1 and rect2 are the same object\n\t * ```\n\t */\n\tget<P extends K>(item: P, cb: (item: P) => V) {\n\t\tif (!this.items.has(item)) {\n\t\t\tthis.items.set(item, cb(item))\n\t\t}\n\n\t\treturn this.items.get(item)!\n\t}\n}\n","import type { Awaitable } from './types'\n\n/**\n * Create a debounced version of a function that delays execution until after a specified wait time.\n *\n * Debouncing ensures that a function is only executed once after a specified delay,\n * even if called multiple times in rapid succession. Each new call resets the timer. The debounced\n * function returns a Promise that resolves with the result of the original function. Includes a\n * cancel method to prevent execution if needed.\n *\n * @param callback - The function to debounce (can be sync or async)\n * @param wait - The delay in milliseconds before executing the function\n * @returns A debounced function that returns a Promise and includes a cancel method\n *\n * @example\n * ```ts\n * // Debounce a search function\n * const searchAPI = (query: string) => fetch(`/search?q=${query}`)\n * const debouncedSearch = debounce(searchAPI, 300)\n *\n * // Multiple rapid calls will only execute the last one after 300ms\n * debouncedSearch('react').then(result => console.log(result))\n * debouncedSearch('react hooks') // This cancels the previous call\n * debouncedSearch('react typescript') // Only this will execute\n *\n * // Cancel pending execution\n * debouncedSearch.cancel()\n *\n * // With async/await\n * const saveData = debounce(async (data: any) => {\n * return await api.save(data)\n * }, 1000)\n *\n * const result = await saveData({name: 'John'})\n * ```\n *\n * @public\n * @see source - https://gist.github.com/ca0v/73a31f57b397606c9813472f7493a940\n */\nexport function debounce<T extends unknown[], U>(\n\tcallback: (...args: T) => Awaitable<U>,\n\twait: number\n) {\n\tlet state:\n\t\t| undefined\n\t\t| {\n\t\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\t\ttimeout: ReturnType<typeof setTimeout>\n\t\t\t\tpromise: Promise<U>\n\t\t\t\tresolve(value: U | PromiseLike<U>): void\n\t\t\t\treject(value: any): void\n\t\t\t\tlatestArgs: T\n\t\t } = undefined\n\n\tconst fn = (...args: T): Promise<U> => {\n\t\tif (!state) {\n\t\t\tstate = {} as any\n\t\t\tstate!.promise = new Promise((resolve, reject) => {\n\t\t\t\tstate!.resolve = resolve\n\t\t\t\tstate!.reject = reject\n\t\t\t})\n\t\t}\n\t\tclearTimeout(state!.timeout)\n\t\tstate!.latestArgs = args\n\t\t// It's up to the consumer of debounce to call `cancel`\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tstate!.timeout = setTimeout(() => {\n\t\t\tconst s = state!\n\t\t\tstate = undefined\n\t\t\ttry {\n\t\t\t\ts.resolve(callback(...s.latestArgs))\n\t\t\t} catch (e) {\n\t\t\t\ts.reject(e)\n\t\t\t}\n\t\t}, wait)\n\n\t\treturn state!.promise\n\t}\n\tfn.cancel = () => {\n\t\tif (!state) return\n\t\tclearTimeout(state.timeout)\n\t\tstate = undefined\n\t}\n\treturn fn\n}\n","/** @public */\nexport interface ErrorAnnotations {\n\ttags: Record<string, number | string | boolean | bigint | symbol | null | undefined>\n\textras: Record<string, unknown>\n}\n\nconst annotationsByError = new WeakMap<object, ErrorAnnotations>()\n\n/**\n * Annotate an error with tags and additional data. Annotations won't overwrite existing ones.\n * Retrieve them with `getErrorAnnotations`.\n *\n * @param error - The error object to annotate\n * @param annotations - Partial annotations to add (tags and/or extras)\n * @returns void\n * @example\n * ```ts\n * const error = new Error('Something went wrong')\n * annotateError(error, {\n * tags: { userId: '123', operation: 'save' },\n * extras: { timestamp: Date.now() }\n * })\n * ```\n *\n * @internal\n */\nexport function annotateError(error: unknown, annotations: Partial<ErrorAnnotations>) {\n\tif (typeof error !== 'object' || error === null) return\n\n\tlet currentAnnotations = annotationsByError.get(error)\n\tif (!currentAnnotations) {\n\t\tcurrentAnnotations = { tags: {}, extras: {} }\n\t\tannotationsByError.set(error, currentAnnotations)\n\t}\n\n\tif (annotations.tags) {\n\t\tcurrentAnnotations.tags = {\n\t\t\t...currentAnnotations.tags,\n\t\t\t...annotations.tags,\n\t\t}\n\t}\n\tif (annotations.extras) {\n\t\tcurrentAnnotations.extras = {\n\t\t\t...currentAnnotations.extras,\n\t\t\t...annotations.extras,\n\t\t}\n\t}\n}\n\n/**\n * Retrieve annotations that have been added to an error object.\n *\n * @param error - The error object to get annotations from\n * @returns The error annotations (tags and extras) or empty objects if none exist\n * @example\n * ```ts\n * const error = new Error('Something went wrong')\n * annotateError(error, { tags: { userId: '123' } })\n * const annotations = getErrorAnnotations(error)\n * console.log(annotations.tags.userId) // '123'\n * ```\n *\n * @internal\n */\nexport function getErrorAnnotations(error: Error): ErrorAnnotations {\n\treturn annotationsByError.get(error) ?? { tags: {}, extras: {} }\n}\n","import { sleep } from './control'\n\n/**\n * A queue that executes tasks sequentially with optional delay between tasks.\n *\n * ExecutionQueue ensures that tasks are executed one at a time in the order they were added,\n * with an optional timeout delay between each task execution. This is useful for rate limiting,\n * preventing race conditions, or controlling the flow of asynchronous operations.\n *\n * @example\n * ```ts\n * // Create a queue with 100ms delay between tasks\n * const queue = new ExecutionQueue(100)\n *\n * // Add tasks to the queue\n * const result1 = await queue.push(() => fetch('/api/data'))\n * const result2 = await queue.push(async () => {\n * const data = await processData()\n * return data\n * })\n *\n * // Check if queue is empty\n * if (queue.isEmpty()) {\n * console.log('All tasks completed')\n * }\n *\n * // Clean up\n * queue.close()\n * ```\n *\n * @internal\n */\nexport class ExecutionQueue {\n\tprivate queue: (() => Promise<any>)[] = []\n\tprivate running = false\n\n\t/**\n\t * Creates a new ExecutionQueue.\n\t *\n\t * Creates a new execution queue that will process tasks sequentially.\n\t * If a timeout is provided, there will be a delay between each task execution,\n\t * which is useful for rate limiting or controlling execution flow.\n\t *\n\t * timeout - Optional delay in milliseconds between task executions\n\t * @example\n\t * ```ts\n\t * // Create queue without delay\n\t * const fastQueue = new ExecutionQueue()\n\t *\n\t * // Create queue with 500ms delay between tasks\n\t * const slowQueue = new ExecutionQueue(500)\n\t * ```\n\t */\n\tconstructor(private readonly timeout?: number) {}\n\n\t/**\n\t * Checks if the queue is empty and not currently running a task.\n\t *\n\t * Determines whether the execution queue has completed all tasks and is idle.\n\t * Returns true only when there are no pending tasks in the queue AND no task is currently being executed.\n\t *\n\t * @returns True if the queue has no pending tasks and is not currently executing\n\t * @example\n\t * ```ts\n\t * const queue = new ExecutionQueue()\n\t *\n\t * console.log(queue.isEmpty()) // true - queue is empty\n\t *\n\t * queue.push(() => console.log('task'))\n\t * console.log(queue.isEmpty()) // false - task is running/pending\n\t * ```\n\t */\n\tisEmpty() {\n\t\treturn this.queue.length === 0 && !this.running\n\t}\n\n\tprivate async run() {\n\t\tif (this.running) return\n\t\ttry {\n\t\t\tthis.running = true\n\t\t\twhile (this.queue.length) {\n\t\t\t\tconst task = this.queue.shift()!\n\t\t\t\tawait task()\n\t\t\t\tif (this.timeout) {\n\t\t\t\t\tawait sleep(this.timeout)\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\t// this try/finally should not be needed because the tasks don't throw\n\t\t\t// but better safe than sorry\n\t\t\t// console.log('\\n\\n\\nrunning false\\n\\n\\n')\n\t\t\tthis.running = false\n\t\t}\n\t}\n\n\t/**\n\t * Adds a task to the queue and returns a promise that resolves with the task's result.\n\t *\n\t * Enqueues a task for sequential execution. The task will be executed after all\n\t * previously queued tasks have completed. If a timeout was specified in the constructor,\n\t * there will be a delay between this task and the next one.\n\t *\n\t * @param task - The function to execute (can be sync or async)\n\t * @returns Promise that resolves with the task's return value\n\t * @example\n\t * ```ts\n\t * const queue = new ExecutionQueue(100)\n\t *\n\t * // Add async task\n\t * const result = await queue.push(async () => {\n\t * const response = await fetch('/api/data')\n\t * return response.json()\n\t * })\n\t *\n\t * // Add sync task\n\t * const number = await queue.push(() => 42)\n\t * ```\n\t */\n\tasync push<T>(task: () => T): Promise<Awaited<T>> {\n\t\treturn new Promise<Awaited<T>>((resolve, reject) => {\n\t\t\tthis.queue.push(() => Promise.resolve(task()).then(resolve).catch(reject))\n\t\t\tthis.run()\n\t\t})\n\t}\n\n\t/**\n\t * Clears all pending tasks from the queue.\n\t *\n\t * Immediately removes all pending tasks from the queue. Any currently\n\t * running task will complete normally, but no additional tasks will be executed.\n\t * This method does not wait for the current task to finish.\n\t *\n\t * @returns void\n\t * @example\n\t * ```ts\n\t * const queue = new ExecutionQueue()\n\t *\n\t * // Add several tasks\n\t * queue.push(() => console.log('task 1'))\n\t * queue.push(() => console.log('task 2'))\n\t * queue.push(() => console.log('task 3'))\n\t *\n\t * // Clear all pending tasks\n\t * queue.close()\n\t * // Only 'task 1' will execute if it was already running\n\t * ```\n\t */\n\tclose() {\n\t\tthis.queue = []\n\t}\n}\n","/**\n * Just a wrapper around `window.fetch` that sets the `referrerPolicy` to `strict-origin-when-cross-origin`.\n *\n * @param input - A Request object or string containing the URL to fetch\n * @param init - Optional request initialization options\n * @returns Promise that resolves to the Response object\n * @internal\n */\nexport async function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n\t// eslint-disable-next-line tldraw/no-restricted-properties\n\treturn window.fetch(input, {\n\t\t// We want to make sure that the referrer is not sent to other domains.\n\t\treferrerPolicy: 'strict-origin-when-cross-origin',\n\t\t...init,\n\t})\n}\n\n/**\n * Just a wrapper around `new Image`, and yeah, it's a bit strange that it's in the network.ts file\n * but the main concern here is the referrerPolicy and setting it correctly.\n *\n * @param width - Optional width for the image element\n * @param height - Optional height for the image element\n * @returns HTMLImageElement with referrerPolicy set to 'strict-origin-when-cross-origin'\n * @internal\n */\nexport const Image = (width?: number, height?: number) => {\n\t// eslint-disable-next-line tldraw/no-restricted-properties\n\tconst img = new window.Image(width, height)\n\timg.referrerPolicy = 'strict-origin-when-cross-origin'\n\treturn img\n}\n","import { fetch } from './network'\n\n/**\n * Utility class providing helper methods for file and blob operations.\n *\n * FileHelpers contains static methods for common file operations including\n * URL fetching, format conversion, and MIME type manipulation. All methods work with\n * web APIs like fetch, FileReader, and Blob/File objects.\n *\n * @example\n * ```ts\n * // Fetch and convert a remote image to data URL\n * const dataUrl = await FileHelpers.urlToDataUrl('https://example.com/image.png')\n *\n * // Convert user-selected file to text\n * const text = await FileHelpers.blobToText(userFile)\n *\n * // Change file MIME type\n * const newFile = FileHelpers.rewriteMimeType(originalFile, 'application/json')\n * ```\n *\n * @public\n */\nexport class FileHelpers {\n\t/**\n\t * Converts a URL to an ArrayBuffer by fetching the resource.\n\t *\n\t * Fetches the resource at the given URL and returns its content as an ArrayBuffer.\n\t * This is useful for loading binary data like images, videos, or other file types.\n\t *\n\t * @param url - The URL of the file to fetch\n\t * @returns Promise that resolves to the file content as an ArrayBuffer\n\t * @example\n\t * ```ts\n\t * const buffer = await FileHelpers.urlToArrayBuffer('https://example.com/image.png')\n\t * console.log(buffer.byteLength) // Size of the file in bytes\n\t * ```\n\t * @public\n\t */\n\tstatic async urlToArrayBuffer(url: string) {\n\t\tconst response = await fetch(url)\n\t\treturn await response.arrayBuffer()\n\t}\n\n\t/**\n\t * Converts a URL to a Blob by fetching the resource.\n\t *\n\t * Fetches the resource at the given URL and returns its content as a Blob object.\n\t * Blobs are useful for handling file data in web applications.\n\t *\n\t * @param url - The URL of the file to fetch\n\t * @returns Promise that resolves to the file content as a Blob\n\t * @example\n\t * ```ts\n\t * const blob = await FileHelpers.urlToBlob('https://example.com/document.pdf')\n\t * console.log(blob.type) // 'application/pdf'\n\t * console.log(blob.size) // Size in bytes\n\t * ```\n\t * @public\n\t */\n\tstatic async urlToBlob(url: string) {\n\t\tconst response = await fetch(url)\n\t\treturn await response.blob()\n\t}\n\n\t/**\n\t * Converts a URL to a data URL by fetching the resource.\n\t *\n\t * Fetches the resource at the given URL and converts it to a base64-encoded data URL.\n\t * If the URL is already a data URL, it returns the URL unchanged. This is useful for embedding\n\t * resources directly in HTML or CSS.\n\t *\n\t * @param url - The URL of the file to convert, or an existing data URL\n\t * @returns Promise that resolves to a data URL string\n\t * @example\n\t * ```ts\n\t * const dataUrl = await FileHelpers.urlToDataUrl('https://example.com/image.jpg')\n\t * // Returns: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEA...'\n\t *\n\t * const existing = await FileHelpers.urlToDataUrl('data:text/plain;base64,SGVsbG8=')\n\t * // Returns the same data URL unchanged\n\t * ```\n\t * @public\n\t */\n\tstatic async urlToDataUrl(url: string) {\n\t\tif (url.startsWith('data:')) return url\n\t\tconst blob = await FileHelpers.urlToBlob(url)\n\t\treturn await FileHelpers.blobToDataUrl(blob)\n\t}\n\n\t/**\n\t * Convert a Blob to a base64 encoded data URL.\n\t *\n\t * Converts a Blob object to a base64-encoded data URL using the FileReader API.\n\t * This is useful for displaying images or embedding file content directly in HTML.\n\t *\n\t * @param file - The Blob object to convert\n\t * @returns Promise that resolves to a base64-encoded data URL string\n\t * @example\n\t * ```ts\n\t * const blob = new Blob(['Hello World'], { type: 'text/plain' })\n\t * const dataUrl = await FileHelpers.blobToDataUrl(blob)\n\t * // Returns: 'data:text/plain;base64,SGVsbG8gV29ybGQ='\n\t *\n\t * // With an image file\n\t * const imageDataUrl = await FileHelpers.blobToDataUrl(myImageFile)\n\t * // Can be used directly in img src attribute\n\t * ```\n\t * @public\n\t */\n\tstatic async blobToDataUrl(file: Blob): Promise<string> {\n\t\treturn await new Promise((resolve, reject) => {\n\t\t\tif (file) {\n\t\t\t\tconst reader = new FileReader()\n\t\t\t\treader.onload = () => resolve(reader.result as string)\n\t\t\t\treader.onerror = (error) => reject(error)\n\t\t\t\treader.onabort = (error) => reject(error)\n\t\t\t\treader.readAsDataURL(file)\n\t\t\t}\n\t\t})\n\t}\n\n\t/**\n\t * Convert a Blob to a unicode text string.\n\t *\n\t * Reads the content of a Blob object as a UTF-8 text string using the FileReader API.\n\t * This is useful for reading text files or extracting text content from blobs.\n\t *\n\t * @param file - The Blob object to convert to text\n\t * @returns Promise that resolves to the text content as a string\n\t * @example\n\t * ```ts\n\t * const textBlob = new Blob(['Hello World'], { type: 'text/plain' })\n\t * const text = await FileHelpers.blobToText(textBlob)\n\t * console.log(text) // 'Hello World'\n\t *\n\t * // With a text file from user input\n\t * const content = await FileHelpers.blobToText(myTextFile)\n\t * console.log(content) // File content as string\n\t * ```\n\t * @public\n\t */\n\tstatic async blobToText(file: Blob): Promise<string> {\n\t\treturn await new Promise((resolve, reject) => {\n\t\t\tif (file) {\n\t\t\t\tconst reader = new FileReader()\n\t\t\t\treader.onload = () => resolve(reader.result as string)\n\t\t\t\treader.onerror = (error) => reject(error)\n\t\t\t\treader.onabort = (error) => reject(error)\n\t\t\t\treader.readAsText(file)\n\t\t\t}\n\t\t})\n\t}\n\n\t/**\n\t * Creates a new Blob or File with a different MIME type.\n\t *\n\t * Creates a copy of the given Blob or File with a new MIME type while preserving\n\t * all other properties. If the current MIME type already matches the new one, returns the\n\t * original object unchanged. For File objects, preserves the filename.\n\t *\n\t * @param blob - The Blob or File object to modify\n\t * @param newMimeType - The new MIME type to assign\n\t * @returns A new Blob or File with the updated MIME type\n\t * @example\n\t * ```ts\n\t * // Change a generic blob to a specific image type\n\t * const blob = new Blob([imageData])\n\t * const imageBlob = FileHelpers.rewriteMimeType(blob, 'image/png')\n\t *\n\t * // Change a file's MIME type while preserving filename\n\t * const file = new File([data], 'document.txt', { type: 'text/plain' })\n\t * const jsonFile = FileHelpers.rewriteMimeType(file, 'application/json')\n\t * console.log(jsonFile.name) // 'document.txt' (preserved)\n\t * console.log(jsonFile.type) // 'application/json' (updated)\n\t * ```\n\t * @public\n\t */\n\tstatic rewriteMimeType(blob: Blob, newMimeType: string): Blob\n\tstatic rewriteMimeType(blob: File, newMimeType: string): File\n\tstatic rewriteMimeType(blob: Blob | File, newMimeType: string): Blob | File {\n\t\tif (blob.type === newMimeType) return blob\n\t\tif (blob instanceof File) {\n\t\t\treturn new File([blob], blob.name, { type: newMimeType })\n\t\t}\n\t\treturn new Blob([blob], { type: newMimeType })\n\t}\n}\n","/**\n * Hash a string using the FNV-1a algorithm.\n *\n * Generates a deterministic hash value for a given string using a variant of the FNV-1a\n * (Fowler-Noll-Vo) algorithm. The hash is returned as a string representation of a 32-bit integer.\n *\n * @param string - The input string to hash\n * @returns A string representation of the 32-bit hash value\n * @example\n * ```ts\n * const hash = getHashForString('hello world')\n * console.log(hash) // '-862545276'\n *\n * // Same input always produces same hash\n * const hash2 = getHashForString('hello world')\n * console.log(hash === hash2) // true\n * ```\n * @public\n */\nexport function getHashForString(string: string) {\n\tlet hash = 0\n\tfor (let i = 0; i < string.length; i++) {\n\t\thash = (hash << 5) - hash + string.charCodeAt(i)\n\t\thash |= 0 // Convert to 32bit integer\n\t}\n\treturn hash + ''\n}\n\n/**\n * Hash an object by converting it to JSON and then hashing the resulting string.\n *\n * Converts the object to a JSON string using JSON.stringify and then applies the same\n * hashing algorithm as getHashForString. Useful for creating consistent hash values\n * for objects, though the hash depends on JSON serialization order.\n *\n * @param obj - The object to hash (any JSON-serializable value)\n * @returns A string representation of the 32-bit hash value\n * @example\n * ```ts\n * const hash1 = getHashForObject({ name: 'John', age: 30 })\n * const hash2 = getHashForObject({ name: 'John', age: 30 })\n * console.log(hash1 === hash2) // true\n *\n * // Arrays work too\n * const arrayHash = getHashForObject([1, 2, 3, 'hello'])\n * console.log(arrayHash) // '-123456789'\n * ```\n * @public\n */\nexport function getHashForObject(obj: any) {\n\treturn getHashForString(JSON.stringify(obj))\n}\n\n/**\n * Hash an ArrayBuffer using the FNV-1a algorithm.\n *\n * Generates a deterministic hash value for binary data stored in an ArrayBuffer.\n * Processes the buffer byte by byte using the same hashing algorithm as getHashForString.\n * Useful for creating consistent identifiers for binary data like images or files.\n *\n * @param buffer - The ArrayBuffer containing binary data to hash\n * @returns A string representation of the 32-bit hash value\n * @example\n * ```ts\n * // Hash some binary data\n * const data = new Uint8Array([1, 2, 3, 4, 5])\n * const hash = getHashForBuffer(data.buffer)\n * console.log(hash) // '123456789'\n *\n * // Hash image file data\n * const fileBuffer = await file.arrayBuffer()\n * const fileHash = getHashForBuffer(fileBuffer)\n * console.log(fileHash) // Unique hash for the file\n * ```\n * @public\n */\nexport function getHashForBuffer(buffer: ArrayBuffer) {\n\tconst view = new DataView(buffer)\n\tlet hash = 0\n\tfor (let i = 0; i < view.byteLength; i++) {\n\t\thash = (hash << 5) - hash + view.getUint8(i)\n\t\thash |= 0 // Convert to 32bit integer\n\t}\n\treturn hash + ''\n}\n\n/**\n * Applies a string transformation algorithm that rearranges and modifies characters.\n *\n * Performs a series of character manipulations on the input string including\n * character repositioning through splicing operations and numeric character transformations.\n * This appears to be a custom encoding/obfuscation function.\n *\n * @param str - The input string to transform\n * @returns The transformed string after applying all manipulations\n * @example\n * ```ts\n * const result = lns('hello123')\n * console.log(result) // Transformed string (exact output depends on algorithm)\n *\n * // Can be used for simple string obfuscation\n * const obfuscated = lns('sensitive-data')\n * console.log(obfuscated) // Obfuscated version\n * ```\n * @public\n */\nexport function lns(str: string) {\n\tconst result = str.split('')\n\tresult.push(...result.splice(0, Math.round(result.length / 5)))\n\tresult.push(...result.splice(0, Math.round(result.length / 4)))\n\tresult.push(...result.splice(0, Math.round(result.length / 3)))\n\tresult.push(...result.splice(0, Math.round(result.length / 2)))\n\treturn result\n\t\t.reverse()\n\t\t.map((n) => (+n ? (+n < 5 ? 5 + +n : +n > 5 ? +n - 5 : n) : n))\n\t\t.join('')\n}\n","/*!\n * MIT License: https://github.com/ai/nanoid/blob/main/LICENSE\n * Modified code originally from <https://github.com/ai/nanoid>\n * Copyright 2017 Andrey Sitnik <andrey@sitnik.ru>\n *\n * `nanoid` is currently only distributed as an ES module. Some tools (jest, playwright) don't\n * properly support ESM-only code yet, and tldraw itself is distributed as both an ES module and a\n * CommonJS module. By including nanoid here, we can make sure it works well in every environment\n * where tldraw is used. We can also remove some unused features like custom alphabets.\n */\n\n// all environments that tldraw runs in (browser, workers, recent node versions) have global\n// `crypto`\nconst crypto = globalThis.crypto\n\n// This alphabet uses `A-Za-z0-9_-` symbols.\n// The order of characters is optimized for better gzip and brotli compression.\n// Same as in non-secure/index.js\nconst urlAlphabet = 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\n\n// It is best to make fewer, larger requests to the crypto module to\n// avoid system call overhead. So, random numbers are generated in a\n// pool. The pool is a Buffer that is larger than the initial random\n// request size by this multiplier. The pool is enlarged if subsequent\n// requests exceed the maximum buffer size.\nconst POOL_SIZE_MULTIPLIER = 128\nlet pool: Uint8Array, poolOffset: number\n\nfunction fillPool(bytes: number) {\n\tif (!pool || pool.length < bytes) {\n\t\tpool = new Uint8Array(bytes * POOL_SIZE_MULTIPLIER)\n\t\tcrypto.getRandomValues(pool)\n\t\tpoolOffset = 0\n\t} else if (poolOffset + bytes > pool.length) {\n\t\tcrypto.getRandomValues(pool)\n\t\tpoolOffset = 0\n\t}\n\tpoolOffset += bytes\n}\n\nfunction nanoid(size = 21) {\n\t// `-=` convert `size` to number to prevent `valueOf` abusing\n\tfillPool((size -= 0))\n\tlet id = ''\n\t// We are reading directly from the random pool to avoid creating new array\n\tfor (let i = poolOffset - size; i < poolOffset; i++) {\n\t\t// It is incorrect to use bytes exceeding the alphabet size.\n\t\t// The following mask reduces the random byte in the 0-255 value\n\t\t// range to the 0-63 value range. Therefore, adding hacks, such\n\t\t// as empty string fallback or magic numbers, is unnecessary because\n\t\t// the bitmask trims bytes down to the alphabet size.\n\t\tid += urlAlphabet[pool[i] & 63]\n\t}\n\treturn id\n}\n\nlet impl = nanoid\n/**\n * Mock the unique ID generator with a custom implementation for testing.\n *\n * Replaces the internal ID generation function with a custom one. This is useful\n * for testing scenarios where you need predictable or deterministic IDs.\n *\n * @param fn - The mock function that should return a string ID. Takes optional size parameter.\n * @example\n * ```ts\n * // Mock with predictable IDs for testing\n * mockUniqueId((size = 21) => 'test-id-' + size)\n * console.log(uniqueId()) // 'test-id-21'\n * console.log(uniqueId(10)) // 'test-id-10'\n *\n * // Restore original implementation when done\n * restoreUniqueId()\n * ```\n * @internal\n */\nexport function mockUniqueId(fn: (size?: number) => string) {\n\timpl = fn\n}\n\n/**\n * Restore the original unique ID generator after mocking.\n *\n * Resets the ID generation function back to the original nanoid implementation.\n * This should be called after testing to restore normal ID generation behavior.\n *\n * @example\n * ```ts\n * // After mocking for tests\n * mockUniqueId(() => 'mock-id')\n *\n * // Restore original behavior\n * restoreUniqueId()\n * console.log(uniqueId()) // Now generates real random IDs again\n * ```\n * @internal\n */\nexport function restoreUniqueId() {\n\timpl = nanoid\n}\n\n/**\n * Generate a unique ID using a modified nanoid algorithm.\n *\n * Generates a cryptographically secure random string ID using URL-safe characters.\n * The default size is 21 characters, which provides a good balance of uniqueness\n * and brevity. Uses the global crypto API for secure random number generation.\n *\n * @param size - Optional length of the generated ID (defaults to 21 characters)\n * @returns A unique string identifier\n * @example\n * ```ts\n * // Generate default 21-character ID\n * const id = uniqueId()\n * console.log(id) // 'V1StGXR8_Z5jdHi6B-myT'\n *\n * // Generate shorter ID\n * const shortId = uniqueId(10)\n * console.log(shortId) // 'V1StGXR8_Z'\n *\n * // Generate longer ID\n * const longId = uniqueId(32)\n * console.log(longId) // 'V1StGXR8_Z5jdHi6B-myTVKahvjdx...'\n * ```\n * @public\n */\nexport function uniqueId(size?: number): string {\n\treturn impl(size)\n}\n","/**\n * Get the first item from an iterable Set or Map.\n *\n * @param value - The iterable Set or Map to get the first item from\n * @returns The first value from the Set or Map\n * @example\n * ```ts\n * const A = getFirstFromIterable(new Set([1, 2, 3])) // 1\n * const B = getFirstFromIterable(\n * \tnew Map([\n * \t\t['a', 1],\n * \t\t['b', 2],\n * \t])\n * ) // 1\n * ```\n * @public\n */\nexport function getFirstFromIterable<T = unknown>(set: Set<T> | Map<any, T>): T {\n\treturn set.values().next().value!\n}\n","/** Simple LRU cache backed by a Map's insertion-order iteration. @public */\nexport class LruCache<K, V> {\n\tprivate map = new Map<K, V>()\n\tconstructor(private maxSize: number) {}\n\n\tget(key: K): V | undefined {\n\t\tif (!this.map.has(key)) return undefined\n\t\tconst value = this.map.get(key)!\n\t\t// Move to most-recent position\n\t\tthis.map.delete(key)\n\t\tthis.map.set(key, value)\n\t\treturn value\n\t}\n\n\tset(key: K, value: V): void {\n\t\tif (this.map.has(key)) this.map.delete(key)\n\t\tthis.map.set(key, value)\n\t\tif (this.map.size > this.maxSize) {\n\t\t\t// Evict oldest entry\n\t\t\tthis.map.delete(this.map.keys().next().value!)\n\t\t}\n\t}\n\n\thas(key: K): boolean {\n\t\treturn this.map.has(key)\n\t}\n\n\t// eslint-disable-next-line tldraw/no-setter-getter\n\tget size(): number {\n\t\treturn this.map.size\n\t}\n}\n","/*!\n * MIT License: https://github.com/vHeemstra/is-apng/blob/main/license\n * Copyright (c) Philip van Heemstra\n */\n\n/**\n * Determines whether an ArrayBuffer contains an animated PNG (APNG) image.\n *\n * This function checks if the provided buffer contains a valid PNG file with animation\n * control chunks (acTL) that precede the image data chunks (IDAT), which indicates\n * it's an animated PNG rather than a static PNG.\n *\n * @param buffer - The ArrayBuffer containing the image data to analyze\n * @returns True if the buffer contains an animated PNG, false otherwise\n *\n * @example\n * ```typescript\n * // Check if an uploaded file contains an animated PNG\n * if (file.type === 'image/apng') {\n * const isAnimated = isApngAnimated(await file.arrayBuffer())\n * console.log(isAnimated ? 'Animated PNG' : 'Static PNG')\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Use with fetch to check remote images\n * const response = await fetch('image.png')\n * const buffer = await response.arrayBuffer()\n * const hasAnimation = isApngAnimated(buffer)\n * ```\n *\n * @public\n */\nexport function isApngAnimated(buffer: ArrayBuffer): boolean {\n\tconst view = new Uint8Array(buffer)\n\n\tif (\n\t\t!view ||\n\t\t!((typeof Buffer !== 'undefined' && Buffer.isBuffer(view)) || view instanceof Uint8Array) ||\n\t\tview.length < 16\n\t) {\n\t\treturn false\n\t}\n\n\tconst isPNG =\n\t\tview[0] === 0x89 &&\n\t\tview[1] === 0x50 &&\n\t\tview[2] === 0x4e &&\n\t\tview[3] === 0x47 &&\n\t\tview[4] === 0x0d &&\n\t\tview[5] === 0x0a &&\n\t\tview[6] === 0x1a &&\n\t\tview[7] === 0x0a\n\n\tif (!isPNG) {\n\t\treturn false\n\t}\n\n\t/**\n\t * Returns the index of the first occurrence of a string pattern in a Uint8Array, or -1 if not found.\n\t *\n\t * Searches for a string pattern by decoding chunks of the byte array to UTF-8 text and using\n\t * regular expression matching. Handles cases where the pattern might be split across chunk boundaries.\n\t *\n\t * @param haystack - The Uint8Array to search in\n\t * @param needle - The string or RegExp pattern to locate\n\t * @param fromIndex - The array index at which to begin the search\n\t * @param upToIndex - The array index up to which to search (optional, defaults to array end)\n\t * @param chunksize - Size of the chunks used when searching (default 1024 bytes)\n\t * @returns The index position of the first match, or -1 if not found\n\t */\n\tfunction indexOfSubstring(\n\t\thaystack: Uint8Array,\n\t\tneedle: string | RegExp,\n\t\tfromIndex: number,\n\t\tupToIndex?: number,\n\t\tchunksize = 1024 /* Bytes */\n\t) {\n\t\t/**\n\t\t * Adopted from: https://stackoverflow.com/a/67771214/2142071\n\t\t */\n\n\t\tif (!needle) {\n\t\t\treturn -1\n\t\t}\n\t\tneedle = new RegExp(needle, 'g')\n\n\t\t// The needle could get split over two chunks.\n\t\t// So, at every chunk we prepend the last few characters\n\t\t// of the last chunk.\n\t\tconst needle_length = needle.source.length\n\t\tconst decoder = new TextDecoder()\n\n\t\t// Handle search offset in line with\n\t\t// `Array.prototype.indexOf()` and `TypedArray.prototype.subarray()`.\n\t\tconst full_haystack_length = haystack.length\n\t\tif (typeof upToIndex === 'undefined') {\n\t\t\tupToIndex = full_haystack_length\n\t\t}\n\t\tif (fromIndex >= full_haystack_length || upToIndex <= 0 || fromIndex >= upToIndex) {\n\t\t\treturn -1\n\t\t}\n\t\thaystack = haystack.subarray(fromIndex, upToIndex)\n\n\t\tlet position = -1\n\t\tlet current_index = 0\n\t\tlet full_length = 0\n\t\tlet needle_buffer = ''\n\n\t\touter: while (current_index < haystack.length) {\n\t\t\tconst next_index = current_index + chunksize\n\t\t\t// subarray doesn't copy\n\t\t\tconst chunk = haystack.subarray(current_index, next_index)\n\t\t\tconst decoded = decoder.decode(chunk, { stream: true })\n\n\t\t\tconst text = needle_buffer + decoded\n\n\t\t\tlet match: RegExpExecArray | null\n\t\t\tlet last_index = -1\n\t\t\twhile ((match = needle.exec(text)) !== null) {\n\t\t\t\tlast_index = match.index - needle_buffer.length\n\t\t\t\tposition = full_length + last_index\n\t\t\t\tbreak outer\n\t\t\t}\n\n\t\t\tcurrent_index = next_index\n\t\t\tfull_length += decoded.length\n\n\t\t\t// Check that the buffer doesn't itself include the needle\n\t\t\t// this would cause duplicate finds (we could also use a Set to avoid that).\n\t\t\tconst needle_index =\n\t\t\t\tlast_index > -1 ? last_index + needle_length : decoded.length - needle_length\n\t\t\tneedle_buffer = decoded.slice(needle_index)\n\t\t}\n\n\t\t// Correct for search offset.\n\t\tif (position >= 0) {\n\t\t\tposition += fromIndex >= 0 ? fromIndex : full_haystack_length + fromIndex\n\t\t}\n\n\t\treturn position\n\t}\n\n\t// APNGs have an animation control chunk ('acTL') preceding the IDATs.\n\t// See: https://en.wikipedia.org/wiki/APNG#File_format\n\tconst idatIdx = indexOfSubstring(view, 'IDAT', 12)\n\tif (idatIdx >= 12) {\n\t\tconst actlIdx = indexOfSubstring(view, 'acTL', 8, idatIdx)\n\t\treturn actlIdx >= 8\n\t}\n\n\treturn false\n}\n\n// globalThis.isApng = isApng\n\n// (new TextEncoder()).encode('IDAT')\n// Decimal: [73, 68, 65, 84]\n// Hex: [0x49, 0x44, 0x41, 0x54]\n\n// (new TextEncoder()).encode('acTL')\n// Decimal: [97, 99, 84, 76]\n// Hex: [0x61, 0x63, 0x54, 0x4C]\n\n// const idatIdx = buffer.indexOf('IDAT')\n// const actlIdx = buffer.indexOf('acTL')\n","/**\n * Determines whether an ArrayBuffer contains an animated AVIF image.\n *\n * This function performs a simple check by examining the 4th byte of the buffer.\n * AVIF animation is indicated when the byte at index 3 equals 44.\n *\n * @param buffer - The ArrayBuffer containing the AVIF image data to analyze\n * @returns True if the buffer contains an animated AVIF, false otherwise\n *\n * @example\n * ```typescript\n * // Check if an AVIF file is animated\n * const response = await fetch('image.avif')\n * const buffer = await response.arrayBuffer()\n * const isAnimated = isAvifAnimated(buffer)\n * if (isAnimated) {\n * console.log('This AVIF contains animation!')\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Use with file input\n * const fileInput = document.querySelector('input[type=\"file\"]')\n * fileInput.addEventListener('change', async (event) => {\n * const file = event.target.files[0]\n * const buffer = await file.arrayBuffer()\n * const hasAnimation = isAvifAnimated(buffer)\n * console.log(hasAnimation ? 'Animated AVIF' : 'Static AVIF')\n * })\n * ```\n *\n * @public\n */\nexport const isAvifAnimated = (buffer: ArrayBuffer) => {\n\tconst view = new Uint8Array(buffer)\n\treturn view[3] === 44\n}\n","/*!\n * MIT License\n * Modified code originally from <https://github.com/qzb/is-animated>\n * Copyright (c) 2016 Józef Sokołowski <j.k.sokolowski@gmail.com>\n */\n\n/** Returns total length of data blocks sequence */\nfunction getDataBlocksLength(buffer: Uint8Array, offset: number): number {\n\tlet length = 0\n\n\twhile (buffer[offset + length]) {\n\t\tlength += buffer[offset + length] + 1\n\t}\n\n\treturn length + 1\n}\n\n/**\n * Checks if buffer contains GIF image by examining the file header.\n *\n * @param buffer - The ArrayBuffer containing the image data to check\n * @returns True if the buffer contains a GIF image, false otherwise\n * @example\n * ```ts\n * // Check a file from user input\n * const file = event.target.files[0]\n * const buffer = await file.arrayBuffer()\n * const isGif = isGIF(buffer)\n * console.log(isGif ? 'GIF image' : 'Not a GIF')\n * ```\n * @public\n */\nexport function isGIF(buffer: ArrayBuffer): boolean {\n\tconst enc = new TextDecoder('ascii')\n\tconst header = enc.decode(buffer.slice(0, 3))\n\treturn header === 'GIF'\n}\n\n/**\n * Checks if buffer contains animated GIF image by parsing the GIF structure and counting image descriptors.\n * A GIF is considered animated if it contains more than one image descriptor block.\n *\n * @param buffer - The ArrayBuffer containing the GIF image data\n * @returns True if the GIF is animated (contains multiple frames), false otherwise\n * @example\n * ```ts\n * // Check if a GIF file is animated\n * const file = event.target.files[0]\n * if (file.type === 'image/gif') {\n * const buffer = await file.arrayBuffer()\n * const animated = isGifAnimated(buffer)\n * console.log(animated ? 'Animated GIF' : 'Static GIF')\n * }\n * ```\n * @public\n */\nexport function isGifAnimated(buffer: ArrayBuffer): boolean {\n\tconst view = new Uint8Array(buffer)\n\tlet hasColorTable, colorTableSize\n\tlet offset = 0\n\tlet imagesCount = 0\n\n\t// Check if this is this image has valid GIF header.\n\t// If not return false. Chrome, FF and IE doesn't handle GIFs with invalid version.\n\tif (!isGIF(buffer)) {\n\t\treturn false\n\t}\n\n\t// Skip header, logical screen descriptor and global color table\n\n\thasColorTable = view[10] & 0x80 // 0b10000000\n\tcolorTableSize = view[10] & 0x07 // 0b00000111\n\n\toffset += 6 // skip header\n\toffset += 7 // skip logical screen descriptor\n\toffset += hasColorTable ? 3 * Math.pow(2, colorTableSize + 1) : 0 // skip global color table\n\n\t// Find if there is more than one image descriptor\n\n\twhile (imagesCount < 2 && offset < view.length) {\n\t\tswitch (view[offset]) {\n\t\t\t// Image descriptor block. According to specification there could be any\n\t\t\t// number of these blocks (even zero). When there is more than one image\n\t\t\t// descriptor browsers will display animation (they shouldn't when there\n\t\t\t// is no delays defined, but they do it anyway).\n\t\t\tcase 0x2c:\n\t\t\t\timagesCount += 1\n\n\t\t\t\thasColorTable = view[offset + 9] & 0x80 // 0b10000000\n\t\t\t\tcolorTableSize = view[offset + 9] & 0x07 // 0b00000111\n\n\t\t\t\toffset += 10 // skip image descriptor\n\t\t\t\toffset += hasColorTable ? 3 * Math.pow(2, colorTableSize + 1) : 0 // skip local color table\n\t\t\t\toffset += getDataBlocksLength(view, offset + 1) + 1 // skip image data\n\n\t\t\t\tbreak\n\n\t\t\t// Skip all extension blocks. In theory this \"plain text extension\" blocks\n\t\t\t// could be frames of animation, but no browser renders them.\n\t\t\tcase 0x21:\n\t\t\t\toffset += 2 // skip introducer and label\n\t\t\t\toffset += getDataBlocksLength(view, offset) // skip this block and following data blocks\n\n\t\t\t\tbreak\n\n\t\t\t// Stop processing on trailer block,\n\t\t\t// all data after this point will is ignored by decoders\n\t\t\tcase 0x3b:\n\t\t\t\toffset = view.length // fast forward to end of buffer\n\t\t\t\tbreak\n\n\t\t\t// Oops! This GIF seems to be invalid\n\t\t\tdefault:\n\t\t\t\t// fast forward to end of buffer\n\t\t\t\toffset = view.length\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\treturn imagesCount > 1\n}\n","/*!\n * MIT License: https://github.com/alexgorbatchev/crc/blob/master/LICENSE\n * Copyright: 2014 Alex Gorbatchev\n * Code: crc32, https://github.com/alexgorbatchev/crc/blob/master/src/calculators/crc32.ts\n */\n\ntype BufferInput = string | ArrayBuffer | Buffer\n\ninterface CRCCalculator<T = BufferInput | Uint8Array> {\n\t(value: T, previous?: number): number\n}\n\nlet TABLE: Array<number> | Int32Array = [\n\t0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,\n\t0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,\n\t0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,\n\t0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,\n\t0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,\n\t0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,\n\t0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,\n\t0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,\n\t0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,\n\t0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,\n\t0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,\n\t0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,\n\t0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,\n\t0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,\n\t0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\n\t0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,\n\t0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,\n\t0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,\n\t0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,\n\t0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,\n\t0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,\n\t0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,\n\t0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,\n\t0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,\n\t0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,\n\t0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,\n\t0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,\n\t0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,\n\t0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,\n\t0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\n\t0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,\n\t0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,\n]\n\nif (typeof Int32Array !== 'undefined') {\n\tTABLE = new Int32Array(TABLE)\n}\n\nconst crc: CRCCalculator<Uint8Array> = (current, previous) => {\n\tlet crc = previous === 0 ? 0 : ~~previous! ^ -1\n\n\tfor (let index = 0; index < current.length; index++) {\n\t\tcrc = TABLE[(crc ^ current[index]) & 0xff] ^ (crc >>> 8)\n\t}\n\n\treturn crc ^ -1\n}\n\nconst LEN_SIZE = 4\nconst CRC_SIZE = 4\n\n/**\n * Utility class for reading and manipulating PNG image files.\n * Provides methods for parsing PNG chunks, validating PNG format, and modifying PNG metadata.\n *\n * @example\n * ```ts\n * // Validate PNG file from blob\n * const blob = new Blob([pngData], { type: 'image/png' })\n * const view = new DataView(await blob.arrayBuffer())\n * const isPng = PngHelpers.isPng(view, 0)\n *\n * // Parse PNG metadata for image processing\n * const chunks = PngHelpers.readChunks(view)\n * const physChunk = PngHelpers.findChunk(view, 'pHYs')\n *\n * // Create high-DPI PNG for export\n * const highDpiBlob = PngHelpers.setPhysChunk(view, 2, { type: 'image/png' })\n * ```\n *\n * @public\n */\nexport class PngHelpers {\n\t/**\n\t * Checks if binary data at the specified offset contains a valid PNG file signature.\n\t * Validates the 8-byte PNG signature: 89 50 4E 47 0D 0A 1A 0A.\n\t *\n\t * @param view - DataView containing the binary data to check\n\t * @param offset - Byte offset where the PNG signature should start\n\t * @returns True if the data contains a valid PNG signature, false otherwise\n\t *\n\t * @example\n\t * ```ts\n\t * // Validate PNG from file upload\n\t * const file = event.target.files[0]\n\t * const buffer = await file.arrayBuffer()\n\t * const view = new DataView(buffer)\n\t *\n\t * if (PngHelpers.isPng(view, 0)) {\n\t * console.log('Valid PNG file detected')\n\t * // Process PNG file...\n\t * } else {\n\t * console.error('Not a valid PNG file')\n\t * }\n\t * ```\n\t */\n\tstatic isPng(view: DataView, offset: number) {\n\t\tif (\n\t\t\tview.getUint8(offset + 0) === 0x89 &&\n\t\t\tview.getUint8(offset + 1) === 0x50 &&\n\t\t\tview.getUint8(offset + 2) === 0x4e &&\n\t\t\tview.getUint8(offset + 3) === 0x47 &&\n\t\t\tview.getUint8(offset + 4) === 0x0d &&\n\t\t\tview.getUint8(offset + 5) === 0x0a &&\n\t\t\tview.getUint8(offset + 6) === 0x1a &&\n\t\t\tview.getUint8(offset + 7) === 0x0a\n\t\t) {\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\t}\n\n\t/**\n\t * Reads the 4-character chunk type identifier from a PNG chunk header.\n\t *\n\t * @param view - DataView containing the PNG data\n\t * @param offset - Byte offset of the chunk type field (after length field)\n\t * @returns 4-character string representing the chunk type (e.g., 'IHDR', 'IDAT', 'IEND')\n\t *\n\t * @example\n\t * ```ts\n\t * // Read chunk type from PNG header (after 8-byte signature)\n\t * const chunkType = PngHelpers.getChunkType(dataView, 8)\n\t * console.log(chunkType) // 'IHDR' (Image Header)\n\t *\n\t * // Read chunk type at a specific position during parsing\n\t * let offset = 8 // Skip PNG signature\n\t * const chunkLength = dataView.getUint32(offset)\n\t * const type = PngHelpers.getChunkType(dataView, offset + 4)\n\t * ```\n\t */\n\tstatic getChunkType(view: DataView, offset: number) {\n\t\treturn [\n\t\t\tString.fromCharCode(view.getUint8(offset)),\n\t\t\tString.fromCharCode(view.getUint8(offset + 1)),\n\t\t\tString.fromCharCode(view.getUint8(offset + 2)),\n\t\t\tString.fromCharCode(view.getUint8(offset + 3)),\n\t\t].join('')\n\t}\n\n\t/**\n\t * Parses all chunks in a PNG file and returns their metadata.\n\t * Skips duplicate IDAT chunks but includes all other chunk types.\n\t *\n\t * @param view - DataView containing the complete PNG file data\n\t * @param offset - Starting byte offset (defaults to 0)\n\t * @returns Record mapping chunk types to their metadata (start position, data offset, and size)\n\t * @throws Error if the data is not a valid PNG file\n\t *\n\t * @example\n\t * ```ts\n\t * // Parse PNG structure for metadata extraction\n\t * const view = new DataView(await blob.arrayBuffer())\n\t * const chunks = PngHelpers.readChunks(view)\n\t *\n\t * // Check for specific chunks\n\t * const ihdrChunk = chunks['IHDR']\n\t * const physChunk = chunks['pHYs']\n\t *\n\t * if (physChunk) {\n\t * console.log(`Found pixel density info at byte ${physChunk.start}`)\n\t * } else {\n\t * console.log('No pixel density information found')\n\t * }\n\t * ```\n\t */\n\tstatic readChunks(view: DataView, offset = 0) {\n\t\tconst chunks: Record<string, { dataOffset: number; size: number; start: number }> = {}\n\t\tif (!PngHelpers.isPng(view, offset)) {\n\t\t\tthrow new Error('Not a PNG')\n\t\t}\n\t\toffset += 8\n\n\t\twhile (offset <= view.buffer.byteLength) {\n\t\t\tconst start = offset\n\t\t\tconst len = view.getInt32(offset)\n\t\t\toffset += 4\n\t\t\tconst chunkType = PngHelpers.getChunkType(view, offset)\n\n\t\t\tif (chunkType === 'IDAT' && chunks[chunkType]) {\n\t\t\t\toffset += len + LEN_SIZE + CRC_SIZE\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (chunkType === 'IEND') {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tchunks[chunkType] = {\n\t\t\t\tstart,\n\t\t\t\tdataOffset: offset + 4,\n\t\t\t\tsize: len,\n\t\t\t}\n\t\t\toffset += len + LEN_SIZE + CRC_SIZE\n\t\t}\n\n\t\treturn chunks\n\t}\n\n\t/**\n\t * Parses the pHYs (physical pixel dimensions) chunk data.\n\t * Reads pixels per unit for X and Y axes, and the unit specifier.\n\t *\n\t * @param view - DataView containing the PNG data\n\t * @param offset - Byte offset of the pHYs chunk data\n\t * @returns Object with ppux (pixels per unit X), ppuy (pixels per unit Y), and unit specifier\n\t *\n\t * @example\n\t * ```ts\n\t * // Extract pixel density information for DPI calculation\n\t * const physChunk = PngHelpers.findChunk(dataView, 'pHYs')\n\t * if (physChunk) {\n\t * const physData = PngHelpers.parsePhys(dataView, physChunk.dataOffset)\n\t *\n\t * if (physData.unit === 1) { // meters\n\t * const dpiX = Math.round(physData.ppux * 0.0254)\n\t * const dpiY = Math.round(physData.ppuy * 0.0254)\n\t * console.log(`DPI: ${dpiX} x ${dpiY}`)\n\t * }\n\t * }\n\t * ```\n\t */\n\tstatic parsePhys(view: DataView, offset: number) {\n\t\treturn {\n\t\t\tppux: view.getUint32(offset),\n\t\t\tppuy: view.getUint32(offset + 4),\n\t\t\tunit: view.getUint8(offset + 8),\n\t\t}\n\t}\n\n\t/**\n\t * Finds a specific chunk type in the PNG file and returns its metadata.\n\t *\n\t * @param view - DataView containing the PNG file data\n\t * @param type - 4-character chunk type to search for (e.g., 'pHYs', 'IDAT')\n\t * @returns Chunk metadata object if found, undefined otherwise\n\t *\n\t * @example\n\t * ```ts\n\t * // Look for pixel density information in PNG\n\t * const physChunk = PngHelpers.findChunk(dataView, 'pHYs')\n\t * if (physChunk) {\n\t * const physData = PngHelpers.parsePhys(dataView, physChunk.dataOffset)\n\t * console.log(`Found pHYs chunk with ${physData.ppux} x ${physData.ppuy} pixels per unit`)\n\t * }\n\t *\n\t * // Check for text metadata\n\t * const textChunk = PngHelpers.findChunk(dataView, 'tEXt')\n\t * if (textChunk) {\n\t * console.log(`Found text metadata at byte ${textChunk.start}`)\n\t * }\n\t * ```\n\t */\n\tstatic findChunk(view: DataView, type: string) {\n\t\tconst chunks = PngHelpers.readChunks(view)\n\t\treturn chunks[type]\n\t}\n\n\t/**\n\t * Adds or replaces a pHYs chunk in a PNG file to set pixel density for high-DPI displays.\n\t * The method determines insertion point by prioritizing IDAT chunk position over existing pHYs,\n\t * creates a properly formatted pHYs chunk with CRC validation, and returns a new Blob.\n\t *\n\t * @param view - DataView containing the original PNG file data\n\t * @param dpr - Device pixel ratio multiplier (defaults to 1)\n\t * @param options - Optional Blob constructor options for MIME type and other properties\n\t * @returns New Blob containing the PNG with updated pixel density information\n\t *\n\t * @example\n\t * ```ts\n\t * // Export PNG with proper pixel density for high-DPI displays\n\t * const canvas = document.createElement('canvas')\n\t * const ctx = canvas.getContext('2d')\n\t * // ... draw content to canvas ...\n\t *\n\t * canvas.toBlob(async (blob) => {\n\t * if (blob) {\n\t * const view = new DataView(await blob.arrayBuffer())\n\t * // Create 2x DPI version for Retina displays\n\t * const highDpiBlob = PngHelpers.setPhysChunk(view, 2, { type: 'image/png' })\n\t * // Download or use the blob...\n\t * }\n\t * }, 'image/png')\n\t * ```\n\t */\n\tstatic setPhysChunk(view: DataView, dpr = 1, options?: BlobPropertyBag) {\n\t\tlet offset = 46\n\t\tlet size = 0\n\t\tconst res1 = PngHelpers.findChunk(view, 'pHYs')\n\t\tif (res1) {\n\t\t\toffset = res1.start\n\t\t\tsize = res1.size\n\t\t}\n\n\t\tconst res2 = PngHelpers.findChunk(view, 'IDAT')\n\t\tif (res2) {\n\t\t\toffset = res2.start\n\t\t\tsize = 0\n\t\t}\n\n\t\tconst pHYsData = new ArrayBuffer(21)\n\t\tconst pHYsDataView = new DataView(pHYsData)\n\n\t\tpHYsDataView.setUint32(0, 9)\n\n\t\tpHYsDataView.setUint8(4, 'p'.charCodeAt(0))\n\t\tpHYsDataView.setUint8(5, 'H'.charCodeAt(0))\n\t\tpHYsDataView.setUint8(6, 'Y'.charCodeAt(0))\n\t\tpHYsDataView.setUint8(7, 's'.charCodeAt(0))\n\n\t\tconst DPI_72 = 2835.5\n\n\t\tpHYsDataView.setInt32(8, DPI_72 * dpr)\n\t\tpHYsDataView.setInt32(12, DPI_72 * dpr)\n\t\tpHYsDataView.setInt8(16, 1)\n\n\t\tconst crcBit = new Uint8Array(pHYsData.slice(4, 17))\n\t\tpHYsDataView.setInt32(17, crc(crcBit))\n\n\t\tconst startBuf = view.buffer.slice(0, offset)\n\t\tconst endBuf = view.buffer.slice(offset + size)\n\n\t\treturn new Blob([startBuf as ArrayBuffer, pHYsData, endBuf as ArrayBuffer], options)\n\t}\n}\n","/*!\n * MIT License: https://github.com/sindresorhus/is-webp/blob/main/license\n * Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n */\n\n/**\n * Determines whether a byte array represents a WebP image by checking the WebP file signature.\n *\n * @param view - The Uint8Array containing the potential WebP image data\n * @returns True if the byte array is a valid WebP image, false otherwise\n * @example\n * ```ts\n * // Check if file data is WebP format\n * const file = new File([...], 'image.webp', { type: 'image/webp' })\n * const buffer = await file.arrayBuffer()\n * const view = new Uint8Array(buffer)\n * const isWebPImage = isWebp(view)\n * console.log(isWebPImage ? 'Valid WebP' : 'Not WebP')\n * ```\n * @internal\n */\nexport function isWebp(view: Uint8Array) {\n\tif (!view || view.length < 12) {\n\t\treturn false\n\t}\n\n\treturn view[8] === 87 && view[9] === 69 && view[10] === 66 && view[11] === 80\n}\n\n/**\n * Determines whether a WebP image file contains animation data by checking the animation flag in the WebP VP8X chunk.\n *\n * @param buffer - The ArrayBuffer containing the WebP image data\n * @returns True if the WebP image is animated, false otherwise\n * @example\n * ```ts\n * // Check if a WebP file from user input is animated\n * const file = new File([...], 'image.webp', { type: 'image/webp' })\n * const buffer = await file.arrayBuffer()\n * const animated = isWebpAnimated(buffer)\n * console.log(animated ? 'Animated WebP' : 'Static WebP')\n * ```\n * @public\n */\nexport function isWebpAnimated(buffer: ArrayBuffer) {\n\tconst view = new Uint8Array(buffer)\n\n\tif (!isWebp(view)) {\n\t\treturn false\n\t}\n\n\tif (!view || view.length < 21) {\n\t\treturn false\n\t}\n\n\treturn ((view[20] >> 1) & 1) === 1\n}\n","import { promiseWithResolve } from '../control'\nimport { Image } from '../network'\nimport { isApngAnimated } from './apng'\nimport { isAvifAnimated } from './avif'\nimport { isGifAnimated } from './gif'\nimport { PngHelpers } from './png'\nimport { isWebpAnimated } from './webp'\n\n/**\n * Array of supported vector image MIME types.\n *\n * @example\n * ```ts\n * import { DEFAULT_SUPPORTED_VECTOR_IMAGE_TYPES } from '@ibodr/utils'\n *\n * const isSvg = DEFAULT_SUPPORTED_VECTOR_IMAGE_TYPES.includes('image/svg+xml')\n * console.log(isSvg) // true\n * ```\n * @public\n */\nexport const DEFAULT_SUPPORTED_VECTOR_IMAGE_TYPES = Object.freeze(['image/svg+xml' as const])\n/**\n * Array of supported static (non-animated) image MIME types.\n *\n * @example\n * ```ts\n * import { DEFAULT_SUPPORTED_STATIC_IMAGE_TYPES } from '@ibodr/utils'\n *\n * const isStatic = DEFAULT_SUPPORTED_STATIC_IMAGE_TYPES.includes('image/jpeg')\n * console.log(isStatic) // true\n * ```\n * @public\n */\nexport const DEFAULT_SUPPORTED_STATIC_IMAGE_TYPES = Object.freeze([\n\t'image/jpeg' as const,\n\t'image/png' as const,\n\t'image/webp' as const,\n])\n/**\n * Array of supported animated image MIME types.\n *\n * @example\n * ```ts\n * import { DEFAULT_SUPPORTED_ANIMATED_IMAGE_TYPES } from '@ibodr/utils'\n *\n * const isAnimated = DEFAULT_SUPPORTED_ANIMATED_IMAGE_TYPES.includes('image/gif')\n * console.log(isAnimated) // true\n * ```\n * @public\n */\nexport const DEFAULT_SUPPORTED_ANIMATED_IMAGE_TYPES = Object.freeze([\n\t'image/gif' as const,\n\t'image/apng' as const,\n\t'image/avif' as const,\n])\n/**\n * Array of all supported image MIME types, combining static, vector, and animated types.\n *\n * @example\n * ```ts\n * import { DEFAULT_SUPPORTED_IMAGE_TYPES } from '@ibodr/utils'\n *\n * const isSupported = DEFAULT_SUPPORTED_IMAGE_TYPES.includes('image/png')\n * console.log(isSupported) // true\n * ```\n * @public\n */\nexport const DEFAULT_SUPPORTED_IMAGE_TYPES = Object.freeze([\n\t...DEFAULT_SUPPORTED_STATIC_IMAGE_TYPES,\n\t...DEFAULT_SUPPORTED_VECTOR_IMAGE_TYPES,\n\t...DEFAULT_SUPPORTED_ANIMATED_IMAGE_TYPES,\n])\n/**\n * Array of supported video MIME types.\n *\n * @example\n * ```ts\n * import { DEFAULT_SUPPORT_VIDEO_TYPES } from '@ibodr/utils'\n *\n * const isVideo = DEFAULT_SUPPORT_VIDEO_TYPES.includes('video/mp4')\n * console.log(isVideo) // true\n * ```\n * @public\n */\nexport const DEFAULT_SUPPORT_VIDEO_TYPES = Object.freeze([\n\t'video/mp4' as const,\n\t'video/webm' as const,\n\t'video/quicktime' as const,\n])\n/**\n * Array of all supported media MIME types, combining images and videos.\n *\n * @example\n * ```ts\n * import { DEFAULT_SUPPORTED_MEDIA_TYPES } from '@ibodr/utils'\n *\n * const isMediaFile = DEFAULT_SUPPORTED_MEDIA_TYPES.includes('video/mp4')\n * console.log(isMediaFile) // true\n * ```\n * @public\n */\nexport const DEFAULT_SUPPORTED_MEDIA_TYPES = Object.freeze([\n\t...DEFAULT_SUPPORTED_IMAGE_TYPES,\n\t...DEFAULT_SUPPORT_VIDEO_TYPES,\n])\n/**\n * Comma-separated string of all supported media MIME types, useful for HTML file input accept attributes.\n *\n * @example\n * ```ts\n * import { DEFAULT_SUPPORTED_MEDIA_TYPE_LIST } from '@ibodr/utils'\n *\n * // Use in HTML file input for media uploads\n * const input = document.createElement('input')\n * input.type = 'file'\n * input.accept = DEFAULT_SUPPORTED_MEDIA_TYPE_LIST\n * input.addEventListener('change', (e) => {\n * const files = (e.target as HTMLInputElement).files\n * if (files) console.log(`Selected ${files.length} file(s)`)\n * })\n * ```\n * @public\n */\nexport const DEFAULT_SUPPORTED_MEDIA_TYPE_LIST = DEFAULT_SUPPORTED_MEDIA_TYPES.join(',')\n\n/**\n * Helpers for media\n *\n * @public\n */\nexport class MediaHelpers {\n\t/**\n\t * Load a video element from a URL with cross-origin support.\n\t *\n\t * @param src - The URL of the video to load\n\t * @param doc - Optional document to create the video element in\n\t * @returns Promise that resolves to the loaded HTMLVideoElement\n\t * @example\n\t * ```ts\n\t * const video = await MediaHelpers.loadVideo('https://example.com/video.mp4')\n\t * console.log(`Video dimensions: ${video.videoWidth}x${video.videoHeight}`)\n\t * ```\n\t * @public\n\t */\n\tstatic loadVideo(src: string, doc?: Document): Promise<HTMLVideoElement> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\tconst video = (doc ?? document).createElement('video')\n\t\t\tvideo.onloadeddata = () => resolve(video)\n\t\t\tvideo.onerror = (e) => {\n\t\t\t\tconsole.error(e)\n\t\t\t\treject(new Error('Could not load video'))\n\t\t\t}\n\t\t\tvideo.crossOrigin = 'anonymous'\n\t\t\tvideo.src = src\n\t\t})\n\t}\n\n\t/**\n\t * Extract a frame from a video element as a data URL.\n\t *\n\t * @param video - The HTMLVideoElement to extract frame from\n\t * @param time - The time in seconds to extract the frame from (default: 0)\n\t * @returns Promise that resolves to a data URL of the video frame\n\t * @example\n\t * ```ts\n\t * const video = await MediaHelpers.loadVideo('https://example.com/video.mp4')\n\t * const frameDataUrl = await MediaHelpers.getVideoFrameAsDataUrl(video, 5.0)\n\t * // Use frameDataUrl as image thumbnail\n\t * const img = document.createElement('img')\n\t * img.src = frameDataUrl\n\t * ```\n\t * @public\n\t */\n\tstatic async getVideoFrameAsDataUrl(video: HTMLVideoElement, time = 0): Promise<string> {\n\t\tconst promise = promiseWithResolve<string>()\n\t\tlet didSetTime = false\n\n\t\tconst onReadyStateChanged = () => {\n\t\t\tif (!didSetTime) {\n\t\t\t\tif (video.readyState >= video.HAVE_METADATA) {\n\t\t\t\t\tdidSetTime = true\n\t\t\t\t\tvideo.currentTime = time\n\t\t\t\t} else {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (video.readyState >= video.HAVE_CURRENT_DATA) {\n\t\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\t\tconst canvas = (video.ownerDocument ?? document).createElement('canvas')\n\t\t\t\tcanvas.width = video.videoWidth\n\t\t\t\tcanvas.height = video.videoHeight\n\t\t\t\tconst ctx = canvas.getContext('2d')\n\t\t\t\tif (!ctx) {\n\t\t\t\t\tthrow new Error('Could not get 2d context')\n\t\t\t\t}\n\t\t\t\tctx.drawImage(video, 0, 0)\n\t\t\t\tpromise.resolve(canvas.toDataURL())\n\t\t\t}\n\t\t}\n\t\tconst onError = (e: Event) => {\n\t\t\tconsole.error(e)\n\t\t\tpromise.reject(new Error('Could not get video frame'))\n\t\t}\n\n\t\tvideo.addEventListener('loadedmetadata', onReadyStateChanged)\n\t\tvideo.addEventListener('loadeddata', onReadyStateChanged)\n\t\tvideo.addEventListener('canplay', onReadyStateChanged)\n\t\tvideo.addEventListener('seeked', onReadyStateChanged)\n\n\t\tvideo.addEventListener('error', onError)\n\t\tvideo.addEventListener('stalled', onError)\n\n\t\tonReadyStateChanged()\n\n\t\ttry {\n\t\t\treturn await promise\n\t\t} finally {\n\t\t\tvideo.removeEventListener('loadedmetadata', onReadyStateChanged)\n\t\t\tvideo.removeEventListener('loadeddata', onReadyStateChanged)\n\t\t\tvideo.removeEventListener('canplay', onReadyStateChanged)\n\t\t\tvideo.removeEventListener('seeked', onReadyStateChanged)\n\n\t\t\tvideo.removeEventListener('error', onError)\n\t\t\tvideo.removeEventListener('stalled', onError)\n\t\t}\n\t}\n\n\t/**\n\t * Load an image from a URL and get its dimensions along with the image element.\n\t *\n\t * @param src - The URL of the image to load\n\t * @param doc - Optional document to use for DOM operations (e.g. measuring SVG dimensions)\n\t * @returns Promise that resolves to an object with width, height, and the image element\n\t * @example\n\t * ```ts\n\t * const { w, h, image } = await MediaHelpers.getImageAndDimensions('https://example.com/image.png')\n\t * console.log(`Image size: ${w}x${h}`)\n\t * // Image is ready to use\n\t * document.body.appendChild(image)\n\t * ```\n\t * @public\n\t */\n\tstatic getImageAndDimensions(\n\t\tsrc: string,\n\t\tdoc?: Document\n\t): Promise<{ w: number; h: number; image: HTMLImageElement }> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst img = Image()\n\t\t\timg.onload = () => {\n\t\t\t\tlet dimensions\n\t\t\t\tif (img.naturalWidth) {\n\t\t\t\t\tdimensions = {\n\t\t\t\t\t\tw: img.naturalWidth,\n\t\t\t\t\t\th: img.naturalHeight,\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Sigh, Firefox doesn't have naturalWidth or naturalHeight for SVGs. :-/\n\t\t\t\t\t// We have to attach to dom and use clientWidth/clientHeight.\n\t\t\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\t\t\tconst body = (doc ?? document).body\n\t\t\t\t\tbody.appendChild(img)\n\t\t\t\t\tdimensions = {\n\t\t\t\t\t\tw: img.clientWidth,\n\t\t\t\t\t\th: img.clientHeight,\n\t\t\t\t\t}\n\t\t\t\t\tbody.removeChild(img)\n\t\t\t\t}\n\t\t\t\tresolve({ ...dimensions, image: img })\n\t\t\t}\n\t\t\timg.onerror = (e) => {\n\t\t\t\tconsole.error(e)\n\t\t\t\treject(new Error('Could not load image'))\n\t\t\t}\n\t\t\timg.crossOrigin = 'anonymous'\n\t\t\timg.referrerPolicy = 'strict-origin-when-cross-origin'\n\t\t\timg.style.visibility = 'hidden'\n\t\t\timg.style.position = 'absolute'\n\t\t\timg.style.opacity = '0'\n\t\t\timg.style.zIndex = '-9999'\n\t\t\timg.src = src\n\t\t})\n\t}\n\n\t/**\n\t * Get the size of a video blob\n\t *\n\t * @param blob - A Blob containing the video\n\t * @param doc - Optional document to create elements in\n\t * @returns Promise that resolves to an object with width and height properties\n\t * @example\n\t * ```ts\n\t * const file = new File([...], 'video.mp4', { type: 'video/mp4' })\n\t * const { w, h } = await MediaHelpers.getVideoSize(file)\n\t * console.log(`Video dimensions: ${w}x${h}`)\n\t * ```\n\t * @public\n\t */\n\tstatic async getVideoSize(blob: Blob, doc?: Document): Promise<{ w: number; h: number }> {\n\t\treturn MediaHelpers.usingObjectURL(blob, async (url) => {\n\t\t\tconst video = await MediaHelpers.loadVideo(url, doc)\n\t\t\treturn { w: video.videoWidth, h: video.videoHeight }\n\t\t})\n\t}\n\n\t/**\n\t * Get the size of an image blob\n\t *\n\t * @param blob - A Blob containing the image\n\t * @param doc - Optional document to use for DOM operations\n\t * @returns Promise that resolves to an object with width and height properties\n\t * @example\n\t * ```ts\n\t * const file = new File([...], 'image.png', { type: 'image/png' })\n\t * const { w, h } = await MediaHelpers.getImageSize(file)\n\t * console.log(`Image dimensions: ${w}x${h}`)\n\t * ```\n\t * @public\n\t */\n\tstatic async getImageSize(\n\t\tblob: Blob,\n\t\tdoc?: Document\n\t): Promise<{ w: number; h: number; pixelRatio: number }> {\n\t\tconst { w, h } = await MediaHelpers.usingObjectURL(blob, (url) =>\n\t\t\tMediaHelpers.getImageAndDimensions(url, doc)\n\t\t)\n\n\t\ttry {\n\t\t\tif (blob.type === 'image/png') {\n\t\t\t\tconst view = new DataView(await blob.arrayBuffer())\n\t\t\t\tif (PngHelpers.isPng(view, 0)) {\n\t\t\t\t\tconst physChunk = PngHelpers.findChunk(view, 'pHYs')\n\t\t\t\t\tif (physChunk) {\n\t\t\t\t\t\tconst physData = PngHelpers.parsePhys(view, physChunk.dataOffset)\n\t\t\t\t\t\tif (physData.unit === 1 && physData.ppux === physData.ppuy) {\n\t\t\t\t\t\t\tconst dpi = Math.round(physData.ppux * 0.0254)\n\t\t\t\t\t\t\t// Try both standard baselines: Windows/web = 96, macOS = 72.\n\t\t\t\t\t\t\t// Pick whichever yields a clean integer ratio > 1.\n\t\t\t\t\t\t\tconst r96 = dpi / 96\n\t\t\t\t\t\t\tconst r72 = dpi / 72\n\t\t\t\t\t\t\tlet pixelRatio = 1\n\t\t\t\t\t\t\tif (Number.isInteger(r96) && r96 > 1) {\n\t\t\t\t\t\t\t\tpixelRatio = r96\n\t\t\t\t\t\t\t} else if (Number.isInteger(r72) && r72 > 1) {\n\t\t\t\t\t\t\t\tpixelRatio = r72\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (pixelRatio > 1) {\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tw: Math.ceil(w / pixelRatio),\n\t\t\t\t\t\t\t\t\th: Math.ceil(h / pixelRatio),\n\t\t\t\t\t\t\t\t\tpixelRatio,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconsole.error(err)\n\t\t\treturn { w, h, pixelRatio: 1 }\n\t\t}\n\t\treturn { w, h, pixelRatio: 1 }\n\t}\n\n\t/**\n\t * Check if a media file blob contains animation data.\n\t *\n\t * @param file - The Blob to check for animation\n\t * @returns Promise that resolves to true if the file is animated, false otherwise\n\t * @example\n\t * ```ts\n\t * const file = new File([...], 'animation.gif', { type: 'image/gif' })\n\t * const animated = await MediaHelpers.isAnimated(file)\n\t * console.log(animated ? 'Animated' : 'Static')\n\t * ```\n\t * @public\n\t */\n\tstatic async isAnimated(file: Blob): Promise<boolean> {\n\t\tif (file.type === 'image/gif') {\n\t\t\treturn isGifAnimated(await file.arrayBuffer())\n\t\t}\n\n\t\tif (file.type === 'image/avif') {\n\t\t\treturn isAvifAnimated(await file.arrayBuffer())\n\t\t}\n\n\t\tif (file.type === 'image/webp') {\n\t\t\treturn isWebpAnimated(await file.arrayBuffer())\n\t\t}\n\n\t\tif (file.type === 'image/apng') {\n\t\t\treturn isApngAnimated(await file.arrayBuffer())\n\t\t}\n\n\t\treturn false\n\t}\n\n\t/**\n\t * Check if a MIME type represents an animated image format.\n\t *\n\t * @param mimeType - The MIME type to check\n\t * @returns True if the MIME type is an animated image format, false otherwise\n\t * @example\n\t * ```ts\n\t * const isAnimated = MediaHelpers.isAnimatedImageType('image/gif')\n\t * console.log(isAnimated) // true\n\t * ```\n\t * @public\n\t */\n\tstatic isAnimatedImageType(mimeType: string | null): boolean {\n\t\treturn DEFAULT_SUPPORTED_ANIMATED_IMAGE_TYPES.includes((mimeType as any) || '')\n\t}\n\n\t/**\n\t * Check if a MIME type represents a static (non-animated) image format.\n\t *\n\t * @param mimeType - The MIME type to check\n\t * @returns True if the MIME type is a static image format, false otherwise\n\t * @example\n\t * ```ts\n\t * const isStatic = MediaHelpers.isStaticImageType('image/jpeg')\n\t * console.log(isStatic) // true\n\t * ```\n\t * @public\n\t */\n\tstatic isStaticImageType(mimeType: string | null): boolean {\n\t\treturn DEFAULT_SUPPORTED_STATIC_IMAGE_TYPES.includes((mimeType as any) || '')\n\t}\n\n\t/**\n\t * Check if a MIME type represents a vector image format.\n\t *\n\t * @param mimeType - The MIME type to check\n\t * @returns True if the MIME type is a vector image format, false otherwise\n\t * @example\n\t * ```ts\n\t * const isVector = MediaHelpers.isVectorImageType('image/svg+xml')\n\t * console.log(isVector) // true\n\t * ```\n\t * @public\n\t */\n\tstatic isVectorImageType(mimeType: string | null): boolean {\n\t\treturn DEFAULT_SUPPORTED_VECTOR_IMAGE_TYPES.includes((mimeType as any) || '')\n\t}\n\n\t/**\n\t * Check if a MIME type represents any supported image format (static, animated, or vector).\n\t *\n\t * @param mimeType - The MIME type to check\n\t * @returns True if the MIME type is a supported image format, false otherwise\n\t * @example\n\t * ```ts\n\t * const isImage = MediaHelpers.isImageType('image/png')\n\t * console.log(isImage) // true\n\t * ```\n\t * @public\n\t */\n\tstatic isImageType(mimeType: string): boolean {\n\t\treturn DEFAULT_SUPPORTED_IMAGE_TYPES.includes((mimeType as any) || '')\n\t}\n\n\t/**\n\t * Utility function to create an object URL from a blob, execute a function with it, and automatically clean it up.\n\t *\n\t * @param blob - The Blob to create an object URL for\n\t * @param fn - Function to execute with the object URL\n\t * @returns Promise that resolves to the result of the function\n\t * @example\n\t * ```ts\n\t * const result = await MediaHelpers.usingObjectURL(imageBlob, async (url) => {\n\t * const { w, h } = await MediaHelpers.getImageAndDimensions(url)\n\t * return { width: w, height: h }\n\t * })\n\t * // Object URL is automatically revoked after function completes\n\t * console.log(`Image dimensions: ${result.width}x${result.height}`)\n\t * ```\n\t * @public\n\t */\n\tstatic async usingObjectURL<T>(blob: Blob, fn: (url: string) => Promise<T>): Promise<T> {\n\t\tconst url = URL.createObjectURL(blob)\n\t\ttry {\n\t\t\treturn await fn(url)\n\t\t} finally {\n\t\t\tURL.revokeObjectURL(url)\n\t\t}\n\t}\n}\n","/**\n * Linear interpolate between two values.\n *\n * @param a - The start value\n * @param b - The end value\n * @param t - The interpolation factor (0-1)\n * @returns The interpolated value\n * @example\n * ```ts\n * const halfway = lerp(0, 100, 0.5) // 50\n * const quarter = lerp(10, 20, 0.25) // 12.5\n * ```\n * @public\n */\nexport function lerp(a: number, b: number, t: number) {\n\treturn a + (b - a) * t\n}\n\n/**\n * Inverse lerp between two values. Given a value `t` in the range [a, b], returns a number between\n * 0 and 1.\n *\n * @param a - The start value of the range\n * @param b - The end value of the range\n * @param t - The value within the range [a, b]\n * @returns The normalized position (0-1) of t within the range [a, b]\n * @example\n * ```ts\n * const position = invLerp(0, 100, 25) // 0.25\n * const normalized = invLerp(10, 20, 15) // 0.5\n * ```\n * @public\n */\nexport function invLerp(a: number, b: number, t: number) {\n\treturn (t - a) / (b - a)\n}\n\n/**\n * Seeded random number generator, using [xorshift](https://en.wikipedia.org/wiki/Xorshift). The\n * result will always be between -1 and 1.\n *\n * Adapted from [seedrandom](https://github.com/davidbau/seedrandom).\n *\n * @param seed - The seed string for deterministic random generation (defaults to empty string)\n * @returns A function that will return a random number between -1 and 1 each time it is called\n * @example\n * ```ts\n * const random = rng('my-seed')\n * const num1 = random() // Always the same for this seed\n * const num2 = random() // Next number in sequence\n *\n * // Different seed produces different sequence\n * const otherRandom = rng('other-seed')\n * const different = otherRandom() // Different value\n * ```\n * @public\n */\nexport function rng(seed = '') {\n\tlet x = 0\n\tlet y = 0\n\tlet z = 0\n\tlet w = 0\n\n\tfunction next() {\n\t\tconst t = x ^ (x << 11)\n\t\tx = y\n\t\ty = z\n\t\tz = w\n\t\tw ^= ((w >>> 19) ^ t ^ (t >>> 8)) >>> 0\n\t\treturn (w / 0x100000000) * 2\n\t}\n\n\tfor (let k = 0; k < seed.length + 64; k++) {\n\t\tx ^= seed.charCodeAt(k) | 0\n\t\tnext()\n\t}\n\n\treturn next\n}\n\n/**\n * Modulate a value between two ranges.\n *\n * @example\n *\n * ```ts\n * const A = modulate(0, [0, 1], [0, 100]) // 0\n * const B = modulate(0.5, [0, 1], [0, 100]) // 50\n * const C = modulate(1, [0, 1], [0, 100]) // 100\n * ```\n *\n * @param value - The interpolation value.\n * @param rangeA - From [low, high]\n * @param rangeB - To [low, high]\n * @param clamp - Whether to clamp the the result to [low, high]\n * @public\n */\nexport function modulate(value: number, rangeA: number[], rangeB: number[], clamp = false): number {\n\tconst [fromLow, fromHigh] = rangeA\n\tconst [v0, v1] = rangeB\n\tconst result = v0 + ((value - fromLow) / (fromHigh - fromLow)) * (v1 - v0)\n\n\treturn clamp\n\t\t? v0 < v1\n\t\t\t? Math.max(Math.min(result, v1), v0)\n\t\t\t: Math.max(Math.min(result, v0), v1)\n\t\t: result\n}\n","import isEqualWith from 'lodash.isequalwith'\n\n/**\n * Safely checks if an object has a specific property as its own property (not inherited).\n * Uses Object.prototype.hasOwnProperty.call to avoid issues with objects that have null prototype\n * or have overridden the hasOwnProperty method.\n *\n * @param obj - The object to check\n * @param key - The property key to check for\n * @returns True if the object has the property as its own property, false otherwise\n * @example\n * ```ts\n * const obj = { name: 'Alice', age: 30 }\n * hasOwnProperty(obj, 'name') // true\n * hasOwnProperty(obj, 'toString') // false (inherited)\n * hasOwnProperty(obj, 'unknown') // false\n * ```\n * @internal\n */\nexport function hasOwnProperty(obj: object, key: string): boolean {\n\treturn Object.prototype.hasOwnProperty.call(obj, key)\n}\n\n/**\n * Safely gets an object's own property value (not inherited). Returns undefined if the property\n * doesn't exist as an own property. Provides type-safe access with proper TypeScript inference.\n *\n * @param obj - The object to get the property from\n * @param key - The property key to retrieve\n * @returns The property value if it exists as an own property, undefined otherwise\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const name = getOwnProperty(user, 'name') // 'Alice'\n * const missing = getOwnProperty(user, 'unknown') // undefined\n * const inherited = getOwnProperty(user, 'toString') // undefined (inherited)\n * ```\n * @internal\n */\nexport function getOwnProperty<K extends string, V>(\n\tobj: Partial<Record<K, V>>,\n\tkey: K\n): V | undefined\n/** @internal */\nexport function getOwnProperty<O extends object>(obj: O, key: string): O[keyof O] | undefined\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown\n/** @internal */\nexport function getOwnProperty(obj: object, key: string): unknown {\n\tif (!hasOwnProperty(obj, key)) {\n\t\treturn undefined\n\t}\n\t// @ts-expect-error we know the property exists\n\treturn obj[key]\n}\n\n/**\n * An alias for `Object.keys` that treats the object as a map and so preserves the type of the keys.\n * Unlike standard Object.keys which returns string[], this maintains the specific string literal types.\n *\n * @param object - The object to get keys from\n * @returns Array of keys with preserved string literal types\n * @example\n * ```ts\n * const config = { theme: 'dark', lang: 'en' } as const\n * const keys = objectMapKeys(config)\n * // keys is Array<'theme' | 'lang'> instead of string[]\n * ```\n * @internal\n */\nexport function objectMapKeys<Key extends string>(object: {\n\treadonly [K in Key]: unknown\n}): Array<Key> {\n\treturn Object.keys(object) as Key[]\n}\n\n/**\n * An alias for `Object.values` that treats the object as a map and so preserves the type of the\n * values. Unlike standard Object.values which returns unknown[], this maintains the specific value types.\n *\n * @param object - The object to get values from\n * @returns Array of values with preserved types\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const values = objectMapValues(scores)\n * // values is Array<number> instead of unknown[]\n * ```\n * @internal\n */\nexport function objectMapValues<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): Array<Value> {\n\treturn Object.values(object) as Value[]\n}\n\n/**\n * An alias for `Object.entries` that treats the object as a map and so preserves the type of the\n * keys and values. Unlike standard Object.entries which returns `Array<[string, unknown]>`, this maintains specific types.\n *\n * @param object - The object to get entries from\n * @returns Array of key-value pairs with preserved types\n * @example\n * ```ts\n * const user = { name: 'Alice', age: 30 }\n * const entries = objectMapEntries(user)\n * // entries is Array<['name' | 'age', string | number]>\n * ```\n * @internal\n */\nexport function objectMapEntries<Obj extends object>(\n\tobject: Obj\n): Array<[keyof Obj, Obj[keyof Obj]]> {\n\treturn Object.entries(object) as [keyof Obj, Obj[keyof Obj]][]\n}\n\n/**\n * Returns the entries of an object as an iterable iterator.\n * Useful when working with large collections, to avoid allocating an array.\n * Only yields own properties (not inherited ones).\n *\n * @param object - The object to iterate over\n * @returns Iterator yielding key-value pairs with preserved types\n * @example\n * ```ts\n * const largeMap = { a: 1, b: 2, c: 3 } // Imagine thousands of entries\n * for (const [key, value] of objectMapEntriesIterable(largeMap)) {\n * // Process entries one at a time without creating a large array\n * console.log(key, value)\n * }\n * ```\n * @internal\n */\nexport function* objectMapEntriesIterable<Key extends string, Value>(object: {\n\t[K in Key]: Value\n}): IterableIterator<[Key, Value]> {\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tyield [key, object[key]]\n\t}\n}\n\n/**\n * An alias for `Object.fromEntries` that treats the object as a map and so preserves the type of the\n * keys and values. Creates an object from key-value pairs with proper TypeScript typing.\n *\n * @param entries - Array of key-value pairs to convert to an object\n * @returns Object with preserved key and value types\n * @example\n * ```ts\n * const pairs: Array<['name' | 'age', string | number]> = [['name', 'Alice'], ['age', 30]]\n * const obj = objectMapFromEntries(pairs)\n * // obj is { name: string | number, age: string | number }\n * ```\n * @internal\n */\nexport function objectMapFromEntries<Key extends string, Value>(\n\tentries: ReadonlyArray<readonly [Key, Value]>\n): { [K in Key]: Value } {\n\treturn Object.fromEntries(entries) as { [K in Key]: Value }\n}\n\n/**\n * Filters an object using a predicate function, returning a new object with only the entries\n * that pass the predicate. Optimized to return the original object if no changes are needed.\n *\n * @param object - The object to filter\n * @param predicate - Function that tests each key-value pair\n * @returns A new object with only the entries that pass the predicate, or the original object if unchanged\n * @example\n * ```ts\n * const scores = { alice: 85, bob: 92, charlie: 78 }\n * const passing = filterEntries(scores, (name, score) => score >= 80)\n * // { alice: 85, bob: 92 }\n * ```\n * @internal\n */\nexport function filterEntries<Key extends string, Value>(\n\tobject: { [K in Key]: Value },\n\tpredicate: (key: Key, value: Value) => boolean\n): { [K in Key]: Value } {\n\tconst result: { [K in Key]?: Value } = {}\n\tlet didChange = false\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tconst value = object[key]\n\t\tif (predicate(key, value)) {\n\t\t\tresult[key] = value\n\t\t} else {\n\t\t\tdidChange = true\n\t\t}\n\t}\n\treturn didChange ? (result as { [K in Key]: Value }) : object\n}\n\n/**\n * Maps the values of an object to new values using a mapper function, preserving keys.\n * The mapper function receives both the key and value for each entry.\n *\n * @param object - The object whose values to transform\n * @param mapper - Function that transforms each value (receives key and value)\n * @returns A new object with the same keys but transformed values\n * @example\n * ```ts\n * const prices = { apple: 1.50, banana: 0.75, orange: 2.00 }\n * const withTax = mapObjectMapValues(prices, (fruit, price) => price * 1.08)\n * // { apple: 1.62, banana: 0.81, orange: 2.16 }\n * ```\n * @internal\n */\nexport function mapObjectMapValues<Key extends string, ValueBefore, ValueAfter>(\n\tobject: { readonly [K in Key]: ValueBefore },\n\tmapper: (key: Key, value: ValueBefore) => ValueAfter\n): { [K in Key]: ValueAfter } {\n\tconst result = {} as { [K in Key]: ValueAfter }\n\tfor (const key in object) {\n\t\tif (!Object.prototype.hasOwnProperty.call(object, key)) continue\n\t\tresult[key] = mapper(key, object[key])\n\t}\n\treturn result\n}\n\n/**\n * Performs a shallow equality check between two objects. Compares all enumerable own properties\n * using Object.is for value comparison. Returns true if both objects have the same keys and values.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @returns True if objects are shallow equal, false otherwise\n * @example\n * ```ts\n * const a = { x: 1, y: 2 }\n * const b = { x: 1, y: 2 }\n * const c = { x: 1, y: 3 }\n * areObjectsShallowEqual(a, b) // true\n * areObjectsShallowEqual(a, c) // false\n * areObjectsShallowEqual(a, a) // true (same reference)\n * ```\n * @internal\n */\nexport function areObjectsShallowEqual<T extends object>(obj1: T, obj2: T): boolean {\n\tif (obj1 === obj2) return true\n\tconst keys1 = Object.keys(obj1)\n\tif (keys1.length !== Object.keys(obj2).length) return false\n\tfor (const key of keys1) {\n\t\tif (!hasOwnProperty(obj2, key)) return false\n\t\tif (!Object.is((obj1 as any)[key], (obj2 as any)[key])) return false\n\t}\n\treturn true\n}\n\n/**\n * Groups an array of values into a record by a key extracted from each value.\n * The key selector function is called for each element to determine the grouping key.\n *\n * @param array - The array to group\n * @param keySelector - Function that extracts the grouping key from each value\n * @returns A record where keys are the extracted keys and values are arrays of grouped items\n * @example\n * ```ts\n * const people = [\n * { name: 'Alice', age: 25 },\n * { name: 'Bob', age: 30 },\n * { name: 'Charlie', age: 25 }\n * ]\n * const byAge = groupBy(people, person => `age-${person.age}`)\n * // { 'age-25': [Alice, Charlie], 'age-30': [Bob] }\n * ```\n * @internal\n */\nexport function groupBy<K extends string, V>(\n\tarray: ReadonlyArray<V>,\n\tkeySelector: (value: V) => K\n): Record<K, V[]> {\n\tconst result: Record<K, V[]> = {} as any\n\tfor (const value of array) {\n\t\tconst key = keySelector(value)\n\t\tif (!result[key]) result[key] = []\n\t\tresult[key].push(value)\n\t}\n\treturn result\n}\n\n/**\n * Creates a new object with specified keys omitted from the original object.\n * Uses shallow copying and then deletes the unwanted keys.\n *\n * @param obj - The source object\n * @param keys - Array of key names to omit from the result\n * @returns A new object without the specified keys\n * @example\n * ```ts\n * const user = { id: '123', name: 'Alice', password: 'secret', email: 'alice@example.com' }\n * const publicUser = omit(user, ['password'])\n * // { id: '123', name: 'Alice', email: 'alice@example.com' }\n * ```\n * @internal\n */\nexport function omit(\n\tobj: Record<string, unknown>,\n\tkeys: ReadonlyArray<string>\n): Record<string, unknown> {\n\tconst result = { ...obj }\n\tfor (const key of keys) {\n\t\tdelete result[key]\n\t}\n\treturn result\n}\n\n/**\n * Compares two objects and returns an array of keys where the values differ.\n * Uses Object.is for comparison, which handles NaN and -0/+0 correctly.\n * Only checks keys present in the first object.\n *\n * @param obj1 - The first object (keys to check come from this object)\n * @param obj2 - The second object to compare against\n * @returns Array of keys where values differ between the objects\n * @example\n * ```ts\n * const before = { name: 'Alice', age: 25, city: 'NYC' }\n * const after = { name: 'Alice', age: 26, city: 'NYC' }\n * const changed = getChangedKeys(before, after)\n * // ['age']\n * ```\n * @internal\n */\nexport function getChangedKeys<T extends object>(obj1: T, obj2: T): (keyof T)[] {\n\tconst result: (keyof T)[] = []\n\tfor (const key in obj1) {\n\t\tif (!Object.is(obj1[key], obj2[key])) {\n\t\t\tresult.push(key)\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Deep equality comparison that allows for floating-point precision errors.\n * Numbers are considered equal if they differ by less than the threshold.\n * Uses lodash.isequalwith internally for the deep comparison logic.\n *\n * @param obj1 - First object to compare\n * @param obj2 - Second object to compare\n * @param threshold - Maximum difference allowed between numbers (default: 0.000001)\n * @returns True if objects are deeply equal with floating-point tolerance\n * @example\n * ```ts\n * const a = { x: 0.1 + 0.2 } // 0.30000000000000004\n * const b = { x: 0.3 }\n * isEqualAllowingForFloatingPointErrors(a, b) // true\n *\n * const c = { coords: [1.0000001, 2.0000001] }\n * const d = { coords: [1.0000002, 2.0000002] }\n * isEqualAllowingForFloatingPointErrors(c, d) // true\n * ```\n * @internal\n */\nexport function isEqualAllowingForFloatingPointErrors(\n\tobj1: object,\n\tobj2: object,\n\tthreshold = 0.000001\n): boolean {\n\treturn isEqualWith(obj1, obj2, (value1, value2) => {\n\t\tif (typeof value1 === 'number' && typeof value2 === 'number') {\n\t\t\treturn Math.abs(value1 - value2) < threshold\n\t\t}\n\t\treturn undefined\n\t})\n}\n","/**\n * Color scheme for performance indicators.\n * Provides consistent colors for performance measurement displays.\n *\n * @public\n */\nexport const PERFORMANCE_COLORS = {\n\tGood: '#40C057',\n\tMid: '#FFC078',\n\tPoor: '#E03131',\n}\n\n/**\n * Default color for performance measurement log prefixes.\n * Uses the 'Good' performance color for console output styling.\n *\n * @public\n */\nexport const PERFORMANCE_PREFIX_COLOR = PERFORMANCE_COLORS.Good\n\n/**\n * Measures and logs the execution time of a callback function.\n * Executes the provided callback and logs the duration to the console with styled output.\n *\n * @param name - Descriptive name for the operation being measured\n * @param cb - Callback function to execute and measure\n * @returns The return value of the callback function\n *\n * @example\n * ```ts\n * const result = measureCbDuration('data processing', () => {\n * return processLargeDataSet(data)\n * })\n * // Console output: \"Perf data processing took 42.5ms\"\n * ```\n *\n * @internal\n */\nexport function measureCbDuration(name: string, cb: () => any) {\n\tconst start = performance.now()\n\tconst result = cb()\n\t// eslint-disable-next-line no-console\n\tconsole.debug(\n\t\t`%cPerf%c ${name} took ${performance.now() - start}ms`,\n\t\t`color: white; background: ${PERFORMANCE_PREFIX_COLOR};padding: 2px;border-radius: 3px;`,\n\t\t'font-weight: normal'\n\t)\n\treturn result\n}\n\n/**\n * Decorator that measures and logs the execution time of class methods.\n * Wraps the decorated method to automatically log its execution duration.\n *\n * @param _target - The class prototype (unused)\n * @param propertyKey - Name of the method being decorated\n * @param descriptor - Property descriptor of the method\n * @returns Modified property descriptor with timing measurement\n *\n * @example\n * ```ts\n * class DataProcessor {\n * @measureDuration\n * processData(data: unknown[]) {\n * return data.map(item => transform(item))\n * }\n * }\n * // When processData is called, logs: \"Perf processData took: 15.2ms\"\n * ```\n *\n * @internal\n */\nexport function measureDuration(_target: any, propertyKey: string, descriptor: PropertyDescriptor) {\n\tconst originalMethod = descriptor.value\n\tdescriptor.value = function (...args: any[]) {\n\t\tconst start = performance.now()\n\t\tconst result = originalMethod.apply(this, args)\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.debug(\n\t\t\t`%cPerf%c ${propertyKey} took: ${performance.now() - start}ms`,\n\t\t\t`color: white; background: ${PERFORMANCE_PREFIX_COLOR};padding: 2px;border-radius: 3px;`,\n\t\t\t'font-weight: normal'\n\t\t)\n\t\treturn result\n\t}\n\treturn descriptor\n}\n\nconst averages = new Map<any, { total: number; count: number }>()\n\n/**\n * Decorator that measures method execution time and tracks running averages.\n * Wraps the decorated method to log both current execution time and running average.\n * Maintains a running total and count for each decorated method to calculate averages.\n *\n * @param _target - The class prototype (unused)\n * @param propertyKey - Name of the method being decorated\n * @param descriptor - Property descriptor of the method\n * @returns Modified property descriptor with timing measurement and averaging\n *\n * @example\n * ```ts\n * class RenderEngine {\n * @measureAverageDuration\n * renderFrame() {\n * // Rendering logic here\n * }\n * }\n * // After multiple calls, logs: \"Perf renderFrame took 16.67ms | average 15.83ms\"\n * ```\n *\n * @internal\n */\nexport function measureAverageDuration(\n\t_target: any,\n\tpropertyKey: string,\n\tdescriptor: PropertyDescriptor\n) {\n\tconst originalMethod = descriptor.value\n\tdescriptor.value = function (...args: any[]) {\n\t\tconst start = performance.now()\n\t\tconst result = originalMethod.apply(this, args)\n\t\tconst end = performance.now()\n\t\tconst length = end - start\n\t\tif (length !== 0) {\n\t\t\tconst value = averages.get(descriptor.value)!\n\t\t\tconst total = value.total + length\n\t\t\tconst count = value.count + 1\n\t\t\taverages.set(descriptor.value, { total, count })\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.debug(\n\t\t\t\t`%cPerf%c ${propertyKey} took ${(end - start).toFixed(2)}ms | average ${(total / count).toFixed(2)}ms`,\n\t\t\t\t`color: white; background: ${PERFORMANCE_PREFIX_COLOR};padding: 2px;border-radius: 3px;`,\n\t\t\t\t'font-weight: normal'\n\t\t\t)\n\t\t}\n\t\treturn result\n\t}\n\taverages.set(descriptor.value, { total: 0, count: 0 })\n\treturn descriptor\n}\n","import { PERFORMANCE_COLORS, PERFORMANCE_PREFIX_COLOR } from './perf'\n\n/**\n * A utility class for measuring and tracking frame rate performance during operations.\n * Provides visual feedback in the browser console with color-coded FPS indicators.\n *\n * @example\n * ```ts\n * const tracker = new PerformanceTracker()\n *\n * tracker.start('render')\n * renderShapes()\n * tracker.stop() // Logs performance info to console\n *\n * // Check if tracking is active\n * if (tracker.isStarted()) {\n * console.log('Still tracking performance')\n * }\n * ```\n *\n * @public\n */\nexport class PerformanceTracker {\n\tprivate startTime = 0\n\tprivate name = ''\n\tprivate frames = 0\n\tprivate started = false\n\tprivate frame: number | null = null\n\n\t/**\n\t * Records animation frames to calculate frame rate.\n\t * Called automatically during performance tracking.\n\t */\n\t// eslint-disable-next-line tldraw/prefer-class-methods\n\trecordFrame = () => {\n\t\tthis.frames++\n\t\tif (!this.started) return\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tthis.frame = requestAnimationFrame(this.recordFrame)\n\t}\n\n\t/**\n\t * Starts performance tracking for a named operation.\n\t *\n\t * @param name - A descriptive name for the operation being tracked\n\t *\n\t * @example\n\t * ```ts\n\t * tracker.start('canvas-render')\n\t * // ... perform rendering operations\n\t * tracker.stop()\n\t * ```\n\t */\n\tstart(name: string) {\n\t\tthis.name = name\n\t\tthis.frames = 0\n\t\tthis.started = true\n\t\tif (this.frame !== null) cancelAnimationFrame(this.frame)\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tthis.frame = requestAnimationFrame(this.recordFrame)\n\t\tthis.startTime = performance.now()\n\t}\n\n\t/**\n\t * Stops performance tracking and logs results to the console.\n\t *\n\t * Displays the operation name, frame rate, and uses color coding:\n\t * - Green background: \\> 55 FPS (good performance)\n\t * - Yellow background: 30-55 FPS (moderate performance)\n\t * - Red background: \\< 30 FPS (poor performance)\n\t *\n\t * @example\n\t * ```ts\n\t * tracker.start('interaction')\n\t * handleUserInteraction()\n\t * tracker.stop() // Logs: \"Perf Interaction 60 fps\"\n\t * ```\n\t */\n\tstop() {\n\t\tthis.started = false\n\t\tif (this.frame !== null) cancelAnimationFrame(this.frame)\n\t\tconst duration = (performance.now() - this.startTime) / 1000\n\t\tconst fps = duration === 0 ? 0 : Math.floor(this.frames / duration)\n\t\tconst background =\n\t\t\tfps > 55\n\t\t\t\t? PERFORMANCE_COLORS.Good\n\t\t\t\t: fps > 30\n\t\t\t\t\t? PERFORMANCE_COLORS.Mid\n\t\t\t\t\t: PERFORMANCE_COLORS.Poor\n\t\tconst color = background === PERFORMANCE_COLORS.Mid ? 'black' : 'white'\n\t\tconst capitalized = this.name[0].toUpperCase() + this.name.slice(1)\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.debug(\n\t\t\t`%cPerf%c ${capitalized} %c${fps}%c fps`,\n\t\t\t`color: white; background: ${PERFORMANCE_PREFIX_COLOR};padding: 2px;border-radius: 3px;`,\n\t\t\t'font-weight: normal',\n\t\t\t`font-weight: bold; padding: 2px; background: ${background};color: ${color};`,\n\t\t\t'font-weight: normal'\n\t\t)\n\t}\n\n\t/**\n\t * Checks whether performance tracking is currently active.\n\t *\n\t * @returns True if tracking is in progress, false otherwise\n\t *\n\t * @example\n\t * ```ts\n\t * if (!tracker.isStarted()) {\n\t * tracker.start('new-operation')\n\t * }\n\t * ```\n\t */\n\tisStarted() {\n\t\treturn this.started\n\t}\n}\n","import { generateKeyBetween, generateNKeysBetween } from 'jittered-fractional-indexing'\n\nconst generateNKeysBetweenWithNoJitter = (a: string | null, b: string | null, n: number) => {\n\treturn generateNKeysBetween(a, b, n, { jitterBits: 0 })\n}\n\nconst generateKeysFn =\n\tprocess.env.NODE_ENV === 'test' ? generateNKeysBetweenWithNoJitter : generateNKeysBetween\n\n/**\n * A string made up of an integer part followed by a fraction part. The fraction point consists of\n * zero or more digits with no trailing zeros. Based on\n * {@link https://observablehq.com/@dgreensp/implementing-fractional-indexing}.\n *\n * @public\n */\nexport type IndexKey = string & { __brand: 'indexKey' }\n\n/**\n * The index key for the first index - 'a0'.\n * @public\n */\nexport const ZERO_INDEX_KEY = 'a0' as IndexKey\n\n/**\n * Validates that a string is a valid IndexKey.\n * @param index - The string to validate.\n * @throws Error if the index is invalid.\n * @internal\n */\nexport function validateIndexKey(index: string): asserts index is IndexKey {\n\ttry {\n\t\tgenerateKeyBetween(index, null)\n\t} catch {\n\t\tthrow new Error('invalid index: ' + index)\n\t}\n}\n\n/**\n * Get a number of indices between two indices.\n * @param below - The index below.\n * @param above - The index above.\n * @param n - The number of indices to get.\n * @returns An array of n IndexKey values between below and above.\n * @example\n * ```ts\n * const indices = getIndicesBetween('a0' as IndexKey, 'a2' as IndexKey, 2)\n * console.log(indices) // ['a0V', 'a1']\n * ```\n * @public\n */\nexport function getIndicesBetween(\n\tbelow: IndexKey | null | undefined,\n\tabove: IndexKey | null | undefined,\n\tn: number\n) {\n\treturn generateKeysFn(below ?? null, above ?? null, n) as IndexKey[]\n}\n\n/**\n * Get a number of indices above an index.\n * @param below - The index below.\n * @param n - The number of indices to get.\n * @returns An array of n IndexKey values above the given index.\n * @example\n * ```ts\n * const indices = getIndicesAbove('a0' as IndexKey, 3)\n * console.log(indices) // ['a1', 'a2', 'a3']\n * ```\n * @public\n */\nexport function getIndicesAbove(below: IndexKey | null | undefined, n: number) {\n\treturn generateKeysFn(below ?? null, null, n) as IndexKey[]\n}\n\n/**\n * Get a number of indices below an index.\n * @param above - The index above.\n * @param n - The number of indices to get.\n * @returns An array of n IndexKey values below the given index.\n * @example\n * ```ts\n * const indices = getIndicesBelow('a2' as IndexKey, 2)\n * console.log(indices) // ['a1', 'a0V']\n * ```\n * @public\n */\nexport function getIndicesBelow(above: IndexKey | null | undefined, n: number) {\n\treturn generateKeysFn(null, above ?? null, n) as IndexKey[]\n}\n\n/**\n * Get the index between two indices.\n * @param below - The index below.\n * @param above - The index above.\n * @returns A single IndexKey value between below and above.\n * @example\n * ```ts\n * const index = getIndexBetween('a0' as IndexKey, 'a2' as IndexKey)\n * console.log(index) // 'a1'\n * ```\n * @public\n */\nexport function getIndexBetween(\n\tbelow: IndexKey | null | undefined,\n\tabove: IndexKey | null | undefined\n) {\n\treturn generateKeysFn(below ?? null, above ?? null, 1)[0] as IndexKey\n}\n\n/**\n * Get the index above a given index.\n * @param below - The index below.\n * @returns An IndexKey value above the given index.\n * @example\n * ```ts\n * const index = getIndexAbove('a0' as IndexKey)\n * console.log(index) // 'a1'\n * ```\n * @public\n */\nexport function getIndexAbove(below: IndexKey | null | undefined = null) {\n\treturn generateKeysFn(below, null, 1)[0] as IndexKey\n}\n\n/**\n * Get the index below a given index.\n * @param above - The index above.\n * @returns An IndexKey value below the given index.\n * @example\n * ```ts\n * const index = getIndexBelow('a2' as IndexKey)\n * console.log(index) // 'a1'\n * ```\n * @public\n */\nexport function getIndexBelow(above: IndexKey | null | undefined = null) {\n\treturn generateKeysFn(null, above, 1)[0] as IndexKey\n}\n\n/**\n * Get n number of indices, starting at an index.\n * @param n - The number of indices to get.\n * @param start - The index to start at.\n * @returns An array containing the start index plus n additional IndexKey values.\n * @example\n * ```ts\n * const indices = getIndices(3, 'a1' as IndexKey)\n * console.log(indices) // ['a1', 'a2', 'a3', 'a4']\n * ```\n * @public\n */\nexport function getIndices(n: number, start = 'a1' as IndexKey) {\n\treturn [start, ...generateKeysFn(start, null, n)] as IndexKey[]\n}\n\n/**\n * Sort by index.\n * @param a - An object with an index property.\n * @param b - An object with an index property.\n * @returns A number indicating sort order (-1, 0, or 1).\n * @example\n * ```ts\n * const shapes = [\n * { id: 'b', index: 'a2' as IndexKey },\n * { id: 'a', index: 'a1' as IndexKey }\n * ]\n * const sorted = shapes.sort(sortByIndex)\n * console.log(sorted) // [{ id: 'a', index: 'a1' }, { id: 'b', index: 'a2' }]\n * ```\n * @public\n */\nexport function sortByIndex<T extends { index: IndexKey }>(a: T, b: T) {\n\tif (a.index < b.index) {\n\t\treturn -1\n\t} else if (a.index > b.index) {\n\t\treturn 1\n\t}\n\treturn 0\n}\n\n/**\n * Sort by index, or null.\n * @param a - An object with an index property.\n * @param b - An object with an index property.\n * @public\n */\nexport function sortByMaybeIndex<T extends { index?: IndexKey | null }>(a: T, b: T) {\n\tif (a.index && b.index) {\n\t\treturn a.index < b.index ? -1 : 1\n\t}\n\tif (a.index && b.index == null) {\n\t\treturn -1\n\t}\n\tif (a.index == null && b.index == null) {\n\t\treturn 0\n\t}\n\treturn 1\n}\n","import { sleep } from './control'\n\n/**\n * Retries an async operation with configurable attempt count, wait duration, and error filtering.\n * Executes the provided async function repeatedly until it succeeds or the maximum number of attempts is reached.\n * Includes support for abort signals and custom error matching to determine which errors should trigger retries.\n *\n * @param fn - The async function to retry on failure\n * @param options - Configuration options for retry behavior:\n * - `attempts`: Maximum number of retry attempts (default: 3)\n * - `waitDuration`: Milliseconds to wait between retry attempts (default: 1000)\n * - `abortSignal`: Optional AbortSignal to cancel the retry operation\n * - `matchError`: Optional function to determine if an error should trigger a retry\n * @returns Promise that resolves with the function's return value on success\n *\n * @example\n * ```ts\n * // Basic retry with default settings (3 attempts, 1 second wait)\n * const data = await retry(async () => {\n * const response = await fetch('/api/data')\n * if (!response.ok) throw new Error('Network error')\n * return response.json()\n * })\n *\n * // Custom retry configuration\n * const result = await retry(\n * async () => unreliableApiCall(),\n * {\n * attempts: 5,\n * waitDuration: 2000,\n * matchError: (error) => error instanceof NetworkError\n * }\n * )\n *\n * // With abort signal for cancellation\n * const controller = new AbortController()\n * setTimeout(() => controller.abort(), 10000) // Cancel after 10 seconds\n *\n * const data = await retry(\n * async () => fetchData(),\n * {\n * attempts: 10,\n * abortSignal: controller.signal\n * }\n * )\n * ```\n *\n * @internal\n */\nexport async function retry<T>(\n\tfn: (args: { attempt: number; remaining: number; total: number }) => Promise<T>,\n\t{\n\t\tattempts = 3,\n\t\twaitDuration = 1000,\n\t\tabortSignal,\n\t\tmatchError,\n\t}: {\n\t\tattempts?: number\n\t\twaitDuration?: number\n\t\tabortSignal?: AbortSignal\n\t\tmatchError?(error: unknown): boolean\n\t} = {}\n): Promise<T> {\n\tlet error: unknown = null\n\tfor (let i = 0; i < attempts; i++) {\n\t\tif (abortSignal?.aborted) throw new Error('aborted')\n\t\ttry {\n\t\t\treturn await fn({ attempt: i, remaining: attempts - i, total: attempts })\n\t\t} catch (e) {\n\t\t\tif (matchError && !matchError(e)) throw e\n\t\t\terror = e\n\t\t\tawait sleep(waitDuration)\n\t\t}\n\t}\n\t// eslint-disable-next-line no-throw-literal\n\tthrow error\n}\n","/**\n * Compares two objects by their id property for use with Array.sort().\n * Sorts objects in ascending order based on their id values.\n *\n * @param a - First object to compare\n * @param b - Second object to compare\n * @returns 1 if a.id \\> b.id, -1 if a.id \\<= b.id\n *\n * @example\n * ```ts\n * const items = [\n * { id: 'c', name: 'Charlie' },\n * { id: 'a', name: 'Alice' },\n * { id: 'b', name: 'Bob' },\n * ]\n *\n * const sorted = items.sort(sortById)\n * // [{ id: 'a', name: 'Alice' }, { id: 'b', name: 'Bob' }, { id: 'c', name: 'Charlie' }]\n * ```\n *\n * @public\n */\nexport function sortById<T extends { id: any }>(a: T, b: T) {\n\treturn a.id > b.id ? 1 : -1\n}\n","/* eslint-disable tldraw/no-direct-storage */\n\n/**\n * Get a value from local storage.\n *\n * @param key - The key to get.\n * @returns The stored value as a string, or null if not found or storage is unavailable.\n * @example\n * ```ts\n * const userTheme = getFromLocalStorage('user-theme')\n * if (userTheme) {\n * console.log('Stored theme:', userTheme)\n * }\n * ```\n * @internal\n */\nexport function getFromLocalStorage(key: string) {\n\ttry {\n\t\treturn localStorage.getItem(key)\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Set a value in local storage. Will not throw an error if localStorage is not available.\n *\n * @param key - The key to set.\n * @param value - The value to set.\n * @returns void\n * @example\n * ```ts\n * const preferences = { theme: 'dark', language: 'en' }\n * setInLocalStorage('user-preferences', JSON.stringify(preferences))\n * ```\n * @internal\n */\nexport function setInLocalStorage(key: string, value: string) {\n\ttry {\n\t\tlocalStorage.setItem(key, value)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Remove a value from local storage. Will not throw an error if localStorage is not available.\n *\n * @param key - The key to remove.\n * @returns void\n * @example\n * ```ts\n * deleteFromLocalStorage('user-preferences')\n * // Value is now removed from localStorage\n * ```\n * @internal\n */\nexport function deleteFromLocalStorage(key: string) {\n\ttry {\n\t\tlocalStorage.removeItem(key)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Clear all values from local storage. Will not throw an error if localStorage is not available.\n *\n * @returns void\n * @example\n * ```ts\n * clearLocalStorage()\n * // All localStorage data is now cleared\n * ```\n * @internal\n */\nexport function clearLocalStorage() {\n\ttry {\n\t\tlocalStorage.clear()\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Get a value from session storage.\n *\n * @param key - The key to get.\n * @returns The stored value as a string, or null if not found or storage is unavailable.\n * @example\n * ```ts\n * const currentTool = getFromSessionStorage('current-tool')\n * if (currentTool) {\n * console.log('Active tool:', currentTool)\n * }\n * ```\n * @internal\n */\nexport function getFromSessionStorage(key: string) {\n\ttry {\n\t\treturn sessionStorage.getItem(key)\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Set a value in session storage. Will not throw an error if sessionStorage is not available.\n *\n * @param key - The key to set.\n * @param value - The value to set.\n * @returns void\n * @example\n * ```ts\n * setInSessionStorage('current-tool', 'select')\n * setInSessionStorage('temp-data', JSON.stringify({ x: 100, y: 200 }))\n * ```\n * @internal\n */\nexport function setInSessionStorage(key: string, value: string) {\n\ttry {\n\t\tsessionStorage.setItem(key, value)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Remove a value from session storage. Will not throw an error if sessionStorage is not available.\n *\n * @param key - The key to remove.\n * @returns void\n * @example\n * ```ts\n * deleteFromSessionStorage('temp-data')\n * // Value is now removed from sessionStorage\n * ```\n * @internal\n */\nexport function deleteFromSessionStorage(key: string) {\n\ttry {\n\t\tsessionStorage.removeItem(key)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Clear all values from session storage. Will not throw an error if sessionStorage is not available.\n *\n * @returns void\n * @example\n * ```ts\n * clearSessionStorage()\n * // All sessionStorage data is now cleared\n * ```\n * @internal\n */\nexport function clearSessionStorage() {\n\ttry {\n\t\tsessionStorage.clear()\n\t} catch {\n\t\t// noop\n\t}\n}\n","/**\n * Creates an enum-like object from string values where each key maps to itself.\n * Useful for creating string constant objects with type safety and autocompletion.\n * @param values - The string values to create the enum from.\n * @returns An object where each provided string is both the key and value.\n * @example\n * ```ts\n * const Colors = stringEnum('red', 'green', 'blue')\n * // Results in: { red: 'red', green: 'green', blue: 'blue' }\n *\n * // Type-safe usage\n * function setColor(color: keyof typeof Colors) {\n * console.log(`Setting color to ${Colors[color]}`)\n * }\n *\n * setColor('red') // ✓ Valid\n * setColor('yellow') // ✗ TypeScript error\n * ```\n * @internal\n */\nexport function stringEnum<T extends string>(...values: T[]): { [K in T]: K } {\n\tconst obj = {} as { [K in T]: K }\n\tfor (const value of values) {\n\t\tobj[value] = value\n\t}\n\treturn obj\n}\n","const isTest = () =>\n\ttypeof process !== 'undefined' &&\n\tprocess.env.NODE_ENV === 'test' &&\n\t// @ts-expect-error\n\t!globalThis.__FORCE_RAF_IN_TESTS__\n\n// Browsers aren't precise with frame timing - this factor prevents skipping frames unnecessarily\n// by aiming slightly below the theoretical frame duration (e.g., ~7.5ms instead of 8.33ms for 120fps)\nconst timingVarianceFactor = 0.9\nconst getTargetTimePerFrame = (targetFps: number) =>\n\tMath.floor(1000 / targetFps) * timingVarianceFactor\n\n/**\n * A scheduler class that manages a queue of functions to be executed at a target frame rate.\n * Each instance maintains its own queue and state, allowing for separate throttling contexts\n * (e.g., UI operations vs network sync operations).\n *\n * @public\n */\nexport class FpsScheduler {\n\tprivate targetFps: number\n\tprivate targetTimePerFrame: number\n\tprivate fpsQueue: Array<() => void> = []\n\tprivate frameRaf: undefined | number\n\tprivate flushRaf: undefined | number\n\tprivate lastFlushTime: number\n\n\tconstructor(targetFps: number = 120) {\n\t\tthis.targetFps = targetFps\n\t\tthis.targetTimePerFrame = getTargetTimePerFrame(targetFps)\n\t\tthis.lastFlushTime = -this.targetTimePerFrame\n\t}\n\n\tupdateTargetFps(targetFps: number) {\n\t\tif (targetFps === this.targetFps) return\n\t\tthis.targetFps = targetFps\n\t\tthis.targetTimePerFrame = getTargetTimePerFrame(targetFps)\n\t\tthis.lastFlushTime = -this.targetTimePerFrame\n\t}\n\n\tprivate flush() {\n\t\tconst queue = this.fpsQueue.splice(0, this.fpsQueue.length)\n\t\tfor (const fn of queue) {\n\t\t\tfn()\n\t\t}\n\t}\n\n\tprivate tick(isOnNextFrame = false) {\n\t\tif (this.frameRaf) return\n\n\t\tconst now = Date.now()\n\t\tconst elapsed = now - this.lastFlushTime\n\n\t\tif (elapsed < this.targetTimePerFrame) {\n\t\t\t// If we're too early to flush, we need to wait until the next frame to try and flush again.\n\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\tthis.frameRaf = requestAnimationFrame(() => {\n\t\t\t\tthis.frameRaf = undefined\n\t\t\t\tthis.tick(true)\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tif (isOnNextFrame) {\n\t\t\t// If we've already waited for the next frame to run the tick, then we can flush immediately\n\t\t\tif (this.flushRaf) return // ...though if there's a flush raf, that means we'll be flushing on this frame already, so we can do nothing here.\n\t\t\tthis.lastFlushTime = now\n\t\t\tthis.flush()\n\t\t} else {\n\t\t\t// If we haven't already waited for the next frame to run the tick, we need to wait until the next frame to flush.\n\t\t\tif (this.flushRaf) return // ...though if there's a flush raf, that means we'll be flushing on the next frame already, so we can do nothing here.\n\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\tthis.flushRaf = requestAnimationFrame(() => {\n\t\t\t\tthis.flushRaf = undefined\n\t\t\t\tthis.lastFlushTime = Date.now()\n\t\t\t\tthis.flush()\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Creates a throttled version of a function that executes at most once per frame.\n\t * The default target frame rate is set by the FpsScheduler instance.\n\t * Subsequent calls within the same frame are ignored, ensuring smooth performance\n\t * for high-frequency events like mouse movements or scroll events.\n\t *\n\t * @param fn - The function to throttle, optionally with a cancel method\n\t * @returns A throttled function with an optional cancel method to remove pending calls\n\t *\n\t * @public\n\t */\n\tfpsThrottle(fn: { (): void; cancel?(): void }): {\n\t\t(): void\n\t\tcancel?(): void\n\t} {\n\t\tif (isTest()) {\n\t\t\tfn.cancel = () => {\n\t\t\t\tif (this.frameRaf) {\n\t\t\t\t\tcancelAnimationFrame(this.frameRaf)\n\t\t\t\t\tthis.frameRaf = undefined\n\t\t\t\t}\n\t\t\t\tif (this.flushRaf) {\n\t\t\t\t\tcancelAnimationFrame(this.flushRaf)\n\t\t\t\t\tthis.flushRaf = undefined\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn fn\n\t\t}\n\n\t\tconst throttledFn = () => {\n\t\t\tif (this.fpsQueue.includes(fn)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.fpsQueue.push(fn)\n\t\t\tthis.tick()\n\t\t}\n\t\tthrottledFn.cancel = () => {\n\t\t\tconst index = this.fpsQueue.indexOf(fn)\n\t\t\tif (index > -1) {\n\t\t\t\tthis.fpsQueue.splice(index, 1)\n\t\t\t}\n\t\t}\n\t\treturn throttledFn\n\t}\n\n\t/**\n\t * Schedules a function to execute on the next animation frame.\n\t * If the same function is passed multiple times before the frame executes,\n\t * it will only be called once, effectively batching multiple calls.\n\t *\n\t * @param fn - The function to execute on the next frame\n\t * @returns A cancel function that can prevent execution if called before the next frame\n\t *\n\t * @public\n\t */\n\tthrottleToNextFrame(fn: () => void): () => void {\n\t\tif (isTest()) {\n\t\t\tfn()\n\t\t\treturn () => void null // noop\n\t\t}\n\n\t\tif (!this.fpsQueue.includes(fn)) {\n\t\t\tthis.fpsQueue.push(fn)\n\t\t\tthis.tick()\n\t\t}\n\n\t\treturn () => {\n\t\t\tconst index = this.fpsQueue.indexOf(fn)\n\t\t\tif (index > -1) {\n\t\t\t\tthis.fpsQueue.splice(index, 1)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Default instance for UI operations\nconst defaultScheduler = new FpsScheduler(120)\n\n/**\n * Creates a throttled version of a function that executes at most once per frame.\n * The default target frame rate is 120fps, but can be customized per function.\n * Subsequent calls within the same frame are ignored, ensuring smooth performance\n * for high-frequency events like mouse movements or scroll events.\n *\n * Uses the default throttle instance for UI operations. If you need a separate\n * throttling queue (e.g., for network operations), create your own Throttle instance.\n *\n * @param fn - The function to throttle, optionally with a cancel method\n * @returns A throttled function with an optional cancel method to remove pending calls\n *\n * @example\n * ```ts\n * // Default 120fps throttling\n * const updateCanvas = fpsThrottle(() => {\n * // This will run at most once per frame (~8.33ms)\n * redrawCanvas()\n * })\n *\n * // Call as often as you want - automatically throttled to 120fps\n * document.addEventListener('mousemove', updateCanvas)\n *\n * // Cancel pending calls if needed\n * updateCanvas.cancel?.()\n * ```\n *\n * @internal\n */\nexport function fpsThrottle(fn: { (): void; cancel?(): void }): {\n\t(): void\n\tcancel?(): void\n} {\n\treturn defaultScheduler.fpsThrottle(fn)\n}\n\n/**\n * Schedules a function to execute on the next animation frame, targeting 120fps.\n * If the same function is passed multiple times before the frame executes,\n * it will only be called once, effectively batching multiple calls.\n *\n * Uses the default throttle instance for UI operations.\n *\n * @param fn - The function to execute on the next frame\n * @returns A cancel function that can prevent execution if called before the next frame\n *\n * @example\n * ```ts\n * const updateUI = throttleToNextFrame(() => {\n * // Batches multiple calls into the next animation frame\n * updateStatusBar()\n * refreshToolbar()\n * })\n *\n * // Multiple calls within the same frame are batched\n * updateUI() // Will execute\n * updateUI() // Ignored (same function already queued)\n * updateUI() // Ignored (same function already queued)\n *\n * // Get cancel function to prevent execution\n * const cancel = updateUI()\n * cancel() // Prevents execution if called before next frame\n * ```\n *\n * @internal\n */\nexport function throttleToNextFrame(fn: () => void): () => void {\n\treturn defaultScheduler.throttleToNextFrame(fn)\n}\n","/* eslint-disable tldraw/no-restricted-properties */\n\n/**\n * A utility class for managing timeouts, intervals, and animation frames with context-based organization and automatic cleanup.\n * Helps prevent memory leaks by organizing timers into named contexts that can be cleared together.\n * @example\n * ```ts\n * const timers = new Timers()\n *\n * // Set timers with context organization\n * timers.setTimeout('ui', () => console.log('Auto save'), 5000)\n * timers.setInterval('ui', () => console.log('Refresh'), 1000)\n * timers.requestAnimationFrame('ui', () => console.log('Render'))\n *\n * // Clear all timers for a context\n * timers.dispose('ui')\n *\n * // Or get context-bound functions\n * const uiTimers = timers.forContext('ui')\n * uiTimers.setTimeout(() => console.log('Contextual timeout'), 1000)\n * ```\n * @public\n */\nexport class Timers {\n\tprivate timeouts = new Map<string, number[]>()\n\tprivate intervals = new Map<string, number[]>()\n\tprivate rafs = new Map<string, number[]>()\n\n\t/**\n\t * Creates a new Timers instance with bound methods for safe callback usage.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * // Methods are pre-bound, safe to use as callbacks\n\t * element.addEventListener('click', timers.dispose)\n\t * ```\n\t */\n\tconstructor() {\n\t\tthis.setTimeout = this.setTimeout.bind(this)\n\t\tthis.setInterval = this.setInterval.bind(this)\n\t\tthis.requestAnimationFrame = this.requestAnimationFrame.bind(this)\n\t\tthis.dispose = this.dispose.bind(this)\n\t}\n\n\t/**\n\t * Creates a timeout that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this timer under.\n\t * @param handler - The function to execute when the timeout expires.\n\t * @param timeout - The delay in milliseconds (default: 0).\n\t * @param args - Additional arguments to pass to the handler.\n\t * @returns The timer ID that can be used with clearTimeout.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.setTimeout('autosave', () => save(), 5000)\n\t * // Timer will be automatically cleared when 'autosave' context is disposed\n\t * ```\n\t * @public\n\t */\n\tsetTimeout(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number {\n\t\tconst id = window.setTimeout(handler, timeout, args)\n\t\tconst current = this.timeouts.get(contextId) ?? []\n\t\tthis.timeouts.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Creates an interval that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this timer under.\n\t * @param handler - The function to execute repeatedly.\n\t * @param timeout - The delay in milliseconds between executions (default: 0).\n\t * @param args - Additional arguments to pass to the handler.\n\t * @returns The interval ID that can be used with clearInterval.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.setInterval('refresh', () => updateData(), 1000)\n\t * // Interval will be automatically cleared when 'refresh' context is disposed\n\t * ```\n\t * @public\n\t */\n\tsetInterval(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number {\n\t\tconst id = window.setInterval(handler, timeout, args)\n\t\tconst current = this.intervals.get(contextId) ?? []\n\t\tthis.intervals.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Requests an animation frame that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this animation frame under.\n\t * @param callback - The function to execute on the next animation frame.\n\t * @returns The request ID that can be used with cancelAnimationFrame.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.requestAnimationFrame('render', () => draw())\n\t * // Animation frame will be automatically cancelled when 'render' context is disposed\n\t * ```\n\t * @public\n\t */\n\trequestAnimationFrame(contextId: string, callback: FrameRequestCallback): number {\n\t\tconst id = window.requestAnimationFrame(callback)\n\t\tconst current = this.rafs.get(contextId) ?? []\n\t\tthis.rafs.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Disposes of all timers associated with the specified context.\n\t * Clears all timeouts, intervals, and animation frames for the given context ID.\n\t * @param contextId - The context identifier whose timers should be cleared.\n\t * @returns void\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * timers.setTimeout('ui', () => console.log('timeout'), 1000)\n\t * timers.setInterval('ui', () => console.log('interval'), 500)\n\t *\n\t * // Clear all 'ui' context timers\n\t * timers.dispose('ui')\n\t * ```\n\t * @public\n\t */\n\tdispose(contextId: string) {\n\t\tthis.timeouts.get(contextId)?.forEach((id) => clearTimeout(id))\n\t\tthis.intervals.get(contextId)?.forEach((id) => clearInterval(id))\n\t\tthis.rafs.get(contextId)?.forEach((id) => cancelAnimationFrame(id))\n\n\t\tthis.timeouts.delete(contextId)\n\t\tthis.intervals.delete(contextId)\n\t\tthis.rafs.delete(contextId)\n\t}\n\n\t/**\n\t * Disposes of all timers across all contexts.\n\t * Clears every timeout, interval, and animation frame managed by this instance.\n\t * @returns void\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * timers.setTimeout('ui', () => console.log('ui'), 1000)\n\t * timers.setTimeout('background', () => console.log('bg'), 2000)\n\t *\n\t * // Clear everything\n\t * timers.disposeAll()\n\t * ```\n\t * @public\n\t */\n\tdisposeAll() {\n\t\tfor (const contextId of this.timeouts.keys()) {\n\t\t\tthis.dispose(contextId)\n\t\t}\n\t}\n\n\t/**\n\t * Returns an object with timer methods bound to a specific context.\n\t * Convenient for getting context-specific timer functions without repeatedly passing the contextId.\n\t * @param contextId - The context identifier to bind the returned methods to.\n\t * @returns An object with setTimeout, setInterval, requestAnimationFrame, and dispose methods bound to the context.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const uiTimers = timers.forContext('ui')\n\t *\n\t * // These are equivalent to calling timers.setTimeout('ui', ...)\n\t * uiTimers.setTimeout(() => console.log('timeout'), 1000)\n\t * uiTimers.setInterval(() => console.log('interval'), 500)\n\t * uiTimers.requestAnimationFrame(() => console.log('frame'))\n\t *\n\t * // Dispose only this context\n\t * uiTimers.dispose()\n\t * ```\n\t * @public\n\t */\n\tforContext(contextId: string) {\n\t\treturn {\n\t\t\tsetTimeout: (handler: TimerHandler, timeout?: number, ...args: any[]) =>\n\t\t\t\tthis.setTimeout(contextId, handler, timeout, args),\n\t\t\tsetInterval: (handler: TimerHandler, timeout?: number, ...args: any[]) =>\n\t\t\t\tthis.setInterval(contextId, handler, timeout, args),\n\t\t\trequestAnimationFrame: (callback: FrameRequestCallback) =>\n\t\t\t\tthis.requestAnimationFrame(contextId, callback),\n\t\t\tdispose: () => this.dispose(contextId),\n\t\t}\n\t}\n}\n","/**\n * Safely parses a URL string without throwing exceptions on invalid input.\n * Returns a URL object for valid URLs or undefined for invalid ones.\n *\n * @param url - The URL string to parse\n * @param baseUrl - Optional base URL to resolve relative URLs against\n * @returns A URL object if parsing succeeds, undefined if it fails\n *\n * @example\n * ```ts\n * // Valid absolute URL\n * const url1 = safeParseUrl('https://example.com')\n * if (url1) {\n * console.log(`Valid URL: ${url1.href}`) // \"Valid URL: https://example.com/\"\n * }\n *\n * // Invalid URL\n * const url2 = safeParseUrl('not-a-url')\n * console.log(url2) // undefined\n *\n * // Relative URL with base\n * const url3 = safeParseUrl('/path', 'https://example.com')\n * if (url3) {\n * console.log(url3.href) // \"https://example.com/path\"\n * }\n *\n * // Error handling\n * function handleUserUrl(input: string) {\n * const url = safeParseUrl(input)\n * if (url) {\n * return url\n * } else {\n * console.log('Invalid URL provided')\n * return null\n * }\n * }\n * ```\n *\n * @public\n */\nexport const safeParseUrl = (url: string, baseUrl?: string | URL) => {\n\ttry {\n\t\treturn new URL(url, baseUrl)\n\t} catch {\n\t\treturn\n\t}\n}\n","/**\n * Get whether a value is not undefined.\n *\n * @param value - The value to check.\n * @returns True if the value is not undefined, with proper type narrowing.\n * @example\n * ```ts\n * const maybeString: string | undefined = getValue()\n *\n * if (isDefined(maybeString)) {\n * // TypeScript knows maybeString is string, not undefined\n * console.log(maybeString.toUpperCase())\n * }\n *\n * // Filter undefined values from arrays\n * const values = [1, undefined, 2, undefined, 3]\n * const definedValues = values.filter(isDefined) // [1, 2, 3]\n * ```\n * @public\n */\nexport function isDefined<T>(value: T): value is typeof value extends undefined ? never : T {\n\treturn value !== undefined\n}\n\n/**\n * Get whether a value is not null.\n *\n * @param value - The value to check.\n * @returns True if the value is not null, with proper type narrowing.\n * @example\n * ```ts\n * const maybeString: string | null = getValue()\n *\n * if (isNonNull(maybeString)) {\n * // TypeScript knows maybeString is string, not null\n * console.log(maybeString.length)\n * }\n *\n * // Filter null values from arrays\n * const values = [\"a\", null, \"b\", null, \"c\"]\n * const nonNullValues = values.filter(isNonNull) // [\"a\", \"b\", \"c\"]\n * ```\n * @public\n */\nexport function isNonNull<T>(value: T): value is typeof value extends null ? never : T {\n\treturn value !== null\n}\n\n/**\n * Get whether a value is not nullish (not null and not undefined).\n *\n * @param value - The value to check.\n * @returns True if the value is neither null nor undefined, with proper type narrowing.\n * @example\n * ```ts\n * const maybeString: string | null | undefined = getValue()\n *\n * if (isNonNullish(maybeString)) {\n * // TypeScript knows maybeString is string, not null or undefined\n * console.log(maybeString.charAt(0))\n * }\n *\n * // Filter nullish values from arrays\n * const values = [\"hello\", null, \"world\", undefined, \"!\"]\n * const cleanValues = values.filter(isNonNullish) // [\"hello\", \"world\", \"!\"]\n * ```\n * @public\n */\nexport function isNonNullish<T>(\n\tvalue: T\n): value is typeof value extends undefined ? never : typeof value extends null ? never : T {\n\treturn value !== null && value !== undefined\n}\n\nfunction getStructuredClone(): [<T>(i: T) => T, boolean] {\n\tif (typeof globalThis !== 'undefined' && (globalThis as any).structuredClone) {\n\t\treturn [globalThis.structuredClone as <T>(i: T) => T, true]\n\t}\n\n\tif (typeof global !== 'undefined' && (global as any).structuredClone) {\n\t\treturn [global.structuredClone as <T>(i: T) => T, true]\n\t}\n\n\tif (typeof window !== 'undefined' && (window as any).structuredClone) {\n\t\treturn [window.structuredClone as <T>(i: T) => T, true]\n\t}\n\n\treturn [<T>(i: T): T => (i ? JSON.parse(JSON.stringify(i)) : i), false]\n}\n\nconst _structuredClone = getStructuredClone()\n\n/**\n * Create a deep copy of a value. Uses the structuredClone API if available, otherwise uses JSON.parse(JSON.stringify()).\n *\n * @param i - The value to clone.\n * @returns A deep copy of the input value.\n * @example\n * ```ts\n * const original = { a: 1, b: { c: 2 } }\n * const copy = structuredClone(original)\n *\n * copy.b.c = 3\n * console.log(original.b.c) // 2 (unchanged)\n * console.log(copy.b.c) // 3\n *\n * // Works with complex objects\n * const complexObject = {\n * date: new Date(),\n * array: [1, 2, 3],\n * nested: { deep: { value: \"test\" } }\n * }\n * const cloned = structuredClone(complexObject)\n * ```\n * @public\n */\nexport const structuredClone = _structuredClone[0]\n\n/**\n * Whether the current environment has native structuredClone support.\n * @returns True if using native structuredClone, false if using JSON fallback.\n * @internal\n */\nexport const isNativeStructuredClone = _structuredClone[1]\n\n/**\n * The prototype object used by structuredClone for cloned objects.\n * When we patch structuredClone in jsdom for testing (see https://github.com/jsdom/jsdom/issues/3363),\n * the Object that is used as a prototype for the cloned object is not the same as the Object in\n * the code under test (that comes from jsdom's fake global context). This constant is used in\n * our code to work around this case.\n *\n * This is also the case for Array prototype, but that problem can be worked around with an\n * Array.isArray() check.\n * @internal\n */\nexport const STRUCTURED_CLONE_OBJECT_PROTOTYPE = Object.getPrototypeOf(structuredClone({}))\n","const usedWarnings = new Set<string>()\n\n/**\n * Issues a deprecation warning for deprecated getter properties, advising users to use\n * the equivalent getter method instead. The warning is shown only once per property name.\n *\n * @param name - The name of the deprecated property (e.g., 'viewport')\n *\n * @example\n * ```ts\n * // Inside a class with deprecated property access\n * get viewport() {\n * warnDeprecatedGetter('viewport')\n * return this.getViewport()\n * }\n *\n * // Usage will show: \"[tldraw] Using 'viewport' is deprecated and will be removed...\"\n * // But only the first time it's accessed\n * ```\n *\n * @internal\n */\nexport function warnDeprecatedGetter(name: string) {\n\twarnOnce(\n\t\t`Using '${name}' is deprecated and will be removed in the near future. Please refactor to use 'get${name[0].toLocaleUpperCase()}${name.slice(\n\t\t\t1\n\t\t)}' instead.`\n\t)\n}\n\n/**\n * Issues a warning message to the console, but only once per unique message.\n * Subsequent calls with the same message are ignored, preventing console spam.\n * All messages are prefixed with \"[tldraw]\".\n *\n * @param message - The warning message to display\n *\n * @example\n * ```ts\n * // Warn about deprecated usage\n * function oldFunction() {\n * warnOnce('oldFunction is deprecated, use newFunction instead')\n * // Continue with implementation...\n * }\n *\n * // First call logs: \"[tldraw] oldFunction is deprecated, use newFunction instead\"\n * oldFunction() // Shows warning\n * oldFunction() // No warning (already shown)\n * oldFunction() // No warning (already shown)\n * ```\n *\n * @internal\n */\nexport function warnOnce(message: string) {\n\tif (usedWarnings.has(message)) return\n\n\tusedWarnings.add(message)\n\tconsole.warn(`[tldraw] ${message}`)\n}\n","import { registerDrawLibraryVersion } from './lib/version'\n\nexport { default as isEqual } from 'lodash.isequal'\nexport { default as isEqualWith } from 'lodash.isequalwith'\nexport { default as throttle } from 'lodash.throttle'\nexport { default as uniq } from 'lodash.uniq'\nexport {\n\tareArraysShallowEqual,\n\tcompact,\n\tdedupe,\n\tlast,\n\tmaxBy,\n\tmergeArraysAndReplaceDefaults,\n\tminBy,\n\tpartition,\n\trotateArray,\n} from './lib/array'\nexport { bind } from './lib/bind'\nexport { WeakCache } from './lib/cache'\nexport {\n\tassert,\n\tassertExists,\n\texhaustiveSwitchError,\n\tpromiseWithResolve,\n\tResult,\n\tsleep,\n\ttype ErrorResult,\n\ttype OkResult,\n} from './lib/control'\nexport { debounce } from './lib/debounce'\nexport { annotateError, getErrorAnnotations, type ErrorAnnotations } from './lib/error'\nexport { ExecutionQueue } from './lib/ExecutionQueue'\nexport { FileHelpers } from './lib/file'\nexport { noop, omitFromStackTrace } from './lib/function'\nexport { getHashForBuffer, getHashForObject, getHashForString, lns } from './lib/hash'\nexport { mockUniqueId, restoreUniqueId, uniqueId } from './lib/id'\nexport { getFirstFromIterable } from './lib/iterable'\nexport { LruCache } from './lib/LruCache'\nexport type { JsonArray, JsonObject, JsonPrimitive, JsonValue } from './lib/json-value'\nexport {\n\tDEFAULT_SUPPORT_VIDEO_TYPES,\n\tDEFAULT_SUPPORTED_IMAGE_TYPES,\n\tDEFAULT_SUPPORTED_MEDIA_TYPE_LIST,\n\tDEFAULT_SUPPORTED_MEDIA_TYPES,\n\tMediaHelpers,\n} from './lib/media/media'\nexport { PngHelpers } from './lib/media/png'\nexport { fetch, Image } from './lib/network'\nexport { invLerp, lerp, modulate, rng } from './lib/number'\nexport {\n\tareObjectsShallowEqual,\n\tfilterEntries,\n\tgetChangedKeys,\n\tgetOwnProperty,\n\tgroupBy,\n\thasOwnProperty,\n\tisEqualAllowingForFloatingPointErrors,\n\tmapObjectMapValues,\n\tobjectMapEntries,\n\tobjectMapEntriesIterable,\n\tobjectMapFromEntries,\n\tobjectMapKeys,\n\tobjectMapValues,\n\tomit,\n} from './lib/object'\nexport { measureAverageDuration, measureCbDuration, measureDuration } from './lib/perf'\nexport { PerformanceTracker } from './lib/PerformanceTracker'\nexport {\n\tgetIndexAbove,\n\tgetIndexBelow,\n\tgetIndexBetween,\n\tgetIndices,\n\tgetIndicesAbove,\n\tgetIndicesBelow,\n\tgetIndicesBetween,\n\tsortByIndex,\n\tsortByMaybeIndex,\n\tvalidateIndexKey,\n\tZERO_INDEX_KEY,\n\ttype IndexKey,\n} from './lib/reordering'\nexport { retry } from './lib/retry'\nexport { sortById } from './lib/sort'\nexport {\n\tclearLocalStorage,\n\tclearSessionStorage,\n\tdeleteFromLocalStorage,\n\tdeleteFromSessionStorage,\n\tgetFromLocalStorage,\n\tgetFromSessionStorage,\n\tsetInLocalStorage,\n\tsetInSessionStorage,\n} from './lib/storage'\nexport { stringEnum } from './lib/stringEnum'\nexport { FpsScheduler, fpsThrottle, throttleToNextFrame } from './lib/throttle'\nexport { Timers } from './lib/timers'\nexport {\n\ttype Awaitable,\n\ttype Expand,\n\ttype MakeUndefinedOptional,\n\ttype RecursivePartial,\n\ttype Required,\n} from './lib/types'\nexport { safeParseUrl } from './lib/url'\nexport {\n\tisDefined,\n\tisNativeStructuredClone,\n\tisNonNull,\n\tisNonNullish,\n\tSTRUCTURED_CLONE_OBJECT_PROTOTYPE,\n\tstructuredClone,\n} from './lib/value'\nexport { registerDrawLibraryVersion } from './lib/version'\nexport { warnDeprecatedGetter, warnOnce } from './lib/warn'\n\nregisterDrawLibraryVersion(\n\t(globalThis as any).DRAW_LIBRARY_NAME,\n\t(globalThis as any).DRAW_LIBRARY_VERSION,\n\t(globalThis as any).DRAW_LIBRARY_MODULES\n)\n"]}
|