@simplysm/core-browser 13.0.0-beta.1

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.
Files changed (98) hide show
  1. package/.cache/typecheck-browser.tsbuildinfo +1 -0
  2. package/.cache/typecheck-tests-browser.tsbuildinfo +1 -0
  3. package/README.md +221 -0
  4. package/dist/core-browser/src/extensions/element-ext.d.ts +98 -0
  5. package/dist/core-browser/src/extensions/element-ext.d.ts.map +1 -0
  6. package/dist/core-browser/src/extensions/html-element-ext.d.ts +54 -0
  7. package/dist/core-browser/src/extensions/html-element-ext.d.ts.map +1 -0
  8. package/dist/core-browser/src/index.d.ts +7 -0
  9. package/dist/core-browser/src/index.d.ts.map +1 -0
  10. package/dist/core-browser/src/utils/blob.d.ts +10 -0
  11. package/dist/core-browser/src/utils/blob.d.ts.map +1 -0
  12. package/dist/core-browser/src/utils/download.d.ts +11 -0
  13. package/dist/core-browser/src/utils/download.d.ts.map +1 -0
  14. package/dist/core-common/src/common.types.d.ts +74 -0
  15. package/dist/core-common/src/common.types.d.ts.map +1 -0
  16. package/dist/core-common/src/env.d.ts +6 -0
  17. package/dist/core-common/src/env.d.ts.map +1 -0
  18. package/dist/core-common/src/errors/argument-error.d.ts +25 -0
  19. package/dist/core-common/src/errors/argument-error.d.ts.map +1 -0
  20. package/dist/core-common/src/errors/not-implemented-error.d.ts +29 -0
  21. package/dist/core-common/src/errors/not-implemented-error.d.ts.map +1 -0
  22. package/dist/core-common/src/errors/sd-error.d.ts +27 -0
  23. package/dist/core-common/src/errors/sd-error.d.ts.map +1 -0
  24. package/dist/core-common/src/errors/timeout-error.d.ts +31 -0
  25. package/dist/core-common/src/errors/timeout-error.d.ts.map +1 -0
  26. package/dist/core-common/src/extensions/arr-ext.d.ts +15 -0
  27. package/dist/core-common/src/extensions/arr-ext.d.ts.map +1 -0
  28. package/dist/core-common/src/extensions/arr-ext.helpers.d.ts +19 -0
  29. package/dist/core-common/src/extensions/arr-ext.helpers.d.ts.map +1 -0
  30. package/dist/core-common/src/extensions/arr-ext.types.d.ts +215 -0
  31. package/dist/core-common/src/extensions/arr-ext.types.d.ts.map +1 -0
  32. package/dist/core-common/src/extensions/map-ext.d.ts +57 -0
  33. package/dist/core-common/src/extensions/map-ext.d.ts.map +1 -0
  34. package/dist/core-common/src/extensions/set-ext.d.ts +36 -0
  35. package/dist/core-common/src/extensions/set-ext.d.ts.map +1 -0
  36. package/dist/core-common/src/features/debounce-queue.d.ts +53 -0
  37. package/dist/core-common/src/features/debounce-queue.d.ts.map +1 -0
  38. package/dist/core-common/src/features/event-emitter.d.ts +66 -0
  39. package/dist/core-common/src/features/event-emitter.d.ts.map +1 -0
  40. package/dist/core-common/src/features/serial-queue.d.ts +47 -0
  41. package/dist/core-common/src/features/serial-queue.d.ts.map +1 -0
  42. package/dist/core-common/src/index.d.ts +32 -0
  43. package/dist/core-common/src/index.d.ts.map +1 -0
  44. package/dist/core-common/src/types/date-only.d.ts +152 -0
  45. package/dist/core-common/src/types/date-only.d.ts.map +1 -0
  46. package/dist/core-common/src/types/date-time.d.ts +96 -0
  47. package/dist/core-common/src/types/date-time.d.ts.map +1 -0
  48. package/dist/core-common/src/types/lazy-gc-map.d.ts +80 -0
  49. package/dist/core-common/src/types/lazy-gc-map.d.ts.map +1 -0
  50. package/dist/core-common/src/types/time.d.ts +68 -0
  51. package/dist/core-common/src/types/time.d.ts.map +1 -0
  52. package/dist/core-common/src/types/uuid.d.ts +35 -0
  53. package/dist/core-common/src/types/uuid.d.ts.map +1 -0
  54. package/dist/core-common/src/utils/bytes.d.ts +51 -0
  55. package/dist/core-common/src/utils/bytes.d.ts.map +1 -0
  56. package/dist/core-common/src/utils/date-format.d.ts +90 -0
  57. package/dist/core-common/src/utils/date-format.d.ts.map +1 -0
  58. package/dist/core-common/src/utils/json.d.ts +34 -0
  59. package/dist/core-common/src/utils/json.d.ts.map +1 -0
  60. package/dist/core-common/src/utils/num.d.ts +60 -0
  61. package/dist/core-common/src/utils/num.d.ts.map +1 -0
  62. package/dist/core-common/src/utils/obj.d.ts +258 -0
  63. package/dist/core-common/src/utils/obj.d.ts.map +1 -0
  64. package/dist/core-common/src/utils/path.d.ts +23 -0
  65. package/dist/core-common/src/utils/path.d.ts.map +1 -0
  66. package/dist/core-common/src/utils/primitive.d.ts +18 -0
  67. package/dist/core-common/src/utils/primitive.d.ts.map +1 -0
  68. package/dist/core-common/src/utils/str.d.ts +103 -0
  69. package/dist/core-common/src/utils/str.d.ts.map +1 -0
  70. package/dist/core-common/src/utils/template-strings.d.ts +84 -0
  71. package/dist/core-common/src/utils/template-strings.d.ts.map +1 -0
  72. package/dist/core-common/src/utils/transferable.d.ts +47 -0
  73. package/dist/core-common/src/utils/transferable.d.ts.map +1 -0
  74. package/dist/core-common/src/utils/wait.d.ts +19 -0
  75. package/dist/core-common/src/utils/wait.d.ts.map +1 -0
  76. package/dist/core-common/src/utils/xml.d.ts +36 -0
  77. package/dist/core-common/src/utils/xml.d.ts.map +1 -0
  78. package/dist/core-common/src/zip/sd-zip.d.ts +80 -0
  79. package/dist/core-common/src/zip/sd-zip.d.ts.map +1 -0
  80. package/dist/extensions/element-ext.js +122 -0
  81. package/dist/extensions/element-ext.js.map +7 -0
  82. package/dist/extensions/html-element-ext.js +50 -0
  83. package/dist/extensions/html-element-ext.js.map +7 -0
  84. package/dist/index.js +7 -0
  85. package/dist/index.js.map +7 -0
  86. package/dist/utils/blob.js +19 -0
  87. package/dist/utils/blob.js.map +7 -0
  88. package/dist/utils/download.js +47 -0
  89. package/dist/utils/download.js.map +7 -0
  90. package/package.json +26 -0
  91. package/src/extensions/element-ext.ts +246 -0
  92. package/src/extensions/html-element-ext.ts +117 -0
  93. package/src/index.ts +11 -0
  94. package/src/utils/blob.ts +19 -0
  95. package/src/utils/download.ts +66 -0
  96. package/tests/extensions/element-ext.spec.ts +729 -0
  97. package/tests/extensions/html-element-ext.spec.ts +190 -0
  98. package/tests/utils/blob.spec.ts +68 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../../../../core-common/src/utils/path.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAKtD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAMnE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIpD"}
