@lichens-innovation/ts-common 1.17.0 → 1.18.0

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/mime.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/types.utils.ts","../src/utils/string.utils.ts","../src/utils/uri.utils.ts","../src/mime/mime.utils.ts","../src/mime/index.ts"],"names":[],"mappings":";;;;;AAEO,IAAM,SAAA,GAAY,CAAC,KAAA,KAA8C,KAAA,KAAU,QAAQ,KAAA,KAAU,MAAA;;;ACC7F,IAAM,OAAA,GAAU,CAAC,GAAA,KAAsD;AAC5E,EAAA,OAAO,SAAA,CAAU,GAAG,CAAA,IAAK,GAAA,EAAK,MAAK,KAAM,EAAA;AAC3C,CAAA;ACUO,IAAM,gBAAA,GAAmB,yCAAA;AAEzB,IAAM,cAAA,GAAiB,CAAC,GAAA,KAAiC;AAC9D,EAAA,IAAI,OAAA,CAAQ,GAAG,CAAA,EAAG;AAChB,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,OAAO,gBAAA,CAAiB,KAAK,GAAG,CAAA;AAClC,CAAA;;;ACvBO,IAAM,iBAAA,GAAoB;AAAA,EAC/B,WAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,cAAA;AAAA,EACA,0BAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAA;;;ACHO,IAAM,YAAA,GAAe,CAAC,KAAA,KAA6C;AACxE,EAAA,IAAI,CAAC,cAAA,CAAe,KAAK,CAAA,EAAG,OAAO,IAAA;AAEnC,EAAA,MAAM,KAAA,GAAQ,gBAAA,CAAiB,IAAA,CAAK,KAAK,CAAA;AACzC,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AAEnB,EAAA,MAAM,GAAG,QAAA,EAAU,MAAM,CAAA,GAAI,KAAA;AAC7B,EAAA,IAAI,CAAC,QAAA,IAAY,CAAC,MAAA,EAAQ,OAAO,IAAA;AAEjC,EAAA,OAAO,EAAE,QAAA,EAAU,MAAA,EAAQ,GAAA,EAAK,SAAA,CAAU,QAAQ,CAAA,EAAE;AACtD;AAEO,IAAM,eAAA,GAAkB,CAAC,QAAA,KAA8B;AAC5D,EAAA,OAAO,iBAAA,CAAkB,SAAS,QAAQ,CAAA;AAC5C;AAEO,IAAM,kBAAA,GAAqB,CAAC,KAAA,KAAiC;AAClE,EAAA,MAAM,MAAA,GAAS,aAAa,KAAK,CAAA;AACjC,EAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AACpB,EAAA,IAAI,CAAC,eAAA,CAAgB,MAAA,CAAO,QAAQ,GAAG,OAAO,IAAA;AAE9C,EAAA,OAAO,KAAA;AACT;AAEO,IAAM,SAAA,GAAY,CAAC,QAAA,KAA6B;AACrD,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,YAAA,CAAa,QAAQ,CAAA;AACtC,EAAA,IAAI,KAAK,OAAO,GAAA;AAEhB,EAAA,MAAM,UAAU,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,QAAA;AAC1C,EAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,OAAA;AAClC;AAEO,IAAM,WAAA,GAAc,CAAC,SAAA,KAA8B;AACxD,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,OAAA,CAAQ,SAAS,CAAA;AACvC,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kDAAA,EAAqD,SAAS,CAAA,CAAA,CAAG,CAAA;AAAA,EACnF;AAEA,EAAA,OAAO,QAAA;AACT","file":"mime.js","sourcesContent":["export const NO_OP: () => void = () => {};\n\nexport const isNullish = (value: unknown): value is null | undefined => value === null || value === undefined;\n\nexport const isNumber = (value?: unknown | null): value is number => {\n if (isNullish(value)) {\n return false;\n }\n\n if (typeof value !== 'number') {\n return false;\n }\n\n if (isNaN(value)) {\n return false;\n }\n\n return true;\n};\n\nexport const isString = (value?: unknown | null): value is string => {\n if (isNullish(value)) {\n return false;\n }\n\n if (typeof value !== 'string') {\n return false;\n }\n\n return true;\n};\n","import { REGEX_ALPHANUMERIC } from './regex';\nimport { isNullish } from './types.utils';\n\nexport const isBlank = (str?: string | null): str is null | undefined | '' => {\n return isNullish(str) || str?.trim() === '';\n};\n\nexport const isNotBlank = (str?: string | null): str is string => {\n return !isBlank(str);\n};\n\nexport const isAlphanumeric = (value: string): boolean => {\n return REGEX_ALPHANUMERIC.test(value);\n};\n\n/**\n * Removes diacritical marks (e.g., accents, umlauts) from a string.\n * This method normalizes the input string to its canonical decomposition\n * form (NFD) and removes any combining diacritical marks.\n *\n * @param {string} value - The input string to normalize.\n * @returns {string} - The normalized string with diacritical marks removed.\n *\n * @example\n * const result = removeDiacriticalMarks(\"Ça va très bien, n'est-ce pas?\");\n * console.log(result); // \"Ca va tres bien, n'est-ce pas?\"\n */\nexport const removeDiacriticalMarks = (value: string): string => {\n if (!value) {\n return '';\n }\n\n return value.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '');\n};\n\n/**\n * Capitalize the first letter of a string.\n * @param str - The input string\n * @returns The string with the first character uppercased\n */\nexport const capitalizeFirst = (str: string): string => {\n if (!str) return str;\n return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\n/**\n * Count the number of words in a text string.\n * Words are separated by whitespace.\n * @param text - The text to count words in\n * @returns The number of words found\n */\nexport const countWords = (text: string): number => {\n if (!text || text.trim().length === 0) return 0;\n return text.split(/\\s+/).filter((word) => word.length > 0).length;\n};\n\n/**\n * Truncate a string to a maximum length, adding an ellipsis if truncated.\n * @param str - The string to truncate\n * @param maxLength - Maximum length before truncation\n * @param ellipsis - The ellipsis string to append (default: \"...\")\n * @returns The truncated string\n */\nexport const truncate = (str: string, maxLength: number, ellipsis = \"...\"): string => {\n if (!str || str.length <= maxLength) return str;\n return str.slice(0, maxLength - ellipsis.length) + ellipsis;\n};\n\n/**\n * Parses an optional comma-separated string into a trimmed, non-blank string array.\n */\nexport const parseCommaSeparatedList = (raw?: string | null): string[] => {\n if (isBlank(raw)) {\n return [];\n }\n\n return raw\n .split(\",\")\n .map((s: string) => s.trim())\n .filter(isNotBlank);\n};\n","import { isBlank } from \".\";\n\nexport const SCHEME_PREFIXES = {\n file: 'file',\n content: 'content',\n http: 'http',\n https: 'https',\n ftp: 'ftp',\n ftps: 'ftps',\n sftp: 'sftp',\n smb: 'smb',\n} as const;\n\nconst SCHEME_PREFIXES_ARRAY = Object.values(SCHEME_PREFIXES);\n\nexport const DATA_URI_PATTERN = /^data:([\\w.+-]+\\/[\\w.+-]+);base64,(.+)$/;\n\nexport const isValidDataUri = (uri?: string | null): boolean => {\n if (isBlank(uri)) {\n return false;\n }\n\n return DATA_URI_PATTERN.test(uri);\n};\n\nexport const hasScheme = (uri?: string | null): boolean => {\n if (!uri) {\n return false;\n }\n\n const lowerUri = uri.toLowerCase();\n return SCHEME_PREFIXES_ARRAY.some((prefix) => lowerUri.startsWith(`${prefix}://`));\n};\n\n/**\n * Extracts the base64 data from a data URI string.\n * Data URIs have the format: data:[<mediatype>][;base64],<data>\n * This function extracts everything after the first comma.\n *\n * @param dataUri - The data URI string (e.g., \"data:image/png;base64,iVBORw0KG...\")\n * @returns The base64 data without the data URI prefix, or the original string if no comma is found\n */\nexport const extractBase64FromDataUri = (dataUri: string): string => {\n return dataUri.split(',')[1] ?? dataUri;\n};\n","export const VALID_IMAGE_TYPES = [\n \"image/png\",\n \"image/jpeg\",\n \"image/jpg\",\n \"image/gif\",\n \"image/webp\",\n \"image/bmp\",\n \"image/svg+xml\",\n \"image/avif\",\n \"image/tiff\",\n \"image/x-icon\",\n \"image/vnd.microsoft.icon\",\n \"image/heic\",\n \"image/heif\",\n];\n","import mime from \"mime\";\n\nimport { DATA_URI_PATTERN, isValidDataUri } from \"~/utils/uri.utils\";\nimport { VALID_IMAGE_TYPES } from \"./mime.utils\";\n\nexport interface ParseDataUriResult {\n mimeType: string;\n base64: string;\n ext: string;\n}\n\nexport const parseDataUri = (input: string): ParseDataUriResult | null => {\n if (!isValidDataUri(input)) return null;\n\n const match = DATA_URI_PATTERN.exec(input);\n if (!match) return null;\n\n const [, mimeType, base64] = match;\n if (!mimeType || !base64) return null;\n\n return { mimeType, base64, ext: mimeToExt(mimeType) };\n};\n\nexport const isImageMimeType = (mimeType: string): boolean => {\n return VALID_IMAGE_TYPES.includes(mimeType);\n};\n\nexport const getImagePreviewSrc = (input: string): string | null => {\n const parsed = parseDataUri(input);\n if (!parsed) return null;\n if (!isImageMimeType(parsed.mimeType)) return null;\n\n return input;\n};\n\nexport const mimeToExt = (mimeType: string): string => {\n const ext = mime.getExtension(mimeType);\n if (ext) return ext;\n\n const subtype = mimeType.split(\"/\")[1] ?? mimeType;\n return subtype.split(\"+\")[0] ?? subtype;\n};\n\nexport const getMimeType = (extension: string): string => {\n const mimeType = mime.getType(extension);\n if (!mimeType) {\n throw new Error(`[getMimeType] Mime type not found for extension: \"${extension}\"`);\n }\n\n return mimeType;\n};\n\n"]}
1
+ {"version":3,"sources":["../src/utils/types.utils.ts","../src/utils/string.utils.ts","../src/utils/uri.utils.ts","../src/mime/mime.utils.ts","../src/mime/index.ts"],"names":[],"mappings":";;;;;AAEO,IAAM,SAAA,GAAY,CAAC,KAAA,KAA8C,KAAA,KAAU,QAAQ,KAAA,KAAU,MAAA;;;ACC7F,IAAM,OAAA,GAAU,CAAC,GAAA,KAAsD;AAC5E,EAAA,OAAO,SAAA,CAAU,GAAG,CAAA,IAAK,GAAA,EAAK,MAAK,KAAM,EAAA;AAC3C,CAAA;ACUO,IAAM,gBAAA,GAAmB,yCAAA;AAEzB,IAAM,cAAA,GAAiB,CAAC,GAAA,KAAiC;AAC9D,EAAA,IAAI,OAAA,CAAQ,GAAG,CAAA,EAAG;AAChB,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,OAAO,gBAAA,CAAiB,KAAK,GAAG,CAAA;AAClC,CAAA;;;ACvBO,IAAM,iBAAA,GAAoB;AAAA,EAC/B,WAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,cAAA;AAAA,EACA,0BAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF;;;ACDO,IAAM,YAAA,GAAe,CAAC,KAAA,KAA6C;AACxE,EAAA,IAAI,CAAC,cAAA,CAAe,KAAK,CAAA,EAAG,OAAO,IAAA;AAEnC,EAAA,MAAM,KAAA,GAAQ,gBAAA,CAAiB,IAAA,CAAK,KAAK,CAAA;AACzC,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AAEnB,EAAA,MAAM,GAAG,QAAA,EAAU,MAAM,CAAA,GAAI,KAAA;AAC7B,EAAA,IAAI,CAAC,QAAA,IAAY,CAAC,MAAA,EAAQ,OAAO,IAAA;AAEjC,EAAA,OAAO,EAAE,QAAA,EAAU,MAAA,EAAQ,GAAA,EAAK,SAAA,CAAU,QAAQ,CAAA,EAAE;AACtD;AAEO,IAAM,eAAA,GAAkB,CAAC,QAAA,KAA8B;AAC5D,EAAA,OAAO,iBAAA,CAAkB,SAAS,QAAQ,CAAA;AAC5C;AAEO,IAAM,gBAAA,GAAmB,CAAC,IAAA,KAAoC;AACnE,EAAA,OAAO,eAAA,CAAgB,KAAK,IAAI,CAAA;AAClC;AAEO,IAAM,uBAAA,GAA0B,CAAC,OAAA,KAA4B;AAClE,EAAA,MAAM,MAAA,GAAS,aAAa,OAAO,CAAA;AACnC,EAAA,IAAI,CAAC,QAAQ,OAAO,KAAA;AAEpB,EAAA,OAAO,MAAA,CAAO,GAAA;AAChB;AAEO,IAAM,kBAAA,GAAqB,CAAC,KAAA,KAAiC;AAClE,EAAA,MAAM,MAAA,GAAS,aAAa,KAAK,CAAA;AACjC,EAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AACpB,EAAA,IAAI,CAAC,eAAA,CAAgB,MAAA,CAAO,QAAQ,GAAG,OAAO,IAAA;AAE9C,EAAA,OAAO,KAAA;AACT;AAEO,IAAM,SAAA,GAAY,CAAC,QAAA,KAA6B;AACrD,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,YAAA,CAAa,QAAQ,CAAA;AACtC,EAAA,IAAI,KAAK,OAAO,GAAA;AAEhB,EAAA,MAAM,UAAU,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,QAAA;AAC1C,EAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,OAAA;AAClC;AAEO,IAAM,WAAA,GAAc,CAAC,SAAA,KAA8B;AACxD,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,OAAA,CAAQ,SAAS,CAAA;AACvC,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kDAAA,EAAqD,SAAS,CAAA,CAAA,CAAG,CAAA;AAAA,EACnF;AAEA,EAAA,OAAO,QAAA;AACT","file":"mime.js","sourcesContent":["export const NO_OP: () => void = () => {};\n\nexport const isNullish = (value: unknown): value is null | undefined => value === null || value === undefined;\n\nexport const isNumber = (value?: unknown | null): value is number => {\n if (isNullish(value)) {\n return false;\n }\n\n if (typeof value !== 'number') {\n return false;\n }\n\n if (isNaN(value)) {\n return false;\n }\n\n return true;\n};\n\nexport const isString = (value?: unknown | null): value is string => {\n if (isNullish(value)) {\n return false;\n }\n\n if (typeof value !== 'string') {\n return false;\n }\n\n return true;\n};\n","import { REGEX_ALPHANUMERIC } from './regex';\nimport { isNullish } from './types.utils';\n\nexport const isBlank = (str?: string | null): str is null | undefined | '' => {\n return isNullish(str) || str?.trim() === '';\n};\n\nexport const isNotBlank = (str?: string | null): str is string => {\n return !isBlank(str);\n};\n\nexport const isAlphanumeric = (value: string): boolean => {\n return REGEX_ALPHANUMERIC.test(value);\n};\n\n/**\n * Removes diacritical marks (e.g., accents, umlauts) from a string.\n * This method normalizes the input string to its canonical decomposition\n * form (NFD) and removes any combining diacritical marks.\n *\n * @param {string} value - The input string to normalize.\n * @returns {string} - The normalized string with diacritical marks removed.\n *\n * @example\n * const result = removeDiacriticalMarks(\"Ça va très bien, n'est-ce pas?\");\n * console.log(result); // \"Ca va tres bien, n'est-ce pas?\"\n */\nexport const removeDiacriticalMarks = (value: string): string => {\n if (!value) {\n return '';\n }\n\n return value.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '');\n};\n\n/**\n * Capitalize the first letter of a string.\n * @param str - The input string\n * @returns The string with the first character uppercased\n */\nexport const capitalizeFirst = (str: string): string => {\n if (!str) return str;\n return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\n/**\n * Count the number of words in a text string.\n * Words are separated by whitespace.\n * @param text - The text to count words in\n * @returns The number of words found\n */\nexport const countWords = (text: string): number => {\n if (!text || text.trim().length === 0) return 0;\n return text.split(/\\s+/).filter((word) => word.length > 0).length;\n};\n\n/**\n * Truncate a string to a maximum length, adding an ellipsis if truncated.\n * @param str - The string to truncate\n * @param maxLength - Maximum length before truncation\n * @param ellipsis - The ellipsis string to append (default: \"...\")\n * @returns The truncated string\n */\nexport const truncate = (str: string, maxLength: number, ellipsis = \"...\"): string => {\n if (!str || str.length <= maxLength) return str;\n return str.slice(0, maxLength - ellipsis.length) + ellipsis;\n};\n\n/**\n * Parses an optional comma-separated string into a trimmed, non-blank string array.\n */\nexport const parseCommaSeparatedList = (raw?: string | null): string[] => {\n if (isBlank(raw)) {\n return [];\n }\n\n return raw\n .split(\",\")\n .map((s: string) => s.trim())\n .filter(isNotBlank);\n};\n","import { isBlank } from \".\";\n\nexport const SCHEME_PREFIXES = {\n file: 'file',\n content: 'content',\n http: 'http',\n https: 'https',\n ftp: 'ftp',\n ftps: 'ftps',\n sftp: 'sftp',\n smb: 'smb',\n} as const;\n\nconst SCHEME_PREFIXES_ARRAY = Object.values(SCHEME_PREFIXES);\n\nexport const DATA_URI_PATTERN = /^data:([\\w.+-]+\\/[\\w.+-]+);base64,(.+)$/;\n\nexport const isValidDataUri = (uri?: string | null): boolean => {\n if (isBlank(uri)) {\n return false;\n }\n\n return DATA_URI_PATTERN.test(uri);\n};\n\nexport const hasScheme = (uri?: string | null): boolean => {\n if (!uri) {\n return false;\n }\n\n const lowerUri = uri.toLowerCase();\n return SCHEME_PREFIXES_ARRAY.some((prefix) => lowerUri.startsWith(`${prefix}://`));\n};\n\n/**\n * Extracts the base64 data from a data URI string.\n * Data URIs have the format: data:[<mediatype>][;base64],<data>\n * This function extracts everything after the first comma.\n *\n * @param dataUri - The data URI string (e.g., \"data:image/png;base64,iVBORw0KG...\")\n * @returns The base64 data without the data URI prefix, or the original string if no comma is found\n */\nexport const extractBase64FromDataUri = (dataUri: string): string => {\n return dataUri.split(',')[1] ?? dataUri;\n};\n\nexport const encodeUrl = (value?: string): string => {\n if (!value) return '';\n return encodeURIComponent(value);\n};\n\nexport const decodeUrl = (value?: string): string => {\n if (!value) return '';\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n};\n\ninterface FormatDataUriArgs {\n mimeType: string;\n base64: string;\n}\n\nexport const formatDataUri = ({ mimeType, base64 }: FormatDataUriArgs): string => {\n return `data:${mimeType};base64,${base64}`;\n};\n\nexport const getBase64ApproxSize = (base64: string): number => {\n return Math.round((base64.length * 3) / 4);\n};\n","export const VALID_IMAGE_TYPES = [\n \"image/png\",\n \"image/jpeg\",\n \"image/jpg\",\n \"image/gif\",\n \"image/webp\",\n \"image/bmp\",\n \"image/svg+xml\",\n \"image/avif\",\n \"image/tiff\",\n \"image/x-icon\",\n \"image/vnd.microsoft.icon\",\n \"image/heic\",\n \"image/heif\",\n];\n","import mime from \"mime\";\n\nimport { DATA_URI_PATTERN, isValidDataUri } from \"~/utils/uri.utils\";\nimport { VALID_IMAGE_TYPES } from './mime.utils';\n\nexport { VALID_IMAGE_TYPES } from './mime.utils';\n\nexport interface ParseDataUriResult {\n mimeType: string;\n base64: string;\n ext: string;\n}\n\nexport const parseDataUri = (input: string): ParseDataUriResult | null => {\n if (!isValidDataUri(input)) return null;\n\n const match = DATA_URI_PATTERN.exec(input);\n if (!match) return null;\n\n const [, mimeType, base64] = match;\n if (!mimeType || !base64) return null;\n\n return { mimeType, base64, ext: mimeToExt(mimeType) };\n};\n\nexport const isImageMimeType = (mimeType: string): boolean => {\n return VALID_IMAGE_TYPES.includes(mimeType);\n};\n\nexport const isValidImageFile = (file: { type: string }): boolean => {\n return isImageMimeType(file.type);\n};\n\nexport const getExtensionFromDataUri = (dataUri: string): string => {\n const parsed = parseDataUri(dataUri);\n if (!parsed) return 'bin';\n\n return parsed.ext;\n};\n\nexport const getImagePreviewSrc = (input: string): string | null => {\n const parsed = parseDataUri(input);\n if (!parsed) return null;\n if (!isImageMimeType(parsed.mimeType)) return null;\n\n return input;\n};\n\nexport const mimeToExt = (mimeType: string): string => {\n const ext = mime.getExtension(mimeType);\n if (ext) return ext;\n\n const subtype = mimeType.split(\"/\")[1] ?? mimeType;\n return subtype.split(\"+\")[0] ?? subtype;\n};\n\nexport const getMimeType = (extension: string): string => {\n const mimeType = mime.getType(extension);\n if (!mimeType) {\n throw new Error(`[getMimeType] Mime type not found for extension: \"${extension}\"`);\n }\n\n return mimeType;\n};\n\n"]}
package/dist/web.cjs CHANGED
@@ -1,5 +1,22 @@
1
1
  'use strict';
