@simplysm/core-browser 13.0.0-beta.7 → 13.0.2
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/extensions/element-ext.d.ts.map +1 -0
- package/dist/extensions/element-ext.js.map +0 -1
- package/dist/extensions/html-element-ext.d.ts.map +1 -0
- package/dist/extensions/html-element-ext.js.map +0 -1
- package/dist/{core-browser/src/index.d.ts → index.d.ts} +2 -1
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -6
- package/dist/index.js.map +1 -2
- package/dist/utils/download.d.ts +8 -0
- package/dist/utils/download.d.ts.map +1 -0
- package/dist/utils/download.js +8 -40
- package/dist/utils/download.js.map +2 -3
- package/dist/{core-browser/src/utils/download.d.ts → utils/fetch.d.ts} +2 -2
- package/dist/utils/fetch.d.ts.map +1 -0
- package/dist/utils/fetch.js +47 -0
- package/dist/utils/fetch.js.map +6 -0
- package/dist/utils/file-dialog.d.ts +8 -0
- package/dist/utils/file-dialog.d.ts.map +1 -0
- package/dist/utils/file-dialog.js +18 -0
- package/dist/utils/file-dialog.js.map +6 -0
- package/package.json +6 -5
- package/src/extensions/element-ext.ts +246 -0
- package/src/extensions/html-element-ext.ts +117 -0
- package/src/index.ts +12 -0
- package/src/utils/download.ts +17 -0
- package/src/utils/fetch.ts +66 -0
- package/src/utils/file-dialog.ts +17 -0
- package/dist/core-browser/src/extensions/element-ext.d.ts.map +0 -1
- package/dist/core-browser/src/extensions/html-element-ext.d.ts.map +0 -1
- package/dist/core-browser/src/index.d.ts.map +0 -1
- package/dist/core-browser/src/utils/blob.d.ts +0 -10
- package/dist/core-browser/src/utils/blob.d.ts.map +0 -1
- package/dist/core-browser/src/utils/download.d.ts.map +0 -1
- package/dist/core-common/src/common.types.d.ts +0 -74
- package/dist/core-common/src/common.types.d.ts.map +0 -1
- package/dist/core-common/src/env.d.ts +0 -6
- package/dist/core-common/src/env.d.ts.map +0 -1
- package/dist/core-common/src/errors/argument-error.d.ts +0 -25
- package/dist/core-common/src/errors/argument-error.d.ts.map +0 -1
- package/dist/core-common/src/errors/not-implemented-error.d.ts +0 -29
- package/dist/core-common/src/errors/not-implemented-error.d.ts.map +0 -1
- package/dist/core-common/src/errors/sd-error.d.ts +0 -27
- package/dist/core-common/src/errors/sd-error.d.ts.map +0 -1
- package/dist/core-common/src/errors/timeout-error.d.ts +0 -31
- package/dist/core-common/src/errors/timeout-error.d.ts.map +0 -1
- package/dist/core-common/src/extensions/arr-ext.d.ts +0 -15
- package/dist/core-common/src/extensions/arr-ext.d.ts.map +0 -1
- package/dist/core-common/src/extensions/arr-ext.helpers.d.ts +0 -19
- package/dist/core-common/src/extensions/arr-ext.helpers.d.ts.map +0 -1
- package/dist/core-common/src/extensions/arr-ext.types.d.ts +0 -215
- package/dist/core-common/src/extensions/arr-ext.types.d.ts.map +0 -1
- package/dist/core-common/src/extensions/map-ext.d.ts +0 -57
- package/dist/core-common/src/extensions/map-ext.d.ts.map +0 -1
- package/dist/core-common/src/extensions/set-ext.d.ts +0 -36
- package/dist/core-common/src/extensions/set-ext.d.ts.map +0 -1
- package/dist/core-common/src/features/debounce-queue.d.ts +0 -53
- package/dist/core-common/src/features/debounce-queue.d.ts.map +0 -1
- package/dist/core-common/src/features/event-emitter.d.ts +0 -66
- package/dist/core-common/src/features/event-emitter.d.ts.map +0 -1
- package/dist/core-common/src/features/serial-queue.d.ts +0 -47
- package/dist/core-common/src/features/serial-queue.d.ts.map +0 -1
- package/dist/core-common/src/index.d.ts +0 -32
- package/dist/core-common/src/index.d.ts.map +0 -1
- package/dist/core-common/src/types/date-only.d.ts +0 -152
- package/dist/core-common/src/types/date-only.d.ts.map +0 -1
- package/dist/core-common/src/types/date-time.d.ts +0 -96
- package/dist/core-common/src/types/date-time.d.ts.map +0 -1
- package/dist/core-common/src/types/lazy-gc-map.d.ts +0 -80
- package/dist/core-common/src/types/lazy-gc-map.d.ts.map +0 -1
- package/dist/core-common/src/types/time.d.ts +0 -68
- package/dist/core-common/src/types/time.d.ts.map +0 -1
- package/dist/core-common/src/types/uuid.d.ts +0 -35
- package/dist/core-common/src/types/uuid.d.ts.map +0 -1
- package/dist/core-common/src/utils/bytes.d.ts +0 -51
- package/dist/core-common/src/utils/bytes.d.ts.map +0 -1
- package/dist/core-common/src/utils/date-format.d.ts +0 -90
- package/dist/core-common/src/utils/date-format.d.ts.map +0 -1
- package/dist/core-common/src/utils/json.d.ts +0 -34
- package/dist/core-common/src/utils/json.d.ts.map +0 -1
- package/dist/core-common/src/utils/num.d.ts +0 -60
- package/dist/core-common/src/utils/num.d.ts.map +0 -1
- package/dist/core-common/src/utils/obj.d.ts +0 -258
- package/dist/core-common/src/utils/obj.d.ts.map +0 -1
- package/dist/core-common/src/utils/path.d.ts +0 -23
- package/dist/core-common/src/utils/path.d.ts.map +0 -1
- package/dist/core-common/src/utils/primitive.d.ts +0 -18
- package/dist/core-common/src/utils/primitive.d.ts.map +0 -1
- package/dist/core-common/src/utils/str.d.ts +0 -103
- package/dist/core-common/src/utils/str.d.ts.map +0 -1
- package/dist/core-common/src/utils/template-strings.d.ts +0 -84
- package/dist/core-common/src/utils/template-strings.d.ts.map +0 -1
- package/dist/core-common/src/utils/transferable.d.ts +0 -47
- package/dist/core-common/src/utils/transferable.d.ts.map +0 -1
- package/dist/core-common/src/utils/wait.d.ts +0 -19
- package/dist/core-common/src/utils/wait.d.ts.map +0 -1
- package/dist/core-common/src/utils/xml.d.ts +0 -36
- package/dist/core-common/src/utils/xml.d.ts.map +0 -1
- package/dist/core-common/src/zip/sd-zip.d.ts +0 -80
- package/dist/core-common/src/zip/sd-zip.d.ts.map +0 -1
- package/dist/utils/blob.js +0 -19
- package/dist/utils/blob.js.map +0 -7
- /package/dist/{core-browser/src/extensions → extensions}/element-ext.d.ts +0 -0
- /package/dist/{core-browser/src/extensions → extensions}/html-element-ext.d.ts +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element-ext.d.ts","sourceRoot":"","sources":["../../src/extensions/element-ext.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,eAAe;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,mBAAmB;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,YAAY;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO;QACf;;;;;WAKG;QACH,OAAO,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;QAE5D;;;;;WAKG;QACH,SAAS,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;QAExE;;;;;WAKG;QACH,YAAY,CAAC,CAAC,SAAS,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;QAE7C;;;;WAIG;QACH,UAAU,IAAI,OAAO,EAAE,CAAC;QAExB;;;;WAIG;QACH,mBAAmB,IAAI,WAAW,GAAG,SAAS,CAAC;QAE/C;;;;WAIG;QACH,uBAAuB,IAAI,WAAW,GAAG,SAAS,CAAC;QAEnD;;;;WAIG;QACH,eAAe,IAAI,OAAO,CAAC;QAE3B;;;;;;;WAOG;QACH,SAAS,IAAI,OAAO,CAAC;KACtB;CACF;AAgED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAUvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAa1D;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,OAAO,GAAE,MAAa,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAkDhG"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/extensions/element-ext.ts"],
|
|
4
|
-
"sourcesContent": ["import { isFocusable } from \"tabbable\";\nimport { TimeoutError } from \"@simplysm/core-common\";\n\n/**\n * \uC694\uC18C bounds \uC815\uBCF4 \uD0C0\uC785\n */\nexport interface ElementBounds {\n /** \uCE21\uC815 \uB300\uC0C1 \uC694\uC18C */\n target: Element;\n /** \uBDF0\uD3EC\uD2B8 \uAE30\uC900 \uC0C1\uB2E8 \uC704\uCE58 */\n top: number;\n /** \uBDF0\uD3EC\uD2B8 \uAE30\uC900 \uC67C\uCABD \uC704\uCE58 */\n left: number;\n /** \uC694\uC18C \uB108\uBE44 */\n width: number;\n /** \uC694\uC18C \uB192\uC774 */\n height: number;\n}\n\ndeclare global {\n interface Element {\n /**\n * \uC140\uB809\uD130\uB85C \uD558\uC704 \uC694\uC18C \uC804\uCCB4 \uAC80\uC0C9\n *\n * @param selector - CSS \uC140\uB809\uD130\n * @returns \uB9E4\uCE6D\uB41C \uC694\uC18C \uBC30\uC5F4 (\uBE48 \uC140\uB809\uD130\uB294 \uBE48 \uBC30\uC5F4 \uBC18\uD658)\n */\n findAll<T extends Element = Element>(selector: string): T[];\n\n /**\n * \uC140\uB809\uD130\uB85C \uCCAB \uBC88\uC9F8 \uB9E4\uCE6D \uC694\uC18C \uAC80\uC0C9\n *\n * @param selector - CSS \uC140\uB809\uD130\n * @returns \uCCAB \uBC88\uC9F8 \uB9E4\uCE6D \uC694\uC18C \uB610\uB294 undefined (\uBE48 \uC140\uB809\uD130\uB294 undefined \uBC18\uD658)\n */\n findFirst<T extends Element = Element>(selector: string): T | undefined;\n\n /**\n * \uC694\uC18C\uB97C \uCCAB \uBC88\uC9F8 \uC790\uC2DD\uC73C\uB85C \uC0BD\uC785\n *\n * @param child - \uC0BD\uC785\uD560 \uC790\uC2DD \uC694\uC18C\n * @returns \uC0BD\uC785\uB41C \uC790\uC2DD \uC694\uC18C\n */\n prependChild<T extends Element>(child: T): T;\n\n /**\n * \uBAA8\uB4E0 \uBD80\uBAA8 \uC694\uC18C \uBAA9\uB85D \uBC18\uD658 (\uAC00\uAE4C\uC6B4 \uC21C\uC11C)\n *\n * @returns \uBD80\uBAA8 \uC694\uC18C \uBC30\uC5F4 (\uAC00\uAE4C\uC6B4 \uBD80\uBAA8\uBD80\uD130 \uC21C\uC11C\uB300\uB85C)\n */\n getParents(): Element[];\n\n /**\n * \uBD80\uBAA8 \uC911 \uCCAB \uBC88\uC9F8 \uD3EC\uCEE4\uC2A4 \uAC00\uB2A5 \uC694\uC18C \uAC80\uC0C9 (tabbable \uC0AC\uC6A9)\n *\n * @returns \uD3EC\uCEE4\uC2A4 \uAC00\uB2A5\uD55C \uCCAB \uBC88\uC9F8 \uBD80\uBAA8 \uC694\uC18C \uB610\uB294 undefined\n */\n findFocusableParent(): HTMLElement | undefined;\n\n /**\n * \uC790\uC2DD \uC911 \uCCAB \uBC88\uC9F8 \uD3EC\uCEE4\uC2A4 \uAC00\uB2A5 \uC694\uC18C \uAC80\uC0C9 (tabbable \uC0AC\uC6A9)\n *\n * @returns \uD3EC\uCEE4\uC2A4 \uAC00\uB2A5\uD55C \uCCAB \uBC88\uC9F8 \uC790\uC2DD \uC694\uC18C \uB610\uB294 undefined\n */\n findFirstFocusableChild(): HTMLElement | undefined;\n\n /**\n * \uC694\uC18C\uAC00 offset \uAE30\uC900 \uC694\uC18C\uC778\uC9C0 \uD655\uC778 (position: relative/absolute/fixed/sticky)\n *\n * @returns position \uC18D\uC131\uC774 relative, absolute, fixed, sticky \uC911 \uD558\uB098\uBA74 true\n */\n isOffsetElement(): boolean;\n\n /**\n * \uC694\uC18C\uAC00 \uD654\uBA74\uC5D0 \uBCF4\uC774\uB294\uC9C0 \uD655\uC778\n *\n * @remarks\n * clientRects \uC874\uC7AC \uC5EC\uBD80, visibility: hidden, opacity: 0 \uC5EC\uBD80\uB97C \uD655\uC778\uD55C\uB2E4.\n *\n * @returns \uC694\uC18C\uAC00 \uD654\uBA74\uC5D0 \uBCF4\uC774\uBA74 true\n */\n isVisible(): boolean;\n }\n}\n\nElement.prototype.findAll = function <T extends Element = Element>(selector: string): T[] {\n const trimmed = selector.trim();\n if (trimmed === \"\") return [];\n return Array.from(this.querySelectorAll<T>(trimmed));\n};\n\nElement.prototype.findFirst = function <T extends Element = Element>(selector: string): T | undefined {\n const trimmed = selector.trim();\n if (trimmed === \"\") return undefined;\n return this.querySelector<T>(trimmed) ?? undefined;\n};\n\nElement.prototype.prependChild = function <T extends Element>(child: T): T {\n return this.insertBefore(child, this.firstElementChild);\n};\n\nElement.prototype.getParents = function (): Element[] {\n const result: Element[] = [];\n let cursor = this.parentNode;\n while (cursor !== null && cursor instanceof Element) {\n result.push(cursor);\n cursor = cursor.parentNode;\n }\n return result;\n};\n\nElement.prototype.findFocusableParent = function (): HTMLElement | undefined {\n let parentEl = this.parentElement;\n while (parentEl !== null) {\n if (isFocusable(parentEl)) {\n return parentEl;\n }\n parentEl = parentEl.parentElement;\n }\n return undefined;\n};\n\nElement.prototype.findFirstFocusableChild = function (): HTMLElement | undefined {\n const walker = document.createTreeWalker(this, NodeFilter.SHOW_ELEMENT);\n let node = walker.nextNode();\n while (node !== null) {\n if (node instanceof HTMLElement && isFocusable(node)) {\n return node;\n }\n node = walker.nextNode();\n }\n return undefined;\n};\n\nElement.prototype.isOffsetElement = function (): boolean {\n return [\"relative\", \"absolute\", \"fixed\", \"sticky\"].includes(getComputedStyle(this).position);\n};\n\nElement.prototype.isVisible = function (): boolean {\n const style = getComputedStyle(this);\n return this.getClientRects().length > 0 && style.visibility !== \"hidden\" && style.opacity !== \"0\";\n};\n\n// ============================================================================\n// \uC815\uC801 \uD568\uC218 (\uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC\uC6A9 \uB610\uB294 \uC5EC\uB7EC \uC694\uC18C \uB300\uC0C1)\n// ============================================================================\n\n/**\n * \uC694\uC18C \uB0B4\uC6A9\uC744 \uD074\uB9BD\uBCF4\uB4DC\uC5D0 \uBCF5\uC0AC (copy \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC\uC5D0\uC11C \uC0AC\uC6A9)\n *\n * @param event - copy \uC774\uBCA4\uD2B8 \uAC1D\uCCB4\n */\nexport function copyElement(event: ClipboardEvent): void {\n const clipboardData = event.clipboardData;\n const target = event.target;\n if (clipboardData == null || !(target instanceof Element)) return;\n\n const firstInputEl = target.querySelector<HTMLInputElement | HTMLTextAreaElement>(\"input, textarea\");\n if (firstInputEl != null) {\n clipboardData.setData(\"text/plain\", firstInputEl.value);\n event.preventDefault();\n }\n}\n\n/**\n * \uD074\uB9BD\uBCF4\uB4DC \uB0B4\uC6A9\uC744 \uC694\uC18C\uC5D0 \uBD99\uC5EC\uB123\uAE30 (paste \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC\uC5D0\uC11C \uC0AC\uC6A9)\n *\n * @remarks\n * \uB300\uC0C1 \uC694\uC18C \uB0B4\uC758 \uCCAB \uBC88\uC9F8 input/textarea\uB97C \uCC3E\uC544 \uC804\uCCB4 \uAC12\uC744 \uD074\uB9BD\uBCF4\uB4DC \uB0B4\uC6A9\uC73C\uB85C \uAD50\uCCB4\uD55C\uB2E4.\n * \uCEE4\uC11C \uC704\uCE58\uB098 \uC120\uD0DD \uC601\uC5ED\uC744 \uACE0\uB824\uD558\uC9C0 \uC54A\uB294\uB2E4.\n *\n * @param event - paste \uC774\uBCA4\uD2B8 \uAC1D\uCCB4\n */\nexport function pasteToElement(event: ClipboardEvent): void {\n const clipboardData = event.clipboardData;\n const target = event.target;\n if (clipboardData == null || !(target instanceof Element)) return;\n\n const contentText = clipboardData.getData(\"text/plain\");\n\n const firstInputEl = target.findFirst<HTMLInputElement | HTMLTextAreaElement>(\"input, textarea\");\n if (firstInputEl !== undefined) {\n firstInputEl.value = contentText;\n firstInputEl.dispatchEvent(new Event(\"input\", { bubbles: true }));\n event.preventDefault();\n }\n}\n\n/**\n * IntersectionObserver\uB97C \uC0AC\uC6A9\uD558\uC5EC \uC694\uC18C\uB4E4\uC758 bounds \uC815\uBCF4 \uC870\uD68C\n *\n * @param els - \uB300\uC0C1 \uC694\uC18C \uBC30\uC5F4\n * @param timeout - \uD0C0\uC784\uC544\uC6C3 (\uBC00\uB9AC\uCD08, \uAE30\uBCF8: 5000)\n * @throws {TimeoutError} \uD0C0\uC784\uC544\uC6C3 \uC2DC\uAC04 \uB0B4\uC5D0 \uC751\uB2F5\uC774 \uC5C6\uC744 \uACBD\uC6B0\n */\nexport async function getBounds(els: Element[], timeout: number = 5000): Promise<ElementBounds[]> {\n // \uC911\uBCF5 \uC81C\uAC70 \uBC0F \uC785\uB825 \uC21C\uC11C\uB300\uB85C \uACB0\uACFC\uB97C \uC815\uB82C\uD558\uAE30 \uC704\uD55C \uC778\uB371\uC2A4 \uB9F5\n const indexMap = new Map(els.map((el, i) => [el, i] as const));\n if (indexMap.size === 0) {\n return [];\n }\n\n // \uC815\uB82C \uC131\uB2A5 \uCD5C\uC801\uD654\uB97C \uC704\uD55C \uC778\uB371\uC2A4 \uB9F5\n const sortIndexMap = new Map(els.map((el, i) => [el, i] as const));\n\n let observer: IntersectionObserver | undefined;\n\n try {\n return await Promise.race([\n new Promise<ElementBounds[]>((resolve) => {\n const results: ElementBounds[] = [];\n\n observer = new IntersectionObserver((entries) => {\n for (const entry of entries) {\n const target = entry.target;\n if (indexMap.has(target)) {\n indexMap.delete(target);\n results.push({\n target,\n top: entry.boundingClientRect.top,\n left: entry.boundingClientRect.left,\n width: entry.boundingClientRect.width,\n height: entry.boundingClientRect.height,\n });\n }\n }\n\n if (indexMap.size === 0) {\n observer?.disconnect();\n // \uC785\uB825 \uC21C\uC11C\uB300\uB85C \uC815\uB82C\n resolve(results.sort((a, b) => sortIndexMap.get(a.target)! - sortIndexMap.get(b.target)!));\n }\n });\n\n for (const el of indexMap.keys()) {\n observer.observe(el);\n }\n }),\n new Promise<ElementBounds[]>((_, reject) =>\n setTimeout(() => reject(new TimeoutError(undefined, `${timeout}ms \uCD08\uACFC`)), timeout),\n ),\n ]);\n } finally {\n observer?.disconnect();\n }\n}\n"],
|
|
5
4
|
"mappings": "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",
|
|
6
5
|
"names": []
|
|
7
6
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-element-ext.d.ts","sourceRoot":"","sources":["../../src/extensions/html-element-ext.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,WAAW;QACnB;;WAEG;QACH,OAAO,IAAI,IAAI,CAAC;QAEhB;;;;;;;;;;;;;;;;;;;;;WAqBG;QACH,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,GAAG;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QAE/E;;;;;;;;;;WAUG;QACH,sBAAsB,CAAC,MAAM,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,MAAM,CAAC,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAC;KAC7G;CACF"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/extensions/html-element-ext.ts"],
|
|
4
|
-
"sourcesContent": ["import { ArgumentError } from \"@simplysm/core-common\";\n\ndeclare global {\n interface HTMLElement {\n /**\n * \uAC15\uC81C \uB9AC\uD398\uC778\uD2B8 (reflow \uD2B8\uB9AC\uAC70)\n */\n repaint(): void;\n\n /**\n * \uBD80\uBAA8 \uC694\uC18C \uAE30\uC900 \uC0C1\uB300 \uC704\uCE58 \uACC4\uC0B0 (CSS \uD3EC\uC9C0\uC154\uB2DD\uC6A9)\n *\n * @remarks\n * \uC774 \uD568\uC218\uB294 \uC694\uC18C\uC758 \uC704\uCE58\uB97C \uBD80\uBAA8 \uC694\uC18C \uAE30\uC900\uC73C\uB85C \uACC4\uC0B0\uD558\uB418, `window.scrollX/Y`\uB97C \uD3EC\uD568\uD558\uC5EC\n * CSS `top`/`left` \uC18D\uC131\uC5D0 \uC9C1\uC811 \uC0AC\uC6A9\uD560 \uC218 \uC788\uB294 \uBB38\uC11C \uAE30\uC900 \uC88C\uD45C\uB97C \uBC18\uD658\uD55C\uB2E4.\n *\n * \uC8FC\uC694 \uC0AC\uC6A9 \uC0AC\uB840:\n * - \uB4DC\uB86D\uB2E4\uC6B4, \uD31D\uC5C5 \uB4F1\uC744 `document.body`\uC5D0 append \uD6C4 \uC704\uCE58 \uC9C0\uC815\n * - \uC2A4\uD06C\uB864\uB41C \uD398\uC774\uC9C0\uC5D0\uC11C\uB3C4 \uC62C\uBC14\uB974\uAC8C \uB3D9\uC791\n *\n * \uACC4\uC0B0\uC5D0 \uD3EC\uD568\uB418\uB294 \uC694\uC18C:\n * - \uBDF0\uD3EC\uD2B8 \uAE30\uC900 \uC704\uCE58 (getBoundingClientRect)\n * - \uBB38\uC11C \uC2A4\uD06C\uB864 \uC704\uCE58 (window.scrollX/Y)\n * - \uBD80\uBAA8 \uC694\uC18C \uB0B4\uBD80 \uC2A4\uD06C\uB864 (parentEl.scrollTop/Left)\n * - \uC911\uAC04 \uC694\uC18C\uB4E4\uC758 border \uB450\uAED8\n * - CSS transform \uBCC0\uD658\n *\n * @param parent - \uAE30\uC900\uC774 \uB420 \uBD80\uBAA8 \uC694\uC18C \uB610\uB294 \uC140\uB809\uD130 (\uC608: document.body, \".container\")\n * @returns CSS top/left \uC18D\uC131\uC5D0 \uC0AC\uC6A9\uD560 \uC218 \uC788\uB294 \uC88C\uD45C\n * @throws {ArgumentError} \uBD80\uBAA8 \uC694\uC18C\uB97C \uCC3E\uC744 \uC218 \uC5C6\uB294 \uACBD\uC6B0\n */\n getRelativeOffset(parent: HTMLElement | string): { top: number; left: number };\n\n /**\n * \uB300\uC0C1\uC774 offset \uC601\uC5ED(\uACE0\uC815 \uD5E4\uB354/\uACE0\uC815 \uC5F4 \uB4F1)\uC5D0 \uAC00\uB824\uC9C4 \uACBD\uC6B0, \uBCF4\uC774\uB3C4\uB85D \uC2A4\uD06C\uB864\n *\n * @remarks\n * \uC774 \uD568\uC218\uB294 \uB300\uC0C1\uC774 \uC2A4\uD06C\uB864 \uC601\uC5ED\uC758 \uC704\uCABD/\uC67C\uCABD \uACBD\uACC4\uB97C \uBC97\uC5B4\uB09C \uACBD\uC6B0\uB9CC \uCC98\uB9AC\uD55C\uB2E4.\n * \uC544\uB798\uCABD/\uC624\uB978\uCABD\uC73C\uB85C \uC2A4\uD06C\uB864\uC774 \uD544\uC694\uD55C \uACBD\uC6B0\uB294 \uBE0C\uB77C\uC6B0\uC800\uC758 \uAE30\uBCF8 \uD3EC\uCEE4\uC2A4 \uC2A4\uD06C\uB864 \uB3D9\uC791\uC5D0 \uC758\uC874\uD55C\uB2E4.\n * \uC8FC\uB85C \uACE0\uC815 \uD5E4\uB354\uB098 \uACE0\uC815 \uC5F4\uC774 \uC788\uB294 \uD14C\uC774\uBE14\uC5D0\uC11C \uD3EC\uCEE4\uC2A4 \uC774\uBCA4\uD2B8\uC640 \uD568\uAED8 \uC0AC\uC6A9\uB41C\uB2E4.\n *\n * @param target - \uB300\uC0C1\uC758 \uCEE8\uD14C\uC774\uB108 \uB0B4 \uC704\uCE58 (offsetTop, offsetLeft)\n * @param offset - \uAC00\uB824\uC9C0\uBA74 \uC548 \uB418\uB294 \uC601\uC5ED \uD06C\uAE30 (\uC608: \uACE0\uC815 \uD5E4\uB354 \uB192\uC774, \uACE0\uC815 \uC5F4 \uB108\uBE44)\n */\n scrollIntoViewIfNeeded(target: { top: number; left: number }, offset?: { top: number; left: number }): void;\n }\n}\n\nHTMLElement.prototype.repaint = function (): void {\n // offsetHeight \uC811\uADFC \uC2DC \uBE0C\uB77C\uC6B0\uC800\uB294 \uB3D9\uAE30\uC801 \uB808\uC774\uC544\uC6C3 \uACC4\uC0B0(forced synchronous layout)\uC744 \uC218\uD589\uD558\uBA70,\n // \uC774\uB85C \uC778\uD574 \uD604\uC7AC \uBC30\uCE58\uB41C \uC2A4\uD0C0\uC77C \uBCC0\uACBD\uC0AC\uD56D\uC774 \uC989\uC2DC \uC801\uC6A9\uB418\uC5B4 \uB9AC\uD398\uC778\uD2B8\uAC00 \uD2B8\uB9AC\uAC70\uB41C\uB2E4.\n void this.offsetHeight;\n};\n\nHTMLElement.prototype.getRelativeOffset = function (parent: HTMLElement | string): { top: number; left: number } {\n const parentEl = typeof parent === \"string\" ? this.closest(parent) : parent;\n\n if (!(parentEl instanceof HTMLElement)) {\n throw new ArgumentError({ parent });\n }\n\n const elementRect = this.getBoundingClientRect();\n const parentRect = parentEl.getBoundingClientRect();\n\n const scrollLeft = window.scrollX;\n const scrollTop = window.scrollY;\n\n const relativeOffset = {\n top: elementRect.top - parentRect.top + scrollTop + (parentEl.scrollTop || 0),\n left: elementRect.left - parentRect.left + scrollLeft + (parentEl.scrollLeft || 0),\n };\n\n let currentEl = this.parentElement;\n while (currentEl !== null && currentEl !== parentEl) {\n const style = getComputedStyle(currentEl);\n relativeOffset.top += parseFloat(style.borderTopWidth) || 0;\n relativeOffset.left += parseFloat(style.borderLeftWidth) || 0;\n currentEl = currentEl.parentElement;\n }\n\n const elTransform = getComputedStyle(this).transform;\n const parentTransform = getComputedStyle(parentEl).transform;\n\n if (elTransform !== \"none\" || parentTransform !== \"none\") {\n const elementMatrix = new DOMMatrix(elTransform);\n const parentMatrix = new DOMMatrix(parentTransform);\n\n if (!elementMatrix.isIdentity || !parentMatrix.isIdentity) {\n const transformedPoint = parentMatrix\n .inverse()\n .multiply(elementMatrix)\n .transformPoint(new DOMPoint(relativeOffset.left, relativeOffset.top));\n\n relativeOffset.left = transformedPoint.x;\n relativeOffset.top = transformedPoint.y;\n }\n }\n\n return relativeOffset;\n};\n\nHTMLElement.prototype.scrollIntoViewIfNeeded = function (\n target: { top: number; left: number },\n offset: { top: number; left: number } = { top: 0, left: 0 },\n): void {\n const scroll = {\n top: this.scrollTop,\n left: this.scrollLeft,\n };\n\n if (target.top - scroll.top < offset.top) {\n this.scrollTop = target.top - offset.top;\n }\n if (target.left - scroll.left < offset.left) {\n this.scrollLeft = target.left - offset.left;\n }\n};\n"],
|
|
5
4
|
"mappings": "AAAA,SAAS,qBAAqB;AAgD9B,YAAY,UAAU,UAAU,WAAkB;AAGhD,OAAK,KAAK;AACZ;AAEA,YAAY,UAAU,oBAAoB,SAAU,QAA6D;AAC/G,QAAM,WAAW,OAAO,WAAW,WAAW,KAAK,QAAQ,MAAM,IAAI;AAErE,MAAI,EAAE,oBAAoB,cAAc;AACtC,UAAM,IAAI,cAAc,EAAE,OAAO,CAAC;AAAA,EACpC;AAEA,QAAM,cAAc,KAAK,sBAAsB;AAC/C,QAAM,aAAa,SAAS,sBAAsB;AAElD,QAAM,aAAa,OAAO;AAC1B,QAAM,YAAY,OAAO;AAEzB,QAAM,iBAAiB;AAAA,IACrB,KAAK,YAAY,MAAM,WAAW,MAAM,aAAa,SAAS,aAAa;AAAA,IAC3E,MAAM,YAAY,OAAO,WAAW,OAAO,cAAc,SAAS,cAAc;AAAA,EAClF;AAEA,MAAI,YAAY,KAAK;AACrB,SAAO,cAAc,QAAQ,cAAc,UAAU;AACnD,UAAM,QAAQ,iBAAiB,SAAS;AACxC,mBAAe,OAAO,WAAW,MAAM,cAAc,KAAK;AAC1D,mBAAe,QAAQ,WAAW,MAAM,eAAe,KAAK;AAC5D,gBAAY,UAAU;AAAA,EACxB;AAEA,QAAM,cAAc,iBAAiB,IAAI,EAAE;AAC3C,QAAM,kBAAkB,iBAAiB,QAAQ,EAAE;AAEnD,MAAI,gBAAgB,UAAU,oBAAoB,QAAQ;AACxD,UAAM,gBAAgB,IAAI,UAAU,WAAW;AAC/C,UAAM,eAAe,IAAI,UAAU,eAAe;AAElD,QAAI,CAAC,cAAc,cAAc,CAAC,aAAa,YAAY;AACzD,YAAM,mBAAmB,aACtB,QAAQ,EACR,SAAS,aAAa,EACtB,eAAe,IAAI,SAAS,eAAe,MAAM,eAAe,GAAG,CAAC;AAEvE,qBAAe,OAAO,iBAAiB;AACvC,qBAAe,MAAM,iBAAiB;AAAA,IACxC;AAAA,EACF;AAEA,SAAO;AACT;AAEA,YAAY,UAAU,yBAAyB,SAC7C,QACA,SAAwC,EAAE,KAAK,GAAG,MAAM,EAAE,GACpD;AACN,QAAM,SAAS;AAAA,IACb,KAAK,KAAK;AAAA,IACV,MAAM,KAAK;AAAA,EACb;AAEA,MAAI,OAAO,MAAM,OAAO,MAAM,OAAO,KAAK;AACxC,SAAK,YAAY,OAAO,MAAM,OAAO;AAAA,EACvC;AACA,MAAI,OAAO,OAAO,OAAO,OAAO,OAAO,MAAM;AAC3C,SAAK,aAAa,OAAO,OAAO,OAAO;AAAA,EACzC;AACF;",
|
|
6
5
|
"names": []
|
|
7
6
|
}
|
|
@@ -2,6 +2,7 @@ import "./extensions/element-ext";
|
|
|
2
2
|
import "./extensions/html-element-ext";
|
|
3
3
|
export * from "./extensions/element-ext";
|
|
4
4
|
export * from "./extensions/html-element-ext";
|
|
5
|
-
export * from "./utils/blob";
|
|
6
5
|
export * from "./utils/download";
|
|
6
|
+
export * from "./utils/fetch";
|
|
7
|
+
export * from "./utils/file-dialog";
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,0BAA0B,CAAC;AAClC,OAAO,+BAA+B,CAAC;AAGvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import "./extensions/element-ext";
|
|
2
|
-
import "./extensions/html-element-ext";
|
|
3
|
-
export * from "./extensions/element-ext";
|
|
4
|
-
export * from "./extensions/html-element-ext";
|
|
5
|
-
export * from "./utils/
|
|
6
|
-
export * from "./utils/
|
|
1
|
+
import "./extensions/element-ext.js";
|
|
2
|
+
import "./extensions/html-element-ext.js";
|
|
3
|
+
export * from "./extensions/element-ext.js";
|
|
4
|
+
export * from "./extensions/html-element-ext.js";
|
|
5
|
+
export * from "./utils/download.js";
|
|
6
|
+
export * from "./utils/fetch.js";
|
|
7
|
+
export * from "./utils/file-dialog.js";
|
|
7
8
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"
|
|
5
|
-
"mappings": "AAGA,OAAO;AACP,OAAO;AAGP,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
4
|
+
"mappings": "AAGA,OAAO;AACP,OAAO;AAGP,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
6
5
|
"names": []
|
|
7
6
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../src/utils/download.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAU/D"}
|
package/dist/utils/download.js
CHANGED
|
@@ -1,47 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const response = await fetch(url);
|
|
4
|
-
if (!response.ok) {
|
|
5
|
-
throw new Error(`Download failed: ${response.status} ${response.statusText}`);
|
|
6
|
-
}
|
|
7
|
-
const contentLength = Number(response.headers.get("Content-Length") ?? 0);
|
|
8
|
-
const reader = (_a = response.body) == null ? void 0 : _a.getReader();
|
|
9
|
-
if (!reader) {
|
|
10
|
-
throw new Error("Response body is not readable");
|
|
11
|
-
}
|
|
1
|
+
function downloadBlob(blob, fileName) {
|
|
2
|
+
const url = URL.createObjectURL(blob);
|
|
12
3
|
try {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const { done, value } = await reader.read();
|
|
18
|
-
if (done) break;
|
|
19
|
-
result2.set(value, receivedLength2);
|
|
20
|
-
receivedLength2 += value.length;
|
|
21
|
-
(_b = options == null ? void 0 : options.onProgress) == null ? void 0 : _b.call(options, { receivedLength: receivedLength2, contentLength });
|
|
22
|
-
}
|
|
23
|
-
return result2;
|
|
24
|
-
}
|
|
25
|
-
const chunks = [];
|
|
26
|
-
let receivedLength = 0;
|
|
27
|
-
while (true) {
|
|
28
|
-
const { done, value } = await reader.read();
|
|
29
|
-
if (done) break;
|
|
30
|
-
chunks.push(value);
|
|
31
|
-
receivedLength += value.length;
|
|
32
|
-
}
|
|
33
|
-
const result = new Uint8Array(receivedLength);
|
|
34
|
-
let position = 0;
|
|
35
|
-
for (const chunk of chunks) {
|
|
36
|
-
result.set(chunk, position);
|
|
37
|
-
position += chunk.length;
|
|
38
|
-
}
|
|
39
|
-
return result;
|
|
4
|
+
const link = document.createElement("a");
|
|
5
|
+
link.href = url;
|
|
6
|
+
link.download = fileName;
|
|
7
|
+
link.click();
|
|
40
8
|
} finally {
|
|
41
|
-
|
|
9
|
+
setTimeout(() => URL.revokeObjectURL(url), 1e3);
|
|
42
10
|
}
|
|
43
11
|
}
|
|
44
12
|
export {
|
|
45
|
-
|
|
13
|
+
downloadBlob
|
|
46
14
|
};
|
|
47
15
|
//# sourceMappingURL=download.js.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/download.ts"],
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"names": ["result", "receivedLength"]
|
|
4
|
+
"mappings": "AAMO,SAAS,aAAa,MAAY,UAAwB;AAC/D,QAAM,MAAM,IAAI,gBAAgB,IAAI;AACpC,MAAI;AACF,UAAM,OAAO,SAAS,cAAc,GAAG;AACvC,SAAK,OAAO;AACZ,SAAK,WAAW;AAChB,SAAK,MAAM;AAAA,EACb,UAAE;AACA,eAAW,MAAM,IAAI,gBAAgB,GAAG,GAAG,GAAI;AAAA,EACjD;AACF;",
|
|
5
|
+
"names": []
|
|
7
6
|
}
|
|
@@ -5,7 +5,7 @@ export interface DownloadProgress {
|
|
|
5
5
|
/**
|
|
6
6
|
* URL에서 바이너리 데이터 다운로드 (진행률 콜백 지원)
|
|
7
7
|
*/
|
|
8
|
-
export declare function
|
|
8
|
+
export declare function fetchUrlBytes(url: string, options?: {
|
|
9
9
|
onProgress?: (progress: DownloadProgress) => void;
|
|
10
10
|
}): Promise<Uint8Array>;
|
|
11
|
-
//# sourceMappingURL=
|
|
11
|
+
//# sourceMappingURL=fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,CAAA;CAAE,GAC9D,OAAO,CAAC,UAAU,CAAC,CAsDrB"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
async function fetchUrlBytes(url, options) {
|
|
2
|
+
var _a, _b;
|
|
3
|
+
const response = await fetch(url);
|
|
4
|
+
if (!response.ok) {
|
|
5
|
+
throw new Error(`Download failed: ${response.status} ${response.statusText}`);
|
|
6
|
+
}
|
|
7
|
+
const contentLength = Number(response.headers.get("Content-Length") ?? 0);
|
|
8
|
+
const reader = (_a = response.body) == null ? void 0 : _a.getReader();
|
|
9
|
+
if (!reader) {
|
|
10
|
+
throw new Error("Response body is not readable");
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
if (contentLength > 0) {
|
|
14
|
+
const result2 = new Uint8Array(contentLength);
|
|
15
|
+
let receivedLength2 = 0;
|
|
16
|
+
while (true) {
|
|
17
|
+
const { done, value } = await reader.read();
|
|
18
|
+
if (done) break;
|
|
19
|
+
result2.set(value, receivedLength2);
|
|
20
|
+
receivedLength2 += value.length;
|
|
21
|
+
(_b = options == null ? void 0 : options.onProgress) == null ? void 0 : _b.call(options, { receivedLength: receivedLength2, contentLength });
|
|
22
|
+
}
|
|
23
|
+
return result2;
|
|
24
|
+
}
|
|
25
|
+
const chunks = [];
|
|
26
|
+
let receivedLength = 0;
|
|
27
|
+
while (true) {
|
|
28
|
+
const { done, value } = await reader.read();
|
|
29
|
+
if (done) break;
|
|
30
|
+
chunks.push(value);
|
|
31
|
+
receivedLength += value.length;
|
|
32
|
+
}
|
|
33
|
+
const result = new Uint8Array(receivedLength);
|
|
34
|
+
let position = 0;
|
|
35
|
+
for (const chunk of chunks) {
|
|
36
|
+
result.set(chunk, position);
|
|
37
|
+
position += chunk.length;
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
} finally {
|
|
41
|
+
reader.releaseLock();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
fetchUrlBytes
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=fetch.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/fetch.ts"],
|
|
4
|
+
"mappings": "AAQA,eAAsB,cACpB,KACA,SACqB;AAXvB;AAYE,QAAM,WAAW,MAAM,MAAM,GAAG;AAChC,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI,MAAM,oBAAoB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,EAC9E;AAEA,QAAM,gBAAgB,OAAO,SAAS,QAAQ,IAAI,gBAAgB,KAAK,CAAC;AACxE,QAAM,UAAS,cAAS,SAAT,mBAAe;AAC9B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AAEA,MAAI;AAEF,QAAI,gBAAgB,GAAG;AACrB,YAAMA,UAAS,IAAI,WAAW,aAAa;AAC3C,UAAIC,kBAAiB;AAErB,aAAO,MAAM;AACX,cAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,YAAI,KAAM;AAEV,QAAAD,QAAO,IAAI,OAAOC,eAAc;AAChC,QAAAA,mBAAkB,MAAM;AACxB,iDAAS,eAAT,iCAAsB,EAAE,gBAAAA,iBAAgB,cAAc;AAAA,MACxD;AAEA,aAAOD;AAAA,IACT;AAGA,UAAM,SAAuB,CAAC;AAC9B,QAAI,iBAAiB;AAErB,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AAEV,aAAO,KAAK,KAAK;AACjB,wBAAkB,MAAM;AAAA,IAC1B;AAGA,UAAM,SAAS,IAAI,WAAW,cAAc;AAC5C,QAAI,WAAW;AACf,eAAW,SAAS,QAAQ;AAC1B,aAAO,IAAI,OAAO,QAAQ;AAC1B,kBAAY,MAAM;AAAA,IACpB;AAEA,WAAO;AAAA,EACT,UAAE;AACA,WAAO,YAAY;AAAA,EACrB;AACF;",
|
|
5
|
+
"names": ["result", "receivedLength"]
|
|
6
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-dialog.d.ts","sourceRoot":"","sources":["../../src/utils/file-dialog.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,SAAS,CAAC,CAa7G"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
function openFileDialog(options) {
|
|
2
|
+
return new Promise((resolve) => {
|
|
3
|
+
const input = document.createElement("input");
|
|
4
|
+
input.type = "file";
|
|
5
|
+
input.multiple = (options == null ? void 0 : options.multiple) ?? false;
|
|
6
|
+
if ((options == null ? void 0 : options.accept) != null) {
|
|
7
|
+
input.accept = options.accept;
|
|
8
|
+
}
|
|
9
|
+
input.onchange = () => {
|
|
10
|
+
resolve(input.files != null && input.files.length > 0 ? [...input.files] : void 0);
|
|
11
|
+
};
|
|
12
|
+
input.click();
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
openFileDialog
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=file-dialog.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/file-dialog.ts"],
|
|
4
|
+
"mappings": "AAGO,SAAS,eAAe,SAAgF;AAC7G,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,OAAO;AACb,UAAM,YAAW,mCAAS,aAAY;AACtC,SAAI,mCAAS,WAAU,MAAM;AAC3B,YAAM,SAAS,QAAQ;AAAA,IACzB;AACA,UAAM,WAAW,MAAM;AACrB,cAAQ,MAAM,SAAS,QAAQ,MAAM,MAAM,SAAS,IAAI,CAAC,GAAG,MAAM,KAAK,IAAI,MAAS;AAAA,IACtF;AACA,UAAM,MAAM;AAAA,EACd,CAAC;AACH;",
|
|
5
|
+
"names": []
|
|
6
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/core-browser",
|
|
3
|
-
"version": "13.0.
|
|
3
|
+
"version": "13.0.2",
|
|
4
4
|
"description": "심플리즘 패키지 - 코어 모듈 (browser)",
|
|
5
5
|
"author": "김석래",
|
|
6
6
|
"repository": {
|
|
@@ -13,17 +13,18 @@
|
|
|
13
13
|
"main": "./dist/index.js",
|
|
14
14
|
"types": "./dist/index.d.ts",
|
|
15
15
|
"files": [
|
|
16
|
-
"dist"
|
|
16
|
+
"dist",
|
|
17
|
+
"src"
|
|
17
18
|
],
|
|
18
19
|
"sideEffects": [
|
|
19
20
|
"./dist/extensions/element-ext.js",
|
|
20
21
|
"./dist/extensions/html-element-ext.js"
|
|
21
22
|
],
|
|
22
23
|
"dependencies": {
|
|
23
|
-
"
|
|
24
|
-
"
|
|
24
|
+
"tabbable": "^6.4.0",
|
|
25
|
+
"@simplysm/core-common": "13.0.2"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"happy-dom": "^20.6.1"
|
|
28
29
|
}
|
|
29
|
-
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { isFocusable } from "tabbable";
|
|
2
|
+
import { TimeoutError } from "@simplysm/core-common";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 요소 bounds 정보 타입
|
|
6
|
+
*/
|
|
7
|
+
export interface ElementBounds {
|
|
8
|
+
/** 측정 대상 요소 */
|
|
9
|
+
target: Element;
|
|
10
|
+
/** 뷰포트 기준 상단 위치 */
|
|
11
|
+
top: number;
|
|
12
|
+
/** 뷰포트 기준 왼쪽 위치 */
|
|
13
|
+
left: number;
|
|
14
|
+
/** 요소 너비 */
|
|
15
|
+
width: number;
|
|
16
|
+
/** 요소 높이 */
|
|
17
|
+
height: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
declare global {
|
|
21
|
+
interface Element {
|
|
22
|
+
/**
|
|
23
|
+
* 셀렉터로 하위 요소 전체 검색
|
|
24
|
+
*
|
|
25
|
+
* @param selector - CSS 셀렉터
|
|
26
|
+
* @returns 매칭된 요소 배열 (빈 셀렉터는 빈 배열 반환)
|
|
27
|
+
*/
|
|
28
|
+
findAll<T extends Element = Element>(selector: string): T[];
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 셀렉터로 첫 번째 매칭 요소 검색
|
|
32
|
+
*
|
|
33
|
+
* @param selector - CSS 셀렉터
|
|
34
|
+
* @returns 첫 번째 매칭 요소 또는 undefined (빈 셀렉터는 undefined 반환)
|
|
35
|
+
*/
|
|
36
|
+
findFirst<T extends Element = Element>(selector: string): T | undefined;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 요소를 첫 번째 자식으로 삽입
|
|
40
|
+
*
|
|
41
|
+
* @param child - 삽입할 자식 요소
|
|
42
|
+
* @returns 삽입된 자식 요소
|
|
43
|
+
*/
|
|
44
|
+
prependChild<T extends Element>(child: T): T;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 모든 부모 요소 목록 반환 (가까운 순서)
|
|
48
|
+
*
|
|
49
|
+
* @returns 부모 요소 배열 (가까운 부모부터 순서대로)
|
|
50
|
+
*/
|
|
51
|
+
getParents(): Element[];
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 부모 중 첫 번째 포커스 가능 요소 검색 (tabbable 사용)
|
|
55
|
+
*
|
|
56
|
+
* @returns 포커스 가능한 첫 번째 부모 요소 또는 undefined
|
|
57
|
+
*/
|
|
58
|
+
findFocusableParent(): HTMLElement | undefined;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 자식 중 첫 번째 포커스 가능 요소 검색 (tabbable 사용)
|
|
62
|
+
*
|
|
63
|
+
* @returns 포커스 가능한 첫 번째 자식 요소 또는 undefined
|
|
64
|
+
*/
|
|
65
|
+
findFirstFocusableChild(): HTMLElement | undefined;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 요소가 offset 기준 요소인지 확인 (position: relative/absolute/fixed/sticky)
|
|
69
|
+
*
|
|
70
|
+
* @returns position 속성이 relative, absolute, fixed, sticky 중 하나면 true
|
|
71
|
+
*/
|
|
72
|
+
isOffsetElement(): boolean;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 요소가 화면에 보이는지 확인
|
|
76
|
+
*
|
|
77
|
+
* @remarks
|
|
78
|
+
* clientRects 존재 여부, visibility: hidden, opacity: 0 여부를 확인한다.
|
|
79
|
+
*
|
|
80
|
+
* @returns 요소가 화면에 보이면 true
|
|
81
|
+
*/
|
|
82
|
+
isVisible(): boolean;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
Element.prototype.findAll = function <T extends Element = Element>(selector: string): T[] {
|
|
87
|
+
const trimmed = selector.trim();
|
|
88
|
+
if (trimmed === "") return [];
|
|
89
|
+
return Array.from(this.querySelectorAll<T>(trimmed));
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
Element.prototype.findFirst = function <T extends Element = Element>(selector: string): T | undefined {
|
|
93
|
+
const trimmed = selector.trim();
|
|
94
|
+
if (trimmed === "") return undefined;
|
|
95
|
+
return this.querySelector<T>(trimmed) ?? undefined;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
Element.prototype.prependChild = function <T extends Element>(child: T): T {
|
|
99
|
+
return this.insertBefore(child, this.firstElementChild);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
Element.prototype.getParents = function (): Element[] {
|
|
103
|
+
const result: Element[] = [];
|
|
104
|
+
let cursor = this.parentNode;
|
|
105
|
+
while (cursor !== null && cursor instanceof Element) {
|
|
106
|
+
result.push(cursor);
|
|
107
|
+
cursor = cursor.parentNode;
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
Element.prototype.findFocusableParent = function (): HTMLElement | undefined {
|
|
113
|
+
let parentEl = this.parentElement;
|
|
114
|
+
while (parentEl !== null) {
|
|
115
|
+
if (isFocusable(parentEl)) {
|
|
116
|
+
return parentEl;
|
|
117
|
+
}
|
|
118
|
+
parentEl = parentEl.parentElement;
|
|
119
|
+
}
|
|
120
|
+
return undefined;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
Element.prototype.findFirstFocusableChild = function (): HTMLElement | undefined {
|
|
124
|
+
const walker = document.createTreeWalker(this, NodeFilter.SHOW_ELEMENT);
|
|
125
|
+
let node = walker.nextNode();
|
|
126
|
+
while (node !== null) {
|
|
127
|
+
if (node instanceof HTMLElement && isFocusable(node)) {
|
|
128
|
+
return node;
|
|
129
|
+
}
|
|
130
|
+
node = walker.nextNode();
|
|
131
|
+
}
|
|
132
|
+
return undefined;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
Element.prototype.isOffsetElement = function (): boolean {
|
|
136
|
+
return ["relative", "absolute", "fixed", "sticky"].includes(getComputedStyle(this).position);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
Element.prototype.isVisible = function (): boolean {
|
|
140
|
+
const style = getComputedStyle(this);
|
|
141
|
+
return this.getClientRects().length > 0 && style.visibility !== "hidden" && style.opacity !== "0";
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// ============================================================================
|
|
145
|
+
// 정적 함수 (이벤트 핸들러용 또는 여러 요소 대상)
|
|
146
|
+
// ============================================================================
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 요소 내용을 클립보드에 복사 (copy 이벤트 핸들러에서 사용)
|
|
150
|
+
*
|
|
151
|
+
* @param event - copy 이벤트 객체
|
|
152
|
+
*/
|
|
153
|
+
export function copyElement(event: ClipboardEvent): void {
|
|
154
|
+
const clipboardData = event.clipboardData;
|
|
155
|
+
const target = event.target;
|
|
156
|
+
if (clipboardData == null || !(target instanceof Element)) return;
|
|
157
|
+
|
|
158
|
+
const firstInputEl = target.querySelector<HTMLInputElement | HTMLTextAreaElement>("input, textarea");
|
|
159
|
+
if (firstInputEl != null) {
|
|
160
|
+
clipboardData.setData("text/plain", firstInputEl.value);
|
|
161
|
+
event.preventDefault();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* 클립보드 내용을 요소에 붙여넣기 (paste 이벤트 핸들러에서 사용)
|
|
167
|
+
*
|
|
168
|
+
* @remarks
|
|
169
|
+
* 대상 요소 내의 첫 번째 input/textarea를 찾아 전체 값을 클립보드 내용으로 교체한다.
|
|
170
|
+
* 커서 위치나 선택 영역을 고려하지 않는다.
|
|
171
|
+
*
|
|
172
|
+
* @param event - paste 이벤트 객체
|
|
173
|
+
*/
|
|
174
|
+
export function pasteToElement(event: ClipboardEvent): void {
|
|
175
|
+
const clipboardData = event.clipboardData;
|
|
176
|
+
const target = event.target;
|
|
177
|
+
if (clipboardData == null || !(target instanceof Element)) return;
|
|
178
|
+
|
|
179
|
+
const contentText = clipboardData.getData("text/plain");
|
|
180
|
+
|
|
181
|
+
const firstInputEl = target.findFirst<HTMLInputElement | HTMLTextAreaElement>("input, textarea");
|
|
182
|
+
if (firstInputEl !== undefined) {
|
|
183
|
+
firstInputEl.value = contentText;
|
|
184
|
+
firstInputEl.dispatchEvent(new Event("input", { bubbles: true }));
|
|
185
|
+
event.preventDefault();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* IntersectionObserver를 사용하여 요소들의 bounds 정보 조회
|
|
191
|
+
*
|
|
192
|
+
* @param els - 대상 요소 배열
|
|
193
|
+
* @param timeout - 타임아웃 (밀리초, 기본: 5000)
|
|
194
|
+
* @throws {TimeoutError} 타임아웃 시간 내에 응답이 없을 경우
|
|
195
|
+
*/
|
|
196
|
+
export async function getBounds(els: Element[], timeout: number = 5000): Promise<ElementBounds[]> {
|
|
197
|
+
// 중복 제거 및 입력 순서대로 결과를 정렬하기 위한 인덱스 맵
|
|
198
|
+
const indexMap = new Map(els.map((el, i) => [el, i] as const));
|
|
199
|
+
if (indexMap.size === 0) {
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// 정렬 성능 최적화를 위한 인덱스 맵
|
|
204
|
+
const sortIndexMap = new Map(els.map((el, i) => [el, i] as const));
|
|
205
|
+
|
|
206
|
+
let observer: IntersectionObserver | undefined;
|
|
207
|
+
|
|
208
|
+
try {
|
|
209
|
+
return await Promise.race([
|
|
210
|
+
new Promise<ElementBounds[]>((resolve) => {
|
|
211
|
+
const results: ElementBounds[] = [];
|
|
212
|
+
|
|
213
|
+
observer = new IntersectionObserver((entries) => {
|
|
214
|
+
for (const entry of entries) {
|
|
215
|
+
const target = entry.target;
|
|
216
|
+
if (indexMap.has(target)) {
|
|
217
|
+
indexMap.delete(target);
|
|
218
|
+
results.push({
|
|
219
|
+
target,
|
|
220
|
+
top: entry.boundingClientRect.top,
|
|
221
|
+
left: entry.boundingClientRect.left,
|
|
222
|
+
width: entry.boundingClientRect.width,
|
|
223
|
+
height: entry.boundingClientRect.height,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (indexMap.size === 0) {
|
|
229
|
+
observer?.disconnect();
|
|
230
|
+
// 입력 순서대로 정렬
|
|
231
|
+
resolve(results.sort((a, b) => sortIndexMap.get(a.target)! - sortIndexMap.get(b.target)!));
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
for (const el of indexMap.keys()) {
|
|
236
|
+
observer.observe(el);
|
|
237
|
+
}
|
|
238
|
+
}),
|
|
239
|
+
new Promise<ElementBounds[]>((_, reject) =>
|
|
240
|
+
setTimeout(() => reject(new TimeoutError(undefined, `${timeout}ms 초과`)), timeout),
|
|
241
|
+
),
|
|
242
|
+
]);
|
|
243
|
+
} finally {
|
|
244
|
+
observer?.disconnect();
|
|
245
|
+
}
|
|
246
|
+
}
|