@@ -0,0 +1,18 @@
1
+ import type { PrimitiveTypeMap, PrimitiveTypeStr } from "../common.types";
2
+ /**
3
+ * 값에서 PrimitiveTypeStr 추론
4
+ *
5
+ * 런타임에서 값의 타입을 검사하여 해당하는 PrimitiveTypeStr을 반환합니다.
6
+ *
7
+ * @param value 타입을 추론할 값
8
+ * @returns 값에 해당하는 PrimitiveTypeStr
9
+ * @throws ArgumentError 지원하지 않는 타입인 경우
10
+ *
11
+ * @example
12
+ * getPrimitiveTypeStr("hello") // "string"
13
+ * getPrimitiveTypeStr(123) // "number"
14
+ * getPrimitiveTypeStr(new DateTime()) // "DateTime"
15
+ * getPrimitiveTypeStr(new Uint8Array()) // "Bytes"
16
+ */
17
+ export declare function getPrimitiveTypeStr(value: PrimitiveTypeMap[PrimitiveTypeStr]): PrimitiveTypeStr;
18
+ //# sourceMappingURL=primitive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitive.d.ts","sourceRoot":"","sources":["../../../../../core-common/src/utils/primitive.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE1E;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,gBAAgB,CAU/F"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * 문자열 유틸리티 함수
3
+ */
4
+ /**
5
+ * 한글 조사를 받침에 따라 적절히 반환
6
+ * @param text 텍스트
7
+ * @param type 조사 타입
8
+ * - `"을"`: 을/를
9
+ * - `"은"`: 은/는
10
+ * - `"이"`: 이/가
11
+ * - `"와"`: 과/와
12
+ * - `"랑"`: 이랑/랑
13
+ * - `"로"`: 으로/로
14
+ * - `"라"`: 이라/라
15
+ *
16
+ * @example
17
+ * getSuffix("사과", "을") // "를"
18
+ * getSuffix("책", "이") // "이"
19
+ */
20
+ export declare function strGetSuffix(text: string, type: "을" | "은" | "이" | "와" | "랑" | "로" | "라"): string;
21
+ /**
22
+ * 전각(Full-width) 문자를 반각(Half-width) 문자로 변환
23
+ *
24
+ * 변환 대상:
25
+ * - 전각 영문 대문자 (A-Z → A-Z)
26
+ * - 전각 영문 소문자 (a-z → a-z)
27
+ * - 전각 숫자 (0-9 → 0-9)
28
+ * - 전각 공백 (  → 일반 공백)
29
+ * - 전각 괄호 (() → ())
30
+ *
31
+ * @example
32
+ * replaceSpecialDefaultChar("A123") // "A123"
33
+ * replaceSpecialDefaultChar("(株)") // "(株)"
34
+ */
35
+ export declare function strReplaceFullWidth(str: string): string;
36
+ /**
37
+ * PascalCase로 변환
38
+ * @example "hello-world" → "HelloWorld"
39
+ * @example "hello_world" → "HelloWorld"
40
+ * @example "hello.world" → "HelloWorld"
41
+ */
42
+ export declare function strToPascalCase(str: string): string;
43
+ /**
44
+ * camelCase로 변환
45
+ * @example "hello-world" → "helloWorld"
46
+ * @example "hello_world" → "helloWorld"
47
+ * @example "HelloWorld" → "helloWorld"
48
+ */
49
+ export declare function strToCamelCase(str: string): string;
50
+ /**
51
+ * kebab-case로 변환
52
+ *
53
+ * @example "HelloWorld" → "hello-world"
54
+ * @example "helloWorld" → "hello-world"
55
+ * @example "hello_world" → "hello_world" (소문자만 있으면 변환 안됨)
56
+ * @example "Hello_World" → "hello-_world" (기존 분리자는 유지됨)
57
+ * @example "Hello-World" → "hello--world" (기존 분리자는 유지됨)
58
+ * @example "XMLParser" → "x-m-l-parser" (연속된 대문자는 각각 분리됨)
59
+ */
60
+ export declare function strToKebabCase(str: string): string;
61
+ /**
62
+ * snake_case로 변환
63
+ *
64
+ * @example "HelloWorld" → "hello_world"
65
+ * @example "helloWorld" → "hello_world"
66
+ * @example "hello-world" → "hello-world" (소문자만 있으면 변환 안됨)
67
+ * @example "Hello-World" → "hello_-world" (기존 분리자는 유지됨)
68
+ * @example "Hello_World" → "hello__world" (기존 분리자는 유지됨)
69
+ * @example "XMLParser" → "x_m_l_parser" (연속된 대문자는 각각 분리됨)
70
+ */
71
+ export declare function strToSnakeCase(str: string): string;
72
+ /**
73
+ * undefined 또는 빈 문자열 여부 체크 (타입 가드)
74
+ *
75
+ * @param str 체크할 문자열
76
+ * @returns undefined, null, 빈 문자열이면 true
77
+ *
78
+ * @example
79
+ * const name: string | undefined = getValue();
80
+ * if (strIsNullOrEmpty(name)) {
81
+ * // name: "" | undefined
82
+ * console.log("이름이 비어있습니다");
83
+ * } else {
84
+ * // name: string (비어있지 않은 문자열)
85
+ * console.log(`이름: ${name}`);
86
+ * }
87
+ */
88
+ export declare function strIsNullOrEmpty(str: string | undefined): str is "" | undefined;
89
+ /**
90
+ * 문자열 특정 위치에 삽입
91
+ *
92
+ * @param str 원본 문자열
93
+ * @param index 삽입할 위치 (0부터 시작)
94
+ * @param insertString 삽입할 문자열
95
+ * @returns 삽입된 새 문자열
96
+ *
97
+ * @example
98
+ * strInsert("Hello World", 5, ","); // "Hello, World"
99
+ * strInsert("abc", 0, "X"); // "Xabc"
100
+ * strInsert("abc", 3, "X"); // "abcX"
101
+ */
102
+ export declare function strInsert(str: string, index: number, insertString: string): string;
103
+ //# sourceMappingURL=str.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"str.d.ts","sourceRoot":"","sources":["../../../../../core-common/src/utils/str.ts"],"names":[],"mappings":"AAAA;;GAEG;AAeH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,MAAM,CAyBhG;AA8ED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD;AAMD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAElD;AAUD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,GAAG,IAAI,EAAE,GAAG,SAAS,CAE/E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAElF"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * 템플릿 문자열 태그 함수들
3
+ * IDE 코드 하이라이팅 지원용 (실제 동작은 문자열 조합 + 들여쓰기 정리)
4
+ */
5
+ /**
6
+ * JavaScript 코드 하이라이팅용 템플릿 태그
7
+ * @param strings 템플릿 문자열 배열
8
+ * @param values 보간된 값들
9
+ * @returns 들여쓰기가 정리된 문자열
10
+ * @example
11
+ * const code = js`
12
+ * function hello() {
13
+ * return "world";
14
+ * }
15
+ * `;
16
+ */
17
+ export declare function js(strings: TemplateStringsArray, ...values: unknown[]): string;
18
+ /**
19
+ * TypeScript 코드 하이라이팅용 템플릿 태그
20
+ * @param strings 템플릿 문자열 배열
21
+ * @param values 보간된 값들
22
+ * @returns 들여쓰기가 정리된 문자열
23
+ * @example
24
+ * const code = ts`
25
+ * interface User {
26
+ * name: string;
27
+ * age: number;
28
+ * }
29
+ * `;
30
+ */
31
+ export declare function ts(strings: TemplateStringsArray, ...values: unknown[]): string;
32
+ /**
33
+ * HTML 마크업 하이라이팅용 템플릿 태그
34
+ * @param strings 템플릿 문자열 배열
35
+ * @param values 보간된 값들
36
+ * @returns 들여쓰기가 정리된 문자열
37
+ * @example
38
+ * const markup = html`
39
+ * <div class="container">
40
+ * <span>${name}</span>
41
+ * </div>
42
+ * `;
43
+ */
44
+ export declare function html(strings: TemplateStringsArray, ...values: unknown[]): string;
45
+ /**
46
+ * MSSQL T-SQL 하이라이팅용 템플릿 태그
47
+ * @param strings 템플릿 문자열 배열
48
+ * @param values 보간된 값들
49
+ * @returns 들여쓰기가 정리된 문자열
50
+ * @example
51
+ * const query = tsql`
52
+ * SELECT TOP 10 *
53
+ * FROM Users
54
+ * WHERE Name LIKE '%${keyword}%'
55
+ * `;
56
+ */
57
+ export declare function tsql(strings: TemplateStringsArray, ...values: unknown[]): string;
58
+ /**
59
+ * MySQL SQL 하이라이팅용 템플릿 태그
60
+ * @param strings 템플릿 문자열 배열
61
+ * @param values 보간된 값들
62
+ * @returns 들여쓰기가 정리된 문자열
63
+ * @example
64
+ * const query = mysql`
65
+ * SELECT *
66
+ * FROM users
67
+ * LIMIT 10
68
+ * `;
69
+ */
70
+ export declare function mysql(strings: TemplateStringsArray, ...values: unknown[]): string;
71
+ /**
72
+ * PostgreSQL SQL 하이라이팅용 템플릿 태그
73
+ * @param strings 템플릿 문자열 배열
74
+ * @param values 보간된 값들
75
+ * @returns 들여쓰기가 정리된 문자열
76
+ * @example
77
+ * const query = pgsql`
78
+ * SELECT *
79
+ * FROM users
80
+ * OFFSET 0 LIMIT 10
81
+ * `;
82
+ */
83
+ export declare function pgsql(strings: TemplateStringsArray, ...values: unknown[]): string;
84
+ //# sourceMappingURL=template-strings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-strings.d.ts","sourceRoot":"","sources":["../../../../../core-common/src/utils/template-strings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;GAWG;AACH,wBAAgB,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAE9E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAE9E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAEhF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAEhF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAEjF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAEjF"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Worker 간 전송 가능한 객체 타입
3
+ *
4
+ * 이 코드에서는 ArrayBuffer만 사용됩니다.
5
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Transferable_objects
6
+ */
7
+ type Transferable = ArrayBuffer;
8
+ /**
9
+ * Transferable 변환 유틸리티 함수
10
+ *
11
+ * Worker 간 데이터 전송을 위한 직렬화/역직렬화를 수행합니다.
12
+ * structuredClone이 지원하지 않는 커스텀 타입들을 처리합니다.
13
+ *
14
+ * 지원 타입:
15
+ * - Date, DateTime, DateOnly, Time, Uuid, RegExp
16
+ * - Error (cause, code, detail 포함)
17
+ * - Uint8Array (다른 TypedArray는 미지원, 일반 객체로 처리됨)
18
+ * - Array, Map, Set, 일반 객체
19
+ *
20
+ * @note 순환 참조가 있으면 transferableEncode 시 TypeError 발생 (경로 정보 포함)
21
+ * @note 동일 객체가 여러 곳에서 참조되면 캐시된 인코딩 결과를 재사용합니다
22
+ *
23
+ * @example
24
+ * // Worker로 데이터 전송
25
+ * const { result, transferList } = transferableEncode(data);
26
+ * worker.postMessage(result, transferList);
27
+ *
28
+ * // Worker에서 데이터 수신
29
+ * const decoded = transferableDecode(event.data);
30
+ */
31
+ /**
32
+ * 심플리즘 타입을 사용한 객체를 일반 객체로 변환
33
+ * Worker에 전송할 수 있는 형태로 직렬화
34
+ *
35
+ * @throws 순환 참조 감지 시 TypeError
36
+ */
37
+ export declare function transferableEncode(obj: unknown): {
38
+ result: unknown;
39
+ transferList: Transferable[];
40
+ };
41
+ /**
42
+ * serialize 객체를 심플리즘 타입 사용 객체로 변환
43
+ * Worker로부터 받은 데이터를 역직렬화
44
+ */
45
+ export declare function transferableDecode(obj: unknown): unknown;
46
+ export {};
47
+ //# sourceMappingURL=transferable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transferable.d.ts","sourceRoot":"","sources":["../../../../../core-common/src/utils/transferable.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,KAAK,YAAY,GAAG,WAAW,CAAC;AAEhC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG;IAChD,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,YAAY,EAAE,CAAC;CAC9B,CAMA;AAqID;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CA2ExD"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * 조건이 참이 될 때까지 대기
3
+ * @param forwarder 조건 함수
4
+ * @param milliseconds 체크 간격 (기본: 100ms)
5
+ * @param maxCount 최대 시도 횟수 (undefined면 무제한)
6
+ *
7
+ * @note 조건이 첫 번째 호출에서 true면 즉시 반환됩니다.
8
+ * @example
9
+ * // maxCount=3: 최대 3번 조건 확인 후 모두 false면 TimeoutError
10
+ * await waitUntil(() => someCondition, 100, 3);
11
+ * @throws TimeoutError 최대 시도 횟수 초과 시
12
+ */
13
+ export declare function waitUntil(forwarder: () => boolean | Promise<boolean>, milliseconds?: number, maxCount?: number): Promise<void>;
14
+ /**
15
+ * 지정된 시간만큼 대기
16
+ * @param millisecond 대기 시간 (ms)
17
+ */
18
+ export declare function waitTime(millisecond: number): Promise<void>;
19
+ //# sourceMappingURL=wait.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait.d.ts","sourceRoot":"","sources":["../../../../../core-common/src/utils/wait.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;GAWG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,EAC3C,YAAY,CAAC,EAAE,MAAM,EACrB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjE"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * XML 변환 유틸리티
3
+ */
4
+ import type { XmlBuilderOptions } from "fast-xml-parser";
5
+ /**
6
+ * XML 문자열을 객체로 파싱
7
+ * @param str XML 문자열
8
+ * @param options 옵션
9
+ * @param options.stripTagPrefix 태그 prefix 제거 여부 (namespace)
10
+ * @returns 파싱된 객체. 구조:
11
+ * - 속성: `$` 객체에 그룹화
12
+ * - 텍스트 노드: `_` 키에 저장
13
+ * - 자식 요소: 배열로 변환 (루트 요소 제외)
14
+ * @example
15
+ * xmlParse('<root id="1"><item>hello</item></root>');
16
+ * // { root: { $: { id: "1" }, item: [{ _: "hello" }] } }
17
+ */
18
+ export declare function xmlParse(str: string, options?: {
19
+ stripTagPrefix?: boolean;
20
+ }): unknown;
21
+ /**
22
+ * 객체를 XML 문자열로 직렬화
23
+ * @param obj 직렬화할 객체
24
+ * @param options fast-xml-parser XmlBuilderOptions (선택)
25
+ * @returns XML 문자열
26
+ * @example
27
+ * xmlStringify({
28
+ * root: {
29
+ * $: { id: "1" },
30
+ * item: [{ _: "hello" }, { _: "world" }],
31
+ * },
32
+ * });
33
+ * // '<root id="1"><item>hello</item><item>world</item></root>'
34
+ */
35
+ export declare function xmlStringify(obj: unknown, options?: XmlBuilderOptions): string;
36
+ //# sourceMappingURL=xml.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xml.d.ts","sourceRoot":"","sources":["../../../../../core-common/src/utils/xml.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAKzD;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAarF;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAS9E"}
@@ -0,0 +1,80 @@
1
+ import type { Bytes } from "../common.types";
2
+ export interface ZipArchiveProgress {
3
+ fileName: string;
4
+ totalSize: number;
5
+ extractedSize: number;
6
+ }
7
+ /**
8
+ * ZIP 아카이브 처리 클래스
9
+ *
10
+ * ZIP 파일의 읽기, 쓰기, 압축/해제를 처리합니다.
11
+ * 내부 캐시를 사용하여 동일 파일의 중복 압축 해제를 방지합니다.
12
+ *
13
+ * @example
14
+ * // ZIP 파일 읽기
15
+ * await using archive = new ZipArchive(zipBytes);
16
+ * const content = await archive.get("file.txt");
17
+ *
18
+ * @example
19
+ * // ZIP 파일 생성
20
+ * await using archive = new ZipArchive();
21
+ * archive.write("file.txt", textBytes);
22
+ * archive.write("data.json", jsonBytes);
23
+ * const zipBytes = await archive.compress();
24
+ *
25
+ * @example
26
+ * // 전체 압축 해제 (진행률 표시)
27
+ * await using archive = new ZipArchive(zipBytes);
28
+ * const files = await archive.extractAll((progress) => {
29
+ * console.log(`${progress.fileName}: ${progress.extractedSize}/${progress.totalSize}`);
30
+ * });
31
+ */
32
+ export declare class ZipArchive {
33
+ private readonly _reader?;
34
+ private readonly _cache;
35
+ private _entries?;
36
+ /**
37
+ * ZipArchive 생성
38
+ * @param data ZIP 데이터 (생략 시 새 아카이브 생성)
39
+ */
40
+ constructor(data?: Blob | Bytes);
41
+ private _getEntries;
42
+ /**
43
+ * 모든 파일을 압축 해제
44
+ * @param progressCallback 진행률 콜백
45
+ */
46
+ extractAll(progressCallback?: (progress: ZipArchiveProgress) => void): Promise<Map<string, Bytes | undefined>>;
47
+ /**
48
+ * 특정 파일 압축 해제
49
+ * @param fileName 파일 이름
50
+ */
51
+ get(fileName: string): Promise<Bytes | undefined>;
52
+ /**
53
+ * 파일 존재 여부 확인
54
+ * @param fileName 파일 이름
55
+ */
56
+ exists(fileName: string): Promise<boolean>;
57
+ /**
58
+ * 파일 쓰기 (캐시에 저장)
59
+ * @param fileName 파일 이름
60
+ * @param bytes 파일 내용
61
+ */
62
+ write(fileName: string, bytes: Bytes): void;
63
+ /**
64
+ * 캐시된 파일들을 ZIP으로 압축
65
+ *
66
+ * @remarks
67
+ * 내부적으로 `extractAll()`을 호출하여 모든 파일을 메모리에 로드한 후 압축합니다.
68
+ * 대용량 ZIP 파일의 경우 메모리 사용량에 주의가 필요합니다.
69
+ */
70
+ compress(): Promise<Bytes>;
71
+ /**
72
+ * 리더 닫기 및 캐시 정리
73
+ */
74
+ close(): Promise<void>;
75
+ /**
76
+ * await using 지원
77
+ */
78
+ [Symbol.asyncDispose](): Promise<void>;
79
+ }
80
+ //# sourceMappingURL=sd-zip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sd-zip.d.ts","sourceRoot":"","sources":["../../../../../core-common/src/zip/sd-zip.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAA0B;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwC;IAC/D,OAAO,CAAC,QAAQ,CAAC,CAA6D;IAE9E;;;OAGG;gBACS,IAAI,CAAC,EAAE,IAAI,GAAG,KAAK;YAUjB,WAAW;IAQzB;;;OAGG;IACG,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,GAAG,SAAS,CAAC,CAAC;IAkDpH;;;OAGG;IACG,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC;IAwBvD;;;OAGG;IACG,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBhD;;;;OAIG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAM3C;;;;;;OAMG;IACG,QAAQ,IAAI,OAAO,CAAC,KAAK,CAAC;IAiBhC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B;;OAEG;IACG,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7C"}
@@ -0,0 +1,122 @@
1
+ import { isFocusable } from "tabbable";
2
+ import { TimeoutError } from "@simplysm/core-common";
3
+ Element.prototype.findAll = function(selector) {
4
+ const trimmed = selector.trim();
5
+ if (trimmed === "") return [];
6
+ return Array.from(this.querySelectorAll(trimmed));
7
+ };
8
+ Element.prototype.findFirst = function(selector) {
9
+ const trimmed = selector.trim();
10
+ if (trimmed === "") return void 0;
11
+ return this.querySelector(trimmed) ?? void 0;
12
+ };
13
+ Element.prototype.prependChild = function(child) {
14
+ return this.insertBefore(child, this.firstElementChild);
15
+ };
16
+ Element.prototype.getParents = function() {
17
+ const result = [];
18
+ let cursor = this.parentNode;
19
+ while (cursor !== null && cursor instanceof Element) {
20
+ result.push(cursor);
21
+ cursor = cursor.parentNode;
22
+ }
23
+ return result;
24
+ };
25
+ Element.prototype.findFocusableParent = function() {
26
+ let parentEl = this.parentElement;
27
+ while (parentEl !== null) {
28
+ if (isFocusable(parentEl)) {
29
+ return parentEl;
30
+ }
31
+ parentEl = parentEl.parentElement;
32
+ }
33
+ return void 0;
34
+ };
35
+ Element.prototype.findFirstFocusableChild = function() {
36
+ const walker = document.createTreeWalker(this, NodeFilter.SHOW_ELEMENT);
37
+ let node = walker.nextNode();
38
+ while (node !== null) {
39
+ if (node instanceof HTMLElement && isFocusable(node)) {
40
+ return node;
41
+ }
42
+ node = walker.nextNode();
43
+ }
44
+ return void 0;
45
+ };
46
+ Element.prototype.isOffsetElement = function() {
47
+ return ["relative", "absolute", "fixed", "sticky"].includes(getComputedStyle(this).position);
48
+ };
49
+ Element.prototype.isVisible = function() {
50
+ const style = getComputedStyle(this);
51
+ return this.getClientRects().length > 0 && style.visibility !== "hidden" && style.opacity !== "0";
52
+ };
53
+ function copyElement(event) {
54
+ const clipboardData = event.clipboardData;
55
+ const target = event.target;
56
+ if (clipboardData == null || !(target instanceof Element)) return;
57
+ const firstInputEl = target.querySelector("input, textarea");
58
+ if (firstInputEl != null) {
59
+ clipboardData.setData("text/plain", firstInputEl.value);
60
+ event.preventDefault();
61
+ }
62
+ }
63
+ function pasteToElement(event) {
64
+ const clipboardData = event.clipboardData;
65
+ const target = event.target;
66
+ if (clipboardData == null || !(target instanceof Element)) return;
67
+ const contentText = clipboardData.getData("text/plain");
68
+ const firstInputEl = target.findFirst("input, textarea");
69
+ if (firstInputEl !== void 0) {
70
+ firstInputEl.value = contentText;
71
+ firstInputEl.dispatchEvent(new Event("input", { bubbles: true }));
72
+ event.preventDefault();
73
+ }
74
+ }
75
+ async function getBounds(els, timeout = 5e3) {
76
+ const indexMap = new Map(els.map((el, i) => [el, i]));
77
+ if (indexMap.size === 0) {
78
+ return [];
79
+ }
80
+ const sortIndexMap = new Map(els.map((el, i) => [el, i]));
81
+ let observer;
82
+ try {
83
+ return await Promise.race([
84
+ new Promise((resolve) => {
85
+ const results = [];
86
+ observer = new IntersectionObserver((entries) => {
87
+ for (const entry of entries) {
88
+ const target = entry.target;
89
+ if (indexMap.has(target)) {
90
+ indexMap.delete(target);
91
+ results.push({
92
+ target,
93
+ top: entry.boundingClientRect.top,
94
+ left: entry.boundingClientRect.left,
95
+ width: entry.boundingClientRect.width,
96
+ height: entry.boundingClientRect.height
97
+ });
98
+ }
99
+ }
100
+ if (indexMap.size === 0) {
101
+ observer == null ? void 0 : observer.disconnect();
102
+ resolve(results.sort((a, b) => sortIndexMap.get(a.target) - sortIndexMap.get(b.target)));
103
+ }
104
+ });
105
+ for (const el of indexMap.keys()) {
106
+ observer.observe(el);
107
+ }
108
+ }),
109
+ new Promise(
110
+ (_, reject) => setTimeout(() => reject(new TimeoutError(void 0, `${timeout}ms \uCD08\uACFC`)), timeout)
111
+ )
112
+ ]);
113
+ } finally {
114
+ observer == null ? void 0 : observer.disconnect();
115
+ }
116
+ }
117
+ export {
118
+ copyElement,
119
+ getBounds,
120
+ pasteToElement
121
+ };
122
+ //# sourceMappingURL=element-ext.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 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
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,50 @@
1
+ import { ArgumentError } from "@simplysm/core-common";
2
+ HTMLElement.prototype.repaint = function() {
3
+ void this.offsetHeight;
4
+ };
5
+ HTMLElement.prototype.getRelativeOffset = function(parent) {
6
+ const parentEl = typeof parent === "string" ? this.closest(parent) : parent;
7
+ if (!(parentEl instanceof HTMLElement)) {
8
+ throw new ArgumentError({ parent });
9
+ }
10
+ const elementRect = this.getBoundingClientRect();
11
+ const parentRect = parentEl.getBoundingClientRect();
12
+ const scrollLeft = window.scrollX;
13
+ const scrollTop = window.scrollY;
14
+ const relativeOffset = {
15
+ top: elementRect.top - parentRect.top + scrollTop + (parentEl.scrollTop || 0),
16
+ left: elementRect.left - parentRect.left + scrollLeft + (parentEl.scrollLeft || 0)
17
+ };
18
+ let currentEl = this.parentElement;
19
+ while (currentEl !== null && currentEl !== parentEl) {
20
+ const style = getComputedStyle(currentEl);
21
+ relativeOffset.top += parseFloat(style.borderTopWidth) || 0;
22
+ relativeOffset.left += parseFloat(style.borderLeftWidth) || 0;
23
+ currentEl = currentEl.parentElement;
24
+ }
25
+ const elTransform = getComputedStyle(this).transform;
26
+ const parentTransform = getComputedStyle(parentEl).transform;
27
+ if (elTransform !== "none" || parentTransform !== "none") {
28
+ const elementMatrix = new DOMMatrix(elTransform);
29
+ const parentMatrix = new DOMMatrix(parentTransform);
30
+ if (!elementMatrix.isIdentity || !parentMatrix.isIdentity) {
31
+ const transformedPoint = parentMatrix.inverse().multiply(elementMatrix).transformPoint(new DOMPoint(relativeOffset.left, relativeOffset.top));
32
+ relativeOffset.left = transformedPoint.x;
33
+ relativeOffset.top = transformedPoint.y;
34
+ }
35
+ }
36
+ return relativeOffset;
37
+ };
38
+ HTMLElement.prototype.scrollIntoViewIfNeeded = function(target, offset = { top: 0, left: 0 }) {
39
+ const scroll = {
40
+ top: this.scrollTop,
41
+ left: this.scrollLeft
42
+ };
43
+ if (target.top - scroll.top < offset.top) {
44
+ this.scrollTop = target.top - offset.top;
45
+ }
46
+ if (target.left - scroll.left < offset.left) {
47
+ this.scrollLeft = target.left - offset.left;
48
+ }
49
+ };
50
+ //# sourceMappingURL=html-element-ext.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 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
+ "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
+ "names": []
7
+ }