2
2
 
3
+ var mime = require('mime');
4
+
5
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
+
7
+ var mime__default = /*#__PURE__*/_interopDefault(mime);
8
+
9
+ // src/web/base64.utils.ts
10
+ var base64ToBlob = ({ base64, mimeType }) => {
11
+ const byteCharacters = atob(base64);
12
+ const byteNumbers = new Array(byteCharacters.length);
13
+ for (let i = 0; i < byteCharacters.length; i++) {
14
+ byteNumbers[i] = byteCharacters.charCodeAt(i);
15
+ }
16
+ const byteArray = new Uint8Array(byteNumbers);
17
+ return new Blob([byteArray], { type: mimeType });
18
+ };
19
+
3
20
  // src/web/browser.utils.ts
4
21
  var getCurrentUrl = () => {
5
22
  if (typeof window === "undefined") {
@@ -8,6 +25,99 @@ var getCurrentUrl = () => {
8
25
  return window.location.href;
9
26
  };
10
27
 
28
+ // src/web/canvas-image.utils.ts
29
+ var fileToImageData = (file) => {
30
+ return new Promise((resolve, reject) => {
31
+ const img = new Image();
32
+ const canvas = document.createElement("canvas");
33
+ const ctx = canvas.getContext("2d");
34
+ if (!ctx) {
35
+ reject(new Error("Failed to get canvas context"));
36
+ return;
37
+ }
38
+ img.onload = () => {
39
+ canvas.width = img.width;
40
+ canvas.height = img.height;
41
+ ctx.drawImage(img, 0, 0);
42
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
43
+ URL.revokeObjectURL(img.src);
44
+ resolve(imageData);
45
+ };
46
+ img.onerror = () => {
47
+ URL.revokeObjectURL(img.src);
48
+ reject(new Error("Failed to load image"));
49
+ };
50
+ img.src = URL.createObjectURL(file);
51
+ });
52
+ };
53
+ var dataUrlToPngBlob = (dataUrl) => {
54
+ return new Promise((resolve, reject) => {
55
+ const img = new Image();
56
+ img.onload = () => {
57
+ const canvas = document.createElement("canvas");
58
+ canvas.width = img.width;
59
+ canvas.height = img.height;
60
+ const ctx = canvas.getContext("2d");
61
+ if (!ctx) {
62
+ reject(new Error("Could not get canvas context"));
63
+ return;
64
+ }
65
+ ctx.drawImage(img, 0, 0);
66
+ canvas.toBlob(
67
+ (blob) => {
68
+ if (blob) {
69
+ resolve(blob);
70
+ } else {
71
+ reject(new Error("Could not convert to PNG"));
72
+ }
73
+ },
74
+ "image/png",
75
+ 1
76
+ );
77
+ };
78
+ img.onerror = () => reject(new Error("Failed to load image"));
79
+ img.src = dataUrl;
80
+ });
81
+ };
82
+ var imageToCanvas = (img) => {
83
+ const canvas = document.createElement("canvas");
84
+ canvas.width = img.naturalWidth;
85
+ canvas.height = img.naturalHeight;
86
+ const ctx = canvas.getContext("2d");
87
+ if (ctx) {
88
+ ctx.drawImage(img, 0, 0);
89
+ }
90
+ return canvas;
91
+ };
92
+ var getPixelColor = ({ img, x, y }) => {
93
+ const canvas = imageToCanvas(img);
94
+ const ctx = canvas.getContext("2d");
95
+ if (!ctx) {
96
+ return { r: 0, g: 0, b: 0, a: 1 };
97
+ }
98
+ const p = ctx.getImageData(x, y, 1, 1).data;
99
+ return {
100
+ r: p[0] ?? 0,
101
+ g: p[1] ?? 0,
102
+ b: p[2] ?? 0,
103
+ a: 1
104
+ };
105
+ };
106
+
107
+ // src/web/clipboard.utils.ts
108
+ var copyTextToClipboard = async (text) => {
109
+ await navigator.clipboard.writeText(text);
110
+ };
111
+ var copyImageToClipboard = async (dataUrl) => {
112
+ const response = await fetch(dataUrl);
113
+ const blob = await response.blob();
114
+ const pngBlob = blob.type === "image/png" ? blob : await dataUrlToPngBlob(dataUrl);
115
+ await navigator.clipboard.write([new ClipboardItem({ "image/png": pngBlob })]);
116
+ };
117
+
118
+ // src/utils/types.utils.ts
119
+ var isNullish = (value) => value === null || value === void 0;
120
+
11
121
  // src/utils/errors.utils.ts
12
122
  var getErrorMessage = (error) => {
13
123
  if (!error) {
@@ -22,6 +132,69 @@ var getErrorMessage = (error) => {
22
132
  return JSON.stringify(error);
23
133
  };
24
134
 
135
+ // src/utils/string.utils.ts
136
+ var isBlank = (str) => {
137
+ return isNullish(str) || str?.trim() === "";
138
+ };
139
+ var DATA_URI_PATTERN = /^data:([\w.+-]+\/[\w.+-]+);base64,(.+)$/;
140
+ var isValidDataUri = (uri) => {
141
+ if (isBlank(uri)) {
142
+ return false;
143
+ }
144
+ return DATA_URI_PATTERN.test(uri);
145
+ };
146
+ var extractBase64FromDataUri = (dataUri) => {
147
+ return dataUri.split(",")[1] ?? dataUri;
148
+ };
149
+
150
+ // src/mime/index.ts
151
+ var parseDataUri = (input) => {
152
+ if (!isValidDataUri(input)) return null;
153
+ const match = DATA_URI_PATTERN.exec(input);
154
+ if (!match) return null;
155
+ const [, mimeType, base64] = match;
156
+ if (!mimeType || !base64) return null;
157
+ return { mimeType, base64, ext: mimeToExt(mimeType) };
158
+ };
159
+ var getExtensionFromDataUri = (dataUri) => {
160
+ const parsed = parseDataUri(dataUri);
161
+ if (!parsed) return "bin";
162
+ return parsed.ext;
163
+ };
164
+ var mimeToExt = (mimeType) => {
165
+ const ext = mime__default.default.getExtension(mimeType);
166
+ if (ext) return ext;
167
+ const subtype = mimeType.split("/")[1] ?? mimeType;
168
+ return subtype.split("+")[0] ?? subtype;
169
+ };
170
+
171
+ // src/web/download.utils.ts
172
+ var downloadBlob = ({ blob, fileName }) => {
173
+ const url = URL.createObjectURL(blob);
174
+ const link = document.createElement("a");
175
+ link.href = url;
176
+ link.download = fileName;
177
+ document.body.appendChild(link);
178
+ link.click();
179
+ document.body.removeChild(link);
180
+ URL.revokeObjectURL(url);
181
+ };
182
+ var downloadDataUrl = ({ dataUrl, fileName }) => {
183
+ const link = document.createElement("a");
184
+ link.href = dataUrl;
185
+ link.download = fileName;
186
+ document.body.appendChild(link);
187
+ link.click();
188
+ document.body.removeChild(link);
189
+ };
190
+ var downloadText = ({ content, fileName, mimeType = "text/plain" }) => {
191
+ const blob = new Blob([content], { type: mimeType });
192
+ downloadBlob({ blob, fileName });
193
+ };
194
+ var downloadJson = ({ content, fileName = "data.json" }) => {
195
+ downloadText({ content, fileName, mimeType: "application/json" });
196
+ };
197
+
25
198
  // src/web/fetch.utils.ts
26
199
  var blobToDataUri = (blob) => {
27
200
  return new Promise((resolve, reject) => {
@@ -50,6 +223,85 @@ var fetchUrlAsDataUri = async (url) => {
50
223
  }
51
224
  };
52
225
 
226
+ // src/web/file-reader.utils.ts
227
+ var readFileAsDataUrl = (file) => {
228
+ return new Promise((resolve, reject) => {
229
+ const reader = new FileReader();
230
+ reader.onload = (ev) => {
231
+ const result = ev.target?.result;
232
+ if (typeof result === "string") {
233
+ resolve(result);
234
+ } else {
235
+ reject(new Error("Failed to read file"));
236
+ }
237
+ };
238
+ reader.onerror = () => reject(new Error("Failed to read file"));
239
+ reader.readAsDataURL(file);
240
+ });
241
+ };
242
+ var readFileAsBase64 = (file) => {
243
+ return new Promise((resolve, reject) => {
244
+ const reader = new FileReader();
245
+ reader.onload = () => {
246
+ const result = reader.result;
247
+ const base64 = extractBase64FromDataUri(result);
248
+ const mimeType = file.type || "application/octet-stream";
249
+ resolve({ base64, mimeType });
250
+ };
251
+ reader.onerror = () => reject(new Error("Failed to read file"));
252
+ reader.readAsDataURL(file);
253
+ });
254
+ };
255
+ var readFileAsText = (file) => {
256
+ return new Promise((resolve, reject) => {
257
+ const reader = new FileReader();
258
+ reader.onload = () => {
259
+ const result = reader.result;
260
+ if (typeof result === "string") {
261
+ resolve(result);
262
+ } else {
263
+ reject(new Error("Failed to read file as text"));
264
+ }
265
+ };
266
+ reader.onerror = () => reject(new Error("Failed to read file"));
267
+ reader.readAsText(file);
268
+ });
269
+ };
270
+ var readFileAsArrayBuffer = (file) => {
271
+ return new Promise((resolve, reject) => {
272
+ const reader = new FileReader();
273
+ reader.onload = () => {
274
+ const result = reader.result;
275
+ if (result instanceof ArrayBuffer) {
276
+ resolve(result);
277
+ } else {
278
+ reject(new Error("Failed to read file as ArrayBuffer"));
279
+ }
280
+ };
281
+ reader.onerror = () => reject(new Error("Failed to read file"));
282
+ reader.readAsArrayBuffer(file);
283
+ });
284
+ };
285
+ var getImageFileFromClipboard = (items) => {
286
+ if (!items) return null;
287
+ for (let i = 0; i < items.length; i++) {
288
+ const item = items[i];
289
+ if (!item?.type.startsWith("image")) continue;
290
+ const file = item.getAsFile();
291
+ if (file) return file;
292
+ }
293
+ return null;
294
+ };
295
+ var clipboardImageToFile = ({ items, onFile }) => {
296
+ const file = getImageFileFromClipboard(items);
297
+ if (file) onFile(file);
298
+ };
299
+ var clipboardImageToDataUrl = ({ items, onLoad, onError }) => {
300
+ const file = getImageFileFromClipboard(items);
301
+ if (!file) return;
302
+ readFileAsDataUrl(file).then(onLoad).catch((error) => onError?.(error instanceof Error ? error : new Error(String(error))));
303
+ };
304
+
53
305
  // src/web/image.utils.ts
54
306
  var hasRechartsElements = (svg) => {
55
307
  return svg.querySelector("g.recharts-layer") !== null || svg.querySelector("g.recharts-cartesian-axis") !== null || svg.querySelector("g.recharts-cartesian-grid") !== null || svg.querySelector("path.recharts-curve") !== null;
@@ -216,19 +468,38 @@ var svgToPngDataUri = async ({
216
468
  });
217
469
  };
218
470
 
471
+ exports.base64ToBlob = base64ToBlob;
219
472
  exports.blobToDataUri = blobToDataUri;
473
+ exports.clipboardImageToDataUrl = clipboardImageToDataUrl;
474
+ exports.clipboardImageToFile = clipboardImageToFile;
220
475
  exports.convertSvgToDataUri = convertSvgToDataUri;
476
+ exports.copyImageToClipboard = copyImageToClipboard;
477
+ exports.copyTextToClipboard = copyTextToClipboard;
478
+ exports.dataUrlToPngBlob = dataUrlToPngBlob;
479
+ exports.downloadBlob = downloadBlob;
480
+ exports.downloadDataUrl = downloadDataUrl;
481
+ exports.downloadJson = downloadJson;
482
+ exports.downloadText = downloadText;
221
483
  exports.fetchUrlAsDataUri = fetchUrlAsDataUri;
484
+ exports.fileToImageData = fileToImageData;
222
485
  exports.findRechartsSvg = findRechartsSvg;
223
486
  exports.getChartAsPngDataUri = getChartAsPngDataUri;
224
487
  exports.getCurrentUrl = getCurrentUrl;
225
488
  exports.getElement = getElement;
489
+ exports.getExtensionFromDataUri = getExtensionFromDataUri;
490
+ exports.getImageFileFromClipboard = getImageFileFromClipboard;
491
+ exports.getPixelColor = getPixelColor;
226
492
  exports.getRechartSvgXml = getRechartSvgXml;
227
493
  exports.getRechartsSvgFromElement = getRechartsSvgFromElement;
228
494
  exports.getSvgAsBase64DataUri = getSvgAsBase64DataUri;
229
495
  exports.getSvgDimensions = getSvgDimensions;
230
496
  exports.hasRechartsElements = hasRechartsElements;
497
+ exports.imageToCanvas = imageToCanvas;
231
498
  exports.prepareSvgClone = prepareSvgClone;
499
+ exports.readFileAsArrayBuffer = readFileAsArrayBuffer;
500
+ exports.readFileAsBase64 = readFileAsBase64;
501
+ exports.readFileAsDataUrl = readFileAsDataUrl;
502
+ exports.readFileAsText = readFileAsText;
232
503
  exports.resizeSvgXml = resizeSvgXml;
233
504
  exports.svgToPngDataUri = svgToPngDataUri;
234
505
  //# sourceMappingURL=web.cjs.map
package/dist/web.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/web/browser.utils.ts","../src/utils/errors.utils.ts","../src/web/fetch.utils.ts","../src/web/image.utils.ts"],"names":[],"mappings":"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","file":"web.cjs","sourcesContent":["export const getCurrentUrl = (): string => {\n if (typeof window === \"undefined\") {\n return \"\";\n }\n\n return window.location.href;\n};\n","export const getErrorMessage = (error: unknown): string => {\n if (!error) {\n return \"\";\n }\n\n if (typeof error === \"string\") {\n return error;\n }\n\n if (typeof error === \"object\" && \"message\" in error) {\n return (error as { message: string }).message;\n }\n\n return JSON.stringify(error);\n};\n\nexport const toError = (error: unknown): Error => {\n if (error instanceof Error) {\n return error;\n }\n\n return new Error(getErrorMessage(error));\n};\n","import { getErrorMessage } from \"../utils\";\n\n/**\n * Converts a Blob to a data URI string.\n */\nexport const blobToDataUri = (blob: Blob): Promise<string | null> => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onerror = () => reject(reader.error);\n reader.onloadend = () => {\n const { result } = reader;\n resolve(typeof result === \"string\" ? result : null);\n };\n\n reader.readAsDataURL(blob);\n });\n};\n\n/**\n * Fetches a resource by URL and returns its content as a data URI.\n * Content type is inferred from the response Content-Type header when possible.\n */\nexport const fetchUrlAsDataUri = async (url: string): Promise<string | null> => {\n try {\n const response = await fetch(url);\n if (!response.ok) {\n console.warn(`[fetchUrlAsDataUri] Response not ok (${response.status}). url: \"${url}\"`);\n return null;\n }\n\n const blob = await response.blob();\n return blobToDataUri(blob);\n } catch (e: unknown) {\n const message = getErrorMessage(e);\n console.error(`[fetchUrlAsDataUri] \"${message}\". url: \"${url}\"`, e);\n return null;\n }\n};\n","import { getErrorMessage, type Dimensions } from \"../utils\";\n\nexport const hasRechartsElements = (svg: SVGSVGElement): boolean => {\n return (\n svg.querySelector(\"g.recharts-layer\") !== null ||\n svg.querySelector(\"g.recharts-cartesian-axis\") !== null ||\n svg.querySelector(\"g.recharts-cartesian-grid\") !== null ||\n svg.querySelector(\"path.recharts-curve\") !== null\n );\n};\n\nexport const findRechartsSvg = (svgs: NodeListOf<SVGSVGElement> | SVGSVGElement[]): SVGSVGElement | null => {\n for (const svg of Array.from(svgs)) {\n if (hasRechartsElements(svg)) {\n return svg;\n }\n }\n\n return null;\n};\n\nexport const getElement = (id: string): HTMLElement | null => {\n const element = document?.getElementById(id);\n if (!element) {\n console.info(`[getElement] Element with id \"${id}\" not found`);\n return null;\n }\n\n return element;\n};\n\nexport interface GetRechartsSvgFromElementArgs {\n chartElement: HTMLElement;\n chartElementId: string;\n}\n\nexport const getRechartsSvgFromElement = ({\n chartElement,\n chartElementId,\n}: GetRechartsSvgFromElementArgs): SVGSVGElement | null => {\n const allSvgs = chartElement.querySelectorAll<SVGSVGElement>(\"svg\");\n if (allSvgs.length === 0) {\n console.info(`[getRechartsSvgFromElement] SVG element not found inside element with id \"${chartElementId}\"`);\n return null;\n }\n\n const rechartSvg = findRechartsSvg(allSvgs);\n if (!rechartSvg) {\n console.info(`[getRechartsSvgFromElement] No Recharts SVG element found inside element with id \"${chartElementId}\"`);\n return null;\n }\n\n return rechartSvg;\n};\n\nexport const getSvgDimensions = (svgElement: SVGSVGElement): Dimensions => {\n const width = svgElement.clientWidth ?? parseInt(svgElement.getAttribute(\"width\") ?? \"800\", 10);\n const height = svgElement.clientHeight ?? parseInt(svgElement.getAttribute(\"height\") ?? \"600\", 10);\n return { width, height };\n};\n\nexport interface PrepareSvgCloneArgs {\n svgElement: SVGSVGElement;\n dimensions: Dimensions;\n}\n\n/**\n * Clones an SVG element and ensures it has the required width and height attributes.\n *\n * This function is necessary for two main reasons:\n *\n * 1. **Defensive cloning**: Cloning prevents modifying the original SVG element in the DOM.\n * Although `XMLSerializer.serializeToString()` does not modify the element, cloning ensures\n * that no accidental modifications are made to the source element.\n *\n * 2. **Required width/height attributes**: When converting SVG → PNG via `svgToPngDataUri`,\n * the HTML Image element requires the SVG to have explicit intrinsic dimensions.\n * Without width/height attributes, the SVG may not render correctly on the canvas,\n * resulting in an incorrect or empty PNG image.\n *\n * @param svgElement - The original SVG element to clone\n * @param dimensions - The dimensions to apply to the cloned SVG if attributes are missing\n * @returns A new cloned SVG element with guaranteed width/height attributes\n */\nexport const prepareSvgClone = ({ svgElement, dimensions }: PrepareSvgCloneArgs): SVGSVGElement => {\n const clonedSvg = svgElement.cloneNode(true) as SVGSVGElement;\n\n if (!clonedSvg.hasAttribute(\"width\")) {\n clonedSvg.setAttribute(\"width\", dimensions.width.toString());\n }\n if (!clonedSvg.hasAttribute(\"height\")) {\n clonedSvg.setAttribute(\"height\", dimensions.height.toString());\n }\n\n return clonedSvg;\n};\n\nexport const convertSvgToDataUri = (svgXml: string): string => {\n const encoder = new TextEncoder();\n const data = encoder.encode(svgXml);\n let binaryString = \"\";\n for (let i = 0; i < data.length; i++) {\n binaryString += String.fromCharCode(data[i]);\n }\n const base64 = btoa(binaryString);\n return `data:image/svg+xml;base64,${base64}`;\n};\n\nexport interface ResizeSvgXmlArgs {\n svgXml: string;\n targetWidth: number;\n targetHeight: number;\n}\n\n/**\n * Modifies SVG XML to set the root <svg> width and height attributes.\n * Used to resize the SVG before converting to PNG at target dimensions (e.g. from PDF layout).\n */\nexport const resizeSvgXml = ({ svgXml, targetWidth, targetHeight }: ResizeSvgXmlArgs): string => {\n const widthAttr = `width=\"${targetWidth}\"`;\n const heightAttr = `height=\"${targetHeight}\"`;\n\n let result = svgXml.replace(/\\bwidth=[\"'][^\"']*[\"']/, widthAttr);\n if (!/\\bwidth\\s*=/.test(result)) {\n result = result.replace(/<svg/, `<svg ${widthAttr}`);\n }\n\n result = result.replace(/\\bheight=[\"'][^\"']*[\"']/, heightAttr);\n if (!/\\bheight\\s*=/.test(result)) {\n result = result.replace(/<svg/, `<svg ${heightAttr}`);\n }\n\n return result;\n};\n\nexport interface GetChartAsPngDataUriArgs {\n chartElementId: string;\n width: number;\n height: number;\n}\n\n/**\n * Gets the Recharts chart as a PNG data URI at the given dimensions (e.g. from PDF zone).\n * Resizes the SVG via resizeSvgXml before conversion; does not use the SVG's intrinsic dimensions.\n */\nexport const getChartAsPngDataUri = async ({\n chartElementId,\n width,\n height,\n}: GetChartAsPngDataUriArgs): Promise<string | null> => {\n if (!chartElementId) {\n return null;\n }\n\n const chartElement: HTMLElement | null = getElement(chartElementId);\n if (!chartElement) {\n return null;\n }\n\n const svgElement: SVGSVGElement | null = getRechartsSvgFromElement({ chartElement, chartElementId });\n if (!svgElement) {\n return null;\n }\n\n const svgXml: string = new XMLSerializer().serializeToString(svgElement);\n const resizedXml: string = resizeSvgXml({ svgXml, targetWidth: width, targetHeight: height });\n const svgDataUri: string = convertSvgToDataUri(resizedXml);\n\n return svgToPngDataUri({\n svgDataUri,\n dimensions: { width, height },\n backgroundColor: \"white\",\n });\n};\n\n/**\n * Retrieves the SVG from a Recharts chart element and converts it to SVG base64\n * @param chartElementId - The ID of the element containing the chart\n * @returns The SVG encoded in base64 with data URI prefix (data:image/svg+xml;base64,...), or null if an error occurs\n */\nexport const getSvgAsBase64DataUri = (chartElementId: string): string | null => {\n const svgXml = getRechartSvgXml(chartElementId);\n if (!svgXml) {\n return null;\n }\n\n return convertSvgToDataUri(svgXml);\n};\n\nexport const getRechartSvgXml = (chartElementId: string): string | null => {\n if (!chartElementId) {\n console.info(`[getRechartSvgXml] No chart element id provided`);\n return null;\n }\n\n const chartElement: HTMLElement | null = getElement(chartElementId);\n if (!chartElement) {\n console.info(`[getRechartSvgXml] Element with id \"${chartElementId}\" not found`);\n return null;\n }\n\n const svgElement: SVGSVGElement | null = getRechartsSvgFromElement({ chartElement, chartElementId });\n if (!svgElement) {\n console.info(`[getRechartSvgXml] No SVG element found inside element with id \"${chartElementId}\"`);\n return null;\n }\n\n const dimensions = getSvgDimensions(svgElement);\n const clonedSvg: SVGSVGElement = prepareSvgClone({ svgElement, dimensions });\n const svgXml: string = new XMLSerializer().serializeToString(clonedSvg);\n\n return svgXml;\n};\n\nexport interface SvgToPngArgs {\n svgDataUri?: string | null;\n dimensions: Dimensions;\n backgroundColor?: string;\n}\n\nexport const svgToPngDataUri = async ({\n svgDataUri,\n dimensions,\n backgroundColor,\n}: SvgToPngArgs): Promise<string | null> => {\n if (!svgDataUri) {\n return null;\n }\n\n const { width, height } = dimensions;\n\n return new Promise((resolve, reject) => {\n const img = new Image();\n\n img.onload = () => {\n try {\n const canvas = document.createElement(\"canvas\");\n canvas.width = width;\n canvas.height = height;\n\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n reject(new Error(\"Failed to get canvas 2D context\"));\n return;\n }\n\n if (backgroundColor) {\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, width, height);\n }\n\n ctx.drawImage(img, 0, 0, width, height);\n const pngDataUri = canvas.toDataURL(\"image/png\");\n resolve(pngDataUri);\n } catch (error) {\n reject(error);\n }\n };\n\n img.onerror = (error) => {\n const message = getErrorMessage(error);\n reject(new Error(`Failed to load SVG image: ${message}`));\n };\n\n img.src = svgDataUri;\n });\n};\n"]}
1
+ {"version":3,"sources":["../src/web/base64.utils.ts","../src/web/browser.utils.ts","../src/web/canvas-image.utils.ts","../src/web/clipboard.utils.ts","../src/utils/types.utils.ts","../src/utils/errors.utils.ts","../src/utils/string.utils.ts","../src/utils/uri.utils.ts","../src/mime/index.ts","../src/web/download.utils.ts","../src/web/fetch.utils.ts","../src/web/file-reader.utils.ts","../src/web/image.utils.ts"],"names":["mime"],"mappings":"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","file":"web.cjs","sourcesContent":["interface Base64ToBlobArgs {\n base64: string;\n mimeType: string;\n}\n\nexport const base64ToBlob = ({ base64, mimeType }: Base64ToBlobArgs): Blob => {\n const byteCharacters = atob(base64);\n const byteNumbers = new Array(byteCharacters.length);\n for (let i = 0; i < byteCharacters.length; i++) {\n byteNumbers[i] = byteCharacters.charCodeAt(i);\n }\n const byteArray = new Uint8Array(byteNumbers);\n return new Blob([byteArray], { type: mimeType });\n};\n","export const getCurrentUrl = (): string => {\n if (typeof window === \"undefined\") {\n return \"\";\n }\n\n return window.location.href;\n};\n","import type { RgbaColor } from '../utils/color.utils';\n\nexport const fileToImageData = (file: File): Promise<ImageData> => {\n return new Promise((resolve, reject) => {\n const img = new Image();\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n\n if (!ctx) {\n reject(new Error('Failed to get canvas context'));\n return;\n }\n\n img.onload = () => {\n canvas.width = img.width;\n canvas.height = img.height;\n ctx.drawImage(img, 0, 0);\n const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n URL.revokeObjectURL(img.src);\n resolve(imageData);\n };\n\n img.onerror = () => {\n URL.revokeObjectURL(img.src);\n reject(new Error('Failed to load image'));\n };\n\n img.src = URL.createObjectURL(file);\n });\n};\n\nexport const dataUrlToPngBlob = (dataUrl: string): Promise<Blob> => {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => {\n const canvas = document.createElement('canvas');\n canvas.width = img.width;\n canvas.height = img.height;\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n reject(new Error('Could not get canvas context'));\n return;\n }\n ctx.drawImage(img, 0, 0);\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new Error('Could not convert to PNG'));\n }\n },\n 'image/png',\n 1,\n );\n };\n img.onerror = () => reject(new Error('Failed to load image'));\n img.src = dataUrl;\n });\n};\n\nexport const imageToCanvas = (img: HTMLImageElement): HTMLCanvasElement => {\n const canvas = document.createElement('canvas');\n canvas.width = img.naturalWidth;\n canvas.height = img.naturalHeight;\n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.drawImage(img, 0, 0);\n }\n return canvas;\n};\n\ninterface GetPixelColorArgs {\n img: HTMLImageElement;\n x: number;\n y: number;\n}\n\nexport const getPixelColor = ({ img, x, y }: GetPixelColorArgs): RgbaColor => {\n const canvas = imageToCanvas(img);\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n return { r: 0, g: 0, b: 0, a: 1 };\n }\n\n const p = ctx.getImageData(x, y, 1, 1).data;\n return {\n r: p[0] ?? 0,\n g: p[1] ?? 0,\n b: p[2] ?? 0,\n a: 1,\n };\n};\n","import { dataUrlToPngBlob } from './canvas-image.utils';\n\nexport const copyTextToClipboard = async (text: string): Promise<void> => {\n await navigator.clipboard.writeText(text);\n};\n\nexport const copyImageToClipboard = async (dataUrl: string): Promise<void> => {\n const response = await fetch(dataUrl);\n const blob = await response.blob();\n\n const pngBlob = blob.type === 'image/png' ? blob : await dataUrlToPngBlob(dataUrl);\n\n await navigator.clipboard.write([new ClipboardItem({ 'image/png': pngBlob })]);\n};\n","export const NO_OP: () => void = () => {};\n\nexport const isNullish = (value: unknown): value is null | undefined => value === null || value === undefined;\n\nexport const isNumber = (value?: unknown | null): value is number => {\n if (isNullish(value)) {\n return false;\n }\n\n if (typeof value !== 'number') {\n return false;\n }\n\n if (isNaN(value)) {\n return false;\n }\n\n return true;\n};\n\nexport const isString = (value?: unknown | null): value is string => {\n if (isNullish(value)) {\n return false;\n }\n\n if (typeof value !== 'string') {\n return false;\n }\n\n return true;\n};\n","export const getErrorMessage = (error: unknown): string => {\n if (!error) {\n return \"\";\n }\n\n if (typeof error === \"string\") {\n return error;\n }\n\n if (typeof error === \"object\" && \"message\" in error) {\n return (error as { message: string }).message;\n }\n\n return JSON.stringify(error);\n};\n\nexport const toError = (error: unknown): Error => {\n if (error instanceof Error) {\n return error;\n }\n\n return new Error(getErrorMessage(error));\n};\n","import { REGEX_ALPHANUMERIC } from './regex';\nimport { isNullish } from './types.utils';\n\nexport const isBlank = (str?: string | null): str is null | undefined | '' => {\n return isNullish(str) || str?.trim() === '';\n};\n\nexport const isNotBlank = (str?: string | null): str is string => {\n return !isBlank(str);\n};\n\nexport const isAlphanumeric = (value: string): boolean => {\n return REGEX_ALPHANUMERIC.test(value);\n};\n\n/**\n * Removes diacritical marks (e.g., accents, umlauts) from a string.\n * This method normalizes the input string to its canonical decomposition\n * form (NFD) and removes any combining diacritical marks.\n *\n * @param {string} value - The input string to normalize.\n * @returns {string} - The normalized string with diacritical marks removed.\n *\n * @example\n * const result = removeDiacriticalMarks(\"Ça va très bien, n'est-ce pas?\");\n * console.log(result); // \"Ca va tres bien, n'est-ce pas?\"\n */\nexport const removeDiacriticalMarks = (value: string): string => {\n if (!value) {\n return '';\n }\n\n return value.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '');\n};\n\n/**\n * Capitalize the first letter of a string.\n * @param str - The input string\n * @returns The string with the first character uppercased\n */\nexport const capitalizeFirst = (str: string): string => {\n if (!str) return str;\n return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\n/**\n * Count the number of words in a text string.\n * Words are separated by whitespace.\n * @param text - The text to count words in\n * @returns The number of words found\n */\nexport const countWords = (text: string): number => {\n if (!text || text.trim().length === 0) return 0;\n return text.split(/\\s+/).filter((word) => word.length > 0).length;\n};\n\n/**\n * Truncate a string to a maximum length, adding an ellipsis if truncated.\n * @param str - The string to truncate\n * @param maxLength - Maximum length before truncation\n * @param ellipsis - The ellipsis string to append (default: \"...\")\n * @returns The truncated string\n */\nexport const truncate = (str: string, maxLength: number, ellipsis = \"...\"): string => {\n if (!str || str.length <= maxLength) return str;\n return str.slice(0, maxLength - ellipsis.length) + ellipsis;\n};\n\n/**\n * Parses an optional comma-separated string into a trimmed, non-blank string array.\n */\nexport const parseCommaSeparatedList = (raw?: string | null): string[] => {\n if (isBlank(raw)) {\n return [];\n }\n\n return raw\n .split(\",\")\n .map((s: string) => s.trim())\n .filter(isNotBlank);\n};\n","import { isBlank } from \".\";\n\nexport const SCHEME_PREFIXES = {\n file: 'file',\n content: 'content',\n http: 'http',\n https: 'https',\n ftp: 'ftp',\n ftps: 'ftps',\n sftp: 'sftp',\n smb: 'smb',\n} as const;\n\nconst SCHEME_PREFIXES_ARRAY = Object.values(SCHEME_PREFIXES);\n\nexport const DATA_URI_PATTERN = /^data:([\\w.+-]+\\/[\\w.+-]+);base64,(.+)$/;\n\nexport const isValidDataUri = (uri?: string | null): boolean => {\n if (isBlank(uri)) {\n return false;\n }\n\n return DATA_URI_PATTERN.test(uri);\n};\n\nexport const hasScheme = (uri?: string | null): boolean => {\n if (!uri) {\n return false;\n }\n\n const lowerUri = uri.toLowerCase();\n return SCHEME_PREFIXES_ARRAY.some((prefix) => lowerUri.startsWith(`${prefix}://`));\n};\n\n/**\n * Extracts the base64 data from a data URI string.\n * Data URIs have the format: data:[<mediatype>][;base64],<data>\n * This function extracts everything after the first comma.\n *\n * @param dataUri - The data URI string (e.g., \"data:image/png;base64,iVBORw0KG...\")\n * @returns The base64 data without the data URI prefix, or the original string if no comma is found\n */\nexport const extractBase64FromDataUri = (dataUri: string): string => {\n return dataUri.split(',')[1] ?? dataUri;\n};\n\nexport const encodeUrl = (value?: string): string => {\n if (!value) return '';\n return encodeURIComponent(value);\n};\n\nexport const decodeUrl = (value?: string): string => {\n if (!value) return '';\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n};\n\ninterface FormatDataUriArgs {\n mimeType: string;\n base64: string;\n}\n\nexport const formatDataUri = ({ mimeType, base64 }: FormatDataUriArgs): string => {\n return `data:${mimeType};base64,${base64}`;\n};\n\nexport const getBase64ApproxSize = (base64: string): number => {\n return Math.round((base64.length * 3) / 4);\n};\n","import mime from \"mime\";\n\nimport { DATA_URI_PATTERN, isValidDataUri } from \"~/utils/uri.utils\";\nimport { VALID_IMAGE_TYPES } from './mime.utils';\n\nexport { VALID_IMAGE_TYPES } from './mime.utils';\n\nexport interface ParseDataUriResult {\n mimeType: string;\n base64: string;\n ext: string;\n}\n\nexport const parseDataUri = (input: string): ParseDataUriResult | null => {\n if (!isValidDataUri(input)) return null;\n\n const match = DATA_URI_PATTERN.exec(input);\n if (!match) return null;\n\n const [, mimeType, base64] = match;\n if (!mimeType || !base64) return null;\n\n return { mimeType, base64, ext: mimeToExt(mimeType) };\n};\n\nexport const isImageMimeType = (mimeType: string): boolean => {\n return VALID_IMAGE_TYPES.includes(mimeType);\n};\n\nexport const isValidImageFile = (file: { type: string }): boolean => {\n return isImageMimeType(file.type);\n};\n\nexport const getExtensionFromDataUri = (dataUri: string): string => {\n const parsed = parseDataUri(dataUri);\n if (!parsed) return 'bin';\n\n return parsed.ext;\n};\n\nexport const getImagePreviewSrc = (input: string): string | null => {\n const parsed = parseDataUri(input);\n if (!parsed) return null;\n if (!isImageMimeType(parsed.mimeType)) return null;\n\n return input;\n};\n\nexport const mimeToExt = (mimeType: string): string => {\n const ext = mime.getExtension(mimeType);\n if (ext) return ext;\n\n const subtype = mimeType.split(\"/\")[1] ?? mimeType;\n return subtype.split(\"+\")[0] ?? subtype;\n};\n\nexport const getMimeType = (extension: string): string => {\n const mimeType = mime.getType(extension);\n if (!mimeType) {\n throw new Error(`[getMimeType] Mime type not found for extension: \"${extension}\"`);\n }\n\n return mimeType;\n};\n\n","import { getExtensionFromDataUri } from '../mime';\n\ninterface DownloadBlobArgs {\n blob: Blob;\n fileName: string;\n}\n\nexport const downloadBlob = ({ blob, fileName }: DownloadBlobArgs): void => {\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = fileName;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n};\n\ninterface DownloadDataUrlArgs {\n dataUrl: string;\n fileName: string;\n}\n\nexport const downloadDataUrl = ({ dataUrl, fileName }: DownloadDataUrlArgs): void => {\n const link = document.createElement('a');\n link.href = dataUrl;\n link.download = fileName;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n};\n\ninterface DownloadTextArgs {\n content: string;\n fileName: string;\n mimeType?: string;\n}\n\nexport const downloadText = ({ content, fileName, mimeType = 'text/plain' }: DownloadTextArgs): void => {\n const blob = new Blob([content], { type: mimeType });\n downloadBlob({ blob, fileName });\n};\n\ninterface DownloadJsonArgs {\n content: string;\n fileName?: string;\n}\n\nexport const downloadJson = ({ content, fileName = 'data.json' }: DownloadJsonArgs): void => {\n downloadText({ content, fileName, mimeType: 'application/json' });\n};\n\nexport { getExtensionFromDataUri };\n","import { getErrorMessage } from \"../utils\";\n\n/**\n * Converts a Blob to a data URI string.\n */\nexport const blobToDataUri = (blob: Blob): Promise<string | null> => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onerror = () => reject(reader.error);\n reader.onloadend = () => {\n const { result } = reader;\n resolve(typeof result === \"string\" ? result : null);\n };\n\n reader.readAsDataURL(blob);\n });\n};\n\n/**\n * Fetches a resource by URL and returns its content as a data URI.\n * Content type is inferred from the response Content-Type header when possible.\n */\nexport const fetchUrlAsDataUri = async (url: string): Promise<string | null> => {\n try {\n const response = await fetch(url);\n if (!response.ok) {\n console.warn(`[fetchUrlAsDataUri] Response not ok (${response.status}). url: \"${url}\"`);\n return null;\n }\n\n const blob = await response.blob();\n return blobToDataUri(blob);\n } catch (e: unknown) {\n const message = getErrorMessage(e);\n console.error(`[fetchUrlAsDataUri] \"${message}\". url: \"${url}\"`, e);\n return null;\n }\n};\n","import { extractBase64FromDataUri } from '../utils/uri.utils';\n\nexport const readFileAsDataUrl = (file: File): Promise<string> => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (ev) => {\n const result = ev.target?.result;\n if (typeof result === 'string') {\n resolve(result);\n } else {\n reject(new Error('Failed to read file'));\n }\n };\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsDataURL(file);\n });\n};\n\nexport interface Base64FileResult {\n base64: string;\n mimeType: string;\n}\n\nexport const readFileAsBase64 = (file: File): Promise<Base64FileResult> => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n const result = reader.result as string;\n const base64 = extractBase64FromDataUri(result);\n const mimeType = file.type || 'application/octet-stream';\n resolve({ base64, mimeType });\n };\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsDataURL(file);\n });\n};\n\nexport const readFileAsText = (file: File): Promise<string> => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n const result = reader.result;\n if (typeof result === 'string') {\n resolve(result);\n } else {\n reject(new Error('Failed to read file as text'));\n }\n };\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsText(file);\n });\n};\n\nexport const readFileAsArrayBuffer = (file: File): Promise<ArrayBuffer> => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n const result = reader.result;\n if (result instanceof ArrayBuffer) {\n resolve(result);\n } else {\n reject(new Error('Failed to read file as ArrayBuffer'));\n }\n };\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsArrayBuffer(file);\n });\n};\n\nexport const getImageFileFromClipboard = (items: DataTransferItemList): File | null => {\n if (!items) return null;\n\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (!item?.type.startsWith('image')) continue;\n\n const file = item.getAsFile();\n if (file) return file;\n }\n\n return null;\n};\n\ninterface ClipboardImageCallbackArgs {\n items: DataTransferItemList;\n onFile: (file: File) => void;\n}\n\nexport const clipboardImageToFile = ({ items, onFile }: ClipboardImageCallbackArgs): void => {\n const file = getImageFileFromClipboard(items);\n if (file) onFile(file);\n};\n\ninterface ClipboardToDataUrlArgs {\n items: DataTransferItemList;\n onLoad: (result: string) => void;\n onError?: (error: Error) => void;\n}\n\nexport const clipboardImageToDataUrl = ({ items, onLoad, onError }: ClipboardToDataUrlArgs): void => {\n const file = getImageFileFromClipboard(items);\n if (!file) return;\n\n readFileAsDataUrl(file)\n .then(onLoad)\n .catch((error) => onError?.(error instanceof Error ? error : new Error(String(error))));\n};\n","import { getErrorMessage, type Dimensions } from \"../utils\";\n\nexport const hasRechartsElements = (svg: SVGSVGElement): boolean => {\n return (\n svg.querySelector(\"g.recharts-layer\") !== null ||\n svg.querySelector(\"g.recharts-cartesian-axis\") !== null ||\n svg.querySelector(\"g.recharts-cartesian-grid\") !== null ||\n svg.querySelector(\"path.recharts-curve\") !== null\n );\n};\n\nexport const findRechartsSvg = (svgs: NodeListOf<SVGSVGElement> | SVGSVGElement[]): SVGSVGElement | null => {\n for (const svg of Array.from(svgs)) {\n if (hasRechartsElements(svg)) {\n return svg;\n }\n }\n\n return null;\n};\n\nexport const getElement = (id: string): HTMLElement | null => {\n const element = document?.getElementById(id);\n if (!element) {\n console.info(`[getElement] Element with id \"${id}\" not found`);\n return null;\n }\n\n return element;\n};\n\nexport interface GetRechartsSvgFromElementArgs {\n chartElement: HTMLElement;\n chartElementId: string;\n}\n\nexport const getRechartsSvgFromElement = ({\n chartElement,\n chartElementId,\n}: GetRechartsSvgFromElementArgs): SVGSVGElement | null => {\n const allSvgs = chartElement.querySelectorAll<SVGSVGElement>(\"svg\");\n if (allSvgs.length === 0) {\n console.info(`[getRechartsSvgFromElement] SVG element not found inside element with id \"${chartElementId}\"`);\n return null;\n }\n\n const rechartSvg = findRechartsSvg(allSvgs);\n if (!rechartSvg) {\n console.info(`[getRechartsSvgFromElement] No Recharts SVG element found inside element with id \"${chartElementId}\"`);\n return null;\n }\n\n return rechartSvg;\n};\n\nexport const getSvgDimensions = (svgElement: SVGSVGElement): Dimensions => {\n const width = svgElement.clientWidth ?? parseInt(svgElement.getAttribute(\"width\") ?? \"800\", 10);\n const height = svgElement.clientHeight ?? parseInt(svgElement.getAttribute(\"height\") ?? \"600\", 10);\n return { width, height };\n};\n\nexport interface PrepareSvgCloneArgs {\n svgElement: SVGSVGElement;\n dimensions: Dimensions;\n}\n\n/**\n * Clones an SVG element and ensures it has the required width and height attributes.\n *\n * This function is necessary for two main reasons:\n *\n * 1. **Defensive cloning**: Cloning prevents modifying the original SVG element in the DOM.\n * Although `XMLSerializer.serializeToString()` does not modify the element, cloning ensures\n * that no accidental modifications are made to the source element.\n *\n * 2. **Required width/height attributes**: When converting SVG → PNG via `svgToPngDataUri`,\n * the HTML Image element requires the SVG to have explicit intrinsic dimensions.\n * Without width/height attributes, the SVG may not render correctly on the canvas,\n * resulting in an incorrect or empty PNG image.\n *\n * @param svgElement - The original SVG element to clone\n * @param dimensions - The dimensions to apply to the cloned SVG if attributes are missing\n * @returns A new cloned SVG element with guaranteed width/height attributes\n */\nexport const prepareSvgClone = ({ svgElement, dimensions }: PrepareSvgCloneArgs): SVGSVGElement => {\n const clonedSvg = svgElement.cloneNode(true) as SVGSVGElement;\n\n if (!clonedSvg.hasAttribute(\"width\")) {\n clonedSvg.setAttribute(\"width\", dimensions.width.toString());\n }\n if (!clonedSvg.hasAttribute(\"height\")) {\n clonedSvg.setAttribute(\"height\", dimensions.height.toString());\n }\n\n return clonedSvg;\n};\n\nexport const convertSvgToDataUri = (svgXml: string): string => {\n const encoder = new TextEncoder();\n const data = encoder.encode(svgXml);\n let binaryString = \"\";\n for (let i = 0; i < data.length; i++) {\n binaryString += String.fromCharCode(data[i]);\n }\n const base64 = btoa(binaryString);\n return `data:image/svg+xml;base64,${base64}`;\n};\n\nexport interface ResizeSvgXmlArgs {\n svgXml: string;\n targetWidth: number;\n targetHeight: number;\n}\n\n/**\n * Modifies SVG XML to set the root <svg> width and height attributes.\n * Used to resize the SVG before converting to PNG at target dimensions (e.g. from PDF layout).\n */\nexport const resizeSvgXml = ({ svgXml, targetWidth, targetHeight }: ResizeSvgXmlArgs): string => {\n const widthAttr = `width=\"${targetWidth}\"`;\n const heightAttr = `height=\"${targetHeight}\"`;\n\n let result = svgXml.replace(/\\bwidth=[\"'][^\"']*[\"']/, widthAttr);\n if (!/\\bwidth\\s*=/.test(result)) {\n result = result.replace(/<svg/, `<svg ${widthAttr}`);\n }\n\n result = result.replace(/\\bheight=[\"'][^\"']*[\"']/, heightAttr);\n if (!/\\bheight\\s*=/.test(result)) {\n result = result.replace(/<svg/, `<svg ${heightAttr}`);\n }\n\n return result;\n};\n\nexport interface GetChartAsPngDataUriArgs {\n chartElementId: string;\n width: number;\n height: number;\n}\n\n/**\n * Gets the Recharts chart as a PNG data URI at the given dimensions (e.g. from PDF zone).\n * Resizes the SVG via resizeSvgXml before conversion; does not use the SVG's intrinsic dimensions.\n */\nexport const getChartAsPngDataUri = async ({\n chartElementId,\n width,\n height,\n}: GetChartAsPngDataUriArgs): Promise<string | null> => {\n if (!chartElementId) {\n return null;\n }\n\n const chartElement: HTMLElement | null = getElement(chartElementId);\n if (!chartElement) {\n return null;\n }\n\n const svgElement: SVGSVGElement | null = getRechartsSvgFromElement({ chartElement, chartElementId });\n if (!svgElement) {\n return null;\n }\n\n const svgXml: string = new XMLSerializer().serializeToString(svgElement);\n const resizedXml: string = resizeSvgXml({ svgXml, targetWidth: width, targetHeight: height });\n const svgDataUri: string = convertSvgToDataUri(resizedXml);\n\n return svgToPngDataUri({\n svgDataUri,\n dimensions: { width, height },\n backgroundColor: \"white\",\n });\n};\n\n/**\n * Retrieves the SVG from a Recharts chart element and converts it to SVG base64\n * @param chartElementId - The ID of the element containing the chart\n * @returns The SVG encoded in base64 with data URI prefix (data:image/svg+xml;base64,...), or null if an error occurs\n */\nexport const getSvgAsBase64DataUri = (chartElementId: string): string | null => {\n const svgXml = getRechartSvgXml(chartElementId);\n if (!svgXml) {\n return null;\n }\n\n return convertSvgToDataUri(svgXml);\n};\n\nexport const getRechartSvgXml = (chartElementId: string): string | null => {\n if (!chartElementId) {\n console.info(`[getRechartSvgXml] No chart element id provided`);\n return null;\n }\n\n const chartElement: HTMLElement | null = getElement(chartElementId);\n if (!chartElement) {\n console.info(`[getRechartSvgXml] Element with id \"${chartElementId}\" not found`);\n return null;\n }\n\n const svgElement: SVGSVGElement | null = getRechartsSvgFromElement({ chartElement, chartElementId });\n if (!svgElement) {\n console.info(`[getRechartSvgXml] No SVG element found inside element with id \"${chartElementId}\"`);\n return null;\n }\n\n const dimensions = getSvgDimensions(svgElement);\n const clonedSvg: SVGSVGElement = prepareSvgClone({ svgElement, dimensions });\n const svgXml: string = new XMLSerializer().serializeToString(clonedSvg);\n\n return svgXml;\n};\n\nexport interface SvgToPngArgs {\n svgDataUri?: string | null;\n dimensions: Dimensions;\n backgroundColor?: string;\n}\n\nexport const svgToPngDataUri = async ({\n svgDataUri,\n dimensions,\n backgroundColor,\n}: SvgToPngArgs): Promise<string | null> => {\n if (!svgDataUri) {\n return null;\n }\n\n const { width, height } = dimensions;\n\n return new Promise((resolve, reject) => {\n const img = new Image();\n\n img.onload = () => {\n try {\n const canvas = document.createElement(\"canvas\");\n canvas.width = width;\n canvas.height = height;\n\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n reject(new Error(\"Failed to get canvas 2D context\"));\n return;\n }\n\n if (backgroundColor) {\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, width, height);\n }\n\n ctx.drawImage(img, 0, 0, width, height);\n const pngDataUri = canvas.toDataURL(\"image/png\");\n resolve(pngDataUri);\n } catch (error) {\n reject(error);\n }\n };\n\n img.onerror = (error) => {\n const message = getErrorMessage(error);\n reject(new Error(`Failed to load SVG image: ${message}`));\n };\n\n img.src = svgDataUri;\n });\n};\n"]}
package/dist/web.d.cts CHANGED
@@ -1,7 +1,49 @@
1
- import { D as Dimensions } from './dimensions.utils-BwIBA5op.cjs';
1
+ import { a as RgbaColor, D as Dimensions } from './dimensions.utils-BSm9gmWz.cjs';
2
+ export { getExtensionFromDataUri } from './mime.cjs';
3
+
4
+ interface Base64ToBlobArgs {
5
+ base64: string;
6
+ mimeType: string;
7
+ }
8
+ declare const base64ToBlob: ({ base64, mimeType }: Base64ToBlobArgs) => Blob;
2
9
 
3
10
  declare const getCurrentUrl: () => string;
4
11
 
12
+ declare const fileToImageData: (file: File) => Promise<ImageData>;
13
+ declare const dataUrlToPngBlob: (dataUrl: string) => Promise<Blob>;
14
+ declare const imageToCanvas: (img: HTMLImageElement) => HTMLCanvasElement;
15
+ interface GetPixelColorArgs {
16
+ img: HTMLImageElement;
17
+ x: number;
18
+ y: number;
19
+ }
20
+ declare const getPixelColor: ({ img, x, y }: GetPixelColorArgs) => RgbaColor;
21
+
22
+ declare const copyTextToClipboard: (text: string) => Promise<void>;
23
+ declare const copyImageToClipboard: (dataUrl: string) => Promise<void>;
24
+
25
+ interface DownloadBlobArgs {
26
+ blob: Blob;
27
+ fileName: string;
28
+ }
29
+ declare const downloadBlob: ({ blob, fileName }: DownloadBlobArgs) => void;
30
+ interface DownloadDataUrlArgs {
31
+ dataUrl: string;
32
+ fileName: string;
33
+ }
34
+ declare const downloadDataUrl: ({ dataUrl, fileName }: DownloadDataUrlArgs) => void;
35
+ interface DownloadTextArgs {
36
+ content: string;
37
+ fileName: string;
38
+ mimeType?: string;
39
+ }
40
+ declare const downloadText: ({ content, fileName, mimeType }: DownloadTextArgs) => void;
41
+ interface DownloadJsonArgs {
42
+ content: string;
43
+ fileName?: string;
44
+ }
45
+ declare const downloadJson: ({ content, fileName }: DownloadJsonArgs) => void;
46
+
5
47
  /**
6
48
  * Converts a Blob to a data URI string.
7
49
  */
@@ -12,6 +54,27 @@ declare const blobToDataUri: (blob: Blob) => Promise<string | null>;
12
54
  */
13
55
  declare const fetchUrlAsDataUri: (url: string) => Promise<string | null>;
14
56
 
57
+ declare const readFileAsDataUrl: (file: File) => Promise<string>;
58
+ interface Base64FileResult {
59
+ base64: string;
60
+ mimeType: string;
61
+ }
62
+ declare const readFileAsBase64: (file: File) => Promise<Base64FileResult>;
63
+ declare const readFileAsText: (file: File) => Promise<string>;
64
+ declare const readFileAsArrayBuffer: (file: File) => Promise<ArrayBuffer>;
65
+ declare const getImageFileFromClipboard: (items: DataTransferItemList) => File | null;
66
+ interface ClipboardImageCallbackArgs {
67
+ items: DataTransferItemList;
68
+ onFile: (file: File) => void;
69
+ }
70
+ declare const clipboardImageToFile: ({ items, onFile }: ClipboardImageCallbackArgs) => void;
71
+ interface ClipboardToDataUrlArgs {
72
+ items: DataTransferItemList;
73
+ onLoad: (result: string) => void;
74
+ onError?: (error: Error) => void;
75
+ }
76
+ declare const clipboardImageToDataUrl: ({ items, onLoad, onError }: ClipboardToDataUrlArgs) => void;
77
+
15
78
  declare const hasRechartsElements: (svg: SVGSVGElement) => boolean;
16
79
  declare const findRechartsSvg: (svgs: NodeListOf<SVGSVGElement> | SVGSVGElement[]) => SVGSVGElement | null;
17
80
  declare const getElement: (id: string) => HTMLElement | null;
@@ -79,4 +142,4 @@ interface SvgToPngArgs {
79
142
  }
80
143
  declare const svgToPngDataUri: ({ svgDataUri, dimensions, backgroundColor, }: SvgToPngArgs) => Promise<string | null>;
81
144
 
82
- export { type GetChartAsPngDataUriArgs, type GetRechartsSvgFromElementArgs, type PrepareSvgCloneArgs, type ResizeSvgXmlArgs, type SvgToPngArgs, blobToDataUri, convertSvgToDataUri, fetchUrlAsDataUri, findRechartsSvg, getChartAsPngDataUri, getCurrentUrl, getElement, getRechartSvgXml, getRechartsSvgFromElement, getSvgAsBase64DataUri, getSvgDimensions, hasRechartsElements, prepareSvgClone, resizeSvgXml, svgToPngDataUri };
145
+ export { type Base64FileResult, type GetChartAsPngDataUriArgs, type GetRechartsSvgFromElementArgs, type PrepareSvgCloneArgs, type ResizeSvgXmlArgs, type SvgToPngArgs, base64ToBlob, blobToDataUri, clipboardImageToDataUrl, clipboardImageToFile, convertSvgToDataUri, copyImageToClipboard, copyTextToClipboard, dataUrlToPngBlob, downloadBlob, downloadDataUrl, downloadJson, downloadText, fetchUrlAsDataUri, fileToImageData, findRechartsSvg, getChartAsPngDataUri, getCurrentUrl, getElement, getImageFileFromClipboard, getPixelColor, getRechartSvgXml, getRechartsSvgFromElement, getSvgAsBase64DataUri, getSvgDimensions, hasRechartsElements, imageToCanvas, prepareSvgClone, readFileAsArrayBuffer, readFileAsBase64, readFileAsDataUrl, readFileAsText, resizeSvgXml, svgToPngDataUri };