@dooboostore/dom-render 1.0.114 → 1.0.115

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.
@@ -28,9 +28,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  mod
29
29
  ));
30
30
 
31
- // ../../node_modules/.pnpm/reflect-metadata@0.2.2/node_modules/reflect-metadata/Reflect.js
31
+ // ../../../node_modules/.pnpm/reflect-metadata@0.2.2/node_modules/reflect-metadata/Reflect.js
32
32
  var require_Reflect = __commonJS({
33
- "../../node_modules/.pnpm/reflect-metadata@0.2.2/node_modules/reflect-metadata/Reflect.js"() {
33
+ "../../../node_modules/.pnpm/reflect-metadata@0.2.2/node_modules/reflect-metadata/Reflect.js"() {
34
34
  var Reflect2;
35
35
  (function(Reflect3) {
36
36
  (function(factory) {
@@ -1232,6 +1232,7 @@ __export(esm_exports, {
1232
1232
  Fetcher: () => Fetcher,
1233
1233
  FormValidator: () => FormValidator,
1234
1234
  FunctionUtils: () => FunctionUtils,
1235
+ HashUtils: () => HashUtils,
1235
1236
  HttpFetcher: () => HttpFetcher,
1236
1237
  HttpJsonFetcher: () => HttpJsonFetcher,
1237
1238
  HttpResponseError: () => HttpResponseError,
@@ -1312,6 +1313,7 @@ __export(esm_exports, {
1312
1313
  isCssCommentItem: () => isCssCommentItem,
1313
1314
  isCssDeclarationItem: () => isCssDeclarationItem,
1314
1315
  isCssRuleItem: () => isCssRuleItem,
1316
+ isDefined: () => isDefined,
1315
1317
  isHttpResponseError: () => isHttpResponseError,
1316
1318
  isPoint2DType: () => isPoint2DType,
1317
1319
  isPoint3DType: () => isPoint3DType,
@@ -1357,6 +1359,12 @@ var ValidUtils;
1357
1359
  return false;
1358
1360
  }
1359
1361
  };
1362
+ ValidUtils22.isGenerator = (value) => {
1363
+ return value !== null && typeof value === "object" && typeof value.next === "function" && typeof value[Symbol.iterator] === "function";
1364
+ };
1365
+ ValidUtils22.isAsyncGenerator = (value) => {
1366
+ return value !== null && typeof value === "object" && typeof value.next === "function" && typeof value[Symbol.asyncIterator] === "function";
1367
+ };
1360
1368
  ValidUtils22.isFrozen = (obj) => {
1361
1369
  return Object.isFrozen(obj);
1362
1370
  };
@@ -3271,6 +3279,12 @@ var Vector = class _Vector {
3271
3279
  this.z = z ?? 0;
3272
3280
  }
3273
3281
  }
3282
+ /**
3283
+ * 성분 대입 (파괴적). 벡터 전달 시 그 성분을 복사.
3284
+ * @example
3285
+ * v.set(1, 2, 3); // v = (1, 2, 3)
3286
+ * v.set(otherVector); // v = other와 동일 성분
3287
+ */
3274
3288
  set(v, y = 0, z = 0) {
3275
3289
  if (v instanceof _Vector || v instanceof Point3D) {
3276
3290
  this.set(v.x || 0, v.y || 0, v.z || 0);
@@ -3281,16 +3295,45 @@ var Vector = class _Vector {
3281
3295
  }
3282
3296
  return this;
3283
3297
  }
3298
+ /**
3299
+ * 복사본 반환 (비파괴). 파괴적 메서드와 조합해 원본 보존용.
3300
+ * @example
3301
+ * const s = a.get(); s.add(b); // s = a+b, a는 그대로
3302
+ */
3284
3303
  get() {
3285
3304
  return new _Vector(this.x, this.y, this.z);
3286
3305
  }
3287
- // 피타고라스의 정리는 a의 제곱 더하기 b 의 제곱은 c 의 제곱과 같다는 것을 정의합니다.
3288
- mag() {
3306
+ /**
3307
+ * 노름(norm). 평평한 공간(유클리드 공간)에서의 직선 거리.
3308
+ * - 수식: ‖v‖ = √(x² + y² + z²)
3309
+ * - 2D에서는 피타고라스 정리 그 자체. 3D는 두 번 적용한 것과 같음.
3310
+ * (바닥 대각선 √(x²+y²) → 공간 대각선 √((바닥)²+z²))
3311
+ * - "유클리드"는 평평한 공간의 기하학을 말함 (좌표계는 데카르트의 것, 유클리드는 좌표 없이 기하학을 세움).
3312
+ * 휘어진 공간(구면·쌍곡)에서는 이 공식이 성립하지 않음.
3313
+ * @example
3314
+ * new Vector(3, 4, 0).norm(); // 5
3315
+ * new Vector(6, 8, 0).norm(); // 10
3316
+ */
3317
+ norm() {
3289
3318
  const x = this.x;
3290
3319
  const y = this.y;
3291
3320
  const z = this.z;
3292
3321
  return Math.sqrt(x * x + y * y + z * z);
3293
3322
  }
3323
+ /**
3324
+ * norm()의 별칭 (p5.js 호환).
3325
+ * @example
3326
+ * new Vector(3, 4, 0).mag(); // 5
3327
+ */
3328
+ mag() {
3329
+ return this.norm();
3330
+ }
3331
+ /**
3332
+ * 덧셈 (파괴적). 성분별 합. 기하학적으로 평행사변형의 대각선.
3333
+ * - 수식: a + b = (ax+bx, ay+by, az+bz)
3334
+ * @example
3335
+ * const a = new Vector(4, 2); a.add(new Vector(-2, 3)); // a = (2, 5)
3336
+ */
3294
3337
  add(v, y = 0, z = 0) {
3295
3338
  if (v instanceof _Vector || v instanceof Point3D) {
3296
3339
  this.x += v.x;
@@ -3302,12 +3345,24 @@ var Vector = class _Vector {
3302
3345
  this.z += z;
3303
3346
  }
3304
3347
  }
3348
+ /**
3349
+ * 덧셈 결과의 새 벡터 반환 (비파괴).
3350
+ * - 수식: a + b = (ax+bx, ay+by, az+bz)
3351
+ * @example
3352
+ * const s = a.toAdd(a, b); // s = a+b, a·b는 그대로
3353
+ */
3305
3354
  toAdd(v1, v2) {
3306
3355
  return new _Vector(v1.x + v2.x, v1.y + v2.y, v1.x + v2.y);
3307
3356
  }
3308
3357
  // public static add(v1: Vector, v2: Vector): Vector {
3309
3358
  // return new Vector(v1.x + v2.x, v1.y + v2.y, v1.x + v2.y);
3310
3359
  // }
3360
+ /**
3361
+ * 뺄셈 (파괴적). a - b는 "a에서 b를 되돌리는" 벡터.
3362
+ * - 수식: a - b = (ax-bx, ay-by, az-bz)
3363
+ * @example
3364
+ * const a = new Vector(4, 2); a.sub(new Vector(1, 1)); // a = (3, 1)
3365
+ */
3311
3366
  sub(v, y = 0, z = 0) {
3312
3367
  if (v instanceof _Vector || v instanceof Point3D) {
3313
3368
  this.x -= v.x;
@@ -3319,6 +3374,12 @@ var Vector = class _Vector {
3319
3374
  this.z -= z;
3320
3375
  }
3321
3376
  }
3377
+ /**
3378
+ * 뺄셈 결과의 새 벡터 반환 (비파괴).
3379
+ * - 수식: a - b = (ax-bx, ay-by, az-bz)
3380
+ * @example
3381
+ * const d = a.toSub(b); // d = a-b, a·b는 그대로
3382
+ */
3322
3383
  toSub(v2) {
3323
3384
  const v1 = this;
3324
3385
  return new _Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
@@ -3327,6 +3388,12 @@ var Vector = class _Vector {
3327
3388
  // public static sub(v1: Vector, v2: Vector): Vector {
3328
3389
  // return new Vector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
3329
3390
  // }
3391
+ /**
3392
+ * 스칼라배 또는 성분별 곱 (파괴적). 스칼라 k>1이면 늘어나고, 0<k<1이면 줄어듦. k<0이면 반대 방향.
3393
+ * - 수식(스칼라): k·v = (k·x, k·y, k·z)
3394
+ * @example
3395
+ * const v = new Vector(1, 2); v.mult(3); // v = (3, 6)
3396
+ */
3330
3397
  mult(v) {
3331
3398
  if (v instanceof _Vector || v instanceof Point3D) {
3332
3399
  this.x *= v.x;
@@ -3339,6 +3406,12 @@ var Vector = class _Vector {
3339
3406
  }
3340
3407
  return this;
3341
3408
  }
3409
+ /**
3410
+ * 성분별 곱 결과의 새 벡터 반환 (비파괴).
3411
+ * - 수식: (ax·bx, ay·by, az·bz)
3412
+ * @example
3413
+ * const m = a.toMult(b); // m = 성분별 곱, a·b는 그대로
3414
+ */
3342
3415
  toMult(v2) {
3343
3416
  const v1 = this;
3344
3417
  return new _Vector(v1.x *= v2.x, v1.y *= v2.y, v1.z *= v2.z);
@@ -3346,6 +3419,12 @@ var Vector = class _Vector {
3346
3419
  // public static mult(v1: Vector, v2: Vector) {
3347
3420
  // return new Vector(v1.x *= v2.x, v1.y *= v2.y, v1.z *= v2.z);
3348
3421
  // }
3422
+ /**
3423
+ * 스칼라 나눗셈 또는 성분별 나눗셈 (파괴적). 정규화의 핵심 연산.
3424
+ * - 수식(스칼라): v/k = (x/k, y/k, z/k)
3425
+ * @example
3426
+ * const v = new Vector(6, 8); v.div(2); // v = (3, 4)
3427
+ */
3349
3428
  div(v) {
3350
3429
  if (v instanceof _Vector || v instanceof Point3D) {
3351
3430
  this.x /= v.x;
@@ -3358,6 +3437,12 @@ var Vector = class _Vector {
3358
3437
  }
3359
3438
  return this;
3360
3439
  }
3440
+ /**
3441
+ * 스칼라 나눗셈 결과의 새 벡터 반환 (비파괴).
3442
+ * - 수식: v/k = (x/k, y/k, z/k)
3443
+ * @example
3444
+ * const h = v.toDiv(2); // h = v/2, v는 그대로
3445
+ */
3361
3446
  toDiv(d) {
3362
3447
  const v = this;
3363
3448
  const rv = v.get();
@@ -3373,10 +3458,22 @@ var Vector = class _Vector {
3373
3458
  // rv.z /= d;
3374
3459
  // return rv;
3375
3460
  // }
3461
+ /**
3462
+ * 두 점(벡터) 사이 거리. 차 벡터의 크기.
3463
+ * - 수식: d = √((dx)² + (dy)² + (dz)²)
3464
+ * @example
3465
+ * new Vector(0, 0).dist(new Vector(3, 4)); // 5
3466
+ */
3376
3467
  dist(v) {
3377
3468
  const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
3378
3469
  return Math.sqrt(dx * dx + dy * dy + dz * dz);
3379
3470
  }
3471
+ /**
3472
+ * 두 점(벡터) 사이 거리 (toDist는 dist와 동일, 비파괴).
3473
+ * - 수식: d = √((dx)² + (dy)² + (dz)²)
3474
+ * @example
3475
+ * a.toDist(b); // a와 b 사이 거리
3476
+ */
3380
3477
  toDist(v2) {
3381
3478
  const v1 = this;
3382
3479
  const dx = v1.x - v2.x, dy = v1.y - v2.y, dz = v1.z - v2.z;
@@ -3388,36 +3485,90 @@ var Vector = class _Vector {
3388
3485
  // dz = v1.z - v2.z;
3389
3486
  // return Math.sqrt(dx * dx + dy * dy + dz * dz);
3390
3487
  // }
3391
- dot(v, y, z) {
3488
+ /**
3489
+ * 내적(dot product). 두 벡터가 같은 방향을 향하는 정도.
3490
+ * - 수식: a·b = ax·bx + ay·by + az·bz = |a||b|cosθ
3491
+ * - θ=90°면 0(직교), 0°면 최대(같은 방향).
3492
+ * - 벡터 전달 시 y·z 생략 가능, 스칼라(x) 전달 시 y·z와 함께 사용.
3493
+ * @example
3494
+ * new Vector(5, 12).dot(new Vector(-5, 12)); // -25+144 = 119
3495
+ * new Vector(1, 0).dot(new Vector(0, 1)); // 0 (직각)
3496
+ * new Vector(1, 2).dot(3, 4); // 1*3+2*4 = 11
3497
+ */
3498
+ dot(v, y = 0, z = 0) {
3392
3499
  if (v instanceof _Vector || v instanceof Point3D) {
3393
3500
  return this.x * v.x + this.y * v.y + this.z * v.z;
3394
3501
  }
3395
3502
  ;
3396
3503
  return this.x * v + this.y * y + this.z * z;
3397
3504
  }
3505
+ /**
3506
+ * 외적(cross product). 두 벡터에 수직인 벡터. 오른손 법칙 방향.
3507
+ * - 수식: a×b = (ay·bz − az·by, az·bx − ax·bz, ax·by − ay·bx)
3508
+ * - 2D에서는 z값 = ax·by − ay·bx (부호 있는 면적, 회전 방향 판정용).
3509
+ * @example
3510
+ * new Vector(1, 0, 0).cross(new Vector(0, 1, 0)); // (0, 0, 1)
3511
+ */
3398
3512
  cross(v) {
3399
3513
  const x = this.x, y = this.y, z = this.z;
3400
3514
  return new _Vector(y * v.z - v.y * z, z * v.x - v.z * x, x * v.y - v.x * y);
3401
3515
  }
3516
+ /**
3517
+ * 정규화 (파괴적). 방향은 그대로, 크기를 1로. 단위벡터 v̂ 생성.
3518
+ * - 수식: v̂ = v / |v|
3519
+ * - 영벡터(|v|=0)는 0으로 나누지 않고 그대로 둠.
3520
+ * @example
3521
+ * const v = new Vector(6, 8); v.normalize(); // v = (0.6, 0.8), |v| = 1
3522
+ */
3402
3523
  normalize() {
3403
- const m = this.mag();
3524
+ const m = this.norm();
3404
3525
  if (m > 0) this.div(m);
3405
3526
  }
3527
+ /**
3528
+ * 크기 상한 (파괴적). 속도가 high를 넘으면 방향 유지한 채 high로 자름. 물리 시뮬레이션 최고속도용.
3529
+ * - 수식: |v| > high → v = v̂ · high
3530
+ * @example
3531
+ * const v = new Vector(6, 8); v.limit(5); // |v|=10 → 5, v = (3, 4)
3532
+ */
3406
3533
  limit(high) {
3407
- if (this.mag() > high) {
3534
+ if (this.norm() > high) {
3408
3535
  this.normalize();
3409
3536
  this.mult(high);
3410
3537
  }
3411
3538
  }
3539
+ /**
3540
+ * 2D 방향각. +x축 기준 반시계 방향 라디안 (-π ~ π).
3541
+ * - 수식: θ = atan2(y, x)
3542
+ * @example
3543
+ * new Vector(1, 1).heading2D(); // π/4 (45°)
3544
+ * new Vector(-1, 0).heading2D(); // π (180°)
3545
+ */
3412
3546
  heading2D() {
3413
3547
  return -Math.atan2(-this.y, this.x);
3414
3548
  }
3549
+ /**
3550
+ * 무작위 방향 단위벡터 반환 (새 Vector, 자신은 변경 안 함).
3551
+ * @example
3552
+ * const r = new Vector().random2D(); // |r| = 1, 방향 랜덤
3553
+ */
3415
3554
  random2D() {
3416
3555
  return this.fromAngle(Math.random() * (2 * Math.PI));
3417
3556
  }
3557
+ /**
3558
+ * 각도→벡터. 각도 θ, 길이 L인 2D 벡터 반환 (새 Vector).
3559
+ * - 수식: (L·cosθ, L·sinθ, 0)
3560
+ * @example
3561
+ * new Vector().fromAngle(Math.PI / 3, 2); // (1, 1.73, 0)
3562
+ */
3418
3563
  fromAngle(angle, length = 1) {
3419
3564
  return new _Vector(length * Math.cos(angle), length * Math.sin(angle), 0);
3420
3565
  }
3566
+ /**
3567
+ * 구면좌표→3D 벡터 (새 Vector 반환, p5.js 컨벤션).
3568
+ * - 수식: (L·sinθ·sinφ, −L·cosθ, L·sinθ·cosφ)
3569
+ * @example
3570
+ * new Vector().fromAngles(Math.PI / 2, Math.PI / 2, 1); // (1, 0, 0)
3571
+ */
3421
3572
  fromAngles(theta, phi, length = 1) {
3422
3573
  const cosPhi = Math.cos(phi);
3423
3574
  const sinPhi = Math.sin(phi);
@@ -3429,18 +3580,43 @@ var Vector = class _Vector {
3429
3580
  length * sinTheta * cosPhi
3430
3581
  );
3431
3582
  }
3583
+ /**
3584
+ * 성분 배열 반환. [x, y, z] 순서.
3585
+ * @example
3586
+ * new Vector(1, 2, 3).array(); // [1, 2, 3]
3587
+ */
3432
3588
  array() {
3433
3589
  return [this.x, this.y, this.z];
3434
3590
  }
3591
+ /**
3592
+ * Point3D로 변환 (위치 의미로 바꿀 때).
3593
+ * @example
3594
+ * new Vector(1, 2, 3).toPoint3D(); // Point3D(1, 2, 3)
3595
+ */
3435
3596
  toPoint3D() {
3436
3597
  return new Point3D(this.x, this.y, this.z);
3437
3598
  }
3599
+ /**
3600
+ * Point2D로 변환 (z 버림).
3601
+ * @example
3602
+ * new Vector(1, 2, 3).toPoint2D(); // Point2D(1, 2)
3603
+ */
3438
3604
  toPoint2D() {
3439
3605
  return new Point2D(this.x, this.y);
3440
3606
  }
3607
+ /**
3608
+ * 복사본 반환 (get()과 동일, 비파괴).
3609
+ * @example
3610
+ * const c = v.copy(); // v와 같은 성분의 새 벡터
3611
+ */
3441
3612
  copy() {
3442
3613
  return new _Vector(this.x, this.y, this.z);
3443
3614
  }
3615
+ /**
3616
+ * 문자열 표현. "[x, y, z]" 형식.
3617
+ * @example
3618
+ * new Vector(1, 2).toString(); // "[1, 2, 0]"
3619
+ */
3444
3620
  toString() {
3445
3621
  return "[" + this.x + ", " + this.y + ", " + this.z + "]";
3446
3622
  }
@@ -5633,87 +5809,64 @@ var throttle = (fn, delay) => {
5633
5809
  // ../core/dist/esm/promise/AbortablePromise.js
5634
5810
  var AbortablePromise = class _AbortablePromise {
5635
5811
  constructor(executor, signal) {
5636
- this.steps = [];
5637
- this.initialExecutor = executor;
5638
5812
  this.signal = signal;
5813
+ if (typeof executor !== "function") {
5814
+ this.source = Promise.resolve(executor);
5815
+ } else if (signal?.aborted) {
5816
+ this.source = Promise.reject(signal.reason);
5817
+ } else {
5818
+ this.source = Promise.resolve().then(executor);
5819
+ }
5820
+ }
5821
+ /**
5822
+ * source 를 abort 와 경쟁시킨 promise. 실제로 소비될 때(then/toPromise) 한 번만 만든다 —
5823
+ * await 는 then() 이 돌려준 새 인스턴스를 버리므로, 미리 만들면 아무도 안 받는 reject 가 unhandled 로 남는다.
5824
+ */
5825
+ get promise() {
5826
+ if (this.guarded) return this.guarded;
5827
+ const signal = this.signal;
5828
+ if (!signal) return this.guarded = this.source;
5829
+ if (signal.aborted) {
5830
+ this.source.catch(() => {
5831
+ });
5832
+ return this.guarded = Promise.reject(signal.reason);
5833
+ }
5834
+ return this.guarded = new Promise((resolve, reject) => {
5835
+ const cleanup = () => signal.removeEventListener("abort", onAbort);
5836
+ const onAbort = () => reject(signal.reason);
5837
+ signal.addEventListener("abort", onAbort, { once: true });
5838
+ this.source.then(
5839
+ (value) => {
5840
+ cleanup();
5841
+ resolve(value);
5842
+ },
5843
+ (reason) => {
5844
+ cleanup();
5845
+ reject(reason);
5846
+ }
5847
+ );
5848
+ });
5639
5849
  }
5640
5850
  then(onfulfilled, onrejected) {
5641
- const newPromise = new _AbortablePromise(
5642
- this.initialExecutor,
5643
- this.signal
5851
+ const signal = this.signal;
5852
+ const next = this.promise.then(
5853
+ onfulfilled ? (value) => {
5854
+ if (signal?.aborted) throw signal.reason;
5855
+ return onfulfilled(value);
5856
+ } : void 0,
5857
+ onrejected
5644
5858
  );
5645
- newPromise.steps = [...this.steps];
5646
- if (onfulfilled) {
5647
- newPromise.steps.push(onfulfilled);
5648
- }
5649
- if (onrejected) {
5650
- newPromise.errorHandler = onrejected;
5651
- } else if (this.errorHandler) {
5652
- newPromise.errorHandler = this.errorHandler;
5653
- }
5654
- return newPromise;
5859
+ return new _AbortablePromise(next, signal);
5655
5860
  }
5656
5861
  catch(onrejected) {
5657
5862
  return this.then(void 0, onrejected);
5658
5863
  }
5659
5864
  finally(onfinally) {
5660
- return this.then(
5661
- (value) => {
5662
- onfinally?.();
5663
- return value;
5664
- },
5665
- (reason) => {
5666
- onfinally?.();
5667
- throw reason;
5668
- }
5669
- );
5670
- }
5671
- async execute() {
5672
- try {
5673
- if (this.signal?.aborted) {
5674
- throw new Error(this.signal.reason || "Aborted");
5675
- }
5676
- const abortPromise = new Promise((_, reject) => {
5677
- if (this.signal?.aborted) {
5678
- return reject(new Error(this.signal.reason || "Aborted"));
5679
- }
5680
- const callback = (e) => {
5681
- const target = e.target;
5682
- this.signal?.removeEventListener("abort", callback);
5683
- reject(new Error(target.reason || "Aborted"));
5684
- };
5685
- this.signal?.addEventListener("abort", callback, { once: true });
5686
- });
5687
- const pipelineRunner = async () => {
5688
- let lastResult;
5689
- if (typeof this.initialExecutor === "function") {
5690
- if (this.signal?.aborted) {
5691
- throw new Error(this.signal.reason || "Aborted");
5692
- }
5693
- lastResult = await this.initialExecutor();
5694
- } else {
5695
- lastResult = await this.initialExecutor;
5696
- }
5697
- for (let i = 0; i < this.steps.length; i++) {
5698
- if (this.signal?.aborted) {
5699
- throw new Error(this.signal.reason || "Aborted");
5700
- }
5701
- const step = this.steps[i];
5702
- lastResult = await step(lastResult);
5703
- }
5704
- return lastResult;
5705
- };
5706
- return await Promise.race([pipelineRunner(), abortPromise]);
5707
- } catch (error) {
5708
- if (this.errorHandler) {
5709
- return await this.errorHandler(error);
5710
- }
5711
- throw error;
5712
- }
5865
+ return new _AbortablePromise(this.promise.finally(onfinally), this.signal);
5713
5866
  }
5714
- // Convert to native Promise
5867
+ // 네이티브 Promise 로 변환 (그냥 await 해도 된다)
5715
5868
  toPromise() {
5716
- return this.execute();
5869
+ return this.promise;
5717
5870
  }
5718
5871
  };
5719
5872
 
@@ -6586,11 +6739,15 @@ var Fetcher = class {
6586
6739
  resolve(gdata);
6587
6740
  }).catch(async (e) => {
6588
6741
  this.error(config, pipe, e);
6589
- config?.error?.();
6742
+ config?.error?.(e);
6590
6743
  if (config?.errorTransform) {
6591
6744
  e = await config.errorTransform(e);
6592
6745
  }
6593
- e = await this.errorTransform(e);
6746
+ try {
6747
+ e = await this.errorTransform(e);
6748
+ } catch (ee) {
6749
+ e = ee;
6750
+ }
6594
6751
  reject(e);
6595
6752
  }).finally(() => {
6596
6753
  this.finally(config, pipe);
@@ -6607,41 +6764,30 @@ var isHttpResponseError = (data) => {
6607
6764
  return data instanceof HttpResponseError;
6608
6765
  };
6609
6766
  var HttpFetcher = class extends Fetcher {
6767
+ // get/post/put/patch/head/delete가 전부 config.config.fetch.method를 세팅하려고 caller가
6768
+ // 넘긴 config(.fetch) 객체를 직접 mutate했다 - 같은 config 객체를 여러 호출이 공유하면
6769
+ // (예: Promise.all로 동시에 get/post) 서로의 method를 덮어쓰는 레이스가 생겼다. caller의
6770
+ // 객체는 절대 건드리지 않고, 얕은 복사본 위에 method만 얹어서 반환한다.
6771
+ withMethod(config, method) {
6772
+ return { ...config, config: { ...config.config, fetch: { ...config.config?.fetch, method } } };
6773
+ }
6610
6774
  get(config) {
6611
- config.config ?? (config.config = {});
6612
- config.config.fetch = config.config?.fetch ?? {};
6613
- config.config.fetch.method = "GET";
6614
- return this.fetch(config);
6775
+ return this.fetch(this.withMethod(config, "GET"));
6615
6776
  }
6616
6777
  post(config) {
6617
- config.config ?? (config.config = {});
6618
- config.config.fetch = config.config?.fetch ?? {};
6619
- config.config.fetch.method = "POST";
6620
- return this.fetch(config);
6778
+ return this.fetch(this.withMethod(config, "POST"));
6621
6779
  }
6622
6780
  patch(config) {
6623
- config.config ?? (config.config = {});
6624
- config.config.fetch = config.config?.fetch ?? {};
6625
- config.config.fetch.method = "PATCH";
6626
- return this.fetch(config);
6781
+ return this.fetch(this.withMethod(config, "PATCH"));
6627
6782
  }
6628
6783
  put(config) {
6629
- config.config ?? (config.config = {});
6630
- config.config.fetch = config.config?.fetch ?? {};
6631
- config.config.fetch.method = "PUT";
6632
- return this.fetch(config);
6784
+ return this.fetch(this.withMethod(config, "PUT"));
6633
6785
  }
6634
6786
  head(config) {
6635
- config.config ?? (config.config = {});
6636
- config.config.fetch = config.config?.fetch ?? {};
6637
- config.config.fetch.method = "HEAD";
6638
- return this.fetch(config);
6787
+ return this.fetch(this.withMethod(config, "HEAD"));
6639
6788
  }
6640
6789
  delete(config) {
6641
- config.config ?? (config.config = {});
6642
- config.config.fetch = config.config?.fetch ?? {};
6643
- config.config.fetch.method = "DELETE";
6644
- return this.fetch(config);
6790
+ return this.fetch(this.withMethod(config, "DELETE"));
6645
6791
  }
6646
6792
  async beforeProxyFetch(config) {
6647
6793
  return config;
@@ -6678,7 +6824,7 @@ var HttpFetcher = class extends Fetcher {
6678
6824
  }
6679
6825
  } else {
6680
6826
  httpResponseError.body = e;
6681
- httpResponseError.message = e.message;
6827
+ httpResponseError.message = e?.message;
6682
6828
  }
6683
6829
  return httpResponseError;
6684
6830
  }
@@ -6688,7 +6834,7 @@ var HttpFetcher = class extends Fetcher {
6688
6834
  if (!(target instanceof URL) && typeof target !== "string") {
6689
6835
  const searchParams = ConvertUtils.toURLSearchParams(target.searchParams ?? {});
6690
6836
  try {
6691
- const url = typeof target.url === "string" ? new URL(target.url) : target.url;
6837
+ const url = new URL(target.url);
6692
6838
  searchParams.forEach((value, key) => {
6693
6839
  url.searchParams.append(key, value);
6694
6840
  });
@@ -6703,43 +6849,30 @@ var HttpFetcher = class extends Fetcher {
6703
6849
  }
6704
6850
  }
6705
6851
  const beforeProxyData = { requestInfo: target, init: config?.fetch };
6706
- let beforeData = config?.beforeProxyFetch ? await config?.beforeProxyFetch(config) : beforeProxyData.requestInfo;
6707
- beforeData = config?.skipGlobalBeforeProxyFetch ? beforeProxyData : await this.beforeProxyFetch(beforeProxyData);
6852
+ let beforeData = config?.beforeProxyFetch ? await config?.beforeProxyFetch(beforeProxyData) : beforeProxyData;
6853
+ beforeData = config?.skipGlobalBeforeProxyFetch ? beforeData : await this.beforeProxyFetch(beforeData);
6708
6854
  target = beforeData.requestInfo;
6709
6855
  if (beforeData.init) {
6710
6856
  config ?? (config = {});
6711
6857
  config.fetch = beforeData.init;
6712
6858
  }
6713
- let abortedTimeout;
6859
+ let requestInit = config?.fetch;
6714
6860
  if (config?.fetch && "timeout" in config.fetch) {
6715
- const abortController = new AbortController();
6716
- abortedTimeout = setTimeout(() => {
6717
- if (config?.fetch?.signal) {
6718
- const inputSignal = config.fetch.signal;
6719
- const listener = () => {
6720
- if (!abortController.signal.aborted) {
6721
- abortController.abort();
6722
- }
6723
- inputSignal.removeEventListener("abort", listener);
6724
- };
6725
- inputSignal.addEventListener("abort", listener);
6726
- }
6727
- if (!abortController.signal.aborted) {
6728
- abortController.abort();
6729
- }
6730
- }, config.fetch.timeout);
6731
- config.fetch.signal = abortController.signal;
6861
+ const timeoutSignal = AbortSignal.timeout(config.fetch.timeout);
6862
+ const signal = config.fetch.signal ? AbortSignal.any([timeoutSignal, config.fetch.signal]) : timeoutSignal;
6863
+ requestInit = { ...config.fetch, signal };
6732
6864
  }
6733
- this.beforeFetch({ target, requestInit: config?.fetch });
6734
- return (config.fetcher ?? fetch)(target, config?.fetch).then(async (it) => {
6735
- this.afterFetch({ target, requestInit: config?.fetch }, it);
6865
+ this.beforeFetch({ target, requestInit });
6866
+ return (config.fetcher ?? fetch)(target, requestInit).then(async (it) => {
6867
+ this.afterFetch({ target, requestInit }, it);
6736
6868
  const afterProxyData = {
6737
- fetch: { target, requestInit: config.fetch },
6869
+ fetch: { target, requestInit },
6738
6870
  config: beforeData,
6739
6871
  response: it
6740
6872
  };
6741
- it = config?.afterProxyFetch ? await config.afterProxyFetch(afterProxyData) : it;
6742
- it = config?.skipGlobalAfterProxyFetch ? it : await this.afterProxyFetch(afterProxyData);
6873
+ afterProxyData.response = config?.afterProxyFetch ? await config.afterProxyFetch(afterProxyData) : it;
6874
+ afterProxyData.response = config?.skipGlobalAfterProxyFetch ? afterProxyData.response : await this.afterProxyFetch(afterProxyData);
6875
+ it = afterProxyData.response;
6743
6876
  config?.fetchResponseAfterCallBack?.(it, config);
6744
6877
  if (!config?.allowedResponseNotOk && !it.ok) {
6745
6878
  throw it;
@@ -6749,30 +6882,31 @@ var HttpFetcher = class extends Fetcher {
6749
6882
  throw data;
6750
6883
  }
6751
6884
  return it;
6752
- }).finally(() => {
6753
- if (abortedTimeout) {
6754
- clearTimeout(abortedTimeout);
6755
- }
6756
6885
  });
6757
6886
  }
6758
6887
  };
6759
6888
 
6760
6889
  // ../core/dist/esm/fetch/HttpJsonFetcher.js
6761
6890
  var HttpJsonFetcher = class extends HttpFetcher {
6891
+ // config.config/config.config.fetch를 직접 mutate하면(예전처럼) 같은 config 객체를 여러
6892
+ // postJson/patchJson/putJson 호출이 동시에 공유할 때 서로의 headers/body를 덮어쓰는 레이스가
6893
+ // 생긴다(HttpFetcher.get/post의 method 레이스랑 같은 문제). caller의 객체는 안 건드리고,
6894
+ // 얕은 복사본을 만들어서 새 config 객체를 리턴한다.
6762
6895
  updateJsonFetchConfigAndData(config) {
6763
- var _a2, _b2;
6764
6896
  const headers = {
6765
6897
  "Content-Type": "application/json",
6766
6898
  Accept: "application/json, text/plain, */*"
6767
6899
  };
6768
- config.config ?? (config.config = {});
6769
- (_a2 = config.config).fetch ?? (_a2.fetch = {});
6770
- (_b2 = config.config.fetch).headers ?? (_b2.headers = {});
6771
- config.config.fetch.headers = { ...headers, ...config.config.fetch?.headers };
6772
- if (config.config?.fetch?.body && typeof config.config?.fetch?.body !== "string") {
6773
- config.config.fetch.body = JSON.stringify(config.config.fetch.body);
6900
+ const fetchInit = { ...config.config?.fetch };
6901
+ const merged = new Headers(headers);
6902
+ if (fetchInit.headers) {
6903
+ new Headers(fetchInit.headers).forEach((value, key) => merged.set(key, value));
6774
6904
  }
6775
- return config;
6905
+ fetchInit.headers = merged;
6906
+ if (fetchInit.body && typeof fetchInit.body !== "string") {
6907
+ fetchInit.body = JSON.stringify(fetchInit.body);
6908
+ }
6909
+ return { ...config, config: { ...config.config, fetch: fetchInit } };
6776
6910
  }
6777
6911
  get(config) {
6778
6912
  return super.get(config);
@@ -8286,7 +8420,7 @@ var StoreLoader = class {
8286
8420
 
8287
8421
  // ../core/dist/esm/url/UrlUtils.js
8288
8422
  var UrlUtils;
8289
- ((UrlUtils2) => {
8423
+ (function(UrlUtils2) {
8290
8424
  UrlUtils2.origin = (fullurl) => {
8291
8425
  return new URL(fullurl).origin;
8292
8426
  };
@@ -8324,15 +8458,28 @@ var UrlUtils;
8324
8458
  });
8325
8459
  return searchParams;
8326
8460
  };
8461
+ UrlUtils2.toAbsoluteUrl = (relative, base) => {
8462
+ return new URL(relative, base);
8463
+ };
8464
+ function toAbsoluteRequest(input, base) {
8465
+ if (input instanceof URL) {
8466
+ return UrlUtils2.toAbsoluteUrl(input.href, base);
8467
+ }
8468
+ if (typeof input === "string") {
8469
+ return UrlUtils2.toAbsoluteUrl(input, base).href;
8470
+ }
8471
+ return new Request(UrlUtils2.toAbsoluteUrl(input.url, base).href, input);
8472
+ }
8473
+ UrlUtils2.toAbsoluteRequest = toAbsoluteRequest;
8327
8474
  UrlUtils2.manipulateSearchParams = (searchParams, options) => {
8328
8475
  if (options?.delete) {
8329
- (0, UrlUtils2.deleteSearchParam)(searchParams, options.delete);
8476
+ UrlUtils2.deleteSearchParam(searchParams, options.delete);
8330
8477
  }
8331
8478
  if (options?.append) {
8332
- (0, UrlUtils2.appendSearchParam)(searchParams, options.append);
8479
+ UrlUtils2.appendSearchParam(searchParams, options.append);
8333
8480
  }
8334
8481
  if (options?.upsert) {
8335
- (0, UrlUtils2.upsertSearchParam)(searchParams, options.upsert);
8482
+ UrlUtils2.upsertSearchParam(searchParams, options.upsert);
8336
8483
  }
8337
8484
  return searchParams;
8338
8485
  };
@@ -8583,12 +8730,13 @@ var ReflectUtils;
8583
8730
  ReflectUtils2.findMetadata = (metadataKey, target, propertyKey) => {
8584
8731
  if (target == null) return void 0;
8585
8732
  let searchTarget = typeof target === "object" && typeof target !== "function" ? target.constructor : target;
8586
- while (searchTarget && searchTarget !== Object) {
8733
+ const seen = /* @__PURE__ */ new Set();
8734
+ while (searchTarget && searchTarget !== Object && !seen.has(searchTarget)) {
8735
+ seen.add(searchTarget);
8587
8736
  const data = propertyKey ? Reflect.getOwnMetadata(metadataKey, searchTarget, propertyKey) : Reflect.getOwnMetadata(metadataKey, searchTarget);
8588
8737
  if (data !== void 0) return data;
8589
8738
  const proto = Object.getPrototypeOf(searchTarget);
8590
8739
  searchTarget = proto && typeof proto === "function" ? proto : proto?.constructor || null;
8591
- if (searchTarget === target) break;
8592
8740
  }
8593
8741
  return void 0;
8594
8742
  };
@@ -8596,12 +8744,13 @@ var ReflectUtils;
8596
8744
  const results = [];
8597
8745
  if (target == null) return results;
8598
8746
  let searchTarget = typeof target === "object" && typeof target !== "function" ? target.constructor : target;
8599
- while (searchTarget && searchTarget !== Object) {
8747
+ const seen = /* @__PURE__ */ new Set();
8748
+ while (searchTarget && searchTarget !== Object && !seen.has(searchTarget)) {
8749
+ seen.add(searchTarget);
8600
8750
  const data = propertyKey ? Reflect.getOwnMetadata(metadataKey, searchTarget, propertyKey) : Reflect.getOwnMetadata(metadataKey, searchTarget);
8601
8751
  if (data !== void 0) results.unshift(data);
8602
8752
  const proto = Object.getPrototypeOf(searchTarget);
8603
8753
  searchTarget = proto && typeof proto === "function" ? proto : proto?.constructor || null;
8604
- if (searchTarget === target) break;
8605
8754
  }
8606
8755
  return results;
8607
8756
  };
@@ -10726,6 +10875,23 @@ function getExpression(value, config) {
10726
10875
  };
10727
10876
  }
10728
10877
 
10878
+ // ../core/dist/esm/hash/HashUtils.js
10879
+ var HashUtils;
10880
+ ((HashUtils2) => {
10881
+ const core53 = (str, seed) => {
10882
+ let h1 = 3735928559 ^ seed, h2 = 1103547991 ^ seed;
10883
+ for (let i = 0; i < str.length; i++) {
10884
+ const ch = str.charCodeAt(i);
10885
+ h1 = Math.imul(h1 ^ ch, 2654435761);
10886
+ h2 = Math.imul(h2 ^ ch, 1597334677);
10887
+ }
10888
+ h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507) ^ Math.imul(h2 ^ h2 >>> 13, 3266489909);
10889
+ h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507) ^ Math.imul(h1 ^ h1 >>> 13, 3266489909);
10890
+ return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16).padStart(14, "0");
10891
+ };
10892
+ HashUtils2.hash53 = (str, seed = 0, xyz = 16) => `${core53(str, seed)}${core53(str, seed + 1)}`.slice(0, Math.max(1, xyz));
10893
+ })(HashUtils || (HashUtils = {}));
10894
+
10729
10895
  // ../core/dist/esm/index.js
10730
10896
  var src_default = {
10731
10897
  // Core utilities are exported as named exports above
@@ -10887,7 +11053,7 @@ var ElementUtils;
10887
11053
  var ElementApply = class _ElementApply {
10888
11054
  constructor(el, config) {
10889
11055
  this.el = el;
10890
- this.window = this.el.ownerDocument.defaultView;
11056
+ this.window = this.el.ownerDocument.defaultView ?? globalThis;
10891
11057
  this.document = this.el.ownerDocument;
10892
11058
  this.id = config?.id ?? el.id;
10893
11059
  this.variableWrap = config?.variableWrap ?? { start: "@", end: "@" };
@@ -10910,6 +11076,8 @@ var ElementApply = class _ElementApply {
10910
11076
  let match;
10911
11077
  while ((match = regex.exec(script)) !== null) {
10912
11078
  variables.push(match[1]);
11079
+ const root = match[1].split(/[.[(]/)[0].trim();
11080
+ if (root && root !== match[1]) variables.push(root);
10913
11081
  }
10914
11082
  return variables;
10915
11083
  }
@@ -11014,10 +11182,15 @@ var ElementApply = class _ElementApply {
11014
11182
  type.variables.forEach((v) => variables.add(v));
11015
11183
  });
11016
11184
  }
11185
+ const bind = config?.bind;
11186
+ const fromBind = (key) => bind != null && typeof key === "string" && !(key in (config?.context ?? {})) && _ElementApply.isUserMember(bind, key);
11017
11187
  const context = new Proxy(config?.context ?? {}, {
11188
+ has(target, key) {
11189
+ return key in target || fromBind(key);
11190
+ },
11018
11191
  get(target, key) {
11019
- const value = target[key];
11020
- return typeof value === "function" ? value.bind(config?.bind ?? target) : value;
11192
+ const value = key in target ? target[key] : fromBind(key) ? bind[key] : void 0;
11193
+ return typeof value === "function" ? value.bind(bind ?? target) : value;
11021
11194
  }
11022
11195
  });
11023
11196
  if (!config?.targetVariableName || config?.targetVariableName && variables.has(config?.targetVariableName)) {
@@ -11042,7 +11215,6 @@ var ElementApply = class _ElementApply {
11042
11215
  }
11043
11216
  }
11044
11217
  `)(context).bind(it.node);
11045
- console.log("------------------->", it, tit);
11046
11218
  if (tit.type === "attribute" && !config?.exclude?.attribute) {
11047
11219
  it.node.setAttribute(tit.name, data());
11048
11220
  } else if (tit.type === "property" && !config?.exclude?.property) {
@@ -11062,6 +11234,15 @@ var ElementApply = class _ElementApply {
11062
11234
  }
11063
11235
  }
11064
11236
  }
11237
+ /** key 가 네이티브(DOM/내장) prototype 이 아니라 사용자 클래스나 인스턴스에 정의돼 있으면 true */
11238
+ static isUserMember(obj, key) {
11239
+ for (let p = obj; p; p = Object.getPrototypeOf(p)) {
11240
+ if (!Object.prototype.hasOwnProperty.call(p, key)) continue;
11241
+ const ctor = p === obj ? null : p.constructor;
11242
+ return !(typeof ctor === "function" && /\[native code\]/.test(Function.prototype.toString.call(ctor)));
11243
+ }
11244
+ return false;
11245
+ }
11065
11246
  removeAllEventListener() {
11066
11247
  const m = this.findAllTarget().filter((it) => it.nodeType === "element").flatMap((it) => it.types.map((sit) => ({ ...sit, node: it.node })).filter((it2) => it2.type === "event"));
11067
11248
  m.forEach((tit) => {
@@ -11439,15 +11620,21 @@ var NodeSlot = class _NodeSlot {
11439
11620
  const slots = this.findSlots();
11440
11621
  return slots.map((s) => s.nodes());
11441
11622
  }
11442
- append(...args) {
11443
- let targetId;
11444
- let items = [];
11445
- if (typeof args[0] === "string" && args.length > 1) {
11446
- targetId = args[0];
11447
- items = args.slice(1);
11448
- } else {
11449
- items = args;
11623
+ /**
11624
+ * Shared disambiguation for the `(...items)` / `(targetId, ...items)` overload pair.
11625
+ * Items are always Node instances (or strings meant as literal content) coming from
11626
+ * callers; a leading string is therefore always treated as `targetId`, even when no
11627
+ * items follow — this avoids misclassifying `targetId` itself as content when the
11628
+ * caller has zero items to insert (e.g. a decorated method returning undefined).
11629
+ */
11630
+ static parseTargetArgs(args) {
11631
+ if (typeof args[0] === "string") {
11632
+ return { targetId: args[0], items: args.slice(1) };
11450
11633
  }
11634
+ return { targetId: void 0, items: args };
11635
+ }
11636
+ append(...args) {
11637
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
11451
11638
  if (!items || items.length === 0) return;
11452
11639
  const slots = this.findSlots(targetId);
11453
11640
  if (!slots || slots.length === 0) return;
@@ -11456,38 +11643,17 @@ var NodeSlot = class _NodeSlot {
11456
11643
  }
11457
11644
  }
11458
11645
  appendHtml(...args) {
11459
- let targetId;
11460
- let items = [];
11461
- if (typeof args[0] === "string" && args.length > 1) {
11462
- targetId = args[0];
11463
- items = args.slice(1);
11464
- } else {
11465
- items = args;
11466
- }
11646
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
11467
11647
  const slots = this.findSlots(targetId);
11468
11648
  for (const s of slots) s.appendHtml(...items);
11469
11649
  }
11470
11650
  appendText(...args) {
11471
- let targetId;
11472
- let items = [];
11473
- if (typeof args[0] === "string" && args.length > 1) {
11474
- targetId = args[0];
11475
- items = args.slice(1);
11476
- } else {
11477
- items = args;
11478
- }
11651
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
11479
11652
  const slots = this.findSlots(targetId);
11480
11653
  for (const s of slots) s.appendText(...items);
11481
11654
  }
11482
11655
  appendCopy(...args) {
11483
- let targetId;
11484
- let items = [];
11485
- if (typeof args[0] === "string" && args.length > 1) {
11486
- targetId = args[0];
11487
- items = args.slice(1);
11488
- } else {
11489
- items = args;
11490
- }
11656
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
11491
11657
  if (!items || items.length === 0) return;
11492
11658
  const slots = this.findSlots(targetId);
11493
11659
  if (!slots || slots.length === 0) return;
@@ -11496,14 +11662,7 @@ var NodeSlot = class _NodeSlot {
11496
11662
  }
11497
11663
  }
11498
11664
  prepend(...args) {
11499
- let targetId;
11500
- let items = [];
11501
- if (typeof args[0] === "string" && args.length > 1) {
11502
- targetId = args[0];
11503
- items = args.slice(1);
11504
- } else {
11505
- items = args;
11506
- }
11665
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
11507
11666
  if (!items || items.length === 0) return;
11508
11667
  const slots = this.findSlots(targetId);
11509
11668
  if (!slots || slots.length === 0) return;
@@ -11512,38 +11671,17 @@ var NodeSlot = class _NodeSlot {
11512
11671
  }
11513
11672
  }
11514
11673
  prependHtml(...args) {
11515
- let targetId;
11516
- let items = [];
11517
- if (typeof args[0] === "string" && args.length > 1) {
11518
- targetId = args[0];
11519
- items = args.slice(1);
11520
- } else {
11521
- items = args;
11522
- }
11674
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
11523
11675
  const slots = this.findSlots(targetId);
11524
11676
  for (const s of slots) s.prependHtml(...items);
11525
11677
  }
11526
11678
  prependText(...args) {
11527
- let targetId;
11528
- let items = [];
11529
- if (typeof args[0] === "string" && args.length > 1) {
11530
- targetId = args[0];
11531
- items = args.slice(1);
11532
- } else {
11533
- items = args;
11534
- }
11679
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
11535
11680
  const slots = this.findSlots(targetId);
11536
11681
  for (const s of slots) s.prependText(...items);
11537
11682
  }
11538
11683
  prependCopy(...args) {
11539
- let targetId;
11540
- let items = [];
11541
- if (typeof args[0] === "string" && args.length > 1) {
11542
- targetId = args[0];
11543
- items = args.slice(1);
11544
- } else {
11545
- items = args;
11546
- }
11684
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
11547
11685
  if (!items || items.length === 0) return;
11548
11686
  const slots = this.findSlots(targetId);
11549
11687
  if (!slots || slots.length === 0) return;
@@ -11563,14 +11701,7 @@ var NodeSlot = class _NodeSlot {
11563
11701
  }
11564
11702
  }
11565
11703
  replaceChildren(...args) {
11566
- let targetId;
11567
- let items = [];
11568
- if (typeof args[0] === "string" && args.length > 1) {
11569
- targetId = args[0];
11570
- items = args.slice(1);
11571
- } else {
11572
- items = args;
11573
- }
11704
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
11574
11705
  const slots = this.findSlots(targetId);
11575
11706
  if (!slots || slots.length === 0) return;
11576
11707
  for (const s of slots) {
@@ -11578,14 +11709,7 @@ var NodeSlot = class _NodeSlot {
11578
11709
  }
11579
11710
  }
11580
11711
  replaceChildrenHtml(...args) {
11581
- let targetId;
11582
- let items = [];
11583
- if (typeof args[0] === "string" && args.length > 1) {
11584
- targetId = args[0];
11585
- items = args.slice(1);
11586
- } else {
11587
- items = args;
11588
- }
11712
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
11589
11713
  const slots = this.findSlots(targetId);
11590
11714
  if (!slots || slots.length === 0) return;
11591
11715
  for (const s of slots) {
@@ -11593,14 +11717,7 @@ var NodeSlot = class _NodeSlot {
11593
11717
  }
11594
11718
  }
11595
11719
  replaceChildrenText(...args) {
11596
- let targetId;
11597
- let items = [];
11598
- if (typeof args[0] === "string" && args.length > 1) {
11599
- targetId = args[0];
11600
- items = args.slice(1);
11601
- } else {
11602
- items = args;
11603
- }
11720
+ const { targetId, items } = _NodeSlot.parseTargetArgs(args);
11604
11721
  const slots = this.findSlots(targetId);
11605
11722
  if (!slots || slots.length === 0) return;
11606
11723
  for (const s of slots) {
@@ -12291,6 +12408,7 @@ var LocationUtils;
12291
12408
  var ROUTER_NO_EVENT_MARKER = "__ROUTER_NO_EVENT__";
12292
12409
  var Router = class {
12293
12410
  constructor(config) {
12411
+ this.leaveGuards = /* @__PURE__ */ new Set();
12294
12412
  this._config = config;
12295
12413
  let routeData;
12296
12414
  if (config?.firstUrl) {
@@ -12311,13 +12429,39 @@ var Router = class {
12311
12429
  this.behaviorSubject = new BehaviorSubject(routeData);
12312
12430
  }
12313
12431
  this.config.window.addEventListener("popstate", (event) => {
12314
- const routeData2 = { ...this.getRouteData(), triggerPoint: "end" };
12315
- this.behaviorSubject.next(routeData2);
12432
+ const publish = () => this.behaviorSubject.next({ ...this.getRouteData(), triggerPoint: "end" });
12433
+ if (!this.leaveGuards.size) return publish();
12434
+ const from = this.value;
12435
+ void this.canLeave(this.getRouteData(), from).then((ok) => {
12436
+ if (ok) publish();
12437
+ else this.config.window.history?.pushState(from.data ?? null, "", from.url);
12438
+ });
12316
12439
  });
12317
12440
  }
12318
12441
  get value() {
12319
12442
  return this.behaviorSubject.getValue();
12320
12443
  }
12444
+ /**
12445
+ * 이동 전 가드 등록. go() 와 뒤로/앞으로 가기(popstate)에 적용된다 (pushState/replaceState 직접 호출은 제외).
12446
+ * 리턴한 함수를 부르면 해제된다.
12447
+ */
12448
+ addLeaveGuard(guard) {
12449
+ this.leaveGuards.add(guard);
12450
+ return () => {
12451
+ this.leaveGuards.delete(guard);
12452
+ };
12453
+ }
12454
+ /** 가드가 하나라도 있는지 (없으면 호출자가 동기로 진행해도 된다) */
12455
+ get hasLeaveGuards() {
12456
+ return this.leaveGuards.size > 0;
12457
+ }
12458
+ /** 등록된 가드를 순서대로 평가. 하나라도 false 면 false */
12459
+ async canLeave(to, from) {
12460
+ for (const guard of [...this.leaveGuards]) {
12461
+ if (await guard(to, from) === false) return false;
12462
+ }
12463
+ return true;
12464
+ }
12321
12465
  get observable() {
12322
12466
  return this.behaviorSubject.asObservable();
12323
12467
  }
@@ -12448,17 +12592,24 @@ var Router = class {
12448
12592
  if (typeof config === "string") {
12449
12593
  config = { path: config };
12450
12594
  }
12451
- if (config?.replace) {
12452
- this.replace(config.path, config.state);
12453
- } else {
12454
- this.push(config.path, config.state);
12455
- }
12456
- if (config.scrollToTop !== false) {
12457
- try {
12458
- this._config.window?.scrollTo?.(0, 0);
12459
- } catch (e) {
12595
+ const target = config;
12596
+ const navigate = () => {
12597
+ if (target?.replace) {
12598
+ this.replace(target.path, target.state);
12599
+ } else {
12600
+ this.push(target.path, target.state);
12460
12601
  }
12461
- }
12602
+ if (target.scrollToTop !== false) {
12603
+ try {
12604
+ this._config.window?.scrollTo?.(0, 0);
12605
+ } catch (e) {
12606
+ }
12607
+ }
12608
+ };
12609
+ if (!this.leaveGuards.size) return navigate();
12610
+ return this.canLeave(this.getRouteData({ pathOrUrl: this.toUrl(target.path) }), this.value).then((ok) => {
12611
+ if (ok) navigate();
12612
+ });
12462
12613
  }
12463
12614
  toUrl(data) {
12464
12615
  let targetPath;