@ninebone/util 0.9.170

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.
@@ -0,0 +1,1559 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __typeError = (msg) => {
3
+ throw TypeError(msg);
4
+ };
5
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
7
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
8
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
9
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
10
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
11
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
12
+ var _name, _color, _Trace_instances, isTraceEnabled_fn, _a, _timer, _queue, _delay, _TaskDebouncer_instances, flush_fn, _request, _shift, _dialog, _init, _onMouseDown, _onTouchStart, _NineUxUtil_instances, prepare_fn, _mode, _detectMode, _startDrag, _init2, _prepareLayout;
13
+ const listeners = /* @__PURE__ */ new Set();
14
+ const _initialConfig = {
15
+ ux: { nativeOverride: false, theme: "light" },
16
+ board: { readOnly: false },
17
+ cssPath: "",
18
+ debug: false
19
+ };
20
+ if (typeof window !== "undefined" && !window.__NINE_GLOBAL_CONFIG__) {
21
+ window.__NINE_GLOBAL_CONFIG__ = _initialConfig;
22
+ }
23
+ const _config = typeof window !== "undefined" ? window.__NINE_GLOBAL_CONFIG__ : _initialConfig;
24
+ const subscribeConfig = (fn) => {
25
+ listeners.add(fn);
26
+ fn("all", _config);
27
+ return () => listeners.delete(fn);
28
+ };
29
+ const config = new Proxy(_config, {
30
+ set(target, prop, value) {
31
+ target[prop] = value;
32
+ listeners.forEach((fn) => fn(prop, target));
33
+ return true;
34
+ },
35
+ get(target, prop) {
36
+ return target[prop];
37
+ }
38
+ });
39
+ const nine$1 = {
40
+ config,
41
+ // Getter에서 window.nine까지 확인할 필요도 없습니다.
42
+ // 이미 config 자체가 전역 저장소(__NINE_GLOBAL_CONFIG__)를 바라보고 있기 때문입니다.
43
+ get cssPath() {
44
+ return this.config.cssPath || "";
45
+ },
46
+ setup(options = {}) {
47
+ Object.entries(options).forEach(([key, value]) => {
48
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
49
+ this.config[key] = { ...this.config[key], ...value };
50
+ } else {
51
+ this.config[key] = value;
52
+ }
53
+ });
54
+ if (typeof window !== "undefined") {
55
+ window.nine = window.nine || this;
56
+ }
57
+ }
58
+ };
59
+ let Trace$1 = (_a = class {
60
+ constructor(name = null, color = "green") {
61
+ __privateAdd(this, _Trace_instances);
62
+ __privateAdd(this, _name);
63
+ __privateAdd(this, _color);
64
+ __privateSet(this, _name, name);
65
+ __privateSet(this, _color, color);
66
+ }
67
+ init(name, color = "green") {
68
+ __privateSet(this, _name, name);
69
+ __privateSet(this, _color, color);
70
+ return this;
71
+ }
72
+ // 🔴 핵심: 소스 위치 유지를 위한 Getter 로직
73
+ get log() {
74
+ if (!__privateMethod(this, _Trace_instances, isTraceEnabled_fn).call(this)) return () => {
75
+ };
76
+ const style = `color: ${__privateGet(this, _color)}; font-weight: bold;`;
77
+ return __privateGet(this, _name) ? console.log.bind(console, `%c[${__privateGet(this, _name)}]`, style) : console.log.bind(console);
78
+ }
79
+ get warn() {
80
+ if (!__privateMethod(this, _Trace_instances, isTraceEnabled_fn).call(this)) return () => {
81
+ };
82
+ return __privateGet(this, _name) ? console.warn.bind(console, `%c[${__privateGet(this, _name)}]`, "color: cyan; font-weight: bold;") : console.warn.bind(console);
83
+ }
84
+ get error() {
85
+ return __privateGet(this, _name) ? console.error.bind(console, `%c[${__privateGet(this, _name)}]`, "color: red; font-weight: bold;") : console.error.bind(console);
86
+ }
87
+ }, _name = new WeakMap(), _color = new WeakMap(), _Trace_instances = new WeakSet(), /**
88
+ * 🎯 실시간 디버그 활성화 및 필터 타겟 여부 체크 헬퍼
89
+ */
90
+ isTraceEnabled_fn = function() {
91
+ if (nine && nine.config && nine.config.debug) {
92
+ const debugConfig = nine.config.debug;
93
+ if (debugConfig.enable === false) {
94
+ return false;
95
+ }
96
+ if (debugConfig.enable === true && Array.isArray(debugConfig.filter)) {
97
+ if (__privateGet(this, _name)) {
98
+ return debugConfig.filter.includes(__privateGet(this, _name));
99
+ }
100
+ }
101
+ return debugConfig.enable;
102
+ }
103
+ if (typeof window !== "undefined") {
104
+ return window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1" || window.location.hostname.startsWith("192.168.");
105
+ }
106
+ return false;
107
+ }, _a);
108
+ const trace$2 = new Trace$1();
109
+ if (typeof window !== "undefined") window.trace = trace$2;
110
+ class TaskDebouncer {
111
+ constructor(delay = 50) {
112
+ __privateAdd(this, _TaskDebouncer_instances);
113
+ __privateAdd(this, _timer, null);
114
+ __privateAdd(this, _queue, []);
115
+ __privateAdd(this, _delay);
116
+ __privateSet(this, _delay, delay);
117
+ }
118
+ /**
119
+ * @param {Function} func - 실행할 함수
120
+ * @param {...any} args - 함수에 전달할 임의의 파라미터들
121
+ */
122
+ exec(func, ...args) {
123
+ __privateGet(this, _queue).push({ func, args });
124
+ if (__privateGet(this, _timer)) clearTimeout(__privateGet(this, _timer));
125
+ __privateSet(this, _timer, setTimeout(() => __privateMethod(this, _TaskDebouncer_instances, flush_fn).call(this), __privateGet(this, _delay)));
126
+ }
127
+ execWithKey(key, func, ...args) {
128
+ __privateSet(this, _queue, __privateGet(this, _queue).filter((task) => task.key !== key));
129
+ __privateGet(this, _queue).push({ key, func, args });
130
+ if (__privateGet(this, _timer)) clearTimeout(__privateGet(this, _timer));
131
+ __privateSet(this, _timer, setTimeout(() => __privateMethod(this, _TaskDebouncer_instances, flush_fn).call(this), __privateGet(this, _delay)));
132
+ }
133
+ }
134
+ _timer = new WeakMap();
135
+ _queue = new WeakMap();
136
+ _delay = new WeakMap();
137
+ _TaskDebouncer_instances = new WeakSet();
138
+ flush_fn = function() {
139
+ if (__privateGet(this, _queue).length === 0) return;
140
+ const tasks = __privateGet(this, _queue).splice(0, __privateGet(this, _queue).length);
141
+ const seen = /* @__PURE__ */ new Set();
142
+ tasks.forEach((task) => {
143
+ const identifier = `${task.func.name}_${JSON.stringify(task.args)}`;
144
+ if (!seen.has(identifier)) {
145
+ task.func(...task.args);
146
+ seen.add(identifier);
147
+ }
148
+ });
149
+ __privateSet(this, _timer, null);
150
+ };
151
+ class Trace extends trace$2.constructor {
152
+ constructor() {
153
+ super();
154
+ this.init("nine-util", "green");
155
+ }
156
+ }
157
+ const trace$1 = new Trace();
158
+ class Loading {
159
+ static show() {
160
+ let overlay = document.getElementById("global-loading-overlay");
161
+ if (!overlay) {
162
+ overlay = document.createElement("div");
163
+ overlay.id = "global-loading-overlay";
164
+ overlay.style.cssText = `
165
+ position: fixed; inset: 0; z-index: 9999;
166
+ background: rgba(0, 0, 0, 0.4); display: flex;
167
+ justify-content: center; align-items: center;
168
+ backdrop-filter: blur(2px);
169
+ `;
170
+ overlay.innerHTML = `<div class="loading-spinner"></div>`;
171
+ document.body.appendChild(overlay);
172
+ if (!document.getElementById("nine-util-style")) {
173
+ const style = document.createElement("style");
174
+ style.id = "nine-util-style";
175
+ style.innerHTML = `
176
+ .loading-spinner {
177
+ width: 48px; height: 48px;
178
+ border: 5px solid rgba(255, 255, 255, 0.3);
179
+ border-top-color: white; border-radius: 50%;
180
+ animation: nine-spin 1s linear infinite;
181
+ }
182
+ @keyframes nine-spin { to { transform: rotate(360deg); } }
183
+ `;
184
+ document.head.appendChild(style);
185
+ }
186
+ }
187
+ overlay.style.display = "flex";
188
+ }
189
+ static hide() {
190
+ const overlay = document.getElementById("global-loading-overlay");
191
+ if (overlay) overlay.style.display = "none";
192
+ }
193
+ }
194
+ const _Fetch = class _Fetch {
195
+ };
196
+ _request = new WeakMap();
197
+ __publicField(_Fetch, "BASE_URL", window.__API_BASE_URL__ || "");
198
+ __privateAdd(_Fetch, _request, (method, url, data = {}, showLoading = true) => {
199
+ const finalUrl = url.startsWith("http") ? url : `${_Fetch.BASE_URL}${url}`;
200
+ if (showLoading) {
201
+ Loading.show();
202
+ }
203
+ const headers = {};
204
+ if (!(data instanceof FormData)) {
205
+ headers["Content-Type"] = "application/json";
206
+ }
207
+ const options = {
208
+ method,
209
+ headers
210
+ };
211
+ let targetUrl = finalUrl;
212
+ if (method === "GET") {
213
+ targetUrl += `?${new URLSearchParams(data)}`;
214
+ } else {
215
+ options.body = data instanceof FormData ? data : JSON.stringify(data);
216
+ }
217
+ return fetch(targetUrl, options).then(async (res) => {
218
+ if (!res.ok) {
219
+ const text = await res.text();
220
+ throw new Error(`API 오류 (${res.status}): ${text}`);
221
+ }
222
+ return res.json();
223
+ }).catch((err) => {
224
+ trace$1.error(`[IdeFetch.${method.toLowerCase()}] ${finalUrl} 실패:`, err);
225
+ throw err;
226
+ }).finally(() => {
227
+ if (showLoading) {
228
+ Loading.hide();
229
+ }
230
+ });
231
+ });
232
+ // 기존 post/get 메서드도 인자를 넘겨주도록 수정
233
+ __publicField(_Fetch, "get", (url, data = {}, showLoading = true) => {
234
+ var _a2;
235
+ return __privateGet(_a2 = _Fetch, _request).call(_a2, "GET", url, data, showLoading);
236
+ });
237
+ __publicField(_Fetch, "post", (url, data = {}, showLoading = true) => {
238
+ var _a2;
239
+ return __privateGet(_a2 = _Fetch, _request).call(_a2, "POST", url, data, showLoading);
240
+ });
241
+ /**
242
+ * 🚀 범용 청크 전송 (파라미터 이름까지 동적 설정)
243
+ * @param {string} url - API 주소
244
+ * @param {Array} rows - 데이터 배열
245
+ * @param {object} options - 상세 옵션
246
+ * - fileKey: 객체 내 파일 속성명 (기본: 'fileContents')
247
+ * - filePartName: 서버에서 받을 파일 파트명 (기본: 'files')
248
+ * - jsonPartName: 서버에서 받을 JSON 파트명 (기본: 'dataList')
249
+ * - chunkSize: 분할 단위 (기본: 10)
250
+ */
251
+ __publicField(_Fetch, "postMultipart", async (url, rows = [], options = {}) => {
252
+ const {
253
+ fileKey = "fileContents",
254
+ filePartName = "files",
255
+ jsonPartName = "dataList",
256
+ chunkSize = 10
257
+ } = options;
258
+ Loading.show();
259
+ let totalCount = 0;
260
+ let lastResponse = null;
261
+ return (async () => {
262
+ for (let i = 0; i < rows.length; i += chunkSize) {
263
+ const formData = new FormData();
264
+ const chunk = rows.slice(i, i + chunkSize);
265
+ const rowDataList = [];
266
+ chunk.forEach((row) => {
267
+ const { [fileKey]: fileObj, _fileObj, ...rest } = row;
268
+ rowDataList.push(rest);
269
+ if (fileObj instanceof File) {
270
+ formData.append(filePartName, fileObj);
271
+ }
272
+ });
273
+ const jsonBlob = new Blob([JSON.stringify(rowDataList)], { type: "application/json" });
274
+ formData.append(jsonPartName, jsonBlob);
275
+ lastResponse = await _Fetch.post(url, formData, false);
276
+ if (lastResponse && (lastResponse.success || lastResponse.status === "OK")) {
277
+ totalCount += chunk.length;
278
+ } else {
279
+ throw new Error(`청크 전송 실패: ${i}번째 섹션`);
280
+ }
281
+ }
282
+ return { ...lastResponse, success: true, totalCount };
283
+ })().catch((err) => {
284
+ trace$1.error("[postChunk] Error:", err);
285
+ throw err;
286
+ }).finally(() => {
287
+ Loading.hide();
288
+ });
289
+ });
290
+ let Fetch = _Fetch;
291
+ const api = Fetch;
292
+ const dialogStyles = `
293
+ dialog::backdrop {
294
+ background: rgba(0, 0, 0, 0.3);
295
+ }
296
+
297
+ dialog:modal {
298
+ display: flex;
299
+ flex-direction: column;
300
+ padding: 0;
301
+ overflow: hidden;
302
+ border: 1px solid darkgreen;
303
+ outline: none;
304
+ resize: both;
305
+ box-shadow: 0 0 4px 0 darkgreen;
306
+ width: 500px;
307
+ height: fit-content;
308
+ min-width: 330px;
309
+ min-height: 60px;
310
+ max-height: 100%;
311
+ }
312
+
313
+
314
+
315
+
316
+ div.head .rect1, div.head .rect2, div.head .rect3 {
317
+ display: none;
318
+ width: 50px;
319
+ height: 100%;
320
+ }
321
+ div.head .rect1 {
322
+ background-color: red;
323
+ }
324
+ div.head .rect2 {
325
+ background-color: darkgreen;
326
+ }
327
+ div.head .rect3 {
328
+ background-color: olive;
329
+ }
330
+
331
+ div.head {
332
+ display: flex;
333
+ align-items: center;
334
+ --height: 30px;
335
+ background-color: darkgreen;
336
+ padding: 4px;
337
+ cursor: move;
338
+ }
339
+ div.head:hover {
340
+ filter: brightness(110%);
341
+ }
342
+
343
+ div.head span {
344
+ font-size: 12px;
345
+ position: relative;
346
+ }
347
+
348
+ div.head span.title {
349
+ color: #ddd;
350
+ margin-left: 4px;
351
+ font-weight: bold;
352
+ }
353
+
354
+ div.head span.sub-title {
355
+ color: #ccc;
356
+ margin-left: 8px;
357
+ font-style: italic;
358
+ }
359
+
360
+ div.head form {
361
+ margin: 0;
362
+ }
363
+ div.head button {
364
+ margin-right: 4px;
365
+ background-color: transparent;
366
+ border: none;
367
+ color: #ccc;
368
+ font-size: x-small;
369
+ }
370
+ div.head button:hover {
371
+ cursor: pointer;
372
+ }
373
+
374
+ div.contents {
375
+ display: flex;
376
+ width: 100%;
377
+ height: 100%;
378
+ overflow: hidden;
379
+ background-color: white;
380
+ color: #333;
381
+ }
382
+ div.left {
383
+ position: relative;
384
+ width: 16px;
385
+ height: 100%;
386
+ background-color: #ddd;
387
+ display: none;
388
+ }
389
+
390
+ div.left span {
391
+ writing-mode: vertical-rl;
392
+ -moz-user-select: none;
393
+ -webkit-user-select: none;
394
+ -ms-user-select: none;
395
+ user-select: none;
396
+ color: #ccc;
397
+ font-weight: 700;
398
+ width: 100%;
399
+ height: 100%;
400
+ margin-left: 3px;
401
+ margin-top: 3px;
402
+ }
403
+ div.close2 {
404
+ display: none;
405
+ position: absolute;
406
+ right: 0;
407
+ top: 3px;
408
+ cursor: pointer;
409
+ color: #666;
410
+ }
411
+ div.close2 svg:hover {
412
+ color: #999;
413
+ }
414
+
415
+ div.body {
416
+ display: flex;
417
+ width: 100%;
418
+ height: unset;
419
+ --border: 3px solid #999;
420
+ --border-top: none;
421
+ overflow-x: hidden;
422
+ overflow-y: auto;
423
+ padding: 10px;
424
+ gap: 8px;
425
+ flex-direction: column;
426
+ }
427
+
428
+
429
+
430
+
431
+ ng-sphere.icon {
432
+ margin-left: 8px;
433
+ }
434
+
435
+ .buttons {
436
+ display: flex;
437
+ position: absolute;
438
+ right: 4px;
439
+ }
440
+
441
+ ng-sphere {
442
+ position: relative;
443
+ --width: 16px;
444
+ --height: 16px;
445
+ cursor: pointer;
446
+ margin-right: 4px;
447
+ display: flex;
448
+ }
449
+ ng-sphere:hover {
450
+ filter: brightness(90%);
451
+ }
452
+ ng-sphere:active {
453
+ filter: brightness(80%);
454
+ }
455
+
456
+ ng-sphere:hover::after {
457
+ content: "";
458
+ position: absolute;
459
+ width: 100%;
460
+ height: 100%;
461
+ background-repeat: no-repeat;
462
+ background-position: center;
463
+ }
464
+ ng-sphere.apply:hover::after {
465
+ background-size: 14px 14px;
466
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><polyline points="2.5,7 6,10 11,3" style="fill:none;stroke:white;stroke-width:2px;" /></svg>');
467
+ }
468
+
469
+ ng-sphere.reset:hover::after {
470
+ background-size: 12px 12px;
471
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" style="fill:none;stroke:white;stroke-width:2px;" focusable="false" aria-hidden="true"><path d="M10 5h5V0"></path><path d="M15 8a6.957 6.957 0 0 1-7 7 6.957 6.957 0 0 1-7-7 6.957 6.957 0 0 1 7-7 6.87 6.87 0 0 1 6.3 4"></path></svg>');
472
+ }
473
+
474
+ ng-sphere.close:hover::after {
475
+ background-size: 12px 12px;
476
+ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" style="fill:none;stroke:white;stroke-width:2px;" focusable="false" aria-hidden="true" viewBox="0 0 16 16"><path d="M2 2l12 12M14 2L2 14"></path></svg>');
477
+ }
478
+
479
+
480
+ button {
481
+ cursor: pointer;
482
+ }
483
+
484
+ .input-area {
485
+ position: relative;
486
+ height: 100%;
487
+ --display: flex;
488
+ textarea {
489
+ width: 100%;
490
+ height: 100%;
491
+ min-height: 100px;
492
+ padding: 8px;
493
+ box-sizing: border-box;
494
+ resize: none;
495
+ border-radius: 2px;
496
+ border-color: #ccc;
497
+ }
498
+ textarea:focus {
499
+ border-color: green;
500
+ outline: none; /* 브라우저 기본 파란색 테두리 제거 */
501
+ }
502
+ }
503
+
504
+ .buttons-confirm {
505
+ position: absolute;
506
+ display: flex;
507
+ justify-content: flex-end;
508
+ bottom: 8px;
509
+ right: 8px;
510
+ }
511
+
512
+
513
+ .buttons-confirm button {
514
+ height: 32px;
515
+ margin-right: 8px;
516
+ border: none;
517
+ outline: none;
518
+ width: 60px;
519
+ -moz-user-select: none;
520
+ -webkit-user-select: none;
521
+ -ms-user-select: none;
522
+ user-select: none;
523
+ }
524
+ .buttons-confirm button:hover {
525
+ filter: brightness(90%);
526
+ }
527
+ .buttons-confirm button:active {
528
+ color: #ccc;
529
+ }
530
+
531
+ button.ok {
532
+ --display: none;
533
+ background-color: darkgreen;
534
+ color: white;
535
+ }
536
+ button.cancel {
537
+ color: white;
538
+ background-color: #6c757d;
539
+ }
540
+
541
+
542
+
543
+ div.msg {
544
+ position: relative;
545
+ height: 100%;
546
+ font-size: 14px;
547
+ color: #333;
548
+ padding-bottom: 48px;
549
+ }
550
+
551
+ .reset, .apply {
552
+ display: none;
553
+ }
554
+
555
+
556
+
557
+ :host(.classic) dialog:modal {
558
+ border: 1px solid #007bff;
559
+ box-shadow: 0 0 4px 0 #007bff;
560
+ }
561
+
562
+ :host(.classic) div.head {
563
+ background-color: #007bff;
564
+ }
565
+ :host(.classic) div.head:hover {
566
+ filter: brightness(110%);
567
+ }
568
+
569
+ :host(.classic) div.head span {
570
+ font-size: 12px;
571
+ }
572
+
573
+ :host(.classic) div.head span.title {
574
+ color: #ddd;
575
+ margin-left: 4px;
576
+ font-weight: bold;
577
+ }
578
+
579
+ :host(.classic) div.head span.sub-title {
580
+ color: #ccc;
581
+ margin-left: 8px;
582
+ font-style: italic;
583
+ }
584
+ :host(.classic) div.head button {
585
+ margin-right: 4px;
586
+ background-color: transparent;
587
+ border: none;
588
+ color: #ccc;
589
+ font-size: x-small;
590
+ }
591
+
592
+
593
+
594
+
595
+ :host(.rgb) dialog:modal {
596
+ border: none;
597
+ box-shadow: unset;
598
+ border-top: none;
599
+ }
600
+
601
+ :host(.rgb) div.left {
602
+ display: block;
603
+ background-color: #ddd;
604
+ }
605
+ :host(.rgb) div.left span {
606
+ color: #ccc;
607
+ }
608
+ :host(.rgb) div.close2 {
609
+ display: block;
610
+ color: #666;
611
+ }
612
+ :host(.rgb) div.close2 svg:hover {
613
+ color: #999;
614
+ }
615
+ :host(.rgb) div.head {
616
+ height: 4px;
617
+ background-color: #999;
618
+ padding: 0;
619
+ }
620
+ :host(.rgb) div.contents {
621
+ height: calc(100% - 4px);
622
+ }
623
+
624
+ :host(.rgb) div.head ng-sphere,
625
+ :host(.rgb) div.head span,
626
+ :host(.rgb) div.head .buttons {
627
+ display: none;
628
+ }
629
+
630
+ :host(.rgb) div.head .rect1,
631
+ :host(.rgb) div.head .rect2,
632
+ :host(.rgb) div.head .rect3 {
633
+ display: flex;
634
+ }
635
+
636
+
637
+ :host(.rgb) div.head:hover {
638
+ filter: unset;
639
+ }
640
+
641
+
642
+ /* --- Animation Core --- */
643
+ :host {
644
+ --nx-duration: 0.4s;
645
+ --nx-timing: cubic-bezier(0.34, 1.56, 0.64, 1);
646
+ }
647
+
648
+ /* 🎯 수정: 애니메이션 클래스가 붙은 경우에만 초기 opacity를 0으로 설정 */
649
+ :host(.fade) dialog,
650
+ :host(.zoom) dialog,
651
+ :host(.moveUp) dialog,
652
+ :host(.moveDown) dialog,
653
+ :host(.moveLeft) dialog,
654
+ :host(.moveRight) dialog,
655
+ :host(.roadRunner) dialog {
656
+ opacity: 0;
657
+ }
658
+
659
+ /* shake는 애니메이션 내부에서 opacity를 다루므로 제외하거나 별도 처리 */
660
+ :host(.shake) dialog {
661
+ opacity: 1;
662
+ }
663
+
664
+ /* 1. Fade (서서히 나타남) */
665
+ :host(.fade) dialog { animation: nx-fade-in var(--nx-duration) forwards; }
666
+ @keyframes nx-fade-in { from { opacity: 0; } to { opacity: 1; } }
667
+
668
+ /* 2. Zoom (커지며 나타남) */
669
+ :host(.zoom) dialog { animation: nx-zoom-in var(--nx-duration) var(--nx-timing) forwards; }
670
+ @keyframes nx-zoom-in { from { opacity: 0; transform: scale(0.5); } to { opacity: 1; transform: scale(1); } }
671
+
672
+ /* 3. Slide (상하좌우) */
673
+ :host(.moveUp) dialog { animation: nx-move-up var(--nx-duration) var(--nx-timing) forwards; }
674
+ :host(.moveDown) dialog { animation: nx-move-down var(--nx-duration) var(--nx-timing) forwards; }
675
+ :host(.moveLeft) dialog { animation: nx-move-left var(--nx-duration) var(--nx-timing) forwards; }
676
+ :host(.moveRight) dialog { animation: nx-move-right var(--nx-duration) var(--nx-timing) forwards; }
677
+
678
+ @keyframes nx-move-up { from { opacity: 0; transform: translateY(100px); } to { opacity: 1; transform: translateY(0); } }
679
+ @keyframes nx-move-down { from { opacity: 0; transform: translateY(-100px); } to { opacity: 1; transform: translateY(0); } }
680
+ @keyframes nx-move-left { from { opacity: 0; transform: translateX(100px); } to { opacity: 1; transform: translateX(0); } }
681
+ @keyframes nx-move-right { from { opacity: 0; transform: translateX(-100px); } to { opacity: 1; transform: translateY(0); } }
682
+
683
+ /* 4. Shake (상하좌우 격렬한 진동 - 에러 인지용) */
684
+ :host(.shake) dialog {
685
+ animation: nx-heavy-shake 0.5s cubic-bezier(.36,.07,.19,.97) both;
686
+ opacity: 1;
687
+ }
688
+
689
+ @keyframes nx-heavy-shake {
690
+ 10%, 90% { transform: translate3d(-1px, -2px, 0); }
691
+ 20%, 80% { transform: translate3d(2px, 4px, 0); }
692
+ 30%, 50%, 70% { transform: translate3d(-6px, -6px, 0); }
693
+ 40%, 60% { transform: translate3d(6px, 6px, 0); }
694
+ }
695
+
696
+ /* 5. Road Runner (등장: 왼쪽에서 탄력 있게 / 퇴장: 움츠렸다가 광속 탈출) */
697
+ :host(.roadRunner) dialog {
698
+ animation: roadRunnerIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
699
+ }
700
+
701
+ @keyframes roadRunnerIn {
702
+ 0% { transform: translateX(-1500px) skewX(30deg); opacity: 1; }
703
+ 70% { transform: translateX(30px) skewX(-10deg); opacity: 1; }
704
+ 100% { transform: translateX(0) skewX(0deg); opacity: 1; }
705
+ }
706
+
707
+ /* --- Out Animations (닫힐 때) --- */
708
+ dialog.out { pointer-events: none; }
709
+
710
+ /* Road Runner 퇴장: 슥 움츠렸다가(Anticipation) 쌩~! */
711
+ :host(.roadRunner) dialog.out {
712
+ animation: roadRunnerOut 0.5s cubic-bezier(0.6, -0.28, 0.735, 0.045) forwards;
713
+ }
714
+
715
+ @keyframes roadRunnerOut {
716
+ 0% {
717
+ transform: translateX(0) scale(1) skewX(0deg);
718
+ opacity: 1;
719
+ }
720
+ 30% {
721
+ /* 예비 동작: 뒤로 살짝 갔다가 움츠러들기 */
722
+ transform: translateX(50px) scaleX(1.2) scaleY(0.8) skewX(-20deg);
723
+ opacity: 1;
724
+ }
725
+ 100% {
726
+ /* 발사: 길게 늘어나며 광속 탈출 */
727
+ transform: translateX(2000px) scaleX(4) scaleY(0.3) skewX(50deg);
728
+ opacity: 0;
729
+ filter: blur(10px); /* 👈 잔상 느낌 추가 */
730
+ }
731
+ }
732
+
733
+ /* 일반 퇴장 (기본) */
734
+ dialog.out { animation: nx-fade-out 0.3s forwards; }
735
+ @keyframes nx-fade-out { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(0.9); } }
736
+ `;
737
+ class nineDialog extends HTMLElement {
738
+ constructor() {
739
+ super();
740
+ __privateAdd(this, _shift);
741
+ __privateAdd(this, _dialog);
742
+ __publicField(this, "showModal", () => {
743
+ var _a2, _b;
744
+ __privateGet(this, _dialog).showModal();
745
+ (_b = ((_a2 = this.shadowRoot) == null ? void 0 : _a2.activeElement) || document.activeElement) == null ? void 0 : _b.blur();
746
+ });
747
+ __publicField(this, "close", () => {
748
+ __privateGet(this, _dialog).close();
749
+ this.remove();
750
+ });
751
+ __privateAdd(this, _init, () => {
752
+ const head = this.querySelector(".head");
753
+ if (head) {
754
+ head.addEventListener("mousedown", __privateGet(this, _onMouseDown));
755
+ head.addEventListener("touchstart", __privateGet(this, _onTouchStart));
756
+ }
757
+ this.querySelectorAll(".close, .close2, .cancel").forEach((btn) => {
758
+ btn.onclick = () => this.closeWithAnimation(null);
759
+ });
760
+ this.querySelectorAll(".ok").forEach((btn) => {
761
+ });
762
+ });
763
+ // --- 드래그 로직 (Vanilla JS) ---
764
+ __privateAdd(this, _onMouseDown, (e) => {
765
+ if (e.target.closest("buttons")) return;
766
+ if (e.button !== 0 || e.altKey || e.ctrlKey || e.shiftKey) return;
767
+ const rect = __privateGet(this, _dialog).getBoundingClientRect();
768
+ __privateSet(this, _shift, {
769
+ x: e.clientX - rect.left,
770
+ y: e.clientY - rect.top
771
+ });
772
+ const onMouseMove = (ev) => {
773
+ __privateGet(this, _dialog).style.position = "fixed";
774
+ __privateGet(this, _dialog).style.margin = "0";
775
+ __privateGet(this, _dialog).style.left = `${ev.clientX - __privateGet(this, _shift).x}px`;
776
+ __privateGet(this, _dialog).style.top = `${ev.clientY - __privateGet(this, _shift).y}px`;
777
+ };
778
+ const onMouseUp = () => {
779
+ document.removeEventListener("mousemove", onMouseMove);
780
+ document.removeEventListener("mouseup", onMouseUp);
781
+ };
782
+ document.addEventListener("mousemove", onMouseMove);
783
+ document.addEventListener("mouseup", onMouseUp);
784
+ });
785
+ __privateAdd(this, _onTouchStart, (e) => {
786
+ if (e.target.closest("buttons")) return;
787
+ const rect = __privateGet(this, _dialog).getBoundingClientRect();
788
+ const touch = e.changedTouches[0];
789
+ __privateSet(this, _shift, {
790
+ x: touch.pageX - rect.left,
791
+ y: touch.pageY - rect.top
792
+ });
793
+ const onTouchMove = (ev) => {
794
+ const t = ev.changedTouches[0];
795
+ __privateGet(this, _dialog).style.position = "fixed";
796
+ __privateGet(this, _dialog).style.margin = "0";
797
+ __privateGet(this, _dialog).style.left = `${t.pageX - __privateGet(this, _shift).x}px`;
798
+ __privateGet(this, _dialog).style.top = `${t.pageY - __privateGet(this, _shift).y}px`;
799
+ };
800
+ const onTouchEnd = () => {
801
+ document.removeEventListener("touchmove", onTouchMove);
802
+ document.removeEventListener("touchend", onTouchEnd);
803
+ };
804
+ document.addEventListener("touchmove", onTouchMove);
805
+ document.addEventListener("touchend", onTouchEnd);
806
+ });
807
+ }
808
+ connectedCallback() {
809
+ const v = this.innerHTML;
810
+ const titleText = this.getAttribute("subject") || "Details";
811
+ trace$1.log(dialogStyles);
812
+ this.innerHTML = `
813
+ <style>${dialogStyles}</style>
814
+
815
+ <dialog>
816
+ <div class="head">
817
+ <div class="rect1"></div>
818
+ <div class="rect2"></div>
819
+ <div class="rect3"></div>
820
+ <ng-sphere class="icon" end-fill="#666" size="8"></ng-sphere>
821
+ <span class="title">${titleText}</span>
822
+ <span class="sub-title"></span>
823
+ <div class="buttons">
824
+ <ng-sphere class="apply" start-fill="#cc6" end-fill="#660" size="16" title="apply"></ng-sphere>
825
+ <ng-sphere class="reset" start-fill="#99f" end-fill="#00f" size="16" title="reset"></ng-sphere>
826
+ <ng-sphere class="close" start-fill="#f99" end-fill="#f00" size="16" title="close"></ng-sphere>
827
+ </div>
828
+ </div>
829
+ <div class="contents">
830
+ <div class="left">
831
+ <span>가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하</span>
832
+ </div>
833
+ <div class="body">
834
+ ${v}
835
+ </div>
836
+ <div class="close2">
837
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
838
+ <path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708"/>
839
+ </svg>
840
+ </div>
841
+ </div>
842
+ </dialog>
843
+ `;
844
+ __privateSet(this, _dialog, this.querySelector("dialog"));
845
+ __privateGet(this, _init).call(this);
846
+ }
847
+ closeWithAnimation(returnValue) {
848
+ __privateGet(this, _dialog).classList.add("out");
849
+ setTimeout(() => {
850
+ __privateGet(this, _dialog).close();
851
+ this.dispatchEvent(new CustomEvent("closed", { detail: returnValue }));
852
+ this.remove();
853
+ }, 300);
854
+ }
855
+ }
856
+ _shift = new WeakMap();
857
+ _dialog = new WeakMap();
858
+ _init = new WeakMap();
859
+ _onMouseDown = new WeakMap();
860
+ _onTouchStart = new WeakMap();
861
+ class BasePopup extends HTMLElement {
862
+ constructor() {
863
+ super();
864
+ this.attachShadow({ mode: "open" });
865
+ }
866
+ static async open(PopupClass, message, title, options, renderFn) {
867
+ var _a2, _b, _c;
868
+ const tagName = PopupClass.tagName.toLowerCase();
869
+ const config2 = {
870
+ "true-text": "확인",
871
+ "false-text": "취소",
872
+ class: "classic",
873
+ animation: "fade",
874
+ ...((_c = (_b = (_a2 = window.nine) == null ? void 0 : _a2.config) == null ? void 0 : _b.ux) == null ? void 0 : _c[tagName.replace("nine-", "").replace("-popup", "")]) || {},
875
+ ...options
876
+ };
877
+ document.querySelectorAll(tagName).forEach((el2) => el2.remove());
878
+ const el = document.createElement(tagName);
879
+ if (config2.class) el.classList.add(config2.class);
880
+ if (config2.animation) el.classList.add(config2.animation);
881
+ document.body.appendChild(el);
882
+ renderFn(el, message, config2);
883
+ const dialogComp = el.shadowRoot.querySelector("nine-dialog");
884
+ if (title) dialogComp.setAttribute("subject", title);
885
+ return new Promise((resolve) => {
886
+ dialogComp.addEventListener("closed", (e) => resolve(e.detail));
887
+ el.setupEvents(resolve, dialogComp);
888
+ dialogComp.showModal();
889
+ });
890
+ }
891
+ }
892
+ if (!customElements.get("nine-dialog")) {
893
+ customElements.define("nine-dialog", nineDialog);
894
+ }
895
+ const _nineConfirmPopup = class _nineConfirmPopup extends BasePopup {
896
+ constructor() {
897
+ super();
898
+ }
899
+ render(message, config2) {
900
+ this.shadowRoot.innerHTML = `
901
+ <nine-dialog>
902
+ <div class="msg">${message.replace(/\n/g, "<br/>")}</div>
903
+ <div class="buttons-confirm">
904
+ <button class="cancel">${config2["false-text"]}</button>
905
+ <button class="ok">${config2["true-text"]}</button>
906
+ </div>
907
+ </nine-dialog>`;
908
+ }
909
+ setupEvents(resolve, dialogComp) {
910
+ this.shadowRoot.querySelector(".ok").onclick = () => dialogComp.closeWithAnimation(true);
911
+ }
912
+ };
913
+ __publicField(_nineConfirmPopup, "tagName", "nine-confirm-popup");
914
+ __publicField(_nineConfirmPopup, "confirm", (m, t, o) => BasePopup.open(_nineConfirmPopup, m, t, o, (el, msg, conf) => el.render(msg, conf)));
915
+ let nineConfirmPopup = _nineConfirmPopup;
916
+ const _nineAlertPopup = class _nineAlertPopup extends BasePopup {
917
+ constructor() {
918
+ super();
919
+ }
920
+ render(message, config2) {
921
+ this.shadowRoot.innerHTML = `
922
+ <nine-dialog>
923
+ <div class="msg">${message.replace(/\n/g, "<br/>")}</div>
924
+ <div class="buttons-confirm">
925
+ <button class="cancel">확인</button>
926
+ </div>
927
+ </nine-dialog>`;
928
+ }
929
+ setupEvents(resolve, dialogComp) {
930
+ }
931
+ };
932
+ __publicField(_nineAlertPopup, "tagName", "nine-alert-popup");
933
+ __publicField(_nineAlertPopup, "alert", (m, t, o) => BasePopup.open(_nineAlertPopup, m, t, o, (el, msg, conf) => el.render(msg, conf)));
934
+ let nineAlertPopup = _nineAlertPopup;
935
+ if (!customElements.get("nine-confirm-popup")) customElements.define("nine-confirm-popup", nineConfirmPopup);
936
+ if (!customElements.get("nine-alert-popup")) customElements.define("nine-alert-popup", nineAlertPopup);
937
+ const _ninePromptPopup = class _ninePromptPopup extends BasePopup {
938
+ constructor() {
939
+ super();
940
+ }
941
+ render(message, config2) {
942
+ trace.log(this);
943
+ trace.log(this.shadowRoot);
944
+ this.shadowRoot.innerHTML = `
945
+ <style>
946
+ dialog {
947
+ height: 300px !important;
948
+ }
949
+ .msg {
950
+ height: unset !important;
951
+ }
952
+ </style>
953
+
954
+ <nine-dialog>
955
+ <div class="msg">${message.replace(/\n/g, "<br/>")}</div>
956
+ <div class="input-area">
957
+ <textarea placeholder="내용을 입력하세요..."></textarea>
958
+ </div>
959
+ <div class="buttons-confirm">
960
+ <button class="cancel">${config2["false-text"]}</button>
961
+ <button class="ok">${config2["true-text"]}</button>
962
+ </div>
963
+ </nine-dialog>`;
964
+ }
965
+ setupEvents(resolve, dialogComp) {
966
+ const textarea = this.shadowRoot.querySelector("textarea");
967
+ const okBtn = this.shadowRoot.querySelector(".ok");
968
+ okBtn.onclick = () => dialogComp.closeWithAnimation(textarea.value);
969
+ requestAnimationFrame(() => textarea.focus());
970
+ }
971
+ };
972
+ __publicField(_ninePromptPopup, "tagName", "nine-prompt-popup");
973
+ __publicField(_ninePromptPopup, "prompt", (m, t, o) => BasePopup.open(_ninePromptPopup, m, t, o, (el, msg, conf) => el.render(msg, conf)));
974
+ let ninePromptPopup = _ninePromptPopup;
975
+ if (!customElements.get("nine-prompt-popup")) {
976
+ customElements.define("nine-prompt-popup", ninePromptPopup);
977
+ }
978
+ const safe = async (promise) => {
979
+ try {
980
+ const data = await promise;
981
+ return [data, null];
982
+ } catch (err) {
983
+ return [null, err];
984
+ }
985
+ };
986
+ class NineUxUtil {
987
+ constructor() {
988
+ __privateAdd(this, _NineUxUtil_instances);
989
+ __publicField(this, "alert", (message, title = "Alert") => {
990
+ return __privateMethod(this, _NineUxUtil_instances, prepare_fn).call(this, "alert", message, title, "classic");
991
+ });
992
+ __publicField(this, "confirm", (message, title = "Confirm") => {
993
+ return __privateMethod(this, _NineUxUtil_instances, prepare_fn).call(this, "confirm", message, title, "classic");
994
+ });
995
+ __publicField(this, "prompt", (message, title = "Prompt") => {
996
+ return __privateMethod(this, _NineUxUtil_instances, prepare_fn).call(this, "prompt", message, title, "classic");
997
+ });
998
+ }
999
+ }
1000
+ _NineUxUtil_instances = new WeakSet();
1001
+ /**
1002
+ * 팝업 준비 로직 (Private 메서드)
1003
+ */
1004
+ prepare_fn = function(type, message, title, defaultClass) {
1005
+ const options = { class: defaultClass, animation: "fade" };
1006
+ let isExecuted = false;
1007
+ const popupMap = {
1008
+ alert: nineAlertPopup,
1009
+ confirm: nineConfirmPopup,
1010
+ prompt: ninePromptPopup
1011
+ };
1012
+ const popup = popupMap[type];
1013
+ const runner = {
1014
+ rgb: () => {
1015
+ options.class = "rgb";
1016
+ return runner;
1017
+ },
1018
+ classic: () => {
1019
+ options.class = "classic";
1020
+ return runner;
1021
+ },
1022
+ shake: () => {
1023
+ options.animation = "shake";
1024
+ return runner;
1025
+ },
1026
+ run: () => {
1027
+ options.animation = "roadRunner";
1028
+ return runner;
1029
+ },
1030
+ zoom: () => {
1031
+ options.animation = "zoom";
1032
+ return runner;
1033
+ },
1034
+ then: (resolve, reject) => {
1035
+ isExecuted = true;
1036
+ return popup[type](message, title, options).then(resolve, reject);
1037
+ }
1038
+ };
1039
+ Promise.resolve().then(() => {
1040
+ if (!isExecuted) {
1041
+ isExecuted = true;
1042
+ popup[type](message, title, options);
1043
+ }
1044
+ });
1045
+ return runner;
1046
+ };
1047
+ // static 필드는 클래스 자체에 저장됨
1048
+ __publicField(NineUxUtil, "cssPath", "");
1049
+ Object.assign(nine$1, new NineUxUtil());
1050
+ class UxSplitter extends HTMLElement {
1051
+ constructor() {
1052
+ super();
1053
+ __privateAdd(this, _mode);
1054
+ __privateAdd(this, _detectMode, (el) => {
1055
+ const prev = el.previousElementSibling;
1056
+ const next = el.nextElementSibling;
1057
+ if (!prev || !next) {
1058
+ __privateSet(this, _mode, this.classList.contains("h") ? "h" : "v");
1059
+ return;
1060
+ }
1061
+ const prevRect = prev.getBoundingClientRect();
1062
+ const nextRect = next.getBoundingClientRect();
1063
+ if (this.classList.contains("h")) {
1064
+ __privateSet(this, _mode, "h");
1065
+ } else if (this.classList.contains("v")) {
1066
+ __privateSet(this, _mode, "v");
1067
+ } else {
1068
+ __privateSet(this, _mode, Math.abs(prevRect.top - nextRect.top) < 5 ? "h" : "v");
1069
+ }
1070
+ });
1071
+ __privateAdd(this, _startDrag, (e) => {
1072
+ e.preventDefault();
1073
+ e.stopPropagation();
1074
+ const splitterRect = this.getBoundingClientRect();
1075
+ const isHorizontal = __privateGet(this, _mode) === "h";
1076
+ const clickOffset = isHorizontal ? e.clientX - splitterRect.left : e.clientY - splitterRect.top;
1077
+ const dragBar = document.createElement("div");
1078
+ dragBar.className = `nx-splitter-drag-bar-${__privateGet(this, _mode)}`;
1079
+ Object.assign(dragBar.style, {
1080
+ position: "absolute",
1081
+ zIndex: "999",
1082
+ background: "#666",
1083
+ opacity: "0.6",
1084
+ pointerEvents: "none"
1085
+ });
1086
+ const root = this.getRootNode({ composed: true });
1087
+ const parent = root instanceof ShadowRoot ? root.host : this.parentElement;
1088
+ const prev = this.previousElementSibling;
1089
+ const next = this.nextElementSibling;
1090
+ if (!parent || !prev || !next) {
1091
+ trace$1.warn("Spliter's parent or siblings not found.");
1092
+ return;
1093
+ }
1094
+ (parent.shadowRoot || parent).appendChild(dragBar);
1095
+ const dragBarOffsetParentRect = dragBar.offsetParent.getBoundingClientRect();
1096
+ const prevRect = prev.getBoundingClientRect();
1097
+ const nextRect = next.getBoundingClientRect();
1098
+ const initialSplitterPosInParent = (isHorizontal ? splitterRect.left - dragBarOffsetParentRect.left : splitterRect.top - dragBarOffsetParentRect.top) + clickOffset;
1099
+ if (isHorizontal) {
1100
+ dragBar.style.top = "0";
1101
+ dragBar.style.left = `${initialSplitterPosInParent}px`;
1102
+ dragBar.style.width = "2px";
1103
+ dragBar.style.height = "100%";
1104
+ } else {
1105
+ dragBar.style.left = "0";
1106
+ dragBar.style.top = `${initialSplitterPosInParent}px`;
1107
+ dragBar.style.height = "2px";
1108
+ dragBar.style.width = "100%";
1109
+ }
1110
+ dragBar.style.mixBlendMode = "difference";
1111
+ dragBar.style.zIndex = "99999";
1112
+ const minLimit = isHorizontal ? prevRect.left - dragBarOffsetParentRect.left : prevRect.top - dragBarOffsetParentRect.top;
1113
+ const maxLimit = isHorizontal ? nextRect.right - dragBarOffsetParentRect.left - splitterRect.width : nextRect.bottom - dragBarOffsetParentRect.top - splitterRect.height;
1114
+ const onMove = (moveEvent) => {
1115
+ const clientPos = isHorizontal ? moveEvent.clientX : moveEvent.clientY;
1116
+ const currentPosInParent = isHorizontal ? clientPos - dragBarOffsetParentRect.left : clientPos - dragBarOffsetParentRect.top;
1117
+ const clampedPos = Math.max(minLimit, Math.min(currentPosInParent, maxLimit));
1118
+ if (isHorizontal) {
1119
+ dragBar.style.left = `${clampedPos}px`;
1120
+ } else {
1121
+ dragBar.style.top = `${clampedPos}px`;
1122
+ }
1123
+ };
1124
+ const onUp = () => {
1125
+ window.removeEventListener("mousemove", onMove);
1126
+ window.removeEventListener("mouseup", onUp);
1127
+ dragBar.remove();
1128
+ const allChildren = Array.from(parent.children);
1129
+ const allPanels = allChildren.filter((el) => el.tagName.toLowerCase() !== "nx-splitter");
1130
+ const style = window.getComputedStyle(parent);
1131
+ const gapValue = isHorizontal ? style.getPropertyValue("column-gap") : style.getPropertyValue("row-gap");
1132
+ const gapSize = parseFloat(gapValue) || 0;
1133
+ const gapCount = allChildren.length > 1 ? allChildren.length - 1 : 0;
1134
+ const totalGapSize = gapCount * gapSize;
1135
+ const finalDragBarPos = isHorizontal ? parseFloat(dragBar.style.left) : parseFloat(dragBar.style.top);
1136
+ const dragOffset = finalDragBarPos - initialSplitterPosInParent;
1137
+ const prevSize = isHorizontal ? prev.getBoundingClientRect().width : prev.getBoundingClientRect().height;
1138
+ const nextSize = isHorizontal ? next.getBoundingClientRect().width : next.getBoundingClientRect().height;
1139
+ let newPrevSize = prevSize + dragOffset;
1140
+ let newNextSize = nextSize - dragOffset;
1141
+ if (newPrevSize < 0) {
1142
+ newNextSize += newPrevSize;
1143
+ newPrevSize = 0;
1144
+ }
1145
+ if (newNextSize < 0) {
1146
+ newPrevSize += newNextSize;
1147
+ newNextSize = 0;
1148
+ }
1149
+ const initialSizes = allPanels.map((panel) => isHorizontal ? panel.getBoundingClientRect().width : panel.getBoundingClientRect().height);
1150
+ const totalSplitterSize = allChildren.reduce((sum, child) => {
1151
+ if (child.tagName.toLowerCase() === "nx-splitter") {
1152
+ return sum + (isHorizontal ? child.getBoundingClientRect().width : child.getBoundingClientRect().height);
1153
+ }
1154
+ return sum;
1155
+ }, 0);
1156
+ const totalContainerSize = isHorizontal ? parent.getBoundingClientRect().width : parent.getBoundingClientRect().height;
1157
+ const totalFlexSpace = totalContainerSize - totalSplitterSize - totalGapSize;
1158
+ let flexSum = 0;
1159
+ allPanels.forEach((panel, index) => {
1160
+ let newSize;
1161
+ if (panel === prev) {
1162
+ newSize = newPrevSize;
1163
+ } else if (panel === next) {
1164
+ newSize = newNextSize;
1165
+ } else {
1166
+ newSize = initialSizes[index];
1167
+ }
1168
+ const newFlexBasis = newSize / totalFlexSpace;
1169
+ trace$1.log(panel);
1170
+ if (panel.classList.contains("sidebar")) {
1171
+ panel.style.flex = `0 0 ${newSize}px`;
1172
+ } else {
1173
+ panel.style.flex = `${newFlexBasis} ${newFlexBasis} 0`;
1174
+ }
1175
+ flexSum += newFlexBasis;
1176
+ });
1177
+ trace$1.log(`dragOffset: ${dragOffset}`);
1178
+ trace$1.log(`Calculated FlexSum: ${flexSum}`);
1179
+ };
1180
+ window.addEventListener("mousemove", onMove);
1181
+ window.addEventListener("mouseup", onUp);
1182
+ });
1183
+ __privateAdd(this, _init2, () => {
1184
+ __privateGet(this, _detectMode).call(this, this);
1185
+ this.classList.add(__privateGet(this, _mode));
1186
+ const contents = this.innerHTML.trim();
1187
+ const gripTmpl = contents === "" ? `<div class="grip"></div>` : `<div class="grip"></div><div class="inner-container">${contents}</div><div class="grip"></div>`;
1188
+ this.innerHTML = "";
1189
+ const htmlTmpl = document.createElement("template");
1190
+ htmlTmpl.innerHTML = `
1191
+ <style>
1192
+ @import "https://cdn.jsdelivr.net/npm/@nine-lab/nine-util@${"0.9.170"}/dist/css/nine-util.css";
1193
+ ${this.cssPath ? `@import "${this.cssPath}";` : ""}
1194
+ </style>
1195
+ ${gripTmpl}
1196
+ `;
1197
+ this.shadowRoot.appendChild(htmlTmpl.content.cloneNode(true));
1198
+ this.shadowRoot.querySelectorAll(".grip").forEach((el) => {
1199
+ el.addEventListener("mousedown", (e) => __privateGet(this, _startDrag).call(this, e));
1200
+ });
1201
+ __privateGet(this, _prepareLayout).call(this);
1202
+ window.addEventListener("resize", () => __privateGet(this, _prepareLayout).call(this));
1203
+ });
1204
+ __privateAdd(this, _prepareLayout, () => {
1205
+ const isHorizontal = __privateGet(this, _mode) === "h";
1206
+ const parent = this.parentElement;
1207
+ const allPanels = Array.from(parent.children).filter((el) => el.tagName.toLowerCase() !== "nx-splitter");
1208
+ if (allPanels.length < 2) return;
1209
+ const parentRect = parent.getBoundingClientRect();
1210
+ const totalContentSize = allPanels.reduce((sum, el) => {
1211
+ const size = isHorizontal ? el.getBoundingClientRect().width : el.getBoundingClientRect().height;
1212
+ return sum + size;
1213
+ }, 0);
1214
+ const totalParentSize = isHorizontal ? parentRect.width : parentRect.height;
1215
+ allPanels.forEach((panel) => {
1216
+ const size = isHorizontal ? panel.getBoundingClientRect().width : panel.getBoundingClientRect().height;
1217
+ const newSize = totalParentSize * (size / totalContentSize);
1218
+ const flexGrow = newSize / totalParentSize;
1219
+ panel.style.flex = `${flexGrow} ${flexGrow} 0`;
1220
+ });
1221
+ });
1222
+ this.attachShadow({ mode: "open" });
1223
+ }
1224
+ connectedCallback() {
1225
+ __privateGet(this, _init2).call(this);
1226
+ }
1227
+ get cssPath() {
1228
+ return this.getAttribute("css-path") || NineUxUtil.cssPath;
1229
+ }
1230
+ }
1231
+ _mode = new WeakMap();
1232
+ _detectMode = new WeakMap();
1233
+ _startDrag = new WeakMap();
1234
+ _init2 = new WeakMap();
1235
+ _prepareLayout = new WeakMap();
1236
+ if (!customElements.get("nine-splitter")) {
1237
+ customElements.define("nine-splitter", UxSplitter);
1238
+ }
1239
+ function getDefaultExportFromCjs(x) {
1240
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
1241
+ }
1242
+ var dayjs_min$1 = { exports: {} };
1243
+ var dayjs_min = dayjs_min$1.exports;
1244
+ var hasRequiredDayjs_min;
1245
+ function requireDayjs_min() {
1246
+ if (hasRequiredDayjs_min) return dayjs_min$1.exports;
1247
+ hasRequiredDayjs_min = 1;
1248
+ (function(module, exports$1) {
1249
+ !(function(t, e) {
1250
+ module.exports = e();
1251
+ })(dayjs_min, (function() {
1252
+ var t = 1e3, e = 6e4, n = 36e5, r = "millisecond", i = "second", s = "minute", u = "hour", a = "day", o = "week", c = "month", f = "quarter", h = "year", d = "date", l = "Invalid Date", $ = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/, y = /\[([^\]]+)]|YYYY|YY|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g, M = { name: "en", weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), ordinal: function(t2) {
1253
+ var e2 = ["th", "st", "nd", "rd"], n2 = t2 % 100;
1254
+ return "[" + t2 + (e2[(n2 - 20) % 10] || e2[n2] || e2[0]) + "]";
1255
+ } }, m = function(t2, e2, n2) {
1256
+ var r2 = String(t2);
1257
+ return !r2 || r2.length >= e2 ? t2 : "" + Array(e2 + 1 - r2.length).join(n2) + t2;
1258
+ }, v = { s: m, z: function(t2) {
1259
+ var e2 = -t2.utcOffset(), n2 = Math.abs(e2), r2 = Math.floor(n2 / 60), i2 = n2 % 60;
1260
+ return (e2 <= 0 ? "+" : "-") + m(r2, 2, "0") + ":" + m(i2, 2, "0");
1261
+ }, m: function t2(e2, n2) {
1262
+ if (e2.date() < n2.date()) return -t2(n2, e2);
1263
+ var r2 = 12 * (n2.year() - e2.year()) + (n2.month() - e2.month()), i2 = e2.clone().add(r2, c), s2 = n2 - i2 < 0, u2 = e2.clone().add(r2 + (s2 ? -1 : 1), c);
1264
+ return +(-(r2 + (n2 - i2) / (s2 ? i2 - u2 : u2 - i2)) || 0);
1265
+ }, a: function(t2) {
1266
+ return t2 < 0 ? Math.ceil(t2) || 0 : Math.floor(t2);
1267
+ }, p: function(t2) {
1268
+ return { M: c, y: h, w: o, d: a, D: d, h: u, m: s, s: i, ms: r, Q: f }[t2] || String(t2 || "").toLowerCase().replace(/s$/, "");
1269
+ }, u: function(t2) {
1270
+ return void 0 === t2;
1271
+ } }, g = "en", D = {};
1272
+ D[g] = M;
1273
+ var p = "$isDayjsObject", S = function(t2) {
1274
+ return t2 instanceof _ || !(!t2 || !t2[p]);
1275
+ }, w = function t2(e2, n2, r2) {
1276
+ var i2;
1277
+ if (!e2) return g;
1278
+ if ("string" == typeof e2) {
1279
+ var s2 = e2.toLowerCase();
1280
+ D[s2] && (i2 = s2), n2 && (D[s2] = n2, i2 = s2);
1281
+ var u2 = e2.split("-");
1282
+ if (!i2 && u2.length > 1) return t2(u2[0]);
1283
+ } else {
1284
+ var a2 = e2.name;
1285
+ D[a2] = e2, i2 = a2;
1286
+ }
1287
+ return !r2 && i2 && (g = i2), i2 || !r2 && g;
1288
+ }, O = function(t2, e2) {
1289
+ if (S(t2)) return t2.clone();
1290
+ var n2 = "object" == typeof e2 ? e2 : {};
1291
+ return n2.date = t2, n2.args = arguments, new _(n2);
1292
+ }, b = v;
1293
+ b.l = w, b.i = S, b.w = function(t2, e2) {
1294
+ return O(t2, { locale: e2.$L, utc: e2.$u, x: e2.$x, $offset: e2.$offset });
1295
+ };
1296
+ var _ = (function() {
1297
+ function M2(t2) {
1298
+ this.$L = w(t2.locale, null, true), this.parse(t2), this.$x = this.$x || t2.x || {}, this[p] = true;
1299
+ }
1300
+ var m2 = M2.prototype;
1301
+ return m2.parse = function(t2) {
1302
+ this.$d = (function(t3) {
1303
+ var e2 = t3.date, n2 = t3.utc;
1304
+ if (null === e2) return /* @__PURE__ */ new Date(NaN);
1305
+ if (b.u(e2)) return /* @__PURE__ */ new Date();
1306
+ if (e2 instanceof Date) return new Date(e2);
1307
+ if ("string" == typeof e2 && !/Z$/i.test(e2)) {
1308
+ var r2 = e2.match($);
1309
+ if (r2) {
1310
+ var i2 = r2[2] - 1 || 0, s2 = (r2[7] || "0").substring(0, 3);
1311
+ return n2 ? new Date(Date.UTC(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2)) : new Date(r2[1], i2, r2[3] || 1, r2[4] || 0, r2[5] || 0, r2[6] || 0, s2);
1312
+ }
1313
+ }
1314
+ return new Date(e2);
1315
+ })(t2), this.init();
1316
+ }, m2.init = function() {
1317
+ var t2 = this.$d;
1318
+ this.$y = t2.getFullYear(), this.$M = t2.getMonth(), this.$D = t2.getDate(), this.$W = t2.getDay(), this.$H = t2.getHours(), this.$m = t2.getMinutes(), this.$s = t2.getSeconds(), this.$ms = t2.getMilliseconds();
1319
+ }, m2.$utils = function() {
1320
+ return b;
1321
+ }, m2.isValid = function() {
1322
+ return !(this.$d.toString() === l);
1323
+ }, m2.isSame = function(t2, e2) {
1324
+ var n2 = O(t2);
1325
+ return this.startOf(e2) <= n2 && n2 <= this.endOf(e2);
1326
+ }, m2.isAfter = function(t2, e2) {
1327
+ return O(t2) < this.startOf(e2);
1328
+ }, m2.isBefore = function(t2, e2) {
1329
+ return this.endOf(e2) < O(t2);
1330
+ }, m2.$g = function(t2, e2, n2) {
1331
+ return b.u(t2) ? this[e2] : this.set(n2, t2);
1332
+ }, m2.unix = function() {
1333
+ return Math.floor(this.valueOf() / 1e3);
1334
+ }, m2.valueOf = function() {
1335
+ return this.$d.getTime();
1336
+ }, m2.startOf = function(t2, e2) {
1337
+ var n2 = this, r2 = !!b.u(e2) || e2, f2 = b.p(t2), l2 = function(t3, e3) {
1338
+ var i2 = b.w(n2.$u ? Date.UTC(n2.$y, e3, t3) : new Date(n2.$y, e3, t3), n2);
1339
+ return r2 ? i2 : i2.endOf(a);
1340
+ }, $2 = function(t3, e3) {
1341
+ return b.w(n2.toDate()[t3].apply(n2.toDate("s"), (r2 ? [0, 0, 0, 0] : [23, 59, 59, 999]).slice(e3)), n2);
1342
+ }, y2 = this.$W, M3 = this.$M, m3 = this.$D, v2 = "set" + (this.$u ? "UTC" : "");
1343
+ switch (f2) {
1344
+ case h:
1345
+ return r2 ? l2(1, 0) : l2(31, 11);
1346
+ case c:
1347
+ return r2 ? l2(1, M3) : l2(0, M3 + 1);
1348
+ case o:
1349
+ var g2 = this.$locale().weekStart || 0, D2 = (y2 < g2 ? y2 + 7 : y2) - g2;
1350
+ return l2(r2 ? m3 - D2 : m3 + (6 - D2), M3);
1351
+ case a:
1352
+ case d:
1353
+ return $2(v2 + "Hours", 0);
1354
+ case u:
1355
+ return $2(v2 + "Minutes", 1);
1356
+ case s:
1357
+ return $2(v2 + "Seconds", 2);
1358
+ case i:
1359
+ return $2(v2 + "Milliseconds", 3);
1360
+ default:
1361
+ return this.clone();
1362
+ }
1363
+ }, m2.endOf = function(t2) {
1364
+ return this.startOf(t2, false);
1365
+ }, m2.$set = function(t2, e2) {
1366
+ var n2, o2 = b.p(t2), f2 = "set" + (this.$u ? "UTC" : ""), l2 = (n2 = {}, n2[a] = f2 + "Date", n2[d] = f2 + "Date", n2[c] = f2 + "Month", n2[h] = f2 + "FullYear", n2[u] = f2 + "Hours", n2[s] = f2 + "Minutes", n2[i] = f2 + "Seconds", n2[r] = f2 + "Milliseconds", n2)[o2], $2 = o2 === a ? this.$D + (e2 - this.$W) : e2;
1367
+ if (o2 === c || o2 === h) {
1368
+ var y2 = this.clone().set(d, 1);
1369
+ y2.$d[l2]($2), y2.init(), this.$d = y2.set(d, Math.min(this.$D, y2.daysInMonth())).$d;
1370
+ } else l2 && this.$d[l2]($2);
1371
+ return this.init(), this;
1372
+ }, m2.set = function(t2, e2) {
1373
+ return this.clone().$set(t2, e2);
1374
+ }, m2.get = function(t2) {
1375
+ return this[b.p(t2)]();
1376
+ }, m2.add = function(r2, f2) {
1377
+ var d2, l2 = this;
1378
+ r2 = Number(r2);
1379
+ var $2 = b.p(f2), y2 = function(t2) {
1380
+ var e2 = O(l2);
1381
+ return b.w(e2.date(e2.date() + Math.round(t2 * r2)), l2);
1382
+ };
1383
+ if ($2 === c) return this.set(c, this.$M + r2);
1384
+ if ($2 === h) return this.set(h, this.$y + r2);
1385
+ if ($2 === a) return y2(1);
1386
+ if ($2 === o) return y2(7);
1387
+ var M3 = (d2 = {}, d2[s] = e, d2[u] = n, d2[i] = t, d2)[$2] || 1, m3 = this.$d.getTime() + r2 * M3;
1388
+ return b.w(m3, this);
1389
+ }, m2.subtract = function(t2, e2) {
1390
+ return this.add(-1 * t2, e2);
1391
+ }, m2.format = function(t2) {
1392
+ var e2 = this, n2 = this.$locale();
1393
+ if (!this.isValid()) return n2.invalidDate || l;
1394
+ var r2 = t2 || "YYYY-MM-DDTHH:mm:ssZ", i2 = b.z(this), s2 = this.$H, u2 = this.$m, a2 = this.$M, o2 = n2.weekdays, c2 = n2.months, f2 = n2.meridiem, h2 = function(t3, n3, i3, s3) {
1395
+ return t3 && (t3[n3] || t3(e2, r2)) || i3[n3].slice(0, s3);
1396
+ }, d2 = function(t3) {
1397
+ return b.s(s2 % 12 || 12, t3, "0");
1398
+ }, $2 = f2 || function(t3, e3, n3) {
1399
+ var r3 = t3 < 12 ? "AM" : "PM";
1400
+ return n3 ? r3.toLowerCase() : r3;
1401
+ };
1402
+ return r2.replace(y, (function(t3, r3) {
1403
+ return r3 || (function(t4) {
1404
+ switch (t4) {
1405
+ case "YY":
1406
+ return String(e2.$y).slice(-2);
1407
+ case "YYYY":
1408
+ return b.s(e2.$y, 4, "0");
1409
+ case "M":
1410
+ return a2 + 1;
1411
+ case "MM":
1412
+ return b.s(a2 + 1, 2, "0");
1413
+ case "MMM":
1414
+ return h2(n2.monthsShort, a2, c2, 3);
1415
+ case "MMMM":
1416
+ return h2(c2, a2);
1417
+ case "D":
1418
+ return e2.$D;
1419
+ case "DD":
1420
+ return b.s(e2.$D, 2, "0");
1421
+ case "d":
1422
+ return String(e2.$W);
1423
+ case "dd":
1424
+ return h2(n2.weekdaysMin, e2.$W, o2, 2);
1425
+ case "ddd":
1426
+ return h2(n2.weekdaysShort, e2.$W, o2, 3);
1427
+ case "dddd":
1428
+ return o2[e2.$W];
1429
+ case "H":
1430
+ return String(s2);
1431
+ case "HH":
1432
+ return b.s(s2, 2, "0");
1433
+ case "h":
1434
+ return d2(1);
1435
+ case "hh":
1436
+ return d2(2);
1437
+ case "a":
1438
+ return $2(s2, u2, true);
1439
+ case "A":
1440
+ return $2(s2, u2, false);
1441
+ case "m":
1442
+ return String(u2);
1443
+ case "mm":
1444
+ return b.s(u2, 2, "0");
1445
+ case "s":
1446
+ return String(e2.$s);
1447
+ case "ss":
1448
+ return b.s(e2.$s, 2, "0");
1449
+ case "SSS":
1450
+ return b.s(e2.$ms, 3, "0");
1451
+ case "Z":
1452
+ return i2;
1453
+ }
1454
+ return null;
1455
+ })(t3) || i2.replace(":", "");
1456
+ }));
1457
+ }, m2.utcOffset = function() {
1458
+ return 15 * -Math.round(this.$d.getTimezoneOffset() / 15);
1459
+ }, m2.diff = function(r2, d2, l2) {
1460
+ var $2, y2 = this, M3 = b.p(d2), m3 = O(r2), v2 = (m3.utcOffset() - this.utcOffset()) * e, g2 = this - m3, D2 = function() {
1461
+ return b.m(y2, m3);
1462
+ };
1463
+ switch (M3) {
1464
+ case h:
1465
+ $2 = D2() / 12;
1466
+ break;
1467
+ case c:
1468
+ $2 = D2();
1469
+ break;
1470
+ case f:
1471
+ $2 = D2() / 3;
1472
+ break;
1473
+ case o:
1474
+ $2 = (g2 - v2) / 6048e5;
1475
+ break;
1476
+ case a:
1477
+ $2 = (g2 - v2) / 864e5;
1478
+ break;
1479
+ case u:
1480
+ $2 = g2 / n;
1481
+ break;
1482
+ case s:
1483
+ $2 = g2 / e;
1484
+ break;
1485
+ case i:
1486
+ $2 = g2 / t;
1487
+ break;
1488
+ default:
1489
+ $2 = g2;
1490
+ }
1491
+ return l2 ? $2 : b.a($2);
1492
+ }, m2.daysInMonth = function() {
1493
+ return this.endOf(c).$D;
1494
+ }, m2.$locale = function() {
1495
+ return D[this.$L];
1496
+ }, m2.locale = function(t2, e2) {
1497
+ if (!t2) return this.$L;
1498
+ var n2 = this.clone(), r2 = w(t2, e2, true);
1499
+ return r2 && (n2.$L = r2), n2;
1500
+ }, m2.clone = function() {
1501
+ return b.w(this.$d, this);
1502
+ }, m2.toDate = function() {
1503
+ return new Date(this.valueOf());
1504
+ }, m2.toJSON = function() {
1505
+ return this.isValid() ? this.toISOString() : null;
1506
+ }, m2.toISOString = function() {
1507
+ return this.$d.toISOString();
1508
+ }, m2.toString = function() {
1509
+ return this.$d.toUTCString();
1510
+ }, M2;
1511
+ })(), Y = _.prototype;
1512
+ return O.prototype = Y, [["$ms", r], ["$s", i], ["$m", s], ["$H", u], ["$W", a], ["$M", c], ["$y", h], ["$D", d]].forEach((function(t2) {
1513
+ Y[t2[1]] = function(e2) {
1514
+ return this.$g(e2, t2[0], t2[1]);
1515
+ };
1516
+ })), O.extend = function(t2, e2) {
1517
+ return t2.$i || (t2(e2, _, O), t2.$i = true), O;
1518
+ }, O.locale = w, O.isDayjs = S, O.unix = function(t2) {
1519
+ return O(1e3 * t2);
1520
+ }, O.en = D[g], O.Ls = D, O.p = {}, O;
1521
+ }));
1522
+ })(dayjs_min$1);
1523
+ return dayjs_min$1.exports;
1524
+ }
1525
+ var dayjs_minExports = requireDayjs_min();
1526
+ const dayjs = /* @__PURE__ */ getDefaultExportFromCjs(dayjs_minExports);
1527
+ class NineUtil {
1528
+ constructor() {
1529
+ // static 필드는 클래스 자체에 저장됨
1530
+ __publicField(this, "formatDate", (v, fmt) => {
1531
+ return dayjs(v).format(fmt);
1532
+ });
1533
+ }
1534
+ }
1535
+ Object.assign(nine$1, new NineUtil());
1536
+ nine$1.safe = safe;
1537
+ nine$1.api = api;
1538
+ nine$1.trace = trace$2;
1539
+ nine$1.subscribeConfig = subscribeConfig;
1540
+ nine$1.config = config || {};
1541
+ if (typeof window !== "undefined") {
1542
+ window.nine = nine$1;
1543
+ }
1544
+ export {
1545
+ Fetch,
1546
+ TaskDebouncer,
1547
+ Trace$1 as Trace,
1548
+ api,
1549
+ config,
1550
+ Loading as loading,
1551
+ nine$1 as nine,
1552
+ nineAlertPopup,
1553
+ nineConfirmPopup,
1554
+ nineDialog,
1555
+ ninePromptPopup,
1556
+ subscribeConfig,
1557
+ trace$2 as trace
1558
+ };
1559
+ //# sourceMappingURL=nine-util.js.map